[azureus] 01/08: Imported Upstream version 5.6.1.2

Stephen Nelson stephenonelson-guest at moszumanska.debian.org
Sun Aug 2 20:32:42 UTC 2015


This is an automated email from the git hooks/post-receive script.

stephenonelson-guest pushed a commit to branch vuze5.6
in repository azureus.

commit 83ae82444eb94bb0d168952f8fc424644e890dd9
Author: Stephen Nelson <stephen at eccostudio.com>
Date:   Fri Jul 31 20:29:16 2015 +0100

    Imported Upstream version 5.6.1.2
---
 azureus2/src/Azureus2.jardesc                      |   968 +-
 azureus2/src/ChangeLog.txt                         |   189 +
 .../sun.net.spi.nameservice.NameServiceDescriptor  |     1 +
 .../src/com/aelitis/azureus/core/AzureusCore.java  |     5 +-
 .../aelitis/azureus/core/AzureusCoreComponent.java |     5 +-
 .../aelitis/azureus/core/AzureusCoreException.java |     5 +-
 .../aelitis/azureus/core/AzureusCoreFactory.java   |     5 +-
 .../azureus/core/AzureusCoreLifecycleAdapter.java  |     5 +-
 .../azureus/core/AzureusCoreLifecycleListener.java |     5 +-
 .../aelitis/azureus/core/AzureusCoreListener.java  |     5 +-
 .../aelitis/azureus/core/AzureusCoreOperation.java |     5 +-
 .../azureus/core/AzureusCoreOperationListener.java |     5 +-
 .../azureus/core/AzureusCoreOperationTask.java     |     5 +-
 .../azureus/core/AzureusCoreRunningListener.java   |    19 +-
 .../aelitis/azureus/core/backup/BackupManager.java |    15 +-
 .../azureus/core/backup/BackupManagerFactory.java  |    15 +-
 .../core/backup/impl/BackupManagerImpl.java        |    15 +-
 .../clientmessageservice/ClientMessageService.java |     5 +-
 .../ClientMessageServiceClient.java                |     5 +-
 .../clientmessageservice/impl/AEClientService.java |    12 +-
 .../impl/ClientConnection.java                     |     5 +-
 .../clientmessageservice/impl/ClientMessage.java   |     5 +-
 .../impl/ClientMessageHandler.java                 |     5 +-
 .../impl/NonBlockingReadWriteService.java          |     5 +-
 .../secure/SecureMessageServiceClient.java         |     5 +-
 .../secure/SecureMessageServiceClientAdapter.java  |     5 +-
 .../secure/SecureMessageServiceClientFactory.java  |     5 +-
 .../secure/SecureMessageServiceClientListener.java |     5 +-
 .../secure/SecureMessageServiceClientMessage.java  |     5 +-
 .../impl/SecureMessageServiceClientHelper.java     |     5 +-
 .../impl/SecureMessageServiceClientImpl.java       |     5 +-
 .../SecureMessageServiceClientMessageImpl.java     |     5 +-
 .../azureus/core/content/AzureusContent.java       |     5 +-
 .../core/content/AzureusContentDirectory.java      |     5 +-
 .../content/AzureusContentDirectoryListener.java   |    15 +-
 .../content/AzureusContentDirectoryManager.java    |     5 +-
 .../core/content/AzureusContentDownload.java       |    15 +-
 .../azureus/core/content/AzureusContentFile.java   |    15 +-
 .../azureus/core/content/AzureusContentFilter.java |    15 +-
 .../aelitis/azureus/core/custom/Customization.java |    15 +-
 .../core/custom/CustomizationException.java        |    15 +-
 .../azureus/core/custom/CustomizationManager.java  |    15 +-
 .../core/custom/CustomizationManagerFactory.java   |    15 +-
 .../core/custom/impl/CustomizationImpl.java        |    15 +-
 .../core/custom/impl/CustomizationManagerImpl.java |    15 +-
 azureus2/src/com/aelitis/azureus/core/dht/DHT.java |    38 +-
 .../com/aelitis/azureus/core/dht/DHTFactory.java   |    19 +-
 .../com/aelitis/azureus/core/dht/DHTListener.java  |    13 +-
 .../com/aelitis/azureus/core/dht/DHTLogger.java    |     5 +-
 .../azureus/core/dht/DHTOperationAdapter.java      |     5 +-
 .../azureus/core/dht/DHTOperationListener.java     |     5 +-
 .../azureus/core/dht/DHTStorageAdapter.java        |     5 +-
 .../aelitis/azureus/core/dht/DHTStorageBlock.java  |     5 +-
 .../aelitis/azureus/core/dht/DHTStorageKey.java    |     5 +-
 .../azureus/core/dht/DHTStorageKeyStats.java       |     5 +-
 .../azureus/core/dht/control/DHTControl.java       |    21 +-
 .../core/dht/control/DHTControlActivity.java       |     5 +-
 .../core/dht/control/DHTControlAdapter.java        |     5 +-
 .../core/dht/control/DHTControlContact.java        |     5 +-
 .../core/dht/control/DHTControlFactory.java        |    45 +-
 .../core/dht/control/DHTControlListener.java       |     5 +-
 .../azureus/core/dht/control/DHTControlStats.java  |     5 +-
 .../dht/control/impl/DHTControlContactImpl.java    |    15 +-
 .../core/dht/control/impl/DHTControlImpl.java      |   570 +-
 .../core/dht/control/impl/DHTControlStatsImpl.java |     5 +-
 .../src/com/aelitis/azureus/core/dht/db/DHTDB.java |    12 +-
 .../aelitis/azureus/core/dht/db/DHTDBFactory.java  |     5 +-
 .../azureus/core/dht/db/DHTDBLookupResult.java     |     5 +-
 .../aelitis/azureus/core/dht/db/DHTDBStats.java    |     5 +-
 .../aelitis/azureus/core/dht/db/DHTDBValue.java    |     5 +-
 .../azureus/core/dht/db/impl/DHTDBImpl.java        |   236 +-
 .../azureus/core/dht/db/impl/DHTDBMapping.java     |    24 +-
 .../azureus/core/dht/db/impl/DHTDBValueImpl.java   |     5 +-
 .../com/aelitis/azureus/core/dht/impl/DHTImpl.java |   139 +-
 .../com/aelitis/azureus/core/dht/impl/DHTLog.java  |     5 +-
 .../azureus/core/dht/nat/DHTNATPuncher.java        |     5 +-
 .../azureus/core/dht/nat/DHTNATPuncherAdapter.java |     5 +-
 .../azureus/core/dht/nat/DHTNATPuncherFactory.java |     5 +-
 .../core/dht/nat/DHTNATPuncherListener.java        |    15 +-
 .../core/dht/nat/impl/DHTNATPuncherImpl.java       |   155 +-
 .../core/dht/netcoords/DHTNetworkPosition.java     |     5 +-
 .../dht/netcoords/DHTNetworkPositionListener.java  |    15 +-
 .../dht/netcoords/DHTNetworkPositionManager.java   |    16 +-
 .../dht/netcoords/DHTNetworkPositionProvider.java  |     5 +-
 .../DHTNetworkPositionProviderInstance.java        |     5 +-
 .../DHTNetworkPositionProviderListener.java        |    15 +-
 .../dht/netcoords/vivaldi/ver1/Coordinates.java    |     8 +-
 .../netcoords/vivaldi/ver1/VivaldiPosition.java    |     8 +-
 .../vivaldi/ver1/VivaldiPositionFactory.java       |     5 +-
 .../vivaldi/ver1/VivaldiPositionProvider.java      |     5 +-
 .../vivaldi/ver1/impl/HeightCoordinatesImpl.java   |     8 +-
 .../vivaldi/ver1/impl/VivaldiPositionImpl.java     |     8 +-
 .../vivaldi/ver1/impl/tests/VivaldiTest.java       |     8 +-
 .../vivaldi/ver1/impl/tests/VivaldiVisualTest.java |     8 +-
 .../aelitis/azureus/core/dht/router/DHTRouter.java |     5 +-
 .../azureus/core/dht/router/DHTRouterAdapter.java  |     5 +-
 .../azureus/core/dht/router/DHTRouterContact.java  |     5 +-
 .../dht/router/DHTRouterContactAttachment.java     |     5 +-
 .../core/dht/router/DHTRouterContactWrapper.java   |    97 +
 .../azureus/core/dht/router/DHTRouterFactory.java  |     5 +-
 .../core/dht/router/DHTRouterFactoryObserver.java  |     5 +-
 .../azureus/core/dht/router/DHTRouterStats.java    |     5 +-
 .../azureus/core/dht/router/DHTRouterWrapper.java  |   211 +
 .../core/dht/router/impl/DHTRouterContactImpl.java |     5 +-
 .../core/dht/router/impl/DHTRouterImpl.java        |     7 +-
 .../core/dht/router/impl/DHTRouterNodeImpl.java    |     5 +-
 .../core/dht/router/impl/DHTRouterStatsImpl.java   |     5 +-
 .../azureus/core/dht/speed/DHTSpeedTester.java     |     5 +-
 .../core/dht/speed/DHTSpeedTesterContact.java      |     5 +-
 .../dht/speed/DHTSpeedTesterContactListener.java   |     5 +-
 .../core/dht/speed/DHTSpeedTesterFactory.java      |    12 +-
 .../core/dht/speed/DHTSpeedTesterListener.java     |     5 +-
 .../core/dht/speed/impl/DHTSpeedTesterImpl.java    |    10 +-
 .../azureus/core/dht/transport/DHTTransport.java   |    17 +-
 .../transport/DHTTransportAlternativeContact.java  |    60 +
 .../transport/DHTTransportAlternativeNetwork.java  |    40 +
 .../core/dht/transport/DHTTransportContact.java    |    29 +-
 .../core/dht/transport/DHTTransportException.java  |     5 +-
 .../core/dht/transport/DHTTransportFactory.java    |     5 +-
 .../dht/transport/DHTTransportFindValueReply.java  |     5 +-
 .../core/dht/transport/DHTTransportFullStats.java  |     5 +-
 .../core/dht/transport/DHTTransportListener.java   |     5 +-
 .../transport/DHTTransportProgressListener.java    |     5 +-
 .../dht/transport/DHTTransportQueryStoreReply.java |    15 +-
 .../dht/transport/DHTTransportReplyHandler.java    |     5 +-
 .../transport/DHTTransportReplyHandlerAdapter.java |     5 +-
 .../dht/transport/DHTTransportRequestHandler.java  |     7 +-
 .../core/dht/transport/DHTTransportStats.java      |     5 +-
 .../core/dht/transport/DHTTransportStoreReply.java |     5 +-
 .../dht/transport/DHTTransportTransferHandler.java |     5 +-
 .../core/dht/transport/DHTTransportValue.java      |     5 +-
 .../loopback/DHTTransportLoopbackContactImpl.java  |    41 +-
 .../loopback/DHTTransportLoopbackImpl.java         |    35 +-
 .../loopback/DHTTransportLoopbackStatsImpl.java    |     5 +-
 .../core/dht/transport/udp/DHTTransportUDP.java    |    39 +-
 .../dht/transport/udp/DHTTransportUDPContact.java  |     5 +-
 .../impl/DHTTransportAlternativeContactImpl.java   |   117 +
 .../impl/DHTTransportAlternativeNetworkImpl.java   |   253 +
 .../udp/impl/DHTTransportUDPContactImpl.java       |    45 +-
 .../transport/udp/impl/DHTTransportUDPImpl.java    |  1861 +--
 .../udp/impl/DHTTransportUDPStatsImpl.java         |     5 +-
 .../core/dht/transport/udp/impl/DHTUDPPacket.java  |     8 +-
 .../dht/transport/udp/impl/DHTUDPPacketData.java   |    13 +-
 .../dht/transport/udp/impl/DHTUDPPacketHelper.java |     5 +-
 .../dht/transport/udp/impl/DHTUDPPacketReply.java  |    31 +-
 .../transport/udp/impl/DHTUDPPacketReplyError.java |     3 +-
 .../udp/impl/DHTUDPPacketReplyFindNode.java        |     3 +-
 .../udp/impl/DHTUDPPacketReplyFindValue.java       |     3 +-
 .../udp/impl/DHTUDPPacketReplyKeyBlock.java        |     3 +-
 .../transport/udp/impl/DHTUDPPacketReplyPing.java  |    47 +-
 .../udp/impl/DHTUDPPacketReplyQueryStorage.java    |     3 +-
 .../transport/udp/impl/DHTUDPPacketReplyStats.java |     3 +-
 .../transport/udp/impl/DHTUDPPacketReplyStore.java |     3 +-
 .../transport/udp/impl/DHTUDPPacketRequest.java    |    29 +-
 .../udp/impl/DHTUDPPacketRequestFindNode.java      |     5 +-
 .../udp/impl/DHTUDPPacketRequestFindValue.java     |     5 +-
 .../udp/impl/DHTUDPPacketRequestKeyBlock.java      |     5 +-
 .../udp/impl/DHTUDPPacketRequestPing.java          |    42 +-
 .../udp/impl/DHTUDPPacketRequestQueryStorage.java  |     5 +-
 .../udp/impl/DHTUDPPacketRequestStats.java         |     5 +-
 .../udp/impl/DHTUDPPacketRequestStore.java         |     5 +-
 .../core/dht/transport/udp/impl/DHTUDPUtils.java   |   274 +-
 .../impl/packethandler/DHTUDPPacketHandler.java    |     5 +-
 .../DHTUDPPacketHandlerException.java              |     5 +-
 .../packethandler/DHTUDPPacketHandlerFactory.java  |     5 +-
 .../packethandler/DHTUDPPacketHandlerStats.java    |     5 +-
 .../packethandler/DHTUDPPacketHandlerStub.java     |    13 +-
 .../packethandler/DHTUDPPacketNetworkHandler.java  |     5 +-
 .../impl/packethandler/DHTUDPPacketReceiver.java   |     5 +-
 .../impl/packethandler/DHTUDPRequestHandler.java   |     5 +-
 .../dht/transport/util/DHTTransferHandler.java     |  1785 +++
 .../transport/util/DHTTransportRequestCounter.java |     7 +-
 .../dht/transport/util/DHTTransportStatsImpl.java  |    14 +-
 .../diskmanager/access/DiskAccessController.java   |     5 +-
 .../access/DiskAccessControllerFactory.java        |     5 +-
 .../access/DiskAccessControllerStats.java          |    15 +-
 .../core/diskmanager/access/DiskAccessRequest.java |     5 +-
 .../access/DiskAccessRequestListener.java          |     5 +-
 .../access/impl/DiskAccessControllerImpl.java      |     5 +-
 .../access/impl/DiskAccessControllerInstance.java  |     5 +-
 .../access/impl/DiskAccessRequestImpl.java         |     5 +-
 .../azureus/core/diskmanager/cache/CacheFile.java  |     5 +-
 .../core/diskmanager/cache/CacheFileManager.java   |     5 +-
 .../cache/CacheFileManagerException.java           |     5 +-
 .../diskmanager/cache/CacheFileManagerFactory.java |     5 +-
 .../diskmanager/cache/CacheFileManagerStats.java   |     5 +-
 .../core/diskmanager/cache/CacheFileOwner.java     |     5 +-
 .../core/diskmanager/cache/impl/CacheEntry.java    |     5 +-
 .../cache/impl/CacheFileManagerImpl.java           |     5 +-
 .../cache/impl/CacheFileManagerStatsImpl.java      |     5 +-
 .../diskmanager/cache/impl/CacheFileWithCache.java |     5 +-
 .../cache/impl/CacheFileWithoutCache.java          |     5 +-
 .../cache/impl/CacheFileWithoutCacheMT.java        |     5 +-
 .../azureus/core/diskmanager/file/FMFile.java      |     3 +-
 .../core/diskmanager/file/FMFileManager.java       |     3 +-
 .../diskmanager/file/FMFileManagerException.java   |     3 +-
 .../diskmanager/file/FMFileManagerFactory.java     |     3 +-
 .../azureus/core/diskmanager/file/FMFileOwner.java |     3 +-
 .../core/diskmanager/file/impl/FMFileAccess.java   |     5 +-
 .../diskmanager/file/impl/FMFileAccessCompact.java |     5 +-
 .../file/impl/FMFileAccessController.java          |     5 +-
 .../diskmanager/file/impl/FMFileAccessLinear.java  |     5 +-
 .../file/impl/FMFileAccessPieceReorderer.java      |     5 +-
 .../core/diskmanager/file/impl/FMFileImpl.java     |    26 +-
 .../core/diskmanager/file/impl/FMFileLimited.java  |     3 +-
 .../diskmanager/file/impl/FMFileManagerImpl.java   |     3 +-
 .../core/diskmanager/file/impl/FMFileTestImpl.java |     5 +-
 .../diskmanager/file/impl/FMFileUnlimited.java     |     3 +-
 .../core/drivedetector/DriveDetectedInfo.java      |     5 +-
 .../core/drivedetector/DriveDetectedListener.java  |     5 +-
 .../azureus/core/drivedetector/DriveDetector.java  |     5 +-
 .../core/drivedetector/DriveDetectorFactory.java   |     5 +-
 .../drivedetector/impl/DriveDetectedInfoImpl.java  |     5 +-
 .../core/drivedetector/impl/DriveDetectorImpl.java |   115 +-
 .../azureus/core/helpers/TorrentFolderWatcher.java |     5 +-
 .../aelitis/azureus/core/impl/AzureusCoreImpl.java |    21 +-
 .../core/impl/AzureusCoreSingleInstanceClient.java |     5 +-
 .../azureus/core/instancemanager/AZInstance.java   |     5 +-
 .../core/instancemanager/AZInstanceManager.java    |     5 +-
 .../instancemanager/AZInstanceManagerAdapter.java  |    15 +-
 .../instancemanager/AZInstanceManagerFactory.java  |     5 +-
 .../instancemanager/AZInstanceManagerListener.java |     5 +-
 .../core/instancemanager/AZInstanceTracked.java    |     5 +-
 .../core/instancemanager/impl/AZInstanceImpl.java  |     5 +-
 .../impl/AZInstanceManagerImpl.java                |     5 +-
 .../instancemanager/impl/AZMyInstanceImpl.java     |     5 +-
 .../instancemanager/impl/AZOtherInstanceImpl.java  |     5 +-
 .../instancemanager/impl/AZPortClashHandler.java   |     5 +-
 .../aelitis/azureus/core/lws/LWSDiskManager.java   |    15 +-
 .../azureus/core/lws/LWSDiskManagerState.java      |     5 +-
 .../com/aelitis/azureus/core/lws/LWSDownload.java  |    39 +-
 .../azureus/core/lws/LWSPeerManagerAdapter.java    |    16 +-
 .../com/aelitis/azureus/core/lws/LWSTorrent.java   |    15 +-
 .../aelitis/azureus/core/lws/LightWeightSeed.java  |    53 +-
 .../azureus/core/lws/LightWeightSeedAdapter.java   |    15 +-
 .../azureus/core/lws/LightWeightSeedManager.java   |    15 +-
 .../com/aelitis/azureus/core/nat/NATTraversal.java |     5 +-
 .../azureus/core/nat/NATTraversalException.java    |     5 +-
 .../azureus/core/nat/NATTraversalHandler.java      |     5 +-
 .../azureus/core/nat/NATTraversalObserver.java     |     5 +-
 .../com/aelitis/azureus/core/nat/NATTraverser.java |     5 +-
 .../core/networkmanager/ConnectionAttempt.java     |     5 +-
 .../core/networkmanager/ConnectionEndpoint.java    |    19 +-
 .../azureus/core/networkmanager/EventWaiter.java   |     5 +-
 .../core/networkmanager/IncomingMessageQueue.java  |     5 +-
 .../core/networkmanager/LimitedRateGroup.java      |     5 +-
 .../core/networkmanager/NetworkConnection.java     |     7 +-
 .../core/networkmanager/NetworkConnectionBase.java |     5 +-
 .../networkmanager/NetworkConnectionFactory.java   |   108 +-
 .../networkmanager/NetworkConnectionHelper.java    |     5 +-
 .../core/networkmanager/NetworkManager.java        |    16 +-
 .../core/networkmanager/OutgoingMessageQueue.java  |     5 +-
 .../core/networkmanager/ProtocolEndpoint.java      |     5 +-
 .../networkmanager/ProtocolEndpointFactory.java    |    15 +-
 .../networkmanager/ProtocolEndpointHandler.java    |    15 +-
 .../core/networkmanager/ProtocolStartpoint.java    |     5 +-
 .../azureus/core/networkmanager/RateHandler.java   |     5 +-
 .../azureus/core/networkmanager/RawMessage.java    |     5 +-
 .../azureus/core/networkmanager/Transport.java     |     9 +-
 .../azureus/core/networkmanager/TransportBase.java |     5 +-
 .../core/networkmanager/TransportEndpoint.java     |     5 +-
 .../core/networkmanager/TransportStartpoint.java   |    15 +-
 .../networkmanager/VirtualChannelSelector.java     |     5 +-
 .../VirtualServerChannelSelector.java              |     7 +-
 .../VirtualServerChannelSelectorFactory.java       |     5 +-
 .../core/networkmanager/admin/NetworkAdmin.java    |    16 +-
 .../core/networkmanager/admin/NetworkAdminASN.java |     5 +-
 .../admin/NetworkAdminASNListener.java             |    15 +-
 .../admin/NetworkAdminException.java               |     5 +-
 .../admin/NetworkAdminHTTPProxy.java               |     5 +-
 .../admin/NetworkAdminNATDevice.java               |     5 +-
 .../admin/NetworkAdminNetworkInterface.java        |     5 +-
 .../admin/NetworkAdminNetworkInterfaceAddress.java |     5 +-
 .../networkmanager/admin/NetworkAdminNode.java     |     5 +-
 .../admin/NetworkAdminProgressListener.java        |    15 +-
 .../admin/NetworkAdminPropertyChangeListener.java  |     5 +-
 .../networkmanager/admin/NetworkAdminProtocol.java |     5 +-
 .../admin/NetworkAdminRouteListener.java           |     5 +-
 .../admin/NetworkAdminRoutesListener.java          |    15 +-
 .../admin/NetworkAdminSocksProxy.java              |     5 +-
 .../admin/NetworkAdminSpeedTestScheduledTest.java  |     5 +-
 ...NetworkAdminSpeedTestScheduledTestListener.java |     5 +-
 .../admin/NetworkAdminSpeedTestScheduler.java      |     5 +-
 .../admin/NetworkAdminSpeedTester.java             |     5 +-
 .../admin/NetworkAdminSpeedTesterListener.java     |     5 +-
 .../admin/NetworkAdminSpeedTesterResult.java       |     5 +-
 .../admin/impl/NetworkAdminASNImpl.java            |     5 +-
 .../admin/impl/NetworkAdminASNLookupImpl.java      |     5 +-
 .../admin/impl/NetworkAdminHTTPProxyImpl.java      |     5 +-
 .../admin/impl/NetworkAdminHTTPTester.java         |     5 +-
 .../admin/impl/NetworkAdminImpl.java               |   178 +-
 .../admin/impl/NetworkAdminNATDeviceImpl.java      |     5 +-
 .../admin/impl/NetworkAdminNATUDPCodecs.java       |     5 +-
 .../admin/impl/NetworkAdminNATUDPReply.java        |     5 +-
 .../admin/impl/NetworkAdminNATUDPRequest.java      |     5 +-
 .../admin/impl/NetworkAdminProtocolImpl.java       |     5 +-
 .../admin/impl/NetworkAdminProtocolTester.java     |     5 +-
 .../admin/impl/NetworkAdminSocksProxyImpl.java     |     5 +-
 .../NetworkAdminSpeedTestScheduledTestImpl.java    |     5 +-
 .../impl/NetworkAdminSpeedTestSchedulerImpl.java   |     5 +-
 .../admin/impl/NetworkAdminSpeedTesterBTImpl.java  |     5 +-
 .../admin/impl/NetworkAdminSpeedTesterImpl.java    |     5 +-
 .../admin/impl/NetworkAdminTCPTester.java          |     5 +-
 .../admin/impl/NetworkAdminUDPTester.java          |     5 +-
 .../admin/impl/swt/NetworkAdminSWTImpl.java        |    22 +-
 .../core/networkmanager/impl/ByteBucket.java       |     5 +-
 .../core/networkmanager/impl/ByteBucketMT.java     |    15 +-
 .../core/networkmanager/impl/ByteBucketST.java     |    15 +-
 .../core/networkmanager/impl/EntityHandler.java    |     5 +-
 .../impl/IncomingConnectionManager.java            |     5 +-
 .../impl/IncomingMessageQueueImpl.java             |    13 +-
 .../networkmanager/impl/MultiPeerDownloader2.java  |     5 +-
 .../networkmanager/impl/MultiPeerUploader.java     |     5 +-
 .../networkmanager/impl/NetworkConnectionImpl.java |    13 +-
 .../impl/NetworkManagerUtilities.java              |     5 +-
 .../impl/OutgoingMessageQueueImpl.java             |     5 +-
 .../core/networkmanager/impl/ProtocolDecoder.java  |     5 +-
 .../impl/ProtocolDecoderAdapter.java               |     5 +-
 .../impl/ProtocolDecoderInitial.java               |    30 +-
 .../networkmanager/impl/ProtocolDecoderPHE.java    |    11 +-
 .../networkmanager/impl/RateControlledEntity.java  |     5 +-
 .../core/networkmanager/impl/RawMessageImpl.java   |     5 +-
 .../core/networkmanager/impl/ReadController.java   |     5 +-
 .../networkmanager/impl/SinglePeerDownloader.java  |     5 +-
 .../networkmanager/impl/SinglePeerUploader.java    |     5 +-
 .../networkmanager/impl/TransferProcessor.java     |   226 +-
 .../core/networkmanager/impl/TransportCipher.java  |     5 +-
 .../impl/TransportCryptoManager.java               |     5 +-
 .../core/networkmanager/impl/TransportHelper.java  |     5 +-
 .../networkmanager/impl/TransportHelperFilter.java |     5 +-
 .../impl/TransportHelperFilterInserter.java        |     5 +-
 .../impl/TransportHelperFilterStream.java          |     5 +-
 .../impl/TransportHelperFilterStreamCipher.java    |     5 +-
 .../impl/TransportHelperFilterStreamXOR.java       |     5 +-
 .../impl/TransportHelperFilterTransparent.java     |     5 +-
 .../core/networkmanager/impl/TransportImpl.java    |     5 +-
 .../core/networkmanager/impl/TransportStats.java   |     5 +-
 .../core/networkmanager/impl/WriteController.java  |     5 +-
 .../core/networkmanager/impl/http/HTTPMessage.java |     5 +-
 .../impl/http/HTTPMessageDecoder.java              |     5 +-
 .../impl/http/HTTPMessageEncoder.java              |     5 +-
 .../impl/http/HTTPNetworkConnection.java           |     8 +-
 .../impl/http/HTTPNetworkConnectionFile.java       |     5 +-
 .../impl/http/HTTPNetworkConnectionWebSeed.java    |     5 +-
 .../impl/http/HTTPNetworkManager.java              |     5 +-
 .../impl/tcp/IncomingSocketChannelManager.java     |    18 +-
 .../impl/tcp/LightweightTCPTransport.java          |     5 +-
 .../impl/tcp/ProtocolEndpointTCP.java              |     5 +-
 .../networkmanager/impl/tcp/ProxyLoginHandler.java |    44 +-
 .../networkmanager/impl/tcp/SelectorGuard.java     |     5 +-
 .../impl/tcp/TCPConnectionManager.java             |    49 +-
 .../networkmanager/impl/tcp/TCPNetworkManager.java |    13 +-
 .../impl/tcp/TCPTransportHelper.java               |    25 +-
 .../impl/tcp/TCPTransportHelperFilterFactory.java  |     5 +-
 .../networkmanager/impl/tcp/TCPTransportImpl.java  |   190 +-
 .../impl/tcp/TransportEndpointTCP.java             |     5 +-
 .../impl/tcp/TransportStartpointTCP.java           |     5 +-
 .../impl/tcp/VirtualAcceptSelector.java            |     5 +-
 .../tcp/VirtualBlockingServerChannelSelector.java  |    12 +-
 .../impl/tcp/VirtualChannelSelectorImpl.java       |     8 +-
 .../VirtualNonBlockingServerChannelSelector.java   |    13 +-
 .../core/networkmanager/impl/test/PHETester.java   |     5 +-
 .../core/networkmanager/impl/udp/NetworkGlue.java  |     5 +-
 .../impl/udp/NetworkGlueListener.java              |     5 +-
 .../impl/udp/NetworkGlueLoopBack.java              |     5 +-
 .../networkmanager/impl/udp/NetworkGlueUDP.java    |     5 +-
 .../impl/udp/ProtocolEndpointUDP.java              |     5 +-
 .../impl/udp/TransportEndpointUDP.java             |     5 +-
 .../networkmanager/impl/udp/UDPConnection.java     |     5 +-
 .../impl/udp/UDPConnectionManager.java             |    14 +-
 .../networkmanager/impl/udp/UDPConnectionSet.java  |     5 +-
 .../networkmanager/impl/udp/UDPNetworkManager.java |     5 +-
 .../core/networkmanager/impl/udp/UDPPacket.java    |     5 +-
 .../core/networkmanager/impl/udp/UDPSelector.java  |     5 +-
 .../core/networkmanager/impl/udp/UDPTransport.java |     5 +-
 .../impl/udp/UDPTransportHelper.java               |     5 +-
 .../aelitis/azureus/core/pairing/PairedNode.java   |    15 +-
 .../azureus/core/pairing/PairedService.java        |    15 +-
 .../core/pairing/PairedServiceRequestHandler.java  |    15 +-
 .../core/pairing/PairingConnectionData.java        |    17 +-
 .../azureus/core/pairing/PairingException.java     |    15 +-
 .../azureus/core/pairing/PairingManager.java       |    17 +-
 .../core/pairing/PairingManagerFactory.java        |    15 +-
 .../core/pairing/PairingManagerListener.java       |    15 +-
 .../aelitis/azureus/core/pairing/PairingTest.java  |    15 +-
 .../azureus/core/pairing/PairingTestListener.java  |    15 +-
 .../core/pairing/impl/PairManagerTunnel.java       |    15 +-
 .../core/pairing/impl/PairingManagerImpl.java      |    43 +-
 .../pairing/impl/PairingManagerTunnelHandler.java  |    15 +-
 .../azureus/core/pairing/impl/swt/PMSWTImpl.java   |    25 +-
 .../azureus/core/peermanager/PeerManager.java      |    30 +-
 .../core/peermanager/PeerManagerRegistration.java  |     5 +-
 .../PeerManagerRegistrationAdapter.java            |     5 +-
 .../peermanager/PeerManagerRoutingListener.java    |     5 +-
 .../peermanager/control/PeerControlInstance.java   |     5 +-
 .../peermanager/control/PeerControlScheduler.java  |     5 +-
 .../control/PeerControlSchedulerFactory.java       |     5 +-
 .../peermanager/control/SpeedTokenDispenser.java   |     5 +-
 .../control/impl/PeerControlSchedulerBasic.java    |     5 +-
 .../control/impl/PeerControlSchedulerImpl.java     |     5 +-
 .../impl/PeerControlSchedulerPrioritised.java      |     5 +-
 .../control/impl/SpeedTokenDispenserBasic.java     |     5 +-
 .../core/peermanager/messaging/Message.java        |     5 +-
 .../peermanager/messaging/MessageException.java    |     5 +-
 .../core/peermanager/messaging/MessageManager.java |     5 +-
 .../messaging/MessageStreamDecoder.java            |     5 +-
 .../messaging/MessageStreamEncoder.java            |     5 +-
 .../messaging/MessageStreamFactory.java            |     5 +-
 .../core/peermanager/messaging/MessagingUtil.java  |     5 +-
 .../peermanager/messaging/azureus/AZBadPiece.java  |     5 +-
 .../messaging/azureus/AZGenericMapPayload.java     |     5 +-
 .../peermanager/messaging/azureus/AZHandshake.java |     5 +-
 .../core/peermanager/messaging/azureus/AZHave.java |     5 +-
 .../peermanager/messaging/azureus/AZMessage.java   |     5 +-
 .../messaging/azureus/AZMessageDecoder.java        |     5 +-
 .../messaging/azureus/AZMessageEncoder.java        |     5 +-
 .../messaging/azureus/AZMessageFactory.java        |     5 +-
 .../peermanager/messaging/azureus/AZMetaData.java  |    15 +-
 .../messaging/azureus/AZPeerExchange.java          |     7 +-
 .../messaging/azureus/AZRequestHint.java           |     5 +-
 .../peermanager/messaging/azureus/AZStatReply.java |     5 +-
 .../messaging/azureus/AZStatRequest.java           |     5 +-
 .../messaging/azureus/AZStylePeerExchange.java     |     5 +-
 .../messaging/azureus/AZUTMetaData.java            |    15 +-
 .../messaging/bittorrent/BTAllowedFast.java        |     5 +-
 .../messaging/bittorrent/BTBitfield.java           |     5 +-
 .../peermanager/messaging/bittorrent/BTCancel.java |     5 +-
 .../peermanager/messaging/bittorrent/BTChoke.java  |     5 +-
 .../messaging/bittorrent/BTDHTPort.java            |     5 +-
 .../messaging/bittorrent/BTHandshake.java          |     5 +-
 .../peermanager/messaging/bittorrent/BTHave.java   |     5 +-
 .../messaging/bittorrent/BTHaveAll.java            |     5 +-
 .../messaging/bittorrent/BTHaveNone.java           |     5 +-
 .../messaging/bittorrent/BTInterested.java         |     5 +-
 .../messaging/bittorrent/BTKeepAlive.java          |     5 +-
 .../messaging/bittorrent/BTLTMessage.java          |     5 +-
 .../messaging/bittorrent/BTMessage.java            |     5 +-
 .../messaging/bittorrent/BTMessageDecoder.java     |     5 +-
 .../messaging/bittorrent/BTMessageEncoder.java     |     5 +-
 .../messaging/bittorrent/BTMessageFactory.java     |     5 +-
 .../peermanager/messaging/bittorrent/BTPiece.java  |     5 +-
 .../messaging/bittorrent/BTRawMessage.java         |    15 +-
 .../messaging/bittorrent/BTRejectRequest.java      |     5 +-
 .../messaging/bittorrent/BTRequest.java            |     5 +-
 .../messaging/bittorrent/BTSuggestPiece.java       |     5 +-
 .../messaging/bittorrent/BTUnchoke.java            |     5 +-
 .../messaging/bittorrent/BTUninterested.java       |     5 +-
 .../ltep/LTDisabledExtensionMessage.java           |     5 +-
 .../messaging/bittorrent/ltep/LTHandshake.java     |    15 +
 .../messaging/bittorrent/ltep/LTMessage.java       |     6 +-
 .../bittorrent/ltep/LTMessageDecoder.java          |    52 +-
 .../bittorrent/ltep/LTMessageEncoder.java          |    79 +-
 .../bittorrent/ltep/LTMessageFactory.java          |     5 +-
 .../messaging/bittorrent/ltep/UTMetaData.java      |    15 +-
 .../messaging/bittorrent/ltep/UTPeerExchange.java  |    13 +-
 .../messaging/bittorrent/ltep/UTUploadOnly.java    |    15 +-
 .../core/peermanager/nat/PeerNATInitiator.java     |     5 +-
 .../peermanager/nat/PeerNATTraversalAdapter.java   |     5 +-
 .../core/peermanager/nat/PeerNATTraverser.java     |     5 +-
 .../core/peermanager/peerdb/PeerDatabase.java      |    38 +-
 .../peermanager/peerdb/PeerDatabaseFactory.java    |     5 +-
 .../core/peermanager/peerdb/PeerExchangerItem.java |   102 +-
 .../azureus/core/peermanager/peerdb/PeerItem.java  |   108 +-
 .../core/peermanager/peerdb/PeerItemFactory.java   |     9 +-
 .../peermanager/piecepicker/EndGameModeChunk.java  |     3 +-
 .../core/peermanager/piecepicker/PiecePicker.java  |     5 +-
 .../piecepicker/PiecePickerFactory.java            |     5 +-
 .../piecepicker/PiecePickerListener.java           |     5 +-
 .../piecepicker/PiecePriorityProvider.java         |     5 +-
 .../peermanager/piecepicker/PieceRTAProvider.java  |     5 +-
 .../piecepicker/impl/PiecePickerImpl.java          |    38 +-
 .../peermanager/piecepicker/util/BitFlags.java     |     5 +-
 .../peermanager/unchoker/DownloadingUnchoker.java  |    11 +-
 .../core/peermanager/unchoker/SeedingUnchoker.java |    12 +-
 .../core/peermanager/unchoker/Unchoker.java        |     7 +-
 .../core/peermanager/unchoker/UnchokerFactory.java |    15 +-
 .../core/peermanager/unchoker/UnchokerUtil.java    |   109 +-
 .../peermanager/uploadslots/DownloadingRanker.java |     5 +-
 .../peermanager/uploadslots/SeedingRanker.java     |     5 +-
 .../core/peermanager/uploadslots/UploadHelper.java |     2 +-
 .../peermanager/uploadslots/UploadSession.java     |     2 +-
 .../uploadslots/UploadSessionPicker.java           |     2 +-
 .../core/peermanager/uploadslots/UploadSlot.java   |     2 +-
 .../peermanager/uploadslots/UploadSlotManager.java |     2 +-
 .../peermanager/utils/AZPeerIdentityManager.java   |     5 +-
 .../peermanager/utils/BTPeerIDByteDecoder.java     |    16 +-
 .../utils/BTPeerIDByteDecoderDefinitions.java      |    16 +-
 .../utils/BTPeerIDByteDecoderUtils.java            |    11 +-
 .../core/peermanager/utils/ClientIdentifier.java   |    16 +-
 .../utils/OutgoingBTHaveMessageAggregator.java     |     5 +-
 .../utils/OutgoingBTPieceMessageHandler.java       |     5 +-
 .../OutgoingBTPieceMessageHandlerAdapter.java      |     5 +-
 .../core/peermanager/utils/PeerClassifier.java     |     5 +-
 .../core/peermanager/utils/PeerMessageLimiter.java |     5 +-
 .../com/aelitis/azureus/core/proxy/AEProxy.java    |     5 +-
 .../azureus/core/proxy/AEProxyAddressMapper.java   |    24 +-
 .../azureus/core/proxy/AEProxyConnection.java      |     5 +-
 .../core/proxy/AEProxyConnectionListener.java      |     5 +-
 .../azureus/core/proxy/AEProxyException.java       |     5 +-
 .../aelitis/azureus/core/proxy/AEProxyFactory.java |    82 +-
 .../aelitis/azureus/core/proxy/AEProxyHandler.java |     5 +-
 .../azureus/core/proxy/AEProxySelector.java        |    26 +-
 .../azureus/core/proxy/AEProxySelectorFactory.java |    17 +-
 .../aelitis/azureus/core/proxy/AEProxyState.java   |     5 +-
 .../core/proxy/impl/AEPluginProxyHandler.java      |   409 +-
 .../core/proxy/impl/AEProxyAddressMapperImpl.java  |   114 +-
 .../core/proxy/impl/AEProxyConnectionImpl.java     |    37 +-
 .../azureus/core/proxy/impl/AEProxyImpl.java       |   123 +-
 .../core/proxy/impl/AEProxySelectorImpl.java       |   131 +-
 .../proxy/impl/swt/AEProxySelectorSWTImpl.java     |    21 +-
 .../azureus/core/proxy/socks/AESocksProxy.java     |     5 +-
 .../core/proxy/socks/AESocksProxyAddress.java      |     5 +-
 .../core/proxy/socks/AESocksProxyConnection.java   |    11 +-
 .../core/proxy/socks/AESocksProxyFactory.java      |     5 +-
 .../socks/AESocksProxyPlugableConnection.java      |     5 +-
 .../AESocksProxyPlugableConnectionFactory.java     |     5 +-
 .../proxy/socks/impl/AESocksProxyAddressImpl.java  |     5 +-
 .../socks/impl/AESocksProxyConnectionImpl.java     |   348 +-
 .../core/proxy/socks/impl/AESocksProxyImpl.java    |     5 +-
 .../AESocksProxyPlugableConnectionDefault.java     |    24 +-
 .../core/proxy/socks/impl/AESocksProxyState.java   |     5 +-
 .../azureus/core/rssgen/RSSGeneratorPlugin.java    |   599 +-
 .../azureus/core/security/CryptoECCUtils.java      |   347 +-
 .../azureus/core/security/CryptoHandler.java       |    15 +-
 .../azureus/core/security/CryptoManager.java       |     5 +-
 .../core/security/CryptoManagerException.java      |     5 +-
 .../core/security/CryptoManagerFactory.java        |     5 +-
 .../core/security/CryptoManagerKeyListener.java    |    67 +-
 .../security/CryptoManagerPasswordException.java   |     5 +-
 .../security/CryptoManagerPasswordHandler.java     |     5 +-
 .../azureus/core/security/CryptoSTSEngine.java     |     5 +-
 .../core/security/impl/CryptoHandlerECC.java       |    25 +-
 .../core/security/impl/CryptoManagerImpl.java      |     5 +-
 .../core/security/impl/CryptoSTSEngineImpl.java    |     5 +-
 .../core/speedmanager/SpeedLimitHandler.java       |  1316 +-
 .../azureus/core/speedmanager/SpeedManager.java    |     5 +-
 .../core/speedmanager/SpeedManagerAdapter.java     |     5 +-
 .../core/speedmanager/SpeedManagerFactory.java     |     5 +-
 .../speedmanager/SpeedManagerLimitEstimate.java    |     5 +-
 .../core/speedmanager/SpeedManagerListener.java    |     5 +-
 .../core/speedmanager/SpeedManagerPingMapper.java  |     5 +-
 .../core/speedmanager/SpeedManagerPingSource.java  |     5 +-
 .../core/speedmanager/SpeedManagerPingZone.java    |     5 +-
 .../impl/SpeedManagerAlgorithmProvider.java        |     5 +-
 .../impl/SpeedManagerAlgorithmProviderAdapter.java |     5 +-
 .../core/speedmanager/impl/SpeedManagerImpl.java   |     5 +-
 .../impl/SpeedManagerPingMapperImpl.java           |     5 +-
 .../core/speedmanager/impl/TestPingSourceImpl.java |     5 +-
 .../speedmanager/impl/TestPingSourceRandom.java    |     5 +-
 .../impl/v1/SpeedManagerAlgorithmProviderV1.java   |     5 +-
 .../core/speedmanager/impl/v2/LimitControl.java    |     5 +-
 .../impl/v2/LimitControlDropUploadFirst.java       |     5 +-
 .../speedmanager/impl/v2/LimitControlSetting.java  |     5 +-
 .../speedmanager/impl/v2/PSMonitorListener.java    |     5 +-
 .../speedmanager/impl/v2/PingSourceManager.java    |     5 +-
 .../core/speedmanager/impl/v2/PingSourceStats.java |     5 +-
 .../core/speedmanager/impl/v2/PingSpaceMapper.java |     5 +-
 .../core/speedmanager/impl/v2/PingSpaceMon.java    |     5 +-
 .../speedmanager/impl/v2/PingSpaceMonitor.java     |     5 +-
 .../impl/v2/SMConfigurationAdapter.java            |     5 +-
 .../impl/v2/SMConfigurationAdapterImpl.java        |     5 +-
 .../azureus/core/speedmanager/impl/v2/SMConst.java |     5 +-
 .../core/speedmanager/impl/v2/SMInstance.java      |     5 +-
 .../core/speedmanager/impl/v2/SMSearchLogger.java  |     5 +-
 .../core/speedmanager/impl/v2/SMSearchManager.java |     5 +-
 .../core/speedmanager/impl/v2/SMUpdate.java        |     5 +-
 .../core/speedmanager/impl/v2/SaturatedMode.java   |     5 +-
 .../speedmanager/impl/v2/SpeedLimitConfidence.java |     5 +-
 .../speedmanager/impl/v2/SpeedLimitListener.java   |     5 +-
 .../speedmanager/impl/v2/SpeedLimitMonitor.java    |     5 +-
 .../v2/SpeedManagerAlgorithmProviderDHTPing.java   |     5 +-
 .../v2/SpeedManagerAlgorithmProviderPingMap.java   |     5 +-
 .../impl/v2/SpeedManagerAlgorithmProviderV2.java   |     5 +-
 .../speedmanager/impl/v2/SpeedManagerLogger.java   |   111 +-
 .../core/speedmanager/impl/v2/TransferMode.java    |     5 +-
 .../impl/v3/SpeedManagerAlgorithmProviderV3.java   |     5 +-
 .../azureus/core/stats/AzureusCoreStats.java       |     5 +-
 .../core/stats/AzureusCoreStatsProvider.java       |     5 +-
 azureus2/src/com/aelitis/azureus/core/tag/Tag.java |    25 +-
 .../com/aelitis/azureus/core/tag/TagDiscovery.java |    77 +
 .../com/aelitis/azureus/core/tag/TagDownload.java  |    17 +-
 .../com/aelitis/azureus/core/tag/TagException.java |    15 +-
 .../com/aelitis/azureus/core/tag/TagFeature.java   |    16 +-
 .../azureus/core/tag/TagFeatureAddress.java        |    15 +-
 .../azureus/core/tag/TagFeatureExecOnAssign.java   |    47 +
 .../azureus/core/tag/TagFeatureFileLocation.java   |    31 +-
 .../azureus/core/tag/TagFeatureListener.java       |    15 +-
 .../azureus/core/tag/TagFeatureProperties.java     |    16 +-
 .../azureus/core/tag/TagFeatureRSSFeed.java        |    15 +-
 .../azureus/core/tag/TagFeatureRateLimit.java      |    15 +-
 .../azureus/core/tag/TagFeatureRunState.java       |    15 +-
 .../azureus/core/tag/TagFeatureTranscode.java      |    15 +-
 .../com/aelitis/azureus/core/tag/TagListener.java  |    15 +-
 .../com/aelitis/azureus/core/tag/TagManager.java   |    15 +-
 .../azureus/core/tag/TagManagerFactory.java        |    15 +-
 .../azureus/core/tag/TagManagerListener.java       |    15 +-
 .../src/com/aelitis/azureus/core/tag/TagPeer.java  |    17 +-
 .../src/com/aelitis/azureus/core/tag/TagType.java  |    15 +-
 .../aelitis/azureus/core/tag/TagTypeAdapter.java   |    15 +-
 .../aelitis/azureus/core/tag/TagTypeListener.java  |    15 +-
 .../src/com/aelitis/azureus/core/tag/Taggable.java |    15 +-
 .../azureus/core/tag/TaggableLifecycleAdapter.java |    64 +
 .../azureus/core/tag/TaggableLifecycleHandler.java |    15 +-
 .../core/tag/TaggableLifecycleListener.java        |    39 +-
 .../aelitis/azureus/core/tag/TaggableResolver.java |    15 +-
 .../com/aelitis/azureus/core/tag/impl/TagBase.java |   169 +-
 .../core/tag/impl/TagDownloadWithState.java        |    42 +-
 .../azureus/core/tag/impl/TagManagerImpl.java      |   497 +-
 .../tag/impl/TagPropertyConstraintHandler.java     |  1470 +++
 .../core/tag/impl/TagPropertyTrackerHandler.java   |    24 +-
 .../impl/TagPropertyTrackerTemplateHandler.java    |    32 +-
 .../core/tag/impl/TagPropertyUntaggedHandler.java  |    23 +-
 .../aelitis/azureus/core/tag/impl/TagTypeBase.java |    17 +-
 .../core/tag/impl/TagTypeDownloadManual.java       |    15 +-
 .../azureus/core/tag/impl/TagTypeWithState.java    |    15 +-
 .../azureus/core/tag/impl/TagWithState.java        |    18 +-
 .../azureus/core/tracker/TrackerPeerSource.java    |   205 +-
 .../core/tracker/TrackerPeerSourceAdapter.java     |   261 +-
 .../azureus/core/update/AzureusRestarter.java      |     5 +-
 .../core/update/AzureusRestarterFactory.java       |     5 +-
 .../core/update/impl/AzureusRestarterImpl.java     |     5 +-
 .../aelitis/azureus/core/util/AEPriorityMixin.java |    17 +-
 .../aelitis/azureus/core/util/AZ3Functions.java    |   225 +-
 .../azureus/core/util/ByteCountedInputStream.java  |     5 +-
 .../azureus/core/util/CaseSensitiveFileMap.java    |     5 +-
 .../aelitis/azureus/core/util/CopyOnWriteList.java |     9 +-
 .../aelitis/azureus/core/util/CopyOnWriteMap.java  |    38 +-
 .../aelitis/azureus/core/util/CopyOnWriteSet.java  |   391 +-
 .../com/aelitis/azureus/core/util/DNSUtils.java    |   211 +-
 .../core/util/DeleteFileOnCloseInputStream.java    |     5 +-
 .../azureus/core/util/FeatureAvailability.java     |     5 +-
 .../aelitis/azureus/core/util/GeneralUtils.java    |   747 +-
 .../com/aelitis/azureus/core/util/HTTPUtils.java   |    55 +-
 .../aelitis/azureus/core/util/HashCodeUtils.java   |     5 +-
 .../aelitis/azureus/core/util/IdentityHashSet.java |    17 +-
 .../aelitis/azureus/core/util/LaunchManager.java   |   303 +-
 .../com/aelitis/azureus/core/util/LinkFileMap.java |     5 +-
 .../azureus/core/util/MultiPartDecoder.java        |     2 +-
 .../com/aelitis/azureus/core/util/NetUtils.java    |     5 +-
 .../aelitis/azureus/core/util/QTFastStartRAF.java  |    17 +-
 .../com/aelitis/azureus/core/util/RegExUtil.java   |    17 +-
 .../aelitis/azureus/core/util/UUIDGenerator.java   |     5 +-
 .../azureus/core/util/UncloseableInputStream.java  |   144 +
 .../aelitis/azureus/core/util/average/Average.java |     5 +-
 .../azureus/core/util/average/AverageFactory.java  |     5 +-
 .../util/average/ExponentialMovingAverage.java     |     5 +-
 .../azureus/core/util/average/MovingAverage.java   |     5 +-
 .../core/util/average/MovingImmediateAverage.java  |     5 +-
 .../azureus/core/util/average/RunningAverage.java  |     5 +-
 .../azureus/core/util/bloom/BloomFilter.java       |    17 +-
 .../core/util/bloom/BloomFilterFactory.java        |     5 +-
 .../core/util/bloom/impl/BloomFilterAddOnly.java   |     5 +-
 .../util/bloom/impl/BloomFilterAddRemove4Bit.java  |     5 +-
 .../util/bloom/impl/BloomFilterAddRemove8Bit.java  |     5 +-
 .../core/util/bloom/impl/BloomFilterImpl.java      |     5 +-
 .../core/util/bloom/impl/BloomFilterRotator.java   |   482 +-
 .../azureus/core/util/dns/DNSUtilsImpl.java        |    15 +-
 .../azureus/core/util/http/HTTPAuthHelper.java     |  2969 +++--
 .../core/util/http/HTTPAuthHelperListener.java     |    63 +-
 .../aelitis/azureus/core/util/png/CRCedChunk.java  |    17 +-
 .../com/aelitis/azureus/core/util/png/Chunk.java   |    17 +-
 .../aelitis/azureus/core/util/png/IDATChunk.java   |    17 +-
 .../aelitis/azureus/core/util/png/IENDChunk.java   |    17 +-
 .../aelitis/azureus/core/util/png/IHDRChunk.java   |    17 +-
 .../src/com/aelitis/azureus/core/util/png/PNG.java |    17 +-
 .../azureus/core/util/png/PngSignatureChunk.java   |    17 +-
 .../core/versioncheck/VersionCheckClient.java      |    29 +-
 .../versioncheck/VersionCheckClientListener.java   |     6 +-
 .../versioncheck/VersionCheckClientUDPCodecs.java  |     5 +-
 .../versioncheck/VersionCheckClientUDPReply.java   |     5 +-
 .../versioncheck/VersionCheckClientUDPRequest.java |     5 +-
 .../aelitis/azureus/core/vuzefile/VuzeFile.java    |   123 +-
 .../azureus/core/vuzefile/VuzeFileComponent.java   |   131 +-
 .../azureus/core/vuzefile/VuzeFileHandler.java     |   539 +-
 .../azureus/core/vuzefile/VuzeFileImpl.java        |   541 +-
 .../azureus/core/vuzefile/VuzeFileMerger.java      |   221 +-
 .../azureus/core/vuzefile/VuzeFileProcessor.java   |    61 +-
 .../azureus/launcher/ClassLoaderWitness.java       |     5 +-
 .../src/com/aelitis/azureus/launcher/Launcher.java |     5 +-
 .../com/aelitis/azureus/launcher/LauncherTest.java |     5 +-
 .../com/aelitis/azureus/launcher/MainExecutor.java |     5 +-
 .../launcher/classloading/PeeringClassloader.java  |     5 +-
 .../launcher/classloading/PrimaryClassloader.java  |     5 +-
 .../classloading/SecondaryClassLoader.java         |     5 +-
 .../com/aelitis/azureus/plugins/I2PHelpers.java    |   166 +
 .../azureus/plugins/clientid/ClientIDPlugin.java   |     5 +-
 .../com/aelitis/azureus/plugins/dht/DHTPlugin.java |    66 +-
 .../azureus/plugins/dht/DHTPluginContact.java      |    34 +-
 .../azureus/plugins/dht/DHTPluginInterface.java    |   174 +
 .../azureus/plugins/dht/DHTPluginKeyStats.java     |     5 +-
 .../azureus/plugins/dht/DHTPluginListener.java     |     5 +-
 .../plugins/dht/DHTPluginOperationAdapter.java     |    61 +
 .../plugins/dht/DHTPluginOperationListener.java    |     5 +-
 .../plugins/dht/DHTPluginProgressListener.java     |     5 +-
 .../plugins/dht/DHTPluginTransferHandler.java      |     7 +-
 .../azureus/plugins/dht/DHTPluginValue.java        |     5 +-
 .../plugins/dht/impl/DHTPluginContactImpl.java     |    76 +-
 .../azureus/plugins/dht/impl/DHTPluginImpl.java    |   297 +-
 .../plugins/dht/impl/DHTPluginImplAdapter.java     |     5 +-
 .../plugins/dht/impl/DHTPluginStorageManager.java  |    14 +-
 .../plugins/dht/impl/DHTPluginValueImpl.java       |     5 +-
 .../plugins/extseed/ExternalSeedException.java     |     5 +-
 .../plugins/extseed/ExternalSeedManualPeer.java    |   117 +-
 .../azureus/plugins/extseed/ExternalSeedPeer.java  |     5 +-
 .../plugins/extseed/ExternalSeedPlugin.java        |    85 +-
 .../plugins/extseed/ExternalSeedReader.java        |     5 +-
 .../plugins/extseed/ExternalSeedReaderFactory.java |    11 +-
 .../extseed/ExternalSeedReaderListener.java        |     5 +-
 .../extseed/impl/ExternalSeedReaderImpl.java       |    33 +-
 .../extseed/impl/ExternalSeedReaderRequest.java    |     5 +-
 .../ExternalSeedReaderFactoryGetRight.java         |    44 +-
 .../impl/getright/ExternalSeedReaderGetRight.java  |     5 +-
 .../webseed/ExternalSeedReaderFactoryWebSeed.java  |    48 +-
 .../impl/webseed/ExternalSeedReaderWebSeed.java    |     5 +-
 .../extseed/util/ExternalSeedHTTPDownloader.java   |     5 +-
 .../util/ExternalSeedHTTPDownloaderLinear.java     |  1361 +-
 .../util/ExternalSeedHTTPDownloaderListener.java   |     5 +-
 .../util/ExternalSeedHTTPDownloaderRange.java      |   139 +-
 .../azureus/plugins/magnet/MagnetPlugin.java       |  1410 +-
 .../plugins/magnet/MagnetPluginException.java      |     5 +-
 .../plugins/magnet/MagnetPluginListener.java       |     5 +-
 .../plugins/magnet/MagnetPluginMDDownloader.java   |   302 +-
 .../magnet/MagnetPluginProgressListener.java       |     5 +-
 .../plugins/magnet/swt/MagnetPluginUISWT.java      |    15 +-
 .../azureus/plugins/net/buddy/BuddyPlugin.java     |  8815 ++++++-------
 .../azureus/plugins/net/buddy/BuddyPluginAZ2.java  |  2041 ++-
 .../net/buddy/BuddyPluginAZ2ChatListener.java      |    89 +-
 .../plugins/net/buddy/BuddyPluginAZ2Listener.java  |    69 +-
 .../net/buddy/BuddyPluginAZ2TrackerListener.java   |    75 +-
 .../plugins/net/buddy/BuddyPluginAdapter.java      |   132 +-
 .../azureus/plugins/net/buddy/BuddyPluginBeta.java |  5524 ++++++++
 .../plugins/net/buddy/BuddyPluginBuddy.java        |  6897 +++++-----
 .../plugins/net/buddy/BuddyPluginBuddyMessage.java |   247 +-
 .../net/buddy/BuddyPluginBuddyMessageHandler.java  |  2125 ++-
 .../net/buddy/BuddyPluginBuddyMessageListener.java |   107 +-
 .../net/buddy/BuddyPluginBuddyReplyListener.java   |    75 +-
 .../net/buddy/BuddyPluginBuddyRequestListener.java |   105 +-
 .../plugins/net/buddy/BuddyPluginException.java    |    85 +-
 .../plugins/net/buddy/BuddyPluginListener.java     |   104 +-
 .../net/buddy/BuddyPluginPasswordException.java    |    95 +-
 .../net/buddy/BuddyPluginTimeoutException.java     |    89 +-
 .../plugins/net/buddy/BuddyPluginUtils.java        |   365 +
 .../net/buddy/BuddyPluginViewInterface.java        |    73 +
 .../plugins/net/buddy/swt/BuddyPluginView.java     |  3268 ++++-
 .../net/buddy/swt/BuddyPluginViewBetaChat.java     |  4219 ++++++
 .../plugins/net/buddy/swt/BuddyPluginViewChat.java |   917 +-
 .../net/buddy/swt/BuddyPluginViewInstance.java     |  4685 ++++---
 .../net/buddy/tracker/BuddyPluginTracker.java      |  4650 +++----
 .../buddy/tracker/BuddyPluginTrackerListener.java  |    71 +-
 .../plugins/net/netstatus/NetStatusPlugin.java     |   524 +-
 .../net/netstatus/NetStatusProtocolTester.java     |  1296 +-
 .../net/netstatus/NetStatusProtocolTesterBT.java   |  1965 +--
 .../netstatus/NetStatusProtocolTesterListener.java |    94 +-
 .../net/netstatus/swt/NetStatusPluginTester.java   |  2028 +--
 .../net/netstatus/swt/NetStatusPluginView.java     |  1168 +-
 .../removerules/DownloadRemoveRulesPlugin.java     |     5 +-
 .../plugins/sharing/hoster/ShareHosterPlugin.java  |   120 +-
 .../startstoprules/always/RunEverythingPlugin.java |     5 +-
 .../defaultplugin/DefaultRankCalculator.java       |   386 +-
 .../DownloadingRankColumnListener.java             |     8 +-
 .../defaultplugin/SeedingRankColumnListener.java   |     8 +-
 .../defaultplugin/StartStopRulesDefaultPlugin.java |    88 +-
 .../defaultplugin/StartStopRulesFPListener.java    |     5 +-
 .../ui/swt/ConfigSectionDownloading.java           |    11 +-
 .../defaultplugin/ui/swt/ConfigSectionQueue.java   |     8 +-
 .../defaultplugin/ui/swt/ConfigSectionSeeding.java |    60 +-
 .../ui/swt/ConfigSectionSeedingAutoStarting.java   |     8 +-
 .../ui/swt/ConfigSectionSeedingFirstPriority.java  |     8 +-
 .../ui/swt/ConfigSectionSeedingIgnore.java         |     8 +-
 .../ui/swt/StartStopRulesDefaultPluginSWTUI.java   |     5 +-
 .../plugins/tracker/dht/DHTTrackerPlugin.java      |   408 +-
 .../plugins/tracker/dht/DHTTrackerPluginAlt.java   |   914 ++
 .../plugins/tracker/local/LocalTrackerPlugin.java  |     7 +-
 .../aelitis/azureus/plugins/upnp/UPnPMapping.java  |     5 +-
 .../azureus/plugins/upnp/UPnPMappingListener.java  |     5 +-
 .../azureus/plugins/upnp/UPnPMappingManager.java   |     5 +-
 .../plugins/upnp/UPnPMappingManagerListener.java   |     5 +-
 .../aelitis/azureus/plugins/upnp/UPnPPlugin.java   |     5 +-
 .../azureus/plugins/upnp/UPnPPluginService.java    |     5 +-
 .../src/com/aelitis/azureus/ui/IUIIntializer.java  |     5 +-
 .../aelitis/azureus/ui/InitializerListener.java    |     5 +-
 azureus2/src/com/aelitis/azureus/ui/Main.java      |     5 +-
 .../src/com/aelitis/azureus/ui/UIFunctions.java    |    56 +-
 .../com/aelitis/azureus/ui/UIFunctionsManager.java |     5 +-
 .../azureus/ui/UIFunctionsUserPrompter.java        |    11 +-
 .../azureus/ui/UIStatusTextClickListener.java      |     5 +-
 .../azureus/ui/UserPrompterResultListener.java     |    18 +
 .../ui/common/RememberedDecisionsManager.java      |     5 +-
 .../aelitis/azureus/ui/common/ToolBarEnabler.java  |    14 -
 .../com/aelitis/azureus/ui/common/ToolBarItem.java |    33 +-
 .../azureus/ui/common/table/TableCellCore.java     |     8 +-
 .../azureus/ui/common/table/TableColumnCore.java   |     8 +-
 .../table/TableColumnCoreCreationListener.java     |     6 +-
 .../ui/common/table/TableColumnSortObject.java     |     6 +-
 .../ui/common/table/TableCountChangeAdapter.java   |     5 +-
 .../ui/common/table/TableCountChangeListener.java  |     5 +-
 .../table/TableDataSourceChangedListener.java      |     5 +-
 .../common/table/TableExpansionChangeListener.java |     5 +-
 .../ui/common/table/TableGroupRowRunner.java       |    18 +
 .../table/TableGroupRowVisibilityRunner.java       |     5 +-
 .../ui/common/table/TableLifeCycleListener.java    |     5 +-
 .../ui/common/table/TableRefreshListener.java      |    18 +
 .../azureus/ui/common/table/TableRowCore.java      |     8 +-
 .../ui/common/table/TableSelectionAdapter.java     |     5 +-
 .../ui/common/table/TableSelectionListener.java    |     5 +-
 .../table/TableStructureEventDispatcher.java       |    27 +-
 .../table/TableStructureModificationListener.java  |    11 +-
 .../aelitis/azureus/ui/common/table/TableView.java |     5 +-
 .../ui/common/table/TableViewFilterCheck.java      |     6 +-
 .../ui/common/table/impl/CoreTableColumn.java      |     8 +-
 .../common/table/impl/DataSourceCallBackUtil.java  |    18 +
 .../ui/common/table/impl/TableColumnImpl.java      |    61 +-
 .../ui/common/table/impl/TableColumnInfoImpl.java  |     6 +-
 .../ui/common/table/impl/TableColumnManager.java   |    90 +-
 .../ui/common/table/impl/TableRowCoreSorter.java   |    18 +
 .../ui/common/table/impl/TableViewImpl.java        |   229 +-
 .../azureus/ui/common/updater/UIUpdatable.java     |     5 +-
 .../ui/common/updater/UIUpdatableAlways.java       |     7 +-
 .../azureus/ui/common/updater/UIUpdater.java       |     5 +-
 .../ui/common/viewtitleinfo/ViewTitleInfo.java     |     6 +-
 .../ui/common/viewtitleinfo/ViewTitleInfo2.java    |     6 +-
 .../viewtitleinfo/ViewTitleInfoListener.java       |     6 +-
 .../common/viewtitleinfo/ViewTitleInfoManager.java |     6 +-
 .../aelitis/azureus/ui/console/MakeTorrent.java    |     8 +-
 .../azureus/ui/mdi/MdiChildCloseListener.java      |     6 +-
 .../aelitis/azureus/ui/mdi/MdiCloseListener.java   |     6 +-
 .../src/com/aelitis/azureus/ui/mdi/MdiEntry.java   |    18 +-
 .../azureus/ui/mdi/MdiEntryCreationListener.java   |    18 +
 .../azureus/ui/mdi/MdiEntryCreationListener2.java  |     6 +-
 .../azureus/ui/mdi/MdiEntryDatasourceListener.java |     4 +-
 .../azureus/ui/mdi/MdiEntryDropListener.java       |     6 +-
 .../azureus/ui/mdi/MdiEntryLoadedListener.java     |     6 +-
 .../azureus/ui/mdi/MdiEntryLogIdListener.java      |     6 +-
 .../azureus/ui/mdi/MdiEntryOpenListener.java       |     6 +-
 .../azureus/ui/mdi/MdiEntryVitalityImage.java      |     6 +-
 .../ui/mdi/MdiEntryVitalityImageListener.java      |     6 +-
 .../com/aelitis/azureus/ui/mdi/MdiListener.java    |     6 +-
 .../azureus/ui/mdi/MultipleDocumentInterface.java  |    61 +-
 .../ui/selectedcontent/DownloadUrlInfo.java        |     6 +-
 .../ui/selectedcontent/ISelectedContent.java       |     6 +-
 .../selectedcontent/ISelectedVuzeFileContent.java  |    63 +-
 .../ui/selectedcontent/SelectedContent.java        |     6 +-
 .../selectedcontent/SelectedContentListener.java   |     6 +-
 .../ui/selectedcontent/SelectedContentManager.java |    10 +-
 .../aelitis/azureus/ui/skin/SkinProperties.java    |     5 +-
 .../azureus/ui/skin/SkinPropertiesImpl.java        |     5 +-
 .../azureus/ui/swt/UIFunctionsManagerSWT.java      |     5 +-
 .../com/aelitis/azureus/ui/swt/UIFunctionsSWT.java |    34 +-
 .../azureus/ui/swt/UISkinnableManagerSWT.java      |     5 +-
 .../azureus/ui/swt/UISkinnableSWTListener.java     |     5 +-
 .../azureus/ui/swt/imageloader/ImageLoader.java    |    10 +-
 .../ui/swt/imageloader/ImageLoaderRefInfo.java     |     5 +-
 .../aelitis/azureus/ui/swt/mdi/MdiEntrySWT.java    |    24 +-
 .../azureus/ui/swt/mdi/MdiSWTMenuHackListener.java |     6 +-
 .../ui/swt/mdi/MultipleDocumentInterfaceSWT.java   |    46 +-
 .../azureus/ui/swt/mdi/TabbedMdiInterface.java     |    47 +
 .../ui/swt/mdi/TabbedMdiMaximizeListener.java      |    24 +
 .../azureus/ui/swt/uiupdater/UIUpdaterSWT.java     |    52 +-
 .../aelitis/azureus/ui/swt/utils/ColorCache.java   |     5 +-
 .../aelitis/azureus/ui/swt/utils/ColorCache2.java  |    17 +-
 .../aelitis/azureus/ui/swt/utils/FontUtils.java    |     5 +-
 .../azureus/ui/swt/utils/UIMagnetHandler.java      |     6 +-
 .../azureus/ui/utils/ImageBytesDownloader.java     |     6 +-
 .../src/com/aelitis/azureus/util/JSONUtils.java    |     5 +-
 .../src/com/aelitis/azureus/util/MapUtils.java     |    22 +-
 .../aelitis/net/magneturi/MagnetURIHandler.java    |     5 +-
 .../net/magneturi/MagnetURIHandlerException.java   |     5 +-
 .../net/magneturi/MagnetURIHandlerListener.java    |     5 +-
 .../MagnetURIHandlerProgressListener.java          |     5 +-
 .../net/magneturi/impl/MagnetURIHandlerClient.java |     5 +-
 .../net/magneturi/impl/MagnetURIHandlerImpl.java   |   249 +-
 .../aelitis/net/natpmp/NATPMPDeviceAdapter.java    |     5 +-
 .../src/com/aelitis/net/natpmp/NatPMPDevice.java   |     5 +-
 .../aelitis/net/natpmp/NatPMPDeviceFactory.java    |     5 +-
 .../aelitis/net/natpmp/impl/NatPMPDeviceImpl.java  |     5 +-
 .../com/aelitis/net/natpmp/upnp/NatPMPUPnP.java    |     5 +-
 .../aelitis/net/natpmp/upnp/NatPMPUPnPFactory.java |     5 +-
 .../aelitis/net/natpmp/upnp/impl/NatPMPImpl.java   |     5 +-
 .../net/natpmp/upnp/impl/NatPMPUPnPImpl.java       |     5 +-
 .../natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java |     5 +-
 azureus2/src/com/aelitis/net/udp/mc/MCGroup.java   |     5 +-
 .../src/com/aelitis/net/udp/mc/MCGroupAdapter.java |     5 +-
 .../com/aelitis/net/udp/mc/MCGroupException.java   |     5 +-
 .../src/com/aelitis/net/udp/mc/MCGroupFactory.java |     5 +-
 .../com/aelitis/net/udp/mc/impl/MCGroupImpl.java   |     5 +-
 .../src/com/aelitis/net/udp/uc/PRUDPPacket.java    |     3 +-
 .../com/aelitis/net/udp/uc/PRUDPPacketHandler.java |     3 +-
 .../net/udp/uc/PRUDPPacketHandlerException.java    |     3 +-
 .../net/udp/uc/PRUDPPacketHandlerFactory.java      |     3 +-
 .../net/udp/uc/PRUDPPacketHandlerRequest.java      |     5 +-
 .../net/udp/uc/PRUDPPacketHandlerStats.java        |     5 +-
 .../aelitis/net/udp/uc/PRUDPPacketReceiver.java    |     5 +-
 .../com/aelitis/net/udp/uc/PRUDPPacketReply.java   |     3 +-
 .../net/udp/uc/PRUDPPacketReplyDecoder.java        |     5 +-
 .../com/aelitis/net/udp/uc/PRUDPPacketRequest.java |     3 +-
 .../net/udp/uc/PRUDPPacketRequestDecoder.java      |     5 +-
 .../aelitis/net/udp/uc/PRUDPPrimordialHandler.java |     5 +-
 .../net/udp/uc/PRUDPReleasablePacketHandler.java   |     5 +-
 .../aelitis/net/udp/uc/PRUDPRequestHandler.java    |     5 +-
 .../udp/uc/impl/PRUDPPacketHandlerFactoryImpl.java |     3 +-
 .../net/udp/uc/impl/PRUDPPacketHandlerImpl.java    |     3 +-
 .../udp/uc/impl/PRUDPPacketHandlerRequestImpl.java |     3 +-
 .../net/udp/uc/impl/PRUDPPacketHandlerSocks.java   |    22 +-
 .../udp/uc/impl/PRUDPPacketHandlerStatsImpl.java   |     5 +-
 azureus2/src/com/aelitis/net/upnp/UPnP.java        |     5 +-
 azureus2/src/com/aelitis/net/upnp/UPnPAction.java  |     5 +-
 .../com/aelitis/net/upnp/UPnPActionArgument.java   |     5 +-
 .../com/aelitis/net/upnp/UPnPActionInvocation.java |     5 +-
 azureus2/src/com/aelitis/net/upnp/UPnPAdapter.java |     5 +-
 azureus2/src/com/aelitis/net/upnp/UPnPDevice.java  |     5 +-
 .../src/com/aelitis/net/upnp/UPnPDeviceImage.java  |    18 +
 .../src/com/aelitis/net/upnp/UPnPException.java    |    46 +-
 azureus2/src/com/aelitis/net/upnp/UPnPFactory.java |     5 +-
 .../src/com/aelitis/net/upnp/UPnPListener.java     |     5 +-
 .../src/com/aelitis/net/upnp/UPnPLogListener.java  |     5 +-
 .../src/com/aelitis/net/upnp/UPnPRootDevice.java   |     5 +-
 .../aelitis/net/upnp/UPnPRootDeviceListener.java   |     5 +-
 azureus2/src/com/aelitis/net/upnp/UPnPSSDP.java    |     5 +-
 .../src/com/aelitis/net/upnp/UPnPSSDPAdapter.java  |     5 +-
 .../src/com/aelitis/net/upnp/UPnPSSDPListener.java |     5 +-
 azureus2/src/com/aelitis/net/upnp/UPnPService.java |     5 +-
 .../com/aelitis/net/upnp/UPnPStateVariable.java    |     5 +-
 .../src/com/aelitis/net/upnp/impl/SSDPIGD.java     |     5 +-
 .../com/aelitis/net/upnp/impl/SSDPIGDFactory.java  |     5 +-
 .../com/aelitis/net/upnp/impl/SSDPIGDListener.java |     5 +-
 .../src/com/aelitis/net/upnp/impl/UPnPImpl.java    |     9 +-
 .../net/upnp/impl/device/UPnPDeviceImageImpl.java  |    18 +
 .../net/upnp/impl/device/UPnPDeviceImpl.java       |    30 +-
 .../net/upnp/impl/device/UPnPRootDeviceImpl.java   |    14 +-
 .../upnp/impl/services/UPnPActionArgumentImpl.java |     5 +-
 .../net/upnp/impl/services/UPnPActionImpl.java     |     5 +-
 .../impl/services/UPnPActionInvocationImpl.java    |    58 +-
 .../impl/services/UPnPSSOfflineDownloaderImpl.java |     5 +-
 .../UPnPSSWANCommonInterfaceConfigImpl.java        |     5 +-
 .../impl/services/UPnPSSWANConnectionImpl.java     |     5 +-
 .../impl/services/UPnPSSWANIPConnectionImpl.java   |     5 +-
 .../impl/services/UPnPSSWANPPPConnectionImpl.java  |     5 +-
 .../net/upnp/impl/services/UPnPServiceImpl.java    |     5 +-
 .../upnp/impl/services/UPnPStateVariableImpl.java  |     5 +-
 .../com/aelitis/net/upnp/impl/ssdp/SSDPCore.java   |     5 +-
 .../aelitis/net/upnp/impl/ssdp/SSDPIGDImpl.java    |     5 +-
 .../net/upnp/services/UPnPOfflineDownloader.java   |     5 +-
 .../net/upnp/services/UPnPSpecificService.java     |     5 +-
 .../services/UPnPWANCommonInterfaceConfig.java     |     5 +-
 .../net/upnp/services/UPnPWANConnection.java       |     5 +-
 .../upnp/services/UPnPWANConnectionListener.java   |     5 +-
 .../services/UPnPWANConnectionPortMapping.java     |     5 +-
 .../net/upnp/services/UPnPWANIPConnection.java     |     5 +-
 .../net/upnp/services/UPnPWANPPPConnection.java    |     5 +-
 .../src/com/aelitis/net/upnpms/UPNPMSBrowser.java  |    17 +-
 .../aelitis/net/upnpms/UPNPMSBrowserFactory.java   |    17 +-
 .../aelitis/net/upnpms/UPNPMSBrowserListener.java  |    15 +-
 .../com/aelitis/net/upnpms/UPNPMSContainer.java    |    17 +-
 .../src/com/aelitis/net/upnpms/UPNPMSItem.java     |    17 +-
 .../src/com/aelitis/net/upnpms/UPNPMSNode.java     |    15 +-
 .../com/aelitis/net/upnpms/UPnPMSException.java    |     5 +-
 azureus2/src/com/aelitis/net/upnpms/impl/Test.java |    17 +-
 .../aelitis/net/upnpms/impl/UPNPMSBrowserImpl.java |    19 +-
 .../net/upnpms/impl/UPNPMSContainerImpl.java       |    17 +-
 .../aelitis/net/upnpms/impl/UPNPMSItemImpl.java    |    17 +-
 .../src/org/apache/commons/lang/Entities.java      |     0
 .../src/org/apache/commons/lang/IntHashMap.java    |     0
 azureus2/src/org/bouncycastle/LICENSE.java         |    63 -
 azureus2/src/org/bouncycastle/asn1/ASN1Choice.java |    14 -
 .../src/org/bouncycastle/asn1/ASN1Encodable.java   |    86 -
 .../org/bouncycastle/asn1/ASN1EncodableVector.java |    14 -
 .../src/org/bouncycastle/asn1/ASN1Generator.java   |    15 -
 .../src/org/bouncycastle/asn1/ASN1InputStream.java |   481 -
 azureus2/src/org/bouncycastle/asn1/ASN1Null.java   |    38 -
 azureus2/src/org/bouncycastle/asn1/ASN1Object.java |    38 -
 .../org/bouncycastle/asn1/ASN1ObjectParser.java    |    64 -
 .../src/org/bouncycastle/asn1/ASN1OctetString.java |   161 -
 .../bouncycastle/asn1/ASN1OctetStringParser.java   |     9 -
 .../org/bouncycastle/asn1/ASN1OutputStream.java    |    36 -
 .../src/org/bouncycastle/asn1/ASN1Sequence.java    |   218 -
 .../org/bouncycastle/asn1/ASN1SequenceParser.java  |    10 -
 azureus2/src/org/bouncycastle/asn1/ASN1Set.java    |   339 -
 .../src/org/bouncycastle/asn1/ASN1SetParser.java   |    10 -
 .../org/bouncycastle/asn1/ASN1StreamParser.java    |   222 -
 .../org/bouncycastle/asn1/ASN1TaggedObject.java    |   205 -
 .../bouncycastle/asn1/ASN1TaggedObjectParser.java  |    12 -
 .../asn1/BERConstructedOctetString.java            |   171 -
 .../bouncycastle/asn1/BERConstructedSequence.java  |    37 -
 .../src/org/bouncycastle/asn1/BERGenerator.java    |   100 -
 .../src/org/bouncycastle/asn1/BERInputStream.java  |   209 -
 azureus2/src/org/bouncycastle/asn1/BERNull.java    |    30 -
 .../bouncycastle/asn1/BEROctetStringGenerator.java |   100 -
 .../bouncycastle/asn1/BEROctetStringParser.java    |    43 -
 .../src/org/bouncycastle/asn1/BEROutputStream.java |    36 -
 .../src/org/bouncycastle/asn1/BERSequence.java     |    59 -
 .../bouncycastle/asn1/BERSequenceGenerator.java    |    41 -
 .../org/bouncycastle/asn1/BERSequenceParser.java   |    25 -
 azureus2/src/org/bouncycastle/asn1/BERSet.java     |    69 -
 .../src/org/bouncycastle/asn1/BERSetParser.java    |    25 -
 .../src/org/bouncycastle/asn1/BERTaggedObject.java |   119 -
 .../bouncycastle/asn1/BERTaggedObjectParser.java   |   154 -
 .../bouncycastle/asn1/ConstructedOctetStream.java  |   111 -
 .../bouncycastle/asn1/DERApplicationSpecific.java  |   170 -
 .../src/org/bouncycastle/asn1/DERBMPString.java    |   126 -
 .../src/org/bouncycastle/asn1/DERBitString.java    |   289 -
 azureus2/src/org/bouncycastle/asn1/DERBoolean.java |   113 -
 .../bouncycastle/asn1/DERConstructedSequence.java  |    53 -
 .../org/bouncycastle/asn1/DERConstructedSet.java   |    79 -
 .../src/org/bouncycastle/asn1/DEREncodable.java    |     6 -
 .../org/bouncycastle/asn1/DEREncodableVector.java  |    38 -
 .../src/org/bouncycastle/asn1/DEREnumerated.java   |   113 -
 .../org/bouncycastle/asn1/DERGeneralString.java    |    92 -
 .../org/bouncycastle/asn1/DERGeneralizedTime.java  |   294 -
 .../src/org/bouncycastle/asn1/DERGenerator.java    |   130 -
 .../src/org/bouncycastle/asn1/DERIA5String.java    |   170 -
 .../src/org/bouncycastle/asn1/DERInputStream.java  |   272 -
 azureus2/src/org/bouncycastle/asn1/DERInteger.java |   134 -
 azureus2/src/org/bouncycastle/asn1/DERNull.java    |    25 -
 .../org/bouncycastle/asn1/DERNumericString.java    |   177 -
 azureus2/src/org/bouncycastle/asn1/DERObject.java  |    20 -
 .../org/bouncycastle/asn1/DERObjectIdentifier.java |   293 -
 .../src/org/bouncycastle/asn1/DEROctetString.java  |    29 -
 .../src/org/bouncycastle/asn1/DEROutputStream.java |    93 -
 .../org/bouncycastle/asn1/DERPrintableString.java  |   204 -
 .../src/org/bouncycastle/asn1/DERSequence.java     |    79 -
 .../bouncycastle/asn1/DERSequenceGenerator.java    |    45 -
 azureus2/src/org/bouncycastle/asn1/DERSet.java     |    99 -
 azureus2/src/org/bouncycastle/asn1/DERString.java  |     9 -
 .../src/org/bouncycastle/asn1/DERT61String.java    |   126 -
 .../src/org/bouncycastle/asn1/DERTaggedObject.java |    88 -
 azureus2/src/org/bouncycastle/asn1/DERTags.java    |    36 -
 azureus2/src/org/bouncycastle/asn1/DERUTCTime.java |   254 -
 .../src/org/bouncycastle/asn1/DERUTF8String.java   |   109 -
 .../org/bouncycastle/asn1/DERUniversalString.java  |   120 -
 .../src/org/bouncycastle/asn1/DERUnknownTag.java   |    86 -
 .../org/bouncycastle/asn1/DERVisibleString.java    |   126 -
 .../asn1/DefiniteLengthInputStream.java            |    95 -
 .../asn1/IndefiniteLengthInputStream.java          |   111 -
 .../org/bouncycastle/asn1/LimitedInputStream.java  |    28 -
 .../src/org/bouncycastle/asn1/OIDTokenizer.java    |    48 -
 .../asn1/cms/CMSObjectIdentifiers.java             |    15 -
 .../src/org/bouncycastle/asn1/cms/ContentInfo.java |    90 -
 .../bouncycastle/asn1/misc/CAST5CBCParameters.java |    71 -
 .../src/org/bouncycastle/asn1/misc/IDEACBCPar.java |    75 -
 .../asn1/misc/MiscObjectIdentifiers.java           |    30 -
 .../bouncycastle/asn1/misc/NetscapeCertType.java   |    54 -
 .../asn1/misc/NetscapeRevocationURL.java           |    18 -
 .../asn1/misc/VerisignCzagExtension.java           |    18 -
 .../src/org/bouncycastle/asn1/misc/package.html    |     5 -
 azureus2/src/org/bouncycastle/asn1/package.html    |     5 -
 .../src/org/bouncycastle/asn1/pkcs/Attribute.java  |    82 -
 .../bouncycastle/asn1/pkcs/AuthenticatedSafe.java  |    47 -
 .../src/org/bouncycastle/asn1/pkcs/CertBag.java    |    53 -
 .../asn1/pkcs/CertificationRequest.java            |    76 -
 .../asn1/pkcs/CertificationRequestInfo.java        |   129 -
 .../org/bouncycastle/asn1/pkcs/ContentInfo.java    |    88 -
 .../org/bouncycastle/asn1/pkcs/DHParameter.java    |    88 -
 .../org/bouncycastle/asn1/pkcs/EncryptedData.java  |   104 -
 .../asn1/pkcs/EncryptedPrivateKeyInfo.java         |    71 -
 .../bouncycastle/asn1/pkcs/EncryptionScheme.java   |    38 -
 .../asn1/pkcs/IssuerAndSerialNumber.java           |    76 -
 .../bouncycastle/asn1/pkcs/KeyDerivationFunc.java  |    14 -
 .../src/org/bouncycastle/asn1/pkcs/MacData.java    |    89 -
 .../bouncycastle/asn1/pkcs/PBES2Algorithms.java    |    77 -
 .../bouncycastle/asn1/pkcs/PBES2Parameters.java    |    54 -
 .../org/bouncycastle/asn1/pkcs/PBKDF2Params.java   |    86 -
 .../bouncycastle/asn1/pkcs/PKCS12PBEParams.java    |    69 -
 .../asn1/pkcs/PKCSObjectIdentifiers.java           |   142 -
 azureus2/src/org/bouncycastle/asn1/pkcs/Pfx.java   |    70 -
 .../org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java |   144 -
 .../bouncycastle/asn1/pkcs/RC2CBCParameter.java    |    89 -
 .../asn1/pkcs/RSAPrivateKeyStructure.java          |   186 -
 .../src/org/bouncycastle/asn1/pkcs/SafeBag.java    |    78 -
 .../src/org/bouncycastle/asn1/pkcs/SignedData.java |   165 -
 .../src/org/bouncycastle/asn1/pkcs/SignerInfo.java |   168 -
 .../src/org/bouncycastle/asn1/pkcs/package.html    |     5 -
 .../asn1/sec/ECPrivateKeyStructure.java            |   102 -
 .../src/org/bouncycastle/asn1/sec/package.html     |     5 -
 .../asn1/teletrust/TeleTrusTObjectIdentifiers.java |    18 -
 .../src/org/bouncycastle/asn1/util/ASN1Dump.java   |   274 -
 .../src/org/bouncycastle/asn1/util/DERDump.java    |    33 -
 azureus2/src/org/bouncycastle/asn1/util/Dump.java  |    22 -
 .../src/org/bouncycastle/asn1/util/package.html    |     5 -
 .../bouncycastle/asn1/x509/AccessDescription.java  |    98 -
 .../asn1/x509/AlgorithmIdentifier.java             |   126 -
 .../org/bouncycastle/asn1/x509/AttCertIssuer.java  |    90 -
 .../asn1/x509/AttCertValidityPeriod.java           |    84 -
 .../src/org/bouncycastle/asn1/x509/Attribute.java  |    87 -
 .../asn1/x509/AttributeCertificate.java            |    94 -
 .../asn1/x509/AttributeCertificateInfo.java        |   165 -
 .../asn1/x509/AuthorityInformationAccess.java      |   101 -
 .../asn1/x509/AuthorityKeyIdentifier.java          |   231 -
 .../bouncycastle/asn1/x509/BasicConstraints.java   |   181 -
 .../org/bouncycastle/asn1/x509/CRLDistPoint.java   |   100 -
 .../src/org/bouncycastle/asn1/x509/CRLNumber.java  |    32 -
 .../src/org/bouncycastle/asn1/x509/CRLReason.java  |   111 -
 .../org/bouncycastle/asn1/x509/CertPolicyId.java   |    20 -
 .../bouncycastle/asn1/x509/CertificateList.java    |   119 -
 .../bouncycastle/asn1/x509/CertificatePair.java    |   169 -
 .../asn1/x509/CertificatePolicies.java             |   147 -
 .../org/bouncycastle/asn1/x509/DSAParameter.java   |    92 -
 .../src/org/bouncycastle/asn1/x509/DigestInfo.java |    86 -
 .../org/bouncycastle/asn1/x509/DisplayText.java    |   165 -
 .../bouncycastle/asn1/x509/DistributionPoint.java  |   158 -
 .../asn1/x509/DistributionPointName.java           |   143 -
 .../bouncycastle/asn1/x509/ExtendedKeyUsage.java   |   128 -
 .../org/bouncycastle/asn1/x509/GeneralName.java    |   258 -
 .../org/bouncycastle/asn1/x509/GeneralNames.java   |    94 -
 .../org/bouncycastle/asn1/x509/GeneralSubtree.java |   200 -
 .../src/org/bouncycastle/asn1/x509/Holder.java     |   242 -
 .../org/bouncycastle/asn1/x509/IetfAttrSyntax.java |   174 -
 .../org/bouncycastle/asn1/x509/IssuerSerial.java   |   106 -
 .../asn1/x509/IssuingDistributionPoint.java        |   256 -
 .../org/bouncycastle/asn1/x509/KeyPurposeId.java   |    37 -
 .../src/org/bouncycastle/asn1/x509/KeyUsage.java   |    77 -
 .../bouncycastle/asn1/x509/NameConstraints.java    |   104 -
 .../bouncycastle/asn1/x509/NoticeReference.java    |   155 -
 .../bouncycastle/asn1/x509/ObjectDigestInfo.java   |   192 -
 .../bouncycastle/asn1/x509/PolicyInformation.java  |    87 -
 .../org/bouncycastle/asn1/x509/PolicyMappings.java |    68 -
 .../bouncycastle/asn1/x509/PolicyQualifierId.java  |    31 -
 .../asn1/x509/PolicyQualifierInfo.java             |   114 -
 .../asn1/x509/PrivateKeyUsagePeriod.java           |    89 -
 .../asn1/x509/RSAPublicKeyStructure.java           |    95 -
 .../org/bouncycastle/asn1/x509/ReasonFlags.java    |    85 -
 .../src/org/bouncycastle/asn1/x509/RoleSyntax.java |   236 -
 .../asn1/x509/SubjectDirectoryAttributes.java      |   144 -
 .../asn1/x509/SubjectKeyIdentifier.java            |    95 -
 .../asn1/x509/SubjectPublicKeyInfo.java            |   126 -
 .../org/bouncycastle/asn1/x509/TBSCertList.java    |   212 -
 .../asn1/x509/TBSCertificateStructure.java         |   193 -
 .../src/org/bouncycastle/asn1/x509/Target.java     |   138 -
 .../bouncycastle/asn1/x509/TargetInformation.java  |   121 -
 .../src/org/bouncycastle/asn1/x509/Targets.java    |   122 -
 azureus2/src/org/bouncycastle/asn1/x509/Time.java  |   133 -
 .../src/org/bouncycastle/asn1/x509/UserNotice.java |   117 -
 .../asn1/x509/V1TBSCertificateGenerator.java       |   125 -
 .../x509/V2AttributeCertificateInfoGenerator.java  |   148 -
 .../src/org/bouncycastle/asn1/x509/V2Form.java     |   130 -
 .../asn1/x509/V2TBSCertListGenerator.java          |   213 -
 .../asn1/x509/V3TBSCertificateGenerator.java       |   158 -
 .../org/bouncycastle/asn1/x509/X509Attributes.java |     8 -
 .../asn1/x509/X509CertificateStructure.java        |   127 -
 .../asn1/x509/X509DefaultEntryConverter.java       |    57 -
 .../org/bouncycastle/asn1/x509/X509Extension.java  |    87 -
 .../org/bouncycastle/asn1/x509/X509Extensions.java |   393 -
 .../asn1/x509/X509ExtensionsGenerator.java         |    99 -
 .../src/org/bouncycastle/asn1/x509/X509Name.java   |  1158 --
 .../asn1/x509/X509NameEntryConverter.java          |   113 -
 .../bouncycastle/asn1/x509/X509NameTokenizer.java  |    91 -
 .../asn1/x509/X509ObjectIdentifiers.java           |    59 -
 .../src/org/bouncycastle/asn1/x509/package.html    |     5 -
 .../org/bouncycastle/asn1/x9/KeySpecificInfo.java  |    68 -
 .../src/org/bouncycastle/asn1/x9/OtherInfo.java    |    96 -
 .../org/bouncycastle/asn1/x9/X962NamedCurves.java  |   211 -
 .../org/bouncycastle/asn1/x9/X962Parameters.java   |    54 -
 azureus2/src/org/bouncycastle/asn1/x9/X9Curve.java |    96 -
 .../org/bouncycastle/asn1/x9/X9ECParameters.java   |   154 -
 .../src/org/bouncycastle/asn1/x9/X9ECPoint.java    |    48 -
 .../org/bouncycastle/asn1/x9/X9FieldElement.java   |    65 -
 .../src/org/bouncycastle/asn1/x9/X9FieldID.java    |    66 -
 .../bouncycastle/asn1/x9/X9IntegerConverter.java   |    47 -
 .../bouncycastle/asn1/x9/X9ObjectIdentifiers.java  |    87 -
 azureus2/src/org/bouncycastle/asn1/x9/package.html |     5 -
 .../bouncycastle/crypto/AsymmetricBlockCipher.java |    45 -
 .../crypto/AsymmetricCipherKeyPair.java            |    44 -
 .../crypto/AsymmetricCipherKeyPairGenerator.java   |    22 -
 .../org/bouncycastle/crypto/BasicAgreement.java    |    21 -
 .../src/org/bouncycastle/crypto/BlockCipher.java   |    56 -
 .../crypto/BufferedAsymmetricBlockCipher.java      |   170 -
 .../bouncycastle/crypto/BufferedBlockCipher.java   |   324 -
 .../bouncycastle/crypto/CipherKeyGenerator.java    |    38 -
 .../org/bouncycastle/crypto/CipherParameters.java  |     8 -
 .../org/bouncycastle/crypto/CryptoException.java   |    27 -
 azureus2/src/org/bouncycastle/crypto/DSA.java      |    36 -
 .../bouncycastle/crypto/DataLengthException.java   |    30 -
 .../bouncycastle/crypto/DerivationFunction.java    |    17 -
 .../bouncycastle/crypto/DerivationParameters.java  |     8 -
 azureus2/src/org/bouncycastle/crypto/Digest.java   |    51 -
 .../crypto/InvalidCipherTextException.java         |    27 -
 .../crypto/KeyGenerationParameters.java            |    48 -
 azureus2/src/org/bouncycastle/crypto/Mac.java      |    71 -
 .../crypto/PBEParametersGenerator.java             |   142 -
 .../crypto/RuntimeCryptoException.java             |    26 -
 .../org/bouncycastle/crypto/StreamBlockCipher.java |   108 -
 .../src/org/bouncycastle/crypto/StreamCipher.java  |    53 -
 azureus2/src/org/bouncycastle/crypto/Wrapper.java  |    18 -
 .../crypto/agreement/ECDHBasicAgreement.java       |    47 -
 .../crypto/agreement/srp/SRP6Client.java           |    93 -
 .../crypto/agreement/srp/SRP6Server.java           |    90 -
 .../crypto/agreement/srp/SRP6Util.java             |    91 -
 .../agreement/srp/SRP6VerifierGenerator.java       |    47 -
 .../bouncycastle/crypto/digests/GeneralDigest.java |   128 -
 .../bouncycastle/crypto/digests/LongDigest.java    |   346 -
 .../org/bouncycastle/crypto/digests/MD2Digest.java |   230 -
 .../org/bouncycastle/crypto/digests/MD4Digest.java |   270 -
 .../org/bouncycastle/crypto/digests/MD5Digest.java |   302 -
 .../crypto/digests/RIPEMD128Digest.java            |   461 -
 .../crypto/digests/RIPEMD160Digest.java            |   422 -
 .../crypto/digests/RIPEMD256Digest.java            |   476 -
 .../crypto/digests/RIPEMD320Digest.java            |   461 -
 .../bouncycastle/crypto/digests/SHA1Digest.java    |   258 -
 .../bouncycastle/crypto/digests/SHA256Digest.java  |   268 -
 .../bouncycastle/crypto/digests/SHA384Digest.java  |    86 -
 .../bouncycastle/crypto/digests/SHA512Digest.java  |    88 -
 .../bouncycastle/crypto/digests/TigerDigest.java   |   859 --
 .../crypto/encodings/ISO9796d1Encoding.java        |   251 -
 .../crypto/encodings/OAEPEncoding.java             |   342 -
 .../crypto/encodings/PKCS1Encoding.java            |   194 -
 .../org/bouncycastle/crypto/encodings/package.html |     5 -
 .../org/bouncycastle/crypto/engines/IESEngine.java |   245 -
 .../org/bouncycastle/crypto/engines/RC4Engine.java |   156 -
 .../org/bouncycastle/crypto/engines/RSAEngine.java |   188 -
 .../crypto/generators/BaseKDFBytesGenerator.java   |   142 -
 .../crypto/generators/DESKeyGenerator.java         |    23 -
 .../crypto/generators/DESedeKeyGenerator.java      |    55 -
 .../crypto/generators/DHBasicKeyPairGenerator.java |    53 -
 .../crypto/generators/DHKeyPairGenerator.java      |    53 -
 .../crypto/generators/DHParametersGenerator.java   |    74 -
 .../crypto/generators/DSAKeyPairGenerator.java     |    58 -
 .../crypto/generators/DSAParametersGenerator.java  |   178 -
 .../crypto/generators/ECKeyPairGenerator.java      |    53 -
 .../crypto/generators/ElGamalKeyPairGenerator.java |    53 -
 .../generators/ElGamalParametersGenerator.java     |    85 -
 .../crypto/generators/KDF2BytesGenerator.java      |    24 -
 .../crypto/generators/MGF1BytesGenerator.java      |   107 -
 .../generators/OpenSSLPBEParametersGenerator.java  |   131 -
 .../generators/PKCS12ParametersGenerator.java      |   233 -
 .../generators/PKCS5S1ParametersGenerator.java     |   119 -
 .../crypto/generators/RSAKeyPairGenerator.java     |   141 -
 .../src/org/bouncycastle/crypto/macs/HMac.java     |   135 -
 .../bouncycastle/crypto/modes/CBCBlockCipher.java  |   233 -
 .../bouncycastle/crypto/modes/CFBBlockCipher.java  |   250 -
 .../bouncycastle/crypto/modes/CTSBlockCipher.java  |   260 -
 .../bouncycastle/crypto/modes/OFBBlockCipher.java  |   182 -
 .../crypto/modes/OpenPGPCFBBlockCipher.java        |   322 -
 .../crypto/modes/PGPCFBBlockCipher.java            |   439 -
 .../crypto/modes/PaddedBlockCipher.java            |   253 -
 .../bouncycastle/crypto/modes/SICBlockCipher.java  |   108 -
 .../src/org/bouncycastle/crypto/modes/package.html |     5 -
 .../crypto/params/AsymmetricKeyParameter.java      |    20 -
 .../bouncycastle/crypto/params/DESParameters.java  |   107 -
 .../crypto/params/DESedeParameters.java            |    57 -
 .../crypto/params/DHKeyGenerationParameters.java   |    25 -
 .../crypto/params/DHKeyParameters.java             |    35 -
 .../bouncycastle/crypto/params/DHParameters.java   |   116 -
 .../crypto/params/DHPrivateKeyParameters.java      |    41 -
 .../crypto/params/DHPublicKeyParameters.java       |    41 -
 .../crypto/params/DHValidationParameters.java      |    46 -
 .../crypto/params/DSAKeyGenerationParameters.java  |    25 -
 .../crypto/params/DSAKeyParameters.java            |    21 -
 .../bouncycastle/crypto/params/DSAParameters.java  |    69 -
 .../crypto/params/DSAPrivateKeyParameters.java     |    23 -
 .../crypto/params/DSAPublicKeyParameters.java      |    23 -
 .../crypto/params/DSAValidationParameters.java     |    56 -
 .../crypto/params/ECDomainParameters.java          |    81 -
 .../crypto/params/ECKeyGenerationParameters.java   |    25 -
 .../crypto/params/ECKeyParameters.java             |    21 -
 .../crypto/params/ECPrivateKeyParameters.java      |    22 -
 .../crypto/params/ECPublicKeyParameters.java       |    22 -
 .../params/ElGamalKeyGenerationParameters.java     |    25 -
 .../crypto/params/ElGamalKeyParameters.java        |    35 -
 .../crypto/params/ElGamalParameters.java           |    46 -
 .../crypto/params/ElGamalPrivateKeyParameters.java |    41 -
 .../crypto/params/ElGamalPublicKeyParameters.java  |    41 -
 .../bouncycastle/crypto/params/IESParameters.java  |    44 -
 .../crypto/params/IESWithCipherParameters.java     |    30 -
 .../crypto/params/ISO18033KDFParameters.java       |    23 -
 .../bouncycastle/crypto/params/KDFParameters.java  |    31 -
 .../bouncycastle/crypto/params/KeyParameter.java   |    30 -
 .../bouncycastle/crypto/params/MGFParameters.java  |    32 -
 .../crypto/params/ParametersWithIV.java            |    39 -
 .../crypto/params/ParametersWithRandom.java        |    41 -
 .../bouncycastle/crypto/params/RC2Parameters.java  |    36 -
 .../bouncycastle/crypto/params/RC5Parameters.java  |    35 -
 .../crypto/params/RSAKeyGenerationParameters.java  |    35 -
 .../crypto/params/RSAKeyParameters.java            |    31 -
 .../crypto/params/RSAPrivateCrtKeyParameters.java  |    67 -
 .../org/bouncycastle/crypto/params/package.html    |     5 -
 .../bouncycastle/crypto/signers/ECDSASigner.java   |   144 -
 .../org/bouncycastle/jce/ECNamedCurveTable.java    |    49 -
 .../jce/PKCS10CertificationRequest.java            |   311 -
 .../src/org/bouncycastle/jce/PKCS7SignedData.java  |   597 -
 .../src/org/bouncycastle/jce/PrincipalUtil.java    |    82 -
 .../src/org/bouncycastle/jce/X509KeyUsage.java     |    57 -
 .../src/org/bouncycastle/jce/X509Principal.java    |   138 -
 .../jce/X509V1CertificateGenerator.java            |   261 -
 .../org/bouncycastle/jce/X509V2CRLGenerator.java   |   323 -
 .../jce/X509V3CertificateGenerator.java            |   342 -
 .../bouncycastle/jce/interfaces/BCKeyStore.java    |    14 -
 .../src/org/bouncycastle/jce/interfaces/ECKey.java |    15 -
 .../bouncycastle/jce/interfaces/ECPrivateKey.java  |    16 -
 .../bouncycastle/jce/interfaces/ECPublicKey.java   |    17 -
 .../bouncycastle/jce/interfaces/ElGamalKey.java    |     8 -
 .../jce/interfaces/ElGamalPrivateKey.java          |    10 -
 .../jce/interfaces/ElGamalPublicKey.java           |    10 -
 .../org/bouncycastle/jce/interfaces/IESKey.java    |    22 -
 .../jce/interfaces/PKCS12BagAttributeCarrier.java  |    21 -
 .../jce/provider/BouncyCastleProvider.java         |   588 -
 .../jce/provider/CertStoreCollectionSpi.java       |   104 -
 .../src/org/bouncycastle/jce/provider/DHUtil.java  |    50 -
 .../src/org/bouncycastle/jce/provider/DSAUtil.java |    49 -
 .../src/org/bouncycastle/jce/provider/ECUtil.java  |    54 -
 .../org/bouncycastle/jce/provider/ElGamalUtil.java |    49 -
 .../jce/provider/JCEECDHKeyAgreement.java          |   173 -
 .../bouncycastle/jce/provider/JCEECPrivateKey.java |   270 -
 .../bouncycastle/jce/provider/JCEECPublicKey.java  |   273 -
 .../bouncycastle/jce/provider/JCEIESCipher.java    |   371 -
 .../bouncycastle/jce/provider/JCERSAPublicKey.java |   140 -
 .../provider/JDKAlgorithmParameterGenerator.java   |   385 -
 .../bouncycastle/jce/provider/JDKDSASigner.java    |   269 -
 .../jce/provider/JDKDigestSignature.java           |   271 -
 .../bouncycastle/jce/provider/JDKKeyFactory.java   |   348 -
 .../jce/provider/JDKKeyPairGenerator.java          |   381 -
 .../jce/provider/JDKMessageDigest.java             |   279 -
 .../jce/provider/JDKX509CertificateFactory.java    |   360 -
 .../bouncycastle/jce/provider/PKIXCertPath.java    |   222 -
 .../bouncycastle/jce/provider/PKIXPolicyNode.java  |   167 -
 .../src/org/bouncycastle/jce/provider/RSAUtil.java |    41 -
 .../jce/provider/X509CRLEntryObject.java           |   168 -
 .../bouncycastle/jce/provider/X509CRLObject.java   |   379 -
 .../jce/provider/X509CertificateObject.java        |   679 -
 .../src/org/bouncycastle/jce/spec/ECKeySpec.java   |    26 -
 .../jce/spec/ECNamedCurveParameterSpec.java        |    60 -
 .../org/bouncycastle/jce/spec/ECParameterSpec.java |    99 -
 .../bouncycastle/jce/spec/ECPrivateKeySpec.java    |    35 -
 .../org/bouncycastle/jce/spec/ECPublicKeySpec.java |    35 -
 .../jce/spec/ElGamalGenParameterSpec.java          |    28 -
 .../org/bouncycastle/jce/spec/ElGamalKeySpec.java  |    20 -
 .../jce/spec/ElGamalParameterSpec.java             |    46 -
 .../jce/spec/ElGamalPrivateKeySpec.java            |    33 -
 .../jce/spec/ElGamalPublicKeySpec.java             |    33 -
 .../src/org/bouncycastle/jce/spec/IEKeySpec.java   |    70 -
 .../bouncycastle/jce/spec/IESParameterSpec.java    |    52 -
 .../src/org/bouncycastle/math/ec/ECConstants.java  |    12 -
 azureus2/src/org/bouncycastle/math/ec/ECCurve.java |   660 -
 .../org/bouncycastle/math/ec/ECFieldElement.java   |  1194 --
 .../src/org/bouncycastle/math/ec/ECMultiplier.java |    19 -
 azureus2/src/org/bouncycastle/math/ec/ECPoint.java |   594 -
 .../org/bouncycastle/math/ec/FpNafMultiplier.java  |    39 -
 .../src/org/bouncycastle/math/ec/IntArray.java     |   518 -
 .../src/org/bouncycastle/math/ec/PreCompInfo.java  |    10 -
 .../org/bouncycastle/math/ec/SimpleBigDecimal.java |   253 -
 azureus2/src/org/bouncycastle/math/ec/Tnaf.java    |   844 --
 .../src/org/bouncycastle/math/ec/ZTauElement.java  |    37 -
 .../src/org/bouncycastle/openssl/PEMReader.java    |   543 -
 .../src/org/bouncycastle/openssl/PEMUtilities.java |   185 -
 .../src/org/bouncycastle/openssl/PEMWriter.java    |   312 -
 .../org/bouncycastle/openssl/PasswordFinder.java   |     9 -
 azureus2/src/org/bouncycastle/util/Arrays.java     |   135 -
 .../src/org/bouncycastle/util/BigIntegers.java     |    78 -
 azureus2/src/org/bouncycastle/util/IPAddress.java  |   120 -
 azureus2/src/org/bouncycastle/util/Selector.java   |     9 -
 azureus2/src/org/bouncycastle/util/Strings.java    |   241 -
 .../src/org/bouncycastle/util/encoders/Base64.java |   345 -
 .../util/encoders/BufferedDecoder.java             |    96 -
 .../util/encoders/BufferedEncoder.java             |    96 -
 .../src/org/bouncycastle/util/encoders/Hex.java    |    78 -
 .../bouncycastle/util/encoders/HexTranslator.java  |    87 -
 .../org/bouncycastle/util/encoders/Translator.java |    23 -
 .../x509/AttributeCertificateHolder.java           |   419 -
 .../x509/AttributeCertificateIssuer.java           |   206 -
 .../src/org/bouncycastle/x509/X509Attribute.java   |    78 -
 .../x509/X509AttributeCertificate.java             |   101 -
 azureus2/src/org/bouncycastle/x509/X509Util.java   |   411 -
 .../x509/X509V2AttributeCertificate.java           |   346 -
 .../org/gudy/azureus2/core3/category/Category.java |     3 +-
 .../azureus2/core3/category/CategoryListener.java  |     3 +-
 .../azureus2/core3/category/CategoryManager.java   |     3 +-
 .../core3/category/CategoryManagerListener.java    |     3 +-
 .../azureus2/core3/category/impl/CategoryImpl.java |    52 +-
 .../core3/category/impl/CategoryManagerImpl.java   |     5 +-
 .../core3/config/COConfigurationListener.java      |     3 +-
 .../core3/config/COConfigurationManager.java       |    13 +-
 .../azureus2/core3/config/ParameterListener.java   |     5 +-
 .../core3/config/PriorityParameterListener.java    |    71 +-
 .../gudy/azureus2/core3/config/StringIterator.java |     8 +-
 .../org/gudy/azureus2/core3/config/StringList.java |     8 +-
 .../core3/config/impl/ConfigurationChecker.java    |   120 +-
 .../core3/config/impl/ConfigurationDefaults.java   |    25 +-
 .../core3/config/impl/ConfigurationManager.java    |    28 +-
 .../ConfigurationParameterNotFoundException.java   |     5 +-
 .../core3/config/impl/StringIteratorImpl.java      |     8 +-
 .../azureus2/core3/config/impl/StringListImpl.java |     8 +-
 .../core3/config/impl/TransferSpeedValidator.java  |     5 +-
 .../org/gudy/azureus2/core3/disk/DiskManager.java  |     6 +-
 .../core3/disk/DiskManagerCheckRequest.java        |     5 +-
 .../disk/DiskManagerCheckRequestListener.java      |     5 +-
 .../azureus2/core3/disk/DiskManagerException.java  |     5 +-
 .../azureus2/core3/disk/DiskManagerFactory.java    |     3 +-
 .../azureus2/core3/disk/DiskManagerFileInfo.java   |     3 +-
 .../core3/disk/DiskManagerFileInfoListener.java    |     5 +-
 .../core3/disk/DiskManagerFileInfoSet.java         |     5 +-
 .../azureus2/core3/disk/DiskManagerListener.java   |     3 +-
 .../gudy/azureus2/core3/disk/DiskManagerPiece.java |     5 +-
 .../core3/disk/DiskManagerReadRequest.java         |     5 +-
 .../core3/disk/DiskManagerReadRequestListener.java |     5 +-
 .../azureus2/core3/disk/DiskManagerRequest.java    |     5 +-
 .../core3/disk/DiskManagerWriteRequest.java        |     5 +-
 .../disk/DiskManagerWriteRequestListener.java      |     5 +-
 .../disk/impl/DiskManagerAllocationScheduler.java  |     5 +-
 .../core3/disk/impl/DiskManagerFileInfoHelper.java |     5 +-
 .../core3/disk/impl/DiskManagerFileInfoImpl.java   |     3 +-
 .../disk/impl/DiskManagerFileInfoSetImpl.java      |     5 +-
 .../core3/disk/impl/DiskManagerHelper.java         |     5 +-
 .../azureus2/core3/disk/impl/DiskManagerImpl.java  |    29 +-
 .../core3/disk/impl/DiskManagerPieceImpl.java      |     5 +-
 .../disk/impl/DiskManagerRecheckInstance.java      |     5 +-
 .../disk/impl/DiskManagerRecheckScheduler.java     |     5 +-
 .../azureus2/core3/disk/impl/DiskManagerUtil.java  |    47 +-
 .../core3/disk/impl/access/DMAccessFactory.java    |     5 +-
 .../azureus2/core3/disk/impl/access/DMChecker.java |     5 +-
 .../azureus2/core3/disk/impl/access/DMReader.java  |     5 +-
 .../azureus2/core3/disk/impl/access/DMWriter.java  |     5 +-
 .../core3/disk/impl/access/impl/DMCheckerImpl.java |     5 +-
 .../core3/disk/impl/access/impl/DMReaderImpl.java  |     5 +-
 .../core3/disk/impl/access/impl/DMWriterImpl.java  |     5 +-
 .../access/impl/DiskManagerCheckRequestImpl.java   |     5 +-
 .../access/impl/DiskManagerReadRequestImpl.java    |     3 +-
 .../impl/access/impl/DiskManagerRequestImpl.java   |     5 +-
 .../access/impl/DiskManagerWriteRequestImpl.java   |     5 +-
 .../core3/disk/impl/piecemapper/DMPieceList.java   |     5 +-
 .../core3/disk/impl/piecemapper/DMPieceMap.java    |     5 +-
 .../disk/impl/piecemapper/DMPieceMapEntry.java     |     5 +-
 .../core3/disk/impl/piecemapper/DMPieceMapper.java |     5 +-
 .../impl/piecemapper/DMPieceMapperFactory.java     |     5 +-
 .../disk/impl/piecemapper/DMPieceMapperFile.java   |     5 +-
 .../disk/impl/piecemapper/impl/DMPieceMapImpl.java |     5 +-
 .../impl/piecemapper/impl/DMPieceMapSimple.java    |     5 +-
 .../disk/impl/piecemapper/impl/PieceListImpl.java  |     5 +-
 .../impl/piecemapper/impl/PieceMapEntryImpl.java   |     5 +-
 .../impl/piecemapper/impl/PieceMapperImpl.java     |     5 +-
 .../core3/disk/impl/resume/RDResumeHandler.java    |     5 +-
 .../azureus2/core3/download/DownloadManager.java   |    10 +-
 .../DownloadManagerActivationListener.java         |     5 +-
 .../download/DownloadManagerAvailability.java      |    35 +
 .../download/DownloadManagerDiskListener.java      |     5 +-
 .../core3/download/DownloadManagerException.java   |     5 +-
 .../core3/download/DownloadManagerFactory.java     |    14 +-
 .../DownloadManagerInitialisationAdapter.java      |     5 +-
 .../core3/download/DownloadManagerListener.java    |     3 +-
 .../download/DownloadManagerPeerListener.java      |     3 +-
 .../download/DownloadManagerPieceListener.java     |     3 +-
 .../core3/download/DownloadManagerState.java       |    10 +-
 .../DownloadManagerStateAttributeListener.java     |     5 +-
 .../core3/download/DownloadManagerStateEvent.java  |     5 +-
 .../download/DownloadManagerStateFactory.java      |     5 +-
 .../download/DownloadManagerStateListener.java     |     5 +-
 .../core3/download/DownloadManagerStats.java       |    28 +-
 .../core3/download/DownloadManagerTPSListener.java |    57 +-
 .../download/DownloadManagerTrackerListener.java   |     3 +-
 .../core3/download/ForceRecheckListener.java       |     5 +-
 .../download/impl/DownloadManagerAdapter.java      |     3 +-
 .../impl/DownloadManagerAvailabilityImpl.java      |   717 ++
 .../download/impl/DownloadManagerController.java   |    85 +-
 .../core3/download/impl/DownloadManagerImpl.java   |   346 +-
 .../download/impl/DownloadManagerMoveHandler.java  |     5 +-
 .../impl/DownloadManagerMoveHandlerUtils.java      |     5 +-
 .../impl/DownloadManagerRateController.java        |    17 +-
 .../download/impl/DownloadManagerStateImpl.java    |    17 +-
 .../download/impl/DownloadManagerStatsImpl.java    |   195 +-
 .../gudy/azureus2/core3/global/GlobalManager.java  |     3 +-
 .../core3/global/GlobalManagerAdapter.java         |     5 +-
 .../GlobalManagerDownloadRemovalVetoException.java |     3 +-
 ...GlobalManagerDownloadWillBeRemovedListener.java |     3 +-
 .../azureus2/core3/global/GlobalManagerEvent.java  |    17 +-
 .../core3/global/GlobalManagerEventListener.java   |    17 +-
 .../core3/global/GlobalManagerFactory.java         |     3 +-
 .../core3/global/GlobalManagerListener.java        |     3 +-
 .../azureus2/core3/global/GlobalManagerStats.java  |     6 +-
 .../core3/global/GlobalMangerProgressListener.java |     5 +-
 .../core3/global/impl/GlobalManagerFileMerger.java |  1362 ++
 .../global/impl/GlobalManagerHostSupport.java      |     5 +-
 .../core3/global/impl/GlobalManagerImpl.java       |   287 +-
 .../core3/global/impl/GlobalManagerStatsImpl.java  |    60 +-
 .../global/impl/GlobalManagerStatsWriter.java      |     5 +-
 .../org/gudy/azureus2/core3/html/HTMLChunk.java    |     5 +-
 .../gudy/azureus2/core3/html/HTMLException.java    |     5 +-
 .../src/org/gudy/azureus2/core3/html/HTMLPage.java |     5 +-
 .../gudy/azureus2/core3/html/HTMLPageFactory.java  |     5 +-
 .../org/gudy/azureus2/core3/html/HTMLUtils.java    |     5 +-
 .../azureus2/core3/html/impl/HTMLChunkImpl.java    |     5 +-
 .../azureus2/core3/html/impl/HTMLPageImpl.java     |     5 +-
 .../core3/internat/IntegratedResourceBundle.java   |     5 +-
 .../azureus2/core3/internat/LocaleTorrentUtil.java |     5 +-
 .../gudy/azureus2/core3/internat/LocaleUtil.java   |     8 +-
 .../azureus2/core3/internat/LocaleUtilDecoder.java |     5 +-
 .../core3/internat/LocaleUtilDecoderCandidate.java |     5 +-
 .../core3/internat/LocaleUtilDecoderFallback.java  |     5 +-
 .../core3/internat/LocaleUtilDecoderReal.java      |     5 +-
 .../internat/LocaleUtilEncodingException.java      |     5 +-
 .../core3/internat/LocaleUtilListener.java         |     5 +-
 .../gudy/azureus2/core3/internat/MessageText.java  |     5 +-
 .../ipchecker/extipchecker/ExternalIPChecker.java  |     3 +-
 .../extipchecker/ExternalIPCheckerFactory.java     |     3 +-
 .../extipchecker/ExternalIPCheckerService.java     |     3 +-
 .../ExternalIPCheckerServiceListener.java          |     3 +-
 .../extipchecker/impl/ExternalIPCheckerImpl.java   |     3 +-
 .../impl/ExternalIPCheckerServiceDiscoveryVIP.java |     3 +-
 .../impl/ExternalIPCheckerServiceDynDNS.java       |     3 +-
 .../impl/ExternalIPCheckerServiceImpl.java         |     3 +-
 .../impl/ExternalIPCheckerServiceNoLookup.java     |     3 +-
 .../impl/ExternalIPCheckerServiceSimple.java       |     3 +-
 .../core3/ipchecker/natchecker/NatChecker.java     |     3 +-
 .../ipchecker/natchecker/NatCheckerServer.java     |     3 +-
 .../org/gudy/azureus2/core3/ipfilter/BadIp.java    |     5 +-
 .../org/gudy/azureus2/core3/ipfilter/BadIps.java   |     3 +-
 .../org/gudy/azureus2/core3/ipfilter/BannedIp.java |     5 +-
 .../gudy/azureus2/core3/ipfilter/BlockedIp.java    |     3 +-
 .../azureus2/core3/ipfilter/IPFilterListener.java  |     5 +-
 .../org/gudy/azureus2/core3/ipfilter/IpFilter.java |     3 +-
 .../azureus2/core3/ipfilter/IpFilterManager.java   |     5 +-
 .../core3/ipfilter/IpFilterManagerFactory.java     |     5 +-
 .../org/gudy/azureus2/core3/ipfilter/IpRange.java  |     3 +-
 .../azureus2/core3/ipfilter/impl/BadIpImpl.java    |     5 +-
 .../azureus2/core3/ipfilter/impl/BadIpsImpl.java   |     3 +-
 .../azureus2/core3/ipfilter/impl/BannedIpImpl.java |     5 +-
 .../core3/ipfilter/impl/BlockedIpImpl.java         |     3 +-
 .../core3/ipfilter/impl/IPAddressRangeManager.java |     5 +-
 .../ipfilter/impl/IpFilterAutoLoaderImpl.java      |     5 +-
 .../azureus2/core3/ipfilter/impl/IpFilterImpl.java |     3 +-
 .../core3/ipfilter/impl/IpFilterManagerImpl.java   |     5 +-
 .../azureus2/core3/ipfilter/impl/IpRangeImpl.java  |     3 +-
 .../impl/tests/FakeTrackerResponseGenerator.java   |     8 +-
 .../azureus2/core3/logging/ILogAlertListener.java  |     5 +-
 .../azureus2/core3/logging/ILogEventListener.java  |     5 +-
 .../org/gudy/azureus2/core3/logging/LogAlert.java  |     5 +-
 .../org/gudy/azureus2/core3/logging/LogEvent.java  |     5 +-
 .../org/gudy/azureus2/core3/logging/LogIDs.java    |     5 +-
 .../gudy/azureus2/core3/logging/LogRelation.java   |     8 +-
 .../azureus2/core3/logging/LogRelationUtils.java   |     5 +-
 .../org/gudy/azureus2/core3/logging/Logger.java    |     5 +-
 .../azureus2/core3/logging/impl/FileLogging.java   |     5 +-
 .../core3/logging/impl/FileLoggingAdapter.java     |     5 +-
 .../azureus2/core3/logging/impl/LoggerImpl.java    |     5 +-
 .../src/org/gudy/azureus2/core3/peer/PEPeer.java   |    22 +-
 .../gudy/azureus2/core3/peer/PEPeerListener.java   |     5 +-
 .../gudy/azureus2/core3/peer/PEPeerManager.java    |    23 +-
 .../azureus2/core3/peer/PEPeerManagerAdapter.java  |     8 +-
 .../azureus2/core3/peer/PEPeerManagerFactory.java  |     3 +-
 .../azureus2/core3/peer/PEPeerManagerListener.java |     5 +-
 .../core3/peer/PEPeerManagerListenerAdapter.java   |    50 +
 .../azureus2/core3/peer/PEPeerManagerStats.java    |     3 +-
 .../org/gudy/azureus2/core3/peer/PEPeerSource.java |     5 +-
 .../org/gudy/azureus2/core3/peer/PEPeerStats.java  |     3 +-
 .../src/org/gudy/azureus2/core3/peer/PEPiece.java  |     5 +-
 .../azureus2/core3/peer/impl/PEPeerControl.java    |    11 +-
 .../core3/peer/impl/PEPeerControlFactory.java      |     3 +-
 .../core3/peer/impl/PEPeerManagerStatsImpl.java    |     3 +-
 .../azureus2/core3/peer/impl/PEPeerStatsImpl.java  |     3 +-
 .../azureus2/core3/peer/impl/PEPeerTransport.java  |     6 +-
 .../peer/impl/PEPeerTransportExtensionHandler.java |     3 +-
 .../core3/peer/impl/PEPeerTransportFactory.java    |     3 +-
 .../gudy/azureus2/core3/peer/impl/PEPieceImpl.java |     9 +-
 .../azureus2/core3/peer/impl/PEPieceWriteImpl.java |     3 +-
 .../core3/peer/impl/control/PEPeerControlImpl.java |   482 +-
 .../core3/peer/impl/control/SuperSeedPeer.java     |     8 +-
 .../core3/peer/impl/control/SuperSeedPiece.java    |     3 +-
 .../impl/transport/PEPeerTransportDebugger.java    |     5 +-
 .../impl/transport/PEPeerTransportProtocol.java    |   614 +-
 .../core3/peer/util/PeerIdentityDataID.java        |     5 +-
 .../core3/peer/util/PeerIdentityManager.java       |     5 +-
 .../gudy/azureus2/core3/peer/util/PeerUtils.java   |   330 +-
 .../core3/security/SECertificateListener.java      |     3 +-
 .../gudy/azureus2/core3/security/SEKeyDetails.java |     5 +-
 .../core3/security/SEPasswordListener.java         |     5 +-
 .../azureus2/core3/security/SESecurityManager.java |     9 +-
 .../core3/security/impl/SESecurityManagerBC.java   |     5 +-
 .../core3/security/impl/SESecurityManagerImpl.java |    95 +-
 .../azureus2/core3/stats/StatsWriterFactory.java   |     3 +-
 .../azureus2/core3/stats/StatsWriterPeriodic.java  |     3 +-
 .../azureus2/core3/stats/StatsWriterStreamer.java  |     3 +-
 .../azureus2/core3/stats/impl/StatsWriterImpl.java |     3 +-
 .../core3/stats/impl/StatsWriterPeriodicImpl.java  |     3 +-
 .../core3/stats/impl/StatsWriterStreamerImpl.java  |     3 +-
 .../core3/stats/transfer/GeneralStats.java         |     3 +-
 .../core3/stats/transfer/LongTermStats.java        |    15 +-
 .../stats/transfer/LongTermStatsListener.java      |    15 +-
 .../core3/stats/transfer/OverallStats.java         |     3 +-
 .../core3/stats/transfer/StatsFactory.java         |     3 +-
 .../stats/transfer/impl/LongTermStatsImpl.java     |    15 +-
 .../stats/transfer/impl/OverallStatsImpl.java      |     3 +-
 .../org/gudy/azureus2/core3/torrent/TOTorrent.java |     3 +-
 .../core3/torrent/TOTorrentAnnounceURLGroup.java   |     3 +-
 .../core3/torrent/TOTorrentAnnounceURLSet.java     |     3 +-
 .../azureus2/core3/torrent/TOTorrentCreator.java   |     5 +-
 .../azureus2/core3/torrent/TOTorrentException.java |     3 +-
 .../azureus2/core3/torrent/TOTorrentFactory.java   |     3 +-
 .../gudy/azureus2/core3/torrent/TOTorrentFile.java |     8 +-
 .../azureus2/core3/torrent/TOTorrentListener.java  |    65 +-
 .../core3/torrent/TOTorrentProgressListener.java   |     3 +-
 .../impl/TOTorrentAnnounceURLGroupImpl.java        |     3 +-
 .../torrent/impl/TOTorrentAnnounceURLSetImpl.java  |     3 +-
 .../core3/torrent/impl/TOTorrentCreateImpl.java    |    38 +-
 .../core3/torrent/impl/TOTorrentCreatorImpl.java   |     5 +-
 .../torrent/impl/TOTorrentDeserialiseImpl.java     |    89 +-
 .../core3/torrent/impl/TOTorrentFileHasher.java    |     5 +-
 .../torrent/impl/TOTorrentFileHasherListener.java  |     3 +-
 .../core3/torrent/impl/TOTorrentFileImpl.java      |     5 +-
 .../azureus2/core3/torrent/impl/TOTorrentImpl.java |     3 +-
 .../torrent/impl/TOTorrentXMLDeserialiser.java     |     3 +-
 .../core3/torrent/impl/TOTorrentXMLSerialiser.java |     3 +-
 .../core3/torrent/impl/TorrentOpenFileOptions.java |    50 +-
 .../core3/torrent/impl/TorrentOpenOptions.java     |   289 +-
 .../core3/torrentdownloader/TorrentDownloader.java |     5 +-
 .../TorrentDownloaderCallBackInterface.java        |     5 +-
 .../TorrentDownloaderException.java                |     3 +-
 .../TorrentDownloaderFactory.java                  |    39 +-
 .../impl/TorrentDownloaderImpl.java                |    22 +-
 .../impl/TorrentDownloaderManager.java             |     5 +-
 .../core3/tracker/client/TRTrackerAnnouncer.java   |     3 +-
 .../client/TRTrackerAnnouncerDataProvider.java     |     3 +-
 .../client/TRTrackerAnnouncerException.java        |     3 +-
 .../tracker/client/TRTrackerAnnouncerFactory.java  |     3 +-
 .../client/TRTrackerAnnouncerFactoryListener.java  |     3 +-
 .../tracker/client/TRTrackerAnnouncerListener.java |     3 +-
 .../tracker/client/TRTrackerAnnouncerResponse.java |     3 +-
 .../client/TRTrackerAnnouncerResponsePeer.java     |     3 +-
 .../core3/tracker/client/TRTrackerScraper.java     |     3 +-
 .../client/TRTrackerScraperClientResolver.java     |     9 +-
 .../tracker/client/TRTrackerScraperFactory.java    |     3 +-
 .../tracker/client/TRTrackerScraperListener.java   |     3 +-
 .../tracker/client/TRTrackerScraperResponse.java   |     3 +-
 .../client/impl/TRTrackerAnnouncerFactoryImpl.java |     3 +-
 .../client/impl/TRTrackerAnnouncerHelper.java      |    89 +-
 .../client/impl/TRTrackerAnnouncerImpl.java        |     5 +-
 .../client/impl/TRTrackerAnnouncerMuxer.java       |  3517 ++---
 .../impl/TRTrackerAnnouncerResponseImpl.java       |     3 +-
 .../impl/TRTrackerAnnouncerResponsePeerImpl.java   |     3 +-
 .../tracker/client/impl/TRTrackerScraperImpl.java  |    15 +-
 .../client/impl/TRTrackerScraperResponseImpl.java  |     5 +-
 .../client/impl/bt/TRTrackerBTAnnouncerImpl.java   |   132 +-
 .../client/impl/bt/TRTrackerBTScraperImpl.java     |     5 +-
 .../impl/bt/TRTrackerBTScraperResponseImpl.java    |     5 +-
 .../tracker/client/impl/bt/TrackerChecker.java     |     5 +-
 .../tracker/client/impl/bt/TrackerLoadTester.java  |     8 +-
 .../tracker/client/impl/bt/TrackerStatus.java      |   210 +-
 .../client/impl/dht/TRTrackerDHTAnnouncerImpl.java |    30 +-
 .../client/impl/dht/TRTrackerDHTScraperImpl.java   |     5 +-
 .../impl/dht/TRTrackerDHTScraperResponseImpl.java  |     5 +-
 .../gudy/azureus2/core3/tracker/host/TRHost.java   |     3 +-
 .../tracker/host/TRHostAuthenticationListener.java |     5 +-
 .../core3/tracker/host/TRHostException.java        |     3 +-
 .../azureus2/core3/tracker/host/TRHostFactory.java |     3 +-
 .../core3/tracker/host/TRHostListener.java         |     3 +-
 .../core3/tracker/host/TRHostListener2.java        |    71 +-
 .../azureus2/core3/tracker/host/TRHostPeer.java    |     3 +-
 .../azureus2/core3/tracker/host/TRHostTorrent.java |     3 +-
 .../core3/tracker/host/TRHostTorrentFinder.java    |     3 +-
 .../core3/tracker/host/TRHostTorrentListener.java  |     3 +-
 .../host/TRHostTorrentRemovalVetoException.java    |     3 +-
 .../core3/tracker/host/TRHostTorrentRequest.java   |     3 +-
 .../host/TRHostTorrentWillBeRemovedListener.java   |     3 +-
 .../core3/tracker/host/impl/TRHostConfigImpl.java  |     3 +-
 .../tracker/host/impl/TRHostExternalTorrent.java   |     3 +-
 .../core3/tracker/host/impl/TRHostImpl.java        |     6 +-
 .../tracker/host/impl/TRHostPeerHostImpl.java      |     3 +-
 .../tracker/host/impl/TRHostPeerPublishImpl.java   |     3 +-
 .../tracker/host/impl/TRHostTorrentHostImpl.java   |     3 +-
 .../host/impl/TRHostTorrentPublishImpl.java        |     3 +-
 .../host/impl/TRHostTorrentRequestImpl.java        |     3 +-
 .../azureus2/core3/tracker/protocol/PRHelpers.java |     3 +-
 .../protocol/udp/PRUDPPacketReplyAnnounce.java     |     3 +-
 .../protocol/udp/PRUDPPacketReplyAnnounce2.java    |     3 +-
 .../protocol/udp/PRUDPPacketReplyConnect.java      |     3 +-
 .../protocol/udp/PRUDPPacketReplyError.java        |     3 +-
 .../protocol/udp/PRUDPPacketReplyScrape.java       |     3 +-
 .../protocol/udp/PRUDPPacketReplyScrape2.java      |     3 +-
 .../protocol/udp/PRUDPPacketRequestAnnounce.java   |     3 +-
 .../protocol/udp/PRUDPPacketRequestAnnounce2.java  |     3 +-
 .../protocol/udp/PRUDPPacketRequestConnect.java    |     3 +-
 .../protocol/udp/PRUDPPacketRequestScrape.java     |     3 +-
 .../tracker/protocol/udp/PRUDPPacketTracker.java   |     5 +-
 .../tracker/protocol/udp/PRUDPTrackerCodecs.java   |     5 +-
 .../core3/tracker/server/TRTrackerServer.java      |     3 +-
 .../TRTrackerServerAuthenticationListener.java     |     5 +-
 .../tracker/server/TRTrackerServerException.java   |     3 +-
 .../tracker/server/TRTrackerServerFactory.java     |    50 +-
 .../server/TRTrackerServerFactoryListener.java     |     3 +-
 .../tracker/server/TRTrackerServerListener.java    |     3 +-
 .../tracker/server/TRTrackerServerListener2.java   |   160 +-
 .../core3/tracker/server/TRTrackerServerPeer.java  |     3 +-
 .../tracker/server/TRTrackerServerPeerBase.java    |     5 +-
 .../tracker/server/TRTrackerServerRequest.java     |     3 +-
 .../server/TRTrackerServerRequestListener.java     |     3 +-
 .../core3/tracker/server/TRTrackerServerStats.java |     3 +-
 .../tracker/server/TRTrackerServerTorrent.java     |     3 +-
 .../server/TRTrackerServerTorrentListener.java     |     5 +-
 .../server/TRTrackerServerTorrentPeerListener.java |     5 +-
 .../server/TRTrackerServerTorrentStats.java        |     3 +-
 .../server/impl/TRTrackerServerFactoryImpl.java    |    45 +-
 .../tracker/server/impl/TRTrackerServerImpl.java   |     3 +-
 .../server/impl/TRTrackerServerNATChecker.java     |     5 +-
 .../impl/TRTrackerServerNatCheckerListener.java    |     5 +-
 .../server/impl/TRTrackerServerPeerImpl.java       |     3 +-
 .../server/impl/TRTrackerServerProcessor.java      |     3 +-
 .../server/impl/TRTrackerServerRequestImpl.java    |     3 +-
 .../server/impl/TRTrackerServerSimplePeer.java     |   131 +-
 .../server/impl/TRTrackerServerStatsImpl.java      |     3 +-
 .../server/impl/TRTrackerServerTorrentImpl.java    |     3 +-
 .../impl/TRTrackerServerTorrentStatsImpl.java      |     3 +-
 .../server/impl/dht/TRTrackerServerDHT.java        |     5 +-
 .../impl/tcp/TRTrackerServerProcessorTCP.java      |    11 +-
 .../server/impl/tcp/TRTrackerServerTCP.java        |    46 +-
 .../server/impl/tcp/blocking/TRBlockingServer.java |     7 +-
 .../tcp/blocking/TRBlockingServerProcessor.java    |    22 +-
 .../impl/tcp/nonblocking/TRNonBlockingServer.java  |    21 +-
 .../nonblocking/TRNonBlockingServerProcessor.java  |    16 +-
 .../TRNonBlockingServerProcessorFactory.java       |     5 +-
 .../impl/udp/TRTrackerServerProcessorUDP.java      |     3 +-
 .../server/impl/udp/TRTrackerServerUDP.java        |     3 +-
 .../core3/tracker/util/TRTrackerUtils.java         |     3 +-
 .../core3/tracker/util/TRTrackerUtilsListener.java |     5 +-
 .../org/gudy/azureus2/core3/util/AECallback.java   |     5 +-
 .../gudy/azureus2/core3/util/AEDiagnostics.java    |   143 +-
 .../core3/util/AEDiagnosticsEvidenceGenerator.java |     5 +-
 .../azureus2/core3/util/AEDiagnosticsLogger.java   |     5 +-
 .../gudy/azureus2/core3/util/AEJavaManagement.java |    15 +-
 .../src/org/gudy/azureus2/core3/util/AEMonSem.java |     5 +-
 .../org/gudy/azureus2/core3/util/AEMonitor.java    |    10 +-
 .../org/gudy/azureus2/core3/util/AEMonitor2.java   |     5 +-
 .../azureus2/core3/util/AENetworkClassifier.java   |    70 +-
 .../core3/util/AENetworkClassifierListener.java    |     5 +-
 .../azureus2/core3/util/AERunStateHandler.java     |    17 +-
 .../org/gudy/azureus2/core3/util/AERunnable.java   |     5 +-
 .../azureus2/core3/util/AERunnableBoolean.java     |     9 +-
 .../gudy/azureus2/core3/util/AERunnableObject.java |     5 +-
 .../core3/util/AERunnableWithCallback.java         |     5 +-
 .../org/gudy/azureus2/core3/util/AESemaphore.java  |     5 +-
 .../org/gudy/azureus2/core3/util/AESemaphore2.java |    95 +-
 .../core3/util/AETemporaryFileHandler.java         |     5 +-
 .../src/org/gudy/azureus2/core3/util/AEThread.java |     5 +-
 .../org/gudy/azureus2/core3/util/AEThread2.java    |     5 +-
 .../org/gudy/azureus2/core3/util/AEVerifier.java   |     5 +-
 .../azureus2/core3/util/AEVerifierException.java   |     5 +-
 .../org/gudy/azureus2/core3/util/AddressUtils.java |   196 +-
 .../gudy/azureus2/core3/util/AsyncController.java  |    63 +-
 .../gudy/azureus2/core3/util/AsyncDispatcher.java  |     5 +-
 .../src/org/gudy/azureus2/core3/util/Average.java  |     5 +-
 .../src/org/gudy/azureus2/core3/util/BDecoder.java |    91 +-
 .../gudy/azureus2/core3/util/BEncodableObject.java |     5 +-
 .../src/org/gudy/azureus2/core3/util/BEncoder.java |    82 +-
 .../azureus2/core3/util/BEncodingException.java    |     5 +-
 .../src/org/gudy/azureus2/core3/util/Base32.java   |     5 +-
 .../gudy/azureus2/core3/util/BrokenMd5Hasher.java  |     3 +-
 .../gudy/azureus2/core3/util/ByteArrayHashMap.java |     5 +-
 .../azureus2/core3/util/ByteEncodedKeyHashMap.java |     3 +-
 .../gudy/azureus2/core3/util/ByteFormatter.java    |     5 +-
 .../src/org/gudy/azureus2/core3/util/CRC32C.java   |    99 +
 .../core3/util/ConcurrentHashMapWrapper.java       |    23 +-
 .../gudy/azureus2/core3/util/ConcurrentHasher.java |     5 +-
 .../core3/util/ConcurrentHasherRequest.java        |     5 +-
 .../util/ConcurrentHasherRequestListener.java      |     5 +-
 .../org/gudy/azureus2/core3/util/Constants.java    |     9 +-
 .../src/org/gudy/azureus2/core3/util/Debug.java    |    13 +-
 .../org/gudy/azureus2/core3/util/DebugLight.java   |     5 +-
 .../gudy/azureus2/core3/util/DebugWeakList.java    |     5 +-
 .../org/gudy/azureus2/core3/util/DelayedEvent.java |     5 +-
 .../gudy/azureus2/core3/util/DirectByteBuffer.java |     5 +-
 .../azureus2/core3/util/DirectByteBufferPool.java  |     5 +-
 .../core3/util/DirectByteBufferPoolReal.java       |  2179 ++--
 .../azureus2/core3/util/DisplayFormatters.java     |     3 +-
 .../org/gudy/azureus2/core3/util/ED2KHasher.java   |     3 +-
 .../core3/util/FileIsADirectoryException.java      |     5 +-
 .../src/org/gudy/azureus2/core3/util/FileUtil.java |    59 +-
 .../core3/util/FrequencyLimitedDispatcher.java     |     5 +-
 .../org/gudy/azureus2/core3/util/HashWrapper.java  |     5 +-
 .../org/gudy/azureus2/core3/util/HashWrapper2.java |   235 +-
 .../azureus2/core3/util/HostNameToIPResolver.java  |    12 +-
 .../core3/util/HostNameToIPResolverException.java  |     5 +-
 .../core3/util/HostNameToIPResolverListener.java   |     5 +-
 .../azureus2/core3/util/IPToHostNameResolver.java  |    25 +-
 .../core3/util/IPToHostNameResolverListener.java   |     5 +-
 .../core3/util/IPToHostNameResolverRequest.java    |     5 +-
 .../src/org/gudy/azureus2/core3/util/Ignore.java   |     5 +-
 .../org/gudy/azureus2/core3/util/IndentWriter.java |     5 +-
 .../org/gudy/azureus2/core3/util/LightHashMap.java |     5 +-
 .../gudy/azureus2/core3/util/LightHashMapEx.java   |    17 +-
 .../org/gudy/azureus2/core3/util/LightHashSet.java |     5 +-
 .../gudy/azureus2/core3/util/ListenerManager.java  |    17 +-
 .../core3/util/ListenerManagerDispatcher.java      |     3 +-
 .../ListenerManagerDispatcherWithException.java    |     3 +-
 .../org/gudy/azureus2/core3/util/MD4Hasher.java    |     5 +-
 .../gudy/azureus2/core3/util/NonDaemonTask.java    |     3 +-
 .../azureus2/core3/util/NonDaemonTaskRunner.java   |     3 +-
 .../gudy/azureus2/core3/util/PausableAverage.java  |     5 +-
 .../gudy/azureus2/core3/util/RARTOCDecoder.java    |    17 +-
 .../org/gudy/azureus2/core3/util/RandomUtils.java  |     5 +-
 .../org/gudy/azureus2/core3/util/RealTimeInfo.java |     5 +-
 .../util/ReferenceCountedDirectByteBuffer.java     |     5 +-
 .../src/org/gudy/azureus2/core3/util/SHA1.java     |     5 +-
 .../org/gudy/azureus2/core3/util/SHA1Hasher.java   |     5 +-
 .../org/gudy/azureus2/core3/util/SHA1Simple.java   |     5 +-
 .../azureus2/core3/util/ShellUtilityFinder.java    |    18 +
 .../org/gudy/azureus2/core3/util/SimpleTimer.java  |     5 +-
 .../gudy/azureus2/core3/util/StringInterner.java   |     5 +-
 .../gudy/azureus2/core3/util/SystemProperties.java |     8 +-
 .../org/gudy/azureus2/core3/util/SystemTime.java   |     7 +-
 .../org/gudy/azureus2/core3/util/ThreadPool.java   |     3 +-
 .../gudy/azureus2/core3/util/ThreadPoolTask.java   |     5 +-
 .../gudy/azureus2/core3/util/TimeFormatter.java    |     5 +-
 .../gudy/azureus2/core3/util/TimeLimitedTask.java  |   239 +-
 .../src/org/gudy/azureus2/core3/util/Timer.java    |     3 +-
 .../org/gudy/azureus2/core3/util/TimerEvent.java   |     3 +-
 .../azureus2/core3/util/TimerEventPerformer.java   |     3 +-
 .../azureus2/core3/util/TimerEventPeriodic.java    |     3 +-
 .../org/gudy/azureus2/core3/util/TorrentUtils.java |   515 +-
 .../org/gudy/azureus2/core3/util/TrackersUtil.java |     3 +-
 .../core3/util/UnresolvableHostManager.java        |     5 +-
 .../src/org/gudy/azureus2/core3/util/UrlUtils.java |   367 +-
 .../gudy/azureus2/core3/util/jar/AEJarBuilder.java |     3 +-
 .../gudy/azureus2/core3/util/jar/AEJarReader.java  |     3 +-
 .../gudy/azureus2/core3/util/jar/AEJarSigner.java  |     5 +-
 .../gudy/azureus2/core3/util/jar/AEJarSigner2.java |     5 +-
 .../azureus2/core3/util/jman/AEMemoryMonitor.java  |    17 +-
 .../azureus2/core3/util/jman/AEThreadMonitor.java  |    41 +-
 .../util/protocol/AzURLStreamHandlerFactory.java   |     5 +-
 .../util/protocol/azplug/AZPluginConnection.java   |    89 +-
 .../core3/util/protocol/azplug/Handler.java        |     3 +-
 .../azureus2/core3/util/protocol/bc/Handler.java   |     3 +-
 .../azureus2/core3/util/protocol/dht/Handler.java  |     3 +-
 .../azureus2/core3/util/protocol/i2p/Handler.java  |     5 +-
 .../core3/util/protocol/maggot/Handler.java        |   122 +
 .../core3/util/protocol/magnet/Handler.java        |    29 +-
 .../util/protocol/magnet/MagnetConnection.java     |     5 +-
 .../util/protocol/magnet/MagnetConnection2.java    |    36 +-
 .../core3/util/protocol/socks5/Handler.java        |     3 +-
 .../util/protocol/socks5/Socks5URLConnection.java  |     3 +-
 .../azureus2/core3/util/protocol/tcp/Handler.java  |     3 +-
 .../core3/util/protocol/tcp/TCPURLConnection.java  |     3 +-
 .../azureus2/core3/util/protocol/tor/Handler.java  |    56 +
 .../azureus2/core3/util/protocol/udp/Handler.java  |     3 +-
 .../core3/util/protocol/udp/UDPURLConnection.java  |     3 +-
 .../azureus2/core3/util/protocol/vuze/Handler.java |     3 +-
 .../util/protocol/vuze/VuzeURLConnection.java      |     3 +-
 .../core3/util/spi/AENameServiceDescriptor.java    |   342 +
 .../SimpleXMLParserDocumentFactory.java            |    22 +-
 .../gudy/azureus2/core3/xml/util/XMLElement.java   |     5 +-
 .../azureus2/core3/xml/util/XMLEscapeWriter.java   |    17 +-
 .../gudy/azureus2/core3/xml/util/XUXmlWriter.java  |     3 +-
 .../azureus2/internat/MessagesBundle.properties    |   417 +-
 .../internat/MessagesBundle_bg_BG.properties       |    11 +-
 .../internat/MessagesBundle_ca_AD.properties       |     8 +-
 .../internat/MessagesBundle_cs_CZ.properties       |    11 +-
 .../internat/MessagesBundle_da_DK.properties       |     2 +
 .../internat/MessagesBundle_de_DE.properties       |    11 +-
 .../internat/MessagesBundle_es_ES.properties       |    71 +-
 .../azureus2/internat/MessagesBundle_eu.properties |  7956 ++++++------
 .../internat/MessagesBundle_fi_FI.properties       |     2 +
 .../internat/MessagesBundle_fr_FR.properties       |  5753 ++++++---
 .../internat/MessagesBundle_fy_NL.properties       |     2 +
 .../internat/MessagesBundle_hu_HU.properties       |     2 +
 .../internat/MessagesBundle_in_ID.properties       |     2 +
 .../internat/MessagesBundle_it_IT.properties       |     9 +-
 .../internat/MessagesBundle_ja_JP.properties       |     2 +
 .../internat/MessagesBundle_ka_GE.properties       |     2 +
 .../internat/MessagesBundle_ko_KR.properties       |    11 +-
 .../internat/MessagesBundle_li_NL.properties       |     2 +
 .../internat/MessagesBundle_lt_LT.properties       |     2 +
 .../internat/MessagesBundle_nl_NL.properties       |     2 +
 .../internat/MessagesBundle_no_NO.properties       |     2 +
 .../azureus2/internat/MessagesBundle_oc.properties |     1 -
 .../internat/MessagesBundle_pl_PL.properties       |     6 +-
 .../internat/MessagesBundle_pt_BR.properties       |  7831 ++++++-----
 .../internat/MessagesBundle_pt_PT.properties       |     2 +
 .../internat/MessagesBundle_ro_RO.properties       |     8 +-
 .../internat/MessagesBundle_ru_RU.properties       |    11 +-
 .../internat/MessagesBundle_sk_SK.properties       |     2 +
 .../azureus2/internat/MessagesBundle_sr.properties |     2 +
 .../internat/MessagesBundle_sr_Latin.properties    |     2 +
 .../internat/MessagesBundle_sv_SE.properties       |     5 +-
 .../internat/MessagesBundle_th_TH.properties       |     2 +
 .../internat/MessagesBundle_uk_UA.properties       |    11 +-
 .../internat/MessagesBundle_zh_CN.properties       |     7 +-
 .../internat/MessagesBundle_zh_TW.properties       |     2 +
 .../org/gudy/azureus2/platform/JavaBitMode.java    |    18 +
 .../gudy/azureus2/platform/PlatformManager.java    |     5 +-
 .../platform/PlatformManagerCapabilities.java      |     5 +-
 .../azureus2/platform/PlatformManagerFactory.java  |     5 +-
 .../azureus2/platform/PlatformManagerListener.java |     5 +-
 .../platform/PlatformManagerPingCallback.java      |     5 +-
 .../platform/PlatformManagerPluginDelegate.java    |     5 +-
 .../platform/dummy/PlatformManagerImpl.java        |     5 +-
 .../platform/macosx/NativeInvocationBridge.java    |     5 +-
 .../gudy/azureus2/platform/macosx/PListEditor.java |   653 +-
 .../platform/macosx/PlatformManagerImpl.java       |    35 +-
 .../macosx/PlatformManagerUpdateChecker.java       |     6 +-
 .../macosx/access/cocoa/CocoaJavaBridge.java       |     5 +-
 .../platform/macosx/access/jnilib/OSXAccess.java   |     7 +-
 .../access/jnilib/OSXDriveDetectListener.java      |    18 +
 .../platform/unix/PlatformManagerImpl.java         |     5 +-
 .../platform/unix/PlatformManagerUnixPlugin.java   |     5 +-
 .../platform/unix/ScriptAfterShutdown.java         |    18 +
 .../platform/unix/ScriptBeforeStartup.java         |    18 +
 .../org/gudy/azureus2/platform/unix/startupScript  |    34 +-
 .../platform/win32/PlatformManagerImpl.java        |    34 +-
 .../win32/PlatformManagerUpdateChecker.java        |     6 +-
 .../platform/win32/access/AEWin32Access.java       |     5 +-
 .../win32/access/AEWin32AccessException.java       |     5 +-
 .../win32/access/AEWin32AccessListener.java        |     5 +-
 .../platform/win32/access/AEWin32Manager.java      |     5 +-
 .../win32/access/impl/AEWin32AccessCallback.java   |     5 +-
 .../access/impl/AEWin32AccessExceptionImpl.java    |     5 +-
 .../win32/access/impl/AEWin32AccessImpl.java       |     5 +-
 .../win32/access/impl/AEWin32AccessInterface.java  |     5 +-
 .../gudy/azureus2/plugins/LaunchablePlugin.java    |     5 +-
 azureus2/src/org/gudy/azureus2/plugins/Plugin.java |     3 +-
 .../org/gudy/azureus2/plugins/PluginAdapter.java   |    15 +-
 .../org/gudy/azureus2/plugins/PluginConfig.java    |     3 +-
 .../azureus2/plugins/PluginConfigListener.java     |     5 +-
 .../src/org/gudy/azureus2/plugins/PluginEvent.java |     3 +-
 .../gudy/azureus2/plugins/PluginEventListener.java |     3 +-
 .../org/gudy/azureus2/plugins/PluginException.java |     3 +-
 .../org/gudy/azureus2/plugins/PluginInterface.java |     3 +-
 .../org/gudy/azureus2/plugins/PluginLauncher.java  |     5 +-
 .../org/gudy/azureus2/plugins/PluginListener.java  |     3 +-
 .../org/gudy/azureus2/plugins/PluginManager.java   |    14 +-
 .../plugins/PluginManagerArgumentHandler.java      |     5 +-
 .../azureus2/plugins/PluginManagerDefaults.java    |     5 +-
 .../gudy/azureus2/plugins/UnloadablePlugin.java    |     5 +-
 .../plugins/clientid/ClientIDException.java        |     5 +-
 .../plugins/clientid/ClientIDGenerator.java        |     6 +-
 .../azureus2/plugins/clientid/ClientIDManager.java |     5 +-
 .../azureus2/plugins/config/ConfigParameter.java   |     5 +-
 .../plugins/config/ConfigParameterListener.java    |     5 +-
 .../plugins/config/PluginConfigSource.java         |     5 +-
 .../azureus2/plugins/ddb/DistributedDatabase.java  |    15 +-
 .../plugins/ddb/DistributedDatabaseContact.java    |     9 +-
 .../plugins/ddb/DistributedDatabaseEvent.java      |     5 +-
 .../plugins/ddb/DistributedDatabaseException.java  |     5 +-
 .../plugins/ddb/DistributedDatabaseKey.java        |     5 +-
 .../plugins/ddb/DistributedDatabaseKeyStats.java   |     5 +-
 .../plugins/ddb/DistributedDatabaseListener.java   |     5 +-
 .../ddb/DistributedDatabaseProgressListener.java   |     5 +-
 .../ddb/DistributedDatabaseTransferHandler.java    |     7 +-
 .../ddb/DistributedDatabaseTransferType.java       |     5 +-
 .../plugins/ddb/DistributedDatabaseValue.java      |     5 +-
 .../plugins/dht/mainline/MainlineDHTManager.java   |     5 +-
 .../plugins/dht/mainline/MainlineDHTProvider.java  |     5 +-
 .../gudy/azureus2/plugins/disk/DiskManager.java    |     3 +-
 .../azureus2/plugins/disk/DiskManagerChannel.java  |     5 +-
 .../azureus2/plugins/disk/DiskManagerEvent.java    |     5 +-
 .../plugins/disk/DiskManagerException.java         |     3 +-
 .../azureus2/plugins/disk/DiskManagerFileInfo.java |     8 +-
 .../azureus2/plugins/disk/DiskManagerListener.java |     5 +-
 .../plugins/disk/DiskManagerRandomReadRequest.java |    17 +-
 .../plugins/disk/DiskManagerReadRequest.java       |    69 +-
 .../disk/DiskManagerReadRequestListener.java       |    75 +-
 .../azureus2/plugins/disk/DiskManagerRequest.java  |     5 +-
 .../plugins/disk/DiskManagerWriteRequest.java      |    69 +-
 .../disk/DiskManagerWriteRequestListener.java      |    69 +-
 .../gudy/azureus2/plugins/download/Download.java   |    21 +-
 .../plugins/download/DownloadActivationEvent.java  |     5 +-
 .../download/DownloadActivationListener.java       |     5 +-
 .../plugins/download/DownloadAnnounceResult.java   |     3 +-
 .../download/DownloadAnnounceResultPeer.java       |     5 +-
 .../download/DownloadAttributeListener.java        |     5 +-
 .../download/DownloadCompletionListener.java       |     2 +-
 .../plugins/download/DownloadEventNotifier.java    |     5 +-
 .../plugins/download/DownloadException.java        |     3 +-
 .../plugins/download/DownloadListener.java         |     3 +-
 .../azureus2/plugins/download/DownloadManager.java |     6 +-
 .../plugins/download/DownloadManagerListener.java  |     3 +-
 .../plugins/download/DownloadManagerStats.java     |    11 +-
 .../plugins/download/DownloadPeerListener.java     |     3 +-
 .../plugins/download/DownloadPropertyEvent.java    |     5 +-
 .../plugins/download/DownloadPropertyListener.java |     5 +-
 .../download/DownloadRemovalVetoException.java     |     3 +-
 .../plugins/download/DownloadScrapeResult.java     |     3 +-
 .../azureus2/plugins/download/DownloadStats.java   |    27 +-
 .../azureus2/plugins/download/DownloadStub.java    |    36 +-
 .../plugins/download/DownloadStubEvent.java        |    15 +-
 .../plugins/download/DownloadStubListener.java     |    15 +-
 .../plugins/download/DownloadTrackerListener.java  |     3 +-
 .../plugins/download/DownloadTypeComplete.java     |     6 +-
 .../plugins/download/DownloadTypeIncomplete.java   |     6 +-
 .../download/DownloadWillBeAddedListener.java      |     5 +-
 .../download/DownloadWillBeRemovedListener.java    |     3 +-
 .../savelocation/DefaultSaveLocationManager.java   |     5 +-
 .../download/savelocation/SaveLocationChange.java  |     5 +-
 .../download/savelocation/SaveLocationManager.java |     5 +-
 .../plugins/installer/FilePluginInstaller.java     |     5 +-
 .../plugins/installer/InstallablePlugin.java       |     5 +-
 .../installer/PluginInstallationListener.java      |    75 +-
 .../plugins/installer/PluginInstaller.java         |     5 +-
 .../plugins/installer/PluginInstallerListener.java |     5 +-
 .../azureus2/plugins/installer/StandardPlugin.java |     5 +-
 .../gudy/azureus2/plugins/ipc/IPCException.java    |     5 +-
 .../gudy/azureus2/plugins/ipc/IPCInterface.java    |     5 +-
 .../gudy/azureus2/plugins/ipfilter/IPBanned.java   |     8 +-
 .../gudy/azureus2/plugins/ipfilter/IPBlocked.java  |     3 +-
 .../gudy/azureus2/plugins/ipfilter/IPFilter.java   |     3 +-
 .../plugins/ipfilter/IPFilterException.java        |     3 +-
 .../gudy/azureus2/plugins/ipfilter/IPRange.java    |     3 +-
 .../plugins/logging/FileLoggerAdapter.java         |     5 +-
 .../gudy/azureus2/plugins/logging/LogAlert.java    |     2 +-
 .../azureus2/plugins/logging/LogAlertListener.java |     2 +-
 .../org/gudy/azureus2/plugins/logging/Logger.java  |     3 +-
 .../plugins/logging/LoggerAlertListener.java       |     5 +-
 .../azureus2/plugins/logging/LoggerChannel.java    |     3 +-
 .../plugins/logging/LoggerChannelListener.java     |     3 +-
 .../gudy/azureus2/plugins/messaging/Message.java   |     5 +-
 .../plugins/messaging/MessageException.java        |     5 +-
 .../azureus2/plugins/messaging/MessageManager.java |     5 +-
 .../plugins/messaging/MessageManagerListener.java  |     5 +-
 .../plugins/messaging/MessageStreamDecoder.java    |     5 +-
 .../plugins/messaging/MessageStreamEncoder.java    |     5 +-
 .../messaging/bittorrent/BTMessageCancel.java      |     5 +-
 .../messaging/bittorrent/BTMessageManager.java     |     5 +-
 .../messaging/bittorrent/BTMessagePiece.java       |     5 +-
 .../messaging/bittorrent/BTMessageRequest.java     |     5 +-
 .../generic/GenericMessageConnection.java          |     5 +-
 .../generic/GenericMessageConnectionListener.java  |     5 +-
 .../messaging/generic/GenericMessageEndpoint.java  |     5 +-
 .../messaging/generic/GenericMessageHandler.java   |     5 +-
 .../generic/GenericMessageRegistration.java        |     5 +-
 .../gudy/azureus2/plugins/network/Connection.java  |     5 +-
 .../plugins/network/ConnectionListener.java        |     5 +-
 .../plugins/network/ConnectionManager.java         |     5 +-
 .../azureus2/plugins/network/ConnectionStub.java   |    17 +-
 .../plugins/network/IncomingMessageQueue.java      |     5 +-
 .../network/IncomingMessageQueueListener.java      |     5 +-
 .../plugins/network/OutgoingMessageQueue.java      |     5 +-
 .../network/OutgoingMessageQueueListener.java      |     5 +-
 .../gudy/azureus2/plugins/network/RateLimiter.java |    87 +-
 .../gudy/azureus2/plugins/network/RawMessage.java  |     5 +-
 .../gudy/azureus2/plugins/network/Transport.java   |     5 +-
 .../azureus2/plugins/network/TransportCipher.java  |     5 +-
 .../plugins/network/TransportException.java        |     5 +-
 .../src/org/gudy/azureus2/plugins/peers/Peer.java  |     3 +-
 .../azureus2/plugins/peers/PeerDescriptor.java     |     5 +-
 .../org/gudy/azureus2/plugins/peers/PeerEvent.java |     5 +-
 .../gudy/azureus2/plugins/peers/PeerListener.java  |     5 +-
 .../gudy/azureus2/plugins/peers/PeerListener2.java |     5 +-
 .../gudy/azureus2/plugins/peers/PeerManager.java   |    29 +-
 .../azureus2/plugins/peers/PeerManagerEvent.java   |   113 +-
 .../plugins/peers/PeerManagerListener.java         |     5 +-
 .../plugins/peers/PeerManagerListener2.java        |    59 +-
 .../azureus2/plugins/peers/PeerManagerStats.java   |     5 +-
 .../azureus2/plugins/peers/PeerReadRequest.java    |     3 +-
 .../org/gudy/azureus2/plugins/peers/PeerStats.java |     3 +-
 .../src/org/gudy/azureus2/plugins/peers/Piece.java |     5 +-
 .../azureus2/plugins/platform/PlatformManager.java |     5 +-
 .../plugins/platform/PlatformManagerException.java |     5 +-
 .../azureus2/plugins/sharing/ShareException.java   |     3 +-
 .../gudy/azureus2/plugins/sharing/ShareItem.java   |     3 +-
 .../azureus2/plugins/sharing/ShareManager.java     |     6 +-
 .../plugins/sharing/ShareManagerListener.java      |     3 +-
 .../azureus2/plugins/sharing/ShareResource.java    |     8 +-
 .../ShareResourceDeletionVetoException.java        |     3 +-
 .../azureus2/plugins/sharing/ShareResourceDir.java |     3 +-
 .../plugins/sharing/ShareResourceDirContents.java  |     3 +-
 .../plugins/sharing/ShareResourceEvent.java        |     5 +-
 .../plugins/sharing/ShareResourceFile.java         |     3 +-
 .../plugins/sharing/ShareResourceListener.java     |     5 +-
 .../ShareResourceWillBeDeletedListener.java        |     3 +-
 .../org/gudy/azureus2/plugins/torrent/Torrent.java |     3 +-
 .../plugins/torrent/TorrentAnnounceURLList.java    |     3 +-
 .../plugins/torrent/TorrentAnnounceURLListSet.java |     3 +-
 .../azureus2/plugins/torrent/TorrentAttribute.java |     5 +-
 .../plugins/torrent/TorrentAttributeEvent.java     |     5 +-
 .../plugins/torrent/TorrentAttributeListener.java  |     5 +-
 .../azureus2/plugins/torrent/TorrentCreator.java   |     5 +-
 .../plugins/torrent/TorrentCreatorListener.java    |     5 +-
 .../plugins/torrent/TorrentDownloader.java         |     3 +-
 .../plugins/torrent/TorrentEncodingException.java  |     5 +-
 .../azureus2/plugins/torrent/TorrentException.java |     3 +-
 .../gudy/azureus2/plugins/torrent/TorrentFile.java |     3 +-
 .../azureus2/plugins/torrent/TorrentManager.java   |     3 +-
 .../plugins/torrent/TorrentManagerEvent.java       |     5 +-
 .../plugins/torrent/TorrentManagerListener.java    |     5 +-
 .../org/gudy/azureus2/plugins/tracker/Tracker.java |    19 +-
 .../azureus2/plugins/tracker/TrackerException.java |     3 +-
 .../azureus2/plugins/tracker/TrackerListener.java  |     3 +-
 .../gudy/azureus2/plugins/tracker/TrackerPeer.java |     3 +-
 .../azureus2/plugins/tracker/TrackerPeerEvent.java |     5 +-
 .../plugins/tracker/TrackerPeerListener.java       |     5 +-
 .../azureus2/plugins/tracker/TrackerTorrent.java   |     3 +-
 .../plugins/tracker/TrackerTorrentListener.java    |     3 +-
 .../TrackerTorrentRemovalVetoException.java        |     3 +-
 .../plugins/tracker/TrackerTorrentRequest.java     |     3 +-
 .../TrackerTorrentWillBeRemovedListener.java       |     3 +-
 .../tracker/web/TrackerAuthenticationAdapter.java  |     5 +-
 .../tracker/web/TrackerAuthenticationListener.java |     5 +-
 .../plugins/tracker/web/TrackerWebContext.java     |     3 +-
 .../tracker/web/TrackerWebPageGenerator.java       |     3 +-
 .../plugins/tracker/web/TrackerWebPageRequest.java |     3 +-
 .../tracker/web/TrackerWebPageResponse.java        |     6 +-
 .../src/org/gudy/azureus2/plugins/ui/Graphic.java  |     8 +-
 .../org/gudy/azureus2/plugins/ui/GraphicURI.java   |    40 +
 .../azureus2/plugins/ui/UIDataSourceListener.java  |    18 +
 .../org/gudy/azureus2/plugins/ui/UIException.java  |     5 +-
 .../gudy/azureus2/plugins/ui/UIInputReceiver.java  |     5 +-
 .../plugins/ui/UIInputReceiverListener.java        |    18 +
 .../gudy/azureus2/plugins/ui/UIInputValidator.java |     5 +-
 .../org/gudy/azureus2/plugins/ui/UIInstance.java   |     5 +-
 .../azureus2/plugins/ui/UIInstanceFactory.java     |     5 +-
 .../org/gudy/azureus2/plugins/ui/UIManager.java    |     9 +-
 .../gudy/azureus2/plugins/ui/UIManagerEvent.java   |     5 +-
 .../plugins/ui/UIManagerEventListener.java         |     5 +-
 .../azureus2/plugins/ui/UIManagerListener.java     |     5 +-
 .../azureus2/plugins/ui/UIManagerListener2.java    |     3 -
 .../org/gudy/azureus2/plugins/ui/UIMessage.java    |     5 +-
 .../org/gudy/azureus2/plugins/ui/UIPluginView.java |     8 +-
 .../plugins/ui/UIPluginViewToolBarListener.java    |    19 +
 .../plugins/ui/components/UIComponent.java         |     7 +-
 .../plugins/ui/components/UIProgressBar.java       |     5 +-
 .../ui/components/UIPropertyChangeEvent.java       |     5 +-
 .../ui/components/UIPropertyChangeListener.java    |     5 +-
 .../azureus2/plugins/ui/components/UITextArea.java |     5 +-
 .../plugins/ui/components/UITextField.java         |     5 +-
 .../plugins/ui/config/ActionParameter.java         |     5 +-
 .../plugins/ui/config/BooleanParameter.java        |     5 +-
 .../azureus2/plugins/ui/config/ColorParameter.java |     5 +-
 .../azureus2/plugins/ui/config/ConfigSection.java  |     3 +-
 .../plugins/ui/config/DirectoryParameter.java      |     5 +-
 .../plugins/ui/config/EnablerParameter.java        |     3 +-
 .../azureus2/plugins/ui/config/FileParameter.java  |     5 +-
 .../azureus2/plugins/ui/config/InfoParameter.java  |     5 +-
 .../azureus2/plugins/ui/config/IntParameter.java   |     5 +-
 .../azureus2/plugins/ui/config/LabelParameter.java |     5 +-
 .../gudy/azureus2/plugins/ui/config/Parameter.java |     3 +-
 .../azureus2/plugins/ui/config/ParameterGroup.java |    10 +-
 .../plugins/ui/config/ParameterListener.java       |     5 +-
 .../plugins/ui/config/ParameterTabFolder.java      |    36 +
 .../plugins/ui/config/PasswordParameter.java       |     5 +-
 .../plugins/ui/config/PluginConfigUIFactory.java   |     3 +-
 .../plugins/ui/config/StringListParameter.java     |     5 +-
 .../plugins/ui/config/StringParameter.java         |     5 +-
 .../azureus2/plugins/ui/config/UIParameter.java    |     5 +-
 .../plugins/ui/config/UIParameterContext.java      |     5 +-
 .../azureus2/plugins/ui/menus/MenuBuilder.java     |    29 +
 .../azureus2/plugins/ui/menus/MenuContext.java     |     2 +-
 .../gudy/azureus2/plugins/ui/menus/MenuItem.java   |    13 +-
 .../plugins/ui/menus/MenuItemFillListener.java     |    29 +-
 .../plugins/ui/menus/MenuItemListener.java         |    10 +-
 .../azureus2/plugins/ui/menus/MenuManager.java     |    47 +-
 .../plugins/ui/model/BasicPluginConfigModel.java   |    20 +-
 .../plugins/ui/model/BasicPluginViewModel.java     |     5 +-
 .../plugins/ui/model/PluginConfigModel.java        |     5 +-
 .../azureus2/plugins/ui/model/PluginViewModel.java |     5 +-
 .../gudy/azureus2/plugins/ui/tables/TableCell.java |     3 +-
 .../plugins/ui/tables/TableCellAddedListener.java  |     3 +-
 .../ui/tables/TableCellClipboardListener.java      |     3 +-
 .../ui/tables/TableCellDisposeListener.java        |     3 +-
 .../ui/tables/TableCellInplaceEditorListener.java  |     3 +-
 .../ui/tables/TableCellLightRefreshListener.java   |     5 +-
 .../plugins/ui/tables/TableCellMouseEvent.java     |     3 +-
 .../plugins/ui/tables/TableCellMouseListener.java  |     8 +-
 .../ui/tables/TableCellMouseMoveListener.java      |     8 +-
 .../ui/tables/TableCellRefreshListener.java        |     3 +-
 .../plugins/ui/tables/TableCellRefresher.java      |    18 +
 .../ui/tables/TableCellToolTipListener.java        |     3 +-
 .../ui/tables/TableCellVisibilityListener.java     |     5 +-
 .../azureus2/plugins/ui/tables/TableColumn.java    |     6 +-
 .../ui/tables/TableColumnCreationListener.java     |     6 +-
 .../ui/tables/TableColumnExtraInfoListener.java    |     6 +-
 .../plugins/ui/tables/TableColumnInfo.java         |     6 +-
 .../plugins/ui/tables/TableContextMenuItem.java    |     3 +-
 .../azureus2/plugins/ui/tables/TableManager.java   |     8 +-
 .../gudy/azureus2/plugins/ui/tables/TableRow.java  |     6 +-
 .../plugins/ui/tables/TableRowMouseEvent.java      |     5 +-
 .../plugins/ui/tables/TableRowMouseListener.java   |     5 +-
 .../plugins/ui/tables/TableRowRefreshListener.java |     6 +-
 .../ui/toolbar/UIToolBarActivationListener.java    |    24 +-
 .../plugins/ui/toolbar/UIToolBarEnablerBase.java   |    18 +
 .../azureus2/plugins/ui/toolbar/UIToolBarItem.java |    46 +
 .../plugins/ui/toolbar/UIToolBarManager.java       |    25 +-
 .../plugins/update/UpdatableComponent.java         |     5 +-
 .../org/gudy/azureus2/plugins/update/Update.java   |     8 +-
 .../plugins/update/UpdateCheckInstance.java        |     5 +-
 .../update/UpdateCheckInstanceListener.java        |     5 +-
 .../azureus2/plugins/update/UpdateChecker.java     |     7 +-
 .../plugins/update/UpdateCheckerListener.java      |     5 +-
 .../azureus2/plugins/update/UpdateException.java   |     5 +-
 .../azureus2/plugins/update/UpdateInstaller.java   |     5 +-
 .../plugins/update/UpdateInstallerListener.java    |    73 +-
 .../azureus2/plugins/update/UpdateListener.java    |     5 +-
 .../azureus2/plugins/update/UpdateManager.java     |     5 +-
 .../update/UpdateManagerDecisionListener.java      |     5 +-
 .../plugins/update/UpdateManagerListener.java      |     5 +-
 .../update/UpdateManagerVerificationListener.java  |     5 +-
 .../plugins/update/UpdateProgressListener.java     |     5 +-
 .../plugins/utils/AggregatedDispatcher.java        |     5 +-
 .../azureus2/plugins/utils/AggregatedList.java     |     5 +-
 .../plugins/utils/AggregatedListAcceptor.java      |     5 +-
 .../azureus2/plugins/utils/ByteArrayWrapper.java   |     5 +-
 .../gudy/azureus2/plugins/utils/DelayedTask.java   |    77 +-
 .../azureus2/plugins/utils/FeatureManager.java     |   467 +-
 .../gudy/azureus2/plugins/utils/Formatters.java    |     3 +-
 .../gudy/azureus2/plugins/utils/LocaleDecoder.java |     3 +-
 .../azureus2/plugins/utils/LocaleListener.java     |     5 +-
 .../azureus2/plugins/utils/LocaleUtilities.java    |     3 +-
 .../azureus2/plugins/utils/LocationProvider.java   |    15 +-
 .../plugins/utils/LocationProviderListener.java    |    15 +-
 .../org/gudy/azureus2/plugins/utils/Monitor.java   |     5 +-
 .../azureus2/plugins/utils/PooledByteBuffer.java   |     5 +-
 .../plugins/utils/PowerManagementListener.java     |    17 +-
 .../org/gudy/azureus2/plugins/utils/Semaphore.java |     3 +-
 .../org/gudy/azureus2/plugins/utils/ShortCuts.java |     5 +-
 .../azureus2/plugins/utils/StaticUtilities.java    |     9 +-
 .../org/gudy/azureus2/plugins/utils/UTTimer.java   |     5 +-
 .../gudy/azureus2/plugins/utils/UTTimerEvent.java  |     5 +-
 .../plugins/utils/UTTimerEventPerformer.java       |     5 +-
 .../org/gudy/azureus2/plugins/utils/Utilities.java |    40 +-
 .../resourcedownloader/ResourceDownloader.java     |     3 +-
 .../ResourceDownloaderAdapter.java                 |     5 +-
 .../ResourceDownloaderCancelledException.java      |     5 +-
 .../ResourceDownloaderDelayedFactory.java          |     5 +-
 .../ResourceDownloaderException.java               |    19 +-
 .../ResourceDownloaderFactory.java                 |     3 +-
 .../ResourceDownloaderListener.java                |     3 +-
 .../utils/resourceuploader/ResourceUploader.java   |     5 +-
 .../ResourceUploaderException.java                 |     5 +-
 .../resourceuploader/ResourceUploaderFactory.java  |     5 +-
 .../gudy/azureus2/plugins/utils/search/Search.java |    63 +-
 .../plugins/utils/search/SearchException.java      |    83 +-
 .../plugins/utils/search/SearchInitiator.java      |   113 +-
 .../plugins/utils/search/SearchInstance.java       |    57 +-
 .../plugins/utils/search/SearchListener.java       |    65 +-
 .../plugins/utils/search/SearchObserver.java       |    85 +-
 .../plugins/utils/search/SearchProvider.java       |   118 +-
 .../utils/search/SearchProviderResults.java        |    75 +-
 .../plugins/utils/search/SearchResult.java         |   115 +-
 .../utils/security/CertificateListener.java        |     5 +-
 .../plugins/utils/security/PasswordListener.java   |     5 +-
 .../plugins/utils/security/SEPublicKey.java        |     5 +-
 .../plugins/utils/security/SEPublicKeyLocator.java |     5 +-
 .../plugins/utils/security/SESecurityManager.java  |     5 +-
 .../plugins/utils/subscriptions/Subscription.java  |    75 +-
 .../utils/subscriptions/SubscriptionException.java |    83 +-
 .../utils/subscriptions/SubscriptionManager.java   |    63 +-
 .../utils/subscriptions/SubscriptionResult.java    |    79 +-
 .../azureus2/plugins/utils/xml/rss/RSSChannel.java |     5 +-
 .../azureus2/plugins/utils/xml/rss/RSSFeed.java    |     5 +-
 .../azureus2/plugins/utils/xml/rss/RSSItem.java    |     5 +-
 .../xml/simpleparser/SimpleXMLParserDocument.java  |     5 +-
 .../SimpleXMLParserDocumentAttribute.java          |     5 +-
 .../SimpleXMLParserDocumentException.java          |     5 +-
 .../SimpleXMLParserDocumentFactory.java            |    19 +-
 .../simpleparser/SimpleXMLParserDocumentNode.java  |     5 +-
 .../org/gudy/azureus2/pluginsimpl/PluginUtils.java |     5 +-
 .../azureus2/pluginsimpl/local/FailedPlugin.java   |     8 +-
 .../pluginsimpl/local/PluginConfigImpl.java        |     3 +-
 .../pluginsimpl/local/PluginCoreUtils.java         |    15 +-
 .../pluginsimpl/local/PluginInitializer.java       |    25 +-
 .../pluginsimpl/local/PluginInterfaceImpl.java     |     3 +-
 .../local/PluginManagerDefaultsImpl.java           |     5 +-
 .../pluginsimpl/local/PluginManagerImpl.java       |     8 +-
 .../local/clientid/ClientIDManagerImpl.java        |   202 +-
 .../local/config/ConfigParameterImpl.java          |     5 +-
 .../local/config/PluginConfigSourceImpl.java       |     5 +-
 .../pluginsimpl/local/ddb/DDBaseContactImpl.java   |    12 +-
 .../pluginsimpl/local/ddb/DDBaseHelpers.java       |     5 +-
 .../azureus2/pluginsimpl/local/ddb/DDBaseImpl.java |   248 +-
 .../pluginsimpl/local/ddb/DDBaseKeyImpl.java       |     5 +-
 .../pluginsimpl/local/ddb/DDBaseTTTorrent.java     |     7 +-
 .../pluginsimpl/local/ddb/DDBaseValueImpl.java     |     5 +-
 .../local/deprecate/PluginDeprecation.java         |     2 +-
 .../deprecate/PluginDeprecationException.java      |     2 +-
 .../local/dht/mainline/MainlineDHTManagerImpl.java |     5 +-
 .../local/disk/DiskManagerChannelImpl.java         |    59 +-
 .../local/disk/DiskManagerFileInfoImpl.java        |     8 +-
 .../pluginsimpl/local/disk/DiskManagerImpl.java    |     3 +-
 .../disk/DiskManagerRandomReadController.java      |    17 +-
 .../local/download/DownloadAnnounceResultImpl.java |     3 +-
 .../local/download/DownloadEventNotifierImpl.java  |     5 +-
 .../pluginsimpl/local/download/DownloadImpl.java   |    38 +-
 .../local/download/DownloadManagerImpl.java        |   195 +-
 .../local/download/DownloadManagerStatsImpl.java   |    17 +-
 .../local/download/DownloadScrapeResultImpl.java   |     3 +-
 .../local/download/DownloadStatsImpl.java          |     7 +-
 .../local/download/DownloadStubImpl.java           |   499 +-
 .../local/installer/FilePluginInstallerImpl.java   |     6 +-
 .../local/installer/InstallablePluginImpl.java     |     5 +-
 .../local/installer/PluginInstallerImpl.java       |    54 +-
 .../local/installer/StandardPluginImpl.java        |     5 +-
 .../pluginsimpl/local/ipc/IPCInterfaceImpl.java    |     5 +-
 .../pluginsimpl/local/ipfilter/IPBannedImpl.java   |     8 +-
 .../pluginsimpl/local/ipfilter/IPBlockedImpl.java  |     3 +-
 .../pluginsimpl/local/ipfilter/IPFilterImpl.java   |     3 +-
 .../pluginsimpl/local/ipfilter/IPRangeImpl.java    |     3 +-
 .../local/launch/PluginLauncherImpl.java           |     5 +-
 .../local/launch/PluginSingleInstanceHandler.java  |     5 +-
 .../local/logging/LoggerChannelImpl.java           |     3 +-
 .../pluginsimpl/local/logging/LoggerImpl.java      |     3 +-
 .../local/messaging/GenericMessage.java            |     5 +-
 .../messaging/GenericMessageConnectionAdapter.java |     5 +-
 .../messaging/GenericMessageConnectionDirect.java  |    28 +-
 .../messaging/GenericMessageConnectionImpl.java    |     5 +-
 .../GenericMessageConnectionIndirect.java          |     5 +-
 .../local/messaging/GenericMessageDecoder.java     |     5 +-
 .../local/messaging/GenericMessageEncoder.java     |     5 +-
 .../messaging/GenericMessageEndpointImpl.java      |     5 +-
 .../local/messaging/MessageAdapter.java            |     5 +-
 .../local/messaging/MessageManagerImpl.java        |     5 +-
 .../messaging/MessageStreamDecoderAdapter.java     |     5 +-
 .../messaging/MessageStreamEncoderAdapter.java     |     5 +-
 .../pluginsimpl/local/network/ConnectionImpl.java  |     7 +-
 .../local/network/ConnectionManagerImpl.java       |     5 +-
 .../local/network/IncomingMessageQueueImpl.java    |     5 +-
 .../local/network/OutgoingMessageQueueImpl.java    |     5 +-
 .../local/network/RawMessageAdapter.java           |     5 +-
 .../pluginsimpl/local/network/TransportImpl.java   |     5 +-
 .../local/peers/PeerForeignDelegate.java           |   129 +-
 .../local/peers/PeerForeignNetworkConnection.java  |    16 +-
 .../azureus2/pluginsimpl/local/peers/PeerImpl.java |   147 +-
 .../pluginsimpl/local/peers/PeerManagerImpl.java   |   107 +-
 .../local/peers/PeerManagerStatsImpl.java          |     5 +-
 .../pluginsimpl/local/peers/PeerStatsImpl.java     |     3 +-
 .../pluginsimpl/local/sharing/ShareConfigImpl.java |     3 +-
 .../pluginsimpl/local/sharing/ShareItemImpl.java   |     3 +-
 .../local/sharing/ShareManagerImpl.java            |    27 +-
 .../sharing/ShareResourceDirContentsImpl.java      |    37 +-
 .../local/sharing/ShareResourceDirImpl.java        |     8 +-
 .../local/sharing/ShareResourceFileImpl.java       |     8 +-
 .../local/sharing/ShareResourceFileOrDirImpl.java  |    32 +-
 .../local/sharing/ShareResourceImpl.java           |     3 +-
 .../local/torrent/BaseTorrentAttributeImpl.java    |     5 +-
 .../local/torrent/TorrentAnnounceURLListImpl.java  |     3 +-
 .../torrent/TorrentAnnounceURLListSetImpl.java     |     3 +-
 .../torrent/TorrentAttributeCategoryImpl.java      |     5 +-
 .../torrent/TorrentAttributeDisplayNameImpl.java   |     5 +-
 .../torrent/TorrentAttributeNetworksImpl.java      |     5 +-
 .../torrent/TorrentAttributePeerSourcesImpl.java   |     5 +-
 .../local/torrent/TorrentAttributePluginImpl.java  |     5 +-
 .../TorrentAttributeRelativeSavePathImpl.java      |     5 +-
 .../TorrentAttributeSharePropertiesImpl.java       |     5 +-
 .../TorrentAttributeTrackerClientExtImpl.java      |     5 +-
 .../torrent/TorrentAttributeUserCommentImpl.java   |     5 +-
 .../local/torrent/TorrentDownloaderImpl.java       |     3 +-
 .../pluginsimpl/local/torrent/TorrentFileImpl.java |     3 +-
 .../pluginsimpl/local/torrent/TorrentImpl.java     |     3 +-
 .../local/torrent/TorrentManagerImpl.java          |     3 +-
 .../pluginsimpl/local/tracker/TrackerImpl.java     |    22 +-
 .../pluginsimpl/local/tracker/TrackerPeerImpl.java |     3 +-
 .../local/tracker/TrackerTorrentImpl.java          |     3 +-
 .../local/tracker/TrackerTorrentRequestImpl.java   |     3 +-
 .../pluginsimpl/local/tracker/TrackerWCHelper.java |     5 +-
 .../local/tracker/TrackerWebContextImpl.java       |    18 +-
 .../local/tracker/TrackerWebPageRequestImpl.java   |     9 +-
 .../local/tracker/TrackerWebPageResponseImpl.java  |     9 +-
 .../local/ui/AbstractUIInputReceiver.java          |     5 +-
 .../pluginsimpl/local/ui/AbstractUIMessage.java    |     5 +-
 .../local/ui/UIManagerEventAdapter.java            |     5 +-
 .../pluginsimpl/local/ui/UIManagerImpl.java        |    15 +-
 .../local/ui/components/UIComponentImpl.java       |    16 +-
 .../local/ui/components/UIProgressBarImpl.java     |     5 +-
 .../local/ui/components/UITextAreaImpl.java        |     5 +-
 .../local/ui/components/UITextFieldImpl.java       |     5 +-
 .../local/ui/config/ActionParameterImpl.java       |     5 +-
 .../local/ui/config/BooleanParameterImpl.java      |     3 +-
 .../local/ui/config/ColorParameter.java            |     3 +-
 .../local/ui/config/ColorParameterImpl.java        |     5 +-
 .../local/ui/config/ConfigSectionHolder.java       |    17 +-
 .../local/ui/config/ConfigSectionRepository.java   |     3 +-
 .../local/ui/config/DirectoryParameterImpl.java    |     3 +-
 .../pluginsimpl/local/ui/config/FileParameter.java |     3 +-
 .../local/ui/config/InfoParameterImpl.java         |     5 +-
 .../local/ui/config/IntParameterImpl.java          |     3 +-
 .../pluginsimpl/local/ui/config/IntsParameter.java |     3 +-
 .../local/ui/config/LabelParameterImpl.java        |     5 +-
 .../local/ui/config/ParameterGroupImpl.java        |    68 +-
 .../pluginsimpl/local/ui/config/ParameterImpl.java |     3 +-
 .../local/ui/config/ParameterImplListener.java     |     5 +-
 .../local/ui/config/ParameterRepository.java       |     3 +-
 .../local/ui/config/ParameterTabFolderImpl.java    |    61 +
 .../local/ui/config/PasswordParameterImpl.java     |     5 +-
 .../local/ui/config/PluginConfigUIFactoryImpl.java |     3 +-
 .../local/ui/config/StringListParameterImpl.java   |     3 +-
 .../local/ui/config/StringParameterImpl.java       |     3 +-
 .../local/ui/config/UIParameterImpl.java           |     5 +-
 .../local/ui/config/UITextAreaImpl.java            |   136 +
 .../local/ui/menus/MenuContextImpl.java            |     2 +-
 .../pluginsimpl/local/ui/menus/MenuItemImpl.java   |    29 +-
 .../local/ui/menus/MenuManagerImpl.java            |     5 +-
 .../local/ui/model/BasicPluginConfigModelImpl.java |    41 +-
 .../local/ui/model/BasicPluginViewModelImpl.java   |     5 +-
 .../local/ui/tables/TableContextMenuItemImpl.java  |     3 +-
 .../local/ui/tables/TableManagerImpl.java          |     3 -
 .../local/update/UpdatableComponentImpl.java       |     5 +-
 .../local/update/UpdateCheckInstanceImpl.java      |     8 +-
 .../local/update/UpdateCheckerImpl.java            |    11 +-
 .../pluginsimpl/local/update/UpdateImpl.java       |    14 +-
 .../local/update/UpdateInstallerImpl.java          |     5 +-
 .../local/update/UpdateManagerImpl.java            |     5 +-
 .../pluginsimpl/local/utils/FormattersImpl.java    |     3 +-
 .../pluginsimpl/local/utils/LocaleDecoderImpl.java |     3 +-
 .../local/utils/LocaleUtilitiesImpl.java           |     3 +-
 .../pluginsimpl/local/utils/MonitorImpl.java       |     5 +-
 .../local/utils/PooledByteBufferImpl.java          |     5 +-
 .../pluginsimpl/local/utils/SemaphoreImpl.java     |     3 +-
 .../pluginsimpl/local/utils/ShortCutsImpl.java     |     5 +-
 .../pluginsimpl/local/utils/UTTimerImpl.java       |     5 +-
 .../pluginsimpl/local/utils/UtilitiesImpl.java     |   346 +-
 .../ResourceDownloaderAlternateImpl.java           |     5 +-
 .../ResourceDownloaderBaseImpl.java                |     3 +-
 .../ResourceDownloaderDelayedImpl.java             |     5 +-
 .../ResourceDownloaderErrorImpl.java               |     5 +-
 .../ResourceDownloaderFactoryImpl.java             |     5 +-
 .../ResourceDownloaderFileImpl.java                |     5 +-
 .../ResourceDownloaderMetaRefreshImpl.java         |     5 +-
 .../ResourceDownloaderRetryImpl.java               |     5 +-
 .../ResourceDownloaderTimeoutImpl.java             |     5 +-
 .../ResourceDownloaderTorrentImpl.java             |     5 +-
 .../ResourceDownloaderURLImpl.java                 |   184 +-
 .../ResourceUploaderFactoryImpl.java               |     5 +-
 .../resourceuploader/ResourceUploaderURLImpl.java  |     5 +-
 .../local/utils/security/SEPublicKeyImpl.java      |     5 +-
 .../local/utils/security/SESTSConnectionImpl.java  |     9 +-
 .../utils/security/SESecurityManagerImpl.java      |     5 +-
 .../local/utils/xml/rss/RSSChannelImpl.java        |     5 +-
 .../local/utils/xml/rss/RSSFeedImpl.java           |    12 +-
 .../local/utils/xml/rss/RSSItemImpl.java           |    33 +-
 .../pluginsimpl/local/utils/xml/rss/RSSUtils.java  |    57 +-
 .../SimpleXMLParserDocumentAttributeImpl.java      |     3 +-
 .../SimpleXMLParserDocumentFactoryImpl.java        |    18 +-
 .../simpleparser/SimpleXMLParserDocumentImpl.java  |   420 +-
 .../SimpleXMLParserDocumentNodeImpl.java           |     3 +-
 .../azureus2/pluginsimpl/remote/RPException.java   |     3 +-
 .../azureus2/pluginsimpl/remote/RPFactory.java     |     3 +-
 .../gudy/azureus2/pluginsimpl/remote/RPObject.java |     3 +-
 .../pluginsimpl/remote/RPPluginConfig.java         |     3 +-
 .../pluginsimpl/remote/RPPluginInterface.java      |     3 +-
 .../gudy/azureus2/pluginsimpl/remote/RPReply.java  |     3 +-
 .../azureus2/pluginsimpl/remote/RPRequest.java     |     3 +-
 .../remote/RPRequestAccessController.java          |     5 +-
 .../pluginsimpl/remote/RPRequestDispatcher.java    |     3 +-
 .../pluginsimpl/remote/RPRequestHandler.java       |     3 +-
 .../remote/disk/RPDiskManagerFileInfo.java         |     5 +-
 .../pluginsimpl/remote/download/RPDownload.java    |    17 +-
 .../remote/download/RPDownloadAnnounceResult.java  |     3 +-
 .../remote/download/RPDownloadManager.java         |    11 +-
 .../remote/download/RPDownloadScrapeResult.java    |     3 +-
 .../remote/download/RPDownloadStats.java           |    10 +-
 .../pluginsimpl/remote/ipfilter/RPIPFilter.java    |     3 +-
 .../pluginsimpl/remote/ipfilter/RPIPRange.java     |     5 +-
 .../rpexceptions/RPInternalProcessException.java   |     5 +-
 .../RPMethodAccessDeniedException.java             |     5 +-
 .../remote/rpexceptions/RPNoObjectIDException.java |     5 +-
 .../RPObjectNoLongerExistsException.java           |     5 +-
 .../rpexceptions/RPThrowableAsReplyException.java  |     5 +-
 .../pluginsimpl/remote/torrent/RPTorrent.java      |     3 +-
 .../remote/torrent/RPTorrentDownloader.java        |     3 +-
 .../remote/torrent/RPTorrentManager.java           |     3 +-
 .../pluginsimpl/remote/tracker/RPTracker.java      |    22 +-
 .../remote/tracker/RPTrackerTorrent.java           |     5 +-
 .../pluginsimpl/remote/utils/RPShortCuts.java      |     5 +-
 .../pluginsimpl/update/PluginUpdatePlugin.java     |    48 +-
 .../pluginsimpl/update/sf/SFPluginDetails.java     |     5 +-
 .../update/sf/SFPluginDetailsException.java        |     5 +-
 .../update/sf/SFPluginDetailsLoader.java           |     5 +-
 .../update/sf/SFPluginDetailsLoaderFactory.java    |     5 +-
 .../update/sf/SFPluginDetailsLoaderListener.java   |     5 +-
 .../update/sf/impl2/SFPluginDetailsImpl.java       |     5 +-
 .../update/sf/impl2/SFPluginDetailsLoaderImpl.java |     5 +-
 .../gudy/azureus2/ui/common/IUserInterface.java    |     5 +-
 .../gudy/azureus2/ui/common/UIImageRepository.java |     3 +-
 .../org/gudy/azureus2/ui/common/UITemplate.java    |     5 +-
 .../azureus2/ui/common/UserInterfaceFactory.java   |     5 +-
 .../azureus2/ui/common/util/MenuItemManager.java   |    21 +-
 .../ui/common/util/MenuItemManagerListener.java    |     6 +-
 .../src/org/gudy/azureus2/ui/icons/archive.png     |   Bin 0 -> 456 bytes
 .../src/org/gudy/azureus2/ui/icons/downarrow.png   |   Bin 0 -> 241 bytes
 .../org/gudy/azureus2/ui/icons/icons.properties    |    14 +
 .../src/org/gudy/azureus2/ui/icons/net_I2P_b.png   |   Bin 0 -> 793 bytes
 .../src/org/gudy/azureus2/ui/icons/net_I2P_s.png   |   Bin 0 -> 582 bytes
 .../src/org/gudy/azureus2/ui/icons/net_Tor_b.png   |   Bin 0 -> 611 bytes
 .../src/org/gudy/azureus2/ui/icons/net_Tor_s.png   |   Bin 0 -> 466 bytes
 .../src/org/gudy/azureus2/ui/icons/popout_win.png  |   Bin 0 -> 271 bytes
 .../azureus2/ui/icons/statusbar/dchat_gray.png     |   Bin 0 -> 499 bytes
 .../ui/icons/statusbar/dchat_gray_text.png         |   Bin 0 -> 1080 bytes
 .../azureus2/ui/icons/statusbar/dchat_green.png    |   Bin 0 -> 1082 bytes
 azureus2/src/org/gudy/azureus2/ui/none/Main.java   |    15 +-
 .../ui/none/internat/MessagesBundle.properties     |    32 +
 .../ui/none/internat/MessagesBundle_eu.properties  |    83 +
 .../none/internat/MessagesBundle_fr_FR.properties  |    80 +
 .../none/internat/MessagesBundle_pt_BR.properties  |    83 +
 .../azureus2/ui/swing/UISwingImageRepository.java  |     3 +-
 .../org/gudy/azureus2/ui/swt/AZProgressBar.java    |    18 +
 azureus2/src/org/gudy/azureus2/ui/swt/Alerts.java  |     5 +-
 .../org/gudy/azureus2/ui/swt/BlockedIpsWindow.java |     3 +-
 .../org/gudy/azureus2/ui/swt/BrowserWrapper.java   |   242 +
 .../gudy/azureus2/ui/swt/BrowserWrapperFake.java   |   499 +
 .../gudy/azureus2/ui/swt/BrowserWrapperSWT.java    |   345 +
 .../gudy/azureus2/ui/swt/CategoryAdderWindow.java  |     5 +-
 .../ui/swt/DelayedListenerMultiCombiner.java       |     6 +-
 .../gudy/azureus2/ui/swt/FileDownloadWindow.java   |    60 +-
 .../org/gudy/azureus2/ui/swt/ImageRepository.java  |    91 +-
 .../gudy/azureus2/ui/swt/ImageViewerWindow.java    |     5 +-
 .../src/org/gudy/azureus2/ui/swt/KeyBindings.java  |    47 +-
 .../org/gudy/azureus2/ui/swt/ListenerDMTask.java   |    92 +
 .../gudy/azureus2/ui/swt/ListenerGetOffSWT.java    |    47 +
 .../org/gudy/azureus2/ui/swt/LocaleUtilSWT.java    |     5 +-
 azureus2/src/org/gudy/azureus2/ui/swt/Main.java    |    11 +-
 .../org/gudy/azureus2/ui/swt/MenuBuildUtils.java   |   319 +-
 .../src/org/gudy/azureus2/ui/swt/Messages.java     |     8 +-
 .../gudy/azureus2/ui/swt/OpenTorrentWindow.java    |   124 +-
 .../org/gudy/azureus2/ui/swt/OpenUrlWindow.java    |     3 +-
 .../org/gudy/azureus2/ui/swt/PasswordWindow.java   |     5 +-
 .../org/gudy/azureus2/ui/swt/PropertiesWindow.java |     5 +-
 .../azureus2/ui/swt/SimpleTextEntryWindow.java     |    18 +-
 .../src/org/gudy/azureus2/ui/swt/StartServer.java  |    10 +-
 .../src/org/gudy/azureus2/ui/swt/StartSocket.java  |     5 +-
 .../org/gudy/azureus2/ui/swt/TextViewerWindow.java |     7 +-
 .../org/gudy/azureus2/ui/swt/TorrentMenuFancy.java |  2244 ++++
 .../src/org/gudy/azureus2/ui/swt/TorrentUtil.java  |  3432 ++---
 .../gudy/azureus2/ui/swt/TrackerChangerWindow.java |     5 +-
 .../src/org/gudy/azureus2/ui/swt/TrayWindow.java   |     7 +-
 .../gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java  |    25 +-
 .../org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java   |     5 +-
 .../gudy/azureus2/ui/swt/UISwitcherListener.java   |     5 +-
 .../org/gudy/azureus2/ui/swt/UISwitcherUtil.java   |     5 +-
 .../src/org/gudy/azureus2/ui/swt/URLTransfer.java  |     5 +-
 .../src/org/gudy/azureus2/ui/swt/UserAlerts.java   |    35 +-
 azureus2/src/org/gudy/azureus2/ui/swt/Utils.java   |  1003 +-
 .../ui/swt/associations/AssociationChecker.java    |     5 +-
 .../azureus2/ui/swt/auth/AuthenticatorWindow.java  |    21 +-
 .../ui/swt/auth/CertificateCreatorWindow.java      |     5 +-
 .../ui/swt/auth/CertificateTrustWindow.java        |     3 +-
 .../gudy/azureus2/ui/swt/auth/CryptoWindow.java    |     7 +-
 .../org/gudy/azureus2/ui/swt/beta/BetaWizard.java  |    17 +-
 .../gudy/azureus2/ui/swt/beta/BetaWizardStart.java |    17 +-
 .../swt/components/BufferedGraphicTableItem.java   |    49 -
 .../swt/components/BufferedGraphicTableItem1.java  |   193 -
 .../azureus2/ui/swt/components/BufferedLabel.java  |     5 +-
 .../ui/swt/components/BufferedTableItem.java       |   130 -
 .../ui/swt/components/BufferedTableItemImpl.java   |   352 -
 .../ui/swt/components/BufferedTableRow.java        |   834 --
 .../ui/swt/components/BufferedToolItem.java        |     3 +-
 .../ui/swt/components/BufferedTruncatedLabel.java  |     5 +-
 .../azureus2/ui/swt/components/BufferedWidget.java |     3 +-
 .../ui/swt/components/CompositeMinSize.java        |    18 +
 .../ui/swt/components/DoubleBufferedLabel.java     |    28 +-
 .../azureus2/ui/swt/components/InPaintInfo.java    |    40 -
 .../gudy/azureus2/ui/swt/components/Legend.java    |     5 +-
 .../gudy/azureus2/ui/swt/components/LinkArea.java  |     5 +-
 .../gudy/azureus2/ui/swt/components/LinkLabel.java |    10 +-
 .../ui/swt/components/StringListChooser.java       |     5 +-
 .../swt/components/graphics/BackGroundGraphic.java |     3 +-
 .../ui/swt/components/graphics/Graphic.java        |     3 +-
 .../swt/components/graphics/MultiPlotGraphic.java  |     3 +-
 .../ui/swt/components/graphics/PieUtils.java       |     8 +-
 .../ui/swt/components/graphics/PingGraphic.java    |     3 +-
 .../ui/swt/components/graphics/Plot3D.java         |     5 +-
 .../azureus2/ui/swt/components/graphics/Scale.java |     3 +-
 .../ui/swt/components/graphics/ScaledGraphic.java  |     3 +-
 .../ui/swt/components/graphics/SpeedGraphic.java   |     3 +-
 .../ui/swt/components/graphics/ValueFormater.java  |     3 +-
 .../ui/swt/components/graphics/ValueSource.java    |    15 +-
 .../ui/swt/components/shell/ShellFactory.java      |     5 +-
 .../ui/swt/components/shell/ShellManager.java      |     5 +-
 .../azureus2/ui/swt/config/BooleanParameter.java   |     5 +-
 .../azureus2/ui/swt/config/ButtonParameter.java    |    11 +-
 .../swt/config/ChangeSelectionActionPerformer.java |     3 +-
 .../azureus2/ui/swt/config/ColorParameter.java     |    51 +-
 .../ui/swt/config/ConfigParameterAdapter.java      |    13 +-
 .../azureus2/ui/swt/config/DirectoryParameter.java |     5 +-
 .../config/DualChangeSelectionActionPerformer.java |     3 +-
 .../config/ExclusiveSelectionActionPerformer.java  |     3 +-
 .../gudy/azureus2/ui/swt/config/FileParameter.java |     5 +-
 .../azureus2/ui/swt/config/FloatParameter.java     |     5 +-
 .../ui/swt/config/GenericActionPerformer.java      |     3 +-
 .../ui/swt/config/IAdditionalActionPerformer.java  |     3 +-
 .../gudy/azureus2/ui/swt/config/IParameter.java    |     3 +-
 .../gudy/azureus2/ui/swt/config/InfoParameter.java |     5 +-
 .../azureus2/ui/swt/config/IntListParameter.java   |     5 +-
 .../gudy/azureus2/ui/swt/config/IntParameter.java  |    12 +-
 .../azureus2/ui/swt/config/IpFilterEditor.java     |     3 +-
 .../gudy/azureus2/ui/swt/config/LinkParameter.java |     5 +-
 .../org/gudy/azureus2/ui/swt/config/Parameter.java |     9 +-
 .../ui/swt/config/ParameterChangeAdapter.java      |     5 +-
 .../ui/swt/config/ParameterChangeListener.java     |     5 +-
 .../azureus2/ui/swt/config/PasswordParameter.java  |     5 +-
 .../azureus2/ui/swt/config/RadioParameter.java     |     5 +-
 .../ui/swt/config/StringAreaParameter.java         |     5 +-
 .../ui/swt/config/StringListParameter.java         |     3 +-
 .../azureus2/ui/swt/config/StringParameter.java    |     5 +-
 .../azureus2/ui/swt/config/TextAreaParameter.java  |   190 +
 .../azureus2/ui/swt/config/UISWTParameter.java     |     7 +-
 .../config/generic/GenericBooleanParameter.java    |    16 +-
 .../swt/config/generic/GenericFloatParameter.java  |   153 +
 .../ui/swt/config/generic/GenericIntParameter.java |    32 +-
 .../config/generic/GenericParameterAdapter.java    |    20 +-
 .../swt/config/plugins/PluginBooleanParameter.java |     3 +-
 .../swt/config/plugins/PluginColorParameter.java   |     3 +-
 .../config/plugins/PluginDirectoryParameter.java   |     3 +-
 .../ui/swt/config/plugins/PluginFileParameter.java |     3 +-
 .../ui/swt/config/plugins/PluginIntParameter.java  |     3 +-
 .../ui/swt/config/plugins/PluginIntsParameter.java |     3 +-
 .../ui/swt/config/plugins/PluginParameter.java     |     3 +-
 .../ui/swt/config/plugins/PluginParameterImpl.java |     3 +-
 .../swt/config/plugins/PluginStringParameter.java  |     3 +-
 .../swt/config/plugins/PluginStringsParameter.java |     3 +-
 .../ui/swt/config/wizard/ConfigureWizard.java      |     3 +-
 .../azureus2/ui/swt/config/wizard/FilePanel.java   |     3 +-
 .../azureus2/ui/swt/config/wizard/FinishPanel.java |     3 +-
 .../ui/swt/config/wizard/LanguagePanel.java        |     5 +-
 .../azureus2/ui/swt/config/wizard/NatPanel.java    |     3 +-
 .../ui/swt/config/wizard/TransferPanel2.java       |     3 +-
 .../ui/swt/config/wizard/WelcomePanel.java         |     7 +-
 .../azureus2/ui/swt/debug/ObfusticateCellText.java |     5 +-
 .../azureus2/ui/swt/debug/ObfusticateImage.java    |     5 +-
 .../azureus2/ui/swt/debug/ObfusticateShell.java    |     5 +-
 .../gudy/azureus2/ui/swt/debug/ObfusticateTab.java |     5 +-
 .../azureus2/ui/swt/debug/UIDebugGenerator.java    |    21 +-
 .../azureus2/ui/swt/donations/DonationWindow.java  |   211 +-
 .../exporttorrent/wizard/ExportTorrentWizard.java  |     3 +-
 .../wizard/ExportTorrentWizardFinishPanel.java     |     3 +-
 .../wizard/ExportTorrentWizardInputPanel.java      |     3 +-
 .../wizard/ExportTorrentWizardOutputPanel.java     |     3 +-
 .../org/gudy/azureus2/ui/swt/help/AboutWindow.java |    52 +-
 .../azureus2/ui/swt/help/HealthHelpWindow.java     |     3 +-
 .../importtorrent/wizard/ImportTorrentWizard.java  |     3 +-
 .../wizard/ImportTorrentWizardFinishPanel.java     |     3 +-
 .../wizard/ImportTorrentWizardInputPanel.java      |     3 +-
 .../wizard/ImportTorrentWizardOutputPanel.java     |     3 +-
 .../ui/swt/ipchecker/ChooseServicePanel.java       |     3 +-
 .../azureus2/ui/swt/ipchecker/IpCheckerWizard.java |     3 +-
 .../ui/swt/ipchecker/IpSetterCallBack.java         |     3 +-
 .../azureus2/ui/swt/ipchecker/ProgressPanel.java   |     3 +-
 .../azureus2/ui/swt/mainwindow/ClipboardCopy.java  |    71 +-
 .../gudy/azureus2/ui/swt/mainwindow/Colors.java    |     8 +-
 .../ui/swt/mainwindow/DebugMenuHelper.java         |    18 +
 .../gudy/azureus2/ui/swt/mainwindow/HSLColor.java  |     5 +-
 .../gudy/azureus2/ui/swt/mainwindow/IMainMenu.java |    18 +
 .../azureus2/ui/swt/mainwindow/IMainStatusBar.java |    17 +-
 .../azureus2/ui/swt/mainwindow/IMainWindow.java    |    18 +
 .../azureus2/ui/swt/mainwindow/IMenuConstants.java |    24 +
 .../swt/mainwindow/ListenerNeedingCoreRunning.java |    18 +
 .../gudy/azureus2/ui/swt/mainwindow/MainMenu.java  |    11 +-
 .../azureus2/ui/swt/mainwindow/MainStatusBar.java  |   394 +-
 .../azureus2/ui/swt/mainwindow/MenuFactory.java    |   330 +-
 .../ui/swt/mainwindow/PluginsMenuHelper.java       |    62 +-
 .../gudy/azureus2/ui/swt/mainwindow/SWTThread.java |     7 +-
 .../SWTThreadAlreadyInstanciatedException.java     |     5 +-
 .../ui/swt/mainwindow/SelectableSpeedMenu.java     |   143 +-
 .../azureus2/ui/swt/mainwindow/SplashWindow.java   |     5 +-
 .../ui/swt/mainwindow/SystemWarningWindow.java     |     6 +-
 .../azureus2/ui/swt/mainwindow/TorrentOpener.java  |   126 +-
 .../gudy/azureus2/ui/swt/maketorrent/BYOPanel.java |    20 +-
 .../ui/swt/maketorrent/DirectoryPanel.java         |     3 +-
 .../azureus2/ui/swt/maketorrent/ModePanel.java     |     3 +-
 .../ui/swt/maketorrent/MultiTrackerEditor.java     |     5 +-
 .../ui/swt/maketorrent/MultiTrackerPanel.java      |     3 +-
 .../ui/swt/maketorrent/NewTorrentWizard.java       |    39 +-
 .../azureus2/ui/swt/maketorrent/ProgressPanel.java |   150 +-
 .../azureus2/ui/swt/maketorrent/SavePathPanel.java |    90 +-
 .../ui/swt/maketorrent/SingleFilePanel.java        |     3 +-
 .../ui/swt/maketorrent/TrackerEditorListener.java  |     3 +-
 .../azureus2/ui/swt/maketorrent/WebSeedPanel.java  |     3 +-
 .../ui/swt/maketorrent/WebSeedsEditor.java         |     9 +-
 .../ui/swt/maketorrent/WebSeedsEditorListener.java |     3 +-
 .../azureus2/ui/swt/minibar/AllTransfersBar.java   |     5 +-
 .../gudy/azureus2/ui/swt/minibar/DownloadBar.java  |    17 +-
 .../org/gudy/azureus2/ui/swt/minibar/MiniBar.java  |    21 +-
 .../azureus2/ui/swt/minibar/MiniBarManager.java    |     5 +-
 .../gudy/azureus2/ui/swt/nat/NatTestWindow.java    |     8 +-
 .../ui/swt/networks/SWTNetworkSelection.java       |     5 +-
 .../gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java |     4 +-
 .../gudy/azureus2/ui/swt/osx/CocoaUIEnhancer.java  |    48 +-
 .../org/gudy/azureus2/ui/swt/osx/OSXFileOpen.java  |    18 +
 .../src/org/gudy/azureus2/ui/swt/osx/Start.java    |     5 +-
 .../ui/swt/plugins/PluginUISWTSkinObject.java      |    18 +
 .../ui/swt/plugins/UISWTConfigSection.java         |     5 +-
 .../gudy/azureus2/ui/swt/plugins/UISWTGraphic.java |     8 +-
 .../ui/swt/plugins/UISWTInputReceiver.java         |     5 +-
 .../azureus2/ui/swt/plugins/UISWTInstance.java     |    16 +-
 .../ui/swt/plugins/UISWTParameterContext.java      |     5 +-
 .../azureus2/ui/swt/plugins/UISWTStatusEntry.java  |     5 +-
 .../ui/swt/plugins/UISWTStatusEntryListener.java   |     5 +-
 .../gudy/azureus2/ui/swt/plugins/UISWTView.java    |    39 +-
 .../azureus2/ui/swt/plugins/UISWTViewEvent.java    |    20 +-
 .../ui/swt/plugins/UISWTViewEventListener.java     |     8 +-
 .../pluginsimpl/AbstractUISWTInputReceiver.java    |    14 +-
 .../ui/swt/pluginsimpl/BasicPluginConfigImpl.java  |   230 +-
 .../ui/swt/pluginsimpl/BasicPluginViewImpl.java    |    39 +-
 .../azureus2/ui/swt/pluginsimpl/UIMessageImpl.java |     5 +-
 .../ui/swt/pluginsimpl/UISWTGraphicImpl.java       |     8 +-
 .../ui/swt/pluginsimpl/UISWTInstanceImpl.java      |    47 +-
 .../ui/swt/pluginsimpl/UISWTStatusEntryImpl.java   |    23 +-
 .../azureus2/ui/swt/pluginsimpl/UISWTViewCore.java |    25 +-
 .../pluginsimpl/UISWTViewCoreEventListener.java    |     6 +-
 .../pluginsimpl/UISWTViewCoreEventListenerEx.java  |    34 +
 .../UISWTViewEventCancelledException.java          |     6 +-
 .../ui/swt/pluginsimpl/UISWTViewEventImpl.java     |     8 +-
 .../pluginsimpl/UISWTViewEventListenerHolder.java  |    23 +-
 .../azureus2/ui/swt/pluginsimpl/UISWTViewImpl.java |   825 +-
 .../ui/swt/pluginsimpl/UIToolBarItemImpl.java      |   181 +
 .../ui/swt/pluginsimpl/UIToolBarManagerCore.java   |    34 +
 .../ui/swt/pluginsimpl/UIToolBarManagerImpl.java   |   189 +
 .../ui/swt/pluginsinstaller/IPWFilePanel.java      |    16 +-
 .../ui/swt/pluginsinstaller/IPWFinishPanel.java    |     8 +-
 .../swt/pluginsinstaller/IPWInstallModePanel.java  |     8 +-
 .../ui/swt/pluginsinstaller/IPWListPanel.java      |     8 +-
 .../ui/swt/pluginsinstaller/IPWModePanel.java      |     8 +-
 .../swt/pluginsinstaller/InstallPluginWizard.java  |     8 +-
 .../ui/swt/pluginsuninstaller/UIPWFinishPanel.java |     8 +-
 .../ui/swt/pluginsuninstaller/UIPWListPanel.java   |     8 +-
 .../pluginsuninstaller/UnInstallPluginWizard.java  |     8 +-
 .../gudy/azureus2/ui/swt/progress/IMessage.java    |    18 +
 .../azureus2/ui/swt/progress/IProgressReport.java  |    21 +
 .../ui/swt/progress/IProgressReportConstants.java  |    18 +
 .../ui/swt/progress/IProgressReporter.java         |    22 +
 .../ui/swt/progress/IProgressReporterListener.java |    18 +
 .../swt/progress/IProgressReportingListener.java   |    18 +
 .../ui/swt/progress/ProgressReportMessage.java     |    18 +
 .../azureus2/ui/swt/progress/ProgressReporter.java |    29 +
 .../ui/swt/progress/ProgressReporterPanel.java     |    36 +-
 .../ui/swt/progress/ProgressReporterStack.java     |    18 +
 .../ui/swt/progress/ProgressReporterWindow.java    |    18 +
 .../ui/swt/progress/ProgressReportingManager.java  |    18 +
 .../azureus2/ui/swt/progress/ProgressWindow.java   |     5 +-
 .../gudy/azureus2/ui/swt/sharing/ShareUtils.java   |     3 +-
 .../ui/swt/sharing/progress/ProgressWindow.java    |     3 +-
 .../azureus2/ui/swt/shells/AbstractWizardPage.java |    18 +
 .../azureus2/ui/swt/shells/AdvRenameWindow.java    |    44 +-
 .../gudy/azureus2/ui/swt/shells/BrowserShell.java  |   109 +-
 .../gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java |    18 +
 .../gudy/azureus2/ui/swt/shells/DockPosition.java  |    19 +-
 .../azureus2/ui/swt/shells/GCStringPrinter.java    |     3 +-
 .../gudy/azureus2/ui/swt/shells/IWizardPage.java   |    18 +
 .../azureus2/ui/swt/shells/MessageBoxShell.java    |    28 +-
 .../azureus2/ui/swt/shells/MessageSlideShell.java  |     5 +-
 .../azureus2/ui/swt/shells/MultipageWizard.java    |    18 +
 .../org/gudy/azureus2/ui/swt/shells/Offset.java    |    18 +
 .../gudy/azureus2/ui/swt/shells/PopupShell.java    |     3 +-
 .../gudy/azureus2/ui/swt/shells/ShellDocker.java   |    18 +
 .../gudy/azureus2/ui/swt/shells/ShellFader.java    |    18 +
 .../gudy/azureus2/ui/swt/shells/ShellSlider.java   |    18 +
 .../ui/swt/shells/SimpleBrowserWindow.java         |    11 +-
 .../azureus2/ui/swt/shells/SpeedScaleShell.java    |   100 +-
 .../azureus2/ui/swt/speedtest/SpeedTestData.java   |     5 +-
 .../ui/swt/speedtest/SpeedTestFinishPanel.java     |     5 +-
 .../azureus2/ui/swt/speedtest/SpeedTestPanel.java  |     5 +-
 .../ui/swt/speedtest/SpeedTestSelector.java        |    30 +-
 .../ui/swt/speedtest/SpeedTestSetLimitPanel.java   |     5 +-
 .../azureus2/ui/swt/speedtest/SpeedTestWizard.java |     5 +-
 .../azureus2/ui/swt/twistie/ITwistieConstants.java |    18 +
 .../azureus2/ui/swt/twistie/ITwistieListener.java  |    18 +
 .../gudy/azureus2/ui/swt/twistie/TwistieLabel.java |    19 +-
 .../azureus2/ui/swt/twistie/TwistieSection.java    |    18 +
 .../azureus2/ui/swt/update/FullUpdateWindow.java   |   201 +-
 .../azureus2/ui/swt/update/SilentInstallUI.java    |   213 +-
 .../azureus2/ui/swt/update/SimpleInstallUI.java    |   581 +-
 .../ui/swt/update/UpdateAutoDownloader.java        |     5 +-
 .../gudy/azureus2/ui/swt/update/UpdateMonitor.java |    24 +-
 .../ui/swt/update/UpdateProgressWindow.java        |     5 +-
 .../gudy/azureus2/ui/swt/update/UpdateWindow.java  |    50 +-
 .../azureus2/ui/swt/updater2/PreUpdateChecker.java |     5 +-
 .../azureus2/ui/swt/updater2/SWTUpdateChecker.java |     9 +-
 .../azureus2/ui/swt/updater2/SWTVersionGetter.java |     8 +-
 .../azureus2/ui/swt/views/ArchivedFilesView.java   |   274 +
 .../gudy/azureus2/ui/swt/views/ConfigShell.java    |    36 +-
 .../org/gudy/azureus2/ui/swt/views/ConfigView.java |   201 +-
 .../ui/swt/views/DownloadActivityView.java         |   124 +-
 .../org/gudy/azureus2/ui/swt/views/FilesView.java  |   259 +-
 .../azureus2/ui/swt/views/FilesViewMenuUtil.java   |   198 +-
 .../gudy/azureus2/ui/swt/views/GeneralView.java    |   143 +-
 .../ui/swt/views/IViewAlwaysInitialize.java        |     6 +-
 .../org/gudy/azureus2/ui/swt/views/LoggerView.java |    54 +-
 .../gudy/azureus2/ui/swt/views/MySharesView.java   |    18 +-
 .../azureus2/ui/swt/views/MyTorrentsSubView.java   |    45 +
 .../azureus2/ui/swt/views/MyTorrentsSuperView.java |   101 +-
 .../gudy/azureus2/ui/swt/views/MyTorrentsView.java |  1244 +-
 .../gudy/azureus2/ui/swt/views/MyTrackerView.java  |    20 +-
 .../azureus2/ui/swt/views/PeersGeneralView.java    |    25 +-
 .../azureus2/ui/swt/views/PeersGraphicView.java    |   105 +-
 .../gudy/azureus2/ui/swt/views/PeersSuperView.java |    32 +-
 .../org/gudy/azureus2/ui/swt/views/PeersView.java  |   153 +-
 .../ui/swt/views/PieceDistributionView.java        |     5 +-
 .../org/gudy/azureus2/ui/swt/views/PiecesView.java |   149 +-
 .../gudy/azureus2/ui/swt/views/ScrapeInfoView.java |    29 +-
 .../azureus2/ui/swt/views/TagSettingsView.java     |   796 ++
 .../gudy/azureus2/ui/swt/views/TaggingView.java    |   485 +
 .../azureus2/ui/swt/views/TorrentInfoView.java     |    34 +-
 .../azureus2/ui/swt/views/TorrentOptionsView.java  |   103 +-
 .../azureus2/ui/swt/views/TrackerAvailView.java    |   189 +
 .../gudy/azureus2/ui/swt/views/TrackerView.java    |   146 +-
 .../org/gudy/azureus2/ui/swt/views/ViewUtils.java  |   440 +-
 .../views/clientstats/ClientStatsDataSource.java   |    24 +
 .../swt/views/clientstats/ClientStatsOverall.java  |     6 +-
 .../ui/swt/views/clientstats/ClientStatsView.java  |   291 +-
 .../ui/swt/views/clientstats/ColumnCS_Count.java   |    42 +
 .../swt/views/clientstats/ColumnCS_Discarded.java  |    41 +
 .../ui/swt/views/clientstats/ColumnCS_Name.java    |    18 +
 .../ui/swt/views/clientstats/ColumnCS_Pct.java     |    18 +
 .../swt/views/clientstats/ColumnCS_Received.java   |    41 +
 .../views/clientstats/ColumnCS_ReceivedPer.java    |    20 +-
 .../ui/swt/views/clientstats/ColumnCS_Sent.java    |    42 +
 .../views/columnsetup/ColumnTC_ChosenColumn.java   |     9 +-
 .../ui/swt/views/columnsetup/ColumnTC_Info.java    |     6 +-
 .../swt/views/columnsetup/ColumnTC_NameInfo.java   |     6 +-
 .../ui/swt/views/columnsetup/ColumnTC_Sample.java  |     6 +-
 .../views/columnsetup/TableColumnSetupWindow.java  |    32 +-
 .../configsections/ConfigSectionBackupRestore.java |    12 +-
 .../configsections/ConfigSectionConnection.java    |    10 +-
 .../ConfigSectionConnectionAdvanced.java           |     8 +-
 .../configsections/ConfigSectionConnectionDNS.java |     8 +-
 .../ConfigSectionConnectionEncryption.java         |     8 +-
 .../ConfigSectionConnectionProxy.java              |    37 +-
 .../views/configsections/ConfigSectionFile.java    |   152 +-
 .../configsections/ConfigSectionFileMove.java      |     8 +-
 .../ConfigSectionFilePerformance.java              |     8 +-
 .../configsections/ConfigSectionFileTorrents.java  |    18 +-
 .../ConfigSectionFileTorrentsDecoding.java         |     8 +-
 .../configsections/ConfigSectionIPFilter.java      |     8 +-
 .../configsections/ConfigSectionInterface.java     |     8 +-
 .../ConfigSectionInterfaceAlerts.java              |     8 +-
 .../ConfigSectionInterfaceColor.java               |    12 +-
 .../ConfigSectionInterfaceDisplay.java             |   127 +-
 .../ConfigSectionInterfaceLanguage.java            |     5 +-
 .../ConfigSectionInterfaceLegacy.java              |     6 +-
 .../ConfigSectionInterfacePassword.java            |     8 +-
 .../ConfigSectionInterfaceStart.java               |     8 +-
 .../ConfigSectionInterfaceTables.java              |   389 +-
 .../views/configsections/ConfigSectionLogging.java |     8 +-
 .../views/configsections/ConfigSectionMode.java    |    12 +-
 .../views/configsections/ConfigSectionPlugins.java |    10 +-
 .../configsections/ConfigSectionSecurity.java      |     8 +-
 .../views/configsections/ConfigSectionSharing.java |     8 +-
 .../configsections/ConfigSectionStartShutdown.java |   244 +-
 .../views/configsections/ConfigSectionStats.java   |    12 +-
 .../views/configsections/ConfigSectionTracker.java |     8 +-
 .../configsections/ConfigSectionTrackerClient.java |     8 +-
 .../configsections/ConfigSectionTrackerServer.java |    12 +-
 .../configsections/ConfigSectionTransfer.java      |    24 +-
 .../ConfigSectionTransferAutoSpeed.java            |     8 +-
 .../ConfigSectionTransferAutoSpeedBeta.java        |     5 +-
 .../ConfigSectionTransferAutoSpeedSelect.java      |     8 +-
 .../configsections/ConfigSectionTransferLAN.java   |     8 +-
 .../azureus2/ui/swt/views/file/FileInfoView.java   |    55 +-
 .../azureus2/ui/swt/views/peer/PeerFilesView.java  |     8 +-
 .../azureus2/ui/swt/views/peer/PeerInfoView.java   |    20 +-
 .../views/peer/RemotePieceDistributionView.java    |    17 +-
 .../swt/views/piece/MyPieceDistributionView.java   |    20 +-
 .../azureus2/ui/swt/views/piece/PieceInfoView.java |    65 +-
 .../azureus2/ui/swt/views/stats/ActivityView.java  |     8 +-
 .../azureus2/ui/swt/views/stats/CacheView.java     |     5 +-
 .../azureus2/ui/swt/views/stats/DHTOpsPanel.java   |    21 +-
 .../azureus2/ui/swt/views/stats/DHTOpsView.java    |    51 +-
 .../gudy/azureus2/ui/swt/views/stats/DHTView.java  |    70 +-
 .../azureus2/ui/swt/views/stats/StatsView.java     |   342 +-
 .../azureus2/ui/swt/views/stats/TagStatsView.java  |  1247 +-
 .../ui/swt/views/stats/TransferStatsView.java      |    11 +-
 .../azureus2/ui/swt/views/stats/VivaldiPanel.java  |     8 +-
 .../azureus2/ui/swt/views/stats/VivaldiView.java   |     8 +-
 .../ui/swt/views/table/CoreTableColumnSWT.java     |    15 +-
 .../azureus2/ui/swt/views/table/TableCellSWT.java  |    11 +-
 .../swt/views/table/TableCellSWTPaintListener.java |     6 +-
 .../swt/views/table/TableColumnOrTreeColumn.java   |   113 -
 .../ui/swt/views/table/TableItemOrTreeItem.java    |   157 -
 .../ui/swt/views/table/TableOrTreeSWT.java         |   394 -
 .../azureus2/ui/swt/views/table/TableRowSWT.java   |     5 +-
 .../swt/views/table/TableRowSWTPaintListener.java  |     6 +-
 .../swt/views/table/TableSelectedRowsListener.java |    18 +
 .../ui/swt/views/table/TableViewFilterCheck.java   |     6 +-
 .../azureus2/ui/swt/views/table/TableViewSWT.java  |    17 +-
 .../ui/swt/views/table/TableViewSWTFilter.java     |    18 +
 .../views/table/TableViewSWTMenuFillListener.java  |     5 +-
 .../swt/views/table/TableViewSWTPanelCreator.java  |    19 +-
 .../ui/swt/views/table/impl/FakeTableCell.java     |    16 +-
 .../ui/swt/views/table/impl/TableCellImpl.java     |   637 -
 .../ui/swt/views/table/impl/TableCellSWTBase.java  |    30 +-
 .../swt/views/table/impl/TableColumnDelegate.java  |   205 -
 .../ui/swt/views/table/impl/TableDelegate.java     |   921 --
 .../ui/swt/views/table/impl/TableItemDelegate.java |   338 -
 .../ui/swt/views/table/impl/TableOrTreeUtils.java  |   190 -
 .../ui/swt/views/table/impl/TableRowImpl.java      |   908 --
 .../ui/swt/views/table/impl/TableRowSWTBase.java   |    40 +-
 .../ui/swt/views/table/impl/TableTooltips.java     |     5 +-
 .../ui/swt/views/table/impl/TableViewFactory.java  |    35 +-
 .../ui/swt/views/table/impl/TableViewSWTImpl.java  |  2972 -----
 .../swt/views/table/impl/TableViewSWT_Common.java  |   168 +-
 .../views/table/impl/TableViewSWT_EraseItem.java   |   243 -
 .../views/table/impl/TableViewSWT_PaintItem.java   |   469 -
 .../views/table/impl/TableViewSWT_TabsCommon.java  |   976 +-
 .../ui/swt/views/table/impl/TableViewTab.java      |    84 +-
 .../swt/views/table/impl/TreeColumnDelegate.java   |   204 -
 .../ui/swt/views/table/impl/TreeDelegate.java      |   916 --
 .../ui/swt/views/table/impl/TreeItemDelegate.java  |   334 -
 .../swt/views/table/painted/TableCellPainted.java  |    21 +
 .../swt/views/table/painted/TableRowPainted.java   |   160 +-
 .../swt/views/table/painted/TableViewPainted.java  |   104 +-
 .../swt/views/table/utils/TableColumnCreator.java  |     9 +-
 .../swt/views/table/utils/TableColumnSWTUtils.java |     5 +-
 .../views/table/utils/TableContextMenuManager.java |     8 +-
 .../ui/swt/views/tableitems/ColumnDateSizer.java   |    10 +-
 .../views/tableitems/archivedfiles/NameItem.java   |   103 +
 .../views/tableitems/archivedfiles/SizeItem.java   |    95 +
 .../ui/swt/views/tableitems/files/DoneItem.java    |     8 +-
 .../tableitems/files/FileAvailabilityItem.java     |     8 +-
 .../swt/views/tableitems/files/FileCRC32Item.java  |     8 +-
 .../ui/swt/views/tableitems/files/FileETAItem.java |     8 +-
 .../views/tableitems/files/FileExtensionItem.java  |     8 +-
 .../views/tableitems/files/FileHashItemBase.java   |    31 +-
 .../swt/views/tableitems/files/FileIndexItem.java  |     8 +-
 .../ui/swt/views/tableitems/files/FileMD5Item.java |     8 +-
 .../views/tableitems/files/FileReadSpeedItem.java  |     8 +-
 .../swt/views/tableitems/files/FileSHA1Item.java   |    34 +
 .../views/tableitems/files/FileWriteSpeedItem.java |     8 +-
 .../swt/views/tableitems/files/FirstPieceItem.java |     8 +-
 .../ui/swt/views/tableitems/files/ModeItem.java    |     8 +-
 .../ui/swt/views/tableitems/files/NameItem.java    |    10 +-
 .../ui/swt/views/tableitems/files/PathItem.java    |     8 +-
 .../ui/swt/views/tableitems/files/PercentItem.java |     8 +-
 .../swt/views/tableitems/files/PieceCountItem.java |     8 +-
 .../swt/views/tableitems/files/PriorityItem.java   |     8 +-
 .../views/tableitems/files/ProgressGraphItem.java  |     5 +-
 .../tableitems/files/RemainingPiecesItem.java      |     8 +-
 .../ui/swt/views/tableitems/files/SizeItem.java    |     8 +-
 .../views/tableitems/files/StorageTypeItem.java    |     8 +-
 .../tableitems/files/TorrentRelativePathItem.java  |     8 +-
 .../views/tableitems/myshares/CategoryItem.java    |     5 +-
 .../ui/swt/views/tableitems/myshares/NameItem.java |     8 +-
 .../ui/swt/views/tableitems/myshares/TypeItem.java |     8 +-
 .../tableitems/mytorrents/AbstractTrackerCell.java |     5 +-
 .../views/tableitems/mytorrents/AlertsItem.java    |     8 +-
 .../tableitems/mytorrents/AvailabilityItem.java    |     8 +-
 .../views/tableitems/mytorrents/AvgAvailItem.java  |     8 +-
 .../tableitems/mytorrents/BadAvailTimeItem.java    |     5 +-
 .../views/tableitems/mytorrents/CategoryItem.java  |     8 +-
 .../tableitems/mytorrents/ColumnFileCount.java     |     5 +-
 .../tableitems/mytorrents/ColumnSizeWithDND.java   |    72 +
 .../tableitems/mytorrents/ColumnTorrentSpeed.java  |    19 +-
 .../tableitems/mytorrents/CommentIconItem.java     |     8 +-
 .../views/tableitems/mytorrents/CommentItem.java   |     8 +-
 .../views/tableitems/mytorrents/CompletedItem.java |     5 +-
 .../tableitems/mytorrents/CompletionItem.java      |    13 +-
 .../views/tableitems/mytorrents/DateAddedItem.java |     5 +-
 .../tableitems/mytorrents/DateCompletedItem.java   |     5 +-
 .../mytorrents/DateFileCompletedItem.java          |    78 +
 .../tableitems/mytorrents/DateLastActiveItem.java  |    63 +
 .../swt/views/tableitems/mytorrents/DoneItem.java  |    15 +-
 .../swt/views/tableitems/mytorrents/DownItem.java  |     8 +-
 .../views/tableitems/mytorrents/DownSpeedItem.java |     8 +-
 .../tableitems/mytorrents/DownSpeedLimitItem.java  |     5 +-
 .../swt/views/tableitems/mytorrents/ETAItem.java   |     8 +-
 .../tableitems/mytorrents/FileExtensionItem.java   |     8 +-
 .../views/tableitems/mytorrents/FilesDoneItem.java |     8 +-
 .../views/tableitems/mytorrents/HealthItem.java    |     8 +-
 .../views/tableitems/mytorrents/IPFilterItem.java  |    27 +-
 .../swt/views/tableitems/mytorrents/MaxSRItem.java |   105 +-
 .../tableitems/mytorrents/MaxUploadsItem.java      |    15 +-
 .../tableitems/mytorrents/MergedDataItem.java      |    71 +
 .../swt/views/tableitems/mytorrents/MinSRItem.java |   103 +-
 .../swt/views/tableitems/mytorrents/NameItem.java  |    14 +-
 .../views/tableitems/mytorrents/NetworksItem.java  |     8 +-
 .../tableitems/mytorrents/OnlyCDing4Item.java      |     8 +-
 .../views/tableitems/mytorrents/PeakDownItem.java  |    17 +-
 .../views/tableitems/mytorrents/PeakUpItem.java    |    15 +-
 .../tableitems/mytorrents/PeerSourcesItem.java     |     8 +-
 .../swt/views/tableitems/mytorrents/PeersItem.java |     8 +-
 .../views/tableitems/mytorrents/PiecesItem.java    |     8 +-
 .../swt/views/tableitems/mytorrents/RankItem.java  |     8 +-
 .../views/tableitems/mytorrents/RemainingItem.java |    10 +-
 .../views/tableitems/mytorrents/SavePathItem.java  |     8 +-
 .../mytorrents/SecondsDownloadingItem.java         |     8 +-
 .../tableitems/mytorrents/SecondsSeedingItem.java  |     8 +-
 .../tableitems/mytorrents/SeedToPeerRatioItem.java |     8 +-
 .../swt/views/tableitems/mytorrents/SeedsItem.java |     8 +-
 .../tableitems/mytorrents/SessionDownItem.java     |     8 +-
 .../views/tableitems/mytorrents/SessionUpItem.java |     8 +-
 .../tableitems/mytorrents/ShareRatioItem.java      |    57 +-
 .../mytorrents/ShareRatioProgressItem.java         |   263 +-
 .../swt/views/tableitems/mytorrents/SizeItem.java  |    72 +-
 .../tableitems/mytorrents/SmoothedDownItem.java    |    15 +-
 .../tableitems/mytorrents/SmoothedETAItem.java     |     8 +-
 .../tableitems/mytorrents/SmoothedUpItem.java      |    15 +-
 .../views/tableitems/mytorrents/StatusItem.java    |     8 +-
 .../mytorrents/SwarmAverageCompletion.java         |     8 +-
 .../tableitems/mytorrents/SwarmAverageSpeed.java   |     8 +-
 .../views/tableitems/mytorrents/TagColorsItem.java |     8 +-
 .../swt/views/tableitems/mytorrents/TagsItem.java  |     8 +-
 .../mytorrents/TimeSinceDownloadItem.java          |     8 +-
 .../tableitems/mytorrents/TimeSinceUploadItem.java |     8 +-
 .../mytorrents/TorrentCreateDateItem.java          |     5 +-
 .../tableitems/mytorrents/TorrentPathItem.java     |     5 +-
 .../tableitems/mytorrents/TotalSpeedItem.java      |     8 +-
 .../tableitems/mytorrents/TrackerCellUtils.java    |    12 +-
 .../tableitems/mytorrents/TrackerNameItem.java     |     8 +-
 .../mytorrents/TrackerNextAccessItem.java          |     8 +-
 .../tableitems/mytorrents/TrackerStatusItem.java   |     8 +-
 .../ui/swt/views/tableitems/mytorrents/UpItem.java |     8 +-
 .../views/tableitems/mytorrents/UpSpeedItem.java   |     8 +-
 .../tableitems/mytorrents/UpSpeedLimitItem.java    |     8 +-
 .../tableitems/mytracker/AnnounceCountItem.java    |     8 +-
 .../tableitems/mytracker/AverageBytesInItem.java   |     8 +-
 .../tableitems/mytracker/AverageBytesOutItem.java  |     8 +-
 .../tableitems/mytracker/BadNATCountItem.java      |     5 +-
 .../views/tableitems/mytracker/CategoryItem.java   |     5 +-
 .../tableitems/mytracker/CompletedCountItem.java   |     8 +-
 .../views/tableitems/mytracker/DateAddedItem.java  |     8 +-
 .../views/tableitems/mytracker/DownloadedItem.java |     8 +-
 .../swt/views/tableitems/mytracker/LeftItem.java   |     8 +-
 .../swt/views/tableitems/mytracker/NameItem.java   |     8 +-
 .../views/tableitems/mytracker/PassiveItem.java    |     8 +-
 .../views/tableitems/mytracker/PeerCountItem.java  |     8 +-
 .../tableitems/mytracker/ScrapeCountItem.java      |     8 +-
 .../views/tableitems/mytracker/SeedCountItem.java  |     8 +-
 .../swt/views/tableitems/mytracker/StatusItem.java |     8 +-
 .../tableitems/mytracker/TotalBytesInItem.java     |     8 +-
 .../tableitems/mytracker/TotalBytesOutItem.java    |     8 +-
 .../views/tableitems/mytracker/TrackerItem.java    |     8 +-
 .../views/tableitems/mytracker/UploadedItem.java   |     8 +-
 .../ui/swt/views/tableitems/peers/ASItem.java      |    56 +-
 .../ui/swt/views/tableitems/peers/ChokedItem.java  |     8 +-
 .../ui/swt/views/tableitems/peers/ChokingItem.java |     8 +-
 .../tableitems/peers/ClientIdentificationItem.java |     5 +-
 .../ui/swt/views/tableitems/peers/ClientItem.java  |     8 +-
 .../views/tableitems/peers/ColumnPeerNetwork.java  |    67 +
 .../views/tableitems/peers/ConnectedTimeItem.java  |     8 +-
 .../views/tableitems/peers/DLedFromOthersItem.java |     8 +-
 .../swt/views/tableitems/peers/DiscardedItem.java  |     8 +-
 .../ui/swt/views/tableitems/peers/DownItem.java    |     8 +-
 .../swt/views/tableitems/peers/DownSpeedItem.java  |     8 +-
 .../views/tableitems/peers/DownSpeedLimitItem.java |     5 +-
 .../views/tableitems/peers/DownloadNameItem.java   |     5 +-
 .../swt/views/tableitems/peers/EncryptionItem.java |     8 +-
 .../ui/swt/views/tableitems/peers/GainItem.java    |     5 +-
 .../peers/HandshakeReservedBytesItem.java          |     5 +-
 .../swt/views/tableitems/peers/HostNameItem.java   |     5 +-
 .../tableitems/peers/IncomingRequestCountItem.java |     8 +-
 .../ui/swt/views/tableitems/peers/IndexItem.java   |    57 +
 .../swt/views/tableitems/peers/InterestedItem.java |     8 +-
 .../views/tableitems/peers/InterestingItem.java    |     8 +-
 .../ui/swt/views/tableitems/peers/IpItem.java      |     8 +-
 .../ui/swt/views/tableitems/peers/LANItem.java     |     8 +-
 .../swt/views/tableitems/peers/MessagingItem.java  |     8 +-
 .../tableitems/peers/OptimisticUnchokeItem.java    |     8 +-
 .../tableitems/peers/OutgoingRequestCountItem.java |     8 +-
 .../swt/views/tableitems/peers/PeerByteIDItem.java |     5 +-
 .../ui/swt/views/tableitems/peers/PeerIDItem.java  |     9 +-
 .../swt/views/tableitems/peers/PeerSourceItem.java |     8 +-
 .../ui/swt/views/tableitems/peers/PercentItem.java |     8 +-
 .../ui/swt/views/tableitems/peers/PieceItem.java   |     8 +-
 .../ui/swt/views/tableitems/peers/PiecesItem.java  |     8 +-
 .../ui/swt/views/tableitems/peers/PortItem.java    |     8 +-
 .../swt/views/tableitems/peers/ProtocolItem.java   |     8 +-
 .../ui/swt/views/tableitems/peers/SnubbedItem.java |     8 +-
 .../ui/swt/views/tableitems/peers/StatUpItem.java  |     8 +-
 .../ui/swt/views/tableitems/peers/StateItem.java   |     8 +-
 .../tableitems/peers/TimeToSendPieceItem.java      |     8 +-
 .../tableitems/peers/TimeUntilCompleteItem.java    |     8 +-
 .../views/tableitems/peers/TotalDownSpeedItem.java |     8 +-
 .../ui/swt/views/tableitems/peers/TypeItem.java    |     8 +-
 .../views/tableitems/peers/UniquePieceItem.java    |     8 +-
 .../views/tableitems/peers/UpDownRatioItem.java    |     8 +-
 .../ui/swt/views/tableitems/peers/UpItem.java      |     8 +-
 .../ui/swt/views/tableitems/peers/UpRatioItem.java |     8 +-
 .../ui/swt/views/tableitems/peers/UpSpeedItem.java |     8 +-
 .../views/tableitems/peers/UpSpeedLimitItem.java   |     8 +-
 .../views/tableitems/pieces/AvailabilityItem.java  |     8 +-
 .../views/tableitems/pieces/BlockCountItem.java    |     8 +-
 .../ui/swt/views/tableitems/pieces/BlocksItem.java |     8 +-
 .../swt/views/tableitems/pieces/CompletedItem.java |     8 +-
 .../views/tableitems/pieces/PieceNumberItem.java   |     8 +-
 .../swt/views/tableitems/pieces/PriorityItem.java  |     8 +-
 .../swt/views/tableitems/pieces/RequestedItem.java |     5 +-
 .../views/tableitems/pieces/ReservedByItem.java    |     8 +-
 .../ui/swt/views/tableitems/pieces/SizeItem.java   |     8 +-
 .../ui/swt/views/tableitems/pieces/SpeedItem.java  |     8 +-
 .../ui/swt/views/tableitems/pieces/TypeItem.java   |     8 +-
 .../swt/views/tableitems/pieces/WritersItem.java   |     8 +-
 .../views/tableitems/tracker/CompletedItem.java    |    13 +-
 .../swt/views/tableitems/tracker/IntervalItem.java |    13 +-
 .../views/tableitems/tracker/LastUpdateItem.java   |     5 +-
 .../swt/views/tableitems/tracker/LeechersItem.java |    13 +-
 .../ui/swt/views/tableitems/tracker/NameItem.java  |    12 +-
 .../ui/swt/views/tableitems/tracker/PeersItem.java |    13 +-
 .../ui/swt/views/tableitems/tracker/SeedsItem.java |    13 +-
 .../swt/views/tableitems/tracker/StatusItem.java   |    14 +-
 .../ui/swt/views/tableitems/tracker/TypeItem.java  |    13 +-
 .../swt/views/tableitems/tracker/UpdateInItem.java |    13 +-
 .../ui/swt/views/utils/CategoryUIUtils.java        |    30 +-
 .../ui/swt/views/utils/CoordinateTransform.java    |    18 +
 .../azureus2/ui/swt/views/utils/LocProvUtils.java  |    15 +-
 .../azureus2/ui/swt/views/utils/ManagerUtils.java  |  1459 ++-
 .../azureus2/ui/swt/views/utils/TagUIUtils.java    |   852 +-
 .../azureus2/ui/swt/welcome/WelcomeWindow.java     |    12 +-
 .../azureus2/ui/swt/win32/Win32UIEnhancer.java     |    68 +-
 .../ui/swt/wizard/AbstractWizardPanel.java         |     3 +-
 .../gudy/azureus2/ui/swt/wizard/IWizardPanel.java  |     3 +-
 .../org/gudy/azureus2/ui/swt/wizard/Wizard.java    |     3 +-
 .../azureus2/ui/swt/wizard/WizardListener.java     |     3 +-
 .../gudy/azureus2/ui/systray/SystemTraySWT.java    |    23 +-
 .../org/gudy/azureus2/ui/webplugin/WebPlugin.java  |   267 +-
 .../ui/webplugin/WebPluginAccessController.java    |     5 +-
 .../org/gudy/azureus2/update/CorePatchChecker.java |     7 +-
 .../org/gudy/azureus2/update/CorePatchLevel.java   |     5 +-
 .../gudy/azureus2/update/CoreUpdateChecker.java    |     6 +-
 .../org/gudy/azureus2/update/UpdateJarPatcher.java |     5 +-
 .../gudy/azureus2/update/UpdaterUpdateChecker.java |     5 +-
 .../src/org/gudy/azureus2/update/UpdaterUtils.java |     5 +-
 azureus2/src/org/json/simple/AUTHORS.txt           |     1 -
 azureus2/src/org/json/simple/ItemList.java         |   205 -
 azureus2/src/org/json/simple/JSONArray.java        |    72 -
 azureus2/src/org/json/simple/JSONObject.java       |   208 -
 azureus2/src/org/json/simple/JSONValue.java        |    36 -
 azureus2/src/org/json/simple/LICENSE.txt           |   504 -
 azureus2/src/org/json/simple/README.txt            |   144 -
 azureus2/src/org/json/simple/Test.java             |    54 -
 .../src/org/json/simple/parser/JSONParser.java     |   192 -
 azureus2/src/org/json/simple/parser/Yylex.java     |   428 -
 azureus2/src/org/json/simple/parser/Yytoken.java   |    31 -
 .../activities/VuzeActivitiesConstants.java        |     6 +-
 .../azureus/activities/VuzeActivitiesEntry.java    |    10 +-
 .../azureus/activities/VuzeActivitiesListener.java |     6 +-
 .../activities/VuzeActivitiesLoadedListener.java   |     6 +-
 .../azureus/activities/VuzeActivitiesManager.java  |     6 +-
 .../azureus/core/cnetwork/ContentNetwork.java      |   561 +-
 .../core/cnetwork/ContentNetworkException.java     |    83 +-
 .../core/cnetwork/ContentNetworkListener.java      |    85 +-
 .../core/cnetwork/ContentNetworkManager.java       |   127 +-
 .../cnetwork/ContentNetworkManagerFactory.java     |    79 +-
 .../ContentNetworkPropertyChangeListener.java      |    59 +-
 .../core/cnetwork/impl/ContentNetworkImpl.java     |   963 +-
 .../cnetwork/impl/ContentNetworkManagerImpl.java   |  1133 +-
 .../core/cnetwork/impl/ContentNetworkVuze.java     |   207 +-
 .../cnetwork/impl/ContentNetworkVuzeGeneric.java   |    18 +-
 .../content/AzureusPlatformContentDirectory.java   |     5 +-
 .../azureus/core/content/ContentException.java     |    83 +-
 .../content/RelatedAttributeLookupListener.java    |    18 +-
 .../azureus/core/content/RelatedContent.java       |   626 +-
 .../core/content/RelatedContentLookupListener.java |    79 +-
 .../core/content/RelatedContentManager.java        | 11531 +++++++----------
 .../content/RelatedContentManagerListener.java     |    87 +-
 .../core/content/RelatedContentSearcher.java       |  2360 ++++
 .../azureus/core/crypto/VuzeCryptoException.java   |    69 +-
 .../azureus/core/crypto/VuzeCryptoListener.java    |    87 +-
 .../azureus/core/crypto/VuzeCryptoManager.java     |   655 +-
 .../com/aelitis/azureus/core/devices/Device.java   |   387 +-
 .../core/devices/DeviceContentDirectory.java       |    73 +-
 .../core/devices/DeviceInternetGateway.java        |    57 +-
 .../azureus/core/devices/DeviceListener.java       |    59 +-
 .../azureus/core/devices/DeviceManager.java        |   341 +-
 .../devices/DeviceManagerDiscoveryListener.java    |    17 +-
 .../core/devices/DeviceManagerException.java       |    87 +-
 .../azureus/core/devices/DeviceManagerFactory.java |   203 +-
 .../core/devices/DeviceManagerListener.java        |    89 +-
 .../azureus/core/devices/DeviceMediaRenderer.java  |   312 +-
 .../core/devices/DeviceMediaRendererTemplate.java  |    65 +-
 .../core/devices/DeviceOfflineDownload.java        |    79 +-
 .../core/devices/DeviceOfflineDownloader.java      |   125 +-
 .../devices/DeviceOfflineDownloaderListener.java   |    77 +-
 .../devices/DeviceOfflineDownloaderManager.java    |   121 +-
 .../azureus/core/devices/DeviceSearchListener.java |    65 +-
 .../azureus/core/devices/DeviceTemplate.java       |   129 +-
 .../aelitis/azureus/core/devices/DeviceUPnP.java   |    33 +
 .../core/devices/TranscodeActionVetoException.java |    67 +-
 .../core/devices/TranscodeAnalysisListener.java    |    73 +-
 .../azureus/core/devices/TranscodeException.java   |   117 +-
 .../azureus/core/devices/TranscodeFile.java        |   289 +-
 .../aelitis/azureus/core/devices/TranscodeJob.java |   255 +-
 .../azureus/core/devices/TranscodeManager.java     |    81 +-
 .../core/devices/TranscodeManagerListener.java     |    75 +-
 .../azureus/core/devices/TranscodeProfile.java     |   109 +-
 .../azureus/core/devices/TranscodeProvider.java    |   155 +-
 .../core/devices/TranscodeProviderAdapter.java     |    89 +-
 .../core/devices/TranscodeProviderAnalysis.java    |   109 +-
 .../azureus/core/devices/TranscodeProviderJob.java |    77 +-
 .../azureus/core/devices/TranscodeQueue.java       |   181 +-
 .../core/devices/TranscodeQueueActionListener.java |    69 +-
 .../core/devices/TranscodeQueueListener.java       |    75 +-
 .../azureus/core/devices/TranscodeTarget.java      |   193 +-
 .../core/devices/TranscodeTargetListener.java      |    83 +-
 .../devices/impl/DeviceContentDirectoryImpl.java   |   231 +-
 .../core/devices/impl/DeviceDriveManager.java      |   895 +-
 .../azureus/core/devices/impl/DeviceImpl.java      |    47 +-
 .../devices/impl/DeviceInternetGatewayImpl.java    |   635 +-
 .../core/devices/impl/DeviceManagerImpl.java       |  3939 +++---
 .../core/devices/impl/DeviceManagerRSSFeed.java    |  1021 +-
 .../core/devices/impl/DeviceManagerUPnPImpl.java   |  2176 ++--
 .../core/devices/impl/DeviceMediaRendererImpl.java |   918 +-
 .../devices/impl/DeviceMediaRendererManual.java    |  1297 +-
 .../impl/DeviceMediaRendererTemplateImpl.java      |   315 +-
 .../devices/impl/DeviceOfflineDownloaderImpl.java  |  3471 +++--
 .../azureus/core/devices/impl/DeviceTivo.java      |  2153 ++--
 .../core/devices/impl/DeviceTivoManager.java       |  1263 +-
 .../azureus/core/devices/impl/DeviceUPnPImpl.java  |    23 +-
 .../azureus/core/devices/impl/DeviceiTunes.java    |  1485 ++-
 .../core/devices/impl/DeviceiTunesManager.java     |   337 +-
 .../core/devices/impl/TranscodeFileImpl.java       |  1831 ++-
 .../core/devices/impl/TranscodeJobImpl.java        |  1889 ++-
 .../devices/impl/TranscodeJobOutputLeecher.java    |  1215 +-
 .../core/devices/impl/TranscodeManagerImpl.java    |  2023 ++-
 .../azureus/core/devices/impl/TranscodePipe.java   |  1137 +-
 .../core/devices/impl/TranscodePipeFileSource.java |   737 +-
 .../devices/impl/TranscodePipeStreamSource.java    |   227 +-
 .../devices/impl/TranscodePipeStreamSource2.java   |   187 +-
 .../core/devices/impl/TranscodeProfileImpl.java    |   245 +-
 .../core/devices/impl/TranscodeProviderVuze.java   |  1853 ++-
 .../core/devices/impl/TranscodeQueueImpl.java      |  3483 +++--
 .../core/download/DiskManagerFileInfoDelegate.java |  1569 ++-
 .../core/download/DiskManagerFileInfoFile.java     |   987 +-
 .../core/download/DiskManagerFileInfoStream.java   |  1677 ++-
 .../core/download/DiskManagerFileInfoURL.java      |  1739 ++-
 .../core/download/DownloadManagerEnhancer.java     |     5 +-
 .../core/download/EnhancedDownloadManager.java     |     5 +-
 .../core/download/EnhancedDownloadManagerFile.java |     5 +-
 .../azureus/core/download/StreamManager.java       |    17 +-
 .../core/download/StreamManagerDownload.java       |    17 +-
 .../download/StreamManagerDownloadListener.java    |    17 +-
 .../core/messenger/ClientMessageContext.java       |     5 +-
 .../core/messenger/ClientMessageContextImpl.java   |     5 +-
 .../azureus/core/messenger/PlatformMessage.java    |     5 +-
 .../azureus/core/messenger/PlatformMessenger.java  |     5 +-
 .../core/messenger/PlatformMessengerException.java |    83 +-
 .../core/messenger/PlatformMessengerListener.java  |     5 +-
 .../core/messenger/browser/BrowserMessage.java     |     5 +-
 .../browser/BrowserMessageDispatcher.java          |     6 +-
 .../listeners/AbstractBrowserMessageListener.java  |     5 +-
 .../browser/listeners/BrowserMessageListener.java  |     5 +-
 .../listeners/MessageCompletionListener.java       |     5 +-
 .../messenger/config/PlatformConfigMessenger.java  |    61 +-
 .../messenger/config/PlatformDevicesMessenger.java |    62 +-
 .../messenger/config/PlatformMessengerConfig.java  |   279 +-
 .../config/PlatformMetaSearchMessenger.java        |   855 +-
 .../config/PlatformSubscriptionsMessenger.java     |   673 +-
 .../messenger/config/PlatformTorrentMessenger.java |     5 +-
 .../config/PlatformVuzeActivitiesMessenger.java    |     6 +-
 .../azureus/core/metasearch/CookieParameter.java   |    87 +-
 .../aelitis/azureus/core/metasearch/Engine.java    |   576 +-
 .../azureus/core/metasearch/MetaSearch.java        |   251 +-
 .../core/metasearch/MetaSearchException.java       |    83 +-
 .../core/metasearch/MetaSearchListener.java        |    75 +-
 .../azureus/core/metasearch/MetaSearchManager.java |   149 +-
 .../core/metasearch/MetaSearchManagerFactory.java  |    79 +-
 .../core/metasearch/MetaSearchManagerListener.java |    59 +-
 .../aelitis/azureus/core/metasearch/Result.java    |   759 +-
 .../azureus/core/metasearch/ResultListener.java    |    75 +-
 .../azureus/core/metasearch/SearchException.java   |    73 +-
 .../azureus/core/metasearch/SearchParameter.java   |    87 +-
 .../azureus/core/metasearch/impl/DateParser.java   |    57 +-
 .../core/metasearch/impl/DateParserClassic.java    |   663 +-
 .../core/metasearch/impl/DateParserRegex.java      |   937 +-
 .../azureus/core/metasearch/impl/EngineImpl.java   |  3241 +++--
 .../core/metasearch/impl/FieldRemapper.java        |   205 +-
 .../core/metasearch/impl/FieldRemapping.java       |   109 +-
 .../core/metasearch/impl/MetaSearchImpl.java       |  2715 ++--
 .../metasearch/impl/MetaSearchManagerImpl.java     |  4305 ++++---
 .../core/metasearch/impl/SearchExecuter.java       |   137 +-
 .../core/metasearch/impl/plugin/PluginEngine.java  |   769 +-
 .../core/metasearch/impl/plugin/PluginResult.java  |   795 +-
 .../core/metasearch/impl/web/FieldMapping.java     |    87 +-
 .../core/metasearch/impl/web/WebEngine.java        |  2955 +++--
 .../core/metasearch/impl/web/WebResult.java        |  1027 +-
 .../core/metasearch/impl/web/json/JSONEngine.java  |   999 +-
 .../metasearch/impl/web/regex/RegexEngine.java     |  1131 +-
 .../core/metasearch/impl/web/rss/RSSEngine.java    |    63 +-
 .../metasearch/utils/MomentsAgoDateFormatter.java  |   307 +-
 .../azureus/core/peer/cache/CacheDiscoverer.java   |     5 +-
 .../azureus/core/peer/cache/CacheDiscovery.java    |     5 +-
 .../aelitis/azureus/core/peer/cache/CachePeer.java |     5 +-
 .../peer/cache/cachelogic/CLCacheDiscovery.java    |     5 +-
 .../aelitis/azureus/core/subs/Subscription.java    |   495 +-
 .../core/subs/SubscriptionAssociationLookup.java   |    57 +-
 .../core/subs/SubscriptionDownloadListener.java    |    69 +-
 .../azureus/core/subs/SubscriptionException.java   |    83 +-
 .../azureus/core/subs/SubscriptionHistory.java     |   223 +-
 .../azureus/core/subs/SubscriptionListener.java    |    69 +-
 .../core/subs/SubscriptionLookupListener.java      |    81 +-
 .../azureus/core/subs/SubscriptionManager.java     |   358 +-
 .../core/subs/SubscriptionManagerFactory.java      |   189 +-
 .../core/subs/SubscriptionManagerListener.java     |    97 +-
 .../core/subs/SubscriptionPopularityListener.java  |    67 +-
 .../azureus/core/subs/SubscriptionResult.java      |   127 +-
 .../azureus/core/subs/SubscriptionScheduler.java   |   105 +-
 .../azureus/core/subs/SubscriptionUtils.java       |   229 +-
 .../core/subs/impl/SubscriptionBodyImpl.java       |  1051 +-
 .../core/subs/impl/SubscriptionDownloader.java     |   337 +-
 .../core/subs/impl/SubscriptionHistoryImpl.java    |  2022 +--
 .../azureus/core/subs/impl/SubscriptionImpl.java   |  4320 +++----
 .../core/subs/impl/SubscriptionManagerImpl.java    | 12902 ++++++++++---------
 .../core/subs/impl/SubscriptionRSSFeed.java        |   671 +-
 .../core/subs/impl/SubscriptionResultImpl.java     |   734 +-
 .../core/subs/impl/SubscriptionSchedulerImpl.java  |  1541 ++-
 .../core/torrent/HasBeenOpenedListener.java        |     6 +-
 .../azureus/core/torrent/PlatformTorrentUtils.java |     5 +-
 .../plugins/net/buddy/swt/SBC_ChatOverview.java    |   491 +
 .../net/buddy/swt/columns/ColumnChatFavorite.java  |    74 +
 .../buddy/swt/columns/ColumnChatMessageCount.java  |    61 +
 .../swt/columns/ColumnChatMsgOutstanding.java      |    69 +
 .../net/buddy/swt/columns/ColumnChatName.java      |    63 +
 .../net/buddy/swt/columns/ColumnChatStatus.java    |    64 +
 .../net/buddy/swt/columns/ColumnChatUserCount.java |    61 +
 .../com/aelitis/azureus/ui/images/check-ro-yes.png |   Bin 0 -> 1005 bytes
 .../aelitis/azureus/ui/images/sb/20px-archive.png  |   Bin 0 -> 471 bytes
 .../aelitis/azureus/ui/images/sb/20px-chat-ov.png  |   Bin 0 -> 746 bytes
 .../aelitis/azureus/ui/images/sb/20px-tag-ov.png   |   Bin 0 -> 326 bytes
 .../com/aelitis/azureus/ui/images/sb/allpeers.png  |   Bin 0 -> 545 bytes
 .../azureus/ui/images/tb/sec_l_l_disabled.png      |   Bin 0 -> 384 bytes
 .../azureus/ui/images/tb/sec_m_disabled.png        |   Bin 0 -> 220 bytes
 .../azureus/ui/images/tb/sec_r_r_disabled.png      |   Bin 0 -> 397 bytes
 .../DownloadUrlInfoContentNetwork.java             |     6 +-
 .../ui/selectedcontent/SelectedContentV3.java      |     6 +-
 .../com/aelitis/azureus/ui/skin/SkinConstants.java |     5 +-
 .../com/aelitis/azureus/ui/skin/skin3.properties   |     3 +
 .../azureus/ui/skin/skin3_archive_dls.properties   |    73 +
 .../aelitis/azureus/ui/skin/skin3_chats.properties |    75 +
 .../azureus/ui/skin/skin3_constants.properties     |     7 +
 .../azureus/ui/skin/skin3_dlg_addtag.properties    |    63 +
 .../ui/skin/skin3_dlg_generic_notop.properties     |    79 +
 ...in3_dlg_opentorrent_options_instance.properties |    25 +-
 .../ui/skin/skin3_dlg_sidebar_popout.properties    |    15 +
 .../azureus/ui/skin/skin3_sidebar.properties       |    43 +-
 .../azureus/ui/skin/skin3_tag_discovery.properties |    67 +
 .../aelitis/azureus/ui/skin/skin3_tags.properties  |    48 +-
 .../azureus/ui/skin/skin3_toolbar.properties       |    33 +-
 .../com/aelitis/azureus/ui/swt/Initializer.java    |    77 +-
 .../azureus/ui/swt/UIConfigDefaultsSWTv3.java      |     5 +-
 .../azureus/ui/swt/browser/BrowserContext.java     |    52 +-
 .../azureus/ui/swt/browser/BrowserWrapper.java     |   277 -
 .../ui/swt/browser/ClientMessageContextSWT.java    |    57 -
 .../azureus/ui/swt/browser/CookiesListener.java    |    18 +
 .../browser/OpenCloseSearchDetailsListener.java    |    18 +
 .../ui/swt/browser/listener/ConfigListener.java    |     9 +-
 .../ui/swt/browser/listener/DisplayListener.java   |    23 +-
 .../swt/browser/listener/DownloadUrlInfoSWT.java   |     6 +-
 .../listener/ExternalLoginCookieListener.java      |    21 +-
 .../browser/listener/ExternalLoginListener.java    |    18 +
 .../swt/browser/listener/ExternalLoginWindow.java  |    23 +-
 .../swt/browser/listener/MetaSearchListener.java   |  4155 +++---
 .../ui/swt/browser/listener/TorrentListener.java   |    18 +
 .../ui/swt/browser/listener/VuzeListener.java      |    23 +-
 .../ui/swt/browser/msg/MessageDispatcherSWT.java   |    89 +-
 .../azureus/ui/swt/columns/ColumnCheckBox.java     |    39 +-
 .../columns/archivedls/ColumnArchiveDLDate.java    |    65 +
 .../archivedls/ColumnArchiveDLFileCount.java       |    76 +
 .../columns/archivedls/ColumnArchiveDLName.java    |    93 +
 .../columns/archivedls/ColumnArchiveDLSize.java    |    89 +
 .../columns/archivedls/ColumnArchiveDLTags.java    |    81 +
 .../ColumnSubscriptionAutoDownload.java            |     9 +-
 .../subscriptions/ColumnSubscriptionCategory.java  |     5 +-
 .../ColumnSubscriptionLastChecked.java             |    10 +-
 .../subscriptions/ColumnSubscriptionName.java      |     3 +-
 .../ColumnSubscriptionNbNewResults.java            |     9 +-
 .../subscriptions/ColumnSubscriptionNbResults.java |     9 +-
 .../subscriptions/ColumnSubscriptionNew.java       |     3 +-
 .../ColumnSubscriptionSubscribers.java             |    10 +-
 .../subscriptions/ColumnSubscriptionTag.java       |     3 +-
 .../ui/swt/columns/tag/ColumnTagCopyOnComp.java    |    74 +
 .../ui/swt/columns/tag/ColumnTagDownLimit.java     |     3 +-
 .../azureus/ui/swt/columns/tag/ColumnTagGroup.java |    82 +
 .../azureus/ui/swt/columns/tag/ColumnTagMaxSR.java |     8 +-
 .../azureus/ui/swt/columns/tag/ColumnTagMinSR.java |     8 +-
 .../azureus/ui/swt/columns/tag/ColumnTagName.java  |     7 +
 .../ui/swt/columns/tag/ColumnTagProperties.java    |    39 +-
 .../ui/swt/columns/tag/ColumnTagPublic.java        |     8 +-
 .../ui/swt/columns/tag/ColumnTagRSSFeed.java       |     8 +-
 .../ui/swt/columns/tag/ColumnTagUpLimit.java       |     3 +-
 .../swt/columns/tag/ColumnTagUploadPriority.java   |     8 +-
 .../ui/swt/columns/tag/ColumnTagVisible.java       |    73 +
 .../tagdiscovery/ColumnTagDiscoveryAddedOn.java    |    51 +
 .../tagdiscovery/ColumnTagDiscoveryName.java       |    47 +
 .../tagdiscovery/ColumnTagDiscoveryNetwork.java    |    46 +
 .../tagdiscovery/ColumnTagDiscoveryTorrent.java    |    68 +
 .../ui/swt/columns/torrent/ColumnControls.java     |     6 +-
 .../ui/swt/columns/torrent/ColumnProgressETA.java  |    25 +-
 .../ui/swt/columns/torrent/ColumnStream.java       |    16 +-
 .../ui/swt/columns/torrent/ColumnThumbAndName.java |    13 +-
 .../ui/swt/columns/torrent/ColumnThumbnail.java    |     8 +-
 .../columns/torrent/ColumnTorrentFileProgress.java |    18 +
 .../ui/swt/columns/torrent/ColumnUnopened.java     |    27 +-
 .../ui/swt/columns/utils/ColumnImageClickArea.java |     6 +-
 .../ui/swt/columns/utils/TableColumnCreatorV3.java |    19 +-
 .../vuzeactivity/ColumnActivityActions.java        |     8 +-
 .../columns/vuzeactivity/ColumnActivityDate.java   |     6 +-
 .../columns/vuzeactivity/ColumnActivityNew.java    |     6 +-
 .../columns/vuzeactivity/ColumnActivityText.java   |     6 +-
 .../columns/vuzeactivity/ColumnActivityType.java   |     6 +-
 .../azureus/ui/swt/devices/DeviceInfoArea.java     |     6 +-
 .../azureus/ui/swt/devices/DeviceInternetView.java |   926 +-
 .../azureus/ui/swt/devices/DeviceManagerUI.java    | 10940 ++++++++--------
 .../azureus/ui/swt/devices/DevicesFTUX.java        |    14 +-
 .../azureus/ui/swt/devices/DevicesODFTUX.java      |     6 +-
 .../azureus/ui/swt/devices/DevicesWizard.java      |    18 +
 .../azureus/ui/swt/devices/SBC_DevicesODView.java  |     6 +-
 .../azureus/ui/swt/devices/SBC_DevicesView.java    |   100 +-
 .../azureus/ui/swt/devices/TranscodeChooser.java   |     6 +-
 .../ui/swt/devices/add/DeviceTemplateChooser.java  |     6 +-
 .../ui/swt/devices/add/ManufacturerChooser.java    |     6 +-
 .../swt/devices/columns/ColumnOD_Completion.java   |     6 +-
 .../ui/swt/devices/columns/ColumnOD_Name.java      |     6 +-
 .../ui/swt/devices/columns/ColumnOD_Remaining.java |     6 +-
 .../ui/swt/devices/columns/ColumnOD_Status.java    |     6 +-
 .../ui/swt/devices/columns/ColumnTJ_Category.java  |     6 +-
 .../swt/devices/columns/ColumnTJ_Completion.java   |     6 +-
 .../devices/columns/ColumnTJ_CopiedToDevice.java   |     6 +-
 .../ui/swt/devices/columns/ColumnTJ_Device.java    |     6 +-
 .../ui/swt/devices/columns/ColumnTJ_Duration.java  |     6 +-
 .../ui/swt/devices/columns/ColumnTJ_Name.java      |     6 +-
 .../ui/swt/devices/columns/ColumnTJ_Profile.java   |     6 +-
 .../ui/swt/devices/columns/ColumnTJ_Rank.java      |     6 +-
 .../swt/devices/columns/ColumnTJ_Resolution.java   |     6 +-
 .../ui/swt/devices/columns/ColumnTJ_Status.java    |     6 +-
 .../ui/swt/devices/columns/ColumnTJ_Tags.java      |     6 +-
 .../azureus/ui/swt/extlistener/StimulusRPC.java    |     5 +-
 .../swt/feature/FeatureManagerInstallWindow.java   |     5 +-
 .../azureus/ui/swt/feature/FeatureManagerUI.java   |    18 +
 .../ui/swt/feature/FeatureManagerUIListener.java   |    18 +
 .../com/aelitis/azureus/ui/swt/mdi/BaseMDI.java    |   399 +-
 .../aelitis/azureus/ui/swt/mdi/BaseMdiEntry.java   |   680 +-
 .../aelitis/azureus/ui/swt/mdi/TabbedEntry.java    |   224 +-
 .../com/aelitis/azureus/ui/swt/mdi/TabbedMDI.java  |   982 +-
 .../azureus/ui/swt/player/PlayerInstallWindow.java |     5 +-
 .../azureus/ui/swt/player/PlayerInstaller.java     |    18 +
 .../ui/swt/player/PlayerInstallerListener.java     |    18 +
 .../plugininstall/SimplePluginInstallWindow.java   |     5 +-
 .../swt/plugininstall/SimplePluginInstaller.java   |    18 +
 .../SimplePluginInstallerListener.java             |    18 +
 .../azureus/ui/swt/search/SearchHandler.java       |    39 +-
 .../azureus/ui/swt/shells/BrowserWindow.java       |    19 +-
 .../azureus/ui/swt/shells/RemotePairingWindow.java |     6 +-
 .../ui/swt/shells/main/DebugMenuHelper.java        |    21 +
 .../azureus/ui/swt/shells/main/MainHelpers.java    |    17 +-
 .../azureus/ui/swt/shells/main/MainMDISetup.java   |   486 +-
 .../azureus/ui/swt/shells/main/MainMenu.java       |   167 +-
 .../azureus/ui/swt/shells/main/MainWindow.java     |    19 +-
 .../ui/swt/shells/main/MainWindowDelayStub.java    |  1811 +--
 .../ui/swt/shells/main/MainWindowFactory.java      |    17 +-
 .../azureus/ui/swt/shells/main/MainWindowImpl.java |   292 +-
 .../ui/swt/shells/main/UIFunctionsImpl.java        |   462 +-
 .../opentorrent/OpenTorrentOptionsWindow.java      |  2266 +++-
 .../swt/shells/opentorrent/OpenTorrentWindow.java  |    66 +-
 .../shells/opentorrent/TableColumnOTOF_Name.java   |     2 +-
 .../ui/swt/shells/uiswitcher/UISwitcherWindow.java |     5 +-
 .../azureus/ui/swt/skin/SWTBGImagePainter.java     |    19 +-
 .../azureus/ui/swt/skin/SWTColorWithAlpha.java     |     6 +-
 .../com/aelitis/azureus/ui/swt/skin/SWTSkin.java   |    21 +-
 .../azureus/ui/swt/skin/SWTSkinButtonUtility.java  |    18 +
 .../ui/swt/skin/SWTSkinCheckboxListener.java       |     6 +-
 .../azureus/ui/swt/skin/SWTSkinFactory.java        |     5 +-
 .../azureus/ui/swt/skin/SWTSkinImageChanger.java   |    19 +-
 .../ui/swt/skin/SWTSkinLayoutCompleteListener.java |     5 +-
 .../aelitis/azureus/ui/swt/skin/SWTSkinObject.java |    19 +-
 .../azureus/ui/swt/skin/SWTSkinObjectAdapter.java  |     5 +-
 .../azureus/ui/swt/skin/SWTSkinObjectBasic.java    |    91 +-
 .../azureus/ui/swt/skin/SWTSkinObjectBrowser.java  |    12 +-
 .../azureus/ui/swt/skin/SWTSkinObjectButton.java   |     6 +-
 .../azureus/ui/swt/skin/SWTSkinObjectCheckbox.java |     6 +-
 .../ui/swt/skin/SWTSkinObjectContainer.java        |     5 +-
 .../ui/swt/skin/SWTSkinObjectExpandBar.java        |    18 +
 .../ui/swt/skin/SWTSkinObjectExpandItem.java       |     5 +-
 .../azureus/ui/swt/skin/SWTSkinObjectImage.java    |    66 +-
 .../azureus/ui/swt/skin/SWTSkinObjectListener.java |     5 +-
 .../azureus/ui/swt/skin/SWTSkinObjectSash.java     |    25 +-
 .../ui/swt/skin/SWTSkinObjectSeparator.java        |    18 +
 .../azureus/ui/swt/skin/SWTSkinObjectSlider.java   |     5 +-
 .../azureus/ui/swt/skin/SWTSkinObjectTab.java      |     5 +-
 .../ui/swt/skin/SWTSkinObjectTabFolder.java        |    41 +-
 .../azureus/ui/swt/skin/SWTSkinObjectText.java     |     5 +-
 .../azureus/ui/swt/skin/SWTSkinObjectText1.java    |     5 +-
 .../azureus/ui/swt/skin/SWTSkinObjectText2.java    |     5 +-
 .../skin/SWTSkinObjectText_UrlClickedListener.java |     6 +-
 .../azureus/ui/swt/skin/SWTSkinObjectTextbox.java  |     6 +-
 .../azureus/ui/swt/skin/SWTSkinObjectToggle.java   |     6 +-
 .../azureus/ui/swt/skin/SWTSkinProperties.java     |     5 +-
 .../ui/swt/skin/SWTSkinPropertiesClone.java        |     5 +-
 .../azureus/ui/swt/skin/SWTSkinPropertiesImpl.java |     5 +-
 .../ui/swt/skin/SWTSkinPropertiesParam.java        |     5 +-
 .../ui/swt/skin/SWTSkinPropertiesParamImpl.java    |     5 +-
 .../aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java |    19 +-
 .../azureus/ui/swt/skin/SWTSkinTabSetListener.java |     5 +-
 .../azureus/ui/swt/skin/SWTSkinToggleListener.java |     6 +-
 .../aelitis/azureus/ui/swt/skin/SWTSkinUtils.java  |    23 +-
 .../azureus/ui/swt/skin/SWTTextPaintListener.java  |    19 +-
 .../swt/subscriptions/SubscriptionListWindow.java  |    18 +
 .../ui/swt/subscriptions/SubscriptionMDIEntry.java |   905 +-
 .../swt/subscriptions/SubscriptionManagerUI.java   |  3609 ++++--
 .../subscriptions/SubscriptionSelectedContent.java |   367 +-
 .../ui/swt/subscriptions/SubscriptionView.java     |    35 +-
 .../subscriptions/SubscriptionViewExternal.java    |    24 +-
 .../subscriptions/SubscriptionViewInternal.java    |    37 +-
 .../ui/swt/subscriptions/SubscriptionWizard.java   |    56 +-
 .../ui/swt/subscriptions/SubscriptionsView.java    |   122 +-
 .../swt/subscriptions/SubscriptionsViewBase.java   |    15 +-
 .../azureus/ui/swt/toolbar/ToolBarItemSO.java      |   199 +-
 .../aelitis/azureus/ui/swt/utils/TagUIUtilsV3.java |   114 +
 .../azureus/ui/swt/utils/TorrentUIUtilsV3.java     |    22 +-
 .../azureus/ui/swt/views/PieceGraphView.java       |     5 +-
 .../aelitis/azureus/ui/swt/views/TopBarView.java   |    50 +-
 .../azureus/ui/swt/views/ViewDownSpeedGraph.java   |    12 +-
 .../azureus/ui/swt/views/ViewQuickConfig.java      |   146 +
 .../azureus/ui/swt/views/ViewTitleInfoBetaP.java   |    18 +
 .../azureus/ui/swt/views/ViewUpSpeedGraph.java     |    11 +-
 .../aelitis/azureus/ui/swt/views/skin/Browse.java  |     5 +-
 .../azureus/ui/swt/views/skin/InfoBarUtil.java     |    13 +-
 .../ui/swt/views/skin/MyTorrentsView_Big.java      |    38 +-
 .../ui/swt/views/skin/SBC_ActivityTableView.java   |    12 +-
 .../ui/swt/views/skin/SBC_ActivityView.java        |     6 +-
 .../swt/views/skin/SBC_ArchivedDownloadsView.java  |   772 ++
 .../azureus/ui/swt/views/skin/SBC_BurnFTUX.java    |     5 +-
 .../ui/swt/views/skin/SBC_GenericBrowsePage.java   |     6 +-
 .../ui/swt/views/skin/SBC_LibraryTableView.java    |   111 +-
 .../swt/views/skin/SBC_LibraryTableView_Big.java   |    18 +
 .../azureus/ui/swt/views/skin/SBC_LibraryView.java |   186 +-
 .../azureus/ui/swt/views/skin/SBC_PlusFTUX.java    |     5 +-
 .../ui/swt/views/skin/SBC_TagDiscovery.java        |   582 +
 .../ui/swt/views/skin/SBC_TagsOverview.java        |   174 +-
 .../ui/swt/views/skin/SBC_TorrentDetailsView.java  |   506 +-
 .../azureus/ui/swt/views/skin/SB_Discovery.java    |     6 +-
 .../azureus/ui/swt/views/skin/SB_Transfers.java    |   467 +-
 .../aelitis/azureus/ui/swt/views/skin/SB_Vuze.java |    18 +
 .../ui/swt/views/skin/SearchResultsTabArea.java    |    14 +-
 .../azureus/ui/swt/views/skin/SkinView.java        |    13 +-
 .../azureus/ui/swt/views/skin/SkinViewManager.java |     5 +-
 .../azureus/ui/swt/views/skin/SkinnedDialog.java   |    19 +-
 .../ui/swt/views/skin/StandardButtonsArea.java     |    18 +
 .../azureus/ui/swt/views/skin/ToolBarView.java     |   857 +-
 .../ui/swt/views/skin/TorrentListViewsUtils.java   |     5 +-
 .../azureus/ui/swt/views/skin/VuzeMessageBox.java  |    33 +-
 .../ui/swt/views/skin/VuzeMessageBoxListener.java  |    18 +
 .../azureus/ui/swt/views/skin/WelcomeView.java     |     5 +-
 .../azureus/ui/swt/views/skin/sidebar/SideBar.java |   482 +-
 .../ui/swt/views/skin/sidebar/SideBarEntrySWT.java |   316 +-
 .../ui/swt/views/skin/sidebar/SideBarToolTips.java |    13 +-
 .../skin/sidebar/SideBarVitalityImageSWT.java      |     6 +-
 .../azureus/ui/swt/widgets/AnimatedImage.java      |    18 +
 .../com/aelitis/azureus/util/ConstantsVuze.java    |     6 +-
 .../aelitis/azureus/util/ContentNetworkUtils.java  |     6 +-
 .../src/com/aelitis/azureus/util/DLReferals.java   |     6 +-
 .../com/aelitis/azureus/util/DataSourceUtils.java  |    48 +-
 .../com/aelitis/azureus/util/DownloadUtils.java    |     5 +-
 .../azureus/util/ExternalStimulusHandler.java      |     5 +-
 .../azureus/util/ExternalStimulusListener.java     |     5 +-
 .../src/com/aelitis/azureus/util/FeatureUtils.java |    15 +-
 .../aelitis/azureus/util/ImportExportUtils.java    |    18 +
 .../azureus/util/InitialisationFunctions.java      |    66 +-
 .../azureus/util/LocalResourceHTTPServer.java      |     5 +-
 .../com/aelitis/azureus/util/NavigationHelper.java |   507 +-
 .../src/com/aelitis/azureus/util/PlayUtils.java    |   130 +-
 .../aelitis/azureus/util/StringCompareUtils.java   |     6 +-
 .../src/com/aelitis/azureus/util/UrlFilter.java    |    23 +-
 build.xml                                          |    10 +-
 .../org/gudy/azureus2/ui/console/ConsoleInput.java |    85 +-
 uis/src/org/gudy/azureus2/ui/console/UI.java       |    30 +-
 .../gudy/azureus2/ui/console/commands/Hack.java    |   129 +
 .../ui/console/commands/IConsoleCommand.java       |   210 +-
 .../gudy/azureus2/ui/console/commands/Show.java    |   224 +-
 .../ui/console/commands/Subscriptions.java         |   382 +
 .../gudy/azureus2/ui/console/commands/Tags.java    |   210 +
 .../ui/console/commands/TorrentCommand.java        |     4 +-
 .../ui/console/commands/TorrentSubCommand.java     |     2 +-
 .../ui/console/multiuser/UserManagerPersister.java |    13 +-
 .../multiuser/persist/UserManagerXMLPersist.java   |    13 +-
 uis/src/org/pf/readme.txt                          |    31 +-
 3542 files changed, 194004 insertions(+), 196912 deletions(-)

diff --git a/azureus2/src/Azureus2.jardesc b/azureus2/src/Azureus2.jardesc
index 6cb466f..4cc1710 100644
--- a/azureus2/src/Azureus2.jardesc
+++ b/azureus2/src/Azureus2.jardesc
@@ -11,530 +11,536 @@
         </sealing>
     </manifest>
     <selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false">
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.sharing.hoster"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.magnet.swt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui.components"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.systray"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.deprecate"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.toolbar"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.clientmessageservice"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.impl.http"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ddb"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.widgets"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.security"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnpms.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.cache.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp.impl.ssdp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipfilter.impl.tests"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.clientmessageservice.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.udp.mc"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.tcp"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.client.impl.dht"/>
+        <folder path="/azureus2_svn/META-INF"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.magnet.icons"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.spi"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.sharing"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.plugins.net.buddy.swt.columns"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.security.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.peer.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.nat"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.versioncheck"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.tracker.web"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.table.utils"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.utils"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.download.savelocation"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.logging"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.common.util"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.pf"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.internat"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.download.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.file"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.torrent"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.file"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.update.sf.impl2"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.disk"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.none.internat"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.net.netstatus.swt"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.magnet.swt"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.json.simple"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.encodings"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.teletrust"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.extseed.impl.getright"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.messaging.azureus"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.shells.opentorrent"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.cms"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.control"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.modes"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console.commands"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.jman"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.helpers"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.upnp"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.config"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.mytracker"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.math.ec"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.x509"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils.xml.simpleparser"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.neuronal"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.splash"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui.menus"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.removerules"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.auth"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.net.netstatus"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.azplug"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.config.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.tracker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.client"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.openssl"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console.multiuser.persist"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.disk"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.network"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.devices"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.updater2"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.sharing"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.table"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl.plugin"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport.udp.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.instancemanager.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.win32"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.skin"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.nat"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.networks"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.impl.http"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.search"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.proxy.socks"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils.security"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipfilter.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.deprecate"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.config"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.animations.shell"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.speedmanager.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.update.sf"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.table.impl"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.feature"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.search"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.unchoker"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.jce"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.associations"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.torrent"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.download"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console.multiuser.commands"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.swt.uiupdater"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.update"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.stats.transfer.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.host"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns.torrent"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.pf.file"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl.tcp.blocking"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.util.win32"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.views.skin.sidebar"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl.access.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.stats.transfer"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipchecker.extipchecker.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.clientmessageservice.secure"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.sec"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl.tcp.nonblocking"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.udp.uc"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.toolbar"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.nat"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.speed.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.tag.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl.tcp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.startstoprules.defaultplugin"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.peers"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.mainwindow"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.tracker.local"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.peers"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.jce.interfaces"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.plugins.net.buddy.swt"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.admin"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl.resume"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.security.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipfilter.impl.tests"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.proxy.impl"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.views.skin"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.peer.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.ipfilter"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.subs.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.associations"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.common"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.x9"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.agreement"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.udp"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.i2p"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.loopcontrol.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.rpexceptions"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.global"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.xml.schemas"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.config"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui.config"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.math.ec"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.piece"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.x509"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.mytracker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.control"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.custom.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.tor"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.files"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.tracker"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ipc"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.update.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.unix"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.installer"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.piecepicker"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.views.skin.sidebar"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.animations.shell"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.crypto"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.average"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.openssl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.pairing.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.magnet"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.disk"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console.util"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns.tagdiscovery"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.devices.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.config.generic"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl.web"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.control.impl"/>
         <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.shells.main"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl.dht"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui.menus"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl.web.regex"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.menus"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.config"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.sharing.progress"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.sharing"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.extseed.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.custom"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.neuronal"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.pluginsimpl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.swt.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.security"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ipc"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.content"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.icons"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ipc"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.update"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.cnetwork"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl.piecemapper.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.jce.provider"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.clientmessageservice.secure.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.natpmp"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.impl.tcp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.clientmessageservice"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.win32.access.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.net.buddy.swt"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.internat"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.help"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.shells"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.none"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl.dht"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swing"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.swt.mdi"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.devices"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns"/>
+        <file path="/azureus2_svn/ChangeLog.txt"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.file"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.digests"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.config.plugins"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.animations"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.startstoprules.defaultplugin.ui.swt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.db.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.protocol"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl.web.json"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp.impl.services"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.extlistener"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.proxy"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl.tcp"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns.torrent"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.resourceuploader"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.udp.mc.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipchecker.natchecker"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.subs.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.natpmp.upnp"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.utils"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.extseed.impl.webseed"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.bloom"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.category"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.nat"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.util"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.pf.text"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.dht.mainline"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.proxy.impl.swt"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.html.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.pairing"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.generators"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.peer.impl.control"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.vuze"/>
         <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl.web.rss"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.images.tb"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.shells"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl.web"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.custom"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.debug"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.engines"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.dht.mainline"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.console"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.content"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.db"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.config"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.extseed.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.proxy.socks"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.mdi"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.messenger.browser.listeners"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.subs"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.components.shell"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.file.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.components.graphics"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.net.buddy.tracker"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.maketorrent"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport.udp.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.tracker.peerauth"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.netcoords"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.table"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.osx"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.logging"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils.security"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.beta"/>
-        <file path="/azureus2_svn/ChangeLog.txt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.impl.udp"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.torrent"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.test"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.pluginsinstaller"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.win32"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.natpmp.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.messaging.azureus"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.torrent"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.i2p"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.stats"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.update"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.icons.toolbar"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.impl.test"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.access"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.speedmanager.impl.v3"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.myshares"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.clientid"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.security"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.png"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.stats"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.macs"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.extseed.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.lws"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.rpexceptions"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.download"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.torrentdownloader"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.pluginsuninstaller"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.xml.rss"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.images.column"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ddb"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.wizard"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.maketorrent"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.admin.impl"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.exporttorrent.wizard"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.client.impl.dht"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ddb"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.peerdb"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.access"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.SWT"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.torrent.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.common"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.startstoprules.always"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.none"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.content"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.icons"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.messaging.generic"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui.config"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.tracker"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.access.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.security.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.bc"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.admin.impl.swt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.win32.access"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.disk"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.views"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.html.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.udp.uc.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.generators"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.icons.statusbar"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.client.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.config"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.jce.provider"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.control"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.eclipse.swt.widgets"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.update"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.custom.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.piece"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.encodings"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.shells.opentorrent"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.magneturi.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.clientid"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.content"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.minibar"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.pkcs"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.images.column"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.model"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.plugins"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.updater.snippets"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.twistie"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.mdi"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.html"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.drivedetector.impl"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.dht"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.impl.tcp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.network"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.internat"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.crypto"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.peerdb"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.content"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.skin"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.mdi"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.images.sb"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.params"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.torrent"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl.web.json"/>
         <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.cnetwork.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console.multiuser"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.swt.utils"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.download"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp.impl.ssdp"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.pf.file"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl.piecemapper.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.vuzefile"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.utils"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.dht"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.magnet"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.download"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.devices"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.global.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.proxy.socks.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.stats.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.torrent"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.peer"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.startstoprules.defaultplugin.ui.swt"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.download"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.security"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.http"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.stats.transfer.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.average"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl.piecemapper"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.win32"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.client.impl"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.instancemanager"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport.udp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.common.viewtitleinfo"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.db"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.messenger.config"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.messenger.browser"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.clientid"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.maggot"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.pieces"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.tracker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.udp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport.udp.impl.packethandler"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.skin"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.resourceuploader"/>
         <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.common"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.clientmessageservice.secure"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils.resourceuploader"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.help"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.logging"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.macosx.access.cocoa"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.drivedetector"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.signers"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.netcoords.vivaldi.ver1.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.common.updater"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.dummy"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.player"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.util.encoders"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.admin.impl"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console.multiuser.persist"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.wizard"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.devices.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.jce.spec"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.peer.impl.transport"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.mainwindow"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.shells.uiswitcher"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl.piecemapper"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.common.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.agreement.srp"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.skin"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.peer.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.speedmanager.impl.v2"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.selectedcontent"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.dns"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.icons.status"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.cache.impl"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.messenger"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.control.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.nat.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.xml.schemas"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.speed"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui.tables"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.netcoords.vivaldi.ver1.impl.tests"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.speedmanager.impl.v1"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl.tcp.nonblocking"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.update.sf.impl2"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.mytorrents"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.clientid"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.xml.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.net.buddy.tracker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.piecepicker.util"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.bloom.impl"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.activities"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipchecker.extipchecker"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.messenger.config"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.components"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.common"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.bc"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.components"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.pluginsinstaller"/>
         <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.browser.msg"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.tag"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.security"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.columnsetup"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.search"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.unchoker"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.net.netstatus"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.pairing.impl.swt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.piecepicker.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.host"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.speedmanager.impl.v3"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.network"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.messaging"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.pluginsimpl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.netcoords.vivaldi.ver1"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.devices.add"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.json.simple.parser"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.update"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.params"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.socks5"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.control.impl"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns.tag"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.startstoprules.defaultplugin"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.loopcontrol"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.cl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.dht.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.utils"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.peers"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.proxy.socks.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.tcp"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.welcome"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.udp.mc"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.piecepicker.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.components.graphics"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.swt.imageloader"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.installer"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.peers"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.installer"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.resourcedownloader"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.client.impl.bt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.messaging.bittorrent"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.peer.impl.control"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.natpmp.upnp"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.common.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.plugininstall"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.logging"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.access.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.win32.access"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.netcoords.vivaldi.ver1.impl"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport.loopback"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.utils"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.splash"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.update"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.net.buddy.swt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.clientmessageservice.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.messaging"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.win32.access.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.extseed.impl.getright"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.global"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.sharing"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.client"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.utils"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.logging.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl.access"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.net.netstatus.swt"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.feature"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.stats"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console.commands"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.swt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.updater2"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.cnetwork"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.shells"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.db.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.core3.torrentdownloader.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp.services"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.torrent"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.peers"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.control"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.tag.impl"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.images.sb"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.peer.cache"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.devices.columns"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.backup.impl"/>
-        <javaElement handleIdentifier="=azureus3_svn/<org.apache.commons.lang"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.cache"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.peer"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.x509"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.mdi"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.uploadslots"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.telnet"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swing"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.SWT"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.twistie"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.dummy"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl.web.regex"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.messaging"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.tracker.dht"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.logging"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.protocol.udp"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.cms"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.dht"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.tables"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.sharing"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.net.buddy"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl.tcp.blocking"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnpms.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.config"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.search"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.disk"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.unix"/>
         <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns.subscriptions"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.subscriptions"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.impl.plugin"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.config.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.versioncheck"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.peer"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.none.internat"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.auth"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.resourcedownloader"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.sharing"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.icons.toolbar"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.messaging"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.launch"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.xml.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.xml.rss"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.mytorrents"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.player"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl.resume"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.icons.status"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.messenger.browser.listeners"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.common.table.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.update"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.torrentdownloader.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipfilter.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.macosx.access.jnilib"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.teletrust"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.digests"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns.tag"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.misc"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.messaging.generic"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.torrent"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.eclipse.swt.widgets"/>
+        <file path="/azureus2_svn/GPL.txt"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.extseed"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.nat"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.dns"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.agreement.srp"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.macosx"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.tracker"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.importtorrent.wizard"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.launcher.classloading"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.magnet.icons"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.applet"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.common.viewtitleinfo"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.xml.simpleparser"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.config"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.global.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.table.painted"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.peer.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.instancemanager.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.win32"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.messaging.bittorrent"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.apache.commons.lang"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.socks5"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils.resourceuploader"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.dht"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.drivedetector"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.debug"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.content"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.protocol"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.columnsetup"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipchecker.natchecker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp.impl.device"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.dht.mainline"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.json.simple.parser"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.peer.cache.cachelogic"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.speed"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.webplugin"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.vuzefile"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipchecker.extipchecker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.util"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.images"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl.udp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.backup"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.subscriptions"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.subscriptions"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.piecepicker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.common.table"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.torrent"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns.archivedls"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.speedmanager.impl.v2"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.download"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.tag"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.pairing.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.natpmp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.engines"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.devices.add"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.speedmanager.impl.v1"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.update.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.extlistener"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.telnet"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.launch"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils.xml.rss"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.clientid"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.proxy.impl.swt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.stats"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.extseed"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.security.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.xml.simpleparser"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.swt"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.netcoords.vivaldi.ver1.impl.tests"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.tracker"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.tracker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.lws"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.animations"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.progress"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.macosx.access.cocoa"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.paddings"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.widgets"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.config.wizard"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.bloom"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.netcoords"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.download.savelocation"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.clientstats"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.magnet"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.platform"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.skin"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.drivedetector.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.rssgen"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.common.table"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.configsections"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.backup"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.vuze"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.xml.simpleparser"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.installer"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.modes"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.router.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.category.impl"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.devices"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.nat"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.update"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.file.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.swt.uiupdater"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.pluginsuninstaller"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.minibar"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.tracker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.stats"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.pf"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ddb"/>
         <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns.vuzeactivity"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport.util"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.messenger.browser"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp.services"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.pairing"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.net.buddy"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.logging"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.messaging"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.launcher"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server.impl.udp"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.ipchecker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.category"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.components"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui.components"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.netcoords.vivaldi.ver1"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.update"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console.multiuser.commands"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.sharing.hoster"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.agreement"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.pkcs"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.tables"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.router.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.pairing.impl.swt"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui.tables"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.peer.impl.transport"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.common"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.rssgen"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.messaging"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.components"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.server"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.natpmp.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.torrentdownloader"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.peer.cache"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.udp.mc.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform.macosx.access.jnilib"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.stats"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.welcome"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.table.painted"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.natpmp.upnp.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.update"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.tracker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.common.updater"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.beta"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipfilter"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.internat"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.proxy.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.http"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.messaging.bittorrent"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.osx"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.extseed.impl.webseed"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.shells.uiswitcher"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.x509"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.config"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.components.shell"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.files"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.magneturi.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.extseed.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.loopcontrol"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.subs"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.host.impl"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui.model"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.peer.cache.cachelogic"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.impl.test"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.config.wizard"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.stats.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.config.generic"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.sec"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport.udp"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.util.win32"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.table.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ipfilter"/>
-        <file path="/azureus2_svn/GPL.txt"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.jman"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.disk"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl.access.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.transport.udp.impl.packethandler"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.peer"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.diskmanager.cache"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.pf.text"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.selectedcontent"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.devices.columns"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.messenger"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.config"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.launcher.classloading"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.views"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.jar"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipchecker.extipchecker.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.donations"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.nat"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.update.sf"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.skin"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.speedmanager"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.columns.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.disk.impl.access"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ui.toolbar"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.common.table.impl"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.swt.mdi"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.misc"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.images"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp.impl.device"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.selectedcontent"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.tracker.local"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.router"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.nat"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.subscriptions"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.pieces"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.sharing.progress"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.udp.uc"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.shells"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.clientid"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.swt.imageloader"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.plugininstall"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.progress"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.tracker.dht"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.speed.impl"/>
-        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.views.skin"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.speedtest"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.html"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.myshares"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.donations"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.utils.xml.simpleparser"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.ui.console"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.proxy"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.activities"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.utils.xml.simpleparser"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.common.util"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.model"/>
         <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.browser.listener"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnpms"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.tracker.host.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.ipfilter"/>
-        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.core3.torrentdownloader.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.download"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.dht.mainline"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.ipchecker"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.platform"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.ipfilter"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.table.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnp.impl.services"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.update"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.piecepicker.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.speedmanager"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.file"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.remote.download"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ipfilter"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.download.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.control.impl"/>
         <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.download"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.messaging.bittorrent"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ipc"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.plugins.network"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.networkmanager.impl.udp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.util.encoders"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.torrent"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.update"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.startstoprules.always"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.magnet"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.configsections"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.nat.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.util.loopcontrol.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.udp.uc.impl"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.core.metasearch.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.dht.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.speedtest"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.systray"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ui.menus"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.importtorrent.wizard"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.images.tb"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.peermanager.uploadslots"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.logging.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.utils"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.archivedfiles"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.ipfilter"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.asn1.x9"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.crypto.signers"/>
+        <javaElement handleIdentifier="=azuis_svn/<org.gudy.azureus2.ui.console.multiuser"/>
         <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.swt.browser"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.jce.spec"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.upnpms"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.plugins"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.dht.router"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.plugins.upnp"/>
+        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.backup.impl"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.platform"/>
+        <javaElement handleIdentifier="=azureus3_svn/<com.aelitis.azureus.ui.selectedcontent"/>
         <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.net.magneturi"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.webplugin"/>
-        <javaElement handleIdentifier="=azureus2_svn/<com.aelitis.azureus.core.speedmanager.impl"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.security"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.bouncycastle.jce.interfaces"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.stats.transfer"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.ui.swt.views.tableitems.peers"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.json.simple"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.pluginsimpl.local.ipfilter"/>
-        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.util.protocol.azplug"/>
+        <javaElement handleIdentifier="=azureus2_svn/<org.gudy.azureus2.core3.category.impl"/>
     </selectedElements>
 </jardesc>
diff --git a/azureus2/src/ChangeLog.txt b/azureus2/src/ChangeLog.txt
index e0fd71d..29be595 100644
--- a/azureus2/src/ChangeLog.txt
+++ b/azureus2/src/ChangeLog.txt
@@ -1,6 +1,195 @@
 VUZE CHANGELOG
 -----------------
 
+2015.06.08 | Vuze 5.6.1.2
+
+FEATURE: UI   | Option to allow chat views to be independent windows [Parg]
+FEATURE: UI   | Added Tags column to archive view [Parg]
+FEATURE: Core | Tag assignment is now persisted across archive/restore [Parg]
+
+CHANGE: UI    | Pop-out views are now independent windows [Parg]
+
+BUGFIX: UI    | Fix Stats view clearing graphs on each view (Classic UI) [TuxPaper]
+BUGFIX: UI    | Fix remembering of minimized state of subtabs [TuxPaper]
+BUGFIX: UI    | Torrent options window was throwing null-pointer exceptions [Parg]
+BUGFIX: UI    | Reduced tab-rebuilds on tag property changes [Parg]
+BUGFIX: UI    | The 'Restore and...' option in the archive view was incorrectly firing per-download [Parg]
+
+
+
+2015.06.02 | Vuze 5.6.1.0
+
+FEATURE: UI   | New 'tagging' subview to allow easy download/tag assignment [TuxPaper]
+FEATURE: UI   | Many sidebar views can now be 'popped out' into a separate window [Parg]
+FEATURE: UI   | Show discovered tags when adding torrents [TuxPaper]
+FEATURE: UI   | Support escaped unicode character entry in chat UI via \unnnn [Parg]
+FEATURE: UI   | New tag settings view in Tags Overview panel [TuxPaper]
+FEATURE: UI   | Brought back client byte stats and added per-network stats [TuxPaper]
+FEATURE: UI   | Support for viewing downloads as local websites in web browser - http://wiki.vuze.com/w/Decentralized_Websites [Parg]
+FEATURE: UI   | Ability to completely disable use of the embedded browser in Vuze [Parg]
+FEATURE: UI   | Added 'torrent last active' column [TuxPaper]
+FEATURE: UI   | Additional option to edit multiple download's trackers in a single operation [Parg]
+FEATURE: UI   | Help menu option to import/export config files (etc) from bencoded <-> json format [Parg]
+FEATURE: Core | Option to delete original .torrent files after addition [Parg]
+FEATURE: Core | Automatically unzip torrents that happen to have been saved in compressed format [Parg]
+FEATURE: Core | 'action on tag assignment' to support auto removal of peers [Parg]
+FEATURE: Core | Per-peer up/down rate limiting on peer set assignment [Parg]  
+FEATURE: Core | Archival of downloads - http://wiki.vuze.com/w/Archiving_Downloads [Parg]
+
+CHANGE: UI    | Torrent hash now shown in torrent options info view [Parg]
+CHANGE: UI    | Subscriptions ca now be shown in the classic UI [TuxPaper] 
+CHANGE: UI    | More consistently handle 'do not download' file sizes when showing size/percent done/remaining [TuxPaper]
+CHANGE: UI    | Automatic closure of torrent download window when automatically invoked [Parg]
+CHANGE: UI    | Current version of components is now shown in update prompt [Parg]
+CHANGE: UI    | Latest 'private torrent' state now persisted across create-torrent operations [Parg]
+CHANGE: Core  | Treat protocol-relative URL's in RSS feeds as http:// [Parg]
+CHANGE: Core  | Changes to a download's networks are now applied directly [Parg]
+
+BUGFIX: UI    | Fix 'reset columns' not resetting all colums [TuxPaper]
+BUGFIX: UI    | Fix fancy menu bounds calculation to ensure correct visibility [TuxPaper]
+BUGFIX: UI    | Creation date in torrent options dialog was incorerctly formatted [TuxPaper]
+BUGFIX: UI    | Use updated trackers in open-torrent-options availability checker [Parg]
+BUGFIX: Core  | Fix config corruption with non-ascii chat options [Parg]
+BUGFIX: Core  | Fix edge case bug with swarm merging [Parg]
+BUGFIX: Core  | Webseed rate limits weren't always being applied correctly [Parg]
+BUGFIX: Core  | Removed small window when rate limits weren't being applied correctly [Parg]
+BUGFIX: Core  | Incorrect tags were being included when getting existing download tags [Parg]
+BUGFIX: Core  | Handle 301/302 redirects from trackers when binding to explicit IPs [Parg]
+BUGFIX: Core  | Handle UPnP device URLs that don't have final / [Parg]
+BUGFIX: Core  | Decode torrents with missing announce-urls correctly [Parg]
+BUGFIX: Core  | Unlimited per-torrent connections not being enforced correctly [Parg]
+
+
+
+2015.03.03 | Vuze 5.6.0.0
+
+FEATURE: UI   | Restructured Library view context (right-click) menu [TuxPaper]
+FEATURE: UI   | A basic quick-options plugin bar view [Parg]
+FEATURE: UI   | Support upload/download disable for Tag rate limits [Parg]
+FEATURE: UI   | Support .vuze files in the plugin installation wizard [Parg]
+FEATURE: UI   | Added some subscription settings to the sidebar context menu [Parg]
+FEATURE: UI   | Explicit browser configuration option for non-public content [Parg]
+FEATURE: UI   | Option to hide do-not-download files in the Files View [Parg]
+FEATURE: UI   | Right-click menu option in Peers View to kick a peer without banning them [Parg]
+FEATURE: UI   | Support for output redirection from console UI commands [Parg]
+FEATURE: Core | Swarm merging - http://wiki.vuze.com/w/Swarm_Merging [Parg]
+FEATURE: Core | Option to automatically select files for 'do not download' based on file type suffix [Parg]
+FEATURE: Core | Device transcodes can now be auto-shared and tagged [Parg]
+FEATURE: Core | isComplete, percentage and age added to Tag constraint language [Parg]
+FEATURE: Plug | Decentralized chat - http://wiki.vuze.com/w/Decentralized_Chat [Parg]
+FEATURE: Plug | RSS-to-chat plugin - http://wiki.vuze.com/w/RSS_To_Chat [Parg]
+FEATURE: Plug | TorBrowser plugin now supports browsing of .i2p content [Parg]
+FEATURE: Plug | Play-to DLNA enabled devices support [TuxPaper]
+FEATURE: Plug | Swarm search is now also accessible via right-click menu [Parg]
+
+CHANGE: UI    | Brazilian Portuguese translation update [Havokdan]
+CHANGE: UI    | Show decoded magnet URI title in download window [Parg]
+CHANGE: UI    | DHT activity view was showing queued activities - fixed to only show active ones [Parg]
+CHANGE: UI    | Added eepsite and onion site to About Window [TuxPaper]
+CHANGE: Core  | Auto-download subscriptions now scheduled more fairly [Parg]
+
+BUGFIX: UI    | Status bar tooltip flicker reduced [Parg]
+BUGFIX: UI    | Sometimes the sub-tab 'sash' could become inaccessible [Parg]
+BUGFIX: Core  | Fix 'is-interested' bug [Parg]
+BUGFIX: Core  | Force disconnect duplicate outbound, stuck peers connections [Parg]
+BUGFIX: Plug  | Magnet URI plugin not always terminating quickly on successfull torrent download [Parg]
+BUGFIX: Plug  | Fixed resource leak in Magnet URI plugin [Parg]
+
+
+
+2014.11.19 | Vuze 5.5.0.0
+
+FEATURE: UI   | Added option to use quick-view rather than 'launch' when double-clicking files [Parg]
+FEATURE: UI   | Tag Discoveries [TuxPaper]
+FEATURE: UI   | Use of ctrl+<space> in download save location field now shows auto-complete suggestions [Parg]
+FEATURE: UI   | History size of saved download locations now configurable [Parg]
+FEATURE: UI   | Added option in torrent options dialog to remove top level folder in multi-file torrents [Parg]
+FEATURE: UI   | RSS subscriptions can now be added via search box [Parg]
+FEATURE: UI   | Added 'Tag groups' to allow more control over tag order in the sidebar [Parg]
+FEATURE: UI   | Tag buttons in Library views now obey visility settings [Parg]
+FEATURE: UI   | Option to only show tag buttons in the complete section of the Library views [Parg]
+FEATURE: UI   | Ability to set short-cut accelerators on a per-config panel basis [Parg]
+FEATURE: UI   | Optional 'selected download' aggregate up/down rates in Library header [Parg]
+FEATURE: UI   | Console UI commands for subscriptions [Parg]
+FEATURE: UI   | Console UI commands for tags [Parg]
+FEATURE: Core | Added ability set an explicit share ratio to help control seeding rules [Parg]
+FEATURE: Core | Option to prevent local tracker host DNS resolution when using SOCKS [Parg]
+FEATURE: Core | Added 'hasNet' to tag constraint language [Parg]
+FEATURE: Core | Speed limit handler ip-sets renamed to peer-sets and now support tags and networks [Parg]
+FEATURE: Core | Support for setting upload and download speeds to 'disabled' [Parg]
+
+CHANGE: UI    | Brazilian Portuguese translation update [Havokdan]
+CHANGE: UI    | Most http links in the UI now have copy-to-clipboard menu option [Parg]
+CHANGE: UI    | Personal share menu enable/disable state not calculated for large torrents due to resource cost [TuxPaper]
+CHANGE: UI    | Automatic renaming oftorrents who's top level folder has changed is now optional [Parg]
+CHANGE: UI    | Prevent disabled sub-rows from being expanded in Library [Parg]
+CHANGE: Core  | Ignore low-noise downloads when considering 'close on download complete' action [Parg]
+CHANGE: Core  | Option to remove low-noise downloads from RSS Feeds [Parg]
+CHANGE: Core  | Handle null-content type being returned by some borked feeds [Parg]
+
+BUGFIX: Core  | Fixed 100% CPU bug in search code [Parg]
+BUGFIX: Core  | Tags weren't being propagated from subscriptions to downloads correctly [Parg]
+BUGFIX: Core  | Fix meta-data download over LT which was causing first peer to be ignored [Parg]
+BUGFIX: Core  | Fixed fast-extension exploit that could be used to waste seeding bandwidth [Parg]
+BUGFIX: Core  | Rotating bloom filters weren't being reset correctly [Parg]
+BUGFIX: Core  | Remove some DNS leaks [Parg]
+
+
+
+2014.07.30 | Vuze 5.4.0.0
+
+FEATURE: UI   | Added 'force start' and 'super seeding' options to the create-torrent wizard [Parg]
+FEATURE: UI   | File filter added to torrent-options dialog [Parg]
+FEATURE: UI   | Minimum/Target share ratio setters added to column menu and torrent options view [Parg]
+FEATURE: UI   | Added 'SHA1' column to files-view [Parg]
+FEATURE: UI   | Added a default save directory to apply when 'best guess' is enabled and nothing matches [Parg]
+FEATURE: UI   | File path names can now be entered into the search box to open the torrent [Parg]
+FEATURE: UI   | New column showing the date of completion of the most recent file [Parg]
+FEATURE: UI   | Added 'initial tags' to the create-torrent wizard [Parg]
+FEATURE: UI   | Enabled networks can now be specified in torrent-options dialog [Parg]
+FEATURE: UI   | Added an 'apply to current' function to tags with initial-save/move-on-complete set [Parg]
+FEATURE: UI   | Added 'availability' button to torrent-options to allow a torrent's availability to be checked before addition [Parg]
+FEATURE: UI   | Tag buttons can now be enabled in Library view; Category buttons can be hidden [Parg]
+FEATURE: UI   | Added 'pause for' option for selected torrents in Library view via Advanced menu [Parg]
+FEATURE: Plug | Friends plugin now supports tag-based sharing to mirror the existing category based sharing [Parg]
+FEATURE: Plug | Improved I2P network integration (new 'I2P Helper Plugin' deprecates existing 'I2P Network Plugin') - see http://wiki.vuze.com/w/I2PHelper_HowTo [Parg]
+FEATURE: Plug | The 'Network Status' plugin now tests connectivity to Vuze services (e.g. pairing service) [Parg]
+FEATURE: Core | Added simple tag constraint language (e.g. to define a tag that contains downloads whose title matches a regex - see wiki) [Parg]
+FEATURE: Core | BEP 40: Canonical Peer Priority [Parg]
+FEATURE: Core | Added 'copy-on-complete' function to tags [Parg]
+FEATURE: Core | HTTPS support for web-seeds [Parg]
+FEATURE: Core | Speed limit handler can now start/stop downloads assigned to particular tags [Parg]
+
+CHANGE: UI    | Brazilian Portuguese translation update [Havokdan]
+CHANGE: UI    | French translation update [Repris d'injustice]
+CHANGE: UI    | Spanish translation update [Valtiel]
+CHANGE: UI    | Basque translation update [Azpidatziak]
+CHANGE: UI    | Network Status plugin results can now be copied to clipboard [Parg]
+CHANGE: UI    | Removed potential duplicate 'media already added' dialogs from inadvertent double-clicking [Parg]
+CHANGE: UI    | Windows: Azureus.exe binary description now set to play better with Firefox/Thunderbird URI launch dialog [TuxPaper]
+CHANGE: UI    | All-peers and console views will now re-open on startup if open on close [Parg]
+CHANGE: UI    | Use consistent sash to separate the tabs area in library views [Parg]
+CHANGE: UI    | Sources view now displays scrape status for stopped downloads [Parg]
+CHANGE: UI    | Update download display name if user renames either single file in a single file torrent or top level folder in a multi-file one [Parg]
+CHANGE: Plug  | Internationalization plugin update [Repris d'injustice]
+CHANGE: Core  | Paused downloads will now not be auto-started if a device attempts to access content [Parg]
+CHANGE: Core  | Reduce CPU usage used for calculating anti-spoof DHT tokens [Parg]
+CHANGE: Core  | Queue rules modified to prevent new seeds from being started if up-limit is reached [Parg]
+
+BUGFIX: UI    | Transparancy settings for mini-bars/transfer-bar not being persisted [Parg]
+BUGFIX: UI    | Primary tracker details were not being updated in detailed sources view [Parg]
+BUGFIX: Core  | Torrent creation was failing when linked folders used and files ignored [Parg]
+BUGFIX: Core  | Paused torrent removal was not removing from tag [Parg]
+BUGFIX: Core  | Torrent private status not being correctly initialised [Gubatron]
+BUGFIX: Core  | Various fixes to network and unresolved address handling [Parg]
+BUGFIX: Core  | Handle missing publish dates in RSS feeds [Parg]
+BUGFIX: Core  | Handle some XML parsing errors better [Parg]
+BUGFIX: Core  | Fix Vuze preventing Windows logoff/shotdown [Parg; Tux]
+BUGFIX: Core  | Async listener thread not always started when needed [Parg]
+BUGFIX: Core  | Handle malformed announce URLs better [Parg]
+
+
+
 2014.02.07 | Vuze 5.3.0.0
 
 FEATURE: UI   | Content selection dialog when more than one file can be played [TuxPaper] 
diff --git a/azureus2/src/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/azureus2/src/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
new file mode 100644
index 0000000..013ca10
--- /dev/null
+++ b/azureus2/src/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
@@ -0,0 +1 @@
+org.gudy.azureus2.core3.util.spi.AENameServiceDescriptor
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCore.java b/azureus2/src/com/aelitis/azureus/core/AzureusCore.java
index 5c5f248..db02154 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCore.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCore.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCoreComponent.java b/azureus2/src/com/aelitis/azureus/core/AzureusCoreComponent.java
index 657655c..61a6ce3 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCoreComponent.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCoreComponent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCoreException.java b/azureus2/src/com/aelitis/azureus/core/AzureusCoreException.java
index ab86f18..b23c209 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCoreException.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCoreException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCoreFactory.java b/azureus2/src/com/aelitis/azureus/core/AzureusCoreFactory.java
index 59c257a..d71535b 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCoreFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCoreFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCoreLifecycleAdapter.java b/azureus2/src/com/aelitis/azureus/core/AzureusCoreLifecycleAdapter.java
index e85f639..090be69 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCoreLifecycleAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCoreLifecycleAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCoreLifecycleListener.java b/azureus2/src/com/aelitis/azureus/core/AzureusCoreLifecycleListener.java
index 8acb5da..b3c82c0 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCoreLifecycleListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCoreLifecycleListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCoreListener.java b/azureus2/src/com/aelitis/azureus/core/AzureusCoreListener.java
index b5d9f9e..aa70331 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCoreListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCoreListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperation.java b/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperation.java
index bb53e08..24210f2 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperation.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperation.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperationListener.java b/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperationListener.java
index 1375f95..eef25ab 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperationListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperationListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperationTask.java b/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperationTask.java
index c7a32e1..e18d68e 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperationTask.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCoreOperationTask.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/AzureusCoreRunningListener.java b/azureus2/src/com/aelitis/azureus/core/AzureusCoreRunningListener.java
index 0b65e0b..44d9f7a 100644
--- a/azureus2/src/com/aelitis/azureus/core/AzureusCoreRunningListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/AzureusCoreRunningListener.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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;
 
 /**
diff --git a/azureus2/src/com/aelitis/azureus/core/backup/BackupManager.java b/azureus2/src/com/aelitis/azureus/core/backup/BackupManager.java
index 19ddf9f..d5f85bd 100644
--- a/azureus2/src/com/aelitis/azureus/core/backup/BackupManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/backup/BackupManager.java
@@ -2,20 +2,19 @@
  * Created on Jun 22, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/backup/BackupManagerFactory.java b/azureus2/src/com/aelitis/azureus/core/backup/BackupManagerFactory.java
index eb1ee7c..a0e1020 100644
--- a/azureus2/src/com/aelitis/azureus/core/backup/BackupManagerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/backup/BackupManagerFactory.java
@@ -2,20 +2,19 @@
  * Created on Jun 22, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/backup/impl/BackupManagerImpl.java b/azureus2/src/com/aelitis/azureus/core/backup/impl/BackupManagerImpl.java
index ee650de..d3d585e 100644
--- a/azureus2/src/com/aelitis/azureus/core/backup/impl/BackupManagerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/backup/impl/BackupManagerImpl.java
@@ -2,20 +2,19 @@
  * Created on Jun 22, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/ClientMessageService.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/ClientMessageService.java
index 79c56d4..da41cad 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/ClientMessageService.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/ClientMessageService.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 31, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.clientmessageservice;
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/ClientMessageServiceClient.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/ClientMessageServiceClient.java
index 52f9755..c2bea8d 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/ClientMessageServiceClient.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/ClientMessageServiceClient.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 31, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.clientmessageservice;
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/AEClientService.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/AEClientService.java
index d4e158d..7f41b26 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/AEClientService.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/AEClientService.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 31, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.clientmessageservice.impl;
@@ -119,6 +116,13 @@ public class AEClientService implements ClientMessageService {
     		error = failure_msg;
     		connect_block.release();  
     	}
+    	
+    	public Object 
+		getConnectionProperty(
+			String property_name)
+		{
+    		return( null );
+		}
     });
     
     if ( !connect_block.reserve( timeout_secs*1000 )){
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientConnection.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientConnection.java
index 160bd8e..1bed408 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientConnection.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 28, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.clientmessageservice.impl;
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientMessage.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientMessage.java
index be4c909..3b81206 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientMessage.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 29, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.clientmessageservice.impl;
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientMessageHandler.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientMessageHandler.java
index 6e7e5fa..12e9909 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientMessageHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/ClientMessageHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 24, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.clientmessageservice.impl;
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/NonBlockingReadWriteService.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/NonBlockingReadWriteService.java
index d81c233..bc39437 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/NonBlockingReadWriteService.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/impl/NonBlockingReadWriteService.java
@@ -1,7 +1,7 @@
 /*
  * Created on Nov 3, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.clientmessageservice.impl;
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClient.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClient.java
index b240e0f..6cf6c2e 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClient.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClient.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientAdapter.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientAdapter.java
index ab27661..9f0ca55 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientFactory.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientFactory.java
index e8d7bf6..fc90eb0 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientListener.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientListener.java
index 2c9d14f..36e6a50 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientMessage.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientMessage.java
index 715febf..843f5fd 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientMessage.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/SecureMessageServiceClientMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientHelper.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientHelper.java
index f4e1754..1cf140e 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientHelper.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientHelper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientImpl.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientImpl.java
index f2bb2e7..79869cf 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientMessageImpl.java b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientMessageImpl.java
index 759f09c..368015b 100644
--- a/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientMessageImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/clientmessageservice/secure/impl/SecureMessageServiceClientMessageImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/content/AzureusContent.java b/azureus2/src/com/aelitis/azureus/core/content/AzureusContent.java
index e5a6791..cf9176a 100644
--- a/azureus2/src/com/aelitis/azureus/core/content/AzureusContent.java
+++ b/azureus2/src/com/aelitis/azureus/core/content/AzureusContent.java
@@ -1,7 +1,7 @@
 /*
  * Created on Dec 19, 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectory.java b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectory.java
index 27a5484..9b2fc11 100644
--- a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectory.java
+++ b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectory.java
@@ -1,7 +1,7 @@
 /*
  * Created on Dec 19, 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectoryListener.java b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectoryListener.java
index 2096c81..37ffb30 100644
--- a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectoryListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectoryListener.java
@@ -2,20 +2,19 @@
  * Created on Apr 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectoryManager.java b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectoryManager.java
index ddeab2f..d7a1632 100644
--- a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectoryManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDirectoryManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Dec 19, 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDownload.java b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDownload.java
index 9b8a9d4..59e422c 100644
--- a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDownload.java
+++ b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentDownload.java
@@ -2,20 +2,19 @@
  * Created on Feb 23, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentFile.java b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentFile.java
index 1dab84b..a0d09c7 100644
--- a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentFile.java
+++ b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentFile.java
@@ -2,20 +2,19 @@
  * Created on Feb 11, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentFilter.java b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentFilter.java
index b01115e..e321d7b 100644
--- a/azureus2/src/com/aelitis/azureus/core/content/AzureusContentFilter.java
+++ b/azureus2/src/com/aelitis/azureus/core/content/AzureusContentFilter.java
@@ -2,20 +2,19 @@
  * Created on Feb 23, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/custom/Customization.java b/azureus2/src/com/aelitis/azureus/core/custom/Customization.java
index 15240e9..1871f4d 100644
--- a/azureus2/src/com/aelitis/azureus/core/custom/Customization.java
+++ b/azureus2/src/com/aelitis/azureus/core/custom/Customization.java
@@ -2,20 +2,19 @@
  * Created on Sep 9, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/custom/CustomizationException.java b/azureus2/src/com/aelitis/azureus/core/custom/CustomizationException.java
index d7c6fd3..79bd237 100644
--- a/azureus2/src/com/aelitis/azureus/core/custom/CustomizationException.java
+++ b/azureus2/src/com/aelitis/azureus/core/custom/CustomizationException.java
@@ -2,20 +2,19 @@
  * Created on Sep 22, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/custom/CustomizationManager.java b/azureus2/src/com/aelitis/azureus/core/custom/CustomizationManager.java
index 67e7b0a..2c3a016 100644
--- a/azureus2/src/com/aelitis/azureus/core/custom/CustomizationManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/custom/CustomizationManager.java
@@ -2,20 +2,19 @@
  * Created on Sep 9, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/custom/CustomizationManagerFactory.java b/azureus2/src/com/aelitis/azureus/core/custom/CustomizationManagerFactory.java
index 1d06e48..741e4d1 100644
--- a/azureus2/src/com/aelitis/azureus/core/custom/CustomizationManagerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/custom/CustomizationManagerFactory.java
@@ -2,20 +2,19 @@
  * Created on Sep 9, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/custom/impl/CustomizationImpl.java b/azureus2/src/com/aelitis/azureus/core/custom/impl/CustomizationImpl.java
index 9a25775..607a124 100644
--- a/azureus2/src/com/aelitis/azureus/core/custom/impl/CustomizationImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/custom/impl/CustomizationImpl.java
@@ -2,20 +2,19 @@
  * Created on Sep 22, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/custom/impl/CustomizationManagerImpl.java b/azureus2/src/com/aelitis/azureus/core/custom/impl/CustomizationManagerImpl.java
index a369642..3289d63 100644
--- a/azureus2/src/com/aelitis/azureus/core/custom/impl/CustomizationManagerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/custom/impl/CustomizationManagerImpl.java
@@ -2,20 +2,19 @@
  * Created on Sep 9, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/DHT.java b/azureus2/src/com/aelitis/azureus/core/dht/DHT.java
index 320c40d..f4c7f6f 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/DHT.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/DHT.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -50,16 +47,21 @@ DHT
 	public static final String	PR_CACHE_AT_CLOSEST_N					= "CacheClosestN";
 	public static final String	PR_ORIGINAL_REPUBLISH_INTERVAL			= "OriginalRepublishInterval";
 	public static final String	PR_CACHE_REPUBLISH_INTERVAL				= "CacheRepublishInterval";
+	public static final String	PR_ENCODE_KEYS							= "EncodeKeys";
+	public static final String	PR_ENABLE_RANDOM_LOOKUP					= "EnableRandomLookup";
 
-	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 short		FLAG_NONE				= 0x0000;
+	public static final short		FLAG_SINGLE_VALUE		= FLAG_NONE;
+	public static final short		FLAG_DOWNLOADING		= 0x0001;
+	public static final short		FLAG_SEEDING			= 0x0002;
+	public static final short		FLAG_MULTI_VALUE		= 0x0004;
+	public static final short		FLAG_STATS				= 0x0008;
+	public static final short		FLAG_ANON				= 0x0010;
+	public static final short		FLAG_PRECIOUS			= 0x0020;
+	public static final short		FLAG_PUT_AND_FORGET		= 0x0040;			// local only
+	public static final short		FLAG_OBFUSCATE_LOOKUP	= 0x0080;			// local only
+	public static final short		FLAG_LOOKUP_FOR_STORE	= 0x0100;			// local only
+	public static final short		FLAG_HIGH_PRIORITY		= 0x0200;			// local only, used in plugin to transmit priority through call stack
 
 	public static final int 	MAX_VALUE_SIZE		= 512;
 
@@ -83,7 +85,7 @@ DHT
 		byte[]					key,
 		String					description,
 		byte[]					value,
-		byte					flags,
+		short					flags,
 		DHTOperationListener	listener );
 	
 		/**
@@ -102,7 +104,7 @@ DHT
 		byte[]					key,
 		String					description,
 		byte[]					value,
-		byte					flags,
+		short					flags,
 		boolean					high_priority,
 		DHTOperationListener	listener );
 	
@@ -111,7 +113,7 @@ DHT
 		byte[]					key,
 		String					description,
 		byte[]					value,
-		byte					flags,
+		short					flags,
 		byte					life_hours,
 		boolean					high_priority,
 		DHTOperationListener	listener );
@@ -121,7 +123,7 @@ DHT
 		byte[]					key,
 		String					description,
 		byte[]					value,
-		byte					flags,
+		short					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,
@@ -149,7 +151,7 @@ DHT
 	get(
 		byte[]					key,
 		String					description,
-		byte					flags,
+		short					flags,
 		int						max_values,
 		long					timeout,
 		boolean					exhaustive,
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/DHTFactory.java b/azureus2/src/com/aelitis/azureus/core/dht/DHTFactory.java
index 30dc482..3acac3e 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/DHTFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/DHTFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -24,8 +21,10 @@ package com.aelitis.azureus.core.dht;
 
 import java.util.Properties;
 
+import com.aelitis.azureus.core.dht.db.DHTDB;
 import com.aelitis.azureus.core.dht.impl.DHTImpl;
 import com.aelitis.azureus.core.dht.nat.DHTNATPuncherAdapter;
+import com.aelitis.azureus.core.dht.router.DHTRouter;
 import com.aelitis.azureus.core.dht.transport.DHTTransport;
 
 /**
@@ -46,4 +45,16 @@ DHTFactory
 	{
 		return( new DHTImpl( transport, properties, storage_adapter, nat_adapter, logger ));
 	}
+	
+	public static DHT
+	create(
+		DHTTransport			transport,
+		DHTRouter				router,
+		DHTDB					database,
+		Properties				properties,
+		DHTStorageAdapter		storage_adapter,
+		DHTLogger				logger )
+	{
+		return( new DHTImpl( transport, router, database, properties, storage_adapter, logger ));
+	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/DHTListener.java b/azureus2/src/com/aelitis/azureus/core/dht/DHTListener.java
index e340ea0..8e628ec 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/DHTListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/DHTListener.java
@@ -4,18 +4,17 @@
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/DHTLogger.java b/azureus2/src/com/aelitis/azureus/core/dht/DHTLogger.java
index 070912a..6b55efe 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/DHTLogger.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/DHTLogger.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Aug-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/DHTOperationAdapter.java b/azureus2/src/com/aelitis/azureus/core/dht/DHTOperationAdapter.java
index 1e644c7..f0531d2 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/DHTOperationAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/DHTOperationAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/DHTOperationListener.java b/azureus2/src/com/aelitis/azureus/core/dht/DHTOperationListener.java
index d562e27..00a59d4 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/DHTOperationListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/DHTOperationListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageAdapter.java b/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageAdapter.java
index d312e8a..393da8b 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageBlock.java b/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageBlock.java
index 8168ec2..40045fd 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageBlock.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageBlock.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageKey.java b/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageKey.java
index 63fb7d0..612eddc 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageKey.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageKey.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageKeyStats.java b/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageKeyStats.java
index f0a4327..007d7f5 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageKeyStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/DHTStorageKeyStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23 May 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControl.java b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControl.java
index 18bb8df..5eee3bb 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -48,6 +45,8 @@ DHTControl
 	public static final int		CACHE_AT_CLOSEST_N_DEFAULT				= 1;
 	public static final int		ORIGINAL_REPUBLISH_INTERVAL_DEFAULT		= 8*60*60*1000;
 	public static final int		CACHE_REPUBLISH_INTERVAL_DEFAULT		=   30*60*1000; 
+	public static final int		ENCODE_KEYS_DEFAULT						= 1;
+	public static final int		ENABLE_RANDOM_DEFAULT					= 1;
 	
 	public void
 	seed(
@@ -56,6 +55,13 @@ DHTControl
 	public boolean
 	isSeeded();
 	
+	/**
+	 * Manually mark things as seeded
+	 */
+	
+	public void
+	setSeeded();
+	
 	public void
 	setSuspended(
 		boolean		susp );
@@ -65,7 +71,7 @@ DHTControl
 		byte[]					key,
 		String					description,
 		byte[]					value,
-		byte					flags,
+		short					flags,
 		byte					life_hours,
 		byte					replication_control,
 		boolean					high_priority,
@@ -83,7 +89,7 @@ DHTControl
 	get(
 		byte[]					key,
 		String					description,
-		byte					flags,
+		short					flags,
 		int						max_values,
 		long					timeout,
 		boolean					exhaustive,
@@ -229,6 +235,9 @@ DHTControl
 		DHTControlListener	l );
 	
 	public void
+	destroy();
+	
+	public void
 	print(
 		boolean	full );
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlActivity.java b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlActivity.java
index 6abcfc8..4de92b3 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlActivity.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlActivity.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlAdapter.java b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlAdapter.java
index f135058..2a031a7 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlContact.java b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlContact.java
index f03a221..4e1ba93 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlContact.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlContact.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlFactory.java b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlFactory.java
index 55ac415..9f2d542 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -25,6 +22,8 @@ package com.aelitis.azureus.core.dht.control;
 
 import com.aelitis.azureus.core.dht.DHTLogger;
 import com.aelitis.azureus.core.dht.control.impl.DHTControlImpl;
+import com.aelitis.azureus.core.dht.db.DHTDB;
+import com.aelitis.azureus.core.dht.router.DHTRouter;
 import com.aelitis.azureus.core.dht.transport.DHTTransport;
 
 /**
@@ -47,6 +46,8 @@ DHTControlFactory
 		int					original_republish_interval,
 		int					cache_republish_interval,
 		int					cache_at_closest_n,
+		boolean				encode_keys,
+		boolean				enable_random_poking,
 		DHTLogger			logger )
 	{
 		return( new DHTControlImpl(
@@ -58,6 +59,42 @@ DHTControlFactory
 						original_republish_interval,
 						cache_republish_interval,
 						cache_at_closest_n,
+						encode_keys,
+						enable_random_poking,
+						logger));
+	}
+	
+	public static DHTControl
+	create(
+		DHTControlAdapter	adapter,
+		DHTTransport		transport,
+		DHTRouter			router,
+		DHTDB				database,
+		int					K,
+		int					B,
+		int					max_rep_per_node,
+		int					search_concurrency,
+		int					lookup_concurrency,
+		int					original_republish_interval,
+		int					cache_republish_interval,
+		int					cache_at_closest_n,
+		boolean				encode_keys,
+		boolean				enable_random_poking,
+		DHTLogger			logger )
+	{
+		return( new DHTControlImpl(
+						adapter,
+						transport, 
+						router,
+						database,
+						K, B, max_rep_per_node,
+						search_concurrency,
+						lookup_concurrency,
+						original_republish_interval,
+						cache_republish_interval,
+						cache_at_closest_n,
+						encode_keys,
+						enable_random_poking,
 						logger));
 	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlListener.java b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlListener.java
index 13b3582..92a1208 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26-Apr-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlStats.java b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlStats.java
index 08d14b0..efd13e9 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/control/DHTControlStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlContactImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlContactImpl.java
index c81b9b4..c8714ae 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlContactImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlContactImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -45,6 +42,16 @@ DHTControlContactImpl
 	{
 		t_contact	= _t_contact;
 	}
+	
+	public
+	DHTControlContactImpl(
+		DHTTransportContact		_t_contact,
+		DHTRouterContact		_r_contact )
+	{
+		t_contact	= _t_contact;
+		r_contact	= _r_contact;
+	}
+	
 	public void
 	setRouterContact(
 		DHTRouterContact		_r_contact )
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlImpl.java
index 857aeef..343ee3c 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.
  *
  */
 
@@ -27,13 +24,10 @@ import java.io.IOException;
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.security.MessageDigest;
 import java.util.*;
 import java.util.Map.Entry;
 
-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;
@@ -53,6 +47,7 @@ import com.aelitis.azureus.core.dht.router.DHTRouter;
 import com.aelitis.azureus.core.dht.router.DHTRouterAdapter;
 import com.aelitis.azureus.core.dht.router.DHTRouterContact;
 import com.aelitis.azureus.core.dht.router.DHTRouterFactory;
+import com.aelitis.azureus.core.dht.router.DHTRouterStats;
 import com.aelitis.azureus.core.dht.transport.*;
 import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP;
 
@@ -96,6 +91,9 @@ DHTControlImpl
 	private int			B;
 	private int			max_rep_per_node;
 	
+	private final boolean	encode_keys;
+	private final boolean	enable_random_poking;
+	
 	private long		router_start_time;
 	private int			router_count;
 		
@@ -111,19 +109,17 @@ DHTControlImpl
 	private long		last_lookup;
 	
 
-	private ListenerManager	listeners 	= ListenerManager.createAsyncManager(
+	private ListenerManager<DHTControlListener>	listeners 	= ListenerManager.createAsyncManager(
 			"DHTControl:listenDispatcher",
-			new ListenerManagerDispatcher()
+			new ListenerManagerDispatcher<DHTControlListener>()
 			{
 				public void
 				dispatch(
-					Object		_listener,
+					DHTControlListener		listener,
 					int			type,
 					Object		value )
-				{
-					DHTControlListener	target = (DHTControlListener)_listener;
-			
-					target.activityChanged((DHTControlActivity)value, type );
+				{			
+					listener.activityChanged((DHTControlActivity)value, type );
 				}
 			});
 
@@ -155,8 +151,10 @@ DHTControlImpl
 		
 	protected AEMonitor	spoof_mon		= new AEMonitor( "DHTControl:spoof" );
 
-	private Cipher 			spoof_cipher;
-	private SecretKey		spoof_key;
+	//private Cipher 			spoof_cipher;
+	//private SecretKey		spoof_key;
+	MessageDigest	spoof_digest;
+	byte[]			spoof_key;
 	
 	private static final int	SPOOF_GEN_HISTORY_SIZE	= 256;
 	
@@ -170,10 +168,20 @@ DHTControlImpl
 				return( size() > SPOOF_GEN_HISTORY_SIZE );
 			}
 		};
-			
-	private byte[]			sid_faraway;
-	private long			sid_faraway_calc_time;
 	
+	private Map<HashWrapper,byte[]>	spoof_gen_history2 = 
+			new LinkedHashMap<HashWrapper,byte[]>(SPOOF_GEN_HISTORY_SIZE,0.75f,true)
+			{
+				protected boolean 
+				removeEldestEntry(
+			   		Map.Entry<HashWrapper,byte[]> eldest) 
+				{
+					return( size() > SPOOF_GEN_HISTORY_SIZE );
+				}
+			};
+		
+	private final static int SPOOF_ID2_SIZE	= 8;
+		
 	private long			last_node_add_check;
 	private byte[]			node_add_check_uninteresting_limit;
 	
@@ -183,6 +191,8 @@ DHTControlImpl
 	private boolean			sleeping;
 	private boolean			suspended;
 	
+	private volatile boolean			destroyed;
+	
 	public
 	DHTControlImpl(
 		DHTControlAdapter	_adapter,
@@ -195,6 +205,8 @@ DHTControlImpl
 		int					_original_republish_interval,
 		int					_cache_republish_interval,
 		int					_cache_at_closest_n,
+		boolean				_encode_keys,
+		boolean				_enable_random_poking,
 		DHTLogger 			_logger )
 	{
 		adapter		= _adapter;
@@ -207,6 +219,8 @@ DHTControlImpl
 		search_concurrency				= _search_concurrency;
 		lookup_concurrency				= _lookup_concurrency;
 		cache_at_closest_n				= _cache_at_closest_n;
+		encode_keys						= _encode_keys;
+		enable_random_poking			= _enable_random_poking;
 		
 			// set this so we don't do initial calculation until reasonably populated
 		
@@ -238,12 +252,17 @@ DHTControlImpl
 		if ( transport.supportsStorage()){
 			
 			try{
+				/*
 				spoof_cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); 
 			
 				KeyGenerator keyGen = KeyGenerator.getInstance("DESede");
 			
 				spoof_key = keyGen.generateKey();
-	
+				*/
+				
+				spoof_digest 	= MessageDigest.getInstance( "MD5" );
+				spoof_key		= new byte[16];
+				RandomUtils.nextSecureBytes( spoof_key );
 			}catch( Throwable e ){
 				
 				Debug.printStackTrace( e );
@@ -281,7 +300,7 @@ DHTControlImpl
 							
 							if ( contact.isAlive()){
 								
-								DHTTransportContact	t_contact = ((DHTControlContactImpl)contact.getAttachment()).getTransportContact();
+								DHTTransportContact	t_contact = ((DHTControlContact)contact.getAttachment()).getTransportContact();
 
 								sorted_contacts.add( t_contact );
 							}
@@ -299,7 +318,7 @@ DHTControlImpl
 							
 							if ( !contact.isAlive()){
 								
-								DHTTransportContact	t_contact = ((DHTControlContactImpl)contact.getAttachment()).getTransportContact();
+								DHTTransportContact	t_contact = ((DHTControlContact)contact.getAttachment()).getTransportContact();
 
 								sorted_contacts.add( t_contact );
 							}
@@ -337,7 +356,7 @@ DHTControlImpl
 
 						if ( !router.isID( rc.getID())){
 							
-							((DHTControlContactImpl)rc.getAttachment()).getTransportContact().createNetworkPositions( false );
+							((DHTControlContact)rc.getAttachment()).getTransportContact().createNetworkPositions( false );
 						}
 					}
 				}
@@ -356,6 +375,88 @@ DHTControlImpl
 			});
 	}
 	
+	public
+	DHTControlImpl(
+		DHTControlAdapter	_adapter,
+		DHTTransport		_transport,
+		DHTRouter			_router,
+		DHTDB				_database,
+		int					_K,
+		int					_B,
+		int					_max_rep_per_node,
+		int					_search_concurrency,
+		int					_lookup_concurrency,
+		int					_original_republish_interval,
+		int					_cache_republish_interval,
+		int					_cache_at_closest_n,
+		boolean				_encode_keys,
+		boolean				_enable_random_poking,
+		DHTLogger 			_logger )
+	{
+		adapter		= _adapter;
+		transport	= _transport;
+		logger		= _logger;
+		
+		K								= _K;
+		B								= _B;
+		max_rep_per_node				= _max_rep_per_node;
+		search_concurrency				= _search_concurrency;
+		lookup_concurrency				= _lookup_concurrency;
+		cache_at_closest_n				= _cache_at_closest_n;
+		encode_keys						= _encode_keys;
+		enable_random_poking			= _enable_random_poking;
+		
+			// set this so we don't do initial calculation until reasonably populated
+		
+		last_dht_estimate_time	= SystemTime.getCurrentTime();
+		
+		database = _database;
+					
+		internal_lookup_pool 	= new ThreadPool("DHTControl:internallookups", lookup_concurrency );
+		internal_put_pool 		= new ThreadPool("DHTControl:internalputs", lookup_concurrency );
+		
+			// external pools queue when full ( as opposed to blocking )
+		
+		external_lookup_pool 	= new ThreadPool("DHTControl:externallookups", EXTERNAL_LOOKUP_CONCURRENCY, true );
+		external_put_pool 		= new ThreadPool("DHTControl:puts", EXTERNAL_PUT_CONCURRENCY, true );
+
+		router	= _router;
+
+		local_contact = transport.getLocalContact();
+		
+		database.setControl( this );
+		
+		node_id_byte_count	= router.getID().length;
+
+		stats = new DHTControlStatsImpl( this );
+
+			// don't bother computing anti-spoof stuff if we don't support value storage
+		
+		if ( transport.supportsStorage()){
+			
+			try{
+				/*
+				spoof_cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); 
+			
+				KeyGenerator keyGen = KeyGenerator.getInstance("DESede");
+			
+				spoof_key = keyGen.generateKey();
+				*/
+				
+				spoof_digest 	= MessageDigest.getInstance( "MD5" );
+				spoof_key		= new byte[16];
+				RandomUtils.nextSecureBytes( spoof_key );
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace( e );
+				
+				logger.log( e );
+			}
+		}
+		
+		transport.setRequestHandler( this );
+	}
+	
 	protected void
 	createRouter(
 		DHTTransportContact		_local_contact)
@@ -403,10 +504,10 @@ DHTControlImpl
 							description,
 							(byte)0,
 							false, 
-							0, 
+							5*60*1000,		// upper bound on this refresh/seeding operation 
 							search_concurrency, 
 							1,
-							router.getK(),	// (parg - removed this) decrease search accuracy for refreshes
+							router.getK()/2,	// (parg - removed this; re-added the /2 on May 2014 to see how it performs) decrease search accuracy for refreshes
 							new lookupResultHandler(new DHTOperationAdapter())
 							{
 								public void
@@ -663,7 +764,7 @@ DHTControlImpl
 			
 			DHTRouterContact	contact	= (DHTRouterContact)it.next();
 			
-			DHTTransportContact	t_contact = ((DHTControlContactImpl)contact.getAttachment()).getTransportContact();
+			DHTTransportContact	t_contact = ((DHTControlContact)contact.getAttachment()).getTransportContact();
 			
 			if ( !t_contact.isValid()){
 				
@@ -685,7 +786,7 @@ DHTControlImpl
 			
 			daos.writeLong( contact.getTimeAlive());
 			
-			DHTTransportContact	t_contact = ((DHTControlContactImpl)contact.getAttachment()).getTransportContact();
+			DHTTransportContact	t_contact = ((DHTControlContact)contact.getAttachment()).getTransportContact();
 			
 			try{
 									
@@ -814,9 +915,24 @@ DHTControlImpl
 		return( seeded );
 	}
 	
+	public void
+	setSeeded()
+	{
+			// manually set as seeded
+		
+		seeded = true;
+		
+		router.seed();
+	}
+	
 	protected void
 	poke()
 	{
+		if ( !enable_random_poking ){
+			
+			return;
+		}
+		
 		long	now = SystemTime.getCurrentTime();
 		
 		if ( 	now < last_lookup ||
@@ -868,7 +984,7 @@ DHTControlImpl
 		byte[]					_unencoded_key,
 		String					_description,
 		byte[]					_value,
-		byte					_flags,
+		short					_flags,
 		byte					_life_hours,
 		byte					_replication_control,
 		boolean					_high_priority,
@@ -935,7 +1051,7 @@ DHTControlImpl
 		byte[]						initial_encoded_key,
 		String						description,
 		DHTTransportValue			value,
-		byte						flags,
+		short						flags,
 		long						timeout,
 		boolean						original_mappings,
 		Set							things_written,
@@ -962,7 +1078,7 @@ DHTControlImpl
 		final byte[]						initial_encoded_key,
 		final String						description,
 		final DHTTransportValue[]			values,
-		final byte							flags,
+		final short							flags,
 		final long							timeout,
 		final boolean						original_mappings,
 		final Set							things_written,
@@ -1023,7 +1139,7 @@ DHTControlImpl
 					high_priority,
 					encoded_key,
 					this_description,
-					flags,
+					(short)( flags | DHT.FLAG_LOOKUP_FOR_STORE ),
 					false, 
 					timeout,
 					search_concurrency,
@@ -1254,7 +1370,7 @@ DHTControlImpl
 		byte[][]								initial_encoded_keys,
 		final String							description,
 		final DHTTransportValue[][]				initial_value_sets,
-		final byte								flags,
+		final short								flags,
 		final List								contacts,
 		final long								timeout,
 		final DHTOperationListenerDemuxer		listener,
@@ -1647,7 +1763,7 @@ DHTControlImpl
 	get(
 		byte[]						unencoded_key,
 		String						description,
-		byte						flags,
+		short						flags,
 		int							max_values,
 		long						timeout,
 		boolean						exhaustive,
@@ -1710,11 +1826,19 @@ DHTControlImpl
 					complete(
 						boolean				timeout )
 					{
-						get_listener.complete(timeout);
-						
-						if ( task_set[0] != null ){
+						try{
+							get_listener.complete(timeout);
+							
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+							
+						}finally{
 							
-							task_set[0].cancel();
+							if ( task_set[0] != null ){
+								
+								task_set[0].cancel();
+							}
 						}
 					}
 				});
@@ -1850,7 +1974,7 @@ DHTControlImpl
 	getSupport(
 		final byte[]						initial_encoded_key,
 		final String						description,
-		final byte							flags,
+		final short							flags,
 		final int							max_values,
 		final long							timeout,
 		final boolean						exhaustive,
@@ -2118,7 +2242,7 @@ DHTControlImpl
 		boolean 					high_priority, 
 		final byte[] 				_lookup_id, 
 		final String 				description, 
-		final byte 					flags, 
+		final short					flags, 
 		final boolean 				value_search, 
 		final long 					timeout, 
 		final int 					concurrency, 
@@ -2269,42 +2393,46 @@ DHTControlImpl
 						runningState = -1;						
 					}
 					
-					if(!error)
-					{
-						// maybe unterminated searches still going on so protect ourselves
-						// against concurrent modification of result set
-						List closest_res = null;
-						try
-						{
-							contacts_to_query_mon.enter();
-
-							if (DHTLog.isOn())
+					try{
+						if(!error){
+						
+							// maybe unterminated searches still going on so protect ourselves
+							// against concurrent modification of result set
+							List closest_res = null;
+							try
 							{
-								DHTLog.log("lookup complete for " + DHTLog.getString(lookup_id));
-								DHTLog.log("    queried = " + DHTLog.getString(contacts_queried));
-								DHTLog.log("    to query = " + DHTLog.getString(contacts_to_query));
-								DHTLog.log("    ok = " + DHTLog.getString(ok_contacts));
+								contacts_to_query_mon.enter();
+	
+								if (DHTLog.isOn())
+								{
+									DHTLog.log("lookup complete for " + DHTLog.getString(lookup_id));
+									DHTLog.log("    queried = " + DHTLog.getString(contacts_queried));
+									DHTLog.log("    to query = " + DHTLog.getString(contacts_to_query));
+									DHTLog.log("    ok = " + DHTLog.getString(ok_contacts));
+								}
+	
+								closest_res = new ArrayList(ok_contacts);
+								// we need to reverse the list as currently closest is at the end
+								Collections.reverse(closest_res);
+	
+								if (timeout <= 0 && !value_search)
+									// we can use the results of this to estimate the DHT size
+									estimateDHTSize(lookup_id, contacts_queried.values(), search_accuracy);
+	
+							} finally
+							{
+								contacts_to_query_mon.exit();
 							}
-
-							closest_res = new ArrayList(ok_contacts);
-							// we need to reverse the list as currently closest is at the end
-							Collections.reverse(closest_res);
-
-							if (timeout <= 0 && !value_search)
-								// we can use the results of this to estimate the DHT size
-								estimateDHTSize(lookup_id, contacts_queried.values(), search_accuracy);
-
-						} finally
-						{
-							contacts_to_query_mon.exit();
+							
+							handler.closest(closest_res);
 						}
 						
-						handler.closest(closest_res);
-					}
-					
-					handler.complete(timeout_occurred);
+						handler.complete(timeout_occurred);
+						
+					}finally{
 					
-					releaseToPool();
+						releaseToPool();
+					}
 				}
 				
 				private synchronized boolean reserve()
@@ -2737,7 +2865,7 @@ DHTControlImpl
 									closest.sendFindValue(replyHandler, lookup_id, rem, flags);
 								} else
 								{
-									closest.sendFindNode(replyHandler, lookup_id);
+									closest.sendFindNode(replyHandler, lookup_id, flags );
 								}
 							} finally
 							{
@@ -2992,7 +3120,7 @@ DHTControlImpl
 				str = "["  + str + "]";
 			}
 			
-			return( contact.getAddress().getAddress() + " - " + str );
+			return( AddressUtils.getHostAddress( contact.getAddress()) + " - " + str );
 		}
 	}
 	
@@ -3092,9 +3220,9 @@ DHTControlImpl
 			}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
@@ -3209,9 +3337,18 @@ DHTControlImpl
 			DHTLog.log( "queryStoreRequest from " + DHTLog.getString( originating_contact )+ ", header_len=" + header_len + ", keys=" + keys.size());
 		}
 
-		int	rand = generateSpoofID( originating_contact );
+		if ( originating_contact.getRandomIDType() == DHTTransportContact.RANDOM_ID_TYPE1 ){
 		
-		originating_contact.setRandomID( rand );
+			int	rand = generateSpoofID( originating_contact );
+		
+			originating_contact.setRandomID( rand );
+			
+		}else{
+			
+			byte[]	rand = generateSpoofID2( originating_contact );
+			
+			originating_contact.setRandomID2( rand );
+		}
 
 		return( database.queryStore( originating_contact, header_len, keys ));
 	}
@@ -3254,9 +3391,18 @@ DHTControlImpl
 		
 		l.toArray( res );
 				
-		int	rand = generateSpoofID( originating_contact );
+		if ( originating_contact.getRandomIDType() == DHTTransportContact.RANDOM_ID_TYPE1 ){
+			
+			int	rand = generateSpoofID( originating_contact );
 		
-		originating_contact.setRandomID( rand );
+			originating_contact.setRandomID( rand );
+			
+		}else{
+			
+			byte[]	rand = generateSpoofID2( originating_contact );
+			
+			originating_contact.setRandomID2( rand );
+		}
 		
 		return( res );
 	}
@@ -3266,7 +3412,7 @@ DHTControlImpl
 		DHTTransportContact originating_contact, 
 		byte[]				key,
 		int					max_values,
-		byte				flags )
+		short				flags )
 	{
 		if ( DHTLog.isOn()){
 			DHTLog.log( "findValueRequest from " + DHTLog.getString( originating_contact.getID()));
@@ -3276,6 +3422,13 @@ DHTControlImpl
 					
 		if ( result != null ){
 			
+			if ( originating_contact.getRandomIDType() == DHTTransportContact.RANDOM_ID_TYPE2 ){
+				
+				byte[]	rand = generateSpoofID2( originating_contact );
+				
+				originating_contact.setRandomID2( rand );
+			}
+			
 			router.contactAlive( originating_contact.getID(), new DHTControlContactImpl(originating_contact));
 
 			DHTStorageBlock	block_details = database.getKeyBlockDetails( key );
@@ -3306,7 +3459,7 @@ DHTControlImpl
 	requestPing(
 		DHTRouterContact	contact )
 	{
-		((DHTControlContactImpl)contact.getAttachment()).getTransportContact().sendPing(
+		((DHTControlContact)contact.getAttachment()).getTransportContact().sendPing(
 				new DHTTransportReplyHandlerAdapter()
 				{
 					public void
@@ -3532,7 +3685,7 @@ DHTControlImpl
 			}
 		}
 		
-		final DHTTransportContact	t_contact = ((DHTControlContactImpl)new_contact.getAttachment()).getTransportContact();
+		final DHTTransportContact	t_contact = ((DHTControlContact)new_contact.getAttachment()).getTransportContact();
 
 		final boolean[]	anti_spoof_done	= { false };
 		
@@ -3643,7 +3796,8 @@ DHTControlImpl
 							router.contactDead( _contact.getID(), false);
 						}
 					},
-					t_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] );
+					t_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20],
+					DHT.FLAG_LOOKUP_FOR_STORE );
 						
 		}else{
 			
@@ -3749,7 +3903,8 @@ DHTControlImpl
 									router.contactDead( _contact.getID(), false);
 								}
 							},
-							t_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] );
+							t_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20],
+							DHT.FLAG_LOOKUP_FOR_STORE );
 				}
 			}
 		}
@@ -3772,7 +3927,7 @@ DHTControlImpl
 		
 		for (int i=0;i<size;i++){
 			
-			sorted_set.add(((DHTControlContactImpl)((DHTRouterContact)l.get(i)).getAttachment()).getTransportContact());
+			sorted_set.add(((DHTControlContact)((DHTRouterContact)l.get(i)).getAttachment()).getTransportContact());
 		}
 		
 		return( sorted_set );
@@ -3842,13 +3997,31 @@ DHTControlImpl
 	encodeKey(
 		byte[]		key )
 	{
-		byte[]	temp = new SHA1Simple().calculateHash( key );
-		
-		byte[]	result =  new byte[node_id_byte_count];
-		
-		System.arraycopy( temp, 0, result, 0, node_id_byte_count );
-		
-		return( result );
+		if ( encode_keys ){
+			
+			byte[]	temp = new SHA1Simple().calculateHash( key );
+			
+			byte[]	result =  new byte[node_id_byte_count];
+			
+			System.arraycopy( temp, 0, result, 0, node_id_byte_count );
+			
+			return( result );
+			
+		}else{
+			
+			if ( key.length == node_id_byte_count ){
+				
+				return( key );
+				
+			}else{
+				
+				byte[]	result =  new byte[node_id_byte_count];
+				
+				System.arraycopy( key, 0, result, 0, Math.min( node_id_byte_count, key.length ));
+				
+				return( result );
+			}
+		}
 	}
 	
 	public int
@@ -4193,7 +4366,11 @@ DHTControlImpl
 					rem_vals++;
 				}
 				
-				combined_dht_estimate = rem_average / rem_vals;
+				long[] router_stats = router.getStats().getStats();
+				
+				long	router_contacts = router_stats[DHTRouterStats.ST_CONTACTS] + router_stats[DHTRouterStats.ST_REPLACEMENTS];
+				
+				combined_dht_estimate = Math.max( rem_average / rem_vals, router_contacts );
 				
 				long	test_val 	= 10;
 				int		test_mag	= 1;
@@ -4237,51 +4414,78 @@ DHTControlImpl
 		return( res );
 	}
 	
-	protected int
+	private int
 	generateSpoofID(
 		DHTTransportContact	contact )
 	{
-		if ( spoof_cipher == null  ){
+		if ( spoof_digest == null  ){
 			
 			return( 0 );
 		}
 		
-		if ( transport.getNetwork() != DHT.NW_CVS ){
+		InetAddress iad = contact.getAddress().getAddress();
 		
-			long	now = SystemTime.getMonotonousTime();
+		try{
+			spoof_mon.enter();
 			
-			byte[] originator_id 	= contact.getID();
-			byte[] my_id			= local_contact.getID();
-
-			if ( sid_faraway == null || now - sid_faraway_calc_time > 1*60*1000 ){
+				// 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
+			
+			Integer existing = spoof_gen_history.get( iad );
+			
+			if ( existing != null ){
+				
+				//System.out.println( "anti-spoof: cached " + existing + " for " + contact.getAddress() + " - total=" + spoof_gen_history.size());
 				
-				int	c_factor = router.getK() * 2;
+				return( existing );
+			}
+
+			byte[]	address = iad.getAddress();
 	
+			//spoof_cipher.init(Cipher.ENCRYPT_MODE, spoof_key ); 
+			//byte[]	data_out = spoof_cipher.doFinal( address );
 	
-				List<DHTTransportContact>	closest_contacts = getClosestContactsList( my_id, c_factor, true );
-				
-				if ( closest_contacts.size() >= c_factor ){
-					
-					sid_faraway = closest_contacts.get( closest_contacts.size()-1).getID();
-					
-					sid_faraway_calc_time = now;
-				}
+			byte[]	data_in = spoof_key.clone();
+			
+			for ( int i=0;i<address.length;i++){
+				data_in[i] ^= address[i];
 			}
 			
-			if ( sid_faraway != null ){
+			byte[] data_out = spoof_digest.digest( data_in );
+						
+			int	res =  	(data_out[0]<<24)&0xff000000 |
+						(data_out[1] << 16)&0x00ff0000 | 
+						(data_out[2] << 8)&0x0000ff00 | 
+						data_out[3]&0x000000ff;
 			
-				int res = computeAndCompareDistances( sid_faraway, originator_id, my_id );
-				
-				//System.out.println( "cac: " + DHTLog.getString2( sid_faraway ) + ", " +  DHTLog.getString2( originator_id ) +  ", " + DHTLog.getString2( my_id ) + " -> " + res );
-				
-				if ( res < 0 ){
-					
-					return( 0 );
-				}
-			}
+			//System.out.println( "anti-spoof: generating " + res + " for " + contact.getAddress() + " - total=" + spoof_gen_history.size());
+
+			spoof_gen_history.put( iad, res );
+			
+			return( res );
+
+		}catch( Throwable e ){
+			
+			logger.log(e);
+			
+		}finally{
+			
+			spoof_mon.exit();
 		}
 		
-		InetAddress iad = contact.getAddress().getAddress();
+		return( 0 );
+	}
+	
+	private byte[]
+	generateSpoofID2(
+		DHTTransportContact	contact )
+	{
+		if ( spoof_digest == null  ){
+			
+			return( new byte[ SPOOF_ID2_SIZE ]);
+		}
+		
+		HashWrapper cid = new HashWrapper( contact.getID());
 		
 		try{
 			spoof_mon.enter();
@@ -4289,7 +4493,7 @@ DHTControlImpl
 				// 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
 			
-			Integer existing = spoof_gen_history.get( iad );
+			byte[] existing = spoof_gen_history2.get( cid );
 			
 			if ( existing != null ){
 				
@@ -4298,20 +4502,27 @@ DHTControlImpl
 				return( existing );
 			}
 						
-			spoof_cipher.init(Cipher.ENCRYPT_MODE, spoof_key ); 
-		
-			byte[]	address = iad.getAddress();
-					
-			byte[]	data_out = spoof_cipher.doFinal( address );
-	
-			int	res =  	(data_out[0]<<24)&0xff000000 |
-						(data_out[1] << 16)&0x00ff0000 | 
-						(data_out[2] << 8)&0x0000ff00 | 
-						data_out[3]&0x000000ff;
+			// spoof_cipher.init(Cipher.ENCRYPT_MODE, spoof_key ); 						
+			// byte[]	data_out = spoof_cipher.doFinal( cid.getBytes());
+			
+			byte[] 	cid_bytes 	= cid.getBytes();
+			byte[]	data_in 	= spoof_key.clone();
+			
+			int	byte_count = Math.min( cid_bytes.length, data_in.length );
+			
+			for ( int i=0;i<byte_count;i++){
+				data_in[i] ^= cid_bytes[i];
+			}
+			
+			byte[] data_out = spoof_digest.digest( data_in );
+			
+			byte[] res = new byte[SPOOF_ID2_SIZE];
+			
+			System.arraycopy( data_out, 0, res, 0, SPOOF_ID2_SIZE );
 			
 			//System.out.println( "anti-spoof: generating " + res + " for " + contact.getAddress() + " - total=" + spoof_gen_history.size());
 
-			spoof_gen_history.put( iad, res );
+			spoof_gen_history2.put( cid, res );
 			
 			return( res );
 
@@ -4324,7 +4535,7 @@ DHTControlImpl
 			spoof_mon.exit();
 		}
 		
-		return( 0 );
+		return( new byte[ SPOOF_ID2_SIZE ]);
 	}
 	
 	public boolean
@@ -4332,7 +4543,30 @@ DHTControlImpl
 		DHTTransportContact 	c,
 		boolean					direct )
 	{
-		boolean	ok = c.getRandomID() == generateSpoofID( c );
+		boolean	ok;
+		
+		if ( c.getRandomIDType() == DHTTransportContact.RANDOM_ID_TYPE1 ){
+			
+			ok = c.getRandomID() == generateSpoofID( c );
+			
+		}else{
+			
+			byte[]	r1 = c.getRandomID2();
+			byte[]	r2 = generateSpoofID2( c );
+			
+			if ( r1 == null && r2 == null ){
+				
+				ok = true;
+				
+			}else if ( r1 == null || r2 == null ){
+				
+				ok = false;
+				
+			}else{
+				
+				ok = Arrays.equals( r1, r2 );
+			}
+		}
 		
 		if ( DHTLog.CONTACT_VERIFY_TRACE ){
 				
@@ -4374,7 +4608,7 @@ DHTControlImpl
 			
 			DHTRouterContact	rc = (DHTRouterContact)contacts.get(i);
 
-			((DHTControlContactImpl)rc.getAttachment()).getTransportContact().sendPing(
+			((DHTControlContact)rc.getAttachment()).getTransportContact().sendPing(
 					new DHTTransportReplyHandlerAdapter()
 					{
 						public void
@@ -4410,6 +4644,22 @@ DHTControlImpl
 	}
 	
 	public void
+	destroy()
+	{
+		destroyed = true;
+		
+		if ( router != null ){
+			
+			router.destroy();
+		}
+		
+		if ( database != null ){
+			
+			database.destroy();
+		}
+	}
+	
+	public void
 	print(
 		boolean		full )
 	{
@@ -4421,10 +4671,10 @@ DHTControlImpl
 			np_str += (j==0?"":",") + nps[j];
 		}
 		
-		logger.log( "DHT Details: external IP = " + transport.getLocalContact().getAddress() + 
-						", network = " + transport.getNetwork() +
-						", protocol = V" + transport.getProtocolVersion() + 
-						", nps = " + np_str );
+		logger.log( "DHT Details: external address=" + transport.getLocalContact().getAddress() + 
+						", network=" + transport.getNetwork() +
+						", protocol=V" + transport.getProtocolVersion() + 
+						", nps=" + np_str + ", est_size=" + getTransportEstimatedDHTSize());
 		
 		router.print();
 		
@@ -4867,6 +5117,12 @@ DHTControlImpl
 			return( delegate.getClockSkew());	
 		}
 		
+		public int
+		getRandomIDType()
+		{
+			return( delegate.getRandomIDType());
+		}
+		
 		public void
 		setRandomID(
 			int	id )
@@ -4880,12 +5136,31 @@ DHTControlImpl
 			return( delegate.getRandomID());
 		}
 		
+		public void
+		setRandomID2(
+			byte[]		id )
+		{
+			delegate.setRandomID2( id );
+		}
+		
+		public byte[]
+		getRandomID2()
+		{
+			return(delegate.getRandomID2());
+		}
+		
 		public String
 		getName()
 		{
 			return( delegate.getName());
 		}
 		
+		public byte[]
+		getBloomKey()
+		{
+			return(delegate.getBloomKey());
+		}
+		
 		public InetSocketAddress
 		getAddress()
 		{
@@ -4904,6 +5179,12 @@ DHTControlImpl
 			return( getAddress());
 		}
 		
+		public Map<String, Object> 
+		exportContactToMap()
+		{
+			return( delegate.exportContactToMap());
+		}
+		
 		public boolean
 		isAlive(
 			long		timeout )
@@ -4975,9 +5256,10 @@ DHTControlImpl
 		public void
 		sendFindNode(
 			DHTTransportReplyHandler	handler,
-			byte[]						id )
+			byte[]						id,
+			short						flags )
 		{
-			delegate.sendFindNode(handler, id);
+			delegate.sendFindNode( handler, id, flags );
 		}
 			
 		public void
@@ -4985,9 +5267,9 @@ DHTControlImpl
 			DHTTransportReplyHandler	handler,
 			byte[]						key,
 			int							max_values,
-			byte						flags )
+			short						flags )
 		{
-			delegate.sendFindValue(handler, key, max_values, flags);
+			delegate.sendFindValue( handler, key, max_values, flags);
 		}
 			
 		public void
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlStatsImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlStatsImpl.java
index 5604207..f37dbef 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlStatsImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/control/impl/DHTControlStatsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDB.java b/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDB.java
index 7e006aa..b4272e6 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDB.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDB.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -57,7 +54,7 @@ DHTDB
 	store(
 		HashWrapper		key,
 		byte[]			value,
-		byte			flags,
+		short			flags,
 		byte			life_hours,
 		byte			replication_control );
 	
@@ -111,7 +108,7 @@ DHTDB
 		DHTTransportContact		reader,
 		HashWrapper				key,
 		int						max_values,
-		byte					flags,
+		short					flags,
 		boolean					external_request );
 		
 		/**
@@ -167,6 +164,9 @@ DHTDB
 		boolean			susp );
 	
 	public void
+	destroy();
+	
+	public void
 	print(
 		boolean		full );
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBFactory.java b/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBFactory.java
index b35c67f..2e72fec 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBLookupResult.java b/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBLookupResult.java
index 5b0b11b..8aa234c 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBLookupResult.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBLookupResult.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBStats.java b/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBStats.java
index 2058273..277ffb7 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Apr-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBValue.java b/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBValue.java
index 2066bd7..a754bde 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBValue.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/db/DHTDBValue.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBImpl.java
index 8d0c1dc..0f7af50 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -31,6 +28,7 @@ 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.AddressUtils;
 import org.gudy.azureus2.core3.util.ByteArrayHashMap;
 import org.gudy.azureus2.core3.util.ByteFormatter;
 import org.gudy.azureus2.core3.util.Debug;
@@ -40,6 +38,7 @@ import org.gudy.azureus2.core3.util.SimpleTimer;
 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 com.aelitis.azureus.core.dht.DHT;
 import com.aelitis.azureus.core.dht.DHTLogger;
@@ -153,9 +152,18 @@ DHTDBImpl
 			}
 		};
 	
+	private TimerEventPeriodic		precious_timer;
+	private TimerEventPeriodic		original_republish_timer;
+	private TimerEventPeriodic		cache_republish_timer;
+	private TimerEventPeriodic		bloom_timer;
+	private TimerEventPeriodic		survey_timer;
+	
+	
 	private boolean	sleeping;
 	private boolean	suspended;
-		
+	
+	private volatile boolean	destroyed;
+	
 	public
 	DHTDBImpl(
 		DHTStorageAdapter	_adapter,
@@ -177,7 +185,7 @@ DHTDBImpl
 		
 		if ( ENABLE_PRECIOUS_STUFF ){
 			
-			SimpleTimer.addPeriodicEvent(
+			precious_timer = SimpleTimer.addPeriodicEvent(
 				"DHTDB:precious",
 				PRECIOUS_CHECK_INTERVAL/4,
 				true, // absolute, we don't want effective time changes (computer suspend/resume) to shift these
@@ -192,75 +200,80 @@ DHTDBImpl
 				});
 		}
 		
-		SimpleTimer.addPeriodicEvent(
-			"DHTDB:op",
-			original_republish_interval,
-			true, // absolute, we don't want effective time changes (computer suspend/resume) to shift these
-			new TimerEventPerformer()
-			{
-				public void
-				perform(
-					TimerEvent	event )
-				{
-					logger.log( "Republish of original mappings starts" );
-					
-					long	start 	= SystemTime.getCurrentTime();
-					
-					int	stats = republishOriginalMappings();
-					
-					long	end 	= SystemTime.getCurrentTime();
-
-					logger.log( "Republish of original mappings completed in " + (end-start) + ": " +
-								"values = " + stats );
-
-				}
-			});
-					
-				// random skew here so that cache refresh isn't very synchronised, as the optimisations
-				// regarding non-republising benefit from this 
+		if ( original_republish_interval > 0 ){
 			
-		SimpleTimer.addPeriodicEvent(
-				"DHTDB:cp",
-				cache_republish_interval + 10000 - RandomUtils.nextInt(20000),
-				true,	// absolute, we don't want effective time changes (computer suspend/resume) to shift these
+			original_republish_timer = SimpleTimer.addPeriodicEvent(
+				"DHTDB:op",
+				original_republish_interval,
+				true, // absolute, we don't want effective time changes (computer suspend/resume) to shift these
 				new TimerEventPerformer()
 				{
 					public void
 					perform(
 						TimerEvent	event )
 					{
-						logger.log( "Republish of cached mappings starts" );
+						logger.log( "Republish of original mappings starts" );
 						
 						long	start 	= SystemTime.getCurrentTime();
 						
-						int[]	stats = republishCachedMappings();		
+						int	stats = republishOriginalMappings();
 						
 						long	end 	= SystemTime.getCurrentTime();
-
-						logger.log( "Republish of cached mappings completed in " + (end-start) + ": " +
-									"values = " + stats[0] + ", keys = " + stats[1] + ", ops = " + stats[2]);
-						
-						if ( force_original_republish ){
-							
-							force_original_republish	= false;
+	
+						logger.log( "Republish of original mappings completed in " + (end-start) + ": " +
+									"values = " + stats );
+	
+					}
+				});
+		}
+		
+		if ( cache_republish_interval > 0 ){
+			
+					// random skew here so that cache refresh isn't very synchronised, as the optimisations
+					// regarding non-republising benefit from this 
+				
+			cache_republish_timer = SimpleTimer.addPeriodicEvent(
+					"DHTDB:cp",
+					cache_republish_interval + 10000 - RandomUtils.nextInt(20000),
+					true,	// absolute, we don't want effective time changes (computer suspend/resume) to shift these
+					new TimerEventPerformer()
+					{
+						public void
+						perform(
+							TimerEvent	event )
+						{
+							logger.log( "Republish of cached mappings starts" );
 							
-							logger.log( "Force republish of original mappings due to router change starts" );
+							long	start 	= SystemTime.getCurrentTime();
 							
-							start 	= SystemTime.getCurrentTime();
+							int[]	stats = republishCachedMappings();		
 							
-							int stats2 = republishOriginalMappings();
+							long	end 	= SystemTime.getCurrentTime();
+	
+							logger.log( "Republish of cached mappings completed in " + (end-start) + ": " +
+										"values = " + stats[0] + ", keys = " + stats[1] + ", ops = " + stats[2]);
 							
-							end 	= SystemTime.getCurrentTime();
-
-							logger.log( "Force republish of original mappings due to router change completed in " + (end-start) + ": " +
-										"values = " + stats2 );
+							if ( force_original_republish ){
+								
+								force_original_republish	= false;
+								
+								logger.log( "Force republish of original mappings due to router change starts" );
+								
+								start 	= SystemTime.getCurrentTime();
+								
+								int stats2 = republishOriginalMappings();
+								
+								end 	= SystemTime.getCurrentTime();
+	
+								logger.log( "Force republish of original mappings due to router change completed in " + (end-start) + ": " +
+											"values = " + stats2 );
+							}
 						}
-					}
-				});
-		
+					});
+		}
 	
 		
-		SimpleTimer.addPeriodicEvent(
+		bloom_timer = SimpleTimer.addPeriodicEvent(
 				"DHTDB:bloom",
 				IP_BLOOM_FILTER_REBUILD_PERIOD,
 				new TimerEventPerformer()
@@ -283,7 +296,7 @@ DHTDBImpl
 				
 		if ( survey_enabled ){
 			
-			SimpleTimer.addPeriodicEvent(
+			survey_timer = SimpleTimer.addPeriodicEvent(
 					"DHTDB:survey",
 					SURVEY_PERIOD,
 					true, 
@@ -338,7 +351,7 @@ DHTDBImpl
 	store(
 		HashWrapper		key,
 		byte[]			value,
-		byte			flags,
+		short			flags,
 		byte			life_hours,
 		byte			replication_control )
 	{
@@ -495,7 +508,7 @@ DHTDBImpl
 		DHTTransportContact		reader,
 		HashWrapper				key,
 		int						max_values,	// 0 -> all
-		byte					flags,
+		short					flags,
 		boolean					external_request )	
 	{
 		try{
@@ -1269,7 +1282,8 @@ DHTDBImpl
 								}
 							}
 						},
-						contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] );
+						contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20],
+						DHT.FLAG_LOOKUP_FOR_STORE );
 				
 				sem.reserve();
 			}
@@ -1395,7 +1409,8 @@ DHTDBImpl
 												router.contactDead( _contact.getID(), false);
 											}
 										},
-										contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] );
+										contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20],
+										DHT.FLAG_LOOKUP_FOR_STORE );
 							}
 					}
 				}
@@ -2650,7 +2665,7 @@ DHTDBImpl
 								continue;
 							}
 							
-							addresses.add( c.getAddress().getAddress().getAddress());
+							addresses.add( AddressUtils.getAddressBytes( c.getAddress()));
 							
 							SurveyContactState	contact_state = survey_state.get( new HashWrapper( c.getID()));
 							
@@ -2748,7 +2763,7 @@ DHTDBImpl
 							SurveyContactState target = potential_targets.get( i );
 							
 							if ( 	bad_addresses.size() > 0 && 
-									bad_addresses.contains( new HashWrapper( target.getContact().getAddress().getAddress().getAddress()))){
+									bad_addresses.contains( new HashWrapper( AddressUtils.getAddressBytes( target.getContact().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
@@ -2864,36 +2879,42 @@ DHTDBImpl
 					}
 				};
 				
+			if ( d_contact.getRandomIDType() != DHTTransportContact.RANDOM_ID_TYPE1 ){
+				
+				Debug.out( "derp" );
+			}
+			
 			if ( d_contact.getRandomID() == 0 ){
 				
 				d_contact.sendFindNode(
-						new DHTTransportReplyHandlerAdapter()
+					new DHTTransportReplyHandlerAdapter()
+					{
+						public void
+						findNodeReply(
+							DHTTransportContact 	_contact,
+							DHTTransportContact[]	_contacts )
+						{	
+							store_exec.run();
+						}
+				
+						public void
+						failed(
+							DHTTransportContact 	_contact,
+							Throwable				_error )
 						{
-							public void
-							findNodeReply(
-								DHTTransportContact 	_contact,
-								DHTTransportContact[]	_contacts )
-							{	
-								store_exec.run();
-							}
-					
-							public void
-							failed(
-								DHTTransportContact 	_contact,
-								Throwable				_error )
-							{
-								try{
-									this_mon.enter();
-										
-									contact.contactFailed();
-										
-								}finally{
+							try{
+								this_mon.enter();
 									
-									this_mon.exit();
-								}
+								contact.contactFailed();
+									
+							}finally{
+								
+								this_mon.exit();
 							}
-						},
-						d_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20] );
+						}
+					},
+					d_contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ANTI_SPOOF2?new byte[0]:new byte[20],
+					DHT.FLAG_LOOKUP_FOR_STORE );
 			}else{
 				
 				store_exec.run();
@@ -3328,7 +3349,7 @@ DHTDBImpl
 			logger.log( "Banning " + contact.getString() + " due to store flooding (" + reason + ")" );
 			
 			ip_filter.ban( 
-					contact.getAddress().getAddress().getHostAddress(),
+					AddressUtils.getHostAddress( contact.getAddress()),
 					"DHT: Sender stored excessive entries at this node (" + reason + ")", false );
 		}
 	}
@@ -3346,7 +3367,9 @@ DHTDBImpl
 		
 			// However, for CVS DHTs we can have sizes of 1000 or less. 
 		
-		int	hit_count = ip_count_bloom_filter.add( contact.getAddress().getAddress().getAddress());
+		byte[] bloom_key = contact.getBloomKey();
+		
+		int	hit_count = ip_count_bloom_filter.add( bloom_key );
 		
 		if ( DHTLog.GLOBAL_BLOOM_TRACE ){
 		
@@ -3372,7 +3395,9 @@ DHTDBImpl
 	decrementValueAdds(
 		DHTTransportContact	contact )
 	{
-		int	hit_count = ip_count_bloom_filter.remove( contact.getAddress().getAddress().getAddress());
+		byte[] bloom_key = contact.getBloomKey();
+		
+		int	hit_count = ip_count_bloom_filter.remove( bloom_key );
 
 		if ( DHTLog.GLOBAL_BLOOM_TRACE ){
 			
@@ -3421,7 +3446,9 @@ DHTDBImpl
 						
 						// logger.log( "    adding " + val.getOriginator().getAddress());
 						
-						int	hits = new_filter.add( val.getOriginator().getAddress().getAddress().getAddress());
+						byte[] bloom_key = val.getOriginator().getBloomKey();
+						
+						int	hits = new_filter.add( bloom_key );
 						
 						if ( hits > max_hits ){
 							
@@ -3607,6 +3634,33 @@ DHTDBImpl
 		}
 	}
 	
+	public void
+	destroy()
+	{
+		destroyed	= true;
+				
+		if ( precious_timer != null ){
+			
+			precious_timer.cancel();
+		}
+		if ( original_republish_timer != null ){
+				
+			original_republish_timer.cancel();
+		}
+		if ( cache_republish_timer != null ){
+			
+			cache_republish_timer.cancel();
+		}
+		if ( bloom_timer != null ){
+			
+			bloom_timer.cancel();
+		}
+		if ( survey_timer != null ){
+			
+			survey_timer.cancel();
+		}
+	}
+	
 	protected class
 	adapterFacade
 		implements DHTStorageAdapter
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBMapping.java b/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBMapping.java
index c23a101..493aafd 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBMapping.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBMapping.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -349,7 +346,7 @@ DHTDBMapping
 	get(
 		DHTTransportContact		by_who,
 		int						max,
-		byte					flags )
+		short					flags )
 	{
 		if ((flags & DHT.FLAG_STATS) != 0 ){
 			
@@ -392,6 +389,9 @@ DHTDBMapping
 		
 		Map<HashWrapper,DHTDBValueImpl>[]	maps = new Map[]{ direct_originator_map_may_be_null, indirect_originator_value_map };
 		
+			// currently we don't filter return values by seeding/downloading flag as scraping is implemented by normal
+			// get operations and if we filtered out seeds for seeds then the caller would see zero seeds. fix oneday!
+		
 		for (int i=0;i<maps.length;i++){
 			
 			Map<HashWrapper,DHTDBValueImpl>			map	= maps[i];
@@ -918,13 +918,13 @@ DHTDBMapping
 
 		DHTTransportContact	originator = value.getOriginator();
 
-		byte[] address_bytes = originator.getAddress().getAddress().getAddress();
+		byte[] bloom_key = originator.getBloomKey();
 		
 		// System.out.println( "addToBloom: existing=" + ip_count_bloom_filter );
 
 		if ( ip_count_bloom_filter == null ){
 			
-			ip_count_bloom_filter = address_bytes;
+			ip_count_bloom_filter = bloom_key;
 			
 			return;
 		}
@@ -944,7 +944,7 @@ DHTDBMapping
 			filter = (BloomFilter)ip_count_bloom_filter;
 		}
 								
-		int	hit_count = filter.add( address_bytes );
+		int	hit_count = filter.add( bloom_key );
 		
 		if ( DHTLog.LOCAL_BLOOM_TRACE ){
 		
@@ -975,13 +975,13 @@ DHTDBMapping
 			return;
 		}
 		
-		byte[] address_bytes = originator.getAddress().getAddress().getAddress();
+		byte[] bloom_key = originator.getBloomKey();
 
 		if ( ip_count_bloom_filter instanceof byte[] ){
 
 			byte[]	existing_address = (byte[])ip_count_bloom_filter;
 
-			if ( Arrays.equals( address_bytes, existing_address )){
+			if ( Arrays.equals( bloom_key, existing_address )){
 				
 				ip_count_bloom_filter = null;
 			}
@@ -991,7 +991,7 @@ DHTDBMapping
 		
 		BloomFilter filter = (BloomFilter)ip_count_bloom_filter;
 		
-		int	hit_count = filter.remove( address_bytes );
+		int	hit_count = filter.remove( bloom_key );
 		
 		if (  DHTLog.LOCAL_BLOOM_TRACE ){
 		
@@ -1041,7 +1041,7 @@ DHTDBMapping
 					
 					// logger.log( "    adding " + val.getOriginator().getAddress());
 					
-					int	hits = new_filter.add( val.getOriginator().getAddress().getAddress().getAddress());
+					int	hits = new_filter.add( val.getOriginator().getBloomKey());
 	
 					if ( hits > max_hits ){
 						
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBValueImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBValueImpl.java
index c6a5a2e..4e4ef55 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBValueImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/db/impl/DHTDBValueImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/impl/DHTImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/impl/DHTImpl.java
index 7554069..4743f0e 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/impl/DHTImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/impl/DHTImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -92,6 +89,8 @@ DHTImpl
 		int		o_rep 	= getProp( PR_ORIGINAL_REPUBLISH_INTERVAL, 	DHTControl.ORIGINAL_REPUBLISH_INTERVAL_DEFAULT );
 		int		c_rep 	= getProp( PR_CACHE_REPUBLISH_INTERVAL, 	DHTControl.CACHE_REPUBLISH_INTERVAL_DEFAULT );
 		int		c_n 	= getProp( PR_CACHE_AT_CLOSEST_N, 			DHTControl.CACHE_AT_CLOSEST_N_DEFAULT );
+		boolean	e_c 	= getProp( PR_ENCODE_KEYS, 					DHTControl.ENCODE_KEYS_DEFAULT ) == 1;
+		boolean	r_p 	= getProp( PR_ENABLE_RANDOM_LOOKUP, 		DHTControl.ENABLE_RANDOM_DEFAULT ) == 1;
 		
 		control = DHTControlFactory.create( 
 				new DHTControlAdapter()
@@ -169,7 +168,7 @@ DHTImpl
 				_transport, 
 				K, B, max_r,
 				s_conc, l_conc, 
-				o_rep, c_rep, c_n,
+				o_rep, c_rep, c_n, e_c, r_p,
 				logger );
 		
 		if ( nat_adapter != null ){
@@ -180,6 +179,116 @@ DHTImpl
 		AERunStateHandler.addListener( this, true );
 	}
 	
+	public 
+	DHTImpl(
+		DHTTransport			_transport,
+		DHTRouter				_router,
+		DHTDB					_database,
+		Properties				_properties,
+		DHTStorageAdapter		_storage_adapter,
+		DHTLogger				_logger )
+	{		
+		properties		= _properties;
+		storage_adapter	= _storage_adapter;
+		logger			= _logger;
+		
+		DHTNetworkPositionManager.initialise( storage_adapter );
+		
+		DHTLog.setLogger( logger );
+		
+		int		K 		= getProp( PR_CONTACTS_PER_NODE, 			DHTControl.K_DEFAULT );
+		int		B 		= getProp( PR_NODE_SPLIT_FACTOR, 			DHTControl.B_DEFAULT );
+		int		max_r	= getProp( PR_MAX_REPLACEMENTS_PER_NODE, 	DHTControl.MAX_REP_PER_NODE_DEFAULT );
+		int		s_conc 	= getProp( PR_SEARCH_CONCURRENCY, 			DHTControl.SEARCH_CONCURRENCY_DEFAULT );
+		int		l_conc 	= getProp( PR_LOOKUP_CONCURRENCY, 			DHTControl.LOOKUP_CONCURRENCY_DEFAULT );
+		int		o_rep 	= getProp( PR_ORIGINAL_REPUBLISH_INTERVAL, 	DHTControl.ORIGINAL_REPUBLISH_INTERVAL_DEFAULT );
+		int		c_rep 	= getProp( PR_CACHE_REPUBLISH_INTERVAL, 	DHTControl.CACHE_REPUBLISH_INTERVAL_DEFAULT );
+		int		c_n 	= getProp( PR_CACHE_AT_CLOSEST_N, 			DHTControl.CACHE_AT_CLOSEST_N_DEFAULT );
+		boolean	e_c 	= getProp( PR_ENCODE_KEYS, 					DHTControl.ENCODE_KEYS_DEFAULT ) == 1;
+		boolean	r_p 	= getProp( PR_ENABLE_RANDOM_LOOKUP, 		DHTControl.ENABLE_RANDOM_DEFAULT ) == 1;
+		
+		control = DHTControlFactory.create( 
+				new DHTControlAdapter()
+				{
+					public DHTStorageAdapter
+					getStorageAdapter()
+					{
+						return( storage_adapter );
+					}
+					
+					public boolean
+					isDiversified(
+						byte[]		key )
+					{
+						if ( storage_adapter == null ){
+							
+							return( false );
+						}
+						
+						return( storage_adapter.isDiversified( key ));
+					}
+					
+					public byte[][]
+					diversify(
+						String				description,
+						DHTTransportContact	cause,
+						boolean				put_operation,
+						boolean				existing,
+						byte[]				key,
+						byte				type,
+						boolean				exhaustive,
+						int					max_depth )
+					{
+						boolean	valid;
+						
+						if ( existing ){
+							
+							valid =	 	type == DHT.DT_FREQUENCY ||
+										type == DHT.DT_SIZE ||
+										type == DHT.DT_NONE;
+						}else{
+							
+							valid = 	type == DHT.DT_FREQUENCY ||
+										type == DHT.DT_SIZE;
+						}
+						
+						if ( storage_adapter != null && valid ){
+							
+							if ( existing ){
+								
+								return( storage_adapter.getExistingDiversification( key, put_operation, exhaustive, max_depth ));
+								
+							}else{
+								
+								return( storage_adapter.createNewDiversification( description, cause, key, put_operation, type, exhaustive, max_depth ));
+							}
+						}else{
+							
+							if ( !valid ){
+								
+								Debug.out( "Invalid diversification received: type = " + type );
+							}
+							
+							if ( existing ){
+								
+								return( new byte[][]{ key });
+								
+							}else{
+								
+								return( new byte[0][] );
+							}
+						}
+					}
+				},
+				_transport, 
+				_router,
+				_database,
+				K, B, max_r,
+				s_conc, l_conc, 
+				o_rep, c_rep, c_n, e_c, r_p,
+				logger );
+	}
+	
 	public void 
 	runStateChanged(
 		long run_state ) 
@@ -318,7 +427,7 @@ DHTImpl
 		byte[]					key,
 		String					description,
 		byte[]					value,
-		byte					flags,
+		short					flags,
 		DHTOperationListener	listener )
 	{
 		control.put( key, description, value, flags, (byte)0, DHT.REP_FACT_DEFAULT, true, listener );
@@ -329,7 +438,7 @@ DHTImpl
 		byte[]					key,
 		String					description,
 		byte[]					value,
-		byte					flags,
+		short					flags,
 		boolean					high_priority,
 		DHTOperationListener	listener )
 	{
@@ -341,7 +450,7 @@ DHTImpl
 		byte[]					key,
 		String					description,
 		byte[]					value,
-		byte					flags,
+		short					flags,
 		byte					life_hours,
 		boolean					high_priority,
 		DHTOperationListener	listener )
@@ -354,7 +463,7 @@ DHTImpl
 		byte[]					key,
 		String					description,
 		byte[]					value,
-		byte					flags,
+		short					flags,
 		byte					life_hours,
 		byte					replication_control,
 		boolean					high_priority,
@@ -374,7 +483,7 @@ DHTImpl
 	get(
 		byte[]					key,
 		String					description,
-		byte					flags,
+		short					flags,
 		int						max_values,
 		long					timeout,
 		boolean					exhaustive,
@@ -468,6 +577,16 @@ DHTImpl
 		DHTNetworkPositionManager.destroy( storage_adapter );
 		
 		AERunStateHandler.removeListener( this );
+		
+		if ( control != null ){
+			
+			control.destroy();
+		}
+		
+		if ( speed_tester != null ){
+			
+			speed_tester.destroy();
+		}
 	}
 	
 	public void
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/impl/DHTLog.java b/azureus2/src/com/aelitis/azureus/core/dht/impl/DHTLog.java
index b835336..9b61eef 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/impl/DHTLog.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/impl/DHTLog.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncher.java b/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncher.java
index 60a5e90..750a9a1 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncher.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Aug-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherAdapter.java b/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherAdapter.java
index 9016c29..91c623f 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Jun-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherFactory.java b/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherFactory.java
index 035ecab..94ae8e8 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Aug-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherListener.java b/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherListener.java
index bddb3f8..fe33b27 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/nat/DHTNATPuncherListener.java
@@ -2,20 +2,19 @@
  * Created on Nov 30, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/nat/impl/DHTNATPuncherImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/nat/impl/DHTNATPuncherImpl.java
index a8bf005..c20b04d 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/nat/impl/DHTNATPuncherImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/nat/impl/DHTNATPuncherImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Aug-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -2185,7 +2182,17 @@ DHTNATPuncherImpl
 		DHTTransportUDPContact	target = (DHTTransportUDPContact)_target;
 		
 		try{
-			DHTTransportContact rendezvous = getRendezvous( reason, target );
+			DHTTransportContact rendezvous = null;
+			
+			if ( rendezvous_used != null && rendezvous_used.length > 0 ){
+				
+				rendezvous = rendezvous_used[0];
+			}
+			
+			if ( rendezvous == null ){
+				
+				rendezvous = getRendezvous( reason, target );
+			}
 			
 			if ( rendezvous_used != null && rendezvous_used.length > 0 ){
 				
@@ -2258,6 +2265,9 @@ DHTNATPuncherImpl
 		}
 	}
 	
+	private Map<String,Object[]>	rendezvous_lookup_cache				= new HashMap<String, Object[]>();
+	private long					rendezvous_lookup_cache_tidy_time	= -1;
+	
 	protected DHTTransportContact
 	getRendezvous(
 		String				reason,
@@ -2270,37 +2280,116 @@ DHTNATPuncherImpl
 			return( explicit );
 		}
 		
-		byte[]	key = getPublishKey( target );
+		String target_key = target.getAddress().toString();
 		
-		final DHTTransportValue[]	result_value = {null};
-		
-		final Semaphore sem = plugin_interface.getUtilities().getSemaphore();
+		DHTTransportValue[]	result_value	= null;
+		AESemaphore 		sem				= null;
+
+		long	now = SystemTime.getMonotonousTime();
 		
-		dht.get( 	key, 
-					reason + ": lookup for '" + target.getString() + "'",
-					(byte)0,
-					1,
-					RENDEZVOUS_LOOKUP_TIMEOUT,
-					false, true,
-					new DHTOperationAdapter()
-					{
-						public void
-						read(
-							DHTTransportContact	contact,
-							DHTTransportValue	value )
-						{
-							result_value[0] = value;
-							
-							sem.release();
-						}
+		synchronized( rendezvous_lookup_cache ){
+			
+			if ( rendezvous_lookup_cache_tidy_time == -1 ){
+				
+				rendezvous_lookup_cache_tidy_time = now;
+				
+			}else if ( now - rendezvous_lookup_cache_tidy_time >= 2*60*1000 ){
+			
+				rendezvous_lookup_cache_tidy_time = now;
+				
+				Iterator<Object[]> it = rendezvous_lookup_cache.values().iterator();
+				
+				while ( it.hasNext()){
+					
+					Object[] entry = it.next();
+					
+					long time = (Long)entry[0];
+					
+					if ( time != -1 && now - time > 2*60*1000 ){
 						
-						public void
-						complete(
-							boolean				timeout )
-						{
-							sem.release();
-						}
-					});
+						it.remove();
+					}
+				}
+			}
+			
+			Object[]	existing = rendezvous_lookup_cache.get( target_key );
+			
+			boolean	do_lookup;
+			
+			if ( existing != null ){
+				
+				long time = (Long)existing[0];
+				
+				if ( time == -1 || now - time  < 2*60*1000 ){
+									
+					sem 			= (AESemaphore)existing[1];
+					result_value	= (DHTTransportValue[])existing[2];
+				
+					do_lookup = false;
+					
+				}else{
+					
+					do_lookup = true;
+				}
+			}else{
+				
+				do_lookup = true;
+			}
+			
+			if ( do_lookup ){
+				
+				result_value = new DHTTransportValue[1];
+				
+				sem = new AESemaphore( "getRend" );
+				
+				final Object[] entry = new Object[]{ -1L, sem, result_value };
+												
+				byte[]	key = getPublishKey( target );
+								
+				dht.get( 	key, 
+							reason + ": lookup for '" + target.getString() + "'",
+							(byte)0,
+							1,
+							RENDEZVOUS_LOOKUP_TIMEOUT,
+							false, true,
+							new DHTOperationAdapter()
+							{
+								public void
+								read(
+									DHTTransportContact	contact,
+									DHTTransportValue	value )
+								{
+									synchronized( rendezvous_lookup_cache ){
+									
+										entry[0] = SystemTime.getMonotonousTime();
+										
+										((DHTTransportValue[])entry[2])[0] = value;
+									
+										((AESemaphore)entry[1]).releaseForever();
+									}
+								}
+								
+								public void
+								complete(
+									boolean				timeout )
+								{
+									synchronized( rendezvous_lookup_cache ){
+											
+										AESemaphore	sem = (AESemaphore)entry[1];
+										
+										if ( !sem.isReleasedForever()){
+											
+											entry[0] = SystemTime.getMonotonousTime();
+											
+											sem.releaseForever();
+										}
+									}
+								}
+							});
+				
+				rendezvous_lookup_cache.put( target_key, entry );
+			}
+		}
 		
 		sem.reserve();
 		
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPosition.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPosition.java
index 6e503ba..ff4893a 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPosition.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPosition.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Apr-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionListener.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionListener.java
index 62ede03..2757e13 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionListener.java
@@ -2,20 +2,19 @@
  * Created on Jul 2, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionManager.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionManager.java
index e8946cb..59489aa 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Apr-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -42,6 +39,7 @@ public class
 DHTNetworkPositionManager 
 {
 	private static DHTNetworkPositionProvider[]	providers = new DHTNetworkPositionProvider[0];
+	private static Object providers_lock = new Object();
 	
 	private static DHTStorageAdapter	storage_adapter = null;
 	
@@ -54,7 +52,7 @@ DHTNetworkPositionManager
 	initialise(
 		DHTStorageAdapter		adapter )
 	{
-		synchronized( providers ){
+		synchronized( providers_lock ){
 			
 			if ( storage_adapter == null ){
 				
@@ -128,7 +126,7 @@ DHTNetworkPositionManager
 	destroy(
 		DHTStorageAdapter		adapter )
 	{
-		synchronized( providers ){
+		synchronized( providers_lock ){
 			
 			if ( storage_adapter == adapter ){
 
@@ -148,7 +146,7 @@ DHTNetworkPositionManager
 	{
 		boolean	fire_added = false;
 		
-		synchronized( providers ){
+		synchronized( providers_lock ){
 	
 			boolean						found 		= false;
 			DHTNetworkPositionProvider	type_found	= null;
@@ -245,7 +243,7 @@ DHTNetworkPositionManager
 	{
 		boolean	removed = false;
 		
-		synchronized( providers ){
+		synchronized( providers_lock ){
 	
 			if ( providers.length == 0 ){
 				
@@ -284,7 +282,7 @@ DHTNetworkPositionManager
 	getProvider(
 		byte		type )
 	{
-		synchronized( providers ){
+		synchronized( providers_lock ){
 
 			for (int i=0;i<providers.length;i++){
 				
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProvider.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProvider.java
index 4c9cdfa..ca7670b 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProvider.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProvider.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Apr-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProviderInstance.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProviderInstance.java
index a6c17ea..3d335ad 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProviderInstance.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProviderInstance.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Apr-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProviderListener.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProviderListener.java
index 5faee68..f6c8944 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProviderListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/DHTNetworkPositionProviderListener.java
@@ -2,20 +2,19 @@
  * Created on Jul 26, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/Coordinates.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/Coordinates.java
index 6237fa9..a7c758f 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/Coordinates.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/Coordinates.java
@@ -2,11 +2,12 @@
  * Created on 22 juin 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.netcoords.vivaldi.ver1;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPosition.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPosition.java
index ba349b4..2331475 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPosition.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPosition.java
@@ -2,11 +2,12 @@
  * Created on 22 juin 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.netcoords.vivaldi.ver1;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPositionFactory.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPositionFactory.java
index c372661..2f389d3 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPositionFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPositionFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPositionProvider.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPositionProvider.java
index a5e2de5..eeeb6d5 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPositionProvider.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/VivaldiPositionProvider.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Apr-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/HeightCoordinatesImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/HeightCoordinatesImpl.java
index fdbf9f6..98586c6 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/HeightCoordinatesImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/HeightCoordinatesImpl.java
@@ -2,11 +2,12 @@
  * Created on 22 juin 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.netcoords.vivaldi.ver1.impl;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/VivaldiPositionImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/VivaldiPositionImpl.java
index aaa3f03..b8f6103 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/VivaldiPositionImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/VivaldiPositionImpl.java
@@ -2,11 +2,12 @@
  * Created on 22 juin 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.netcoords.vivaldi.ver1.impl;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/tests/VivaldiTest.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/tests/VivaldiTest.java
index 04592ed..2ad0713 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/tests/VivaldiTest.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/tests/VivaldiTest.java
@@ -2,11 +2,12 @@
  * Created on 22 juin 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.netcoords.vivaldi.ver1.impl.tests;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/tests/VivaldiVisualTest.java b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/tests/VivaldiVisualTest.java
index 5949874..363818d 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/tests/VivaldiVisualTest.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/netcoords/vivaldi/ver1/impl/tests/VivaldiVisualTest.java
@@ -2,11 +2,12 @@
  * Created on 22 juin 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.netcoords.vivaldi.ver1.impl.tests;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouter.java b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouter.java
index 42a6779..f49cab0 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouter.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterAdapter.java b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterAdapter.java
index b386875..bd6677c 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContact.java b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContact.java
index a55f951..0468baa 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContact.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContact.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContactAttachment.java b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContactAttachment.java
index 1a390e5..79e8992 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContactAttachment.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContactAttachment.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContactWrapper.java b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContactWrapper.java
new file mode 100644
index 0000000..f6a340b
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterContactWrapper.java
@@ -0,0 +1,97 @@
+/*
+ * Created on Aug 27, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.core.dht.router;
+
+public class 
+DHTRouterContactWrapper 
+	implements DHTRouterContact
+{
+	private DHTRouterContact		delegate;
+	
+	public
+	DHTRouterContactWrapper(
+		DHTRouterContact		_contact )
+	{
+		delegate	= _contact;
+	}
+	
+	protected DHTRouterContact
+	getDelegate()
+	{
+		return( delegate );
+	}
+	
+	public byte[]
+	getID()
+	{
+		return( delegate.getID());
+	}
+	
+	public DHTRouterContactAttachment
+	getAttachment()
+	{
+		return( delegate.getAttachment());
+	}
+	
+	public boolean
+	hasBeenAlive()
+	{
+		return( delegate.hasBeenAlive());
+	}
+	
+	public boolean
+	isFailing()
+	{
+		return( delegate.isFailing());
+	}
+	
+	public boolean
+	isAlive()
+	{
+		return( delegate.isAlive());
+	}	
+	
+	public long
+	getTimeAlive()
+	{
+		return( delegate.getTimeAlive());
+	}
+	
+	public String
+	getString()
+	{
+		return( delegate.getString());
+	}
+	
+	public boolean 
+	isBucketEntry()
+	{
+		return( delegate.isBucketEntry());
+	}
+
+	public boolean 
+	isReplacement()
+	{
+		return( delegate.isReplacement());
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterFactory.java b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterFactory.java
index 8a1e65a..fbbc09e 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterFactoryObserver.java b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterFactoryObserver.java
index 18e4b90..e1f2b64 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterFactoryObserver.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterFactoryObserver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Apr-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterStats.java b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterStats.java
index 68cdffa..090c669 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterWrapper.java b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterWrapper.java
new file mode 100644
index 0000000..784435a
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/DHTRouterWrapper.java
@@ -0,0 +1,211 @@
+/*
+ * Created on Aug 26, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.core.dht.router;
+
+import java.util.List;
+
+public class 
+DHTRouterWrapper
+	implements DHTRouter
+{
+	private final DHTRouter		delegate;
+	
+	public
+	DHTRouterWrapper(
+		DHTRouter		_delegate )
+	{
+		delegate	= _delegate;
+	}
+	
+	protected DHTRouter
+	getDelegate()
+	{
+		return( delegate );
+	}
+	
+	public int
+	getK()
+	{
+		return( delegate.getK());
+	}
+	
+	public byte[]
+	getID()
+	{
+		return( delegate.getID());
+	}
+	
+	public boolean
+	isID(
+		byte[]	node_id )
+	{
+		return( delegate.isID(node_id));
+	}
+	
+	public DHTRouterContact
+	getLocalContact()
+	{
+		return( delegate.getLocalContact());
+	}
+	
+	public void
+	setAdapter(
+		DHTRouterAdapter	_adapter )
+	{
+		delegate.setAdapter(_adapter);
+	}
+
+	public void
+	seed()
+	{
+		delegate.seed();
+	}
+	
+	public void
+	contactKnown(
+		byte[]						node_id,
+		DHTRouterContactAttachment	attachment,
+		boolean						force )
+	{
+		delegate.contactKnown(node_id, attachment, force);
+	}
+	
+	public void
+	contactAlive(
+		byte[]						node_id,
+		DHTRouterContactAttachment	attachment )
+	{
+		delegate.contactAlive(node_id, attachment);
+	}
+
+	public DHTRouterContact
+	contactDead(
+		byte[]						node_id,
+		boolean						force )
+	{
+		return( delegate.contactDead(node_id, force));	
+	}
+	
+	public DHTRouterContact
+	findContact(
+		byte[]	node_id )
+	{
+		return( delegate.findContact(node_id));
+	}
+
+	public List<DHTRouterContact>
+	findClosestContacts(
+		byte[]		node_id,
+		int			num_to_return,
+		boolean		live_only )
+	{
+		return( delegate.findClosestContacts(node_id, num_to_return, live_only));
+	}
+		
+	public void
+	recordLookup(
+		byte[]	node_id )
+	{
+		delegate.recordLookup(node_id);
+	}
+	
+	public boolean
+	requestPing(
+		byte[]	node_id )
+	{
+		return( delegate.requestPing(node_id));
+	}
+	
+	public void
+	refreshIdleLeaves(
+		long	idle_max )
+	{
+		delegate.refreshIdleLeaves(idle_max);
+	}
+	
+	public byte[]
+	refreshRandom()
+	{
+		return( delegate.refreshRandom());
+	}
+	
+	public List<DHTRouterContact>
+	findBestContacts(
+		int		max )
+	{
+		return( delegate.findBestContacts(max));
+	}
+	
+	public List<DHTRouterContact>
+	getAllContacts()
+	{
+		return( delegate.getAllContacts());
+	}
+	
+	public DHTRouterStats
+	getStats()
+	{
+		return( delegate.getStats());
+	}
+	
+	public void
+	setSleeping(
+		boolean	sleeping )
+	{
+		delegate.setSleeping(sleeping);
+	}
+	
+	public void
+	setSuspended(
+		boolean			susp )
+	{
+		delegate.setSuspended(susp);
+	}
+	
+	public void
+	destroy()
+	{
+		delegate.destroy();
+	}
+	
+	public void
+	print()
+	{
+		delegate.print();
+	}
+
+	public boolean addObserver(DHTRouterObserver rto)
+	{
+		return( delegate.addObserver(rto));
+	}
+	
+	public boolean containsObserver(DHTRouterObserver rto)
+	{
+		return( delegate.containsObserver(rto));
+	}
+
+	public boolean removeObserver(DHTRouterObserver rto)
+	{
+		return( delegate.removeObserver(rto));
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterContactImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterContactImpl.java
index 010d1bb..b746728 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterContactImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterContactImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterImpl.java
index 9fc43a3..33da5f0 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -1517,7 +1514,7 @@ DHTRouterImpl
 		try{
 			this_mon.enter();
 		
-			log( "DHT: " + DHTLog.getString2(router_node_id) + ", node count = " + getNodeCount()+ ", contacts =" + getContactCount());
+			log( "DHT: " + DHTLog.getString2(router_node_id) + ", node count=" + getNodeCount()+ ", contacts=" + getContactCount());
 		
 			root.print( "", "" );
 			
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterNodeImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterNodeImpl.java
index a7b0cca..1d776a6 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterNodeImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterNodeImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterStatsImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterStatsImpl.java
index 98e59a4..d4e8383 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterStatsImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/router/impl/DHTRouterStatsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTester.java b/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTester.java
index cb1b93e..642f8cf 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTester.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTester.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterContact.java b/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterContact.java
index ffdcc0d..2eda13b 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterContact.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterContact.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterContactListener.java b/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterContactListener.java
index 44df43b..769c4b0 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterContactListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterContactListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterFactory.java b/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterFactory.java
index 0b63e19..ab2a77f 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -32,6 +29,13 @@ DHTSpeedTesterFactory
 	create(
 		DHT		dht )
 	{
+			// if we're testing and there's no PI then don't create
+		
+		if ( dht.getLogger().getPluginInterface() == null ){
+			
+			return( null );
+		}
+		
 		return( new DHTSpeedTesterImpl( dht ));
 	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterListener.java b/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterListener.java
index 7e5ee6f..429c8a0 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/speed/DHTSpeedTesterListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/speed/impl/DHTSpeedTesterImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/speed/impl/DHTSpeedTesterImpl.java
index 9e79498..e0d3e41 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/speed/impl/DHTSpeedTesterImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/speed/impl/DHTSpeedTesterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -482,6 +479,11 @@ DHTSpeedTesterImpl
 						{
 							int	rtt = getElapsed();
 							
+							if ( rtt < 0 ){
+								
+								Debug.out( "Invalid RTT: " + rtt );
+							}
+							
 							try{
 								synchronized( activePing.this ){
 																
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransport.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransport.java
index 024a3fc..7e070d3 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransport.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransport.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -28,6 +25,7 @@ package com.aelitis.azureus.core.dht.transport;
  */
 
 import java.io.*;
+import java.util.Map;
 
 public interface 
 DHTTransport 
@@ -106,6 +104,17 @@ DHTTransport
 	
 	public void
 	registerTransferHandler(
+		byte[]							handler_key,
+		DHTTransportTransferHandler		handler );
+	
+	public void
+	registerTransferHandler(
+		byte[]							handler_key,
+		DHTTransportTransferHandler		handler,
+		Map<String,Object>				options );
+	
+	public void
+	unregisterTransferHandler(
 		byte[]						handler_key,
 		DHTTransportTransferHandler	handler );
 	
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportAlternativeContact.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportAlternativeContact.java
new file mode 100644
index 0000000..5338e99
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportAlternativeContact.java
@@ -0,0 +1,60 @@
+/*
+ * Created on May 29, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.core.dht.transport;
+
+import java.util.Map;
+
+public interface 
+DHTTransportAlternativeContact 
+{
+	public int
+	getNetworkType();
+	
+	public int
+	getVersion();
+	
+		/** 
+		 * A good-enough ID to spot duplicates - must be equal to Arrays.hashCode( BEncode( getProperties()));
+		 * @return
+		 */
+	
+	public int
+	getID();
+	
+		/**
+		 * @deprecated
+		 * @return
+		 */
+	
+	public int
+	getLastAlive();
+	
+		/**
+		 * Gets the contact's age since last known to be alive in seconds
+		 * @return
+		 */
+	
+	public int
+	getAge();
+	
+	public Map<String,Object>
+	getProperties();
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportAlternativeNetwork.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportAlternativeNetwork.java
new file mode 100644
index 0000000..2e93a0b
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportAlternativeNetwork.java
@@ -0,0 +1,40 @@
+/*
+ * Created on May 29, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.core.dht.transport;
+
+import java.util.List;
+
+public interface 
+DHTTransportAlternativeNetwork 
+{
+	public static final int	AT_MLDHT_IPV4		= 1;
+	public static final int	AT_MLDHT_IPV6		= 2;
+	public static final int	AT_I2P				= 3;
+	
+	public static final int[]	AT_ALL = { AT_MLDHT_IPV4, AT_MLDHT_IPV6, AT_I2P };
+	
+	public int
+	getNetworkType();
+	
+	public List<DHTTransportAlternativeContact>
+	getContacts(
+		int		max );
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportContact.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportContact.java
index d824cae..2314342 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportContact.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportContact.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -36,6 +33,9 @@ import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
 public interface 
 DHTTransportContact
 {
+	public static final int RANDOM_ID_TYPE1	= 1;
+	public static final int RANDOM_ID_TYPE2	= 2;
+	
 	public int
 	getMaxFailForLiveCount();
 	
@@ -54,6 +54,9 @@ DHTTransportContact
 	public long
 	getClockSkew();
 	
+	public int
+	getRandomIDType();
+	
 	public void
 	setRandomID(
 		int	id );
@@ -61,9 +64,19 @@ DHTTransportContact
 	public int
 	getRandomID();
 	
+	public void
+	setRandomID2(
+		byte[]		id );
+	
+	public byte[]
+	getRandomID2();
+	
 	public String
 	getName();
 	
+	public byte[]
+	getBloomKey();
+	
 	public InetSocketAddress
 	getAddress();
 	
@@ -117,14 +130,15 @@ DHTTransportContact
 	public void
 	sendFindNode(
 		DHTTransportReplyHandler	handler,
-		byte[]						id );
+		byte[]						id,
+		short						flags );
 		
 	public void
 	sendFindValue(
 		DHTTransportReplyHandler	handler,
 		byte[]						key,
 		int							max_values,
-		byte						flags );
+		short						flags );
 		
 	public void
 	sendKeyBlock(
@@ -141,6 +155,9 @@ DHTTransportContact
 	
 		throws IOException, DHTTransportException;
 	
+	public Map<String, Object> 
+	exportContactToMap();
+	
 	public void
 	remove();
 	
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportException.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportException.java
index 14a80e1..7f228f0 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportException.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFactory.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFactory.java
index d20472f..0f1f2a6 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFindValueReply.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFindValueReply.java
index 906b516..ef41a14 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFindValueReply.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFindValueReply.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFullStats.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFullStats.java
index c1b2618..b37bef6 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFullStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportFullStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportListener.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportListener.java
index 234e432..8061270 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportProgressListener.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportProgressListener.java
index 78997ce..bfe5337 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportProgressListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportProgressListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportQueryStoreReply.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportQueryStoreReply.java
index ba3d43d..10901e4 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportQueryStoreReply.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportQueryStoreReply.java
@@ -2,20 +2,19 @@
  * 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandler.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandler.java
index f067f7a..3b65534 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandlerAdapter.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandlerAdapter.java
index 7c1d8bd..7651f4b 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandlerAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportReplyHandlerAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportRequestHandler.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportRequestHandler.java
index ab76c69..94e15ee 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportRequestHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportRequestHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -68,7 +65,7 @@ DHTTransportRequestHandler
 		DHTTransportContact contact, 
 		byte[]				key,
 		int					max_values,
-		byte				flags );
+		short				flags );
 
 		/**
 		 * Mechanism for reporting that a contact has been imported
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportStats.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportStats.java
index f51cd7e..6befa6b 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportStoreReply.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportStoreReply.java
index 3b262c1..416bd82 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportStoreReply.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportStoreReply.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportTransferHandler.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportTransferHandler.java
index 125d6e6..7e5e40f 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportTransferHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportTransferHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportValue.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportValue.java
index 5ee7df7..7031a14 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportValue.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/DHTTransportValue.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackContactImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackContactImpl.java
index 712bb0f..a6acf94 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackContactImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackContactImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -78,6 +75,12 @@ DHTTransportLoopbackContactImpl
 	}
 	
 	public int
+	getRandomIDType()
+	{
+		return( RANDOM_ID_TYPE1 );
+	}
+	
+	public int
 	getRandomID()
 	{
 		return( random_id );
@@ -90,6 +93,18 @@ DHTTransportLoopbackContactImpl
 		random_id	= _random_id;
 	}
 	
+	public void
+	setRandomID2(
+		byte[]		id )
+	{	
+	}
+	
+	public byte[]
+	getRandomID2()
+	{
+		return( null );
+	}
+	
 	public boolean
 	isValid()
 	{
@@ -120,6 +135,13 @@ DHTTransportLoopbackContactImpl
 		return( "" );
 	}
 	
+	public byte[]
+	getBloomKey()
+	{
+		return( null );
+	}
+	
+	
 	public InetSocketAddress
 	getAddress()
 	{
@@ -206,7 +228,8 @@ DHTTransportLoopbackContactImpl
 	public void
 	sendFindNode(
 		DHTTransportReplyHandler	handler,
-		byte[]						nid )
+		byte[]						nid,
+		short						flags )
 	{
 		transport.sendFindNode( this, handler, nid );
 	}
@@ -216,7 +239,7 @@ DHTTransportLoopbackContactImpl
 		DHTTransportReplyHandler	handler,
 		byte[]						key,
 		int							max,
-		byte						flags )
+		short						flags )
 	{
 		transport.sendFindValue( this, handler, key, max, flags );
 	}
@@ -242,6 +265,12 @@ DHTTransportLoopbackContactImpl
 		transport.exportContact( this, os );
 	}
 	
+	public Map<String, Object> 
+	exportContactToMap()
+	{
+		return( transport.exportContactToMap( this ));
+	}
+	
 	public void
 	remove()
 	{
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackImpl.java
index 6720d2e..be7e06a 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -285,6 +282,17 @@ DHTTransportLoopbackImpl
 		return( request_handler );
 	}
 	
+	public Map<String,Object>
+	exportContactToMap(
+		DHTTransportContact	contact ) 
+	{
+		Map<String,Object>	result = new HashMap<String, Object>();
+		
+		result.put( "i", contact.getID());
+		
+		return( result );
+	}
+	
 	public void
 	exportContact(
 		DHTTransportContact	contact,
@@ -647,7 +655,7 @@ DHTTransportLoopbackImpl
 		final DHTTransportReplyHandler	handler,
 		final byte[]					key,
 		final int						max,
-		final byte						flags )
+		final short						flags )
 	{
 		AERunnable	runnable = 
 			new AERunnable()
@@ -668,7 +676,7 @@ DHTTransportLoopbackImpl
 		DHTTransportReplyHandler	handler,
 		byte[]						key,
 		int							max,
-		byte						flags )
+		short						flags )
 	{
 		DHTTransportLoopbackImpl	target = findTarget( contact.getID());
 		
@@ -729,6 +737,21 @@ DHTTransportLoopbackImpl
 	{
 	}
 	
+	public void
+	registerTransferHandler(
+		byte[]						handler_key,
+		DHTTransportTransferHandler	handler,
+		Map<String,Object>			options )
+	{
+	}
+	
+	public void
+	unregisterTransferHandler(
+		byte[]						handler_key,
+		DHTTransportTransferHandler	handler )
+	{
+	}
+	
 	public byte[]
 	readTransfer(
 		DHTTransportProgressListener	listener,
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackStatsImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackStatsImpl.java
index 4b10a32..39ba6c8 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackStatsImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/loopback/DHTTransportLoopbackStatsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 01-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDP.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDP.java
index 71ec6e0..f8025d6 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDP.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDP.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,19 +14,18 @@
  * 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;
 
 import java.net.InetSocketAddress;
+import java.util.Map;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 
 import com.aelitis.azureus.core.dht.transport.DHTTransport;
+import com.aelitis.azureus.core.dht.transport.DHTTransportAlternativeNetwork;
 import com.aelitis.azureus.core.dht.transport.DHTTransportException;
 import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketHandler;
 import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPRequestHandler;
@@ -54,6 +53,9 @@ DHTTransportUDP
 	public static final byte PROTOCOL_VERSION_4511					= 50;	// main
 	public static final byte PROTOCOL_VERSION_4600					= 50;	// min -> 50
 	public static final byte PROTOCOL_VERSION_4720					= 50;	
+	public static final byte PROTOCOL_VERSION_4800					= 51;	
+	public static final byte PROTOCOL_VERSION_5400					= 52;	
+	public static final byte PROTOCOL_VERSION_5500					= 52;	// min -> 51
 
 	public static final byte PROTOCOL_VERSION_DIV_AND_CONT			= 6;
 	public static final byte PROTOCOL_VERSION_ANTI_SPOOF			= 7;
@@ -99,6 +101,9 @@ DHTTransportUDP
 	public static final byte PROTOCOL_VERSION_VIVALDI_OPTIONAL		= 51;	// optional vivaldi
 	public static final byte PROTOCOL_VERSION_PACKET_FLAGS			= 51;	// flags field added to request and reply packets
 
+	public static final byte PROTOCOL_VERSION_ALT_CONTACTS			= 52;
+	public static final byte PROTOCOL_VERSION_PACKET_FLAGS2			= 53;	// flags2 field added to request and reply packets
+
 		// multiple networks reformats the requests and therefore needs the above fix to work
 	
 	public static final byte PROTOCOL_VERSION_NETWORKS				= PROTOCOL_VERSION_FIX_ORIGINATOR;
@@ -117,11 +122,11 @@ DHTTransportUDP
 		}
 	}
 	
-	public static final byte PROTOCOL_VERSION_MAIN					= Helper.getVersion( PROTOCOL_VERSION_VIVALDI_OPTIONAL );
-	public static final byte PROTOCOL_VERSION_CVS					= Helper.getVersion( PROTOCOL_VERSION_VIVALDI_OPTIONAL );
+	public static final byte PROTOCOL_VERSION_MAIN					= Helper.getVersion( PROTOCOL_VERSION_PACKET_FLAGS2 );
+	public static final byte PROTOCOL_VERSION_CVS					= Helper.getVersion( PROTOCOL_VERSION_PACKET_FLAGS2 );
 
-	public static final byte PROTOCOL_VERSION_MIN					= Helper.getVersion( PROTOCOL_VERSION_RESTRICT_ID3 );
-	public static final byte PROTOCOL_VERSION_MIN_CVS				= Helper.getVersion( PROTOCOL_VERSION_RESTRICT_ID3 );
+	public static final byte PROTOCOL_VERSION_MIN					= Helper.getVersion( PROTOCOL_VERSION_VIVALDI_OPTIONAL );
+	public static final byte PROTOCOL_VERSION_MIN_CVS				= Helper.getVersion( PROTOCOL_VERSION_VIVALDI_OPTIONAL );
 	
 
 	
@@ -139,9 +144,27 @@ DHTTransportUDP
 	
 		throws DHTTransportException;
 	
+	public DHTTransportUDPContact
+	importContact(
+		Map<String,Object>		map )
+	
+		throws DHTTransportException;
+	
 	public DHTUDPRequestHandler
 	getRequestHandler();
 	
 	public DHTUDPPacketHandler
 	getPacketHandler();
+	
+	public DHTTransportAlternativeNetwork
+	getAlternativeNetwork(
+		int		network_type );
+	
+	public void
+	registerAlternativeNetwork(
+		DHTTransportAlternativeNetwork		network );
+	
+	public void
+	unregisterAlternativeNetwork(
+		DHTTransportAlternativeNetwork		network );
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDPContact.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDPContact.java
index c55d58a..b121d59 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDPContact.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/DHTTransportUDPContact.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportAlternativeContactImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportAlternativeContactImpl.java
new file mode 100644
index 0000000..dd6921d
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportAlternativeContactImpl.java
@@ -0,0 +1,117 @@
+/*
+ * Created on May 29, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.core.dht.transport.udp.impl;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.gudy.azureus2.core3.util.BDecoder;
+import org.gudy.azureus2.core3.util.SystemTime;
+
+import com.aelitis.azureus.core.dht.transport.DHTTransportAlternativeContact;
+
+public class 
+DHTTransportAlternativeContactImpl
+	implements DHTTransportAlternativeContact
+{
+	private final byte		network_type;
+	private final byte		version;
+	private final short		initial_age;
+	private final byte[]	encoded;
+	
+	private final int		id;
+	
+	private final int			start_time		= (int)( SystemTime.getMonotonousTime()/1000 );
+		
+	protected
+	DHTTransportAlternativeContactImpl(
+		byte			_network_type,
+		byte			_version,
+		short			_age,
+		byte[]			_encoded )
+	{
+		network_type	= _network_type;
+		version			= _version;
+		initial_age		= _age<0?Short.MAX_VALUE:_age;
+		encoded			= _encoded;
+				
+		id = Arrays.hashCode( encoded );
+	}
+	
+	public int
+	getNetworkType()
+	{
+		return( network_type&0xff );
+	}
+	
+	public int
+	getVersion()
+	{
+		return( version&0xff );
+	}
+	
+	public int
+	getID()
+	{
+		return( id );
+	}
+	
+	public int
+	getLastAlive()
+	{		
+		return( start_time - initial_age );
+	}
+	
+	public int
+	getAge()
+	{
+		if ( initial_age < 0 ){
+			
+			return( Short.MAX_VALUE );
+		}
+		
+		int elapsed = ((int)( SystemTime.getMonotonousTime()/1000 )) - start_time;
+		
+		int rem = Short.MAX_VALUE - initial_age;
+		
+		if ( rem < elapsed ){
+			
+			return( Short.MAX_VALUE );
+			
+		}else{
+			
+			return((short)( initial_age + elapsed ));
+		}
+	}
+	
+	public Map<String,Object>
+	getProperties()
+	{
+		try{
+			return( BDecoder.decode( encoded ));
+			
+		}catch( Throwable e ){
+			
+			return( new HashMap<String,Object>());
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportAlternativeNetworkImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportAlternativeNetworkImpl.java
new file mode 100644
index 0000000..e21b89f
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportAlternativeNetworkImpl.java
@@ -0,0 +1,253 @@
+/*
+ * Created on May 29, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.core.dht.transport.udp.impl;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.aelitis.azureus.core.dht.transport.DHTTransportAlternativeContact;
+import com.aelitis.azureus.core.dht.transport.DHTTransportAlternativeNetwork;
+
+public class 
+DHTTransportAlternativeNetworkImpl 
+	implements DHTTransportAlternativeNetwork
+{
+	private static final int	LIVE_AGE_SECS 		= 20*60;
+	private static final int	LIVEISH_AGE_SECS 	= 40*60;
+	private static final int	MAX_CONTACTS_PUB	= 64;
+	private static final int	MAX_CONTACTS_I2P	= 16;
+	
+	private static final boolean	TRACE = false;
+	
+	private int	network;
+	private final int	max_contacts;
+	
+	private TreeSet<DHTTransportAlternativeContact> contacts =
+		new TreeSet<DHTTransportAlternativeContact>(
+			new Comparator<DHTTransportAlternativeContact>() 
+			{
+				public int 
+				compare(
+					DHTTransportAlternativeContact o1,
+					DHTTransportAlternativeContact o2 ) 
+				{
+					int res = o1.getAge() - o2.getAge();
+					
+					if ( res == 0 ){
+						
+						res = o1.getID() - o2.getID();
+					}
+					
+					return( res );
+				}
+			});
+	
+	
+	protected
+	DHTTransportAlternativeNetworkImpl(
+		int		_net )
+	{
+		network	= _net;
+		
+		max_contacts = network == AT_I2P?MAX_CONTACTS_I2P:MAX_CONTACTS_PUB;
+	}
+	
+	public int
+	getNetworkType()
+	{
+		return( network );
+	}
+	
+	public List<DHTTransportAlternativeContact>
+	getContacts(
+		int			max )
+	{
+		return( getContacts( max, false ));
+	}
+	
+	protected List<DHTTransportAlternativeContact>
+	getContacts(
+		int			max,
+		boolean		live_only )
+	{
+		if ( max == 0 ){
+			
+			max = max_contacts;
+		}
+		
+		List<DHTTransportAlternativeContact> result = new ArrayList<DHTTransportAlternativeContact>( max );
+	
+		Set<Integer>	used_ids = new HashSet<Integer>();
+		
+		synchronized( contacts ){
+			
+			Iterator<DHTTransportAlternativeContact> it = contacts.iterator();
+			
+			while( it.hasNext()){
+								
+				DHTTransportAlternativeContact contact = it.next();
+				
+				if ( live_only && contact.getAge() > LIVEISH_AGE_SECS ){
+					
+					break;
+				}
+				
+				Integer id = contact.getID();
+				
+				if ( used_ids.contains( id )){
+					
+					continue;
+				}
+				
+				used_ids.add( id );
+				
+				result.add( contact );
+				
+				if ( result.size() == max ){
+					
+					break;
+				}
+
+			}
+		}
+		
+		if ( TRACE ){
+			System.out.println( network + ": sending " + result.size() + " contacts" );
+		}
+		
+		return( result );
+	}
+	
+	private void
+	trim()
+	{
+		Iterator<DHTTransportAlternativeContact> it = contacts.iterator();
+		
+		int	pos = 0;
+		
+		while( it.hasNext()){
+				
+			it.next();
+			
+			pos++;
+			
+			if(  pos > max_contacts ){
+				
+				it.remove();
+			}
+		}
+	}
+	
+	protected void
+	addContactsForSend(
+		List<DHTTransportAlternativeContact>	new_contacts )
+	{
+		synchronized( contacts ){
+			
+			for ( DHTTransportAlternativeContact new_contact: new_contacts ){
+				
+				if ( TRACE ) System.out.println( network + ": send: add contact: " + getString(new_contact));
+				
+				contacts.add( new_contact );
+			}
+			
+			if ( contacts.size() > max_contacts ){
+				
+				trim();
+			}
+			
+			if ( TRACE ) System.out.println( network + ":     contacts=" + contacts.size());
+		}
+	}
+	
+	protected void
+	addContactFromReply(
+		DHTTransportAlternativeContact		new_contact )
+	{
+		synchronized( contacts ){
+				
+			if ( TRACE ) System.out.println( network + ": recv: add contact: " +  getString(new_contact));
+			
+			contacts.add( new_contact );
+				
+			if ( contacts.size() > max_contacts ){
+				
+				trim();
+			}
+			
+			if ( TRACE ) System.out.println( network + ":     contacts=" + contacts.size());
+		}		
+	}
+	
+	protected int
+	getRequiredContactCount()
+	{
+		synchronized( contacts ){
+			
+			int	num_contacts = contacts.size();
+			
+			int	result = 0;
+			
+			if ( num_contacts < max_contacts ){
+						
+				result =  max_contacts - num_contacts;
+				
+			}else{
+				
+				Iterator<DHTTransportAlternativeContact> it = contacts.iterator();
+					
+				int	pos = 0;
+				
+				while( it.hasNext()){
+					
+					DHTTransportAlternativeContact contact = it.next();
+					
+					if ( contact.getAge() > LIVE_AGE_SECS ){
+				
+						result = max_contacts - pos;
+						
+						break;
+						
+					}else{
+						
+						pos++;
+					}
+				}
+			}
+				
+			if ( TRACE ) System.out.println( network + ": required=" + result );
+			
+			return( result );
+		}
+	}
+	
+	private String
+	getString(
+		DHTTransportAlternativeContact		contact )
+	{
+		return( contact.getProperties() + ", age=" + contact.getAge());
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPContactImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPContactImpl.java
index f4ae0ae..fc634e4 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPContactImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPContactImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -31,7 +28,7 @@ import java.util.Map;
 import org.gudy.azureus2.core3.util.AERunStateHandler;
 import org.gudy.azureus2.core3.util.AESemaphore;
 
-
+import com.aelitis.azureus.core.dht.DHT;
 import com.aelitis.azureus.core.dht.impl.DHTLog;
 import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
 import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager;
@@ -164,6 +161,12 @@ DHTTransportUDPContactImpl
 		return( skew );
 	}
 	
+	public int
+	getRandomIDType()
+	{
+		return( RANDOM_ID_TYPE1 );
+	}
+	
 	public void
 	setRandomID(
 		int		_random_id )
@@ -177,6 +180,18 @@ DHTTransportUDPContactImpl
 		return( random_id );
 	}
 	
+	public void
+	setRandomID2(
+		byte[]		id )
+	{	
+	}
+	
+	public byte[]
+	getRandomID2()
+	{
+		return( null );
+	}
+	
 	protected int
 	getNodeStatus()
 	{
@@ -241,6 +256,12 @@ DHTTransportUDPContactImpl
 		return( DHTLog.getString2( id  ));
 	}
 	
+	public byte[]
+	getBloomKey()
+	{
+		return( getAddress().getAddress().getAddress());
+	}
+	
 	public InetSocketAddress
 	getAddress()
 	{
@@ -374,7 +395,8 @@ DHTTransportUDPContactImpl
 	public void
 	sendFindNode(
 		DHTTransportReplyHandler	handler,
-		byte[]						nid )
+		byte[]						nid,
+		short						flags )
 	{
 		transport.sendFindNode( this, handler, nid );
 	}
@@ -384,7 +406,7 @@ DHTTransportUDPContactImpl
 		DHTTransportReplyHandler	handler,
 		byte[]						key,
 		int							max_values,
-		byte						flags )
+		short						flags )
 	{
 		transport.sendFindValue( this, handler, key, max_values, flags );
 	}
@@ -415,7 +437,8 @@ DHTTransportUDPContactImpl
 					handler.failed( _contact, _error );
 				}
 			},
-			new byte[0] );
+			new byte[0],
+			DHT.FLAG_NONE );
 		
 	}
 	
@@ -445,6 +468,12 @@ DHTTransportUDPContactImpl
 		transport.exportContact( this, os );
 	}
 	
+	public Map<String, Object> 
+	exportContactToMap()
+	{
+		return( transport.exportContactToMap( this ));
+	}
+	
 	public void
 	remove()
 	{
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPImpl.java
index e5ba4ba..9dfd50d 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -30,7 +27,6 @@ import java.net.InetSocketAddress;
 import java.util.*;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.ipfilter.IpFilter;
 import org.gudy.azureus2.core3.ipfilter.IpFilterManagerFactory;
 import org.gudy.azureus2.core3.util.AEMonitor;
@@ -38,11 +34,9 @@ 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.Average;
-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.DelayedEvent;
-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;
@@ -51,7 +45,6 @@ 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.impl.DHTLog;
 import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
 import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager;
 import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionProvider;
@@ -64,11 +57,14 @@ import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacke
 import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketHandlerStub;
 import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketReceiver;
 import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPRequestHandler;
+import com.aelitis.azureus.core.dht.transport.util.DHTTransferHandler;
 import com.aelitis.azureus.core.dht.transport.util.DHTTransportRequestCounter;
+import com.aelitis.azureus.core.dht.transport.util.DHTTransferHandler.Packet;
 import com.aelitis.azureus.core.util.average.AverageFactory;
 import com.aelitis.azureus.core.util.average.MovingImmediateAverage;
 import com.aelitis.azureus.core.util.bloom.BloomFilter;
 import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
+import com.aelitis.azureus.core.versioncheck.VersionCheckClient;
 import com.aelitis.net.udp.uc.PRUDPPacketHandler;
 
 /**
@@ -81,27 +77,12 @@ DHTTransportUDPImpl
 	implements DHTTransportUDP, DHTUDPRequestHandler
 {
 	public static boolean TEST_EXTERNAL_IP	= false;
-	
-	public static final int	TRANSFER_QUEUE_MAX			= 64;
-	public static final long MAX_TRANSFER_QUEUE_BYTES	= 8*1024*1024;	 
 		
-	public static final long	WRITE_XFER_RESEND_DELAY		= 12500;
-	public static final long	READ_XFER_REREQUEST_DELAY	= 5000;
-	public static final long	WRITE_REPLY_TIMEOUT			= 60000;		
-	
 	public static final int		MIN_ADDRESS_CHANGE_PERIOD_INIT_DEFAULT	= 5*60*1000;
 	public static final int		MIN_ADDRESS_CHANGE_PERIOD_NEXT_DEFAULT	= 10*60*1000;
 	
 	public static final int		STORE_TIMEOUT_MULTIPLIER = 2;
-	
-	private static boolean	XFER_TRACE	= false;
-	
-	static{
-		if ( XFER_TRACE ){
-			System.out.println( "**** DHTTransportUDPImpl xfer trace on ****" );
-		}
-	}	
-	
+		
 	
 	private String				external_address;
 	private int					min_address_change_period = MIN_ADDRESS_CHANGE_PERIOD_INIT_DEFAULT;
@@ -127,18 +108,7 @@ DHTTransportUDPImpl
 	private DHTTransportRequestHandler	request_handler;
 	
 	private DHTTransportUDPContactImpl		local_contact;
-	
-	private Map transfer_handlers 	= new HashMap();
-	private Map	read_transfers		= new HashMap();
-	private Map write_transfers		= new HashMap();
-	
-	private long	last_xferq_log;
-	
-	private int 	active_write_queue_processor_count;
-	private long	total_bytes_on_transfer_queues;
-	
-	private Map	call_transfers		= new HashMap();
-	
+		
 	private long last_address_change;
 	
 	private List listeners	= new ArrayList();
@@ -151,6 +121,7 @@ DHTTransportUDPImpl
 	private boolean		bootstrap_node	= false;
 	
 	private byte		generic_flags	= DHTTransportUDP.GF_NONE;
+	private byte		generic_flags2	= VersionCheckClient.getSingleton().getDHTFlags();
 	
 	private static final int CONTACT_HISTORY_MAX 		= 32;
 	private static final int CONTACT_HISTORY_PING_SIZE	= 24;
@@ -221,6 +192,8 @@ DHTTransportUDPImpl
 	private boolean		initial_address_change_deferred;
 	private boolean		address_changing;
 	
+	private DHTTransferHandler xfer_handler;
+	
 	public
 	DHTTransportUDPImpl(
 		byte			_protocol_version,
@@ -266,6 +239,57 @@ DHTTransportUDPImpl
 			logger.log( e );
 		}
 		
+		xfer_handler = 
+			new DHTTransferHandler(
+				new DHTTransferHandler.Adapter() {
+					
+					public void 
+					sendRequest(
+						DHTTransportContact 	_contact, 
+						Packet 					packet	) 
+					{
+						DHTTransportUDPContactImpl	contact = (DHTTransportUDPContactImpl)_contact;
+						
+						DHTUDPPacketData	request = 
+								new DHTUDPPacketData(
+									DHTTransportUDPImpl.this, 
+									packet.getConnectionId(), 
+									local_contact, 
+									contact );
+						
+						request.setDetails( 
+							packet.getPacketType(), 
+							packet.getTransferKey(), 
+							packet.getRequestKey(), 
+							packet.getData(), 
+							packet.getStartPosition(),
+							packet.getLength(),
+							packet.getTotalLength());
+								
+						try{
+							checkAddress( contact );
+										
+							stats.dataSent( request );
+							
+							packet_handler.send(
+								request,
+								contact.getTransportAddress());
+							
+						}catch( Throwable e ){
+							
+						}
+					}
+					
+					public long 
+					getConnectionID() 
+					{
+						return( DHTTransportUDPImpl.this.getConnectionID());
+					}
+				}, 
+				DHTUDPPacketData.MAX_DATA_SIZE, 
+				1,
+				logger);
+			
 		int last_pct = COConfigurationManager.getIntParameter( "dht.udp.net" + network + ".routeable_pct", -1 );
 		
 		if ( last_pct > 0 ){
@@ -273,6 +297,8 @@ DHTTransportUDPImpl
 			routeable_percentage_average.update( last_pct );
 		}
 		
+		DHTUDPUtils.registerTransport( this );
+		
 		createPacketHandler();
 		
 		SimpleTimer.addPeriodicEvent(
@@ -287,6 +313,8 @@ DHTTransportUDPImpl
 					TimerEvent	event )
 				{
 					updateStats( tick_count++);
+					
+					checkAltContacts();
 				}
 			});
 		
@@ -431,6 +459,10 @@ DHTTransportUDPImpl
 	updateStats(
 		int	tick_count )
 	{
+			// pick up latest value
+		
+		generic_flags2	= VersionCheckClient.getSingleton().getDHTFlags();
+		
 		long	alien_count	= 0;
 		
 		long[]	aliens = stats.getAliens();
@@ -622,6 +654,12 @@ DHTTransportUDPImpl
 		return( generic_flags );
 	}
 	
+	public byte
+	getGenericFlags2()
+	{
+		return( generic_flags2 );
+	}
+	
 	public void
 	setGenericFlag(
 		byte		flag,
@@ -1344,6 +1382,68 @@ DHTTransportUDPImpl
 		DHTUDPUtils.serialiseContact( os, contact );
 	}
 	
+	public Map<String,Object>
+	exportContactToMap(
+		DHTTransportContact	contact )
+	{
+		Map<String,Object>		result = new HashMap<String, Object>();
+		
+		result.put( "v",contact.getProtocolVersion());
+		
+		InetSocketAddress address = contact.getExternalAddress();
+		
+		result.put( "p", address.getPort());
+		
+		InetAddress	ia = address.getAddress();
+		
+		if ( ia == null ){
+			
+	
+			result.put( "h", address.getHostName());
+			
+		}else{
+		
+			result.put( "a", ia.getAddress());
+		}
+		
+		return( result );
+	}
+	
+	public DHTTransportUDPContact
+	importContact(
+		Map<String,Object>		map )
+	{
+		int version = ((Number)map.get( "v" )).intValue();
+		
+		int port = ((Number)map.get( "p" )).intValue();
+		
+		byte[]	a = (byte[])map.get( "a" );
+				
+		InetSocketAddress address;
+		
+		try{
+			if ( a == null ){
+				
+				address = InetSocketAddress.createUnresolved( new String((byte[])map.get("h"), "UTF-8" ), port );
+			}else{
+			
+				address = new InetSocketAddress( InetAddress.getByAddress( a ), port );
+			}
+			
+			DHTTransportUDPContactImpl contact = new DHTTransportUDPContactImpl( false, this, address, address, (byte)version, 0, 0, (byte)0 );
+			
+			importContact( contact, false );
+				
+			return( contact );
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( null );
+		}
+	}
+	
 	public void
 	removeContact(
 		DHTTransportContact	contact )
@@ -1491,6 +1591,8 @@ DHTTransportUDPImpl
 			final DHTUDPPacketRequestPing	request = 
 				new DHTUDPPacketRequestPing( this, connection_id, local_contact, contact );
 				
+			requestAltContacts( request );
+			
 			stats.pingSent( request );
 
 			requestSendRequestProcessor( contact, request );
@@ -1513,9 +1615,11 @@ DHTTransportUDPImpl
 							}
 							
 							contact.setInstanceIDAndVersion( packet.getTargetInstanceID(), packet.getProtocolVersion());
-							
+							   
 							requestSendReplyProcessor( contact, handler, packet, elapsed_time );							
 								
+							receiveAltContacts((DHTUDPPacketReplyPing)packet );
+							
 							stats.pingOK();
 							
 							handler.pingReply( contact, (int)elapsed_time );
@@ -2374,7 +2478,7 @@ outer:
 		final DHTTransportReplyHandler		handler,
 		byte[]								key,
 		int									max_values,
-		byte								flags )
+		short								flags )
 	{
 		try{
 			checkAddress( contact );
@@ -2390,7 +2494,7 @@ outer:
 			
 			request.setMaximumValues( max_values );
 			
-			request.setFlags( flags );
+			request.setFlags((byte)flags );
 			
 			requestSendRequestProcessor( contact, request );
 
@@ -2506,1055 +2610,152 @@ outer:
 		return( res[0] );
 	}
 	
-		// read request
+	public void
+	registerTransferHandler(
+		byte[]						handler_key,
+		DHTTransportTransferHandler	handler )
+	{
+		xfer_handler.registerTransferHandler(handler_key, handler);
+	}
 	
-	protected void
-	sendReadRequest(
-		long						connection_id,	
-		DHTTransportUDPContactImpl	contact,
-		byte[]						transfer_key,
-		byte[]						key )
+	public void
+	registerTransferHandler(
+		byte[]						handler_key,
+		DHTTransportTransferHandler	handler,
+		Map<String,Object>			options )
 	{
-		sendReadRequest( connection_id, contact, transfer_key, key, 0, 0 );
+		xfer_handler.registerTransferHandler( handler_key, handler, options );
 	}
 	
-	protected void
-	sendReadRequest(
-		long						connection_id,	
-		DHTTransportUDPContactImpl	contact,
-		byte[]						transfer_key,
-		byte[]						key,
-		int							start_pos,
-		int							len )
+	public void
+	unregisterTransferHandler(
+		byte[]						handler_key,
+		DHTTransportTransferHandler	handler )
 	{
-		final DHTUDPPacketData	request = 
-			new DHTUDPPacketData( this, connection_id, local_contact, contact );
-			
-		request.setDetails( DHTUDPPacketData.PT_READ_REQUEST, transfer_key, key, new byte[0], start_pos, len, 0 );
-				
-		try{
-			checkAddress( contact );
-			
-			if ( XFER_TRACE ){
-				logger.log( "Transfer read request: key = " + DHTLog.getFullString( key ) + ", contact = " + contact.getString());
-			}
-			
-			stats.dataSent( request );
-			
-			packet_handler.send(
-				request,
-				contact.getTransportAddress());
-			
-		}catch( Throwable e ){
-			
-		}
+		xfer_handler.unregisterTransferHandler(handler_key, handler);
 	}
 	
-	protected void
-	sendReadReply(
-		long						connection_id,	
-		DHTTransportUDPContactImpl	contact,
-		byte[]						transfer_key,
-		byte[]						key,
-		byte[]						data,
-		int							start_position,
-		int							length,
-		int							total_length )
+	public byte[]
+	readTransfer(
+		DHTTransportProgressListener	listener,
+		DHTTransportContact				target,
+		byte[]							handler_key,
+		byte[]							key,
+		long							timeout )
+	
+		throws DHTTransportException
 	{
-		final DHTUDPPacketData	request = 
-			new DHTUDPPacketData( this, connection_id, local_contact, contact );
-			
-		request.setDetails( DHTUDPPacketData.PT_READ_REPLY, transfer_key, key, data, start_position, length, total_length );
-		
-		try{
-			checkAddress( contact );
-			
-			if ( XFER_TRACE ){
-				logger.log( "Transfer read reply: key = " + DHTLog.getFullString( key ) + ", contact = " + contact.getString());
-			}
-			
-			stats.dataSent( request );
-			
-			packet_handler.send(
-				request,
-				contact.getTransportAddress());
-			
-		}catch( Throwable e ){
-			
-		}
+		return( xfer_handler.readTransfer( listener, target, handler_key, key, timeout ));
 	}
 	
-	protected void
-	sendWriteRequest(
-		long						connection_id,	
-		DHTTransportUDPContactImpl	contact,
-		byte[]						transfer_key,
-		byte[]						key,
-		byte[]						data,
-		int							start_position,
-		int							length,
-		int							total_length )
+	public void
+	writeTransfer(
+		DHTTransportProgressListener	listener,
+		DHTTransportContact				target,
+		byte[]							handler_key,
+		byte[]							key,
+		byte[]							data,
+		long							timeout )
+	
+		throws DHTTransportException
 	{
-		final DHTUDPPacketData	request = 
-			new DHTUDPPacketData( this, connection_id, local_contact, contact );
-			
-		request.setDetails( DHTUDPPacketData.PT_WRITE_REQUEST, transfer_key, key, data, start_position, length, total_length );
-		
-		try{
-			checkAddress( contact );
-			
-			if ( XFER_TRACE ){
-				logger.log( "Transfer write request: key = " + DHTLog.getFullString( key ) + ", contact = " + contact.getString());
-			}
-			
-			stats.dataSent( request );
-			
-			packet_handler.send(
-				request,
-				contact.getTransportAddress());
-			
-		}catch( Throwable e ){
-			
-		}
+		xfer_handler.writeTransfer(listener, target, handler_key, key, data, timeout);
+	}
+	
+	public byte[]
+	writeReadTransfer(
+		DHTTransportProgressListener	listener,
+		DHTTransportContact				target,
+		byte[]							handler_key,
+		byte[]							data,
+		long							timeout )	
+	
+		throws DHTTransportException
+	{
+		return( xfer_handler.writeReadTransfer( listener, target, handler_key, data, timeout ));
 	}
 	
 	protected void
-	sendWriteReply(
-		long						connection_id,	
-		DHTTransportUDPContactImpl	contact,
-		byte[]						transfer_key,
-		byte[]						key,
-		int							start_position,
-		int							length )
+	dataRequest(
+		final DHTTransportUDPContactImpl	originator,
+		final DHTUDPPacketData				req )
 	{
-		final DHTUDPPacketData	request = 
-			new DHTUDPPacketData( this, connection_id, local_contact, contact );
-			
-		request.setDetails( DHTUDPPacketData.PT_WRITE_REPLY, transfer_key, key, new byte[0], start_position, length, 0 );
+		stats.dataReceived();
 		
-		try{
-			checkAddress( contact );
-			
-			if ( XFER_TRACE ){
-				logger.log( "Transfer write reply: key = " + DHTLog.getFullString( key ) + ", contact = " + contact.getString());
-			}
-			
-			stats.dataSent( request );
-			
-			packet_handler.send(
-				request,
-				contact.getTransportAddress());
-			
-		}catch( Throwable e ){
-			
-		}
+		xfer_handler.receivePacket( 
+			originator, 
+			new DHTTransferHandler.Packet(
+				req.getConnectionId(),
+				req.getPacketType(),
+				req.getTransferKey(),
+				req.getRequestKey(),
+				req.getData(),
+				req.getStartPosition(),
+				req.getLength(),
+				req.getTotalLength()));
 	}
-	
+		
 	public void
-	registerTransferHandler(
-		byte[]						handler_key,
-		DHTTransportTransferHandler	handler )
+	process(
+		DHTUDPPacketRequest	request,
+		boolean				alien )
 	{
-		logger.log( "Transfer handler (" + handler.getName() + ") registered for key '" + ByteFormatter.encodeString( handler_key ));
-		
-		transfer_handlers.put( 
-			new HashWrapper( handler_key ), 
-			new transferHandlerInterceptor(
-					handler ));
+		process( packet_handler, request, alien  );
 	}
 	
-	protected int
-	handleTransferRequest(
-		DHTTransportUDPContactImpl	target,
-		long						connection_id,
-		byte[]						transfer_key,
-		byte[]						request_key,
-		byte[]						data,
-		int							start,
-		int							length,
-		boolean						write_request,
-		boolean						first_packet_only )
-	
-		throws DHTTransportException
+	public void
+	process(
+		DHTUDPPacketHandlerStub		packet_handler_stub,
+		DHTUDPPacketRequest			request,
+		boolean						alien )
 	{
-		DHTTransportTransferHandler	handler = (DHTTransportTransferHandler)transfer_handlers.get(new HashWrapper( transfer_key ));
-		
-		if ( handler == null ){
-			
-			// can get a lot of these on startup so we'll downgrade to just ignoring
-			//logger.log( "No transfer handler registered for key '" + ByteFormatter.encodeString(transfer_key) + "'" );
-			//throw( new DHTTransportException( "No transfer handler registered for " + ByteFormatter.encodeString(transfer_key) ));
+		if ( request_handler == null ){
 			
-			return( -1 );
-		}
-
-		if ( data == null ){
+			logger.log( "Ignoring packet as not yet ready to process" );
 			
-			data = handler.handleRead( target, request_key );
+			return;
 		}
 		
-		if ( data == null ){
+		try{			
+			stats.incomingRequestReceived( request, alien );
 			
-			return( -1 );
+			InetSocketAddress	transport_address = request.getAddress();
 			
-		}else{
+			DHTTransportUDPContactImpl	originating_contact = 
+				new DHTTransportUDPContactImpl( 
+						false,
+						this, 
+						transport_address, 
+						request.getOriginatorAddress(), 
+						request.getOriginatorVersion(),
+						request.getOriginatorInstanceID(),
+						request.getClockSkew(),
+						request.getGenericFlags());
+			
+			try{
+				checkAddress( originating_contact );
+					
+			}catch( DHTUDPPacketHandlerException e ){
 				
-				// special case 0 length data
+				return;
+			}
+
+			requestReceiveRequestProcessor( originating_contact, request );
+			
+			boolean	bad_originator = !originating_contact.addressMatchesID();
+			
+				// bootstrap node returns details regardless of whether the originator ID matches
+				// as the details will help the sender discover their correct ID (hopefully)
 			
-			if ( data.length == 0 ){
+			if ( bad_originator && !bootstrap_node ){
 				
-				if ( write_request ){
-					
-					sendWriteRequest(
-							connection_id,
-							target,
-							transfer_key,
-							request_key,
-							data,
-							0,
-							0,
-							0 );						
-				}else{
-					
-					sendReadReply( 
-							connection_id,
-							target,
-							transfer_key,
-							request_key,
-							data,
-							0,
-							0,
-							0 );
-				}
-			}else{
-								
-				if ( start < 0 ){
-					
-					start	= 0;
-					
-				}else if ( start >= data.length ){
+				String	contact_string = originating_contact.getString();
+
+				if ( recent_reports.get(contact_string) == null ){
 					
-					logger.log( "dataRequest: invalid start position" );
+					recent_reports.put( contact_string, "" );
 					
-					return( data.length );
-				}
-								
-				if ( length <= 0 ){
-					
-					length = data.length;
-					
-				}else if ( start + length > data.length ){
-					
-					logger.log( "dataRequest: invalid length" );
-					
-					return( data.length );
-				}
-				
-				int	end = start+length;
-				
-				while( start < end ){
-					
-					int	chunk = end - start;
-					
-					if ( chunk > DHTUDPPacketData.MAX_DATA_SIZE ){
-						
-						chunk = DHTUDPPacketData.MAX_DATA_SIZE;								
-					}
-					
-					if ( write_request ){
-						
-						sendWriteRequest(
-								connection_id,
-								target,
-								transfer_key,
-								request_key,
-								data,
-								start,
-								chunk,
-								data.length );
-												
-						if ( first_packet_only ){
-							
-							break;
-						}
-					}else{
-						
-						sendReadReply( 
-								connection_id,
-								target,
-								transfer_key,
-								request_key,
-								data,
-								start,
-								chunk,
-								data.length );
-					}
-					
-					start += chunk;
-				}
-			}
-			
-			return( data.length );
-		}
-	}
-	
-	protected void
-	dataRequest(
-		final DHTTransportUDPContactImpl	originator,
-		final DHTUDPPacketData				req )
-	{
-		/*
-		if ((int)(Math.random() * 4 )== 0 ){
-			
-			System.out.println("dropping request packet:" + req.getString());
-			
-			return;
-		}
-		*/
-		
-		stats.dataReceived();
-		
-			// both requests and replies come through here. Currently we only support read
-			// requests so we can safely use the data.length == 0 test to discriminate between
-			// a request and a reply to an existing transfer
-		
-		byte	packet_type = req.getPacketType();
-		
-		if ( XFER_TRACE ){
-			System.out.println( "dataRequest: originator=" + originator.getAddress() + ",packet=" + req.getString());
-		}
-		
-		if ( packet_type == DHTUDPPacketData.PT_READ_REPLY ){
-			
-			transferQueue	queue = lookupTransferQueue( read_transfers, req.getConnectionId());
-			
-				// unmatched -> drop it
-			
-			if ( queue != null ){
-			
-				queue.add( req );
-			}
-			
-		}else if ( packet_type == DHTUDPPacketData.PT_WRITE_REPLY ){
-				
-			transferQueue	queue = lookupTransferQueue( write_transfers, req.getConnectionId());
-				
-				// unmatched -> drop it
-				
-			if ( queue != null ){
-				
-				queue.add( req );
-			}
-		}else{
-			
-			byte[]	transfer_key = req.getTransferKey();
-									
-			if ( packet_type == DHTUDPPacketData.PT_READ_REQUEST ){
-
-				try{
-					handleTransferRequest( 
-							originator,
-							req.getConnectionId(),
-							transfer_key,
-							req.getRequestKey(),
-							null,
-							req.getStartPosition(),
-							req.getLength(),
-							false, false );
-					
-				}catch( DHTTransportException e ){
-					
-					logger.log(e);
-				}
-
-			}else{
-				
-					// 	write request 
-					
-				transferQueue	old_queue = lookupTransferQueue( read_transfers, req.getConnectionId());
-				
-				if ( old_queue != null ){
-					
-					old_queue.add( req );
-					
-				}else{
-				
-					final DHTTransportTransferHandler	handler = (DHTTransportTransferHandler)transfer_handlers.get(new HashWrapper( transfer_key ));
-					
-					if ( handler == null ){
-						
-						logger.log( "No transfer handler registered for key '" + ByteFormatter.encodeString(transfer_key) + "'" );
-						
-					}else{
-											
-						try{
-							final transferQueue new_queue = new transferQueue( read_transfers, req.getConnectionId());
-						
-								// add the initial data for this write request
-							
-							new_queue.add( req );
-							
-								// set up the queue processor
-								
-							try{
-								this_mon.enter();
-								
-								if ( active_write_queue_processor_count >= TRANSFER_QUEUE_MAX ){
-									
-									new_queue.destroy();
-									
-									throw( new DHTTransportException( "Active write queue process thread limit exceeded" ));
-								}
-								
-								active_write_queue_processor_count++;
-								
-								if ( XFER_TRACE ){
-									System.out.println( "active_write_queue_processor_count=" + active_write_queue_processor_count );
-								}
-							}finally{
-								
-								this_mon.exit();
-							}
-
-							new AEThread2( "DHTTransportUDP:writeQueueProcessor", true )
-								{
-									public void
-									run()
-									{
-										try{
-											byte[] write_data = 
-												runTransferQueue( 
-													new_queue, 
-													new DHTTransportProgressListener()
-													{
-														public void
-														reportSize(
-															long	size )
-														{
-															if ( XFER_TRACE ){
-																System.out.println( "writeXfer: size=" + size );
-															}
-														}
-														
-														public void
-														reportActivity(
-															String	str )
-														{
-															if ( XFER_TRACE ){
-																System.out.println( "writeXfer: act=" + str );
-															}
-														}
-														
-														public void
-														reportCompleteness(
-															int		percent )
-														{
-															if ( XFER_TRACE ){
-																System.out.println( "writeXfer: %=" + percent );
-															}
-														}
-													},
-													originator,
-													req.getTransferKey(),
-													req.getRequestKey(),
-													60000,
-													false );
-											
-											if ( write_data != null ){
-												
-													// xfer complete, send ack if multi-packet xfer
-													// (ack already sent below if single packet)
-												
-												if ( 	req.getStartPosition() != 0 ||
-														req.getLength() != req.getTotalLength() ){
-													
-													sendWriteReply(
-															req.getConnectionId(),
-															originator,
-															req.getTransferKey(),
-															req.getRequestKey(),
-															0,
-															req.getTotalLength());
-												}
-												
-												byte[]	reply_data = handler.handleWrite( originator, req.getRequestKey(), write_data );
-												
-												if ( reply_data != null ){
-													
-													writeTransfer(
-															new DHTTransportProgressListener()
-															{
-																public void
-																reportSize(
-																	long	size )
-																{
-																	if ( XFER_TRACE ){
-																		System.out.println( "writeXferReply: size=" + size );
-																	}
-																}
-																
-																public void
-																reportActivity(
-																	String	str )
-																{
-																	if ( XFER_TRACE ){
-																		System.out.println( "writeXferReply: act=" + str );
-																	}
-																}
-																
-																public void
-																reportCompleteness(
-																	int		percent )
-																{
-																	if ( XFER_TRACE ){
-																		System.out.println( "writeXferReply: %=" + percent );
-																	}
-																}
-															},
-															originator,
-															req.getTransferKey(),
-															req.getRequestKey(),
-															reply_data,
-															WRITE_REPLY_TIMEOUT );
-															
-												}
-											}
-											
-										}catch( DHTTransportException e ){
-											
-											logger.log( "Failed to process transfer queue: " + Debug.getNestedExceptionMessage(e));
-											
-										}finally{
-											
-											try{
-												this_mon.enter();
-																								
-												active_write_queue_processor_count--;
-												
-												if ( XFER_TRACE ){
-													System.out.println( "active_write_queue_processor_count=" + active_write_queue_processor_count );
-												}
-											}finally{
-												
-												this_mon.exit();
-											}
-										}
-									}
-								}.start();
-								
-									// indicate that at least one packet has been received
-								
-							sendWriteReply(
-								req.getConnectionId(),
-								originator,
-								req.getTransferKey(),
-								req.getRequestKey(),
-								req.getStartPosition(),
-								req.getLength());
-							
-						}catch( DHTTransportException e ){
-							
-							long now = SystemTime.getMonotonousTime();
-							
-							if ( last_xferq_log == 0 || now - last_xferq_log > 5*60*1000 ){
-							
-								last_xferq_log = now;
-								
-								logger.log( "Failed to create transfer queue" );
-							
-								logger.log( e );
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-		
-	public byte[]
-	readTransfer(
-		DHTTransportProgressListener	listener,
-		DHTTransportContact				target,
-		byte[]							handler_key,
-		byte[]							key,
-		long							timeout )
-	
-		throws DHTTransportException
-	{
-		long	connection_id 	= getConnectionID();
-		
-		transferQueue	transfer_queue = new transferQueue( read_transfers, connection_id );
-		
-		return( runTransferQueue( transfer_queue, listener, target, handler_key, key, timeout, true ));
-	}
-	
-	protected byte[]
-	runTransferQueue(
-		transferQueue					transfer_queue,
-		DHTTransportProgressListener	listener,
-		DHTTransportContact				target,
-		byte[]							handler_key,
-		byte[]							key,
-		long							timeout,
-		boolean							read_transfer )
-	
-		throws DHTTransportException
-	{		
-		SortedSet	packets = 
-			new TreeSet(
-				new Comparator()
-				{
-					public int
-					compare(
-						Object	o1,
-						Object	o2 )
-					{
-						DHTUDPPacketData	p1 = (DHTUDPPacketData)o1;
-						DHTUDPPacketData	p2 = (DHTUDPPacketData)o2;
-						
-						return( p1.getStartPosition() - p2.getStartPosition());
-					}
-				});
-		
-		int	entire_request_count = 0;
-		
-		int transfer_size 	= -1;
-		int	transferred		= 0;
-		
-		String	target_name = DHTLog.getString2(target.getID());
-		
-		try{
-			long	start = SystemTime.getCurrentTime();
-			
-			if ( read_transfer ){
-			
-				listener.reportActivity( getMessageText( "request_all", target_name ));
-
-				entire_request_count++;
-			
-				sendReadRequest( transfer_queue.getID(), (DHTTransportUDPContactImpl)target, handler_key, key );
-
-			}else{
-				
-					// write transfer - data already on its way, no need to request it
-				
-				entire_request_count++;
-			}
-			
-			while( SystemTime.getCurrentTime() - start <= timeout ){					
-				
-				DHTUDPPacketData	reply = transfer_queue.receive( READ_XFER_REREQUEST_DELAY );
-				
-				if ( reply != null ){
-	
-					if ( transfer_size == -1 ){
-						
-						transfer_size = reply.getTotalLength();
-						
-						listener.reportSize( transfer_size );
-					}
-					
-					Iterator	it = packets.iterator();
-					
-					boolean	duplicate = false;
-					
-					while( it.hasNext()){
-						
-						DHTUDPPacketData	p = (DHTUDPPacketData)it.next();
-						
-							// ignore overlaps
-						
-						if (	p.getStartPosition() < reply.getStartPosition() + reply.getLength() &&
-								p.getStartPosition() + p.getLength() > reply.getStartPosition()){
-							
-							duplicate	= true;
-							
-							break;
-						}
-					}
-					
-					if ( !duplicate ){
-						
-						listener.reportActivity( 
-								getMessageText( "received_bit", 
-								new String[]{ 
-										String.valueOf( reply.getStartPosition()),
-										String.valueOf(reply.getStartPosition() + reply.getLength()),
-										target_name }));
-
-						transferred += reply.getLength();
-						
-						listener.reportCompleteness( transfer_size==0?100: ( 100 * transferred / transfer_size ));
-						
-						packets.add( reply );
-						
-							// see if we're done				
-					
-						it = packets.iterator();
-						
-						int	pos			= 0;
-						int	actual_end	= -1;
-						
-						while( it.hasNext()){
-							
-							DHTUDPPacketData	p = (DHTUDPPacketData)it.next();
-						
-							if ( actual_end == -1 ){
-								
-								actual_end = p.getTotalLength();
-							}
-							
-							if ( p.getStartPosition() != pos ){
-								
-									// missing data, give up
-								
-								break;
-							}
-							
-							pos += p.getLength();
-							
-							if ( pos == actual_end ){
-							
-									// huzzah, we got the lot
-							
-								listener.reportActivity( getMessageText( "complete" ));
-								
-								byte[]	result = new byte[actual_end];
-								
-								it =  packets.iterator();
-								
-								pos	= 0;
-								
-								while( it.hasNext()){
-									
-									p = (DHTUDPPacketData)it.next();
-
-									System.arraycopy( p.getData(), 0, result, pos, p.getLength());
-									
-									pos	+= p.getLength();
-								}
-								
-								return( result );
-							}
-						}
-					}
-				}else{
-					
-						// timeout, look for missing bits
-					
-					if ( packets.size() == 0 ){
-						
-						if ( entire_request_count == 2 ){
-						
-							listener.reportActivity( getMessageText( "timeout", target_name ));
-							
-							return( null );
-						}
-						
-						entire_request_count++;
-						
-						listener.reportActivity( getMessageText( "rerequest_all", target_name ));
-						
-						sendReadRequest( transfer_queue.getID(), (DHTTransportUDPContactImpl)target, handler_key, key );
-						
-					}else{
-						
-						Iterator it = packets.iterator();
-					
-						int	pos			= 0;
-						int	actual_end	= -1;
-						
-						while( it.hasNext()){
-							
-							DHTUDPPacketData	p = (DHTUDPPacketData)it.next();
-						
-							if ( actual_end == -1 ){
-								
-								actual_end = p.getTotalLength();
-							}
-							
-							if ( p.getStartPosition() != pos ){
-								
-								listener.reportActivity( 
-										getMessageText( "rerequest_bit",
-												new String[]{
-													String.valueOf( pos ),
-													String.valueOf( p.getStartPosition()),
-													target_name }));
-								
-								sendReadRequest( 
-										transfer_queue.getID(), 
-										(DHTTransportUDPContactImpl)target, 
-										handler_key, 
-										key,
-										pos,
-										p.getStartPosition()-pos );
-							
-							}
-							
-							pos = p.getStartPosition() + p.getLength();
-						}
-						
-						if ( pos != actual_end ){
-							
-							listener.reportActivity( 
-									getMessageText( "rerequest_bit",
-											new String[]{
-												String.valueOf( pos ),
-												String.valueOf( actual_end ),
-												target_name }));
-			
-							sendReadRequest( 
-									transfer_queue.getID(), 
-									(DHTTransportUDPContactImpl)target, 
-									handler_key, 
-									key,
-									pos,
-									actual_end - pos );						
-						}
-					}
-				}
-			}
-			
-			if ( packets.size()==0 ){
-				
-				listener.reportActivity( getMessageText( "timeout", target_name ));
-				
-			}else{
-				
-				listener.reportActivity( 
-						getMessageText( 
-							"timeout_some", 
-							new String[]{ String.valueOf( packets.size()), target_name }));
-							
-			}
-			
-			return( null );
-			
-		}finally{
-			
-			transfer_queue.destroy();
-		}
-	}
-	
-	public void
-	writeTransfer(
-		DHTTransportProgressListener	listener,
-		DHTTransportContact				target,
-		byte[]							handler_key,
-		byte[]							key,
-		byte[]							data,
-		long							timeout )
-	
-		throws DHTTransportException
-	{
-		transferQueue	transfer_queue = null;
-	
-		try{
-			long	connection_id 	= getConnectionID();
-		
-			transfer_queue = new transferQueue( write_transfers, connection_id );
-		
-			boolean	ok 				= false;
-			boolean	reply_received	= false;
-			
-			int		loop			= 0;
-			int		total_length	= data.length;
-			
-			long	start = SystemTime.getCurrentTime();
-			
-			long	last_packet_time = 0;
-			
-			while( true ){
-				
-				long	now = SystemTime.getCurrentTime();
-				
-				if ( now < start ){
-					
-					start				= now;
-					
-					last_packet_time	= 0;
-					
-				}else{
-					
-					if ( now - start > timeout ){
-						
-						break;
-					}
-				}
-				
-				long	time_since_last_packet = now - last_packet_time;
-				
-				if ( time_since_last_packet >= WRITE_XFER_RESEND_DELAY ){
-					
-					listener.reportActivity( getMessageText( loop==0?"sending":"resending" ));
-				
-					loop++;
-				
-					total_length =	handleTransferRequest(
-												(DHTTransportUDPContactImpl)target,
-												connection_id,
-												handler_key,
-												key,
-												data,
-												-1, -1,
-												true,
-												reply_received );	// first packet only if we've has a reply
-				
-					last_packet_time		= now;
-					time_since_last_packet	= 0;
-				}
-				
-				DHTUDPPacketData packet = transfer_queue.receive( WRITE_XFER_RESEND_DELAY - time_since_last_packet );
-			
-				if ( packet != null ){
-					
-					last_packet_time	= now;
-					
-					reply_received = true;
-					
-					if ( packet.getStartPosition() == 0 && packet.getLength() == total_length ){
-						
-						ok	= true;
-					
-						break;
-					}
-				}
-			}
-			
-			if ( ok ){
-				
-				listener.reportCompleteness( 100 );
-				
-				listener.reportActivity( getMessageText( "send_complete" ));
-				
-			}else{
-				
-				listener.reportActivity( getMessageText( "send_timeout" ));
-				
-				throw( new DHTTransportException( "Timeout" ));
-			}
-		}finally{
-			
-			if ( transfer_queue != null ){
-				
-				transfer_queue.destroy();
-			}
-		}
-	}
-	
-	public byte[]
-	writeReadTransfer(
-		DHTTransportProgressListener	listener,
-		DHTTransportContact				target,
-		byte[]							handler_key,
-		byte[]							data,
-		long							timeout )	
-	
-		throws DHTTransportException
-	{
-		byte[]	call_key = new byte[20];
-		
-		random.nextBytes( call_key );
-		
-		AESemaphore	call_sem = new AESemaphore( "DHTTransportUDP:calSem" );
-		
-		HashWrapper	wrapped_key = new HashWrapper( call_key );
-		
-		try{
-			this_mon.enter();
-			
-			call_transfers.put( wrapped_key, call_sem );
-		
-		}finally{
-			
-			this_mon.exit();
-		}
-		
-		writeTransfer( listener, target, handler_key, call_key, data, timeout );
-		
-		if ( call_sem.reserve( timeout )){
-			
-			try{
-				this_mon.enter();
-			
-				Object	res = call_transfers.remove( wrapped_key );
-				
-				if ( res instanceof byte[] ){
-					
-					return((byte[])res);
-				}
-			}finally{
-				
-				this_mon.exit();
-			}
-		}
-		
-		throw( new DHTTransportException( "timeout" ));
-	}
-	
-	
-	public void
-	process(
-		DHTUDPPacketRequest	request,
-		boolean				alien )
-	{
-		process( packet_handler, request, alien  );
-	}
-	
-	public void
-	process(
-		DHTUDPPacketHandlerStub		packet_handler_stub,
-		DHTUDPPacketRequest			request,
-		boolean						alien )
-	{
-		if ( request_handler == null ){
-			
-			logger.log( "Ignoring packet as not yet ready to process" );
-			
-			return;
-		}
-		
-		try{			
-			stats.incomingRequestReceived( request, alien );
-			
-			InetSocketAddress	transport_address = request.getAddress();
-			
-			DHTTransportUDPContactImpl	originating_contact = 
-				new DHTTransportUDPContactImpl( 
-						false,
-						this, 
-						transport_address, 
-						request.getOriginatorAddress(), 
-						request.getOriginatorVersion(),
-						request.getOriginatorInstanceID(),
-						request.getClockSkew(),
-						request.getGenericFlags());
-			
-			try{
-				checkAddress( originating_contact );
-					
-			}catch( DHTUDPPacketHandlerException e ){
-				
-				return;
-			}
-
-			requestReceiveRequestProcessor( originating_contact, request );
-			
-			boolean	bad_originator = !originating_contact.addressMatchesID();
-			
-				// bootstrap node returns details regardless of whether the originator ID matches
-				// as the details will help the sender discover their correct ID (hopefully)
-			
-			if ( bad_originator && !bootstrap_node ){
-				
-				String	contact_string = originating_contact.getString();
-
-				if ( recent_reports.get(contact_string) == null ){
-					
-					recent_reports.put( contact_string, "" );
-					
-					logger.log( "Node " + contact_string + " has incorrect ID, reporting it to them" );
+					logger.log( "Node " + contact_string + " has incorrect ID, reporting it to them" );
 				}
 				
 				DHTUDPPacketReplyError	reply = 
@@ -3602,6 +2803,8 @@ outer:
 						
 						request_handler.pingRequest( originating_contact );
 						
+						DHTUDPPacketRequestPing ping = (DHTUDPPacketRequestPing)request;
+												
 						DHTUDPPacketReplyPing	reply = 
 							new DHTUDPPacketReplyPing(
 									this,
@@ -3609,6 +2812,8 @@ outer:
 									request.getConnectionId(),
 									local_contact,
 									originating_contact );
+													
+						sendAltContacts( ping, reply );
 						
 						requestReceiveReplyProcessor( originating_contact, reply );
 
@@ -3951,36 +3156,286 @@ outer:
 									
 								requestReceiveReplyProcessor( originating_contact, reply );
 	
-								packet_handler_stub.send( reply, request.getAddress());
+								packet_handler_stub.send( reply, request.getAddress());
+							
+							}else{
+								
+								reply.setContacts(res.getContacts());
+								
+								requestReceiveReplyProcessor( originating_contact, reply );
+	
+								packet_handler_stub.send( reply, request.getAddress());
+							}
+						}
+					}
+				}else if ( request instanceof DHTUDPPacketData ){
+					
+					if ( !bootstrap_node ){
+						
+						dataRequest(originating_contact, (DHTUDPPacketData)request );
+					}
+				}else{
+					
+					Debug.out( "Unexpected packet:" + request.toString());
+				}
+			}
+		}catch( DHTUDPPacketHandlerException e ){
+			
+			// not interesting, send packet fail or something
+			
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+		}
+	}
+	
+		// the _state networks are populated via ping requests to other peers
+	
+	private Map<Integer, DHTTransportAlternativeNetworkImpl>	alt_net_states 		= new HashMap<Integer, DHTTransportAlternativeNetworkImpl>();
+	
+		// the _providers represent a local source of contacts that are used as a primary
+		// source of contacts for replying to other peers ping requests
+		
+	private volatile Map<Integer, DHTTransportAlternativeNetwork>		alt_net_providers	= new HashMap<Integer, DHTTransportAlternativeNetwork>();
+	
+	private Object	alt_net_providers_lock = new Object();
+	
+	{
+		for ( Integer net: DHTTransportAlternativeNetwork.AT_ALL ){
+			
+			alt_net_states.put( net, new DHTTransportAlternativeNetworkImpl( net ));
+		}
+	}
+	
+	public DHTTransportAlternativeNetwork
+	getAlternativeNetwork(
+		int		network_type )
+	{
+		return( alt_net_states.get( network_type ));
+	}
+	
+	public void
+	registerAlternativeNetwork(
+		DHTTransportAlternativeNetwork		network )
+	{
+		synchronized( alt_net_providers_lock ){
+			
+			Map<Integer, DHTTransportAlternativeNetwork> new_providers = new HashMap<Integer, DHTTransportAlternativeNetwork>( alt_net_providers );
+			
+			new_providers.put( network.getNetworkType(), network );
+			
+			alt_net_providers = new_providers;
+		}
+	}
+	
+	public void
+	unregisterAlternativeNetwork(
+		DHTTransportAlternativeNetwork		network )
+	{
+		synchronized( alt_net_providers_lock ){
+			
+			Map<Integer, DHTTransportAlternativeNetwork> new_providers = new HashMap<Integer, DHTTransportAlternativeNetwork>( alt_net_providers );
+			
+			Iterator< Map.Entry<Integer, DHTTransportAlternativeNetwork>> it = new_providers.entrySet().iterator();
+			
+			while( it.hasNext()){
+				
+				if ( it.next().getValue() == network ){
+					
+					it.remove();
+				}
+			}
+			
+			alt_net_providers = new_providers;
+		}
+	}
+	
+	private void
+	checkAltContacts()
+	{
+		int	total_required = 0;
+		
+		for ( DHTTransportAlternativeNetworkImpl net: alt_net_states.values()){
+			
+			total_required += net.getRequiredContactCount();
+		}
+		
+		if ( total_required > 0 ){
+			
+			List<DHTTransportContact> targets = new ArrayList<DHTTransportContact>( ROUTABLE_CONTACT_HISTORY_MAX );
+			
+			try{
+				this_mon.enter();
+				
+				for ( DHTTransportContact contact: routable_contact_history.values()){
+				
+					if ( contact.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ALT_CONTACTS ){
+						
+						targets.add( contact );
+					}
+				}
+				
+			}finally{
+				
+				this_mon.exit();
+			}
+			
+			if ( targets.size() > 0 ){
+				
+				targets.get( RandomUtils.nextInt( targets.size())).sendPing( 
+					new DHTTransportReplyHandlerAdapter()
+					{
+						public void
+						pingReply(
+							DHTTransportContact _contact )
+						{
 							
-							}else{
-								
-								reply.setContacts(res.getContacts());
-								
-								requestReceiveReplyProcessor( originating_contact, reply );
+						}
+						
+						public void
+						failed(
+							DHTTransportContact 	_contact,
+							Throwable				_error )
+						{
+							
+						}
+					});
+			}
+		}
+	}
 	
-								packet_handler_stub.send( reply, request.getAddress());
-							}
+	private void
+	sendAltContacts(
+		DHTUDPPacketRequestPing		request,
+		DHTUDPPacketReplyPing		reply )
+	{		
+		if ( request.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ALT_CONTACTS ){
+
+			int[]	alt_nets 	= request.getAltNetworks();
+			int[] 	counts 		= request.getAltNetworkCounts();
+
+			if ( alt_nets.length > 0 ){
+				
+				List<DHTTransportAlternativeContact>	alt_contacts = new ArrayList<DHTTransportAlternativeContact>();
+								
+				Map<Integer, DHTTransportAlternativeNetwork> providers = alt_net_providers;
+				
+				for ( int i=0; i<alt_nets.length;i++){
+				
+					int	count = counts[i];
+					
+					if ( count == 0 ){
+						
+						continue;
+					}
+					
+					int	net = alt_nets[i];
+					
+					DHTTransportAlternativeNetworkImpl local = alt_net_states.get( net );
+					
+					if ( local == null ){
+						
+						continue;
+					}
+					
+					int wanted = local.getRequiredContactCount();
+					
+					if ( wanted > 0 ){
+						
+						DHTTransportAlternativeNetwork provider = providers.get( net );
+						
+						if ( provider != null ){
+							
+							local.addContactsForSend( provider.getContacts( wanted ));
 						}
 					}
-				}else if ( request instanceof DHTUDPPacketData ){
 					
-					if ( !bootstrap_node ){
+						// need to limit response for large serialisations
+					
+					if ( net == DHTTransportAlternativeNetwork.AT_I2P ){
 						
-						dataRequest(originating_contact, (DHTUDPPacketData)request );
+						count = Math.min( 2, count );
 					}
-				}else{
 					
-					Debug.out( "Unexpected packet:" + request.toString());
+					alt_contacts.addAll( local.getContacts( count, true ));
+				}
+				
+				if ( alt_contacts.size() > 0 ){
+					
+					reply.setAltContacts( alt_contacts );
 				}
 			}
-		}catch( DHTUDPPacketHandlerException e ){
+		}
+	}
+	
+	private void
+	requestAltContacts(
+		DHTUDPPacketRequestPing		request )
+	{
+		if ( request.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ALT_CONTACTS ){
 			
-			// not interesting, send packet fail or something
+				// see if we could do with any more alt contacts
 			
-		}catch( Throwable e ){
+			List<int[]> wanted = null;
 			
-			Debug.printStackTrace(e);
+			for ( DHTTransportAlternativeNetworkImpl net: alt_net_states.values()){
+				
+				int req = net.getRequiredContactCount();
+				
+				if ( req > 0 ){
+					
+					int net_type = net.getNetworkType();
+					
+					if ( net_type == DHTTransportAlternativeNetwork.AT_I2P ){
+						
+						req = Math.min( 2, req );
+					}
+
+					if ( wanted == null ){
+						
+						wanted = new ArrayList<int[]>( alt_net_states.size());
+					}
+					
+					wanted.add( new int[]{ net_type, req } );
+				}
+			}
+			
+			if ( wanted != null ){
+				
+				int[] networks 	= new int[wanted.size()];
+				int[] counts	= new int[networks.length];
+				
+				for ( int i=0;i<networks.length;i++ ){
+					
+					int[] 	entry = wanted.get( i );
+					
+					networks[i] = entry[0];
+					counts[i]	= entry[1];
+				}
+				
+					// doesn't matter how many we request in total, the reply will be
+					// limited to whatever the max is
+				
+				request.setAltContactRequest( networks, counts );
+			}
+		}
+	}
+	
+	private void
+	receiveAltContacts(
+		DHTUDPPacketReplyPing		reply )
+	{		
+		if ( reply.getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ALT_CONTACTS ){
+
+			for ( DHTTransportAlternativeContact contact: reply.getAltContacts()){
+				
+				DHTTransportAlternativeNetworkImpl net = alt_net_states.get( contact.getNetworkType());
+				
+				if ( net != null ){
+					
+					net.addContactFromReply( contact );
+				}
+			}
 		}
 	}
 	
@@ -4129,207 +3584,6 @@ outer:
 		listeners.remove(l);
 	}
 
-	protected transferQueue
-	lookupTransferQueue(
-		Map			transfers,
-		long		id )
-	{
-		try{
-			this_mon.enter();
-
-			return((transferQueue)transfers.get(new Long(id)));
-			
-		}finally{
-			
-			this_mon.exit();
-		}	
-	}
-	
-	protected String
-	getMessageText(
-		String	resource )
-	{
-		return( MessageText.getString( "DHTTransport.report." + resource ));
-	}
-	
-	protected String
-	getMessageText(
-		String	resource,
-		String	param )
-	{
-		return( MessageText.getString( "DHTTransport.report." + resource, new String[]{ param }));
-	}
-	
-	protected String
-	getMessageText(
-		String		resource,
-		String[]	params )
-	{
-		return( MessageText.getString( "DHTTransport.report." + resource, params));
-	}
-	
-	protected class
-	transferQueue
-	{
-		private Map			transfers;
-		private long		id;
-		private boolean		destroyed;
-		
-		private List		packets	= new ArrayList();
-		
-		private AESemaphore	packets_sem	= new AESemaphore("DHTUDPTransport:transferQueue");
-		
-		protected
-		transferQueue(
-			Map			_transfers,
-			long		_id )
-		
-			throws DHTTransportException
-		{
-			transfers	= _transfers;
-			id			= _id;
-			
-			try{
-				this_mon.enter();
-
-				if ( transfers.size() > TRANSFER_QUEUE_MAX ){
-					
-					Debug.out( "Transfer queue count limit exceeded" );
-					
-					throw( new DHTTransportException( "Transfer queue limit exceeded" ));
-				}
-				
-				Long l_id = new Long( id );
-				
-				transferQueue	existing = (transferQueue)transfers.get( l_id );
-				
-				if ( existing != null ){
-					
-					existing.destroy();
-				}
-				
-				transfers.put( l_id, this );
-				
-			}finally{
-				
-				this_mon.exit();
-			}			
-		}
-		
-		protected long
-		getID()
-		{
-			return( id );
-		}
-		
-		protected void
-		add(
-			DHTUDPPacketData	packet )
-		{
-			try{
-				this_mon.enter();
-	
-				if ( destroyed ){
-					
-					return;
-				}
-				
-				if ( total_bytes_on_transfer_queues > MAX_TRANSFER_QUEUE_BYTES ){
-					
-					Debug.out( "Transfer queue byte limit exceeded" );
-				
-						// just drop the packet
-					
-					return;
-				}
-				
-				int	length = packet.getLength();
-				
-				total_bytes_on_transfer_queues += length;
-				
-				if ( XFER_TRACE ){
-					System.out.println( "total_bytes_on_transfer_queues=" + total_bytes_on_transfer_queues );
-				}
-				
-				packets.add( packet );
-				
-			}finally{
-				
-				this_mon.exit();
-			}
-			
-			packets_sem.release();
-		}
-		
-		protected DHTUDPPacketData
-		receive(
-			long	timeout )
-		{
-			if ( packets_sem.reserve( timeout )){
-				
-				try{
-					this_mon.enter();
-						
-					if ( destroyed ){
-						
-						return( null );
-					}
-					
-					DHTUDPPacketData packet = (DHTUDPPacketData)packets.remove(0);
-					
-					int	length = packet.getLength();
-					
-					total_bytes_on_transfer_queues -= length;
-
-					if ( XFER_TRACE ){
-						System.out.println( "total_bytes_on_transfer_queues=" + total_bytes_on_transfer_queues );
-					}
-					
-					return( packet );
-					
-				}finally{
-					
-					this_mon.exit();
-				}				
-			}else{
-				
-				return( null );
-			}
-		}
-		
-		protected void
-		destroy()
-		{
-			try{
-				this_mon.enter();
-					
-				destroyed = true;
-				
-				transfers.remove( new Long( id ));
-				
-				for (int i=0;i<packets.size();i++){
-					
-					DHTUDPPacketData	packet = (DHTUDPPacketData)packets.get(i);
-					
-					int	length = packet.getLength();
-					
-					total_bytes_on_transfer_queues -= length;
-					
-					if ( XFER_TRACE ){
-						System.out.println( "total_bytes_on_transfer_queues=" + total_bytes_on_transfer_queues );
-					}
-				}
-				
-				packets.clear();
-				
-				packets_sem.releaseForever();
-				
-			}finally{
-				
-				this_mon.exit();
-			}
-		}
-	}
 	
 	/*
 	private PrintWriter	contact_log;
@@ -4374,65 +3628,4 @@ outer:
 		}
 	}
 	*/
-	
-	protected class
-	transferHandlerInterceptor
-		implements DHTTransportTransferHandler
-	{
-		private DHTTransportTransferHandler		handler;
-		
-		protected
-		transferHandlerInterceptor(
-			DHTTransportTransferHandler		_handler )
-		{
-			handler	= _handler;
-		}
-		
-		public String
-		getName()
-		{
-			return( handler.getName());
-		}
-		
-		public byte[]
-    	handleRead(
-    		DHTTransportContact	originator,
-    		byte[]				key )
-		{
-			return( handler.handleRead( originator, key ));
-		}
-    	
-    	public byte[]
-    	handleWrite(
-    		DHTTransportContact	originator,
-    		byte[]				key,
-    		byte[]				value )
-    	{
-    		HashWrapper	key_wrapper = new HashWrapper( key );
-    		
-    			// see if this is the response to an outstanding call
-    		
-    		try{
-    			this_mon.enter();
-    			
-    			Object	obj = call_transfers.get( key_wrapper );
-    			
-    			if ( obj instanceof AESemaphore ){
-    				
-    				AESemaphore	sem = (AESemaphore)obj;
-    				
-    				call_transfers.put( key_wrapper, value );
-    				
-    				sem.release();
-    				
-    				return( null );
-    			}
-    		}finally{
-    			
-    			this_mon.exit();
-    		}
-    		
-    		return( handler.handleWrite( originator, key, value ));
-    	}
-	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPStatsImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPStatsImpl.java
index 8ca592a..0b38a48 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPStatsImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTTransportUDPStatsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacket.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacket.java
index 31cb53f..2810a73 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacket.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacket.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -33,4 +30,7 @@ DHTUDPPacket
 	
 	public byte
 	getGenericFlags();
+	
+	public byte
+	getGenericFlags2();
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketData.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketData.java
index 4384ea7..101219b 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketData.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketData.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -40,10 +37,10 @@ public class
 DHTUDPPacketData 
 	extends DHTUDPPacketRequest
 {
-	protected static final byte		PT_READ_REQUEST		= 0x00;
-	protected static final byte		PT_READ_REPLY		= 0x01;
-	protected static final byte		PT_WRITE_REQUEST	= 0x02;
-	protected static final byte		PT_WRITE_REPLY		= 0x03;
+	public static final byte		PT_READ_REQUEST		= 0x00;
+	public static final byte		PT_READ_REPLY		= 0x01;
+	public static final byte		PT_WRITE_REQUEST	= 0x02;
+	public static final byte		PT_WRITE_REPLY		= 0x03;
 	
 	private byte	packet_type;
 	private byte[]	transfer_key;
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketHelper.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketHelper.java
index da24969..2f4a40f 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketHelper.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketHelper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReply.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReply.java
index a1cdfcf..db49cd7 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReply.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReply.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -50,7 +47,8 @@ DHTUDPPacketReply
 		1 +		// ver
 		1 +		// net 
 		4 +		// instance
-		1;		// flags
+		1 + 	// flags
+		1;		// flags2
 	
 	private DHTTransportUDPImpl 	transport;
 	
@@ -60,6 +58,9 @@ DHTUDPPacketReply
 	private int		network;
 	private int		target_instance_id;
 	private byte	flags;
+	private byte	flags2;
+
+	
 	private long	skew;
 		
 	private DHTNetworkPosition[]	network_positions;
@@ -96,6 +97,8 @@ DHTUDPPacketReply
 		skew	= _remote_contact.getClockSkew();
 		
 		flags	= transport.getGenericFlags();
+		
+		flags2	= transport.getGenericFlags2();
 	}
 	
 	protected
@@ -143,6 +146,11 @@ DHTUDPPacketReply
 			
 			flags	= is.readByte();
 		}
+		
+		if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_PACKET_FLAGS2 ){
+			
+			flags2	= is.readByte();
+		}
 	}
 	
 	public DHTTransportUDPImpl
@@ -193,6 +201,12 @@ DHTUDPPacketReply
 		return( flags );
 	}
 	
+	public byte
+	getGenericFlags2()
+	{
+		return( flags2 );
+	}
+	
 	public void
 	setNetwork(
 		int		_network )
@@ -243,11 +257,16 @@ DHTUDPPacketReply
 
 			os.writeByte( flags );
 		}
+		
+		if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_PACKET_FLAGS2 ){
+
+			os.writeByte( flags2 );
+		}
 	}
 	
 	public String
 	getString()
 	{
-		return( super.getString() + ",[con="+connection_id+",prot=" + protocol_version + ",ven=" + vendor_id + ",net="+network + ",fl=" + flags + "]");
+		return( super.getString() + ",[con="+connection_id+",prot=" + protocol_version + ",ven=" + vendor_id + ",net="+network + ",fl=" + flags + "/" + flags2 + "]");
 	}
 }
\ No newline at end of file
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyError.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyError.java
index 6c2df3c..53f1755 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyError.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyError.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyFindNode.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyFindNode.java
index bba1621..8a2b0cb 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyFindNode.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyFindNode.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyFindValue.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyFindValue.java
index ec04956..cf052de 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyFindValue.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyFindValue.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyKeyBlock.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyKeyBlock.java
index a1f89ca..2cc4726 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyKeyBlock.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyKeyBlock.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyPing.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyPing.java
index f4f679d..a413341 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyPing.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyPing.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -28,7 +29,9 @@ package com.aelitis.azureus.core.dht.transport.udp.impl;
 
 import java.io.*;
 import java.net.InetSocketAddress;
+import java.util.List;
 
+import com.aelitis.azureus.core.dht.transport.DHTTransportAlternativeContact;
 import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
 import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP;
 import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler;
@@ -37,6 +40,10 @@ public class
 DHTUDPPacketReplyPing
 	extends DHTUDPPacketReply
 {
+	private static final DHTTransportAlternativeContact[] EMPTY_CONTACTS = {};
+	
+	private DHTTransportAlternativeContact[]	alt_contacts = EMPTY_CONTACTS;
+	
 	public
 	DHTUDPPacketReplyPing(
 		DHTTransportUDPImpl		transport,
@@ -63,6 +70,11 @@ DHTUDPPacketReplyPing
 
 			DHTUDPUtils.deserialiseVivaldi( this, is );
 		}
+		
+		if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ALT_CONTACTS ){
+			
+			alt_contacts = DHTUDPUtils.deserialiseAltContacts( is );
+		}
 	}
 	
 	public void
@@ -77,5 +89,38 @@ DHTUDPPacketReplyPing
 
 			DHTUDPUtils.serialiseVivaldi( this, os );
 		}
+		
+		if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ALT_CONTACTS ){
+			
+			DHTUDPUtils.serialiseAltContacts( os, alt_contacts );
+		}
 	}
+	
+	protected void
+	setAltContacts(
+		List<DHTTransportAlternativeContact>	_contacts )
+	{
+		final int MAX_CONTACTS = 16;
+		
+		if ( _contacts.size() < MAX_CONTACTS ){
+		
+			alt_contacts = _contacts.toArray( new DHTTransportAlternativeContact[ _contacts.size()]);
+			
+		}else{
+			
+			alt_contacts = new DHTTransportAlternativeContact[MAX_CONTACTS];
+			
+			for ( int i=0;i<alt_contacts.length;i++){
+				
+				alt_contacts[i] = _contacts.get(i);
+			}
+		}
+	}
+	
+	protected DHTTransportAlternativeContact[]
+	getAltContacts()
+	{
+		return( alt_contacts );
+	}
+	
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyQueryStorage.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyQueryStorage.java
index 5212a0b..f3b9a91 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyQueryStorage.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyQueryStorage.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyStats.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyStats.java
index aa5129b..d6406da 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyStore.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyStore.java
index cfeddeb..76045b5 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyStore.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketReplyStore.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequest.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequest.java
index cf5614a..1d01a61 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequest.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -52,7 +49,9 @@ DHTUDPPacketRequest
 		4 + 		// network
 		4 +			// instance id
 		8 +			// time
-		DHTUDPUtils.INETSOCKETADDRESS_IPV4_SIZE;
+		DHTUDPUtils.INETSOCKETADDRESS_IPV4_SIZE +
+		1 +			// flags
+		1;			// flags2
 		
 	private DHTTransportUDPImpl	transport;
 	
@@ -65,6 +64,7 @@ DHTUDPPacketRequest
 	private InetSocketAddress	originator_address;
 	private int					originator_instance_id;
 	private byte				flags;
+	private byte				flags2;
 	
 	private long				skew;
 	
@@ -99,6 +99,7 @@ DHTUDPPacketRequest
 		originator_time			= SystemTime.getCurrentTime();
 		
 		flags	= transport.getGenericFlags();
+		flags2	= transport.getGenericFlags2();
 	}
 	
 	protected
@@ -177,6 +178,11 @@ DHTUDPPacketRequest
 			
 			flags	= is.readByte();
 		}
+		
+		if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_PACKET_FLAGS2 ){
+			
+			flags2	= is.readByte();
+		}
 	}
 	
 	protected void
@@ -252,6 +258,11 @@ DHTUDPPacketRequest
 
 			os.writeByte( flags );
 		}
+		
+		if ( protocol_version >= DHTTransportUDP.PROTOCOL_VERSION_PACKET_FLAGS2 ){
+
+			os.writeByte( flags2 );
+		}
 	}
 	
 	protected void
@@ -311,6 +322,12 @@ DHTUDPPacketRequest
 		return( flags );
 	}
 	
+	public byte
+	getGenericFlags2()
+	{
+		return( flags2 );
+	}
+	
 	protected byte
 	getOriginatorVersion()
 	{
@@ -339,6 +356,6 @@ DHTUDPPacketRequest
 	public String
 	getString()
 	{
-		return( super.getString() + ",[prot=" + protocol_version + ",ven=" + vendor_id + ",net="+network+",ov=" + originator_version + ",fl=" + flags + "]");
+		return( super.getString() + ",[prot=" + protocol_version + ",ven=" + vendor_id + ",net="+network+",ov=" + originator_version + ",fl=" + flags + "/" + flags2 + "]");
 	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestFindNode.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestFindNode.java
index 806f465..a627d5c 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestFindNode.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestFindNode.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestFindValue.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestFindValue.java
index b5ecd68..a647dfb 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestFindValue.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestFindValue.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestKeyBlock.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestKeyBlock.java
index 35c1ed7..98734d1 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestKeyBlock.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestKeyBlock.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestPing.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestPing.java
index 8a9b07a..c0dd332 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestPing.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestPing.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -26,6 +23,7 @@ import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 
+import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP;
 import com.aelitis.azureus.core.dht.transport.udp.impl.packethandler.DHTUDPPacketNetworkHandler;
 
 
@@ -38,6 +36,11 @@ public class
 DHTUDPPacketRequestPing 
 	extends DHTUDPPacketRequest
 {
+	private static final int[] 	EMPTY_INTS = {};
+	
+	private int[]	alt_networks			= EMPTY_INTS;
+	private int[]	alt_network_counts		= EMPTY_INTS;
+	
 	public
 	DHTUDPPacketRequestPing(
 		DHTTransportUDPImpl				_transport,
@@ -59,6 +62,11 @@ DHTUDPPacketRequestPing
 	{
 		super( network_handler, is,  DHTUDPPacketHelper.ACT_REQUEST_PING, con_id, trans_id );
 		
+		if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ALT_CONTACTS ){
+			
+			DHTUDPUtils.deserialiseAltContactRequest( this, is );
+		}
+		
 		super.postDeserialise(is);
 	}
 	
@@ -70,9 +78,35 @@ DHTUDPPacketRequestPing
 	{
 		super.serialise(os);
 		
+		if ( getProtocolVersion() >= DHTTransportUDP.PROTOCOL_VERSION_ALT_CONTACTS ){
+			
+			DHTUDPUtils.serialiseAltContactRequest( this, os );
+		}
+		
 		super.postSerialise( os );
 	}
 	
+	protected void
+	setAltContactRequest(
+		int[]	networks,
+		int[]	counts )
+	{
+		alt_networks		= networks;
+		alt_network_counts	= counts;
+	}
+	
+	protected int[]
+	getAltNetworks()
+	{
+		return( alt_networks );
+	}
+	
+	protected int[]
+	getAltNetworkCounts()
+	{
+		return( alt_network_counts );
+	}
+	
 	public String
 	getString()
 	{
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestQueryStorage.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestQueryStorage.java
index 02b52d7..be443f1 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestQueryStorage.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestQueryStorage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStats.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStats.java
index 4866239..f997526 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStore.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStore.java
index 8af918a..390cba8 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStore.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPPacketRequestStore.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPUtils.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPUtils.java
index 343533e..6084ff9 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPUtils.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/DHTUDPUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -26,11 +23,15 @@ import java.io.*;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import java.util.TreeSet;
 
+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.RandomUtils;
@@ -42,6 +43,8 @@ import com.aelitis.azureus.core.dht.impl.DHTLog;
 import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
 import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager;
 import com.aelitis.azureus.core.dht.netcoords.vivaldi.ver1.VivaldiPositionFactory;
+import com.aelitis.azureus.core.dht.transport.DHTTransportAlternativeContact;
+import com.aelitis.azureus.core.dht.transport.DHTTransportAlternativeNetwork;
 import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
 import com.aelitis.azureus.core.dht.transport.DHTTransportException;
 import com.aelitis.azureus.core.dht.transport.DHTTransportFullStats;
@@ -438,6 +441,38 @@ DHTUDPUtils
 		return( new DHTTransportUDPContactImpl( false, transport, external_address, external_address, version, 0, 0, (byte)0 ));
 	}
 	
+	protected static void
+	serialiseAltContact(
+		DataOutputStream					os,
+		DHTTransportAlternativeContact		contact )
+	
+		throws IOException, DHTTransportException
+	{
+		os.write((byte)contact.getNetworkType());
+		
+		os.write((byte)contact.getVersion());
+		
+		os.writeShort( contact.getAge());
+	
+		byte[] encoded = BEncoder.encode( contact.getProperties());
+		
+		serialiseByteArray( os, encoded, 65535 );
+	}
+	
+	protected static DHTTransportAlternativeContactImpl
+	deserialiseAltContact(
+		DataInputStream			is )
+	
+		throws IOException, DHTTransportException
+	{
+		byte	network_type 	= is.readByte();
+		byte	version		 	= is.readByte();
+		short	age				= is.readShort();
+		
+		byte[]	encoded = deserialiseByteArray( is, 65535 );
+		
+		return( new DHTTransportAlternativeContactImpl( network_type, version, age, encoded ));
+	}
 
 	protected static DHTTransportValue[]
 	deserialiseTransportValues(
@@ -725,7 +760,115 @@ DHTUDPUtils
 		
 		return( res );
 	}
+		
+	protected static void
+	serialiseAltContacts(
+		DataOutputStream					os,
+		DHTTransportAlternativeContact[]	contacts )
+	
+		throws IOException
+	{
+		if ( contacts == null ){
+			
+			contacts = new DHTTransportAlternativeContact[0];
+		}
+		
+		serialiseLength( os, contacts.length, 64 );
+		
+		for (int i=0;i<contacts.length;i++){
 			
+			try{
+				serialiseAltContact( os, contacts[i] );
+				
+			}catch( DHTTransportException e ){
+				
+				Debug.printStackTrace(e);
+				
+					// not much we can do here to recover - shouldn't fail anyways
+				
+				throw( new IOException(e.getMessage()));
+			}
+		}
+	}
+
+	protected static DHTTransportAlternativeContact[]
+	deserialiseAltContacts(
+		DataInputStream			is )
+	
+		throws IOException
+	{
+		int	len = deserialiseLength( is, 64 );
+		
+		List<DHTTransportAlternativeContact>	l = new ArrayList<DHTTransportAlternativeContact>( len );
+		
+		for (int i=0;i<len;i++){
+			
+			try{
+				
+				DHTTransportAlternativeContact contact = deserialiseAltContact( is );
+								
+				l.add( contact );
+				
+			}catch( DHTTransportException e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+				
+		DHTTransportAlternativeContact[]	res = new DHTTransportAlternativeContact[l.size()];
+		
+		l.toArray( res );
+		
+		return( res );
+	}
+	
+	protected static void
+	serialiseAltContactRequest(
+		DHTUDPPacketRequestPing		ping,
+		DataOutputStream			os )
+		
+		throws IOException
+	{
+		int[]	nets 	= ping.getAltNetworks();
+		int[]	counts	= ping.getAltNetworkCounts();
+		
+		int len = nets==null||counts==null?0:nets.length;
+		
+		serialiseLength( os, len, 16 );
+		
+		for ( int i=0;i<len;i++ ){
+			
+			os.write( nets[i] );
+			os.write( counts[i] );
+		}
+	}
+	
+	protected static void
+	deserialiseAltContactRequest(
+		DHTUDPPacketRequestPing		ping,
+		DataInputStream				is )
+		
+		throws IOException
+	{
+		int	len = deserialiseLength( is, 16 );
+
+		int[]	nets 	= new int[len];
+		int[]	counts	= new int[len];
+		
+		for ( int i=0;i<len;i++){
+			
+			nets[i] 	= is.read();
+			counts[i]	= is.read();
+			
+			if ( nets[i] == -1 || counts[i] == -1 ){
+				
+				throw( new EOFException());
+			}
+		}
+		
+		ping.setAltContactRequest( nets, counts );
+	}
+	
 	protected static void
 	serialiseVivaldi(
 		DHTUDPPacketReply	reply, 
@@ -1191,4 +1334,127 @@ DHTUDPUtils
 		
 		return( res );
 	}
+	
+	private static List<DHTTransportUDPImpl>			transports 		= new ArrayList<DHTTransportUDPImpl>();
+	private static List<DHTTransportAlternativeNetwork>	alt_networks 	= new ArrayList<DHTTransportAlternativeNetwork>();
+	
+	protected static void
+	registerTransport(
+		DHTTransportUDPImpl		transport )
+	{
+		synchronized( transports ){
+			
+			transports.add( transport );
+			
+			for ( DHTTransportAlternativeNetwork net: alt_networks ){
+				
+				transport.registerAlternativeNetwork( net );
+			}
+		}
+	}
+	
+	public static void
+	registerAlternativeNetwork(
+		DHTTransportAlternativeNetwork	net )
+	{
+		synchronized( transports ){
+			
+			alt_networks.add( net );
+			
+			for ( DHTTransportUDPImpl transport: transports ){
+				
+				transport.registerAlternativeNetwork( net );
+			}
+		}
+	}
+	
+	public static void
+	unregisterAlternativeNetwork(
+		DHTTransportAlternativeNetwork	net )
+	{
+		synchronized( transports ){
+			
+			alt_networks.remove( net );
+			
+			for ( DHTTransportUDPImpl transport: transports ){
+				
+				transport.unregisterAlternativeNetwork( net );
+			}
+		}
+	}
+	
+	public static List<DHTTransportAlternativeContact>
+	getAlternativeContacts(
+		int			network,
+		int			max )
+	{
+		List<DHTTransportAlternativeContact>	result_list = new ArrayList<DHTTransportAlternativeContact>(max);
+		
+		if ( max > 0 ){
+			
+			TreeSet<DHTTransportAlternativeContact> result_set =
+				new TreeSet<DHTTransportAlternativeContact>(
+					new Comparator<DHTTransportAlternativeContact>() 
+					{
+						public int 
+						compare(
+							DHTTransportAlternativeContact o1,
+							DHTTransportAlternativeContact o2 ) 
+						{
+							int res = o1.getAge() - o2.getAge();
+							
+							if ( res == 0 ){
+								
+								res = o1.getID() - o2.getID();
+							}
+							
+							return( res );
+						}
+					});
+			
+			synchronized( transports ){
+
+					// if we have a local provider then grab stuff from here
+				
+				for ( DHTTransportAlternativeNetwork net: alt_networks ){
+					
+					if ( net.getNetworkType() == network ){
+						
+						List<DHTTransportAlternativeContact> temp = net.getContacts( max );
+						
+						if ( temp != null ){
+							
+							result_set.addAll( temp );
+						}
+					}
+				}
+								
+					// merge in any remote contacts and then take the best ones
+				
+				for ( DHTTransportUDPImpl transport: transports ){
+										
+					DHTTransportAlternativeNetwork alt = transport.getAlternativeNetwork( network );
+					
+					if ( alt != null ){
+						
+						List<DHTTransportAlternativeContact> temp = alt.getContacts( max );
+						
+						if ( temp != null ){
+							
+							result_set.addAll( temp );
+						}
+					}
+				}
+			}
+	
+			Iterator<DHTTransportAlternativeContact> it = result_set.iterator();
+			
+			while( it.hasNext() && result_list.size() < max ){
+				
+				result_list.add( it.next());
+			}
+		}
+		
+		return( result_list );
+	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandler.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandler.java
index 8d7a4ab..fe4dd8b 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerException.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerException.java
index 33b548d..1bf5377 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerException.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerFactory.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerFactory.java
index 8353bd6..0982848 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerStats.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerStats.java
index e0a63bc..baf9161 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerStub.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerStub.java
index 0efb9cf..51c375f 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerStub.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketHandlerStub.java
@@ -4,18 +4,17 @@
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketNetworkHandler.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketNetworkHandler.java
index 2cd7d34..e782791 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketNetworkHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketNetworkHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketReceiver.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketReceiver.java
index 2f5bf48..4a0fbcf 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketReceiver.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPPacketReceiver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPRequestHandler.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPRequestHandler.java
index cb71249..db58384 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPRequestHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/udp/impl/packethandler/DHTUDPRequestHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransferHandler.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransferHandler.java
new file mode 100644
index 0000000..883270d
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransferHandler.java
@@ -0,0 +1,1785 @@
+/*
+ * Created on Sep 12, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.core.dht.transport.util;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.gudy.azureus2.core3.internat.MessageText;
+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.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.SystemTime;
+
+import com.aelitis.azureus.core.dht.DHTLogger;
+import com.aelitis.azureus.core.dht.impl.DHTLog;
+import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
+import com.aelitis.azureus.core.dht.transport.DHTTransportException;
+import com.aelitis.azureus.core.dht.transport.DHTTransportProgressListener;
+import com.aelitis.azureus.core.dht.transport.DHTTransportTransferHandler;
+import com.aelitis.azureus.core.dht.transport.udp.impl.DHTUDPPacketData;
+
+
+
+public class 
+DHTTransferHandler 
+{
+	private static final int	TRANSFER_QUEUE_MAX			= 128;
+	private static final long 	MAX_TRANSFER_QUEUE_BYTES	= 8*1024*1024;	 
+		
+	private static final long	WRITE_XFER_RESEND_DELAY_BASE		= 12500;
+	private static final long	READ_XFER_REREQUEST_DELAY_BASE		= 5000;
+	private static final long	WRITE_REPLY_TIMEOUT_BASE			= 60000;		
+	
+	private final long	WRITE_XFER_RESEND_DELAY;
+	private final long	READ_XFER_REREQUEST_DELAY;
+	private final long	WRITE_REPLY_TIMEOUT;	
+
+	private static boolean	XFER_TRACE	= false;
+
+	private Map<HashWrapper,transferHandlerInterceptor> transfer_handlers 	= new HashMap<HashWrapper,transferHandlerInterceptor>();
+	
+	private Map<Long,transferQueue>	read_transfers		= new HashMap<Long,transferQueue>();
+	private Map<Long,transferQueue> write_transfers		= new HashMap<Long,transferQueue>();
+	
+	private long	last_xferq_log;
+	
+	private int 	active_write_queue_processor_count;
+	private long	total_bytes_on_transfer_queues;
+	
+	private Map<HashWrapper,Object>	call_transfers		= new HashMap<HashWrapper,Object>();
+
+	private final Adapter			adapter;
+	private final int				max_data;
+	private final DHTLogger			logger;
+	
+	private AEMonitor	this_mon	= new AEMonitor( "DHTTransferHandler" );
+
+	public
+	DHTTransferHandler(
+		Adapter		_adapter,
+		int			_max_data,
+		DHTLogger	_logger )
+	{
+		this( _adapter, _max_data, 2, _logger );
+	}
+	
+	public
+	DHTTransferHandler(
+		Adapter		_adapter,
+		int			_max_data,
+		float		_latency_indicator,
+		DHTLogger	_logger )
+	{
+		adapter		= _adapter;
+		max_data	= _max_data;
+		logger		= _logger;
+		
+		WRITE_XFER_RESEND_DELAY 	= (long)( _latency_indicator*WRITE_XFER_RESEND_DELAY_BASE );
+		READ_XFER_REREQUEST_DELAY	= (long)( _latency_indicator*READ_XFER_REREQUEST_DELAY_BASE );
+		WRITE_REPLY_TIMEOUT			= (long)( _latency_indicator*WRITE_REPLY_TIMEOUT_BASE );
+	}
+	
+	
+	public void
+	registerTransferHandler(
+		byte[]						handler_key,
+		DHTTransportTransferHandler	handler )
+	{
+		registerTransferHandler( handler_key, handler, null );
+	}
+	
+	public void
+	registerTransferHandler(
+		byte[]						handler_key,
+		DHTTransportTransferHandler	handler,
+		Map<String,Object>			options )
+	{
+		if ( XFER_TRACE ){
+			logger.log( "Transfer handler (" + handler.getName() + ") registered for key '" + ByteFormatter.encodeString( handler_key ));
+		}
+		
+		synchronized( transfer_handlers ){
+			
+			transferHandlerInterceptor existing = 
+				transfer_handlers.put( 
+					new HashWrapper( handler_key ), 
+					new transferHandlerInterceptor(
+							handler, options ));
+			
+			if ( existing != null ){
+				
+				Debug.out( "Duplicate transfer handler: existing=" + existing.getName() + ", new=" + handler.getName());
+			}
+		}
+	}
+	
+	public void
+	unregisterTransferHandler(
+		byte[]						handler_key,
+		DHTTransportTransferHandler	handler )
+	{
+		if ( XFER_TRACE ){
+			logger.log( "Transfer handler (" + handler.getName() + ") unregistered for key '" + ByteFormatter.encodeString( handler_key ));
+		}
+		
+		synchronized( transfer_handlers ){
+			
+			transfer_handlers.remove( new HashWrapper( handler_key ));
+		}
+	}
+	
+	protected int
+	handleTransferRequest(
+		DHTTransportContact			target,
+		long						connection_id,
+		byte[]						transfer_key,
+		byte[]						request_key,
+		byte[]						data,
+		int							start,
+		int							length,
+		boolean						write_request,
+		boolean						first_packet_only )
+	
+		throws DHTTransportException
+	{
+		transferHandlerInterceptor	handler; 
+		
+		synchronized( transfer_handlers ){
+		
+			handler = transfer_handlers.get(new HashWrapper( transfer_key ));
+		}
+		
+		if ( handler == null ){
+			
+			// can get a lot of these on startup so we'll downgrade to just ignoring
+			//logger.log( "No transfer handler registered for key '" + ByteFormatter.encodeString(transfer_key) + "'" );
+			//throw( new DHTTransportException( "No transfer handler registered for " + ByteFormatter.encodeString(transfer_key) ));
+			
+			return( -1 );
+		}
+
+		if ( data == null ){
+			
+			data = handler.handleRead( target, request_key );
+		}
+		
+		if ( data == null ){
+			
+			return( -1 );
+			
+		}else{
+				
+				// special case 0 length data
+			
+			if ( data.length == 0 ){
+				
+				if ( write_request ){
+					
+					sendWriteRequest(
+							connection_id,
+							target,
+							transfer_key,
+							request_key,
+							data,
+							0,
+							0,
+							0 );						
+				}else{
+					
+					sendReadReply( 
+							connection_id,
+							target,
+							transfer_key,
+							request_key,
+							data,
+							0,
+							0,
+							0 );
+				}
+			}else{
+								
+				if ( start < 0 ){
+					
+					start	= 0;
+					
+				}else if ( start >= data.length ){
+					
+					logger.log( "dataRequest: invalid start position" );
+					
+					return( data.length );
+				}
+								
+				if ( length <= 0 ){
+					
+					length = data.length;
+					
+				}else if ( start + length > data.length ){
+					
+					logger.log( "dataRequest: invalid length" );
+					
+					return( data.length );
+				}
+				
+				int	end = start+length;
+				
+				while( start < end ){
+					
+					int	chunk = end - start;
+					
+					if ( chunk > max_data ){
+						
+						chunk = max_data;								
+					}
+					
+					if ( write_request ){
+						
+						sendWriteRequest(
+								connection_id,
+								target,
+								transfer_key,
+								request_key,
+								data,
+								start,
+								chunk,
+								data.length );
+												
+						if ( first_packet_only ){
+							
+							break;
+						}
+					}else{
+						
+						sendReadReply( 
+								connection_id,
+								target,
+								transfer_key,
+								request_key,
+								data,
+								start,
+								chunk,
+								data.length );
+					}
+					
+					start += chunk;
+				}
+			}
+			
+			return( data.length );
+		}
+	}
+	
+	public void
+	receivePacket(
+		final DHTTransportContact		originator,
+		final Packet					req )
+	{
+		/*
+		if ((int)(Math.random() * 4 )== 0 ){
+			
+			System.out.println("dropping request packet:" + req.getString());
+			
+			return;
+		}
+		*/
+				
+			// both requests and replies come through here. Currently we only support read
+			// requests so we can safely use the data.length == 0 test to discriminate between
+			// a request and a reply to an existing transfer
+		
+		byte	packet_type = req.getPacketType();
+		
+		if ( XFER_TRACE ){
+			System.out.println( "dataRequest: originator=" + originator.getAddress() + ",packet=" + req.getString());
+		}
+		
+		if ( packet_type == Packet.PT_READ_REPLY ){
+			
+			transferQueue	queue = lookupTransferQueue( read_transfers, req.getConnectionId());
+			
+				// unmatched -> drop it
+			
+			if ( queue != null ){
+			
+				queue.add( req );
+			}
+			
+		}else if ( packet_type == Packet.PT_WRITE_REPLY ){
+				
+			transferQueue	queue = lookupTransferQueue( write_transfers, req.getConnectionId());
+				
+				// unmatched -> drop it
+				
+			if ( queue != null ){
+				
+				queue.add( req );
+			}
+		}else{
+			
+			byte[]	transfer_key = req.getTransferKey();
+									
+			if ( packet_type == Packet.PT_READ_REQUEST ){
+
+				try{
+					handleTransferRequest( 
+							originator,
+							req.getConnectionId(),
+							transfer_key,
+							req.getRequestKey(),
+							null,
+							req.getStartPosition(),
+							req.getLength(),
+							false, false );
+					
+				}catch( DHTTransportException e ){
+					
+					logger.log(e);
+				}
+
+			}else{
+				
+					// 	write request 
+					
+				transferQueue	old_queue = lookupTransferQueue( read_transfers, req.getConnectionId());
+				
+				if ( old_queue != null ){
+					
+					old_queue.add( req );
+					
+				}else{
+				
+					final transferHandlerInterceptor	handler;
+					
+					synchronized( transfer_handlers ){
+						
+						handler = transfer_handlers.get(new HashWrapper( transfer_key ));
+					}
+					
+					if ( handler == null ){
+						
+						// get lots of these when local endpoint removed while other's still out there...
+						
+						//logger.log( "No transfer handler registered for key '" + ByteFormatter.encodeString(transfer_key) + "'" );
+						
+					}else{
+						try{
+
+							int	req_total_len = req.getTotalLength();
+							
+							if (  handler.getBooleanOption( "disable_call_acks", false ) && req_total_len == req.getLength()){
+								
+								byte[] write_data = req.getData();
+								
+								if ( write_data.length != req_total_len ){
+									
+									byte[]	temp = new byte[req_total_len];
+									
+									System.arraycopy( write_data, 0, temp, 0, req_total_len );
+									
+									write_data = temp;
+								}
+								
+								final byte[]	reply_data = handler.handleWrite( originator, req.getConnectionId(), req.getRequestKey(), write_data );
+								
+								if ( reply_data != null ){
+									
+									if ( reply_data.length <= max_data ){
+																				
+										long write_connection_id = adapter.getConnectionID();
+										
+										sendWriteRequest(
+												write_connection_id,
+												originator,
+												transfer_key,
+												req.getRequestKey(),
+												reply_data,
+												0,
+												reply_data.length,
+												reply_data.length );
+									}else{
+										
+										try{
+											this_mon.enter();
+											
+											if ( active_write_queue_processor_count >= TRANSFER_QUEUE_MAX ){
+																								
+												throw( new DHTTransportException( "Active write queue process thread limit exceeded" ));
+											}
+											
+											active_write_queue_processor_count++;
+											
+											if ( XFER_TRACE ){
+												System.out.println( "active_write_queue_processor_count=" + active_write_queue_processor_count );
+											}
+										}finally{
+											
+											this_mon.exit();
+										}
+										
+										new AEThread2( "DHTTransportUDP:writeQueueProcessor", true )
+										{
+											public void
+											run()
+											{
+												try{
+
+													writeTransfer(
+															new DHTTransportProgressListener()
+															{
+																public void
+																reportSize(
+																	long	size )
+																{
+																	if ( XFER_TRACE ){
+																		System.out.println( "writeXferReply: size=" + size );
+																	}
+																}
+																
+																public void
+																reportActivity(
+																	String	str )
+																{
+																	if ( XFER_TRACE ){
+																		System.out.println( "writeXferReply: act=" + str );
+																	}
+																}
+																
+																public void
+																reportCompleteness(
+																	int		percent )
+																{
+																	if ( XFER_TRACE ){
+																		System.out.println( "writeXferReply: %=" + percent );
+																	}
+																}
+															},
+															originator,
+															req.getTransferKey(),
+															req.getRequestKey(),
+															reply_data,
+															WRITE_REPLY_TIMEOUT );
+													
+												}catch( DHTTransportException e ){
+													
+													logger.log( "Failed to process transfer queue: " + Debug.getNestedExceptionMessage(e));
+													
+												}finally{
+													
+													try{
+														this_mon.enter();
+																										
+														active_write_queue_processor_count--;
+														
+														if ( XFER_TRACE ){
+															System.out.println( "active_write_queue_processor_count=" + active_write_queue_processor_count );
+														}
+													}finally{
+														
+														this_mon.exit();
+													}
+												}
+											}
+										}.start();
+										
+											// indicate that at least one packet has been received
+											
+										sendWriteReply(
+											req.getConnectionId(),
+											originator,
+											req.getTransferKey(),
+											req.getRequestKey(),
+											req.getStartPosition(),
+											req.getLength());
+									}	
+								}					
+							}else{
+								
+								final transferQueue new_queue = new transferQueue( read_transfers, req.getConnectionId());
+							
+									// add the initial data for this write request
+								
+								new_queue.add( req );
+								
+									// set up the queue processor
+									
+								try{
+									this_mon.enter();
+									
+									if ( active_write_queue_processor_count >= TRANSFER_QUEUE_MAX ){
+										
+										new_queue.destroy();
+										
+										throw( new DHTTransportException( "Active write queue process thread limit exceeded" ));
+									}
+									
+									active_write_queue_processor_count++;
+									
+									if ( XFER_TRACE ){
+										System.out.println( "active_write_queue_processor_count=" + active_write_queue_processor_count );
+									}
+								}finally{
+									
+									this_mon.exit();
+								}
+	
+								new AEThread2( "DHTTransportUDP:writeQueueProcessor", true )
+									{
+										public void
+										run()
+										{
+											try{
+												byte[] write_data = 
+													runTransferQueue( 
+														new_queue, 
+														new DHTTransportProgressListener()
+														{
+															public void
+															reportSize(
+																long	size )
+															{
+																if ( XFER_TRACE ){
+																	System.out.println( "writeXfer: size=" + size );
+																}
+															}
+															
+															public void
+															reportActivity(
+																String	str )
+															{
+																if ( XFER_TRACE ){
+																	System.out.println( "writeXfer: act=" + str );
+																}
+															}
+															
+															public void
+															reportCompleteness(
+																int		percent )
+															{
+																if ( XFER_TRACE ){
+																	System.out.println( "writeXfer: %=" + percent );
+																}
+															}
+														},
+														originator,
+														req.getTransferKey(),
+														req.getRequestKey(),
+														60000,
+														false );
+												
+												if ( write_data != null ){
+													
+														// xfer complete, send ack if multi-packet xfer
+														// (ack already sent below if single packet)
+													
+													if ( 	req.getStartPosition() != 0 ||
+															req.getLength() != req.getTotalLength() ){
+														
+														sendWriteReply(
+																req.getConnectionId(),
+																originator,
+																req.getTransferKey(),
+																req.getRequestKey(),
+																0,
+																req.getTotalLength());
+													}
+													
+													byte[]	reply_data = handler.handleWrite( originator, req.getConnectionId(), req.getRequestKey(), write_data );
+													
+													if ( reply_data != null ){
+														
+														writeTransfer(
+																new DHTTransportProgressListener()
+																{
+																	public void
+																	reportSize(
+																		long	size )
+																	{
+																		if ( XFER_TRACE ){
+																			System.out.println( "writeXferReply: size=" + size );
+																		}
+																	}
+																	
+																	public void
+																	reportActivity(
+																		String	str )
+																	{
+																		if ( XFER_TRACE ){
+																			System.out.println( "writeXferReply: act=" + str );
+																		}
+																	}
+																	
+																	public void
+																	reportCompleteness(
+																		int		percent )
+																	{
+																		if ( XFER_TRACE ){
+																			System.out.println( "writeXferReply: %=" + percent );
+																		}
+																	}
+																},
+																originator,
+																req.getTransferKey(),
+																req.getRequestKey(),
+																reply_data,
+																WRITE_REPLY_TIMEOUT );
+																
+													}
+												}
+												
+											}catch( DHTTransportException e ){
+												
+												logger.log( "Failed to process transfer queue: " + Debug.getNestedExceptionMessage(e));
+												
+											}finally{
+												
+												try{
+													this_mon.enter();
+																									
+													active_write_queue_processor_count--;
+													
+													if ( XFER_TRACE ){
+														System.out.println( "active_write_queue_processor_count=" + active_write_queue_processor_count );
+													}
+												}finally{
+													
+													this_mon.exit();
+												}
+											}
+										}
+									}.start();
+									
+										// indicate that at least one packet has been received
+									
+								sendWriteReply(
+									req.getConnectionId(),
+									originator,
+									req.getTransferKey(),
+									req.getRequestKey(),
+									req.getStartPosition(),
+									req.getLength());
+							}
+						}catch( DHTTransportException e ){
+								
+							long now = SystemTime.getMonotonousTime();
+							
+							if ( last_xferq_log == 0 || now - last_xferq_log > 5*60*1000 ){
+							
+								last_xferq_log = now;
+								
+								logger.log( "Failed to create transfer queue" );
+							
+								logger.log( e );
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+		
+	public byte[]
+	readTransfer(
+		DHTTransportProgressListener	listener,
+		DHTTransportContact				target,
+		byte[]							handler_key,
+		byte[]							key,
+		long							timeout )
+	
+		throws DHTTransportException
+	{
+		long	connection_id 	= adapter.getConnectionID();
+		
+		transferQueue	transfer_queue = new transferQueue( read_transfers, connection_id );
+		
+		return( runTransferQueue( transfer_queue, listener, target, handler_key, key, timeout, true ));
+	}
+	
+	protected byte[]
+	runTransferQueue(
+		transferQueue					transfer_queue,
+		DHTTransportProgressListener	listener,
+		DHTTransportContact				target,
+		byte[]							handler_key,
+		byte[]							key,
+		long							timeout,
+		boolean							read_transfer )
+	
+		throws DHTTransportException
+	{		
+		SortedSet<Packet>	packets = 
+			new TreeSet<Packet>(
+				new Comparator<Packet>()
+				{
+					public int
+					compare(
+						Packet	p1,
+						Packet	p2 )
+					{
+						return( p1.getStartPosition() - p2.getStartPosition());
+					}
+				});
+		
+		int	entire_request_count = 0;
+		
+		int transfer_size 	= -1;
+		int	transferred		= 0;
+		
+		String	target_name = DHTLog.getString2(target.getID());
+		
+		try{
+			long	start = SystemTime.getCurrentTime();
+			
+			if ( read_transfer ){
+			
+				listener.reportActivity( getMessageText( "request_all", target_name ));
+
+				entire_request_count++;
+			
+				sendReadRequest( transfer_queue.getConnectionID(), target, handler_key, key, 0, 0 );
+
+			}else{
+				
+					// write transfer - data already on its way, no need to request it
+				
+				entire_request_count++;
+			}
+			
+			while( SystemTime.getCurrentTime() - start <= timeout ){					
+				
+				Packet	reply = transfer_queue.receive( READ_XFER_REREQUEST_DELAY );
+				
+				if ( reply != null ){
+	
+					if ( transfer_size == -1 ){
+						
+						transfer_size = reply.getTotalLength();
+						
+						listener.reportSize( transfer_size );
+					}
+					
+					Iterator<Packet>	it = packets.iterator();
+					
+					boolean	duplicate = false;
+					
+					while( it.hasNext()){
+						
+						Packet	p = it.next();
+						
+							// ignore overlaps
+						
+						if (	p.getStartPosition() < reply.getStartPosition() + reply.getLength() &&
+								p.getStartPosition() + p.getLength() > reply.getStartPosition()){
+							
+							duplicate	= true;
+							
+							break;
+						}
+					}
+					
+					if ( !duplicate ){
+						
+						listener.reportActivity( 
+								getMessageText( "received_bit", 
+								new String[]{ 
+										String.valueOf( reply.getStartPosition()),
+										String.valueOf(reply.getStartPosition() + reply.getLength()),
+										target_name }));
+
+						transferred += reply.getLength();
+						
+						listener.reportCompleteness( transfer_size==0?100: ( 100 * transferred / transfer_size ));
+						
+						packets.add( reply );
+						
+							// see if we're done				
+					
+						it = packets.iterator();
+						
+						int	pos			= 0;
+						int	actual_end	= -1;
+						
+						while( it.hasNext()){
+							
+							Packet	p = (Packet)it.next();
+						
+							if ( actual_end == -1 ){
+								
+								actual_end = p.getTotalLength();
+							}
+							
+							if ( p.getStartPosition() != pos ){
+								
+									// missing data, give up
+								
+								break;
+							}
+							
+							pos += p.getLength();
+							
+							if ( pos == actual_end ){
+							
+									// huzzah, we got the lot
+							
+								listener.reportActivity( getMessageText( "complete" ));
+								
+								byte[]	result = new byte[actual_end];
+								
+								it =  packets.iterator();
+								
+								pos	= 0;
+								
+								while( it.hasNext()){
+									
+									p = (Packet)it.next();
+
+									System.arraycopy( p.getData(), 0, result, pos, p.getLength());
+									
+									pos	+= p.getLength();
+								}
+								
+								return( result );
+							}
+						}
+					}
+				}else{
+					
+						// timeout, look for missing bits
+					
+					if ( packets.size() == 0 ){
+						
+						if ( entire_request_count == 2 ){
+						
+							listener.reportActivity( getMessageText( "timeout", target_name ));
+							
+							return( null );
+						}
+						
+						entire_request_count++;
+						
+						listener.reportActivity( getMessageText( "rerequest_all", target_name ));
+						
+						sendReadRequest( transfer_queue.getConnectionID(), target, handler_key, key, 0, 0 );
+						
+					}else{
+						
+						Iterator<Packet> it = packets.iterator();
+					
+						int	pos			= 0;
+						int	actual_end	= -1;
+						
+						while( it.hasNext()){
+							
+							Packet	p = it.next();
+						
+							if ( actual_end == -1 ){
+								
+								actual_end = p.getTotalLength();
+							}
+							
+							if ( p.getStartPosition() != pos ){
+								
+								listener.reportActivity( 
+										getMessageText( "rerequest_bit",
+												new String[]{
+													String.valueOf( pos ),
+													String.valueOf( p.getStartPosition()),
+													target_name }));
+								
+								sendReadRequest( 
+										transfer_queue.getConnectionID(), 
+										target, 
+										handler_key, 
+										key,
+										pos,
+										p.getStartPosition()-pos );
+							
+							}
+							
+							pos = p.getStartPosition() + p.getLength();
+						}
+						
+						if ( pos != actual_end ){
+							
+							listener.reportActivity( 
+									getMessageText( "rerequest_bit",
+											new String[]{
+												String.valueOf( pos ),
+												String.valueOf( actual_end ),
+												target_name }));
+			
+							sendReadRequest( 
+									transfer_queue.getConnectionID(), 
+									target, 
+									handler_key, 
+									key,
+									pos,
+									actual_end - pos );						
+						}
+					}
+				}
+			}
+			
+			if ( packets.size()==0 ){
+				
+				listener.reportActivity( getMessageText( "timeout", target_name ));
+				
+			}else{
+				
+				listener.reportActivity( 
+						getMessageText( 
+							"timeout_some", 
+							new String[]{ String.valueOf( packets.size()), target_name }));
+							
+			}
+			
+			return( null );
+			
+		}finally{
+			
+			transfer_queue.destroy();
+		}
+	}
+	
+	public void
+	writeTransfer(
+		DHTTransportProgressListener	listener,
+		DHTTransportContact				target,
+		byte[]							handler_key,
+		byte[]							key,
+		byte[]							data,
+		long							timeout )
+	
+		throws DHTTransportException
+	{
+		long	connection_id 	= adapter.getConnectionID();
+
+		writeTransfer( listener, target, connection_id, handler_key, key, data, timeout );
+	}
+	
+	private void
+	writeTransfer(
+		DHTTransportProgressListener	listener,
+		DHTTransportContact				target,
+		long							connection_id,
+		byte[]							handler_key,
+		byte[]							key,
+		byte[]							data,
+		long							timeout )
+	
+		throws DHTTransportException
+	{
+		transferQueue	transfer_queue = null;
+	
+		try{		
+			transfer_queue = new transferQueue( write_transfers, connection_id );
+		
+			boolean	ok 				= false;
+			boolean	reply_received	= false;
+			
+			int		loop			= 0;
+			int		total_length	= data.length;
+			
+			long	start = SystemTime.getCurrentTime();
+			
+			long	last_packet_time = 0;
+			
+			while( true ){
+				
+				long	now = SystemTime.getCurrentTime();
+				
+				if ( now < start ){
+					
+					start				= now;
+					
+					last_packet_time	= 0;
+					
+				}else{
+					
+					if ( now - start > timeout ){
+						
+						break;
+					}
+				}
+				
+				long	time_since_last_packet = now - last_packet_time;
+				
+				if ( time_since_last_packet >= WRITE_XFER_RESEND_DELAY ){
+					
+					listener.reportActivity( getMessageText( loop==0?"sending":"resending" ));
+				
+					loop++;
+				
+					total_length =	handleTransferRequest(
+												target,
+												connection_id,
+												handler_key,
+												key,
+												data,
+												-1, -1,
+												true,
+												reply_received );	// first packet only if we've has a reply
+				
+					last_packet_time		= now;
+					time_since_last_packet	= 0;
+				}
+				
+				Packet packet = transfer_queue.receive( WRITE_XFER_RESEND_DELAY - time_since_last_packet );
+			
+				if ( packet != null ){
+					
+					last_packet_time	= now;
+					
+					reply_received = true;
+					
+					if ( packet.getStartPosition() == 0 && packet.getLength() == total_length ){
+						
+						ok	= true;
+					
+						break;
+					}
+				}
+			}
+			
+			if ( ok ){
+				
+				listener.reportCompleteness( 100 );
+				
+				listener.reportActivity( getMessageText( "send_complete" ));
+				
+			}else{
+				
+				listener.reportActivity( getMessageText( "send_timeout" ));
+				
+				throw( new DHTTransportException( "Timeout" ));
+			}
+		}finally{
+			
+			if ( transfer_queue != null ){
+				
+				transfer_queue.destroy();
+			}
+		}
+	}
+	
+	public byte[]
+	writeReadTransfer(
+		DHTTransportProgressListener	listener,
+		DHTTransportContact				target,
+		byte[]							transfer_key,
+		byte[]							data,
+		long							timeout )	
+	
+		throws DHTTransportException
+	{
+		transferHandlerInterceptor	handler;
+		
+		synchronized( transfer_handlers ){
+			
+			handler = transfer_handlers.get(new HashWrapper( transfer_key ));
+		}
+
+		if ( handler == null ){
+			
+			return( null );
+		}
+		
+		boolean	no_acks = handler.getBooleanOption( "disable_call_acks", false ) && data.length <= max_data;
+			
+		long	connection_id 	= adapter.getConnectionID();
+		
+		byte[]	call_key = new byte[20];
+		
+		RandomUtils.SECURE_RANDOM.nextBytes( call_key );
+		
+		AESemaphore	call_sem = new AESemaphore( "DHTTransportUDP:calSem" );
+		
+		HashWrapper	wrapped_key = new HashWrapper( call_key );
+		
+		try{
+			this_mon.enter();
+			
+			call_transfers.put( wrapped_key, new Object[]{ call_sem, connection_id });
+		
+		}finally{
+			
+			this_mon.exit();
+		}
+		
+		boolean	removed = false;
+		
+		try{
+			if ( no_acks ){
+								
+				int retry_count = 0;
+				
+				while( true ){
+					
+					long	start = SystemTime.getMonotonousTime();
+
+					sendWriteRequest(
+							connection_id,
+							target,
+							transfer_key,
+							call_key,
+							data,
+							0,
+							data.length,
+							data.length );
+					
+					long timeout_to_use = Math.min( timeout,  WRITE_XFER_RESEND_DELAY );
+					
+					if ( call_sem.reserve( timeout_to_use )){
+						
+						try{
+							this_mon.enter();
+						
+							Object	res = call_transfers.remove( wrapped_key );
+							
+							removed = true;
+									
+							if ( res instanceof byte[] ){
+								
+								return((byte[])res);
+							}
+						}finally{
+							
+							this_mon.exit();
+						}
+						
+						break;
+						
+					}else{
+						
+						if ( retry_count > 0 ){
+							
+							break;
+						}
+						
+						retry_count++;
+						
+						timeout -= SystemTime.getMonotonousTime() - start;
+						
+						if ( timeout < 1000 ){
+							
+							break;
+						}
+					}
+				}
+			}else{
+							
+				writeTransfer( listener, target, connection_id, transfer_key, call_key, data, timeout );
+				
+				if ( call_sem.reserve( timeout )){
+					
+					try{
+						this_mon.enter();
+					
+						Object	res = call_transfers.remove( wrapped_key );
+						
+						removed = true;
+						
+						if ( res instanceof byte[] ){
+							
+							return((byte[])res);
+						}
+					}finally{
+						
+						this_mon.exit();
+					}
+				}
+			}
+		}finally{
+			
+			if ( !removed ){
+				
+				try{
+					this_mon.enter();
+				
+					call_transfers.remove( wrapped_key );
+					
+				}finally{
+					
+					this_mon.exit();
+				}
+			}
+		}
+		
+		throw( new DHTTransportException( "timeout" ));
+	}
+	
+	protected transferQueue
+	lookupTransferQueue(
+		Map<Long,transferQueue>			transfers,
+		long							id )
+	{
+		try{
+			this_mon.enter();
+
+			return(transfers.get(new Long(id)));
+			
+		}finally{
+			
+			this_mon.exit();
+		}	
+	}
+	
+	protected String
+	getMessageText(
+		String	resource )
+	{
+		return( MessageText.getString( "DHTTransport.report." + resource ));
+	}
+	
+	protected String
+	getMessageText(
+		String	resource,
+		String	param )
+	{
+		return( MessageText.getString( "DHTTransport.report." + resource, new String[]{ param }));
+	}
+	
+	protected String
+	getMessageText(
+		String		resource,
+		String[]	params )
+	{
+		return( MessageText.getString( "DHTTransport.report." + resource, params));
+	}
+	
+	protected class
+	transferQueue
+	{
+		private Map<Long,transferQueue>			transfers;
+		
+		private long		connection_id;
+		private boolean		destroyed;
+		
+		private List<Packet>		packets	= new ArrayList<Packet>();
+		
+		private AESemaphore	packets_sem	= new AESemaphore("DHTUDPTransport:transferQueue");
+		
+		protected
+		transferQueue(
+			Map<Long,transferQueue>		_transfers,
+			long						_connection_id )
+		
+			throws DHTTransportException
+		{
+			transfers		= _transfers;
+			connection_id	= _connection_id;
+			
+			try{
+				this_mon.enter();
+
+				if ( transfers.size() > TRANSFER_QUEUE_MAX ){
+					
+					Debug.out( "Transfer queue count limit exceeded" );
+					
+					throw( new DHTTransportException( "Transfer queue limit exceeded" ));
+				}
+				
+				Long l_id = new Long( connection_id );
+				
+				transferQueue	existing = (transferQueue)transfers.get( l_id );
+				
+				if ( existing != null ){
+					
+					existing.destroy();
+				}
+				
+				transfers.put( l_id, this );
+				
+			}finally{
+				
+				this_mon.exit();
+			}			
+		}
+		
+		protected long
+		getConnectionID()
+		{
+			return( connection_id );
+		}
+		
+		protected void
+		add(
+			Packet	packet )
+		{
+			try{
+				this_mon.enter();
+	
+				if ( destroyed ){
+					
+					return;
+				}
+				
+				if ( total_bytes_on_transfer_queues > MAX_TRANSFER_QUEUE_BYTES ){
+					
+					Debug.out( "Transfer queue byte limit exceeded" );
+				
+						// just drop the packet
+					
+					return;
+				}
+				
+				int	length = packet.getLength();
+				
+				total_bytes_on_transfer_queues += length;
+				
+				if ( XFER_TRACE ){
+					System.out.println( "total_bytes_on_transfer_queues=" + total_bytes_on_transfer_queues );
+				}
+				
+				packets.add( packet );
+				
+			}finally{
+				
+				this_mon.exit();
+			}
+			
+			packets_sem.release();
+		}
+		
+		protected Packet
+		receive(
+			long	timeout )
+		{
+			if ( packets_sem.reserve( timeout )){
+				
+				try{
+					this_mon.enter();
+						
+					if ( destroyed ){
+						
+						return( null );
+					}
+					
+					Packet packet = (Packet)packets.remove(0);
+					
+					int	length = packet.getLength();
+					
+					total_bytes_on_transfer_queues -= length;
+
+					if ( XFER_TRACE ){
+						System.out.println( "total_bytes_on_transfer_queues=" + total_bytes_on_transfer_queues );
+					}
+					
+					return( packet );
+					
+				}finally{
+					
+					this_mon.exit();
+				}				
+			}else{
+				
+				return( null );
+			}
+		}
+		
+		protected void
+		destroy()
+		{
+			try{
+				this_mon.enter();
+					
+				destroyed = true;
+				
+				transfers.remove( new Long( connection_id ));
+				
+				for (int i=0;i<packets.size();i++){
+					
+					Packet	packet = (Packet)packets.get(i);
+					
+					int	length = packet.getLength();
+					
+					total_bytes_on_transfer_queues -= length;
+					
+					if ( XFER_TRACE ){
+						System.out.println( "total_bytes_on_transfer_queues=" + total_bytes_on_transfer_queues );
+					}
+				}
+				
+				packets.clear();
+				
+				packets_sem.releaseForever();
+				
+			}finally{
+				
+				this_mon.exit();
+			}
+		}
+	}
+	
+	public void
+	sendReadRequest(
+		long						connection_id,	
+		DHTTransportContact			contact,
+		byte[]						transfer_key,
+		byte[]						key,
+		int							start_pos,
+		int							len )
+	{
+		if ( XFER_TRACE ){
+			logger.log( "Transfer read request: key = " + DHTLog.getFullString( key ) + ", contact = " + contact.getString());
+		}
+
+		adapter.sendRequest(
+			contact,
+			new Packet(
+				connection_id,
+				Packet.PT_READ_REQUEST, 
+				transfer_key, 
+				key, 
+				new byte[0], 
+				start_pos, 
+				len, 
+				0 ));
+	}
+	
+	public void
+	sendReadReply(
+		long						connection_id,	
+		DHTTransportContact			contact,
+		byte[]						transfer_key,
+		byte[]						key,
+		byte[]						data,
+		int							start_position,
+		int							length,
+		int							total_length )
+	{					
+		if ( XFER_TRACE ){
+			logger.log( "Transfer read reply: key = " + DHTLog.getFullString( key ) + ", contact = " + contact.getString());
+		}
+		
+		adapter.sendRequest(
+			contact,
+			new Packet(
+				connection_id,
+				Packet.PT_READ_REPLY, 
+				transfer_key, 
+				key, 
+				data, 
+				start_position, 
+				length, 
+				total_length ));
+	}
+	
+	public void
+	sendWriteRequest(
+		long						connection_id,	
+		DHTTransportContact			contact,
+		byte[]						transfer_key,
+		byte[]						key,
+		byte[]						data,
+		int							start_position,
+		int							length,
+		int							total_length )
+	{
+		if ( XFER_TRACE ){
+			logger.log( "Transfer write request: key = " + DHTLog.getFullString( key ) + ", contact = " + contact.getString());
+		}
+		
+		adapter.sendRequest(
+			contact,
+			new Packet(
+				connection_id,
+				Packet.PT_WRITE_REQUEST, 
+				transfer_key, 
+				key, 
+				data, 
+				start_position, 
+				length, 
+				total_length ));
+	}
+	
+	public void
+	sendWriteReply(
+		long						connection_id,	
+		DHTTransportContact			contact,
+		byte[]						transfer_key,
+		byte[]						key,
+		int							start_position,
+		int							length )
+	{
+		if ( XFER_TRACE ){
+			logger.log( "Transfer write reply: key = " + DHTLog.getFullString( key ) + ", contact = " + contact.getString());
+		}
+		
+		adapter.sendRequest(		
+			contact,
+			new Packet(
+				connection_id,
+				Packet.PT_WRITE_REPLY, 
+				transfer_key, 
+				key, 
+				new byte[0], 
+				start_position, 
+				length, 
+				0 ));
+	}
+	
+	protected class
+	transferHandlerInterceptor
+		implements DHTTransportTransferHandler
+	{
+		private DHTTransportTransferHandler		handler;
+		private Map<String,Object>				options;
+		
+		protected
+		transferHandlerInterceptor(
+			DHTTransportTransferHandler		_handler,
+			Map<String,Object>				_options )
+		{
+			handler	= _handler;
+			options	= _options;
+		}
+		
+		public String
+		getName()
+		{
+			return( handler.getName());
+		}
+		
+		public boolean
+		getBooleanOption(
+			String		name,
+			boolean		def )
+		{
+			if ( options == null ){
+				
+				return( def );
+			}
+			
+			Boolean b = (Boolean)options.get( name );
+			
+			return( b==null?def:b );
+		}
+		
+		public byte[]
+    	handleRead(
+    		DHTTransportContact		originator,
+    		byte[]					key )
+		{
+			return( handler.handleRead( originator, key ));
+		}
+    	
+	   	public byte[]
+	   	handleWrite(
+	   		DHTTransportContact		originator,
+	   		byte[]					key,
+	   		byte[]					value )
+	   	{
+	   		return( handleWrite( originator, 0, key, value ));
+	   	}
+	   	
+    	public byte[]
+    	handleWrite(
+    		DHTTransportContact		originator,
+    		long					connection_id,
+    		byte[]					key,
+    		byte[]					value )
+    	{
+    		HashWrapper	key_wrapper = new HashWrapper( key );
+    		
+    			// see if this is the response to an outstanding call
+    		
+    		try{
+    			this_mon.enter();
+    			
+    			Object	_obj = call_transfers.get( key_wrapper );
+    			
+    			if ( _obj instanceof Object[] ){
+    				
+    				Object[] obj = (Object[])_obj;
+    				
+    					// prevent loopback requests from returning the request as the result
+    				
+    				if ((Long)obj[1] != connection_id ){
+    					
+	    				AESemaphore	sem = (AESemaphore)obj[0];
+	    				
+	    				call_transfers.put( key_wrapper, value );
+	    				
+	    				sem.release();
+	    				
+	    				return( null );
+    				}
+    			}
+    		}finally{
+    			
+    			this_mon.exit();
+    		}
+    		
+    		return( handler.handleWrite( originator, key, value ));
+    	}
+	}
+	
+	public static class
+	Packet
+	{
+		public static final byte		PT_READ_REQUEST		= DHTUDPPacketData.PT_READ_REQUEST;
+		public static final byte		PT_READ_REPLY		= DHTUDPPacketData.PT_READ_REPLY;
+		public static final byte		PT_WRITE_REQUEST	= DHTUDPPacketData.PT_WRITE_REQUEST;
+		public static final byte		PT_WRITE_REPLY		= DHTUDPPacketData.PT_WRITE_REPLY;
+
+		private long	connection_id;
+		private byte	packet_type;
+		private byte[]	transfer_key;
+		private byte[]	key;
+		private byte[]	data;
+		private int		start_position;
+		private int		length;
+		private int		total_length;
+		
+		private int		flags;
+		
+		public
+		Packet(
+			long		_connection_id,
+			byte		_packet_type,
+			byte[]		_transfer_key,
+			byte[]		_key,
+			byte[]		_data,
+			int			_start_position,
+			int			_length,
+			int			_total_length )
+		{
+			connection_id	= _connection_id;
+			packet_type		= _packet_type;
+			transfer_key	= _transfer_key;
+			key				= _key;
+			data			= _data;
+			start_position	= _start_position;
+			length			= _length;
+			total_length	= _total_length;
+		}
+		
+		public
+		Packet(
+			long		_connection_id,
+			byte		_packet_type,
+			byte[]		_transfer_key,
+			byte[]		_key,
+			byte[]		_data,
+			int			_start_position,
+			int			_length,
+			int			_total_length,
+			int			_flags )
+		{
+			connection_id	= _connection_id;
+			packet_type		= _packet_type;
+			transfer_key	= _transfer_key;
+			key				= _key;
+			data			= _data;
+			start_position	= _start_position;
+			length			= _length;
+			total_length	= _total_length;
+			flags			= _flags;
+		}
+		
+		public long
+		getConnectionId()
+		{
+			return( connection_id );
+		}
+		
+		public byte
+		getPacketType()
+		{
+			return( packet_type );
+		}
+		
+		public byte[]
+		getTransferKey()
+		{
+			return( transfer_key );
+		}
+		
+		public byte[]
+		getRequestKey()
+		{
+			return( key );
+		}
+		
+		public byte[]
+		getData()
+		{
+			return( data );
+		}
+		
+		public int
+		getStartPosition()
+		{
+			return( start_position );
+		}
+		
+		public int
+		getLength()
+		{
+			return( length );
+		}
+		
+		public int
+		getTotalLength()
+		{
+			return( total_length );
+		}
+		
+		public int
+		getFlags()
+		{
+			return( flags );
+		}
+		
+		public String
+		getString()
+		{
+			return( "tk=" + DHTLog.getString2( transfer_key ) + ",rk=" + 
+					DHTLog.getString2( key ) + ",data=" + data.length +
+					",st=" + start_position + ",len=" + length + ",tot=" + total_length );
+		}
+	}
+	
+	public interface
+	Adapter
+	{
+		public long
+		getConnectionID();
+		
+		public void
+		sendRequest(
+			DHTTransportContact			contact,
+			Packet						packet );
+	
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransportRequestCounter.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransportRequestCounter.java
index 727ccaa..af9c6bc 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransportRequestCounter.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransportRequestCounter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -120,7 +117,7 @@ DHTTransportRequestCounter
 		DHTTransportContact contact, 
 		byte[]				key,
 		int					max,
-		byte				flags )
+		short				flags )
 	{
 		stats.findValueReceived();
 		
diff --git a/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransportStatsImpl.java b/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransportStatsImpl.java
index 459bf16..aa36403 100644
--- a/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransportStatsImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/dht/transport/util/DHTTransportStatsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -25,6 +22,7 @@ package com.aelitis.azureus.core.dht.transport.util;
 import java.net.InetSocketAddress;
 import java.util.Arrays;
 
+import org.gudy.azureus2.core3.util.AddressUtils;
 import org.gudy.azureus2.core3.util.SystemTime;
 
 import com.aelitis.azureus.core.dht.impl.DHTLog;
@@ -397,7 +395,7 @@ DHTTransportStatsImpl
 	{
 		outgoing_requests++;		
 
-		if ( DHTLog.TRACE_VERSIONS ){
+		if ( DHTLog.TRACE_VERSIONS && request != null ){
 			
 			byte protocol_version = request.getProtocolVersion();
 			
@@ -445,7 +443,7 @@ DHTTransportStatsImpl
 	{
 		incoming_requests++;
 		
-		if ( alien ){
+		if ( alien && request != null ){
 			
 			// System.out.println( "Alien on net " + request.getNetwork() + " - sender=" + request.getAddress());
 			
@@ -481,7 +479,7 @@ DHTTransportStatsImpl
 			}
 		}
 		
-		if ( DHTLog.TRACE_VERSIONS ){
+		if ( DHTLog.TRACE_VERSIONS && request != null ){
 			
 			byte protocol_version = request.getProtocolVersion();
 			
@@ -539,7 +537,7 @@ DHTTransportStatsImpl
 		InetSocketAddress	originator_address,
 		long				skew )
 	{
-		byte[]	bytes = originator_address.getAddress().getAddress();
+		byte[]	bytes = AddressUtils.getAddressBytes( originator_address );
 		
 		if ( skew_originator_bloom.contains( bytes)){
 		
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessController.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessController.java
index ca28deb..5c83a83 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessController.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessController.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessControllerFactory.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessControllerFactory.java
index fa3b9ce..d27e4e8 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessControllerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessControllerFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessControllerStats.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessControllerStats.java
index 086cc1f..e874fed 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessControllerStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessControllerStats.java
@@ -2,20 +2,19 @@
  * Created on Apr 3, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessRequest.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessRequest.java
index 2c67431..4f45804 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessRequest.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessRequestListener.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessRequestListener.java
index 901dd9e..ced5812 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessRequestListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/DiskAccessRequestListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessControllerImpl.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessControllerImpl.java
index 4b228a1..313f431 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessControllerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessControllerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessControllerInstance.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessControllerInstance.java
index c3cac74..8d9b4a6 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessControllerInstance.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessControllerInstance.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessRequestImpl.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessRequestImpl.java
index 1630512..f00bd02 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessRequestImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/access/impl/DiskAccessRequestImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFile.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFile.java
index 868719f..e7764dc 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFile.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFile.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManager.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManager.java
index 544c68b..a3d2350 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerException.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerException.java
index 2031654..5dfe2a0 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerException.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerFactory.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerFactory.java
index 690ad0a..2958b33 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerStats.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerStats.java
index b766cbd..77e9a6a 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileManagerStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileOwner.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileOwner.java
index f560018..e4a6e11 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileOwner.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/CacheFileOwner.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheEntry.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheEntry.java
index de56ce5..8fbcedb 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheEntry.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheEntry.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerImpl.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerImpl.java
index 3d6a33d..1cd7e54 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerStatsImpl.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerStatsImpl.java
index 68068fe..493d572 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerStatsImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileManagerStatsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithCache.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithCache.java
index 17c963d..2dc916c 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithCache.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithCache.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCache.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCache.java
index 5484850..53b94fa 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCache.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCache.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCacheMT.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCacheMT.java
index 3423eae..bead032 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCacheMT.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/cache/impl/CacheFileWithoutCacheMT.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 27, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFile.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFile.java
index 18f5b9d..4f8d6db 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFile.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFile.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManager.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManager.java
index 046e9fa..d7be19b 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManagerException.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManagerException.java
index 5ab7966..6ac197e 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManagerException.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManagerException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManagerFactory.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManagerFactory.java
index bae3452..4b0963d 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManagerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileManagerFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileOwner.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileOwner.java
index ae2120f..26d1eea 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileOwner.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/FMFileOwner.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccess.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccess.java
index 872ca85..2d51b58 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccess.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccess.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessCompact.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessCompact.java
index 499146b..042eecc 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessCompact.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessCompact.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessController.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessController.java
index c4a1e7d..676c2da 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessController.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessController.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessLinear.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessLinear.java
index 7806662..1928815 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessLinear.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessLinear.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessPieceReorderer.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessPieceReorderer.java
index cf81e56..5c4a081 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessPieceReorderer.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileAccessPieceReorderer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileImpl.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileImpl.java
index 46d0de7..1293a4c 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -1049,9 +1050,8 @@ FMFileImpl
 			created_dirs_leaf	= target;
 			created_dirs		= new ArrayList();
 			
-			if (FileUtil.mkdirs(parent)){
+			if ( FileUtil.mkdirs(parent)){
 			
-				created_dirs_leaf	= target;
 				created_dirs		= new_dirs;
 
 				/*
@@ -1061,7 +1061,25 @@ FMFileImpl
 				}
 				*/
 			}else{
-        		throw( new FMFileManagerException( "Failed to create parent directory '" + parent + "'"));	
+					// had some reports of this exception being thrown when starting a torrent
+					// double check in case there's some parallel creation being triggered somehow
+				
+				try{
+					Thread.sleep( RandomUtils.nextInt( 1000 ));
+					
+				}catch( Throwable e ){
+				}
+				
+				FileUtil.mkdirs( parent );
+				
+				if ( parent.isDirectory()){
+        		
+					created_dirs		= new_dirs;
+					
+				}else{
+					
+					throw( new FMFileManagerException( "Failed to create parent directory '" + parent + "'"));
+				}
         	}
         }
 	}
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileLimited.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileLimited.java
index 0753a23..af0d43d 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileLimited.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileLimited.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileManagerImpl.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileManagerImpl.java
index 6953fea..7be2627 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileManagerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileTestImpl.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileTestImpl.java
index be25deb..68c92ea 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileTestImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileTestImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Oct-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileUnlimited.java b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileUnlimited.java
index 9f3440a..8b7a069 100644
--- a/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileUnlimited.java
+++ b/azureus2/src/com/aelitis/azureus/core/diskmanager/file/impl/FMFileUnlimited.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectedInfo.java b/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectedInfo.java
index 7eeb6d4..c67396a 100644
--- a/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectedInfo.java
+++ b/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectedInfo.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 26, 2009 5:34:26 PM
- * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.drivedetector;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectedListener.java b/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectedListener.java
index 7a8892d..8020698 100644
--- a/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectedListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectedListener.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 26, 2009 5:03:07 PM
- * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.drivedetector;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetector.java b/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetector.java
index 62d929e..d872e63 100644
--- a/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetector.java
+++ b/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetector.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 26, 2009 5:00:17 PM
- * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.drivedetector;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectorFactory.java b/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectorFactory.java
index 437acad..6dbf3bb 100644
--- a/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectorFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/drivedetector/DriveDetectorFactory.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 26, 2009 5:17:41 PM
- * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.drivedetector;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/drivedetector/impl/DriveDetectedInfoImpl.java b/azureus2/src/com/aelitis/azureus/core/drivedetector/impl/DriveDetectedInfoImpl.java
index bc7895c..fb89cd3 100644
--- a/azureus2/src/com/aelitis/azureus/core/drivedetector/impl/DriveDetectedInfoImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/drivedetector/impl/DriveDetectedInfoImpl.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 26, 2009 5:36:43 PM
- * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.drivedetector.impl;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/drivedetector/impl/DriveDetectorImpl.java b/azureus2/src/com/aelitis/azureus/core/drivedetector/impl/DriveDetectorImpl.java
index 7b073a4..b1cacf6 100644
--- a/azureus2/src/com/aelitis/azureus/core/drivedetector/impl/DriveDetectorImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/drivedetector/impl/DriveDetectorImpl.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 26, 2009 5:18:54 PM
- * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.drivedetector.impl;
 
@@ -42,6 +39,8 @@ public class DriveDetectorImpl
 	
 	private Map<File, Map> mapDrives = new HashMap<File, Map>(1); 
 	
+	private AsyncDispatcher	dispatcher = new AsyncDispatcher( "DriveDetector" );
+	
 	public DriveDetectorImpl() {
 		AEDiagnostics.addEvidenceGenerator(this);
 	}
@@ -87,55 +86,75 @@ public class DriveDetectorImpl
 		listListeners.remove(l);
 	}
 
-	public void driveDetected(File location, Map info) {
-		location = normaliseFile( location );
-		mon_driveDetector.enter();
-		try {
-			if (!mapDrives.containsKey(location)) {
-				info.put("File", location);
-				mapDrives.put(location, info);
-			} else {
-				// already there, no trigger
-				return;
-			}
-			
-		} finally {
-			mon_driveDetector.exit();
-		}
+	public void driveDetected(final File _location, final Map info) {
 		
-		for (DriveDetectedListener l : listListeners) {
-			try {
-				l.driveDetected(new DriveDetectedInfoImpl(location, info));
- 			} catch (Throwable e) {
- 				Debug.out(e);
-			}
-		}
+		// seen the file-normalization hang on OSX (at least) and this is invoked on the SWT
+		// thread and thus borks the UI - make it async
+		
+		dispatcher.dispatch(
+			new AERunnable() {
+				
+				@Override
+				public void runSupport() 
+				{
+					File location = normaliseFile( _location );
+					mon_driveDetector.enter();
+					try {
+						if (!mapDrives.containsKey(location)) {
+							info.put("File", location);
+							mapDrives.put(location, info);
+						} else {
+							// already there, no trigger
+							return;
+						}
+						
+					} finally {
+						mon_driveDetector.exit();
+					}
+					
+					for (DriveDetectedListener l : listListeners) {
+						try {
+							l.driveDetected(new DriveDetectedInfoImpl(location, info));
+			 			} catch (Throwable e) {
+			 				Debug.out(e);
+						}
+					}
+				}
+			});
 	}
 
-	public void driveRemoved(File location) {
-		location = normaliseFile( location );
-		Map map;
-		mon_driveDetector.enter();
-		try {
-			map = mapDrives.remove(location);
-			if (map == null) {
-				// not there, no trigger
-				return;
-			}
-		} finally {
-			mon_driveDetector.exit();
-		}
-		
-		for (DriveDetectedListener l : listListeners) {
-			try {
-				l.driveRemoved(new DriveDetectedInfoImpl(location, map));
-			} catch (Throwable e) {
-				Debug.out(e);
-			}
-		}
+	public void driveRemoved(final File _location) {
+		dispatcher.dispatch(
+				new AERunnable() {
+					
+					@Override
+					public void runSupport() 
+					{
+						File location = normaliseFile( _location );
+						Map map;
+						mon_driveDetector.enter();
+						try {
+							map = mapDrives.remove(location);
+							if (map == null) {
+								// not there, no trigger
+								return;
+							}
+						} finally {
+							mon_driveDetector.exit();
+						}
+						
+						for (DriveDetectedListener l : listListeners) {
+							try {
+								l.driveRemoved(new DriveDetectedInfoImpl(location, map));
+							} catch (Throwable e) {
+								Debug.out(e);
+							}
+						}
+					}
+				});
 	}
 	
-	protected File
+	private File
 	normaliseFile(
 		File		f )
 	{
diff --git a/azureus2/src/com/aelitis/azureus/core/helpers/TorrentFolderWatcher.java b/azureus2/src/com/aelitis/azureus/core/helpers/TorrentFolderWatcher.java
index 91d6e2d..e1d6f9b 100644
--- a/azureus2/src/com/aelitis/azureus/core/helpers/TorrentFolderWatcher.java
+++ b/azureus2/src/com/aelitis/azureus/core/helpers/TorrentFolderWatcher.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 25, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/impl/AzureusCoreImpl.java b/azureus2/src/com/aelitis/azureus/core/impl/AzureusCoreImpl.java
index 2bd6df0..feb6897 100644
--- a/azureus2/src/com/aelitis/azureus/core/impl/AzureusCoreImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/impl/AzureusCoreImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.
  *
  */
 
@@ -206,7 +203,7 @@ AzureusCoreImpl
 
 	private AzureusCoreOperation	initialisation_op = createOperation( AzureusCoreOperation.OP_INITIALISATION );
 	
-	public static boolean SUPPRESS_CLASSLOADER_ERRORS = false;
+	public static boolean SUPPRESS_CLASSLOADER_ERRORS = true;
 	
 	private boolean ca_shutdown_computer_after_stop	= false;
 	private long	ca_last_time_downloading 		= -1;
@@ -1457,6 +1454,8 @@ AzureusCoreImpl
 					
 						Debug.out( "Shutdown blocked, force exiting" );
 						
+						stopping_sem.releaseForever();
+						
 						SESecurityManager.exitVM(0);
 					}
 					
@@ -2226,9 +2225,16 @@ AzureusCoreImpl
 			
 			if ( manager.getDownloadState().getFlag( DownloadManagerState.FLAG_METADATA_DOWNLOAD )){
 				
+					// we want this to complete before considering actions
+				
 				return;
 			}
 			
+			if ( manager.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )){
+				
+				continue;	// don't count these as interesting as the user isn't directly interested in them
+			}
+			
 			int state = manager.getState();
 			
 			if ( state == DownloadManager.STATE_FINISHING ){
@@ -2614,6 +2620,11 @@ AzureusCoreImpl
 		AzureusCoreLifecycleListener	l )
 	{
 		lifecycle_listeners.add(l);
+		
+		if ( global_manager != null ){
+			
+			l.componentCreated( this, global_manager );
+		}
 	}
 	
 	public void
diff --git a/azureus2/src/com/aelitis/azureus/core/impl/AzureusCoreSingleInstanceClient.java b/azureus2/src/com/aelitis/azureus/core/impl/AzureusCoreSingleInstanceClient.java
index 26c5fd8..14cca73 100644
--- a/azureus2/src/com/aelitis/azureus/core/impl/AzureusCoreSingleInstanceClient.java
+++ b/azureus2/src/com/aelitis/azureus/core/impl/AzureusCoreSingleInstanceClient.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Sep-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstance.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstance.java
index 40b27d8..efa7f44 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstance.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstance.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManager.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManager.java
index 398e0f1..6b42aa0 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerAdapter.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerAdapter.java
index 206fa77..08760d9 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerAdapter.java
@@ -2,20 +2,19 @@
  * Created on May 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerFactory.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerFactory.java
index bf8e33e..c98548b 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerListener.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerListener.java
index e39898c..45c103c 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceManagerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceTracked.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceTracked.java
index ca39050..2feb3f2 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceTracked.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/AZInstanceTracked.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZInstanceImpl.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZInstanceImpl.java
index a6f1a59..6a96d10 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZInstanceImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZInstanceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZInstanceManagerImpl.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZInstanceManagerImpl.java
index 82185f2..85ea328 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZInstanceManagerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZInstanceManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZMyInstanceImpl.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZMyInstanceImpl.java
index 843855d..ed4fba0 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZMyInstanceImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZMyInstanceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZOtherInstanceImpl.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZOtherInstanceImpl.java
index e3a707e..15c21e7 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZOtherInstanceImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZOtherInstanceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZPortClashHandler.java b/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZPortClashHandler.java
index 4bc2952..2e06a77 100644
--- a/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZPortClashHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/instancemanager/impl/AZPortClashHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/lws/LWSDiskManager.java b/azureus2/src/com/aelitis/azureus/core/lws/LWSDiskManager.java
index 803c01b..0bd89a1 100644
--- a/azureus2/src/com/aelitis/azureus/core/lws/LWSDiskManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/lws/LWSDiskManager.java
@@ -2,20 +2,19 @@
  * Created on Jul 16, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/lws/LWSDiskManagerState.java b/azureus2/src/com/aelitis/azureus/core/lws/LWSDiskManagerState.java
index 2e6eba6..b689b1b 100644
--- a/azureus2/src/com/aelitis/azureus/core/lws/LWSDiskManagerState.java
+++ b/azureus2/src/com/aelitis/azureus/core/lws/LWSDiskManagerState.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/lws/LWSDownload.java b/azureus2/src/com/aelitis/azureus/core/lws/LWSDownload.java
index a8668dd..92755fb 100644
--- a/azureus2/src/com/aelitis/azureus/core/lws/LWSDownload.java
+++ b/azureus2/src/com/aelitis/azureus/core/lws/LWSDownload.java
@@ -2,20 +2,19 @@
  * Created on Jul 16, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -25,9 +24,11 @@ import java.io.File;
 import java.net.URL;
 import java.util.*;
 
-
+import org.gudy.azureus2.core3.peer.PEPeerSource;
 import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabase;
 import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.plugins.download.Download;
 import org.gudy.azureus2.plugins.download.DownloadActivationEvent;
@@ -52,6 +53,7 @@ import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
 import org.gudy.azureus2.plugins.torrent.TorrentManager;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.ddb.DDBaseImpl;
 import org.gudy.azureus2.pluginsimpl.local.download.DownloadAnnounceResultImpl;
 
 
@@ -186,13 +188,13 @@ LWSDownload
 	getFlag(
 		long		flag )
 	{
-		return( false );
+		return( flag ==  Download.FLAG_LIGHT_WEIGHT );
 	}
 	
 	public long 
 	getFlags() 
 	{
-		return 0;
+		return( Download.FLAG_LIGHT_WEIGHT );
 	}
 	
 	public int
@@ -373,11 +375,11 @@ LWSDownload
 
 		if ( attribute == tm.getAttribute( TorrentAttribute.TA_NETWORKS )){
 			
-			return( new String[]{ "Public" });
+			return( new String[]{ AENetworkClassifier.AT_PUBLIC });
 			
 		}else if ( attribute == tm.getAttribute( TorrentAttribute.TA_PEER_SOURCES )){
 			
-			return( new String[]{ "DHT" });
+			return( new String[]{ PEPeerSource.PS_DHT });
 		}
 		
 		return( null );
@@ -933,6 +935,12 @@ LWSDownload
 		throw( new DownloadException( "Not Supported" ));
 	}
 	
+	public List<DistributedDatabase>
+	getDistributedDatabases()
+	{
+		return( DDBaseImpl.getDDBs( this ));
+	}
+	
 	public byte[]
 	getTorrentHash()
 	{
@@ -958,4 +966,9 @@ LWSDownload
 	{
 		Debug.out( "Not Supported" );
 	}
+
+	// @see org.gudy.azureus2.plugins.download.Download#getPrimaryFile()
+	public DiskManagerFileInfo getPrimaryFile() {
+		return null;
+	}
 }
\ No newline at end of file
diff --git a/azureus2/src/com/aelitis/azureus/core/lws/LWSPeerManagerAdapter.java b/azureus2/src/com/aelitis/azureus/core/lws/LWSPeerManagerAdapter.java
index a1e8fee..82f5f5d 100644
--- a/azureus2/src/com/aelitis/azureus/core/lws/LWSPeerManagerAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/lws/LWSPeerManagerAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -33,6 +30,7 @@ import org.gudy.azureus2.core3.peer.PEPeer;
 import org.gudy.azureus2.core3.peer.PEPeerManagerAdapter;
 import org.gudy.azureus2.core3.peer.PEPiece;
 import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.Debug;
 
 import com.aelitis.azureus.core.networkmanager.NetworkManager;
@@ -45,6 +43,8 @@ LWSPeerManagerAdapter
 	extends 	LogRelation
 	implements 	PEPeerManagerAdapter
 {
+	private final static String[]	enabled_networks = { AENetworkClassifier.AT_PUBLIC };
+	
 	private LightWeightSeed			lws;
 	
 	private PeerManagerRegistration	peer_manager_registration;
@@ -147,7 +147,13 @@ LWSPeerManagerAdapter
 	isNetworkEnabled(
 		String	network )
 	{
-		return( true );
+		return( network == AENetworkClassifier.AT_PUBLIC );
+	}
+	
+	public String[]
+	getEnabledNetworks()
+	{
+		return( enabled_networks );
 	}
 	
 	public int 
diff --git a/azureus2/src/com/aelitis/azureus/core/lws/LWSTorrent.java b/azureus2/src/com/aelitis/azureus/core/lws/LWSTorrent.java
index 84e3ea7..6b9045d 100644
--- a/azureus2/src/com/aelitis/azureus/core/lws/LWSTorrent.java
+++ b/azureus2/src/com/aelitis/azureus/core/lws/LWSTorrent.java
@@ -2,20 +2,19 @@
  * Created on Jul 16, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeed.java b/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeed.java
index f098e53..7d32990 100644
--- a/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeed.java
+++ b/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeed.java
@@ -2,20 +2,19 @@
  * Created on Jul 16, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -36,6 +35,7 @@ import org.gudy.azureus2.core3.peer.PEPeer;
 import org.gudy.azureus2.core3.peer.PEPeerManager;
 import org.gudy.azureus2.core3.peer.PEPeerManagerFactory;
 import org.gudy.azureus2.core3.peer.PEPeerManagerListener;
+import org.gudy.azureus2.core3.peer.PEPeerManagerListenerAdapter;
 import org.gudy.azureus2.core3.peer.PEPiece;
 import org.gudy.azureus2.core3.peer.util.PeerUtils;
 import org.gudy.azureus2.core3.torrent.TOTorrent;
@@ -387,7 +387,7 @@ LightWeightSeed
 								disk_manager );
 	
 				peer_manager.addListener(
-					new PEPeerManagerListener()
+					new PEPeerManagerListenerAdapter()
 					{
 						public void 
 						peerAdded( 
@@ -405,41 +405,6 @@ LightWeightSeed
 						{
 							last_activity_time = SystemTime.getMonotonousTime();
 						}
-						
-						public void 
-						peerDiscovered(
-							PEPeerManager manager,
-							PeerItem peer, 
-							PEPeer finder) 
-						{
-						}
-						  
-						public void 
-						pieceAdded( 
-							PEPeerManager 	manager, 
-							PEPiece 		peice, 
-							PEPeer 			for_peer )
-						{
-						}
-						  
-						public void 
-						pieceRemoved( 
-							PEPeerManager 	manager, 
-							PEPiece 		peice )
-						{
-						}
-
-						public void 
-						peerSentBadData(
-							PEPeerManager 	manager,
-							PEPeer 			peer, 
-							int 			pieceNumber) 
-						{							
-						}
-						public void
-						destroyed()
-						{
-						}
 					});
 				
 				peer_manager.start();
diff --git a/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeedAdapter.java b/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeedAdapter.java
index a581e4c..f9f2189 100644
--- a/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeedAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeedAdapter.java
@@ -2,20 +2,19 @@
  * Created on Jul 16, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeedManager.java b/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeedManager.java
index 84f2218..42d4fae 100644
--- a/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeedManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/lws/LightWeightSeedManager.java
@@ -2,20 +2,19 @@
  * Created on Jul 16, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/nat/NATTraversal.java b/azureus2/src/com/aelitis/azureus/core/nat/NATTraversal.java
index 3cfb908..ad7212f 100644
--- a/azureus2/src/com/aelitis/azureus/core/nat/NATTraversal.java
+++ b/azureus2/src/com/aelitis/azureus/core/nat/NATTraversal.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalException.java b/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalException.java
index 7fae4c0..679bf74 100644
--- a/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalException.java
+++ b/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 9 Aug 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalHandler.java b/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalHandler.java
index 20354fc..3f1fc4d 100644
--- a/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalObserver.java b/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalObserver.java
index b3784ce..835b2ef 100644
--- a/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalObserver.java
+++ b/azureus2/src/com/aelitis/azureus/core/nat/NATTraversalObserver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/nat/NATTraverser.java b/azureus2/src/com/aelitis/azureus/core/nat/NATTraverser.java
index a08b86e..8a1c909 100644
--- a/azureus2/src/com/aelitis/azureus/core/nat/NATTraverser.java
+++ b/azureus2/src/com/aelitis/azureus/core/nat/NATTraverser.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/ConnectionAttempt.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/ConnectionAttempt.java
index 0821c09..9047451 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/ConnectionAttempt.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/ConnectionAttempt.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/ConnectionEndpoint.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/ConnectionEndpoint.java
index e7c16d9..85f14da 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/ConnectionEndpoint.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/ConnectionEndpoint.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -226,6 +223,13 @@ ConnectionEndpoint
 				    		listener.connectFailure(failure_msg);
 				    	}
 				    }
+				    
+			    	public Object 
+					getConnectionProperty(
+						String property_name)
+					{
+			    		return( listener.getConnectionProperty( property_name ));
+					}
 				};
 			
 			boolean	ok = true;
@@ -426,5 +430,12 @@ ConnectionEndpoint
 			
 			listener.connectFailure( failure_msg );
 		}
+		
+		public Object 
+		getConnectionProperty(
+			String property_name)
+		{
+			return( listener.getConnectionProperty( property_name ));
+		}
 	}	
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/EventWaiter.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/EventWaiter.java
index 497b57a..027846a 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/EventWaiter.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/EventWaiter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/IncomingMessageQueue.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/IncomingMessageQueue.java
index 15ef9ed..f724332 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/IncomingMessageQueue.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/IncomingMessageQueue.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 17, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/LimitedRateGroup.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/LimitedRateGroup.java
index 9dab087..8d02f7a 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/LimitedRateGroup.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/LimitedRateGroup.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 9, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnection.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnection.java
index 7eba113..4b9b175 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnection.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 21, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -120,6 +117,8 @@ NetworkConnection
      */
     public void exceptionThrown( Throwable error );
     
+    public Object getConnectionProperty( String property_name);
+    
     public String
     getDescription();
   }
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionBase.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionBase.java
index c6917ea..2d92e7d 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionBase.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionBase.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionFactory.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionFactory.java
index 71632fa..bb25846 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 21, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,44 +14,96 @@
  * 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.networkmanager;
 
+import org.gudy.azureus2.core3.util.Debug;
+
 import com.aelitis.azureus.core.networkmanager.impl.NetworkConnectionImpl;
 import com.aelitis.azureus.core.peermanager.messaging.MessageStreamDecoder;
 import com.aelitis.azureus.core.peermanager.messaging.MessageStreamEncoder;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
 
 /**
  *
  */
-public class NetworkConnectionFactory {
-  
-  /**
-   * Create an OUTGOING connection.
-   * @param remote_address
-   * @param encoder
-   * @param decoder
-   * @return outbound connection
-   */
-  protected static NetworkConnection create( ConnectionEndpoint	target, MessageStreamEncoder encoder, MessageStreamDecoder decoder, boolean connect_with_crypto, boolean allow_fallback, byte[][] shared_secrets ) {
-    return new NetworkConnectionImpl( target, encoder, decoder, connect_with_crypto, allow_fallback, shared_secrets );
-  }
+public class 
+NetworkConnectionFactory 
+{
+	private static CopyOnWriteList<NetworkConnectionFactoryListener>	listeners = new CopyOnWriteList<NetworkConnectionFactory.NetworkConnectionFactoryListener>();
+	
+	/**
+	 * Create an OUTGOING connection.
+	 * @param remote_address
+	 * @param encoder
+	 * @param decoder
+	 * @return outbound connection
+	 */
+	protected static NetworkConnection create( ConnectionEndpoint	target, MessageStreamEncoder encoder, MessageStreamDecoder decoder, boolean connect_with_crypto, boolean allow_fallback, byte[][] shared_secrets ) {
+		NetworkConnection connection = new NetworkConnectionImpl( target, encoder, decoder, connect_with_crypto, allow_fallback, shared_secrets );
+		
+		for ( NetworkConnectionFactoryListener listener: listeners ){
+			
+			try{
+				listener.connectionCreated( connection );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+		
+		return( connection );
+	}
+
 
-  
-  /**
-   * Create an INCOMING connection.
-   * @param remote_channel
-   * @param data_already_read
-   * @param encoder
-   * @param decoder
-   * @return inbound connection
-   */
-  protected static NetworkConnection create( Transport transport, MessageStreamEncoder encoder, MessageStreamDecoder decoder ) {
-    return new NetworkConnectionImpl( transport, encoder, decoder );
-  }
+	/**
+	 * Create an INCOMING connection.
+	 * @param remote_channel
+	 * @param data_already_read
+	 * @param encoder
+	 * @param decoder
+	 * @return inbound connection
+	 */
+	protected static NetworkConnection create( Transport transport, MessageStreamEncoder encoder, MessageStreamDecoder decoder ) {
+		
+		NetworkConnection connection = new NetworkConnectionImpl( transport, encoder, decoder );
+		
+		for ( NetworkConnectionFactoryListener listener: listeners ){
+			
+			try{
+				listener.connectionCreated( connection );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+		
+		return( connection );
+	}
+	
+	public static void
+	addListener(
+		NetworkConnectionFactoryListener		l )
+	{
+		listeners.add( l );
+	}
+	
+	public static void
+	removeListener(
+		NetworkConnectionFactoryListener		l )
+	{
+		listeners.remove( l );
+	}
+	
+	public interface
+	NetworkConnectionFactoryListener
+	{
+		public void
+		connectionCreated(
+			NetworkConnection		connection );
+	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionHelper.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionHelper.java
index e52e8d0..dd369c8 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionHelper.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkConnectionHelper.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 6, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkManager.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkManager.java
index 2234e42..27f218c 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/NetworkManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 29, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -32,6 +29,7 @@ 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.GlobalManagerListener;
+import org.gudy.azureus2.core3.util.AddressUtils;
 import org.gudy.azureus2.core3.util.Debug;
 
 import com.aelitis.azureus.core.AzureusCore;
@@ -512,11 +510,15 @@ public class NetworkManager {
   startTransferProcessing( 
 	NetworkConnectionBase 	peer_connection )
   {
-  	if( peer_connection.isLANLocal() && lan_rate_enabled ) {
+  	if (	lan_rate_enabled && 	
+  			( 	peer_connection.isLANLocal() || 
+  				AddressUtils.applyLANRateLimits( peer_connection.getEndpoint().getNotionalAddress()))){
+  		
   		lan_upload_processor.registerPeerConnection( peer_connection, true );
   		lan_download_processor.registerPeerConnection( peer_connection, false );
-  	}
-  	else {
+  		
+  	}else {
+  		
   		upload_processor.registerPeerConnection( peer_connection, true );
   		download_processor.registerPeerConnection( peer_connection, false );
   	}
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/OutgoingMessageQueue.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/OutgoingMessageQueue.java
index a42fb27..5cb0c87 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/OutgoingMessageQueue.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/OutgoingMessageQueue.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 8, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpoint.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpoint.java
index ef83c99..185f794 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpoint.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpoint.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpointFactory.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpointFactory.java
index 366eb0a..75b292f 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpointFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpointFactory.java
@@ -2,20 +2,19 @@
  * Created on Oct 14, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpointHandler.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpointHandler.java
index d82cac9..48d1bc6 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpointHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolEndpointHandler.java
@@ -2,20 +2,19 @@
  * Created on Oct 14, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolStartpoint.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolStartpoint.java
index e25d0e7..7d37a10 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolStartpoint.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/ProtocolStartpoint.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/RateHandler.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/RateHandler.java
index f7cf815..0fd75a7 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/RateHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/RateHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 6, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/RawMessage.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/RawMessage.java
index ecc1142..1490f57 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/RawMessage.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/RawMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/Transport.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/Transport.java
index f03c94c..2d3cddd 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/Transport.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/Transport.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 8, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -166,5 +163,9 @@ Transport
      * @param failure_msg failure reason
      */
     public void connectFailure( Throwable failure_msg );
+    
+    public Object
+    getConnectionProperty(
+    	String		property_name );
   }
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportBase.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportBase.java
index f2b6ca7..8fb1a27 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportBase.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportBase.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportEndpoint.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportEndpoint.java
index f4beaa6..beaa8da 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportEndpoint.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportEndpoint.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportStartpoint.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportStartpoint.java
index c46e6ef..560a4b1 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportStartpoint.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/TransportStartpoint.java
@@ -2,20 +2,19 @@
  * Created on Nov 8, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualChannelSelector.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualChannelSelector.java
index a29720f..46352d3 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualChannelSelector.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualChannelSelector.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jun 5, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualServerChannelSelector.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualServerChannelSelector.java
index fb0aaf4..9428242 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualServerChannelSelector.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualServerChannelSelector.java
@@ -1,7 +1,7 @@
 /*
  * Created on Dec 4, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -42,6 +39,8 @@ public interface VirtualServerChannelSelector {
  
   public InetAddress getBoundToAddress();
  
+  public int getPort();
+  
   public long getTimeOfLastAccept();
   
   /**
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualServerChannelSelectorFactory.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualServerChannelSelectorFactory.java
index f5c9634..ca6727b 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualServerChannelSelectorFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/VirtualServerChannelSelectorFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Feb-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdmin.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdmin.java
index dc48c6c..c72437b 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdmin.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdmin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -225,8 +222,17 @@ NetworkAdmin
 	public abstract InetAddress
 	getDefaultPublicAddress();
 	
-	public abstract InetAddress getDefaultPublicAddressV6();
+	public abstract InetAddress
+	getDefaultPublicAddress(
+		boolean	peek );
+	
+	public abstract InetAddress 
+	getDefaultPublicAddressV6();
 	
+	public abstract InetAddress 
+	getDefaultPublicAddressV6(
+		boolean	peek );
+
 	public abstract boolean	hasDHTIPV6();
 	
 	public abstract void
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminASN.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminASN.java
index b0b1424..76a8513 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminASN.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminASN.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminASNListener.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminASNListener.java
index 7482a95..6230bde 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminASNListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminASNListener.java
@@ -2,20 +2,19 @@
  * Created on Dec 24, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminException.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminException.java
index 1ca46d8..c822662 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminException.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminHTTPProxy.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminHTTPProxy.java
index 7942171..c775245 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminHTTPProxy.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminHTTPProxy.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNATDevice.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNATDevice.java
index 7dbad64..0beb587 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNATDevice.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNATDevice.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNetworkInterface.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNetworkInterface.java
index 6e28649..70a5435 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNetworkInterface.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNetworkInterface.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNetworkInterfaceAddress.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNetworkInterfaceAddress.java
index 2ceb7da..f2ddeff 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNetworkInterfaceAddress.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNetworkInterfaceAddress.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNode.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNode.java
index f2ec4e2..7d9b8b5 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNode.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminNode.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminProgressListener.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminProgressListener.java
index 29177a4..ce31ca4 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminProgressListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminProgressListener.java
@@ -2,20 +2,19 @@
  * Created on Feb 1, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminPropertyChangeListener.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminPropertyChangeListener.java
index 1e143f4..3feca12 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminPropertyChangeListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminPropertyChangeListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminProtocol.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminProtocol.java
index b8781d0..0c38331 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminProtocol.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminProtocol.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminRouteListener.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminRouteListener.java
index 420d593..ea6dada 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminRouteListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminRouteListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminRoutesListener.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminRoutesListener.java
index f7c1a87..45f5e0b 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminRoutesListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminRoutesListener.java
@@ -2,20 +2,19 @@
  * Created on Jan 30, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSocksProxy.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSocksProxy.java
index 8a8a4cc..36e9588 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSocksProxy.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSocksProxy.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduledTest.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduledTest.java
index ca8040e..6797a24 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduledTest.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduledTest.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 1, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduledTestListener.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduledTestListener.java
index e6d84a2..6d5c35c 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduledTestListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduledTestListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 1, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduler.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduler.java
index 08062d2..6040c37 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduler.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTestScheduler.java
@@ -1,7 +1,7 @@
 /**
 * Created on Apr 17, 2007
 * Created by Alan Snyder
-* Copyright (C) 2007 Aelitis, All Rights Reserved.
+* Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
 * 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.
-*
 */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTester.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTester.java
index 8d1384d..555bd0b 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTester.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTester.java
@@ -1,7 +1,7 @@
 /**
 * Created on Apr 17, 2007
 * Created by Alan Snyder
-* Copyright (C) 2007 Aelitis, All Rights Reserved.
+* Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
 * 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.
-*
 */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTesterListener.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTesterListener.java
index 2ac6219..031772e 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTesterListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTesterListener.java
@@ -1,7 +1,7 @@
 /**
 * Created on Apr 17, 2007
 * Created by Alan Snyder
-* Copyright (C) 2007 Aelitis, All Rights Reserved.
+* Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
 * 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.networkmanager.admin;
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTesterResult.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTesterResult.java
index 60b9724..9bdeae2 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTesterResult.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/NetworkAdminSpeedTesterResult.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 1, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminASNImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminASNImpl.java
index bbbbb50..5c8f10f 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminASNImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminASNImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 11, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminASNLookupImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminASNLookupImpl.java
index c2be710..c7e9591 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminASNLookupImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminASNLookupImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminHTTPProxyImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminHTTPProxyImpl.java
index f526b17..b069cb8 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminHTTPProxyImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminHTTPProxyImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminHTTPTester.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminHTTPTester.java
index 3b594de..48deb38 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminHTTPTester.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminHTTPTester.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminImpl.java
index 162189c..fb875cb 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -254,6 +251,8 @@ NetworkAdminImpl
 		
 		AEDiagnostics.addEvidenceGenerator( this );
 		
+		checkDNSSPI();
+		
 		AzureusCoreFactory.addCoreRunningListener(
 			new AzureusCoreRunningListener()
 			{
@@ -274,6 +273,41 @@ NetworkAdminImpl
 		initialised = true;
 	}
 	
+	private void
+	checkDNSSPI()
+	{
+		String	error_str	= null;
+		
+		try{
+			InetAddress ia = InetAddress.getByName( "dns.test.client.vuze.com" );
+			
+			if ( ia.isLoopbackAddress()){
+				
+				// looks good!
+				
+			}else{
+				
+				error_str = "Loopback address expected, got " + ia;
+			}
+		}catch( UnknownHostException e ){
+			
+			error_str = "DNS SPI not loaded";
+			
+		}catch( Throwable e ){
+			
+			error_str = "Test lookup failed: " + Debug.getNestedExceptionMessage( e );
+		}
+		
+		if ( error_str != null ){
+			
+			Logger.log(					
+				new LogAlert(
+					true,
+					LogAlert.AT_WARNING,
+					MessageText.getString( "network.admin.dns.spi.fail", new String[]{ error_str })));
+		}
+	}
+	
 	protected void
 	setIPv6Enabled(
 		boolean enabled )
@@ -700,7 +734,7 @@ addressLoop:
 					new LogAlert(
 						true,
 						LogAlert.AT_WARNING,
-						"'Enforce IP Bindings' is selected but no bindings have been specified\n\nSee Tools->Options->Connection->Advanced Network Settings" ));
+						MessageText.getString( "network.admin.bind.enforce.fail" )));
 			}
 		}
 		
@@ -1344,50 +1378,80 @@ addressLoop:
 	private static InetAddress[]		gdpa_lock = { null };
 	private static AESemaphore			gdpa_sem;
 	private static long					gdpa_last_fail;
+	private static long					gdpa_last_lookup;
+	private static AESemaphore			gdpa_initial_sem = new AESemaphore( "gdpa:init" );
 	
 	public InetAddress
 	getDefaultPublicAddress()
 	{
+		return( getDefaultPublicAddress( false ));
+	}
+	
+	public InetAddress
+	getDefaultPublicAddress(
+		boolean		peek )
+	{
 		final AESemaphore	sem;
 				
 		synchronized( gdpa_lock ){
+				
+			long	now = SystemTime.getMonotonousTime();
 						
 			if ( gdpa_sem == null ){
+			
+				boolean	do_lookup = true;
 				
-				gdpa_sem = sem = new AESemaphore( "getDefaultPublicAddress");
-				
-				new AEThread2( "getDefaultPublicAddress" )
-				{
-					public void
-					run()
-					{
-						InetAddress address = null;
+				if ( peek ){
+					
+					if ( gdpa_last_lookup != 0 && now - gdpa_last_lookup <= 60*1000 ){
 						
-						try{
-							Utilities utils = PluginInitializer.getDefaultInterface().getUtilities();
-							
-							address = utils.getPublicAddress();
+						do_lookup = false;
+					}
+				}
+
+				if ( do_lookup ){
+										
+					gdpa_last_lookup = now;
+					
+					gdpa_sem = sem = new AESemaphore( "getDefaultPublicAddress");
+									
+					new AEThread2( "getDefaultPublicAddress" )
+					{
+						public void
+						run()
+						{
+							InetAddress address = null;
 							
-							if ( address == null ){
+							try{
+								Utilities utils = PluginInitializer.getDefaultInterface().getUtilities();
 								
-								address = utils.getPublicAddress( true );
-							}
-						}catch( Throwable e ){
-							
-						}finally{
-							
-							synchronized( gdpa_lock ){
+								address = utils.getPublicAddress();
 								
-								gdpa_lock[0]	= address;	
-																
-								sem.releaseForever();
+								if ( address == null ){
+									
+									address = utils.getPublicAddress( true );
+								}
+							}catch( Throwable e ){
+								
+							}finally{
 								
-								gdpa_sem = null;
+								synchronized( gdpa_lock ){
+									
+									gdpa_lock[0]	= address;	
+																	
+									sem.releaseForever();
+									
+									gdpa_sem = null;
+									
+									gdpa_initial_sem.releaseForever();
+								}
 							}
 						}
-					}
-				}.start();
-				
+					}.start();
+				}else{
+					
+					sem = null;		// no lookup this time around - we're peeking
+				}
 			}else{
 				
 				sem = gdpa_sem;
@@ -1399,27 +1463,51 @@ addressLoop:
 			}
 		}
 
-			// in case things block - yes, they can do :(
-		
-		boolean	worked = sem.reserve( 10*1000 );
-		
-		synchronized( gdpa_lock ){
-				
-			if ( worked ){
+		if ( peek ){
+			
+				// we're doing a peek and don't want to wait
+			
+			gdpa_initial_sem.reserve( 10*1000 );
+			
+			synchronized( gdpa_lock ){
 				
-				gdpa_last_fail = 0;
+				return( gdpa_lock[0] );
+			}
+		}else{
+				// in case things block - yes, they can do :(
+			
+			boolean	worked = sem.reserve( 10*1000 );
+			
+			synchronized( gdpa_lock ){
+					
+				if ( worked ){
+					
+					gdpa_last_fail = 0;
+					
+				}else{
 				
-			}else{
+					gdpa_initial_sem.releaseForever();
+					
+					gdpa_last_fail = SystemTime.getMonotonousTime();
+				}
 				
-				gdpa_last_fail = SystemTime.getMonotonousTime();
+				return( gdpa_lock[0] );
 			}
-			
-			return( gdpa_lock[0] );
 		}
 	}
 	
 	@Override
-	public InetAddress getDefaultPublicAddressV6() {
+	public InetAddress 
+	getDefaultPublicAddressV6() 
+	{
+		return( getDefaultPublicAddressV6( false ));
+	}
+	
+	@Override
+	public InetAddress 
+	getDefaultPublicAddressV6(
+		boolean	peek ) 
+	{
 		if(!supportsIPv6)
 			return null;
 		
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATDeviceImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATDeviceImpl.java
index 07d4918..0ac79e8 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATDeviceImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATDeviceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPCodecs.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPCodecs.java
index 8270281..01562d5 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPCodecs.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPCodecs.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPReply.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPReply.java
index 8cf0b4f..0bc8d38 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPReply.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPReply.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPRequest.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPRequest.java
index 3ab4d56..a6781a9 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPRequest.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminNATUDPRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminProtocolImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminProtocolImpl.java
index 47fcb01..8bb7024 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminProtocolImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminProtocolImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminProtocolTester.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminProtocolTester.java
index 4e11e23..242f417 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminProtocolTester.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminProtocolTester.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSocksProxyImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSocksProxyImpl.java
index b2799ed..26b85d8 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSocksProxyImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSocksProxyImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestScheduledTestImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestScheduledTestImpl.java
index 01022eb..a4e3002 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestScheduledTestImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestScheduledTestImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 1, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestSchedulerImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestSchedulerImpl.java
index 915e7a1..966536c 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestSchedulerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTestSchedulerImpl.java
@@ -1,7 +1,7 @@
 /**
 * Created on Apr 17, 2007
 * Created by Alan Snyder
-* Copyright (C) 2007 Aelitis, All Rights Reserved.
+* Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
 * 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.
-*
 */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterBTImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterBTImpl.java
index 3267790..a98d603 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterBTImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterBTImpl.java
@@ -1,7 +1,7 @@
 /**
 * Created on Apr 17, 2007
 * Created by Alan Snyder
-* Copyright (C) 2007 Aelitis, All Rights Reserved.
+* Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
 * 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.networkmanager.admin.impl;
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterImpl.java
index 5ce5b86..475638d 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminSpeedTesterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 1, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminTCPTester.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminTCPTester.java
index f7bc0ab..9479efe 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminTCPTester.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminTCPTester.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminUDPTester.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminUDPTester.java
index 2e21e64..b1be534 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminUDPTester.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/NetworkAdminUDPTester.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/swt/NetworkAdminSWTImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/swt/NetworkAdminSWTImpl.java
index 1c264d4..feb9867 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/swt/NetworkAdminSWTImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/admin/impl/swt/NetworkAdminSWTImpl.java
@@ -2,20 +2,19 @@
  * Created on Aug 14, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -44,12 +43,12 @@ import com.aelitis.azureus.core.networkmanager.admin.impl.NetworkAdminImpl;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdater;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
 
 public class 
 NetworkAdminSWTImpl 
 {
-	private AzureusCore				core;
 	private NetworkAdminImpl		network_admin;
 	
 	private UISWTStatusEntry 	status;
@@ -69,7 +68,6 @@ NetworkAdminSWTImpl
 		AzureusCore				_core,
 		NetworkAdminImpl		_network_admin )
 	{
-		core			= _core;
 		network_admin	= _network_admin;
 		
 		final PluginInterface default_pi = PluginInitializer.getDefaultInterface();
@@ -194,7 +192,9 @@ NetworkAdminSWTImpl
 			
 													if ( uif != null ){
 			
-														uif.openView( UIFunctions.VIEW_CONFIG, "connection.advanced" );
+														uif.getMDI().showEntryByID(
+																MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+																"connection.advanced");
 													}
 												}
 											});
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucket.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucket.java
index 21cdc63..68df69f 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucket.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucket.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 26, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucketMT.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucketMT.java
index 03a38b3..b9f2a58 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucketMT.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucketMT.java
@@ -2,20 +2,19 @@
  * Created on Dec 1, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucketST.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucketST.java
index 81481b8..1ff45b9 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucketST.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ByteBucketST.java
@@ -2,20 +2,19 @@
  * Created on Dec 1, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/EntityHandler.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/EntityHandler.java
index d1310ee..091fffa 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/EntityHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/EntityHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 23, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/IncomingConnectionManager.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/IncomingConnectionManager.java
index d34b5bf..086f255 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/IncomingConnectionManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/IncomingConnectionManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/IncomingMessageQueueImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/IncomingMessageQueueImpl.java
index 76e3ffd..7b79ab2 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/IncomingMessageQueueImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/IncomingMessageQueueImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 17, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -134,7 +131,9 @@ public class IncomingMessageQueueImpl implements IncomingMessageQueue{
         
         for( int x=0; x < listeners_ref.size(); x++ ) {
           MessageQueueListener mql = (MessageQueueListener)listeners_ref.get( x );
-          handled = handled || mql.messageReceived( msg );
+          if ( mql.messageReceived( msg )){
+        	  handled = true;
+          }
         }
         
         if( !handled ) {
@@ -191,7 +190,9 @@ public class IncomingMessageQueueImpl implements IncomingMessageQueue{
     
     for( int x=0; x < listeners_ref.size(); x++ ) {
       MessageQueueListener mql = (MessageQueueListener)listeners_ref.get( x );
-      handled = handled || mql.messageReceived( message );
+      if ( mql.messageReceived( message )){
+    	  handled = true;
+      }
       
       if( message.getType() == Message.TYPE_DATA_PAYLOAD ) {
         mql.dataBytesReceived( size );
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/MultiPeerDownloader2.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/MultiPeerDownloader2.java
index 9036691..acf0861 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/MultiPeerDownloader2.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/MultiPeerDownloader2.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 22, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/MultiPeerUploader.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/MultiPeerUploader.java
index da2a3a3..4a050b1 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/MultiPeerUploader.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/MultiPeerUploader.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 28, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/NetworkConnectionImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/NetworkConnectionImpl.java
index 6771a2a..9d499b8 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/NetworkConnectionImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/NetworkConnectionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 29, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -31,7 +28,6 @@ import org.gudy.azureus2.core3.util.AddressUtils;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.LightHashMap;
 
-
 import com.aelitis.azureus.core.networkmanager.*;
 import com.aelitis.azureus.core.peermanager.messaging.MessageStreamDecoder;
 import com.aelitis.azureus.core.peermanager.messaging.MessageStreamEncoder;
@@ -176,6 +172,13 @@ NetworkConnectionImpl
 			        is_connected = false;
 			        connection_listener.connectFailure( failure_msg );
 			      }
+			      
+			    	public Object 
+					getConnectionProperty(
+						String property_name)
+					{
+			    		return( connection_listener.getConnectionProperty( property_name ));
+					}
 			    });
     
     if ( closed ){
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/NetworkManagerUtilities.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/NetworkManagerUtilities.java
index 247e577..0c77896 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/NetworkManagerUtilities.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/NetworkManagerUtilities.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 19, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/OutgoingMessageQueueImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/OutgoingMessageQueueImpl.java
index 1b1be8a..20a38c8 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/OutgoingMessageQueueImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/OutgoingMessageQueueImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 8, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoder.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoder.java
index 0e1035b..5e45b59 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderAdapter.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderAdapter.java
index 9d1e2c7..27b13a0 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderInitial.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderInitial.java
index 0781483..320d40e 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderInitial.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderInitial.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,21 +14,19 @@
  * 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.networkmanager.impl;
 
 import java.io.IOException;
+import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 
-
 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.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.AddressUtils;
 import org.gudy.azureus2.core3.util.SystemTime;
 
@@ -127,15 +125,21 @@ ProtocolDecoderInitial
 																		
 								if ( NetworkManager.REQUIRE_CRYPTO_HANDSHAKE && match == ProtocolDecoderAdapter.MATCH_CRYPTO_NO_AUTO_FALLBACK ){
 								
+									InetSocketAddress isa = transport.getAddress();
+									
 									if ( NetworkManager.INCOMING_HANDSHAKE_FALLBACK_ALLOWED ){
-										if (Logger.isEnabled())
-											Logger.log(new LogEvent(LOGID, "Incoming connection ["+ transport.getAddress() + "] is not encrypted but has been accepted as fallback is enabled" ));
-									}
-									else if( AddressUtils.isLANLocalAddress( transport.getAddress().getAddress().getHostAddress() ) == AddressUtils.LAN_LOCAL_YES ) {
-										if (Logger.isEnabled())
-											Logger.log(new LogEvent(LOGID, "Incoming connection ["+ transport.getAddress() + "] is not encrypted but has been accepted as lan-local" ));
-									}
-									else{										
+										if (Logger.isEnabled()){
+											Logger.log(new LogEvent(LOGID, "Incoming connection ["+ isa + "] is not encrypted but has been accepted as fallback is enabled" ));
+										}
+									}else if( AddressUtils.isLANLocalAddress( AddressUtils.getHostAddress( isa )) == AddressUtils.LAN_LOCAL_YES ) {
+										if (Logger.isEnabled()){
+											Logger.log(new LogEvent(LOGID, "Incoming connection ["+ isa + "] is not encrypted but has been accepted as lan-local" ));
+										}
+									}else if ( AENetworkClassifier.categoriseAddress( isa ) != AENetworkClassifier.AT_PUBLIC ){
+										if (Logger.isEnabled()){ 
+											Logger.log(new LogEvent(LOGID, "Incoming connection ["+ isa + "] is not encrypted but has been accepted as not a public network" ));
+										}
+									}else{										
 										throw( new IOException( "Crypto required but incoming connection has none" ));
 									}
 								}
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderPHE.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderPHE.java
index c5e7663..560d4ea 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderPHE.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ProtocolDecoderPHE.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -24,6 +21,7 @@ package com.aelitis.azureus.core.networkmanager.impl;
 
 import java.io.IOException;
 import java.math.BigInteger;
+import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 import java.security.KeyFactory;
 import java.security.KeyPair;
@@ -46,6 +44,7 @@ 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.AEMonitor;
+import org.gudy.azureus2.core3.util.AddressUtils;
 import org.gudy.azureus2.core3.util.ByteFormatter;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.HashWrapper;
@@ -1950,7 +1949,9 @@ ProtocolDecoderPHE
 			
 			if ( !outbound ){
 				
-				byte[]	address = transport.getAddress().getAddress().getAddress();
+				InetSocketAddress is_address = transport.getAddress();
+				
+				byte[]	address = AddressUtils.getAddressBytes( is_address );
 				
 				int	hit_count = generate_bloom.add( address );
 				
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/RateControlledEntity.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/RateControlledEntity.java
index c1368b3..85d397a 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/RateControlledEntity.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/RateControlledEntity.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 27, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/RawMessageImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/RawMessageImpl.java
index 6b4e1f8..ab50877 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/RawMessageImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/RawMessageImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 11, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ReadController.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ReadController.java
index 0389c40..79e52d8 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ReadController.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/ReadController.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 16, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/SinglePeerDownloader.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/SinglePeerDownloader.java
index 3187a13..dc027de 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/SinglePeerDownloader.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/SinglePeerDownloader.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 28, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/SinglePeerUploader.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/SinglePeerUploader.java
index 32459cd..b00496b 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/SinglePeerUploader.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/SinglePeerUploader.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 28, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransferProcessor.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransferProcessor.java
index 7809df0..2fc4a5c 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransferProcessor.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransferProcessor.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 7, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -359,93 +356,156 @@ public class TransferProcessor {
    * Upgrade the given connection to a high-speed transfer handler.
    * @param connection to upgrade
    */
-  public void upgradePeerConnection( final NetworkConnectionBase connection, int partition_id ) {
+  public void 
+  upgradePeerConnection( 
+	final NetworkConnectionBase 	connection, 
+	int 							partition_id ) 
+  {  
     ConnectionData connection_data = null;
     
-    try{ connections_mon.enter();
-      connection_data = (ConnectionData)connections.get( connection );
+    try{ 
+    	connections_mon.enter();
+      
+    	connection_data = (ConnectionData)connections.get( connection );
+    	
+    }finally{
+    	
+    	connections_mon.exit(); 
     }
-    finally{ connections_mon.exit(); }
     
-    if( connection_data != null && connection_data.state == ConnectionData.STATE_NORMAL ) {
+    if ( connection_data != null && connection_data.state == ConnectionData.STATE_NORMAL ){
+    	
       final ConnectionData conn_data = connection_data;
       
-      main_controller.upgradePeerConnection( connection, new RateHandler() {
-        public int getCurrentNumBytesAllowed() {          
-          // sync global rate
-          if( main_bucket.getRate() != max_rate.getRateLimitBytesPerSecond() ) {
-            main_bucket.setRate( max_rate.getRateLimitBytesPerSecond() );
-          }
-          
-          int allowed = main_bucket.getAvailableByteCount();
+      main_controller.upgradePeerConnection( 
+    		connection, 
+    		new RateHandler() 
+    		{
+    			public int 
+    			getCurrentNumBytesAllowed() 
+    			{          
+    					// sync global rate
 
-          // reserve bandwidth for the general pool
-          allowed -= connection.getMssSize();
-          
-          if ( allowed < 0 )allowed = 0;
-          
-          	// only apply group rates to non-lan local connections 
-          
-          if ( RATE_LIMIT_LAN_TOO || !( connection.isLANLocal() && NetworkManager.isLANRateEnabled())){
-	          // sync group rates
-	          
-	          try{
-		           for (int i=0;i<conn_data.group_datas.length;i++){
-		        	   
-		        	  LimitedRateGroup group = conn_data.groups[i];
-		        	  
-		     		  //boolean log = group.getName().contains("parg");
-
-			          int group_rate = NetworkManagerUtilities.getGroupRateLimit( conn_data.groups[i] );
-			          
-			          ByteBucket group_bucket = conn_data.group_datas[i].bucket;
-			          
-			          /*
-			          if ( log ){
-			        	  long now = SystemTime.getCurrentTime();
-			        	  if ( now - last_log > 500 ){
-			        		  last_log = now;
-			        		  System.out.println( "    " + group.getName() + " -> " + group_rate + "/" + group_bucket.getAvailableByteCount());
-			        	  }
-			          }
-			          */
-			          
-			          if ( group_bucket.getRate() != group_rate ){
-			        	  
-			        	  group_bucket.setRate( group_rate );
-			          }
-			          
-			          int 	group_allowed = group_bucket.getAvailableByteCount();
-			          
-			          if ( group_allowed < allowed ){
-			        	  
-			        	  allowed = group_allowed;
-			          }
-		           }
-	          }catch( Throwable e ){
-	        	  // conn_data.group stuff is not synchronized for speed but can cause borkage if new
-	        	  // limiters added so trap here
-	        	  
-	        	  if (!( e instanceof IndexOutOfBoundsException )){
-	        		  
-	        		  Debug.printStackTrace(e);
-	        	  }
-	          }
-          }
-                  	            
-           return allowed;
-        }
+    				if( main_bucket.getRate() != max_rate.getRateLimitBytesPerSecond() ) {
 
-        public void bytesProcessed( int num_bytes_written ) {
-          if ( RATE_LIMIT_LAN_TOO || !( connection.isLANLocal() && NetworkManager.isLANRateEnabled())){
-	          for (int i=0;i<conn_data.group_datas.length;i++){
-	        	  conn_data.group_datas[i].bucket.setBytesUsed( num_bytes_written );
-	        	  conn_data.groups[i].updateBytesUsed( num_bytes_written );
-	          }
-          }
-          main_bucket.setBytesUsed( num_bytes_written );
-        }
-      }, partition_id );
+    					main_bucket.setRate( max_rate.getRateLimitBytesPerSecond() );
+    				}
+
+    				int allowed = main_bucket.getAvailableByteCount();
+
+    					// reserve bandwidth for the general pool
+
+    				allowed -= connection.getMssSize();
+
+    				if ( allowed < 0 )allowed = 0;
+
+	    				// only apply group rates to non-lan local connections 
+	
+	    				// ******* READ ME *******
+	    				// If you ever come here looking for an explanation as to why on torrent startup some peers
+	    				// appear to be ignoring rate limits for the first few pieces of a download
+	    				// REMEMBER that fast-start extension pieces are downloaded while be peer is choking us and hence
+	    				// in a non-upgraded state WHICH MEANS that rate limits are NOT APPLIED
+
+
+    				if ( RATE_LIMIT_LAN_TOO || !( connection.isLANLocal() && NetworkManager.isLANRateEnabled())){
+
+    						// sync group rates
+
+    					LimitedRateGroup[]	groups 		= conn_data.groups;
+    					GroupData[]			group_datas = conn_data.group_datas; 
+
+    					if ( groups.length != group_datas.length ){
+    							// yeah, I know....
+    						try{ 
+    							connections_mon.enter();
+
+    							groups 		= conn_data.groups;
+    							group_datas	= conn_data.group_datas;
+    						}finally{ 
+    							connections_mon.exit(); 
+    						}
+    					}
+
+    					try{
+    						for (int i=0;i<group_datas.length;i++){
+
+    							//boolean log = group.getName().contains("parg");
+
+    							int group_rate = NetworkManagerUtilities.getGroupRateLimit(  groups[i] );
+
+    							ByteBucket group_bucket = group_datas[i].bucket;
+
+    							/*
+						          if ( log ){
+						        	  long now = SystemTime.getCurrentTime();
+						        	  if ( now - last_log > 500 ){
+						        		  last_log = now;
+						        		  System.out.println( "    " + group.getName() + " -> " + group_rate + "/" + group_bucket.getAvailableByteCount());
+						        	  }
+						          }
+    							 */
+
+    							if ( group_bucket.getRate() != group_rate ){
+
+    								group_bucket.setRate( group_rate );
+    							}
+
+    							int 	group_allowed = group_bucket.getAvailableByteCount();
+
+    							if ( group_allowed < allowed ){
+
+    								allowed = group_allowed;
+    							}
+    						}
+    					}catch( Throwable e ){
+    						
+    						// conn_data.group stuff is not synchronized for speed but can cause borkage if new
+    						// limiters added so trap here
+
+    						if (!( e instanceof IndexOutOfBoundsException )){
+
+    							Debug.printStackTrace(e);
+    						}
+    					}
+    				}
+
+    				return allowed;
+    			}
+
+    			public void 
+    			bytesProcessed( 
+    					int num_bytes_written ) 
+    			{
+    				if ( RATE_LIMIT_LAN_TOO || !( connection.isLANLocal() && NetworkManager.isLANRateEnabled())){
+
+      					LimitedRateGroup[]	groups 		= conn_data.groups;
+    					GroupData[]			group_datas = conn_data.group_datas; 
+
+    					if ( groups.length != group_datas.length ){
+    							// yeah, I know....
+    						try{ 
+    							connections_mon.enter();
+
+    							groups 		= conn_data.groups;
+    							group_datas	= conn_data.group_datas;
+    						}finally{ 
+    							connections_mon.exit(); 
+    						}
+    					}
+    					
+    					for (int i=0;i<group_datas.length;i++){
+    						
+    						group_datas[i].bucket.setBytesUsed( num_bytes_written );
+    						
+    						groups[i].updateBytesUsed( num_bytes_written );
+    					}
+    				}
+
+    				main_bucket.setBytesUsed( num_bytes_written );
+    			}
+    		}, 
+    		partition_id );
       
       conn_data.state = ConnectionData.STATE_UPGRADED;
     }
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportCipher.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportCipher.java
index 15902a6..ad86253 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportCipher.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportCipher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportCryptoManager.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportCryptoManager.java
index 4bcb736..de44fdf 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportCryptoManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportCryptoManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 18, 2006
  * Created by Alon Rohter
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.networkmanager.impl;
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelper.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelper.java
index e19da5b..5c600e5 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelper.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilter.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilter.java
index 36104fb..b1d09e9 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilter.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterInserter.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterInserter.java
index 506d377..5cc8fa3 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterInserter.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterInserter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStream.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStream.java
index 40d1cd0..e6bc815 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStream.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStream.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStreamCipher.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStreamCipher.java
index fe73779..b40577b 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStreamCipher.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStreamCipher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStreamXOR.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStreamXOR.java
index e6e3f6c..6c5ac6e 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStreamXOR.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterStreamXOR.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterTransparent.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterTransparent.java
index 8b54cbf..c90e5ce 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterTransparent.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportHelperFilterTransparent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportImpl.java
index 6c6346d..575b706 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportStats.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportStats.java
index 074ef9a..24bbe7c 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/TransportStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 19, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/WriteController.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/WriteController.java
index 59f4ec8..c1236b4 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/WriteController.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/WriteController.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 27, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessage.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessage.java
index d10ee5b..fb17c79 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessage.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 5 Oct 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessageDecoder.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessageDecoder.java
index 7ba3020..ad96871 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessageDecoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessageDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 2 Oct 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessageEncoder.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessageEncoder.java
index efc0131..5339fa4 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessageEncoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPMessageEncoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 2 Oct 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnection.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnection.java
index b57d10b..eb1babc 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnection.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 3 Oct 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -35,6 +32,7 @@ import org.gudy.azureus2.core3.logging.Logger;
 import org.gudy.azureus2.core3.peer.impl.PEPeerControl;
 import org.gudy.azureus2.core3.peer.impl.PEPeerTransport;
 import org.gudy.azureus2.core3.peer.util.PeerUtils;
+import org.gudy.azureus2.core3.util.AddressUtils;
 import org.gudy.azureus2.core3.util.Constants;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.DirectByteBuffer;
@@ -1281,7 +1279,7 @@ HTTPNetworkConnection
 		protected byte[]
 		getAddress()
 		{
-			return( connection.getEndpoint().getNotionalAddress().getAddress().getAddress());
+			return( AddressUtils.getAddressBytes( connection.getEndpoint().getNotionalAddress()));
 		}
 		
 		protected byte[]
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnectionFile.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnectionFile.java
index dc0e194..b083764 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnectionFile.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnectionFile.java
@@ -1,7 +1,7 @@
 /*
  * Created on 4 Oct 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnectionWebSeed.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnectionWebSeed.java
index f6434a1..91d7951 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnectionWebSeed.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkConnectionWebSeed.java
@@ -1,7 +1,7 @@
 /*
  * Created on 4 Oct 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkManager.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkManager.java
index 7b45b78..4f826a9 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/http/HTTPNetworkManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 2 Oct 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/IncomingSocketChannelManager.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/IncomingSocketChannelManager.java
index fd35ffe..2b0b064 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/IncomingSocketChannelManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/IncomingSocketChannelManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 18, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -55,6 +52,8 @@ import com.aelitis.azureus.core.networkmanager.impl.IncomingConnectionManager;
 import com.aelitis.azureus.core.networkmanager.impl.ProtocolDecoder;
 import com.aelitis.azureus.core.networkmanager.impl.TransportCryptoManager;
 import com.aelitis.azureus.core.networkmanager.impl.TransportHelperFilter;
+import com.aelitis.azureus.core.proxy.AEProxyAddressMapper;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
 
 
 /**
@@ -85,6 +84,7 @@ public class IncomingSocketChannelManager
 
   private long	last_non_local_connection_time;
   
+  private final AEProxyAddressMapper proxy_address_mapper = AEProxyFactory.getAddressMapper();
   
   /**
    * Create manager and begin accepting and routing new connections.
@@ -447,20 +447,22 @@ public class IncomingSocketChannelManager
  
     SocketChannel	channel = ((TCPTransportHelper)filter.getHelper()).getSocketChannel();
        
+    Socket socket = channel.socket();
+
     //set advanced socket options
     try {
       int so_sndbuf_size = COConfigurationManager.getIntParameter( "network.tcp.socket.SO_SNDBUF" );
-      if( so_sndbuf_size > 0 )  channel.socket().setSendBufferSize( so_sndbuf_size );
+      if( so_sndbuf_size > 0 )  socket.setSendBufferSize( so_sndbuf_size );
       
       String ip_tos = COConfigurationManager.getStringParameter( "network.tcp.socket.IPDiffServ" );
-      if( ip_tos.length() > 0 )  channel.socket().setTrafficClass( Integer.decode( ip_tos ).intValue() );
+      if( ip_tos.length() > 0 )  socket.setTrafficClass( Integer.decode( ip_tos ).intValue() );
     }
     catch( Throwable t ) {
       t.printStackTrace();
     }
     
-	InetSocketAddress tcp_address = new InetSocketAddress( channel.socket().getInetAddress(), channel.socket().getPort());
-
+    InetSocketAddress tcp_address = proxy_address_mapper.applyPortMapping( socket.getInetAddress(), socket.getPort());
+    
 	ConnectionEndpoint	co_ep = new ConnectionEndpoint(tcp_address);
 
 	ProtocolEndpointTCP	pe_tcp = (ProtocolEndpointTCP)ProtocolEndpointFactory.createEndpoint( ProtocolEndpoint.PROTOCOL_TCP, co_ep, tcp_address );
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/LightweightTCPTransport.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/LightweightTCPTransport.java
index c7fac72..d86b879 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/LightweightTCPTransport.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/LightweightTCPTransport.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 28, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.networkmanager.impl.tcp;
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/ProtocolEndpointTCP.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/ProtocolEndpointTCP.java
index f2d54ba..dcc7d21 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/ProtocolEndpointTCP.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/ProtocolEndpointTCP.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/ProxyLoginHandler.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/ProxyLoginHandler.java
index 09ee4eb..cc0fc17 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/ProxyLoginHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/ProxyLoginHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 1, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,13 @@
  * 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.networkmanager.impl.tcp;
 
 import java.io.IOException;
+import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Proxy;
 import java.net.SocketAddress;
@@ -38,7 +36,6 @@ import com.aelitis.azureus.core.networkmanager.*;
 import com.aelitis.azureus.core.proxy.AEProxyFactory;
 import com.aelitis.azureus.core.proxy.AEProxySelector;
 import com.aelitis.azureus.core.proxy.AEProxySelectorFactory;
-import com.aelitis.azureus.core.proxy.socks.impl.AESocksProxyState;
 
 
 /**
@@ -152,7 +149,8 @@ public class ProxyLoginHandler {
     	mapped_ip = AEProxyFactory.getAddressMapper().internalise( remote_address.getHostName() ); 
     }
     else{
-    	mapped_ip = remote_address.getAddress().getHostName();
+    
+    	mapped_ip = AddressUtils.getHostNameNoResolve( remote_address );
     }
     
     if( socks_version.equals( "V4" ) ) {
@@ -375,14 +373,44 @@ public class ProxyLoginHandler {
     handshake.put( (byte)1 ); // command = CONNECT
     handshake.putShort( (short)remote_address.getPort() );
 
-    byte[] ip_bytes = HostNameToIPResolver.syncResolve( remote_address.getAddress().getHostAddress() ).getAddress();
+    	// for v4 we have to resolve the address locally
+    
+    InetAddress ia = remote_address.getAddress();
+    
+    String host_str;
+    
+    if ( ia == null ){
+    	
+    		// unresolved
+    	
+    	host_str = remote_address.getHostName();
+    	
+    }else{
+    	
+    	host_str = ia.getHostAddress();
+    }
+    
+    InetAddress address = HostNameToIPResolver.syncResolve( host_str );
+    
+    if ( address == null ){
+    	
+    	throw( new Exception( "Unresolved host: " + remote_address));
+    }
+    
+    byte[] ip_bytes = address.getAddress();
 
+    if ( ip_bytes.length != 4 ){
+    	
+    	throw( new Exception( "Unsupported IPv6 address: " + remote_address ));
+    }
+    
     handshake.put( ip_bytes[ 0 ] );
     handshake.put( ip_bytes[ 1 ] );
     handshake.put( ip_bytes[ 2 ] );
     handshake.put( ip_bytes[ 3 ] );
     
-    if( socks_user.length() > 0 ) {
+    if( socks_user.length() > 0 ){
+    	
       handshake.put( socks_user.getBytes() );
     }
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/SelectorGuard.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/SelectorGuard.java
index f4260d3..68df316 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/SelectorGuard.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/SelectorGuard.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 28, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.networkmanager.impl.tcp;
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPConnectionManager.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPConnectionManager.java
index f07251b..a08c43a 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPConnectionManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPConnectionManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 13, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -117,6 +114,35 @@ public class TCPConnectionManager {
 			});
   }
   
+  private int rcv_size;
+  private int snd_size;
+  private String ip_tos;
+  private int local_bind_port;
+  
+  {
+	  COConfigurationManager.addAndFireParameterListeners(
+			new String[]{
+				"network.tcp.socket.SO_RCVBUF",
+				"network.tcp.socket.SO_SNDBUF",
+				"network.tcp.socket.IPDiffServ",
+				"network.bind.local.port"
+			},
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					String name )
+				{
+					rcv_size = COConfigurationManager.getIntParameter( "network.tcp.socket.SO_RCVBUF" );				 
+
+					snd_size = COConfigurationManager.getIntParameter( "network.tcp.socket.SO_SNDBUF" );
+
+					ip_tos = COConfigurationManager.getStringParameter( "network.tcp.socket.IPDiffServ" );
+					
+					local_bind_port = COConfigurationManager.getIntParameter( "network.bind.local.port" );
+				}
+			});
+  }
   
   private static final int CONNECT_ATTEMPT_TIMEOUT = 15*1000;  // parg: reduced from 30 sec as almost never see worthwhile connections take longer that this
   private static final int CONNECT_ATTEMPT_STALL_TIME = 3*1000;  //3sec
@@ -308,11 +334,11 @@ public class TCPConnectionManager {
 	  boolean	bind_failed		= false;
 	  try {
 
-
 		  request.channel = SocketChannel.open();
 
+		  InetAddress bindIP = null;
+		  
 		  try {  //advanced socket options
-			  int rcv_size = COConfigurationManager.getIntParameter( "network.tcp.socket.SO_RCVBUF" );
 			  if( rcv_size > 0 ) {
 				  if (Logger.isEnabled())
 					  Logger.log(new LogEvent(LOGID, "Setting socket receive buffer size"
@@ -321,7 +347,6 @@ public class TCPConnectionManager {
 				  request.channel.socket().setReceiveBufferSize( rcv_size );
 			  }
 
-			  int snd_size = COConfigurationManager.getIntParameter( "network.tcp.socket.SO_SNDBUF" );
 			  if( snd_size > 0 ) {
 				  if (Logger.isEnabled())
 					  Logger.log(new LogEvent(LOGID, "Setting socket send buffer size "
@@ -330,7 +355,6 @@ public class TCPConnectionManager {
 				  request.channel.socket().setSendBufferSize( snd_size );
 			  }
 
-			  String ip_tos = COConfigurationManager.getStringParameter( "network.tcp.socket.IPDiffServ" );
 			  if( ip_tos.length() > 0 ) {
 				  if (Logger.isEnabled())
 					  Logger.log(new LogEvent(LOGID, "Setting socket TOS field "
@@ -339,15 +363,12 @@ public class TCPConnectionManager {
 				  request.channel.socket().setTrafficClass( Integer.decode( ip_tos ).intValue() );
 			  }
 
-
-			  int local_bind_port = COConfigurationManager.getIntParameter( "network.bind.local.port" );
-
 			  if( local_bind_port > 0 ) {
 				  request.channel.socket().setReuseAddress( true );
 			  }
 
 			  try {
-				  InetAddress bindIP = NetworkAdmin.getSingleton().getMultiHomedOutgoingRoundRobinBindAddress(request.address.getAddress());
+				  bindIP = NetworkAdmin.getSingleton().getMultiHomedOutgoingRoundRobinBindAddress(request.address.getAddress());
 				  if ( bindIP != null ) {
 					  if (Logger.isEnabled()) 	Logger.log(new LogEvent(LOGID, "Binding outgoing connection [" + request.address + "] to local IP address: " + bindIP+":"+local_bind_port));
 					  request.channel.socket().bind( new InetSocketAddress( bindIP, local_bind_port ) );
@@ -385,8 +406,8 @@ public class TCPConnectionManager {
 			  
 				  //dont pass the exception outwards, so we will continue processing connection without advanced options set
 				 
-				  String msg = "Error while processing advanced socket options.";
-				  Debug.out( msg, t );
+				  String msg = "Error while processing advanced socket options (rcv=" + rcv_size + ", snd=" + snd_size + ", tos=" + ip_tos + ", port=" + local_bind_port + ", bind=" + bindIP + ")";
+				  //Debug.out( msg, t );
 				  Logger.log(new LogAlert(LogAlert.UNREPEATABLE, msg, t));
 				  
 			  }else{
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPNetworkManager.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPNetworkManager.java
index d77958c..972b433 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPNetworkManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPNetworkManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -24,6 +21,7 @@ package com.aelitis.azureus.core.networkmanager.impl.tcp;
 
 
 import java.net.InetAddress;
+import java.nio.channels.CancelledKeyException;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -200,7 +198,12 @@ TCPNetworkManager
 			    				
 		    			}catch( Throwable t ) {
 		    				
-		    				Debug.out( "readSelectorLoop() EXCEPTION: ", t );
+		    					// filter out the boring ones
+		    				
+		    				if (!( t instanceof CancelledKeyException )){
+		    				
+		    					Debug.out( "readSelectorLoop() EXCEPTION: ", t );
+		    				}
 		    			}      
 		    		}
 		    	}
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportHelper.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportHelper.java
index 2ca9811..649b29e 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportHelper.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportHelper.java
@@ -1,7 +1,7 @@
 /*
  * Created on Nov 1, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,13 @@
  * 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.networkmanager.impl.tcp;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.net.Socket;
 import java.net.SocketException;
 import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
@@ -34,6 +32,8 @@ import org.gudy.azureus2.core3.util.*;
 import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector;
 import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector.VirtualSelectorListener;
 import com.aelitis.azureus.core.networkmanager.impl.TransportHelper;
+import com.aelitis.azureus.core.proxy.AEProxyAddressMapper;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
 
 
 
@@ -46,7 +46,9 @@ TCPTransportHelper
 {
 	public static final int READ_TIMEOUT		= 10*1000;
 	public static final int CONNECT_TIMEOUT		= 20*1000;
-	  
+	
+	private static final AEProxyAddressMapper proxy_address_mapper = AEProxyFactory.getAddressMapper();
+
 	public static final int MAX_PARTIAL_WRITE_RETAIN	= 64;	// aim here is to catch headers
 	
 	private long remainingBytesToScatter = 0; 
@@ -61,6 +63,8 @@ TCPTransportHelper
 	
 	private boolean	trace;
 	
+	private volatile InetSocketAddress	tcp_address;
+	
 	private volatile boolean closed;
 	
 	public TCPTransportHelper( SocketChannel _channel ) {
@@ -70,7 +74,16 @@ TCPTransportHelper
 	public InetSocketAddress
 	getAddress()
 	{
-		return( new InetSocketAddress( channel.socket().getInetAddress(), channel.socket().getPort()));
+		if ( tcp_address != null ){
+			
+			return( tcp_address );
+		}
+		
+		Socket socket = channel.socket();
+		
+	    tcp_address = proxy_address_mapper.applyPortMapping( socket.getInetAddress(), socket.getPort());
+	    	
+	    return( tcp_address );
 	}
 	
 	public String
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportHelperFilterFactory.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportHelperFilterFactory.java
index f28a684..bbb91d5 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportHelperFilterFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportHelperFilterFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 18, 2006
  * Created by Alon Rohter
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.networkmanager.impl.tcp;
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportImpl.java
index 944b118..c095a15 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TCPTransportImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 8, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -25,6 +22,8 @@ package com.aelitis.azureus.core.networkmanager.impl.tcp;
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.logging.*;
@@ -36,6 +35,8 @@ import com.aelitis.azureus.core.networkmanager.impl.TransportHelperFilter;
 import com.aelitis.azureus.core.networkmanager.impl.TransportCryptoManager;
 import com.aelitis.azureus.core.networkmanager.impl.TransportHelper;
 import com.aelitis.azureus.core.networkmanager.impl.TransportImpl;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
 
 
 
@@ -62,8 +63,8 @@ public class TCPTransportImpl extends TransportImpl implements Transport {
   private int		fallback_count;
   private final boolean fallback_allowed;
 
-  private boolean	is_socks;
-  
+  private boolean				is_socks;
+  private volatile PluginProxy	plugin_proxy;
   
   /**
    * Constructor for disconnected (outbound) transport.
@@ -101,7 +102,10 @@ public class TCPTransportImpl extends TransportImpl implements Transport {
     is_inbound_connection = true;
     connect_with_crypto = false;  //inbound connections will automatically be using crypto if necessary
     fallback_allowed = false;
-    description = ( is_inbound_connection ? "R" : "L" ) + ": " + getSocketChannel().socket().getInetAddress().getHostAddress() + ": " + getSocketChannel().socket().getPort();
+    
+    InetSocketAddress address = endpoint.getAddress();
+    
+    description = ( is_inbound_connection ? "R" : "L" ) + ": " + AddressUtils.getHostNameNoResolve( address ) + ": " + address.getPort();
  
   }
   
@@ -203,9 +207,50 @@ public class TCPTransportImpl extends TransportImpl implements Transport {
     }
     
     final InetSocketAddress	address = protocol_endpoint.getAddress();
-
-    is_socks = COConfigurationManager.getBooleanParameter( "Proxy.Data.Enable" ) && !address.equals( ProxyLoginHandler.DEFAULT_SOCKS_SERVER_ADDRESS );
-
+    
+    if ( !address.equals( ProxyLoginHandler.DEFAULT_SOCKS_SERVER_ADDRESS )){
+   
+     
+    			// see if a plugin can handle this connection
+    		
+		if ( address.isUnresolved()){
+			
+			String host = address.getHostName();
+			
+			if ( AENetworkClassifier.categoriseAddress( host ) != AENetworkClassifier.AT_PUBLIC ){
+			
+				Map<String,Object>	opts = new HashMap<String,Object>();
+				
+				Object peer_nets = listener.getConnectionProperty( AEProxyFactory.PO_PEER_NETWORKS );
+				
+				if ( peer_nets != null ){
+					
+					opts.put( AEProxyFactory.PO_PEER_NETWORKS, peer_nets );
+				}
+				
+				PluginProxy pp = plugin_proxy;
+				
+				plugin_proxy = null;
+				
+				if ( pp != null ){
+				
+						// most likely crypto fallback connection so don't assume it is a bad
+						// outcome
+					
+					pp.setOK( true );
+				}
+					
+				plugin_proxy = AEProxyFactory.getPluginProxy( "outbound connection", host, address.getPort(), opts );
+				    		
+			}
+		}
+    	
+		if ( plugin_proxy == null ){
+			
+		   	is_socks = COConfigurationManager.getBooleanParameter( "Proxy.Data.Enable" );
+		}
+    }
+        
     final TCPTransportImpl transport_instance = this;    
     
      
@@ -219,6 +264,7 @@ public class TCPTransportImpl extends TransportImpl implements Transport {
       	if( channel == null ) {
       		String msg = "connectSuccess:: given channel == null";
       		Debug.out( msg );
+      		setConnectResult( false );
       		listener.connectFailure( new Exception( msg ) );
       		return;
       	}
@@ -226,6 +272,8 @@ public class TCPTransportImpl extends TransportImpl implements Transport {
         if( has_been_closed ) {  //closed between select ops
         	TCPNetworkManager.getSingleton().getConnectDisconnectManager().closeConnection( channel );  //just close it
           
+        	setConnectResult( false );
+        	
   			listener.connectFailure( new Throwable( "Connection has been closed" ));
 
           return;
@@ -234,41 +282,110 @@ public class TCPTransportImpl extends TransportImpl implements Transport {
         connect_request_key = null;
         description = ( is_inbound_connection ? "R" : "L" ) + ": " + channel.socket().getInetAddress().getHostAddress() + ": " + channel.socket().getPort();
 
-        if( is_socks ) {  //proxy server connection established, login
+        PluginProxy pp = plugin_proxy;
+        
+        if ( is_socks ){  //proxy server connection established, login
         	if (Logger.isEnabled())
         		Logger.log(new LogEvent(LOGID,"Socket connection established to proxy server [" +description+ "], login initiated..."));
-          
-        		// set up a transparent filter for socks negotiation
+
+        	// set up a transparent filter for socks negotiation
+
+        	setFilter( TCPTransportHelperFilterFactory.createTransparentFilter( channel ));
+
+        	new ProxyLoginHandler( transport_instance, address, new ProxyLoginHandler.ProxyListener() {
+        		public void connectSuccess() {
+        			if (Logger.isEnabled())
+        				Logger.log(new LogEvent(LOGID, "Proxy [" +description+ "] login successful." ));
+        			handleCrypto( address, channel, initial_data, priority, listener );
+        		}
+
+        		public void connectFailure( Throwable failure_msg ) {
+        			close( "Proxy login failed" );
+        			listener.connectFailure( failure_msg );
+        		}
+        	});
+        }else if ( pp != null ){
+
+           	if (Logger.isEnabled()){
+        		Logger.log(new LogEvent(LOGID,"Socket connection established via plugin proxy [" +description+ "], login initiated..."));
+           	}
+           	
+           		// set up a transparent filter for socks negotiation
+
+        	setFilter( TCPTransportHelperFilterFactory.createTransparentFilter( channel ));
+
+        	String pp_host = pp.getHost();
         	
-          setFilter( TCPTransportHelperFilterFactory.createTransparentFilter( channel ));
-      		
-          new ProxyLoginHandler( transport_instance, address, new ProxyLoginHandler.ProxyListener() {
-            public void connectSuccess() {
-            	if (Logger.isEnabled())
-            		Logger.log(new LogEvent(LOGID, "Proxy [" +description+ "] login successful." ));
-            	handleCrypto( address, channel, initial_data, priority, listener );
-            }
-            
-            public void connectFailure( Throwable failure_msg ) {
-            	close( "Proxy login failed" );
-            	listener.connectFailure( failure_msg );
-            }
-          });
-        }
-        else {  //direct connection established, notify
+        	InetSocketAddress ia_address;
+        	
+        	if ( AENetworkClassifier.categoriseAddress( pp_host ) == AENetworkClassifier.AT_PUBLIC ){
+        	
+        		ia_address = new InetSocketAddress( pp.getHost(), pp.getPort());
+        	
+        	}else{
+        		
+        		ia_address = InetSocketAddress.createUnresolved( pp_host, pp.getPort());
+        	}
+        	
+        	new ProxyLoginHandler( 
+        		transport_instance, 
+        		ia_address,
+        		new ProxyLoginHandler.ProxyListener() 
+        		{
+        			public void 
+        			connectSuccess() 
+        			{
+	        			if (Logger.isEnabled()){
+	        				Logger.log(new LogEvent(LOGID, "Proxy [" +description+ "] login successful." ));
+	        			}
+	        			setConnectResult( true );
+	        			
+	        			handleCrypto( address, channel, initial_data, priority, listener );
+        			}
+
+        			public void 
+        			connectFailure( 
+        				Throwable failure_msg ) 
+        			{
+        				setConnectResult( false );
+        				
+        				close( "Proxy login failed" );
+        				
+        				listener.connectFailure( failure_msg );
+        			}
+        		},
+        		"V4a", "", "" );
+        	
+        }else {  //direct connection established, notify
         	handleCrypto( address, channel, initial_data, priority, listener );
         }
       }
 
       public void connectFailure( Throwable failure_msg ) {
         connect_request_key = null;
+        setConnectResult( false );
         listener.connectFailure( failure_msg );
       }
     };
     
     connect_request_key = connect_listener;
     
-    InetSocketAddress to_connect = is_socks ? ProxyLoginHandler.getProxyAddress( address ): address;
+    InetSocketAddress to_connect;
+    
+    PluginProxy pp = plugin_proxy;
+    
+    if ( is_socks ){
+    	
+    	to_connect = ProxyLoginHandler.getProxyAddress( address );
+    	
+    }else if ( pp != null ){
+    	
+    	to_connect = (InetSocketAddress)pp.getProxy().address();
+    	
+    }else{
+    	
+    	to_connect = address;
+    }
     
     TCPNetworkManager.getSingleton().getConnectDisconnectManager().requestNewConnection( to_connect, connect_listener, priority );
   }
@@ -451,12 +568,23 @@ public class TCPTransportImpl extends TransportImpl implements Transport {
 	 close( reason );
   }
   
+  private void
+  setConnectResult(
+	boolean		ok )
+  {
+	 PluginProxy pp = plugin_proxy;
+	 if ( pp != null ){
+		 plugin_proxy = null;
+		 pp.setOK(ok);
+	 }
+  }
+  
   /**
    * Close the transport connection.
    */
   public void close( String reason ) {
     has_been_closed = true;
-    
+    setConnectResult( false );
     if( connect_request_key != null ) {
     	TCPNetworkManager.getSingleton().getConnectDisconnectManager().cancelRequest( connect_request_key );
     }
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TransportEndpointTCP.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TransportEndpointTCP.java
index 9c446f9..5721670 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TransportEndpointTCP.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TransportEndpointTCP.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TransportStartpointTCP.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TransportStartpointTCP.java
index 50bf0b0..7fd1178 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TransportStartpointTCP.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/TransportStartpointTCP.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualAcceptSelector.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualAcceptSelector.java
index 50344f1..833fe67 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualAcceptSelector.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualAcceptSelector.java
@@ -1,7 +1,7 @@
 /*
  * Created on Dec 4, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualBlockingServerChannelSelector.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualBlockingServerChannelSelector.java
index 7d85b06..56ab33e 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualBlockingServerChannelSelector.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualBlockingServerChannelSelector.java
@@ -1,7 +1,7 @@
 /*
  * Created on Dec 4, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -166,6 +163,13 @@ public class VirtualBlockingServerChannelSelector
   	return null;
   }
   
+  public int getPort()
+  {
+	 	if( server_channel != null ) {
+	  		return server_channel.socket().getLocalPort();
+	  	}
+	  	return -1;
+  }
   
   public long getTimeOfLastAccept() {
   	return last_accept_time;
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualChannelSelectorImpl.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualChannelSelectorImpl.java
index e51b371..faa4712 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualChannelSelectorImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualChannelSelectorImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 28, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.networkmanager.impl.tcp;
@@ -802,7 +799,8 @@ public class VirtualChannelSelectorImpl {
 	 				 
 	 				logged_broken_select = true;
 	 				 
-	 				Debug.outNoStack( "Select operation looks broken, trying workaround" );
+	 				//We always get this on OSX
+	 				//Debug.outNoStack( "Select operation looks broken, trying workaround" );
 	 			 }
 	 		 }
  		 }else{
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualNonBlockingServerChannelSelector.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualNonBlockingServerChannelSelector.java
index 6d6dd34..078d872 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualNonBlockingServerChannelSelector.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/tcp/VirtualNonBlockingServerChannelSelector.java
@@ -1,7 +1,7 @@
 /*
  * Created on Dec 4, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -192,6 +189,14 @@ VirtualNonBlockingServerChannelSelector
 	  return server_channel.socket().getInetAddress();
   }
   
+  public int getPort() {
+	  if ( server_channels.size() == 0 ){
+		  return( -1);
+	  }
+	  ServerSocketChannel	server_channel = (ServerSocketChannel)server_channels.get(0);
+ 	
+	  return server_channel.socket().getLocalPort();
+  }
   
   public long getTimeOfLastAccept() {
   	return last_accept_time;
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/test/PHETester.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/test/PHETester.java
index b2e3bf8..9837fa6 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/test/PHETester.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/test/PHETester.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlue.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlue.java
index af7479d..1e7b161 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlue.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlue.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueListener.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueListener.java
index a5edf0a..14337de 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueLoopBack.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueLoopBack.java
index dc9ad31..0fb945f 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueLoopBack.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueLoopBack.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueUDP.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueUDP.java
index 16ca0c6..9d5ca66 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueUDP.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/NetworkGlueUDP.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/ProtocolEndpointUDP.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/ProtocolEndpointUDP.java
index 7861650..52aab6f 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/ProtocolEndpointUDP.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/ProtocolEndpointUDP.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/TransportEndpointUDP.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/TransportEndpointUDP.java
index b2f6701..41ad180 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/TransportEndpointUDP.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/TransportEndpointUDP.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnection.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnection.java
index 77692e8..8789e8a 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnection.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionManager.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionManager.java
index 5c09303..fc0b5e8 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,18 +14,15 @@
  * 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.networkmanager.impl.udp;
 
 import java.util.*;
-
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
@@ -138,6 +135,13 @@ UDPConnectionManager
 		UDPTransportHelper	helper = null;
 
 		try{
+			if ( address.isUnresolved()){
+				
+				listener.connectFailure( new UnknownHostException( address.getHostName()));
+				
+				return;
+			}
+			
 			int time = listener.connectAttemptStarted( -1 );
 			
 			if ( time != -1 ){
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionSet.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionSet.java
index 6821d06..9f25e03 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionSet.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPConnectionSet.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPNetworkManager.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPNetworkManager.java
index c0ced9d..fcff0a3 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPNetworkManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPNetworkManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPPacket.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPPacket.java
index 5b08113..934c336 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPPacket.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPPacket.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPSelector.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPSelector.java
index a9f69c9..e3ca057 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPSelector.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPSelector.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPTransport.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPTransport.java
index 606a96a..92233ff 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPTransport.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPTransport.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPTransportHelper.java b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPTransportHelper.java
index 722aa1d..214b340 100644
--- a/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPTransportHelper.java
+++ b/azureus2/src/com/aelitis/azureus/core/networkmanager/impl/udp/UDPTransportHelper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/PairedNode.java b/azureus2/src/com/aelitis/azureus/core/pairing/PairedNode.java
index 6c16657..e55c177 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/PairedNode.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/PairedNode.java
@@ -2,20 +2,19 @@
  * Created on Jul 1, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/PairedService.java b/azureus2/src/com/aelitis/azureus/core/pairing/PairedService.java
index 4bd29c8..4ffdbdc 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/PairedService.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/PairedService.java
@@ -2,20 +2,19 @@
  * 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/PairedServiceRequestHandler.java b/azureus2/src/com/aelitis/azureus/core/pairing/PairedServiceRequestHandler.java
index 492701b..8ac12a2 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/PairedServiceRequestHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/PairedServiceRequestHandler.java
@@ -2,20 +2,19 @@
  * Created on Dec 10, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/PairingConnectionData.java b/azureus2/src/com/aelitis/azureus/core/pairing/PairingConnectionData.java
index 4b1cb69..ef79e65 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/PairingConnectionData.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/PairingConnectionData.java
@@ -2,20 +2,19 @@
  * 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -30,6 +29,8 @@ PairingConnectionData
 	public static final String ATTR_PORT_OVERRIDE	= "port_or";
 	public static final String ATTR_PROTOCOL		= "protocol";
 	public static final String ATTR_HOST			= "host";
+	public static final String ATTR_I2P				= "I2P";
+	public static final String ATTR_TOR				= "Tor";
 	
 	public void
 	setAttribute(
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/PairingException.java b/azureus2/src/com/aelitis/azureus/core/pairing/PairingException.java
index 297e925..724aae8 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/PairingException.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/PairingException.java
@@ -2,20 +2,19 @@
  * 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/PairingManager.java b/azureus2/src/com/aelitis/azureus/core/pairing/PairingManager.java
index ad8fe8c..e488f6d 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/PairingManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/PairingManager.java
@@ -2,20 +2,19 @@
  * 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -31,6 +30,8 @@ import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;
 public interface 
 PairingManager 
 {
+	public static String CONFIG_SECTION_ID = "Pairing";
+
 	public boolean
 	isEnabled();
 	
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/PairingManagerFactory.java b/azureus2/src/com/aelitis/azureus/core/pairing/PairingManagerFactory.java
index f8689b2..c494a11 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/PairingManagerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/PairingManagerFactory.java
@@ -2,20 +2,19 @@
  * 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/PairingManagerListener.java b/azureus2/src/com/aelitis/azureus/core/pairing/PairingManagerListener.java
index aacf54d..53f9dc3 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/PairingManagerListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/PairingManagerListener.java
@@ -2,20 +2,19 @@
  * 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/PairingTest.java b/azureus2/src/com/aelitis/azureus/core/pairing/PairingTest.java
index 95ef128..fe103fe 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/PairingTest.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/PairingTest.java
@@ -2,20 +2,19 @@
  * Created on Jan 21, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/PairingTestListener.java b/azureus2/src/com/aelitis/azureus/core/pairing/PairingTestListener.java
index dac9593..c4617e0 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/PairingTestListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/PairingTestListener.java
@@ -2,20 +2,19 @@
  * Created on Jan 21, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairManagerTunnel.java b/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairManagerTunnel.java
index 4a4433b..614fbc5 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairManagerTunnel.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairManagerTunnel.java
@@ -2,20 +2,19 @@
  * Created on Dec 6, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairingManagerImpl.java b/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairingManagerImpl.java
index 7dff5e2..f074ccb 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairingManagerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairingManagerImpl.java
@@ -2,20 +2,19 @@
  * 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -155,6 +154,8 @@ PairingManagerImpl
 	private StringParameter		param_public_ipv6;
 	private StringParameter		param_host;
 	
+	private BooleanParameter 	param_net_enable;
+
 	private StringParameter		param_local_ipv4;
 	private StringParameter		param_local_ipv6;
 
@@ -223,7 +224,7 @@ PairingManagerImpl
 		final UIManager	ui_manager = default_pi.getUIManager();
 		
 		BasicPluginConfigModel configModel = ui_manager.createBasicPluginConfigModel(
-				ConfigSection.SECTION_CONNECTION, "Pairing");
+				ConfigSection.SECTION_CONNECTION, CONFIG_SECTION_ID);
 
 		configModel.addHyperlinkParameter2( "ConfigView.label.please.visit.here", MessageText.getString( "ConfigView.section.connection.pairing.url" ));
 
@@ -370,6 +371,15 @@ PairingManagerImpl
 					param_srp_set,
 				});
 		
+			// optional
+		
+		param_net_enable = configModel.addBooleanParameter2( "pairing.nets.enable", "pairing.nets.enable", false );
+
+		configModel.createGroup(
+				"pairing.group.optional",
+				new Parameter[]{
+						param_net_enable });
+		
 			// explicit
 		
 		LabelParameter	param_e_info = configModel.addLabelParameter2( "pairing.explicit.info" );
@@ -413,6 +423,7 @@ PairingManagerImpl
 		param_local_ipv4.addListener(	change_listener );
 		param_local_ipv6.addListener(	change_listener );
 		param_host.addListener(	change_listener );
+		param_net_enable.addListener(	change_listener );
 		
 		param_e_enable.addEnabledOnSelection( param_public_ipv4 );
 		param_e_enable.addEnabledOnSelection( param_public_ipv6 );
@@ -1334,9 +1345,11 @@ PairingManagerImpl
 						updateGlobals( true );
 					}
 					
+					boolean	enable_nets = param_net_enable.getValue();
+					
 					for ( PairedServiceImpl service: services.values()){
 						
-						list.add( service.toMap());
+						list.add( service.toMap( enable_nets ));
 					}
 					
 					has_services = list.size() > 0;
@@ -2223,7 +2236,8 @@ PairingManagerImpl
 		}
 		
 		protected Map<String,String>
-		toMap()
+		toMap(
+			boolean		enable_nets )
 		{
 			Map<String,String> result = new HashMap<String, String>();
 			
@@ -2234,6 +2248,13 @@ PairingManagerImpl
 				result.putAll( attributes );
 			}
 			
+			if ( !enable_nets ){
+				
+				result.remove( PairingConnectionData.ATTR_I2P );
+				
+				result.remove( PairingConnectionData.ATTR_TOR );
+			}
+			
 			return( result );
 		}
 	}
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairingManagerTunnelHandler.java b/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairingManagerTunnelHandler.java
index aa86e6d..c6e488e 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairingManagerTunnelHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/impl/PairingManagerTunnelHandler.java
@@ -2,20 +2,19 @@
  * Created on Dec 5, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/pairing/impl/swt/PMSWTImpl.java b/azureus2/src/com/aelitis/azureus/core/pairing/impl/swt/PMSWTImpl.java
index 150307b..bdc0ff4 100644
--- a/azureus2/src/com/aelitis/azureus/core/pairing/impl/swt/PMSWTImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/pairing/impl/swt/PMSWTImpl.java
@@ -2,20 +2,19 @@
  * Created on Aug 14, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -43,6 +42,7 @@ import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntry;
 import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntryListener;
 import org.gudy.azureus2.ui.swt.auth.CryptoWindow;
 
+import com.aelitis.azureus.core.pairing.PairingManager;
 import com.aelitis.azureus.core.pairing.impl.PairingManagerImpl;
 import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
 import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminNetworkInterface;
@@ -53,6 +53,7 @@ import com.aelitis.azureus.core.util.AZ3Functions;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdater;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
 
 public class 
@@ -246,7 +247,9 @@ PMSWTImpl
 			
 													if ( uif != null ){
 			
-														uif.openView( UIFunctions.VIEW_CONFIG, "Pairing" );
+														uif.getMDI().showEntryByID(
+																MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+																PairingManager.CONFIG_SECTION_ID );
 													}
 												}
 											});
@@ -263,7 +266,9 @@ PMSWTImpl
 													
 													if ( uif != null ){
 			
-														uif.openView( UIFunctions.VIEW_CONFIG, "Pairing" );
+														uif.getMDI().showEntryByID(
+																MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+																PairingManager.CONFIG_SECTION_ID );
 													}
 												}
 											};
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManager.java b/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManager.java
index dbc55d1..ab9f380 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 20, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -37,8 +34,10 @@ import org.gudy.azureus2.core3.peer.util.PeerIdentityManager;
 import org.gudy.azureus2.core3.torrent.TOTorrentFile;
 import org.gudy.azureus2.core3.util.AEGenericCallback;
 import org.gudy.azureus2.core3.util.AEMonitor;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.AERunStateHandler;
 import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.AddressUtils;
 import org.gudy.azureus2.core3.util.ByteFormatter;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.HashWrapper;
@@ -786,8 +785,8 @@ public class PeerManager implements AzureusCoreStatsProvider{
 
 					return( false );
 				}
-
-				return( known_seeds.contains( address.getAddress().getAddress()));
+				
+				return( known_seeds.contains( AddressUtils.getAddressBytes( address )));
 
 			}finally{
 
@@ -810,7 +809,7 @@ public class PeerManager implements AzureusCoreStatsProvider{
 				// can't include port as it will be a randomly allocated one in general. two people behind the
 				// same NAT will have to connect to each other using LAN peer finder 
 
-				known_seeds.add( address.getAddress().getAddress() );
+				known_seeds.add( AddressUtils.getAddressBytes( address ));
 
 			}finally{
 
@@ -984,11 +983,22 @@ public class PeerManager implements AzureusCoreStatsProvider{
 			ConnectionEndpoint ep = connection.getEndpoint();
 			
 			
-			InetAddress address = ep.getNotionalAddress().getAddress();
+			InetSocketAddress is_address = ep.getNotionalAddress();
 			
-			String host_address = address.getHostAddress();
+			String host_address = AddressUtils.getHostAddress( is_address );
+
+			String net_cat = AENetworkClassifier.categoriseAddress( host_address );
+			
+			if ( !control.isNetworkEnabled( net_cat )){
+				
+				connection.close( "Network '" + net_cat + "' is not enabled" );
 
-			boolean same_allowed = COConfigurationManager.getBooleanParameter( "Allow Same IP Peers" ) || address.isLoopbackAddress();
+				return;
+			}
+			
+			InetAddress address_mbn = is_address.getAddress();
+			
+			boolean same_allowed = COConfigurationManager.getBooleanParameter( "Allow Same IP Peers" ) || ( address_mbn != null && address_mbn.isLoopbackAddress());
 
 			if ( !same_allowed && PeerIdentityManager.containsIPAddress( control.getPeerIdentityDataID(), host_address )){
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRegistration.java b/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRegistration.java
index 4752459..d63acf4 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRegistration.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRegistration.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRegistrationAdapter.java b/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRegistrationAdapter.java
index 0b92082..865a183 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRegistrationAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRegistrationAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRoutingListener.java b/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRoutingListener.java
index 774db08..46dd5bd 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRoutingListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/PeerManagerRoutingListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 3 Oct 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlInstance.java b/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlInstance.java
index b02e49f..816295b 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlInstance.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlInstance.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.peermanager.control;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlScheduler.java b/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlScheduler.java
index 93849d9..8731be7 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlScheduler.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlScheduler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.peermanager.control;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlSchedulerFactory.java b/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlSchedulerFactory.java
index ce40c33..5bf5c18 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlSchedulerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/control/PeerControlSchedulerFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.peermanager.control;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/control/SpeedTokenDispenser.java b/azureus2/src/com/aelitis/azureus/core/peermanager/control/SpeedTokenDispenser.java
index 71975ca..818ba19 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/control/SpeedTokenDispenser.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/control/SpeedTokenDispenser.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 23, 2007
  * Created by The8472
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerBasic.java b/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerBasic.java
index 7afdeb7..b1f00f3 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerBasic.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerBasic.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 23, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerImpl.java b/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerImpl.java
index d58191e..a1a8568 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.peermanager.control.impl;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerPrioritised.java b/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerPrioritised.java
index a92d1d6..81254cd 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerPrioritised.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/PeerControlSchedulerPrioritised.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 23, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/SpeedTokenDispenserBasic.java b/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/SpeedTokenDispenserBasic.java
index d8dd97a..7cb0bc8 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/SpeedTokenDispenserBasic.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/control/impl/SpeedTokenDispenserBasic.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 23, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/Message.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/Message.java
index 06e718e..a9dba8b 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/Message.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/Message.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 8, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageException.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageException.java
index eafb1c3..a276e2c 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageException.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageException.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 8, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageManager.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageManager.java
index 0588233..2f8bb24 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 8, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamDecoder.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamDecoder.java
index d9907ed..5a24516 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamDecoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 25, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamEncoder.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamEncoder.java
index 68fd6ef..99aa9d0 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamEncoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamEncoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 8, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamFactory.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamFactory.java
index eeb061e..d8a4735 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessageStreamFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 23, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessagingUtil.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessagingUtil.java
index c733511..76e148a 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessagingUtil.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/MessagingUtil.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jun 17, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZBadPiece.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZBadPiece.java
index 2c2142b..093e921 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZBadPiece.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZBadPiece.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 19, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZGenericMapPayload.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZGenericMapPayload.java
index 3325d41..7f1b0ac 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZGenericMapPayload.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZGenericMapPayload.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHandshake.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHandshake.java
index e4a678e..a06b0d7 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHandshake.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHandshake.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHave.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHave.java
index a8b87d6..de44593 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHave.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZHave.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 19, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessage.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessage.java
index bba3a2b..8d851ca 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessage.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 20, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageDecoder.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageDecoder.java
index e2b341a..081a461 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageDecoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 8, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageEncoder.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageEncoder.java
index f0a9391..0b1f27c 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageEncoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageEncoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 8, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageFactory.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageFactory.java
index dc582a8..cc0181a 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMessageFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 19, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMetaData.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMetaData.java
index 52c4e47..cd175ab 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMetaData.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZMetaData.java
@@ -2,20 +2,19 @@
  * Created on Mar 7, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZPeerExchange.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZPeerExchange.java
index bb55ee1..917b926 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZPeerExchange.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZPeerExchange.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -123,7 +120,7 @@ public class AZPeerExchange implements AZMessage, AZStylePeerExchange {
         	udp_port = ((udp_ports[pos*2]<<8)&0xff00) + (udp_ports[pos*2+1]&0xff);
         }
         try{
-        	PeerItem peer = PeerItemFactory.createPeerItem( full_address, PeerItemFactory.PEER_SOURCE_PEER_EXCHANGE, type, udp_port );
+        	PeerItem peer = PeerItemFactory.createPeerItem( full_address, PeerItemFactory.PEER_SOURCE_PEER_EXCHANGE, type, udp_port, AENetworkClassifier.AT_PUBLIC );
         	peers.add( peer );
         }catch( Exception t ){
             Logger.log(new LogEvent( LOGID, LogEvent.LT_WARNING,"PEX: invalid peer received" ));	 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZRequestHint.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZRequestHint.java
index 14aea48..6142710 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZRequestHint.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZRequestHint.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 19, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStatReply.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStatReply.java
index 7b38a53..c5ad16e 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStatReply.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStatReply.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 19, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStatRequest.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStatRequest.java
index 7708fcd..224df32 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStatRequest.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStatRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 19, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStylePeerExchange.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStylePeerExchange.java
index 7bcd0e2..0a73123 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStylePeerExchange.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZStylePeerExchange.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18 Sep 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.messaging.azureus;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZUTMetaData.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZUTMetaData.java
index 092cae8..b48fe60 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZUTMetaData.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/azureus/AZUTMetaData.java
@@ -2,20 +2,19 @@
  * Created on Mar 14, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTAllowedFast.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTAllowedFast.java
index 40cc588..ad7843c 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTAllowedFast.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTAllowedFast.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTBitfield.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTBitfield.java
index a79ef03..6b0a91e 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTBitfield.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTBitfield.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTCancel.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTCancel.java
index c8c7719..dca8008 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTCancel.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTCancel.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTChoke.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTChoke.java
index b44b631..e5ead7e 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTChoke.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTChoke.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTDHTPort.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTDHTPort.java
index 5a560bb..2611b26 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTDHTPort.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTDHTPort.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 Jan 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.messaging.bittorrent;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHandshake.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHandshake.java
index 6c49c8c..610e495 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHandshake.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHandshake.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHave.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHave.java
index 4d3cd62..7ffe9bb 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHave.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHave.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHaveAll.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHaveAll.java
index 7f6d64d..6010b35 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHaveAll.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHaveAll.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHaveNone.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHaveNone.java
index 52952c2..ba01721 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHaveNone.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTHaveNone.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTInterested.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTInterested.java
index b9fe188..b9d53d4 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTInterested.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTInterested.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTKeepAlive.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTKeepAlive.java
index a730c14..ccc1162 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTKeepAlive.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTKeepAlive.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTLTMessage.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTLTMessage.java
index 9962a3e..c7e8819 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTLTMessage.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTLTMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 Sep 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.messaging.bittorrent;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessage.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessage.java
index 5e2f788..fae9e89 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessage.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 17, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageDecoder.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageDecoder.java
index 9930a9b..76c64fb 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageDecoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 24, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageEncoder.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageEncoder.java
index 1b9b29e..e07df80 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageEncoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageEncoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 8, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageFactory.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageFactory.java
index 372c98d..23a8efa 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTMessageFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTPiece.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTPiece.java
index eb94e7f..3615484 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTPiece.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTPiece.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRawMessage.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRawMessage.java
index a7fb5d9..c31084a 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRawMessage.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRawMessage.java
@@ -2,20 +2,19 @@
  * Created on Mar 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRejectRequest.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRejectRequest.java
index ac7eff6..c9d8b37 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRejectRequest.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRejectRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRequest.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRequest.java
index 50d8c28..66edb1f 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRequest.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTSuggestPiece.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTSuggestPiece.java
index 3051a6e..97fb848 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTSuggestPiece.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTSuggestPiece.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTUnchoke.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTUnchoke.java
index 762528c..5d785dd 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTUnchoke.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTUnchoke.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTUninterested.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTUninterested.java
index 5b4c418..dd2517f 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTUninterested.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/BTUninterested.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTDisabledExtensionMessage.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTDisabledExtensionMessage.java
index 59d1301..21d834c 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTDisabledExtensionMessage.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTDisabledExtensionMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 Sep 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.messaging.bittorrent.ltep;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTHandshake.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTHandshake.java
index 1141fb2..7a3c04a 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTHandshake.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTHandshake.java
@@ -258,6 +258,21 @@ public class LTHandshake implements LTMessage {
 		}
 	}
 	
+	public void
+	addOptionalExtensionMapping(
+		String		id,
+		long		subid )
+	{
+		Map ext = (Map)data_dict.get("m");
+		
+		if ( ext == null ){
+			ext = new HashMap();
+			data_dict.put( "m", ext );
+		}
+		
+		ext.put( id, new Long( subid ));
+	}
+			
 	public String getFeatureID() {return LTMessage.LT_FEATURE_ID;}
 	public int getFeatureSubID() {return LTMessage.SUBID_LT_HANDSHAKE;}
 	public String getID() {return LTHandshake.ID_LT_HANDSHAKE;}
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessage.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessage.java
index 3c9ba49..5b2aca8 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessage.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 Sep 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.messaging.bittorrent.ltep;
 
@@ -52,4 +49,5 @@ public interface LTMessage extends Message {
 	public static final byte[] ID_UT_UPLOAD_ONLY_BYTES  = ID_UT_UPLOAD_ONLY.getBytes();
 	public static final int SUBID_UT_UPLOAD_ONLY        = 4;
 
+	// 10 -> 20 reserved for non-public nets
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageDecoder.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageDecoder.java
index 8f96353..6673a93 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageDecoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 Sep 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.messaging.bittorrent.ltep;
 
@@ -29,6 +26,7 @@ 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.BTMessageDecoder;
+import com.aelitis.azureus.core.util.CopyOnWriteMap;
 
 /**
  * @author Allan Crooks
@@ -36,9 +34,33 @@ import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessageDecode
  */
 public class LTMessageDecoder extends BTMessageDecoder {
 	
-	private Map<Byte,byte[]>	entension_handlers = new HashMap<Byte, byte[]>();
+	private static CopyOnWriteMap<Byte,byte[]>	default_entension_handlers = new CopyOnWriteMap<Byte, byte[]>();
 	
-	public LTMessageDecoder() {}
+	public static void
+	addDefaultExtensionHandler(
+		long		id,
+		byte[]		message_id )
+	{
+		default_entension_handlers.put( (byte)id, message_id );
+	}
+	
+	public static void
+	removeDefaultExtensionHandler(
+		long		id )
+	{
+		default_entension_handlers.remove( (byte)id );
+	}
+	
+	private CopyOnWriteMap<Byte,byte[]>	extension_handlers = new CopyOnWriteMap<Byte, byte[]>();
+	
+	public 
+	LTMessageDecoder() 
+	{		
+		if ( default_entension_handlers.size() > 0 ){
+		
+			extension_handlers.putAll( default_entension_handlers );
+		}
+	}
 
 	protected Message createMessage(DirectByteBuffer ref_buff) throws MessageException {
 		// Check to see if it is a LT-extension message. If not, delegate to BTMessageDecoder.
@@ -62,10 +84,8 @@ public class LTMessageDecoder extends BTMessageDecoder {
 				return MessageManager.getSingleton().createMessage(LTMessage.ID_UT_UPLOAD_ONLY_BYTES, ref_buff, (byte)1);
 			default: {
 			  byte[]	message_id;
-			  synchronized( entension_handlers ){
 					
-				  message_id = entension_handlers.get( id );
-			  }
+			  message_id = extension_handlers.get( id );
 			  
 			  if ( message_id != null ){
 				return MessageManager.getSingleton().createMessage( message_id, ref_buff, (byte)1);
@@ -80,10 +100,14 @@ public class LTMessageDecoder extends BTMessageDecoder {
 	addExtensionHandler(
 		byte		id,
 		byte[]		message_id )
-	{
-		synchronized( entension_handlers ){
-		
-			entension_handlers.put( id, message_id );
-		}
+	{		
+		extension_handlers.put( id, message_id );
+	}
+	
+	public void
+	removeExtensionHandler(
+		byte		id )
+	{		
+		extension_handlers.remove( id );
 	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageEncoder.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageEncoder.java
index 7c84923..2fc37e9 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageEncoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageEncoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 Sep 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.messaging.bittorrent.ltep;
 
@@ -127,16 +124,78 @@ public class LTMessageEncoder implements MessageStreamEncoder {
 	}
 	
 	public boolean supportsUTPEX() {
-		if (this.extension_map == null) {return false;}
-		Number num = (Number)this.extension_map.get("ut_pex");
-		
-		return( num != null && num.intValue() != 0 );
+		return( supportsExtension("ut_pex"));
 	}
 
 	public boolean supportsUTMetaData() {
-		if (this.extension_map == null) {return false;}
-		Number num = (Number)this.extension_map.get("ut_metadata");
+		return( supportsExtension("ut_metadata"));
+	}
+	
+	public boolean
+	supportsExtension(
+		String		extension_name )
+	{
+		if (extension_map == null) {return false;}
+		
+		Number num = (Number)this.extension_map.get( extension_name );
 		
 		return( num != null && num.intValue() != 0 );
 	}
+	
+	public static final int	CET_PEX	= 1;
+	
+	private Map<Integer,CustomExtensionHandler>		custom_handlers;
+	
+	public void
+	addCustomExtensionHandler(
+		int							extension_type,
+		CustomExtensionHandler		handler )
+	{
+		if ( custom_handlers == null ){
+			
+			custom_handlers = new HashMap<Integer, LTMessageEncoder.CustomExtensionHandler>();
+		}
+		
+		custom_handlers.put( extension_type, handler );
+	}
+	
+	public boolean
+	hasCustomExtensionHandler(
+		int		extension_type )
+	{
+		if ( custom_handlers == null ){
+			
+			return( false );
+		}
+		
+		return( custom_handlers.containsKey( extension_type ));
+	}
+	
+	public Object
+	handleCustomExtension(
+		int			extension_type,
+		Object[]	args )
+	{
+		if ( custom_handlers == null ){
+			
+			return( null );
+		}
+		
+		CustomExtensionHandler handler = custom_handlers.get( extension_type );
+		
+		if ( handler != null ){
+			
+			return( handler.handleExtension(args));
+		}
+		
+		return( null );
+	}
+	
+	public interface
+	CustomExtensionHandler
+	{
+		public Object
+		handleExtension(
+			Object[]	args );
+	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageFactory.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageFactory.java
index b64ff47..3b215fb 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/LTMessageFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 Sep 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.messaging.bittorrent.ltep;
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTMetaData.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTMetaData.java
index 39965c4..66b836a 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTMetaData.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTMetaData.java
@@ -2,20 +2,19 @@
  * Created on Mar 7, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTPeerExchange.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTPeerExchange.java
index 5a131cf..129f9ba 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTPeerExchange.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTPeerExchange.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18 Sep 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.messaging.bittorrent.ltep;
 
@@ -25,6 +22,8 @@ import java.util.*;
 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.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.DirectByteBuffer;
 
 import com.aelitis.azureus.core.networkmanager.NetworkManager;
@@ -99,7 +98,9 @@ public class UTPeerExchange implements AZStylePeerExchange, LTMessage {
 	      for (int i=0; i<peers.size(); i++ ) {
 	    	  peer = (PeerItem)peers.get(i);
 	    	  byte[] serialised_peer = peer.getSerialization();
-	    	  if (serialised_peer.length != peer_byte_size) {System.out.println("> " + serialised_peer.length + ":" + peer_byte_size);}
+	    	  if (serialised_peer.length != peer_byte_size) {
+	    		  Debug.out("invalid serialization- " + serialised_peer.length + ":" + peer_byte_size);
+	    	  }
 	    	  System.arraycopy(serialised_peer, 0, raw_peers, i * peer_byte_size, peer_byte_size);
 	    	  if (peer_flags != null && NetworkManager.getCryptoRequired(peer.getCryptoLevel())) {
 	    		  peer_flags[i] |= 0x01; // Encrypted connection. 
@@ -156,7 +157,7 @@ public class UTPeerExchange implements AZStylePeerExchange, LTMessage {
 	    		  continue;
 	    	  
 	    	  try {
-	    		  PeerItem peer = PeerItemFactory.createPeerItem(full_address, PeerItemFactory.PEER_SOURCE_PEER_EXCHANGE, type, 0);
+	    		  PeerItem peer = PeerItemFactory.createPeerItem(full_address, PeerItemFactory.PEER_SOURCE_PEER_EXCHANGE, type, 0, AENetworkClassifier.AT_PUBLIC);
 	    		  peers.add(peer);
 	    	  }
 	    	  catch (Exception e) {
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTUploadOnly.java b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTUploadOnly.java
index 758bcfa..d930478 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTUploadOnly.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/messaging/bittorrent/ltep/UTUploadOnly.java
@@ -2,20 +2,19 @@
  * Created on Mar 7, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATInitiator.java b/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATInitiator.java
index 633c237..1552351 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATInitiator.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATInitiator.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATTraversalAdapter.java b/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATTraversalAdapter.java
index 1bb4516..3aed50e 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATTraversalAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATTraversalAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATTraverser.java b/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATTraverser.java
index f0fe63b..a4c86dc 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATTraverser.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/nat/PeerNATTraverser.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerDatabase.java b/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerDatabase.java
index fcfd1dc..69c418f 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerDatabase.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerDatabase.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 26, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -46,7 +43,27 @@ public class PeerDatabase {
   private long start_time = SystemTime.getMonotonousTime();
   
   private final HashMap peer_connections = new HashMap();
-  private final LinkedHashSet<PeerItem> discovered_peers = new LinkedHashSet<PeerItem>();
+  
+  private final TreeSet<PeerItem> discovered_peers = 
+		 new TreeSet<PeerItem>(
+			new Comparator<PeerItem>()
+			{
+				public int 
+				compare(
+					PeerItem o1, 
+					PeerItem o2 ) 
+				{
+					long res = o2.getPriority() - o1.getPriority();
+					
+					if ( res == 0 ){
+						
+						res = o1.compareTo( o2 );
+					}
+					
+					return( res<0?-1:(res>0?1:0 ));
+				}
+			});
+  
   private final AEMonitor map_mon = new AEMonitor( "PeerDatabase" );
   
   private PeerItem[] cached_peer_popularities = null;
@@ -276,7 +293,16 @@ public class PeerDatabase {
    * @return peer to connect, or null of no optimistic peer available
    */
   public PeerItem getNextOptimisticConnectPeer( ) {
-	  return(getNextOptimisticConnectPeer(0));
+	  PeerItem item = getNextOptimisticConnectPeer(0);
+	  
+	  /*
+	  if ( item != null ){
+		  
+		 System.out.println( "pri: " + item.getPriority());
+	  }
+	  */
+	  
+	  return( item );
   }
   
   private PeerItem getNextOptimisticConnectPeer( final int recursion_count ) {
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerDatabaseFactory.java b/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerDatabaseFactory.java
index 73dca1e..e0b4f0b 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerDatabaseFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerDatabaseFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 27, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerExchangerItem.java b/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerExchangerItem.java
index 935e7f6..d05247a 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerExchangerItem.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerExchangerItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 27, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -37,8 +34,10 @@ public class PeerExchangerItem {
   private static final int MAX_KNOWN_PER_PEER = 500;
   
   
-  private final PeerDatabase parent_db;
-  private final PeerItem base_peer;
+  private final PeerDatabase 	parent_db;
+  private final PeerItem 		base_peer;
+  private final String			network;
+  
   private final LinkedHashSet<PeerItem> connections_added 		= new LinkedHashSet<PeerItem>();
   private final LinkedHashSet<PeerItem> connections_dropped 	= new LinkedHashSet<PeerItem>();
   private final Map<PeerItem,Object> connected_peers = new LightHashMap<PeerItem,Object>();
@@ -49,8 +48,10 @@ public class PeerExchangerItem {
 
   protected PeerExchangerItem( PeerDatabase parent_db, PeerItem peer, Helper helper ) {
     this.parent_db = parent_db;
-    this.base_peer = peer;
+    this.base_peer = peer;    
     this.helper = helper;
+    
+    network = peer.getNetwork();
   }
   
 
@@ -136,6 +137,7 @@ public class PeerExchangerItem {
    * Get the list of peer connections added since this method was last called.
    * @return new peer connections
    */
+  
   public PeerItem[] getNewlyAddedPeerConnections() {
     try{  peers_mon.enter();
       if( connections_added.isEmpty() )  return null;
@@ -156,7 +158,50 @@ public class PeerExchangerItem {
     finally{  peers_mon.exit();  }
   }
   
-
+  public PeerItem[] 
+  getNewlyAddedPeerConnections( 
+	  String network ) 
+  {
+	  try{  
+		  peers_mon.enter();
+		  
+		  if ( connections_added.isEmpty())  return null;
+	
+		  int num_to_send = connections_added.size() > MAX_PEERS_PER_VOLLEY ? MAX_PEERS_PER_VOLLEY : connections_added.size();
+	
+		  List<PeerItem> peers = new ArrayList<PeerItem>( num_to_send );
+	
+		  Iterator<PeerItem> it = connections_added.iterator();
+	
+		  while( peers.size() < num_to_send && it.hasNext()){
+	
+			  PeerItem	peer = it.next();
+	
+			  if ( peer.getNetwork() == network ){
+	
+				  peers.add( peer );
+			  }
+				
+			  	// throw away items that don't match this network to prevent them from building
+			  	// up and filling the cache preventing addition of other network items. This 
+			  	// could be improved by either maintaining separate caches per network or perhaps
+			  	// only trashing non-network entries when cache gets (near to)full
+			  
+			  it.remove();
+		  }
+	
+		  if ( peers.size() == 0 ){
+			  
+			  return( null );
+		  }
+		  
+		  return peers.toArray( new PeerItem[peers.size()]);
+		  
+	  }finally{
+		  
+		  peers_mon.exit();  
+	  }
+  }
   
   /**
    * Get the list of peer connections dropped since this method was last called.
@@ -181,6 +226,47 @@ public class PeerExchangerItem {
     finally{  peers_mon.exit();  }
   }
   
+  public PeerItem[] 
+  getNewlyDroppedPeerConnections( 
+	  String network ) 
+  {
+	  try{  
+		  peers_mon.enter();
+		  
+		  if ( connections_dropped.isEmpty())  return null;
+	
+		  int num_to_send = connections_dropped.size() > MAX_PEERS_PER_VOLLEY ? MAX_PEERS_PER_VOLLEY : connections_dropped.size();
+	
+		  List<PeerItem> peers = new ArrayList<PeerItem>( num_to_send );
+	
+		  Iterator<PeerItem> it = connections_dropped.iterator();
+	
+		  while( peers.size() < num_to_send && it.hasNext()){
+	
+			  PeerItem	peer = it.next();
+	
+			  if ( peer.getNetwork() == network ){
+	
+				  peers.add( peer );
+			  }
+			  
+			  	// see above comment
+			  
+			  it.remove();
+		  }
+	
+		  if ( peers.size() == 0 ){
+			  
+			  return( null );
+		  }
+		  
+		  return peers.toArray( new PeerItem[peers.size()]);
+		  
+	  }finally{
+		  
+		  peers_mon.exit();  
+	  }
+  }
 
   /**
    * Clears all current peer state records and stops any future state maintenance.
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerItem.java b/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerItem.java
index 72fa2d5..bf99b4e 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerItem.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 26, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,19 +14,19 @@
  * 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.peermanager.peerdb;
 
+import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
 
 import org.gudy.azureus2.core3.peer.PEPeerSource;
+import org.gudy.azureus2.core3.peer.util.PeerUtils;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.plugins.peers.PeerDescriptor;
 
 
@@ -45,18 +45,30 @@ public class PeerItem implements PeerDescriptor {
   private final byte crypto_level;
   private final short up_speed;
   
+  private final int		priority;
+  private final String	network;
+  
   protected PeerItem( String _address, int _tcp_port, byte _source, byte _handshake, int _udp_port, byte _crypto_level, int _up_speed  ) {
     byte[] raw;
+    network = AENetworkClassifier.categoriseAddress( _address );
     try{
-      //see if we can resolve the address into a compact raw IPv4/6 byte array (4 or 16 bytes)
-      InetAddress ip = InetAddress.getByName( _address );
-      raw = ip.getAddress();
-    }
-    catch( UnknownHostException e ) {
-      //not a standard IPv4/6 address, so just use the full string bytes
-      raw = _address.getBytes();
+	    if ( network == AENetworkClassifier.AT_PUBLIC ){
+		    try{
+		      //see if we can resolve the address into a compact raw IPv4/6 byte array (4 or 16 bytes)
+		      InetAddress ip = InetAddress.getByName( _address );
+		      raw = ip.getAddress();
+		    }
+		    catch( UnknownHostException e ) {
+		      //not a standard IPv4/6 address, so just use the full string bytes
+		      raw = _address.getBytes( "ISO8859-1" );
+		    }
+	    }else{
+	    	raw = _address.getBytes( "ISO8859-1" );
+	    }
+    }catch( UnsupportedEncodingException e ){
+    	raw = _address.getBytes();
     }
-
+    
     address = raw;
     tcp_port = (short)_tcp_port;
     udp_port = (short)_udp_port;
@@ -65,10 +77,12 @@ public class PeerItem implements PeerDescriptor {
     handshake = _handshake;
     crypto_level = _crypto_level;
     up_speed = (short)_up_speed;
+    
+    priority = PeerUtils.getPeerPriority( address, tcp_port );
   }
   
 
-  protected PeerItem( byte[] _serialization, byte _source, byte _handshake, int _udp_port ) throws Exception{
+  protected PeerItem( byte[] _serialization, byte _source, byte _handshake, int _udp_port, String _network ) throws Exception{
 	if ( _serialization.length < 6 || _serialization.length > 32){
 		throw( new Exception( "PeerItem: invalid serialisation length - " + _serialization.length ));
 	}
@@ -86,6 +100,10 @@ public class PeerItem implements PeerDescriptor {
     udp_port = (short)_udp_port;
     crypto_level = PeerItemFactory.CRYPTO_LEVEL_1;	// TODO: serialise this...
     up_speed = 0; // TODO:...
+    
+    priority = PeerUtils.getPeerPriority( address, tcp_port );
+    
+    network	= _network;
   }
     
   
@@ -101,21 +119,27 @@ public class PeerItem implements PeerDescriptor {
   
   
   public String getAddressString() {
-    try{
-      //see if it's an IPv4/6 address (4 or 16 bytes)
-      return InetAddress.getByAddress( address ).getHostAddress();
-    }
-    catch( UnknownHostException e ) {
-      //not a standard IPv4/6 address, so just return as full string
-      return new String( address );
-    }
+	try{
+		if ( network == AENetworkClassifier.AT_PUBLIC ){
+		    try{
+		      //see if it's an IPv4/6 address (4 or 16 bytes)
+		      return InetAddress.getByAddress( address ).getHostAddress();
+		    }
+		    catch( UnknownHostException e ) {
+		      //not a standard IPv4/6 address, so just return as full string
+		      return new String( address, "ISO8859-1" );
+		    }
+		}else{
+			 return new String( address, "ISO8859-1" );
+		}
+	}catch( UnsupportedEncodingException e ){
+		return( new String( address ));
+	}
   }
   
-  public String
-  getIP()
-  {
-	  return( getAddressString());
-  }
+  public String getIP(){ return( getAddressString());  }
+  
+  public String getNetwork(){ return( network ); }
   
   public int getTCPPort() {  return tcp_port&0xffff;  }
   
@@ -145,7 +169,39 @@ public class PeerItem implements PeerDescriptor {
   
   public int hashCode() {  return hashcode;  }
   
+  public int 
+  compareTo(
+	PeerItem	other )
+  {
+	  int res = tcp_port - other.tcp_port;
+	  
+	  if  ( res == 0 ){
+		  
+		  res = udp_port - other.udp_port;
+	  
+		  if ( res == 0 ){
+		  	  
+			  res = address.length - other.address.length;
+	  
+			  if ( res == 0 ){
+				
+				  for ( int i=0;i<address.length;i++){
+					  
+					  res = address[i] - other.address[i];
+					  
+					  if ( res != 0 ){
+						  
+						  break;
+					  }
+				  }
+			  }
+		  }
+	  }
+	  
+	  return( res );
+  }
   
+  public long getPriority(){ return priority&0xffffffffL; }
   
   public static String convertSourceString( byte source_id ) {
     //we use an int to store the source text string as this class is supposed to be lightweight
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerItemFactory.java b/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerItemFactory.java
index 1cefd7c..9d9111a 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerItemFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/peerdb/PeerItemFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 27, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -70,8 +67,8 @@ public class PeerItemFactory {
    * @param source this peer info was obtained from
    * @return peer
    */
-  public static PeerItem createPeerItem( byte[] serialization, byte source, byte handshake_type, int udp_port ) throws Exception {
-    return (PeerItem)StringInterner.internObject( new PeerItem( serialization, source, handshake_type, udp_port ) );
+  public static PeerItem createPeerItem( byte[] serialization, byte source, byte handshake_type, int udp_port, String network ) throws Exception {
+    return (PeerItem)StringInterner.internObject( new PeerItem( serialization, source, handshake_type, udp_port, network ) );
   }
   
   
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/EndGameModeChunk.java b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/EndGameModeChunk.java
index 0b8a49d..5f2c24b 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/EndGameModeChunk.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/EndGameModeChunk.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePicker.java b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePicker.java
index aa14c46..bcf7359 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePicker.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePicker.java
@@ -1,7 +1,7 @@
 /*
  * Created by Joseph Bridgewater
  * Created on Jan 2, 2006
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePickerFactory.java b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePickerFactory.java
index 1386588..09d2d54 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePickerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePickerFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created by Joseph Bridgewater
  * Created on Jan 2, 2006
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePickerListener.java b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePickerListener.java
index aff6702..b85b844 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePickerListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePickerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePriorityProvider.java b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePriorityProvider.java
index 02763ab..63880f6 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePriorityProvider.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PiecePriorityProvider.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PieceRTAProvider.java b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PieceRTAProvider.java
index b2f5775..c53903a 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PieceRTAProvider.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/PieceRTAProvider.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 May 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/impl/PiecePickerImpl.java b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/impl/PiecePickerImpl.java
index c94227a..dff31be 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/impl/PiecePickerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/impl/PiecePickerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created by Joseph Bridgewater
  * Created on Jan 2, 2006
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -2859,7 +2856,7 @@ implements PiecePicker
 	 * and attach/detach listeners to them
 	 */
 	private class PEPeerManagerListenerImpl
-	implements PEPeerManagerListener
+	extends PEPeerManagerListenerAdapter
 	{
 		public final void peerAdded(final PEPeerManager manager, PEPeer peer )
 		{
@@ -2879,37 +2876,6 @@ implements PiecePicker
 			final PEPeerListenerImpl peerListener =(PEPeerListenerImpl)peerListeners.remove(peer);
 			peer.removeListener(peerListener);
 		}
-
-		public void peerDiscovered(PEPeerManager manager, PeerItem peer, PEPeer finder) {
-		}
-		
-		public void 
-		pieceAdded( 
-			PEPeerManager 	manager, 
-			PEPiece 		piece, 
-			PEPeer 			for_peer )
-		{
-		}
-		  
-		public void 
-		pieceRemoved( 
-			PEPeerManager 	manager, 
-			PEPiece 		piece )
-		{
-		}
-		
-		public void 
-		peerSentBadData(
-			PEPeerManager 	manager,
-			PEPeer 			peer, 
-			int 			pieceNumber) 
-		{							
-		}
-		
-		public void
-		destroyed()
-		{		
-		}
 	}
 
 	/**
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/util/BitFlags.java b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/util/BitFlags.java
index 2914990..8de1c56 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/util/BitFlags.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/piecepicker/util/BitFlags.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 30, 2005
  * Created by Joseph Bridgewater
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/DownloadingUnchoker.java b/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/DownloadingUnchoker.java
index a87a779..a5286cd 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/DownloadingUnchoker.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/DownloadingUnchoker.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 5, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -74,7 +71,7 @@ public class DownloadingUnchoker implements Unchoker {
   
   
 
-  public void calculateUnchokes( int max_to_unchoke, ArrayList<PEPeer> all_peers, boolean force_refresh, boolean check_priority_connections ) {
+  public void calculateUnchokes( int max_to_unchoke, ArrayList<PEPeer> all_peers, boolean force_refresh, boolean check_priority_connections, boolean do_high_latency_peers ) {
     int max_optimistic = ((max_to_unchoke - 1) / 10) + 1;  //one optimistic unchoke for every 10 upload slots
     
     ArrayList<PEPeer> optimistic_unchokes = new ArrayList<PEPeer>();
@@ -198,6 +195,10 @@ public class DownloadingUnchoker implements Unchoker {
       }
     }
 
+    if ( do_high_latency_peers ){
+    	
+    	UnchokerUtil.doHighLatencyPeers( chokes, unchokes, true );
+    }
   }
   
   
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/SeedingUnchoker.java b/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/SeedingUnchoker.java
index 593d95d..094990d 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/SeedingUnchoker.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/SeedingUnchoker.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 5, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -89,7 +86,7 @@ public class SeedingUnchoker implements Unchoker {
   
   
 
-  public void calculateUnchokes( int max_to_unchoke, ArrayList<PEPeer> all_peers, boolean force_refresh, boolean check_priority_connections ) {
+  public void calculateUnchokes( int max_to_unchoke, ArrayList<PEPeer> all_peers, boolean force_refresh, boolean check_priority_connections, boolean do_high_latency_peers ) {
 	  
 	int max_optimistic = ((max_to_unchoke - 1) / 5) + 1;  //one optimistic unchoke for every 5 upload slots
 	  
@@ -195,6 +192,11 @@ public class SeedingUnchoker implements Unchoker {
     	//add Friend peers preferentially, leaving room for 1 non-friend peer for every 5 upload slots
     	setBuddyUnchokes( max_to_unchoke - max_optimistic, all_peers );
     }
+    
+    if ( do_high_latency_peers ){
+    	
+    	UnchokerUtil.doHighLatencyPeers( chokes, unchokes, false );
+    }
   }
   
   
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/Unchoker.java b/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/Unchoker.java
index 98cc86b..9df0772 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/Unchoker.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/Unchoker.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 5, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -49,7 +46,7 @@ Unchoker
    * @param all_peers list of peers to choose from
    * @param force_refresh force a refresh of optimistic unchokes
    */
-  public void calculateUnchokes( int max_to_unchoke, ArrayList<PEPeer> all_peers, boolean force_refresh, boolean check_priority_connections );
+  public void calculateUnchokes( int max_to_unchoke, ArrayList<PEPeer> all_peers, boolean force_refresh, boolean check_priority_connections, boolean do_high_latency_peers );
   
   /**
    * Get the list of peers calculated to be choked.
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/UnchokerFactory.java b/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/UnchokerFactory.java
index 430a878..6ae3e0e 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/UnchokerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/UnchokerFactory.java
@@ -2,20 +2,19 @@
  * Created on Aug 24, 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/UnchokerUtil.java b/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/UnchokerUtil.java
index 64b7f00..79ec8f5 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/UnchokerUtil.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/unchoker/UnchokerUtil.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 5, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -26,6 +23,7 @@ import java.util.*;
 
 import org.gudy.azureus2.core3.peer.PEPeer;
 import org.gudy.azureus2.core3.peer.impl.PEPeerTransport;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.RandomUtils;
 
 /**
@@ -39,8 +37,17 @@ public class UnchokerUtil {
    * @param allow_snubbed if true, ignore snubbed state
    * @return true if peer is allowed to be unchoked, false if not
    */
-  public static boolean isUnchokable( PEPeer peer, boolean allow_snubbed ) {
-    return peer.getPeerState() == PEPeer.TRANSFERING && !peer.isSeed() && !peer.isRelativeSeed() && peer.isInterested() && ( !peer.isSnubbed() || allow_snubbed );
+  public static boolean 
+  isUnchokable( 
+	PEPeer peer, 
+	boolean allow_snubbed ) 
+  {
+	  return(	peer.getPeerState() == PEPeer.TRANSFERING && 
+			  	!peer.isSeed() && 
+			  	!peer.isRelativeSeed() && 
+			  	peer.isInterested() && 
+			  	!peer.isUploadDisabled() &&
+			  	( !peer.isSnubbed() || allow_snubbed ));
   }
   
 
@@ -205,4 +212,94 @@ public class UnchokerUtil {
 		}
   }
   
+  public static void 
+  doHighLatencyPeers( 
+	 ArrayList<PEPeer> 	peers_to_choke, 
+	 ArrayList<PEPeer> 	peers_to_unchoke,
+	 boolean			allow_snubbed )
+  {
+	
+	  // when called we don't want to choke high-latency peers
+	
+	  if ( peers_to_choke.size() == 0 ){
+		  
+		  return;
+	  }
+	  
+	  //System.out.println( "doHLP: " + peers_to_choke + ", " + peers_to_unchoke );
+	  
+	  Iterator<PEPeer> choke_it = peers_to_choke.iterator();
+	  
+	  int	to_remove = 0;
+	  
+	  while( choke_it.hasNext()){
+		  
+		  PEPeer peer = choke_it.next();
+		  
+		  if ( AENetworkClassifier.categoriseAddress( peer.getIp()) != AENetworkClassifier.AT_PUBLIC ){
+			  
+			  if ( isUnchokable( peer, allow_snubbed )){
+			
+				  //System.out.println( "   removed " + peer );
+				  
+				  choke_it.remove();
+			
+				  to_remove++;
+				  
+			  }else{
+				  
+				  // it isn't unchokable so we need to choke it whatever
+			
+			  }
+		  }
+	  }
+	  
+	  	// if we've removed any chokes then we need to balance things by removing an equal number
+	  	// of unchokes
+	  
+	  if ( to_remove > 0 ){
+		  
+		  ListIterator<PEPeer> unchoke_it = peers_to_unchoke.listIterator( peers_to_unchoke.size());
+		  
+		  	// preferrably balance with high latency peers
+		  
+		  while( unchoke_it.hasPrevious()){
+			 
+			  PEPeer peer = unchoke_it.previous();
+			  
+			  if ( AENetworkClassifier.categoriseAddress( peer.getIp()) != AENetworkClassifier.AT_PUBLIC ){
+				  
+				  //System.out.println( "   balanced with " + peer );
+				  
+				  unchoke_it.remove();
+				  
+				  to_remove--;
+				  
+				  if ( to_remove == 0 ){
+					  
+					  return;
+				  }
+			  }
+		  }
+		  
+		  if ( to_remove > 0 ){
+			 
+			  unchoke_it = peers_to_unchoke.listIterator( peers_to_unchoke.size());
+			  
+			  while( unchoke_it.hasPrevious()){
+				 	
+				  PEPeer peer = unchoke_it.previous();
+				  
+				  unchoke_it.remove();
+				  
+				  to_remove--;
+				  
+				  if ( to_remove == 0 ){
+					  
+					  return;
+				  }
+			  }
+		  }
+	  }
+  }	  
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/DownloadingRanker.java b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/DownloadingRanker.java
index d1cd98d..1811613 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/DownloadingRanker.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/DownloadingRanker.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 5, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/SeedingRanker.java b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/SeedingRanker.java
index 3bfee94..689fa33 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/SeedingRanker.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/SeedingRanker.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 5, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadHelper.java b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadHelper.java
index a9f2096..6585108 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadHelper.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadHelper.java
@@ -1,7 +1,7 @@
 /*
  * Created on Mar 20, 2006
  * Created by Alon Rohter
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSession.java b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSession.java
index d88cc1a..e4ca161 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSession.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSession.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 17, 2006
  * Created by Alon Rohter
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSessionPicker.java b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSessionPicker.java
index d0623be..2d4486b 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSessionPicker.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSessionPicker.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 17, 2006
  * Created by Alon Rohter
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSlot.java b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSlot.java
index a20817c..9b688cb 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSlot.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSlot.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 15, 2006
  * Created by Alon Rohter
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSlotManager.java b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSlotManager.java
index 3f5d0d2..5fe44e8 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSlotManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/uploadslots/UploadSlotManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 15, 2006
  * Created by Alon Rohter
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/AZPeerIdentityManager.java b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/AZPeerIdentityManager.java
index d916a63..59a9f00 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/AZPeerIdentityManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/AZPeerIdentityManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 21, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoder.java b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoder.java
index 9c45577..0126543 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoder.java
@@ -2,7 +2,7 @@
  * Created on Nov 12, 2003
  * Created by Alon Rohter
  * Copyright (C) 2003-2004 Alon Rohter, All Rights Reserved.
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.peermanager.utils;
@@ -249,6 +246,11 @@ public class BTPeerIDByteDecoder {
 			if (client_with_version != null) {return client_with_version;}
 			return client;
 		}
+		
+		// Specific version of BitTorrent used "-M" with all random
+		if (peer_id_bytes[0] == '-' && peer_id_bytes[1] == 'M') {
+			return "BitTorrent 7.8.2";
+		}
 
 		client = identifyAwkwardClient(peer_id_bytes);
 		if (client != null) {return client;}
@@ -608,6 +610,12 @@ public class BTPeerIDByteDecoder {
 
 		assertDecode( "\u00B5Torrent 3.4.0", "2D55543334302D000971FDE48C3688D2023506FC" );
 		
+		assertDecode( "BitTorrent 7.9.1", "2D42543739312D00A5792226709266A467EAD700" );
+		
+		assertDecode( "Tixati 1.1.0.7", "-TX1107-811513660630" );
+		
+		assertDecode( "Torch 6.2.9.2", "-TB6292-jhBrpKfnZ!6e" );	// I know this is wrong as the real version is apparently Torch 29.0.0.6292 according to LTEP but woreva
+		
 		System.out.println("Done.");
 	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderDefinitions.java b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderDefinitions.java
index 084fc3b..e97c892 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderDefinitions.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderDefinitions.java
@@ -1,7 +1,7 @@
 /*
  * Created on 7 Jun 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.utils;
 
@@ -49,6 +46,7 @@ public class BTPeerIDByteDecoderDefinitions {
 	static String VER_AZ_THREE_DIGITS_PLUS_MNEMONIC = "1.2.3 [4]";
 	static String VER_AZ_ONE_MAJ_TWO_MIN_PLUS_MNEMONIC = "1.23 [4]";
 	static String VER_AZ_FOUR_DIGITS = "1.2.3.4";
+	static String VER_AZ_V_FOUR_DIGITS = "v1.2.3.4";
 	static String VER_AZ_TWO_MAJ_TWO_MIN = "12.34";
 	static String VER_AZ_SKIP_FIRST_ONE_MAJ_TWO_MIN = "2.34";
 	static String VER_AZ_KTORRENT_STYLE = "1.2.3=[RD].4";
@@ -257,12 +255,14 @@ public class BTPeerIDByteDecoderDefinitions {
 		addAzStyle("DE", "Deluge", VER_AZ_FOUR_DIGITS);
 		addAzStyle("EB", "EBit");
 		addAzStyle("ES", "Electric Sheep", VER_AZ_THREE_DIGITS);
+		addAzStyle("eM", "eMule", NO_VERSION); // has what looks like a 1.2.3.4 version, but 1004 != 0.60
 		addAzStyle("FC", "FileCroc");
 		addAzStyle("FG", "FlashGet", VER_AZ_SKIP_FIRST_ONE_MAJ_TWO_MIN);
 		addAzStyle("FT", "FoxTorrent/RedSwoosh");
 		addAzStyle("GR", "GetRight", "1.2");
 		addAzStyle("GS", "GSTorrent"); // TODO: Format is v"abcd"
 		addAzStyle("HL", "Halite", VER_AZ_THREE_DIGITS);
+		addAzStyle("IL", "iLivid", VER_AZ_THREE_DIGITS);
 		addAzStyle("HN", "Hydranode");
 		addAzStyle("KG", "KGet");
 		addAzStyle("KT", "KTorrent", VER_AZ_KTORRENT_STYLE);
@@ -285,7 +285,7 @@ public class BTPeerIDByteDecoderDefinitions {
 		addAzStyle("PD", "Pando");
 		addAzStyle("PE", "PeerProject");
 		addAzStyle("pX", "pHoeniX");
-		addAzStyle("qB", "qBittorrent", VER_AZ_THREE_DIGITS);
+		addAzStyle("qB", "qBittorrent", VER_AZ_THREE_ALPHANUMERIC_DIGITS);
 		addAzStyle("QD", "qqdownload");
 		addAzStyle("RT", "Retriever");
 		addAzStyle("RZ", "RezTorrent");
@@ -299,16 +299,20 @@ public class BTPeerIDByteDecoderDefinitions {
 		addAzStyle("ST", "SymTorrent", "2.34");
 		addAzStyle("st", "SharkTorrent");
 		addAzStyle("SZ", "Shareaza");
+		addAzStyle("TB", "Torch");
 		addAzStyle("TN", "Torrent.NET");
 		addAzStyle("TR", "Transmission", VER_AZ_TRANSMISSION_STYLE);
 		addAzStyle("TS", "TorrentStorm");
 		addAzStyle("TT", "TuoTu", VER_AZ_THREE_DIGITS);
+		addAzStyle("tT", "tTorrent", VER_AZ_V_FOUR_DIGITS);
+		addAzStyle("TX", "Tixati");
 		addAzStyle("UL", "uLeecher!");
 		addAzStyle("UT", "\u00B5Torrent", VER_AZ_THREE_DIGITS_PLUS_MNEMONIC);
 		addAzStyle("UM", "\u00B5Torrent Mac", VER_AZ_THREE_DIGITS_PLUS_MNEMONIC);
 		addAzStyle("WT", "Bitlet");
 		addAzStyle("WY", "FireTorrent"); // formerly Wyzo.
 		addAzStyle("VG", "\u54c7\u560E (Vagaa)", VER_AZ_FOUR_DIGITS);
+		addAzStyle("XF", "Xfplay", 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", "1.2.34");
@@ -450,6 +454,8 @@ public class BTPeerIDByteDecoderDefinitions {
 		client = addSimpleClient("\u00B5Torrent", "-UT");		// UT 3.4+
 		addVersionedClient(client, VER_BYTE_BLOCK_DOTTED_CHAR, 3);
 
+		client = addSimpleClient("BitTorrent", "-BT");		// BitTorrent 7.9.1 appeared with this: -BTnnn-
+		addVersionedClient(client, VER_BYTE_BLOCK_DOTTED_CHAR, 3);
 	}
 	
 	static class ClientData {
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderUtils.java b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderUtils.java
index 565e2f2..13ad5f7 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderUtils.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/BTPeerIDByteDecoderUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on 7 Jun 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peermanager.utils;
 
@@ -219,7 +216,8 @@ class BTPeerIDByteDecoderUtils {
 		}
 		
 		if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_FOUR_DIGITS) {
-			return intchar(a) + "." + intchar(b) + "." + intchar(c) + "." + intchar(d);
+			return decodeAlphaNumericChar(a) + "." + decodeAlphaNumericChar(b) + "."
+					+ decodeAlphaNumericChar(c) + "." + decodeAlphaNumericChar(d);
 		}
 		else if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_THREE_DIGITS ||
 				version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_THREE_DIGITS_PLUS_MNEMONIC ||
@@ -286,6 +284,9 @@ class BTPeerIDByteDecoderUtils {
 		else if (version_scheme.equals("12.3-4")) {
 			return decodeAlphaNumericChar(a) + decodeAlphaNumericChar(b) + "." + decodeAlphaNumericChar(c) + "-" + decodeAlphaNumericChar(d);
 		}
+		else if (version_scheme == BTPeerIDByteDecoderDefinitions.VER_AZ_V_FOUR_DIGITS) {
+			return "v" + decodeAzStyleVersionNumber(version_data, BTPeerIDByteDecoderDefinitions.VER_AZ_FOUR_DIGITS);
+		}
 		else {
 			throw new RuntimeException("unknown AZ style version number scheme - " + version_scheme);
 		}
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/ClientIdentifier.java b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/ClientIdentifier.java
index ea7c729..09fb972 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/ClientIdentifier.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/ClientIdentifier.java
@@ -121,7 +121,7 @@ public class ClientIdentifier {
 				  }
 			  }
 		  }
-		  
+
 		  String discrepancy_type;
 		  if (is_fake) {discrepancy_type = "fake_client";}
 		  else if (is_mismatch) {discrepancy_type = "mismatch_id";}
@@ -220,6 +220,20 @@ public class ClientIdentifier {
 			}
 		}
 		
+		if (client_type_peer.startsWith("\u8FC5\u96F7\u5728\u7EBF")
+				&& handshake_name_to_process.length() > 0
+				&& Character.isDigit(handshake_name_to_process.charAt(0))) {
+			return peer_id_name + " (" + handshake_name_to_process + ")";
+		}
+		
+			// meh, now we have Mainline and BitTorrent confusion from 7.9.2 onwards, fix here is just to do a further check on the names as they will
+			// have been 'normalised' into BitTorrent by here
+		
+		if ( peer_id_name.equals( handshake_name )){
+			
+			return( peer_id_name );
+		}
+		
 		// Can't determine what the client is.
 		return asDiscrepancy(null, peer_id_name, handshake_name, "mismatch_id", "LTEP", peer_id);
 	}
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTHaveMessageAggregator.java b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTHaveMessageAggregator.java
index 444e10e..1a9fcbe 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTHaveMessageAggregator.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTHaveMessageAggregator.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 18, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandler.java b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandler.java
index 3142c43..744b5ae 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 19, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandlerAdapter.java b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandlerAdapter.java
index 52c7eb8..6158929 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandlerAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/OutgoingBTPieceMessageHandlerAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 17, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/PeerClassifier.java b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/PeerClassifier.java
index c125339..a8d4f35 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/PeerClassifier.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/PeerClassifier.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 9, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/PeerMessageLimiter.java b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/PeerMessageLimiter.java
index 5226e94..2da5dd4 100644
--- a/azureus2/src/com/aelitis/azureus/core/peermanager/utils/PeerMessageLimiter.java
+++ b/azureus2/src/com/aelitis/azureus/core/peermanager/utils/PeerMessageLimiter.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 18, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxy.java b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxy.java
index e2bd632..804ee4d 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxy.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxy.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyAddressMapper.java b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyAddressMapper.java
index 583991c..5a0349d 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyAddressMapper.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyAddressMapper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,14 +14,13 @@
  * 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.proxy;
 
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.URL;
 
 /**
@@ -57,4 +56,21 @@ AEProxyAddressMapper
 	public URL
 	externalise(
 		URL		url );
+	
+	public PortMapping
+	registerPortMapping(
+		int		local_port,
+		String	ip );
+	
+	public InetSocketAddress
+	applyPortMapping(
+		InetAddress		address,
+		int				port );
+	
+	public interface
+	PortMapping
+	{
+		public void
+		unregister();
+	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyConnection.java b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyConnection.java
index d98d791..dda5d1b 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyConnection.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyConnectionListener.java b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyConnectionListener.java
index de19d1c..07f4aa4 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyConnectionListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyConnectionListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyException.java b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyException.java
index 2b177ad..de48c15 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyException.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyFactory.java b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyFactory.java
index 5ed870e..66a8572 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -25,10 +22,12 @@ package com.aelitis.azureus.core.proxy;
 import java.net.Proxy;
 import java.net.URL;
 import java.util.List;
+import java.util.Map;
 
 import org.gudy.azureus2.plugins.PluginInterface;
 
 import com.aelitis.azureus.core.proxy.impl.*;
+import com.aelitis.azureus.plugins.dht.DHTPluginInterface;
 
 /**
  * @author parg
@@ -64,6 +63,8 @@ AEProxyFactory
 		return( AEProxyAddressMapperImpl.getSingleton());
 	}
 	
+	public static final String PO_PEER_NETWORKS = "peer_networks";
+	
 	public static PluginProxy
 	getPluginProxy(
 		String		reason,
@@ -78,7 +79,17 @@ AEProxyFactory
 		URL			target,
 		boolean		can_wait )
 	{
-		return( AEPluginProxyHandler.getPluginProxy( reason, target, can_wait ));
+		return( getPluginProxy( reason, target, null, can_wait ));
+	}
+	
+	public static PluginProxy
+	getPluginProxy(
+		String				reason,
+		URL					target,
+		Map<String,Object>	proxy_options,
+		boolean				can_wait )
+	{
+		return( AEPluginProxyHandler.getPluginProxy( reason, target, proxy_options, can_wait ));
 	}
 	
 	public static PluginProxy
@@ -87,11 +98,21 @@ AEProxyFactory
 		String		host,
 		int			port )
 	{
-		return( AEPluginProxyHandler.getPluginProxy( reason, host, port ));
+		return( getPluginProxy( reason, host, port, null ));
 	}
 		
 	public static PluginProxy
 	getPluginProxy(
+		String				reason,
+		String				host,
+		int					port,
+		Map<String,Object>	proxy_options )
+	{
+		return( AEPluginProxyHandler.getPluginProxy( reason, host, port, proxy_options ));
+	}
+	
+	public static PluginProxy
+	getPluginProxy(
 		Proxy		proxy )
 	{
 		return( AEPluginProxyHandler.getPluginProxy( proxy ));
@@ -122,9 +143,45 @@ AEProxyFactory
 		return( AEPluginProxyHandler.getPluginHTTPProxyProviders( can_wait ));
 	}
 	
+	public static boolean
+	hasPluginProxy()
+	{
+		return( AEPluginProxyHandler.hasPluginProxy());
+	}
+	
+	public static final String	SP_HOST		= "host";
+	public static final String	SP_PORT		= "port";
+	
+	public static Map<String,Object>
+	getPluginServerProxy(
+		String					reason,
+		String					network,
+		String					server_uid,
+		Map<String,Object>		options )
+	{
+		return( AEPluginProxyHandler.getPluginServerProxy( reason, network, server_uid, options ));
+	}
+	
+	public static final String	DP_DOWNLOAD		= "download";
+	public static final String	DP_NETWORKS		= "networks";
+
+	
+	public static DHTPluginInterface
+	getPluginDHTProxy(
+		String					reason,
+		String					network,
+		Map<String,Object>		options )
+	{
+		return( AEPluginProxyHandler.getPluginDHTProxy( reason, network, options ));
+
+	}
+	
 	public interface
 	PluginProxy
 	{
+		public String
+		getTarget();
+		
 		public PluginProxy
 		getChildProxy(
 			String		reason,
@@ -163,4 +220,17 @@ AEProxyFactory
 		public void
 		destroy();
 	}
+	
+	
+	public static class
+	UnknownHostException
+		extends RuntimeException
+	{
+		public
+		UnknownHostException(
+			String	host )
+		{
+			super( host );
+		}
+	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyHandler.java b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyHandler.java
index 64b3a10..21c0e4a 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxySelector.java b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxySelector.java
index da269b6..1c96a7e 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxySelector.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxySelector.java
@@ -2,20 +2,19 @@
  * Created on Nov 1, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -37,6 +36,15 @@ AEProxySelector
 	endNoProxy();
 	
 	public Proxy
+	setProxy(
+		InetSocketAddress		address,
+		Proxy					proxy );
+	
+	public Proxy
+	removeProxy(
+		InetSocketAddress		address );
+	
+	public Proxy
 	getSOCKSProxy(
 		InetSocketAddress	proxy_address,
 		InetSocketAddress	target );
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxySelectorFactory.java b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxySelectorFactory.java
index 455da35..52d9712 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxySelectorFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxySelectorFactory.java
@@ -2,20 +2,19 @@
  * Created on Nov 1, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyState.java b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyState.java
index 61c0c0f..bf80caa 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyState.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/AEProxyState.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEPluginProxyHandler.java b/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEPluginProxyHandler.java
index 846bd16..18b9981 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEPluginProxyHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEPluginProxyHandler.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -27,15 +26,20 @@ import java.net.Proxy;
 import java.net.URL;
 import java.util.*;
 
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.AESemaphore;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.core3.util.TorrentUtils;
 import org.gudy.azureus2.core3.util.UrlUtils;
 import org.gudy.azureus2.plugins.PluginAdapter;
 import org.gudy.azureus2.plugins.PluginEvent;
 import org.gudy.azureus2.plugins.PluginEventListener;
 import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.ipc.IPCInterface;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
 
 import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
@@ -43,16 +47,31 @@ import com.aelitis.azureus.core.proxy.AEProxySelectorFactory;
 import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginHTTPProxy;
 import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
 import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.plugins.dht.DHTPluginInterface;
 
 public class 
 AEPluginProxyHandler 
 {
 	private static CopyOnWriteList<PluginInterface>		plugins = new CopyOnWriteList<PluginInterface>();
 	
-	private static final AESemaphore plugin_init_complete = new AESemaphore( "init:waiter" );
+	private static final int			plugin_init_max_wait	= 30*1000;
+	private static final AESemaphore 	plugin_init_complete 	= new AESemaphore( "init:waiter" );
+	
+	private static boolean	enable_plugin_proxies_with_socks;
 	
 	static{
 		try{
+			COConfigurationManager.addAndFireParameterListener(
+				"Proxy.SOCKS.disable.plugin.proxies",
+				new ParameterListener() {	
+					public void 
+					parameterChanged(
+						String parameterName) 
+					{
+						enable_plugin_proxies_with_socks = !COConfigurationManager.getBooleanParameter( parameterName );
+					}
+				});
+			
 			AzureusCore core = AzureusCoreFactory.getSingleton();
 			
 			PluginInterface default_pi = core.getPluginManager().getDefaultPluginInterface();
@@ -107,7 +126,9 @@ AEPluginProxyHandler
 	pluginAdded(
 		PluginInterface pi )
 	{
-		if ( pi.getPluginID().equals( "aznettor" )){
+		String pid = pi.getPluginID();
+		
+		if ( pid.equals( "aznettor" ) || pid.equals( "azneti2phelper" )){
 			
 			plugins.add( pi );
 		}
@@ -117,16 +138,120 @@ AEPluginProxyHandler
 	pluginRemoved(
 		PluginInterface pi )
 	{
-		if ( pi.getPluginID().equals( "aznettor" )){
+		String pid = pi.getPluginID();
+		
+		if ( pid.equals( "aznettor" ) || pid.equals( "azneti2phelper" )){
 			
 			plugins.remove( pi );
 		}
 	}
 	
+	private static boolean
+	waitForPlugins(
+		int		max_wait )
+	{
+		if ( PluginInitializer.isInitThread()){
+			
+			Debug.out( "Hmm, rework this" );
+		}
+		
+		return( plugin_init_complete.reserve( max_wait ));
+	}
+	
 	private static final Map<Proxy,WeakReference<PluginProxyImpl>>	proxy_map = new IdentityHashMap<Proxy,WeakReference<PluginProxyImpl>>();
 	
+	public static boolean
+	hasPluginProxyForNetwork(
+		String		network,
+		boolean		supports_data )
+	{
+		long start = SystemTime.getMonotonousTime();
+	
+		while( true ){
+			
+			long	rem = plugin_init_max_wait - ( SystemTime.getMonotonousTime() - start );
+			
+			if ( rem <= 0 ){
+				
+				return( false );
+			}
+		
+			boolean wait_complete = waitForPlugins( Math.min( (int)rem, 1000 ));
+
+			boolean result = getPluginProxyForNetwork( network, supports_data ) != null;
+				
+			if ( result || wait_complete ){
+				
+				return( result );
+			}
+		}
+	}
+	
+	private static PluginInterface
+	getPluginProxyForNetwork(
+		String		network,
+		boolean		supports_data )
+	{
+		for ( PluginInterface pi: plugins ){
+
+			String pid = pi.getPluginID();
+			
+			if ( pid.equals( "aznettor" ) && network == AENetworkClassifier.AT_TOR ){
+				
+				if ( !supports_data ){
+				
+					return( pi );
+				}
+			}
+			
+			if ( pid.equals( "azneti2phelper" ) && network == AENetworkClassifier.AT_I2P ){
+				
+				return( pi );
+			}
+		}
+		
+		return( null );
+	}
+	
+	public static boolean
+	hasPluginProxy()
+	{
+		waitForPlugins( plugin_init_max_wait );
+	
+		for ( PluginInterface pi: plugins ){
+		
+			try{
+				IPCInterface ipc = pi.getIPC();
+			
+				if ( ipc.canInvoke( "testHTTPPseudoProxy", new Object[]{ TorrentUtils.getDecentralisedEmptyURL() })){
+					
+					return( true );
+				}
+			}catch( Throwable e ){				
+			}
+		}
+
+		return( false );
+	}
+	
+	private static boolean
+	isEnabled()
+	{
+		Proxy system_proxy = AEProxySelectorFactory.getSelector().getActiveProxy();
+		
+		if ( system_proxy == null || system_proxy.equals( Proxy.NO_PROXY )){
+			
+			return( true );
+			
+		}else{
+		
+			return( enable_plugin_proxies_with_socks );
+		}
+	}
+	
 		/**
-		 * This method should NOT BE CALLED as it is in the .impl package - unfortunately the featman plugin calls it
+		 * This method should NOT BE CALLED as it is in the .impl package - unfortunately the featman plugin calls it - will be removed 
+		 * when aefeatman 1.3.2 is released
 		 * @param reason
 		 * @param target
 		 * @deprecated
@@ -138,43 +263,61 @@ AEPluginProxyHandler
 		String	reason,
 		URL		target )
 	{
-		return( getPluginProxy( reason, target, false ));
+		return( getPluginProxy( reason, target, null, false ));
 	}
 	
 	public static PluginProxyImpl
 	getPluginProxy(
-		String	reason,
-		URL		target,
-		boolean	can_wait )
-	{
-		Proxy system_proxy = AEProxySelectorFactory.getSelector().getActiveProxy();
-		
-		if ( system_proxy == null || system_proxy.equals( Proxy.NO_PROXY )){
+		String					reason,
+		URL						target,
+		Map<String,Object>		properties,
+		boolean					can_wait )
+	{		
+		if ( isEnabled()){
+	
+			String url_protocol = target.getProtocol().toLowerCase();
 			
-			if ( can_wait ){
+			if ( url_protocol.startsWith( "http" ) || url_protocol.equals( "ftp" )){
 				
-				plugin_init_complete.reserve();
-			}
-			
-			for ( PluginInterface pi: plugins ){
+				if ( can_wait ){
+					
+					waitForPlugins(0);
+				}
 				
-				try{
-					IPCInterface ipc = pi.getIPC();
+				if ( properties == null ){
 					
-					Object[] proxy_details = (Object[])ipc.invoke( "getProxy", new Object[]{ reason, target } );
+					properties = new HashMap<String, Object>();
+				}
+				
+				for ( PluginInterface pi: plugins ){
 					
-					if ( proxy_details != null ){
+					try{
+						IPCInterface ipc = pi.getIPC();
 						
-						if ( proxy_details.length == 2 ){
+						Object[] proxy_details;
 						
-								// support old plugins
+						if ( ipc.canInvoke( "getProxy", new Object[]{ reason, target, properties } )){
 							
-							proxy_details = new Object[]{ proxy_details[0], proxy_details[1], target.getHost()};
+							proxy_details = (Object[])ipc.invoke( "getProxy", new Object[]{ reason, target, properties } );
+
+						}else{
+						
+							proxy_details = (Object[])ipc.invoke( "getProxy", new Object[]{ reason, target } );
 						}
 						
-						return( new PluginProxyImpl( reason, ipc, proxy_details ));
+						if ( proxy_details != null ){
+							
+							if ( proxy_details.length == 2 ){
+							
+									// support old plugins
+								
+								proxy_details = new Object[]{ proxy_details[0], proxy_details[1], target.getHost()};
+							}
+							
+							return( new PluginProxyImpl( target.toExternalForm(), reason, ipc, properties, proxy_details ));
+						}
+					}catch( Throwable e ){				
 					}
-				}catch( Throwable e ){				
 				}
 			}
 		}
@@ -184,24 +327,37 @@ AEPluginProxyHandler
 	
 	public static PluginProxyImpl
 	getPluginProxy(
-		String		reason,
-		String		host,
-		int			port )
+		String					reason,
+		String					host,
+		int						port,
+		Map<String,Object>		properties )
 	{
-		Proxy system_proxy = AEProxySelectorFactory.getSelector().getActiveProxy();
-		
-		if ( system_proxy == null || system_proxy.equals( Proxy.NO_PROXY )){
+		if ( isEnabled()){
+			
+			if ( properties == null ){
+				
+				properties = new HashMap<String, Object>();
+			}
 			
 			for ( PluginInterface pi: plugins ){
 				
 				try{
 					IPCInterface ipc = pi.getIPC();
 					
-					Object[] proxy_details = (Object[])ipc.invoke( "getProxy", new Object[]{ reason, host, port });
+					Object[] proxy_details;
+					
+					if ( ipc.canInvoke( "getProxy", new Object[]{ reason, host, port, properties })){
+						
+						proxy_details = (Object[])ipc.invoke( "getProxy", new Object[]{ reason, host, port, properties });
+
+					}else{
+					
+						proxy_details = (Object[])ipc.invoke( "getProxy", new Object[]{ reason, host, port });
+					}
 					
 					if ( proxy_details != null ){
 						
-						return( new PluginProxyImpl( reason, ipc, proxy_details ));
+						return( new PluginProxyImpl( host + ":" + port, reason, ipc, properties, proxy_details ));
 					}
 				}catch( Throwable e ){	
 				}
@@ -236,24 +392,30 @@ AEPluginProxyHandler
 		URL			url,
 		boolean		can_wait )
 	{
-		Proxy system_proxy = AEProxySelectorFactory.getSelector().getActiveProxy();
-		
-		if ( system_proxy == null || system_proxy.equals( Proxy.NO_PROXY )){
-			
-			if ( can_wait ){
-				
-				plugin_init_complete.reserve();
-			}
+		if ( isEnabled()){
 			
-			for ( PluginInterface pi: plugins ){
-				
-				try{
-					IPCInterface ipc = pi.getIPC();
+			String url_protocol = url.getProtocol().toLowerCase();
+
+			if ( url_protocol.startsWith( "http" )){
+
+				if ( can_wait ){
 					
-					return((Boolean)ipc.invoke( "testHTTPPseudoProxy", new Object[]{ url }));
+					waitForPlugins(0);
+				}
+				
+				for ( PluginInterface pi: plugins ){
 					
-				}catch( Throwable e ){	
+					try{
+						IPCInterface ipc = pi.getIPC();
+						
+						return((Boolean)ipc.invoke( "testHTTPPseudoProxy", new Object[]{ url }));
+						
+					}catch( Throwable e ){	
+					}
 				}
+			}else{
+				
+				Debug.out( "Unsupported protocol: " + url_protocol );
 			}
 		}
 		
@@ -266,28 +428,34 @@ AEPluginProxyHandler
 		URL			url,
 		boolean		can_wait )
 	{
-		Proxy system_proxy = AEProxySelectorFactory.getSelector().getActiveProxy();
-		
-		if ( system_proxy == null || system_proxy.equals( Proxy.NO_PROXY )){
-			
-			if ( can_wait ){
-				
-				plugin_init_complete.reserve();
-			}
+		if ( isEnabled()){
 			
-			for ( PluginInterface pi: plugins ){
-				
-				try{
-					IPCInterface ipc = pi.getIPC();
+			String url_protocol = url.getProtocol().toLowerCase();
+
+			if ( url_protocol.startsWith( "http" )){
+
+				if ( can_wait ){
 					
-					Proxy proxy = (Proxy)ipc.invoke( "createHTTPPseudoProxy", new Object[]{ reason, url });
+					waitForPlugins(0);
+				}
+				
+				for ( PluginInterface pi: plugins ){
 					
-					if ( proxy != null ){
+					try{
+						IPCInterface ipc = pi.getIPC();
 						
-						return( new PluginHTTPProxyImpl( reason, ipc, proxy ));
+						Proxy proxy = (Proxy)ipc.invoke( "createHTTPPseudoProxy", new Object[]{ reason, url });
+						
+						if ( proxy != null ){
+							
+							return( new PluginHTTPProxyImpl( reason, ipc, proxy ));
+						}
+					}catch( Throwable e ){	
 					}
-				}catch( Throwable e ){	
 				}
+			}else{
+				
+				Debug.out( "Unsupported protocol: " + url_protocol );
 			}
 		}
 		
@@ -296,11 +464,11 @@ AEPluginProxyHandler
 	
 	public static List<PluginInterface>
 	getPluginHTTPProxyProviders(
-		boolean	can_wait )
+		boolean		can_wait )
 	{
 		if ( can_wait ){
 			
-			plugin_init_complete.reserve();
+			waitForPlugins(0);
 		}
 		
 		List<PluginInterface> pis = 
@@ -311,32 +479,102 @@ AEPluginProxyHandler
 		return( pis );
 	}
 	
+	public static Map<String,Object>
+	getPluginServerProxy(
+		String					reason,
+		String					network,
+		String					server_uid,
+		Map<String,Object>		options )
+	{
+		waitForPlugins( plugin_init_max_wait );
+		
+		PluginInterface pi = getPluginProxyForNetwork( network, false );
+		
+		if ( pi == null ){
+			
+			return( null );
+		}
+		
+		options = new HashMap<String,Object>( options );
+		
+		options.put( "id", server_uid );
+		
+		try{
+			IPCInterface ipc = pi.getIPC();
+			
+			Map<String,Object> reply = (Map<String,Object>)ipc.invoke( "getProxyServer", new Object[]{ reason, options });
+			
+			return( reply );
+			
+		}catch( Throwable e ){
+			
+		}
+		
+		return( null );
+	}
+	
+	public static DHTPluginInterface
+	getPluginDHTProxy(
+		String					reason,
+		String					network,
+		Map<String,Object>		options )
+	{
+		waitForPlugins( plugin_init_max_wait );
+		
+		PluginInterface pi = getPluginProxyForNetwork( network, false );
+		
+		if ( pi == null ){
+			
+			return( null );
+		}
+			
+		try{
+			IPCInterface ipc = pi.getIPC();
+			
+			DHTPluginInterface reply = (DHTPluginInterface)ipc.invoke( "getProxyDHT", new Object[]{ reason, options });
+			
+			return( reply );
+			
+		}catch( Throwable e ){
+			
+		}
+		
+		return( null );		
+	}
 
 	private static class
 	PluginProxyImpl
 		implements PluginProxy
 	{
-		private long				create_time = SystemTime.getMonotonousTime();
+		private final long					create_time = SystemTime.getMonotonousTime();
 		
-		private String				reason;
+		private final String				target;
+		private final String				reason;
 		
-		private IPCInterface		ipc;
-		private Object[]			proxy_details;
+		private final IPCInterface			ipc;
+		private final Map<String,Object>	proxy_options;
+		private final Object[]				proxy_details;
 		
 		private List<PluginProxyImpl>	children = new ArrayList<AEPluginProxyHandler.PluginProxyImpl>();
 		
 		private
 		PluginProxyImpl(
+			String				_target,
 			String				_reason,
 			IPCInterface		_ipc,
+			Map<String,Object>	_proxy_options,
 			Object[]			_proxy_details )
 		{
+			target				= _target;
 			reason				= _reason;
 			ipc					= _ipc;
+			proxy_options		= _proxy_options;
 			proxy_details		= _proxy_details;
 			
 			WeakReference<PluginProxyImpl>	my_ref = new WeakReference<PluginProxyImpl>( this );
 			
+			List<PluginProxyImpl>	removed = new ArrayList<PluginProxyImpl>();
+			
 			synchronized( proxy_map ){
 				
 				proxy_map.put( getProxy(), my_ref );
@@ -361,12 +599,25 @@ AEPluginProxyHandler
 							
 							if ( now - pp.create_time > 5*60*1000 ){
 								
+								removed.add( pp );
+								
 								it.remove();
 							}
 						}
 					}
 				}
 			}
+			
+			for ( PluginProxyImpl pp: removed ){
+				
+				pp.setOK( false );
+			}
+		}
+		
+		public String
+		getTarget()
+		{
+			return( target );
 		}
 		
 		public PluginProxy 
@@ -374,7 +625,7 @@ AEPluginProxyHandler
 			String		child_reason,
 			URL 		url) 
 		{
-			PluginProxyImpl	child = getPluginProxy( reason + " - " + child_reason, url, false );
+			PluginProxyImpl	child = getPluginProxy( reason + " - " + child_reason, url, proxy_options, false );
 			
 			if ( child != null ){
 				
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyAddressMapperImpl.java b/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyAddressMapperImpl.java
index 4a27234..c4c12a8 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyAddressMapperImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyAddressMapperImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -24,15 +21,18 @@ package com.aelitis.azureus.core.proxy.impl;
 
 import java.util.*;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.MalformedURLException;
 import java.net.URL;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.util.AEMonitor;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.ByteFormatter;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.RandomUtils;
 
+import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
 import com.aelitis.azureus.core.proxy.AEProxyAddressMapper;
 
 /**
@@ -61,7 +61,9 @@ AEProxyAddressMapperImpl
 	protected Map<String,String>		reverse_map	= new HashMap<String,String>();
 	
 	protected AEMonitor	this_mon	= new AEMonitor( "AEProxyAddressMapper" );
-			
+		
+	private Map<Integer,PortMappingImpl>	port_mappings = new HashMap<Integer,PortMappingImpl>();
+	
 	protected
 	AEProxyAddressMapperImpl()
 	{
@@ -247,4 +249,106 @@ AEProxyAddressMapperImpl
 			return( url );
 		}
 	}
+	
+	
+	public PortMapping
+	registerPortMapping(
+		int		local_port,
+		String	ip )
+	{
+		PortMappingImpl mapping = new PortMappingImpl( ip, local_port );
+		
+		synchronized( port_mappings ){
+			
+			port_mappings.put( local_port, mapping );
+		}
+		
+		return( mapping );
+	}
+	
+	public InetSocketAddress
+	applyPortMapping(
+		InetAddress		address,
+		int				port )
+	{
+		InetSocketAddress result;
+					
+		PortMappingImpl mapping;
+		
+		synchronized( port_mappings ){
+			
+			mapping = port_mappings.get( port );
+		}
+		
+		if ( mapping == null ){
+		
+			result = new InetSocketAddress( address, port );
+		
+		}else{
+
+			InetAddress bind_ip = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress();
+			
+			if ( bind_ip == null || bind_ip.isAnyLocalAddress()){
+				
+				bind_ip = null;
+			}
+			
+			if (	bind_ip == null && address.isLoopbackAddress() ||
+					bind_ip != null && bind_ip.equals( address )){
+
+				String ip = mapping.getIP();
+				
+				if ( AENetworkClassifier.categoriseAddress( ip ) == AENetworkClassifier.AT_PUBLIC ){
+					
+					result = new InetSocketAddress( ip, port );
+					
+				}else{
+					
+						// default to port 6881 here - might need to fix this up one day if this doesn't
+						// remain the sensible default
+					
+					result = InetSocketAddress.createUnresolved( ip, 6881 );
+				}
+			}else{
+				
+				result = new InetSocketAddress( address, port );
+			}
+		}
+		
+		//System.out.println( "Applying mapping: " + address + "/" + port + " -> " + result );
+		
+		return( result );
+	}
+	
+	private class
+	PortMappingImpl
+		implements PortMapping
+	{
+		private String	ip;
+		private int		port;
+		
+		private
+		PortMappingImpl(
+			String		_ip,
+			int			_port )
+		{
+			ip		= _ip;
+			port	= _port;
+		}
+		
+		private String
+		getIP()
+		{
+			return( ip );
+		}
+		
+		public void 
+		unregister() 
+		{
+			synchronized( port_mappings ){
+				
+				port_mappings.remove( port );
+			}
+		}
+	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyConnectionImpl.java b/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyConnectionImpl.java
index f04ac15..ef6245a 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyConnectionImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyConnectionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -212,23 +209,25 @@ AEProxyConnectionImpl
 				
 				}else{
 				
-					String message = reason.getMessage();
+					String message = Debug.getNestedExceptionMessage( reason );
+											
+					message = message.toLowerCase( Locale.US );
 					
-					if ( message != null ){
+					if ( 	( reason instanceof AsynchronousCloseException ) ||
+							message.contains( "closed" ) || 
+							message.contains( "aborted" ) || 
+							message.contains( "disconnected" ) || 
+							message.contains( "timeout" ) || 
+							message.contains( "timed" ) ||
+							message.contains( "refused" ) ||
+							message.contains( "unreachable" ) ||
+							message.contains( "reset" ) ||
+							message.contains( "no route" ) ||
+							message.contains( "family" ) ||		// address family not supported
+							message.contains( "key is invalid" ) ||
+							message.contains( "dns lookup" )){
 						
-						message = message.toLowerCase();
-					}
-					
-					if ( 	message != null &&
-							( 	message.contains( "closed" ) || 
-								message.contains( "aborted" ) || 
-								message.contains( "timeout" ) || 
-								message.contains( "timed" ) ||
-								message.contains( "refused" ) ||
-								message.contains( "reset" ) ||
-								message.contains( "no route" ) ||
-								message.contains( "key is invalid" ) ||
-								message.contains( "dns lookup" ))){
+							// boring
 						
 						Logger.log(new LogEvent(LOGID, "AEProxyProcessor: " + getName()	+ " failed: " + message ));
 						
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyImpl.java b/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyImpl.java
index 8eff5c0..217ce3a 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxyImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -32,11 +29,10 @@ import java.nio.channels.SocketChannel;
 
 import org.gudy.azureus2.core3.logging.*;
 import org.gudy.azureus2.core3.util.AEMonitor;
-import org.gudy.azureus2.core3.util.AEThread;
+import org.gudy.azureus2.core3.util.AEThread2;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.SystemTime;
 
-
 import com.aelitis.azureus.core.networkmanager.VirtualChannelSelector;
 import com.aelitis.azureus.core.proxy.*;
 
@@ -107,61 +103,43 @@ AEProxyImpl
 				port	= ss.getLocalPort();
 			}
 				
-			Thread connect_thread = 
-				new AEThread("AEProxy:connect.loop")
+			new AEThread2("AEProxy:connect.loop")
+			{
+				public void
+				run()
 				{
-					public void
-					runSupport()
-					{
-						selectLoop( connect_selector );
-					}
-				};
-	
-			connect_thread.setDaemon( true );
+					selectLoop( connect_selector );
+				}
+			}.start();
 	
-			connect_thread.start();
 	
-			Thread read_thread = 
-				new AEThread("AEProxy:read.loop")
+			new AEThread2("AEProxy:read.loop")
+			{
+				public void
+				run()
 				{
-					public void
-					runSupport()
-					{
-						selectLoop( read_selector );
-					}
-				};
-	
-			read_thread.setDaemon( true );
+					selectLoop( read_selector );
+				}
+			}.start();
 	
-			read_thread.start();
-			
-			Thread write_thread = 
-				new AEThread("AEProxy:write.loop")
+			new AEThread2("AEProxy:write.loop")
+			{
+				public void
+				run()
 				{
-					public void
-					runSupport()
-					{
-						selectLoop( write_selector );
-					}
-				};
-	
-			write_thread.setDaemon( true );
+					selectLoop( write_selector );
+				}
+			}.start();
 	
-			write_thread.start();
 			
-			Thread accept_thread = 
-					new AEThread("AEProxy:accept.loop")
-					{
-						public void
-						runSupport()
-						{
-							acceptLoop( ssc );
-						}
-					};
-		
-			accept_thread.setDaemon( true );
-		
-			accept_thread.start();									
+			new AEThread2("AEProxy:accept.loop")
+			{
+				public void
+				run()
+				{
+					acceptLoop( ssc );
+				}
+			}.start();						
 		
 			if (Logger.isEnabled())
 				Logger.log(new LogEvent(LOGID, "AEProxy: listener established on port "
@@ -215,8 +193,10 @@ AEProxyImpl
 				}else{
 						
 					try{
-						socket_channel.configureBlocking(false);
+						socket_channel.configureBlocking( false );
 	
+						socket_channel.socket().setTcpNoDelay( true );
+						
 					}catch( Throwable e ){
 						
 						socket_channel.close();
@@ -260,22 +240,25 @@ AEProxyImpl
 				}
 			}catch( Throwable e ){
 				
-				failed_accepts++;
-
-				if (Logger.isEnabled())
-					Logger.log(new LogEvent(LOGID, "AEProxy: listener failed on port "
-							+ port, e)); 
-			
-				if ( failed_accepts > 100 && successfull_accepts == 0 ){
-
-						// looks like its not going to work...
-						// some kind of socket problem
-					Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE,
-							LogAlert.AT_ERROR, "Network.alert.acceptfail"), new String[] {
-							"" + port, "TCP" });
-			
-					break;
-				}			
+				if ( !destroyed ){
+					
+					failed_accepts++;
+	
+					if (Logger.isEnabled())
+						Logger.log(new LogEvent(LOGID, "AEProxy: listener failed on port "
+								+ port, e)); 
+				
+					if ( failed_accepts > 100 && successfull_accepts == 0 ){
+	
+							// looks like its not going to work...
+							// some kind of socket problem
+						Logger.logTextResource(new LogAlert(LogAlert.UNREPEATABLE,
+								LogAlert.AT_ERROR, "Network.alert.acceptfail"), new String[] {
+								"" + port, "TCP" });
+				
+						break;
+					}	
+				}
 			}
 		}
 	}
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxySelectorImpl.java b/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxySelectorImpl.java
index 2b36ab0..37c0f4c 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxySelectorImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/impl/AEProxySelectorImpl.java
@@ -2,20 +2,19 @@
  * Created on Nov 1, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -25,9 +24,10 @@ import java.io.IOException;
 import java.net.*;
 import java.util.*;
 
-
 import org.gudy.azureus2.core3.config.COConfigurationListener;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.AddressUtils;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.HostNameToIPResolver;
 import org.gudy.azureus2.core3.util.SystemTime;
@@ -36,6 +36,7 @@ import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.AzureusCoreRunningListener;
 import com.aelitis.azureus.core.proxy.*;
+import com.aelitis.azureus.core.util.CopyOnWriteMap;
 import com.aelitis.azureus.core.util.DNSUtils;
 
 public class 
@@ -72,6 +73,8 @@ AEProxySelectorImpl
 	private volatile ActiveProxy		active_proxy;			
 	private volatile List<String>		alt_dns_servers	= new ArrayList<String>();
 	
+	private CopyOnWriteMap<String,List<Proxy>>	explicit_proxy_map = new CopyOnWriteMap<String, List<Proxy>>();	
+	
 	private
 	AEProxySelectorImpl()
 	{	
@@ -223,11 +226,96 @@ AEProxySelectorImpl
 		tls.set( tls.get() - 1  );
 	}
 	
+	public Proxy
+	setProxy(
+		InetSocketAddress		address,
+		Proxy					proxy )
+	{
+		List<Proxy> p = new ArrayList<Proxy>();
+		
+		p.add( proxy );
+		
+		String address_str = AddressUtils.getHostNameNoResolve( address ) + ":" + address.getPort();
+		
+		List<Proxy> old = explicit_proxy_map.put( address_str, Collections.unmodifiableList( p ));
+		
+		if ( old != null ){
+			
+			return( old.get(0));
+			
+		}else{
+			
+			return( null );
+		}
+	}
+	
+	public Proxy
+	removeProxy(
+		InetSocketAddress		address )
+	{
+		String address_str = AddressUtils.getHostNameNoResolve( address ) + ":" + address.getPort();
+
+		List<Proxy> old = explicit_proxy_map.remove( address_str );
+		
+		if ( old != null ){
+			
+			return( old.get(0));
+			
+		}else{
+			
+			return( null );
+		}
+	}
+	
 	public List<Proxy> 
 	select(
 		URI uri )
 	{	
 		List<Proxy>  result;
+
+		if ( explicit_proxy_map.size() > 0 ){
+	
+			try{
+				String	host 	= uri.getHost();
+				
+				if ( host != null ){
+					
+					int port 		= uri.getPort();
+					
+					if ( port == -1 ){
+						
+						String scheme = uri.getScheme();
+						
+						if ( scheme != null ){
+							
+							scheme = scheme.toLowerCase( Locale.US );
+						
+							if ( scheme.equals( "http" )){
+								
+								port = 80;
+								
+							}else if ( scheme.equals( "https" )){
+								
+								port = 443;
+							}
+						}
+					}
+					
+					if ( port != -1 ){
+											
+						List<Proxy> p = explicit_proxy_map.get( host + ":" + port );
+						
+						if ( p != null ){
+							
+							return( p );
+						}
+					}
+				}
+			}catch( Throwable e ){
+				
+				e.printStackTrace();
+			}
+		}
 		
 		if ( tls.get() > 0 ){
 			
@@ -236,6 +324,29 @@ AEProxySelectorImpl
 		}else{
 		
 			result = selectSupport( uri );
+			
+			String host = uri.getHost();
+			
+			if ( host != null ){
+				
+				if ( host.endsWith( ".i2p" ) || host.endsWith( ".onion" )){
+
+					List<Proxy> trimmed = new ArrayList<Proxy>( result.size());
+					
+					for ( Proxy p: result ){
+						
+						if ( p.type() != Proxy.Type.DIRECT ){
+							
+							trimmed.add( p );
+						}
+					}
+					
+					if ( trimmed.size() == 0 ){
+					
+						throw( new AEProxyFactory.UnknownHostException( host ));
+					}
+				}
+			}
 		}
 		
 		if ( LOG ){
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/impl/swt/AEProxySelectorSWTImpl.java b/azureus2/src/com/aelitis/azureus/core/proxy/impl/swt/AEProxySelectorSWTImpl.java
index c430532..b63a482 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/impl/swt/AEProxySelectorSWTImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/impl/swt/AEProxySelectorSWTImpl.java
@@ -2,20 +2,19 @@
  * Created on Aug 14, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -53,6 +52,7 @@ import com.aelitis.azureus.core.proxy.impl.AEProxySelectorImpl;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdater;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
 
 public class 
@@ -230,8 +230,9 @@ AEProxySelectorSWTImpl
 													UIFunctions uif = UIFunctionsManager.getUIFunctions();
 			
 													if ( uif != null ){
-			
-														uif.openView( UIFunctions.VIEW_CONFIG, "proxy" );
+														uif.getMDI().showEntryByID(
+																MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+																"proxy");
 													}
 												}
 											});
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxy.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxy.java
index fbaa7f6..3b99380 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxy.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxy.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyAddress.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyAddress.java
index 4eae188..a22ccc3 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyAddress.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyAddress.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyConnection.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyConnection.java
index 65cbcce..578a42b 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyConnection.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -40,6 +37,12 @@ AESocksProxyConnection
 	public AEProxyConnection
 	getConnection();
 	
+	public String
+	getUsername();
+	
+	public String
+	getPassword();
+	
 	public void
 	disableDNSLookups();
 	
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyFactory.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyFactory.java
index fdfa046..549b60b 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyPlugableConnection.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyPlugableConnection.java
index 73fba46..a539f22 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyPlugableConnection.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyPlugableConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyPlugableConnectionFactory.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyPlugableConnectionFactory.java
index b9948d5..51ad93c 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyPlugableConnectionFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/AESocksProxyPlugableConnectionFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyAddressImpl.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyAddressImpl.java
index 3286977..57f274a 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyAddressImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyAddressImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyConnectionImpl.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyConnectionImpl.java
index 1801b62..d590b18 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyConnectionImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyConnectionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -47,15 +44,18 @@ AESocksProxyConnectionImpl
 	private static final LogIDs LOGID = LogIDs.NET;
 	public static final boolean	TRACE	= false;
 	
-	protected AESocksProxyImpl		proxy;
-	protected AEProxyConnection		connection;
-	protected boolean				disable_dns_lookups;
+	private final AESocksProxyImpl		proxy;
+	private final AEProxyConnection		connection;
 	
-	protected SocketChannel			source_channel;
+	private boolean					disable_dns_lookups;
+	private String					username;
+	private String					password;
 	
-	protected int					socks_version;
+	private SocketChannel			source_channel;
 	
-	protected AESocksProxyPlugableConnection	plugable_connection;
+	private int						socks_version;
+	
+	private AESocksProxyPlugableConnection	plugable_connection;
 	
 	protected
 	AESocksProxyConnectionImpl(
@@ -107,6 +107,18 @@ AESocksProxyConnectionImpl
 		return( name );
 	}
 	
+	public String
+	getUsername()
+	{
+		return( username );
+	}
+	
+	public String
+	getPassword()
+	{
+		return( password );
+	}
+	
 	protected AEProxyState
 	getInitialState()
 	{
@@ -164,10 +176,10 @@ AESocksProxyConnectionImpl
 	
 		throws IOException
 	{
-		new proxyStateClose();
+		new ProxyStateClose();
 	}
 	
-	protected class
+	private class
 	proxyStateVersion
 		extends AESocksProxyState
 	{
@@ -227,7 +239,7 @@ AESocksProxyConnectionImpl
 	
 		// V4
 	
-	protected class
+	private class
 	proxyStateV4Request
 		extends AESocksProxyState
 	{
@@ -336,7 +348,7 @@ AESocksProxyConnectionImpl
 		}
 	}
 	
-	protected class
+	private class
 	proxyStateV4aRequest
 		extends AESocksProxyState
 	{
@@ -441,7 +453,7 @@ AESocksProxyConnectionImpl
 		}
 	}
 	
-	protected class
+	private class
 	proxyStateV4Reply
 		extends AESocksProxyState
 	{
@@ -496,7 +508,7 @@ AESocksProxyConnectionImpl
 	
 		// V5
 	
-	protected class
+	private class
 	proxyStateV5MethodNumber
 		extends AESocksProxyState
 	{
@@ -544,7 +556,7 @@ AESocksProxyConnectionImpl
 		}
 	}
 	
-	protected class
+	private class
 	proxyStateV5Methods
 		extends AESocksProxyState
 	{
@@ -583,52 +595,252 @@ AESocksProxyConnectionImpl
 				return( true );
 			}
 			
-				// we just ignore actual method values
+			buffer.flip();
 			
-			new proxyStateV5MethodsReply();
+			byte[] methods = new byte[ buffer.remaining()];
 			
-			return( true );
+			buffer.get( methods );
+			
+			boolean found_no_auth 	= false;
+			boolean found_user_pass	= false;
+			
+			for ( int i=0;i<methods.length;i++){
+				
+				int method = methods[i]&0xff;
+				
+				if ( method == 0 ){
+					
+					found_no_auth = true;
+					
+				}else if ( method == 2 ){
+					
+					found_user_pass = true;
+				}
+			}
+			
+			if ( found_no_auth ){
+			
+				new proxyStateV5MethodsReply( 0 );
+			
+				return( true );
+				
+			}else if ( found_user_pass ){
+					
+				new proxyStateV5MethodsReply( 2 );
+				
+				return( true );
+				
+			}else{
+				
+				throw( new IOException( "V5: No supported methods requested" ));
+			}
 		}
 	}
 	
-	protected class
+	private class
 	proxyStateV5MethodsReply
-		extends AESocksProxyState
+		extends ProxyStateWriter
 	{
 		
 		protected
-		proxyStateV5MethodsReply()
+		proxyStateV5MethodsReply(
+			int	selected_method )
 		
 			throws IOException
 		{
-			super( AESocksProxyConnectionImpl.this );
+			if ( selected_method == 0 ){
 			
-			new proxyStateV5Request();
+				new proxyStateV5Request();
+				
+			}else{
+				
+				new proxyStateV5Username();
+			}
 			
 			connection.setWriteState( this );
 			
-			buffer	= ByteBuffer.wrap(new byte[]{(byte)5,(byte)0});
+			buffer	= ByteBuffer.wrap(new byte[]{(byte)5,(byte)selected_method});
 			
 			write( source_channel );
 		}
+	}
+	
+	/*
+    +----+------+----------+------+----------+
+    |VER | ULEN |  UNAME   | PLEN |  PASSWD  |
+    +----+------+----------+------+----------+
+    | 1  |  1   | 1 to 255 |  1   | 1 to 255 |
+    +----+------+----------+------+----------+
+    */
+	
+	private class
+	proxyStateV5Username
+		extends AESocksProxyState
+	{
+		boolean	got_length	= false;
+		
+		protected
+		proxyStateV5Username()
+		{
+			super( AESocksProxyConnectionImpl.this );
+			
+			connection.setReadState( this );
+			
+			buffer	= ByteBuffer.allocate(2);
+		}
 		
 		protected boolean
-		writeSupport(
-			SocketChannel 		sc )
+		readSupport(
+			final SocketChannel 		sc )
 		
 			throws IOException
 		{
-			int len = sc.write( buffer );
+			int	len = sc.read( buffer );
+			
+			if ( len == 0 ){
+				
+				return( false );
+				
+			}else if ( len == -1 ){
+				
+				throw( new IOException( "Connection closed" ));
+			}
+			
 			
 			if ( buffer.hasRemaining()){
 				
-				connection.requestWriteSelect( sc );
+				return( true );
 			}
 			
-			return( len > 0 );
+			buffer.flip();
+			
+			if ( !got_length){
+				
+				buffer.get();		// version
+				
+				int	length = ((int)buffer.get()) & 0xff;
+				
+				buffer = ByteBuffer.allocate( length );
+				
+				got_length	= true;
+				
+			}else{
+				
+				String	user_name = "";
+				
+				while( buffer.hasRemaining()){
+				
+					user_name += (char)buffer.get();
+				}
+													
+				new proxyStateV5Password( user_name );
+			}
+			
+			return( true );
 		}
 	}
 	
+	private class
+	proxyStateV5Password
+		extends AESocksProxyState
+	{
+		private final String username;
+		
+		boolean	got_length	= false;
+		
+		protected
+		proxyStateV5Password(
+			String		_username )
+		{
+			super( AESocksProxyConnectionImpl.this );
+			
+			username = _username;
+			
+			connection.setReadState( this );
+			
+			buffer	= ByteBuffer.allocate(1);
+		}
+		
+		protected boolean
+		readSupport(
+			final SocketChannel 		sc )
+		
+			throws IOException
+		{
+			int	len = sc.read( buffer );
+			
+			if ( len == 0 ){
+				
+				return( false );
+				
+			}else if ( len == -1 ){
+				
+				throw( new IOException( "Connection closed" ));
+			}
+			
+			
+			if ( buffer.hasRemaining()){
+				
+				return( true );
+			}
+			
+			buffer.flip();
+			
+			if ( !got_length){
+				
+				int	length = ((int)buffer.get()) & 0xff;
+				
+				buffer = ByteBuffer.allocate( length );
+				
+				got_length	= true;
+				
+			}else{
+				
+				String	password = "";
+				
+				while( buffer.hasRemaining()){
+				
+					password += (char)buffer.get();
+				}
+													
+				AESocksProxyConnectionImpl.this.username	= username;
+				AESocksProxyConnectionImpl.this.password	= password;
+				
+				new proxyStateV5UsernamePasswordReply();
+			}
+			
+			return( true );
+		}
+	}
+	
+	/*
+	 +----+--------+
+     |VER | STATUS |
+     +----+--------+
+     | 1  |   1    |
+     +----+--------+
+     */
+	
+	private class
+	proxyStateV5UsernamePasswordReply
+		extends ProxyStateWriter
+	{
+		protected
+		proxyStateV5UsernamePasswordReply()
+		
+			throws IOException
+		{
+			new proxyStateV5Request();
+			
+			connection.setWriteState( this );
+			
+			buffer	= ByteBuffer.wrap(new byte[]{(byte)1,(byte)0});
+			
+			write( source_channel );
+		}
+	}
+	
+	
 	/*
     +----+-----+-------+------+----------+----------+
     |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
@@ -653,7 +865,7 @@ AESocksProxyConnectionImpl
 	             order
 	             */
 	
-	protected class
+	private class
 	proxyStateV5Request
 		extends AESocksProxyState
 	{
@@ -731,7 +943,7 @@ AESocksProxyConnectionImpl
 		}
 	}
 	
-	protected class
+	private class
 	proxyStateV5RequestIP
 		extends AESocksProxyState
 	{
@@ -783,7 +995,7 @@ AESocksProxyConnectionImpl
 		}
 	}
 	
-	protected class
+	private class
 	proxyStateV5RequestIPV6
 		extends AESocksProxyState
 	{
@@ -835,7 +1047,7 @@ AESocksProxyConnectionImpl
 		}
 	}
 	
-	protected class
+	private class
 	proxyStateV5RequestDNS
 		extends AESocksProxyState
 	{
@@ -925,7 +1137,7 @@ AESocksProxyConnectionImpl
 		}
 	}
 	
-	protected class
+	private class
 	proxyStateV5RequestPort
 		extends AESocksProxyState
 	{
@@ -1014,7 +1226,7 @@ AESocksProxyConnectionImpl
       */
 	
 	
-	protected class
+	private class
 	proxyStateV5Reply
 		extends AESocksProxyState
 	{
@@ -1061,19 +1273,15 @@ AESocksProxyConnectionImpl
 		}
 	}
 	
-	
-	protected class
+	private class
 	proxyStateV5UDPAssociateReply
-		extends AESocksProxyState
-	{
-		
+		extends ProxyStateWriter
+	{	
 		protected
 		proxyStateV5UDPAssociateReply()
 		
 			throws IOException
 		{
-			super( AESocksProxyConnectionImpl.this );
-						
 			connection.setWriteState( this );
 			
 			byte[]	addr = new byte[4];
@@ -1086,10 +1294,35 @@ AESocksProxyConnectionImpl
 					new byte[]{(byte)5,(byte)reply_state,(byte)0,(byte)1,
 								addr[0],addr[1],addr[2],addr[3],
 								(byte)((port>>8)&0xff), (byte)(port&0xff)});
-					
-			
+							
 			write( source_channel );			
 		}
+	}
+	
+	public void
+	connected()
+	
+		throws IOException
+	{
+		if ( socks_version == 4 ){
+			
+			new proxyStateV4Reply();
+			
+		}else{
+			
+			new proxyStateV5Reply();
+		}
+	}
+	
+	private class
+	ProxyStateWriter
+		extends AESocksProxyState
+	{
+		private
+		ProxyStateWriter()
+		{
+			super( AESocksProxyConnectionImpl.this );
+		}
 		
 		protected boolean
 		writeSupport(
@@ -1107,28 +1340,13 @@ AESocksProxyConnectionImpl
 			return( len > 0 );
 		}
 	}
-	public void
-	connected()
 	
-		throws IOException
-	{
-		if ( socks_version == 4 ){
-			
-			new proxyStateV4Reply();
-			
-		}else{
-			
-			new proxyStateV5Reply();
-		}
-	}
-
-	
-	protected class
-	proxyStateClose
+	private class
+	ProxyStateClose
 		extends AESocksProxyState
 	{
-		protected
-		proxyStateClose()
+		private
+		ProxyStateClose()
 		
 			throws IOException
 		{	
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyImpl.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyImpl.java
index 6ffd3c1..a49be62 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyPlugableConnectionDefault.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyPlugableConnectionDefault.java
index 96b0513..94b5236 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyPlugableConnectionDefault.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyPlugableConnectionDefault.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -184,13 +181,20 @@ AESocksProxyPlugableConnectionDefault
 	        		
 	        	}catch( IOException e ){
 	        		
-	        			// if the address is unresolved then the calculated bind address can be invalid
-	        			// (might pick an IPv6 address for example when this is unbindable). In this case
-	        			// carry on and attempt to connect as this will fail anyway
-	        		
-	        		if ( ! ( e.getMessage().contains( "not supported" ) && address.isUnresolved())){
+	        		if ( bindIP.isAnyLocalAddress()){
+	        			
+	        			// no point in moaning here about this
+	        			
+	        		}else{
 	        			
-	        			throw( e );
+		        			// if the address is unresolved then the calculated bind address can be invalid
+		        			// (might pick an IPv6 address for example when this is unbindable). In this case
+		        			// carry on and attempt to connect as this will fail anyway
+		        		
+		        		if ( ! ( e.getMessage().contains( "not supported" ) && address.isUnresolved())){
+		        			
+		        			throw( e );
+		        		}
 	        		}
 	        	}
 	        }
diff --git a/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyState.java b/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyState.java
index 063fb3f..97dba78 100644
--- a/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyState.java
+++ b/azureus2/src/com/aelitis/azureus/core/proxy/socks/impl/AESocksProxyState.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/rssgen/RSSGeneratorPlugin.java b/azureus2/src/com/aelitis/azureus/core/rssgen/RSSGeneratorPlugin.java
index da13ef5..22c8c7b 100644
--- a/azureus2/src/com/aelitis/azureus/core/rssgen/RSSGeneratorPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/core/rssgen/RSSGeneratorPlugin.java
@@ -1,295 +1,304 @@
-/*
- * 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.config.HyperlinkParameter;
-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		= "Local RSS etc.";
-	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 )
-	{
-		plugin_interface.getPluginProperties().setProperty( "plugin.version", 	"1.0" );
-		plugin_interface.getPluginProperties().setProperty( "plugin.name", 		PLUGIN_NAME );
-
-		synchronized( RSSGeneratorPlugin.class ){
-			
-			if ( loaded ){
-				
-				return;
-			}
-			
-			loaded = true;
-		}
-				
-		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 )){
-			
-			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_ENABLE, new Boolean( COConfigurationManager.getBooleanParameter( "Plugin.default.device.rss.enable", false )));
-		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" );
-	    
-	    defaults.put( WebPlugin.PR_CONFIG_MODEL_PARAMS, new String[]{ ConfigSection.SECTION_ROOT, "rss" });
-	}
-	
-	public static RSSGeneratorPlugin
-	getSingleton()
-	{
-		return( singleton );
-	}
-	
-	
-	private static Map<String,Provider>	providers = new TreeMap<String, Provider>();
-	
-	private HyperlinkParameter		test_param;
-	
-	public
-	RSSGeneratorPlugin()
-	{
-		super( defaults );		
-	}
-	
-	public String
-	getURL()
-	{
-		return( getProtocol() + "://127.0.0.1:" + getPort() + "/" );
-	}
-	
-	@Override
-	protected void
-	setupServer()
-	{
-		super.setupServer();
-		
-		if ( test_param != null ){
-		
-			test_param.setEnabled( isPluginEnabled());
-		
-			test_param.setHyperlink( getURL());
-		}
-	}
-	
-	public static void
-	registerProvider(
-		String				name,
-		Provider			provider )
-	{
-		synchronized( providers ){
-		
-			providers.put( name, provider );
-		}
-	}
-	
-	public static void
-	unregisterProvider(
-		String				name )
-	{
-		synchronized( providers ){
-		
-			providers.remove( name );
-		}
-	}
-	
-	public void
-	initialize(
-		PluginInterface		pi )
-	
-		throws PluginException
-	{
-		singleton = this;
-
-		pi.getPluginProperties().setProperty( "plugin.name", PLUGIN_NAME );
-		
-		super.initialize( pi );
-	}
-	
-	@Override
-	protected void
-	initStage(
-		int	num )
-	{
-		if ( num == 1 ){
-			
-			BasicPluginConfigModel  config = getConfigModel();
-			
-			test_param = config.addHyperlinkParameter2( "rss.internal.test.url", "" );
-			
-			test_param.setEnabled( isPluginEnabled());
-		}
-	}
-	
-	public boolean
-	generateSupport(
-		TrackerWebPageRequest		request,
-		TrackerWebPageResponse		response )
-	
-		throws IOException
-	{
-		String url = request.getURL();
-		
-		if ( url.startsWith( "/" )){
-			
-			url = url.substring( 1 );
-		}
-	
-		if ( url.length() == 0 || url.charAt(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();
-	}
-}
+/*
+ * Created on Oct 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.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.BooleanParameter;
+import org.gudy.azureus2.plugins.ui.config.ConfigSection;
+import org.gudy.azureus2.plugins.ui.config.HyperlinkParameter;
+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		= "Local RSS etc.";
+	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 )
+	{
+		plugin_interface.getPluginProperties().setProperty( "plugin.version", 	"1.0" );
+		plugin_interface.getPluginProperties().setProperty( "plugin.name", 		PLUGIN_NAME );
+
+		synchronized( RSSGeneratorPlugin.class ){
+			
+			if ( loaded ){
+				
+				return;
+			}
+			
+			loaded = true;
+		}
+				
+		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 )){
+			
+			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_ENABLE, new Boolean( COConfigurationManager.getBooleanParameter( "Plugin.default.device.rss.enable", false )));
+		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" );
+	    
+	    defaults.put( WebPlugin.PR_CONFIG_MODEL_PARAMS, new String[]{ ConfigSection.SECTION_ROOT, "rss" });
+	}
+	
+	public static RSSGeneratorPlugin
+	getSingleton()
+	{
+		return( singleton );
+	}
+	
+	
+	private static Map<String,Provider>	providers = new TreeMap<String, Provider>();
+	
+	private HyperlinkParameter		test_param;
+	private BooleanParameter		enable_low_noise;
+	
+	public
+	RSSGeneratorPlugin()
+	{
+		super( defaults );		
+	}
+	
+	public boolean
+	isLowNoiseEnabled()
+	{
+		return( enable_low_noise.getValue());
+	}
+	
+	public String
+	getURL()
+	{
+		return( getProtocol() + "://127.0.0.1:" + getPort() + "/" );
+	}
+	
+	@Override
+	protected void
+	setupServer()
+	{
+		super.setupServer();
+		
+		if ( test_param != null ){
+		
+			test_param.setEnabled( isPluginEnabled());
+		
+			test_param.setHyperlink( getURL());
+		}
+	}
+	
+	public static void
+	registerProvider(
+		String				name,
+		Provider			provider )
+	{
+		synchronized( providers ){
+		
+			providers.put( name, provider );
+		}
+	}
+	
+	public static void
+	unregisterProvider(
+		String				name )
+	{
+		synchronized( providers ){
+		
+			providers.remove( name );
+		}
+	}
+	
+	public void
+	initialize(
+		PluginInterface		pi )
+	
+		throws PluginException
+	{
+		singleton = this;
+
+		pi.getPluginProperties().setProperty( "plugin.name", PLUGIN_NAME );
+		
+		super.initialize( pi );
+	}
+	
+	@Override
+	protected void
+	initStage(
+		int	num )
+	{
+		if ( num == 1 ){
+			
+			BasicPluginConfigModel  config = getConfigModel();
+			
+			test_param = config.addHyperlinkParameter2( "rss.internal.test.url", "" );
+			
+			enable_low_noise = config.addBooleanParameter2( "rss.internal.enable.low.noise", "rss.internal.enable.low.noise", true );
+			
+			test_param.setEnabled( isPluginEnabled());
+		}
+	}
+	
+	public boolean
+	generateSupport(
+		TrackerWebPageRequest		request,
+		TrackerWebPageResponse		response )
+	
+		throws IOException
+	{
+		String url = request.getURL();
+		
+		if ( url.startsWith( "/" )){
+			
+			url = url.substring( 1 );
+		}
+	
+		if ( url.length() == 0 || url.charAt(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/azureus2/src/com/aelitis/azureus/core/security/CryptoECCUtils.java b/azureus2/src/com/aelitis/azureus/core/security/CryptoECCUtils.java
index 4dc2faa..f17ff7f 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/CryptoECCUtils.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/CryptoECCUtils.java
@@ -1,174 +1,173 @@
-/*
- * Created on Jul 12, 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.core.security;
-
-import java.math.BigInteger;
-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.Signature;
-import java.security.spec.KeySpec;
-
-import org.bouncycastle.jce.ECNamedCurveTable;
-import org.bouncycastle.jce.interfaces.ECPrivateKey;
-import org.bouncycastle.jce.interfaces.ECPublicKey;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-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.math.ec.ECPoint;
-
-public class 
-CryptoECCUtils 
-{
-	private static final ECNamedCurveParameterSpec ECCparam = ECNamedCurveTable.getParameterSpec("prime192v2");
-
-	public static KeyPair 
-	createKeys()
-	
-		throws CryptoManagerException
-	{
-		try
-		{
-			KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA", BouncyCastleProvider.PROVIDER_NAME);
-			
-			keyGen.initialize(ECCparam);
-
-			return keyGen.genKeyPair();
-			
-		}catch(Throwable e){
-			
-			throw( new CryptoManagerException( "Failed to create keys", e ));
-		}
-	}
-	
-	public static Signature 
-	getSignature(
-		Key key )
-	
-		throws CryptoManagerException
-	{
-		try
-		{
-			Signature ECCsig = Signature.getInstance("SHA1withECDSA", BouncyCastleProvider.PROVIDER_NAME);
-			
-			if( key instanceof ECPrivateKey ){
-				
-				ECCsig.initSign((ECPrivateKey)key);
-				
-			}else if( key instanceof ECPublicKey ){
-				
-				ECCsig.initVerify((ECPublicKey)key);
-
-			}else{
-				
-				throw new CryptoManagerException("Invalid Key Type, ECC keys required");
-			}
-			
-			return ECCsig;
-			
-		}catch( CryptoManagerException e ){
-		
-			throw( e );
-			
-		}catch( Throwable e ){
-			
-			throw( new CryptoManagerException( "Failed to create Signature", e ));
-		}
-	}
-
-	public static byte[] 
-   	keyToRawdata( 
-   		PrivateKey privkey )
-   	
-   		throws CryptoManagerException
-   	{
-   		if(!(privkey instanceof ECPrivateKey)){
-   			
-   			throw( new CryptoManagerException( "Invalid private key" ));
-   		}
-   		
-   		return ((ECPrivateKey)privkey).getD().toByteArray();
-   	}
-
-	public static PrivateKey 
-   	rawdataToPrivkey(
-   		byte[] input )
-   	
-   		throws CryptoManagerException
-   	{
-   		BigInteger D = new BigInteger(input);
-   		
-   		KeySpec keyspec = new ECPrivateKeySpec(D,(ECParameterSpec)ECCparam);
-   		
-   		PrivateKey privkey = null;
-   		
-   		try{
-   			privkey = KeyFactory.getInstance("ECDSA",BouncyCastleProvider.PROVIDER_NAME).generatePrivate(keyspec);
-   			
-   			return privkey;
-   			
-   		}catch( Throwable e ){
-   	
-   			throw( new CryptoManagerException( "Failed to decode private key" ));
-   		}
-   	}
-   	
-	public static byte[] 
-   	keyToRawdata(
-   		PublicKey pubkey )
-   	
-   		throws CryptoManagerException
-   	{
-   		if(!(pubkey instanceof ECPublicKey)){
-   			
-   			throw( new CryptoManagerException( "Invalid public key" ));
-   		}
-   		
-   		return ((ECPublicKey)pubkey).getQ().getEncoded();
-   	}
-   	
-   	
-	public static  PublicKey 
-   	rawdataToPubkey(
-   		byte[] input )
-   	
-   		throws CryptoManagerException
-   	{
-   		ECPoint W = ECCparam.getCurve().decodePoint(input);
-   		
-   		KeySpec keyspec = new ECPublicKeySpec(W,(ECParameterSpec)ECCparam);
-
-   		try{
-   			
-   			return KeyFactory.getInstance("ECDSA", BouncyCastleProvider.PROVIDER_NAME).generatePublic(keyspec);
-   			
-   		}catch (Throwable e){
-   		
-   			throw( new CryptoManagerException( "Failed to decode public key", e ));
-   		}
-   	}	
-}
+/*
+ * Created on Jul 12, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.security;
+
+import java.math.BigInteger;
+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.Signature;
+import java.security.spec.KeySpec;
+
+import org.bouncycastle.jce.ECNamedCurveTable;
+import org.bouncycastle.jce.interfaces.ECPrivateKey;
+import org.bouncycastle.jce.interfaces.ECPublicKey;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+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.math.ec.ECPoint;
+
+public class 
+CryptoECCUtils 
+{
+	private static final ECNamedCurveParameterSpec ECCparam = ECNamedCurveTable.getParameterSpec("prime192v2");
+
+	public static KeyPair 
+	createKeys()
+	
+		throws CryptoManagerException
+	{
+		try
+		{
+			KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDSA", BouncyCastleProvider.PROVIDER_NAME);
+			
+			keyGen.initialize(ECCparam);
+
+			return keyGen.genKeyPair();
+			
+		}catch(Throwable e){
+			
+			throw( new CryptoManagerException( "Failed to create keys", e ));
+		}
+	}
+	
+	public static Signature 
+	getSignature(
+		Key key )
+	
+		throws CryptoManagerException
+	{
+		try
+		{
+			Signature ECCsig = Signature.getInstance("SHA1withECDSA", BouncyCastleProvider.PROVIDER_NAME);
+			
+			if( key instanceof ECPrivateKey ){
+				
+				ECCsig.initSign((ECPrivateKey)key);
+				
+			}else if( key instanceof ECPublicKey ){
+				
+				ECCsig.initVerify((ECPublicKey)key);
+
+			}else{
+				
+				throw new CryptoManagerException("Invalid Key Type, ECC keys required");
+			}
+			
+			return ECCsig;
+			
+		}catch( CryptoManagerException e ){
+		
+			throw( e );
+			
+		}catch( Throwable e ){
+			
+			throw( new CryptoManagerException( "Failed to create Signature", e ));
+		}
+	}
+
+	public static byte[] 
+   	keyToRawdata( 
+   		PrivateKey privkey )
+   	
+   		throws CryptoManagerException
+   	{
+   		if(!(privkey instanceof ECPrivateKey)){
+   			
+   			throw( new CryptoManagerException( "Invalid private key" ));
+   		}
+   		
+   		return ((ECPrivateKey)privkey).getD().toByteArray();
+   	}
+
+	public static PrivateKey 
+   	rawdataToPrivkey(
+   		byte[] input )
+   	
+   		throws CryptoManagerException
+   	{
+   		BigInteger D = new BigInteger(input);
+   		
+   		KeySpec keyspec = new ECPrivateKeySpec(D,(ECParameterSpec)ECCparam);
+   		
+   		PrivateKey privkey = null;
+   		
+   		try{
+   			privkey = KeyFactory.getInstance("ECDSA",BouncyCastleProvider.PROVIDER_NAME).generatePrivate(keyspec);
+   			
+   			return privkey;
+   			
+   		}catch( Throwable e ){
+   	
+   			throw( new CryptoManagerException( "Failed to decode private key" ));
+   		}
+   	}
+   	
+	public static byte[] 
+   	keyToRawdata(
+   		PublicKey pubkey )
+   	
+   		throws CryptoManagerException
+   	{
+   		if(!(pubkey instanceof ECPublicKey)){
+   			
+   			throw( new CryptoManagerException( "Invalid public key" ));
+   		}
+   		
+   		return ((ECPublicKey)pubkey).getQ().getEncoded();
+   	}
+   	
+   	
+	public static  PublicKey 
+   	rawdataToPubkey(
+   		byte[] input )
+   	
+   		throws CryptoManagerException
+   	{
+   		ECPoint W = ECCparam.getCurve().decodePoint(input);
+   		
+   		KeySpec keyspec = new ECPublicKeySpec(W,(ECParameterSpec)ECCparam);
+
+   		try{
+   			
+   			return KeyFactory.getInstance("ECDSA", BouncyCastleProvider.PROVIDER_NAME).generatePublic(keyspec);
+   			
+   		}catch (Throwable e){
+   		
+   			throw( new CryptoManagerException( "Failed to decode public key", e ));
+   		}
+   	}	
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/security/CryptoHandler.java b/azureus2/src/com/aelitis/azureus/core/security/CryptoHandler.java
index e606515..9ee0242 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/CryptoHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/CryptoHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,14 +14,14 @@
  * 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.security;
 
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
 public interface 
 CryptoHandler 
 {
@@ -98,6 +98,13 @@ CryptoHandler
 	
 		throws CryptoManagerException;
 
+	public CryptoSTSEngine
+	getSTSEngine(
+		PublicKey		public_key,
+		PrivateKey		private_key )
+	
+		throws CryptoManagerException;
+	
 	public byte[]
 	peekPublicKey();
 	
diff --git a/azureus2/src/com/aelitis/azureus/core/security/CryptoManager.java b/azureus2/src/com/aelitis/azureus/core/security/CryptoManager.java
index c2f80ae..a038c1c 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/CryptoManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/CryptoManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerException.java b/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerException.java
index 20980fc..f255895 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerException.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerFactory.java b/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerFactory.java
index 353a1fe..4e1218f 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerKeyListener.java b/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerKeyListener.java
index 140dd6d..bdc3709 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerKeyListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerKeyListener.java
@@ -1,34 +1,33 @@
-/*
- * Created on Mar 19, 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.core.security;
-
-public interface 
-CryptoManagerKeyListener 
-{
-	public void
-	keyChanged(
-		CryptoHandler		handler );
-	
-	public void
-	keyLockStatusChanged(
-		CryptoHandler		handler );
-}
+/*
+ * Created on Mar 19, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.security;
+
+public interface 
+CryptoManagerKeyListener 
+{
+	public void
+	keyChanged(
+		CryptoHandler		handler );
+	
+	public void
+	keyLockStatusChanged(
+		CryptoHandler		handler );
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerPasswordException.java b/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerPasswordException.java
index 1901fb3..b9925cb 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerPasswordException.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerPasswordException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerPasswordHandler.java b/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerPasswordHandler.java
index c77c2a5..26d3ef2 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerPasswordHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/CryptoManagerPasswordHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/security/CryptoSTSEngine.java b/azureus2/src/com/aelitis/azureus/core/security/CryptoSTSEngine.java
index a179d5b..aa0ca31 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/CryptoSTSEngine.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/CryptoSTSEngine.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoHandlerECC.java b/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoHandlerECC.java
index d79862e..7011008 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoHandlerECC.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoHandlerECC.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -293,6 +290,16 @@ CryptoHandlerECC
 		return( new CryptoSTSEngineImpl( getMyPublicKey(  reason, true ), getMyPrivateKey( reason )));
 	}
 	
+	public CryptoSTSEngine
+	getSTSEngine(
+		PublicKey		public_key,
+		PrivateKey		private_key )
+	
+		throws CryptoManagerException
+	{
+		return( new CryptoSTSEngineImpl( public_key, private_key ));
+	}
+	
 	public byte[]
 	peekPublicKey()
 	{
@@ -524,14 +531,14 @@ CryptoHandlerECC
 							use_method_private_key	= null;
 						}
 					}
-				}
 			
-				if ( use_method_private_key == null ){
+					if ( use_method_private_key == null ){
 					
-					throw( new CryptoManagerException( "Failed to get private key" ));
-				}
+						throw( new CryptoManagerException( "Failed to get private key" ));
+					}
 				
-				return( use_method_private_key );
+					return( use_method_private_key );
+				}
 			}
 		}finally{
 			
diff --git a/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoManagerImpl.java b/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoManagerImpl.java
index 5f11874..6fdf2fd 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoManagerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoSTSEngineImpl.java b/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoSTSEngineImpl.java
index 7a1b803..12141ef 100644
--- a/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoSTSEngineImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/security/impl/CryptoSTSEngineImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 Jun 2006
  * Created by Aaron Grunthal and Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedLimitHandler.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedLimitHandler.java
index 911f197..9d6ba60 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedLimitHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedLimitHandler.java
@@ -2,20 +2,19 @@
  * Created on Feb 3, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -49,11 +48,14 @@ import org.gudy.azureus2.core3.stats.transfer.LongTermStats;
 import org.gudy.azureus2.core3.stats.transfer.LongTermStatsListener;
 import org.gudy.azureus2.core3.stats.transfer.StatsFactory;
 import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.AERunnable;
 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.Debug;
 import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.core3.util.FrequencyLimitedDispatcher;
 import org.gudy.azureus2.core3.util.HashWrapper;
 import org.gudy.azureus2.core3.util.HostNameToIPResolver;
 import org.gudy.azureus2.core3.util.IndentWriter;
@@ -82,8 +84,11 @@ import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
 import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.networkmanager.LimitedRateGroup;
 import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagDownload;
 import com.aelitis.azureus.core.tag.TagFeature;
+import com.aelitis.azureus.core.tag.TagFeatureExecOnAssign;
 import com.aelitis.azureus.core.tag.TagFeatureRateLimit;
+import com.aelitis.azureus.core.tag.TagListener;
 import com.aelitis.azureus.core.tag.TagManager;
 import com.aelitis.azureus.core.tag.TagManagerFactory;
 import com.aelitis.azureus.core.tag.TagPeer;
@@ -100,6 +105,10 @@ SpeedLimitHandler
 {
 	private static SpeedLimitHandler		singleton;
 	
+	private static Object	RL_TO_BE_REMOVED_LOCK = new Object();
+	private static Object	RLD_TO_BE_REMOVED_KEY = new Object();
+	private static Object	RLU_TO_BE_REMOVED_KEY = new Object();
+	
 	public static SpeedLimitHandler
 	getSingleton(
 		AzureusCore		core )
@@ -191,7 +200,27 @@ SpeedLimitHandler
 		
 		loadSchedule();
 	}
+
 	
+	public boolean 
+	hasAnyProfiles() {
+		if (!COConfigurationManager.hasParameter("speed.limit.handler.state",
+				true)) {
+			return false;
+		}
+		
+		Map map = loadConfig();
+		if (map.size() == 0) {
+			return false;
+		}
+		
+		List<Map> list = (List<Map>)map.get( "profiles" );
+		if (list == null || list.size() == 0) {
+			return false;
+		}
+		return true;
+	}
+
 	private synchronized Map
 	loadConfig()
 	{
@@ -202,7 +231,11 @@ SpeedLimitHandler
 	saveConfig(
 		Map		map )
 	{
-		COConfigurationManager.setParameter( "speed.limit.handler.state", map );
+		if (map.isEmpty()) {
+			COConfigurationManager.removeParameter( "speed.limit.handler.state"); 
+		} else {
+			COConfigurationManager.setParameter( "speed.limit.handler.state", map );
+		}
 		
 		COConfigurationManager.save();
 	}
@@ -337,7 +370,7 @@ SpeedLimitHandler
 		List<String> lines = details.getString( true, false );
 		
 		lines.add( "" );
-		lines.add( "IP Sets" );
+		lines.add( "Peer Sets" );
 		if ( current_ip_sets.size() == 0 ){
 			lines.add( "    None" );
 		}else{
@@ -869,18 +902,22 @@ SpeedLimitHandler
 					
 					result.add( "'" +line + "' is invalid: use enable=(yes|no)" );
 				}
-			}else if ( lc_line.startsWith( "ip_set" )){
+			}else if ( lc_line.startsWith( "ip_set" ) || lc_line.startsWith( "peer_set" ) ){
 
 				try{
 						// uppercase here as category names are case sensitive..
 					
-					String[] args = line.substring(6).split( "," );
+					String[] args = line.substring(lc_line.indexOf('_')+4).split( "," );
 					
 					boolean	inverse 	= false;
 					int		up_lim		= -1;
 					int		down_lim	= -1;
 					
-					List<String>	categories = new ArrayList<String>();
+					int		peer_up_lim		= 0;
+					int		peer_down_lim	= 0;
+
+					
+					Set<String>	categories_or_tags = new HashSet<String>();
 					
 					IPSet set = null;
 					
@@ -912,7 +949,15 @@ SpeedLimitHandler
 								
 								down_lim = (int)parseRate( lc_rhs );
 								
-							}else if ( lc_lhs.equals( "cat" )){
+							}else if ( lc_lhs.equals( "peer_up" )){
+								
+								peer_up_lim = (int)parseRate( lc_rhs );
+								
+							}else if ( lc_lhs.equals( "peer_down" )){
+								
+								peer_down_lim = (int)parseRate( lc_rhs );
+								
+							}else if ( lc_lhs.equals( "cat" ) || lc_lhs.equals( "tag" )){
 								
 								String[] cats = rhs.split( " " );
 								
@@ -922,12 +967,7 @@ SpeedLimitHandler
 									
 									if ( cat.length() > 0 ){
 										
-										if ( categories == null ){
-											
-											categories = new ArrayList<String>();
-										}
-										
-										categories.add( cat );
+										categories_or_tags.add( cat );
 									}
 								}
 							}else{
@@ -961,9 +1001,9 @@ SpeedLimitHandler
 											
 										}else{
 											
-											if ( !set.addCIDRorCC( bit )){
+											if ( !set.addCIDRorCCetc( bit )){
 											
-												result.add( "CIDR, CC or ip_set reference '" + bit + "' isn't valid" );
+												result.add( "CIDR, CC, Network or ip_set reference '" + bit + "' isn't valid" );
 											}
 										}
 									}
@@ -977,11 +1017,11 @@ SpeedLimitHandler
 						throw( new Exception());
 					}
 					
-					set.setParameters( inverse, up_lim, down_lim, categories );
+					set.setParameters( inverse, up_lim, down_lim, peer_up_lim, peer_down_lim, categories_or_tags );
 					
 				}catch( Throwable e ){
 					
-					result.add( "'" +line + "' is invalid: use ip_set <name>=<cidrs...> [,inverse=[yes|no]] [,up=<limit>] [,down=<limit>] [,cat=<categories>]: " + e.getMessage());
+					result.add( "'" +line + "' is invalid: use ip_set <name>=<cidrs...> [,inverse=[yes|no]] [,up=<limit>] [,down=<limit>] [,peer_up=<limit>] [,peer_down=<limit>] [,cat=<categories>]: " + e.getMessage());
 				}
 			}else if ( lc_line.startsWith( "net_limit" )){
 
@@ -1119,7 +1159,7 @@ SpeedLimitHandler
 				
 				List<String>	errors = new ArrayList<String>();
 				
-				if ( bits.size() == 6 ){
+				if ( bits.size() >= 6 ){
 					
 					String	freq_str = bits.get(0).toLowerCase( Locale.US );
 					
@@ -1203,9 +1243,83 @@ SpeedLimitHandler
 						errors.add( "'to' is invalid" );
 					}
 					
+					List<ScheduleRuleExtensions>	extensions = null;
+					
+					for ( int i=6; i<bits.size(); i++ ){
+					
+							// optional extensions
+							// start_tag:<tag_name> and stop_tag
+							
+						String	extension = bits.get(i);
+						
+						String[] temp = extension.split( ":" );
+						
+						boolean	ok 		= false;
+						String	extra 	= "";
+						
+						if ( temp.length == 2 ){
+							
+							String	ext_cmd 	= temp[0];
+							String	ext_param	= temp[1];
+							
+							if ( 	ext_cmd.equals( "start_tag" ) || 
+									ext_cmd.equals( "stop_tag" )  ||
+									ext_cmd.equals( "pause_tag" ) ||
+									ext_cmd.equals( "resume_tag" )){
+								
+								TagDownload tag = (TagDownload)TagManagerFactory.getTagManager().getTagType( TagType.TT_DOWNLOAD_MANUAL ).getTag( ext_param, true );
+								
+								if ( tag == null ){
+									
+									tag = (TagDownload)TagManagerFactory.getTagManager().getTagType( TagType.TT_DOWNLOAD_STATE ).getTag( ext_param, true );
+
+								}
+								if ( tag == null ){
+									
+									extra = ", tag '" + ext_param + "' not found";
+									
+								}else{
+									
+									if ( extensions == null ){
+										
+										extensions = new ArrayList<SpeedLimitHandler.ScheduleRuleExtensions>( bits.size()-6 );
+									}
+									
+									int	et;
+									
+									if ( ext_cmd.equals( "start_tag" )){
+										
+										et = ScheduleRuleExtensions.ET_START_TAG;
+										
+									}else if ( ext_cmd.equals( "stop_tag" )){
+										
+										et = ScheduleRuleExtensions.ET_STOP_TAG;
+										
+									}else if ( ext_cmd.equals( "pause_tag" )){
+										
+										et = ScheduleRuleExtensions.ET_PAUSE_TAG;
+										
+									}else{
+										
+										et = ScheduleRuleExtensions.ET_RESUME_TAG;
+									}									
+									
+									extensions.add( new ScheduleRuleExtensions( et, tag ));
+									
+									ok = true;
+								}
+							}
+						}
+						
+						if ( !ok ){
+							
+							errors.add( "extension '" + extension + "' is invalid" + extra );
+						}
+					}
+					
 					if ( errors.size() == 0 ){
 						
-						rules.add( new ScheduleRule( freq, profile, from_mins, to_mins ));
+						rules.add( new ScheduleRule( freq, profile, from_mins, to_mins, extensions ));
 						
 					}else{
 						
@@ -1220,7 +1334,7 @@ SpeedLimitHandler
 					}
 				}else{
 					
-					result.add( "'" + line + "' is invalid: use <frequency> <profile> from <hh:mm> to <hh:mm>" );
+					result.add( "'" + line + "' is invalid: use <frequency> <profile> from <hh:mm> to <hh:mm> [extensions]*" );
 				}
 			}
 		}
@@ -1487,14 +1601,43 @@ SpeedLimitHandler
 		return( -1 );
 	}
 	
-	private DownloadManagerListener dml;
+	private DML current_dml;
+	
 	private static Object	ip_set_peer_key = new Object();
 
-	private synchronized void
+	private FrequencyLimitedDispatcher check_ip_sets_limiter = new FrequencyLimitedDispatcher(
+			new AERunnable() {
+				public void runSupport() {
+					checkIPSetsSupport();
+				}
+			}, 500 );
+
+	{
+		check_ip_sets_limiter.setSingleThreaded();
+	}
+	
+	private void
 	checkIPSets()
 	{
+		check_ip_sets_limiter.dispatch();
+	}
+	
+	private synchronized void
+	checkIPSetsSupport()
+	{
 		final org.gudy.azureus2.plugins.download.DownloadManager download_manager = plugin_interface.getDownloadManager();
 		
+			// first off kill any existing download manager listener so that any peers that
+			// may happen to to get added while we're working through this stuff don't sneak in and 
+			// get allocated to rate limiters incorrectly
+		
+		if ( current_dml != null ){
+			
+			current_dml.destroy();
+			
+			current_dml = null;
+		}
+
 		Download[] downloads = download_manager.getDownloads();
 		
 		for ( Download dm: downloads ){
@@ -1513,7 +1656,24 @@ SpeedLimitHandler
 						
 						if ( ip_set_rate_limiters_down.containsValue( l )){
 							
-							peer.removeRateLimiter( l , false );
+							synchronized( RL_TO_BE_REMOVED_LOCK ){
+								
+								List<RateLimiter> to_be_removed = (List<RateLimiter>)peer.getUserData( RLD_TO_BE_REMOVED_KEY );
+								
+								if ( to_be_removed == null ){
+									
+									to_be_removed = new ArrayList<RateLimiter>();
+									
+									peer.setUserData( RLD_TO_BE_REMOVED_KEY, to_be_removed );
+								}
+								
+								to_be_removed.add( l );	
+							}
+							
+							// defer as removing the rate limiter and then re-adding it gives time for
+							// quite a lot to happen in between
+							
+							// peer.removeRateLimiter( l , false );
 						}
 					}
 					
@@ -1523,7 +1683,21 @@ SpeedLimitHandler
 						
 						if ( ip_set_rate_limiters_up.containsValue( l )){
 							
-							peer.removeRateLimiter( l , true );
+							synchronized( RL_TO_BE_REMOVED_LOCK ){
+								
+								List<RateLimiter> to_be_removed = (List<RateLimiter>)peer.getUserData( RLU_TO_BE_REMOVED_KEY );
+								
+								if ( to_be_removed == null ){
+									
+									to_be_removed = new ArrayList<RateLimiter>();
+									
+									peer.setUserData( RLU_TO_BE_REMOVED_KEY, to_be_removed );
+								}
+								
+								to_be_removed.add( l );	
+							}
+							
+							// peer.removeRateLimiter( l , true );
 						}
 					}
 				}
@@ -1533,7 +1707,7 @@ SpeedLimitHandler
 		ip_set_rate_limiters_down.clear();
 		ip_set_rate_limiters_up.clear();
 		
-		boolean	has_cats = false;
+		boolean	has_cats_or_tags = false;
 		
 		for ( IPSet set: current_ip_sets.values()){
 			
@@ -1541,12 +1715,14 @@ SpeedLimitHandler
 			
 			ip_set_rate_limiters_up.put( set.getName(), set.getUpLimiter());
 			
-			if ( set.getCategories() != null ){
+			if ( set.getCategoriesOrTags() != null ){
 				
-				has_cats = true;
+				has_cats_or_tags = true;
 			}
+			
+			set.removeAllPeers();
 		}
-		
+				
 		if ( current_ip_sets.size() == 0 ){
 			
 			if ( ip_set_event != null ){
@@ -1556,12 +1732,6 @@ SpeedLimitHandler
 				ip_set_event = null;
 				
 			}
-			if ( dml != null ){
-				
-				download_manager.removeListener( dml );
-				
-				dml = null;
-			}
 		}else{
 			
 			if ( ip_set_event == null ){
@@ -1580,7 +1750,7 @@ SpeedLimitHandler
 							{
 								tick_count++;
 								
-								synchronized( current_ip_sets){
+								synchronized( SpeedLimitHandler.this ){
 									
 									for ( IPSet set: current_ip_sets.values()){
 										
@@ -1604,144 +1774,253 @@ SpeedLimitHandler
 							}
 						});
 			}
+						
+			current_dml = new DML( download_manager, has_cats_or_tags );
+		}
+	}
+	
+	private class
+	DML
+		implements DownloadManagerListener
+	{
+		private final Object		lock = SpeedLimitHandler.this;
+				
+		private final org.gudy.azureus2.plugins.download.DownloadManager		download_manager;
+		private final boolean													has_cats_or_tags;
+		
+		private List<Runnable>	listener_removers = new ArrayList<Runnable>();
+		
+		private volatile boolean	destroyed;
+		
+		private
+		DML(
+			org.gudy.azureus2.plugins.download.DownloadManager		_download_manager,
+			boolean													_has_cats_or_tags )
+		{
+			download_manager	= _download_manager;
+			has_cats_or_tags	= _has_cats_or_tags;
 			
-			if ( dml != null ){
+			download_manager.addListener( this, true );
+		}
+	
+		private void
+		destroy()
+		{
+			synchronized( lock ){
+				
+				destroyed	= true;
 				
-				download_manager.removeListener( dml );
+				download_manager.removeListener( this );
+				
+				for ( Runnable r: listener_removers ){
+					
+					try{
+						r.run();
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+				}
+				
+				listener_removers.clear();
 			}
+		}
 			
-			final boolean	f_has_cats = has_cats;
-			
-			dml = 
-				new DownloadManagerListener()
-				{
-					final DownloadManagerListener this_dml = this;
+		public void
+		downloadAdded(
+			final Download	download )
+		{
+			synchronized( lock ){
+				
+				if ( destroyed ){
+					
+					return;
+				}
+
+				if ( has_cats_or_tags ){
 					
+						// attribute listener
+	
 					final DownloadAttributeListener attr_listener = new
-						DownloadAttributeListener()
-						{
-							public void 
-							attributeEventOccurred(
-								Download 			download, 
-								TorrentAttribute 	attribute, 
-								int 				event_type )
+							DownloadAttributeListener()
 							{
-								if ( dml != this_dml ){
-									
-									download.removeAttributeListener( this, category_attribute, DownloadAttributeListener.WRITTEN );
-									
-									return;
+								public void 
+								attributeEventOccurred(
+									Download 			download, 
+									TorrentAttribute 	attribute, 
+									int 				event_type )
+								{
+									checkIPSets();
 								}
-								
+							};
+	
+					
+						// tag listener
+					
+					final TagType tt = TagManagerFactory.getTagManager().getTagType( TagType.TT_DOWNLOAD_MANUAL );
+					
+					final DownloadManager core_download = PluginCoreUtils.unwrap( download );
+									
+					final TagListener tag_listener = 
+						new TagListener() {
+							
+							public void 
+							taggableSync(
+								Tag tag ) 
+							{
+							}
+							
+							public void 
+							taggableRemoved(
+								Tag 		tag, 
+								Taggable 	tagged) 
+							{
+								checkIPSets();
+							}
+							
+							public void 
+							taggableAdded(
+								Tag 		tag, 
+								Taggable 	tagged) 
+							{
 								checkIPSets();
 							}
 						};
 						
-					public void
-					downloadAdded(
-						final Download	download )
-					{
-						if ( dml != this_dml ){
 							
-							download_manager.removeListener( this );
-							
-							return;
-						}
+						download.addAttributeListener( attr_listener, category_attribute, DownloadAttributeListener.WRITTEN );
 						
-						if ( f_has_cats ){
+						tt.addTagListener( core_download, tag_listener );
+
+						listener_removers.add(
+							new Runnable(){public void run(){
+								
+								download.removeAttributeListener( attr_listener, category_attribute, DownloadAttributeListener.WRITTEN );
+								
+								tt.removeTagListener( core_download, tag_listener );
+							}});
+					}				
+				
+					// peer listener
 							
-							download.addAttributeListener(
-								attr_listener,
-								category_attribute,
-								DownloadAttributeListener.WRITTEN );
-						}
+				final DownloadPeerListener	peer_listener = 
+					new DownloadPeerListener()
+					{
+						private Runnable 	pm_listener_remover;
+						
+						public void
+						peerManagerAdded(
+							final Download			download,
+							final PeerManager		peer_manager )
+						{
 							
-						download.addPeerListener(
-							new DownloadPeerListener()
-							{
-								public void
-								peerManagerAdded(
-									final Download			download,
-									final PeerManager		peer_manager )
-								{
-									if ( dml != this_dml ){
-										
-										download.removePeerListener( this );
-										
-										return;
-									}
+							synchronized( lock ){
+								
+								if ( destroyed ){
 									
-									peer_manager.addListener(
-										new PeerManagerListener2()
+									return;
+								}
+								
+								final PeerManagerListener2 listener = 
+									new PeerManagerListener2()
+									{
+										public void
+										eventOccurred(
+											PeerManagerEvent	event )
 										{
-											public void
-											eventOccurred(
-												PeerManagerEvent	event )
-											{
-												if ( dml != this_dml ){
-													
-													peer_manager.removeListener( this );
-													
-													return;
-												}
+											if ( destroyed ){
+												
+												return;
+											}
+											
+											if ( event.getType() == PeerManagerEvent.ET_PEER_ADDED ){
+												
+												peersAdded( download, peer_manager, new Peer[]{ event.getPeer() });
+												
+											}else if ( event.getType() == PeerManagerEvent.ET_PEER_REMOVED ){
 												
-												if ( event.getType() == PeerManagerEvent.ET_PEER_ADDED ){
-													
-													peersAdded( download, new Peer[]{ event.getPeer() });
-													
-												}else if ( event.getType() == PeerManagerEvent.ET_PEER_REMOVED ){
-													
-													peerRemoved( download, event.getPeer());
-												}
+												peerRemoved( download, peer_manager, event.getPeer());
 											}
-										});
+										}
+									};
+										
+								peer_manager.addListener( listener );
+								
+								pm_listener_remover =
+									new Runnable(){public void run(){
+										peer_manager.removeListener( listener );
+									}};
 									
-									Peer[] peers = peer_manager.getPeers();
-																				
-									peersAdded( download, peers );
-								}
+								listener_removers.add( pm_listener_remover );
+							}	
+						
+							Peer[] peers = peer_manager.getPeers();
+																		
+							peersAdded( download, peer_manager, peers );
+						}
+						
+						public void
+						peerManagerRemoved(
+							Download		download,
+							PeerManager		peer_manager )
+						{	
+							synchronized( lock ){
 								
-								public void
-								peerManagerRemoved(
-									Download		download,
-									PeerManager		peer_manager )
-								{						
+								if ( pm_listener_remover != null && listener_removers.contains( pm_listener_remover  )){
+									
+									pm_listener_remover.run();
+									
+									listener_removers.remove( pm_listener_remover );
 								}
-							});
-					}
-				
-						
-					public void
-					downloadRemoved(
-						Download	download )
-					{
-					}
-				};
+							}
+						}
+					};
+										
+				download.addPeerListener( peer_listener );
+					
+				listener_removers.add(
+					new Runnable(){public void run(){
+						download.removePeerListener( peer_listener );
+					}});	
+			}
+		}
+	
 			
-			download_manager.addListener( dml, true );
+		public void
+		downloadRemoved(
+			Download	download )
+		{
 		}
-	}
+	};
+
 	
 	private void
 	peersAdded(
 		Download	download,
+		PeerManager	peer_manager,
 		Peer[]		peers )
 	{
 		IPSet[]		sets;
 		long[][][]	set_ranges;
 		Set[]		set_ccs;
+		Set[]		set_nets;
 		
-		boolean	has_ccs = false;
+		boolean	has_ccs 	= false;
+		boolean	has_nets 	= false;
 		
-		String	category = null;
+		Set<String>	category_or_tags = null;
 		
-		synchronized( current_ip_sets ){
+		TagManager tm = TagManagerFactory.getTagManager();
+
+		synchronized( this ){
 			
 			int	len = current_ip_sets.size();
 			
 			sets 		= new IPSet[len];
 			set_ranges	= new long[len][][];
 			set_ccs		= new Set[len];
+			set_nets	= new Set[len];
 			
 			int	pos = 0;
 			
@@ -1750,17 +2029,37 @@ SpeedLimitHandler
 				sets[pos]		= set;
 				set_ranges[pos]	= set.getRanges();
 				set_ccs[pos]	= set.getCountryCodes();
+				set_nets[pos]	= set.getNetworks();
 				
 				if ( set_ccs[pos].size() > 0 ){
 					
 					has_ccs = true;
 				}
 				
+				if ( set_nets[pos].size() > 0 ){
+					
+					has_nets = true;
+				}
+				
 				pos++;
 				
-				if ( category == null && set.getCategories() != null ){
+				if ( category_or_tags == null && set.getCategoriesOrTags() != null ){
 				
-					category = download.getAttribute( category_attribute );
+					category_or_tags = new HashSet<String>();
+					
+					String cat = download.getAttribute( category_attribute );
+					
+					if ( cat != null && cat.length() > 0 ){
+						
+						category_or_tags.add( cat );
+					}
+					
+					List<Tag> tags = tm.getTagsForTaggable( TagType.TT_DOWNLOAD_MANUAL, PluginCoreUtils.unwrap( download ));
+					
+					for ( Tag t: tags ){
+						
+						category_or_tags.add( t.getTagName( true ));
+					}
 				}
 			}
 		}
@@ -1772,128 +2071,207 @@ SpeedLimitHandler
 		
 		for ( Peer peer: peers ){
 			
-			long[] entry = (long[])peer.getUserData( ip_set_peer_key );
-
-			long	l_address;
-
-			if ( entry == null ){
-				
-				l_address = 0;
+			List<RateLimiter>	rlu_tbr;
+			List<RateLimiter>	rld_tbr;
+			
+			synchronized( RL_TO_BE_REMOVED_LOCK ){
 				
-				String ip = peer.getIp();
+				rlu_tbr = (List<RateLimiter>)peer.getUserData( RLU_TO_BE_REMOVED_KEY );
+				rld_tbr = (List<RateLimiter>)peer.getUserData( RLD_TO_BE_REMOVED_KEY );
 				
-				if ( !ip.contains( ":" )){
-					
-					byte[] bytes = HostNameToIPResolver.hostAddressToBytes( ip );
-					
-					if ( bytes != null ){
-						
-						l_address = ((long)((bytes[0]<<24)&0xff000000 | (bytes[1] << 16)&0x00ff0000 | (bytes[2] << 8)&0x0000ff00 | bytes[3]&0x000000ff))&0xffffffffL;
-
-					}
+				if ( rlu_tbr != null ){
+					peer.setUserData( RLU_TO_BE_REMOVED_KEY, null );
+				}
+				if ( rld_tbr != null ){
+					peer.setUserData( RLD_TO_BE_REMOVED_KEY, null );
 				}
-				
-				entry = new long[]{ l_address };
-				
-				peer.setUserData( ip_set_peer_key, entry );
-				
-			}else{
-				
-				l_address = entry[0];
 			}
 			
-			String	peer_cc = null;
-			
-			if ( has_ccs ){
-				
-				String[] details = PeerUtils.getCountryDetails( peer );
-				
-				if ( details != null && details.length > 0 ){
+			try{
+				long[] entry = (long[])peer.getUserData( ip_set_peer_key );
+	
+				long	l_address;
+	
+				if ( entry == null ){
 					
-					peer_cc = details[0];
-				}	
-			}
-			
-			Set<IPSet>	added_to_sets = new HashSet<IPSet>();
-			
-			if ( l_address != 0 ){
-								
-				for ( int i=0;i<set_ranges.length;i++ ){
+					l_address = 0;
 					
-					long[][] ranges = set_ranges[i];
+					String ip = peer.getIp();
 					
-					if ( ranges.length == 0 ){
+					if ( !ip.contains( ":" )){
 						
-						continue;
+						byte[] bytes = HostNameToIPResolver.hostAddressToBytes( ip );
+						
+						if ( bytes != null ){
+							
+							l_address = ((long)((bytes[0]<<24)&0xff000000 | (bytes[1] << 16)&0x00ff0000 | (bytes[2] << 8)&0x0000ff00 | bytes[3]&0x000000ff))&0xffffffffL;
+	
+						}
 					}
 					
-					IPSet set = sets[i];
+					entry = new long[]{ l_address };
+					
+					peer.setUserData( ip_set_peer_key, entry );
+					
+				}else{
 					
-					boolean is_inverse = set.isInverse();
+					l_address = entry[0];
+				}
+				
+				String	peer_cc 	= null;
+				String 	peer_net	= null;
+				
+				if ( has_ccs ){
 					
-					List<String> set_cats = set.getCategories();
+					String[] details = PeerUtils.getCountryDetails( peer );
 					
-					if ( set_cats == null || set_cats.contains( category )){
+					if ( details != null && details.length > 0 ){
+						
+						peer_cc = details[0];
+					}	
+				}
+				
+				if ( has_nets ){
 					
-						boolean	hit = false;
+					peer_net = AENetworkClassifier.categoriseAddress( peer.getIp());
+				}
+				
+				Set<IPSet>	added_to_sets = new HashSet<IPSet>();
+				
+				if ( l_address != 0 ){
+									
+					for ( int i=0;i<set_ranges.length;i++ ){
+						
+						long[][] ranges = set_ranges[i];
 						
-						for ( long[] range: ranges ){
+						if ( ranges.length == 0 ){
 							
-							if ( l_address >= range[0] && l_address <= range[1] ){
-															
-								hit	= true;
-	
-								if ( !is_inverse ){
+							continue;
+						}
+						
+						IPSet set = sets[i];
+						
+						boolean is_inverse = set.isInverse();
+						
+						Set<String> set_cats_or_tags = set.getCategoriesOrTags();
+						
+						if ( set_cats_or_tags == null || new HashSet<String>( set_cats_or_tags ).removeAll( category_or_tags )){
+						
+							boolean	hit = false;
+							
+							for ( long[] range: ranges ){
 								
-									addLimiters( peer, set );
+								if ( l_address >= range[0] && l_address <= range[1] ){
+																
+									hit	= true;
+		
+									if ( !is_inverse ){
 									
-									added_to_sets.add( set );
+										addLimiters( peer_manager, peer, set, rlu_tbr, rld_tbr );
+										
+										added_to_sets.add( set );
+									}
+		
+									break;
 								}
+							}
+							
+							if ( is_inverse && !hit ){
+								
+								addLimiters( peer_manager, peer, set, rlu_tbr, rld_tbr );
+								
+								added_to_sets.add( set );
+							}
+						}
+					}
+				}
+				
+				if ( peer_cc != null ){
+					
+					for ( int i=0;i<set_ccs.length;i++ ){
+						
+						IPSet set = sets[i];
 	
-								break;
+						if ( added_to_sets.contains( set )){
+							
+							continue;
+						}
+						
+						Set<String>	ccs = set_ccs[i];
+						
+						if ( ccs.size() == 0 ){
+							
+							continue;
+						}
+											
+						boolean not_inverse = !set.isInverse();
+						
+						Set<String> set_cats_or_tags = set.getCategoriesOrTags();
+						
+						if ( set_cats_or_tags == null || new HashSet<String>( set_cats_or_tags ).removeAll( category_or_tags )){
+												
+							boolean	hit = ccs.contains( peer_cc );
+																
+							if ( hit == not_inverse ){
+								
+								addLimiters( peer_manager, peer, set, rlu_tbr, rld_tbr );
+								
+								added_to_sets.add( set );
 							}
 						}
+					}
+				}
+				
+				if ( peer_net != null ){
+					
+					for ( int i=0;i<set_nets.length;i++ ){
+						
+						IPSet set = sets[i];
+	
+						if ( added_to_sets.contains( set )){
+							
+							continue;
+						}
+						
+						Set<String>	nets = set_nets[i];
 						
-						if ( is_inverse && !hit ){
+						if ( nets.size() == 0 ){
 							
-							addLimiters( peer, set );
-							
-							added_to_sets.add( set );
+							continue;
+						}
+											
+						boolean not_inverse = !set.isInverse();
+						
+						Set<String> set_cats_or_tags = set.getCategoriesOrTags();
+						
+						if ( set_cats_or_tags == null || new HashSet<String>( set_cats_or_tags ).removeAll( category_or_tags )){
+												
+							boolean	hit = nets.contains( peer_net );
+																
+							if ( hit == not_inverse ){
+								
+								addLimiters( peer_manager, peer, set, rlu_tbr, rld_tbr );
+								
+								added_to_sets.add( set );
+							}
 						}
 					}
 				}
-			}
-			
-			if ( peer_cc != null ){
+			}finally{
 				
-				for ( int i=0;i<set_ccs.length;i++ ){
+				if ( rlu_tbr != null ){
 					
-					IPSet set = sets[i];
-
-					if ( added_to_sets.contains( set )){
+					for ( RateLimiter l: rlu_tbr ){
 						
-						continue;
+						peer.removeRateLimiter( l, true );
 					}
+				}
+				
+				if ( rld_tbr != null ){
 					
-					Set<String>	ccs = set_ccs[i];
-					
-					if ( ccs.size() == 0 ){
+					for ( RateLimiter l: rld_tbr ){
 						
-						continue;
-					}
-										
-					boolean not_inverse = !set.isInverse();
-					
-					List<String> set_cats = set.getCategories();
-					
-					if ( set_cats == null || set_cats.contains( category )){
-											
-						boolean	hit = ccs.contains( peer_cc );
-															
-						if ( hit == not_inverse ){
-							
-							addLimiters( peer, set );
-						}
+						peer.removeRateLimiter( l, false );
 					}
 				}
 			}
@@ -1903,11 +2281,12 @@ SpeedLimitHandler
 	private void
 	peerRemoved(
 		Download	download,
+		PeerManager	peer_manager,
 		Peer		peer )
 	{
 		Collection<IPSet> sets;
 		
-		synchronized( current_ip_sets ){
+		synchronized( this ){
 			
 			if ( current_ip_sets.size() == 0 ){
 				
@@ -1919,14 +2298,17 @@ SpeedLimitHandler
 		
 		for ( IPSet s: sets ){
 			
-			s.removePeer( peer );
+			s.removePeer( peer_manager, peer );
 		}
 	}
 	
 	private void
 	addLimiters(
-		Peer	peer,
-		IPSet	set )
+		PeerManager			peer_manager,
+		Peer				peer,
+		IPSet				set,
+		List<RateLimiter>	up_to_be_removed,
+		List<RateLimiter>	down_to_be_removed )
 	{
 		boolean	matched = false;
 		
@@ -1946,8 +2328,17 @@ SpeedLimitHandler
 					break;
 				}
 			}
-			if ( !found ){
-														
+			
+			if ( found ){
+				
+				if ( up_to_be_removed != null && up_to_be_removed.remove( l )){
+					
+						// supposed to have been removed but is still required
+					
+					matched = true;
+				}
+			}else{
+				
 				peer.addRateLimiter( l, true );
 				
 				matched = true;
@@ -1970,8 +2361,15 @@ SpeedLimitHandler
 					break;
 				}
 			}
-			if ( !found ){
-													
+			
+			if ( found ){
+			
+				if ( down_to_be_removed != null && down_to_be_removed.remove( l )){
+					
+					matched = true;
+				}
+			}else{
+				
 				peer.addRateLimiter( l, false );
 				
 				matched = true;
@@ -1980,7 +2378,21 @@ SpeedLimitHandler
 		
 		if ( matched ){
 			
-			set.addPeer( peer );
+			set.addPeer( peer_manager, peer );
+		}
+		
+		int	peer_up = set.getPeerUpLimit();
+		
+		if ( peer_up > 0 ){
+			
+			peer.getStats().setUploadRateLimit( peer_up );
+		}
+		
+		int	peer_down = set.getPeerDownLimit();
+		
+		if ( peer_down > 0 ){
+			
+			peer.getStats().setDownloadRateLimit( peer_down );
 		}
 	}
 	
@@ -2132,6 +2544,11 @@ SpeedLimitHandler
 			}
 		}
 		
+		if ( active_rule != null ){
+			
+			active_rule.checkExtensions();
+		}
+		
 		if ( current_rule != active_rule && net_limits.size() > 0 ){
 			
 				// net_limits can depend on the active rule, recalc
@@ -2153,20 +2570,21 @@ SpeedLimitHandler
 	{
 		List<String>	result = new ArrayList<String>();
 		
-		result.add( "# Enter rules on separate lines below this section." );
+		result.add( "# Enter rules on separate lines below this section - see http://wiki.vuze.com/w/Speed_Limit_Scheduler for more details" );
 		result.add( "# Rules are of the following types:" );
-		result.add( "#    enable=(yes|no)   - controls whether the entire schedule is enabled or not (default=enabled)" );
-		result.add( "#    <frequency> <profile_name> from <time> to <time>" );
+		result.add( "#    enable=(yes|no)   - controls whether the entire schedule is enabled or not (default=yes)" );
+		result.add( "#    <frequency> <profile_name> from <time> to <time> [extension]*" );
 		result.add( "#        frequency: daily|weekdays|weekends|<day_of_week>" );
 		result.add( "#            day_of_week: mon|tue|wed|thu|fri|sat|sun" );
 		result.add( "#        time: hh:mm - 24 hour clock; 00:00=midnight; local time" );
-		result.add( "#    ip_set <ip_set_name> [<CIDR_specs...>|CC list|<prior_set_name>] [,inverse=[yes|no]] [,up=<limit>] [,down=<limit>] [cat=<cat names>]" );
-		result.add( "#    net_limit (daily|weekly|monthly)[:<profile>] [total=<limit>] [up=<limit>] [down=<limit>]");
+		result.add( "#        extension: (start_tag|stop_tag|pause_tag|resume_tag):<tag_name>" );
+		result.add( "#    peer_set <set_name>=[<CIDR_specs...>|CC list|Network List|<prior_set_name>] [,inverse=[yes|no]] [,up=<limit>] [,down=<limit>] [,cat=<cat names>] [,tag=<tag names>]" );
+		result.add( "#    net_limit (daily|weekly|monthly)[:<profile>] [total=<limit>] [up=<limit>] [down=<limit>] [peer_up=<limit>] [peer_down=<limit>]");
 		result.add( "#" );
 		result.add( "# For example - assuming there are profiles called 'no_limits' and 'limited_upload' defined:" );
 		result.add( "#" );
 		result.add( "#     daily no_limits from 00:00 to 23:59" );
-		result.add( "#     daily limited_upload from 06:00 to 22:00" );
+		result.add( "#     daily limited_upload from 06:00 to 22:00 stop_tag:bigstuff" );
 		result.add( "#     daily pause_all from 08:00 to 17:00" );
 		result.add( "#" );
 		result.add( "#     net_limit monthly total=250G          // flat montly limit" );
@@ -2174,12 +2592,12 @@ SpeedLimitHandler
 		result.add( "#     net_limit monthly:no_limits                  // no monthly limit when no_limits active" );
 		result.add( "#     net_limit monthly:limited_upload total=100G  // 100G a month limit when limited_upload active" );
 		result.add( "#" );
-		result.add( "#     ip_set external=211.34.128.0/19 211.35.128.0/17" );
-		result.add( "#     ip_set Europe=EU;AD;AL;AT;BA;BE;BG;BY;CH;CS;CZ;DE;DK;EE;ES;FI;FO;FR;FX;GB;GI;GR;HR;HU;IE;IS;IT;LI;LT;LU;LV;MC;MD;MK;MT;NL;NO;PL;PT;RO;SE;SI;SJ;SK;SM;UA;VA" );
-		result.add( "#     ip_set Blorp=Europe;US" );
+		result.add( "#     peer_set external=211.34.128.0/19 211.35.128.0/17" );
+		result.add( "#     peer_set Europe=EU;AD;AL;AT;BA;BE;BG;BY;CH;CS;CZ;DE;DK;EE;ES;FI;FO;FR;FX;GB;GI;GR;HR;HU;IE;IS;IT;LI;LT;LU;LV;MC;MD;MK;MT;NL;NO;PL;PT;RO;SE;SI;SJ;SK;SM;UA;VA" );
+		result.add( "#     peer_set Blorp=Europe;US" );
 		result.add( "#" );
 		result.add( "# When multiple rules apply the one further down the list of rules take precedence" );
-		result.add( "# Currently ip_set limits are not schedulable" );
+		result.add( "# Currently peer_set limits are not schedulable" );
 		result.add( "# Comment lines are prefixed with '#'" );
 		result.add( "# Pre-defined profiles: " + predefined_profile_names );
 
@@ -2797,7 +3215,7 @@ SpeedLimitHandler
 				    	int	tag_up_limit	 	= rl.getTagUploadLimit();
 				    	int	tag_down_limit 		= rl.getTagDownloadLimit();
 				    	
-				    	if ( tag_up_limit > 0 || tag_down_limit > 0 ){
+				    	if ( tag_up_limit != 0 || tag_down_limit != 0 ){
 				    	
 				    		tag_limits.put( 
 				    			tag_type.getTagType() + "." + tag.getTagID(),
@@ -3172,6 +3590,9 @@ SpeedLimitHandler
 		    int	total_tag_limits_up 	= 0;
 		    int	total_tag_limits_down 	= 0;
 
+		    boolean some_up_disabled 	= false;
+		    boolean some_down_disabled	= false;
+		    
 		    TagManager tm = TagManagerFactory.getTagManager();
 		    
 			for ( Map.Entry<String,int[]> entry: tag_limits.entrySet()){
@@ -3207,8 +3628,17 @@ SpeedLimitHandler
 		    		int	up 		= limits[0];
 		    		int	down 	= limits[1];
 		    		
-		    		total_tag_limits_up 	+= up;
-		    		total_tag_limits_down 	+= down;
+		    		if ( up > 0 ){
+		    			total_tag_limits_up 	+= up;
+		    		}else if ( up < 0 ){
+		    			some_up_disabled = true;
+		    		}
+		    		
+		    		if ( down > 0 ){
+		    			total_tag_limits_down 	+= down;
+		    		}else if ( down < 0 ){
+		    			some_down_disabled = true;
+		    		}
 		    		
 		    		result.add( "    " + tag_name + ": " + formatUp( up ) + ", " + formatDown( down ));
 
@@ -3217,15 +3647,33 @@ SpeedLimitHandler
 		    	}
 		    }
 		    
+			String dis_str = "";
+			
+			if ( some_up_disabled ){
+			
+				dis_str = "up";
+			}
+			
+			if ( some_down_disabled ){
+				
+				dis_str += (dis_str.length()==0?"":"&") + "down";
+				
+			}
+			
+			if (dis_str.length() > 0 ){
+				
+				dis_str = " (some " + dis_str + " disabled)";
+			}
+			
 		    if ( total_tag_limits == 0 ){
 		    	
-		    	result.add( "    None" );
+		    	result.add( "    None" + dis_str );
 		    	
 		    }else{
 		    	
 		    	result.add( "    ----" );
 		    	
-		    	result.add( "    Total=" + total_tag_limits + " - Compounded limits: " + formatUp( total_tag_limits_up ) + ", " + formatDown( total_tag_limits_down ));
+		    	result.add( "    Total=" + total_tag_limits + " - Compounded limits: " + formatUp( total_tag_limits_up ) + ", " + formatDown( total_tag_limits_down ) + dis_str );
 
 		    }
 		    
@@ -3363,17 +3811,21 @@ SpeedLimitHandler
 		private int		from_mins;
 		private int		to_mins;
 		
+		private List<ScheduleRuleExtensions>	extensions;
+		
 		private 
 		ScheduleRule(
-			byte			_freq,
-			String			_profile,
-			int				_from,
-			int				_to )
+			byte							_freq,
+			String							_profile,
+			int								_from,
+			int								_to,
+			List<ScheduleRuleExtensions>	_exts )
 		{
 			frequency 		= _freq;
 			profile_name	= _profile;
 			from_mins		= _from;
 			to_mins			= _to;
+			extensions		= _exts;
 		}
 		
 		private List<ScheduleRule>
@@ -3398,8 +3850,8 @@ SpeedLimitHandler
 					next_frequency |= FR_MON;
 				}
 				
-				ScheduleRule	rule1 = new ScheduleRule( frequency, profile_name, from_mins, 23*60+59 );
-				ScheduleRule	rule2 = new ScheduleRule( next_frequency, profile_name, 0, to_mins );
+				ScheduleRule	rule1 = new ScheduleRule( frequency, profile_name, from_mins, 23*60+59, extensions );
+				ScheduleRule	rule2 = new ScheduleRule( next_frequency, profile_name, 0, to_mins, extensions );
 
 				result.add( rule1 );
 				result.add( rule2 );
@@ -3408,6 +3860,18 @@ SpeedLimitHandler
 			return( result );
 		}
 		
+		private void
+		checkExtensions()
+		{
+			if ( extensions != null ){
+				
+				for ( ScheduleRuleExtensions ext: extensions ){
+					
+					ext.checkExtension();
+				}
+			}
+		}
+		
 		private boolean
 		sameAs(
 			ScheduleRule	other )
@@ -3417,6 +3881,34 @@ SpeedLimitHandler
 				return( false );
 			}
 			
+			if ( extensions != other.extensions ){
+				
+				if ( extensions == null || other.extensions == null || extensions.size() != other.extensions.size()){
+					
+					return( false );
+				}
+				
+				for ( ScheduleRuleExtensions ext1: extensions ){
+					
+					boolean match = false;
+					
+					for ( ScheduleRuleExtensions ext2: other.extensions ){
+						
+						if ( ext1.sameAs( ext2 )){
+							
+							match = true;
+							
+							break;
+						}
+					}
+					
+					if ( !match ){
+						
+						return( false );
+					}
+				}
+			}
+			
 			return( frequency == other.frequency &&
 					profile_name.equals( other.profile_name ) &&
 					from_mins == other.from_mins &&
@@ -3469,7 +3961,17 @@ SpeedLimitHandler
 				freq_str = "sun";
 			}
 			
-			return( "profile=" + profile_name + ", frequency=" + freq_str + ", from=" + getTime( from_mins ) + ", to=" + getTime( to_mins ));
+			String ext_str = "";
+			
+			if ( extensions != null ){
+				
+				for ( ScheduleRuleExtensions ext: extensions ){
+					
+					ext_str += ", " + ext.getString();
+				}
+			}
+			
+			return( "profile=" + profile_name + ", frequency=" + freq_str + ", from=" + getTime( from_mins ) + ", to=" + getTime( to_mins ) + ext_str );
 		}
 		
 		private String
@@ -3496,6 +3998,114 @@ SpeedLimitHandler
 		}
 	}
 	
+	private class
+	ScheduleRuleExtensions
+	{
+		private static final int ET_START_TAG 	= 1;
+		private static final int ET_STOP_TAG 	= 2;
+		private static final int ET_PAUSE_TAG 	= 3;
+		private static final int ET_RESUME_TAG 	= 4;
+		
+		private int				extension_type;
+		private TagDownload		tag;
+		
+		private
+		ScheduleRuleExtensions(
+			int				_et,
+			TagDownload		_tag )
+		{
+			extension_type		= _et;
+			tag					= _tag;
+		}
+		
+		private void
+		checkExtension()
+		{
+			Set<DownloadManager> downloads = tag.getTaggedDownloads();
+			
+			for ( DownloadManager download: downloads ){
+								
+				if ( download.isPaused()){
+				
+					if ( extension_type == ET_RESUME_TAG ){
+						
+						if ( rule_pause_all_active || net_limit_pause_all_active ){
+						
+								// things are going to get messy if we do this
+							
+						}else{
+						
+							download.resume();
+						}
+					}
+					
+					continue;
+				}
+				
+				int	state = download.getState();
+				
+				if ( extension_type == ET_START_TAG ){
+					
+					if ( state == DownloadManager.STATE_STOPPED ){
+						
+						download.setStateWaiting();
+					}
+				}else{
+					
+					if ( extension_type == ET_PAUSE_TAG ){
+						
+						if ( !download.isPaused()){
+							
+							download.pause();
+						}
+					}else if ( extension_type == ET_STOP_TAG ){
+						
+						if ( 	state != Download.ST_ERROR &&
+								state != Download.ST_STOPPED &&
+								state != Download.ST_STOPPING ){
+							
+							download.stopIt( DownloadManager.STATE_STOPPED, false, false );
+						}
+					}
+				}
+			}
+		}
+		
+		private boolean
+		sameAs( 
+			ScheduleRuleExtensions	other )
+		{
+			return( extension_type == other.extension_type && tag == other.tag );
+		}
+		
+		private String
+		getString()
+		{
+			String str;
+			
+			if ( extension_type == ET_START_TAG ){
+				
+				str = "start_tag";
+				
+			}else if ( extension_type == ET_STOP_TAG ){
+				
+				str = "stop_tag";
+				
+			}else if ( extension_type == ET_RESUME_TAG ){
+
+				str = "resume_tag";
+				
+			}else{
+				
+				str = "pause_tag";
+			}
+			
+			str += ":" + tag.getTagName( true );
+			
+			return( str );
+		}
+	}
+	
 	private static class
 	NetLimit
 	{
@@ -3555,10 +4165,11 @@ SpeedLimitHandler
 		
 		private long[][]			ranges 			= new long[0][];
 		private Set<String>			country_codes 	= new HashSet<String>();
+		private Set<String>			networks	 	= new HashSet<String>();
 		
 		private boolean	inverse;
 		
-		private List<String>	categories;
+		private Set<String>	categories_or_tags;
 		
 		private boolean	has_explicit_up_lim;
 		private boolean	has_explicit_down_lim;
@@ -3574,6 +4185,9 @@ SpeedLimitHandler
 		private RateLimiter		up_limiter;
 		private RateLimiter		down_limiter;
 		
+		private int				peer_up_lim;
+		private int				peer_down_lim;
+		
 		private TagPeerImpl		tag_impl;
 		
 		private
@@ -3582,8 +4196,8 @@ SpeedLimitHandler
 		{			
 			name	= _name;
 			
-			up_limiter 		= plugin_interface.getConnectionManager().createRateLimiter( "ips-" + name, 0 );
-			down_limiter 	= plugin_interface.getConnectionManager().createRateLimiter( "ips-" + name, 0 );
+			up_limiter 		= plugin_interface.getConnectionManager().createRateLimiter( "ps-" + name, 0 );
+			down_limiter 	= plugin_interface.getConnectionManager().createRateLimiter( "ps-" + name, 0 );
 		}
 		
 		private void
@@ -3611,7 +4225,9 @@ SpeedLimitHandler
 			boolean			_inverse,
 			int				_up_lim,
 			int				_down_lim,
-			List<String>	_cats )
+			int				_peer_up_lim,
+			int				_peer_down_lim,
+			Set<String>		_cats_or_tags )
 		{
 			inverse	= _inverse;
 			
@@ -3628,16 +4244,31 @@ SpeedLimitHandler
 			up_limiter.setRateLimitBytesPerSecond( _up_lim );
 			down_limiter.setRateLimitBytesPerSecond( _down_lim );
 			
-			categories = _cats.size()==0?null:_cats;
+			peer_up_lim 	= _peer_up_lim;
+			peer_down_lim	= _peer_down_lim;
+			
+			categories_or_tags = _cats_or_tags.size()==0?null:_cats_or_tags;
+		}
+		
+		private int
+		getPeerUpLimit()
+		{
+			return( peer_up_lim );
+		}
+		
+		private int
+		getPeerDownLimit()
+		{
+			return( peer_down_lim );
 		}
 		
 		private boolean
-		addCIDRorCC(
-			String		cidr_or_cc )
+		addCIDRorCCetc(
+			String		cidr_or_cc_etc )
 		{
-			if ( Character.isDigit( cidr_or_cc.charAt( 0 ))){
+			if ( Character.isDigit( cidr_or_cc_etc.charAt( 0 ))){
 				
-				String cidr = cidr_or_cc;
+				String cidr = cidr_or_cc_etc;
 				
 				int	pos = cidr.indexOf( '/' );
 				
@@ -3704,8 +4335,27 @@ SpeedLimitHandler
 					return( false );
 				}
 			}else{
+								
+				for ( String net: AENetworkClassifier.AT_NETWORKS ){
+					
+					if ( cidr_or_cc_etc.equalsIgnoreCase( net )){
+						
+						networks.add( net );
+						
+						return( true );
+					}
+				}
+				
+					// special case for matching everything
+				
+				if ( cidr_or_cc_etc.equalsIgnoreCase( "all" )){
+				
+					networks.addAll( Arrays.asList( AENetworkClassifier.AT_NETWORKS ));
+					
+					return( true );
+				}
 				
-				String cc = cidr_or_cc;
+				String cc = cidr_or_cc_etc;
 				
 				if ( cc.length() != 2 ){
 					
@@ -3730,6 +4380,8 @@ SpeedLimitHandler
 			ranges = new_ranges;
 			
 			country_codes.addAll( other.country_codes );
+			
+			networks.addAll( other.networks );
 		}
 		
 		private String
@@ -3750,6 +4402,12 @@ SpeedLimitHandler
 			return( country_codes );
 		}
 		
+		private Set<String>
+		getNetworks()
+		{
+			return( networks );
+		}
+		
 		private RateLimiter
 		getUpLimiter()
 		{
@@ -3762,10 +4420,10 @@ SpeedLimitHandler
 			return( down_limiter );
 		}
 		
-		private List<String>
-		getCategories()
+		private Set<String>
+		getCategoriesOrTags()
 		{
-			return( categories );
+			return( categories_or_tags );
 		}
 		
 		private void
@@ -3803,25 +4461,38 @@ SpeedLimitHandler
 		
 		private void
 		addPeer(
-			Peer		peer )
+			PeerManager		peer_manager,
+			Peer			peer )
 		{
 			TagPeerImpl tag = tag_impl;
 			
 			if ( tag != null ){
 				
-				tag.add( PluginCoreUtils.unwrap( peer ));
+				tag.add( peer_manager, peer );
 			}
 		}
 		
 		private void
 		removePeer(
-			Peer		peer )
+			PeerManager		peer_manager,
+			Peer			peer )
 		{
 			TagPeerImpl tag = tag_impl;
 			
 			if ( tag != null ){
 				
-				tag.remove( PluginCoreUtils.unwrap( peer ));
+				tag.remove( peer_manager, peer );
+			}
+		}
+		
+		private void
+		removeAllPeers()
+		{
+			TagPeerImpl tag = tag_impl;
+			
+			if ( tag != null ){
+				
+				tag.removeAll();
 			}
 		}
 		
@@ -3845,6 +4516,11 @@ SpeedLimitHandler
 				address_count += range[1] - range[0] + 1;
 			}
 			
+			if ( address_count == 0 ){
+				
+				return( "[]");
+			}
+			
 			return( String.valueOf( address_count ));
 		}
 		
@@ -3854,15 +4530,18 @@ SpeedLimitHandler
 			return( name + ": Up=" + format(up_limiter.getRateLimitBytesPerSecond()) + " (" + DisplayFormatters.formatByteCountToKiBEtcPerSec((long)send_rate.getAverage()) + ")" + 
 					", Down=" + format( down_limiter.getRateLimitBytesPerSecond()) + " (" + DisplayFormatters.formatByteCountToKiBEtcPerSec((long)receive_rate.getAverage()) + ")" + 
 					", Addresses=" + getAddressString() + 
+					", CC=" + country_codes +
+					", Networks=" + networks +
 					", Inverse=" + inverse +
-					", Categories=" + categories );
+					", Categories/Tags=" + (categories_or_tags==null?"[]":String.valueOf(categories_or_tags)) +
+					", Peer_Up=" + format( peer_up_lim ) + ", Peer_Down=" + format( peer_down_lim ));
 					
 		}
 		
 		private class
 		TagPeerImpl
 			extends TagBase
-			implements TagPeer
+			implements TagPeer, TagFeatureExecOnAssign
 		{
 			private Object	UPLOAD_PRIORITY_ADDED_KEY = new Object();
 			
@@ -3887,7 +4566,13 @@ SpeedLimitHandler
 			{
 				return( Taggable.TT_PEER );
 			}
-			 
+			
+			public int
+			getSupportedActions()
+			{
+				return( TagFeatureExecOnAssign.ACTION_DESTROY );
+			}
+			
 			private void
 			update(
 				int		tick_count )
@@ -3968,8 +4653,18 @@ SpeedLimitHandler
 			
 			private void
 			add(
-				PEPeer		peer )
-			{
+				PeerManager		peer_manager,
+				Peer			_peer )
+			{	
+				PEPeer peer = PluginCoreUtils.unwrap( _peer );
+				
+				if ( isActionEnabled( TagFeatureExecOnAssign.ACTION_DESTROY )){
+					
+					peer_manager.removePeer( _peer );
+										
+					return;
+				}
+
 				synchronized( this ){
 										
 					if ( peer.getPeerState() == PEPeer.TRANSFERING ){
@@ -3996,8 +4691,11 @@ SpeedLimitHandler
 			
 			private void
 			remove(
-				PEPeer		peer )
+				PeerManager		peer_manager,
+				Peer			_peer )
 			{
+				PEPeer peer = PluginCoreUtils.unwrap( _peer );
+				
 				synchronized( this ){
 					
 					if ( pending_peers.remove( peer )){
@@ -4014,6 +4712,26 @@ SpeedLimitHandler
 				removeTaggable( peer );
 			}
 			
+			private void
+			removeAll()
+			{
+				List<PEPeer> to_remove;
+				
+				synchronized( this ){
+					
+					pending_peers.clear();
+
+					to_remove = new ArrayList<PEPeer>( added_peers );
+					
+					added_peers.clear();
+				}
+					
+				for ( PEPeer peer: to_remove ){
+				
+					removeTaggable( peer );
+				}
+			}
+			
 			public void
 			addTaggable(
 				Taggable	t )
@@ -4022,7 +4740,7 @@ SpeedLimitHandler
 					
 					((PEPeer)t).updateAutoUploadPriority( UPLOAD_PRIORITY_ADDED_KEY, true );
 				}
-				
+								
 				super.addTaggable( t );
 			}
 			
@@ -4034,7 +4752,7 @@ SpeedLimitHandler
 					
 					((PEPeer)t).updateAutoUploadPriority( UPLOAD_PRIORITY_ADDED_KEY, false );
 				}
-
+				
 				super.removeTaggable( t );
 			}
 			
@@ -4108,6 +4826,18 @@ SpeedLimitHandler
 					up_limiter.setRateLimitBytesPerSecond( bps );
 					
 					COConfigurationManager.setParameter( "speed.limit.handler.ipset_n." + getTagID() + ".up", bps );
+					
+						// force a resync of rates (there's a rate limit wrapper on PeerImpl that might need a kick)
+					
+					List<PEPeer> peers = getTaggedPeers();
+					
+					for ( PEPeer peer: peers ){
+						
+						for ( LimitedRateGroup l: peer.getRateLimiters( true )){
+							
+							l.getRateLimitBytesPerSecond();
+						}
+					}
 				}
 			}
 			
@@ -4132,6 +4862,18 @@ SpeedLimitHandler
 					down_limiter.setRateLimitBytesPerSecond( bps );
 					
 					COConfigurationManager.setParameter( "speed.limit.handler.ipset_n." + getTagID() + ".down", bps );
+					
+						// force a resync of rates (there's a rate limit wrapper on PeerImpl that might need a kick)
+						
+					List<PEPeer> peers = getTaggedPeers();
+					
+					for ( PEPeer peer: peers ){
+						
+						for ( LimitedRateGroup l: peer.getRateLimiters( false )){
+							
+							l.getRateLimitBytesPerSecond();
+						}
+					}
 				}
 			}
 			
@@ -4199,6 +4941,12 @@ SpeedLimitHandler
 				
 				super.removeTag();
 			}
+			
+			public String
+			getDescription()
+			{
+				return( getDetailString());
+			}
 		}
 	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManager.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManager.java
index b1fdbce..da24880 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerAdapter.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerAdapter.java
index 384138b..3dd8667 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerFactory.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerFactory.java
index 9d7c9d7..f5e77fe 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerLimitEstimate.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerLimitEstimate.java
index 2d7351e..4eac8ae 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerLimitEstimate.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerLimitEstimate.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 5, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerListener.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerListener.java
index b9aa332..e5f0f3f 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 10, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingMapper.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingMapper.java
index fce36fe..9471863 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingMapper.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingMapper.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 3, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingSource.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingSource.java
index 96edea9..239c9a8 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingSource.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingSource.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingZone.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingZone.java
index 88cabab..58f0c3f 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingZone.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/SpeedManagerPingZone.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 2, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerAlgorithmProvider.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerAlgorithmProvider.java
index d21040e..3bb2943 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerAlgorithmProvider.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerAlgorithmProvider.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 7, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerAlgorithmProviderAdapter.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerAlgorithmProviderAdapter.java
index 7a21009..5f6224b 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerAlgorithmProviderAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerAlgorithmProviderAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 7, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerImpl.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerImpl.java
index 33de6aa..4a18397 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerPingMapperImpl.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerPingMapperImpl.java
index ba837ed..d966149 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerPingMapperImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/SpeedManagerPingMapperImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 6, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/TestPingSourceImpl.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/TestPingSourceImpl.java
index ed36665..3e862c3 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/TestPingSourceImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/TestPingSourceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Aug 8, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/TestPingSourceRandom.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/TestPingSourceRandom.java
index 5b0683c..8c87c8b 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/TestPingSourceRandom.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/TestPingSourceRandom.java
@@ -1,7 +1,7 @@
 /*
  * Created on Aug 8, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v1/SpeedManagerAlgorithmProviderV1.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v1/SpeedManagerAlgorithmProviderV1.java
index d6c9656..c295861 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v1/SpeedManagerAlgorithmProviderV1.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v1/SpeedManagerAlgorithmProviderV1.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 7, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControl.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControl.java
index 6e8cbff..bf8eb6f 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControl.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControl.java
@@ -3,7 +3,7 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
 /**
  * Created on Jul 12, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -16,9 +16,6 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
  * 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 interface LimitControl
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlDropUploadFirst.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlDropUploadFirst.java
index 6d537a8..6db28c2 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlDropUploadFirst.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlDropUploadFirst.java
@@ -3,7 +3,7 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
 /**
  * Created on Jul 9, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -16,9 +16,6 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
  * 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 LimitControlDropUploadFirst implements LimitControl
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlSetting.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlSetting.java
index 0930ec1..b3c20b7 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlSetting.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/LimitControlSetting.java
@@ -3,7 +3,7 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
 /**
  * Created on Jul 12, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -16,9 +16,6 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
  * 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 LimitControlSetting
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PSMonitorListener.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PSMonitorListener.java
index 566f045..3ed81e8 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PSMonitorListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PSMonitorListener.java
@@ -5,7 +5,7 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
 /**
  * Created on Jul 16, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -18,9 +18,6 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
  * 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 interface PSMonitorListener
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSourceManager.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSourceManager.java
index 1db9e75..7d59230 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSourceManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSourceManager.java
@@ -11,7 +11,7 @@ import org.gudy.azureus2.core3.util.SystemTime;
 /**
  * Created on May 31, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -24,9 +24,6 @@ import org.gudy.azureus2.core3.util.SystemTime;
  * 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.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSourceStats.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSourceStats.java
index 9f96cf8..b5a18ca 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSourceStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSourceStats.java
@@ -7,7 +7,7 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource;
 /**
  * Created on May 8, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -20,9 +20,6 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource;
  * 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.
  */
 
 /**
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMapper.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMapper.java
index 3960654..226ec75 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMapper.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMapper.java
@@ -3,7 +3,7 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
 /**
  * Created on Jun 14, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -16,9 +16,6 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
  * 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.
  */
 
 /**
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMon.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMon.java
index 3f35874..1589e36 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMon.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMon.java
@@ -12,7 +12,7 @@ import java.util.ArrayList;
 /**
  * Created on Jul 16, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -25,9 +25,6 @@ import java.util.ArrayList;
  * 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.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMonitor.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMonitor.java
index 83de987..9ecb8f4 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMonitor.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/PingSpaceMonitor.java
@@ -5,7 +5,7 @@ import org.gudy.azureus2.core3.util.SystemTime;
 /**
  * Created on Jun 29, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -18,9 +18,6 @@ import org.gudy.azureus2.core3.util.SystemTime;
  * 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 PingSpaceMonitor
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConfigurationAdapter.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConfigurationAdapter.java
index 6f67e89..a509e6a 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConfigurationAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConfigurationAdapter.java
@@ -5,7 +5,7 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
 /**
  * Created on Jul 30, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -18,9 +18,6 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
  * 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 interface SMConfigurationAdapter
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConfigurationAdapterImpl.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConfigurationAdapterImpl.java
index 3f83947..019d14e 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConfigurationAdapterImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConfigurationAdapterImpl.java
@@ -6,7 +6,7 @@ import org.gudy.azureus2.core3.config.COConfigurationManager;
 /**
  * Created on Jul 30, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -19,9 +19,6 @@ import org.gudy.azureus2.core3.config.COConfigurationManager;
  * 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 SMConfigurationAdapterImpl implements SMConfigurationAdapter
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConst.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConst.java
index 4b31d0f..e6cf18a 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConst.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMConst.java
@@ -5,7 +5,7 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
 /**
  * Created on Jul 18, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -18,9 +18,6 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
  * 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 SMConst
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMInstance.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMInstance.java
index c0985ff..215907f 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMInstance.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMInstance.java
@@ -1,7 +1,7 @@
 /**
  * Created on Jul 11, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.speedmanager.impl.v2;
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMSearchLogger.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMSearchLogger.java
index 8b775bc..caa572e 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMSearchLogger.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMSearchLogger.java
@@ -11,7 +11,7 @@ import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderA
 /**
  * Created on Jul 30, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -24,9 +24,6 @@ import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderA
  * 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.
  */
 
 /**
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMSearchManager.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMSearchManager.java
index 3d17eb1..e4b46d2 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMSearchManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMSearchManager.java
@@ -3,7 +3,7 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
 /**
  * Created on Jul 30, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -16,9 +16,6 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
  * 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.
  */
 
 /**
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMUpdate.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMUpdate.java
index b3a765a..5be584c 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMUpdate.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SMUpdate.java
@@ -3,7 +3,7 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
 /**
  * Created on Jul 11, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -16,9 +16,6 @@ package com.aelitis.azureus.core.speedmanager.impl.v2;
  * 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 SMUpdate
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SaturatedMode.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SaturatedMode.java
index 86e865e..5f7726b 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SaturatedMode.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SaturatedMode.java
@@ -1,7 +1,7 @@
 /**
  * Created on May 21, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.speedmanager.impl.v2;
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitConfidence.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitConfidence.java
index 150857e..7852a9f 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitConfidence.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitConfidence.java
@@ -6,7 +6,7 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
 /**
  * Created on Jun 5, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -19,9 +19,6 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
  * 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 SpeedLimitConfidence
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitListener.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitListener.java
index 6850489..21dc9f4 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitListener.java
@@ -6,7 +6,7 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
 /**
  * Created on Jul 24, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -19,9 +19,6 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
  * 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 SpeedLimitListener implements SpeedManagerListener {
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitMonitor.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitMonitor.java
index 5517a9d..d965a36 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitMonitor.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedLimitMonitor.java
@@ -12,7 +12,7 @@ import com.aelitis.azureus.core.AzureusCoreFactory;
 /**
  * Created on May 23, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -25,9 +25,6 @@ import com.aelitis.azureus.core.AzureusCoreFactory;
  * 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.
  */
 
 /**
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderDHTPing.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderDHTPing.java
index 673ee56..a169dfe 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderDHTPing.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderDHTPing.java
@@ -16,7 +16,7 @@ import java.util.*;
 /**
  * Created on May 14, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -29,9 +29,6 @@ import java.util.*;
  * 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.
  */
 
 /**
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderPingMap.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderPingMap.java
index b9dde89..745aa8f 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderPingMap.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderPingMap.java
@@ -13,7 +13,7 @@ import java.util.ArrayList;
 /**
  * Created on Aug 5, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -26,9 +26,6 @@ import java.util.ArrayList;
  * 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 SpeedManagerAlgorithmProviderPingMap 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderV2.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderV2.java
index 6173cf7..eaab929 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderV2.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerAlgorithmProviderV2.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 7, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerLogger.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerLogger.java
index 309ce11..2be5057 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerLogger.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/SpeedManagerLogger.java
@@ -1,56 +1,55 @@
-/*
- * Created on Oct 13, 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.core.speedmanager.impl.v2;
-
-import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderAdapter;
-
-public class 
-SpeedManagerLogger 
-{
-	private static String									prefix;
-	private static SpeedManagerAlgorithmProviderAdapter		adapter;
-	
-	protected static void
-	setAdapter(
-		String										_prefix,
-		SpeedManagerAlgorithmProviderAdapter		_adapter )
-	{
-		prefix	= _prefix;
-		adapter = _adapter;
-	}
-	
-	public static void
-	log(
-		String	str )
-	{
-		if ( adapter != null ){
-			
-			adapter.log( prefix + ": " + str );
-		}
-	}
-	
-	public static void
-	trace(
-		String	str )
-	{
-	}
-}
+/*
+ * Created on Oct 13, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.speedmanager.impl.v2;
+
+import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerAlgorithmProviderAdapter;
+
+public class 
+SpeedManagerLogger 
+{
+	private static String									prefix;
+	private static SpeedManagerAlgorithmProviderAdapter		adapter;
+	
+	protected static void
+	setAdapter(
+		String										_prefix,
+		SpeedManagerAlgorithmProviderAdapter		_adapter )
+	{
+		prefix	= _prefix;
+		adapter = _adapter;
+	}
+	
+	public static void
+	log(
+		String	str )
+	{
+		if ( adapter != null ){
+			
+			adapter.log( prefix + ": " + str );
+		}
+	}
+	
+	public static void
+	trace(
+		String	str )
+	{
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/TransferMode.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/TransferMode.java
index bbb9044..f5dfbdb 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/TransferMode.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v2/TransferMode.java
@@ -5,7 +5,7 @@ import org.gudy.azureus2.core3.util.SystemTime;
 /**
  * Created on Jun 1, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -18,9 +18,6 @@ import org.gudy.azureus2.core3.util.SystemTime;
  * 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.
  */
 
 /**
diff --git a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v3/SpeedManagerAlgorithmProviderV3.java b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v3/SpeedManagerAlgorithmProviderV3.java
index b21cc0b..cba9468 100644
--- a/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v3/SpeedManagerAlgorithmProviderV3.java
+++ b/azureus2/src/com/aelitis/azureus/core/speedmanager/impl/v3/SpeedManagerAlgorithmProviderV3.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 7, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/stats/AzureusCoreStats.java b/azureus2/src/com/aelitis/azureus/core/stats/AzureusCoreStats.java
index e26ddbc..814489e 100644
--- a/azureus2/src/com/aelitis/azureus/core/stats/AzureusCoreStats.java
+++ b/azureus2/src/com/aelitis/azureus/core/stats/AzureusCoreStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/stats/AzureusCoreStatsProvider.java b/azureus2/src/com/aelitis/azureus/core/stats/AzureusCoreStatsProvider.java
index 4aa17e3..75c80f3 100644
--- a/azureus2/src/com/aelitis/azureus/core/stats/AzureusCoreStatsProvider.java
+++ b/azureus2/src/com/aelitis/azureus/core/stats/AzureusCoreStatsProvider.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/Tag.java b/azureus2/src/com/aelitis/azureus/core/tag/Tag.java
index 687a2a7..d3bca0d 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/Tag.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/Tag.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -89,6 +88,13 @@ Tag
 		boolean		visible );
 	
 	public String
+	getGroup();
+	
+	public void
+	setGroup(
+		String		group );
+	
+	public String
 	getImageID();
 	
 	public void
@@ -123,6 +129,9 @@ Tag
 	public void
 	removeTag();
 	
+	public String
+	getDescription();
+	
 	public void
 	addTagListener(
 		TagListener	listener,
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagDiscovery.java b/azureus2/src/com/aelitis/azureus/core/tag/TagDiscovery.java
new file mode 100644
index 0000000..d546539
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagDiscovery.java
@@ -0,0 +1,77 @@
+/**
+ * Created on Oct 3, 2014
+ *
+ * Copyright Azureus Software, 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.core.tag;
+
+import org.gudy.azureus2.core3.util.SystemTime;
+
+/**
+ * @author TuxPaper
+ * @created Oct 3, 2014
+ *
+ */
+public class TagDiscovery
+{
+	public static int DISCOVERY_TYPE_RCM = 0;
+	public static int DISCOVERY_TYPE_META_PARSE = 1; // derived from torrent (name, tracker, etc) 
+	//public static int DISCOVERY_TYPE_PEER = 2; // Not used, but if we ever get tags from connected peers..
+	
+
+	private String name;
+	private String torrentName;
+	private String network;
+	private byte[] hash;
+	
+	private long timestamp;
+	private int discoveryType;
+	
+	public TagDiscovery(String name, String network, String torrentName, byte[] hash) {
+		super();
+		this.name = name;
+		this.network = network;
+		this.torrentName = torrentName;
+		this.hash = hash;
+		this.timestamp = SystemTime.getCurrentTime();
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public String getNetwork(){
+		return network;
+	}
+	
+	public String getTorrentName() {
+		return torrentName;
+	}
+
+	public byte[] getHash() {
+		return hash;
+	}
+	
+	public long getTimestamp() {
+		return timestamp;
+	}
+	
+	public long getDiscoveryType() {
+		return discoveryType;
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagDownload.java b/azureus2/src/com/aelitis/azureus/core/tag/TagDownload.java
index 48bb487..b024a61 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagDownload.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagDownload.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -33,4 +32,4 @@ TagDownload
 	
 	public Set<DownloadManager>
 	getTaggedDownloads();
-}
\ No newline at end of file
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagException.java b/azureus2/src/com/aelitis/azureus/core/tag/TagException.java
index e7abaa1..322cb6b 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagException.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagException.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagFeature.java b/azureus2/src/com/aelitis/azureus/core/tag/TagFeature.java
index bdf8630..9e872dc 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagFeature.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagFeature.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -31,5 +30,6 @@ TagFeature
 	public static final int TF_XCODE			= 0x00000008;
 	public static final int TF_FILE_LOCATION	= 0x00000010;
 	public static final int TF_PROPERTIES		= 0x00000020;
+	public static final int TF_EXEC_ON_ASSIGN	= 0x00000040;
 	
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureAddress.java b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureAddress.java
index 5a542e7..3789059 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureAddress.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureAddress.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureExecOnAssign.java b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureExecOnAssign.java
new file mode 100644
index 0000000..e5c9c72
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureExecOnAssign.java
@@ -0,0 +1,47 @@
+/*
+ * Created on Apr 18, 2015
+ * Created by Paul Gardner
+ * 
+ * Copyright 2015 Azureus Software, 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.core.tag;
+
+public interface 
+TagFeatureExecOnAssign
+	extends TagFeature
+{
+	public static final int ACTION_NONE		= 0x0000;
+	public static final int ACTION_DESTROY	= 0x0001;
+	
+	public int
+	getSupportedActions();
+	
+	public boolean
+	supportsAction(
+		int		action );
+	
+	public boolean
+	isActionEnabled(
+		int		action );
+	
+	public void
+	setActionEnabled(
+		int			action,
+		boolean		enabled );
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureFileLocation.java b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureFileLocation.java
index a78b894..f6de1e9 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureFileLocation.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureFileLocation.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -26,6 +25,8 @@ import java.io.File;
 public interface 
 TagFeatureFileLocation 
 {
+		// initial location
+	
 	public boolean
 	supportsTagInitialSaveFolder();
 	
@@ -36,6 +37,8 @@ TagFeatureFileLocation
 	setTagInitialSaveFolder(
 		File		folder );
 	
+		// move 
+	
 	public boolean
 	supportsTagMoveOnComplete();
 	
@@ -45,4 +48,16 @@ TagFeatureFileLocation
 	public void
 	setTagMoveOnCompleteFolder(
 		File		folder );
+	
+		// copy 
+	
+	public boolean
+	supportsTagCopyOnComplete();
+	
+	public File
+	getTagCopyOnCompleteFolder();
+	
+	public void
+	setTagCopyOnCompleteFolder(
+		File		folder );
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureListener.java b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureListener.java
index e264dda..66e60dd 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureListener.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureProperties.java b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureProperties.java
index bd98ac9..455df87 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureProperties.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureProperties.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -27,6 +26,7 @@ TagFeatureProperties
 	public static final String	PR_TRACKERS 			= "trackers";
 	public static final String	PR_UNTAGGED 			= "untagged";
 	public static final String	PR_TRACKER_TEMPLATES 	= "tracker_templates";
+	public static final String	PR_CONSTRAINT		 	= "constraint";
 	
 	public static final int		PT_STRING_LIST	= 1;
 	public static final int		PT_BOOLEAN		= 2;
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRSSFeed.java b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRSSFeed.java
index 2eebd98..03917d5 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRSSFeed.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRSSFeed.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRateLimit.java b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRateLimit.java
index 355ee9a..a5a4dfd 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRateLimit.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRateLimit.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRunState.java b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRunState.java
index 781d54f..6521818 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRunState.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureRunState.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureTranscode.java b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureTranscode.java
index ba64de6..af2e03e 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureTranscode.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagFeatureTranscode.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagListener.java b/azureus2/src/com/aelitis/azureus/core/tag/TagListener.java
index e4d392f..755b6be 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagListener.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagManager.java b/azureus2/src/com/aelitis/azureus/core/tag/TagManager.java
index 142d3cc..218f4f5 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagManager.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagManagerFactory.java b/azureus2/src/com/aelitis/azureus/core/tag/TagManagerFactory.java
index 1593fed..6a67a57 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagManagerFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagManagerFactory.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagManagerListener.java b/azureus2/src/com/aelitis/azureus/core/tag/TagManagerListener.java
index 86a5567..a2ce1fe 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagManagerListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagManagerListener.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagPeer.java b/azureus2/src/com/aelitis/azureus/core/tag/TagPeer.java
index 9deb3fa..7edd92a 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagPeer.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagPeer.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -29,7 +28,7 @@ public interface
 TagPeer
 	extends Tag, TagFeatureRateLimit
 {
-	public static final int FEATURES = TagFeature.TF_RATE_LIMIT;
+	public static final int FEATURES = TagFeature.TF_RATE_LIMIT | TagFeature.TF_EXEC_ON_ASSIGN;
 	
 	public List<PEPeer>
 	getTaggedPeers();
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagType.java b/azureus2/src/com/aelitis/azureus/core/tag/TagType.java
index 47a31da..694332c 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagType.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagType.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagTypeAdapter.java b/azureus2/src/com/aelitis/azureus/core/tag/TagTypeAdapter.java
index c11a8d9..76e90dd 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagTypeAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagTypeAdapter.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TagTypeListener.java b/azureus2/src/com/aelitis/azureus/core/tag/TagTypeListener.java
index 784b6d6..19f7b9d 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TagTypeListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TagTypeListener.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/Taggable.java b/azureus2/src/com/aelitis/azureus/core/tag/Taggable.java
index d9ea071..99f5d38 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/Taggable.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/Taggable.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleAdapter.java b/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleAdapter.java
new file mode 100644
index 0000000..7cde945
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleAdapter.java
@@ -0,0 +1,64 @@
+/*
+ * Created on Nov 6, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.core.tag;
+
+import java.util.List;
+
+public class 
+TaggableLifecycleAdapter
+	implements TaggableLifecycleListener
+{
+	public void
+	initialised(
+		List<Taggable>	current_taggables )
+	{
+	}
+	
+	public void
+	taggableCreated(
+		Taggable		taggable )
+	{
+	}
+	
+	public void
+	taggableDestroyed(
+		Taggable		taggable )
+	{
+	}
+	
+	public void
+	taggableTagged(
+		TagType			tag_type,	
+		Tag				tag,
+		Taggable		taggable )
+	{
+	}
+	
+	public void
+	taggableUntagged(
+		TagType			tag_type,	
+		Tag				tag,
+		Taggable		taggable )
+	{
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleHandler.java b/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleHandler.java
index 5f5c9ae..647d4c3 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleHandler.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleListener.java b/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleListener.java
index ac7a94c..fd04e23 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TaggableLifecycleListener.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -37,4 +36,28 @@ TaggableLifecycleListener
 	public void
 	taggableDestroyed(
 		Taggable		taggable );
+	
+	/**
+	 * Currently only implemented for manual_download tag changes
+	 * @param tag_type
+	 * @param tag
+	 * @param taggable
+	 */
+	public void
+	taggableTagged(
+		TagType			tag_type,	
+		Tag				tag,
+		Taggable		taggable );
+	
+	/**
+	 * Currently only implemented for manual_download tag changes
+	 * @param tag_type
+	 * @param tag
+	 * @param taggable
+	 */
+	public void
+	taggableUntagged(
+		TagType			tag_type,	
+		Tag				tag,
+		Taggable		taggable );
 }
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/TaggableResolver.java b/azureus2/src/com/aelitis/azureus/core/tag/TaggableResolver.java
index 117ca4c..4edc384 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/TaggableResolver.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/TaggableResolver.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagBase.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagBase.java
index 8c5fbaf..02305fc 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagBase.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagBase.java
@@ -3,26 +3,24 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
 package com.aelitis.azureus.core.tag.impl;
 
 import java.io.File;
-import java.util.ArrayList;
 import java.util.Set;
 
 import org.gudy.azureus2.core3.internat.MessageText;
@@ -33,6 +31,7 @@ import org.gudy.azureus2.core3.util.SimpleTimer;
 
 import com.aelitis.azureus.core.tag.Tag;
 import com.aelitis.azureus.core.tag.TagException;
+import com.aelitis.azureus.core.tag.TagFeatureExecOnAssign;
 import com.aelitis.azureus.core.tag.TagFeatureFileLocation;
 import com.aelitis.azureus.core.tag.TagFeatureProperties;
 import com.aelitis.azureus.core.tag.TagFeatureRSSFeed;
@@ -51,6 +50,7 @@ TagBase
 	protected static final String	AT_RATELIMIT_DOWN	= "rl.down";
 	protected static final String	AT_VISIBLE			= "vis";
 	protected static final String	AT_PUBLIC			= "pub";
+	protected static final String	AT_GROUP			= "gr";
 	protected static final String	AT_CAN_BE_PUBLIC	= "canpub";
 	protected static final String	AT_ORIGINAL_NAME	= "oname";
 	protected static final String	AT_IMAGE_ID			= "img.id";
@@ -59,10 +59,12 @@ TagBase
 	protected static final String	AT_RATELIMIT_UP_PRI	= "rl.uppri";
 	protected static final String	AT_XCODE_TARGET		= "xcode.to";
 	protected static final String	AT_FL_MOVE_COMP		= "fl.comp";
+	protected static final String	AT_FL_COPY_COMP		= "fl.copy";
 	protected static final String	AT_FL_INIT_LOC		= "fl.init";
 	protected static final String	AT_RATELIMIT_MIN_SR	= "rl.minsr";
 	protected static final String	AT_RATELIMIT_MAX_SR	= "rl.maxsr";
-	protected static final String	AT_PROPERTY_PREFX	= "pp.";
+	protected static final String	AT_PROPERTY_PREFIX	= "pp.";
+	protected static final String	AT_EOA_PREFIX		= "eoa.";
 
 	private static final String[] EMPTY_STRING_LIST = {};
 	
@@ -103,7 +105,8 @@ TagBase
 		
 	private Boolean	is_visible;
 	private Boolean	is_public;
-	
+	private String	group;
+
 	private TagFeatureRateLimit		tag_rl;
 	private TagFeatureRSSFeed		tag_rss;
 	private TagFeatureFileLocation	tag_fl;
@@ -121,8 +124,9 @@ TagBase
 		
 		if ( getManager().isEnabled()){
 		
-			is_visible = readBooleanAttribute( AT_VISIBLE, null );
-			is_public = readBooleanAttribute( AT_PUBLIC, null );
+			is_visible 	= readBooleanAttribute( AT_VISIBLE, null );
+			is_public 	= readBooleanAttribute( AT_PUBLIC, null );
+			group		= readStringAttribute( AT_GROUP, null );
 			
 			if ( this instanceof TagFeatureRateLimit ){
 				
@@ -350,6 +354,31 @@ TagBase
 		}
 	}
 	
+	public String
+	getGroup()
+	{
+		return( group );
+	}
+	
+	public void
+	setGroup(
+		String		new_group )
+	{
+		if ( group == null && new_group == null ){
+			
+			return;
+		}
+		
+		if ( group == null || new_group == null || !group.equals(new_group)){
+			
+			group	= new_group;
+			
+			writeStringAttribute( AT_GROUP, new_group );
+			
+			tag_type.fireChanged( this );
+		}	
+	}
+	
 	protected boolean
 	getVisibleDefault()
 	{
@@ -562,6 +591,56 @@ TagBase
 		}
 	}
 	
+		// copy on complete
+		
+	public boolean
+	supportsTagCopyOnComplete()
+	{
+		return( false );
+	}
+	
+	public File
+	getTagCopyOnCompleteFolder()
+	{
+		if ( tag_fl != null ){
+			
+			String str = readStringAttribute( AT_FL_COPY_COMP, null );
+			
+			if ( str == null ){
+				
+				return( null );
+				
+			}else{
+				
+				return( new File( str ));
+			}
+		}
+		
+		return( null );
+	}
+	
+	public void
+	setTagCopyOnCompleteFolder(
+		File		folder )
+	{
+		if ( tag_fl != null ){
+			
+			File	existing = getTagCopyOnCompleteFolder();
+			
+			if ( existing == null && folder == null ){
+				
+				return;
+				
+			}else if ( existing == null || folder == null || !existing.equals( folder )){
+				
+				writeStringAttribute( AT_FL_COPY_COMP, folder==null?null:folder.getAbsolutePath());
+				
+				tag_type.fireChanged( this );
+			}
+		}
+	}
+
+	
 		// min ratio
 	
 	public int
@@ -623,6 +702,52 @@ TagBase
 		return( new TagPropertyImpl( name, type ));
 	}
 	
+		// exec on assign
+	
+	public int
+	getSupportedActions()
+	{
+		return( TagFeatureExecOnAssign.ACTION_NONE );
+	}
+	
+	public boolean
+	supportsAction(
+		int		action )
+	{
+		return((getSupportedActions() & action ) != 0 );
+	}
+	
+	public boolean
+	isActionEnabled(
+		int		action )
+	{
+		if ( !supportsAction( action )){
+			
+			Debug.out( "not supported" );
+			
+			return( false );
+		}
+		
+		return( readBooleanAttribute( AT_PROPERTY_PREFIX + action, false ));
+	}
+	
+	public void
+	setActionEnabled(
+		int			action,
+		boolean		enabled )
+	{
+		if ( !supportsAction( action )){
+			
+			Debug.out( "not supported" );
+			
+			return;
+		}
+		
+		writeBooleanAttribute( AT_PROPERTY_PREFIX + action, enabled );
+	}
+	
+		// others
+	
 	public void
 	addTaggable(
 		Taggable	t )
@@ -666,12 +791,20 @@ TagBase
 		}
 	}
 	
+	public String
+	getDescription()
+	{
+		return( null );
+	}
+	
 	public void
 	addTagListener(
 		TagListener	listener,
 		boolean		fire_for_existing )
 	{
-		t_listeners.addListener( listener );
+		if (!t_listeners.hasListener(listener)) {
+			t_listeners.addListener( listener );
+		}
 		
 		if ( fire_for_existing ){
 			
@@ -937,7 +1070,7 @@ TagBase
 		setStringList(
 			String[]	value )
 		{
-			if ( writeStringListAttribute( AT_PROPERTY_PREFX + name, value )){
+			if ( writeStringListAttribute( AT_PROPERTY_PREFIX + name, value )){
 				
 				for ( TagPropertyListener l: listeners ){
 					
@@ -957,14 +1090,14 @@ TagBase
 		public String[]
 		getStringList()
 		{
-			return( readStringListAttribute( AT_PROPERTY_PREFX + name, EMPTY_STRING_LIST ));
+			return( readStringListAttribute( AT_PROPERTY_PREFIX + name, EMPTY_STRING_LIST ));
 		}
 		
 		public void
 		setBoolean(
 			boolean	value )
 		{
-			if ( writeBooleanAttribute( AT_PROPERTY_PREFX + name, value )){
+			if ( writeBooleanAttribute( AT_PROPERTY_PREFIX + name, value )){
 				
 				for ( TagPropertyListener l: listeners ){
 					
@@ -984,7 +1117,7 @@ TagBase
 		public Boolean
 		getBoolean()
 		{
-			return( readBooleanAttribute( AT_PROPERTY_PREFX + name, null ));
+			return( readBooleanAttribute( AT_PROPERTY_PREFIX + name, null ));
 		}
 		
 		public String
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagDownloadWithState.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagDownloadWithState.java
index 88185b2..35b6dab 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagDownloadWithState.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagDownloadWithState.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -120,7 +119,8 @@ TagDownloadWithState
 		new TagProperty[]{ 
 			createTagProperty( TagFeatureProperties.PR_TRACKERS, TagFeatureProperties.PT_STRING_LIST ),
 			createTagProperty( TagFeatureProperties.PR_UNTAGGED, TagFeatureProperties.PT_BOOLEAN ),
-			createTagProperty( TagFeatureProperties.PR_TRACKER_TEMPLATES, TagFeatureProperties.PT_STRING_LIST ) 
+			createTagProperty( TagFeatureProperties.PR_TRACKER_TEMPLATES, TagFeatureProperties.PT_STRING_LIST ),
+			createTagProperty( TagFeatureProperties.PR_CONSTRAINT, TagFeatureProperties.PT_STRING_LIST ) 
 		};
 	
 	public
@@ -328,7 +328,12 @@ TagDownloadWithState
 			
 			if ( dm.isDestroyed()){
 				
-				Debug.out( "Invalid Taggable added - download is destroyed: " + dm.getDisplayName());
+				// There's a race condition when stopping and removing a torrent that isn't easy to avoid in terms
+				// of a download being added to the 'stopped' tag and concurrently removed. 
+				// There will be a subseqent 'downloadRemoved' action triggered that should tidy up any
+				// inconsistency left due to this
+				
+				//Debug.out( "Invalid Taggable added - download is destroyed: " + dm.getDisplayName());
 				
 			}else{
 			
@@ -395,6 +400,8 @@ TagDownloadWithState
 		upload_rate_limit	= bps;
 		
 		writeLongAttribute( AT_RATELIMIT_UP, upload_rate_limit );
+
+		getTagType().fireChanged( this );
 	}
 	
 	public int
@@ -430,6 +437,8 @@ TagDownloadWithState
 		download_rate_limit	= bps;
 		
 		writeLongAttribute( AT_RATELIMIT_DOWN, download_rate_limit );
+
+		getTagType().fireChanged( this );
 	}
 	
 	public int
@@ -475,6 +484,8 @@ TagDownloadWithState
 				dm.updateAutoUploadPriority( UPLOAD_PRIORITY_ADDED_KEY, priority>0 );
 			}
 		}
+
+		getTagType().fireChanged( this );
 	}
 	
 	public int
@@ -527,6 +538,8 @@ TagDownloadWithState
 			
 			dm.getDownloadState().setIntParameter( DownloadManagerState.PARAM_MIN_SHARE_RATIO, sr );
 		}
+
+		getTagType().fireChanged( this );
 	}
 	
 	public int
@@ -579,6 +592,8 @@ TagDownloadWithState
 			
 			dm.getDownloadState().setIntParameter( DownloadManagerState.PARAM_MAX_SHARE_RATIO, sr );
 		}
+
+		getTagType().fireChanged( this );
 	}
 	
 	private void
@@ -839,6 +854,13 @@ TagDownloadWithState
 	}
 	
 	@Override
+	public boolean
+	supportsTagCopyOnComplete()
+	{
+		return( supports_file_location );
+	}
+	
+	@Override
 	public TagProperty[]
 	getSupportedProperties()
 	{
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagManagerImpl.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagManagerImpl.java
index c628c72..43810e7 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagManagerImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagManagerImpl.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -30,12 +29,17 @@ import java.net.URL;
 import java.util.*;
 
 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.DownloadManagerState;
 import org.gudy.azureus2.core3.global.GlobalManager;
+import org.gudy.azureus2.core3.logging.LogAlert;
+import org.gudy.azureus2.core3.logging.Logger;
 import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.AERunnable;
+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.Base32;
@@ -55,6 +59,7 @@ import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.PluginManager;
 import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadCompletionListener;
 import org.gudy.azureus2.plugins.download.DownloadScrapeResult;
 import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
@@ -68,11 +73,12 @@ import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter;
 import com.aelitis.azureus.core.rssgen.RSSGeneratorPlugin;
 import com.aelitis.azureus.core.tag.*;
 import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.core.util.IdentityHashSet;
 import com.aelitis.azureus.util.MapUtils;
 
 public class 
 TagManagerImpl
-	implements TagManager
+	implements TagManager, DownloadCompletionListener
 {
 	private static final String	CONFIG_FILE 				= "tag.config";
 	
@@ -108,6 +114,8 @@ TagManagerImpl
 	
 	private Set<TagBase>	rss_tags = new HashSet<TagBase>();
 	
+	private Set<DownloadManager>	active_copy_on_complete = new IdentityHashSet<DownloadManager>();
+	
 	private RSSGeneratorPlugin.Provider rss_generator = 
 		new RSSGeneratorPlugin.Provider()
 		{
@@ -128,11 +136,55 @@ TagManagerImpl
 				
 				String path = url.getPath();
 				
+				String	query = url.getQuery();
+				
+				if ( query != null ){
+					
+					path += "?" + query;
+				}
+				
 				int	pos = path.indexOf( '?' );
 				
 				if ( pos != -1 ){
 					
+					String args = path.substring( pos+1 );
+
 					path = path.substring(0,pos);
+					
+					if ( path.endsWith( "GetTorrent" )){
+						
+						String[] bits = args.split( "&" );
+						
+						for ( String bit: bits ){
+							
+							String[] temp = bit.split( "=" );
+							
+							if ( temp.length == 2 ){
+								
+								if ( temp[0].equals( "hash" )){
+									
+									try{
+										Download download = AzureusCoreFactory.getSingleton().getPluginManager().getDefaultPluginInterface().getDownloadManager().getDownload( Base32.decode( temp[1] ));
+										
+										Torrent torrent = download.getTorrent();
+										
+										response.getOutputStream().write( torrent.writeToBEncodedData());
+										
+										response.setContentType( "application/x-bittorrent" );
+										
+										return( true );
+										
+									}catch( Throwable e ){
+										
+									}
+								}
+							}
+						}
+						
+						response.setReplyStatus( 404 );
+						
+						return( true );	
+					}
 				}
 				
 				path = path.substring( RSS_PROVIDER.length()+1);
@@ -210,6 +262,9 @@ TagManagerImpl
 						return( true );
 					}
 					
+					boolean	enable_low_noise = RSSGeneratorPlugin.getSingleton().isLowNoiseEnabled();
+
+					
 					Set<DownloadManager> dms = tag.getTaggedDownloads();
 					
 					List<Download> downloads = new ArrayList<Download>( dms.size());
@@ -225,6 +280,21 @@ TagManagerImpl
 							continue;
 						}
 						
+						DownloadManagerState state = dm.getDownloadState();
+						
+						if ( state.getFlag( DownloadManagerState.FLAG_METADATA_DOWNLOAD )){
+							
+							continue;
+						}
+						
+						if ( !enable_low_noise ){
+							
+							if (  state.getFlag( DownloadManagerState.FLAG_LOW_NOISE )){
+								
+								continue;
+							}
+						}
+						
 						if ( !TorrentUtils.isReallyPrivate( torrent )){
 						
 							dl_marker += dm.getDownloadState().getLongParameter( DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME );
@@ -344,7 +414,7 @@ TagManagerImpl
 						pw.println( "<title>" + escape( tag.getTagName( true )) + "</title>" );
 						
 						Collections.sort(
-								downloads,
+							downloads,
 							new Comparator<Download>()
 							{
 								public int 
@@ -359,13 +429,13 @@ TagManagerImpl
 								}
 							});
 											
-										
+													
 						pw.println(	"<pubDate>" + TimeFormatter.getHTTPDate( last_modified ) + "</pubDate>" );
 					
 						for (int i=0;i<downloads.size();i++){
 							
 							Download download = downloads.get( i );
-							
+
 							DownloadManager	core_download = PluginCoreUtils.unwrap( download );
 							
 							Torrent torrent = download.getTorrent();
@@ -380,9 +450,82 @@ TagManagerImpl
 							
 							pw.println( "<guid>" + hash_str + "</guid>" );
 							
-							String magnet_url = escape( UrlUtils.getMagnetURI( download.getName(), torrent ));
+							String magnet_uri = UrlUtils.getMagnetURI( download );
+							
+							String obtained_from = TorrentUtils.getObtainedFrom( core_download.getTorrent());
+							
+							String[] dl_nets = core_download.getDownloadState().getNetworks();
+							
+							boolean	added_fl = false;
+							
+							if ( obtained_from != null ){
+								
+								try{
+									URL ou = new URL( obtained_from );
+									
+									if ( ou.getProtocol().toLowerCase( Locale.US ).startsWith( "http" )){
+										
+										String host = ou.getHost();
+										
+											// make sure the originator network is compatible with the ones enabled
+											// for the download
+										
+										String net = AENetworkClassifier.categoriseAddress( host );
+										
+										boolean	net_ok = false;
+										
+										if ( dl_nets == null || dl_nets.length == 0 ){
+										
+											net_ok = true;
+											
+										}else{
+											
+											for ( String dl_net: dl_nets ){
+											
+												if ( dl_net == net ){
+													
+													net_ok = true;
+													
+													break;
+												}
+											}
+										}
+										
+										if ( net_ok ){
+											
+											magnet_uri += "&fl=" + UrlUtils.encode( ou.toExternalForm());
+											
+											added_fl = true;
+										}
+									}
+								}catch( Throwable e ){
+									
+								}
+							}
+							
+								// in theory we could add multiple &fls but it keeps things less confusing
+								// and more efficient to just use one - if an external link is available and
+								// the torrent file is a reasonable size and the rss feed is popular then this
+								// can avoid quite a bit of load - plus it reduces the size of magnet URI
+							
+							if ( !added_fl ){
+							
+								String host = (String)request.getHeaders().get( "host" );
+								
+								if ( host != null ){
+									
+										// don't need to check network here as we are replying with the network
+										// used to contact us
+									
+									String local_fl = url.getProtocol() + "://" + host + "/" + RSS_PROVIDER + "/GetTorrent?hash=" + Base32.encode( torrent.getHash());
+																	
+									magnet_uri += "&fl=" + UrlUtils.encode( local_fl );
+								}
+							}
+																			
+							magnet_uri = escape( magnet_uri );
 	
-							pw.println( "<link>" + magnet_url + "</link>" );
+							pw.println( "<link>" + magnet_uri + "</link>" );
 							
 							long added = core_download.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME);
 							
@@ -391,7 +534,7 @@ TagManagerImpl
 							pw.println(	"<vuze:size>" + torrent.getSize()+ "</vuze:size>" );
 							pw.println(	"<vuze:assethash>" + hash_str + "</vuze:assethash>" );
 															
-							pw.println( "<vuze:downloadurl>" + magnet_url + "</vuze:downloadurl>" );
+							pw.println( "<vuze:downloadurl>" + magnet_uri + "</vuze:downloadurl>" );
 					
 							DownloadScrapeResult scrape = download.getLastScrapeResult();
 							
@@ -497,9 +640,18 @@ TagManagerImpl
 		
 		new TagPropertyTrackerTemplateHandler( azureus_core, this );
 		
+		new TagPropertyConstraintHandler( azureus_core, this );
+		
 		azureus_core.addLifecycleListener(
 			new AzureusCoreLifecycleAdapter()
 			{
+				public void
+				started(
+					AzureusCore		core )
+				{
+					core.getPluginManager().getDefaultPluginInterface().getDownloadManager().getGlobalDownloadEventNotifier().addCompletionListener( TagManagerImpl.this);
+				}
+				
 				public void 
 				componentCreated(
 					AzureusCore 			core,
@@ -613,6 +765,178 @@ TagManagerImpl
 			});
 	}
 	
+	public void 
+	onCompletion(
+		Download d )
+	{
+		final DownloadManager manager = PluginCoreUtils.unwrap( d );
+	
+		List<Tag> tags = getTagsForTaggable( manager );
+		
+		List<Tag> cc_tags = new ArrayList<Tag>();
+		
+		for ( Tag tag: tags ){
+			
+			if ( tag.getTagType().hasTagTypeFeature( TagFeature.TF_FILE_LOCATION )){
+			
+				TagFeatureFileLocation fl = (TagFeatureFileLocation)tag;
+
+				if ( fl.supportsTagCopyOnComplete()){
+					
+					File save_loc = fl.getTagCopyOnCompleteFolder();
+					
+					if ( save_loc != null ){
+						
+						cc_tags.add( tag );
+					}
+				}
+			}
+		}
+		
+		if ( cc_tags.size() > 0 ){
+			
+			if ( cc_tags.size() > 1 ){
+				
+				Collections.sort(
+						cc_tags,
+					new Comparator<Tag>()
+					{
+						public int 
+						compare(
+							Tag o1, Tag o2) 
+						{
+							return( o1.getTagID() - o2.getTagID());
+						}
+					});
+			}
+			
+			final File new_loc = ((TagFeatureFileLocation)cc_tags.get(0)).getTagCopyOnCompleteFolder();
+			
+			File old_loc = manager.getSaveLocation();
+			
+			if ( !new_loc.equals( old_loc )){
+				
+				boolean do_it;
+				
+				synchronized( active_copy_on_complete ){
+					
+					if ( active_copy_on_complete.contains( manager )){
+						
+						do_it = false;
+						
+					}else{
+						
+						active_copy_on_complete.add( manager );
+						
+						do_it = true;
+					}
+				}
+				
+				if ( do_it ){
+					
+					new AEThread2( "tm:copy")
+					{
+						public void
+						run()
+						{
+							try{
+								long stopped_and_incomplete_start 	= 0;
+								long looks_good_start 				= 0;
+								
+								while( true ){
+									
+									if ( manager.isDestroyed()){
+										
+										throw( new Exception( "Download has been removed" ));
+									}
+									
+									DiskManager dm = manager.getDiskManager();
+								
+									if ( dm == null ){
+										
+										looks_good_start = 0;
+										
+										if ( !manager.getAssumedComplete()){
+											
+											long	now = SystemTime.getMonotonousTime();
+											
+											if ( stopped_and_incomplete_start == 0 ){
+											
+												stopped_and_incomplete_start = now;
+												
+											}else if ( now - stopped_and_incomplete_start > 30*1000 ){
+												
+												throw( new Exception( "Download is stopped and incomplete" ));
+											}
+										}else{
+											
+											break;
+										}
+									}else{
+										
+										stopped_and_incomplete_start = 0;
+										
+										if ( manager.getAssumedComplete()){
+											
+											if ( dm.getMoveProgress() == -1 && dm.getCompleteRecheckStatus() == -1 ){
+												
+												long	now = SystemTime.getMonotonousTime();
+												
+												if ( looks_good_start == 0 ){
+												
+													looks_good_start = now;
+													
+												}else if ( now - looks_good_start > 5*1000 ){
+													
+													break;
+												}
+											}
+										}else{
+											
+											looks_good_start = 0;
+										}
+									}
+									
+									//System.out.println( "Waiting" );
+									
+									Thread.sleep( 1000 );
+								}
+								
+								manager.copyDataFiles( new_loc );
+								
+								Logger.logTextResource(
+									new LogAlert(
+										manager, 
+										LogAlert.REPEATABLE,
+										LogAlert.AT_INFORMATION, 
+										"alert.copy.on.comp.done"),
+									new String[]{ manager.getDisplayName(), new_loc.toString()});
+								 
+							}catch( Throwable e ){
+								
+								 Logger.logTextResource(
+									new LogAlert(
+										manager, 
+										LogAlert.REPEATABLE,
+										LogAlert.AT_ERROR, 
+										"alert.copy.on.comp.fail"),
+									new String[]{ manager.getDisplayName(), new_loc.toString(), Debug.getNestedExceptionMessage(e)});
+								 
+							}finally{
+								
+								synchronized( active_copy_on_complete ){
+									
+									active_copy_on_complete.remove( manager );
+								}
+								
+							}
+						}
+					}.start();
+				}
+			}
+		}
+	}
+	
 	private void
 	resolverInitialized(
 		TaggableResolver		resolver )
@@ -751,8 +1075,10 @@ TagManagerImpl
 			// hack to support initial-save-location logic when a user manually assigns a tag and the download
 			// hasn't had files allocated yet (most common scenario is user has 'add-torrent-stopped' set up)
 		
+		int tt = tag_type.getTagType();
+		
 		try{
-			if ( tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL && tagged instanceof DownloadManager ){
+			if ( tt == TagType.TT_DOWNLOAD_MANUAL && tagged instanceof DownloadManager ){
 				
 				TagFeatureFileLocation fl = (TagFeatureFileLocation)tag;
 	
@@ -792,6 +1118,58 @@ TagManagerImpl
 		
 			Debug.out(e );
 		}
+		
+			// hack to limit tagged/untagged callbacks as the auto-dl-state ones generate a lot
+			// of traffic and thusfar nobody's interested in it
+		
+		if ( tt == TagType.TT_DOWNLOAD_MANUAL ){
+			
+			synchronized( lifecycle_handlers ){
+				
+				long type = tagged.getTaggableType();
+				
+				LifecycleHandlerImpl handler = lifecycle_handlers.get( type );
+				
+				if ( handler == null ){
+					
+					handler = new LifecycleHandlerImpl();
+					
+					lifecycle_handlers.put( type, handler );
+				}
+				
+				handler.taggableTagged( tag_type, tag, tagged );
+			}
+		}
+	}
+	
+	public void
+	taggableRemoved(
+		TagType		tag_type,
+		Tag			tag,
+		Taggable	tagged )
+	{
+		int tt = tag_type.getTagType();
+
+			// as above
+		
+		if ( tt == TagType.TT_DOWNLOAD_MANUAL ){
+
+			synchronized( lifecycle_handlers ){
+				
+				long type = tagged.getTaggableType();
+				
+				LifecycleHandlerImpl handler = lifecycle_handlers.get( type );
+				
+				if ( handler == null ){
+					
+					handler = new LifecycleHandlerImpl();
+					
+					lifecycle_handlers.put( type, handler );
+				}
+				
+				handler.taggableUntagged( tag_type, tag, tagged );
+			}
+		}
 	}
 	
 	public List<Tag>
@@ -1747,8 +2125,13 @@ TagManagerImpl
 							{
 								for ( TaggableLifecycleListener listener: listeners_ref ){
 									
-									
-									listener.taggableCreated( t );
+									try{
+										listener.taggableCreated( t );
+										
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}
 								}
 							}
 						});
@@ -1777,7 +2160,83 @@ TagManagerImpl
 							{
 								for ( TaggableLifecycleListener listener: listeners_ref ){
 									
-									listener.taggableDestroyed( t );
+									try{
+										listener.taggableDestroyed( t );
+										
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}
+								}
+							}
+						});
+				}
+			}
+		}
+		
+		public void
+		taggableTagged(
+			final TagType	tag_type,
+			final Tag		tag,
+			final Taggable	taggable )
+		{
+			synchronized( this ){
+				
+				if ( initialised ){
+					
+					final List<TaggableLifecycleListener> listeners_ref = listeners.getList();
+					 
+					async_dispatcher.dispatch(
+						new AERunnable()
+						{
+							@Override
+							public void 
+							runSupport() 
+							{
+								for ( TaggableLifecycleListener listener: listeners_ref ){
+									
+									try{
+										listener.taggableTagged( tag_type, tag, taggable);
+										
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}
+								}
+							}
+						});
+				}
+			}
+		}
+		
+		public void
+		taggableUntagged(
+			final TagType	tag_type,
+			final Tag		tag,
+			final Taggable	taggable )
+		{
+			synchronized( this ){
+				
+				if ( initialised ){
+					
+					final List<TaggableLifecycleListener> listeners_ref = listeners.getList();
+					 
+					async_dispatcher.dispatch(
+						new AERunnable()
+						{
+							@Override
+							public void 
+							runSupport() 
+							{
+								for ( TaggableLifecycleListener listener: listeners_ref ){
+									
+									try{
+										listener.taggableUntagged( tag_type, tag, taggable );
+										
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}
 								}
 							}
 						});
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyConstraintHandler.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyConstraintHandler.java
new file mode 100644
index 0000000..a8ce930
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyConstraintHandler.java
@@ -0,0 +1,1470 @@
+/*
+ * Created on Sep 4, 2013
+ * Created by Paul Gardner
+ * 
+ * Copyright 2013 Azureus Software, 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.core.tag.impl;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+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.plugins.download.Download;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagFeatureProperties;
+import com.aelitis.azureus.core.tag.TagFeatureProperties.TagProperty;
+import com.aelitis.azureus.core.tag.TagFeatureProperties.TagPropertyListener;
+import com.aelitis.azureus.core.tag.TagListener;
+import com.aelitis.azureus.core.tag.TagType;
+import com.aelitis.azureus.core.tag.TagTypeListener;
+import com.aelitis.azureus.core.tag.Taggable;
+import com.aelitis.azureus.core.tag.TaggableLifecycleAdapter;
+
+public class 
+TagPropertyConstraintHandler 
+	implements TagTypeListener
+{
+	private final AzureusCore		azureus_core;
+	private final TagManagerImpl	tag_manager;
+		
+	private boolean		initialised;
+	private boolean 	initial_assignment_complete;
+	
+	private Map<Tag,TagConstraint>	constrained_tags 	= new HashMap<Tag,TagConstraint>();
+	
+	private Map<Tag,Map<DownloadManager,Long>>			apply_history 		= new HashMap<Tag, Map<DownloadManager,Long>>();
+	
+	private AsyncDispatcher	dispatcher = new AsyncDispatcher( "tag:constraints" );
+	
+	private TimerEventPeriodic		timer;
+	
+	private
+	TagPropertyConstraintHandler()
+	{
+		azureus_core	= null;
+		tag_manager		= null;
+	}
+
+	protected
+	TagPropertyConstraintHandler(
+		AzureusCore		_core,
+		TagManagerImpl	_tm )
+	{
+		azureus_core	= _core;
+		tag_manager		= _tm;
+		
+		tag_manager.addTaggableLifecycleListener(
+			Taggable.TT_DOWNLOAD,
+			new TaggableLifecycleAdapter()
+			{
+				public void
+				initialised(
+					List<Taggable>	current_taggables )
+				{
+					try{
+						TagType tt = tag_manager.getTagType( TagType.TT_DOWNLOAD_MANUAL );
+						
+						tt.addTagTypeListener( TagPropertyConstraintHandler.this, true );
+
+					}finally{
+						
+						AzureusCoreFactory.addCoreRunningListener(
+							new AzureusCoreRunningListener()
+							{	
+								public void 
+								azureusCoreRunning(
+									AzureusCore core )
+								{
+									synchronized( constrained_tags ){
+																				
+										initialised = true;
+
+										apply( core.getGlobalManager().getDownloadManagers(), true );
+									}
+								}
+							});
+					}
+				}
+				
+				public void
+				taggableCreated(
+					Taggable		taggable )
+				{
+					apply((DownloadManager)taggable, null, false );
+				}
+			});
+	}
+	
+	public void
+	tagTypeChanged(
+		TagType		tag_type )
+	{
+	}
+	
+	public void
+	tagAdded(
+		Tag			tag )
+	{
+		TagFeatureProperties tfp = (TagFeatureProperties)tag;
+		
+		TagProperty prop = tfp.getProperty( TagFeatureProperties.PR_CONSTRAINT );
+		
+		if ( prop != null ){
+			
+			prop.addListener(
+				new TagPropertyListener() 
+				{
+					public void
+					propertyChanged(
+						TagProperty		property )
+					{		
+						handleProperty( property );
+					}
+					
+					public void
+					propertySync(
+						TagProperty		property )
+					{	
+					}
+				});
+			
+			handleProperty( prop );
+		}
+		
+		tag.addTagListener(
+			new TagListener() 
+			{	
+				public void 
+				taggableSync(
+					Tag tag ) 
+				{
+				}
+				
+				public void 
+				taggableRemoved(
+					Tag 		tag, 
+					Taggable 	tagged ) 
+				{
+					apply((DownloadManager)tagged, tag, true );
+				}
+				
+				public void 
+				taggableAdded(
+					Tag 		tag,
+					Taggable 	tagged ) 
+				{
+					apply((DownloadManager)tagged, tag, true );
+				}
+			}, false );
+	}
+	
+	public void
+	tagChanged(
+		Tag			tag )
+	{
+	}
+	
+	private void
+	checkTimer()
+	{
+		if ( constrained_tags.size() > 0 ){
+			
+			if ( timer == null ){
+				
+				timer = 
+					SimpleTimer.addPeriodicEvent(
+						"tag:constraint:timer",
+						30*1000,
+						new TimerEventPerformer() {
+							
+							public void 
+							perform(
+								TimerEvent event) 
+							{
+								apply_history.clear();
+								
+								apply();
+							}
+						});
+			}
+			
+		}else if ( timer != null ){
+			
+			timer.cancel();
+			
+			timer = null;
+			
+			apply_history.clear();
+		}
+	}
+	
+	public void
+	tagRemoved(
+		Tag			tag )
+	{
+		synchronized( constrained_tags ){
+			
+			if ( constrained_tags.containsKey( tag )){
+				
+				constrained_tags.remove( tag );
+				
+				checkTimer();
+			}
+		}
+	}
+	
+	private void
+	handleProperty(
+		TagProperty		property )
+	{
+		Tag	tag = property.getTag();
+				
+		synchronized( constrained_tags ){
+		
+			String[] temp = property.getStringList();
+			
+			String constraint = temp == null || temp.length < 1?"":temp[0].trim();
+						
+			if ( constraint.length() == 0 ){
+				
+				if ( constrained_tags.containsKey( tag )){
+					
+					constrained_tags.remove( tag );
+				}
+			}else{
+				
+				TagConstraint con = constrained_tags.get( tag );
+				
+				if ( con != null && con.getConstraint().equals( constraint )){
+					
+					return;
+				}
+									
+				Set<Taggable> existing = tag.getTagged();
+					
+				for ( Taggable e: existing ){
+						
+					tag.removeTaggable( e );
+				}
+			
+				con = new TagConstraint( tag, constraint );
+				
+				constrained_tags.put( tag, con );
+								
+				if ( initialised ){
+				
+					apply( con );
+				}
+			}
+			
+			checkTimer();
+		}
+	}
+	
+	private void
+	apply(
+		final DownloadManager				dm,
+		Tag									related_tag,
+		boolean								auto )
+	{
+		if ( dm.isDestroyed()){
+			
+			return;
+		}
+		
+		synchronized( constrained_tags ){
+			
+			if ( constrained_tags.size() == 0 || !initialised ){
+				
+				return;
+			}
+			
+			if ( auto && !initial_assignment_complete ){
+				
+				return;
+			}
+		}
+				
+		dispatcher.dispatch(
+			new AERunnable() 
+			{
+				public void 
+				runSupport() 
+				{
+					List<TagConstraint>	cons;
+					
+					synchronized( constrained_tags ){
+					
+						cons = new ArrayList<TagConstraint>( constrained_tags.values());
+					}
+					
+					for ( TagConstraint con: cons ){
+							
+						con.apply( dm );
+					}
+				}
+			});
+	}
+	
+	private void
+	apply(
+		final List<DownloadManager>		dms,
+		final boolean					initial_assignment )
+	{
+		synchronized( constrained_tags ){
+			
+			if ( constrained_tags.size() == 0 || !initialised ){
+				
+				return;
+			}
+		}
+		
+		dispatcher.dispatch(
+			new AERunnable() 
+			{
+				public void 
+				runSupport() 
+				{
+					List<TagConstraint>	cons;
+					
+					synchronized( constrained_tags ){
+					
+						cons = new ArrayList<TagConstraint>( constrained_tags.values());
+					}
+						
+						// set up initial constraint tagged state without following implications
+					
+					for ( TagConstraint con: cons ){
+						
+						con.apply( dms );
+					}
+						
+					if ( initial_assignment ){
+						
+						synchronized( constrained_tags ){
+						
+							initial_assignment_complete = true;
+						}
+					
+							// go over them one more time to pick up consequential constraints
+						
+						for ( TagConstraint con: cons ){
+							
+							con.apply( dms );
+						}
+					}
+				}
+			});
+	}
+	
+	private void
+	apply(
+		final TagConstraint		constraint )
+	{
+		synchronized( constrained_tags ){
+			
+			if ( !initialised ){
+				
+				return;
+			}
+		}
+		
+		dispatcher.dispatch(
+			new AERunnable() 
+			{
+				public void 
+				runSupport() 
+				{
+					List<DownloadManager> dms = azureus_core.getGlobalManager().getDownloadManagers();
+
+					constraint.apply( dms );
+				}
+			});
+	}
+	
+	private void
+	apply()
+	{
+		synchronized( constrained_tags ){
+			
+			if ( constrained_tags.size() == 0 || !initialised ){
+				
+				return;
+			}
+		}
+		
+		dispatcher.dispatch(
+			new AERunnable() 
+			{
+				public void 
+				runSupport() 
+				{
+					List<DownloadManager> dms = azureus_core.getGlobalManager().getDownloadManagers();
+					
+					List<TagConstraint>	cons;
+					
+					synchronized( constrained_tags ){
+					
+						cons = new ArrayList<TagConstraint>( constrained_tags.values());
+					}
+					
+					for ( TagConstraint con: cons ){
+						
+						con.apply( dms );
+					}
+				}
+			});
+	}
+	
+	private ConstraintExpr
+	compileConstraint(
+		String		expr )
+	{
+		return( new TagConstraint( null, expr ).expr );
+	}
+	
+	private class
+	TagConstraint
+	{
+		private Tag		tag;
+		private String	constraint;
+		
+		private ConstraintExpr	expr;
+		
+		private
+		TagConstraint(
+			Tag			_tag,
+			String		_constraint )
+		{
+			tag			= _tag;
+			constraint	= _constraint;
+		
+			try{
+				expr = compileStart( constraint, new HashMap<String,ConstraintExpr>());
+				
+			}catch( Throwable e ){
+				
+				Debug.out( "Invalid constraint: " + constraint + " - " + Debug.getNestedExceptionMessage( e ));
+			}
+		}
+		
+		private ConstraintExpr
+		compileStart(
+			String						str,
+			Map<String,ConstraintExpr>	context )
+		{		
+			str = str.trim();
+			
+			if ( str.equalsIgnoreCase( "true" )){
+				
+				return( new ConstraintExprTrue());
+			}
+			
+			char[] chars = str.toCharArray();
+				
+			boolean	in_quote 	= false;
+				
+			int	level 			= 0;
+			int	bracket_start 	= 0;
+			
+			StringBuffer result = new StringBuffer( str.length());
+			
+			for ( int i=0;i<chars.length;i++){
+					
+				char c = chars[i];
+																	
+				if ( c == '"' ){
+	
+					if ( i == 0 || chars[i-1] != '\\' ){
+						
+						in_quote = !in_quote;
+					}
+				}
+				
+				if ( !in_quote ){
+					
+					if ( c == '(' ){
+						
+						level++;
+						
+						if ( level == 1 ){
+							
+							bracket_start = i+1;
+						}
+					}else if ( c == ')' ){
+						
+						level--;
+						
+						if ( level == 0 ){
+						
+							String bracket_text = new String( chars, bracket_start, i-bracket_start ).trim();
+							
+							if ( result.length() > 0 && Character.isLetterOrDigit( result.charAt( result.length()-1 ))){
+								
+									// function call
+								
+								String key = "{" + context.size() + "}";
+								
+								context.put( key, new ConstraintExprParams( bracket_text ));
+																
+								result.append( "(" ).append( key ).append( ")" );
+								
+							}else{
+								
+								ConstraintExpr sub_expr = compileStart( bracket_text, context );
+								
+								String key = "{" + context.size() + "}";
+								
+								context.put(key, sub_expr );
+								
+								result.append( key );
+							}
+						}
+					}else if ( level == 0 ){
+						
+						if ( !Character.isWhitespace( c )){
+						
+							result.append( c );
+						}
+					}
+				}else if ( level == 0 ){
+						
+					result.append( c );
+					
+				}
+			}
+			
+			if ( level != 0 ){
+				
+				throw( new RuntimeException( "Unmatched '(' in \"" + str + "\"" ));
+			}
+			
+			if ( in_quote ){
+				
+				throw( new RuntimeException( "Unmatched '\"' in \"" + str + "\"" ));
+			}
+			
+			return( compileBasic( result.toString(), context ));
+		}
+		
+		private ConstraintExpr
+		compileBasic(
+			String						str,
+			Map<String,ConstraintExpr>	context )
+		{	
+			if ( str.startsWith( "{" )){
+				
+				return( context.get( str ));
+				
+			}else if ( str.contains( "||" )){
+				
+				String[] bits = str.split( "\\|\\|" );
+				
+				return( new ConstraintExprOr( compile( bits, context )));
+				
+			}else if ( str.contains( "&&" )){
+				
+				String[] bits = str.split( "&&" );
+				
+				return( new ConstraintExprAnd( compile( bits, context )));
+				
+			}else if ( str.contains( "^" )){
+				
+				String[] bits = str.split( "\\^" );
+				
+				return( new ConstraintExprXor( compile( bits, context )));
+				
+			}else if ( str.startsWith( "!" )){
+				
+				return( new ConstraintExprNot( compileBasic( str.substring(1).trim(), context )));
+				
+			}else{
+				
+				int	pos = str.indexOf( '(' );
+				
+				if ( pos > 0 && str.endsWith( ")" )){
+					
+					String func = str.substring( 0, pos );
+					
+					String key = str.substring( pos+1, str.length() - 1 ).trim();
+					
+					ConstraintExprParams params = (ConstraintExprParams)context.get( key );
+										
+					return( new ConstraintExprFunction( func, params ));
+
+				}else{
+					
+					throw( new RuntimeException( "Unsupported construct: " + str ));
+				}
+			}
+		}
+		
+		private ConstraintExpr[]
+		compile(
+			String[]					bits,
+			Map<String,ConstraintExpr>	context )
+		{
+			ConstraintExpr[] res = new ConstraintExpr[ bits.length ];
+			
+			for ( int i=0; i<bits.length;i++){
+				
+				res[i] = compileBasic( bits[i].trim(), context );
+			}
+			
+			return( res );
+		}
+		
+		private Tag
+		getTag()
+		{
+			return( tag );
+		}
+		
+		private String
+		getConstraint()
+		{
+			return( constraint );
+		}
+		
+		private void
+		apply(
+			DownloadManager			dm )
+		{
+			if ( dm.isDestroyed() || !dm.isPersistent()){
+				
+				return;
+			}
+
+			if ( expr == null ){
+				
+				return;
+			}
+			
+			Set<Taggable>	existing = tag.getTagged();
+						
+			if ( testConstraint( dm )){
+				
+				if ( !existing.contains( dm )){
+					
+					if( canAddTaggable( dm )){
+					
+						tag.addTaggable( dm );
+					}
+				}
+			}else{
+				
+				if ( existing.contains( dm )){
+					
+					tag.removeTaggable( dm );
+				}
+			}
+		}
+		
+		private void
+		apply(
+			List<DownloadManager>	dms )
+		{
+			if ( expr == null ){
+				
+				return;
+			}
+
+			Set<Taggable>	existing = tag.getTagged();
+			
+			for ( DownloadManager dm: dms ){
+			
+				if ( dm.isDestroyed() || !dm.isPersistent()){
+					
+					continue;
+				}
+				
+				if ( testConstraint( dm )){
+					
+					if ( !existing.contains( dm )){
+						
+						if ( canAddTaggable( dm )){
+						
+							tag.addTaggable( dm );
+						}
+					}
+				}else{
+					
+					if ( existing.contains( dm )){
+						
+						tag.removeTaggable( dm );
+					}
+				}
+			}
+		}
+		
+		private boolean
+		canAddTaggable(
+			DownloadManager		dm )
+		{
+			long	now = SystemTime.getMonotonousTime();
+				
+			Map<DownloadManager,Long> recent_dms = apply_history.get( tag );
+				
+			if ( recent_dms != null ){
+					
+				Long time = recent_dms.get( dm );
+					
+				if ( time != null && now - time < 1000 ){
+					
+					System.out.println( "Not applying constraint as too recently actioned: " + dm.getDisplayName() + "/" + tag.getTagName( true ));
+
+					return( false );
+				}
+			}
+			
+			if ( recent_dms == null ){
+					
+				recent_dms = new HashMap<DownloadManager,Long>();
+					
+				apply_history.put( tag, recent_dms );
+			}
+				
+			recent_dms.put( dm, now );
+			
+			return( true );
+		}
+		
+		private boolean
+		testConstraint(
+			DownloadManager	dm )
+		{
+			List<Tag> dm_tags = tag_manager.getTagsForTaggable( dm );
+			
+			return( expr.eval( dm, dm_tags ));
+		}
+	}
+	
+	private interface
+	ConstraintExpr
+	{
+		public boolean
+		eval(
+			DownloadManager		dm,
+			List<Tag>			tags );
+		
+		public String
+		getString();
+	}
+	
+	private class
+	ConstraintExprTrue
+		implements ConstraintExpr
+	{
+		public boolean
+		eval(
+			DownloadManager		dm,
+			List<Tag>			tags )
+		{
+			return( true );
+		}
+		
+		public String
+		getString()
+		{
+			return( "true" );
+		}
+	}
+	
+	private class
+	ConstraintExprParams
+		implements  ConstraintExpr
+	{
+		private String	value;
+		
+		private
+		ConstraintExprParams(
+			String	_value )
+		{
+			value = _value.trim();
+		}
+		
+		public boolean
+		eval(
+			DownloadManager		dm,
+			List<Tag>			tags )
+		{
+			return( false );
+		}
+		
+		public Object[]
+		getValues()
+		{
+			if ( value.length() == 0 ){
+				
+				return( new String[0]);
+				
+			}else if ( !value.contains( "," )){
+			
+				return( new Object[]{ value });
+				
+			}else{
+				
+				char[]	chars = value.toCharArray();
+				
+				boolean in_quote = false;
+				
+				List<String>	params = new ArrayList<String>(16);
+				
+				StringBuffer current_param = new StringBuffer( value.length());
+				
+				for (int i=0;i<chars.length;i++){
+				
+					char c = chars[i];
+					
+					if ( c == '"' ){
+						
+						if ( i == 0 || chars[i-1] != '\\' ){
+							
+							in_quote = !in_quote;
+						}
+					}
+					
+					if ( c == ',' && !in_quote ){
+						
+						params.add( current_param.toString());
+						
+						current_param.setLength( 0 );
+						
+					}else{
+						
+						if ( in_quote || !Character.isWhitespace( c )){
+						
+							current_param.append( c );
+						}
+					}
+				}
+				
+				params.add( current_param.toString());
+				
+				return( params.toArray( new Object[ params.size()]));
+			}
+		}
+		
+		public String
+		getString()
+		{
+			return( value );
+		}
+	}
+	
+	private class
+	ConstraintExprNot
+		implements  ConstraintExpr
+	{
+		private	ConstraintExpr expr;
+		
+		private
+		ConstraintExprNot(
+			ConstraintExpr	e )
+		{
+			expr = e;
+		}
+		
+		public boolean
+		eval(
+			DownloadManager		dm,
+			List<Tag>			tags )		
+		{
+			return( !expr.eval( dm, tags ));
+		}
+		
+		public String
+		getString()
+		{
+			return( "!(" + expr.getString() + ")");
+		}
+	}
+	
+	private class
+	ConstraintExprOr
+		implements  ConstraintExpr
+	{
+		private ConstraintExpr[]	exprs;
+		
+		private
+		ConstraintExprOr(
+			ConstraintExpr[]	_exprs )
+		{
+			exprs = _exprs;
+		}
+		
+		public boolean
+		eval(
+			DownloadManager		dm,
+			List<Tag>			tags )		
+		{
+			for ( ConstraintExpr expr: exprs ){
+				
+				if ( expr.eval( dm, tags )){
+					
+					return( true );
+				}
+			}
+			
+			return( false );
+		}
+		
+		public String
+		getString()
+		{
+			String res = "";
+			
+			for ( int i=0;i<exprs.length;i++){
+				
+				res += (i==0?"":"||") + exprs[i].getString();
+			}
+			
+			return( "(" + res + ")" );
+		}
+	}
+	
+	private class
+	ConstraintExprAnd
+		implements  ConstraintExpr
+	{
+		private ConstraintExpr[]	exprs;
+		
+		private
+		ConstraintExprAnd(
+			ConstraintExpr[]	_exprs )
+		{
+			exprs = _exprs;
+		}
+		
+		public boolean
+		eval(
+			DownloadManager		dm,
+			List<Tag>			tags )
+		{
+			for ( ConstraintExpr expr: exprs ){
+				
+				if ( !expr.eval( dm, tags )){
+					
+					return( false );
+				}
+			}
+			
+			return( true );
+		}
+		
+		public String
+		getString()
+		{
+			String res = "";
+			
+			for ( int i=0;i<exprs.length;i++){
+				
+				res += (i==0?"":"&&") + exprs[i].getString();
+			}
+			
+			return( "(" + res + ")" );
+		}
+	}
+	
+	private class
+	ConstraintExprXor
+		implements  ConstraintExpr
+	{
+		private ConstraintExpr[]	exprs;
+		
+		private
+		ConstraintExprXor(
+			ConstraintExpr[]	_exprs )
+		{
+			exprs = _exprs;
+			
+			if ( exprs.length < 2 ){
+				
+				throw( new RuntimeException( "Two or more arguments required for ^" ));
+			}
+		}
+		
+		public boolean
+		eval(
+			DownloadManager		dm,
+			List<Tag>			tags )
+		{
+			boolean res = exprs[0].eval( dm, tags );
+			
+			for ( int i=1;i<exprs.length;i++){
+				
+				res = res ^ exprs[i].eval( dm, tags );
+			}
+			
+			return( res );
+		}
+		
+		public String
+		getString()
+		{
+			String res = "";
+			
+			for ( int i=0;i<exprs.length;i++){
+				
+				res += (i==0?"":"^") + exprs[i].getString();
+			}
+			
+			return( "(" + res + ")" );
+		}
+	}
+	
+	private static final int FT_HAS_TAG		= 1;
+	private static final int FT_IS_PRIVATE	= 2;
+	
+	private static final int FT_GE			= 3;
+	private static final int FT_GT			= 4;
+	private static final int FT_LE			= 5;
+	private static final int FT_LT			= 6;
+	private static final int FT_EQ			= 7;
+	private static final int FT_NEQ			= 8;
+	
+	private static final int FT_CONTAINS	= 9;
+	private static final int FT_MATCHES		= 10;
+	
+	private static final int FT_HAS_NET		= 11;
+	private static final int FT_IS_COMPLETE	= 12;
+	private static final int FT_CAN_ARCHIVE	= 13;
+
+	
+	private class
+	ConstraintExprFunction
+		implements  ConstraintExpr
+	{
+		
+		private	final String 				func_name;
+		private final ConstraintExprParams	params_expr;
+		private final Object[]				params;
+		
+		private final int	fn_type;
+		
+		private
+		ConstraintExprFunction(
+			String 					_func_name,
+			ConstraintExprParams	_params )
+		{
+			func_name	= _func_name;
+			params_expr	= _params;
+			
+			params		= _params.getValues();
+			
+			boolean	params_ok = false;
+			
+			if ( func_name.equals( "hasTag" )){
+				
+				fn_type = FT_HAS_TAG;
+				
+				params_ok = params.length == 1 && getStringLiteral( params, 0 );
+				
+			}else if ( func_name.equals( "hasNet" )){
+					
+				fn_type = FT_HAS_NET;
+					
+				params_ok = params.length == 1 && getStringLiteral( params, 0 );
+				
+				if ( params_ok ){
+					
+					params[0] = AENetworkClassifier.internalise((String)params[0]);
+					
+					params_ok = params[0] != null;
+				}
+			}else if ( func_name.equals( "isPrivate" )){
+
+				fn_type = FT_IS_PRIVATE;
+
+				params_ok = params.length == 0;
+				
+			}else if ( func_name.equals( "isComplete" )){
+
+				fn_type = FT_IS_COMPLETE;
+
+				params_ok = params.length == 0;
+				
+			}else if ( func_name.equals( "canArchive" )){
+
+				fn_type = FT_CAN_ARCHIVE;
+
+				params_ok = params.length == 0;
+
+			}else if ( func_name.equals( "isGE" )){
+				
+				fn_type = FT_GE;
+				
+				params_ok = params.length == 2;
+				
+			}else if ( func_name.equals( "isGT" )){
+				
+				fn_type = FT_GT;
+				
+				params_ok = params.length == 2;
+				
+			}else if ( func_name.equals( "isLE" )){
+				
+				fn_type = FT_LE;
+				
+				params_ok = params.length == 2;
+				
+			}else if ( func_name.equals( "isLT" )){
+				
+				fn_type = FT_LT;
+				
+				params_ok = params.length == 2;
+				
+			}else if ( func_name.equals( "isEQ" )){
+				
+				fn_type = FT_EQ;
+				
+				params_ok = params.length == 2;
+				
+			}else if ( func_name.equals( "isNEQ" )){
+				
+				fn_type = FT_NEQ;
+				
+				params_ok = params.length == 2;
+			
+			}else if ( func_name.equals( "contains" )){
+				
+				fn_type = FT_CONTAINS;
+					
+				params_ok = params.length == 2;
+
+			}else if ( func_name.equals( "matches" )){
+				
+				fn_type = FT_MATCHES;
+					
+				params_ok = params.length == 2 && getStringLiteral( params, 1 );
+
+			}else{
+				
+				throw( new RuntimeException( "Unsupported function '" + func_name + "'" ));
+			}
+			
+			if ( !params_ok ){
+				
+				throw( new RuntimeException( "Invalid parameters for function '" + func_name + "': " + params_expr.getString()));
+
+			}
+		}
+	
+		public boolean
+		eval(
+			DownloadManager		dm,
+			List<Tag>			tags )
+		{
+			switch( fn_type ){
+				case FT_HAS_TAG:{
+				
+					String tag_name = (String)params[0];
+					
+					for ( Tag t: tags ){
+						
+						if ( t.getTagName( true ).equals( tag_name )){
+							
+							return( true );
+						}
+					}
+					
+					return( false );
+				}
+				case FT_HAS_NET:{
+					
+					String net_name = (String)params[0];
+					
+					if ( net_name != null ){
+						
+						String[] nets = dm.getDownloadState().getNetworks();
+						
+						if ( nets != null ){
+							
+							for ( String net: nets ){
+								
+								if ( net == net_name ){
+									
+									return( true );
+								}
+							}
+						}
+					}
+					
+					return( false );
+				}
+				case FT_IS_PRIVATE:{
+				
+					TOTorrent t = dm.getTorrent();
+				
+					return( t != null && t.getPrivate());
+				}
+				case FT_IS_COMPLETE:{
+					
+					return( dm.isDownloadComplete( false ));
+				}
+				case FT_CAN_ARCHIVE:{
+					
+					Download dl = PluginCoreUtils.wrap( dm );
+					
+					return( dl != null && dl.canStubbify());
+				}
+				case FT_GE:
+				case FT_GT:
+				case FT_LE:
+				case FT_LT:
+				case FT_EQ:
+				case FT_NEQ:{
+								
+					Number n1 = getNumeric( dm, params, 0 );
+					Number n2 = getNumeric( dm, params, 1 );
+				
+					switch( fn_type ){
+					
+						case FT_GE:
+							return( n1.doubleValue() >= n2.doubleValue());
+						case FT_GT:
+							return( n1.doubleValue() > n2.doubleValue());
+						case FT_LE:
+							return( n1.doubleValue() <= n2.doubleValue());
+						case FT_LT:
+							return( n1.doubleValue() < n2.doubleValue());
+						case FT_EQ:
+							return( n1.doubleValue() == n2.doubleValue());
+						case FT_NEQ:
+							return( n1.doubleValue() != n2.doubleValue());
+					}
+					
+					return( false );
+				}
+				case FT_CONTAINS:{
+					
+					String	s1 = getString( dm, params, 0 );
+					String	s2 = getString( dm, params, 1 );
+					
+					return( s1.contains( s2 ));
+				}
+				case FT_MATCHES:{
+					
+					String	s1 = getString( dm, params, 0 );
+					
+					if ( params[1] == null ){
+						
+						return( false );
+						
+					}else if ( params[1] instanceof Pattern ){
+						
+						return(((Pattern)params[1]).matcher( s1 ).find());
+						
+					}else{
+						
+						try{
+							Pattern p = Pattern.compile((String)params[1], Pattern.CASE_INSENSITIVE );
+							
+							params[1] = p;
+							
+							return( p.matcher( s1 ).find());
+							
+						}catch( Throwable e ){
+							
+							Debug.out( "Invalid constraint pattern: " + params[1] );
+							
+							params[1] = null;
+						}
+					}
+					
+					return( false );
+				}
+			}
+			
+			return( false );
+		}
+		
+		private boolean
+		getStringLiteral(
+			Object[]	args,
+			int			index )
+		{
+			Object _arg = args[index];
+			
+			if ( _arg instanceof String ){
+				
+				String arg = (String)_arg;
+			
+				if ( arg.startsWith( "\"" ) && arg.endsWith( "\"" )){
+					
+					args[index] = arg.substring( 1, arg.length() - 1 );
+					
+					return( true );
+				}
+			}
+				
+			return( false );
+		}
+		
+		private String
+		getString(
+			DownloadManager		dm,
+			Object[]			args,
+			int					index )
+		{
+			String str = (String)args[index];
+			
+			if ( str.startsWith( "\"" ) && str.endsWith( "\"" )){
+				
+				return( str.substring( 1, str.length() - 1 ));
+				
+			}else if ( str.equals( "name" )){
+				
+				return( dm.getDisplayName());
+				
+			}else{
+				
+				Debug.out( "Invalid constraint string: " + str );
+				
+				String result = "\"\"";
+				
+				args[index] = result;
+				
+				return( result );
+			}
+		}
+
+		private Number
+		getNumeric(
+			DownloadManager		dm,
+			Object[]			args,
+			int					index )
+		{
+			Object arg = args[index];
+			
+			if ( arg instanceof Number ){
+				
+				return((Number)arg);
+			}
+			
+			String str = (String)arg;
+			
+			Number result = 0;
+			
+			try{
+				if ( Character.isDigit( str.charAt(0))){
+				
+					if ( str.contains( "." )){
+						
+						result = Float.parseFloat( str );
+						
+					}else{
+						
+						result = Long.parseLong( str );
+					}
+					
+					return( result );
+					
+				}else if ( str.equals( "shareratio" )){
+					
+					result = null;	// don't cache this!
+					
+					int sr = dm.getStats().getShareRatio();
+					
+					if ( sr == -1 ){
+						
+						return( Integer.MAX_VALUE );
+						
+					}else{
+						
+						return( new Float( sr/1000.0f ));
+					}
+				}else if ( str.equals( "percent" )){
+					
+					result = null;	// don't cache this!
+					
+						// 0->1000
+					
+					int percent = dm.getStats().getPercentDoneExcludingDND();
+
+					return( new Float( percent/10.0f ));
+					
+				}else if ( str.equals( "age" )){
+					
+					result = null;	// don't cache this!
+						
+					long added = dm.getDownloadState().getLongParameter( DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME );
+
+					if ( added <= 0 ){
+						
+						return( 0 );
+					}
+					
+					return(( SystemTime.getCurrentTime() - added )/1000 );		// secs
+					
+				}else{
+					
+					Debug.out( "Invalid constraint numeric: " + str );
+					
+					return( result );
+				}
+			}catch( Throwable e){
+				
+				Debug.out( "Invalid constraint numeric: " + str );
+
+				return( result );
+				
+			}finally{
+				
+				if ( result != null ){
+					
+						// cache literal results 
+					
+					args[index] = result;
+				}
+			}
+		}
+		
+		public String
+		getString()
+		{
+			return( func_name + "(" + params_expr.getString() + ")" );
+		}
+	}
+	
+	public static void
+	main(
+		String[]	args )
+	{
+		TagPropertyConstraintHandler handler = new TagPropertyConstraintHandler();
+		
+		//System.out.println( handler.compileConstraint( "!(hasTag(\"bil\") && (hasTag( \"fred\" ))) || hasTag(\"toot\")" ).getString());
+		System.out.println( handler.compileConstraint( "isGE( shareratio, 1.5)" ).getString());
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyTrackerHandler.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyTrackerHandler.java
index 1a38900..f379ae9 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyTrackerHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyTrackerHandler.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -39,6 +38,7 @@ import com.aelitis.azureus.core.tag.TagFeatureProperties.TagProperty;
 import com.aelitis.azureus.core.tag.TagType;
 import com.aelitis.azureus.core.tag.TagTypeAdapter;
 import com.aelitis.azureus.core.tag.Taggable;
+import com.aelitis.azureus.core.tag.TaggableLifecycleAdapter;
 import com.aelitis.azureus.core.tag.TaggableLifecycleListener;
 
 public class 
@@ -60,7 +60,7 @@ TagPropertyTrackerHandler
 		
 		tag_manager.addTaggableLifecycleListener(
 			Taggable.TT_DOWNLOAD,
-			new TaggableLifecycleListener()
+			new TaggableLifecycleAdapter()
 			{
 				public void
 				initialised(
@@ -99,12 +99,6 @@ TagPropertyTrackerHandler
 				{
 					handleDownload( (DownloadManager)taggable );
 				}
-				
-				public void
-				taggableDestroyed(
-					Taggable		taggable )
-				{
-				}
 			});
 	}
 	
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyTrackerTemplateHandler.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyTrackerTemplateHandler.java
index 0163adb..315894e 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyTrackerTemplateHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyTrackerTemplateHandler.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -37,6 +36,7 @@ import com.aelitis.azureus.core.tag.TagListener;
 import com.aelitis.azureus.core.tag.TagType;
 import com.aelitis.azureus.core.tag.TagTypeAdapter;
 import com.aelitis.azureus.core.tag.Taggable;
+import com.aelitis.azureus.core.tag.TaggableLifecycleAdapter;
 import com.aelitis.azureus.core.tag.TaggableLifecycleListener;
 
 public class 
@@ -54,7 +54,7 @@ TagPropertyTrackerTemplateHandler
 		
 		tag_manager.addTaggableLifecycleListener(
 			Taggable.TT_DOWNLOAD,
-			new TaggableLifecycleListener()
+			new TaggableLifecycleAdapter()
 			{
 				public void
 				initialised(
@@ -83,18 +83,6 @@ TagPropertyTrackerTemplateHandler
 						},
 						true );
 				}
-				
-				public void
-				taggableCreated(
-					Taggable		taggable )
-				{
-				}
-				
-				public void
-				taggableDestroyed(
-					Taggable		taggable )
-				{
-				}
 			});
 	}
 
@@ -156,7 +144,7 @@ TagPropertyTrackerTemplateHandler
 						
 					}else{
 						
-						trackers = TorrentUtils.removeAnnounceURLs( trackers, template_trackers );
+						trackers = TorrentUtils.removeAnnounceURLs( trackers, template_trackers, true );
 					}
 					
 					TorrentUtils.listToAnnounceGroups( trackers, torrent );
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyUntaggedHandler.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyUntaggedHandler.java
index 532683e..d396d16 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyUntaggedHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagPropertyUntaggedHandler.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -70,7 +69,7 @@ TagPropertyUntaggedHandler
 		
 		tag_manager.addTaggableLifecycleListener(
 			Taggable.TT_DOWNLOAD,
-			new TaggableLifecycleListener()
+			new TaggableLifecycleAdapter()
 			{
 				public void
 				initialised(
@@ -147,12 +146,6 @@ TagPropertyUntaggedHandler
 				{
 					addDownloads( Arrays.asList( new DownloadManager[]{ (DownloadManager)taggable }));
 				}
-				
-				public void
-				taggableDestroyed(
-					Taggable		taggable )
-				{
-				}
 			});
 	}
 	
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeBase.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeBase.java
index 4c0148d..16096da 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeBase.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeBase.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -404,6 +403,8 @@ TagTypeBase
 				}
 			}
 		}
+		
+		manager.taggableRemoved( this, tag, tagged );
 	}
 	
 	public void
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeDownloadManual.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeDownloadManual.java
index 417a4c1..ba8f15c 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeDownloadManual.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeDownloadManual.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeWithState.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeWithState.java
index 186abf4..53f9e77 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeWithState.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagTypeWithState.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagWithState.java b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagWithState.java
index 6c3505b..7c6cd83 100644
--- a/azureus2/src/com/aelitis/azureus/core/tag/impl/TagWithState.java
+++ b/azureus2/src/com/aelitis/azureus/core/tag/impl/TagWithState.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -112,7 +111,8 @@ TagWithState
 						
 					}else{
 						
-						Debug.out( "No taggable ID for " + taggable );
+						// Get this when the taggable is a download that has lost its torrent
+						// Debug.out( "No taggable ID for " + taggable );
 					}
 				}catch( Throwable e ){
 					
diff --git a/azureus2/src/com/aelitis/azureus/core/tracker/TrackerPeerSource.java b/azureus2/src/com/aelitis/azureus/core/tracker/TrackerPeerSource.java
index b8a5fdb..4935284 100644
--- a/azureus2/src/com/aelitis/azureus/core/tracker/TrackerPeerSource.java
+++ b/azureus2/src/com/aelitis/azureus/core/tracker/TrackerPeerSource.java
@@ -1,103 +1,102 @@
-/*
- * Created on Dec 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.core.tracker;
-
-public interface 
-TrackerPeerSource 
-{
-	public static final int TP_UNKNOWN		= 0;
-	public static final int TP_TRACKER		= 1;
-	public static final int TP_HTTP_SEED	= 2;
-	public static final int TP_DHT			= 3;
-	public static final int TP_LAN			= 4;
-	public static final int TP_PEX			= 5;
-	public static final int TP_INCOMING		= 6;
-	public static final int TP_PLUGIN		= 7;
-	
-	public static final int ST_UNKNOWN		= 0;
-	public static final int ST_DISABLED		= 1;
-	public static final int ST_STOPPED		= 2;
-	public static final int ST_QUEUED		= 3;
-	public static final int ST_UPDATING		= 4;
-	public static final int ST_ONLINE 		= 5;
-	public static final int ST_ERROR		= 6;
-	public static final int ST_AVAILABLE	= 7;
-	public static final int ST_UNAVAILABLE	= 8;
-	public static final int ST_INITIALISING	= 9;
-
-	
-	public int
-	getType();
-	
-	public String
-	getName();
-	
-	public int
-	getStatus();
-	
-	public String
-	getStatusString();
-	
-	public int
-	getSeedCount();
-	
-	public int
-	getLeecherCount();
-	
-	public int
-	getPeers();
-	
-		/**
-		 * If the tracker source supports 'number downloads completed' this will be >= 0 
-		 * @return
-		 */
-	
-	public int
-	getCompletedCount();
-	
-	public int
-	getLastUpdate();
-	
-	public int
-	getSecondsToUpdate();
-	
-	public int
-	getInterval();
-	
-	public int
-	getMinInterval();
-	
-	public boolean
-	isUpdating();
-	
-	public boolean
-	canManuallyUpdate();
-	
-	public void
-	manualUpdate();
-	
-	public boolean
-	canDelete();
-	
-	public void
-	delete();
-}
+/*
+ * Created on Dec 8, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.tracker;
+
+public interface 
+TrackerPeerSource 
+{
+	public static final int TP_UNKNOWN		= 0;
+	public static final int TP_TRACKER		= 1;
+	public static final int TP_HTTP_SEED	= 2;
+	public static final int TP_DHT			= 3;
+	public static final int TP_LAN			= 4;
+	public static final int TP_PEX			= 5;
+	public static final int TP_INCOMING		= 6;
+	public static final int TP_PLUGIN		= 7;
+	
+	public static final int ST_UNKNOWN		= 0;
+	public static final int ST_DISABLED		= 1;
+	public static final int ST_STOPPED		= 2;
+	public static final int ST_QUEUED		= 3;
+	public static final int ST_UPDATING		= 4;
+	public static final int ST_ONLINE 		= 5;
+	public static final int ST_ERROR		= 6;
+	public static final int ST_AVAILABLE	= 7;
+	public static final int ST_UNAVAILABLE	= 8;
+	public static final int ST_INITIALISING	= 9;
+
+	
+	public int
+	getType();
+	
+	public String
+	getName();
+	
+	public int
+	getStatus();
+	
+	public String
+	getStatusString();
+	
+	public int
+	getSeedCount();
+	
+	public int
+	getLeecherCount();
+	
+	public int
+	getPeers();
+	
+		/**
+		 * If the tracker source supports 'number downloads completed' this will be >= 0 
+		 * @return
+		 */
+	
+	public int
+	getCompletedCount();
+	
+	public int
+	getLastUpdate();
+	
+	public int
+	getSecondsToUpdate();
+	
+	public int
+	getInterval();
+	
+	public int
+	getMinInterval();
+	
+	public boolean
+	isUpdating();
+	
+	public boolean
+	canManuallyUpdate();
+	
+	public void
+	manualUpdate();
+	
+	public boolean
+	canDelete();
+	
+	public void
+	delete();
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/tracker/TrackerPeerSourceAdapter.java b/azureus2/src/com/aelitis/azureus/core/tracker/TrackerPeerSourceAdapter.java
index 64dae5d..d4e7e9a 100644
--- a/azureus2/src/com/aelitis/azureus/core/tracker/TrackerPeerSourceAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/core/tracker/TrackerPeerSourceAdapter.java
@@ -1,131 +1,130 @@
-/*
- * Created on Dec 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.tracker;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-public abstract class 
-TrackerPeerSourceAdapter 
-	implements TrackerPeerSource
-{
-	public int
-	getType()
-	{
-		return( TP_UNKNOWN );
-	}
-	
-	public String
-	getName()
-	{
-		return( "" );
-	}
-	
-	public int
-	getStatus()
-	{
-		return( ST_UNKNOWN );
-	}
-	
-	public String
-	getStatusString()
-	{
-		return( null );
-	}
-	
-	public int
-	getSeedCount()
-	{
-		return( -1 );
-	}
-	
-	public int
-	getLeecherCount()
-	{
-		return( -1 );
-	}
-	
-	public int
-	getPeers()
-	{
-		return( -1 );
-	}
-	
-	public int
-	getCompletedCount()
-	{
-		return( -1 );
-	}
-	
-	public int
-	getLastUpdate() 
-	{
-		return( 0 );
-	}
-	
-	public int
-	getSecondsToUpdate()
-	{
-		return( -1 );
-	}
-	
-	public int
-	getInterval()
-	{
-		return( -1 );
-	}
-	
-	public int
-	getMinInterval()
-	{
-		return( -1 );
-	}
-	
-	public boolean
-	isUpdating()
-	{
-		return( false );
-	}
-	
-	public boolean
-	canManuallyUpdate()
-	{
-		return( false );
-	}
-	
-	public void
-	manualUpdate()
-	{
-		Debug.out( "derp" );
-	}
-	
-	public boolean 
-	canDelete() 
-	{
-		return( false );
-	}
-	
-	public void 
-	delete() 
-	{
-		Debug.out( "derp" );
-	}
-}
+/*
+ * Created on Dec 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.tracker;
+
+import org.gudy.azureus2.core3.util.Debug;
+
+public abstract class 
+TrackerPeerSourceAdapter 
+	implements TrackerPeerSource
+{
+	public int
+	getType()
+	{
+		return( TP_UNKNOWN );
+	}
+	
+	public String
+	getName()
+	{
+		return( "" );
+	}
+	
+	public int
+	getStatus()
+	{
+		return( ST_UNKNOWN );
+	}
+	
+	public String
+	getStatusString()
+	{
+		return( null );
+	}
+	
+	public int
+	getSeedCount()
+	{
+		return( -1 );
+	}
+	
+	public int
+	getLeecherCount()
+	{
+		return( -1 );
+	}
+	
+	public int
+	getPeers()
+	{
+		return( -1 );
+	}
+	
+	public int
+	getCompletedCount()
+	{
+		return( -1 );
+	}
+	
+	public int
+	getLastUpdate() 
+	{
+		return( 0 );
+	}
+	
+	public int
+	getSecondsToUpdate()
+	{
+		return( -1 );
+	}
+	
+	public int
+	getInterval()
+	{
+		return( -1 );
+	}
+	
+	public int
+	getMinInterval()
+	{
+		return( -1 );
+	}
+	
+	public boolean
+	isUpdating()
+	{
+		return( false );
+	}
+	
+	public boolean
+	canManuallyUpdate()
+	{
+		return( false );
+	}
+	
+	public void
+	manualUpdate()
+	{
+		Debug.out( "derp" );
+	}
+	
+	public boolean 
+	canDelete() 
+	{
+		return( false );
+	}
+	
+	public void 
+	delete() 
+	{
+		Debug.out( "derp" );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/update/AzureusRestarter.java b/azureus2/src/com/aelitis/azureus/core/update/AzureusRestarter.java
index 5d7f778..95546fd 100644
--- a/azureus2/src/com/aelitis/azureus/core/update/AzureusRestarter.java
+++ b/azureus2/src/com/aelitis/azureus/core/update/AzureusRestarter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/update/AzureusRestarterFactory.java b/azureus2/src/com/aelitis/azureus/core/update/AzureusRestarterFactory.java
index 1341162..806df2d 100644
--- a/azureus2/src/com/aelitis/azureus/core/update/AzureusRestarterFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/update/AzureusRestarterFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/update/impl/AzureusRestarterImpl.java b/azureus2/src/com/aelitis/azureus/core/update/impl/AzureusRestarterImpl.java
index 3199878..e27f74f 100644
--- a/azureus2/src/com/aelitis/azureus/core/update/impl/AzureusRestarterImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/update/impl/AzureusRestarterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 16, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.update.impl;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/AEPriorityMixin.java b/azureus2/src/com/aelitis/azureus/core/util/AEPriorityMixin.java
index 426c699..a6835db 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/AEPriorityMixin.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/AEPriorityMixin.java
@@ -2,20 +2,19 @@
  * Created on Sep 9, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/AZ3Functions.java b/azureus2/src/com/aelitis/azureus/core/util/AZ3Functions.java
index 372cce1..1cd1629 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/AZ3Functions.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/AZ3Functions.java
@@ -1,110 +1,115 @@
-/*
- * Created on Jan 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 com.aelitis.azureus.core.util;
-
-import java.net.URL;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-
-public class 
-AZ3Functions 
-{
-	private static volatile provider	provider;
-	
-	public static void
-	setProvider(
-		provider		_p )
-	{
-		provider	= _p;
-	}
-	
-	public static provider
-	getProvider()
-	{
-		return( provider );
-	}
-	
-	public interface
-	provider
-	{
-		public static int SERVICE_SITE_RELATIVE = 27;
-
-		public void
-		subscribeToRSS(
-			String		name,
-			URL 		url,
-			int			interval,
-			boolean		is_public,
-			String		creator_ref )
-		
-			throws Exception;
-		
-		public void
-		openRemotePairingWindow();
-		
-		public boolean
-		canPlay(
-			DownloadManager		dm,
-			int					file_index );
-		
-		public void
-		play(
-			DownloadManager		dm,
-			int					file_index );
-
-		public void
-		setOpened(
-			DownloadManager		dm,
-			boolean				opened );
-		
-		public TranscodeTarget[]
-		getTranscodeTargets();
-		
-		public interface
-		TranscodeTarget
-		{
-			public String
-			getID();
-			
-			public String
-			getName();
-			
-			public TranscodeProfile[]
-			getProfiles();
-		}
-		
-		public interface
-		TranscodeProfile
-		{
-			public String
-			getUID();
-			
-			public String
-			getName();
-		}
-
-		public String
-		getDefaultContentNetworkURL(
-				int type, 
-				Object[] params);
-	}
-}
+/*
+ * Created on Jan 7, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.util;
+
+import java.net.URL;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+
+public class 
+AZ3Functions 
+{
+	private static volatile provider	provider;
+	
+	public static void
+	setProvider(
+		provider		_p )
+	{
+		provider	= _p;
+	}
+	
+	public static provider
+	getProvider()
+	{
+		return( provider );
+	}
+	
+	public interface
+	provider
+	{
+		public static int SERVICE_SITE_RELATIVE = 27;
+
+		public void
+		subscribeToRSS(
+			String		name,
+			URL 		url,
+			int			interval,
+			boolean		is_public,
+			String		creator_ref )
+		
+			throws Exception;
+		
+		public void
+		subscribeToSubscription(
+			String		uri )
+		
+			throws Exception;
+		
+		public void
+		openRemotePairingWindow();
+		
+		public boolean
+		canPlay(
+			DownloadManager		dm,
+			int					file_index );
+		
+		public void
+		play(
+			DownloadManager		dm,
+			int					file_index );
+
+		public void
+		setOpened(
+			DownloadManager		dm,
+			boolean				opened );
+		
+		public TranscodeTarget[]
+		getTranscodeTargets();
+		
+		public interface
+		TranscodeTarget
+		{
+			public String
+			getID();
+			
+			public String
+			getName();
+			
+			public TranscodeProfile[]
+			getProfiles();
+		}
+		
+		public interface
+		TranscodeProfile
+		{
+			public String
+			getUID();
+			
+			public String
+			getName();
+		}
+
+		public String
+		getDefaultContentNetworkURL(
+				int type, 
+				Object[] params);
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/util/ByteCountedInputStream.java b/azureus2/src/com/aelitis/azureus/core/util/ByteCountedInputStream.java
index a589ed9..6f40226 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/ByteCountedInputStream.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/ByteCountedInputStream.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 8, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/CaseSensitiveFileMap.java b/azureus2/src/com/aelitis/azureus/core/util/CaseSensitiveFileMap.java
index 3a09640..eaf71de 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/CaseSensitiveFileMap.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/CaseSensitiveFileMap.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteList.java b/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteList.java
index ee15baf..ce63fd8 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteList.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteList.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -70,7 +67,9 @@ implements Iterable<T>
 							}
 						}
 						writer.println(count + " lists with " + size + " total entries");
-						writer.println((size/count) + " avg size");
+						if ( count > 0 ){
+							writer.println((size/count) + " avg size");
+						}
 					} catch (Throwable t) {
 					} finally {
 						writer.exdent();
diff --git a/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteMap.java b/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteMap.java
index cf87b24..6985361 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteMap.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteMap.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.util;
 
@@ -27,31 +24,44 @@ import java.util.Map;
  * @author Allan Crooks
  *
  */
-public class CopyOnWriteMap {
-	private volatile Map map;
+public class CopyOnWriteMap<K,V> {
+	private volatile Map<K,V> map;
 	
 	public CopyOnWriteMap() {
-		this.map = new HashMap(0);
+		this.map = new HashMap<K,V>(4);
 	}
 	
-	public void put(Object key, Object val) {
+	public V put(K key, V val) {
 		synchronized(this) {
-			HashMap new_map = new HashMap(map);
-			new_map.put(key, val);
+			HashMap<K,V> new_map = new HashMap<K,V>(map);
+			V result = new_map.put(key, val);
 			this.map = new_map;
+			return( result );
 		}
 	}
 	
-	public Object remove(Object key) {
+	public void putAll(Map<K,V> m ) {
 		synchronized(this) {
-			HashMap new_map = new HashMap(map);
-			Object res = new_map.remove(key);
+			HashMap<K,V> new_map = new HashMap<K,V>(map);
+			new_map.putAll( m );
+			this.map = new_map;
+		}
+	}
+	
+	public void putAll( CopyOnWriteMap<K,V> m ){
+		putAll( m.map );
+	}
+	
+	public V remove(Object key) {
+		synchronized(this) {
+			HashMap<K,V> new_map = new HashMap<K,V>(map);
+			V res = new_map.remove(key);
 			this.map = new_map;
 			return res;
 		}
 	}
 	
-	public Object get(Object key) {
+	public V get(K key) {
 		return this.map.get(key);
 	}
 	
diff --git a/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteSet.java b/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteSet.java
index c19e592..5bf4b16 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteSet.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/CopyOnWriteSet.java
@@ -1,196 +1,195 @@
-/*
- * Created on May 30, 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.core.util;
-
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-public class 
-CopyOnWriteSet<T> 
-{
-	private boolean	is_identify;
-	
-	private volatile Set<T>	set;
-	
-	private boolean	visible = false;
-	
-	public 
-	CopyOnWriteSet(
-		boolean	identity_hash_set )
-	{
-		is_identify = identity_hash_set;
-		
-		if ( is_identify ){
-			
-			set = new IdentityHashSet<T>();
-			
-		}else{
-			
-			set = new HashSet<T>();
-		}
-	}
-	
-	public void
-	add(
-		T		o )
-	{
-		synchronized( this ){
-			
-			if ( visible ){
-			
-				Set<T> new_set;
-				
-				if ( is_identify ){
-					
-					new_set = new IdentityHashSet<T>( set );
-					
-				}else{
-					
-					new_set = new HashSet<T>( set );
-				}
-			
-				new_set.add( o );
-			
-				set = new_set;
-				
-				visible = false;
-				
-			}else{
-				
-				set.add( o );
-			}
-		}
-	}
-	
-	public boolean
-	remove(
-		T		o )
-	{
-		synchronized( this ){
-			
-			if ( visible ){
-				
-				Set<T> new_set;
-				
-				if ( is_identify ){
-					
-					new_set = new IdentityHashSet<T>( set );
-					
-				}else{
-					
-					new_set = new HashSet<T>( set );
-				}
-				
-				boolean res = new_set.remove( o );
-				
-				set = new_set;
-				
-				visible = false;
-				
-				return( res );
-				
-			}else{
-				
-				return( set.remove( o ));
-			}
-		}
-	}
-	
-	public boolean
-	contains(
-		T	o )
-	{
-		return( set.contains( o ));
-	}
-	
-	public int
-	size()
-	{
-		return( set.size());
-	}
-	
-	public Set<T>
-	getSet()
-	{
-		synchronized( this ){
-
-			visible = true;
-			
-			return( set );
-		}
-	}
-	
-	public Iterator<T>
-	iterator()
-	{
-		synchronized( this ){
-
-			visible = true;
-		
-			return( new CopyOnWriteSetIterator( set.iterator()));
-		}
-	}
-	
-	private class
-	CopyOnWriteSetIterator
-		implements Iterator<T>
-	{
-		private Iterator<T>	it;
-		private T			last;
-		
-		protected
-		CopyOnWriteSetIterator(
-			Iterator<T>		_it )
-		{
-			it		= _it;
-		}
-		
-		public boolean
-		hasNext()
-		{
-			return( it.hasNext());
-		}
-		
-		public T
-		next()
-		{
-			last	= it.next();
-			
-			return( last );
-		}
-		
-		public void
-		remove()
-		{
-				// don't actually remove it from the iterator. can't go backwards with this iterator so this is
-				// not a problem
-			
-			if ( last == null ){
-			
-				throw( new IllegalStateException( "next has not been called!" ));
-			}
-			
-			CopyOnWriteSet.this.remove( last );
-		}
-	}
-}
+/*
+ * Created on May 30, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.util;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class 
+CopyOnWriteSet<T> 
+{
+	private boolean	is_identify;
+	
+	private volatile Set<T>	set;
+	
+	private boolean	visible = false;
+	
+	public 
+	CopyOnWriteSet(
+		boolean	identity_hash_set )
+	{
+		is_identify = identity_hash_set;
+		
+		if ( is_identify ){
+			
+			set = new IdentityHashSet<T>();
+			
+		}else{
+			
+			set = new HashSet<T>();
+		}
+	}
+	
+	public void
+	add(
+		T		o )
+	{
+		synchronized( this ){
+			
+			if ( visible ){
+			
+				Set<T> new_set;
+				
+				if ( is_identify ){
+					
+					new_set = new IdentityHashSet<T>( set );
+					
+				}else{
+					
+					new_set = new HashSet<T>( set );
+				}
+			
+				new_set.add( o );
+			
+				set = new_set;
+				
+				visible = false;
+				
+			}else{
+				
+				set.add( o );
+			}
+		}
+	}
+	
+	public boolean
+	remove(
+		T		o )
+	{
+		synchronized( this ){
+			
+			if ( visible ){
+				
+				Set<T> new_set;
+				
+				if ( is_identify ){
+					
+					new_set = new IdentityHashSet<T>( set );
+					
+				}else{
+					
+					new_set = new HashSet<T>( set );
+				}
+				
+				boolean res = new_set.remove( o );
+				
+				set = new_set;
+				
+				visible = false;
+				
+				return( res );
+				
+			}else{
+				
+				return( set.remove( o ));
+			}
+		}
+	}
+	
+	public boolean
+	contains(
+		T	o )
+	{
+		return( set.contains( o ));
+	}
+	
+	public int
+	size()
+	{
+		return( set.size());
+	}
+	
+	public Set<T>
+	getSet()
+	{
+		synchronized( this ){
+
+			visible = true;
+			
+			return( set );
+		}
+	}
+	
+	public Iterator<T>
+	iterator()
+	{
+		synchronized( this ){
+
+			visible = true;
+		
+			return( new CopyOnWriteSetIterator( set.iterator()));
+		}
+	}
+	
+	private class
+	CopyOnWriteSetIterator
+		implements Iterator<T>
+	{
+		private Iterator<T>	it;
+		private T			last;
+		
+		protected
+		CopyOnWriteSetIterator(
+			Iterator<T>		_it )
+		{
+			it		= _it;
+		}
+		
+		public boolean
+		hasNext()
+		{
+			return( it.hasNext());
+		}
+		
+		public T
+		next()
+		{
+			last	= it.next();
+			
+			return( last );
+		}
+		
+		public void
+		remove()
+		{
+				// don't actually remove it from the iterator. can't go backwards with this iterator so this is
+				// not a problem
+			
+			if ( last == null ){
+			
+				throw( new IllegalStateException( "next has not been called!" ));
+			}
+			
+			CopyOnWriteSet.this.remove( last );
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/util/DNSUtils.java b/azureus2/src/com/aelitis/azureus/core/util/DNSUtils.java
index 2ee43e2..e792654 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/DNSUtils.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/DNSUtils.java
@@ -1,106 +1,105 @@
-/*
- * Created on Jun 11, 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.util;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.List;
-
-
-import org.gudy.azureus2.core3.util.Debug;
-
-
-public class 
-DNSUtils 
-{
-	private static DNSUtilsIntf impl;
-	
-	static{
-		String cla = System.getProperty( "az.factory.dnsutils.impl", "com.aelitis.azureus.core.util.dns.DNSUtilsImpl" );
-		
-		try{
-			impl = (DNSUtilsIntf)Class.forName( cla ).newInstance();
-			
-		}catch( Throwable e ){
-			
-			Debug.out( "Failed to instantiate impl: " + cla, e );
-		}
-	}
-		
-	public static DNSUtilsIntf
-	getSingleton()
-	{
-		return( impl );
-	}
-	
-	public interface
-	DNSUtilsIntf
-	{
-		public DNSDirContext
-		getInitialDirContext()
-		
-			throws Exception;
-		
-		public DNSDirContext
-		getDirContextForServer(
-			String		dns_server_ip )
-		
-			throws Exception;
-		
-		public Inet6Address
-		getIPV6ByName(
-			String		host )
-		
-			throws UnknownHostException;
-		
-		public List<InetAddress>
-		getAllByName(
-			String		host )
-			
-			throws UnknownHostException;
-
-		public List<InetAddress>
-		getAllByName(
-			DNSUtils.DNSDirContext	context,
-			String					host )
-			
-			throws UnknownHostException;
-		
-		public List<String>
-		getTXTRecords(
-			String		query );
-		
-		public String
-		getTXTRecord(
-			String		query )
-		
-			throws UnknownHostException;
-	}
-	
-	public interface
-	DNSDirContext
-	{
-		public String
-		getString();
-	}
-}
+/*
+ * Created on Jun 11, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.util;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+
+
+import org.gudy.azureus2.core3.util.Debug;
+
+
+public class 
+DNSUtils 
+{
+	private static DNSUtilsIntf impl;
+	
+	static{
+		String cla = System.getProperty( "az.factory.dnsutils.impl", "com.aelitis.azureus.core.util.dns.DNSUtilsImpl" );
+		
+		try{
+			impl = (DNSUtilsIntf)Class.forName( cla ).newInstance();
+			
+		}catch( Throwable e ){
+			
+			Debug.out( "Failed to instantiate impl: " + cla, e );
+		}
+	}
+		
+	public static DNSUtilsIntf
+	getSingleton()
+	{
+		return( impl );
+	}
+	
+	public interface
+	DNSUtilsIntf
+	{
+		public DNSDirContext
+		getInitialDirContext()
+		
+			throws Exception;
+		
+		public DNSDirContext
+		getDirContextForServer(
+			String		dns_server_ip )
+		
+			throws Exception;
+		
+		public Inet6Address
+		getIPV6ByName(
+			String		host )
+		
+			throws UnknownHostException;
+		
+		public List<InetAddress>
+		getAllByName(
+			String		host )
+			
+			throws UnknownHostException;
+
+		public List<InetAddress>
+		getAllByName(
+			DNSUtils.DNSDirContext	context,
+			String					host )
+			
+			throws UnknownHostException;
+		
+		public List<String>
+		getTXTRecords(
+			String		query );
+		
+		public String
+		getTXTRecord(
+			String		query )
+		
+			throws UnknownHostException;
+	}
+	
+	public interface
+	DNSDirContext
+	{
+		public String
+		getString();
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/util/DeleteFileOnCloseInputStream.java b/azureus2/src/com/aelitis/azureus/core/util/DeleteFileOnCloseInputStream.java
index 6cc156f..b2c73db 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/DeleteFileOnCloseInputStream.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/DeleteFileOnCloseInputStream.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 8, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/FeatureAvailability.java b/azureus2/src/com/aelitis/azureus/core/util/FeatureAvailability.java
index c83c322..cc8356f 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/FeatureAvailability.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/FeatureAvailability.java
@@ -1,7 +1,7 @@
 /*
  * Created on Nov 6, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/GeneralUtils.java b/azureus2/src/com/aelitis/azureus/core/util/GeneralUtils.java
index bc06d48..2f7e102 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/GeneralUtils.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/GeneralUtils.java
@@ -1,374 +1,373 @@
-/*
- * Created on Jun 9, 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.core.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.config.ParameterListener;
-import org.gudy.azureus2.core3.util.Constants;
-
-import com.aelitis.azureus.core.util.average.AverageFactory;
-import com.aelitis.azureus.core.util.average.MovingImmediateAverage;
-
-public class 
-GeneralUtils 
-{
-		/**
-		 * string.replaceAll does \\ and $ expansion in replacement, this doesn't, in fact it
-		 * doesn't do any pattern matching at all, it is a literal replacement
-		 * @param str
-		 * @param from_str		= NOTE, no regex support
-		 * @param replacement
-		 * @return
-		 */
-
-        // XXX: This doesn't appear to be used...
-    public static String
-	replaceAll(
-		String	str,
-		String	from_str,
-		String	replacement )
-	{
-		StringBuffer	res = null;
-				
-		int	pos = 0;
-		
-		while( true ){
-		
-			int	p1 = str.indexOf( from_str, pos );
-			
-			if ( p1 == -1 ){
-				
-				if ( res == null ){
-				
-					return( str );
-				}
-				
-				res.append( str.substring( pos ));
-				
-				return( res.toString());
-				
-			}else{
-				
-				if ( res == null ){
-					
-					res = new StringBuffer( str.length() * 2 );
-				}
-				
-				if ( p1 > pos ){
-					
-					res.append( str.substring( pos, p1 ));
-				}
-				
-				res.append( replacement );
-				
-				pos = p1 + from_str.length();
-			}
-		}
-	}
-	
-	/**
-	 * as above but does safe replacement of multiple strings (i.e. a match in the replacement
-	 * of one string won't be substituted by another)
-	 * @param str
-	 * @param from_strs
-	 * @param to_strs
-	 * @return
-	 */
-	public static String
-	replaceAll(
-		String		str,
-		String[]	from_strs,
-		String[]	to_strs )
-	{
-		StringBuffer	res = null;
-				
-		int	pos = 0;
-		
-		while( true ){
-		
-			int	min_match_pos 	= Integer.MAX_VALUE;
-			int	match_index		= -1;
-			
-			for ( int i=0;i<from_strs.length;i++ ){
-			
-				int	pt = str.indexOf( from_strs[i], pos );
-				
-				if ( pt != -1 ){
-					
-					if ( pt < min_match_pos ){
-						
-						min_match_pos		= pt;
-						match_index			= i;
-					}
-				}
-			}
-			
-			if ( match_index == -1 ){
-				
-				if ( res == null ){
-				
-					return( str );
-				}
-				
-				res.append( str.substring( pos ));
-				
-				return( res.toString());
-				
-			}else{
-				
-				if ( res == null ){
-					
-					res = new StringBuffer( str.length() * 2 );
-				}
-				
-				if ( min_match_pos > pos ){
-					
-					res.append( str.substring( pos, min_match_pos ));
-				}
-				
-				res.append( to_strs[match_index] );
-				
-				pos = min_match_pos + from_strs[match_index].length();
-			}
-		}
-	}
-	
-	private final static String REGEX_URLHTML = "<A HREF=\"(.+?)\">(.+?)</A>";
-	public static String stripOutHyperlinks(String message) {
-		return Pattern.compile(REGEX_URLHTML, Pattern.CASE_INSENSITIVE).matcher(
-				message).replaceAll("$2");
-	}
-	
-		/**
-		 * splits space separated tokens respecting quotes (either " or ' )
-		 * @param str
-		 * @return
-		 */
-		
-	public static String[]
-	splitQuotedTokens(
-		String		str )
-	{
-		List<String>	bits = new ArrayList<String>();
-		
-		char	quote 				= ' ';
-		boolean	escape 				= false;
-		boolean	bit_contains_quotes = false;
-			
-		String	bit = "";
-		
-		char[] chars = str.toCharArray();
-		
-		for (int i=0;i<chars.length;i++){
-			
-			char c = chars[i];
-			
-			if ( Character.isWhitespace(c)){
-				
-				c = ' ';
-			}
-			
-			if ( escape ){
-				
-				bit += c;
-				
-				escape = false;
-				
-				continue;
-				
-			}else if ( c == '\\' ){
-				
-				escape = true;
-				
-				continue;
-			}
-			
-			if ( c == '"' || c == '\'' && ( i == 0 || chars[ i-1 ] != '\\' )){
-				
-				if ( quote == ' ' ){
-						
-					bit_contains_quotes = true;
-					
-					quote = c;
-					
-				}else if ( quote == c ){
-										
-					quote = ' ';
-					
-				}else{
-					
-					bit += c;
-				}
-			}else{
-				
-				if ( quote == ' ' ){
-					
-					if ( c == ' ' ){
-						
-						if ( bit.length() > 0 || bit_contains_quotes ){
-							
-							bit_contains_quotes = false;
-							
-							bits.add( bit );
-							
-							bit = "";
-						}
-					}else{
-					
-						bit += c;
-					}
-				}else{
-					
-					bit += c;
-				}
-			}
-		}	
-		
-		if ( quote != ' ' ){
-			
-			bit += quote;
-		}
-		
-		if ( bit.length() > 0 || bit_contains_quotes ){
-			
-			bits.add( bit );
-		}
-		
-		return( bits.toArray( new String[bits.size()]));
-	}
-	
-	public static ProcessBuilder 
-	createProcessBuilder(
-		File workingDir,
-		String[] cmd, 
-		String[] extra_env) 
-	
-		throws IOException 
-	{
-		ProcessBuilder pb;
-
-		Map<String, String> newEnv = new HashMap<String, String>();
-		newEnv.putAll(System.getenv());
-		newEnv.put("LANG", "C.UTF-8");
-		if (extra_env != null && extra_env.length > 1) {
-			for (int i = 1; i < extra_env.length; i += 2) {
-				newEnv.put(extra_env[i - 1], extra_env[i]);
-			}
-		}
-
-		if ( Constants.isWindows ){
-			String[] i18n = new String[cmd.length + 2];
-			i18n[0] = "cmd";
-			i18n[1] = "/C";
-			i18n[2] = escapeDosCmd(cmd[0]);
-			for (int counter = 1; counter < cmd.length; counter++) {
-				if (cmd[counter].length() == 0) {
-					i18n[counter + 2] = "";
-				} else {
-					String envName = "JENV_" + counter;
-					i18n[counter + 2] = "%" + envName + "%";
-					newEnv.put(envName, cmd[counter]);
-				}
-			}
-			cmd = i18n;
-		}
-
-		pb = new ProcessBuilder(cmd);
-		Map<String, String> env = pb.environment();
-		env.putAll(newEnv);
-
-		if (workingDir != null) {
-			pb.directory(workingDir);
-		}
-		return pb;
-	}
-
-	private static String escapeDosCmd(String string) {
-		String s = string.replaceAll("([&%^])", "^$1");
-		s = s.replaceAll("'", "\"'\"");
-		return s;
-	}
-	
-	private static int SMOOTHING_UPDATE_WINDOW	 	= 60;
-	private static int SMOOTHING_UPDATE_INTERVAL 	= 1;
-
-	
-	static{
-		COConfigurationManager.addAndFireParameterListener(
-			"Stats Smoothing Secs",
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					String name ) 
-				{
-					SMOOTHING_UPDATE_WINDOW	= COConfigurationManager.getIntParameter( "Stats Smoothing Secs" );
-				
-					if ( SMOOTHING_UPDATE_WINDOW < 30 ){
-						
-						SMOOTHING_UPDATE_WINDOW = 30;
-						
-					}else if ( SMOOTHING_UPDATE_WINDOW > 30*60 ){
-						
-						SMOOTHING_UPDATE_WINDOW = 30*60;
-					}
-					
-					SMOOTHING_UPDATE_INTERVAL = SMOOTHING_UPDATE_WINDOW/60;
-					
-					if ( SMOOTHING_UPDATE_INTERVAL < 1 ){
-						
-						SMOOTHING_UPDATE_INTERVAL = 1;
-						
-					}else if ( SMOOTHING_UPDATE_INTERVAL > 20 ){
-						
-						SMOOTHING_UPDATE_INTERVAL = 20;
-					}
-				}
-			});
-	}
-	
-	public static int
-	getSmoothUpdateWindow()
-	{
-		return( SMOOTHING_UPDATE_WINDOW );
-	}
-	
-	public static int
-	getSmoothUpdateInterval()
-	{
-		return( SMOOTHING_UPDATE_INTERVAL );
-	}
-	
-	public static MovingImmediateAverage
-	getSmoothAverage()
-	{
-		return( AverageFactory.MovingImmediateAverage(SMOOTHING_UPDATE_WINDOW/SMOOTHING_UPDATE_INTERVAL ));
-	}
-}
+/*
+ * Created on Jun 9, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
+import org.gudy.azureus2.core3.util.Constants;
+
+import com.aelitis.azureus.core.util.average.AverageFactory;
+import com.aelitis.azureus.core.util.average.MovingImmediateAverage;
+
+public class 
+GeneralUtils 
+{
+		/**
+		 * string.replaceAll does \\ and $ expansion in replacement, this doesn't, in fact it
+		 * doesn't do any pattern matching at all, it is a literal replacement
+		 * @param str
+		 * @param from_str		= NOTE, no regex support
+		 * @param replacement
+		 * @return
+		 */
+
+        // XXX: This doesn't appear to be used...
+    public static String
+	replaceAll(
+		String	str,
+		String	from_str,
+		String	replacement )
+	{
+		StringBuffer	res = null;
+				
+		int	pos = 0;
+		
+		while( true ){
+		
+			int	p1 = str.indexOf( from_str, pos );
+			
+			if ( p1 == -1 ){
+				
+				if ( res == null ){
+				
+					return( str );
+				}
+				
+				res.append( str.substring( pos ));
+				
+				return( res.toString());
+				
+			}else{
+				
+				if ( res == null ){
+					
+					res = new StringBuffer( str.length() * 2 );
+				}
+				
+				if ( p1 > pos ){
+					
+					res.append( str.substring( pos, p1 ));
+				}
+				
+				res.append( replacement );
+				
+				pos = p1 + from_str.length();
+			}
+		}
+	}
+	
+	/**
+	 * as above but does safe replacement of multiple strings (i.e. a match in the replacement
+	 * of one string won't be substituted by another)
+	 * @param str
+	 * @param from_strs
+	 * @param to_strs
+	 * @return
+	 */
+	public static String
+	replaceAll(
+		String		str,
+		String[]	from_strs,
+		String[]	to_strs )
+	{
+		StringBuffer	res = null;
+				
+		int	pos = 0;
+		
+		while( true ){
+		
+			int	min_match_pos 	= Integer.MAX_VALUE;
+			int	match_index		= -1;
+			
+			for ( int i=0;i<from_strs.length;i++ ){
+			
+				int	pt = str.indexOf( from_strs[i], pos );
+				
+				if ( pt != -1 ){
+					
+					if ( pt < min_match_pos ){
+						
+						min_match_pos		= pt;
+						match_index			= i;
+					}
+				}
+			}
+			
+			if ( match_index == -1 ){
+				
+				if ( res == null ){
+				
+					return( str );
+				}
+				
+				res.append( str.substring( pos ));
+				
+				return( res.toString());
+				
+			}else{
+				
+				if ( res == null ){
+					
+					res = new StringBuffer( str.length() * 2 );
+				}
+				
+				if ( min_match_pos > pos ){
+					
+					res.append( str.substring( pos, min_match_pos ));
+				}
+				
+				res.append( to_strs[match_index] );
+				
+				pos = min_match_pos + from_strs[match_index].length();
+			}
+		}
+	}
+	
+	private final static String REGEX_URLHTML = "<A HREF=\"(.+?)\">(.+?)</A>";
+	public static String stripOutHyperlinks(String message) {
+		return Pattern.compile(REGEX_URLHTML, Pattern.CASE_INSENSITIVE).matcher(
+				message).replaceAll("$2");
+	}
+	
+		/**
+		 * splits space separated tokens respecting quotes (either " or ' )
+		 * @param str
+		 * @return
+		 */
+		
+	public static String[]
+	splitQuotedTokens(
+		String		str )
+	{
+		List<String>	bits = new ArrayList<String>();
+		
+		char	quote 				= ' ';
+		boolean	escape 				= false;
+		boolean	bit_contains_quotes = false;
+			
+		String	bit = "";
+		
+		char[] chars = str.toCharArray();
+		
+		for (int i=0;i<chars.length;i++){
+			
+			char c = chars[i];
+			
+			if ( Character.isWhitespace(c)){
+				
+				c = ' ';
+			}
+			
+			if ( escape ){
+				
+				bit += c;
+				
+				escape = false;
+				
+				continue;
+				
+			}else if ( c == '\\' ){
+				
+				escape = true;
+				
+				continue;
+			}
+			
+			if ( c == '"' || c == '\'' && ( i == 0 || chars[ i-1 ] != '\\' )){
+				
+				if ( quote == ' ' ){
+						
+					bit_contains_quotes = true;
+					
+					quote = c;
+					
+				}else if ( quote == c ){
+										
+					quote = ' ';
+					
+				}else{
+					
+					bit += c;
+				}
+			}else{
+				
+				if ( quote == ' ' ){
+					
+					if ( c == ' ' ){
+						
+						if ( bit.length() > 0 || bit_contains_quotes ){
+							
+							bit_contains_quotes = false;
+							
+							bits.add( bit );
+							
+							bit = "";
+						}
+					}else{
+					
+						bit += c;
+					}
+				}else{
+					
+					bit += c;
+				}
+			}
+		}	
+		
+		if ( quote != ' ' ){
+			
+			bit += quote;
+		}
+		
+		if ( bit.length() > 0 || bit_contains_quotes ){
+			
+			bits.add( bit );
+		}
+		
+		return( bits.toArray( new String[bits.size()]));
+	}
+	
+	public static ProcessBuilder 
+	createProcessBuilder(
+		File workingDir,
+		String[] cmd, 
+		String[] extra_env) 
+	
+		throws IOException 
+	{
+		ProcessBuilder pb;
+
+		Map<String, String> newEnv = new HashMap<String, String>();
+		newEnv.putAll(System.getenv());
+		newEnv.put("LANG", "C.UTF-8");
+		if (extra_env != null && extra_env.length > 1) {
+			for (int i = 1; i < extra_env.length; i += 2) {
+				newEnv.put(extra_env[i - 1], extra_env[i]);
+			}
+		}
+
+		if ( Constants.isWindows ){
+			String[] i18n = new String[cmd.length + 2];
+			i18n[0] = "cmd";
+			i18n[1] = "/C";
+			i18n[2] = escapeDosCmd(cmd[0]);
+			for (int counter = 1; counter < cmd.length; counter++) {
+				if (cmd[counter].length() == 0) {
+					i18n[counter + 2] = "";
+				} else {
+					String envName = "JENV_" + counter;
+					i18n[counter + 2] = "%" + envName + "%";
+					newEnv.put(envName, cmd[counter]);
+				}
+			}
+			cmd = i18n;
+		}
+
+		pb = new ProcessBuilder(cmd);
+		Map<String, String> env = pb.environment();
+		env.putAll(newEnv);
+
+		if (workingDir != null) {
+			pb.directory(workingDir);
+		}
+		return pb;
+	}
+
+	private static String escapeDosCmd(String string) {
+		String s = string.replaceAll("([&%^])", "^$1");
+		s = s.replaceAll("'", "\"'\"");
+		return s;
+	}
+	
+	private static int SMOOTHING_UPDATE_WINDOW	 	= 60;
+	private static int SMOOTHING_UPDATE_INTERVAL 	= 1;
+
+	
+	static{
+		COConfigurationManager.addAndFireParameterListener(
+			"Stats Smoothing Secs",
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					String name ) 
+				{
+					SMOOTHING_UPDATE_WINDOW	= COConfigurationManager.getIntParameter( "Stats Smoothing Secs" );
+				
+					if ( SMOOTHING_UPDATE_WINDOW < 30 ){
+						
+						SMOOTHING_UPDATE_WINDOW = 30;
+						
+					}else if ( SMOOTHING_UPDATE_WINDOW > 30*60 ){
+						
+						SMOOTHING_UPDATE_WINDOW = 30*60;
+					}
+					
+					SMOOTHING_UPDATE_INTERVAL = SMOOTHING_UPDATE_WINDOW/60;
+					
+					if ( SMOOTHING_UPDATE_INTERVAL < 1 ){
+						
+						SMOOTHING_UPDATE_INTERVAL = 1;
+						
+					}else if ( SMOOTHING_UPDATE_INTERVAL > 20 ){
+						
+						SMOOTHING_UPDATE_INTERVAL = 20;
+					}
+				}
+			});
+	}
+	
+	public static int
+	getSmoothUpdateWindow()
+	{
+		return( SMOOTHING_UPDATE_WINDOW );
+	}
+	
+	public static int
+	getSmoothUpdateInterval()
+	{
+		return( SMOOTHING_UPDATE_INTERVAL );
+	}
+	
+	public static MovingImmediateAverage
+	getSmoothAverage()
+	{
+		return( AverageFactory.MovingImmediateAverage(SMOOTHING_UPDATE_WINDOW/SMOOTHING_UPDATE_INTERVAL ));
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/util/HTTPUtils.java b/azureus2/src/com/aelitis/azureus/core/util/HTTPUtils.java
index c59d7f8..e5916ca 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/HTTPUtils.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/HTTPUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 15, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.util;
@@ -170,6 +167,17 @@ public class HTTPUtils {
 	decodeChunkedEncoding(
 		Socket		socket )
 
+				throws IOException 
+	{
+		return decodeChunkedEncoding(socket, false);
+	}
+
+
+	public static InputStream 
+	decodeChunkedEncoding(
+		Socket		socket,
+		boolean ignoreStatusCode)
+
 		throws IOException 
 	{
 		InputStream	is = socket.getInputStream();
@@ -196,8 +204,8 @@ public class HTTPUtils {
 		int p1 = reply_header.indexOf(NL);
 
 		String first_line = reply_header.substring(0, p1).trim();
-
-		if ( first_line.indexOf( "200" ) == -1 ){
+		
+		if ( !ignoreStatusCode && first_line.indexOf( "200" ) == -1 ){
 
 			String	info = null;
 			
@@ -224,7 +232,7 @@ public class HTTPUtils {
 			
 			throw ( new IOException( error ));
 		}
-
+		
 		String lc_reply_header = reply_header.toLowerCase( Constants.LOCALE_ENGLISH );
 
 		int te_pos = lc_reply_header.indexOf("transfer-encoding");
@@ -312,6 +320,39 @@ public class HTTPUtils {
 
 				return (new ByteArrayInputStream(baos.toByteArray()));
 			}
+		} else {
+			// if we have a content-length, grab only that many bytes
+			// Some socket connectsions will timeout if you try to read more
+			int cl_pos = lc_reply_header.indexOf("content-length");
+			if (cl_pos == -1) {
+				return is;
+			}
+			String property = lc_reply_header.substring(cl_pos);
+
+			property = property.substring(property.indexOf(':') + 1,
+					property.indexOf(NL)).trim();
+			try {
+  			long length = Long.parseLong(property);
+  			
+  			// could be smarter with the buffer here
+  			if (length > 0xFFFF) {
+  				return is;
+  			}
+
+  			int remaining = (int) length;
+  			int pos = 0;
+  			byte[] buffer = new byte[remaining];
+  			while (remaining > 0) {
+  				int read = is.read(buffer, pos, remaining);
+  				if (read < 0) {
+  					break;
+  				}
+  				remaining -= read;
+  				pos += read;
+  			}
+  			return new ByteArrayInputStream(buffer);
+			} catch (NumberFormatException ignoreError) {
+			}
 		}
 
 		return (is);
diff --git a/azureus2/src/com/aelitis/azureus/core/util/HashCodeUtils.java b/azureus2/src/com/aelitis/azureus/core/util/HashCodeUtils.java
index d53ca46..e44fc8e 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/HashCodeUtils.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/HashCodeUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created by Joseph Bridgewater
  * Created on Feb 24, 2006
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/IdentityHashSet.java b/azureus2/src/com/aelitis/azureus/core/util/IdentityHashSet.java
index 543cfa7..6ae6780 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/IdentityHashSet.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/IdentityHashSet.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -84,4 +83,4 @@ IdentityHashSet<E>
 	{
 		return identity_map.keySet().iterator();
 	}
-}
\ No newline at end of file
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/util/LaunchManager.java b/azureus2/src/com/aelitis/azureus/core/util/LaunchManager.java
index c0017c6..33a13c4 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/LaunchManager.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/LaunchManager.java
@@ -1,152 +1,151 @@
-/*
- * Created on Mar 1, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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.util;
-
-import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.util.AEThread2;
-
-public class 
-LaunchManager 
-{
-	private static LaunchManager	singleton = new LaunchManager();
-	
-	public static LaunchManager
-	getManager()
-	{
-		return( singleton );
-	}
-	
-	private CopyOnWriteList<LaunchController>	controllers	= new CopyOnWriteList<LaunchController>();
-	
-	public void
-	launchRequest(
-		final LaunchTarget	target,
-		final LaunchAction	action )
-	{
-		new AEThread2( "LaunchManager:request" )
-		{
-			public void
-			run()
-			{
-				for ( LaunchController c: controllers ){
-					
-					try{
-						c.handleRequest( target );
-						
-					}catch( Throwable e ){
-						
-						action.actionDenied( e );
-						
-						return;
-					}
-				}
-				
-				action.actionAllowed();
-			}
-		}.start();
-	}
-	
-	public LaunchTarget
-	createTarget(
-		DownloadManager		dm )
-	{
-		return( new LaunchTarget( dm ));
-	}
-	
-	public LaunchTarget
-	createTarget(
-		DiskManagerFileInfo		fi )
-	{
-		return( new LaunchTarget( fi ));
-	}
-	
-	public void
-	addController(
-		LaunchController	controller )
-	{
-		controllers.add( controller );
-	}
-	
-	public void
-	removeController(
-		LaunchController	controller )
-	{
-		controllers.remove( controller );
-	}
-	
-	public class
-	LaunchTarget
-	{
-		private DownloadManager			dm;
-		private DiskManagerFileInfo		file_info;
-		
-		private 
-		LaunchTarget(
-			DownloadManager		_dm )
-		{
-			dm		= _dm;
-		}
-		
-		private 
-		LaunchTarget(
-			DiskManagerFileInfo		_file_info )
-		{
-			file_info	= _file_info;	
-			dm			= file_info.getDownloadManager();
-		}
-		
-		public DownloadManager
-		getDownload()
-		{
-			return( dm );
-		}
-		
-		public DiskManagerFileInfo
-		getFile()
-		{
-			return( file_info );
-		}
-	}
-	
-	public interface
-	LaunchController
-	{
-		public void
-		handleRequest(
-			LaunchTarget		target )
-		
-			throws Throwable;
-	}
-	
-	public interface
-	LaunchAction
-	{
-		public void
-		actionAllowed();
-		
-		public void
-		actionDenied(
-			Throwable			reason );
-			
-	}
-}
+/*
+ * Created on Mar 1, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.util;
+
+import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.util.AEThread2;
+
+public class 
+LaunchManager 
+{
+	private static LaunchManager	singleton = new LaunchManager();
+	
+	public static LaunchManager
+	getManager()
+	{
+		return( singleton );
+	}
+	
+	private CopyOnWriteList<LaunchController>	controllers	= new CopyOnWriteList<LaunchController>();
+	
+	public void
+	launchRequest(
+		final LaunchTarget	target,
+		final LaunchAction	action )
+	{
+		new AEThread2( "LaunchManager:request" )
+		{
+			public void
+			run()
+			{
+				for ( LaunchController c: controllers ){
+					
+					try{
+						c.handleRequest( target );
+						
+					}catch( Throwable e ){
+						
+						action.actionDenied( e );
+						
+						return;
+					}
+				}
+				
+				action.actionAllowed();
+			}
+		}.start();
+	}
+	
+	public LaunchTarget
+	createTarget(
+		DownloadManager		dm )
+	{
+		return( new LaunchTarget( dm ));
+	}
+	
+	public LaunchTarget
+	createTarget(
+		DiskManagerFileInfo		fi )
+	{
+		return( new LaunchTarget( fi ));
+	}
+	
+	public void
+	addController(
+		LaunchController	controller )
+	{
+		controllers.add( controller );
+	}
+	
+	public void
+	removeController(
+		LaunchController	controller )
+	{
+		controllers.remove( controller );
+	}
+	
+	public class
+	LaunchTarget
+	{
+		private DownloadManager			dm;
+		private DiskManagerFileInfo		file_info;
+		
+		private 
+		LaunchTarget(
+			DownloadManager		_dm )
+		{
+			dm		= _dm;
+		}
+		
+		private 
+		LaunchTarget(
+			DiskManagerFileInfo		_file_info )
+		{
+			file_info	= _file_info;	
+			dm			= file_info.getDownloadManager();
+		}
+		
+		public DownloadManager
+		getDownload()
+		{
+			return( dm );
+		}
+		
+		public DiskManagerFileInfo
+		getFile()
+		{
+			return( file_info );
+		}
+	}
+	
+	public interface
+	LaunchController
+	{
+		public void
+		handleRequest(
+			LaunchTarget		target )
+		
+			throws Throwable;
+	}
+	
+	public interface
+	LaunchAction
+	{
+		public void
+		actionAllowed();
+		
+		public void
+		actionDenied(
+			Throwable			reason );
+			
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/util/LinkFileMap.java b/azureus2/src/com/aelitis/azureus/core/util/LinkFileMap.java
index 7b7861f..63defb9 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/LinkFileMap.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/LinkFileMap.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/MultiPartDecoder.java b/azureus2/src/com/aelitis/azureus/core/util/MultiPartDecoder.java
index b164024..15f48f7 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/MultiPartDecoder.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/MultiPartDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/com/aelitis/azureus/core/util/NetUtils.java b/azureus2/src/com/aelitis/azureus/core/util/NetUtils.java
index f4e0882..0946b2b 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/NetUtils.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/NetUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/QTFastStartRAF.java b/azureus2/src/com/aelitis/azureus/core/util/QTFastStartRAF.java
index 4a62e76..6c6c62e 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/QTFastStartRAF.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/QTFastStartRAF.java
@@ -2,20 +2,19 @@
  * Created on Jan 19, 2011
  * Created by Paul Gardner
  * 
- * Copyright 2011 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/RegExUtil.java b/azureus2/src/com/aelitis/azureus/core/util/RegExUtil.java
index 255665a..b491a08 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/RegExUtil.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/RegExUtil.java
@@ -2,20 +2,19 @@
  * Created on Nov 1, 2011
  * Created by Paul Gardner
  * 
- * Copyright 2011 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/UUIDGenerator.java b/azureus2/src/com/aelitis/azureus/core/util/UUIDGenerator.java
index dbfe530..2bd02d0 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/UUIDGenerator.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/UUIDGenerator.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/UncloseableInputStream.java b/azureus2/src/com/aelitis/azureus/core/util/UncloseableInputStream.java
new file mode 100644
index 0000000..36ce2b0
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/core/util/UncloseableInputStream.java
@@ -0,0 +1,144 @@
+/*
+ * Created on May 23, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.core.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class 
+UncloseableInputStream 
+	extends InputStream
+{
+	private InputStream		is;
+	
+	private boolean			closed;
+	
+	public
+	UncloseableInputStream(
+		InputStream		_is )
+	{
+		is		= _is;
+	}
+	
+	@Override
+	public int 
+	read() 
+		throws IOException 
+	{
+		if ( closed ){
+			throw( new IOException( "Stream Closed" ));
+		}
+	
+		return( is.read());
+	}
+
+	public int 
+	read(
+		byte b[] )
+
+		throws IOException 
+	{
+		if ( closed ){
+			throw( new IOException( "Stream Closed" ));
+		}
+	
+		return( is.read( b ));
+	}
+
+	public int 
+	read(
+		byte b[], 
+		int off, 
+		int len) 
+
+		throws IOException 
+	{
+		if ( closed ){
+			throw( new IOException( "Stream Closed" ));
+		}
+		
+		return( is.read( b, off, len ));
+	}
+
+	public void 
+	close() 
+			
+		throws IOException
+	{
+		closed	= true;
+	}
+
+	public long 
+	skip(
+		long n )
+		
+		throws IOException
+	{
+		if ( closed ){
+			throw( new IOException( "Stream Closed" ));
+		}
+		
+		return( is.skip( n ));
+	}
+
+	public int 
+	available()
+	
+		throws IOException
+	{
+		if ( closed ){
+			throw( new IOException( "Stream Closed" ));
+		}
+		
+		return( is.available());
+	}
+
+	public void
+	mark(
+		int readlimit )
+	{
+		is.mark( readlimit );
+	}
+
+	public void 
+	reset()
+	
+		throws IOException
+	{
+		if ( closed ){
+			throw( new IOException( "Stream Closed" ));
+		}
+		
+		is.reset();
+	}
+
+	public boolean 
+	markSupported() 
+	{
+		return( false );	// lets say no to prevent interaction with delegated stream...
+	}
+	
+	public boolean
+	isClosed()
+	{
+		return( closed );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/util/average/Average.java b/azureus2/src/com/aelitis/azureus/core/util/average/Average.java
index 52de73e..1bc8010 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/average/Average.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/average/Average.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 08, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.util.average;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/average/AverageFactory.java b/azureus2/src/com/aelitis/azureus/core/util/average/AverageFactory.java
index 22ffa25..d05a569 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/average/AverageFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/average/AverageFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 08, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.util.average;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/average/ExponentialMovingAverage.java b/azureus2/src/com/aelitis/azureus/core/util/average/ExponentialMovingAverage.java
index 0b54c2a..3fdf940 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/average/ExponentialMovingAverage.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/average/ExponentialMovingAverage.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 08, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.util.average;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/average/MovingAverage.java b/azureus2/src/com/aelitis/azureus/core/util/average/MovingAverage.java
index cae3c26..da4d284 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/average/MovingAverage.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/average/MovingAverage.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 08, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.util.average;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/average/MovingImmediateAverage.java b/azureus2/src/com/aelitis/azureus/core/util/average/MovingImmediateAverage.java
index 99aa480..6ff8658 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/average/MovingImmediateAverage.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/average/MovingImmediateAverage.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 08, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.util.average;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/average/RunningAverage.java b/azureus2/src/com/aelitis/azureus/core/util/average/RunningAverage.java
index 3f65cc1..b04a86a 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/average/RunningAverage.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/average/RunningAverage.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 08, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.util.average;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/bloom/BloomFilter.java b/azureus2/src/com/aelitis/azureus/core/util/bloom/BloomFilter.java
index eb64760..82e038c 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/bloom/BloomFilter.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/bloom/BloomFilter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Apr-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -50,18 +47,18 @@ BloomFilter
 	
 	public int
 	getEntryCount();
-	
-		/**
-		 * Returns overall capacity
-		 * @return
-		 */
-	
+		
 	public void 
 	clear();
 	
 	public long
 	getStartTimeMono();
 	
+	/**
+	 * Returns overall capacity
+	 * @return
+	 */
+
 	public int
 	getSize();
 	
diff --git a/azureus2/src/com/aelitis/azureus/core/util/bloom/BloomFilterFactory.java b/azureus2/src/com/aelitis/azureus/core/util/bloom/BloomFilterFactory.java
index f3552b5..f9e7224 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/bloom/BloomFilterFactory.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/bloom/BloomFilterFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Apr-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddOnly.java b/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddOnly.java
index 9130695..e2d8276 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddOnly.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddOnly.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-May-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove4Bit.java b/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove4Bit.java
index e4b4072..45839de 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove4Bit.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove4Bit.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-May-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove8Bit.java b/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove8Bit.java
index 502a912..4371ade 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove8Bit.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterAddRemove8Bit.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-May-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterImpl.java b/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterImpl.java
index 4de6342..57a987f 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Apr-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterRotator.java b/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterRotator.java
index c774682..d627f18 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterRotator.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/bloom/impl/BloomFilterRotator.java
@@ -1,239 +1,243 @@
-/*
- * Created on Oct 29, 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.core.util.bloom.impl;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.core.util.bloom.BloomFilter;
-
-public class 
-BloomFilterRotator
-	implements BloomFilter
-{
-	private volatile BloomFilter 	current_filter;
-	private int						current_filter_index;
-	
-	private final BloomFilter[]	filters;
-	
-	private long start_time = SystemTime.getMonotonousTime();
-	
-	public
-	BloomFilterRotator(
-		BloomFilter		_target,
-		int				_num )
-	{
-		filters = new BloomFilter[_num];
-		
-		filters[0] = _target;
-		
-		for (int i=1;i<filters.length;i++){
-			
-			filters[i] = _target.getReplica();
-		}
-		
-		current_filter 			= _target;
-		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 )
-	{
-		synchronized( filters ){
-			
-			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 )
-	{		
-		synchronized( filters ){
-					
-			int	filter_size 	= current_filter.getSize();
-			int	filter_entries	= current_filter.getEntryCount();
-			
-			int	limit	= filter_size / 8;	// capacity limit 
-			
-			if ( filter_entries > limit ){
-				
-				filter_entries = limit;
-			}
-			
-			int	update_chunk = limit / filters.length;
-			
-			int	num_to_update =  ( filter_entries / update_chunk ) + 1; 
-			
-			if ( num_to_update > filters.length ){
-				
-				num_to_update = filters.length;
-			}
-			
-			//System.out.println( "rot_bloom: cur=" + current_filter_index + ", upd=" + num_to_update + ",ent=" + filter_entries );
-			
-			int	res = 0;
-			
-			for (int i=current_filter_index;i<current_filter_index+num_to_update;i++){
-				
-				int	r = filters[i%filters.length].add( value );
-
-				if ( i == current_filter_index ){
-					
-					res = r;
-				}
-			}
-			
-			if ( current_filter.getEntryCount() > limit ){
-				
-				filters[current_filter_index] = current_filter.getReplica();
-
-				current_filter_index = (current_filter_index+1)%filters.length;
-				
-				current_filter = filters[ current_filter_index ];
-			}
-			
-			return( res );
-		}
-	}
-	
-	public int
-	remove(
-		byte[]		value )
-	{
-		int	res = 0;
-		
-		for (int i=0;i<filters.length;i++){
-			
-			BloomFilter	filter = filters[i];
-			
-			int r = filter.remove( value );
-			
-			if ( filter == current_filter ){
-				
-				res = r;
-			}
-		}
-		
-		return( res );
-	}
-	
-	public boolean
-	contains(
-		byte[]		value )
-	{
-		return( current_filter.contains(value));
-	}
-	
-	public int
-	count(
-		byte[]		value )
-	{
-		return( current_filter.count( value ));
-	}
-	
-	public int
-	getEntryCount()
-	{
-		return( current_filter.getEntryCount());
-	}
-	
-	public int
-	getSize()
-	{
-		return( current_filter.getSize());
-	}
-	
-	public BloomFilter
-	getReplica()
-	{
-		return( new BloomFilterRotator( current_filter, filters.length ));
-	}
-	
-	public long 
-	getStartTimeMono()
-	{
-		return( start_time );
-	}
-	
-	public void 
-	clear() 
-	{
-		current_filter.clear();
-	}
-	
-	public String
-	getString()
-	{
-		return( "ind=" + current_filter_index + ",filt=" + current_filter.getString());
-	}
-}
+/*
+ * Created on Oct 29, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.util.bloom.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.gudy.azureus2.core3.util.SystemTime;
+
+import com.aelitis.azureus.core.util.bloom.BloomFilter;
+
+public class 
+BloomFilterRotator
+	implements BloomFilter
+{
+	private volatile BloomFilter 	current_filter;
+	private int						current_filter_index;
+	
+	private final BloomFilter[]	filters;
+	
+	private long start_time = SystemTime.getMonotonousTime();
+	
+	public
+	BloomFilterRotator(
+		BloomFilter		_target,
+		int				_num )
+	{
+		filters = new BloomFilter[_num];
+		
+		filters[0] = _target;
+		
+		for (int i=1;i<filters.length;i++){
+			
+			filters[i] = _target.getReplica();
+		}
+		
+		current_filter 			= _target;
+		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 )
+	{
+		synchronized( filters ){
+			
+			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 )
+	{		
+		synchronized( filters ){
+					
+			int	filter_size 	= current_filter.getSize();
+			int	filter_entries	= current_filter.getEntryCount();
+			
+			int	limit	= filter_size / 8;	// capacity limit 
+			
+			if ( filter_entries > limit ){
+				
+				filter_entries = limit;
+			}
+			
+			int	update_chunk = limit / filters.length;
+			
+			int	num_to_update =  ( filter_entries / update_chunk ) + 1; 
+			
+			if ( num_to_update > filters.length ){
+				
+				num_to_update = filters.length;
+			}
+			
+			//System.out.println( "rot_bloom: cur=" + current_filter_index + ", upd=" + num_to_update + ",ent=" + filter_entries );
+			
+			int	res = 0;
+			
+			for (int i=current_filter_index;i<current_filter_index+num_to_update;i++){
+				
+				int	r = filters[i%filters.length].add( value );
+
+				if ( i == current_filter_index ){
+					
+					res = r;
+				}
+			}
+			
+			if ( current_filter.getEntryCount() > limit ){
+				
+				filters[current_filter_index] = current_filter.getReplica();
+
+				current_filter_index = (current_filter_index+1)%filters.length;
+				
+				current_filter = filters[ current_filter_index ];
+			}
+			
+			return( res );
+		}
+	}
+	
+	public int
+	remove(
+		byte[]		value )
+	{
+		int	res = 0;
+		
+		for (int i=0;i<filters.length;i++){
+			
+			BloomFilter	filter = filters[i];
+			
+			int r = filter.remove( value );
+			
+			if ( filter == current_filter ){
+				
+				res = r;
+			}
+		}
+		
+		return( res );
+	}
+	
+	public boolean
+	contains(
+		byte[]		value )
+	{
+		return( current_filter.contains(value));
+	}
+	
+	public int
+	count(
+		byte[]		value )
+	{
+		return( current_filter.count( value ));
+	}
+	
+	public int
+	getEntryCount()
+	{
+		return( current_filter.getEntryCount());
+	}
+	
+	public int
+	getSize()
+	{
+		return( current_filter.getSize());
+	}
+	
+	public BloomFilter
+	getReplica()
+	{
+		return( new BloomFilterRotator( current_filter, filters.length ));
+	}
+	
+	public long 
+	getStartTimeMono()
+	{
+		return( start_time );
+	}
+	
+	public void 
+	clear() 
+	{
+		start_time  = SystemTime.getMonotonousTime();
+
+		for ( BloomFilter filter: filters ){
+			
+			filter.clear();
+		}
+	}
+	
+	public String
+	getString()
+	{
+		return( "ind=" + current_filter_index + ",filt=" + current_filter.getString());
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/util/dns/DNSUtilsImpl.java b/azureus2/src/com/aelitis/azureus/core/util/dns/DNSUtilsImpl.java
index a4c8eb5..6344a0f 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/dns/DNSUtilsImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/dns/DNSUtilsImpl.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/core/util/http/HTTPAuthHelper.java b/azureus2/src/com/aelitis/azureus/core/util/http/HTTPAuthHelper.java
index 21d98d5..586ac4d 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/http/HTTPAuthHelper.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/http/HTTPAuthHelper.java
@@ -1,1485 +1,1484 @@
-/*
- * Created on Oct 2, 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.core.util.http;
-
-import java.net.*;
-import java.nio.charset.Charset;
-import java.util.*;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.InflaterInputStream;
-import java.io.*;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-import org.gudy.azureus2.core3.security.SESecurityManager;
-import org.gudy.azureus2.core3.util.*;
-
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-public class 
-HTTPAuthHelper 
-{
-	public static final boolean	TRACE	= false;
-	
-	public static final int MAX_PROCESSORS = 32;
-		
-	public static final int	CONNECT_TIMEOUT		= 30*1000;
-	public static final int READ_TIMEOUT		= 30*1000;
-
-	private HTTPAuthHelper			parent;
-	private Map						children	= new HashMap();
-	
-	private URL						delegate_to;
-	private String					delegate_to_host;
-	private int						delegate_to_port;
-	private boolean					delegate_is_https;
-	
-	private Proxy	delegate_to_proxy;
-	
-	private CopyOnWriteList			listeners = new CopyOnWriteList();
-	
-	private int		port;
-	
-	private ServerSocket	server_socket;	
-	
-	private boolean			http_only_detected;
-	
-	private Map				cookie_names_set	= new HashMap();
-	
-	private ThreadPool		thread_pool = new ThreadPool("HTTPSniffer", MAX_PROCESSORS, true );
-	
-	private List			processors = new ArrayList();
-	
-	private volatile boolean		destroyed;
-		
-	public
-	HTTPAuthHelper(
-		URL			url )
-	
-		throws Exception
-	{
-		this( null, url );
-	}
-	
-	private
-	HTTPAuthHelper(
-		HTTPAuthHelper			_parent,
-		URL						_delegate_to )
-	
-		throws Exception
-	{
-		parent				= _parent;
-		delegate_to			= _delegate_to;
-		
-		delegate_to_host	= delegate_to.getHost();
-		delegate_is_https	= delegate_to.getProtocol().toLowerCase().equals( "https" );
-		delegate_to_port	= delegate_to.getPort()==-1?delegate_to.getDefaultPort():delegate_to.getPort();
-					
-		server_socket = new ServerSocket();
-		
-		server_socket.setReuseAddress( true ); 
-             
-		server_socket.bind( new InetSocketAddress( "127.0.0.1", 0 ));
-        
-        port = server_socket.getLocalPort();
-	}
-	
-	public void
-	setProxy(
-		Proxy		_proxy )
-	{
-		delegate_to_proxy	= _proxy;
-	}
-	
-	public void
-	start()
-	{
-        new AEThread2( 
-        	"HTTPSniffingProxy: " + delegate_to_host + ":" + delegate_to_port + "/" + delegate_is_https + "/" + port, 
-        	true )
-        	{
-        		public void 
-        		run() 
-        		{
-        			try{
-        				while( !destroyed ){
-    
-        					Socket	socket = server_socket.accept();
-        					   
-        					socket.setSoTimeout( READ_TIMEOUT );
-        					
-        					synchronized( HTTPAuthHelper.this ){
-        						
-        						if ( processors.size() >= MAX_PROCESSORS ){
-        							
-        							try{
-        								Debug.out( "Too many processors" );
-        								
-        								socket.close();
-        								
-        							}catch( Throwable e ){
-        							}
-        						}else{
-        							
-        							processor proc = new processor( socket );
-        							
-        							processors.add( proc );
-        							
-        							proc.start();
-        						}
-        					}
-        				}
-        			}catch( Throwable e ){
-        				
-        				if ( !destroyed ){
-        					
-        					Debug.printStackTrace( e );
-        				}
-        			}
-        		}
-        	}.start();	
-	}
-	
-	public int
-	getPort()
-	{
-		return( port );
-	}
-	
-	public boolean
-	wasHTTPOnlyCookieDetected()
-	{
-		return( http_only_detected );
-	}
-	
-	private void
-	setHTTPOnlyCookieDetected()
-	{
-		http_only_detected = true;
-		
-		if ( parent != null ){
-			
-			parent.setHTTPOnlyCookieDetected();
-		}
-	}
-	
-	private String
-	getKey(
-		URL		url )
-	{
-		int child_port = url.getPort()==-1?url.getDefaultPort():url.getPort();
-		
-		String	key = url.getProtocol() + ":" + url.getHost() + ":" + child_port;
-
-		return( key );
-	}
-	
-	private HTTPAuthHelper
-	getChild(
-		String		url_str,
-		boolean		optional )
-	
-		throws Exception
-	{
-		if ( parent != null ){
-	
-			return( parent.getChild( url_str,optional ));
-		}
-	
-		String lc_url_str = url_str.toLowerCase();
-		
-		if ( lc_url_str.startsWith( "http://" ) || lc_url_str.startsWith( "https://")){
-			
-			URL child_url = new URL( url_str );
-			
-			String	child_key = getKey( child_url );
-			
-			if ( child_key.equals( getKey( delegate_to ))){
-				
-				return( this );
-			}
-			
-			synchronized( this ){
-	
-				if ( destroyed ){
-					
-					throw( new Exception( "Destroyed" ));
-				}
-				
-				HTTPAuthHelper child = (HTTPAuthHelper)children.get( child_key );
-				
-				if ( optional ){
-					
-						// create children for related domains
-					
-					String	base_host 	= delegate_to.getHost();
-					String	child_host	= child_url.getHost();
-					
-					int	base_pos = base_host.lastIndexOf( '.' );
-					base_pos = base_host.lastIndexOf( '.', base_pos-1 );
-					
-					int	child_pos = child_host.lastIndexOf( '.' );
-					child_pos = child_host.lastIndexOf( '.', child_pos-1 );
-
-					String base_dom 	= base_host.substring( base_pos, base_host.length());
-					String child_dom 	= child_host.substring( child_pos, child_host.length());
-					
-					if ( base_dom.equals( child_dom )){
-						
-						optional = false;
-					}
-				}
-				
-				if ( child == null && !optional ){
-				
-					child = new HTTPAuthHelper( this, new URL( url_str ));
-							
-					children.put( child_key, child );
-					
-					child.start();
-				}
-				
-				return( child );
-			}
-		}else{
-				//relative
-			
-			return( this );
-		}
-	}
-
-	private void
-	addSetCookieName(
-		String		name,
-		String		value )
-	{
-		if ( parent != null ){
-			
-			parent.addSetCookieName( name, value );
-			
-		}else{
-			
-			boolean	new_entry;
-			
-			synchronized( cookie_names_set ){
-		
-				trace( "SetCookieName: " + name );
-				
-				String old_value = (String)cookie_names_set.put( name, value );
-				
-				new_entry = old_value==null || !old_value.equals( value );
-			}
-			
-			if ( new_entry ){
-				
-				Iterator it = listeners.iterator();
-				
-				while( it.hasNext()){
-					
-					try{
-						((HTTPAuthHelperListener)it.next()).cookieFound( this, name, value );
-						
-					}catch( Throwable e ){
-						
-						Debug.printStackTrace(e );
-					}
-				}
-			}
-		}
-	}
-	
-	private boolean
-	hasSetCookieName(
-		String		name )
-	{
-		if ( parent != null ){
-			
-			return( parent.hasSetCookieName( name ));
-			
-		}else{
-		
-			synchronized( cookie_names_set ){
-				
-				trace( "GetCookieName: " + name );
-				
-				return( cookie_names_set.containsKey( name ));
-			}
-		}
-	}
-	
-	public void
-	addListener(
-		HTTPAuthHelperListener		listener )
-	{
-		listeners.add( listener );
-	}
-	
-	public void
-	destroy()
-	{
-		List	processors_to_destroy;
-		List	chidren_to_destroy;
-		
-		synchronized( this ){
-			
-			if ( destroyed ){
-				
-				return;
-			}
-			
-			destroyed = true;
-				
-			chidren_to_destroy = new ArrayList( children.values());
-			
-			children.clear();
-			
-			processors_to_destroy = new ArrayList( processors );
-			
-			processors.clear();
-			
-			try{				
-				server_socket.close();
-
-			}catch( Throwable e ){	
-			}
-		}
-				
-		for (int i=0;i<chidren_to_destroy.size();i++){
-			
-			try{
-				((HTTPAuthHelper)chidren_to_destroy.get(i)).destroy();
-				
-			}catch( Throwable e ){
-			}
-		}
-		
-		for (int i=0;i<processors_to_destroy.size();i++){
-			
-			try{
-				((processor)processors_to_destroy.get(i)).destroy();
-			
-			}catch( Throwable e ){
-			}
-		}
-	}
-	
-	private class
-	processor
-	{
-		private static final String	NL = "\r\n";
-		
-		private Socket		socket_in;
-		private Socket		socket_out;
-		
-		private volatile boolean	destroyed;
-		
-		private
-		processor(
-			Socket		_socket )
-		{
-			socket_in	= _socket;
-		}
-		
-		private void
-		start()
-		{
-			thread_pool.run(
-				new AERunnable()
-				{
-					public void
-					runSupport()
-					{
-						try{
-							sniff();
-							
-						}finally{
-													
-							synchronized( HTTPAuthHelper.this ){
-
-								processors.remove( processor.this );
-							}
-						}
-					}
-				});
-		}
-		
-		private void
-		sniff()
-		{
-			try{
-				InputStream is = socket_in.getInputStream();
-				
-				String request_header = readHeader( is );
-								
-				connectToDelegate();
-				
-				process( request_header );
-				
-			}catch( Throwable e ){
-				
-				if ( !( e instanceof IOException )){
-					
-					Debug.out( e );
-				}
-				
-				destroy();
-			}
-		}
-		
-		private void
-		connectToDelegate()
-		
-			throws IOException
-		{
-			try{
-				if ( delegate_is_https ){
-					
-					TrustManager[] trustAllCerts = new TrustManager[]{
-							new X509TrustManager() {
-								public java.security.cert.X509Certificate[] getAcceptedIssuers() {
-									return null;
-								}
-								public void checkClientTrusted(
-										java.security.cert.X509Certificate[] certs, String authType) {
-								}
-								public void checkServerTrusted(
-										java.security.cert.X509Certificate[] certs, String authType) {
-								}
-							}
-						};
-				
-					SSLContext sc = SSLContext.getInstance("SSL");
-				
-					sc.init(null, trustAllCerts, RandomUtils.SECURE_RANDOM );
-				
-					SSLSocketFactory factory = sc.getSocketFactory();
-
-					try{
-						if ( delegate_to_proxy == null ){
-							
-							socket_out = factory.createSocket();
-							
-							socket_out.connect( new InetSocketAddress( delegate_to_host, delegate_to_port ), CONNECT_TIMEOUT );
-							
-						}else{
-							
-							Socket plain_socket = new Socket( delegate_to_proxy );
-							
-							plain_socket.connect( new InetSocketAddress( delegate_to_host, delegate_to_port ), CONNECT_TIMEOUT );
-							
-							socket_out = factory.createSocket( plain_socket, delegate_to_host, delegate_to_port, true );
-						}
-					
-					}catch( SSLException ssl_excep ){
-								
-						if ( socket_out != null ){
-							
-							try{
-								socket_out.close();
-								
-							}catch( Throwable e ){		
-							}
-						}
-						
-						factory = SESecurityManager.installServerCertificates( "AZ-sniffer:" + delegate_to_host + ":" + port, delegate_to_host, delegate_to_port );
-						
-						if ( delegate_to_proxy == null ){
-							
-							socket_out = factory.createSocket();
-							
-							socket_out.connect( new InetSocketAddress( delegate_to_host, delegate_to_port ), CONNECT_TIMEOUT );
-							
-						}else{
-							
-							Socket plain_socket = new Socket( delegate_to_proxy );
-							
-							plain_socket.connect( new InetSocketAddress( delegate_to_host, delegate_to_port ), CONNECT_TIMEOUT );
-							
-							socket_out = factory.createSocket( plain_socket, delegate_to_host, delegate_to_port, true );
-						}					}
-				}else{
-					
-					if ( delegate_to_proxy == null ){
-					
-						socket_out = new Socket();
-						
-					}else{
-						
-						socket_out = new Socket( delegate_to_proxy );
-					}
-					
-					socket_out.connect( new InetSocketAddress( delegate_to_host, delegate_to_port ), CONNECT_TIMEOUT );
-				}
-			}catch( Throwable e ){
-				
-				if ( e instanceof IOException ){
-					
-					throw((IOException)e );
-				}
-				
-				throw( new IOException( e.toString()));
-				
-			}finally{
-				
-				if ( socket_out != null ){
-										
-					synchronized( this ){
-						
-						if ( destroyed ){
-
-							try{
-								socket_out.close();
-								
-							}catch( Throwable e ){
-								
-							}finally{
-								
-								socket_out = null;
-							}
-							
-							throw( new IOException( "destroyed" ));
-						}
-					}
-				}
-			}
-		}
-		
-		private void
-		process(
-			String		request_header )
-		
-			throws Exception
-		{
-			final OutputStream target_os = socket_out.getOutputStream();
-			
-			String[]	request_lines = splitHeader( request_header );
-			
-			String target_url = request_lines[0];
-			
-			int	space_pos = target_url.indexOf(' ');
-			
-			if ( space_pos == -1 ){
-				
-				System.out.println( "eh?" );
-			}
-			target_url = target_url.substring( space_pos ).trim();
-			
-			space_pos = target_url.indexOf(' ');
-			
-			target_url = target_url.substring( 0, space_pos ).trim();
-
-			trace( "Page request for " + target_url );
-			
-			List	cookies_to_remove = new ArrayList();
-
-			for (int i=0;i<request_lines.length;i++){
-				
-				String	line_out	= request_lines[i];
-
-				String	line_in 	= line_out.trim().toLowerCase();
-				
-				String[] bits = line_in.split(":");
-				
-				if ( bits.length >= 2 ){
-					
-					String	lhs = bits[0].trim();
-					
-					if ( lhs.equals( "host" )){
-						
-						String	port_str;
-						
-						if ( delegate_to_port == 80 || delegate_to_port == 443 ){
-						
-							port_str = "";
-							
-						}else{
-							
-							port_str = ":" + delegate_to_port;
-						}
-						
-						line_out = "Host: " + delegate_to_host + port_str;
-						
-					}else if ( lhs.equals( "connection" )){
-						
-						line_out = "Connection: close";
-						
-					}else if ( lhs.equals( "referer" )){
-						
-						String page = line_out.substring( line_out.indexOf( ':' )+1).trim();
-						
-						page = page.substring( page.indexOf( "://") + 3);
-						
-						int pos = page.indexOf( '/' );
-						
-						if ( pos >= 0 ){
-						
-							page = page.substring( pos );
-							
-						}else{
-							
-							page = "/";
-						}
-						
-						String	port_str;
-						
-						if ( delegate_to_port == 80 || delegate_to_port == 443 ){
-						
-							port_str = "";
-							
-						}else{
-							
-							port_str = ":" + delegate_to_port;
-						}
-
-						line_out = "Referer: http" + (delegate_is_https?"s":"") + "://" + delegate_to_host + port_str + page;
-						
-					}else if ( lhs.equals( "cookie" )){
-
-						String cookies_str = line_out.substring( line_out.indexOf( ':' )+1).trim();
-						
-						String[] cookies = cookies_str.split( ";" );
-						
-						String	cookies_out = "";
-						
-						for (int j=0;j<cookies.length;j++){
-							
-							String	cookie = cookies[j];
-							
-							String	name = cookie.split( "=" )[0].trim();
-							
-							if ( hasSetCookieName( name )){
-								
-								cookies_out += (cookies_out.length()==0?"":"; ") + cookie;
-								
-							}else{
-								
-								cookies_to_remove.add( name );
-							}
-						}
-						
-						if ( cookies_out.length() > 0 ){
-							
-							line_out = "Cookie: " + cookies_out;
-							
-						}else{
-							
-							line_out = null;
-						}
-					}
-				}
-				
-				if ( line_out != null ){
-					
-					trace( "-> " + line_out );
-					
-					target_os.write((line_out+NL).getBytes());
-				}
-			}
-			
-			target_os.write( NL.getBytes());
-			
-			target_os.flush();
-			
-			new AEThread2( "HTTPSniffingProxy:proc:2", true )
-			{
-				public void 
-				run() 
-				{
-					try{
-						InputStream	source_is = socket_in.getInputStream();
-						
-						byte[]	buffer = new byte[32000];
-	
-						while( !destroyed ){
-												
-							int	len = source_is.read( buffer );
-								
-							if ( len <= 0 ){
-									
-								break;
-							}
-							
-							target_os.write( buffer, 0, len );
-							
-							trace( "POST:" + new String( buffer, 0, len ));
-							
-						}
-					}catch( Throwable e ){
-					}
-				}
-			}.start();
-			
-			InputStream	target_is = socket_out.getInputStream();
-			
-			OutputStream	source_os = socket_in.getOutputStream();
-			
-			String	reply_header = readHeader( target_is );
-			
-			String[]	reply_lines = splitHeader( reply_header );
-				
-			String	content_type	= null;
-			String	content_charset	= "ISO-8859-1";
-			
-			for (int i=0;i<reply_lines.length;i++){
-				
-				String	line_in 	= reply_lines[i].trim().toLowerCase();
-				
-				String[] bits = line_in.split(":");
-				
-				if ( bits.length >= 2 ){
-
-					String	lhs = bits[0].trim();
-					
-					if ( lhs.equals( "content-type" )){
-						
-						String rhs = reply_lines[i].substring( line_in.indexOf( ':' ) + 1 ).trim();
-								
-						String[] x = rhs.split( ";" );
-						
-						content_type = x[0];
-						
-						if ( x.length > 1 ){
-							
-							int	pos = rhs.toLowerCase().indexOf( "charset" );
-						
-							if ( pos >= 0 ){
-							
-								String cc = rhs.substring( pos+1 );
-							
-								pos = cc.indexOf('=');
-							
-								if ( pos != -1 ){
-								
-									cc = cc.substring( pos+1 ).trim();
-								
-									if ( Charset.isSupported( cc )){
-																		
-										content_charset = cc;
-									}
-								}
-							}
-						}
-					}
-				}
-			}
-			
-			boolean	rewrite 			= false;
-			boolean	chunked				= false;
-			String	content_encoding	= null;
-			
-			if ( content_type == null ){
-				
-				rewrite = true;
-				
-			}else{
-			
-				content_type = content_type.toLowerCase();
-				
-				if ( content_type.indexOf( "text/" ) != -1 ){
-					
-					rewrite = true;
-				}
-			}
-							
-			for (int i=0;i<reply_lines.length;i++){
-								
-				String	line_out	= reply_lines[i];
-
-				String	line_in 	= line_out.trim().toLowerCase();
-				
-				String[] bits = line_in.split(":");
-				
-				if ( bits.length >= 2 ){
-					
-					String	lhs = bits[0].trim();
-					
-					if ( lhs.equals( "set-cookie" )){
-						
-						String	cookies_in = line_out.substring( line_out.indexOf( ':' )+1 );
-						
-						String[] cookies;
-						
-						if ( cookies_in.toLowerCase().indexOf( "expires" ) == -1 ){
-							
-							cookies = cookies_in.split( "," );
-							
-						}else{
-							
-							cookies = new String[]{ cookies_in };
-						}
-						
-						String	cookies_out = "";
-						
-						for (int c=0;c<cookies.length;c++){
-							
-							String	cookie = cookies[c];
-						
-							String[]	x = cookie.split( ";" );
-							
-							String	modified_cookie = "";
-							
-							for (int j=0;j<x.length;j++){
-								
-								String entry = x[j].trim();
-								
-								if ( entry.equalsIgnoreCase( "httponly" )){
-									
-									setHTTPOnlyCookieDetected();
-									
-								}else if ( entry.equalsIgnoreCase( "secure" )){
-									
-								}else if ( entry.toLowerCase().startsWith( "domain" )){
-									
-										// remove domain restriction so cookie sent to localhost
-									
-								}else if ( entry.toLowerCase().startsWith( "expires" )){
-									
-										// force to be session cookie otherwise we'll end up sending
-										// cookies from multiple sites to 'localhost'
-								}else{
-									
-									if ( j == 0 ){
-										
-										int pos = entry.indexOf( '=' );
-										
-										String name 	= entry.substring( 0, pos ).trim();
-										String value 	= entry.substring( pos+1 ).trim();
-										
-										addSetCookieName( name, value );
-									}
-									
-									modified_cookie += (modified_cookie.length()==0?"":"; ") + entry;
-								}
-							}
-							
-							cookies_out += (c==0?"":", " ) + modified_cookie;
-						}					
-						
-						line_out = "Set-Cookie: " + cookies_out;
-						
-					}else if ( lhs.equals( "set-cookie2" )){
-						
-							// http://www.ietf.org/rfc/rfc2965.txt
-						
-							// one or more comma separated
-						
-						String	cookies_in = line_out.substring( line_out.indexOf( ':' )+1 );
-						
-						String[] cookies = cookies_in.split( "," );
-						
-						String	cookies_out = "";
-						
-						for (int c=0;c<cookies.length;c++){
-							
-							String	cookie = cookies[c];
-							
-							String[]	x = cookie.split( ";" );
-							
-							String	modified_cookie = "";
-							
-							for (int j=0;j<x.length;j++){
-								
-								String entry = x[j].trim();
-								
-								if ( entry.equalsIgnoreCase( "secure" )){
-									
-								}else if ( entry.equalsIgnoreCase( "discard" )){
-	
-								}else if ( entry.toLowerCase().startsWith( "domain" )){
-																									
-								}else if ( entry.toLowerCase().startsWith( "port" )){
-																		
-								}else{
-									
-									if ( j == 0 ){
-									
-										int pos = entry.indexOf( '=' );
-										
-										String name = entry.substring( 0, pos ).trim();
-										
-										String value 	= entry.substring( pos+1 ).trim();
-										
-										addSetCookieName( name, value );
-									}
-									
-									modified_cookie += (modified_cookie.length()==0?"":"; ") + entry;
-								}
-							}
-							
-							cookies_out += (c==0?"":", " ) + modified_cookie + "; Discard";
-						}
-						
-						line_out = "Set-Cookie2: " + cookies_out;
-
-					}else if ( lhs.equals( "connection" )){
-						
-						line_out = "Connection: close";
-						
-					}else if ( lhs.equals( "location" )){
-						
-						String page = line_out.substring( line_out.indexOf( ':' )+1).trim();
-						
-						String child_url = page.trim();
-						
-						HTTPAuthHelper child = getChild( child_url, false );
-
-						int	pos = page.indexOf( "://" );
-						
-						if ( pos >= 0 ){
-							
-								// absolute 
-							
-							page = page.substring( pos + 3);
-						
-							pos = page.indexOf( '/' );
-						
-							if ( pos >= 0 ){
-							
-								page = page.substring( pos );
-							
-							}else{
-							
-								page = "/";
-							}
-						}else{
-							
-								// relative. actually illegal as must be absolute
-							
-							if ( !page.startsWith( "/" )){
-								
-								String	temp = target_url;
-								
-								int marker = temp.indexOf( "://" );
-								
-								if ( marker != -1 ){
-									
-										// strip out absolute part
-									
-									temp = temp.substring( marker + 3 );
-									
-									marker = temp.indexOf( "/" );
-									
-									if ( marker == -1 ){
-										
-										temp = "/";
-										
-									}else{
-										
-										temp = temp.substring( marker );
-									}
-								}else{
-									
-									if ( !temp.startsWith( "/" )){
-										
-										temp = "/" + temp;
-									}
-								}
-								
-								marker = temp.lastIndexOf( "/" );
-								
-								if ( marker >= 0 ){
-									
-									temp = temp.substring( 0, marker+1 );
-								}
-								
-								page = temp + page;
-							}
-						}
-						
-						line_out = "Location: http://127.0.0.1:" + child.getPort() + page;
-						
-					}else if ( lhs.equals( "content-encoding" )){
-						 
-						if ( rewrite ){
-							
-							String	encoding = bits[1].trim();
-								 					
-		 					if ( 	encoding.equalsIgnoreCase( "gzip"  ) || 
-		 							encoding.equalsIgnoreCase( "deflate" )){
-			 									 					
-				 				content_encoding = encoding;
-			 					
-				 				line_out = null;
-		 					}
-						}
-					}else if ( lhs.equals( "content-length" )){
-
-						if ( rewrite ){
-							
-							line_out = null;
-						}
-					}else if ( lhs.equals( "transfer-encoding" )){
-
-						if ( bits[1].indexOf( "chunked" ) != -1 ){
-							
-							chunked = true;
-							
-							if ( rewrite ){
-								
-								line_out = null;
-							}
-						}
-	 				}
-				}
-				
-				if ( line_out != null ){
-					
-					trace( "<- " + line_out );
-					
-					source_os.write((line_out+NL).getBytes());
-				}
-			}
-			
-			for ( int i=0;i<cookies_to_remove.size();i++ ){
-				
-				String	name = (String)cookies_to_remove.get(i);
-				
-				if ( !hasSetCookieName( name )){
-					
-					String	remove_str = "Set-Cookie: " + name + "=X; expires=Sun, 01 Jan 2000 01:00:00 GMT";
-					
-					trace( "<- (cookie removal) " + remove_str );
-					
-					source_os.write((remove_str+NL).getBytes());
-					
-					remove_str = "Set-Cookie2: " + name + "=X; Max-Age=0; Version=1";
-					
-					trace( "<- (cookie removal) " + remove_str );
-					
-					source_os.write((remove_str+NL).getBytes());
-				}
-			}
-			
-			byte[]	buffer = new byte[32000];
-			
-
-			if ( rewrite ){
-										
-				StringBuffer	sb = new StringBuffer();
-					
-				if ( chunked ){
-					
-						// chunking uses ISO-8859-1
-					
-					while( true ){
-						
-						int	len = target_is.read( buffer );
-						
-						if ( len <= 0 ){
-							
-							break;
-						}
-						
-						sb.append(new String( buffer, 0, len, "ISO-8859-1" ));
-					}
-					
-					StringBuffer	sb_dechunked = new StringBuffer( sb.length());
-					
-					String chunk = "";
-	
-					int total_length = 0;
-	
-					int	sb_pos = 0;
-										
-					while( sb_pos < sb.length()){
-	
-						chunk += sb.charAt( sb_pos++ );
-	
-							// second time around the chunk will be prefixed with NL
-							// from end of previous
-							// so make sure we ignore this
-	
-						if ( chunk.endsWith( NL ) && chunk.length() > 2 ){
-	
-							int semi_pos = chunk.indexOf( ';' );
-	
-							if ( semi_pos != -1 ){
-	
-								chunk = chunk.substring( 0, semi_pos );
-							}
-	
-							chunk = chunk.trim();
-	
-							int chunk_length = Integer.parseInt( chunk, 16 );
-	
-							if ( chunk_length <= 0 ){
-	
-								break;
-							}
-	
-							total_length += chunk_length;
-	
-							if ( total_length > 2*1024*1024 ){
-	
-								throw (new IOException("Chunk size " + chunk_length
-										+ " too large"));
-							}
-	
-							char[] chunk_buffer = new char[chunk_length];
-	
-							sb.getChars( sb_pos, sb_pos + chunk_length, chunk_buffer, 0 );
-	
-							sb_dechunked.append( chunk_buffer );
-	
-							sb_pos += chunk_length;
-							
-							chunk = "";
-						}
-					}
-					
-						// dechunked ISO-8859-1 - unzip if required and then apply correct charset						
-
-					target_is = new ByteArrayInputStream( sb_dechunked.toString().getBytes( "ISO-8859-1" ));
-				}
-				
-				if ( content_encoding != null ){
-
-					if ( content_encoding.equalsIgnoreCase( "gzip"  )){
-		 					
-						target_is = new GZIPInputStream( target_is );
-		 							 				
-	 				}else if ( content_encoding.equalsIgnoreCase( "deflate" )){
-	 						
-	 					target_is = new InflaterInputStream( target_is );
-	 				}
-	 			}
-					
-				sb.setLength(0);
-					
-				while( !destroyed ){
-						
-					int	len = target_is.read( buffer );
-						
-					if ( len <= 0 ){
-							
-						break;
-					}
-				
-					sb.append(new String( buffer, 0, len, content_charset ));
-				}
-				
-				String 	str 	= sb.toString();
-				String	lc_str 	= str.toLowerCase();
-				
-				StringBuffer	result 	= null;
-				int				str_pos	= 0;
-				
-				// FileUtil.writeBytesAsFile( "C:\\temp\\xxx" + new Random().nextInt(100000) + ".txt", str.getBytes());
-				
-				while( true ){
-					
-						// http://a.b
-					
-					int	url_start = str.length() - str_pos >=10?lc_str.indexOf( "http", str_pos ):-1;
-					
-					if ( url_start == -1 ){
-												
-						break;
-					}
-					
-					int	match_pos;
-					
-					if ( lc_str.charAt( url_start + 4 ) == 's' ){
-						
-						match_pos = url_start + 5;
-						
-					}else{
-						
-						match_pos = url_start + 4;
-					}
-					
-					if ( lc_str.substring( match_pos, match_pos+3 ).equals( "://" )){
-						
-						int	url_end = -1;
-						
-						for (int i=match_pos+3;;i++){
-							
-							char c = lc_str.charAt(i);
-							
-							if ( c == '/' ){
-							
-								url_end = i+1;
-								
-								break;
-																
-							}else if ( c == '.' || c == '-' || c == ':' ){
-								
-							}else if ( c >= '0' && c <= '9' ){
-								
-							}else if ( c >= 'a' && c <= 'z' ){
-																
-							}else{
-								
-								url_end = i;
-								
-								break;
-							}
-							
-							if ( i == lc_str.length()-1 ){
-
-								url_end = i;
-							}
-						}
-						
-						if ( url_end > url_start ){
-							
-							String 	url_str = str.substring( url_start, url_end );
-							
-							boolean	appended = false;
-							
-							try{	
-									// make sure vald URL
-								
-								URL url = new URL( url_str );
-								
-								if ( url.getHost().length() > 0 ){
-								
-									boolean	existing_only = true;
-									
-										// override if form action or meta
-									
-									for (int i=url_start-1;i>=0&&url_start-i<512;i--){
-										
-										if ( lc_str.charAt( i ) == '<' ){
-											
-											String prefix = lc_str.substring(i, url_start);
-											
-											if ( prefix.indexOf( "form" ) != -1 ){
-												
-												existing_only = false;
-												
-											}else if ( 	prefix.indexOf( "meta" ) != -1 &&
-														prefix.indexOf( "http-equiv" ) != -1 ){
-												
-												existing_only = false;
-											}
-											
-											break;
-										}
-									}
-									
-									HTTPAuthHelper child = getChild(  url_str, existing_only );
-									
-									if ( child != null ){
-										
-										String replacement = "http://127.0.0.1:" + child.getPort();
-										
-										if ( url_str.endsWith( "/" )){
-											
-											replacement += "/";
-										}
-										
-										if ( result == null ){
-											
-											result = new StringBuffer( str.length());
-											
-											if ( url_start > 0 ){
-												
-												result.append( str.subSequence( 0, url_start ));
-											}
-										}else if ( url_start > str_pos ){
-											
-											result.append( str.subSequence( str_pos, url_start ));
-										}
-										
-										trace( "Replacing " + url_str + " with " + replacement );
-										
-										result.append( replacement );
-										
-										appended = true;
-										
-									}else{
-										
-										trace( "    No child for " + url_str );
-									}
-								}
-							}catch( Throwable e ){
-								
-							}
-							
-							if ( result != null && !appended ){
-								
-								result.append( str.subSequence( str_pos, url_end ));
-							}
-							
-							str_pos = url_end;
-							
-						}else{
-							
-							break;
-						}
-					}else{
-						
-						if ( result != null ){
-							
-							result.append( str.subSequence( str_pos, match_pos ));
-						}
-						
-						str_pos = match_pos;
-					}
-				}
-				
-				if ( result != null ){
-							
-					if ( str_pos < str.length() ){
-						
-						result.append( str.subSequence( str_pos, str.length()));
-					}
-
-					sb = result;
-				}
-				
-				source_os.write( ( "Content-Length: " + sb.length() + NL ).getBytes());
-				
-				source_os.write( NL.getBytes());
-				
-				source_os.write( sb.toString().getBytes( content_charset ));
-				
-			}else{
-				
-				source_os.write( NL.getBytes());
-							
-				while( !destroyed  ){
-									
-					int	len = target_is.read( buffer );
-					
-					if ( len <= 0 ){
-						
-						break;
-					}
-					
-					source_os.write( buffer, 0, len );
-				}
-			}
-		}
-		
-		private String
-		readHeader(
-			InputStream		is )
-		
-			throws IOException
-		{
-			String	header = "";
-			
-			byte[]	buffer = new byte[1];
-			
-			boolean	found = false;
-			
-			while( true ){
-			
-				if ( is.read( buffer ) != 1 ){
-					
-					break;
-				}
-				
-				header += (char)buffer[0];
-				
-				if ( header.endsWith( NL + NL )){
-					
-					found = true;
-					
-					break;
-				}
-			}
-			
-			if ( !found ){
-				
-				throw( new IOException( "End of stream reading header" ));
-			}
-			
-			return( header );
-		}
-		
-		private String[]
-		splitHeader(
-			String		str )
-		{
-			String[] bits = str.split( NL );
-			
-			return( bits );
-		}
-			
-		private void
-		destroy()
-		{
-			synchronized( this ){
-				
-				if ( destroyed ){
-					
-					return;
-				}
-				
-				destroyed = true;
-			}
-			
-			if ( socket_out != null ){
-				
-				try{
-					socket_out.close();
-					
-				}catch( Throwable e ){
-					
-				}
-			}
-			try{
-				socket_in.close();
-				
-			}catch( Throwable e ){
-			}
-		}
-	}
-	
-	private void
-	trace(
-		String		str )
-	{
-		if ( TRACE ){
-			
-			System.out.println( str );
-		}
-	}
-	
-	public static void
-	main(
-		String[]		args )
-	{
-		try{
-			HTTPAuthHelper proxy = new HTTPAuthHelper( new URL( "https://client.vuze.com/" ));
-			
-			proxy.start();
-			
-			System.out.println( "port=" + proxy.getPort());
-			
-			while( true ){
-				
-				Thread.sleep(1000);
-			}
-		}catch( Throwable e ){
-			
-			e.printStackTrace();
-		}
-	}
-}
+/*
+ * Created on Oct 2, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.util.http;
+
+import java.net.*;
+import java.nio.charset.Charset;
+import java.util.*;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.InflaterInputStream;
+import java.io.*;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.gudy.azureus2.core3.security.SESecurityManager;
+import org.gudy.azureus2.core3.util.*;
+
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
+public class 
+HTTPAuthHelper 
+{
+	public static final boolean	TRACE	= false;
+	
+	public static final int MAX_PROCESSORS = 32;
+		
+	public static final int	CONNECT_TIMEOUT		= 30*1000;
+	public static final int READ_TIMEOUT		= 30*1000;
+
+	private HTTPAuthHelper			parent;
+	private Map						children	= new HashMap();
+	
+	private URL						delegate_to;
+	private String					delegate_to_host;
+	private int						delegate_to_port;
+	private boolean					delegate_is_https;
+	
+	private Proxy	delegate_to_proxy;
+	
+	private CopyOnWriteList			listeners = new CopyOnWriteList();
+	
+	private int		port;
+	
+	private ServerSocket	server_socket;	
+	
+	private boolean			http_only_detected;
+	
+	private Map				cookie_names_set	= new HashMap();
+	
+	private ThreadPool		thread_pool = new ThreadPool("HTTPSniffer", MAX_PROCESSORS, true );
+	
+	private List			processors = new ArrayList();
+	
+	private volatile boolean		destroyed;
+		
+	public
+	HTTPAuthHelper(
+		URL			url )
+	
+		throws Exception
+	{
+		this( null, url );
+	}
+	
+	private
+	HTTPAuthHelper(
+		HTTPAuthHelper			_parent,
+		URL						_delegate_to )
+	
+		throws Exception
+	{
+		parent				= _parent;
+		delegate_to			= _delegate_to;
+		
+		delegate_to_host	= delegate_to.getHost();
+		delegate_is_https	= delegate_to.getProtocol().toLowerCase().equals( "https" );
+		delegate_to_port	= delegate_to.getPort()==-1?delegate_to.getDefaultPort():delegate_to.getPort();
+					
+		server_socket = new ServerSocket();
+		
+		server_socket.setReuseAddress( true ); 
+             
+		server_socket.bind( new InetSocketAddress( "127.0.0.1", 0 ));
+        
+        port = server_socket.getLocalPort();
+	}
+	
+	public void
+	setProxy(
+		Proxy		_proxy )
+	{
+		delegate_to_proxy	= _proxy;
+	}
+	
+	public void
+	start()
+	{
+        new AEThread2( 
+        	"HTTPSniffingProxy: " + delegate_to_host + ":" + delegate_to_port + "/" + delegate_is_https + "/" + port, 
+        	true )
+        	{
+        		public void 
+        		run() 
+        		{
+        			try{
+        				while( !destroyed ){
+    
+        					Socket	socket = server_socket.accept();
+        					   
+        					socket.setSoTimeout( READ_TIMEOUT );
+        					
+        					synchronized( HTTPAuthHelper.this ){
+        						
+        						if ( processors.size() >= MAX_PROCESSORS ){
+        							
+        							try{
+        								Debug.out( "Too many processors" );
+        								
+        								socket.close();
+        								
+        							}catch( Throwable e ){
+        							}
+        						}else{
+        							
+        							processor proc = new processor( socket );
+        							
+        							processors.add( proc );
+        							
+        							proc.start();
+        						}
+        					}
+        				}
+        			}catch( Throwable e ){
+        				
+        				if ( !destroyed ){
+        					
+        					Debug.printStackTrace( e );
+        				}
+        			}
+        		}
+        	}.start();	
+	}
+	
+	public int
+	getPort()
+	{
+		return( port );
+	}
+	
+	public boolean
+	wasHTTPOnlyCookieDetected()
+	{
+		return( http_only_detected );
+	}
+	
+	private void
+	setHTTPOnlyCookieDetected()
+	{
+		http_only_detected = true;
+		
+		if ( parent != null ){
+			
+			parent.setHTTPOnlyCookieDetected();
+		}
+	}
+	
+	private String
+	getKey(
+		URL		url )
+	{
+		int child_port = url.getPort()==-1?url.getDefaultPort():url.getPort();
+		
+		String	key = url.getProtocol() + ":" + url.getHost() + ":" + child_port;
+
+		return( key );
+	}
+	
+	private HTTPAuthHelper
+	getChild(
+		String		url_str,
+		boolean		optional )
+	
+		throws Exception
+	{
+		if ( parent != null ){
+	
+			return( parent.getChild( url_str,optional ));
+		}
+	
+		String lc_url_str = url_str.toLowerCase();
+		
+		if ( lc_url_str.startsWith( "http://" ) || lc_url_str.startsWith( "https://")){
+			
+			URL child_url = new URL( url_str );
+			
+			String	child_key = getKey( child_url );
+			
+			if ( child_key.equals( getKey( delegate_to ))){
+				
+				return( this );
+			}
+			
+			synchronized( this ){
+	
+				if ( destroyed ){
+					
+					throw( new Exception( "Destroyed" ));
+				}
+				
+				HTTPAuthHelper child = (HTTPAuthHelper)children.get( child_key );
+				
+				if ( optional ){
+					
+						// create children for related domains
+					
+					String	base_host 	= delegate_to.getHost();
+					String	child_host	= child_url.getHost();
+					
+					int	base_pos = base_host.lastIndexOf( '.' );
+					base_pos = base_host.lastIndexOf( '.', base_pos-1 );
+					
+					int	child_pos = child_host.lastIndexOf( '.' );
+					child_pos = child_host.lastIndexOf( '.', child_pos-1 );
+
+					String base_dom 	= base_host.substring( base_pos, base_host.length());
+					String child_dom 	= child_host.substring( child_pos, child_host.length());
+					
+					if ( base_dom.equals( child_dom )){
+						
+						optional = false;
+					}
+				}
+				
+				if ( child == null && !optional ){
+				
+					child = new HTTPAuthHelper( this, new URL( url_str ));
+							
+					children.put( child_key, child );
+					
+					child.start();
+				}
+				
+				return( child );
+			}
+		}else{
+				//relative
+			
+			return( this );
+		}
+	}
+
+	private void
+	addSetCookieName(
+		String		name,
+		String		value )
+	{
+		if ( parent != null ){
+			
+			parent.addSetCookieName( name, value );
+			
+		}else{
+			
+			boolean	new_entry;
+			
+			synchronized( cookie_names_set ){
+		
+				trace( "SetCookieName: " + name );
+				
+				String old_value = (String)cookie_names_set.put( name, value );
+				
+				new_entry = old_value==null || !old_value.equals( value );
+			}
+			
+			if ( new_entry ){
+				
+				Iterator it = listeners.iterator();
+				
+				while( it.hasNext()){
+					
+					try{
+						((HTTPAuthHelperListener)it.next()).cookieFound( this, name, value );
+						
+					}catch( Throwable e ){
+						
+						Debug.printStackTrace(e );
+					}
+				}
+			}
+		}
+	}
+	
+	private boolean
+	hasSetCookieName(
+		String		name )
+	{
+		if ( parent != null ){
+			
+			return( parent.hasSetCookieName( name ));
+			
+		}else{
+		
+			synchronized( cookie_names_set ){
+				
+				trace( "GetCookieName: " + name );
+				
+				return( cookie_names_set.containsKey( name ));
+			}
+		}
+	}
+	
+	public void
+	addListener(
+		HTTPAuthHelperListener		listener )
+	{
+		listeners.add( listener );
+	}
+	
+	public void
+	destroy()
+	{
+		List	processors_to_destroy;
+		List	chidren_to_destroy;
+		
+		synchronized( this ){
+			
+			if ( destroyed ){
+				
+				return;
+			}
+			
+			destroyed = true;
+				
+			chidren_to_destroy = new ArrayList( children.values());
+			
+			children.clear();
+			
+			processors_to_destroy = new ArrayList( processors );
+			
+			processors.clear();
+			
+			try{				
+				server_socket.close();
+
+			}catch( Throwable e ){	
+			}
+		}
+				
+		for (int i=0;i<chidren_to_destroy.size();i++){
+			
+			try{
+				((HTTPAuthHelper)chidren_to_destroy.get(i)).destroy();
+				
+			}catch( Throwable e ){
+			}
+		}
+		
+		for (int i=0;i<processors_to_destroy.size();i++){
+			
+			try{
+				((processor)processors_to_destroy.get(i)).destroy();
+			
+			}catch( Throwable e ){
+			}
+		}
+	}
+	
+	private class
+	processor
+	{
+		private static final String	NL = "\r\n";
+		
+		private Socket		socket_in;
+		private Socket		socket_out;
+		
+		private volatile boolean	destroyed;
+		
+		private
+		processor(
+			Socket		_socket )
+		{
+			socket_in	= _socket;
+		}
+		
+		private void
+		start()
+		{
+			thread_pool.run(
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						try{
+							sniff();
+							
+						}finally{
+													
+							synchronized( HTTPAuthHelper.this ){
+
+								processors.remove( processor.this );
+							}
+						}
+					}
+				});
+		}
+		
+		private void
+		sniff()
+		{
+			try{
+				InputStream is = socket_in.getInputStream();
+				
+				String request_header = readHeader( is );
+								
+				connectToDelegate();
+				
+				process( request_header );
+				
+			}catch( Throwable e ){
+				
+				if ( !( e instanceof IOException )){
+					
+					Debug.out( e );
+				}
+				
+				destroy();
+			}
+		}
+		
+		private void
+		connectToDelegate()
+		
+			throws IOException
+		{
+			try{
+				if ( delegate_is_https ){
+					
+					TrustManager[] trustAllCerts = new TrustManager[]{
+							new X509TrustManager() {
+								public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+									return null;
+								}
+								public void checkClientTrusted(
+										java.security.cert.X509Certificate[] certs, String authType) {
+								}
+								public void checkServerTrusted(
+										java.security.cert.X509Certificate[] certs, String authType) {
+								}
+							}
+						};
+				
+					SSLContext sc = SSLContext.getInstance("SSL");
+				
+					sc.init(null, trustAllCerts, RandomUtils.SECURE_RANDOM );
+				
+					SSLSocketFactory factory = sc.getSocketFactory();
+
+					try{
+						if ( delegate_to_proxy == null ){
+							
+							socket_out = factory.createSocket();
+							
+							socket_out.connect( new InetSocketAddress( delegate_to_host, delegate_to_port ), CONNECT_TIMEOUT );
+							
+						}else{
+							
+							Socket plain_socket = new Socket( delegate_to_proxy );
+							
+							plain_socket.connect( new InetSocketAddress( delegate_to_host, delegate_to_port ), CONNECT_TIMEOUT );
+							
+							socket_out = factory.createSocket( plain_socket, delegate_to_host, delegate_to_port, true );
+						}
+					
+					}catch( SSLException ssl_excep ){
+								
+						if ( socket_out != null ){
+							
+							try{
+								socket_out.close();
+								
+							}catch( Throwable e ){		
+							}
+						}
+						
+						factory = SESecurityManager.installServerCertificates( "AZ-sniffer:" + delegate_to_host + ":" + port, delegate_to_host, delegate_to_port );
+						
+						if ( delegate_to_proxy == null ){
+							
+							socket_out = factory.createSocket();
+							
+							socket_out.connect( new InetSocketAddress( delegate_to_host, delegate_to_port ), CONNECT_TIMEOUT );
+							
+						}else{
+							
+							Socket plain_socket = new Socket( delegate_to_proxy );
+							
+							plain_socket.connect( new InetSocketAddress( delegate_to_host, delegate_to_port ), CONNECT_TIMEOUT );
+							
+							socket_out = factory.createSocket( plain_socket, delegate_to_host, delegate_to_port, true );
+						}					}
+				}else{
+					
+					if ( delegate_to_proxy == null ){
+					
+						socket_out = new Socket();
+						
+					}else{
+						
+						socket_out = new Socket( delegate_to_proxy );
+					}
+					
+					socket_out.connect( new InetSocketAddress( delegate_to_host, delegate_to_port ), CONNECT_TIMEOUT );
+				}
+			}catch( Throwable e ){
+				
+				if ( e instanceof IOException ){
+					
+					throw((IOException)e );
+				}
+				
+				throw( new IOException( e.toString()));
+				
+			}finally{
+				
+				if ( socket_out != null ){
+										
+					synchronized( this ){
+						
+						if ( destroyed ){
+
+							try{
+								socket_out.close();
+								
+							}catch( Throwable e ){
+								
+							}finally{
+								
+								socket_out = null;
+							}
+							
+							throw( new IOException( "destroyed" ));
+						}
+					}
+				}
+			}
+		}
+		
+		private void
+		process(
+			String		request_header )
+		
+			throws Exception
+		{
+			final OutputStream target_os = socket_out.getOutputStream();
+			
+			String[]	request_lines = splitHeader( request_header );
+			
+			String target_url = request_lines[0];
+			
+			int	space_pos = target_url.indexOf(' ');
+			
+			if ( space_pos == -1 ){
+				
+				System.out.println( "eh?" );
+			}
+			target_url = target_url.substring( space_pos ).trim();
+			
+			space_pos = target_url.indexOf(' ');
+			
+			target_url = target_url.substring( 0, space_pos ).trim();
+
+			trace( "Page request for " + target_url );
+			
+			List	cookies_to_remove = new ArrayList();
+
+			for (int i=0;i<request_lines.length;i++){
+				
+				String	line_out	= request_lines[i];
+
+				String	line_in 	= line_out.trim().toLowerCase();
+				
+				String[] bits = line_in.split(":");
+				
+				if ( bits.length >= 2 ){
+					
+					String	lhs = bits[0].trim();
+					
+					if ( lhs.equals( "host" )){
+						
+						String	port_str;
+						
+						if ( delegate_to_port == 80 || delegate_to_port == 443 ){
+						
+							port_str = "";
+							
+						}else{
+							
+							port_str = ":" + delegate_to_port;
+						}
+						
+						line_out = "Host: " + delegate_to_host + port_str;
+						
+					}else if ( lhs.equals( "connection" )){
+						
+						line_out = "Connection: close";
+						
+					}else if ( lhs.equals( "referer" )){
+						
+						String page = line_out.substring( line_out.indexOf( ':' )+1).trim();
+						
+						page = page.substring( page.indexOf( "://") + 3);
+						
+						int pos = page.indexOf( '/' );
+						
+						if ( pos >= 0 ){
+						
+							page = page.substring( pos );
+							
+						}else{
+							
+							page = "/";
+						}
+						
+						String	port_str;
+						
+						if ( delegate_to_port == 80 || delegate_to_port == 443 ){
+						
+							port_str = "";
+							
+						}else{
+							
+							port_str = ":" + delegate_to_port;
+						}
+
+						line_out = "Referer: http" + (delegate_is_https?"s":"") + "://" + delegate_to_host + port_str + page;
+						
+					}else if ( lhs.equals( "cookie" )){
+
+						String cookies_str = line_out.substring( line_out.indexOf( ':' )+1).trim();
+						
+						String[] cookies = cookies_str.split( ";" );
+						
+						String	cookies_out = "";
+						
+						for (int j=0;j<cookies.length;j++){
+							
+							String	cookie = cookies[j];
+							
+							String	name = cookie.split( "=" )[0].trim();
+							
+							if ( hasSetCookieName( name )){
+								
+								cookies_out += (cookies_out.length()==0?"":"; ") + cookie;
+								
+							}else{
+								
+								cookies_to_remove.add( name );
+							}
+						}
+						
+						if ( cookies_out.length() > 0 ){
+							
+							line_out = "Cookie: " + cookies_out;
+							
+						}else{
+							
+							line_out = null;
+						}
+					}
+				}
+				
+				if ( line_out != null ){
+					
+					trace( "-> " + line_out );
+					
+					target_os.write((line_out+NL).getBytes());
+				}
+			}
+			
+			target_os.write( NL.getBytes());
+			
+			target_os.flush();
+			
+			new AEThread2( "HTTPSniffingProxy:proc:2", true )
+			{
+				public void 
+				run() 
+				{
+					try{
+						InputStream	source_is = socket_in.getInputStream();
+						
+						byte[]	buffer = new byte[32000];
+	
+						while( !destroyed ){
+												
+							int	len = source_is.read( buffer );
+								
+							if ( len <= 0 ){
+									
+								break;
+							}
+							
+							target_os.write( buffer, 0, len );
+							
+							trace( "POST:" + new String( buffer, 0, len ));
+							
+						}
+					}catch( Throwable e ){
+					}
+				}
+			}.start();
+			
+			InputStream	target_is = socket_out.getInputStream();
+			
+			OutputStream	source_os = socket_in.getOutputStream();
+			
+			String	reply_header = readHeader( target_is );
+			
+			String[]	reply_lines = splitHeader( reply_header );
+				
+			String	content_type	= null;
+			String	content_charset	= "ISO-8859-1";
+			
+			for (int i=0;i<reply_lines.length;i++){
+				
+				String	line_in 	= reply_lines[i].trim().toLowerCase();
+				
+				String[] bits = line_in.split(":");
+				
+				if ( bits.length >= 2 ){
+
+					String	lhs = bits[0].trim();
+					
+					if ( lhs.equals( "content-type" )){
+						
+						String rhs = reply_lines[i].substring( line_in.indexOf( ':' ) + 1 ).trim();
+								
+						String[] x = rhs.split( ";" );
+						
+						content_type = x[0];
+						
+						if ( x.length > 1 ){
+							
+							int	pos = rhs.toLowerCase().indexOf( "charset" );
+						
+							if ( pos >= 0 ){
+							
+								String cc = rhs.substring( pos+1 );
+							
+								pos = cc.indexOf('=');
+							
+								if ( pos != -1 ){
+								
+									cc = cc.substring( pos+1 ).trim();
+								
+									if ( Charset.isSupported( cc )){
+																		
+										content_charset = cc;
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+			
+			boolean	rewrite 			= false;
+			boolean	chunked				= false;
+			String	content_encoding	= null;
+			
+			if ( content_type == null ){
+				
+				rewrite = true;
+				
+			}else{
+			
+				content_type = content_type.toLowerCase();
+				
+				if ( content_type.indexOf( "text/" ) != -1 ){
+					
+					rewrite = true;
+				}
+			}
+							
+			for (int i=0;i<reply_lines.length;i++){
+								
+				String	line_out	= reply_lines[i];
+
+				String	line_in 	= line_out.trim().toLowerCase();
+				
+				String[] bits = line_in.split(":");
+				
+				if ( bits.length >= 2 ){
+					
+					String	lhs = bits[0].trim();
+					
+					if ( lhs.equals( "set-cookie" )){
+						
+						String	cookies_in = line_out.substring( line_out.indexOf( ':' )+1 );
+						
+						String[] cookies;
+						
+						if ( cookies_in.toLowerCase().indexOf( "expires" ) == -1 ){
+							
+							cookies = cookies_in.split( "," );
+							
+						}else{
+							
+							cookies = new String[]{ cookies_in };
+						}
+						
+						String	cookies_out = "";
+						
+						for (int c=0;c<cookies.length;c++){
+							
+							String	cookie = cookies[c];
+						
+							String[]	x = cookie.split( ";" );
+							
+							String	modified_cookie = "";
+							
+							for (int j=0;j<x.length;j++){
+								
+								String entry = x[j].trim();
+								
+								if ( entry.equalsIgnoreCase( "httponly" )){
+									
+									setHTTPOnlyCookieDetected();
+									
+								}else if ( entry.equalsIgnoreCase( "secure" )){
+									
+								}else if ( entry.toLowerCase().startsWith( "domain" )){
+									
+										// remove domain restriction so cookie sent to localhost
+									
+								}else if ( entry.toLowerCase().startsWith( "expires" )){
+									
+										// force to be session cookie otherwise we'll end up sending
+										// cookies from multiple sites to 'localhost'
+								}else{
+									
+									if ( j == 0 ){
+										
+										int pos = entry.indexOf( '=' );
+										
+										String name 	= entry.substring( 0, pos ).trim();
+										String value 	= entry.substring( pos+1 ).trim();
+										
+										addSetCookieName( name, value );
+									}
+									
+									modified_cookie += (modified_cookie.length()==0?"":"; ") + entry;
+								}
+							}
+							
+							cookies_out += (c==0?"":", " ) + modified_cookie;
+						}					
+						
+						line_out = "Set-Cookie: " + cookies_out;
+						
+					}else if ( lhs.equals( "set-cookie2" )){
+						
+							// http://www.ietf.org/rfc/rfc2965.txt
+						
+							// one or more comma separated
+						
+						String	cookies_in = line_out.substring( line_out.indexOf( ':' )+1 );
+						
+						String[] cookies = cookies_in.split( "," );
+						
+						String	cookies_out = "";
+						
+						for (int c=0;c<cookies.length;c++){
+							
+							String	cookie = cookies[c];
+							
+							String[]	x = cookie.split( ";" );
+							
+							String	modified_cookie = "";
+							
+							for (int j=0;j<x.length;j++){
+								
+								String entry = x[j].trim();
+								
+								if ( entry.equalsIgnoreCase( "secure" )){
+									
+								}else if ( entry.equalsIgnoreCase( "discard" )){
+	
+								}else if ( entry.toLowerCase().startsWith( "domain" )){
+																									
+								}else if ( entry.toLowerCase().startsWith( "port" )){
+																		
+								}else{
+									
+									if ( j == 0 ){
+									
+										int pos = entry.indexOf( '=' );
+										
+										String name = entry.substring( 0, pos ).trim();
+										
+										String value 	= entry.substring( pos+1 ).trim();
+										
+										addSetCookieName( name, value );
+									}
+									
+									modified_cookie += (modified_cookie.length()==0?"":"; ") + entry;
+								}
+							}
+							
+							cookies_out += (c==0?"":", " ) + modified_cookie + "; Discard";
+						}
+						
+						line_out = "Set-Cookie2: " + cookies_out;
+
+					}else if ( lhs.equals( "connection" )){
+						
+						line_out = "Connection: close";
+						
+					}else if ( lhs.equals( "location" )){
+						
+						String page = line_out.substring( line_out.indexOf( ':' )+1).trim();
+						
+						String child_url = page.trim();
+						
+						HTTPAuthHelper child = getChild( child_url, false );
+
+						int	pos = page.indexOf( "://" );
+						
+						if ( pos >= 0 ){
+							
+								// absolute 
+							
+							page = page.substring( pos + 3);
+						
+							pos = page.indexOf( '/' );
+						
+							if ( pos >= 0 ){
+							
+								page = page.substring( pos );
+							
+							}else{
+							
+								page = "/";
+							}
+						}else{
+							
+								// relative. actually illegal as must be absolute
+							
+							if ( !page.startsWith( "/" )){
+								
+								String	temp = target_url;
+								
+								int marker = temp.indexOf( "://" );
+								
+								if ( marker != -1 ){
+									
+										// strip out absolute part
+									
+									temp = temp.substring( marker + 3 );
+									
+									marker = temp.indexOf( "/" );
+									
+									if ( marker == -1 ){
+										
+										temp = "/";
+										
+									}else{
+										
+										temp = temp.substring( marker );
+									}
+								}else{
+									
+									if ( !temp.startsWith( "/" )){
+										
+										temp = "/" + temp;
+									}
+								}
+								
+								marker = temp.lastIndexOf( "/" );
+								
+								if ( marker >= 0 ){
+									
+									temp = temp.substring( 0, marker+1 );
+								}
+								
+								page = temp + page;
+							}
+						}
+						
+						line_out = "Location: http://127.0.0.1:" + child.getPort() + page;
+						
+					}else if ( lhs.equals( "content-encoding" )){
+						 
+						if ( rewrite ){
+							
+							String	encoding = bits[1].trim();
+								 					
+		 					if ( 	encoding.equalsIgnoreCase( "gzip"  ) || 
+		 							encoding.equalsIgnoreCase( "deflate" )){
+			 									 					
+				 				content_encoding = encoding;
+			 					
+				 				line_out = null;
+		 					}
+						}
+					}else if ( lhs.equals( "content-length" )){
+
+						if ( rewrite ){
+							
+							line_out = null;
+						}
+					}else if ( lhs.equals( "transfer-encoding" )){
+
+						if ( bits[1].indexOf( "chunked" ) != -1 ){
+							
+							chunked = true;
+							
+							if ( rewrite ){
+								
+								line_out = null;
+							}
+						}
+	 				}
+				}
+				
+				if ( line_out != null ){
+					
+					trace( "<- " + line_out );
+					
+					source_os.write((line_out+NL).getBytes());
+				}
+			}
+			
+			for ( int i=0;i<cookies_to_remove.size();i++ ){
+				
+				String	name = (String)cookies_to_remove.get(i);
+				
+				if ( !hasSetCookieName( name )){
+					
+					String	remove_str = "Set-Cookie: " + name + "=X; expires=Sun, 01 Jan 2000 01:00:00 GMT";
+					
+					trace( "<- (cookie removal) " + remove_str );
+					
+					source_os.write((remove_str+NL).getBytes());
+					
+					remove_str = "Set-Cookie2: " + name + "=X; Max-Age=0; Version=1";
+					
+					trace( "<- (cookie removal) " + remove_str );
+					
+					source_os.write((remove_str+NL).getBytes());
+				}
+			}
+			
+			byte[]	buffer = new byte[32000];
+			
+
+			if ( rewrite ){
+										
+				StringBuffer	sb = new StringBuffer();
+					
+				if ( chunked ){
+					
+						// chunking uses ISO-8859-1
+					
+					while( true ){
+						
+						int	len = target_is.read( buffer );
+						
+						if ( len <= 0 ){
+							
+							break;
+						}
+						
+						sb.append(new String( buffer, 0, len, "ISO-8859-1" ));
+					}
+					
+					StringBuffer	sb_dechunked = new StringBuffer( sb.length());
+					
+					String chunk = "";
+	
+					int total_length = 0;
+	
+					int	sb_pos = 0;
+										
+					while( sb_pos < sb.length()){
+	
+						chunk += sb.charAt( sb_pos++ );
+	
+							// second time around the chunk will be prefixed with NL
+							// from end of previous
+							// so make sure we ignore this
+	
+						if ( chunk.endsWith( NL ) && chunk.length() > 2 ){
+	
+							int semi_pos = chunk.indexOf( ';' );
+	
+							if ( semi_pos != -1 ){
+	
+								chunk = chunk.substring( 0, semi_pos );
+							}
+	
+							chunk = chunk.trim();
+	
+							int chunk_length = Integer.parseInt( chunk, 16 );
+	
+							if ( chunk_length <= 0 ){
+	
+								break;
+							}
+	
+							total_length += chunk_length;
+	
+							if ( total_length > 2*1024*1024 ){
+	
+								throw (new IOException("Chunk size " + chunk_length
+										+ " too large"));
+							}
+	
+							char[] chunk_buffer = new char[chunk_length];
+	
+							sb.getChars( sb_pos, sb_pos + chunk_length, chunk_buffer, 0 );
+	
+							sb_dechunked.append( chunk_buffer );
+	
+							sb_pos += chunk_length;
+							
+							chunk = "";
+						}
+					}
+					
+						// dechunked ISO-8859-1 - unzip if required and then apply correct charset						
+
+					target_is = new ByteArrayInputStream( sb_dechunked.toString().getBytes( "ISO-8859-1" ));
+				}
+				
+				if ( content_encoding != null ){
+
+					if ( content_encoding.equalsIgnoreCase( "gzip"  )){
+		 					
+						target_is = new GZIPInputStream( target_is );
+		 							 				
+	 				}else if ( content_encoding.equalsIgnoreCase( "deflate" )){
+	 						
+	 					target_is = new InflaterInputStream( target_is );
+	 				}
+	 			}
+					
+				sb.setLength(0);
+					
+				while( !destroyed ){
+						
+					int	len = target_is.read( buffer );
+						
+					if ( len <= 0 ){
+							
+						break;
+					}
+				
+					sb.append(new String( buffer, 0, len, content_charset ));
+				}
+				
+				String 	str 	= sb.toString();
+				String	lc_str 	= str.toLowerCase();
+				
+				StringBuffer	result 	= null;
+				int				str_pos	= 0;
+				
+				// FileUtil.writeBytesAsFile( "C:\\temp\\xxx" + new Random().nextInt(100000) + ".txt", str.getBytes());
+				
+				while( true ){
+					
+						// http://a.b
+					
+					int	url_start = str.length() - str_pos >=10?lc_str.indexOf( "http", str_pos ):-1;
+					
+					if ( url_start == -1 ){
+												
+						break;
+					}
+					
+					int	match_pos;
+					
+					if ( lc_str.charAt( url_start + 4 ) == 's' ){
+						
+						match_pos = url_start + 5;
+						
+					}else{
+						
+						match_pos = url_start + 4;
+					}
+					
+					if ( lc_str.substring( match_pos, match_pos+3 ).equals( "://" )){
+						
+						int	url_end = -1;
+						
+						for (int i=match_pos+3;;i++){
+							
+							char c = lc_str.charAt(i);
+							
+							if ( c == '/' ){
+							
+								url_end = i+1;
+								
+								break;
+																
+							}else if ( c == '.' || c == '-' || c == ':' ){
+								
+							}else if ( c >= '0' && c <= '9' ){
+								
+							}else if ( c >= 'a' && c <= 'z' ){
+																
+							}else{
+								
+								url_end = i;
+								
+								break;
+							}
+							
+							if ( i == lc_str.length()-1 ){
+
+								url_end = i;
+							}
+						}
+						
+						if ( url_end > url_start ){
+							
+							String 	url_str = str.substring( url_start, url_end );
+							
+							boolean	appended = false;
+							
+							try{	
+									// make sure vald URL
+								
+								URL url = new URL( url_str );
+								
+								if ( url.getHost().length() > 0 ){
+								
+									boolean	existing_only = true;
+									
+										// override if form action or meta
+									
+									for (int i=url_start-1;i>=0&&url_start-i<512;i--){
+										
+										if ( lc_str.charAt( i ) == '<' ){
+											
+											String prefix = lc_str.substring(i, url_start);
+											
+											if ( prefix.indexOf( "form" ) != -1 ){
+												
+												existing_only = false;
+												
+											}else if ( 	prefix.indexOf( "meta" ) != -1 &&
+														prefix.indexOf( "http-equiv" ) != -1 ){
+												
+												existing_only = false;
+											}
+											
+											break;
+										}
+									}
+									
+									HTTPAuthHelper child = getChild(  url_str, existing_only );
+									
+									if ( child != null ){
+										
+										String replacement = "http://127.0.0.1:" + child.getPort();
+										
+										if ( url_str.endsWith( "/" )){
+											
+											replacement += "/";
+										}
+										
+										if ( result == null ){
+											
+											result = new StringBuffer( str.length());
+											
+											if ( url_start > 0 ){
+												
+												result.append( str.subSequence( 0, url_start ));
+											}
+										}else if ( url_start > str_pos ){
+											
+											result.append( str.subSequence( str_pos, url_start ));
+										}
+										
+										trace( "Replacing " + url_str + " with " + replacement );
+										
+										result.append( replacement );
+										
+										appended = true;
+										
+									}else{
+										
+										trace( "    No child for " + url_str );
+									}
+								}
+							}catch( Throwable e ){
+								
+							}
+							
+							if ( result != null && !appended ){
+								
+								result.append( str.subSequence( str_pos, url_end ));
+							}
+							
+							str_pos = url_end;
+							
+						}else{
+							
+							break;
+						}
+					}else{
+						
+						if ( result != null ){
+							
+							result.append( str.subSequence( str_pos, match_pos ));
+						}
+						
+						str_pos = match_pos;
+					}
+				}
+				
+				if ( result != null ){
+							
+					if ( str_pos < str.length() ){
+						
+						result.append( str.subSequence( str_pos, str.length()));
+					}
+
+					sb = result;
+				}
+				
+				source_os.write( ( "Content-Length: " + sb.length() + NL ).getBytes());
+				
+				source_os.write( NL.getBytes());
+				
+				source_os.write( sb.toString().getBytes( content_charset ));
+				
+			}else{
+				
+				source_os.write( NL.getBytes());
+							
+				while( !destroyed  ){
+									
+					int	len = target_is.read( buffer );
+					
+					if ( len <= 0 ){
+						
+						break;
+					}
+					
+					source_os.write( buffer, 0, len );
+				}
+			}
+		}
+		
+		private String
+		readHeader(
+			InputStream		is )
+		
+			throws IOException
+		{
+			String	header = "";
+			
+			byte[]	buffer = new byte[1];
+			
+			boolean	found = false;
+			
+			while( true ){
+			
+				if ( is.read( buffer ) != 1 ){
+					
+					break;
+				}
+				
+				header += (char)buffer[0];
+				
+				if ( header.endsWith( NL + NL )){
+					
+					found = true;
+					
+					break;
+				}
+			}
+			
+			if ( !found ){
+				
+				throw( new IOException( "End of stream reading header" ));
+			}
+			
+			return( header );
+		}
+		
+		private String[]
+		splitHeader(
+			String		str )
+		{
+			String[] bits = str.split( NL );
+			
+			return( bits );
+		}
+			
+		private void
+		destroy()
+		{
+			synchronized( this ){
+				
+				if ( destroyed ){
+					
+					return;
+				}
+				
+				destroyed = true;
+			}
+			
+			if ( socket_out != null ){
+				
+				try{
+					socket_out.close();
+					
+				}catch( Throwable e ){
+					
+				}
+			}
+			try{
+				socket_in.close();
+				
+			}catch( Throwable e ){
+			}
+		}
+	}
+	
+	private void
+	trace(
+		String		str )
+	{
+		if ( TRACE ){
+			
+			System.out.println( str );
+		}
+	}
+	
+	public static void
+	main(
+		String[]		args )
+	{
+		try{
+			HTTPAuthHelper proxy = new HTTPAuthHelper( new URL( "https://client.vuze.com/" ));
+			
+			proxy.start();
+			
+			System.out.println( "port=" + proxy.getPort());
+			
+			while( true ){
+				
+				Thread.sleep(1000);
+			}
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/util/http/HTTPAuthHelperListener.java b/azureus2/src/com/aelitis/azureus/core/util/http/HTTPAuthHelperListener.java
index ebd2233..bbe8743 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/http/HTTPAuthHelperListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/http/HTTPAuthHelperListener.java
@@ -1,32 +1,31 @@
-/*
- * Created on Oct 9, 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.core.util.http;
-
-public interface 
-HTTPAuthHelperListener 
-{
-	public void
-	cookieFound(
-		HTTPAuthHelper		helper,
-		String				cookie_name,
-		String				cookie_value );
-}
+/*
+ * Created on Oct 9, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.util.http;
+
+public interface 
+HTTPAuthHelperListener 
+{
+	public void
+	cookieFound(
+		HTTPAuthHelper		helper,
+		String				cookie_name,
+		String				cookie_value );
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/util/png/CRCedChunk.java b/azureus2/src/com/aelitis/azureus/core/util/png/CRCedChunk.java
index c5af3d3..d903f72 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/png/CRCedChunk.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/png/CRCedChunk.java
@@ -2,20 +2,19 @@
  * Created on Feb 5, 2008
  * Created by Olivier Chalouhi
  * 
- * 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 package com.aelitis.azureus.core.util.png;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/png/Chunk.java b/azureus2/src/com/aelitis/azureus/core/util/png/Chunk.java
index 8c0a81f..93496ad 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/png/Chunk.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/png/Chunk.java
@@ -2,20 +2,19 @@
  * Created on Feb 5, 2008
  * Created by Olivier Chalouhi
  * 
- * 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 package com.aelitis.azureus.core.util.png;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/png/IDATChunk.java b/azureus2/src/com/aelitis/azureus/core/util/png/IDATChunk.java
index 655cd8d..3fdd3e4 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/png/IDATChunk.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/png/IDATChunk.java
@@ -2,20 +2,19 @@
  * Created on Feb 5, 2008
  * Created by Olivier Chalouhi
  * 
- * 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 package com.aelitis.azureus.core.util.png;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/png/IENDChunk.java b/azureus2/src/com/aelitis/azureus/core/util/png/IENDChunk.java
index b9ff0fb..a6fb46c 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/png/IENDChunk.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/png/IENDChunk.java
@@ -2,20 +2,19 @@
  * Created on Feb 5, 2008
  * Created by Olivier Chalouhi
  * 
- * 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 package com.aelitis.azureus.core.util.png;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/png/IHDRChunk.java b/azureus2/src/com/aelitis/azureus/core/util/png/IHDRChunk.java
index 1c43831..0a0f759 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/png/IHDRChunk.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/png/IHDRChunk.java
@@ -2,20 +2,19 @@
  * Created on Feb 5, 2008
  * Created by Olivier Chalouhi
  * 
- * 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 package com.aelitis.azureus.core.util.png;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/png/PNG.java b/azureus2/src/com/aelitis/azureus/core/util/png/PNG.java
index 4c6bd85..499b159 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/png/PNG.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/png/PNG.java
@@ -2,20 +2,19 @@
  * Created on Feb 5, 2008
  * Created by Olivier Chalouhi
  * 
- * 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 package com.aelitis.azureus.core.util.png;
diff --git a/azureus2/src/com/aelitis/azureus/core/util/png/PngSignatureChunk.java b/azureus2/src/com/aelitis/azureus/core/util/png/PngSignatureChunk.java
index 7ca3b2a..f7dc856 100644
--- a/azureus2/src/com/aelitis/azureus/core/util/png/PngSignatureChunk.java
+++ b/azureus2/src/com/aelitis/azureus/core/util/png/PngSignatureChunk.java
@@ -2,20 +2,19 @@
  * Created on Feb 5, 2008
  * Created by Olivier Chalouhi
  * 
- * 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 package com.aelitis.azureus.core.util.png;
diff --git a/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClient.java b/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClient.java
index b317fb4..2e5ac80 100644
--- a/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClient.java
+++ b/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClient.java
@@ -1,7 +1,7 @@
 /*
  * Created on Dec 20, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -70,6 +67,7 @@ public class VersionCheckClient {
 	public static final String	REASON_UPDATE_CHECK_START		= "us";
 	public static final String	REASON_UPDATE_CHECK_PERIODIC	= "up";
 	public static final String	REASON_CHECK_SWT				= "sw";
+	public static final String	REASON_DHT_FLAGS				= "df";
 	public static final String	REASON_DHT_EXTENDED_ALLOWED		= "dx";
 	public static final String	REASON_DHT_ENABLE_ALLOWED		= "de";
 	public static final String	REASON_EXTERNAL_IP				= "ip";
@@ -689,6 +687,24 @@ public class VersionCheckClient {
 		return res;
 	}
 
+	public byte 
+	getDHTFlags() 
+	{
+		Map map = getMostRecentVersionCheckData();
+
+		if ( map != null ){
+			
+			byte[] b_flags = (byte[])map.get( "dht_flags" );
+			
+			if ( b_flags != null ){
+				
+				return( new Integer(new String( b_flags )).byteValue());
+			}
+		}
+		
+		return( (byte)0xff );
+	}
+	
 	public String[]
 	getRecommendedPlugins()
 	{
@@ -1429,7 +1445,8 @@ public class VersionCheckClient {
 		message.put( "appid",   SystemProperties.getApplicationIdentifier());
 		message.put( "appname", SystemProperties.getApplicationName());
 		message.put( "version", Constants.AZUREUS_VERSION );
-
+		message.put( "first_version", COConfigurationManager.getStringParameter( "First Recorded Version", "" ));
+		
 		String	sub_ver = Constants.AZUREUS_SUBVER;
 
 		if ( sub_ver.length() > 0 ){
@@ -1450,6 +1467,8 @@ public class VersionCheckClient {
 		boolean using_phe = COConfigurationManager.getBooleanParameter( "network.transport.encrypted.require" );
 		message.put( "using_phe", using_phe ? new Long(1) : new Long(0) );
 
+		message.put( "imode", COConfigurationManager.getStringParameter( "installer.mode", "" ));
+		
 		//swt stuff
 		try {
 			Class c = Class.forName( "org.eclipse.swt.SWT" );
diff --git a/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientListener.java b/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientListener.java
index 317ca35..1c15706 100644
--- a/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientListener.java
+++ b/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on May 18, 2010
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPCodecs.java b/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPCodecs.java
index 1d185f7..a0dff63 100644
--- a/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPCodecs.java
+++ b/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPCodecs.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPReply.java b/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPReply.java
index 4d1df92..17d437a 100644
--- a/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPReply.java
+++ b/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPReply.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPRequest.java b/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPRequest.java
index b401103..d33b034 100644
--- a/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPRequest.java
+++ b/azureus2/src/com/aelitis/azureus/core/versioncheck/VersionCheckClientUDPRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFile.java b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFile.java
index f61f1b3..eb19752 100644
--- a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFile.java
+++ b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFile.java
@@ -1,62 +1,61 @@
-/*
- * Created on May 16, 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.core.vuzefile;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Map;
-
-public interface 
-VuzeFile 
-{
-	public String
-	getName();
-	
-	public VuzeFileComponent[]
-	getComponents();
-	
-	public VuzeFileComponent
-	addComponent(
-		int		type,
-		Map		content );
-	
-	public byte[]
-	exportToBytes()
-	
-		throws IOException;
-	
-	public Map
-	exportToMap()
-	
-		throws IOException;
-	
-	public String
-	exportToJSON()
-	
-		throws IOException;
-	
-	public void
-	write(
-		File	target )
-	
-		throws IOException;
-}
+/*
+ * Created on May 16, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.vuzefile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+public interface 
+VuzeFile 
+{
+	public String
+	getName();
+	
+	public VuzeFileComponent[]
+	getComponents();
+	
+	public VuzeFileComponent
+	addComponent(
+		int		type,
+		Map		content );
+	
+	public byte[]
+	exportToBytes()
+	
+		throws IOException;
+	
+	public Map
+	exportToMap()
+	
+		throws IOException;
+	
+	public String
+	exportToJSON()
+	
+		throws IOException;
+	
+	public void
+	write(
+		File	target )
+	
+		throws IOException;
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileComponent.java b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileComponent.java
index 29a3822..abebdcf 100644
--- a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileComponent.java
+++ b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileComponent.java
@@ -1,66 +1,65 @@
-/*
- * Created on May 19, 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.core.vuzefile;
-
-import java.util.*;
-
-public interface 
-VuzeFileComponent 
-{
-	public static final int COMP_TYPE_NONE						= 0x00000000;
-	public static final int COMP_TYPE_METASEARCH_TEMPLATE		= 0x00000001;
-	public static final int COMP_TYPE_V3_NAVIGATION				= 0x00000002;
-	public static final int COMP_TYPE_V3_CONDITION_CHECK		= 0x00000004;
-	public static final int COMP_TYPE_PLUGIN					= 0x00000008;
-	public static final int COMP_TYPE_SUBSCRIPTION				= 0x00000010;
-	public static final int COMP_TYPE_SUBSCRIPTION_SINGLETON	= 0x00000020;
-	public static final int COMP_TYPE_CUSTOMIZATION				= 0x00000040;
-	public static final int COMP_TYPE_CONTENT_NETWORK			= 0x00000080;
-	public static final int COMP_TYPE_METASEARCH_OPERATION		= 0x00000100;
-	public static final int COMP_TYPE_DEVICE					= 0x00000200;
-	public static final int COMP_TYPE_CONFIG_SETTINGS			= 0x00000400;
-	public static final int COMP_TYPE_ADD_TORRENT				= 0x00000800;
-
-	public int
-	getType();
-	
-	public String
-	getTypeName();
-	
-	public Map
-	getContent();
-	
-	public void
-	setProcessed();
-	
-	public boolean
-	isProcessed();
-	
-	public void
-	setData(
-		Object	key,
-		Object	value );
-	
-	public Object
-	getData(
-		Object	key );
-}
+/*
+ * Created on May 19, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.vuzefile;
+
+import java.util.*;
+
+public interface 
+VuzeFileComponent 
+{
+	public static final int COMP_TYPE_NONE						= 0x00000000;
+	public static final int COMP_TYPE_METASEARCH_TEMPLATE		= 0x00000001;
+	public static final int COMP_TYPE_V3_NAVIGATION				= 0x00000002;
+	public static final int COMP_TYPE_V3_CONDITION_CHECK		= 0x00000004;
+	public static final int COMP_TYPE_PLUGIN					= 0x00000008;
+	public static final int COMP_TYPE_SUBSCRIPTION				= 0x00000010;
+	public static final int COMP_TYPE_SUBSCRIPTION_SINGLETON	= 0x00000020;
+	public static final int COMP_TYPE_CUSTOMIZATION				= 0x00000040;
+	public static final int COMP_TYPE_CONTENT_NETWORK			= 0x00000080;
+	public static final int COMP_TYPE_METASEARCH_OPERATION		= 0x00000100;
+	public static final int COMP_TYPE_DEVICE					= 0x00000200;
+	public static final int COMP_TYPE_CONFIG_SETTINGS			= 0x00000400;
+	public static final int COMP_TYPE_ADD_TORRENT				= 0x00000800;
+
+	public int
+	getType();
+	
+	public String
+	getTypeName();
+	
+	public Map
+	getContent();
+	
+	public void
+	setProcessed();
+	
+	public boolean
+	isProcessed();
+	
+	public void
+	setData(
+		Object	key,
+		Object	value );
+	
+	public Object
+	getData(
+		Object	key );
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileHandler.java b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileHandler.java
index d374dd3..6b3fb3c 100644
--- a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileHandler.java
+++ b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileHandler.java
@@ -1,270 +1,269 @@
-/*
- * Created on May 16, 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.core.vuzefile;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URL;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.BDecoder;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.FileUtil;
-import org.gudy.azureus2.plugins.utils.StaticUtilities;
-import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
-
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-
-public class 
-VuzeFileHandler 
-{
-	private static VuzeFileHandler singleton = new VuzeFileHandler();
-	
-	public static VuzeFileHandler
-	getSingleton()
-	{
-		return( singleton );
-	}
-	
-	private CopyOnWriteList<VuzeFileProcessor>	processors = new CopyOnWriteList<VuzeFileProcessor>();
-	
-	
-	protected
-	VuzeFileHandler()
-	{
-	}
-	
-	public VuzeFile
-	loadVuzeFile(
-		String	target  )
-	{
-		try{
-			File test_file = new File( target );
-	
-			if ( test_file.isFile()){
-					
-				return( getVuzeFile( new FileInputStream( test_file )));
-				
-			}else{
-				
-				URL	url = new URI( target ).toURL();
-				
-				String	protocol = url.getProtocol().toLowerCase();
-				
-				if ( protocol.equals( "http" ) || protocol.equals( "https" )){
-					
-					ResourceDownloader rd = StaticUtilities.getResourceDownloaderFactory().create( url );
-				
-					return( getVuzeFile(rd.download()));
-				}
-			}
-		}catch( Throwable e ){
-		}
-		
-		return( null );
-	}
-	
-	public VuzeFile
-	loadVuzeFile(
-		byte[]		bytes )
-	{
-		return( loadVuzeFile( new ByteArrayInputStream( bytes )));
-	}
-	
-	public VuzeFile
-	loadVuzeFile(
-		InputStream 	is )
-	{
-		return( getVuzeFile( is ));
-	}
-	
-	public VuzeFile
-	loadVuzeFile(
-		File 	file )
-	{
-		InputStream is = null;
-		
-		try{
-			is = new FileInputStream( file );
-			
-			return( getVuzeFile( is ));
-			
-		}catch( Throwable e ){
-			
-			return( null );
-			
-		}finally{
-	
-			if ( is != null ){
-				
-				try{
-					is.close();
-					
-				}catch( Throwable e ){	
-				}
-			}
-		}
-	}
-	
-	protected VuzeFile
-	getVuzeFile(
-		InputStream		is )
-	{
-		try{
-			BufferedInputStream bis = new BufferedInputStream( is );
-			
-			try{
-				bis.mark(100);
-				
-				boolean is_json = false;
-				
-				while( true ){
-				
-					int next = bis.read();
-				
-					if ( next == -1 ){
-						
-						break;
-					}
-					
-					char c = (char)next;
-					
-					if ( !Character.isWhitespace(c)){
-						
-						is_json = c == '{';
-						
-						break;
-					}
-				}
-				
-				bis.reset();
-				
-				Map map;
-				
-				if ( is_json ){
-					
-					byte[] bytes = FileUtil.readInputStreamAsByteArray( bis, 2*1024*1024 );
-										
-					map = BDecoder.decodeFromJSON( new String( bytes, "UTF-8" ));
-					
-				}else{
-
-					map = BDecoder.decode(bis);
-				}
-				
-				return( loadVuzeFile( map ));
-				
-			}finally{
-				
-				is.close();
-			}
-		}catch( Throwable e ){
-		}
-		
-		return( null );
-	}
-	
-	public VuzeFile
-	loadVuzeFile(
-		Map	map )
-	{
-		if ( map.containsKey( "vuze" ) && !map.containsKey( "info" )){
-					
-			return( new VuzeFileImpl( this, (Map)map.get( "vuze" )));
-		}
-		
-		return( null );
-	}
-	
-	public VuzeFile
-	loadAndHandleVuzeFile(
-		String		target,
-		int			expected_types )
-	{
-		VuzeFile vf = loadVuzeFile( target );
-		
-		if ( vf == null ){
-			
-			return( null );
-		}
-		
-		handleFiles( new VuzeFile[]{ vf }, expected_types );
-		
-		return( vf );
-	}
-	
-	public void
-	handleFiles(
-		VuzeFile[]		files,
-		int				expected_types )
-	{
-		Iterator<VuzeFileProcessor> it = processors.iterator();
-		
-		while( it.hasNext()){
-			
-			VuzeFileProcessor	proc = it.next();
-			
-			try{
-				proc.process( files, expected_types );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-		
-		for (int i=0;i<files.length;i++){
-			
-			VuzeFile vf = files[i];
-			
-			VuzeFileComponent[] comps = vf.getComponents();
-			
-			for (int j=0;j<comps.length;j++){
-				
-				VuzeFileComponent comp = comps[j];
-				
-				if ( !comp.isProcessed()){
-				
-					Debug.out( "Failed to handle Vuze file component " + comp.getContent());
-				}
-			}
-		}
-	}
-	
-	public VuzeFile
-	create()
-	{
-		return( new VuzeFileImpl( this ));
-	}
-			
-	public void
-	addProcessor(
-		VuzeFileProcessor		proc )
-	{
-		processors.add( proc );
-	}
-}
+/*
+ * Created on May 16, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.vuzefile;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.BDecoder;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.plugins.utils.StaticUtilities;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
+
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
+
+public class 
+VuzeFileHandler 
+{
+	private static VuzeFileHandler singleton = new VuzeFileHandler();
+	
+	public static VuzeFileHandler
+	getSingleton()
+	{
+		return( singleton );
+	}
+	
+	private CopyOnWriteList<VuzeFileProcessor>	processors = new CopyOnWriteList<VuzeFileProcessor>();
+	
+	
+	protected
+	VuzeFileHandler()
+	{
+	}
+	
+	public VuzeFile
+	loadVuzeFile(
+		String	target  )
+	{
+		try{
+			File test_file = new File( target );
+	
+			if ( test_file.isFile()){
+					
+				return( getVuzeFile( new FileInputStream( test_file )));
+				
+			}else{
+				
+				URL	url = new URI( target ).toURL();
+				
+				String	protocol = url.getProtocol().toLowerCase();
+				
+				if ( protocol.equals( "http" ) || protocol.equals( "https" )){
+					
+					ResourceDownloader rd = StaticUtilities.getResourceDownloaderFactory().create( url );
+				
+					return( getVuzeFile(rd.download()));
+				}
+			}
+		}catch( Throwable e ){
+		}
+		
+		return( null );
+	}
+	
+	public VuzeFile
+	loadVuzeFile(
+		byte[]		bytes )
+	{
+		return( loadVuzeFile( new ByteArrayInputStream( bytes )));
+	}
+	
+	public VuzeFile
+	loadVuzeFile(
+		InputStream 	is )
+	{
+		return( getVuzeFile( is ));
+	}
+	
+	public VuzeFile
+	loadVuzeFile(
+		File 	file )
+	{
+		InputStream is = null;
+		
+		try{
+			is = new FileInputStream( file );
+			
+			return( getVuzeFile( is ));
+			
+		}catch( Throwable e ){
+			
+			return( null );
+			
+		}finally{
+	
+			if ( is != null ){
+				
+				try{
+					is.close();
+					
+				}catch( Throwable e ){	
+				}
+			}
+		}
+	}
+	
+	protected VuzeFile
+	getVuzeFile(
+		InputStream		is )
+	{
+		try{
+			BufferedInputStream bis = new BufferedInputStream( is );
+			
+			try{
+				bis.mark(100);
+				
+				boolean is_json = false;
+				
+				while( true ){
+				
+					int next = bis.read();
+				
+					if ( next == -1 ){
+						
+						break;
+					}
+					
+					char c = (char)next;
+					
+					if ( !Character.isWhitespace(c)){
+						
+						is_json = c == '{';
+						
+						break;
+					}
+				}
+				
+				bis.reset();
+				
+				Map map;
+				
+				if ( is_json ){
+					
+					byte[] bytes = FileUtil.readInputStreamAsByteArray( bis, 2*1024*1024 );
+										
+					map = BDecoder.decodeFromJSON( new String( bytes, "UTF-8" ));
+					
+				}else{
+
+					map = BDecoder.decode(bis);
+				}
+				
+				return( loadVuzeFile( map ));
+				
+			}finally{
+				
+				is.close();
+			}
+		}catch( Throwable e ){
+		}
+		
+		return( null );
+	}
+	
+	public VuzeFile
+	loadVuzeFile(
+		Map	map )
+	{
+		if ( map.containsKey( "vuze" ) && !map.containsKey( "info" )){
+					
+			return( new VuzeFileImpl( this, (Map)map.get( "vuze" )));
+		}
+		
+		return( null );
+	}
+	
+	public VuzeFile
+	loadAndHandleVuzeFile(
+		String		target,
+		int			expected_types )
+	{
+		VuzeFile vf = loadVuzeFile( target );
+		
+		if ( vf == null ){
+			
+			return( null );
+		}
+		
+		handleFiles( new VuzeFile[]{ vf }, expected_types );
+		
+		return( vf );
+	}
+	
+	public void
+	handleFiles(
+		VuzeFile[]		files,
+		int				expected_types )
+	{
+		Iterator<VuzeFileProcessor> it = processors.iterator();
+		
+		while( it.hasNext()){
+			
+			VuzeFileProcessor	proc = it.next();
+			
+			try{
+				proc.process( files, expected_types );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+		
+		for (int i=0;i<files.length;i++){
+			
+			VuzeFile vf = files[i];
+			
+			VuzeFileComponent[] comps = vf.getComponents();
+			
+			for (int j=0;j<comps.length;j++){
+				
+				VuzeFileComponent comp = comps[j];
+				
+				if ( !comp.isProcessed()){
+				
+					Debug.out( "Failed to handle Vuze file component " + comp.getContent());
+				}
+			}
+		}
+	}
+	
+	public VuzeFile
+	create()
+	{
+		return( new VuzeFileImpl( this ));
+	}
+			
+	public void
+	addProcessor(
+		VuzeFileProcessor		proc )
+	{
+		processors.add( proc );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileImpl.java b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileImpl.java
index 2e988b4..28c2644 100644
--- a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileImpl.java
+++ b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileImpl.java
@@ -1,271 +1,270 @@
-/*
- * Created on May 18, 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.core.vuzefile;
-
-import java.io.*;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.BEncoder;
-
-public class 
-VuzeFileImpl
-	implements VuzeFile
-{
-	private VuzeFileHandler			handler;
-	private VuzeFileComponent[]		components;
-	
-	protected
-	VuzeFileImpl(
-		VuzeFileHandler		_handler )
-	{
-		handler = _handler;
-		
-		components = new VuzeFileComponent[0];
-	}
-	
-	protected
-	VuzeFileImpl(
-		VuzeFileHandler		_handler,
-		Map					map )
-	{
-		handler = _handler;
-		
-		List	l_comps = (List)map.get( "components" );
-		
-		components = new VuzeFileComponent[l_comps.size()];
-		
-		for (int i=0;i<l_comps.size();i++){
-			
-			Map	comp = (Map)l_comps.get(i);
-			
-			int	type 	= ((Long)comp.get( "type" )).intValue();
-			Map	content	= (Map)comp.get( "content" );
-			
-			components[i] = new comp( type, content );
-		}
-	}
-	
-	public String
-	getName()
-	{
-		String str = "";
-		
-		for ( VuzeFileComponent comp: components ){
-			
-			str += (str.length()==0?"":",") + comp.getTypeName();
-		}
-		
-		return( str );
-	}
-	
-	public VuzeFileComponent[] 
-	getComponents()
-	{
-		return( components ); 
-	}
-	
-	public VuzeFileComponent
-	addComponent(
-		int		type,
-		Map		content )
-	{
-		VuzeFileComponent comp = new comp( type, content );
-		
-		int	old_len = components.length;
-		
-		VuzeFileComponent[] res = new VuzeFileComponent[old_len+1];
-		
-		System.arraycopy( components, 0, res, 0, old_len );
-		
-		res[ old_len ] = comp;
-		
-		components = res;
-		
-		return( comp );
-	}
-	
-	public Map
-	exportToMap()
-	
-		throws IOException
-	{
-		Map	map = new HashMap();
-		
-		Map vuze_map = new HashMap();
-		
-		map.put( "vuze", vuze_map );
-		
-		List	list = new ArrayList();
-		
-		vuze_map.put( "components", list );
-		
-		for (int i=0;i<components.length;i++){
-			
-			VuzeFileComponent comp = components[i];
-			
-			Map	entry = new HashMap();
-			
-			entry.put( "type", new Long( comp.getType()));
-			
-			entry.put( "content", comp.getContent());
-			
-			list.add( entry );
-		}
-				
-		return( map );
-	}
-	
-	public byte[] 
-	exportToBytes() 
-	
-		throws IOException 
-	{
-		return( BEncoder.encode( exportToMap()));
-	}
-	
-	public String
-	exportToJSON()
-	
-		throws IOException
-	{
-		return( BEncoder.encodeToJSON( exportToMap()));
-	}
-	
-	public void 
-	write(
-		File target )
-	
-		throws IOException 
-	{
-		FileOutputStream	fos = new FileOutputStream( target );
-		
-		try{
-			fos.write( exportToBytes());
-			
-		}finally{
-			
-			fos.close();
-		}
-	}
-	
-	protected class
-	comp
-		implements VuzeFileComponent
-	{
-		private int			type;
-		private Map			contents;
-		private boolean		processed;
-		
-		private Map			user_data;
-		
-		protected
-		comp(
-			int		_type,
-			Map		_contents )
-		{
-			type		= _type;
-			contents	= _contents;
-		}
-		
-		public int
-		getType()
-		{
-			return( type );
-		}
-		
-		public String 
-		getTypeName() 
-		{
-			switch( type ){
-				case COMP_TYPE_NONE: 
-					return( "None" );
-				case COMP_TYPE_METASEARCH_TEMPLATE: 
-					return( "Search Template" );
-				case COMP_TYPE_V3_NAVIGATION: 
-					return( "Navigation" );
-				case COMP_TYPE_V3_CONDITION_CHECK: 
-					return( "Condition Check" );
-				case COMP_TYPE_PLUGIN: 
-					return( "Plugin" );
-				case COMP_TYPE_SUBSCRIPTION: 
-					return( "Subscription" );
-				case COMP_TYPE_SUBSCRIPTION_SINGLETON: 
-					return( "Subscription" );
-				case COMP_TYPE_CUSTOMIZATION: 
-					return( "Customization" );
-				case COMP_TYPE_CONTENT_NETWORK: 
-					return( "Content Network" );
-				case COMP_TYPE_METASEARCH_OPERATION: 
-					return( "Search Operation" );
-				case COMP_TYPE_DEVICE: 
-					return( "Device" );
-				case COMP_TYPE_CONFIG_SETTINGS: 
-					return( "Config Settings" );
-				default: 
-					return( "Unknown" );
-			}
-		}
-		
-		public Map
-		getContent()
-		{
-			return( contents );
-		}
-		
-		public void
-		setProcessed()
-		{
-			processed	= true;
-		}
-		
-		public boolean
-		isProcessed()
-		{
-			return( processed );
-		}
-		
-		public synchronized void
-		setData(
-			Object	key,
-			Object	value )
-		{
-			if ( user_data == null ){
-				
-				user_data = new HashMap();
-			}
-			
-			user_data.put( key, value );
-		}
-		
-		public synchronized Object
-		getData(
-			Object	key )
-		{
-			if ( user_data == null ){
-				
-				return( null );
-			}
-			
-			return( user_data.get( key ));
-		}
-	}
-}
+/*
+ * Created on May 18, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.vuzefile;
+
+import java.io.*;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.BEncoder;
+
+public class 
+VuzeFileImpl
+	implements VuzeFile
+{
+	private VuzeFileHandler			handler;
+	private VuzeFileComponent[]		components;
+	
+	protected
+	VuzeFileImpl(
+		VuzeFileHandler		_handler )
+	{
+		handler = _handler;
+		
+		components = new VuzeFileComponent[0];
+	}
+	
+	protected
+	VuzeFileImpl(
+		VuzeFileHandler		_handler,
+		Map					map )
+	{
+		handler = _handler;
+		
+		List	l_comps = (List)map.get( "components" );
+		
+		components = new VuzeFileComponent[l_comps.size()];
+		
+		for (int i=0;i<l_comps.size();i++){
+			
+			Map	comp = (Map)l_comps.get(i);
+			
+			int	type 	= ((Long)comp.get( "type" )).intValue();
+			Map	content	= (Map)comp.get( "content" );
+			
+			components[i] = new comp( type, content );
+		}
+	}
+	
+	public String
+	getName()
+	{
+		String str = "";
+		
+		for ( VuzeFileComponent comp: components ){
+			
+			str += (str.length()==0?"":",") + comp.getTypeName();
+		}
+		
+		return( str );
+	}
+	
+	public VuzeFileComponent[] 
+	getComponents()
+	{
+		return( components ); 
+	}
+	
+	public VuzeFileComponent
+	addComponent(
+		int		type,
+		Map		content )
+	{
+		VuzeFileComponent comp = new comp( type, content );
+		
+		int	old_len = components.length;
+		
+		VuzeFileComponent[] res = new VuzeFileComponent[old_len+1];
+		
+		System.arraycopy( components, 0, res, 0, old_len );
+		
+		res[ old_len ] = comp;
+		
+		components = res;
+		
+		return( comp );
+	}
+	
+	public Map
+	exportToMap()
+	
+		throws IOException
+	{
+		Map	map = new HashMap();
+		
+		Map vuze_map = new HashMap();
+		
+		map.put( "vuze", vuze_map );
+		
+		List	list = new ArrayList();
+		
+		vuze_map.put( "components", list );
+		
+		for (int i=0;i<components.length;i++){
+			
+			VuzeFileComponent comp = components[i];
+			
+			Map	entry = new HashMap();
+			
+			entry.put( "type", new Long( comp.getType()));
+			
+			entry.put( "content", comp.getContent());
+			
+			list.add( entry );
+		}
+				
+		return( map );
+	}
+	
+	public byte[] 
+	exportToBytes() 
+	
+		throws IOException 
+	{
+		return( BEncoder.encode( exportToMap()));
+	}
+	
+	public String
+	exportToJSON()
+	
+		throws IOException
+	{
+		return( BEncoder.encodeToJSON( exportToMap()));
+	}
+	
+	public void 
+	write(
+		File target )
+	
+		throws IOException 
+	{
+		FileOutputStream	fos = new FileOutputStream( target );
+		
+		try{
+			fos.write( exportToBytes());
+			
+		}finally{
+			
+			fos.close();
+		}
+	}
+	
+	protected class
+	comp
+		implements VuzeFileComponent
+	{
+		private int			type;
+		private Map			contents;
+		private boolean		processed;
+		
+		private Map			user_data;
+		
+		protected
+		comp(
+			int		_type,
+			Map		_contents )
+		{
+			type		= _type;
+			contents	= _contents;
+		}
+		
+		public int
+		getType()
+		{
+			return( type );
+		}
+		
+		public String 
+		getTypeName() 
+		{
+			switch( type ){
+				case COMP_TYPE_NONE: 
+					return( "None" );
+				case COMP_TYPE_METASEARCH_TEMPLATE: 
+					return( "Search Template" );
+				case COMP_TYPE_V3_NAVIGATION: 
+					return( "Navigation" );
+				case COMP_TYPE_V3_CONDITION_CHECK: 
+					return( "Condition Check" );
+				case COMP_TYPE_PLUGIN: 
+					return( "Plugin" );
+				case COMP_TYPE_SUBSCRIPTION: 
+					return( "Subscription" );
+				case COMP_TYPE_SUBSCRIPTION_SINGLETON: 
+					return( "Subscription" );
+				case COMP_TYPE_CUSTOMIZATION: 
+					return( "Customization" );
+				case COMP_TYPE_CONTENT_NETWORK: 
+					return( "Content Network" );
+				case COMP_TYPE_METASEARCH_OPERATION: 
+					return( "Search Operation" );
+				case COMP_TYPE_DEVICE: 
+					return( "Device" );
+				case COMP_TYPE_CONFIG_SETTINGS: 
+					return( "Config Settings" );
+				default: 
+					return( "Unknown" );
+			}
+		}
+		
+		public Map
+		getContent()
+		{
+			return( contents );
+		}
+		
+		public void
+		setProcessed()
+		{
+			processed	= true;
+		}
+		
+		public boolean
+		isProcessed()
+		{
+			return( processed );
+		}
+		
+		public synchronized void
+		setData(
+			Object	key,
+			Object	value )
+		{
+			if ( user_data == null ){
+				
+				user_data = new HashMap();
+			}
+			
+			user_data.put( key, value );
+		}
+		
+		public synchronized Object
+		getData(
+			Object	key )
+		{
+			if ( user_data == null ){
+				
+				return( null );
+			}
+			
+			return( user_data.get( key ));
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileMerger.java b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileMerger.java
index ab3960c..8122589 100644
--- a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileMerger.java
+++ b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileMerger.java
@@ -1,111 +1,110 @@
-/*
- * Created on Nov 12, 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.core.vuzefile;
-
-import java.io.*;
-
-public class 
-VuzeFileMerger 
-{
-	protected
-	VuzeFileMerger(
-		String[]		args )
-	{
-		if ( args.length != 1 ){
-			
-			usage();
-		}
-		
-		File	input_dir = new File( args[0] );
-		
-		if ( !input_dir.isDirectory()){
-			
-			usage();
-		}
-		
-		try{
-			File	output_file = new File( args[0] + ".vuze" );
-			
-			File[]	files = input_dir.listFiles();
-			
-			VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
-			
-			VuzeFile target = vfh.create();
-			
-			for ( int i=0;i<files.length;i++){
-				
-				File f = files[i];
-				
-				if ( f.isDirectory()){
-					
-					continue;
-				}
-				
-				if ( !f.getName().endsWith( ".vuze" )){
-					
-					continue;
-				}
-				
-				VuzeFile vf = vfh.loadVuzeFile( f.getAbsolutePath());
-				
-				System.out.println( "Read " + f );
-				
-				VuzeFileComponent[] comps = vf.getComponents();
-				
-				for (int j=0;j<comps.length;j++){
-					
-					VuzeFileComponent comp = comps[j];
-					
-					target.addComponent( comp.getType(), comp.getContent());
-					
-					System.out.println( "    added component: " + comp.getType());
-				}
-			}
-			
-			target.write( output_file );
-			
-			System.out.println( "Wrote " + output_file );
-			
-		}catch( Throwable e ){
-			
-			System.err.print( "Failed to merge vuze files" );
-			
-			e.printStackTrace();
-		}
-	}
-	
-	protected void
-	usage()
-	{
-		System.err.println( "Usage: <dir_of_vuze_files_to_merge>" );
-		
-		System.exit(1);
-	}
-	
-	public static void
-	main(
-		String[]		args )
-	{
-		new VuzeFileMerger( args );
-
-	}
-}
+/*
+ * Created on Nov 12, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.vuzefile;
+
+import java.io.*;
+
+public class 
+VuzeFileMerger 
+{
+	protected
+	VuzeFileMerger(
+		String[]		args )
+	{
+		if ( args.length != 1 ){
+			
+			usage();
+		}
+		
+		File	input_dir = new File( args[0] );
+		
+		if ( !input_dir.isDirectory()){
+			
+			usage();
+		}
+		
+		try{
+			File	output_file = new File( args[0] + ".vuze" );
+			
+			File[]	files = input_dir.listFiles();
+			
+			VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
+			
+			VuzeFile target = vfh.create();
+			
+			for ( int i=0;i<files.length;i++){
+				
+				File f = files[i];
+				
+				if ( f.isDirectory()){
+					
+					continue;
+				}
+				
+				if ( !f.getName().endsWith( ".vuze" )){
+					
+					continue;
+				}
+				
+				VuzeFile vf = vfh.loadVuzeFile( f.getAbsolutePath());
+				
+				System.out.println( "Read " + f );
+				
+				VuzeFileComponent[] comps = vf.getComponents();
+				
+				for (int j=0;j<comps.length;j++){
+					
+					VuzeFileComponent comp = comps[j];
+					
+					target.addComponent( comp.getType(), comp.getContent());
+					
+					System.out.println( "    added component: " + comp.getType());
+				}
+			}
+			
+			target.write( output_file );
+			
+			System.out.println( "Wrote " + output_file );
+			
+		}catch( Throwable e ){
+			
+			System.err.print( "Failed to merge vuze files" );
+			
+			e.printStackTrace();
+		}
+	}
+	
+	protected void
+	usage()
+	{
+		System.err.println( "Usage: <dir_of_vuze_files_to_merge>" );
+		
+		System.exit(1);
+	}
+	
+	public static void
+	main(
+		String[]		args )
+	{
+		new VuzeFileMerger( args );
+
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileProcessor.java b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileProcessor.java
index 1396994..4129a6d 100644
--- a/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileProcessor.java
+++ b/azureus2/src/com/aelitis/azureus/core/vuzefile/VuzeFileProcessor.java
@@ -1,31 +1,30 @@
-/*
- * Created on May 19, 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.core.vuzefile;
-
-public interface 
-VuzeFileProcessor 
-{
-	public void
-	process(
-		VuzeFile[]		files,
-		int				expected_types );
-}
+/*
+ * Created on May 19, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.vuzefile;
+
+public interface 
+VuzeFileProcessor 
+{
+	public void
+	process(
+		VuzeFile[]		files,
+		int				expected_types );
+}
diff --git a/azureus2/src/com/aelitis/azureus/launcher/ClassLoaderWitness.java b/azureus2/src/com/aelitis/azureus/launcher/ClassLoaderWitness.java
index 022b5c7..888573d 100644
--- a/azureus2/src/com/aelitis/azureus/launcher/ClassLoaderWitness.java
+++ b/azureus2/src/com/aelitis/azureus/launcher/ClassLoaderWitness.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.launcher;
 
diff --git a/azureus2/src/com/aelitis/azureus/launcher/Launcher.java b/azureus2/src/com/aelitis/azureus/launcher/Launcher.java
index f976252..e37d5ba 100644
--- a/azureus2/src/com/aelitis/azureus/launcher/Launcher.java
+++ b/azureus2/src/com/aelitis/azureus/launcher/Launcher.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.launcher;
 
diff --git a/azureus2/src/com/aelitis/azureus/launcher/LauncherTest.java b/azureus2/src/com/aelitis/azureus/launcher/LauncherTest.java
index 71563c4..fab92c8 100644
--- a/azureus2/src/com/aelitis/azureus/launcher/LauncherTest.java
+++ b/azureus2/src/com/aelitis/azureus/launcher/LauncherTest.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.launcher;
 
diff --git a/azureus2/src/com/aelitis/azureus/launcher/MainExecutor.java b/azureus2/src/com/aelitis/azureus/launcher/MainExecutor.java
index 40b655f..afffc10 100644
--- a/azureus2/src/com/aelitis/azureus/launcher/MainExecutor.java
+++ b/azureus2/src/com/aelitis/azureus/launcher/MainExecutor.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.launcher;
 
diff --git a/azureus2/src/com/aelitis/azureus/launcher/classloading/PeeringClassloader.java b/azureus2/src/com/aelitis/azureus/launcher/classloading/PeeringClassloader.java
index 37e3e8f..d9923bb 100644
--- a/azureus2/src/com/aelitis/azureus/launcher/classloading/PeeringClassloader.java
+++ b/azureus2/src/com/aelitis/azureus/launcher/classloading/PeeringClassloader.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.launcher.classloading;
 
diff --git a/azureus2/src/com/aelitis/azureus/launcher/classloading/PrimaryClassloader.java b/azureus2/src/com/aelitis/azureus/launcher/classloading/PrimaryClassloader.java
index da99909..dc6571b 100644
--- a/azureus2/src/com/aelitis/azureus/launcher/classloading/PrimaryClassloader.java
+++ b/azureus2/src/com/aelitis/azureus/launcher/classloading/PrimaryClassloader.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.launcher.classloading;
 
diff --git a/azureus2/src/com/aelitis/azureus/launcher/classloading/SecondaryClassLoader.java b/azureus2/src/com/aelitis/azureus/launcher/classloading/SecondaryClassLoader.java
index 0287f7f..f794b3e 100644
--- a/azureus2/src/com/aelitis/azureus/launcher/classloading/SecondaryClassLoader.java
+++ b/azureus2/src/com/aelitis/azureus/launcher/classloading/SecondaryClassLoader.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.launcher.classloading;
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/I2PHelpers.java b/azureus2/src/com/aelitis/azureus/plugins/I2PHelpers.java
new file mode 100644
index 0000000..51ff59a
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/plugins/I2PHelpers.java
@@ -0,0 +1,166 @@
+/*
+ * Created on Mar 6, 2015
+ * Created by Paul Gardner
+ * 
+ * Copyright 2015 Azureus Software, 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.plugins;
+
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.Debug;
+
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.UIFunctionsUserPrompter;
+
+public class 
+I2PHelpers 
+{
+	private static final Object i2p_install_lock = new Object();
+	
+	private static boolean i2p_installing = false;
+	
+	public static boolean
+	isInstallingI2PHelper()
+	{
+		synchronized( i2p_install_lock ){
+			
+			return( i2p_installing );
+		}
+	}
+
+	public static boolean
+	installI2PHelper(
+		String				remember_id,
+		final boolean[]		install_outcome,
+		final Runnable		callback )
+	{
+		return installI2PHelper(null, remember_id, install_outcome, callback);
+	}
+
+	public static boolean
+	installI2PHelper(
+		String extra_text,
+		String				remember_id,
+		final boolean[]		install_outcome,
+		final Runnable		callback )
+	{
+		synchronized( i2p_install_lock ){
+			
+			if ( i2p_installing ){
+				
+				Debug.out( "I2P Helper already installing" );
+				
+				return( false );
+			}
+			
+			i2p_installing = true;
+		}
+		
+		boolean	installing = false;
+		
+		try{
+			UIFunctions uif = UIFunctionsManager.getUIFunctions();
+			
+			if ( uif == null ){
+				
+				Debug.out( "UIFunctions unavailable - can't install plugin" );
+				
+				return( false );
+			}
+			
+			String title = MessageText.getString("azneti2phelper.install");
+			
+			String text = "";
+			if (extra_text != null) {
+				text = extra_text + "\n\n";
+			}
+			text += MessageText.getString("azneti2phelper.install.text" );
+			
+			UIFunctionsUserPrompter prompter = uif.getUserPrompter(title, text, new String[] {
+				MessageText.getString("Button.yes"),
+				MessageText.getString("Button.no")
+			}, 0);
+			
+			if ( remember_id != null ){
+
+				prompter.setRemember( 
+					remember_id, 
+					false,
+					MessageText.getString("MessageBoxWindow.nomoreprompting"));
+			}
+			
+			prompter.setAutoCloseInMS(0);
+			
+			prompter.open(null);
+			
+			boolean	install = prompter.waitUntilClosed() == 0;
+			
+			if ( install ){
+	
+				installing = true;
+				
+				uif.installPlugin(
+						"azneti2phelper",
+						"azneti2phelper.install",
+						new UIFunctions.actionListener()
+						{
+							public void
+							actionComplete(
+								Object		result )
+							{
+								try{
+									if ( callback != null ){
+										
+										if ( result instanceof Boolean ){
+											
+											install_outcome[0] = (Boolean)result;
+										}
+										
+										callback.run();
+									}
+								}finally{
+																		
+									synchronized( i2p_install_lock ){
+											
+										i2p_installing = false;
+									}
+								}	
+							}
+						});
+			
+			}else{
+				
+				Debug.out( "I2P Helper install declined (either user reply or auto-remembered)" );
+			}
+			
+			return( install );
+			
+		}finally{
+			
+			if ( !installing ){
+			
+				synchronized( i2p_install_lock ){
+					
+					i2p_installing = false;
+				}
+			}
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/clientid/ClientIDPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/clientid/ClientIDPlugin.java
index b01ed60..cf2e6ac 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/clientid/ClientIDPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/clientid/ClientIDPlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPlugin.java
index dc731a4..07f880f 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -71,7 +68,7 @@ import com.aelitis.azureus.plugins.upnp.UPnPPlugin;
 
 public class 
 DHTPlugin
-	implements Plugin
+	implements Plugin, DHTPluginInterface
 {
 		// data will be the DHT instance created
 	
@@ -1105,6 +1102,12 @@ DHTPlugin
 		return( extended_use );
 	}
 	
+	public String 
+	getNetwork() 
+	{
+		return( AENetworkClassifier.AT_PUBLIC );
+	}
+	
 	public boolean
 	isReachable()
 	{
@@ -1774,6 +1777,20 @@ DHTPlugin
 	
 	public DHTPluginContact
 	importContact(
+		Map<String,Object>		map )
+	{
+		if ( !isEnabled()){
+			
+			throw( new RuntimeException( "DHT isn't enabled" ));
+		}
+
+			// first DHT will do here
+		
+		return( dhts[0].importContact( map ));
+	}
+	
+	public DHTPluginContact
+	importContact(
 		InetSocketAddress				address )
 	{
 		if ( !isEnabled()){
@@ -1866,7 +1883,8 @@ DHTPlugin
 	public void
 	registerHandler(
 		byte[]							handler_key,
-		final DHTPluginTransferHandler	handler )
+		final DHTPluginTransferHandler	handler,
+		Map<String,Object>				options )
 	{
 		if ( !isEnabled()){
 			
@@ -1875,10 +1893,26 @@ DHTPlugin
 		
 		for (int i=0;i<dhts.length;i++){
 			
-			dhts[i].registerHandler( handler_key, handler );
+			dhts[i].registerHandler( handler_key, handler, options );
 		}
 	}
 
+	public void
+	unregisterHandler(
+		byte[]							handler_key,
+		final DHTPluginTransferHandler	handler )
+	{
+		if ( !isEnabled()){
+			
+			throw( new RuntimeException( "DHT isn't enabled" ));
+		}
+		
+		for (int i=0;i<dhts.length;i++){
+			
+			dhts[i].unregisterHandler( handler_key, handler );
+		}
+	}
+	
 	public int
 	getStatus()
 	{
@@ -1929,6 +1963,24 @@ DHTPlugin
 		return( null );
 	}
 	
+	public DHTInterface[] 
+	getDHTInterfaces() 
+	{
+		if ( dhts == null ){
+			
+			return( new DHTInterface[0] );
+		}
+		
+		DHTInterface[] result = new DHTInterface[dhts.length];
+		
+		for (int i=0;i<dhts.length;i++){
+			
+			result[i] = dhts[i];
+		}
+		
+		return( result );
+	}
+	
 	protected long
 	loadClockSkew()
 	{
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginContact.java b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginContact.java
index 53b4802..00502c0 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginContact.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginContact.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -49,6 +46,9 @@ DHTPluginContact
 	public int
 	getNetwork();
 	
+	public Map<String,Object>
+	exportToMap();
+	
 	public boolean
 	isAlive(
 		long		timeout );
@@ -66,8 +66,26 @@ DHTPluginContact
 	
 	public byte[]
 	read(
-		final DHTPluginProgressListener	listener,
-		final byte[]					handler_key,
-		final byte[]					key,
-		final long						timeout );
+		DHTPluginProgressListener	listener,
+		byte[]						handler_key,
+		byte[]						key,
+		long						timeout );
+	
+	public void
+	write(
+		DHTPluginProgressListener	listener,
+		byte[]						handler_key,
+		byte[]						key,
+		byte[]						data,
+		long						timeout );
+	
+	public byte[]
+	call(
+		DHTPluginProgressListener	listener,
+		byte[]						handler_key,
+		byte[]						data,
+		long						timeout );
+	
+	public String
+	getString();
 }
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginInterface.java b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginInterface.java
new file mode 100644
index 0000000..fdf11cd
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginInterface.java
@@ -0,0 +1,174 @@
+/*
+ * Created on Sep 3, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.plugins.dht;
+
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.Map;
+
+import com.aelitis.azureus.core.dht.DHT;
+
+public interface 
+DHTPluginInterface 
+{
+	public static final byte		FLAG_SINGLE_VALUE	= DHT.FLAG_SINGLE_VALUE;
+	public static final byte		FLAG_DOWNLOADING	= DHT.FLAG_DOWNLOADING;
+	public static final byte		FLAG_SEEDING		= DHT.FLAG_SEEDING;
+	public static final byte		FLAG_MULTI_VALUE	= DHT.FLAG_MULTI_VALUE;
+	public static final byte		FLAG_STATS			= DHT.FLAG_STATS;
+	public static final byte		FLAG_ANON			= DHT.FLAG_ANON;
+	public static final byte		FLAG_PRECIOUS		= DHT.FLAG_PRECIOUS;
+	
+	public static final int			MAX_VALUE_SIZE		= DHT.MAX_VALUE_SIZE;
+
+
+	
+	public boolean
+	isEnabled();
+	
+	public boolean
+	isExtendedUseAllowed();
+	
+	public boolean
+	isInitialising();
+	
+	public boolean
+	isSleeping();
+	
+	public DHTPluginContact
+	getLocalAddress();
+	
+	public String
+	getNetwork();
+	
+	public DHTPluginKeyStats
+	decodeStats(
+		DHTPluginValue		value );
+	
+	public void
+	registerHandler(
+		byte[]							handler_key,
+		DHTPluginTransferHandler		handler,
+		Map<String,Object>				options );
+	
+	public void
+	unregisterHandler(
+		byte[]							handler_key,
+		DHTPluginTransferHandler		handler );
+
+	public DHTPluginContact
+	importContact(
+		InetSocketAddress				address );
+	
+	public DHTPluginContact
+	importContact(
+		InetSocketAddress				address,
+		byte							version );
+	
+	public DHTPluginContact
+	importContact(
+		InetSocketAddress				address,
+		byte							version,
+		boolean							is_cvs );
+	
+	public DHTPluginContact
+	importContact(
+		Map<String,Object>				map );		
+	
+	public void
+	get(
+		byte[]								original_key,
+		String								description,
+		byte								flags,
+		int									max_values,
+		long								timeout,
+		boolean								exhaustive,
+		boolean								high_priority,
+		DHTPluginOperationListener			original_listener );
+	
+	public void
+	put(
+		byte[]						key,
+		String						description,
+		byte[]						value,
+		byte						flags,
+		DHTPluginOperationListener	listener);
+	
+	public DHTInterface[]
+	getDHTInterfaces();
+	
+	public List<DHTPluginValue>
+	getValues();
+
+	public void
+	remove(
+		byte[]						key,
+		String						description,
+		DHTPluginOperationListener	listener );
+	
+	public void
+	remove(
+		DHTPluginContact[]			targets,
+		byte[]						key,
+		String						description,
+		DHTPluginOperationListener	listener );
+	
+	public void
+	addListener(
+		DHTPluginListener	l );
+
+	
+	public void
+	removeListener(
+		DHTPluginListener	l );
+
+	
+	public void
+	log(
+		String	str );
+
+	public interface
+	DHTInterface
+	{
+		public byte[]
+		getID();
+		
+		public boolean
+		isIPV6();
+		
+		public int
+		getNetwork();
+				
+		public DHTPluginContact[]
+		getReachableContacts();
+		
+		public DHTPluginContact[]
+		getRecentContacts();
+		
+		public List<DHTPluginContact>
+		getClosestContacts(
+			byte[]		to_id,
+			boolean		live_only );
+	}
+	
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginKeyStats.java b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginKeyStats.java
index 9463e46..bbedcf8 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginKeyStats.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginKeyStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23 May 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginListener.java b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginListener.java
index 798a609..3b2b1dd 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginOperationAdapter.java b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginOperationAdapter.java
new file mode 100644
index 0000000..f3163fb
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginOperationAdapter.java
@@ -0,0 +1,61 @@
+/*
+ * Created on Oct 7, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.plugins.dht;
+
+public class 
+DHTPluginOperationAdapter
+	implements DHTPluginOperationListener
+{
+	public void
+	starts(
+		byte[]				key )
+	{	
+	}
+	
+	public boolean
+	diversified()
+	{
+		return( true );
+	}
+	
+	public void
+	valueRead(
+		DHTPluginContact	originator,
+		DHTPluginValue		value )
+	{	
+	}
+	
+	public void
+	valueWritten(
+		DHTPluginContact	target,
+		DHTPluginValue		value )
+	{		
+	}
+	
+	public void
+	complete(
+		byte[]				key,
+		boolean				timeout_occurred )
+	{	
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginOperationListener.java b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginOperationListener.java
index b6956fe..da7a475 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginOperationListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginOperationListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 01-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginProgressListener.java b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginProgressListener.java
index 34818fd..32c8978 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginProgressListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginProgressListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginTransferHandler.java b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginTransferHandler.java
index ee0821f..24de813 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginTransferHandler.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginTransferHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -38,7 +35,7 @@ DHTPluginTransferHandler
 		DHTPluginContact	originator,
 		byte[]				key );
 	
-	public void
+	public byte[]
 	handleWrite(
 		DHTPluginContact	originator,
 		byte[]				key,
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginValue.java b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginValue.java
index ac47938..142e90b 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginValue.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/DHTPluginValue.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginContactImpl.java b/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginContactImpl.java
index ea272de..2730b9f 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginContactImpl.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginContactImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -90,6 +87,12 @@ DHTPluginContactImpl
 		return( contact.getAddress());
 	}
 	
+	public Map<String, Object> 
+	exportToMap() 
+	{
+		return( contact.exportContactToMap());
+	}
+	
 	public boolean
 	isAlive(
 		long		timeout )
@@ -142,6 +145,44 @@ DHTPluginContactImpl
 		return( puncher.punch( "Tunnel", contact, null, null ));
 	}
 
+	public Map
+	openTunnel(
+		DHTPluginContact[]	rendezvous,
+		Map					client_data )
+	{
+		DHTNATPuncher puncher = plugin.getDHT().getNATPuncher();
+		
+		if ( puncher == null ){
+			
+			return( null );
+		}
+		
+		if ( rendezvous == null || rendezvous.length == 0 ){
+		
+			return( puncher.punch( "Tunnel", contact, null, client_data ));
+			
+		}else{
+			
+			DHTTransportContact[] r = new DHTTransportContact[rendezvous.length];
+			
+			for ( int i=0;i<r.length;i++){
+				
+				r[0] = ((DHTPluginContactImpl)rendezvous[i]).contact;
+			}
+			
+			Map result = puncher.punch( "Tunnel", contact, r, client_data );
+			
+			DHTTransportContact used = r[0];
+			
+			if ( used != null ){
+				
+				rendezvous[0] = new DHTPluginContactImpl( plugin, used );
+			}
+			
+			return( result );
+		}
+	}
+
 	public byte[]
     read(
     	DHTPluginProgressListener	listener,
@@ -151,4 +192,31 @@ DHTPluginContactImpl
 	{
 		return( plugin.read( listener, this, handler_key, key, timeout ));
 	}
+	
+	public void
+    write(
+    	DHTPluginProgressListener	listener,
+    	byte[]						handler_key,
+    	byte[]						key,
+    	byte[]						data,
+    	long						timeout )
+	{
+		plugin.write( listener, this, handler_key, key, data, timeout );
+	}
+	
+	public byte[]
+    call(
+    	DHTPluginProgressListener	listener,
+    	byte[]						handler_key,
+    	byte[]						data,
+    	long						timeout )
+	{
+		return( plugin.call( listener, this, handler_key, data, timeout ));
+	}
+	
+	public String 
+	getString() 
+	{
+		return( contact.getString());
+	}
 }
\ No newline at end of file
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginImpl.java b/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginImpl.java
index 866b1cf..a2aa21f 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginImpl.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -29,10 +26,13 @@ import java.io.File;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 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 org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.Constants;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.FileUtil;
@@ -78,6 +78,7 @@ import com.aelitis.azureus.plugins.dht.DHTPluginOperationListener;
 import com.aelitis.azureus.plugins.dht.DHTPluginProgressListener;
 import com.aelitis.azureus.plugins.dht.DHTPluginTransferHandler;
 import com.aelitis.azureus.plugins.dht.DHTPluginValue;
+import com.aelitis.azureus.plugins.dht.DHTPluginInterface.DHTInterface;
 import com.aelitis.azureus.plugins.dht.impl.DHTPluginStorageManager;
 
 
@@ -88,6 +89,7 @@ import com.aelitis.azureus.plugins.dht.impl.DHTPluginStorageManager;
 
 public class 
 DHTPluginImpl
+	implements DHTInterface
 {
 	private static final String	SEED_ADDRESS_V4	= Constants.DHT_SEED_ADDRESS_V4;
 	private static final String	SEED_ADDRESS_V6	= Constants.DHT_SEED_ADDRESS_V6;
@@ -557,13 +559,18 @@ outer:
 								
 								if ( is_v6 == v6 ){
 									
-									if ( importSeed( p.getIp(), peer_udp_port ) != null ){
+									String ip =  p.getIp();
+									
+									if ( AENetworkClassifier.categoriseAddress( ip ) == AENetworkClassifier.AT_PUBLIC ){
 										
-										peers_imported++;
-																	
-										if ( peers_imported > seed_limit ){
+										if ( importSeed( ip, peer_udp_port ) != null ){
 											
-											break outer;
+											peers_imported++;
+																		
+											if ( peers_imported > seed_limit ){
+												
+												break outer;
+											}
 										}
 									}
 								}
@@ -1139,6 +1146,21 @@ outer:
 	
 	public DHTPluginContact
 	importContact(
+		Map<String,Object>				map )
+	{
+		try{
+			return( new DHTPluginContactImpl( this, transport.importContact( map)));
+			
+		}catch( DHTTransportException	e ){
+			
+			Debug.printStackTrace(e);
+			
+			return( null );
+		}
+	}
+	
+	public DHTPluginContact
+	importContact(
 		InetSocketAddress				address )
 	{
 		try{
@@ -1170,40 +1192,81 @@ outer:
 	
 		// direct read/write support
 	
+	private Map<DHTPluginTransferHandler,DHTTransportTransferHandler>	handler_map = new HashMap<DHTPluginTransferHandler, DHTTransportTransferHandler>();
+
 	public void
 	registerHandler(
 		byte[]							handler_key,
-		final DHTPluginTransferHandler	handler )
+		final DHTPluginTransferHandler	handler,
+		Map<String,Object>				options )
 	{
-		dht.getTransport().registerTransferHandler( 
-				handler_key,
-				new DHTTransportTransferHandler()
+		DHTTransportTransferHandler h = 
+			new DHTTransportTransferHandler()
+			{
+				public String
+				getName()
 				{
-					public String
-					getName()
-					{
-						return( handler.getName());
-					}
-					
-					public byte[]
-					handleRead(
-						DHTTransportContact	originator,
-						byte[]				key )
-					{
-						return( handler.handleRead( new DHTPluginContactImpl( DHTPluginImpl.this, originator ), key ));
-					}
-					
-					public byte[]
-					handleWrite(
-							DHTTransportContact	originator,
-						byte[]				key,
-						byte[]				value )
-					{
-						handler.handleWrite( new DHTPluginContactImpl( DHTPluginImpl.this, originator ), key, value );
-						
-						return( null );
-					}
-				});
+					return( handler.getName());
+				}
+				
+				public byte[]
+				handleRead(
+					DHTTransportContact	originator,
+					byte[]				key )
+				{
+					return( handler.handleRead( new DHTPluginContactImpl( DHTPluginImpl.this, originator ), key ));
+				}
+				
+				public byte[]
+				handleWrite(
+					DHTTransportContact	originator,
+					byte[]				key,
+					byte[]				value )
+				{
+					return( handler.handleWrite( new DHTPluginContactImpl( DHTPluginImpl.this, originator ), key, value ));
+				}
+			};
+		
+		synchronized( handler_map ){
+			
+			if ( handler_map.containsKey( handler )){
+				
+				Debug.out( "Warning: handler already exists" );
+			}else{
+				
+				handler_map.put( handler, h );
+			}
+		}
+		
+		dht.getTransport().registerTransferHandler( handler_key, h, options );
+	}
+	
+	public void
+	unregisterHandler(
+		byte[]							handler_key,
+		final DHTPluginTransferHandler	handler )
+	{
+		DHTTransportTransferHandler h;
+		
+		synchronized( handler_map ){
+		
+			h = handler_map.remove( handler );
+		}
+		
+		if ( h == null ){
+			
+			Debug.out( "Mapping not found for handler" );
+			
+		}else{
+			
+			try{
+				getDHT().getTransport().unregisterTransferHandler( handler_key, h );
+
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
 	}
 	
 	public byte[]
@@ -1249,7 +1312,98 @@ outer:
 			throw( new RuntimeException( e ));
 		}
 	}
-
+	
+	public void
+	write(
+		final DHTPluginProgressListener	listener,
+		DHTPluginContact				target,
+		byte[]							handler_key,
+		byte[]							key,
+		byte[]							data,
+		long							timeout )
+	{
+		try{
+			dht.getTransport().writeTransfer(
+					new DHTTransportProgressListener()
+					{
+						public void
+						reportSize(
+							long	size )
+						{
+							listener.reportSize( size );
+						}
+						
+						public void
+						reportActivity(
+							String	str )
+						{
+							listener.reportActivity( str );
+						}
+						
+						public void
+						reportCompleteness(
+							int		percent )
+						{
+							listener.reportCompleteness( percent );
+						}
+					},
+					((DHTPluginContactImpl)target).getContact(), 
+					handler_key, 
+					key, 
+					data,
+					timeout );
+			
+		}catch( DHTTransportException e ){
+			
+			throw( new RuntimeException( e ));
+		}
+	}
+	
+	public byte[]
+	call(
+		final DHTPluginProgressListener	listener,
+		DHTPluginContact				target,
+		byte[]							handler_key,
+		byte[]							data,
+		long							timeout )
+	{
+		try{
+			return( 
+				dht.getTransport().writeReadTransfer(
+					new DHTTransportProgressListener()
+					{
+						public void
+						reportSize(
+							long	size )
+						{
+							listener.reportSize( size );
+						}
+						
+						public void
+						reportActivity(
+							String	str )
+						{
+							listener.reportActivity( str );
+						}
+						
+						public void
+						reportCompleteness(
+							int		percent )
+						{
+							listener.reportCompleteness( percent );
+						}
+					},
+					((DHTPluginContactImpl)target).getContact(), 
+					handler_key, 
+					data,
+					timeout ));
+			
+		}catch( DHTTransportException e ){
+			
+			throw( new RuntimeException( e ));
+		}
+	}
+	
 	public DHT
 	getDHT()
 	{
@@ -1340,4 +1494,69 @@ outer:
 			return( null );
 		}
 	}
+	
+	public byte[]
+	getID()
+	{
+		return( dht.getRouter().getID());
+	}
+	
+	public boolean
+	isIPV6()
+	{
+		return( dht.getTransport().isIPV6());
+	}
+	
+	public int
+	getNetwork()
+	{
+		return( dht.getTransport().getNetwork());
+	}
+			
+	public DHTPluginContact[]
+	getReachableContacts()
+	{
+		DHTTransportContact[] contacts = dht.getTransport().getReachableContacts();
+		
+		DHTPluginContact[] result = new DHTPluginContact[contacts.length];
+		
+		for ( int i=0;i<contacts.length;i++ ){
+			
+			result[i] = new DHTPluginContactImpl( this, contacts[i] );
+		}
+		
+		return( result );
+	}
+	
+	public DHTPluginContact[]
+	getRecentContacts()
+	{
+		DHTTransportContact[] contacts = dht.getTransport().getRecentContacts();
+		
+		DHTPluginContact[] result = new DHTPluginContact[contacts.length];
+		
+		for ( int i=0;i<contacts.length;i++ ){
+			
+			result[i] = new DHTPluginContactImpl( this, contacts[i] );
+		}
+	
+		return( result );
+	}
+	
+	public List<DHTPluginContact>
+	getClosestContacts(
+		byte[]		to_id,
+		boolean		live_only )
+	{
+		List<DHTTransportContact> contacts = dht.getControl().getClosestKContactsList(to_id, live_only);
+		
+		List<DHTPluginContact> result = new ArrayList<DHTPluginContact>( contacts.size());
+		
+		for ( DHTTransportContact contact: contacts ){
+			
+			result.add( new DHTPluginContactImpl( this, contact ));
+		}
+		
+		return( result );
+	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginImplAdapter.java b/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginImplAdapter.java
index 35a4c27..383d6f9 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginImplAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginImplAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 11, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginStorageManager.java b/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginStorageManager.java
index 5da8139..8aea8f4 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginStorageManager.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginStorageManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -52,7 +49,6 @@ import com.aelitis.azureus.core.dht.DHTStorageKey;
 import com.aelitis.azureus.core.dht.DHTStorageKeyStats;
 import com.aelitis.azureus.core.dht.impl.DHTLog;
 import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
-import com.aelitis.azureus.core.dht.transport.DHTTransportFullStats;
 import com.aelitis.azureus.core.dht.transport.DHTTransportValue;
 import com.aelitis.azureus.core.util.bloom.BloomFilter;
 import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
@@ -200,7 +196,7 @@ DHTPluginStorageManager
 		return( network );
 	}
 	
-	protected void
+	public void
 	importContacts(
 		DHT		dht )
 	{
@@ -237,7 +233,7 @@ DHTPluginStorageManager
 		}
 	}
 	
-	protected void
+	public void
 	exportContacts(
 		DHT		dht )
 	{
@@ -2275,9 +2271,9 @@ DHTPluginStorageManager
 								( LOCAL_DIVERSIFICATION_READS_PER_MIN * LOCAL_DIVERSIFICATION_READS_PER_MIN_SAMPLES *10 ) / 3 );
 					}
 					
-					byte[]	address_bytes = contact.getAddress().getAddress().getAddress();
+					byte[]	bloom_key = contact.getBloomKey();
 					
-					ip_bloom_filter.add( address_bytes );
+					ip_bloom_filter.add( bloom_key );
 				}
 			}
 		}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginValueImpl.java b/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginValueImpl.java
index 21e6cca..0d80da2 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginValueImpl.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/dht/impl/DHTPluginValueImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedException.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedException.java
index b2cc4f2..9494a4f 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedException.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedManualPeer.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedManualPeer.java
index 89308cd..6104913 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedManualPeer.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedManualPeer.java
@@ -1,59 +1,58 @@
-/*
- * Created on Feb 8, 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.plugins.extseed;
-
-public class 
-ExternalSeedManualPeer 
-{
-	private ExternalSeedPeer		peer;
-	
-	protected
-	ExternalSeedManualPeer(
-		ExternalSeedPeer	_peer )
-	{
-		peer		= _peer;
-	}
-	
-	public String
-	getIP()
-	{
-		return( peer.getIp());
-	}
-	  
-	public byte[]
-	read(
-		int		piece_number,
-		int		offset,
-		int		length,
-		int		timeout )
-	
-		throws ExternalSeedException
-	{
-		return( peer.getReader().read( piece_number, offset, length, timeout ));
-	}
-	
-	public ExternalSeedPeer
-	getDelegate()
-	{
-		return( peer );
-	}
-}
+/*
+ * Created on Feb 8, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.extseed;
+
+public class 
+ExternalSeedManualPeer 
+{
+	private ExternalSeedPeer		peer;
+	
+	protected
+	ExternalSeedManualPeer(
+		ExternalSeedPeer	_peer )
+	{
+		peer		= _peer;
+	}
+	
+	public String
+	getIP()
+	{
+		return( peer.getIp());
+	}
+	  
+	public byte[]
+	read(
+		int		piece_number,
+		int		offset,
+		int		length,
+		int		timeout )
+	
+		throws ExternalSeedException
+	{
+		return( peer.getReader().read( piece_number, offset, length, timeout ));
+	}
+	
+	public ExternalSeedPeer
+	getDelegate()
+	{
+		return( peer );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedPeer.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedPeer.java
index 6e7c0f1..e5cca45 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedPeer.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedPeer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedPlugin.java
index 2f687cc..00b9da6 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedPlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -26,6 +23,7 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.*;
 
+import org.gudy.azureus2.core3.torrent.TOTorrent;
 import org.gudy.azureus2.core3.util.AEThread2;
 import org.gudy.azureus2.core3.util.SystemTime;
 import org.gudy.azureus2.plugins.Plugin;
@@ -519,6 +517,22 @@ ExternalSeedPlugin
 		}	
 	}
 	
+	public ExternalSeedReader[]
+	getManualWebSeeds(
+		Torrent	torrent )
+	{
+		List<ExternalSeedReader>		result = new ArrayList<ExternalSeedReader>();
+		
+		for (int i=0;i<factories.length;i++){
+
+			ExternalSeedReader[] peers = factories[i].getSeedReaders( this, torrent );
+			
+			result.addAll( Arrays.asList( peers ));
+		}
+		
+		return( result.toArray( new  ExternalSeedReader[result.size()]));
+	}
+	
 	public TrackerPeerSource
 	getTrackerPeerSource(
 		final Download		download )
@@ -587,7 +601,7 @@ ExternalSeedPlugin
 				}
 				
 				public int
-				getPeers()
+				getSeedCount()
 				{
 					fixup();
 					
@@ -620,6 +634,67 @@ ExternalSeedPlugin
 			});
 	}
 	
+	public TrackerPeerSource
+	getTrackerPeerSource(
+		final Torrent		torrent )
+	{
+		return(
+			new TrackerPeerSourceAdapter()
+			{				
+				private ExternalSeedReader[]	peers = getManualWebSeeds( torrent );				
+				
+				public int
+				getType()
+				{
+					return( TP_HTTP_SEED );
+				}
+				
+				public int
+				getStatus()
+				{
+					return( peers.length==0?ST_UNAVAILABLE:ST_AVAILABLE );
+				}
+				
+				public String
+				getName()
+				{					
+					if ( peers.length == 0 ){
+						
+						return( "" );
+					}
+					
+					StringBuffer sb = new StringBuffer();
+					
+					for ( ExternalSeedReader peer: peers ){
+						
+						if ( sb.length() > 0 ){
+							
+							sb.append( ", " );
+						}
+						
+						String str = peer.getURL().toExternalForm();
+						
+						int pos = str.indexOf( '?' );
+						
+						if ( pos != -1 ){
+							
+							str = str.substring( 0, pos );
+						}
+						
+						sb.append( str );
+					}
+					
+					return( sb.toString());
+				}
+				
+				public int
+				getSeedCount()
+				{					
+					return( peers.length==0?-1:peers.length );
+				}
+			});
+	}
+	
 	public int
 	getGlobalDownloadRateBytesPerSec()
 	{
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReader.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReader.java
index ac1fa2d..7550236 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReader.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReader.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReaderFactory.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReaderFactory.java
index bc205eb..71bd8e3 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReaderFactory.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReaderFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -25,6 +22,7 @@ package com.aelitis.azureus.plugins.extseed;
 import java.util.Map;
 
 import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.torrent.Torrent;
 
 public interface 
 ExternalSeedReaderFactory 
@@ -32,6 +30,11 @@ ExternalSeedReaderFactory
 	public ExternalSeedReader[]
 	getSeedReaders(
 		ExternalSeedPlugin	plugin,
+		Torrent				torrent );
+	
+	public ExternalSeedReader[]
+	getSeedReaders(
+		ExternalSeedPlugin	plugin,
 		Download			download );
 	
 	public ExternalSeedReader[]
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReaderListener.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReaderListener.java
index 439484f..ad98e10 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReaderListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/ExternalSeedReaderListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderImpl.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderImpl.java
index ec5530d..f8d3561 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderImpl.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -27,6 +24,7 @@ import java.util.*;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.config.ParameterListener;
 import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.AESemaphore;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.HostNameToIPResolver;
@@ -46,6 +44,7 @@ import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.plugins.utils.Monitor;
 import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
 import org.gudy.azureus2.plugins.utils.Semaphore;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
 
 import com.aelitis.azureus.core.util.CopyOnWriteSet;
 import com.aelitis.azureus.plugins.extseed.ExternalSeedException;
@@ -296,6 +295,7 @@ ExternalSeedReaderImpl
 		boolean	early_days = time_since_start < INITIAL_DELAY;
 		
 		try{
+			Download download = peer_manager.getDownload();
 
 				// first respect failure count 
 			
@@ -332,14 +332,19 @@ ExternalSeedReaderImpl
 				return( false );
 			}
 			
-			if ( peer_manager.getDownload().getState() != Download.ST_DOWNLOADING ){
+			if ( download.getState() != Download.ST_DOWNLOADING ){
 				
 				return( false );
 			}
 				
 				// check dnd completeness too
 			
-			if ( peer_manager.getDownload().isComplete()){
+			if ( download.isComplete()){
+				
+				return( false );
+			}
+			
+			if ( !PluginCoreUtils.unwrap( download ).getDownloadState().isNetworkEnabled( AENetworkClassifier.categoriseAddress( host ))){
 				
 				return( false );
 			}
@@ -431,7 +436,7 @@ ExternalSeedReaderImpl
 				
 				if ( min_availability > 0 ){
 										
-					float availability = peer_manager.getDownload().getStats().getAvailability();
+					float availability = download.getStats().getAvailability();
 				
 					if ( availability < min_availability){
 					
@@ -454,7 +459,7 @@ ExternalSeedReaderImpl
 			
 				// if we have an announce result and there are no seeds, or it failed then go for it
 			
-			DownloadAnnounceResult ar = peer_manager.getDownload().getLastAnnounceResult();
+			DownloadAnnounceResult ar = download.getLastAnnounceResult();
 			
 			if ( ar != null ){
 				
@@ -661,6 +666,9 @@ ExternalSeedReaderImpl
 			
 			status = active?"Active":"Idle";
 			
+			rate_bytes_permitted		= 0;
+			rate_bytes_read				= 0;
+			
 			setActiveSupport( _peer_manager, _active );
 			
 		}finally{
@@ -810,7 +818,7 @@ ExternalSeedReaderImpl
 			// has already happened and prepare for what will
 		
 		int	res = 0;
-		
+				
 		synchronized( rate_sem ){
 			
 			if ( rate_bytes_read > 0 ){
@@ -836,6 +844,13 @@ ExternalSeedReaderImpl
 				
 				rate_bytes_permitted = rem;
 			}
+			
+				// if things are way out then hack them back - most likely a change from unlimited to limited...
+			
+			if ( rate_bytes_permitted > max*10L ){
+				
+				rate_bytes_permitted = max;
+			}
 		}
 		
 		return( res );
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderRequest.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderRequest.java
index 31841d8..3e6b6af 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderRequest.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/ExternalSeedReaderRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 May 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderFactoryGetRight.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderFactoryGetRight.java
index ebe79dd..e2ce891 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderFactoryGetRight.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderFactoryGetRight.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -43,12 +40,27 @@ ExternalSeedReaderFactoryGetRight
 	}
 	
 	public ExternalSeedReader[]
+	getSeedReaders(
+		ExternalSeedPlugin		plugin,
+		Download				download )
+	{		
+		return( getSeedReaders( plugin, download.getName(), download.getTorrent()));
+	}
+	
+	public ExternalSeedReader[]
+   	getSeedReaders(
+   		ExternalSeedPlugin		plugin,
+   		Torrent					torrent )
+  	{	
+		return( getSeedReaders( plugin, torrent.getName(), torrent ));
+  	}
+	
+	private ExternalSeedReader[]
    	getSeedReaders(
    		ExternalSeedPlugin		plugin,
-   		Download				download )
+   		String					name,
+   		Torrent					torrent )
   	{		
-  		Torrent	torrent = download.getTorrent();
-  		
   		try{
   			Map	config = new HashMap();
   			
@@ -73,7 +85,7 @@ ExternalSeedReaderFactoryGetRight
   				config.put( "url-list-params2", obj );
   			}
   			
-  			return( getSeedReaders( plugin, download, config ));
+  			return( getSeedReaders( plugin, name, torrent, config ));
   			
   		}catch( Throwable e ){
 			
@@ -88,6 +100,16 @@ ExternalSeedReaderFactoryGetRight
   		ExternalSeedPlugin		plugin,
   		Download				download,
   		Map						config )
+  	{
+		return( getSeedReaders( plugin, download.getName(), download.getTorrent(), config ));
+  	}
+	
+	private ExternalSeedReader[]
+  	getSeedReaders(
+  		ExternalSeedPlugin		plugin,
+  		String					name,
+  		Torrent					torrent,
+  		Map						config )
 	{				
 		try{
 			Object	obj = config.get( "url-list" );
@@ -147,13 +169,13 @@ ExternalSeedReaderFactoryGetRight
 							
 							String	protocol = url.getProtocol().toLowerCase();
 																			
-							if ( protocol.equals( "http" )){
+							if ( protocol.startsWith( "http" )){
 								
-								readers.add( new ExternalSeedReaderGetRight(plugin, download.getTorrent(), url, my_params ));
+								readers.add( new ExternalSeedReaderGetRight(plugin, torrent, url, my_params ));
 								
 							}else{
 								
-								plugin.log( download.getName() + ": GR unsupported protocol: " + url );
+								plugin.log( name + ": GR unsupported protocol: " + url );
 							}
 						}
 					}catch( Throwable e ){
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderGetRight.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderGetRight.java
index 3630d11..dfe1b99 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderGetRight.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/getright/ExternalSeedReaderGetRight.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderFactoryWebSeed.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderFactoryWebSeed.java
index 5ee5368..ebd8a0d 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderFactoryWebSeed.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderFactoryWebSeed.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -43,12 +40,27 @@ ExternalSeedReaderFactoryWebSeed
 	}
 	
 	public ExternalSeedReader[]
- 	getSeedReaders(
- 		ExternalSeedPlugin		plugin,
- 		Download				download )
+	getSeedReaders(
+		ExternalSeedPlugin		plugin,
+		Download				download )
 	{		
-		Torrent	torrent = download.getTorrent();
-		
+		return( getSeedReaders( plugin, download.getName(), download.getTorrent()));
+	}
+	
+	public ExternalSeedReader[]
+   	getSeedReaders(
+   		ExternalSeedPlugin		plugin,
+   		Torrent					torrent )
+  	{	
+		return( getSeedReaders( plugin, torrent.getName(), torrent ));
+  	}
+	
+	private ExternalSeedReader[]
+   	getSeedReaders(
+   		ExternalSeedPlugin		plugin,
+   		String					name,
+   		Torrent					torrent )
+	{				
 		try{
 			Map	config = new HashMap();
 			
@@ -59,7 +71,7 @@ ExternalSeedReaderFactoryWebSeed
 				config.put( "httpseeds", obj );
 			}
 			
-			return( getSeedReaders( plugin, download, config ));
+			return( getSeedReaders( plugin, name, torrent, config ));
 			
 		}catch( Throwable e ){
 		
@@ -74,9 +86,17 @@ ExternalSeedReaderFactoryWebSeed
   		ExternalSeedPlugin		plugin,
   		Download				download,
   		Map						config )
-	{		
-		Torrent	torrent = download.getTorrent();
-		
+  	{
+		return( getSeedReaders( plugin, download.getName(), download.getTorrent(), config ));
+  	}
+	
+	private ExternalSeedReader[]
+  	getSeedReaders(
+  		ExternalSeedPlugin		plugin,
+  		String					name,
+  		Torrent					torrent,
+  		Map						config )
+	{				
 		try{
 			Object	obj = config.get( "httpseeds" );
 			
@@ -128,7 +148,7 @@ ExternalSeedReaderFactoryWebSeed
 							
 						}else{
 							
-							plugin.log( download.getName() + ": WS unsupported protocol: " + url );
+							plugin.log( name + ": WS unsupported protocol: " + url );
 						}
 					}catch( Throwable e ){
 						
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderWebSeed.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderWebSeed.java
index 7c1917a..01e69c8 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderWebSeed.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/impl/webseed/ExternalSeedReaderWebSeed.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloader.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloader.java
index 9ff5042..3d5c35a 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloader.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloader.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderLinear.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderLinear.java
index 02724e5..5dd3414 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderLinear.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderLinear.java
@@ -1,659 +1,702 @@
-/*
- * 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.networkmanager.admin.NetworkAdmin;
-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 );
-					
-					if ( NetworkAdmin.getSingleton().hasMissingForcedBind()){
-						
-						throw( new ExternalSeedException( "Forced bind address is missing" ));
-					}
-					
-					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 ){
-						
-						connection.setConnectTimeout( time_remaining );
-					}
-								
-					connection.connect();
-				
-					time_remaining	= listener.getPermittedTime();
-										
-					if ( time_remaining < 0 ){
-						
-						throw( new IOException( "Timeout during connect" ));
-					}
-					
-					connection.setReadTimeout( 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 = connection.getHeaderFieldDate("Retry-After", -1L);
-		            	
-		                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();
-									
-									if ( raf.read( buffer, 0, buffer_len ) != buffer_len ){
-										
-										throw( new IOException( "Error reading scratch file" ));
-									}
-									
-									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()
-		{
-		}
-	}
-	
-	private static 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 );
-		}		
-	}
-}
+/*
+ * Created on Oct 21, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.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.Proxy;
+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.AENetworkClassifier;
+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.networkmanager.admin.NetworkAdmin;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
+import com.aelitis.azureus.plugins.extseed.ExternalSeedException;
+
+public class 
+ExternalSeedHTTPDownloaderLinear 
+	implements ExternalSeedHTTPDownloader
+{
+	final private URL		very_original_url;
+	final 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 )
+	{
+		very_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		= "";
+			
+			PluginProxy		plugin_proxy	= null;
+			
+			boolean proxy_ok = false;
+
+			try{
+				URL	original_url 	= very_original_url;
+				URL current_url		= original_url;
+				
+				Proxy	current_proxy = null;
+				
+				if ( AENetworkClassifier.categoriseAddress( original_url.getHost()) != AENetworkClassifier.AT_PUBLIC ){
+					
+					plugin_proxy = AEProxyFactory.getPluginProxy( "webseed", original_url );
+					
+					if ( plugin_proxy != null ){
+						
+						current_url		= plugin_proxy.getURL();
+				
+						current_proxy	= plugin_proxy.getProxy();
+					}
+				}
+				
+				InputStream			is				= null;
+				
+				try{
+					SESecurityManager.setThreadPasswordHandler( this );
+					
+					if ( NetworkAdmin.getSingleton().hasMissingForcedBind()){
+						
+						throw( new ExternalSeedException( "Forced bind address is missing" ));
+					}
+					
+					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;
+							
+					if ( current_proxy == null ){
+						
+						connection = (HttpURLConnection)current_url.openConnection();
+						
+					}else{
+						
+						connection = (HttpURLConnection)current_url.openConnection( current_proxy );
+						
+						connection.setRequestProperty( "HOST", plugin_proxy.getURLHostRewrite() + (original_url.getPort()==-1?"":(":" + original_url.getPort())));
+					}
+					
+					connection.setRequestProperty( "Connection", "Keep-Alive" );
+					connection.setRequestProperty( "User-Agent", user_agent );
+						
+					int	time_remaining	= listener.getPermittedTime();
+					
+					if ( time_remaining > 0 ){
+						
+						connection.setConnectTimeout( time_remaining );
+					}
+								
+					connection.connect();
+				
+					proxy_ok = true;
+					
+					time_remaining	= listener.getPermittedTime();
+										
+					if ( time_remaining < 0 ){
+						
+						throw( new IOException( "Timeout during connect" ));
+					}
+					
+					connection.setReadTimeout( 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 = connection.getHeaderFieldDate("Retry-After", -1L);
+		            	
+		                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 );
+				
+			}finally{
+				
+				if ( plugin_proxy != null ){
+					
+					plugin_proxy.setOK( proxy_ok );
+				}
+			}
+			
+				// 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();
+									
+									if ( raf.read( buffer, 0, buffer_len ) != buffer_len ){
+										
+										throw( new IOException( "Error reading scratch file" ));
+									}
+									
+									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()
+		{
+		}
+	}
+	
+	private static 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/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderListener.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderListener.java
index 0724259..180b73d 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 May 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderRange.java b/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderRange.java
index 597b9de..474b31b 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderRange.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/extseed/util/ExternalSeedHTTPDownloaderRange.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -29,6 +26,7 @@ import java.io.OutputStream;
 import java.net.HttpURLConnection;
 import java.net.InetSocketAddress;
 import java.net.PasswordAuthentication;
+import java.net.Proxy;
 import java.net.Socket;
 import java.net.URL;
 import java.util.HashSet;
@@ -42,9 +40,13 @@ import javax.net.ssl.SSLSession;
 
 import org.gudy.azureus2.core3.security.SEPasswordListener;
 import org.gudy.azureus2.core3.security.SESecurityManager;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException;
 
 import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
 import com.aelitis.azureus.plugins.extseed.ExternalSeedException;
 
 public class 
@@ -54,8 +56,8 @@ ExternalSeedHTTPDownloaderRange
 	public static final String	NL = "\r\n";
 	
 
-	private URL			original_url;
-	private String		user_agent;
+	private final URL		very_original_url;
+	private String			user_agent;
 	
 	private URL			redirected_url;
 	private int			consec_redirect_fails;
@@ -68,14 +70,14 @@ ExternalSeedHTTPDownloaderRange
 		URL		_url,
 		String	_user_agent )
 	{
-		original_url	= _url;
-		user_agent		= _user_agent;
+		very_original_url	= _url;
+		user_agent			= _user_agent;
 	}
 	
 	public URL
 	getURL()
 	{
-		return( original_url );
+		return( very_original_url );
 	}
 	
 	public void
@@ -120,6 +122,10 @@ ExternalSeedHTTPDownloaderRange
 				
 		String	outcome = "";
 		
+		PluginProxy		plugin_proxy	= null;
+		
+		boolean proxy_ok = false;
+		
 		try{
 			SESecurityManager.setThreadPasswordHandler( this );
 			
@@ -134,16 +140,45 @@ ExternalSeedHTTPDownloaderRange
 			int					response;
 			
 			Set<String>	redirect_urls = new HashSet<String>();
-						
+							
 redirect_loop:
 			while( true ){
+
+				URL	original_url 	= redirected_url==null?very_original_url:redirected_url;
+				URL current_url		= original_url;
 				
-				URL	target = redirected_url==null?original_url:redirected_url;
+				if ( plugin_proxy != null ){
+					
+					plugin_proxy.setOK( true );
+					
+					plugin_proxy = null;
+				}
+				
+				Proxy	current_proxy = null;
+				
+				if ( AENetworkClassifier.categoriseAddress( original_url.getHost()) != AENetworkClassifier.AT_PUBLIC ){
+					
+					plugin_proxy = AEProxyFactory.getPluginProxy( "webseed", original_url );
+					
+					if ( plugin_proxy != null ){
+						
+						current_url		= plugin_proxy.getURL();
+				
+						current_proxy	= plugin_proxy.getProxy();
+					}
+				}
 				
 				for ( int ssl_loop=0; ssl_loop<2; ssl_loop++ ){
 					
 					try{
-						connection = (HttpURLConnection)target.openConnection();
+						if ( current_proxy == null ){
+							
+							connection = (HttpURLConnection)current_url.openConnection();
+							
+						}else{
+							
+							connection = (HttpURLConnection)current_url.openConnection( current_proxy );
+						}
 						
 						if ( connection instanceof HttpsURLConnection ){
 							
@@ -172,6 +207,11 @@ redirect_loop:
 							connection.setRequestProperty( prop_names[i], prop_values[i] );
 						}
 						
+						if ( plugin_proxy != null ){
+							
+							connection.setRequestProperty( "HOST", plugin_proxy.getURLHostRewrite() + (original_url.getPort()==-1?"":(":" + original_url.getPort())));
+						}
+
 						int	time_remaining	= listener.getPermittedTime();
 						
 						if ( time_remaining > 0 ){
@@ -242,7 +282,7 @@ redirect_loop:
 						
 						if ( ssl_loop == 0 ){
 							
-							if ( SESecurityManager.installServerCertificates( target ) != null ){
+							if ( SESecurityManager.installServerCertificates( current_url ) != null ){
 								
 									// certificate has been installed
 								
@@ -259,11 +299,14 @@ redirect_loop:
 				}
 			}
 			
-			URL final_url = connection.getURL();
-			
-			if ( consec_redirect_fails < 10 && !original_url.toExternalForm().equals( final_url.toExternalForm())){
+			if ( plugin_proxy == null ){
+				
+				URL final_url = connection.getURL();
 				
-				redirected_url = final_url;
+				if ( consec_redirect_fails < 10 && !very_original_url.toExternalForm().equals( final_url.toExternalForm())){
+					
+					redirected_url = final_url;
+				}
 			}
 			
 			last_response	= response;
@@ -293,6 +336,8 @@ redirect_loop:
             
 			is = connection.getInputStream();
 			
+			proxy_ok = true;
+
 			if ( 	response == HttpURLConnection.HTTP_ACCEPTED || 
 					response == HttpURLConnection.HTTP_OK ||
 					response == HttpURLConnection.HTTP_PARTIAL ){
@@ -438,6 +483,11 @@ redirect_loop:
 					
 				}
 			}
+						
+			if ( plugin_proxy != null ){
+				
+				plugin_proxy.setOK( proxy_ok );
+			}
 		}
 	}
 	
@@ -466,10 +516,13 @@ redirect_loop:
 		
 		boolean	connected = false;
 		
-		try{				
+		PluginProxy		plugin_proxy 	= null;
+		boolean			proxy_ok		= 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 +
+				"GET " + very_original_url.getPath() + "?" + very_original_url.getQuery() + " HTTP/1.1" + NL +
+				"Host: " + very_original_url.getHost() + (very_original_url.getPort()==-1?"":( ":" + very_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;
@@ -483,19 +536,54 @@ redirect_loop:
 			
 			int	time_remaining	= listener.getPermittedTime();
 			
+			URL	original_url 	= very_original_url;
+			URL current_url		= original_url;	
+	
+			Proxy	current_proxy = null;
+			
+			if ( AENetworkClassifier.categoriseAddress( very_original_url.getHost()) != AENetworkClassifier.AT_PUBLIC ){
+				
+				plugin_proxy = AEProxyFactory.getPluginProxy( "webseed", original_url );
+				
+				if ( plugin_proxy != null ){
+					
+					current_url		= plugin_proxy.getURL();
+			
+					current_proxy	= plugin_proxy.getProxy();
+				}
+			}
+		
 			if ( time_remaining > 0 ){
 				
-				socket = new Socket();
+				if ( current_proxy == null ){
+				
+					socket = new Socket();
+					
+				}else{
+					
+					socket = new Socket( current_proxy );
+				}
 				
-				socket.connect( new InetSocketAddress( original_url.getHost(), original_url.getPort()==-1?original_url.getDefaultPort():original_url.getPort()), time_remaining );
+				socket.connect( new InetSocketAddress( current_url.getHost(), current_url.getPort()==-1?current_url.getDefaultPort():current_url.getPort()), time_remaining );
 				
 			}else{
 		
-				socket = new Socket(  original_url.getHost(), original_url.getPort()==-1?original_url.getDefaultPort():original_url.getPort());
+				if ( current_proxy == null ){
+				
+					socket = new Socket(  current_url.getHost(), current_url.getPort()==-1?current_url.getDefaultPort():current_url.getPort());
+					
+				}else{
+					
+					socket = new Socket( current_proxy );
+
+					socket.connect( new InetSocketAddress( current_url.getHost(), current_url.getPort()==-1?current_url.getDefaultPort():current_url.getPort()));
+				}
 			}
 			
 			connected	= true;
 			
+			proxy_ok = true;
+			
 			time_remaining	= listener.getPermittedTime();
 
 			if ( time_remaining < 0 ){
@@ -707,6 +795,11 @@ redirect_loop:
 				}catch( Throwable e ){
 				}
 			}
+			
+			if ( plugin_proxy != null ){
+				
+				plugin_proxy.setOK( proxy_ok );
+			}
 		}
 	}
 	
diff --git a/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPlugin.java
index 222c774..79cf2e4 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -24,6 +21,8 @@ package com.aelitis.azureus.plugins.magnet;
 
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
+import java.net.NoRouteToHostException;
+import java.net.Proxy;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -32,11 +31,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.net.InetSocketAddress;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.torrent.TOTorrent;
 import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLGroup;
 import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
 import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
 import org.gudy.azureus2.core3.util.AEMonitor;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.AERunnable;
 import org.gudy.azureus2.core3.util.AESemaphore;
 import org.gudy.azureus2.core3.util.AEThread2;
@@ -82,7 +84,13 @@ import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
 import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter;
 import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException;
 import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
 
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
 import com.aelitis.azureus.core.util.CopyOnWriteList;
 import com.aelitis.azureus.core.util.FeatureAvailability;
 import com.aelitis.net.magneturi.*;
@@ -158,6 +166,9 @@ MagnetPlugin
 					Torrent torrent;
 					String name;
 					Object ds = ((TableRow)_target).getDataSource();
+					
+					Download download = null;
+					
 					if (ds instanceof ShareResourceFile) {
 						try {
 							torrent = ((ShareResourceFile) ds).getItem().getTorrent();
@@ -173,7 +184,7 @@ MagnetPlugin
 							}
 							name = ((ShareResourceDir) ds).getName();
 					} else if (ds instanceof Download) {
-						Download download = (Download)((TableRow)_target).getDataSource();
+						download = (Download)((TableRow)_target).getDataSource();
 						torrent = download.getTorrent();
 						name = download.getName();
 					} else {
@@ -181,7 +192,20 @@ MagnetPlugin
 					}
 				  
 					
-					String cb_data = UrlUtils.getMagnetURI( name, torrent );
+					String cb_data = download==null?UrlUtils.getMagnetURI( name, torrent ):UrlUtils.getMagnetURI( download);
+					
+					if ( download != null ){
+						
+						List<Tag> tags = TagManagerFactory.getTagManager().getTagsForTaggable( TagType.TT_DOWNLOAD_MANUAL, PluginCoreUtils.unwrap( download ));
+						
+						for ( Tag tag: tags ){
+							
+							if ( tag.isPublic()){
+								
+								cb_data += "&tag=" + UrlUtils.encode( tag.getTagName( true ));
+							}
+						}
+					}
 					
 					// removed this as well - nothing wrong with allowing magnet copy
 					// for private torrents - they still can't be tracked if you don't
@@ -315,7 +339,7 @@ MagnetPlugin
 								
 								byte[] torrent_data = torrent.writeToBEncodedData();
 								
-								torrent_data = addTrackersAndWebSeeds( torrent_data, args );
+								torrent_data = addTrackersAndWebSeedsEtc( torrent_data, args, new HashSet<String>());
 								
 								return( torrent_data);
 							}
@@ -578,22 +602,42 @@ MagnetPlugin
 	
 		throws MagnetURIHandlerException
 	{
-		byte[]	torrent_data = downloadSupport( listener, hash, args, sources, timeout, flags );
+		DownloadResult result = downloadSupport( listener, hash, args, sources, timeout, flags );
+		
+		if ( result == null ){
+		
+			return( null );
+		}
+		
+		return( addTrackersAndWebSeedsEtc( result, args  ));
+	}
+	
+	private byte[]
+	addTrackersAndWebSeedsEtc(
+		DownloadResult		result,
+		String				args )
+	{
+		byte[]		torrent_data 	= result.getTorrentData();
+		Set<String>	networks		= result.getNetworks();
 		
-		return( addTrackersAndWebSeeds( torrent_data, args  ));
+		return( addTrackersAndWebSeedsEtc( torrent_data, args, networks ));
 	}
 	
 	private byte[]
-	addTrackersAndWebSeeds(
-		byte[]		torrent_data,
-		String		args )
+	addTrackersAndWebSeedsEtc(
+		byte[]			torrent_data,
+		String			args,
+		Set<String>		networks )
 	{
+		List<String>	new_web_seeds 	= new ArrayList<String>();
+		List<String>	new_trackers 	= new ArrayList<String>();
+
+		Set<String>	tags			= new HashSet<String>();
+		
 		if ( args != null ){
 			
 			String[] bits = args.split( "&" );
 			
-			List<String>	new_web_seeds 	= new ArrayList<String>();
-			List<String>	new_trackers 	= new ArrayList<String>();
 
 			for ( String bit: bits ){
 				
@@ -617,119 +661,136 @@ MagnetPlugin
 							
 						}catch( Throwable e ){							
 						}
+					}else if ( lhs.equals( "tag" )){
+						
+						tags.add( x[1] );
 					}
 				}
 			}
+		}
+			
+		if ( new_web_seeds.size() > 0 || new_trackers.size() > 0 || networks.size() > 0 ){
 			
-			if ( new_web_seeds.size() > 0 || new_trackers.size() > 0 ){
+			try{
+				TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedByteArray( torrent_data );
+
+				boolean	update_torrent = false;
 				
-				try{
-					TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedByteArray( torrent_data );
-	
-					boolean	update_torrent = false;
+				if ( new_web_seeds.size() > 0 ){
 					
-					if ( new_web_seeds.size() > 0 ){
-						
-						Object obj = torrent.getAdditionalProperty( "url-list" );
+					Object obj = torrent.getAdditionalProperty( "url-list" );
+					
+					List<String> existing = new ArrayList<String>();
+					
+					if ( obj instanceof byte[] ){
+		                
+						try{
+							new_web_seeds.remove( new URL( new String((byte[])obj, "UTF-8" )).toExternalForm());
+							
+						}catch( Throwable e ){							
+						}
+					}else if ( obj instanceof List ){
 						
-						List<String> existing = new ArrayList<String>();
+						List<byte[]> l = (List<byte[]>)obj;
 						
-						if ( obj instanceof byte[] ){
-			                
+						for ( byte[] b: l ){
+							
 							try{
-								new_web_seeds.remove( new URL( new String((byte[])obj, "UTF-8" )).toExternalForm());
+								existing.add( new URL( new String((byte[])b, "UTF-8" )).toExternalForm());
 								
 							}catch( Throwable e ){							
 							}
-						}else if ( obj instanceof List ){
+						}
+					}
+					
+					boolean update_ws = false;
+					
+					for ( String e: new_web_seeds ){
+						
+						if ( !existing.contains( e )){
 							
-							List<byte[]> l = (List<byte[]>)obj;
+							existing.add( e );
 							
-							for ( byte[] b: l ){
-								
-								try{
-									existing.add( new URL( new String((byte[])b, "UTF-8" )).toExternalForm());
-									
-								}catch( Throwable e ){							
-								}
-							}
+							update_ws = true;
 						}
+					}
+					
+					if ( update_ws ){
+					
+						List<byte[]>	l = new ArrayList<byte[]>();
 						
-						boolean update_ws = false;
-						
-						for ( String e: new_web_seeds ){
+						for ( String s: existing ){
 							
-							if ( !existing.contains( e )){
-								
-								existing.add( e );
-								
-								update_ws = true;
-							}
+							l.add( s.getBytes( "UTF-8" ));
 						}
 						
-						if ( update_ws ){
+						torrent.setAdditionalProperty( "url-list", l );
 						
-							List<byte[]>	l = new ArrayList<byte[]>();
-							
-							for ( String s: existing ){
-								
-								l.add( s.getBytes( "UTF-8" ));
-							}
-							
-							torrent.setAdditionalProperty( "url-list", l );
-							
-							update_torrent = true;
+						update_torrent = true;
+					}
+				}
+				
+				if ( new_trackers.size() > 0 ){
+											
+					URL announce_url = torrent.getAnnounceURL();
+												
+					new_trackers.remove( announce_url.toExternalForm());
+					
+					TOTorrentAnnounceURLGroup group = torrent.getAnnounceURLGroup();
+					
+					TOTorrentAnnounceURLSet[] sets = group.getAnnounceURLSets();
+					
+					for ( TOTorrentAnnounceURLSet set: sets ){
+						
+						URL[] set_urls = set.getAnnounceURLs();
+						
+						for( URL set_url: set_urls ){
+																																	
+							new_trackers.remove( set_url.toExternalForm());
 						}
 					}
 					
 					if ( new_trackers.size() > 0 ){
-												
-						URL announce_url = torrent.getAnnounceURL();
-													
-						new_trackers.remove( announce_url.toExternalForm());
-						
-						TOTorrentAnnounceURLGroup group = torrent.getAnnounceURLGroup();
 						
-						TOTorrentAnnounceURLSet[] sets = group.getAnnounceURLSets();
+						TOTorrentAnnounceURLSet[]	new_sets = new TOTorrentAnnounceURLSet[ sets.length + new_trackers.size()];
 						
-						for ( TOTorrentAnnounceURLSet set: sets ){
+						for ( int i=0;i<sets.length;i++){
 							
-							URL[] set_urls = set.getAnnounceURLs();
-							
-							for( URL set_url: set_urls ){
-																																		
-								new_trackers.remove( set_url.toExternalForm());
-							}
+							new_sets[i] = sets[i];
 						}
 						
-						if ( new_trackers.size() > 0 ){
-							
-							TOTorrentAnnounceURLSet[]	new_sets = new TOTorrentAnnounceURLSet[ sets.length + new_trackers.size()];
-							
-							for ( int i=0;i<sets.length;i++){
-								
-								new_sets[i] = sets[i];
-							}
-							
-							for ( int i=0;i<new_trackers.size();i++){
-								
-								TOTorrentAnnounceURLSet new_set = group.createAnnounceURLSet( new URL[]{ new URL( new_trackers.get(i))});
-								
-								new_sets[i+sets.length] = new_set;
-							}
+						for ( int i=0;i<new_trackers.size();i++){
 							
-							group.setAnnounceURLSets( new_sets );
+							TOTorrentAnnounceURLSet new_set = group.createAnnounceURLSet( new URL[]{ new URL( new_trackers.get(i))});
 							
-							update_torrent = true;
+							new_sets[i+sets.length] = new_set;
 						}
-					}
-					
-					if ( update_torrent ){
 						
-						torrent_data = BEncoder.encode( torrent.serialiseToMap());
+						group.setAnnounceURLSets( new_sets );
+						
+						update_torrent = true;
 					}
-				}catch( Throwable e ){
 				}
+				
+				if ( networks.size() > 0 ){
+						
+					TorrentUtils.setNetworkCache( torrent, new ArrayList<String>( networks ));
+
+					update_torrent = true;
+				}
+				
+				if ( tags.size() > 0 ){
+					
+					TorrentUtils.setTagCache( torrent, new ArrayList<String>( tags ));
+
+					update_torrent = true;
+				}
+				
+				if ( update_torrent ){
+					
+					torrent_data = BEncoder.encode( torrent.serialiseToMap());
+				}
+			}catch( Throwable e ){
 			}
 		}
 		
@@ -741,14 +802,14 @@ MagnetPlugin
 	private static class
 	DownloadActivity
 	{
-		private volatile byte[]						result;
+		private volatile DownloadResult				result;
 		private volatile MagnetURIHandlerException	error;
 		
 		private AESemaphore		sem = new AESemaphore( "MP:DA" );
 		
 		public void
 		setResult(
-			byte[]	_result )
+			DownloadResult	_result )
 		{
 			result	= _result;
 			
@@ -771,7 +832,7 @@ MagnetPlugin
 			sem.releaseForever();
 		}
 		
-		public byte[]
+		public DownloadResult
 		getResult()
 		
 			throws MagnetURIHandlerException
@@ -787,7 +848,7 @@ MagnetPlugin
 		}
 	}
 	
-	private byte[]
+	private DownloadResult
  	downloadSupport(
  		MagnetPluginProgressListener	listener,
  		byte[]							hash,
@@ -840,7 +901,7 @@ MagnetPlugin
 
  	}
 	
-	private byte[]
+	private DownloadResult
 	_downloadSupport(
 		final MagnetPluginProgressListener		listener,
 		final byte[]							hash,
@@ -853,6 +914,8 @@ MagnetPlugin
 	{
 		boolean	md_enabled;
 		
+		final boolean	dummy_hash = Arrays.equals( hash, new byte[20] );
+		
 		if ((flags & FL_DISABLE_MD_LOOKUP) != 0 ){
 			
 			md_enabled = false;
@@ -862,13 +925,181 @@ MagnetPlugin
 			md_enabled = md_lookup.getValue() && FeatureAvailability.isMagnetMDEnabled();
 		}
 
+		final byte[][]		result_holder 	= { null };
+		final Throwable[] 	result_error 	= { null };
+
 		TimerEvent							md_delay_event = null;
-		final byte[][]						md_result = { null };
-		final Throwable[] 					md_error = { null };
 		final MagnetPluginMDDownloader[]	md_downloader = { null };
 		
-		final byte[][]						fl_result = { null };
+		boolean	net_pub_default = COConfigurationManager.getBooleanParameter( "Network Selection Default." + AENetworkClassifier.AT_PUBLIC );
+		
+		final Set<String>	networks_enabled;
+		
+		final Set<String>	additional_networks = new HashSet<String>();
+
+		if ( args != null ){
+			
+			String[] bits = args.split( "&" );
+			
+			List<URL>	fl_args 	= new ArrayList<URL>();
+			
+			Set<String>	tr_networks 		= new HashSet<String>();
+			Set<String>	explicit_networks 	= new HashSet<String>();
+
+			for ( String bit: bits ){
+				
+				if ( bit.startsWith( "maggot_sha1" )){
+
+					tr_networks.clear();
+					
+					explicit_networks.clear();
+					
+					fl_args.clear();
+					
+					explicit_networks.add( AENetworkClassifier.AT_I2P  );
+					
+					break;
+				}
+					
+				String[] x = bit.split( "=" );
+				
+				if ( x.length == 2 ){
+					
+					String	lhs = x[0].toLowerCase();
+					
+					if ( lhs.equals( "fl" )){
+						
+						try{
+							URL url = new URL( UrlUtils.decode( x[1] ));
+							
+							fl_args.add(url );
+							
+							tr_networks.add( AENetworkClassifier.categoriseAddress( url.getHost()));
 
+						}catch( Throwable e ){							
+						}
+					}else if ( lhs.equals( "tr" )){
+						
+						try{
+							tr_networks.add( AENetworkClassifier.categoriseAddress( new URL( UrlUtils.decode( x[1] )).getHost()));
+							
+						}catch( Throwable e ){							
+						}
+					}else if ( lhs.equals( "net" )){
+						
+						String network = AENetworkClassifier.internalise( x[1] );
+						
+						if ( network != null ){
+							
+							explicit_networks.add( network );
+						}
+					}
+				}
+			}
+			
+			networks_enabled = explicit_networks.size()>0?explicit_networks:tr_networks;
+			
+			if ( net_pub_default ){
+				
+				if ( networks_enabled.size() == 0 ){
+					
+					networks_enabled.add( AENetworkClassifier.AT_PUBLIC );
+				}
+			}else{
+				
+				networks_enabled.remove( AENetworkClassifier.AT_PUBLIC );
+			}
+			
+			if ( fl_args.size() > 0 ){
+				
+				final AESemaphore fl_sem = new AESemaphore( "fl_sem" );
+				
+				int	fl_run = 0;
+				
+				for ( int i=0;i<fl_args.size() && i < 3; i++ ){
+					
+					final URL fl_url = fl_args.get( i );
+					
+					String url_net = AENetworkClassifier.categoriseAddress( fl_url.getHost());
+					
+					if ( networks_enabled.contains( url_net )){
+						
+						new AEThread2( "Magnet:fldl", true )
+						{
+							public void 
+							run() 
+							{
+								try{
+									TOTorrent torrent = TorrentUtils.download( fl_url, timeout );
+									
+									if ( torrent != null ){
+										
+										if ( dummy_hash || Arrays.equals( torrent.getHash(), hash )){
+											
+											synchronized( result_holder ){
+												
+												result_holder[0] = BEncoder.encode( torrent.serialiseToMap());
+											}
+										}
+									}
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+									
+								}finally{
+									
+									fl_sem.release();
+								}
+							}
+						}.start();
+						
+						fl_run++;
+					}
+				}
+			
+				if ( dummy_hash ){
+						
+					long	remaining = timeout;
+					
+					for ( int i=0; i<fl_run && remaining>0; i++ ){
+					
+						long	start = SystemTime.getMonotonousTime();
+						
+						if ( !fl_sem.reserve( remaining )){
+							
+							break;
+						}
+					
+						remaining -= (SystemTime.getMonotonousTime() - start );
+						
+						synchronized( result_holder ){
+						
+							if ( result_holder[0] != null ){
+							
+								return( new DownloadResult( result_holder[0], networks_enabled, additional_networks ));
+							}
+						}
+					}	
+				}
+			}
+		}else{
+				
+			networks_enabled = new HashSet<String>();
+			
+			if ( net_pub_default ){
+									
+				networks_enabled.add( AENetworkClassifier.AT_PUBLIC );
+			}
+		}
+		
+		if ( dummy_hash ){
+		
+			return( null );
+		}
+		
+			// networks-enabled has either the networks inferrable from the magnet set up
+			// or, if none, then public (but only if public is enabled by default )
+				
 		if ( md_enabled ){
 			
 			int	delay_millis = md_lookup_delay.getValue()*1000;
@@ -892,7 +1123,7 @@ MagnetPlugin
 									return;
 								}
 								
-								md_downloader[0] = mdd = new MagnetPluginMDDownloader( plugin_interface, hash, args );
+								md_downloader[0] = mdd = new MagnetPluginMDDownloader( plugin_interface, hash, networks_enabled, sources, args );
 							}
 							
 							listener.reportActivity( getMessageText( "report.md.starts" ));
@@ -912,14 +1143,17 @@ MagnetPlugin
 									
 									public void
 									complete(
-										TOTorrent	torrent )
+										TOTorrent		torrent,
+										Set<String>		peer_networks )
 									{
 										listener.reportActivity( getMessageText( "report.md.done" ));
 										
-										synchronized( md_result ){
+										synchronized( result_holder ){
 										
+											additional_networks.addAll( peer_networks );
+											
 											try{
-												md_result[0] = BEncoder.encode( torrent.serialiseToMap());
+												result_holder[0] = BEncoder.encode( torrent.serialiseToMap());
 												
 											}catch( Throwable e ){
 												
@@ -934,9 +1168,9 @@ MagnetPlugin
 									{
 										listener.reportActivity( getMessageText( "report.error", Debug.getNestedExceptionMessage(e)));
 										
-										synchronized( md_result ){
+										synchronized( result_holder ){
 											
-											md_error[0] = e;
+											result_error[0] = e;
 										}
 									}
 								});
@@ -944,549 +1178,488 @@ MagnetPlugin
 					});
 		}
 		
-		if ( args != null ){
-			
-			String[] bits = args.split( "&" );
-			
-			List<URL>	fl_args 	= new ArrayList<URL>();
 
-			for ( String bit: bits ){
-				
-				String[] x = bit.split( "=" );
+		try{
+			try{
+				long	remaining	= timeout;
+								
+				boolean	sl_enabled				= secondary_lookup.getValue() && FeatureAvailability.isMagnetSLEnabled();
+				boolean	sl_failed				= false;
+				long secondary_lookup_time 	= -1;
+
+				final Object[] secondary_result = { null };
+
+					// public DHT lookup
 				
-				if ( x.length == 2 ){
+				if ( networks_enabled.contains( AENetworkClassifier.AT_PUBLIC )){
 					
-					String	lhs = x[0].toLowerCase();
+					boolean	is_first_download = first_download;
 					
-					if ( lhs.equals( "fl" )){
+					if ( is_first_download ){
+					
+						listener.reportActivity( getMessageText( "report.waiting_ddb" ));
 						
-						try{
-							fl_args.add( new URL( UrlUtils.decode( x[1] )));
-							
-						}catch( Throwable e ){							
-						}
+						first_download = false;
 					}
-				}
-			}
-			
-			if ( fl_args.size() > 0 ){
-				
-				for ( int i=0;i<fl_args.size() && i < 3; i++ ){
-					
-					final URL fl_url = fl_args.get( i );
 					
-					new AEThread2( "Magnet:fldl", true )
-					{
-						public void 
-						run() 
-						{
-							try{
-								TOTorrent torrent = TorrentUtils.download( fl_url );
-								
-								if ( torrent != null ){
-									
-									if ( Arrays.equals( torrent.getHash(), hash )){
-										
-										synchronized( fl_result ){
-											
-											fl_result[0] = BEncoder.encode( torrent.serialiseToMap());
-										}
-									}
-								}
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-						}
-					}.start();
-				}
-			}
-		}
-		
-		try{
-			try{
-				long	remaining	= timeout;
-								
-				boolean	sl_enabled				= secondary_lookup.getValue() && FeatureAvailability.isMagnetSLEnabled();
-				boolean	sl_failed				= false;
-				long secondary_lookup_time 	= -1;
-
-				final Object[] secondary_result = { null };
-
-				boolean	is_first_download = first_download;
+					final DistributedDatabase db = plugin_interface.getDistributedDatabase();
 				
-				if ( is_first_download ){
-				
-					listener.reportActivity( getMessageText( "report.waiting_ddb" ));
-					
-					first_download = false;
-				}
-				
-				final DistributedDatabase db = plugin_interface.getDistributedDatabase();
-				
-				if ( db.isAvailable()){
-					
-					final List			potential_contacts 		= new ArrayList();
-					final AESemaphore	potential_contacts_sem 	= new AESemaphore( "MagnetPlugin:liveones" );
-					final AEMonitor		potential_contacts_mon	= new AEMonitor( "MagnetPlugin:liveones" );
-					
-					final int[]			outstanding		= {0};
-					final boolean[]		lookup_complete	= {false};
-					
-					listener.reportActivity(  getMessageText( "report.searching" ));
-					
-					DistributedDatabaseListener	ddb_listener = 
-						new DistributedDatabaseListener()
-						{
-							private Set	found_set = new HashSet();
-							
-							public void
-							event(
-								DistributedDatabaseEvent 		event )
+					if ( db.isAvailable()){
+						
+						final List			potential_contacts 		= new ArrayList();
+						final AESemaphore	potential_contacts_sem 	= new AESemaphore( "MagnetPlugin:liveones" );
+						final AEMonitor		potential_contacts_mon	= new AEMonitor( "MagnetPlugin:liveones" );
+						
+						final int[]			outstanding		= {0};
+						final boolean[]		lookup_complete	= {false};
+						
+						listener.reportActivity(  getMessageText( "report.searching" ));
+						
+						DistributedDatabaseListener	ddb_listener = 
+							new DistributedDatabaseListener()
 							{
-								int	type = event.getType();
+								private Set	found_set = new HashSet();
+								
+								public void
+								event(
+									DistributedDatabaseEvent 		event )
+								{
+									int	type = event.getType();
+				
+									if ( type == DistributedDatabaseEvent.ET_OPERATION_STARTS ){
 			
-								if ( type == DistributedDatabaseEvent.ET_OPERATION_STARTS ){
-		
-										// give live results a chance before kicking in explicit ones
-									
-									if ( sources.length > 0 ){
+											// give live results a chance before kicking in explicit ones
 										
-										new DelayedEvent(
-											"MP:sourceAdd",
-											10*1000,
-											new AERunnable()
-											{
-												public void
-												runSupport()
+										if ( sources.length > 0 ){
+											
+											new DelayedEvent(
+												"MP:sourceAdd",
+												10*1000,
+												new AERunnable()
 												{
-													addExplicitSources();
-												}
-											});
-									}
-									
-								}else if ( type == DistributedDatabaseEvent.ET_VALUE_READ ){
-															
-									contactFound( event.getValue().getContact());
-					
-								}else if (	type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ||
-											type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ){
+													public void
+													runSupport()
+													{
+														addExplicitSources();
+													}
+												});
+										}
 										
-									listener.reportActivity( getMessageText( "report.found", String.valueOf( found_set.size())));
-									
-										// now inject any explicit sources
-		
-									addExplicitSources();
-									
-									try{
-										potential_contacts_mon.enter();													
-		
-										lookup_complete[0] = true;
+									}else if ( type == DistributedDatabaseEvent.ET_VALUE_READ ){
+																
+										contactFound( event.getValue().getContact());
+						
+									}else if (	type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ||
+												type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ){
+											
+										listener.reportActivity( getMessageText( "report.found", String.valueOf( found_set.size())));
 										
-									}finally{
+											// now inject any explicit sources
+			
+										addExplicitSources();
 										
-										potential_contacts_mon.exit();
+										try{
+											potential_contacts_mon.enter();													
+			
+											lookup_complete[0] = true;
+											
+										}finally{
+											
+											potential_contacts_mon.exit();
+										}
+										
+										potential_contacts_sem.release();
 									}
-									
-									potential_contacts_sem.release();
 								}
-							}
-							
-							protected void
-							addExplicitSources()
-							{	
-								for (int i=0;i<sources.length;i++){
-									
-									try{
-										contactFound( db.importContact(sources[i]));
-										
-									}catch( Throwable e ){
+								
+								protected void
+								addExplicitSources()
+								{	
+									for (int i=0;i<sources.length;i++){
 										
-										Debug.printStackTrace(e);
+										try{
+											contactFound( db.importContact(sources[i]));
+											
+										}catch( Throwable e ){
+											
+											Debug.printStackTrace(e);
+										}
 									}
 								}
-							}
-							
-							public void
-							contactFound(
-								final DistributedDatabaseContact	contact )
-							{
-								String	key = contact.getAddress().toString();
 								
-								synchronized( found_set ){
+								public void
+								contactFound(
+									final DistributedDatabaseContact	contact )
+								{
+									String	key = contact.getAddress().toString();
 									
-									if ( found_set.contains( key )){
+									synchronized( found_set ){
+										
+										if ( found_set.contains( key )){
+											
+											return;
+										}
 										
-										return;
+										found_set.add( key );
 									}
 									
-									found_set.add( key );
-								}
-								
-								if ( listener.verbose()){
-								
-									listener.reportActivity( getMessageText( "report.found", contact.getName()));
-								}
-								
-								try{
-									potential_contacts_mon.enter();													
-		
-									outstanding[0]++;
+									if ( listener.verbose()){
 									
-								}finally{
+										listener.reportActivity( getMessageText( "report.found", contact.getName()));
+									}
 									
-									potential_contacts_mon.exit();
-								}
-								
-								contact.isAlive(
-									20*1000,
-									new DistributedDatabaseListener()
-									{
-										public void 
-										event(
-											DistributedDatabaseEvent event) 
+									try{
+										potential_contacts_mon.enter();													
+			
+										outstanding[0]++;
+										
+									}finally{
+										
+										potential_contacts_mon.exit();
+									}
+									
+									contact.isAlive(
+										20*1000,
+										new DistributedDatabaseListener()
 										{
-											try{
-												boolean	alive = event.getType() == DistributedDatabaseEvent.ET_OPERATION_COMPLETE;
-													
-												if ( listener.verbose()){
-												
-													listener.reportActivity( 
-														getMessageText( alive?"report.alive":"report.dead",	contact.getName()));
-												}
-												
+											public void 
+											event(
+												DistributedDatabaseEvent event) 
+											{
 												try{
-													potential_contacts_mon.enter();
-													
-													Object[]	entry = new Object[]{ new Boolean( alive ), contact};
+													boolean	alive = event.getType() == DistributedDatabaseEvent.ET_OPERATION_COMPLETE;
+														
+													if ( listener.verbose()){
 													
-													boolean	added = false;
+														listener.reportActivity( 
+															getMessageText( alive?"report.alive":"report.dead",	contact.getName()));
+													}
 													
-													if ( alive ){
+													try{
+														potential_contacts_mon.enter();
 														
-															// try and place before first dead entry 
-												
-														for (int i=0;i<potential_contacts.size();i++){
+														Object[]	entry = new Object[]{ new Boolean( alive ), contact};
+														
+														boolean	added = false;
+														
+														if ( alive ){
 															
-															if (!((Boolean)((Object[])potential_contacts.get(i))[0]).booleanValue()){
-																
-																potential_contacts.add(i, entry );
-																
-																added = true;
+																// try and place before first dead entry 
+													
+															for (int i=0;i<potential_contacts.size();i++){
 																
-																break;
+																if (!((Boolean)((Object[])potential_contacts.get(i))[0]).booleanValue()){
+																	
+																	potential_contacts.add(i, entry );
+																	
+																	added = true;
+																	
+																	break;
+																}
 															}
 														}
-													}
-													
-													if ( !added ){
 														
-														potential_contacts.add( entry );	// dead at end
+														if ( !added ){
+															
+															potential_contacts.add( entry );	// dead at end
+														}
+															
+													}finally{
+															
+														potential_contacts_mon.exit();
 													}
-														
 												}finally{
-														
-													potential_contacts_mon.exit();
-												}
-											}finally{
-												
-												try{
-													potential_contacts_mon.enter();													
-		
-													outstanding[0]--;
 													
-												}finally{
+													try{
+														potential_contacts_mon.enter();													
+			
+														outstanding[0]--;
+														
+													}finally{
+														
+														potential_contacts_mon.exit();
+													}
 													
-													potential_contacts_mon.exit();
+													potential_contacts_sem.release();
 												}
-												
-												potential_contacts_sem.release();
 											}
-										}
-									});
-							}
-						};
-						
-					db.read(
-						ddb_listener,
-						db.createKey( hash, "Torrent download lookup for '" + ByteFormatter.encodeString( hash ) + "'" ),
-						timeout,
-						DistributedDatabase.OP_EXHAUSTIVE_READ | DistributedDatabase.OP_PRIORITY_HIGH );
-										
-					long 	overall_start 			= SystemTime.getMonotonousTime();					
-					long 	last_found 				= -1;
-										
-					AsyncDispatcher	dispatcher = new AsyncDispatcher();
-					
-					while( remaining > 0 ){
-						
-						try{
-							potential_contacts_mon.enter();
-		
-							if ( 	lookup_complete[0] && 
-									potential_contacts.size() == 0 &&
-									outstanding[0] == 0 ){
-								
-								break;
-							}
-						}finally{
+										});
+								}
+							};
 							
-							potential_contacts_mon.exit();
-						}
-										
+						db.read(
+							ddb_listener,
+							db.createKey( hash, "Torrent download lookup for '" + ByteFormatter.encodeString( hash ) + "'" ),
+							timeout,
+							DistributedDatabase.OP_EXHAUSTIVE_READ | DistributedDatabase.OP_PRIORITY_HIGH );
+											
+						long 	overall_start 			= SystemTime.getMonotonousTime();					
+						long 	last_found 				= -1;
+											
+						AsyncDispatcher	dispatcher = new AsyncDispatcher();
 						
 						while( remaining > 0 ){
-						
-							if ( listener.cancelled()){
-								
-								return( null );
-							}
 							
-							synchronized( md_result ){
-								
-								if ( md_result[0] != null ){
+							try{
+								potential_contacts_mon.enter();
+			
+								if ( 	lookup_complete[0] && 
+										potential_contacts.size() == 0 &&
+										outstanding[0] == 0 ){
 									
-									return( md_result[0] );
+									break;
 								}
+							}finally{
+								
+								potential_contacts_mon.exit();
 							}
 											
-							synchronized( fl_result ){
+							
+							while( remaining > 0 ){
+							
+								if ( listener.cancelled()){
+									
+									return( null );
+								}
 								
-								if ( fl_result[0] != null ){
+								synchronized( result_holder ){
 									
-									return( fl_result[0] );
+									if ( result_holder[0] != null ){
+										
+										return( new DownloadResult( result_holder[0], networks_enabled, additional_networks ));
+									}
 								}
-							}
-							
-							long wait_start = SystemTime.getMonotonousTime();
-		
-							boolean got_sem = potential_contacts_sem.reserve( 1000 );
-				
-							long now = SystemTime.getMonotonousTime();
-							
-							remaining -= ( now - wait_start );
-						
-							if ( got_sem ){
-							
-								last_found = now;
 								
-								break;
+								long wait_start = SystemTime.getMonotonousTime();
+			
+								boolean got_sem = potential_contacts_sem.reserve( 1000 );
+					
+								long now = SystemTime.getMonotonousTime();
 								
-							}else{
+								remaining -= ( now - wait_start );
+							
+								if ( got_sem ){
 								
-								if ( sl_enabled ){
+									last_found = now;
 									
-									if ( secondary_lookup_time == -1 ){
+									break;
 									
-										long	base_time;
-										
-										if ( last_found == -1 || now - overall_start > 60*1000 ){
-											
-											base_time = overall_start;
-											
-										}else{
-											
-											base_time = last_found;
-										}
+								}else{
+									
+									if ( sl_enabled ){
 										
-										long	time_so_far = now - base_time;
+										if ( secondary_lookup_time == -1 ){
 										
-										if ( time_so_far > SECONDARY_LOOKUP_DELAY ){
+											long	base_time;
 											
-											secondary_lookup_time = SystemTime.getMonotonousTime();
+											if ( last_found == -1 || now - overall_start > 60*1000 ){
+												
+												base_time = overall_start;
+												
+											}else{
+												
+												base_time = last_found;
+											}
 											
-											doSecondaryLookup( listener, secondary_result, hash, args );
-										}
-									}else{
-										
-										try{
-											byte[] torrent = getSecondaryLookupResult( secondary_result );
+											long	time_so_far = now - base_time;
 											
-											if ( torrent != null ){
+											if ( time_so_far > SECONDARY_LOOKUP_DELAY ){
 												
-												return( torrent );
+												secondary_lookup_time = SystemTime.getMonotonousTime();
+												
+												doSecondaryLookup( listener, secondary_result, hash, networks_enabled, args );
 											}
-										}catch( ResourceDownloaderException e ){
-											
-											sl_failed = true;
+										}else{
 											
-											// ignore, we just continue processing
+											try{
+												byte[] torrent = getSecondaryLookupResult( secondary_result );
+												
+												if ( torrent != null ){
+													
+													return( new DownloadResult( torrent, networks_enabled, additional_networks ));
+												}
+											}catch( ResourceDownloaderException e ){
+												
+												sl_failed = true;
+												
+												// ignore, we just continue processing
+											}
 										}
 									}
+			
+									continue;
 								}
-		
-								continue;
 							}
-						}
-						
-						final DistributedDatabaseContact	contact;
-						final boolean						live_contact;
-						
-						try{
-							potential_contacts_mon.enter();
 							
-							// System.out.println( "rem=" + remaining + ",pot=" + potential_contacts.size() + ",out=" + outstanding[0] );
+							if ( sl_enabled ){
+								
+									// check before we try another DHT contact
+								
+								try{
+									byte[] torrent = getSecondaryLookupResult( secondary_result );
+									
+									if ( torrent != null ){
+										
+										return( new DownloadResult( torrent, networks_enabled, additional_networks ));
+									}
+								}catch( ResourceDownloaderException e ){
+									
+									sl_failed = true;
+								}
+							}
 							
-							if ( potential_contacts.size() == 0 ){
+							final DistributedDatabaseContact	contact;
+							final boolean						live_contact;
+							
+							try{
+								potential_contacts_mon.enter();
 								
-								if ( outstanding[0] == 0 ){
+								// System.out.println( "rem=" + remaining + ",pot=" + potential_contacts.size() + ",out=" + outstanding[0] );
 								
-									break;
+								if ( potential_contacts.size() == 0 ){
 									
+									if ( outstanding[0] == 0 ){
+									
+										break;
+										
+									}else{
+										
+										continue;
+									}
 								}else{
+								
+									Object[]	entry = (Object[])potential_contacts.remove(0);
 									
-									continue;
+									live_contact 	= ((Boolean)entry[0]).booleanValue(); 
+									contact 		= (DistributedDatabaseContact)entry[1];
 								}
-							}else{
-							
-								Object[]	entry = (Object[])potential_contacts.remove(0);
 								
-								live_contact 	= ((Boolean)entry[0]).booleanValue(); 
-								contact 		= (DistributedDatabaseContact)entry[1];
+							}finally{
+								
+								potential_contacts_mon.exit();
 							}
+								
+							// System.out.println( "magnetDownload: " + contact.getName() + ", live = " + live_contact );
 							
-						}finally{
+							final AESemaphore	contact_sem 	= new AESemaphore( "MD:contact" );
 							
-							potential_contacts_mon.exit();
-						}
-							
-						// System.out.println( "magnetDownload: " + contact.getName() + ", live = " + live_contact );
-						
-						final AESemaphore	contact_sem 	= new AESemaphore( "MD:contact" );
-						final byte[][]		contact_data	= { null };
-						
-						dispatcher.dispatch(
-							new AERunnable()
-							{
-								public void
-								runSupport()
+							dispatcher.dispatch(
+								new AERunnable()
 								{
-									try{
-										if ( !live_contact ){
-											
-											listener.reportActivity( getMessageText( "report.tunnel", contact.getName()));
-						
-											contact.openTunnel();
-										}
-										
+									public void
+									runSupport()
+									{
 										try{
-											listener.reportActivity( getMessageText( "report.downloading", contact.getName()));
+											if ( !live_contact ){
+												
+												listener.reportActivity( getMessageText( "report.tunnel", contact.getName()));
+							
+												contact.openTunnel();
+											}
 											
-											DistributedDatabaseValue	value = 
-												contact.read( 
-														new DistributedDatabaseProgressListener()
-														{
-															public void
-															reportSize(
-																long	size )
-															{
-																listener.reportSize( size );
-															}
-															public void
-															reportActivity(
-																String	str )
-															{
-																listener.reportActivity( str );
-															}
-															
-															public void
-															reportCompleteness(
-																int		percent )
+											try{
+												listener.reportActivity( getMessageText( "report.downloading", contact.getName()));
+												
+												DistributedDatabaseValue	value = 
+													contact.read( 
+															new DistributedDatabaseProgressListener()
 															{
-																listener.reportCompleteness( percent );
-															}
-														},
-														db.getStandardTransferType( DistributedDatabaseTransferType.ST_TORRENT ),
-														db.createKey ( hash , "Torrent download content for '" + ByteFormatter.encodeString( hash ) + "'"),
-														timeout );
+																public void
+																reportSize(
+																	long	size )
+																{
+																	listener.reportSize( size );
+																}
+																public void
+																reportActivity(
+																	String	str )
+																{
+																	listener.reportActivity( str );
+																}
 																
-											if ( value != null ){
-												
-													// let's verify the torrent
-												
-												byte[]	data = (byte[])value.getValue(byte[].class);
-						
-												try{
-													TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedByteArray( data );
+																public void
+																reportCompleteness(
+																	int		percent )
+																{
+																	listener.reportCompleteness( percent );
+																}
+															},
+															db.getStandardTransferType( DistributedDatabaseTransferType.ST_TORRENT ),
+															db.createKey ( hash , "Torrent download content for '" + ByteFormatter.encodeString( hash ) + "'"),
+															timeout );
+																	
+												if ( value != null ){
 													
-													if ( Arrays.equals( hash, torrent.getHash())){
+														// let's verify the torrent
 													
-														listener.reportContributor( contact.getAddress());
-												
-														synchronized( contact_data ){
+													byte[]	data = (byte[])value.getValue(byte[].class);
+							
+													try{
+														TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedByteArray( data );
+														
+														if ( Arrays.equals( hash, torrent.getHash())){
+														
+															listener.reportContributor( contact.getAddress());
+													
+															synchronized( result_holder ){
+																
+																result_holder[0] = data;
+															}												
+														}else{
 															
-															contact_data[0] = data;
-														}												
-													}else{
+															listener.reportActivity( getMessageText( "report.error", "torrent invalid (hash mismatch)" ));
+														}
+													}catch( Throwable e ){
 														
-														listener.reportActivity( getMessageText( "report.error", "torrent invalid (hash mismatch)" ));
+														listener.reportActivity( getMessageText( "report.error", "torrent invalid (decode failed)" ));
 													}
-												}catch( Throwable e ){
-													
-													listener.reportActivity( getMessageText( "report.error", "torrent invalid (decode failed)" ));
 												}
+											}catch( Throwable e ){
+												
+												listener.reportActivity( getMessageText( "report.error", Debug.getNestedExceptionMessage(e)));
+												
+												Debug.printStackTrace(e);
 											}
-										}catch( Throwable e ){
-											
-											listener.reportActivity( getMessageText( "report.error", Debug.getNestedExceptionMessage(e)));
+										}finally{
 											
-											Debug.printStackTrace(e);
+											contact_sem.release();
 										}
-									}finally{
-										
-										contact_sem.release();
 									}
-								}
-							});
-						
-						while( true ){
+								});
 							
-							if ( listener.cancelled()){
+							while( true ){
 								
-								return( null );
-							}
-							
-							boolean got_sem = contact_sem.reserve( 500 );
-														
-							synchronized( contact_data ){
+								if ( listener.cancelled()){
 									
-								if ( contact_data[0] != null ){
-										
-									return( contact_data[0] );
+									return( null );
 								}
-							}
-							
-							synchronized( md_result ){
 								
-								if ( md_result[0] != null ){
+								boolean got_sem = contact_sem.reserve( 500 );
+																							
+								synchronized( result_holder ){
 									
-									return( md_result[0] );
+									if ( result_holder[0] != null ){
+										
+										return( new DownloadResult( result_holder[0], networks_enabled, additional_networks ));
+									}
 								}
-							}
-							
-							synchronized( fl_result ){
 								
-								if ( fl_result[0] != null ){
+								if ( got_sem ){
 									
-									return( fl_result[0] );
+									break;
 								}
 							}
-							
-							if ( got_sem ){
-								
-								break;
-							}
 						}
-					}
-				}else{
-					
-					if ( is_first_download ){
-					
-						listener.reportActivity( getMessageText( "report.ddb_disabled" ));
+					}else{
+						
+						if ( is_first_download ){
+						
+							listener.reportActivity( getMessageText( "report.ddb_disabled" ));
+						}
 					}
 				}
-				
-					// DDB lookup process is complete
+			
+					// DDB lookup process is complete or skipped
 					// If secondary lookup is active/doable then hang around until it completes
 				
 				if ( sl_enabled && !sl_failed ){
@@ -1495,7 +1668,7 @@ MagnetPlugin
 						
 						secondary_lookup_time = SystemTime.getMonotonousTime();
 						
-						doSecondaryLookup(listener, secondary_result, hash, args );
+						doSecondaryLookup(listener, secondary_result, hash, networks_enabled, args );
 					}
 					
 					while( SystemTime.getMonotonousTime() - secondary_lookup_time < SECONDARY_LOOKUP_MAX_TIME ){
@@ -1510,25 +1683,17 @@ MagnetPlugin
 							
 							if ( torrent != null ){
 								
-								return( torrent );
-							}
-							
-							synchronized( md_result ){
-								
-								if ( md_result[0] != null ){
-									
-									return( md_result[0] );
-								}
+								return( new DownloadResult( torrent, networks_enabled, additional_networks ));
 							}
 							
-							synchronized( fl_result ){
+							synchronized( result_holder ){
 								
-								if ( fl_result[0] != null ){
+								if ( result_holder[0] != null ){
 									
-									return( fl_result[0] );
+									return( new DownloadResult( result_holder[0], networks_enabled, additional_networks ));
 								}
 							}
-							
+														
 							Thread.sleep( 500 );
 							
 						}catch( ResourceDownloaderException e ){
@@ -1564,7 +1729,7 @@ MagnetPlugin
 							
 								if ( torrent != null ){
 								
-									return( torrent );
+									return( new DownloadResult( torrent, networks_enabled, additional_networks ));
 								}
 							}catch( ResourceDownloaderException e ){
 								
@@ -1574,26 +1739,18 @@ MagnetPlugin
 							}
 						}
 						
-						synchronized( md_result ){
+						synchronized( result_holder ){
 							
-							if ( md_result[0] != null ){
+							if ( result_holder[0] != null ){
 								
-								return( md_result[0] );
+								return( new DownloadResult( result_holder[0], networks_enabled, additional_networks ));
 							}
 							
-							if ( md_error[0] != null ){
+							if ( result_error[0] != null ){
 								
 								break;
 							}
 						}
-						
-						synchronized( fl_result ){
-							
-							if ( fl_result[0] != null ){
-								
-								return( fl_result[0] );
-							}
-						}
 					}
 				}
 				
@@ -1629,16 +1786,50 @@ MagnetPlugin
 		final MagnetPluginProgressListener		listener,
 		final Object[]							result,
 		byte[]									hash,
-		String									args )
+		Set<String>								networks_enabled,
+		String									args )	
 	{
 		listener.reportActivity( getMessageText( "report.secondarylookup", null ));
 		
+		PluginProxy	plugin_proxy = null;
+
 		try{
+			URL original_sl_url = new URL( SECONDARY_LOOKUP + "magnetLookup?hash=" + Base32.encode( hash ) + (args.length()==0?"":("&args=" + UrlUtils.encode( args ))));
+
+			URL 	sl_url	= original_sl_url;
+			Proxy	proxy	= null;
+												
+			if ( !networks_enabled.contains( AENetworkClassifier.AT_PUBLIC )){
+			
+				plugin_proxy = AEProxyFactory.getPluginProxy( "secondary magnet lookup", sl_url );
+				
+				if ( plugin_proxy == null ){
+					
+					throw( new NoRouteToHostException( "plugin proxy unavailable" ));
+					
+				}else{
+					
+					proxy 	= plugin_proxy.getProxy();
+					sl_url	= plugin_proxy.getURL();							
+				}
+			}
+			
 			ResourceDownloaderFactory rdf = plugin_interface.getUtilities().getResourceDownloaderFactory();
-		
-			URL sl_url = new URL( SECONDARY_LOOKUP + "magnetLookup?hash=" + Base32.encode( hash ) + (args.length()==0?"":("&args=" + UrlUtils.encode( args ))));
+					
+			ResourceDownloader rd;
+			
+			if ( proxy == null ){
+				
+				rd = rdf.create( sl_url );
+				
+			}else{
+				
+				rd = rdf.create( sl_url, proxy );
+				
+				rd.setProperty( "URL_HOST", original_sl_url.getHost());
+			}
 			
-			ResourceDownloader rd = rdf.create( sl_url );
+			final PluginProxy f_pp = plugin_proxy;
 			
 			rd.addListener(
 				new ResourceDownloaderAdapter()
@@ -1648,14 +1839,20 @@ MagnetPlugin
 						ResourceDownloader	downloader,
 						InputStream			data )
 					{
-						listener.reportActivity( getMessageText( "report.secondarylookup.ok", null ));
-
-						synchronized( result ){
-						
-							result[0] = data;
+						try{
+							listener.reportActivity( getMessageText( "report.secondarylookup.ok", null ));
+	
+							synchronized( result ){
+							
+								result[0] = data;
+							}
+							
+							return( true );
+							
+						}finally{
+							
+							complete();
 						}
-						
-						return( true );
 					}
 					
 					public void
@@ -1663,19 +1860,39 @@ MagnetPlugin
 						ResourceDownloader			downloader,
 						ResourceDownloaderException e )
 					{
-						synchronized( result ){
+						try{
+							synchronized( result ){
+								
+								result[0] = e;
+							}
+							
+							listener.reportActivity( getMessageText( "report.secondarylookup.fail" ));
+							
+						}finally{
+							
+							complete();
+						}
+					}
+					
+					private void
+					complete()
+					{
+						if ( f_pp != null ){
 							
-							result[0] = e;
+							f_pp.setOK( true );		// outcome doesn't really indicate whether the result was wholesome
 						}
-						
-						listener.reportActivity( getMessageText( "report.secondarylookup.fail" ));
 					}
 				});
 			
 			rd.asyncDownload();
-			
+				
 		}catch( Throwable e ){
 			
+			if ( plugin_proxy != null ){
+				
+				plugin_proxy.setOK( true );		// tidy up, no indication of proxy badness here so say its ok
+			}
+			
 			listener.reportActivity( getMessageText( "report.secondarylookup.fail", Debug.getNestedExceptionMessage( e ) ));
 		}
 	}
@@ -1750,4 +1967,37 @@ MagnetPlugin
 	{
 		listeners.remove( listener );
 	}
+	
+	private class
+	DownloadResult
+	{
+		private byte[]		data;
+		private Set<String>	networks;
+		
+		private
+		DownloadResult(
+			byte[]			torrent_data,
+			Set<String>		networks_enabled,
+			Set<String>		additional_networks )
+		{
+			data		= torrent_data;
+			
+			networks = new HashSet<String>();
+			
+			networks.addAll( networks_enabled );
+			networks.addAll( additional_networks );
+		}
+		
+		private byte[]
+		getTorrentData()
+		{
+			return( data );
+		}
+		
+		private Set<String>
+		getNetworks()
+		{
+			return( networks );
+		}
+	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginException.java b/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginException.java
index 9553d63..32eca70 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginException.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginListener.java b/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginListener.java
index a11d898..0d23ee6 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 8, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginMDDownloader.java b/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginMDDownloader.java
index 2aeaca2..d7d5248 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginMDDownloader.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginMDDownloader.java
@@ -2,20 +2,19 @@
  * Created on Mar 9, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -24,9 +23,12 @@ package com.aelitis.azureus.plugins.magnet;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.RandomAccessFile;
+import java.net.InetSocketAddress;
 import java.net.URL;
 import java.util.*;
 
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.download.DownloadManagerState;
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.peer.PEPeerManager;
 import org.gudy.azureus2.core3.torrent.TOTorrent;
@@ -34,14 +36,21 @@ import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLGroup;
 import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
 import org.gudy.azureus2.core3.torrent.TOTorrentCreator;
 import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 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.AddressUtils;
 import org.gudy.azureus2.core3.util.BDecoder;
 import org.gudy.azureus2.core3.util.Base32;
 import org.gudy.azureus2.core3.util.ByteFormatter;
 import org.gudy.azureus2.core3.util.Debug;
 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;
+import org.gudy.azureus2.core3.util.TimerEventPerformer;
+import org.gudy.azureus2.core3.util.TimerEventPeriodic;
 import org.gudy.azureus2.core3.util.TorrentUtils;
 import org.gudy.azureus2.core3.util.UrlUtils;
 import org.gudy.azureus2.plugins.PluginInterface;
@@ -69,6 +78,8 @@ MagnetPluginMDDownloader
 	
 	private PluginInterface		plugin_interface;
 	private byte[]				hash;
+	private Set<String>			networks;
+	private InetSocketAddress[]	addresses;
 	private String				args;
 	
 	private volatile boolean		started;
@@ -84,10 +95,14 @@ MagnetPluginMDDownloader
 	MagnetPluginMDDownloader(
 		PluginInterface		_plugin_interface,
 		byte[]				_hash,
+		Set<String>			_networks,
+		InetSocketAddress[]	_addresses,
 		String				_args )
 	{
 		plugin_interface	= _plugin_interface;
 		hash				= _hash;
+		networks			= _networks;
+		addresses			= _addresses;
 		args				= _args;
 	}
 	
@@ -222,17 +237,20 @@ MagnetPluginMDDownloader
 
 			RandomAccessFile raf = new RandomAccessFile( data_file, "rw" );
 			
-			byte[] buffer = new byte[256*1024];
-			
-			Arrays.fill( buffer, (byte)0xff );
-			
-			for (long i=0;i<32*1024*1024;i+=buffer.length){
+			try{
+				byte[] buffer = new byte[512*1024];
 				
-				raf.write( buffer );
+				Arrays.fill( buffer, (byte)0xff );
+				
+				for (long i=0;i<64*1024*1024;i+=buffer.length){
+					
+					raf.write( buffer );
+				}
+			}finally{
+			
+				raf.close();
 			}
 			
-			raf.close();
-						
 			URL announce_url = TorrentUtils.getDecentralisedURL( hash );
 			
 			TOTorrentCreator creator = 
@@ -245,8 +263,8 @@ MagnetPluginMDDownloader
 			
 			String[] bits = args.split( "&" );
 			
-			List<String>	trackers = new ArrayList<String>();
-
+			List<String>	trackers 	= new ArrayList<String>();
+			
 			String	name = "magnet:" + Base32.encode( hash );
 			
 			for ( String bit: bits ){
@@ -259,17 +277,22 @@ MagnetPluginMDDownloader
 					
 					if ( lhs.equals( "tr" )){
 						
-						trackers.add( UrlUtils.decode( x[1] ));
+						String tracker = UrlUtils.decode( x[1] );
 						
+						trackers.add( tracker );
+
 					}else if ( lhs.equals( "dn" )){
 						
 						name = UrlUtils.decode( x[1] );
 					}
 				}
 			}
-			
+				
 			if ( trackers.size() > 0 ){
 				
+					// stick the decentralised one we created above in position 0 - this will be
+					// removed later if the torrent is downloaded
+				
 				trackers.add( 0, announce_url.toExternalForm());
 				
 				TOTorrentAnnounceURLGroup ag = meta_torrent.getAnnounceURLGroup();
@@ -279,7 +302,9 @@ MagnetPluginMDDownloader
 				for ( String tracker: trackers ){
 				
 					try{
-						sets.add( ag.createAnnounceURLSet(new URL[]{ new URL( tracker )}));
+						URL tracker_url =  new URL( tracker );
+												
+						sets.add( ag.createAnnounceURLSet(new URL[]{ tracker_url }));
 						
 					}catch( Throwable e ){
 						
@@ -314,7 +339,72 @@ MagnetPluginMDDownloader
 			
 			String	display_name = MessageText.getString( "MagnetPlugin.use.md.download.name", new String[]{ name });
 			
-			PluginCoreUtils.unwrap( download ).getDownloadState().setDisplayName( display_name + ".torrent" );
+			DownloadManagerState state = PluginCoreUtils.unwrap( download ).getDownloadState();
+			
+			state.setDisplayName( display_name + ".torrent" );
+			
+			if (	 networks.size() == 0 ||
+					( networks.size() == 1 && networks.contains( AENetworkClassifier.AT_PUBLIC ))){
+				
+					// no clues in the magnet link, or just public 
+					// start off by enabling all networks, public will be disabled later
+					// if off by default
+				
+				for ( String network: AENetworkClassifier.AT_NETWORKS ){
+				
+					state.setNetworkEnabled( network, true );
+				}
+				
+			}else{
+				
+				for ( String network: networks ){
+					
+					state.setNetworkEnabled( network, true );
+				}
+				
+					// disable public network if no explicit trackers are public ones
+				
+				if ( !networks.contains( AENetworkClassifier.AT_PUBLIC )){
+					
+					state.setNetworkEnabled( AENetworkClassifier.AT_PUBLIC, false );
+				}
+			}
+				
+				// if user has specifically disabled the public network then remove this too
+				// as this gives them a way to control metadata download network usage
+			
+			if ( !COConfigurationManager.getBooleanParameter( "Network Selection Default." + AENetworkClassifier.AT_PUBLIC )){
+				
+				state.setNetworkEnabled( AENetworkClassifier.AT_PUBLIC, false );
+			}
+
+			final List<InetSocketAddress>	peers_to_inject = new ArrayList<InetSocketAddress>();
+			
+			if ( addresses != null && addresses.length > 0 ){
+				
+				String[] enabled_nets = state.getNetworks();
+				
+				for ( InetSocketAddress address: addresses ){
+					
+					String host = AddressUtils.getHostAddress( address );
+					
+					String net = AENetworkClassifier.categoriseAddress( host );
+					
+					for ( String n: enabled_nets ){
+						
+						if ( n == net ){
+							
+							peers_to_inject.add( address );
+							
+							break;
+						}
+					}
+				}
+			}
+			
+			final Set<String> peer_networks = new HashSet<String>();
+			
+			final List<Map<String,Object>> peers_for_cache = new ArrayList<Map<String,Object>>();
 			
 			download.addPeerListener(
 				new DownloadPeerListener()
@@ -358,6 +448,28 @@ MagnetPluginMDDownloader
 									
 									final Peer peer = event.getPeer();
 									
+									try{
+										String	peer_ip = peer.getIp();
+										
+										String network = AENetworkClassifier.categoriseAddress( peer_ip );
+										
+										synchronized( peer_networks ){
+											
+											peer_networks.add( network );
+											
+											Map<String,Object> map = new HashMap<String,Object>();
+											
+											peers_for_cache.add( map );
+											
+											map.put( "ip", peer_ip.getBytes( "UTF-8" ));
+											
+											map.put( "port", new Long(peer.getPort()));
+										}
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}
+									
 									peer.addListener(
 										new PeerListener2()
 										{
@@ -382,7 +494,7 @@ MagnetPluginMDDownloader
 													return;
 												}
 												
-												synchronized( this ){
+												synchronized( pm_listener ){
 													
 													if ( md_size > 0 ){
 														
@@ -540,10 +652,95 @@ MagnetPluginMDDownloader
 			DownloadManagerListener dl_listener = 
 				new DownloadManagerListener()
 				{
+					private Object				lock  = this;
+					
+					private TimerEventPeriodic	timer_event;
+					private boolean				removed;
+					
 					public void
 					downloadAdded(
-						Download	download )
+						final Download	download )
 					{
+						if ( download == f_download ){
+							
+							synchronized( lock ){
+								
+								if ( !removed ){
+									
+									if ( timer_event == null ){
+								
+										timer_event = 
+											SimpleTimer.addPeriodicEvent(
+												"announcer",
+												30*1000,
+												new TimerEventPerformer()
+												{	
+													public void 
+													perform(
+														TimerEvent event) 
+													{
+														synchronized( lock ){
+															
+															if ( removed ){
+																
+																return;
+															}
+													
+																// it is possible for the running_sem to be released before
+																// the downloadRemoved event is fired and the listener removed
+																// so the removed event never fires...
+														
+															if ( running_sem.isReleasedForever()){
+															
+																if ( timer_event != null ){
+																	
+																	timer_event.cancel();
+																	
+																	timer_event = null;
+																}
+																
+																return;
+															}
+														}
+														
+														download.requestTrackerAnnounce( true );
+	
+														injectPeers( download );
+													}
+												});
+									}
+									
+									if ( peers_to_inject.size() > 0 ){
+										
+										SimpleTimer.addEvent(
+											"injecter",
+											SystemTime.getOffsetTime( 5*1000 ),
+											new TimerEventPerformer(){
+												public void perform( TimerEvent event ){
+													injectPeers( download );
+												}
+											});
+									}
+								}
+							}
+						}
+					}
+					
+					private void
+					injectPeers(
+						Download	download )
+					{					
+						PeerManager pm = download.getPeerManager();
+
+						if ( pm != null ){
+							
+							for ( InetSocketAddress address: peers_to_inject ){
+																				
+								pm.addPeer(
+									AddressUtils.getHostAddress( address ),
+									address.getPort());
+							}
+						}
 					}
 					
 					public void
@@ -552,6 +749,18 @@ MagnetPluginMDDownloader
 					{
 						if ( dl == f_download ){
 							
+							synchronized( lock ){
+								
+								removed = true;
+								
+								if ( timer_event != null ){
+									
+									timer_event.cancel();
+									
+									timer_event = null;
+								}
+							}
+							
 							if ( !( cancelled || completed )){
 								
 								error[0] = new Exception( "Download manually removed" );
@@ -562,10 +771,9 @@ MagnetPluginMDDownloader
 					}
 				};
 				
-			download_manager.addListener( dl_listener, false );
+			download_manager.addListener( dl_listener, true );
 
-			try{
-			
+			try{			
 				download.moveTo(1);		
 				
 				download.setForceStart( true );
@@ -600,6 +808,30 @@ MagnetPluginMDDownloader
 				
 				if ( url_sets != null ){
 					
+						// first entry should be the decentralised one that we want to remove now
+
+					List<TOTorrentAnnounceURLSet> updated = new ArrayList<TOTorrentAnnounceURLSet>();
+					
+					for ( TOTorrentAnnounceURLSet set: url_sets ){
+						
+						if ( !TorrentUtils.isDecentralised( set.getAnnounceURLs()[0] )){
+							
+							updated.add( set );
+						}
+					}
+					
+					if ( updated.size() == 0 ){
+						
+						url_sets = null;
+						
+					}else{
+						
+						url_sets = updated.toArray( new TOTorrentAnnounceURLSet[updated.size()]);
+					}
+				}
+				
+				if ( url_sets != null ){
+					
 					torrent.setAnnounceURL( url_sets[0].getAnnounceURLs()[0] );
 					
 					torrent.getAnnounceURLGroup().setAnnounceURLSets( url_sets );
@@ -609,7 +841,16 @@ MagnetPluginMDDownloader
 					torrent.setAnnounceURL( TorrentUtils.getDecentralisedURL( hash ));
 				}
 				
-				listener.complete( torrent );
+				if ( peers_for_cache.size() > 0 ){
+					
+					Map<String,List<Map<String,Object>>> peer_cache = new HashMap<String, List<Map<String,Object>>>();
+					
+					peer_cache.put( "tracker_peers", peers_for_cache );
+					
+					TorrentUtils.setPeerCache( torrent, peer_cache );
+				}
+								
+				listener.complete( torrent, peer_networks );
 				
 			}else{
 									
@@ -726,7 +967,8 @@ MagnetPluginMDDownloader
 		
 		public void
 		complete(
-			TOTorrent	torrent );
+			TOTorrent		torrent,
+			Set<String>		peer_networks );
 		
 		public void
 		failed(
diff --git a/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginProgressListener.java b/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginProgressListener.java
index 9e1ca7e..ebb1abe 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginProgressListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/magnet/MagnetPluginProgressListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/magnet/swt/MagnetPluginUISWT.java b/azureus2/src/com/aelitis/azureus/plugins/magnet/swt/MagnetPluginUISWT.java
index 09714ee..7c59c1b 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/magnet/swt/MagnetPluginUISWT.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/magnet/swt/MagnetPluginUISWT.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPlugin.java
index 21a9156..e814e16 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPlugin.java
@@ -1,4338 +1,4477 @@
-/*
- * Created on Mar 19, 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.plugins.net.buddy;
-
-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;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.core3.util.protocol.azplug.AZPluginConnection;
-import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
-import org.gudy.azureus2.plugins.*;
-import org.gudy.azureus2.plugins.ddb.*;
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadException;
-import org.gudy.azureus2.plugins.download.DownloadScrapeResult;
-import org.gudy.azureus2.plugins.ipc.IPCException;
-import org.gudy.azureus2.plugins.logging.LoggerChannel;
-import org.gudy.azureus2.plugins.messaging.MessageException;
-import org.gudy.azureus2.plugins.messaging.MessageManager;
-import org.gudy.azureus2.plugins.messaging.generic.GenericMessageConnection;
-import org.gudy.azureus2.plugins.messaging.generic.GenericMessageHandler;
-import org.gudy.azureus2.plugins.messaging.generic.GenericMessageRegistration;
-import org.gudy.azureus2.plugins.network.ConnectionManager;
-import org.gudy.azureus2.plugins.network.RateLimiter;
-import org.gudy.azureus2.plugins.torrent.Torrent;
-import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
-import org.gudy.azureus2.plugins.ui.UIInstance;
-import org.gudy.azureus2.plugins.ui.UIManagerListener;
-import org.gudy.azureus2.plugins.ui.config.*;
-import org.gudy.azureus2.plugins.ui.menus.MenuItem;
-import org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener;
-import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
-import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
-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.plugins.utils.*;
-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.pluginsimpl.local.PluginCoreUtils;
-
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.security.*;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-import com.aelitis.azureus.core.util.bloom.BloomFilter;
-import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
-import com.aelitis.azureus.plugins.magnet.MagnetPlugin;
-import com.aelitis.azureus.plugins.magnet.MagnetPluginProgressListener;
-import com.aelitis.azureus.plugins.net.buddy.tracker.BuddyPluginTracker;
-
-public class 
-BuddyPlugin 
-	implements Plugin
-{
-	public static final boolean SUPPORT_ONLINE_STATUS		= true;
-	
-	public static final int VERSION_INITIAL	= 1;
-	public static final int VERSION_CHAT	= 2;
-	public static final int VERSION_CURRENT	= VERSION_CHAT;
-	
-	
-	public static final int MT_V3_CHAT		= 1;
-	
-	private static final int FEED_UPDATE_MIN_MILLIS	= 6*60*60*1000;
-	
-	public static final int MAX_MESSAGE_SIZE	= 4*1024*1024;
-	
-	public static final int	SUBSYSTEM_INTERNAL	= 0;
-	public static final int	SUBSYSTEM_AZ2		= 1;
-	public static final int	SUBSYSTEM_AZ3		= 2;
-	
-	protected static final int	SUBSYSTEM_MSG_TYPE_BASE	= 1024;
-	
-	public static final int STATUS_ONLINE			= 0;
-	public static final int STATUS_AWAY				= 1;
-	public static final int STATUS_NOT_AVAILABLE	= 2;
-	public static final int STATUS_BUSY				= 3;
-	public static final int STATUS_APPEAR_OFFLINE	= 4;
-	
-	public static final String[] STATUS_VALUES 	= { "0", "1", "2", "3", "4" };
-	
-	public static final String[] STATUS_KEYS = {
-		"os_online", "os_away", "os_not_avail", "os_busy", "os_offline"
-	};
-
-	public static final String[] STATUS_STRINGS = new String[ STATUS_KEYS.length ];
-	
-	protected static final int RT_INTERNAL_REQUEST_PING		= 1;
-	protected static final int RT_INTERNAL_REPLY_PING		= 2;
-	protected static final int RT_INTERNAL_REQUEST_CLOSE	= 3;
-	protected static final int RT_INTERNAL_REPLY_CLOSE		= 4;
-	protected static final int RT_INTERNAL_FRAGMENT			= 5;
-	
-	protected static final boolean TRACE = false; 
-
-	private static final String VIEW_ID = "azbuddy";
-
-	private static final int	INIT_UNKNOWN		= 0;
-	private static final int	INIT_OK				= 1;
-	private static final int	INIT_BAD			= 2;
-	
-	private static final int	MAX_UNAUTH_BUDDIES	= 16;
-	
-	public static final int	TIMER_PERIOD	= 10*1000;
-	
-	private static final int	BUDDY_STATUS_CHECK_PERIOD_MIN	= 3*60*1000;
-	private static final int	BUDDY_STATUS_CHECK_PERIOD_INC	= 1*60*1000;
-	
-	protected static final int	STATUS_REPUBLISH_PERIOD		= 10*60*1000;
-	private static final int	STATUS_REPUBLISH_TICKS		= STATUS_REPUBLISH_PERIOD/TIMER_PERIOD;
-
-	private static final int	CHECK_YGM_PERIOD			= 5*60*1000;
-	private static final int	CHECK_YGM_TICKS				= CHECK_YGM_PERIOD/TIMER_PERIOD;
-	private static final int	YGM_BLOOM_LIFE_PERIOD		= 60*60*1000;
-	private static final int	YGM_BLOOM_LIFE_TICKS		= YGM_BLOOM_LIFE_PERIOD/TIMER_PERIOD;
-
-	private static final int	SAVE_CONFIG_PERIOD			= 60*1000;
-	private static final int	SAVE_CONFIG_TICKS			= SAVE_CONFIG_PERIOD/TIMER_PERIOD;
-
-	public static final int		PERSISTENT_MSG_RETRY_PERIOD		= 5*60*1000;
-	private static final int	PERSISTENT_MSG_CHECK_PERIOD		= 60*1000;
-	private static final int	PERSISTENT_MSG_CHECK_TICKS		= PERSISTENT_MSG_CHECK_PERIOD/TIMER_PERIOD;
-
-	private static final int	UNAUTH_BLOOM_RECREATE		= 120*1000;
-	private static final int	UNAUTH_BLOOM_CHUNK			= 1000;
-	private static BloomFilter	unauth_bloom;
-	private static long			unauth_bloom_create_time;
-
-	private static final int	BLOOM_CHECK_PERIOD			= UNAUTH_BLOOM_RECREATE/2;
-	private static final int	BLOOM_CHECK_TICKS			= BLOOM_CHECK_PERIOD/TIMER_PERIOD;
-
-	private static BloomFilter	ygm_unauth_bloom;
-
-	public static final int STREAM_CRYPTO 	= MessageManager.STREAM_ENCRYPTION_RC4_REQUIRED;
-	public static final int BLOCK_CRYPTO	= SESecurityManager.BLOCK_ENCRYPTION_AES;
-	
-	//public static final int STREAM_CRYPTO 	= MessageManager.STREAM_ENCRYPTION_NONE;
-	//public static final int BLOCK_CRYPTO	= SESecurityManager.BLOCK_ENCRYPTION_NONE;
-	
-	private volatile int	 initialisation_state = INIT_UNKNOWN;
-	
-	private PluginInterface	plugin_interface;
-	
-	private LoggerChannel	logger;
-	
-	private BooleanParameter 		enabled_param; 
-	private StringParameter 		nick_name_param;
-	private StringListParameter 	online_status_param;
-	private BooleanParameter 		enable_chat_notifications; 
-	private StringParameter 		cat_pub;
-
-	private boolean			ready_to_publish;
-	private publishDetails	current_publish		= new publishDetails();
-	private publishDetails	latest_publish		= current_publish;
-	private long			last_publish_start;
-	private TimerEvent		republish_delay_event;
-	
-	private AsyncDispatcher	publish_dispatcher = new AsyncDispatcher();
-	
-	private	DistributedDatabase 	ddb;
-	
-	private CryptoHandler ecc_handler = CryptoManagerFactory.getSingleton().getECCHandler();
-
-	private List<BuddyPluginBuddy>	buddies 	= new ArrayList<BuddyPluginBuddy>();
-	
-	private List<BuddyPluginBuddy>	connected_at_close;
-	
-	private Map<String,BuddyPluginBuddy>		buddies_map	= new HashMap<String,BuddyPluginBuddy>();
-	
-	private CopyOnWriteList<BuddyPluginListener>				listeners 			= new CopyOnWriteList<BuddyPluginListener>();
-	private CopyOnWriteList<BuddyPluginBuddyRequestListener>	request_listeners	= new CopyOnWriteList<BuddyPluginBuddyRequestListener>(); 
-		
-	private SESecurityManager	sec_man;
-
-	private GenericMessageRegistration	msg_registration;
-			
-	private RateLimiter	inbound_limiter; 
-		
-	private RateLimiter	outbound_limiter; 
-	
-	private boolean		config_dirty;
-	
-	private Random	random = RandomUtils.SECURE_RANDOM;
-	
-	private BuddyPluginAZ2		az2_handler;
-	
-	private List<DistributedDatabaseContact>	publish_write_contacts = new ArrayList<DistributedDatabaseContact>();
-	
-	private int		status_seq;
-	
-	{
-		while( status_seq == 0 ){
-			
-			status_seq = random.nextInt();
-		}
-	}
-		
-	private Set<BuddyPluginBuddy>			pd_preinit		= new HashSet<BuddyPluginBuddy>();
-	
-	private List<BuddyPluginBuddy>			pd_queue 		= new ArrayList<BuddyPluginBuddy>();
-	private AESemaphore						pd_queue_sem	= new AESemaphore( "BuddyPlugin:persistDispatch");
-	private AEThread2						pd_thread;
-	
-	private boolean		bogus_ygm_written;
-	
-	private BuddyPluginTracker	buddy_tracker;
-	
-	private TorrentAttribute	ta_category;
-
-	private Set<String>	public_categories = new HashSet<String>();
-	
-	public static void
-	load(
-		PluginInterface		plugin_interface )
-	{
-		String name = 
-			plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "Views.plugins." + VIEW_ID + ".title" );
-		
-		plugin_interface.getPluginProperties().setProperty( "plugin.version", 	"1.0" );
-		plugin_interface.getPluginProperties().setProperty( "plugin.name", 		name );
-	}
-
-	public void
-	initialize(
-		final PluginInterface		_plugin_interface )
-	{		
-		plugin_interface	= _plugin_interface;
-		
-			
-		ta_category		= plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_CATEGORY );
-
-		az2_handler = new BuddyPluginAZ2( this );
-				
-		sec_man = plugin_interface.getUtilities().getSecurityManager();
-
-		logger = plugin_interface.getLogger().getChannel( "Friends" );
-		
-		logger.setDiagnostic();
-				
-		final LocaleUtilities lu = plugin_interface.getUtilities().getLocaleUtilities();
-		
-		lu.addListener(
-			new LocaleListener()
-			{
-				public void 
-				localeChanged(
-					Locale		l )
-				{
-					updateLocale(lu);
-				}
-			});
-		
-		updateLocale(lu);
-		
-		BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel( "Views.plugins." + VIEW_ID + ".title" );
-			
-			// enabled
-
-		enabled_param = config.addBooleanParameter2( "azbuddy.enabled", "azbuddy.enabled", false );
-				
-			// nickname
-
-		nick_name_param = config.addStringParameter2( "azbuddy.nickname", "azbuddy.nickname", "" );
-
-		nick_name_param.setGenerateIntermediateEvents( false );
-		
-		nick_name_param.addListener(
-				new ParameterListener()
-				{
-					public void
-					parameterChanged(
-						Parameter	param )
-					{
-						updateNickName( nick_name_param.getValue());
-					}
-				});
-		
-			// online status
-
-		String[]	os_values 	= STATUS_VALUES;
-		String[]	os_labels	= STATUS_STRINGS;
-		
-		online_status_param = config.addStringListParameter2(
-				"azbuddy.online_status", "azbuddy.online_status",
-				os_values,
-				os_labels,
-				os_values[0] );
-				
-		online_status_param.addListener(
-				new ParameterListener()
-				{
-					public void
-					parameterChanged(
-						Parameter	param )
-					{
-						 int status = Integer.parseInt( online_status_param.getValue());
-						 
-						 updateOnlineStatus( status );
-					}
-				});
-		
-		online_status_param.setVisible( SUPPORT_ONLINE_STATUS  ); // If we add this then use proper message texts in the STATUS_STRINGS
-		
-			// protocol speed
-		
-		final IntParameter	protocol_speed = config.addIntParameter2( "azbuddy.protocolspeed", "azbuddy.protocolspeed", 32 );
-		
-		protocol_speed.setMinimumRequiredUserMode( Parameter.MODE_ADVANCED );
-		
-		ConnectionManager cman = plugin_interface.getConnectionManager();
-		
-		int inbound_limit = protocol_speed.getValue()*1024;
-
-		inbound_limiter 	= cman.createRateLimiter( "buddy_up", inbound_limit );	
-		outbound_limiter 	= cman.createRateLimiter( "buddy_down", 0 );
-
-		protocol_speed.addListener(
-				new ParameterListener()
-				{
-					public void
-					parameterChanged(
-						Parameter	param )
-					{
-						inbound_limiter.setRateLimitBytesPerSecond( protocol_speed.getValue()*1024 );
-					}
-				});
-		
-			// chat notifications
-		
-		enable_chat_notifications = config.addBooleanParameter2( "azbuddy.enable_chat_notif", "azbuddy.enable_chat_notif", true );
-		
-			// default published cats
-		
-		cat_pub = config.addStringParameter2( "azbuddy.enable_cat_pub", "azbuddy.enable_cat_pub", "" );
-		
-		cat_pub.setGenerateIntermediateEvents( false );
-		
-		setPublicCats( cat_pub.getValue(), false );
-		
-		cat_pub.addListener(
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					Parameter 	param ) 
-				{
-					setPublicCats( cat_pub.getValue(), false);
-				}
-			});
-		
-			// config end
-				
-		
-		final TableContextMenuItem menu_item_itorrents = 
-			plugin_interface.getUIManager().getTableManager().addContextMenuItem(TableManager.TABLE_MYTORRENTS_INCOMPLETE, "azbuddy.contextmenu");
-		final TableContextMenuItem menu_item_ctorrents 	= 
-			plugin_interface.getUIManager().getTableManager().addContextMenuItem(TableManager.TABLE_MYTORRENTS_COMPLETE, "azbuddy.contextmenu");
-		
-		menu_item_itorrents.setStyle(TableContextMenuItem.STYLE_MENU);
-		menu_item_ctorrents.setStyle(TableContextMenuItem.STYLE_MENU);
-		
-		MenuItemFillListener	menu_fill_listener = 
-			new MenuItemFillListener()
-			{
-				public void
-				menuWillBeShown(
-					MenuItem	menu,
-					Object		_target )
-				{
-					menu.removeAllChildItems();
-
-					if ( !( isEnabled() && isAvailable())){
-						
-						menu.setEnabled( false );
-						
-						return;
-					}
-					
-					final List<Torrent>	torrents = new ArrayList<Torrent>();
-								
-					if ( _target instanceof TableRow ){
-						
-						addDownload( torrents, (TableRow)_target );
-	
-					}else{
-						
-						TableRow[] rows = (TableRow[])_target;
-					     
-						for ( TableRow row: rows ){
-							
-							addDownload( torrents, row );
-						}
-					}
-					
-					if ( torrents.size() == 0 ){
-						
-						menu.setEnabled( false );
-
-					}else{
-					
-						List<BuddyPluginBuddy> buddies = getBuddies();
-						
-						boolean	incomplete = ((TableContextMenuItem)menu).getTableID() == TableManager.TABLE_MYTORRENTS_INCOMPLETE;
-						
-						TableContextMenuItem parent = incomplete?menu_item_itorrents:menu_item_ctorrents;
-												
-						for (int i=0;i<buddies.size();i++){
-							
-							final BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(i);
-							
-							if ( buddy.isOnline( true )){
-								
-								TableContextMenuItem item =
-									plugin_interface.getUIManager().getTableManager().addContextMenuItem(
-										parent,
-										"!" + buddy.getName() + "!");
-								
-								item.addMultiListener(
-									new MenuItemListener()
-									{
-										public void 
-										selected(
-											MenuItem 	menu,
-											Object 		target ) 
-										{
-											for ( Torrent torrent: torrents ){
-											
-												az2_handler.sendAZ2Torrent( torrent, buddy );
-											}
-										}
-									});
-							}
-						}
-					
-						menu.setEnabled( true );
-					}
-				}
-				
-				protected void
-				addDownload(
-					List<Torrent>		torrents,
-					TableRow			row )
-				{
-					Object obj = row.getDataSource();
-					
-					Download	download;
-					
-					if ( obj instanceof Download ){
-						
-						download = (Download)obj;
-						
-					}else{
-						
-						DiskManagerFileInfo file = (DiskManagerFileInfo)obj;
-						
-						try{
-							download	= file.getDownload();
-							
-						}catch( DownloadException e ){	
-							
-							Debug.printStackTrace(e);
-							
-							return;
-						}
-					}
-					
-					Torrent torrent = download.getTorrent();
-					
-					if ( torrent != null && !TorrentUtils.isReallyPrivate( PluginCoreUtils.unwrap( torrent ))){
-						
-						torrents.add( torrent );
-					}
-				}
-			};
-			
-		menu_item_itorrents.addFillListener( menu_fill_listener );
-		menu_item_ctorrents.addFillListener( menu_fill_listener );
-		
-		buddy_tracker = new BuddyPluginTracker( this, config );
-		
-		plugin_interface.getUIManager().addUIListener(
-			new UIManagerListener()
-			{
-				public void
-				UIAttached(
-					final UIInstance		instance )
-				{
-					if ( instance.getUIType() == UIInstance.UIT_SWT ){
-							
-						try{
-							Class.forName( "com.aelitis.azureus.plugins.net.buddy.swt.BuddyPluginView").getConstructor(
-								new Class[]{ BuddyPlugin.class, UIInstance.class, String.class } ).newInstance(
-									new Object[]{ BuddyPlugin.this, instance, VIEW_ID } );
-							
-							// new BuddyPluginView( BuddyPlugin.this, swt_ui, VIEW_ID );
-							
-						}catch( Throwable e ){
-							e.printStackTrace();
-						}
-					}
-					
-					setupDisablePrompt(instance);
-				}
-
-				public void
-				UIDetached(
-					UIInstance		instance )
-				{
-				}
-			});
-		
-		ParameterListener enabled_listener = 
-			new ParameterListener()
-			{
-				public void
-				parameterChanged(
-					Parameter	param )
-				{
-					boolean enabled = enabled_param.getValue();
-
-					nick_name_param.setEnabled( enabled );
-					
-						// only toggle overall state on a real change
-					
-					if ( param != null ){
-					
-						setEnabledInternal( enabled );
-						fireEnabledStateChanged();
-					}
-				}
-			};
-		
-		enabled_listener.parameterChanged( null );
-			
-		enabled_param.addListener( enabled_listener );
-		
-		loadConfig();
-		
-		registerMessageHandler();
-		
-		plugin_interface.addListener(
-			new PluginListener()
-			{
-				public void
-				initializationComplete()
-				{
-					final DelayedTask dt = plugin_interface.getUtilities().createDelayedTask(new Runnable()
-						{
-							public void 
-							run() 
-							{
-								new AEThread2( "BuddyPlugin:init", true )
-								{
-									public void
-									run()
-									{
-										startup();
-									}
-								}.start();
-							}
-						});
-					
-					dt.queue();
-				}
-				
-				public void
-				closedownInitiated()
-				{	
-					saveConfig( true );
-					
-					closedown();
-				}
-				
-				public void
-				closedownComplete()
-				{				
-				}
-			});
-	}
-		
-	protected void
-	updateLocale(
-		LocaleUtilities	lu )
-	{
-		for ( int i=0;i<STATUS_STRINGS.length;i++){
-			
-			STATUS_STRINGS[i] = lu.getLocalisedMessageText( "azbuddy." + STATUS_KEYS[i] );
-		}
-		
-		if ( online_status_param != null ){
-			
-			online_status_param.setLabels( STATUS_STRINGS );
-		}
-	}
-	
-	/**
-	 * 
-	 *
-	 * @since 3.0.5.3
-	 */
-	protected void 
-	setupDisablePrompt(
-			final UIInstance ui) 
-	{
-		if (plugin_interface == null) {
-			return;
-		}
-
-		String enabledConfigID = "PluginInfo." + plugin_interface.getPluginID()
-				+ ".enabled";
-		COConfigurationManager.addParameterListener(enabledConfigID,
-				new org.gudy.azureus2.core3.config.ParameterListener() {
-					public void parameterChanged(
-							String parameterName) 
-					{
-						fireEnabledStateChanged();
-					}
-				});
-	}
-	
-	public void
-	showConfig()
-	{
-		plugin_interface.getUIManager().showConfigSection("Views.plugins." + VIEW_ID + ".title");
-	}
-	
-	protected void
-	startup()
-	{
-		try{
-			ddb = plugin_interface.getDistributedDatabase();
-		
-			if ( !ddb.isAvailable()){
-				
-				throw( new Exception( "DDB Unavailable" ));
-			}
-				// pick up initial values before enabling
-
-			ddb.addListener(
-				new DistributedDatabaseListener()
-				{
-					public void 
-					event(
-						DistributedDatabaseEvent event )
-					{
-						if ( event.getType() == DistributedDatabaseEvent.ET_LOCAL_CONTACT_CHANGED ){
-							
-							updateIP();
-						}
-					}
-				});
-					
-			updateIP();
-			
-			updateNickName( nick_name_param.getValue());
-						 
-			updateOnlineStatus( Integer.parseInt( online_status_param.getValue()));
-			 
-			COConfigurationManager.addAndFireParameterListeners(
-					new String[]{
-						"TCP.Listen.Port",
-						"TCP.Listen.Port.Enable",
-						"UDP.Listen.Port",
-						"UDP.Listen.Port.Enable" },
-					new org.gudy.azureus2.core3.config.ParameterListener()
-					{
-						public void 
-						parameterChanged(
-							String parameterName )
-						{
-							updateListenPorts();
-						}
-					});
-			
-			CryptoManagerFactory.getSingleton().addKeyListener(
-				new CryptoManagerKeyListener()
-				{
-					public void 
-					keyChanged(
-						CryptoHandler handler ) 
-					{
-						updateKey();
-					}
-					
-					public void
-					keyLockStatusChanged(
-						CryptoHandler		handler )
-					{	
-						boolean unlocked = handler.isUnlocked();
-						
-						if ( unlocked ){
-							
-							if ( latest_publish.isEnabled()){
-								
-								updatePublish( latest_publish );
-							}
-						}else{
-							
-							new AEThread2( "BuddyPlugin:disc", true )
-							{
-								public void
-								run()
-								{
-									List buddies = getAllBuddies();
-									
-									for (int i=0;i<buddies.size();i++){
-										
-										((BuddyPluginBuddy)buddies.get(i)).disconnect();
-									}
-								}
-							}.start();
-						}
-					}
-				});
-			
-			ready_to_publish	= true;
-			
-			setEnabledInternal( enabled_param.getValue());
-			
-			checkBuddiesAndRepublish();
-			
-			fireInitialised( true );
-			
-				// try to re-establish connection to previously connectd buddies
-			
-			List<BuddyPluginBuddy> buddies = getBuddies();
-			
-			for ( BuddyPluginBuddy buddy: buddies ){
-				
-				if ( buddy.getIP() != null && !buddy.isConnected()){
-				
-					log( "Attempting reconnect to " + buddy.getString());
-					
-					buddy.sendKeepAlive();
-				}
-			}
-			
-		}catch( Throwable e ){
-		
-			log( "Initialisation failed", e );
-			
-			fireInitialised( false );
-		}
-	}
-	
-	public boolean
-	isEnabled()
-	{
-		if (enabled_param == null) {return false;}
-		return( enabled_param.getValue());
-	}
-	
-	public void
-	setEnabled(
-		boolean		enabled )
-	{
-		if (enabled_param == null) {return;}
-		enabled_param.setValue( enabled );
-	}
-	
-	protected void
-	setEnabledInternal(
-		boolean		_enabled )
-	{
-		synchronized( this ){
-						
-			if ( latest_publish.isEnabled() != _enabled ){
-				
-				publishDetails new_publish = latest_publish.getCopy();
-				
-				new_publish.setEnabled( _enabled );
-				
-				updatePublish( new_publish );
-			}
-		}
-	}
-	
-	public BuddyPluginTracker
-	getTracker()
-	{
-		return( buddy_tracker );
-	}
-	
-	public String
-	getNickname()
-	{
-		return(  nick_name_param.getValue());
-	}
-	
-	public void
-	setNickname(
-		String	str )
-	{
-		nick_name_param.setValue( str );
-	}
-	
-	public void
-	setOnlineStatus(
-		int		status )
-	{
-		online_status_param.setValue( "" + status );
-	}
-	
-	public int
-	getOnlineStatus()
-	{
-		return( latest_publish.getOnlineStatus());
-	}
-	
-	public BooleanParameter
-	getEnableChatNotificationsParameter()
-	{
-		return( enable_chat_notifications );
-	}
-	
-	protected String
-	normaliseCat(
-		String		str )
-	{
-		if ( str == null ){
-			
-			return( null );
-			
-		}else if ( str.toLowerCase().equals( "all" )){
-			
-			return( "All" );
-			
-		}else{
-			
-			return( str );
-		}
-	}
-	
-	protected void
-	normaliseCats(
-		Set<String>	cats )
-	{
-		if ( cats != null ){
-			
-			boolean	all_found = false;
-			
-			Iterator<String> it = cats.iterator();
-			
-			while( it.hasNext()){
-				
-				if ( it.next().toLowerCase().equals( "all" )){
-					
-					it.remove();
-					
-					all_found = true;
-				}
-			}
-			
-			if ( all_found ){
-				
-				cats.add( "All" );
-			}
-		}
-	}
-	
-	public boolean
-	isPublicCategory(
-		String	cat )
-	{
-		cat = normaliseCat( cat );
-		
-		return( public_categories.contains( cat ));
-	}
-	
-	public void
-	addPublicCategory(
-		String	cat )
-	{
-		cat = normaliseCat( cat );
-		
-		Set<String> new_cats = new HashSet( public_categories );
-		
-		if ( new_cats.add( cat )){
-		
-			setPublicCats( new_cats, true );
-		}
-	}
-	
-	public void
-	removePublicCategory(
-		String	cat )
-	{
-		cat = normaliseCat( cat );
-		
-		Set<String> new_cats = new HashSet( public_categories );
-		
-		if ( new_cats.remove( cat )){
-		
-			setPublicCats( new_cats, true );
-		}
-	}
-	
-	protected void
-	setPublicCats(
-		String	str,
-		boolean	persist )
-	{
-		Set<String>	new_pub_cats = new HashSet<String>();
-		
-		String[]	bits = str.split(",");
-		
-		for (String s: bits ){
-			
-			s = s.trim();
-			
-			if ( bits.length > 0 ){
-				
-				new_pub_cats.add( normaliseCat( s ));
-			}
-		}
-		
-		setPublicCats( new_pub_cats, persist );
-	}
-	
-	protected void
-	setPublicCats(
-		Set<String>	new_pub_cats,
-		boolean		persist )
-	{
-		if ( !public_categories.equals( new_pub_cats )){
-			
-			Set<String> removed = new HashSet<String>( public_categories );
-			
-			removed.removeAll( new_pub_cats );
-			
-			public_categories = new_pub_cats;
-			
-			if ( persist ){
-				
-				String cat_str = "";
-				
-				for ( String s: public_categories ){
-					
-					cat_str += (cat_str.length()==0?"":",") + s;
-				}
-				
-				cat_pub.setValue( cat_str );
-			}
-			
-			List<BuddyPluginBuddy> buds = getBuddies();
-			
-			for ( BuddyPluginBuddy b: buds ){
-				
-				Set<String> local = b.getLocalAuthorisedRSSCategories();
-				
-				if ( local != null || new_pub_cats.size() > 0 ){
-					
-					if ( local == null ){
-						
-						local = new HashSet<String>();
-						
-					}else{
-						
-							// gotta clone else we're messing with stuff that ain't ours
-						
-						local = new HashSet<String>( local );
-					}
-					
-					local.addAll( new_pub_cats );
-				
-					local.removeAll( removed );
-				
-					b.setLocalAuthorisedRSSCategories( local );
-				}
-			}
-		}
-	}
-	
-	protected void
-	registerMessageHandler()
-	{
-		try{
-			addRequestListener(
-				new BuddyPluginBuddyRequestListener()
-				{
-					public Map
-					requestReceived(
-						BuddyPluginBuddy	from_buddy,
-						int					subsystem,
-						Map					request )
-					
-						throws BuddyPluginException
-					{
-						if ( subsystem == SUBSYSTEM_INTERNAL ){
-						
-							if ( !from_buddy.isAuthorised()){
-							
-								throw( new BuddyPluginException( "Unauthorised" ));
-							}
-							
-							return( processInternalRequest( from_buddy, request ));							
-						}
-
-						return( null );
-					}
-					
-					public void
-					pendingMessages(
-						BuddyPluginBuddy[]	from_buddies )
-					{
-					}
-				});
-			
-			msg_registration = 
-				plugin_interface.getMessageManager().registerGenericMessageType(
-					"AZBUDDY", "Buddy message handler", 
-					STREAM_CRYPTO,
-					new GenericMessageHandler()
-					{
-						public boolean
-						accept(
-							GenericMessageConnection	connection )
-						
-							throws MessageException
-						{
-							if ( !isEnabled()){
-								
-								return( false );
-							}
-							
-							final String originator = connection.getEndpoint().getNotionalAddress().getAddress().getHostAddress();
-							
-							if ( TRACE ){
-								System.out.println( "accept " + originator );
-							}
-							
-							try{
-								String reason = "Friend: Incoming connection establishment (" + originator + ")";
-									
-								addRateLimiters( connection );
-
-								connection = 
-									sec_man.getSTSConnection(
-											connection, 
-											sec_man.getPublicKey( SEPublicKey.KEY_TYPE_ECC_192, reason ),
-											new SEPublicKeyLocator()
-											{
-												public boolean
-												accept(
-													Object		context,
-													SEPublicKey	other_key )
-												{
-													String	other_key_str = Base32.encode( other_key.encodeRawPublicKey());
-
-													if ( TRACE ){
-														System.out.println( "Incoming: acceptKey - " + other_key_str );
-													}
-													
-													try{
-														synchronized( BuddyPlugin.this ){
-																
-															int	unauth_count = 0;
-															
-															for (int i=0;i<buddies.size();i++){
-															
-																BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(i);
-	
-																if ( buddy.getPublicKey().equals( other_key_str )){
-																	
-																		// don't accept a second or subsequent connection for unauth buddies
-																		// as they have a single chance to be processed
-																	
-																	if ( !buddy.isAuthorised()){
-																		
-																		log( "Incoming connection from " + originator + " failed as for unauthorised buddy" );
-																		
-																		return( false );
-																	}
-																	
-																	buddy.incomingConnection((GenericMessageConnection)context );	
-																	
-																	return( true );
-																}
-																
-																if ( !buddy.isAuthorised()){
-																	
-																	unauth_count++;
-																}
-															}
-															
-																// no existing authorised buddy
-															
-															if ( unauth_count < MAX_UNAUTH_BUDDIES ){
-																		
-																if ( tooManyUnauthConnections( originator )){
-																	
-																	log( "Too many recent unauthorised connections from " + originator );
-																	
-																	return( false );
-																}
-																
-																BuddyPluginBuddy buddy = addBuddy( other_key_str, SUBSYSTEM_AZ2, false );
-																
-																if ( buddy != null ){
-																
-																	buddy.incomingConnection((GenericMessageConnection)context );	
-																	
-																	return( true );
-																	
-																}else{
-																	
-																	return( false );
-																}
-															}
-														}
-														
-														log( "Incoming connection from " + originator + " failed due to pk mismatch" );
-	
-														return( false );
-														
-													}catch( Throwable e ){
-														
-														log( "Incomming connection from " + originator + " failed", e );
-														
-														return( false );
-													}
-												}
-											},
-											reason,
-											BLOCK_CRYPTO );
-							
-							}catch( Throwable e ){
-								
-								connection.close();
-								
-								log( "Incoming connection from " + originator + " failed", e );
-							}
-							
-							return( true );
-						}
-					});
-					
-		}catch( Throwable e ){
-			
-			log( "Failed to register message listener", e );
-		}
-	}
-	
-	protected void
-	addRateLimiters(
-		GenericMessageConnection	connection )
-	{
-		connection.addInboundRateLimiter( inbound_limiter );
-		connection.addOutboundRateLimiter( outbound_limiter );
-	}
-	
-	protected boolean
-	tooManyUnauthConnections(
-		String	originator )
-	{
-		synchronized( this ){
-	
-			if ( unauth_bloom == null ){
-				
-				unauth_bloom = BloomFilterFactory.createAddRemove4Bit( UNAUTH_BLOOM_CHUNK );
-				
-				unauth_bloom_create_time	= SystemTime.getCurrentTime();
-			}
-			
-			int	hit_count = unauth_bloom.add( originator.getBytes());
-			
-			if ( hit_count >= 8 ){
-			    		
-				Debug.out( "Too many recent unauthorised connection attempts from " + originator );
-     		
-				return( true );
-			}
-			
-			return( false );
-		}
-	}
-	
-	protected void
-	checkUnauthBloom()
-	{
-		synchronized( this ){
-		
-			if ( unauth_bloom != null ){
-				
-				long	now = SystemTime.getCurrentTime();
-				
-				if ( now < unauth_bloom_create_time ){
-					
-					unauth_bloom_create_time = now;
-					
-				}else if ( now - unauth_bloom_create_time > UNAUTH_BLOOM_RECREATE ){
-					
-					unauth_bloom = null;
-				}
-			}
-		}
-	}
-	
-	protected void
-	checkMaxMessageSize(
-		int		size )
-	
-		throws BuddyPluginException
-	{
-		if ( size > MAX_MESSAGE_SIZE ){
-			
-			throw( new BuddyPluginException( "Message is too large to send, limit is " + DisplayFormatters.formatByteCountToKiBEtc( MAX_MESSAGE_SIZE )));
-		}
-	}
-	
-	protected void
-	checkPersistentDispatch()
-	{
-		List	buddies_copy;
-		
-		synchronized( this ){
-		
-			buddies_copy = new ArrayList( buddies );
-		}
-				
-		for (int i=0;i<buddies_copy.size();i++){
-			
-			BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies_copy.get(i);
-
-			buddy.checkPersistentDispatch();
-		}
-	}
-	
-	protected void
-	persistentDispatchInit()
-	{
-		Iterator it = pd_preinit.iterator();
-		
-		while( it.hasNext()){
-		
-			persistentDispatchPending((BuddyPluginBuddy)it.next());
-		}
-		
-		pd_preinit = null;
-	}
-	
-	protected void
-	persistentDispatchPending(
-		BuddyPluginBuddy	buddy )
-	{
-		synchronized( pd_queue ){
-			
-			if ( initialisation_state == INIT_UNKNOWN ){
-				
-				pd_preinit.add( buddy );
-				
-				return;
-			}
-			
-			if ( !pd_queue.contains( buddy )){
-				
-				pd_queue.add( buddy );
-				
-				pd_queue_sem.release();
-				
-				if ( pd_thread == null ){
-					
-					pd_thread = 
-						new AEThread2( "BuddyPlugin:persistDispatch", true )
-						{
-							public void
-							run()
-							{
-								while( true ){
-									
-									if ( !pd_queue_sem.reserve( 30*1000 )){
-										
-										synchronized( pd_queue ){
-											
-											if ( pd_queue.isEmpty()){
-												
-												pd_thread	= null;
-												
-												break;
-											}
-										}
-									}else{
-										
-										BuddyPluginBuddy	buddy;
-										
-										synchronized( pd_queue ){
-											
-											buddy = (BuddyPluginBuddy)pd_queue.remove(0);
-										}
-										
-										buddy.persistentDispatch();
-									}
-								}
-							}
-						};
-						
-					pd_thread.start();
-				}
-			}
-		}
-	}
-	
-	protected Map
-	processInternalRequest(
-		BuddyPluginBuddy	from_buddy,
-		Map					request )		
-		
-		throws BuddyPluginException
-	{
-		int	type = ((Long)request.get("type")).intValue();
-		
-		if ( type == RT_INTERNAL_REQUEST_PING ){
-		
-			Map	reply = new HashMap();
-		
-			reply.put( "type", new Long( RT_INTERNAL_REPLY_PING ));
-		
-			return( reply );
-			
-		}else if ( type == RT_INTERNAL_REQUEST_CLOSE ){
-		
-			from_buddy.receivedCloseRequest( request );
-			
-			Map	reply = new HashMap();
-		
-			reply.put( "type", new Long( RT_INTERNAL_REPLY_CLOSE ));
-		
-			return( reply );
-			
-		}else{
-			
-			throw( new BuddyPluginException( "Unrecognised request type " + type ));
-		}
-	}
-
-	protected void
-	updateListenPorts()
-	{
-		synchronized( this ){
-
-			int	tcp_port = COConfigurationManager.getIntParameter( "TCP.Listen.Port" );
-			boolean	tcp_enabled = COConfigurationManager.getBooleanParameter( "TCP.Listen.Port.Enable" );
-			int	udp_port = COConfigurationManager.getIntParameter("UDP.Listen.Port" );
-			boolean	udp_enabled = COConfigurationManager.getBooleanParameter( "UDP.Listen.Port.Enable" );
-				
-			if ( !tcp_enabled ){
-				
-				tcp_port = 0;
-			}
-			
-			if ( !udp_enabled ){
-				
-				udp_port = 0;
-			}
-			
-			if ( 	latest_publish.getTCPPort() != tcp_port ||
-					latest_publish.getUDPPort() != udp_port ){
-				
-				publishDetails new_publish = latest_publish.getCopy();
-				
-				new_publish.setTCPPort( tcp_port );
-				new_publish.setUDPPort( udp_port );
-				
-				updatePublish( new_publish );
-			}
-		}
-	}
-	
-	protected void
-	updateIP()
-	{
-		if ( ddb == null || !ddb.isAvailable()){
-			
-			return;
-		}
-				
-		synchronized( this ){
-
-			InetAddress public_ip = ddb.getLocalContact().getAddress().getAddress();
-				
-			if ( 	latest_publish.getIP() == null ||
-					!latest_publish.getIP().equals( public_ip )){
-					
-				publishDetails new_publish = latest_publish.getCopy();
-				
-				new_publish.setIP( public_ip );
-				
-				updatePublish( new_publish );
-			}
-		}
-	}
-	
-	protected void
-	updateNickName(
-		String		new_nick )
-	{
-		new_nick = new_nick.trim();
-		
-		if ( new_nick.length() == 0 ){
-			
-			new_nick = null;
-		}
-		
-		synchronized( this ){
-
-			String	old_nick = latest_publish.getNickName();
-			
-			if ( !stringsEqual( new_nick, old_nick )){
-			
-				publishDetails new_publish = latest_publish.getCopy();
-					
-				new_publish.setNickName( new_nick );
-					
-				updatePublish( new_publish );
-			}
-		}
-	}
-	
-	protected void
-	updateOnlineStatus(
-		int		new_status )
-	{
-		boolean	changed;
-		
-		synchronized( this ){
-
-			int	old_status = latest_publish.getOnlineStatus();
-			
-			changed = old_status != new_status;
-			
-			if ( changed ){
-			
-				publishDetails new_publish = latest_publish.getCopy();
-					
-				new_publish.setOnlineStatus( new_status );
-					
-				updatePublish( new_publish );
-			}
-		}
-		
-		if ( changed ){
-			
-			List	buddies = getAllBuddies();
-						
-			for (int i=0;i<buddies.size();i++){
-				
-				BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(i);
-				
-				if ( buddy.isConnected()){
-				
-					buddy.sendKeepAlive();
-				}
-			}
-		}
-	}
-	
-	public String
-	getOnlineStatus(
-		int		status )
-	{
-		if ( status >= STATUS_STRINGS.length || status < 0 ){
-		
-			status = 0;
-		}
-		
-		return( STATUS_STRINGS[status] );
-	}
-	
-	protected boolean
-	stringsEqual(
-		String	s1, 
-		String	s2 )
-	{
-		if ( s1 == null && s2 == null ){
-			
-			return( true );
-		}
-		
-		if ( s1 == null || s2 == null ){
-			
-			return( false );
-		}
-		
-		return( s1.equals( s2 ));
-	}
-	
-	protected void
-	updateKey()
-	{
-		synchronized( this ){
-
-			publishDetails new_publish = latest_publish.getCopy();
-				
-			new_publish.setPublicKey( null );
-				
-			updatePublish( new_publish );
-		}
-	}
-	
-	protected void
-	updatePublish(
-		final publishDetails	details )
-	{
-		latest_publish = details;
-		
-		if ( ddb == null || !ready_to_publish ){
-			
-			return;
-		}
-		
-		publish_dispatcher.dispatch(
-			new AERunnable()
-			{
-				public void
-				runSupport()
-				{
-						// only execute the most recent publish
-					
-					if ( publish_dispatcher.getQueueSize() > 0 ){
-						
-						return;
-					}
-					
-					updatePublishSupport( details );
-				}
-			});
-	}
-	
-	protected void
-	updatePublishSupport(
-		publishDetails	details )
-	{
-		byte[]	key_to_remove = null;
-		
-		publishDetails	existing_details;
-		
-		boolean	log_this;
-		
-		synchronized( this ){
-
-			log_this = !current_publish.getString().equals( details.getString());
-			
-			existing_details = current_publish;
-			
-			if ( !details.isEnabled()){
-				
-				if ( current_publish.isPublished()){
-					
-					key_to_remove	= current_publish.getPublicKey();
-				}
-			}else{
-								
-				if ( details.getPublicKey() == null ){
-					
-					try{
-						details.setPublicKey( ecc_handler.getPublicKey( "Creating online status key" ));
-						
-					}catch( Throwable e ){
-						
-						log( "Failed to publish details", e );
-						
-						return;
-					}			
-				}
-				
-				if ( current_publish.isPublished()){
-					
-					byte[]	existing_key = current_publish.getPublicKey();
-				
-					if ( !Arrays.equals( existing_key, details.getPublicKey())){
-						
-						key_to_remove = existing_key;
-					}
-				}
-			}
-			
-			current_publish = details;
-		}
-		
-		if ( key_to_remove != null ){
-			
-			log( "Removing old status publish: " + existing_details.getString());
-			
-			try{
-				ddb.delete(
-					new DistributedDatabaseListener()
-					{
-						public void
-						event(
-							DistributedDatabaseEvent		event )
-						{
-						}
-					},
-					getStatusKey( key_to_remove, "Friend status de-registration for old key" ));
-				
-			}catch( Throwable e ){	
-			
-				log( "Failed to remove existing publish", e );
-			}
-		}
-		
-		if ( details.isEnabled()){
-			
-				// ensure we have a sensible ip
-			
-			InetAddress ip = details.getIP();
-			
-			if ( ip.isLoopbackAddress() || ip.isLinkLocalAddress() || ip.isSiteLocalAddress()){
-				
-				log( "Can't publish as ip address is invalid: " + details.getString());
-				
-				return;
-			}
-			
-			details.setPublished( true );
-			
-			Map	payload = new HashMap();
-			
-			if ( details.getTCPPort() > 0 ){
-			
-				payload.put( "t", new Long(  details.getTCPPort() ));
-			}
-			
-			if (  details.getUDPPort() > 0 ){
-				
-				payload.put( "u", new Long( details.getUDPPort() ));
-			}
-						
-			payload.put( "i", ip.getAddress());
-			
-			String	nick = details.getNickName();
-			
-			if ( nick != null ){
-				
-				if ( nick.length() > 32 ){
-					
-					nick = nick.substring( 0, 32 );
-				}
-				
-				payload.put( "n", nick );
-			}
-			
-			payload.put( "o", new Long( details.getOnlineStatus()));
-			
-			int	next_seq = ++status_seq;
-			
-			if ( next_seq == 0 ){
-				
-				next_seq = ++status_seq;
-			}
-			
-			details.setSequence( next_seq );
-			
-			payload.put( "s", new Long( next_seq ));
-			
-			payload.put( "v", new Long( VERSION_CURRENT ));
-			
-			boolean	failed_to_get_key = true;
-			
-			try{
-				byte[] data = BEncoder.encode( payload );
-										
-				DistributedDatabaseKey	key = getStatusKey( details.getPublicKey(), "My buddy status registration " + payload );
-	
-				byte[] signature = ecc_handler.sign( data, "Friend online status" );
-			
-				failed_to_get_key = false;
-				
-				byte[]	signed_payload = new byte[ 1 + signature.length + data.length ];
-				
-				signed_payload[0] = (byte)signature.length;
-				
-				System.arraycopy( signature, 0, signed_payload, 1, signature.length );
-				System.arraycopy( data, 0, signed_payload, 1 + signature.length, data.length );		
-				
-				DistributedDatabaseValue	value = ddb.createValue( signed_payload );
-				
-				final AESemaphore	sem = new AESemaphore( "BuddyPlugin:reg" );
-				
-				if ( log_this ){
-					
-					logMessage( "Publishing status starts: " + details.getString());
-				}
-				
-				last_publish_start = SystemTime.getMonotonousTime();
-				
-				ddb.write(
-					new DistributedDatabaseListener()
-					{
-						private List<DistributedDatabaseContact>	write_contacts = new ArrayList<DistributedDatabaseContact>();
-						
-						public void
-						event(
-							DistributedDatabaseEvent		event )
-						{
-							int	type = event.getType();
-						
-							if ( type == DistributedDatabaseEvent.ET_VALUE_WRITTEN ){
-								
-								write_contacts.add( event.getContact());
-								
-							}else if ( 	type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ||
-										type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){
-
-								synchronized( publish_write_contacts ){
-									
-									publish_write_contacts.clear();
-									
-									publish_write_contacts.addAll( write_contacts );
-								}
-								
-								sem.release();
-							}
-						}
-					},
-					key,
-					value );
-				
-				sem.reserve();
-				
-				if ( log_this ){
-				
-					logMessage( "My status publish complete" );
-				}
-			}catch( Throwable e ){
-				
-				logMessage( "Failed to publish online status", e );
-				
-				if ( failed_to_get_key ){
-					
-					synchronized( this ){
-						
-						if ( republish_delay_event != null ){
-							
-							return;
-						}
-						
-						if ( 	last_publish_start == 0 ||
-								SystemTime.getMonotonousTime() - last_publish_start > STATUS_REPUBLISH_PERIOD ){
-						
-							log( "Rescheduling publish as failed to get key" );
-						
-							republish_delay_event = SimpleTimer.addEvent(
-								"BuddyPlugin:republish",
-								SystemTime.getCurrentTime() + 60*1000,
-								new TimerEventPerformer()
-								{
-									public void 
-									perform(
-										TimerEvent event) 
-									{
-										synchronized( BuddyPlugin.this ){
-											
-											republish_delay_event = null;
-										}
-										
-										if ( 	last_publish_start == 0 ||
-												SystemTime.getMonotonousTime() - last_publish_start > STATUS_REPUBLISH_PERIOD ){
-										
-											if ( latest_publish.isEnabled()){
-												
-												updatePublish( latest_publish );
-											}
-										}
-									}
-								});
-								
-						}	
-					}
-				}
-			}
-		}
-	}
-	
-	protected int
-	getCurrentStatusSeq()
-	{
-		synchronized( this ){
-		
-			return( current_publish.getSequence());
-		}
-	}
-	
-	protected void
-	closedown()
-	{
-		logMessage( "Closing down" );
-
-		List<BuddyPluginBuddy>	buddies = getAllBuddies();
-		
-		synchronized( this ){
-			
-			connected_at_close = new ArrayList<BuddyPluginBuddy>();
-			
-			for ( BuddyPluginBuddy buddy: buddies ){
-				
-				if ( buddy.isConnected()){
-					
-					connected_at_close.add( buddy );
-				}
-			}
-		}
-		
-		if ( ddb != null ){
-			
-			boolean	restarting = AzureusCoreFactory.isCoreAvailable() ? AzureusCoreFactory.getSingleton().isRestarting() : false;
-			
-			logMessage( "   closing buddy connections" );
-			
-			for (int i=0;i<buddies.size();i++){
-				
-				((BuddyPluginBuddy)buddies.get(i)).sendCloseRequest( restarting );
-			}
-			
-			if ( !restarting ){
-				
-				logMessage( "   updating online status" );
-				
-				List	contacts = new ArrayList();
-				
-				synchronized( publish_write_contacts ){
-					
-					contacts.addAll( publish_write_contacts );
-				}
-				
-				byte[] key_to_remove;
-				
-				synchronized( this ){
-	
-					key_to_remove	= current_publish.getPublicKey();
-				}
-				
-				if ( contacts.size() == 0 || key_to_remove == null ){
-					
-					return;
-				}
-				
-				DistributedDatabaseContact[] contact_a = new DistributedDatabaseContact[contacts.size()];
-				
-				contacts.toArray( contact_a );
-				
-				try{
-					ddb.delete(
-						new DistributedDatabaseListener()
-						{
-							public void
-							event(
-								DistributedDatabaseEvent		event )
-							{
-								if ( event.getType() == DistributedDatabaseEvent.ET_VALUE_DELETED ){
-	
-									// System.out.println( "Deleted status from " + event.getContact().getName());
-								}
-							}
-						},
-						getStatusKey( key_to_remove, "Friend status de-registration for closedown" ),
-						contact_a );
-					
-				}catch( Throwable e ){	
-				
-					log( "Failed to remove existing publish", e );
-				}
-			}
-		}
-	}
-	
-	protected DistributedDatabaseKey
-	getStatusKey(
-		byte[]	public_key,
-		String	reason )
-	
-		throws Exception
-	{
-		byte[]	key_prefix = "azbuddy:status".getBytes();
-		
-		byte[]	key_bytes = new byte[ key_prefix.length + public_key.length ];
-		
-		System.arraycopy( key_prefix, 0, key_bytes, 0, key_prefix.length );
-		System.arraycopy( public_key, 0, key_bytes, key_prefix.length, public_key.length );
-		
-		DistributedDatabaseKey key = ddb.createKey( key_bytes, reason );
-		
-		return( key );
-	}
-
-	protected DistributedDatabaseKey
-	getYGMKey(
-		byte[]	public_key,
-		String	reason )
-	
-		throws Exception
-	{
-		byte[]	key_prefix = "azbuddy:ygm".getBytes();
-		
-		byte[]	key_bytes = new byte[ key_prefix.length + public_key.length ];
-		
-		System.arraycopy( key_prefix, 0, key_bytes, 0, key_prefix.length );
-		System.arraycopy( public_key, 0, key_bytes, key_prefix.length, public_key.length );
-		
-		DistributedDatabaseKey key = ddb.createKey( key_bytes, reason );
-		
-		return( key );
-	}
-	
-	protected void
-	setConfigDirty()
-	{
-		synchronized( this ){
-			
-			config_dirty = true;
-		}
-	}
-		
-	protected void
-	loadConfig()
-	{
-		long	now = SystemTime.getCurrentTime();
-		
-		synchronized( this ){
-			
-			Map map = readConfig(); 
-					
-			List	buddies_config = (List)map.get( "friends" );
-				
-			if ( buddies_config != null ){
-					
-				if ( buddies_config.size() == 0 ){
-					
-					deleteConfig();
-					
-				}else{
-					for (int i=0;i<buddies_config.size();i++){
-						
-						Object o = buddies_config.get(i);
-			
-						if ( o instanceof Map ){
-							
-							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 ){
-								
-								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 ){
-								
-								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 ){
-								
-								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 );
-						}
-					}
-				}
-			}
-			
-			int	num_buddies = buddies.size();
-			
-			for ( BuddyPluginBuddy b: buddies ){
-				
-				b.setInitialStatus( now, num_buddies );
-			}
-		}
-	}
-	
-	protected String
-	decodeString(
-		byte[]		bytes )
-	{
-		if (  bytes == null ){
-			
-			return( null );
-		}
-		
-		try{
-			return( new String( bytes, "UTF8" ));
-			
-		}catch( Throwable e ){
-			
-			return( null );
-		}
-	}
-	
-	protected void
-	saveConfig()
-	{
-		saveConfig( false );
-	}
-	
-	protected void
-	saveConfig(
-		boolean	force )
-	{
-		synchronized( this ){
-
-			if ( config_dirty || force ){
-				
-				List buddies_config = new ArrayList();
-		
-				for (int i=0;i<buddies.size();i++){
-					
-					BuddyPluginBuddy buddy = (BuddyPluginBuddy)buddies.get(i);
-		
-					if ( !buddy.isAuthorised()){
-						
-						continue;
-					}
-					
-					Map	map = new HashMap();
-				
-					map.put( "ct", new Long( buddy.getCreatedTime()));
-					
-					map.put( "pk", buddy.getPublicKey());
-				
-					List	ygm = buddy.getYGMMarkers();
-					
-					if ( ygm != null ){
-						
-						map.put( "ygm", ygm );
-					}
-					
-					String	nick = buddy.getNickName();
-					
-					if ( nick != null ){
-						
-						map.put( "n", nick );
-					}
-					
-					map.put( "ls", new Long( buddy.getLastStatusSeq()));
-					
-					map.put( "lo", new Long( buddy.getLastTimeOnline()));
-					
-					map.put( "ss", new Long( buddy.getSubsystem()));
-					
-					map.put( "v", new Long( buddy.getVersion()));
-					
-					if ( buddy.getLocalAuthorisedRSSCategoriesAsString() != null ){
-						map.put( "lc", buddy.getLocalAuthorisedRSSCategoriesAsString());
-					}
-					
-					if ( buddy.getRemoteAuthorisedRSSCategoriesAsString() != null ){
-						map.put( "rc", buddy.getRemoteAuthorisedRSSCategoriesAsString());
-					}
-
-					boolean connected = 
-						buddy.isConnected() ||
-						( connected_at_close != null && connected_at_close.contains( buddy ));
-					
-					if ( connected ){
-						
-						InetAddress	ip 			= buddy.getIP();
-						int			tcp_port	= buddy.getTCPPort();
-						int			udp_port	= buddy.getUDPPort();
-						
-						if ( ip != null ){
-							
-							map.put( "ip", ip.getAddress());
-							map.put( "tcp", new Long( tcp_port ));
-							map.put( "udp", new Long( udp_port ));
-						}
-					}
-					
-					buddies_config.add( map );
-				}
-				
-				Map	map = new HashMap();
-				
-				if ( buddies_config.size() > 0 ){
-				
-					map.put( "friends", buddies_config );
-				
-					writeConfig( map );
-					
-				}else{
-					
-					deleteConfig();
-				}
-				
-				config_dirty = false;
-			}
-		}
-	}
-	
-	public BuddyPluginBuddy
-	addBuddy(
-		String		key,
-		int			subsystem )
-	
-	{
-		return( addBuddy( key, subsystem, true ));
-	}
-	
-	protected BuddyPluginBuddy
-	addBuddy(
-		String		key,
-		int			subsystem,
-		boolean		authorised )
-	{
-		if ( key.length() == 0 || !verifyPublicKey( key )){
-			
-			return( null );
-		}
-				
-		BuddyPluginBuddy	buddy_to_return = null;
-		
-			// buddy may be already present as unauthorised in which case we pick it up
-			// and authorise it and send the added event (we don't fire added events for
-			// unauthorised buddies)
-		
-		synchronized( this ){
-						
-			for (int i=0;i<buddies.size();i++){
-				
-				BuddyPluginBuddy buddy = (BuddyPluginBuddy)buddies.get(i);
-				
-				if ( buddy.getPublicKey().equals( key )){
-					
-					if ( buddy.getSubsystem() != subsystem ){
-						
-						log( "Buddy " + buddy.getString() + ": subsystem changed from " + buddy.getSubsystem() + " to " + subsystem );
-						
-						buddy.setSubsystem( subsystem );
-						
-						saveConfig( true );
-					}
-					
-					if ( authorised && !buddy.isAuthorised()){
-						
-						log( "Buddy " + buddy.getString() + ": no authorised" );
-						
-						buddy.setAuthorised( true );
-						
-						buddy_to_return	= buddy;
-						
-					}else{
-					
-						return( buddy );
-					}
-				}
-			}
-			
-			if ( buddy_to_return == null ){
-				
-				buddy_to_return = 
-					new BuddyPluginBuddy( this, SystemTime.getCurrentTime(), subsystem, authorised, key, null, VERSION_CURRENT, null, null, 0, 0, null );
-				
-				buddies.add( buddy_to_return );
-				
-				buddies_map.put( key, buddy_to_return );
-				
-				if ( !authorised ){
-					
-					log( "Added unauthorised buddy: " + buddy_to_return.getString());
-				}
-			}
-			
-			if ( buddy_to_return.isAuthorised()){
-				
-				logMessage( "Added buddy " + buddy_to_return.getString());
-	
-				saveConfig( true );
-			}
-		}
-				
-		fireAdded( buddy_to_return );
-		
-		return( buddy_to_return );
-	}
-	
-	protected void
-	removeBuddy(
-		BuddyPluginBuddy 	buddy )
-	{
-		synchronized( this ){
-
-			if ( !buddies.remove( buddy )){
-				
-				return;
-			}
-		
-			buddies_map.remove( buddy.getPublicKey());
-						
-			logMessage( "Removed friend " + buddy.getString());
-
-			saveConfig( true );
-		}
-		
-		buddy.destroy();
-				
-		fireRemoved( buddy );
-	}
-	
-	protected Map
-	readConfig()
-	{
-		File	config_file = new File( plugin_interface.getUtilities().getAzureusUserDir(), "friends.config" );
-		
-		return( readConfigFile( config_file ));
-	}
-	
-	protected void
-	writeConfig(
-		Map		map )
-	{
-		File	config_file = new File( plugin_interface.getUtilities().getAzureusUserDir(), "friends.config" );
-		
-		writeConfigFile( config_file, map );
-	}
-	
-	protected void
-	deleteConfig()
-	{
-		Utilities utils = plugin_interface.getUtilities();
-
-		File	config_file = new File( utils.getAzureusUserDir(), "friends.config" );
-		
-		utils.deleteResilientBEncodedFile(
-				config_file.getParentFile(), config_file.getName(), true );
-
-	}
-	
-	protected Map
-	readConfigFile(
-		File		name )
-	{
-		Utilities utils = plugin_interface.getUtilities();
-		
-		Map map = utils.readResilientBEncodedFile(
-						name.getParentFile(), name.getName(), true );
-		
-		if ( map == null ){
-			
-			map = new HashMap();
-		}
-		
-		return( map );
-	}
-	
-	protected boolean
-	writeConfigFile(
-		File		name,
-		Map			data )
-	{
-		Utilities utils = plugin_interface.getUtilities();
-			
-		utils.writeResilientBEncodedFile(
-			name.getParentFile(), name.getName(), data, true );
-		
-		return( name.exists());
-	}
-	
-	protected File
-	getBuddyConfigDir()
-	{
-		return( new File( plugin_interface.getUtilities().getAzureusUserDir(), "friends" ));
-	}
-	
-	public BuddyPluginAZ2
-	getAZ2Handler()
-	{
-		return( az2_handler );
-	}
-	
-	public String
-	getPublicKey()
-	{
-		try{
-			return( Base32.encode(ecc_handler.getPublicKey( "Friend get key" )));
-			
-		}catch( Throwable e ){
-			
-			logMessage( "Failed to access public key", e );
-			
-			return( null );
-		}
-	}
-	
-	public boolean
-	verifyPublicKey(
-		String		key )
-	{
-		return( ecc_handler.verifyPublicKey( Base32.decode( key )));
-	}
-	
-	protected void
-	checkBuddiesAndRepublish()
-	{
-		updateBuddys();
-		
-		plugin_interface.getUtilities().createTimer( "Buddy checker" ).addPeriodicEvent(
-			TIMER_PERIOD,
-			new UTTimerEventPerformer()
-			{
-				int	tick_count;
-				
-				public void 
-				perform(
-					UTTimerEvent event ) 
-				{
-					tick_count++;
-					
-					if ( !isEnabled()){
-						
-						return;
-					}
-												
-					updateBuddys();
-					
-					if ( tick_count % STATUS_REPUBLISH_TICKS == 0 ){
-							
-						if ( latest_publish.isEnabled()){
-								
-							updatePublish( latest_publish );
-						}
-					}
-					
-					if ( tick_count % CHECK_YGM_TICKS == 0 ){
-
-						checkMessagePending( tick_count );
-					}
-					
-					if ( tick_count % BLOOM_CHECK_TICKS == 0 ){
-						
-						checkUnauthBloom();
-					}
-					
-					if ( tick_count % SAVE_CONFIG_TICKS == 0 ){
-
-						saveConfig();
-					}
-					
-					if ( tick_count % PERSISTENT_MSG_CHECK_TICKS == 0 ){
-						
-						checkPersistentDispatch();
-					}
-					
-					if ( buddy_tracker != null ){
-						
-						buddy_tracker.tick( tick_count );
-					}
-				}
-			});
-	}
-	
-	protected void
-	updateBuddys()
-	{
-		List	buddies_copy;
-		
-		synchronized( this ){
-		
-			buddies_copy = new ArrayList( buddies );
-		}
-		
-		long	now = SystemTime.getCurrentTime();
-		
-		Random random = new Random();
-		
-		for (int i=0;i<buddies_copy.size();i++){
-			
-			BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies_copy.get(i);
-			
-			long	last_check = buddy.getLastStatusCheckTime();
-			
-			buddy.checkTimeouts();
-			
-			int	period = BUDDY_STATUS_CHECK_PERIOD_MIN + BUDDY_STATUS_CHECK_PERIOD_INC*buddies_copy.size()/5;
-			
-				// randomise a bit
-			
-			period += random.nextInt( 2*60*1000 );
-			
-				// last check may be in the future as we defer checks for seemingly inactive buddies
-			
-			if ( now - last_check > period ){
-				
-				if ( !buddy.statusCheckActive()){
-			
-					if ( buddy.isAuthorised()){
-					
-						updateBuddyStatus( buddy );
-					}
-				}
-			}
-		}
-		
-			// trim any non-authorised buddies that have gone idle
-
-		synchronized( this ){
-			
-			for (int i=0;i<buddies_copy.size();i++){
-			
-				BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies_copy.get(i);
-				
-				if ( buddy.isIdle() && !buddy.isAuthorised()){
-					
-					removeBuddy( buddy );
-				}
-			}
-		}
-	}
-	
-	protected void
-	updateBuddyStatus(
-		final BuddyPluginBuddy	buddy )
-	{	
-		if ( !buddy.statusCheckStarts()){
-			
-			return;
-		}
-		
-		log( "Updating buddy status: " + buddy.getString());
-
-		try{							
-			final byte[]	public_key = buddy.getRawPublicKey();
-
-			DistributedDatabaseKey	key = 
-				getStatusKey( public_key, "Friend status check for " + buddy.getName());
-			
-			ddb.read(
-				new DistributedDatabaseListener()
-				{
-					private long	latest_time;
-					private Map		status;
-					
-					public void
-					event(
-						DistributedDatabaseEvent		event )
-					{
-						int	type = event.getType();
-						
-						if ( type == DistributedDatabaseEvent.ET_VALUE_READ ){
-							
-							try{
-								DistributedDatabaseValue value = event.getValue();
-								
-								long time = value.getCreationTime();
-								
-								if ( time > latest_time ){
-								
-									byte[] signed_stuff = (byte[])value.getValue( byte[].class );
-								
-									Map	new_status = verifyAndExtract( signed_stuff, public_key );
-									
-									if ( new_status != null ){
-	
-										status = new_status;
-																																							
-										latest_time = time;
-									}
-								}
-							}catch( Throwable e ){
-								
-								log( "Read failed", e );
-							}
-						}else if ( 	type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ||
-									type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){
-							
-							if ( status == null ){
-																
-								buddy.statusCheckFailed();
-								
-							}else{
-								
-								try{
-									Long	l_tcp_port = (Long)status.get( "t" );
-									Long	l_udp_port = (Long)status.get( "u" );
-									
-									int	tcp_port = l_tcp_port==null?0:l_tcp_port.intValue();
-									int udp_port = l_udp_port==null?0:l_udp_port.intValue();
-									
-									InetAddress ip = InetAddress.getByAddress((byte[])status.get("i"));
-									
-									String	nick = decodeString((byte[])status.get( "n" ));
-									
-									Long	l_seq = (Long)status.get( "s" );
-									
-									int		seq = l_seq==null?0:l_seq.intValue();
-									
-									Long	l_os = (Long)status.get( "o" );
-									
-									int		os = l_os==null?BuddyPlugin.STATUS_ONLINE:l_os.intValue();
-											
-									Long	l_ver = (Long)status.get( "v" );
-									
-									int		ver = l_ver==null?VERSION_INITIAL:l_ver.intValue();
-											
-									buddy.statusCheckComplete( latest_time, ip, tcp_port, udp_port, nick, os, seq, ver );
-									
-								}catch( Throwable e ){
-									
-									buddy.statusCheckFailed();
-									
-									log( "Status decode failed", e );
-								}
-							}
-						}
-					}
-				},
-				key,
-				120*1000 );
-			
-		}catch( Throwable e ){
-			
-			buddy.statusCheckFailed();
-			
-			log( "Friend status update failed: " + buddy.getString(), e );
-		}
-	}
-	
-	protected Map
-	verifyAndExtract(
-		byte[]		signed_stuff,
-		byte[]		public_key )
-	
-		throws BuddyPluginException
-	{
-		int	signature_length = ((int)signed_stuff[0])&0xff;
-		
-		byte[]	signature 	= new byte[ signature_length ];
-		byte[]	data		= new byte[ signed_stuff.length - 1 - signature_length];
-		
-		System.arraycopy( signed_stuff, 1, signature, 0, signature_length );
-		System.arraycopy( signed_stuff, 1 + signature_length, data, 0, data.length );
-			
-		try{
-			if ( ecc_handler.verify( public_key, data, signature )){													
-	
-				return( BDecoder.decode( data ));
-																																	
-			}else{
-				
-				logMessage( "Signature verification failed" );
-				
-				return( null );
-			}
-		}catch( Throwable e ){
-			
-			rethrow( "Verification failed", e );
-			
-			return( null );
-		}
-	}
-	
-	protected byte[]
-	signAndInsert(
-		Map		plain_stuff,
-		String	reason )
-	
-		throws BuddyPluginException
-	{
-		try{
-			byte[] data = BEncoder.encode( plain_stuff );
-			
-			byte[] signature = ecc_handler.sign( data, reason );
-		
-			byte[]	signed_payload = new byte[ 1 + signature.length + data.length ];
-			
-			signed_payload[0] = (byte)signature.length;
-			
-			System.arraycopy( signature, 0, signed_payload, 1, signature.length );
-			System.arraycopy( data, 0, signed_payload, 1 + signature.length, data.length );		
-	
-			return( signed_payload );
-			
-		}catch( Throwable e ){
-			
-			rethrow( "Signing failed", e );
-			
-			return( null );
-		}
-	}
-	
-	public boolean
-	verify(
-		String				pk,
-		byte[]				payload,
-		byte[]				signature )
-	
-		throws BuddyPluginException
-	{
-		return( verify( Base32.decode( pk ), payload, signature ));
-	}
-	
-	protected boolean
-	verify(
-		BuddyPluginBuddy	buddy,
-		byte[]				payload,
-		byte[]				signature )
-	
-		throws BuddyPluginException
-	{
-		return( verify( buddy.getRawPublicKey(), payload, signature ));
-	}
-	
-	protected boolean
-	verify(
-		byte[]				pk,
-		byte[]				payload,
-		byte[]				signature )
-	
-		throws BuddyPluginException
-	{
-		try{
-		
-			return( ecc_handler.verify( pk, payload, signature ));
-			
-		}catch( Throwable e ){
-			
-			rethrow( "Verification failed", e );
-			
-			return( false );
-		}
-	}
-	
-	public byte[]
-   	sign(
-   		byte[]		payload )
-	        	
-	   	throws BuddyPluginException
-	{ 
-		try{
-		
-			return( ecc_handler.sign( payload, "Friend message signing" ));
-
-		}catch( Throwable e ){
-			
-			rethrow( "Signing failed", e );
-			
-			return( null );
-		}
-	}
-
-	protected cryptoResult
-	encrypt(
-		BuddyPluginBuddy	buddy,
-		byte[]				payload )
-	
-		throws BuddyPluginException
-	{
-		return encrypt(buddy.getPublicKey(), payload, buddy.getName());
-	}
-
-	public cryptoResult
-	encrypt(
-		String				pk,
-		byte[]				payload,
-		String				forWho )
-	
-		throws BuddyPluginException
-	{
-		
-		try{
-			byte[]	hash = new byte[20];
-			
-			random.nextBytes( hash );
-			
-			Map	content = new HashMap();
-			
-			content.put( "h", hash );
-			content.put( "p", payload );
-			
-			final byte[] encrypted = ecc_handler.encrypt( Base32.decode(pk), BEncoder.encode( content ), "Encrypting message for " + forWho);
-			
-			final byte[] sha1_hash = new SHA1Simple().calculateHash( hash );
-			
-			return( 
-				new cryptoResult()
-				{
-					public byte[]
-		    		getChallenge()
-					{
-						return( sha1_hash );
-					}
-		    		
-		    		public byte[]
-		    		getPayload()
-		    		{
-		    			return( encrypted );
-		    		}
-				});
-			
-		}catch( Throwable e ){
-			
-			rethrow( "Encryption failed", e );
-			
-			return( null );
-		}
-	}
-	
-	protected cryptoResult
-	decrypt(
-		BuddyPluginBuddy	buddy,
-		byte[]				content,
-		String forName)
-	
-		throws BuddyPluginException
-	{
-		
-		try{
-			final byte[] decrypted = ecc_handler.decrypt( buddy.getRawPublicKey(), content, "Decrypting message for " + buddy.getName());
-			
-			final Map	map = BDecoder.decode( decrypted );
-			
-			return( 
-				new cryptoResult()
-				{
-					public byte[]
-		    		getChallenge()
-					{
-						return((byte[])map.get("h"));
-					}
-		    		
-		    		public byte[]
-		    		getPayload()
-		    		{
-		    			return((byte[])map.get("p"));
-		    		}
-				});
-			
-		}catch( Throwable e ){
-			
-			rethrow( "Decryption failed", e );
-			
-			return( null );
-		}
-	}
-
-	public cryptoResult
-	decrypt(
-		String				public_key,
-		byte[]				content )
-	
-		throws BuddyPluginException
-	{
-		
-		try{
-			final byte[] decrypted = ecc_handler.decrypt( Base32.decode(public_key), content, "Decrypting message for " + public_key);
-			
-			final Map	map = BDecoder.decode( decrypted );
-			
-			return( 
-				new cryptoResult()
-				{
-					public byte[]
-		    		getChallenge()
-					{
-						return((byte[])map.get("h"));
-					}
-		    		
-		    		public byte[]
-		    		getPayload()
-		    		{
-		    			return((byte[])map.get("p"));
-		    		}
-				});
-			
-		}catch( Throwable e ){
-			
-			rethrow( "Decryption failed", e );
-			
-			return( null );
-		}
-	}
-
-	protected void
-	setMessagePending(
-		BuddyPluginBuddy			buddy,
-		final operationListener		listener )
-	
-		throws BuddyPluginException
-	{		
-		try{
-			checkAvailable();
-
-			final String	reason = "Friend YGM write for " + buddy.getName();
-			
-			Map	payload = new HashMap();
-			
-			payload.put( "r", new Long( random.nextLong()));
-			
-			byte[] signed_payload = signAndInsert( payload, reason);
-			
-			Map	envelope = new HashMap();
-			
-			envelope.put( "pk", ecc_handler.getPublicKey( reason ));
-			envelope.put( "ss", signed_payload );
-			
-			DistributedDatabaseValue	value = ddb.createValue( BEncoder.encode( envelope ));
-										
-			logMessage( reason + " starts: " + payload );
-			
-			DistributedDatabaseKey	key = getYGMKey( buddy.getRawPublicKey(), reason );
-
-			ddb.write(
-				new DistributedDatabaseListener()
-				{
-					public void
-					event(
-						DistributedDatabaseEvent		event )
-					{
-						int	type = event.getType();
-					
-						if ( 	type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ||
-								type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){
-							
-							logMessage( reason + " complete"  );
-
-							listener.complete();
-						}
-					}
-				},
-				key,
-				value );
-
-		}catch( Throwable e ){
-			
-			try{				
-				rethrow( "Failed to publish YGM", e );
-								
-			}finally{
-				
-				listener.complete();
-			}
-		}
-	}
-	
-	public void
-	checkMessagePending(
-		int	tick_count )
-	{
-		log( "Checking YGM" );
-
-		if ( tick_count % YGM_BLOOM_LIFE_TICKS == 0 ){
-			
-			synchronized( this ){
-				
-				ygm_unauth_bloom = null;
-			}
-		}
-
-		try{	
-			String	reason = "Friend YGM check";
-			
-			byte[] public_key = ecc_handler.getPublicKey( reason );
-
-			DistributedDatabaseKey	key = getYGMKey( public_key, reason );
-			
-			ddb.read(
-				new DistributedDatabaseListener()
-				{	
-					private List		new_ygm_buddies = new ArrayList();
-					private boolean	 	unauth_permitted = false;;
-					
-					public void
-					event(
-						DistributedDatabaseEvent		event )
-					{
-						int	type = event.getType();
-						
-						if ( type == DistributedDatabaseEvent.ET_VALUE_READ ){
-							
-							try{
-								DistributedDatabaseValue value = event.getValue();
-																
-								byte[]	envelope = (byte[])value.getValue( byte[].class );
-								
-								Map	map = BDecoder.decode( envelope );
-								
-								byte[]	pk = (byte[])map.get( "pk" );
-								
-								if ( pk == null ){
-									
-									return;
-								}
-								
-								String	pk_str = Base32.encode( pk );
-								
-								BuddyPluginBuddy buddy = getBuddyFromPublicKey( pk_str );
-																
-								if ( buddy == null || !buddy.isAuthorised() ){
-									
-									if ( buddy == null ){
-									
-										log( "YGM entry from unknown friend '" + pk_str + "' - ignoring" );
-										
-									}else{								
-									
-										log( "YGM entry from unauthorised friend '" + pk_str + "' - ignoring" );
-									}
-
-									byte[] address = event.getContact().getAddress().getAddress().getAddress();
-									
-									synchronized( BuddyPlugin.this ){
-									
-										if ( ygm_unauth_bloom == null ){
-										
-											ygm_unauth_bloom = BloomFilterFactory.createAddOnly(512);
-										}
-										
-										if ( !ygm_unauth_bloom.contains( address )){
-											
-											ygm_unauth_bloom.add( address );
-											
-											unauth_permitted = true;
-										}
-									}
-								}else{
-									
-									byte[]	signed_stuff = (byte[])map.get( "ss" );
-									
-									Map	payload = verifyAndExtract( signed_stuff, pk );
-									
-									if ( payload != null ){
-										
-										long	rand = ((Long)payload.get("r")).longValue();
-										
-										if ( buddy.addYGMMarker( rand )){
-											
-											new_ygm_buddies.add( buddy );
-										}
-									}
-								}
-							}catch( Throwable e ){
-								
-								log( "Read failed", e );
-							}
-						}else if ( 	type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ||
-									type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){
-							
-							if ( new_ygm_buddies.size() > 0 || unauth_permitted ){
-								
-								BuddyPluginBuddy[] b = new BuddyPluginBuddy[new_ygm_buddies.size()];
-								
-								new_ygm_buddies.toArray( b );
-								
-								fireYGM( b );
-							}
-						}
-					}
-				},
-				key,
-				120*1000,
-				DistributedDatabase.OP_EXHAUSTIVE_READ );
-			
-			boolean	write_bogus_ygm = false;
-			
-			synchronized( this ){
-			
-				if ( !bogus_ygm_written ){
-					
-					bogus_ygm_written = write_bogus_ygm = true;
-				}
-			}
-			
-			if ( write_bogus_ygm ){
-				
-				final String	reason2 = "Friend YGM write for myself";
-				
-				Map	envelope = new HashMap();
-								
-				DistributedDatabaseValue	value = ddb.createValue( BEncoder.encode( envelope ));
-											
-				logMessage( reason2 + " starts" );
-				
-				ddb.write(
-					new DistributedDatabaseListener()
-					{
-						public void
-						event(
-							DistributedDatabaseEvent		event )
-						{
-							int	type = event.getType();
-						
-							if ( type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){
-								
-								logMessage( reason2 + " complete"  );
-							}
-						}
-					},
-					key,
-					value );
-			}
-			
-		}catch( Throwable e ){
-						
-			logMessage( "YGM check failed", e );
-		}
-	}
-	
-	public BuddyPluginBuddy
-	getBuddyFromPublicKey(
-		String		key )
-	{
-		synchronized( this ){
-			
-			return((BuddyPluginBuddy)buddies_map.get( key ));
-		}
-	}
-	
-	public PluginInterface
-	getPluginInterface()
-	{
-		return( plugin_interface );
-	}
-	
-	protected SESecurityManager
-	getSecurityManager()
-	{
-		return( sec_man );
-	}
-	
-	protected GenericMessageRegistration
-	getMessageRegistration()
-	{
-		return( msg_registration );
-	}
-	
-		/**
-		 * Returns authorised buddies only
-		 */
-	
-	public List<BuddyPluginBuddy>
-	getBuddies()
-	{
-		synchronized( this ){
-			
-			List<BuddyPluginBuddy>	result = new ArrayList<BuddyPluginBuddy>();
-			
-			for (int i=0;i<buddies.size();i++){
-				
-				BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(i);
-				
-				if ( buddy.isAuthorised()){
-					
-					result.add( buddy );
-				}
-			}
-			
-			return( result );
-		}
-	}
-	
-	protected List<BuddyPluginBuddy>
-	getAllBuddies()
-	{
-		synchronized( this ){
-			
-			return( new ArrayList<BuddyPluginBuddy>( buddies ));
-		}
-	}
-	
-	public boolean
-	isAvailable()
-	{
-		try{
-			checkAvailable();
-			
-			return( true );
-			
-		}catch( Throwable e ){
-			
-			return( false );
-		}
-	}
-	
-	protected void
-	checkAvailable()
-	
-		throws BuddyPluginException
-	{
-		if ( initialisation_state == INIT_UNKNOWN ){
-			
-			throw( new BuddyPluginException( "Plugin not yet initialised" ));
-			
-		}else if ( initialisation_state == INIT_BAD ){
-			
-			throw( new BuddyPluginException( "Plugin unavailable" ));
-
-		}
-	}
-	
-
-	protected void
-	fireInitialised(
-		boolean		ok )
-	{
-		if ( ok ){
-			
-			initialisation_state = INIT_OK;
-				
-		}else{
-			
-			initialisation_state = INIT_BAD;
-		}
-		      
-		persistentDispatchInit();
-		
-		if ( ok ){
-			
-			buddy_tracker.initialise();
-		}
-		
-		List	 listeners_ref = listeners.getList();
-		
-		for (int i=0;i<listeners_ref.size();i++){
-
-			try{
-				((BuddyPluginListener)listeners_ref.get(i)).initialised( ok );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}	
-	}
-	
-	public void
-	addListener(
-		BuddyPluginListener	listener )
-	{
-		if ( listeners.contains(listener) ){
-			return;
-		}
-
-		listeners.add( listener );
-		
-		if ( initialisation_state != INIT_UNKNOWN ){
-			
-			listener.initialised( initialisation_state == INIT_OK );
-		}
-	}
-	
-	public void
-	removeListener(
-		BuddyPluginListener	listener )
-	{
-		listeners.remove( listener );
-	}
-	
-	protected Map
-	requestReceived(
-		BuddyPluginBuddy		from_buddy,
-		int						subsystem,
-		Map						content )
-	
-		throws BuddyPluginException
-	{
-		List	 listeners_ref = request_listeners.getList();
-		
-		for (int i=0;i<listeners_ref.size();i++){
-			
-			try{
-				Map reply = ((BuddyPluginBuddyRequestListener)listeners_ref.get(i)).requestReceived(from_buddy, subsystem, content);
-				
-				if ( reply != null ){
-					
-					return( reply );
-				}
-			}catch( BuddyPluginException e ){
-				
-				throw( e );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace( e );
-				
-				throw( new BuddyPluginException( "Request processing failed", e ));
-			}
-		}
-		
-		return( null );
-	}
-	
-	protected void
-   	fireAdded(
-   		BuddyPluginBuddy		buddy )
-   	{
-		if ( buddy.isAuthorised()){
-
-			buddy.setLocalAuthorisedRSSCategories( public_categories );
-			
-	   		List	 listeners_ref = listeners.getList();
-	   		
-	   		for (int i=0;i<listeners_ref.size();i++){
-	   			
-	   			try{
-	   				((BuddyPluginListener)listeners_ref.get(i)).buddyAdded( buddy );
-	 
-	   			}catch( Throwable e ){
-	   				
-	   				Debug.printStackTrace( e );
-	   			}
-	   		}
-		}
-   	}
-	
-	protected void
-   	fireRemoved(
-   		BuddyPluginBuddy		buddy )
-   	{
-		if ( buddy.isAuthorised()){
-			
-	   		List	 listeners_ref = listeners.getList();
-	   		
-	   		for (int i=0;i<listeners_ref.size();i++){
-	   			
-	   			try{
-	   				((BuddyPluginListener)listeners_ref.get(i)).buddyRemoved( buddy );
-	 
-	   			}catch( Throwable e ){
-	   				
-	   				Debug.printStackTrace( e );
-	   			}
-	   		}
-		}
-   	}
-	
-	protected void
-   	fireDetailsChanged(
-   		BuddyPluginBuddy		buddy )
-   	{
-		if ( buddy.isAuthorised()){
-			
-	   		List	 listeners_ref = listeners.getList();
-	   		
-	   		for (int i=0;i<listeners_ref.size();i++){
-	   			
-	   			try{
-	   				((BuddyPluginListener)listeners_ref.get(i)).buddyChanged( buddy );
-	 
-	   			}catch( Throwable e ){
-	   				
-	   				Debug.printStackTrace( e );
-	   			}
-	   		}
-		}
-   	}
-	
-	protected void
-   	fireYGM(
-   		BuddyPluginBuddy[]		from_buddies )
-   	{
-   		List	 listeners_ref = request_listeners.getList();
-   		
-   		for (int i=0;i<listeners_ref.size();i++){
-   			
-   			try{
-   				((BuddyPluginBuddyRequestListener)listeners_ref.get(i)).pendingMessages( from_buddies );
- 
-   			}catch( Throwable e ){
-   				
-   				Debug.printStackTrace( e );
-   			}
-   		}
-   	}
-
-	protected void
- 	fireEnabledStateChanged()
- 	{
-		final boolean enabled = !plugin_interface.getPluginState().isDisabled() && isEnabled();
-
- 		List	 listeners_ref = listeners.getList();
- 		
- 		for (int i=0;i<listeners_ref.size();i++){
- 			
- 			try{
- 				((BuddyPluginListener)listeners_ref.get(i)).enabledStateChanged( enabled );
-
- 			}catch( Throwable e ){
- 				
- 				Debug.printStackTrace( e );
- 			}
- 		}
- 	}
-	
-	protected void
-	rethrow(
-		String		reason,
-		Throwable	e )
-	
-		throws BuddyPluginException
-	{
-		logMessage( reason, e );
-
-		if ( e instanceof CryptoManagerPasswordException ){
-		
-		
-			throw( new BuddyPluginPasswordException(((CryptoManagerPasswordException)e).wasIncorrect(), reason, e ));
-		
-		}else{
-		
-			throw( new BuddyPluginException( reason, e ));
-		}
-	}
-	
-
-	public InputStream
-	handleURLProtocol(
-		 AZPluginConnection			connection,
-		String						arg_str )
-	
-		throws IPCException
-	{
-		String[]	args = arg_str.split( "&" );
-		
-		String		pk 			= null;
-		String		category	= "All";
-		byte[]		hash		= null;
-		
-		for (String arg: args ){
-			
-			String[]	bits = arg.split( "=" );
-			
-			String	lhs = bits[0];
-			String	rhs	= UrlUtils.decode( bits[1] );
-			
-			if ( lhs.equals( "pk" )){
-				
-				pk		= rhs;
-				
-			}else if ( lhs.equals( "cat" )){
-				
-				category = rhs;
-				
-			}else if ( lhs.equals( "hash" )){
-				
-				hash	= Base32.decode(rhs);
-			}
-		}
-		
-		if ( pk == null ){
-			
-			throw( new IPCException( "Public key missing from '" + arg_str + "'" ));
-		}
-		
-		BuddyPluginBuddy	buddy	= getBuddyFromPublicKey( pk );
-
-		if ( buddy == null ){
-			
-			throw( new IPCException( "Buddy with public key '" + pk + "' not found" ));
-		}
-		
-		if ( hash == null ){
-			
-			return( handleUPRSS( connection, buddy, category ));
-			
-		}else{
-			
-			return( handleUPTorrent( connection, buddy, category, hash ));
-		}
-	}
-	
-	public InputStream
-	handleUPRSS(
-		final AZPluginConnection	connection,
-		BuddyPluginBuddy			buddy,
-		String						category )
-	
-		throws IPCException
-	{
-		if ( !buddy.isOnline( true )){
-			
-			throw( new IPCException( "Buddy isn't online" ));
-		}
-		
-		Map<String,Object>	msg = new HashMap<String, Object>();
-
-		final String if_mod 	= connection.getRequestProperty( "If-Modified-Since" );
-
-		try{
-			msg.put( "cat", category.getBytes( "UTF-8" ));
-									
-			if ( if_mod != null ){
-				
-				msg.put( "if_mod", if_mod );
-			}
-			
-			// String etag		= connection.getRequestProperty( "If-None-Match" );
-					
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-		
-		final Object[] 		result 		= { null };
-		final AESemaphore	result_sem 	= new AESemaphore( "BuddyPlugin:rss" );
-				
-		final String	etag = buddy.getPublicKey() + "-" + category;
-		
-		az2_handler.sendAZ2RSSMessage( 
-			buddy,
-			msg,
-			new BuddyPluginAZ2TrackerListener()
-			{
-				public Map
-				messageReceived(
-					BuddyPluginBuddy	buddy,
-					Map					message )
-				{
-					try{						
-						byte[] bytes = (byte[])message.get( "rss" );
-					
-						ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
-						
-						result[0] = bais;
-						
-						connection.setHeaderField( "ETag", etag );
-						
-						byte[] b_last_mod = (byte[])message.get( "last_mod" );
-						
-						if ( b_last_mod != null ){
-						
-							String	last_mod = new String( b_last_mod, "UTF-8" );
-							
-							connection.setHeaderField( "Last-Modified", last_mod );
-							
-							if ( if_mod != null && if_mod.equals( last_mod ) && bytes.length == 0 ){
-								
-								connection.setResponse( HttpURLConnection.HTTP_NOT_MODIFIED, "Not Modified" );
-							}
-						}
-						
-						result_sem.release();
-						
-					}catch( Throwable e ){
-					
-						messageFailed( buddy, e );
-					}
-					
-					return( null );
-				}
-				
-				public void
-				messageFailed(
-					BuddyPluginBuddy	buddy,
-					Throwable			cause )
-				{					
-					result[0] = new IPCException( "Read failed", cause );
-					
-					result_sem.release();
-				}
-			});
-		
-		result_sem.reserve( 60*1000 );
-		
-		if ( result[0] == null ){
-			
-			throw( new IPCException( "Timeout" ));
-			
-		}else if ( result[0] instanceof InputStream ){
-			
-			return((InputStream)result[0]);
-			
-		}else{
-			
-			throw((IPCException)result[0]);
-		}
-	}
-
-	public InputStream
-	handleUPTorrent(
-		final AZPluginConnection	connection,
-		final BuddyPluginBuddy		buddy,
-		String						category,
-		final byte[]				hash )
-	
-		throws IPCException
-	{
-		final long timeout = 120*1000;
-
-		final Object[] 		result 		= { null };
-		final AESemaphore	result_sem 	= new AESemaphore( "BuddyPlugin:upt" );
-			
-		log( "Attempting to download torrent for " + Base32.encode( hash ));
-		
-			// first try and get torrent direct from the buddy
-		
-		if ( buddy.isOnline( true )){
-
-			try{
-				
-				Map<String,Object>	msg = new HashMap<String, Object>();
-			
-				try{
-					msg.put( "cat", category.getBytes( "UTF-8" ));
-									
-					msg.put( "hash", hash );
-							
-				}catch( Throwable e ){
-					
-					Debug.out( e );
-				}
-							
-				az2_handler.sendAZ2RSSMessage( 
-					buddy,
-					msg,
-					new BuddyPluginAZ2TrackerListener()
-					{
-						private boolean	result_set;
-					
-						public Map
-						messageReceived(
-							BuddyPluginBuddy	buddy,
-							Map					message )
-						{
-							try{						
-								byte[] bytes = (byte[])message.get( "torrent" );
-									
-								log( "    torrent downloaded from buddy" );
-								
-								setResult( bytes );
-																
-							}catch( Throwable e ){
-							
-								messageFailed( buddy, e );
-							}
-							
-							return( null );
-						}
-						
-						public void
-						messageFailed(
-							BuddyPluginBuddy	buddy,
-							Throwable			cause )
-						{					
-							setResult( new IPCException( "Read failed", cause ));
-						}
-						
-						protected void
-						setResult(
-							Object		obj )
-						{
-							synchronized( result ){
-								
-								if ( result_set ){
-									
-									return;
-								}
-								
-								result_set = true;
-								
-								if ( !( result[0] instanceof byte[] )){
-								
-									result[0] = obj;
-								}
-								
-								result_sem.release();
-							}
-						}
-					});
-			}catch( Throwable e ){
-				
-				result[0] = new IPCException( "Buddy torrent get failed", e );
-				
-				result_sem.release();
-			}
-		}else{
-			
-			result[0] = new IPCException( "Buddy is offline" );
-
-			result_sem.release();
-		}
-		
-			// second try and get via magnet
-		
-		final MagnetPlugin	magnet_plugin = getMagnetPlugin();
-		
-		if ( magnet_plugin == null ){
-		
-			synchronized( result ){
-				
-				if ( result[0] == null ){
-					
-					result[0] = new IPCException( "Magnet plugin unavailable" );
-				}
-			}
-				
-			result_sem.release();
-			
-		}else{
-
-			new AEThread2( "BuddyPlugin:mag", true )
-			{
-				private boolean result_set;
-				
-				public void
-				run()
-				{
-					try{
-						
-						if ( buddy.isOnline( true )){
-							
-							Thread.sleep(10*1000);
-						}
-						
-						synchronized( result ){
-
-							if ( result[0] instanceof byte[] ){
-								
-								setResult( null );
-								
-								return;
-							}
-						}
-						
-						byte[] torrent_data = magnet_plugin.download(
-							new MagnetPluginProgressListener()
-							{
-								public void
-								reportSize(
-									long	size )
-								{
-								}
-								
-								public void
-								reportActivity(
-									String	str )
-								{
-									log( "    MagnetDownload: " + str );
-								}
-								
-								public void
-								reportCompleteness(
-									int		percent )
-								{
-								}
-								
-								public void
-								reportContributor(
-									InetSocketAddress	address )
-								{
-								}
-								
-								public boolean 
-								verbose() 
-								{
-									return( false );
-								}
-								
-								public boolean 
-								cancelled() 
-								{
-									return( false );
-								}
-							},
-							hash,
-							"",
-							new InetSocketAddress[0],
-							timeout,
-							MagnetPlugin.FL_NONE );
-						
-						if ( torrent_data == null ){
-							
-							setResult( new IPCException( "Magnet timeout" ));
-													
-						}else{					
-							
-							log( "    torrent downloaded from magnet" );
-
-							setResult( torrent_data );
-						}
-					}catch( Throwable e ){
-						
-						setResult( new IPCException( "Magnet get failed", e ));
-					}
-				}
-				
-				protected void
-				setResult(
-					Object		obj )
-				{
-					synchronized( result ){
-						
-						if ( result_set ){
-							
-							return;
-						}
-						
-						result_set = true;
-						
-						if ( obj != null ){
-							
-							if ( 	result[0] == null ||
-									( obj instanceof byte[] && !( result[0] instanceof byte[] ))){
-								
-								result[0] = obj;
-							}
-						}
-							
-						result_sem.release();
-					}
-				}
-			}.start();
-		}
-		
-		long	start = SystemTime.getMonotonousTime();
-				
-		if ( result_sem.reserve(timeout )){
-			
-			if ( !( result[0] instanceof byte[] )){
-		
-				long	rem = timeout - ( SystemTime.getMonotonousTime() - start );
-				
-				if ( rem > 0 ){
-				
-					result_sem.reserve(rem );
-				}
-			}
-		}
-		
-		if ( result[0] == null ){
-			
-			log( "    torrent download timeout" );
-
-			throw( new IPCException( "Timeout" ));
-			
-		}else if ( result[0] instanceof byte[] ){
-						
-			return( new ByteArrayInputStream((byte[])result[0]));
-			
-		}else{
-			
-			IPCException error = (IPCException)result[0];
-			
-			log( "    torrent downloaded failed: " + Debug.getNestedExceptionMessage( error ));
-
-			throw( error );
-		}
-	}
-
-	protected MagnetPlugin
-	getMagnetPlugin()
-	{
-		PluginInterface  pi  = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass( MagnetPlugin.class );
-	
-		if ( pi == null ){
-			
-			return( null );
-		}
-		
-		return((MagnetPlugin)pi.getPlugin());
-	}
-	
-	public feedDetails
-	getRSS(
-		BuddyPluginBuddy		buddy,
-		String					category,
-		String					if_mod )
-	
-		throws BuddyPluginException
-	{
-		if ( !buddy.isLocalRSSCategoryAuthorised( category )){
-			
-			throw( new BuddyPluginException( "Unauthorised category '" + category + "'" ));
-		}
-		
-		buddy.localRSSCategoryRead( category );
-		
-		Download[] downloads = plugin_interface.getDownloadManager().getDownloads();
-		
-		List<Download>	selected_dls = new ArrayList<Download>();
-		
-		long	fingerprint	= 0;
-		
-		for (int i=0;i<downloads.length;i++){
-			
-			Download download = downloads[i];
-			
-			Torrent torrent = download.getTorrent();
-			
-			if ( torrent == null ){
-				
-				continue;
-			}
-			
-			String dl_cat = download.getAttribute( ta_category );
-		
-			if ( 	category.equalsIgnoreCase( "all" ) ||
-					( dl_cat != null && dl_cat.equals( category ))){
-				
-				if ( !TorrentUtils.isReallyPrivate( PluginCoreUtils.unwrap( torrent ))){
-					
-					selected_dls.add( download );
-					
-					byte[] hash = torrent.getHash();
-					
-					int	num = (hash[0]<<24)&0xff000000 | (hash[1] << 16)&0x00ff0000 | (hash[2] << 8)&0x0000ff00 | hash[3]&0x000000ff;
-
-					fingerprint += num;
-				}
-			}
-		}
-		
-		PluginConfig pc = plugin_interface.getPluginconfig();
-
-		String	feed_finger_key = "feed_finger.category." + category;
-		String	feed_date_key 	= "feed_date.category." + category;
-
-		long	existing_fingerprint 	= pc.getPluginLongParameter( feed_finger_key, 0 );
-		long	feed_date 				= pc.getPluginLongParameter( feed_date_key, 0 );
-
-		long	now = SystemTime.getCurrentTime();
-
-		if ( existing_fingerprint == fingerprint ){
-			
-				// update every now and then to pick up new peer/seed values
-			
-			if ( selected_dls.size() > 0 ){
-
-				if ( 	now < feed_date ||
-						now - feed_date > FEED_UPDATE_MIN_MILLIS ){
-					
-					feed_date = now;
-				
-					pc.setPluginParameter( feed_date_key, feed_date );
-				}
-			}
-		}else{
-			
-			pc.setPluginParameter( feed_finger_key, fingerprint );
-			
-			
-				// ensure feed date goes up
-			
-			if ( now <= feed_date ){
-				
-				feed_date++;
-				
-			}else{
-				
-				feed_date = now;
-			}
-			
-			pc.setPluginParameter( feed_date_key, feed_date );
-		}
-		
-		String last_modified = TimeFormatter.getHTTPDate( feed_date );
-
-		if ( if_mod != null && if_mod.equals( last_modified )){
-			
-			return( new feedDetails( new byte[0], last_modified ));
-		}
-				
-		ByteArrayOutputStream	os = new ByteArrayOutputStream();
-			
-		try{
-			PrintWriter pw = new PrintWriter(new OutputStreamWriter( os, "UTF-8" ));
-			
-			pw.println( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
-			
-			pw.println( "<rss version=\"2.0\" xmlns:vuze=\"http://www.vuze.com\">" );
-			
-			pw.println( "<channel>" );
-			
-			pw.println( "<title>" + escape( category ) + "</title>" );
-			
-			Collections.sort(
-				selected_dls,
-				new Comparator<Download>()
-				{
-					public int 
-					compare(
-						Download d1, 
-						Download d2) 
-					{
-						long	added1 = getAddedTime( d1 )/1000;
-						long	added2 = getAddedTime( d2 )/1000;
-		
-						return((int)(added2 - added1 ));
-					}
-				});
-								
-							
-			pw.println(	"<pubDate>" + last_modified + "</pubDate>" );
-		
-			for (int i=0;i<selected_dls.size();i++){
-				
-				Download download = (Download)selected_dls.get( i );
-				
-				DownloadManager	core_download = PluginCoreUtils.unwrap( download );
-				
-				Torrent torrent = download.getTorrent();
-				
-				String	hash_str = Base32.encode( torrent.getHash());
-				
-				pw.println( "<item>" );
-				
-				pw.println( "<title>" + escape( download.getName()) + "</title>" );
-				
-				pw.println( "<guid>" + hash_str + "</guid>" );
-				
-				long added = core_download.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME);
-				
-				pw.println(	"<pubDate>" + TimeFormatter.getHTTPDate( added ) + "</pubDate>" );
-				
-				pw.println(	"<vuze:size>" + torrent.getSize()+ "</vuze:size>" );
-				pw.println(	"<vuze:assethash>" + hash_str + "</vuze:assethash>" );
-				
-				String url = "azplug:?id=azbuddy&name=Friends&arg=";
-				
-				String arg = "pk=" + getPublicKey() + "&cat=" + category + "&hash=" + Base32.encode(torrent.getHash());
-
-				url += URLEncoder.encode( arg, "UTF-8" );
-			
-				pw.println( "<vuze:downloadurl>" + escape( url ) + "</vuze:downloadurl>" );
-		
-				DownloadScrapeResult scrape = download.getLastScrapeResult();
-				
-				if ( scrape != null && scrape.getResponseType() == DownloadScrapeResult.RT_SUCCESS ){
-					
-					pw.println(	"<vuze:seeds>" + scrape.getSeedCount() + "</vuze:seeds>" );
-					pw.println(	"<vuze:peers>" + scrape.getNonSeedCount() + "</vuze:peers>" );
-				}
-				
-				pw.println( "</item>" );
-			}
-			
-			pw.println( "</channel>" );
-			
-			pw.println( "</rss>" );
-		
-			pw.flush();
-			
-			return( new feedDetails( os.toByteArray(), last_modified ));
-			
-		}catch( IOException e ){
-			
-			throw( new BuddyPluginException( "", e ));
-		}
-	}
-	
-	public byte[]
-	getRSSTorrent(
-		BuddyPluginBuddy		buddy,
-		String					category,
-		byte[]					hash )
-	
-		throws BuddyPluginException
-	{
-		if ( !buddy.isLocalRSSCategoryAuthorised( category )){
-			
-			throw( new BuddyPluginException( "Unauthorised category '" + category + "'" ));
-		}
-		
-		try{
-			Download download = plugin_interface.getDownloadManager().getDownload( hash );
-			
-			if ( download != null ){
-				
-				Torrent	torrent = download.getTorrent();
-			
-				if ( torrent != null ){
-								
-					String dl_cat = download.getAttribute( ta_category );
-					
-					if ( 	category.equalsIgnoreCase( "all" ) ||
-							( dl_cat != null && dl_cat.equals( category ))){
-						
-						if ( !TorrentUtils.isReallyPrivate( PluginCoreUtils.unwrap( torrent ))){
-							
-							torrent = torrent.removeAdditionalProperties();
-							
-							return( torrent.writeToBEncodedData());
-						}
-					}
-				}
-			}
-		}catch( Throwable e ){
-			
-			throw( new BuddyPluginException( "getTorrent failed", e ));
-		}
-		
-		throw( new BuddyPluginException( "Not found" ));
-	}		
-
-	protected long
-	getAddedTime(
-		Download	download )
-	{
-		DownloadManager	core_download = PluginCoreUtils.unwrap( download );
-		
-		return( core_download.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME));
-	}
-	
-	protected String
-	escape(
-		String	str )
-	{
-		return( XUXmlWriter.escapeXML(str));
-	}
-	
-	public void
-	addRequestListener(
-		BuddyPluginBuddyRequestListener	listener )
-	{
-		request_listeners.add( listener );
-	}
-	
-	public void
-	removeRequestListener(
-		BuddyPluginBuddyRequestListener	listener )
-	{
-		request_listeners.remove( listener );
-	}
-	
-	public void
-	logMessage(
-		String		str,
-		Throwable	e )
-	{
-		logMessage( str + ": " + Debug.getNestedExceptionMessage(e), true );
-	}
-	
-	public void
-	logMessage(
-		String		str )
-	{
-		logMessage( str, false );
-	}
-	
-	public void
-	logMessage(
-		String		str,
-		boolean		is_error )
-	{
-		log( str );
-		
-		Iterator it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((BuddyPluginListener)it.next()).messageLogged( str, is_error );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace( e );
-			}
-		}
-	}
-	
-	public void
-	log(
-		String		str )
-	{
-		logger.log( str );
-	}
-	
-	public void
-	log(
-		String		str,
-		Throwable	e )
-	{
-		logger.log( str + ": " + Debug.getNestedExceptionMessageAndStack( e ));
-	}
-
-	private class
-	publishDetails
-		implements Cloneable
-	{
-		private byte[]			public_key;
-		private InetAddress		ip;
-		private int				tcp_port;
-		private int				udp_port;
-		private String			nick_name;
-		private int				online_status		= STATUS_ONLINE;
-		
-		private boolean			enabled;
-		private boolean			published;
-		
-		private int				sequence;
-		
-		protected publishDetails
-		getCopy()
-		{
-			try{
-				publishDetails copy = (publishDetails)clone();
-				
-				copy.published = false;
-				
-				return( copy );
-				
-			}catch( Throwable e ){
-				
-				return( null);
-			}
-		}
-		
-		protected boolean
-		isPublished()
-		{
-			return( published );
-		}
-		
-		protected void
-		setPublished(
-			boolean		b )
-		{
-			published	= b;
-		}
-		
-		protected boolean
-		isEnabled()
-		{
-			return( enabled );
-		}
-		
-		protected void
-		setEnabled(
-			boolean	_enabled )
-		{
-			enabled	= _enabled;
-		}
-		
-		protected void
-		setSequence(
-			int		seq )
-		{
-			sequence = seq;
-		}
-		
-		protected int
-		getSequence()
-		{
-			return( sequence );
-		}
-		
-		protected byte[]
-		getPublicKey()
-		{
-			return( public_key );
-		}
-		
-		protected void
-		setPublicKey(
-			byte[]		k )
-		{
-			public_key	= k;
-		}
-		
-		protected InetAddress
-		getIP()
-		{
-			return( ip );
-		}
-		
-		protected void
-		setIP(
-			InetAddress	_ip )
-		{
-			ip	= _ip;
-		}
-		
-		protected int
-		getTCPPort()
-		{
-			return( tcp_port );
-		}
-		
-		protected void
-		setTCPPort(
-			int		_port )
-		{
-			tcp_port = _port;
-		}
-		
-		protected int
-		getUDPPort()
-		{
-			return( udp_port );
-		}
-		
-		protected void
-		setUDPPort(
-			int		_port )
-		{
-			udp_port = _port;
-		}
-		
-		protected String
-		getNickName()
-		{
-			return( nick_name );
-		}
-		
-		protected void
-		setNickName(
-			String		 n )
-		{
-			nick_name	= n;
-		}
-		
-		protected int
-		getOnlineStatus()
-		{
-			return( online_status );
-		}
-		
-		protected void
-		setOnlineStatus(
-			int		_status )
-		{
-			online_status = _status;
-		}
-		
-		protected String
-		getString()
-		{
-			return( "enabled=" + enabled + ",ip=" + ip + ",tcp=" + tcp_port + ",udp=" + udp_port + ",stat=" + online_status + ",key=" + (public_key==null?"<none>":Base32.encode( public_key )));
-		}
-	}
-	
-	protected interface
-	operationListener
-	{
-		public void
-		complete();
-	}
-	
-	public interface
-	cryptoResult
-	{
-		public byte[]
-		getChallenge();
-		
-		public byte[]
-		getPayload();
-	}
-	
-	protected class
-	feedDetails
-	{
-		private byte[]		contents;
-		private String		last_modified;
-		
-		protected
-		feedDetails(
-			byte[]		_contents,
-			String		_last_modified )
-		{
-			contents		= _contents;
-			last_modified	= _last_modified;
-		}
-		
-		protected byte[]
-		getContent()
-		{
-			return( contents );
-		}
-		
-		protected String
-		getLastModified()
-		{
-			return( last_modified );
-		}
-	}
-}
+/*
+ * Created on Mar 19, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+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;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.util.protocol.azplug.AZPluginConnection;
+import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
+import org.gudy.azureus2.plugins.*;
+import org.gudy.azureus2.plugins.ddb.*;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadException;
+import org.gudy.azureus2.plugins.download.DownloadScrapeResult;
+import org.gudy.azureus2.plugins.ipc.IPCException;
+import org.gudy.azureus2.plugins.logging.LoggerChannel;
+import org.gudy.azureus2.plugins.messaging.MessageException;
+import org.gudy.azureus2.plugins.messaging.MessageManager;
+import org.gudy.azureus2.plugins.messaging.generic.GenericMessageConnection;
+import org.gudy.azureus2.plugins.messaging.generic.GenericMessageHandler;
+import org.gudy.azureus2.plugins.messaging.generic.GenericMessageRegistration;
+import org.gudy.azureus2.plugins.network.ConnectionManager;
+import org.gudy.azureus2.plugins.network.RateLimiter;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
+import org.gudy.azureus2.plugins.ui.UIInstance;
+import org.gudy.azureus2.plugins.ui.UIManagerListener;
+import org.gudy.azureus2.plugins.ui.config.*;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
+import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
+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.plugins.utils.*;
+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.pluginsimpl.local.PluginCoreUtils;
+
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.security.*;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.core.util.bloom.BloomFilter;
+import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
+import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
+import com.aelitis.azureus.plugins.magnet.MagnetPlugin;
+import com.aelitis.azureus.plugins.magnet.MagnetPluginProgressListener;
+import com.aelitis.azureus.plugins.net.buddy.tracker.BuddyPluginTracker;
+
+public class 
+BuddyPlugin 
+	implements Plugin
+{
+	public static final boolean SUPPORT_ONLINE_STATUS		= true;
+	
+	public static final int VERSION_INITIAL	= 1;
+	public static final int VERSION_CHAT	= 2;
+	public static final int VERSION_CURRENT	= VERSION_CHAT;
+	
+	
+	public static final int MT_V3_CHAT		= 1;
+	
+	private static final int FEED_UPDATE_MIN_MILLIS	= 6*60*60*1000;
+	
+	public static final int MAX_MESSAGE_SIZE	= 4*1024*1024;
+	
+	public static final int	SUBSYSTEM_INTERNAL	= 0;
+	public static final int	SUBSYSTEM_AZ2		= 1;
+	public static final int	SUBSYSTEM_AZ3		= 2;
+	
+	protected static final int	SUBSYSTEM_MSG_TYPE_BASE	= 1024;
+	
+	public static final int STATUS_ONLINE			= 0;
+	public static final int STATUS_AWAY				= 1;
+	public static final int STATUS_NOT_AVAILABLE	= 2;
+	public static final int STATUS_BUSY				= 3;
+	public static final int STATUS_APPEAR_OFFLINE	= 4;
+	
+	public static final String[] STATUS_VALUES 	= { "0", "1", "2", "3", "4" };
+	
+	public static final String[] STATUS_KEYS = {
+		"os_online", "os_away", "os_not_avail", "os_busy", "os_offline"
+	};
+
+	public static final String[] STATUS_STRINGS = new String[ STATUS_KEYS.length ];
+	
+	protected static final int RT_INTERNAL_REQUEST_PING		= 1;
+	protected static final int RT_INTERNAL_REPLY_PING		= 2;
+	protected static final int RT_INTERNAL_REQUEST_CLOSE	= 3;
+	protected static final int RT_INTERNAL_REPLY_CLOSE		= 4;
+	protected static final int RT_INTERNAL_FRAGMENT			= 5;
+	
+	protected static final boolean TRACE = false; 
+
+	private static final String VIEW_ID = "azbuddy";
+
+	private static final int	INIT_UNKNOWN		= 0;
+	private static final int	INIT_OK				= 1;
+	private static final int	INIT_BAD			= 2;
+	
+	private static final int	MAX_UNAUTH_BUDDIES	= 16;
+	
+	public static final int	TIMER_PERIOD	= 10*1000;
+	
+	private static final int	BUDDY_STATUS_CHECK_PERIOD_MIN	= 3*60*1000;
+	private static final int	BUDDY_STATUS_CHECK_PERIOD_INC	= 1*60*1000;
+	
+	protected static final int	STATUS_REPUBLISH_PERIOD		= 10*60*1000;
+	private static final int	STATUS_REPUBLISH_TICKS		= STATUS_REPUBLISH_PERIOD/TIMER_PERIOD;
+
+	private static final int	CHECK_YGM_PERIOD			= 5*60*1000;
+	private static final int	CHECK_YGM_TICKS				= CHECK_YGM_PERIOD/TIMER_PERIOD;
+	private static final int	YGM_BLOOM_LIFE_PERIOD		= 60*60*1000;
+	private static final int	YGM_BLOOM_LIFE_TICKS		= YGM_BLOOM_LIFE_PERIOD/TIMER_PERIOD;
+
+	private static final int	SAVE_CONFIG_PERIOD			= 60*1000;
+	private static final int	SAVE_CONFIG_TICKS			= SAVE_CONFIG_PERIOD/TIMER_PERIOD;
+
+	public static final int		PERSISTENT_MSG_RETRY_PERIOD		= 5*60*1000;
+	private static final int	PERSISTENT_MSG_CHECK_PERIOD		= 60*1000;
+	private static final int	PERSISTENT_MSG_CHECK_TICKS		= PERSISTENT_MSG_CHECK_PERIOD/TIMER_PERIOD;
+
+	private static final int	UNAUTH_BLOOM_RECREATE		= 120*1000;
+	private static final int	UNAUTH_BLOOM_CHUNK			= 1000;
+
+	private static final int	BLOOM_CHECK_PERIOD			= UNAUTH_BLOOM_RECREATE/2;
+	private static final int	BLOOM_CHECK_TICKS			= BLOOM_CHECK_PERIOD/TIMER_PERIOD;
+
+	public static final int STREAM_CRYPTO 	= MessageManager.STREAM_ENCRYPTION_RC4_REQUIRED;
+	public static final int BLOCK_CRYPTO	= SESecurityManager.BLOCK_ENCRYPTION_AES;
+	
+	//public static final int STREAM_CRYPTO 	= MessageManager.STREAM_ENCRYPTION_NONE;
+	//public static final int BLOCK_CRYPTO	= SESecurityManager.BLOCK_ENCRYPTION_NONE;
+	
+	private volatile int	 initialisation_state = INIT_UNKNOWN;
+	
+	private PluginInterface	plugin_interface;
+	
+	private LoggerChannel	logger;
+	
+	private BooleanParameter 		classic_enabled_param; 
+	private StringParameter 		nick_name_param;
+	private StringListParameter 	online_status_param;
+	private BooleanParameter 		enable_chat_notifications; 
+	private StringParameter 		cat_pub;
+
+	
+	private BooleanParameter 		beta_enabled_param; 
+
+	
+	private boolean			ready_to_publish;
+	private publishDetails	current_publish		= new publishDetails();
+	private publishDetails	latest_publish		= current_publish;
+	private long			last_publish_start;
+	private TimerEvent		republish_delay_event;
+	
+	private BloomFilter		unauth_bloom;
+	private long			unauth_bloom_create_time;
+	private BloomFilter	ygm_unauth_bloom;
+
+	
+	private AsyncDispatcher	publish_dispatcher = new AsyncDispatcher();
+	
+	private	DistributedDatabase 	ddb;
+	
+	private CryptoHandler ecc_handler = CryptoManagerFactory.getSingleton().getECCHandler();
+
+	private List<BuddyPluginBuddy>	buddies 	= new ArrayList<BuddyPluginBuddy>();
+	
+	private List<BuddyPluginBuddy>	connected_at_close;
+	
+	private Map<String,BuddyPluginBuddy>		buddies_map	= new HashMap<String,BuddyPluginBuddy>();
+	
+	private CopyOnWriteList<BuddyPluginListener>				listeners 			= new CopyOnWriteList<BuddyPluginListener>();
+	private CopyOnWriteList<BuddyPluginBuddyRequestListener>	request_listeners	= new CopyOnWriteList<BuddyPluginBuddyRequestListener>(); 
+		
+	private SESecurityManager	sec_man;
+
+	private GenericMessageRegistration	msg_registration;
+			
+	private RateLimiter	inbound_limiter; 
+		
+	private RateLimiter	outbound_limiter; 
+	
+	private boolean		config_dirty;
+	
+	private Random	random = RandomUtils.SECURE_RANDOM;
+	
+	private BuddyPluginAZ2		az2_handler;
+	
+	private List<DistributedDatabaseContact>	publish_write_contacts = new ArrayList<DistributedDatabaseContact>();
+	
+	private int		status_seq;
+	
+	{
+		while( status_seq == 0 ){
+			
+			status_seq = random.nextInt();
+		}
+	}
+		
+	private Set<BuddyPluginBuddy>			pd_preinit		= new HashSet<BuddyPluginBuddy>();
+	
+	private List<BuddyPluginBuddy>			pd_queue 		= new ArrayList<BuddyPluginBuddy>();
+	private AESemaphore						pd_queue_sem	= new AESemaphore( "BuddyPlugin:persistDispatch");
+	private AEThread2						pd_thread;
+	
+	private boolean		bogus_ygm_written;
+	
+	private BuddyPluginTracker	buddy_tracker;
+	
+	private TorrentAttribute	ta_category;
+
+	private Set<String>	public_tags_or_categories = new HashSet<String>();
+	
+	
+	private BuddyPluginBeta		beta_plugin;
+	
+	private BuddyPluginViewInterface	swt_ui;
+	
+	public static void
+	load(
+		PluginInterface		plugin_interface )
+	{
+		String name = 
+			plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "Views.plugins." + VIEW_ID + ".title" );
+		
+		plugin_interface.getPluginProperties().setProperty( "plugin.version", 	"1.0" );
+		plugin_interface.getPluginProperties().setProperty( "plugin.name", 		name );
+	}
+
+	public void
+	initialize(
+		final PluginInterface		_plugin_interface )
+	{		
+		plugin_interface	= _plugin_interface;
+		
+			
+		ta_category		= plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_CATEGORY );
+
+		az2_handler = new BuddyPluginAZ2( this );
+				
+		sec_man = plugin_interface.getUtilities().getSecurityManager();
+
+		logger = plugin_interface.getLogger().getChannel( "Friends" );
+		
+		logger.setDiagnostic();
+				
+		final LocaleUtilities lu = plugin_interface.getUtilities().getLocaleUtilities();
+		
+		lu.addListener(
+			new LocaleListener()
+			{
+				public void 
+				localeChanged(
+					Locale		l )
+				{
+					updateLocale(lu);
+				}
+			});
+		
+		updateLocale(lu);
+		
+		BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel( "Views.plugins." + VIEW_ID + ".title" );
+			
+			// enabled
+
+		classic_enabled_param = config.addBooleanParameter2( "azbuddy.enabled", "azbuddy.enabled", false );
+				
+			// nickname
+
+		nick_name_param = config.addStringParameter2( "azbuddy.nickname", "azbuddy.nickname", "" );
+
+		nick_name_param.setGenerateIntermediateEvents( false );
+		
+		nick_name_param.addListener(
+				new ParameterListener()
+				{
+					public void
+					parameterChanged(
+						Parameter	param )
+					{
+						updateNickName( nick_name_param.getValue());
+					}
+				});
+		
+			// online status
+
+		String[]	os_values 	= STATUS_VALUES;
+		String[]	os_labels	= STATUS_STRINGS;
+		
+		online_status_param = config.addStringListParameter2(
+				"azbuddy.online_status", "azbuddy.online_status",
+				os_values,
+				os_labels,
+				os_values[0] );
+				
+		online_status_param.addListener(
+				new ParameterListener()
+				{
+					public void
+					parameterChanged(
+						Parameter	param )
+					{
+						 int status = Integer.parseInt( online_status_param.getValue());
+						 
+						 updateOnlineStatus( status );
+					}
+				});
+		
+		online_status_param.setVisible( SUPPORT_ONLINE_STATUS  ); // If we add this then use proper message texts in the STATUS_STRINGS
+		
+			// protocol speed
+		
+		final IntParameter	protocol_speed = config.addIntParameter2( "azbuddy.protocolspeed", "azbuddy.protocolspeed", 32 );
+		
+		protocol_speed.setMinimumRequiredUserMode( Parameter.MODE_ADVANCED );
+		
+		ConnectionManager cman = plugin_interface.getConnectionManager();
+		
+		int inbound_limit = protocol_speed.getValue()*1024;
+
+		inbound_limiter 	= cman.createRateLimiter( "buddy_up", inbound_limit );	
+		outbound_limiter 	= cman.createRateLimiter( "buddy_down", 0 );
+
+		protocol_speed.addListener(
+				new ParameterListener()
+				{
+					public void
+					parameterChanged(
+						Parameter	param )
+					{
+						inbound_limiter.setRateLimitBytesPerSecond( protocol_speed.getValue()*1024 );
+					}
+				});
+		
+			// chat notifications
+		
+		enable_chat_notifications = config.addBooleanParameter2( "azbuddy.enable_chat_notif", "azbuddy.enable_chat_notif", true );
+		
+			// default published tags or cats
+		
+		cat_pub = config.addStringParameter2( "azbuddy.enable_cat_pub", "azbuddy.enable_cat_pub", "" );
+		
+		cat_pub.setGenerateIntermediateEvents( false );
+		
+		setPublicTagsOrCategories( cat_pub.getValue(), false );
+		
+		final BooleanParameter tracker_enable = config.addBooleanParameter2("azbuddy.tracker.enabled", "azbuddy.tracker.enabled", true );
+
+		cat_pub.addListener(
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					Parameter 	param ) 
+				{
+					setPublicTagsOrCategories( cat_pub.getValue(), false);
+				}
+			});
+		
+		config.createGroup(
+			"label.classic",
+			new Parameter[]{
+					classic_enabled_param, nick_name_param, online_status_param,
+					protocol_speed, enable_chat_notifications, cat_pub, tracker_enable
+			});
+		
+			// decentralised stuff
+		
+		
+		beta_enabled_param = config.addBooleanParameter2( "azbuddy.dchat.decentralized.enabled", "azbuddy.dchat.decentralized.enabled", true );
+		
+		
+		config.createGroup(
+				"azbuddy.dchat.decentralized",
+				new Parameter[]{
+						beta_enabled_param, 
+				});
+		
+		
+		
+			// config end
+			
+		beta_plugin = new BuddyPluginBeta( plugin_interface, this, beta_enabled_param );
+		
+		final TableContextMenuItem menu_item_itorrents = 
+			plugin_interface.getUIManager().getTableManager().addContextMenuItem(TableManager.TABLE_MYTORRENTS_INCOMPLETE, "azbuddy.contextmenu");
+		final TableContextMenuItem menu_item_ctorrents 	= 
+			plugin_interface.getUIManager().getTableManager().addContextMenuItem(TableManager.TABLE_MYTORRENTS_COMPLETE, "azbuddy.contextmenu");
+		
+		menu_item_itorrents.setStyle(TableContextMenuItem.STYLE_MENU);
+		menu_item_ctorrents.setStyle(TableContextMenuItem.STYLE_MENU);
+		
+		MenuItemFillListener	menu_fill_listener = 
+			new MenuItemFillListener()
+			{
+				public void
+				menuWillBeShown(
+					MenuItem	menu,
+					Object		_target )
+				{
+					menu.removeAllChildItems();
+
+					if ( !( isClassicEnabled() && isAvailable())){
+						
+						menu.setEnabled( false );
+						
+						return;
+					}
+					
+					final List<Torrent>	torrents = new ArrayList<Torrent>();
+								
+					if ( _target instanceof TableRow ){
+						
+						addDownload( torrents, (TableRow)_target );
+	
+					}else{
+						
+						TableRow[] rows = (TableRow[])_target;
+					     
+						for ( TableRow row: rows ){
+							
+							addDownload( torrents, row );
+						}
+					}
+					
+					if ( torrents.size() == 0 ){
+						
+						menu.setEnabled( false );
+
+					}else{
+					
+						List<BuddyPluginBuddy> buddies = getBuddies();
+						
+						boolean	incomplete = ((TableContextMenuItem)menu).getTableID() == TableManager.TABLE_MYTORRENTS_INCOMPLETE;
+						
+						TableContextMenuItem parent = incomplete?menu_item_itorrents:menu_item_ctorrents;
+												
+						for (int i=0;i<buddies.size();i++){
+							
+							final BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(i);
+							
+							if ( buddy.isOnline( true )){
+								
+								TableContextMenuItem item =
+									plugin_interface.getUIManager().getTableManager().addContextMenuItem(
+										parent,
+										"!" + buddy.getName() + "!");
+								
+								item.addMultiListener(
+									new MenuItemListener()
+									{
+										public void 
+										selected(
+											MenuItem 	menu,
+											Object 		target ) 
+										{
+											for ( Torrent torrent: torrents ){
+											
+												az2_handler.sendAZ2Torrent( torrent, buddy );
+											}
+										}
+									});
+							}
+						}
+					
+						menu.setEnabled( true );
+					}
+				}
+				
+				protected void
+				addDownload(
+					List<Torrent>		torrents,
+					TableRow			row )
+				{
+					Object obj = row.getDataSource();
+					
+					Download	download;
+					
+					if ( obj instanceof Download ){
+						
+						download = (Download)obj;
+						
+					}else{
+						
+						DiskManagerFileInfo file = (DiskManagerFileInfo)obj;
+						
+						try{
+							download	= file.getDownload();
+							
+						}catch( DownloadException e ){	
+							
+							Debug.printStackTrace(e);
+							
+							return;
+						}
+					}
+					
+					Torrent torrent = download.getTorrent();
+					
+					if ( torrent != null && !TorrentUtils.isReallyPrivate( PluginCoreUtils.unwrap( torrent ))){
+						
+						torrents.add( torrent );
+					}
+				}
+			};
+			
+		menu_item_itorrents.addFillListener( menu_fill_listener );
+		menu_item_ctorrents.addFillListener( menu_fill_listener );
+		
+		buddy_tracker = new BuddyPluginTracker( this, tracker_enable );
+		
+		plugin_interface.getUIManager().addUIListener(
+			new UIManagerListener()
+			{
+				public void
+				UIAttached(
+					final UIInstance		instance )
+				{
+					if ( instance.getUIType() == UIInstance.UIT_SWT ){
+							
+						try{
+							swt_ui = (BuddyPluginViewInterface)Class.forName( "com.aelitis.azureus.plugins.net.buddy.swt.BuddyPluginView").getConstructor(
+								new Class[]{ BuddyPlugin.class, UIInstance.class, String.class } ).newInstance(
+									new Object[]{ BuddyPlugin.this, instance, VIEW_ID } );
+							
+							// new BuddyPluginView( BuddyPlugin.this, swt_ui, VIEW_ID );
+							
+						}catch( Throwable e ){
+							e.printStackTrace();
+						}
+					}
+					
+					setupDisablePrompt(instance);
+				}
+
+				public void
+				UIDetached(
+					UIInstance		instance )
+				{
+				}
+			});
+		
+		ParameterListener enabled_listener = 
+			new ParameterListener()
+			{
+				public void
+				parameterChanged(
+					Parameter	param )
+				{
+					boolean classic_enabled = classic_enabled_param.getValue();
+					
+					nick_name_param.setEnabled( classic_enabled );
+					online_status_param.setEnabled( classic_enabled );
+					protocol_speed.setEnabled( classic_enabled );
+					enable_chat_notifications.setEnabled( classic_enabled );
+					cat_pub.setEnabled( classic_enabled );
+					tracker_enable.setEnabled( classic_enabled );
+					
+						// only toggle overall state on a real change
+					
+					if ( param != null ){
+					
+						setClassicEnabledInternal( classic_enabled );
+						fireEnabledStateChanged();
+					}
+					
+					boolean beta_enabled = beta_enabled_param.getValue();
+				}
+			};
+		
+		enabled_listener.parameterChanged( null );
+			
+		classic_enabled_param.addListener( enabled_listener );
+		beta_enabled_param.addListener( enabled_listener );
+		
+		loadConfig();
+		
+		registerMessageHandler();
+		
+		plugin_interface.addListener(
+			new PluginListener()
+			{
+				public void
+				initializationComplete()
+				{
+					final DelayedTask dt = plugin_interface.getUtilities().createDelayedTask(new Runnable()
+						{
+							public void 
+							run() 
+							{
+								new AEThread2( "BuddyPlugin:init", true )
+								{
+									public void
+									run()
+									{
+										startup();
+										
+										beta_plugin.startup();
+									}
+								}.start();
+							}
+						});
+					
+					dt.queue();					
+				}
+				
+				public void
+				closedownInitiated()
+				{	
+					saveConfig( true );
+					
+					closedown();
+					
+					beta_plugin.closedown();
+				}
+				
+				public void
+				closedownComplete()
+				{				
+				}
+			});
+	}
+	
+	protected void
+	updateLocale(
+		LocaleUtilities	lu )
+	{
+		for ( int i=0;i<STATUS_STRINGS.length;i++){
+			
+			STATUS_STRINGS[i] = lu.getLocalisedMessageText( "azbuddy." + STATUS_KEYS[i] );
+		}
+		
+		if ( online_status_param != null ){
+			
+			online_status_param.setLabels( STATUS_STRINGS );
+		}
+	}
+	
+	/**
+	 * 
+	 *
+	 * @since 3.0.5.3
+	 */
+	protected void 
+	setupDisablePrompt(
+			final UIInstance ui) 
+	{
+		if (plugin_interface == null) {
+			return;
+		}
+
+		String enabledConfigID = "PluginInfo." + plugin_interface.getPluginID()
+				+ ".enabled";
+		COConfigurationManager.addParameterListener(enabledConfigID,
+				new org.gudy.azureus2.core3.config.ParameterListener() {
+					public void parameterChanged(
+							String parameterName) 
+					{
+						fireEnabledStateChanged();
+					}
+				});
+	}
+	
+	public void
+	showConfig()
+	{
+		plugin_interface.getUIManager().showConfigSection("Views.plugins." + VIEW_ID + ".title");
+	}
+	
+	protected void
+	startup()
+	{
+		try{
+			ddb = plugin_interface.getDistributedDatabase();
+		
+			if ( !ddb.isAvailable()){
+				
+				throw( new Exception( "DDB Unavailable" ));
+			}
+				// pick up initial values before enabling
+
+			ddb.addListener(
+				new DistributedDatabaseListener()
+				{
+					public void 
+					event(
+						DistributedDatabaseEvent event )
+					{
+						if ( event.getType() == DistributedDatabaseEvent.ET_LOCAL_CONTACT_CHANGED ){
+							
+							updateIP();
+						}
+					}
+				});
+					
+			updateIP();
+			
+			updateNickName( nick_name_param.getValue());
+						 
+			updateOnlineStatus( Integer.parseInt( online_status_param.getValue()));
+			 
+			COConfigurationManager.addAndFireParameterListeners(
+					new String[]{
+						"TCP.Listen.Port",
+						"TCP.Listen.Port.Enable",
+						"UDP.Listen.Port",
+						"UDP.Listen.Port.Enable" },
+					new org.gudy.azureus2.core3.config.ParameterListener()
+					{
+						public void 
+						parameterChanged(
+							String parameterName )
+						{
+							updateListenPorts();
+						}
+					});
+			
+			CryptoManagerFactory.getSingleton().addKeyListener(
+				new CryptoManagerKeyListener()
+				{
+					public void 
+					keyChanged(
+						CryptoHandler handler ) 
+					{
+						updateKey();
+					}
+					
+					public void
+					keyLockStatusChanged(
+						CryptoHandler		handler )
+					{	
+						boolean unlocked = handler.isUnlocked();
+						
+						if ( unlocked ){
+							
+							if ( latest_publish.isEnabled()){
+								
+								updatePublish( latest_publish );
+							}
+						}else{
+							
+							new AEThread2( "BuddyPlugin:disc", true )
+							{
+								public void
+								run()
+								{
+									List buddies = getAllBuddies();
+									
+									for (int i=0;i<buddies.size();i++){
+										
+										((BuddyPluginBuddy)buddies.get(i)).disconnect();
+									}
+								}
+							}.start();
+						}
+					}
+				});
+			
+			ready_to_publish	= true;
+			
+			setClassicEnabledInternal( classic_enabled_param.getValue());
+			
+			checkBuddiesAndRepublish();
+			
+			fireClassicInitialised( true );
+			
+				// try to re-establish connection to previously connectd buddies
+			
+			List<BuddyPluginBuddy> buddies = getBuddies();
+			
+			for ( BuddyPluginBuddy buddy: buddies ){
+				
+				if ( buddy.getIP() != null && !buddy.isConnected()){
+				
+					log( "Attempting reconnect to " + buddy.getString());
+					
+					buddy.sendKeepAlive();
+				}
+			}
+			
+		}catch( Throwable e ){
+		
+			log( "Initialisation failed", e );
+			
+			fireClassicInitialised( false );
+		}
+	}
+	
+	public boolean
+	isClassicEnabled()
+	{
+		if (classic_enabled_param == null) {return false;}
+		
+		return( classic_enabled_param.getValue());
+	}
+	
+	public void
+	setClassicEnabled(
+		boolean		enabled )
+	{
+		if (classic_enabled_param == null) {return;}
+		classic_enabled_param.setValue( enabled );
+	}
+	
+	protected void
+	setClassicEnabledInternal(
+		boolean		_enabled )
+	{
+		synchronized( this ){
+						
+			if ( latest_publish.isEnabled() != _enabled ){
+				
+				publishDetails new_publish = latest_publish.getCopy();
+				
+				new_publish.setEnabled( _enabled );
+				
+				updatePublish( new_publish );
+			}
+		}
+	}
+	
+	public boolean
+	isBetaEnabled()
+	{
+		if ( beta_enabled_param == null ){
+			
+			return( false );
+		}
+		
+		return( beta_enabled_param.getValue());
+	}
+	
+	public BuddyPluginBeta
+	getBeta()
+	{
+		return( beta_plugin );
+	}
+	
+	public BuddyPluginTracker
+	getTracker()
+	{
+		return( buddy_tracker );
+	}
+	
+	public String
+	getNickname()
+	{
+		return(  nick_name_param.getValue());
+	}
+	
+	public void
+	setNickname(
+		String	str )
+	{
+		nick_name_param.setValue( str );
+	}
+	
+	public void
+	setOnlineStatus(
+		int		status )
+	{
+		online_status_param.setValue( "" + status );
+	}
+	
+	public int
+	getOnlineStatus()
+	{
+		return( latest_publish.getOnlineStatus());
+	}
+	
+	public BooleanParameter
+	getEnableChatNotificationsParameter()
+	{
+		return( enable_chat_notifications );
+	}
+	
+	protected String
+	normaliseCat(
+		String		str )
+	{
+		if ( str == null ){
+			
+			return( null );
+			
+		}else if ( str.toLowerCase().equals( "all" )){
+			
+			return( "All" );
+			
+		}else{
+			
+			return( str );
+		}
+	}
+	
+	protected void
+	normaliseCats(
+		Set<String>	cats )
+	{
+		if ( cats != null ){
+			
+			boolean	all_found = false;
+			
+			Iterator<String> it = cats.iterator();
+			
+			while( it.hasNext()){
+				
+				if ( it.next().toLowerCase().equals( "all" )){
+					
+					it.remove();
+					
+					all_found = true;
+				}
+			}
+			
+			if ( all_found ){
+				
+				cats.add( "All" );
+			}
+		}
+	}
+	
+	public boolean
+	isPublicTagOrCategory(
+		String	cat )
+	{
+		cat = normaliseCat( cat );
+		
+		return( public_tags_or_categories.contains( cat ));
+	}
+	
+	public void
+	addPublicTagOrCategory(
+		String	cat )
+	{
+		cat = normaliseCat( cat );
+		
+		Set<String> new_cats = new HashSet( public_tags_or_categories );
+		
+		if ( new_cats.add( cat )){
+		
+			setPublicTagsOrCategories( new_cats, true );
+		}
+	}
+	
+	public void
+	removePublicTagOrCategory(
+		String	cat )
+	{
+		cat = normaliseCat( cat );
+		
+		Set<String> new_cats = new HashSet( public_tags_or_categories );
+		
+		if ( new_cats.remove( cat )){
+		
+			setPublicTagsOrCategories( new_cats, true );
+		}
+	}
+	
+	protected void
+	setPublicTagsOrCategories(
+		String	str,
+		boolean	persist )
+	{
+		Set<String>	new_pub_cats = new HashSet<String>();
+		
+		String[]	bits = str.split(",");
+		
+		for (String s: bits ){
+			
+			s = s.trim();
+			
+			if ( bits.length > 0 ){
+				
+				new_pub_cats.add( normaliseCat( s ));
+			}
+		}
+		
+		setPublicTagsOrCategories( new_pub_cats, persist );
+	}
+	
+	protected void
+	setPublicTagsOrCategories(
+		Set<String>	new_pub_tags_or_cats,
+		boolean		persist )
+	{
+		if ( !public_tags_or_categories.equals( new_pub_tags_or_cats )){
+			
+			Set<String> removed = new HashSet<String>( public_tags_or_categories );
+			
+			removed.removeAll( new_pub_tags_or_cats );
+			
+			public_tags_or_categories = new_pub_tags_or_cats;
+			
+			if ( persist ){
+				
+				String cat_str = "";
+				
+				for ( String s: public_tags_or_categories ){
+					
+					cat_str += (cat_str.length()==0?"":",") + s;
+				}
+				
+				cat_pub.setValue( cat_str );
+			}
+			
+			List<BuddyPluginBuddy> buds = getBuddies();
+			
+			for ( BuddyPluginBuddy b: buds ){
+				
+				Set<String> local = b.getLocalAuthorisedRSSTagsOrCategories();
+				
+				if ( local != null || new_pub_tags_or_cats.size() > 0 ){
+					
+					if ( local == null ){
+						
+						local = new HashSet<String>();
+						
+					}else{
+						
+							// gotta clone else we're messing with stuff that ain't ours
+						
+						local = new HashSet<String>( local );
+					}
+					
+					local.addAll( new_pub_tags_or_cats );
+				
+					local.removeAll( removed );
+				
+					b.setLocalAuthorisedRSSTagsOrCategories( local );
+				}
+			}
+		}
+	}
+	
+	protected void
+	registerMessageHandler()
+	{
+		try{
+			addRequestListener(
+				new BuddyPluginBuddyRequestListener()
+				{
+					public Map
+					requestReceived(
+						BuddyPluginBuddy	from_buddy,
+						int					subsystem,
+						Map					request )
+					
+						throws BuddyPluginException
+					{
+						if ( subsystem == SUBSYSTEM_INTERNAL ){
+						
+							if ( !from_buddy.isAuthorised()){
+							
+								throw( new BuddyPluginException( "Unauthorised" ));
+							}
+							
+							return( processInternalRequest( from_buddy, request ));							
+						}
+
+						return( null );
+					}
+					
+					public void
+					pendingMessages(
+						BuddyPluginBuddy[]	from_buddies )
+					{
+					}
+				});
+			
+			msg_registration = 
+				plugin_interface.getMessageManager().registerGenericMessageType(
+					"AZBUDDY", "Buddy message handler", 
+					STREAM_CRYPTO,
+					new GenericMessageHandler()
+					{
+						public boolean
+						accept(
+							GenericMessageConnection	connection )
+						
+							throws MessageException
+						{
+							if ( !isClassicEnabled()){
+								
+								return( false );
+							}
+							
+							final String originator = connection.getEndpoint().getNotionalAddress().getAddress().getHostAddress();
+							
+							if ( TRACE ){
+								System.out.println( "accept " + originator );
+							}
+							
+							try{
+								String reason = "Friend: Incoming connection establishment (" + originator + ")";
+									
+								addRateLimiters( connection );
+
+								connection = 
+									sec_man.getSTSConnection(
+											connection, 
+											sec_man.getPublicKey( SEPublicKey.KEY_TYPE_ECC_192, reason ),
+											new SEPublicKeyLocator()
+											{
+												public boolean
+												accept(
+													Object		context,
+													SEPublicKey	other_key )
+												{
+													String	other_key_str = Base32.encode( other_key.encodeRawPublicKey());
+
+													if ( TRACE ){
+														System.out.println( "Incoming: acceptKey - " + other_key_str );
+													}
+													
+													try{
+														synchronized( BuddyPlugin.this ){
+																
+															int	unauth_count = 0;
+															
+															for (int i=0;i<buddies.size();i++){
+															
+																BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(i);
+	
+																if ( buddy.getPublicKey().equals( other_key_str )){
+																	
+																		// don't accept a second or subsequent connection for unauth buddies
+																		// as they have a single chance to be processed
+																	
+																	if ( !buddy.isAuthorised()){
+																		
+																		log( "Incoming connection from " + originator + " failed as for unauthorised buddy" );
+																		
+																		return( false );
+																	}
+																	
+																	buddy.incomingConnection((GenericMessageConnection)context );	
+																	
+																	return( true );
+																}
+																
+																if ( !buddy.isAuthorised()){
+																	
+																	unauth_count++;
+																}
+															}
+															
+																// no existing authorised buddy
+															
+															if ( unauth_count < MAX_UNAUTH_BUDDIES ){
+																		
+																if ( tooManyUnauthConnections( originator )){
+																	
+																	log( "Too many recent unauthorised connections from " + originator );
+																	
+																	return( false );
+																}
+																
+																BuddyPluginBuddy buddy = addBuddy( other_key_str, SUBSYSTEM_AZ2, false );
+																
+																if ( buddy != null ){
+																
+																	buddy.incomingConnection((GenericMessageConnection)context );	
+																	
+																	return( true );
+																	
+																}else{
+																	
+																	return( false );
+																}
+															}
+														}
+														
+														log( "Incoming connection from " + originator + " failed due to pk mismatch" );
+	
+														return( false );
+														
+													}catch( Throwable e ){
+														
+														log( "Incomming connection from " + originator + " failed", e );
+														
+														return( false );
+													}
+												}
+											},
+											reason,
+											BLOCK_CRYPTO );
+							
+							}catch( Throwable e ){
+								
+								connection.close();
+								
+								log( "Incoming connection from " + originator + " failed", e );
+							}
+							
+							return( true );
+						}
+					});
+					
+		}catch( Throwable e ){
+			
+			log( "Failed to register message listener", e );
+		}
+	}
+	
+	protected void
+	addRateLimiters(
+		GenericMessageConnection	connection )
+	{
+		connection.addInboundRateLimiter( inbound_limiter );
+		connection.addOutboundRateLimiter( outbound_limiter );
+	}
+	
+	protected boolean
+	tooManyUnauthConnections(
+		String	originator )
+	{
+		synchronized( this ){
+	
+			if ( unauth_bloom == null ){
+				
+				unauth_bloom = BloomFilterFactory.createAddRemove4Bit( UNAUTH_BLOOM_CHUNK );
+				
+				unauth_bloom_create_time	= SystemTime.getCurrentTime();
+			}
+			
+			int	hit_count = unauth_bloom.add( originator.getBytes());
+			
+			if ( hit_count >= 8 ){
+			    		
+				Debug.out( "Too many recent unauthorised connection attempts from " + originator );
+     		
+				return( true );
+			}
+			
+			return( false );
+		}
+	}
+	
+	protected void
+	checkUnauthBloom()
+	{
+		synchronized( this ){
+		
+			if ( unauth_bloom != null ){
+				
+				long	now = SystemTime.getCurrentTime();
+				
+				if ( now < unauth_bloom_create_time ){
+					
+					unauth_bloom_create_time = now;
+					
+				}else if ( now - unauth_bloom_create_time > UNAUTH_BLOOM_RECREATE ){
+					
+					unauth_bloom = null;
+				}
+			}
+		}
+	}
+	
+	protected void
+	checkMaxMessageSize(
+		int		size )
+	
+		throws BuddyPluginException
+	{
+		if ( size > MAX_MESSAGE_SIZE ){
+			
+			throw( new BuddyPluginException( "Message is too large to send, limit is " + DisplayFormatters.formatByteCountToKiBEtc( MAX_MESSAGE_SIZE )));
+		}
+	}
+	
+	protected void
+	checkPersistentDispatch()
+	{
+		List	buddies_copy;
+		
+		synchronized( this ){
+		
+			buddies_copy = new ArrayList( buddies );
+		}
+				
+		for (int i=0;i<buddies_copy.size();i++){
+			
+			BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies_copy.get(i);
+
+			buddy.checkPersistentDispatch();
+		}
+	}
+	
+	protected void
+	persistentDispatchInit()
+	{
+		Iterator it = pd_preinit.iterator();
+		
+		while( it.hasNext()){
+		
+			persistentDispatchPending((BuddyPluginBuddy)it.next());
+		}
+		
+		pd_preinit = null;
+	}
+	
+	protected void
+	persistentDispatchPending(
+		BuddyPluginBuddy	buddy )
+	{
+		synchronized( pd_queue ){
+			
+			if ( initialisation_state == INIT_UNKNOWN ){
+				
+				pd_preinit.add( buddy );
+				
+				return;
+			}
+			
+			if ( !pd_queue.contains( buddy )){
+				
+				pd_queue.add( buddy );
+				
+				pd_queue_sem.release();
+				
+				if ( pd_thread == null ){
+					
+					pd_thread = 
+						new AEThread2( "BuddyPlugin:persistDispatch", true )
+						{
+							public void
+							run()
+							{
+								while( true ){
+									
+									if ( !pd_queue_sem.reserve( 30*1000 )){
+										
+										synchronized( pd_queue ){
+											
+											if ( pd_queue.isEmpty()){
+												
+												pd_thread	= null;
+												
+												break;
+											}
+										}
+									}else{
+										
+										BuddyPluginBuddy	buddy;
+										
+										synchronized( pd_queue ){
+											
+											buddy = (BuddyPluginBuddy)pd_queue.remove(0);
+										}
+										
+										buddy.persistentDispatch();
+									}
+								}
+							}
+						};
+						
+					pd_thread.start();
+				}
+			}
+		}
+	}
+	
+	protected Map
+	processInternalRequest(
+		BuddyPluginBuddy	from_buddy,
+		Map					request )		
+		
+		throws BuddyPluginException
+	{
+		int	type = ((Long)request.get("type")).intValue();
+		
+		if ( type == RT_INTERNAL_REQUEST_PING ){
+		
+			Map	reply = new HashMap();
+		
+			reply.put( "type", new Long( RT_INTERNAL_REPLY_PING ));
+		
+			return( reply );
+			
+		}else if ( type == RT_INTERNAL_REQUEST_CLOSE ){
+		
+			from_buddy.receivedCloseRequest( request );
+			
+			Map	reply = new HashMap();
+		
+			reply.put( "type", new Long( RT_INTERNAL_REPLY_CLOSE ));
+		
+			return( reply );
+			
+		}else{
+			
+			throw( new BuddyPluginException( "Unrecognised request type " + type ));
+		}
+	}
+
+	protected void
+	updateListenPorts()
+	{
+		synchronized( this ){
+
+			int	tcp_port = COConfigurationManager.getIntParameter( "TCP.Listen.Port" );
+			boolean	tcp_enabled = COConfigurationManager.getBooleanParameter( "TCP.Listen.Port.Enable" );
+			int	udp_port = COConfigurationManager.getIntParameter("UDP.Listen.Port" );
+			boolean	udp_enabled = COConfigurationManager.getBooleanParameter( "UDP.Listen.Port.Enable" );
+				
+			if ( !tcp_enabled ){
+				
+				tcp_port = 0;
+			}
+			
+			if ( !udp_enabled ){
+				
+				udp_port = 0;
+			}
+			
+			if ( 	latest_publish.getTCPPort() != tcp_port ||
+					latest_publish.getUDPPort() != udp_port ){
+				
+				publishDetails new_publish = latest_publish.getCopy();
+				
+				new_publish.setTCPPort( tcp_port );
+				new_publish.setUDPPort( udp_port );
+				
+				updatePublish( new_publish );
+			}
+		}
+	}
+	
+	protected void
+	updateIP()
+	{
+		if ( ddb == null || !ddb.isAvailable()){
+			
+			return;
+		}
+				
+		synchronized( this ){
+
+			InetAddress public_ip = ddb.getLocalContact().getAddress().getAddress();
+				
+			if ( 	latest_publish.getIP() == null ||
+					!latest_publish.getIP().equals( public_ip )){
+					
+				publishDetails new_publish = latest_publish.getCopy();
+				
+				new_publish.setIP( public_ip );
+				
+				updatePublish( new_publish );
+			}
+		}
+	}
+	
+	protected void
+	updateNickName(
+		String		new_nick )
+	{
+		new_nick = new_nick.trim();
+		
+		if ( new_nick.length() == 0 ){
+			
+			new_nick = null;
+		}
+		
+		synchronized( this ){
+
+			String	old_nick = latest_publish.getNickName();
+			
+			if ( !stringsEqual( new_nick, old_nick )){
+			
+				publishDetails new_publish = latest_publish.getCopy();
+					
+				new_publish.setNickName( new_nick );
+					
+				updatePublish( new_publish );
+			}
+		}
+	}
+	
+	protected void
+	updateOnlineStatus(
+		int		new_status )
+	{
+		boolean	changed;
+		
+		synchronized( this ){
+
+			int	old_status = latest_publish.getOnlineStatus();
+			
+			changed = old_status != new_status;
+			
+			if ( changed ){
+			
+				publishDetails new_publish = latest_publish.getCopy();
+					
+				new_publish.setOnlineStatus( new_status );
+					
+				updatePublish( new_publish );
+			}
+		}
+		
+		if ( changed ){
+			
+			List	buddies = getAllBuddies();
+						
+			for (int i=0;i<buddies.size();i++){
+				
+				BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(i);
+				
+				if ( buddy.isConnected()){
+				
+					buddy.sendKeepAlive();
+				}
+			}
+		}
+	}
+	
+	public String
+	getOnlineStatus(
+		int		status )
+	{
+		if ( status >= STATUS_STRINGS.length || status < 0 ){
+		
+			status = 0;
+		}
+		
+		return( STATUS_STRINGS[status] );
+	}
+	
+	protected boolean
+	stringsEqual(
+		String	s1, 
+		String	s2 )
+	{
+		if ( s1 == null && s2 == null ){
+			
+			return( true );
+		}
+		
+		if ( s1 == null || s2 == null ){
+			
+			return( false );
+		}
+		
+		return( s1.equals( s2 ));
+	}
+	
+	protected void
+	updateKey()
+	{
+		synchronized( this ){
+
+			publishDetails new_publish = latest_publish.getCopy();
+				
+			new_publish.setPublicKey( null );
+				
+			updatePublish( new_publish );
+		}
+	}
+	
+	protected void
+	updatePublish(
+		final publishDetails	details )
+	{
+		latest_publish = details;
+		
+		if ( ddb == null || !ready_to_publish ){
+			
+			return;
+		}
+		
+		publish_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void
+				runSupport()
+				{
+						// only execute the most recent publish
+					
+					if ( publish_dispatcher.getQueueSize() > 0 ){
+						
+						return;
+					}
+					
+					updatePublishSupport( details );
+				}
+			});
+	}
+	
+	protected void
+	updatePublishSupport(
+		publishDetails	details )
+	{
+		byte[]	key_to_remove = null;
+		
+		publishDetails	existing_details;
+		
+		boolean	log_this;
+		
+		synchronized( this ){
+
+			log_this = !current_publish.getString().equals( details.getString());
+			
+			existing_details = current_publish;
+			
+			if ( !details.isEnabled()){
+				
+				if ( current_publish.isPublished()){
+					
+					key_to_remove	= current_publish.getPublicKey();
+				}
+			}else{
+								
+				if ( details.getPublicKey() == null ){
+					
+					try{
+						details.setPublicKey( ecc_handler.getPublicKey( "Creating online status key" ));
+						
+					}catch( Throwable e ){
+						
+						log( "Failed to publish details", e );
+						
+						return;
+					}			
+				}
+				
+				if ( current_publish.isPublished()){
+					
+					byte[]	existing_key = current_publish.getPublicKey();
+				
+					if ( !Arrays.equals( existing_key, details.getPublicKey())){
+						
+						key_to_remove = existing_key;
+					}
+				}
+			}
+			
+			current_publish = details;
+		}
+		
+		if ( key_to_remove != null ){
+			
+			log( "Removing old status publish: " + existing_details.getString());
+			
+			try{
+				ddb.delete(
+					new DistributedDatabaseListener()
+					{
+						public void
+						event(
+							DistributedDatabaseEvent		event )
+						{
+						}
+					},
+					getStatusKey( key_to_remove, "Friend status de-registration for old key" ));
+				
+			}catch( Throwable e ){	
+			
+				log( "Failed to remove existing publish", e );
+			}
+		}
+		
+		if ( details.isEnabled()){
+			
+				// ensure we have a sensible ip
+			
+			InetAddress ip = details.getIP();
+			
+			if ( ip.isLoopbackAddress() || ip.isLinkLocalAddress() || ip.isSiteLocalAddress()){
+				
+				log( "Can't publish as ip address is invalid: " + details.getString());
+				
+				return;
+			}
+			
+			details.setPublished( true );
+			
+			Map	payload = new HashMap();
+			
+			if ( details.getTCPPort() > 0 ){
+			
+				payload.put( "t", new Long(  details.getTCPPort() ));
+			}
+			
+			if (  details.getUDPPort() > 0 ){
+				
+				payload.put( "u", new Long( details.getUDPPort() ));
+			}
+						
+			payload.put( "i", ip.getAddress());
+			
+			String	nick = details.getNickName();
+			
+			if ( nick != null ){
+				
+				if ( nick.length() > 32 ){
+					
+					nick = nick.substring( 0, 32 );
+				}
+				
+				payload.put( "n", nick );
+			}
+			
+			payload.put( "o", new Long( details.getOnlineStatus()));
+			
+			int	next_seq = ++status_seq;
+			
+			if ( next_seq == 0 ){
+				
+				next_seq = ++status_seq;
+			}
+			
+			details.setSequence( next_seq );
+			
+			payload.put( "s", new Long( next_seq ));
+			
+			payload.put( "v", new Long( VERSION_CURRENT ));
+			
+			boolean	failed_to_get_key = true;
+			
+			try{
+				byte[] data = BEncoder.encode( payload );
+										
+				DistributedDatabaseKey	key = getStatusKey( details.getPublicKey(), "My buddy status registration " + payload );
+	
+				byte[] signature = ecc_handler.sign( data, "Friend online status" );
+			
+				failed_to_get_key = false;
+				
+				byte[]	signed_payload = new byte[ 1 + signature.length + data.length ];
+				
+				signed_payload[0] = (byte)signature.length;
+				
+				System.arraycopy( signature, 0, signed_payload, 1, signature.length );
+				System.arraycopy( data, 0, signed_payload, 1 + signature.length, data.length );		
+				
+				DistributedDatabaseValue	value = ddb.createValue( signed_payload );
+				
+				final AESemaphore	sem = new AESemaphore( "BuddyPlugin:reg" );
+				
+				if ( log_this ){
+					
+					logMessage( "Publishing status starts: " + details.getString());
+				}
+				
+				last_publish_start = SystemTime.getMonotonousTime();
+				
+				ddb.write(
+					new DistributedDatabaseListener()
+					{
+						private List<DistributedDatabaseContact>	write_contacts = new ArrayList<DistributedDatabaseContact>();
+						
+						public void
+						event(
+							DistributedDatabaseEvent		event )
+						{
+							int	type = event.getType();
+						
+							if ( type == DistributedDatabaseEvent.ET_VALUE_WRITTEN ){
+								
+								write_contacts.add( event.getContact());
+								
+							}else if ( 	type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ||
+										type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){
+
+								synchronized( publish_write_contacts ){
+									
+									publish_write_contacts.clear();
+									
+									publish_write_contacts.addAll( write_contacts );
+								}
+								
+								sem.release();
+							}
+						}
+					},
+					key,
+					value );
+				
+				sem.reserve();
+				
+				if ( log_this ){
+				
+					logMessage( "My status publish complete" );
+				}
+			}catch( Throwable e ){
+				
+				logMessage( "Failed to publish online status", e );
+				
+				if ( failed_to_get_key ){
+					
+					synchronized( this ){
+						
+						if ( republish_delay_event != null ){
+							
+							return;
+						}
+						
+						if ( 	last_publish_start == 0 ||
+								SystemTime.getMonotonousTime() - last_publish_start > STATUS_REPUBLISH_PERIOD ){
+						
+							log( "Rescheduling publish as failed to get key" );
+						
+							republish_delay_event = SimpleTimer.addEvent(
+								"BuddyPlugin:republish",
+								SystemTime.getCurrentTime() + 60*1000,
+								new TimerEventPerformer()
+								{
+									public void 
+									perform(
+										TimerEvent event) 
+									{
+										synchronized( BuddyPlugin.this ){
+											
+											republish_delay_event = null;
+										}
+										
+										if ( 	last_publish_start == 0 ||
+												SystemTime.getMonotonousTime() - last_publish_start > STATUS_REPUBLISH_PERIOD ){
+										
+											if ( latest_publish.isEnabled()){
+												
+												updatePublish( latest_publish );
+											}
+										}
+									}
+								});
+								
+						}	
+					}
+				}
+			}
+		}
+	}
+	
+	protected int
+	getCurrentStatusSeq()
+	{
+		synchronized( this ){
+		
+			return( current_publish.getSequence());
+		}
+	}
+	
+	protected void
+	closedown()
+	{
+		logMessage( "Closing down" );
+
+		List<BuddyPluginBuddy>	buddies = getAllBuddies();
+		
+		synchronized( this ){
+			
+			connected_at_close = new ArrayList<BuddyPluginBuddy>();
+			
+			for ( BuddyPluginBuddy buddy: buddies ){
+				
+				if ( buddy.isConnected()){
+					
+					connected_at_close.add( buddy );
+				}
+			}
+		}
+		
+		if ( ddb != null ){
+			
+			boolean	restarting = AzureusCoreFactory.isCoreAvailable() ? AzureusCoreFactory.getSingleton().isRestarting() : false;
+			
+			logMessage( "   closing buddy connections" );
+			
+			for (int i=0;i<buddies.size();i++){
+				
+				((BuddyPluginBuddy)buddies.get(i)).sendCloseRequest( restarting );
+			}
+			
+			if ( !restarting ){
+				
+				logMessage( "   updating online status" );
+				
+				List	contacts = new ArrayList();
+				
+				synchronized( publish_write_contacts ){
+					
+					contacts.addAll( publish_write_contacts );
+				}
+				
+				byte[] key_to_remove;
+				
+				synchronized( this ){
+	
+					key_to_remove	= current_publish.getPublicKey();
+				}
+				
+				if ( contacts.size() == 0 || key_to_remove == null ){
+					
+					return;
+				}
+				
+				DistributedDatabaseContact[] contact_a = new DistributedDatabaseContact[contacts.size()];
+				
+				contacts.toArray( contact_a );
+				
+				try{
+					ddb.delete(
+						new DistributedDatabaseListener()
+						{
+							public void
+							event(
+								DistributedDatabaseEvent		event )
+							{
+								if ( event.getType() == DistributedDatabaseEvent.ET_VALUE_DELETED ){
+	
+									// System.out.println( "Deleted status from " + event.getContact().getName());
+								}
+							}
+						},
+						getStatusKey( key_to_remove, "Friend status de-registration for closedown" ),
+						contact_a );
+					
+				}catch( Throwable e ){	
+				
+					log( "Failed to remove existing publish", e );
+				}
+			}
+		}
+	}
+	
+	protected DistributedDatabaseKey
+	getStatusKey(
+		byte[]	public_key,
+		String	reason )
+	
+		throws Exception
+	{
+		byte[]	key_prefix = "azbuddy:status".getBytes();
+		
+		byte[]	key_bytes = new byte[ key_prefix.length + public_key.length ];
+		
+		System.arraycopy( key_prefix, 0, key_bytes, 0, key_prefix.length );
+		System.arraycopy( public_key, 0, key_bytes, key_prefix.length, public_key.length );
+		
+		DistributedDatabaseKey key = ddb.createKey( key_bytes, reason );
+		
+		return( key );
+	}
+
+	protected DistributedDatabaseKey
+	getYGMKey(
+		byte[]	public_key,
+		String	reason )
+	
+		throws Exception
+	{
+		byte[]	key_prefix = "azbuddy:ygm".getBytes();
+		
+		byte[]	key_bytes = new byte[ key_prefix.length + public_key.length ];
+		
+		System.arraycopy( key_prefix, 0, key_bytes, 0, key_prefix.length );
+		System.arraycopy( public_key, 0, key_bytes, key_prefix.length, public_key.length );
+		
+		DistributedDatabaseKey key = ddb.createKey( key_bytes, reason );
+		
+		return( key );
+	}
+	
+	protected void
+	setConfigDirty()
+	{
+		synchronized( this ){
+			
+			config_dirty = true;
+		}
+	}
+		
+	protected void
+	loadConfig()
+	{
+		long	now = SystemTime.getCurrentTime();
+		
+		synchronized( this ){
+			
+			Map map = readConfig(); 
+					
+			List	buddies_config = (List)map.get( "friends" );
+				
+			if ( buddies_config != null ){
+					
+				if ( buddies_config.size() == 0 ){
+					
+					deleteConfig();
+					
+				}else{
+					for (int i=0;i<buddies_config.size();i++){
+						
+						Object o = buddies_config.get(i);
+			
+						if ( o instanceof Map ){
+							
+							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 ){
+								
+								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 ){
+								
+								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 ){
+								
+								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 );
+						}
+					}
+				}
+			}
+			
+			int	num_buddies = buddies.size();
+			
+			for ( BuddyPluginBuddy b: buddies ){
+				
+				b.setInitialStatus( now, num_buddies );
+			}
+		}
+	}
+	
+	protected String
+	decodeString(
+		byte[]		bytes )
+	{
+		if (  bytes == null ){
+			
+			return( null );
+		}
+		
+		try{
+			return( new String( bytes, "UTF8" ));
+			
+		}catch( Throwable e ){
+			
+			return( null );
+		}
+	}
+	
+	protected void
+	saveConfig()
+	{
+		saveConfig( false );
+	}
+	
+	protected void
+	saveConfig(
+		boolean	force )
+	{
+		synchronized( this ){
+
+			if ( config_dirty || force ){
+				
+				List buddies_config = new ArrayList();
+		
+				for (int i=0;i<buddies.size();i++){
+					
+					BuddyPluginBuddy buddy = (BuddyPluginBuddy)buddies.get(i);
+		
+					if ( !buddy.isAuthorised()){
+						
+						continue;
+					}
+					
+					Map	map = new HashMap();
+				
+					map.put( "ct", new Long( buddy.getCreatedTime()));
+					
+					map.put( "pk", buddy.getPublicKey());
+				
+					List	ygm = buddy.getYGMMarkers();
+					
+					if ( ygm != null ){
+						
+						map.put( "ygm", ygm );
+					}
+					
+					String	nick = buddy.getNickName();
+					
+					if ( nick != null ){
+						
+						map.put( "n", nick );
+					}
+					
+					map.put( "ls", new Long( buddy.getLastStatusSeq()));
+					
+					map.put( "lo", new Long( buddy.getLastTimeOnline()));
+					
+					map.put( "ss", new Long( buddy.getSubsystem()));
+					
+					map.put( "v", new Long( buddy.getVersion()));
+					
+					if ( buddy.getLocalAuthorisedRSSTagsOrCategoriesAsString() != null ){
+						map.put( "lc", buddy.getLocalAuthorisedRSSTagsOrCategoriesAsString());
+					}
+					
+					if ( buddy.getRemoteAuthorisedRSSTagsOrCategoriesAsString() != null ){
+						map.put( "rc", buddy.getRemoteAuthorisedRSSTagsOrCategoriesAsString());
+					}
+
+					boolean connected = 
+						buddy.isConnected() ||
+						( connected_at_close != null && connected_at_close.contains( buddy ));
+					
+					if ( connected ){
+						
+						InetAddress	ip 			= buddy.getIP();
+						int			tcp_port	= buddy.getTCPPort();
+						int			udp_port	= buddy.getUDPPort();
+						
+						if ( ip != null ){
+							
+							map.put( "ip", ip.getAddress());
+							map.put( "tcp", new Long( tcp_port ));
+							map.put( "udp", new Long( udp_port ));
+						}
+					}
+					
+					buddies_config.add( map );
+				}
+				
+				Map	map = new HashMap();
+				
+				if ( buddies_config.size() > 0 ){
+				
+					map.put( "friends", buddies_config );
+				
+					writeConfig( map );
+					
+				}else{
+					
+					deleteConfig();
+				}
+				
+				config_dirty = false;
+			}
+		}
+	}
+	
+	public BuddyPluginBuddy
+	addBuddy(
+		String		key,
+		int			subsystem )
+	
+	{
+		return( addBuddy( key, subsystem, true ));
+	}
+	
+	protected BuddyPluginBuddy
+	addBuddy(
+		String		key,
+		int			subsystem,
+		boolean		authorised )
+	{
+		if ( key.length() == 0 || !verifyPublicKey( key )){
+			
+			return( null );
+		}
+				
+		BuddyPluginBuddy	buddy_to_return = null;
+		
+			// buddy may be already present as unauthorised in which case we pick it up
+			// and authorise it and send the added event (we don't fire added events for
+			// unauthorised buddies)
+		
+		synchronized( this ){
+						
+			for (int i=0;i<buddies.size();i++){
+				
+				BuddyPluginBuddy buddy = (BuddyPluginBuddy)buddies.get(i);
+				
+				if ( buddy.getPublicKey().equals( key )){
+					
+					if ( buddy.getSubsystem() != subsystem ){
+						
+						log( "Buddy " + buddy.getString() + ": subsystem changed from " + buddy.getSubsystem() + " to " + subsystem );
+						
+						buddy.setSubsystem( subsystem );
+						
+						saveConfig( true );
+					}
+					
+					if ( authorised && !buddy.isAuthorised()){
+						
+						log( "Buddy " + buddy.getString() + ": no authorised" );
+						
+						buddy.setAuthorised( true );
+						
+						buddy_to_return	= buddy;
+						
+					}else{
+					
+						return( buddy );
+					}
+				}
+			}
+			
+			if ( buddy_to_return == null ){
+				
+				buddy_to_return = 
+					new BuddyPluginBuddy( this, SystemTime.getCurrentTime(), subsystem, authorised, key, null, VERSION_CURRENT, null, null, 0, 0, null );
+				
+				buddies.add( buddy_to_return );
+				
+				buddies_map.put( key, buddy_to_return );
+				
+				if ( !authorised ){
+					
+					log( "Added unauthorised buddy: " + buddy_to_return.getString());
+				}
+			}
+			
+			if ( buddy_to_return.isAuthorised()){
+				
+				logMessage( "Added buddy " + buddy_to_return.getString());
+	
+				saveConfig( true );
+			}
+		}
+				
+		fireAdded( buddy_to_return );
+		
+		return( buddy_to_return );
+	}
+	
+	protected void
+	removeBuddy(
+		BuddyPluginBuddy 	buddy )
+	{
+		synchronized( this ){
+
+			if ( !buddies.remove( buddy )){
+				
+				return;
+			}
+		
+			buddies_map.remove( buddy.getPublicKey());
+						
+			logMessage( "Removed friend " + buddy.getString());
+
+			saveConfig( true );
+		}
+		
+		buddy.destroy();
+				
+		fireRemoved( buddy );
+	}
+	
+	protected Map
+	readConfig()
+	{
+		File	config_file = new File( plugin_interface.getUtilities().getAzureusUserDir(), "friends.config" );
+		
+		return( readConfigFile( config_file ));
+	}
+	
+	protected void
+	writeConfig(
+		Map		map )
+	{
+		File	config_file = new File( plugin_interface.getUtilities().getAzureusUserDir(), "friends.config" );
+		
+		writeConfigFile( config_file, map );
+	}
+	
+	protected void
+	deleteConfig()
+	{
+		Utilities utils = plugin_interface.getUtilities();
+
+		File	config_file = new File( utils.getAzureusUserDir(), "friends.config" );
+		
+		utils.deleteResilientBEncodedFile(
+				config_file.getParentFile(), config_file.getName(), true );
+
+	}
+	
+	protected Map
+	readConfigFile(
+		File		name )
+	{
+		Utilities utils = plugin_interface.getUtilities();
+		
+		Map map = utils.readResilientBEncodedFile(
+						name.getParentFile(), name.getName(), true );
+		
+		if ( map == null ){
+			
+			map = new HashMap();
+		}
+		
+		return( map );
+	}
+	
+	protected boolean
+	writeConfigFile(
+		File		name,
+		Map			data )
+	{
+		Utilities utils = plugin_interface.getUtilities();
+			
+		utils.writeResilientBEncodedFile(
+			name.getParentFile(), name.getName(), data, true );
+		
+		return( name.exists());
+	}
+	
+	protected File
+	getBuddyConfigDir()
+	{
+		return( new File( plugin_interface.getUtilities().getAzureusUserDir(), "friends" ));
+	}
+	
+	public BuddyPluginAZ2
+	getAZ2Handler()
+	{
+		return( az2_handler );
+	}
+	
+	public String
+	getPublicKey()
+	{
+		try{
+			return( Base32.encode(ecc_handler.getPublicKey( "Friend get key" )));
+			
+		}catch( Throwable e ){
+			
+			logMessage( "Failed to access public key", e );
+			
+			return( null );
+		}
+	}
+	
+	public boolean
+	verifyPublicKey(
+		String		key )
+	{
+		return( ecc_handler.verifyPublicKey( Base32.decode( key )));
+	}
+	
+	protected void
+	checkBuddiesAndRepublish()
+	{
+		updateBuddys();
+		
+		plugin_interface.getUtilities().createTimer( "Buddy checker" ).addPeriodicEvent(
+			TIMER_PERIOD,
+			new UTTimerEventPerformer()
+			{
+				int	tick_count;
+				
+				public void 
+				perform(
+					UTTimerEvent event ) 
+				{
+					tick_count++;
+					
+					if ( !isClassicEnabled()){
+						
+						return;
+					}
+												
+					updateBuddys();
+					
+					if ( tick_count % STATUS_REPUBLISH_TICKS == 0 ){
+							
+						if ( latest_publish.isEnabled()){
+								
+							updatePublish( latest_publish );
+						}
+					}
+					
+					if ( tick_count % CHECK_YGM_TICKS == 0 ){
+
+						checkMessagePending( tick_count );
+					}
+					
+					if ( tick_count % BLOOM_CHECK_TICKS == 0 ){
+						
+						checkUnauthBloom();
+					}
+					
+					if ( tick_count % SAVE_CONFIG_TICKS == 0 ){
+
+						saveConfig();
+					}
+					
+					if ( tick_count % PERSISTENT_MSG_CHECK_TICKS == 0 ){
+						
+						checkPersistentDispatch();
+					}
+					
+					if ( buddy_tracker != null ){
+						
+						buddy_tracker.tick( tick_count );
+					}
+				}
+			});
+	}
+	
+	protected void
+	updateBuddys()
+	{
+		List	buddies_copy;
+		
+		synchronized( this ){
+		
+			buddies_copy = new ArrayList( buddies );
+		}
+		
+		long	now = SystemTime.getCurrentTime();
+		
+		Random random = new Random();
+		
+		for (int i=0;i<buddies_copy.size();i++){
+			
+			BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies_copy.get(i);
+			
+			long	last_check = buddy.getLastStatusCheckTime();
+			
+			buddy.checkTimeouts();
+			
+			int	period = BUDDY_STATUS_CHECK_PERIOD_MIN + BUDDY_STATUS_CHECK_PERIOD_INC*buddies_copy.size()/5;
+			
+				// randomise a bit
+			
+			period += random.nextInt( 2*60*1000 );
+			
+				// last check may be in the future as we defer checks for seemingly inactive buddies
+			
+			if ( now - last_check > period ){
+				
+				if ( !buddy.statusCheckActive()){
+			
+					if ( buddy.isAuthorised()){
+					
+						updateBuddyStatus( buddy );
+					}
+				}
+			}
+		}
+		
+			// trim any non-authorised buddies that have gone idle
+
+		synchronized( this ){
+			
+			for (int i=0;i<buddies_copy.size();i++){
+			
+				BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies_copy.get(i);
+				
+				if ( buddy.isIdle() && !buddy.isAuthorised()){
+					
+					removeBuddy( buddy );
+				}
+			}
+		}
+	}
+	
+	protected void
+	updateBuddyStatus(
+		final BuddyPluginBuddy	buddy )
+	{	
+		if ( !buddy.statusCheckStarts()){
+			
+			return;
+		}
+		
+		log( "Updating buddy status: " + buddy.getString());
+
+		try{							
+			final byte[]	public_key = buddy.getRawPublicKey();
+
+			DistributedDatabaseKey	key = 
+				getStatusKey( public_key, "Friend status check for " + buddy.getName());
+			
+			ddb.read(
+				new DistributedDatabaseListener()
+				{
+					private long	latest_time;
+					private Map		status;
+					
+					public void
+					event(
+						DistributedDatabaseEvent		event )
+					{
+						int	type = event.getType();
+						
+						if ( type == DistributedDatabaseEvent.ET_VALUE_READ ){
+							
+							try{
+								DistributedDatabaseValue value = event.getValue();
+								
+								long time = value.getCreationTime();
+								
+								if ( time > latest_time ){
+								
+									byte[] signed_stuff = (byte[])value.getValue( byte[].class );
+								
+									Map	new_status = verifyAndExtract( signed_stuff, public_key );
+									
+									if ( new_status != null ){
+	
+										status = new_status;
+																																							
+										latest_time = time;
+									}
+								}
+							}catch( Throwable e ){
+								
+								log( "Read failed", e );
+							}
+						}else if ( 	type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ||
+									type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){
+							
+							if ( status == null ){
+																
+								buddy.statusCheckFailed();
+								
+							}else{
+								
+								try{
+									Long	l_tcp_port = (Long)status.get( "t" );
+									Long	l_udp_port = (Long)status.get( "u" );
+									
+									int	tcp_port = l_tcp_port==null?0:l_tcp_port.intValue();
+									int udp_port = l_udp_port==null?0:l_udp_port.intValue();
+									
+									InetAddress ip = InetAddress.getByAddress((byte[])status.get("i"));
+									
+									String	nick = decodeString((byte[])status.get( "n" ));
+									
+									Long	l_seq = (Long)status.get( "s" );
+									
+									int		seq = l_seq==null?0:l_seq.intValue();
+									
+									Long	l_os = (Long)status.get( "o" );
+									
+									int		os = l_os==null?BuddyPlugin.STATUS_ONLINE:l_os.intValue();
+											
+									Long	l_ver = (Long)status.get( "v" );
+									
+									int		ver = l_ver==null?VERSION_INITIAL:l_ver.intValue();
+											
+									buddy.statusCheckComplete( latest_time, ip, tcp_port, udp_port, nick, os, seq, ver );
+									
+								}catch( Throwable e ){
+									
+									buddy.statusCheckFailed();
+									
+									log( "Status decode failed", e );
+								}
+							}
+						}
+					}
+				},
+				key,
+				120*1000 );
+			
+		}catch( Throwable e ){
+			
+			buddy.statusCheckFailed();
+			
+			log( "Friend status update failed: " + buddy.getString(), e );
+		}
+	}
+	
+	protected Map
+	verifyAndExtract(
+		byte[]		signed_stuff,
+		byte[]		public_key )
+	
+		throws BuddyPluginException
+	{
+		int	signature_length = ((int)signed_stuff[0])&0xff;
+		
+		byte[]	signature 	= new byte[ signature_length ];
+		byte[]	data		= new byte[ signed_stuff.length - 1 - signature_length];
+		
+		System.arraycopy( signed_stuff, 1, signature, 0, signature_length );
+		System.arraycopy( signed_stuff, 1 + signature_length, data, 0, data.length );
+			
+		try{
+			if ( ecc_handler.verify( public_key, data, signature )){													
+	
+				return( BDecoder.decode( data ));
+																																	
+			}else{
+				
+				logMessage( "Signature verification failed" );
+				
+				return( null );
+			}
+		}catch( Throwable e ){
+			
+			rethrow( "Verification failed", e );
+			
+			return( null );
+		}
+	}
+	
+	protected byte[]
+	signAndInsert(
+		Map		plain_stuff,
+		String	reason )
+	
+		throws BuddyPluginException
+	{
+		try{
+			byte[] data = BEncoder.encode( plain_stuff );
+			
+			byte[] signature = ecc_handler.sign( data, reason );
+		
+			byte[]	signed_payload = new byte[ 1 + signature.length + data.length ];
+			
+			signed_payload[0] = (byte)signature.length;
+			
+			System.arraycopy( signature, 0, signed_payload, 1, signature.length );
+			System.arraycopy( data, 0, signed_payload, 1 + signature.length, data.length );		
+	
+			return( signed_payload );
+			
+		}catch( Throwable e ){
+			
+			rethrow( "Signing failed", e );
+			
+			return( null );
+		}
+	}
+	
+	public boolean
+	verify(
+		String				pk,
+		byte[]				payload,
+		byte[]				signature )
+	
+		throws BuddyPluginException
+	{
+		return( verify( Base32.decode( pk ), payload, signature ));
+	}
+	
+	protected boolean
+	verify(
+		BuddyPluginBuddy	buddy,
+		byte[]				payload,
+		byte[]				signature )
+	
+		throws BuddyPluginException
+	{
+		return( verify( buddy.getRawPublicKey(), payload, signature ));
+	}
+	
+	protected boolean
+	verify(
+		byte[]				pk,
+		byte[]				payload,
+		byte[]				signature )
+	
+		throws BuddyPluginException
+	{
+		try{
+		
+			return( ecc_handler.verify( pk, payload, signature ));
+			
+		}catch( Throwable e ){
+			
+			rethrow( "Verification failed", e );
+			
+			return( false );
+		}
+	}
+	
+	public byte[]
+   	sign(
+   		byte[]		payload )
+	        	
+	   	throws BuddyPluginException
+	{ 
+		try{
+		
+			return( ecc_handler.sign( payload, "Friend message signing" ));
+
+		}catch( Throwable e ){
+			
+			rethrow( "Signing failed", e );
+			
+			return( null );
+		}
+	}
+
+	protected cryptoResult
+	encrypt(
+		BuddyPluginBuddy	buddy,
+		byte[]				payload )
+	
+		throws BuddyPluginException
+	{
+		return encrypt(buddy.getPublicKey(), payload, buddy.getName());
+	}
+
+	public cryptoResult
+	encrypt(
+		String				pk,
+		byte[]				payload,
+		String				forWho )
+	
+		throws BuddyPluginException
+	{
+		
+		try{
+			byte[]	hash = new byte[20];
+			
+			random.nextBytes( hash );
+			
+			Map	content = new HashMap();
+			
+			content.put( "h", hash );
+			content.put( "p", payload );
+			
+			final byte[] encrypted = ecc_handler.encrypt( Base32.decode(pk), BEncoder.encode( content ), "Encrypting message for " + forWho);
+			
+			final byte[] sha1_hash = new SHA1Simple().calculateHash( hash );
+			
+			return( 
+				new cryptoResult()
+				{
+					public byte[]
+		    		getChallenge()
+					{
+						return( sha1_hash );
+					}
+		    		
+		    		public byte[]
+		    		getPayload()
+		    		{
+		    			return( encrypted );
+		    		}
+				});
+			
+		}catch( Throwable e ){
+			
+			rethrow( "Encryption failed", e );
+			
+			return( null );
+		}
+	}
+	
+	protected cryptoResult
+	decrypt(
+		BuddyPluginBuddy	buddy,
+		byte[]				content,
+		String forName)
+	
+		throws BuddyPluginException
+	{
+		
+		try{
+			final byte[] decrypted = ecc_handler.decrypt( buddy.getRawPublicKey(), content, "Decrypting message for " + buddy.getName());
+			
+			final Map	map = BDecoder.decode( decrypted );
+			
+			return( 
+				new cryptoResult()
+				{
+					public byte[]
+		    		getChallenge()
+					{
+						return((byte[])map.get("h"));
+					}
+		    		
+		    		public byte[]
+		    		getPayload()
+		    		{
+		    			return((byte[])map.get("p"));
+		    		}
+				});
+			
+		}catch( Throwable e ){
+			
+			rethrow( "Decryption failed", e );
+			
+			return( null );
+		}
+	}
+
+	public cryptoResult
+	decrypt(
+		String				public_key,
+		byte[]				content )
+	
+		throws BuddyPluginException
+	{
+		
+		try{
+			final byte[] decrypted = ecc_handler.decrypt( Base32.decode(public_key), content, "Decrypting message for " + public_key);
+			
+			final Map	map = BDecoder.decode( decrypted );
+			
+			return( 
+				new cryptoResult()
+				{
+					public byte[]
+		    		getChallenge()
+					{
+						return((byte[])map.get("h"));
+					}
+		    		
+		    		public byte[]
+		    		getPayload()
+		    		{
+		    			return((byte[])map.get("p"));
+		    		}
+				});
+			
+		}catch( Throwable e ){
+			
+			rethrow( "Decryption failed", e );
+			
+			return( null );
+		}
+	}
+
+	protected void
+	setMessagePending(
+		BuddyPluginBuddy			buddy,
+		final operationListener		listener )
+	
+		throws BuddyPluginException
+	{		
+		try{
+			checkAvailable();
+
+			final String	reason = "Friend YGM write for " + buddy.getName();
+			
+			Map	payload = new HashMap();
+			
+			payload.put( "r", new Long( random.nextLong()));
+			
+			byte[] signed_payload = signAndInsert( payload, reason);
+			
+			Map	envelope = new HashMap();
+			
+			envelope.put( "pk", ecc_handler.getPublicKey( reason ));
+			envelope.put( "ss", signed_payload );
+			
+			DistributedDatabaseValue	value = ddb.createValue( BEncoder.encode( envelope ));
+										
+			logMessage( reason + " starts: " + payload );
+			
+			DistributedDatabaseKey	key = getYGMKey( buddy.getRawPublicKey(), reason );
+
+			ddb.write(
+				new DistributedDatabaseListener()
+				{
+					public void
+					event(
+						DistributedDatabaseEvent		event )
+					{
+						int	type = event.getType();
+					
+						if ( 	type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ||
+								type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){
+							
+							logMessage( reason + " complete"  );
+
+							listener.complete();
+						}
+					}
+				},
+				key,
+				value );
+
+		}catch( Throwable e ){
+			
+			try{				
+				rethrow( "Failed to publish YGM", e );
+								
+			}finally{
+				
+				listener.complete();
+			}
+		}
+	}
+	
+	public void
+	checkMessagePending(
+		int	tick_count )
+	{
+		log( "Checking YGM" );
+
+		if ( tick_count % YGM_BLOOM_LIFE_TICKS == 0 ){
+			
+			synchronized( this ){
+				
+				ygm_unauth_bloom = null;
+			}
+		}
+
+		try{	
+			String	reason = "Friend YGM check";
+			
+			byte[] public_key = ecc_handler.getPublicKey( reason );
+
+			DistributedDatabaseKey	key = getYGMKey( public_key, reason );
+			
+			ddb.read(
+				new DistributedDatabaseListener()
+				{	
+					private List		new_ygm_buddies = new ArrayList();
+					private boolean	 	unauth_permitted = false;;
+					
+					public void
+					event(
+						DistributedDatabaseEvent		event )
+					{
+						int	type = event.getType();
+						
+						if ( type == DistributedDatabaseEvent.ET_VALUE_READ ){
+							
+							try{
+								DistributedDatabaseValue value = event.getValue();
+																
+								byte[]	envelope = (byte[])value.getValue( byte[].class );
+								
+								Map	map = BDecoder.decode( envelope );
+								
+								byte[]	pk = (byte[])map.get( "pk" );
+								
+								if ( pk == null ){
+									
+									return;
+								}
+								
+								String	pk_str = Base32.encode( pk );
+								
+								BuddyPluginBuddy buddy = getBuddyFromPublicKey( pk_str );
+																
+								if ( buddy == null || !buddy.isAuthorised() ){
+									
+									if ( buddy == null ){
+									
+										log( "YGM entry from unknown friend '" + pk_str + "' - ignoring" );
+										
+									}else{								
+									
+										log( "YGM entry from unauthorised friend '" + pk_str + "' - ignoring" );
+									}
+
+									byte[] address = event.getContact().getAddress().getAddress().getAddress();
+									
+									synchronized( BuddyPlugin.this ){
+									
+										if ( ygm_unauth_bloom == null ){
+										
+											ygm_unauth_bloom = BloomFilterFactory.createAddOnly(512);
+										}
+										
+										if ( !ygm_unauth_bloom.contains( address )){
+											
+											ygm_unauth_bloom.add( address );
+											
+											unauth_permitted = true;
+										}
+									}
+								}else{
+									
+									byte[]	signed_stuff = (byte[])map.get( "ss" );
+									
+									Map	payload = verifyAndExtract( signed_stuff, pk );
+									
+									if ( payload != null ){
+										
+										long	rand = ((Long)payload.get("r")).longValue();
+										
+										if ( buddy.addYGMMarker( rand )){
+											
+											new_ygm_buddies.add( buddy );
+										}
+									}
+								}
+							}catch( Throwable e ){
+								
+								log( "Read failed", e );
+							}
+						}else if ( 	type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT ||
+									type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){
+							
+							if ( new_ygm_buddies.size() > 0 || unauth_permitted ){
+								
+								BuddyPluginBuddy[] b = new BuddyPluginBuddy[new_ygm_buddies.size()];
+								
+								new_ygm_buddies.toArray( b );
+								
+								fireYGM( b );
+							}
+						}
+					}
+				},
+				key,
+				120*1000,
+				DistributedDatabase.OP_EXHAUSTIVE_READ );
+			
+			boolean	write_bogus_ygm = false;
+			
+			synchronized( this ){
+			
+				if ( !bogus_ygm_written ){
+					
+					bogus_ygm_written = write_bogus_ygm = true;
+				}
+			}
+			
+			if ( write_bogus_ygm ){
+				
+				final String	reason2 = "Friend YGM write for myself";
+				
+				Map	envelope = new HashMap();
+								
+				DistributedDatabaseValue	value = ddb.createValue( BEncoder.encode( envelope ));
+											
+				logMessage( reason2 + " starts" );
+				
+				ddb.write(
+					new DistributedDatabaseListener()
+					{
+						public void
+						event(
+							DistributedDatabaseEvent		event )
+						{
+							int	type = event.getType();
+						
+							if ( type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE ){
+								
+								logMessage( reason2 + " complete"  );
+							}
+						}
+					},
+					key,
+					value );
+			}
+			
+		}catch( Throwable e ){
+						
+			logMessage( "YGM check failed", e );
+		}
+	}
+	
+	public BuddyPluginBuddy
+	getBuddyFromPublicKey(
+		String		key )
+	{
+		synchronized( this ){
+			
+			return((BuddyPluginBuddy)buddies_map.get( key ));
+		}
+	}
+	
+	public PluginInterface
+	getPluginInterface()
+	{
+		return( plugin_interface );
+	}
+	
+	protected SESecurityManager
+	getSecurityManager()
+	{
+		return( sec_man );
+	}
+	
+	protected GenericMessageRegistration
+	getMessageRegistration()
+	{
+		return( msg_registration );
+	}
+	
+		/**
+		 * Returns authorised buddies only
+		 */
+	
+	public List<BuddyPluginBuddy>
+	getBuddies()
+	{
+		synchronized( this ){
+			
+			List<BuddyPluginBuddy>	result = new ArrayList<BuddyPluginBuddy>();
+			
+			for (int i=0;i<buddies.size();i++){
+				
+				BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(i);
+				
+				if ( buddy.isAuthorised()){
+					
+					result.add( buddy );
+				}
+			}
+			
+			return( result );
+		}
+	}
+	
+	protected List<BuddyPluginBuddy>
+	getAllBuddies()
+	{
+		synchronized( this ){
+			
+			return( new ArrayList<BuddyPluginBuddy>( buddies ));
+		}
+	}
+	
+	public boolean
+	isAvailable()
+	{
+		try{
+			checkAvailable();
+			
+			return( true );
+			
+		}catch( Throwable e ){
+			
+			return( false );
+		}
+	}
+	
+	protected void
+	checkAvailable()
+	
+		throws BuddyPluginException
+	{
+		if ( initialisation_state == INIT_UNKNOWN ){
+			
+			throw( new BuddyPluginException( "Plugin not yet initialised" ));
+			
+		}else if ( initialisation_state == INIT_BAD ){
+			
+			throw( new BuddyPluginException( "Plugin unavailable" ));
+
+		}
+	}
+	
+
+	protected void
+	fireClassicInitialised(
+		boolean		ok )
+	{
+		if ( ok ){
+			
+			initialisation_state = INIT_OK;
+				
+		}else{
+			
+			initialisation_state = INIT_BAD;
+		}
+		      
+		persistentDispatchInit();
+		
+		if ( ok ){
+			
+			buddy_tracker.initialise();
+		}
+		
+		List	 listeners_ref = listeners.getList();
+		
+		for (int i=0;i<listeners_ref.size();i++){
+
+			try{
+				((BuddyPluginListener)listeners_ref.get(i)).initialised( ok );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}	
+	}
+	
+	public void
+	addListener(
+		BuddyPluginListener	listener )
+	{
+		if ( listeners.contains(listener) ){
+			return;
+		}
+
+		listeners.add( listener );
+		
+		if ( initialisation_state != INIT_UNKNOWN ){
+			
+			listener.initialised( initialisation_state == INIT_OK );
+		}
+	}
+	
+	public void
+	removeListener(
+		BuddyPluginListener	listener )
+	{
+		listeners.remove( listener );
+	}
+	
+	protected Map
+	requestReceived(
+		BuddyPluginBuddy		from_buddy,
+		int						subsystem,
+		Map						content )
+	
+		throws BuddyPluginException
+	{
+		List	 listeners_ref = request_listeners.getList();
+		
+		for (int i=0;i<listeners_ref.size();i++){
+			
+			try{
+				Map reply = ((BuddyPluginBuddyRequestListener)listeners_ref.get(i)).requestReceived(from_buddy, subsystem, content);
+				
+				if ( reply != null ){
+					
+					return( reply );
+				}
+			}catch( BuddyPluginException e ){
+				
+				throw( e );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace( e );
+				
+				throw( new BuddyPluginException( "Request processing failed", e ));
+			}
+		}
+		
+		return( null );
+	}
+	
+	protected void
+   	fireAdded(
+   		BuddyPluginBuddy		buddy )
+   	{
+		if ( buddy.isAuthorised()){
+
+			buddy.setLocalAuthorisedRSSTagsOrCategories( public_tags_or_categories );
+			
+	   		List	 listeners_ref = listeners.getList();
+	   		
+	   		for (int i=0;i<listeners_ref.size();i++){
+	   			
+	   			try{
+	   				((BuddyPluginListener)listeners_ref.get(i)).buddyAdded( buddy );
+	 
+	   			}catch( Throwable e ){
+	   				
+	   				Debug.printStackTrace( e );
+	   			}
+	   		}
+		}
+   	}
+	
+	protected void
+   	fireRemoved(
+   		BuddyPluginBuddy		buddy )
+   	{
+		if ( buddy.isAuthorised()){
+			
+	   		List	 listeners_ref = listeners.getList();
+	   		
+	   		for (int i=0;i<listeners_ref.size();i++){
+	   			
+	   			try{
+	   				((BuddyPluginListener)listeners_ref.get(i)).buddyRemoved( buddy );
+	 
+	   			}catch( Throwable e ){
+	   				
+	   				Debug.printStackTrace( e );
+	   			}
+	   		}
+		}
+   	}
+	
+	protected void
+   	fireDetailsChanged(
+   		BuddyPluginBuddy		buddy )
+   	{
+		if ( buddy.isAuthorised()){
+			
+	   		List	 listeners_ref = listeners.getList();
+	   		
+	   		for (int i=0;i<listeners_ref.size();i++){
+	   			
+	   			try{
+	   				((BuddyPluginListener)listeners_ref.get(i)).buddyChanged( buddy );
+	 
+	   			}catch( Throwable e ){
+	   				
+	   				Debug.printStackTrace( e );
+	   			}
+	   		}
+		}
+   	}
+	
+	protected void
+   	fireYGM(
+   		BuddyPluginBuddy[]		from_buddies )
+   	{
+   		List	 listeners_ref = request_listeners.getList();
+   		
+   		for (int i=0;i<listeners_ref.size();i++){
+   			
+   			try{
+   				((BuddyPluginBuddyRequestListener)listeners_ref.get(i)).pendingMessages( from_buddies );
+ 
+   			}catch( Throwable e ){
+   				
+   				Debug.printStackTrace( e );
+   			}
+   		}
+   	}
+
+	protected void
+ 	fireEnabledStateChanged()
+ 	{
+		final boolean enabled = !plugin_interface.getPluginState().isDisabled() && isClassicEnabled();
+
+ 		List	 listeners_ref = listeners.getList();
+ 		
+ 		for (int i=0;i<listeners_ref.size();i++){
+ 			
+ 			try{
+ 				((BuddyPluginListener)listeners_ref.get(i)).enabledStateChanged( enabled );
+
+ 			}catch( Throwable e ){
+ 				
+ 				Debug.printStackTrace( e );
+ 			}
+ 		}
+ 	}
+	
+	protected void
+ 	fireUpdated()
+ 	{		
+ 		for ( BuddyPluginListener listener: listeners ){
+ 			
+ 			try{
+ 				listener.updated();
+
+ 			}catch( Throwable e ){
+ 				
+ 				Debug.printStackTrace( e );
+ 			}
+ 		}
+ 	}
+	
+	protected BuddyPluginViewInterface
+	getSWTUI()
+	{
+		return( swt_ui );
+	}
+	
+	protected void
+	rethrow(
+		String		reason,
+		Throwable	e )
+	
+		throws BuddyPluginException
+	{
+		logMessage( reason, e );
+
+		if ( e instanceof CryptoManagerPasswordException ){
+		
+		
+			throw( new BuddyPluginPasswordException(((CryptoManagerPasswordException)e).wasIncorrect(), reason, e ));
+		
+		}else{
+		
+			throw( new BuddyPluginException( reason, e ));
+		}
+	}
+		
+	public InputStream
+	handleURLProtocol(
+		AZPluginConnection			connection,
+		String						arg_str )
+	
+		throws IPCException
+	{
+		if ( arg_str.toLowerCase( Locale.US ).startsWith( "chat:" )){
+			
+				//azplug:?id=azbuddy&arg=chat%3Aanon%3Fmonkey%2520magic
+
+			if ( !beta_enabled_param.getValue()){
+				
+				throw( new IPCException( "Decentralized chat not enabled" ));
+			}
+				
+			try{
+				InputStream result = beta_plugin.handleURI( arg_str, false );
+				
+				if ( result != null ){
+					
+					return( result );
+				}
+				
+					// return an empty .vuze file to keep things happy...
+				
+				return( new ByteArrayInputStream( VuzeFileHandler.getSingleton().create().exportToBytes() ));
+
+			}catch( Throwable e ){
+				
+				throw( new IPCException( e ));
+			}	
+						
+		}else{
+			
+			String[]	args = arg_str.split( "&" );
+			
+			String		pk 				= null;
+			String		category_or_tag	= "All";
+			byte[]		hash			= null;
+			
+			for (String arg: args ){
+				
+				String[]	bits = arg.split( "=" );
+				
+				String	lhs = bits[0];
+				String	rhs	= UrlUtils.decode( bits[1] );
+				
+				if ( lhs.equals( "pk" )){
+					
+					pk		= rhs;
+					
+				}else if ( lhs.equals( "cat" )){
+					
+					category_or_tag = rhs;
+					
+				}else if ( lhs.equals( "hash" )){
+					
+					hash	= Base32.decode(rhs);
+				}
+			}
+			
+			if ( pk == null ){
+				
+				throw( new IPCException( "Public key missing from '" + arg_str + "'" ));
+			}
+			
+			BuddyPluginBuddy	buddy	= getBuddyFromPublicKey( pk );
+	
+			if ( buddy == null ){
+				
+				throw( new IPCException( "Buddy with public key '" + pk + "' not found" ));
+			}
+			
+			if ( hash == null ){
+				
+				return( handleUPRSS( connection, buddy, category_or_tag ));
+				
+			}else{
+				
+				return( handleUPTorrent( connection, buddy, category_or_tag, hash ));
+			}
+		}
+	}
+	
+	public InputStream
+	handleUPRSS(
+		final AZPluginConnection	connection,
+		BuddyPluginBuddy			buddy,
+		String						tag_or_category )
+	
+		throws IPCException
+	{
+		if ( !buddy.isOnline( true )){
+			
+			throw( new IPCException( "Buddy isn't online" ));
+		}
+		
+		Map<String,Object>	msg = new HashMap<String, Object>();
+
+		final String if_mod 	= connection.getRequestProperty( "If-Modified-Since" );
+
+		try{
+			msg.put( "cat", tag_or_category.getBytes( "UTF-8" ));
+									
+			if ( if_mod != null ){
+				
+				msg.put( "if_mod", if_mod );
+			}
+			
+			// String etag		= connection.getRequestProperty( "If-None-Match" );
+					
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+		
+		final Object[] 		result 		= { null };
+		final AESemaphore	result_sem 	= new AESemaphore( "BuddyPlugin:rss" );
+				
+		final String	etag = buddy.getPublicKey() + "-" + tag_or_category;
+		
+		az2_handler.sendAZ2RSSMessage( 
+			buddy,
+			msg,
+			new BuddyPluginAZ2TrackerListener()
+			{
+				public Map
+				messageReceived(
+					BuddyPluginBuddy	buddy,
+					Map					message )
+				{
+					try{						
+						byte[] bytes = (byte[])message.get( "rss" );
+					
+						ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+						
+						result[0] = bais;
+						
+						connection.setHeaderField( "ETag", etag );
+						
+						byte[] b_last_mod = (byte[])message.get( "last_mod" );
+						
+						if ( b_last_mod != null ){
+						
+							String	last_mod = new String( b_last_mod, "UTF-8" );
+							
+							connection.setHeaderField( "Last-Modified", last_mod );
+							
+							if ( if_mod != null && if_mod.equals( last_mod ) && bytes.length == 0 ){
+								
+								connection.setResponse( HttpURLConnection.HTTP_NOT_MODIFIED, "Not Modified" );
+							}
+						}
+						
+						result_sem.release();
+						
+					}catch( Throwable e ){
+					
+						messageFailed( buddy, e );
+					}
+					
+					return( null );
+				}
+				
+				public void
+				messageFailed(
+					BuddyPluginBuddy	buddy,
+					Throwable			cause )
+				{					
+					result[0] = new IPCException( "Read failed", cause );
+					
+					result_sem.release();
+				}
+			});
+		
+		result_sem.reserve( 60*1000 );
+		
+		if ( result[0] == null ){
+			
+			throw( new IPCException( "Timeout" ));
+			
+		}else if ( result[0] instanceof InputStream ){
+			
+			return((InputStream)result[0]);
+			
+		}else{
+			
+			throw((IPCException)result[0]);
+		}
+	}
+
+	public InputStream
+	handleUPTorrent(
+		final AZPluginConnection	connection,
+		final BuddyPluginBuddy		buddy,
+		String						tag_or_category,
+		final byte[]				hash )
+	
+		throws IPCException
+	{
+		final long timeout = 120*1000;
+
+		final Object[] 		result 		= { null };
+		final AESemaphore	result_sem 	= new AESemaphore( "BuddyPlugin:upt" );
+			
+		log( "Attempting to download torrent for " + Base32.encode( hash ));
+		
+			// first try and get torrent direct from the buddy
+		
+		if ( buddy.isOnline( true )){
+
+			try{
+				
+				Map<String,Object>	msg = new HashMap<String, Object>();
+			
+				try{
+					msg.put( "cat", tag_or_category.getBytes( "UTF-8" ));
+									
+					msg.put( "hash", hash );
+							
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+							
+				az2_handler.sendAZ2RSSMessage( 
+					buddy,
+					msg,
+					new BuddyPluginAZ2TrackerListener()
+					{
+						private boolean	result_set;
+					
+						public Map
+						messageReceived(
+							BuddyPluginBuddy	buddy,
+							Map					message )
+						{
+							try{						
+								byte[] bytes = (byte[])message.get( "torrent" );
+									
+								log( "    torrent downloaded from buddy" );
+								
+								setResult( bytes );
+																
+							}catch( Throwable e ){
+							
+								messageFailed( buddy, e );
+							}
+							
+							return( null );
+						}
+						
+						public void
+						messageFailed(
+							BuddyPluginBuddy	buddy,
+							Throwable			cause )
+						{					
+							setResult( new IPCException( "Read failed", cause ));
+						}
+						
+						protected void
+						setResult(
+							Object		obj )
+						{
+							synchronized( result ){
+								
+								if ( result_set ){
+									
+									return;
+								}
+								
+								result_set = true;
+								
+								if ( !( result[0] instanceof byte[] )){
+								
+									result[0] = obj;
+								}
+								
+								result_sem.release();
+							}
+						}
+					});
+			}catch( Throwable e ){
+				
+				result[0] = new IPCException( "Buddy torrent get failed", e );
+				
+				result_sem.release();
+			}
+		}else{
+			
+			result[0] = new IPCException( "Buddy is offline" );
+
+			result_sem.release();
+		}
+		
+			// second try and get via magnet
+		
+		final MagnetPlugin	magnet_plugin = getMagnetPlugin();
+		
+		if ( magnet_plugin == null ){
+		
+			synchronized( result ){
+				
+				if ( result[0] == null ){
+					
+					result[0] = new IPCException( "Magnet plugin unavailable" );
+				}
+			}
+				
+			result_sem.release();
+			
+		}else{
+
+			new AEThread2( "BuddyPlugin:mag", true )
+			{
+				private boolean result_set;
+				
+				public void
+				run()
+				{
+					try{
+						
+						if ( buddy.isOnline( true )){
+							
+							Thread.sleep(10*1000);
+						}
+						
+						synchronized( result ){
+
+							if ( result[0] instanceof byte[] ){
+								
+								setResult( null );
+								
+								return;
+							}
+						}
+						
+						byte[] torrent_data = magnet_plugin.download(
+							new MagnetPluginProgressListener()
+							{
+								public void
+								reportSize(
+									long	size )
+								{
+								}
+								
+								public void
+								reportActivity(
+									String	str )
+								{
+									log( "    MagnetDownload: " + str );
+								}
+								
+								public void
+								reportCompleteness(
+									int		percent )
+								{
+								}
+								
+								public void
+								reportContributor(
+									InetSocketAddress	address )
+								{
+								}
+								
+								public boolean 
+								verbose() 
+								{
+									return( false );
+								}
+								
+								public boolean 
+								cancelled() 
+								{
+									return( false );
+								}
+							},
+							hash,
+							"",
+							new InetSocketAddress[0],
+							timeout,
+							MagnetPlugin.FL_NONE );
+						
+						if ( torrent_data == null ){
+							
+							setResult( new IPCException( "Magnet timeout" ));
+													
+						}else{					
+							
+							log( "    torrent downloaded from magnet" );
+
+							setResult( torrent_data );
+						}
+					}catch( Throwable e ){
+						
+						setResult( new IPCException( "Magnet get failed", e ));
+					}
+				}
+				
+				protected void
+				setResult(
+					Object		obj )
+				{
+					synchronized( result ){
+						
+						if ( result_set ){
+							
+							return;
+						}
+						
+						result_set = true;
+						
+						if ( obj != null ){
+							
+							if ( 	result[0] == null ||
+									( obj instanceof byte[] && !( result[0] instanceof byte[] ))){
+								
+								result[0] = obj;
+							}
+						}
+							
+						result_sem.release();
+					}
+				}
+			}.start();
+		}
+		
+		long	start = SystemTime.getMonotonousTime();
+				
+		if ( result_sem.reserve(timeout )){
+			
+			if ( !( result[0] instanceof byte[] )){
+		
+				long	rem = timeout - ( SystemTime.getMonotonousTime() - start );
+				
+				if ( rem > 0 ){
+				
+					result_sem.reserve(rem );
+				}
+			}
+		}
+		
+		if ( result[0] == null ){
+			
+			log( "    torrent download timeout" );
+
+			throw( new IPCException( "Timeout" ));
+			
+		}else if ( result[0] instanceof byte[] ){
+						
+			return( new ByteArrayInputStream((byte[])result[0]));
+			
+		}else{
+			
+			IPCException error = (IPCException)result[0];
+			
+			log( "    torrent downloaded failed: " + Debug.getNestedExceptionMessage( error ));
+
+			throw( error );
+		}
+	}
+
+	protected MagnetPlugin
+	getMagnetPlugin()
+	{
+		PluginInterface  pi  = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass( MagnetPlugin.class );
+	
+		if ( pi == null ){
+			
+			return( null );
+		}
+		
+		return((MagnetPlugin)pi.getPlugin());
+	}
+	
+	public feedDetails
+	getRSS(
+		BuddyPluginBuddy		buddy,
+		String					tag_or_category,
+		String					if_mod )
+	
+		throws BuddyPluginException
+	{
+		if ( !buddy.isLocalRSSTagOrCategoryAuthorised( tag_or_category )){
+			
+			throw( new BuddyPluginException( "Unauthorised tag/category '" + tag_or_category + "'" ));
+		}
+		
+		buddy.localRSSTagOrCategoryRead( tag_or_category );
+		
+		Download[] downloads = plugin_interface.getDownloadManager().getDownloads();
+		
+		List<Download>	selected_dls = new ArrayList<Download>();
+		
+		long	fingerprint	= 0;
+		
+		for (int i=0;i<downloads.length;i++){
+			
+			Download download = downloads[i];
+			
+			Torrent torrent = download.getTorrent();
+			
+			if ( torrent == null ){
+				
+				continue;
+			}
+			
+			boolean	match = tag_or_category.equalsIgnoreCase( "all" );
+			
+			if ( !match ){
+			
+				String dl_cat = download.getAttribute( ta_category );
+		
+				match = dl_cat != null && dl_cat.equals( tag_or_category );
+			}
+			
+			if ( !match ){
+				
+				try{
+					List<Tag> tags = TagManagerFactory.getTagManager().getTagsForTaggable( TagType.TT_DOWNLOAD_MANUAL, PluginCoreUtils.unwrap( download ));
+					
+					for ( Tag tag: tags ){
+						
+						if ( tag.getTagName( true ).equals( tag_or_category )){
+							
+							match = true;
+							
+							break;
+						}
+					}
+				}catch( Throwable e ){
+				}
+			}
+			
+			if ( match ){
+				
+				if ( !TorrentUtils.isReallyPrivate( PluginCoreUtils.unwrap( torrent ))){
+					
+					selected_dls.add( download );
+					
+					byte[] hash = torrent.getHash();
+					
+					int	num = (hash[0]<<24)&0xff000000 | (hash[1] << 16)&0x00ff0000 | (hash[2] << 8)&0x0000ff00 | hash[3]&0x000000ff;
+
+					fingerprint += num;
+				}
+			}
+		}
+		
+		PluginConfig pc = plugin_interface.getPluginconfig();
+
+		String	feed_finger_key = "feed_finger.category." + tag_or_category;
+		String	feed_date_key 	= "feed_date.category." + tag_or_category;
+
+		long	existing_fingerprint 	= pc.getPluginLongParameter( feed_finger_key, 0 );
+		long	feed_date 				= pc.getPluginLongParameter( feed_date_key, 0 );
+
+		long	now = SystemTime.getCurrentTime();
+
+		if ( existing_fingerprint == fingerprint ){
+			
+				// update every now and then to pick up new peer/seed values
+			
+			if ( selected_dls.size() > 0 ){
+
+				if ( 	now < feed_date ||
+						now - feed_date > FEED_UPDATE_MIN_MILLIS ){
+					
+					feed_date = now;
+				
+					pc.setPluginParameter( feed_date_key, feed_date );
+				}
+			}
+		}else{
+			
+			pc.setPluginParameter( feed_finger_key, fingerprint );
+			
+			
+				// ensure feed date goes up
+			
+			if ( now <= feed_date ){
+				
+				feed_date++;
+				
+			}else{
+				
+				feed_date = now;
+			}
+			
+			pc.setPluginParameter( feed_date_key, feed_date );
+		}
+		
+		String last_modified = TimeFormatter.getHTTPDate( feed_date );
+
+		if ( if_mod != null && if_mod.equals( last_modified )){
+			
+			return( new feedDetails( new byte[0], last_modified ));
+		}
+				
+		ByteArrayOutputStream	os = new ByteArrayOutputStream();
+			
+		try{
+			PrintWriter pw = new PrintWriter(new OutputStreamWriter( os, "UTF-8" ));
+			
+			pw.println( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
+			
+			pw.println( "<rss version=\"2.0\" xmlns:vuze=\"http://www.vuze.com\">" );
+			
+			pw.println( "<channel>" );
+			
+			pw.println( "<title>" + escape( tag_or_category ) + "</title>" );
+			
+			Collections.sort(
+				selected_dls,
+				new Comparator<Download>()
+				{
+					public int 
+					compare(
+						Download d1, 
+						Download d2) 
+					{
+						long	added1 = getAddedTime( d1 )/1000;
+						long	added2 = getAddedTime( d2 )/1000;
+		
+						return((int)(added2 - added1 ));
+					}
+				});
+								
+							
+			pw.println(	"<pubDate>" + last_modified + "</pubDate>" );
+		
+			for (int i=0;i<selected_dls.size();i++){
+				
+				Download download = (Download)selected_dls.get( i );
+				
+				DownloadManager	core_download = PluginCoreUtils.unwrap( download );
+				
+				Torrent torrent = download.getTorrent();
+				
+				String	hash_str = Base32.encode( torrent.getHash());
+				
+				pw.println( "<item>" );
+				
+				pw.println( "<title>" + escape( download.getName()) + "</title>" );
+				
+				pw.println( "<guid>" + hash_str + "</guid>" );
+				
+				long added = core_download.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME);
+				
+				pw.println(	"<pubDate>" + TimeFormatter.getHTTPDate( added ) + "</pubDate>" );
+				
+				pw.println(	"<vuze:size>" + torrent.getSize()+ "</vuze:size>" );
+				pw.println(	"<vuze:assethash>" + hash_str + "</vuze:assethash>" );
+				
+				String url = "azplug:?id=azbuddy&name=Friends&arg=";
+				
+				String arg = "pk=" + getPublicKey() + "&cat=" + tag_or_category + "&hash=" + Base32.encode(torrent.getHash());
+
+				url += URLEncoder.encode( arg, "UTF-8" );
+			
+				pw.println( "<vuze:downloadurl>" + escape( url ) + "</vuze:downloadurl>" );
+		
+				DownloadScrapeResult scrape = download.getLastScrapeResult();
+				
+				if ( scrape != null && scrape.getResponseType() == DownloadScrapeResult.RT_SUCCESS ){
+					
+					pw.println(	"<vuze:seeds>" + scrape.getSeedCount() + "</vuze:seeds>" );
+					pw.println(	"<vuze:peers>" + scrape.getNonSeedCount() + "</vuze:peers>" );
+				}
+				
+				pw.println( "</item>" );
+			}
+			
+			pw.println( "</channel>" );
+			
+			pw.println( "</rss>" );
+		
+			pw.flush();
+			
+			return( new feedDetails( os.toByteArray(), last_modified ));
+			
+		}catch( IOException e ){
+			
+			throw( new BuddyPluginException( "", e ));
+		}
+	}
+	
+	public byte[]
+	getRSSTorrent(
+		BuddyPluginBuddy		buddy,
+		String					category,
+		byte[]					hash )
+	
+		throws BuddyPluginException
+	{
+		if ( !buddy.isLocalRSSTagOrCategoryAuthorised( category )){
+			
+			throw( new BuddyPluginException( "Unauthorised category '" + category + "'" ));
+		}
+		
+		try{
+			Download download = plugin_interface.getDownloadManager().getDownload( hash );
+			
+			if ( download != null ){
+				
+				Torrent	torrent = download.getTorrent();
+			
+				if ( torrent != null ){
+								
+					String dl_cat = download.getAttribute( ta_category );
+					
+					if ( 	category.equalsIgnoreCase( "all" ) ||
+							( dl_cat != null && dl_cat.equals( category ))){
+						
+						if ( !TorrentUtils.isReallyPrivate( PluginCoreUtils.unwrap( torrent ))){
+							
+							torrent = torrent.removeAdditionalProperties();
+							
+							return( torrent.writeToBEncodedData());
+						}
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			throw( new BuddyPluginException( "getTorrent failed", e ));
+		}
+		
+		throw( new BuddyPluginException( "Not found" ));
+	}		
+
+	protected long
+	getAddedTime(
+		Download	download )
+	{
+		DownloadManager	core_download = PluginCoreUtils.unwrap( download );
+		
+		return( core_download.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME));
+	}
+	
+	protected String
+	escape(
+		String	str )
+	{
+		return( XUXmlWriter.escapeXML(str));
+	}
+	
+	public void
+	addRequestListener(
+		BuddyPluginBuddyRequestListener	listener )
+	{
+		request_listeners.add( listener );
+	}
+	
+	public void
+	removeRequestListener(
+		BuddyPluginBuddyRequestListener	listener )
+	{
+		request_listeners.remove( listener );
+	}
+	
+	public void
+	logMessage(
+		String		str,
+		Throwable	e )
+	{
+		logMessage( str + ": " + Debug.getNestedExceptionMessage(e), true );
+	}
+	
+	public void
+	logMessage(
+		String		str )
+	{
+		logMessage( str, false );
+	}
+	
+	public void
+	logMessage(
+		String		str,
+		boolean		is_error )
+	{
+		log( str );
+		
+		Iterator it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((BuddyPluginListener)it.next()).messageLogged( str, is_error );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace( e );
+			}
+		}
+	}
+	
+	public void
+	log(
+		String		str )
+	{
+		logger.log( str );
+	}
+	
+	public void
+	log(
+		String		str,
+		Throwable	e )
+	{
+		logger.log( str + ": " + Debug.getNestedExceptionMessageAndStack( e ));
+	}
+
+	private class
+	publishDetails
+		implements Cloneable
+	{
+		private byte[]			public_key;
+		private InetAddress		ip;
+		private int				tcp_port;
+		private int				udp_port;
+		private String			nick_name;
+		private int				online_status		= STATUS_ONLINE;
+		
+		private boolean			enabled;
+		private boolean			published;
+		
+		private int				sequence;
+		
+		protected publishDetails
+		getCopy()
+		{
+			try{
+				publishDetails copy = (publishDetails)clone();
+				
+				copy.published = false;
+				
+				return( copy );
+				
+			}catch( Throwable e ){
+				
+				return( null);
+			}
+		}
+		
+		protected boolean
+		isPublished()
+		{
+			return( published );
+		}
+		
+		protected void
+		setPublished(
+			boolean		b )
+		{
+			published	= b;
+		}
+		
+		protected boolean
+		isEnabled()
+		{
+			return( enabled );
+		}
+		
+		protected void
+		setEnabled(
+			boolean	_enabled )
+		{
+			enabled	= _enabled;
+		}
+		
+		protected void
+		setSequence(
+			int		seq )
+		{
+			sequence = seq;
+		}
+		
+		protected int
+		getSequence()
+		{
+			return( sequence );
+		}
+		
+		protected byte[]
+		getPublicKey()
+		{
+			return( public_key );
+		}
+		
+		protected void
+		setPublicKey(
+			byte[]		k )
+		{
+			public_key	= k;
+		}
+		
+		protected InetAddress
+		getIP()
+		{
+			return( ip );
+		}
+		
+		protected void
+		setIP(
+			InetAddress	_ip )
+		{
+			ip	= _ip;
+		}
+		
+		protected int
+		getTCPPort()
+		{
+			return( tcp_port );
+		}
+		
+		protected void
+		setTCPPort(
+			int		_port )
+		{
+			tcp_port = _port;
+		}
+		
+		protected int
+		getUDPPort()
+		{
+			return( udp_port );
+		}
+		
+		protected void
+		setUDPPort(
+			int		_port )
+		{
+			udp_port = _port;
+		}
+		
+		protected String
+		getNickName()
+		{
+			return( nick_name );
+		}
+		
+		protected void
+		setNickName(
+			String		 n )
+		{
+			nick_name	= n;
+		}
+		
+		protected int
+		getOnlineStatus()
+		{
+			return( online_status );
+		}
+		
+		protected void
+		setOnlineStatus(
+			int		_status )
+		{
+			online_status = _status;
+		}
+		
+		protected String
+		getString()
+		{
+			return( "enabled=" + enabled + ",ip=" + ip + ",tcp=" + tcp_port + ",udp=" + udp_port + ",stat=" + online_status + ",key=" + (public_key==null?"<none>":Base32.encode( public_key )));
+		}
+	}
+	
+	protected interface
+	operationListener
+	{
+		public void
+		complete();
+	}
+	
+	public interface
+	cryptoResult
+	{
+		public byte[]
+		getChallenge();
+		
+		public byte[]
+		getPayload();
+	}
+	
+	protected class
+	feedDetails
+	{
+		private byte[]		contents;
+		private String		last_modified;
+		
+		protected
+		feedDetails(
+			byte[]		_contents,
+			String		_last_modified )
+		{
+			contents		= _contents;
+			last_modified	= _last_modified;
+		}
+		
+		protected byte[]
+		getContent()
+		{
+			return( contents );
+		}
+		
+		protected String
+		getLastModified()
+		{
+			return( last_modified );
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2.java
index 04db3a0..0cf843e 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2.java
@@ -1,1021 +1,1020 @@
-/*
- * Created on Apr 10, 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.plugins.net.buddy;
-
-import java.security.SecureRandom;
-import java.util.*;
-
-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.RandomUtils;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.torrent.Torrent;
-import org.gudy.azureus2.plugins.ui.UIManagerEvent;
-
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-public class 
-BuddyPluginAZ2 
-{
-	public static final int RT_AZ2_REQUEST_MESSAGE		= 1;
-	public static final int RT_AZ2_REPLY_MESSAGE		= 2;
-	
-	public static final int RT_AZ2_REQUEST_SEND_TORRENT	= 3;
-	public static final int RT_AZ2_REPLY_SEND_TORRENT	= 4;
-
-	public static final int RT_AZ2_REQUEST_CHAT			= 5;
-	public static final int RT_AZ2_REPLY_CHAT			= 6;
-
-	public static final int RT_AZ2_REQUEST_TRACK		= 7;
-	public static final int RT_AZ2_REPLY_TRACK			= 8;
-
-	public static final int RT_AZ2_REQUEST_RSS			= 9;
-	public static final int RT_AZ2_REPLY_RSS			= 10;
-
-	public static final int CHAT_MSG_TYPE_TEXT						= 1;
-	public static final int CHAT_MSG_TYPE_PARTICIPANTS_ADDED		= 2;
-	public static final int CHAT_MSG_TYPE_PARTICIPANTS_REMOVED		= 3;
-	
-
-	private static final int SEND_TIMEOUT = 2*60*1000;
-	
-	private BuddyPlugin		plugin;
-	
-	private Map				chats 		= new HashMap();
-	
-	private CopyOnWriteList	listeners = new CopyOnWriteList();
-	
-	private CopyOnWriteList	track_listeners = new CopyOnWriteList();
-	
-	protected 
-	BuddyPluginAZ2(
-		BuddyPlugin		_plugin )
-	{
-		plugin	= _plugin;
-		
-		plugin.addRequestListener(
-				new BuddyPluginBuddyRequestListener()
-				{
-					public Map
-					requestReceived(
-						BuddyPluginBuddy	from_buddy,
-						int					subsystem,
-						Map					request )
-					
-						throws BuddyPluginException
-					{
-						if ( subsystem == BuddyPlugin.SUBSYSTEM_AZ2 ){
-							
-							if ( !from_buddy.isAuthorised()){
-							
-								throw( new BuddyPluginException( "Unauthorised" ));
-							}
-						
-							return( processAZ2Request( from_buddy, request ));
-						}
-
-						return( null );
-					}
-					
-					public void
-					pendingMessages(
-						BuddyPluginBuddy[]	from_buddies )
-					{
-					}
-				});
-	}
-	
-	protected Map
-	processAZ2Request(
-		final BuddyPluginBuddy	from_buddy,
-		Map						request )		
-		
-		throws BuddyPluginException
-	{
-		logMessage( "AZ2 request received: " + from_buddy.getString() + " -> " + request );
-			
-		int	type = ((Long)request.get( "type" )).intValue();
-		
-		Map	reply = new HashMap();
-				
-		if ( type == RT_AZ2_REQUEST_MESSAGE ){
-			
-			try{
-				String	msg = new String( (byte[])request.get( "msg" ), "UTF8" );
-			
-				from_buddy.setLastMessageReceived( msg );
-				
-			}catch( Throwable e ){
-				
-			}
-			
-			reply.put( "type", new Long( RT_AZ2_REPLY_MESSAGE ));
-
-		}else if (  type == RT_AZ2_REQUEST_SEND_TORRENT ){
-			
-			try{
-				final Torrent	torrent = plugin.getPluginInterface().getTorrentManager().createFromBEncodedData((byte[])request.get( "torrent" ));
-			
-				new AEThread2( "torrentAdder", true )
-				{
-					public void
-					run()
-					{
-						PluginInterface pi = plugin.getPluginInterface();
-						
-						String msg = pi.getUtilities().getLocaleUtilities().getLocalisedMessageText(
-								"azbuddy.addtorrent.msg", 
-								new String[]{ from_buddy.getName(), torrent.getName() });
-						
-						long res = pi.getUIManager().showMessageBox(
-										"azbuddy.addtorrent.title",
-										"!" + msg + "!",
-										UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
-						
-						if ( res == UIManagerEvent.MT_YES ){
-						
-							pi.getUIManager().openTorrent( torrent );
-						}
-					}
-				}.start();
-				
-				reply.put( "type", new Long( RT_AZ2_REPLY_SEND_TORRENT ));
-				
-			}catch( Throwable e ){
-				
-				throw( new BuddyPluginException( "Torrent receive failed " + type ));
-			}
-		}else if (  type == RT_AZ2_REQUEST_CHAT ){
-			
-			Map msg = (Map)request.get( "msg" );
-			
-			String	id = new String((byte[])msg.get( "id" ));
-			
-			chatInstance	chat;
-			boolean			new_chat = false;
-			
-			synchronized( chats ){
-				
-				 chat = (chatInstance)chats.get( id );
-				 
-				 if ( chat == null ){
-					 
-					 if ( chats.size() > 32 ){
-						 
-						 throw( new BuddyPluginException( "Too many chats" ));
-					 }
-					 
-					 chat = new chatInstance( id );
-					 
-					 chats.put( id, chat );
-					 
-					 new_chat = true;
-				 }
-			}
-			
-			if ( new_chat ){
-			
-				informCreated( chat );
-			}
-			
-			chat.addParticipant( from_buddy );
-			
-			chat.process( from_buddy, msg );
-						
-			reply.put( "type", new Long( RT_AZ2_REPLY_CHAT ));
-						
-		}else if (  type == RT_AZ2_REQUEST_TRACK ){
-			
-			Map msg = (Map)request.get( "msg" );
-
-			Iterator it = track_listeners.iterator();
-			
-			boolean	ok = false;
-			
-			while( it.hasNext()){
-				
-				try{
-			
-					Map res = ((BuddyPluginAZ2TrackerListener)it.next()).messageReceived( from_buddy, msg );
-					
-					if ( res != null ){
-						
-						reply.put( "msg", res );
-						reply.put( "type", new Long( RT_AZ2_REPLY_TRACK ));
-
-						ok = true;
-						
-						break;
-					}
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-			
-			if ( !ok ){
-			
-				throw( new BuddyPluginException( "Unhandled request type " + type ));
-			}
-		}else if (  type == RT_AZ2_REQUEST_RSS ){
-				
-			try{
-				Map<String,Object> res = new HashMap<String, Object>();
-
-				reply.put( "msg", res );
-				reply.put( "type", new Long( RT_AZ2_REPLY_RSS ));
-
-				Map msg = (Map)request.get( "msg" );
-
-				String category = new String((byte[])msg.get( "cat"), "UTF-8" );
-				
-				byte[] hash	= (byte[])msg.get( "hash" );
-				
-				if ( hash == null ){
-					
-					byte[]	if_mod 	= (byte[])msg.get( "if_mod" );
-					
-					BuddyPlugin.feedDetails feed = plugin.getRSS( from_buddy, category, if_mod==null?null:new String( if_mod, "UTF-8" ));
-					
-					res.put( "rss", feed.getContent());
-					
-					res.put( "last_mod", feed.getLastModified());
-					
-				}else{
-					
-					res.put( "torrent", plugin.getRSSTorrent( from_buddy, category, hash ));
-				}
-			}catch( BuddyPluginException e  ){
-				
-				throw( e );
-				
-			}catch( Throwable e ){
-				
-				throw( new BuddyPluginException( "Failed to handle rss", e ));
-			}
-		}else{
-			
-			throw( new BuddyPluginException( "Unrecognised request type " + type ));
-		}
-		
-		logMessage( "AZ2 reply sent: " + from_buddy.getString() + " <- " + reply );
-
-		return( reply );
-	}
-		
-	public chatInstance
-	createChat(
-		BuddyPluginBuddy[]		buddies )
-	{
-		byte[]	id_bytes = new byte[20];
-		
-		RandomUtils.SECURE_RANDOM.nextBytes( id_bytes );
-		
-		String	id = Base32.encode( id_bytes );
-		
-		chatInstance	chat;
-		
-		synchronized( chats ){
-
-			chat = new chatInstance( id );
-			
-			chats.put( id, chat );
-		}
-		
-		logMessage( "Chat " + chat.getID() + " created" );
-
-		informCreated( chat );
-					
-		chat.addParticipants( buddies, true );
-		
-		return( chat );
-	}
-	
-	protected void
-	destroyChat(
-		chatInstance	chat )
-	{
-		synchronized( chats ){
-
-			chats.remove( chat.getID());
-		}
-		
-		logMessage( "Chat " + chat.getID() + " destroyed" );
-		
-		informDestroyed( chat );
-	}
-	
-	protected void
-	informCreated(
-		chatInstance		chat )
-	{
-		Iterator	it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			((BuddyPluginAZ2Listener)it.next()).chatCreated( chat );
-		}
-	}
-	
-	protected void
-	informDestroyed(
-		chatInstance		chat )
-	{
-		Iterator	it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			((BuddyPluginAZ2Listener)it.next()).chatDestroyed( chat );
-		}
-	}
-	
-	public void
-	sendAZ2Message(
-		BuddyPluginBuddy	buddy,
-		String				msg )
-	{
-		try{
-			Map	request = new HashMap();
-			
-			request.put( "type", new Long( RT_AZ2_REQUEST_MESSAGE ));
-			request.put( "msg", msg.getBytes());
-			
-			sendMessage( buddy, request );
-				
-		}catch( Throwable e ){
-			
-			logMessageAndPopup( "Send message failed", e );
-		}
-	}
-	
-	protected void
-	sendAZ2Chat(
-		BuddyPluginBuddy	buddy,
-		Map					msg )
-	{
-		try{
-			Map	request = new HashMap();
-			
-			request.put( "type", new Long( RT_AZ2_REQUEST_CHAT ));
-			request.put( "msg", msg );
-			
-			sendMessage( buddy, request );
-				
-		}catch( Throwable e ){
-			
-			logMessageAndPopup( "Send message failed", e );
-		}
-	}
-	
-	public void
-	sendAZ2Torrent(
-		Torrent				torrent,
-		BuddyPluginBuddy	buddy )
-	{
-		try{
-			
-			Map	request = new HashMap();
-			
-			request.put( "type", new Long( RT_AZ2_REQUEST_SEND_TORRENT ));
-			request.put( "torrent", torrent.writeToBEncodedData());
-			
-			sendMessage( buddy, request );
-			
-		}catch( Throwable e ){
-			
-			logMessageAndPopup( "Send torrent failed", e );
-		}
-	}
-	
-	public void
-	sendAZ2TrackerMessage(
-		BuddyPluginBuddy						buddy,
-		Map										msg,
-		final BuddyPluginAZ2TrackerListener		listener )
-	{
-		logMessage( "AZ2 request sent: " + buddy.getString() + " <- " + msg );
-
-		try{
-			Map	request = new HashMap();
-			
-			request.put( "type", new Long( RT_AZ2_REQUEST_TRACK ));
-			request.put( "msg", msg );
-			
-			buddy.sendMessage(
-				BuddyPlugin.SUBSYSTEM_AZ2,
-				request,
-				SEND_TIMEOUT,
-				new BuddyPluginBuddyReplyListener()
-				{
-					public void
-					replyReceived(
-						BuddyPluginBuddy		from_buddy,
-						Map						reply )
-					{
-						int type = ((Long)reply.get( "type")).intValue();
-						
-						if ( type != RT_AZ2_REPLY_TRACK ){
-							
-							sendFailed( from_buddy, new BuddyPluginException( "Mismatched reply type" ));
-						}
-						
-						listener.messageReceived( from_buddy, (Map)reply.get( "msg" ));
-					}
-					
-					public void
-					sendFailed(
-						BuddyPluginBuddy		to_buddy,
-						BuddyPluginException	cause )
-					{
-						listener.messageFailed( to_buddy, cause );
-					}
-				});
-				
-		}catch( Throwable e ){
-			
-			logMessageAndPopup( "Send message failed", e );
-		}
-	}
-	
-	public void
-	sendAZ2RSSMessage(
-		BuddyPluginBuddy						buddy,
-		Map										msg,
-		final BuddyPluginAZ2TrackerListener		listener )
-	{
-		logMessage( "AZ2 request sent: " + buddy.getString() + " <- " + msg );
-
-		try{
-			Map	request = new HashMap();
-			
-			request.put( "type", new Long( RT_AZ2_REQUEST_RSS ));
-			request.put( "msg", msg );
-			
-			buddy.sendMessage(
-				BuddyPlugin.SUBSYSTEM_AZ2,
-				request,
-				SEND_TIMEOUT,
-				new BuddyPluginBuddyReplyListener()
-				{
-					public void
-					replyReceived(
-						BuddyPluginBuddy		from_buddy,
-						Map						reply )
-					{
-						int type = ((Long)reply.get( "type")).intValue();
-						
-						if ( type != RT_AZ2_REPLY_RSS ){
-							
-							sendFailed( from_buddy, new BuddyPluginException( "Mismatched reply type" ));
-						}
-						
-						listener.messageReceived( from_buddy, (Map)reply.get( "msg" ));
-					}
-					
-					public void
-					sendFailed(
-						BuddyPluginBuddy		to_buddy,
-						BuddyPluginException	cause )
-					{
-						listener.messageFailed( to_buddy, cause );
-					}
-				});
-				
-		}catch( Throwable e ){
-			
-			logMessage( "Send message failed", e );
-		}
-	}
-	
-	protected void
-	sendMessage(
-		BuddyPluginBuddy	buddy,
-		Map					request )
-	
-		throws BuddyPluginException
-	{
-		logMessage( "AZ2 request sent: " + buddy.getString() + " <- " + request );
-
-		buddy.getMessageHandler().queueMessage( 
-				BuddyPlugin.SUBSYSTEM_AZ2,
-				request,
-				SEND_TIMEOUT );		
-	}
-	
-	public void
-	addListener(
-		BuddyPluginAZ2Listener		listener )
-	{
-		listeners.add( listener );
-	}
-	
-	public void
-	removeListener(
-		BuddyPluginAZ2Listener		listener )
-	{
-		listeners.remove( listener );
-	}
-	
-	public void
-	addTrackerListener(
-		BuddyPluginAZ2TrackerListener		listener )
-	{
-		track_listeners.add( listener );
-	}
-	
-	public void
-	removeTrackerListener(
-		BuddyPluginAZ2TrackerListener		listener )
-	{
-		track_listeners.remove( listener );
-	}
-	
-	protected void
-	logMessageAndPopup(
-		String		str,
-		Throwable	e )
-	{
-		logMessageAndPopup( str + ": " + Debug.getNestedExceptionMessage(e));
-	}
-	
-	protected void
-	logMessageAndPopup(
-		String		str )
-	{
-		logMessage( str );
-		
-		plugin.getPluginInterface().getUIManager().showMessageBox(
-			"azbuddy.msglog.title", "!" + str + "!", UIManagerEvent.MT_OK );
-	}
-	
-	protected void
-	logMessage(
-		String		str )
-	{
-		plugin.logMessage( str );
-	}
-	
-	protected void
-	logMessage(
-		String		str,
-		Throwable 	e )
-	{
-		plugin.logMessage( str + ": " + Debug.getNestedExceptionMessage(e));
-	}
-	
-	public class
-	chatInstance
-		extends BuddyPluginAdapter
-	{
-		private String		id;
-		
-		private Map				participants 	= new HashMap();
-		private CopyOnWriteList	listeners 		= new CopyOnWriteList();
-		
-		private List			history			= new ArrayList();
-		
-		protected
-		chatInstance(
-			String		_id )
-		{
-			id		= _id;
-			
-			plugin.addListener( this );
-		}
-		
-		public String
-		getID()
-		{
-			return( id );
-		}
-		
-		public void
-		buddyAdded(
-			BuddyPluginBuddy	buddy )
-		{
-			buddyChanged( buddy );
-		}
-		
-		public void
-		buddyRemoved(
-			BuddyPluginBuddy	buddy )
-		{
-			chatParticipant p = getParticipant( buddy );
-			
-			if ( p != null ){
-				
-				Iterator it = listeners.iterator();
-				
-				while( it.hasNext()){
-					
-					try{
-						((BuddyPluginAZ2ChatListener)it.next()).participantRemoved( p );
-						
-					}catch( Throwable e ){
-						
-						Debug.printStackTrace(e);
-					}
-				}
-			}
-		}
-
-		public void
-		buddyChanged(
-			BuddyPluginBuddy	buddy )
-		{
-			chatParticipant p = getParticipant( buddy );
-			
-			if ( p != null ){
-			
-				Iterator it = listeners.iterator();
-			
-				while( it.hasNext()){
-					
-					try{
-						((BuddyPluginAZ2ChatListener)it.next()).participantChanged( p );
-						
-					}catch( Throwable e ){
-						
-						Debug.printStackTrace(e);
-					}
-				}
-			}
-		}
-		
-		protected void
-		process(
-			BuddyPluginBuddy	from_buddy,
-			Map					msg )
-		{
-			chatParticipant p = getOrAddParticipant( from_buddy );
-			
-			int	type = ((Long)msg.get( "type")).intValue();
-			
-			if ( type == CHAT_MSG_TYPE_TEXT ){
-		
-				Iterator it = listeners.iterator();
-				
-				synchronized( history ){
-				
-					history.add( new chatMessage( p.getName(), msg ));
-					
-					if ( history.size() > 128 ){
-						
-						history.remove(0);
-					}
-				}
-				
-				while( it.hasNext()){
-					
-					try{
-						((BuddyPluginAZ2ChatListener)it.next()).messageReceived( p, msg );
-						
-					}catch( Throwable e ){
-						
-						Debug.printStackTrace(e);
-					}
-				}
-			}else if ( type == CHAT_MSG_TYPE_PARTICIPANTS_ADDED ){
-				
-				List added = (List)msg.get( "p" );
-				
-				for (int i=0;i<added.size();i++){
-					
-					Map	participant = (Map)added.get(i);
-					
-					String pk = new String((byte[])participant.get( "pk" ));
-					
-					if ( !pk.equals( plugin.getPublicKey())){
-					
-						addParticipant( pk );
-					}
-				}
-			}
-		}
-		
-		public void
-		sendMessage(
-			Map		msg )
-		{
-			msg.put( "type", new Long( CHAT_MSG_TYPE_TEXT ));
-			
-			sendMessageBase( msg );
-		}
-		
-		protected void
-		sendMessageBase(
-			Map		msg )
-		{
-			Map	ps;
-			
-			synchronized( participants ){
-				
-				ps = new HashMap( participants );
-			}
-			
-			msg.put( "id", id );
-			
-			Iterator it = ps.values().iterator();
-			
-			while( it.hasNext()){
-				
-				chatParticipant participant = (chatParticipant)it.next();
-				
-				if ( participant.isAuthorised()){
-					
-					sendAZ2Chat( participant.getBuddy(), msg );
-				}
-			}
-		}
-		
-		public chatMessage[]
-		getHistory()
-		{
-			synchronized( history ){
-				
-				chatMessage[]	res = new chatMessage[history.size()];
-				
-				history.toArray( res );
-				
-				return( res );
-			}
-		}
-	
-		protected chatParticipant
-		getOrAddParticipant(
-			BuddyPluginBuddy	buddy )
-		{
-			return( addParticipant( buddy ));
-		}
-		
-		public chatParticipant
-		addParticipant(
-			String		pk )
-		{
-			chatParticipant p;
-			
-			BuddyPluginBuddy buddy = plugin.getBuddyFromPublicKey( pk );
-			
-			synchronized( participants ){
-				
-				p = (chatParticipant)participants.get( pk );
-
-				if ( p != null ){
-					
-					return( p );
-				}
-				
-				if ( buddy == null ){
-				
-					p = new chatParticipant( pk );
-					
-				}else{
-					
-					p = new chatParticipant( buddy );
-				}
-				
-				participants.put( pk, p );
-			}
-			
-			Iterator it = listeners.iterator();
-			
-			while( it.hasNext()){
-				
-				try{
-					((BuddyPluginAZ2ChatListener)it.next()).participantAdded( p );
-					
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-			
-			return( p );
-		}
-		
-		public chatParticipant
-		addParticipant(
-			BuddyPluginBuddy	buddy )
-		{
-			return( addParticipant( buddy.getPublicKey()));
-		}
-		
-		public void
-		addParticipants(
-			BuddyPluginBuddy[]		buddies,
-			boolean					inform_others )
-		{
-			for (int i=0;i<buddies.length;i++ ){
-				
-				addParticipant( buddies[i] );
-			}
-			
-			if ( inform_others ){
-			
-				Map	msg = new HashMap();
-				
-				msg.put( "type", new Long( CHAT_MSG_TYPE_PARTICIPANTS_ADDED ));
-				
-				List	added = new ArrayList();
-				
-				msg.put( "p", added );
-				
-				for ( int i=0;i<buddies.length;i++){
-				
-					Map map = new HashMap();
-					
-					map.put( "pk", buddies[i].getPublicKey());
-					
-					added.add( map );
-				}
-				
-				sendMessageBase( msg );
-			}
-		}
-
-		protected chatParticipant
-		getParticipant(
-			BuddyPluginBuddy	b )
-		{
-			String	pk = b.getPublicKey();
-			
-			synchronized( participants ){
-				
-				chatParticipant p = (chatParticipant)participants.get( pk );
-
-				if ( p != null ){
-					
-					return( p );
-				}
-			}
-			
-			return( null );
-		}
-		
-		public chatParticipant[]
-		getParticipants()
-		{
-			synchronized( participants ){
-
-				chatParticipant[]	res = new chatParticipant[participants.size()];
-				
-				participants.values().toArray( res );
-				
-				return( res );
-			}
-		}
-		
-		protected void
-		removeParticipant(
-			chatParticipant		p )
-		{
-			boolean	removed;
-			
-			synchronized( participants ){
-
-				removed = participants.remove( p.getPublicKey()) != null;
-			}
-			
-			if ( removed ){
-				
-				Iterator it = listeners.iterator();
-				
-				while( it.hasNext()){
-					
-					try{
-						((BuddyPluginAZ2ChatListener)it.next()).participantRemoved( p );
-						
-					}catch( Throwable e ){
-						
-						Debug.printStackTrace(e);
-					}
-				}
-			}
-		}
-		
-		public void
-		destroy()
-		{
-			plugin.removeListener( this );
-
-			destroyChat( this );
-		}
-		
-		public void
-		addListener(
-			BuddyPluginAZ2ChatListener		listener )
-		{
-			listeners.add( listener );
-		}
-		
-		public void
-		removeListener(
-			BuddyPluginAZ2ChatListener		listener )
-		{
-			listeners.remove( listener );
-		}
-	}
-	
-	public class
-	chatParticipant
-	{
-		private BuddyPluginBuddy	buddy;
-		private String				public_key;
-		
-		protected
-		chatParticipant(
-			BuddyPluginBuddy		_buddy )
-		{
-			buddy = _buddy;
-		}
-		
-		protected
-		chatParticipant(
-			String			pk  )
-		{
-			public_key = pk;
-		}
-		
-		public boolean
-		isAuthorised()
-		{
-			return( buddy != null );
-		}
-		
-		public BuddyPluginBuddy
-		getBuddy()
-		{
-			return( buddy );
-		}
-		
-		public String
-		getPublicKey()
-		{
-			if ( buddy != null ){
-				
-				return( buddy.getPublicKey());
-			}
-			
-			return( public_key );
-		}
-		
-		public String
-		getName()
-		{
-			if ( buddy != null ){
-				
-				return( buddy.getName());
-			}
-			
-			return( public_key );
-		}
-	}
-	
-	public class
-	chatMessage
-	{
-		private String		nick;
-		private Map			map;
-		
-		protected
-		chatMessage(
-			String			_nick,
-			Map				_map )
-		{
-			nick		= _nick;
-			map			= _map;
-		}
-		
-		public String
-		getNickName()
-		{
-			return( nick );
-		}
-		
-		public Map
-		getMessage()
-		{
-			return( map );
-		}
-	}
-}
+/*
+ * Created on Apr 10, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+import java.security.SecureRandom;
+import java.util.*;
+
+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.RandomUtils;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.ui.UIManagerEvent;
+
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
+public class 
+BuddyPluginAZ2 
+{
+	public static final int RT_AZ2_REQUEST_MESSAGE		= 1;
+	public static final int RT_AZ2_REPLY_MESSAGE		= 2;
+	
+	public static final int RT_AZ2_REQUEST_SEND_TORRENT	= 3;
+	public static final int RT_AZ2_REPLY_SEND_TORRENT	= 4;
+
+	public static final int RT_AZ2_REQUEST_CHAT			= 5;
+	public static final int RT_AZ2_REPLY_CHAT			= 6;
+
+	public static final int RT_AZ2_REQUEST_TRACK		= 7;
+	public static final int RT_AZ2_REPLY_TRACK			= 8;
+
+	public static final int RT_AZ2_REQUEST_RSS			= 9;
+	public static final int RT_AZ2_REPLY_RSS			= 10;
+
+	public static final int CHAT_MSG_TYPE_TEXT						= 1;
+	public static final int CHAT_MSG_TYPE_PARTICIPANTS_ADDED		= 2;
+	public static final int CHAT_MSG_TYPE_PARTICIPANTS_REMOVED		= 3;
+	
+
+	private static final int SEND_TIMEOUT = 2*60*1000;
+	
+	private BuddyPlugin		plugin;
+	
+	private Map				chats 		= new HashMap();
+	
+	private CopyOnWriteList	listeners = new CopyOnWriteList();
+	
+	private CopyOnWriteList	track_listeners = new CopyOnWriteList();
+	
+	protected 
+	BuddyPluginAZ2(
+		BuddyPlugin		_plugin )
+	{
+		plugin	= _plugin;
+		
+		plugin.addRequestListener(
+				new BuddyPluginBuddyRequestListener()
+				{
+					public Map
+					requestReceived(
+						BuddyPluginBuddy	from_buddy,
+						int					subsystem,
+						Map					request )
+					
+						throws BuddyPluginException
+					{
+						if ( subsystem == BuddyPlugin.SUBSYSTEM_AZ2 ){
+							
+							if ( !from_buddy.isAuthorised()){
+							
+								throw( new BuddyPluginException( "Unauthorised" ));
+							}
+						
+							return( processAZ2Request( from_buddy, request ));
+						}
+
+						return( null );
+					}
+					
+					public void
+					pendingMessages(
+						BuddyPluginBuddy[]	from_buddies )
+					{
+					}
+				});
+	}
+	
+	protected Map
+	processAZ2Request(
+		final BuddyPluginBuddy	from_buddy,
+		Map						request )		
+		
+		throws BuddyPluginException
+	{
+		logMessage( "AZ2 request received: " + from_buddy.getString() + " -> " + request );
+			
+		int	type = ((Long)request.get( "type" )).intValue();
+		
+		Map	reply = new HashMap();
+				
+		if ( type == RT_AZ2_REQUEST_MESSAGE ){
+			
+			try{
+				String	msg = new String( (byte[])request.get( "msg" ), "UTF8" );
+			
+				from_buddy.setLastMessageReceived( msg );
+				
+			}catch( Throwable e ){
+				
+			}
+			
+			reply.put( "type", new Long( RT_AZ2_REPLY_MESSAGE ));
+
+		}else if (  type == RT_AZ2_REQUEST_SEND_TORRENT ){
+			
+			try{
+				final Torrent	torrent = plugin.getPluginInterface().getTorrentManager().createFromBEncodedData((byte[])request.get( "torrent" ));
+			
+				new AEThread2( "torrentAdder", true )
+				{
+					public void
+					run()
+					{
+						PluginInterface pi = plugin.getPluginInterface();
+						
+						String msg = pi.getUtilities().getLocaleUtilities().getLocalisedMessageText(
+								"azbuddy.addtorrent.msg", 
+								new String[]{ from_buddy.getName(), torrent.getName() });
+						
+						long res = pi.getUIManager().showMessageBox(
+										"azbuddy.addtorrent.title",
+										"!" + msg + "!",
+										UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+						
+						if ( res == UIManagerEvent.MT_YES ){
+						
+							pi.getUIManager().openTorrent( torrent );
+						}
+					}
+				}.start();
+				
+				reply.put( "type", new Long( RT_AZ2_REPLY_SEND_TORRENT ));
+				
+			}catch( Throwable e ){
+				
+				throw( new BuddyPluginException( "Torrent receive failed " + type ));
+			}
+		}else if (  type == RT_AZ2_REQUEST_CHAT ){
+			
+			Map msg = (Map)request.get( "msg" );
+			
+			String	id = new String((byte[])msg.get( "id" ));
+			
+			chatInstance	chat;
+			boolean			new_chat = false;
+			
+			synchronized( chats ){
+				
+				 chat = (chatInstance)chats.get( id );
+				 
+				 if ( chat == null ){
+					 
+					 if ( chats.size() > 32 ){
+						 
+						 throw( new BuddyPluginException( "Too many chats" ));
+					 }
+					 
+					 chat = new chatInstance( id );
+					 
+					 chats.put( id, chat );
+					 
+					 new_chat = true;
+				 }
+			}
+			
+			if ( new_chat ){
+			
+				informCreated( chat );
+			}
+			
+			chat.addParticipant( from_buddy );
+			
+			chat.process( from_buddy, msg );
+						
+			reply.put( "type", new Long( RT_AZ2_REPLY_CHAT ));
+						
+		}else if (  type == RT_AZ2_REQUEST_TRACK ){
+			
+			Map msg = (Map)request.get( "msg" );
+
+			Iterator it = track_listeners.iterator();
+			
+			boolean	ok = false;
+			
+			while( it.hasNext()){
+				
+				try{
+			
+					Map res = ((BuddyPluginAZ2TrackerListener)it.next()).messageReceived( from_buddy, msg );
+					
+					if ( res != null ){
+						
+						reply.put( "msg", res );
+						reply.put( "type", new Long( RT_AZ2_REPLY_TRACK ));
+
+						ok = true;
+						
+						break;
+					}
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+			
+			if ( !ok ){
+			
+				throw( new BuddyPluginException( "Unhandled request type " + type ));
+			}
+		}else if (  type == RT_AZ2_REQUEST_RSS ){
+				
+			try{
+				Map<String,Object> res = new HashMap<String, Object>();
+
+				reply.put( "msg", res );
+				reply.put( "type", new Long( RT_AZ2_REPLY_RSS ));
+
+				Map msg = (Map)request.get( "msg" );
+
+				String category = new String((byte[])msg.get( "cat"), "UTF-8" );
+				
+				byte[] hash	= (byte[])msg.get( "hash" );
+				
+				if ( hash == null ){
+					
+					byte[]	if_mod 	= (byte[])msg.get( "if_mod" );
+					
+					BuddyPlugin.feedDetails feed = plugin.getRSS( from_buddy, category, if_mod==null?null:new String( if_mod, "UTF-8" ));
+					
+					res.put( "rss", feed.getContent());
+					
+					res.put( "last_mod", feed.getLastModified());
+					
+				}else{
+					
+					res.put( "torrent", plugin.getRSSTorrent( from_buddy, category, hash ));
+				}
+			}catch( BuddyPluginException e  ){
+				
+				throw( e );
+				
+			}catch( Throwable e ){
+				
+				throw( new BuddyPluginException( "Failed to handle rss", e ));
+			}
+		}else{
+			
+			throw( new BuddyPluginException( "Unrecognised request type " + type ));
+		}
+		
+		logMessage( "AZ2 reply sent: " + from_buddy.getString() + " <- " + reply );
+
+		return( reply );
+	}
+		
+	public chatInstance
+	createChat(
+		BuddyPluginBuddy[]		buddies )
+	{
+		byte[]	id_bytes = new byte[20];
+		
+		RandomUtils.SECURE_RANDOM.nextBytes( id_bytes );
+		
+		String	id = Base32.encode( id_bytes );
+		
+		chatInstance	chat;
+		
+		synchronized( chats ){
+
+			chat = new chatInstance( id );
+			
+			chats.put( id, chat );
+		}
+		
+		logMessage( "Chat " + chat.getID() + " created" );
+
+		informCreated( chat );
+					
+		chat.addParticipants( buddies, true );
+		
+		return( chat );
+	}
+	
+	protected void
+	destroyChat(
+		chatInstance	chat )
+	{
+		synchronized( chats ){
+
+			chats.remove( chat.getID());
+		}
+		
+		logMessage( "Chat " + chat.getID() + " destroyed" );
+		
+		informDestroyed( chat );
+	}
+	
+	protected void
+	informCreated(
+		chatInstance		chat )
+	{
+		Iterator	it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			((BuddyPluginAZ2Listener)it.next()).chatCreated( chat );
+		}
+	}
+	
+	protected void
+	informDestroyed(
+		chatInstance		chat )
+	{
+		Iterator	it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			((BuddyPluginAZ2Listener)it.next()).chatDestroyed( chat );
+		}
+	}
+	
+	public void
+	sendAZ2Message(
+		BuddyPluginBuddy	buddy,
+		String				msg )
+	{
+		try{
+			Map	request = new HashMap();
+			
+			request.put( "type", new Long( RT_AZ2_REQUEST_MESSAGE ));
+			request.put( "msg", msg.getBytes());
+			
+			sendMessage( buddy, request );
+				
+		}catch( Throwable e ){
+			
+			logMessageAndPopup( "Send message failed", e );
+		}
+	}
+	
+	protected void
+	sendAZ2Chat(
+		BuddyPluginBuddy	buddy,
+		Map					msg )
+	{
+		try{
+			Map	request = new HashMap();
+			
+			request.put( "type", new Long( RT_AZ2_REQUEST_CHAT ));
+			request.put( "msg", msg );
+			
+			sendMessage( buddy, request );
+				
+		}catch( Throwable e ){
+			
+			logMessageAndPopup( "Send message failed", e );
+		}
+	}
+	
+	public void
+	sendAZ2Torrent(
+		Torrent				torrent,
+		BuddyPluginBuddy	buddy )
+	{
+		try{
+			
+			Map	request = new HashMap();
+			
+			request.put( "type", new Long( RT_AZ2_REQUEST_SEND_TORRENT ));
+			request.put( "torrent", torrent.writeToBEncodedData());
+			
+			sendMessage( buddy, request );
+			
+		}catch( Throwable e ){
+			
+			logMessageAndPopup( "Send torrent failed", e );
+		}
+	}
+	
+	public void
+	sendAZ2TrackerMessage(
+		BuddyPluginBuddy						buddy,
+		Map										msg,
+		final BuddyPluginAZ2TrackerListener		listener )
+	{
+		logMessage( "AZ2 request sent: " + buddy.getString() + " <- " + msg );
+
+		try{
+			Map	request = new HashMap();
+			
+			request.put( "type", new Long( RT_AZ2_REQUEST_TRACK ));
+			request.put( "msg", msg );
+			
+			buddy.sendMessage(
+				BuddyPlugin.SUBSYSTEM_AZ2,
+				request,
+				SEND_TIMEOUT,
+				new BuddyPluginBuddyReplyListener()
+				{
+					public void
+					replyReceived(
+						BuddyPluginBuddy		from_buddy,
+						Map						reply )
+					{
+						int type = ((Long)reply.get( "type")).intValue();
+						
+						if ( type != RT_AZ2_REPLY_TRACK ){
+							
+							sendFailed( from_buddy, new BuddyPluginException( "Mismatched reply type" ));
+						}
+						
+						listener.messageReceived( from_buddy, (Map)reply.get( "msg" ));
+					}
+					
+					public void
+					sendFailed(
+						BuddyPluginBuddy		to_buddy,
+						BuddyPluginException	cause )
+					{
+						listener.messageFailed( to_buddy, cause );
+					}
+				});
+				
+		}catch( Throwable e ){
+			
+			logMessageAndPopup( "Send message failed", e );
+		}
+	}
+	
+	public void
+	sendAZ2RSSMessage(
+		BuddyPluginBuddy						buddy,
+		Map										msg,
+		final BuddyPluginAZ2TrackerListener		listener )
+	{
+		logMessage( "AZ2 request sent: " + buddy.getString() + " <- " + msg );
+
+		try{
+			Map	request = new HashMap();
+			
+			request.put( "type", new Long( RT_AZ2_REQUEST_RSS ));
+			request.put( "msg", msg );
+			
+			buddy.sendMessage(
+				BuddyPlugin.SUBSYSTEM_AZ2,
+				request,
+				SEND_TIMEOUT,
+				new BuddyPluginBuddyReplyListener()
+				{
+					public void
+					replyReceived(
+						BuddyPluginBuddy		from_buddy,
+						Map						reply )
+					{
+						int type = ((Long)reply.get( "type")).intValue();
+						
+						if ( type != RT_AZ2_REPLY_RSS ){
+							
+							sendFailed( from_buddy, new BuddyPluginException( "Mismatched reply type" ));
+						}
+						
+						listener.messageReceived( from_buddy, (Map)reply.get( "msg" ));
+					}
+					
+					public void
+					sendFailed(
+						BuddyPluginBuddy		to_buddy,
+						BuddyPluginException	cause )
+					{
+						listener.messageFailed( to_buddy, cause );
+					}
+				});
+				
+		}catch( Throwable e ){
+			
+			logMessage( "Send message failed", e );
+		}
+	}
+	
+	protected void
+	sendMessage(
+		BuddyPluginBuddy	buddy,
+		Map					request )
+	
+		throws BuddyPluginException
+	{
+		logMessage( "AZ2 request sent: " + buddy.getString() + " <- " + request );
+
+		buddy.getMessageHandler().queueMessage( 
+				BuddyPlugin.SUBSYSTEM_AZ2,
+				request,
+				SEND_TIMEOUT );		
+	}
+	
+	public void
+	addListener(
+		BuddyPluginAZ2Listener		listener )
+	{
+		listeners.add( listener );
+	}
+	
+	public void
+	removeListener(
+		BuddyPluginAZ2Listener		listener )
+	{
+		listeners.remove( listener );
+	}
+	
+	public void
+	addTrackerListener(
+		BuddyPluginAZ2TrackerListener		listener )
+	{
+		track_listeners.add( listener );
+	}
+	
+	public void
+	removeTrackerListener(
+		BuddyPluginAZ2TrackerListener		listener )
+	{
+		track_listeners.remove( listener );
+	}
+	
+	protected void
+	logMessageAndPopup(
+		String		str,
+		Throwable	e )
+	{
+		logMessageAndPopup( str + ": " + Debug.getNestedExceptionMessage(e));
+	}
+	
+	protected void
+	logMessageAndPopup(
+		String		str )
+	{
+		logMessage( str );
+		
+		plugin.getPluginInterface().getUIManager().showMessageBox(
+			"azbuddy.msglog.title", "!" + str + "!", UIManagerEvent.MT_OK );
+	}
+	
+	protected void
+	logMessage(
+		String		str )
+	{
+		plugin.logMessage( str );
+	}
+	
+	protected void
+	logMessage(
+		String		str,
+		Throwable 	e )
+	{
+		plugin.logMessage( str + ": " + Debug.getNestedExceptionMessage(e));
+	}
+	
+	public class
+	chatInstance
+		extends BuddyPluginAdapter
+	{
+		private String		id;
+		
+		private Map				participants 	= new HashMap();
+		private CopyOnWriteList	listeners 		= new CopyOnWriteList();
+		
+		private List			history			= new ArrayList();
+		
+		protected
+		chatInstance(
+			String		_id )
+		{
+			id		= _id;
+			
+			plugin.addListener( this );
+		}
+		
+		public String
+		getID()
+		{
+			return( id );
+		}
+		
+		public void
+		buddyAdded(
+			BuddyPluginBuddy	buddy )
+		{
+			buddyChanged( buddy );
+		}
+		
+		public void
+		buddyRemoved(
+			BuddyPluginBuddy	buddy )
+		{
+			chatParticipant p = getParticipant( buddy );
+			
+			if ( p != null ){
+				
+				Iterator it = listeners.iterator();
+				
+				while( it.hasNext()){
+					
+					try{
+						((BuddyPluginAZ2ChatListener)it.next()).participantRemoved( p );
+						
+					}catch( Throwable e ){
+						
+						Debug.printStackTrace(e);
+					}
+				}
+			}
+		}
+
+		public void
+		buddyChanged(
+			BuddyPluginBuddy	buddy )
+		{
+			chatParticipant p = getParticipant( buddy );
+			
+			if ( p != null ){
+			
+				Iterator it = listeners.iterator();
+			
+				while( it.hasNext()){
+					
+					try{
+						((BuddyPluginAZ2ChatListener)it.next()).participantChanged( p );
+						
+					}catch( Throwable e ){
+						
+						Debug.printStackTrace(e);
+					}
+				}
+			}
+		}
+		
+		protected void
+		process(
+			BuddyPluginBuddy	from_buddy,
+			Map					msg )
+		{
+			chatParticipant p = getOrAddParticipant( from_buddy );
+			
+			int	type = ((Long)msg.get( "type")).intValue();
+			
+			if ( type == CHAT_MSG_TYPE_TEXT ){
+		
+				Iterator it = listeners.iterator();
+				
+				synchronized( history ){
+				
+					history.add( new chatMessage( p.getName(), msg ));
+					
+					if ( history.size() > 128 ){
+						
+						history.remove(0);
+					}
+				}
+				
+				while( it.hasNext()){
+					
+					try{
+						((BuddyPluginAZ2ChatListener)it.next()).messageReceived( p, msg );
+						
+					}catch( Throwable e ){
+						
+						Debug.printStackTrace(e);
+					}
+				}
+			}else if ( type == CHAT_MSG_TYPE_PARTICIPANTS_ADDED ){
+				
+				List added = (List)msg.get( "p" );
+				
+				for (int i=0;i<added.size();i++){
+					
+					Map	participant = (Map)added.get(i);
+					
+					String pk = new String((byte[])participant.get( "pk" ));
+					
+					if ( !pk.equals( plugin.getPublicKey())){
+					
+						addParticipant( pk );
+					}
+				}
+			}
+		}
+		
+		public void
+		sendMessage(
+			Map		msg )
+		{
+			msg.put( "type", new Long( CHAT_MSG_TYPE_TEXT ));
+			
+			sendMessageBase( msg );
+		}
+		
+		protected void
+		sendMessageBase(
+			Map		msg )
+		{
+			Map	ps;
+			
+			synchronized( participants ){
+				
+				ps = new HashMap( participants );
+			}
+			
+			msg.put( "id", id );
+			
+			Iterator it = ps.values().iterator();
+			
+			while( it.hasNext()){
+				
+				chatParticipant participant = (chatParticipant)it.next();
+				
+				if ( participant.isAuthorised()){
+					
+					sendAZ2Chat( participant.getBuddy(), msg );
+				}
+			}
+		}
+		
+		public chatMessage[]
+		getHistory()
+		{
+			synchronized( history ){
+				
+				chatMessage[]	res = new chatMessage[history.size()];
+				
+				history.toArray( res );
+				
+				return( res );
+			}
+		}
+	
+		protected chatParticipant
+		getOrAddParticipant(
+			BuddyPluginBuddy	buddy )
+		{
+			return( addParticipant( buddy ));
+		}
+		
+		public chatParticipant
+		addParticipant(
+			String		pk )
+		{
+			chatParticipant p;
+			
+			BuddyPluginBuddy buddy = plugin.getBuddyFromPublicKey( pk );
+			
+			synchronized( participants ){
+				
+				p = (chatParticipant)participants.get( pk );
+
+				if ( p != null ){
+					
+					return( p );
+				}
+				
+				if ( buddy == null ){
+				
+					p = new chatParticipant( pk );
+					
+				}else{
+					
+					p = new chatParticipant( buddy );
+				}
+				
+				participants.put( pk, p );
+			}
+			
+			Iterator it = listeners.iterator();
+			
+			while( it.hasNext()){
+				
+				try{
+					((BuddyPluginAZ2ChatListener)it.next()).participantAdded( p );
+					
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+			
+			return( p );
+		}
+		
+		public chatParticipant
+		addParticipant(
+			BuddyPluginBuddy	buddy )
+		{
+			return( addParticipant( buddy.getPublicKey()));
+		}
+		
+		public void
+		addParticipants(
+			BuddyPluginBuddy[]		buddies,
+			boolean					inform_others )
+		{
+			for (int i=0;i<buddies.length;i++ ){
+				
+				addParticipant( buddies[i] );
+			}
+			
+			if ( inform_others ){
+			
+				Map	msg = new HashMap();
+				
+				msg.put( "type", new Long( CHAT_MSG_TYPE_PARTICIPANTS_ADDED ));
+				
+				List	added = new ArrayList();
+				
+				msg.put( "p", added );
+				
+				for ( int i=0;i<buddies.length;i++){
+				
+					Map map = new HashMap();
+					
+					map.put( "pk", buddies[i].getPublicKey());
+					
+					added.add( map );
+				}
+				
+				sendMessageBase( msg );
+			}
+		}
+
+		protected chatParticipant
+		getParticipant(
+			BuddyPluginBuddy	b )
+		{
+			String	pk = b.getPublicKey();
+			
+			synchronized( participants ){
+				
+				chatParticipant p = (chatParticipant)participants.get( pk );
+
+				if ( p != null ){
+					
+					return( p );
+				}
+			}
+			
+			return( null );
+		}
+		
+		public chatParticipant[]
+		getParticipants()
+		{
+			synchronized( participants ){
+
+				chatParticipant[]	res = new chatParticipant[participants.size()];
+				
+				participants.values().toArray( res );
+				
+				return( res );
+			}
+		}
+		
+		protected void
+		removeParticipant(
+			chatParticipant		p )
+		{
+			boolean	removed;
+			
+			synchronized( participants ){
+
+				removed = participants.remove( p.getPublicKey()) != null;
+			}
+			
+			if ( removed ){
+				
+				Iterator it = listeners.iterator();
+				
+				while( it.hasNext()){
+					
+					try{
+						((BuddyPluginAZ2ChatListener)it.next()).participantRemoved( p );
+						
+					}catch( Throwable e ){
+						
+						Debug.printStackTrace(e);
+					}
+				}
+			}
+		}
+		
+		public void
+		destroy()
+		{
+			plugin.removeListener( this );
+
+			destroyChat( this );
+		}
+		
+		public void
+		addListener(
+			BuddyPluginAZ2ChatListener		listener )
+		{
+			listeners.add( listener );
+		}
+		
+		public void
+		removeListener(
+			BuddyPluginAZ2ChatListener		listener )
+		{
+			listeners.remove( listener );
+		}
+	}
+	
+	public class
+	chatParticipant
+	{
+		private BuddyPluginBuddy	buddy;
+		private String				public_key;
+		
+		protected
+		chatParticipant(
+			BuddyPluginBuddy		_buddy )
+		{
+			buddy = _buddy;
+		}
+		
+		protected
+		chatParticipant(
+			String			pk  )
+		{
+			public_key = pk;
+		}
+		
+		public boolean
+		isAuthorised()
+		{
+			return( buddy != null );
+		}
+		
+		public BuddyPluginBuddy
+		getBuddy()
+		{
+			return( buddy );
+		}
+		
+		public String
+		getPublicKey()
+		{
+			if ( buddy != null ){
+				
+				return( buddy.getPublicKey());
+			}
+			
+			return( public_key );
+		}
+		
+		public String
+		getName()
+		{
+			if ( buddy != null ){
+				
+				return( buddy.getName());
+			}
+			
+			return( public_key );
+		}
+	}
+	
+	public class
+	chatMessage
+	{
+		private String		nick;
+		private Map			map;
+		
+		protected
+		chatMessage(
+			String			_nick,
+			Map				_map )
+		{
+			nick		= _nick;
+			map			= _map;
+		}
+		
+		public String
+		getNickName()
+		{
+			return( nick );
+		}
+		
+		public Map
+		getMessage()
+		{
+			return( map );
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2ChatListener.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2ChatListener.java
index 2b544a8..43e2944 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2ChatListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2ChatListener.java
@@ -1,45 +1,44 @@
-/*
- * Created on Apr 29, 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.plugins.net.buddy;
-
-import java.util.Map;
-
-public interface 
-BuddyPluginAZ2ChatListener 
-{
-	public void
-	messageReceived(
-		BuddyPluginAZ2.chatParticipant	participant,
-		Map								msg );
-	
-	public void
-	participantAdded(
-		BuddyPluginAZ2.chatParticipant	participant );
-	
-	public void
-	participantChanged(
-		BuddyPluginAZ2.chatParticipant	participant );
-	
-	public void
-	participantRemoved(
-		BuddyPluginAZ2.chatParticipant	participant );
-}
+/*
+ * Created on Apr 29, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+import java.util.Map;
+
+public interface 
+BuddyPluginAZ2ChatListener 
+{
+	public void
+	messageReceived(
+		BuddyPluginAZ2.chatParticipant	participant,
+		Map								msg );
+	
+	public void
+	participantAdded(
+		BuddyPluginAZ2.chatParticipant	participant );
+	
+	public void
+	participantChanged(
+		BuddyPluginAZ2.chatParticipant	participant );
+	
+	public void
+	participantRemoved(
+		BuddyPluginAZ2.chatParticipant	participant );
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2Listener.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2Listener.java
index 56d778b..1e5dd1f 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2Listener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2Listener.java
@@ -1,35 +1,34 @@
-/*
- * Created on Apr 26, 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.plugins.net.buddy;
-
-
-public interface 
-BuddyPluginAZ2Listener 
-{
-	public void
-	chatCreated(
-		BuddyPluginAZ2.chatInstance		chat );
-	
-	public void
-	chatDestroyed(
-		BuddyPluginAZ2.chatInstance		chat );
-}
+/*
+ * Created on Apr 26, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+
+public interface 
+BuddyPluginAZ2Listener 
+{
+	public void
+	chatCreated(
+		BuddyPluginAZ2.chatInstance		chat );
+	
+	public void
+	chatDestroyed(
+		BuddyPluginAZ2.chatInstance		chat );
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2TrackerListener.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2TrackerListener.java
index c8e0726..8b873f8 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2TrackerListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAZ2TrackerListener.java
@@ -1,38 +1,37 @@
-/*
- * Created on May 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.plugins.net.buddy;
-
-import java.util.*;
-
-public interface 
-BuddyPluginAZ2TrackerListener 
-{
-	public Map
-	messageReceived(
-		BuddyPluginBuddy	buddy,
-		Map					message );
-	
-	public void
-	messageFailed(
-		BuddyPluginBuddy	buddy,
-		Throwable			cause );
-}
+/*
+ * Created on May 27, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+import java.util.*;
+
+public interface 
+BuddyPluginAZ2TrackerListener 
+{
+	public Map
+	messageReceived(
+		BuddyPluginBuddy	buddy,
+		Map					message );
+	
+	public void
+	messageFailed(
+		BuddyPluginBuddy	buddy,
+		Throwable			cause );
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAdapter.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAdapter.java
index df9fdc0..0e42e83 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginAdapter.java
@@ -1,64 +1,68 @@
-/*
- * Created on Jun 3, 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.plugins.net.buddy;
-
-public class 
-BuddyPluginAdapter 
-	implements BuddyPluginListener
-{
-	public void
-	initialised(
-		boolean		available )
-	{
-	}
-	
-	public void
-	buddyAdded(
-		BuddyPluginBuddy	buddy )
-	{
-	}
-	
-	public void
-	buddyRemoved(
-		BuddyPluginBuddy	buddy )
-	{
-	}
-
-	public void
-	buddyChanged(
-		BuddyPluginBuddy	buddy )
-	{
-	}
-	
-	public void
-	messageLogged(
-		String		str,
-		boolean		is_error )
-	{
-	}
-	
-	public void
-	enabledStateChanged(
-		boolean enabled)
-	{
-	}
-}
+/*
+ * Created on Jun 3, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+public class 
+BuddyPluginAdapter 
+	implements BuddyPluginListener
+{
+	public void
+	initialised(
+		boolean		available )
+	{
+	}
+	
+	public void
+	buddyAdded(
+		BuddyPluginBuddy	buddy )
+	{
+	}
+	
+	public void
+	buddyRemoved(
+		BuddyPluginBuddy	buddy )
+	{
+	}
+
+	public void
+	buddyChanged(
+		BuddyPluginBuddy	buddy )
+	{
+	}
+	
+	public void
+	messageLogged(
+		String		str,
+		boolean		is_error )
+	{
+	}
+	
+	public void
+	enabledStateChanged(
+		boolean enabled)
+	{
+	}
+	
+	public void 
+	updated() 
+	{
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBeta.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBeta.java
new file mode 100644
index 0000000..cc32bea
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBeta.java
@@ -0,0 +1,5524 @@
+/*
+ * Created on Oct 13, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.plugins.net.buddy;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.net.InetSocketAddress;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.AEDiagnostics;
+import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+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.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.DisplayFormatters;
+import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.core3.util.IndentWriter;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.core3.util.TimeFormatter;
+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.core3.xml.util.XUXmlWriter;
+import org.gudy.azureus2.plugins.PluginEvent;
+import org.gudy.azureus2.plugins.PluginEventListener;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ipc.IPCException;
+import org.gudy.azureus2.plugins.sharing.ShareManager;
+import org.gudy.azureus2.plugins.sharing.ShareManagerListener;
+import org.gudy.azureus2.plugins.sharing.ShareResource;
+import org.gudy.azureus2.plugins.sharing.ShareResourceDir;
+import org.gudy.azureus2.plugins.sharing.ShareResourceFile;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.ui.config.BooleanParameter;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+
+import com.aelitis.azureus.core.proxy.impl.AEPluginProxyHandler;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
+public class
+BuddyPluginBeta 
+{
+	public static final boolean DEBUG_ENABLED			= System.getProperty( "az.chat.buddy.debug", "0" ).equals( "1" );
+	public static final boolean BETA_CHAN_ENABLED		= System.getProperty( "az.chat.buddy.beta.chan", "1" ).equals( "1" );
+
+	public static final String	BETA_CHAT_KEY = 	"test:beta:chat";
+	
+	public static final int PRIVATE_CHAT_DISABLED			= 1;
+	public static final int PRIVATE_CHAT_PINNED_ONLY		= 2;
+	public static final int PRIVATE_CHAT_ENABLED			= 3;
+	
+	private static final String	FLAGS_MSG_STATUS_KEY		= "s";
+	private static final int 	FLAGS_MSG_STATUS_CHAT_NONE	= 0;		// def
+	private static final int 	FLAGS_MSG_STATUS_CHAT_QUIT	= 1;
+	
+	public static final String 	FLAGS_MSG_ORIGIN_KEY 		= "o";
+	public static final int 	FLAGS_MSG_ORIGIN_USER 		= 0;		// def
+	public static final int 	FLAGS_MSG_ORIGIN_RATINGS 	= 1;
+	public static final int 	FLAGS_MSG_ORIGIN_SEED_REQ 	= 2;
+	
+	public static final String 	FLAGS_MSG_FLASH_OVERRIDE	= "f";
+	public static final int		FLAGS_MSG_FLASH_NO 			= 0;		// def
+	public static final int		FLAGS_MSG_FLASH_YES 		= 1;
+
+	
+	private BuddyPlugin			plugin;
+	private PluginInterface		plugin_interface;
+	private BooleanParameter	enabled;
+	
+	private AsyncDispatcher		dispatcher = new AsyncDispatcher( "BuddyPluginBeta" );
+	
+	private Map<String,ChatInstance>		chat_instances_map 	= new HashMap<String, BuddyPluginBeta.ChatInstance>();
+	private CopyOnWriteList<ChatInstance>	chat_instances_list	= new CopyOnWriteList<BuddyPluginBeta.ChatInstance>();
+	
+	private PluginInterface azmsgsync_pi;
+
+	private TimerEventPeriodic		timer;
+	
+	private String					shared_public_nickname;
+	private String					shared_anon_nickname;
+	private int						max_chat_ui_lines;
+	private int						max_chat_ui_kb;
+	private boolean					standalone_windows;
+	private boolean					hide_ratings;
+	
+	private int						private_chat_state;
+	private boolean					shared_anon_endpoint;
+	private boolean					sound_enabled;
+	private String					sound_file;
+		
+	private Map<String,Map<String,Object>>		opts_map;
+	
+	private CopyOnWriteList<FTUXStateChangeListener>		ftux_listeners = new CopyOnWriteList<FTUXStateChangeListener>();
+	
+	private boolean	ftux_accepted = false;
+	
+	private CopyOnWriteList<ChatManagerListener>		listeners = new CopyOnWriteList<ChatManagerListener>();
+	
+	private AtomicInteger		private_chat_id = new AtomicInteger();
+	
+	private AESemaphore	init_complete = new AESemaphore( "bpb:init" );
+	
+	protected
+	BuddyPluginBeta(
+		PluginInterface		_pi,
+		BuddyPlugin			_plugin,
+
+		BooleanParameter	_enabled )
+	{
+		plugin_interface 	= _pi;
+		plugin				= _plugin;
+		enabled				= _enabled;
+		
+		ftux_accepted 	= COConfigurationManager.getBooleanParameter( "azbuddy.dchat.ftux.accepted", false );
+
+		shared_public_nickname 	= COConfigurationManager.getStringParameter( "azbuddy.chat.shared_nick", "" );
+		shared_anon_nickname 	= COConfigurationManager.getStringParameter( "azbuddy.chat.shared_anon_nick", "" );
+		private_chat_state	 	= COConfigurationManager.getIntParameter( "azbuddy.chat.private_chat_state", PRIVATE_CHAT_ENABLED );
+		
+		shared_anon_endpoint	= COConfigurationManager.getBooleanParameter( "azbuddy.chat.share_i2p_endpoint", true );
+		sound_enabled			= COConfigurationManager.getBooleanParameter( "azbuddy.chat.notif.sound.enable", false );
+		sound_file			 	= COConfigurationManager.getStringParameter( "azbuddy.chat.notif.sound.file", "" );
+	
+		opts_map				= COConfigurationManager.getMapParameter( "azbuddy.dchat.optsmap", new HashMap<String,Map<String,Object>>());	// should migrate others to use this...
+
+		
+			// migration starts 
+		
+		Map<String,Long> favourite_map	= COConfigurationManager.getMapParameter( "azbuddy.dchat.favemap", new HashMap<String,Long>());
+		
+		if ( favourite_map.size() > 0 ){
+		
+			migrateBooleans( favourite_map, "fave" );
+		
+			COConfigurationManager.removeParameter( "azbuddy.dchat.favemap" );
+		}
+		
+		Map<String,Long> save_messages_map		= COConfigurationManager.getMapParameter( "azbuddy.dchat.savemsgmap", new HashMap<String,Long>());
+		
+		if ( save_messages_map.size() > 0 ){
+			
+			migrateBooleans( save_messages_map, "save" );
+		
+			COConfigurationManager.removeParameter( "azbuddy.dchat.savemsgmap" );
+		}
+		
+		Map<String,Long> log_messages_map		= COConfigurationManager.getMapParameter( "azbuddy.dchat.logmsgmap", new HashMap<String,Long>());
+		
+		if ( log_messages_map.size() > 0 ){
+			
+			migrateBooleans( log_messages_map, "log" );
+		
+			COConfigurationManager.removeParameter( "azbuddy.dchat.logmsgmap" );
+		}
+		
+		Map<String,byte[]> lmi_map				= COConfigurationManager.getMapParameter( "azbuddy.dchat.lmimap", new HashMap<String,byte[]>());
+			
+		if ( lmi_map.size() > 0 ){
+			
+			migrateByteArrays( lmi_map, "lmi" );
+		
+			COConfigurationManager.removeParameter( "azbuddy.dchat.lmimap" );
+		}
+		
+		// migration ends
+		
+		max_chat_ui_lines		= COConfigurationManager.getIntParameter( "azbuddy.dchat.ui.max.lines", 250 );
+		max_chat_ui_kb			= COConfigurationManager.getIntParameter( "azbuddy.dchat.ui.max.char.kb", 10 );
+		standalone_windows		= COConfigurationManager.getBooleanParameter( "azbuddy.dchat.ui.standalone.windows", false );
+		hide_ratings			= COConfigurationManager.getBooleanParameter( "azbuddy.dchat.ui.hide.ratings", false );
+		
+		SimpleTimer.addPeriodicEvent(
+			"BPB:checkfave",
+			30*1000,
+			new TimerEventPerformer() 
+			{		
+				public void 
+				perform(
+					TimerEvent event ) 
+				{
+					checkFavourites();
+				}
+			});
+		
+		AEDiagnostics.addEvidenceGenerator(
+			new AEDiagnosticsEvidenceGenerator() 
+			{		
+				public void 
+				generate(
+					IndentWriter writer ) 
+				{
+					writer.println( "Chat (active=" + chat_instances_list.size() + ")" );
+					
+					try{
+						writer.indent();	
+
+						for ( ChatInstance inst: chat_instances_list ){
+							
+							writer.println( "users=" + inst.getEstimatedNodes() + ", msg=" + inst.getMessageCount( true ) + ", status=" + inst.getStatus());
+						}
+					}finally{
+						
+						writer.exdent();
+					}
+				}
+			});
+	}
+	
+	public boolean 
+	isAvailable()
+	{
+		return( plugin_interface.getPluginManager().getPluginInterfaceByID( "azmsgsync", true ) != null );
+	}
+	
+	public boolean
+	isInitialised()
+	{
+		return( init_complete.isReleasedForever());
+	}
+	
+	public int
+	getMaxUILines()
+	{
+		return( max_chat_ui_lines );
+	}
+	
+	public void
+	setMaxUILines(
+		int		num )
+	{
+		max_chat_ui_lines		= num;
+		
+		COConfigurationManager.setParameter( "azbuddy.dchat.ui.max.lines", num );
+
+		COConfigurationManager.setDirty();
+	}
+	
+	public int
+	getMaxUICharsKB()
+	{
+		return( max_chat_ui_kb );
+	}
+	
+	public void
+	setMaxUICharsKB(
+		int		num )
+	{
+		max_chat_ui_kb			= num;
+		
+		COConfigurationManager.setParameter( "azbuddy.dchat.ui.max.char.kb", num );
+
+		COConfigurationManager.setDirty();
+	}
+	
+	public boolean
+	getStandAloneWindows()
+	{
+		return( standalone_windows );
+	}
+	
+	public void
+	setStandAloneWindows(
+		boolean		b )
+	{
+		standalone_windows			= b;
+		
+		COConfigurationManager.setParameter( "azbuddy.dchat.ui.standalone.windows", b );
+
+		COConfigurationManager.setDirty();
+	}
+
+	public boolean
+	getHideRatings()
+	{
+		return( hide_ratings );
+	}
+	
+	public void
+	setHideRatings(
+		boolean		b )
+	{
+		hide_ratings			= b;
+		
+		COConfigurationManager.setParameter( "azbuddy.dchat.ui.hide.ratings", b );
+
+		COConfigurationManager.setDirty();
+	}
+	
+	public boolean
+	getFavourite(
+		String		net,
+		String		key )
+	{
+		return( getBooleanOption( net, key, "fave", false ));
+	}
+	
+	public void
+	setFavourite(
+		String		net,
+		String		key,
+		boolean		b )
+	{
+		setBooleanOption( net, key, "fave", b );
+			
+		checkFavourites();
+	}
+	
+	public List<String[]>
+	getFavourites()
+	{
+		synchronized( opts_map ){
+
+			List<String[]>	result = new ArrayList<String[]>();
+
+			for ( Map.Entry<String,Map<String,Object>> entry: opts_map.entrySet()){
+						
+				String 				net_key = entry.getKey();
+				Map<String,Object>	map	= entry.getValue();
+				
+				Long	value = (Long)map.get( "fave" );
+				
+				if ( value != null && value == 1 ){
+					
+					String[] bits = net_key.split( ":", 2 );
+					
+					String network 	= AENetworkClassifier.internalise( bits[0] );
+					String key		= decodeKey( bits[1] );
+					
+					result.add( new String[]{ network, key });
+				}
+			}
+			
+			return( result );
+		}
+	}
+	
+	private void
+	checkFavourites()
+	{
+		dispatcher.dispatch(
+			new AERunnable() 
+			{	
+				@Override
+				public void 
+				runSupport() 
+				{
+					try{
+						List<String[]>	faves = getFavourites();
+						
+						Set<String>	set = new HashSet<String>();
+						
+						for ( String[] fave: faves ){
+							
+							String	net = fave[0];
+							String	key	= fave[1];
+							
+							set.add( net + ":" + key );
+							
+							ChatInstance chat = peekChatInstance( net, key, false );
+	
+							if ( chat == null || !chat.getKeepAlive()){
+							
+									// get a reference to the chat
+								
+								try{
+									chat = getChat( net, key );
+								
+									chat.setKeepAlive( true );
+									
+								}catch( Throwable e ){
+									
+								}
+							}
+						}
+						
+						for ( ChatInstance chat: chat_instances_list ){
+							
+							if ( chat.getKeepAlive()){
+								
+								String	net = chat.getNetwork();
+								String	key = chat.getKey();
+								
+								if ( !set.contains( net + ":" + key )){
+									
+									if ( 	net == AENetworkClassifier.AT_PUBLIC &&
+											key.equals(BETA_CHAT_KEY)){
+										
+										// leave
+										
+									}else{
+										
+											// release our reference
+										
+										chat.setKeepAlive( false );
+										
+										chat.destroy();
+									}
+								}
+							}
+						}
+					}finally{
+						
+						init_complete.releaseForever();
+					}
+				}
+			});
+	}
+	
+/*
+ * 			String chat_key_base = "azbuddy.chat." + getNetAndKey();
+			
+			String shared_key 	= chat_key_base + ".shared";
+			String nick_key 	= chat_key_base + ".nick";
+
+			is_shared_nick 	= COConfigurationManager.getBooleanParameter( shared_key, true );
+			instance_nick 	= COConfigurationManager.getStringParameter( nick_key, "" );
+ */
+	
+		// nick
+	
+	public String
+	getNick(
+		String		net,
+		String		key )
+	{
+			// migrate
+		
+		String old_key = "azbuddy.chat." + net + ": " + key + ".nick";
+				
+		if ( COConfigurationManager.doesParameterNonDefaultExist( old_key )){
+			
+			String temp = COConfigurationManager.getStringParameter( old_key, "" );
+			
+			COConfigurationManager.removeParameter( old_key );
+
+			if ( temp.length() > 0 ){
+				
+				setNick( net, key, temp );
+				
+				return( temp );
+			}
+		}
+		
+		String nick = getStringOption( net, key, "nick", "" );
+		
+		return( nick );
+	}
+	
+	public void
+	setNick(
+		String		net,
+		String		key,
+		String		nick )
+	{
+		setStringOption( net, key, "nick", nick ); 
+	}
+	
+		// shared nick
+	
+	private boolean
+	getSharedNick(
+		String		net,
+		String		key )
+	{
+		String old_key = "azbuddy.chat." + net + ": " + key + ".shared";
+		
+		if ( COConfigurationManager.doesParameterNonDefaultExist( old_key )){
+			
+			boolean temp = COConfigurationManager.getBooleanParameter( old_key, true );
+			
+			COConfigurationManager.removeParameter( old_key );
+
+			if ( !temp ){
+				
+				setSharedNick( net, key, false );
+			}
+			
+			return( temp );
+		}
+		
+		return( getBooleanOption( net, key, "sn", true ));
+	}
+	
+	private void
+	setSharedNick(
+		String		net,
+		String		key,
+		boolean		b )
+	{
+		setBooleanOption( net, key, "sn", b );
+	}
+	
+		// save messages
+	
+	private boolean
+	getSaveMessages(
+		String		net,
+		String		key )
+	{
+		return( getBooleanOption( net, key, "save", false ));
+	}
+	
+	private void
+	setSaveMessages(
+		String		net,
+		String		key,
+		boolean		b )
+	{
+		setBooleanOption( net, key, "save", b );
+	}
+
+		// log messages
+	
+	private boolean
+	getLogMessages(
+		String		net,
+		String		key )
+	{
+		return( getBooleanOption( net, key, "log", false ));
+	}
+	
+	private void
+	setLogMessages(
+		String		net,
+		String		key,
+		boolean		b )
+	{
+		setBooleanOption( net, key, "log", b );
+
+	}
+	
+		// auto-mute
+	
+	private boolean
+	getAutoMute(
+		String		net,
+		String		key )
+	{
+		return( getBooleanOption( net, key, "automute", false ));
+	}
+	
+	private void
+	setAutoMute(
+		String		net,
+		String		key,
+		boolean		b )
+	{
+		setBooleanOption( net, key, "automute", b );
+	}
+	
+		// last message info
+	
+	public String
+	getLastMessageInfo(
+		String		net,
+		String		key )
+	{
+		return( getStringOption( net, key, "lmi", null ));
+	}
+	
+	public void
+	setLastMessageInfo(
+		String		net,
+		String		key,
+		String		info )
+	{
+		setStringOption( net, key, "lmi", info ); 
+	}
+	
+		// migration
+	
+	private void
+	migrateBooleans(
+		Map<String,Long>		map,
+		String					name )
+	{
+		for ( Map.Entry<String, Long> entry: map.entrySet()){
+			
+			String 	net_key = entry.getKey();
+			Long	value	= entry.getValue();
+			
+			if ( value == 1 ){
+				
+				String[] bits = net_key.split( ":", 2 );
+				
+				String network 	= AENetworkClassifier.internalise( bits[0] );
+				String key		= bits[1];
+								
+				setBooleanOption( network, key, name, true );
+			}
+		}
+	}
+	
+	private void
+	migrateByteArrays(
+		Map<String,byte[]>		map,
+		String					name )
+	{
+		for ( Map.Entry<String, byte[]> entry: map.entrySet()){
+			
+			String 	net_key = entry.getKey();
+			byte[]	value	= entry.getValue();
+							
+			String[] bits = net_key.split( ":", 2 );
+				
+			String network 	= AENetworkClassifier.internalise( bits[0] );
+			String key		= bits[1];
+								
+			setByteArrayOption( network, key, name, value );
+		}
+	}
+	
+	private void
+	setBooleanOption(
+		String		net,
+		String		key,
+		String		name,
+		boolean		value )
+	{
+		setGenericOption(net, key, name, value?1L:0L );
+	}
+	
+	private boolean
+	getBooleanOption(
+		String		net,
+		String		key,
+		String		name,
+		boolean		def )
+	{
+		Object	obj = getGenericOption(net, key, name);
+		
+		if ( obj instanceof Number ){
+			
+			return(((Number)obj).intValue()!=0);
+		}
+		
+		return( def );
+	}
+	
+	private void
+	setStringOption(
+		String		net,
+		String		key,
+		String		name,
+		String		value )
+	{
+		try{
+			setByteArrayOption( net, key, name, value.getBytes( "UTF-8" ));
+			
+		}catch( Throwable e ){
+			
+		}
+	}
+	
+	private String
+	getStringOption(
+		String		net,
+		String		key,
+		String		name,
+		String		def )
+	{
+		byte[]	bytes = getByteArrayOption( net, key, name );
+		
+		if ( bytes != null ){
+			
+			try{
+				return( new String( bytes, "UTF-8" ));
+			
+			}catch( Throwable e ){
+			
+			}
+		}
+		
+		return( def );
+	}
+	
+	private void
+	setByteArrayOption(
+		String		net,
+		String		key,
+		String		name,
+		byte[]		value )
+	{
+		setGenericOption( net, key, name, value );
+	}
+	
+	private byte[]
+	getByteArrayOption(
+		String		net,
+		String		key,
+		String		name )
+	{
+		Object	obj = getGenericOption(net, key, name);
+		
+		if ( obj instanceof byte[] ){
+			
+			return((byte[])obj);
+		}
+		
+		return( null );
+	}
+	
+	private String
+	encodeKey(
+		String	key )
+	{
+		try{
+			return( Base32.encode( key.getBytes( "UTF-8" )));
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e);
+			
+			return( "" );
+		}
+	}
+	
+	private String
+	decodeKey(
+		String		key )
+	{
+		try{
+			return( new String( Base32.decode( key ),"UTF-8" ));
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e);
+			
+			return( "" );
+		}
+	}
+	
+	private Object
+	getGenericOption(
+		String		net,
+		String		key,
+		String		name )
+	{
+		String net_key = net + ":" + encodeKey( key );
+		
+		synchronized( opts_map ){
+			
+			Map<String,Object>	opts = (Map<String,Object>)opts_map.get( net_key );
+			
+			if ( opts == null ){
+					
+				return( null );
+			}
+			
+			return( opts.get( name ));
+		}
+	}
+	
+	private void
+	setGenericOption(
+		String		net,
+		String		key,
+		String		name,
+		Object		value )
+	{
+		String net_key = net + ":" + encodeKey( key );
+		
+		synchronized( opts_map ){
+						
+			try{
+				Map<String,Object>	opts = (Map<String,Object>)opts_map.get( net_key );
+				
+				if ( opts == null ){
+				
+					opts = new HashMap<String, Object>();
+				
+					opts_map.put( net_key, opts );
+				}
+			
+				opts.put( name, value );
+			
+				COConfigurationManager.setParameter( "azbuddy.dchat.optsmap", opts_map );
+				
+			}catch( Throwable e ){
+			}
+		}
+		
+		COConfigurationManager.setDirty();
+	}
+	
+	private void
+	removeAllOptions(
+		String		net,
+		String		key )
+	{
+		String net_key = net + ":" + encodeKey( key );
+		
+		synchronized( opts_map ){
+						
+			try{
+				Map<String,Object>	opts = (Map<String,Object>)opts_map.remove( net_key );
+				
+				if ( opts == null ){
+				
+					return;
+				}
+						
+				COConfigurationManager.setParameter( "azbuddy.dchat.optsmap", opts_map );
+				
+			}catch( Throwable e ){
+			}
+		}
+		
+		COConfigurationManager.setDirty();
+	}
+	
+	public String
+	getSharedPublicNickname()
+	{
+		return( shared_public_nickname );
+	}
+	
+	public void
+	setSharedPublicNickname(
+		String		_nick )
+	{
+		if ( !_nick.equals( shared_public_nickname )){
+			
+			shared_public_nickname	= _nick;
+		
+			COConfigurationManager.setParameter( "azbuddy.chat.shared_nick", _nick );
+			
+			COConfigurationManager.setDirty();
+
+			allUpdated();		
+		}	
+	}
+	
+	public String
+	getSharedAnonNickname()
+	{
+		return( shared_anon_nickname );
+	}
+	
+	public void
+	setSharedAnonNickname(
+		String		_nick )
+	{
+		if ( !_nick.equals( shared_anon_nickname )){
+			
+			shared_anon_nickname	= _nick;
+		
+			COConfigurationManager.setParameter( "azbuddy.chat.shared_anon_nick", _nick );
+			
+			COConfigurationManager.setDirty();
+
+			allUpdated();		
+		}	
+	}
+	
+	public int
+	getPrivateChatState()
+	{
+		return( private_chat_state );
+	}
+	
+	public void
+	setPrivateChatState(
+		int		state )
+	{
+		if ( state !=  private_chat_state ){
+			
+			private_chat_state	= state;
+		
+			COConfigurationManager.setParameter( "azbuddy.chat.private_chat_state", state );
+			
+			COConfigurationManager.setDirty();
+
+			plugin.fireUpdated();
+		}	
+	}
+	
+	public boolean
+	getSharedAnonEndpoint()
+	{
+		return( shared_anon_endpoint );
+	}
+	
+	public void
+	setSharedAnonEndpoint(
+		boolean		b )
+	{
+		if ( b !=  shared_anon_endpoint ){
+			
+			shared_anon_endpoint	= b;
+		
+			COConfigurationManager.setParameter( "azbuddy.chat.share_i2p_endpoint", b );
+			
+			COConfigurationManager.setDirty();
+
+			plugin.fireUpdated();
+		}	
+	}
+	
+	public void
+	setSoundEnabled(
+		boolean		b )
+	{
+		if ( b !=  sound_enabled ){
+			
+			sound_enabled	= b;
+		
+			COConfigurationManager.setParameter( "azbuddy.chat.notif.sound.enable", b );
+			
+			COConfigurationManager.setDirty();
+			
+			plugin.fireUpdated();
+		}	
+	}
+	
+	public boolean
+	getSoundEnabled()
+	{
+		return( sound_enabled );
+	}
+	
+	public String
+	getSoundFile()
+	{
+		return( sound_file );
+	}
+	
+	public void
+	setSoundFile(
+		String		_file )
+	{
+		if ( !_file.equals( sound_file )){
+			
+			sound_file	= _file;
+		
+			COConfigurationManager.setParameter( "azbuddy.chat.notif.sound.file", _file );
+			
+			COConfigurationManager.setDirty();
+			
+			plugin.fireUpdated();	
+		}	
+	}
+	
+	private void
+	allUpdated()
+	{
+		for ( ChatInstance chat: chat_instances_list ){
+			
+			chat.updated();
+		}
+		
+		plugin.fireUpdated();
+	}
+	
+	protected void
+	startup()
+	{						
+		plugin_interface.addEventListener(
+			new PluginEventListener()
+			{
+				public void 
+				handleEvent(
+					PluginEvent ev )
+				{
+					int	type = ev.getType();
+					
+					if ( type == PluginEvent.PEV_INITIAL_SHARING_COMPLETE ){
+						
+						try{
+							ShareManager share_manager = plugin_interface.getShareManager();
+							
+							share_manager.addListener(
+								new ShareManagerListener() {
+									
+									public void 
+									resourceModified(
+										ShareResource old_resource,
+										ShareResource new_resource ) 
+									{
+										checkTag( new_resource );
+									}
+									
+									public void 
+									resourceDeleted(
+										ShareResource resource ) 
+									{
+									}
+									
+									public void 
+									resourceAdded(
+										ShareResource resource )
+									{
+										checkTag( resource );
+									}
+									
+									public void 
+									reportProgress(
+										int percent_complete )
+									{
+									}
+									
+									public void 
+									reportCurrentTask(
+										String task_description ) 
+									{				}
+								});
+							
+							ShareResource[] existing = share_manager.getShares();
+							
+							for ( ShareResource sr: existing ){
+								
+								checkTag( sr );
+							}
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}else if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL ){
+						
+						pluginAdded((PluginInterface)ev.getValue());
+						
+					}else  if ( type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL ){
+						
+						pluginRemoved((PluginInterface)ev.getValue());
+					}
+				}
+			});
+		
+		PluginInterface[] plugins = plugin_interface.getPluginManager().getPlugins( true );
+		
+		for ( PluginInterface pi: plugins ){
+			
+			if ( pi.getPluginState().isOperational()){
+			
+				pluginAdded( pi );
+			}
+		}
+	}
+	
+	private void
+	checkTag(
+		ShareResource		resource )
+	{
+		Map<String,String>	properties = resource.getProperties();
+		
+		if ( properties != null ){
+			
+			String ud = properties.get( ShareManager.PR_USER_DATA );
+			
+			if ( ud.equals( "buddyplugin:share" )){
+				
+				try{
+
+					Torrent torrent = null;
+				
+					if ( resource instanceof ShareResourceFile ){
+						
+						torrent = ((ShareResourceFile)resource).getItem().getTorrent();
+						
+					}else if ( resource instanceof ShareResourceDir ){
+						
+						torrent = ((ShareResourceDir)resource).getItem().getTorrent();
+					}
+					
+					if ( torrent != null ){
+						
+						Download download = plugin_interface.getPluginManager().getDefaultPluginInterface().getShortCuts().getDownload( torrent.getHash());
+	
+						if ( download != null ){
+							
+							tagDownload( download );
+						}
+					}
+				}catch( Throwable e ){
+					
+				}
+			}
+		}
+	}
+	
+	public void
+	tagDownload(
+		Download	download )
+	{
+		try{
+			TagType tt = TagManagerFactory.getTagManager().getTagType( TagType.TT_DOWNLOAD_MANUAL );
+			
+			Tag tag = tt.getTag( "tag.azbuddy.dchat.shares", false );
+			
+			if ( tag == null ){
+				
+				tag = tt.createTag( "tag.azbuddy.dchat.shares", true );
+				
+				tag.setCanBePublic( false );
+				
+				tag.setPublic( false );
+			}
+			
+			tag.addTaggable( PluginCoreUtils.unwrap( download ));
+			
+		}catch( Throwable e ){
+		
+			Debug.out( e );
+		}	
+	}
+	
+	protected void
+	closedown()
+	{
+		
+	}
+		
+	private void
+	pluginAdded(
+		final PluginInterface	pi )
+	{
+		if ( pi.getPluginID().equals( "azmsgsync" )){
+			
+			synchronized( chat_instances_map ){
+
+				azmsgsync_pi = pi;
+				
+				Iterator<ChatInstance>	it = chat_instances_map.values().iterator();
+					
+				while( it.hasNext()){
+					
+					ChatInstance inst = it.next();
+					
+					try{
+						inst.bind( azmsgsync_pi, null );
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+						
+						it.remove();
+					}
+				}
+			}
+			
+			dispatcher.dispatch(
+				new AERunnable() {
+					
+					@Override
+					public void 
+					runSupport() 
+					{
+						try{
+							if ( Constants.isCVSVersion() && enabled.getValue()){
+								
+								if ( BETA_CHAN_ENABLED ){
+								
+									ChatInstance chat = getChat( AENetworkClassifier.AT_PUBLIC, BETA_CHAT_KEY );
+								
+									chat.setKeepAlive( true );
+								}
+							}	
+						}catch( Throwable e ){
+							
+							// Debug.out( e );
+						}
+					}
+				});
+
+		}
+	}
+	
+	private void
+	pluginRemoved(
+		PluginInterface	pi )
+	{
+		if ( pi.getPluginID().equals( "azmsgsync" )){
+			
+			synchronized( chat_instances_map ){
+
+				azmsgsync_pi = null;
+						
+				Iterator<ChatInstance>	it = chat_instances_map.values().iterator();
+				
+				while( it.hasNext()){
+					
+					ChatInstance inst = it.next();
+					
+					inst.unbind();
+					
+					if ( inst.isPrivateChat()){
+						
+						it.remove();
+					}	
+				}
+			}
+		}
+	}
+		
+	public boolean
+	isI2PAvailable()
+	{
+		return( AEPluginProxyHandler.hasPluginProxyForNetwork( AENetworkClassifier.AT_I2P, false ));
+	}
+	
+	public InputStream
+	handleURI(
+		String		url_str,
+		boolean		open_only )
+		
+		throws Exception
+	{
+		
+			// url_str will be something like chat:anon?Test%20Me[&a=b]...
+			// should really be chat:anon?key=Test%20Me but we'll support the shorthand
+		
+			// azplug:?id=azbuddy&arg=chat%3A%3FTest%2520Me%26format%3Drss
+			// azplug:?id=azbuddy&arg=chat%3A%3Fkey%3DTest%2520Me%26format%3Drss
+				
+		int	pos = url_str.indexOf( '?' );
+		
+		String protocol;
+		String key 		= null;
+		String format	= null;
+		
+		if ( pos != -1 ){
+			
+			protocol = url_str.substring( 0, pos ).toLowerCase( Locale.US );
+			
+			String args = url_str.substring( pos+1 );
+			
+			String[] bits = args.split( "&" );
+			
+			for ( String bit: bits ){
+				
+				String[] temp = bit.split( "=" );
+				
+				if ( temp.length == 1 ){
+					
+					key = UrlUtils.decode( temp[0] );
+					
+				}else{
+					
+					String lhs = temp[0].toLowerCase( Locale.US );
+					String rhs = UrlUtils.decode( temp[1] );
+					
+					if ( lhs.equals( "key" )){
+						
+						key = rhs;
+						
+					}else if ( lhs.equals( "format" )){
+						
+						format	= rhs;
+					}
+				}
+			}
+					
+		}else{
+			
+			throw( new Exception( "Malformed request" ));
+		}
+		
+		if ( key == null ){
+			
+			throw( new Exception( "Key missing" ));
+		}
+		
+		if ( open_only ){
+			
+			format = null;
+		}
+		
+		String network;
+		
+		if ( protocol.startsWith( "chat:anon" )){
+				
+			if ( !isI2PAvailable()){
+				
+				throw( new Exception( "I2P unavailable" ));
+			}
+			
+			network = AENetworkClassifier.AT_I2P;
+			
+		}else if ( protocol.startsWith( "chat" )){
+			
+			network = AENetworkClassifier.AT_PUBLIC;
+			
+		}else{
+		
+			throw( new Exception( "Invalid protocol: " + protocol ));
+		}
+		
+		if ( format == null || !format.equalsIgnoreCase( "rss" )){
+		
+			BuddyPluginViewInterface ui = plugin.getSWTUI();
+
+			if ( ui == null ){
+				
+				throw( new Exception( "UI unavailable" ));
+			}
+		
+			ChatInstance chat = getChat( network, key);
+
+			ui.openChat( chat );
+		
+			return( null );
+			
+		}else{
+			
+			ChatInstance chat = peekChatInstance( network, key, true );
+			
+			if ( chat == null ){
+				
+				throw( new Exception( "Chat unavailable" ));
+			}
+			
+				// we need this chat to hang around
+			
+			if ( !chat.isFavourite()){
+				
+				chat.setFavourite( true );
+				
+				chat.setKeepAlive( true );
+			}
+			
+			if ( !chat.getSaveMessages()){
+				
+				chat.setSaveMessages( true );
+			}
+			
+			List<ChatMessage> messages = chat.getMessages();
+			
+			ByteArrayOutputStream baos = new ByteArrayOutputStream( 10*1024 );
+			
+			PrintWriter pw = new PrintWriter( new OutputStreamWriter( baos, "UTF-8" ));
+			
+			pw.println( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
+			
+			pw.println( "<rss version=\"2.0\" xmlns:vuze=\"http://www.vuze.com\">" );
+			
+			pw.println( "<channel>" );
+			
+			pw.println( "<title>" + escape( chat.getName()) + "</title>" );
+					
+			long	last_modified;
+			
+			if ( messages.size() == 0 ){
+				
+				last_modified = SystemTime.getCurrentTime();
+				
+			}else{
+				
+				last_modified = messages.get( messages.size()-1).getTimeStamp();
+			}
+										
+			pw.println(	"<pubDate>" + TimeFormatter.getHTTPDate( last_modified ) + "</pubDate>" );
+		
+			for ( ChatMessage message: messages ){
+								
+				List<Map<String,Object>>	magnets = extractMagnets( message.getMessage());
+				
+				if ( magnets.size() == 0 ){
+					
+					continue;
+				}
+				
+				String item_date = TimeFormatter.getHTTPDate( message.getTimeStamp());
+
+				for ( Map<String,Object> magnet: magnets ){
+					
+					String	hash 	= (String)magnet.get( "hash" );
+					
+					if ( hash == null ){
+						
+						continue;
+					}
+					
+					String	title 	= (String)magnet.get( "title" );
+					
+					if ( title == null ){
+						
+						title = hash;
+					}
+				
+					String	link	= (String)magnet.get( "link" );
+					
+					if ( link == null ){
+						
+						link = (String)magnet.get( "magnet" );
+					}
+					
+					pw.println( "<item>" );
+				
+					pw.println( "<title>" + escape( title ) + "</title>" );
+				
+					pw.println( "<guid>" + hash + "</guid>" );
+				
+					String	cdp	= (String)magnet.get( "cdp" );
+
+					if ( cdp != null ){
+						
+						pw.println( "<link>" + escape( cdp ) + "</link>" );
+					}
+					
+					Long	size 		= (Long)magnet.get( "size" );
+					Long	seeds 		= (Long)magnet.get( "seeds" );
+					Long	leechers 	= (Long)magnet.get( "leechers" );
+					Long	date	 	= (Long)magnet.get( "date" );
+
+					String enclosure = 
+							"<enclosure " + 
+								"type=\"application/x-bittorrent\" " +
+								"url=\"" + escape( link ) + "\"";
+					
+					if ( size != null ){
+						
+						enclosure += " length=\"" + size + "\"";
+					}
+					
+					enclosure += " />";
+					
+					pw.println( enclosure );
+							
+					String date_str = (date==null||date<=0)?item_date:TimeFormatter.getHTTPDate( date );
+					
+					pw.println(	"<pubDate>" + date_str + "</pubDate>" );
+				
+					
+					if ( size != null ){
+						
+						pw.println(	"<vuze:size>" + size + "</vuze:size>" );
+					}
+					
+					if ( seeds != null ){
+						
+						pw.println(	"<vuze:seeds>" + seeds + "</vuze:seeds>" );
+					}
+					
+					if ( leechers != null ){
+						
+						pw.println(	"<vuze:peers>" + leechers + "</vuze:peers>" );
+					}
+					
+					pw.println(	"<vuze:assethash>" + hash + "</vuze:assethash>" );
+												
+					pw.println( "<vuze:downloadurl>" + escape( link ) + "</vuze:downloadurl>" );
+				
+					pw.println( "</item>" );
+				}
+			}
+			
+			pw.println( "</channel>" );
+			
+			pw.println( "</rss>" );
+			
+			pw.flush();
+			
+			return( new ByteArrayInputStream( baos.toByteArray()));
+		}
+	}
+	
+	private List<Map<String,Object>>
+	extractMagnets(
+		String		str )
+	{
+		List<Map<String,Object>> result = new ArrayList<Map<String,Object>>();
+		
+		int	len = str.length();
+		
+		String	lc_str = str.toLowerCase( Locale.US );
+		
+		int	pos = 0;
+		
+		while( pos < len ){
+			
+			pos = lc_str.indexOf( "magnet:", pos );
+			
+			if ( pos == -1 ){
+				
+				break;
+			}
+			
+			int	start = pos;
+			
+			while( pos < len ){
+				
+				char c = str.charAt( pos );
+				
+				if ( Character.isWhitespace( c ) || ( c == '"' && start > 0 && lc_str.charAt( start-1 ) == '"' )){
+					
+					break;
+					
+				}else{
+					
+					pos++;
+				}
+			}
+			
+			String magnet = str.substring( start, pos );
+			
+			int x = magnet.indexOf( '?' );
+			
+			if ( x != -1 ){
+			
+				Map<String,Object> map = new HashMap<String,Object>();
+				
+					// remove any trailing ui name hack
+				
+				int	p1 = magnet.lastIndexOf( "[[" );
+				
+				if ( p1 != -1 && magnet.endsWith( "]]" )){
+					
+					magnet = magnet.substring( 0, p1 );
+				}
+				
+				map.put( "magnet", magnet );
+				
+				List<String>	trackers = new ArrayList<String>();
+				
+				map.put( "trackers", trackers );
+				
+				String[] bits = magnet.substring( x+1 ).split( "&" );
+				
+				for ( String bit: bits ){
+					
+					String[] temp = bit.split( "=" );
+					
+					if ( temp.length == 2 ){
+						
+						try{
+
+							String	lhs = temp[0].toLowerCase( Locale.US );
+							String	rhs = UrlUtils.decode( temp[1] );
+							
+							if ( lhs.equals( "xt" )){
+								
+								String lc_rhs = rhs.toLowerCase( Locale.US );
+								
+								int p = lc_rhs.indexOf( "btih:" );
+								
+								if ( p >= 0 ){
+									
+									map.put( "hash", lc_rhs.substring( p+5 ).toUpperCase( Locale.US ));
+								}
+								
+							}else if ( lhs.equals( "dn" )){
+								
+								map.put( "title", rhs );
+								
+							}else if ( lhs.equals( "tr" )){
+								
+								trackers.add( rhs );
+								
+							}else if ( lhs.equals( "fl" )){
+								
+								map.put( "link", rhs );
+								
+							}else if ( lhs.equals( "xl" )){
+								
+								long size = Long.parseLong( rhs );
+								
+								map.put( "size", size );
+								
+							}else if ( lhs.equals( "_d" )){
+								
+								long date = Long.parseLong( rhs );
+								
+								map.put( "date", date );
+
+							}else if ( lhs.equals( "_s" )){
+								
+								long seeds = Long.parseLong( rhs );
+								
+								map.put( "seeds", seeds );
+								
+							}else if ( lhs.equals( "_l" )){
+								
+								long leechers = Long.parseLong( rhs );
+								
+								map.put( "leechers", leechers );
+								
+							}else if ( lhs.equals( "_c" )){
+							
+								map.put( "cdp", rhs );
+							}
+						}catch( Throwable e ){
+							
+						}
+
+					}
+				}
+			
+				//System.out.println( magnet + " -> " + map );
+				
+				result.add( map );
+			}
+		}
+		
+		return( result );
+	}
+	
+	private String
+	escape(
+		String	str )
+	{
+		return( XUXmlWriter.escapeXML(str));
+	}
+	
+	public boolean
+	getFTUXAccepted()
+	{
+		return( ftux_accepted );
+	}
+	
+	public void
+	setFTUXAccepted(
+		boolean	accepted )
+	{
+		ftux_accepted = accepted;
+		
+		COConfigurationManager.setParameter( "azbuddy.dchat.ftux.accepted", true );
+		
+		COConfigurationManager.save();
+		
+		for ( FTUXStateChangeListener l: ftux_listeners ){
+			
+			l.stateChanged( accepted );
+		}
+	}
+	
+	public void
+	addFTUXStateChangeListener(
+		FTUXStateChangeListener		listener )
+	{
+		ftux_listeners.add( listener );
+		
+		listener.stateChanged( ftux_accepted );
+	}
+	
+	public void
+	removeFTUXStateChangeListener(
+		FTUXStateChangeListener		listener )
+	{
+		ftux_listeners.remove( listener );
+	}
+	
+	private void
+	logMessage(
+		ChatInstance		chat,
+		ChatMessage			message )
+	{
+		File log_dir = AEDiagnostics.getLogDir();
+		
+		log_dir = new File( log_dir, "chat" );
+		
+		if ( !log_dir.exists()){
+			
+			log_dir.mkdir();
+		}
+		
+		File log_file = new File( log_dir, FileUtil.convertOSSpecificChars( chat.getName(), false ) + ".log" );
+		
+		PrintWriter	pw = null;
+		
+		try{
+			
+			pw = new PrintWriter( new OutputStreamWriter( new FileOutputStream( log_file, true ), "UTF-8" ));
+						
+			SimpleDateFormat time_format 	= new SimpleDateFormat( "yyyy/MM/dd HH:mm" );
+
+			String msg = "[" + time_format.format( new Date( message.getTimeStamp())) + "]";
+							
+			msg += " <" + message.getParticipant().getName( true ) + "> " + message.getMessage();
+
+			pw.println( msg );
+			
+		}catch( Throwable e ){
+			
+		}finally{
+			
+			if ( pw != null ){
+				
+				pw.close();
+			}
+		}
+	}
+	
+	public void
+	getAndShowChat(
+		String		network,
+		String		key )
+		
+		throws Exception
+	{
+		BuddyPluginViewInterface ui = plugin.getSWTUI();
+		
+		if ( ui == null ){
+			
+			throw( new Exception( "UI unavailable" ));
+		}
+				
+		ChatInstance chat = getChat( network, key) ;
+			
+		ui.openChat( chat );
+	}
+	
+	public void
+	showChat(
+		ChatInstance	inst )
+		
+		throws Exception
+	{
+		BuddyPluginViewInterface ui = plugin.getSWTUI();
+		
+		if ( ui == null ){
+			
+			throw( new Exception( "UI unavailable" ));
+		}
+							
+		ui.openChat( inst );
+	}
+	
+	private String
+	pkToString(
+		byte[]		pk )
+	{		
+		byte[] temp = new byte[3];
+		
+		if ( pk != null ){
+			
+			System.arraycopy( pk, 8, temp, 0, 3 );
+		}
+		
+		return( ByteFormatter.encodeString( temp ));
+	}
+	
+	public ChatInstance
+	importChat(
+		String		import_data )
+		
+		throws Exception
+	{
+		if ( azmsgsync_pi == null ){
+			
+			throw( new Exception( "Plugin unavailable " ));
+		}
+		
+		Map<String,Object>		options = new HashMap<String, Object>();
+				
+		options.put( "import_data", import_data.getBytes( "UTF-8" ));
+	
+		Map<String,Object> reply = (Map<String,Object>)azmsgsync_pi.getIPC().invoke( "importMessageHandler", new Object[]{ options } );
+
+		String	key			= new String((byte[])reply.get( "key" ), "UTF-8" );
+		String	network	 	= (String)reply.get( "network" );
+		Object	handler 	= reply.get( "handler" );
+		
+		return( getChat( network, key, null, handler, false, null ));
+	}
+	
+	public ChatInstance
+	getChat(
+		Download		download )
+	{
+		String	key = BuddyPluginUtils.getChatKey( download );
+
+		if ( key != null ){
+			
+			String[] networks = PluginCoreUtils.unwrap( download ).getDownloadState().getNetworks();
+			
+			boolean	has_i2p = false;
+			
+			for ( String net: networks ){
+				
+				if ( net == AENetworkClassifier.AT_PUBLIC ){
+					
+					try{
+						ChatInstance inst = getChat( net, key );
+						
+						return( inst );
+						
+					}catch( Throwable e ){
+						
+					}
+				}else if ( net == AENetworkClassifier.AT_I2P ){
+					
+					has_i2p = true;
+				}
+			}
+			
+			if ( has_i2p ){
+				
+				try{
+					ChatInstance inst = getChat( AENetworkClassifier.AT_I2P, key );
+					
+					return( inst );
+										
+				}catch( Throwable e ){
+					
+				}
+			}
+		}
+		
+		return( null );
+	}
+	
+	public ChatInstance
+	getChat(
+		String			network,
+		String			key )	
+		
+		throws Exception
+	{
+		return( getChat( network, key, null, null, false, null ));
+	}
+	
+	public ChatInstance
+	getChat(
+		String					network,
+		String					key,
+		Map<String,Object>		options )
+		
+		throws Exception
+	{
+		return( getChat( network, key, null, null, false, options ));
+	}
+	
+	public ChatInstance
+	getChat(
+		ChatParticipant		participant )
+		
+		throws Exception
+	{
+		String key = participant.getChat().getKey() + " - " + participant.getName() + " (outgoing)[" + private_chat_id.getAndIncrement() + "]";
+		
+		return( getChat( participant.getChat().getNetwork(), key, participant, null, true, null ));
+	}
+	
+	public ChatInstance
+	getChat(
+		ChatParticipant	parent_participant,
+		Object			handler )
+		
+		throws Exception
+	{
+		String key = parent_participant.getChat().getKey() + " - " + parent_participant.getName() + " (incoming)[" + private_chat_id.getAndIncrement() + "]";
+
+		return( getChat( parent_participant.getChat().getNetwork(), key, null, handler, true, null ));
+	}
+	
+	private ChatInstance
+	getChat(
+		String				network,
+		String				key,
+		ChatParticipant		private_target,
+		Object				handler,
+		boolean				is_private_chat,
+		Map<String,Object>	options )
+		
+		throws Exception
+	{
+		if ( !enabled.getValue()){
+			
+			throw( new Exception( "Plugin not enabled" ));
+		}
+		
+		String meta_key = network + ":" + key;
+	
+		ChatInstance 	result;
+		
+		ChatInstance	added = null;
+		
+		synchronized( chat_instances_map ){
+			
+			result = chat_instances_map.get( meta_key );
+			
+			if ( result == null ){
+							
+				result = new ChatInstance( network, key, private_target, is_private_chat, options );
+			
+				chat_instances_map.put( meta_key, result );
+				
+				chat_instances_list.add( result );
+				
+				added = result;
+				
+				if ( azmsgsync_pi != null ){
+					
+					try{
+						result.bind( azmsgsync_pi, handler );
+						
+					}catch( Throwable e ){
+						
+						chat_instances_map.remove( meta_key );
+						
+						chat_instances_list.remove( result );
+						
+						added = null;
+						
+						result.destroy();
+						
+						if ( e instanceof Exception ){
+							
+							throw((Exception)e);
+						}
+						
+						throw( new Exception( e ));
+					}
+				}
+			}else{
+				
+				result.addReference();
+			}
+			
+			if ( timer == null ){
+				
+				timer = 
+					SimpleTimer.addPeriodicEvent(
+						"BPB:timer",
+						2500,
+						new TimerEventPerformer() {
+							
+							public void 
+							perform(
+								TimerEvent event ) 
+							{									
+								for ( ChatInstance inst: chat_instances_list ){
+										
+									inst.update();
+								}
+							}
+						});
+			}			
+		}
+		
+		if ( added != null ){
+			
+			for ( ChatManagerListener l: BuddyPluginBeta.this.listeners ){
+				
+				try{
+					l.chatAdded( added );
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+		}
+		
+		return( result );
+	}
+	
+	/**
+	 * returns existing chat if found without adding a reference to it. If create_if_missing supplied
+	 * then this will create a new chat (and add a reference to it) so use this parameter with
+	 * caution
+	 */
+	
+	private ChatInstance
+	peekChatInstance(
+		String				network,
+		String				key,
+		boolean				create_if_missing )
+	{
+		String meta_key = network + ":" + key;
+	
+		synchronized( chat_instances_map ){
+			
+			ChatInstance inst = chat_instances_map.get( meta_key );
+			
+			if ( inst == null && create_if_missing ){
+				
+				try{
+					inst = getChat( network, key );
+					
+				}catch( Throwable e ){
+					
+				}
+			}
+			
+			return( inst );
+		}
+	}
+	
+	public Map<String,Object>
+	peekChat(
+		Download		download )
+	{
+		String	key = BuddyPluginUtils.getChatKey( download );
+
+		if ( key != null ){
+			
+			String[] networks = PluginCoreUtils.unwrap( download ).getDownloadState().getNetworks();
+			
+			boolean	has_i2p = false;
+			
+			for ( String net: networks ){
+				
+				if ( net == AENetworkClassifier.AT_PUBLIC ){
+					
+					try{
+						return( peekChat( net, key ));
+												
+					}catch( Throwable e ){
+						
+					}
+				}else if ( net == AENetworkClassifier.AT_I2P ){
+					
+					has_i2p = true;
+				}
+			}
+			
+			if ( has_i2p ){
+				
+				try{
+					return( peekChat( AENetworkClassifier.AT_I2P, key ));
+															
+				}catch( Throwable e ){
+					
+				}
+			}
+		}
+		
+		return( null );
+	}
+	
+	public Map<String,Object>
+	peekChat(
+		String				network,
+		String				key )
+	{
+		Map<String,Object>		reply = new HashMap<String, Object>();
+		
+		try{
+			PluginInterface pi;
+		
+			synchronized( chat_instances_map ){
+
+				pi = azmsgsync_pi;
+			}
+			
+			if ( pi != null ){
+				
+				Map<String,Object>		options = new HashMap<String, Object>();
+				
+				options.put( "network", network );
+				options.put( "key", key.getBytes( "UTF-8" ));
+
+				options.put( "timeout", 60*1000 );
+				
+				if ( network != AENetworkClassifier.AT_PUBLIC ){
+					
+					options.put( "server_id", getSharedAnonEndpoint()?"dchat_shared":"dchat" );
+				}
+
+				reply = (Map<String,Object>)pi.getIPC().invoke( "peekMessageHandler", new Object[]{ options } );
+			}
+				
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+		
+		return( reply );
+	}
+	
+	public List<ChatInstance>
+	getChats()
+	{
+		return( chat_instances_list.getList());
+	}
+	
+	public void
+	addListener(
+		ChatManagerListener		l,
+		boolean					fire_for_existing )
+	{
+		listeners.add( l );
+		
+		if ( fire_for_existing ){
+			
+			for ( ChatInstance inst: chat_instances_list ){
+				
+				l.chatAdded( inst );
+			}
+		}
+	}
+	
+	public void
+	removeListener(
+		ChatManagerListener		l )
+	{
+		listeners.remove( l );
+	}
+	
+	private static Pattern auto_dup_pattern1 = Pattern.compile( "File '(.*?)' is" );
+	private static Pattern auto_dup_pattern2 = Pattern.compile( ":([a-zA-Z2-7]{32})", Pattern.CASE_INSENSITIVE );
+
+	private static Pattern[] auto_dup_patterns = { auto_dup_pattern1, auto_dup_pattern2 };
+	
+	public class
+	ChatInstance
+	{
+		public static final String	OPT_INVISIBLE		= "invisible";		// Boolean
+		
+		private static final int	MSG_HISTORY_MAX	= 512;
+		
+		private final String		network;
+		private final String		key;
+		
+		private boolean				is_private_chat;
+		private boolean				is_invisible_chat;
+		
+		private final ChatParticipant		private_target;
+		
+		private Object		binding_lock = new Object();
+		private AESemaphore	binding_sem;
+		
+		private volatile PluginInterface		msgsync_pi;
+		private volatile Object					handler;
+		
+		private byte[]							my_public_key;
+		private byte[]							managing_public_key;
+		private boolean							read_only;
+		private int								ipc_version;
+		
+		private InetSocketAddress				my_address;
+		
+		private Object	chat_lock = this;
+		
+		private AtomicInteger						message_uid_next = new AtomicInteger();
+		
+		private List<ChatMessage>					messages	= new ArrayList<ChatMessage>();
+		private ByteArrayHashMap<String>			message_ids = new ByteArrayHashMap<String>();
+		private int									messages_not_mine_count;
+		
+		private ByteArrayHashMap<ChatParticipant>	participants = new ByteArrayHashMap<ChatParticipant>();
+		
+		private Map<String,List<ChatParticipant>>	nick_clash_map = new HashMap<String, List<ChatParticipant>>();
+		
+		private CopyOnWriteList<ChatListener>		listeners = new CopyOnWriteList<ChatListener>();
+		
+		private Map<Object,Object>					user_data = new HashMap<Object, Object>();
+		
+		private LinkedHashMap<String,String>							auto_dup_set = 
+			new LinkedHashMap<String,String>(500,0.75f,true)
+			{
+				protected boolean 
+				removeEldestEntry(
+					Map.Entry<String,String> eldest) 
+				{
+					return size() > 500;
+				}
+			};
+			
+		private boolean		keep_alive;
+		private boolean		have_interest;
+		
+		private Map<String,Object> 	status;
+		
+		private boolean		is_shared_nick;
+		private String		instance_nick;
+		
+		private int			reference_count;
+		
+		private ChatMessage		last_message_requiring_attention;
+		private boolean			message_outstanding;
+		
+		private boolean		is_favourite;
+		private boolean		auto_notify;
+		
+		private boolean		save_messages;
+		private boolean		log_messages;
+		private boolean		auto_mute;
+		
+		private boolean		destroyed;
+		
+		private
+		ChatInstance(
+			String				_network,
+			String				_key,
+			ChatParticipant		_private_target,
+			boolean				_is_private_chat,
+			Map<String,Object>	_options )
+		{
+			network 		= _network;
+			key				= _key;
+			
+				// private chat args
+			
+			private_target	= _private_target;			
+			is_private_chat = _is_private_chat;
+			
+			is_shared_nick 	= getSharedNick( network, key );
+			instance_nick 	= getNick( network, key );
+			
+			if ( !is_private_chat ){
+			
+				is_favourite 	= getFavourite( network, key );
+				save_messages 	= BuddyPluginBeta.this.getSaveMessages( network, key );
+				log_messages 	= BuddyPluginBeta.this.getLogMessages( network, key );
+				auto_mute 		= BuddyPluginBeta.this.getAutoMute( network, key );
+			}
+			
+			if ( _options != null ){
+				
+				Boolean	invis = (Boolean)_options.get( OPT_INVISIBLE );
+				
+				if ( invis != null && invis ){
+					
+					is_invisible_chat = true;
+				}
+			}
+			
+			addReference();
+		}
+		
+		public ChatInstance
+		getClone()
+		
+			throws Exception
+		{
+			if ( is_private_chat ){
+				
+				addReference();
+				
+				return( this );
+				
+			}else{
+			
+					// can probably just do the above...
+				
+				return( BuddyPluginBeta.this.getChat( network, key ));
+			}
+		}
+		
+		protected void
+		addReference()
+		{
+			synchronized( chat_lock ){
+				
+				reference_count++;
+			}
+		}
+		
+		public String
+		getName()
+		{
+			String str = key;
+			
+			int pos = str.lastIndexOf( '[' );
+			
+			if ( pos != -1 && str.endsWith( "]")){
+				
+				String temp = str.substring( pos+1, str.length()-1 );
+				
+				if ( temp.contains( "pk=" )){
+					
+					str = str.substring( 0, pos );
+					
+					if ( temp.contains( "ro=1" )){
+				
+						str += "[R]";
+					}else{
+						
+						str += "[M]";
+					}
+				}else{
+					
+					str = str.substring( 0, pos );
+				}
+			}
+			
+			return( 
+				MessageText.getString(
+					network==AENetworkClassifier.AT_PUBLIC?"label.public":"label.anon") + 
+					" - '" + str + "'" );
+		}
+		
+		public String
+		getShortName()
+		{
+			
+			String	short_name = getName();
+			
+			if ( short_name.length() > 60 ){
+				
+				short_name = short_name.substring( 0, 60 ) + "...";
+			}
+			
+			return( short_name );
+		}
+		
+		public String
+		getNetwork()
+		{
+			return( network );
+		}
+		
+		public String
+		getKey()
+		{
+			return( key );
+		}
+		
+		public boolean
+		isFavourite()
+		{
+			return( is_favourite );
+		}
+		
+		public void
+		setAutoNotify(
+			boolean		b )
+		{
+			auto_notify	= b;
+		}
+		
+		public boolean
+		isAutoNotify()
+		{
+			return( auto_notify );
+		}
+		
+		public boolean
+		isInteresting()
+		{
+			return( have_interest );
+		}
+		
+		public boolean
+		isStatistics()
+		{
+			return( key.startsWith( "Statistics:" ));
+		}
+		
+		public void
+		setFavourite(
+			boolean		b )
+		{
+			if ( !is_private_chat ){
+				
+				if ( b != is_favourite ){
+					
+					is_favourite = b;
+					
+					BuddyPluginBeta.this.setFavourite( network, key, b );
+				}
+			}
+		}
+		
+		public boolean
+		getSaveMessages()
+		{
+			return( save_messages );
+		}
+		
+		public void
+		setSaveMessages(
+			boolean		b )
+		{
+			if ( !is_private_chat ){
+				
+				if ( b != save_messages ){
+					
+					save_messages = b;
+					
+					BuddyPluginBeta.this.setSaveMessages( network, key, b );
+					
+					Map<String,Object>	options = new HashMap<String, Object>();
+					
+					options.put( "save_messages", b );
+					
+					try{
+						updateOptions( options );
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+				}
+			}
+		}
+		
+		public boolean
+		getLogMessages()
+		{
+			return( log_messages );
+		}
+		
+		public void
+		setLogMessages(
+			boolean		b )
+		{
+			if ( !is_private_chat ){
+				
+				if ( b != log_messages ){
+					
+					log_messages = b;
+					
+					BuddyPluginBeta.this.setLogMessages( network, key, b );
+					
+				}
+			}
+		}
+		
+		public boolean
+		getAutoMute()
+		{
+			return( auto_mute );
+		}
+		
+		public void
+		setAutoMute(
+			boolean		b )
+		{
+			if ( !is_private_chat ){
+				
+				if ( b != auto_mute ){
+					
+					auto_mute = b;
+					
+					BuddyPluginBeta.this.setAutoMute( network, key, b );
+					
+				}
+			}
+		}
+		
+		private void
+		setSpammer(
+			ChatParticipant		participant,
+			boolean				is_spammer )
+		{
+			Map<String,Object>	options = new HashMap<String, Object>();
+			
+			options.put( "pk", participant.getPublicKey());
+			options.put( "spammer", is_spammer );
+			
+			try{
+				updateOptions( options );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+		
+		public boolean
+		isManaged()
+		{
+			return( managing_public_key != null );
+		}
+		
+		public boolean
+		amManager()
+		{
+			return( managing_public_key != null && Arrays.equals( my_public_key, managing_public_key ));
+		}
+		
+		public boolean
+		isManagedFor(
+			String		network,
+			String		key )
+		{
+			if ( getNetwork() != network ){
+				
+				return( false );
+			}
+			
+			return( getKey().equals( key + "[pk=" + Base32.encode( getPublicKey()) + "]" ));
+		}
+		
+		public ChatInstance
+		getManagedChannel()
+		
+			throws Exception
+		{
+			if ( isManaged()){
+				
+				throw( new Exception( "Channel is already managed" ));
+			}
+			
+			String new_key = getKey() + "[pk=" + Base32.encode( getPublicKey()) + "]";
+			
+			ChatInstance inst = getChat( getNetwork(), new_key );
+			
+			return( inst );
+		}
+		
+		public boolean
+		isReadOnlyFor(
+			String		network,
+			String		key )
+		{
+			if ( getNetwork() != network ){
+				
+				return( false );
+			}
+			
+			return( getKey().equals( key + "[pk=" + Base32.encode( getPublicKey()) + "&ro=1]" ));
+		}
+		
+		public ChatInstance
+		getReadOnlyChannel()
+		
+			throws Exception
+		{
+			if ( isManaged()){
+				
+				throw( new Exception( "Channel is already managed" ));
+			}
+			
+			String new_key = getKey() + "[pk=" + Base32.encode( getPublicKey()) + "&ro=1]";
+			
+			ChatInstance inst = getChat( getNetwork(), new_key );
+			
+			return( inst );
+		}
+		
+		public boolean
+		isReadOnly()
+		{
+			return( read_only && !amManager());
+		}
+		
+		public String
+		getURL()
+		{
+			if ( network == AENetworkClassifier.AT_PUBLIC ){
+				
+				return( "chat:?" + UrlUtils.encode( key ));
+				
+			}else{
+				
+				return( "chat:anon:?" + UrlUtils.encode( key ));
+			}
+		}
+		
+		public byte[]
+		getPublicKey()
+		{
+			return( my_public_key );
+		}
+		
+		public boolean
+		isInvisible()
+		{
+			return( is_invisible_chat );
+		}
+		
+		public boolean
+		isPrivateChat()
+		{
+			return( is_private_chat );
+		}
+		
+		public boolean
+		isAnonymous()
+		{
+			return( network != AENetworkClassifier.AT_PUBLIC );
+		}
+		
+		public String
+		getNetAndKey()
+		{
+			return( network + ": " + key );
+		}
+		
+		public void
+		setKeepAlive(
+			boolean		b )
+		{
+			keep_alive	= b;
+		}
+		
+		public boolean
+		getKeepAlive()
+		{
+			return( keep_alive );
+		}
+		
+		public String
+		getDefaultNickname()
+		{
+			return( pkToString( getPublicKey()));
+		}
+		
+		public boolean
+		isSharedNickname()
+		{
+			return( is_shared_nick );
+		}
+		
+		public void
+		setSharedNickname(
+			boolean		_shared ) 
+		{
+			if ( _shared != is_shared_nick ){
+			
+				is_shared_nick	= _shared;
+			
+				setSharedNick( network, key, _shared );
+				
+				updated();
+			}
+		}
+		
+		public String
+		getInstanceNickname()
+		{
+			return( instance_nick );
+		}
+		
+		public void
+		setInstanceNickname(
+			String		_nick )
+		{
+			if ( !_nick.equals( instance_nick )){
+				
+				instance_nick	= _nick;
+			
+				setNick( network, key, _nick );
+				
+				updated();
+			}
+		}
+		
+		public String
+		getNickname()
+		{
+			if ( is_shared_nick ){
+				
+				return( network == AENetworkClassifier.AT_PUBLIC?shared_public_nickname:shared_anon_nickname );
+				
+			}else{
+				
+				return( instance_nick );
+			}
+		}
+		
+		private Object
+		getHandler()
+		{
+			return( handler );
+		}
+		
+		private void
+		bind(
+			PluginInterface		_msgsync_pi,
+			Object				_handler )
+		
+			throws Exception
+		{	
+			boolean	inform_avail = false;
+			
+			synchronized( binding_lock ){
+				
+				binding_sem = new AESemaphore( "bpb:bind" );
+				
+				try{
+			
+					msgsync_pi = _msgsync_pi;
+		
+					if ( _handler != null ){
+						
+						handler		= _handler;
+						
+						try{
+							Map<String,Object>		options = new HashMap<String, Object>();
+									
+							options.put( "handler", _handler );
+							
+							options.put( "addlistener", this );
+									
+							Map<String,Object> reply = (Map<String,Object>)msgsync_pi.getIPC().invoke( "updateMessageHandler", new Object[]{ options } );
+								
+							my_public_key 		= (byte[])reply.get( "pk" );
+							managing_public_key = (byte[])reply.get( "mpk" );
+							Boolean ro 			= (Boolean)reply.get( "ro" );
+		
+							read_only = ro != null && ro;
+							
+							Number ipc_v = (Number)reply.get( "ipc_version" );
+							
+							ipc_version = ipc_v ==null?1:ipc_v.intValue();
+		
+							inform_avail = true;
+
+						}catch( Throwable e ){
+							
+							throw( new Exception( e ));
+						}
+					}else{
+					
+						try{
+							Map<String,Object>		options = new HashMap<String, Object>();
+							
+							options.put( "network", network );
+							options.put( "key", key.getBytes( "UTF-8" ));
+								
+							if ( private_target != null ){
+							
+								options.put( "parent_handler", private_target.getChat().getHandler());
+								options.put( "target_pk", private_target.getPublicKey());
+								options.put( "target_contact", private_target.getContact());
+							}
+							
+							if ( network != AENetworkClassifier.AT_PUBLIC ){
+								
+								options.put( "server_id", getSharedAnonEndpoint()?"dchat_shared":"dchat" );
+							}
+							
+							options.put( "listener", this );
+									
+							if ( getSaveMessages()){
+								
+								options.put( "save_messages", true );
+							}
+							
+							Map<String,Object> reply = (Map<String,Object>)msgsync_pi.getIPC().invoke( "getMessageHandler", new Object[]{ options } );
+							
+							handler = reply.get( "handler" );
+							
+							my_public_key = (byte[])reply.get( "pk" );
+							managing_public_key = (byte[])reply.get( "mpk" );
+							Boolean ro 			= (Boolean)reply.get( "ro" );
+		
+							read_only = ro != null && ro;
+							
+							Number ipc_v = (Number)reply.get( "ipc_version" );
+							
+							ipc_version = ipc_v ==null?1:ipc_v.intValue();
+							
+							inform_avail = true;
+							
+						}catch( Throwable e ){
+							
+							throw( new Exception( e ));
+						}
+					}
+				}finally{
+					
+					binding_sem.releaseForever();
+
+					binding_sem = null;
+				}
+			}
+			
+			if ( inform_avail ){
+					
+				for ( ChatListener l: listeners ){
+					
+					try{
+						l.stateChanged( true );
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+				}
+			}
+		}
+		
+		private void
+		updateOptions(
+			Map<String,Object>		options )
+			
+			throws Exception
+		{	
+			if ( handler == null || msgsync_pi == null ){
+				
+				Debug.out( "No handler!" );
+				
+			}else{
+				
+				options.put( "handler", handler );
+
+				msgsync_pi.getIPC().invoke( "updateMessageHandler", new Object[]{ options });
+			}
+		}
+		
+		private void
+		unbind()
+		{
+			for ( ChatListener l: listeners ){
+				
+				try{
+					l.stateChanged( false );
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+			
+			handler 	= null;
+			msgsync_pi	= null;
+		}
+		
+		public boolean
+		isAvailable()
+		{
+			return( handler != null );
+		}
+		
+		public ChatMessage[]
+		getHistory()
+		{
+			synchronized( chat_lock ){
+				
+				return( messages.toArray( new ChatMessage[ messages.size() ]));
+			}
+		}
+		
+		private void
+		update()
+		{
+			PluginInterface		current_pi 			= msgsync_pi;
+			Object 				current_handler 	= handler;
+			
+			if ( current_handler != null && current_pi != null ){
+							
+				try{
+					Map<String,Object>		options = new HashMap<String, Object>();
+					
+					options.put( "handler", current_handler );
+	
+					status = (Map<String,Object>)current_pi.getIPC().invoke( "getStatus", new Object[]{ options } );
+										
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+			
+			updated();
+		}
+		
+		private void
+		updated()
+		{
+			for ( ChatListener l: listeners ){
+				
+				try{	
+					l.updated();
+					
+				}catch( Throwable e ){
+				
+					Debug.out( e );
+				}
+			}
+		}
+		
+		public int
+		getEstimatedNodes()
+		{
+			Map<String,Object> map = status;
+			
+			if ( map == null ){
+				
+				return( -1 );
+			}
+			
+			return(((Number)map.get( "node_est" )).intValue());
+		}
+		
+		public int
+		getMessageCount(
+			boolean	not_mine )
+		{
+			if ( not_mine ){
+				
+				return( messages_not_mine_count );
+				
+			}else{
+			
+				return( messages.size());
+			}
+		}
+		
+			/**
+			 * -ve -> state unknown
+			 * 0 - synced
+			 * +ve - number of messages pending
+			 * @return
+			 */
+		
+		public int
+		getIncomingSyncState()
+		{
+			Map<String,Object> map = status;
+			
+			if ( map == null ){
+				
+				return( -3 );
+			}
+			
+			Number	in_pending = (Number)map.get( "msg_in_pending" );
+			
+			return( in_pending==null?-2:in_pending.intValue());
+		}
+		
+		/**
+		 * -ve -> state unknown
+		 * 0 - synced
+		 * +ve - number of messages pending
+		 * @return
+		 */
+		
+		public int
+		getOutgoingSyncState()
+		{
+			Map<String,Object> map = status;
+			
+			if ( map == null ){
+				
+				return( -3 );
+			}
+			
+			Number	out_pending = (Number)map.get( "msg_out_pending" );
+			
+			return( out_pending==null?-2:out_pending.intValue());
+		}
+		
+		public String
+		getStatus()
+		{
+			PluginInterface		current_pi 			= msgsync_pi;
+			Object 				current_handler 	= handler;
+
+			if ( current_pi == null ){
+				
+				return( MessageText.getString( "azbuddy.dchat.status.noplugin" ));
+			}
+			
+			if ( current_handler == null ){
+				
+				return( MessageText.getString( "azbuddy.dchat.status.nohandler" ));
+			}
+			
+			Map<String,Object> map = status;
+			
+			if ( map == null ){
+				
+				return( MessageText.getString( "azbuddy.dchat.status.notavail" ));
+				
+			}else{
+				int status 			= ((Number)map.get( "status" )).intValue();
+				int dht_count 		= ((Number)map.get( "dht_nodes" )).intValue();
+				
+				int nodes_local 	= ((Number)map.get( "nodes_local" )).intValue();
+				int nodes_live 		= ((Number)map.get( "nodes_live" )).intValue();
+				int nodes_dying 	= ((Number)map.get( "nodes_dying" )).intValue();
+				
+				int req_in 			= ((Number)map.get( "req_in" )).intValue();
+				double req_in_rate 	= ((Number)map.get( "req_in_rate" )).doubleValue();
+				int req_out_ok 		= ((Number)map.get( "req_out_ok" )).intValue();
+				int req_out_fail 	= ((Number)map.get( "req_out_fail" )).intValue();
+				double req_out_rate = ((Number)map.get( "req_out_rate" )).doubleValue();
+									
+				if ( status == 0 || status == 1 ){
+					
+					String	arg1;
+					String	arg2;
+					
+					if ( isPrivateChat()){
+						
+						arg1 = MessageText.getString( "label.private.chat" ) + ": ";
+						arg2 = "";
+					}else{
+						
+						if ( status == 0 ){
+						
+							arg1 = MessageText.getString( "pairing.status.initialising" ) + ": ";
+							arg2 = "DHT=" + (dht_count<0?"...":String.valueOf(dht_count)) + ", ";
+
+						}else if ( status == 1 ){
+							
+							arg1 = "";
+							arg2 = "DHT=" + dht_count + ", ";
+					
+						}else{
+							arg1 = "";
+							arg2 = "";
+						}
+					}
+					
+					String arg3 = nodes_local+"/"+nodes_live+"/"+nodes_dying;
+					String arg4 = DisplayFormatters.formatDecimal(req_out_rate,1) + "/" +  DisplayFormatters.formatDecimal(req_in_rate,1);
+					
+					String str = 
+						MessageText.getString(
+							"azbuddy.dchat.node.status",
+							new String[]{ arg1, arg2, arg3, arg4 });
+					
+					if ( isReadOnly()){
+						
+						str += ", R-";
+						
+					}else if ( amManager()){
+						
+						if ( read_only ){
+							
+							str += ", R+";
+							
+						}else{
+						
+							str += ", M+";
+						}
+					}else if ( isManaged()){
+						
+						str += ", M-";
+					}
+						
+					
+					return( str );
+					
+				}else{
+					
+					return( MessageText.getString( "azbuddy.dchat.status.destroyed" ));
+				}
+			}
+		}
+		
+		private TimerEvent	sort_event;
+		private boolean		sort_force_changed;
+		
+		private void
+		sortMessages(
+			boolean		force_change )
+		{
+			synchronized( chat_lock ){
+				
+				if ( force_change ){
+					
+					sort_force_changed = true;
+				}
+				
+				if ( sort_event != null ){
+					
+					return;
+				}
+				
+				sort_event = 
+					SimpleTimer.addEvent(
+						"msgsort",
+						SystemTime.getOffsetTime( 500 ),
+						new TimerEventPerformer()
+						{
+							public void 
+							perform(
+								TimerEvent event) 
+							{
+								boolean	changed = false;
+								
+								synchronized( chat_lock ){
+									
+									sort_event = null;
+									
+									changed = sortMessagesSupport();
+									
+									if ( sort_force_changed ){
+										
+										changed = true;
+												
+										sort_force_changed = false;
+									}
+								}
+								
+								if ( changed ){
+									
+									for ( ChatListener l: listeners ){
+										
+										l.messagesChanged();
+									}
+								}
+							}
+						});
+			}
+		}
+		
+		private boolean
+		sortMessagesSupport()
+		{
+			int	num_messages = messages.size();
+			
+			ByteArrayHashMap<ChatMessage>	id_map 		= new ByteArrayHashMap<ChatMessage>( num_messages );
+			Map<ChatMessage,ChatMessage>	prev_map 	= new HashMap<ChatMessage,ChatMessage>( num_messages );
+			
+			Map<ChatMessage,Object>	next_map 			= new HashMap<ChatMessage,Object>( num_messages );
+			
+				// build id map so we can lookup prev messages
+			
+			// System.out.println( "Sorting messages" );
+			
+			for ( ChatMessage msg: messages ){
+				
+				// System.out.println( "    " + msg.getString());
+				
+				byte[]	id = msg.getID();
+				
+				id_map.put( id, msg );
+			}
+			
+				// build sets of prev/next links 
+			
+			for ( ChatMessage msg: messages ){
+				
+				byte[]	prev_id 	= msg.getPreviousID();
+				
+				if ( prev_id != null ){
+					
+					ChatMessage prev_msg = id_map.get( prev_id );
+					
+					if ( prev_msg != null ){
+						
+						msg.setPreviousID( prev_msg.getID());	// save some mem
+						
+						// ordering prev_msg::msg
+					
+						prev_map.put( msg, prev_msg );
+						
+						Object existing = next_map.get( prev_msg );
+						
+						if ( existing == null ){
+							
+							next_map.put( prev_msg, msg );
+							
+						}else if ( existing instanceof ChatMessage ){
+							
+							List<ChatMessage> list = new ArrayList<ChatMessage>();
+							
+							list.add( (ChatMessage)existing );
+							list.add( msg );
+							
+							next_map.put( prev_msg,  list );
+							
+						}else{
+							
+							((List<ChatMessage>)existing).add( msg );
+						}
+					}
+				}
+			}
+			
+				// a comparator to consistently order messages to ensure sorting is determinstic
+			
+			Comparator<ChatMessage> message_comparator = 
+					new Comparator<ChatMessage>()
+					{					
+						public int 
+						compare(
+							ChatMessage o1, 
+							ChatMessage o2 ) 
+						{
+							return( o1.getUID() - o2.getUID());
+						}
+					};
+					
+				// break any loops arbitrarily
+		
+			Set<ChatMessage>	linked_messages = new TreeSet<ChatMessage>(	message_comparator );
+			
+			linked_messages.addAll( prev_map.keySet());
+			
+			while( linked_messages.size() > 0 ){
+				
+				ChatMessage start = linked_messages.iterator().next();
+					
+				linked_messages.remove( start );
+				
+				ChatMessage current = start;
+				
+				int	loops = 0;
+				
+				while( true ){
+				
+					loops++;
+					
+					if ( loops > num_messages ){
+						
+						Debug.out( "infinte loop" );
+						
+						break;
+					}
+					
+					ChatMessage prev_msg = prev_map.get( current );
+					
+					if ( prev_msg == null ){
+						
+						break;
+						
+					}else{
+						
+						linked_messages.remove( prev_msg );
+						
+						if ( prev_msg == start ){
+												
+								// loopage
+							
+							prev_map.put( current, null );
+							next_map.put( prev_msg, null );
+							
+							Debug.out( "Loopage" );
+							
+							break;
+							
+						}else{
+							
+							current = prev_msg;
+						}
+					}
+				}
+				
+			}
+				// find the heads of the various trees
+			
+			Set<ChatMessage>		tree_heads = new TreeSet<ChatMessage>( message_comparator );
+			
+			for ( ChatMessage msg: messages ){
+				
+				ChatMessage prev_msg = prev_map.get( msg );
+				
+				if ( prev_msg != null ){
+					
+					int	 loops = 0;
+					
+					while( true ){
+					
+						loops++;
+						
+						if ( loops > num_messages ){
+							
+							Debug.out( "infinte loop" );
+							
+							break;
+						}
+						
+						ChatMessage prev_prev = prev_map.get( prev_msg );
+						
+						if ( prev_prev == null ){
+							
+							tree_heads.add( prev_msg );
+							
+							break;
+							
+						}else{
+							
+							prev_msg = prev_prev;
+						}
+					}
+				}
+			}
+			
+			// System.out.println( "Got trees: " + tree_heads.size());
+			
+			Set<ChatMessage>	remainder_set = new HashSet<BuddyPluginBeta.ChatMessage>( messages );
+			
+			List<ChatMessage> result = null;
+			
+			for ( ChatMessage head: tree_heads ){
+				
+				List<ChatMessage>	chain = flattenTree( head, next_map, num_messages );
+				
+				remainder_set.removeAll( chain );
+				
+				if ( result == null ){
+					
+					result = chain;
+					
+				}else{
+					
+					result = merge( result, chain );
+				}
+			}
+			
+			if ( remainder_set.size() > 0 ){
+				
+					// these are messages not part of any chain so sort based on time
+				
+				List<ChatMessage>	remainder = new ArrayList<ChatMessage>( remainder_set );
+				
+				Collections.sort(
+						remainder,
+						new Comparator<ChatMessage>()
+						{
+							public int 
+							compare(
+								ChatMessage m1, 
+								ChatMessage m2 ) 
+							{
+								long l = m1.getTimeStamp() - m2.getTimeStamp();
+								
+								if ( l < 0 ){
+									return( -1 );
+								}else if ( l > 0 ){
+									return( 1 );
+								}else{
+									return( m1.getUID() - m2.getUID());
+								}
+							}
+						});
+				
+				if ( result == null ){
+					
+					result = remainder;
+					
+				}else{
+					
+					result = merge( result, remainder );
+				}
+			}
+						
+			if ( result == null ){
+						
+				return( false );
+			}
+			
+			boolean	changed = false;
+
+			if ( messages.size() != result.size()){
+					
+				Debug.out( "Inconsistent: " + messages.size() + "/" + result.size());
+
+				changed = true;
+			}
+					
+			Set<ChatParticipant>	participants = new HashSet<ChatParticipant>();
+			
+			for ( int i=0;i<result.size();i++){
+				
+				ChatMessage msg = result.get(i);
+				
+				ChatParticipant p = msg.getParticipant();
+					
+				participants.add( p );
+				
+				if ( !changed ){
+						
+					if ( messages.get(i) != msg ){
+					
+						// System.out.println( "changed at " + i + ": new = " + msg.getString() + ", old = " + messages.get(i).getString());
+						changed = true;
+					}
+				}
+			}
+				
+			if ( changed ){
+				
+				messages = result;
+				
+				for ( ChatParticipant p: participants ){
+					
+					p.resetMessages();
+				}
+				
+				Set<ChatParticipant>	updated = new HashSet<ChatParticipant>();
+				
+				for ( ChatMessage msg: messages ){
+					
+					ChatParticipant p = msg.getParticipant();
+					
+					if ( p.replayMessage( msg )){
+						
+						updated.add( p );
+					}
+				}
+				
+				for ( ChatParticipant p: updated ){
+					
+					updated( p );
+				}
+			}
+			
+			return( changed );
+		}
+		
+		private List<ChatMessage>
+		flattenTree(
+			ChatMessage					head,
+			Map<ChatMessage,Object>		next_map,
+			int							num_messages )
+		{
+			if ( num_messages <= 0 ){
+				
+					// fail safe in case for some reason we end up in a loop
+				
+				return(  new ArrayList<ChatMessage>());
+			}
+			
+			List<ChatMessage> chain = new ArrayList<ChatMessage>( num_messages );
+
+			ChatMessage msg = head;
+							
+			while( true ){
+								
+				chain.add( msg );
+					
+				num_messages--;
+				
+				Object entry = next_map.get( msg );
+				
+				if ( entry instanceof ChatMessage ){
+					
+					msg = (ChatMessage)entry;
+					
+				}else if ( entry instanceof List ){
+					
+					List<ChatMessage> list = (List<ChatMessage>)entry;
+					
+					List<ChatMessage> current = null;
+										
+					for ( ChatMessage node: list ){
+						
+						List<ChatMessage> temp = flattenTree( node, next_map, num_messages );
+												
+						num_messages -= temp.size();
+						
+						if ( current == null ){
+							
+							current = temp;
+							
+						}else{
+							
+							current = merge( current, temp );
+						}
+					}
+					
+					chain.addAll( current );
+										
+					break;
+					
+				}else{
+					
+					break;
+				}
+			}
+			
+			return( chain );
+		}
+		
+		private List<ChatMessage>
+		merge(
+			List<ChatMessage>		list1,
+			List<ChatMessage>		list2 )
+		{
+			int	size1 = list1.size();
+			int size2 = list2.size();
+			
+			List<ChatMessage>	result = new ArrayList<ChatMessage>( size1 + size2 );
+			
+			int	pos1 = 0;
+			int pos2 = 0;
+						
+			while( true ){
+				
+				if ( pos1 == size1 ){
+					
+					for ( int i=pos2;i<size2;i++){
+						
+						result.add( list2.get(i));
+					}
+					
+					break;
+					
+				}else if ( pos2 == size2 ){
+					
+					for ( int i=pos1;i<size1;i++){
+						
+						result.add( list1.get(i));
+					}
+					
+					break;
+					
+				}else{
+					
+					ChatMessage m1 = list1.get( pos1 );
+					ChatMessage m2 = list2.get( pos2 );
+				
+					long t1 = m1.getTimeStamp();
+					long t2 = m2.getTimeStamp();
+					
+					if ( t1 < t2 || ( t1 == t2 && m1.getUID() < m2.getUID())){
+						
+						result.add( m1 );
+						
+						pos1++;
+						
+					}else{
+						
+						result.add( m2 );
+						
+						pos2++;
+					}
+				}
+			}
+			
+			return( result );
+		}
+		
+		public void
+		messageReceived(
+			Map<String,Object>			message_map )
+			
+			throws IPCException
+		{
+			AESemaphore sem;
+			
+			synchronized( binding_lock ){
+				
+				sem = binding_sem;
+			}
+			
+			if ( sem != null ){
+				
+				sem.reserve();
+			}
+			
+			ChatMessage msg = new ChatMessage( message_uid_next.incrementAndGet(), message_map );
+			
+			long sequence = msg.getSequence();
+						
+			ChatParticipant	new_participant = null;
+				
+			boolean	sort_outstanding = false;
+			
+			byte[]	prev_id 	= msg.getPreviousID();
+						
+			synchronized( chat_lock ){
+				
+				byte[] id = msg.getID();
+				
+				if ( message_ids.containsKey( id )){
+					
+						// duplicate, probably from plugin unload, reload and re-bind
+					
+					return;
+				}
+				
+				message_ids.put( id, "" );
+				
+					// best case is that message belongs at the end
+				
+				int old_msgs = messages.size();
+
+				messages.add( msg );
+						
+				if ( messages.size() > MSG_HISTORY_MAX ){
+					
+					ChatMessage removed = messages.remove(0);
+					
+					old_msgs--;
+					
+					message_ids.remove( removed.getID());
+					
+					ChatParticipant rem_part = removed.getParticipant();
+					
+					rem_part.removeMessage( removed );
+					
+					if ( !rem_part.isMe()){
+						
+						messages_not_mine_count--;
+					}
+				}
+				
+				int origin = msg.getFlagOrigin();
+				
+				if ( origin != FLAGS_MSG_ORIGIN_USER ){
+					
+					String auto_msg = msg.getMessage();
+					
+					if ( auto_msg.contains( "File" )){
+					
+						auto_msg = auto_msg.replace( '\\', '/' );
+					}
+					
+					outer:
+					for ( Pattern p: auto_dup_patterns ){
+					
+						Matcher m = p.matcher( auto_msg );
+					
+						while( m.find()){
+							
+							String dup_key = m.group( 1 );
+							
+							if ( auto_dup_set.containsKey( dup_key )){
+																
+								msg.setDuplicate();
+								
+								break outer;
+							}
+							
+							auto_dup_set.put( dup_key, "" );
+						}
+					}
+				}
+				
+				byte[] pk = msg.getPublicKey();
+				
+				ChatParticipant participant = participants.get( pk );
+								
+				if ( participant == null ){
+					
+					new_participant = participant = new ChatParticipant( this, pk );
+					
+					participants.put( pk, participant );
+										
+					participant.addMessage( msg );
+					
+					if ( auto_mute && !participant.isMe()){
+						
+						participant.setIgnored( true );
+					}
+										
+				}else{
+										
+					participant.addMessage( msg );										
+				}
+					
+				if ( log_messages ){
+					
+					if ( !msg.isIgnored()){
+					
+						logMessage( this, msg );
+					}
+				}
+
+				if ( participant.isMe()){
+					
+					InetSocketAddress address = msg.getAddress();
+					
+					if ( address != null ){
+						
+						my_address = address;
+					}
+					
+					if ( msg.getFlagFlashOverride()){
+					
+						last_message_requiring_attention = msg;
+					}
+				}else{
+					
+					if ( !msg.isIgnored()){
+					
+						last_message_requiring_attention = msg;
+					}
+					
+					messages_not_mine_count++;
+				}
+				
+				if ( sort_event != null ){
+					
+					sort_outstanding = true;
+					
+				}else{
+					
+					if ( old_msgs == 0 ){	
+						
+					}else if ( prev_id != null && Arrays.equals( prev_id, messages.get(old_msgs-1).getID())){
+
+						// in right place already by linkage
+						
+					}else if ( msg.getMessageType() != ChatMessage.MT_NORMAL ){
+
+						// info etc always go last
+						
+					}else{
+						
+						sortMessages( true );
+						
+						sort_outstanding = true;
+					}
+				}
+			}
+			
+			if ( new_participant != null ){
+				
+				for ( ChatListener l: listeners ){
+					
+					l.participantAdded( new_participant );
+				}
+			}
+			
+			for ( ChatListener l: listeners ){
+					
+				l.messageReceived( msg, sort_outstanding );
+			}
+		}
+		
+		public Map<String,Object>
+		chatRequested(
+			Map<String,Object>			message_map )
+			
+			throws IPCException
+		{
+			AESemaphore sem;
+			
+			synchronized( binding_lock ){
+				
+				sem = binding_sem;
+			}
+			
+			if ( sem != null ){
+				
+				sem.reserve();
+			}
+			
+			if ( isStatistics()){
+				
+				throw( new IPCException( "Private chat disabled for statistical channels" ));
+			}
+			
+			if ( private_chat_state == PRIVATE_CHAT_DISABLED ){
+				
+				throw( new IPCException( "Private chat disabled by recipient" ));
+			}
+			
+			try{
+				Object	new_handler 	= message_map.get( "handler" );
+				
+				byte[]	remote_pk 		= (byte[])message_map.get( "pk" );
+				
+				ChatParticipant	participant;
+				
+				synchronized( chat_lock ){
+	
+					participant = participants.get( remote_pk );
+				}
+				
+				if ( participant == null ){
+					
+					throw( new IPCException( "Private chat requires you send at least one message to the main chat first" ));
+				}
+					
+				if ( private_chat_state == PRIVATE_CHAT_PINNED_ONLY && !participant.isPinned()){
+					
+					throw( new IPCException( "Recipient will only accept private chats from pinned participants" ));
+				}
+				
+				BuddyPluginViewInterface ui = plugin.getSWTUI();
+				
+				if ( ui == null ){
+					
+					throw( new IPCException( "Chat unavailable" ));
+				}
+									
+				ChatInstance inst = getChat( participant, new_handler );
+
+				if ( !isSharedNickname()){
+					
+					inst.setSharedNickname( false );
+					
+					inst.setInstanceNickname( getInstanceNickname());
+				}
+				
+				ui.openChat( inst );
+				
+				Map<String,Object>	reply = new HashMap<String, Object>();
+				
+				reply.put( "nickname", participant.getName());
+				
+				return( reply );
+				
+			}catch( IPCException e ){
+				
+				throw( e );
+				
+			}catch( Throwable e ){
+				
+				throw( new IPCException( e ));
+			}
+		}
+		
+		AsyncDispatcher	dispatcher = new AsyncDispatcher( "sendAsync" );
+		
+		public void 
+		sendMessage(
+			final String					message,
+			final Map<String,Object>		options )
+		{
+			sendMessage( message, null, options );
+		}
+		
+		public void 
+		sendMessage(
+			final String					message,
+			final Map<String,Object>		flags,
+			final Map<String,Object>		options )
+		{
+			dispatcher.dispatch(
+				new AERunnable()
+				{
+					
+					@Override
+					public void 
+					runSupport() 
+					{
+						sendMessageSupport( message, flags, options );
+					}
+				});
+		}
+		
+		public void 
+		sendRawMessage(
+			final byte[]					message,
+			final Map<String,Object>		flags,
+			final Map<String,Object>		options )
+		{
+			dispatcher.dispatch(
+				new AERunnable()
+				{
+					
+					@Override
+					public void 
+					runSupport() 
+					{
+						sendMessageSupport( message, flags, options );
+					}
+				});
+		}
+		
+		public void 
+		sendLocalMessage(
+			final String		message,
+			final String[]		args,
+			final int			message_type )
+		{
+			if ( ipc_version < 2 ){
+				
+				return;
+			}
+			
+			dispatcher.dispatch(
+				new AERunnable()
+				{
+					
+					@Override
+					public void 
+					runSupport() 
+					{
+						Map<String,Object>		options = new HashMap<String, Object>();
+						
+						String raw_message;
+						
+						if ( message.startsWith( "!") && message.endsWith( "!" )){
+
+							raw_message = message.substring( 1, message.length() - 1 );
+			
+						}else{
+							
+							raw_message = MessageText.getString( message, args );
+						}
+						options.put( "is_local", true );
+						options.put( "message", raw_message );
+						options.put( "message_type", message_type );
+						
+						sendMessageSupport( "", null, options );
+					}
+				});
+		}
+		
+		public void 
+		sendControlMessage(
+			final String		cmd )
+		{
+			if ( ipc_version < 3 ){
+				
+				return;
+			}
+			
+			dispatcher.dispatch(
+				new AERunnable()
+				{
+					
+					@Override
+					public void 
+					runSupport() 
+					{
+						Map<String,Object>		options = new HashMap<String, Object>();
+						
+						options.put( "is_control", true );
+						options.put( "cmd", cmd );
+						
+						sendMessageSupport( "", null, options );
+					}
+				});
+		}
+		
+		private void 
+		sendMessageSupport(
+			Object					o_message,
+			Map<String,Object>		flags,
+			Map<String,Object>		options )
+		{
+			if ( handler == null || msgsync_pi == null ){
+				
+				Debug.out( "No handler/plugin" );
+				
+			}else{
+				
+				if ( o_message instanceof String ){
+					
+					String message = (String)o_message;
+					
+					if ( message.equals( "!dump!" )){
+						
+						synchronized( chat_lock ){
+							
+							for ( ChatMessage msg: messages ){
+								
+								System.out.println( msg.getTimeStamp() + ": " + pkToString( msg.getID()) + ", " + pkToString( msg.getPreviousID()) + ", " + msg.getSequence() + " - " + msg.getMessage());
+							}
+						}
+						return;
+						
+					}else if ( message.equals( "!sort!" )){
+						
+						sortMessages( false );
+						
+						return;
+						
+					}else if ( message.equals( "!flood!" )){
+						
+						if ( DEBUG_ENABLED ){
+						
+							SimpleTimer.addPeriodicEvent(
+								"flooder",
+								1500,
+								new TimerEventPerformer() {
+									
+									public void perform(TimerEvent event) {
+									
+										sendMessage( "flood - " + SystemTime.getCurrentTime(), null );
+										
+									}
+								});
+						}
+						
+						return;
+						
+		
+					}else if ( message.equals( "!ftux!" )){
+						
+						plugin.getBeta().setFTUXAccepted( false );
+						
+						return;
+					}
+					
+					if ( message.startsWith( "/" )){
+											
+						String[] bits = message.split( "[\\s]+", 3 );
+						
+						String command = bits[0].toLowerCase( Locale.US );
+						
+						boolean	ok = false;
+						
+						try{
+							if ( command.equals( "/help" )){
+								
+								String link = MessageText.getString( "azbuddy.dchat.link.url" );
+								
+								sendLocalMessage( "label.see.x.for.help", new String[]{ link }, ChatMessage.MT_INFO );
+	
+								ok = true;
+								
+							}else if ( command.equals( "/join" )){
+								
+								if ( bits.length > 1 ){
+									
+									bits = message.split( "[\\s]+", 2 );
+									
+									String key = bits[1];
+									
+									if ( key.startsWith( "\"" ) && key.endsWith( "\"" )){
+										key = key.substring(1,key.length()-1);
+									}
+									
+									getAndShowChat( getNetwork(), key );
+									
+									ok = true;
+								}
+							}else if ( command.equals( "/nick" )){
+								
+								if ( bits.length > 1 ){
+
+									bits = message.split( "[\\s]+", 2 );
+									
+									setSharedNickname( false );
+									
+									setInstanceNickname( bits[1]);
+									
+									ok = true;
+								}
+
+							}else if ( command.equals( "/pjoin" )){
+								
+								if ( bits.length > 1 ){
+									
+									bits = message.split( "[\\s]+", 2 );
+									
+									String key = bits[1];
+									
+									if ( key.startsWith( "\"" ) && key.endsWith( "\"" )){
+										key = key.substring(1,key.length()-1);
+									}
+									
+									getAndShowChat( AENetworkClassifier.AT_PUBLIC, key );
+									
+									ok = true;
+								}
+							}else if ( command.equals( "/ajoin" )){
+								
+								if ( bits.length > 1 && isI2PAvailable()){
+									
+									bits = message.split( "[\\s]+", 2 );
+									
+									String key = bits[1];
+									
+									if ( key.startsWith( "\"" ) && key.endsWith( "\"" )){
+										key = key.substring(1,key.length()-1);
+									}
+									
+									getAndShowChat( AENetworkClassifier.AT_I2P, key );
+									
+									ok = true;
+								}
+							}else if ( command.equals( "/msg" ) || command.equals( "/query" )){
+								
+								if ( bits.length > 1 ){
+									
+									String nick = bits[1];
+									
+									String	pm = bits.length ==2?"":bits[2].trim();
+									
+									ChatParticipant p = getParticipant( nick );
+									
+									if ( p == null ){
+										
+										throw( new Exception( "Nick not found: " + nick ));
+										
+									}else if ( p.isMe()){
+										
+										throw( new Exception( "Can't chat to yourself" ));
+									}
+									
+									ChatInstance ci = p.createPrivateChat();
+									
+									if ( pm.length() > 0 ){
+									
+										ci.sendMessage( pm, new HashMap<String, Object>());
+									}
+									
+									showChat( ci );
+									
+									ok = true;
+								}
+							}else if ( command.equals( "/ignore" )){
+								
+								if ( bits.length > 1 ){
+									
+									String nick = bits[1];
+									
+									boolean	ignore = true;
+									
+									if ( nick.equals( "-r" ) && bits.length > 2 ){
+										
+										nick = bits[2];
+										
+										ignore = false;
+									}
+									
+									ChatParticipant p = getParticipant( nick );
+									
+									if ( p == null ){
+										
+										throw( new Exception( "Nick not found: " + nick ));
+									}
+									
+									p.setIgnored( ignore );
+									
+										// obviously the setter should do this but whatever for the mo
+									
+									updated( p );
+									
+									ok = true;
+								}
+								
+							}else if ( command.equals( "/control" )){
+								
+								if ( ipc_version >= 3 ){
+									
+									String[] bits2 = message.split( "[\\s]+", 2 );
+		
+									if ( bits2.length > 1 ){
+										
+										sendControlMessage( bits2[1] );
+										
+										ok = true;
+										
+									}else{
+										
+										throw( new Exception( "Invalid command: " + message ));
+									}
+								}
+								
+							}else if ( command.equals( "/peek" )){
+								
+								if ( bits.length > 1 ){
+									
+									Map<String,Object> result = peekChat( getNetwork(), bits[1] );
+									
+									sendLocalMessage( "!" + result + "!", null, ChatMessage.MT_INFO );
+									
+									ok = true;
+								}
+							}else if ( command.equals( "/clone" )){
+								
+								getAndShowChat( getNetwork(), getKey());
+								
+								ok = true;
+							}
+							
+							if ( !ok ){
+								
+								throw( new Exception( "Unhandled command: " + message ));
+							}
+						}catch( Throwable e ){
+							
+							sendLocalMessage( "!" + Debug.getNestedExceptionMessage( e ) + "!", null, ChatMessage.MT_ERROR );
+						}
+						
+						return;
+					}
+				}
+				
+				try{
+					ChatMessage		prev_message 	= null;
+					long			prev_sequence	= -1;
+					
+					synchronized( chat_lock ){
+						
+						int	pos = messages.size() - 1;
+						
+						int	 missing_seq = 0;
+						
+						while( pos >= 0 ){
+						
+							ChatMessage m = messages.get( pos-- );
+														
+							if ( m.getMessageType() == ChatMessage.MT_NORMAL ){
+							
+								if ( prev_message == null ){
+								
+									prev_message = m;
+								}
+								
+								prev_sequence = m.getSequence();
+							
+								if ( prev_sequence > 0 ){
+																		
+									break;
+									
+								}else{
+									
+									missing_seq++;
+								}
+							}
+						}
+						
+						if ( prev_message != null ){
+															
+							prev_sequence += missing_seq;
+						}
+					}
+					
+					if ( options == null ){
+						
+						options = new HashMap<String, Object>();
+						
+					}else{
+						
+							// clone as we are updating
+						
+						options = new HashMap<String, Object>( options );
+					}
+					
+					options.put( "handler", handler );
+					
+					Map<String,Object>	payload = new HashMap<String, Object>();
+					
+					if ( o_message instanceof String ){
+					
+						payload.put( "msg", ((String)o_message).getBytes( "UTF-8" ));
+						
+					}else{
+						
+						payload.put( "msg", (byte[])o_message );
+					}
+					
+					payload.put( "nick", getNickname().getBytes( "UTF-8" ));
+					
+					if ( prev_message != null ){
+						
+						payload.put( "pre", prev_message.getID());
+						payload.put( "seq", prev_sequence + 1 );
+					}
+					
+					if ( flags != null ){
+						
+						payload.put( "f", flags );
+					}
+					
+					options.put( "content", BEncoder.encode( payload ));
+												
+					Map<String,Object> reply = (Map<String,Object>)msgsync_pi.getIPC().invoke( "sendMessage", new Object[]{ options } );
+					
+						// once we participate in a chat then we want to keep it around to ensure
+						// or at least try and ensure message delivery
+					
+					have_interest = true;
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+		}
+		
+		public String
+		export()
+		{
+			if ( handler == null || msgsync_pi == null ){
+
+				return( "" );
+			}
+			try{
+				Map<String,Object>		options = new HashMap<String, Object>();
+				
+				options.put( "handler", handler );
+	
+				Map<String,Object> reply = (Map<String,Object>)msgsync_pi.getIPC().invoke( "exportMessageHandler", new Object[]{ options } );
+
+				return((String)reply.get( "export_data" ));
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				return( "" );
+			}
+		}
+		
+		public List<ChatMessage>
+		getMessages()
+		{
+			synchronized( chat_lock ){
+
+				return( new ArrayList<ChatMessage>( messages ));
+			}
+		}
+		
+		public ChatParticipant[]
+		getParticipants()
+		{
+			synchronized( chat_lock ){
+				
+				return( participants.values().toArray( new ChatParticipant[ participants.size()]));
+			}
+		}
+		
+		public ChatParticipant
+		getParticipant(
+			String	nick )
+		{
+			synchronized( chat_lock ){
+				
+				for ( ChatParticipant cp: participants.values()){
+					
+					if ( cp.getName().equals( nick )){
+						
+						return( cp );
+					}
+				}
+			}
+			
+			return( null );
+		}
+		
+		protected void
+		updated(
+			ChatParticipant		p )
+		{
+			for ( ChatListener l: listeners ){
+				
+				l.participantChanged( p );
+			}
+		}
+		
+		private void
+		registerNick(
+			ChatParticipant		p,
+			String				old_nick,
+			String				new_nick )
+		{
+			synchronized( chat_lock ){
+				
+				if ( old_nick != null ){
+				
+					List<ChatParticipant> list = nick_clash_map.get( old_nick );
+					
+					if ( list != null && list.remove( p )){
+												
+						if ( list.size() == 0 ){
+							
+							nick_clash_map.remove( old_nick );
+							
+						}else{
+							
+							if ( list.size() == 1 ){
+							
+								list.get(0).setNickClash( false );
+							}
+						}
+					}else{
+						
+						Debug.out( "inconsistent" );
+					}
+				}
+				
+				List<ChatParticipant> list = nick_clash_map.get( new_nick );
+	
+				if ( list == null ){
+					
+					list = new ArrayList<BuddyPluginBeta.ChatParticipant>();
+					
+					nick_clash_map.put( new_nick, list );
+				}
+				
+				if ( list.contains( p )){
+					
+					Debug.out( "inconsistent" );
+					
+				}else{
+					
+					list.add( p );
+					
+					if ( list.size() > 1 ){
+						
+						p.setNickClash( true );
+						
+						if ( list.size() == 2 ){
+							
+							list.get(0).setNickClash( true );
+						}
+					}else{
+						
+						p.setNickClash( false );
+					}
+				}
+			}
+		}
+		
+		public ChatMessage
+		getLastMessageRequiringAttention()
+		{
+			return( last_message_requiring_attention );
+		}
+		
+		public void
+		setUserData(
+			Object		key,
+			Object		value )
+		{
+			synchronized( user_data ){
+				
+				user_data.put( key, value );
+			}
+		}
+		
+		public Object
+		getUserData(
+			Object		key )
+		{
+			synchronized( user_data ){
+				
+				return( user_data.get( key ));
+			}	
+		}
+		
+		public boolean
+		getMessageOutstanding()
+		{
+			synchronized( chat_lock ){
+			
+				return( message_outstanding );
+			}
+		}
+		
+		public void
+		setMessageOutstanding( 
+			boolean		b )
+		{
+			synchronized( chat_lock ){
+			
+				if ( message_outstanding == b ){
+					
+					return;
+				}
+				
+				message_outstanding = b;
+				
+				if ( !b ){
+					
+					if ( messages.size() > 0 ){
+						
+						ChatMessage	last_read_msg = messages.get( messages.size()-1 );
+						
+						long last_read_time = last_read_msg.getTimeStamp();
+						
+						String last_info = (SystemTime.getCurrentTime()/1000) + "/" + (last_read_time/1000) + "/" + Base32.encode( last_read_msg.getID());
+						
+						BuddyPluginBeta.this.setLastMessageInfo( network, key, last_info );
+					}
+				}
+			}
+		}
+		
+		public boolean
+		isOldOutstandingMessage(
+			ChatMessage			msg )
+		{
+			synchronized( chat_lock ){
+				
+				String info = BuddyPluginBeta.this.getLastMessageInfo( network, key );
+				
+				if ( info != null ){
+					
+					String[] bits = info.split( "/" );
+					
+					try{
+						long	old_time_secs 	= Long.parseLong( bits[0] );
+						long	old_msg_secs 	= Long.parseLong( bits[1] );
+						byte[]	old_id			= Base32.decode( bits[2] );
+						
+						long	msg_secs	= msg.getTimeStamp()/1000;
+						byte[]	id			= msg.getID();
+						
+						if ( Arrays.equals( id, old_id )){
+							
+							return( true );
+						}
+						
+						long	old_cuttoff = old_time_secs - 5*60;
+						
+						if ( old_msg_secs > old_cuttoff ){
+							
+							old_cuttoff = old_msg_secs;
+						}
+						
+						if ( msg_secs <= old_cuttoff ){
+							
+							return( true );
+						}
+						
+						if ( message_ids.containsKey( old_id ) && message_ids.containsKey( id )){
+							
+							int	msg_index 		= -1;
+							int old_msg_index 	= -1;
+							
+							for ( int i=0;i<messages.size();i++){
+								
+								ChatMessage m = messages.get(i);
+								
+								if ( m == msg ){
+									
+									msg_index = i;
+									
+								}else if ( Arrays.equals( m.getID(), old_id )){
+									
+									old_msg_index = i;
+								}
+							}
+							
+							if ( msg_index <= old_msg_index ){
+								
+								return( true );
+							}
+						}
+					}catch( Throwable e ){
+						
+					}
+				}
+			}
+			
+			return( false );
+		}
+		
+		public InetSocketAddress
+		getMyAddress()
+		{
+			return( my_address );
+		}
+		
+		public void
+		addListener(
+			ChatListener		listener )
+		{
+			listeners.add( listener );
+		}
+		
+		public void
+		removeListener(
+			ChatListener		listener )
+		{
+			listeners.remove( listener );
+		}
+		
+		public void
+		remove()
+		{
+			destroy( true );
+			
+			removeAllOptions( network, key );
+		}
+		
+		public boolean
+		isDestroyed()
+		{
+			return( destroyed );
+		}
+		
+		public void
+		destroy()
+		{
+			destroy( false );
+		}
+		
+		private void
+		destroy(
+			boolean		force )
+		{
+			synchronized( chat_lock ){
+				
+				if ( force ){
+					
+					reference_count	= 0;
+					keep_alive		= false;
+					have_interest	= false;
+					
+				}else{
+					
+					reference_count--;
+					
+					if ( reference_count > 0 ){
+						
+						return;
+					}
+				}
+			}
+			
+			if ( !( keep_alive || (have_interest && !is_private_chat ))){
+				
+				destroyed = true;
+				
+				if ( handler != null ){
+							
+					if ( is_private_chat ){
+						
+						Map<String,Object>		flags = new HashMap<String, Object>();
+						
+						flags.put( FLAGS_MSG_STATUS_KEY, FLAGS_MSG_STATUS_CHAT_QUIT );
+						
+						sendMessageSupport( "", flags, new HashMap<String, Object>());
+					}
+					
+					try{
+						Map<String,Object>		options = new HashMap<String, Object>();
+						
+						options.put( "handler", handler );
+													
+						Map<String,Object> reply = (Map<String,Object>)msgsync_pi.getIPC().invoke( "removeMessageHandler", new Object[]{ options } );
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+						
+					}finally{
+						
+						String meta_key = network + ":" + key;
+
+						ChatInstance	removed = null;
+						
+						synchronized( chat_instances_map ){
+						
+							ChatInstance inst = chat_instances_map.remove( meta_key );
+							
+							if ( inst != null ){
+								
+								removed = inst;
+								
+								chat_instances_list.remove( inst );
+							}
+							
+							if ( chat_instances_map.size() == 0 ){
+								
+								if ( timer != null ){
+									
+									timer.cancel();
+									
+									timer = null;
+								}
+							}
+						}
+						
+						if ( removed != null ){
+							
+							for ( ChatManagerListener l: BuddyPluginBeta.this.listeners ){
+								
+								try{
+									l.chatRemoved( removed );
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	public class
+	ChatParticipant
+	{
+		private final ChatInstance		chat;
+		private final byte[]			pk;
+		
+		private String				nickname;
+		private boolean				is_ignored;
+		private boolean				is_spammer;
+		private boolean				is_pinned;
+		private boolean				nick_clash;
+		
+		private List<ChatMessage>	participant_messages	= new ArrayList<ChatMessage>();
+		
+		private Boolean				is_me;
+		
+		private
+		ChatParticipant(
+			ChatInstance		_chat,
+			byte[]				_pk )
+		{
+			chat	= _chat;
+			pk		= _pk;
+			
+			nickname = pkToString( pk );
+			
+			is_pinned = COConfigurationManager.getBooleanParameter( getPinKey(), false );
+			
+			chat.registerNick( this, null, nickname );
+		}
+		
+		public ChatInstance
+		getChat()
+		{
+			return( chat );
+		}
+	
+		public byte[]
+		getPublicKey()
+		{
+			return( pk );
+		}
+		
+		public Map<String,Object>
+		getContact()
+		{
+			synchronized( chat.chat_lock ){
+			
+				if ( participant_messages.isEmpty()){
+					
+					return( null );
+				}
+
+				return( participant_messages.get( participant_messages.size()-1).getContact());
+			}
+		}
+		
+		public InetSocketAddress
+		getAddress()
+		{
+			synchronized( chat.chat_lock ){
+			
+				if ( participant_messages.isEmpty()){
+					
+					return( null );
+				}
+				
+				return( participant_messages.get( participant_messages.size()-1).getAddress());
+			}
+		}
+		
+		public boolean
+		isMe()
+		{
+			if ( is_me != null ){
+				
+				return( is_me );
+			}
+			
+			byte[] chat_key = chat.getPublicKey();
+			
+			if ( chat_key != null ){
+			
+				is_me = Arrays.equals( pk, chat_key );
+			}
+			
+			return( is_me==null?false:is_me );
+		}
+		
+		public String
+		getName()
+		{
+			return( getName( true ));
+		}
+		
+		public String
+		getName(
+			boolean	use_nick )
+		{
+			if ( use_nick ){
+				
+				return( nickname );
+				
+			}else{
+				
+				return( pkToString( pk ));
+			}
+		}
+		
+		public boolean
+		hasNickname()
+		{
+			return( !nickname.equals( pkToString( pk )));
+		}
+		
+		private void
+		addMessage(
+			ChatMessage		message )
+		{
+			participant_messages.add( message );
+			
+			message.setParticipant( this );
+			
+			message.setIgnored( is_ignored || is_spammer );
+			
+			String new_nickname = message.getNickName();
+			
+			if ( !nickname.equals( new_nickname )){
+			
+				chat.registerNick( this, nickname, new_nickname );
+
+				message.setNickClash( isNickClash());
+				
+				nickname = new_nickname;
+								
+				chat.updated( this );
+				
+			}else{
+				
+				message.setNickClash( isNickClash());
+			}
+		}
+		
+		private boolean
+		replayMessage(
+			ChatMessage		message )
+		{
+			participant_messages.add( message );
+						
+			message.setIgnored( is_ignored || is_spammer );
+
+			String new_nickname = message.getNickName();
+			
+			if ( !nickname.equals( new_nickname )){
+			
+				chat.registerNick( this, nickname, new_nickname );
+
+				message.setNickClash( isNickClash());
+				
+				nickname = new_nickname;
+								
+				return( true );
+				
+			}else{
+				
+				message.setNickClash( isNickClash());
+				
+				return( false );
+			}
+		}
+		
+		private void
+		removeMessage(
+			ChatMessage		message )
+		{
+			participant_messages.remove( message );
+		}
+		
+		private void
+		resetMessages()
+		{
+			String new_nickname = pkToString( pk );
+			
+			if ( !nickname.equals( new_nickname )){
+				
+				chat.registerNick( this, nickname, new_nickname );
+
+				nickname = new_nickname;
+			}
+			
+			participant_messages.clear();
+		}
+		
+		public List<ChatMessage>
+		getMessages()
+		{
+			synchronized( chat.chat_lock ){
+				
+				return( new ArrayList<ChatMessage>( participant_messages ));
+			}
+		}
+		
+		public boolean
+		isIgnored()
+		{
+			return( is_ignored );
+		}
+		
+		public void
+		setIgnored(
+			boolean		b )
+		{
+			if ( b != is_ignored ){
+				
+				is_ignored = b;
+				
+				synchronized( chat.chat_lock ){
+
+					for ( ChatMessage message: participant_messages ){
+						
+						message.setIgnored( b || is_spammer);
+					}
+				}
+			}
+		}
+		
+		public boolean
+		isSpammer()
+		{
+			return( is_spammer );
+		}
+		
+		public boolean
+		canSpammer()
+		{
+			return( participant_messages.size() >= 5 && !is_spammer );
+		}
+		
+		public void
+		setSpammer(
+			boolean		b )
+		{
+			if ( b != is_spammer ){
+				
+				is_spammer = b;
+				
+				chat.setSpammer( this, b );
+
+				synchronized( chat.chat_lock ){
+
+					for ( ChatMessage message: participant_messages ){
+						
+						message.setIgnored( b || is_ignored );
+					}
+				}
+			}
+		}
+		
+		public boolean
+		isPinned()
+		{
+			return( is_pinned );
+		}
+		
+		private String
+		getPinKey()
+		{
+			return( "azbuddy.chat.pinned." + ByteFormatter.encodeString( pk, 0, 16 ));
+		}
+		
+		public void
+		setPinned(
+			boolean		b )
+		{
+			if ( b != is_pinned ){
+			
+				is_pinned = b;
+				
+				String key = getPinKey();
+				
+				if ( is_pinned ){
+				
+					COConfigurationManager.setParameter( key, true );
+					
+				}else{
+				
+					COConfigurationManager.removeParameter( key );
+				}
+				
+				COConfigurationManager.setDirty();
+			}
+		}
+		
+		public boolean
+		isNickClash()
+		{
+			return( nick_clash );
+		}
+		
+		private void
+		setNickClash(
+			boolean	b )
+		{
+			nick_clash = b;
+		}
+		
+		public ChatInstance
+		createPrivateChat()
+		
+			throws Exception
+		{			
+			ChatInstance inst = BuddyPluginBeta.this.getChat( this );
+			
+			ChatInstance	parent = getChat();
+			
+			if ( !parent.isSharedNickname()){
+				
+				inst.setSharedNickname( false );
+				
+				inst.setInstanceNickname( parent.getInstanceNickname());
+			}
+
+			return( inst );
+		}
+	}
+	
+	public class
+	ChatMessage
+	{
+		public static final int MT_NORMAL	= 1;
+		public static final int MT_INFO		= 2;
+		public static final int MT_ERROR	= 3;
+		
+		private final int						uid;
+		private final Map<String,Object>		map;
+		
+		private WeakReference<Map<String,Object>>	payload_ref;
+		
+		private final byte[]					message_id;
+		private final long						timestamp;
+
+		private ChatParticipant					participant;
+
+		private byte[]							previous_id;
+		private long							sequence;
+		
+		private boolean							is_ignored;
+		private boolean							is_duplicate;
+		private boolean							is_nick_clash;
+		
+		private
+		ChatMessage(
+			int						_uid,
+			Map<String,Object>		_map )
+		{
+			uid		= _uid;
+			map		= _map;
+			
+			message_id = (byte[])map.get( "id" );
+			
+			timestamp = SystemTime.getCurrentTime() - getAgeWhenReceived()*1000L;
+
+			Map<String,Object> payload = getPayload();
+			
+			previous_id = (byte[])payload.get( "pre" );
+			
+			Number	l_seq = (Number)payload.get( "seq" );
+			
+			sequence = l_seq==null?0:l_seq.longValue();
+		}
+		
+		protected int
+		getUID()
+		{
+			return( uid );
+		}
+		
+		private void
+		setParticipant(
+			ChatParticipant		p )
+		{
+			participant	= p;
+		}
+		
+		public ChatParticipant
+		getParticipant()
+		{
+			return( participant );
+		}
+		
+		private void
+		setNickClash(
+			boolean	clash )
+		{
+			is_nick_clash = clash;
+		}
+		
+		public boolean
+		isNickClash()
+		{
+			return( is_nick_clash );
+		}
+		
+		private Map<String,Object>
+		getPayload()
+		{
+			synchronized( this ){
+				
+				Map<String,Object> payload = null;
+				
+				if ( payload_ref != null ){
+					
+					payload = payload_ref.get();
+					
+					if ( payload != null ){
+						
+						return( payload );
+					}
+				}
+			
+				try{
+					byte[] content_bytes = (byte[])map.get( "content" );
+					
+					if ( content_bytes != null && content_bytes.length > 0 ){
+						
+						payload = BDecoder.decode( content_bytes );
+					}
+				}catch( Throwable e){
+				}
+				
+				if ( payload == null ){
+					
+					payload = new HashMap<String, Object>();
+				}
+				
+				payload_ref = new WeakReference<Map<String,Object>>( payload );
+				
+				return( payload );
+			}
+		}
+		
+		private int
+		getMessageStatus()
+		{
+			Map<String,Object> payload = getPayload();
+
+			if ( payload != null ){
+				
+				Map<String,Object>	flags = (Map<String,Object>)payload.get( "f" );
+				
+				if ( flags != null ){
+					
+					Number status = (Number)flags.get( FLAGS_MSG_STATUS_KEY );
+					
+					if ( status != null ){
+						
+						return( status.intValue());
+					}
+				}
+			}
+			
+			return( FLAGS_MSG_STATUS_CHAT_NONE );
+		}
+		
+		private boolean
+		getFlagFlashOverride()
+		{
+			Map<String,Object> payload = getPayload();
+
+			if ( payload != null ){
+				
+				Map<String,Object>	flags = (Map<String,Object>)payload.get( "f" );
+				
+				if ( flags != null ){
+					
+					Number override = (Number)flags.get( FLAGS_MSG_FLASH_OVERRIDE );
+					
+					if ( override != null ){
+						
+						return( override.intValue() != 0 );
+					}
+				}
+			}
+			
+			return( false );
+		}
+		
+		public int
+		getFlagOrigin()
+		{
+			Map<String,Object> payload = getPayload();
+
+			if ( payload != null ){
+				
+				Map<String,Object>	flags = (Map<String,Object>)payload.get( "f" );
+				
+				if ( flags != null ){
+					
+					Number origin = (Number)flags.get( FLAGS_MSG_ORIGIN_KEY );
+					
+					if ( origin != null ){
+						
+						return( origin.intValue());
+					}
+				}
+			}
+			
+			return( FLAGS_MSG_ORIGIN_USER );
+		}
+		
+		public String
+		getMessage()
+		{
+			try{
+				String	report = (String)map.get( "error" );
+				
+				if ( report != null ){
+					
+					if ( report.length() > 2 && report.charAt(1) == ':' ){
+						
+						return( report.substring( 2 ));
+					}
+					
+					return( report );
+				}
+				
+				if ( getMessageStatus() == FLAGS_MSG_STATUS_CHAT_QUIT ){
+					
+					return( participant.getName() + " has quit" );
+				}
+				
+					// was just a string for a while...
+				
+				Map<String,Object> payload = getPayload();
+					
+				if ( payload != null ){
+					
+					byte[] msg_bytes = (byte[])payload.get( "msg" );
+					
+					if ( msg_bytes != null ){
+					
+						return( new String( msg_bytes, "UTF-8" ));
+					}
+				}
+				
+				
+				
+				return( new String((byte[])map.get( "content" ), "UTF-8" ));
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+					
+				return( "" );
+			}
+		}
+		
+		public byte[]
+		getRawMessage()
+		{
+			try{
+				String	report = (String)map.get( "error" );
+				
+				if ( report != null ){
+					
+					return( null );
+				}
+				
+				if ( getMessageStatus() == FLAGS_MSG_STATUS_CHAT_QUIT ){
+					
+					return( null );
+				}
+				
+					// was just a string for a while...
+				
+				Map<String,Object> payload = getPayload();
+					
+				if ( payload != null ){
+					
+					byte[] msg_bytes = (byte[])payload.get( "msg" );
+					
+					if ( msg_bytes != null ){
+					
+						return( msg_bytes );
+					}
+				}
+				
+				return( (byte[])map.get( "content" ));
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+					
+				return( null );
+			}
+		}
+		
+		public int
+		getMessageType()
+		{
+			String	report = (String)map.get( "error" );
+			
+			if ( report == null ){
+				
+				if ( getMessageStatus() == FLAGS_MSG_STATUS_CHAT_QUIT ){
+					
+					return( MT_INFO );
+				}
+				
+				return( MT_NORMAL );
+				
+			}else{
+				
+				if ( report.length() < 2 || report.charAt(1) != ':' ){
+					
+					return( MT_ERROR );
+				}
+								
+				char type = report.charAt(0);
+				
+				if ( type == 'i' ){
+					
+					return( MT_INFO );
+				}else{
+					
+					return( MT_ERROR );
+				}
+			}
+		}
+		
+		public void
+		setDuplicate()
+		{
+			is_duplicate	= true;
+		}
+		
+		public boolean
+		isIgnored()
+		{
+			return( is_duplicate || is_ignored );
+		}
+		
+		public void
+		setIgnored(
+			boolean		b )
+		{
+			is_ignored = b;
+		}
+		
+		public byte[]
+		getID()
+		{
+			return( message_id );
+		}
+		
+		public byte[]
+		getPreviousID()
+		{
+			return( previous_id );
+		}
+		
+		private void
+		setPreviousID(
+			byte[]		pid )
+		{
+			previous_id = pid;
+		}
+		
+		public long
+		getSequence()
+		{
+			return( sequence );
+		}
+		
+		public byte[]
+		getPublicKey()
+		{
+			return((byte[])map.get( "pk" ));
+		}
+		
+		public Map<String,Object>
+		getContact()
+		{
+			return((Map<String,Object>)map.get( "contact" ));
+		}
+		
+		public InetSocketAddress
+		getAddress()
+		{
+			return((InetSocketAddress)map.get( "address" ));
+		}
+		
+		private int
+		getAgeWhenReceived()
+		{
+			return(((Number)map.get( "age" )).intValue());
+		}
+		
+		public long
+		getTimeStamp()
+		{
+			return( timestamp );
+		}
+		
+		public String
+		getNickName()
+		{		
+				// always use payload if available (for real messages)
+			
+			Map<String,Object> payload = getPayload();
+			
+			if ( payload != null ){
+				
+				byte[] nick = (byte[])payload.get( "nick" );
+				
+				if ( nick != null ){
+					
+					try{
+						String str = new String( nick, "UTF-8" );
+						
+						if ( str.length() > 0 ){
+						
+							return( str );
+						}
+					}catch( Throwable e ){
+					}
+				}
+			}
+			
+				// otherwise assume it is internally generated for non-normal messages
+			
+			if ( getMessageType() != ChatMessage.MT_NORMAL ){
+				
+				String nick = participant.getChat().getNickname();
+				
+				if ( nick.length() > 0 ){
+					
+					return( nick );
+				}
+			}
+
+				// default when no user specified one present
+			
+			return( pkToString( getPublicKey()));
+		}
+		
+		public String
+		getString()
+		{
+			return( "a=" + new SimpleDateFormat( "D HH:mm:ss" ).format( getTimeStamp()) + ", i=" + pkToString( message_id ) + ", p=" + pkToString( previous_id ) + ": " + getMessage());
+		}
+	}
+	
+	public interface
+	ChatManagerListener
+	{
+		public void
+		chatAdded(
+			ChatInstance	inst );
+		
+		public void
+		chatRemoved(
+			ChatInstance	inst );
+	}
+	
+	public interface
+	ChatListener
+	{
+		public void
+		messageReceived(
+			ChatMessage				message,
+			boolean					sort_outstanding );
+		
+		public void
+		messagesChanged();
+		
+		public void
+		participantAdded(
+			ChatParticipant			participant );
+		
+		public void
+		participantChanged(
+			ChatParticipant			participant );
+		
+		public void
+		participantRemoved(
+			ChatParticipant			participant );
+		
+		public void
+		stateChanged(
+			boolean					avail );
+		
+		public void
+		updated();
+	}
+	
+	public static class
+	ChatAdapter
+		implements ChatListener
+	{
+		public void 
+		updated() 
+		{
+		}
+		
+		public void 
+		stateChanged(
+			boolean avail ) 
+		{
+		}
+		
+		public void 
+		participantRemoved(
+			ChatParticipant participant) 
+		{			
+		}
+		
+		public void 
+		participantChanged(
+			ChatParticipant participant) 
+		{
+		}
+		
+		public void 
+		participantAdded(
+			ChatParticipant participant) 
+		{
+		}
+		
+		public void 
+		messagesChanged() 
+		{
+		}
+		
+		public void 
+		messageReceived(
+			ChatMessage 	message,
+			boolean			sort_outstanding )
+		{
+		}	
+	}
+	
+	public interface
+	FTUXStateChangeListener
+	{
+		public void
+		stateChanged(
+			boolean	accepted );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddy.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddy.java
index 797e3db..1c502b3 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddy.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddy.java
@@ -1,3449 +1,3448 @@
-/*
- * Created on Apr 1, 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.plugins.net.buddy;
-
-import java.io.File;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.util.*;
-
-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.AddressUtils;
-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.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;
-import org.gudy.azureus2.plugins.messaging.generic.GenericMessageConnectionListener;
-import org.gudy.azureus2.plugins.messaging.generic.GenericMessageEndpoint;
-import org.gudy.azureus2.plugins.messaging.generic.GenericMessageRegistration;
-import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
-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 com.aelitis.azureus.core.util.AZ3Functions;
-
-
-public class 
-BuddyPluginBuddy 
-{
-	private static final boolean TRACE = BuddyPlugin.TRACE;
-	
-	private static final int CONNECTION_IDLE_TIMEOUT	= 5*60*1000;
-	private static final int CONNECTION_KEEP_ALIVE		= 1*60*1000;
-	
-	private static final int MAX_ACTIVE_CONNECTIONS		= 5;
-	private static final int MAX_QUEUED_MESSAGES		= 256;
-	
-	private static final int RT_REQUEST_DATA	= 1;
-	
-	private static final int RT_REPLY_DATA		= 2;	
-	private static final int RT_REPLY_ERROR		= 99;
-
-	
-	private BuddyPlugin		plugin;
-	private long			created_time;
-	private int				subsystem;
-	private boolean			authorised;
-	private String			public_key;
-	private String			nick_name;
-	private List<Long>		recent_ygm;
-	
-	private int				last_status_seq;
-	
-	private long			post_time;
-	private InetAddress		ip;
-	private int				tcp_port;
-	private int				udp_port;
-	private int				online_status	= BuddyPlugin.STATUS_ONLINE;	// default
-		
-	private int				version		= BuddyPlugin.VERSION_CHAT;	// assume everyone now supports chat
-	
-	private boolean			online;
-	private long			last_time_online;
-	
-	private long			status_check_count;
-	private long			last_status_check_time;
-	
-	private boolean			check_active;
-		
-	private List<buddyConnection>		connections	= new ArrayList<buddyConnection>();
-	private List<buddyMessage>			messages	= new ArrayList<buddyMessage>();
-	private buddyMessage				current_message;
-	
-	private int	next_connection_id;
-	private int	next_message_id;
-	
-	private boolean	ygm_active;
-	private boolean	ygm_pending;
-	
-	private long 	latest_ygm_time;
-	private String	last_message_received;
-	
-	private Set<Long>		offline_seq_set;
-	
-	private int		message_out_count;
-	private int		message_in_count;
-	private int		message_out_bytes;
-	private int		message_in_bytes;
-	
-	private String	received_frag_details = "";
-	
-	private BuddyPluginBuddyMessageHandler		persistent_msg_handler;
-
-	private Map<Object,Object>		user_data = new LightHashMap<Object,Object>();
-	
-	private boolean	keep_alive_outstanding;
-	private volatile long	last_connect_attempt	= SystemTime.getCurrentTime();
-	private volatile int	consec_connect_fails;
-	
-	private long last_auto_reconnect	= -1;
-	
-	private Object				rss_lock = new Object();
-	
-	private Set<String>			rss_local_cats;
-	private Set<String>			rss_remote_cats;
-	private Set<String>			rss_cats_read;
-	
-	private AESemaphore			outgoing_connect_sem = new AESemaphore( "BPB:outcon", 1 );
-	
-	private volatile boolean	closing;
-	private volatile boolean	destroyed;
-	
-	protected
-	BuddyPluginBuddy(
-		BuddyPlugin	_plugin,
-		long		_created_time,
-		int			_subsystem,
-		boolean		_authorised,
-		String		_pk,
-		String		_nick_name,
-		int			_version,
-		String		_rss_local_cats,
-		String		_rss_remote_cats,
-		int			_last_status_seq,
-		long		_last_time_online,
-		List<Long>	_recent_ygm )
-	{
-		plugin				= _plugin;
-		created_time		= _created_time;
-		subsystem			= _subsystem;
-		authorised			= _authorised;
-		public_key 			= _pk;
-		nick_name			= _nick_name;
-		version				= Math.max( version, _version );
-		rss_local_cats		= stringToCats( _rss_local_cats );
-		rss_remote_cats		= stringToCats( _rss_remote_cats );
-		last_status_seq		= _last_status_seq;
-		last_time_online	= _last_time_online;
-		recent_ygm			= _recent_ygm;
-		
-		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()
-	{
-		return( plugin );
-	}
-	
-	public BuddyPluginBuddyMessageHandler
-	getMessageHandler()
-	{
-		return( persistent_msg_handler );
-	}
-	
-	protected void
-	persistentDispatchPending()
-	{
-		plugin.persistentDispatchPending( this );
-	}
-	
-	protected void
-	checkPersistentDispatch()
-	{
-		persistent_msg_handler.checkPersistentDispatch();
-	}
-	
-	protected void
-	persistentDispatch()
-	{
-		persistent_msg_handler.persistentDispatch();
-	}
-	
-	public Map
-	readConfigFile(
-		File		name )
-	{
-		return( plugin.readConfigFile( name ));
-	}
-	
-	public boolean
-	writeConfigFile(
-		File		name,
-		Map			data )
-	{
-		return( plugin.writeConfigFile( name, data ));
-	}
-	
-	protected long
-	getCreatedTime()
-	{
-		return( created_time );
-	}
-	
-	public int
-	getSubsystem()
-	{
-		return( subsystem );
-	}
-	
-	protected void
-	setSubsystem(
-		int		_s )
-	{
-		subsystem = _s;
-	}
-	
-	public boolean
-	isAuthorised()
-	{
-		return( authorised );
-	}
-	
-	protected void
-	setAuthorised(
-		boolean		_a )
-	{
-		authorised = _a;
-	}
-	
-	public String
-	getPublicKey()
-	{
-		return( public_key );
-	}
-	
-	protected byte[]
-	getRawPublicKey()
-	{
-		return( Base32.decode( public_key ));
-	}
-	
-	protected String
-	getShortString()
-	{
-		return( public_key.substring( 0, 16 ) + "..." );
-	}
-	
-	public String
-	getNickName()
-	{
-		return( nick_name );
-	}
-	
-	public int
-	getVersion()
-	{
-		return( version );
-	}
-	
-	protected void
-	setVersion(
-		int		v )
-	{
-		if ( version < v ){
-			
-			version = v;
-			
-			plugin.fireDetailsChanged( this );
-		}
-	}
-	
-	public String
-	getLocalAuthorisedRSSCategoriesAsString()
-	{
-		synchronized( rss_lock ){
-		
-			return( catsToString( rss_local_cats ));
-		}
-	}
-	
-	public Set<String>
-  	getLocalAuthorisedRSSCategories()
-  	{
-		synchronized( rss_lock ){
-  		
-			return( rss_local_cats );
-		}
-  	}
-	
-	public void
-	addLocalAuthorisedRSSCategory(
-		String	category )
-	{
-		category = plugin.normaliseCat( category );
-	
-		boolean dirty;
-		
-		synchronized( rss_lock ){
-			
-			if ( rss_local_cats == null ){
-				
-				rss_local_cats = new HashSet<String>();
-			}
-			
-			if ( dirty = !rss_local_cats.contains( category )){
-							
-				rss_local_cats.add( category );
-			}
-		}
-		
-		if ( dirty ){
-			
-			plugin.setConfigDirty();
-			
-			plugin.fireDetailsChanged( this );
-			
-				// tell buddy of change
-			
-			if ( isConnected()){
-				
-				sendKeepAlive();
-			}
-		}
-	}
-	
-	public void
-	removeLocalAuthorisedRSSCategory(
-		String	category )
-	{
-		category = plugin.normaliseCat( category );
-		
-		boolean	dirty;
-		
-		synchronized( rss_lock ){
-			
-			if ( rss_local_cats == null ){
-			
-				return;
-			
-			}else{
-		
-				dirty = rss_local_cats.remove( category );
-			}
-		}
-		
-		if ( dirty ){
-			
-			plugin.setConfigDirty();
-		
-			plugin.fireDetailsChanged( this );
-			
-				// tell buddy of change
-			
-			if ( isConnected()){
-				
-				sendKeepAlive();
-			}
-		}
-	}
-	
-	public void
-	setLocalAuthorisedRSSCategories(
-		String			new_cats )
-	{
-		setLocalAuthorisedRSSCategories( stringToCats( new_cats ));
-	}
-	
-	public void
-	setLocalAuthorisedRSSCategories(
-		Set<String>		new_cats )
-	{	
-		plugin.normaliseCats( new_cats );
-		
-		boolean dirty;
-		
-		synchronized( rss_lock ){
-			
-			if ( dirty = !catsIdentical( new_cats, rss_local_cats) ){
-			
-				rss_local_cats = new_cats;
-			}
-		}
-		
-		if ( dirty ){
-			
-			plugin.setConfigDirty();
-			
-			plugin.fireDetailsChanged( this );
-			
-				// tell buddy of change
-			
-			if ( isConnected()){
-				
-				sendKeepAlive();
-			}
-		}	
-	}
-	
-	public Set<String>
-  	getRemoteAuthorisedRSSCategories()
-  	{
-  		return( rss_remote_cats );
-  	}
-	
-	public String
-	getRemoteAuthorisedRSSCategoriesAsString()
-	{
-		return( catsToString( rss_remote_cats ));
-	}
-	
-	protected void
-	setRemoteAuthorisedRSSCategories(
-		Set<String>		new_cats )
-	{
-		plugin.normaliseCats( new_cats );
-		
-		boolean	dirty;
-		
-		synchronized( rss_lock ){
-			
-			if ( dirty = !catsIdentical( new_cats, rss_remote_cats) ){
-			
-				rss_remote_cats = new_cats;
-			}
-		}
-		
-		if ( dirty ){
-			
-			plugin.setConfigDirty();
-			 
-			plugin.fireDetailsChanged( this );
-		}
-	}
-	
-	public boolean
-	isLocalRSSCategoryAuthorised(
-		String	category )
-	{
-		category = plugin.normaliseCat( category );
-	
-		synchronized( rss_lock ){
-			
-			if ( rss_local_cats != null ){
-			
-				return( rss_local_cats.contains( category ));
-			}
-		
-			return( false );
-		}
-	}
-	
-	public boolean
-	isRemoteRSSCategoryAuthorised(
-		String	category )
-	{
-		category = plugin.normaliseCat( category );
-		
-		synchronized( rss_lock ){
-			
-			if ( rss_remote_cats != null ){
-			
-				return( rss_remote_cats.contains( category ));
-			}
-			
-			return( false );
-		}
-	}
-	
-	protected void
-	localRSSCategoryRead(
-		String		str )
-	{
-		boolean dirty;
-		
-		synchronized( rss_lock ){
-			
-			if ( rss_cats_read == null ){
-				
-				rss_cats_read = new HashSet<String>();
-			}
-			
-			dirty = rss_cats_read.add( str );
-		}
-		
-		if ( dirty ){
-			
-			// not persisted currently - plugin.setConfigDirty();
-			 
-			plugin.fireDetailsChanged( this );
-		}
-	}
-	
-	public String
-	getLocalReadCategoriesAsString()
-	{
-		synchronized( rss_lock ){
-
-			return( catsToString( rss_cats_read ));
-		}
-	}
-	
-	public URL
-	getSubscriptionURL(
-		String		cat )
-	{
-		String url = "azplug:?id=azbuddy&name=Friends&arg=";
-		
-		String arg = "pk=" + getPublicKey() + "&cat=" + cat;
-
-		try{
-			url += URLEncoder.encode( arg, "UTF-8" );
-			
-			return( new URL( url ));
-			
-		}catch( Throwable e ){
-	
-			Debug.out( e );
-			
-			return( null );
-		}
-	}
-	
-	public void
-	subscribeToCategory(
-		String	cat )
-	
-		throws BuddyPluginException
-	{
-		AZ3Functions.provider az3 = AZ3Functions.getProvider();
-
-		if ( az3 == null ){
-			
-			throw( new BuddyPluginException( "AZ3 subsystem not available" ));
-		}
-		
-		try{
-			az3.subscribeToRSS( 
-				getName() + ": " + cat, 
-				getSubscriptionURL(cat),
-				15,
-				false,
-				getPublicKey() + ":" + cat );
-				
-		}catch( Throwable e ){
-				
-			throw( new BuddyPluginException( "Failed to add subscription", e ));
-		}
-	}
-	
-	public boolean
-	isSubscribedToCategory(
-		String	cat,
-		String	creator_ref )
-	{
-		if ( creator_ref == null ){
-			
-			return( false );
-		}
-		
-		return( creator_ref.equals( getPublicKey() + ":" + cat ));
-	}
-	
-	protected String
-	catsToString(
-		Set<String>	cats )
-	{
-		if ( cats == null || cats.size() == 0 ){
-			
-			return( null );
-		}
-		
-		String	str = "";
-		
-		for (String s:cats ){
-			
-			str += (str.length()==0?"":",") + s;
-		}
-		
-		return( str );
-	}
-	
-	protected boolean
-	catsIdentical(
-		Set<String>	c1,
-		Set<String>	c2 )
-	{
-		if ( c1 == null && c2 == null ){
-			
-			return( true );
-			
-		}else if ( c1 == null || c2 == null ){
-			
-			return( false );
-			
-		}else{
-			
-			return( c1.equals( c2 ));
-		}
-	}
-	
-	protected Set<String>
-	stringToCats(
-		String	str )
-	{
-		if ( str == null ){
-			
-			return( null );
-		}
-		
-		String[] bits = str.split( "," );
-		
-		Set<String> res = new HashSet<String>( bits.length );
-		
-		for ( String b: bits ){
-			
-			b = b.trim();
-			
-			if ( b.length() > 0 ){
-				
-				res.add( b );
-			}
-		}
-		
-		if ( res.size() == 0 ){
-			
-			return( null );
-		}
-		
-		return( res );
-	}
-	
-	public int
-	getOnlineStatus()
-	{
-		return( online_status );
-	}
-	
-	protected void
-	setOnlineStatus(
-		int		s )
-	{
-		if ( online_status != s ){
-			
-			online_status = s;
-			
-			plugin.fireDetailsChanged( this );
-		}
-	}
-	
-	public String
-	getName()
-	{
-		if ( nick_name != null ){
-			
-			return( nick_name );
-		}
-		
-		return( getShortString());
-	}
-	
-	public void
-	remove()
-	{
-		persistent_msg_handler.destroy();
-		
-		plugin.removeBuddy( this );
-	}
-	
-	public InetAddress
-	getIP()
-	{
-		return( ip );
-	}
-	
-	public InetAddress
-	getAdjustedIP()
-	{
-		if ( ip == null ){
-			
-			return( null );
-		}
-		
-		InetSocketAddress address = new InetSocketAddress( ip, tcp_port );
-		
-		InetSocketAddress adjusted_address = AddressUtils.adjustTCPAddress( address, true );
-		
-		if ( adjusted_address != address ){
-			
-			return( adjusted_address.getAddress());
-		}
-		
-		address = new InetSocketAddress( ip, udp_port );
-		
-		adjusted_address = AddressUtils.adjustUDPAddress( address, true );
-		
-		if ( adjusted_address != address ){
-			
-			return( adjusted_address.getAddress());
-		}
-	
-		return( ip );
-	}
-	
-	public List
-	getAdjustedIPs()
-	{
-		List	result = new ArrayList();
-		
-		if ( ip == null ){
-			
-			return( result );
-		}
-		
-		InetAddress adjusted = getAdjustedIP();
-		
-		if ( adjusted == ip ){
-			
-			result.add( ip );
-			
-		}else{
-			
-			List l = AddressUtils.getLANAddresses( adjusted.getHostAddress());
-			
-			for (int i=0;i<l.size();i++){
-				
-				try{
-					result.add( InetAddress.getByName((String)l.get(i)));
-					
-				}catch( Throwable e ){
-					
-				}
-			}
-		}
-		
-		return( result );
-	}
-
-	
-	public int
-	getTCPPort()
-	{
-		return( tcp_port );
-	}
-	
-	public int
-	getUDPPort()
-	{
-		return( udp_port );
-	}
-	
-	public boolean
-	isOnline(
-		boolean	is_connected )
-	{
-		boolean	connected = isConnected();
-		
-			// if we're connected then we're online whatever
-		
-		if ( connected ){
-			
-			return( true );
-		}
-		
-		if ( !online ){
-			
-			return( false );
-		}
-	
-		if ( is_connected ){
-		
-			return( false );
-			
-		}else{
-			
-			return( true );
-		}
-	}
-	
-	protected boolean
-	isIdle()
-	{
-		synchronized( this ){
-		
-			return( connections.size() == 0 );
-		}
-	}
-	
-	public long
-	getLastTimeOnline()
-	{
-		return( last_time_online );
-	}
-	
-	public BuddyPlugin.cryptoResult
-	encrypt(
-		byte[]		payload )
-	
-		throws BuddyPluginException
-	{
-		return( plugin.encrypt( this, payload ));
-	}
-	
-	public BuddyPlugin.cryptoResult
-	decrypt(
-		byte[]		payload )
-	
-		throws BuddyPluginException
-	{
-		return( plugin.decrypt( this, payload, getName() ));
-	}
-	
-	public boolean
-	verify(
-		byte[]		payload,
-		byte[]		signature )
-	
-		throws BuddyPluginException
-	{
-		
-		return( plugin.verify( this, payload, signature ));
-	}
-	
-	public BuddyPluginBuddyMessage
-	storeMessage(
-		int		type,
-		Map		msg )
-	{
-		return( persistent_msg_handler.storeExplicitMessage( type, msg ));
-	}
-	
-	public List<BuddyPluginBuddyMessage>
-	retrieveMessages(
-		int		type )
-	{
-		return( persistent_msg_handler.retrieveExplicitMessages( type ));
-	}
-	
-	public void
-	setMessagePending()
-	
-		throws BuddyPluginException
-	{
-		synchronized( this ){
-			
-			if ( ygm_active ){
-				
-				ygm_pending = true;
-				
-				return;
-			}
-			
-			ygm_active = true;
-		}
-		
-		plugin.setMessagePending( 
-			this,
-			new BuddyPlugin.operationListener()
-			{
-				public void 
-				complete() 
-				{
-					boolean	retry;
-					
-					synchronized( BuddyPluginBuddy.this ){
-						
-						ygm_active = false;
-						
-						retry = ygm_pending;
-						
-						ygm_pending = false;
-					}
-					
-					if ( retry ){
-						
-						try{
-							setMessagePending();
-							
-						}catch( BuddyPluginException e ){
-							
-							log( "Failed to send YGM", e );
-						}
-					}
-				}	
-			});
-	}
-	
-	public long
-	getLastMessagePending()
-	{
-		return( latest_ygm_time );
-	}
-	
-	protected boolean
-	addYGMMarker(
-		long		marker )
-	{
-		Long	l = new Long( marker );
-		
-		synchronized( this ){
-		
-			if ( recent_ygm == null ){
-				
-				recent_ygm = new ArrayList<Long>();
-			}
-			
-			if ( recent_ygm.contains( l )){
-				
-				return( false );
-			}
-			
-			recent_ygm.add( l );
-			
-			if ( recent_ygm.size() > 16 ){
-				
-				recent_ygm.remove(0);
-			}
-			
-			latest_ygm_time = SystemTime.getCurrentTime();
-		}
-		
-		plugin.setConfigDirty();
-		
-		plugin.fireDetailsChanged( this );
-		
-		return( true );
-	}
-	
-	protected void
-	setLastMessageReceived(
-		String		str )
-	{
-		last_message_received = str;
-		
-		plugin.fireDetailsChanged( this );
-	}
-	
-	public String
-	getLastMessageReceived()
-	{
-		return( last_message_received==null?"":last_message_received );
-	}
-	
-	protected List<Long>
-	getYGMMarkers()
-	{
-		synchronized( this ){
-		
-			return( recent_ygm==null?null:new ArrayList<Long>( recent_ygm ));
-		}
-	}
-	
-	protected int
-	getLastStatusSeq()
-	{
-		synchronized( this ){
-			
-			return( last_status_seq );
-		}
-	}
-	
-	protected void
-	buddyConnectionEstablished(
-		boolean		outgoing )
-	{
-		buddyActive();
-	}
-	
-	protected void
-	buddyMessageSent(
-		int			size,
-		boolean		record_active )
-	{
-		message_out_count++;
-		message_out_bytes += size;
-		
-		if ( record_active ){
-		
-			buddyActive();
-		}
-	}
-	
-	protected void
-	buddyMessageReceived(
-		int		size )
-	{		
-		message_in_count++;
-		message_in_bytes += size;
-		
-		received_frag_details = "";
-		
-		buddyActive();
-	}
-	
-	protected void
-	buddyMessageFragmentReceived(
-		int		num_received,
-		int		total )
-	{
-		received_frag_details = num_received + "/" + total;
-		
-		plugin.fireDetailsChanged( this );
-	}
-	
-	public String
-	getMessageInFragmentDetails()
-	{
-		return( received_frag_details );
-	}
-	
-	public int
-	getMessageInCount()
-	{
-		return( message_in_count );
-	}
-	
-	public int
-	getMessageOutCount()
-	{
-		return( message_out_count );
-	}
-	
-	public int
-	getBytesInCount()
-	{
-		return( message_in_bytes );
-	}
-	
-	public int
-	getBytesOutCount()
-	{
-		return( message_out_bytes );
-	}
-	
-	public boolean
-	isConnected()
-	{
-		boolean connected = false;
-		
-		synchronized( this ){
-						
-			for (int i=0;i<connections.size();i++){
-				
-				buddyConnection c = (buddyConnection)connections.get(i);
-				
-				if ( c.isConnected() && !c.hasFailed()){
-					
-					connected = true;
-				}
-			}
-		}
-		
-		return( connected );
-	}
-	
-	protected void
-	buddyActive()
-	{
-		long	now = SystemTime.getCurrentTime();
-		
-		synchronized( this ){
-			
-			last_time_online			= now;
-			online						= true;
-		}
-			
-		persistentDispatchPending();
-		
-		plugin.fireDetailsChanged( this );
-	}
-	
-	public void
-	ping()
-		throws BuddyPluginException
-	{
-		plugin.checkAvailable();
-		
-		try{
-			Map	ping_request = new HashMap();
-			
-			ping_request.put( "type", new Long( BuddyPlugin.RT_INTERNAL_REQUEST_PING ));
-			
-			sendMessage(
-				BuddyPlugin.SUBSYSTEM_INTERNAL,
-				ping_request,
-				60*1000,
-				new BuddyPluginBuddyReplyListener()
-				{
-					public void
-					replyReceived(
-						BuddyPluginBuddy	from_buddy,
-						Map					reply )
-					{
-						log( "Ping reply received:" + reply );
-					}
-					
-					public void
-					sendFailed(
-						BuddyPluginBuddy		to_buddy,
-						BuddyPluginException	cause )
-					{
-						log( "Ping failed to " + getString(), cause );
-					}
-				});
-			
-		}catch( Throwable e ){
-						
-			throw( new BuddyPluginException( "Ping failed", e ));
-		}
-	}
-	
-	protected void
-	sendCloseRequest(
-		boolean		restarting )
-	{
-		List	to_send = new ArrayList();
-	
-		synchronized( this ){
-				
-			closing	= true;
-			
-			for (int i=0;i<connections.size();i++){
-				
-				buddyConnection c = (buddyConnection)connections.get(i);
-				
-				if ( c.isConnected() && !c.hasFailed() && !c.isActive()){
-					
-					to_send.add( c );
-				}
-			}
-		}
-		
-		for (int i=0;i<to_send.size();i++){
-			
-			buddyConnection c = (buddyConnection)to_send.get(i);
-			
-			try{
-				Map	close_request = new HashMap();
-				
-				close_request.put( "type", new Long( BuddyPlugin.RT_INTERNAL_REQUEST_CLOSE ));
-				
-				close_request.put( "r", new Long( restarting?1:0));
-				
-				close_request.put( "os", new Long( plugin.getCurrentStatusSeq()));
-				
-				final buddyMessage	message = 
-					new buddyMessage( BuddyPlugin.SUBSYSTEM_INTERNAL, close_request, 60*1000 );
-
-				message.setListener(
-						new BuddyPluginBuddyReplyListener()
-						{
-							public void
-							replyReceived(
-								BuddyPluginBuddy	from_buddy,
-								Map					reply )
-							{
-								log( "Close reply received:" + reply );
-							}
-							
-							public void
-							sendFailed(
-								BuddyPluginBuddy		to_buddy,
-								BuddyPluginException	cause )
-							{
-								log( "Close failed to " + getString(), cause );
-							}
-						});
-				
-				c.sendCloseMessage( message );
-
-			}catch( Throwable e ){
-							
-				log( "Close request failed", e );
-			}
-		}
-	}
-	
-	protected void
-	receivedCloseRequest(
-		Map		request )
-	{
-		List<buddyConnection>	closing = new ArrayList<buddyConnection>();
-		
-		synchronized( this ){
-			
-			closing.addAll( connections );
-		}
-		
-		for (int i=0;i<closing.size();i++){
-			
-			((buddyConnection)closing.get(i)).remoteClosing();
-		}
-		
-		try{
-			boolean	restarting = ((Long)request.get( "r" )).longValue() == 1;
-			
-			if ( restarting ){
-				
-				logMessage( "restarting" );
-				
-			}else{
-				
-				logMessage( "going offline" );
-				
-				boolean	details_change = false;
-				
-				synchronized( this ){
-					
-					if ( offline_seq_set == null ){
-						
-						offline_seq_set = new HashSet<Long>();
-					}
-					
-					offline_seq_set.add( new Long( last_status_seq ));
-					
-					offline_seq_set.add((Long)request.get( "os" ));
-					
-					if ( online ){
-						
-						online					= false;
-						consec_connect_fails	= 0;
-						
-						details_change	= true;
-					}
-				}
-				
-				if ( details_change ){
-					
-					plugin.fireDetailsChanged( this );
-				}
-			}
-		}catch( Throwable e ){
-			
-			Debug.out( "Failed to decode close request", e );
-		}
-	}
-	
-	public void
-	sendMessage(
-		final int								subsystem,
-		final Map								content,
-		final int								timeout_millis,
-		final BuddyPluginBuddyReplyListener		listener )
-	
-		throws BuddyPluginException
-	{
-		plugin.checkAvailable();
-		
-		boolean	wait = false;
-				
-		if ( ip == null ){
-			
-			synchronized( this ){
-				
-				wait = check_active;
-			}
-			
-			if ( !wait ){
-			
-				if ( SystemTime.getCurrentTime() - last_status_check_time > 30*1000 ){
-				
-					plugin.updateBuddyStatus( this );
-				
-					wait	= true;
-				}
-			}
-		}
-		
-		if ( wait ){
-			
-			new AEThread2( "BuddyPluginBuddy:sendWait", true )
-			{
-				public void
-				run()
-				{
-					try{
-						long	start = SystemTime.getCurrentTime();
-						
-						for (int i=0;i<20;i++){
-							
-							if ( ip != null ){
-								
-								break;
-							}
-							
-							Thread.sleep( 1000 );
-						}
-						
-						long	elapsed = SystemTime.getCurrentTime() - start;
-						
-						int new_tm = timeout_millis;
-						
-						if ( elapsed > 0 && timeout_millis > 0 ){
-							
-							new_tm -= elapsed;
-							
-							if ( new_tm <= 0 ){
-								
-								listener.sendFailed( BuddyPluginBuddy.this, new BuddyPluginException( "Timeout" ));
-								
-								return;
-							}
-						}
-						
-						sendMessageSupport( content, subsystem, new_tm, listener );
-						
-					}catch( Throwable e ){
-						
-						if ( e instanceof BuddyPluginException ){
-							
-							listener.sendFailed( BuddyPluginBuddy.this, (BuddyPluginException)e);
-						}else{
-						
-							listener.sendFailed( BuddyPluginBuddy.this, new BuddyPluginException( "Send failed", e ));
-						}
-					}
-				}				
-			}.start();
-			
-		}else{
-			
-			sendMessageSupport( content, subsystem, timeout_millis, listener );
-		}
-	}
-	
-	protected void
-	sendMessageSupport(
-		final Map								content,
-		final int								subsystem,
-		final int								timeout_millis,
-		final BuddyPluginBuddyReplyListener		original_listener )
-	
-		throws BuddyPluginException
-	{
-		boolean too_many_messages = false;
-		
-		synchronized( this ){
-		
-			too_many_messages = messages.size() >= MAX_QUEUED_MESSAGES;
-		}
-		
-		if ( too_many_messages ){
-			
-			throw( new BuddyPluginException( "Too many messages queued" ));
-		}
-		
-		final buddyMessage	message = new buddyMessage( subsystem, content, timeout_millis );
-		
-		BuddyPluginBuddyReplyListener	listener_delegate = 
-			new BuddyPluginBuddyReplyListener()
-			{
-				public void
-				replyReceived(
-					BuddyPluginBuddy		from_buddy,
-					Map						reply )
-				{
-					// logMessage( "Msg " + message.getString() + " ok" );
-					
-					try{
-						synchronized( BuddyPluginBuddy.this ){
-							
-							if ( current_message != message ){
-								
-								Debug.out( "Inconsistent: reply received not for current message" );
-							}
-							
-							current_message = null;
-						}
-						
-						original_listener.replyReceived( from_buddy, reply );
-						
-					}finally{
-						
-						dispatchMessage();
-					}
-				}
-				
-				public void
-				sendFailed(
-					BuddyPluginBuddy		to_buddy,
-					BuddyPluginException	cause )
-				{
-					logMessage( "Msg " + message.getString() + " failed: " + Debug.getNestedExceptionMessage( cause ));
-
-					try{
-							// only try and reconcile this failure with the current message if
-							// the message has actually been sent
-						
-						boolean	was_active;
-						
-						if ( cause instanceof BuddyPluginTimeoutException ){
-							
-							was_active = ((BuddyPluginTimeoutException)cause).wasActive();
-							
-						}else{
-							
-							was_active = true;
-						}
-						
-						if ( was_active ){
-							
-							synchronized( BuddyPluginBuddy.this ){
-								
-								if ( current_message != message ){
-									
-									Debug.out( "Inconsistent: error received not for current message" );
-								}
-								
-								current_message = null;
-							}
-						}
-						
-						long	now = SystemTime.getCurrentTime();
-						
-						int	retry_count = message.getRetryCount();
-						
-						if ( retry_count < 1 && !message.timedOut( now )){
-							
-							message.setRetry();
-							
-							// logMessage( "Msg " + message.getString() + " retrying" );
-
-							synchronized( BuddyPluginBuddy.this ){
-								
-								messages.add( 0, message );
-							}
-						}else{
-						
-							original_listener.sendFailed( to_buddy, cause );
-						}
-					}finally{
-							
-						dispatchMessage();
-					}
-				}
-			};
-			
-		message.setListener( listener_delegate );
-			
-		int	size;
-		
-		synchronized( this ){
-			
-			messages.add( message );
-			
-			size = messages.size();
-		}
-		
-		// logMessage( "Msg " + message.getString() + " added: num=" + size );
-		
-		dispatchMessage();
-	}
-	
-	protected void
-	dispatchMessage()
-	{
-		buddyConnection	bc = null;
-		
-		buddyMessage 	allocated_message 	= null;
-		Throwable		failed_msg_error 	= null;
-		
-		boolean	inform_dirty	= false;
-		
-		synchronized( this ){
-	
-			if ( current_message != null || messages.size() == 0 || closing ){
-				
-				return;
-			}
-			
-			allocated_message = current_message = (buddyMessage)messages.remove( 0 );
-			
-			for (int i=0;i<connections.size();i++){
-				
-				buddyConnection c = (buddyConnection)connections.get(i);
-				
-				if ( !c.hasFailed()){
-					
-					bc	= c;
-				}
-			}
-			
-			if ( bc == null ){
-				
-				if ( destroyed ){
-					
-					failed_msg_error = new BuddyPluginException( "Friend destroyed" );
-					
-				}else if ( connections.size() >= MAX_ACTIVE_CONNECTIONS ){
-					
-					failed_msg_error = new BuddyPluginException( "Too many active connections" );
-				}
-			}
-		}
-		
-		if ( failed_msg_error != null ){
-			
-			allocated_message.reportFailed( failed_msg_error );
-			
-			return;
-		}
-		
-		if ( bc == null ){
-			
-				// single-thread outgoing connect attempts
-			
-			try{
-				outgoing_connect_sem.reserve();
-			
-				synchronized( this ){
-
-					if ( current_message != allocated_message ){
-						
-						failed_msg_error = new BuddyPluginException( "current message no longer active" );
-						
-					}else if ( closing ){
-						
-						return;
-					}
-						
-					if ( failed_msg_error == null ){
-						
-						for (int i=0;i<connections.size();i++){
-							
-							buddyConnection c = (buddyConnection)connections.get(i);
-							
-							if ( !c.hasFailed()){
-								
-								bc	= c;
-							}
-						}
-						
-						if ( bc == null ){
-							
-							if ( destroyed ){
-								
-								failed_msg_error = new BuddyPluginException( "Friend destroyed" );
-								
-							}else if ( connections.size() >= MAX_ACTIVE_CONNECTIONS ){
-								
-								failed_msg_error = new BuddyPluginException( "Too many active connections" );
-							}
-						}
-					}
-				}
-				
-				if ( bc == null && failed_msg_error == null ){
-					
-					try{
-							// can't perform connect op while synchronized as may deadlock on password
-							// aquisition
-						
-						GenericMessageConnection generic_connection = outgoingConnection();
-
-						synchronized( this ){
-
-							if ( current_message != allocated_message ){
-								
-								failed_msg_error = new BuddyPluginException( "current message no longer active" );
-								
-								generic_connection.close();
-								
-							}else{
-								
-								bc = new buddyConnection( generic_connection, true );
-								
-								inform_dirty = connections.size() == 0;
-								
-								connections.add( bc );
-							
-								// logMessage( "Con " + bc.getString() + " added: num=" + connections.size() );
-							}
-						}
-					}catch( Throwable e ){
-						
-						failed_msg_error = e;
-					}
-				}
-			}finally{
-				
-				outgoing_connect_sem.release();
-			}
-		}
-			
-		if ( failed_msg_error != null ){
-			
-			allocated_message.reportFailed( failed_msg_error );
-			
-			return;
-		}
-			
-		try{
-			// logMessage( "Allocating msg " + allocated_message.getString() + " to con " + bc.getString());
-
-			bc.sendMessage( allocated_message );
-		
-		}catch( BuddyPluginException e ){
-			
-			allocated_message.reportFailed( e );
-		}
-		
-		if ( inform_dirty ){
-			
-			plugin.setConfigDirty();
-		}
-	}
-	
-	protected void
-	removeConnection(
-		buddyConnection			bc )
-	{
-		int	size;
-		
-		synchronized( this ){
-			
-			connections.remove( bc );
-			
-			size = connections.size();
-		}
-		
-		if ( size == 0 ){
-							
-			plugin.setConfigDirty();
-		}
-		
-		if ( size == 0 && bc.isConnected() && !bc.isClosing() && !bc.isRemoteClosing()){
-			
-				// dropped connection, kick in a keep alive 
-			
-			if ( consec_connect_fails < 3 ){
-				
-				if ( consec_connect_fails == 0 ){
-					
-					long	now = SystemTime.getMonotonousTime();
-					
-					boolean do_it = false;
-					
-					synchronized( this ){
-					
-						if ( 	last_auto_reconnect == -1 || 
-								now - last_auto_reconnect > 30*1000 ){
-							
-							last_auto_reconnect = now;
-							
-							do_it = true;
-						}
-					}
-					
-					if ( do_it ){
-						
-							// delay a bit
-						
-						new DelayedEvent(
-								"BuddyPluginBuddy:recon",
-								new Random().nextInt( 3000 ),
-								new AERunnable()
-								{
-									public void
-									runSupport()
-									{
-										int	size;
-										
-										synchronized( BuddyPluginBuddy.this ){
-																					
-											size = connections.size();
-										}
-										
-										if ( consec_connect_fails == 0 && size == 0 ){
-				
-											log( "Attempting reconnect after dropped connection" );
-											
-											sendKeepAlive();
-										}
-									}
-								});
-					}
-							
-				}else{
-					
-					long	delay = 60*1000;
-					
-					delay <<= Math.min( 3, consec_connect_fails );
-			
-					if ( SystemTime.getCurrentTime() - last_connect_attempt >= delay ){
-						
-						sendKeepAlive();
-					}
-				}
-			}
-		}
-		
-		// logMessage( "Con " + bc.getString() + " removed: num=" + size );
-
-			// connection failed, see if we need to attempt to re-establish
-		
-		plugin.fireDetailsChanged( this );
-		
-		dispatchMessage();
-	}
-	
-	protected long
-	getLastStatusCheckTime()
-	{
-		return( last_status_check_time );
-	}
-	
-	protected boolean
-	statusCheckActive()
-	{
-		synchronized( this ){
-
-			return( check_active );
-		}
-	}
-	
-	protected boolean
-	statusCheckStarts()
-	{
-		synchronized( this ){
-			
-			if ( check_active ){
-				
-				return( false );
-			}
-		
-			last_status_check_time = SystemTime.getCurrentTime();
-		
-			check_active = true;
-		}
-		
-		return( true );
-	}
-	
-	protected void
-	statusCheckFailed()
-	{
-		boolean	details_change = false;
-
-		synchronized( this ){
-
-			try{
-				if ( online ){
-					
-					online					= false;
-					consec_connect_fails	= 0;
-					
-					details_change	= true;
-				}
-			}finally{
-			
-				status_check_count++;
-				
-				check_active = false;
-			}
-		}
-			
-		if ( details_change ){
-			
-			plugin.fireDetailsChanged( this );
-		}
-	}
-	
-	protected void
-	setCachedStatus(
-		InetAddress		_ip,
-		int				_tcp_port,
-		int				_udp_port )
-	{
-		synchronized( this ){
-
-			if ( ip == null ){
-			
-				ip			= _ip;
-				tcp_port	= _tcp_port;
-				udp_port	= _udp_port;
-			}
-		}
-	}
-	
-	protected void
-	statusCheckComplete(
-		long			_post_time,
-		InetAddress		_ip,
-		int				_tcp_port,
-		int				_udp_port,
-		String			_nick_name,
-		int				_online_status,
-		int				_status_seq,
-		int				_version )
-	{
-		boolean	details_change 	= false;
-		boolean	config_dirty 	= false;
-
-		long	now = SystemTime.getCurrentTime();
-		
-		if ( now < last_time_online ){
-			
-			last_time_online = now;
-		}
-		
-		boolean is_connected = isConnected();
-		
-		synchronized( this ){
-
-			try{
-					// do we explicitly know that this sequence number denotes an offline buddy
-				
-				if ( offline_seq_set != null ){
-					
-					if ( offline_seq_set.contains(new Long( _status_seq ))){
-						
-						return;
-						
-					}else{
-						
-						offline_seq_set = null;
-					}
-				}
-				
-				boolean	seq_change = _status_seq != last_status_seq;
-				
-				boolean timed_out;
-
-					// change in sequence means we're online
-				
-				if ( seq_change ){
-					
-					last_status_seq		= _status_seq;
-					last_time_online	= now;
-					
-					timed_out 			= false;
-					details_change		= true;
-					
-				}else{
-				
-					timed_out =  now - last_time_online >= BuddyPlugin.STATUS_REPUBLISH_PERIOD * 3 ;
-				}	
-				
-				if ( online ){
-					
-					if ( timed_out ){
-							
-						online					= false;
-						consec_connect_fails	= 0;
-						
-						details_change	= true;
-					}
-				}else{	
-					
-					if ( seq_change || !timed_out ){
-						
-						online			= true;
-						details_change	= true;
-					}
-				}
-				
-				post_time	= _post_time;
-				
-				if ( 	!addressesEqual( ip, _ip ) ||
-						tcp_port != _tcp_port ||
-						udp_port != _udp_port ||
-						version	 < _version ){
-					
-					ip				= _ip;
-					tcp_port		= _tcp_port;
-					udp_port		= _udp_port;
-					
-					if ( version < _version ){
-					
-						version			= _version;
-					}
-					
-					details_change	= true;
-				}
-				
-					// if we are connected then we use the status sent over the connection
-					// as it is more up to date
-				
-				if ( 	!is_connected &&
-						online_status != _online_status ){
-					
-					online_status	= _online_status;
-					
-					details_change	= true;
-				}
-				
-				if ( !plugin.stringsEqual( nick_name, _nick_name )){
-					
-					nick_name	= _nick_name;
-					
-					config_dirty	= true;
-					details_change	= true;
-				}
-			}finally{
-			
-				status_check_count++;
-					
-				check_active = false;
-			}
-		}
-		
-		if ( config_dirty ){
-			
-			plugin.setConfigDirty();
-		}
-		
-		if ( details_change ){
-			
-			if ( online ){
-				
-				persistentDispatchPending();
-			}
-			
-			plugin.fireDetailsChanged( this );
-		}
-		
-		plugin.logMessage( getString());
-	}
-	
-	protected boolean
-	addressesEqual(
-		InetAddress		ip1,
-		InetAddress		ip2 )
-	{
-		if ( ip1 == null && ip2 == null ){
-			
-			return( true );
-			
-		}else if ( ip1 == null || ip2 == null ){
-			
-			return( false );
-			
-		}else{
-	
-			return( ip1.equals( ip2 ));
-		}
-	}
-	
-	protected void
-	checkTimeouts()
-	{
-		long	now = SystemTime.getCurrentTime();
-		
-		List	failed = null;
-		
-		List	connections_to_check = null;
-		
-		boolean	messages_queued;
-		
-		synchronized( this ){
-			
-			messages_queued = messages.size() > 0;
-			
-			if ( messages_queued ){
-							
-				Iterator	it = messages.iterator();
-				
-				while( it.hasNext()){
-					
-					buddyMessage	message = (buddyMessage)it.next();
-					
-					if ( message.timedOut( now )){
-						
-						it.remove();
-						
-						if ( failed == null ){
-							
-							failed = new ArrayList();
-						}
-						
-						failed.add( message );
-					}
-				}
-			}
-			
-			if ( connections.size() > 0 ){
-				
-				connections_to_check = new ArrayList( connections );
-			}
-		}
-		
-		boolean	send_keep_alive = false;
-
-		if ( connections_to_check == null ){			
-			
-				// no active connections
-			
-			if ( online && ip != null && !messages_queued ){
-				
-					// see if we should attempt a pre-emptive connect
-				
-				if ( consec_connect_fails < 3 ){
-					
-					long	delay = 60*1000;
-											
-					delay <<= Math.min( 3, consec_connect_fails );
-				
-					send_keep_alive = now - last_connect_attempt >= delay;
-				}
-			}
-		}else{
-			
-			for (int i=0;i<connections_to_check.size();i++){
-				
-				buddyConnection connection = (buddyConnection)connections_to_check.get(i);
-				
-				boolean closed = connection.checkTimeout( now );
-				
-				if ( 	ip != null &&
-						!closed && 
-						!messages_queued &&
-						connection.isConnected() && 
-						!connection.isActive()){
-					
-					if ( now - connection.getLastActive( now ) > CONNECTION_KEEP_ALIVE ){
-									
-						send_keep_alive	= true;
-					}
-				}
-			}
-		}
-		
-		if ( send_keep_alive ){
-			
-			sendKeepAlive();
-		}
-		
-		if ( failed != null ){
-			
-			for (int i=0;i<failed.size();i++){
-				
-				((buddyMessage)failed.get(i)).reportFailed( new BuddyPluginTimeoutException( "Timeout", false ));
-			}
-		}
-	}
-	
-	protected void
-	sendKeepAlive()
-	{
-		boolean send_keep_alive = true;
-		
-		synchronized( this ){
-			
-			if ( keep_alive_outstanding ){
-				
-				send_keep_alive = false;
-				
-			}else{
-			
-				keep_alive_outstanding = true;
-			}
-		}
-		
-		if ( send_keep_alive ){
-			
-			try{
-				Map	ping_request = new HashMap();
-				
-				ping_request.put( "type", new Long( BuddyPlugin.RT_INTERNAL_REQUEST_PING ));
-				
-				sendMessageSupport(
-					ping_request,
-					BuddyPlugin.SUBSYSTEM_INTERNAL,
-					60*1000,
-					new BuddyPluginBuddyReplyListener()
-					{
-						public void
-						replyReceived(
-							BuddyPluginBuddy	from_buddy,
-							Map					reply )
-						{
-							synchronized( BuddyPluginBuddy.this ){
-								
-								keep_alive_outstanding = false;
-							}
-						}
-						
-						public void
-						sendFailed(
-							BuddyPluginBuddy		to_buddy,
-							BuddyPluginException	cause )
-						{
-							synchronized( BuddyPluginBuddy.this ){
-								
-								keep_alive_outstanding = false;
-							}
-						}
-					});
-				
-			}catch( Throwable e ){
-				
-				synchronized( this ){
-					
-					keep_alive_outstanding = false;
-				}
-			}
-		}
-	}
-	
-	public String
-	getConnectionsString()
-	{
-		synchronized( this ){
-			
-			String	str = "";
-			
-			for (int i=0;i<connections.size();i++){
-				
-				str += (str.length()==0?"":",") + ((buddyConnection)connections.get(i)).getString( true );
-			}
-			
-			return( str );
-		}
-	}
-	
-	public void
-	disconnect()
-	{
-		List	to_disconnect = new ArrayList();
-		
-		synchronized( this ){
-			
-			to_disconnect.addAll( connections );
-		}
-		
-		for (int i=0;i<to_disconnect.size();i++){
-			
-			((buddyConnection)to_disconnect.get(i)).disconnect();
-		}
-	}
-	
-	protected boolean
-	isClosing()
-	{
-		return( closing );
-	}
-	
-	protected void
-	destroy()
-	{
-		List<buddyConnection>	to_close = new ArrayList<buddyConnection>();
-		
-		synchronized( this ){
-			
-			destroyed = true;
-			
-			to_close.addAll( connections );
-		}
-		
-		for (int i=0;i<to_close.size();i++){
-			
-			((buddyConnection)to_close.get(i)).close();
-		}
-	}
-	
-	protected void
-	logMessage(
-		String	str )
-	{
-		plugin.logMessage( getShortString() + ": " + str );
-	}
-	
-	protected GenericMessageConnection
-	outgoingConnection()
-	
-		throws BuddyPluginException
-	{
-		GenericMessageRegistration msg_registration = plugin.getMessageRegistration();
-
-		if ( msg_registration == null ){
-						
-			throw( new BuddyPluginException( "Messaging system unavailable" ));
-		}
-		
-		InetAddress ip = getIP();
-		
-		if ( ip == null ){
-						
-			throw( new BuddyPluginException( "Friend offline (no usable IP address)" ));
-		}
-		
-		InetSocketAddress	tcp_target	= null;
-		InetSocketAddress	udp_target	= null;
-		
-		int	tcp_port = getTCPPort();
-		
-		if ( tcp_port > 0 ){
-			
-			tcp_target = new InetSocketAddress( ip, tcp_port );
-		}
-		
-		int	udp_port = getUDPPort();
-		
-		if ( udp_port > 0 ){
-			
-			udp_target = new InetSocketAddress( ip, udp_port );
-		}
-
-		InetSocketAddress	notional_target = tcp_target;
-		
-		if ( notional_target == null ){
-		
-			notional_target = udp_target;
-		}
-		
-		if ( notional_target == null ){
-						
-			throw( new BuddyPluginException( "Friend offline (no usable protocols)" ));
-		}
-		
-		GenericMessageEndpoint	endpoint = msg_registration.createEndpoint( notional_target );
-		
-		if ( tcp_target != null ){
-		
-			endpoint.addTCP( tcp_target );
-		}
-		
-		if ( udp_target != null ){
-		
-			endpoint.addUDP( udp_target );
-		}
-				
-		GenericMessageConnection	con = null;
-		
-		try{
-			last_connect_attempt = SystemTime.getCurrentTime();
-			
-			con = msg_registration.createConnection( endpoint );
-				
-			plugin.addRateLimiters( con );
-			
-			String reason = "Friend: Outgoing connection establishment";
-	
-			SESecurityManager sec_man = plugin.getSecurityManager();
-			
-			con = sec_man.getSTSConnection( 
-					con, 
-					sec_man.getPublicKey( SEPublicKey.KEY_TYPE_ECC_192, reason ),
-	
-					new SEPublicKeyLocator()
-					{
-						public boolean
-						accept(
-							Object			context,
-							SEPublicKey		other_key )
-						{
-							String	other_key_str = Base32.encode( other_key.encodeRawPublicKey());
-
-							if ( other_key_str.equals( public_key )){
-								
-								consec_connect_fails	= 0;
-								
-								return( true );
-								
-							}else{
-								
-								log( getString() + ": connection failed due to pk mismatch" );
-							
-								return( false );
-							}
-						}
-					},
-					reason, 
-					BuddyPlugin.BLOCK_CRYPTO );		
-				
-			con.connect();
-			
-			return( con );
-			
-		}catch( Throwable e ){
-			
-			if ( con != null ){
-			
-				consec_connect_fails++;
-				
-				try{
-					con.close();
-					
-				}catch( Throwable f ){
-					
-					log( "Failed to close connection", f );
-				}
-			}
-			
-			throw( new BuddyPluginException( "Failed to send message", e ));
-		}
-	}
-	
-	protected void
-	incomingConnection(
-		GenericMessageConnection	_connection )
-	
-		throws BuddyPluginException
-	{
-		addConnection( _connection );
-	}
-	
-	protected void
-	addConnection(
-		GenericMessageConnection		_connection )
-	
-		throws BuddyPluginException
-	{
-		//int	size;
-		
-		buddyConnection bc = new buddyConnection( _connection, false );
-		
-		boolean inform_dirty = false;
-		
-		synchronized( this ){
-			
-			if ( destroyed ){
-				
-				throw( new BuddyPluginException( "Friend has been destroyed" ));
-			}
-			
-			inform_dirty = connections.size() == 0;
-			
-			connections.add( bc );
-			
-			//size = connections.size();
-		}
-		
-		// logMessage( "Con " + bc.getString() + " added: num=" + size );
-		
-		if ( inform_dirty ){
-			
-			plugin.setConfigDirty();
-		}
-	}
-	
-	public void
-	setUserData(
-		Object		key,
-		Object		value )
-	{
-		synchronized( user_data ){
-			
-			user_data.put(key, value);
-		}
-	}
-	
-	public Object
-	getUserData(
-		Object		key )
-	{
-		synchronized( user_data ){
-
-			return( user_data.get( key ));
-		}
-	}
-	
-	protected void
-	log(
-		String		str )
-	{
-		plugin.log( str );
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable 	e )
-	{
-		plugin.log( str, e );
-	}
-	
-	public String
-	getString()
-	{
-		return( "pk=" +  getShortString() + (nick_name==null?"":(",nick=" + nick_name)) + ",ip=" + ip + ",tcp=" + tcp_port + ",udp=" + udp_port + ",online=" + online + ",age=" + (SystemTime.getCurrentTime() - post_time ));
-	}
-
-	protected class
-	buddyMessage
-	{
-		private int									message_id;
-		
-		private Map									request;
-		private int									subsystem;
-		private BuddyPluginBuddyReplyListener		listener;
-		private int									timeout_millis;
-		
-		private long					queue_time	= SystemTime.getCurrentTime();
-		
-		private boolean		timed_out;
-		private int			retry_count;
-		private boolean		complete;
-		
-		protected
-		buddyMessage(
-			int									_subsystem,
-			Map									_request,
-			int									_timeout )
-		{
-			synchronized( BuddyPluginBuddy.this ){
-			
-				message_id = next_message_id++;
-			}
-			
-			request			= _request;
-			subsystem		= _subsystem;
-			timeout_millis	= _timeout;
-		}
-		
-		protected void
-		setListener(
-			BuddyPluginBuddyReplyListener		_listener )
-		{
-			listener		= _listener;
-		}
-		
-		protected int
-		getRetryCount()
-		{
-			synchronized( this ){
-
-				return( retry_count );
-			}
-		}
-		
-		protected void
-		setDontRetry()
-		{
-			retry_count = 99;
-		}
-		
-		protected void
-		setRetry()
-		{
-			synchronized( this ){
-				
-				retry_count++;
-				
-				complete 	= false;
-				timed_out 	= false;
-				
-			}
-		}
-		
-		protected boolean
-		timedOut(
-			long	now )
-		{
-			if ( timed_out ){
-				
-				return( true );
-			}
-			
-			if ( now < queue_time ){
-				
-				queue_time = now;
-				
-				return( false );
-				
-			}else{
-				
-				timed_out = now - queue_time >= timeout_millis;
-				
-				return( timed_out );
-			}
-		}
-		
-		protected Map
-		getRequest()
-		{
-			return( request );
-		}
-		
-		protected int
-		getSubsystem()
-		{
-			return( subsystem );
-		}
-		
-		protected int
-		getID()
-		{
-			return( message_id );
-		}
-		
-		protected void
-		reportComplete(
-			Map		reply )
-		{
-			synchronized( this ){
-				
-				if ( complete ){
-					
-					return;
-				}
-				
-				complete = true;
-			}
-			
-			try{
-				listener.replyReceived(  BuddyPluginBuddy.this, reply );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-		
-		protected void
-		reportFailed(
-			Throwable	error )
-		{
-			synchronized( this ){
-				
-				if ( complete ){
-					
-					return;
-				}
-				
-				complete = true;
-			}
-			
-			try{
-				if ( error instanceof BuddyPluginException ){
-					
-					listener.sendFailed( BuddyPluginBuddy.this, (BuddyPluginException)error );
-					
-				}else{
-				
-					listener.sendFailed(  BuddyPluginBuddy.this, new BuddyPluginException( "",  error ));
-				}
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-		
-		protected String
-		getString()
-		{
-			return( "id=" + message_id + ",ss=" + subsystem + (retry_count==0?"":(",retry="+retry_count)));
-		}
-	}
-	
-	protected class
-	buddyConnection
-		implements fragmentHandlerReceiver
-	{
-		private fragmentHandler					fragment_handler;
-		private int								connection_id;
-		private boolean							outgoing;
-		
-		private String							dir_str;
-		
-		
-		private volatile buddyMessage	active_message;
-		
-		private volatile boolean			connected;
-		private volatile boolean			closing;
-		private volatile boolean			remote_closing;
-		private volatile boolean			failed;
-		
-		private long			last_active	= SystemTime.getCurrentTime();
-		
-		protected
-		buddyConnection(
-			GenericMessageConnection		_connection,
-			boolean							_outgoing )
-		{
-			fragment_handler	= new fragmentHandler( _connection, this );
-			
-			outgoing	= _outgoing;
-			
-			synchronized( BuddyPluginBuddy.this ){
-				
-				connection_id = next_connection_id++;
-			}
-			
-			dir_str = outgoing?"Outgoing":"Incoming";
-			
-			if ( !outgoing ){
-				
-				connected = true;
-				
-				buddyConnectionEstablished( false );
-			}
-			
-			fragment_handler.start();
-		}
-		
-		protected boolean
-		isConnected()
-		{
-			return( connected );
-		}
-		
-		protected boolean
-		hasFailed()
-		{
-			return( failed );
-		}
-		
-		protected boolean
-		isOutgoing()
-		{
-			return( outgoing );
-		}
-		
-		protected long
-		getLastActive(
-			long		now )
-		{
-			if ( now < last_active ){
-				
-				last_active = now;
-			}
-			
-			return( last_active );
-		}
-		
-		protected void
-		sendMessage(
-			buddyMessage	message )
-		
-			throws BuddyPluginException
-		{			
-			BuddyPluginException	failed_error = null;
-
-			buddyMessage	msg_to_send			= null;
-
-			synchronized( this ){
-				
-				if ( BuddyPluginBuddy.this.isClosing()){
-					
-					throw( new BuddyPluginException( "Close in progress" ));
-				}
-				
-				if ( active_message != null ){
-					
-					Debug.out( "Inconsistent: active message already set" );
-					
-					failed_error = new BuddyPluginException( "Inconsistent state" );
-					
-				}else if ( failed || closing ){
-					
-					throw( new BuddyPluginException( "Connection failed" ));
-					
-				}else{
-										
-					active_message = message;
-					
-					if ( connected ){
-						
-						msg_to_send = active_message;
-					}
-				}
-			}
-			
-			if ( failed_error != null ){
-				
-				failed( failed_error );
-				
-				throw( failed_error );
-			}
-			
-			if ( msg_to_send != null ){
-			
-				send( msg_to_send );
-			}
-		}
-		
-		protected void
-		sendCloseMessage(
-			buddyMessage	message )	
-		{			
-			boolean	ok_to_send;
-			
-			synchronized( this ){
-				
-				ok_to_send = active_message == null && connected && !failed && !closing;
-			}
-			
-			if ( ok_to_send ){
-			
-				send( message );
-			}
-		}
-		
-		public boolean
-		isActive()
-		{
-			return( active_message != null );
-		}
-		
-		public void
-		connected()
-		{
-			if ( TRACE ){
-				System.out.println( dir_str + " connected" );
-			}
-			
-			buddyMessage	msg_to_send = null;
-			
-			synchronized( this ){
-				
-				last_active	= SystemTime.getCurrentTime();
-				
-				connected = true;
-				
-				msg_to_send = active_message;
-			}
-			
-			buddyConnectionEstablished( true );
-			
-			if ( msg_to_send != null  ){
-			
-				send( msg_to_send );
-			}
-		}
-		
-		protected boolean
-		checkTimeout(
-			long	now )
-		{
-			buddyMessage	bm = null;
-			
-			boolean	close = false;
-			
-			synchronized( this ){
-
-				if ( active_message != null ){
-					
-					if ( active_message.timedOut( now )){
-						
-						bm	= active_message;
-						
-						active_message	= null;
-					}
-				}
-								
-				if ( now < last_active ){
-					
-					last_active = now;
-				}
-				
-				if ( now - last_active > CONNECTION_IDLE_TIMEOUT ){
-										
-					close	= true;
-				}
-			}
-			
-			if ( bm != null ){
-				
-				bm.reportFailed( new BuddyPluginTimeoutException( "Timeout", true ));
-			}
-
-			if ( close ){
-				
-				close();
-			}
-			
-			return( close );
-		}
-		
-		protected void
-		send(
-			buddyMessage		msg )
-		{
-			Map request = msg.getRequest();
-			
-			Map	send_map = new HashMap();
-			
-			send_map.put( "type", new Long( RT_REQUEST_DATA ));
-			send_map.put( "req", request );
-			send_map.put( "ss", new Long( msg.getSubsystem()));
-			send_map.put( "id", new Long( msg.getID()));
-			send_map.put( "oz", new Long( plugin.getOnlineStatus()));
-			send_map.put( "v", new Long( BuddyPlugin.VERSION_CURRENT ));
-			
-			String	loc_cat = getLocalAuthorisedRSSCategoriesAsString();
-			
-			if ( loc_cat != null ){
-				send_map.put( "cat", loc_cat );
-			}
-			
-			try{
-				// logMessage( "Sending " + msg.getString() + " to " + getString());
-
-				fragment_handler.send( send_map, true, true );
-							
-				synchronized( this ){
-					
-					last_active	= SystemTime.getCurrentTime();;
-				}
-			}catch( BuddyPluginException e ){
-			
-				try{			
-					failed( e );
-				
-				}catch( Throwable f ){
-				
-					Debug.printStackTrace(f);
-				}
-			}
-		}
-		
-		public void
-		receive(
-			Map			data_map )
-		{
-			synchronized( this ){
-				
-				last_active	= SystemTime.getCurrentTime();;
-			}
-			
-			if ( TRACE ){
-				System.out.println( dir_str + " receive: " + data_map );
-			}
-
-			try{
-				int	type = ((Long)data_map.get("type")).intValue();
-				
-				Long	l_os = (Long)data_map.get( "oz" );
-				
-				if ( l_os != null ){
-					
-					setOnlineStatus( l_os.intValue());
-				}
-				
-				Long	l_ver = (Long)data_map.get( "v" );
-				
-				if ( l_ver != null ){
-					
-					setVersion( l_ver.intValue());
-				}
-				
-				byte[]	b_rem_cat = (byte[])data_map.get( "cat" );
-				
-				if ( b_rem_cat == null ){
-					
-					setRemoteAuthorisedRSSCategories( null );
-					
-				}else{
-					
-					setRemoteAuthorisedRSSCategories( stringToCats( new String( b_rem_cat, "UTF-8" )));
-				}
-				
-				if ( type == RT_REQUEST_DATA ){
-					
-					// logMessage( "Received type=" + type + " from " + getString());
-				
-					Long	subsystem = (Long)data_map.get( "ss" );
-					
-					Map	reply;
-					
-					int	reply_type;
-					
-					Map request = (Map)data_map.get( "req" );
-
-					String	error = null;
-					
-					if ( request == null || subsystem == null ){
-						
-						reply	= null;
-						
-					}else{
-						
-						try{
-						
-							reply = plugin.requestReceived( BuddyPluginBuddy.this, subsystem.intValue(), request );
-							
-						}catch( Throwable e ){
-							
-							error = Debug.getNestedExceptionMessage(e);
-							
-							reply = null;
-						}
-					}
-					
-					if ( reply == null ){
-						
-						reply_type = RT_REPLY_ERROR;
-						
-						reply = new HashMap();
-						
-						reply.put( "error", error==null?"No handlers available to process request":error );
-						
-					}else{
-						
-						reply_type = RT_REPLY_DATA;
-					}
-					
-					Map reply_map = new HashMap();
-					
-					reply_map.put( "ss", subsystem );
-					reply_map.put( "type", new Long( reply_type ));																
-					reply_map.put( "id", data_map.get( "id" ) );
-					reply_map.put( "oz", new Long( plugin.getOnlineStatus()));
-
-					String	loc_cat = getLocalAuthorisedRSSCategoriesAsString();
-					
-					if ( loc_cat != null ){
-						reply_map.put( "cat", loc_cat );
-					}
-					
-					reply_map.put( "rep", reply );
-					
-						// don't record as active here as (1) we recorded as active above when 
-						// receiving request (2) we may be replying to a 'closing' message and
-						// we don't want the reply to mark as online 
-
-					fragment_handler.send( reply_map, false, false );
-					
-				}else if ( type == RT_REPLY_DATA || type == RT_REPLY_ERROR ){
-					
-					long	id = ((Long)data_map.get( "id" )).longValue();
-					
-					buddyMessage	bm;
-					
-					synchronized( this ){
-						
-						if ( 	active_message != null &&
-								active_message.getID() == id ){
-								
-							bm = active_message;
-		
-							active_message = null;
-							
-						}else{
-								
-							bm = null;
-						}
-					}
-					
-					Map	reply = (Map)data_map.get( "rep" );
-					
-					if ( bm == null ){
-						
-						logMessage( "reply discarded as no matching request: " + reply );
-						
-					}else{
-						
-						if ( type == RT_REPLY_ERROR ){
-							
-							bm.setDontRetry();
-							
-							bm.reportFailed( new BuddyPluginException(new String((byte[])reply.get( "error" ))));
-							
-						}else{
-							
-							bm.reportComplete( reply );
-						}
-					}				
-				}else{
-					
-						// ignore unknown message types
-				}
-			}catch( Throwable e ){
-				
-				failed( e );	
-			}
-		}
-		
-		protected void
-		close()
-		{
-			closing = true;
-			
-			failed( new BuddyPluginException( "Closing" ));
-		}
-		
-		protected boolean
-		isClosing()
-		{
-			return( closing );
-		}
-		
-		protected void
-		remoteClosing()
-		{
-			remote_closing = true;
-		}
-		
-		protected boolean
-		isRemoteClosing()
-		{
-			return( remote_closing );
-		}
-		
-		protected void
-		disconnect()
-		{
-			fragment_handler.close();
-		}
-		
-		public void
-		failed(
-			Throwable 					error )
-		{
-			buddyMessage bm = null;
-			
-			if ( !connected && outgoing ){
-				
-				consec_connect_fails++;
-			}
-			
-			synchronized( this ){
-				
-				if ( failed ){
-					
-					return;
-				}
-				
-				failed = true;
-				
-				bm = active_message;
-				
-				active_message	 = null;
-			}
-			
-			logMessage( "Con " + getString() + " failed: " + Debug.getNestedExceptionMessage( error ));
-			
-			try{
-				if ( !closing ){
-					
-					if ( TRACE ){
-						System.out.println( dir_str + " connection error:" );
-					}
-				}
-				
-				fragment_handler.close();
-
-			}finally{
-								
-				removeConnection( this );
-				
-				if ( bm != null ){
-					
-					bm.reportFailed( error );
-				}
-			}
-		}
-		
-		protected String
-		getString()
-		{
-			return( getString( false ));
-		}
-		
-		protected String
-		getString(
-			boolean	short_form )
-		{
-			if ( short_form ){
-				
-				return( fragment_handler.getString());
-				
-			}else{
-				
-				return("id=" + connection_id + ",dir=" + ( outgoing?"out":"in" ));
-			}
-		}
-	}
-	
-	protected class
-	fragmentHandler
-		implements GenericMessageConnectionListener
-	{
-		private GenericMessageConnection	connection;
-		private fragmentHandlerReceiver		receiver;
-		
-		private int	next_fragment_id	= 0;
-		
-		private fragmentAssembly	current_request_frag;
-		private fragmentAssembly	current_reply_frag;
-		
-		private int					send_count;
-		private int					recv_count;
-		
-		protected
-		fragmentHandler(
-			GenericMessageConnection	_connection,
-			fragmentHandlerReceiver		_receiver )
-		{
-			connection	= _connection;
-			receiver	= _receiver;	
-		}
-	
-		public void
-		start()
-		{
-			connection.addListener( this );
-		}
-		
-		public void
-		connected(
-			GenericMessageConnection	connection )
-		{
-			receiver.connected();
-		}
-		
-		public void
-		failed(
-			GenericMessageConnection	connection,
-			Throwable 					error )
-		
-			throws MessageException
-		{
-			receiver.failed( error );
-		}
-		
-		protected void
-		send(
-			Map			data_map,
-			boolean		is_request,
-			boolean		record_active )
-			
-			throws BuddyPluginException
-		{
-			try{
-				byte[] data = BEncoder.encode( data_map );
-				
-				int	data_length = data.length;
-				
-				plugin.checkMaxMessageSize( data_length );
-				
-				int	max_chunk = connection.getMaximumMessageSize() - 1024;
-								
-				if ( data_length > max_chunk ){
-					
-					int	fragment_id;
-					
-					synchronized( this ){
-						
-						fragment_id = next_fragment_id++;
-					}
-					
-					int chunk_num = 0;
-					
-					for (int i=0;i<data_length;i+=max_chunk){
-						
-						int	end = Math.min( data_length, i + max_chunk );
-						
-						if ( end > i ){
-							
-							byte[]	chunk = new byte[ end-i ];
-							
-							System.arraycopy( data, i, chunk, 0, chunk.length );
-							
-							Map	chunk_map = new HashMap();
-							
-							chunk_map.put( "type", new Long( BuddyPlugin.RT_INTERNAL_FRAGMENT ));
-							chunk_map.put( "f", new Long( fragment_id ));
-							chunk_map.put( "l", new Long( data_length ));
-							chunk_map.put( "c", new Long( max_chunk ));
-							chunk_map.put( "i", new Long( chunk_num ));
-							chunk_map.put( "q", new Long( is_request?1:0 ));
-							chunk_map.put( "d", chunk );
-							
-							byte[] chunk_data = BEncoder.encode( chunk_map );
-
-							PooledByteBuffer chunk_buffer = 
-								plugin.getPluginInterface().getUtilities().allocatePooledByteBuffer( chunk_data );
-						
-							try{									
-								connection.send( chunk_buffer );
-							
-								chunk_buffer = null;
-								
-							}finally{
-								
-								if ( chunk_buffer != null ){
-									
-									chunk_buffer.returnToPool();
-								}
-							}
-						}
-						
-						chunk_num++;
-					}
-				}else{
-					
-					PooledByteBuffer buffer = 
-						plugin.getPluginInterface().getUtilities().allocatePooledByteBuffer( data );
-				
-					try{			
-					
-						connection.send( buffer );
-					
-						buffer = null;
-						
-					}finally{
-						
-						if ( buffer != null ){
-							
-							buffer.returnToPool();
-						}
-					}
-				}
-				
-				buddyMessageSent( data.length, record_active );
-				
-				send_count++;
-				
-			}catch( Throwable e ){
-				
-				throw( new BuddyPluginException( "Send failed", e ));
-			}
-		}
-		
-		public void
-		receive(
-			GenericMessageConnection	connection,
-			PooledByteBuffer			message )
-		
-			throws MessageException
-		{
-			try{
-					// while in unauth state we only allow a few messages. max should be 1
-					// for an 'accept request' but I feel generous
-				
-				if ( recv_count >= 4 && !isAuthorised()){
-				
-					throw( new MessageException( "Too many messages received while in unauthorised state" ));
-				}
-				
-				byte[]	content = message.toByteArray();
-				
-				Map	data_map = BDecoder.decode( content );
-				
-				if (((Long)data_map.get( "type" )).intValue() == BuddyPlugin.RT_INTERNAL_FRAGMENT ){
-					
-					Map	chunk_map = data_map;
-					
-					int	fragment_id = ((Long)chunk_map.get( "f" )).intValue();
-					int	data_length = ((Long)chunk_map.get( "l" )).intValue();
-					int	chunk_size 	= ((Long)chunk_map.get( "c" )).intValue();
-					int	chunk_num 	= ((Long)chunk_map.get( "i" )).intValue();
-					
-					boolean	is_request = ((Long)chunk_map.get("q")).intValue() == 1;
-					
-					byte[]	chunk_data = (byte[])chunk_map.get("d" );
-					
-					plugin.checkMaxMessageSize( data_length );
-					
-					fragmentAssembly assembly;
-					
-					if ( is_request ){
-						
-						if ( current_request_frag == null ){
-							
-							current_request_frag = new fragmentAssembly( fragment_id, data_length, chunk_size );
-						}
-						
-						assembly = current_request_frag;
-						
-					}else{
-						
-						if ( current_reply_frag == null ){
-							
-							current_reply_frag = new fragmentAssembly( fragment_id, data_length, chunk_size );
-						}
-						
-						assembly = current_reply_frag;
-					}
-					
-					if ( assembly.getID() != fragment_id ){
-							
-						throw( new BuddyPluginException( "Fragment receive error: concurrent decode not supported" ));
-					}
-					
-					if ( assembly.receive( chunk_num, chunk_data )){
-										
-						if ( is_request ){
-
-							current_request_frag = null;
-							
-						}else{
-							
-							current_reply_frag = null;
-						}
-						
-						buddyMessageReceived( data_length );
-
-						recv_count++;
-						
-						receiver.receive( BDecoder.decode( assembly.getData()));
-						
-					}else{
-						
-						buddyMessageFragmentReceived( assembly.getChunksReceived(), assembly.getTotalChunks());
-					}
-				}else{
-				
-					buddyMessageReceived( content.length );
-
-					recv_count++;
-					
-					receiver.receive( data_map );					
-				}
-			}catch( Throwable e ){
-				
-				receiver.failed( e );
-				
-			}finally{
-				
-				message.returnToPool();
-			}
-		}
-		
-		protected void
-		close()
-		{
-			try{
-			
-				connection.close();
-				
-			}catch( Throwable e ){
-				
-				// Debug.printStackTrace( e );
-				
-			}finally{
-				
-				receiver.failed( new Exception( "Connection closed" ));
-			}
-		}
-		
-		protected String
-		getString()
-		{
-			return( connection.getType());
-		}
-		
-		protected class
-		fragmentAssembly
-		{
-			private int		id;
-			private byte[]	data;
-			private int		chunk_size;
-			
-			private int		num_chunks;
-			private Set		chunks_received = new HashSet();
-			
-			protected
-			fragmentAssembly(
-				int		_id,
-				int		_length,
-				int		_chunk_size )
-			{
-				id			= _id;
-				chunk_size	= _chunk_size;
-				
-				data		= new byte[_length];
-				
-				num_chunks = (_length + chunk_size - 1 )/chunk_size;
-			}
-			
-			protected int
-			getID()
-			{
-				return( id );
-			}
-			
-			protected int
-			getChunksReceived()
-			{
-				return( chunks_received.size());
-			}
-			
-			protected int
-			getTotalChunks()
-			{
-				return( num_chunks );
-			}
-			
-			protected boolean
-			receive(
-				int		chunk_num,
-				byte[]	chunk )
-			{
-				// System.out.println( "received chunk " + chunk_num + " of " + num_chunks );
-				
-				Integer	i = new Integer( chunk_num );
-				
-				if ( chunks_received.contains( i )){
-					
-					return( false );
-				}
-				
-				chunks_received.add( i );
-				
-				System.arraycopy( chunk, 0, data, chunk_num*chunk_size, chunk.length );
-				
-				return( chunks_received.size() == num_chunks );
-			}
-			
-			protected byte[]
-			getData()
-			{
-				return( data );
-			}
-		}
-	}	
-	
-	interface
-	fragmentHandlerReceiver
-	{
-		public void
-		connected();
-		
-		public void
-		receive(
-			Map			data );
-		
-		public void
-		failed(
-			Throwable	error );
-	}
-}
+/*
+ * Created on Apr 1, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+import java.io.File;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.*;
+
+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.AddressUtils;
+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.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;
+import org.gudy.azureus2.plugins.messaging.generic.GenericMessageConnectionListener;
+import org.gudy.azureus2.plugins.messaging.generic.GenericMessageEndpoint;
+import org.gudy.azureus2.plugins.messaging.generic.GenericMessageRegistration;
+import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
+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 com.aelitis.azureus.core.util.AZ3Functions;
+
+
+public class 
+BuddyPluginBuddy 
+{
+	private static final boolean TRACE = BuddyPlugin.TRACE;
+	
+	private static final int CONNECTION_IDLE_TIMEOUT	= 5*60*1000;
+	private static final int CONNECTION_KEEP_ALIVE		= 1*60*1000;
+	
+	private static final int MAX_ACTIVE_CONNECTIONS		= 5;
+	private static final int MAX_QUEUED_MESSAGES		= 256;
+	
+	private static final int RT_REQUEST_DATA	= 1;
+	
+	private static final int RT_REPLY_DATA		= 2;	
+	private static final int RT_REPLY_ERROR		= 99;
+
+	
+	private BuddyPlugin		plugin;
+	private long			created_time;
+	private int				subsystem;
+	private boolean			authorised;
+	private String			public_key;
+	private String			nick_name;
+	private List<Long>		recent_ygm;
+	
+	private int				last_status_seq;
+	
+	private long			post_time;
+	private InetAddress		ip;
+	private int				tcp_port;
+	private int				udp_port;
+	private int				online_status	= BuddyPlugin.STATUS_ONLINE;	// default
+		
+	private int				version		= BuddyPlugin.VERSION_CHAT;	// assume everyone now supports chat
+	
+	private boolean			online;
+	private long			last_time_online;
+	
+	private long			status_check_count;
+	private long			last_status_check_time;
+	
+	private boolean			check_active;
+		
+	private List<buddyConnection>		connections	= new ArrayList<buddyConnection>();
+	private List<buddyMessage>			messages	= new ArrayList<buddyMessage>();
+	private buddyMessage				current_message;
+	
+	private int	next_connection_id;
+	private int	next_message_id;
+	
+	private boolean	ygm_active;
+	private boolean	ygm_pending;
+	
+	private long 	latest_ygm_time;
+	private String	last_message_received;
+	
+	private Set<Long>		offline_seq_set;
+	
+	private int		message_out_count;
+	private int		message_in_count;
+	private int		message_out_bytes;
+	private int		message_in_bytes;
+	
+	private String	received_frag_details = "";
+	
+	private BuddyPluginBuddyMessageHandler		persistent_msg_handler;
+
+	private Map<Object,Object>		user_data = new LightHashMap<Object,Object>();
+	
+	private boolean	keep_alive_outstanding;
+	private volatile long	last_connect_attempt	= SystemTime.getCurrentTime();
+	private volatile int	consec_connect_fails;
+	
+	private long last_auto_reconnect	= -1;
+	
+	private Object				rss_lock = new Object();
+	
+	private Set<String>			rss_local_cats;
+	private Set<String>			rss_remote_cats;
+	private Set<String>			rss_cats_read;
+	
+	private AESemaphore			outgoing_connect_sem = new AESemaphore( "BPB:outcon", 1 );
+	
+	private volatile boolean	closing;
+	private volatile boolean	destroyed;
+	
+	protected
+	BuddyPluginBuddy(
+		BuddyPlugin	_plugin,
+		long		_created_time,
+		int			_subsystem,
+		boolean		_authorised,
+		String		_pk,
+		String		_nick_name,
+		int			_version,
+		String		_rss_local_cats,
+		String		_rss_remote_cats,
+		int			_last_status_seq,
+		long		_last_time_online,
+		List<Long>	_recent_ygm )
+	{
+		plugin				= _plugin;
+		created_time		= _created_time;
+		subsystem			= _subsystem;
+		authorised			= _authorised;
+		public_key 			= _pk;
+		nick_name			= _nick_name;
+		version				= Math.max( version, _version );
+		rss_local_cats		= stringToCats( _rss_local_cats );
+		rss_remote_cats		= stringToCats( _rss_remote_cats );
+		last_status_seq		= _last_status_seq;
+		last_time_online	= _last_time_online;
+		recent_ygm			= _recent_ygm;
+		
+		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()
+	{
+		return( plugin );
+	}
+	
+	public BuddyPluginBuddyMessageHandler
+	getMessageHandler()
+	{
+		return( persistent_msg_handler );
+	}
+	
+	protected void
+	persistentDispatchPending()
+	{
+		plugin.persistentDispatchPending( this );
+	}
+	
+	protected void
+	checkPersistentDispatch()
+	{
+		persistent_msg_handler.checkPersistentDispatch();
+	}
+	
+	protected void
+	persistentDispatch()
+	{
+		persistent_msg_handler.persistentDispatch();
+	}
+	
+	public Map
+	readConfigFile(
+		File		name )
+	{
+		return( plugin.readConfigFile( name ));
+	}
+	
+	public boolean
+	writeConfigFile(
+		File		name,
+		Map			data )
+	{
+		return( plugin.writeConfigFile( name, data ));
+	}
+	
+	protected long
+	getCreatedTime()
+	{
+		return( created_time );
+	}
+	
+	public int
+	getSubsystem()
+	{
+		return( subsystem );
+	}
+	
+	protected void
+	setSubsystem(
+		int		_s )
+	{
+		subsystem = _s;
+	}
+	
+	public boolean
+	isAuthorised()
+	{
+		return( authorised );
+	}
+	
+	protected void
+	setAuthorised(
+		boolean		_a )
+	{
+		authorised = _a;
+	}
+	
+	public String
+	getPublicKey()
+	{
+		return( public_key );
+	}
+	
+	protected byte[]
+	getRawPublicKey()
+	{
+		return( Base32.decode( public_key ));
+	}
+	
+	protected String
+	getShortString()
+	{
+		return( public_key.substring( 0, 16 ) + "..." );
+	}
+	
+	public String
+	getNickName()
+	{
+		return( nick_name );
+	}
+	
+	public int
+	getVersion()
+	{
+		return( version );
+	}
+	
+	protected void
+	setVersion(
+		int		v )
+	{
+		if ( version < v ){
+			
+			version = v;
+			
+			plugin.fireDetailsChanged( this );
+		}
+	}
+	
+	public String
+	getLocalAuthorisedRSSTagsOrCategoriesAsString()
+	{
+		synchronized( rss_lock ){
+		
+			return( catsToString( rss_local_cats ));
+		}
+	}
+	
+	public Set<String>
+  	getLocalAuthorisedRSSTagsOrCategories()
+  	{
+		synchronized( rss_lock ){
+  		
+			return( rss_local_cats );
+		}
+  	}
+	
+	public void
+	addLocalAuthorisedRSSTagOrCategory(
+		String	category )
+	{
+		category = plugin.normaliseCat( category );
+	
+		boolean dirty;
+		
+		synchronized( rss_lock ){
+			
+			if ( rss_local_cats == null ){
+				
+				rss_local_cats = new HashSet<String>();
+			}
+			
+			if ( dirty = !rss_local_cats.contains( category )){
+							
+				rss_local_cats.add( category );
+			}
+		}
+		
+		if ( dirty ){
+			
+			plugin.setConfigDirty();
+			
+			plugin.fireDetailsChanged( this );
+			
+				// tell buddy of change
+			
+			if ( isConnected()){
+				
+				sendKeepAlive();
+			}
+		}
+	}
+	
+	public void
+	removeLocalAuthorisedRSSTagOrCategory(
+		String	category )
+	{
+		category = plugin.normaliseCat( category );
+		
+		boolean	dirty;
+		
+		synchronized( rss_lock ){
+			
+			if ( rss_local_cats == null ){
+			
+				return;
+			
+			}else{
+		
+				dirty = rss_local_cats.remove( category );
+			}
+		}
+		
+		if ( dirty ){
+			
+			plugin.setConfigDirty();
+		
+			plugin.fireDetailsChanged( this );
+			
+				// tell buddy of change
+			
+			if ( isConnected()){
+				
+				sendKeepAlive();
+			}
+		}
+	}
+	
+	public void
+	setLocalAuthorisedRSSTagsOrCategories(
+		String			new_cats )
+	{
+		setLocalAuthorisedRSSTagsOrCategories( stringToCats( new_cats ));
+	}
+	
+	public void
+	setLocalAuthorisedRSSTagsOrCategories(
+		Set<String>		new_cats )
+	{	
+		plugin.normaliseCats( new_cats );
+		
+		boolean dirty;
+		
+		synchronized( rss_lock ){
+			
+			if ( dirty = !catsIdentical( new_cats, rss_local_cats) ){
+			
+				rss_local_cats = new_cats;
+			}
+		}
+		
+		if ( dirty ){
+			
+			plugin.setConfigDirty();
+			
+			plugin.fireDetailsChanged( this );
+			
+				// tell buddy of change
+			
+			if ( isConnected()){
+				
+				sendKeepAlive();
+			}
+		}	
+	}
+	
+	public Set<String>
+  	getRemoteAuthorisedRSSTagsOrCategories()
+  	{
+  		return( rss_remote_cats );
+  	}
+	
+	public String
+	getRemoteAuthorisedRSSTagsOrCategoriesAsString()
+	{
+		return( catsToString( rss_remote_cats ));
+	}
+	
+	protected void
+	setRemoteAuthorisedRSSTagsOrCategories(
+		Set<String>		new_cats )
+	{
+		plugin.normaliseCats( new_cats );
+		
+		boolean	dirty;
+		
+		synchronized( rss_lock ){
+			
+			if ( dirty = !catsIdentical( new_cats, rss_remote_cats) ){
+			
+				rss_remote_cats = new_cats;
+			}
+		}
+		
+		if ( dirty ){
+			
+			plugin.setConfigDirty();
+			 
+			plugin.fireDetailsChanged( this );
+		}
+	}
+	
+	public boolean
+	isLocalRSSTagOrCategoryAuthorised(
+		String	category )
+	{
+		category = plugin.normaliseCat( category );
+	
+		synchronized( rss_lock ){
+			
+			if ( rss_local_cats != null ){
+			
+				return( rss_local_cats.contains( category ));
+			}
+		
+			return( false );
+		}
+	}
+	
+	public boolean
+	isRemoteRSSTagOrCategoryAuthorised(
+		String	category )
+	{
+		category = plugin.normaliseCat( category );
+		
+		synchronized( rss_lock ){
+			
+			if ( rss_remote_cats != null ){
+			
+				return( rss_remote_cats.contains( category ));
+			}
+			
+			return( false );
+		}
+	}
+	
+	protected void
+	localRSSTagOrCategoryRead(
+		String		str )
+	{
+		boolean dirty;
+		
+		synchronized( rss_lock ){
+			
+			if ( rss_cats_read == null ){
+				
+				rss_cats_read = new HashSet<String>();
+			}
+			
+			dirty = rss_cats_read.add( str );
+		}
+		
+		if ( dirty ){
+			
+			// not persisted currently - plugin.setConfigDirty();
+			 
+			plugin.fireDetailsChanged( this );
+		}
+	}
+	
+	public String
+	getLocalReadTagsOrCategoriesAsString()
+	{
+		synchronized( rss_lock ){
+
+			return( catsToString( rss_cats_read ));
+		}
+	}
+	
+	public URL
+	getSubscriptionURL(
+		String		cat )
+	{
+		String url = "azplug:?id=azbuddy&name=Friends&arg=";
+		
+		String arg = "pk=" + getPublicKey() + "&cat=" + cat;
+
+		try{
+			url += URLEncoder.encode( arg, "UTF-8" );
+			
+			return( new URL( url ));
+			
+		}catch( Throwable e ){
+	
+			Debug.out( e );
+			
+			return( null );
+		}
+	}
+	
+	public void
+	subscribeToCategory(
+		String	cat )
+	
+		throws BuddyPluginException
+	{
+		AZ3Functions.provider az3 = AZ3Functions.getProvider();
+
+		if ( az3 == null ){
+			
+			throw( new BuddyPluginException( "AZ3 subsystem not available" ));
+		}
+		
+		try{
+			az3.subscribeToRSS( 
+				getName() + ": " + cat, 
+				getSubscriptionURL(cat),
+				15,
+				false,
+				getPublicKey() + ":" + cat );
+				
+		}catch( Throwable e ){
+				
+			throw( new BuddyPluginException( "Failed to add subscription", e ));
+		}
+	}
+	
+	public boolean
+	isSubscribedToTagOrCategory(
+		String	cat,
+		String	creator_ref )
+	{
+		if ( creator_ref == null ){
+			
+			return( false );
+		}
+		
+		return( creator_ref.equals( getPublicKey() + ":" + cat ));
+	}
+	
+	protected String
+	catsToString(
+		Set<String>	cats )
+	{
+		if ( cats == null || cats.size() == 0 ){
+			
+			return( null );
+		}
+		
+		String	str = "";
+		
+		for (String s:cats ){
+			
+			str += (str.length()==0?"":",") + s;
+		}
+		
+		return( str );
+	}
+	
+	protected boolean
+	catsIdentical(
+		Set<String>	c1,
+		Set<String>	c2 )
+	{
+		if ( c1 == null && c2 == null ){
+			
+			return( true );
+			
+		}else if ( c1 == null || c2 == null ){
+			
+			return( false );
+			
+		}else{
+			
+			return( c1.equals( c2 ));
+		}
+	}
+	
+	protected Set<String>
+	stringToCats(
+		String	str )
+	{
+		if ( str == null ){
+			
+			return( null );
+		}
+		
+		String[] bits = str.split( "," );
+		
+		Set<String> res = new HashSet<String>( bits.length );
+		
+		for ( String b: bits ){
+			
+			b = b.trim();
+			
+			if ( b.length() > 0 ){
+				
+				res.add( b );
+			}
+		}
+		
+		if ( res.size() == 0 ){
+			
+			return( null );
+		}
+		
+		return( res );
+	}
+	
+	public int
+	getOnlineStatus()
+	{
+		return( online_status );
+	}
+	
+	protected void
+	setOnlineStatus(
+		int		s )
+	{
+		if ( online_status != s ){
+			
+			online_status = s;
+			
+			plugin.fireDetailsChanged( this );
+		}
+	}
+	
+	public String
+	getName()
+	{
+		if ( nick_name != null ){
+			
+			return( nick_name );
+		}
+		
+		return( getShortString());
+	}
+	
+	public void
+	remove()
+	{
+		persistent_msg_handler.destroy();
+		
+		plugin.removeBuddy( this );
+	}
+	
+	public InetAddress
+	getIP()
+	{
+		return( ip );
+	}
+	
+	public InetAddress
+	getAdjustedIP()
+	{
+		if ( ip == null ){
+			
+			return( null );
+		}
+		
+		InetSocketAddress address = new InetSocketAddress( ip, tcp_port );
+		
+		InetSocketAddress adjusted_address = AddressUtils.adjustTCPAddress( address, true );
+		
+		if ( adjusted_address != address ){
+			
+			return( adjusted_address.getAddress());
+		}
+		
+		address = new InetSocketAddress( ip, udp_port );
+		
+		adjusted_address = AddressUtils.adjustUDPAddress( address, true );
+		
+		if ( adjusted_address != address ){
+			
+			return( adjusted_address.getAddress());
+		}
+	
+		return( ip );
+	}
+	
+	public List
+	getAdjustedIPs()
+	{
+		List	result = new ArrayList();
+		
+		if ( ip == null ){
+			
+			return( result );
+		}
+		
+		InetAddress adjusted = getAdjustedIP();
+		
+		if ( adjusted == ip ){
+			
+			result.add( ip );
+			
+		}else{
+			
+			List l = AddressUtils.getLANAddresses( adjusted.getHostAddress());
+			
+			for (int i=0;i<l.size();i++){
+				
+				try{
+					result.add( InetAddress.getByName((String)l.get(i)));
+					
+				}catch( Throwable e ){
+					
+				}
+			}
+		}
+		
+		return( result );
+	}
+
+	
+	public int
+	getTCPPort()
+	{
+		return( tcp_port );
+	}
+	
+	public int
+	getUDPPort()
+	{
+		return( udp_port );
+	}
+	
+	public boolean
+	isOnline(
+		boolean	is_connected )
+	{
+		boolean	connected = isConnected();
+		
+			// if we're connected then we're online whatever
+		
+		if ( connected ){
+			
+			return( true );
+		}
+		
+		if ( !online ){
+			
+			return( false );
+		}
+	
+		if ( is_connected ){
+		
+			return( false );
+			
+		}else{
+			
+			return( true );
+		}
+	}
+	
+	protected boolean
+	isIdle()
+	{
+		synchronized( this ){
+		
+			return( connections.size() == 0 );
+		}
+	}
+	
+	public long
+	getLastTimeOnline()
+	{
+		return( last_time_online );
+	}
+	
+	public BuddyPlugin.cryptoResult
+	encrypt(
+		byte[]		payload )
+	
+		throws BuddyPluginException
+	{
+		return( plugin.encrypt( this, payload ));
+	}
+	
+	public BuddyPlugin.cryptoResult
+	decrypt(
+		byte[]		payload )
+	
+		throws BuddyPluginException
+	{
+		return( plugin.decrypt( this, payload, getName() ));
+	}
+	
+	public boolean
+	verify(
+		byte[]		payload,
+		byte[]		signature )
+	
+		throws BuddyPluginException
+	{
+		
+		return( plugin.verify( this, payload, signature ));
+	}
+	
+	public BuddyPluginBuddyMessage
+	storeMessage(
+		int		type,
+		Map		msg )
+	{
+		return( persistent_msg_handler.storeExplicitMessage( type, msg ));
+	}
+	
+	public List<BuddyPluginBuddyMessage>
+	retrieveMessages(
+		int		type )
+	{
+		return( persistent_msg_handler.retrieveExplicitMessages( type ));
+	}
+	
+	public void
+	setMessagePending()
+	
+		throws BuddyPluginException
+	{
+		synchronized( this ){
+			
+			if ( ygm_active ){
+				
+				ygm_pending = true;
+				
+				return;
+			}
+			
+			ygm_active = true;
+		}
+		
+		plugin.setMessagePending( 
+			this,
+			new BuddyPlugin.operationListener()
+			{
+				public void 
+				complete() 
+				{
+					boolean	retry;
+					
+					synchronized( BuddyPluginBuddy.this ){
+						
+						ygm_active = false;
+						
+						retry = ygm_pending;
+						
+						ygm_pending = false;
+					}
+					
+					if ( retry ){
+						
+						try{
+							setMessagePending();
+							
+						}catch( BuddyPluginException e ){
+							
+							log( "Failed to send YGM", e );
+						}
+					}
+				}	
+			});
+	}
+	
+	public long
+	getLastMessagePending()
+	{
+		return( latest_ygm_time );
+	}
+	
+	protected boolean
+	addYGMMarker(
+		long		marker )
+	{
+		Long	l = new Long( marker );
+		
+		synchronized( this ){
+		
+			if ( recent_ygm == null ){
+				
+				recent_ygm = new ArrayList<Long>();
+			}
+			
+			if ( recent_ygm.contains( l )){
+				
+				return( false );
+			}
+			
+			recent_ygm.add( l );
+			
+			if ( recent_ygm.size() > 16 ){
+				
+				recent_ygm.remove(0);
+			}
+			
+			latest_ygm_time = SystemTime.getCurrentTime();
+		}
+		
+		plugin.setConfigDirty();
+		
+		plugin.fireDetailsChanged( this );
+		
+		return( true );
+	}
+	
+	protected void
+	setLastMessageReceived(
+		String		str )
+	{
+		last_message_received = str;
+		
+		plugin.fireDetailsChanged( this );
+	}
+	
+	public String
+	getLastMessageReceived()
+	{
+		return( last_message_received==null?"":last_message_received );
+	}
+	
+	protected List<Long>
+	getYGMMarkers()
+	{
+		synchronized( this ){
+		
+			return( recent_ygm==null?null:new ArrayList<Long>( recent_ygm ));
+		}
+	}
+	
+	protected int
+	getLastStatusSeq()
+	{
+		synchronized( this ){
+			
+			return( last_status_seq );
+		}
+	}
+	
+	protected void
+	buddyConnectionEstablished(
+		boolean		outgoing )
+	{
+		buddyActive();
+	}
+	
+	protected void
+	buddyMessageSent(
+		int			size,
+		boolean		record_active )
+	{
+		message_out_count++;
+		message_out_bytes += size;
+		
+		if ( record_active ){
+		
+			buddyActive();
+		}
+	}
+	
+	protected void
+	buddyMessageReceived(
+		int		size )
+	{		
+		message_in_count++;
+		message_in_bytes += size;
+		
+		received_frag_details = "";
+		
+		buddyActive();
+	}
+	
+	protected void
+	buddyMessageFragmentReceived(
+		int		num_received,
+		int		total )
+	{
+		received_frag_details = num_received + "/" + total;
+		
+		plugin.fireDetailsChanged( this );
+	}
+	
+	public String
+	getMessageInFragmentDetails()
+	{
+		return( received_frag_details );
+	}
+	
+	public int
+	getMessageInCount()
+	{
+		return( message_in_count );
+	}
+	
+	public int
+	getMessageOutCount()
+	{
+		return( message_out_count );
+	}
+	
+	public int
+	getBytesInCount()
+	{
+		return( message_in_bytes );
+	}
+	
+	public int
+	getBytesOutCount()
+	{
+		return( message_out_bytes );
+	}
+	
+	public boolean
+	isConnected()
+	{
+		boolean connected = false;
+		
+		synchronized( this ){
+						
+			for (int i=0;i<connections.size();i++){
+				
+				buddyConnection c = (buddyConnection)connections.get(i);
+				
+				if ( c.isConnected() && !c.hasFailed()){
+					
+					connected = true;
+				}
+			}
+		}
+		
+		return( connected );
+	}
+	
+	protected void
+	buddyActive()
+	{
+		long	now = SystemTime.getCurrentTime();
+		
+		synchronized( this ){
+			
+			last_time_online			= now;
+			online						= true;
+		}
+			
+		persistentDispatchPending();
+		
+		plugin.fireDetailsChanged( this );
+	}
+	
+	public void
+	ping()
+		throws BuddyPluginException
+	{
+		plugin.checkAvailable();
+		
+		try{
+			Map	ping_request = new HashMap();
+			
+			ping_request.put( "type", new Long( BuddyPlugin.RT_INTERNAL_REQUEST_PING ));
+			
+			sendMessage(
+				BuddyPlugin.SUBSYSTEM_INTERNAL,
+				ping_request,
+				60*1000,
+				new BuddyPluginBuddyReplyListener()
+				{
+					public void
+					replyReceived(
+						BuddyPluginBuddy	from_buddy,
+						Map					reply )
+					{
+						log( "Ping reply received:" + reply );
+					}
+					
+					public void
+					sendFailed(
+						BuddyPluginBuddy		to_buddy,
+						BuddyPluginException	cause )
+					{
+						log( "Ping failed to " + getString(), cause );
+					}
+				});
+			
+		}catch( Throwable e ){
+						
+			throw( new BuddyPluginException( "Ping failed", e ));
+		}
+	}
+	
+	protected void
+	sendCloseRequest(
+		boolean		restarting )
+	{
+		List	to_send = new ArrayList();
+	
+		synchronized( this ){
+				
+			closing	= true;
+			
+			for (int i=0;i<connections.size();i++){
+				
+				buddyConnection c = (buddyConnection)connections.get(i);
+				
+				if ( c.isConnected() && !c.hasFailed() && !c.isActive()){
+					
+					to_send.add( c );
+				}
+			}
+		}
+		
+		for (int i=0;i<to_send.size();i++){
+			
+			buddyConnection c = (buddyConnection)to_send.get(i);
+			
+			try{
+				Map	close_request = new HashMap();
+				
+				close_request.put( "type", new Long( BuddyPlugin.RT_INTERNAL_REQUEST_CLOSE ));
+				
+				close_request.put( "r", new Long( restarting?1:0));
+				
+				close_request.put( "os", new Long( plugin.getCurrentStatusSeq()));
+				
+				final buddyMessage	message = 
+					new buddyMessage( BuddyPlugin.SUBSYSTEM_INTERNAL, close_request, 60*1000 );
+
+				message.setListener(
+						new BuddyPluginBuddyReplyListener()
+						{
+							public void
+							replyReceived(
+								BuddyPluginBuddy	from_buddy,
+								Map					reply )
+							{
+								log( "Close reply received:" + reply );
+							}
+							
+							public void
+							sendFailed(
+								BuddyPluginBuddy		to_buddy,
+								BuddyPluginException	cause )
+							{
+								log( "Close failed to " + getString(), cause );
+							}
+						});
+				
+				c.sendCloseMessage( message );
+
+			}catch( Throwable e ){
+							
+				log( "Close request failed", e );
+			}
+		}
+	}
+	
+	protected void
+	receivedCloseRequest(
+		Map		request )
+	{
+		List<buddyConnection>	closing = new ArrayList<buddyConnection>();
+		
+		synchronized( this ){
+			
+			closing.addAll( connections );
+		}
+		
+		for (int i=0;i<closing.size();i++){
+			
+			((buddyConnection)closing.get(i)).remoteClosing();
+		}
+		
+		try{
+			boolean	restarting = ((Long)request.get( "r" )).longValue() == 1;
+			
+			if ( restarting ){
+				
+				logMessage( "restarting" );
+				
+			}else{
+				
+				logMessage( "going offline" );
+				
+				boolean	details_change = false;
+				
+				synchronized( this ){
+					
+					if ( offline_seq_set == null ){
+						
+						offline_seq_set = new HashSet<Long>();
+					}
+					
+					offline_seq_set.add( new Long( last_status_seq ));
+					
+					offline_seq_set.add((Long)request.get( "os" ));
+					
+					if ( online ){
+						
+						online					= false;
+						consec_connect_fails	= 0;
+						
+						details_change	= true;
+					}
+				}
+				
+				if ( details_change ){
+					
+					plugin.fireDetailsChanged( this );
+				}
+			}
+		}catch( Throwable e ){
+			
+			Debug.out( "Failed to decode close request", e );
+		}
+	}
+	
+	public void
+	sendMessage(
+		final int								subsystem,
+		final Map								content,
+		final int								timeout_millis,
+		final BuddyPluginBuddyReplyListener		listener )
+	
+		throws BuddyPluginException
+	{
+		plugin.checkAvailable();
+		
+		boolean	wait = false;
+				
+		if ( ip == null ){
+			
+			synchronized( this ){
+				
+				wait = check_active;
+			}
+			
+			if ( !wait ){
+			
+				if ( SystemTime.getCurrentTime() - last_status_check_time > 30*1000 ){
+				
+					plugin.updateBuddyStatus( this );
+				
+					wait	= true;
+				}
+			}
+		}
+		
+		if ( wait ){
+			
+			new AEThread2( "BuddyPluginBuddy:sendWait", true )
+			{
+				public void
+				run()
+				{
+					try{
+						long	start = SystemTime.getCurrentTime();
+						
+						for (int i=0;i<20;i++){
+							
+							if ( ip != null ){
+								
+								break;
+							}
+							
+							Thread.sleep( 1000 );
+						}
+						
+						long	elapsed = SystemTime.getCurrentTime() - start;
+						
+						int new_tm = timeout_millis;
+						
+						if ( elapsed > 0 && timeout_millis > 0 ){
+							
+							new_tm -= elapsed;
+							
+							if ( new_tm <= 0 ){
+								
+								listener.sendFailed( BuddyPluginBuddy.this, new BuddyPluginException( "Timeout" ));
+								
+								return;
+							}
+						}
+						
+						sendMessageSupport( content, subsystem, new_tm, listener );
+						
+					}catch( Throwable e ){
+						
+						if ( e instanceof BuddyPluginException ){
+							
+							listener.sendFailed( BuddyPluginBuddy.this, (BuddyPluginException)e);
+						}else{
+						
+							listener.sendFailed( BuddyPluginBuddy.this, new BuddyPluginException( "Send failed", e ));
+						}
+					}
+				}				
+			}.start();
+			
+		}else{
+			
+			sendMessageSupport( content, subsystem, timeout_millis, listener );
+		}
+	}
+	
+	protected void
+	sendMessageSupport(
+		final Map								content,
+		final int								subsystem,
+		final int								timeout_millis,
+		final BuddyPluginBuddyReplyListener		original_listener )
+	
+		throws BuddyPluginException
+	{
+		boolean too_many_messages = false;
+		
+		synchronized( this ){
+		
+			too_many_messages = messages.size() >= MAX_QUEUED_MESSAGES;
+		}
+		
+		if ( too_many_messages ){
+			
+			throw( new BuddyPluginException( "Too many messages queued" ));
+		}
+		
+		final buddyMessage	message = new buddyMessage( subsystem, content, timeout_millis );
+		
+		BuddyPluginBuddyReplyListener	listener_delegate = 
+			new BuddyPluginBuddyReplyListener()
+			{
+				public void
+				replyReceived(
+					BuddyPluginBuddy		from_buddy,
+					Map						reply )
+				{
+					// logMessage( "Msg " + message.getString() + " ok" );
+					
+					try{
+						synchronized( BuddyPluginBuddy.this ){
+							
+							if ( current_message != message ){
+								
+								Debug.out( "Inconsistent: reply received not for current message" );
+							}
+							
+							current_message = null;
+						}
+						
+						original_listener.replyReceived( from_buddy, reply );
+						
+					}finally{
+						
+						dispatchMessage();
+					}
+				}
+				
+				public void
+				sendFailed(
+					BuddyPluginBuddy		to_buddy,
+					BuddyPluginException	cause )
+				{
+					logMessage( "Msg " + message.getString() + " failed: " + Debug.getNestedExceptionMessage( cause ));
+
+					try{
+							// only try and reconcile this failure with the current message if
+							// the message has actually been sent
+						
+						boolean	was_active;
+						
+						if ( cause instanceof BuddyPluginTimeoutException ){
+							
+							was_active = ((BuddyPluginTimeoutException)cause).wasActive();
+							
+						}else{
+							
+							was_active = true;
+						}
+						
+						if ( was_active ){
+							
+							synchronized( BuddyPluginBuddy.this ){
+								
+								if ( current_message != message ){
+									
+									Debug.out( "Inconsistent: error received not for current message" );
+								}
+								
+								current_message = null;
+							}
+						}
+						
+						long	now = SystemTime.getCurrentTime();
+						
+						int	retry_count = message.getRetryCount();
+						
+						if ( retry_count < 1 && !message.timedOut( now )){
+							
+							message.setRetry();
+							
+							// logMessage( "Msg " + message.getString() + " retrying" );
+
+							synchronized( BuddyPluginBuddy.this ){
+								
+								messages.add( 0, message );
+							}
+						}else{
+						
+							original_listener.sendFailed( to_buddy, cause );
+						}
+					}finally{
+							
+						dispatchMessage();
+					}
+				}
+			};
+			
+		message.setListener( listener_delegate );
+			
+		int	size;
+		
+		synchronized( this ){
+			
+			messages.add( message );
+			
+			size = messages.size();
+		}
+		
+		// logMessage( "Msg " + message.getString() + " added: num=" + size );
+		
+		dispatchMessage();
+	}
+	
+	protected void
+	dispatchMessage()
+	{
+		buddyConnection	bc = null;
+		
+		buddyMessage 	allocated_message 	= null;
+		Throwable		failed_msg_error 	= null;
+		
+		boolean	inform_dirty	= false;
+		
+		synchronized( this ){
+	
+			if ( current_message != null || messages.size() == 0 || closing ){
+				
+				return;
+			}
+			
+			allocated_message = current_message = (buddyMessage)messages.remove( 0 );
+			
+			for (int i=0;i<connections.size();i++){
+				
+				buddyConnection c = (buddyConnection)connections.get(i);
+				
+				if ( !c.hasFailed()){
+					
+					bc	= c;
+				}
+			}
+			
+			if ( bc == null ){
+				
+				if ( destroyed ){
+					
+					failed_msg_error = new BuddyPluginException( "Friend destroyed" );
+					
+				}else if ( connections.size() >= MAX_ACTIVE_CONNECTIONS ){
+					
+					failed_msg_error = new BuddyPluginException( "Too many active connections" );
+				}
+			}
+		}
+		
+		if ( failed_msg_error != null ){
+			
+			allocated_message.reportFailed( failed_msg_error );
+			
+			return;
+		}
+		
+		if ( bc == null ){
+			
+				// single-thread outgoing connect attempts
+			
+			try{
+				outgoing_connect_sem.reserve();
+			
+				synchronized( this ){
+
+					if ( current_message != allocated_message ){
+						
+						failed_msg_error = new BuddyPluginException( "current message no longer active" );
+						
+					}else if ( closing ){
+						
+						return;
+					}
+						
+					if ( failed_msg_error == null ){
+						
+						for (int i=0;i<connections.size();i++){
+							
+							buddyConnection c = (buddyConnection)connections.get(i);
+							
+							if ( !c.hasFailed()){
+								
+								bc	= c;
+							}
+						}
+						
+						if ( bc == null ){
+							
+							if ( destroyed ){
+								
+								failed_msg_error = new BuddyPluginException( "Friend destroyed" );
+								
+							}else if ( connections.size() >= MAX_ACTIVE_CONNECTIONS ){
+								
+								failed_msg_error = new BuddyPluginException( "Too many active connections" );
+							}
+						}
+					}
+				}
+				
+				if ( bc == null && failed_msg_error == null ){
+					
+					try{
+							// can't perform connect op while synchronized as may deadlock on password
+							// aquisition
+						
+						GenericMessageConnection generic_connection = outgoingConnection();
+
+						synchronized( this ){
+
+							if ( current_message != allocated_message ){
+								
+								failed_msg_error = new BuddyPluginException( "current message no longer active" );
+								
+								generic_connection.close();
+								
+							}else{
+								
+								bc = new buddyConnection( generic_connection, true );
+								
+								inform_dirty = connections.size() == 0;
+								
+								connections.add( bc );
+							
+								// logMessage( "Con " + bc.getString() + " added: num=" + connections.size() );
+							}
+						}
+					}catch( Throwable e ){
+						
+						failed_msg_error = e;
+					}
+				}
+			}finally{
+				
+				outgoing_connect_sem.release();
+			}
+		}
+			
+		if ( failed_msg_error != null ){
+			
+			allocated_message.reportFailed( failed_msg_error );
+			
+			return;
+		}
+			
+		try{
+			// logMessage( "Allocating msg " + allocated_message.getString() + " to con " + bc.getString());
+
+			bc.sendMessage( allocated_message );
+		
+		}catch( BuddyPluginException e ){
+			
+			allocated_message.reportFailed( e );
+		}
+		
+		if ( inform_dirty ){
+			
+			plugin.setConfigDirty();
+		}
+	}
+	
+	protected void
+	removeConnection(
+		buddyConnection			bc )
+	{
+		int	size;
+		
+		synchronized( this ){
+			
+			connections.remove( bc );
+			
+			size = connections.size();
+		}
+		
+		if ( size == 0 ){
+							
+			plugin.setConfigDirty();
+		}
+		
+		if ( size == 0 && bc.isConnected() && !bc.isClosing() && !bc.isRemoteClosing()){
+			
+				// dropped connection, kick in a keep alive 
+			
+			if ( consec_connect_fails < 3 ){
+				
+				if ( consec_connect_fails == 0 ){
+					
+					long	now = SystemTime.getMonotonousTime();
+					
+					boolean do_it = false;
+					
+					synchronized( this ){
+					
+						if ( 	last_auto_reconnect == -1 || 
+								now - last_auto_reconnect > 30*1000 ){
+							
+							last_auto_reconnect = now;
+							
+							do_it = true;
+						}
+					}
+					
+					if ( do_it ){
+						
+							// delay a bit
+						
+						new DelayedEvent(
+								"BuddyPluginBuddy:recon",
+								new Random().nextInt( 3000 ),
+								new AERunnable()
+								{
+									public void
+									runSupport()
+									{
+										int	size;
+										
+										synchronized( BuddyPluginBuddy.this ){
+																					
+											size = connections.size();
+										}
+										
+										if ( consec_connect_fails == 0 && size == 0 ){
+				
+											log( "Attempting reconnect after dropped connection" );
+											
+											sendKeepAlive();
+										}
+									}
+								});
+					}
+							
+				}else{
+					
+					long	delay = 60*1000;
+					
+					delay <<= Math.min( 3, consec_connect_fails );
+			
+					if ( SystemTime.getCurrentTime() - last_connect_attempt >= delay ){
+						
+						sendKeepAlive();
+					}
+				}
+			}
+		}
+		
+		// logMessage( "Con " + bc.getString() + " removed: num=" + size );
+
+			// connection failed, see if we need to attempt to re-establish
+		
+		plugin.fireDetailsChanged( this );
+		
+		dispatchMessage();
+	}
+	
+	protected long
+	getLastStatusCheckTime()
+	{
+		return( last_status_check_time );
+	}
+	
+	protected boolean
+	statusCheckActive()
+	{
+		synchronized( this ){
+
+			return( check_active );
+		}
+	}
+	
+	protected boolean
+	statusCheckStarts()
+	{
+		synchronized( this ){
+			
+			if ( check_active ){
+				
+				return( false );
+			}
+		
+			last_status_check_time = SystemTime.getCurrentTime();
+		
+			check_active = true;
+		}
+		
+		return( true );
+	}
+	
+	protected void
+	statusCheckFailed()
+	{
+		boolean	details_change = false;
+
+		synchronized( this ){
+
+			try{
+				if ( online ){
+					
+					online					= false;
+					consec_connect_fails	= 0;
+					
+					details_change	= true;
+				}
+			}finally{
+			
+				status_check_count++;
+				
+				check_active = false;
+			}
+		}
+			
+		if ( details_change ){
+			
+			plugin.fireDetailsChanged( this );
+		}
+	}
+	
+	protected void
+	setCachedStatus(
+		InetAddress		_ip,
+		int				_tcp_port,
+		int				_udp_port )
+	{
+		synchronized( this ){
+
+			if ( ip == null ){
+			
+				ip			= _ip;
+				tcp_port	= _tcp_port;
+				udp_port	= _udp_port;
+			}
+		}
+	}
+	
+	protected void
+	statusCheckComplete(
+		long			_post_time,
+		InetAddress		_ip,
+		int				_tcp_port,
+		int				_udp_port,
+		String			_nick_name,
+		int				_online_status,
+		int				_status_seq,
+		int				_version )
+	{
+		boolean	details_change 	= false;
+		boolean	config_dirty 	= false;
+
+		long	now = SystemTime.getCurrentTime();
+		
+		if ( now < last_time_online ){
+			
+			last_time_online = now;
+		}
+		
+		boolean is_connected = isConnected();
+		
+		synchronized( this ){
+
+			try{
+					// do we explicitly know that this sequence number denotes an offline buddy
+				
+				if ( offline_seq_set != null ){
+					
+					if ( offline_seq_set.contains(new Long( _status_seq ))){
+						
+						return;
+						
+					}else{
+						
+						offline_seq_set = null;
+					}
+				}
+				
+				boolean	seq_change = _status_seq != last_status_seq;
+				
+				boolean timed_out;
+
+					// change in sequence means we're online
+				
+				if ( seq_change ){
+					
+					last_status_seq		= _status_seq;
+					last_time_online	= now;
+					
+					timed_out 			= false;
+					details_change		= true;
+					
+				}else{
+				
+					timed_out =  now - last_time_online >= BuddyPlugin.STATUS_REPUBLISH_PERIOD * 3 ;
+				}	
+				
+				if ( online ){
+					
+					if ( timed_out ){
+							
+						online					= false;
+						consec_connect_fails	= 0;
+						
+						details_change	= true;
+					}
+				}else{	
+					
+					if ( seq_change || !timed_out ){
+						
+						online			= true;
+						details_change	= true;
+					}
+				}
+				
+				post_time	= _post_time;
+				
+				if ( 	!addressesEqual( ip, _ip ) ||
+						tcp_port != _tcp_port ||
+						udp_port != _udp_port ||
+						version	 < _version ){
+					
+					ip				= _ip;
+					tcp_port		= _tcp_port;
+					udp_port		= _udp_port;
+					
+					if ( version < _version ){
+					
+						version			= _version;
+					}
+					
+					details_change	= true;
+				}
+				
+					// if we are connected then we use the status sent over the connection
+					// as it is more up to date
+				
+				if ( 	!is_connected &&
+						online_status != _online_status ){
+					
+					online_status	= _online_status;
+					
+					details_change	= true;
+				}
+				
+				if ( !plugin.stringsEqual( nick_name, _nick_name )){
+					
+					nick_name	= _nick_name;
+					
+					config_dirty	= true;
+					details_change	= true;
+				}
+			}finally{
+			
+				status_check_count++;
+					
+				check_active = false;
+			}
+		}
+		
+		if ( config_dirty ){
+			
+			plugin.setConfigDirty();
+		}
+		
+		if ( details_change ){
+			
+			if ( online ){
+				
+				persistentDispatchPending();
+			}
+			
+			plugin.fireDetailsChanged( this );
+		}
+		
+		plugin.logMessage( getString());
+	}
+	
+	protected boolean
+	addressesEqual(
+		InetAddress		ip1,
+		InetAddress		ip2 )
+	{
+		if ( ip1 == null && ip2 == null ){
+			
+			return( true );
+			
+		}else if ( ip1 == null || ip2 == null ){
+			
+			return( false );
+			
+		}else{
+	
+			return( ip1.equals( ip2 ));
+		}
+	}
+	
+	protected void
+	checkTimeouts()
+	{
+		long	now = SystemTime.getCurrentTime();
+		
+		List	failed = null;
+		
+		List	connections_to_check = null;
+		
+		boolean	messages_queued;
+		
+		synchronized( this ){
+			
+			messages_queued = messages.size() > 0;
+			
+			if ( messages_queued ){
+							
+				Iterator	it = messages.iterator();
+				
+				while( it.hasNext()){
+					
+					buddyMessage	message = (buddyMessage)it.next();
+					
+					if ( message.timedOut( now )){
+						
+						it.remove();
+						
+						if ( failed == null ){
+							
+							failed = new ArrayList();
+						}
+						
+						failed.add( message );
+					}
+				}
+			}
+			
+			if ( connections.size() > 0 ){
+				
+				connections_to_check = new ArrayList( connections );
+			}
+		}
+		
+		boolean	send_keep_alive = false;
+
+		if ( connections_to_check == null ){			
+			
+				// no active connections
+			
+			if ( online && ip != null && !messages_queued ){
+				
+					// see if we should attempt a pre-emptive connect
+				
+				if ( consec_connect_fails < 3 ){
+					
+					long	delay = 60*1000;
+											
+					delay <<= Math.min( 3, consec_connect_fails );
+				
+					send_keep_alive = now - last_connect_attempt >= delay;
+				}
+			}
+		}else{
+			
+			for (int i=0;i<connections_to_check.size();i++){
+				
+				buddyConnection connection = (buddyConnection)connections_to_check.get(i);
+				
+				boolean closed = connection.checkTimeout( now );
+				
+				if ( 	ip != null &&
+						!closed && 
+						!messages_queued &&
+						connection.isConnected() && 
+						!connection.isActive()){
+					
+					if ( now - connection.getLastActive( now ) > CONNECTION_KEEP_ALIVE ){
+									
+						send_keep_alive	= true;
+					}
+				}
+			}
+		}
+		
+		if ( send_keep_alive ){
+			
+			sendKeepAlive();
+		}
+		
+		if ( failed != null ){
+			
+			for (int i=0;i<failed.size();i++){
+				
+				((buddyMessage)failed.get(i)).reportFailed( new BuddyPluginTimeoutException( "Timeout", false ));
+			}
+		}
+	}
+	
+	protected void
+	sendKeepAlive()
+	{
+		boolean send_keep_alive = true;
+		
+		synchronized( this ){
+			
+			if ( keep_alive_outstanding ){
+				
+				send_keep_alive = false;
+				
+			}else{
+			
+				keep_alive_outstanding = true;
+			}
+		}
+		
+		if ( send_keep_alive ){
+			
+			try{
+				Map	ping_request = new HashMap();
+				
+				ping_request.put( "type", new Long( BuddyPlugin.RT_INTERNAL_REQUEST_PING ));
+				
+				sendMessageSupport(
+					ping_request,
+					BuddyPlugin.SUBSYSTEM_INTERNAL,
+					60*1000,
+					new BuddyPluginBuddyReplyListener()
+					{
+						public void
+						replyReceived(
+							BuddyPluginBuddy	from_buddy,
+							Map					reply )
+						{
+							synchronized( BuddyPluginBuddy.this ){
+								
+								keep_alive_outstanding = false;
+							}
+						}
+						
+						public void
+						sendFailed(
+							BuddyPluginBuddy		to_buddy,
+							BuddyPluginException	cause )
+						{
+							synchronized( BuddyPluginBuddy.this ){
+								
+								keep_alive_outstanding = false;
+							}
+						}
+					});
+				
+			}catch( Throwable e ){
+				
+				synchronized( this ){
+					
+					keep_alive_outstanding = false;
+				}
+			}
+		}
+	}
+	
+	public String
+	getConnectionsString()
+	{
+		synchronized( this ){
+			
+			String	str = "";
+			
+			for (int i=0;i<connections.size();i++){
+				
+				str += (str.length()==0?"":",") + ((buddyConnection)connections.get(i)).getString( true );
+			}
+			
+			return( str );
+		}
+	}
+	
+	public void
+	disconnect()
+	{
+		List	to_disconnect = new ArrayList();
+		
+		synchronized( this ){
+			
+			to_disconnect.addAll( connections );
+		}
+		
+		for (int i=0;i<to_disconnect.size();i++){
+			
+			((buddyConnection)to_disconnect.get(i)).disconnect();
+		}
+	}
+	
+	protected boolean
+	isClosing()
+	{
+		return( closing );
+	}
+	
+	protected void
+	destroy()
+	{
+		List<buddyConnection>	to_close = new ArrayList<buddyConnection>();
+		
+		synchronized( this ){
+			
+			destroyed = true;
+			
+			to_close.addAll( connections );
+		}
+		
+		for (int i=0;i<to_close.size();i++){
+			
+			((buddyConnection)to_close.get(i)).close();
+		}
+	}
+	
+	protected void
+	logMessage(
+		String	str )
+	{
+		plugin.logMessage( getShortString() + ": " + str );
+	}
+	
+	protected GenericMessageConnection
+	outgoingConnection()
+	
+		throws BuddyPluginException
+	{
+		GenericMessageRegistration msg_registration = plugin.getMessageRegistration();
+
+		if ( msg_registration == null ){
+						
+			throw( new BuddyPluginException( "Messaging system unavailable" ));
+		}
+		
+		InetAddress ip = getIP();
+		
+		if ( ip == null ){
+						
+			throw( new BuddyPluginException( "Friend offline (no usable IP address)" ));
+		}
+		
+		InetSocketAddress	tcp_target	= null;
+		InetSocketAddress	udp_target	= null;
+		
+		int	tcp_port = getTCPPort();
+		
+		if ( tcp_port > 0 ){
+			
+			tcp_target = new InetSocketAddress( ip, tcp_port );
+		}
+		
+		int	udp_port = getUDPPort();
+		
+		if ( udp_port > 0 ){
+			
+			udp_target = new InetSocketAddress( ip, udp_port );
+		}
+
+		InetSocketAddress	notional_target = tcp_target;
+		
+		if ( notional_target == null ){
+		
+			notional_target = udp_target;
+		}
+		
+		if ( notional_target == null ){
+						
+			throw( new BuddyPluginException( "Friend offline (no usable protocols)" ));
+		}
+		
+		GenericMessageEndpoint	endpoint = msg_registration.createEndpoint( notional_target );
+		
+		if ( tcp_target != null ){
+		
+			endpoint.addTCP( tcp_target );
+		}
+		
+		if ( udp_target != null ){
+		
+			endpoint.addUDP( udp_target );
+		}
+				
+		GenericMessageConnection	con = null;
+		
+		try{
+			last_connect_attempt = SystemTime.getCurrentTime();
+			
+			con = msg_registration.createConnection( endpoint );
+				
+			plugin.addRateLimiters( con );
+			
+			String reason = "Friend: Outgoing connection establishment";
+	
+			SESecurityManager sec_man = plugin.getSecurityManager();
+			
+			con = sec_man.getSTSConnection( 
+					con, 
+					sec_man.getPublicKey( SEPublicKey.KEY_TYPE_ECC_192, reason ),
+	
+					new SEPublicKeyLocator()
+					{
+						public boolean
+						accept(
+							Object			context,
+							SEPublicKey		other_key )
+						{
+							String	other_key_str = Base32.encode( other_key.encodeRawPublicKey());
+
+							if ( other_key_str.equals( public_key )){
+								
+								consec_connect_fails	= 0;
+								
+								return( true );
+								
+							}else{
+								
+								log( getString() + ": connection failed due to pk mismatch" );
+							
+								return( false );
+							}
+						}
+					},
+					reason, 
+					BuddyPlugin.BLOCK_CRYPTO );		
+				
+			con.connect();
+			
+			return( con );
+			
+		}catch( Throwable e ){
+			
+			if ( con != null ){
+			
+				consec_connect_fails++;
+				
+				try{
+					con.close();
+					
+				}catch( Throwable f ){
+					
+					log( "Failed to close connection", f );
+				}
+			}
+			
+			throw( new BuddyPluginException( "Failed to send message", e ));
+		}
+	}
+	
+	protected void
+	incomingConnection(
+		GenericMessageConnection	_connection )
+	
+		throws BuddyPluginException
+	{
+		addConnection( _connection );
+	}
+	
+	protected void
+	addConnection(
+		GenericMessageConnection		_connection )
+	
+		throws BuddyPluginException
+	{
+		//int	size;
+		
+		buddyConnection bc = new buddyConnection( _connection, false );
+		
+		boolean inform_dirty = false;
+		
+		synchronized( this ){
+			
+			if ( destroyed ){
+				
+				throw( new BuddyPluginException( "Friend has been destroyed" ));
+			}
+			
+			inform_dirty = connections.size() == 0;
+			
+			connections.add( bc );
+			
+			//size = connections.size();
+		}
+		
+		// logMessage( "Con " + bc.getString() + " added: num=" + size );
+		
+		if ( inform_dirty ){
+			
+			plugin.setConfigDirty();
+		}
+	}
+	
+	public void
+	setUserData(
+		Object		key,
+		Object		value )
+	{
+		synchronized( user_data ){
+			
+			user_data.put(key, value);
+		}
+	}
+	
+	public Object
+	getUserData(
+		Object		key )
+	{
+		synchronized( user_data ){
+
+			return( user_data.get( key ));
+		}
+	}
+	
+	protected void
+	log(
+		String		str )
+	{
+		plugin.log( str );
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable 	e )
+	{
+		plugin.log( str, e );
+	}
+	
+	public String
+	getString()
+	{
+		return( "pk=" +  getShortString() + (nick_name==null?"":(",nick=" + nick_name)) + ",ip=" + ip + ",tcp=" + tcp_port + ",udp=" + udp_port + ",online=" + online + ",age=" + (SystemTime.getCurrentTime() - post_time ));
+	}
+
+	protected class
+	buddyMessage
+	{
+		private int									message_id;
+		
+		private Map									request;
+		private int									subsystem;
+		private BuddyPluginBuddyReplyListener		listener;
+		private int									timeout_millis;
+		
+		private long					queue_time	= SystemTime.getCurrentTime();
+		
+		private boolean		timed_out;
+		private int			retry_count;
+		private boolean		complete;
+		
+		protected
+		buddyMessage(
+			int									_subsystem,
+			Map									_request,
+			int									_timeout )
+		{
+			synchronized( BuddyPluginBuddy.this ){
+			
+				message_id = next_message_id++;
+			}
+			
+			request			= _request;
+			subsystem		= _subsystem;
+			timeout_millis	= _timeout;
+		}
+		
+		protected void
+		setListener(
+			BuddyPluginBuddyReplyListener		_listener )
+		{
+			listener		= _listener;
+		}
+		
+		protected int
+		getRetryCount()
+		{
+			synchronized( this ){
+
+				return( retry_count );
+			}
+		}
+		
+		protected void
+		setDontRetry()
+		{
+			retry_count = 99;
+		}
+		
+		protected void
+		setRetry()
+		{
+			synchronized( this ){
+				
+				retry_count++;
+				
+				complete 	= false;
+				timed_out 	= false;
+				
+			}
+		}
+		
+		protected boolean
+		timedOut(
+			long	now )
+		{
+			if ( timed_out ){
+				
+				return( true );
+			}
+			
+			if ( now < queue_time ){
+				
+				queue_time = now;
+				
+				return( false );
+				
+			}else{
+				
+				timed_out = now - queue_time >= timeout_millis;
+				
+				return( timed_out );
+			}
+		}
+		
+		protected Map
+		getRequest()
+		{
+			return( request );
+		}
+		
+		protected int
+		getSubsystem()
+		{
+			return( subsystem );
+		}
+		
+		protected int
+		getID()
+		{
+			return( message_id );
+		}
+		
+		protected void
+		reportComplete(
+			Map		reply )
+		{
+			synchronized( this ){
+				
+				if ( complete ){
+					
+					return;
+				}
+				
+				complete = true;
+			}
+			
+			try{
+				listener.replyReceived(  BuddyPluginBuddy.this, reply );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+		
+		protected void
+		reportFailed(
+			Throwable	error )
+		{
+			synchronized( this ){
+				
+				if ( complete ){
+					
+					return;
+				}
+				
+				complete = true;
+			}
+			
+			try{
+				if ( error instanceof BuddyPluginException ){
+					
+					listener.sendFailed( BuddyPluginBuddy.this, (BuddyPluginException)error );
+					
+				}else{
+				
+					listener.sendFailed(  BuddyPluginBuddy.this, new BuddyPluginException( "",  error ));
+				}
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+		
+		protected String
+		getString()
+		{
+			return( "id=" + message_id + ",ss=" + subsystem + (retry_count==0?"":(",retry="+retry_count)));
+		}
+	}
+	
+	protected class
+	buddyConnection
+		implements fragmentHandlerReceiver
+	{
+		private fragmentHandler					fragment_handler;
+		private int								connection_id;
+		private boolean							outgoing;
+		
+		private String							dir_str;
+		
+		
+		private volatile buddyMessage	active_message;
+		
+		private volatile boolean			connected;
+		private volatile boolean			closing;
+		private volatile boolean			remote_closing;
+		private volatile boolean			failed;
+		
+		private long			last_active	= SystemTime.getCurrentTime();
+		
+		protected
+		buddyConnection(
+			GenericMessageConnection		_connection,
+			boolean							_outgoing )
+		{
+			fragment_handler	= new fragmentHandler( _connection, this );
+			
+			outgoing	= _outgoing;
+			
+			synchronized( BuddyPluginBuddy.this ){
+				
+				connection_id = next_connection_id++;
+			}
+			
+			dir_str = outgoing?"Outgoing":"Incoming";
+			
+			if ( !outgoing ){
+				
+				connected = true;
+				
+				buddyConnectionEstablished( false );
+			}
+			
+			fragment_handler.start();
+		}
+		
+		protected boolean
+		isConnected()
+		{
+			return( connected );
+		}
+		
+		protected boolean
+		hasFailed()
+		{
+			return( failed );
+		}
+		
+		protected boolean
+		isOutgoing()
+		{
+			return( outgoing );
+		}
+		
+		protected long
+		getLastActive(
+			long		now )
+		{
+			if ( now < last_active ){
+				
+				last_active = now;
+			}
+			
+			return( last_active );
+		}
+		
+		protected void
+		sendMessage(
+			buddyMessage	message )
+		
+			throws BuddyPluginException
+		{			
+			BuddyPluginException	failed_error = null;
+
+			buddyMessage	msg_to_send			= null;
+
+			synchronized( this ){
+				
+				if ( BuddyPluginBuddy.this.isClosing()){
+					
+					throw( new BuddyPluginException( "Close in progress" ));
+				}
+				
+				if ( active_message != null ){
+					
+					Debug.out( "Inconsistent: active message already set" );
+					
+					failed_error = new BuddyPluginException( "Inconsistent state" );
+					
+				}else if ( failed || closing ){
+					
+					throw( new BuddyPluginException( "Connection failed" ));
+					
+				}else{
+										
+					active_message = message;
+					
+					if ( connected ){
+						
+						msg_to_send = active_message;
+					}
+				}
+			}
+			
+			if ( failed_error != null ){
+				
+				failed( failed_error );
+				
+				throw( failed_error );
+			}
+			
+			if ( msg_to_send != null ){
+			
+				send( msg_to_send );
+			}
+		}
+		
+		protected void
+		sendCloseMessage(
+			buddyMessage	message )	
+		{			
+			boolean	ok_to_send;
+			
+			synchronized( this ){
+				
+				ok_to_send = active_message == null && connected && !failed && !closing;
+			}
+			
+			if ( ok_to_send ){
+			
+				send( message );
+			}
+		}
+		
+		public boolean
+		isActive()
+		{
+			return( active_message != null );
+		}
+		
+		public void
+		connected()
+		{
+			if ( TRACE ){
+				System.out.println( dir_str + " connected" );
+			}
+			
+			buddyMessage	msg_to_send = null;
+			
+			synchronized( this ){
+				
+				last_active	= SystemTime.getCurrentTime();
+				
+				connected = true;
+				
+				msg_to_send = active_message;
+			}
+			
+			buddyConnectionEstablished( true );
+			
+			if ( msg_to_send != null  ){
+			
+				send( msg_to_send );
+			}
+		}
+		
+		protected boolean
+		checkTimeout(
+			long	now )
+		{
+			buddyMessage	bm = null;
+			
+			boolean	close = false;
+			
+			synchronized( this ){
+
+				if ( active_message != null ){
+					
+					if ( active_message.timedOut( now )){
+						
+						bm	= active_message;
+						
+						active_message	= null;
+					}
+				}
+								
+				if ( now < last_active ){
+					
+					last_active = now;
+				}
+				
+				if ( now - last_active > CONNECTION_IDLE_TIMEOUT ){
+										
+					close	= true;
+				}
+			}
+			
+			if ( bm != null ){
+				
+				bm.reportFailed( new BuddyPluginTimeoutException( "Timeout", true ));
+			}
+
+			if ( close ){
+				
+				close();
+			}
+			
+			return( close );
+		}
+		
+		protected void
+		send(
+			buddyMessage		msg )
+		{
+			Map request = msg.getRequest();
+			
+			Map	send_map = new HashMap();
+			
+			send_map.put( "type", new Long( RT_REQUEST_DATA ));
+			send_map.put( "req", request );
+			send_map.put( "ss", new Long( msg.getSubsystem()));
+			send_map.put( "id", new Long( msg.getID()));
+			send_map.put( "oz", new Long( plugin.getOnlineStatus()));
+			send_map.put( "v", new Long( BuddyPlugin.VERSION_CURRENT ));
+			
+			String	loc_cat = getLocalAuthorisedRSSTagsOrCategoriesAsString();
+			
+			if ( loc_cat != null ){
+				send_map.put( "cat", loc_cat );
+			}
+			
+			try{
+				// logMessage( "Sending " + msg.getString() + " to " + getString());
+
+				fragment_handler.send( send_map, true, true );
+							
+				synchronized( this ){
+					
+					last_active	= SystemTime.getCurrentTime();;
+				}
+			}catch( BuddyPluginException e ){
+			
+				try{			
+					failed( e );
+				
+				}catch( Throwable f ){
+				
+					Debug.printStackTrace(f);
+				}
+			}
+		}
+		
+		public void
+		receive(
+			Map			data_map )
+		{
+			synchronized( this ){
+				
+				last_active	= SystemTime.getCurrentTime();;
+			}
+			
+			if ( TRACE ){
+				System.out.println( dir_str + " receive: " + data_map );
+			}
+
+			try{
+				int	type = ((Long)data_map.get("type")).intValue();
+				
+				Long	l_os = (Long)data_map.get( "oz" );
+				
+				if ( l_os != null ){
+					
+					setOnlineStatus( l_os.intValue());
+				}
+				
+				Long	l_ver = (Long)data_map.get( "v" );
+				
+				if ( l_ver != null ){
+					
+					setVersion( l_ver.intValue());
+				}
+				
+				byte[]	b_rem_cat = (byte[])data_map.get( "cat" );
+				
+				if ( b_rem_cat == null ){
+					
+					setRemoteAuthorisedRSSTagsOrCategories( null );
+					
+				}else{
+					
+					setRemoteAuthorisedRSSTagsOrCategories( stringToCats( new String( b_rem_cat, "UTF-8" )));
+				}
+				
+				if ( type == RT_REQUEST_DATA ){
+					
+					// logMessage( "Received type=" + type + " from " + getString());
+				
+					Long	subsystem = (Long)data_map.get( "ss" );
+					
+					Map	reply;
+					
+					int	reply_type;
+					
+					Map request = (Map)data_map.get( "req" );
+
+					String	error = null;
+					
+					if ( request == null || subsystem == null ){
+						
+						reply	= null;
+						
+					}else{
+						
+						try{
+						
+							reply = plugin.requestReceived( BuddyPluginBuddy.this, subsystem.intValue(), request );
+							
+						}catch( Throwable e ){
+							
+							error = Debug.getNestedExceptionMessage(e);
+							
+							reply = null;
+						}
+					}
+					
+					if ( reply == null ){
+						
+						reply_type = RT_REPLY_ERROR;
+						
+						reply = new HashMap();
+						
+						reply.put( "error", error==null?"No handlers available to process request":error );
+						
+					}else{
+						
+						reply_type = RT_REPLY_DATA;
+					}
+					
+					Map reply_map = new HashMap();
+					
+					reply_map.put( "ss", subsystem );
+					reply_map.put( "type", new Long( reply_type ));																
+					reply_map.put( "id", data_map.get( "id" ) );
+					reply_map.put( "oz", new Long( plugin.getOnlineStatus()));
+
+					String	loc_cat = getLocalAuthorisedRSSTagsOrCategoriesAsString();
+					
+					if ( loc_cat != null ){
+						reply_map.put( "cat", loc_cat );
+					}
+					
+					reply_map.put( "rep", reply );
+					
+						// don't record as active here as (1) we recorded as active above when 
+						// receiving request (2) we may be replying to a 'closing' message and
+						// we don't want the reply to mark as online 
+
+					fragment_handler.send( reply_map, false, false );
+					
+				}else if ( type == RT_REPLY_DATA || type == RT_REPLY_ERROR ){
+					
+					long	id = ((Long)data_map.get( "id" )).longValue();
+					
+					buddyMessage	bm;
+					
+					synchronized( this ){
+						
+						if ( 	active_message != null &&
+								active_message.getID() == id ){
+								
+							bm = active_message;
+		
+							active_message = null;
+							
+						}else{
+								
+							bm = null;
+						}
+					}
+					
+					Map	reply = (Map)data_map.get( "rep" );
+					
+					if ( bm == null ){
+						
+						logMessage( "reply discarded as no matching request: " + reply );
+						
+					}else{
+						
+						if ( type == RT_REPLY_ERROR ){
+							
+							bm.setDontRetry();
+							
+							bm.reportFailed( new BuddyPluginException(new String((byte[])reply.get( "error" ))));
+							
+						}else{
+							
+							bm.reportComplete( reply );
+						}
+					}				
+				}else{
+					
+						// ignore unknown message types
+				}
+			}catch( Throwable e ){
+				
+				failed( e );	
+			}
+		}
+		
+		protected void
+		close()
+		{
+			closing = true;
+			
+			failed( new BuddyPluginException( "Closing" ));
+		}
+		
+		protected boolean
+		isClosing()
+		{
+			return( closing );
+		}
+		
+		protected void
+		remoteClosing()
+		{
+			remote_closing = true;
+		}
+		
+		protected boolean
+		isRemoteClosing()
+		{
+			return( remote_closing );
+		}
+		
+		protected void
+		disconnect()
+		{
+			fragment_handler.close();
+		}
+		
+		public void
+		failed(
+			Throwable 					error )
+		{
+			buddyMessage bm = null;
+			
+			if ( !connected && outgoing ){
+				
+				consec_connect_fails++;
+			}
+			
+			synchronized( this ){
+				
+				if ( failed ){
+					
+					return;
+				}
+				
+				failed = true;
+				
+				bm = active_message;
+				
+				active_message	 = null;
+			}
+			
+			logMessage( "Con " + getString() + " failed: " + Debug.getNestedExceptionMessage( error ));
+			
+			try{
+				if ( !closing ){
+					
+					if ( TRACE ){
+						System.out.println( dir_str + " connection error:" );
+					}
+				}
+				
+				fragment_handler.close();
+
+			}finally{
+								
+				removeConnection( this );
+				
+				if ( bm != null ){
+					
+					bm.reportFailed( error );
+				}
+			}
+		}
+		
+		protected String
+		getString()
+		{
+			return( getString( false ));
+		}
+		
+		protected String
+		getString(
+			boolean	short_form )
+		{
+			if ( short_form ){
+				
+				return( fragment_handler.getString());
+				
+			}else{
+				
+				return("id=" + connection_id + ",dir=" + ( outgoing?"out":"in" ));
+			}
+		}
+	}
+	
+	protected class
+	fragmentHandler
+		implements GenericMessageConnectionListener
+	{
+		private GenericMessageConnection	connection;
+		private fragmentHandlerReceiver		receiver;
+		
+		private int	next_fragment_id	= 0;
+		
+		private fragmentAssembly	current_request_frag;
+		private fragmentAssembly	current_reply_frag;
+		
+		private int					send_count;
+		private int					recv_count;
+		
+		protected
+		fragmentHandler(
+			GenericMessageConnection	_connection,
+			fragmentHandlerReceiver		_receiver )
+		{
+			connection	= _connection;
+			receiver	= _receiver;	
+		}
+	
+		public void
+		start()
+		{
+			connection.addListener( this );
+		}
+		
+		public void
+		connected(
+			GenericMessageConnection	connection )
+		{
+			receiver.connected();
+		}
+		
+		public void
+		failed(
+			GenericMessageConnection	connection,
+			Throwable 					error )
+		
+			throws MessageException
+		{
+			receiver.failed( error );
+		}
+		
+		protected void
+		send(
+			Map			data_map,
+			boolean		is_request,
+			boolean		record_active )
+			
+			throws BuddyPluginException
+		{
+			try{
+				byte[] data = BEncoder.encode( data_map );
+				
+				int	data_length = data.length;
+				
+				plugin.checkMaxMessageSize( data_length );
+				
+				int	max_chunk = connection.getMaximumMessageSize() - 1024;
+								
+				if ( data_length > max_chunk ){
+					
+					int	fragment_id;
+					
+					synchronized( this ){
+						
+						fragment_id = next_fragment_id++;
+					}
+					
+					int chunk_num = 0;
+					
+					for (int i=0;i<data_length;i+=max_chunk){
+						
+						int	end = Math.min( data_length, i + max_chunk );
+						
+						if ( end > i ){
+							
+							byte[]	chunk = new byte[ end-i ];
+							
+							System.arraycopy( data, i, chunk, 0, chunk.length );
+							
+							Map	chunk_map = new HashMap();
+							
+							chunk_map.put( "type", new Long( BuddyPlugin.RT_INTERNAL_FRAGMENT ));
+							chunk_map.put( "f", new Long( fragment_id ));
+							chunk_map.put( "l", new Long( data_length ));
+							chunk_map.put( "c", new Long( max_chunk ));
+							chunk_map.put( "i", new Long( chunk_num ));
+							chunk_map.put( "q", new Long( is_request?1:0 ));
+							chunk_map.put( "d", chunk );
+							
+							byte[] chunk_data = BEncoder.encode( chunk_map );
+
+							PooledByteBuffer chunk_buffer = 
+								plugin.getPluginInterface().getUtilities().allocatePooledByteBuffer( chunk_data );
+						
+							try{									
+								connection.send( chunk_buffer );
+							
+								chunk_buffer = null;
+								
+							}finally{
+								
+								if ( chunk_buffer != null ){
+									
+									chunk_buffer.returnToPool();
+								}
+							}
+						}
+						
+						chunk_num++;
+					}
+				}else{
+					
+					PooledByteBuffer buffer = 
+						plugin.getPluginInterface().getUtilities().allocatePooledByteBuffer( data );
+				
+					try{			
+					
+						connection.send( buffer );
+					
+						buffer = null;
+						
+					}finally{
+						
+						if ( buffer != null ){
+							
+							buffer.returnToPool();
+						}
+					}
+				}
+				
+				buddyMessageSent( data.length, record_active );
+				
+				send_count++;
+				
+			}catch( Throwable e ){
+				
+				throw( new BuddyPluginException( "Send failed", e ));
+			}
+		}
+		
+		public void
+		receive(
+			GenericMessageConnection	connection,
+			PooledByteBuffer			message )
+		
+			throws MessageException
+		{
+			try{
+					// while in unauth state we only allow a few messages. max should be 1
+					// for an 'accept request' but I feel generous
+				
+				if ( recv_count >= 4 && !isAuthorised()){
+				
+					throw( new MessageException( "Too many messages received while in unauthorised state" ));
+				}
+				
+				byte[]	content = message.toByteArray();
+				
+				Map	data_map = BDecoder.decode( content );
+				
+				if (((Long)data_map.get( "type" )).intValue() == BuddyPlugin.RT_INTERNAL_FRAGMENT ){
+					
+					Map	chunk_map = data_map;
+					
+					int	fragment_id = ((Long)chunk_map.get( "f" )).intValue();
+					int	data_length = ((Long)chunk_map.get( "l" )).intValue();
+					int	chunk_size 	= ((Long)chunk_map.get( "c" )).intValue();
+					int	chunk_num 	= ((Long)chunk_map.get( "i" )).intValue();
+					
+					boolean	is_request = ((Long)chunk_map.get("q")).intValue() == 1;
+					
+					byte[]	chunk_data = (byte[])chunk_map.get("d" );
+					
+					plugin.checkMaxMessageSize( data_length );
+					
+					fragmentAssembly assembly;
+					
+					if ( is_request ){
+						
+						if ( current_request_frag == null ){
+							
+							current_request_frag = new fragmentAssembly( fragment_id, data_length, chunk_size );
+						}
+						
+						assembly = current_request_frag;
+						
+					}else{
+						
+						if ( current_reply_frag == null ){
+							
+							current_reply_frag = new fragmentAssembly( fragment_id, data_length, chunk_size );
+						}
+						
+						assembly = current_reply_frag;
+					}
+					
+					if ( assembly.getID() != fragment_id ){
+							
+						throw( new BuddyPluginException( "Fragment receive error: concurrent decode not supported" ));
+					}
+					
+					if ( assembly.receive( chunk_num, chunk_data )){
+										
+						if ( is_request ){
+
+							current_request_frag = null;
+							
+						}else{
+							
+							current_reply_frag = null;
+						}
+						
+						buddyMessageReceived( data_length );
+
+						recv_count++;
+						
+						receiver.receive( BDecoder.decode( assembly.getData()));
+						
+					}else{
+						
+						buddyMessageFragmentReceived( assembly.getChunksReceived(), assembly.getTotalChunks());
+					}
+				}else{
+				
+					buddyMessageReceived( content.length );
+
+					recv_count++;
+					
+					receiver.receive( data_map );					
+				}
+			}catch( Throwable e ){
+				
+				receiver.failed( e );
+				
+			}finally{
+				
+				message.returnToPool();
+			}
+		}
+		
+		protected void
+		close()
+		{
+			try{
+			
+				connection.close();
+				
+			}catch( Throwable e ){
+				
+				// Debug.printStackTrace( e );
+				
+			}finally{
+				
+				receiver.failed( new Exception( "Connection closed" ));
+			}
+		}
+		
+		protected String
+		getString()
+		{
+			return( connection.getType());
+		}
+		
+		protected class
+		fragmentAssembly
+		{
+			private int		id;
+			private byte[]	data;
+			private int		chunk_size;
+			
+			private int		num_chunks;
+			private Set		chunks_received = new HashSet();
+			
+			protected
+			fragmentAssembly(
+				int		_id,
+				int		_length,
+				int		_chunk_size )
+			{
+				id			= _id;
+				chunk_size	= _chunk_size;
+				
+				data		= new byte[_length];
+				
+				num_chunks = (_length + chunk_size - 1 )/chunk_size;
+			}
+			
+			protected int
+			getID()
+			{
+				return( id );
+			}
+			
+			protected int
+			getChunksReceived()
+			{
+				return( chunks_received.size());
+			}
+			
+			protected int
+			getTotalChunks()
+			{
+				return( num_chunks );
+			}
+			
+			protected boolean
+			receive(
+				int		chunk_num,
+				byte[]	chunk )
+			{
+				// System.out.println( "received chunk " + chunk_num + " of " + num_chunks );
+				
+				Integer	i = new Integer( chunk_num );
+				
+				if ( chunks_received.contains( i )){
+					
+					return( false );
+				}
+				
+				chunks_received.add( i );
+				
+				System.arraycopy( chunk, 0, data, chunk_num*chunk_size, chunk.length );
+				
+				return( chunks_received.size() == num_chunks );
+			}
+			
+			protected byte[]
+			getData()
+			{
+				return( data );
+			}
+		}
+	}	
+	
+	interface
+	fragmentHandlerReceiver
+	{
+		public void
+		connected();
+		
+		public void
+		receive(
+			Map			data );
+		
+		public void
+		failed(
+			Throwable	error );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessage.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessage.java
index 69b807a..ddedda1 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessage.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessage.java
@@ -1,124 +1,123 @@
-/*
- * Created on Apr 23, 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.plugins.net.buddy;
-
-import java.util.Map;
-
-public class 
-BuddyPluginBuddyMessage 
-{
-	private BuddyPluginBuddyMessageHandler		handler;
-	private int									id;
-	private int									subsystem;
-	private int									timeout;
-	private long								create_time;
-	private boolean								deleted;
-	
-	protected
-	BuddyPluginBuddyMessage(
-		BuddyPluginBuddyMessageHandler		_handler,
-		int									_id,
-		int									_subsystem,
-		Map									_request,
-		int									_timeout,
-		long								_create_time )
-	
-		throws BuddyPluginException
-	{
-		handler		= _handler;
-		id			= _id;
-		subsystem	= _subsystem;
-		timeout		= _timeout;
-		create_time	= _create_time;
-		
-		if ( _request != null ){
-			
-			handler.writeRequest( this, _request );
-		}
-	}
-	
-	public BuddyPluginBuddy
-	getBuddy()
-	{
-		return( handler.getBuddy());
-	}
-	
-	public int
-	getID()
-	{
-		return( id );
-	}
-	
-	public int
-	getSubsystem()
-	{
-		return( subsystem );
-	}
-	
-	public Map
-	getRequest()
-	
-		throws BuddyPluginException
-	{
-		return( handler.readRequest( this ));
-	}
-	
-		/**
-		 * Only available for pending-success messages, so don't make public 
-		 * @return
-		 * @throws BuddyPluginException
-		 */
-	
-	protected Map
-	getReply()
-	
-		throws BuddyPluginException
-	{
-		return( handler.readReply( this ));
-	}
-	
-	protected int
-	getTimeout()
-	{
-		return( timeout );
-	}
-	
-	protected long
-	getCreateTime()
-	{
-		return( create_time );
-	}
-	
-	public void
-	delete()
-	{
-		deleted = true;
-		
-		handler.deleteMessage( this );
-	}
-	
-	public boolean
-	isDeleted()
-	{
-		return( deleted );
-	}
-}
+/*
+ * Created on Apr 23, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+import java.util.Map;
+
+public class 
+BuddyPluginBuddyMessage 
+{
+	private BuddyPluginBuddyMessageHandler		handler;
+	private int									id;
+	private int									subsystem;
+	private int									timeout;
+	private long								create_time;
+	private boolean								deleted;
+	
+	protected
+	BuddyPluginBuddyMessage(
+		BuddyPluginBuddyMessageHandler		_handler,
+		int									_id,
+		int									_subsystem,
+		Map									_request,
+		int									_timeout,
+		long								_create_time )
+	
+		throws BuddyPluginException
+	{
+		handler		= _handler;
+		id			= _id;
+		subsystem	= _subsystem;
+		timeout		= _timeout;
+		create_time	= _create_time;
+		
+		if ( _request != null ){
+			
+			handler.writeRequest( this, _request );
+		}
+	}
+	
+	public BuddyPluginBuddy
+	getBuddy()
+	{
+		return( handler.getBuddy());
+	}
+	
+	public int
+	getID()
+	{
+		return( id );
+	}
+	
+	public int
+	getSubsystem()
+	{
+		return( subsystem );
+	}
+	
+	public Map
+	getRequest()
+	
+		throws BuddyPluginException
+	{
+		return( handler.readRequest( this ));
+	}
+	
+		/**
+		 * Only available for pending-success messages, so don't make public 
+		 * @return
+		 * @throws BuddyPluginException
+		 */
+	
+	protected Map
+	getReply()
+	
+		throws BuddyPluginException
+	{
+		return( handler.readReply( this ));
+	}
+	
+	protected int
+	getTimeout()
+	{
+		return( timeout );
+	}
+	
+	protected long
+	getCreateTime()
+	{
+		return( create_time );
+	}
+	
+	public void
+	delete()
+	{
+		deleted = true;
+		
+		handler.deleteMessage( this );
+	}
+	
+	public boolean
+	isDeleted()
+	{
+		return( deleted );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessageHandler.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessageHandler.java
index aa098dd..5bfd9e0 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessageHandler.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessageHandler.java
@@ -1,1063 +1,1062 @@
-/*
- * Created on Apr 23, 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.plugins.net.buddy;
-
-import java.io.File;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.BDecoder;
-import org.gudy.azureus2.core3.util.BEncoder;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-public class 
-BuddyPluginBuddyMessageHandler 
-{
-	private BuddyPluginBuddy		buddy;
-	private File					store;
-	
-	private Map	config_map;
-	private int	message_count;
-	private int pending_deletes;
-	
-	private int	next_message_id;
-	
-	private CopyOnWriteList			listeners = new CopyOnWriteList();
-	
-	private BuddyPluginBuddyMessage	active_message;
-	
-	private long					last_failure;
-	private long					last_pending_success;
-	
-	
-	protected
-	BuddyPluginBuddyMessageHandler(
-		BuddyPluginBuddy		_buddy,
-		File					_store )
-	{
-		buddy	= _buddy;
-		store	= _store;
-		
-		loadConfig();
-		
-		if ( message_count > 0 ){
-			
-			buddy.persistentDispatchPending();
-		}
-	}
-	
-	public BuddyPluginBuddy
-	getBuddy()
-	{
-		return( buddy );
-	}
-	
-	public BuddyPluginBuddyMessage
-	queueMessage(
-		int		subsystem,
-		Map		content,
-		int		timeout_millis )
-	
-		throws BuddyPluginException
-	{
-		BuddyPluginBuddyMessage	message;
-		
-		boolean	dispatch_pending;
-		
-		synchronized( this ){
-			
-			int	id = next_message_id++;
-			
-			message = 
-				new BuddyPluginBuddyMessage( 
-						this, id, subsystem, content, timeout_millis, SystemTime.getCurrentTime());
-		
-			storeMessage( message );
-			
-			dispatch_pending = message_count == 1;
-		}
-		
-		Iterator it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((BuddyPluginBuddyMessageListener)it.next()).messageQueued( message );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-		
-		if ( dispatch_pending ){
-			
-			buddy.persistentDispatchPending();
-		}
-		
-		return( message );
-	}	
-	
-	protected void
-	checkPersistentDispatch()
-	{
-		boolean	request_dispatch = false;
-		
-		synchronized( this ){
-
-			long	now = SystemTime.getCurrentTime();
-
-			if ( now < last_failure ){
-				
-				last_failure = now;
-			}
-
-			if ( now < last_pending_success ){
-				
-				last_pending_success = now;
-			}
-
-			if ( last_pending_success > 0 && now - last_pending_success >= BuddyPlugin.PERSISTENT_MSG_RETRY_PERIOD ){
-				
-				request_dispatch = true;
-				
-			}else if ( active_message != null || message_count == 0 || last_failure == 0 ){
-				
-					// no messages pending
-				
-			}else{
-				
-				request_dispatch = now - last_failure >= BuddyPlugin.PERSISTENT_MSG_RETRY_PERIOD;
-			}
-		}
-		
-		if ( request_dispatch ){
-			
-			buddy.persistentDispatchPending();
-		}
-	}
-	
-	protected void
-	persistentDispatch()
-	{
-		checkPendingSuccess();
-		
-		synchronized( this ){
-
-			if ( active_message != null || message_count == 0 ){
-				
-				return;
-			}
-			
-			List	messages = (List)config_map.get( "messages" );
-
-			Map		map = (Map)messages.get(0);
-			
-			try{
-				active_message = restoreMessage( map );
-				
-			}catch( Throwable e ){
-				
-					// should never happen...
-				
-				Debug.out( "Failed to restore message, deleting it", e );
-				
-				messages.remove(0);
-								
-				try{
-					saveConfig();
-					
-				}catch( Throwable f ){
-					
-					buddy.log( "Config save failed during delete of bad message", f );
-				}
-			}
-		}
-		
-		boolean	request_ok = false;
-		
-		try{
-			Map	request = active_message.getRequest();
-		
-			request_ok = true;
-			
-			buddy.sendMessage(
-					active_message.getSubsystem(),
-					request,
-					active_message.getTimeout(),
-					new BuddyPluginBuddyReplyListener()
-					{
-						public void
-						replyReceived(
-							BuddyPluginBuddy		from_buddy,
-							Map						reply )
-						{
-							BuddyPluginBuddyMessage message = active_message;
-							
-								// inform listeners before deleting message as it gives them one
-								// last chance to do something with the message if they so desire
-							
-							Iterator it = listeners.iterator();
-							
-							boolean	processing_ok = true;
-							
-								// prematurely reduce message count when informing listeners
-								// so they see the "correct" value
-							
-							try{
-								synchronized( BuddyPluginBuddyMessageHandler.this ){
-									
-									pending_deletes++;
-								}
-								
-								while( it.hasNext()){
-									
-									try{
-										if ( !((BuddyPluginBuddyMessageListener)it.next()).deliverySucceeded( message, reply )){
-											
-											processing_ok = false;
-										}
-										
-									}catch( Throwable e ){
-										
-										Debug.printStackTrace(e);
-									}
-								}
-							}finally{
-								
-								synchronized( BuddyPluginBuddyMessageHandler.this ){
-									
-									pending_deletes--;
-								}
-							}
-							if ( processing_ok ){
-							
-								message.delete();
-								
-							}else{
-								synchronized( BuddyPluginBuddyMessageHandler.this ){
-									
-									boolean found = false;
-									
-									List	messages = (List)config_map.get( "messages" );
-
-									if ( messages != null ){
-										
-										for ( int i=0;i<messages.size();i++){
-											
-											Map	msg = (Map)messages.get(i);
-											
-											if ( message.getID() == ((Long)msg.get( "id")).intValue()){
-												
-												found = true;
-												
-												messages.remove(i);
-												
-												try{
-													writeReply( message, reply );
-
-													List pending_success = (List)config_map.get( "pending_success" );
-													
-													if ( pending_success == null ){
-														
-														pending_success = new ArrayList();
-														
-														config_map.put( "pending_success", pending_success );
-													}
-													
-													pending_success.add( msg );
-													
-													last_pending_success = SystemTime.getCurrentTime();
-													
-													buddy.log( "Message moved to pending success queue after listener failed" );
-													
-													saveConfig();
-													
-												}catch( Throwable e ){
-													
-													buddy.log( "Config save failed during message pending queueing", e );
-												}
-												
-												break;
-											}
-										}	
-									}
-									
-									if ( !found ){
-																				
-										buddy.log( "Failed to find message " + message.getID());
-									}
-								}
-							}
-							
-							boolean messages_queued;
-							
-							synchronized( BuddyPluginBuddyMessageHandler.this ){
-
-								active_message 	= null;
-								
-								messages_queued = message_count > 0;
-								
-								last_failure	= 0;
-							}
-															
-							if ( messages_queued ){
-							
-								buddy.persistentDispatchPending();
-							}
-						}
-						
-						public void
-						sendFailed(
-							BuddyPluginBuddy		to_buddy,
-							BuddyPluginException	cause )
-						{
-							BuddyPluginBuddyMessage message = active_message;
-							
-							synchronized( BuddyPluginBuddyMessageHandler.this ){
-
-								active_message 	= null;
-								
-								last_failure	= SystemTime.getCurrentTime();
-							}
-							
-							reportFailed( message, cause, true );
-						}
-					});
-					
-		}catch( Throwable cause ){
-			
-			BuddyPluginBuddyMessage message = active_message;
-
-			synchronized( this ){
-
-				active_message 	= null;
-				
-				last_failure	= SystemTime.getCurrentTime();
-			}
-			
-			boolean do_subsequent = true;
-			
-			if ( !request_ok && !( cause instanceof BuddyPluginPasswordException )){
-				
-				buddy.logMessage( "Message request unavailable, deleting message" );
-				
-				message.delete();
-				
-				boolean messages_queued = false;
-				
-				synchronized( this ){
-
-					last_failure = 0;
-					
-					messages_queued = message_count > 0;
-				}
-					
-				if ( messages_queued ){
-				
-					do_subsequent = false;
-					
-					buddy.persistentDispatchPending();
-				}
-			}
-			
-			reportFailed( message, cause, do_subsequent );
-		}
-	}
-	
-	protected void
-	reportFailed(
-		BuddyPluginBuddyMessage		message,
-		Throwable					cause,
-		boolean						do_subsequent )
-	{	
-		BuddyPluginException b_cause;
-		
-		if ( cause instanceof BuddyPluginException ){
-			
-			b_cause = (BuddyPluginException)cause;
-			
-		}else{
-			
-			b_cause = new BuddyPluginException( "Failed to send message", cause );
-		}
-		
-		reportFailedSupport( message, b_cause );
-		
-		if ( do_subsequent ){
-			
-			List	other_messages = new ArrayList();
-			
-			synchronized( this ){
-	
-				List	messages = (List)config_map.get( "messages" );
-	
-				for (int i=0;i<messages.size();i++){
-				
-					try{
-						BuddyPluginBuddyMessage msg = restoreMessage((Map)messages.get(i));
-	
-						if ( msg.getID() != message.getID()){
-							
-							other_messages.add( msg );
-						}
-					}catch( Throwable e ){
-						
-					}
-				}
-			}
-	
-			if ( other_messages.size() > 0 ){
-				
-				BuddyPluginException o_cause = new BuddyPluginException( "Reporting probable failure to subsequent messages" );
-				
-				for (int i=0;i<other_messages.size();i++){
-					
-					reportFailedSupport((BuddyPluginBuddyMessage)other_messages.get(i), o_cause );
-				}
-			}
-		}
-	}
-	
-	protected void
-	reportFailedSupport(
-		BuddyPluginBuddyMessage		message,
-		BuddyPluginException		cause )
-	{	
-		Iterator it = listeners.iterator();
-	
-		while( it.hasNext()){
-			
-			try{
-				((BuddyPluginBuddyMessageListener)it.next()).deliveryFailed( message, cause );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-	}
-	
-	protected void
-	checkPendingSuccess()
-	{
-		List	pending_messages = new ArrayList();
-		
-		boolean	save_pending = false;
-		
-		synchronized( this ){
-			
-			last_pending_success	= 0;
-
-			List pending_success = (List)config_map.get( "pending_success" );
-
-			if ( pending_success == null || pending_success.size() == 0 ){
-				
-				return;
-			}
-			
-			Iterator it = pending_success.iterator();
-			
-			while( it.hasNext()){
-				
-				Map	map = (Map)it.next();
-			
-				try{
-					pending_messages.add( restoreMessage( map ));
-					
-				}catch( Throwable e ){
-					
-					buddy.log( "Failed to restore message from pending success queue", e );
-					
-					it.remove();
-					
-					save_pending = true;
-				}
-			}
-		}
-		
-		for ( int i=0;i<pending_messages.size();i++){
-	
-			BuddyPluginBuddyMessage message = (BuddyPluginBuddyMessage)pending_messages.get(i);
-			
-			try{
-				Map	reply = message.getReply();
-				
-				Iterator it = listeners.iterator();
-				
-				boolean	processing_ok = true;
-				
-				while( it.hasNext()){
-					
-					try{
-						if ( !((BuddyPluginBuddyMessageListener)it.next()).deliverySucceeded( message, reply )){
-							
-							processing_ok = false;
-						}
-						
-					}catch( Throwable e ){
-						
-						Debug.printStackTrace(e);
-					}
-				}
-	
-				if ( processing_ok ){
-				
-					message.delete();
-					
-				}else{
-					synchronized( this ){
-	
-						last_pending_success = SystemTime.getCurrentTime();
-					}
-				}
-			}catch( BuddyPluginPasswordException e ){
-				
-				buddy.log( "Failed to restore message reply", e );
-
-					// we don't want to delete the message if failed due to password issue
-				
-			}catch( Throwable e ){
-				
-				buddy.log( "Failed to restore message reply - deleting message", e );
-
-				message.delete();
-			}
-		}
-		
-		if ( save_pending ){
-			
-			try{
-				saveConfig();
-				
-			}catch( Throwable e ){
-				
-				buddy.log( "Save failed during pending success processing", e );
-			}
-		}
-	}
-	
-	public int
-	getMessageCount()
-	{
-		synchronized( this ){
-		
-			return( message_count - pending_deletes );
-		}
-	}
-	
-	protected void
-	deleteMessage(
-		BuddyPluginBuddyMessage		message )
-	{
-		Iterator it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((BuddyPluginBuddyMessageListener)it.next()).messageDeleted( message );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-		
-		synchronized( this ){
-			
-			String[]	keys = { "messages", "pending_success", "explicit" };
-			
-			for (int i=0;i<keys.length;i++){
-				
-				List	messages = (List)config_map.get( keys[i] );
-	
-				if ( messages != null ){
-	
-					boolean	found = false;
-					
-					for ( int j=0;j<messages.size();j++){
-						
-						Map	msg = (Map)messages.get(j);
-						
-						if ( message.getID() == ((Long)msg.get( "id")).intValue()){
-							
-							messages.remove(j);
-							
-							found	= true;
-							
-							break;
-						}
-					}
-				
-					if ( found ){
-					
-						deleteRequest( message );
-						
-						deleteReply( message );
-						
-						try{
-							saveConfig();
-							
-						}catch( Throwable e ){
-							
-							buddy.log( "Config save failed during message delete", e );
-						}
-						
-						return;
-					}
-				}
-			}
-		}
-	}
-	
-	protected void
-	destroy()
-	{
-		synchronized( this ){
-			
-			config_map.clear();
-			
-			try{
-				saveConfig();
-				
-			}catch( Throwable e ){
-				
-				buddy.log( "Config save failed during destroy", e );
-			}
-		}
-	}
-	
-	protected void
-	writeRequest(
-		BuddyPluginBuddyMessage		message,
-		Map							content )
-	
-		throws BuddyPluginException
-	{
-		writeContent( message.getID() + ".req.dat", content );
-	}
-	
-	protected Map
-	readRequest(
-		BuddyPluginBuddyMessage		message )
-	
-		throws BuddyPluginException
-	{		
-		return( readContent( message.getID() + ".req.dat" ));
-	}
-	
-	protected void
-	writeReply(
-		BuddyPluginBuddyMessage		message,
-		Map							content )
-	
-		throws BuddyPluginException
-	{
-		writeContent( message.getID() + ".rep.dat", content );
-	}
-	
-	protected Map
-	readReply(
-		BuddyPluginBuddyMessage		message )
-	
-		throws BuddyPluginException
-	{		
-		return( readContent( message.getID() + ".rep.dat" ));
-	}
-	
-	protected void
-	writeContent(
-		String						target_str,
-		Map							content )
-	
-		throws BuddyPluginException
-	{
-		if ( !store.exists()){
-			
-			if ( !store.mkdirs()){
-				
-				throw( new BuddyPluginException( "Failed to create " + store ));
-			}
-		}
-		
-		File target = new File( store, target_str );
-		
-		try{
-		
-			BuddyPlugin.cryptoResult result = buddy.encrypt( BEncoder.encode( content ));
-			
-			Map	store_map = new HashMap();
-			
-			store_map.put( "pk", buddy.getPlugin().getPublicKey());
-			store_map.put( "data", result.getPayload());
-			
-			if ( !buddy.writeConfigFile( target, store_map )){
-				
-				throw( new BuddyPluginException( "failed to write " + target ));
-			}
-			
-		}catch( BuddyPluginException e ){
-			
-			throw( e );
-			
-		}catch( Throwable e ){
-			
-			throw( new BuddyPluginException( "Failed to write message", e ));
-		}
-	}
-	
-	protected Map
-	readContent(
-		String						target_str )
-	
-		throws BuddyPluginException
-	{		
-		File target = new File( store, target_str );
-
-		if ( !target.exists()){
-
-			throw( new BuddyPluginException( "Failed to read persisted message - " + target + " doesn't exist" ));
-		}
-
-		Map	map = buddy.readConfigFile( target );
-		
-		if ( map.size() == 0 ){
-			
-			throw( new BuddyPluginException( "Failed to read persisted message file " + target ));
-		}
-		
-		try{
-			String	pk = new String((byte[])map.get("pk"));
-			
-			if ( !pk.equals( buddy.getPlugin().getPublicKey())){
-				
-				throw( new BuddyPluginException( "Can't decrypt message as key changed" ));
-			}
-			
-			byte[]	data = (byte[])map.get( "data" );
-			
-			return( BDecoder.decode( buddy.decrypt( data ).getPayload()));
-			
-		}catch( BuddyPluginException e ){
-			
-			throw( e );
-			
-		}catch( Throwable e ){
-			
-			throw( new BuddyPluginException( "Failed to read message", e ));
-		}
-	}
-	
-	protected void
-	deleteRequest(
-		BuddyPluginBuddyMessage		message )
-	{
-		deleteRequest( message.getID());
-	}
-	
-	protected void
-	deleteRequest(
-		int			id  )
-	{	
-		File target = new File( store, id + ".req.dat" );
-		
-		if ( target.exists()){
-			
-			if ( !target.delete()){
-				
-				Debug.out( "Failed to delete " + target );
-			}
-		}
-	}
-	
-	protected void
-	deleteReply(
-		BuddyPluginBuddyMessage		message )
-	{
-		deleteReply( message.getID());
-	}
-	
-	protected void
-	deleteReply(
-		int			id  )
-	{	
-		File target = new File( store, id + ".rep.dat" );
-		
-		if ( target.exists()){
-			
-			if ( !target.delete()){
-				
-				Debug.out( "Failed to delete " + target );
-			}
-		}
-	}
-	
-	public BuddyPluginBuddyMessage
-	storeExplicitMessage(
-		int		type,
-		Map		msg )
-	{
-		BuddyPluginBuddyMessage	message;
-				
-		synchronized( this ){
-			
-			int	id = next_message_id++;
-			
-			try{
-				message = 
-					new BuddyPluginBuddyMessage( 
-							this, id, BuddyPlugin.SUBSYSTEM_MSG_TYPE_BASE + type, msg, 0, SystemTime.getCurrentTime());
-			
-				storeExplicitMessage( message );
-				
-			}catch( Throwable e ){
-				
-				buddy.log( "Failed to store explicit message", e );
-				
-				return( null );
-			}
-		}
-		
-		return( message );
-	}
-	
-	public List<BuddyPluginBuddyMessage>
-	retrieveExplicitMessages(
-		int		type )
-	{
-		List<BuddyPluginBuddyMessage>	result = new ArrayList<BuddyPluginBuddyMessage>();
-		
-		synchronized( this ){
-
-			List<Map<String,Object>>	messages = (List<Map<String,Object>>)config_map.get( "explicit" );
-			
-			if ( messages != null ){
-				
-				for (int i=0;i<messages.size();i++){
-					
-					try{
-						BuddyPluginBuddyMessage msg = restoreMessage(messages.get(i));
-						
-						if ( msg.getSubsystem() == BuddyPlugin.SUBSYSTEM_MSG_TYPE_BASE + type ){
-							
-							result.add( msg );
-						}
-					}catch( Throwable e ){
-						
-						buddy.log( "Failed to restore message", e );
-					}
-				}
-			}
-		}
-		
-		return( result );
-	}
-	
-	protected void
-	storeExplicitMessage(
-		BuddyPluginBuddyMessage		msg )
-	
-		throws BuddyPluginException
-	{
-		storeMessageSupport( msg, "explicit" );
-	}
-	
-	protected void
-	storeMessage(
-		BuddyPluginBuddyMessage		msg )
-	
-		throws BuddyPluginException
-	{
-		storeMessageSupport( msg, "messages" );
-	}
-	
-	protected void
-	storeMessageSupport(
-		BuddyPluginBuddyMessage		msg,
-		String						key )
-	
-		throws BuddyPluginException
-	{
-		List	messages = (List)config_map.get( key );
-
-		if ( messages == null ){
-			
-			messages = new ArrayList();
-			
-			config_map.put( key, messages );
-		}
-		
-		Map map = new HashMap();
-		
-		map.put( "id", new Long( msg.getID()));
-		map.put( "ss", new Long( msg.getSubsystem()));
-		map.put( "to", new Long( msg.getTimeout()));
-		map.put( "cr", new Long( msg.getCreateTime()));
-		
-		messages.add( map );
-				
-		saveConfig();
-	}
-	
-	protected BuddyPluginBuddyMessage
-	restoreMessage(
-		Map			map )
-	
-		throws BuddyPluginException
-	{
-		int	id = ((Long)map.get( "id" )).intValue();
-		int	ss = ((Long)map.get( "ss" )).intValue();
-		int	to = ((Long)map.get( "to" )).intValue();
-		
-		long	cr = ((Long)map.get( "cr" )).longValue();
-		
-		return( new BuddyPluginBuddyMessage( this, id, ss, null, to, cr ));
-	}
-	
-	protected void
-	loadConfig()
-	{
-		File	config_file = new File( store, "messages.dat" );
-		
-		if ( config_file.exists()){
-			
-			config_map = buddy.readConfigFile( config_file );
-			
-		}else{
-			
-			config_map = new HashMap();
-		}
-		
-		List	messages = (List)config_map.get( "messages" );
-		
-		if ( messages != null ){
-			
-			message_count = messages.size();
-			
-			if ( message_count > 0 ){
-				
-				Map	last_msg = (Map)messages.get( message_count - 1 );
-				
-				next_message_id = ((Long)last_msg.get( "id")).intValue() + 1;
-			}
-		}
-		
-		List	pending_success = (List)config_map.get( "pending_success" );
-		
-		if ( pending_success != null ){
-			
-			int ps_count = pending_success.size();
-		
-			if ( ps_count > 0 ){
-										
-				Map	last_msg = (Map)pending_success.get( ps_count - 1 );
-					
-				next_message_id = Math.max( next_message_id, ((Long)last_msg.get( "id")).intValue() + 1 );
-				
-				synchronized( this ){
-				
-					last_pending_success = SystemTime.getCurrentTime();
-				}
-			}
-		}
-		
-		List	explicit = (List)config_map.get( "explicit" );
-		
-		if ( explicit != null ){
-			
-			int exp_count = explicit.size();
-		
-			if ( exp_count > 0 ){
-										
-				Map	last_msg = (Map)explicit.get( exp_count - 1 );
-					
-				next_message_id = Math.max( next_message_id, ((Long)last_msg.get( "id")).intValue() + 1 );
-			}
-		}
-	}
-	
-	protected void
-	saveConfig()
-	
-		throws BuddyPluginException
-	{
-		File	config_file = new File( store, "messages.dat" );
-		
-		List	messages 	= (List)config_map.get( "messages" );
-		List	pending 	= (List)config_map.get( "pending_success" );
-		List	explicit 	= (List)config_map.get( "explicit" );
-
-		if ( 	( messages == null || messages.size() == 0 ) && 
-				( pending == null || pending.size() == 0 ) && 
-				( explicit == null || explicit.size() == 0 )){
-			
-			if ( store.exists()){
-			
-				File[]	 files = store.listFiles();
-			
-				for (int i=0;i<files.length;i++ ){
-					
-					files[i].delete();
-				}
-				
-				store.delete();
-			}
-			
-			message_count = 0;
-			
-			next_message_id	= 0;
-			
-		}else{
-			
-			if ( !store.exists()){
-				
-				if ( !store.mkdirs()){
-					
-					throw( new BuddyPluginException( "Failed to create " + store ));
-				}
-			}
-			
-			if ( !buddy.writeConfigFile( config_file, config_map )){
-				
-				throw( new BuddyPluginException( "Failed to write" + config_file ));
-			}
-			
-			message_count = messages==null?0:messages.size();
-		}
-	}
-	
-	public void
-	addListener(
-		BuddyPluginBuddyMessageListener		listener )
-	{
-		listeners.add( listener );
-	}
-	
-	public void
-	removeListener(
-		BuddyPluginBuddyMessageListener		listener )
-	{
-		listeners.remove( listener );
-	}
-}
+/*
+ * Created on Apr 23, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+import java.io.File;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.BDecoder;
+import org.gudy.azureus2.core3.util.BEncoder;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.SystemTime;
+
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
+public class 
+BuddyPluginBuddyMessageHandler 
+{
+	private BuddyPluginBuddy		buddy;
+	private File					store;
+	
+	private Map	config_map;
+	private int	message_count;
+	private int pending_deletes;
+	
+	private int	next_message_id;
+	
+	private CopyOnWriteList			listeners = new CopyOnWriteList();
+	
+	private BuddyPluginBuddyMessage	active_message;
+	
+	private long					last_failure;
+	private long					last_pending_success;
+	
+	
+	protected
+	BuddyPluginBuddyMessageHandler(
+		BuddyPluginBuddy		_buddy,
+		File					_store )
+	{
+		buddy	= _buddy;
+		store	= _store;
+		
+		loadConfig();
+		
+		if ( message_count > 0 ){
+			
+			buddy.persistentDispatchPending();
+		}
+	}
+	
+	public BuddyPluginBuddy
+	getBuddy()
+	{
+		return( buddy );
+	}
+	
+	public BuddyPluginBuddyMessage
+	queueMessage(
+		int		subsystem,
+		Map		content,
+		int		timeout_millis )
+	
+		throws BuddyPluginException
+	{
+		BuddyPluginBuddyMessage	message;
+		
+		boolean	dispatch_pending;
+		
+		synchronized( this ){
+			
+			int	id = next_message_id++;
+			
+			message = 
+				new BuddyPluginBuddyMessage( 
+						this, id, subsystem, content, timeout_millis, SystemTime.getCurrentTime());
+		
+			storeMessage( message );
+			
+			dispatch_pending = message_count == 1;
+		}
+		
+		Iterator it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((BuddyPluginBuddyMessageListener)it.next()).messageQueued( message );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+		
+		if ( dispatch_pending ){
+			
+			buddy.persistentDispatchPending();
+		}
+		
+		return( message );
+	}	
+	
+	protected void
+	checkPersistentDispatch()
+	{
+		boolean	request_dispatch = false;
+		
+		synchronized( this ){
+
+			long	now = SystemTime.getCurrentTime();
+
+			if ( now < last_failure ){
+				
+				last_failure = now;
+			}
+
+			if ( now < last_pending_success ){
+				
+				last_pending_success = now;
+			}
+
+			if ( last_pending_success > 0 && now - last_pending_success >= BuddyPlugin.PERSISTENT_MSG_RETRY_PERIOD ){
+				
+				request_dispatch = true;
+				
+			}else if ( active_message != null || message_count == 0 || last_failure == 0 ){
+				
+					// no messages pending
+				
+			}else{
+				
+				request_dispatch = now - last_failure >= BuddyPlugin.PERSISTENT_MSG_RETRY_PERIOD;
+			}
+		}
+		
+		if ( request_dispatch ){
+			
+			buddy.persistentDispatchPending();
+		}
+	}
+	
+	protected void
+	persistentDispatch()
+	{
+		checkPendingSuccess();
+		
+		synchronized( this ){
+
+			if ( active_message != null || message_count == 0 ){
+				
+				return;
+			}
+			
+			List	messages = (List)config_map.get( "messages" );
+
+			Map		map = (Map)messages.get(0);
+			
+			try{
+				active_message = restoreMessage( map );
+				
+			}catch( Throwable e ){
+				
+					// should never happen...
+				
+				Debug.out( "Failed to restore message, deleting it", e );
+				
+				messages.remove(0);
+								
+				try{
+					saveConfig();
+					
+				}catch( Throwable f ){
+					
+					buddy.log( "Config save failed during delete of bad message", f );
+				}
+			}
+		}
+		
+		boolean	request_ok = false;
+		
+		try{
+			Map	request = active_message.getRequest();
+		
+			request_ok = true;
+			
+			buddy.sendMessage(
+					active_message.getSubsystem(),
+					request,
+					active_message.getTimeout(),
+					new BuddyPluginBuddyReplyListener()
+					{
+						public void
+						replyReceived(
+							BuddyPluginBuddy		from_buddy,
+							Map						reply )
+						{
+							BuddyPluginBuddyMessage message = active_message;
+							
+								// inform listeners before deleting message as it gives them one
+								// last chance to do something with the message if they so desire
+							
+							Iterator it = listeners.iterator();
+							
+							boolean	processing_ok = true;
+							
+								// prematurely reduce message count when informing listeners
+								// so they see the "correct" value
+							
+							try{
+								synchronized( BuddyPluginBuddyMessageHandler.this ){
+									
+									pending_deletes++;
+								}
+								
+								while( it.hasNext()){
+									
+									try{
+										if ( !((BuddyPluginBuddyMessageListener)it.next()).deliverySucceeded( message, reply )){
+											
+											processing_ok = false;
+										}
+										
+									}catch( Throwable e ){
+										
+										Debug.printStackTrace(e);
+									}
+								}
+							}finally{
+								
+								synchronized( BuddyPluginBuddyMessageHandler.this ){
+									
+									pending_deletes--;
+								}
+							}
+							if ( processing_ok ){
+							
+								message.delete();
+								
+							}else{
+								synchronized( BuddyPluginBuddyMessageHandler.this ){
+									
+									boolean found = false;
+									
+									List	messages = (List)config_map.get( "messages" );
+
+									if ( messages != null ){
+										
+										for ( int i=0;i<messages.size();i++){
+											
+											Map	msg = (Map)messages.get(i);
+											
+											if ( message.getID() == ((Long)msg.get( "id")).intValue()){
+												
+												found = true;
+												
+												messages.remove(i);
+												
+												try{
+													writeReply( message, reply );
+
+													List pending_success = (List)config_map.get( "pending_success" );
+													
+													if ( pending_success == null ){
+														
+														pending_success = new ArrayList();
+														
+														config_map.put( "pending_success", pending_success );
+													}
+													
+													pending_success.add( msg );
+													
+													last_pending_success = SystemTime.getCurrentTime();
+													
+													buddy.log( "Message moved to pending success queue after listener failed" );
+													
+													saveConfig();
+													
+												}catch( Throwable e ){
+													
+													buddy.log( "Config save failed during message pending queueing", e );
+												}
+												
+												break;
+											}
+										}	
+									}
+									
+									if ( !found ){
+																				
+										buddy.log( "Failed to find message " + message.getID());
+									}
+								}
+							}
+							
+							boolean messages_queued;
+							
+							synchronized( BuddyPluginBuddyMessageHandler.this ){
+
+								active_message 	= null;
+								
+								messages_queued = message_count > 0;
+								
+								last_failure	= 0;
+							}
+															
+							if ( messages_queued ){
+							
+								buddy.persistentDispatchPending();
+							}
+						}
+						
+						public void
+						sendFailed(
+							BuddyPluginBuddy		to_buddy,
+							BuddyPluginException	cause )
+						{
+							BuddyPluginBuddyMessage message = active_message;
+							
+							synchronized( BuddyPluginBuddyMessageHandler.this ){
+
+								active_message 	= null;
+								
+								last_failure	= SystemTime.getCurrentTime();
+							}
+							
+							reportFailed( message, cause, true );
+						}
+					});
+					
+		}catch( Throwable cause ){
+			
+			BuddyPluginBuddyMessage message = active_message;
+
+			synchronized( this ){
+
+				active_message 	= null;
+				
+				last_failure	= SystemTime.getCurrentTime();
+			}
+			
+			boolean do_subsequent = true;
+			
+			if ( !request_ok && !( cause instanceof BuddyPluginPasswordException )){
+				
+				buddy.logMessage( "Message request unavailable, deleting message" );
+				
+				message.delete();
+				
+				boolean messages_queued = false;
+				
+				synchronized( this ){
+
+					last_failure = 0;
+					
+					messages_queued = message_count > 0;
+				}
+					
+				if ( messages_queued ){
+				
+					do_subsequent = false;
+					
+					buddy.persistentDispatchPending();
+				}
+			}
+			
+			reportFailed( message, cause, do_subsequent );
+		}
+	}
+	
+	protected void
+	reportFailed(
+		BuddyPluginBuddyMessage		message,
+		Throwable					cause,
+		boolean						do_subsequent )
+	{	
+		BuddyPluginException b_cause;
+		
+		if ( cause instanceof BuddyPluginException ){
+			
+			b_cause = (BuddyPluginException)cause;
+			
+		}else{
+			
+			b_cause = new BuddyPluginException( "Failed to send message", cause );
+		}
+		
+		reportFailedSupport( message, b_cause );
+		
+		if ( do_subsequent ){
+			
+			List	other_messages = new ArrayList();
+			
+			synchronized( this ){
+	
+				List	messages = (List)config_map.get( "messages" );
+	
+				for (int i=0;i<messages.size();i++){
+				
+					try{
+						BuddyPluginBuddyMessage msg = restoreMessage((Map)messages.get(i));
+	
+						if ( msg.getID() != message.getID()){
+							
+							other_messages.add( msg );
+						}
+					}catch( Throwable e ){
+						
+					}
+				}
+			}
+	
+			if ( other_messages.size() > 0 ){
+				
+				BuddyPluginException o_cause = new BuddyPluginException( "Reporting probable failure to subsequent messages" );
+				
+				for (int i=0;i<other_messages.size();i++){
+					
+					reportFailedSupport((BuddyPluginBuddyMessage)other_messages.get(i), o_cause );
+				}
+			}
+		}
+	}
+	
+	protected void
+	reportFailedSupport(
+		BuddyPluginBuddyMessage		message,
+		BuddyPluginException		cause )
+	{	
+		Iterator it = listeners.iterator();
+	
+		while( it.hasNext()){
+			
+			try{
+				((BuddyPluginBuddyMessageListener)it.next()).deliveryFailed( message, cause );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+	}
+	
+	protected void
+	checkPendingSuccess()
+	{
+		List	pending_messages = new ArrayList();
+		
+		boolean	save_pending = false;
+		
+		synchronized( this ){
+			
+			last_pending_success	= 0;
+
+			List pending_success = (List)config_map.get( "pending_success" );
+
+			if ( pending_success == null || pending_success.size() == 0 ){
+				
+				return;
+			}
+			
+			Iterator it = pending_success.iterator();
+			
+			while( it.hasNext()){
+				
+				Map	map = (Map)it.next();
+			
+				try{
+					pending_messages.add( restoreMessage( map ));
+					
+				}catch( Throwable e ){
+					
+					buddy.log( "Failed to restore message from pending success queue", e );
+					
+					it.remove();
+					
+					save_pending = true;
+				}
+			}
+		}
+		
+		for ( int i=0;i<pending_messages.size();i++){
+	
+			BuddyPluginBuddyMessage message = (BuddyPluginBuddyMessage)pending_messages.get(i);
+			
+			try{
+				Map	reply = message.getReply();
+				
+				Iterator it = listeners.iterator();
+				
+				boolean	processing_ok = true;
+				
+				while( it.hasNext()){
+					
+					try{
+						if ( !((BuddyPluginBuddyMessageListener)it.next()).deliverySucceeded( message, reply )){
+							
+							processing_ok = false;
+						}
+						
+					}catch( Throwable e ){
+						
+						Debug.printStackTrace(e);
+					}
+				}
+	
+				if ( processing_ok ){
+				
+					message.delete();
+					
+				}else{
+					synchronized( this ){
+	
+						last_pending_success = SystemTime.getCurrentTime();
+					}
+				}
+			}catch( BuddyPluginPasswordException e ){
+				
+				buddy.log( "Failed to restore message reply", e );
+
+					// we don't want to delete the message if failed due to password issue
+				
+			}catch( Throwable e ){
+				
+				buddy.log( "Failed to restore message reply - deleting message", e );
+
+				message.delete();
+			}
+		}
+		
+		if ( save_pending ){
+			
+			try{
+				saveConfig();
+				
+			}catch( Throwable e ){
+				
+				buddy.log( "Save failed during pending success processing", e );
+			}
+		}
+	}
+	
+	public int
+	getMessageCount()
+	{
+		synchronized( this ){
+		
+			return( message_count - pending_deletes );
+		}
+	}
+	
+	protected void
+	deleteMessage(
+		BuddyPluginBuddyMessage		message )
+	{
+		Iterator it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((BuddyPluginBuddyMessageListener)it.next()).messageDeleted( message );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+		
+		synchronized( this ){
+			
+			String[]	keys = { "messages", "pending_success", "explicit" };
+			
+			for (int i=0;i<keys.length;i++){
+				
+				List	messages = (List)config_map.get( keys[i] );
+	
+				if ( messages != null ){
+	
+					boolean	found = false;
+					
+					for ( int j=0;j<messages.size();j++){
+						
+						Map	msg = (Map)messages.get(j);
+						
+						if ( message.getID() == ((Long)msg.get( "id")).intValue()){
+							
+							messages.remove(j);
+							
+							found	= true;
+							
+							break;
+						}
+					}
+				
+					if ( found ){
+					
+						deleteRequest( message );
+						
+						deleteReply( message );
+						
+						try{
+							saveConfig();
+							
+						}catch( Throwable e ){
+							
+							buddy.log( "Config save failed during message delete", e );
+						}
+						
+						return;
+					}
+				}
+			}
+		}
+	}
+	
+	protected void
+	destroy()
+	{
+		synchronized( this ){
+			
+			config_map.clear();
+			
+			try{
+				saveConfig();
+				
+			}catch( Throwable e ){
+				
+				buddy.log( "Config save failed during destroy", e );
+			}
+		}
+	}
+	
+	protected void
+	writeRequest(
+		BuddyPluginBuddyMessage		message,
+		Map							content )
+	
+		throws BuddyPluginException
+	{
+		writeContent( message.getID() + ".req.dat", content );
+	}
+	
+	protected Map
+	readRequest(
+		BuddyPluginBuddyMessage		message )
+	
+		throws BuddyPluginException
+	{		
+		return( readContent( message.getID() + ".req.dat" ));
+	}
+	
+	protected void
+	writeReply(
+		BuddyPluginBuddyMessage		message,
+		Map							content )
+	
+		throws BuddyPluginException
+	{
+		writeContent( message.getID() + ".rep.dat", content );
+	}
+	
+	protected Map
+	readReply(
+		BuddyPluginBuddyMessage		message )
+	
+		throws BuddyPluginException
+	{		
+		return( readContent( message.getID() + ".rep.dat" ));
+	}
+	
+	protected void
+	writeContent(
+		String						target_str,
+		Map							content )
+	
+		throws BuddyPluginException
+	{
+		if ( !store.exists()){
+			
+			if ( !store.mkdirs()){
+				
+				throw( new BuddyPluginException( "Failed to create " + store ));
+			}
+		}
+		
+		File target = new File( store, target_str );
+		
+		try{
+		
+			BuddyPlugin.cryptoResult result = buddy.encrypt( BEncoder.encode( content ));
+			
+			Map	store_map = new HashMap();
+			
+			store_map.put( "pk", buddy.getPlugin().getPublicKey());
+			store_map.put( "data", result.getPayload());
+			
+			if ( !buddy.writeConfigFile( target, store_map )){
+				
+				throw( new BuddyPluginException( "failed to write " + target ));
+			}
+			
+		}catch( BuddyPluginException e ){
+			
+			throw( e );
+			
+		}catch( Throwable e ){
+			
+			throw( new BuddyPluginException( "Failed to write message", e ));
+		}
+	}
+	
+	protected Map
+	readContent(
+		String						target_str )
+	
+		throws BuddyPluginException
+	{		
+		File target = new File( store, target_str );
+
+		if ( !target.exists()){
+
+			throw( new BuddyPluginException( "Failed to read persisted message - " + target + " doesn't exist" ));
+		}
+
+		Map	map = buddy.readConfigFile( target );
+		
+		if ( map.size() == 0 ){
+			
+			throw( new BuddyPluginException( "Failed to read persisted message file " + target ));
+		}
+		
+		try{
+			String	pk = new String((byte[])map.get("pk"));
+			
+			if ( !pk.equals( buddy.getPlugin().getPublicKey())){
+				
+				throw( new BuddyPluginException( "Can't decrypt message as key changed" ));
+			}
+			
+			byte[]	data = (byte[])map.get( "data" );
+			
+			return( BDecoder.decode( buddy.decrypt( data ).getPayload()));
+			
+		}catch( BuddyPluginException e ){
+			
+			throw( e );
+			
+		}catch( Throwable e ){
+			
+			throw( new BuddyPluginException( "Failed to read message", e ));
+		}
+	}
+	
+	protected void
+	deleteRequest(
+		BuddyPluginBuddyMessage		message )
+	{
+		deleteRequest( message.getID());
+	}
+	
+	protected void
+	deleteRequest(
+		int			id  )
+	{	
+		File target = new File( store, id + ".req.dat" );
+		
+		if ( target.exists()){
+			
+			if ( !target.delete()){
+				
+				Debug.out( "Failed to delete " + target );
+			}
+		}
+	}
+	
+	protected void
+	deleteReply(
+		BuddyPluginBuddyMessage		message )
+	{
+		deleteReply( message.getID());
+	}
+	
+	protected void
+	deleteReply(
+		int			id  )
+	{	
+		File target = new File( store, id + ".rep.dat" );
+		
+		if ( target.exists()){
+			
+			if ( !target.delete()){
+				
+				Debug.out( "Failed to delete " + target );
+			}
+		}
+	}
+	
+	public BuddyPluginBuddyMessage
+	storeExplicitMessage(
+		int		type,
+		Map		msg )
+	{
+		BuddyPluginBuddyMessage	message;
+				
+		synchronized( this ){
+			
+			int	id = next_message_id++;
+			
+			try{
+				message = 
+					new BuddyPluginBuddyMessage( 
+							this, id, BuddyPlugin.SUBSYSTEM_MSG_TYPE_BASE + type, msg, 0, SystemTime.getCurrentTime());
+			
+				storeExplicitMessage( message );
+				
+			}catch( Throwable e ){
+				
+				buddy.log( "Failed to store explicit message", e );
+				
+				return( null );
+			}
+		}
+		
+		return( message );
+	}
+	
+	public List<BuddyPluginBuddyMessage>
+	retrieveExplicitMessages(
+		int		type )
+	{
+		List<BuddyPluginBuddyMessage>	result = new ArrayList<BuddyPluginBuddyMessage>();
+		
+		synchronized( this ){
+
+			List<Map<String,Object>>	messages = (List<Map<String,Object>>)config_map.get( "explicit" );
+			
+			if ( messages != null ){
+				
+				for (int i=0;i<messages.size();i++){
+					
+					try{
+						BuddyPluginBuddyMessage msg = restoreMessage(messages.get(i));
+						
+						if ( msg.getSubsystem() == BuddyPlugin.SUBSYSTEM_MSG_TYPE_BASE + type ){
+							
+							result.add( msg );
+						}
+					}catch( Throwable e ){
+						
+						buddy.log( "Failed to restore message", e );
+					}
+				}
+			}
+		}
+		
+		return( result );
+	}
+	
+	protected void
+	storeExplicitMessage(
+		BuddyPluginBuddyMessage		msg )
+	
+		throws BuddyPluginException
+	{
+		storeMessageSupport( msg, "explicit" );
+	}
+	
+	protected void
+	storeMessage(
+		BuddyPluginBuddyMessage		msg )
+	
+		throws BuddyPluginException
+	{
+		storeMessageSupport( msg, "messages" );
+	}
+	
+	protected void
+	storeMessageSupport(
+		BuddyPluginBuddyMessage		msg,
+		String						key )
+	
+		throws BuddyPluginException
+	{
+		List	messages = (List)config_map.get( key );
+
+		if ( messages == null ){
+			
+			messages = new ArrayList();
+			
+			config_map.put( key, messages );
+		}
+		
+		Map map = new HashMap();
+		
+		map.put( "id", new Long( msg.getID()));
+		map.put( "ss", new Long( msg.getSubsystem()));
+		map.put( "to", new Long( msg.getTimeout()));
+		map.put( "cr", new Long( msg.getCreateTime()));
+		
+		messages.add( map );
+				
+		saveConfig();
+	}
+	
+	protected BuddyPluginBuddyMessage
+	restoreMessage(
+		Map			map )
+	
+		throws BuddyPluginException
+	{
+		int	id = ((Long)map.get( "id" )).intValue();
+		int	ss = ((Long)map.get( "ss" )).intValue();
+		int	to = ((Long)map.get( "to" )).intValue();
+		
+		long	cr = ((Long)map.get( "cr" )).longValue();
+		
+		return( new BuddyPluginBuddyMessage( this, id, ss, null, to, cr ));
+	}
+	
+	protected void
+	loadConfig()
+	{
+		File	config_file = new File( store, "messages.dat" );
+		
+		if ( config_file.exists()){
+			
+			config_map = buddy.readConfigFile( config_file );
+			
+		}else{
+			
+			config_map = new HashMap();
+		}
+		
+		List	messages = (List)config_map.get( "messages" );
+		
+		if ( messages != null ){
+			
+			message_count = messages.size();
+			
+			if ( message_count > 0 ){
+				
+				Map	last_msg = (Map)messages.get( message_count - 1 );
+				
+				next_message_id = ((Long)last_msg.get( "id")).intValue() + 1;
+			}
+		}
+		
+		List	pending_success = (List)config_map.get( "pending_success" );
+		
+		if ( pending_success != null ){
+			
+			int ps_count = pending_success.size();
+		
+			if ( ps_count > 0 ){
+										
+				Map	last_msg = (Map)pending_success.get( ps_count - 1 );
+					
+				next_message_id = Math.max( next_message_id, ((Long)last_msg.get( "id")).intValue() + 1 );
+				
+				synchronized( this ){
+				
+					last_pending_success = SystemTime.getCurrentTime();
+				}
+			}
+		}
+		
+		List	explicit = (List)config_map.get( "explicit" );
+		
+		if ( explicit != null ){
+			
+			int exp_count = explicit.size();
+		
+			if ( exp_count > 0 ){
+										
+				Map	last_msg = (Map)explicit.get( exp_count - 1 );
+					
+				next_message_id = Math.max( next_message_id, ((Long)last_msg.get( "id")).intValue() + 1 );
+			}
+		}
+	}
+	
+	protected void
+	saveConfig()
+	
+		throws BuddyPluginException
+	{
+		File	config_file = new File( store, "messages.dat" );
+		
+		List	messages 	= (List)config_map.get( "messages" );
+		List	pending 	= (List)config_map.get( "pending_success" );
+		List	explicit 	= (List)config_map.get( "explicit" );
+
+		if ( 	( messages == null || messages.size() == 0 ) && 
+				( pending == null || pending.size() == 0 ) && 
+				( explicit == null || explicit.size() == 0 )){
+			
+			if ( store.exists()){
+			
+				File[]	 files = store.listFiles();
+			
+				for (int i=0;i<files.length;i++ ){
+					
+					files[i].delete();
+				}
+				
+				store.delete();
+			}
+			
+			message_count = 0;
+			
+			next_message_id	= 0;
+			
+		}else{
+			
+			if ( !store.exists()){
+				
+				if ( !store.mkdirs()){
+					
+					throw( new BuddyPluginException( "Failed to create " + store ));
+				}
+			}
+			
+			if ( !buddy.writeConfigFile( config_file, config_map )){
+				
+				throw( new BuddyPluginException( "Failed to write" + config_file ));
+			}
+			
+			message_count = messages==null?0:messages.size();
+		}
+	}
+	
+	public void
+	addListener(
+		BuddyPluginBuddyMessageListener		listener )
+	{
+		listeners.add( listener );
+	}
+	
+	public void
+	removeListener(
+		BuddyPluginBuddyMessageListener		listener )
+	{
+		listeners.remove( listener );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessageListener.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessageListener.java
index 8546bf9..b0cc665 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessageListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyMessageListener.java
@@ -1,54 +1,53 @@
-/*
- * Created on Apr 23, 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.plugins.net.buddy;
-
-import java.util.Map;
-
-public interface 
-BuddyPluginBuddyMessageListener 
-{
-	public void
-	messageQueued(
-		BuddyPluginBuddyMessage		message );
-	
-		/**
-		 * Indicates that a message has been delivered to the buddy
-		 * @param message
-		 * @param reply
-		 * @return true if message procesing complete, false if failed and require re-invocation of this listener periodically to 
-		 * attempt processing again
-		 */
-	
-	public boolean
-	deliverySucceeded(
-		BuddyPluginBuddyMessage		message,
-		Map							reply );
-	
-	public void
-	deliveryFailed(
-		BuddyPluginBuddyMessage		message,
-		BuddyPluginException		cause );
-	
-	public void
-	messageDeleted(
-		BuddyPluginBuddyMessage		message );
-}
+/*
+ * Created on Apr 23, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+import java.util.Map;
+
+public interface 
+BuddyPluginBuddyMessageListener 
+{
+	public void
+	messageQueued(
+		BuddyPluginBuddyMessage		message );
+	
+		/**
+		 * Indicates that a message has been delivered to the buddy
+		 * @param message
+		 * @param reply
+		 * @return true if message procesing complete, false if failed and require re-invocation of this listener periodically to 
+		 * attempt processing again
+		 */
+	
+	public boolean
+	deliverySucceeded(
+		BuddyPluginBuddyMessage		message,
+		Map							reply );
+	
+	public void
+	deliveryFailed(
+		BuddyPluginBuddyMessage		message,
+		BuddyPluginException		cause );
+	
+	public void
+	messageDeleted(
+		BuddyPluginBuddyMessage		message );
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyReplyListener.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyReplyListener.java
index e6762e9..61cea75 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyReplyListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyReplyListener.java
@@ -1,38 +1,37 @@
-/*
- * Created on Apr 3, 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.plugins.net.buddy;
-
-import java.util.Map;
-
-public interface 
-BuddyPluginBuddyReplyListener 
-{
-	public void
-	replyReceived(
-		BuddyPluginBuddy		from_buddy,
-		Map						reply );
-	
-	public void
-	sendFailed(
-		BuddyPluginBuddy		to_buddy,
-		BuddyPluginException	cause );
-}
+/*
+ * Created on Apr 3, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+import java.util.Map;
+
+public interface 
+BuddyPluginBuddyReplyListener 
+{
+	public void
+	replyReceived(
+		BuddyPluginBuddy		from_buddy,
+		Map						reply );
+	
+	public void
+	sendFailed(
+		BuddyPluginBuddy		to_buddy,
+		BuddyPluginException	cause );
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyRequestListener.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyRequestListener.java
index fd14980..c96850a 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyRequestListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginBuddyRequestListener.java
@@ -1,53 +1,52 @@
-/*
- * Created on Apr 4, 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.plugins.net.buddy;
-
-import java.util.Map;
-
-public interface 
-BuddyPluginBuddyRequestListener 
-{
-		/**
-		 * Request receieved for a buddy. If the buddy is not authorised then the BuddyPluginBuddy
-		 * is transient and should only be used for the duration of this request. Use outside of 
-		 * this context is undefined. If you want to authorise a transient buddy then you need
-		 * to call BuddyPlugin.addBuddy with the required public key
-		 * 
-		 * @param from_buddy
-		 * @param subsystem
-		 * @param request
-		 * @return
-		 * @throws BuddyPluginException
-		 */
-	
-	public Map
-	requestReceived(
-		BuddyPluginBuddy	from_buddy,
-		int					subsystem,
-		Map					request )
-	
-		throws BuddyPluginException;
-	
-	public void
-	pendingMessages(
-		BuddyPluginBuddy[]	from_buddies );
-}
+/*
+ * Created on Apr 4, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+import java.util.Map;
+
+public interface 
+BuddyPluginBuddyRequestListener 
+{
+		/**
+		 * Request receieved for a buddy. If the buddy is not authorised then the BuddyPluginBuddy
+		 * is transient and should only be used for the duration of this request. Use outside of 
+		 * this context is undefined. If you want to authorise a transient buddy then you need
+		 * to call BuddyPlugin.addBuddy with the required public key
+		 * 
+		 * @param from_buddy
+		 * @param subsystem
+		 * @param request
+		 * @return
+		 * @throws BuddyPluginException
+		 */
+	
+	public Map
+	requestReceived(
+		BuddyPluginBuddy	from_buddy,
+		int					subsystem,
+		Map					request )
+	
+		throws BuddyPluginException;
+	
+	public void
+	pendingMessages(
+		BuddyPluginBuddy[]	from_buddies );
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginException.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginException.java
index 6e3ca0c..c5630d7 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginException.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginException.java
@@ -1,43 +1,42 @@
-/*
- * Created on Apr 3, 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.plugins.net.buddy;
-
-public class 
-BuddyPluginException
-	extends Exception
-{
-	
-	public
-	BuddyPluginException(
-		String	str )
-	{
-		super( str );
-	}
-	
-	public
-	BuddyPluginException(
-		String		str,
-		Throwable 	cause )
-	{
-		super( str, cause );
-	}
-}
+/*
+ * Created on Apr 3, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+public class 
+BuddyPluginException
+	extends Exception
+{
+	
+	public
+	BuddyPluginException(
+		String	str )
+	{
+		super( str );
+	}
+	
+	public
+	BuddyPluginException(
+		String		str,
+		Throwable 	cause )
+	{
+		super( str, cause );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginListener.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginListener.java
index 906a8f7..d885fd2 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginListener.java
@@ -1,51 +1,53 @@
-/*
- * Created on Apr 1, 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.plugins.net.buddy;
-
-public interface 
-BuddyPluginListener 
-{
-	public void
-	initialised(
-		boolean		available );
-	
-	public void
-	buddyAdded(
-		BuddyPluginBuddy	buddy );
-	
-	public void
-	buddyRemoved(
-		BuddyPluginBuddy	buddy );
-
-	public void
-	buddyChanged(
-		BuddyPluginBuddy	buddy );
-	
-	public void
-	messageLogged(
-		String		str,
-		boolean		is_error );
-	
-	public void
-	enabledStateChanged(
-		boolean enabled);
-}
+/*
+ * Created on Apr 1, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+public interface 
+BuddyPluginListener 
+{
+	public void
+	initialised(
+		boolean		available );
+	
+	public void
+	buddyAdded(
+		BuddyPluginBuddy	buddy );
+	
+	public void
+	buddyRemoved(
+		BuddyPluginBuddy	buddy );
+
+	public void
+	buddyChanged(
+		BuddyPluginBuddy	buddy );
+	
+	public void
+	messageLogged(
+		String		str,
+		boolean		is_error );
+	
+	public void
+	enabledStateChanged(
+		boolean enabled );
+	
+	public void
+	updated();
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginPasswordException.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginPasswordException.java
index de81a7d..d1ca462 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginPasswordException.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginPasswordException.java
@@ -1,48 +1,47 @@
-/*
- * Created on May 2, 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.plugins.net.buddy;
-
-
-public class 
-BuddyPluginPasswordException
-	extends BuddyPluginException
-{
-	
-	private boolean 	was_incorrecte;
-	
-	public 
-	BuddyPluginPasswordException(
-		boolean		_was_incorrecte,
-		String		str,
-		Throwable	cause )
-	{
-		super( str, cause );
-		
-		was_incorrecte = _was_incorrecte;
-	}
-	
-	public boolean
-	wasIncorrect()
-	{
-		return( was_incorrecte );
-	}
-}
+/*
+ * Created on May 2, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+
+public class 
+BuddyPluginPasswordException
+	extends BuddyPluginException
+{
+	
+	private boolean 	was_incorrecte;
+	
+	public 
+	BuddyPluginPasswordException(
+		boolean		_was_incorrecte,
+		String		str,
+		Throwable	cause )
+	{
+		super( str, cause );
+		
+		was_incorrecte = _was_incorrecte;
+	}
+	
+	public boolean
+	wasIncorrect()
+	{
+		return( was_incorrecte );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginTimeoutException.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginTimeoutException.java
index 0da1731..4b11c22 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginTimeoutException.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginTimeoutException.java
@@ -1,45 +1,44 @@
-/*
- * Created on Jun 1, 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.plugins.net.buddy;
-
-public class 
-BuddyPluginTimeoutException
-	extends BuddyPluginException
-{
-	private boolean	was_active;
-	
-	protected
-	BuddyPluginTimeoutException(
-		String		str,
-		boolean		active )
-	{
-		super( str );
-		
-		was_active = active;
-	}
-	
-	protected boolean
-	wasActive()
-	{
-		return( was_active );
-	}
-}
+/*
+ * Created on Jun 1, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy;
+
+public class 
+BuddyPluginTimeoutException
+	extends BuddyPluginException
+{
+	private boolean	was_active;
+	
+	protected
+	BuddyPluginTimeoutException(
+		String		str,
+		boolean		active )
+	{
+		super( str );
+		
+		was_active = active;
+	}
+	
+	protected boolean
+	wasActive()
+	{
+		return( was_active );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginUtils.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginUtils.java
new file mode 100644
index 0000000..2f95cac
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginUtils.java
@@ -0,0 +1,365 @@
+/*
+ * Created on Nov 5, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.plugins.net.buddy;
+
+import java.util.Map;
+
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
+import org.gudy.azureus2.core3.util.ByteFormatter;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.ChatInstance;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginViewInterface.ViewListener;
+
+
+public class 
+BuddyPluginUtils 
+{
+	private static BuddyPlugin
+	getPlugin()
+	{
+		PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( "azbuddy", true );
+		
+		if ( pi != null ){
+			
+			return((BuddyPlugin)pi.getPlugin());
+		}
+		
+		return( null );
+	}
+	
+	public static BuddyPluginBeta
+	getBetaPlugin()
+	{
+		BuddyPlugin bp = getPlugin();
+		
+		if ( bp != null && bp.isBetaEnabled()){
+			
+			BuddyPluginBeta beta = bp.getBeta();
+			
+			if ( beta.isAvailable()){
+				
+				return( beta );
+			}
+		}
+		
+		return( null );
+	}
+	
+	public static boolean
+	isBetaChatAvailable()
+	{
+		BuddyPlugin bp = getPlugin();
+		
+		if ( bp != null && bp.isBetaEnabled()){
+			
+			return( bp.getBeta().isAvailable());
+		}
+		
+		return( false );
+	}
+	
+	public static boolean
+	isBetaChatAnonAvailable()
+	{
+		BuddyPlugin bp = getPlugin();
+		
+		if ( bp != null && bp.isBetaEnabled()){
+			
+			return( bp.getBeta().isAvailable() && bp.getBeta().isI2PAvailable());
+		}
+		
+		return( false );
+	}
+	
+	public static void
+	createBetaChat(
+		final String		network,
+		final String		key,
+		final Runnable		callback )
+	{
+		new AEThread2( "Chat create async" )
+		{
+			public void
+			run()
+			{
+				try{
+					BuddyPlugin bp = getPlugin();
+					
+					bp.getBeta().getAndShowChat( network, key );
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+					
+				}finally{
+					
+					if ( callback != null ){
+					
+						callback.run();
+					}
+				}
+			}
+		}.start();
+	}
+	
+	public static Map<String,Object>
+	peekChat(
+		String		net,
+		String		key )
+	{
+		BuddyPlugin bp = getPlugin();
+		
+		if ( bp != null && bp.isBetaEnabled()){
+			
+			return( bp.getBeta().peekChat( net, key ));
+		}
+		
+		return( null );
+	}
+	
+	public static Map<String,Object>
+	peekChat(
+		Download		download )
+	{
+		BuddyPlugin bp = getPlugin();
+		
+		if ( bp != null && bp.isBetaEnabled()){
+			
+			return( bp.getBeta().peekChat( download ));
+		}
+		
+		return( null );
+	}
+	
+	private static AsyncDispatcher peek_dispatcher = new AsyncDispatcher( "peeker" );
+	
+	public static void
+	peekChatAsync(
+		final String		net,
+		final String		key,
+		final Runnable		done )
+	{
+		boolean	async = false;
+		
+		try{
+			if ( isBetaChatAvailable()){
+	
+				if ( net != AENetworkClassifier.AT_PUBLIC && !isBetaChatAnonAvailable()){
+					
+					return;
+				}
+				
+				if ( peek_dispatcher.getQueueSize() > 200 ){
+					
+					return;
+				}
+								
+				peek_dispatcher.dispatch(
+					new AERunnable() {
+						
+						@Override
+						public void 
+						runSupport() 
+						{
+							try{
+								Map<String,Object> peek_data = BuddyPluginUtils.peekChat( net, key );
+									
+								if ( peek_data != null ){
+									
+									Number	message_count 	= (Number)peek_data.get( "m" );
+									Number	node_count 		= (Number)peek_data.get( "n" );
+									
+									if ( message_count != null && node_count != null ){
+										
+										if ( message_count.intValue() > 0 ){
+											
+											BuddyPluginBeta.ChatInstance chat = BuddyPluginUtils.getChat( net, key );
+						
+											if ( chat != null ){
+												
+												chat.setAutoNotify( true );
+											}
+										}
+									}	
+								}
+							}finally{
+								
+								done.run();
+							}
+						}
+					});
+				
+				async = true;
+			}
+		}finally{
+			
+			if ( !async ){
+				
+				done.run();
+			}
+		}
+	}
+	
+	public static ChatInstance
+	getChat(
+		String		net,
+		String		key )
+	{
+		BuddyPlugin bp = getPlugin();
+		
+		if ( bp != null && bp.isBetaEnabled()){
+			
+			try{
+				return( bp.getBeta().getChat( net, key ));
+				
+			}catch( Throwable e ){
+				
+			}
+		}
+		
+		return( null );
+	}
+	
+	public static ChatInstance
+	getChat(
+		String					net,
+		String					key,
+		Map<String,Object>		options )
+	{
+		BuddyPlugin bp = getPlugin();
+		
+		if ( bp != null && bp.isBetaEnabled()){
+			
+			try{
+				return( bp.getBeta().getChat( net, key, options ));
+				
+			}catch( Throwable e ){
+				
+			}
+		}
+		
+		return( null );
+	}
+	
+	public static ChatInstance
+	getChat(
+		Download		download )
+	{
+		BuddyPlugin bp = getPlugin();
+		
+		if ( bp != null && bp.isBetaEnabled()){
+			
+			return( bp.getBeta().getChat( download ));
+		}
+		
+		return( null );
+	}
+	
+	public static BuddyPluginViewInterface.View
+	buildChatView(
+		Map<String,Object>	properties,
+		ViewListener		listener )
+	{
+		BuddyPlugin bp = getPlugin();
+		
+		if ( bp != null && bp.isBetaEnabled() && bp.getBeta().isAvailable()){
+			
+			BuddyPluginViewInterface ui = bp.getSWTUI();
+			
+			if ( ui != null ){
+				
+				return( ui.buildView( properties, listener ));
+			}
+		}
+
+		return( null );
+	}
+	
+	public static String
+	getChatKey(
+		TOTorrent		torrent )
+	{
+		if ( torrent == null ){
+			
+			return( null );
+		}
+		
+		return( getChatKey( PluginCoreUtils.wrap( torrent )));
+	}
+	
+	public static String
+	getChatKey(
+		Download		download )
+	{
+		return( getChatKey( download.getTorrent()));
+	}
+	
+	public static String
+	getChatKey(
+		Torrent		torrent )
+	{		
+		if ( torrent == null ){
+			
+			return( null );
+		}
+		
+			// use torrent name here to canonicalize things in case user has renamed download display name
+			// also it is more important to get a consistent string rather than something correctly localised
+		
+		String	torrent_name = null;
+		
+		try{
+			TOTorrent to_torrent = PluginCoreUtils.unwrap( torrent );
+			
+			torrent_name = to_torrent.getUTF8Name();
+			
+			if ( torrent_name == null ){
+				
+				torrent_name = new String( to_torrent.getName(), "UTF-8" );
+			}
+		}catch( Throwable e ){
+			
+		}
+		
+		if ( torrent_name == null ){
+			
+			torrent_name = torrent.getName();
+		}
+		
+		String key = "Download: " + torrent_name + " {" + ByteFormatter.encodeString( torrent.getHash()) + "}";
+
+		return( key );
+	}
+	
+
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginViewInterface.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginViewInterface.java
new file mode 100644
index 0000000..3bc5ec0
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/BuddyPluginViewInterface.java
@@ -0,0 +1,73 @@
+/*
+ * Created on Oct 21, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.plugins.net.buddy;
+
+import java.util.Map;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.ChatInstance;
+
+public interface 
+BuddyPluginViewInterface 
+{
+	public void
+	openChat(
+		ChatInstance		chat );
+	
+	public static final String	VP_SWT_COMPOSITE	= "swt_comp";
+	public static final String	VP_DOWNLOAD			= "download";		// DownloadAdapter
+	
+	public View
+	buildView(
+		Map<String,Object>	properties,
+		ViewListener		listener );
+	
+	public interface
+	DownloadAdapter
+	{
+		public DownloadManager
+		getCoreDownload();
+		
+		public String[]
+		getNetworks();
+		
+		public String
+		getChatKey();
+	}
+	
+	public interface
+	View
+	{
+		public void
+		destroy();
+	}
+	
+	public interface
+	ViewListener
+	{
+		public void
+		chatActivated(
+			ChatInstance		chat );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginView.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginView.java
index 5a69e68..4cca005 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginView.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginView.java
@@ -1,460 +1,2808 @@
-/*
- * Created on Mar 19, 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.plugins.net.buddy.swt;
-
-import java.net.URL;
-
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.ui.UIInstance;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
-import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntry;
-import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntryListener;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
-
-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.plugins.net.buddy.BuddyPlugin;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2Listener;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginListener;
-import com.aelitis.azureus.plugins.net.buddy.tracker.BuddyPluginTracker;
-import com.aelitis.azureus.plugins.net.buddy.tracker.BuddyPluginTrackerListener;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-
-
-public class 
-BuddyPluginView
-	implements UISWTViewEventListener
-{
-	private BuddyPlugin		plugin;
-	private UISWTInstance	ui_instance;
-	
-	private BuddyPluginViewInstance		current_instance;
-	
-	private Image iconNLI;
-	private Image iconIDLE;
-	private Image iconIN;
-	private Image iconOUT;
-		
-	public
-	BuddyPluginView(
-		BuddyPlugin		_plugin,
-		UIInstance		_ui_instance,
-		String			VIEW_ID )
-	{
-		plugin			= _plugin;
-		ui_instance		= (UISWTInstance)_ui_instance;
-		
-		plugin.getAZ2Handler().addListener(
-			new BuddyPluginAZ2Listener()
-			{
-				public void
-				chatCreated(
-					final BuddyPluginAZ2.chatInstance		chat )
-				{
-					final Display display = ui_instance.getDisplay();
-					
-					if ( !display.isDisposed()){
-						
-						display.asyncExec(
-							new Runnable()
-							{
-								public void
-								run()
-								{
-									if ( !display.isDisposed()){
-									
-										new BuddyPluginViewChat( plugin, display, chat );
-									}
-								}
-							});
-					}
-				}
-				
-				public void
-				chatDestroyed(
-					BuddyPluginAZ2.chatInstance		chat )
-				{
-				}
-			});
-		
-
-		SimpleTimer.addEvent("BuddyStatusInit", SystemTime.getOffsetTime(1000),
-				new TimerEventPerformer() {
-					public void perform(
-							TimerEvent event ) 
-					{
-						UISWTStatusEntry label = ui_instance.createStatusEntry();
-
-						label.setText(MessageText.getString("azbuddy.tracker.bbb.status.title"));
-
-						new statusUpdater(ui_instance);
-					}
-				});
-
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				ImageLoader imageLoader = ImageLoader.getInstance();
-
-				iconNLI = imageLoader.getImage( "bbb_nli" );
-				iconIDLE = imageLoader.getImage( "bbb_idle" );
-				iconIN = imageLoader.getImage( "bbb_in" );
-				iconOUT = imageLoader.getImage( "bbb_out" );
-			}
-		});
-		
-		ui_instance.addView(	UISWTInstance.VIEW_MAIN, VIEW_ID, this );
-	}
-	
-	public boolean 
-	eventOccurred(
-		UISWTViewEvent event )
-	{
-		switch( event.getType() ){
-
-			case UISWTViewEvent.TYPE_CREATE:{
-				
-				if ( current_instance != null ){
-					
-					return( false );
-				}
-								
-				break;
-			}
-			case UISWTViewEvent.TYPE_INITIALIZE:{
-				
-
-				current_instance = new BuddyPluginViewInstance(plugin, ui_instance, (Composite)event.getData());
-				
-				break;
-			}
-			case UISWTViewEvent.TYPE_CLOSE:
-			case UISWTViewEvent.TYPE_DESTROY:{
-				
-				try{
-					if ( current_instance != null ){
-						
-						current_instance.destroy();
-					}
-				}finally{
-					
-					current_instance = null;
-				}
-				
-				break;
-			}
-		}
-		
-		return true;
-	}
-	
-	protected class
-	statusUpdater
-		implements BuddyPluginTrackerListener
-	{
-		private UISWTStatusEntry	label;
-		private UISWTStatusEntry	status;
-		private BuddyPluginTracker	tracker;
-		
-		private TimerEventPeriodic	update_event;
-
-		private CryptoManager	crypto;
-		private boolean			crypto_ok;
-		private boolean			has_buddies;
-		
-		protected
-		statusUpdater(
-			UISWTInstance		instance )
-		{
-			status	= ui_instance.createStatusEntry();
-			label 	= ui_instance.createStatusEntry();
-			
-			label.setText( MessageText.getString( "azbuddy.tracker.bbb.status.title" ));
-			label.setTooltipText( MessageText.getString( "azbuddy.tracker.bbb.status.title.tooltip" ));
-			
-			tracker = plugin.getTracker();
-				
-			status.setText( "" );
-			
-			status.setImageEnabled( true );
-			
-			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(),
-									"dweeble" );
-			
-			mi.addListener(
-				new MenuItemListener()
-				{
-					public void
-					selected(
-						MenuItem			menu,
-						Object 				target )
-					{
-						System.out.println( "whee" );
-					}
-				});
-			*/
-			
-			UISWTStatusEntryListener click_listener = 
-				new UISWTStatusEntryListener()
-			{
-					public void 
-					entryClicked(
-						UISWTStatusEntry entry )
-					{
-						try{
-							plugin.getPluginInterface().getUIManager().openURL(
-									new URL( "http://wiki.vuze.com" ));
-							
-						}catch( Throwable e ){
-							
-							Debug.printStackTrace(e);
-						}
-					}
-				};
-				
-			status.setListener( click_listener );
-			label.setListener( click_listener );
-	
-			
-			plugin.addListener( 
-				new BuddyPluginListener()
-				{
-					public void
-					initialised(
-						boolean		available )
-					{
-					}
-					
-					public void
-					buddyAdded(
-						BuddyPluginBuddy	buddy )
-					{
-						if ( !has_buddies ){
-							
-							has_buddies = true;
-						
-							updateStatus();
-						}
-					}
-					
-					public void
-					buddyRemoved(
-						BuddyPluginBuddy	buddy )
-					{
-						has_buddies	= plugin.getBuddies().size() > 0;	
-						
-						if ( !has_buddies ){
-							
-							updateStatus();
-						}
-					}
-
-					public void
-					buddyChanged(
-						BuddyPluginBuddy	buddy )
-					{
-					}
-					
-					public void
-					messageLogged(
-						String		str,
-						boolean		error )
-					{
-					}
-					
-					public void
-					enabledStateChanged(
-						boolean enabled )
-					{
-					}
-				});
-			
-			crypto = CryptoManagerFactory.getSingleton();
-			
-			crypto.addKeyListener(
-				new CryptoManagerKeyListener()
-				{
-					public void
-					keyChanged(
-						CryptoHandler		handler )
-					{
-					}
-					
-					public void
-					keyLockStatusChanged(
-						CryptoHandler		handler )
-					{
-						boolean	ok = crypto.getECCHandler().isUnlocked();
-						
-						if ( ok != crypto_ok ){
-							
-							crypto_ok = ok;
-							
-							updateStatus();
-						}
-					}
-				});
-			
-			crypto_ok = crypto.getECCHandler().isUnlocked();
-				
-			updateStatus();
-		}
-				
-		public void
-		networkStatusChanged(
-			BuddyPluginTracker	tracker,
-			int					new_status )
-		{
-			updateStatus();
-		}
-		
-		protected synchronized void
-		updateStatus()
-		{
-			if ( tracker.isEnabled() && has_buddies ){
-				
-				status.setVisible( true );
-				label.setVisible( true );
-				
-				if ( has_buddies && !crypto_ok ){
-					
-					status.setImage( iconNLI );
-					
-					status.setTooltipText( MessageText.getString( "azbuddy.tracker.bbb.status.nli" ));
-
-					disableUpdates();
-					
-				}else{
-					
-					int	network_status = tracker.getNetworkStatus();
-					
-					if ( network_status == BuddyPluginTracker.BUDDY_NETWORK_IDLE ){
-						
-						status.setImage( iconIDLE );
-						
-						status.setTooltipText( MessageText.getString( "azbuddy.tracker.bbb.status.idle" ));
-						
-						disableUpdates();
-						
-					}else if ( network_status == BuddyPluginTracker.BUDDY_NETWORK_INBOUND ){
-						
-						status.setImage( iconIN );
-						
-						enableUpdates();
-						
-					}else{
-						
-						status.setImage( iconOUT );
-						
-						enableUpdates();
-					}
-				}
-			}else{
-				
-				disableUpdates();
-				
-				status.setVisible( false );
-				label.setVisible( false );
-			}
-		}
-		
-		protected void
-		enableUpdates()
-		{
-			if ( update_event == null ){
-				
-				update_event = SimpleTimer.addPeriodicEvent(
-					"Buddy:GuiUpdater",
-					2500,
-					new TimerEventPerformer()
-					{
-						public void 
-						perform(
-							TimerEvent event ) 
-						{	
-							synchronized( statusUpdater.this ){
-								
-								if ( tracker.isEnabled() && ( crypto_ok || !has_buddies )){
-									
-									String	tt;
-															
-									int ns = tracker.getNetworkStatus();
-									
-									if ( ns == BuddyPluginTracker.BUDDY_NETWORK_IDLE ){
-										
-										tt = MessageText.getString( "azbuddy.tracker.bbb.status.idle" );
-									
-									}else if ( ns == BuddyPluginTracker.BUDDY_NETWORK_INBOUND ){
-										
-										tt = MessageText.getString( "azbuddy.tracker.bbb.status.in" ) + ": " + DisplayFormatters.formatByteCountToKiBEtcPerSec( tracker.getNetworkReceiveBytesPerSecond());
-										
-									}else{
-										
-										tt = MessageText.getString( "azbuddy.tracker.bbb.status.out" ) + ": " + DisplayFormatters.formatByteCountToKiBEtcPerSec( tracker.getNetworkSendBytesPerSecond());
-									}
-																			
-									status.setTooltipText( tt );
-								}
-							}
-						}					
-					});
-			}
-		}
-		
-		protected void
-		disableUpdates()
-		{
-			if ( update_event != null ){
-
-				update_event.cancel();
-				
-				update_event = null;
-			}
-		}
-		
-		public void 
-		enabledStateChanged(
-			BuddyPluginTracker 		tracker,
-			boolean 				enabled ) 
-		{
-			updateStatus();
-		}
-	}
-}
+/*
+ * Created on Mar 19, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy.swt;
+
+import java.applet.Applet;
+import java.applet.AudioClip;
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+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.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.Graphic;
+import org.gudy.azureus2.plugins.ui.UIInstance;
+import org.gudy.azureus2.plugins.ui.menus.MenuContext;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
+import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
+import org.gudy.azureus2.plugins.ui.tables.TableManager;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl;
+import org.gudy.azureus2.ui.swt.MenuBuildUtils;
+import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
+import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntry;
+import org.gudy.azureus2.ui.swt.plugins.UISWTStatusEntryListener;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
+import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
+
+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.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
+import com.aelitis.azureus.core.tag.Taggable;
+import com.aelitis.azureus.core.tag.TaggableLifecycleAdapter;
+import com.aelitis.azureus.plugins.I2PHelpers;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2Listener;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAdapter;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.ChatMessage;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginUtils;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginViewInterface;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.ChatInstance;
+import com.aelitis.azureus.plugins.net.buddy.tracker.BuddyPluginTracker;
+import com.aelitis.azureus.plugins.net.buddy.tracker.BuddyPluginTrackerListener;
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
+import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+
+
+public class 
+BuddyPluginView
+	implements UISWTViewEventListener, BuddyPluginViewInterface
+{
+	private BuddyPlugin		plugin;
+	private UISWTInstance	ui_instance;
+	private String			VIEW_ID;
+	
+	private BuddyPluginViewInstance		current_instance;
+	
+	private Image iconNLI;
+	private Image iconIDLE;
+	private Image iconIN;
+	private Image iconOUT;
+	
+	private	final String default_sound 	= "org/gudy/azureus2/ui/icons/downloadFinished.wav";
+
+	public
+	BuddyPluginView(
+		BuddyPlugin		_plugin,
+		UIInstance		_ui_instance,
+		String			_VIEW_ID )
+	{
+		plugin			= _plugin;
+		ui_instance		= (UISWTInstance)_ui_instance;
+		VIEW_ID			= _VIEW_ID;
+		
+		plugin.getAZ2Handler().addListener(
+			new BuddyPluginAZ2Listener()
+			{
+				public void
+				chatCreated(
+					final BuddyPluginAZ2.chatInstance		chat )
+				{
+					final Display display = ui_instance.getDisplay();
+					
+					if ( !display.isDisposed()){
+						
+						display.asyncExec(
+							new Runnable()
+							{
+								public void
+								run()
+								{
+									if ( !display.isDisposed()){
+									
+										new BuddyPluginViewChat( plugin, display, chat );
+									}
+								}
+							});
+					}
+				}
+				
+				public void
+				chatDestroyed(
+					BuddyPluginAZ2.chatInstance		chat )
+				{
+				}
+			});
+		
+
+		SimpleTimer.addEvent("BuddyStatusInit", SystemTime.getOffsetTime(1000),
+				new TimerEventPerformer() {
+					public void perform(
+							TimerEvent event ) 
+					{
+						UISWTStatusEntry label = ui_instance.createStatusEntry();
+
+						label.setText(MessageText.getString("azbuddy.tracker.bbb.status.title"));
+
+						new statusUpdater(ui_instance);
+					}
+				});
+
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				ImageLoader imageLoader = ImageLoader.getInstance();
+
+				iconNLI = imageLoader.getImage( "bbb_nli" );
+				iconIDLE = imageLoader.getImage( "bbb_idle" );
+				iconIN = imageLoader.getImage( "bbb_in" );
+				iconOUT = imageLoader.getImage( "bbb_out" );
+			}
+		});
+		
+		ui_instance.addView(	UISWTInstance.VIEW_MAIN, VIEW_ID, this );
+					
+		checkBetaInit();
+	}
+	
+	public boolean 
+	eventOccurred(
+		UISWTViewEvent event )
+	{
+		switch( event.getType() ){
+
+			case UISWTViewEvent.TYPE_CREATE:{
+				
+				if ( current_instance != null ){
+					
+					return( false );
+				}
+								
+				event.getView().setDestroyOnDeactivate(false);
+				break;
+			}
+			case UISWTViewEvent.TYPE_INITIALIZE:{
+				
+
+				current_instance = new BuddyPluginViewInstance( this, plugin, ui_instance, (Composite)event.getData());
+				
+				break;
+			}
+			case UISWTViewEvent.TYPE_CLOSE:
+			case UISWTViewEvent.TYPE_DESTROY:{
+				
+				try{
+					if ( current_instance != null ){
+						
+						current_instance.destroy();
+					}
+				}finally{
+					
+					current_instance = null;
+				}
+				
+				break;
+			}
+		}
+		
+		return true;
+	}
+	
+	public void 
+	openChat(
+		final ChatInstance chat )
+	{
+		final Display display = Display.getDefault();
+	
+		if ( display.isDisposed()){
+			
+			return;
+		}
+		
+		display.asyncExec(
+			new Runnable()
+			{
+				public void
+				run()
+				{
+					if ( display.isDisposed()){
+						
+						return;
+					}
+				
+					new BuddyPluginViewBetaChat( BuddyPluginView.this, plugin, chat );
+				}
+			});
+	}
+	
+	protected class
+	statusUpdater
+		implements BuddyPluginTrackerListener
+	{
+		private UISWTStatusEntry	label;
+		private UISWTStatusEntry	status;
+		private BuddyPluginTracker	tracker;
+		
+		private TimerEventPeriodic	update_event;
+
+		private CryptoManager	crypto;
+		private boolean			crypto_ok;
+		private boolean			has_buddies;
+		
+		protected
+		statusUpdater(
+			UISWTInstance		instance )
+		{
+			status	= ui_instance.createStatusEntry();
+			label 	= ui_instance.createStatusEntry();
+			
+			label.setText( MessageText.getString( "azbuddy.tracker.bbb.status.title" ));
+			label.setTooltipText( MessageText.getString( "azbuddy.tracker.bbb.status.title.tooltip" ));
+			
+			tracker = plugin.getTracker();
+				
+			status.setText( "" );
+			
+			status.setImageEnabled( true );
+			
+			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(),
+									"dweeble" );
+			
+			mi.addListener(
+				new MenuItemListener()
+				{
+					public void
+					selected(
+						MenuItem			menu,
+						Object 				target )
+					{
+						System.out.println( "whee" );
+					}
+				});
+			*/
+			
+			UISWTStatusEntryListener click_listener = 
+				new UISWTStatusEntryListener()
+			{
+					public void 
+					entryClicked(
+						UISWTStatusEntry entry )
+					{
+						try{
+							plugin.getPluginInterface().getUIManager().openURL(
+									new URL( "http://wiki.vuze.com" ));
+							
+						}catch( Throwable e ){
+							
+							Debug.printStackTrace(e);
+						}
+					}
+				};
+				
+			status.setListener( click_listener );
+			label.setListener( click_listener );
+	
+			
+			plugin.addListener( 
+				new BuddyPluginAdapter()
+				{
+					public void
+					initialised(
+						boolean		available )
+					{
+					}
+					
+					public void
+					buddyAdded(
+						BuddyPluginBuddy	buddy )
+					{
+						if ( !has_buddies ){
+							
+							has_buddies = true;
+						
+							updateStatus();
+						}
+					}
+					
+					public void
+					buddyRemoved(
+						BuddyPluginBuddy	buddy )
+					{
+						has_buddies	= plugin.getBuddies().size() > 0;	
+						
+						if ( !has_buddies ){
+							
+							updateStatus();
+						}
+					}
+
+					public void
+					buddyChanged(
+						BuddyPluginBuddy	buddy )
+					{
+					}
+					
+					public void
+					messageLogged(
+						String		str,
+						boolean		error )
+					{
+					}
+					
+					public void
+					enabledStateChanged(
+						boolean enabled )
+					{
+					}
+				});
+			
+			crypto = CryptoManagerFactory.getSingleton();
+			
+			crypto.addKeyListener(
+				new CryptoManagerKeyListener()
+				{
+					public void
+					keyChanged(
+						CryptoHandler		handler )
+					{
+					}
+					
+					public void
+					keyLockStatusChanged(
+						CryptoHandler		handler )
+					{
+						boolean	ok = crypto.getECCHandler().isUnlocked();
+						
+						if ( ok != crypto_ok ){
+							
+							crypto_ok = ok;
+							
+							updateStatus();
+						}
+					}
+				});
+			
+			crypto_ok = crypto.getECCHandler().isUnlocked();
+				
+			updateStatus();
+		}
+				
+		public void
+		networkStatusChanged(
+			BuddyPluginTracker	tracker,
+			int					new_status )
+		{
+			updateStatus();
+		}
+		
+		protected synchronized void
+		updateStatus()
+		{
+			if ( tracker.isEnabled() && has_buddies ){
+				
+				status.setVisible( true );
+				label.setVisible( true );
+				
+				if ( has_buddies && !crypto_ok ){
+					
+					status.setImage( iconNLI );
+					
+					status.setTooltipText( MessageText.getString( "azbuddy.tracker.bbb.status.nli" ));
+
+					disableUpdates();
+					
+				}else{
+					
+					int	network_status = tracker.getNetworkStatus();
+					
+					if ( network_status == BuddyPluginTracker.BUDDY_NETWORK_IDLE ){
+						
+						status.setImage( iconIDLE );
+						
+						status.setTooltipText( MessageText.getString( "azbuddy.tracker.bbb.status.idle" ));
+						
+						disableUpdates();
+						
+					}else if ( network_status == BuddyPluginTracker.BUDDY_NETWORK_INBOUND ){
+						
+						status.setImage( iconIN );
+						
+						enableUpdates();
+						
+					}else{
+						
+						status.setImage( iconOUT );
+						
+						enableUpdates();
+					}
+				}
+			}else{
+				
+				disableUpdates();
+				
+				status.setVisible( false );
+				label.setVisible( false );
+			}
+		}
+		
+		protected void
+		enableUpdates()
+		{
+			if ( update_event == null ){
+				
+				update_event = SimpleTimer.addPeriodicEvent(
+					"Buddy:GuiUpdater",
+					2500,
+					new TimerEventPerformer()
+					{
+						public void 
+						perform(
+							TimerEvent event ) 
+						{	
+							synchronized( statusUpdater.this ){
+								
+								if ( tracker.isEnabled() && ( crypto_ok || !has_buddies )){
+									
+									String	tt;
+															
+									int ns = tracker.getNetworkStatus();
+									
+									if ( ns == BuddyPluginTracker.BUDDY_NETWORK_IDLE ){
+										
+										tt = MessageText.getString( "azbuddy.tracker.bbb.status.idle" );
+									
+									}else if ( ns == BuddyPluginTracker.BUDDY_NETWORK_INBOUND ){
+										
+										tt = MessageText.getString( "azbuddy.tracker.bbb.status.in" ) + ": " + DisplayFormatters.formatByteCountToKiBEtcPerSec( tracker.getNetworkReceiveBytesPerSecond());
+										
+									}else{
+										
+										tt = MessageText.getString( "azbuddy.tracker.bbb.status.out" ) + ": " + DisplayFormatters.formatByteCountToKiBEtcPerSec( tracker.getNetworkSendBytesPerSecond());
+									}
+																			
+									status.setTooltipText( tt );
+								}
+							}
+						}					
+					});
+			}
+		}
+		
+		protected void
+		disableUpdates()
+		{
+			if ( update_event != null ){
+
+				update_event.cancel();
+				
+				update_event = null;
+			}
+		}
+		
+		public void 
+		enabledStateChanged(
+			BuddyPluginTracker 		tracker,
+			boolean 				enabled ) 
+		{
+			updateStatus();
+		}
+	}
+	
+	private boolean	beta_init_done;
+	
+	private static Object	CHAT_LM_KEY		= new Object();
+	
+	private HashMap<UISWTView,BetaSubViewHolder> beta_subviews = new HashMap<UISWTView,BetaSubViewHolder>();
+	
+	private Map<ChatInstance,Integer>	chat_uis = new HashMap<BuddyPluginBeta.ChatInstance, Integer>();
+	
+	private UISWTStatusEntry	beta_status;
+	private Image				bs_chat_gray;
+	private Image				bs_chat_gray_text;
+	private Image				bs_chat_green;
+		
+	private void
+	checkBetaInit()
+	{
+		if ( plugin.isBetaEnabled() && plugin.getBeta().isAvailable()){
+
+			synchronized( this ){
+				
+				if ( beta_init_done ){
+					
+					return;
+				}
+				
+				beta_init_done = true;
+			}
+			
+			MenuManager menu_manager = plugin.getPluginInterface().getUIManager().getMenuManager();
+				
+			MenuItem chat_item = menu_manager.addMenuItem( MenuManager.MENU_DOWNLOAD_CONTEXT, "label.chat" );
+
+			final MenuItem mi_chat =  
+				MenuBuildUtils.addChatMenu( 
+					menu_manager, 
+					chat_item,
+					new MenuBuildUtils.ChatKeyResolver() 
+					{
+						public String 
+						getChatKey(
+							Object object ) 
+						{
+							return( BuddyPluginUtils.getChatKey((Download)object ));
+						}
+					});
+						
+			addBetaSubviews( true );
+			
+			beta_status	= ui_instance.createStatusEntry();
+
+			beta_status.setImageEnabled( true );
+			
+			beta_status.setVisible( true );
+
+			updateIdleTT();
+			
+			Utils.execSWTThread(new AERunnable() {
+				public void runSupport() {
+					ImageLoader imageLoader = ImageLoader.getInstance();
+
+					bs_chat_gray		= imageLoader.getImage( "dchat_gray" );
+					bs_chat_gray_text 	= imageLoader.getImage( "dchat_gray_text" );
+					bs_chat_green 		= imageLoader.getImage( "dchat_green" );
+					
+					beta_status.setImage( bs_chat_gray );
+					
+					mi_chat.setGraphic( ui_instance.createGraphic( bs_chat_gray ));
+				}
+			});
+			
+			beta_status.setListener(
+				new UISWTStatusEntryListener() {
+					
+					public void 
+					entryClicked(
+						UISWTStatusEntry entry )
+					{
+						Set<ChatInstance> current_instances = menu_latest_instances;
+						
+						for ( ChatInstance chat: current_instances ){
+							
+							if ( chat.getMessageOutstanding()){
+
+								try{
+									openChat( chat.getClone());
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+							}
+						}
+					}
+				});
+			
+			SimpleTimer.addPeriodicEvent(
+				"msgcheck",
+				30*1000,
+				new TimerEventPerformer() 
+				{	
+					public void 
+					perform(
+						TimerEvent event) 
+					{
+						List<ChatInstance>	chats = plugin.getBeta().getChats();
+						
+						synchronized( pending_msg_map ){
+
+							for ( ChatInstance chat: chats ){
+							
+								if ( chat.isInvisible()){
+									
+									continue;
+								}
+								
+								if ( !chat_uis.containsKey( chat )){
+									
+									if ( 	chat.isFavourite() || 
+											chat.isAutoNotify() || 
+											chat.isInteresting()){
+										
+										if ( !chat.isStatistics()){
+											
+											ChatMessage last_msg = chat.getLastMessageRequiringAttention();
+											
+											if ( last_msg != null ){
+												
+												ChatMessage last_handled = (ChatMessage)chat.getUserData( CHAT_LM_KEY );
+												
+												long last_msg_time = last_msg.getTimeStamp();
+												
+												if ( 	last_handled == null ||
+														last_msg_time > last_handled.getTimeStamp()){
+													
+													chat.setUserData( CHAT_LM_KEY, last_msg );
+													
+													betaMessagePending( chat, null, last_msg );
+												}
+											}
+										}
+									}
+								}
+							}
+						
+							updateIdleTT();
+						}
+					}
+				});
+		}
+	}
+	
+	private void
+	addBetaSubviews(
+		boolean	enable )
+	{
+		String[] views = {
+			TableManager.TABLE_MYTORRENTS_ALL_BIG,
+			TableManager.TABLE_MYTORRENTS_INCOMPLETE,
+			TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG,
+			TableManager.TABLE_MYTORRENTS_COMPLETE,
+			"TagsView",
+		};
+		
+		if ( enable ){
+			
+			TagManagerFactory.getTagManager().addTaggableLifecycleListener(
+				Taggable.TT_DOWNLOAD,
+				new TaggableLifecycleAdapter()
+				{
+					public void
+					taggableTagged(
+						TagType			tag_type,	
+						Tag				tag,
+						Taggable		taggable )
+					{
+						if ( tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL ){
+							
+							DownloadManager dm  = (DownloadManager)taggable;
+							
+							for ( BetaSubViewHolder h: beta_subviews.values()){
+								
+								h.tagsUpdated( dm );
+							}
+						}
+					}
+					
+					public void
+					taggableUntagged(
+						TagType			tag_type,	
+						Tag				tag,
+						Taggable		taggable )
+					{
+						if ( tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL ){
+							
+							DownloadManager dm  = (DownloadManager)taggable;
+							
+							for ( BetaSubViewHolder h: beta_subviews.values()){
+								
+								h.tagsUpdated( dm );
+							}
+						}
+					}
+				});
+			
+			UISWTViewEventListener listener = 
+				new UISWTViewEventListener()
+				{	
+					public boolean 
+					eventOccurred(
+						UISWTViewEvent event ) 
+					{
+						UISWTView 	currentView = event.getView();
+						
+						switch (event.getType()) {
+							case UISWTViewEvent.TYPE_CREATE:{
+								
+								beta_subviews.put(currentView, new BetaSubViewHolder());
+								currentView.setDestroyOnDeactivate(false);
+								
+								break;
+							}
+							case UISWTViewEvent.TYPE_INITIALIZE:{
+							
+								BetaSubViewHolder subview = beta_subviews.get(currentView);
+								
+								if ( subview != null ){
+									
+									subview.initialise(event.getView(), (Composite)event.getData());
+								}
+		
+								break;
+							}
+							case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:{
+								
+								BetaSubViewHolder subview = beta_subviews.get(currentView);
+								
+								if ( subview != null ){
+									
+									subview.setDataSource( event.getData());
+								}
+								
+								break;
+							}
+							case UISWTViewEvent.TYPE_FOCUSGAINED:{
+								
+								BetaSubViewHolder subview = beta_subviews.get(currentView);
+								
+								if ( subview != null ){
+									
+									subview.gotFocus();
+								}
+								
+								break;
+							}
+							case UISWTViewEvent.TYPE_FOCUSLOST:{
+								
+								BetaSubViewHolder subview = beta_subviews.get(currentView);
+								
+								if ( subview != null ){
+									
+									subview.lostFocus();
+								}
+								
+								break;
+							}
+							case UISWTViewEvent.TYPE_DESTROY:{
+								
+								BetaSubViewHolder subview = beta_subviews.remove(currentView);
+							
+								if ( subview != null ){
+									
+									subview.destroy();
+								}
+								
+								break;
+							}
+						}
+						return true;
+					}
+				};
+				
+			for ( String table_id: views ){
+				
+				ui_instance.addView(table_id, "azbuddy.ui.menu.chat",	listener );
+			}
+		}else{
+			
+			for ( String table_id: views ){
+				
+				ui_instance.removeViews( table_id, "azbuddy.ui.menu.chat" );
+			}
+			
+			for ( UISWTView entry: new ArrayList<UISWTView>(beta_subviews.keySet())){
+				
+				entry.closeView();
+			}
+			
+			beta_subviews.clear();
+		}
+	}
+	
+	private static Map<String,Object[]>	pending_msg_map = new HashMap<String,Object[]>();
+	private static TimerEventPeriodic	pending_msg_event;
+
+	protected void
+	registerUI(
+		ChatInstance		chat )
+	{
+		synchronized( pending_msg_map ){
+		
+			Integer num = chat_uis.get( chat );
+		
+			if ( num == null ){
+			
+				num = 1;
+				
+			}else{
+				
+				num++;
+			}
+			
+			chat_uis.put( chat, num );
+			
+			if ( num == 1 ){
+				
+				updateIdleTT();
+			}
+		}
+	}
+	
+	protected void
+	unregisterUI(
+		ChatInstance		chat )
+	{
+		synchronized( pending_msg_map ){
+			
+			Integer num = chat_uis.get( chat );
+		
+			if ( num == null ){
+			
+				//eh
+				
+			}else{
+				
+				num--;
+			}
+			
+			if ( num == 0 ){
+				
+				chat_uis.remove( chat );
+			
+				updateIdleTT();
+				
+			}else{
+				
+				chat_uis.put( chat, num );
+			}
+		}
+	}
+		
+	private List<ChatInstance>
+	sortChats(
+		Collection<ChatInstance>	chats )
+	{
+		List<ChatInstance>	result = new ArrayList<ChatInstance>(chats);
+		
+		Collections.sort(
+			result,
+			new Comparator<ChatInstance>() 
+			{
+				public int 
+				compare(
+					ChatInstance o1, 
+					ChatInstance o2) 
+				{
+					int res = o1.getNetAndKey().compareTo( o2.getNetAndKey());
+					
+					return( res );
+				}	
+			});
+		
+		return( result );
+	}
+	
+	private void
+	updateIdleTT()
+	{
+		if ( pending_msg_map.size() == 0 ){
+		
+			
+			Set<ChatInstance>	instances = new HashSet<BuddyPluginBeta.ChatInstance>();
+			
+			if ( chat_uis.size() > 0 ){
+			
+				for ( ChatInstance chat: chat_uis.keySet()){
+				
+					instances.add( chat );
+				}
+			}
+			
+			List<ChatInstance>	chats = plugin.getBeta().getChats();
+			
+			for ( ChatInstance chat: chats ){
+				
+				if ( !chat_uis.containsKey( chat )){
+						
+					if ( chat.isFavourite() || chat.isPrivateChat()){
+						
+						instances.add( chat );					
+					}
+				}
+			}
+			
+			String text = MessageText.getString( "label.no.messages" );
+
+			for ( ChatInstance chat: sortChats( instances )){
+				
+				text += "\n  " + chat.getShortName();
+			}
+			
+			if ( beta_status != null ){
+			
+				beta_status.setTooltipText( text );
+			}
+			
+			buildMenu( instances );
+			
+			beta_status.setImage( bs_chat_gray );
+		}
+	}
+	
+	protected void
+	playSound()
+	{
+		if ( plugin.getBeta().getSoundEnabled()){
+			
+			final String sound_file = plugin.getBeta().getSoundFile();
+					
+			new AEThread2("BuddyPluginSound" ){
+				public void run() {
+					try {
+						AudioClip audio_clip = null;
+						
+						if ( sound_file.length() == 0 ){
+							
+							audio_clip = Applet.newAudioClip(BuddyPluginView.class.getClassLoader().getResource( default_sound ));
+
+						}else{
+							
+							URL	file_url = new File( sound_file ).toURI().toURL();
+
+	    					audio_clip = Applet.newAudioClip( file_url );
+						}
+						
+						audio_clip.play();
+	
+						Thread.sleep(2500);
+	
+					} catch (Throwable e) {
+	
+					}
+				}
+			}.start();
+		}
+	}
+	
+	protected void
+	betaMessagePending(
+		ChatInstance		chat,
+		Control				comp_maybe_null,
+		ChatMessage			pending_message )
+	{
+		synchronized( pending_msg_map ){
+			
+			String key = chat.getNetAndKey();
+			
+			Object[] entry = pending_msg_map.get( key );
+			
+			if ( pending_message != null ){
+			
+				if ( chat.isOldOutstandingMessage( pending_message )){
+					
+					return;
+				}
+				
+				chat.setMessageOutstanding( true );
+				
+				if ( entry == null ){
+					
+					entry = new Object[]{ 1, new HashSet<Control>(), chat };
+					
+					pending_msg_map.put( key, entry );
+					
+				}else{
+					
+					entry[0] = ((Integer)entry[0]) + 1;
+				}
+				
+				HashSet<Control> controls = (HashSet<Control>)entry[1];
+				
+				if ( controls.contains( comp_maybe_null )){
+					
+					return;
+				}
+				
+				controls.add( comp_maybe_null );
+				
+				if ( pending_msg_event == null ){
+					
+					pending_msg_event = 
+						SimpleTimer.addPeriodicEvent(
+							"BPPM",
+							2500,
+							new TimerEventPerformer()
+							{	
+								private int	tick_count = 0;
+									
+								private Set<ChatInstance>	prev_instances = new HashSet<ChatInstance>();
+								
+								public void 
+								perform(
+									TimerEvent event )
+								{
+									tick_count++;
+									
+									synchronized( pending_msg_map ){
+										
+										Set<ChatInstance>			current_instances 	= new HashSet<ChatInstance>();
+										Map<ChatInstance,Object>	instance_map 		= new HashMap<ChatInstance, Object>();
+										
+										Iterator<Map.Entry<String,Object[]>> it = pending_msg_map.entrySet().iterator();
+											
+										boolean	has_new = false;
+										
+										while( it.hasNext()){
+											
+											Map.Entry<String,Object[]> map_entry = it.next();
+											
+											Object[] entry = map_entry.getValue();
+											
+											ChatInstance chat = (ChatInstance)entry[2];
+											
+											if ( chat.isDestroyed()){
+												
+												it.remove();
+												
+											}else{
+											
+												HashSet<Control> comps = ((HashSet<Control>)entry[1]);
+												
+												Iterator<Control>	control_it = comps.iterator();
+												
+												while( control_it.hasNext()){
+													
+													Control c = control_it.next();
+													
+													if ( c != null && c.isDisposed()){
+														
+														it.remove();
+													}
+												}
+												
+												if ( comps.size() == 0 ){
+													
+													it.remove();
+													
+												}else{
+												
+													current_instances.add( chat );
+													
+													if ( !prev_instances.contains( chat )){
+														
+														has_new = true;
+													}
+													
+													instance_map.put( chat, entry[0] );
+												}
+											}
+										}
+										
+										
+										if ( pending_msg_map.size() == 0 ){
+											
+											pending_msg_event.cancel();
+											
+											pending_msg_event = null;
+										}
+										
+										if ( current_instances.size() == 0 ){
+											
+											updateIdleTT();
+											
+											beta_status.setImage( bs_chat_gray );
+											
+										}else{
+											
+											String tt_text = "";
+
+											for ( ChatInstance chat: sortChats( current_instances )){
+												
+												String short_name = chat.getShortName();
+
+												tt_text += (tt_text.length()==0?"":"\n") + instance_map.get( chat ) + " - " + short_name;
+											}
+											
+											buildMenu( current_instances );														
+											
+											if ( has_new ){
+												
+												playSound();
+											}
+											
+											beta_status.setTooltipText( tt_text );
+										
+											beta_status.setImage( tick_count%2==0?bs_chat_gray_text:bs_chat_green);
+										}
+										
+										prev_instances = current_instances;
+									}
+								}
+							});
+				}
+			}else{
+
+				chat.setUserData( CHAT_LM_KEY, chat.getLastMessageRequiringAttention());
+
+				chat.setMessageOutstanding( false );
+				
+				if ( entry != null ){
+					
+					pending_msg_map.remove( key );
+					
+					if ( pending_msg_event == null ){
+						
+						Debug.out( "eh?" );
+					}
+				}
+			}
+		}
+	}
+	
+	private List<MenuItem>		menu_items = new ArrayList<MenuItem>();
+	private Set<ChatInstance>	menu_latest_instances = new HashSet<ChatInstance>();
+
+	private void
+	buildMenu(
+		final Set<ChatInstance>	current_instances )
+	{
+		if ( menu_items.size() == 0 || !menu_latest_instances.equals( current_instances )){
+
+			for ( MenuItem mi: menu_items ){
+				
+				mi.remove();
+			}
+			
+			menu_items.clear();
+			
+			final MenuManager menu_manager = plugin.getPluginInterface().getUIManager().getMenuManager();
+	
+			MenuContext mc = beta_status.getMenuContext();
+								
+			for ( final ChatInstance chat: sortChats( current_instances )){
+			
+				String	short_name = chat.getShortName();
+																	
+				MenuItem mi = menu_manager.addMenuItem( mc, "!" + short_name + "!" );
+				
+				mi.addListener(
+					new MenuItemListener() {
+						
+						public void selected(MenuItem menu, Object target) {
+						
+							try{
+								openChat( chat.getClone());
+								
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}
+					});
+				
+				menu_items.add( mi );
+			}
+			
+			boolean	need_sep = true;
+			
+				// open all
+			
+			if ( current_instances.size() > 1 ){
+				
+				MenuItem mi = menu_manager.addMenuItem( mc, "sep1" );
+				
+				need_sep = false;
+				
+				mi.setStyle( MenuItem.STYLE_SEPARATOR );
+				
+				menu_items.add( mi );
+				
+				mi = menu_manager.addMenuItem( mc, "label.open.all" );
+				
+				mi.addListener(
+					new MenuItemListener() {
+						
+						public void selected(MenuItem menu, Object target) {
+						
+							for ( ChatInstance chat: current_instances ){
+								
+								try{
+									openChat( chat.getClone());
+									
+								}catch( Throwable e ){
+										
+									Debug.out( e );
+								}
+							}
+						}
+					});
+				
+				menu_items.add( mi );
+			}
+			
+			if ( need_sep ){
+				
+				MenuItem mi = menu_manager.addMenuItem( mc, "sep2" );
+				
+				mi.setStyle( MenuItem.STYLE_SEPARATOR );
+				
+				menu_items.add( mi );
+			}
+			
+				// create channel
+			
+			MenuItem mi = menu_manager.addMenuItem( mc, "chat.view.create.chat" );
+	
+			mi.setStyle( MenuItem.STYLE_MENU );
+			
+			menu_items.add( mi );
+			
+			mi.addFillListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener() {
+				public void menuWillBeShown(MenuItem menu, Object data){
+					
+					menu.removeAllChildItems();
+					
+					MenuItem mi = menu_manager.addMenuItem( menu, "!" + MessageText.getString( "label.public" ) + "...!" );
+					
+					mi.addListener(
+						new MenuItemListener()
+						{
+							public void
+							selected(
+								MenuItem			menu,
+								Object 				target )
+							{
+								SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+										"chat.view.enter.key.title", "chat.view.enter.key.msg");
+								
+								entryWindow.prompt();
+								
+								if ( entryWindow.hasSubmittedInput()){
+									
+									String key = entryWindow.getSubmittedInput().trim();
+									
+									BuddyPluginUtils.createBetaChat( AENetworkClassifier.AT_PUBLIC, key, null ); 
+								}
+							}
+						});
+					
+					mi = menu_manager.addMenuItem( menu, "!" + MessageText.getString( "label.anon" ) + "...!" );
+					
+					mi.addListener(
+							new MenuItemListener()
+							{
+								public void
+								selected(
+									MenuItem			menu,
+									Object 				target )
+								{
+									if ( plugin.getBeta().isI2PAvailable()){
+										
+										SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+												"chat.view.enter.key.title", "chat.view.enter.key.msg");
+										
+										entryWindow.prompt();
+										
+										if ( entryWindow.hasSubmittedInput()){
+											
+											String key = entryWindow.getSubmittedInput().trim();
+											
+											BuddyPluginUtils.createBetaChat( AENetworkClassifier.AT_I2P, key, null ); 
+										}
+									}else{
+										
+										I2PHelpers.installI2PHelper( null, null, null );
+									}
+									
+								}
+							});
+	
+					if ( I2PHelpers.isInstallingI2PHelper()){
+						
+						mi.setEnabled( false );
+						mi.setText(  mi.getText() + " (" + MessageText.getString( "PeersView.state.pending" ) + ")" );
+					}
+				}});
+	
+					
+				// chat overview
+			
+			mi = menu_manager.addMenuItem( mc, "!" + MessageText.getString( "chats.view.heading" ) + "...!" );
+
+			mi.addListener(
+				new MenuItemListener()
+				{
+					public void
+					selected(
+						MenuItem			menu,
+						Object 				target )
+					{
+						UIFunctions uif = UIFunctionsManager.getUIFunctions();
+
+						if ( uif != null ){
+
+							uif.getMDI().showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_CHAT);
+						}
+					}
+				});
+			
+			menu_items.add( mi );
+			
+			mi = menu_manager.addMenuItem( mc, "sep3" );
+			
+			mi.setStyle( MenuItem.STYLE_SEPARATOR );
+			
+			menu_items.add( mi );
+
+				// options
+			
+			mi = menu_manager.addMenuItem( mc, "MainWindow.menu.view.configuration" );
+
+			mi.addListener(
+				new MenuItemListener()
+				{
+					public void
+					selected(
+						MenuItem			menu,
+						Object 				target )
+					{
+						ui_instance.openView( UISWTInstance.VIEW_MAIN, VIEW_ID, null );
+					}
+				});
+			
+			menu_items.add( mi );
+			
+
+			menu_latest_instances = current_instances;
+		}
+	}
+	
+	private static AsyncDispatcher	public_dispatcher 	= new AsyncDispatcher();
+	private static AsyncDispatcher	anon_dispatcher 	= new AsyncDispatcher();
+	
+	private static AtomicInteger	public_done = new AtomicInteger();
+	private static AtomicInteger	anon_done 	= new AtomicInteger();
+	
+	
+	private static final Object	adapter_key = new Object();
+	
+	public DownloadAdapter
+	getDownloadAdapter(
+		final Download			download )
+	{
+		synchronized( adapter_key ){
+			
+			DownloadAdapter adapter = (DownloadAdapter)download.getUserData( adapter_key );
+			
+			if ( adapter == null ){
+				
+				adapter = 
+					new DownloadAdapter()
+					{
+						public DownloadManager
+						getCoreDownload()
+						{
+							return( PluginCoreUtils.unwrap( download ));
+						}
+						
+						public String[] 
+						getNetworks() 
+						{
+							DownloadManager dm = getCoreDownload();
+							
+							if ( dm == null ){
+								
+								return( new String[0]);
+								
+							}else{
+							
+								return( dm.getDownloadState().getNetworks());
+							}
+						}
+						
+						public String
+						getChatKey()
+						{
+							return( BuddyPluginUtils.getChatKey( download ));
+						}
+					};
+				
+				download.setUserData( adapter_key,adapter );
+			}
+			
+			return( adapter );
+		}
+	}
+	
+	public View
+	buildView(
+		Map<String,Object>		properties,
+		ViewListener			listener )
+	{
+		BetaSubViewHolder view = new BetaSubViewHolder();
+		
+		Composite	swt_composite = (Composite)properties.get( BuddyPluginViewInterface.VP_SWT_COMPOSITE );
+		
+		DownloadAdapter	download = (DownloadAdapter)properties.get( BuddyPluginViewInterface.VP_DOWNLOAD );
+		
+		view.initialise( swt_composite, download, listener );
+		
+		return( view );
+	}
+	
+	private class
+	BetaSubViewHolder
+		implements View
+	{
+		private int CHAT_DOWNLOAD 		= 0;
+		private int CHAT_TRACKERS 		= 1;
+		private int CHAT_TAG	 		= 2;
+		private int CHAT_GENERAL		= 3;
+		private int CHAT_FAVOURITES		= 4;
+		
+		private boolean			download_only_mode;
+		
+		private ViewListener	view_listener;
+		
+		private Composite[]		chat_composites;
+		
+		private List<Button>	mode_buttons = new ArrayList<Button>();
+		
+		private Group			middle;
+		
+		private	CTabFolder  	tab_folder;
+		private CTabItem 		public_item;
+		private CTabItem 		anon_item;
+		
+		private int				last_build_chat_mode	= -1;
+		private int				chat_mode				= CHAT_DOWNLOAD;
+		
+		private DownloadAdapter		current_download;
+		private String				current_tracker;
+		private Tag					current_tag;
+		private String				current_general;
+		
+		private String			current_favourite_net;
+		private String			current_favourite_key;
+		
+		private Tag				current_ds_tag;
+
+		private boolean			have_focus;
+		private boolean			rebuild_outstanding	= true;
+		private Group lhs;
+		
+		private
+		BetaSubViewHolder()
+		{
+			checkBetaInit();
+		}
+		
+		private void
+		initialise(
+			Composite			parent,
+			DownloadAdapter		download,
+			ViewListener		listener )
+		{
+			view_listener 		= listener;
+			current_download	= download;
+			download_only_mode	= true;
+			
+			initialiseSupport( parent );
+			
+			String[] nets = current_download.getNetworks();
+			
+			if ( nets.length > 0 ){
+				
+				String	net_to_activate = nets[0];
+				
+				for ( String net: nets ){
+					
+					if ( net == AENetworkClassifier.AT_PUBLIC ){
+						
+						net_to_activate = net;
+						
+						break;
+					}
+				}
+				
+				activateNetwork( net_to_activate, true );
+			}
+		}
+		
+		private void
+		initialise(
+			UISWTView		view,
+			Composite		parent )
+		{		
+			UISWTView parent_view = view.getParentView();
+			
+			if ( parent_view != null ){
+			
+				Object initial_ds = parent_view.getInitialDataSource();
+			
+				if ( initial_ds instanceof Tag ){
+					
+					current_ds_tag = (Tag)initial_ds;
+				}
+			}
+			
+			initialiseSupport( parent );
+		}
+		
+		private void
+		initialiseSupport(
+			Composite		parent )
+		{
+			final Composite composite	= parent;
+			
+			GridLayout layout = new GridLayout();
+			layout.numColumns = download_only_mode?1:3;
+			layout.marginHeight = 0;
+			layout.marginWidth = 0;
+			layout.marginTop = 4;
+			layout.marginRight = 4;
+			composite.setLayout(layout);
+			
+			GridData grid_data = new GridData(GridData.FILL_BOTH );
+			composite.setLayoutData(grid_data);
+
+			if ( !download_only_mode ){
+				
+				// left
+			
+				lhs = new Group( composite, SWT.NULL );
+				lhs.setText( MessageText.getString( "label.chat.type" ));
+				layout = new GridLayout();
+				layout.numColumns = 1;
+				layout.horizontalSpacing = 1;
+				layout.verticalSpacing = 1;
+				lhs.setLayout(layout);
+				grid_data = new GridData(GridData.FILL_VERTICAL );
+				//grid_data.widthHint = 200;
+				lhs.setLayoutData(grid_data);
+				
+				Button downloads = new Button( lhs, SWT.TOGGLE );		
+				downloads.setText( MessageText.getString( "v3.MainWindow.button.download" ));
+				downloads.setData( CHAT_DOWNLOAD );
+				
+				Button trackers = new Button( lhs, SWT.TOGGLE );		
+				trackers.setText( MessageText.getString( "label.trackers" ));
+				trackers.setData( CHAT_TRACKERS );
+				
+				Button tags = new Button( lhs, SWT.TOGGLE );			
+				tags.setText( MessageText.getString( "label.tags" ));
+				tags.setData( CHAT_TAG );
+				
+				Button general = new Button( lhs, SWT.TOGGLE );			
+				general.setText( MessageText.getString( "ConfigView.section.global" ));
+				general.setData( CHAT_GENERAL );
+				
+				Button favourites = new Button( lhs, SWT.TOGGLE );
+				favourites.setText( MessageText.getString( "label.favorites" ));
+				favourites.setData( CHAT_FAVOURITES );
+				
+				if ( download_only_mode ){
+					
+					lhs.setVisible( false );
+				}
+				
+					// middle
+				
+				middle = new Group( composite, SWT.NULL );
+				layout = new GridLayout();
+				layout.numColumns = 1;
+				middle.setLayout(layout);
+				grid_data = new GridData(GridData.FILL_VERTICAL );
+				grid_data.widthHint = 0;
+				middle.setLayoutData(grid_data);
+	
+				middle.setText( "" );
+				
+				middle.setVisible( false );
+			
+				downloads.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						buildChatMode( CHAT_DOWNLOAD, true );
+					}});
+				
+				trackers.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						buildChatMode( CHAT_TRACKERS, true );
+					}});
+
+				tags.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						buildChatMode( CHAT_TAG, true );
+					}});	
+				
+				general.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {			
+						buildChatMode( CHAT_GENERAL, true );
+					}});
+				
+				favourites.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						buildChatMode( CHAT_FAVOURITES, true );
+					}});
+				
+				downloads.setSelection( true );
+				
+				mode_buttons.add( downloads );
+				mode_buttons.add( trackers );
+				mode_buttons.add( tags );
+				mode_buttons.add( general );
+				mode_buttons.add( favourites );
+				
+				setupButtonGroup( mode_buttons );
+			}
+			
+				// chat tab area
+			
+			tab_folder = new CTabFolder(composite, SWT.LEFT);
+			
+			tab_folder.setTabHeight(20);
+			grid_data = new GridData(GridData.FILL_BOTH);
+			tab_folder.setLayoutData(grid_data);
+			
+				// public
+			
+			public_item = new CTabItem(tab_folder, SWT.NULL);
+
+			public_item.setText( MessageText.getString( "label.public.chat" ));
+			public_item.setData( AENetworkClassifier.AT_PUBLIC );
+			
+			Composite public_composite = new Composite( tab_folder, SWT.NULL );
+	
+			public_item.setControl( public_composite );
+			
+			grid_data = new GridData(GridData.FILL_BOTH );
+			public_composite.setLayoutData(grid_data);
+			public_composite.setData( "tabitem", public_item );
+			
+				// anon
+
+			Composite anon_composite = null;
+											
+			{
+				anon_item = new CTabItem(tab_folder, SWT.NULL);
+	
+				anon_item.setText( MessageText.getString( "label.anon.chat" ));
+				anon_item.setData( AENetworkClassifier.AT_I2P );
+				
+				anon_composite = new Composite( tab_folder, SWT.NULL );
+		
+				anon_item.setControl( anon_composite );
+				
+				grid_data = new GridData(GridData.FILL_BOTH );
+				anon_composite.setLayoutData(grid_data);
+				anon_composite.setData( "tabitem", anon_item );
+			}
+			
+			chat_composites = new Composite[]{ public_composite, anon_composite };
+				
+			tab_folder.addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					CTabItem item = (CTabItem) e.item;
+					
+					String network = (String)item.getData();
+											
+					activateNetwork( network );
+				}
+			});
+		}
+		
+		private void
+		tagsUpdated(
+			DownloadManager	dm )
+		{
+			DownloadAdapter download = current_download;
+			
+			if ( download == null ){
+				
+				return;
+			}
+			
+			if ( chat_mode == CHAT_TAG ){
+			
+				if ( dm == download.getCoreDownload()){
+				
+					Utils.execSWTThread(
+						new Runnable() 
+						{	
+							public void 
+							run() 
+							{
+								rebuild_outstanding = true;
+								
+								activate();
+							}
+						});
+				}
+			}
+		}
+		
+		private void
+		setupButtonGroup(
+			final List<Button>		buttons )
+		{
+			for ( final Button b: buttons ){
+
+				b.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						if ( !b.getSelection()){
+							
+							b.setSelection( true );
+						}
+						for ( Button b2: buttons ){
+							
+							if ( b2 != b ){
+								b2.setSelection( false );
+							}
+						}
+					}});
+			}
+			
+			Utils.makeButtonsEqualWidth( buttons );
+		}
+		
+		private void
+		selectButtonGroup(
+			List<Button>		buttons,
+			int					data )
+		{
+			for ( Button b: buttons ){
+				
+				b.setSelection( (Integer)b.getData() == data );
+			}
+		}
+		
+		private void
+		selectButtonGroup(
+			List<Button>		buttons,
+			String				data )
+		{
+			for ( Button b: buttons ){
+				
+				String str = (String)b.getData();
+				
+				b.setSelection( str != null && str.endsWith( data ));
+			}
+		}
+		
+		private void
+		setChatMode(
+			int		mode )
+		{
+			if ( chat_mode == mode ){
+				
+				return;
+			}
+			
+			chat_mode = mode;
+			
+			selectButtonGroup( mode_buttons, mode );
+		}
+		
+		private void
+		buildChatMode(
+			int				mode,
+			boolean			activate )		
+		{
+			DownloadAdapter	download = current_download;
+			
+			chat_mode = mode;
+			
+			if ( mode == CHAT_GENERAL && last_build_chat_mode == mode ){
+				
+					// doesn't change so no rebuild required
+			}else{
+				
+				if ( !download_only_mode ){
+					
+					for ( Control c: middle.getChildren()){
+						
+						c.dispose();
+					}
+					
+					if ( mode == CHAT_DOWNLOAD ||(( mode == CHAT_TRACKERS || mode == CHAT_TAG ) &&  download == null && current_ds_tag == null )){
+						
+						middle.setVisible( false );
+						middle.setText( "" );
+						
+						GridData grid_data = new GridData(GridData.FILL_VERTICAL );
+						grid_data.widthHint = 0;
+						middle.setLayoutData(grid_data);
+						
+					}else if ( mode == CHAT_TRACKERS ){
+						
+						middle.setVisible( true );				
+						middle.setText( MessageText.getString( "label.tracker.selection" ));
+						
+						Set<String> trackers = new HashSet<String>();
+						
+						if ( current_download != null ){
+							
+							DownloadManager core_dm = current_download.getCoreDownload();
+							
+							if ( core_dm != null ){
+								
+								trackers = TorrentUtils.getUniqueTrackerHosts( core_dm.getTorrent());
+							}
+						}
+									
+						GridLayout layout = new GridLayout();
+						layout.horizontalSpacing = 1;
+						layout.verticalSpacing = 1;
+						
+						layout.numColumns = 1;
+						middle.setLayout(layout);
+						GridData grid_data = new GridData(GridData.FILL_VERTICAL );
+						middle.setLayoutData(grid_data);
+						
+						Set<String>	reduced_trackers = new HashSet<String>();
+						
+						for ( String tracker: trackers ){
+							
+							String[] bits = tracker.split( "\\." );
+							
+							int	num_bits = bits.length;
+							
+							if ( bits[num_bits-1].equals( "dht" )){
+								
+								continue;
+							}
+							
+							if ( bits.length > 2 ){
+								
+								tracker = bits[num_bits-2] + "." +  bits[num_bits-1];
+							}
+							
+							reduced_trackers.add( tracker );
+						}
+						
+						int	num_trackers = reduced_trackers.size();
+						
+						if ( num_trackers == 0 ){
+							
+							current_tracker = null;
+							Label label = new Label( middle, SWT.NULL );
+							label.setText( MessageText.getString( "label.none.assigned" ));
+							label.setEnabled( false );
+	
+						}else{
+								
+							Composite	tracker_area;
+							
+							if ( num_trackers > 4 ){
+								
+								tracker_area = createScrolledComposite( middle );
+								
+							}else{
+								
+								tracker_area = middle;
+							}
+
+							List<String>sorted_trackers = new ArrayList<String>( reduced_trackers );
+							
+							Collections.sort( sorted_trackers );
+							
+							if ( !sorted_trackers.contains( current_tracker )){
+								
+								current_tracker = sorted_trackers.get(0);
+							}
+								
+							final List<Button>	buttons = new ArrayList<Button>();
+		
+							for ( final String tracker: sorted_trackers ){
+								
+								Button button = new Button( tracker_area, SWT.TOGGLE );
+								
+								button.setText( tracker );
+								button.setData( tracker );
+								
+								button.addSelectionListener(new SelectionAdapter() {
+									public void widgetSelected(SelectionEvent e) {
+										current_tracker = tracker;
+										activate();
+									}});
+								buttons.add( button );
+							}
+														
+							setupButtonGroup( buttons );
+							
+							selectButtonGroup( buttons, current_tracker );
+						}
+					}else if ( mode == CHAT_TAG ){
+							
+						lhs.setVisible(download != null);
+						GridData grid_data = new GridData(GridData.FILL_VERTICAL );
+						if (download == null) {
+							grid_data.exclude = true;
+						}
+						lhs.setLayoutData(grid_data);
+							
+
+						middle.setVisible( true );				
+						middle.setText( MessageText.getString( "label.tag.selection" ));
+						
+						List<Tag> tags;
+						
+						if ( current_download == null ){
+							
+							tags = new ArrayList<Tag>();
+							
+						}else{
+							
+							DownloadManager core_dm = current_download.getCoreDownload();
+							
+							if ( core_dm == null ){
+								
+								tags = new ArrayList<Tag>();
+								
+							}else{
+							
+								tags = TagManagerFactory.getTagManager().getTagsForTaggable( TagType.TT_DOWNLOAD_MANUAL, core_dm );
+							}
+						}
+						
+						if ( current_ds_tag != null && !tags.contains( current_ds_tag )){
+							
+							tags.add( current_ds_tag );
+						}
+						
+						GridLayout layout = new GridLayout();
+						layout.horizontalSpacing = 1;
+						layout.verticalSpacing = 1;
+						
+						layout.numColumns = 1;
+						middle.setLayout(layout);
+						grid_data = new GridData(GridData.FILL_VERTICAL );
+						middle.setLayoutData(grid_data);
+	
+						int	num_tags = tags.size();
+						
+						if ( num_tags == 0 ){
+							
+							current_tag = null;
+							Label label = new Label( middle, SWT.NULL );
+							label.setText( MessageText.getString( "label.none.assigned" ));
+							label.setEnabled( false );
+	
+						}else{
+							
+							Composite	tag_area;
+							
+							if ( num_tags > 4 ){
+								
+								tag_area = createScrolledComposite( middle );
+								
+							}else{
+								
+								tag_area = middle;
+							}
+							
+							tags = TagUIUtils.sortTags( tags );
+							
+							if ( !tags.contains( current_tag )){
+							
+								current_tag = tags.get(0);
+							}
+							
+							final List<Button>	buttons = new ArrayList<Button>();
+		
+							for ( final Tag tag: tags ){
+								
+								Button button = new Button( tag_area, SWT.TOGGLE );
+								
+								String tag_name = tag.getTagName( true );
+								
+								button.setText( tag_name );
+								button.setData( tag_name );
+								
+								button.addSelectionListener(new SelectionAdapter() {
+									public void widgetSelected(SelectionEvent e) {
+										current_tag = tag;
+										activate();
+									}});
+								buttons.add( button );
+							}
+														
+							setupButtonGroup( buttons );
+							
+							selectButtonGroup( buttons, current_tag.getTagName( true ));
+						}
+					}else if ( mode == CHAT_GENERAL ){
+						
+						middle.setVisible( true );				
+						middle.setText( MessageText.getString( "azbuddy.dchat.general.chats" ));
+		
+						GridLayout layout = new GridLayout();
+						layout.horizontalSpacing = 1;
+						layout.verticalSpacing = 1;
+						
+						layout.numColumns = 1;
+						middle.setLayout(layout);
+						GridData grid_data = new GridData(GridData.FILL_VERTICAL );
+						middle.setLayoutData(grid_data);
+						
+						final List<Button>	buttons = new ArrayList<Button>();
+							
+						String[][] general_data = {
+								{ "label.help", 		"General: Help" },
+								{ "label.announce", 	"General: Announce" },
+								{ "label.beta",			BuddyPluginBeta.BETA_CHAT_KEY },
+						};
+						
+						for ( String[] entry: general_data ){
+												
+							final	String key = entry[1];
+							
+							if ( key == BuddyPluginBeta.BETA_CHAT_KEY && !Constants.isCVSVersion()){
+								
+								continue;
+							}
+							
+							Button button = new Button( middle, SWT.TOGGLE );
+								
+							button.setText( MessageText.getString( entry[0] ) );
+							button.setData( key );
+							
+							button.addSelectionListener(new SelectionAdapter() {
+								public void widgetSelected(SelectionEvent e) {
+									current_general = key;;
+									activate();
+								}});
+							
+							buttons.add( button );
+						}
+						
+						setupButtonGroup( buttons );
+						
+						if ( current_general != null ){
+							
+							selectButtonGroup( buttons, current_general );
+						}
+					}else{
+						
+						middle.setVisible( true );				
+						middle.setText( MessageText.getString( "azbuddy.dchat.fave.chats" ));
+																		
+						GridLayout layout = new GridLayout();
+						layout.horizontalSpacing 	= 1;
+						layout.verticalSpacing 		= 1;
+						
+						layout.numColumns = 1;
+						middle.setLayout(layout);
+						GridData grid_data = new GridData(GridData.FILL_VERTICAL );
+						middle.setLayoutData(grid_data);
+	
+						List<String[]>	list = plugin.getBeta().getFavourites();
+						
+						int	num_faves = list.size();
+
+						if ( num_faves == 0 ){
+							
+							Label label = new Label( middle, SWT.NULL );
+							label.setText( MessageText.getString( "label.none.assigned" ));
+							label.setEnabled( false );
+												
+						}else{
+							
+							Composite	fave_area;
+							
+							if ( num_faves > 4 ){
+								
+								fave_area = createScrolledComposite( middle );
+								
+							}else{
+								
+								fave_area = middle;
+							}
+							
+							final List<Button>	buttons = new ArrayList<Button>();
+							
+							Collections.sort(
+								list,
+								new Comparator<String[]>()
+								{
+									Comparator<String> c = new FormattersImpl().getAlphanumericComparator( true );
+									
+									public int compare(String[] o1, String[] o2) {
+										
+										int result = o1[0].compareTo( o2[0] );
+							
+										if ( result == 0 ){
+											
+											result = c.compare( o1[1], o2[1] );
+										}
+										
+										return( result );
+									}
+								});
+							
+							for ( String[] entry: list ){
+								
+								final	String net = entry[0];
+								final	String key = entry[1];
+								
+								Button button = new Button( fave_area, SWT.TOGGLE );
+								
+								String	short_name = "(" + MessageText.getString( net==AENetworkClassifier.AT_PUBLIC?"label.public.short":"label.anon.short" ) + ")";
+								
+								short_name += " " + key;
+								
+								if ( short_name.length() > 30 ){
+									
+									short_name = short_name.substring( 0, 30 ) + "...";
+								}
+								
+								String	long_name = "(" + MessageText.getString( net==AENetworkClassifier.AT_PUBLIC?"label.public":"label.anon" ) + ")";
+								
+								long_name += " " + key;
+		
+								button.setText( short_name );
+								button.setAlignment( SWT.LEFT );
+								button.setToolTipText( long_name );
+								
+								button.setData( net + ":" + key );
+								
+								button.addSelectionListener(new SelectionAdapter() {
+									public void widgetSelected(SelectionEvent e) {
+										current_favourite_net = net;
+										current_favourite_key = key;
+										activate();
+									}});
+								
+								buttons.add( button );
+							}
+							
+							setupButtonGroup( buttons );
+							
+							if ( current_favourite_key != null ){
+								
+								selectButtonGroup( buttons, current_favourite_net + ":" + current_favourite_key );
+							}
+						}
+					}
+					
+					middle.getParent().layout( true, true );
+				}
+				
+				last_build_chat_mode	= mode;
+			}
+		
+			if ( activate ){
+				
+				activate();
+			}
+		}
+		
+		private Composite
+		createScrolledComposite(
+			final Composite		parent )
+		{
+			final ScrolledComposite scrollable = 
+				new ScrolledComposite(parent, SWT.V_SCROLL)
+				{
+						// this code required to show/hide scroll bar when visible or not
+				
+				    private final Point 	bar_size;  
+				    private int				x_adjust;
+				    private boolean			first_time	= true;
+				    private boolean			hacking;
+				    
+				    {
+				        Composite composite = new Composite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
+				        
+				        composite.setSize(1, 1);
+				        
+				        bar_size = composite.computeSize(0, 0);
+				        
+				        composite.dispose();
+				    }
+
+				    public Point 
+				    computeSize(
+				    	int 		wHint, 
+				    	int 		hHint, 
+				    	boolean 	changed )
+				    {
+				        Point point = super.computeSize(wHint, hHint, changed);
+				       
+				        if ( !hacking ){
+				        	
+					        final boolean was_visible = getVerticalBar().isVisible();
+					        
+					        Utils.execSWTThreadLater(
+					        	0,
+					        	new Runnable()
+					        	{
+					        		public void 
+					        		run()
+					        		{
+					        			if ( isDisposed()){
+					        				
+					        				return;
+					        			}
+					        			
+					        			boolean is_visible = getVerticalBar().isVisible();
+
+					        			if ( first_time || was_visible != is_visible ){
+
+					        				x_adjust = is_visible?0:-bar_size.x;
+
+					        				try{
+					        					hacking = true;
+
+					        					parent.getParent().layout( true, true );
+
+					        				}finally{
+
+					        					hacking = false;
+					        				}
+					        			}
+					        		};	
+					        	});
+				        }
+				        
+				        point.x += x_adjust;
+				        
+				        return point;
+				    }
+				};
+			
+			scrollable.setLayoutData( new GridData(GridData.FILL_VERTICAL ));
+
+			final Composite scrollChild = new Composite( scrollable, SWT.NONE );
+
+			GridLayout gLayoutChild = new GridLayout();
+			gLayoutChild.numColumns = 1;
+			
+			gLayoutChild.horizontalSpacing 	= 1;
+			gLayoutChild.verticalSpacing 	= 1;
+			gLayoutChild.marginWidth 		= 0;
+			gLayoutChild.marginHeight		= 0;
+			scrollChild.setLayout(gLayoutChild);
+			scrollChild.setLayoutData( new GridData(GridData.FILL_VERTICAL ));
+
+			scrollable.setContent(scrollChild);
+			scrollable.setExpandVertical(true);
+			scrollable.setExpandHorizontal(true);	
+			scrollable.setAlwaysShowScrollBars( false );
+			
+			scrollable.setMinSize(scrollChild.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+			
+			scrollable.addControlListener(new ControlAdapter() {
+				public void controlResized(ControlEvent e) {
+					Rectangle r = scrollable.getClientArea();
+					scrollable.setMinSize(scrollChild.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+				}
+			});
+			
+			return( scrollChild );
+		}
+		
+		private void
+		activate()
+		{
+			if ( rebuild_outstanding ){
+				
+				rebuild_outstanding = false;
+				
+				if ( current_download == null ){
+					
+						setChatMode( current_ds_tag==null?CHAT_GENERAL:CHAT_TAG );
+				}
+				
+				buildChatMode( chat_mode, false );
+			}
+			
+			activateNetwork( null );
+		}
+		
+		private void
+		activateNetwork(
+			String		network  )
+		{
+			if ( network != null ){
+				
+					// explicit network is only set when we're switching public/anon tabs so
+					// we use it directly and don't need to reselect the tab coz we're on it
+				
+				activateNetwork( network, false );
+				
+			}else{
+					// network == null -> select most appropriate one
+				
+				if ( chat_mode == CHAT_FAVOURITES && current_favourite_net != null ){
+					
+					activateNetwork( current_favourite_net, true );
+	
+				}else{
+					
+					DownloadAdapter	download 	= current_download;
+					
+					if ( download == null ){
+						
+							// no current download to guide us, default to public
+						
+						activateNetwork( AENetworkClassifier.AT_PUBLIC, true );
+						
+					}else{
+																			
+						String[] nets = download.getNetworks();
+						
+						boolean	pub 	= false;
+						boolean	anon	= false;
+						
+						for ( String net: nets ){
+						
+							if ( net == AENetworkClassifier.AT_PUBLIC ){
+								
+								pub = true;
+								
+							}else if ( net == AENetworkClassifier.AT_I2P ){
+								
+								anon = true;
+							}
+						}
+						
+						if ( pub && anon ){
+							activateNetwork( AENetworkClassifier.AT_PUBLIC, true );
+							activateNetwork( AENetworkClassifier.AT_I2P, false );	// warm it up
+						}else if ( pub ){
+							activateNetwork( AENetworkClassifier.AT_PUBLIC, true );
+						}else if ( anon ){
+							activateNetwork( AENetworkClassifier.AT_I2P, true );
+						}
+					}
+				}
+			}
+		}
+		
+		private void
+		activateNetwork(
+			String			network,
+			boolean			select_tab )
+		{		
+			String key;
+		
+			if ( chat_mode == CHAT_DOWNLOAD ){
+			
+				DownloadAdapter	download 	= current_download;
+				
+				if ( download == null ){
+					
+					key = null;
+					
+				}else{
+
+					key = download.getChatKey();
+				}
+			}else if ( chat_mode == CHAT_TRACKERS ){
+				
+				String tracker = current_tracker;
+				
+				if ( tracker == null ){
+					
+					key = null;
+					
+				}else{
+						
+					key = "Tracker: " + tracker;
+				}
+			}else if ( chat_mode == CHAT_TAG ){
+				
+				Tag	tag = current_tag;
+				
+				if ( tag == null ){
+					
+					key = null;
+					
+				}else{
+						
+					key = TagUIUtils.getChatKey( tag );
+				}
+			}else if ( chat_mode == CHAT_GENERAL ){
+				
+				key = current_general;
+				
+			}else{
+				
+				key	= current_favourite_key;
+			}
+			
+			activateChat( network, key, select_tab );
+		}
+		
+		private void
+		activateChat(
+			final String		network,
+			final String		key,
+			boolean				select_tab )	
+		{		
+			final Composite chat_composite = chat_composites[network==AENetworkClassifier.AT_PUBLIC?0:1];
+			
+			if ( chat_composite == null ){
+				
+				return;
+			}
+			
+			final String comp_key = network + ":" + key;
+			
+			String existing_comp_key = (String)chat_composite.getData();
+			
+			if ( existing_comp_key == null || !existing_comp_key.equals( comp_key )){
+								
+				for ( Control c: chat_composite.getChildren()){
+					
+					c.dispose();
+				}
+					
+				if ( key == null ){
+					
+					chat_composite.setData( comp_key );
+					
+					return;
+				}
+				
+				AsyncDispatcher disp 		= network==AENetworkClassifier.AT_PUBLIC?public_dispatcher:anon_dispatcher;
+				
+				final AtomicInteger	counter 	= network==AENetworkClassifier.AT_PUBLIC?public_done:anon_done;
+				
+				disp.dispatch(
+					new AERunnable(){						
+						@Override
+						public void 
+						runSupport() 
+						{
+							if ( chat_composite.isDisposed()){
+								
+								return;
+							}
+						
+							try{
+								final ChatInstance chat = (network == AENetworkClassifier.AT_I2P && !plugin.getBeta().isI2PAvailable())?null:plugin.getBeta().getChat( network, key );
+						
+								counter.incrementAndGet();
+																
+								Utils.execSWTThread(
+									new Runnable()
+									{
+										public void
+										run()
+										{
+											if ( chat_composite.isDisposed()){
+												
+												return;
+											}
+										
+											for ( Control c: chat_composite.getChildren()){
+												
+												c.dispose();
+											}
+											
+											if ( chat == null ){
+												
+												GridLayout layout = new GridLayout();
+												//layout.horizontalSpacing = 1;
+												//layout.verticalSpacing = 1;
+												layout.numColumns = 3;
+										
+												chat_composite.setLayout( layout );
+												
+												Label label = new Label( chat_composite, SWT.NULL );
+												
+												label.setText( MessageText.getString( "azbuddy.dchat.not.installed" ));
+												
+												final Button install_button = new Button( chat_composite, SWT.NULL );
+												
+												install_button.setText( MessageText.getString( "UpdateWindow.columns.install" ));
+												
+												install_button.addSelectionListener(
+													new SelectionAdapter() {
+														
+														public void widgetSelected(SelectionEvent e) {
+															
+															final boolean[] result = { false };
+																														
+															I2PHelpers.installI2PHelper(
+																null, result,
+																new Runnable() {
+																	
+																	private long				start = SystemTime.getMonotonousTime();
+																	private TimerEventPeriodic 	timer;
+
+																	public void 
+																	run() 
+																	{
+																		if ( result[0] ){																		
+																		
+																			Utils.execSWTThread(
+																					new Runnable()
+																					{
+																						public void
+																						run() 
+																						{
+																							install_button.setEnabled( false );
+																						}
+																					});
+																			
+																			timer = 
+																				SimpleTimer.addPeriodicEvent(
+																					"install-waiter",
+																					1000,
+																					new TimerEventPerformer() 
+																					{	
+																						public void 
+																						perform(
+																							TimerEvent event) 
+																						{																							
+																							if ( plugin.getBeta().isI2PAvailable()){
+																								
+																								timer.cancel();
+																								
+																								Utils.execSWTThread(
+																									new Runnable()
+																									{
+																										public void
+																										run() 
+																										{
+																											String existing_comp_key = (String)chat_composite.getData();
+			
+																											if ( existing_comp_key == null || existing_comp_key.equals( comp_key )){
+																												
+																												counter.set( 0 );
+																												
+																												chat_composite.setData( null );
+																												
+																												activateChat( network, key, true );
+																											}
+																										}
+																									});
+																							}else{
+																								
+																								if ( SystemTime.getMonotonousTime() - start > 5*60*1000 ){
+																									
+																									timer.cancel();
+																								}
+																							}
+																							
+																						}
+																					});
+																			
+																		}
+																	}
+																});
+														}
+													});
+												
+												List<Button> buttons = new ArrayList<Button>();
+												
+												buttons.add( install_button );
+												
+												Utils.makeButtonsEqualWidth( buttons );
+												
+												chat_composite.layout( true, true );
+												
+											}else{
+												
+												BuddyPluginViewBetaChat view = new BuddyPluginViewBetaChat( BuddyPluginView.this, plugin, chat, chat_composite );
+												
+												((CTabItem)chat_composite.getData("tabitem")).setToolTipText( key );
+												
+												chat_composite.layout( true, true );
+												
+												chat_composite.setData( comp_key );
+												
+												chat_composite.setData( "viewitem", view );
+												
+												if ( view_listener != null ){
+													
+													try{
+														view_listener.chatActivated(chat);
+														
+													}catch( Throwable e){
+														
+														Debug.out( e );
+													}
+												}
+											}
+										}
+									});
+								
+							}catch( Throwable e ){
+								
+								e.printStackTrace();
+							}	
+							
+						}
+					});
+		
+				if ( counter.get() == 0 ){
+					
+					GridLayout layout = new GridLayout();
+					layout.numColumns = 1;
+					chat_composite.setLayout(layout);
+	
+					Label label = new Label( chat_composite, SWT.NULL );
+					
+					label.setText( MessageText.getString( "v3.MainWindow.view.wait" ));
+					GridData grid_data = new GridData(GridData.FILL_BOTH );
+					label.setLayoutData(grid_data);
+	
+				}
+				
+				chat_composite.layout( true, true );
+				
+			}else{
+				
+				BuddyPluginViewBetaChat existing_chat =  (BuddyPluginViewBetaChat)chat_composite.getData( "viewitem" );
+				
+				if ( existing_chat != null ){
+					
+					existing_chat.activate();
+				}
+			}
+			
+			if ( select_tab ){
+				
+				tab_folder.setSelection( network==AENetworkClassifier.AT_PUBLIC?public_item:anon_item );
+			}
+		}
+		
+		private void
+		setDataSource(
+			Object		obj )
+		{									
+			Download 			dl 		= null;
+			DiskManagerFileInfo	dl_file = null;
+			Tag					tag		= null;
+			
+			if ( obj instanceof Object[]){
+				
+				Object[] ds = (Object[])obj;
+				
+				if ( ds.length > 0 ){
+					
+					if ( ds[0] instanceof Download ){
+		
+						dl = (Download)ds[0];
+						
+					}else if ( ds[0] instanceof DiskManagerFileInfo ){
+						
+						dl_file = (DiskManagerFileInfo)ds[0];
+						
+					}else if ( ds[0] instanceof Tag ) {
+						
+						tag = (Tag) ds[0];
+					}
+				}
+			}else{
+				
+				if ( obj instanceof Download ){
+					
+					dl = (Download)obj;
+					
+				}else if ( obj instanceof DiskManagerFileInfo ){
+					
+					dl_file = (DiskManagerFileInfo)obj;
+					
+				}else if ( obj instanceof Tag ){
+					
+					tag = (Tag)obj;
+				}
+			}
+			
+			if ( dl_file != null ){
+				
+				try{
+					dl = dl_file.getDownload();
+					
+				}catch( Throwable e ){	
+				}
+			}
+			
+			synchronized( this ){
+				
+				if ( dl == current_download && tag == current_ds_tag ){
+					
+					return;
+				}
+				
+				current_download 	= dl==null?null:getDownloadAdapter( dl );
+				current_ds_tag		= tag;
+				
+				if (current_download != null) {
+					setChatMode(CHAT_DOWNLOAD);
+				}
+				
+				rebuild_outstanding = true;
+				
+				if ( have_focus ){
+					
+					activate();
+				}
+			}
+		}
+		
+		private void
+		gotFocus()
+		{
+			synchronized( this ){
+				
+				have_focus = true;
+								
+				activate();
+			}
+		}
+		
+		private void
+		lostFocus()
+		{
+			synchronized( this ){
+				
+				have_focus = false;
+			}
+		}
+		
+		public void
+		destroy()
+		{			
+			//System.out.println( "Destroyed" );
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewBetaChat.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewBetaChat.java
new file mode 100644
index 0000000..c0c38d1
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewBetaChat.java
@@ -0,0 +1,4219 @@
+/*
+ * Created on Apr 26, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy.swt;
+
+import java.io.File;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTarget;
+import org.eclipse.swt.dnd.DropTargetAdapter;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+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.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MenuAdapter;
+import org.eclipse.swt.events.MenuDetectEvent;
+import org.eclipse.swt.events.MenuDetectListener;
+import org.eclipse.swt.events.MenuEvent;
+import org.eclipse.swt.events.MenuListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+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.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+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.config.COConfigurationManager;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.AddressUtils;
+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.FrequencyLimitedDispatcher;
+import org.gudy.azureus2.core3.util.RandomUtils;
+import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.core3.util.UrlUtils;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.sharing.ShareManager;
+import org.gudy.azureus2.plugins.sharing.ShareResourceDir;
+import org.gudy.azureus2.plugins.sharing.ShareResourceFile;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.UIManagerEvent;
+import org.gudy.azureus2.plugins.utils.LocaleUtilities;
+import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.URLTransfer;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.BufferedLabel;
+import org.gudy.azureus2.ui.swt.components.LinkLabel;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
+import org.gudy.azureus2.ui.swt.mainwindow.Colors;
+import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
+
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.*;
+import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+
+public class 
+BuddyPluginViewBetaChat 
+	implements ChatListener
+{
+	private static final boolean TEST_LOOPBACK_CHAT = System.getProperty( "az.chat.loopback.enable", "0" ).equals( "1" );
+	private static final boolean DEBUG_ENABLED		= BuddyPluginBeta.DEBUG_ENABLED;
+
+	private static final int	MAX_MSG_LENGTH	= 400;
+	
+	private static final Set<BuddyPluginViewBetaChat>	active_windows = new HashSet<BuddyPluginViewBetaChat>();
+	
+	private static boolean auto_ftux_popout_done	= false;
+	
+	private final BuddyPluginView		view;
+	private final BuddyPlugin			plugin;
+	private final BuddyPluginBeta		beta;
+	private final ChatInstance			chat;
+	
+	private final LocaleUtilities		lu;
+	
+	private Shell 					shell;
+	
+	private StyledText 				log;
+	private StyleRange[]			log_styles = new StyleRange[0];
+	
+	private BufferedLabel			table_header;
+	private Table					buddy_table;
+	private BufferedLabel		 	status;
+	
+	private Button 					shared_nick_button;
+	private Text 					nickname;
+	
+	private Text 					input_area;
+	
+	private DropTarget[]			drop_targets;
+	
+	private LinkedHashMap<ChatMessage,Integer>	messages		= new LinkedHashMap<ChatMessage,Integer>();
+	private List<ChatParticipant>				participants 	= new ArrayList<ChatParticipant>();
+	
+	private Map<ChatParticipant,ChatMessage>	participant_last_message_map = new HashMap<ChatParticipant, ChatMessage>();
+	
+	private boolean		table_resort_required;
+	
+	private Font	italic_font;
+	private Font	bold_font;
+	private Font	big_font;
+	private Font	small_font;
+	
+	private Color	ftux_dark_bg;
+	private Color	ftux_dark_fg;
+	private Color	ftux_light_bg;
+	
+	private boolean	ftux_ok;
+	private boolean	build_complete;
+	
+	protected
+	BuddyPluginViewBetaChat(
+		BuddyPluginView	_view,
+		BuddyPlugin		_plugin,
+		ChatInstance	_chat )
+	{
+		view	= _view;
+		plugin	= _plugin;
+		chat	= _chat;
+		beta	= plugin.getBeta();
+		
+		lu		= plugin.getPluginInterface().getUtilities().getLocaleUtilities();
+		
+		if ( beta.getStandAloneWindows()){
+			
+			shell = ShellFactory.createShell( (Shell)null, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX );
+			
+		}else{
+			
+			shell = ShellFactory.createMainShell( SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX );
+		}
+		
+		shell.addListener(
+			SWT.Show,
+			new Listener() {
+				public void handleEvent(Event event) {
+					activate();
+				}
+			});
+		
+		shell.setText( lu.getLocalisedMessageText( "label.chat" ) + ": " + chat.getName());
+				
+		Utils.setShellIcon(shell);
+		
+		build( shell );
+		
+		shell.addListener(
+			SWT.Traverse, 
+			new Listener() 
+			{	
+				public void 
+				handleEvent(
+					Event e ) 
+				{
+					if ( e.character == SWT.ESC){
+					
+						close();
+				}
+			}
+			});
+		
+		shell.addControlListener(
+			new ControlListener()
+			{
+				private volatile Rectangle last_position;
+				
+				private FrequencyLimitedDispatcher disp = 
+					new FrequencyLimitedDispatcher(
+						new AERunnable() {
+							
+							@Override
+							public void 
+							runSupport() 
+							{
+								Rectangle	pos = last_position;
+								
+								String str = pos.x+","+pos.y+","+pos.width+","+pos.height;
+																
+								COConfigurationManager.setParameter( "azbuddy.dchat.ui.last.win.pos", str );
+							}
+						},
+					1000 );
+				
+				public void 
+				controlResized(
+					ControlEvent e) 
+				{
+					handleChange();
+				}
+				
+				public void 
+				controlMoved(
+					ControlEvent e) 
+				{
+					handleChange();
+				}
+				
+				private void
+				handleChange()
+				{
+					last_position = shell.getBounds();
+					
+					disp.dispatch();
+				}
+			});
+	
+		
+		int DEFAULT_WIDTH	= 500;
+		int DEFAULT_HEIGHT	= 500;
+		int MIN_WIDTH		= 300;
+		int MIN_HEIGHT		= 150;
+
+		
+		String str_pos = COConfigurationManager.getStringParameter( "azbuddy.dchat.ui.last.win.pos", "" );
+
+		Rectangle last_bounds = null;
+
+		try{
+			if ( str_pos != null && str_pos.length() > 0 ){
+				
+				String[] bits = str_pos.split( "," );
+				
+				if ( bits.length == 4 ){
+					
+					int[]	 i_bits = new int[4];
+					
+					for ( int i=0;i<bits.length;i++){
+						
+						i_bits[i] = Integer.parseInt( bits[i] );
+					}
+														 
+					last_bounds = 
+						new Rectangle(
+							i_bits[0], 
+							i_bits[1], 
+							Math.max( MIN_WIDTH, i_bits[2] ),
+							Math.max( MIN_HEIGHT, i_bits[3] ));
+				}
+			}
+		}catch( Throwable e ){
+		}
+				
+	    //Utils.createURLDropTarget(shell, input_area);
+	    
+		if ( active_windows.size() > 0 ){
+			
+			int	max_x = 0;
+			int max_y = 0;
+			
+			for ( BuddyPluginViewBetaChat window: active_windows ){
+				
+				if ( !window.shell.isDisposed()){
+					
+					Rectangle rect = window.shell.getBounds();
+					
+					max_x = Math.max( max_x, rect.x );
+					max_y = Math.max( max_y, rect.y );
+				}
+			}
+				
+			Rectangle rect = new Rectangle( 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT );
+							
+			rect.x = max_x + 16;
+			rect.y = max_y + 16;
+			
+			if ( last_bounds != null ){
+				
+				rect.width 	= last_bounds.width;
+				rect.height	=  last_bounds.height;
+			}
+			
+			shell.setBounds( rect );
+									
+			Utils.verifyShellRect( shell, true );
+			
+		}else{
+  			
+			if ( last_bounds != null ){
+										
+				shell.setBounds( last_bounds );
+					    
+				Utils.verifyShellRect( shell, true );
+						 
+			}else{
+			
+			    shell.setSize( DEFAULT_WIDTH, DEFAULT_HEIGHT );
+
+				Utils.centreWindow(shell);
+			}
+		}
+		
+	    active_windows.add( this );
+
+	    shell.addDisposeListener(
+	    	new DisposeListener(){
+				public void 
+				widgetDisposed(DisposeEvent e)
+				{
+					active_windows.remove( BuddyPluginViewBetaChat.this );
+				}
+			});
+	    
+	    shell.open();
+	    
+	    shell.forceActive();
+	}
+	
+	protected
+	BuddyPluginViewBetaChat(
+		BuddyPluginView	_view,
+		BuddyPlugin		_plugin,
+		ChatInstance	_chat,
+		Composite		_parent )
+	{
+		view	= _view;
+		plugin	= _plugin;
+		chat	= _chat;
+		beta	= plugin.getBeta();
+
+		lu		= plugin.getPluginInterface().getUtilities().getLocaleUtilities();
+		
+		build( _parent );
+	}
+	
+	private void
+	build(
+		Composite		parent )
+	{
+		view.registerUI( chat );
+		
+		boolean public_chat = !chat.isPrivateChat();
+	
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		parent.setLayout(layout);
+		GridData grid_data = new GridData(GridData.FILL_BOTH );
+		parent.setLayoutData(grid_data);
+
+		Composite sash_area = new Composite( parent, SWT.NONE );
+		layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		sash_area.setLayout(layout);
+		
+		grid_data = new GridData(GridData.FILL_BOTH );
+		grid_data.horizontalSpan = 2;
+		sash_area.setLayoutData(grid_data);
+		
+	    final SashForm sash = new SashForm(sash_area,SWT.HORIZONTAL );
+	    grid_data = new GridData(GridData.FILL_BOTH );
+	    sash.setLayoutData(grid_data);
+	    	    
+		final Composite lhs = new Composite(sash, SWT.NONE);
+		
+		lhs.addDisposeListener(
+				new DisposeListener()
+				{
+					public void 
+					widgetDisposed(
+						DisposeEvent arg0 ) 
+					{
+						Font[] fonts = { italic_font, bold_font, big_font, small_font };
+						
+						for ( Font f: fonts ){
+							
+							if ( f != null ){
+								
+								f.dispose();
+							}
+						}
+						
+						Color[] colours = { ftux_dark_bg, ftux_dark_fg, ftux_light_bg };
+						
+						for ( Color c: colours ){
+							
+							if ( c != null ){
+								
+								c.dispose();
+							}
+						}
+						
+						if ( drop_targets != null ){
+							
+							for ( DropTarget dt: drop_targets ){
+								
+								dt.dispose();
+							}
+						}
+						
+						closed();
+					}
+				});		
+		
+		layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		layout.marginTop = 4;
+		layout.marginLeft = 4;
+		lhs.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_BOTH );
+		grid_data.widthHint = 300;
+		lhs.setLayoutData(grid_data);
+		
+		final Label menu_drop = new Label( lhs, SWT.NULL );
+		
+		FontData fontData = menu_drop.getFont().getFontData()[0];
+		
+		Display display = menu_drop.getDisplay();
+		
+		italic_font = new Font( display, new FontData( fontData.getName(), fontData.getHeight(), SWT.ITALIC ));
+		bold_font 	= new Font( display, new FontData( fontData.getName(), fontData.getHeight(), SWT.BOLD ));
+		big_font 	= new Font( display, new FontData( fontData.getName(), (int)(fontData.getHeight()*1.5), SWT.BOLD ));
+		small_font 	= new Font( display, new FontData( fontData.getName(), (int)(fontData.getHeight()*0.5), SWT.BOLD ));
+
+		ftux_dark_bg 	= new Color( display, 183, 200, 212 );
+		ftux_dark_fg 	= new Color( display, 0, 81, 134 );
+		ftux_light_bg 	= new Color( display, 236, 242, 246 );
+		
+		status = new BufferedLabel( lhs, SWT.LEFT | SWT.DOUBLE_BUFFERED );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL);
+		
+		status.setLayoutData(grid_data);
+		status.setText( MessageText.getString( "PeersView.state.pending" ));
+		
+		Image image = ImageLoader.getInstance().getImage( "menu_down" );
+		menu_drop.setImage( image );
+		grid_data = new GridData();
+		grid_data.widthHint=image.getBounds().width;
+		grid_data.heightHint=image.getBounds().height;
+		menu_drop.setLayoutData(grid_data);
+
+		menu_drop.setCursor(menu_drop.getDisplay().getSystemCursor(SWT.CURSOR_HAND));		
+
+		Control status_control = status.getControl();
+		
+		final Menu status_menu = new Menu( status_control );
+		
+		status.getControl().setMenu( status_menu );
+		menu_drop.setMenu( status_menu );
+		
+		menu_drop.addMouseListener(new MouseAdapter() {
+			public void mouseDown(MouseEvent event) {
+				try{
+					Point p = status_menu.getDisplay().map( menu_drop, null, event.x, event.y );
+					
+					status_menu.setLocation( p );
+					
+					status_menu.setVisible(true);
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e);
+				}
+			}
+		});
+
+		if ( public_chat ){
+				
+			Menu status_clip_menu = new Menu(lhs.getShell(), SWT.DROP_DOWN);
+			MenuItem status_clip_item = new MenuItem( status_menu, SWT.CASCADE);
+			status_clip_item.setMenu(status_clip_menu);
+			status_clip_item.setText(  MessageText.getString( "label.copy.to.clipboard" ));
+			
+			MenuItem status_mi = new MenuItem( status_clip_menu, SWT.PUSH );
+			status_mi.setText( MessageText.getString( "azbuddy.dchat.copy.channel.key" ));
+			
+			status_mi.addSelectionListener(
+					new SelectionAdapter() {				
+						public void 
+						widgetSelected(
+							SelectionEvent e ) 
+						{
+							ClipboardCopy.copyToClipBoard( chat.getKey());
+						}
+					});
+			
+			status_mi = new MenuItem( status_clip_menu, SWT.PUSH );
+			status_mi.setText( MessageText.getString( "azbuddy.dchat.copy.channel.url" ));
+			
+			status_mi.addSelectionListener(
+					new SelectionAdapter() {				
+						public void 
+						widgetSelected(
+							SelectionEvent e ) 
+						{
+							ClipboardCopy.copyToClipBoard( chat.getURL());
+						}
+					});
+			
+			status_mi = new MenuItem( status_clip_menu, SWT.PUSH );
+			status_mi.setText( MessageText.getString( "azbuddy.dchat.copy.rss.url" ));
+			
+			status_mi.addSelectionListener(
+					new SelectionAdapter() {				
+						public void 
+						widgetSelected(
+							SelectionEvent e ) 
+						{
+							ClipboardCopy.copyToClipBoard( "azplug:?id=azbuddy&arg=" + UrlUtils.encode( chat.getURL() + "&format=rss" ));
+						}
+					});
+			
+			status_mi = new MenuItem( status_clip_menu, SWT.PUSH );
+			status_mi.setText( MessageText.getString( "azbuddy.dchat.copy.channel.pk" ));
+			
+			status_mi.addSelectionListener(
+					new SelectionAdapter() {				
+						public void 
+						widgetSelected(
+							SelectionEvent e ) 
+						{
+							ClipboardCopy.copyToClipBoard( Base32.encode( chat.getPublicKey()));
+						}
+					});
+							
+			status_mi = new MenuItem( status_clip_menu, SWT.PUSH );
+			status_mi.setText( MessageText.getString( "azbuddy.dchat.copy.channel.export" ));
+			
+			status_mi.addSelectionListener(
+					new SelectionAdapter() {				
+						public void 
+						widgetSelected(
+							SelectionEvent e ) 
+						{
+							ClipboardCopy.copyToClipBoard( chat.export());
+						}
+					});
+			
+			if ( !chat.isManaged()){
+				
+				Menu status_channel_menu = new Menu(lhs.getShell(), SWT.DROP_DOWN);
+				MenuItem status_channel_item = new MenuItem( status_menu, SWT.CASCADE);
+				status_channel_item.setMenu(status_channel_menu);
+				status_channel_item.setText(  MessageText.getString( "azbuddy.dchat.rchans" ));
+		
+					// Managed channel
+				
+				status_mi = new MenuItem( status_channel_menu, SWT.PUSH );
+				status_mi.setText( MessageText.getString( "azbuddy.dchat.rchans.managed" ));
+		
+				status_mi.addSelectionListener(
+						new SelectionAdapter() {				
+							public void 
+							widgetSelected(
+								SelectionEvent event ) 
+							{								
+								try{
+									ChatInstance inst = chat.getManagedChannel();
+									
+									new BuddyPluginViewBetaChat( view, plugin, inst );
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+							}
+						});
+				
+					// RO channel
+				
+				status_mi = new MenuItem( status_channel_menu, SWT.PUSH );
+				status_mi.setText( MessageText.getString( "azbuddy.dchat.rchans.ro" ));
+		
+				status_mi.addSelectionListener(
+						new SelectionAdapter() {				
+							public void 
+							widgetSelected(
+								SelectionEvent event ) 
+							{
+								try{
+									ChatInstance inst = chat.getReadOnlyChannel();
+									
+									new BuddyPluginViewBetaChat( view, plugin, inst );
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}						
+							}
+						});
+				
+					// Random sub-channel
+				
+				status_mi = new MenuItem( status_channel_menu, SWT.PUSH );
+				status_mi.setText( MessageText.getString( "azbuddy.dchat.rchans.rand" ));
+		
+				status_mi.addSelectionListener(
+						new SelectionAdapter() {				
+							public void 
+							widgetSelected(
+								SelectionEvent event ) 
+							{
+								try{
+									byte[]	rand = new byte[20];
+									
+									RandomUtils.nextSecureBytes( rand );
+									
+									ChatInstance inst = beta.getChat( chat.getNetwork(), chat.getKey() + " {" + Base32.encode( rand ) + "}" );
+									
+									new BuddyPluginViewBetaChat( view, plugin, inst );
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}						
+							}
+						});
+				if ( beta.isI2PAvailable()){
+					
+					status_mi = new MenuItem( status_channel_menu, SWT.PUSH );
+					status_mi.setText( MessageText.getString(  chat.getNetwork()==AENetworkClassifier.AT_I2P?"azbuddy.dchat.rchans.pub":"azbuddy.dchat.rchans.anon" ));
+			
+					status_mi.addSelectionListener(
+							new SelectionAdapter() {				
+								public void 
+								widgetSelected(
+									SelectionEvent event ) 
+								{
+									try{
+										ChatInstance inst = beta.getChat( chat.getNetwork()==AENetworkClassifier.AT_I2P?AENetworkClassifier.AT_PUBLIC:AENetworkClassifier.AT_I2P, chat.getKey());
+										
+										new BuddyPluginViewBetaChat( view, plugin, inst );
+										
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}						
+								}
+							});
+				}
+			}
+							
+			final MenuItem fave_mi = new MenuItem( status_menu, SWT.CHECK );
+			fave_mi.setText( MessageText.getString( "label.fave" ));
+			
+			fave_mi.addSelectionListener(
+					new SelectionAdapter() {				
+						public void 
+						widgetSelected(
+							SelectionEvent e ) 
+						{
+							chat.setFavourite( fave_mi.getSelection());
+						}
+					});
+			
+			final Menu advanced_menu = new Menu(status_menu.getShell(), SWT.DROP_DOWN);
+			MenuItem advanced_menu_item = new MenuItem( status_menu, SWT.CASCADE);
+			advanced_menu_item.setMenu(advanced_menu);
+			advanced_menu_item.setText(  MessageText.getString( "MyTorrentsView.menu.advancedmenu" ));
+
+			final MenuItem persist_mi = new MenuItem( advanced_menu, SWT.CHECK );
+			persist_mi.setText( MessageText.getString( "azbuddy.dchat.save.messages" ));
+			
+			persist_mi.addSelectionListener(
+					new SelectionAdapter() {				
+						public void 
+						widgetSelected(
+							SelectionEvent e ) 
+						{
+							chat.setSaveMessages( persist_mi.getSelection());
+						}
+					});
+			
+			final MenuItem log_mi = new MenuItem( advanced_menu, SWT.CHECK );
+			log_mi.setText( MessageText.getString( "azbuddy.dchat.log.messages" ));
+			
+			log_mi.addSelectionListener(
+					new SelectionAdapter() {				
+						public void 
+						widgetSelected(
+							SelectionEvent e ) 
+						{
+							chat.setLogMessages( log_mi.getSelection());
+						}
+					});		
+			
+			final MenuItem automute_mi = new MenuItem( advanced_menu, SWT.CHECK );
+			automute_mi.setText( MessageText.getString( "azbuddy.dchat.auto.mute" ));
+			
+			automute_mi.addSelectionListener(
+					new SelectionAdapter() {				
+						public void 
+						widgetSelected(
+							SelectionEvent e ) 
+						{
+							chat.setAutoMute( automute_mi.getSelection());
+						}
+					});		
+			
+			status_menu.addMenuListener(
+					new MenuAdapter() 
+					{
+						public void 
+						menuShown(
+							MenuEvent e ) 
+						{
+							fave_mi.setSelection( chat.isFavourite());
+							persist_mi.setSelection( chat.getSaveMessages());
+							log_mi.setSelection( chat.getLogMessages());
+							automute_mi.setSelection( chat.getAutoMute());
+						}
+					});
+		}else{
+			
+			final Menu status_priv_menu = new Menu(lhs.getShell(), SWT.DROP_DOWN);
+			MenuItem status_priv_item = new MenuItem( status_menu, SWT.CASCADE);
+			status_priv_item.setMenu(status_priv_menu);
+			status_priv_item.setText(  MessageText.getString( "label.private.chat" ));
+					
+			SelectionAdapter listener = 
+				new SelectionAdapter()
+				{				
+					public void 
+					widgetSelected(
+						SelectionEvent e ) 
+					{
+						beta.setPrivateChatState((Integer)((MenuItem)e.widget).getData());
+					}
+				};
+			
+			MenuItem status_mi = new MenuItem( status_priv_menu, SWT.RADIO );
+			status_mi.setText( MessageText.getString( "devices.contextmenu.od.enabled" ));
+			status_mi.setData( BuddyPluginBeta.PRIVATE_CHAT_ENABLED );
+			
+			status_mi.addSelectionListener( listener );
+		
+			status_mi = new MenuItem( status_priv_menu, SWT.RADIO );
+			status_mi.setText( MessageText.getString( "label.pinned.only" ));
+			status_mi.setData( BuddyPluginBeta.PRIVATE_CHAT_PINNED_ONLY );
+			
+			status_mi.addSelectionListener( listener );
+
+			status_mi = new MenuItem( status_priv_menu, SWT.RADIO );
+			status_mi.setText( MessageText.getString( "pairing.status.disabled" ));
+			status_mi.setData( BuddyPluginBeta.PRIVATE_CHAT_DISABLED );
+			
+			status_mi.addSelectionListener( listener );
+
+			
+			status_priv_menu.addMenuListener(
+				new MenuAdapter() 
+				{
+					public void 
+					menuShown(
+						MenuEvent e ) 
+					{
+						int pc_state = beta.getPrivateChatState();
+						
+						for ( MenuItem mi: status_priv_menu.getItems()){
+							
+							mi.setSelection( pc_state == (Integer)mi.getData());
+						}
+					}
+				});
+			
+			final MenuItem fave_mi = new MenuItem( status_menu, SWT.CHECK );
+			fave_mi.setText( MessageText.getString( "label.keep.alive" ));
+			
+			status_menu.addMenuListener(
+				new MenuAdapter() 
+				{
+					public void 
+					menuShown(
+						MenuEvent e ) 
+					{
+						fave_mi.setSelection( chat.getUserData( "AC:KeepAlive" ) != null );
+					}
+				});
+			
+			fave_mi.addSelectionListener(
+					new SelectionAdapter() {				
+						public void 
+						widgetSelected(
+							SelectionEvent e ) 
+						{
+							ChatInstance clone = (ChatInstance)chat.getUserData( "AC:KeepAlive" );
+							
+							if ( clone != null ){
+								
+								clone.destroy();
+								
+								clone = null;
+								
+							}else{
+								
+								try{
+									clone = chat.getClone();
+									
+								}catch( Throwable f ){
+									
+								}
+							}
+							
+							chat.setUserData( "AC:KeepAlive", clone );
+						}
+					});
+		}
+		
+		
+		final Composite ftux_stack = new Composite(lhs, SWT.NONE);
+		grid_data = new GridData(GridData.FILL_BOTH );
+		grid_data.horizontalSpan = 2;
+		ftux_stack.setLayoutData( grid_data );
+		
+        final StackLayout stack_layout = new StackLayout();
+        ftux_stack.setLayout(stack_layout);
+        
+		final Composite log_holder = new Composite(ftux_stack, SWT.BORDER);
+		
+		final Composite ftux_holder = new Composite(ftux_stack, SWT.BORDER);
+		
+			// FTUX panel
+		
+		layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		layout.horizontalSpacing = 0;
+		layout.verticalSpacing = 0;
+		ftux_holder.setLayout(layout);
+		
+		ftux_holder.setBackground( ftux_light_bg );
+
+			// top info
+		
+		Composite ftux_top_area = new Composite( ftux_holder, SWT.NULL );
+		layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		layout.verticalSpacing = 0;
+		ftux_top_area.setLayout(layout);
+		
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 2;
+		grid_data.heightHint = 30;
+		ftux_top_area.setLayoutData(grid_data);
+		ftux_top_area.setBackground( ftux_dark_bg );
+
+		
+		Label ftux_top = new Label( ftux_top_area, SWT.WRAP );
+		grid_data = new GridData(SWT.LEFT, SWT.CENTER, true, true );
+		grid_data.horizontalIndent = 8;
+		ftux_top.setLayoutData(grid_data);
+		
+		ftux_top.setAlignment( SWT.LEFT );
+		ftux_top.setBackground( ftux_dark_bg );
+		ftux_top.setForeground( ftux_dark_fg );
+		ftux_top.setFont( big_font );
+		ftux_top.setText( MessageText.getString( "azbuddy.dchat.ftux.welcome" ));
+		
+			// middle info
+		
+		Label ftux_hack = new Label( ftux_holder, SWT.NULL );
+		grid_data = new GridData();
+		grid_data.heightHint=40;
+		grid_data.widthHint=0;
+		ftux_hack.setLayoutData(grid_data);
+		
+		final StyledText ftux_middle = new StyledText( ftux_holder, SWT.READ_ONLY | SWT.V_SCROLL | SWT.WRAP | SWT.NO_FOCUS );
+		
+		grid_data = new GridData(GridData.FILL_BOTH );
+		grid_data.horizontalSpan = 1;
+		grid_data.verticalIndent = 4;
+		grid_data.horizontalIndent = 16;
+		ftux_middle.setLayoutData(grid_data);
+		
+		ftux_middle.setBackground( ftux_light_bg );
+				
+		String info1_text = 
+		"Vuze chat allows you to communicate with other Vuze users directly by sending and receiving messages.\n" +
+		"It is a decentralized chat system - there are no central servers involved, all messages are passed directly between Vuze users.\n" +
+		"Consequently Vuze has absolutely no control over message content. In particular no mechanism exists (nor is possible) for Vuze to moderate or otherwise control either messages or the users that send messages.";
+		
+		String info2_text =
+		"I UNDERSTAND AND AGREE that Vuze has no responsibility whatsoever with my enabling this function and using chat.";
+		
+		String[] info_lines = info1_text.split( "\n" );
+		
+		for ( String line: info_lines ){
+		
+			ftux_middle.append( line );
+			
+			if ( line != info_lines[info_lines.length-1] ){
+			
+				ftux_middle.append( "\n" );
+				
+				int	pos = ftux_middle.getText().length();
+				
+					// zero width space in large font to get smaller paragraph spacing 
+				
+				ftux_middle.append( "\u200B" );
+				
+				StyleRange styleRange = new StyleRange();
+				styleRange.start = pos;
+				styleRange.length = 1;
+				styleRange.font = big_font;
+				
+				ftux_middle.setStyleRange( styleRange );
+			}
+		}
+
+			// checkbox area
+		
+		Composite ftux_check_area = new Composite( ftux_holder, SWT.NULL );
+		layout = new GridLayout();
+		layout.marginLeft = 0;
+		layout.marginWidth = 0;
+		layout.numColumns = 2;
+		ftux_check_area.setLayout(layout);
+		
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 2;
+		ftux_check_area.setLayoutData( grid_data );
+		ftux_check_area.setBackground(  ftux_light_bg );
+
+		final Button ftux_check = new Button( ftux_check_area, SWT.CHECK );
+		grid_data = new GridData();
+		grid_data.horizontalIndent = 16;
+		ftux_check.setLayoutData( grid_data );
+		ftux_check.setBackground(  ftux_light_bg );
+		
+		Label ftux_check_test = new Label( ftux_check_area, SWT.WRAP );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		ftux_check_test.setLayoutData(grid_data);
+		
+		ftux_check_test.setBackground( ftux_light_bg );
+		ftux_check_test.setText( info2_text );
+
+		
+			// bottom info
+		
+		final StyledText ftux_bottom = new StyledText( ftux_holder, SWT.READ_ONLY | SWT.WRAP | SWT.NO_FOCUS );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 2;
+		grid_data.horizontalIndent = 16;
+		ftux_bottom.setLayoutData(grid_data);
+		
+		ftux_bottom.setBackground( ftux_light_bg );
+		ftux_bottom.setFont( bold_font );
+		ftux_bottom.setText( MessageText.getString( "azbuddy.dchat.ftux.footer" ) + " " );
+		
+		{
+			int	start	= ftux_bottom.getText().length();
+			
+			String url 		= MessageText.getString( "faq.legal.url" );
+			String url_text	= MessageText.getString( "label.more.dot" );
+			
+			ftux_bottom.append( url_text );
+			
+			StyleRange styleRange = new StyleRange();
+			styleRange.start = start;
+			styleRange.length = url_text.length();
+			styleRange.foreground = Colors.blue;
+			styleRange.underline = true;
+			
+			styleRange.data = url;
+			
+			ftux_bottom.setStyleRange( styleRange );
+		}
+		
+		ftux_bottom.addListener(
+				SWT.MouseUp, 
+				new Listener()
+				{
+					public void handleEvent(Event event) {
+						int offset = ftux_bottom.getOffsetAtLocation(new Point (event.x, event.y));
+						StyleRange style = ftux_bottom.getStyleRangeAtOffset(offset);
+						
+						if ( style != null ){
+							
+							String url = (String)style.data;
+							
+							try{
+								Utils.launch( new URL( url ));
+								
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}
+					}
+				});
+		
+		Label ftux_line = new Label( ftux_holder, SWT.SEPARATOR | SWT.HORIZONTAL );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 2;
+		grid_data.verticalIndent = 4;
+		ftux_line.setLayoutData( grid_data ); 
+		
+		Composite ftux_button_area = new Composite( ftux_holder, SWT.NULL );
+		layout = new GridLayout();
+		layout.numColumns = 2;
+		ftux_button_area.setLayout(layout);
+		
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 2;
+		ftux_button_area.setLayoutData( grid_data );
+		ftux_button_area.setBackground( Colors.white );
+		
+		Label filler = new Label( ftux_button_area, SWT.NULL );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		filler.setLayoutData( grid_data );
+		filler.setBackground( Colors.white );
+		
+		final Button ftux_accept = new Button( ftux_button_area, SWT.PUSH );
+		grid_data = new GridData();
+		grid_data.horizontalAlignment = SWT.RIGHT;
+		grid_data.widthHint = 60;
+		ftux_accept.setLayoutData(grid_data);
+
+		ftux_accept.setText( MessageText.getString( "label.accept" ));
+		
+		ftux_accept.setEnabled( false );
+		
+		ftux_accept.addSelectionListener(
+			new SelectionAdapter() {
+				
+				public void widgetSelected(SelectionEvent e) {
+					beta.setFTUXAccepted( true );
+				}
+			});
+		
+		ftux_check.addSelectionListener(
+			new SelectionAdapter() {
+					
+				public void widgetSelected(SelectionEvent e) {
+					ftux_accept.setEnabled( ftux_check.getSelection());
+				}
+		});
+			// LOG panel
+		
+		layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		layout.marginLeft = 4;
+		log_holder.setLayout(layout);
+		//grid_data = new GridData(GridData.FILL_BOTH );
+		//grid_data.horizontalSpan = 2;
+		//log_holder.setLayoutData(grid_data);
+		
+		log = new StyledText(log_holder,SWT.READ_ONLY | SWT.V_SCROLL | SWT.WRAP | SWT.NO_FOCUS );
+		grid_data = new GridData(GridData.FILL_BOTH);
+		grid_data.horizontalSpan = 1;
+		//grid_data.horizontalIndent = 4;
+		log.setLayoutData(grid_data);
+		//log.setIndent( 4 );
+		
+		log.setEditable( false );
+
+		log_holder.setBackground( log.getBackground());
+
+		final Menu log_menu = new Menu( log );
+		
+		log.setMenu(  log_menu );
+				
+		log.addMenuDetectListener(
+			new MenuDetectListener() {
+				
+				public void 
+				menuDetected(
+					MenuDetectEvent e ) 
+				{
+					e.doit = false;
+					
+					boolean	handled = false;
+					
+					for ( MenuItem mi: log_menu.getItems()){
+						
+						mi.dispose();
+					}
+
+					try{
+						Point mapped = log.getDisplay().map( null, log, new Point( e.x, e.y ));
+						
+						int offset = log.getOffsetAtLocation( mapped );
+						
+						StyleRange sr = log.getStyleRangeAtOffset(  offset );
+												
+						if ( sr != null ){
+
+							Object data = sr.data;
+							
+							if ( data instanceof ChatParticipant ){
+								
+								ChatParticipant cp = (ChatParticipant)data;
+								
+								List<ChatParticipant> cps = new ArrayList<ChatParticipant>();
+								
+								cps.add( cp );
+								
+								buildParticipantMenu( log_menu, cps );
+								
+								handled = true;
+																
+							}else if ( data instanceof String ){
+								
+								String url_str = (String)sr.data;
+								
+								String str = url_str;
+								
+								if ( str.length() > 50 ){
+									
+									str = str.substring( 0, 50 ) + "...";
+								}
+								
+									// magnet special case for anon chat
+								
+								if ( chat.isAnonymous() && url_str.toLowerCase( Locale.US ).startsWith( "magnet:" )){
+									
+									String[] magnet_uri = { url_str };
+									
+									Set<String> networks = UrlUtils.extractNetworks( magnet_uri );
+									
+									String i2p_only_uri = magnet_uri[0] + "&net=" + UrlUtils.encode( AENetworkClassifier.AT_I2P );
+										
+									String i2p_only_str = i2p_only_uri;
+									
+									if ( i2p_only_str.length() > 50 ){
+										
+										i2p_only_str = i2p_only_str.substring( 0, 50 ) + "...";
+									}
+									
+									i2p_only_str = lu.getLocalisedMessageText( "azbuddy.dchat.open.i2p.magnet" ) + ": " + i2p_only_str;
+									
+									final MenuItem mi_open_i2p_vuze = new MenuItem( log_menu, SWT.PUSH );
+									
+									mi_open_i2p_vuze.setText( i2p_only_str);
+									mi_open_i2p_vuze.setData( i2p_only_uri );
+
+									mi_open_i2p_vuze.addSelectionListener(
+										new SelectionAdapter() {
+											
+											public void 
+											widgetSelected(
+												SelectionEvent e ) 
+											{
+												String url_str = (String)mi_open_i2p_vuze.getData();
+												
+												if ( url_str != null ){
+													
+													TorrentOpener.openTorrent( url_str );
+												}
+											}
+										});
+									
+									if ( networks.size() == 1 && networks.iterator().next() == AENetworkClassifier.AT_I2P ){
+										
+										// already done above
+										
+									}else{
+										
+										str = lu.getLocalisedMessageText( "azbuddy.dchat.open.magnet" ) + ": " + str;
+										
+										final MenuItem mi_open_vuze = new MenuItem( log_menu, SWT.PUSH );
+										
+										mi_open_vuze.setText( str);
+										mi_open_vuze.setData( url_str );
+
+										mi_open_vuze.addSelectionListener(
+											new SelectionAdapter() {
+												
+												public void 
+												widgetSelected(
+													SelectionEvent e ) 
+												{
+													String url_str = (String)mi_open_vuze.getData();
+													
+													if ( url_str != null ){
+														
+														TorrentOpener.openTorrent( url_str );
+													}
+												}
+											});
+									}
+								}else{
+								
+								
+									str = lu.getLocalisedMessageText( "azbuddy.dchat.open.in.vuze" ) + ": " + str;
+																		
+									final MenuItem mi_open_vuze = new MenuItem( log_menu, SWT.PUSH );
+									
+									mi_open_vuze.setText( str);
+									mi_open_vuze.setData( url_str );
+
+									mi_open_vuze.addSelectionListener(
+										new SelectionAdapter() {
+											
+											public void 
+											widgetSelected(
+												SelectionEvent e ) 
+											{
+												String url_str = (String)mi_open_vuze.getData();
+												
+												if ( url_str != null ){
+													
+													String lc_url_str = url_str.toLowerCase( Locale.US );
+													
+													if ( lc_url_str.startsWith( "chat:" )){
+														
+														try{
+															beta.handleURI( url_str, true );
+															
+														}catch( Throwable f ){
+															
+															Debug.out( f );
+														}
+														
+													}else{
+													
+														TorrentOpener.openTorrent( url_str );
+													}
+												}
+											}
+										});
+								}
+								
+								final MenuItem mi_open_ext = new MenuItem( log_menu, SWT.PUSH );
+								
+								mi_open_ext.setText( lu.getLocalisedMessageText( "azbuddy.dchat.open.in.browser" ));
+								
+								mi_open_ext.addSelectionListener(
+									new SelectionAdapter() {
+										
+										public void 
+										widgetSelected(
+											SelectionEvent e ) 
+										{
+											String url_str = (String)mi_open_ext.getData();
+											
+											Utils.launch( url_str );
+										}
+									});
+								
+								new MenuItem( log_menu, SWT.SEPARATOR );
+								
+								if ( chat.isAnonymous() && url_str.toLowerCase( Locale.US ).startsWith( "magnet:" )){
+
+									String[] magnet_uri = { url_str };
+									
+									Set<String> networks = UrlUtils.extractNetworks( magnet_uri );
+									
+									String i2p_only_uri = magnet_uri[0] + "&net=" + UrlUtils.encode( AENetworkClassifier.AT_I2P );
+
+									final MenuItem mi_copy_i2p_clip = new MenuItem( log_menu, SWT.PUSH );
+									
+									mi_copy_i2p_clip.setText( lu.getLocalisedMessageText( "azbuddy.dchat.copy.i2p.magnet" ));
+									mi_copy_i2p_clip.setData( i2p_only_uri );
+
+									mi_copy_i2p_clip.addSelectionListener(
+											new SelectionAdapter() {
+												
+												public void 
+												widgetSelected(
+													SelectionEvent e ) 
+												{
+													String url_str = (String)mi_copy_i2p_clip.getData();
+													
+													if ( url_str != null ){
+														
+														ClipboardCopy.copyToClipBoard( url_str );
+													}
+												}
+											});
+									
+									if ( networks.size() == 1 && networks.iterator().next() == AENetworkClassifier.AT_I2P ){
+										
+										// already done above
+										
+									}else{
+										
+										final MenuItem mi_copy_clip = new MenuItem( log_menu, SWT.PUSH );
+										
+										mi_copy_clip.setText( lu.getLocalisedMessageText( "azbuddy.dchat.copy.magnet" ));
+										mi_copy_clip.setData( url_str );
+
+										mi_copy_clip.addSelectionListener(
+												new SelectionAdapter() {
+													
+													public void 
+													widgetSelected(
+														SelectionEvent e ) 
+													{
+														String url_str = (String)mi_copy_clip.getData();
+														
+														if ( url_str != null ){
+															
+															ClipboardCopy.copyToClipBoard( url_str );
+														}
+													}
+												});
+										
+									}
+								}else{
+									
+									final MenuItem mi_copy_clip = new MenuItem( log_menu, SWT.PUSH );
+									
+									mi_copy_clip.setText( lu.getLocalisedMessageText( "label.copy.to.clipboard" ));
+									mi_copy_clip.setData( url_str );
+
+									mi_copy_clip.addSelectionListener(
+											new SelectionAdapter() {
+												
+												public void 
+												widgetSelected(
+													SelectionEvent e ) 
+												{
+													String url_str = (String)mi_copy_clip.getData();
+													
+													if ( url_str != null ){
+														
+														ClipboardCopy.copyToClipBoard( url_str );
+													}
+												}
+											});
+								}				
+																
+								if ( url_str.toLowerCase().startsWith( "http" )){
+									
+									mi_open_ext.setData( url_str );
+									
+									mi_open_ext.setEnabled( true );
+									
+								}else{
+									
+									mi_open_ext.setEnabled( false );
+								}
+																
+								handled = true;
+							}
+						}
+					}catch( Throwable f ){
+					}
+					
+					if ( !handled ){
+						
+						final String text = log.getSelectionText();
+						
+						if ( text != null && text.length() > 0 ){
+							
+							MenuItem   item = new MenuItem( log_menu, SWT.NONE );
+
+							item.setText( MessageText.getString( "label.copy.to.clipboard"));
+
+							item.addSelectionListener(
+								new SelectionAdapter()
+								{
+									@Override
+									public void 
+									widgetSelected(
+										SelectionEvent e ) 
+									{
+										ClipboardCopy.copyToClipBoard( text );
+									}
+								});
+							
+							handled = true;
+						}
+					}
+					
+					if ( handled ){
+						
+						e.doit = true;
+					}
+				}
+			});
+		
+		log.addListener(
+			SWT.MouseDoubleClick,
+			new Listener()
+			{
+				public void 
+				handleEvent(
+					Event e )
+				{
+					try{
+						final int offset = log.getOffsetAtLocation( new Point( e.x, e.y ) );
+						
+						for ( int i=0;i<log_styles.length;i++){
+							
+							StyleRange sr = log_styles[i];
+							
+							Object data = sr.data;
+
+							if ( data != null && offset >= sr.start && offset < sr.start + sr.length ){
+								
+								boolean anon_chat = chat.isAnonymous();
+								
+								if ( data instanceof String ){
+									
+									final String	url_str = (String)data;
+									
+									String lc_url_str = url_str.toLowerCase( Locale.US );
+									
+									if ( lc_url_str.startsWith( "chat:" )){
+										
+											// no double-click support for anon->public chats
+										
+										if ( anon_chat && !lc_url_str.startsWith( "chat:anon:" )){
+											
+											return;
+										}
+										
+										try{
+											beta.handleURI( url_str, true );
+											
+										}catch( Throwable f ){
+											
+											Debug.out( f );
+										}
+									}else{
+										
+											// no double-click support for anon->public urls
+										
+										if ( anon_chat ){
+											
+											try{
+												String host = new URL( lc_url_str ).getHost();
+												
+													// note that magnet-uris are always decoded here as public, which is what we want mostly
+												
+												if ( AENetworkClassifier.categoriseAddress( host ) == AENetworkClassifier.AT_PUBLIC ){
+		
+													return;
+	
+												}
+											}catch( Throwable f ){
+												
+												return;
+											}
+										}
+										
+										if ( 	lc_url_str.contains( ".torrent" ) || 
+												UrlUtils.parseTextForMagnets( url_str ) != null ){
+											
+											TorrentOpener.openTorrent( url_str );
+											
+										}else{
+											
+											if ( url_str.toLowerCase( Locale.US ).startsWith( "http" )){
+												
+													// without this backoff we end up with the text widget
+													// being left in a 'mouse down' state when returning to it :(
+												
+												Utils.execSWTThreadLater(
+													100, 
+													new Runnable() 
+													{
+														public void 
+														run()
+														{	
+															Utils.launch( url_str );
+														}
+													});
+											}else{
+												
+												TorrentOpener.openTorrent( url_str );
+											}
+										}
+									}
+									
+									log.setSelection( offset );
+									
+									e.doit = false;
+									
+								}else if ( data instanceof ChatParticipant ){
+									
+									ChatParticipant participant = (ChatParticipant)data;
+									
+									String name = participant.getName( true );
+									
+									String existing = input_area.getText();
+									
+									if ( existing.length() > 0 && !existing.endsWith( " " )){
+										
+										name = " " + name;
+									}
+									
+									input_area.append( name );
+								}
+							}
+						}
+					}catch( Throwable f ){
+						
+					}
+				}
+			});
+
+		log.addMouseTrackListener(
+			new MouseTrackListener() {
+				
+				private StyleRange		old_range;
+				private StyleRange		temp_range;
+				private int				temp_index;
+				
+				public void mouseHover(MouseEvent e) {
+					
+					boolean active = false;
+
+					try{
+						int offset = log.getOffsetAtLocation( new Point( e.x, e.y ) );
+						
+						for ( int i=0;i<log_styles.length;i++){
+							
+							StyleRange sr = log_styles[i];
+							
+							Object data = sr.data;
+
+							if ( data != null && offset >= sr.start && offset < sr.start + sr.length ){
+									
+								if ( old_range != null  ){
+									
+									if ( 	temp_index < log_styles.length &&
+											log_styles[temp_index] == temp_range ){
+										
+										log_styles[ temp_index ] = old_range;
+																				
+										old_range	= null;
+									}
+								}
+								
+								sr = log_styles[i];
+								
+								log.setToolTipText( MessageText.getString( "label.right.click.for.options" ));
+								
+									
+								StyleRange derp = new StyleRange( sr );
+									
+								derp.start = sr.start;
+								derp.length = sr.length;
+								
+								derp.borderStyle = SWT.BORDER_DASH;
+								
+								old_range	= sr;
+								temp_range	= derp;
+								temp_index	= i;
+								
+								log_styles[i] = derp;
+								
+								log.setStyleRanges( log_styles );
+								
+								active = true;
+									
+								break;
+							}
+						}
+					}catch( Throwable f ){
+				
+					}
+					
+					if ( !active ){
+						
+						log.setToolTipText( "" );
+						
+						if ( old_range != null ){
+							
+							if ( 	temp_index < log_styles.length &&
+									log_styles[temp_index] == temp_range ){
+								
+								log_styles[ temp_index ] = old_range;
+								
+								old_range	= null;
+								
+								log.setStyleRanges( log_styles );
+							}
+						}
+					}
+				}
+				
+				public void mouseExit(MouseEvent e) {
+					// TODO Auto-generated method stub
+					
+				}
+				
+				public void mouseEnter(MouseEvent e) {
+					// TODO Auto-generated method stub
+					
+				}
+			});
+
+		
+		log.addKeyListener(
+			new KeyAdapter()
+			{
+				public void 
+				keyPressed(
+					KeyEvent event ) 
+				{
+					int key = event.character;
+					
+					if ( key <= 26 && key > 0 ){
+						
+						key += 'a' - 1;
+					}
+
+					if ( key == 'a' && event.stateMask == SWT.MOD1 ){
+						
+						event.doit = false;
+						
+						log.selectAll();
+					}
+				}
+			});
+		
+		Composite rhs = new Composite(sash, SWT.NONE);
+		layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		layout.marginTop = 4;
+		layout.marginRight = 4;
+		rhs.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_VERTICAL );
+		int rhs_width=Constants.isWindows?150:160;
+		grid_data.widthHint = rhs_width;
+		rhs.setLayoutData(grid_data);
+
+			// options
+		
+		Composite top_right = new Composite(rhs, SWT.NONE);
+		layout = new GridLayout();
+		layout.numColumns = 3;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		
+		top_right.setLayout(layout);
+		grid_data = new GridData( GridData.FILL_HORIZONTAL );
+		//grid_data.heightHint = 50;
+		top_right.setLayoutData(grid_data);
+		
+		boolean	can_popout = shell == null && public_chat;
+
+		Label label = new Label( top_right, SWT.NULL );
+		grid_data = new GridData( GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan=can_popout?1:2;
+		label.setLayoutData(grid_data);
+		
+		LinkLabel link = new LinkLabel( top_right, "label.help", lu.getLocalisedMessageText( "azbuddy.dchat.link.url" ));	
+		//grid_data.horizontalAlignment = SWT.END;
+		//link.getlabel().setLayoutData( grid_data );
+
+		if ( can_popout ){
+			
+			Label pop_out = new Label( top_right, SWT.NULL );
+			image = ImageLoader.getInstance().getImage( "popout_window" );
+			pop_out.setImage( image );
+			grid_data = new GridData();
+			grid_data.widthHint=image.getBounds().width;
+			grid_data.heightHint=image.getBounds().height;
+			pop_out.setLayoutData(grid_data);
+			
+			pop_out.setCursor(label.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
+			
+			pop_out.setToolTipText( MessageText.getString( "label.pop.out" ));
+			
+			pop_out.addMouseListener(new MouseAdapter() {
+				public void mouseUp(MouseEvent arg0) {
+					try{
+						new BuddyPluginViewBetaChat( view, plugin, chat.getClone());
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e);
+					}
+				}
+			});
+				
+		}	
+		
+			// nick name
+		
+		Composite nick_area = new Composite(top_right, SWT.NONE);
+		layout = new GridLayout();
+		layout.numColumns = 4;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		if ( !Constants.isWindows ){
+			layout.horizontalSpacing = 2;
+			layout.verticalSpacing = 2;
+		}
+		nick_area.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan=3;
+		nick_area.setLayoutData(grid_data);
+		
+		label = new Label( nick_area, SWT.NULL );
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.nick" ));
+		grid_data = new GridData();
+		//grid_data.horizontalIndent=4;
+		label.setLayoutData(grid_data);
+
+		nickname = new Text( nick_area, SWT.BORDER );
+		grid_data = new GridData( GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan=1;
+		nickname.setLayoutData( grid_data );
+
+		nickname.setText( chat.getNickname());
+		nickname.setMessage( chat.getDefaultNickname());
+		
+		label = new Label( nick_area, SWT.NULL );
+		label.setText( lu.getLocalisedMessageText( "label.shared" ));
+		label.setToolTipText( lu.getLocalisedMessageText( "azbuddy.dchat.shared.tooltip" ));
+		
+		shared_nick_button = new Button( nick_area, SWT.CHECK );
+		
+		shared_nick_button.setSelection( chat.isSharedNickname());
+
+		shared_nick_button.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void widgetSelected(SelectionEvent arg0) {
+					
+					boolean shared = shared_nick_button.getSelection();
+					
+					chat.setSharedNickname( shared );
+				}
+			});
+		
+		nickname.addListener(SWT.FocusOut, new Listener() {
+	        public void handleEvent(Event event) {
+	        	String nick = nickname.getText().trim();
+	        	
+	        	if ( chat.isSharedNickname()){
+	        		
+	        		if ( chat.getNetwork() == AENetworkClassifier.AT_PUBLIC ){
+	        		
+	        			beta.setSharedPublicNickname( nick );
+	        			
+	        		}else{
+	        			
+	        			beta.setSharedAnonNickname( nick );
+	        		}
+	        	}else{
+	        		
+	        		chat.setInstanceNickname( nick );
+	        	}
+	        }
+	    });
+				
+		
+		table_header = new BufferedLabel( top_right, SWT.DOUBLE_BUFFERED );
+		grid_data = new GridData( GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan=3;
+		if ( !Constants.isWindows ){
+			grid_data.horizontalIndent = 2;
+		}
+		table_header.setLayoutData( grid_data );
+		table_header.setText(MessageText.getString( "PeersView.state.pending" ));
+		
+			// table
+		
+		buddy_table = new Table(rhs, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL);
+
+		String[] headers = { 
+				"azbuddy.ui.table.name" };
+
+		int[] sizes = { rhs_width-10 };
+
+		int[] aligns = { SWT.LEFT };
+
+		for (int i = 0; i < headers.length; i++){
+
+			TableColumn tc = new TableColumn(buddy_table, aligns[i]);
+				
+			tc.setWidth(sizes[i]);
+
+			Messages.setLanguageText(tc, headers[i]);
+		}	
+
+	    buddy_table.setHeaderVisible(true);
+
+	    grid_data = new GridData(GridData.FILL_BOTH);
+	    // grid_data.heightHint = buddy_table.getHeaderHeight() * 3;
+		buddy_table.setLayoutData(grid_data);
+		
+		
+		buddy_table.addListener(
+			SWT.SetData,
+			new Listener()
+			{
+				public void 
+				handleEvent(
+					Event event) 
+				{
+					TableItem item = (TableItem)event.item;
+					
+					setItemData( item );
+				}
+			});
+		
+		final Menu menu = new Menu(buddy_table);
+		
+		buddy_table.setMenu( menu );
+		
+		menu.addMenuListener(
+			new MenuListener() 
+			{
+				public void 
+				menuShown(
+					MenuEvent e ) 
+				{
+					MenuItem[] items = menu.getItems();
+					
+					for (int i = 0; i < items.length; i++){
+						
+						items[i].dispose();
+					}
+
+					final TableItem[] selection = buddy_table.getSelection();
+					
+					List<ChatParticipant>	participants = new ArrayList<BuddyPluginBeta.ChatParticipant>( selection.length );
+					
+					for (int i=0;i<selection.length;i++){
+						
+						TableItem item = selection[i];
+						
+						ChatParticipant	participant = (ChatParticipant)item.getData();
+
+						if ( participant == null ){
+							
+								// item data won't be set yet for items that haven't been
+								// visible...
+							
+							participant = setItemData( item );
+						}
+						
+						if ( participant != null ){
+						
+							participants.add( participant );
+						}
+					}
+					
+					buildParticipantMenu( menu, participants );
+				}
+				
+				public void menuHidden(MenuEvent e) {
+				}
+			});
+		
+		buddy_table.addKeyListener(
+				new KeyAdapter()
+				{
+					public void 
+					keyPressed(
+						KeyEvent event ) 
+					{
+						int key = event.character;
+						
+						if ( key <= 26 && key > 0 ){
+							
+							key += 'a' - 1;
+						}
+
+						if ( key == 'a' && event.stateMask == SWT.MOD1 ){
+							
+							event.doit = false;
+							
+							buddy_table.selectAll();
+						}
+					}
+				});
+		
+		
+		buddy_table.addMouseListener(
+			new MouseAdapter()
+			{
+				public void 
+				mouseDoubleClick(
+					MouseEvent e ) 
+				{
+					TableItem[] selection = buddy_table.getSelection();
+					
+					if ( selection.length != 1 ){
+						
+						return;
+					}
+					
+					TableItem item = selection[0];
+						
+					ChatParticipant	participant = (ChatParticipant)item.getData();
+					
+					String name = participant.getName( true );
+					
+					String existing = input_area.getText();
+					
+					if ( existing.length() > 0 && !existing.endsWith( " " )){
+						
+						name = " " + name;
+					}
+					
+					input_area.append( name );
+
+				}
+			});
+		
+	    Utils.maintainSashPanelWidth( sash, rhs, new int[]{ 700, 300 }, "azbuddy.dchat.ui.sash.pos" );
+	    
+	    /*
+	    Listener sash_listener= 
+	    	new Listener()
+	    	{
+	    		private int	lhs_weight;
+	    		private int	lhs_width;
+	    		
+		    	public void 
+				handleEvent(
+					Event ev ) 
+				{
+		    		if ( ev.widget == lhs ){
+		    			
+		    			int[] weights = sash.getWeights();
+		    			
+		    			
+		    			if ( lhs_weight != weights[0] ){
+		    				
+		    					// sash has moved
+		    				
+		    				lhs_weight = weights[0];
+		    				
+		    					// keep track of the width
+		    				
+		    				lhs_width = lhs.getBounds().width;
+		    			}
+		    		}else{
+		    			
+		    				// resize
+		    			
+		    			if ( lhs_width > 0 ){
+		    						    				
+				            int width = sash.getClientArea().width;
+				            	
+				            double ratio = (double)lhs_width/width;
+	
+				            lhs_weight = (int)(ratio*1000 );
+				          
+				            sash.setWeights( new int[]{ lhs_weight, 1000 - lhs_weight });
+		    			}
+		    		}
+			    }
+		    };
+	    
+	    lhs.addListener(SWT.Resize, sash_listener );
+	    sash.addListener(SWT.Resize, sash_listener );
+	    */
+	    
+			// Text
+		
+		input_area = new Text( parent, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP | SWT.BORDER);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 2;
+		grid_data.heightHint = 30;
+		grid_data.horizontalIndent = 4;
+		input_area.setLayoutData(grid_data);
+			
+		input_area.setTextLimit( MAX_MSG_LENGTH );
+		
+		input_area.addKeyListener(
+			new KeyListener()
+			{
+				private LinkedList<String>	history 	= new LinkedList<String>();
+				private int					history_pos	= -1;
+				
+				private String				buffered_message = "";
+				
+				public void 
+				keyPressed(
+					KeyEvent e) 
+				{
+					if ( e.keyCode == SWT.CR ){
+				
+						e.doit = false;
+						
+						String message = input_area.getText().trim();
+						
+						if ( message.length() > 0 ){
+							
+							sendMessage(  message );
+							
+							history.addFirst( message );
+							
+							if ( history.size() > 32 ){
+								
+								history.removeLast();
+							}
+							
+							history_pos = -1;
+							
+							buffered_message = "";
+							
+							input_area.setText( "" );
+						}
+					}else if ( e.keyCode == SWT.ARROW_UP ){
+							
+						history_pos++;
+						
+						if ( history_pos < history.size()){
+						
+							if ( history_pos == 0 ){
+								
+								buffered_message = input_area.getText().trim();
+							}
+
+							String msg = history.get( history_pos );
+							
+							input_area.setText( msg );
+							
+							input_area.setSelection( msg.length());
+							
+						}else{
+							
+							history_pos = history.size() - 1;
+						}
+						
+						e.doit = false;
+						
+					}else if ( e.keyCode == SWT.ARROW_DOWN ){
+
+						history_pos--;
+
+						if ( history_pos >= 0 ){
+													
+							String msg = history.get( history_pos );
+							
+							input_area.setText( msg );
+							
+							input_area.setSelection( msg.length());
+							
+						}else{
+								
+							if ( history_pos == -1 ){
+								
+								input_area.setText( buffered_message );
+								
+								if ( buffered_message.length() > 0 ){
+	
+									input_area.setSelection( buffered_message.length());
+								
+									buffered_message = "";
+								}
+							}else{
+								
+								history_pos = -1;
+							}
+						}
+						
+						e.doit = false;
+						
+					}else{
+						
+						if ( e.stateMask == SWT.MOD1 ){
+
+							int key = e.character;
+							
+							if ( key <= 26 && key > 0 ){
+								
+								key += 'a'-1;
+							}
+
+							if ( key == 'a' ){
+								
+								input_area.selectAll();
+							}
+						}
+					}
+				}
+				
+				public void 
+				keyReleased(
+					KeyEvent e ) 
+				{
+				}
+			});
+		
+		ftux_ok = beta.getFTUXAccepted();
+		
+		if ( chat.isReadOnly()){
+		
+			input_area.setText( MessageText.getString( "azbuddy.dchat.ro" ));
+					
+			input_area.setEnabled( false );
+		
+		}else if ( !ftux_ok ){
+			
+			input_area.setEnabled( false );
+			
+		}else{
+		
+			input_area.setFocus();
+		}
+		
+		final boolean[] ftux_init_done = { false };
+		
+		beta.addFTUXStateChangeListener(
+			new FTUXStateChangeListener()
+			{
+				public void
+				stateChanged(
+					final boolean		_ftux_ok )
+				{
+					if ( ftux_stack.isDisposed()){
+						
+						beta.removeFTUXStateChangeListener( this );
+						
+					}else{
+						
+						Utils.execSWTThread(
+							new Runnable()
+							{
+								
+								public void 
+								run()
+								{
+									ftux_ok = _ftux_ok;
+									
+									stack_layout.topControl = ftux_ok?log_holder:ftux_holder;
+									
+									if ( ftux_init_done[0]){
+									
+										ftux_stack.layout( true, true );
+									}
+									
+									if ( !chat.isReadOnly()){
+										
+										input_area.setEnabled( ftux_ok );
+									}
+									
+									table_resort_required = true;
+									
+									updateTable( false );
+								}
+							});
+					}
+				}
+			});
+
+		if ( !chat.isReadOnly()){
+			
+			drop_targets = new DropTarget[]{
+				new DropTarget(log, DND.DROP_COPY),
+				new DropTarget(input_area, DND.DROP_COPY)
+			};
+			
+			for ( DropTarget drop_target: drop_targets ){
+				
+				drop_target.setTransfer(new Transfer[] {
+					URLTransfer.getInstance(),
+					FileTransfer.getInstance(),
+					TextTransfer.getInstance(),
+				});
+		
+				drop_target.addDropListener(new DropTargetAdapter() {
+					public void dropAccept(DropTargetEvent event) {
+						event.currentDataType = URLTransfer.pickBestType(event.dataTypes,
+								event.currentDataType);
+					}
+		
+					public void dragEnter(DropTargetEvent event) {
+					}
+		
+					public void dragOperationChanged(DropTargetEvent event) {
+					}
+		
+					public void dragOver(DropTargetEvent event) {
+	
+						if ((event.operations & DND.DROP_LINK) > 0)
+							event.detail = DND.DROP_LINK;
+						else if ((event.operations & DND.DROP_COPY) > 0)
+							event.detail = DND.DROP_COPY;
+						else if ((event.operations & DND.DROP_DEFAULT) > 0)
+							event.detail = DND.DROP_COPY;
+		
+		
+						event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_SCROLL | DND.FEEDBACK_EXPAND;
+					}
+		
+					public void dragLeave(DropTargetEvent event) {
+					}
+		
+					public void drop(DropTargetEvent event) {
+						handleDrop( event.data );				
+					}
+				});
+			}
+		}
+		
+		ftux_init_done[0] = true;
+		
+		Control[] focus_controls = { log, input_area, buddy_table, nickname, shared_nick_button };
+		
+		Listener focus_listener = new Listener() {
+			
+			public void handleEvent(Event event) {
+				activate();
+			}
+		};
+		
+		for ( Control c: focus_controls ){
+			
+			c.addListener( SWT.FocusIn, focus_listener );
+		}
+
+		BuddyPluginBeta.ChatParticipant[] existing_participants = chat.getParticipants();
+		
+		synchronized( participants ){
+			
+			participants.addAll( Arrays.asList( existing_participants ));
+		}
+		
+		table_resort_required = true;
+		
+		updateTable( false );
+		
+		BuddyPluginBeta.ChatMessage[] history = chat.getHistory();
+				
+		logChatMessages( history );
+		
+		chat.addListener( this );
+		
+		build_complete	= true;
+		
+		if ( can_popout && !ftux_ok && !auto_ftux_popout_done ){
+			
+			auto_ftux_popout_done = true;
+			
+			try{
+				new BuddyPluginViewBetaChat( view, plugin, chat.getClone());
+				
+			}catch( Throwable e ){
+				
+			}
+		}
+	}
+	
+	private void
+	buildParticipantMenu(
+		final Menu					menu,
+		final List<ChatParticipant>	participants )
+	{
+		boolean	can_ignore 	= false;
+		boolean	can_listen	= false;
+		boolean	can_pin		= false;
+		boolean	can_unpin	= false;
+		
+		boolean	can_spam	= false;
+		boolean	can_unspam	= false;
+				
+		for ( ChatParticipant participant: participants ){
+						
+			if ( DEBUG_ENABLED ){
+				
+				System.out.println( participant.getName() + "/" + participant.getAddress());
+				
+				List<ChatMessage>	messages = participant.getMessages();
+				
+				for ( ChatMessage msg: messages ){
+					
+					System.out.println( "    " + msg.getTimeStamp() + ", " + msg.getAddress() + " - " + msg.getMessage());
+				}
+			}
+			
+			if ( participant.isIgnored()){
+			
+				can_listen = true;
+				
+			}else{
+				
+				can_ignore = true;
+			}
+			
+			if ( participant.isPinned()){
+				
+				can_unpin = true;
+				
+			}else{
+				
+				if ( !participant.isMe()){
+				
+					can_pin = true;
+				}
+			}
+			
+			if ( participant.isSpammer()){
+				
+				can_unspam = true;
+				
+			}else{
+				
+				can_spam |= participant.canSpammer();
+			}
+		}
+		
+		final MenuItem ignore_item = new MenuItem(menu, SWT.PUSH);
+		
+		ignore_item.setText( lu.getLocalisedMessageText( "label.mute" ) );
+
+		ignore_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent e) 
+				{
+					boolean	changed = false;
+					
+					for ( ChatParticipant participant: participants ){
+						
+						if ( !participant.isIgnored()){
+							
+							participant.setIgnored( true );
+							
+							setProperties( participant );
+							
+							changed = true;
+						}
+					}
+					
+					if ( changed ){
+						
+						messagesChanged();
+					}
+				};
+			});
+		
+		ignore_item.setEnabled( can_ignore );
+		
+		final MenuItem listen_item = new MenuItem(menu, SWT.PUSH);
+		
+		listen_item.setText(lu.getLocalisedMessageText( "label.listen" ) );
+
+		listen_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent e) 
+				{
+					boolean	changed = false;
+					
+					for ( ChatParticipant participant: participants ){
+						
+						if ( participant.isIgnored()){
+							
+							participant.setIgnored( false );
+							
+							setProperties( participant );
+							
+							changed = true;
+						}
+					}
+					
+					if ( changed ){
+						
+						messagesChanged();
+					}
+				};
+			});
+		
+		listen_item.setEnabled( can_listen );
+		
+			// spam
+		
+		final MenuItem spam_item = new MenuItem(menu, SWT.PUSH);
+		
+		spam_item.setText(lu.getLocalisedMessageText( "label.spam" ) );
+
+		spam_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent e) 
+				{
+					boolean	changed = false;
+					
+					for ( ChatParticipant participant: participants ){
+						
+						if ( participant.canSpammer()){
+							
+							participant.setSpammer( true );
+							
+							setProperties( participant );
+							
+							changed = true;
+						}
+					}
+					
+					if ( changed ){
+						
+						messagesChanged();
+					}
+				};
+			});
+		
+		spam_item.setEnabled( can_spam );
+		
+		final MenuItem unspam_item = new MenuItem(menu, SWT.PUSH);
+		
+		unspam_item.setText(lu.getLocalisedMessageText( "label.not.spam" ) );
+
+		unspam_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent e) 
+				{
+					boolean	changed = false;
+					
+					for ( ChatParticipant participant: participants ){
+						
+						if ( participant.isSpammer()){
+							
+							participant.setSpammer( false );
+							
+							setProperties( participant );
+							
+							changed = true;
+						}
+					}
+					
+					if ( changed ){
+						
+						messagesChanged();
+					}
+				};
+			});
+		
+		unspam_item.setEnabled( can_unspam );
+		
+			// pin
+		
+		new MenuItem(menu, SWT.SEPARATOR );
+		
+		final MenuItem pin_item = new MenuItem(menu, SWT.PUSH);
+		
+		pin_item.setText( lu.getLocalisedMessageText( "label.pin" ) );
+
+		pin_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent e) 
+				{
+					for ( ChatParticipant participant: participants ){
+						
+						if ( !participant.isPinned()){
+							
+							if ( !participant.isMe()){
+								
+								participant.setPinned( true );
+								
+								setProperties( participant );
+							}
+						}
+					}
+				};
+			});
+		
+		pin_item.setEnabled( can_pin );
+		
+		final MenuItem unpin_item = new MenuItem(menu, SWT.PUSH);
+		
+		unpin_item.setText( lu.getLocalisedMessageText( "label.unpin" ) );
+
+		unpin_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent e) 
+				{
+					for ( ChatParticipant participant: participants ){
+						
+						if ( participant.isPinned()){
+							
+							participant.setPinned( false );
+							
+							setProperties( participant );
+						}
+					}
+				};
+			});
+		
+		unpin_item.setEnabled( can_unpin );
+		
+		if ( !chat.isPrivateChat()){
+			
+			new MenuItem(menu, SWT.SEPARATOR );
+			
+			final MenuItem private_chat_item = new MenuItem(menu, SWT.PUSH);
+			
+			private_chat_item.setText( lu.getLocalisedMessageText( "label.private.chat" ) );
+
+			final byte[]	chat_pk = chat.getPublicKey();
+
+			private_chat_item.addSelectionListener(
+				new SelectionAdapter() 
+				{
+					public void 
+					widgetSelected(
+						SelectionEvent e) 
+					{
+						for ( ChatParticipant participant: participants ){
+							
+							if ( TEST_LOOPBACK_CHAT || !Arrays.equals( participant.getPublicKey(), chat_pk )){
+								
+								try{
+									ChatInstance chat = participant.createPrivateChat();
+								
+									new BuddyPluginViewBetaChat( view, plugin, chat);
+									
+								}catch( Throwable f ){
+									
+									Debug.out( f );
+								}
+							}
+						}
+					};
+				});
+				
+			boolean	pc_enable = false;
+			
+			if ( chat_pk != null ){
+				
+				for ( ChatParticipant participant: participants ){
+					
+					if ( !Arrays.equals( participant.getPublicKey(), chat_pk )){
+						
+						pc_enable = true;
+					}
+				}
+			}
+			
+			private_chat_item.setEnabled( pc_enable || TEST_LOOPBACK_CHAT );
+		}
+		
+		if ( participants.size() == 1 ){
+			
+			new MenuItem(menu, SWT.SEPARATOR );
+	
+			final MenuItem mi_copy_clip = new MenuItem( menu, SWT.PUSH );
+			
+			mi_copy_clip.setText( lu.getLocalisedMessageText( "label.copy.to.clipboard" ));
+	
+			mi_copy_clip.addSelectionListener(
+				new SelectionAdapter() {
+					
+					public void 
+					widgetSelected(
+						SelectionEvent e ) 
+					{
+						ClipboardCopy.copyToClipBoard( participants.get(0).getName( true ));
+					}
+				});
+		}
+	}
+	
+	private ChatParticipant
+	setItemData(
+		TableItem		item )
+	{
+		int index = buddy_table.indexOf(item);
+		
+		if ( index < 0 || index >= participants.size()){
+			
+			return( null );
+		}
+		
+		ChatParticipant	participant = (BuddyPluginBeta.ChatParticipant)participants.get(index);
+		
+		item.setData( participant );
+		
+		item.setText(0, participant.getName( ftux_ok ));		
+		
+		setProperties( item, participant );	
+		
+		return( participant );
+	}
+	
+	private void
+	setProperties(
+		ChatParticipant		p )
+	{
+		for ( TableItem ti: buddy_table.getItems()){
+			
+			if ( ti.getData() == p ){
+				
+				setProperties( ti, p );
+			}
+		}
+	}
+	
+	private void
+	setProperties(
+		TableItem			item,
+		ChatParticipant		p )
+	{
+		if ( p.isIgnored() || p.isSpammer()){
+		
+			item.setForeground( 0, Colors.grey );
+			
+		}else{
+			
+			if ( p.isPinned()){
+			
+				item.setForeground( 0, Colors.fadedGreen );
+				
+			}else{
+			
+				if ( p.isMe()){
+					
+					item.setForeground( 0, Colors.fadedGreen );
+					
+					item.setFont( 0, italic_font );
+					
+				}else if ( p.isNickClash()){
+					
+					item.setForeground( 0, Colors.red );
+					
+				}else{
+					
+					if ( p.hasNickname()){
+						
+						item.setForeground( 0, Colors.blues[Colors.FADED_DARKEST] );
+						
+					}else{
+						
+						item.setForeground( 0, Colors.black );
+					}
+				}
+			}
+		}
+	}
+	
+	protected void
+	addDisposeListener(
+		final DisposeListener	listener )
+	{
+		if ( shell != null ){
+			
+			if ( shell.isDisposed()){
+				
+				listener.widgetDisposed( null );
+				
+			}else{
+									
+				shell.addDisposeListener( listener );
+			}
+		}
+	}
+	
+	private void
+	updateTableHeader()
+	{
+		int	active 	= buddy_table.getItemCount();
+		int online	= chat.getEstimatedNodes();
+		
+		String msg = 
+			lu.getLocalisedMessageText( 
+				"azbuddy.dchat.user.status",
+					new String[]{
+						online >=100?"100+":String.valueOf( online ),
+						String.valueOf( active )
+					});
+			
+		table_header.setText( msg );
+	}
+	
+	protected void
+	updateTable(
+		boolean	async )
+	{
+		if ( async ){
+			
+			if ( !buddy_table.isDisposed()){
+
+				Utils.execSWTThread(
+					new Runnable()
+					{
+						public void
+						run()
+						{
+							if ( buddy_table.isDisposed()){
+
+								return;
+							}
+							
+							updateTable( false );
+							
+							updateTableHeader();
+						}
+					});
+			}					
+		}else{
+			
+			if ( table_resort_required ){
+				
+				table_resort_required = false;
+				
+				sortParticipants();
+			}
+			
+			buddy_table.setItemCount( participants.size());
+			buddy_table.clearAll();
+			buddy_table.redraw();
+		}
+	}
+	
+	private void
+	handleDrop(
+		Object	payload )
+	{
+		if ( payload instanceof String[]){
+			
+			String[]	files = (String[])payload;
+			
+			for ( String file: files ){
+			
+				File f = new File( file );
+
+				if ( f.exists()){
+				
+					dropFile( f );
+				}
+			}
+		}else if ( payload instanceof String ){
+			
+			String stuff = (String)payload;
+			
+			if ( stuff.startsWith( "DownloadManager\n" ) ||stuff.startsWith( "DiskManagerFileInfo\n" )){
+				
+				String[]	bits =  Constants.PAT_SPLIT_SLASH_N.split(stuff);
+				
+				for (int i=1;i<bits.length;i++){
+					
+					String	hash_str = bits[i];
+					
+					int	pos = hash_str.indexOf(';');
+					
+					try{
+
+						if ( pos == -1 ){
+							
+							byte[]	 hash = Base32.decode( bits[i] );
+			
+							Download download = AzureusCoreFactory.getSingleton().getPluginManager().getDefaultPluginInterface().getShortCuts().getDownload(hash);
+							
+							dropDownload( download );
+										
+						}else{
+							
+							String[] files = hash_str.split(";");
+							
+							byte[]	 hash = Base32.decode( files[0].trim());
+							
+							DiskManagerFileInfo[] dm_files = AzureusCoreFactory.getSingleton().getPluginManager().getDefaultPluginInterface().getShortCuts().getDownload(hash).getDiskManagerFileInfo();
+							
+							for (int j=1;j<files.length;j++){
+								
+								DiskManagerFileInfo dm_file = dm_files[Integer.parseInt(files[j].trim())];
+								
+								dropDownloadFile( dm_file );
+							}
+						}
+					}catch( Throwable e ){
+						
+						Debug.out( "Failed to get download for hash " + bits[1] );
+					}
+				}
+			}else if ( stuff.startsWith( "TranscodeFile\n" )){
+				
+				String[]	bits =  Constants.PAT_SPLIT_SLASH_N.split(stuff);
+				
+				for (int i=1;i<bits.length;i++){
+					
+					File f = new File( bits[i] );
+
+					if ( f.isFile()){
+					
+						dropFile( f );
+					}
+				}
+			}else{
+				
+				String lc_stuff = stuff.toLowerCase( Locale.US );
+				
+				if ( 	lc_stuff.startsWith( "http:" ) || 
+						lc_stuff.startsWith( "https:" ) ||
+						lc_stuff.startsWith( "magnet: ")){
+			
+					dropURL( stuff );
+				}
+			}
+		}else if ( payload instanceof URLTransfer.URLType ){
+			
+			String url = ((URLTransfer.URLType)payload).linkURL;
+			
+			if ( url != null ){
+				
+				dropURL( url );
+			}
+		}
+	}
+	
+	private void
+	dropURL(
+		String	str )
+	{
+		input_area.setText( input_area.getText() + str );
+	}
+	
+	private void
+	dropFile(
+		final File	file )
+	{
+		try{			
+			if ( file.exists() && file.canRead()){
+				
+				new AEThread2( "share async" )
+				{
+					public void
+					run()
+					{
+						PluginInterface pi = plugin.getPluginInterface();
+						
+						Map<String,String>	properties = new HashMap<String, String>();
+						
+						String[]	networks;
+						
+						if ( chat.isAnonymous()){
+							
+							networks = AENetworkClassifier.AT_NON_PUBLIC;
+							
+						}else{
+							
+							networks = AENetworkClassifier.AT_NETWORKS;
+						}
+						
+						String networks_str = "";
+						
+						for ( String net: networks ){
+							
+							networks_str += (networks_str.length()==0?"":",") + net;
+						}
+						
+						properties.put( ShareManager.PR_PERSONAL, "true" );
+						properties.put( ShareManager.PR_NETWORKS, networks_str );
+						properties.put( ShareManager.PR_USER_DATA, "buddyplugin:share" );
+						
+						Torrent 	torrent;
+
+						try{
+							if ( file.isFile()){
+								
+								ShareResourceFile srf = pi.getShareManager().addFile( file, properties );
+								
+								torrent = srf.getItem().getTorrent();
+								
+							}else{
+								
+								ShareResourceDir srd = pi.getShareManager().addDir( file, properties );
+								
+								torrent = srd.getItem().getTorrent();
+							}	
+													
+							final Download download = pi.getPluginManager().getDefaultPluginInterface().getShortCuts().getDownload( torrent.getHash());
+	
+							if ( download == null ){
+								
+								throw( new Exception( "Download no longer exists" ));
+								
+							}
+							Utils.execSWTThread(
+								new Runnable() {
+									
+									public void 
+									run()
+									{
+										dropDownload( download );
+
+									}
+								});
+							
+						}catch( Throwable e ){
+							
+							dropFailed( file.getName(), e );
+						}
+					}
+				}.start();
+	
+			}else{
+				
+				throw( new Exception( "File '" + file + "' does not exist or is not accessible" ));
+			}
+			
+		}catch( Throwable e ){
+			
+			dropFailed( file.getName(), e );
+		}
+	}
+	
+	private void
+	dropDownload(
+		Download		download )
+	{		
+		String magnet = UrlUtils.getMagnetURI( download, 80 );
+		
+		InetSocketAddress address = chat.getMyAddress();
+		
+		if ( address != null ){
+			
+			String address_str = AddressUtils.getHostAddress(address) + ":" + address.getPort();
+			
+			String arg = "&xsource=" + UrlUtils.encode( address_str );
+			
+			if ( magnet.length() + arg.length() < MAX_MSG_LENGTH ){
+				
+				magnet += arg;
+			}
+		}
+		
+		if ( magnet.length() < MAX_MSG_LENGTH-10 ){
+					
+			magnet += "[[$dn]]";
+		}
+		
+		plugin.getBeta().tagDownload( download );
+		
+		download.setForceStart( true );
+		
+		input_area.setText( input_area.getText() + magnet );
+	}
+	
+	private void
+	dropDownloadFile(
+		DiskManagerFileInfo		file )
+	{
+		try{
+			Download download = file.getDownload();
+			
+			if ( download.getTorrent().isSimpleTorrent()){
+				
+				dropDownload( download );
+				
+				return;
+			}
+			
+			File target = file.getFile( true );
+			
+			if (	 target.exists() && 
+					( file.getDownloaded() == file.getLength() ||
+					( download.isComplete() && !file.isSkipped()))){	// just in case cached file completion is borked
+				
+				dropFile( target );
+				
+			}else{
+				
+				throw( new Exception( "File is incomplete or missing" ));
+			}
+		}catch( Throwable e ){
+			
+			dropFailed( file.getFile(true).getName(), e );
+		}
+	}
+	
+	private void
+	dropFailed(
+		String		content,
+		Throwable 	e )
+	{
+		UIManager ui_manager = plugin.getPluginInterface().getUIManager();
+				
+		String details = 
+			MessageText.getString( 
+				"azbuddy.dchat.share.fail.msg",
+				new String[]{ content, Debug.getNestedExceptionMessage( e ) });
+			
+		ui_manager.showMessageBox(
+				"azbuddy.dchat.share.fail.title",
+				"!" + details + "!",
+				UIManagerEvent.MT_OK );
+	}
+	
+	protected void
+	close()
+	{
+		if ( shell != null ){
+		
+			shell.dispose();
+		}
+	}
+	
+	protected void
+	closed()
+	{
+		chat.removeListener( this );
+		
+		chat.destroy();
+		
+		view.unregisterUI( chat );
+	}
+	
+	public void 
+	stateChanged(
+		final boolean avail ) 
+	{
+		if ( buddy_table.isDisposed()){
+			
+			return;
+		}
+	
+		Utils.execSWTThread(
+			new Runnable()
+			{
+				public void
+				run()
+				{
+					if ( buddy_table.isDisposed()){
+						
+						return;
+					}
+					
+					input_area.setEnabled( avail );
+					
+						// update as key may now be available
+					
+					nickname.setMessage( chat.getDefaultNickname());
+				}
+			});
+	}
+	
+	public void 
+	updated() 
+	{
+		if ( status.isDisposed()){
+			
+			return;
+		}
+	
+		Utils.execSWTThread(
+			new Runnable()
+			{
+				public void
+				run()
+				{
+					if ( status.isDisposed()){
+						
+						return;
+					}
+				
+					status.setText( chat.getStatus());
+					
+					boolean	is_shared = chat.isSharedNickname();
+					
+					if ( is_shared != shared_nick_button.getSelection()){
+						
+						shared_nick_button.setSelection( is_shared );
+					}
+						
+					if ( !nickname.isFocusControl()){
+						
+						String nick = nickname.getText().trim();
+							
+						if ( !chat.getNickname().equals( nick )){
+								
+							nickname.setText( chat.getNickname());
+						}
+					}
+					
+					if ( table_resort_required ){
+						
+						updateTable( false );
+					}
+					
+					updateTableHeader();
+				}
+			});
+	}
+	
+	private void
+	sortParticipants()
+	{
+		Collections.sort(
+			participants,
+			new Comparator<ChatParticipant>()
+			{
+				private Comparator<String> comp = new FormattersImpl().getAlphanumericComparator( true );
+				
+				public int 
+				compare(
+					ChatParticipant p1, 
+					ChatParticipant p2 ) 
+				{
+					boolean	b_p1 = p1.hasNickname();
+					boolean	b_p2 = p2.hasNickname();
+					
+					if ( b_p1 == b_p2 ){
+					
+						return( comp.compare( p1.getName( ftux_ok ), p2.getName( ftux_ok )));
+						
+					}else if ( b_p1 ){
+						
+						return( -1 );
+						
+					}else{
+						
+						return( 1 );
+					}
+				}
+			});
+	}
+	
+	public void
+	participantAdded(
+		ChatParticipant		participant )
+	{
+		synchronized( participants ){
+			
+			participants.add( participant );
+			
+			table_resort_required = true;
+		}
+		
+		updateTable( true );
+	}
+	
+	public void
+	participantChanged(
+		final ChatParticipant		participant )
+	{
+		if ( !buddy_table.isDisposed()){
+
+			Utils.execSWTThread(
+				new Runnable()
+				{
+					public void
+					run()
+					{
+						if ( buddy_table.isDisposed()){
+
+							return;
+						}
+						
+						TableItem[] items = buddy_table.getItems();
+						
+						String	name = participant.getName( ftux_ok );
+						
+						for ( TableItem item: items ){
+							
+							if ( item.getData() == participant ){
+								
+								setProperties( item, participant );
+								
+								String old_name = item.getText(0);
+								
+								if ( !old_name.equals( name )){
+								
+									item.setText( 0, name );
+									
+									table_resort_required = true;
+								}
+							}
+						}
+					}
+				});
+		}			
+	}
+	
+	public void
+	participantRemoved(
+		ChatParticipant		participant )
+	{
+		synchronized( participants ){
+			
+			participants.remove( participant );
+			
+			participant_last_message_map.remove( participant );
+		}
+		
+		updateTable( true );
+	}
+	
+	protected void
+	sendMessage(
+		String		text )
+	{
+		//logChatMessage( plugin.getNickname(), Colors.green, text );
+		
+		try{
+				// decode escaped unicode chars
+			
+			Pattern p = Pattern.compile("(?i)\\\\u([\\dabcdef]{4})");
+
+			Matcher m = p.matcher( text );
+
+			boolean result = m.find();
+
+			if ( result ){
+
+				StringBuffer sb = new StringBuffer();
+
+		    	while( result ){
+		    		
+		    		 String str = m.group(1);
+		    		 
+		    		 int unicode = Integer.parseInt( str, 16 );
+		    		 
+		    		 m.appendReplacement(sb, String.valueOf((char)unicode));
+		    		 
+		    		 result = m.find(); 
+		    	 }
+
+				m.appendTail(sb);
+
+				text = sb.toString();
+			}
+		}catch( Throwable e ){
+		}
+		
+		chat.sendMessage( text, new HashMap<String, Object>());
+	}
+	
+	private String
+	expand(
+		Map<String,String>	params,
+		String				str,
+		boolean				url_decode )
+	{
+		int	pos = 0;
+		
+		String result = "";
+		
+		while( true ){
+			
+			int new_pos = str.indexOf('$', pos );
+			
+			if ( new_pos == -1 ){
+				
+				result += str.substring( pos );
+				
+				break;
+			}
+			
+			result += str.substring( pos, new_pos );
+			
+			int end_pos = str.length();
+			
+			for ( int i=new_pos+1;i<end_pos;i++){
+				
+				char c = str.charAt( i );
+				
+				if ( !( Character.isLetterOrDigit(c) || c == '_' )){
+					
+					end_pos = i;
+					
+					break;
+				}
+			}
+			
+			String param = str.substring( new_pos+1, end_pos );
+			
+			String value = params.get( param );
+			
+			if ( value == null ){
+		
+				pos = new_pos + 1;
+				
+				result += "$";
+				
+			}else{
+				
+				if ( url_decode ){
+					
+					result += UrlUtils.decode( value );
+					
+				}else{
+					
+					result += value;
+				}
+				
+				pos = end_pos;
+			}
+		}
+		
+		return( result );
+	}
+	
+	public void
+	messageReceived(
+		final ChatMessage	message,
+		boolean				sort_outstanding )
+	{
+		if ( sort_outstanding ){
+		
+				// we'll pick things up on the 'messagesChanged' callback after the sort
+			
+			return;
+		}
+		
+		if ( !log.isDisposed()){
+
+			Utils.execSWTThread(
+				new Runnable()
+				{
+					public void
+					run()
+					{
+						if ( log.isDisposed()){
+
+							return;
+						}
+													
+						logChatMessage( message );
+					}
+				});
+		}
+	}
+	
+	public void 
+	messagesChanged() 
+	{
+		if ( !log.isDisposed()){
+
+			Utils.execSWTThread(
+				new Runnable()
+				{
+					public void
+					run()
+					{
+						if ( log.isDisposed()){
+
+							return;
+						}
+						
+						try{								
+							resetChatMessages();
+							
+							BuddyPluginBeta.ChatMessage[] history = chat.getHistory();
+															
+							logChatMessages( history );
+							
+						}catch( Throwable e ){
+							
+							Debug.printStackTrace(e);
+						}
+					}
+				});
+		}
+	}
+	
+	private String	previous_says 				= null;
+	private int		previous_says_mt			= -1;
+	private long	last_seen_message			= -1;	
+	private long	last_seen_message_pending	= -1;
+	
+	private void
+	resetChatMessages()
+	{
+		log.setText( "" );
+		
+		messages.clear();
+		
+		previous_says	= null;
+		
+		synchronized( participants ){
+			
+			participant_last_message_map.clear();
+		}
+	}
+	
+	private void
+	logChatMessage(
+		ChatMessage		message )
+	{
+		logChatMessages( new ChatMessage[]{ message } );
+	}
+	
+	private final SimpleDateFormat time_format1 	= new SimpleDateFormat( "HH:mm" );
+	private final SimpleDateFormat time_format2a 	= new SimpleDateFormat( "EE h" );
+	private final SimpleDateFormat time_format2b 	= new SimpleDateFormat( "a" );
+	private final SimpleDateFormat time_format3 	= new SimpleDateFormat( "dd/MM" );
+
+	private String
+	getChatTimestamp(
+		long		now,
+		long		time )
+	{
+		long 	age 	= now - time;
+		Date	date	= new Date( time );
+		
+		if ( age < 24*60*60*1000L ){
+			
+			return( time_format1.format( date ));
+			
+		}else if ( age < 7*24*60*60*1000L ){
+			
+			return( time_format2a.format( date ) + time_format2b.format( date ).toLowerCase());
+
+		}else{
+			
+			return( time_format3.format( date ));
+		}
+	}
+	
+	private void
+	logChatMessages(
+		ChatMessage[]		all_messages )
+	{	
+		long	now = SystemTime.getCurrentTime();
+		
+		int	existing_length = log.getText().length();
+		
+		StringBuffer	appended = new StringBuffer( 2048 );
+		
+		List<StyleRange>	new_ranges = new ArrayList<StyleRange>();
+		
+		ChatMessage	last_message_not_ours 		= null;
+		
+		boolean	ignore_ratings = beta.getHideRatings();
+		
+		for ( ChatMessage message: all_messages ){
+			
+			if ( messages.containsKey( message )){
+				
+				continue;
+			}
+						
+			String	original_msg		= message.getMessage();
+
+			if ( !message.isIgnored() && original_msg.length() > 0 ){
+				
+				if ( ignore_ratings ){
+					
+					int origin = message.getFlagOrigin();
+					
+					if ( origin == BuddyPluginBeta.FLAGS_MSG_ORIGIN_RATINGS ){
+						
+						continue;
+					}
+				}
+				
+				long time = message.getTimeStamp();
+
+				ChatParticipant participant = message.getParticipant();
+
+				boolean	is_me = participant.isMe();
+				
+				if ( !is_me ){
+					
+					last_message_not_ours		= message;
+				}
+				
+				int	overall_start = appended.length();
+				
+				String	nick 	= message.getNickName();
+				
+				int	message_type = message.getMessageType();
+								
+				Color colour = Colors.blues[Colors.FADED_DARKEST];
+				
+				if ( message_type ==  ChatMessage.MT_INFO ){
+					
+					colour = Colors.grey;
+					
+				}else if ( message_type ==  ChatMessage.MT_ERROR ){
+						
+					colour = Colors.red;		
+					
+				}else if ( participant.isPinned() || is_me ){
+					
+					colour = Colors.fadedGreen;
+					
+				}else if ( message.isNickClash()){
+					
+					colour = Colors.red;
+				}
+								
+				String stamp = getChatTimestamp( now, time );
+				
+				ChatMessage	last_message;
+				
+				synchronized( participants ){
+					
+					last_message = participant_last_message_map.get( participant );
+					
+					participant_last_message_map.put( participant, message );
+				}
+
+				String 	says;
+				int		stamp_len;
+				
+				int	was_len = 0;
+				
+				if ( message_type != ChatMessage.MT_NORMAL ){
+					
+					says = "[" + stamp + "]";
+					
+					stamp_len = says.length();
+					
+				}else{
+					
+					says = "[" + stamp + "] " + (nick.length()>20?(nick.substring(0,16) + "..."):nick);
+			
+					stamp_len = stamp.length() + 3;
+					
+					if ( last_message != null && !participant.isMe()){
+						
+						String last_nick = last_message.getNickName();
+						
+						if ( !nick.equals(last_nick)){
+							
+							String was = " (was " + (last_nick.length()>20?(last_nick.substring(0,16) + "..."):last_nick) + ")";
+							
+							says += was;
+							
+							was_len = was.length();
+						}
+					}
+				}
+				
+				says += message_type == ChatMessage.MT_NORMAL?"\n":" ";
+				
+				if ( previous_says == null || previous_says_mt != message_type || !previous_says.equals( says )){
+					
+					previous_says 		= says;
+					previous_says_mt	= message_type;
+					
+					int	start = existing_length + appended.length();
+							
+					appended.append( says );
+					
+					{
+						StyleRange styleRange = new StyleRange();
+						styleRange.start = start;
+						styleRange.length = stamp_len;
+						styleRange.foreground = Colors.grey;
+						
+						if ( participant.isMe()){
+							
+							styleRange.font = italic_font;
+						}
+						
+						new_ranges.add( styleRange);
+					}
+					
+					if ( colour != Colors.black ){
+						
+						int rem = says.length() - stamp_len;
+						
+						if ( rem > 0 ){
+							StyleRange styleRange = new StyleRange();
+							styleRange.start = start + stamp_len;
+							styleRange.length = rem - was_len;
+							styleRange.foreground = colour;
+							styleRange.data = participant;
+							
+							if ( participant.isMe()){
+								
+								styleRange.font = italic_font;
+							}
+							
+							new_ranges.add( styleRange);
+						}
+					}
+				}
+				
+				final int start = existing_length + appended.length();
+				
+				String	msg = original_msg;
+				
+				try{
+					{
+						List<Object>		segments = new ArrayList<Object>();
+						
+						int	pos = 0;
+						
+						while( true ){
+							
+							int old_pos = pos;
+							
+							pos = original_msg.indexOf( ':', old_pos );
+							
+							if ( pos == -1 ){
+								
+								String tail = original_msg.substring( old_pos );
+								
+								if ( tail.length() > 0 ){
+									
+									segments.add( tail );
+								}
+								
+								break;
+							}
+							
+							boolean	was_url = false;
+							
+							String	protocol = "";
+							
+							for (int i=pos-1; i>=0; i-- ){
+								
+								char c = original_msg.charAt(i);
+								
+								if ( !Character.isLetterOrDigit( c )){
+									
+									if ( c == '"' ){
+										
+										protocol = c + protocol;
+									}
+									
+									break;
+								}
+								
+								protocol = c + protocol;
+							}
+							
+							if ( protocol.length() > 0 ){
+								
+								char term_char = ' ';
+								
+								if ( protocol.startsWith( "\"" )){
+									
+									term_char = '"';
+								}
+								
+								int	url_start 	= pos - protocol.length();
+								int	url_end 	= original_msg.length();
+								
+								for ( int i=pos+1;i<url_end;i++){
+									
+									char c = original_msg.charAt( i );
+									
+									if ( c == term_char || ( term_char == ' ' && Character.isWhitespace( c ))){
+										
+										url_end = term_char==' '?i:(i+1);
+										
+										break;
+									}
+								}
+									
+								if ( url_end > pos+1 && !Character.isDigit( protocol.charAt(0))){
+									
+									try{									
+										String url_str = protocol + original_msg.substring( pos, url_end );
+								
+										if ( url_str.startsWith( "\"" ) && url_str.endsWith( "\"" )){
+											
+											url_str = url_str.substring( 1, url_str.length()-1 );
+										}
+										
+										URL	url = new URL( url_str );
+										
+										if ( url_start > old_pos ){
+											
+											segments.add( original_msg.substring( old_pos, url_start ));
+										}
+										
+										segments.add( url );
+										
+										was_url = true;
+										
+										pos	= url_end;
+										
+									}catch( Throwable e ){
+										
+									}
+								}
+							}
+							
+							if ( !was_url ){
+								
+								pos++;
+								
+								segments.add( original_msg.substring( old_pos, pos ) );
+							}
+						}
+						
+						if ( segments.size() > 1 ){
+							
+							List<Object>	temp = new ArrayList<Object>( segments.size());
+						
+							String	str = "";
+							
+							for ( Object obj: segments ){
+								
+								if ( obj instanceof String ){
+							
+									str += obj;
+									
+								}else{
+									
+									if ( str.length() > 0 ){
+										
+										temp.add( str );
+									}
+									
+									str = "";
+									
+									temp.add( obj );
+								}
+							}
+						
+							if ( str.length() > 0 ){
+								
+								temp.add( str );
+							}
+							
+							segments = temp;
+						}
+											
+						Map<String,String>	params = new HashMap<String,String>();
+						
+						for ( int i=0;i<segments.size(); i++ ){
+							
+							Object obj = segments.get(i);
+						
+							if ( obj instanceof URL ){
+								
+								params.clear();
+								
+								String str = ((URL)obj).toExternalForm();
+								
+								int	qpos = str.indexOf( '?' );
+								
+								if ( qpos > 0 ){
+									
+									int	hpos = str.lastIndexOf( "[[" );
+	
+									String[]	bits = str.substring( qpos+1, hpos==-1?str.length():hpos ).split( "&" );
+									
+									for ( String bit: bits ){
+										
+										String[] temp = bit.split( "=", 2 );
+										
+										if ( temp.length == 2 ){
+											
+											params.put( temp[0], temp[1] );
+										}
+									}
+																
+									if ( hpos > 0 && str.endsWith( "]]" )){
+										
+										str = 	str.substring( 0, hpos ) + 
+												"[[" +
+												expand( params, str.substring( hpos+2, str.length()-2 ), false ) +
+												"]]";
+										
+										try{
+											segments.set( i, new URL( str ));
+											
+										}catch( Throwable e ){
+											
+											Debug.out( e );
+										}
+									}
+								}else{
+									
+									int	hpos = str.lastIndexOf( "[[" );
+																								
+									if ( hpos > 0 && str.endsWith( "]]" )){
+										
+										str = 	str.substring( 0, hpos ) + 
+												"[[" +
+												str.substring( hpos+2, str.length()-2 ) +
+												"]]";
+										
+										try{
+											segments.set( i, new URL( str ));
+											
+										}catch( Throwable e ){
+											
+											Debug.out( e );
+										}
+									}
+								}
+							}else{
+								
+								String str = (String)obj;
+								
+								if ( params.size() > 0 ){
+									
+									segments.set( i, expand( params, str, true ));
+								}
+							}
+						}
+							
+						StringBuffer sb = new StringBuffer( 1024 );
+						
+						for ( Object obj: segments ){
+							
+							if ( obj instanceof URL ){
+							
+								sb.append( "\"" + ((URL)obj).toExternalForm() + "\"" );
+								
+							}else{
+								
+								sb.append((String)obj);
+							}
+						}
+						
+						msg = sb.toString();
+					}
+					
+					{	
+							// should rewrite this one day to use the segments above directly... We'd need to handle URLs in expansions though
+						
+						int	next_style_start = start;
+						
+						int	pos = 0;
+						
+						while( pos < msg.length()){
+							
+							pos = msg.indexOf( ':', pos );
+							
+							if ( pos == -1 ){
+								
+								break;
+							}
+							
+							String	protocol = "";
+							
+							for (int i=pos-1; i>=0; i-- ){
+								
+								char c = msg.charAt(i);
+								
+								if ( !Character.isLetterOrDigit( c )){
+									
+									if ( c == '"' ){
+										
+										protocol = c + protocol;
+									}
+									
+									break;
+								}
+								
+								protocol = c + protocol;
+							}
+							
+							if ( protocol.length() > 0 ){
+								
+								char term_char = ' ';
+								
+								if ( protocol.startsWith( "\"" )){
+									
+									term_char = '"';
+								}
+								
+								int	url_start 	= pos - protocol.length();
+								int	url_end 	= msg.length();
+								
+								for ( int i=pos+1;i<url_end;i++){
+									
+									char c = msg.charAt( i );
+									
+									if ( c == term_char || ( term_char == ' ' && Character.isWhitespace( c ))){
+										
+										url_end = term_char==' '?i:(i+1);
+										
+										break;
+									}
+								}
+									
+								if ( url_end > pos+1 && !Character.isDigit( protocol.charAt(0))){
+									
+									try{									
+										String url_str = protocol + msg.substring( pos, url_end );
+								
+										if ( url_str.startsWith( "\"" ) && url_str.endsWith( "\"" )){
+											
+											url_str = url_str.substring( 1, url_str.length()-1 );
+										}
+	
+										if ( protocol.equalsIgnoreCase( "chat" )){
+											
+											if ( url_str.toLowerCase( Locale.US ).startsWith( "chat:anon" )){
+												
+												if ( !beta.isI2PAvailable()){
+													
+													throw( new Exception( "Anonymous chat unavailable" ));
+												}
+											}
+										}else{
+										
+												// test that it is a valid URL
+											
+											URL	url = new URL( url_str );
+										}
+										
+										String original_url_str = url_str;
+										
+										String display_url = UrlUtils.decode( url_str );
+
+											// support a lame way of naming links - just append [[<url-encoded desc>]] to the URL
+																				
+										int hack_pos = url_str.lastIndexOf( "[[" );
+										
+										if ( hack_pos > 0 && url_str.endsWith( "]]" )){
+											
+											String substitution = url_str.substring( hack_pos + 2, url_str.length() - 2  ).trim();
+											
+											url_str = url_str.substring( 0, hack_pos );
+											
+												// prevent anything that looks like a URL from being used as the display
+												// text to avoid 'confusion'
+	
+											if ( UrlUtils.parseTextForURL( substitution, true ) == null ){
+												
+												display_url = UrlUtils.decode( substitution );
+												
+											}else{
+												
+												display_url = UrlUtils.decode( url_str );
+											}										
+										}
+										
+										if ( term_char != ' ' || !display_url.equals( original_url_str )){
+											
+											int	old_len = msg.length();
+											
+											msg = msg.substring( 0, url_start ) + display_url + msg.substring( url_end );
+											
+												// msg has probably changed length, update the end-pointer accordingly
+											
+											url_end += (msg.length() - old_len );
+										}
+										
+										int	this_style_start 	= start + url_start;
+										int this_style_length	= display_url.length();
+										
+										if ( this_style_start > next_style_start ){
+											
+											if ( message_type ==  ChatMessage.MT_INFO ){
+												
+												StyleRange styleRange 	= new StyleRange();
+												styleRange.start 		= next_style_start;
+												styleRange.length 		= this_style_start - next_style_start;
+												styleRange.foreground 	= Colors.grey;
+												
+												new_ranges.add( styleRange);
+												
+												next_style_start = this_style_start + this_style_length;
+											}
+										}
+										
+											/* Check that the URL is actually going tobe useful. IN particular, if it is a magnet URI with
+											 * no hash and no &fl links then it ain't gonna work
+											 */
+										
+										boolean	will_work = true;
+										
+										try{
+											
+											String lc_url = url_str.toLowerCase( Locale.US );
+											
+											if ( lc_url.startsWith( "magnet" )){
+												
+												if ( 	( !lc_url.contains( "btih:" )) ||
+														lc_url.contains( "btih:&" ) ||
+														lc_url.endsWith( "btih:" )){
+													
+														// no hash
+													
+													if ( !lc_url.contains( "&fl=" )){
+														
+															// no direct link
+															
+														will_work = false;
+													}
+												}
+											}
+										}catch( Throwable e ){
+											
+										}
+										
+										if ( will_work ){
+											
+											StyleRange styleRange 	= new StyleRange();
+											styleRange.start 		= this_style_start;
+											styleRange.length 		= this_style_length;
+											styleRange.foreground 	= Colors.blue;
+											styleRange.underline 	= true;
+											
+												// DON'T store the URL object because in their wisdom SWT invokes the .equals method
+												// on data objects when trying to find 'similar' ones, and for URLs this causes
+												// a name service lookup...
+											
+											styleRange.data = url_str;
+											
+											new_ranges.add( styleRange);
+											
+										}else{
+											
+											StyleRange styleRange 	= new StyleRange();
+											styleRange.start 		= this_style_start;
+											styleRange.length 		= this_style_length;
+											styleRange.font 		= bold_font;
+											
+											new_ranges.add( styleRange);
+										}
+									}catch( Throwable e ){
+										
+										//e.printStackTrace();
+									}
+								}
+								
+								pos = url_end;
+		
+							}else{
+								
+								pos = pos+1;
+							}		
+						}
+					
+						if ( next_style_start < start + msg.length() ){
+							
+							if ( message_type ==  ChatMessage.MT_INFO ){
+								
+								StyleRange styleRange 	= new StyleRange();
+								styleRange.start 		= next_style_start;
+								styleRange.length 		= start + msg.length() - next_style_start;
+								styleRange.foreground 	= Colors.grey;
+								
+								new_ranges.add( styleRange);
+							}
+						}
+					}
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+				
+				appended.append( msg ); 
+
+				appended.append( "\n" ); 
+				
+				int	actual_length = appended.length() - overall_start;
+				
+				messages.put( message, actual_length );
+			}
+		}
+
+		if ( appended.length() > 0 ){
+		
+			try{
+				log.setVisible( false );
+				
+				log.append( appended.toString());
+				
+				if ( new_ranges.size() > 0 ){
+				
+					List<StyleRange> existing_ranges = Arrays.asList( log.getStyleRanges());
+					
+					List<StyleRange> all_ranges = new ArrayList<StyleRange>( existing_ranges.size() + new_ranges.size());
+					
+					all_ranges.addAll( existing_ranges );
+					
+					all_ranges.addAll( new_ranges );
+					
+					StyleRange[] ranges = all_ranges.toArray( new StyleRange[ all_ranges.size()]);
+					
+					for ( StyleRange sr: ranges ){
+						
+						sr.borderStyle = SWT.NONE;
+					}
+					
+					log.setStyleRanges( ranges );
+					
+					log_styles = ranges;				
+				}
+				
+				
+				Iterator<Integer> it = null;
+				
+				int max_lines 	= beta.getMaxUILines();
+				int max_chars	= beta.getMaxUICharsKB() * 1024;
+				
+				while ( messages.size() > max_lines || log.getText().length() > max_chars ){
+					
+					if ( it == null ){
+						
+						it = messages.values().iterator();
+					}
+					
+					if ( !it.hasNext()){
+						
+						break;
+					}
+					
+					int to_remove = it.next();
+					
+					it.remove();
+					
+					log.replaceTextRange( 0,  to_remove, "" );
+					
+					log_styles = log.getStyleRanges();
+				}
+				
+				log.setSelection( log.getText().length());
+				
+			}finally{
+			
+				log.setVisible( true );
+			}
+			
+			if ( last_message_not_ours != null ){
+				
+				long last_message_not_ours_time = last_message_not_ours.getTimeStamp();
+				
+				if ( build_complete ){
+				
+					if ( 	( !log.isVisible()) || 
+							( shell != null && shell.getMinimized()) ||
+							log.getDisplay().getFocusControl() == null ){
+							
+						if ( last_message_not_ours_time > last_seen_message ){
+						
+							last_seen_message_pending = last_message_not_ours_time;
+							
+							view.betaMessagePending( chat, log, last_message_not_ours );
+						}
+					}else{
+						
+						last_seen_message = last_message_not_ours_time;
+					}
+				}else{
+					
+						// assume that during construction the messages will be seen
+					
+					if ( last_message_not_ours_time > last_seen_message ){
+					
+						last_seen_message = last_message_not_ours_time;
+					}
+				}
+			}
+		}
+	}
+	
+	public void
+	activate()
+	{
+		if ( last_seen_message_pending > last_seen_message ){
+			
+			last_seen_message = last_seen_message_pending;
+		}
+		
+		view.betaMessagePending( chat, log, null );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewChat.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewChat.java
index 6f01af7..e469b4c 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewChat.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewChat.java
@@ -1,459 +1,458 @@
-/*
- * Created on Apr 26, 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.plugins.net.buddy.swt;
-
-import java.util.*;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.StyleRange;
-import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.KeyListener;
-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.Display;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-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.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;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2ChatListener;
-import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy;
-
-public class 
-BuddyPluginViewChat 
-	implements BuddyPluginAZ2ChatListener
-{
-	private BuddyPlugin						plugin;
-	private BuddyPluginAZ2.chatInstance		chat;
-	
-	private LocaleUtilities		lu;
-	
-	private Shell 		shell;
-	private StyledText 	log;
-	private Table		buddy_table;
-	
-	private List		participants = new ArrayList();
-	
-	protected
-	BuddyPluginViewChat(
-		BuddyPlugin						_plugin,
-		Display 						_display,
-		BuddyPluginAZ2.chatInstance		_chat )
-	{
-		plugin	= _plugin;
-		chat	= _chat;
-		
-		lu		= plugin.getPluginInterface().getUtilities().getLocaleUtilities();
-		
-		shell = ShellFactory.createMainShell( SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX );
-
-		shell.addDisposeListener(
-			new DisposeListener()
-			{
-				public void 
-				widgetDisposed(
-					DisposeEvent arg0 ) 
-				{
-					closed();
-				}
-			});
-		
-		shell.setText( lu.getLocalisedMessageText( "azbuddy.chat.title" ));
-				
-		Utils.setShellIcon(shell);
-		
-		GridLayout layout = new GridLayout();
-		layout.numColumns = 2;
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		shell.setLayout(layout);
-		GridData grid_data = new GridData(GridData.FILL_BOTH );
-		shell.setLayoutData(grid_data);
-
-		
-		log = new StyledText(shell,SWT.READ_ONLY | SWT.V_SCROLL | SWT.BORDER | SWT.WRAP | SWT.NO_FOCUS );
-		grid_data = new GridData(GridData.FILL_BOTH);
-		grid_data.horizontalSpan = 1;
-		grid_data.horizontalIndent = 4;
-		grid_data.widthHint = 300;
-		grid_data.heightHint = 400;
-		log.setLayoutData(grid_data);
-		log.setIndent( 4 );
-		
-		log.setEditable( false );
-
-		Composite rhs = new Composite(shell, SWT.NONE);
-		layout = new GridLayout();
-		layout.numColumns = 1;
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		rhs.setLayout(layout);
-		grid_data = new GridData(GridData.FILL_BOTH );
-		grid_data.widthHint = 150;
-		rhs.setLayoutData(grid_data);
-
-			// table
-		
-		buddy_table = new Table(rhs, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL);
-
-		String[] headers = { 
-				"azbuddy.ui.table.name" };
-
-		int[] sizes = { 150 };
-
-		int[] aligns = { SWT.LEFT };
-
-		for (int i = 0; i < headers.length; i++){
-
-			TableColumn tc = new TableColumn(buddy_table, aligns[i]);
-				
-			tc.setWidth(sizes[i]);
-
-			Messages.setLanguageText(tc, headers[i]);
-		}	
-
-	    buddy_table.setHeaderVisible(true);
-
-	    grid_data = new GridData(GridData.FILL_BOTH);
-	    grid_data.heightHint = buddy_table.getHeaderHeight() * 3;
-		buddy_table.setLayoutData(grid_data);
-		
-		
-		buddy_table.addListener(
-			SWT.SetData,
-			new Listener()
-			{
-				public void 
-				handleEvent(
-					Event event) 
-				{
-					TableItem item = (TableItem)event.item;
-					
-					int index = buddy_table.indexOf(item);
-	
-					if ( index < 0 || index >= participants.size()){
-						
-						return;
-					}
-					
-					BuddyPluginAZ2.chatParticipant	participant = (BuddyPluginAZ2.chatParticipant)participants.get(index);
-					
-					BuddyPluginBuddy buddy = participant.getBuddy();
-					
-					if ( buddy == null ){
-						
-						item.setForeground( 0, Colors.red );
-						
-					}else if ( buddy.isOnline( false )){
-						
-						item.setForeground( 0, Colors.black );
-						
-					}else{
-						
-						item.setForeground( 0, Colors.grey );
-					}
-					
-					item.setText(0, participant.getName());					
-				}
-			});
-		
-		
-		
-		
-			// Text
-		
-		final Text text = new Text( shell, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP | SWT.BORDER);
-		grid_data = new GridData(GridData.FILL_HORIZONTAL );
-		grid_data.horizontalSpan = 2;
-		grid_data.heightHint = 50;
-		text.setLayoutData(grid_data);
-				
-		text.addKeyListener(
-			new KeyListener()
-			{
-				public void 
-				keyPressed(
-					KeyEvent e) 
-				{
-					if ( e.keyCode == SWT.CR ){
-				
-						e.doit = false;
-						
-						sendMessage( text.getText());
-						
-						text.setText( "" );
-					}
-				}
-				
-				public void 
-				keyReleased(
-					KeyEvent e ) 
-				{
-				}
-			});
-		
-		text.setFocus();
-		
-		shell.addListener(
-			SWT.Traverse, 
-			new Listener() 
-			{	
-				public void 
-				handleEvent(
-					Event e ) 
-				{
-					if ( e.character == SWT.ESC){
-					
-						close();
-				}
-			}
-		});
-		
-		BuddyPluginAZ2.chatParticipant[] existing_participants = chat.getParticipants();
-		
-		synchronized( participants ){
-			
-			participants.addAll( Arrays.asList( existing_participants ));
-		}
-		
-		updateTable( false );
-		
-		BuddyPluginAZ2.chatMessage[] history = chat.getHistory();
-		
-		for (int i=0;i<history.length;i++){
-			
-			logChatMessage( history[i].getNickName(), Colors.blue, history[i].getMessage());
-		}
-		
-		chat.addListener( this );
-		
-	    shell.pack();
-	    Utils.createURLDropTarget(shell, text);
-	    Utils.centreWindow(shell);
-	    shell.open();
-	}
-	
-	protected void
-	updateTable(
-		boolean	async )
-	{
-		if ( async ){
-			
-			if ( !buddy_table.isDisposed()){
-
-				buddy_table.getDisplay().asyncExec(
-						new Runnable()
-						{
-							public void
-							run()
-							{
-								if ( buddy_table.isDisposed()){
-
-									return;
-								}
-								
-								updateTable( false );
-							}
-						});
-			}					
-		}else{
-			
-			buddy_table.setItemCount( participants.size());
-			buddy_table.clearAll();
-			buddy_table.redraw();
-		}
-	}
-	
-	protected void
-	close()
-	{
-		shell.dispose();
-	}
-	
-	protected void
-	closed()
-	{
-		chat.removeListener( this );
-		
-		chat.destroy();
-	}
-	
-	public void
-	participantAdded(
-		BuddyPluginAZ2.chatParticipant		participant )
-	{
-		synchronized( participants ){
-			
-			participants.add( participant );
-		}
-		
-		updateTable( true );
-	}
-	
-	public void
-	participantChanged(
-		BuddyPluginAZ2.chatParticipant		participant )
-	{
-		updateTable( true );
-	}
-	
-	public void
-	participantRemoved(
-		BuddyPluginAZ2.chatParticipant		participant )
-	{
-		synchronized( participants ){
-			
-			participants.remove( participant );
-		}
-		
-		updateTable( true );
-	}
-	
-	protected void
-	sendMessage(
-		String		text )
-	{
-		Map	msg = new HashMap();
-		
-		try{
-			msg.put( "line", text.getBytes( "UTF-8" ));
-		
-		}catch( Throwable e ){
-			
-			msg.put( "line", text.getBytes());
-		}
-		
-		logChatMessage( plugin.getNickname(), Colors.green, msg );
-		
-		chat.sendMessage( msg );
-	}
-	
-	public void
-	messageReceived(
-		final BuddyPluginAZ2.chatParticipant	participant,
-		final Map								msg )
-	{
-		if ( !log.isDisposed()){
-
-			log.getDisplay().asyncExec(
-					new Runnable()
-					{
-						public void
-						run()
-						{
-							if ( log.isDisposed()){
-
-								return;
-							}
-							
-							try{
-								logChatMessage( participant.getName(), Colors.blue, msg );
-								
-							}catch( Throwable e ){
-								
-								Debug.printStackTrace(e);
-							}
-						}
-					});
-		}
-	}
-	
-	protected void
-	logChatMessage(
-		String		buddy_name,
-		Color 		colour,
-		Map			map )
-	{
-		byte[]	line = (byte[])map.get( "line" );
-		
-		String msg;
-		
-		try{
-			msg = new String( line, "UTF-8" );
-			
-		}catch( Throwable e ){
-			
-			msg = new String( line );
-		}
-
-		if ( buddy_name.length() > 32 ){
-			
-			buddy_name = buddy_name.substring(0,16) + "...";
-		}
-		
-		int	start = log.getText().length();
-		
-		if ( msg.startsWith( "/me" )){
-			
-			msg = msg.substring( 3 ).trim();
-			
-			String	me = "* " + buddy_name + " " + msg;
-			
-			log.append( me  );
-			
-			if ( colour != Colors.black ){
-				
-				StyleRange styleRange = new StyleRange();
-				styleRange.start = start;
-				styleRange.length = me.length();
-				styleRange.foreground = colour;
-				log.setStyleRange(styleRange);
-			}
-			
-			log.append( "\n" );
-			
-		}else{
-			String says = lu.getLocalisedMessageText( "azbuddy.chat.says", new String[]{ buddy_name }) + "\n";
-			
-			log.append( says ); 
-			
-			if ( colour != Colors.black ){
-				
-				StyleRange styleRange = new StyleRange();
-				styleRange.start = start;
-				styleRange.length = says.length();
-				styleRange.foreground = colour;
-				log.setStyleRange(styleRange);
-			}
-			
-			log.append( msg + "\n" ); 
-		}
-
-		log.setSelection( log.getText().length());
-	}
-}
+/*
+ * Created on Apr 26, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy.swt;
+
+import java.util.*;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+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.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+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.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;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginAZ2ChatListener;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy;
+
+public class 
+BuddyPluginViewChat 
+	implements BuddyPluginAZ2ChatListener
+{
+	private BuddyPlugin						plugin;
+	private BuddyPluginAZ2.chatInstance		chat;
+	
+	private LocaleUtilities		lu;
+	
+	private Shell 		shell;
+	private StyledText 	log;
+	private Table		buddy_table;
+	
+	private List		participants = new ArrayList();
+	
+	protected
+	BuddyPluginViewChat(
+		BuddyPlugin						_plugin,
+		Display 						_display,
+		BuddyPluginAZ2.chatInstance		_chat )
+	{
+		plugin	= _plugin;
+		chat	= _chat;
+		
+		lu		= plugin.getPluginInterface().getUtilities().getLocaleUtilities();
+		
+		shell = ShellFactory.createMainShell( SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX );
+
+		shell.addDisposeListener(
+			new DisposeListener()
+			{
+				public void 
+				widgetDisposed(
+					DisposeEvent arg0 ) 
+				{
+					closed();
+				}
+			});
+		
+		shell.setText( lu.getLocalisedMessageText( "azbuddy.chat.title" ));
+				
+		Utils.setShellIcon(shell);
+		
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		shell.setLayout(layout);
+		GridData grid_data = new GridData(GridData.FILL_BOTH );
+		shell.setLayoutData(grid_data);
+
+		
+		log = new StyledText(shell,SWT.READ_ONLY | SWT.V_SCROLL | SWT.BORDER | SWT.WRAP | SWT.NO_FOCUS );
+		grid_data = new GridData(GridData.FILL_BOTH);
+		grid_data.horizontalSpan = 1;
+		grid_data.horizontalIndent = 4;
+		grid_data.widthHint = 300;
+		grid_data.heightHint = 400;
+		log.setLayoutData(grid_data);
+		log.setIndent( 4 );
+		
+		log.setEditable( false );
+
+		Composite rhs = new Composite(shell, SWT.NONE);
+		layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		rhs.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_BOTH );
+		grid_data.widthHint = 150;
+		rhs.setLayoutData(grid_data);
+
+			// table
+		
+		buddy_table = new Table(rhs, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL);
+
+		String[] headers = { 
+				"azbuddy.ui.table.name" };
+
+		int[] sizes = { 150 };
+
+		int[] aligns = { SWT.LEFT };
+
+		for (int i = 0; i < headers.length; i++){
+
+			TableColumn tc = new TableColumn(buddy_table, aligns[i]);
+				
+			tc.setWidth(sizes[i]);
+
+			Messages.setLanguageText(tc, headers[i]);
+		}	
+
+	    buddy_table.setHeaderVisible(true);
+
+	    grid_data = new GridData(GridData.FILL_BOTH);
+	    grid_data.heightHint = buddy_table.getHeaderHeight() * 3;
+		buddy_table.setLayoutData(grid_data);
+		
+		
+		buddy_table.addListener(
+			SWT.SetData,
+			new Listener()
+			{
+				public void 
+				handleEvent(
+					Event event) 
+				{
+					TableItem item = (TableItem)event.item;
+					
+					int index = buddy_table.indexOf(item);
+	
+					if ( index < 0 || index >= participants.size()){
+						
+						return;
+					}
+					
+					BuddyPluginAZ2.chatParticipant	participant = (BuddyPluginAZ2.chatParticipant)participants.get(index);
+					
+					BuddyPluginBuddy buddy = participant.getBuddy();
+					
+					if ( buddy == null ){
+						
+						item.setForeground( 0, Colors.red );
+						
+					}else if ( buddy.isOnline( false )){
+						
+						item.setForeground( 0, Colors.black );
+						
+					}else{
+						
+						item.setForeground( 0, Colors.grey );
+					}
+					
+					item.setText(0, participant.getName());					
+				}
+			});
+		
+		
+		
+		
+			// Text
+		
+		final Text text = new Text( shell, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP | SWT.BORDER);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 2;
+		grid_data.heightHint = 50;
+		text.setLayoutData(grid_data);
+				
+		text.addKeyListener(
+			new KeyListener()
+			{
+				public void 
+				keyPressed(
+					KeyEvent e) 
+				{
+					if ( e.keyCode == SWT.CR ){
+				
+						e.doit = false;
+						
+						sendMessage( text.getText());
+						
+						text.setText( "" );
+					}
+				}
+				
+				public void 
+				keyReleased(
+					KeyEvent e ) 
+				{
+				}
+			});
+		
+		text.setFocus();
+		
+		shell.addListener(
+			SWT.Traverse, 
+			new Listener() 
+			{	
+				public void 
+				handleEvent(
+					Event e ) 
+				{
+					if ( e.character == SWT.ESC){
+					
+						close();
+				}
+			}
+		});
+		
+		BuddyPluginAZ2.chatParticipant[] existing_participants = chat.getParticipants();
+		
+		synchronized( participants ){
+			
+			participants.addAll( Arrays.asList( existing_participants ));
+		}
+		
+		updateTable( false );
+		
+		BuddyPluginAZ2.chatMessage[] history = chat.getHistory();
+		
+		for (int i=0;i<history.length;i++){
+			
+			logChatMessage( history[i].getNickName(), Colors.blue, history[i].getMessage());
+		}
+		
+		chat.addListener( this );
+		
+	    shell.pack();
+	    Utils.createURLDropTarget(shell, text);
+	    Utils.centreWindow(shell);
+	    shell.open();
+	}
+	
+	protected void
+	updateTable(
+		boolean	async )
+	{
+		if ( async ){
+			
+			if ( !buddy_table.isDisposed()){
+
+				buddy_table.getDisplay().asyncExec(
+						new Runnable()
+						{
+							public void
+							run()
+							{
+								if ( buddy_table.isDisposed()){
+
+									return;
+								}
+								
+								updateTable( false );
+							}
+						});
+			}					
+		}else{
+			
+			buddy_table.setItemCount( participants.size());
+			buddy_table.clearAll();
+			buddy_table.redraw();
+		}
+	}
+	
+	protected void
+	close()
+	{
+		shell.dispose();
+	}
+	
+	protected void
+	closed()
+	{
+		chat.removeListener( this );
+		
+		chat.destroy();
+	}
+	
+	public void
+	participantAdded(
+		BuddyPluginAZ2.chatParticipant		participant )
+	{
+		synchronized( participants ){
+			
+			participants.add( participant );
+		}
+		
+		updateTable( true );
+	}
+	
+	public void
+	participantChanged(
+		BuddyPluginAZ2.chatParticipant		participant )
+	{
+		updateTable( true );
+	}
+	
+	public void
+	participantRemoved(
+		BuddyPluginAZ2.chatParticipant		participant )
+	{
+		synchronized( participants ){
+			
+			participants.remove( participant );
+		}
+		
+		updateTable( true );
+	}
+	
+	protected void
+	sendMessage(
+		String		text )
+	{
+		Map	msg = new HashMap();
+		
+		try{
+			msg.put( "line", text.getBytes( "UTF-8" ));
+		
+		}catch( Throwable e ){
+			
+			msg.put( "line", text.getBytes());
+		}
+		
+		logChatMessage( plugin.getNickname(), Colors.green, msg );
+		
+		chat.sendMessage( msg );
+	}
+	
+	public void
+	messageReceived(
+		final BuddyPluginAZ2.chatParticipant	participant,
+		final Map								msg )
+	{
+		if ( !log.isDisposed()){
+
+			log.getDisplay().asyncExec(
+					new Runnable()
+					{
+						public void
+						run()
+						{
+							if ( log.isDisposed()){
+
+								return;
+							}
+							
+							try{
+								logChatMessage( participant.getName(), Colors.blue, msg );
+								
+							}catch( Throwable e ){
+								
+								Debug.printStackTrace(e);
+							}
+						}
+					});
+		}
+	}
+	
+	protected void
+	logChatMessage(
+		String		buddy_name,
+		Color 		colour,
+		Map			map )
+	{
+		byte[]	line = (byte[])map.get( "line" );
+		
+		String msg;
+		
+		try{
+			msg = new String( line, "UTF-8" );
+			
+		}catch( Throwable e ){
+			
+			msg = new String( line );
+		}
+
+		if ( buddy_name.length() > 32 ){
+			
+			buddy_name = buddy_name.substring(0,16) + "...";
+		}
+		
+		int	start = log.getText().length();
+		
+		if ( msg.startsWith( "/me" )){
+			
+			msg = msg.substring( 3 ).trim();
+			
+			String	me = "* " + buddy_name + " " + msg;
+			
+			log.append( me  );
+			
+			if ( colour != Colors.black ){
+				
+				StyleRange styleRange = new StyleRange();
+				styleRange.start = start;
+				styleRange.length = me.length();
+				styleRange.foreground = colour;
+				log.setStyleRange(styleRange);
+			}
+			
+			log.append( "\n" );
+			
+		}else{
+			String says = lu.getLocalisedMessageText( "azbuddy.chat.says", new String[]{ buddy_name }) + "\n";
+			
+			log.append( says ); 
+			
+			if ( colour != Colors.black ){
+				
+				StyleRange styleRange = new StyleRange();
+				styleRange.start = start;
+				styleRange.length = says.length();
+				styleRange.foreground = colour;
+				log.setStyleRange(styleRange);
+			}
+			
+			log.append( msg + "\n" ); 
+		}
+
+		log.setSelection( log.getText().length());
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewInstance.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewInstance.java
index 9f37b01..514012c 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewInstance.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/swt/BuddyPluginViewInstance.java
@@ -1,1830 +1,2855 @@
-/*
- * Created on Apr 2, 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.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;
-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.*;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-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;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
-
-import com.aelitis.azureus.core.security.*;
-import com.aelitis.azureus.core.util.AZ3Functions;
-import com.aelitis.azureus.plugins.net.buddy.*;
-
-public class 
-BuddyPluginViewInstance 
-	implements BuddyPluginListener, BuddyPluginBuddyRequestListener
-{
-	private static final int LOG_NORMAL 	= 1;
-	private static final int LOG_SUCCESS 	= 2;
-	private static final int LOG_ERROR 		= 3;
-
-
-	private BuddyPlugin	plugin;
-	private UIInstance	ui_instance;
-	private Composite	composite;
-	private Table 		buddy_table;
-	private StyledText 	log;
-
-	private List	buddies = new ArrayList();
-
-	private boolean	init_complete;
-		
-	protected
-	BuddyPluginViewInstance(
-		BuddyPlugin		_plugin,
-		UIInstance		_ui_instance,
-		Composite		_composite )
-	{
-		plugin		= _plugin;
-		ui_instance	= _ui_instance;
-		composite	= _composite;
-
-		final LocaleUtilities lu = plugin.getPluginInterface().getUtilities().getLocaleUtilities();
-			
-		Composite main = new Composite(composite, SWT.NONE);
-		GridLayout layout = new GridLayout();
-		layout.numColumns = 1;
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		main.setLayout(layout);
-		GridData grid_data = new GridData(GridData.FILL_BOTH );
-		main.setLayoutData(grid_data);
-
-		if ( !plugin.isEnabled()){
-			
-			Label control_label = new Label( main, SWT.NULL );
-			control_label.setText( lu.getLocalisedMessageText( "azbuddy.disabled" ));
-
-			return;
-		}
-			// control area
-		
-		final Composite controls = new Composite(main, SWT.NONE);
-		layout = new GridLayout();
-		layout.numColumns = 6;
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		controls.setLayout(layout);
-		grid_data = new GridData(GridData.FILL_HORIZONTAL );
-		controls.setLayoutData(grid_data);
-		
-		Label control_label = new Label( controls, SWT.NULL );
-		control_label.setText( lu.getLocalisedMessageText( "azbuddy.ui.new_buddy" ) + " " );
-		
-		final Text control_text = new Text( controls, SWT.BORDER );
-		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
-		control_text.setLayoutData(gridData);
-	
-		final Button control_button = new Button( controls, SWT.NULL );
-		control_button.setText( lu.getLocalisedMessageText( "azbuddy.ui.add" ));
-		
-		control_button.setEnabled( false );
-		
-		control_text.addModifyListener(
-			new ModifyListener() {
-	        	public void 
-	        	modifyText(
-	        		ModifyEvent e ) 
-	        	{					
-					control_button.setEnabled( plugin.verifyPublicKey( control_text.getText().trim())); 
-	        	}
-	        });
-		
-		control_button.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent e )
-				{
-					plugin.addBuddy( control_text.getText().trim(), BuddyPlugin.SUBSYSTEM_AZ2 );
-					
-					control_text.setText( "" );
-				}
-			});
-		
-		final Label control_lab_pk = new Label( controls, SWT.NULL );
-		control_lab_pk.setText( lu.getLocalisedMessageText( "azbuddy.ui.mykey" ) + " ");
-
-		final Text control_val_pk = new Text( controls, SWT.NULL );
-		gridData = new GridData();
-		gridData.widthHint = 400;
-		control_val_pk.setLayoutData(gridData);
-
-		control_val_pk.setEditable( false );
-		control_val_pk.setBackground( control_lab_pk.getBackground());
-		
-		control_val_pk.addKeyListener(
-			new KeyListener()
-			{
-				public void 
-				keyPressed(
-					KeyEvent event) 
-				{
-					int	key = event.character;
-					
-					if (key <= 26 && key > 0){
-						
-						key += 'a' - 1;
-					}
-				
-					if ( event.stateMask == SWT.MOD1 && key == 'a' ){
-	
-						control_val_pk.setSelection( 0, control_val_pk.getText().length());	
-					}
-				}
-				
-				public void 
-				keyReleased(
-					KeyEvent event) 
-				{	
-				}
-			});
-		
-
-	
-
-    	final CryptoManager crypt_man = CryptoManagerFactory.getSingleton();
-
-		byte[]	public_key = crypt_man.getECCHandler().peekPublicKey();
-		  
-		if ( public_key == null ){
-			
-		    Messages.setLanguageText(control_val_pk, "ConfigView.section.security.publickey.undef");
-
-		}else{
-		    			    			    
-			control_val_pk.setText( Base32.encode( public_key ));
-		}
-		
-	    Messages.setLanguageText(control_val_pk, "ConfigView.copy.to.clipboard.tooltip", true);
-
-	    control_val_pk.setCursor(main.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
-	    control_val_pk.setForeground(Colors.blue);
-	    control_val_pk.addMouseListener(new MouseAdapter() {
-	    	public void mouseDoubleClick(MouseEvent arg0) {
-	    		copyToClipboard();
-	    	}
-	    	public void mouseDown(MouseEvent arg0) {
-	    		copyToClipboard();
-	    	}
-	    	protected void
-	    	copyToClipboard()
-	    	{
-    			new Clipboard(control_val_pk.getDisplay()).setContents(new Object[] {control_val_pk.getText()}, new Transfer[] {TextTransfer.getInstance()});
-	    	}
-	    });
-		
-		crypt_man.addKeyListener(
-				new CryptoManagerKeyListener()
-				{
-					public void 
-					keyChanged(
-						final CryptoHandler handler ) 
-					{
-						if ( control_val_pk.isDisposed()){
-							
-							crypt_man.removeKeyListener( this );
-							
-						}else if ( handler.getType() == CryptoManager.HANDLER_ECC ){
-							
-							control_val_pk.getDisplay().asyncExec(
-								new Runnable()
-								{
-									public void 
-									run()
-									{
-										byte[]	public_key = handler.peekPublicKey();
-		
-										if ( public_key == null ){
-																				
-											 Messages.setLanguageText(control_val_pk, "ConfigView.section.security.publickey.undef");
-											
-										}else{
-											
-											control_val_pk.setText( Base32.encode( public_key ));
-										}
-										 
-										controls.layout();
-									}
-								});
-						}
-					}
-					
-					public void
-					keyLockStatusChanged(
-						CryptoHandler		handler )
-					{
-					}
-				});
-		
-		final Button config_button = new Button( controls, SWT.NULL );
-		config_button.setText( lu.getLocalisedMessageText( "plugins.basicview.config" ));
-
-		config_button.addSelectionListener(
-				new SelectionAdapter() 
-				{
-					public void 
-					widgetSelected(
-						SelectionEvent e )
-					{
-						plugin.showConfig();
-					}
-				});
-		
-			// table and log
-		
-		final Composite form = new Composite(main, SWT.NONE);
-		FormLayout flayout = new FormLayout();
-		flayout.marginHeight = 0;
-		flayout.marginWidth = 0;
-		form.setLayout(flayout);
-		gridData = new GridData(GridData.FILL_BOTH);
-		form.setLayoutData(gridData);
-
-
-		final Composite child1 = new Composite(form,SWT.NULL);
-		layout = new GridLayout();
-		layout.numColumns = 1;
-		layout.horizontalSpacing = 0;
-		layout.verticalSpacing = 0;
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		child1.setLayout(layout);
-
-		final Sash sash = new Sash(form, SWT.HORIZONTAL);
-	
-		final Composite child2 = new Composite(form,SWT.NULL);
-		layout = new GridLayout();
-		layout.numColumns = 1;
-		layout.horizontalSpacing = 0;
-		layout.verticalSpacing = 0;
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		child2.setLayout(layout);
-
-		FormData formData;
-
-			// child1
-		
-		formData = new FormData();
-		formData.left = new FormAttachment(0, 0);
-		formData.right = new FormAttachment(100, 0);
-		formData.top = new FormAttachment(0, 0);
-		child1.setLayoutData(formData);
-
-		final FormData child1Data = formData;
-		
-		final int SASH_WIDTH = 4;
-		
-			// sash
-		
-		formData = new FormData();
-		formData.left = new FormAttachment(0, 0);
-		formData.right = new FormAttachment(100, 0);
-		formData.top = new FormAttachment(child1);
-		formData.height = SASH_WIDTH;
-		sash.setLayoutData(formData);
-
-			// child2
-		
-		formData = new FormData();
-		formData.left = new FormAttachment(0, 0);
-		formData.right = new FormAttachment(100, 0);
-		formData.bottom = new FormAttachment(100, 0);
-		formData.top = new FormAttachment(sash);
-		child2.setLayoutData(formData);
-
-		final PluginConfig pc = plugin.getPluginInterface().getPluginconfig();
-		
-		sash.setData( "PCT", new Float( pc.getPluginFloatParameter( "swt.sash.position", 0.7f )));
-		
-		sash.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent e ) 
-				{
-					if (e.detail == SWT.DRAG){
-						return;
-					}
-					
-					child1Data.height = e.y + e.height - SASH_WIDTH;
-					
-					form.layout();
-	
-					Float l = new Float((double)child1.getBounds().height / form.getBounds().height);
-					
-					sash.setData( "PCT", l );
-					
-					pc.setPluginParameter( "swt.sash.position", l.floatValue());
-				}
-			});
-
-		form.addListener(
-			SWT.Resize, 
-			new Listener() 
-			{
-				public void 
-				handleEvent(Event e) 
-				{
-					Float l = (Float) sash.getData( "PCT" );
-					
-					if ( l != null ){
-						
-						child1Data.height = (int) (form.getBounds().height * l.doubleValue());
-					
-						form.layout();
-					}
-				}
-			});
-			
-			// table
-		
-		buddy_table = new Table(child1, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL);
-
-		final String[] headers = { 
-				"azbuddy.ui.table.name", 
-				"azbuddy.ui.table.online",  
-				"azbuddy.ui.table.lastseen", 
-				"azbuddy.ui.table.last_ygm", 
-				"azbuddy.ui.table.last_msg",
-				"azbuddy.ui.table.loc_cat",
-				"azbuddy.ui.table.rem_cat",
-				"azbuddy.ui.table.read_cat",
-				"azbuddy.ui.table.con",
-				"azbuddy.ui.table.msg_in",
-				"azbuddy.ui.table.msg_out",
-				"azbuddy.ui.table.msg_queued",
-				"MyTrackerView.bytesin",
-				"MyTrackerView.bytesout",
-				"azbuddy.ui.table.ss" };
-
-		int[] sizes = { 250, 100, 100, 100, 200, 100, 100, 100, 75, 75, 75, 75, 75, 75, 40 };
-
-		int[] aligns = { SWT.LEFT, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.LEFT, SWT.LEFT, SWT.LEFT, SWT.LEFT, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER };
-
-		for (int i = 0; i < headers.length; i++){
-
-			TableColumn tc = new TableColumn(buddy_table, aligns[i]);
-				
-			tc.setWidth(sizes[i]);
-
-			Messages.setLanguageText(tc, headers[i]);
-		}	
-
-	    buddy_table.setHeaderVisible(true);
-
-	    TableColumn[] columns = buddy_table.getColumns();
-	    columns[0].setData(new Integer(FilterComparator.FIELD_NAME));
-	    columns[1].setData(new Integer(FilterComparator.FIELD_ONLINE));
-	    columns[2].setData(new Integer(FilterComparator.FIELD_LAST_SEEN));
-	    columns[3].setData(new Integer(FilterComparator.FIELD_YGM));
-	    columns[4].setData(new Integer(FilterComparator.FIELD_LAST_MSG));
-	    columns[5].setData(new Integer(FilterComparator.FIELD_LOC_CAT));
-	    columns[6].setData(new Integer(FilterComparator.FIELD_REM_CAT));
-	    columns[7].setData(new Integer(FilterComparator.FIELD_READ_CAT));
-	    columns[8].setData(new Integer(FilterComparator.FIELD_CON));
-	    columns[9].setData(new Integer(FilterComparator.FIELD_MSG_IN));
-	    columns[10].setData(new Integer(FilterComparator.FIELD_MSG_OUT));
-	    columns[11].setData(new Integer(FilterComparator.FIELD_QUEUED));
-	    columns[12].setData(new Integer(FilterComparator.FIELD_BYTES_IN));
-	    columns[13].setData(new Integer(FilterComparator.FIELD_BYTES_OUT));
-	    columns[14].setData(new Integer(FilterComparator.FIELD_SS));
-	    
-	    
-	    final FilterComparator comparator = new FilterComparator();
-	    
-	    Listener sort_listener = 
-	    	new Listener() 
-	    	{
-		    	public void 
-		    	handleEvent(
-		    		Event e ) 
-		    	{
-		    		TableColumn tc = (TableColumn) e.widget;
-	
-		    		int field = ((Integer) tc.getData()).intValue();
-	
-		    		comparator.setField( field );
-	
-		    		Collections.sort( buddies,comparator);
-	
-		    		updateTable();
-		    	}
-	    	};
-	    
-	    for (int i=0;i<columns.length;i++){
-	    	
-	    	columns[i].addListener(SWT.Selection,sort_listener);
-	    }	    
-	    
-	    gridData = new GridData(GridData.FILL_BOTH);
-	    gridData.heightHint = buddy_table.getHeaderHeight() * 3;
-		buddy_table.setLayoutData(gridData);
-		
-		
-		buddy_table.addListener(
-			SWT.SetData,
-			new Listener()
-			{
-				public void 
-				handleEvent(
-					Event event) 
-				{
-					TableItem item = (TableItem)event.item;
-					
-					int index = buddy_table.indexOf(item);
-	
-					if ( index < 0 || index >= buddies.size()){
-						
-						return;
-					}
-					
-					BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(index);
-					
-					item.setText(0, buddy.getName());
-					
-					int	os;
-					
-					if ( buddy.isOnline( false )){
-						
-						os = buddy.getOnlineStatus();
-						
-					}else{
-						
-						os = BuddyPlugin.STATUS_APPEAR_OFFLINE;
-					}
-					
-					if ( os == BuddyPlugin.STATUS_APPEAR_OFFLINE ){
-						
-						item.setText( 1, "" );
-						
-					}else{
-					
-						item.setText(1, plugin.getOnlineStatus( os ));
-					}
-					
-					long lo = buddy.getLastTimeOnline();
-					
-					item.setText(2, lo==0?"":new SimpleDateFormat().format(new Date( lo )));
-
-					long	last_ygm = buddy.getLastMessagePending();;
-					
-					item.setText(3, last_ygm==0?"":new SimpleDateFormat().format(new Date( last_ygm )));
-					
-					String	lm = buddy.getLastMessageReceived();
-					
-					item.setText(4, lm==null?"":lm);
-					
-					String loc_cat = buddy.getLocalAuthorisedRSSCategoriesAsString();
-					if ( loc_cat == null ){
-						loc_cat = "";
-					}
-					item.setText(5, "" + loc_cat);
-
-					String rem_cat = buddy.getRemoteAuthorisedRSSCategoriesAsString();
-					if ( rem_cat == null ){
-						rem_cat = "";
-					}
-					item.setText(6, "" + rem_cat);
-
-					String read_cat = buddy.getLocalReadCategoriesAsString();
-					if ( read_cat == null ){
-						read_cat = "";
-					}
-					item.setText(7, "" + read_cat);
-
-					item.setText(8, "" + buddy.getConnectionsString());
-					
-					String in_frag = buddy.getMessageInFragmentDetails();
-					
-					item.setText(9, "" + buddy.getMessageInCount() + (in_frag.length()==0?"":("+" + in_frag )));
-					item.setText(10, "" + buddy.getMessageOutCount());
-					item.setText(11, "" + buddy.getMessageHandler().getMessageCount());
-					item.setText(12, "" + DisplayFormatters.formatByteCountToKiBEtc(buddy.getBytesInCount()));
-					item.setText(13, "" + DisplayFormatters.formatByteCountToKiBEtc(buddy.getBytesOutCount()));
-
-					item.setText(14, "" + buddy.getSubsystem() + " v" + buddy.getVersion());
-					
-					item.setData( buddy );
-				}
-			});
-		
-		final Listener tt_label_listener = 
-			new Listener() 
-			{
-				public void handleEvent(Event event) {
-					Label label = (Label) event.widget;
-					Shell shell = label.getShell();
-					switch (event.type) {
-					case SWT.MouseDown:
-						Event e = new Event();
-						e.item = (TableItem) label.getData("_TABLEITEM");
-						buddy_table.setSelection(new TableItem[] { (TableItem) e.item });
-						buddy_table.notifyListeners(SWT.Selection, e);
-						// fall through
-					case SWT.MouseExit:
-						shell.dispose();
-						break;
-					}
-				}
-			};
-
-
-		Listener	tt_table_listener = 
-			new Listener()
-			{
-				private Shell tip = null;
-
-				private Label label = null;
-
-				public void 
-				handleEvent(
-					Event event ) 
-				{
-					switch (event.type){
-						case SWT.Dispose:
-						case SWT.KeyDown:
-						case SWT.MouseMove: {
-							if (tip == null)
-								break;
-							tip.dispose();
-							tip = null;
-							label = null;
-							break;
-						}
-						case SWT.MouseHover: 
-						{
-							Point mouse_position = new Point(event.x, event.y);
-							
-							TableItem item = buddy_table.getItem( mouse_position );
-														
-							if (item != null) {
-								
-								if (tip != null && !tip.isDisposed()){
-									
-									tip.dispose();
-									
-									tip = null;
-								}
-								
-								int index = buddy_table.indexOf(item);
-								
-								if ( index < 0 || index >= buddies.size()){
-									
-									return;
-								}
-
-								BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(index);
-
-								int	item_index = 0;
-								
-								for (int i=0;i<headers.length;i++){
-									
-									Rectangle bounds = item.getBounds(i);
-									
-									if ( bounds.contains( mouse_position )){
-										
-										item_index = i;
-										
-										break;
-									}
-								}
-								
-								if( item_index != 0 ){
-									
-									return;
-								}
-								
-								tip = new Shell(buddy_table.getShell(), SWT.ON_TOP | SWT.TOOL);
-								tip.setLayout(new FillLayout());
-								label = new Label(tip, SWT.NONE);
-								label.setForeground(buddy_table.getDisplay()
-										.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
-								label.setBackground(buddy_table.getDisplay()
-										.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
-								label.setData("_TABLEITEM", item);
-								
-								label.setText( getToolTip( buddy ));
-								
-								label.addListener(SWT.MouseExit, tt_label_listener);
-								label.addListener(SWT.MouseDown, tt_label_listener);
-								Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT);
-								Rectangle rect = item.getBounds(item_index);
-								Point pt = buddy_table.toDisplay(rect.x, rect.y);
-								tip.setBounds(pt.x, pt.y, size.x, size.y);
-								tip.setVisible(true);
-							}
-						}
-					}
-				}
-				
-				protected String
-				getToolTip(
-					BuddyPluginBuddy	buddy )
-				{
-					List addresses = buddy.getAdjustedIPs();
-					
-					InetAddress	ip	= buddy.getIP();
-					
-					InetAddress adj = buddy.getAdjustedIP();
-					
-					String	str = "";
-					
-					if ( ip == null ){
-						
-						str = "<none>";
-						
-					}else if ( ip == adj ){
-						
-						str = ip.getHostAddress();
-						
-					}else{
-						
-						str = ip.getHostAddress() + "{";
-					
-						for (int i=0;i<addresses.size();i++){
-							
-							str += (i==0?"":"/") + ((InetAddress)addresses.get(i)).getHostAddress();
-						}
-						
-						str += "}";
-					}
-					
-					return(  "ip=" + str + ",tcp=" + buddy.getTCPPort() + ",udp=" + buddy.getUDPPort());
-				}
-			};
-			
-		buddy_table.addListener(SWT.Dispose, tt_table_listener);
-		buddy_table.addListener(SWT.KeyDown, tt_table_listener);
-		buddy_table.addListener(SWT.MouseMove, tt_table_listener);
-		buddy_table.addListener(SWT.MouseHover, tt_table_listener);
-		    			
-
-
-		final Menu menu = new Menu(buddy_table);
-		
-		final MenuItem remove_item = new MenuItem(menu, SWT.PUSH);
-		
-		remove_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.remove" ));
-
-		remove_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent e) 
-				{
-					TableItem[] selection = buddy_table.getSelection();
-					
-					for (int i=0;i<selection.length;i++){
-						
-						BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-						
-						buddy.remove();
-					}
-				};
-			});
-		
-			// get public key
-				
-		final MenuItem get_pk_item = new MenuItem(menu, SWT.PUSH);
-
-		get_pk_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.copypk" ) );
-
-		get_pk_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent event ) 
-				{
-					TableItem[] selection = buddy_table.getSelection();
-					
-					StringBuffer sb = new StringBuffer();
-					
-					for (int i=0;i<selection.length;i++){
-						
-						BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-						
-						sb.append( buddy.getPublicKey() + "\r\n" );
-					}
-					
-					if ( sb.length() > 0 ){
-					
-						writeToClipboard( sb.toString());
-					}
-				};
-			});
-		
-			// disconnect message
-		
-		if ( Constants.isCVSVersion()){
-			final  MenuItem send_msg_item = new MenuItem(menu, SWT.PUSH);
-	
-			send_msg_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.disconnect" ) );
-	
-			send_msg_item.addSelectionListener(
-				new SelectionAdapter() 
-				{
-					public void 
-					widgetSelected(
-						SelectionEvent event ) 
-					{
-						TableItem[] selection = buddy_table.getSelection();
-				
-						for (int i=0;i<selection.length;i++){
-							
-							BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-							
-							buddy.disconnect();
-						}
-					}
-				});
-		}
-		
-			// send message
-		
-		final  MenuItem send_msg_item = new MenuItem(menu, SWT.PUSH);
-
-		send_msg_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.send" ) );
-
-		send_msg_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent event ) 
-				{
-					final TableItem[] selection = buddy_table.getSelection();
-					
-					UIInputReceiver prompter = ui_instance.getInputReceiver();
-					
-					prompter.setLocalisedTitle( lu.getLocalisedMessageText( "azbuddy.ui.menu.send" ));
-					prompter.setLocalisedMessage( lu.getLocalisedMessageText( "azbuddy.ui.menu.send_msg" ) );
-					
-					try{
-						prompter.prompt(new UIInputReceiverListener() {
-							public void UIInputReceiverClosed(UIInputReceiver prompter) {
-								String text = prompter.getSubmittedInput();
-								
-								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 ){
-						
-					}
-				};
-			});
-		
-			// chat
-		
-		final  MenuItem chat_item = new MenuItem(menu, SWT.PUSH);
-
-		chat_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.chat" ) );
-
-		chat_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent event ) 
-				{
-					TableItem[] selection = buddy_table.getSelection();
-					
-					BuddyPluginBuddy[] buddies = new BuddyPluginBuddy[selection.length];
-					
-					for (int i=0;i<selection.length;i++){
-						
-						BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-
-						buddies[i] = buddy;
-					}
-								
-					plugin.getAZ2Handler().createChat( buddies );
-				};
-			});
-		
-			// ping
-		
-		final MenuItem ping_item = new MenuItem(menu, SWT.PUSH);
-
-		ping_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.ping" ) );
-
-		ping_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent event ) 
-				{
-					TableItem[] selection = buddy_table.getSelection();
-					
-					for (int i=0;i<selection.length;i++){
-						
-						BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-						
-						try{					
-							buddy.ping();
-							
-						}catch( Throwable e ){
-							
-							print( "Ping failed", e );
-						}
-					}
-				};
-			});
-		
-			// ygm
-		
-		final MenuItem ygm_item = new MenuItem(menu, SWT.PUSH);
-
-		ygm_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.ygm" ) );
-
-		ygm_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent event ) 
-				{
-					TableItem[] selection = buddy_table.getSelection();
-					
-					for (int i=0;i<selection.length;i++){
-						
-						BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-						
-						try{
-							buddy.setMessagePending();
-							
-						}catch( Throwable e ){
-							
-							print( "YGM failed", e );
-						}
-					}
-				};
-			});
-		
-		
-			// encrypt
-		
-		final MenuItem encrypt_item = new MenuItem(menu, SWT.PUSH);
-
-		encrypt_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.enc" ) );
-
-		encrypt_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent event ) 
-				{
-					TableItem[] selection = buddy_table.getSelection();
-					
-					String	str = readFromClipboard();
-					
-					if( str != null ){
-						
-						StringBuffer sb = new StringBuffer();
-						
-						for (int i=0;i<selection.length;i++){
-							
-							BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-							
-							try{
-								byte[]	contents = str.getBytes( "UTF-8" );
-								
-								BuddyPlugin.cryptoResult result = buddy.encrypt( contents );
-								
-								sb.append( "key: " );
-								sb.append( plugin.getPublicKey());
-								sb.append( "\r\n" );
-								
-								sb.append( "hash: " );
-								sb.append( Base32.encode( result.getChallenge()));
-								sb.append( "\r\n" );
-
-								sb.append( "payload: " );
-								sb.append( Base32.encode( result.getPayload()));
-								sb.append( "\r\n\r\n" );
-								
-							}catch( Throwable e ){
-								
-								print( "YGM failed", e );
-							}
-						}
-						
-						writeToClipboard( sb.toString());
-					}
-				};
-			});
-		
-			// decrypt
-		
-		final MenuItem decrypt_item = new MenuItem(menu, SWT.PUSH);
-
-		decrypt_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.dec" ) );
-
-		decrypt_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent event ) 
-				{
-					String	str = readFromClipboard();
-					
-					if ( str != null ){
-						
-						String[] 	bits = str.split( "\n" );
-						
-						StringBuffer sb = new StringBuffer();
-	
-						BuddyPluginBuddy	buddy 	= null;
-						byte[]				hash	= null;
-						
-						for (int i=0;i<bits.length;i++){
-							
-							String	bit = bits[i].trim();
-							
-							if ( bit.length() > 0 ){
-							
-								int	pos = bit.indexOf( ':' );
-								
-								if ( pos == -1 ){
-									
-									continue;
-								}
-								
-								String	lhs = bit.substring( 0, pos ).trim();
-								String	rhs	= bit.substring( pos+1 ).trim();
-								
-								if ( lhs.equals( "key" )){
-									
-									buddy = plugin.getBuddyFromPublicKey( rhs );
-									
-								}else if ( lhs.equals( "hash" )){
-									
-									hash	= Base32.decode( rhs );
-									
-								}else if ( lhs.equals( "payload" )){
-								
-									byte[]	payload = Base32.decode( rhs );
-									
-									if ( buddy != null ){
-										
-										try{
-											BuddyPlugin.cryptoResult result = buddy.decrypt( payload );
-											
-											byte[] sha1 = new SHA1Simple().calculateHash( result.getChallenge());
-											
-											sb.append( "key: " );
-											sb.append( buddy.getPublicKey());
-											sb.append( "\r\n" );
-
-											sb.append( "hash_ok: " + Arrays.equals( hash, sha1 ));
-											sb.append( "\r\n" );
-											
-											sb.append( "payload: " );
-											sb.append( new String( result.getPayload(), "UTF-8" ));
-											sb.append( "\r\n\r\n" );
-											
-										}catch( Throwable e ){
-											
-											print( "decrypt failed", e );
-										}
-									}
-								}
-							}
-						}
-						
-						if ( sb.length() > 0 ){
-						
-							writeToClipboard( sb.toString());
-						}
-					}
-				};
-			});
-		
-			// sign
-		
-		final MenuItem sign_item = new MenuItem(menu, SWT.PUSH);
-
-		sign_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.sign" ) );
-
-		sign_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent event ) 
-				{
-					String	str = readFromClipboard();
-					
-					if ( str != null ){
-						
-						StringBuffer sb = new StringBuffer();
-						
-						try{
-							sb.append( "key: " );
-							sb.append( plugin.getPublicKey());
-							sb.append( "\r\n" );
-
-							byte[] payload = str.getBytes( "UTF-8" );
-							
-							sb.append( "data: " );
-							sb.append( Base32.encode( payload ));
-							sb.append( "\r\n" );
-
-							byte[]	sig = plugin.sign( payload );
-
-							sb.append( "sig: " );
-							sb.append( Base32.encode( sig ));
-							sb.append( "\r\n" );
-
-						}catch( Throwable e ){
-							
-							print( "sign failed", e );
-						}
-						
-						if ( sb.length() > 0 ){
-						
-							writeToClipboard( sb.toString());
-						}
-					}
-				};
-			});
-		
-			// verify
-		
-		final MenuItem verify_item = new MenuItem(menu, SWT.PUSH);
-
-		verify_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.verify" ) );
-
-		verify_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent event ) 
-				{
-					String	str = readFromClipboard();
-					
-					if ( str != null ){
-						
-						String[] 	bits = str.split( "\n" );
-						
-						StringBuffer sb = new StringBuffer();
-	
-						String				pk 		= null;
-						byte[]				data	= null;
-						
-						for (int i=0;i<bits.length;i++){
-							
-							String	bit = bits[i].trim();
-							
-							if ( bit.length() > 0 ){
-							
-								int	pos = bit.indexOf( ':' );
-								
-								if ( pos == -1 ){
-									
-									continue;
-								}
-								
-								String	lhs = bit.substring( 0, pos ).trim();
-								String	rhs	= bit.substring( pos+1 ).trim();
-								
-								if ( lhs.equals( "key" )){
-									
-									pk = rhs;
-									
-								}else if ( lhs.equals( "data" )){
-									
-									data	= Base32.decode( rhs );
-									
-								}else if ( lhs.equals( "sig" )){
-								
-									byte[]	sig = Base32.decode( rhs );
-									
-									if ( pk != null && data != null ){
-										
-										try{
-											
-											sb.append( "key: " );
-											sb.append( pk );
-											sb.append( "\r\n" );
-
-											boolean ok = plugin.verify( pk, data, sig );
-											
-											sb.append( "sig_ok: " + ok  );
-											sb.append( "\r\n" );
-											
-											sb.append( "data: " );
-											sb.append( new String( data, "UTF-8" ));
-											sb.append( "\r\n\r\n" );
-											
-										}catch( Throwable e ){
-											
-											print( "decrypt failed", e );
-										}
-									}
-								}
-							}
-						}
-						
-						if ( sb.length() > 0 ){
-						
-							writeToClipboard( sb.toString());
-						}
-					}
-				};
-			});
-				
-		
-			// cats
-		
-		Menu cat_menu = new Menu(menu.getShell(), SWT.DROP_DOWN);
-		MenuItem cat_item = new MenuItem(menu, SWT.CASCADE);
-		Messages.setLanguageText(cat_item, "azbuddy.ui.menu.cat" );
-		cat_item.setMenu(cat_menu);
-
-			// cats - share
-		
-		final MenuItem cat_share_item = new MenuItem(cat_menu, SWT.PUSH);
-
-		cat_share_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.share" ) );
-
-		cat_share_item.addSelectionListener(
-			new SelectionAdapter() 
-			{
-				public void 
-				widgetSelected(
-					SelectionEvent event ) 
-				{
-					UIInputReceiver prompter = ui_instance.getInputReceiver();
-					
-					prompter.setLocalisedTitle( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.set" ));
-					prompter.setLocalisedMessage( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.set_msg" ));
-					
-					prompter.prompt(new UIInputReceiverListener() {
-						public void UIInputReceiverClosed(UIInputReceiver prompter) {
-							String cats = prompter.getSubmittedInput();
-							
-							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 );
-								}
-							}
-						}
-					});
-					
-				};
-			});
-		
-			// cats - subscribe
-		
-		final Menu cat_subs_menu = new Menu(cat_menu.getShell(), SWT.DROP_DOWN);
-		final MenuItem cat_subs_item = new MenuItem(cat_menu, SWT.CASCADE);
-		Messages.setLanguageText(cat_subs_item, "azbuddy.ui.menu.cat_subs" );
-		cat_subs_item.setMenu(cat_subs_menu);
-
-		cat_subs_menu.addMenuListener(
-			new MenuListener()
-			{
-				public void 
-				menuShown(
-					MenuEvent arg0 ) 
-				{
-					MenuItem[] items = cat_subs_menu.getItems();
-					
-					for (int i = 0; i < items.length; i++){
-						
-						items[i].dispose();
-					}
-					
-					final AZ3Functions.provider az3 = AZ3Functions.getProvider();
-					
-					if ( az3 != null ){
-						
-						final TableItem[] selection = buddy_table.getSelection();
-						
-						Set<String> avail_cats = new TreeSet<String>();
-						
-						for (int i=0;i<selection.length;i++){
-							
-							BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-							
-							Set<String> cats = buddy.getRemoteAuthorisedRSSCategories();
-							
-							if ( cats != null ){
-								
-								avail_cats.addAll( cats );
-							}
-						}
-						
-						for ( final String cat: avail_cats ){
-							
-							final MenuItem subs_item = new MenuItem( cat_subs_menu, SWT.PUSH );
-	
-							subs_item.setText( cat );
-	
-							subs_item.addSelectionListener(
-								new SelectionAdapter() 
-								{
-									public void 
-									widgetSelected(
-										SelectionEvent event ) 
-									{
-										for (int i=0;i<selection.length;i++){
-											
-											BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
-
-											if ( buddy.isRemoteRSSCategoryAuthorised( cat )){
-												
-												try{
-													buddy.subscribeToCategory( cat );
-													
-												}catch( Throwable e ){
-													
-													print( "Failed", e );
-												}
-											}
-										}
-									}
-								});
-						}
-					}
-				}
-				
-				public void 
-				menuHidden(
-					MenuEvent arg0 ) 
-				{
-				}
-			});
-		
-		
-			// done with menus
-		
-		buddy_table.setMenu( menu );
-			
-		menu.addMenuListener(
-			new MenuListener()
-			{
-				public void 
-				menuShown(
-					MenuEvent arg0 ) 
-				{
-					boolean	available = plugin.isAvailable();
-					
-					TableItem[] selection = buddy_table.getSelection();
-						
-					remove_item.setEnabled( selection.length > 0 );
-					get_pk_item.setEnabled( available && selection.length > 0 );
-					send_msg_item.setEnabled(available && selection.length > 0);
-					chat_item.setEnabled(available && selection.length > 0);
-					ping_item.setEnabled(available && selection.length > 0);
-					ygm_item.setEnabled(available && selection.length > 0);
-					encrypt_item.setEnabled(selection.length > 0);
-					decrypt_item.setEnabled(true);
-					sign_item.setEnabled(true);
-					verify_item.setEnabled(true);
-				}
-				
-				public void 
-				menuHidden(
-					MenuEvent arg0 ) 
-				{
-				}
-			});
-		
-			// log area
-
-		log = new StyledText(child2,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
-		grid_data = new GridData(GridData.FILL_BOTH);
-		grid_data.horizontalSpan = 1;
-		grid_data.horizontalIndent = 4;
-		log.setLayoutData(grid_data);
-		log.setIndent( 4 );
-
-		buddies = plugin.getBuddies();
-		
-		for (int i=0;i<buddies.size();i++){
-			
-			buddyAdded((BuddyPluginBuddy)buddies.get(i));
-		}
-		
-		Collections.sort( buddies, comparator );
-
-		plugin.addListener( this );
-		
-		plugin.addRequestListener( this );
-		
-		init_complete	= true;
-	    
-		updateTable();
-	}
-
-	protected String
-	readFromClipboard()
-	{
-		 Object o = 
-			 new Clipboard(SWTThread.getInstance().getDisplay()).getContents(
-			      TextTransfer.getInstance());
-		 
-		 if ( o instanceof String ){
-			 
-			 return((String)o);
-		 }
-		 
-		 return( null );
-	}
-
-	protected void
-	writeToClipboard(
-		String	str )
-	{
-		 new Clipboard(SWTThread.getInstance().getDisplay()).setContents(
-			      new Object[] {str }, 
-			      new Transfer[] {TextTransfer.getInstance()});
-	}
-
-	protected void
-	updateTable()
-	{
-		if ( init_complete ){
-			
-			buddy_table.setItemCount( buddies.size());
-			buddy_table.clearAll();
-			buddy_table.redraw();
-		}
-	}
-	
-	public void 
-	initialised(
-		boolean available ) 
-	{
-		print( "Initialisation complete: available=" + available );
-	}
-	
-	public void
-	buddyAdded(
-		final BuddyPluginBuddy	buddy )
-	{
-		if ( buddy_table.isDisposed()){
-			
-			return;
-		}
-		
-		buddy.getMessageHandler().addListener(
-			new BuddyPluginBuddyMessageListener()
-			{
-				public void
-				messageQueued(
-					BuddyPluginBuddyMessage		message )
-				{
-					print( message.getBuddy().getName() + ": message queued, id=" + message.getID());
-					
-					update();
-				}
-				
-				public void
-				messageDeleted(
-					BuddyPluginBuddyMessage		message )
-				{
-					print( message.getBuddy().getName() + ": message deleted, id=" + message.getID());
-					
-					update();
-				}
-				
-				public boolean
-				deliverySucceeded(
-					BuddyPluginBuddyMessage		message,
-					Map							reply )
-				{
-					print( message.getBuddy().getName() + ": message delivered, id=" + message.getID() + ", reply=" + reply );
-					
-					update();
-					
-					return( true );
-				}
-				
-				public void
-				deliveryFailed(
-					BuddyPluginBuddyMessage		message,
-					BuddyPluginException		cause )
-				{
-					print( message.getBuddy().getName() + ": message failed, id=" + message.getID(), cause );
-					
-					update();
-				}
-				
-				protected void
-				update()
-				{
-					if ( !buddy_table.isDisposed()){
-						
-						buddy_table.getDisplay().asyncExec(
-							new Runnable()
-							{
-								public void
-								run()
-								{
-									if ( !buddy_table.isDisposed()){
-										
-										updateTable();
-									}
-								}
-							});
-					}
-				}
-			});
-		
-		if ( !buddies.contains( buddy )){
-			
-			buddy_table.getDisplay().asyncExec(
-					new Runnable()
-					{
-						public void
-						run()
-						{
-							if ( !buddy_table.isDisposed()){
-								
-								if ( !buddies.contains( buddy )){
-									
-									buddies.add( buddy );
-									
-									updateTable();
-								}
-							}
-						}
-					});
-		}
-	}
-
-	public void
-	buddyRemoved(
-		final BuddyPluginBuddy	buddy )
-	{
-		if ( !buddy_table.isDisposed()){
-			
-			buddy_table.getDisplay().asyncExec(
-					new Runnable()
-					{
-						public void
-						run()
-						{
-							if ( !buddy_table.isDisposed()){
-								
-								if ( buddies.remove( buddy )){
-																	
-									updateTable();
-								}
-							}
-						}
-					});	
-		}
-	}
-
-	public void
-	buddyChanged(
-		final BuddyPluginBuddy	buddy )
-	{
-		if ( !buddy_table.isDisposed()){
-			
-			buddy_table.getDisplay().asyncExec(
-					new Runnable()
-					{
-						public void
-						run()
-						{
-							if ( !buddy_table.isDisposed()){
-																								
-								updateTable();
-							}
-						}
-					});	
-		}
-	}
-	
-	public void
-	messageLogged(
-		String		str,
-		boolean		error )
-	{
-		print( str, error?LOG_ERROR:LOG_NORMAL, false, false );
-	}
-	
-	// @see com.aelitis.azureus.plugins.net.buddy.BuddyPluginListener#enabledStateChanged(boolean)
-	public void 
-	enabledStateChanged(
-			boolean enabled) {
-	}
-
-	public Map
-	requestReceived(
-		BuddyPluginBuddy	from_buddy,
-		int					subsystem,
-		Map					request )
-	
-		throws BuddyPluginException
-	{
-		return( null );
-	}
-	
-	public void
-	pendingMessages(
-		BuddyPluginBuddy[]	from_buddies )
-	{
-		String	str = "";
-		
-		for (int i=0;i<from_buddies.length;i++){
-			
-			str += (str.length()==0?"":",") + from_buddies[i].getName();
-		}
-		
-		print( "YGM received: " + str );
-	}
-	
-	protected void
-	print(
-		String		str,
-		Throwable	e )
-	{
-		print( str + ": " + Debug.getNestedExceptionMessage( e ));
-	}
-	
-	protected void
-	print(
-		String		str )
-	{
-		print( str, LOG_NORMAL, false, true );
-	}
-
-	protected void
-	print(
-		final String		str,
-		final int			log_type,
-		final boolean		clear_first,
-		boolean				log_to_plugin )
-	{
-		if ( log_to_plugin ){
-
-			plugin.log( str );
-		}
-
-		if ( !log.isDisposed()){
-
-			final int f_log_type = log_type;
-
-			log.getDisplay().asyncExec(
-					new Runnable()
-					{
-						public void
-						run()
-						{
-							if ( log.isDisposed()){
-
-								return;
-							}
-
-							int	start;
-
-							if ( clear_first ){
-
-								start	= 0;
-
-								log.setText( str + "\n" );
-
-							}else{
-
-								String	text = log.getText();
-								
-								start = text.length();
-
-								if ( start > 32000 ){
-									
-									log.replaceTextRange( 0, 1024, "" );
-									
-									start = log.getText().length();
-								}
-								
-								log.append( str + "\n" );
-							}
-
-							Color 	color;
-
-							if ( f_log_type == LOG_NORMAL ){
-
-								color = Colors.black;
-
-							}else if ( f_log_type == LOG_SUCCESS ){
-
-								color = Colors.green;
-
-							}else{
-
-								color = Colors.red;
-							}
-
-							if ( color != Colors.black ){
-								
-								StyleRange styleRange = new StyleRange();
-								styleRange.start = start;
-								styleRange.length = str.length();
-								styleRange.foreground = color;
-								log.setStyleRange(styleRange);
-							}
-							
-							log.setSelection( log.getText().length());
-						}
-					});
-		}
-	}
-
-	protected void
-	destroy()
-	{
-		composite = null;
-		
-		plugin.removeListener( this );
-		
-		plugin.removeRequestListener( this );
-
-	}
-	
-	protected class 
-	FilterComparator 
-		implements Comparator 
-	{
-		boolean ascending = false;
-
-		static final int FIELD_NAME			= 0;
-		static final int FIELD_ONLINE 		= 1;
-		static final int FIELD_LAST_SEEN 	= 2;
-		static final int FIELD_YGM		 	= 3;
-		static final int FIELD_LAST_MSG 	= 4;
-		static final int FIELD_LOC_CAT	 	= 5;
-		static final int FIELD_REM_CAT 		= 6;
-		static final int FIELD_READ_CAT 	= 7;
-		static final int FIELD_CON		 	= 8;
-		static final int FIELD_MSG_IN	 	= 9;
-		static final int FIELD_MSG_OUT	 	= 10;
-		static final int FIELD_QUEUED	 	= 11;
-		static final int FIELD_BYTES_IN 	= 12;
-		static final int FIELD_BYTES_OUT 	= 13;
-		static final int FIELD_SS		 	= 14;
-
-		int field = FIELD_NAME;
-
-		public int 
-		compare(
-			Object arg0,
-			Object arg1) 
-		{
-			BuddyPluginBuddy b1 = (BuddyPluginBuddy) arg0;
-			BuddyPluginBuddy b2 = (BuddyPluginBuddy) arg1;
-			
-			int	res = 0;
-			
-			if(field == FIELD_NAME){				
-				 res = b1.getName().compareTo( b2.getName());
-			}else if(field == FIELD_ONLINE){
-				res = ( b1.isOnline( false )?1:0 ) - ( b2.isOnline( false )?1:0 );
-			}else if(field == FIELD_LAST_SEEN){
-				res = sortInt( b1.getLastTimeOnline() - b2.getLastTimeOnline());
-			}else if(field == FIELD_YGM){
-				res = sortInt( b1.getLastMessagePending() - b2.getLastMessagePending());
-			}else if(field == FIELD_LAST_MSG){
-				res = b1.getLastMessageReceived().compareTo( b2.getLastMessageReceived());
-			}else if(field == FIELD_LOC_CAT){
-				res = compareStrings( b1.getLocalAuthorisedRSSCategoriesAsString(), b2.getLocalAuthorisedRSSCategoriesAsString());
-			}else if(field == FIELD_REM_CAT){
-				res = compareStrings( b1.getRemoteAuthorisedRSSCategoriesAsString(), b2.getRemoteAuthorisedRSSCategoriesAsString());
-			}else if(field == FIELD_READ_CAT){
-				res = compareStrings( b1.getLocalReadCategoriesAsString(), b2.getLocalReadCategoriesAsString());
-			}else if(field == FIELD_CON){
-				res = b1.getConnectionsString().compareTo( b2.getConnectionsString());
-			}else if(field == FIELD_MSG_IN){
-				res = b1.getMessageInCount() - b2.getMessageInCount();
-			}else if(field == FIELD_MSG_OUT){
-				res = b1.getMessageOutCount() - b2.getMessageOutCount();
-			}else if(field == FIELD_QUEUED){
-				res = b1.getMessageHandler().getMessageCount() - b2.getMessageHandler().getMessageCount();
-			}else if(field == FIELD_BYTES_IN){
-				res = b1.getBytesInCount() - b2.getBytesInCount();
-			}else if(field == FIELD_BYTES_OUT){
-				res = b1.getBytesOutCount() - b2.getBytesOutCount();
-			}else if(field == FIELD_SS){
-				res =  b1.getSubsystem() - b2.getSubsystem();
-			}
-			
-			return(( ascending ? 1 : -1) * res );
-		}
-
-		protected int
-		compareStrings(
-			String	s1,
-			String	s2 )
-		{
-			if ( s1 == null && s2 == null ){
-				return(0);
-			}else if ( s1 == null ){
-				return(-1);
-			}else if ( s2 == null ){
-				return( 1 );
-			}else{
-				return( s1.compareTo(s2));
-			}
-		}
-		
-		protected int
-		sortInt(
-			long	l )
-		{
-			if ( l < 0 ){
-				return( -1 );
-			}else if ( l > 0 ){
-				return( 1 );
-			}else{
-				return( 0 );
-			}
-		}
-		public void 
-		setField(
-			int newField ) 
-		{      
-			if(field == newField) ascending = ! ascending;
-			
-			field = newField;
-		}
-	}
-}
+/*
+ * Created on Apr 2, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.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.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.custom.StyleRange;
+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.*;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.PluginConfig;
+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.UIInstance;
+import org.gudy.azureus2.plugins.ui.UIManagerEvent;
+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.LinkLabel;
+import org.gudy.azureus2.ui.swt.config.IntParameter;
+import org.gudy.azureus2.ui.swt.config.Parameter;
+import org.gudy.azureus2.ui.swt.config.ParameterChangeAdapter;
+import org.gudy.azureus2.ui.swt.mainwindow.Colors;
+import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
+
+import com.aelitis.azureus.core.security.*;
+import com.aelitis.azureus.core.util.AZ3Functions;
+import com.aelitis.azureus.plugins.net.buddy.*;
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+
+public class 
+BuddyPluginViewInstance 
+	implements BuddyPluginListener, BuddyPluginBuddyRequestListener
+{
+	private static final int LOG_NORMAL 	= 1;
+	private static final int LOG_SUCCESS 	= 2;
+	private static final int LOG_ERROR 		= 3;
+
+	private BuddyPluginView		view;
+	private BuddyPlugin			plugin;
+	private UIInstance			ui_instance;
+	private LocaleUtilities		lu;
+	private Composite			composite;
+	private Table 				buddy_table;
+	private StyledText 			log;
+
+	private Text 	public_nickname;
+	private Text 	anon_nickname;
+	
+	private List	buddies = new ArrayList();
+
+	private Button	plugin_install_button;
+	
+	private boolean	init_complete;
+		
+	protected
+	BuddyPluginViewInstance(
+		BuddyPluginView	_view,
+		BuddyPlugin		_plugin,
+		UIInstance		_ui_instance,
+		Composite		_composite )
+	{
+		view		= _view;
+		plugin		= _plugin;
+		ui_instance	= _ui_instance;
+		composite	= _composite;
+
+		lu = plugin.getPluginInterface().getUtilities().getLocaleUtilities();
+			
+		CTabFolder  tab_folder = new CTabFolder(composite, SWT.LEFT);
+		tab_folder.setBorderVisible(true);
+		tab_folder.setTabHeight(20);
+		GridData grid_data = new GridData(GridData.FILL_BOTH);
+		tab_folder.setLayoutData(grid_data);
+		
+		CTabItem beta_item = new CTabItem(tab_folder, SWT.NULL);
+
+		beta_item.setText( lu.getLocalisedMessageText( "azbuddy.dchat.decentralized" ));
+		
+		Composite beta_area = new Composite( tab_folder, SWT.NULL );
+		beta_item.setControl( beta_area );
+		
+		createBeta( beta_area );
+		
+		CTabItem classic_item = new CTabItem(tab_folder, SWT.NULL);
+
+		classic_item.setText( lu.getLocalisedMessageText(  "label.classic" ));
+		
+		Composite classic_area = new Composite( tab_folder, SWT.NULL );
+		classic_item.setControl( classic_area );
+		
+		createClassic( classic_area );
+		
+		tab_folder.setSelection( beta_item );
+	}
+	
+	private void
+	createBeta(
+		Composite main )
+	{	
+		final BuddyPluginBeta plugin_beta = plugin.getBeta();
+		
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 3;
+		//layout.marginHeight = 0;
+		//layout.marginWidth = 0;
+		main.setLayout(layout);
+		GridData grid_data = new GridData(GridData.FILL_BOTH );
+		main.setLayoutData(grid_data);
+
+		if ( !plugin.isBetaEnabled()){
+			
+			Label control_label = new Label( main, SWT.NULL );
+			control_label.setText( lu.getLocalisedMessageText( "azbuddy.disabled" ));
+
+			return;
+		}
+		
+		final BuddyPluginBeta beta = plugin.getBeta();
+		
+		boolean i2p_enabled = plugin_beta.isI2PAvailable();
+
+			// info
+		
+		Composite info_area = new Composite( main, SWT.NULL );
+		layout = new GridLayout();
+		layout.numColumns = 3;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		info_area.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 3;
+		info_area.setLayoutData(grid_data);
+
+		Label label = new Label( info_area, SWT.NULL );
+		
+		label.setText(  lu.getLocalisedMessageText( "azbuddy.dchat.info" ));
+
+		new LinkLabel(info_area, "ConfigView.label.please.visit.here", lu.getLocalisedMessageText( "azbuddy.dchat.link.url" ));
+		
+		label = new Label( info_area, SWT.NULL );
+		
+			// install plugin
+		
+		label = new Label( info_area, SWT.NULL );
+
+		label.setText(  MessageText.getString( "azmsgsync.install.text" ));
+		
+		plugin_install_button = new Button( info_area, SWT.NULL );
+				
+		plugin_install_button.setText( MessageText.getString( "UpdateWindow.columns.install" ));
+		
+		plugin_install_button.addSelectionListener(
+			new SelectionAdapter() {
+				
+				public void 
+				widgetSelected(SelectionEvent e) 
+				{
+					plugin_install_button.setEnabled( false );
+					
+					new AEThread2( "installer" )
+					{
+						public void
+						run()
+						{
+							boolean	ok = false;
+							
+							String	msg;
+							
+							try{
+								installMsgSyncPlugin();
+								
+								msg = MessageText.getString( "azmsgsync.install.ok.msg" );
+								
+								ok = true;
+								
+							}catch( Throwable e ){
+								
+								msg = MessageText.getString( 
+											"azmsgsync.install.fail.msg",
+											new String[]{ Debug.getNestedExceptionMessage( e )});
+								
+							}finally{
+								
+								if ( !checkMsgSyncPlugin()){
+									
+									if ( ok ){
+									
+											// something weird happened
+										
+										ok = false;
+										
+										msg = MessageText.getString(
+												"azmsgsync.install.fail.msg",
+												new String[]{ "Unexpected error, check logs" });
+									}
+								}
+							}
+							
+							plugin.getPluginInterface().getUIManager().showMessageBox(
+								ok?"aztorplugin.browser.install.ok":"aztorplugin.browser.install.fail",
+								"!" + msg + "!",
+								UIManagerEvent.MT_OK );
+						}
+					}.start();
+				}
+			});
+		
+		checkMsgSyncPlugin();
+		
+			// UI
+		
+		final Group ui_area = new Group( main, SWT.NULL );
+		layout = new GridLayout();
+		layout.numColumns = 3;
+		ui_area.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 3;
+		ui_area.setLayoutData(grid_data);
+		
+		ui_area.setText( lu.getLocalisedMessageText( "ConfigView.section.style" ));
+		
+			// shared public nick
+		
+		label = new Label( ui_area, SWT.NULL );
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.public.nick" ));
+
+		public_nickname = new Text( ui_area, SWT.BORDER );
+		grid_data = new GridData();
+		grid_data.widthHint = 200;
+		public_nickname.setLayoutData( grid_data );
+
+		public_nickname.setText( plugin_beta.getSharedPublicNickname());
+		public_nickname.addListener(SWT.FocusOut, new Listener() {
+	        public void handleEvent(Event event) {
+	        	plugin_beta.setSharedPublicNickname( public_nickname.getText().trim());
+	        }
+	    });
+
+		label = new Label( ui_area, SWT.NULL );
+		
+			// shared anon nick
+			
+		label = new Label( ui_area, SWT.NULL );
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.anon.nick" ) );
+	
+		anon_nickname = new Text( ui_area, SWT.BORDER );
+		grid_data = new GridData();
+		grid_data.widthHint = 200;
+		anon_nickname.setLayoutData( grid_data );
+	
+		anon_nickname.setText( plugin_beta.getSharedAnonNickname());
+		anon_nickname.addListener(SWT.FocusOut, new Listener() {
+	        public void handleEvent(Event event) {
+	        	plugin_beta.setSharedAnonNickname( anon_nickname.getText().trim());
+	        }
+	    });
+	
+		label = new Label( ui_area, SWT.NULL );
+
+			// max lines 
+		
+		label = new Label( ui_area, SWT.NULL );
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.ui.max.lines" ) );
+
+		final IntParameter max_lines = new IntParameter(ui_area,
+				"azbuddy.chat.temp.ui.max.lines", 128, Integer.MAX_VALUE );
+		
+		max_lines.setValue( beta.getMaxUILines());
+		
+		max_lines.addChangeListener(
+			new ParameterChangeAdapter()
+			{
+				@Override
+				public void 
+				parameterChanged(
+					Parameter 	p,
+					boolean 	caused_internally ) 
+				{
+					beta.setMaxUILines( max_lines.getValue());
+				}
+			});
+		
+		label = new Label( ui_area, SWT.NULL );
+
+		// max chars 
+		
+		label = new Label( ui_area, SWT.NULL );
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.ui.max.kb" ) );
+
+		final IntParameter max_chars = new IntParameter(ui_area,
+			"azbuddy.chat.temp.ui.max.chars", 1, 512 );
+	
+		max_chars.setValue( beta.getMaxUICharsKB());
+		
+		max_chars.addChangeListener(
+			new ParameterChangeAdapter()
+			{
+				@Override
+				public void 
+				parameterChanged(
+					Parameter 	p,
+					boolean 	caused_internally ) 
+				{
+					beta.setMaxUICharsKB( max_chars.getValue());
+				}
+			});
+		
+		label = new Label( ui_area, SWT.NULL );
+		
+			// hide ratings
+		
+		final Button hide_ratings = new Button( ui_area, SWT.CHECK );
+		
+		hide_ratings.setText( lu.getLocalisedMessageText( "azbuddy.dchat.ui.hide.ratings" ));
+				
+		hide_ratings.setSelection( plugin_beta.getHideRatings());
+		
+		hide_ratings.addSelectionListener(
+				new SelectionAdapter() 
+				{
+					public void 
+					widgetSelected(
+						SelectionEvent ev )
+					{
+						plugin_beta.setHideRatings( hide_ratings.getSelection());
+					}
+				});	
+		
+		label = new Label( ui_area, SWT.NULL );
+		grid_data = new GridData();
+		grid_data.horizontalSpan = 2;
+		label.setLayoutData(grid_data);
+		
+			// standalone windows
+		
+		final Button stand_alone = new Button( ui_area, SWT.CHECK );
+		
+		stand_alone.setText( lu.getLocalisedMessageText( "azbuddy.dchat.ui.standalone.windows" ));
+				
+		stand_alone.setSelection( plugin_beta.getStandAloneWindows());
+		
+		stand_alone.addSelectionListener(
+				new SelectionAdapter() 
+				{
+					public void 
+					widgetSelected(
+						SelectionEvent ev )
+					{
+						plugin_beta.setStandAloneWindows( stand_alone.getSelection());
+					}
+				});	
+		
+		
+			// notifications
+		
+		final Group noti_area = new Group( main, SWT.NULL );
+		layout = new GridLayout();
+		layout.numColumns = 4;
+		noti_area.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 3;
+		noti_area.setLayoutData(grid_data);
+		
+		noti_area.setText( lu.getLocalisedMessageText( "v3.MainWindow.tab.events" ));
+
+		final Button noti_enable = new Button( noti_area, SWT.CHECK );
+		
+		noti_enable.setText( lu.getLocalisedMessageText( "azbuddy.dchat.noti.sound" ));
+		
+		boolean	sound_enabled = plugin_beta.getSoundEnabled();
+		
+		noti_enable.setSelection( sound_enabled );
+		
+		noti_enable.addSelectionListener(
+				new SelectionAdapter() 
+				{
+					public void 
+					widgetSelected(
+						SelectionEvent ev )
+					{
+						plugin_beta.setSoundEnabled( noti_enable.getSelection());
+					}
+				});	
+		
+		
+		final Text noti_file = new Text( noti_area, SWT.BORDER );
+		grid_data = new GridData();
+		grid_data.widthHint = 400;
+		noti_file.setLayoutData( grid_data );
+		
+		String sound_file = plugin_beta.getSoundFile();
+		
+		if ( sound_file.length() == 0 ){
+			
+			sound_file = "<default>";
+		}
+		
+		noti_file.setText( sound_file );
+		
+		noti_file.addListener(
+			SWT.FocusOut,
+			new Listener() {
+				
+				public void handleEvent(Event event){
+					String val = noti_file.getText().trim();
+					
+					if ( val.length() == 0 || val.startsWith( "<" )){
+						
+						noti_file.setText( "<default>" );
+						
+						val = "";
+					}
+					
+					if ( !val.equals( plugin_beta.getSoundFile())){
+						
+						plugin_beta.setSoundFile( val );
+					}
+				}
+			});
+		
+		final Button noti_browse = new Button(noti_area, SWT.PUSH);
+
+		final ImageLoader imageLoader = ImageLoader.getInstance();
+		
+		final Image imgOpenFolder = imageLoader.getImage( "openFolderButton" );
+
+		noti_area.addDisposeListener(
+			new DisposeListener() {
+				
+				public void widgetDisposed(DisposeEvent e) {
+					imageLoader.releaseImage( "openFolderButton" );
+				}
+			});
+		
+		noti_browse.setImage( imgOpenFolder );
+
+		imgOpenFolder.setBackground(noti_browse.getBackground());
+
+		noti_browse.setToolTipText(MessageText.getString("ConfigView.button.browse"));
+
+		noti_browse.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				FileDialog dialog = new FileDialog(noti_area.getShell(),
+						SWT.APPLICATION_MODAL);
+				dialog.setFilterExtensions(new String[] {
+					"*.wav"
+				});
+				dialog.setFilterNames(new String[] {
+					"*.wav"
+				});
+
+				dialog.setText(MessageText.getString( "ConfigView.section.interface.wavlocation" ));
+
+				String path = dialog.open();
+
+				if ( path != null ){
+
+					path = path.trim();
+					
+					if ( path.startsWith( "<" )){
+						
+						path = "";
+					}
+					
+					plugin_beta.setSoundFile( path.trim());
+				}
+				
+				view.playSound();
+			}
+		});
+		
+		label = new Label( noti_area, SWT.WRAP );
+		
+		label.setText( MessageText.getString("ConfigView.section.interface.wavlocation.info"));
+		
+		if ( !sound_enabled ){
+			
+			noti_file.setEnabled( false );
+			noti_browse.setEnabled( false );
+		}
+				
+			// private chats
+		
+		Group private_chat_area = new Group( main, SWT.NULL );
+		layout = new GridLayout();
+		layout.numColumns = 3;
+		//layout.marginHeight = 0;
+		//layout.marginWidth = 0;
+		private_chat_area.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 3;
+		private_chat_area.setLayoutData(grid_data);
+		
+		private_chat_area.setText( lu.getLocalisedMessageText( "label.private.chat" ));
+
+		label = new Label( private_chat_area, SWT.NULL );
+		
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.pc.enable" ));
+		
+		final Button private_chat_enable = new Button( private_chat_area, SWT.CHECK );
+
+		label = new Label( private_chat_area, SWT.NULL );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		label.setLayoutData(grid_data);
+
+		private_chat_enable.addSelectionListener(
+				new SelectionAdapter() 
+				{
+					public void 
+					widgetSelected(
+						SelectionEvent ev )
+					{
+						plugin_beta.setPrivateChatState( private_chat_enable.getSelection()?BuddyPluginBeta.PRIVATE_CHAT_ENABLED:BuddyPluginBeta.PRIVATE_CHAT_DISABLED );
+					}
+				});
+		
+		final Label pc_pinned_only = new Label( private_chat_area, SWT.NULL );
+		
+		pc_pinned_only.setText( lu.getLocalisedMessageText( "azbuddy.dchat.pc.pinned.only" ));
+		
+		final Button private_chat_pinned = new Button( private_chat_area, SWT.CHECK );
+
+		label = new Label( private_chat_area, SWT.NULL );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		label.setLayoutData(grid_data);
+
+		private_chat_pinned.addSelectionListener(
+				new SelectionAdapter() 
+				{
+					public void 
+					widgetSelected(
+						SelectionEvent ev )
+					{
+						plugin_beta.setPrivateChatState( private_chat_pinned.getSelection()?BuddyPluginBeta.PRIVATE_CHAT_PINNED_ONLY:BuddyPluginBeta.PRIVATE_CHAT_ENABLED );
+					}
+				});
+		
+		int pc_state = plugin_beta.getPrivateChatState();
+		
+		private_chat_enable.setSelection( pc_state != BuddyPluginBeta.PRIVATE_CHAT_DISABLED );
+		private_chat_pinned.setSelection( pc_state == BuddyPluginBeta.PRIVATE_CHAT_PINNED_ONLY );
+		
+		private_chat_pinned.setEnabled( pc_state != BuddyPluginBeta.PRIVATE_CHAT_DISABLED );
+		pc_pinned_only.setEnabled( pc_state != BuddyPluginBeta.PRIVATE_CHAT_DISABLED );
+		
+			// import
+			
+		Group import_area = new Group( main, SWT.NULL );
+		layout = new GridLayout();
+		layout.numColumns = 3;
+		import_area.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 3;
+		import_area.setLayoutData(grid_data);
+		
+		import_area.setText( lu.getLocalisedMessageText( "azbuddy.dchat.cannel.import" ));
+	
+		label = new Label( import_area, SWT.NULL );
+		
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.import.data" ));
+		
+		final Text import_data = new Text( import_area, SWT.BORDER );
+		grid_data = new GridData();
+		grid_data.widthHint = 400;
+		import_data.setLayoutData( grid_data );
+			
+		final Button import_button = new Button( import_area, SWT.NULL );
+	
+		import_button.setText( lu.getLocalisedMessageText( "br.restore" ));
+		
+		import_button.addSelectionListener(
+				new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent ev )
+				{
+					import_button.setEnabled( false );
+					
+					final Display display = composite.getDisplay();
+
+					final String data		= import_data.getText().trim();
+					
+					new AEThread2( "async" )
+					{
+						public void
+						run()
+						{
+							if ( display.isDisposed()){
+								
+								return;
+							}
+							
+							try{
+								final BuddyPluginBeta.ChatInstance inst = plugin_beta.importChat( data );
+								
+								display.asyncExec(
+									new Runnable()
+									{
+										public void
+										run()
+										{
+											if ( !display.isDisposed()){
+																							
+												BuddyPluginViewBetaChat chat = new BuddyPluginViewBetaChat( view, plugin, inst );
+													
+												import_button.setEnabled( true );
+												
+												chat.addDisposeListener(
+													new DisposeListener()
+													{
+														public void 
+														widgetDisposed(
+															DisposeEvent e) 
+														{
+															if ( !import_button.isDisposed()){
+															
+																import_button.setEnabled( true );
+															}
+														}
+													});
+											}
+										}
+									});
+									
+							}catch( Throwable e){
+								
+								display.asyncExec(
+									new Runnable()
+									{
+										public void
+										run()
+										{
+											if ( !import_button.isDisposed()){
+											
+												import_button.setEnabled( true );
+											}
+										}
+									});
+								
+								Debug.out( e );
+							}
+						}
+					}.start();
+				}
+			});
+	
+			// Advanced
+		
+		Group adv_area = new Group( main, SWT.NULL );
+		adv_area.setText( lu.getLocalisedMessageText( "MyTorrentsView.menu.advancedmenu" ));
+		layout = new GridLayout();
+		layout.numColumns = 3;
+		adv_area.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 3;
+		adv_area.setLayoutData(grid_data);
+		
+	
+			// shared endpoint
+		
+		label = new Label( adv_area, SWT.NULL );
+		
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.anon.share.endpoint" ));
+	
+		final Button shared_endpoint = new Button( adv_area, SWT.CHECK );
+	
+		shared_endpoint.addSelectionListener(
+				new SelectionAdapter() 
+				{
+					public void 
+					widgetSelected(
+						SelectionEvent ev )
+					{
+						plugin_beta.setSharedAnonEndpoint( shared_endpoint.getSelection());
+					}
+				});	
+		
+		shared_endpoint.setSelection( plugin_beta.getSharedAnonEndpoint());
+		
+		label = new Label( adv_area, SWT.NULL );
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.anon.share.endpoint.info" ));
+	
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		label.setLayoutData(grid_data);
+		
+		
+		
+			// testing
+		
+		Group test_area = new Group( main, SWT.NULL );
+		test_area.setText( lu.getLocalisedMessageText( "br.test" ));
+		layout = new GridLayout();
+		layout.numColumns = 4;
+		test_area.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 3;
+		test_area.setLayoutData(grid_data);
+
+	
+			// public beta channel
+			
+		label = new Label( test_area, SWT.NULL );
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.public.beta" ));
+		
+		Button beta_button = new Button( test_area, SWT.NULL );
+		
+		setupButton( beta_button, lu.getLocalisedMessageText( "Button.open" ), AENetworkClassifier.AT_PUBLIC, BuddyPluginBeta.BETA_CHAT_KEY );
+		
+		label = new Label( test_area, SWT.NULL );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 2;
+		label.setLayoutData(grid_data);
+		
+			// anonymous beta channel
+			
+		label = new Label( test_area, SWT.NULL );
+		
+		label.setText(  lu.getLocalisedMessageText( "azbuddy.dchat.anon.beta" ));
+	
+		Button beta_i2p_button = new Button( test_area, SWT.NULL );
+	
+		setupButton( beta_i2p_button, lu.getLocalisedMessageText( "Button.open" ), AENetworkClassifier.AT_I2P, BuddyPluginBeta.BETA_CHAT_KEY );
+		
+		beta_i2p_button.setEnabled( i2p_enabled );
+		
+		label = new Label( test_area, SWT.NULL );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		grid_data.horizontalSpan = 2;
+		label.setLayoutData(grid_data);
+		
+			// create custom channel
+		
+		label = new Label( test_area, SWT.NULL );
+		label.setText( lu.getLocalisedMessageText( "azbuddy.dchat.create.join.key" ));
+		
+		final Text channel_key = new Text( test_area, SWT.BORDER );
+		grid_data = new GridData();
+		grid_data.widthHint = 200;
+		channel_key.setLayoutData( grid_data );
+		
+		final Button create_i2p_button = new Button( test_area, SWT.CHECK );
+		
+		create_i2p_button.setText( lu.getLocalisedMessageText( "label.anon.i2p" ));
+		
+		create_i2p_button.setEnabled( i2p_enabled );
+
+		final Button create_button = new Button( test_area, SWT.NULL );
+
+		create_button.setText( lu.getLocalisedMessageText( "Button.open" ));
+		
+		create_button.addSelectionListener(
+				new SelectionAdapter() 
+				{
+					public void 
+					widgetSelected(
+						SelectionEvent ev )
+					{
+						create_button.setEnabled( false );
+						
+						final Display display = composite.getDisplay();
+						
+						final String network 	= create_i2p_button.getSelection()?AENetworkClassifier.AT_I2P:AENetworkClassifier.AT_PUBLIC;
+						final String key		= channel_key.getText().trim();
+						
+						new AEThread2( "async" )
+						{
+							public void
+							run()
+							{
+								if ( display.isDisposed()){
+									
+									return;
+								}
+								
+								try{
+									final BuddyPluginBeta.ChatInstance inst = plugin_beta.getChat( network, key );
+									
+									display.asyncExec(
+										new Runnable()
+										{
+											public void
+											run()
+											{
+												if ( !display.isDisposed()){
+																								
+													BuddyPluginViewBetaChat chat = new BuddyPluginViewBetaChat( view, plugin, inst );
+														
+													create_button.setEnabled( true );
+													
+													chat.addDisposeListener(
+														new DisposeListener()
+														{
+															public void 
+															widgetDisposed(
+																DisposeEvent e) 
+															{
+																if ( !create_button.isDisposed()){
+																
+																	create_button.setEnabled( true );
+																}
+															}
+														});
+												}
+											}
+										});
+										
+								}catch( Throwable e){
+									
+									display.asyncExec(
+										new Runnable()
+										{
+											public void
+											run()
+											{
+												if ( !create_button.isDisposed()){
+												
+													create_button.setEnabled( true );
+												}
+											}
+										});
+									
+									Debug.out( e );
+								}
+							}
+						}.start();
+					}
+				});
+		
+		
+			// end of UI
+		
+		List<Button>	buttons = new ArrayList<Button>();
+		
+		buttons.add( create_button );
+		buttons.add( beta_button );
+		buttons.add( beta_i2p_button );
+		buttons.add( import_button );
+		
+		Utils.makeButtonsEqualWidth( buttons );
+		
+		plugin.addListener( 
+				new BuddyPluginAdapter()
+				{			
+					public void updated()
+					{
+						if ( public_nickname.isDisposed()){
+							
+							plugin.removeListener( this );
+							
+						}else{
+							
+							public_nickname.getDisplay().asyncExec(
+								new Runnable()
+								{
+									public void
+									run()
+									{
+										if ( public_nickname.isDisposed()){
+											
+											return;
+										}
+										
+										String nick = plugin_beta.getSharedPublicNickname();
+		
+										if ( !public_nickname.getText().equals( nick )){
+											
+											public_nickname.setText( nick );
+										}
+										
+										nick = plugin_beta.getSharedAnonNickname();
+		
+										if ( !anon_nickname.getText().equals( nick )){
+											
+											anon_nickname.setText( nick );
+										}
+										
+										shared_endpoint.setSelection( plugin_beta.getSharedAnonEndpoint());
+										
+										int pc_state = plugin_beta.getPrivateChatState();
+										
+										private_chat_enable.setSelection( pc_state != BuddyPluginBeta.PRIVATE_CHAT_DISABLED );
+										private_chat_pinned.setSelection( pc_state == BuddyPluginBeta.PRIVATE_CHAT_PINNED_ONLY );
+										private_chat_pinned.setEnabled( pc_state != BuddyPluginBeta.PRIVATE_CHAT_DISABLED );
+										pc_pinned_only.setEnabled( pc_state != BuddyPluginBeta.PRIVATE_CHAT_DISABLED );
+										
+										String str = plugin_beta.getSoundFile();
+										
+										if ( str.length() == 0 ){
+											
+											noti_file.setText("<default>");
+											
+										}else{
+											
+											
+											noti_file.setText( str );
+										}
+										
+										boolean se = plugin_beta.getSoundEnabled();
+										
+										noti_file.setEnabled( se );
+										noti_browse.setEnabled( se );
+									}
+								});
+						}
+					}
+				});
+	}
+
+	private boolean
+	isMsgSyncPluginInstalled()
+	{
+		PluginInterface pi = plugin.getPluginInterface().getPluginManager().getPluginInterfaceByID( "azmsgsync" );
+		
+		return( pi != null ); // && pi.getPluginState().isOperational());
+	}
+	
+	private boolean
+	checkMsgSyncPlugin()
+	{
+		if ( plugin_install_button == null ){
+			
+			return( false );
+		}
+		
+		final boolean installed = isMsgSyncPluginInstalled();
+			
+		Utils.execSWTThread(
+			new Runnable()
+			{
+				public void
+				run()
+				{
+					plugin_install_button.setEnabled( !installed );
+				}
+			});
+		
+		return( installed );
+	}
+	
+	private void
+	installMsgSyncPlugin()
+	
+		throws Throwable
+	{
+		UIFunctions uif = UIFunctionsManager.getUIFunctions();
+		
+		if ( uif == null ){
+			
+			throw( new Exception( "UIFunctions unavailable - can't install plugin" ));
+		}
+		
+		
+		final AESemaphore sem = new AESemaphore( "installer_wait" );
+		
+		final Throwable[] error = { null };
+		
+		uif.installPlugin(
+				"azmsgsync",
+				"azmsgsync.install",
+				new UIFunctions.actionListener()
+				{
+					public void
+					actionComplete(
+						Object		result )
+					{
+						try{
+							if ( result instanceof Boolean ){
+								
+							}else{
+								
+								error[0] = (Throwable)result;
+							}
+						}finally{
+							
+							sem.release();
+						}
+					}
+				});
+		
+		sem.reserve();
+		
+		if ( error[0] instanceof Throwable ){
+			
+			throw((Throwable)error[0] );
+		}
+	}
+	
+	private void
+	setupButton(
+		final Button			button,
+		final String			title,
+		final String			network,
+		final String			key )
+	{
+		button.setText( title );
+		
+		button.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent ev )
+				{
+					button.setEnabled( false );
+					
+					final Display display = composite.getDisplay();
+					
+					new AEThread2( "async" )
+					{
+						public void
+						run()
+						{
+							try{
+								final BuddyPluginBeta.ChatInstance inst = plugin.getBeta().getChat( network, key );
+								
+								display.asyncExec(
+									new Runnable()
+									{
+										public void
+										run()
+										{
+											if ( !display.isDisposed()){
+																							
+												BuddyPluginViewBetaChat chat = new BuddyPluginViewBetaChat( view, plugin, inst );
+															
+												chat.addDisposeListener(
+													new DisposeListener()
+													{
+														public void 
+														widgetDisposed(
+															DisposeEvent e) 
+														{
+															if ( !button.isDisposed()){
+															
+																button.setEnabled( true );
+															}
+														}
+													});
+											}
+										}
+									});
+									
+							}catch( Throwable e){
+								
+								display.asyncExec(
+									new Runnable()
+									{
+										public void
+										run()
+										{
+											if ( !button.isDisposed()){
+												
+												button.setEnabled( true );
+											}										
+										}
+									});
+															
+								Debug.out( e );
+							}
+						}
+					}.start();
+				}
+			});
+	}
+	private void
+	createClassic(
+		Composite main )
+	{	
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		main.setLayout(layout);
+		GridData grid_data = new GridData(GridData.FILL_BOTH );
+		main.setLayoutData(grid_data);
+
+		if ( !plugin.isClassicEnabled()){
+			
+			Label control_label = new Label( main, SWT.NULL );
+			control_label.setText( lu.getLocalisedMessageText( "azbuddy.disabled" ));
+
+			return;
+		}
+			// control area
+		
+		final Composite controls = new Composite(main, SWT.NONE);
+		layout = new GridLayout();
+		layout.numColumns = 6;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		controls.setLayout(layout);
+		grid_data = new GridData(GridData.FILL_HORIZONTAL );
+		controls.setLayoutData(grid_data);
+		
+		Label control_label = new Label( controls, SWT.NULL );
+		control_label.setText( lu.getLocalisedMessageText( "azbuddy.ui.new_buddy" ) + " " );
+		
+		final Text control_text = new Text( controls, SWT.BORDER );
+		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+		control_text.setLayoutData(gridData);
+	
+		final Button control_button = new Button( controls, SWT.NULL );
+		control_button.setText( lu.getLocalisedMessageText( "azbuddy.ui.add" ));
+		
+		control_button.setEnabled( false );
+		
+		control_text.addModifyListener(
+			new ModifyListener() {
+	        	public void 
+	        	modifyText(
+	        		ModifyEvent e ) 
+	        	{					
+					control_button.setEnabled( plugin.verifyPublicKey( control_text.getText().trim())); 
+	        	}
+	        });
+		
+		control_button.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent e )
+				{
+					plugin.addBuddy( control_text.getText().trim(), BuddyPlugin.SUBSYSTEM_AZ2 );
+					
+					control_text.setText( "" );
+				}
+			});
+		
+		final Label control_lab_pk = new Label( controls, SWT.NULL );
+		control_lab_pk.setText( lu.getLocalisedMessageText( "azbuddy.ui.mykey" ) + " ");
+
+		final Text control_val_pk = new Text( controls, SWT.NULL );
+		gridData = new GridData();
+		gridData.widthHint = 400;
+		control_val_pk.setLayoutData(gridData);
+
+		control_val_pk.setEditable( false );
+		control_val_pk.setBackground( control_lab_pk.getBackground());
+		
+		control_val_pk.addKeyListener(
+			new KeyListener()
+			{
+				public void 
+				keyPressed(
+					KeyEvent event) 
+				{
+					int	key = event.character;
+					
+					if (key <= 26 && key > 0){
+						
+						key += 'a' - 1;
+					}
+				
+					if ( event.stateMask == SWT.MOD1 && key == 'a' ){
+	
+						control_val_pk.setSelection( 0, control_val_pk.getText().length());	
+					}
+				}
+				
+				public void 
+				keyReleased(
+					KeyEvent event) 
+				{	
+				}
+			});
+		
+
+	
+
+    	final CryptoManager crypt_man = CryptoManagerFactory.getSingleton();
+
+		byte[]	public_key = crypt_man.getECCHandler().peekPublicKey();
+		  
+		if ( public_key == null ){
+			
+		    Messages.setLanguageText(control_val_pk, "ConfigView.section.security.publickey.undef");
+
+		}else{
+		    			    			    
+			control_val_pk.setText( Base32.encode( public_key ));
+		}
+		
+	    Messages.setLanguageText(control_val_pk, "ConfigView.copy.to.clipboard.tooltip", true);
+
+	    control_val_pk.setCursor(main.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
+	    control_val_pk.setForeground(Colors.blue);
+	    control_val_pk.addMouseListener(new MouseAdapter() {
+	    	public void mouseDoubleClick(MouseEvent arg0) {
+	    		copyToClipboard();
+	    	}
+	    	public void mouseDown(MouseEvent arg0) {
+	    		copyToClipboard();
+	    	}
+	    	protected void
+	    	copyToClipboard()
+	    	{
+    			new Clipboard(control_val_pk.getDisplay()).setContents(new Object[] {control_val_pk.getText()}, new Transfer[] {TextTransfer.getInstance()});
+	    	}
+	    });
+		
+		crypt_man.addKeyListener(
+				new CryptoManagerKeyListener()
+				{
+					public void 
+					keyChanged(
+						final CryptoHandler handler ) 
+					{
+						if ( control_val_pk.isDisposed()){
+							
+							crypt_man.removeKeyListener( this );
+							
+						}else if ( handler.getType() == CryptoManager.HANDLER_ECC ){
+							
+							control_val_pk.getDisplay().asyncExec(
+								new Runnable()
+								{
+									public void 
+									run()
+									{
+										byte[]	public_key = handler.peekPublicKey();
+		
+										if ( public_key == null ){
+																				
+											 Messages.setLanguageText(control_val_pk, "ConfigView.section.security.publickey.undef");
+											
+										}else{
+											
+											control_val_pk.setText( Base32.encode( public_key ));
+										}
+										 
+										controls.layout();
+									}
+								});
+						}
+					}
+					
+					public void
+					keyLockStatusChanged(
+						CryptoHandler		handler )
+					{
+					}
+				});
+		
+		final Button config_button = new Button( controls, SWT.NULL );
+		config_button.setText( lu.getLocalisedMessageText( "plugins.basicview.config" ));
+
+		config_button.addSelectionListener(
+				new SelectionAdapter() 
+				{
+					public void 
+					widgetSelected(
+						SelectionEvent e )
+					{
+						plugin.showConfig();
+					}
+				});
+		
+			// table and log
+		
+		final Composite form = new Composite(main, SWT.NONE);
+		FormLayout flayout = new FormLayout();
+		flayout.marginHeight = 0;
+		flayout.marginWidth = 0;
+		form.setLayout(flayout);
+		gridData = new GridData(GridData.FILL_BOTH);
+		form.setLayoutData(gridData);
+
+
+		final Composite child1 = new Composite(form,SWT.NULL);
+		layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.horizontalSpacing = 0;
+		layout.verticalSpacing = 0;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		child1.setLayout(layout);
+
+		final Sash sash = new Sash(form, SWT.HORIZONTAL);
+	
+		final Composite child2 = new Composite(form,SWT.NULL);
+		layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.horizontalSpacing = 0;
+		layout.verticalSpacing = 0;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		child2.setLayout(layout);
+
+		FormData formData;
+
+			// child1
+		
+		formData = new FormData();
+		formData.left = new FormAttachment(0, 0);
+		formData.right = new FormAttachment(100, 0);
+		formData.top = new FormAttachment(0, 0);
+		child1.setLayoutData(formData);
+
+		final FormData child1Data = formData;
+		
+		final int SASH_WIDTH = 4;
+		
+			// sash
+		
+		formData = new FormData();
+		formData.left = new FormAttachment(0, 0);
+		formData.right = new FormAttachment(100, 0);
+		formData.top = new FormAttachment(child1);
+		formData.height = SASH_WIDTH;
+		sash.setLayoutData(formData);
+
+			// child2
+		
+		formData = new FormData();
+		formData.left = new FormAttachment(0, 0);
+		formData.right = new FormAttachment(100, 0);
+		formData.bottom = new FormAttachment(100, 0);
+		formData.top = new FormAttachment(sash);
+		child2.setLayoutData(formData);
+
+		final PluginConfig pc = plugin.getPluginInterface().getPluginconfig();
+		
+		sash.setData( "PCT", new Float( pc.getPluginFloatParameter( "swt.sash.position", 0.7f )));
+		
+		sash.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent e ) 
+				{
+					if (e.detail == SWT.DRAG){
+						return;
+					}
+					
+					child1Data.height = e.y + e.height - SASH_WIDTH;
+					
+					form.layout();
+	
+					Float l = new Float((double)child1.getBounds().height / form.getBounds().height);
+					
+					sash.setData( "PCT", l );
+					
+					pc.setPluginParameter( "swt.sash.position", l.floatValue());
+				}
+			});
+
+		form.addListener(
+			SWT.Resize, 
+			new Listener() 
+			{
+				public void 
+				handleEvent(Event e) 
+				{
+					Float l = (Float) sash.getData( "PCT" );
+					
+					if ( l != null ){
+						
+						child1Data.height = (int) (form.getBounds().height * l.doubleValue());
+					
+						form.layout();
+					}
+				}
+			});
+			
+			// table
+		
+		buddy_table = new Table(child1, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL);
+
+		final String[] headers = { 
+				"azbuddy.ui.table.name", 
+				"azbuddy.ui.table.online",  
+				"azbuddy.ui.table.lastseen", 
+				"azbuddy.ui.table.last_ygm", 
+				"azbuddy.ui.table.last_msg",
+				"azbuddy.ui.table.loc_cat",
+				"azbuddy.ui.table.rem_cat",
+				"azbuddy.ui.table.read_cat",
+				"azbuddy.ui.table.con",
+				"azbuddy.ui.table.msg_in",
+				"azbuddy.ui.table.msg_out",
+				"azbuddy.ui.table.msg_queued",
+				"MyTrackerView.bytesin",
+				"MyTrackerView.bytesout",
+				"azbuddy.ui.table.ss" };
+
+		int[] sizes = { 250, 100, 100, 100, 200, 100, 100, 100, 75, 75, 75, 75, 75, 75, 40 };
+
+		int[] aligns = { SWT.LEFT, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.LEFT, SWT.LEFT, SWT.LEFT, SWT.LEFT, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER, SWT.CENTER };
+
+		for (int i = 0; i < headers.length; i++){
+
+			TableColumn tc = new TableColumn(buddy_table, aligns[i]);
+				
+			tc.setWidth(sizes[i]);
+
+			Messages.setLanguageText(tc, headers[i]);
+		}	
+
+	    buddy_table.setHeaderVisible(true);
+
+	    TableColumn[] columns = buddy_table.getColumns();
+	    columns[0].setData(new Integer(FilterComparator.FIELD_NAME));
+	    columns[1].setData(new Integer(FilterComparator.FIELD_ONLINE));
+	    columns[2].setData(new Integer(FilterComparator.FIELD_LAST_SEEN));
+	    columns[3].setData(new Integer(FilterComparator.FIELD_YGM));
+	    columns[4].setData(new Integer(FilterComparator.FIELD_LAST_MSG));
+	    columns[5].setData(new Integer(FilterComparator.FIELD_LOC_CAT));
+	    columns[6].setData(new Integer(FilterComparator.FIELD_REM_CAT));
+	    columns[7].setData(new Integer(FilterComparator.FIELD_READ_CAT));
+	    columns[8].setData(new Integer(FilterComparator.FIELD_CON));
+	    columns[9].setData(new Integer(FilterComparator.FIELD_MSG_IN));
+	    columns[10].setData(new Integer(FilterComparator.FIELD_MSG_OUT));
+	    columns[11].setData(new Integer(FilterComparator.FIELD_QUEUED));
+	    columns[12].setData(new Integer(FilterComparator.FIELD_BYTES_IN));
+	    columns[13].setData(new Integer(FilterComparator.FIELD_BYTES_OUT));
+	    columns[14].setData(new Integer(FilterComparator.FIELD_SS));
+	    
+	    
+	    final FilterComparator comparator = new FilterComparator();
+	    
+	    Listener sort_listener = 
+	    	new Listener() 
+	    	{
+		    	public void 
+		    	handleEvent(
+		    		Event e ) 
+		    	{
+		    		TableColumn tc = (TableColumn) e.widget;
+	
+		    		int field = ((Integer) tc.getData()).intValue();
+	
+		    		comparator.setField( field );
+	
+		    		Collections.sort( buddies,comparator);
+	
+		    		updateTable();
+		    	}
+	    	};
+	    
+	    for (int i=0;i<columns.length;i++){
+	    	
+	    	columns[i].addListener(SWT.Selection,sort_listener);
+	    }	    
+	    
+	    gridData = new GridData(GridData.FILL_BOTH);
+	    gridData.heightHint = buddy_table.getHeaderHeight() * 3;
+		buddy_table.setLayoutData(gridData);
+		
+		
+		buddy_table.addListener(
+			SWT.SetData,
+			new Listener()
+			{
+				public void 
+				handleEvent(
+					Event event) 
+				{
+					TableItem item = (TableItem)event.item;
+					
+					int index = buddy_table.indexOf(item);
+	
+					if ( index < 0 || index >= buddies.size()){
+						
+						return;
+					}
+					
+					BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(index);
+					
+					item.setText(0, buddy.getName());
+					
+					int	os;
+					
+					if ( buddy.isOnline( false )){
+						
+						os = buddy.getOnlineStatus();
+						
+					}else{
+						
+						os = BuddyPlugin.STATUS_APPEAR_OFFLINE;
+					}
+					
+					if ( os == BuddyPlugin.STATUS_APPEAR_OFFLINE ){
+						
+						item.setText( 1, "" );
+						
+					}else{
+					
+						item.setText(1, plugin.getOnlineStatus( os ));
+					}
+					
+					long lo = buddy.getLastTimeOnline();
+					
+					item.setText(2, lo==0?"":new SimpleDateFormat().format(new Date( lo )));
+
+					long	last_ygm = buddy.getLastMessagePending();;
+					
+					item.setText(3, last_ygm==0?"":new SimpleDateFormat().format(new Date( last_ygm )));
+					
+					String	lm = buddy.getLastMessageReceived();
+					
+					item.setText(4, lm==null?"":lm);
+					
+					String loc_cat = buddy.getLocalAuthorisedRSSTagsOrCategoriesAsString();
+					if ( loc_cat == null ){
+						loc_cat = "";
+					}
+					item.setText(5, "" + loc_cat);
+
+					String rem_cat = buddy.getRemoteAuthorisedRSSTagsOrCategoriesAsString();
+					if ( rem_cat == null ){
+						rem_cat = "";
+					}
+					item.setText(6, "" + rem_cat);
+
+					String read_cat = buddy.getLocalReadTagsOrCategoriesAsString();
+					if ( read_cat == null ){
+						read_cat = "";
+					}
+					item.setText(7, "" + read_cat);
+
+					item.setText(8, "" + buddy.getConnectionsString());
+					
+					String in_frag = buddy.getMessageInFragmentDetails();
+					
+					item.setText(9, "" + buddy.getMessageInCount() + (in_frag.length()==0?"":("+" + in_frag )));
+					item.setText(10, "" + buddy.getMessageOutCount());
+					item.setText(11, "" + buddy.getMessageHandler().getMessageCount());
+					item.setText(12, "" + DisplayFormatters.formatByteCountToKiBEtc(buddy.getBytesInCount()));
+					item.setText(13, "" + DisplayFormatters.formatByteCountToKiBEtc(buddy.getBytesOutCount()));
+
+					item.setText(14, "" + buddy.getSubsystem() + " v" + buddy.getVersion());
+					
+					item.setData( buddy );
+				}
+			});
+		
+		final Listener tt_label_listener = 
+			new Listener() 
+			{
+				public void handleEvent(Event event) {
+					Label label = (Label) event.widget;
+					Shell shell = label.getShell();
+					switch (event.type) {
+					case SWT.MouseDown:
+						Event e = new Event();
+						e.item = (TableItem) label.getData("_TABLEITEM");
+						buddy_table.setSelection(new TableItem[] { (TableItem) e.item });
+						buddy_table.notifyListeners(SWT.Selection, e);
+						// fall through
+					case SWT.MouseExit:
+						shell.dispose();
+						break;
+					}
+				}
+			};
+
+
+		Listener	tt_table_listener = 
+			new Listener()
+			{
+				private Shell tip = null;
+
+				private Label label = null;
+
+				public void 
+				handleEvent(
+					Event event ) 
+				{
+					switch (event.type){
+						case SWT.Dispose:
+						case SWT.KeyDown:
+						case SWT.MouseMove: {
+							if (tip == null)
+								break;
+							tip.dispose();
+							tip = null;
+							label = null;
+							break;
+						}
+						case SWT.MouseHover: 
+						{
+							Point mouse_position = new Point(event.x, event.y);
+							
+							TableItem item = buddy_table.getItem( mouse_position );
+														
+							if (item != null) {
+								
+								if (tip != null && !tip.isDisposed()){
+									
+									tip.dispose();
+									
+									tip = null;
+								}
+								
+								int index = buddy_table.indexOf(item);
+								
+								if ( index < 0 || index >= buddies.size()){
+									
+									return;
+								}
+
+								BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(index);
+
+								int	item_index = 0;
+								
+								for (int i=0;i<headers.length;i++){
+									
+									Rectangle bounds = item.getBounds(i);
+									
+									if ( bounds.contains( mouse_position )){
+										
+										item_index = i;
+										
+										break;
+									}
+								}
+								
+								if( item_index != 0 ){
+									
+									return;
+								}
+								
+								tip = new Shell(buddy_table.getShell(), SWT.ON_TOP | SWT.TOOL);
+								tip.setLayout(new FillLayout());
+								label = new Label(tip, SWT.NONE);
+								label.setForeground(buddy_table.getDisplay()
+										.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+								label.setBackground(buddy_table.getDisplay()
+										.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+								label.setData("_TABLEITEM", item);
+								
+								label.setText( getToolTip( buddy ));
+								
+								label.addListener(SWT.MouseExit, tt_label_listener);
+								label.addListener(SWT.MouseDown, tt_label_listener);
+								Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+								Rectangle rect = item.getBounds(item_index);
+								Point pt = buddy_table.toDisplay(rect.x, rect.y);
+								tip.setBounds(pt.x, pt.y, size.x, size.y);
+								tip.setVisible(true);
+							}
+						}
+					}
+				}
+				
+				protected String
+				getToolTip(
+					BuddyPluginBuddy	buddy )
+				{
+					List addresses = buddy.getAdjustedIPs();
+					
+					InetAddress	ip	= buddy.getIP();
+					
+					InetAddress adj = buddy.getAdjustedIP();
+					
+					String	str = "";
+					
+					if ( ip == null ){
+						
+						str = "<none>";
+						
+					}else if ( ip == adj ){
+						
+						str = ip.getHostAddress();
+						
+					}else{
+						
+						str = ip.getHostAddress() + "{";
+					
+						for (int i=0;i<addresses.size();i++){
+							
+							str += (i==0?"":"/") + ((InetAddress)addresses.get(i)).getHostAddress();
+						}
+						
+						str += "}";
+					}
+					
+					return(  "ip=" + str + ",tcp=" + buddy.getTCPPort() + ",udp=" + buddy.getUDPPort());
+				}
+			};
+			
+		buddy_table.addListener(SWT.Dispose, tt_table_listener);
+		buddy_table.addListener(SWT.KeyDown, tt_table_listener);
+		buddy_table.addListener(SWT.MouseMove, tt_table_listener);
+		buddy_table.addListener(SWT.MouseHover, tt_table_listener);
+		    			
+
+
+		final Menu menu = new Menu(buddy_table);
+		
+		final MenuItem remove_item = new MenuItem(menu, SWT.PUSH);
+		
+		remove_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.remove" ));
+
+		remove_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent e) 
+				{
+					TableItem[] selection = buddy_table.getSelection();
+					
+					for (int i=0;i<selection.length;i++){
+						
+						BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+						
+						buddy.remove();
+					}
+				};
+			});
+		
+			// get public key
+				
+		final MenuItem get_pk_item = new MenuItem(menu, SWT.PUSH);
+
+		get_pk_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.copypk" ) );
+
+		get_pk_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent event ) 
+				{
+					TableItem[] selection = buddy_table.getSelection();
+					
+					StringBuffer sb = new StringBuffer();
+					
+					for (int i=0;i<selection.length;i++){
+						
+						BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+						
+						sb.append( buddy.getPublicKey() + "\r\n" );
+					}
+					
+					if ( sb.length() > 0 ){
+					
+						writeToClipboard( sb.toString());
+					}
+				};
+			});
+		
+			// disconnect message
+		
+		if ( Constants.isCVSVersion()){
+			final  MenuItem send_msg_item = new MenuItem(menu, SWT.PUSH);
+	
+			send_msg_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.disconnect" ) );
+	
+			send_msg_item.addSelectionListener(
+				new SelectionAdapter() 
+				{
+					public void 
+					widgetSelected(
+						SelectionEvent event ) 
+					{
+						TableItem[] selection = buddy_table.getSelection();
+				
+						for (int i=0;i<selection.length;i++){
+							
+							BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+							
+							buddy.disconnect();
+						}
+					}
+				});
+		}
+		
+			// send message
+		
+		final  MenuItem send_msg_item = new MenuItem(menu, SWT.PUSH);
+
+		send_msg_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.send" ) );
+
+		send_msg_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent event ) 
+				{
+					final TableItem[] selection = buddy_table.getSelection();
+					
+					UIInputReceiver prompter = ui_instance.getInputReceiver();
+					
+					prompter.setLocalisedTitle( lu.getLocalisedMessageText( "azbuddy.ui.menu.send" ));
+					prompter.setLocalisedMessage( lu.getLocalisedMessageText( "azbuddy.ui.menu.send_msg" ) );
+					
+					try{
+						prompter.prompt(new UIInputReceiverListener() {
+							public void UIInputReceiverClosed(UIInputReceiver prompter) {
+								String text = prompter.getSubmittedInput();
+								
+								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 ){
+						
+					}
+				};
+			});
+		
+			// chat
+		
+		final  MenuItem chat_item = new MenuItem(menu, SWT.PUSH);
+
+		chat_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.chat" ) );
+
+		chat_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent event ) 
+				{
+					TableItem[] selection = buddy_table.getSelection();
+					
+					BuddyPluginBuddy[] buddies = new BuddyPluginBuddy[selection.length];
+					
+					for (int i=0;i<selection.length;i++){
+						
+						BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+
+						buddies[i] = buddy;
+					}
+								
+					plugin.getAZ2Handler().createChat( buddies );
+				};
+			});
+		
+			// ping
+		
+		final MenuItem ping_item = new MenuItem(menu, SWT.PUSH);
+
+		ping_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.ping" ) );
+
+		ping_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent event ) 
+				{
+					TableItem[] selection = buddy_table.getSelection();
+					
+					for (int i=0;i<selection.length;i++){
+						
+						BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+						
+						try{					
+							buddy.ping();
+							
+						}catch( Throwable e ){
+							
+							print( "Ping failed", e );
+						}
+					}
+				};
+			});
+		
+			// ygm
+		
+		final MenuItem ygm_item = new MenuItem(menu, SWT.PUSH);
+
+		ygm_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.ygm" ) );
+
+		ygm_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent event ) 
+				{
+					TableItem[] selection = buddy_table.getSelection();
+					
+					for (int i=0;i<selection.length;i++){
+						
+						BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+						
+						try{
+							buddy.setMessagePending();
+							
+						}catch( Throwable e ){
+							
+							print( "YGM failed", e );
+						}
+					}
+				};
+			});
+		
+		
+			// encrypt
+		
+		final MenuItem encrypt_item = new MenuItem(menu, SWT.PUSH);
+
+		encrypt_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.enc" ) );
+
+		encrypt_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent event ) 
+				{
+					TableItem[] selection = buddy_table.getSelection();
+					
+					String	str = readFromClipboard();
+					
+					if( str != null ){
+						
+						StringBuffer sb = new StringBuffer();
+						
+						for (int i=0;i<selection.length;i++){
+							
+							BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+							
+							try{
+								byte[]	contents = str.getBytes( "UTF-8" );
+								
+								BuddyPlugin.cryptoResult result = buddy.encrypt( contents );
+								
+								sb.append( "key: " );
+								sb.append( plugin.getPublicKey());
+								sb.append( "\r\n" );
+								
+								sb.append( "hash: " );
+								sb.append( Base32.encode( result.getChallenge()));
+								sb.append( "\r\n" );
+
+								sb.append( "payload: " );
+								sb.append( Base32.encode( result.getPayload()));
+								sb.append( "\r\n\r\n" );
+								
+							}catch( Throwable e ){
+								
+								print( "YGM failed", e );
+							}
+						}
+						
+						writeToClipboard( sb.toString());
+					}
+				};
+			});
+		
+			// decrypt
+		
+		final MenuItem decrypt_item = new MenuItem(menu, SWT.PUSH);
+
+		decrypt_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.dec" ) );
+
+		decrypt_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent event ) 
+				{
+					String	str = readFromClipboard();
+					
+					if ( str != null ){
+						
+						String[] 	bits = str.split( "\n" );
+						
+						StringBuffer sb = new StringBuffer();
+	
+						BuddyPluginBuddy	buddy 	= null;
+						byte[]				hash	= null;
+						
+						for (int i=0;i<bits.length;i++){
+							
+							String	bit = bits[i].trim();
+							
+							if ( bit.length() > 0 ){
+							
+								int	pos = bit.indexOf( ':' );
+								
+								if ( pos == -1 ){
+									
+									continue;
+								}
+								
+								String	lhs = bit.substring( 0, pos ).trim();
+								String	rhs	= bit.substring( pos+1 ).trim();
+								
+								if ( lhs.equals( "key" )){
+									
+									buddy = plugin.getBuddyFromPublicKey( rhs );
+									
+								}else if ( lhs.equals( "hash" )){
+									
+									hash	= Base32.decode( rhs );
+									
+								}else if ( lhs.equals( "payload" )){
+								
+									byte[]	payload = Base32.decode( rhs );
+									
+									if ( buddy != null ){
+										
+										try{
+											BuddyPlugin.cryptoResult result = buddy.decrypt( payload );
+											
+											byte[] sha1 = new SHA1Simple().calculateHash( result.getChallenge());
+											
+											sb.append( "key: " );
+											sb.append( buddy.getPublicKey());
+											sb.append( "\r\n" );
+
+											sb.append( "hash_ok: " + Arrays.equals( hash, sha1 ));
+											sb.append( "\r\n" );
+											
+											sb.append( "payload: " );
+											sb.append( new String( result.getPayload(), "UTF-8" ));
+											sb.append( "\r\n\r\n" );
+											
+										}catch( Throwable e ){
+											
+											print( "decrypt failed", e );
+										}
+									}
+								}
+							}
+						}
+						
+						if ( sb.length() > 0 ){
+						
+							writeToClipboard( sb.toString());
+						}
+					}
+				};
+			});
+		
+			// sign
+		
+		final MenuItem sign_item = new MenuItem(menu, SWT.PUSH);
+
+		sign_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.sign" ) );
+
+		sign_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent event ) 
+				{
+					String	str = readFromClipboard();
+					
+					if ( str != null ){
+						
+						StringBuffer sb = new StringBuffer();
+						
+						try{
+							sb.append( "key: " );
+							sb.append( plugin.getPublicKey());
+							sb.append( "\r\n" );
+
+							byte[] payload = str.getBytes( "UTF-8" );
+							
+							sb.append( "data: " );
+							sb.append( Base32.encode( payload ));
+							sb.append( "\r\n" );
+
+							byte[]	sig = plugin.sign( payload );
+
+							sb.append( "sig: " );
+							sb.append( Base32.encode( sig ));
+							sb.append( "\r\n" );
+
+						}catch( Throwable e ){
+							
+							print( "sign failed", e );
+						}
+						
+						if ( sb.length() > 0 ){
+						
+							writeToClipboard( sb.toString());
+						}
+					}
+				};
+			});
+		
+			// verify
+		
+		final MenuItem verify_item = new MenuItem(menu, SWT.PUSH);
+
+		verify_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.verify" ) );
+
+		verify_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent event ) 
+				{
+					String	str = readFromClipboard();
+					
+					if ( str != null ){
+						
+						String[] 	bits = str.split( "\n" );
+						
+						StringBuffer sb = new StringBuffer();
+	
+						String				pk 		= null;
+						byte[]				data	= null;
+						
+						for (int i=0;i<bits.length;i++){
+							
+							String	bit = bits[i].trim();
+							
+							if ( bit.length() > 0 ){
+							
+								int	pos = bit.indexOf( ':' );
+								
+								if ( pos == -1 ){
+									
+									continue;
+								}
+								
+								String	lhs = bit.substring( 0, pos ).trim();
+								String	rhs	= bit.substring( pos+1 ).trim();
+								
+								if ( lhs.equals( "key" )){
+									
+									pk = rhs;
+									
+								}else if ( lhs.equals( "data" )){
+									
+									data	= Base32.decode( rhs );
+									
+								}else if ( lhs.equals( "sig" )){
+								
+									byte[]	sig = Base32.decode( rhs );
+									
+									if ( pk != null && data != null ){
+										
+										try{
+											
+											sb.append( "key: " );
+											sb.append( pk );
+											sb.append( "\r\n" );
+
+											boolean ok = plugin.verify( pk, data, sig );
+											
+											sb.append( "sig_ok: " + ok  );
+											sb.append( "\r\n" );
+											
+											sb.append( "data: " );
+											sb.append( new String( data, "UTF-8" ));
+											sb.append( "\r\n\r\n" );
+											
+										}catch( Throwable e ){
+											
+											print( "decrypt failed", e );
+										}
+									}
+								}
+							}
+						}
+						
+						if ( sb.length() > 0 ){
+						
+							writeToClipboard( sb.toString());
+						}
+					}
+				};
+			});
+				
+		
+			// cats
+		
+		Menu cat_menu = new Menu(menu.getShell(), SWT.DROP_DOWN);
+		MenuItem cat_item = new MenuItem(menu, SWT.CASCADE);
+		Messages.setLanguageText(cat_item, "azbuddy.ui.menu.cat" );
+		cat_item.setMenu(cat_menu);
+
+			// cats - share
+		
+		final MenuItem cat_share_item = new MenuItem(cat_menu, SWT.PUSH);
+
+		cat_share_item.setText( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.share" ) );
+
+		cat_share_item.addSelectionListener(
+			new SelectionAdapter() 
+			{
+				public void 
+				widgetSelected(
+					SelectionEvent event ) 
+				{
+					UIInputReceiver prompter = ui_instance.getInputReceiver();
+					
+					prompter.setLocalisedTitle( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.set" ));
+					prompter.setLocalisedMessage( lu.getLocalisedMessageText( "azbuddy.ui.menu.cat.set_msg" ));
+					
+					prompter.prompt(new UIInputReceiverListener() {
+						public void UIInputReceiverClosed(UIInputReceiver prompter) {
+							String cats = prompter.getSubmittedInput();
+							
+							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.setLocalAuthorisedRSSTagsOrCategories( cats );
+								}
+							}
+						}
+					});
+					
+				};
+			});
+		
+			// cats - subscribe
+		
+		final Menu cat_subs_menu = new Menu(cat_menu.getShell(), SWT.DROP_DOWN);
+		final MenuItem cat_subs_item = new MenuItem(cat_menu, SWT.CASCADE);
+		Messages.setLanguageText(cat_subs_item, "azbuddy.ui.menu.cat_subs" );
+		cat_subs_item.setMenu(cat_subs_menu);
+
+		cat_subs_menu.addMenuListener(
+			new MenuListener()
+			{
+				public void 
+				menuShown(
+					MenuEvent arg0 ) 
+				{
+					MenuItem[] items = cat_subs_menu.getItems();
+					
+					for (int i = 0; i < items.length; i++){
+						
+						items[i].dispose();
+					}
+					
+					final AZ3Functions.provider az3 = AZ3Functions.getProvider();
+					
+					if ( az3 != null ){
+						
+						final TableItem[] selection = buddy_table.getSelection();
+						
+						Set<String> avail_cats = new TreeSet<String>();
+						
+						for (int i=0;i<selection.length;i++){
+							
+							BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+							
+							Set<String> cats = buddy.getRemoteAuthorisedRSSTagsOrCategories();
+							
+							if ( cats != null ){
+								
+								avail_cats.addAll( cats );
+							}
+						}
+						
+						for ( final String cat: avail_cats ){
+							
+							final MenuItem subs_item = new MenuItem( cat_subs_menu, SWT.PUSH );
+	
+							subs_item.setText( cat );
+	
+							subs_item.addSelectionListener(
+								new SelectionAdapter() 
+								{
+									public void 
+									widgetSelected(
+										SelectionEvent event ) 
+									{
+										for (int i=0;i<selection.length;i++){
+											
+											BuddyPluginBuddy buddy = (BuddyPluginBuddy)selection[i].getData();
+
+											if ( buddy.isRemoteRSSTagOrCategoryAuthorised( cat )){
+												
+												try{
+													buddy.subscribeToCategory( cat );
+													
+												}catch( Throwable e ){
+													
+													print( "Failed", e );
+												}
+											}
+										}
+									}
+								});
+						}
+					}
+				}
+				
+				public void 
+				menuHidden(
+					MenuEvent arg0 ) 
+				{
+				}
+			});
+		
+		
+			// done with menus
+		
+		buddy_table.setMenu( menu );
+			
+		menu.addMenuListener(
+			new MenuListener()
+			{
+				public void 
+				menuShown(
+					MenuEvent arg0 ) 
+				{
+					boolean	available = plugin.isAvailable();
+					
+					TableItem[] selection = buddy_table.getSelection();
+						
+					remove_item.setEnabled( selection.length > 0 );
+					get_pk_item.setEnabled( available && selection.length > 0 );
+					send_msg_item.setEnabled(available && selection.length > 0);
+					chat_item.setEnabled(available && selection.length > 0);
+					ping_item.setEnabled(available && selection.length > 0);
+					ygm_item.setEnabled(available && selection.length > 0);
+					encrypt_item.setEnabled(selection.length > 0);
+					decrypt_item.setEnabled(true);
+					sign_item.setEnabled(true);
+					verify_item.setEnabled(true);
+				}
+				
+				public void 
+				menuHidden(
+					MenuEvent arg0 ) 
+				{
+				}
+			});
+		
+			// log area
+
+		log = new StyledText(child2,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+		grid_data = new GridData(GridData.FILL_BOTH);
+		grid_data.horizontalSpan = 1;
+		grid_data.horizontalIndent = 4;
+		log.setLayoutData(grid_data);
+		log.setIndent( 4 );
+
+		buddies = plugin.getBuddies();
+		
+		for (int i=0;i<buddies.size();i++){
+			
+			buddyAdded((BuddyPluginBuddy)buddies.get(i));
+		}
+		
+		Collections.sort( buddies, comparator );
+
+		plugin.addListener( this );
+		
+		plugin.addRequestListener( this );
+		
+		init_complete	= true;
+	    
+		updateTable();
+	}
+
+	protected String
+	readFromClipboard()
+	{
+		 Object o = 
+			 new Clipboard(SWTThread.getInstance().getDisplay()).getContents(
+			      TextTransfer.getInstance());
+		 
+		 if ( o instanceof String ){
+			 
+			 return((String)o);
+		 }
+		 
+		 return( null );
+	}
+
+	protected void
+	writeToClipboard(
+		String	str )
+	{
+		 new Clipboard(SWTThread.getInstance().getDisplay()).setContents(
+			      new Object[] {str }, 
+			      new Transfer[] {TextTransfer.getInstance()});
+	}
+
+	protected void
+	updateTable()
+	{
+		if ( init_complete ){
+			
+			buddy_table.setItemCount( buddies.size());
+			buddy_table.clearAll();
+			buddy_table.redraw();
+		}
+	}
+	
+	public void 
+	initialised(
+		boolean available ) 
+	{
+		print( "Initialisation complete: available=" + available );
+	}
+	
+	public void
+	buddyAdded(
+		final BuddyPluginBuddy	buddy )
+	{
+		if ( buddy_table.isDisposed()){
+			
+			return;
+		}
+		
+		buddy.getMessageHandler().addListener(
+			new BuddyPluginBuddyMessageListener()
+			{
+				public void
+				messageQueued(
+					BuddyPluginBuddyMessage		message )
+				{
+					print( message.getBuddy().getName() + ": message queued, id=" + message.getID());
+					
+					update();
+				}
+				
+				public void
+				messageDeleted(
+					BuddyPluginBuddyMessage		message )
+				{
+					print( message.getBuddy().getName() + ": message deleted, id=" + message.getID());
+					
+					update();
+				}
+				
+				public boolean
+				deliverySucceeded(
+					BuddyPluginBuddyMessage		message,
+					Map							reply )
+				{
+					print( message.getBuddy().getName() + ": message delivered, id=" + message.getID() + ", reply=" + reply );
+					
+					update();
+					
+					return( true );
+				}
+				
+				public void
+				deliveryFailed(
+					BuddyPluginBuddyMessage		message,
+					BuddyPluginException		cause )
+				{
+					print( message.getBuddy().getName() + ": message failed, id=" + message.getID(), cause );
+					
+					update();
+				}
+				
+				protected void
+				update()
+				{
+					if ( !buddy_table.isDisposed()){
+						
+						buddy_table.getDisplay().asyncExec(
+							new Runnable()
+							{
+								public void
+								run()
+								{
+									if ( !buddy_table.isDisposed()){
+										
+										updateTable();
+									}
+								}
+							});
+					}
+				}
+			});
+		
+		if ( !buddies.contains( buddy )){
+			
+			buddy_table.getDisplay().asyncExec(
+					new Runnable()
+					{
+						public void
+						run()
+						{
+							if ( !buddy_table.isDisposed()){
+								
+								if ( !buddies.contains( buddy )){
+									
+									buddies.add( buddy );
+									
+									updateTable();
+								}
+							}
+						}
+					});
+		}
+	}
+
+	public void
+	buddyRemoved(
+		final BuddyPluginBuddy	buddy )
+	{
+		if ( !buddy_table.isDisposed()){
+			
+			buddy_table.getDisplay().asyncExec(
+					new Runnable()
+					{
+						public void
+						run()
+						{
+							if ( !buddy_table.isDisposed()){
+								
+								if ( buddies.remove( buddy )){
+																	
+									updateTable();
+								}
+							}
+						}
+					});	
+		}
+	}
+
+	public void
+	buddyChanged(
+		final BuddyPluginBuddy	buddy )
+	{
+		if ( !buddy_table.isDisposed()){
+			
+			buddy_table.getDisplay().asyncExec(
+					new Runnable()
+					{
+						public void
+						run()
+						{
+							if ( !buddy_table.isDisposed()){
+																								
+								updateTable();
+							}
+						}
+					});	
+		}
+	}
+	
+	public void
+	messageLogged(
+		String		str,
+		boolean		error )
+	{
+		print( str, error?LOG_ERROR:LOG_NORMAL, false, false );
+	}
+	
+	public void 
+	enabledStateChanged(
+		boolean enabled )
+	{
+	}
+
+	public void 
+	updated() 
+	{	
+	}
+	
+	public Map
+	requestReceived(
+		BuddyPluginBuddy	from_buddy,
+		int					subsystem,
+		Map					request )
+	
+		throws BuddyPluginException
+	{
+		return( null );
+	}
+	
+	public void
+	pendingMessages(
+		BuddyPluginBuddy[]	from_buddies )
+	{
+		String	str = "";
+		
+		for (int i=0;i<from_buddies.length;i++){
+			
+			str += (str.length()==0?"":",") + from_buddies[i].getName();
+		}
+		
+		print( "YGM received: " + str );
+	}
+	
+	protected void
+	print(
+		String		str,
+		Throwable	e )
+	{
+		print( str + ": " + Debug.getNestedExceptionMessage( e ));
+	}
+	
+	protected void
+	print(
+		String		str )
+	{
+		print( str, LOG_NORMAL, false, true );
+	}
+
+	protected void
+	print(
+		final String		str,
+		final int			log_type,
+		final boolean		clear_first,
+		boolean				log_to_plugin )
+	{
+		if ( log_to_plugin ){
+
+			plugin.log( str );
+		}
+
+		if ( !log.isDisposed()){
+
+			final int f_log_type = log_type;
+
+			log.getDisplay().asyncExec(
+					new Runnable()
+					{
+						public void
+						run()
+						{
+							if ( log.isDisposed()){
+
+								return;
+							}
+
+							int	start;
+
+							if ( clear_first ){
+
+								start	= 0;
+
+								log.setText( str + "\n" );
+
+							}else{
+
+								String	text = log.getText();
+								
+								start = text.length();
+
+								if ( start > 32000 ){
+									
+									log.replaceTextRange( 0, 1024, "" );
+									
+									start = log.getText().length();
+								}
+								
+								log.append( str + "\n" );
+							}
+
+							Color 	color;
+
+							if ( f_log_type == LOG_NORMAL ){
+
+								color = Colors.black;
+
+							}else if ( f_log_type == LOG_SUCCESS ){
+
+								color = Colors.green;
+
+							}else{
+
+								color = Colors.red;
+							}
+
+							if ( color != Colors.black ){
+								
+								StyleRange styleRange = new StyleRange();
+								styleRange.start = start;
+								styleRange.length = str.length();
+								styleRange.foreground = color;
+								log.setStyleRange(styleRange);
+							}
+							
+							log.setSelection( log.getText().length());
+						}
+					});
+		}
+	}
+
+	protected void
+	destroy()
+	{
+		composite = null;
+		
+		plugin.removeListener( this );
+		
+		plugin.removeRequestListener( this );
+
+	}
+	
+	protected class 
+	FilterComparator 
+		implements Comparator 
+	{
+		boolean ascending = false;
+
+		static final int FIELD_NAME			= 0;
+		static final int FIELD_ONLINE 		= 1;
+		static final int FIELD_LAST_SEEN 	= 2;
+		static final int FIELD_YGM		 	= 3;
+		static final int FIELD_LAST_MSG 	= 4;
+		static final int FIELD_LOC_CAT	 	= 5;
+		static final int FIELD_REM_CAT 		= 6;
+		static final int FIELD_READ_CAT 	= 7;
+		static final int FIELD_CON		 	= 8;
+		static final int FIELD_MSG_IN	 	= 9;
+		static final int FIELD_MSG_OUT	 	= 10;
+		static final int FIELD_QUEUED	 	= 11;
+		static final int FIELD_BYTES_IN 	= 12;
+		static final int FIELD_BYTES_OUT 	= 13;
+		static final int FIELD_SS		 	= 14;
+
+		int field = FIELD_NAME;
+
+		public int 
+		compare(
+			Object arg0,
+			Object arg1) 
+		{
+			BuddyPluginBuddy b1 = (BuddyPluginBuddy) arg0;
+			BuddyPluginBuddy b2 = (BuddyPluginBuddy) arg1;
+			
+			int	res = 0;
+			
+			if(field == FIELD_NAME){				
+				 res = b1.getName().compareTo( b2.getName());
+			}else if(field == FIELD_ONLINE){
+				res = ( b1.isOnline( false )?1:0 ) - ( b2.isOnline( false )?1:0 );
+			}else if(field == FIELD_LAST_SEEN){
+				res = sortInt( b1.getLastTimeOnline() - b2.getLastTimeOnline());
+			}else if(field == FIELD_YGM){
+				res = sortInt( b1.getLastMessagePending() - b2.getLastMessagePending());
+			}else if(field == FIELD_LAST_MSG){
+				res = b1.getLastMessageReceived().compareTo( b2.getLastMessageReceived());
+			}else if(field == FIELD_LOC_CAT){
+				res = compareStrings( b1.getLocalAuthorisedRSSTagsOrCategoriesAsString(), b2.getLocalAuthorisedRSSTagsOrCategoriesAsString());
+			}else if(field == FIELD_REM_CAT){
+				res = compareStrings( b1.getRemoteAuthorisedRSSTagsOrCategoriesAsString(), b2.getRemoteAuthorisedRSSTagsOrCategoriesAsString());
+			}else if(field == FIELD_READ_CAT){
+				res = compareStrings( b1.getLocalReadTagsOrCategoriesAsString(), b2.getLocalReadTagsOrCategoriesAsString());
+			}else if(field == FIELD_CON){
+				res = b1.getConnectionsString().compareTo( b2.getConnectionsString());
+			}else if(field == FIELD_MSG_IN){
+				res = b1.getMessageInCount() - b2.getMessageInCount();
+			}else if(field == FIELD_MSG_OUT){
+				res = b1.getMessageOutCount() - b2.getMessageOutCount();
+			}else if(field == FIELD_QUEUED){
+				res = b1.getMessageHandler().getMessageCount() - b2.getMessageHandler().getMessageCount();
+			}else if(field == FIELD_BYTES_IN){
+				res = b1.getBytesInCount() - b2.getBytesInCount();
+			}else if(field == FIELD_BYTES_OUT){
+				res = b1.getBytesOutCount() - b2.getBytesOutCount();
+			}else if(field == FIELD_SS){
+				res =  b1.getSubsystem() - b2.getSubsystem();
+			}
+			
+			return(( ascending ? 1 : -1) * res );
+		}
+
+		protected int
+		compareStrings(
+			String	s1,
+			String	s2 )
+		{
+			if ( s1 == null && s2 == null ){
+				return(0);
+			}else if ( s1 == null ){
+				return(-1);
+			}else if ( s2 == null ){
+				return( 1 );
+			}else{
+				return( s1.compareTo(s2));
+			}
+		}
+		
+		protected int
+		sortInt(
+			long	l )
+		{
+			if ( l < 0 ){
+				return( -1 );
+			}else if ( l > 0 ){
+				return( 1 );
+			}else{
+				return( 0 );
+			}
+		}
+		public void 
+		setField(
+			int newField ) 
+		{      
+			if(field == newField) ascending = ! ascending;
+			
+			field = newField;
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/tracker/BuddyPluginTracker.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/tracker/BuddyPluginTracker.java
index 75157e9..08a3cd5 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/tracker/BuddyPluginTracker.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/tracker/BuddyPluginTracker.java
@@ -1,2324 +1,2326 @@
-/*
- * Created on May 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.plugins.net.buddy.tracker;
-
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.util.*;
-
-import org.gudy.azureus2.core3.global.GlobalManager;
-import org.gudy.azureus2.core3.global.GlobalManagerAdapter;
-import org.gudy.azureus2.core3.peer.PEPeerManager;
-import org.gudy.azureus2.core3.util.AddressUtils;
-import org.gudy.azureus2.core3.util.Average;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.HashWrapper;
-import org.gudy.azureus2.core3.util.LightHashMap;
-import org.gudy.azureus2.core3.util.SHA1;
-import org.gudy.azureus2.core3.util.SimpleTimer;
-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.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadAnnounceResult;
-import org.gudy.azureus2.plugins.download.DownloadListener;
-import org.gudy.azureus2.plugins.download.DownloadManagerListener;
-import org.gudy.azureus2.plugins.download.DownloadPeerListener;
-import org.gudy.azureus2.plugins.download.DownloadScrapeResult;
-import org.gudy.azureus2.plugins.download.DownloadTrackerListener;
-import org.gudy.azureus2.plugins.peers.Peer;
-import org.gudy.azureus2.plugins.peers.PeerEvent;
-import org.gudy.azureus2.plugins.peers.PeerListener2;
-import org.gudy.azureus2.plugins.peers.PeerManager;
-import org.gudy.azureus2.plugins.peers.PeerManagerListener;
-import org.gudy.azureus2.plugins.peers.PeerStats;
-import org.gudy.azureus2.plugins.torrent.Torrent;
-import org.gudy.azureus2.plugins.ui.config.BooleanParameter;
-import org.gudy.azureus2.plugins.ui.config.Parameter;
-import org.gudy.azureus2.plugins.ui.config.ParameterListener;
-import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
-import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
-
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-import com.aelitis.azureus.core.util.CopyOnWriteSet;
-import com.aelitis.azureus.plugins.net.buddy.*;
-
-public class 
-BuddyPluginTracker 
-	implements BuddyPluginListener, DownloadManagerListener, BuddyPluginAZ2TrackerListener, DownloadPeerListener
-{
-	private  static final Object	PEER_KEY		= new Object();		// maps to Download object
-	
-	private static final Object	PEER_STATS_KEY	= new Object();
-	
-	public static final int BUDDY_NETWORK_IDLE		= 1;
-	public static final int BUDDY_NETWORK_OUTBOUND	= 2;
-	public static final int BUDDY_NETWORK_INBOUND	= 3;
-	
-	private static final int	TRACK_CHECK_PERIOD		= 15*1000;
-	private static final int	TRACK_CHECK_TICKS		= TRACK_CHECK_PERIOD/BuddyPlugin.TIMER_PERIOD;
-
-	private static final int	PEER_CHECK_PERIOD		= 60*1000;
-	private static final int	PEER_CHECK_TICKS		= PEER_CHECK_PERIOD/BuddyPlugin.TIMER_PERIOD;
-	
-	private static final int	PEER_RECHECK_PERIOD		= 120*1000;
-	private static final int	PEER_RECHECK_TICKS		= PEER_RECHECK_PERIOD/BuddyPlugin.TIMER_PERIOD;
-
-	private static final int	TRACK_INTERVAL			= 10*60*1000;
-	
-	private static final int	SHORT_ID_SIZE			= 4;
-	private static final int	FULL_ID_SIZE			= 20;
-	
-	private static final int	REQUEST_TRACKER_SUMMARY	= 1;
-	private static final int	REPLY_TRACKER_SUMMARY	= 2;
-	private static final int	REQUEST_TRACKER_STATUS	= 3;
-	private static final int	REPLY_TRACKER_STATUS	= 4;
-	private static final int	REQUEST_TRACKER_CHANGE	= 5;
-	private static final int	REPLY_TRACKER_CHANGE	= 6;
-	private static final int	REQUEST_TRACKER_ADD		= 7;
-	private static final int	REPLY_TRACKER_ADD		= 8;
-	
-	private static final int	RETRY_SEND_MIN			= 5*60*1000;
-	private static final int	RETRY_SEND_MAX			= 60*60*1000;
-	
-	private static final int	BUDDY_NO		= 0;
-	private static final int	BUDDY_MAYBE		= 1;
-	private static final int	BUDDY_YES		= 2;
-	
-	private BuddyPlugin		plugin;
-	
-	private boolean			plugin_enabled;
-	private boolean			tracker_enabled;
-	private boolean			seeding_only;
-	
-	private boolean			old_plugin_enabled;
-	private boolean			old_tracker_enabled;
-	private boolean			old_seeding_only;
-	
-	private int				network_status = BUDDY_NETWORK_IDLE;
-	
-	private Set				online_buddies 			= new HashSet();
-	private Map				online_buddy_ips		= new HashMap();
-	
-	private Set				tracked_downloads		= new HashSet();
-	private int				download_set_id;
-	
-	private Set				last_processed_download_set;
-	private int				last_processed_download_set_id;
-	
-	private Map				short_id_map	= new HashMap();
-	private Map				full_id_map		= new HashMap();
-	
-	private Set				actively_tracking	= new HashSet();
-		
-	private CopyOnWriteSet<Peer>	buddy_peers	= new CopyOnWriteSet<Peer>( true );
-	
-	private CopyOnWriteList	listeners = new CopyOnWriteList();
-	
-	private TimerEventPeriodic	buddy_stats_timer;
-	
-	private Average buddy_receive_speed = Average.getInstance(1000, 10);
-	
-	private Average buddy_send_speed 	= Average.getInstance(1000, 10);
-	
-	public
-	BuddyPluginTracker(
-		BuddyPlugin					_plugin,
-		BasicPluginConfigModel		_config )
-	{
-		plugin		= _plugin;
-		
-		final BooleanParameter te = _config.addBooleanParameter2("azbuddy.tracker.enabled", "azbuddy.tracker.enabled", true );
-		
-		tracker_enabled = te.getValue();
-		
-		te.addListener(
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					Parameter param )
-				{
-					tracker_enabled = te.getValue();
-					
-					checkEnabledState();
-				}
-			});
-		
-		// Assumed if we already have a plugin reference, that the
-		// Azureus Core is available
-		GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
-		
-		gm.addListener(
-			new GlobalManagerAdapter()
-			{
-				public void 
-				seedingStatusChanged( 
-					boolean seeding_only_mode,
-					boolean potentially_seeding_only )
-				{
-					seeding_only = potentially_seeding_only;
-					
-					checkEnabledState();
-				}
-			}, false );
-		
-		seeding_only = gm.isPotentiallySeedingOnly();
-		
-		checkEnabledState();
-	}
-	
-	public void
-	initialise()
-	{
-		plugin_enabled = plugin.isEnabled();
-		
-		checkEnabledState();
-		
-		List buddies = plugin.getBuddies();
-		
-		for (int i=0;i<buddies.size();i++){
-			
-			buddyAdded((BuddyPluginBuddy)buddies.get(i));
-		}
-		
-		plugin.addListener( this );
-		
-		plugin.getAZ2Handler().addTrackerListener( this );
-
-		plugin.getPluginInterface().getDownloadManager().addListener( this, true );
-	}
-	
-	public void
-	tick(
-		int		tick_count )
-	{
-		if ( tick_count % TRACK_CHECK_TICKS == 0 ){
-			
-			checkTracking();
-		}
-		
-		if ( ( tick_count-1 ) % TRACK_CHECK_TICKS == 0 ){
-			
-			doTracking();
-		}
-		
-		if ( tick_count % PEER_CHECK_TICKS == 0 ){
-			
-			checkPeers();
-		}
-		
-		if ( tick_count % PEER_RECHECK_TICKS == 0 ){
-			
-			recheckPeers();
-		}
-	}
-	
-	public int
-	getNetworkStatus()
-	{
-		return( network_status );
-	}
-	
-	public long
-	getNetworkReceiveBytesPerSecond()
-	{
-		return( buddy_receive_speed.getAverage());
-	}
-	
-	public long
-	getNetworkSendBytesPerSecond()
-	{
-		return( buddy_send_speed.getAverage());
-	}
-	
-	protected void
-	doTracking()
-	{
-		if ( !( plugin_enabled && tracker_enabled )){
-			
-			return;
-		}
-
-		Map	to_do = new HashMap();
-		
-		Set active_set = new HashSet();
-		
-		synchronized( online_buddies ){
-
-			Iterator it = online_buddies.iterator();
-				
-			while( it.hasNext()){
-				
-				BuddyPluginBuddy	buddy = (BuddyPluginBuddy)it.next();
-				
-				buddyData buddy_data = getBuddyData( buddy );
-				
-				Map active = buddy_data.getDownloadsToTrack();
-				
-				if ( active.size() > 0 ){
-					
-					Iterator it2 = active.entrySet().iterator();
-					
-					List track_now = new ArrayList();
-					
-					while( it2.hasNext()){
-						
-						Map.Entry entry = (Map.Entry)it2.next();
-						
-						Download 	dl 	= (Download)entry.getKey();
-						boolean		now = ((Boolean)entry.getValue()).booleanValue();
-						
-						if ( now ){
-							
-							track_now.add( dl );
-						}
-						
-						active_set.add( dl );
-					}
-					
-					if( track_now.size() > 0 ){
-					
-						to_do.put( buddy, track_now );
-					}
-				}
-			}
-		}
-		
-		synchronized( actively_tracking ){
-			
-			Iterator it = active_set.iterator();
-			
-			while( it.hasNext()){
-				
-				Download dl = (Download)it.next();
-				
-				if ( !actively_tracking.contains( dl )){
-					
-					actively_tracking.add( dl );
-					
-					trackPeers( dl );
-				}
-			}
-			
-			it = actively_tracking.iterator();
-			
-			while( it.hasNext()){
-				
-				Download dl = (Download)it.next();
-				
-				if ( !active_set.contains( dl )){
-					
-					it.remove();
-					
-					untrackPeers( dl );
-				}
-			}
-		}
-		
-		Iterator it = to_do.entrySet().iterator();
-		
-		while( it.hasNext()){
-			
-			Map.Entry	entry = (Map.Entry)it.next();
-					
-			BuddyPluginBuddy buddy = (BuddyPluginBuddy)entry.getKey();
-			
-			if ( !buddy.isOnline( false )){
-				
-				continue;
-			}
-			
-			InetAddress ip 			= buddy.getAdjustedIP();
-			
-			if ( ip == null ){
-				
-				continue;
-			}
-			
-			int			tcp_port	= buddy.getTCPPort();
-			int			udp_port	= buddy.getUDPPort();
-			
-			List	downloads = (List)entry.getValue();
-			
-			for (int i=0;i<downloads.size();i++){
-				
-				Download	download = (Download)downloads.get(i);
-				
-				PeerManager pm = download.getPeerManager();
-				
-				if ( pm == null ){
-					
-					continue;
-				}
-				
-				Peer[] existing_peers = pm.getPeers( ip.getHostAddress());
-			
-				boolean	connected = false;
-				
-				for (int j=0;j<existing_peers.length;j++){
-					
-					Peer peer = existing_peers[j];
-					
-					if ( 	peer.getTCPListenPort() == tcp_port ||
-							peer.getUDPListenPort() == udp_port ){
-						
-						connected = true;
-						
-						break;
-					}	
-				}
-				
-				if ( connected ){
-					
-					log( download.getName() + " - peer " + ip.getHostAddress() + " already connected" );
-					
-					continue;
-				}
-				
-				log( download.getName() + " - connecting to peer " + ip.getHostAddress());
-
-				PEPeerManager c_pm = PluginCoreUtils.unwrap( pm ); 
-				
-				Map	user_data = new LightHashMap();
-				
-				user_data.put( PEER_KEY, download );
-				
-				user_data.put( Peer.PR_PRIORITY_CONNECTION, new Boolean( true ));
-				
-				c_pm.addPeer( ip.getHostAddress(), tcp_port, udp_port, true, user_data );
-			}
-		}
-	}
-	
-	protected void
-	checkTracking()
-	{
-		if ( !( plugin_enabled && tracker_enabled )){
-			
-			return;
-		}
-		
-		List	online;
-		
-		synchronized( online_buddies ){
-
-			online = new ArrayList( online_buddies );
-		}
-		
-		Set			downloads;
-		int			downloads_id;
-		
-		synchronized( tracked_downloads ){
-			
-			boolean downloads_changed = last_processed_download_set_id != download_set_id;
-			
-			if ( downloads_changed ){
-				
-				last_processed_download_set 	= new HashSet( tracked_downloads );
-				last_processed_download_set_id	= download_set_id;
-			}
-			
-			downloads 		= last_processed_download_set;
-			downloads_id	= last_processed_download_set_id;
-		}
-		
-		Map	diff_map = new HashMap();
-		
-		for (int i=0;i<online.size();i++){
-			
-			BuddyPluginBuddy	buddy = (BuddyPluginBuddy)online.get(i);
-			
-			buddyData buddy_data = getBuddyData( buddy );
-			
-			buddy_data.updateLocal( downloads, downloads_id, diff_map );
-		}
-	}		
-	
-	public void
-	initialised(
-		boolean		available )
-	{	
-	}
-	
-	public void
-	buddyAdded(
-		BuddyPluginBuddy	buddy )
-	{
-		buddyChanged( buddy );
-	}
-	
-	public void
-	buddyRemoved(
-		BuddyPluginBuddy	buddy )
-	{
-		buddyChanged( buddy );
-	}
-
-	public void
-	buddyChanged(
-		BuddyPluginBuddy	buddy )
-	{	
-		if ( buddy.isOnline( false )){
-			
-			addBuddy( buddy );
-			
-		}else{
-			
-			removeBuddy( buddy );
-		}
-	}
-	
-	protected buddyData
-	getBuddyData(
-		BuddyPluginBuddy		buddy )
-	{
-		synchronized( online_buddies ){
-			
-			buddyData buddy_data = (buddyData)buddy.getUserData( BuddyPluginTracker.class );
-
-			if ( buddy_data == null ){
-				
-				buddy_data = new buddyData( buddy );
-				
-				buddy.setUserData( BuddyPluginTracker.class, buddy_data );
-			}
-			
-			return( buddy_data );
-		}
-	}
-	
-	protected buddyData
-	addBuddy(
-		BuddyPluginBuddy		buddy )
-	{
-		synchronized( online_buddies ){
-			
-			if ( !online_buddies.contains( buddy )){
-				
-				online_buddies.add( buddy );
-			}
-			
-			buddyData bd = getBuddyData( buddy );
-			
-			if ( bd.hasIPChanged()){
-				
-				String	ip = bd.getIP();
-				
-				if ( ip != null ){
-					
-					List	l = (List)online_buddy_ips.get( ip );
-					
-					if ( l != null ){
-						
-						l.remove( buddy );
-						
-						if ( l.size() == 0 ){
-							
-							online_buddy_ips.remove( ip );
-						}
-					}
-				}
-				
-				bd.updateIP();
-				
-				ip = bd.getIP();
-				
-				if ( ip != null ){
-					
-					List l = (List)online_buddy_ips.get( ip );
-					
-					if ( l == null ){
-						
-						l = new ArrayList();
-						
-						online_buddy_ips.put( ip, l );
-					}
-				
-					l.add( buddy );
-				}
-			}
-			
-			return( bd );
-		}
-	}
-		
-	protected void
-	removeBuddy(
-		BuddyPluginBuddy		buddy )
-	{		
-		synchronized( online_buddies ){
-
-			if ( online_buddies.contains( buddy )){
-				
-				buddyData bd = getBuddyData( buddy );
-
-				online_buddies.remove( buddy );
-				
-				String	ip = bd.getIP();
-				
-				if ( ip != null ){
-					
-					List	l = (List)online_buddy_ips.get( ip );
-					
-					if ( l != null ){
-						
-						l.remove( buddy );
-						
-						if ( l.size() == 0 ){
-							
-							online_buddy_ips.remove( ip );
-						}
-					}
-				}
-			}
-		}
-	}
-	
-	protected int
-	isBuddy(
-		Peer		peer )
-	{
-		String	peer_ip = peer.getIp();
-		
-		List ips = AddressUtils.getLANAddresses( peer_ip );
-
-		synchronized( online_buddies ){
-			
-			int	result = BUDDY_NO;
-		
-			String	tested = "";
-outer:	
-			for (int i=0;i<ips.size();i++){
-
-				String ip = (String)ips.get(i);
-				
-				tested += ip;
-				
-				List buddies =(List)online_buddy_ips.get( ip  );
-			
-				if ( buddies != null ){
-									
-					if ( peer.getTCPListenPort() == 0 && peer.getUDPListenPort() == 0 ){
-						
-						result = BUDDY_MAYBE;
-						
-					}else{
-					
-						for (int j=0;j<buddies.size();j++){
-								
-							BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(j);
-								
-							if (	buddy.getTCPPort() == peer.getTCPListenPort() &&
-									buddy.getTCPPort() != 0 ){
-								
-								result =  BUDDY_YES;
-								
-								break outer;
-							}
-									
-							if (	buddy.getUDPPort() == peer.getUDPListenPort() &&
-									buddy.getUDPPort() != 0 ){
-								
-								result =  BUDDY_YES;
-								
-								break outer;
-							}
-						}
-					}
-				}
-			}
-			
-			// log( "isBuddy: " + peer_ip + " -> " + result + ",tested=" + tested );
-			
-			return( result );
-		}
-	}
-	
-	public void
-	messageLogged(
-		String		str,
-		boolean		error )
-	{	
-	}
-	
-	public void
-	enabledStateChanged(
-		boolean 	_enabled )
-	{
-		plugin_enabled = _enabled;
-		
-		checkEnabledState();
-	}
-	
-	public boolean
-	isEnabled()
-	{
-		synchronized( this ){
-			
-			return( plugin_enabled && tracker_enabled );
-		}
-	}
-	
-	protected void
-	checkEnabledState()
-	{
-		boolean	seeding_change 	= false;
-		boolean	enabled_change	= false;
-		
-		synchronized( this ){
-			
-			boolean	old_enabled = old_plugin_enabled && old_tracker_enabled;
-			
-			if ( plugin_enabled != old_plugin_enabled ){
-				
-				log( "Plugin enabled state changed to " + plugin_enabled );
-				
-				old_plugin_enabled = plugin_enabled;
-			}
-			
-			if ( tracker_enabled != old_tracker_enabled ){
-				
-				log( "Tracker enabled state changed to " + tracker_enabled );
-				
-				old_tracker_enabled = tracker_enabled;
-			}
-			
-			if ( seeding_only != old_seeding_only ){
-				
-				log( "Seeding-only state changed to " + seeding_only );
-				
-				old_seeding_only = seeding_only;
-				
-				seeding_change = true;
-			}
-			
-			enabled_change = old_enabled != ( plugin_enabled && tracker_enabled );
-		}
-		
-		if ( seeding_change ){
-			
-			updateSeedingMode();
-		}
-		
-		if ( enabled_change ){
-			
-			fireEnabledChanged( isEnabled());
-		}
-	}
-	
-	protected void
-	updateSeedingMode()
-	{
-		updateNetworkStatus();
-		
-		List	online;
-		
-		synchronized( online_buddies ){
-
-			online = new ArrayList( online_buddies );
-		}
-		
-		for (int i=0;i<online.size();i++){
-			
-			buddyData buddy_data = getBuddyData((BuddyPluginBuddy)online.get(i));
-			
-			if ( buddy_data.hasDownloadsInCommon()){
-				
-				buddy_data.updateStatus();
-			}
-		}
-	}
-	
-	public void
-	downloadAdded(
-		final Download	download )
-	{
-		Torrent t = download.getTorrent();
-		
-		if ( t == null ){
-			
-			return;
-		}
-		
-		if ( t.isPrivate()){
-			
-			download.addTrackerListener(
-				new DownloadTrackerListener()
-				{
-					public void 
-					scrapeResult(
-						DownloadScrapeResult result )
-					{					
-					}
-	
-					public void 
-					announceResult(
-						DownloadAnnounceResult result)
-					{
-						if ( okToTrack( download )){
-							
-							trackDownload( download );
-							
-						}else{
-							
-							untrackDownload( download );
-						}						
-					}
-				}, 
-				false );
-		}
-		
-		if ( okToTrack( download )){
-			
-			trackDownload( download );
-		}
-		
-		download.addListener(
-			new DownloadListener()
-			{
-				public void
-				stateChanged(
-					Download		download,
-					int				old_state,
-					int				new_state )
-				{
-					if ( okToTrack( download )){
-						
-						trackDownload( download );
-						
-					}else{
-						
-						untrackDownload( download );
-					}
-				}
-
-				public void
-				positionChanged(
-					Download	download, 
-					int 		oldPosition,
-					int 		newPosition )
-				{
-				}
-			});
-	}
-	
-	public void
-	downloadRemoved(
-		Download	download )
-	{
-		untrackDownload( download );
-	}
-	
-	protected void
-	trackDownload(
-		Download	download )
-	{
-		synchronized( tracked_downloads ){
-			
-			if ( tracked_downloads.contains( download )){
-				
-				return;
-			}
-							
-			downloadData download_data = new downloadData( download );
-				
-			download.setUserData( BuddyPluginTracker.class, download_data );
-			
-			HashWrapper	full_id		= download_data.getID();
-			
-			HashWrapper short_id 	= new HashWrapper( full_id.getHash(), 0, 4 );
-			
-			full_id_map.put( full_id, download );
-			
-			List	dls = (List)short_id_map.get( short_id );
-			
-			if ( dls == null ){
-				
-				dls = new ArrayList();
-				
-				short_id_map.put( short_id, dls );
-			}
-			
-			dls.add( download );
-			
-			tracked_downloads.add( download );
-			
-			download_set_id++;
-		}
-	}
-	
-	protected void
-	untrackDownload(
-		Download	download )
-	{
-		synchronized( tracked_downloads ){
-			
-			if ( tracked_downloads.remove( download )){
-				
-				download_set_id++;
-				
-				downloadData download_data = (downloadData)download.getUserData( BuddyPluginTracker.class );
-								
-				download.setUserData( BuddyPluginTracker.class, null );
-				
-				HashWrapper	full_id		= download_data.getID();
-				
-				full_id_map.remove( full_id );
-				
-				HashWrapper short_id 	= new HashWrapper( full_id.getHash(), 0, SHORT_ID_SIZE );
-				
-				List	dls = (List)short_id_map.get( short_id );
-
-				if ( dls != null ){
-					
-					dls.remove( download );
-					
-					if ( dls.size() == 0 ){
-						
-						short_id_map.remove( short_id );
-					}
-				}
-			}
-		}
-		
-		synchronized( online_buddies ){
-
-			Iterator it = online_buddies.iterator();
-				
-			while( it.hasNext()){
-				
-				BuddyPluginBuddy	buddy = (BuddyPluginBuddy)it.next();
-				
-				buddyData buddy_data = getBuddyData( buddy );
-				
-				buddy_data.resetTracking( download );
-			}
-		}
-		
-		synchronized( actively_tracking ){
-
-			actively_tracking.remove( download );
-		}
-	}
-	
-	protected void
-	trackPeers(
-		final Download		download )
-	{
-		PeerManager pm = download.getPeerManager();
-		
-			// not running
-		
-		if ( pm == null ){
-
-			synchronized( actively_tracking ){
-
-				actively_tracking.remove( download );
-			}
-		}else{
-			
-			log( "Tracking peers for " + download.getName());
-						
-			download.addPeerListener( this );
-		}
-	}
-	
-	public void
-	peerManagerAdded(
-		Download		download,
-		PeerManager		peer_manager )
-	{
-		trackPeers( download, peer_manager );
-	}
-	
-	public void
-	peerManagerRemoved(
-		Download		download,
-		PeerManager		peer_manager )
-	{
-		synchronized( actively_tracking ){
-
-			actively_tracking.remove( download );
-		}
-		
-		download.removePeerListener( this );
-	}
-	
-	protected void
-	trackPeers(
-		final Download	download,
-		PeerManager		pm )
-	{
-		pm.addListener(
-			new PeerManagerListener()
-			{
-				public void
-				peerAdded(
-					PeerManager		manager,
-					Peer			peer )
-				{
-					synchronized( actively_tracking ){
-						
-						if ( !actively_tracking.contains( download )){
-							
-							manager.removeListener( this );
-							
-							return;
-						}
-					}
-				
-					trackPeer( download, peer );
-				}
-				
-				public void
-				peerRemoved(
-					PeerManager	manager,
-					Peer		peer )
-				{
-				}
-			});
-		
-		Peer[] peers = pm.getPeers();
-		
-		for (int i=0;i<peers.length;i++){
-			
-			trackPeer( download, peers[i] );
-		}
-	}
-	
-	protected void
-	trackPeer(
-		final Download	download,
-		final Peer		peer )
-	{
-		int type = isBuddy( peer );
-		
-		if ( type == BUDDY_YES ){
-			
-			markBuddyPeer( download, peer );
-			
-		}else if ( type == BUDDY_MAYBE ){
-			
-				// mark as peer early so that we get optimistic disconnect if needed
-			
-			markBuddyPeer( download, peer );
-			
-			PeerListener2 listener = 
-				new PeerListener2()
-				{
-					public void 
-					eventOccurred(
-						PeerEvent event )
-					{
-						if ( event.getType() == PeerEvent.ET_STATE_CHANGED ){
-							
-							if (((Integer)event.getData()).intValue() == Peer.TRANSFERING ){
-								
-								peer.removeListener( this );
-								
-									// withdraw buddy marker if it turns out our earlier optimism
-									// was misplaced
-								
-								if ( isBuddy( peer ) != BUDDY_YES ){
-									
-									unmarkBuddyPeer( peer );
-								}
-							}
-						}
-					}
-				};
-				
-			peer.addListener( listener );
-
-			if ( peer.getState() == Peer.TRANSFERING ){
-				
-				peer.removeListener( listener );
-				
-					// withdraw buddy marker if it turns out our earlier optimism
-					// was misplaced
-			
-				if ( isBuddy( peer ) != BUDDY_YES ){
-					
-					unmarkBuddyPeer( peer );
-				}
-			}
-		}
-	}
-	
-	protected void
-	untrackPeers(
-		Download		download )
-	{
-		log( "Not tracking peers for " + download.getName());
-		
-		download.removePeerListener( this );
-		
-		PeerManager pm = download.getPeerManager();
-		
-		if ( pm != null ){
-
-			Peer[] peers = pm.getPeers();
-			
-			for (int i=0;i<peers.length;i++){
-				
-				Peer	peer = peers[i];
-				
-				unmarkBuddyPeer( peer );
-			}
-		}
-	}
-	
-	protected void
-	markBuddyPeer(
-		final Download		download,
-		final Peer			peer )
-	{
-		boolean	state_changed 	= false;
-		
-		synchronized( buddy_peers ){
-			
-			if ( !buddy_peers.contains( peer )){
-				
-				log( "Adding buddy peer " + peer.getIp());
-				
-				if ( buddy_peers.size() == 0 ){
-					
-					if ( buddy_stats_timer == null ){
-						
-						buddy_stats_timer = 
-							SimpleTimer.addPeriodicEvent(
-								"BuddyTracker:stats",
-								1000,
-								new TimerEventPerformer()
-								{
-									public void 
-									perform(
-										TimerEvent event )
-									{
-										Iterator it = buddy_peers.iterator();
-										
-										long	total_sent		= 0;
-										long	total_received	= 0;
-										
-										while( it.hasNext()){
-											
-											Peer	p = (Peer)it.next();
-											
-											PeerStats ps = p.getStats();
-											
-											long sent		= ps.getTotalSent();
-											long received 	= ps.getTotalReceived();
-											
-											long[]	last = (long[])p.getUserData( PEER_STATS_KEY );
-											
-											if ( last != null ){
-												
-												total_sent 		+= sent - last[0];
-												total_received	+= received - last[1];
-											}
-											
-											p.setUserData( PEER_STATS_KEY, new long[]{ sent, received });
-										}
-										
-										buddy_receive_speed.addValue( total_received );
-										buddy_send_speed.addValue( total_sent );
-									}
-								});
-					}
-					
-					state_changed 	= true;
-				}
-				
-				buddy_peers.add( peer );
-				
-				peer.setUserData( PEER_KEY, download );
-				
-				peer.setPriorityConnection( true );
-								
-				log( download.getName() + ": adding buddy peer " + peer.getIp());
-
-				peer.addListener(
-					new PeerListener2()
-					{ 
-						public void 
-						eventOccurred(
-							PeerEvent event )
-						{
-							if ( event.getType() == PeerEvent.ET_STATE_CHANGED ){
-								
-								int	state = ((Integer)event.getData()).intValue();
-								
-								if ( state == Peer.CLOSING || state == Peer.DISCONNECTED ){
-									
-									peer.removeListener( this );
-									
-									unmarkBuddyPeer( peer );
-								}
-							}	
-						}
-					});
-			}
-		}
-		
-		if ( peer.getState() == Peer.CLOSING || peer.getState() == Peer.DISCONNECTED ){
-			
-			unmarkBuddyPeer( peer );
-		}
-		
-		if ( state_changed ){
-			
-			updateNetworkStatus();
-		}
-	}
-	
-	protected void
-	unmarkBuddyPeer(
-		Peer		peer )
-	{
-		boolean	state_changed = false;
-		
-		synchronized( buddy_peers ){
-
-			Download download = (Download)peer.getUserData( PEER_KEY );
-				
-			if ( download == null ){
-				
-				return;
-			}
-
-			if ( buddy_peers.remove( peer )){
-				
-				if ( buddy_peers.size() == 0 ){
-					
-					state_changed = true;
-					
-					if ( buddy_stats_timer != null ){
-						
-						buddy_stats_timer.cancel();
-						
-						buddy_stats_timer = null;
-					}
-				}
-				
-				log( download.getName() + ": removing buddy peer " + peer.getIp());
-			}
-			
-			peer.setUserData( PEER_KEY, null );
-			
-			peer.setPriorityConnection( false );
-		}	
-		
-		if ( state_changed ){
-			
-			updateNetworkStatus();
-		}
-	}
-	
-	protected void
-	checkPeers()
-	{
-		List	to_unmark = new ArrayList();
-		
-		synchronized( buddy_peers ){
-
-			Iterator	it = buddy_peers.iterator();
-			
-			while( it.hasNext()){
-				
-				Peer	peer = (Peer)it.next();
-				
-				if ( peer.getState() == Peer.CLOSING || peer.getState() == Peer.DISCONNECTED ){
-					
-					to_unmark.add( peer );
-				}
-			}
-		}
-		
-		for (int i=0;i<to_unmark.size();i++){
-			
-			unmarkBuddyPeer((Peer)to_unmark.get(i));
-		}
-	}
-	
-	protected void
-	recheckPeers()
-	{
-			// go over peers for active torrents to see if we've missed and. can really only
-			// happen with multi-homed LAN setups where a new (and utilised) route is found
-			// after we start tracking 
-		
-		synchronized( actively_tracking ){
-			
-			Iterator it = actively_tracking.iterator();
-			
-			while( it.hasNext()){
-				
-				Download download = (Download)it.next();
-				
-				PeerManager pm = download.getPeerManager();
-				
-				if ( pm != null ){
-					
-					Peer[] peers = pm.getPeers();
-					
-					for (int i=0;i<peers.length;i++){
-						
-						trackPeer( download, peers[i] );
-					}
-				}
-			}
-		}
-	}
-	
-	protected void
-	updateNetworkStatus()
-	{	
-		int		new_status;
-		boolean	changed = false;
-		
-		synchronized( buddy_peers ){
-	
-			if ( buddy_peers.size() == 0 ){
-				
-				new_status 	= BUDDY_NETWORK_IDLE;
-				
-			}else{
-				
-				new_status	= seeding_only?BUDDY_NETWORK_OUTBOUND:BUDDY_NETWORK_INBOUND;
-			}
-			
-			if ( new_status != network_status ){
-				
-				network_status	= new_status;
-				
-				changed	= true;
-			}
-		}
-		
-		if ( changed ){
-		
-			fireStateChange( new_status );
-		}
-	}
-	
-	public void
-	addListener(
-		BuddyPluginTrackerListener		l )
-	{
-		listeners.add( l );
-	}
-	
-	public void
-	removeListener(
-		BuddyPluginTrackerListener		l )
-	{
-		listeners.remove( l );
-	}
-	
-	protected void
-	fireStateChange(
-		int		state )
-	{
-		Iterator	it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((BuddyPluginTrackerListener)it.next()).networkStatusChanged( this, state );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}
-	}
-	
-	protected void
-	fireEnabledChanged(
-		boolean	enabled )
-	{
-		Iterator	it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((BuddyPluginTrackerListener)it.next()).enabledStateChanged( this, enabled );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}
-	}
-	
-	protected void
-	sendMessage(
-		BuddyPluginBuddy	buddy,
-		int					type,
-		Map					body )
-	{
-		Map	msg = new HashMap();
-		
-		msg.put( "type", new Long( type ));
-		msg.put( "msg", body );
-		
-		plugin.getAZ2Handler().sendAZ2TrackerMessage(
-				buddy, 
-				msg, 
-				BuddyPluginTracker.this );
-	}
-	
-	public Map
-	messageReceived(
-		BuddyPluginBuddy	buddy,
-		Map					message )
-	{
-		buddyData buddy_data = buddyAlive( buddy );
-		
-		int type = ((Long)message.get( "type" )).intValue();
-		
-		Map msg = (Map)message.get( "msg" );
-		
-		return( buddy_data.receiveMessage( type, msg ));
-	}
-	
-	public void
-	messageFailed(
-		BuddyPluginBuddy	buddy,
-		Throwable			cause )
-	{
-		log( "Failed to send message to " + buddy.getName(), cause );
-		
-		buddyDead( buddy );
-	}
-	
-	protected buddyData
-	buddyAlive(
-		BuddyPluginBuddy		buddy )
-	{
-		buddyData buddy_data = addBuddy( buddy );
-		
-		buddy_data.setAlive( true );
-		
-		return( buddy_data );
-	}
-	
-	protected void
-	buddyDead(
-		BuddyPluginBuddy		buddy )
-	{
-		buddyData buddy_data = getBuddyData( buddy );
-
-		if ( buddy_data != null ){
-			
-			buddy_data.setAlive( false );
-		}
-	}
-	
-	protected boolean
-	okToTrack(
-		Download	d )
-	{
-		Torrent	t = d.getTorrent();
-		
-		if ( t == null ){
-			
-			return( false );
-		}
-		
-			// only track private torrents if we have successfully received peers from tracker
-			// which means we have the torrent legitimately. As this rule is enforced by both
-			// ends of the tracking operation it means we will only track between peers that
-			// both have a legitimate copy of the torrent.
-				
-		if ( t.isPrivate()){
-			
-			DownloadAnnounceResult announce = d.getLastAnnounceResult();
-
-			if ( 	announce == null ||
-					announce.getResponseType() != DownloadAnnounceResult.RT_SUCCESS ||
-					announce.getPeers().length < 2 ){
-				
-				return( false );
-			}
-		}
-		
-		int state = d.getState();
-		
-		return( 	state != Download.ST_ERROR && 
-					state != Download.ST_STOPPING && 
-					state != Download.ST_STOPPED );
-	}
-	
-	protected void
-	log(
-		String		str )
-	{
-		plugin.log( "Tracker: " + str );
-	}
-	
-	protected void
-	log(
-		String		str,
-		boolean		verbose )
-	{
-		if ( verbose ){
-			
-			if ( Constants.isCVSVersion()){
-			
-				log( str );
-			}
-		}else{
-			
-			log( str );
-		}
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable 	e )
-	{
-		plugin.log( "Tracker: " + str, e );
-	}
-	
-	private class
-	buddyData
-	{
-		private BuddyPluginBuddy		buddy;
-		
-		private Set	downloads_sent;
-		private int	downloads_sent_id;
-		
-		private Map		downloads_in_common;
-		private boolean	buddy_seeding_only;
-		
-		private int		consecutive_fails;
-		private long	last_fail;
-		
-		private String	current_ip;
-		
-		protected
-		buddyData(
-			BuddyPluginBuddy		_buddy )
-		{
-			buddy	= _buddy;
-		}
-		
-		protected void
-		updateIP()
-		{
-			InetAddress	latest_ip = buddy.getAdjustedIP();
-			
-			if ( latest_ip != null ){
-			
-				current_ip	= latest_ip.getHostAddress();
-			
-				log( "IP set to " + current_ip );
-			}
-		}
-			
-		protected boolean
-		hasIPChanged()
-		{
-			InetAddress	latest_ip = buddy.getAdjustedIP();
-			
-			if ( latest_ip == null && current_ip == null ){
-				
-				return( false );
-				
-			}else if ( latest_ip == null || current_ip == null ){
-				
-				return( true );
-				
-			}else{
-			
-				return(	!current_ip.equals( latest_ip.getHostAddress()));
-			}
-		}
-		
-		protected String
-		getIP()
-		{
-			return( current_ip );
-		}
-		
-		protected boolean
-		hasDownloadsInCommon()
-		{
-			synchronized( this ){
-			
-				return( downloads_in_common != null );
-			}
-		}
-		
-		protected void
-		setAlive(
-			boolean		alive )
-		{
-			synchronized( this ){
-				
-				if ( alive ){
-					
-					consecutive_fails		= 0;
-					last_fail				= 0;
-
-				}else{
-					
-					consecutive_fails++;
-					
-					last_fail	= SystemTime.getMonotonousTime();
-				}
-			}
-		}
-		
-		protected void
-		updateLocal(
-			Set		downloads,
-			int		id,
-			Map		diff_map )
-		{
-			if ( consecutive_fails > 0 ){
-				
-				long	retry_millis = RETRY_SEND_MIN;
-				
-				for (int i=0;i<consecutive_fails-1;i++){
-					
-					retry_millis <<= 2;
-					
-					if ( retry_millis > RETRY_SEND_MAX ){
-						
-						retry_millis = RETRY_SEND_MAX;
-						
-						break;
-					}
-				}
-				
-				long	now = SystemTime.getMonotonousTime();
-				
-				if ( now - last_fail >= retry_millis ){
-					
-					last_fail			= now;	// assume we're going to fail so we avoid
-												// falling through here multiple times before
-												// actuallt failing again
-					
-					downloads_sent 		= null;
-					downloads_sent_id	= 0;
-				}
-			}
-			
-				// first check to see if completion state changed for any common downloads
-			
-			List	comp_changed = new ArrayList();
-			
-			synchronized( this ){
-				
-				if ( downloads_in_common != null ){
-					
-					Iterator it = downloads_in_common.entrySet().iterator();
-					
-					while( it.hasNext()){
-						
-						Map.Entry	entry = (Map.Entry)it.next();
-						
-						Download d = (Download)entry.getKey();
-
-						buddyDownloadData	bdd = (buddyDownloadData)entry.getValue();
-						
-						boolean	local_complete = d.isComplete( false );
-						
-						if ( local_complete != bdd.isLocalComplete()){
-							
-							bdd.setLocalComplete( local_complete );
-							
-							comp_changed.add( d );
-						}
-					}
-				}
-			}
-			
-			if ( comp_changed.size() > 0 ){
-				
-				byte[][] change_details = exportFullIDs( comp_changed );
-				
-				if( change_details[0].length > 0 ){
-					
-					Map	msg = new HashMap();
-										
-					msg.put( "seeding", new Long( seeding_only?1:0 ));
-					
-					msg.put( "change", 		change_details[0] );
-					msg.put( "change_s", 	change_details[1] );
-
-					sendMessage( buddy, REQUEST_TRACKER_CHANGE, msg );
-				}
-			}
-			
-			if ( id == downloads_sent_id ){
-				
-				return;
-			}
-			
-			Long	key = new Long(((long)id) << 32 | (long)downloads_sent_id);
-				
-			Object[]	diffs = (Object[])diff_map.get( key );
-			
-			boolean	incremental = downloads_sent != null;
-			
-			byte[]	added_bytes;
-			byte[]	removed_bytes;
-			
-			if ( diffs == null ){
-				
-				List	added;
-				List	removed	= new ArrayList();
-				
-
-				if ( downloads_sent == null ){
-					
-					added 	= new ArrayList( downloads );
-					
-				}else{
-					
-					added	= new ArrayList();
-
-					Iterator	it1 = downloads.iterator();
-					
-					while( it1.hasNext()){
-					
-						Download download = (Download)it1.next();
-						
-						if ( okToTrack( download )){
-							
-							if ( !downloads_sent.contains( download )){
-								
-								added.add( download );
-							}
-						}
-					}
-					
-					Iterator	it2 = downloads_sent.iterator();
-					
-					while( it2.hasNext()){
-					
-						Download download = (Download)it2.next();
-						
-						if ( !downloads.contains( download )){
-							
-							removed.add( download );
-						}
-					}
-				}
-				
-				added_bytes 	= exportShortIDs( added );
-				removed_bytes	= exportFullIDs( removed )[0];
-				
-				diff_map.put( key, new Object[]{ added_bytes, removed_bytes });
-			}else{
-				
-				added_bytes 	= (byte[])diffs[0];
-				removed_bytes 	= (byte[])diffs[1];
-			}
-				
-			downloads_sent 		= downloads;
-			downloads_sent_id	= id;
-			
-			if ( added_bytes.length == 0 && removed_bytes.length == 0 ){
-				
-				return;
-			}
-			
-			Map	msg = new HashMap();
-			
-			if ( added_bytes.length > 0 ){
-				
-				msg.put( "added", 	added_bytes );
-			}
-			
-			if ( removed_bytes.length > 0 ){
-				
-				msg.put( "removed", removed_bytes );
-			}
-			
-			msg.put( "inc", 	new Long( incremental?1:0 ));
-			msg.put( "seeding", new Long( seeding_only?1:0 ));
-			
-			sendMessage( buddy, REQUEST_TRACKER_SUMMARY, msg );
-		}	
-		
-		protected Map
-		updateRemote(
-			Map		msg )
-		{			
-			List	added 	= importShortIDs((byte[])msg.get( "added" ));
-			
-			Map	reply = new HashMap();
-			
-			byte[][] add_details = exportFullIDs( added );
-			
-			if( add_details[0].length > 0 ){
-			
-				reply.put( "added", 	add_details[0] );
-				reply.put( "added_s", 	add_details[1] );
-			}
-			
-			synchronized( this ){
-
-				if ( downloads_in_common != null ){
-
-					Map removed = importFullIDs( (byte[])msg.get( "removed" ), null );
-					
-					Iterator it = removed.keySet().iterator();
-					
-					while( it.hasNext()){
-						
-						Download d = (Download)it.next();
-						
-						if ( downloads_in_common.remove( d ) != null ){
-							
-							log( "Removed " + d.getName() + " common download", false, true );
-						}
-					}
-				
-					if ( downloads_in_common.size() == 0 ){
-						
-						downloads_in_common = null;
-					}
-				}
-			}
-			
-			return( reply );
-		}
-		
-		protected void
-		updateCommonDownloads(
-			Map			downloads,
-			boolean		incremental )
-		{
-			synchronized( this ){
-
-				if ( downloads_in_common == null ){
-					
-					downloads_in_common = new HashMap();
-					
-				}else{
-					
-						// if not incremental then remove any downloads that no longer
-						// are in common
-					
-					if ( !incremental ){
-						
-						Iterator it = downloads_in_common.keySet().iterator();
-						
-						while( it.hasNext()){
-							
-							Download download = (Download)it.next();
-							
-							if ( !downloads.containsKey( download )){
-								
-								log( "Removing " + download.getName() + " from common downloads", false, true );
-
-								it.remove();
-							}
-						}
-					}
-				}
-				
-				Iterator it = downloads.entrySet().iterator();
-				
-				while( it.hasNext()){
-					
-					Map.Entry	entry = (Map.Entry)it.next();
-			
-					Download d = (Download)entry.getKey();
-
-					buddyDownloadData	bdd = (buddyDownloadData)entry.getValue();
-					
-					buddyDownloadData existing = (buddyDownloadData)downloads_in_common.get( d );
-					
-					if ( existing == null ){
-						
-						log( "Adding " + d.getName() + " to common downloads (bdd=" + bdd.getString() + ")", false, true );
-						
-						downloads_in_common.put( d, bdd );
-						
-					}else{
-						
-						boolean	old_rc = existing.isRemoteComplete();
-						boolean	new_rc = bdd.isRemoteComplete();
-						
-						if ( old_rc != new_rc ){
-						
-							existing.setRemoteComplete( new_rc ); 
-							
-							log( "Changing " + d.getName() + " common downloads (bdd=" + existing.getString() + ")", false, true );
-						}				
-					}
-				}
-				
-				if ( downloads_in_common.size() == 0 ){
-					
-					downloads_in_common = null;
-				}
-			}
-		}
-		
-		protected void
-		updateStatus()
-		{
-			Map	msg = new HashMap();
-			
-			msg.put( "seeding", new Long( seeding_only?1:0 ));
-			
-			sendMessage( buddy, REQUEST_TRACKER_STATUS, msg );
-		}
-		
-		protected Map
-		receiveMessage(
-			int			type,
-			Map			msg_in )
-		{
-			int	reply_type	= -1;
-			Map	msg_out		= null;
-
-			Long	l_seeding = (Long)msg_in.get( "seeding" );
-			
-			if( l_seeding != null ){
-				
-				boolean old = buddy_seeding_only;
-				
-				buddy_seeding_only = l_seeding.intValue() == 1;
-				
-				if ( old != buddy_seeding_only ){
-					
-					log( "Seeding only changed to " + buddy_seeding_only );
-				}
-			}
-			
-			if ( type == REQUEST_TRACKER_SUMMARY ){
-		
-				reply_type	= REPLY_TRACKER_SUMMARY;
-				
-				msg_out = updateRemote( msg_in );
-				
-				msg_out.put( "inc", msg_in.get( "inc" ));
-								
-			}else if ( type == REQUEST_TRACKER_STATUS ){
-				
-				reply_type	= REPLY_TRACKER_STATUS;
-				
-			}else if ( type == REQUEST_TRACKER_CHANGE ){
-
-				reply_type	= REPLY_TRACKER_STATUS;
-									
-				Map downloads = importFullIDs( (byte[])msg_in.get( "changed" ), (byte[])msg_in.get( "changed_s" ) );
-
-				updateCommonDownloads( downloads, true );
-								
-			}else if ( type == REQUEST_TRACKER_ADD ){
-
-				reply_type	= REPLY_TRACKER_ADD;
-										
-				Map downloads = importFullIDs( (byte[])msg_in.get( "added" ), (byte[])msg_in.get( "added_s" ) );
-
-				updateCommonDownloads( downloads, true );
-
-			}else if ( type == REPLY_TRACKER_SUMMARY ){
-				
-					// full hashes on reply
-				
-				byte[]	possible_matches 		= (byte[])msg_in.get( "added" );
-				byte[]	possible_match_states 	= (byte[])msg_in.get( "added_s" );
-
-				boolean	incremental = ((Long)msg_in.get( "inc" )).intValue() == 1;
-				
-				if ( possible_matches != null && possible_match_states != null ){
-							
-					Map downloads = importFullIDs( possible_matches, possible_match_states );
-						
-					if ( downloads.size() > 0 ){
-												
-						updateCommonDownloads( downloads, incremental );
-						
-						byte[][] common_details = exportFullIDs( new ArrayList( downloads.keySet()));
-						
-						if( common_details[0].length > 0 ){
-							
-							Map	msg = new HashMap();
-												
-							msg.put( "seeding", new Long( seeding_only?1:0 ));
-							
-							msg.put( "added", 	common_details[0] );
-							msg.put( "added_s", common_details[1] );
-
-							sendMessage( buddy, REQUEST_TRACKER_ADD, msg );
-						}
-					}
-				}
-								
-			}else if ( 	type == REPLY_TRACKER_CHANGE ||
-						type == REPLY_TRACKER_STATUS ||
-						type == REPLY_TRACKER_ADD ){
-				
-					// nothing interesting in reply for these
-			}else{
-				
-				log( "Unrecognised type " + type );
-			}
-			
-			if ( reply_type != -1 ){
-				
-				Map	reply = new HashMap();
-			
-				reply.put( "type", new Long( reply_type ));
-		
-				if ( msg_out == null ){
-					
-					msg_out = new HashMap();
-				}
-				
-				msg_out.put( "seeding", new Long( seeding_only?1:0 ));
-			
-				reply.put( "msg", msg_out );
-
-				return( reply );
-			}
-			
-			return( null );
-		}
-		
-		protected byte[]
-		exportShortIDs(
-			List	downloads )
-		{
-			byte[]	res = new byte[ SHORT_ID_SIZE * downloads.size() ];
-			
-			for (int i=0;i<downloads.size();i++ ){
-				
-				Download download = (Download)downloads.get(i);
-				
-				downloadData download_data = (downloadData)download.getUserData( BuddyPluginTracker.class );
-				
-				if ( download_data != null ){
-
-					System.arraycopy(
-						download_data.getID().getBytes(),
-						0,
-						res,
-						i * SHORT_ID_SIZE,
-						SHORT_ID_SIZE );
-				}
-			}
-			
-			return( res );
-		}
-		
-		protected List
-		importShortIDs(
-			byte[]		ids )
-		{
-			List	res = new ArrayList();
-			
-			if ( ids != null ){
-				
-				synchronized( tracked_downloads ){
-
-					for (int i=0;i<ids.length;i+= SHORT_ID_SIZE ){
-					
-						List dls = (List)short_id_map.get( new HashWrapper( ids, i, SHORT_ID_SIZE ));
-						
-						if ( dls != null ){
-							
-							res.addAll( dls );
-						}
-					}
-				}
-			}
-			
-			return( res );
-		}
-		
-		protected byte[][]
-   		exportFullIDs(
-   			List	downloads )
-   		{
-   			byte[]	hashes 	= new byte[ FULL_ID_SIZE * downloads.size() ];
-   			byte[] 	states	= new byte[ downloads.size()];
-   			
-   			for (int i=0;i<downloads.size();i++ ){
-   				
-   				Download download = (Download)downloads.get(i);
-   				
-   				downloadData download_data = (downloadData)download.getUserData( BuddyPluginTracker.class );
-   				
-   				if ( download_data != null ){
-
-   					System.arraycopy(
-   						download_data.getID().getBytes(),
-   						0,
-   						hashes,
-   						i * FULL_ID_SIZE,
-   						FULL_ID_SIZE );
-   					
-   					states[i] = download.isComplete( false )?(byte)0x01:(byte)0x00;
-   				}
-   			}
-   			
-   			return( new byte[][]{ hashes, states });
-   		}
-		
-		protected Map
-		importFullIDs(
-			byte[]		ids,
-			byte[]		states )
-		{
-			Map	res = new HashMap();
-			
-			if ( ids != null ){
-				
-				synchronized( tracked_downloads ){
-
-					for (int i=0;i<ids.length;i+= FULL_ID_SIZE ){
-					
-						Download dl = (Download)full_id_map.get( new HashWrapper( ids, i, FULL_ID_SIZE ));
-						
-						if ( dl != null ){
-							
-							buddyDownloadData bdd = new buddyDownloadData( dl );
-							
-							if ( states != null ){
-							
-								bdd.setRemoteComplete(( states[i/FULL_ID_SIZE] & 0x01 ) != 0 );
-							}
-							
-							res.put( dl, bdd );
-						}
-					}
-				}
-			}
-			
-			return( res );
-		}
-		
-		protected Map
-		getDownloadsToTrack()
-		{
-			Map	res = new HashMap();
-
-			if ( seeding_only == buddy_seeding_only ){
-				
-				log( "Not tracking, buddy and me both " + (seeding_only?"seeding":"downloading"), true, false );
-
-				return( res );
-			}			
-		
-			long	now = SystemTime.getMonotonousTime();
-			
-			synchronized( this ){
-
-				if ( downloads_in_common == null ){
-					
-					log( "Not tracking, buddy has nothing in common", true, false );
-
-					return( res );
-				}
-				
-				Iterator it = downloads_in_common.entrySet().iterator();
-				
-				while( it.hasNext()){
-					
-					Map.Entry	entry = (Map.Entry)it.next();
-			
-					Download d = (Download)entry.getKey();
-
-					buddyDownloadData	bdd = (buddyDownloadData)entry.getValue();
-					
-					if ( d.isComplete( false ) && bdd.isRemoteComplete()){
-						
-							// both complete, nothing to do!
-						
-						log( d.getName() + " - not tracking, both complete", true, true );
-						
-					}else{
-						
-						long	last_track = bdd.getTrackTime();
-						
-						if ( 	last_track == 0 || 
-								now - last_track >= TRACK_INTERVAL ){
-							
-							log( d.getName() + " - tracking", false, true );
-
-							bdd.setTrackTime( now );
-							
-							res.put( d, new Boolean( true ));
-							
-						}else{
-							
-							res.put( d, new Boolean( false ));
-						}
-					}
-				}
-			}
-			
-			return( res );
-		}
-		
-		protected void
-		resetTracking(
-			Download		download )
-		{
-			synchronized( this ){
-				
-				if ( downloads_in_common == null ){
-					
-					return;
-				}
-				
-				buddyDownloadData bdd = (buddyDownloadData)downloads_in_common.get( download );
-				
-				if ( bdd != null ){
-					
-					bdd.resetTrackTime();
-				}
-			}
-		}
-		
-		protected void
-		log(
-			String	str )
-		{
-			BuddyPluginTracker.this.log( buddy.getName() + ": " + str );
-		}
-		
-		protected void
-		log(
-			String	str,
-			boolean	verbose,
-			boolean	no_buddy )
-		{
-			BuddyPluginTracker.this.log( (no_buddy?"":( buddy.getName() + ": ")) + str, verbose );
-		}
-	}
-	
-	private static class
-	buddyDownloadData
-	{
-		private boolean	local_is_complete;
-		private boolean	remote_is_complete;
-		private long	last_track;
-		
-		protected
-		buddyDownloadData(
-			Download		download )
-		{
-			local_is_complete = download.isComplete( false );
-		}
-		
-		protected void
-		setLocalComplete(
-			boolean		b )
-		{
-			local_is_complete	= b;
-		}
-	
-		protected boolean
-		isLocalComplete()
-		{
-			return( local_is_complete );
-		}
-		
-		protected void
-		setRemoteComplete(
-			boolean		b )
-		{
-			remote_is_complete	= b;
-		}
-	
-		protected boolean
-		isRemoteComplete()
-		{
-			return( remote_is_complete );
-		}
-		
-		protected void
-		setTrackTime(
-			long	time )
-		{
-			last_track	= time;
-		}
-		
-		protected long
-		getTrackTime()
-		{
-			return( last_track );
-		}
-		
-		protected void
-		resetTrackTime()
-		{
-			last_track	= 0;
-		}
-		
-		protected String
-		getString()
-		{
-			return( "lic=" + local_is_complete + ",ric=" + remote_is_complete + ",lt=" + last_track );
-		}
-	}
-	
-	private static class
-	downloadData
-	{
-		private static final byte[]	IV = {(byte)0x7A, (byte)0x7A, (byte)0xAD, (byte)0xAB, (byte)0x8E, (byte)0xBF, (byte)0xCD, (byte)0x39, (byte)0x87, (byte)0x0, (byte)0xA4, (byte)0xB8, (byte)0xFE, (byte)0x40, (byte)0xA2, (byte)0xE8 }; 
-			
-		private HashWrapper	id;
-		
-		protected
-		downloadData(
-			Download	download )
-		{
-			Torrent t = download.getTorrent();
-			
-			if ( t != null ){
-				
-				byte[]	hash = t.getHash();
-				
-				SHA1	sha1 = new SHA1();
-			
-				sha1.update( ByteBuffer.wrap( IV ));
-				sha1.update( ByteBuffer.wrap( hash ));
-				
-				id = new HashWrapper( sha1.digest() );
-			}
-		}
-		
-		protected HashWrapper
-		getID()
-		{
-			return( id );
-		}
-	}
-}
+/*
+ * Created on May 27, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy.tracker;
+
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.util.*;
+
+import org.gudy.azureus2.core3.global.GlobalManager;
+import org.gudy.azureus2.core3.global.GlobalManagerAdapter;
+import org.gudy.azureus2.core3.peer.PEPeerManager;
+import org.gudy.azureus2.core3.util.AddressUtils;
+import org.gudy.azureus2.core3.util.Average;
+import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.HashWrapper;
+import org.gudy.azureus2.core3.util.LightHashMap;
+import org.gudy.azureus2.core3.util.SHA1;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+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.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadAnnounceResult;
+import org.gudy.azureus2.plugins.download.DownloadListener;
+import org.gudy.azureus2.plugins.download.DownloadManagerListener;
+import org.gudy.azureus2.plugins.download.DownloadPeerListener;
+import org.gudy.azureus2.plugins.download.DownloadScrapeResult;
+import org.gudy.azureus2.plugins.download.DownloadTrackerListener;
+import org.gudy.azureus2.plugins.peers.Peer;
+import org.gudy.azureus2.plugins.peers.PeerEvent;
+import org.gudy.azureus2.plugins.peers.PeerListener2;
+import org.gudy.azureus2.plugins.peers.PeerManager;
+import org.gudy.azureus2.plugins.peers.PeerManagerListener;
+import org.gudy.azureus2.plugins.peers.PeerStats;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.ui.config.BooleanParameter;
+import org.gudy.azureus2.plugins.ui.config.Parameter;
+import org.gudy.azureus2.plugins.ui.config.ParameterListener;
+import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.core.util.CopyOnWriteSet;
+import com.aelitis.azureus.plugins.net.buddy.*;
+
+public class 
+BuddyPluginTracker 
+	implements BuddyPluginListener, DownloadManagerListener, BuddyPluginAZ2TrackerListener, DownloadPeerListener
+{
+	private  static final Object	PEER_KEY		= new Object();		// maps to Download object
+	
+	private static final Object	PEER_STATS_KEY	= new Object();
+	
+	public static final int BUDDY_NETWORK_IDLE		= 1;
+	public static final int BUDDY_NETWORK_OUTBOUND	= 2;
+	public static final int BUDDY_NETWORK_INBOUND	= 3;
+	
+	private static final int	TRACK_CHECK_PERIOD		= 15*1000;
+	private static final int	TRACK_CHECK_TICKS		= TRACK_CHECK_PERIOD/BuddyPlugin.TIMER_PERIOD;
+
+	private static final int	PEER_CHECK_PERIOD		= 60*1000;
+	private static final int	PEER_CHECK_TICKS		= PEER_CHECK_PERIOD/BuddyPlugin.TIMER_PERIOD;
+	
+	private static final int	PEER_RECHECK_PERIOD		= 120*1000;
+	private static final int	PEER_RECHECK_TICKS		= PEER_RECHECK_PERIOD/BuddyPlugin.TIMER_PERIOD;
+
+	private static final int	TRACK_INTERVAL			= 10*60*1000;
+	
+	private static final int	SHORT_ID_SIZE			= 4;
+	private static final int	FULL_ID_SIZE			= 20;
+	
+	private static final int	REQUEST_TRACKER_SUMMARY	= 1;
+	private static final int	REPLY_TRACKER_SUMMARY	= 2;
+	private static final int	REQUEST_TRACKER_STATUS	= 3;
+	private static final int	REPLY_TRACKER_STATUS	= 4;
+	private static final int	REQUEST_TRACKER_CHANGE	= 5;
+	private static final int	REPLY_TRACKER_CHANGE	= 6;
+	private static final int	REQUEST_TRACKER_ADD		= 7;
+	private static final int	REPLY_TRACKER_ADD		= 8;
+	
+	private static final int	RETRY_SEND_MIN			= 5*60*1000;
+	private static final int	RETRY_SEND_MAX			= 60*60*1000;
+	
+	private static final int	BUDDY_NO		= 0;
+	private static final int	BUDDY_MAYBE		= 1;
+	private static final int	BUDDY_YES		= 2;
+	
+	private BuddyPlugin		plugin;
+	
+	private boolean			plugin_enabled;
+	private boolean			tracker_enabled;
+	private boolean			seeding_only;
+	
+	private boolean			old_plugin_enabled;
+	private boolean			old_tracker_enabled;
+	private boolean			old_seeding_only;
+	
+	private int				network_status = BUDDY_NETWORK_IDLE;
+	
+	private Set				online_buddies 			= new HashSet();
+	private Map				online_buddy_ips		= new HashMap();
+	
+	private Set				tracked_downloads		= new HashSet();
+	private int				download_set_id;
+	
+	private Set				last_processed_download_set;
+	private int				last_processed_download_set_id;
+	
+	private Map				short_id_map	= new HashMap();
+	private Map				full_id_map		= new HashMap();
+	
+	private Set				actively_tracking	= new HashSet();
+		
+	private CopyOnWriteSet<Peer>	buddy_peers	= new CopyOnWriteSet<Peer>( true );
+	
+	private CopyOnWriteList	listeners = new CopyOnWriteList();
+	
+	private TimerEventPeriodic	buddy_stats_timer;
+	
+	private Average buddy_receive_speed = Average.getInstance(1000, 10);
+	
+	private Average buddy_send_speed 	= Average.getInstance(1000, 10);
+	
+	public
+	BuddyPluginTracker(
+		BuddyPlugin					_plugin,
+		final BooleanParameter 		tracker_enable	)
+	{
+		plugin		= _plugin;	
+		
+		tracker_enabled = tracker_enable.getValue();
+		
+		tracker_enable.addListener(
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					Parameter param )
+				{
+					tracker_enabled = tracker_enable.getValue();
+					
+					checkEnabledState();
+				}
+			});
+		
+		// Assumed if we already have a plugin reference, that the
+		// Azureus Core is available
+		GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
+		
+		gm.addListener(
+			new GlobalManagerAdapter()
+			{
+				public void 
+				seedingStatusChanged( 
+					boolean seeding_only_mode,
+					boolean potentially_seeding_only )
+				{
+					seeding_only = potentially_seeding_only;
+					
+					checkEnabledState();
+				}
+			}, false );
+		
+		seeding_only = gm.isPotentiallySeedingOnly();
+		
+		checkEnabledState();
+	}
+	
+	public void
+	initialise()
+	{
+		plugin_enabled = plugin.isClassicEnabled();
+		
+		checkEnabledState();
+		
+		List buddies = plugin.getBuddies();
+		
+		for (int i=0;i<buddies.size();i++){
+			
+			buddyAdded((BuddyPluginBuddy)buddies.get(i));
+		}
+		
+		plugin.addListener( this );
+		
+		plugin.getAZ2Handler().addTrackerListener( this );
+
+		plugin.getPluginInterface().getDownloadManager().addListener( this, true );
+	}
+	
+	public void
+	tick(
+		int		tick_count )
+	{
+		if ( tick_count % TRACK_CHECK_TICKS == 0 ){
+			
+			checkTracking();
+		}
+		
+		if ( ( tick_count-1 ) % TRACK_CHECK_TICKS == 0 ){
+			
+			doTracking();
+		}
+		
+		if ( tick_count % PEER_CHECK_TICKS == 0 ){
+			
+			checkPeers();
+		}
+		
+		if ( tick_count % PEER_RECHECK_TICKS == 0 ){
+			
+			recheckPeers();
+		}
+	}
+	
+	public int
+	getNetworkStatus()
+	{
+		return( network_status );
+	}
+	
+	public long
+	getNetworkReceiveBytesPerSecond()
+	{
+		return( buddy_receive_speed.getAverage());
+	}
+	
+	public long
+	getNetworkSendBytesPerSecond()
+	{
+		return( buddy_send_speed.getAverage());
+	}
+	
+	protected void
+	doTracking()
+	{
+		if ( !( plugin_enabled && tracker_enabled )){
+			
+			return;
+		}
+
+		Map	to_do = new HashMap();
+		
+		Set active_set = new HashSet();
+		
+		synchronized( online_buddies ){
+
+			Iterator it = online_buddies.iterator();
+				
+			while( it.hasNext()){
+				
+				BuddyPluginBuddy	buddy = (BuddyPluginBuddy)it.next();
+				
+				buddyData buddy_data = getBuddyData( buddy );
+				
+				Map active = buddy_data.getDownloadsToTrack();
+				
+				if ( active.size() > 0 ){
+					
+					Iterator it2 = active.entrySet().iterator();
+					
+					List track_now = new ArrayList();
+					
+					while( it2.hasNext()){
+						
+						Map.Entry entry = (Map.Entry)it2.next();
+						
+						Download 	dl 	= (Download)entry.getKey();
+						boolean		now = ((Boolean)entry.getValue()).booleanValue();
+						
+						if ( now ){
+							
+							track_now.add( dl );
+						}
+						
+						active_set.add( dl );
+					}
+					
+					if( track_now.size() > 0 ){
+					
+						to_do.put( buddy, track_now );
+					}
+				}
+			}
+		}
+		
+		synchronized( actively_tracking ){
+			
+			Iterator it = active_set.iterator();
+			
+			while( it.hasNext()){
+				
+				Download dl = (Download)it.next();
+				
+				if ( !actively_tracking.contains( dl )){
+					
+					actively_tracking.add( dl );
+					
+					trackPeers( dl );
+				}
+			}
+			
+			it = actively_tracking.iterator();
+			
+			while( it.hasNext()){
+				
+				Download dl = (Download)it.next();
+				
+				if ( !active_set.contains( dl )){
+					
+					it.remove();
+					
+					untrackPeers( dl );
+				}
+			}
+		}
+		
+		Iterator it = to_do.entrySet().iterator();
+		
+		while( it.hasNext()){
+			
+			Map.Entry	entry = (Map.Entry)it.next();
+					
+			BuddyPluginBuddy buddy = (BuddyPluginBuddy)entry.getKey();
+			
+			if ( !buddy.isOnline( false )){
+				
+				continue;
+			}
+			
+			InetAddress ip 			= buddy.getAdjustedIP();
+			
+			if ( ip == null ){
+				
+				continue;
+			}
+			
+			int			tcp_port	= buddy.getTCPPort();
+			int			udp_port	= buddy.getUDPPort();
+			
+			List	downloads = (List)entry.getValue();
+			
+			for (int i=0;i<downloads.size();i++){
+				
+				Download	download = (Download)downloads.get(i);
+				
+				PeerManager pm = download.getPeerManager();
+				
+				if ( pm == null ){
+					
+					continue;
+				}
+				
+				Peer[] existing_peers = pm.getPeers( ip.getHostAddress());
+			
+				boolean	connected = false;
+				
+				for (int j=0;j<existing_peers.length;j++){
+					
+					Peer peer = existing_peers[j];
+					
+					if ( 	peer.getTCPListenPort() == tcp_port ||
+							peer.getUDPListenPort() == udp_port ){
+						
+						connected = true;
+						
+						break;
+					}	
+				}
+				
+				if ( connected ){
+					
+					log( download.getName() + " - peer " + ip.getHostAddress() + " already connected" );
+					
+					continue;
+				}
+				
+				log( download.getName() + " - connecting to peer " + ip.getHostAddress());
+
+				PEPeerManager c_pm = PluginCoreUtils.unwrap( pm ); 
+				
+				Map	user_data = new LightHashMap();
+				
+				user_data.put( PEER_KEY, download );
+				
+				user_data.put( Peer.PR_PRIORITY_CONNECTION, new Boolean( true ));
+				
+				c_pm.addPeer( ip.getHostAddress(), tcp_port, udp_port, true, user_data );
+			}
+		}
+	}
+	
+	protected void
+	checkTracking()
+	{
+		if ( !( plugin_enabled && tracker_enabled )){
+			
+			return;
+		}
+		
+		List	online;
+		
+		synchronized( online_buddies ){
+
+			online = new ArrayList( online_buddies );
+		}
+		
+		Set			downloads;
+		int			downloads_id;
+		
+		synchronized( tracked_downloads ){
+			
+			boolean downloads_changed = last_processed_download_set_id != download_set_id;
+			
+			if ( downloads_changed ){
+				
+				last_processed_download_set 	= new HashSet( tracked_downloads );
+				last_processed_download_set_id	= download_set_id;
+			}
+			
+			downloads 		= last_processed_download_set;
+			downloads_id	= last_processed_download_set_id;
+		}
+		
+		Map	diff_map = new HashMap();
+		
+		for (int i=0;i<online.size();i++){
+			
+			BuddyPluginBuddy	buddy = (BuddyPluginBuddy)online.get(i);
+			
+			buddyData buddy_data = getBuddyData( buddy );
+			
+			buddy_data.updateLocal( downloads, downloads_id, diff_map );
+		}
+	}		
+	
+	public void
+	initialised(
+		boolean		available )
+	{	
+	}
+	
+	public void
+	buddyAdded(
+		BuddyPluginBuddy	buddy )
+	{
+		buddyChanged( buddy );
+	}
+	
+	public void
+	buddyRemoved(
+		BuddyPluginBuddy	buddy )
+	{
+		buddyChanged( buddy );
+	}
+
+	public void
+	buddyChanged(
+		BuddyPluginBuddy	buddy )
+	{	
+		if ( buddy.isOnline( false )){
+			
+			addBuddy( buddy );
+			
+		}else{
+			
+			removeBuddy( buddy );
+		}
+	}
+	
+	protected buddyData
+	getBuddyData(
+		BuddyPluginBuddy		buddy )
+	{
+		synchronized( online_buddies ){
+			
+			buddyData buddy_data = (buddyData)buddy.getUserData( BuddyPluginTracker.class );
+
+			if ( buddy_data == null ){
+				
+				buddy_data = new buddyData( buddy );
+				
+				buddy.setUserData( BuddyPluginTracker.class, buddy_data );
+			}
+			
+			return( buddy_data );
+		}
+	}
+	
+	protected buddyData
+	addBuddy(
+		BuddyPluginBuddy		buddy )
+	{
+		synchronized( online_buddies ){
+			
+			if ( !online_buddies.contains( buddy )){
+				
+				online_buddies.add( buddy );
+			}
+			
+			buddyData bd = getBuddyData( buddy );
+			
+			if ( bd.hasIPChanged()){
+				
+				String	ip = bd.getIP();
+				
+				if ( ip != null ){
+					
+					List	l = (List)online_buddy_ips.get( ip );
+					
+					if ( l != null ){
+						
+						l.remove( buddy );
+						
+						if ( l.size() == 0 ){
+							
+							online_buddy_ips.remove( ip );
+						}
+					}
+				}
+				
+				bd.updateIP();
+				
+				ip = bd.getIP();
+				
+				if ( ip != null ){
+					
+					List l = (List)online_buddy_ips.get( ip );
+					
+					if ( l == null ){
+						
+						l = new ArrayList();
+						
+						online_buddy_ips.put( ip, l );
+					}
+				
+					l.add( buddy );
+				}
+			}
+			
+			return( bd );
+		}
+	}
+		
+	protected void
+	removeBuddy(
+		BuddyPluginBuddy		buddy )
+	{		
+		synchronized( online_buddies ){
+
+			if ( online_buddies.contains( buddy )){
+				
+				buddyData bd = getBuddyData( buddy );
+
+				online_buddies.remove( buddy );
+				
+				String	ip = bd.getIP();
+				
+				if ( ip != null ){
+					
+					List	l = (List)online_buddy_ips.get( ip );
+					
+					if ( l != null ){
+						
+						l.remove( buddy );
+						
+						if ( l.size() == 0 ){
+							
+							online_buddy_ips.remove( ip );
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	protected int
+	isBuddy(
+		Peer		peer )
+	{
+		String	peer_ip = peer.getIp();
+		
+		List ips = AddressUtils.getLANAddresses( peer_ip );
+
+		synchronized( online_buddies ){
+			
+			int	result = BUDDY_NO;
+		
+			String	tested = "";
+outer:	
+			for (int i=0;i<ips.size();i++){
+
+				String ip = (String)ips.get(i);
+				
+				tested += ip;
+				
+				List buddies =(List)online_buddy_ips.get( ip  );
+			
+				if ( buddies != null ){
+									
+					if ( peer.getTCPListenPort() == 0 && peer.getUDPListenPort() == 0 ){
+						
+						result = BUDDY_MAYBE;
+						
+					}else{
+					
+						for (int j=0;j<buddies.size();j++){
+								
+							BuddyPluginBuddy	buddy = (BuddyPluginBuddy)buddies.get(j);
+								
+							if (	buddy.getTCPPort() == peer.getTCPListenPort() &&
+									buddy.getTCPPort() != 0 ){
+								
+								result =  BUDDY_YES;
+								
+								break outer;
+							}
+									
+							if (	buddy.getUDPPort() == peer.getUDPListenPort() &&
+									buddy.getUDPPort() != 0 ){
+								
+								result =  BUDDY_YES;
+								
+								break outer;
+							}
+						}
+					}
+				}
+			}
+			
+			// log( "isBuddy: " + peer_ip + " -> " + result + ",tested=" + tested );
+			
+			return( result );
+		}
+	}
+	
+	public void
+	messageLogged(
+		String		str,
+		boolean		error )
+	{	
+	}
+	
+	public void
+	enabledStateChanged(
+		boolean 	_enabled )
+	{
+		plugin_enabled = _enabled;
+		
+		checkEnabledState();
+	}
+	
+	public void 
+	updated() 
+	{
+	}
+	
+	public boolean
+	isEnabled()
+	{
+		synchronized( this ){
+			
+			return( plugin_enabled && tracker_enabled );
+		}
+	}
+	
+	protected void
+	checkEnabledState()
+	{
+		boolean	seeding_change 	= false;
+		boolean	enabled_change	= false;
+		
+		synchronized( this ){
+			
+			boolean	old_enabled = old_plugin_enabled && old_tracker_enabled;
+			
+			if ( plugin_enabled != old_plugin_enabled ){
+				
+				log( "Plugin enabled state changed to " + plugin_enabled );
+				
+				old_plugin_enabled = plugin_enabled;
+			}
+			
+			if ( tracker_enabled != old_tracker_enabled ){
+				
+				log( "Tracker enabled state changed to " + tracker_enabled );
+				
+				old_tracker_enabled = tracker_enabled;
+			}
+			
+			if ( seeding_only != old_seeding_only ){
+				
+				log( "Seeding-only state changed to " + seeding_only );
+				
+				old_seeding_only = seeding_only;
+				
+				seeding_change = true;
+			}
+			
+			enabled_change = old_enabled != ( plugin_enabled && tracker_enabled );
+		}
+		
+		if ( seeding_change ){
+			
+			updateSeedingMode();
+		}
+		
+		if ( enabled_change ){
+			
+			fireEnabledChanged( isEnabled());
+		}
+	}
+	
+	protected void
+	updateSeedingMode()
+	{
+		updateNetworkStatus();
+		
+		List	online;
+		
+		synchronized( online_buddies ){
+
+			online = new ArrayList( online_buddies );
+		}
+		
+		for (int i=0;i<online.size();i++){
+			
+			buddyData buddy_data = getBuddyData((BuddyPluginBuddy)online.get(i));
+			
+			if ( buddy_data.hasDownloadsInCommon()){
+				
+				buddy_data.updateStatus();
+			}
+		}
+	}
+	
+	public void
+	downloadAdded(
+		final Download	download )
+	{
+		Torrent t = download.getTorrent();
+		
+		if ( t == null ){
+			
+			return;
+		}
+		
+		if ( t.isPrivate()){
+			
+			download.addTrackerListener(
+				new DownloadTrackerListener()
+				{
+					public void 
+					scrapeResult(
+						DownloadScrapeResult result )
+					{					
+					}
+	
+					public void 
+					announceResult(
+						DownloadAnnounceResult result)
+					{
+						if ( okToTrack( download )){
+							
+							trackDownload( download );
+							
+						}else{
+							
+							untrackDownload( download );
+						}						
+					}
+				}, 
+				false );
+		}
+		
+		if ( okToTrack( download )){
+			
+			trackDownload( download );
+		}
+		
+		download.addListener(
+			new DownloadListener()
+			{
+				public void
+				stateChanged(
+					Download		download,
+					int				old_state,
+					int				new_state )
+				{
+					if ( okToTrack( download )){
+						
+						trackDownload( download );
+						
+					}else{
+						
+						untrackDownload( download );
+					}
+				}
+
+				public void
+				positionChanged(
+					Download	download, 
+					int 		oldPosition,
+					int 		newPosition )
+				{
+				}
+			});
+	}
+	
+	public void
+	downloadRemoved(
+		Download	download )
+	{
+		untrackDownload( download );
+	}
+	
+	protected void
+	trackDownload(
+		Download	download )
+	{
+		synchronized( tracked_downloads ){
+			
+			if ( tracked_downloads.contains( download )){
+				
+				return;
+			}
+							
+			downloadData download_data = new downloadData( download );
+				
+			download.setUserData( BuddyPluginTracker.class, download_data );
+			
+			HashWrapper	full_id		= download_data.getID();
+			
+			HashWrapper short_id 	= new HashWrapper( full_id.getHash(), 0, 4 );
+			
+			full_id_map.put( full_id, download );
+			
+			List	dls = (List)short_id_map.get( short_id );
+			
+			if ( dls == null ){
+				
+				dls = new ArrayList();
+				
+				short_id_map.put( short_id, dls );
+			}
+			
+			dls.add( download );
+			
+			tracked_downloads.add( download );
+			
+			download_set_id++;
+		}
+	}
+	
+	protected void
+	untrackDownload(
+		Download	download )
+	{
+		synchronized( tracked_downloads ){
+			
+			if ( tracked_downloads.remove( download )){
+				
+				download_set_id++;
+				
+				downloadData download_data = (downloadData)download.getUserData( BuddyPluginTracker.class );
+								
+				download.setUserData( BuddyPluginTracker.class, null );
+				
+				HashWrapper	full_id		= download_data.getID();
+				
+				full_id_map.remove( full_id );
+				
+				HashWrapper short_id 	= new HashWrapper( full_id.getHash(), 0, SHORT_ID_SIZE );
+				
+				List	dls = (List)short_id_map.get( short_id );
+
+				if ( dls != null ){
+					
+					dls.remove( download );
+					
+					if ( dls.size() == 0 ){
+						
+						short_id_map.remove( short_id );
+					}
+				}
+			}
+		}
+		
+		synchronized( online_buddies ){
+
+			Iterator it = online_buddies.iterator();
+				
+			while( it.hasNext()){
+				
+				BuddyPluginBuddy	buddy = (BuddyPluginBuddy)it.next();
+				
+				buddyData buddy_data = getBuddyData( buddy );
+				
+				buddy_data.resetTracking( download );
+			}
+		}
+		
+		synchronized( actively_tracking ){
+
+			actively_tracking.remove( download );
+		}
+	}
+	
+	protected void
+	trackPeers(
+		final Download		download )
+	{
+		PeerManager pm = download.getPeerManager();
+		
+			// not running
+		
+		if ( pm == null ){
+
+			synchronized( actively_tracking ){
+
+				actively_tracking.remove( download );
+			}
+		}else{
+			
+			log( "Tracking peers for " + download.getName());
+						
+			download.addPeerListener( this );
+		}
+	}
+	
+	public void
+	peerManagerAdded(
+		Download		download,
+		PeerManager		peer_manager )
+	{
+		trackPeers( download, peer_manager );
+	}
+	
+	public void
+	peerManagerRemoved(
+		Download		download,
+		PeerManager		peer_manager )
+	{
+		synchronized( actively_tracking ){
+
+			actively_tracking.remove( download );
+		}
+		
+		download.removePeerListener( this );
+	}
+	
+	protected void
+	trackPeers(
+		final Download	download,
+		PeerManager		pm )
+	{
+		pm.addListener(
+			new PeerManagerListener()
+			{
+				public void
+				peerAdded(
+					PeerManager		manager,
+					Peer			peer )
+				{
+					synchronized( actively_tracking ){
+						
+						if ( !actively_tracking.contains( download )){
+							
+							manager.removeListener( this );
+							
+							return;
+						}
+					}
+				
+					trackPeer( download, peer );
+				}
+				
+				public void
+				peerRemoved(
+					PeerManager	manager,
+					Peer		peer )
+				{
+				}
+			});
+		
+		Peer[] peers = pm.getPeers();
+		
+		for (int i=0;i<peers.length;i++){
+			
+			trackPeer( download, peers[i] );
+		}
+	}
+	
+	protected void
+	trackPeer(
+		final Download	download,
+		final Peer		peer )
+	{
+		int type = isBuddy( peer );
+		
+		if ( type == BUDDY_YES ){
+			
+			markBuddyPeer( download, peer );
+			
+		}else if ( type == BUDDY_MAYBE ){
+			
+				// mark as peer early so that we get optimistic disconnect if needed
+			
+			markBuddyPeer( download, peer );
+			
+			PeerListener2 listener = 
+				new PeerListener2()
+				{
+					public void 
+					eventOccurred(
+						PeerEvent event )
+					{
+						if ( event.getType() == PeerEvent.ET_STATE_CHANGED ){
+							
+							if (((Integer)event.getData()).intValue() == Peer.TRANSFERING ){
+								
+								peer.removeListener( this );
+								
+									// withdraw buddy marker if it turns out our earlier optimism
+									// was misplaced
+								
+								if ( isBuddy( peer ) != BUDDY_YES ){
+									
+									unmarkBuddyPeer( peer );
+								}
+							}
+						}
+					}
+				};
+				
+			peer.addListener( listener );
+
+			if ( peer.getState() == Peer.TRANSFERING ){
+				
+				peer.removeListener( listener );
+				
+					// withdraw buddy marker if it turns out our earlier optimism
+					// was misplaced
+			
+				if ( isBuddy( peer ) != BUDDY_YES ){
+					
+					unmarkBuddyPeer( peer );
+				}
+			}
+		}
+	}
+	
+	protected void
+	untrackPeers(
+		Download		download )
+	{
+		log( "Not tracking peers for " + download.getName());
+		
+		download.removePeerListener( this );
+		
+		PeerManager pm = download.getPeerManager();
+		
+		if ( pm != null ){
+
+			Peer[] peers = pm.getPeers();
+			
+			for (int i=0;i<peers.length;i++){
+				
+				Peer	peer = peers[i];
+				
+				unmarkBuddyPeer( peer );
+			}
+		}
+	}
+	
+	protected void
+	markBuddyPeer(
+		final Download		download,
+		final Peer			peer )
+	{
+		boolean	state_changed 	= false;
+		
+		synchronized( buddy_peers ){
+			
+			if ( !buddy_peers.contains( peer )){
+				
+				log( "Adding buddy peer " + peer.getIp());
+				
+				if ( buddy_peers.size() == 0 ){
+					
+					if ( buddy_stats_timer == null ){
+						
+						buddy_stats_timer = 
+							SimpleTimer.addPeriodicEvent(
+								"BuddyTracker:stats",
+								1000,
+								new TimerEventPerformer()
+								{
+									public void 
+									perform(
+										TimerEvent event )
+									{
+										Iterator it = buddy_peers.iterator();
+										
+										long	total_sent		= 0;
+										long	total_received	= 0;
+										
+										while( it.hasNext()){
+											
+											Peer	p = (Peer)it.next();
+											
+											PeerStats ps = p.getStats();
+											
+											long sent		= ps.getTotalSent();
+											long received 	= ps.getTotalReceived();
+											
+											long[]	last = (long[])p.getUserData( PEER_STATS_KEY );
+											
+											if ( last != null ){
+												
+												total_sent 		+= sent - last[0];
+												total_received	+= received - last[1];
+											}
+											
+											p.setUserData( PEER_STATS_KEY, new long[]{ sent, received });
+										}
+										
+										buddy_receive_speed.addValue( total_received );
+										buddy_send_speed.addValue( total_sent );
+									}
+								});
+					}
+					
+					state_changed 	= true;
+				}
+				
+				buddy_peers.add( peer );
+				
+				peer.setUserData( PEER_KEY, download );
+				
+				peer.setPriorityConnection( true );
+								
+				log( download.getName() + ": adding buddy peer " + peer.getIp());
+
+				peer.addListener(
+					new PeerListener2()
+					{ 
+						public void 
+						eventOccurred(
+							PeerEvent event )
+						{
+							if ( event.getType() == PeerEvent.ET_STATE_CHANGED ){
+								
+								int	state = ((Integer)event.getData()).intValue();
+								
+								if ( state == Peer.CLOSING || state == Peer.DISCONNECTED ){
+									
+									peer.removeListener( this );
+									
+									unmarkBuddyPeer( peer );
+								}
+							}	
+						}
+					});
+			}
+		}
+		
+		if ( peer.getState() == Peer.CLOSING || peer.getState() == Peer.DISCONNECTED ){
+			
+			unmarkBuddyPeer( peer );
+		}
+		
+		if ( state_changed ){
+			
+			updateNetworkStatus();
+		}
+	}
+	
+	protected void
+	unmarkBuddyPeer(
+		Peer		peer )
+	{
+		boolean	state_changed = false;
+		
+		synchronized( buddy_peers ){
+
+			Download download = (Download)peer.getUserData( PEER_KEY );
+				
+			if ( download == null ){
+				
+				return;
+			}
+
+			if ( buddy_peers.remove( peer )){
+				
+				if ( buddy_peers.size() == 0 ){
+					
+					state_changed = true;
+					
+					if ( buddy_stats_timer != null ){
+						
+						buddy_stats_timer.cancel();
+						
+						buddy_stats_timer = null;
+					}
+				}
+				
+				log( download.getName() + ": removing buddy peer " + peer.getIp());
+			}
+			
+			peer.setUserData( PEER_KEY, null );
+			
+			peer.setPriorityConnection( false );
+		}	
+		
+		if ( state_changed ){
+			
+			updateNetworkStatus();
+		}
+	}
+	
+	protected void
+	checkPeers()
+	{
+		List	to_unmark = new ArrayList();
+		
+		synchronized( buddy_peers ){
+
+			Iterator	it = buddy_peers.iterator();
+			
+			while( it.hasNext()){
+				
+				Peer	peer = (Peer)it.next();
+				
+				if ( peer.getState() == Peer.CLOSING || peer.getState() == Peer.DISCONNECTED ){
+					
+					to_unmark.add( peer );
+				}
+			}
+		}
+		
+		for (int i=0;i<to_unmark.size();i++){
+			
+			unmarkBuddyPeer((Peer)to_unmark.get(i));
+		}
+	}
+	
+	protected void
+	recheckPeers()
+	{
+			// go over peers for active torrents to see if we've missed and. can really only
+			// happen with multi-homed LAN setups where a new (and utilised) route is found
+			// after we start tracking 
+		
+		synchronized( actively_tracking ){
+			
+			Iterator it = actively_tracking.iterator();
+			
+			while( it.hasNext()){
+				
+				Download download = (Download)it.next();
+				
+				PeerManager pm = download.getPeerManager();
+				
+				if ( pm != null ){
+					
+					Peer[] peers = pm.getPeers();
+					
+					for (int i=0;i<peers.length;i++){
+						
+						trackPeer( download, peers[i] );
+					}
+				}
+			}
+		}
+	}
+	
+	protected void
+	updateNetworkStatus()
+	{	
+		int		new_status;
+		boolean	changed = false;
+		
+		synchronized( buddy_peers ){
+	
+			if ( buddy_peers.size() == 0 ){
+				
+				new_status 	= BUDDY_NETWORK_IDLE;
+				
+			}else{
+				
+				new_status	= seeding_only?BUDDY_NETWORK_OUTBOUND:BUDDY_NETWORK_INBOUND;
+			}
+			
+			if ( new_status != network_status ){
+				
+				network_status	= new_status;
+				
+				changed	= true;
+			}
+		}
+		
+		if ( changed ){
+		
+			fireStateChange( new_status );
+		}
+	}
+	
+	public void
+	addListener(
+		BuddyPluginTrackerListener		l )
+	{
+		listeners.add( l );
+	}
+	
+	public void
+	removeListener(
+		BuddyPluginTrackerListener		l )
+	{
+		listeners.remove( l );
+	}
+	
+	protected void
+	fireStateChange(
+		int		state )
+	{
+		Iterator	it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((BuddyPluginTrackerListener)it.next()).networkStatusChanged( this, state );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+	}
+	
+	protected void
+	fireEnabledChanged(
+		boolean	enabled )
+	{
+		Iterator	it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((BuddyPluginTrackerListener)it.next()).enabledStateChanged( this, enabled );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+	}
+	
+	protected void
+	sendMessage(
+		BuddyPluginBuddy	buddy,
+		int					type,
+		Map					body )
+	{
+		Map	msg = new HashMap();
+		
+		msg.put( "type", new Long( type ));
+		msg.put( "msg", body );
+		
+		plugin.getAZ2Handler().sendAZ2TrackerMessage(
+				buddy, 
+				msg, 
+				BuddyPluginTracker.this );
+	}
+	
+	public Map
+	messageReceived(
+		BuddyPluginBuddy	buddy,
+		Map					message )
+	{
+		buddyData buddy_data = buddyAlive( buddy );
+		
+		int type = ((Long)message.get( "type" )).intValue();
+		
+		Map msg = (Map)message.get( "msg" );
+		
+		return( buddy_data.receiveMessage( type, msg ));
+	}
+	
+	public void
+	messageFailed(
+		BuddyPluginBuddy	buddy,
+		Throwable			cause )
+	{
+		log( "Failed to send message to " + buddy.getName(), cause );
+		
+		buddyDead( buddy );
+	}
+	
+	protected buddyData
+	buddyAlive(
+		BuddyPluginBuddy		buddy )
+	{
+		buddyData buddy_data = addBuddy( buddy );
+		
+		buddy_data.setAlive( true );
+		
+		return( buddy_data );
+	}
+	
+	protected void
+	buddyDead(
+		BuddyPluginBuddy		buddy )
+	{
+		buddyData buddy_data = getBuddyData( buddy );
+
+		if ( buddy_data != null ){
+			
+			buddy_data.setAlive( false );
+		}
+	}
+	
+	protected boolean
+	okToTrack(
+		Download	d )
+	{
+		Torrent	t = d.getTorrent();
+		
+		if ( t == null ){
+			
+			return( false );
+		}
+		
+			// only track private torrents if we have successfully received peers from tracker
+			// which means we have the torrent legitimately. As this rule is enforced by both
+			// ends of the tracking operation it means we will only track between peers that
+			// both have a legitimate copy of the torrent.
+				
+		if ( t.isPrivate()){
+			
+			DownloadAnnounceResult announce = d.getLastAnnounceResult();
+
+			if ( 	announce == null ||
+					announce.getResponseType() != DownloadAnnounceResult.RT_SUCCESS ||
+					announce.getPeers().length < 2 ){
+				
+				return( false );
+			}
+		}
+		
+		int state = d.getState();
+		
+		return( 	state != Download.ST_ERROR && 
+					state != Download.ST_STOPPING && 
+					state != Download.ST_STOPPED );
+	}
+	
+	protected void
+	log(
+		String		str )
+	{
+		plugin.log( "Tracker: " + str );
+	}
+	
+	protected void
+	log(
+		String		str,
+		boolean		verbose )
+	{
+		if ( verbose ){
+			
+			if ( Constants.isCVSVersion()){
+			
+				log( str );
+			}
+		}else{
+			
+			log( str );
+		}
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable 	e )
+	{
+		plugin.log( "Tracker: " + str, e );
+	}
+	
+	private class
+	buddyData
+	{
+		private BuddyPluginBuddy		buddy;
+		
+		private Set	downloads_sent;
+		private int	downloads_sent_id;
+		
+		private Map		downloads_in_common;
+		private boolean	buddy_seeding_only;
+		
+		private int		consecutive_fails;
+		private long	last_fail;
+		
+		private String	current_ip;
+		
+		protected
+		buddyData(
+			BuddyPluginBuddy		_buddy )
+		{
+			buddy	= _buddy;
+		}
+		
+		protected void
+		updateIP()
+		{
+			InetAddress	latest_ip = buddy.getAdjustedIP();
+			
+			if ( latest_ip != null ){
+			
+				current_ip	= latest_ip.getHostAddress();
+			
+				log( "IP set to " + current_ip );
+			}
+		}
+			
+		protected boolean
+		hasIPChanged()
+		{
+			InetAddress	latest_ip = buddy.getAdjustedIP();
+			
+			if ( latest_ip == null && current_ip == null ){
+				
+				return( false );
+				
+			}else if ( latest_ip == null || current_ip == null ){
+				
+				return( true );
+				
+			}else{
+			
+				return(	!current_ip.equals( latest_ip.getHostAddress()));
+			}
+		}
+		
+		protected String
+		getIP()
+		{
+			return( current_ip );
+		}
+		
+		protected boolean
+		hasDownloadsInCommon()
+		{
+			synchronized( this ){
+			
+				return( downloads_in_common != null );
+			}
+		}
+		
+		protected void
+		setAlive(
+			boolean		alive )
+		{
+			synchronized( this ){
+				
+				if ( alive ){
+					
+					consecutive_fails		= 0;
+					last_fail				= 0;
+
+				}else{
+					
+					consecutive_fails++;
+					
+					last_fail	= SystemTime.getMonotonousTime();
+				}
+			}
+		}
+		
+		protected void
+		updateLocal(
+			Set		downloads,
+			int		id,
+			Map		diff_map )
+		{
+			if ( consecutive_fails > 0 ){
+				
+				long	retry_millis = RETRY_SEND_MIN;
+				
+				for (int i=0;i<consecutive_fails-1;i++){
+					
+					retry_millis <<= 2;
+					
+					if ( retry_millis > RETRY_SEND_MAX ){
+						
+						retry_millis = RETRY_SEND_MAX;
+						
+						break;
+					}
+				}
+				
+				long	now = SystemTime.getMonotonousTime();
+				
+				if ( now - last_fail >= retry_millis ){
+					
+					last_fail			= now;	// assume we're going to fail so we avoid
+												// falling through here multiple times before
+												// actuallt failing again
+					
+					downloads_sent 		= null;
+					downloads_sent_id	= 0;
+				}
+			}
+			
+				// first check to see if completion state changed for any common downloads
+			
+			List	comp_changed = new ArrayList();
+			
+			synchronized( this ){
+				
+				if ( downloads_in_common != null ){
+					
+					Iterator it = downloads_in_common.entrySet().iterator();
+					
+					while( it.hasNext()){
+						
+						Map.Entry	entry = (Map.Entry)it.next();
+						
+						Download d = (Download)entry.getKey();
+
+						buddyDownloadData	bdd = (buddyDownloadData)entry.getValue();
+						
+						boolean	local_complete = d.isComplete( false );
+						
+						if ( local_complete != bdd.isLocalComplete()){
+							
+							bdd.setLocalComplete( local_complete );
+							
+							comp_changed.add( d );
+						}
+					}
+				}
+			}
+			
+			if ( comp_changed.size() > 0 ){
+				
+				byte[][] change_details = exportFullIDs( comp_changed );
+				
+				if( change_details[0].length > 0 ){
+					
+					Map	msg = new HashMap();
+										
+					msg.put( "seeding", new Long( seeding_only?1:0 ));
+					
+					msg.put( "change", 		change_details[0] );
+					msg.put( "change_s", 	change_details[1] );
+
+					sendMessage( buddy, REQUEST_TRACKER_CHANGE, msg );
+				}
+			}
+			
+			if ( id == downloads_sent_id ){
+				
+				return;
+			}
+			
+			Long	key = new Long(((long)id) << 32 | (long)downloads_sent_id);
+				
+			Object[]	diffs = (Object[])diff_map.get( key );
+			
+			boolean	incremental = downloads_sent != null;
+			
+			byte[]	added_bytes;
+			byte[]	removed_bytes;
+			
+			if ( diffs == null ){
+				
+				List	added;
+				List	removed	= new ArrayList();
+				
+
+				if ( downloads_sent == null ){
+					
+					added 	= new ArrayList( downloads );
+					
+				}else{
+					
+					added	= new ArrayList();
+
+					Iterator	it1 = downloads.iterator();
+					
+					while( it1.hasNext()){
+					
+						Download download = (Download)it1.next();
+						
+						if ( okToTrack( download )){
+							
+							if ( !downloads_sent.contains( download )){
+								
+								added.add( download );
+							}
+						}
+					}
+					
+					Iterator	it2 = downloads_sent.iterator();
+					
+					while( it2.hasNext()){
+					
+						Download download = (Download)it2.next();
+						
+						if ( !downloads.contains( download )){
+							
+							removed.add( download );
+						}
+					}
+				}
+				
+				added_bytes 	= exportShortIDs( added );
+				removed_bytes	= exportFullIDs( removed )[0];
+				
+				diff_map.put( key, new Object[]{ added_bytes, removed_bytes });
+			}else{
+				
+				added_bytes 	= (byte[])diffs[0];
+				removed_bytes 	= (byte[])diffs[1];
+			}
+				
+			downloads_sent 		= downloads;
+			downloads_sent_id	= id;
+			
+			if ( added_bytes.length == 0 && removed_bytes.length == 0 ){
+				
+				return;
+			}
+			
+			Map	msg = new HashMap();
+			
+			if ( added_bytes.length > 0 ){
+				
+				msg.put( "added", 	added_bytes );
+			}
+			
+			if ( removed_bytes.length > 0 ){
+				
+				msg.put( "removed", removed_bytes );
+			}
+			
+			msg.put( "inc", 	new Long( incremental?1:0 ));
+			msg.put( "seeding", new Long( seeding_only?1:0 ));
+			
+			sendMessage( buddy, REQUEST_TRACKER_SUMMARY, msg );
+		}	
+		
+		protected Map
+		updateRemote(
+			Map		msg )
+		{			
+			List	added 	= importShortIDs((byte[])msg.get( "added" ));
+			
+			Map	reply = new HashMap();
+			
+			byte[][] add_details = exportFullIDs( added );
+			
+			if( add_details[0].length > 0 ){
+			
+				reply.put( "added", 	add_details[0] );
+				reply.put( "added_s", 	add_details[1] );
+			}
+			
+			synchronized( this ){
+
+				if ( downloads_in_common != null ){
+
+					Map removed = importFullIDs( (byte[])msg.get( "removed" ), null );
+					
+					Iterator it = removed.keySet().iterator();
+					
+					while( it.hasNext()){
+						
+						Download d = (Download)it.next();
+						
+						if ( downloads_in_common.remove( d ) != null ){
+							
+							log( "Removed " + d.getName() + " common download", false, true );
+						}
+					}
+				
+					if ( downloads_in_common.size() == 0 ){
+						
+						downloads_in_common = null;
+					}
+				}
+			}
+			
+			return( reply );
+		}
+		
+		protected void
+		updateCommonDownloads(
+			Map			downloads,
+			boolean		incremental )
+		{
+			synchronized( this ){
+
+				if ( downloads_in_common == null ){
+					
+					downloads_in_common = new HashMap();
+					
+				}else{
+					
+						// if not incremental then remove any downloads that no longer
+						// are in common
+					
+					if ( !incremental ){
+						
+						Iterator it = downloads_in_common.keySet().iterator();
+						
+						while( it.hasNext()){
+							
+							Download download = (Download)it.next();
+							
+							if ( !downloads.containsKey( download )){
+								
+								log( "Removing " + download.getName() + " from common downloads", false, true );
+
+								it.remove();
+							}
+						}
+					}
+				}
+				
+				Iterator it = downloads.entrySet().iterator();
+				
+				while( it.hasNext()){
+					
+					Map.Entry	entry = (Map.Entry)it.next();
+			
+					Download d = (Download)entry.getKey();
+
+					buddyDownloadData	bdd = (buddyDownloadData)entry.getValue();
+					
+					buddyDownloadData existing = (buddyDownloadData)downloads_in_common.get( d );
+					
+					if ( existing == null ){
+						
+						log( "Adding " + d.getName() + " to common downloads (bdd=" + bdd.getString() + ")", false, true );
+						
+						downloads_in_common.put( d, bdd );
+						
+					}else{
+						
+						boolean	old_rc = existing.isRemoteComplete();
+						boolean	new_rc = bdd.isRemoteComplete();
+						
+						if ( old_rc != new_rc ){
+						
+							existing.setRemoteComplete( new_rc ); 
+							
+							log( "Changing " + d.getName() + " common downloads (bdd=" + existing.getString() + ")", false, true );
+						}				
+					}
+				}
+				
+				if ( downloads_in_common.size() == 0 ){
+					
+					downloads_in_common = null;
+				}
+			}
+		}
+		
+		protected void
+		updateStatus()
+		{
+			Map	msg = new HashMap();
+			
+			msg.put( "seeding", new Long( seeding_only?1:0 ));
+			
+			sendMessage( buddy, REQUEST_TRACKER_STATUS, msg );
+		}
+		
+		protected Map
+		receiveMessage(
+			int			type,
+			Map			msg_in )
+		{
+			int	reply_type	= -1;
+			Map	msg_out		= null;
+
+			Long	l_seeding = (Long)msg_in.get( "seeding" );
+			
+			if( l_seeding != null ){
+				
+				boolean old = buddy_seeding_only;
+				
+				buddy_seeding_only = l_seeding.intValue() == 1;
+				
+				if ( old != buddy_seeding_only ){
+					
+					log( "Seeding only changed to " + buddy_seeding_only );
+				}
+			}
+			
+			if ( type == REQUEST_TRACKER_SUMMARY ){
+		
+				reply_type	= REPLY_TRACKER_SUMMARY;
+				
+				msg_out = updateRemote( msg_in );
+				
+				msg_out.put( "inc", msg_in.get( "inc" ));
+								
+			}else if ( type == REQUEST_TRACKER_STATUS ){
+				
+				reply_type	= REPLY_TRACKER_STATUS;
+				
+			}else if ( type == REQUEST_TRACKER_CHANGE ){
+
+				reply_type	= REPLY_TRACKER_STATUS;
+									
+				Map downloads = importFullIDs( (byte[])msg_in.get( "changed" ), (byte[])msg_in.get( "changed_s" ) );
+
+				updateCommonDownloads( downloads, true );
+								
+			}else if ( type == REQUEST_TRACKER_ADD ){
+
+				reply_type	= REPLY_TRACKER_ADD;
+										
+				Map downloads = importFullIDs( (byte[])msg_in.get( "added" ), (byte[])msg_in.get( "added_s" ) );
+
+				updateCommonDownloads( downloads, true );
+
+			}else if ( type == REPLY_TRACKER_SUMMARY ){
+				
+					// full hashes on reply
+				
+				byte[]	possible_matches 		= (byte[])msg_in.get( "added" );
+				byte[]	possible_match_states 	= (byte[])msg_in.get( "added_s" );
+
+				boolean	incremental = ((Long)msg_in.get( "inc" )).intValue() == 1;
+				
+				if ( possible_matches != null && possible_match_states != null ){
+							
+					Map downloads = importFullIDs( possible_matches, possible_match_states );
+						
+					if ( downloads.size() > 0 ){
+												
+						updateCommonDownloads( downloads, incremental );
+						
+						byte[][] common_details = exportFullIDs( new ArrayList( downloads.keySet()));
+						
+						if( common_details[0].length > 0 ){
+							
+							Map	msg = new HashMap();
+												
+							msg.put( "seeding", new Long( seeding_only?1:0 ));
+							
+							msg.put( "added", 	common_details[0] );
+							msg.put( "added_s", common_details[1] );
+
+							sendMessage( buddy, REQUEST_TRACKER_ADD, msg );
+						}
+					}
+				}
+								
+			}else if ( 	type == REPLY_TRACKER_CHANGE ||
+						type == REPLY_TRACKER_STATUS ||
+						type == REPLY_TRACKER_ADD ){
+				
+					// nothing interesting in reply for these
+			}else{
+				
+				log( "Unrecognised type " + type );
+			}
+			
+			if ( reply_type != -1 ){
+				
+				Map	reply = new HashMap();
+			
+				reply.put( "type", new Long( reply_type ));
+		
+				if ( msg_out == null ){
+					
+					msg_out = new HashMap();
+				}
+				
+				msg_out.put( "seeding", new Long( seeding_only?1:0 ));
+			
+				reply.put( "msg", msg_out );
+
+				return( reply );
+			}
+			
+			return( null );
+		}
+		
+		protected byte[]
+		exportShortIDs(
+			List	downloads )
+		{
+			byte[]	res = new byte[ SHORT_ID_SIZE * downloads.size() ];
+			
+			for (int i=0;i<downloads.size();i++ ){
+				
+				Download download = (Download)downloads.get(i);
+				
+				downloadData download_data = (downloadData)download.getUserData( BuddyPluginTracker.class );
+				
+				if ( download_data != null ){
+
+					System.arraycopy(
+						download_data.getID().getBytes(),
+						0,
+						res,
+						i * SHORT_ID_SIZE,
+						SHORT_ID_SIZE );
+				}
+			}
+			
+			return( res );
+		}
+		
+		protected List
+		importShortIDs(
+			byte[]		ids )
+		{
+			List	res = new ArrayList();
+			
+			if ( ids != null ){
+				
+				synchronized( tracked_downloads ){
+
+					for (int i=0;i<ids.length;i+= SHORT_ID_SIZE ){
+					
+						List dls = (List)short_id_map.get( new HashWrapper( ids, i, SHORT_ID_SIZE ));
+						
+						if ( dls != null ){
+							
+							res.addAll( dls );
+						}
+					}
+				}
+			}
+			
+			return( res );
+		}
+		
+		protected byte[][]
+   		exportFullIDs(
+   			List	downloads )
+   		{
+   			byte[]	hashes 	= new byte[ FULL_ID_SIZE * downloads.size() ];
+   			byte[] 	states	= new byte[ downloads.size()];
+   			
+   			for (int i=0;i<downloads.size();i++ ){
+   				
+   				Download download = (Download)downloads.get(i);
+   				
+   				downloadData download_data = (downloadData)download.getUserData( BuddyPluginTracker.class );
+   				
+   				if ( download_data != null ){
+
+   					System.arraycopy(
+   						download_data.getID().getBytes(),
+   						0,
+   						hashes,
+   						i * FULL_ID_SIZE,
+   						FULL_ID_SIZE );
+   					
+   					states[i] = download.isComplete( false )?(byte)0x01:(byte)0x00;
+   				}
+   			}
+   			
+   			return( new byte[][]{ hashes, states });
+   		}
+		
+		protected Map
+		importFullIDs(
+			byte[]		ids,
+			byte[]		states )
+		{
+			Map	res = new HashMap();
+			
+			if ( ids != null ){
+				
+				synchronized( tracked_downloads ){
+
+					for (int i=0;i<ids.length;i+= FULL_ID_SIZE ){
+					
+						Download dl = (Download)full_id_map.get( new HashWrapper( ids, i, FULL_ID_SIZE ));
+						
+						if ( dl != null ){
+							
+							buddyDownloadData bdd = new buddyDownloadData( dl );
+							
+							if ( states != null ){
+							
+								bdd.setRemoteComplete(( states[i/FULL_ID_SIZE] & 0x01 ) != 0 );
+							}
+							
+							res.put( dl, bdd );
+						}
+					}
+				}
+			}
+			
+			return( res );
+		}
+		
+		protected Map
+		getDownloadsToTrack()
+		{
+			Map	res = new HashMap();
+
+			if ( seeding_only == buddy_seeding_only ){
+				
+				log( "Not tracking, buddy and me both " + (seeding_only?"seeding":"downloading"), true, false );
+
+				return( res );
+			}			
+		
+			long	now = SystemTime.getMonotonousTime();
+			
+			synchronized( this ){
+
+				if ( downloads_in_common == null ){
+					
+					log( "Not tracking, buddy has nothing in common", true, false );
+
+					return( res );
+				}
+				
+				Iterator it = downloads_in_common.entrySet().iterator();
+				
+				while( it.hasNext()){
+					
+					Map.Entry	entry = (Map.Entry)it.next();
+			
+					Download d = (Download)entry.getKey();
+
+					buddyDownloadData	bdd = (buddyDownloadData)entry.getValue();
+					
+					if ( d.isComplete( false ) && bdd.isRemoteComplete()){
+						
+							// both complete, nothing to do!
+						
+						log( d.getName() + " - not tracking, both complete", true, true );
+						
+					}else{
+						
+						long	last_track = bdd.getTrackTime();
+						
+						if ( 	last_track == 0 || 
+								now - last_track >= TRACK_INTERVAL ){
+							
+							log( d.getName() + " - tracking", false, true );
+
+							bdd.setTrackTime( now );
+							
+							res.put( d, new Boolean( true ));
+							
+						}else{
+							
+							res.put( d, new Boolean( false ));
+						}
+					}
+				}
+			}
+			
+			return( res );
+		}
+		
+		protected void
+		resetTracking(
+			Download		download )
+		{
+			synchronized( this ){
+				
+				if ( downloads_in_common == null ){
+					
+					return;
+				}
+				
+				buddyDownloadData bdd = (buddyDownloadData)downloads_in_common.get( download );
+				
+				if ( bdd != null ){
+					
+					bdd.resetTrackTime();
+				}
+			}
+		}
+		
+		protected void
+		log(
+			String	str )
+		{
+			BuddyPluginTracker.this.log( buddy.getName() + ": " + str );
+		}
+		
+		protected void
+		log(
+			String	str,
+			boolean	verbose,
+			boolean	no_buddy )
+		{
+			BuddyPluginTracker.this.log( (no_buddy?"":( buddy.getName() + ": ")) + str, verbose );
+		}
+	}
+	
+	private static class
+	buddyDownloadData
+	{
+		private boolean	local_is_complete;
+		private boolean	remote_is_complete;
+		private long	last_track;
+		
+		protected
+		buddyDownloadData(
+			Download		download )
+		{
+			local_is_complete = download.isComplete( false );
+		}
+		
+		protected void
+		setLocalComplete(
+			boolean		b )
+		{
+			local_is_complete	= b;
+		}
+	
+		protected boolean
+		isLocalComplete()
+		{
+			return( local_is_complete );
+		}
+		
+		protected void
+		setRemoteComplete(
+			boolean		b )
+		{
+			remote_is_complete	= b;
+		}
+	
+		protected boolean
+		isRemoteComplete()
+		{
+			return( remote_is_complete );
+		}
+		
+		protected void
+		setTrackTime(
+			long	time )
+		{
+			last_track	= time;
+		}
+		
+		protected long
+		getTrackTime()
+		{
+			return( last_track );
+		}
+		
+		protected void
+		resetTrackTime()
+		{
+			last_track	= 0;
+		}
+		
+		protected String
+		getString()
+		{
+			return( "lic=" + local_is_complete + ",ric=" + remote_is_complete + ",lt=" + last_track );
+		}
+	}
+	
+	private static class
+	downloadData
+	{
+		private static final byte[]	IV = {(byte)0x7A, (byte)0x7A, (byte)0xAD, (byte)0xAB, (byte)0x8E, (byte)0xBF, (byte)0xCD, (byte)0x39, (byte)0x87, (byte)0x0, (byte)0xA4, (byte)0xB8, (byte)0xFE, (byte)0x40, (byte)0xA2, (byte)0xE8 }; 
+			
+		private HashWrapper	id;
+		
+		protected
+		downloadData(
+			Download	download )
+		{
+			Torrent t = download.getTorrent();
+			
+			if ( t != null ){
+				
+				byte[]	hash = t.getHash();
+				
+				SHA1	sha1 = new SHA1();
+			
+				sha1.update( ByteBuffer.wrap( IV ));
+				sha1.update( ByteBuffer.wrap( hash ));
+				
+				id = new HashWrapper( sha1.digest() );
+			}
+		}
+		
+		protected HashWrapper
+		getID()
+		{
+			return( id );
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/tracker/BuddyPluginTrackerListener.java b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/tracker/BuddyPluginTrackerListener.java
index d20a213..6db6084 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/buddy/tracker/BuddyPluginTrackerListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/buddy/tracker/BuddyPluginTrackerListener.java
@@ -1,36 +1,35 @@
-/*
- * Created on May 29, 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.plugins.net.buddy.tracker;
-
-public interface 
-BuddyPluginTrackerListener 
-{
-	public void
-	enabledStateChanged(
-		BuddyPluginTracker	tracker,
-		boolean				enabled );
-	
-	public void
-	networkStatusChanged(
-		BuddyPluginTracker	tracker,
-		int					new_status );
-}
+/*
+ * Created on May 29, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy.tracker;
+
+public interface 
+BuddyPluginTrackerListener 
+{
+	public void
+	enabledStateChanged(
+		BuddyPluginTracker	tracker,
+		boolean				enabled );
+	
+	public void
+	networkStatusChanged(
+		BuddyPluginTracker	tracker,
+		int					new_status );
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusPlugin.java
index e44aa52..0ce97df 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusPlugin.java
@@ -1,255 +1,269 @@
-/*
- * Created on Jan 30, 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.plugins.net.netstatus;
-
-
-import org.gudy.azureus2.core3.util.AESemaphore;
-import org.gudy.azureus2.core3.util.AEThread2;
-
-import org.gudy.azureus2.core3.util.Constants;
-
-import org.gudy.azureus2.plugins.*;
-
-import org.gudy.azureus2.plugins.logging.LoggerChannel;
-import org.gudy.azureus2.plugins.ui.UIInstance;
-import org.gudy.azureus2.plugins.ui.UIManagerListener;
-import org.gudy.azureus2.plugins.ui.config.ActionParameter;
-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;
-
-public class 
-NetStatusPlugin
-	implements Plugin
-{
-	public static final String VIEW_ID = "aznetstatus";
-	
-	private PluginInterface	plugin_interface;
-	
-	private LoggerChannel	logger;
-	
-	// private StringParameter ping_target;
-	
-	private ActionParameter test_button;
-	private StringParameter test_address;
-	
-	private NetStatusProtocolTester		protocol_tester;
-	private AESemaphore					protocol_tester_sem	= new AESemaphore( "ProtTestSem" );
-	
-	public static void
-	load(
-		PluginInterface		plugin_interface )
-	{
-		String name = 
-			plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "Views.plugins." + VIEW_ID + ".title" );
-		
-		plugin_interface.getPluginProperties().setProperty( "plugin.version", 	"1.0" );
-		plugin_interface.getPluginProperties().setProperty( "plugin.name", 		name );
-
-	}
-	
-	public void
-	initialize(
-		final PluginInterface		_plugin_interface )
-	{
-		plugin_interface	= _plugin_interface;
-				
-		logger = plugin_interface.getLogger().getChannel( "NetStatus" );
-		
-		logger.setDiagnostic();
-				
-		BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel( "Views.plugins." + VIEW_ID + ".title" );
-		
-		// ping_target = config.addStringParameter2( "plugin.aznetstatus.pingtarget", "plugin.aznetstatus.pingtarget", "www.google.com" );
-		
-		if ( Constants.isCVSVersion()){
-			
-			test_address = config.addStringParameter2( "plugin.aznetstatus.test_address", "plugin.aznetstatus.test_address", "" );
-	
-			test_button = config.addActionParameter2( "test", "test " );
-			
-			test_button.setEnabled( false );
-			
-			test_button.addListener(
-				new ParameterListener()
-				{
-					public void
-					parameterChanged(
-						Parameter	param )
-					{
-						protocol_tester.runTest( 
-								test_address.getValue().trim(),
-								new NetStatusProtocolTesterListener()
-								{
-									public void 
-									sessionAdded(
-											NetStatusProtocolTesterBT.Session session ) 
-									{
-									}
-									
-									public void
-									complete(
-										NetStatusProtocolTesterBT	tester )
-									{
-									}
-									
-									public void 
-									log(
-										String str ) 
-									{
-										logger.log( str );
-									}
-									
-									public void 
-									logError(
-										String str ) 
-									{
-										logger.log( str );
-									}
-									
-									public void 
-									logError(
-										String 		str,
-										Throwable 	e )
-									{
-										logger.log( str, e );
-									}
-								});
-					}
-				});
-		}
-		
-		plugin_interface.getUIManager().addUIListener(
-			new UIManagerListener()
-			{
-				public void
-				UIAttached(
-					UIInstance		instance )
-				{
-					if ( instance.getUIType() == UIInstance.UIT_SWT ){
-						
-						try{
-							Class.forName( "com.aelitis.azureus.plugins.net.netstatus.swt.NetStatusPluginView" ).getConstructor(
-								new Class[]{ NetStatusPlugin.class, UIInstance.class, String.class } ).newInstance(
-									new Object[]{ NetStatusPlugin.this, instance, VIEW_ID } );
-							
-						}catch( Throwable e ){
-							
-							e.printStackTrace();
-						}
-					}
-				}
-
-				public void
-				UIDetached(
-					UIInstance		instance )
-				{
-				}
-			});
-		
-		plugin_interface.addListener(
-			new PluginListener()
-			{
-				public void
-				initializationComplete()
-				{
-					new AEThread2( "NetstatusPlugin:init", true )
-					{
-						public void
-						run()
-						{
-							try{
-								protocol_tester = new NetStatusProtocolTester( NetStatusPlugin.this, plugin_interface );
-								
-								if ( test_button != null ){
-									
-									test_button.setEnabled( true );
-								}
-							}finally{
-								
-								protocol_tester_sem.releaseForever();
-							}
-						}
-					}.start();
-				}
-				
-				public void
-				closedownInitiated()
-				{				
-				}
-				
-				public void
-				closedownComplete()
-				{				
-				}
-			});
-	}
-	
-	public NetStatusProtocolTester
-	getProtocolTester()
-	{
-		protocol_tester_sem.reserve();
-		
-		return( protocol_tester );
-	}
-	
-	/*
-	public String
-	getPingTarget()
-	{
-		return( ping_target.getValue());
-	}
-	*/
-	
-	public void
-	setBooleanParameter(
-		String	name,
-		boolean	value )
-	{
-		plugin_interface.getPluginconfig().setPluginParameter( name , value );
-	}
-	
-	public boolean
-	getBooleanParameter(
-		String	name,
-		boolean	def )
-	{
-		return( plugin_interface.getPluginconfig().getPluginBooleanParameter( name, def ));
-	}
-	
-	public void
-	log(
-		String		str )
-	{
-		logger.log( str );
-	}
-	
-	public void
-	log(
-		String		str,
-		Throwable	e )
-	{
-		logger.log( str );
-		logger.log( e );
-	}
-}
+/*
+ * Created on Jan 30, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.netstatus;
+
+
+import org.gudy.azureus2.core3.util.AESemaphore;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.plugins.*;
+import org.gudy.azureus2.plugins.logging.LoggerChannel;
+import org.gudy.azureus2.plugins.ui.UIInstance;
+import org.gudy.azureus2.plugins.ui.UIManagerListener;
+import org.gudy.azureus2.plugins.ui.config.ActionParameter;
+import org.gudy.azureus2.plugins.ui.config.BooleanParameter;
+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;
+
+public class 
+NetStatusPlugin
+	implements Plugin
+{
+	public static final String VIEW_ID = "aznetstatus";
+	
+	private PluginInterface	plugin_interface;
+	
+	private LoggerChannel	logger;
+	
+	// private StringParameter ping_target;
+	private BooleanParameter	logging_detailed;
+	
+	private ActionParameter test_button;
+	private StringParameter test_address;
+	
+	private NetStatusProtocolTester		protocol_tester;
+	private AESemaphore					protocol_tester_sem	= new AESemaphore( "ProtTestSem" );
+	
+	public static void
+	load(
+		PluginInterface		plugin_interface )
+	{
+		String name = 
+			plugin_interface.getUtilities().getLocaleUtilities().getLocalisedMessageText( "Views.plugins." + VIEW_ID + ".title" );
+		
+		plugin_interface.getPluginProperties().setProperty( "plugin.version", 	"1.0" );
+		plugin_interface.getPluginProperties().setProperty( "plugin.name", 		name );
+
+	}
+	
+	public void
+	initialize(
+		final PluginInterface		_plugin_interface )
+	{
+		plugin_interface	= _plugin_interface;
+				
+		logger = plugin_interface.getLogger().getChannel( "NetStatus" );
+		
+		logger.setDiagnostic();
+				
+		BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel( "Views.plugins." + VIEW_ID + ".title" );
+		
+		logging_detailed = config.addBooleanParameter2( "plugin.aznetstatus.logfull", "plugin.aznetstatus.logfull", false );
+		
+		// ping_target = config.addStringParameter2( "plugin.aznetstatus.pingtarget", "plugin.aznetstatus.pingtarget", "www.google.com" );
+		
+		/*
+		if ( Constants.isCVSVersion()){
+			
+			test_address = config.addStringParameter2( "plugin.aznetstatus.test_address", "plugin.aznetstatus.test_address", "" );
+	
+			test_button = config.addActionParameter2( "test", "test " );
+			
+			test_button.setEnabled( false );
+			
+			test_button.addListener(
+				new ParameterListener()
+				{
+					public void
+					parameterChanged(
+						Parameter	param )
+					{
+						protocol_tester.runTest( 
+								test_address.getValue().trim(),
+								new NetStatusProtocolTesterListener()
+								{
+									public void 
+									sessionAdded(
+											NetStatusProtocolTesterBT.Session session ) 
+									{
+									}
+									
+									public void
+									complete(
+										NetStatusProtocolTesterBT	tester )
+									{
+									}
+									
+									public void 
+									log(
+										String 		str,
+										boolean		detailed )
+									{
+										if ( detailed && !logging_detailed.getValue()){
+											
+											return;
+										}
+										
+										logger.log( str );
+									}
+									
+									public void 
+									logError(
+										String str ) 
+									{
+										logger.log( str );
+									}
+									
+									public void 
+									logError(
+										String 		str,
+										Throwable 	e )
+									{
+										logger.log( str, e );
+									}
+								});
+					}
+				});
+		}
+		*/
+		
+		plugin_interface.getUIManager().addUIListener(
+			new UIManagerListener()
+			{
+				public void
+				UIAttached(
+					UIInstance		instance )
+				{
+					if ( instance.getUIType() == UIInstance.UIT_SWT ){
+						
+						try{
+							Class.forName( "com.aelitis.azureus.plugins.net.netstatus.swt.NetStatusPluginView" ).getConstructor(
+								new Class[]{ NetStatusPlugin.class, UIInstance.class, String.class } ).newInstance(
+									new Object[]{ NetStatusPlugin.this, instance, VIEW_ID } );
+							
+						}catch( Throwable e ){
+							
+							e.printStackTrace();
+						}
+					}
+				}
+
+				public void
+				UIDetached(
+					UIInstance		instance )
+				{
+				}
+			});
+		
+		plugin_interface.addListener(
+			new PluginListener()
+			{
+				public void
+				initializationComplete()
+				{
+					new AEThread2( "NetstatusPlugin:init", true )
+					{
+						public void
+						run()
+						{
+							try{
+								protocol_tester = new NetStatusProtocolTester( NetStatusPlugin.this, plugin_interface );
+								
+								if ( test_button != null ){
+									
+									test_button.setEnabled( true );
+								}
+							}finally{
+								
+								protocol_tester_sem.releaseForever();
+							}
+						}
+					}.start();
+				}
+				
+				public void
+				closedownInitiated()
+				{				
+				}
+				
+				public void
+				closedownComplete()
+				{				
+				}
+			});
+	}
+	
+	public boolean
+	isDetailedLogging()
+	{
+		return( logging_detailed.getValue());
+	}
+	
+	public NetStatusProtocolTester
+	getProtocolTester()
+	{
+		protocol_tester_sem.reserve();
+		
+		return( protocol_tester );
+	}
+	
+	/*
+	public String
+	getPingTarget()
+	{
+		return( ping_target.getValue());
+	}
+	*/
+	
+	public void
+	setBooleanParameter(
+		String	name,
+		boolean	value )
+	{
+		plugin_interface.getPluginconfig().setPluginParameter( name , value );
+	}
+	
+	public boolean
+	getBooleanParameter(
+		String	name,
+		boolean	def )
+	{
+		return( plugin_interface.getPluginconfig().getPluginBooleanParameter( name, def ));
+	}
+	
+	public void
+	log(
+		String		str )
+	{
+		logger.log( str );
+	}
+	
+	public void
+	log(
+		String		str,
+		Throwable	e )
+	{
+		logger.log( str );
+		logger.log( e );
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTester.java b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTester.java
index bdd3ea8..76696b4 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTester.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTester.java
@@ -1,648 +1,648 @@
-/*
- * Created on Feb 15, 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.plugins.net.netstatus;
-
-import java.net.InetSocketAddress;
-import java.util.*;
-
-
-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.BDecoder;
-import org.gudy.azureus2.core3.util.BEncoder;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.DelayedEvent;
-import org.gudy.azureus2.core3.util.HashWrapper;
-import org.gudy.azureus2.core3.util.SimpleTimer;
-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.plugins.PluginInterface;
-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 com.aelitis.azureus.core.dht.DHT;
-import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
-import com.aelitis.azureus.core.networkmanager.NetworkManager;
-import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager;
-import com.aelitis.azureus.plugins.dht.DHTPlugin;
-import com.aelitis.azureus.plugins.net.netstatus.NetStatusProtocolTesterBT.Session;
-
-
-public class 
-NetStatusProtocolTester
-	implements DistributedDatabaseTransferHandler
-{
-	private static final int REQUEST_HISTORY_MAX	= 64;
-	
-	private static final int MAX_ACTIVE_TESTS	= 3;
-	private static final int MAX_TEST_TIME		= 120*1000;
-	
-	private static final int TEST_TYPE_BT		= 1;
-	
-	private static final int	VERSION_INITIAL	= 1;
-	
-	private static final int	CURRENT_VERSION	= VERSION_INITIAL;
-		
-	private static final int	BT_MAX_SLAVES	= 8;
-	
-	private NetStatusPlugin		plugin;
-	private PluginInterface		plugin_interface;
-
-	private DistributedDatabase	ddb;
-		
-	private DHTPlugin			dht_plugin;
-	
-	
-
-	private testXferType transfer_type = new testXferType();
-
-	private Map	request_history =  
-		new LinkedHashMap(REQUEST_HISTORY_MAX,0.75f,true)
-		{
-			protected boolean 
-			removeEldestEntry(
-		   		Map.Entry eldest) 
-			{
-				return size() > REQUEST_HISTORY_MAX;
-			}
-		};
-		
-	private List active_tests 		= new ArrayList();
-	
-	private TimerEventPeriodic	timer_event	= null;
-		
-	protected
-	NetStatusProtocolTester(
-		NetStatusPlugin		_plugin,
-		PluginInterface		_plugin_interface )
-	{
-		plugin				= _plugin;
-		plugin_interface	= _plugin_interface;
-		
-		try{
-			PluginInterface dht_pi = plugin_interface.getPluginManager().getPluginInterfaceByClass( DHTPlugin.class );
-			
-			if ( dht_pi != null ){
-				
-				dht_plugin = (DHTPlugin)dht_pi.getPlugin();
-			}
-
-			ddb = plugin_interface.getDistributedDatabase();
-			
-			if ( ddb.isAvailable()){
-			
-				ddb.addTransferHandler( transfer_type, this );
-			
-				log( "DDB transfer type registered" );
-				
-			}else{
-				
-				log( "DDB transfer type not registered, DDB unavailable" );
-			}			
-		}catch( Throwable e ){
-			
-			log( "DDB transfer type registration failed", e );
-		}
-	}
-	
-	public NetStatusProtocolTesterBT
-	runTest(
-		final NetStatusProtocolTesterListener		listener )
-	{
-		return( runTest( "", listener ));
-	}
-	
-	public NetStatusProtocolTesterBT
-	runTest(
-		String										test_address,
-		final NetStatusProtocolTesterListener		listener )
-	{
-		final NetStatusProtocolTesterBT bt_tester = new NetStatusProtocolTesterBT( this, true );
-
-		bt_tester.addListener( listener );
-		
-		bt_tester.start();
-		
-		addToActive( bt_tester );
-		
-		try{
-			if ( test_address.length() == 0 ){
-				
-				DHT[]	dhts = dht_plugin.getDHTs();
-				
-				DHT	target_dht = null;
-				
-				int	target_network	= Constants.isCVSVersion()?DHT.NW_CVS:DHT.NW_MAIN;
-				
-				for (int i=0;i<dhts.length;i++){
-					
-					if ( dhts[i].getTransport().getNetwork() == target_network ){
-						
-						target_dht = dhts[i];
-						
-						break;
-					}
-				}
-				
-				if ( target_dht == null ){
-					
-					listener.logError( "Distributed database unavailable" );
-					
-				}else{
-					
-					DHTTransportContact[] contacts = target_dht.getTransport().getReachableContacts();
-					
-					final List f_contacts = new ArrayList(Arrays.asList(contacts));
-					
-					final int[]	ok = new int[]{ 0 };
-					
-					final int	num_threads = Math.min( BT_MAX_SLAVES, contacts.length );
-					
-					listener.log( "Searching " + contacts.length + " contacts for " + num_threads + " test targets" );
-							
-					final AESemaphore	sem = new AESemaphore( "NetStatusProbe" );
-					
-					for (int i=0;i<num_threads;i++){
-						
-						new AEThread2( "NetStatusProbe", true )
-						{
-							public void
-							run()
-							{
-								try{
-									while( !bt_tester.isDestroyed()){
-										
-										DHTTransportContact	contact = null;
-										
-										synchronized( ok ){
-											
-											if ( ok[0] < num_threads && f_contacts.size() > 0 ){
-												
-												contact = (DHTTransportContact)f_contacts.remove(0);
-											}
-										}
-										
-										if ( contact == null ){
-											
-											break;
-										}
-										
-										try{
-											DistributedDatabaseContact ddb_contact = ddb.importContact( contact.getAddress());
-											
-											if ( tryTest( bt_tester, ddb_contact )){
-												
-												synchronized( ok ){
-													
-													ok[0]++;
-												}
-											}
-										}catch( Throwable e ){
-											
-											listener.logError( "Contact import for " + contact.getName() + " failed", e );
-										}
-									}
-								}finally{
-									
-									sem.release();
-								}
-							}
-						}.start();
-					}
-					
-					for (int i=0;i<num_threads;i++){
-						
-						sem.reserve();
-					}
-					
-					listener.log( "Searching complete, " + ok[0] + " targets found" );
-				}
-			}else{
-				
-				String[]	bits = test_address.split( ":" );
-				
-				if ( bits.length != 2 ){
-					
-					log( "Invalid address - use <host>:<port> " );
-					
-					return( bt_tester );
-				}
-				
-				InetSocketAddress address = new InetSocketAddress( bits[0].trim(), Integer.parseInt( bits[1].trim()));
-				 
-				DistributedDatabaseContact contact = ddb.importContact( address );
-
-				tryTest( bt_tester, contact );
-			}
-		}catch( Throwable e ){
-			
-			listener.logError( "Test failed", e );
-			
-		}finally{
-			
-			bt_tester.addListener(
-				new NetStatusProtocolTesterListener()
-				{
-					public void 
-					sessionAdded(
-						Session session) 
-					{
-					}
-					
-					public void
-					complete(
-						NetStatusProtocolTesterBT tester )
-					{
-						removeFromActive( tester );
-					}
-					
-					public void
-					log(
-						String		str )
-					{
-					}
-					
-					public void
-					logError(
-						String		str )
-					{
-					}
-					
-					public void
-					logError(
-						String		str,
-						Throwable	e )
-					{
-					}
-				});
-			
-			bt_tester.setOutboundConnectionsComplete();
-			
-			new DelayedEvent(
-				"NetStatus:killer",
-				10*1000,
-				new AERunnable()
-				{
-					public void
-					runSupport()
-					{
-						listener.log( "Destroying tester" );
-						
-						bt_tester.destroy();
-					}
-				});
-		}
-		
-		return( bt_tester );
-	}
-	
-	protected boolean
-	tryTest(
-		NetStatusProtocolTesterBT		bt_tester,
-		DistributedDatabaseContact		contact )
-	{
-		boolean	use_crypto = NetworkManager.getCryptoRequired( NetworkManager.CRYPTO_OVERRIDE_NONE );
-
-		log( "Trying test to " + contact.getName());
-		
-		Map	request = new HashMap();
-		
-		request.put( "v", new Long( CURRENT_VERSION ));
-				
-		request.put( "t", new Long( TEST_TYPE_BT ));
-			
-		request.put( "h", bt_tester.getServerHash());
-			
-		request.put( "c", new Long( use_crypto?1:0 ));
-		
-		Map	reply = sendRequest( contact, request );
-				
-		byte[]	server_hash = reply==null?null:(byte[])reply.get( "h" );
-			
-		if ( server_hash != null ){
-				
-			log( "    " + contact.getName() + " accepted test" );
-			
-			bt_tester.testOutbound( adjustLoopback( contact.getAddress()), server_hash, use_crypto );
-			
-			return( true );
-			
-		}else{
-			
-			log( "    " + contact.getName() + " declined test" );
-
-			return( false );
-		}
-	}
-	
-	protected InetSocketAddress
-	adjustLoopback(
-		InetSocketAddress	address )
-	{
-		InetSocketAddress local = dht_plugin.getLocalAddress().getAddress();
-		
-		if ( local.getAddress().getHostAddress().equals( address.getAddress().getHostAddress())){
-			
-			return( new InetSocketAddress( "127.0.0.1", address.getPort()));
-			
-		}else{
-			
-			return( address );
-		}
-	}
-	
-	protected Map
-	sendRequest(
-		DistributedDatabaseContact	contact,
-		Map							request )
-	{
-		try{
-			log( "Sending DDB request to " + contact.getName() + " - " + request );
-			
-			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 );
-			
-			if ( value == null ){
-				
-				return( null );
-			}
-			
-			Map reply = BDecoder.decode((byte[])value.getValue( byte[].class ));
-			
-			log( "    received reply - " + reply );
-			
-			return( reply );
-			
-		}catch( Throwable e ){
-			
-			log( "sendRequest failed", e );
-			
-			return( null );
-		}
-	}
-	
-	protected Map
-	receiveRequest(
-		InetSocketAddress	originator,
-		Map					request )
-	{
-		Map	reply = new HashMap();
-		
-		Long	test_type	= (Long)request.get( "t" );
-		
-		reply.put( "v", new Long( CURRENT_VERSION ));
-		
-		if ( test_type != null ){
-			
-			if ( test_type.intValue() == TEST_TYPE_BT ){
-				
-				TCPNetworkManager tcp_man = TCPNetworkManager.getSingleton();
-				
-				InetSocketAddress adjusted_originator = adjustLoopback( originator );
-				
-				boolean	test = adjusted_originator.getAddress().isLoopbackAddress();
-				
-				if ( 	test ||
-						(	tcp_man.isTCPListenerEnabled() &&
-							tcp_man.getTCPListeningPortNumber() == ddb.getLocalContact().getAddress().getPort() &&
-							SystemTime.getCurrentTime() - tcp_man.getLastIncomingNonLocalConnectionTime() <= 24*60*60*1000 )){
-					
-					byte[]	their_hash	= (byte[])request.get( "h" );
-					
-					if ( their_hash != null ){
-						
-						NetStatusProtocolTesterBT bt_tester;
-						
-						synchronized( active_tests ){
-							
-							if ( active_tests.size() > MAX_ACTIVE_TESTS ){
-								
-								log( "Too many active tests" );
-								
-								return( reply );
-								
-							}else{
-								
-								bt_tester = new NetStatusProtocolTesterBT( this, false );
-								
-								bt_tester.start();
-								
-								addToActive( bt_tester );
-							}
-						}
-						
-						Long	l_crypto = (Long)request.get( "c" );
-						
-						boolean	use_crypto = l_crypto!=null&&l_crypto.longValue()==1;
-						
-						bt_tester.testOutbound( adjusted_originator, their_hash, use_crypto );
-						
-						reply.put( "h", bt_tester.getServerHash());
-					}
-				}
-			}
-		}		
-		
-		return( reply );
-	}
-	
-	protected void
-	addToActive(
-		NetStatusProtocolTesterBT		tester )
-	{
-		synchronized( active_tests ){
-
-			active_tests.add( tester );
-			
-			if ( timer_event == null ){
-				
-				timer_event = 
-					SimpleTimer.addPeriodicEvent(
-						"NetStatusProtocolTester:timer",
-						30*1000,
-						new TimerEventPerformer()
-						{
-							public void 
-							perform(
-								TimerEvent event )
-							{
-								long	now = SystemTime.getCurrentTime();
-								
-								List	to_remove = new ArrayList();
-								
-								synchronized( active_tests ){
-
-									for (int i=0;i<active_tests.size();i++){
-										
-										NetStatusProtocolTesterBT tester = (NetStatusProtocolTesterBT)active_tests.get(i);
-										
-										long start = tester.getStartTime( now );
-										
-										if ( now - start > MAX_TEST_TIME ){
-											
-											to_remove.add( tester );
-										}
-									}
-								}
-								
-								for ( int i=0;i<to_remove.size();i++ ){
-									
-									removeFromActive( (NetStatusProtocolTesterBT)to_remove.get(i));
-								}
-							}
-						});
-			}
-		}
-	}
-	
-	protected void
-	removeFromActive(
-		NetStatusProtocolTesterBT		tester )
-	{
-		tester.destroy();
-		
-		synchronized( active_tests ){
-			
-			active_tests.remove( tester );
-			
-			if ( active_tests.size() == 0 ){
-				
-				if ( timer_event != null ){
-					
-					timer_event.cancel();
-					
-					timer_event = null;
-				}
-			}
-		}
-	}
-	
-	public DistributedDatabaseValue
-	read(
-		DistributedDatabaseContact			contact,
-		DistributedDatabaseTransferType		type,
-		DistributedDatabaseKey				ddb_key )
-	
-		throws DistributedDatabaseException
-	{
-		Object	o_key = ddb_key.getKey();
-		
-		try{
-			byte[]	key = (byte[])o_key;
-			
-			HashWrapper	hw = new HashWrapper( key );
-			
-			synchronized( request_history ){
-				
-				if ( request_history.containsKey( hw )){
-										
-					return( null );
-				}
-				
-				request_history.put( hw, "" );
-			}
-			
-			Map	request = BDecoder.decode( (byte[])o_key);
-			
-			log( "Received DDB request from " + contact.getName() + " - " + request );
-
-			Map	result = receiveRequest( contact.getAddress(), request );
-			
-			return( ddb.createValue( BEncoder.encode( result )));
-			
-		}catch( Throwable e ){
-			
-			log( "DDB read failed", e );
-			
-			return( null );
-		}
-	}
-	
-	public void
-	write(
-		DistributedDatabaseContact			contact,
-		DistributedDatabaseTransferType		type,
-		DistributedDatabaseKey				key,
-		DistributedDatabaseValue			value )
-	
-		throws DistributedDatabaseException
-	{
-		throw( new DistributedDatabaseException( "not supported" ));
-	}
-	
-	
-	public void
-	log(
-		String		str )
-	{
-		plugin.log( str );
-	}
-	
-	public void
-	log(
-		String		str,
-		Throwable	e )
-	{
-		plugin.log( str, e );
-	}
-	
-	
-	protected class
-	testXferType
-		implements DistributedDatabaseTransferType
-	{	
-	}
-}
+/*
+ * Created on Feb 15, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.netstatus;
+
+import java.net.InetSocketAddress;
+import java.util.*;
+
+
+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.BDecoder;
+import org.gudy.azureus2.core3.util.BEncoder;
+import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.core3.util.DelayedEvent;
+import org.gudy.azureus2.core3.util.HashWrapper;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+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.plugins.PluginInterface;
+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 com.aelitis.azureus.core.dht.DHT;
+import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
+import com.aelitis.azureus.core.networkmanager.NetworkManager;
+import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager;
+import com.aelitis.azureus.plugins.dht.DHTPlugin;
+import com.aelitis.azureus.plugins.net.netstatus.NetStatusProtocolTesterBT.Session;
+
+
+public class 
+NetStatusProtocolTester
+	implements DistributedDatabaseTransferHandler
+{
+	private static final int REQUEST_HISTORY_MAX	= 64;
+	
+	private static final int MAX_ACTIVE_TESTS	= 3;
+	private static final int MAX_TEST_TIME		= 120*1000;
+	
+	private static final int TEST_TYPE_BT		= 1;
+	
+	private static final int	VERSION_INITIAL	= 1;
+	
+	private static final int	CURRENT_VERSION	= VERSION_INITIAL;
+		
+	private static final int	BT_MAX_SLAVES	= 8;
+	
+	private NetStatusPlugin		plugin;
+	private PluginInterface		plugin_interface;
+
+	private DistributedDatabase	ddb;
+		
+	private DHTPlugin			dht_plugin;
+	
+	
+
+	private testXferType transfer_type = new testXferType();
+
+	private Map	request_history =  
+		new LinkedHashMap(REQUEST_HISTORY_MAX,0.75f,true)
+		{
+			protected boolean 
+			removeEldestEntry(
+		   		Map.Entry eldest) 
+			{
+				return size() > REQUEST_HISTORY_MAX;
+			}
+		};
+		
+	private List active_tests 		= new ArrayList();
+	
+	private TimerEventPeriodic	timer_event	= null;
+		
+	protected
+	NetStatusProtocolTester(
+		NetStatusPlugin		_plugin,
+		PluginInterface		_plugin_interface )
+	{
+		plugin				= _plugin;
+		plugin_interface	= _plugin_interface;
+		
+		try{
+			PluginInterface dht_pi = plugin_interface.getPluginManager().getPluginInterfaceByClass( DHTPlugin.class );
+			
+			if ( dht_pi != null ){
+				
+				dht_plugin = (DHTPlugin)dht_pi.getPlugin();
+			}
+
+			ddb = plugin_interface.getDistributedDatabase();
+			
+			if ( ddb.isAvailable()){
+			
+				ddb.addTransferHandler( transfer_type, this );
+			
+				log( "DDB transfer type registered" );
+				
+			}else{
+				
+				log( "DDB transfer type not registered, DDB unavailable" );
+			}			
+		}catch( Throwable e ){
+			
+			log( "DDB transfer type registration failed", e );
+		}
+	}
+	
+	public NetStatusProtocolTesterBT
+	runTest(
+		final NetStatusProtocolTesterListener		listener )
+	{
+		return( runTest( "", listener ));
+	}
+	
+	public NetStatusProtocolTesterBT
+	runTest(
+		String										test_address,
+		final NetStatusProtocolTesterListener		listener )
+	{
+		final NetStatusProtocolTesterBT bt_tester = new NetStatusProtocolTesterBT( this, true );
+
+		bt_tester.addListener( listener );
+		
+		bt_tester.start();
+		
+		addToActive( bt_tester );
+		
+		try{
+			if ( test_address.length() == 0 ){
+				
+				DHT[]	dhts = dht_plugin.getDHTs();
+				
+				DHT	target_dht = null;
+				
+				int	target_network	= Constants.isCVSVersion()?DHT.NW_CVS:DHT.NW_MAIN;
+				
+				for (int i=0;i<dhts.length;i++){
+					
+					if ( dhts[i].getTransport().getNetwork() == target_network ){
+						
+						target_dht = dhts[i];
+						
+						break;
+					}
+				}
+				
+				if ( target_dht == null ){
+					
+					listener.logError( "Distributed database unavailable" );
+					
+				}else{
+					
+					DHTTransportContact[] contacts = target_dht.getTransport().getReachableContacts();
+					
+					final List f_contacts = new ArrayList(Arrays.asList(contacts));
+					
+					final int[]	ok = new int[]{ 0 };
+					
+					final int	num_threads = Math.min( BT_MAX_SLAVES, contacts.length );
+					
+					listener.log( "Searching " + contacts.length + " contacts for " + num_threads + " test targets", false );
+							
+					final AESemaphore	sem = new AESemaphore( "NetStatusProbe" );
+					
+					for (int i=0;i<num_threads;i++){
+						
+						new AEThread2( "NetStatusProbe", true )
+						{
+							public void
+							run()
+							{
+								try{
+									while( !bt_tester.isDestroyed()){
+										
+										DHTTransportContact	contact = null;
+										
+										synchronized( ok ){
+											
+											if ( ok[0] < num_threads && f_contacts.size() > 0 ){
+												
+												contact = (DHTTransportContact)f_contacts.remove(0);
+											}
+										}
+										
+										if ( contact == null ){
+											
+											break;
+										}
+										
+										try{
+											DistributedDatabaseContact ddb_contact = ddb.importContact( contact.getAddress());
+											
+											if ( tryTest( bt_tester, ddb_contact )){
+												
+												synchronized( ok ){
+													
+													ok[0]++;
+												}
+											}
+										}catch( Throwable e ){
+											
+											listener.logError( "Contact import for " + contact.getName() + " failed", e );
+										}
+									}
+								}finally{
+									
+									sem.release();
+								}
+							}
+						}.start();
+					}
+					
+					for (int i=0;i<num_threads;i++){
+						
+						sem.reserve();
+					}
+					
+					listener.log( "Searching complete, " + ok[0] + " targets found", false );
+				}
+			}else{
+				
+				String[]	bits = test_address.split( ":" );
+				
+				if ( bits.length != 2 ){
+					
+					log( "Invalid address - use <host>:<port> " );
+					
+					return( bt_tester );
+				}
+				
+				InetSocketAddress address = new InetSocketAddress( bits[0].trim(), Integer.parseInt( bits[1].trim()));
+				 
+				DistributedDatabaseContact contact = ddb.importContact( address );
+
+				tryTest( bt_tester, contact );
+			}
+		}catch( Throwable e ){
+			
+			listener.logError( "Test failed", e );
+			
+		}finally{
+			
+			bt_tester.addListener(
+				new NetStatusProtocolTesterListener()
+				{
+					public void 
+					sessionAdded(
+						Session session) 
+					{
+					}
+					
+					public void
+					complete(
+						NetStatusProtocolTesterBT tester )
+					{
+						removeFromActive( tester );
+					}
+					
+					public void
+					log(
+						String		str,
+						boolean		detailed )
+					{
+					}
+					
+					public void
+					logError(
+						String		str )
+					{
+					}
+					
+					public void
+					logError(
+						String		str,
+						Throwable	e )
+					{
+					}
+				});
+			
+			bt_tester.setOutboundConnectionsComplete();
+			
+			new DelayedEvent(
+				"NetStatus:killer",
+				10*1000,
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						listener.log( "Destroying tester", false );
+						
+						bt_tester.destroy();
+					}
+				});
+		}
+		
+		return( bt_tester );
+	}
+	
+	protected boolean
+	tryTest(
+		NetStatusProtocolTesterBT		bt_tester,
+		DistributedDatabaseContact		contact )
+	{
+		boolean	use_crypto = NetworkManager.getCryptoRequired( NetworkManager.CRYPTO_OVERRIDE_NONE );
+
+		log( "Trying test to " + contact.getName());
+		
+		Map	request = new HashMap();
+		
+		request.put( "v", new Long( CURRENT_VERSION ));
+				
+		request.put( "t", new Long( TEST_TYPE_BT ));
+			
+		request.put( "h", bt_tester.getServerHash());
+			
+		request.put( "c", new Long( use_crypto?1:0 ));
+		
+		Map	reply = sendRequest( contact, request );
+				
+		byte[]	server_hash = reply==null?null:(byte[])reply.get( "h" );
+			
+		if ( server_hash != null ){
+				
+			log( "    " + contact.getName() + " accepted test" );
+			
+			bt_tester.testOutbound( adjustLoopback( contact.getAddress()), server_hash, use_crypto );
+			
+			return( true );
+			
+		}else{
+			
+			log( "    " + contact.getName() + " declined test" );
+
+			return( false );
+		}
+	}
+	
+	protected InetSocketAddress
+	adjustLoopback(
+		InetSocketAddress	address )
+	{
+		InetSocketAddress local = dht_plugin.getLocalAddress().getAddress();
+		
+		if ( local.getAddress().getHostAddress().equals( address.getAddress().getHostAddress())){
+			
+			return( new InetSocketAddress( "127.0.0.1", address.getPort()));
+			
+		}else{
+			
+			return( address );
+		}
+	}
+	
+	protected Map
+	sendRequest(
+		DistributedDatabaseContact	contact,
+		Map							request )
+	{
+		try{
+			log( "Sending DDB request to " + contact.getName() + " - " + request );
+			
+			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 );
+			
+			if ( value == null ){
+				
+				return( null );
+			}
+			
+			Map reply = BDecoder.decode((byte[])value.getValue( byte[].class ));
+			
+			log( "    received reply - " + reply );
+			
+			return( reply );
+			
+		}catch( Throwable e ){
+			
+			log( "sendRequest failed", e );
+			
+			return( null );
+		}
+	}
+	
+	protected Map
+	receiveRequest(
+		InetSocketAddress	originator,
+		Map					request )
+	{
+		Map	reply = new HashMap();
+		
+		Long	test_type	= (Long)request.get( "t" );
+		
+		reply.put( "v", new Long( CURRENT_VERSION ));
+		
+		if ( test_type != null ){
+			
+			if ( test_type.intValue() == TEST_TYPE_BT ){
+				
+				TCPNetworkManager tcp_man = TCPNetworkManager.getSingleton();
+				
+				InetSocketAddress adjusted_originator = adjustLoopback( originator );
+				
+				boolean	test = adjusted_originator.getAddress().isLoopbackAddress();
+				
+				if ( 	test ||
+						(	tcp_man.isTCPListenerEnabled() &&
+							tcp_man.getTCPListeningPortNumber() == ddb.getLocalContact().getAddress().getPort() &&
+							SystemTime.getCurrentTime() - tcp_man.getLastIncomingNonLocalConnectionTime() <= 24*60*60*1000 )){
+					
+					byte[]	their_hash	= (byte[])request.get( "h" );
+					
+					if ( their_hash != null ){
+						
+						NetStatusProtocolTesterBT bt_tester;
+						
+						synchronized( active_tests ){
+							
+							if ( active_tests.size() > MAX_ACTIVE_TESTS ){
+								
+								log( "Too many active tests" );
+								
+								return( reply );
+								
+							}else{
+								
+								bt_tester = new NetStatusProtocolTesterBT( this, false );
+								
+								bt_tester.start();
+								
+								addToActive( bt_tester );
+							}
+						}
+						
+						Long	l_crypto = (Long)request.get( "c" );
+						
+						boolean	use_crypto = l_crypto!=null&&l_crypto.longValue()==1;
+						
+						bt_tester.testOutbound( adjusted_originator, their_hash, use_crypto );
+						
+						reply.put( "h", bt_tester.getServerHash());
+					}
+				}
+			}
+		}		
+		
+		return( reply );
+	}
+	
+	protected void
+	addToActive(
+		NetStatusProtocolTesterBT		tester )
+	{
+		synchronized( active_tests ){
+
+			active_tests.add( tester );
+			
+			if ( timer_event == null ){
+				
+				timer_event = 
+					SimpleTimer.addPeriodicEvent(
+						"NetStatusProtocolTester:timer",
+						30*1000,
+						new TimerEventPerformer()
+						{
+							public void 
+							perform(
+								TimerEvent event )
+							{
+								long	now = SystemTime.getCurrentTime();
+								
+								List	to_remove = new ArrayList();
+								
+								synchronized( active_tests ){
+
+									for (int i=0;i<active_tests.size();i++){
+										
+										NetStatusProtocolTesterBT tester = (NetStatusProtocolTesterBT)active_tests.get(i);
+										
+										long start = tester.getStartTime( now );
+										
+										if ( now - start > MAX_TEST_TIME ){
+											
+											to_remove.add( tester );
+										}
+									}
+								}
+								
+								for ( int i=0;i<to_remove.size();i++ ){
+									
+									removeFromActive( (NetStatusProtocolTesterBT)to_remove.get(i));
+								}
+							}
+						});
+			}
+		}
+	}
+	
+	protected void
+	removeFromActive(
+		NetStatusProtocolTesterBT		tester )
+	{
+		tester.destroy();
+		
+		synchronized( active_tests ){
+			
+			active_tests.remove( tester );
+			
+			if ( active_tests.size() == 0 ){
+				
+				if ( timer_event != null ){
+					
+					timer_event.cancel();
+					
+					timer_event = null;
+				}
+			}
+		}
+	}
+	
+	public DistributedDatabaseValue
+	read(
+		DistributedDatabaseContact			contact,
+		DistributedDatabaseTransferType		type,
+		DistributedDatabaseKey				ddb_key )
+	
+		throws DistributedDatabaseException
+	{
+		Object	o_key = ddb_key.getKey();
+		
+		try{
+			byte[]	key = (byte[])o_key;
+			
+			HashWrapper	hw = new HashWrapper( key );
+			
+			synchronized( request_history ){
+				
+				if ( request_history.containsKey( hw )){
+										
+					return( null );
+				}
+				
+				request_history.put( hw, "" );
+			}
+			
+			Map	request = BDecoder.decode( (byte[])o_key);
+			
+			log( "Received DDB request from " + contact.getName() + " - " + request );
+
+			Map	result = receiveRequest( contact.getAddress(), request );
+			
+			return( ddb.createValue( BEncoder.encode( result )));
+			
+		}catch( Throwable e ){
+			
+			log( "DDB read failed", e );
+			
+			return( null );
+		}
+	}
+	
+	public DistributedDatabaseValue
+	write(
+		DistributedDatabaseContact			contact,
+		DistributedDatabaseTransferType		type,
+		DistributedDatabaseKey				key,
+		DistributedDatabaseValue			value )
+	
+		throws DistributedDatabaseException
+	{
+		throw( new DistributedDatabaseException( "not supported" ));
+	}
+	
+	
+	public void
+	log(
+		String		str )
+	{
+		plugin.log( str );
+	}
+	
+	public void
+	log(
+		String		str,
+		Throwable	e )
+	{
+		plugin.log( str, e );
+	}
+	
+	
+	protected class
+	testXferType
+		implements DistributedDatabaseTransferType
+	{	
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTesterBT.java b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTesterBT.java
index 7cbec42..b1bdd8e 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTesterBT.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTesterBT.java
@@ -1,972 +1,993 @@
-/*
- * Created on Feb 15, 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.plugins.net.netstatus;
-
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.AESemaphore;
-import org.gudy.azureus2.core3.util.ByteFormatter;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.DelayedEvent;
-import org.gudy.azureus2.core3.util.DirectByteBuffer;
-import org.gudy.azureus2.core3.util.HashWrapper;
-import org.gudy.azureus2.core3.util.RandomUtils;
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.core.networkmanager.ConnectionEndpoint;
-import com.aelitis.azureus.core.networkmanager.IncomingMessageQueue;
-import com.aelitis.azureus.core.networkmanager.NetworkConnection;
-import com.aelitis.azureus.core.networkmanager.NetworkManager;
-import com.aelitis.azureus.core.networkmanager.OutgoingMessageQueue;
-import com.aelitis.azureus.core.networkmanager.ProtocolEndpoint;
-import com.aelitis.azureus.core.networkmanager.ProtocolEndpointFactory;
-import com.aelitis.azureus.core.networkmanager.impl.tcp.ProtocolEndpointTCP;
-import com.aelitis.azureus.core.peermanager.PeerManager;
-import com.aelitis.azureus.core.peermanager.PeerManagerRegistration;
-import com.aelitis.azureus.core.peermanager.PeerManagerRegistrationAdapter;
-import com.aelitis.azureus.core.peermanager.messaging.Message;
-import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTBitfield;
-import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTHandshake;
-import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTHave;
-import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessage;
-import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessageDecoder;
-import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessageEncoder;
-import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessageFactory;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-public class 
-NetStatusProtocolTesterBT 
-{
-	private static Random	random = RandomUtils.SECURE_RANDOM;
-	
-	private NetStatusProtocolTester			tester;
-	private boolean							test_initiator;
-	
-	private CopyOnWriteList					listeners	= new CopyOnWriteList();
-	
-	
-	private byte[]		my_hash;
-	private byte[]		peer_id;
-	
-	private PeerManagerRegistration		pm_reg;
-
-	private long		start_time	= SystemTime.getCurrentTime();
-	
-	private List		sessions	= new ArrayList();
-	private int			session_id_next;
-	
-	private int			outbound_attempts	= 0;
-	private int			outbound_connects	= 0;
-	private int			inbound_connects	= 0;
-
-	private boolean		outbound_connections_complete;
-	private AESemaphore	completion_sem = new AESemaphore( "Completion" );
-	
-	
-	private boolean		destroyed;
-	
-	protected
-	NetStatusProtocolTesterBT(
-		NetStatusProtocolTester			_tester,
-		boolean							_test_initiator )
-	{
-		tester			= _tester;
-		test_initiator	= _test_initiator;
-	}
-	
-	protected void
-	start()
-	{
-		my_hash = new byte[20];
-		
-		random.nextBytes( my_hash );
-		
-		peer_id = new byte[20];
-		
-		random.nextBytes( peer_id );
-		
-
-		pm_reg = PeerManager.getSingleton().registerLegacyManager(
-			new HashWrapper( my_hash ),
-			new PeerManagerRegistrationAdapter()
-			{
-				public byte[][]
-	          	getSecrets()
-				{
-					return( new byte[][]{ my_hash });
-				}
-	          	
-	          	public boolean
-	          	manualRoute(
-	          		NetworkConnection		connection )
-	          	{
-	          		log( "Got incoming connection from " + connection.getEndpoint().getNotionalAddress());
-	          		
-	          		new Session( connection, null );
-	          			          		
-	          		return( true );
-	          	}
-	          	
-	          	public boolean
-	          	isPeerSourceEnabled(
-	          		String					peer_source )
-	          	{
-	          		return( true );
-	          	}
-	          	
-	          	public boolean
-	          	activateRequest(
-	          		InetSocketAddress		remote_address )
-	          	{
-	          		return( true );
-	          	}
-	          	
-	          	public void
-	          	deactivateRequest(
-	          		InetSocketAddress		remote_address )
-	          	{
-	          	}
-	          	
-	          	public String
-	          	getDescription()
-	          	{
-	          		return( "NetStatusPlugin - router" );
-	          	}
-
-			});
-		
-		log( "Incoming routing established for " + ByteFormatter.encodeString( my_hash ));
-	}
-	
-	protected byte[]
-	getServerHash()
-	{
-		return( my_hash );
-	}
-	
-	protected long
-	getStartTime(
-		long	now )
-	{
-		if ( now < start_time ){
-			
-			start_time = now;
-		}
-		
-		return( start_time );
-	}
-	
-	protected void
-	testOutbound(
-		InetSocketAddress		address,
-		final byte[]			their_hash,
-		boolean					use_crypto )
-	{
-			// regardless of the caller's desires, override with crypto if we're using it
-		
-		if ( NetworkManager.getCryptoRequired( NetworkManager.CRYPTO_OVERRIDE_NONE )){
-			
-			use_crypto = true;
-		}
-		
-		log( "Making outbound connection to " + address );
-		
-		synchronized( this ){
-		
-			outbound_attempts++;
-		}
-				
-		boolean	allow_fallback	= false;
-		
-		ProtocolEndpoint	pe = ProtocolEndpointFactory.createEndpoint( ProtocolEndpoint.PROTOCOL_TCP, address );
-		
-		ConnectionEndpoint connection_endpoint	= new ConnectionEndpoint( address );
-
-		connection_endpoint.addProtocol( pe );
-
-		final NetworkConnection connection = 
-			NetworkManager.getSingleton().createConnection(
-					connection_endpoint, 
-					new BTMessageEncoder(), 
-					new BTMessageDecoder(), 
-					use_crypto, 
-					allow_fallback, 
-					new byte[][]{ their_hash });
-	
-		new Session( connection, their_hash );
-	}
-		
-	public void
-	destroy()
-	{
-		List	to_close	= new ArrayList();
-		
-		synchronized( sessions ){
-			
-			if ( destroyed ){
-				
-				return;
-			}
-			
-			destroyed = true;
-			
-			to_close.addAll( sessions );
-			
-			sessions.clear();
-		}
-		
-		for (int i=0;i<to_close.size();i++){
-			
-			Session session = (Session)to_close.get(i);
-			
-			session.close();
-		}
-		
-		pm_reg.unregister();
-		
-		checkCompletion();
-		
-		log( "Incoming routing destroyed for " + ByteFormatter.encodeString( my_hash ));
-	}
-	
-	protected boolean
-	isDestroyed()
-	{
-		return( destroyed );
-	}
-	
-	public void
-	setOutboundConnectionsComplete()
-	{
-		synchronized( sessions ){
-
-			outbound_connections_complete	= true;
-		}
-		
-		checkCompletion();
-	}
-	
-	protected void
-	checkCompletion()
-	{
-		boolean	inform = false;
-		
-		synchronized( sessions ){
-	
-			if ( completion_sem.isReleasedForever()){
-				
-				return;
-			}
-			
-			if ( 	destroyed || 
-					( outbound_connections_complete && sessions.size() == 0 )){
-				
-				inform = true;
-				
-				completion_sem.releaseForever();
-			}
-		}
-		
-		if ( inform ){
-			
-			Iterator it = listeners.iterator();
-				
-			while( it.hasNext()){
-				
-				try{
-					((NetStatusProtocolTesterListener)it.next()).complete( this );
-					
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-		}
-	}
-	
-	public boolean
-	waitForCompletion(
-		long		max_millis )
-	{
-		if ( max_millis == 0 ){
-			
-			completion_sem.reserve();
-			
-			return( true );
-			
-		}else{
-		
-			return( completion_sem.reserve( max_millis ));
-		}
-	}
-	
-	public void
-	addListener(
-		NetStatusProtocolTesterListener		l )
-	{
-		listeners.add( l );
-	}
-	
-	public void
-	removeListener(
-		NetStatusProtocolTesterListener		l )
-	{
-		listeners.remove( l );
-	}
-	
-	public int
-	getOutboundConnects()
-	{
-		return( outbound_connects );
-	}
-	
-	public int
-	getInboundConnects()
-	{
-		return( inbound_connects );
-	}
-	
-	public String
-	getStatus()
-	{
-		return( "sessions=" + sessions.size() + 
-					", out_attempts=" + outbound_attempts + 
-					", out_connect=" + outbound_connects + 
-					", in_connect=" + inbound_connects );
-	}
-	
-	protected void
-	log(
-		String	str )
-	{
-		Iterator it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((NetStatusProtocolTesterListener)it.next()).log( str );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-		
-		tester.log( str );
-	}
-	
-	protected void
-	logError(
-		String	str )
-	{
-		Iterator it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((NetStatusProtocolTesterListener)it.next()).logError( str );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-		
-		tester.log( str );
-	}
-	
-	protected void
-	logError(
-		String		str,
-		Throwable	e )
-	{
-		Iterator it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((NetStatusProtocolTesterListener)it.next()).logError( str, e );
-				
-			}catch( Throwable f ){
-				
-				Debug.printStackTrace(f);
-			}
-		}
-		
-		tester.log( str, e );
-	}
-	
-	public class
-	Session
-	{
-		private NetworkConnection		connection;
-		private int						session_id;
-		private boolean					initiator;
-		private byte[]					info_hash;
-		
-		private boolean 	handshake_sent;
-		private boolean		handshake_received;
-		
-		private boolean 	bitfield_sent;
-		private boolean		bitfield_received;
-		
-		private int			num_pieces;
-		private boolean		is_seed;
-		private Set			missing_pieces = new HashSet();
-		
-		private boolean		connected;
-		private boolean		closing;
-		private boolean		closed;
-		
-		protected
-		Session(
-			NetworkConnection		_connection,
-			byte[]					_info_hash )
-		{
-			connection	= _connection;
-			info_hash	= _info_hash;
-
-			initiator 	= info_hash != null;
-			
-			synchronized( sessions ){
-			
-				session_id_next++;
-				
-				session_id = session_id_next;
-				
-				if ( destroyed ){
-					
-					log( "Already destroyed" );
-					
-					close();
-					
-					return;
-					
-				}else{
-					
-						// if we're a responder then we limit connections as we should only
-						// receive 1 (be generous, give them 3 in case we decide to reconnect)
-					
-					if ( !( test_initiator || initiator )){
-						
-						int responder_sessions = 0;
-						
-						for (int i=0;i<sessions.size();i++){
-							
-							Session	existing_session = (Session)sessions.get(i);
-							
-							if ( !existing_session.isInitiator()){
-								
-								responder_sessions++;
-							}
-						}
-						
-						if ( responder_sessions >= 2 ){
-							
-							log( "Too many responder sessions" );
-							
-							close();
-							
-							return;
-						}
-					}
-					
-					sessions.add( this );
-					
-					is_seed = initiator && sessions.size()%2 == 0;
-				}
-			}
-			
-			Iterator it = listeners.iterator();
-			
-			while( it.hasNext()){
-				
-				try{
-					((NetStatusProtocolTesterListener)it.next()).sessionAdded( this );
-					
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-			
-			connection.connect( 
-					ProtocolEndpoint.CONNECT_PRIORITY_MEDIUM,
-					new NetworkConnection.ConnectionListener() 
-					{
-						final String	type = initiator?"Outbound":"Inbound";
-						
-						public int 
-						connectStarted(
-							int default_connect_timeout )
-						{	
-							log( type + " connect start" );
-
-							return( default_connect_timeout );
-						}
-						
-						public final void 
-						connectSuccess( 
-							ByteBuffer remaining_initial_data ) 
-						{
-							log( type + " connect success" );
-							
-							connected	= true;
-							
-							synchronized( NetStatusProtocolTesterBT.this ){
-								
-								if ( initiator ){
-									
-									outbound_connects++;
-									
-								}else{
-									
-									inbound_connects++;
-								}
-							}
-							
-							connected();
-						}
-
-						public final void 
-						connectFailure( 
-							Throwable e ) 
-						{
-							if ( !closing ){
-							
-								logError( type + " connection fail", e );
-							}
-							
-							close();
-						}
-
-						public final void 
-						exceptionThrown( 
-							Throwable e ) 
-						{
-							if ( !closing ){
-
-								logError( type + " connection fail", e );
-							}
-							
-							close();					
-						}
-	    			
-						public String
-						getDescription()
-						{
-							return( "NetStatusPlugin - " + type );
-						}
-					});
-		}
-		
-		public boolean
-		isInitiator()
-		{
-			return( initiator );
-		}
-		
-		public boolean
-		isConnected()
-		{
-			return( connected );
-		}
-		
-		public boolean
-		isSeed()
-		{
-			return( is_seed );
-		}
-		
-		public boolean
-		isOK()
-		{
-			return( bitfield_received );
-		}
-		
-		protected void
-		connected()
-		{
-			connection.getIncomingMessageQueue().registerQueueListener(
-				new IncomingMessageQueue.MessageQueueListener() 
-				{
-					
-					public boolean 
-					messageReceived(
-						Message message ) 
-					{               
-						try{
-							String	message_id = message.getID();
-	
-							log( "Incoming message received: " + message.getID());
-							
-					        if ( message_id.equals( BTMessage.ID_BT_HANDSHAKE )){
-						
-					        	handshake_received = true;
-					        	
-				        		BTHandshake handshake = (BTHandshake)message;
-					        		
-				        		info_hash = handshake.getDataHash();
-				        		
-				        		num_pieces = 500 + (info_hash[0]&0xff);
-				        		
-				        			// we use the piece at 'n' + 1 to indicate a close request by sending a HAVE for it
-				        			// this helps us tidily close things
-				        		
-				        		if ( num_pieces%8 == 0 ){
-				        			
-				        			num_pieces--;
-				        		}
-				        		
-				        		if ( !is_seed ){
-				        			
-				        			int missing = random.nextInt( num_pieces/2 ) + 5;
-				        			
-				        			for (int i=0;i<missing;i++){
-				        				
-				        				missing_pieces.add( new Integer( random.nextInt( num_pieces )));
-				        			}
-				        		}
-				        		
-				        		sendHandshake();
-					        	
-					        	sendBitfield();
-					        	
-					        	connection.getIncomingMessageQueue().getDecoder().resumeDecoding();
-					        	
-					        }else if ( message_id.equals( BTMessage.ID_BT_BITFIELD )){
-									
-					        	bitfield_received = true;
-					        	
-					        	BTBitfield bitfield = (BTBitfield)message;
-					  
-					        	ByteBuffer bb = bitfield.getBitfield().getBuffer((byte)0);
-					        	
-					        	byte[]	contents = new byte[bb.remaining()];
-					        	
-					        	bb.get( contents );
-					        						        	
-					        }else if ( message_id.equals( BTMessage.ID_BT_HAVE  )){
-					        	
-					        	BTHave have = (BTHave)message;
-					        	
-					        	if ( have.getPieceNumber() == num_pieces ){
-					        		
-					    			synchronized( sessions ){
-
-					    				closing = true;
-					    			}
-					    			
-					    			close();
-					        	}
-					        }
-					        
-					        return( true );
-					        
-						}finally{
-							
-							message.destroy();
-						}
-					}
-	  
-
-					public final void 
-					protocolBytesReceived(
-						int byte_count ) 
-					
-					{
-					}
-
-					public final void 
-					dataBytesReceived( 
-						int byte_count ) 
-					{
-					}
-					
-					public boolean 
-					isPriority() 
-					{
-						return true;
-					}
-				});
-
-			connection.getOutgoingMessageQueue().registerQueueListener( 
-				new OutgoingMessageQueue.MessageQueueListener() 
-				{
-					public final boolean 
-					messageAdded( 
-						Message message )
-					{
-						return( true );
-					}
-		
-					public final void 
-					messageQueued( 
-						Message message )
-					{
-					}
-		
-					public final void 
-					messageRemoved( 
-						Message message )
-					{
-						
-					}
-		
-					public final void 
-					messageSent( 
-						Message message ) 
-					{
-						log( "Outgoing message sent: " + message.getID());
-					}
-		
-					public final void 
-					protocolBytesSent( 
-						int byte_count ) 
-					{
-					}
-		
-					public final void 
-					dataBytesSent( 
-						int byte_count ) 
-					{
-					}
-					
-					public void 
-					flush()
-					{
-					}
-			});
-
-			connection.startMessageProcessing();
-			
-			if ( initiator ){
-				
-				sendHandshake();
-			}
-		}
-		
-		protected void
-		sendHandshake()
-		{
-			if ( !handshake_sent ){
-				
-				handshake_sent = true;
-				
-				connection.getOutgoingMessageQueue().addMessage(
-					new BTHandshake( info_hash, peer_id, false, BTMessageFactory.MESSAGE_VERSION_INITIAL ),
-					false );
-			}
-		}
-		
-		protected void
-		sendHave(
-			int	piece_number )
-		{
-			BTHave message = new BTHave( piece_number, BTMessageFactory.MESSAGE_VERSION_INITIAL );
-			
-			OutgoingMessageQueue out_q = connection.getOutgoingMessageQueue();
-			
-			out_q.addMessage( message, false );
-			
-			out_q.flush();
-		}
-		
-		protected void
-		sendBitfield()
-		{
-			if ( !bitfield_sent ){
-			
-				bitfield_sent = true;
-				
-				byte[]	bits = new byte[( num_pieces + 7 ) /8];
-				
-				int	pos = 0;
-				
-				int i		= 0;
-				int bToSend	= 0;
-				
-				for (; i <num_pieces; i++ ){
-					
-					if ((i %8) ==0){
-						
-						bToSend =0;
-					}
-					
-					bToSend = bToSend << 1;
-					
-					boolean	has_piece = !missing_pieces.contains( new Integer(i));
-					
-					if ( has_piece ){
-						
-						bToSend += 1;
-					}
-					
-					if ((i %8) ==7){
-					
-						bits[pos++] = (byte)bToSend;
-					}
-				}
-				
-				if ((i %8) !=0){
-				
-					bToSend = bToSend << (8 - (i % 8));
-					
-					bits[pos++] = (byte)bToSend;
-				}
-								
-				DirectByteBuffer buffer = new DirectByteBuffer( ByteBuffer.wrap( bits ));
-
-				connection.getOutgoingMessageQueue().addMessage(
-					new BTBitfield( buffer, BTMessageFactory.MESSAGE_VERSION_INITIAL ),
-					false );
-			}
-		}
-		
-		protected void
-		close()
-		{
-			synchronized( sessions ){
-
-				sessions.remove( this );
-				
-				if ( !closing ){
-					
-					closing	= true;
-
-				}else{
-					
-					closed = true;
-				}
-			}
-
-			if ( closed ){
-				
-				log( "Closing connection" );
-				
-				connection.close( null );
-				
-			}else{
-				
-				sendHave( num_pieces );
-				
-				new DelayedEvent( 
-					"NetStatus:delayClose",
-					5000,
-					new AERunnable()
-					{
-						public void
-						runSupport()
-						{
-							if ( !closed ){
-								
-								close();
-							}
-						}
-					});
-			}
-			
-			checkCompletion();
-		}
-		
-		public String
-		getProtocolString()
-		{
-			String	str = "";
-			
-			if ( connected ){
-				
-				str = "connected";
-				
-				str += addSent( "hand", handshake_sent );
-				str += addRecv( "hand", handshake_received );
-				str += addSent( "bitf", bitfield_sent );
-				str += addRecv( "bitf", bitfield_received );
-
-			}else{
-				
-				str = "not connected";
-			}
-			
-			return( str );
-		}
-		
-		protected String
-		addSent(
-			String	str,
-			boolean	ok ) 
-		{
-			if ( ok ){
-				
-				return( ", " + str + " sent" );
-			}else{
-				
-				return( ", " + str + " !sent" );
-			}
-		}
-		
-		protected String
-		addRecv(
-			String	str,
-			boolean	ok ) 
-		{
-			if ( ok ){
-				
-				return( ", " + str + " recv" );
-			}else{
-				
-				return( ", " + str + " !recv" );
-			}
-		}
-		
-		protected String
-		getLogPrefix()
-		{
-			return( "(" + (initiator?"L":"R") + (is_seed?"S":"L") + " " + session_id + ") " );
-		}
-		
-		protected void
-		log(
-			String	str )
-		{
-			NetStatusProtocolTesterBT.this.log( getLogPrefix() + str );
-		}
-		
-		protected void
-		logError(
-			String	str )
-		{
-			NetStatusProtocolTesterBT.this.logError( getLogPrefix() + str );
-		}
-		
-		protected void
-		logError(
-			String		str,
-			Throwable	e )
-		{
-			NetStatusProtocolTesterBT.this.logError( getLogPrefix() + str, e );
-		}
-	}
-}
+/*
+ * Created on Feb 15, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.netstatus;
+
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AESemaphore;
+import org.gudy.azureus2.core3.util.ByteFormatter;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.DelayedEvent;
+import org.gudy.azureus2.core3.util.DirectByteBuffer;
+import org.gudy.azureus2.core3.util.HashWrapper;
+import org.gudy.azureus2.core3.util.RandomUtils;
+import org.gudy.azureus2.core3.util.SystemTime;
+
+import com.aelitis.azureus.core.networkmanager.ConnectionEndpoint;
+import com.aelitis.azureus.core.networkmanager.IncomingMessageQueue;
+import com.aelitis.azureus.core.networkmanager.NetworkConnection;
+import com.aelitis.azureus.core.networkmanager.NetworkManager;
+import com.aelitis.azureus.core.networkmanager.OutgoingMessageQueue;
+import com.aelitis.azureus.core.networkmanager.ProtocolEndpoint;
+import com.aelitis.azureus.core.networkmanager.ProtocolEndpointFactory;
+import com.aelitis.azureus.core.peermanager.PeerManager;
+import com.aelitis.azureus.core.peermanager.PeerManagerRegistration;
+import com.aelitis.azureus.core.peermanager.PeerManagerRegistrationAdapter;
+import com.aelitis.azureus.core.peermanager.messaging.Message;
+import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTBitfield;
+import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTHandshake;
+import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTHave;
+import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessage;
+import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessageDecoder;
+import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessageEncoder;
+import com.aelitis.azureus.core.peermanager.messaging.bittorrent.BTMessageFactory;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
+public class 
+NetStatusProtocolTesterBT 
+{
+	private static Random	random = RandomUtils.SECURE_RANDOM;
+	
+	private NetStatusProtocolTester			tester;
+	private boolean							test_initiator;
+	
+	private CopyOnWriteList					listeners	= new CopyOnWriteList();
+	
+	
+	private byte[]		my_hash;
+	private byte[]		peer_id;
+	
+	private PeerManagerRegistration		pm_reg;
+
+	private long		start_time	= SystemTime.getCurrentTime();
+	
+	private List		sessions	= new ArrayList();
+	private int			session_id_next;
+	
+	private int			outbound_attempts	= 0;
+	private int			outbound_connects	= 0;
+	private int			inbound_connects	= 0;
+
+	private boolean		outbound_connections_complete;
+	private AESemaphore	completion_sem = new AESemaphore( "Completion" );
+	
+	
+	private boolean		destroyed;
+	
+	protected
+	NetStatusProtocolTesterBT(
+		NetStatusProtocolTester			_tester,
+		boolean							_test_initiator )
+	{
+		tester			= _tester;
+		test_initiator	= _test_initiator;
+	}
+	
+	protected void
+	start()
+	{
+		my_hash = new byte[20];
+		
+		random.nextBytes( my_hash );
+		
+		peer_id = new byte[20];
+		
+		random.nextBytes( peer_id );
+		
+
+		pm_reg = PeerManager.getSingleton().registerLegacyManager(
+			new HashWrapper( my_hash ),
+			new PeerManagerRegistrationAdapter()
+			{
+				public byte[][]
+	          	getSecrets()
+				{
+					return( new byte[][]{ my_hash });
+				}
+	          	
+	          	public boolean
+	          	manualRoute(
+	          		NetworkConnection		connection )
+	          	{
+	          		log( "Got incoming connection from " + connection.getEndpoint().getNotionalAddress());
+	          		
+	          		new Session( connection, null );
+	          			          		
+	          		return( true );
+	          	}
+	          	
+	          	public boolean
+	          	isPeerSourceEnabled(
+	          		String					peer_source )
+	          	{
+	          		return( true );
+	          	}
+	          	
+	          	public boolean
+	          	activateRequest(
+	          		InetSocketAddress		remote_address )
+	          	{
+	          		return( true );
+	          	}
+	          	
+	          	public void
+	          	deactivateRequest(
+	          		InetSocketAddress		remote_address )
+	          	{
+	          	}
+	          	
+	          	public String
+	          	getDescription()
+	          	{
+	          		return( "NetStatusPlugin - router" );
+	          	}
+
+			});
+		
+		log( "Incoming routing established for " + ByteFormatter.encodeString( my_hash ));
+	}
+	
+	protected byte[]
+	getServerHash()
+	{
+		return( my_hash );
+	}
+	
+	protected long
+	getStartTime(
+		long	now )
+	{
+		if ( now < start_time ){
+			
+			start_time = now;
+		}
+		
+		return( start_time );
+	}
+	
+	protected void
+	testOutbound(
+		InetSocketAddress		address,
+		final byte[]			their_hash,
+		boolean					use_crypto )
+	{
+			// regardless of the caller's desires, override with crypto if we're using it
+		
+		if ( NetworkManager.getCryptoRequired( NetworkManager.CRYPTO_OVERRIDE_NONE )){
+			
+			use_crypto = true;
+		}
+		
+		log( "Making outbound connection to " + address );
+		
+		synchronized( this ){
+		
+			outbound_attempts++;
+		}
+				
+		boolean	allow_fallback	= false;
+		
+		ProtocolEndpoint	pe = ProtocolEndpointFactory.createEndpoint( ProtocolEndpoint.PROTOCOL_TCP, address );
+		
+		ConnectionEndpoint connection_endpoint	= new ConnectionEndpoint( address );
+
+		connection_endpoint.addProtocol( pe );
+
+		final NetworkConnection connection = 
+			NetworkManager.getSingleton().createConnection(
+					connection_endpoint, 
+					new BTMessageEncoder(), 
+					new BTMessageDecoder(), 
+					use_crypto, 
+					allow_fallback, 
+					new byte[][]{ their_hash });
+	
+		new Session( connection, their_hash );
+	}
+		
+	public void
+	destroy()
+	{
+		List	to_close	= new ArrayList();
+		
+		synchronized( sessions ){
+			
+			if ( destroyed ){
+				
+				return;
+			}
+			
+			destroyed = true;
+			
+			to_close.addAll( sessions );
+			
+			sessions.clear();
+		}
+		
+		for (int i=0;i<to_close.size();i++){
+			
+			Session session = (Session)to_close.get(i);
+			
+			session.close();
+		}
+		
+		pm_reg.unregister();
+		
+		checkCompletion();
+		
+		log( "Incoming routing destroyed for " + ByteFormatter.encodeString( my_hash ));
+	}
+	
+	protected boolean
+	isDestroyed()
+	{
+		return( destroyed );
+	}
+	
+	public void
+	setOutboundConnectionsComplete()
+	{
+		synchronized( sessions ){
+
+			outbound_connections_complete	= true;
+		}
+		
+		checkCompletion();
+	}
+	
+	protected void
+	checkCompletion()
+	{
+		boolean	inform = false;
+		
+		synchronized( sessions ){
+	
+			if ( completion_sem.isReleasedForever()){
+				
+				return;
+			}
+			
+			if ( 	destroyed || 
+					( outbound_connections_complete && sessions.size() == 0 )){
+				
+				inform = true;
+				
+				completion_sem.releaseForever();
+			}
+		}
+		
+		if ( inform ){
+			
+			Iterator it = listeners.iterator();
+				
+			while( it.hasNext()){
+				
+				try{
+					((NetStatusProtocolTesterListener)it.next()).complete( this );
+					
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+		}
+	}
+	
+	public boolean
+	waitForCompletion(
+		long		max_millis )
+	{
+		if ( max_millis == 0 ){
+			
+			completion_sem.reserve();
+			
+			return( true );
+			
+		}else{
+		
+			return( completion_sem.reserve( max_millis ));
+		}
+	}
+	
+	public void
+	addListener(
+		NetStatusProtocolTesterListener		l )
+	{
+		listeners.add( l );
+	}
+	
+	public void
+	removeListener(
+		NetStatusProtocolTesterListener		l )
+	{
+		listeners.remove( l );
+	}
+	
+	public int
+	getOutboundConnects()
+	{
+		return( outbound_connects );
+	}
+	
+	public int
+	getInboundConnects()
+	{
+		return( inbound_connects );
+	}
+	
+	public String
+	getStatus()
+	{
+		return( "sessions=" + sessions.size() + 
+					", out_attempts=" + outbound_attempts + 
+					", out_connect=" + outbound_connects + 
+					", in_connect=" + inbound_connects );
+	}
+	
+	protected void
+	log(
+		String		str )
+	{
+		log( str, false );
+	}
+	
+	protected void
+	log(
+		String		str,
+		boolean 	detailed )
+	{
+		Iterator it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((NetStatusProtocolTesterListener)it.next()).log( str, detailed );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+		
+		tester.log( str );
+	}
+	
+	protected void
+	logError(
+		String	str )
+	{
+		Iterator it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((NetStatusProtocolTesterListener)it.next()).logError( str );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+		
+		tester.log( str );
+	}
+	
+	protected void
+	logError(
+		String		str,
+		Throwable	e )
+	{
+		Iterator it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((NetStatusProtocolTesterListener)it.next()).logError( str, e );
+				
+			}catch( Throwable f ){
+				
+				Debug.printStackTrace(f);
+			}
+		}
+		
+		tester.log( str, e );
+	}
+	
+	public class
+	Session
+	{
+		private NetworkConnection		connection;
+		private int						session_id;
+		private boolean					initiator;
+		private byte[]					info_hash;
+		
+		private boolean 	handshake_sent;
+		private boolean		handshake_received;
+		
+		private boolean 	bitfield_sent;
+		private boolean		bitfield_received;
+		
+		private int			num_pieces;
+		private boolean		is_seed;
+		private Set			missing_pieces = new HashSet();
+		
+		private boolean		connected;
+		private boolean		closing;
+		private boolean		closed;
+		
+		protected
+		Session(
+			NetworkConnection		_connection,
+			byte[]					_info_hash )
+		{
+			connection	= _connection;
+			info_hash	= _info_hash;
+
+			initiator 	= info_hash != null;
+			
+			synchronized( sessions ){
+			
+				session_id_next++;
+				
+				session_id = session_id_next;
+				
+				if ( destroyed ){
+					
+					log( "Already destroyed" );
+					
+					close();
+					
+					return;
+					
+				}else{
+					
+						// if we're a responder then we limit connections as we should only
+						// receive 1 (be generous, give them 3 in case we decide to reconnect)
+					
+					if ( !( test_initiator || initiator )){
+						
+						int responder_sessions = 0;
+						
+						for (int i=0;i<sessions.size();i++){
+							
+							Session	existing_session = (Session)sessions.get(i);
+							
+							if ( !existing_session.isInitiator()){
+								
+								responder_sessions++;
+							}
+						}
+						
+						if ( responder_sessions >= 2 ){
+							
+							log( "Too many responder sessions" );
+							
+							close();
+							
+							return;
+						}
+					}
+					
+					sessions.add( this );
+					
+					is_seed = initiator && sessions.size()%2 == 0;
+				}
+			}
+			
+			Iterator it = listeners.iterator();
+			
+			while( it.hasNext()){
+				
+				try{
+					((NetStatusProtocolTesterListener)it.next()).sessionAdded( this );
+					
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+			
+			connection.connect( 
+					ProtocolEndpoint.CONNECT_PRIORITY_MEDIUM,
+					new NetworkConnection.ConnectionListener() 
+					{
+						final String	type = initiator?"Outbound":"Inbound";
+						
+						public int 
+						connectStarted(
+							int default_connect_timeout )
+						{	
+							log( type + " connect start", true );
+
+							return( default_connect_timeout );
+						}
+						
+						public final void 
+						connectSuccess( 
+							ByteBuffer remaining_initial_data ) 
+						{
+							log( type + " connect success", true );
+							
+							connected	= true;
+							
+							synchronized( NetStatusProtocolTesterBT.this ){
+								
+								if ( initiator ){
+									
+									outbound_connects++;
+									
+								}else{
+									
+									inbound_connects++;
+								}
+							}
+							
+							connected();
+						}
+
+						public final void 
+						connectFailure( 
+							Throwable e ) 
+						{
+							if ( !closing ){
+							
+								logError( type + " connection fail", e );
+							}
+							
+							close();
+						}
+
+						public final void 
+						exceptionThrown( 
+							Throwable e ) 
+						{
+							if ( !closing ){
+
+								logError( type + " connection fail", e );
+							}
+							
+							close();					
+						}
+	    			
+						public Object 
+						getConnectionProperty( 
+							String property_name )
+						{
+							return( null );
+						}
+						
+						public String
+						getDescription()
+						{
+							return( "NetStatusPlugin - " + type );
+						}
+					});
+		}
+		
+		public boolean
+		isInitiator()
+		{
+			return( initiator );
+		}
+		
+		public boolean
+		isConnected()
+		{
+			return( connected );
+		}
+		
+		public boolean
+		isSeed()
+		{
+			return( is_seed );
+		}
+		
+		public boolean
+		isOK()
+		{
+			return( bitfield_received );
+		}
+		
+		protected void
+		connected()
+		{
+			connection.getIncomingMessageQueue().registerQueueListener(
+				new IncomingMessageQueue.MessageQueueListener() 
+				{
+					
+					public boolean 
+					messageReceived(
+						Message message ) 
+					{               
+						try{
+							String	message_id = message.getID();
+	
+							log( "Incoming message received: " + message.getID(), true );
+							
+					        if ( message_id.equals( BTMessage.ID_BT_HANDSHAKE )){
+						
+					        	handshake_received = true;
+					        	
+				        		BTHandshake handshake = (BTHandshake)message;
+					        		
+				        		info_hash = handshake.getDataHash();
+				        		
+				        		num_pieces = 500 + (info_hash[0]&0xff);
+				        		
+				        			// we use the piece at 'n' + 1 to indicate a close request by sending a HAVE for it
+				        			// this helps us tidily close things
+				        		
+				        		if ( num_pieces%8 == 0 ){
+				        			
+				        			num_pieces--;
+				        		}
+				        		
+				        		if ( !is_seed ){
+				        			
+				        			int missing = random.nextInt( num_pieces/2 ) + 5;
+				        			
+				        			for (int i=0;i<missing;i++){
+				        				
+				        				missing_pieces.add( new Integer( random.nextInt( num_pieces )));
+				        			}
+				        		}
+				        		
+				        		sendHandshake();
+					        	
+					        	sendBitfield();
+					        	
+					        	connection.getIncomingMessageQueue().getDecoder().resumeDecoding();
+					        	
+					        }else if ( message_id.equals( BTMessage.ID_BT_BITFIELD )){
+									
+					        	bitfield_received = true;
+					        	
+					        	BTBitfield bitfield = (BTBitfield)message;
+					  
+					        	ByteBuffer bb = bitfield.getBitfield().getBuffer((byte)0);
+					        	
+					        	byte[]	contents = new byte[bb.remaining()];
+					        	
+					        	bb.get( contents );
+					        						        	
+					        }else if ( message_id.equals( BTMessage.ID_BT_HAVE  )){
+					        	
+					        	BTHave have = (BTHave)message;
+					        	
+					        	if ( have.getPieceNumber() == num_pieces ){
+					        		
+					    			synchronized( sessions ){
+
+					    				closing = true;
+					    			}
+					    			
+					    			close();
+					        	}
+					        }
+					        
+					        return( true );
+					        
+						}finally{
+							
+							message.destroy();
+						}
+					}
+	  
+
+					public final void 
+					protocolBytesReceived(
+						int byte_count ) 
+					
+					{
+					}
+
+					public final void 
+					dataBytesReceived( 
+						int byte_count ) 
+					{
+					}
+					
+					public boolean 
+					isPriority() 
+					{
+						return true;
+					}
+				});
+
+			connection.getOutgoingMessageQueue().registerQueueListener( 
+				new OutgoingMessageQueue.MessageQueueListener() 
+				{
+					public final boolean 
+					messageAdded( 
+						Message message )
+					{
+						return( true );
+					}
+		
+					public final void 
+					messageQueued( 
+						Message message )
+					{
+					}
+		
+					public final void 
+					messageRemoved( 
+						Message message )
+					{
+						
+					}
+		
+					public final void 
+					messageSent( 
+						Message message ) 
+					{
+						log( "Outgoing message sent: " + message.getID(), true );
+					}
+		
+					public final void 
+					protocolBytesSent( 
+						int byte_count ) 
+					{
+					}
+		
+					public final void 
+					dataBytesSent( 
+						int byte_count ) 
+					{
+					}
+					
+					public void 
+					flush()
+					{
+					}
+			});
+
+			connection.startMessageProcessing();
+			
+			if ( initiator ){
+				
+				sendHandshake();
+			}
+		}
+		
+		protected void
+		sendHandshake()
+		{
+			if ( !handshake_sent ){
+				
+				handshake_sent = true;
+				
+				connection.getOutgoingMessageQueue().addMessage(
+					new BTHandshake( info_hash, peer_id, false, BTMessageFactory.MESSAGE_VERSION_INITIAL ),
+					false );
+			}
+		}
+		
+		protected void
+		sendHave(
+			int	piece_number )
+		{
+			BTHave message = new BTHave( piece_number, BTMessageFactory.MESSAGE_VERSION_INITIAL );
+			
+			OutgoingMessageQueue out_q = connection.getOutgoingMessageQueue();
+			
+			out_q.addMessage( message, false );
+			
+			out_q.flush();
+		}
+		
+		protected void
+		sendBitfield()
+		{
+			if ( !bitfield_sent ){
+			
+				bitfield_sent = true;
+				
+				byte[]	bits = new byte[( num_pieces + 7 ) /8];
+				
+				int	pos = 0;
+				
+				int i		= 0;
+				int bToSend	= 0;
+				
+				for (; i <num_pieces; i++ ){
+					
+					if ((i %8) ==0){
+						
+						bToSend =0;
+					}
+					
+					bToSend = bToSend << 1;
+					
+					boolean	has_piece = !missing_pieces.contains( new Integer(i));
+					
+					if ( has_piece ){
+						
+						bToSend += 1;
+					}
+					
+					if ((i %8) ==7){
+					
+						bits[pos++] = (byte)bToSend;
+					}
+				}
+				
+				if ((i %8) !=0){
+				
+					bToSend = bToSend << (8 - (i % 8));
+					
+					bits[pos++] = (byte)bToSend;
+				}
+								
+				DirectByteBuffer buffer = new DirectByteBuffer( ByteBuffer.wrap( bits ));
+
+				connection.getOutgoingMessageQueue().addMessage(
+					new BTBitfield( buffer, BTMessageFactory.MESSAGE_VERSION_INITIAL ),
+					false );
+			}
+		}
+		
+		protected void
+		close()
+		{
+			synchronized( sessions ){
+
+				sessions.remove( this );
+				
+				if ( !closing ){
+					
+					closing	= true;
+
+				}else{
+					
+					closed = true;
+				}
+			}
+
+			if ( closed ){
+				
+				log( "Closing connection", true  );
+				
+				connection.close( null );
+				
+			}else{
+				
+				sendHave( num_pieces );
+				
+				new DelayedEvent( 
+					"NetStatus:delayClose",
+					5000,
+					new AERunnable()
+					{
+						public void
+						runSupport()
+						{
+							if ( !closed ){
+								
+								close();
+							}
+						}
+					});
+			}
+			
+			checkCompletion();
+		}
+		
+		public String
+		getProtocolString()
+		{
+			String	str = "";
+			
+			if ( connected ){
+				
+				str = "connected";
+				
+				str += addSent( "hand", handshake_sent );
+				str += addRecv( "hand", handshake_received );
+				str += addSent( "bitf", bitfield_sent );
+				str += addRecv( "bitf", bitfield_received );
+
+			}else{
+				
+				str = "not connected";
+			}
+			
+			return( str );
+		}
+		
+		protected String
+		addSent(
+			String	str,
+			boolean	ok ) 
+		{
+			if ( ok ){
+				
+				return( ", " + str + " sent" );
+			}else{
+				
+				return( ", " + str + " !sent" );
+			}
+		}
+		
+		protected String
+		addRecv(
+			String	str,
+			boolean	ok ) 
+		{
+			if ( ok ){
+				
+				return( ", " + str + " recv" );
+			}else{
+				
+				return( ", " + str + " !recv" );
+			}
+		}
+		
+		protected String
+		getLogPrefix()
+		{
+			return( "(" + (initiator?"L":"R") + (is_seed?"S":"L") + " " + session_id + ") " );
+		}
+		
+		protected void
+		log(
+			String	str )
+		{
+			NetStatusProtocolTesterBT.this.log( getLogPrefix() + str );
+		}
+		
+		protected void
+		log(
+			String		str,
+			boolean		is_detailed )
+		{
+			NetStatusProtocolTesterBT.this.log( getLogPrefix() + str, is_detailed );
+		}
+		
+		protected void
+		logError(
+			String	str )
+		{
+			NetStatusProtocolTesterBT.this.logError( getLogPrefix() + str );
+		}
+		
+		protected void
+		logError(
+			String		str,
+			Throwable	e )
+		{
+			NetStatusProtocolTesterBT.this.logError( getLogPrefix() + str, e );
+		}
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTesterListener.java b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTesterListener.java
index e02a06b..0dd09b3 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTesterListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/NetStatusProtocolTesterListener.java
@@ -1,47 +1,47 @@
-/*
- * Created on Feb 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 com.aelitis.azureus.plugins.net.netstatus;
-
-public interface 
-NetStatusProtocolTesterListener 
-{
-	public void
-	sessionAdded(
-		NetStatusProtocolTesterBT.Session	session );
-	
-	public void
-	complete(
-		NetStatusProtocolTesterBT			tester );
-	
-	public void
-	log(
-		String		str );
-	
-	public void
-	logError(
-		String		str );
-	
-	public void
-	logError(
-		String		str,
-		Throwable	e );
-}
+/*
+ * Created on Feb 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.netstatus;
+
+public interface 
+NetStatusProtocolTesterListener 
+{
+	public void
+	sessionAdded(
+		NetStatusProtocolTesterBT.Session	session );
+	
+	public void
+	complete(
+		NetStatusProtocolTesterBT			tester );
+	
+	public void
+	log(
+		String		str,
+		boolean		is_detailed );
+	
+	public void
+	logError(
+		String		str );
+	
+	public void
+	logError(
+		String		str,
+		Throwable	e );
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/swt/NetStatusPluginTester.java b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/swt/NetStatusPluginTester.java
index d108251..96d79ee 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/swt/NetStatusPluginTester.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/swt/NetStatusPluginTester.java
@@ -1,867 +1,1161 @@
-/*
- * Created on Jan 31, 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.plugins.net.netstatus.swt;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.networkmanager.admin.*;
-import com.aelitis.azureus.core.versioncheck.VersionCheckClient;
-import com.aelitis.azureus.plugins.net.netstatus.NetStatusPlugin;
-import com.aelitis.azureus.plugins.net.netstatus.NetStatusProtocolTesterBT;
-import com.aelitis.azureus.plugins.net.netstatus.NetStatusProtocolTesterListener;
-
-public class 
-NetStatusPluginTester 
-{
-	//public static final int		TEST_PING_ROUTE		= 0x00000001;
-	public static final int		TEST_NAT_PROXIES	= 0x00000002;
-	public static final int		TEST_OUTBOUND		= 0x00000004;
-	public static final int		TEST_INBOUND		= 0x00000008;
-	public static final int		TEST_BT_CONNECT		= 0x00000010;
-	public static final int		TEST_IPV6			= 0x00000020;
-
-	
-	private static final int	ROUTE_TIMEOUT	= 120*1000;
-
-	private NetStatusPlugin		plugin;
-	private int					test_types;
-	private loggerProvider		logger;
-	
-	private volatile boolean	test_cancelled;
-	
-	public
-	NetStatusPluginTester(
-		NetStatusPlugin		_plugin,
-		int					_test_types,
-		loggerProvider		_logger )
-	{
-		plugin		= _plugin;
-		test_types	= _test_types;
-		logger		= _logger;
-	}
-	
-	protected boolean
-	doTest(
-		int		type )
-	{
-		return((test_types & type ) != 0 );
-	}
-	
-	public void
-	run(AzureusCore core)
-	{
-		final NetworkAdmin	admin = NetworkAdmin.getSingleton();
-		
-		boolean	checked_public	= false;
-
-		Set<InetAddress>	public_addresses = new HashSet<InetAddress>();
-		
-		InetAddress def_pa = admin.getDefaultPublicAddress();
-		
-		if ( def_pa != null ){
-			
-			log( "Default public address is " + def_pa.getHostAddress());
-			
-			addPublicAddress( public_addresses, def_pa );
-			
-			checked_public = true;
-		}
-		
-		/* this ain't working well and some users reporting crashes so boo
-		 *
-		if ( doTest( TEST_PING_ROUTE )){
-			
-			log( "Testing routing for the following interfaces:" );
-			
-			NetworkAdminNetworkInterface[] interfaces = admin.getInterfaces();
-			
-			for (int i=0;i<interfaces.length;i++){
-				
-				NetworkAdminNetworkInterface	intf = interfaces[i];
-				
-				NetworkAdminNetworkInterfaceAddress[] addresses = intf.getAddresses();
-				
-				String	a_str = "";
-				
-				for (int j=0;j<addresses.length;j++){
-					
-					NetworkAdminNetworkInterfaceAddress address = addresses[j];
-					
-					InetAddress ia = address.getAddress();
-					
-					if ( ia.isLoopbackAddress() || ia instanceof Inet6Address ){
-						
-					}else{
-						
-						a_str += (a_str.length()==0?"":",") + ia.getHostAddress();
-					}
-				}
-				
-				if ( a_str.length() > 0 ){
-					
-					log( "    " + intf.getName() + "/" + intf.getDisplayName() + ": " + a_str );
-				}
-			}
-			
-			if ( admin.canPing()){
-				
-				log( "Running ping tests" );
-				
-				try{
-					InetAddress	target_address = InetAddress.getByName( plugin.getPingTarget());
-					
-					final Map	active_pings = new HashMap();
-					
-					admin.pingTargets(
-						target_address, 
-						ROUTE_TIMEOUT, 
-						new NetworkAdminRoutesListener()
-						{
-							private int	timeouts;
-							
-							public boolean
-							foundNode(
-								NetworkAdminNetworkInterfaceAddress		intf,
-								NetworkAdminNode[]						route,
-								int										distance,
-								int										rtt )
-							{
-								if ( test_cancelled ){
-									
-									return( false );
-								}
-								
-								synchronized( active_pings ){
-									
-									active_pings.put( intf, route );
-								}
-								
-								log( "  " + intf.getAddress().getHostAddress() + " -> " + route[route.length-1].getAddress().getHostAddress());
-								
-								return( false );
-							}
-							
-							public boolean
-							timeout(
-								NetworkAdminNetworkInterfaceAddress		intf,
-								NetworkAdminNode[]						route,
-								int										distance )
-							{
-								if ( test_cancelled ){
-									
-									return( false );
-								}
-								
-								log( "  " + intf.getAddress().getHostAddress() + " - timeout" );
-								
-								timeouts++;
-								
-								if ( timeouts >= 3 ){
-									
-									return( false );
-								}
-								
-								return( true );
-							}
-						});
-		
-					if ( test_cancelled ){
-						
-						return;
-					}
-					
-					int	num_routes = active_pings.size();
-					
-					if ( num_routes == 0 ){
-						
-						logError( "No active pings found!" );
-						
-					}else{
-						
-						log( "Found " + num_routes + " pings(s)" );
-						
-						Iterator it = active_pings.entrySet().iterator();
-						
-						while( it.hasNext()){
-							
-							Map.Entry entry = (Map.Entry)it.next();
-							
-							NetworkAdminNetworkInterfaceAddress address = (NetworkAdminNetworkInterfaceAddress)entry.getKey();
-							
-							NetworkAdminNode[]	route = (NetworkAdminNode[])entry.getValue();
-							
-							String	node_str = "";
-							
-							for (int i=0;i<route.length;i++){
-								
-								node_str += (i==0?"":",") + route[i].getAddress().getHostAddress();
-							}
-							
-							log( "    " + address.getInterface().getName() + "/" + address.getAddress().getHostAddress() + " - " + node_str );
-						}
-					}
-				}catch( Throwable e ){
-					
-					logError( "Pinging failed: " + Debug.getNestedExceptionMessage(e));
-				}
-			}else{
-				
-				logError( "Can't run ping test as not supported" );
-			}
-			
-			if ( test_cancelled ){
-				
-				return;
-			}
-			
-			if ( admin.canTraceRoute()){
-				
-				log( "Running trace route tests" );
-				
-				try{
-					InetAddress	target_address = InetAddress.getByName( plugin.getPingTarget());
-					
-					final Map	active_routes = new HashMap();
-					
-					admin.getRoutes( 
-						target_address, 
-						ROUTE_TIMEOUT, 
-						new NetworkAdminRoutesListener()
-						{
-							private String	last_as = "";
-							
-							public boolean
-							foundNode(
-								NetworkAdminNetworkInterfaceAddress		intf,
-								NetworkAdminNode[]						route,
-								int										distance,
-								int										rtt )
-							{
-								if ( test_cancelled ){
-									
-									return( false );
-								}
-								
-								synchronized( active_routes ){
-									
-									active_routes.put( intf, route );
-								}
-								
-								InetAddress ia = route[route.length-1].getAddress();
-								
-								String	as = "";
-								
-								if ( !ia.isLinkLocalAddress() && !ia.isSiteLocalAddress()){
-									
-									try{
-										NetworkAdminASN asn = admin.lookupASN( ia );
-										
-										as = asn.getString();
-										
-										if ( as.equals( last_as )){
-											
-											as = "";
-											
-										}else{
-											
-											last_as = as;
-										}
-									}catch( Throwable e ){
-										
-									}
-								}
-								
-								log( "  " + intf.getAddress().getHostAddress() + " -> " + ia.getHostAddress() + " (hop=" + distance + ")" + (as.length()==0?"":( " - " + as )));
-								
-								return( true );
-							}
-							
-							public boolean
-							timeout(
-								NetworkAdminNetworkInterfaceAddress		intf,
-								NetworkAdminNode[]						route,
-								int										distance )
-							{
-								if ( test_cancelled ){
-									
-									return( false );
-								}
-								
-								log( "  " + intf.getAddress().getHostAddress() + " - timeout (hop=" + distance + ")" );
-		
-									// see if we're getting nowhere
-								
-								if ( route.length == 0 && distance >= 5 ){
-								
-									logError( "    giving up, no responses" );
-									
-									return( false );
-								}
-								
-									// see if we've got far enough
-								
-								if ( route.length >= 5 && distance > 6 ){
-									
-									log( "    truncating, sufficient responses" );
-		
-									return( false );
-								}
-								
-								return( true );
-							}
-						});
-		
-					if ( test_cancelled ){
-						
-						return;
-					}
-					
-					int	num_routes = active_routes.size();
-					
-					if ( num_routes == 0 ){
-						
-						logError( "No active routes found!" );
-						
-					}else{
-						
-						log( "Found " + num_routes + " route(s)" );
-						
-						Iterator it = active_routes.entrySet().iterator();
-						
-						while( it.hasNext()){
-							
-							Map.Entry entry = (Map.Entry)it.next();
-							
-							NetworkAdminNetworkInterfaceAddress address = (NetworkAdminNetworkInterfaceAddress)entry.getKey();
-							
-							NetworkAdminNode[]	route = (NetworkAdminNode[])entry.getValue();
-							
-							String	node_str = "";
-							
-							for (int i=0;i<route.length;i++){
-								
-								node_str += (i==0?"":",") + route[i].getAddress().getHostAddress();
-							}
-							
-							log( "    " + address.getInterface().getName() + "/" + address.getAddress().getHostAddress() + " - " + node_str );
-						}
-					}
-				}catch( Throwable e ){
-					
-					logError( "Route tracing failed: " + Debug.getNestedExceptionMessage(e));
-				}
-			}else{
-					
-				logError( "Can't run trace route test as not supported" );
-			}
-			
-			if ( test_cancelled ){
-				
-				return;
-			}
-		}
-		*/
-		
-		if ( doTest( TEST_NAT_PROXIES )){
-	
-			checked_public = true;
-			
-			NetworkAdminNATDevice[] nat_devices = admin.getNATDevices(core);
-			
-			log( nat_devices.length + " NAT device" + (nat_devices.length==1?"":"s") + " found" );
-			
-			for (int i=0;i<nat_devices.length;i++){
-				
-				NetworkAdminNATDevice device = nat_devices[i];
-				
-				InetAddress ext_address = device.getExternalAddress();
-				
-				addPublicAddress( public_addresses, ext_address );
-				
-				log( "    " + device.getString());
-			}
-			
-			NetworkAdminSocksProxy[] socks_proxies = admin.getSocksProxies();
-			
-			if ( socks_proxies.length == 0 ){
-				
-				log( "No SOCKS proxy found" );
-
-			}else if (  socks_proxies.length == 1 ){
-				
-				log( "One SOCKS proxy found" );
-				
-			}else{
-				
-				log( socks_proxies.length + " SOCKS proxies found" );
-			}
-			
-			for (int i=0;i<socks_proxies.length;i++){
-				
-				NetworkAdminSocksProxy proxy = socks_proxies[i];
-				
-				log( "    " + proxy.getString());
-			}
-			
-			NetworkAdminHTTPProxy http_proxy = admin.getHTTPProxy();
-			
-			if ( http_proxy == null ){
-				
-				log( "No HTTP proxy found" );
-				
-			}else{
-				
-				log( "HTTP proxy found" );
-				
-				log( "    " + http_proxy.getString());
-			}
-		}
-		
-		InetAddress[] bind_addresses = admin.getAllBindAddresses( false );
-		
-		int	num_binds = 0;
-		
-		for ( int i=0;i<bind_addresses.length;i++ ){
-		
-			if ( bind_addresses[i] != null ){
-				
-				num_binds++;
-			}
-		}
-		
-		if ( num_binds == 0 ){
-			
-			log( "No explicit bind address set" );
-			
-		}else{
-		
-			log( num_binds + " bind addresses" );
-			
-			for ( int i=0;i<bind_addresses.length;i++ ){
-		
-				if ( bind_addresses[i] != null ){
-				
-					log( "    " + bind_addresses[i].getHostAddress());
-				}
-			}
-		}
-		
-		if ( doTest( TEST_OUTBOUND )){
-
-			checked_public = true;
-			
-			NetworkAdminProtocol[] outbound_protocols = admin.getOutboundProtocols(core);
-			
-			if ( outbound_protocols.length == 0 ){
-				
-				log( "No outbound protocols" );
-				
-			}else{
-				
-				for (int i=0;i<outbound_protocols.length;i++){
-					
-					if ( test_cancelled ){
-						
-						return;
-					}
-					
-					NetworkAdminProtocol protocol = outbound_protocols[i];
-					
-					log( "Testing " + protocol.getName());
-					
-					try{
-						InetAddress public_address = 
-							protocol.test( 
-								null,
-								new NetworkAdminProgressListener()
-								{
-									public void 
-									reportProgress(
-										String task )
-									{
-										log( "    " + task );
-									}
-								});
-						
-						logSuccess( "    Test successful" );
-						
-						addPublicAddress( public_addresses, public_address );
-						
-					}catch( Throwable e ){
-						
-						logError( "    Test failed", e );
-					}
-				}
-			}
-		}
-		
-		if ( doTest( TEST_INBOUND )){
-
-			checked_public = true;
-			
-			NetworkAdminProtocol[] inbound_protocols = admin.getInboundProtocols(core);
-			
-			if ( inbound_protocols.length == 0 ){
-				
-				log( "No inbound protocols" );
-				
-			}else{
-				
-				for (int i=0;i<inbound_protocols.length;i++){
-					
-					if ( test_cancelled ){
-						
-						return;
-					}
-					
-					NetworkAdminProtocol protocol = inbound_protocols[i];
-					
-					log( "Testing " + protocol.getName());
-					
-					try{
-						InetAddress public_address = 
-							protocol.test( 
-								null,
-								new NetworkAdminProgressListener()
-								{
-									public void 
-									reportProgress(
-										String task )
-									{
-										log( "    " + task );
-									}
-								});
-						
-						logSuccess( "    Test successful" );
-	
-						addPublicAddress( public_addresses, public_address );
-						
-					}catch( Throwable e ){
-						
-						logError( "    Test failed", e );
-						logInfo(  "    Check your port forwarding for " + protocol.getTypeString() + " " + protocol.getPort());
-					}
-				}
-			}
-		}
-		
-		if ( checked_public ){
-			
-			if ( public_addresses.size() == 0 ){
-				
-				log( "No public addresses found" );
-				
-			}else{
-				
-				Iterator<InetAddress>	it = public_addresses.iterator();
-				
-				log( public_addresses.size() + " public/external addresses found" );
-				
-				while( it.hasNext()){
-					
-					InetAddress	pub_address = it.next();
-					
-					log( "    " + pub_address.getHostAddress());
-					
-					try{
-						NetworkAdminASN asn = admin.lookupASN(pub_address);
-						
-						log( "    AS details: " + asn.getString());
-						
-					}catch( Throwable e ){
-						
-						logError( "    failed to lookup AS", e );
-					}
-				}
-			}
-		}
-		
-		if ( doTest( TEST_BT_CONNECT )){
-
-			log( "Distributed protocol test" );
-			
-			NetStatusProtocolTesterBT bt_test = 
-				plugin.getProtocolTester().runTest(
-				
-					new NetStatusProtocolTesterListener()
-					{
-						private List	sessions = new ArrayList();
-						
-						public void
-						complete(
-							NetStatusProtocolTesterBT	tester )
-						{
-							log( "Results" );
-							
-							if ( tester.getOutboundConnects() < 4 ){
-								
-								log( "    insufficient outbound connects for analysis" );
-								
-								return;
-							}
-							
-							int outgoing_seed_ok		= 0;
-							int outgoing_leecher_ok		= 0;
-							int outgoing_seed_bad		= 0;
-							int outgoing_leecher_bad	= 0;
-							
-							int incoming_connect_ok	= 0;						
-							
-							for (int i=0;i<sessions.size();i++){
-								
-								NetStatusProtocolTesterBT.Session session = (NetStatusProtocolTesterBT.Session)sessions.get(i);
-								
-								if ( session.isOK()){
-									
-									if ( session.isInitiator()){
-										
-										if ( session.isSeed()){
-											
-											outgoing_seed_ok++;
-											
-										}else{
-											
-											outgoing_leecher_ok++;
-										}
-									}else{
-									
-										incoming_connect_ok++;
-									}
-								}else{
-	
-									if ( session.isConnected()){
-										
-										if ( session.isInitiator()){
-											
-											if ( session.isSeed()){
-												
-												outgoing_seed_bad++;
-												
-											}else{
-												
-												outgoing_leecher_bad++;
-											}
-										}else{
-											
-											incoming_connect_ok++;										
-										}
-									}
-								}
-								
-								log( "  " + 
-										( session.isInitiator()?"Outbound":"Inbound" ) + "," + 
-										( session.isSeed()?"Seed":"Leecher") + "," + 
-										session.getProtocolString());
-							}
-							
-							if ( incoming_connect_ok == 0 ){
-								
-								logError( "  No incoming connections received, likely NAT problems" );
-							}
-							
-							if ( 	outgoing_leecher_ok > 0 &&
-									outgoing_seed_ok == 0 &&
-									outgoing_seed_bad > 0 ){
-								
-								logError( "  Outgoing seed connects appear to be failing while non-seeds succeed" );
-							}
-						}
-						
-						public void
-						sessionAdded(
-							NetStatusProtocolTesterBT.Session	session )
-						{
-							synchronized( sessions ){
-								
-								sessions.add( session );
-							}
-						}
-						
-						public void
-						log(
-							String		str )
-						{
-							NetStatusPluginTester.this.log( "  " + str );
-						}
-						
-						public void
-						logError(
-							String		str )
-						{
-							NetStatusPluginTester.this.logError( "  " + str );
-						}
-						
-						public void
-						logError(
-							String		str,
-							Throwable	e )
-						{
-							NetStatusPluginTester.this.logError( "  " + str, e );
-						}
-					});
-			
-			while( !bt_test.waitForCompletion( 5000 )){
-				
-				if ( isCancelled()){
-					
-					bt_test.destroy();
-					
-					break;
-				}
-				
-				log( "    Status: " + bt_test.getStatus());
-			}
-		}
-		
-		if ( doTest( TEST_IPV6 )){
-
-			log( "IPv6 test" );
-			
-			InetAddress ipv6_address = admin.getDefaultPublicAddressV6();
-			
-			if ( ipv6_address == null ){
-				
-				log( "    No default public IPv6 address found" );
-				
-			}else{
-				
-				log( "    Default public IPv6 address: " + ipv6_address.getHostAddress());
-
-				log( "    Testing connectivity..." );
-				
-				String res = VersionCheckClient.getSingleton().getExternalIpAddress( false, true, true );
-				
-				if ( res != null && res.length() > 0 ){
-					
-					logSuccess( "        Connect succeeded, reported IPv6 address: " + res );
-					
-				}else{
-					
-					logError( "        Connect failed" );
-				}
-			}
-		}
-	}
-	
-	protected void
-	addPublicAddress(
-		Set<InetAddress>	addresses,
-		InetAddress			address )
-	{
-		if ( address == null ){
-			
-			return;
-		}
-			
-		if ( 	address.isAnyLocalAddress() ||
-				address.isLoopbackAddress() ||
-				address.isLinkLocalAddress()||
-				address.isSiteLocalAddress()){
-			
-				return;
-		}
-		
-		addresses.add( address );
-	}
-	
-	public void
-	cancel()
-	{
-		test_cancelled	= true;
-	}
-	
-	public boolean
-	isCancelled()
-	{
-		return( test_cancelled );
-	}
-	
-	protected void
-	log(
-		String	str )
-	{
-		logger.log( str );
-	}
-	
-	protected void
-	logSuccess(
-		String	str )
-	{
-		logger.logSuccess( str );
-	}
-	
-	protected void
-	logInfo(
-		String	str )
-	{
-		logger.logInfo( str );
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable	e )
-	{
-		logger.log( str + ": " + e.getLocalizedMessage());
-	}
-	
-	protected void
-	logError(
-		String	str )
-	{
-		logger.logFailure( str );
-	}
-	
-	protected void
-	logError(
-		String		str,
-		Throwable	e )
-	{
-		logger.logFailure( str + ": " + e.getLocalizedMessage());
-	}
-	
-	public interface
-	loggerProvider
-	{
-		public void
-		log(
-			String	str );
-		
-		public void
-		logSuccess(
-			String	str );
-		
-		public void
-		logInfo(
-			String	str );
-		
-		public void
-		logFailure(
-			String	str );
-	}
-	
-}
+/*
+ * Created on Jan 31, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.netstatus.swt;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.URL;
+import java.util.*;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSession;
+
+import java.security.cert.Certificate;
+
+import org.gudy.azureus2.core3.util.BDecoder;
+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.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.networkmanager.admin.*;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
+import com.aelitis.azureus.core.versioncheck.VersionCheckClient;
+import com.aelitis.azureus.plugins.net.netstatus.NetStatusPlugin;
+import com.aelitis.azureus.plugins.net.netstatus.NetStatusProtocolTesterBT;
+import com.aelitis.azureus.plugins.net.netstatus.NetStatusProtocolTesterListener;
+
+public class 
+NetStatusPluginTester 
+{
+	//public static final int		TEST_PING_ROUTE		= 0x00000001;
+	public static final int		TEST_NAT_PROXIES	= 0x00000002;
+	public static final int		TEST_OUTBOUND		= 0x00000004;
+	public static final int		TEST_INBOUND		= 0x00000008;
+	public static final int		TEST_BT_CONNECT		= 0x00000010;
+	public static final int		TEST_IPV6			= 0x00000020;
+	public static final int		TEST_VUZE_SERVICES	= 0x00000040;
+	public static final int		TEST_PROXY_CONNECT	= 0x00000080;
+
+	
+	private static final int	ROUTE_TIMEOUT	= 120*1000;
+
+	private NetStatusPlugin		plugin;
+	private int					test_types;
+	private loggerProvider		logger;
+	
+	private volatile boolean	test_cancelled;
+	
+	public
+	NetStatusPluginTester(
+		NetStatusPlugin		_plugin,
+		int					_test_types,
+		loggerProvider		_logger )
+	{
+		plugin		= _plugin;
+		test_types	= _test_types;
+		logger		= _logger;
+	}
+	
+	protected boolean
+	doTest(
+		int		type )
+	{
+		if ( test_cancelled ){
+			
+			return( false );
+		}
+		
+		return((test_types & type ) != 0 );
+	}
+	
+	public void
+	run(AzureusCore core)
+	{
+		final NetworkAdmin	admin = NetworkAdmin.getSingleton();
+		
+		boolean	checked_public	= false;
+
+		Set<InetAddress>	public_addresses = new HashSet<InetAddress>();
+		
+		InetAddress def_pa = admin.getDefaultPublicAddress();
+		
+		if ( def_pa != null ){
+			
+			log( "Default public address is " + def_pa.getHostAddress());
+			
+			addPublicAddress( public_addresses, def_pa );
+			
+			checked_public = true;
+		}
+		
+		/* this ain't working well and some users reporting crashes so boo
+		 *
+		if ( doTest( TEST_PING_ROUTE )){
+			
+			log( "Testing routing for the following interfaces:" );
+			
+			NetworkAdminNetworkInterface[] interfaces = admin.getInterfaces();
+			
+			for (int i=0;i<interfaces.length;i++){
+				
+				NetworkAdminNetworkInterface	intf = interfaces[i];
+				
+				NetworkAdminNetworkInterfaceAddress[] addresses = intf.getAddresses();
+				
+				String	a_str = "";
+				
+				for (int j=0;j<addresses.length;j++){
+					
+					NetworkAdminNetworkInterfaceAddress address = addresses[j];
+					
+					InetAddress ia = address.getAddress();
+					
+					if ( ia.isLoopbackAddress() || ia instanceof Inet6Address ){
+						
+					}else{
+						
+						a_str += (a_str.length()==0?"":",") + ia.getHostAddress();
+					}
+				}
+				
+				if ( a_str.length() > 0 ){
+					
+					log( "    " + intf.getName() + "/" + intf.getDisplayName() + ": " + a_str );
+				}
+			}
+			
+			if ( admin.canPing()){
+				
+				log( "Running ping tests" );
+				
+				try{
+					InetAddress	target_address = InetAddress.getByName( plugin.getPingTarget());
+					
+					final Map	active_pings = new HashMap();
+					
+					admin.pingTargets(
+						target_address, 
+						ROUTE_TIMEOUT, 
+						new NetworkAdminRoutesListener()
+						{
+							private int	timeouts;
+							
+							public boolean
+							foundNode(
+								NetworkAdminNetworkInterfaceAddress		intf,
+								NetworkAdminNode[]						route,
+								int										distance,
+								int										rtt )
+							{
+								if ( test_cancelled ){
+									
+									return( false );
+								}
+								
+								synchronized( active_pings ){
+									
+									active_pings.put( intf, route );
+								}
+								
+								log( "  " + intf.getAddress().getHostAddress() + " -> " + route[route.length-1].getAddress().getHostAddress());
+								
+								return( false );
+							}
+							
+							public boolean
+							timeout(
+								NetworkAdminNetworkInterfaceAddress		intf,
+								NetworkAdminNode[]						route,
+								int										distance )
+							{
+								if ( test_cancelled ){
+									
+									return( false );
+								}
+								
+								log( "  " + intf.getAddress().getHostAddress() + " - timeout" );
+								
+								timeouts++;
+								
+								if ( timeouts >= 3 ){
+									
+									return( false );
+								}
+								
+								return( true );
+							}
+						});
+		
+					if ( test_cancelled ){
+						
+						return;
+					}
+					
+					int	num_routes = active_pings.size();
+					
+					if ( num_routes == 0 ){
+						
+						logError( "No active pings found!" );
+						
+					}else{
+						
+						log( "Found " + num_routes + " pings(s)" );
+						
+						Iterator it = active_pings.entrySet().iterator();
+						
+						while( it.hasNext()){
+							
+							Map.Entry entry = (Map.Entry)it.next();
+							
+							NetworkAdminNetworkInterfaceAddress address = (NetworkAdminNetworkInterfaceAddress)entry.getKey();
+							
+							NetworkAdminNode[]	route = (NetworkAdminNode[])entry.getValue();
+							
+							String	node_str = "";
+							
+							for (int i=0;i<route.length;i++){
+								
+								node_str += (i==0?"":",") + route[i].getAddress().getHostAddress();
+							}
+							
+							log( "    " + address.getInterface().getName() + "/" + address.getAddress().getHostAddress() + " - " + node_str );
+						}
+					}
+				}catch( Throwable e ){
+					
+					logError( "Pinging failed: " + Debug.getNestedExceptionMessage(e));
+				}
+			}else{
+				
+				logError( "Can't run ping test as not supported" );
+			}
+			
+			if ( test_cancelled ){
+				
+				return;
+			}
+			
+			if ( admin.canTraceRoute()){
+				
+				log( "Running trace route tests" );
+				
+				try{
+					InetAddress	target_address = InetAddress.getByName( plugin.getPingTarget());
+					
+					final Map	active_routes = new HashMap();
+					
+					admin.getRoutes( 
+						target_address, 
+						ROUTE_TIMEOUT, 
+						new NetworkAdminRoutesListener()
+						{
+							private String	last_as = "";
+							
+							public boolean
+							foundNode(
+								NetworkAdminNetworkInterfaceAddress		intf,
+								NetworkAdminNode[]						route,
+								int										distance,
+								int										rtt )
+							{
+								if ( test_cancelled ){
+									
+									return( false );
+								}
+								
+								synchronized( active_routes ){
+									
+									active_routes.put( intf, route );
+								}
+								
+								InetAddress ia = route[route.length-1].getAddress();
+								
+								String	as = "";
+								
+								if ( !ia.isLinkLocalAddress() && !ia.isSiteLocalAddress()){
+									
+									try{
+										NetworkAdminASN asn = admin.lookupASN( ia );
+										
+										as = asn.getString();
+										
+										if ( as.equals( last_as )){
+											
+											as = "";
+											
+										}else{
+											
+											last_as = as;
+										}
+									}catch( Throwable e ){
+										
+									}
+								}
+								
+								log( "  " + intf.getAddress().getHostAddress() + " -> " + ia.getHostAddress() + " (hop=" + distance + ")" + (as.length()==0?"":( " - " + as )));
+								
+								return( true );
+							}
+							
+							public boolean
+							timeout(
+								NetworkAdminNetworkInterfaceAddress		intf,
+								NetworkAdminNode[]						route,
+								int										distance )
+							{
+								if ( test_cancelled ){
+									
+									return( false );
+								}
+								
+								log( "  " + intf.getAddress().getHostAddress() + " - timeout (hop=" + distance + ")" );
+		
+									// see if we're getting nowhere
+								
+								if ( route.length == 0 && distance >= 5 ){
+								
+									logError( "    giving up, no responses" );
+									
+									return( false );
+								}
+								
+									// see if we've got far enough
+								
+								if ( route.length >= 5 && distance > 6 ){
+									
+									log( "    truncating, sufficient responses" );
+		
+									return( false );
+								}
+								
+								return( true );
+							}
+						});
+		
+					if ( test_cancelled ){
+						
+						return;
+					}
+					
+					int	num_routes = active_routes.size();
+					
+					if ( num_routes == 0 ){
+						
+						logError( "No active routes found!" );
+						
+					}else{
+						
+						log( "Found " + num_routes + " route(s)" );
+						
+						Iterator it = active_routes.entrySet().iterator();
+						
+						while( it.hasNext()){
+							
+							Map.Entry entry = (Map.Entry)it.next();
+							
+							NetworkAdminNetworkInterfaceAddress address = (NetworkAdminNetworkInterfaceAddress)entry.getKey();
+							
+							NetworkAdminNode[]	route = (NetworkAdminNode[])entry.getValue();
+							
+							String	node_str = "";
+							
+							for (int i=0;i<route.length;i++){
+								
+								node_str += (i==0?"":",") + route[i].getAddress().getHostAddress();
+							}
+							
+							log( "    " + address.getInterface().getName() + "/" + address.getAddress().getHostAddress() + " - " + node_str );
+						}
+					}
+				}catch( Throwable e ){
+					
+					logError( "Route tracing failed: " + Debug.getNestedExceptionMessage(e));
+				}
+			}else{
+					
+				logError( "Can't run trace route test as not supported" );
+			}
+			
+			if ( test_cancelled ){
+				
+				return;
+			}
+		}
+		*/
+		
+		if ( doTest( TEST_NAT_PROXIES )){
+	
+			checked_public = true;
+			
+			NetworkAdminNATDevice[] nat_devices = admin.getNATDevices(core);
+			
+			log( nat_devices.length + " NAT device" + (nat_devices.length==1?"":"s") + " found" );
+			
+			for (int i=0;i<nat_devices.length;i++){
+				
+				NetworkAdminNATDevice device = nat_devices[i];
+				
+				InetAddress ext_address = device.getExternalAddress();
+				
+				addPublicAddress( public_addresses, ext_address );
+				
+				log( "    " + device.getString());
+			}
+			
+			NetworkAdminSocksProxy[] socks_proxies = admin.getSocksProxies();
+			
+			if ( socks_proxies.length == 0 ){
+				
+				log( "No SOCKS proxy found" );
+
+			}else if (  socks_proxies.length == 1 ){
+				
+				log( "One SOCKS proxy found" );
+				
+			}else{
+				
+				log( socks_proxies.length + " SOCKS proxies found" );
+			}
+			
+			for (int i=0;i<socks_proxies.length;i++){
+				
+				NetworkAdminSocksProxy proxy = socks_proxies[i];
+				
+				log( "    " + proxy.getString());
+			}
+			
+			NetworkAdminHTTPProxy http_proxy = admin.getHTTPProxy();
+			
+			if ( http_proxy == null ){
+				
+				log( "No HTTP proxy found" );
+				
+			}else{
+				
+				log( "HTTP proxy found" );
+				
+				log( "    " + http_proxy.getString());
+			}
+		}
+		
+		InetAddress[] bind_addresses = admin.getAllBindAddresses( false );
+		
+		int	num_binds = 0;
+		
+		for ( int i=0;i<bind_addresses.length;i++ ){
+		
+			if ( bind_addresses[i] != null ){
+				
+				num_binds++;
+			}
+		}
+		
+		if ( num_binds == 0 ){
+			
+			log( "No explicit bind address set" );
+			
+		}else{
+		
+			log( num_binds + " bind addresses" );
+			
+			for ( int i=0;i<bind_addresses.length;i++ ){
+		
+				if ( bind_addresses[i] != null ){
+				
+					log( "    " + bind_addresses[i].getHostAddress());
+				}
+			}
+		}
+		
+		if ( doTest( TEST_OUTBOUND )){
+
+			checked_public = true;
+			
+			NetworkAdminProtocol[] outbound_protocols = admin.getOutboundProtocols(core);
+			
+			if ( outbound_protocols.length == 0 ){
+				
+				log( "No outbound protocols" );
+				
+			}else{
+				
+				for (int i=0;i<outbound_protocols.length;i++){
+					
+					if ( test_cancelled ){
+						
+						return;
+					}
+					
+					NetworkAdminProtocol protocol = outbound_protocols[i];
+					
+					log( "Testing " + protocol.getName());
+					
+					try{
+						InetAddress public_address = 
+							protocol.test( 
+								null,
+								new NetworkAdminProgressListener()
+								{
+									public void 
+									reportProgress(
+										String task )
+									{
+										log( "    " + task );
+									}
+								});
+						
+						logSuccess( "    Test successful" );
+						
+						addPublicAddress( public_addresses, public_address );
+						
+					}catch( Throwable e ){
+						
+						logError( "    Test failed", e );
+					}
+				}
+			}
+		}
+		
+		if ( doTest( TEST_INBOUND )){
+
+			checked_public = true;
+			
+			NetworkAdminProtocol[] inbound_protocols = admin.getInboundProtocols(core);
+			
+			if ( inbound_protocols.length == 0 ){
+				
+				log( "No inbound protocols" );
+				
+			}else{
+				
+				for (int i=0;i<inbound_protocols.length;i++){
+					
+					if ( test_cancelled ){
+						
+						return;
+					}
+					
+					NetworkAdminProtocol protocol = inbound_protocols[i];
+					
+					log( "Testing " + protocol.getName());
+					
+					try{
+						InetAddress public_address = 
+							protocol.test( 
+								null,
+								new NetworkAdminProgressListener()
+								{
+									public void 
+									reportProgress(
+										String task )
+									{
+										log( "    " + task );
+									}
+								});
+						
+						logSuccess( "    Test successful" );
+	
+						addPublicAddress( public_addresses, public_address );
+						
+					}catch( Throwable e ){
+						
+						logError( "    Test failed", e );
+						logInfo(  "    Check your port forwarding for " + protocol.getTypeString() + " " + protocol.getPort());
+					}
+				}
+			}
+		}
+		
+		if ( checked_public ){
+			
+			if ( public_addresses.size() == 0 ){
+				
+				log( "No public addresses found" );
+				
+			}else{
+				
+				Iterator<InetAddress>	it = public_addresses.iterator();
+				
+				log( public_addresses.size() + " public/external addresses found" );
+				
+				while( it.hasNext()){
+					
+					InetAddress	pub_address = it.next();
+					
+					log( "    " + pub_address.getHostAddress());
+					
+					try{
+						NetworkAdminASN asn = admin.lookupASN(pub_address);
+						
+						log( "    AS details: " + asn.getString());
+						
+					}catch( Throwable e ){
+						
+						logError( "    failed to lookup AS", e );
+					}
+				}
+			}
+		}
+		
+		if ( doTest( TEST_VUZE_SERVICES )){
+			
+			log( "Vuze Services test" );
+			
+			String[][] services = { 
+					{ "Vuze Website", 		"https://www.vuze.com/" },
+					{ "Client Website", 	"https://client.vuze.com/" },
+					{ "Version Server", 	"http://version.vuze.com/?dee" },
+					{ "Pairing Server", 	"https://pair.vuze.com/pairing/web/view?" },
+					{ "License Server", 	"https://license.vuze.com/licence" },
+					{ "Plugins Website", 	"https://plugins.vuze.com/" },
+			};
+			
+			for ( String[] service: services ){
+				
+				if ( test_cancelled ){
+					
+					return;
+				}
+				
+				try{
+					URL	url = new URL( service[1] );
+			
+					log( "    " + service[0] + " - " + url.getHost());
+
+					boolean	is_https = url.getProtocol().equals( "https" );
+					
+					if ( is_https ){
+						
+						String[]	host_bits = url.getHost().split( "\\." );
+						
+						String host_match = "." + host_bits[host_bits.length-2] + "." + host_bits[host_bits.length-1];
+
+						HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
+																	  	
+						con.setHostnameVerifier(
+							new HostnameVerifier()
+							{
+								public boolean
+								verify(
+									String		host,
+									SSLSession	session )
+								{
+									return( true );
+								}
+							});
+						
+						
+						con.setInstanceFollowRedirects( false );
+						
+						con.setConnectTimeout( 30*1000 );
+						con.setReadTimeout( 30*1000 );
+		
+						con.getResponseCode();
+							
+						con.getInputStream();
+						
+						Certificate[] certs = con.getServerCertificates();
+							
+						if ( certs == null || certs.length == 0 ){
+								
+							logError( "        No certificates returned" );
+								
+						}else{
+							
+							Certificate cert = certs[0];
+							
+							java.security.cert.X509Certificate x509_cert;
+							
+							if ( cert instanceof java.security.cert.X509Certificate ){
+								
+								x509_cert = (java.security.cert.X509Certificate)cert;
+								
+							}else{
+								
+								java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
+								
+								x509_cert = (java.security.cert.X509Certificate)cf.generateCertificate(new ByteArrayInputStream(cert.getEncoded()));
+							}
+
+							log( "        Certificate: " + x509_cert.getSubjectDN());
+						
+							Collection<List<?>> alt_names = x509_cert.getSubjectAlternativeNames();
+							
+							boolean match = false;
+							
+							for ( List<?> alt_name: alt_names ){
+								
+								int	type = ((Number)alt_name.get(0)).intValue();
+								
+								if ( type == 2 ){		// DNS name
+									
+									String	dns_name = (String)alt_name.get(1);
+									
+									if ( dns_name.endsWith( host_match )){
+										
+										match = true;
+										
+										break;
+									}
+								}
+							}
+							
+							if ( !match ){
+								
+								logError( "        Failed: Host '" + host_match + "' not found in certificate" );
+								
+							}else{
+								
+								logSuccess( "        Connection result: " + con.getResponseCode() + "/" + con.getResponseMessage());
+							}
+						}
+					}else{
+						
+						HttpURLConnection con = (HttpURLConnection)url.openConnection();
+						
+						con.setInstanceFollowRedirects( false );
+						
+						con.setConnectTimeout( 30*1000 );
+						con.setReadTimeout( 30*1000 );
+		
+						if ( con.getResponseCode() != 200 ){
+							
+							throw( new Exception( "Connection failed: " + con.getResponseCode() + "/" + con.getResponseMessage()));
+						}
+							
+						Map resp = BDecoder.decode( new BufferedInputStream( con.getInputStream(), 16*1024 ));
+						
+						if ( resp != null && resp.containsKey( "version" )){
+							
+							logSuccess( "        Connection result: " + con.getResponseCode() + "/" + con.getResponseMessage());
+
+						}else{
+							
+							logError( "        Unexpected reply from server: " + resp );
+						}
+					}
+				}catch( Throwable e ){
+				
+					logError( "        Failed: " + Debug.getNestedExceptionMessage( e ));
+				}
+			}
+		}
+		
+		if ( doTest( TEST_PROXY_CONNECT )){
+			
+			log( "Indirect Connect test" );
+			
+			try{
+				URL target = new URL( "https://www.vuze.com" );
+				
+				PluginProxy proxy = AEProxyFactory.getPluginProxy( "Network Status test", target );
+				
+				if ( proxy == null ){
+					
+					String url_str = "http://azureus.sourceforge.net/plugin_detailssf.php?plugin=aznettor&os=";
+					
+					if ( Constants.isWindows ){
+						
+						url_str += "Windows";
+						
+					}else{
+						
+						url_str += "Mac%20OSX";
+					}
+					
+					URL url = new URL( url_str );
+					
+					logError( "    No plugin proxy available" );
+					logInfo( "    For the plugin installer see " + url.toExternalForm());
+					
+				}else{
+				
+					log( "    Connecting to " + target.toExternalForm());
+					
+					HttpURLConnection con = (HttpURLConnection)proxy.getURL().openConnection( proxy.getProxy());
+					
+					if ( con instanceof HttpsURLConnection ){
+										  	
+						((HttpsURLConnection)con).setHostnameVerifier(
+								new HostnameVerifier()
+								{
+									public boolean
+									verify(
+										String		host,
+										SSLSession	session )
+									{
+										return( true );
+									}
+								});
+					}
+					
+					con.setRequestProperty( "HOST", proxy.getURLHostRewrite());
+					
+					con.setInstanceFollowRedirects( false );
+					
+					con.setConnectTimeout( 60*1000 );
+					con.setReadTimeout( 30*1000 );
+	
+					try{
+						int resp = con.getResponseCode();
+							
+						if ( con instanceof HttpsURLConnection ){
+							
+							Certificate[] certs = ((HttpsURLConnection)con).getServerCertificates();
+							
+							if ( certs == null || certs.length == 0 ){
+								
+								logError( "    No certificates returned" );
+								
+							}else{
+								Certificate cert = certs[0];
+								
+								java.security.cert.X509Certificate x509_cert;
+								
+								if ( cert instanceof java.security.cert.X509Certificate ){
+									
+									x509_cert = (java.security.cert.X509Certificate)cert;
+									
+								}else{
+									
+									java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory.getInstance("X.509");
+									
+									x509_cert = (java.security.cert.X509Certificate)cf.generateCertificate(new ByteArrayInputStream(cert.getEncoded()));
+								}
+	
+								log( "    Certificate: " + x509_cert.getSubjectDN());
+							}
+						}
+					
+						if ( resp == 200 ){
+							
+							logSuccess( "    Connection result: " + con.getResponseCode() + "/" + con.getResponseMessage());
+							
+						}else{
+							
+							log( "    Connection result: " + con.getResponseCode() + "/" + con.getResponseMessage());
+						}
+					}finally{
+						
+						proxy.setOK( true );
+					}
+				}
+			}catch( Throwable e ){
+				
+				logError( "    Failed: " + Debug.getNestedExceptionMessage( e ));
+				logError( "    Check the logs for the 'Tor Helper Plugin' (Tools->Plugins->Log Views)" );
+			}
+		}
+		
+		if ( doTest( TEST_BT_CONNECT )){
+
+			log( "Distributed protocol test" );
+			
+			NetStatusProtocolTesterBT bt_test = 
+				plugin.getProtocolTester().runTest(
+				
+					new NetStatusProtocolTesterListener()
+					{
+						private List	sessions = new ArrayList();
+						
+						public void
+						complete(
+							NetStatusProtocolTesterBT	tester )
+						{
+							log( "Results", false );
+							
+							if ( tester.getOutboundConnects() < 4 ){
+								
+								log( "    insufficient outbound connects for analysis", false );
+								
+								return;
+							}
+							
+							int outgoing_seed_ok		= 0;
+							int outgoing_leecher_ok		= 0;
+							int outgoing_seed_bad		= 0;
+							int outgoing_leecher_bad	= 0;
+							
+							int incoming_connect_ok	= 0;						
+							
+							for (int i=0;i<sessions.size();i++){
+								
+								NetStatusProtocolTesterBT.Session session = (NetStatusProtocolTesterBT.Session)sessions.get(i);
+								
+								if ( session.isOK()){
+									
+									if ( session.isInitiator()){
+										
+										if ( session.isSeed()){
+											
+											outgoing_seed_ok++;
+											
+										}else{
+											
+											outgoing_leecher_ok++;
+										}
+									}else{
+									
+										incoming_connect_ok++;
+									}
+								}else{
+	
+									if ( session.isConnected()){
+										
+										if ( session.isInitiator()){
+											
+											if ( session.isSeed()){
+												
+												outgoing_seed_bad++;
+												
+											}else{
+												
+												outgoing_leecher_bad++;
+											}
+										}else{
+											
+											incoming_connect_ok++;										
+										}
+									}
+								}
+								
+								log( "  " + 
+										( session.isInitiator()?"Outbound":"Inbound" ) + "," + 
+										( session.isSeed()?"Seed":"Leecher") + "," + 
+										session.getProtocolString(), false );
+							}
+							
+							boolean	good = true;
+							
+							if ( incoming_connect_ok == 0 ){
+								
+								logError( "  No incoming connections received, likely NAT problems" );
+								
+								good = false;
+							}
+							
+							if ( 	outgoing_leecher_ok > 0 &&
+									outgoing_seed_ok == 0 &&
+									outgoing_seed_bad > 0 ){
+								
+								logError( "  Outgoing seed connects appear to be failing while non-seeds succeed" );
+								
+								good = false;
+							}
+							
+							if ( good ){
+								
+								logSuccess( "    Test successful" );
+							}
+						}
+						
+						public void
+						sessionAdded(
+							NetStatusProtocolTesterBT.Session	session )
+						{
+							synchronized( sessions ){
+								
+								sessions.add( session );
+							}
+						}
+						
+						public void
+						log(
+							String		str,
+							boolean		detailed )
+						{
+							NetStatusPluginTester.this.log( "  " + str, detailed );
+						}
+						
+						public void
+						logError(
+							String		str )
+						{
+							NetStatusPluginTester.this.logError( "  " + str );
+						}
+						
+						public void
+						logError(
+							String		str,
+							Throwable	e )
+						{
+							NetStatusPluginTester.this.logError( "  " + str, e );
+						}
+					});
+			
+			while( !bt_test.waitForCompletion( 5000 )){
+				
+				if ( isCancelled()){
+					
+					bt_test.destroy();
+					
+					break;
+				}
+				
+				log( "    Status: " + bt_test.getStatus());
+			}
+		}
+		
+		if ( doTest( TEST_IPV6 )){
+
+			log( "IPv6 test" );
+			
+			InetAddress ipv6_address = admin.getDefaultPublicAddressV6();
+			
+			if ( ipv6_address == null ){
+				
+				log( "    No default public IPv6 address found" );
+				
+			}else{
+				
+				log( "    Default public IPv6 address: " + ipv6_address.getHostAddress());
+
+				log( "    Testing connectivity..." );
+				
+				String res = VersionCheckClient.getSingleton().getExternalIpAddress( false, true, true );
+				
+				if ( res != null && res.length() > 0 ){
+					
+					logSuccess( "        Connect succeeded, reported IPv6 address: " + res );
+					
+				}else{
+					
+					logError( "        Connect failed" );
+				}
+			}
+		}
+	}
+	
+	protected void
+	addPublicAddress(
+		Set<InetAddress>	addresses,
+		InetAddress			address )
+	{
+		if ( address == null ){
+			
+			return;
+		}
+			
+		if ( 	address.isAnyLocalAddress() ||
+				address.isLoopbackAddress() ||
+				address.isLinkLocalAddress()||
+				address.isSiteLocalAddress()){
+			
+				return;
+		}
+		
+		addresses.add( address );
+	}
+	
+	public void
+	cancel()
+	{
+		test_cancelled	= true;
+	}
+	
+	public boolean
+	isCancelled()
+	{
+		return( test_cancelled );
+	}
+	
+	protected void
+	log(
+		String		str )
+	{
+		log( str, false );
+	}
+	
+	protected void
+	log(
+		String		str,
+		boolean		detailed )
+	{
+		logger.log( str, detailed );
+	}
+	
+	protected void
+	logSuccess(
+		String	str )
+	{
+		logger.logSuccess( str );
+	}
+	
+	protected void
+	logInfo(
+		String	str )
+	{
+		logger.logInfo( str );
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable	e )
+	{
+		logger.log( str + ": " + e.getLocalizedMessage(), false );
+	}
+	
+	protected void
+	logError(
+		String	str )
+	{
+		logger.logFailure( str );
+	}
+	
+	protected void
+	logError(
+		String		str,
+		Throwable	e )
+	{
+		logger.logFailure( str + ": " + e.getLocalizedMessage());
+	}
+	
+	public interface
+	loggerProvider
+	{
+		public void
+		log(
+			String	str,
+			boolean	is_detailed );
+		
+		public void
+		logSuccess(
+			String	str );
+		
+		public void
+		logInfo(
+			String	str );
+		
+		public void
+		logFailure(
+			String	str );
+	}
+	
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/swt/NetStatusPluginView.java b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/swt/NetStatusPluginView.java
index e025db5..5de6f23 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/swt/NetStatusPluginView.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/net/netstatus/swt/NetStatusPluginView.java
@@ -1,556 +1,612 @@
-/*
- * Created on Jan 30, 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.plugins.net.netstatus.swt;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.StyleRange;
-import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Color;
-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.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.ui.UIInstance;
-import org.gudy.azureus2.ui.swt.Messages;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
-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.plugins.net.netstatus.NetStatusPlugin;
-
-public class 
-NetStatusPluginView 
-	implements UISWTViewEventListener
-{
-	private NetStatusPlugin	plugin;
-	
-	private boolean		created = false;	
-
-	private Composite	composite;
-	private Button		start_button;
-	private Button		cancel_button;
-	private StyledText 	log;
-	
-	private int			selected_tests;
-	
-	private NetStatusPluginTester		current_test;
-	
-	private static final int LOG_NORMAL 	= 1;
-	private static final int LOG_SUCCESS 	= 2;
-	private static final int LOG_ERROR 		= 3;
-	private static final int LOG_INFO 		= 4;
-	
-	private int	log_type	= LOG_NORMAL;
-	
-	public
-	NetStatusPluginView(
-		NetStatusPlugin	_plugin,
-		UIInstance		_ui,
-		String			VIEW_ID )
-	{
-		plugin	= _plugin;
-		
-		((UISWTInstance)_ui).addView( UISWTInstance.VIEW_MAIN, VIEW_ID, this );
-	}
-	
-	public boolean 
-	eventOccurred(
-		UISWTViewEvent event )
-	{
-		switch( event.getType() ){
-
-			case UISWTViewEvent.TYPE_CREATE:{
-				
-				if ( created ){
-					
-					return( false );
-				}
-				
-				created = true;
-				
-				break;
-			}
-			case UISWTViewEvent.TYPE_INITIALIZE:{
-				
-				initialise((Composite)event.getData());
-				
-				break;
-			}
-			case UISWTViewEvent.TYPE_CLOSE:
-			case UISWTViewEvent.TYPE_DESTROY:{
-				
-				try{
-					destroy();
-					
-				}finally{
-					
-					created = false;
-				}
-				
-				break;
-			}
-		}
-		
-		return true;
-	}
-	
-	protected void
-	initialise(
-		Composite	_composite )
-	{
-		composite	= _composite;
-		
-		Composite main = new Composite(composite, SWT.NONE);
-		GridLayout layout = new GridLayout();
-		layout.numColumns = 1;
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		main.setLayout(layout);
-		GridData grid_data = new GridData(GridData.FILL_BOTH );
-		main.setLayoutData(grid_data);
-		
-			// control
-		
-		Composite control = new Composite(main, SWT.NONE);
-		layout = new GridLayout();
-		layout.numColumns = 3;
-		layout.marginHeight = 4;
-		layout.marginWidth = 4;
-		control.setLayout(layout);
-
-		grid_data = new GridData(GridData.FILL_HORIZONTAL);
-		grid_data.horizontalSpan = 1;
-		control.setLayoutData(grid_data);
-
-				// start
-		
-			start_button = new Button( control, SWT.PUSH );
-				
-		 	Messages.setLanguageText( start_button, "ConfigView.section.start");
-		 	
-		 	start_button.addSelectionListener(
-		 		new SelectionAdapter()
-		 		{
-		 			public void
-		 			widgetSelected(
-		 				SelectionEvent e )
-		 			{
-		 				start_button.setEnabled( false );
-		 				
-		 				cancel_button.setEnabled( true );
-		 				
-		 				startTest();
-		 			}
-		 		});
-		 	
-		 		// cancel
-		 	
-		 	cancel_button = new Button( control, SWT.PUSH );
-		 	
-		 	Messages.setLanguageText( cancel_button, "UpdateWindow.cancel");
-		 	
-		 	cancel_button.addSelectionListener(
-		 		new SelectionAdapter()
-		 		{
-		 			public void
-		 			widgetSelected(
-		 				SelectionEvent e )
-		 			{
-		 				cancel_button.setEnabled( false );
-		 						 				
-		 				cancelTest();
-		 			}
-		 		});
-		
-		 	cancel_button.setEnabled( false );
-		 	
-			Composite options = new Composite(control, SWT.NONE);
-			layout = new GridLayout();
-			layout.numColumns 	 	= 3;
-			layout.marginHeight 	= 4;
-			layout.marginWidth 		= 4;
-			options.setLayout(layout);
-
-			grid_data = new GridData(GridData.FILL_HORIZONTAL);
-			options.setLayoutData(grid_data);
-
-			/*
-				Button opt1 = new Button( options, SWT.CHECK );
-
-				opt1.setText( "ping/route" );
-				
-				addOption( opt1, NetStatusPluginTester.TEST_PING_ROUTE );
-			*/
-				Button opt2 = new Button( options, SWT.CHECK );
-
-				opt2.setText( "outbound" );
-
-				addOption( opt2, NetStatusPluginTester.TEST_OUTBOUND, true );
-
-				Button opt3 = new Button( options, SWT.CHECK );
-
-				opt3.setText( "inbound" );
-
-				addOption( opt3, NetStatusPluginTester.TEST_INBOUND, true );
-
-				Button opt4 = new Button( options, SWT.CHECK );
-
-				opt4.setText( "nat/proxies" );
-
-				addOption( opt4, NetStatusPluginTester.TEST_NAT_PROXIES, true );
-
-				Button opt5 = new Button( options, SWT.CHECK );
-
-				opt5.setText( "BT connect" );
-
-				addOption( opt5, NetStatusPluginTester.TEST_BT_CONNECT, true );
-				
-				Button opt6 = new Button( options, SWT.CHECK );
-
-				opt6.setText( "IPv6" );
-
-				boolean ipv6_enabled = COConfigurationManager.getBooleanParameter( "IPV6 Enable Support" );
-				
-				addOption( opt6, NetStatusPluginTester.TEST_IPV6, ipv6_enabled );
-
-				
-			// log area
-		
-		log = new StyledText(main,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
-		grid_data = new GridData(GridData.FILL_BOTH);
-		grid_data.horizontalSpan = 1;
-		grid_data.horizontalIndent = 4;
-		log.setLayoutData(grid_data);
-		log.setIndent( 4 );
-	}
-	
-	protected void
-	addOption(
-		final Button		button,
-		final int			type,
-		boolean				enable )
-	{
-		final String	config = "test.option." + type;
-		
-		boolean	selected = plugin.getBooleanParameter( config, enable );
-		
-		if ( selected ){
-			
-			selected_tests |= type;
-			
-		}else{
-			
-			selected_tests &= ~type;
-		}
-		
-		if ( !enable ){
-			
-			button.setEnabled( false );
-		}
-		
-		button.setSelection( selected );
-		
-	 	button.addSelectionListener(
-		 		new SelectionAdapter()
-		 		{
-		 			public void
-		 			widgetSelected(
-		 				SelectionEvent e )
-		 			{
-		 				boolean selected = button.getSelection();
-		 				
-		 				if ( selected ){
-		 					
-		 					selected_tests |= type;
-		 					
-		 				}else{
-		 					
-		 					selected_tests &= ~type;
-		 				}
-		 				
-		 				plugin.setBooleanParameter( config, selected );
-		 			}
-		 		});
-	}
-			
-	protected void
-	startTest()
-	{
-		CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD,
-				new AzureusCoreRunningListener() {
-			public void azureusCoreRunning(AzureusCore core) {
-				startTestSupport(core);
-			}
-		});
-	}
-	
-	protected void
-	cancelTest()
-	{
-		new AEThread2( "NetStatus:cancel", true )
-			{
-				public void
-				run()
-				{
-					cancelTestSupport();
-				}
-			}.start();
-	}
-	
-	protected void
-	startTestSupport(AzureusCore core)
-	{
-		try{
-			synchronized( this ){
-				
-				if ( current_test != null ){
-					
-					Debug.out( "Test already running!!!!" );
-					
-					return;
-				}
-				
-				current_test = 
-					new NetStatusPluginTester(
-						plugin,
-						selected_tests,
-						new NetStatusPluginTester.loggerProvider()
-						{
-							public void 
-							log(
-								String str) 
-							{
-								println( str );
-							}
-							
-							public void 
-							logSuccess(
-								String str) 
-							{
-								try{
-									log_type = LOG_SUCCESS;
-									
-									println( str );
-									
-								}finally{
-									
-									log_type = LOG_NORMAL;
-								}
-							}
-							
-							public void 
-							logInfo(
-								String str) 
-							{
-								try{
-									log_type = LOG_INFO;
-									
-									println( str );
-									
-								}finally{
-									
-									log_type = LOG_NORMAL;
-								}
-							}
-							
-							public void 
-							logFailure(
-								String str) 
-							{
-								try{
-									log_type = LOG_ERROR;
-									
-									println( str );
-									
-								}finally{
-									
-									log_type = LOG_NORMAL;
-								}
-							}
-						});
-			}
-			
-			println( "Test starting", true );
-
-			current_test.run(core);			
-			
-			println( current_test.isCancelled()?"Test Cancelled":"Test complete" );
-			
-		}catch( Throwable e ){
-			
-		}finally{
-			
-			try{
-				Composite c = composite;
-				
-				if ( c != null && !c.isDisposed()){
-					
-					try{
-						c.getDisplay().asyncExec(
-							new Runnable()
-							{
-								public void
-								run()
-								{
-									if ( !start_button.isDisposed()){
-										
-										start_button.setEnabled( true );
-									}
-									
-									if ( !cancel_button.isDisposed()){
-										
-										cancel_button.setEnabled( false );
-									}
-								}
-							});
-						
-					}catch( Throwable e ){
-					}
-				}
-			}finally{
-				
-				synchronized( this ){
-
-					current_test.cancel();
-					
-					current_test = null;
-				}
-			}
-		}
-	}
-	
-	protected void
-	println(
-		String		str )
-	{
-		print( str + "\n", false );
-	}
-	
-	protected void
-	println(
-		String		str,
-		boolean		clear_first )
-	{
-		print( str + "\n", clear_first );
-	}
-	
-	protected void
-	print(
-		final String		str,
-		final boolean		clear_first )
-	{
-		plugin.log( str );
-		
-		if ( !( log.isDisposed() || log.getDisplay().isDisposed())){
-			
-			final int f_log_type = log_type;
-			
-			log.getDisplay().asyncExec(
-					new Runnable()
-					{
-						public void
-						run()
-						{
-							if ( log.isDisposed()){
-								
-								return;
-							}
-							
-							int	start;
-							
-							if ( clear_first ){
-							
-								start	= 0;
-								
-								log.setText( str );
-								
-							}else{
-							
-								start = log.getText().length();
-								
-								log.append( str );
-							}
-							
-							Color 	color;
-							
-							if ( f_log_type == LOG_NORMAL ){
-								
-								color = Colors.black;
-								
-							}else if ( f_log_type == LOG_SUCCESS ){
-								
-								color = Colors.green;
-								
-							}else if ( f_log_type == LOG_INFO ){
-								
-								color = Colors.blue;
-								
-							}else{
-								
-								color = Colors.red;
-							}
-							
-							StyleRange styleRange = new StyleRange();
-							styleRange.start = start;
-							styleRange.length = str.length();
-							styleRange.foreground = color;
-							log.setStyleRange(styleRange);
-							
-							log.setSelection( log.getText().length());
-						}
-					});
-		}
-	}
-	
-	protected void
-	cancelTestSupport()
-	{
-		synchronized( this ){
-			
-			if ( current_test != null ){
-				
-				println( "Cancelling test..." );
-				
-				current_test.cancel();
-			}
-		}
-	}
-	
-	protected void
-	destroy()
-	{
-		cancelTest();
-		
-		composite = null;
-	}
-}
+/*
+ * Created on Jan 30, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.plugins.net.netstatus.swt;
+
+import java.util.ArrayList;
+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.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+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.Group;
+import org.eclipse.swt.widgets.Label;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.ui.UIInstance;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
+import org.gudy.azureus2.ui.swt.mainwindow.Colors;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
+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.proxy.AEProxyFactory;
+import com.aelitis.azureus.plugins.net.netstatus.NetStatusPlugin;
+
+public class 
+NetStatusPluginView 
+	implements UISWTViewEventListener
+{
+	private NetStatusPlugin	plugin;
+	
+	private boolean		created = false;	
+
+	private Composite	composite;
+	private Button		start_button;
+	private Button		cancel_button;
+	private StyledText 	log;
+	
+	private int			selected_tests;
+	
+	private NetStatusPluginTester		current_test;
+	
+	private static final int LOG_NORMAL 	= 1;
+	private static final int LOG_SUCCESS 	= 2;
+	private static final int LOG_ERROR 		= 3;
+	private static final int LOG_INFO 		= 4;
+	
+	private int	log_type	= LOG_NORMAL;
+	
+	public
+	NetStatusPluginView(
+		NetStatusPlugin	_plugin,
+		UIInstance		_ui,
+		String			VIEW_ID )
+	{
+		plugin	= _plugin;
+		
+		((UISWTInstance)_ui).addView( UISWTInstance.VIEW_MAIN, VIEW_ID, this );
+	}
+	
+	public boolean 
+	eventOccurred(
+		UISWTViewEvent event )
+	{
+		switch( event.getType() ){
+
+			case UISWTViewEvent.TYPE_CREATE:{
+				
+				if ( created ){
+					
+					return( false );
+				}
+				
+				created = true;
+				
+				break;
+			}
+			case UISWTViewEvent.TYPE_INITIALIZE:{
+				
+				initialise((Composite)event.getData());
+				
+				break;
+			}
+			case UISWTViewEvent.TYPE_CLOSE:
+			case UISWTViewEvent.TYPE_DESTROY:{
+				
+				try{
+					destroy();
+					
+				}finally{
+					
+					created = false;
+				}
+				
+				break;
+			}
+		}
+		
+		return true;
+	}
+	
+	protected void
+	initialise(
+		Composite	_composite )
+	{
+		composite	= _composite;
+		
+		Composite main = new Composite(composite, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		main.setLayout(layout);
+		GridData grid_data = new GridData(GridData.FILL_BOTH );
+		main.setLayoutData(grid_data);
+		
+			// control
+		
+		Composite control = new Composite(main, SWT.NONE);
+		layout = new GridLayout();
+		layout.numColumns = 3;
+		layout.marginHeight = 4;
+		layout.marginWidth = 4;
+		control.setLayout(layout);
+
+		Label info = new Label( control, SWT.NULL );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL);
+		grid_data.horizontalSpan = 3;
+		info.setLayoutData( grid_data );
+		Messages.setLanguageText( info,  "label.test.internet" );
+		
+		grid_data = new GridData(GridData.FILL_HORIZONTAL);
+		grid_data.horizontalSpan = 1;
+		control.setLayoutData(grid_data);
+
+		List<Button> buttons = new ArrayList<Button>();
+		
+				// start
+		
+			start_button = new Button( control, SWT.PUSH );
+				
+			buttons.add( start_button );
+			
+		 	Messages.setLanguageText( start_button, "ConfigView.section.start");
+		 	
+		 	start_button.addSelectionListener(
+		 		new SelectionAdapter()
+		 		{
+		 			public void
+		 			widgetSelected(
+		 				SelectionEvent e )
+		 			{
+		 				start_button.setEnabled( false );
+		 				
+		 				cancel_button.setEnabled( true );
+		 				
+		 				startTest();
+		 			}
+		 		});
+		 	
+		 		// cancel
+		 	
+		 	cancel_button = new Button( control, SWT.PUSH );
+		 	
+		 	buttons.add( cancel_button );
+		 	
+		 	Messages.setLanguageText( cancel_button, "UpdateWindow.cancel");
+		 	
+		 	cancel_button.addSelectionListener(
+		 		new SelectionAdapter()
+		 		{
+		 			public void
+		 			widgetSelected(
+		 				SelectionEvent e )
+		 			{
+		 				cancel_button.setEnabled( false );
+		 						 				
+		 				cancelTest();
+		 			}
+		 		});
+		
+		 	cancel_button.setEnabled( false );
+		 	
+		 	Utils.makeButtonsEqualWidth( buttons );
+		 	
+			Group options = new Group(control, SWT.NONE);
+			layout = new GridLayout();
+			layout.numColumns 	 	= 4;
+			layout.marginHeight 	= 4;
+			layout.marginWidth 		= 4;
+			options.setLayout(layout);
+		 	Messages.setLanguageText( options, "label.test.types");
+
+
+			grid_data = new GridData(GridData.FILL_HORIZONTAL);
+			options.setLayoutData(grid_data);
+
+			/*
+				Button opt1 = new Button( options, SWT.CHECK );
+
+				opt1.setText( "ping/route" );
+				
+				addOption( opt1, NetStatusPluginTester.TEST_PING_ROUTE );
+			*/
+				Button opt = new Button( options, SWT.CHECK );
+
+				Messages.setLanguageText( opt, "label.outbound" );
+
+				addOption( opt, NetStatusPluginTester.TEST_OUTBOUND, true );
+
+				opt = new Button( options, SWT.CHECK );
+
+				Messages.setLanguageText( opt, "label.inbound" );
+
+				addOption( opt, NetStatusPluginTester.TEST_INBOUND, true );
+
+				opt = new Button( options, SWT.CHECK );
+
+				Messages.setLanguageText( opt, "label.nat.proxies" );
+
+				addOption( opt, NetStatusPluginTester.TEST_NAT_PROXIES, true );
+
+				opt = new Button( options, SWT.CHECK );
+
+				Messages.setLanguageText( opt, "label.bt.connect" );
+
+				addOption( opt, NetStatusPluginTester.TEST_BT_CONNECT, true );
+				
+				opt = new Button( options, SWT.CHECK );
+
+				opt.setText( "IPv6" );
+
+				boolean ipv6_enabled = COConfigurationManager.getBooleanParameter( "IPV6 Enable Support" );
+				
+				addOption( opt, NetStatusPluginTester.TEST_IPV6, ipv6_enabled );
+
+				opt = new Button( options, SWT.CHECK );
+
+				Messages.setLanguageText( opt, "label.vuze.services" );
+				
+				addOption( opt, NetStatusPluginTester.TEST_VUZE_SERVICES, true );
+
+				if ( Constants.isWindows || Constants.isOSX ){
+					
+					opt = new Button( options, SWT.CHECK );
+	
+					Messages.setLanguageText( opt, "label.indirect.connect" );
+					
+					boolean ic_enabled = AEProxyFactory.hasPluginProxy();
+	
+					addOption( opt, NetStatusPluginTester.TEST_PROXY_CONNECT, ic_enabled );
+				}
+				
+			// log area
+		
+		log = new StyledText(main,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+		grid_data = new GridData(GridData.FILL_BOTH);
+		grid_data.horizontalSpan = 1;
+		grid_data.horizontalIndent = 4;
+		log.setLayoutData(grid_data);
+		log.setIndent( 4 );
+		
+		ClipboardCopy.addCopyToClipMenu(
+				log,
+				new ClipboardCopy.copyToClipProvider()
+				{
+					public String 
+					getText() 
+					{
+						return( log.getText().trim());
+					}
+				});
+	}
+	
+	protected void
+	addOption(
+		final Button		button,
+		final int			type,
+		boolean				enable )
+	{
+		final String	config = "test.option." + type;
+		
+		boolean	selected = plugin.getBooleanParameter( config, enable );
+		
+		if ( selected && enable ){
+			
+			selected_tests |= type;
+			
+		}else{
+			
+			selected_tests &= ~type;
+		}
+		
+		if ( !enable ){
+			
+			button.setEnabled( false );
+		}
+		
+		button.setSelection( selected );
+		
+	 	button.addSelectionListener(
+		 		new SelectionAdapter()
+		 		{
+		 			public void
+		 			widgetSelected(
+		 				SelectionEvent e )
+		 			{
+		 				boolean selected = button.getSelection();
+		 				
+		 				if ( selected ){
+		 					
+		 					selected_tests |= type;
+		 					
+		 				}else{
+		 					
+		 					selected_tests &= ~type;
+		 				}
+		 				
+		 				plugin.setBooleanParameter( config, selected );
+		 			}
+		 		});
+	}
+			
+	protected void
+	startTest()
+	{
+		CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD,
+				new AzureusCoreRunningListener() {
+			public void azureusCoreRunning(AzureusCore core) {
+				startTestSupport(core);
+			}
+		});
+	}
+	
+	protected void
+	cancelTest()
+	{
+		new AEThread2( "NetStatus:cancel", true )
+			{
+				public void
+				run()
+				{
+					cancelTestSupport();
+				}
+			}.start();
+	}
+	
+	protected void
+	startTestSupport(AzureusCore core)
+	{
+		try{
+			synchronized( this ){
+				
+				if ( current_test != null ){
+					
+					Debug.out( "Test already running!!!!" );
+					
+					return;
+				}
+				
+				current_test = 
+					new NetStatusPluginTester(
+						plugin,
+						selected_tests,
+						new NetStatusPluginTester.loggerProvider()
+						{
+							public void 
+							log(
+								String 		str,
+								boolean		detailed )
+							{
+								if ( detailed && !plugin.isDetailedLogging()){
+									
+									return;
+								}
+								
+								println( str );
+							}
+							
+							public void 
+							logSuccess(
+								String str) 
+							{
+								try{
+									log_type = LOG_SUCCESS;
+									
+									println( str );
+									
+								}finally{
+									
+									log_type = LOG_NORMAL;
+								}
+							}
+							
+							public void 
+							logInfo(
+								String str) 
+							{
+								try{
+									log_type = LOG_INFO;
+									
+									println( str );
+									
+								}finally{
+									
+									log_type = LOG_NORMAL;
+								}
+							}
+							
+							public void 
+							logFailure(
+								String str) 
+							{
+								try{
+									log_type = LOG_ERROR;
+									
+									println( str );
+									
+								}finally{
+									
+									log_type = LOG_NORMAL;
+								}
+							}
+						});
+			}
+			
+			println( "Test starting", true );
+
+			current_test.run(core);			
+			
+			println( current_test.isCancelled()?"Test Cancelled":"Test complete" );
+			
+		}catch( Throwable e ){
+			
+		}finally{
+			
+			try{
+				Composite c = composite;
+				
+				if ( c != null && !c.isDisposed()){
+					
+					try{
+						c.getDisplay().asyncExec(
+							new Runnable()
+							{
+								public void
+								run()
+								{
+									if ( !start_button.isDisposed()){
+										
+										start_button.setEnabled( true );
+									}
+									
+									if ( !cancel_button.isDisposed()){
+										
+										cancel_button.setEnabled( false );
+									}
+								}
+							});
+						
+					}catch( Throwable e ){
+					}
+				}
+			}finally{
+				
+				synchronized( this ){
+
+					current_test.cancel();
+					
+					current_test = null;
+				}
+			}
+		}
+	}
+	
+	protected void
+	println(
+		String		str )
+	{
+		print( str + "\n", false );
+	}
+	
+	protected void
+	println(
+		String		str,
+		boolean		clear_first )
+	{
+		print( str + "\n", clear_first );
+	}
+	
+	protected void
+	print(
+		final String		str,
+		final boolean		clear_first )
+	{
+		plugin.log( str );
+		
+		if ( !( log.isDisposed() || log.getDisplay().isDisposed())){
+			
+			final int f_log_type = log_type;
+			
+			log.getDisplay().asyncExec(
+					new Runnable()
+					{
+						public void
+						run()
+						{
+							if ( log.isDisposed()){
+								
+								return;
+							}
+							
+							int	start;
+							
+							if ( clear_first ){
+							
+								start	= 0;
+								
+								log.setText( str );
+								
+							}else{
+							
+								start = log.getText().length();
+								
+								log.append( str );
+							}
+							
+							Color 	color;
+							
+							if ( f_log_type == LOG_NORMAL ){
+								
+								color = Colors.black;
+								
+							}else if ( f_log_type == LOG_SUCCESS ){
+								
+								color = Colors.green;
+								
+							}else if ( f_log_type == LOG_INFO ){
+								
+								color = Colors.blue;
+								
+							}else{
+								
+								color = Colors.red;
+							}
+							
+							StyleRange styleRange = new StyleRange();
+							styleRange.start = start;
+							styleRange.length = str.length();
+							styleRange.foreground = color;
+							log.setStyleRange(styleRange);
+							
+							log.setSelection( log.getText().length());
+						}
+					});
+		}
+	}
+	
+	protected void
+	cancelTestSupport()
+	{
+		synchronized( this ){
+			
+			if ( current_test != null ){
+				
+				println( "Cancelling test..." );
+				
+				current_test.cancel();
+			}
+		}
+	}
+	
+	protected void
+	destroy()
+	{
+		cancelTest();
+		
+		composite = null;
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/removerules/DownloadRemoveRulesPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/removerules/DownloadRemoveRulesPlugin.java
index a172340..29a7854 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/removerules/DownloadRemoveRulesPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/removerules/DownloadRemoveRulesPlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/sharing/hoster/ShareHosterPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/sharing/hoster/ShareHosterPlugin.java
index 2fe0946..4a12e55 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/sharing/hoster/ShareHosterPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/sharing/hoster/ShareHosterPlugin.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -26,6 +27,7 @@ package com.aelitis.azureus.plugins.sharing.hoster;
  *
  */
 
+import java.io.File;
 import java.util.*;
 
 import org.gudy.azureus2.plugins.*;
@@ -35,9 +37,15 @@ import org.gudy.azureus2.plugins.tracker.*;
 import org.gudy.azureus2.plugins.utils.DelayedTask;
 import org.gudy.azureus2.plugins.sharing.*;
 import org.gudy.azureus2.plugins.download.*;
-
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
 import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.TorrentUtils;
+
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManager;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
 
 public class 
 ShareHosterPlugin
@@ -168,7 +176,7 @@ ShareHosterPlugin
 				
 				if ( download == null ){
 					
-					new_download = download_manager.addNonPersistentDownload( torrent, item.getTorrentFile(), file_resource.getFile());
+					new_download = addDownload( resource, torrent, item.getTorrentFile(), file_resource.getFile());
 				}
 			}else if ( type == ShareResource.ST_DIR ){
 			
@@ -182,7 +190,7 @@ ShareHosterPlugin
 				
 				if ( download == null ){
 					
-					new_download = download_manager.addNonPersistentDownload( torrent, item.getTorrentFile(), dir_resource.getDir());
+					new_download = addDownload( resource, torrent, item.getTorrentFile(), dir_resource.getDir());
 				}
 			}
 			
@@ -282,6 +290,110 @@ ShareHosterPlugin
 		}
 	}
 	
+	private Download
+	addDownload(
+		ShareResource		resource,
+		final Torrent		torrent,
+		File				torrent_file,
+		File				data_file )
+		
+		throws DownloadException
+	{
+		Map<String,String>	properties  = resource.getProperties();
+		
+		final List<String>	networks 	= new ArrayList<String>();
+		final List<Tag>		tags		= new ArrayList<Tag>();
+		
+		if ( properties != null ){
+			
+			String nets = properties.get( ShareManager.PR_NETWORKS );
+			
+			if ( nets != null ){
+				
+				String[] bits = nets.split( "," );
+								
+				for ( String bit: bits ){
+			
+					bit = AENetworkClassifier.internalise( bit.trim());
+					
+					if ( bit != null ){
+						
+						networks.add( bit );
+					}
+				}
+			}
+			
+			String tags_str = properties.get( ShareManager.PR_TAGS );
+			
+			if ( tags_str != null ){
+				
+				String[] bits = tags_str.split( "," );
+						
+				TagManager tm = TagManagerFactory.getTagManager();
+				
+				for ( String bit: bits ){
+			
+					try{
+						long tag_uid = Long.parseLong( bit.trim());
+						
+						Tag tag = tm.lookupTagByUID( tag_uid );
+						
+						if ( tag != null ){
+							
+							tags.add( tag );
+						}
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+				}
+			}
+		}	
+				
+		DownloadWillBeAddedListener dwbal = null; 
+
+		if ( networks.size() > 0 ){
+			
+			dwbal = 
+				new DownloadWillBeAddedListener()
+				{		
+					public void 
+					initialised(
+						Download download )
+					{
+						if ( Arrays.equals( download.getTorrentHash(), torrent.getHash())){ 
+						
+							PluginCoreUtils.unwrap( download ).getDownloadState().setNetworks( networks.toArray( new String[networks.size()]));
+						}
+					}
+				};
+		
+			download_manager.addDownloadWillBeAddedListener( dwbal );
+		}
+		
+		try{
+			Download download = download_manager.addNonPersistentDownload( torrent, torrent_file, data_file );
+
+			if ( tags.size() > 0 ){
+				
+				org.gudy.azureus2.core3.download.DownloadManager dm = PluginCoreUtils.unwrap( download );
+				
+				for ( Tag tag: tags ){
+					
+					tag.addTaggable( dm );
+				}
+			}
+			return( download );		
+			
+		}finally{
+			
+			if ( dwbal != null ){
+				
+				download_manager.removeDownloadWillBeAddedListener( dwbal );
+			}
+		}
+	}
+	
 	protected void
 	canResourceBeDeleted(
 		ShareResource	resource )
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/always/RunEverythingPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/always/RunEverythingPlugin.java
index 61d0796..417cbdf 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/always/RunEverythingPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/always/RunEverythingPlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/DefaultRankCalculator.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/DefaultRankCalculator.java
index af90866..08d5694 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/DefaultRankCalculator.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/DefaultRankCalculator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.startstoprules.defaultplugin;
@@ -528,88 +525,101 @@ public class DefaultRankCalculator implements DownloadManagerStateAttributeListe
 	public int recalcSeedingRank() {
 		try {
 			downloadData_this_mon.enter();
+			
+			int	oldSR = dl.getSeedingRank();
+			
+			int newSR = _recalcSeedingRankSupport( oldSR );
+			
+			if ( newSR != oldSR ){
+				
+				dl.setSeedingRank( newSR );
+			}
+			return( newSR );
+			
+		} finally {
+
+			downloadData_this_mon.exit();
+		}
+	}
+	
+	private int _recalcSeedingRankSupport( int oldSR ) {
 
-			sExplainSR = "";
+		sExplainSR = "";
 
-			int oldSR = dl.getSeedingRank();
-			DownloadStats stats = dl.getStats();
+		DownloadStats stats = dl.getStats();
 
-			int newSR = 0;
+		int newSR = 0;
 
-			// make undownloaded sort to top so they can start first.
-			if (!dl.isComplete()) {
-				newSR = SR_COMPLETE_STARTS_AT + (10000 - dl.getPosition());
-				dl.setSeedingRank(newSR);
-				// make sure we capture FP being turned off when torrent does from
-				// complete to incomplete
-				isFirstPriority();
-				if ( rules.bDebugLog ){
-					sExplainSR += "  not complete. SetSR " + newSR + "\n";
-				}
-				return newSR;
+		// make undownloaded sort to top so they can start first.
+		if (!dl.isComplete()) {
+			newSR = SR_COMPLETE_STARTS_AT + (10000 - dl.getPosition());
+			// make sure we capture FP being turned off when torrent does from
+			// complete to incomplete
+			isFirstPriority();
+			if ( rules.bDebugLog ){
+				sExplainSR += "  not complete. SetSR " + newSR + "\n";
 			}
+			return newSR;
+		}
 
-			// here we are seeding
+		// here we are seeding
 
-			lastModifiedShareRatio = stats.getShareRatio();
-			DownloadScrapeResult sr = dl.getAggregatedScrapeResult();
-			lastModifiedScrapeResultPeers = rules.calcPeersNoUs(dl,sr);
-			lastModifiedScrapeResultSeeds = rules.calcSeedsNoUs(dl,sr);
+		lastModifiedShareRatio = stats.getShareRatio();
+		DownloadScrapeResult sr = dl.getAggregatedScrapeResult();
+		lastModifiedScrapeResultPeers = rules.calcPeersNoUs(dl,sr);
+		lastModifiedScrapeResultSeeds = rules.calcSeedsNoUs(dl,sr);
 
-			boolean bScrapeResultsOk = (lastModifiedScrapeResultPeers > 0 || lastModifiedScrapeResultSeeds > 0
-					|| lastScrapeResultOk) && (lastModifiedScrapeResultPeers >= 0 && lastModifiedScrapeResultSeeds >= 0);
+		boolean bScrapeResultsOk = (lastModifiedScrapeResultPeers > 0 || lastModifiedScrapeResultSeeds > 0
+				|| lastScrapeResultOk) && (lastModifiedScrapeResultPeers >= 0 && lastModifiedScrapeResultSeeds >= 0);
 
-			if (!isFirstPriority()) {
-				// Check Ignore Rules
-				// never apply ignore rules to First Priority Matches
-				// (we don't want leechers circumventing the 0.5 rule)
+		if (!isFirstPriority()) {
+			// Check Ignore Rules
+			// never apply ignore rules to First Priority Matches
+			// (we don't want leechers circumventing the 0.5 rule)
 
-				//0 means unlimited
-				int	activeMaxSR = dlSpecificMaxShareRatio;
-				if ( activeMaxSR <= 0 ){
-					activeMaxSR = iIgnoreShareRatio;
-				}
-				if (activeMaxSR != 0 && lastModifiedShareRatio >= activeMaxSR
-						&& (lastModifiedScrapeResultSeeds >= iIgnoreShareRatio_SeedStart || !bScrapeResultsOk)
-						&& lastModifiedShareRatio != -1) {
-					
-					if (rules.bDebugLog)
-						sExplainSR += "  shareratio met: shareRatio(" + lastModifiedShareRatio
-								+ ") >= " + activeMaxSR + "\n";
-
-					dl.setSeedingRank(SR_SHARERATIOMET);
-					return SR_SHARERATIOMET;
-				} else if (rules.bDebugLog && activeMaxSR != 0
-						&& lastModifiedShareRatio >= activeMaxSR) {
-					sExplainSR += "  shareratio NOT met: ";
-					if (lastModifiedScrapeResultSeeds >= iIgnoreShareRatio_SeedStart) 
-						sExplainSR += lastModifiedScrapeResultSeeds + " below seed threshold of "
-								+ iIgnoreShareRatio_SeedStart;
-					sExplainSR += "\n";
-				}
+			//0 means unlimited
+			int	activeMaxSR = dlSpecificMaxShareRatio;
+			if ( activeMaxSR <= 0 ){
+				activeMaxSR = iIgnoreShareRatio;
+			}
+			if (activeMaxSR != 0 && lastModifiedShareRatio >= activeMaxSR
+					&& (lastModifiedScrapeResultSeeds >= iIgnoreShareRatio_SeedStart || !bScrapeResultsOk)
+					&& lastModifiedShareRatio != -1) {
+				
+				if (rules.bDebugLog)
+					sExplainSR += "  shareratio met: shareRatio(" + lastModifiedShareRatio
+							+ ") >= " + activeMaxSR + "\n";
+
+				return SR_SHARERATIOMET;
+			} else if (rules.bDebugLog && activeMaxSR != 0
+					&& lastModifiedShareRatio >= activeMaxSR) {
+				sExplainSR += "  shareratio NOT met: ";
+				if (lastModifiedScrapeResultSeeds >= iIgnoreShareRatio_SeedStart) 
+					sExplainSR += lastModifiedScrapeResultSeeds + " below seed threshold of "
+							+ iIgnoreShareRatio_SeedStart;
+				sExplainSR += "\n";
+			}
 
-				if (lastModifiedScrapeResultPeers == 0 && bScrapeResultsOk) {
-					// If both bIgnore0Peers and bFirstPriorityIgnore0Peer are on,
-					// we won't know which one it is at this point.
-					// We have to use the normal SR_0PEERS in case it isn't FP
-					if (bIgnore0Peers) {
-						if (rules.bDebugLog)
-							sExplainSR += "  Ignore 0 Peers criteria met\n";
+			if (lastModifiedScrapeResultPeers == 0 && bScrapeResultsOk) {
+				// If both bIgnore0Peers and bFirstPriorityIgnore0Peer are on,
+				// we won't know which one it is at this point.
+				// We have to use the normal SR_0PEERS in case it isn't FP
+				if (bIgnore0Peers) {
+					if (rules.bDebugLog)
+						sExplainSR += "  Ignore 0 Peers criteria met\n";
 
-						dl.setSeedingRank(SR_0PEERS);
-						return SR_0PEERS;
-					}
+					return SR_0PEERS;
+				}
 
 //					if (bFirstPriorityIgnore0Peer) {
 //						if (rules.bDebugLog)
 //							sExplainSR += "  Ignore 0 Peers criteria for FP met\n";
 //
-//						dl.setSeedingRank(SR_FP0PEERS);
 //						return SR_FP0PEERS;
 //					}
-				} else if (rules.bDebugLog && lastModifiedScrapeResultPeers == 0) {
-					sExplainSR += "  0 Peer Ignore rule NOT applied: Scrape invalid\n";
-				}
+			} else if (rules.bDebugLog && lastModifiedScrapeResultPeers == 0) {
+				sExplainSR += "  0 Peer Ignore rule NOT applied: Scrape invalid\n";
+			}
 
 //				if (numPeers != 0 && iFirstPriorityIgnoreSPRatio != 0
 //						&& numSeeds / numPeers >= iFirstPriorityIgnoreSPRatio) {
@@ -619,162 +629,150 @@ public class DefaultRankCalculator implements DownloadManagerStateAttributeListe
 //								+ ") >= Threshold("
 //								+ iFirstPriorityIgnoreSPRatio + ")\n";
 //
-//					dl.setSeedingRank(SR_FP_SPRATIOMET);
 //					return SR_FP_SPRATIOMET;
 //				}
 
-				//0 means disabled
-				if ((iIgnoreSeedCount != 0) && (lastModifiedScrapeResultSeeds >= iIgnoreSeedCount)) {
-					if (rules.bDebugLog)
-						sExplainSR += "  SeedCount Ignore rule met.  numSeeds("
-								+ lastModifiedScrapeResultSeeds + " >= iIgnoreSeedCount(" + iIgnoreSeedCount + ")\n"; 
+			//0 means disabled
+			if ((iIgnoreSeedCount != 0) && (lastModifiedScrapeResultSeeds >= iIgnoreSeedCount)) {
+				if (rules.bDebugLog)
+					sExplainSR += "  SeedCount Ignore rule met.  numSeeds("
+							+ lastModifiedScrapeResultSeeds + " >= iIgnoreSeedCount(" + iIgnoreSeedCount + ")\n"; 
 
-					dl.setSeedingRank(SR_NUMSEEDSMET);
-					return SR_NUMSEEDSMET;
-				}
+				return SR_NUMSEEDSMET;
+			}
 
-				// Ignore when P:S ratio met
-				// (More Peers for each Seed than specified in Config)
-				//0 means never stop
-				if (iIgnoreRatioPeers != 0 && lastModifiedScrapeResultSeeds != 0) {
-					float ratio = (float) lastModifiedScrapeResultPeers / lastModifiedScrapeResultSeeds;
-					if (ratio <= iIgnoreRatioPeers
-							&& lastModifiedScrapeResultSeeds >= iIgnoreRatioPeers_SeedStart) {
+			// Ignore when P:S ratio met
+			// (More Peers for each Seed than specified in Config)
+			//0 means never stop
+			if (iIgnoreRatioPeers != 0 && lastModifiedScrapeResultSeeds != 0) {
+				float ratio = (float) lastModifiedScrapeResultPeers / lastModifiedScrapeResultSeeds;
+				if (ratio <= iIgnoreRatioPeers
+						&& lastModifiedScrapeResultSeeds >= iIgnoreRatioPeers_SeedStart) {
 
-						if (rules.bDebugLog)
-							sExplainSR += "  P:S Ignore rule met.  ratio(" + ratio
-									+ " <= threshold(" + iIgnoreRatioPeers_SeedStart + ")\n";
+					if (rules.bDebugLog)
+						sExplainSR += "  P:S Ignore rule met.  ratio(" + ratio
+								+ " <= threshold(" + iIgnoreRatioPeers_SeedStart + ")\n";
 
-						dl.setSeedingRank(SR_RATIOMET);
-						return SR_RATIOMET;
-					}
+					return SR_RATIOMET;
 				}
 			}
+		}
 
-			// Never do anything with rank type of none
-			if (iRankType == StartStopRulesDefaultPlugin.RANK_NONE) {
-				if (rules.bDebugLog)
-					sExplainSR += "  Ranking Type set to none.. blanking seeding rank\n";
-				
-				// everythink ok!
-				dl.setSeedingRank(newSR);
+		// Never do anything with rank type of none
+		if (iRankType == StartStopRulesDefaultPlugin.RANK_NONE) {
+			if (rules.bDebugLog)
+				sExplainSR += "  Ranking Type set to none.. blanking seeding rank\n";
+			
+			// everythink ok!
+			return newSR;
+		}
+
+		if (iRankType == StartStopRulesDefaultPlugin.RANK_TIMED) {
+			if (bIsFirstPriority) {
+				newSR += SR_TIMED_QUEUED_ENDS_AT + 1;
 				return newSR;
 			}
 
-			if (iRankType == StartStopRulesDefaultPlugin.RANK_TIMED) {
-				if (bIsFirstPriority) {
-					newSR += SR_TIMED_QUEUED_ENDS_AT + 1;
-					dl.setSeedingRank(newSR);
-					return newSR;
-				}
-
-				int state = dl.getState();
-				if (state == Download.ST_STOPPING || state == Download.ST_STOPPED
-						|| state == Download.ST_ERROR) {
-					if (rules.bDebugLog)
-						sExplainSR += "  Download stopping, stopped or in error\n";
-					dl.setSeedingRank(SR_NOTQUEUED);
-					return SR_NOTQUEUED;
-				} else if (state == Download.ST_SEEDING || state == Download.ST_READY
-						|| state == Download.ST_WAITING || state == Download.ST_PREPARING) {
-					// force sort to top
-					long lMsElapsed = 0;
-					if (state == Download.ST_SEEDING && !dl.isForceStart())
-						lMsElapsed = (SystemTime.getCurrentTime() - stats
-								.getTimeStartedSeeding());
-
-					if (lMsElapsed >= minTimeAlive) {
-						dl.setSeedingRank(1);
-						if (oldSR > SR_TIMED_QUEUED_ENDS_AT) {
-							rules.requestProcessCycle(null);
-							if (rules.bDebugLog)
-								rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION,
-										"somethingChanged: TimeUp");
-						}
-					} else {
-						newSR = SR_TIMED_QUEUED_ENDS_AT + 1 + (int) (lMsElapsed / 1000);
-						dl.setSeedingRank(newSR);
-						if (oldSR <= SR_TIMED_QUEUED_ENDS_AT) {
-							rules.requestProcessCycle(null);
-							if (rules.bDebugLog)
-								rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION,
-										"somethingChanged: strange timer change");
-						}
+			int state = dl.getState();
+			if (state == Download.ST_STOPPING || state == Download.ST_STOPPED
+					|| state == Download.ST_ERROR) {
+				if (rules.bDebugLog)
+					sExplainSR += "  Download stopping, stopped or in error\n";
+				return SR_NOTQUEUED;
+			} else if (state == Download.ST_SEEDING || state == Download.ST_READY
+					|| state == Download.ST_WAITING || state == Download.ST_PREPARING) {
+				// force sort to top
+				long lMsElapsed = 0;
+				if (state == Download.ST_SEEDING && !dl.isForceStart())
+					lMsElapsed = (SystemTime.getCurrentTime() - stats
+							.getTimeStartedSeeding());
+
+				if (lMsElapsed >= minTimeAlive) {
+					newSR = 1;
+					if (oldSR > SR_TIMED_QUEUED_ENDS_AT) {
+						rules.requestProcessCycle(null);
+						if (rules.bDebugLog)
+							rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION,
+									"somethingChanged: TimeUp");
 					}
-					return newSR;
 				} else {
-					if (oldSR <= 0) {
-						newSR = SR_TIMED_QUEUED_ENDS_AT - dl.getPosition();
-						dl.setSeedingRank(newSR);
+					newSR = SR_TIMED_QUEUED_ENDS_AT + 1 + (int) (lMsElapsed / 1000);
+					if (oldSR <= SR_TIMED_QUEUED_ENDS_AT) {
 						rules.requestProcessCycle(null);
 						if (rules.bDebugLog)
 							rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION,
-									"somethingChanged: NotIgnored");
+									"somethingChanged: strange timer change");
 					}
-					return newSR;
 				}
+				return newSR;
+			} else { // ST_QUEUED
+				if (oldSR <= 0) {
+					newSR = SR_TIMED_QUEUED_ENDS_AT - dl.getPosition();
+					rules.requestProcessCycle(null);
+					if (rules.bDebugLog)
+						rules.log.log(dl.getTorrent(), LoggerChannel.LT_INFORMATION,
+								"somethingChanged: NotIgnored");
+				} else {
+					newSR = oldSR;
+				}
+				return newSR;
 			}
+		}
 
-			/** 
-			 * Add to SeedingRank based on Rank Type
-			 */
+		/** 
+		 * Add to SeedingRank based on Rank Type
+		 */
 
-			// SeedCount and SPRatio require Scrape Results..
-			if (bScrapeResultsOk) {
-				if ( iRankType == StartStopRulesDefaultPlugin.RANK_PEERCOUNT )
-				{
-					if(lastModifiedScrapeResultPeers > lastModifiedScrapeResultSeeds * 10)
-						newSR = 100 * lastModifiedScrapeResultPeers * 10;
-					else
-						newSR = (int)((long)100 * lastModifiedScrapeResultPeers * lastModifiedScrapeResultPeers/(lastModifiedScrapeResultSeeds+1));
-				}				
-				else if ((iRankType == StartStopRulesDefaultPlugin.RANK_SEEDCOUNT)
-						&& (iRankTypeSeedFallback == 0 || iRankTypeSeedFallback > lastModifiedScrapeResultSeeds))
-				{
-					if (lastModifiedScrapeResultSeeds < 10000)
-						newSR = 10000 - lastModifiedScrapeResultSeeds;
-					else
-						newSR = 1;
-					// shift over to make way for fallback
-					newSR *= SEEDONLY_SHIFT;
-
-				} else { // iRankType == RANK_SPRATIO or we are falling back
-					if (lastModifiedScrapeResultPeers != 0) {
-						if (lastModifiedScrapeResultSeeds == 0) {
-							if (lastModifiedScrapeResultPeers >= minPeersToBoostNoSeeds)
-								newSR += SPRATIO_BASE_LIMIT;
-						} else { // numSeeds != 0 && numPeers != 0
-							float x = (float) lastModifiedScrapeResultSeeds / lastModifiedScrapeResultPeers;
-							newSR += SPRATIO_BASE_LIMIT / ((x + 1) * (x + 1));
-						}
+		// SeedCount and SPRatio require Scrape Results..
+		if (bScrapeResultsOk) {
+			if ( iRankType == StartStopRulesDefaultPlugin.RANK_PEERCOUNT )
+			{
+				if(lastModifiedScrapeResultPeers > lastModifiedScrapeResultSeeds * 10)
+					newSR = 100 * lastModifiedScrapeResultPeers * 10;
+				else
+					newSR = (int)((long)100 * lastModifiedScrapeResultPeers * lastModifiedScrapeResultPeers/(lastModifiedScrapeResultSeeds+1));
+			}				
+			else if ((iRankType == StartStopRulesDefaultPlugin.RANK_SEEDCOUNT)
+					&& (iRankTypeSeedFallback == 0 || iRankTypeSeedFallback > lastModifiedScrapeResultSeeds))
+			{
+				if (lastModifiedScrapeResultSeeds < 10000)
+					newSR = 10000 - lastModifiedScrapeResultSeeds;
+				else
+					newSR = 1;
+				// shift over to make way for fallback
+				newSR *= SEEDONLY_SHIFT;
+
+			} else { // iRankType == RANK_SPRATIO or we are falling back
+				if (lastModifiedScrapeResultPeers != 0) {
+					if (lastModifiedScrapeResultSeeds == 0) {
+						if (lastModifiedScrapeResultPeers >= minPeersToBoostNoSeeds)
+							newSR += SPRATIO_BASE_LIMIT;
+					} else { // numSeeds != 0 && numPeers != 0
+						float x = (float) lastModifiedScrapeResultSeeds / lastModifiedScrapeResultPeers;
+						newSR += SPRATIO_BASE_LIMIT / ((x + 1) * (x + 1));
 					}
 				}
-			} else {
-				if (rules.bDebugLog)
-					sExplainSR += "  Can't calculate SR, no scrape results\n";
 			}
-			
-			if (staleCDOffset > 0) {
-				// every 10 minutes of not being active, subtract one SR
-				if (newSR > staleCDOffset) {
-					newSR -= staleCDOffset;
-					sExplainSR += "  subtracted " + staleCDOffset + " due to non-activeness\n";
-				} else {
-					staleCDOffset = 0; 
-				}
+		} else {
+			if (rules.bDebugLog)
+				sExplainSR += "  Can't calculate SR, no scrape results\n";
+		}
+		
+		if (staleCDOffset > 0) {
+			// every 10 minutes of not being active, subtract one SR
+			if (newSR > staleCDOffset) {
+				newSR -= staleCDOffset;
+				sExplainSR += "  subtracted " + staleCDOffset + " due to non-activeness\n";
+			} else {
+				staleCDOffset = 0; 
 			}
+		}
 
-			if (newSR < 0)
-				newSR = 1;
-
-			if (newSR != oldSR)
-				dl.setSeedingRank(newSR);
-			return newSR;
-		} finally {
+		if (newSR < 0)
+			newSR = 1;
 
-			downloadData_this_mon.exit();
-		}
-	} // recalcSeedingRank
+		return newSR;
+	} 
 
 	/** Does the torrent match First Priority criteria? 
 	 * @return FP State 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/DownloadingRankColumnListener.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/DownloadingRankColumnListener.java
index c9e8f3a..ae5e346 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/DownloadingRankColumnListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/DownloadingRankColumnListener.java
@@ -3,11 +3,12 @@
  * Created : Sep 27, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.startstoprules.defaultplugin;
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/SeedingRankColumnListener.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/SeedingRankColumnListener.java
index b55fbd1..123ab81 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/SeedingRankColumnListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/SeedingRankColumnListener.java
@@ -3,11 +3,12 @@
  * Created : Sep 27, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.startstoprules.defaultplugin;
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesDefaultPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesDefaultPlugin.java
index 06aed38..0323aae 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesDefaultPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesDefaultPlugin.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -192,6 +193,10 @@ public class StartStopRulesDefaultPlugin implements Plugin,
 	
 	private boolean bStopOnceBandwidthMet = false;
 
+	private boolean bStartNoMoreSeedsWhenUpLimitMet			= false;
+	private boolean	bStartNoMoreSeedsWhenUpLimitMetPercent	= true;
+	private int		bStartNoMoreSeedsWhenUpLimitMetSlack	= 95;
+	
 		// downloading params
 	
 	private boolean	bDownloadAutoReposition;
@@ -443,13 +448,24 @@ public class StartStopRulesDefaultPlugin implements Plugin,
 				"ConfigView.label.seeding.firstPriority.ignoreIdleHours", 24);
 		
 		// seeding subsection
+		
 		configModel.addIntParameter2("StartStopManager_iAddForSeedingDLCopyCount",
 				"ConfigView.label.seeding.addForSeedingDLCopyCount", 1);
+		
 		configModel.addIntParameter2("StartStopManager_iNumPeersAsFullCopy",
 				PREFIX_RES + "numPeersAsFullCopy", 0);
 		configModel.addIntParameter2("StartStopManager_iFakeFullCopySeedStart",
 				PREFIX_RES + "fakeFullCopySeedStart", 1);
 
+		configModel.addBooleanParameter2("StartStopManager_bStartNoMoreSeedsWhenUpLimitMet",
+				"ConfigView.label.seeding.StartStopManager_bStartNoMoreSeedsWhenUpLimitMet", false);
+		
+		configModel.addBooleanParameter2("StartStopManager_bStartNoMoreSeedsWhenUpLimitMetPercent",
+				"ConfigView.label.seeding.bStartNoMoreSeedsWhenUpLimitMetPercent", true);
+		
+		configModel.addIntParameter2("StartStopManager_bStartNoMoreSeedsWhenUpLimitMetSlack",
+				"ConfigView.label.seeding.bStartNoMoreSeedsWhenUpLimitMetSlack", 95);
+		
 		// downloading subsection
 		
 		PREFIX_RES = "ConfigView.label.downloading.";
@@ -859,7 +875,9 @@ public class StartStopRulesDefaultPlugin implements Plugin,
 			
 			bStopOnceBandwidthMet = plugin_config.getBooleanParameter("StartStopManager_bStopOnceBandwidthMet");
 			
-			
+			bStartNoMoreSeedsWhenUpLimitMet			= plugin_config.getBooleanParameter("StartStopManager_bStartNoMoreSeedsWhenUpLimitMet" );
+			bStartNoMoreSeedsWhenUpLimitMetPercent	= plugin_config.getBooleanParameter("StartStopManager_bStartNoMoreSeedsWhenUpLimitMetPercent" );
+			bStartNoMoreSeedsWhenUpLimitMetSlack	= plugin_config.getIntParameter("StartStopManager_bStartNoMoreSeedsWhenUpLimitMetSlack" );
 
 			boolean move_top = plugin_config.getBooleanParameter("StartStopManager_bNewSeedsMoveTop");
 			plugin_config.setBooleanParameter(
@@ -1097,6 +1115,8 @@ public class StartStopRulesDefaultPlugin implements Plugin,
 
 		int maxTorrents;
 		
+		boolean upLimitProhibitsNewSeeds;
+		
 		public int maxUploadSpeed()
 		{
 			return downloading == 0 ? globalUploadWhenSeedingLimit : globalUploadLimit;
@@ -1236,6 +1256,31 @@ public class StartStopRulesDefaultPlugin implements Plugin,
 				//System.out.println("maxTorrents = " + maxTorrents + " = " + iMaxUploadSpeed + " / " + minSpeedPerActive);
 				//System.out.println("totalTorrents = " + (activeSeedingCount + totalStalledSeeders + totalDownloading));
 			}
+			
+				// parg - added a new option here to simply not start any more seeds if upload limit (roughly) met
+			
+			long	up_limit = maxUploadSpeed();
+			
+			if ( bStartNoMoreSeedsWhenUpLimitMet && up_limit > 0 ){
+				
+				long current_up_kbps = download_manager.getStats().getSmoothedSendRate()/1024;
+				
+				long target;
+				
+				if ( bStartNoMoreSeedsWhenUpLimitMetPercent ){
+				
+					target = up_limit * bStartNoMoreSeedsWhenUpLimitMetSlack / 100;
+					
+				}else{
+					
+					target = up_limit - bStartNoMoreSeedsWhenUpLimitMetSlack;
+				}
+									
+				if ( current_up_kbps > target ){
+					
+					upLimitProhibitsNewSeeds = true;
+				}
+			}
 		} // constructor
 	}
 
@@ -2129,17 +2174,29 @@ public class StartStopRulesDefaultPlugin implements Plugin,
 					sDebugLine += "\n  Torrent is waiting or seeding";
 			}
 
+			boolean	up_limit_prohibits = false;
+			
+			if ( !okToQueue ){
+				
+				if ( totals.upLimitProhibitsNewSeeds ){
+						
+					okToQueue = true;
+						
+					up_limit_prohibits = true;
+				}
+			}
+			
 			// Note: First Priority are sorted to the top, 
 			//       so they will always start first
 
-			// XXX Change to waiting if queued and we have an open slot
+			// XXX   to waiting if queued and we have an open slot
 			if (!okToQueue
 					&& (state == Download.ST_QUEUED)
 					&& (totals.maxActive == 0 || vars.numWaitingOrSeeding < totals.maxSeeders) 
 					//&& (totals.maxActive == 0 || (activeSeedingCount + activeDLCount) < totals.maxActive) &&
 					&& (rank >= DefaultRankCalculator.SR_IGNORED_LESS_THAN)
 					&& (vars.stalledSeeders < maxStalledSeeding)
-					&& !vars.higherCDtoStart) {
+					&& !vars.higherCDtoStart){
 				try {
 					if (bDebugLog)
 						sDebugLine += "\n  restart: ok2Q=" + okToQueue
@@ -2178,7 +2235,13 @@ public class StartStopRulesDefaultPlugin implements Plugin,
 						sDebugLine += " at limit, stalledSeeders(" + vars.stalledSeeders
 								+ ") >= maxStalledSeeding("
 								+ maxStalledSeeding + ") ";
+						
+					} else if ( up_limit_prohibits ){
+						
+						sDebugLine += " upload rate prohibits starting new seeds";
+						
 					} else {
+					
 						sDebugLine += "huh? qd="
 								+ (state == Download.ST_QUEUED)
 								+ "; "
@@ -2228,10 +2291,17 @@ public class StartStopRulesDefaultPlugin implements Plugin,
 
 				boolean okToStop = bForceStop;
 				if (!okToStop) {
-					// break up the logic into variables to make more readable
-					boolean bOverLimit = vars.numWaitingOrSeeding > totals.maxSeeders
-				      || (!bActivelySeeding && vars.stalledSeeders > maxStalledSeeding)
-							|| (vars.numWaitingOrSeeding >= totals.maxSeeders && vars.higherCDtoStart);
+						// break up the logic into variables to make more readable
+						// parg: added the "or up-limit-prohibits & higherCD" case because if we're not starting any new
+						// seeds and we're below the seed limit we will never get to stop any lower priority seeds in order
+						// to cause the up-rate to fall to the point where we can start a higher priority seed...
+					
+					boolean bOverLimit = 
+							vars.numWaitingOrSeeding > totals.maxSeeders || 
+							(!bActivelySeeding && vars.stalledSeeders > maxStalledSeeding) || 
+							(	( 	vars.numWaitingOrSeeding >= totals.maxSeeders || 
+									totals.upLimitProhibitsNewSeeds ) && vars.higherCDtoStart);
+							
 					boolean bSeeding = state == Download.ST_SEEDING;
 
 					// not checking AND (at limit of seeders OR rank is set to ignore) AND
@@ -2240,6 +2310,8 @@ public class StartStopRulesDefaultPlugin implements Plugin,
 								!download.isMoving() &&
 								(bOverLimit || rank < DefaultRankCalculator.SR_IGNORED_LESS_THAN) &&
 								(globalRateAdjustedActivelySeeding || !bSeeding || (!globalRateAdjustedActivelySeeding && bSeeding));
+					
+						// PARG - the above last (..) in the condition always evaluates to TRUE... why oh why!
 
 					if (bDebugLog) {
 						if (okToStop) {
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesFPListener.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesFPListener.java
index ad1cda9..e4e7ed0 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesFPListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/StartStopRulesFPListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.plugins.startstoprules.defaultplugin;
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionDownloading.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionDownloading.java
index bea83d4..f692ba6 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionDownloading.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionDownloading.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.startstoprules.defaultplugin.ui.swt;
@@ -32,6 +30,7 @@ import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.config.BooleanParameter;
 import org.gudy.azureus2.ui.swt.config.ChangeSelectionActionPerformer;
 import org.gudy.azureus2.ui.swt.config.IntParameter;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
 
@@ -104,6 +103,8 @@ public class ConfigSectionDownloading implements UISWTConfigSection {
 			Utils.launch((String) ((Label) arg0.widget).getData());
 		}
 	});
+	ClipboardCopy.addCopyToClipMenu( linkLabel );
+	
     	// enable
     
     gridData = new GridData();
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionQueue.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionQueue.java
index 9656421..e1e5bb8 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionQueue.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionQueue.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.startstoprules.defaultplugin.ui.swt;
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding.java
index c4cad80..3eb2e59 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeeding.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.startstoprules.defaultplugin.ui.swt;
@@ -24,7 +22,6 @@ 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.config.COConfigurationManager;
 import org.gudy.azureus2.core3.util.AERunnable;
 import org.gudy.azureus2.ui.swt.Messages;
@@ -74,12 +71,61 @@ public class ConfigSectionSeeding implements UISWTConfigSection {
     gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL);
     cSeeding.setLayoutData(gridData);
 
-    // General Seeding Options
+    	// General Seeding Options
+    
     label = new Label(cSeeding, SWT.NULL);
     Messages.setLanguageText(label, "ConfigView.label.minSeedingTime");
     gridData = new GridData();
     new IntParameter(cSeeding, "StartStopManager_iMinSeedingTime").setLayoutData(gridData);
 
+    	// don't start more seeds
+    
+    gridData = new GridData();
+    gridData.horizontalSpan = 2;
+    final BooleanParameter dontStartMore = 
+    	new BooleanParameter(cSeeding, "StartStopManager_bStartNoMoreSeedsWhenUpLimitMet",
+                         "ConfigView.label.bStartNoMoreSeedsWhenUpLimitMet");
+    dontStartMore.setLayoutData(gridData);
+
+    
+    final Composite cDontStartOptions = new Composite(cSeeding, SWT.NULL);
+    layout = new GridLayout();
+    layout.numColumns = 3;
+    layout.marginWidth = 0;
+    layout.marginHeight = 0;
+    cDontStartOptions.setLayout(layout);
+    gridData = new GridData();
+    gridData.horizontalIndent = 15;
+    gridData.horizontalSpan = 2;
+    cDontStartOptions.setLayoutData(gridData);
+    
+	label = new Label(cDontStartOptions, SWT.NULL);
+	ImageLoader.getInstance().setLabelImage(label, "subitem");
+    gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+    label.setLayoutData(gridData);
+    
+    Label xlabel = new Label(cDontStartOptions, SWT.NULL);
+    Messages.setLanguageText(xlabel, "ConfigView.label.bStartNoMoreSeedsWhenUpLimitMetSlack");
+    gridData = new GridData();
+    IntParameter slack = new IntParameter(cDontStartOptions, "StartStopManager_bStartNoMoreSeedsWhenUpLimitMetSlack");
+    slack.setLayoutData(gridData);
+
+	label = new Label(cDontStartOptions, SWT.NULL);
+	ImageLoader.getInstance().setLabelImage(label, "subitem");
+	gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+    label.setLayoutData(gridData);
+    
+    gridData = new GridData();
+    gridData.horizontalSpan = 2;
+    BooleanParameter slackIsPercent = new BooleanParameter(cDontStartOptions, "StartStopManager_bStartNoMoreSeedsWhenUpLimitMetPercent",
+                         "ConfigView.label.bStartNoMoreSeedsWhenUpLimitMetPercent");
+    slackIsPercent.setLayoutData(gridData);
+
+    dontStartMore.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( slack, slackIsPercent ));
+    dontStartMore.setAdditionalActionPerformer(new ChangeSelectionActionPerformer( xlabel ));
+    
+    	// disconnect seeds when seeding
+    
     gridData = new GridData();
     gridData.horizontalSpan = 2;
     new BooleanParameter(cSeeding, "Disconnect Seed",
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingAutoStarting.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingAutoStarting.java
index 871230e..339ebee 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingAutoStarting.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingAutoStarting.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.startstoprules.defaultplugin.ui.swt;
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingFirstPriority.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingFirstPriority.java
index 033665b..a8cf277 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingFirstPriority.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingFirstPriority.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.startstoprules.defaultplugin.ui.swt;
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingIgnore.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingIgnore.java
index 89dfbc0..e81f53d 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingIgnore.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/ConfigSectionSeedingIgnore.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.startstoprules.defaultplugin.ui.swt;
diff --git a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/StartStopRulesDefaultPluginSWTUI.java b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/StartStopRulesDefaultPluginSWTUI.java
index e17a795..768607f 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/StartStopRulesDefaultPluginSWTUI.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/startstoprules/defaultplugin/ui/swt/StartStopRulesDefaultPluginSWTUI.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPlugin.java
index 33fd18d..4102603 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,13 @@
  * 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.tracker.dht;
 
 
+import java.net.InetSocketAddress;
 import java.net.URL;
 import java.net.UnknownHostException;
 import java.util.*;
@@ -62,6 +60,7 @@ import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
 import org.gudy.azureus2.plugins.ui.UIManager;
 import org.gudy.azureus2.plugins.ui.config.BooleanParameter;
 import org.gudy.azureus2.plugins.ui.config.ConfigSection;
+import org.gudy.azureus2.plugins.ui.config.IntParameter;
 import org.gudy.azureus2.plugins.ui.config.Parameter;
 import org.gudy.azureus2.plugins.ui.config.ParameterListener;
 import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
@@ -71,11 +70,7 @@ import org.gudy.azureus2.plugins.utils.UTTimerEvent;
 import org.gudy.azureus2.plugins.utils.UTTimerEventPerformer;
 import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
 
-import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
-import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager;
 import com.aelitis.azureus.core.networkmanager.NetworkManager;
-import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
-import com.aelitis.azureus.core.networkmanager.admin.NetworkAdminASN;
 import com.aelitis.azureus.core.tracker.TrackerPeerSource;
 import com.aelitis.azureus.core.tracker.TrackerPeerSourceAdapter;
 import com.aelitis.azureus.plugins.dht.*;
@@ -135,8 +130,8 @@ 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			= false;
-	private static boolean ADD_NETPOS_DERIVED_TARGETS		= false;
+	//private static final boolean ADD_ASN_DERIVED_TARGET			= false;
+	//private static final boolean ADD_NETPOS_DERIVED_TARGETS		= false;
 	
 	private static URL	DEFAULT_URL;
 	
@@ -187,11 +182,13 @@ DHTTrackerPlugin
 	
 	private AEMonitor			this_mon	= new AEMonitor( "DHTTrackerPlugin" );
 	
-	private DHTNetworkPosition[]	current_network_positions;
-	private long					last_net_pos_time;
+	//private DHTNetworkPosition[]	current_network_positions;
+	//private long					last_net_pos_time;
 	
 	private AESemaphore			initialised_sem = new AESemaphore( "DHTTrackerPlugin:init" );
 	
+	private DHTTrackerPluginAlt	alt_lookup_handler;
+	
 	private boolean				disable_put;
 	
 	{
@@ -285,6 +282,18 @@ DHTTrackerPlugin
 			System.out.println( "**** DHT Tracker default set for testing purposes ****" );
 		}
 		
+		BooleanParameter	enable_alt 	= config.addBooleanParameter2( "dhttracker.enable_alt", "dhttracker.enable_alt", true );
+		
+		IntParameter 		alt_port 	= config.addIntParameter2( "dhttracker.alt_port", "dhttracker.alt_port", 0, 0, 65535 );
+
+		enable_alt.addEnabledOnSelection( alt_port );
+		
+		config.createGroup( "dhttracker.alt_group", new Parameter[]{ enable_alt,alt_port });
+		
+		if ( enable_alt.getValue()){
+			
+			alt_lookup_handler = new DHTTrackerPluginAlt( alt_port.getValue());
+		}
 		
 		model.getActivity().setVisible( false );
 		model.getProgress().setVisible( false );
@@ -469,6 +478,8 @@ DHTTrackerPlugin
 			{
 				private int	ticks;
 				
+				private String 	prev_alt_status = "";
+				
 				public void 
 				perform(
 					UTTimerEvent event) 
@@ -481,6 +492,21 @@ DHTTrackerPlugin
 						
 						processNonRegistrations();
 					}
+					
+					if ( alt_lookup_handler != null ){
+						
+						if ( ticks % 4 == 0 ){
+							
+							String alt_status = alt_lookup_handler.getString();
+							
+							if ( !alt_status.equals( prev_alt_status )){
+				
+								log.log( "Alternative stats: " + alt_status );
+								
+								prev_alt_status = alt_status;
+							}
+						}
+					}
 				}
 			});
 	}
@@ -1730,6 +1756,10 @@ DHTTrackerPlugin
 		
 		final long[]	max_retry = { 0 };
 		
+		final boolean do_alt = 
+			alt_lookup_handler != null && 
+			(!( download.getFlag( Download.FLAG_LOW_NOISE ) || download.getFlag( Download.FLAG_LIGHT_WEIGHT )));
+		
 		int	num_done = 0;
 		
 		for (int i=0;i<targets.length;i++){
@@ -1751,9 +1781,11 @@ DHTTrackerPlugin
 			
 			num_done++;
 			
+			final boolean is_complete = isComplete( download );
+			
 			dht.get(target.getHash(), 
 					"Tracker announce for '" + download.getName() + "'" + target.getDesc(),
-					isComplete( download )?DHTPlugin.FLAG_SEEDING:DHTPlugin.FLAG_DOWNLOADING,
+					is_complete?DHTPlugin.FLAG_SEEDING:DHTPlugin.FLAG_DOWNLOADING,
 					NUM_WANT, 
 					target_type==REG_TYPE_FULL?ANNOUNCE_TIMEOUT:ANNOUNCE_DERIVED_TIMEOUT,
 					false, false,
@@ -1768,7 +1800,36 @@ DHTTrackerPlugin
 						int		seed_count;
 						int		leecher_count;
 						
-						boolean	complete;
+						volatile boolean	complete;
+						
+						{
+							if ( do_alt ){
+								
+								alt_lookup_handler.get( 
+										target.getHash(),
+										is_complete,
+										new DHTTrackerPluginAlt.LookupListener()
+										{
+											public void
+											foundPeer(
+												InetSocketAddress	address )
+											{
+												alternativePeerRead( address );
+											}
+											
+											public boolean
+											isComplete()
+											{
+												return( complete && addresses.size() > 5 );
+											}
+											
+											public void 
+											completed() 
+											{
+											}
+										});
+							}
+						}
 						
 						public boolean
 						diversified()
@@ -1782,6 +1843,50 @@ DHTTrackerPlugin
 						{
 						}
 						
+						private void
+						alternativePeerRead(
+							InetSocketAddress		peer )
+						{
+							boolean	try_injection = false;
+							
+							synchronized( this ){
+								
+								if ( complete ){
+									
+									try_injection = addresses.size() < 5;
+									
+								}else{
+								
+									try{
+										addresses.add( peer.getAddress().getHostAddress());
+										ports.add( peer.getPort());
+										udp_ports.add( 0 );
+										flags.add( null );
+										
+										is_seeds.add( false );
+										leecher_count++;
+										
+									}catch( Throwable e ){
+									}
+								}
+							}
+							
+							if ( try_injection ){
+								
+								PeerManager pm = download.getPeerManager();
+								
+								if ( pm != null ){
+									
+									pm.peerDiscovered( 
+										PEPeerSource.PS_DHT,
+										peer.getAddress().getHostAddress(), 
+										peer.getPort(),
+										0,
+										NetworkManager.getCryptoRequired( NetworkManager.CRYPTO_OVERRIDE_NONE ));
+								}
+							}
+						}
+						
 						public void
 						valueRead(
 							DHTPluginContact	originator,
@@ -2575,11 +2680,6 @@ DHTTrackerPlugin
 					
 					if ( !force ){
 						
-						if ( false && !dht.isReachable()){
-							
-							continue;
-						}
-						
 						if ( interesting_pub_max > 0 && interesting_published > interesting_pub_max ){
 							
 							continue;
@@ -3185,15 +3285,15 @@ DHTTrackerPlugin
 	protected class
 	RegistrationDetails
 	{
-		private static final int DERIVED_ACTIVE_MIN_MILLIS	= 2*60*60*1000;
+		//private static final int DERIVED_ACTIVE_MIN_MILLIS	= 2*60*60*1000;
 		
 		private putDetails			put_details;
 		private byte				flags;
 		private trackerTarget[]		put_targets;
 		private List<trackerTarget>	not_put_targets;
 		
-		private long			derived_active_start	= -1;
-		private long			previous_metric;
+		//private long			derived_active_start	= -1;
+		//private long			previous_metric;
 		
 		protected
 		RegistrationDetails(
@@ -3331,7 +3431,7 @@ DHTTrackerPlugin
     			
     			result.add( new trackerTarget( torrent_hash, REG_TYPE_FULL, "" ));
     		}
-    		
+ /*   		
     		if ( ADD_ASN_DERIVED_TARGET ){
     			
 	    	    NetworkAdminASN net_asn = NetworkAdmin.getSingleton().getCurrentASN();
@@ -3458,12 +3558,14 @@ DHTTrackerPlugin
     		
 	    		not_put_targets = skipped_targets;
     		}
+    		*/
     		
 	    	put_targets 	= result.toArray( new trackerTarget[result.size()]);
     	}
 	}
 	
-	protected DHTNetworkPosition[]
+	/*
+	private DHTNetworkPosition[]
 	getNetworkPositions()
 	{
 		DHTNetworkPosition[] res = current_network_positions;
@@ -3480,6 +3582,7 @@ DHTTrackerPlugin
 		
 		return( res );
 	}
+	*/
 	
 	private void
 	log(
@@ -3728,6 +3831,242 @@ DHTTrackerPlugin
 			});
 	}
 	
+	
+	public TrackerPeerSource[]
+	getTrackerPeerSources(
+		final Torrent		torrent )
+	{
+		TrackerPeerSource vuze_dht = 
+			new TrackerPeerSourceAdapter()
+			{
+				private volatile boolean	query_done;
+				private volatile int		status		= ST_INITIALISING;
+			
+				private volatile int		seeds 		= 0;
+				private volatile int		leechers 	= 0;
+				
+				
+				private void
+				fixup()
+				{
+					if ( initialised_sem.isReleasedForever()){
+						
+						synchronized( this ){
+							
+							if ( query_done ){
+								
+								return;
+							}
+							
+							query_done = true;
+							
+							status = ST_UPDATING;
+						}
+						
+						dht.get(	torrent.getHash(), 
+									"Availability lookup for '" + torrent.getName() + "'",
+									DHTPlugin.FLAG_DOWNLOADING,
+									NUM_WANT, 
+									ANNOUNCE_DERIVED_TIMEOUT,
+									false, true,
+									new DHTPluginOperationListener()
+									{
+										public void
+										starts(
+											byte[]				key )
+										{	
+										}
+										
+										public boolean
+										diversified()
+										{
+											return( true );
+										}
+										
+										public void
+										valueRead(
+											DHTPluginContact	originator,
+											DHTPluginValue		value )
+										{
+											if (( value.getFlags() & DHTPlugin.FLAG_DOWNLOADING ) == 1 ){
+												
+												seeds++;
+												
+											}else{
+												
+												leechers++;
+											}
+										}
+										
+										public void
+										valueWritten(
+											DHTPluginContact	target,
+											DHTPluginValue		value )
+										{
+											
+										}
+										
+										public void
+										complete(
+											byte[]				key,
+											boolean				timeout_occurred )
+										{
+											status		= ST_ONLINE;
+										}
+									});
+					}
+				}
+				
+				public int
+				getType()
+				{
+					return( TP_DHT );
+				}
+				
+				public String
+				getName()
+				{
+					return( "Vuze DHT" );
+				}
+				
+				public int
+				getStatus()
+				{
+					fixup();
+					
+					return( status );
+				}
+				
+				public int
+				getSeedCount()
+				{
+					fixup();
+					
+					int	result = seeds;
+					
+					if ( result == 0 && status != ST_ONLINE ){
+						
+						return( -1 );
+					}
+					
+					return( result );
+				}
+				
+				public int
+				getLeecherCount()
+				{
+					fixup();
+					
+					int	result = leechers;
+					
+					if ( result == 0 && status != ST_ONLINE ){
+						
+						return( -1 );
+					}
+					
+					return( result );
+				}
+				
+				public int
+				getPeers()
+				{
+					return( -1 );
+				}
+				
+				public boolean
+				isUpdating()
+				{
+					return( status == ST_UPDATING );
+				}
+
+			};
+			
+		if ( alt_lookup_handler != null ){
+			
+			TrackerPeerSource alt_dht = 
+					new TrackerPeerSourceAdapter()
+					{
+						private volatile int		status 	= ST_UPDATING;
+						private volatile int		peers 	= 0;
+						
+						{
+							alt_lookup_handler.get( 
+									torrent.getHash(),
+									false,
+									new DHTTrackerPluginAlt.LookupListener()
+									{
+										public void
+										foundPeer(
+											InetSocketAddress	address )
+										{
+											peers++;
+										}
+										
+										public boolean
+										isComplete()
+										{
+											return( false );
+										}
+										
+										public void
+										completed()
+										{
+											status = ST_ONLINE;
+										}
+									});
+						}
+					
+						
+						public int
+						getType()
+						{
+							return( TP_DHT );
+						}
+						
+						public String
+						getName()
+						{
+							return( "Mainline DHT" );
+						}
+						
+						public int
+						getStatus()
+						{
+							return( status );
+						}
+						
+						public int
+						getPeers()
+						{
+							int	result = peers;
+							
+							if ( result == 0 && status != ST_ONLINE ){
+								
+								return( -1 );
+							}
+							
+							return( result );
+						}
+						
+						public boolean
+						isUpdating()
+						{
+							return( status == ST_UPDATING );
+						}
+	
+					};
+		
+			return( new TrackerPeerSource[]{ vuze_dht, alt_dht } );
+			
+		}else{
+			
+			return( new TrackerPeerSource[]{ vuze_dht } );
+		}
+	}
+	
+	
+	
+	/*
 	public static List<Object[]>
 	getVivaldiTargets(
 		byte[]					torrent_hash,
@@ -3753,26 +4092,6 @@ DHTTrackerPlugin
 		
 		int[] triangle2 = slicer.findVertices( t2_x, t2_y );
 		
-		/*
-		
-		System.out.println( "NetPos: " + loc_str );						
-
-		String	tr1_str = "";
-		
-		for (int j=0;j<triangle1.length;j+=2 ){
-			
-			tr1_str += (j==0?"":",") + "(" + triangle1[j] + "," + triangle1[j+1] + ")";
-		}
-		
-		String	tr2_str = "";
-		
-		for (int j=0;j<triangle2.length;j+=2 ){
-			
-			tr2_str += (j==0?"":",") + "(" + triangle2[j] + "," + triangle2[j+1] + ")";
-		}
-		
-		System.out.println( "t1=" + tr1_str + ",t2=" + tr2_str );
-		*/
 		
 		for (int j=0;j<triangle1.length;j+=2 ){
 
@@ -3849,6 +4168,7 @@ DHTTrackerPlugin
 	{
 		return(Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)));
 	}
+	*/
 	
 	protected static class
 	putDetails
diff --git a/azureus2/src/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPluginAlt.java b/azureus2/src/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPluginAlt.java
new file mode 100644
index 0000000..12cec9b
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/plugins/tracker/dht/DHTTrackerPluginAlt.java
@@ -0,0 +1,914 @@
+/*
+ * Created on May 30, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.plugins.tracker.dht;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.AERunnable;
+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.ByteArrayHashMap;
+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.RandomUtils;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+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 com.aelitis.azureus.core.dht.transport.DHTTransportAlternativeContact;
+import com.aelitis.azureus.core.dht.transport.DHTTransportAlternativeNetwork;
+import com.aelitis.azureus.core.dht.transport.udp.impl.DHTUDPUtils;
+import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
+
+public class 
+DHTTrackerPluginAlt 
+{
+	private static final long	startup_time 	= SystemTime.getMonotonousTime();
+	private static final int	startup_grace	= 60*1000; 
+	
+	private static final int INITAL_DELAY	= 5*1000;
+	private static final int RPC_TIMEOUT	= 15*1000;
+	private static final int LOOKUP_TIMEOUT	= 90*1000;
+	private static final int LOOKUP_LINGER	= 5*1000;
+	
+	private static final int CONC_LOOKUPS	= 8;
+	private static final int NUM_WANT		= 32; 
+			
+	private static final int NID_CLOSENESS_LIMIT	= 10;
+	
+	
+	private final int		port;
+	
+	private final byte[]	NID = new byte[20];
+	
+	private DatagramSocket	current_server;
+	private Throwable		last_server_error;
+	
+	private ByteArrayHashMap<Object[]>	tid_map = new ByteArrayHashMap<Object[]>();
+
+	private TimerEventPeriodic	timer_event;
+	
+	private AsyncDispatcher		dispatcher = new AsyncDispatcher();
+	
+	private volatile long	lookup_count;
+	private volatile long	hit_count;
+	
+	private volatile long	packets_out;
+	private volatile long	packets_in;
+	private volatile long	bytes_out;
+	private volatile long	bytes_in;
+	
+	protected
+	DHTTrackerPluginAlt(
+		int		_port )
+	{
+		port	= _port;
+		
+			// there is no node id restriction for requests
+		
+		RandomUtils.nextBytes( NID );
+	}
+	
+	private DatagramSocket
+	getServer()
+	{
+		synchronized( this ){
+			
+			if ( current_server != null ){
+				
+				if ( current_server.isClosed()){
+					
+					current_server = null;
+					
+				}else{
+					
+					return( current_server );
+				}
+			}
+	
+			try{
+				final DatagramSocket server = new DatagramSocket(null);
+				
+				server.setReuseAddress(true);
+				
+				InetAddress bind_ip = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress();
+				
+				if ( bind_ip == null ){
+					
+					bind_ip = InetAddress.getByName( "127.0.0.1" );
+				}
+				
+				server.bind( new InetSocketAddress(bind_ip, port));
+							
+				current_server = server;
+				
+				last_server_error	= null;
+				
+				new AEThread2( "DHTPluginAlt:server" )
+				{
+					public void
+					run()
+					{
+						try{
+							while( true ){
+								
+								byte[] buffer = new byte[5120];
+								
+								DatagramPacket packet = new DatagramPacket( buffer, buffer.length );
+					
+								server.receive( packet );
+								
+								packets_in++;
+								
+								bytes_in += packet.getLength();
+								
+								Map<String, Object> map = new BDecoder().decodeByteArray(packet.getData(), 0, packet.getLength() ,false);
+								
+								//System.out.println( "got " + map );
+								
+								byte[]	tid = (byte[])map.get( "t" );
+								
+								if ( tid != null ){
+									
+									Object[] task;
+									
+									synchronized( tid_map ){
+					
+										task = tid_map.remove( tid );
+									}
+									
+									if ( task != null ){
+										
+										((GetPeersTask)task[0]).handleReply((InetSocketAddress)packet.getSocketAddress(), tid, map );
+									}
+								}
+							}
+						}catch( Throwable e ){
+							
+						}finally{
+							
+							try{
+								server.close();
+								
+							}catch( Throwable f ){
+							}
+							
+							synchronized( DHTTrackerPluginAlt.this ){
+								
+								if ( current_server == server ){
+									
+									current_server = null;
+								}
+							}
+						}
+					}
+				}.start();
+		
+				return( server );
+				
+			}catch( Throwable e ){
+				
+				last_server_error = e;
+				
+				return( null );
+			}
+		}
+	}
+	
+	protected void
+	get(
+		final byte[]				hash,
+		final boolean				no_seeds,
+		final LookupListener		listener )
+	{	
+		SimpleTimer.addEvent(
+			"altlookup.delay",
+			SystemTime.getCurrentTime() + INITAL_DELAY,
+			new TimerEventPerformer() 
+			{	
+				public void 
+				perform(
+					TimerEvent event) 
+				{
+					if ( listener.isComplete()){
+						
+						return;
+					}
+					
+					if ( dispatcher.getQueueSize() > 100 ){
+						
+						return;
+					}
+					
+					dispatcher.dispatch(
+						new AERunnable() {
+							
+							@Override
+							public void 
+							runSupport() 
+							{
+								getSupport( hash, no_seeds, listener );
+							}
+						});
+				}
+			});
+	}
+	
+	private void
+	getSupport(
+		final byte[]				hash,
+		final boolean				no_seeds,
+		final LookupListener		listener )
+	{
+		List<DHTTransportAlternativeContact> contacts;
+		
+		while( true ){
+			
+			if ( listener.isComplete()){
+				
+				return;
+			}
+			
+			contacts = DHTUDPUtils.getAlternativeContacts( DHTTransportAlternativeNetwork.AT_MLDHT_IPV4, 16 );
+			
+			if ( contacts.size() == 0 ){
+			
+				long now = SystemTime.getMonotonousTime();
+				
+				if ( now - startup_time < startup_grace ){
+					
+					try{
+						Thread.sleep(5000);
+						
+					}catch( Throwable e ){
+						
+					}
+					
+					continue;
+				}
+				
+				return;
+				
+			}else{
+			
+				break;
+			}
+		}
+		
+		DatagramSocket	server = getServer();
+		
+		if ( server == null ){
+			
+			return;
+		}
+		
+		lookup_count++;
+		
+		new GetPeersTask( server, contacts, hash, no_seeds, listener );
+	}
+	
+	private byte[]
+	send(
+		GetPeersTask		task,
+		DatagramSocket		server,
+		InetSocketAddress	address,
+		Map<String,Object>	map )
+		
+		throws IOException
+	{
+		byte[]	tid;
+		
+		while( true ){
+			
+			tid = new byte[4];
+			
+			RandomUtils.nextBytes( tid );
+	
+			synchronized( tid_map ){
+				
+				if ( tid_map.containsKey( tid )){
+					
+					continue;
+				}
+				
+				tid_map.put( tid, new Object[]{ task, SystemTime.getMonotonousTime() });
+				
+				if ( timer_event == null ){
+					
+					timer_event = 
+						SimpleTimer.addPeriodicEvent(
+							"dhtalttimer",
+							2500,
+							new TimerEventPerformer() 
+							{	
+								public void 
+								perform(
+									TimerEvent event) 
+								{
+									checkTimeouts();
+									
+									synchronized( tid_map ){
+										
+										if ( tid_map.size() == 0 ){
+											
+											timer_event.cancel();
+											
+											timer_event = null;
+										}
+									}
+								}
+							});
+				}
+			}
+			
+			try{
+				map.put( "t", tid );
+		
+				// System.out.println( "Sending: " + map );
+					
+				byte[] 	data_out = BEncoder.encode( map );
+				
+				DatagramPacket packet = new DatagramPacket( data_out, data_out.length);
+				
+				packet.setSocketAddress( address );
+		
+				packets_out++;
+				bytes_out += data_out.length;
+						
+				server.send( packet );
+				
+				return( tid );
+				
+			}catch( Throwable e ){
+				
+				try{
+					server.close();
+					
+				}catch( Throwable f ){
+					
+				}
+				
+				synchronized( tid_map ){
+
+					tid_map.remove( tid );
+				}
+				
+				if ( e instanceof IOException ){
+					
+					throw((IOException)e);
+					
+				}else{
+					
+					throw(new IOException(Debug.getNestedExceptionMessage(e)));
+				}
+			}
+		}
+	}
+	
+	private void
+	checkTimeouts()
+	{
+		long	now = SystemTime.getMonotonousTime();
+		
+		List<Object[]>	timeouts = null;
+		
+		synchronized( tid_map ){
+			
+			Iterator<byte[]> it = tid_map.keys().iterator();
+			
+			while( it.hasNext()){
+				
+				byte[] key = it.next();
+				
+				Object[]	value = tid_map.get( key );
+				
+				long time = (Long)value[1];
+				
+				if ( now - time > RPC_TIMEOUT ){
+					
+					tid_map.remove( key );
+					
+					if ( timeouts == null ){
+						
+						timeouts = new ArrayList<Object[]>();
+					}
+					
+					timeouts.add(new Object[]{ key, value[0] });
+				}
+			}
+		}
+		
+		if ( timeouts != null ){
+			
+			for ( Object[] entry: timeouts ){
+				
+				try{			
+					((GetPeersTask)entry[1]).handleTimeout((byte[])entry[0]);
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+		}
+	}
+	
+	protected String
+	getString()
+	{
+		return( "lookups=" + lookup_count + ", hits=" + hit_count +
+				", out=" + packets_out + "/" + DisplayFormatters.formatByteCountToKiBEtc( bytes_out ) + 
+				", in=" + packets_in + "/" + DisplayFormatters.formatByteCountToKiBEtc( bytes_in ) + 
+				(last_server_error==null?"":(", error=" + Debug.getNestedExceptionMessage( last_server_error ))));
+	}
+	
+	private class
+	GetPeersTask
+	{
+		private long				start_time	= SystemTime.getMonotonousTime();
+		
+		private DatagramSocket		server;
+		private byte[]				torrent_hash;
+		private boolean				no_seeds;
+		private LookupListener		listener;
+		
+		private List<DHTTransportAlternativeContact>	initial_contacts;
+		
+		private ByteArrayHashMap<InetSocketAddress>	active_queries = new ByteArrayHashMap<InetSocketAddress>();
+		
+		private Set<InetSocketAddress>		queried_nodes = new HashSet<InetSocketAddress>();
+		
+		Comparator<byte[]>	comparator = 
+			new Comparator<byte[]>()
+			{
+				public int 
+				compare(
+					byte[] o1, 
+					byte[] o2) 
+				{
+					for ( int i=0; i < o1.length;i++ ){
+						
+						byte b1 = o1[i];
+						byte b2 = o2[i]; 
+	
+						if ( b1 == b2 ){
+							
+							continue;
+						}
+						
+						byte t = torrent_hash[i];
+						
+						int d1 = (b1^t)&0xff;
+						int d2 = (b2^t)&0xff; 
+							
+						if ( d1 == d2 ){
+							
+							continue;
+						}
+	
+						if ( d1 < d2 ){
+							
+							return( -1 );
+							
+						}else{
+							
+							return( 1 );
+						}
+					}
+					
+					return( 0 );
+				}
+			};
+			
+		private TreeMap<byte[],InetSocketAddress>	to_query = new TreeMap<byte[], InetSocketAddress>( comparator );
+
+		private TreeMap<byte[],InetSocketAddress>	heard_from =
+				new TreeMap<byte[], InetSocketAddress>(
+					new Comparator<byte[]>()
+					{
+						public int 
+						compare(
+							byte[] o1, 
+							byte[] o2) 
+						{
+							return( -comparator.compare(o1, o2));
+						}
+					});
+		
+		private long	found_peer_time;
+		
+		private Set<InetSocketAddress>	found_peers = new HashSet<InetSocketAddress>();
+		
+		private int		query_count;
+		private int		timeout_count;
+		private int		reply_count;
+		
+		private boolean	completed;
+		private boolean	failed;
+		
+		private
+		GetPeersTask(
+			DatagramSocket								_server,
+			List<DHTTransportAlternativeContact>		_contacts,
+			byte[]										_torrent_hash,
+			boolean										_no_seeds,
+			LookupListener								_listener )
+		{
+			server			= _server;
+			torrent_hash	= _torrent_hash;
+			no_seeds		= _no_seeds;
+			listener		= _listener;
+			
+			initial_contacts = _contacts;
+			
+			tryQuery();
+		}
+		
+		private void
+		search(
+			InetSocketAddress	address )
+			
+			throws IOException
+		{			
+			if ( queried_nodes.contains( address )){
+					
+				return;
+			}
+				
+			queried_nodes.add( address );
+			
+			Map<String,Object> map = new HashMap<String,Object>();
+						
+			map.put( "q", "get_peers" );
+			map.put( "y", "q" );
+			
+			Map<String,Object> args = new HashMap<String,Object>();
+			
+			map.put( "a", args );
+			
+			args.put( "id", NID );
+			
+			args.put( "info_hash", torrent_hash );
+			
+			args.put( "noseed", new Long( no_seeds?1:0 ));
+					
+			byte[]	tid = send( this, server, address, map );
+				
+			query_count++;
+			
+			active_queries.put( tid, address );
+		}
+		
+		private void
+		tryQuery()
+		{
+			if ( listener.isComplete()){
+				
+				return;
+			}
+			
+			try{
+				synchronized( this ){
+					
+					if ( failed || active_queries.size() >= CONC_LOOKUPS ){
+						
+						return;
+					}
+					
+					long	now = SystemTime.getMonotonousTime();
+					
+					if ( now - start_time > LOOKUP_TIMEOUT ){
+						
+						return;
+					}
+					
+					if ( found_peer_time > 0 ){
+						
+						if ( found_peers.size() > NUM_WANT ){
+							
+							setCompleted();
+							
+							return;
+						}
+						
+						if ( now - found_peer_time > LOOKUP_LINGER ){
+							
+							setCompleted();
+							
+							return;
+						}
+					}
+					
+					try{
+						byte[]	limit_nid;
+						
+						if ( heard_from.size() >= NID_CLOSENESS_LIMIT ){
+							
+							limit_nid = heard_from.keySet().iterator().next();
+							
+						}else{
+							
+							limit_nid = null;
+						}
+						
+						Iterator<Map.Entry<byte[],InetSocketAddress>> query_it = to_query.entrySet().iterator();
+						
+						while( query_it.hasNext()){
+							
+							Map.Entry<byte[],InetSocketAddress> entry = query_it.next();
+							
+							query_it.remove();
+	
+							byte[]	nid = entry.getKey();
+							
+							if ( limit_nid != null && comparator.compare( limit_nid, nid ) <= 0 ){
+								
+								// System.out.println( "skipping " + ByteFormatter.encodeString( nid ) + ": limit=" + ByteFormatter.encodeString( limit_nid ) + "/" + ByteFormatter.encodeString( torrent_hash ));
+								
+								continue;
+							}
+							
+							// System.out.println( "searching " + ByteFormatter.encodeString( nid ));
+									
+							InetSocketAddress	address = entry.getValue();
+							
+							search( address );
+							
+							if ( active_queries.size() >= CONC_LOOKUPS ){
+								
+								return;
+							}
+						}
+						
+						if ( heard_from.size() < 10 ){
+							
+							Iterator<DHTTransportAlternativeContact> contact_it = initial_contacts.iterator();
+							
+							while( contact_it.hasNext()){
+								
+								DHTTransportAlternativeContact	contact = contact_it.next();
+								
+								contact_it.remove();
+								
+								Map<String,Object>	properties = contact.getProperties();
+								
+								byte[]	_a 	= (byte[])properties.get( "a" );
+								Long	_p	= (Long)properties.get( "p" );
+								
+								if ( _a != null && _p != null ){
+								
+									try{
+										InetSocketAddress address = new InetSocketAddress( InetAddress.getByAddress( _a ), _p.intValue());
+									
+										search( address );
+								
+										if ( active_queries.size() >= CONC_LOOKUPS ){
+											
+											return;
+										}
+									}catch( Throwable e ){
+										
+									}
+								}
+							}
+						}
+					}finally{
+						
+						if ( active_queries.size() == 0 ){
+							
+							setCompleted();
+						}
+					}
+				}
+			}catch( Throwable e ){
+				
+				synchronized( this ){
+				
+					setFailed();
+				}
+			}finally{
+				
+				// log();
+			}
+		}
+		
+		private void
+		handleTimeout(
+			byte[]	tid )
+		{
+			synchronized( this ){
+				
+				active_queries.remove( tid );
+				
+				timeout_count++;
+			}
+			
+			tryQuery();
+		}
+		
+		private void
+		handleReply(
+			InetSocketAddress		from,
+			byte[]					tid,
+			Map<String,Object>		map )
+			
+			throws IOException
+		{
+			Map<String,Object> reply = (Map<String,Object>)map.get( "r" );
+
+			synchronized( this ){
+				
+				active_queries.remove( tid );
+				
+				reply_count++;
+				
+				if ( reply == null ){
+					
+						// error response, ignore
+					
+					return;
+				}
+				
+				heard_from.put((byte[])reply.get( "id" ), from );
+				
+				if ( heard_from.size() > NID_CLOSENESS_LIMIT ){
+					
+					Iterator<byte[]> it = heard_from.keySet().iterator();
+					
+					it.next();
+					
+					it.remove();
+				}
+			}		
+			
+			ArrayList<byte[]>	values = ( ArrayList<byte[]>)reply.get( "values" );
+		
+			if ( values != null ){
+				
+				synchronized( this ){
+					
+					if ( found_peer_time == 0 ){
+						
+						found_peer_time	= SystemTime.getMonotonousTime();
+						
+					}
+				}
+				
+				for ( byte[] value: values ){
+					
+					try{
+						ByteBuffer bb = ByteBuffer.wrap( value );
+						
+						byte[]	address = new byte[value.length-2];
+						
+						bb.get( address );
+						
+						int	port = bb.getShort()&0xffff;
+						
+						InetSocketAddress addr = new InetSocketAddress( InetAddress.getByAddress(address), port );
+						
+						synchronized( this ){
+						
+							if ( found_peers.contains( addr )){
+								
+								continue;
+							}
+							
+							found_peers.add( addr );
+						}
+						
+						hit_count++;
+						
+						listener.foundPeer( addr );
+						
+					}catch( Throwable e ){
+					}
+				}
+			}
+			
+			byte[]	nodes 	= (byte[])reply.get( "nodes" );
+			byte[]	nodes6 	= (byte[])reply.get( "nodes6" );
+		
+			if ( nodes != null ){
+			
+				int	entry_size = 20+4+2;
+				
+				for ( int i=0;i<nodes.length;i+=entry_size ){
+					
+					ByteBuffer bb = ByteBuffer.wrap(nodes, i, entry_size );
+
+					byte[] nid = new byte[20];
+					
+					bb.get(nid);
+
+					byte[] address = new byte[ 4 ];
+				
+					bb.get( address );
+
+					int port = bb.getShort()&0xffff;
+					
+					try{
+						InetSocketAddress addr = new InetSocketAddress( InetAddress.getByAddress(address), port );
+				
+						synchronized( this ){
+
+							if ( !queried_nodes.contains( addr )){
+								
+								to_query.put( nid, addr );
+							}
+						}
+					}catch( Throwable e ){
+					}
+				}
+			}
+			
+			tryQuery();
+		}
+		
+		private void
+		setCompleted()
+		{
+			if ( !completed ){
+				
+				completed = true;
+				
+				listener.completed();
+			}
+		}
+		
+		private void
+		setFailed()
+		{
+			failed = true;
+			
+			setCompleted();
+		}
+		
+		private void
+		log()
+		{
+			System.out.println( 
+				ByteFormatter.encodeString( torrent_hash ) + 
+				": send=" + query_count + 
+				", recv=" + reply_count + 
+				", t/o=" + timeout_count + 
+				", elapsed=" + (SystemTime.getMonotonousTime() - start_time ) + 
+				", toq=" + to_query.size() + 
+				", found=" + found_peers.size());
+			
+			synchronized( this ){
+				
+				for ( byte[] nid: heard_from.keySet()){
+					
+					System.out.println( "    " + ByteFormatter.encodeString( nid ));
+				}
+			}
+		}
+	}
+	
+	
+	protected interface
+	LookupListener
+	{
+		public void
+		foundPeer(
+			InetSocketAddress	address );
+		
+		public boolean
+		isComplete();
+		
+		public void
+		completed();
+	}
+}
diff --git a/azureus2/src/com/aelitis/azureus/plugins/tracker/local/LocalTrackerPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/tracker/local/LocalTrackerPlugin.java
index 871727c..7d755be 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/tracker/local/LocalTrackerPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/tracker/local/LocalTrackerPlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -628,7 +625,7 @@ LocalTrackerPlugin
 
 		if ( download.isComplete() && is_seed ){
 			
-			return( is_seed?1:0 );
+			return( 1 );
 		}
 		
 		PeerManager	peer_manager = download.getPeerManager();
diff --git a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMapping.java b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMapping.java
index f3e21bb..dbf9183 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMapping.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMapping.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingListener.java b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingListener.java
index 1f4e812..51f1590 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingManager.java b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingManager.java
index c7e6cf4..a4b9e0d 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingManager.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingManagerListener.java b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingManagerListener.java
index 4e1cfc1..f42f593 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingManagerListener.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPMappingManagerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPPlugin.java b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPPlugin.java
index 63f6ddd..87bc6c1 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPPlugin.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPPlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPPluginService.java b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPPluginService.java
index 5c1cabe..717142b 100644
--- a/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPPluginService.java
+++ b/azureus2/src/com/aelitis/azureus/plugins/upnp/UPnPPluginService.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/IUIIntializer.java b/azureus2/src/com/aelitis/azureus/ui/IUIIntializer.java
index 144db9e..99ddb30 100644
--- a/azureus2/src/com/aelitis/azureus/ui/IUIIntializer.java
+++ b/azureus2/src/com/aelitis/azureus/ui/IUIIntializer.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 29, 2006 3:06:06 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/InitializerListener.java b/azureus2/src/com/aelitis/azureus/ui/InitializerListener.java
index 2b26a74..d4b75cb 100644
--- a/azureus2/src/com/aelitis/azureus/ui/InitializerListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/InitializerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/Main.java b/azureus2/src/com/aelitis/azureus/ui/Main.java
index b4edbe4..bcf6340 100644
--- a/azureus2/src/com/aelitis/azureus/ui/Main.java
+++ b/azureus2/src/com/aelitis/azureus/ui/Main.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus2/src/com/aelitis/azureus/ui/UIFunctions.java b/azureus2/src/com/aelitis/azureus/ui/UIFunctions.java
index e65ef99..dc74f96 100644
--- a/azureus2/src/com/aelitis/azureus/ui/UIFunctions.java
+++ b/azureus2/src/com/aelitis/azureus/ui/UIFunctions.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 14, 2006 9:02:55 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,17 +13,14 @@
  * 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;
 
 
-import org.gudy.azureus2.core3.torrent.TOTorrent;
 import org.gudy.azureus2.core3.torrent.impl.TorrentOpenOptions;
 
 import com.aelitis.azureus.core.AzureusCoreComponent;
+import com.aelitis.azureus.core.tag.Tag;
 import com.aelitis.azureus.ui.common.updater.UIUpdater;
 import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 
@@ -35,31 +32,30 @@ import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 public interface UIFunctions
 	extends AzureusCoreComponent
 {
-	public static final String	MAIN_WINDOW_NAME		= "Vuze Bittorrent Client";
-	public static final String	MAIN_WINDOW_NAME_PLUS	= "Vuze Plus Bittorrent Client";
-	
+	public static final String	MAIN_WINDOW_NAME 		= System.getProperty( "azureus.window.title", "Vuze Bittorrent Client" );
+	public static final String	MAIN_WINDOW_NAME_PLUS 	= System.getProperty( "azureus.window.title", "Vuze Plus Bittorrent Client" );
+		
 	public static int STATUSICON_NONE = 0;
 
 	public static int STATUSICON_WARNING = 1;
 
 	public static int STATUSICON_ERROR = 2;
 
-	
-	public static final int VIEW_CONSOLE = 0;
+	/** @deprecated Used by azburn */
+	public static final int VIEW_MYTORRENTS = 8;
+	/** @deprecated Used by rcm */
 	public static final int VIEW_CONFIG = 4;
+	/** @deprecated Used by rcm */
 	public static final int VIEW_DM_DETAILS = 5;
-	public static final int VIEW_DM_MULTI_OPTIONS = 6;
-	public static final int VIEW_MYSHARES = 7;
-	public static final int VIEW_MYTORRENTS = 8;
-	public static final int VIEW_MYTRACKER = 9;
-	public static final int VIEW_ALLPEERS = 10;
-	public static final int VIEW_PEERS_STATS = 12;
-	public static final int VIEW_TAG = 13;
-	public static final int VIEW_TAGS_OVERVIEW = 14;
 
+	
 	public static final int ACTION_FULL_UPDATE				= 1;	// arg: String - url; response Boolean - ok
 	public static final int ACTION_UPDATE_RESTART_REQUEST	= 2;	// arg: Boolean - true->no auto-select response Boolean - ok
 	
+	public static final int VS_TRAY_ONLY				= 1;		// low-resource minimized state
+	public static final int VS_MINIMIZED_TO_TRAY		= 2;		// minimized to tray only
+	public static final int VS_MINIMIZED				= 3;		// normal minimized
+	public static final int VS_ACTIVE					= 4;		// active
 
 	/**
 	 * Bring main window to the front
@@ -75,6 +71,8 @@ public interface UIFunctions
 	 */
 	void bringToFront(boolean tryTricks);
 	
+	public int getVisibilityState();
+	
 	/**
 	 * Change/Refresh the language of the UI
 	 */
@@ -127,10 +125,7 @@ public interface UIFunctions
 	public UIUpdater getUIUpdater();
 
 	/**
-	 * @param viewID
-	 * @param data
-	 *
-	 * @since 3.1.1.1
+	 * @deprecated Use {@link #getMDI()}
 	 */
 	void openView(int viewID, Object datasource);
 	
@@ -196,6 +191,15 @@ public interface UIFunctions
 		boolean 	launch_already_checked, 
 		boolean 	complete_only );
 
+	public static final String 	OTO_DEFAULT_TO_STOPPED			= "defaultStopped";		// Boolean
+	public static final boolean OTO_DEFAULT_TO_STOPPED_DEFAULT	= false;
+	
+	public static final String 	OTO_FORCE_OPEN					= "forceOpen";			// Boolean
+	public static final boolean OTO_FORCE_OPEN_DEFAULT			= false;
+	
+	public static final String 	OTO_HIDE_ERRORS					= "hideErrors";			// Boolean
+	public static final boolean OTO_HIDE_ERRORS_DEFAULT			= false;
+	
 	/**
 	 * Opens the Torrent Add Options Window, if configured to
 	 * 
@@ -205,4 +209,12 @@ public interface UIFunctions
 	public boolean addTorrentWithOptions(boolean force, TorrentOpenOptions torrentOptions);
 
 	public void showErrorMessage(String keyPrefix, String details, String[] textParams); 
+	
+	public void showCreateTagDialog(TagReturner tagReturner);
+	
+	public interface 
+	TagReturner 
+	{
+		public void returnedTags(Tag[] tags);
+	}
 }
diff --git a/azureus2/src/com/aelitis/azureus/ui/UIFunctionsManager.java b/azureus2/src/com/aelitis/azureus/ui/UIFunctionsManager.java
index 995b975..a60313f 100644
--- a/azureus2/src/com/aelitis/azureus/ui/UIFunctionsManager.java
+++ b/azureus2/src/com/aelitis/azureus/ui/UIFunctionsManager.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 12, 2006 2:47:29 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/UIFunctionsUserPrompter.java b/azureus2/src/com/aelitis/azureus/ui/UIFunctionsUserPrompter.java
index 6279c09..cc6caa0 100644
--- a/azureus2/src/com/aelitis/azureus/ui/UIFunctionsUserPrompter.java
+++ b/azureus2/src/com/aelitis/azureus/ui/UIFunctionsUserPrompter.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
@@ -112,6 +109,12 @@ public interface UIFunctionsUserPrompter
 	void setRememberText(String rememberText);
 
 	/**
+	 * @since 5601
+	 * @param button
+	 */
+	void setRememberOnlyIfButton( int button );
+	
+	/**
 	 * @param url
 	 *
 	 * @since 3.0.0.9
diff --git a/azureus2/src/com/aelitis/azureus/ui/UIStatusTextClickListener.java b/azureus2/src/com/aelitis/azureus/ui/UIStatusTextClickListener.java
index 5b4f63b..746c8d0 100644
--- a/azureus2/src/com/aelitis/azureus/ui/UIStatusTextClickListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/UIStatusTextClickListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus2/src/com/aelitis/azureus/ui/UserPrompterResultListener.java b/azureus2/src/com/aelitis/azureus/ui/UserPrompterResultListener.java
index 3c6aba3..ba0e068 100644
--- a/azureus2/src/com/aelitis/azureus/ui/UserPrompterResultListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/UserPrompterResultListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui;
 
 public interface UserPrompterResultListener
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/RememberedDecisionsManager.java b/azureus2/src/com/aelitis/azureus/ui/common/RememberedDecisionsManager.java
index 89551d4..199dbf9 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/RememberedDecisionsManager.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/RememberedDecisionsManager.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/ToolBarEnabler.java b/azureus2/src/com/aelitis/azureus/ui/common/ToolBarEnabler.java
deleted file mode 100644
index 71144d5..0000000
--- a/azureus2/src/com/aelitis/azureus/ui/common/ToolBarEnabler.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.aelitis.azureus.ui.common;
-
-import java.util.Map;
-
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarEnablerBase;
-
-// Change with caution: Some internal plugins use this directly
-public interface ToolBarEnabler
-	extends UIToolBarEnablerBase
-{
-	public void refreshToolBar(Map<String, Boolean> list);
-
-	public boolean toolBarItemActivated(String itemKey);
-}
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/ToolBarItem.java b/azureus2/src/com/aelitis/azureus/ui/common/ToolBarItem.java
index be61c69..5fea833 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/ToolBarItem.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/ToolBarItem.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.common;
 
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener;
@@ -6,13 +24,26 @@ import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
 public interface ToolBarItem
 	extends UIToolBarItem
 {
+	public static interface ToolBarItemListener
+	{
+		public void uiFieldChanged(ToolBarItem item);
+
+		public boolean triggerToolBarItem(ToolBarItem item, long activationType,
+				Object datasource);
+	}
+
 	public boolean triggerToolBarItem(long activationType, Object datasource);
 
-	public void setDefaultActivationListener(UIToolBarActivationListener toolBarActivation);
+	public void setDefaultActivationListener(
+			UIToolBarActivationListener toolBarActivation);
 
 	public void setAlwaysAvailable(boolean b);
 
 	public String getTooltipID();
 
 	public UIToolBarActivationListener getDefaultActivationListener();
+
+	public void addToolBarItemListener(ToolBarItemListener l);
+	
+	public void removeToolBarItemListener(ToolBarItemListener l);
 }
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableCellCore.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableCellCore.java
index c645192..1d913f9 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableCellCore.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableCellCore.java
@@ -2,11 +2,12 @@
  * File    : TableCellCore.java
  * Created : 2004/May/14
  *
- * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.common.table;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnCore.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnCore.java
index f9297be..07ba613 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnCore.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnCore.java
@@ -1,9 +1,10 @@
 /**
- * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.common.table;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnCoreCreationListener.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnCoreCreationListener.java
index acc8b32..fafad21 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnCoreCreationListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnCoreCreationListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 20, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnSortObject.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnSortObject.java
index 51c393e..b057c3a 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnSortObject.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableColumnSortObject.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 2, 2008 
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableCountChangeAdapter.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableCountChangeAdapter.java
index 0f5f02c..ec85846 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableCountChangeAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableCountChangeAdapter.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.table;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableCountChangeListener.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableCountChangeListener.java
index 788b977..39f080b 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableCountChangeListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableCountChangeListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.table;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableDataSourceChangedListener.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableDataSourceChangedListener.java
index de690ee..3ea2711 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableDataSourceChangedListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableDataSourceChangedListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.table;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableExpansionChangeListener.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableExpansionChangeListener.java
index 7a7aa7e..b6bf5a2 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableExpansionChangeListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableExpansionChangeListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.table;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableGroupRowRunner.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableGroupRowRunner.java
index 8afd36a..58d6aa4 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableGroupRowRunner.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableGroupRowRunner.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.common.table;
 
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableGroupRowVisibilityRunner.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableGroupRowVisibilityRunner.java
index a735626..a558af1 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableGroupRowVisibilityRunner.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableGroupRowVisibilityRunner.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.table;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableLifeCycleListener.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableLifeCycleListener.java
index f989eb2..03d22bf 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableLifeCycleListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableLifeCycleListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.table;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableRefreshListener.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableRefreshListener.java
index a889275..d372ed5 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableRefreshListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableRefreshListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.common.table;
 
 public interface TableRefreshListener
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableRowCore.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableRowCore.java
index 1c0d27b..85f9b0e 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableRowCore.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableRowCore.java
@@ -1,9 +1,10 @@
 /**
- * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.common.table;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableSelectionAdapter.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableSelectionAdapter.java
index ade8c7d..a463d8d 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableSelectionAdapter.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableSelectionAdapter.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.table;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableSelectionListener.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableSelectionListener.java
index 5aa9f5d..78f74a0 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableSelectionListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableSelectionListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.table;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableStructureEventDispatcher.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableStructureEventDispatcher.java
index 78bb611..d90210e 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableStructureEventDispatcher.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableStructureEventDispatcher.java
@@ -3,11 +3,12 @@
  * Created : 27 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,18 +18,13 @@
  * 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.common.table;
 
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.Set;
 
 import org.gudy.azureus2.core3.util.AEMonitor;
 import org.gudy.azureus2.core3.util.Debug;
@@ -101,23 +97,6 @@ public class TableStructureEventDispatcher implements
 		}
 	}
 
-	public Set<Class<?>> prepareForTableReset() 
-	{
-		Set<Class<?>> dataSourceTypes = new HashSet<Class<?>>();
-		
-		Iterator iter = listeners.iterator();
-		while (iter.hasNext()) {
-			TableStructureModificationListener listener = (TableStructureModificationListener) iter.next();
-			try{
-				dataSourceTypes.addAll( listener.prepareForTableReset());
-			}catch( Throwable e ){
-				Debug.printStackTrace(e);
-			}
-		}	
-		
-		return( dataSourceTypes );
-	}
-	
 	public void tableStructureChanged( boolean columnAddedOrRemoved, Class forPluginDataSourceType ) {
 
 			Iterator iter = listeners.iterator();
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableStructureModificationListener.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableStructureModificationListener.java
index bf4376b..209f376 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableStructureModificationListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableStructureModificationListener.java
@@ -3,11 +3,12 @@
  * Created : 26 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,14 +18,10 @@
  * 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.common.table;
 
-import java.util.Set;
 
 /**
  * @author Olivier
@@ -32,8 +29,6 @@ import java.util.Set;
  */
 public interface TableStructureModificationListener<T>
 {
-	Set<Class<?>> prepareForTableReset();
-	
 	void tableStructureChanged(boolean columnAddedOrRemoved, Class forPluginDataSourceType );
 
 	void columnOrderChanged(int[] iPositions);
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableView.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableView.java
index 522ae55..855a7a5 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableView.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableView.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.table;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/TableViewFilterCheck.java b/azureus2/src/com/aelitis/azureus/ui/common/table/TableViewFilterCheck.java
index 0aa6904..0e228d2 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/TableViewFilterCheck.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/TableViewFilterCheck.java
@@ -1,10 +1,12 @@
 /**
  * Created on Oct 4, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/CoreTableColumn.java b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/CoreTableColumn.java
index 5cb1769..89b86f9 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/CoreTableColumn.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/CoreTableColumn.java
@@ -1,11 +1,12 @@
 /*
  * File    : CoreTableColumn.java
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,9 +16,6 @@
  * 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.common.table.impl;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/DataSourceCallBackUtil.java b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/DataSourceCallBackUtil.java
index fa645db..489b488 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/DataSourceCallBackUtil.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/DataSourceCallBackUtil.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.common.table.impl;
 
 import java.util.ArrayList;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnImpl.java b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnImpl.java
index af8d591..15c9ace 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnImpl.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnImpl.java
@@ -1,11 +1,12 @@
 /**
- * Copyright (C) 2004-2007 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, Inc, All Rights Reserved.
  * 
  * Date: July 14, 2004
  *
  * 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.
+ * 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
@@ -15,13 +16,11 @@
  * 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.common.table.impl;
 
+import java.io.UnsupportedEncodingException;
 import java.util.*;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
@@ -217,27 +216,9 @@ public class TableColumnImpl
 		return sName;
 	}
 
-	public String getNameOverride(){
-		
-		Object name_override = getUserData( ATTRIBUTE_NAME_OVERIDE );
-		
-		if ( name_override != null ){
-						
-			if ( name_override instanceof String ){
-				
-				return((String)name_override);
-				
-			}else if ( name_override instanceof byte[]){
-				
-				try{
-					return( new String((byte[])name_override, "UTF-8" ));
-					
-				}catch( Throwable e ){
-				}
-			}
-		}
-		
-		return( null );
+	public String getNameOverride()
+	{
+		return getUserDataString( ATTRIBUTE_NAME_OVERIDE );
 	}
 	  
 	public void setNameOverride( String name )
@@ -983,6 +964,23 @@ public class TableColumnImpl
 		return null;
 	}
 	
+	public String getUserDataString(String key) {
+		if(userData != null) {
+			Object o = userData.get(key);
+			if (o instanceof String) {
+				return (String) o;
+			} else if (o instanceof byte[]) {
+				try {
+					String s = new String((byte[]) o, "utf-8");
+					// write it back to the map, so we don't continually create new String objects
+					userData.put(key, s);
+				} catch (UnsupportedEncodingException e) {
+				}
+			}
+		}
+		return null;
+	}
+	
 	public void setUserData(String key, Object value) {
 		if(userData == null)
 			userData = new LightHashMap(2);
@@ -1085,9 +1083,14 @@ public class TableColumnImpl
 		
 		pos++;
 		if (list.length >= (pos + 1) && (list[pos] instanceof Map)) {
-			userData = (Map)list[pos];
-			if(userData.size() < 1)
-				userData = null;
+			Map loadedUserData = (Map)list[pos];
+			if (userData == null || userData.size() == 0) {
+				userData = loadedUserData;
+			} else {
+				for (Object key : loadedUserData.keySet()) {
+					userData.put(key, loadedUserData.get(key));
+				}
+			}
 		}
 		pos++;
 		if (list.length >= (pos + 1) && (list[pos] instanceof Number)) {
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnInfoImpl.java b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnInfoImpl.java
index dd6733a..eb8c2b9 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnInfoImpl.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnInfoImpl.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 5, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnManager.java b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnManager.java
index eba81da..33a0621 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnManager.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableColumnManager.java
@@ -1,11 +1,12 @@
 /*
  * File    : TableColumnManager.java
 *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,9 +16,6 @@
  * 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.common.table.impl;
@@ -102,6 +100,7 @@ public class TableColumnManager {
 	 * key = TableID; value = table column ids
 	 */
 	private Map<String, String[]> mapTableDefaultColumns = new LightHashMap<String, String[]>();
+	private Map<String, Class[]> mapTableIDsDSTs = new LightHashMap<String, Class[]>();
 
 	private static final Map<String, String> mapResetTable_Version;
 	private static final boolean RERESET = false;
@@ -434,6 +433,8 @@ public class TableColumnManager {
 	 * @since 4.0.0.5
 	 */
 	private void doAddCreate(Map mTypes, String tableID, Map<Class<?>, List> mapDST) {
+		
+		mapTableIDsDSTs.put(tableID, mapDST.keySet().toArray(new Class[0]));
 		ArrayList<TableColumnCore> listAdded = new ArrayList<TableColumnCore>();
 		for (Class forDataSourceType : mapDST.keySet()) {
 			List listDST = mapDST.get(forDataSourceType);
@@ -500,7 +501,7 @@ public class TableColumnManager {
     return (TableColumnCore)mTypes.get(sColumnName);
   }
   
-  public void ensureIntegrety(String sTableID) {
+  public void ensureIntegrety(Class dataSourceType, String sTableID) {
     Map mTypes = (Map)items.get(sTableID);
     if (mTypes == null)
       return;
@@ -521,20 +522,8 @@ public class TableColumnManager {
     }
 
   	if (iPos == 0) {
-			String[] defaultColumnNames = getDefaultColumnNames(sTableID);
-			if (defaultColumnNames != null) {
-				int i = 0;
-				for (String name : defaultColumnNames) {
-					TableColumnCore column = getTableColumnCore(sTableID, name);
-					if (column != null) {
-						column.reset();
-						column.setVisible(true);
-						column.setPositionNoShift(i++);
-					}
-				}
-				saveTableColumns(null, sTableID);
-				TableStructureEventDispatcher.getInstance(sTableID).tableStructureChanged(true, null);
-			}
+  		// no columns?  Something must have went wrong, so reset them all
+  		resetColumns(dataSourceType, sTableID);
   	}
   
   }
@@ -827,31 +816,15 @@ public class TableColumnManager {
 	resetAllTables()
 	{
 		for ( String tableID: new ArrayList<String>( mapTableDefaultColumns.keySet())){
-			
-			String[] defaultColumnNames = getDefaultColumnNames( tableID );
-			
-			if ( defaultColumnNames != null ){
-				
-				TableStructureEventDispatcher disp = TableStructureEventDispatcher.getInstance( tableID );
-				
-				Set<Class<?>> dataSourceTypes = disp.prepareForTableReset();
-				
-				int i = 0;
-				for (String name : defaultColumnNames) {
-					TableColumnCore column = getTableColumnCore(tableID, name);
-					if (column != null) {
-						column.reset();
-						column.setVisible(true);
-						column.setPositionNoShift(i++);
-					}
-				}
-				
-				for ( Class<?> cla: dataSourceTypes ){
-					
-					saveTableColumns( cla, tableID);
-				
-					TableStructureEventDispatcher.getInstance( tableID ).tableStructureChanged(true, cla );
-				}
+
+			Class[] dataSourceTypes = mapTableIDsDSTs.get(tableID);
+
+			if (dataSourceTypes == null || dataSourceTypes.length == 0) {
+				resetColumns(null, tableID);
+			} else {
+  			for (Class dataSourceType : dataSourceTypes) {
+  				resetColumns(dataSourceType, tableID);
+  			}
 			}
 		}
 	}
@@ -903,4 +876,31 @@ public class TableColumnManager {
 		}
 	}
 
+	public void resetColumns(Class dataSourceType, String tableID) {
+		TableColumnCore[] allTableColumns = getAllTableColumnCoreAsArray(
+				dataSourceType, tableID);
+		if (allTableColumns != null) {
+			for (TableColumnCore column : allTableColumns) {
+				if (column != null) {
+					column.setVisible(false);
+					column.reset();
+				}
+			}
+		}
+		String[] defaultColumnNames = getDefaultColumnNames(tableID);
+		if (defaultColumnNames != null) {
+			int i = 0;
+			for (String name : defaultColumnNames) {
+				TableColumnCore column = getTableColumnCore(tableID, name);
+				if (column != null) {
+					column.setVisible(true);
+					column.setPositionNoShift(i++);
+				}
+			}
+		}
+		saveTableColumns(dataSourceType, tableID);
+		TableStructureEventDispatcher.getInstance(tableID).tableStructureChanged(
+				true, dataSourceType);
+	}
+
 }
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableRowCoreSorter.java b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableRowCoreSorter.java
index 7f6609a..04435d6 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableRowCoreSorter.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableRowCoreSorter.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.common.table.impl;
 
 import java.util.Comparator;
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableViewImpl.java b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableViewImpl.java
index 0d5d01a..3fede7c 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableViewImpl.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/table/impl/TableViewImpl.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.common.table.impl;
 
 import java.util.*;
@@ -198,7 +213,7 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 				tableID);
 
 		// fixup order
-		tcManager.ensureIntegrety(tableID);
+		tcManager.ensureIntegrety(classPluginDataSourceType, tableID);
 	}
 
 
@@ -229,6 +244,7 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 
 	// @see com.aelitis.azureus.ui.common.table.TableView#setParentDataSource(java.lang.Object)
 	public void setParentDataSource(Object newDataSource) {
+		//System.out.println(getTableID()  + "] setParentDataSource " + newDataSource);
 		parentDataSource = newDataSource;
 		Object[] listeners = listenersDataSourceChanged.toArray();
 		for (int i = 0; i < listeners.length; i++) {
@@ -558,6 +574,9 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 
 		synchronized (rows_sync) {
 			DATASOURCETYPE[] unfilteredArray = (DATASOURCETYPE[]) listUnfilteredDataSources.keySet().toArray();
+			if (DEBUGADDREMOVE) {
+				debug("filter: unfilteredArray is " + unfilteredArray.length);
+			}
 
 			Set<DATASOURCETYPE> existing = new HashSet<DATASOURCETYPE>(
 					getDataSources());
@@ -608,8 +627,9 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 		AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger("table");
 		diag_logger.log(SystemTime.getCurrentTime() + ":" + getTableID() + ": " + s);
 
-		System.out.println(Thread.currentThread().getName() + "] " + SystemTime.getCurrentTime() + ": " + getTableID() + ": "
-				+ s);
+		System.out.println(Thread.currentThread().getName() + "."
+				+ Integer.toHexString(hashCode()) + "] " + SystemTime.getCurrentTime()
+				+ ": " + getTableID() + ": " + s);
 	}
 
 	private void _processDataSourceQueue() {
@@ -667,12 +687,14 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 			return;
 		}
 
-		if (DEBUGADDREMOVE) {
-			debug("AddDS: " + dataSource );
-		}
 		synchronized (rows_sync) {
 			listUnfilteredDataSources.put(dataSource,"");
 		}
+		if (DEBUGADDREMOVE) {
+			debug("AddDS: " + dataSource + "; listUnfilteredDS: "
+					+ listUnfilteredDataSources.size() + " via "
+					+ Debug.getCompressedStackTrace(4));
+		}
 
 		if (!skipFilterCheck && filter != null
 				&& !filter.checker.filterCheck(dataSource, filter.text, filter.regex)) {
@@ -780,7 +802,9 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 
 			if (DEBUGADDREMOVE) {
 				debug("Queued " + count + " of " + dataSources.length
-						+ " dataSources to add.  Total Queued: " + dataSourcesToAdd.size());
+						+ " dataSources to add.  Total Qd: " + dataSourcesToAdd.size()
+						+ ";Unfiltered: " + listUnfilteredDataSources.size() + " via "
+						+ Debug.getCompressedStackTrace(5));
 			}
 
 		}
@@ -891,14 +915,15 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 			return;
 		}
 
-		if (DEBUGADDREMOVE) {
-			debug("RemDS: " + dataSource );
-		}
-
 		synchronized (rows_sync) {
 			listUnfilteredDataSources.remove(dataSource);
 		}
 
+
+		if (DEBUGADDREMOVE) {
+			debug("RemDS: " + dataSource + "; listUnfilteredDS=" + listUnfilteredDataSources.size() );
+		}
+
 		if (DataSourceCallBackUtil.IMMEDIATE_ADDREMOVE_DELAY == 0) {
 			reallyRemoveDataSources(new Object[] {
 				dataSource
@@ -953,8 +978,9 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 
 			if (DEBUGADDREMOVE) {
 				debug("Queued " + dataSources.length
-						+ " dataSources to remove.  Total Queued: "
-						+ dataSourcesToRemove.size() + " via " + Debug.getCompressedStackTrace(4));
+						+ " dataSources to remove.  Total Qd: " + dataSourcesToRemove.size()
+						+ "; Unfiltered: " + listUnfilteredDataSources.size() + " via "
+						+ Debug.getCompressedStackTrace(4));
 			}
 		}
 
@@ -1332,44 +1358,49 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 		TableRowCore[] selectedRows = getSelectedRows();
 			
 		boolean bWas0Rows = getRowCount() == 0;
-		synchronized (rows_sync) {
-			try {
+		try {
 
-  			if (DEBUGADDREMOVE) {
-  				debug("--" + " Add " + dataSources.length + " rows to SWT");
-  			}
-  
-  			long lStartTime = SystemTime.getCurrentTime();
-  			
-  			final List<TableRowCore> rowsAdded = new ArrayList<TableRowCore>();
-  			
-  			// add to sortedRows list in best position.  
-  			// We need to be in the SWT thread because the rowSorter may end up
-  			// calling SWT objects.
-  			for (int i = 0; i < dataSources.length; i++) {
-  				Object dataSource = dataSources[i];
-  				if (dataSource == null) {
-  					continue;
-  				}
-  
-  				TableRowCore row = mapDataSourceToRow.get(dataSource);
-  				//if ((row == null) || row.isRowDisposed() || sortedRows.indexOf(row) >= 0) {
-  				if (row == null || row.isRowDisposed()) {
-  					continue;
-  				}
-  				if (sortColumn != null) {
-  					TableCellCore cell = row.getSortColumnCell(null);
-  					if (cell != null) {
-  						try {
-  							cell.invalidate();
-  							cell.refresh(true);
-  						} catch (Exception e) {
-  							Logger.log(new LogEvent(LOGID,
-  									"Minor error adding a row to table " + getTableID(), e));
-  						}
-  					}
-  				}
-  
+			if (DEBUGADDREMOVE) {
+				debug("--" + " Add " + dataSources.length + " rows to SWT");
+			}
+
+			long lStartTime = SystemTime.getCurrentTime();
+			
+			final List<TableRowCore> rowsAdded = new ArrayList<TableRowCore>();
+			
+			// add to sortedRows list in best position.  
+			// We need to be in the SWT thread because the rowSorter may end up
+			// calling SWT objects.
+			for (int i = 0; i < dataSources.length; i++) {
+				Object dataSource = dataSources[i];
+				if (dataSource == null) {
+					continue;
+				}
+
+				TableRowCore row;
+				synchronized (rows_sync) {
+					row = mapDataSourceToRow.get(dataSource);
+				}
+				//if ((row == null) || row.isRowDisposed() || sortedRows.indexOf(row) >= 0) {
+				if (row == null || row.isRowDisposed()) {
+					continue;
+				}
+				if (sortColumn != null) {
+					TableCellCore cell = row.getSortColumnCell(null);
+					if (cell != null) {
+						try {
+							cell.invalidate();
+							// refresh could have caused a thread lock if we were 
+							// synchronized by rows_sync
+							cell.refresh(true);
+						} catch (Exception e) {
+							Logger.log(new LogEvent(LOGID,
+									"Minor error adding a row to table " + getTableID(), e));
+						}
+					}
+				}
+
+				synchronized (rows_sync) {
   				try {
   					int index = 0;
   					if (sortedRows.size() > 0) {
@@ -1427,30 +1458,32 @@ public abstract class TableViewImpl<DATASOURCETYPE>
   						Debug.out(e2);
   					}
   				}
-  			} // for dataSources
-  
-  			// NOTE: if the listener tries to do something like setSelected,
-  			// it will fail because we aren't done adding.
-  			// we should trigger after fillRowGaps()
-  			triggerListenerRowAdded(rowsAdded.toArray(new TableRowCore[0]));
-  
-  
-  			if (DEBUGADDREMOVE) {
-  				debug("Adding took " + (SystemTime.getCurrentTime() - lStartTime)
-  						+ "ms");
-  			}
-  
-  		} catch (Exception e) {
-  			Logger.log(new LogEvent(LOGID, "Error while adding row to Table "
-  					+ getTableID(), e));
-  		}
+				}
+			} // for dataSources
+
+			// NOTE: if the listener tries to do something like setSelected,
+			// it will fail because we aren't done adding.
+			// we should trigger after fillRowGaps()
+			triggerListenerRowAdded(rowsAdded.toArray(new TableRowCore[0]));
+
+
+			if (DEBUGADDREMOVE) {
+				debug("Adding took " + (SystemTime.getCurrentTime() - lStartTime)
+						+ "ms");
+			}
+
+		} catch (Exception e) {
+			Logger.log(new LogEvent(LOGID, "Error while adding row to Table "
+					+ getTableID(), e));
 		}
 		refreshenProcessDataSourcesTimer();
 
 		visibleRowsChanged();
 		fillRowGaps(false);
 
-		setSelectedRows(selectedRows);
+		if (selectedRows.length > 0) {
+			setSelectedRows(selectedRows);
+		}
 		if (DEBUGADDREMOVE) {
 			debug("<< " + size(false));
 		}
@@ -1580,19 +1613,6 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 		}
 	}
 
-	public Set<Class<?>> prepareForTableReset(){
-		TableColumnCore[] tableColumns = getVisibleColumns();
-		for (TableColumnCore column : tableColumns) {
-			column.setVisible(false);
-		}
-		
-		HashSet<Class<?>> result = new HashSet<Class<?>>();
-		
-		result.add( getDataSourceType());
-		
-		return( result );
-	}
-	
 	/* (non-Javadoc)
 	 * @see com.aelitis.azureus.ui.common.table.TableView#getTableColumn(java.lang.String)
 	 */
@@ -1636,27 +1656,28 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 	/***********************************/
 
 	public List<Object> getSelectedDataSourcesList() {
-		if (listSelectedCoreDataSources != null) {
-			return listSelectedCoreDataSources;
-		}
 		synchronized ( rows_sync ) {
+			if (listSelectedCoreDataSources != null) {
+				return listSelectedCoreDataSources;
+			}
+
 			if (isDisposed() || selectedRows.size() == 0) {
-  			return Collections.emptyList();
-  		}
-  
-  		final ArrayList<Object> l = new ArrayList<Object>(
-  				selectedRows.size());
-  		for (TableRowCore row : selectedRows) {
-  			if (row != null && !row.isRowDisposed()) {
-  				Object ds = row.getDataSource(true);
-  				if (ds != null) {
-  					l.add(ds);
-  				}
-  			}
-  		}
- 
-  		listSelectedCoreDataSources = l;
-  		return l;
+				return Collections.emptyList();
+			}
+
+			final ArrayList<Object> l = new ArrayList<Object>(
+					selectedRows.size());
+			for (TableRowCore row : selectedRows) {
+				if (row != null && !row.isRowDisposed()) {
+					Object ds = row.getDataSource(true);
+					if (ds != null) {
+						l.add(ds);
+					}
+				}
+			}
+
+			listSelectedCoreDataSources = l;
+			return l;
 		}
 	}
 
@@ -1960,7 +1981,7 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 				triggerDeselectionListeners(oldSelectionList.toArray(new TableRowCore[0]));
 			}
 
-			triggerTabViewsDataSourceChanged(false);
+			triggerTabViewsDataSourceChanged();
 		}
 
 	}
@@ -1997,7 +2018,7 @@ public abstract class TableViewImpl<DATASOURCETYPE>
 		}
 	}
 
-	public abstract void triggerTabViewsDataSourceChanged(boolean sendParent);
+	public abstract void triggerTabViewsDataSourceChanged();
 
 	protected abstract void uiChangeColumnIndicator();
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdatable.java b/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdatable.java
index fc925eb..8c0a202 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdatable.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdatable.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 15, 2006 1:05:17 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.updater;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdatableAlways.java b/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdatableAlways.java
index a5b2ba2..1910563 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdatableAlways.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdatableAlways.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 13, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -29,4 +31,5 @@ package com.aelitis.azureus.ui.common.updater;
 public interface UIUpdatableAlways
 	extends UIUpdatable
 {
+	public void updateUI( boolean is_visible );
 }
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdater.java b/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdater.java
index 69eff15..fd7b929 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdater.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/updater/UIUpdater.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 15, 2006 1:41:18 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.common.updater;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfo.java b/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfo.java
index a6fd589..a99300b 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfo.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfo.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 8, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfo2.java b/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfo2.java
index 32aba47..ccdf290 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfo2.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfo2.java
@@ -1,10 +1,12 @@
 /**
  * Created on Nov 17, 2010
  *
- * Copyright 2010 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfoListener.java b/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfoListener.java
index 4f9313b..8ad8238 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfoListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfoListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 8, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfoManager.java b/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfoManager.java
index 319709d..f579785 100644
--- a/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfoManager.java
+++ b/azureus2/src/com/aelitis/azureus/ui/common/viewtitleinfo/ViewTitleInfoManager.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 8, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/console/MakeTorrent.java b/azureus2/src/com/aelitis/azureus/ui/console/MakeTorrent.java
index 6390c0a..d9bd0e6 100644
--- a/azureus2/src/com/aelitis/azureus/ui/console/MakeTorrent.java
+++ b/azureus2/src/com/aelitis/azureus/ui/console/MakeTorrent.java
@@ -2,11 +2,12 @@
  * Created on May 27th 2004
  * Created by Olivier Chalouhi
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.console;
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiChildCloseListener.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiChildCloseListener.java
index 3f32807..4fc0bac 100644
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiChildCloseListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiChildCloseListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Nov 16, 2010
  *
- * Copyright 2010 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiCloseListener.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiCloseListener.java
index f4e060b..cc2aca7 100755
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiCloseListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiCloseListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 24, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntry.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntry.java
index 8ae5193..e0f44ed 100755
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntry.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntry.java
@@ -1,10 +1,12 @@
 /**
  * Created on Aug 13, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -23,7 +25,6 @@ import java.util.Map;
 import org.gudy.azureus2.plugins.ui.UIPluginView;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarEnablerBase;
 
-import com.aelitis.azureus.ui.common.ToolBarEnabler;
 import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
 
 
@@ -32,7 +33,7 @@ import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
  * @created Aug 13, 2008
  *
  */
-public interface MdiEntry
+public interface MdiEntry extends UIPluginView
 {
 
 	public String getParentID();
@@ -43,10 +44,6 @@ public interface MdiEntry
 
 	public boolean isCloseable();
 
-	public Class<? extends UIPluginView> getViewClass();
-
-	public UIPluginView getView();
-
 	public String getId();
 
 	public MdiEntryVitalityImage addVitalityImage(String imageID);
@@ -147,11 +144,6 @@ public interface MdiEntry
 
 	public UIToolBarEnablerBase[] getToolbarEnablers();
 
-	/**
-	 * @deprecated For azburn
-	 */
-	public void addToolbarEnabler(ToolBarEnabler enabler);
-
 	public void addToolbarEnabler(UIToolBarEnablerBase enabler);
 
 	public void removeToolbarEnabler(UIToolBarEnablerBase enabler);
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryCreationListener.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryCreationListener.java
index 2b03c20..0fab114 100755
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryCreationListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryCreationListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.mdi;
 
 public interface MdiEntryCreationListener
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryCreationListener2.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryCreationListener2.java
index 95377b4..db2dd7a 100644
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryCreationListener2.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryCreationListener2.java
@@ -2,9 +2,11 @@
  * Created on Jun 3, 2013
  *
  * Copyright Azureus Software, 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.
+ * 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
@@ -21,6 +23,8 @@ package com.aelitis.azureus.ui.mdi;
 import java.util.Map;
 
 /**
+ * Creation Listener with access to mdi, id, datasource, and params
+ * 
  * @author TuxPaper
  * @created Jun 3, 2013
  *
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryDatasourceListener.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryDatasourceListener.java
index 9b77152..bd384a3 100644
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryDatasourceListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryDatasourceListener.java
@@ -1,8 +1,10 @@
 /**
  * Copyright 2013 Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryDropListener.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryDropListener.java
index c94a8c2..ec223a7 100755
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryDropListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryDropListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 13, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryLoadedListener.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryLoadedListener.java
index 41a9eea..5c69482 100644
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryLoadedListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryLoadedListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Nov 17, 2010
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryLogIdListener.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryLogIdListener.java
index 1d2b512..114498d 100755
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryLogIdListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryLogIdListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Nov 6, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryOpenListener.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryOpenListener.java
index 2a6c7f2..197dc7a 100755
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryOpenListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryOpenListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Dec 3, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryVitalityImage.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryVitalityImage.java
index 1ec9678..f9a14f8 100755
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryVitalityImage.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryVitalityImage.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 15, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryVitalityImageListener.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryVitalityImageListener.java
index 4722b57..267604f 100755
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryVitalityImageListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiEntryVitalityImageListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 15, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiListener.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiListener.java
index 051ea97..fbbf1d9 100755
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MdiListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MdiListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 17, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/mdi/MultipleDocumentInterface.java b/azureus2/src/com/aelitis/azureus/ui/mdi/MultipleDocumentInterface.java
index f674778..9bab849 100755
--- a/azureus2/src/com/aelitis/azureus/ui/mdi/MultipleDocumentInterface.java
+++ b/azureus2/src/com/aelitis/azureus/ui/mdi/MultipleDocumentInterface.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.mdi;
 
 import java.util.List;
@@ -19,8 +37,6 @@ public interface MultipleDocumentInterface
 
 	public static final String SIDEBAR_HEADER_DVD = "header.dvd";
 
-	public static final String SIDEBAR_HEADER_SUBSCRIPTIONS = "header.subscriptions";
-
 	public static final String SIDEBAR_HEADER_PLUGINS = "header.plugins";
 
 	public static final String SIDEBAR_SECTION_PLUGINS = "Plugins";
@@ -39,9 +55,13 @@ public interface MultipleDocumentInterface
 
 	public static final String SIDEBAR_SECTION_TAGS = "TagsOverview";
 
+	public static final String SIDEBAR_SECTION_TAG_DISCOVERY = "TagDiscovery";
+
+	public static final String SIDEBAR_SECTION_CHAT = "ChatOverview";
+
 	public static final String SIDEBAR_SECTION_LIBRARY_UNOPENED = "LibraryUnopened";
 	
-	public static final String SIDEBAR_TORRENT_DETAILS_PREFIX = "DMDetails_";
+	public static final String SIDEBAR_SECTION_TORRENT_DETAILS = "DMDetails";
 
 	public static final String SIDEBAR_SECTION_WELCOME = "Welcome";
 
@@ -57,8 +77,26 @@ public interface MultipleDocumentInterface
 
 	public static final String SIDEBAR_SECTION_SEARCH = "Search";
 	
+	public static final String SIDEBAR_SECTION_ALLPEERS = "AllPeersView";
+	
+	public static final String SIDEBAR_SECTION_TORRENT_OPTIONS = "TorrentOptionsView";
+
+	public static final String SIDEBAR_SECTION_MY_SHARES = "MySharesView";
+
+	public static final String SIDEBAR_SECTION_MY_TRACKER = "MyTrackerView";
+	
+	public static final String SIDEBAR_SECTION_CLIENT_STATS = "ClientStatsView";
+
+	public static final String SIDEBAR_SECTION_LOGGER = "LoggerView";
+
+	public static final String SIDEBAR_SECTION_CONFIG = "ConfigView";
+
+	public static final String SIDEBAR_SECTION_ARCHIVED_DOWNLOADS = "ArchivedDownloads";
+
 	public boolean showEntryByID(String id);
 
+	public boolean showEntryByID(String id, Object datasource);
+
 		/**
 		 * If you prefix the 'preferedAfterID' string with '~' then the operation will actually
 		 * switch to 'preferedBeforeID'
@@ -99,10 +137,19 @@ public interface MultipleDocumentInterface
 	public void registerEntry(String id,
 			MdiEntryCreationListener2 mdiEntryCreationListener2);
 
+	public void deregisterEntry(String id, MdiEntryCreationListener l);
+	
+	public void deregisterEntry(String id,
+			MdiEntryCreationListener2 mdiEntryCreationListener2);
+
 	public boolean entryExists(String id);
 
 	public void removeItem(MdiEntry entry);
 
+	/**
+	 * When an entry can not be opened (ie. creation listener isn't registered yet),
+	 * call this to store your open request
+	 */
 	public void setEntryAutoOpen(String id, Object datasource);
 	
 	public void removeEntryAutoOpen(String id);
@@ -124,4 +171,12 @@ public interface MultipleDocumentInterface
 	public boolean loadEntryByID(String id, boolean activate,
 			boolean onlyLoadOnce, Object datasource);
 
+	/**
+	 * @return
+	 * @since 5.6.0.1
+	 */
+	public int getEntriesCount();
+	
+	public boolean isDisposed();
+
 }
diff --git a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/DownloadUrlInfo.java b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/DownloadUrlInfo.java
index bdf6165..b2793d8 100644
--- a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/DownloadUrlInfo.java
+++ b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/DownloadUrlInfo.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 12, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/ISelectedContent.java b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/ISelectedContent.java
index 5847b0f..977683f 100644
--- a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/ISelectedContent.java
+++ b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/ISelectedContent.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jun 9, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/ISelectedVuzeFileContent.java b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/ISelectedVuzeFileContent.java
index c06e38f..551d62a 100644
--- a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/ISelectedVuzeFileContent.java
+++ b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/ISelectedVuzeFileContent.java
@@ -1,32 +1,31 @@
-/*
- * Created on Apr 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.ui.selectedcontent;
-
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-
-public interface 
-ISelectedVuzeFileContent 
-	extends ISelectedContent
-{
-	public VuzeFile
-	getVuzeFile();
-}
+/*
+ * Created on Apr 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.selectedcontent;
+
+import com.aelitis.azureus.core.vuzefile.VuzeFile;
+
+public interface 
+ISelectedVuzeFileContent 
+	extends ISelectedContent
+{
+	public VuzeFile
+	getVuzeFile();
+}
diff --git a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContent.java b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContent.java
index 1aaf7c2..b1114b2 100644
--- a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContent.java
+++ b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContent.java
@@ -1,10 +1,12 @@
 /**
  * Created on May 6, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentListener.java b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentListener.java
index 0802832..f52f505 100644
--- a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on May 6, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentManager.java b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentManager.java
index 9cab024..50b4336 100644
--- a/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentManager.java
+++ b/azureus2/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentManager.java
@@ -1,10 +1,12 @@
 /**
  * Created on May 6, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -184,6 +186,10 @@ public class SelectedContentManager
 			contents = getCurrentlySelectedContent();
 		}
 		if (contents.length == 0) {
+			TableView tv = SelectedContentManager.getCurrentlySelectedTableView();
+			if (tv != null) {
+				return tv.getSelectedDataSources(false);
+			}
 			return null;
 		}
 		if (contents.length == 1) {
diff --git a/azureus2/src/com/aelitis/azureus/ui/skin/SkinProperties.java b/azureus2/src/com/aelitis/azureus/ui/skin/SkinProperties.java
index 21aa313..6153d4d 100644
--- a/azureus2/src/com/aelitis/azureus/ui/skin/SkinProperties.java
+++ b/azureus2/src/com/aelitis/azureus/ui/skin/SkinProperties.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 26, 2006 8:34:56 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/skin/SkinPropertiesImpl.java b/azureus2/src/com/aelitis/azureus/ui/skin/SkinPropertiesImpl.java
index 35b5059..cc376d8 100644
--- a/azureus2/src/com/aelitis/azureus/ui/skin/SkinPropertiesImpl.java
+++ b/azureus2/src/com/aelitis/azureus/ui/skin/SkinPropertiesImpl.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 29, 2006 4:23:01 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/UIFunctionsManagerSWT.java b/azureus2/src/com/aelitis/azureus/ui/swt/UIFunctionsManagerSWT.java
index d3af489..fcea4ee 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/UIFunctionsManagerSWT.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/UIFunctionsManagerSWT.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 13, 2006 12:28:36 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/UIFunctionsSWT.java b/azureus2/src/com/aelitis/azureus/ui/swt/UIFunctionsSWT.java
index 344c8fc..1225e88 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/UIFunctionsSWT.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/UIFunctionsSWT.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 12, 2006 3:11:00 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,14 +13,13 @@
  * 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;
 
-import org.eclipse.swt.widgets.Shell;
+import java.util.Map;
 
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager;
 import org.gudy.azureus2.ui.swt.mainwindow.IMainMenu;
 import org.gudy.azureus2.ui.swt.mainwindow.IMainStatusBar;
@@ -32,6 +31,7 @@ import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
 
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
+import com.aelitis.azureus.ui.swt.mdi.TabbedMdiInterface;
 
 /**
  * @author TuxPaper
@@ -76,8 +76,6 @@ public interface UIFunctionsSWT
 	public void openPluginView(String sParentID, String sViewID,
 			UISWTViewEventListener l, Object dataSource, boolean bSetFocus);
 
-	public void openPluginView(final UISWTViewCore view, final String name);
-
 	/**
 	 * @param viewID
 	 */
@@ -143,5 +141,27 @@ public interface UIFunctionsSWT
 	 */
 	public void openTorrentOpenOptions(Shell shell, String sPathOfFilesToOpen,
 			String[] sFilesToOpen, boolean defaultToStopped, boolean forceOpen);
+	
+	/**
+	 * @since 5.6.0.1
+	 * @param shell
+	 * @param sPathOfFilesToOpen
+	 * @param sFilesToOpen
+	 * @param options	See UIFunctions constants
+	 */
+	public void 
+	openTorrentOpenOptions(
+		Shell 					shell, 
+		String 					sPathOfFilesToOpen,
+		String[] 				sFilesToOpen, 
+		Map<String,Object>		options );
+
+	/**
+	 * 
+	 * @param parent 
+	 * @param id TODO
+	 * @since 5.6.0.1
+	 */
+	public TabbedMdiInterface createTabbedMDI(Composite parent, String id);
 
 }
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/UISkinnableManagerSWT.java b/azureus2/src/com/aelitis/azureus/ui/swt/UISkinnableManagerSWT.java
index 6115b9e..4ca953d 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/UISkinnableManagerSWT.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/UISkinnableManagerSWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/UISkinnableSWTListener.java b/azureus2/src/com/aelitis/azureus/ui/swt/UISkinnableSWTListener.java
index 65239b4..f2c737a 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/UISkinnableSWTListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/UISkinnableSWTListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/imageloader/ImageLoader.java b/azureus2/src/com/aelitis/azureus/ui/swt/imageloader/ImageLoader.java
index bc92138..1718b6e 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/imageloader/ImageLoader.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/imageloader/ImageLoader.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 7, 2006 2:31:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.imageloader;
 
@@ -151,7 +148,7 @@ public class ImageLoader
 		if (Collections.binarySearch(notFound, sKey) >= 0) {
 			return null;
 		}
-
+		
 		for (int i = 0; i < sSuffixChecks.length; i++) {
 			String sSuffix = sSuffixChecks[i];
 
@@ -316,7 +313,7 @@ public class ImageLoader
 							}
 							
 							if ( isRealImage(image)){
-																
+								
 								image = fadeImage(image);
 								
 								image_key = sTryFile;
@@ -620,7 +617,6 @@ public class ImageLoader
 	}
 
 	public Image[] getImages(String sKey) {
-		//System.out.println("getImages " + sKey);
 		if (sKey == null) {
 			return new Image[0];
 		}
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/imageloader/ImageLoaderRefInfo.java b/azureus2/src/com/aelitis/azureus/ui/swt/imageloader/ImageLoaderRefInfo.java
index 4c3ef5d..58bd7e2 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/imageloader/ImageLoaderRefInfo.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/imageloader/ImageLoaderRefInfo.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jan 1, 2009 3:17:06 PM
- * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.imageloader;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MdiEntrySWT.java b/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MdiEntrySWT.java
index 76b1828..6696dca 100755
--- a/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MdiEntrySWT.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MdiEntrySWT.java
@@ -1,11 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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.mdi;
 
 import org.eclipse.swt.graphics.Image;
-
-import org.gudy.azureus2.plugins.ui.UIPluginView;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
 
@@ -17,14 +27,10 @@ import com.aelitis.azureus.ui.mdi.MdiEntry;
  *
  */
 public interface MdiEntrySWT
-	extends MdiEntry
+	extends MdiEntry, UISWTViewCore
 {
 	//public SWTSkinObject getSkinObject();
 
-	public UIPluginView getView();
-
-	public UISWTViewCore getCoreView();
-
 	public UISWTViewEventListener getEventListener();
 
 	public void addListener(MdiSWTMenuHackListener l);
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MdiSWTMenuHackListener.java b/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MdiSWTMenuHackListener.java
index c0fb5d0..042251a 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MdiSWTMenuHackListener.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MdiSWTMenuHackListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Nov 16, 2010
  *
- * Copyright 2010 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MultipleDocumentInterfaceSWT.java b/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MultipleDocumentInterfaceSWT.java
index 3a854f5..651f24f 100755
--- a/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MultipleDocumentInterfaceSWT.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/mdi/MultipleDocumentInterfaceSWT.java
@@ -1,5 +1,17 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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.mdi;
 
@@ -25,24 +37,30 @@ public interface MultipleDocumentInterfaceSWT
 	/**
 	 * If you prefix the 'preferedAfterID' string with '~' then the operation will actually
 	 * switch to 'preferedBeforeID'
-	 * @param parentID
-	 * @param l
-	 * @param id
-	 * @param closeable
-	 * @param datasource
-	 * @param preferredAfterID
-	 * @return
 	 */
-	public MdiEntry createEntryFromEventListener(String parentID,
-			UISWTViewEventListener l, String id, boolean closeable, Object datasource, String preferredAfterID);
+	public MdiEntry createEntryFromEventListener(String parentEntryID,
+			UISWTViewEventListener l, String id, boolean closeable, 
+			Object datasource, String preferredAfterID);
+
+
+	public MdiEntry createEntryFromEventListener(String parentEntryID,
+			String parentViewID,
+			UISWTViewEventListener l, String id, boolean closeable, 
+			Object datasource, String preferredAfterID);
 
-	public MdiEntry createEntryFromView(String parentID, UISWTViewCore view,
-			String id, Object datasource, boolean closeable, boolean show,
-			boolean expand);
+	public MdiEntry createEntryFromEventListener(String parentEntryID,
+			Class<? extends UISWTViewEventListener> cla, String id, boolean closeable,
+			Object data, String preferedAfterID);
 
 	public MdiEntrySWT getEntrySWT(String id);
 
 	public MdiEntrySWT getCurrentEntrySWT();
 
 	public MdiEntrySWT getEntryFromSkinObject(PluginUISWTSkinObject skinObject);
+
+	/**
+	 * @param closeableConfigFile
+	 * @since 5.6.0.1
+	 */
+	void setCloseableConfigFile(String closeableConfigFile);
 }
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/mdi/TabbedMdiInterface.java b/azureus2/src/com/aelitis/azureus/ui/swt/mdi/TabbedMdiInterface.java
new file mode 100644
index 0000000..cd78049
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/mdi/TabbedMdiInterface.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.mdi;
+
+import org.eclipse.swt.custom.CTabFolder;
+
+/**
+ * az2 access to some {@link TabbedMdi} methods
+ */
+public interface TabbedMdiInterface
+	extends MultipleDocumentInterfaceSWT
+{
+
+	public CTabFolder getTabFolder();
+
+	public void setMaximizeVisible(boolean visible);
+
+	public void setMinimizeVisible(boolean visible);
+
+	public boolean getMinimized();
+
+	public void setMinimized(boolean minimized);
+
+	public int getFolderHeight();
+	
+	public void addListener(MdiSWTMenuHackListener l);
+	
+	public void setTabbedMdiMaximizeListener(TabbedMdiMaximizeListener l);
+	
+	public void updateUI();
+}
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/mdi/TabbedMdiMaximizeListener.java b/azureus2/src/com/aelitis/azureus/ui/swt/mdi/TabbedMdiMaximizeListener.java
new file mode 100644
index 0000000..40aa2c7
--- /dev/null
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/mdi/TabbedMdiMaximizeListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.mdi;
+
+public interface TabbedMdiMaximizeListener
+{
+	public void maximizePressed();
+}
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/uiupdater/UIUpdaterSWT.java b/azureus2/src/com/aelitis/azureus/ui/swt/uiupdater/UIUpdaterSWT.java
index 3216f74..41126ea 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/uiupdater/UIUpdaterSWT.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/uiupdater/UIUpdaterSWT.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 15, 2006 12:29:32 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.uiupdater;
 
@@ -69,11 +66,11 @@ public class UIUpdaterSWT
 
 	private boolean refreshed = true;
 
-	private ArrayList<UIUpdatable> updateables = new ArrayList<UIUpdatable>();
+	private CopyOnWriteList<UIUpdatable> updateables = new CopyOnWriteList<UIUpdatable>();
 	
 	private Map<UIUpdatable, String> debug_Updateables; 
 
-	private ArrayList<UIUpdatable> alwaysUpdateables = new ArrayList<UIUpdatable>();
+	private CopyOnWriteList<UIUpdatable> alwaysUpdateables = new CopyOnWriteList<UIUpdatable>();
 
 	private AEMonitor updateables_mon = new AEMonitor("updateables");
 
@@ -134,7 +131,7 @@ public class UIUpdaterSWT
 								if (noneVisible) {
 									//System.out.println("nothing visible!");
 									if (alwaysUpdateables.size() > 0) {
-										update(alwaysUpdateables);
+										update(alwaysUpdateables,false);
 									}
 									return;
 								}
@@ -147,7 +144,7 @@ public class UIUpdaterSWT
 								}
 							}
 
-							update(updateables);
+							update(updateables,true);
 						} catch (Exception e) {
 							Logger.log(new LogEvent(LOGID,
 									"Error while trying to update GUI", e));
@@ -243,7 +240,7 @@ public class UIUpdaterSWT
 		COConfigurationManager.removeParameterListener(CFG_REFRESH_INTERVAL, this);
 	}
 
-	private void update(List<UIUpdatable> updateables) {
+	private void update(CopyOnWriteList<UIUpdatable> updateables, boolean is_visible ) {
 		long start = 0;
 		Map mapTimeMap = DEBUG_TIMER ? new HashMap() : null;
 
@@ -252,28 +249,27 @@ public class UIUpdaterSWT
 			return;
 		}
 
-		Object[] updateablesArray = updateables.toArray();
-		for (int i = 0; i < updateablesArray.length; i++) {
-			UIUpdatable updateable = (UIUpdatable) updateablesArray[i];
-			if (updateable == null) {
-				removeUpdater(updateable);
-			}else{
-				try {
-					if (DEBUG_TIMER) {
-						start = SystemTime.getCurrentTime();
-					}
+		for ( UIUpdatable updateable: updateables ){
+			try {
+				if (DEBUG_TIMER) {
+					start = SystemTime.getCurrentTime();
+				}
+				if ( updateable instanceof UIUpdatableAlways ){
+					((UIUpdatableAlways)updateable).updateUI(is_visible);
+				}else{
 					updateable.updateUI();
-					if (DEBUG_TIMER) {
-						long diff = SystemTime.getCurrentTime() - start;
-						if (diff > 0) {
-							mapTimeMap.put(updateable, new Long(diff));
-						}
+				}
+				
+				if (DEBUG_TIMER) {
+					long diff = SystemTime.getCurrentTime() - start;
+					if (diff > 0) {
+						mapTimeMap.put(updateable, new Long(diff));
 					}
-				} catch (Throwable t) {
-					Logger.log(new LogEvent(LOGID,
-							"Error while trying to update UI Element "
-									+ updateable.getUpdateUIName(), t));
 				}
+			} catch (Throwable t) {
+				Logger.log(new LogEvent(LOGID,
+						"Error while trying to update UI Element "
+								+ updateable.getUpdateUIName(), t));
 			}
 		}
 		if (DEBUG_TIMER) {
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/utils/ColorCache.java b/azureus2/src/com/aelitis/azureus/ui/swt/utils/ColorCache.java
index 3e60417..d0066a0 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/utils/ColorCache.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/utils/ColorCache.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 30, 2006 6:22:44 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.utils;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/utils/ColorCache2.java b/azureus2/src/com/aelitis/azureus/ui/swt/utils/ColorCache2.java
index d03ecf6..6de9b76 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/utils/ColorCache2.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/utils/ColorCache2.java
@@ -2,20 +2,19 @@
  * Created on Nov 10, 2011
  * Created by Paul Gardner
  * 
- * Copyright 2011 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/utils/FontUtils.java b/azureus2/src/com/aelitis/azureus/ui/swt/utils/FontUtils.java
index 909d2c5..df0af4c 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/utils/FontUtils.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/utils/FontUtils.java
@@ -1,6 +1,6 @@
 /*
  * Created on Mar 7, 2010 11:10:45 AM
- * Copyright (C) 2010 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.utils;
 
diff --git a/azureus2/src/com/aelitis/azureus/ui/swt/utils/UIMagnetHandler.java b/azureus2/src/com/aelitis/azureus/ui/swt/utils/UIMagnetHandler.java
index 3f50f29..f52ba19 100644
--- a/azureus2/src/com/aelitis/azureus/ui/swt/utils/UIMagnetHandler.java
+++ b/azureus2/src/com/aelitis/azureus/ui/swt/utils/UIMagnetHandler.java
@@ -1,10 +1,12 @@
 /**
  * Created on May 27, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/ui/utils/ImageBytesDownloader.java b/azureus2/src/com/aelitis/azureus/ui/utils/ImageBytesDownloader.java
index d324e70..fa1e68a 100644
--- a/azureus2/src/com/aelitis/azureus/ui/utils/ImageBytesDownloader.java
+++ b/azureus2/src/com/aelitis/azureus/ui/utils/ImageBytesDownloader.java
@@ -1,10 +1,12 @@
 /**
  * Created on Apr 28, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/azureus/util/JSONUtils.java b/azureus2/src/com/aelitis/azureus/util/JSONUtils.java
index 265ff7c..378e471 100644
--- a/azureus2/src/com/aelitis/azureus/util/JSONUtils.java
+++ b/azureus2/src/com/aelitis/azureus/util/JSONUtils.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus2/src/com/aelitis/azureus/util/MapUtils.java b/azureus2/src/com/aelitis/azureus/util/MapUtils.java
index a93bf16..118b995 100644
--- a/azureus2/src/com/aelitis/azureus/util/MapUtils.java
+++ b/azureus2/src/com/aelitis/azureus/util/MapUtils.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
@@ -97,6 +94,23 @@ public class MapUtils
 		}
 	}
 
+	public static String
+	getString(
+		Object	obj )
+	{
+		if ( obj instanceof String ){
+			return((String)obj);
+		}else if ( obj instanceof byte[]){
+			
+			try{
+				return new String((byte[])obj, "UTF-8");
+			}catch( Throwable e ){
+				
+			}
+		}
+		return( null );
+	}
+	
 	public static void setMapString(Map map, String key, String val ){
 		if ( map == null ){
 			Debug.out( "Map is null!" );
diff --git a/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandler.java b/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandler.java
index 2dbed77..d8cc7b2 100644
--- a/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandler.java
+++ b/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerException.java b/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerException.java
index 7d401e5..95d926e 100644
--- a/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerException.java
+++ b/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerListener.java b/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerListener.java
index 9e96aec..0824afc 100644
--- a/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerListener.java
+++ b/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerProgressListener.java b/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerProgressListener.java
index cc7d988..3a09441 100644
--- a/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerProgressListener.java
+++ b/azureus2/src/com/aelitis/net/magneturi/MagnetURIHandlerProgressListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/magneturi/impl/MagnetURIHandlerClient.java b/azureus2/src/com/aelitis/net/magneturi/impl/MagnetURIHandlerClient.java
index 480478e..e3808a4 100644
--- a/azureus2/src/com/aelitis/net/magneturi/impl/MagnetURIHandlerClient.java
+++ b/azureus2/src/com/aelitis/net/magneturi/impl/MagnetURIHandlerClient.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Sep-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/magneturi/impl/MagnetURIHandlerImpl.java b/azureus2/src/com/aelitis/net/magneturi/impl/MagnetURIHandlerImpl.java
index f2e210d..a7ab5dd 100644
--- a/azureus2/src/com/aelitis/net/magneturi/impl/MagnetURIHandlerImpl.java
+++ b/azureus2/src/com/aelitis/net/magneturi/impl/MagnetURIHandlerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -34,6 +31,7 @@ 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.CopyOnWriteList;
 import com.aelitis.azureus.core.util.HTTPUtils;
 import com.aelitis.azureus.core.util.png.PNG;
 import com.aelitis.net.magneturi.MagnetURIHandler;
@@ -56,7 +54,7 @@ MagnetURIHandlerImpl
 	
 	private static AEMonitor				class_mon = new AEMonitor( "MagnetURLHandler:class" );
 	
-	private static final int				DOWNLOAD_TIMEOUT	= 3*60*1000;
+	private static final int				DOWNLOAD_TIMEOUT	= 10*60*1000;	// needs to be fairly large as non-public downloads can take a while...
 	
 	protected static final String	NL			= "\015\012";
 	
@@ -83,7 +81,7 @@ MagnetURIHandlerImpl
 	
 	private int		port;
 	
-	private List	listeners	= new ArrayList();
+	private CopyOnWriteList<MagnetURIHandlerListener>	listeners	= new CopyOnWriteList<MagnetURIHandlerListener>();
 	
 	private Map		info_map 	= new HashMap();
 	
@@ -387,7 +385,7 @@ MagnetURIHandlerImpl
 						String	lhs 	= arg.substring( 0, pos ).trim();
 						String	lc_lhs 	= lhs.toLowerCase( MessageText.LOCALE_ENGLISH );
 									
-						String	rhs = URLDecoder.decode( arg.substring( pos+1 ).trim(), Constants.DEFAULT_ENCODING);
+						String	rhs = UrlUtils.decode( arg.substring( pos+1 ).trim());
 
 						if ( lc_lhs.equals( "xt" )){
 							
@@ -420,7 +418,7 @@ MagnetURIHandlerImpl
 								source_params.add( rhs );
 							}
 						}
-					}catch( UnsupportedEncodingException e ){
+					}catch( Throwable e ){
 						
 						Debug.printStackTrace( e );
 					}
@@ -431,9 +429,9 @@ MagnetURIHandlerImpl
 
 		if ( get.startsWith( "/magnet10/badge.img" )){
 			
-			for (int i=0;i<listeners.size();i++){
+			for ( MagnetURIHandlerListener listener: listeners ){
 				
-				byte[]	data = ((MagnetURIHandlerListener)listeners.get(i)).badge();
+				byte[]	data = listener.badge();
 					
 				if ( data != null ){
 					
@@ -453,9 +451,9 @@ MagnetURIHandlerImpl
 
 			if ( urn != null && urn.toLowerCase( MessageText.LOCALE_ENGLISH ).startsWith( "urn:btih:")){
 			
-				for (int i=0;i<listeners.size();i++){
+				for ( MagnetURIHandlerListener listener: listeners ){
 					
-					byte[]	data = ((MagnetURIHandlerListener)listeners.get(i)).badge();
+					byte[]	data = listener.badge();
 						
 					if ( data != null ){
 						
@@ -537,9 +535,9 @@ MagnetURIHandlerImpl
 						url = new URL( "magnet:?xt=" + urn );
 					}
 					
-					for (int i=0;i<listeners.size();i++){
+					for ( MagnetURIHandlerListener listener: listeners ){
 						
-						if (((MagnetURIHandlerListener)listeners.get(i)).download( url )){
+						if ( listener.download( url )){
 							
 							ok = true;
 							
@@ -563,9 +561,9 @@ MagnetURIHandlerImpl
 				
 				if ( "image".equalsIgnoreCase((String)lc_params.get( "result" ))){
 					
-					for (int i=0;i<listeners.size();i++){
+					for ( MagnetURIHandlerListener listener: listeners ){
 
-						byte[]	data = ((MagnetURIHandlerListener)listeners.get(i)).badge();
+						byte[]	data = listener.badge();
 					
 						if ( data != null ){
 							
@@ -615,7 +613,17 @@ MagnetURIHandlerImpl
 					if ( p != -1 ){
 						
 						try{
-							InetSocketAddress	sa = new InetSocketAddress( source.substring(0,p), Integer.parseInt( source.substring(p+1)));
+							String 	host 	= source.substring(0,p);
+							int		port 	= Integer.parseInt( source.substring(p+1));
+							
+								// deal with somwe borked "/ip-address;:port strings
+							
+							if ( host.startsWith( "/" )){
+								
+								host = host.substring(1);
+							}
+							
+							InetSocketAddress	sa = new InetSocketAddress( host, port );
 							
 							sources.add( sa );
 							
@@ -626,19 +634,23 @@ MagnetURIHandlerImpl
 					}
 				}
 					
-				InetSocketAddress[]	s = sources.toArray( new InetSocketAddress[ sources.size()] );
+				final InetSocketAddress[]	s = sources.toArray( new InetSocketAddress[ sources.size()] );
 				
 				if (Logger.isEnabled())
 					Logger.log(new LogEvent(LOGID, "MagnetURIHandler: download of '"
 							+ encoded + "' starts (initial sources=" + s.length + ")"));
 
-				byte[] sha1 = UrlUtils.decodeSHA1Hash( encoded );
+				byte[] _sha1 = UrlUtils.decodeSHA1Hash( encoded );
 					
-				if ( sha1 == null ){
+				if ( _sha1 == null ){
 					
-					throw( new Exception( "Invalid info hash '" + encoded + "'" ));
+					_sha1 = new byte[20];	// dummy to still allow &fl links to work...
+					
+					//throw( new Exception( "Invalid info hash '" + encoded + "'" ));
 				}
 				
+				final byte[] sha1 = _sha1;
+				
 				byte[] data = null;
 				
 				String verbose_str = lc_params.get( "verbose" );
@@ -672,63 +684,148 @@ MagnetURIHandlerImpl
 						});
 				
 				try{
-					for (int i=0;i<listeners.size();i++){
+					final String f_arg_str = arg_str;
+					
+					final byte[][] 		f_data 	= { null };
+					final Throwable[]	f_error = { null };
+					
+					final AESemaphore wait_sem = new AESemaphore( "download-waiter" );
+					
+					List<Runnable> tasks = new ArrayList<Runnable>();
 					
-						data = ((MagnetURIHandlerListener)listeners.get(i)).download(
-								new MagnetURIHandlerProgressListener()
+					for ( final MagnetURIHandlerListener listener: listeners ){
+					
+						tasks.add(
+							new Runnable()
+							{
+								public void
+								run()
 								{
-									public void
-									reportSize(
-										long	size )
-									{
-										pw.print( "X-Report: " + getMessageText( "torrent_size", String.valueOf( size )) + NL );
+									try{
+										byte[] data = 
+											listener.download(
+												new MagnetURIHandlerProgressListener()
+												{
+													public void
+													reportSize(
+														long	size )
+													{
+														pw.print( "X-Report: " + getMessageText( "torrent_size", String.valueOf( size )) + NL );
+														
+														pw.flush();
+													}
+													
+													public void
+													reportActivity(
+														String	str )
+													{
+														pw.print( "X-Report: " + str + NL );
+																								
+														pw.flush();
+													}
+													
+													public void
+													reportCompleteness(
+														int		percent )
+													{
+														pw.print( "X-Report: " + getMessageText( "percent", String.valueOf(percent)) + NL );
+														
+														pw.flush();
+													}
+													
+													public boolean 
+													verbose()
+													{
+														return( verbose );
+													}
+													
+													public boolean
+													cancelled()
+													{
+														synchronized( cancel ){
+															
+															if ( cancel[0] ){
+																
+																return( true );
+															}
+														}
+														
+														synchronized( f_data ){
+														
+															return( f_data[0] != null );
+														}
+													}
+												},
+												sha1, 
+												f_arg_str,
+												s,
+												DOWNLOAD_TIMEOUT );
 										
-										pw.flush();
-									}
-									
-									public void
-									reportActivity(
-										String	str )
-									{
-										pw.print( "X-Report: " + str + NL );
-																				
-										pw.flush();
-									}
-									
-									public void
-									reportCompleteness(
-										int		percent )
-									{
-										pw.print( "X-Report: " + getMessageText( "percent", String.valueOf(percent)) + NL );
+										synchronized( f_data ){
 										
-										pw.flush();
-									}
-									
-									public boolean 
-									verbose()
-									{
-										return( verbose );
+											if ( data != null ){
+										
+												if ( f_data[0] == null ){
+													
+													f_data[0] = data;
+												}
+											}
+										}
+									}catch( Throwable e ){
+										
+										synchronized( f_data ){
+										
+											f_error[0] = e;
+										}
+										
+									}finally{
+										
+										wait_sem.release();
 									}
-									
-									public boolean
-									cancelled()
+								}
+							});
+					}
+					
+					if ( tasks.size() > 0 ){
+						
+						if ( tasks.size() == 1 ){
+							
+							tasks.get(0).run();
+							
+						}else{
+							
+							for ( final Runnable task: tasks ){
+								
+								new AEThread2( "MUH:dasync" )
+								{
+									public void
+									run()
 									{
-										synchronized( cancel ){
-											
-											return( cancel[0] );
-										}
+										task.run();
 									}
-								},
-								sha1, 
-								arg_str,
-								s,
-								DOWNLOAD_TIMEOUT );
+								}.start();
+							}
+							
+							for ( int i=0; i<tasks.size(); i++ ){
+								
+								wait_sem.reserve();
+							}
+						}
 						
-						if ( data != null ){
+						synchronized( f_data ){
 							
-							break;
+							data = f_data[0];
+								
+							if ( data == null ){
+									
+								if ( f_error[0] != null ){
+										
+									throw( f_error[0] );
+								}
+							}
 						}
 					}
+					
 				}finally{
 					
 					keep_alive.cancel();
@@ -794,7 +891,7 @@ MagnetURIHandlerImpl
 					
 				}else{
 					
-					for (int i=0;i<listeners.size() && value == Integer.MIN_VALUE;i++){
+					for ( MagnetURIHandlerListener listener: listeners ){
 						
 							// no idea why we copy, but let's keep doing so
 						
@@ -802,7 +899,12 @@ MagnetURIHandlerImpl
 						
 						paramsCopy.putAll( original_params);
 
-						value = ((MagnetURIHandlerListener)listeners.get(i)).get( name, paramsCopy );
+						value = listener.get( name, paramsCopy );
+						
+						if ( value != Integer.MIN_VALUE ){
+							
+							break;
+						}
 					}
 				}
 								
@@ -929,7 +1031,7 @@ MagnetURIHandlerImpl
 
 				boolean	result = false;
 				
-				for (int i=0;i<listeners.size() && !result;i++){
+				for ( MagnetURIHandlerListener listener: listeners ){
 					
 						// no idea why we copy, but let's keep on doing so
 					
@@ -937,7 +1039,12 @@ MagnetURIHandlerImpl
 					
 					paramsCopy.putAll( original_params );
 					
-					result = ((MagnetURIHandlerListener)listeners.get(i)).set( name, paramsCopy );
+					result = listener.set( name, paramsCopy );
+					
+					if ( result ){
+						
+						break;
+					}
 				}
 				
 				int	width 	= result?20:10;
diff --git a/azureus2/src/com/aelitis/net/natpmp/NATPMPDeviceAdapter.java b/azureus2/src/com/aelitis/net/natpmp/NATPMPDeviceAdapter.java
index c487fec..8179350 100644
--- a/azureus2/src/com/aelitis/net/natpmp/NATPMPDeviceAdapter.java
+++ b/azureus2/src/com/aelitis/net/natpmp/NATPMPDeviceAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/natpmp/NatPMPDevice.java b/azureus2/src/com/aelitis/net/natpmp/NatPMPDevice.java
index dd1f8b1..987e9ee 100644
--- a/azureus2/src/com/aelitis/net/natpmp/NatPMPDevice.java
+++ b/azureus2/src/com/aelitis/net/natpmp/NatPMPDevice.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/natpmp/NatPMPDeviceFactory.java b/azureus2/src/com/aelitis/net/natpmp/NatPMPDeviceFactory.java
index 0016fe2..7c96362 100644
--- a/azureus2/src/com/aelitis/net/natpmp/NatPMPDeviceFactory.java
+++ b/azureus2/src/com/aelitis/net/natpmp/NatPMPDeviceFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/natpmp/impl/NatPMPDeviceImpl.java b/azureus2/src/com/aelitis/net/natpmp/impl/NatPMPDeviceImpl.java
index f144780..00b9fb8 100644
--- a/azureus2/src/com/aelitis/net/natpmp/impl/NatPMPDeviceImpl.java
+++ b/azureus2/src/com/aelitis/net/natpmp/impl/NatPMPDeviceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jun-2006
  * Created by Marc Colosimo
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  * Connection class for NAT-PMP (Port Mapping Protocol) Devices
  * 
diff --git a/azureus2/src/com/aelitis/net/natpmp/upnp/NatPMPUPnP.java b/azureus2/src/com/aelitis/net/natpmp/upnp/NatPMPUPnP.java
index b47fc5e..a01d2b8 100644
--- a/azureus2/src/com/aelitis/net/natpmp/upnp/NatPMPUPnP.java
+++ b/azureus2/src/com/aelitis/net/natpmp/upnp/NatPMPUPnP.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/natpmp/upnp/NatPMPUPnPFactory.java b/azureus2/src/com/aelitis/net/natpmp/upnp/NatPMPUPnPFactory.java
index a8664e8..0af2fee 100644
--- a/azureus2/src/com/aelitis/net/natpmp/upnp/NatPMPUPnPFactory.java
+++ b/azureus2/src/com/aelitis/net/natpmp/upnp/NatPMPUPnPFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPImpl.java b/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPImpl.java
index 187875e..e72f29d 100644
--- a/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPImpl.java
+++ b/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Jun 2006
  * Created by Marc Colosimo
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
  
diff --git a/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPImpl.java b/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPImpl.java
index 979ba98..4d73fe4 100644
--- a/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPImpl.java
+++ b/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java b/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java
index 28d6adb..62cc8cc 100644
--- a/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java
+++ b/azureus2/src/com/aelitis/net/natpmp/upnp/impl/NatPMPUPnPRootDeviceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/mc/MCGroup.java b/azureus2/src/com/aelitis/net/udp/mc/MCGroup.java
index 6306e5c..0a8aed9 100644
--- a/azureus2/src/com/aelitis/net/udp/mc/MCGroup.java
+++ b/azureus2/src/com/aelitis/net/udp/mc/MCGroup.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/mc/MCGroupAdapter.java b/azureus2/src/com/aelitis/net/udp/mc/MCGroupAdapter.java
index 4dd7bfd..9b8d5b8 100644
--- a/azureus2/src/com/aelitis/net/udp/mc/MCGroupAdapter.java
+++ b/azureus2/src/com/aelitis/net/udp/mc/MCGroupAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/mc/MCGroupException.java b/azureus2/src/com/aelitis/net/udp/mc/MCGroupException.java
index d4557e5..4c5433e 100644
--- a/azureus2/src/com/aelitis/net/udp/mc/MCGroupException.java
+++ b/azureus2/src/com/aelitis/net/udp/mc/MCGroupException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/mc/MCGroupFactory.java b/azureus2/src/com/aelitis/net/udp/mc/MCGroupFactory.java
index 483e7f8..24f6560 100644
--- a/azureus2/src/com/aelitis/net/udp/mc/MCGroupFactory.java
+++ b/azureus2/src/com/aelitis/net/udp/mc/MCGroupFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/mc/impl/MCGroupImpl.java b/azureus2/src/com/aelitis/net/udp/mc/impl/MCGroupImpl.java
index 66ca673..1111db9 100644
--- a/azureus2/src/com/aelitis/net/udp/mc/impl/MCGroupImpl.java
+++ b/azureus2/src/com/aelitis/net/udp/mc/impl/MCGroupImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacket.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacket.java
index cef4890..a0ce3e7 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacket.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacket.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandler.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandler.java
index 4318d30..23d58bc 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandler.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerException.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerException.java
index cfd1300..0416b03 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerException.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerFactory.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerFactory.java
index 389f603..7199b87 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerFactory.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerRequest.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerRequest.java
index d4e27e6..9e0e4e3 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerRequest.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Jun-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerStats.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerStats.java
index f3a1905..bcc29fe 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerStats.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketHandlerStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReceiver.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReceiver.java
index bebf1e7..f855d0d 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReceiver.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReceiver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReply.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReply.java
index a66a784..eb2ad4c 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReply.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReply.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReplyDecoder.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReplyDecoder.java
index 5c06258..6539da4 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReplyDecoder.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketReplyDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketRequest.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketRequest.java
index d855a6f..d406769 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketRequest.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketRequest.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketRequestDecoder.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketRequestDecoder.java
index 0ddbc84..6072ac8 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketRequestDecoder.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPacketRequestDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPrimordialHandler.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPrimordialHandler.java
index 8fbd842..51f4780 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPPrimordialHandler.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPPrimordialHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPReleasablePacketHandler.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPReleasablePacketHandler.java
index cef08d7..7a84115 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPReleasablePacketHandler.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPReleasablePacketHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/uc/PRUDPRequestHandler.java b/azureus2/src/com/aelitis/net/udp/uc/PRUDPRequestHandler.java
index 402b5df..8cbf6c9 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/PRUDPRequestHandler.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/PRUDPRequestHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerFactoryImpl.java b/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerFactoryImpl.java
index ec61cd0..ea8c6f7 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerFactoryImpl.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerFactoryImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerImpl.java b/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerImpl.java
index da7a3e5..ea9319b 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerImpl.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerRequestImpl.java b/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerRequestImpl.java
index 8b63822..2e8cda9 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerRequestImpl.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerRequestImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerSocks.java b/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerSocks.java
index 67b9d8c..b1966da 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerSocks.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerSocks.java
@@ -2,20 +2,19 @@
  * Created on Jun 8, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -36,6 +35,7 @@ import java.net.Socket;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.config.ParameterListener;
+import org.gudy.azureus2.core3.util.AddressUtils;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.HostNameToIPResolver;
 
@@ -174,8 +174,8 @@ PRUDPPacketHandlerSocks
 		      	mapped_ip = AEProxyFactory.getAddressMapper().internalise( target.getHostName() );
 		      	
 		    }else{
-		    	  
-		      	mapped_ip = target.getAddress().getHostName();
+		    	
+		      	mapped_ip = AddressUtils.getHostNameNoResolve( target );
 		    }
 		    
 		    dos.writeByte( (byte)5 ); // version
diff --git a/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerStatsImpl.java b/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerStatsImpl.java
index 2719f2c..cb18d83 100644
--- a/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerStatsImpl.java
+++ b/azureus2/src/com/aelitis/net/udp/uc/impl/PRUDPPacketHandlerStatsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnP.java b/azureus2/src/com/aelitis/net/upnp/UPnP.java
index 25610ea..492bce8 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnP.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnP.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPAction.java b/azureus2/src/com/aelitis/net/upnp/UPnPAction.java
index 64ed07f..c6df09b 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPAction.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPAction.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPActionArgument.java b/azureus2/src/com/aelitis/net/upnp/UPnPActionArgument.java
index 215d3da..47ad4f3 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPActionArgument.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPActionArgument.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPActionInvocation.java b/azureus2/src/com/aelitis/net/upnp/UPnPActionInvocation.java
index fa2dbc7..0472d05 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPActionInvocation.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPActionInvocation.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPAdapter.java b/azureus2/src/com/aelitis/net/upnp/UPnPAdapter.java
index 8cd02d2..04bbd4c 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPAdapter.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPDevice.java b/azureus2/src/com/aelitis/net/upnp/UPnPDevice.java
index 5d092d2..86fc3a6 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPDevice.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPDevice.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPDeviceImage.java b/azureus2/src/com/aelitis/net/upnp/UPnPDeviceImage.java
index 5c81611..df2d91c 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPDeviceImage.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPDeviceImage.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.net.upnp;
 
 public interface UPnPDeviceImage
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPException.java b/azureus2/src/com/aelitis/net/upnp/UPnPException.java
index a01780a..223c74f 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPException.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,14 +14,15 @@
  * 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;
 
+import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument;
+
+import com.aelitis.net.upnp.impl.services.UPnPActionImpl;
+
 /**
  * @author parg
  *
@@ -31,6 +32,13 @@ public class
 UPnPException
 	extends Exception
 {
+	public String soap_action;
+	public UPnPActionImpl action;
+	public String fault;
+	
+	public int fault_code;
+	public SimpleXMLParserDocument resp_doc;
+
 	public 
 	UPnPException(
 		String		str )
@@ -44,4 +52,34 @@ UPnPException
 	{
 		super( str, cause );
 	}
+
+	public
+	UPnPException(
+			String string, 
+			Throwable e, 
+			String soap_action,
+			UPnPActionImpl action,
+			SimpleXMLParserDocument resp_doc)
+	{
+			super(string, e);
+  		this.soap_action = soap_action;
+  		this.action = action;
+  		this.resp_doc = resp_doc;
+	}
+
+	public UPnPException(
+			String message, 
+			String soap_action,
+			UPnPActionImpl action, 
+			SimpleXMLParserDocument resp_doc, 
+			String fault,
+			int fault_code)
+	{
+		super(message);
+		this.soap_action = soap_action;
+		this.action = action;
+		this.resp_doc = resp_doc;
+		this.fault = fault;
+		this.fault_code = fault_code;
+	}
 }
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPFactory.java b/azureus2/src/com/aelitis/net/upnp/UPnPFactory.java
index 773821f..4f5719a 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPFactory.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPListener.java b/azureus2/src/com/aelitis/net/upnp/UPnPListener.java
index c1d40e9..d431cdd 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPListener.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPLogListener.java b/azureus2/src/com/aelitis/net/upnp/UPnPLogListener.java
index 94040e9..a8bc8ab 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPLogListener.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPLogListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPRootDevice.java b/azureus2/src/com/aelitis/net/upnp/UPnPRootDevice.java
index 9566391..bebe5f1 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPRootDevice.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPRootDevice.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPRootDeviceListener.java b/azureus2/src/com/aelitis/net/upnp/UPnPRootDeviceListener.java
index cd63af4..7664e1a 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPRootDeviceListener.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPRootDeviceListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPSSDP.java b/azureus2/src/com/aelitis/net/upnp/UPnPSSDP.java
index cda3fea..2715344 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPSSDP.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPSSDP.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPSSDPAdapter.java b/azureus2/src/com/aelitis/net/upnp/UPnPSSDPAdapter.java
index 4197457..db490be 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPSSDPAdapter.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPSSDPAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPSSDPListener.java b/azureus2/src/com/aelitis/net/upnp/UPnPSSDPListener.java
index de76f46..1cf5948 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPSSDPListener.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPSSDPListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPService.java b/azureus2/src/com/aelitis/net/upnp/UPnPService.java
index 0662ee1..cf6fd94 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPService.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPService.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/UPnPStateVariable.java b/azureus2/src/com/aelitis/net/upnp/UPnPStateVariable.java
index 2ebd1ed..46b2cb1 100644
--- a/azureus2/src/com/aelitis/net/upnp/UPnPStateVariable.java
+++ b/azureus2/src/com/aelitis/net/upnp/UPnPStateVariable.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGD.java b/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGD.java
index 43ebb70..7254496 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGD.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGD.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGDFactory.java b/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGDFactory.java
index 1d9e3ee..dc238a5 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGDFactory.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGDFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGDListener.java b/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGDListener.java
index 5c85a84..163bdf6 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGDListener.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/SSDPIGDListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/UPnPImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/UPnPImpl.java
index 3614db3..803d6df 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/UPnPImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/UPnPImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -691,7 +688,7 @@ UPnPImpl
 					fails[1] = SystemTime.getMonotonousTime();
 				}
 			
-				adapter.log( Debug.getNestedExceptionMessageAndStack(e));
+				adapter.log( "Failed to parse XML from :" + url_str + ": " + Debug.getNestedExceptionMessageAndStack(e));
 			}
 			
 			if (e instanceof UPnPException ){
@@ -912,7 +909,7 @@ UPnPImpl
 						
 						pw.flush();
 						
-						InputStream	is = HTTPUtils.decodeChunkedEncoding( socket );
+						InputStream	is = HTTPUtils.decodeChunkedEncoding( socket, true );
 						
 						return( parseXML( is ));
 						
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPDeviceImageImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPDeviceImageImpl.java
index bd39efa..0b033fd 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPDeviceImageImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPDeviceImageImpl.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.net.upnp.impl.device;
 
 import com.aelitis.net.upnp.UPnPDeviceImage;
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPDeviceImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPDeviceImpl.java
index c4a25b8..5b18eeb 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPDeviceImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPDeviceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,11 @@
  * 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.device;
 
-import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentAttribute;
 import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentNode;
 
 /**
@@ -69,7 +65,7 @@ UPnPDeviceImpl
 		root_device		= _root_device;
 		
 		device_type		= getMandatoryField( device_node, "DeviceType" );
-		friendly_name	= getMandatoryField( device_node, "FriendlyName" );
+		friendly_name	= getOptionalField( device_node, "FriendlyName" );	// should be mandatory but missing on DD-WRT (for example)
 		
 		/*
 		  <modelName>3Com ADSL 11g</modelName> 
@@ -85,6 +81,28 @@ UPnPDeviceImpl
 		model_url			= getOptionalField( device_node, "modelURL");
 		presentation_url	= getOptionalField( device_node, "presentationURL");
 		
+		if ( friendly_name == null ){
+			
+			// handle fact that mandatory field might be missing
+			
+			String[] bits = { manufacturer, model_description, model_number };
+			
+			friendly_name = "";
+			
+			for ( String bit: bits ){
+				
+				if ( bit != null ){
+				
+					friendly_name += (friendly_name.length()==0?"":"/") + bit;
+				}
+			}
+			
+			if ( friendly_name.length() == 0 ){
+				
+				friendly_name = "UPnP Device";
+			}
+		}
+		
 		boolean	interested = device_type.equalsIgnoreCase( "urn:schemas-upnp-org:device:WANConnectionDevice:1" );
 		
 		root_device.getUPnP().log( indent + friendly_name + (interested?" *":""));
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPRootDeviceImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPRootDeviceImpl.java
index 3ee0985..34943f0 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPRootDeviceImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/device/UPnPRootDeviceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -274,7 +271,14 @@ UPnPRootDeviceImpl
 			
 			p1 = abs_url.indexOf( "/", p1 );
 			
-			abs_url = abs_url.substring( 0, p1 );
+			if ( p1 == -1 ){
+				
+				// no trailing / (e.g. http://192.167.2.3:1234 )
+				
+			}else{
+			
+				abs_url = abs_url.substring( 0, p1 );
+			}
 			
 			return( abs_url + (url.startsWith("/")?"":"/") + url );
 		}
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionArgumentImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionArgumentImpl.java
index 593bc4c..70fa28a 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionArgumentImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionArgumentImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionImpl.java
index 5219ed0..27f6e6f 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionInvocationImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionInvocationImpl.java
index ced1628..f02cf59 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionInvocationImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPActionInvocationImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -30,6 +27,7 @@ package com.aelitis.net.upnp.impl.services;
 import java.util.*;
 
 import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument;
+import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentAttribute;
 import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentNode;
 
 import com.aelitis.net.upnp.*;
@@ -69,6 +67,7 @@ UPnPActionInvocationImpl
 		UPnPService	service = action.getService();
 		
 		String	soap_action = service.getServiceType() + "#" + action.getName();
+		SimpleXMLParserDocument resp_doc = null;
 		
 		try{
 			String	request =
@@ -95,22 +94,59 @@ UPnPActionInvocationImpl
 							
 				// try standard POST
 			
-			SimpleXMLParserDocument resp_doc	= ((UPnPDeviceImpl)action.getService().getDevice()).getUPnP().performSOAPRequest( service, soap_action, request );
+			resp_doc	= ((UPnPDeviceImpl)action.getService().getDevice()).getUPnP().performSOAPRequest( service, soap_action, request );
 						
 			SimpleXMLParserDocumentNode	body = resp_doc.getChild( "Body" );
 			
-			SimpleXMLParserDocumentNode fault = body.getChild( "Fault" );
+			SimpleXMLParserDocumentNode faultSection = body.getChild( "Fault" );
 			
-			if ( fault != null ){
+			if ( faultSection != null ){
 				
-				throw( new UPnPException( "Invoke of '" + soap_action + "' failed - fault reported: " + fault.getValue()));
+				String faultValue = faultSection.getValue();
+				if (faultValue != null && faultValue.length() > 0) {
+  				throw (new UPnPException("Invoke of '" + soap_action
+  						+ "' failed - fault reported: " + faultValue, soap_action,
+  						action, resp_doc, faultValue, -1));
+				}
+				
+				SimpleXMLParserDocumentNode faultDetail = faultSection.getChild("detail");
+				if (faultDetail != null) {
+					SimpleXMLParserDocumentNode error = faultDetail.getChild("UPnPError");
+					if (error != null) {
+						int errCodeNumber = -1;
+						String errDescValue = null;
+						
+						SimpleXMLParserDocumentNode errCode = error.getChild("errorCode");
+						if (errCode != null) {
+							String errCodeValue = errCode.getValue();
+							try {
+								errCodeNumber = Integer.parseInt(errCodeValue);
+							} catch (Throwable t) {
+							}
+						}
+
+						SimpleXMLParserDocumentNode errDesc = error.getChild("errorDescription");
+						if (errDesc != null) {
+							errDescValue = errDesc.getValue();
+							if (errDescValue != null && errDescValue.length() == 0) {
+								errDescValue = null;
+							}
+						}
+								
+	  				throw (new UPnPException("Invoke of '" + soap_action
+	  						+ "' failed - fault reported: " + errDescValue, soap_action,
+	  						action, resp_doc, errDescValue, errCodeNumber));
+					}
+				}
 			}
 			
 			SimpleXMLParserDocumentNode	resp_node = body.getChild( action.getName() + "Response" );
 			
 			if ( resp_node == null ){
 				
-				throw( new UPnPException( "Invoke of '" + soap_action + "' failed - response missing: " + body.getValue()));
+				throw (new UPnPException("Invoke of '" + soap_action
+						+ "' failed - response missing: " + body.getValue(), soap_action,
+						action, resp_doc, null, -1));
 			}
 			
 			SimpleXMLParserDocumentNode[]	out_nodes = resp_node.getChildren();
@@ -131,7 +167,9 @@ UPnPActionInvocationImpl
 				throw((UPnPException)e);
 			}
 			
-			throw( new UPnPException( "Invoke of '" + soap_action + "' on '" + action.getService().getControlURLs() + "' failed: " + e.getMessage(), e ));	
+			throw new UPnPException("Invoke of '" + soap_action + "' on '"
+					+ action.getService().getControlURLs() + "' failed: "
+					+ e.getMessage(), e, soap_action, action, resp_doc);
 		}
 	}
 	
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSOfflineDownloaderImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSOfflineDownloaderImpl.java
index 9886df4..64d2823 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSOfflineDownloaderImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSOfflineDownloaderImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANCommonInterfaceConfigImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANCommonInterfaceConfigImpl.java
index 9b1826c..232c535 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANCommonInterfaceConfigImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANCommonInterfaceConfigImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANConnectionImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANConnectionImpl.java
index b5a6430..daef71d 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANConnectionImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANConnectionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANIPConnectionImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANIPConnectionImpl.java
index 1258ac4..a9f8aac 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANIPConnectionImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANIPConnectionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANPPPConnectionImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANPPPConnectionImpl.java
index 47d6b56..e6e1af6 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANPPPConnectionImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPSSWANPPPConnectionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPServiceImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPServiceImpl.java
index 11ebe91..67c0995 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPServiceImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPServiceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPStateVariableImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPStateVariableImpl.java
index 60327d0..97509a9 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPStateVariableImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/services/UPnPStateVariableImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/ssdp/SSDPCore.java b/azureus2/src/com/aelitis/net/upnp/impl/ssdp/SSDPCore.java
index 6e51fb8..8b77f8c 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/ssdp/SSDPCore.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/ssdp/SSDPCore.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/impl/ssdp/SSDPIGDImpl.java b/azureus2/src/com/aelitis/net/upnp/impl/ssdp/SSDPIGDImpl.java
index 5df4159..78bf2b6 100644
--- a/azureus2/src/com/aelitis/net/upnp/impl/ssdp/SSDPIGDImpl.java
+++ b/azureus2/src/com/aelitis/net/upnp/impl/ssdp/SSDPIGDImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/services/UPnPOfflineDownloader.java b/azureus2/src/com/aelitis/net/upnp/services/UPnPOfflineDownloader.java
index 83b29fa..a620bdf 100644
--- a/azureus2/src/com/aelitis/net/upnp/services/UPnPOfflineDownloader.java
+++ b/azureus2/src/com/aelitis/net/upnp/services/UPnPOfflineDownloader.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/services/UPnPSpecificService.java b/azureus2/src/com/aelitis/net/upnp/services/UPnPSpecificService.java
index 5b6cb2d..04c1ca9 100644
--- a/azureus2/src/com/aelitis/net/upnp/services/UPnPSpecificService.java
+++ b/azureus2/src/com/aelitis/net/upnp/services/UPnPSpecificService.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANCommonInterfaceConfig.java b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANCommonInterfaceConfig.java
index 7e6e958..ec2ab91 100644
--- a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANCommonInterfaceConfig.java
+++ b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANCommonInterfaceConfig.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnection.java b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnection.java
index 59a93e0..384acf9 100644
--- a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnection.java
+++ b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnectionListener.java b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnectionListener.java
index 59151e3..0ad1cd1 100644
--- a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnectionListener.java
+++ b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnectionListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10 May 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnectionPortMapping.java b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnectionPortMapping.java
index 9d58590..55d02d0 100644
--- a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnectionPortMapping.java
+++ b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANConnectionPortMapping.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANIPConnection.java b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANIPConnection.java
index 382166e..bac6dfb 100644
--- a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANIPConnection.java
+++ b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANIPConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANPPPConnection.java b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANPPPConnection.java
index b37e2ab..4ae0057 100644
--- a/azureus2/src/com/aelitis/net/upnp/services/UPnPWANPPPConnection.java
+++ b/azureus2/src/com/aelitis/net/upnp/services/UPnPWANPPPConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowser.java b/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowser.java
index 7eb60b3..1c7e027 100644
--- a/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowser.java
+++ b/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowser.java
@@ -2,20 +2,19 @@
  * Created on Dec 19, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowserFactory.java b/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowserFactory.java
index 95c05e9..3031458 100644
--- a/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowserFactory.java
+++ b/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowserFactory.java
@@ -2,20 +2,19 @@
  * Created on Dec 19, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowserListener.java b/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowserListener.java
index 988eb22..5a989b2 100644
--- a/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowserListener.java
+++ b/azureus2/src/com/aelitis/net/upnpms/UPNPMSBrowserListener.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2012 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/net/upnpms/UPNPMSContainer.java b/azureus2/src/com/aelitis/net/upnpms/UPNPMSContainer.java
index f84080a..5196639 100644
--- a/azureus2/src/com/aelitis/net/upnpms/UPNPMSContainer.java
+++ b/azureus2/src/com/aelitis/net/upnpms/UPNPMSContainer.java
@@ -2,20 +2,19 @@
  * Created on Dec 19, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/net/upnpms/UPNPMSItem.java b/azureus2/src/com/aelitis/net/upnpms/UPNPMSItem.java
index a253cac..a10a4a5 100644
--- a/azureus2/src/com/aelitis/net/upnpms/UPNPMSItem.java
+++ b/azureus2/src/com/aelitis/net/upnpms/UPNPMSItem.java
@@ -2,20 +2,19 @@
  * Created on Dec 19, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/net/upnpms/UPNPMSNode.java b/azureus2/src/com/aelitis/net/upnpms/UPNPMSNode.java
index 1734df7..0ef3dc2 100644
--- a/azureus2/src/com/aelitis/net/upnpms/UPNPMSNode.java
+++ b/azureus2/src/com/aelitis/net/upnpms/UPNPMSNode.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2012 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/net/upnpms/UPnPMSException.java b/azureus2/src/com/aelitis/net/upnpms/UPnPMSException.java
index b49dddb..5a69062 100644
--- a/azureus2/src/com/aelitis/net/upnpms/UPnPMSException.java
+++ b/azureus2/src/com/aelitis/net/upnpms/UPnPMSException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/com/aelitis/net/upnpms/impl/Test.java b/azureus2/src/com/aelitis/net/upnpms/impl/Test.java
index 7028f72..73e15fe 100644
--- a/azureus2/src/com/aelitis/net/upnpms/impl/Test.java
+++ b/azureus2/src/com/aelitis/net/upnpms/impl/Test.java
@@ -2,20 +2,19 @@
  * Created on Dec 19, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSBrowserImpl.java b/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSBrowserImpl.java
index d145547..ffb768f 100644
--- a/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSBrowserImpl.java
+++ b/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSBrowserImpl.java
@@ -2,20 +2,19 @@
  * Created on Dec 19, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -205,7 +204,7 @@ UPNPMSBrowserImpl
 			rd.setProperty( "URL_X-AV-Client-Info", "av=1.0; cn=\"Azureus Software, Inc.\"; mn=\"" + client_name + "\"; mv=\""+ Constants.AZUREUS_VERSION + "\"" );
 			rd.setProperty( "URL_Content-Type", "text/xml; charset=\"utf-8\"" );
 					
-			SimpleXMLParserDocument  doc = SimpleXMLParserDocumentFactory.create( rd.download());
+			SimpleXMLParserDocument  doc = SimpleXMLParserDocumentFactory.create( url, rd.download());
 
 			// doc.print();
 			
diff --git a/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSContainerImpl.java b/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSContainerImpl.java
index 05f9c66..4f575e4 100644
--- a/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSContainerImpl.java
+++ b/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSContainerImpl.java
@@ -2,20 +2,19 @@
  * Created on Dec 20, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSItemImpl.java b/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSItemImpl.java
index 77bf70d..67eb5d2 100644
--- a/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSItemImpl.java
+++ b/azureus2/src/com/aelitis/net/upnpms/impl/UPNPMSItemImpl.java
@@ -2,20 +2,19 @@
  * Created on Dec 20, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus3/src/org/apache/commons/lang/Entities.java b/azureus2/src/org/apache/commons/lang/Entities.java
similarity index 100%
rename from azureus3/src/org/apache/commons/lang/Entities.java
rename to azureus2/src/org/apache/commons/lang/Entities.java
diff --git a/azureus3/src/org/apache/commons/lang/IntHashMap.java b/azureus2/src/org/apache/commons/lang/IntHashMap.java
similarity index 100%
rename from azureus3/src/org/apache/commons/lang/IntHashMap.java
rename to azureus2/src/org/apache/commons/lang/IntHashMap.java
diff --git a/azureus2/src/org/bouncycastle/LICENSE.java b/azureus2/src/org/bouncycastle/LICENSE.java
deleted file mode 100644
index f3573c4..0000000
--- a/azureus2/src/org/bouncycastle/LICENSE.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.bouncycastle;
-
-/**
- * The Bouncy Castle License
- *
- * Copyright (c) 2000 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
- * <p>
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
- * and associated documentation files (the "Software"), to deal in the Software without restriction, 
- * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
- * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- * <p>
- * The above copyright notice and this permission notice shall be included in all copies or substantial
- * portions of the Software.
- * <p>
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-public class LICENSE
-{
-    public static String licenseText =
-      "Copyright (c) 2000 The Legion Of The Bouncy Castle (http://www.bouncycastle.org) "
-      + System.getProperty("line.separator")
-      + System.getProperty("line.separator")
-      + "Permission is hereby granted, free of charge, to any person obtaining a copy of this software "
-      + System.getProperty("line.separator")
-      + "and associated documentation files (the \"Software\"), to deal in the Software without restriction, "
-      + System.getProperty("line.separator")
-      + "including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, "
-      + System.getProperty("line.separator")
-      + "and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,"
-      + System.getProperty("line.separator")
-      + "subject to the following conditions:"
-      + System.getProperty("line.separator")
-      + System.getProperty("line.separator")
-      + "The above copyright notice and this permission notice shall be included in all copies or substantial"
-      + System.getProperty("line.separator")
-      + "portions of the Software."
-      + System.getProperty("line.separator")
-      + System.getProperty("line.separator")
-      + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,"
-      + System.getProperty("line.separator")
-      + "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR"
-      + System.getProperty("line.separator")
-      + "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE"
-      + System.getProperty("line.separator")
-      + "LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR"
-      + System.getProperty("line.separator")
-      + "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER"
-      + System.getProperty("line.separator")
-      + "DEALINGS IN THE SOFTWARE.";
-
-    public static void main(
-        String[]    args)
-    {
-        System.out.println(licenseText);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1Choice.java b/azureus2/src/org/bouncycastle/asn1/ASN1Choice.java
deleted file mode 100644
index 603131d..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1Choice.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * Marker interface for CHOICE objects - if you implement this in a role your
- * own object any attempt to tag the object implicitly will convert the tag to
- * an explicit one as the encoding rules require.
- * <p>
- * If you use this interface your class should also implement the getInstance
- * pattern which takes a tag object and the tagging mode used. 
- */
-public interface ASN1Choice
-{
-    // marker interface
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1Encodable.java b/azureus2/src/org/bouncycastle/asn1/ASN1Encodable.java
deleted file mode 100644
index 34b1b8f..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1Encodable.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-public abstract class ASN1Encodable
-    implements DEREncodable
-{
-    public static final String DER = "DER";
-    public static final String BER = "BER";
-    
-    public byte[] getEncoded() 
-        throws IOException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        ASN1OutputStream        aOut = new ASN1OutputStream(bOut);
-        
-        aOut.writeObject(this);
-        
-        return bOut.toByteArray();
-    }
-    
-    public byte[] getEncoded(
-        String encoding) 
-        throws IOException
-    {
-        if (encoding.equals(DER))
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            DEROutputStream         dOut = new DEROutputStream(bOut);
-            
-            dOut.writeObject(this);
-            
-            return bOut.toByteArray();
-        }
-        
-        return this.getEncoded();
-    }
-    
-    /**
-     * Return the DER encoding of the object, null if the DER encoding can not be made.
-     * 
-     * @return a DER byte array, null otherwise.
-     */
-    public byte[] getDEREncoded()
-    {
-        try
-        {
-            return this.getEncoded(DER);
-        }
-        catch (IOException e)
-        {
-            return null;
-        }
-    }
-    
-    public int hashCode()
-    {
-        return this.toASN1Object().hashCode();
-    }
-
-    public boolean equals(
-        Object  o)
-    {
-        if (this == o)
-        {
-            return true;
-        }
-        
-        if (!(o instanceof DEREncodable))
-        {
-            return false;
-        }
-
-        DEREncodable other = (DEREncodable)o;
-
-        return this.toASN1Object().equals(other.getDERObject());
-    }
-
-    public DERObject getDERObject()
-    {        
-        return this.toASN1Object();
-    }
-
-    public abstract DERObject toASN1Object();
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1EncodableVector.java b/azureus2/src/org/bouncycastle/asn1/ASN1EncodableVector.java
deleted file mode 100644
index 1f50ddf..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1EncodableVector.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * the parent class for this will eventually disappear. Use this one!
- */
-public class ASN1EncodableVector
-    extends DEREncodableVector
-{
-    // migrating from DEREncodeableVector
-    public ASN1EncodableVector()
-    {
-        
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1Generator.java b/azureus2/src/org/bouncycastle/asn1/ASN1Generator.java
deleted file mode 100644
index 50cb705..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1Generator.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.OutputStream;
-
-public abstract class ASN1Generator
-{
-    protected OutputStream _out;
-    
-    public ASN1Generator(OutputStream out)
-    {
-        _out = out;
-    }
-    
-    public abstract OutputStream getRawOutputStream();
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1InputStream.java b/azureus2/src/org/bouncycastle/asn1/ASN1InputStream.java
deleted file mode 100644
index 44c0332..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1InputStream.java
+++ /dev/null
@@ -1,481 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Vector;
-
-/**
- * a general purpose ASN.1 decoder - note: this class differs from the
- * others in that it returns null after it has read the last object in
- * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
- * returned.
- */
-public class ASN1InputStream
-    extends FilterInputStream
-    implements DERTags
-{
-    private static final DERObject END_OF_STREAM = new DERObject()
-    {
-        void encode(
-            DEROutputStream out)
-        throws IOException
-        {
-            throw new IOException("Eeek!");
-        }
-        public int hashCode()
-        {
-            return 0;
-        }
-        public boolean equals(
-            Object o) 
-        {
-            return o == this;
-        }
-    };
-    
-    boolean eofFound = false;
-    int     limit = Integer.MAX_VALUE;
-
-    public ASN1InputStream(
-        InputStream is)
-    {
-        super(is);
-    }
-
-    /**
-     * Create an ASN1InputStream based on the input byte array. The length of DER objects in
-     * the stream is automatically limited to the length of the input array.
-     * 
-     * @param input array containing ASN.1 encoded data.
-     */
-    public ASN1InputStream(
-        byte[] input)
-    {
-        this(new ByteArrayInputStream(input), input.length);
-    }
-    
-    /**
-     * Create an ASN1InputStream where no DER object will be longer than limit.
-     * 
-     * @param input stream containing ASN.1 encoded data.
-     * @param limit maximum size of a DER encoded object.
-     */
-    public ASN1InputStream(
-        InputStream input,
-        int         limit)
-    {
-        super(input);
-        this.limit = limit;
-    }
-    
-    protected int readLength()
-        throws IOException
-    {
-        int length = read();
-        if (length < 0)
-        {
-            throw new IOException("EOF found when length expected");
-        }
-
-        if (length == 0x80)
-        {
-            return -1;      // indefinite-length encoding
-        }
-
-        if (length > 127)
-        {
-            int size = length & 0x7f;
-
-            if (size > 4)
-            {
-                throw new IOException("DER length more than 4 bytes");
-            }
-            
-            length = 0;
-            for (int i = 0; i < size; i++)
-            {
-                int next = read();
-
-                if (next < 0)
-                {
-                    throw new IOException("EOF found reading length");
-                }
-
-                length = (length << 8) + next;
-            }
-            
-            if (length < 0)
-            {
-                throw new IOException("corrupted stream - negative length found");
-            }
-            
-            if (length >= limit)   // after all we must have read at least 1 byte
-            {
-                throw new IOException("corrupted stream - out of bounds length found");
-            }
-        }
-
-        return length;
-    }
-
-    protected void readFully(
-        byte[]  bytes)
-        throws IOException
-    {
-        int     left = bytes.length;
-        int     len;
-
-        if (left == 0)
-        {
-            return;
-        }
-
-        while ((len = read(bytes, bytes.length - left, left)) > 0)
-        {
-            if ((left -= len) == 0)
-            {
-                return;
-            }
-        }
-
-        if (left != 0)
-        {
-            throw new EOFException("EOF encountered in middle of object");
-        }
-    }
-
-    /**
-     * build an object given its tag and the number of bytes to construct it from.
-     */
-    protected DERObject buildObject(
-        int       tag,
-        int       tagNo,
-        int       length)
-        throws IOException
-    {
-        if ((tag & APPLICATION) != 0)
-        {
-            return new DERApplicationSpecific(tagNo, readDefiniteLengthFully(length));
-        }
-
-        boolean isConstructed = (tag & CONSTRUCTED) != 0;
-
-        if (isConstructed)
-        {
-            switch (tag)
-            {
-            case SEQUENCE | CONSTRUCTED:
-                return new DERSequence(buildDerEncodableVector(length));
-            case SET | CONSTRUCTED:
-                return new DERSet(buildDerEncodableVector(length), false);
-            case OCTET_STRING | CONSTRUCTED:
-                return buildDerConstructedOctetString(length);
-            default:
-            {
-                //
-                // with tagged object tag number is bottom 5 bits
-                //
-                if ((tag & TAGGED) != 0)  
-                {
-                    if (length == 0)     // empty tag!
-                    {
-                        return new DERTaggedObject(false, tagNo, new DERSequence());
-                    }
-
-                    ASN1EncodableVector v = buildDerEncodableVector(length);
-
-                    if (v.size() == 1)
-                    {
-                        //
-                        // explicitly tagged (probably!) - if it isn't we'd have to
-                        // tell from the context
-                        //
-                        return new DERTaggedObject(tagNo, v.get(0));
-                    }
-
-                    return new DERTaggedObject(false, tagNo, new DERSequence(v));
-                }
-
-                return new DERUnknownTag(tag, readDefiniteLengthFully(length));
-            }
-            }
-        }
-
-        byte[] bytes = readDefiniteLengthFully(length);
-
-        switch (tag)
-        {
-        case NULL:
-            return DERNull.INSTANCE;   
-        case BOOLEAN:
-            return new DERBoolean(bytes);
-        case INTEGER:
-            return new DERInteger(bytes);
-        case ENUMERATED:
-            return new DEREnumerated(bytes);
-        case OBJECT_IDENTIFIER:
-            return new DERObjectIdentifier(bytes);
-        case BIT_STRING:
-        {
-            int     padBits = bytes[0];
-            byte[]  data = new byte[bytes.length - 1];
-
-            System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
-
-            return new DERBitString(data, padBits);
-        }
-        case NUMERIC_STRING:
-            return new DERNumericString(bytes);
-        case UTF8_STRING:
-            return new DERUTF8String(bytes);
-        case PRINTABLE_STRING:
-            return new DERPrintableString(bytes);
-        case IA5_STRING:
-            return new DERIA5String(bytes);
-        case T61_STRING:
-            return new DERT61String(bytes);
-        case VISIBLE_STRING:
-            return new DERVisibleString(bytes);
-        case GENERAL_STRING:
-            return new DERGeneralString(bytes);
-        case UNIVERSAL_STRING:
-            return new DERUniversalString(bytes);
-        case BMP_STRING:
-            return new DERBMPString(bytes);
-        case OCTET_STRING:
-            return new DEROctetString(bytes);
-        case UTC_TIME:
-            return new DERUTCTime(bytes);
-        case GENERALIZED_TIME:
-            return new DERGeneralizedTime(bytes);
-        default:
-        {
-            //
-            // with tagged object tag number is bottom 5 bits
-            //
-            if ((tag & TAGGED) != 0)  
-            {
-                if (bytes.length == 0)     // empty tag!
-                {
-                    return new DERTaggedObject(false, tagNo, DERNull.INSTANCE);
-                }
-
-                //
-                // simple type - implicit... return an octet string
-                //
-                return new DERTaggedObject(false, tagNo, new DEROctetString(bytes));
-            }
-
-            return new DERUnknownTag(tag, bytes);
-        }
-        }
-    }
-
-    private byte[] readDefiniteLengthFully(int length)
-        throws IOException
-    {
-        byte[] bytes = new byte[length];
-        readFully(bytes);
-        return bytes;
-    }
-
-    /**
-     * read a string of bytes representing an indefinite length object.
-     */
-    private byte[] readIndefiniteLengthFully()
-        throws IOException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        int                     b, b1;
-
-        b1 = read();
-
-        while ((b = read()) >= 0)
-        {
-            if (b1 == 0 && b == 0)
-            {
-                break;
-            }
-
-            bOut.write(b1);
-            b1 = b;
-        }
-
-        return bOut.toByteArray();
-    }
-
-    private BERConstructedOctetString buildConstructedOctetString(DERObject sentinel)
-        throws IOException
-    {
-        Vector octs = new Vector();
-        DERObject o;
-
-        while ((o = readObject()) != sentinel)
-        {
-            octs.addElement(o);
-        }
-
-        return new BERConstructedOctetString(octs);
-    }
-
-    //
-    // yes, people actually do this...
-    //
-    private BERConstructedOctetString buildDerConstructedOctetString(int length)
-        throws IOException
-    {
-        DefiniteLengthInputStream dIn = new DefiniteLengthInputStream(this, length);
-        ASN1InputStream aIn = new ASN1InputStream(dIn, length);
-
-        return aIn.buildConstructedOctetString(null);
-    }
-
-    private ASN1EncodableVector buildEncodableVector(DERObject sentinel)
-        throws IOException
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-        DERObject o;
-
-        while ((o = readObject()) != sentinel)
-        {
-            v.add(o);
-        }
-
-        return v;
-    }
-
-    private ASN1EncodableVector buildDerEncodableVector(int length)
-        throws IOException
-    {
-        DefiniteLengthInputStream dIn = new DefiniteLengthInputStream(this, length);
-        ASN1InputStream aIn = new ASN1InputStream(dIn, length);
-
-        return aIn.buildEncodableVector(null);
-    }
-
-    public DERObject readObject()
-        throws IOException
-    {
-        int tag = read();
-        if (tag == -1)
-        {
-            if (eofFound)
-            {
-                throw new EOFException("attempt to read past end of file.");
-            }
-
-            eofFound = true;
-
-            return null;
-        }
-    
-        int tagNo = 0;
-        
-        if ((tag & TAGGED) != 0 || (tag & APPLICATION) != 0)
-        {
-            tagNo = readTagNumber(tag);
-        }
-        
-        int     length = readLength();
-
-        if (length < 0)    // indefinite length method
-        {
-            switch (tag)
-            {
-            case NULL:
-                return BERNull.INSTANCE;
-            case SEQUENCE | CONSTRUCTED:
-                return new BERSequence(buildEncodableVector(END_OF_STREAM));
-            case SET | CONSTRUCTED:
-                return new BERSet(buildEncodableVector(END_OF_STREAM), false);
-            case OCTET_STRING | CONSTRUCTED:
-                return buildConstructedOctetString(END_OF_STREAM);
-            default:
-            {
-                //
-                // with tagged object tag number is bottom 5 bits
-                //
-                if ((tag & TAGGED) != 0)  
-                {
-                    //
-                    // simple type - implicit... return an octet string
-                    //
-                    if ((tag & CONSTRUCTED) == 0)
-                    {
-                        byte[] bytes = readIndefiniteLengthFully();
-
-                        return new BERTaggedObject(false, tagNo, new DEROctetString(bytes));
-                    }
-
-                    //
-                    // either constructed or explicitly tagged
-                    //
-                    ASN1EncodableVector v = buildEncodableVector(END_OF_STREAM);
-
-                    if (v.size() == 0)     // empty tag!
-                    {
-                        return new DERTaggedObject(tagNo);
-                    }
-
-                    if (v.size() == 1)
-                    {
-                        //
-                        // explicitly tagged (probably!) - if it isn't we'd have to
-                        // tell from the context
-                        //
-                        return new BERTaggedObject(tagNo, v.get(0));
-                    }
-
-                    return new BERTaggedObject(false, tagNo, new BERSequence(v));
-                }
-
-                throw new IOException("unknown BER object encountered");
-            }
-            }
-        }
-        else
-        {
-            if (tag == 0 && length == 0)    // end of contents marker.
-            {
-                return END_OF_STREAM;
-            }
-
-            return buildObject(tag, tagNo, length);
-        }
-    }
-
-    private int readTagNumber(int tag) 
-        throws IOException
-    {
-        int tagNo = tag & 0x1f;
-
-        if (tagNo == 0x1f)
-        {
-            int b = read();
-
-            tagNo = 0;
-
-            while ((b >= 0) && ((b & 0x80) != 0))
-            {
-                tagNo |= (b & 0x7f);
-                tagNo <<= 7;
-                b = read();
-            }
-
-            if (b < 0)
-            {
-                eofFound = true;
-                throw new EOFException("EOF found inside tag value.");
-            }
-            
-            tagNo |= (b & 0x7f);
-        }
-        
-        return tagNo;
-    }
-}
-
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1Null.java b/azureus2/src/org/bouncycastle/asn1/ASN1Null.java
deleted file mode 100644
index 302d063..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1Null.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * A NULL object.
- */
-public abstract class ASN1Null
-    extends ASN1Object
-{
-    public ASN1Null()
-    {
-    }
-
-    public int hashCode()
-    {
-        return 0;
-    }
-
-    boolean asn1Equals(
-        DERObject o)
-    {
-        if (!(o instanceof ASN1Null))
-        {
-            return false;
-        }
-        
-        return true;
-    }
-
-    abstract void encode(DEROutputStream out)
-        throws IOException;
-
-    public String toString()
-    {
-         return "NULL";
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1Object.java b/azureus2/src/org/bouncycastle/asn1/ASN1Object.java
deleted file mode 100644
index 7a0b113..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1Object.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public abstract  class ASN1Object
-    extends DERObject
-{
-    /**
-     * Create a base ASN.1 object from a byte stream.
-     *
-     * @param data the byte stream to parse.
-     * @return the base ASN.1 object represented by the byte stream.
-     * @exception IOException if there is a problem parsing the data.
-     */
-    public static ASN1Object fromByteArray(byte[] data)
-        throws IOException
-    {
-        ASN1InputStream aIn = new ASN1InputStream(data);
-
-        return (ASN1Object)aIn.readObject();
-    }
-
-    public final boolean equals(Object o)
-    {
-        if (this == o)
-        {
-            return true;
-        }
-        
-        return (o instanceof DEREncodable) && asn1Equals(((DEREncodable)o).getDERObject());
-    }
-
-    public abstract int hashCode();
-
-    abstract void encode(DEROutputStream out) throws IOException;
-
-    abstract boolean asn1Equals(DERObject o);
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1ObjectParser.java b/azureus2/src/org/bouncycastle/asn1/ASN1ObjectParser.java
deleted file mode 100644
index 2bd5489..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1ObjectParser.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-public class ASN1ObjectParser
-{
-    private int              _baseTag;
-    private int              _tagNumber;
-
-    private ASN1StreamParser _aIn;
-
-    protected ASN1ObjectParser(
-        int         baseTag,
-        int         tagNumber,
-        InputStream contentStream)
-    {
-        _baseTag = baseTag;
-        _tagNumber = tagNumber;
-        _aIn = new ASN1StreamParser(contentStream);
-    }
-
-    /**
-     * Return the tag number for this object.
-     *
-     * @return the tag number.
-     */
-    int getTagNumber()
-    {
-        return _tagNumber;
-    }
-
-    int getBaseTag()
-    {
-        return _baseTag;
-    }
-
-    DEREncodable readObject()
-        throws IOException
-    {
-        return _aIn.readObject();
-    }
-
-    ASN1EncodableVector readVector()
-        throws IllegalStateException
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-        DEREncodable obj;
-
-        try
-        {
-            while ((obj = readObject()) != null)
-            {
-                v.add(obj.getDERObject());
-            }
-        }
-        catch (IOException e)
-        {
-            throw new IllegalStateException(e.getMessage());
-        }
-
-        return v;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1OctetString.java b/azureus2/src/org/bouncycastle/asn1/ASN1OctetString.java
deleted file mode 100644
index 6a8f69f..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1OctetString.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package org.bouncycastle.asn1;
-
-import org.bouncycastle.util.encoders.Hex;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.Vector;
-
-public abstract class ASN1OctetString
-    extends ASN1Object
-    implements ASN1OctetStringParser
-{
-    byte[]  string;
-
-    /**
-     * return an Octet String from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want.
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *              be converted.
-     */
-    public static ASN1OctetString getInstance(
-        ASN1TaggedObject    obj,
-        boolean             explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-    
-    /**
-     * return an Octet String from the given object.
-     *
-     * @param obj the object we want converted.
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static ASN1OctetString getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof ASN1OctetString)
-        {
-            return (ASN1OctetString)obj;
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            Vector      v = new Vector();
-            Enumeration e = ((ASN1Sequence)obj).getObjects();
-
-            while (e.hasMoreElements())
-            {
-                v.addElement(e.nextElement());
-            }
-
-            return new BERConstructedOctetString(v);
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * @param string the octets making up the octet string.
-     */
-    public ASN1OctetString(
-        byte[]  string)
-    {
-        this.string = string;
-    }
-
-    public ASN1OctetString(
-        DEREncodable obj)
-    {
-        try
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            DEROutputStream         dOut = new DEROutputStream(bOut);
-
-            dOut.writeObject(obj);
-            dOut.close();
-
-            this.string = bOut.toByteArray();
-        }
-        catch (IOException e)
-        {
-            throw new IllegalArgumentException("Error processing object : " + e.toString());
-        }
-    }
-
-    public InputStream getOctetStream()
-    {
-        return new ByteArrayInputStream(string);
-    }
-
-    public ASN1OctetStringParser parser()
-    {
-        return this;
-    }
-
-    public byte[] getOctets()
-    {
-        return string;
-    }
-
-    public int hashCode()
-    {
-        byte[]  b = this.getOctets();
-        int     value = 0;
-
-        for (int i = 0; i != b.length; i++)
-        {
-            value ^= (b[i] & 0xff) << (i % 4);
-        }
-
-        return value;
-    }
-
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof ASN1OctetString))
-        {
-            return false;
-        }
-
-        ASN1OctetString  other = (ASN1OctetString)o;
-
-        byte[] b1 = other.string;
-        byte[] b2 = this.string;
-
-        if (b1.length != b2.length)
-        {
-            return false;
-        }
-
-        for (int i = 0; i != b1.length; i++)
-        {
-            if (b1[i] != b2[i])
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    abstract void encode(DEROutputStream out)
-        throws IOException;
-
-    public String toString()
-    {
-      return "#"+new String(Hex.encode(string));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1OctetStringParser.java b/azureus2/src/org/bouncycastle/asn1/ASN1OctetStringParser.java
deleted file mode 100644
index 641020c..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1OctetStringParser.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-
-public interface ASN1OctetStringParser
-    extends DEREncodable
-{
-    public InputStream getOctetStream();
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1OutputStream.java b/azureus2/src/org/bouncycastle/asn1/ASN1OutputStream.java
deleted file mode 100644
index 5897d09..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1OutputStream.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class ASN1OutputStream
-    extends DEROutputStream
-{
-    public ASN1OutputStream(
-        OutputStream    os)
-    {
-        super(os);
-    }
-
-    public void writeObject(
-        Object    obj)
-        throws IOException
-    {
-        if (obj == null)
-        {
-            writeNull();
-        }
-        else if (obj instanceof DERObject)
-        {
-            ((DERObject)obj).encode(this);
-        }
-        else if (obj instanceof DEREncodable)
-        {
-            ((DEREncodable)obj).getDERObject().encode(this);
-        }
-        else
-        {
-            throw new IOException("object not ASN1Encodable");
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1Sequence.java b/azureus2/src/org/bouncycastle/asn1/ASN1Sequence.java
deleted file mode 100644
index ff79cb4..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1Sequence.java
+++ /dev/null
@@ -1,218 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-public abstract class ASN1Sequence
-    extends ASN1Object
-{
-    private Vector seq = new Vector();
-
-    /**
-     * return an ASN1Sequence from the given object.
-     *
-     * @param obj the object we want converted.
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static ASN1Sequence getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof ASN1Sequence)
-        {
-            return (ASN1Sequence)obj;
-        }
-
-        throw new IllegalArgumentException("unknown object in getInstance");
-    }
-
-    /**
-     * Return an ASN1 sequence from a tagged object. There is a special
-     * case here, if an object appears to have been explicitly tagged on 
-     * reading but we were expecting it to be implictly tagged in the 
-     * normal course of events it indicates that we lost the surrounding
-     * sequence - so we need to add it back (this will happen if the tagged
-     * object is a sequence that contains other sequences). If you are
-     * dealing with implicitly tagged sequences you really <b>should</b>
-     * be using this method.
-     *
-     * @param obj the tagged object.
-     * @param explicit true if the object is meant to be explicitly tagged,
-     *          false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *          be converted.
-     */
-    public static ASN1Sequence getInstance(
-        ASN1TaggedObject    obj,
-        boolean             explicit)
-    {
-        if (explicit)
-        {
-            if (!obj.isExplicit())
-            {
-                throw new IllegalArgumentException("object implicit - explicit expected.");
-            }
-
-            return (ASN1Sequence)obj.getObject();
-        }
-        else
-        {
-            //
-            // constructed object which appears to be explicitly tagged
-            // when it should be implicit means we have to add the
-            // surrounding sequence.
-            //
-            if (obj.isExplicit())
-            {
-                if (obj instanceof BERTaggedObject)
-                {
-                    return new BERSequence(obj.getObject());
-                }
-                else
-                {
-                    return new DERSequence(obj.getObject());
-                }
-            }
-            else
-            {
-                if (obj.getObject() instanceof ASN1Sequence)
-                {
-                    return (ASN1Sequence)obj.getObject();
-                }
-            }
-        }
-
-        throw new IllegalArgumentException(
-                "unknown object in getInstanceFromTagged");
-    }
-
-    public Enumeration getObjects()
-    {
-        return seq.elements();
-    }
-
-    public ASN1SequenceParser parser()
-    {
-        final ASN1Sequence outer = this;
-
-        return new ASN1SequenceParser()
-        {
-            private final int max = size();
-
-            private int index;
-
-            public DEREncodable readObject() throws IOException
-            {
-                if (index == max)
-                {
-                    return null;
-                }
-                
-                DEREncodable obj = getObjectAt(index++);
-                if (obj instanceof ASN1Sequence)
-                {
-                    return ((ASN1Sequence)obj).parser();
-                }
-                if (obj instanceof ASN1Set)
-                {
-                    return ((ASN1Set)obj).parser();
-                }
-
-                return obj;
-            }
-
-            public DERObject getDERObject()
-            {
-                return outer;
-            }
-        };
-    }
-
-    /**
-     * return the object at the sequence postion indicated by index.
-     *
-     * @param index the sequence number (starting at zero) of the object
-     * @return the object at the sequence postion indicated by index.
-     */
-    public DEREncodable getObjectAt(
-        int index)
-    {
-        return (DEREncodable)seq.elementAt(index);
-    }
-
-    /**
-     * return the number of objects in this sequence.
-     *
-     * @return the number of objects in this sequence.
-     */
-    public int size()
-    {
-        return seq.size();
-    }
-
-    public int hashCode()
-    {
-        Enumeration             e = this.getObjects();
-        int                     hashCode = 0;
-
-        while (e.hasMoreElements())
-        {
-            Object    o = e.nextElement();
-            
-            if (o != null)
-            {
-                hashCode ^= o.hashCode();
-            }
-        }
-
-        return hashCode;
-    }
-
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof ASN1Sequence))
-        {
-            return false;
-        }
-        
-        ASN1Sequence   other = (ASN1Sequence)o;
-
-        if (this.size() != other.size())
-        {
-            return false;
-        }
-
-        Enumeration s1 = this.getObjects();
-        Enumeration s2 = other.getObjects();
-
-        while (s1.hasMoreElements())
-        {
-            DERObject  o1 = ((DEREncodable)s1.nextElement()).getDERObject();
-            DERObject  o2 = ((DEREncodable)s2.nextElement()).getDERObject();
-
-            if (o1 == o2 || (o1 != null && o1.equals(o2)))
-            {
-                continue;
-            }
-
-            return false;
-        }
-
-        return true;
-    }
-
-    protected void addObject(
-        DEREncodable obj)
-    {
-        seq.addElement(obj);
-    }
-
-    abstract void encode(DEROutputStream out)
-        throws IOException;
-
-    public String toString() 
-    {
-      return seq.toString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1SequenceParser.java b/azureus2/src/org/bouncycastle/asn1/ASN1SequenceParser.java
deleted file mode 100644
index ceda6bd..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1SequenceParser.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public interface ASN1SequenceParser
-    extends DEREncodable
-{
-    DEREncodable readObject()
-        throws IOException;
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1Set.java b/azureus2/src/org/bouncycastle/asn1/ASN1Set.java
deleted file mode 100644
index 444158e..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1Set.java
+++ /dev/null
@@ -1,339 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-abstract public class ASN1Set
-    extends ASN1Object
-{
-    protected Vector set = new Vector();
-
-    /**
-     * return an ASN1Set from the given object.
-     *
-     * @param obj the object we want converted.
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static ASN1Set getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof ASN1Set)
-        {
-            return (ASN1Set)obj;
-        }
-
-        throw new IllegalArgumentException("unknown object in getInstance");
-    }
-
-    /**
-     * Return an ASN1 set from a tagged object. There is a special
-     * case here, if an object appears to have been explicitly tagged on 
-     * reading but we were expecting it to be implictly tagged in the 
-     * normal course of events it indicates that we lost the surrounding
-     * set - so we need to add it back (this will happen if the tagged
-     * object is a sequence that contains other sequences). If you are
-     * dealing with implicitly tagged sets you really <b>should</b>
-     * be using this method.
-     *
-     * @param obj the tagged object.
-     * @param explicit true if the object is meant to be explicitly tagged
-     *          false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *          be converted.
-     */
-    public static ASN1Set getInstance(
-        ASN1TaggedObject    obj,
-        boolean             explicit)
-    {
-        if (explicit)
-        {
-            if (!obj.isExplicit())
-            {
-                throw new IllegalArgumentException("object implicit - explicit expected.");
-            }
-
-            return (ASN1Set)obj.getObject();
-        }
-        else
-        {
-            //
-            // constructed object which appears to be explicitly tagged
-            // and it's really implicit means we have to add the
-            // surrounding sequence.
-            //
-            if (obj.isExplicit())
-            {
-                ASN1Set    set = new DERSet(obj.getObject());
-
-                return set;
-            }
-            else
-            {
-                if (obj.getObject() instanceof ASN1Set)
-                {
-                    return (ASN1Set)obj.getObject();
-                }
-
-                //
-                // in this case the parser returns a sequence, convert it
-                // into a set.
-                //
-                ASN1EncodableVector  v = new ASN1EncodableVector();
-
-                if (obj.getObject() instanceof ASN1Sequence)
-                {
-                    ASN1Sequence s = (ASN1Sequence)obj.getObject();
-                    Enumeration e = s.getObjects();
-
-                    while (e.hasMoreElements())
-                    {
-                        v.add((DEREncodable)e.nextElement());
-                    }
-
-                    return new DERSet(v, false);
-                }
-            }
-        }
-
-        throw new IllegalArgumentException(
-                    "unknown object in getInstanceFromTagged");
-    }
-
-    public ASN1Set()
-    {
-    }
-
-    public Enumeration getObjects()
-    {
-        return set.elements();
-    }
-
-    /**
-     * return the object at the set postion indicated by index.
-     *
-     * @param index the set number (starting at zero) of the object
-     * @return the object at the set postion indicated by index.
-     */
-    public DEREncodable getObjectAt(
-        int index)
-    {
-        return (DEREncodable)set.elementAt(index);
-    }
-
-    /**
-     * return the number of objects in this set.
-     *
-     * @return the number of objects in this set.
-     */
-    public int size()
-    {
-        return set.size();
-    }
-
-    public ASN1SetParser parser()
-    {
-        final ASN1Set outer = this;
-
-        return new ASN1SetParser()
-        {
-            private final int max = size();
-
-            private int index;
-
-            public DEREncodable readObject() throws IOException
-            {
-                if (index == max)
-                {
-                    return null;
-                }
-
-                DEREncodable obj = getObjectAt(index++);
-                if (obj instanceof ASN1Sequence)
-                {
-                    return ((ASN1Sequence)obj).parser();
-                }
-                if (obj instanceof ASN1Set)
-                {
-                    return ((ASN1Set)obj).parser();
-                }
-
-                return obj;
-            }
-
-            public DERObject getDERObject()
-            {
-                return outer;
-            }
-        };
-    }
-
-    public int hashCode()
-    {
-        Enumeration             e = this.getObjects();
-        int                     hashCode = 0;
-
-        while (e.hasMoreElements())
-        {
-            hashCode ^= e.nextElement().hashCode();
-        }
-
-        return hashCode;
-    }
-
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof ASN1Set))
-        {
-            return false;
-        }
-
-        ASN1Set   other = (ASN1Set)o;
-
-        if (this.size() != other.size())
-        {
-            return false;
-        }
-
-        Enumeration s1 = this.getObjects();
-        Enumeration s2 = other.getObjects();
-
-        while (s1.hasMoreElements())
-        {
-            DERObject  o1 = ((DEREncodable)s1.nextElement()).getDERObject();
-            DERObject  o2 = ((DEREncodable)s2.nextElement()).getDERObject();
-
-            if (o1 == o2 || (o1 != null && o1.equals(o2)))
-            {
-                continue;
-            }
-
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * return true if a <= b (arrays are assumed padded with zeros).
-     */
-    private boolean lessThanOrEqual(
-         byte[] a,
-         byte[] b)
-    {
-         if (a.length <= b.length)
-         {
-             for (int i = 0; i != a.length; i++)
-             {
-                 int    l = a[i] & 0xff;
-                 int    r = b[i] & 0xff;
-                 
-                 if (r > l)
-                 {
-                     return true;
-                 }
-                 else if (l > r)
-                 {
-                     return false;
-                 }
-             }
-
-             return true;
-         }
-         else
-         {
-             for (int i = 0; i != b.length; i++)
-             {
-                 int    l = a[i] & 0xff;
-                 int    r = b[i] & 0xff;
-                 
-                 if (r > l)
-                 {
-                     return true;
-                 }
-                 else if (l > r)
-                 {
-                     return false;
-                 }
-             }
-
-             return false;
-         }
-    }
-
-    private byte[] getEncoded(
-        DEREncodable obj)
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        ASN1OutputStream        aOut = new ASN1OutputStream(bOut);
-
-        try
-        {
-            aOut.writeObject(obj);
-        }
-        catch (IOException e)
-        {
-            throw new IllegalArgumentException("cannot encode object added to SET");
-        }
-
-        return bOut.toByteArray();
-    }
-
-    protected void sort()
-    {
-        if (set.size() > 1)
-        {
-            boolean    swapped = true;
-            int        lastSwap = set.size() - 1;
-
-            while (swapped)
-            {
-                int    index = 0;
-                int    swapIndex = 0;
-                byte[] a = getEncoded((DEREncodable)set.elementAt(0));
-                
-                swapped = false;
-
-                while (index != lastSwap)
-                {
-                    byte[] b = getEncoded((DEREncodable)set.elementAt(index + 1));
-
-                    if (lessThanOrEqual(a, b))
-                    {
-                        a = b;
-                    }
-                    else
-                    {
-                        Object  o = set.elementAt(index);
-
-                        set.setElementAt(set.elementAt(index + 1), index);
-                        set.setElementAt(o, index + 1);
-
-                        swapped = true;
-                        swapIndex = index;
-                    }
-
-                    index++;
-                }
-
-                lastSwap = swapIndex;
-            }
-        }
-    }
-
-    protected void addObject(
-        DEREncodable obj)
-    {
-        set.addElement(obj);
-    }
-
-    abstract void encode(DEROutputStream out)
-            throws IOException;
-
-    public String toString() 
-    {
-      return set.toString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1SetParser.java b/azureus2/src/org/bouncycastle/asn1/ASN1SetParser.java
deleted file mode 100644
index b09a170..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1SetParser.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public interface ASN1SetParser
-    extends DEREncodable
-{
-    public DEREncodable readObject()
-        throws IOException;
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1StreamParser.java b/azureus2/src/org/bouncycastle/asn1/ASN1StreamParser.java
deleted file mode 100644
index 2acafeb..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1StreamParser.java
+++ /dev/null
@@ -1,222 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-public class ASN1StreamParser
-{
-    InputStream _in;
-
-    private int     _limit;
-    private boolean _eofFound;
-
-    public ASN1StreamParser(
-        InputStream in)
-    {
-        this(in, Integer.MAX_VALUE);
-    }
-
-    public ASN1StreamParser(
-        InputStream in,
-        int         limit)
-    {
-        this._in = in;
-        this._limit = limit;
-    }
-
-    public ASN1StreamParser(
-        byte[] encoding)
-    {
-        this(new ByteArrayInputStream(encoding), encoding.length);
-    }
-
-    InputStream getParentStream()
-    {
-        return _in;
-    }
-
-    private int readLength()
-        throws IOException
-    {
-        int length = _in.read();
-        if (length < 0)
-        {
-            throw new EOFException("EOF found when length expected");
-        }
-
-        if (length == 0x80)
-        {
-            return -1;      // indefinite-length encoding
-        }
-
-        if (length > 127)
-        {
-            int size = length & 0x7f;
-
-            if (size > 4)
-            {
-                throw new IOException("DER length more than 4 bytes");
-            }
-
-            length = 0;
-            for (int i = 0; i < size; i++)
-            {
-                int next = _in.read();
-
-                if (next < 0)
-                {
-                    throw new EOFException("EOF found reading length");
-                }
-
-                length = (length << 8) + next;
-            }
-
-            if (length < 0)
-            {
-                throw new IOException("corrupted stream - negative length found");
-            }
-
-            if (length >= _limit)   // after all we must have read at least 1 byte
-            {
-                throw new IOException("corrupted stream - out of bounds length found");
-            }
-        }
-
-        return length;
-    }
-
-    public DEREncodable readObject()
-        throws IOException
-    {
-        int tag = _in.read();
-        if (tag == -1)
-        {
-            if (_eofFound)
-            {
-                throw new EOFException("attempt to read past end of file.");
-            }
-
-            _eofFound = true;
-
-            return null;
-        }
-
-        //
-        // turn of looking for "00" while we resolve the tag
-        //
-        set00Check(false);
-
-        //
-        // calculate tag number
-        //
-        int baseTagNo = tag & ~DERTags.CONSTRUCTED;
-        int tagNo = baseTagNo;
-
-        if ((tag & DERTags.TAGGED) != 0)
-        {
-            tagNo = tag & 0x1f;
-
-            //
-            // with tagged object tag number is bottom 5 bits, or stored at the start of the content
-            //
-            if (tagNo == 0x1f)
-            {
-                tagNo = 0;
-
-                int b = _in.read();
-
-                while ((b >= 0) && ((b & 0x80) != 0))
-                {
-                    tagNo |= (b & 0x7f);
-                    tagNo <<= 7;
-                    b = _in.read();
-                }
-
-                if (b < 0)
-                {
-                    _eofFound = true;
-
-                    throw new EOFException("EOF encountered inside tag value.");
-                }
-
-                tagNo |= (b & 0x7f);
-            }
-        }
-
-        //
-        // calculate length
-        //
-        int length = readLength();
-
-        if (length < 0)  // indefinite length
-        {
-            IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in);
-
-            switch (baseTagNo)
-            {
-            case DERTags.NULL:
-                while (indIn.read() >= 0)
-                {
-                    // make sure we skip to end of object
-                }
-                return BERNull.INSTANCE;
-            case DERTags.OCTET_STRING:
-                return new BEROctetStringParser(new ASN1ObjectParser(tag, tagNo, indIn));
-            case DERTags.SEQUENCE:
-                return new BERSequenceParser(new ASN1ObjectParser(tag, tagNo, indIn));
-            case DERTags.SET:
-                return new BERSetParser(new ASN1ObjectParser(tag, tagNo, indIn));
-            default:
-                return new BERTaggedObjectParser(tag, tagNo, indIn);
-            }
-        }
-        else
-        {
-            DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
-
-            switch (baseTagNo)
-            {
-            case DERTags.INTEGER:
-                return new DERInteger(defIn.toByteArray());
-            case DERTags.NULL:
-                defIn.toByteArray(); // make sure we read to end of object bytes.
-                return DERNull.INSTANCE;
-            case DERTags.OBJECT_IDENTIFIER:
-                return new DERObjectIdentifier(defIn.toByteArray());
-            case DERTags.OCTET_STRING:
-                return new DEROctetString(defIn.toByteArray());
-            case DERTags.SEQUENCE:
-                return new DERSequence(loadVector(defIn, length)).parser();
-            case DERTags.SET:
-                return new DERSet(loadVector(defIn, length)).parser();
-            default:
-                return new BERTaggedObjectParser(tag, tagNo, defIn);
-            }
-        }
-    }
-
-    private void set00Check(boolean enabled)
-    {
-        if (_in instanceof IndefiniteLengthInputStream)
-        {
-            ((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
-        }
-    }
-
-    private ASN1EncodableVector loadVector(InputStream in, int length)
-        throws IOException
-    {
-        ASN1InputStream         aIn = new ASN1InputStream(in, length);
-        ASN1EncodableVector     v = new ASN1EncodableVector();
-
-        DERObject obj;
-        while ((obj = aIn.readObject()) != null)
-        {
-            v.add(obj);
-        }
-
-        return v;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1TaggedObject.java b/azureus2/src/org/bouncycastle/asn1/ASN1TaggedObject.java
deleted file mode 100644
index a4e792a..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1TaggedObject.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * ASN.1 TaggedObject - in ASN.1 nottation this is any object proceeded by
- * a [n] where n is some number - these are assume to follow the construction
- * rules (as with sequences).
- */
-public abstract class ASN1TaggedObject
-    extends ASN1Object
-    implements ASN1TaggedObjectParser
-{
-    int             tagNo;
-    boolean         empty = false;
-    boolean         explicit = true;
-    DEREncodable    obj = null;
-
-    static public ASN1TaggedObject getInstance(
-        ASN1TaggedObject    obj,
-        boolean             explicit)
-    {
-        if (explicit)
-        {
-            return (ASN1TaggedObject)obj.getObject();
-        }
-
-        throw new IllegalArgumentException("implicitly tagged tagged object");
-    }
-
-    static public ASN1TaggedObject getInstance(
-        Object obj) 
-    {
-        if (obj == null || obj instanceof ASN1TaggedObject) 
-        {
-                return (ASN1TaggedObject)obj;
-        }
-
-        throw new IllegalArgumentException("unknown object in getInstance");
-    }
-
-    /**
-     * Create a tagged object in the explicit style.
-     * 
-     * @param tagNo the tag number for this object.
-     * @param obj the tagged object.
-     */
-    public ASN1TaggedObject(
-        int             tagNo,
-        DEREncodable    obj)
-    {
-        this.explicit = true;
-        this.tagNo = tagNo;
-        this.obj = obj;
-    }
-
-    /**
-     * Create a tagged object with the style given by the value of explicit.
-     * <p>
-     * If the object implements ASN1Choice the tag style will always be changed
-     * to explicit in accordance with the ASN.1 encoding rules.
-     * </p>
-     * @param explicit true if the object is explicitly tagged.
-     * @param tagNo the tag number for this object.
-     * @param obj the tagged object.
-     */
-    public ASN1TaggedObject(
-        boolean         explicit,
-        int             tagNo,
-        DEREncodable    obj)
-    {
-        if (obj instanceof ASN1Choice)
-        {
-            this.explicit = true;
-        }
-        else
-        {
-            this.explicit = explicit;
-        }
-        
-        this.tagNo = tagNo;
-        this.obj = obj;
-    }
-    
-    boolean asn1Equals(
-        DERObject o)
-    {
-        if (!(o instanceof ASN1TaggedObject))
-        {
-            return false;
-        }
-        
-        ASN1TaggedObject other = (ASN1TaggedObject)o;
-        
-        if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
-        {
-            return false;
-        }
-        
-        if(obj == null)
-        {
-            if (other.obj != null)
-            {
-                return false;
-            }
-        }
-        else
-        {
-            if (!(obj.getDERObject().equals(other.obj.getDERObject())))
-            {
-                return false;
-            }
-        }
-        
-        return true;
-    }
-    
-    public int hashCode()
-    {
-        int code = tagNo;
-
-        if (obj != null)
-        {
-            code ^= obj.hashCode();
-        }
-
-        return code;
-    }
-
-    public int getTagNo()
-    {
-        return tagNo;
-    }
-
-    /**
-     * return whether or not the object may be explicitly tagged. 
-     * <p>
-     * Note: if the object has been read from an input stream, the only
-     * time you can be sure if isExplicit is returning the true state of
-     * affairs is if it returns false. An implicitly tagged object may appear
-     * to be explicitly tagged, so you need to understand the context under
-     * which the reading was done as well, see getObject below.
-     */
-    public boolean isExplicit()
-    {
-        return explicit;
-    }
-
-    public boolean isEmpty()
-    {
-        return empty;
-    }
-
-    /**
-     * return whatever was following the tag.
-     * <p>
-     * Note: tagged objects are generally context dependent if you're
-     * trying to extract a tagged object you should be going via the
-     * appropriate getInstance method.
-     */
-    public DERObject getObject()
-    {
-        if (obj != null)
-        {
-            return obj.getDERObject();
-        }
-
-        return null;
-    }
-
-    /**
-     * Return the object held in this tagged object as a parser assuming it has
-     * the type of the passed in tag. If the object doesn't have a parser
-     * associated with it, the base object is returned.
-     */
-    public DEREncodable getObjectParser(
-        int     tag,
-        boolean isExplicit)
-    {
-        switch (tag)
-        {
-        case DERTags.SET:
-            return ASN1Set.getInstance(this, isExplicit).parser();
-        case DERTags.SEQUENCE:
-            return ASN1Sequence.getInstance(this, isExplicit).parser();
-        case DERTags.OCTET_STRING:
-            return ASN1OctetString.getInstance(this, isExplicit).parser();
-        }
-
-        if (isExplicit)
-        {
-            return getObject();
-        }
-
-        throw new RuntimeException("implicit tagging not implemented for tag: " + tag);
-    }
-
-    abstract void encode(DEROutputStream  out)
-        throws IOException;
-
-    public String toString()
-    {
-        return "[" + tagNo + "]" + obj;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ASN1TaggedObjectParser.java b/azureus2/src/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
deleted file mode 100644
index 5574bf8..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public interface ASN1TaggedObjectParser
-    extends DEREncodable
-{
-    public int getTagNo();
-    
-    public DEREncodable getObjectParser(int tag, boolean isExplicit)
-        throws IOException;
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERConstructedOctetString.java b/azureus2/src/org/bouncycastle/asn1/BERConstructedOctetString.java
deleted file mode 100644
index 8693d8b..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERConstructedOctetString.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-public class BERConstructedOctetString
-    extends DEROctetString
-{
-    private static final int MAX_LENGTH = 1000;
-
-    /**
-     * convert a vector of octet strings into a single byte string
-     */
-    static private byte[] toBytes(
-        Vector  octs)
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-
-        for (int i = 0; i != octs.size(); i++)
-        {
-            try
-            {
-                DEROctetString  o = (DEROctetString)octs.elementAt(i);
-
-                bOut.write(o.getOctets());
-            }
-            catch (ClassCastException e)
-            {
-                throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString");
-            }
-            catch (IOException e)
-            {
-                throw new IllegalArgumentException("exception converting octets " + e.toString());
-            }
-        }
-
-        return bOut.toByteArray();
-    }
-
-    private Vector  octs;
-
-    /**
-     * @param string the octets making up the octet string.
-     */
-    public BERConstructedOctetString(
-        byte[]  string)
-    {
-        super(string);
-    }
-
-    public BERConstructedOctetString(
-        Vector  octs)
-    {
-        super(toBytes(octs));
-
-        this.octs = octs;
-    }
-
-    public BERConstructedOctetString(
-        DERObject  obj)
-    {
-        super(obj);
-    }
-
-    public BERConstructedOctetString(
-        DEREncodable  obj)
-    {
-        super(obj.getDERObject());
-    }
-
-    public byte[] getOctets()
-    {
-        return string;
-    }
-
-    /**
-     * return the DER octets that make up this string.
-     */
-    public Enumeration getObjects()
-    {
-        if (octs == null)
-        {
-            return generateOcts().elements();
-        }
-
-        return octs.elements();
-    }
-
-    private Vector generateOcts()
-    {
-        int     start = 0;
-        int     end = 0;
-        Vector  vec = new Vector();
-
-        while ((end + 1) < string.length)
-        {
-            if (string[end] == 0 && string[end + 1] == 0)
-            {
-                byte[]  nStr = new byte[end - start + 1];
-
-                System.arraycopy(string, start, nStr, 0, nStr.length);
-
-                vec.addElement(new DEROctetString(nStr));
-                start = end + 1;
-            }
-            end++;
-        }
-
-        byte[]  nStr = new byte[string.length - start];
-
-        System.arraycopy(string, start, nStr, 0, nStr.length);
-
-        vec.addElement(new DEROctetString(nStr));
-
-        return vec;
-    }
-
-    public void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
-        {
-            out.write(CONSTRUCTED | OCTET_STRING);
-
-            out.write(0x80);
-
-            //
-            // write out the octet array
-            //
-            if (octs != null)
-            {
-                for (int i = 0; i != octs.size(); i++)
-                {
-                    out.writeObject(octs.elementAt(i));
-                }
-            }
-            else
-            {
-                for (int i = 0; i < string.length; i += MAX_LENGTH)
-                {
-                    int end;
-
-                    if (i + MAX_LENGTH > string.length)
-                    {
-                        end = string.length;
-                    }
-                    else
-                    {
-                        end = i + MAX_LENGTH;
-                    }
-
-                    byte[]  nStr = new byte[end - i];
-
-                    System.arraycopy(string, i, nStr, 0, nStr.length);
-
-                    out.writeObject(new DEROctetString(nStr));
-                }
-            }
-
-            out.write(0x00);
-            out.write(0x00);
-        }
-        else
-        {
-            super.encode(out);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERConstructedSequence.java b/azureus2/src/org/bouncycastle/asn1/BERConstructedSequence.java
deleted file mode 100644
index 998eaeb..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERConstructedSequence.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * @deprecated use BERSequence
- */
-public class BERConstructedSequence
-    extends DERConstructedSequence
-{
-    /*
-     */
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
-        {
-            out.write(SEQUENCE | CONSTRUCTED);
-            out.write(0x80);
-            
-            Enumeration e = getObjects();
-            while (e.hasMoreElements())
-            {
-                out.writeObject(e.nextElement());
-            }
-        
-            out.write(0x00);
-            out.write(0x00);
-        }
-        else
-        {
-            super.encode(out);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERGenerator.java b/azureus2/src/org/bouncycastle/asn1/BERGenerator.java
deleted file mode 100644
index 6b32741..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERGenerator.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class BERGenerator
-    extends ASN1Generator
-{
-    private boolean      _tagged = false;
-    private boolean      _isExplicit;
-    private int          _tagNo;
-    
-    protected BERGenerator(
-        OutputStream out)
-    {
-        super(out);
-    }
-
-    public BERGenerator(
-        OutputStream out,
-        int tagNo,
-        boolean isExplicit) 
-    {
-        super(out);
-        
-        _tagged = true;
-        _isExplicit = isExplicit;
-        _tagNo = tagNo;
-    }
-
-    public OutputStream getRawOutputStream()
-    {
-        return _out;
-    }
-    
-    private void writeHdr(
-        int tag)
-        throws IOException
-    {
-        _out.write(tag);
-        _out.write(0x80);
-    }
-    
-    protected void writeBERHeader(
-        int tag) 
-        throws IOException
-    {
-        if (_tagged)
-        {
-            int tagNum = _tagNo | DERTags.TAGGED;
-
-            if (_isExplicit)
-            {
-                writeHdr(tagNum | DERTags.CONSTRUCTED);
-                writeHdr(tag);
-            }
-            else
-            {   
-                if ((tag & DERTags.CONSTRUCTED) != 0)
-                {
-                    writeHdr(tagNum | DERTags.CONSTRUCTED);
-                }
-                else
-                {
-                    writeHdr(tagNum);
-                }
-            }
-        }
-        else
-        {
-            writeHdr(tag);
-        }
-    }
-    
-    protected void writeBERBody(
-        InputStream contentStream)
-        throws IOException
-    {
-        int ch;
-        
-        while ((ch = contentStream.read()) >= 0)
-        {
-            _out.write(ch);
-        }
-    }
-
-    protected void writeBEREnd()
-        throws IOException
-    {
-        _out.write(0x00);
-        _out.write(0x00);
-        
-        if (_tagged && _isExplicit)  // write extra end for tag header
-        {
-            _out.write(0x00);
-            _out.write(0x00);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERInputStream.java b/azureus2/src/org/bouncycastle/asn1/BERInputStream.java
deleted file mode 100644
index 397fc06..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERInputStream.java
+++ /dev/null
@@ -1,209 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Vector;
-
-/**
- * @deprecated use ASN1InputStream
- */
-public class BERInputStream
-    extends DERInputStream
-{
-    private static final DERObject END_OF_STREAM = new DERObject()
-    {
-                                        void encode(
-                                            DEROutputStream out)
-                                        throws IOException
-                                        {
-                                            throw new IOException("Eeek!");
-                                        }
-                                        public int hashCode()
-                                        {
-                                            return 0;
-                                        }
-                                        public boolean equals(
-                                            Object o) 
-                                        {
-                                            return o == this;
-                                        }
-                                    };
-    public BERInputStream(
-        InputStream is)
-    {
-        super(is);
-    }
-
-    /**
-     * read a string of bytes representing an indefinite length object.
-     */
-    private byte[] readIndefiniteLengthFully()
-        throws IOException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        int                     b, b1;
-
-        b1 = read();
-
-        while ((b = read()) >= 0)
-        {
-            if (b1 == 0 && b == 0)
-            {
-                break;
-            }
-
-            bOut.write(b1);
-            b1 = b;
-        }
-
-        return bOut.toByteArray();
-    }
-
-    private BERConstructedOctetString buildConstructedOctetString()
-        throws IOException
-    {
-        Vector               octs = new Vector();
-
-        for (;;)
-        {
-            DERObject        o = readObject();
-
-            if (o == END_OF_STREAM)
-            {
-                break;
-            }
-
-            octs.addElement(o);
-        }
-
-        return new BERConstructedOctetString(octs);
-    }
-
-    public DERObject readObject()
-        throws IOException
-    {
-        int tag = read();
-        if (tag == -1)
-        {
-            throw new EOFException();
-        }
-    
-        int     length = readLength();
-
-        if (length < 0)    // indefinite length method
-        {
-            switch (tag)
-            {
-            case NULL:
-                return null;
-            case SEQUENCE | CONSTRUCTED:
-                BERConstructedSequence  seq = new BERConstructedSequence();
-    
-                for (;;)
-                {
-                    DERObject   obj = readObject();
-
-                    if (obj == END_OF_STREAM)
-                    {
-                        break;
-                    }
-
-                    seq.addObject(obj);
-                }
-                return seq;
-            case OCTET_STRING | CONSTRUCTED:
-                return buildConstructedOctetString();
-            case SET | CONSTRUCTED:
-                ASN1EncodableVector  v = new ASN1EncodableVector();
-    
-                for (;;)
-                {
-                    DERObject   obj = readObject();
-
-                    if (obj == END_OF_STREAM)
-                    {
-                        break;
-                    }
-
-                    v.add(obj);
-                }
-                return new BERSet(v);
-            default:
-                //
-                // with tagged object tag number is bottom 5 bits
-                //
-                if ((tag & TAGGED) != 0)  
-                {
-                    if ((tag & 0x1f) == 0x1f)
-                    {
-                        throw new IOException("unsupported high tag encountered");
-                    }
-
-                    //
-                    // simple type - implicit... return an octet string
-                    //
-                    if ((tag & CONSTRUCTED) == 0)
-                    {
-                        byte[]  bytes = readIndefiniteLengthFully();
-
-                        return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
-                    }
-
-                    //
-                    // either constructed or explicitly tagged
-                    //
-                    DERObject        dObj = readObject();
-
-                    if (dObj == END_OF_STREAM)     // empty tag!
-                    {
-                        return new DERTaggedObject(tag & 0x1f);
-                    }
-
-                    DERObject       next = readObject();
-
-                    //
-                    // explicitly tagged (probably!) - if it isn't we'd have to
-                    // tell from the context
-                    //
-                    if (next == END_OF_STREAM)
-                    {
-                        return new BERTaggedObject(tag & 0x1f, dObj);
-                    }
-
-                    //
-                    // another implicit object, we'll create a sequence...
-                    //
-                    seq = new BERConstructedSequence();
-
-                    seq.addObject(dObj);
-
-                    do
-                    {
-                        seq.addObject(next);
-                        next = readObject();
-                    }
-                    while (next != END_OF_STREAM);
-
-                    return new BERTaggedObject(false, tag & 0x1f, seq);
-                }
-
-                throw new IOException("unknown BER object encountered");
-            }
-        }
-        else
-        {
-            if (tag == 0 && length == 0)    // end of contents marker.
-            {
-                return END_OF_STREAM;
-            }
-
-            byte[]  bytes = new byte[length];
-    
-            readFully(bytes);
-    
-            return buildObject(tag, bytes);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERNull.java b/azureus2/src/org/bouncycastle/asn1/BERNull.java
deleted file mode 100644
index 92bc10d..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERNull.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * A BER NULL object.
- */
-public class BERNull
-    extends DERNull
-{
-    public static final BERNull INSTANCE = new BERNull();
-
-    public BERNull()
-    {
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
-        {
-            out.write(NULL);
-        }
-        else
-        {
-            super.encode(out);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BEROctetStringGenerator.java b/azureus2/src/org/bouncycastle/asn1/BEROctetStringGenerator.java
deleted file mode 100644
index aa511de..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BEROctetStringGenerator.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class BEROctetStringGenerator
-    extends BERGenerator
-{
-    public BEROctetStringGenerator(OutputStream out) 
-        throws IOException
-    {
-        super(out);
-        
-        writeBERHeader(DERTags.CONSTRUCTED | DERTags.OCTET_STRING);
-    }
-
-    public BEROctetStringGenerator(
-        OutputStream out,
-        int tagNo,
-        boolean isExplicit) 
-        throws IOException
-    {
-        super(out, tagNo, isExplicit);
-        
-        writeBERHeader(DERTags.CONSTRUCTED | DERTags.OCTET_STRING);
-    }
-    
-    public OutputStream getOctetOutputStream()
-    {
-        return getOctetOutputStream(new byte[1000]); // limit for CER encoding.
-    }
-
-    public OutputStream getOctetOutputStream(
-        byte[] buf)
-    {
-        return new BufferedBEROctetStream(buf);
-    }
-   
-    private class BufferedBEROctetStream
-        extends OutputStream
-    {
-        private byte[] _buf;
-        private int    _off;
-    
-        BufferedBEROctetStream(
-            byte[] buf)
-        {
-            _buf = buf;
-            _off = 0;
-        }
-        
-        public void write(
-            int b)
-            throws IOException
-        {
-            _buf[_off++] = (byte)b;
-
-            if (_off == _buf.length)
-            {
-                _out.write(new DEROctetString(_buf).getEncoded());
-                _off = 0;
-            }
-        }
-
-        public void write(byte[] b, int off, int len) throws IOException
-        {
-            while (len > 0)
-            {
-                int numToCopy = Math.min(len, _buf.length - _off);
-                System.arraycopy(b, off, _buf, _off, numToCopy);
-
-                _off += numToCopy;
-                if (_off < _buf.length)
-                {
-                    break;
-                }
-
-                _out.write(new DEROctetString(_buf).getEncoded());
-                _off = 0;
-
-                off += numToCopy;
-                len -= numToCopy;
-            }
-        }
-
-        public void close() 
-            throws IOException
-        {
-            if (_off != 0)
-            {
-                byte[] bytes = new byte[_off];
-                System.arraycopy(_buf, 0, bytes, 0, _off);
-                
-                _out.write(new DEROctetString(bytes).getEncoded());
-            }
-            
-             writeBEREnd();
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BEROctetStringParser.java b/azureus2/src/org/bouncycastle/asn1/BEROctetStringParser.java
deleted file mode 100644
index e3e8d61..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BEROctetStringParser.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-public class BEROctetStringParser
-    implements ASN1OctetStringParser
-{
-    private ASN1ObjectParser _parser;
-
-    protected BEROctetStringParser(
-        ASN1ObjectParser parser)
-    {
-        _parser = parser;
-    }
-
-    public InputStream getOctetStream()
-    {
-        return new ConstructedOctetStream(_parser);
-    }
-
-    public DERObject getDERObject()
-    {
-        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-        InputStream in = this.getOctetStream();
-        int         ch;
-
-        try
-        {
-            while ((ch = in.read()) >= 0)
-            {
-                bOut.write(ch);
-            }
-        }
-        catch (IOException e)
-        {
-            throw new IllegalStateException("IOException converting stream to byte array: " + e.getMessage());
-        }
-
-        return new BERConstructedOctetString(bOut.toByteArray());
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BEROutputStream.java b/azureus2/src/org/bouncycastle/asn1/BEROutputStream.java
deleted file mode 100644
index c2e8da4..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BEROutputStream.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class BEROutputStream
-    extends DEROutputStream
-{
-    public BEROutputStream(
-        OutputStream    os)
-    {
-        super(os);
-    }
-
-    public void writeObject(
-        Object    obj)
-        throws IOException
-    {
-        if (obj == null)
-        {
-            writeNull();
-        }
-        else if (obj instanceof DERObject)
-        {
-            ((DERObject)obj).encode(this);
-        }
-        else if (obj instanceof DEREncodable)
-        {
-            ((DEREncodable)obj).getDERObject().encode(this);
-        }
-        else
-        {
-            throw new IOException("object not BEREncodable");
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERSequence.java b/azureus2/src/org/bouncycastle/asn1/BERSequence.java
deleted file mode 100644
index c389fa8..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERSequence.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-public class BERSequence
-    extends DERSequence
-{
-    /**
-     * create an empty sequence
-     */
-    public BERSequence()
-    {
-    }
-
-    /**
-     * create a sequence containing one object
-     */
-    public BERSequence(
-        DEREncodable    obj)
-    {
-        super(obj);
-    }
-
-    /**
-     * create a sequence containing a vector of objects.
-     */
-    public BERSequence(
-        DEREncodableVector   v)
-    {
-        super(v);
-    }
-
-    /*
-     */
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
-        {
-            out.write(SEQUENCE | CONSTRUCTED);
-            out.write(0x80);
-            
-            Enumeration e = getObjects();
-            while (e.hasMoreElements())
-            {
-                out.writeObject(e.nextElement());
-            }
-        
-            out.write(0x00);
-            out.write(0x00);
-        }
-        else
-        {
-            super.encode(out);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERSequenceGenerator.java b/azureus2/src/org/bouncycastle/asn1/BERSequenceGenerator.java
deleted file mode 100644
index 88b4a10..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERSequenceGenerator.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class BERSequenceGenerator
-    extends BERGenerator
-{
-    public BERSequenceGenerator(
-        OutputStream out) 
-        throws IOException
-    {
-        super(out);
-
-        writeBERHeader(DERTags.CONSTRUCTED | DERTags.SEQUENCE);
-    }
-
-    public BERSequenceGenerator(
-        OutputStream out,
-        int tagNo,
-        boolean isExplicit) 
-        throws IOException
-    {
-        super(out, tagNo, isExplicit);
-        
-        writeBERHeader(DERTags.CONSTRUCTED | DERTags.SEQUENCE);
-    }
-
-    public void addObject(
-        DEREncodable object)
-        throws IOException
-    {
-        object.getDERObject().encode(new DEROutputStream(_out));
-    }
-    
-    public void close() 
-        throws IOException
-    {
-        writeBEREnd();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERSequenceParser.java b/azureus2/src/org/bouncycastle/asn1/BERSequenceParser.java
deleted file mode 100644
index af76c60..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERSequenceParser.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class BERSequenceParser
-    implements ASN1SequenceParser
-{
-    private ASN1ObjectParser _parser;
-
-    BERSequenceParser(ASN1ObjectParser parser)
-    {
-        this._parser = parser;
-    }
-
-    public DEREncodable readObject()
-        throws IOException
-    {
-        return _parser.readObject();
-    }
-
-    public DERObject getDERObject()
-    {
-        return new BERSequence(_parser.readVector());
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERSet.java b/azureus2/src/org/bouncycastle/asn1/BERSet.java
deleted file mode 100644
index 1ccf0fd..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERSet.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-public class BERSet
-    extends DERSet
-{
-    /**
-     * create an empty sequence
-     */
-    public BERSet()
-    {
-    }
-
-    /**
-     * create a set containing one object
-     */
-    public BERSet(
-        DEREncodable    obj)
-    {
-        super(obj);
-    }
-
-    /**
-     * @param v - a vector of objects making up the set.
-     */
-    public BERSet(
-        DEREncodableVector   v)
-    {
-        super(v, false);
-    }
-
-    /**
-     * @param v - a vector of objects making up the set.
-     */
-    BERSet(
-        DEREncodableVector   v,
-        boolean              needsSorting)
-    {
-        super(v, needsSorting);
-    }
-
-    /*
-     */
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
-        {
-            out.write(SET | CONSTRUCTED);
-            out.write(0x80);
-            
-            Enumeration e = getObjects();
-            while (e.hasMoreElements())
-            {
-                out.writeObject(e.nextElement());
-            }
-        
-            out.write(0x00);
-            out.write(0x00);
-        }
-        else
-        {
-            super.encode(out);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERSetParser.java b/azureus2/src/org/bouncycastle/asn1/BERSetParser.java
deleted file mode 100644
index 7f9d1d1..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERSetParser.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class BERSetParser
-    implements ASN1SetParser
-{
-    private ASN1ObjectParser _parser;
-
-    BERSetParser(ASN1ObjectParser parser)
-    {
-        this._parser = parser;
-    }
-
-    public DEREncodable readObject()
-        throws IOException
-    {
-        return _parser.readObject();
-    }
-
-    public DERObject getDERObject()
-    {
-        return new BERSet(_parser.readVector());
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERTaggedObject.java b/azureus2/src/org/bouncycastle/asn1/BERTaggedObject.java
deleted file mode 100644
index 2e06c40..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERTaggedObject.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * BER TaggedObject - in ASN.1 nottation this is any object proceeded by
- * a [n] where n is some number - these are assume to follow the construction
- * rules (as with sequences).
- */
-public class BERTaggedObject
-    extends DERTaggedObject
-{
-    /**
-     * @param tagNo the tag number for this object.
-     * @param obj the tagged object.
-     */
-    public BERTaggedObject(
-        int             tagNo,
-        DEREncodable    obj)
-    {
-        super(tagNo, obj);
-    }
-
-    /**
-     * @param explicit true if an explicitly tagged object.
-     * @param tagNo the tag number for this object.
-     * @param obj the tagged object.
-     */
-    public BERTaggedObject(
-        boolean         explicit,
-        int             tagNo,
-        DEREncodable    obj)
-    {
-        super(explicit, tagNo, obj);
-    }
-
-    /**
-     * create an implicitly tagged object that contains a zero
-     * length sequence.
-     */
-    public BERTaggedObject(
-        int             tagNo)
-    {
-        super(false, tagNo, new BERSequence());
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
-        {
-            out.write(CONSTRUCTED | TAGGED | tagNo);
-            out.write(0x80);
-
-            if (!empty)
-            {
-                if (!explicit)
-                {
-                    if (obj instanceof ASN1OctetString)
-                    {
-                        Enumeration  e;
-
-                        if (obj instanceof BERConstructedOctetString)
-                        {
-                            e = ((BERConstructedOctetString)obj).getObjects();
-                        }
-                        else
-                        {
-                            ASN1OctetString             octs = (ASN1OctetString)obj;
-                            BERConstructedOctetString   berO = new BERConstructedOctetString(octs.getOctets());
-
-                            e = berO.getObjects();
-                        }
-
-                        while (e.hasMoreElements())
-                        {
-                            out.writeObject(e.nextElement());
-                        }
-                    }
-                    else if (obj instanceof ASN1Sequence)
-                    {
-                        Enumeration  e = ((ASN1Sequence)obj).getObjects();
-
-                        while (e.hasMoreElements())
-                        {
-                            out.writeObject(e.nextElement());
-                        }
-                    }
-                    else if (obj instanceof ASN1Set)
-                    {
-                        Enumeration  e = ((ASN1Set)obj).getObjects();
-
-                        while (e.hasMoreElements())
-                        {
-                            out.writeObject(e.nextElement());
-                        }
-                    }
-                    else
-                    {
-                        throw new RuntimeException("not implemented: " + obj.getClass().getName());
-                    }
-                }
-                else
-                {
-                    out.writeObject(obj);
-                }
-            }
-
-            out.write(0x00);
-            out.write(0x00);
-        }
-        else
-        {
-            super.encode(out);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/BERTaggedObjectParser.java b/azureus2/src/org/bouncycastle/asn1/BERTaggedObjectParser.java
deleted file mode 100644
index 17229f3..0000000
--- a/azureus2/src/org/bouncycastle/asn1/BERTaggedObjectParser.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class BERTaggedObjectParser
-    implements ASN1TaggedObjectParser
-{
-    private int _baseTag;
-    private int _tagNumber;
-    private InputStream _contentStream;
-
-    private boolean _indefiniteLength;
-
-    protected BERTaggedObjectParser(
-        int         baseTag,
-        int         tagNumber,
-        InputStream contentStream)
-    {
-        _baseTag = baseTag;
-        _tagNumber = tagNumber;
-        _contentStream = contentStream;
-        _indefiniteLength = contentStream instanceof IndefiniteLengthInputStream;
-    }
-
-    public boolean isConstructed()
-    {
-        return (_baseTag & DERTags.CONSTRUCTED) != 0;
-    }
-
-    public int getTagNo()
-    {
-        return _tagNumber;
-    }
-    
-    public DEREncodable getObjectParser(
-        int     tag,
-        boolean isExplicit)
-        throws IOException
-    {
-        if (isExplicit)
-        {
-            return new ASN1StreamParser(_contentStream).readObject();
-        }
-        else
-        {
-            switch (tag)
-            {
-            case DERTags.SET:
-                if (_indefiniteLength)
-                {
-                    return new BERSetParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream));
-                }
-                else
-                {
-                    return new DERSet(loadVector(_contentStream)).parser();
-                }
-            case DERTags.SEQUENCE:
-                if (_indefiniteLength)
-                {
-                    return new BERSequenceParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream));
-                }
-                else
-                {
-                    return new DERSequence(loadVector(_contentStream)).parser();
-                }
-            case DERTags.OCTET_STRING:
-                if (_indefiniteLength || this.isConstructed())
-                {
-                    return new BEROctetStringParser(new ASN1ObjectParser(_baseTag, _tagNumber, _contentStream));
-                }
-                else
-                {
-                    return new DEROctetString(((DefiniteLengthInputStream)_contentStream).toByteArray()).parser();
-                }
-            }
-        }
-
-        throw new RuntimeException("implicit tagging not implemented");
-    }
-
-    private ASN1EncodableVector loadVector(InputStream in)
-        throws IOException
-    {
-        ASN1StreamParser        aIn = new ASN1StreamParser(in);
-        ASN1EncodableVector     v = new ASN1EncodableVector();
-        DEREncodable            obj = aIn.readObject();
-
-        while (obj != null)
-        {
-            v.add(obj.getDERObject());
-            obj = aIn.readObject();
-        }
-
-        return v;
-    }
-
-    private ASN1EncodableVector rLoadVector(InputStream in)
-    {
-        try
-        {
-            return loadVector(in);
-        }
-        catch (IOException e)
-        {
-            throw new IllegalStateException(e.getMessage());
-        }
-    }
-
-    public DERObject getDERObject()
-    {
-        if (_indefiniteLength)
-        {
-            ASN1EncodableVector v = rLoadVector(_contentStream);
-
-            if (v.size() > 1)
-            {
-                return new BERTaggedObject(false, _tagNumber, new BERSequence(v));
-            }
-            else if (v.size() == 1)
-            {
-                return new BERTaggedObject(true, _tagNumber, v.get(0));
-            }
-            else
-            {
-                return new BERTaggedObject(false, _tagNumber, new BERSequence());
-            }
-        }
-        else
-        {
-            if (this.isConstructed())
-            {
-                ASN1EncodableVector v = rLoadVector(_contentStream);
-
-                if (v.size() == 1)
-                {
-                    return new DERTaggedObject(true, _tagNumber, v.get(0));
-                }
-
-                return new DERTaggedObject(false, _tagNumber, new DERSequence(v));                
-            }
-
-            try
-            {
-                return new DERTaggedObject(false, _tagNumber, new DEROctetString(((DefiniteLengthInputStream)_contentStream).toByteArray()));
-            }
-            catch (IOException e)
-            {
-                throw new IllegalStateException(e.getMessage());
-            }
-        }
-
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/ConstructedOctetStream.java b/azureus2/src/org/bouncycastle/asn1/ConstructedOctetStream.java
deleted file mode 100644
index 0734f40..0000000
--- a/azureus2/src/org/bouncycastle/asn1/ConstructedOctetStream.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-class ConstructedOctetStream
-    extends InputStream
-{
-    private final ASN1ObjectParser _parser;
-
-    private boolean                _first = true;
-    private InputStream            _currentStream;
-
-    ConstructedOctetStream(
-        ASN1ObjectParser parser)
-    {
-        _parser = parser;
-    }
-
-    public int read(byte[] b, int off, int len) throws IOException
-    {
-        if (_currentStream == null)
-        {
-            if (!_first)
-            {
-                return -1;
-            }
-
-            ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
-
-            if (s == null)
-            {
-                return -1;
-            }
-
-            _first = false;
-            _currentStream = s.getOctetStream();
-        }
-
-        int totalRead = 0;
-
-        for (;;)
-        {
-            int numRead = _currentStream.read(b, off + totalRead, len - totalRead);
-
-            if (numRead >= 0)
-            {
-                totalRead += numRead;
-
-                if (totalRead == len)
-                {
-                    return totalRead;
-                }
-            }
-            else
-            {
-                ASN1OctetStringParser aos = (ASN1OctetStringParser)_parser.readObject();
-
-                if (aos == null)
-                {
-                    _currentStream = null;
-                    return totalRead < 1 ? -1 : totalRead;
-                }
-
-                _currentStream = aos.getOctetStream();
-            }
-        }
-    }
-
-    public int read()
-        throws IOException
-    {
-        if (_currentStream == null)
-        {
-            if (!_first)
-            {
-                return -1;
-            }
-
-            ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
-    
-            if (s == null)
-            {
-                return -1;
-            }
-    
-            _first = false;
-            _currentStream = s.getOctetStream();
-        }
-
-        for (;;)
-        {
-            int b = _currentStream.read();
-
-            if (b >= 0)
-            {
-                return b;
-            }
-
-            ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
-
-            if (s == null)
-            {
-                _currentStream = null;
-                return -1;
-            }
-
-            _currentStream = s.getOctetStream();
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERApplicationSpecific.java b/azureus2/src/org/bouncycastle/asn1/DERApplicationSpecific.java
deleted file mode 100644
index 7ae9beb..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERApplicationSpecific.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * Base class for an application specific object
- */
-public class DERApplicationSpecific 
-    extends ASN1Object
-{
-    private int       tag;
-    private byte[]    octets;
-    
-    public DERApplicationSpecific(
-        int        tag,
-        byte[]    octets)
-    {
-        this.tag = tag;
-        this.octets = octets;
-    }
-    
-    public DERApplicationSpecific(
-        int                  tag, 
-        DEREncodable         object) 
-        throws IOException 
-    {
-        this(true, tag, object);
-    }
-
-    public DERApplicationSpecific(
-        boolean      explicit,
-        int          tag,
-        DEREncodable object)
-        throws IOException
-    {
-        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-        DEROutputStream dos = new DEROutputStream(bOut);
-
-        dos.writeObject(object);
-
-        byte[] data = bOut.toByteArray();
-
-        if (tag >= 0x1f)
-        {
-            throw new IOException("unsupported tag number");
-        }
-
-        if (explicit)
-        {
-            this.tag = tag | DERTags.CONSTRUCTED;
-            this.octets = data;
-        }
-        else
-        {
-            this.tag = tag;
-            int lenBytes = getLengthOfLength(data);
-            byte[] tmp = new byte[data.length - lenBytes];
-            System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
-            this.octets = tmp;
-        }
-    }
-
-    private int getLengthOfLength(byte[] data)
-    {
-        int count = 2;               // TODO: assumes only a 1 byte tag number
-
-        while((data[count - 1] & 0x80) != 0)
-        {
-            count++;
-        }
-
-        return count;
-    }
-
-    public boolean isConstructed()
-    {
-        return (tag & DERTags.CONSTRUCTED) != 0;
-    }
-    
-    public byte[] getContents()
-    {
-        return octets;
-    }
-    
-    public int getApplicationTag() 
-    {
-        return tag;
-    }
-     
-    public DERObject getObject() 
-        throws IOException 
-    {
-        return new ASN1InputStream(getContents()).readObject();
-    }
-
-    /**
-     * Return the enclosed object assuming implicit tagging.
-     *
-     * @param derTagNo the type tag that should be applied to the object's contents.
-     * @return  the resulting object
-     * @throws IOException if reconstruction fails.
-     */
-    public DERObject getObject(int derTagNo)
-        throws IOException
-    {
-        if (tag >= 0x1f)
-        {
-            throw new IOException("unsupported tag number");
-        }
-                
-        byte[] tmp = this.getEncoded();
-
-        tmp[0] = (byte)derTagNo;
-        
-        return new ASN1InputStream(tmp).readObject();
-    }
-    
-    /* (non-Javadoc)
-     * @see org.bouncycastle.asn1.DERObject#encode(org.bouncycastle.asn1.DEROutputStream)
-     */
-    void encode(DEROutputStream out) throws IOException
-    {
-        out.writeEncoded(DERTags.APPLICATION | tag, octets);
-    }
-    
-    boolean asn1Equals(
-        DERObject o)
-    {
-        if (!(o instanceof DERApplicationSpecific))
-        {
-            return false;
-        }
-        
-        DERApplicationSpecific other = (DERApplicationSpecific)o;
-        
-        if (tag != other.tag)
-        {
-            return false;
-        }
-        
-        if (octets.length != other.octets.length)
-        {
-            return false;
-        }
-        
-        for (int i = 0; i < octets.length; i++) 
-        {
-            if (octets[i] != other.octets[i])
-            {
-                return false;
-            }
-        }
-        
-        return true;
-    }
-    
-    public int hashCode()
-    {
-        byte[]  b = this.getContents();
-        int     value = 0;
-
-        for (int i = 0; i != b.length; i++)
-        {
-            value ^= (b[i] & 0xff) << (i % 4);
-        }
-
-        return value ^ this.getApplicationTag();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERBMPString.java b/azureus2/src/org/bouncycastle/asn1/DERBMPString.java
deleted file mode 100644
index 1472325..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERBMPString.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER BMPString object.
- */
-public class DERBMPString
-    extends ASN1Object
-    implements DERString
-{
-    String  string;
-
-    /**
-     * return a BMP String from the given object.
-     *
-     * @param obj the object we want converted.
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERBMPString getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERBMPString)
-        {
-            return (DERBMPString)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERBMPString(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return a BMP String from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *              be converted.
-     */
-    public static DERBMPString getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-    
-
-    /**
-     * basic constructor - byte encoded string.
-     */
-    public DERBMPString(
-        byte[]   string)
-    {
-        char[]  cs = new char[string.length / 2];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
-        }
-
-        this.string = new String(cs);
-    }
-
-    /**
-     * basic constructor
-     */
-    public DERBMPString(
-        String   string)
-    {
-        this.string = string;
-    }
-
-    public String getString()
-    {
-        return string;
-    }
-
-    public String toString()
-    {
-        return string;
-    }
-
-    public int hashCode()
-    {
-        return this.getString().hashCode();
-    }
-
-    protected boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERBMPString))
-        {
-            return false;
-        }
-
-        DERBMPString  s = (DERBMPString)o;
-
-        return this.getString().equals(s.getString());
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        char[]  c = string.toCharArray();
-        byte[]  b = new byte[c.length * 2];
-
-        for (int i = 0; i != c.length; i++)
-        {
-            b[2 * i] = (byte)(c[i] >> 8);
-            b[2 * i + 1] = (byte)c[i];
-        }
-
-        out.writeEncoded(BMP_STRING, b);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERBitString.java b/azureus2/src/org/bouncycastle/asn1/DERBitString.java
deleted file mode 100644
index 1463db7..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERBitString.java
+++ /dev/null
@@ -1,289 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-public class DERBitString
-    extends ASN1Object
-    implements DERString
-{
-    private static final char[]  table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-    
-    protected byte[]      data;
-    protected int         padBits;
-
-    /**
-     * return the correct number of pad bits for a bit string defined in
-     * a 32 bit constant
-     */
-    static protected int getPadBits(
-        int bitString)
-    {
-        int val = 0;
-        for (int i = 3; i >= 0; i--) 
-        {
-            //
-            // this may look a little odd, but if it isn't done like this pre jdk1.2
-            // JVM's break!
-            //
-            if (i != 0)
-            {
-                if ((bitString >> (i * 8)) != 0) 
-                {
-                    val = (bitString >> (i * 8)) & 0xFF;
-                    break;
-                }
-            }
-            else
-            {
-                if (bitString != 0)
-                {
-                    val = bitString & 0xFF;
-                    break;
-                }
-            }
-        }
- 
-        if (val == 0)
-        {
-            return 7;
-        }
-
-
-        int bits = 1;
-
-        while (((val <<= 1) & 0xFF) != 0)
-        {
-            bits++;
-        }
-
-        return 8 - bits;
-    }
-
-    /**
-     * return the correct number of bytes for a bit string defined in
-     * a 32 bit constant
-     */
-    static protected byte[] getBytes(int bitString)
-    {
-        int bytes = 4;
-        for (int i = 3; i >= 1; i--)
-        {
-            if ((bitString & (0xFF << (i * 8))) != 0)
-            {
-                break;
-            }
-            bytes--;
-        }
-        
-        byte[] result = new byte[bytes];
-        for (int i = 0; i < bytes; i++)
-        {
-            result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
-        }
-
-        return result;
-    }
-
-    /**
-     * return a Bit String from the passed in object
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERBitString getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERBitString)
-        {
-            return (DERBitString)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            byte[]  bytes = ((ASN1OctetString)obj).getOctets();
-            int     padBits = bytes[0];
-            byte[]  data = new byte[bytes.length - 1];
-
-            System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
-
-            return new DERBitString(data, padBits);
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return a Bit String from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERBitString getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-    
-    protected DERBitString(
-        byte    data,
-        int     padBits)
-    {
-        this.data = new byte[1];
-        this.data[0] = data;
-        this.padBits = padBits;
-    }
-
-    /**
-     * @param data the octets making up the bit string.
-     * @param padBits the number of extra bits at the end of the string.
-     */
-    public DERBitString(
-        byte[]  data,
-        int     padBits)
-    {
-        this.data = data;
-        this.padBits = padBits;
-    }
-
-    public DERBitString(
-        byte[]  data)
-    {
-        this(data, 0);
-    }
-
-    public DERBitString(
-        DEREncodable  obj)
-    {
-        try
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            DEROutputStream         dOut = new DEROutputStream(bOut);
-
-            dOut.writeObject(obj);
-            dOut.close();
-
-            this.data = bOut.toByteArray();
-            this.padBits = 0;
-        }
-        catch (IOException e)
-        {
-            throw new IllegalArgumentException("Error processing object : " + e.toString());
-        }
-    }
-
-    public byte[] getBytes()
-    {
-        return data;
-    }
-
-    public int getPadBits()
-    {
-        return padBits;
-    }
-
-
-    /**
-     * @return the value of the bit string as an int (truncating if necessary)
-     */
-    public int intValue()
-    {
-        int value = 0;
-        
-        for (int i = 0; i != data.length && i != 4; i++)
-        {
-            value |= (data[i] & 0xff) << (8 * i);
-        }
-        
-        return value;
-    }
-    
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        byte[]  bytes = new byte[getBytes().length + 1];
-
-        bytes[0] = (byte)getPadBits();
-        System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
-
-        out.writeEncoded(BIT_STRING, bytes);
-    }
-
-    public int hashCode()
-    {
-        int     value = 0;
-
-        for (int i = 0; i != data.length; i++)
-        {
-            value ^= (data[i] & 0xff) << (i % 4);
-        }
-
-        return value;
-    }
-    
-    protected boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERBitString))
-        {
-            return false;
-        }
-
-        DERBitString  other = (DERBitString)o;
-
-        if (data.length != other.data.length)
-        {
-            return false;
-        }
-
-        for (int i = 0; i != data.length; i++)
-        {
-            if (data[i] != other.data[i])
-            {
-                return false;
-            }
-        }
-
-        return (padBits == other.padBits);
-    }
-
-    public String getString()
-    {
-        StringBuffer          buf = new StringBuffer("#");
-        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-        ASN1OutputStream      aOut = new ASN1OutputStream(bOut);
-        
-        try
-        {
-            aOut.writeObject(this);
-        }
-        catch (IOException e)
-        {
-           throw new RuntimeException("internal error encoding BitString");
-        }
-        
-        byte[]    string = bOut.toByteArray();
-        
-        for (int i = 0; i != string.length; i++)
-        {
-            buf.append(table[(string[i] >>> 4) & 0xf]);
-            buf.append(table[string[i] & 0xf]);
-        }
-        
-        return buf.toString();
-    }
-
-    public String toString()
-    {
-        return getString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERBoolean.java b/azureus2/src/org/bouncycastle/asn1/DERBoolean.java
deleted file mode 100644
index a2f0c4d..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERBoolean.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DERBoolean
-    extends ASN1Object
-{
-    byte         value;
-
-    public static final DERBoolean FALSE = new DERBoolean(false);
-    public static final DERBoolean TRUE  = new DERBoolean(true);
-
-    /**
-     * return a boolean from the passed in object.
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERBoolean getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERBoolean)
-        {
-            return (DERBoolean)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERBoolean(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return a DERBoolean from the passed in boolean.
-     */
-    public static DERBoolean getInstance(
-        boolean  value)
-    {
-        return (value ? TRUE : FALSE);
-    }
-
-    /**
-     * return a Boolean from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERBoolean getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-    
-    public DERBoolean(
-        byte[]       value)
-    {
-        this.value = value[0];
-    }
-
-    public DERBoolean(
-        boolean     value)
-    {
-        this.value = (value) ? (byte)0xff : (byte)0;
-    }
-
-    public boolean isTrue()
-    {
-        return (value != 0);
-    }
-
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        byte[]  bytes = new byte[1];
-
-        bytes[0] = value;
-
-        out.writeEncoded(BOOLEAN, bytes);
-    }
-    
-    protected boolean asn1Equals(
-        DERObject  o)
-    {
-        if ((o == null) || !(o instanceof DERBoolean))
-        {
-            return false;
-        }
-
-        return (value == ((DERBoolean)o).value);
-    }
-    
-    public int hashCode()
-    {
-        return value;
-    }
-
-
-    public String toString()
-    {
-      return (value != 0) ? "TRUE" : "FALSE";
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERConstructedSequence.java b/azureus2/src/org/bouncycastle/asn1/DERConstructedSequence.java
deleted file mode 100644
index 99a493e..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERConstructedSequence.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * @deprecated use DERSequence.
- */
-public class DERConstructedSequence
-    extends ASN1Sequence
-{
-    public void addObject(
-        DEREncodable obj)
-    {
-        super.addObject(obj);
-    }
-
-    public int getSize()
-    {
-        return size();
-    }
-
-    /*
-     * A note on the implementation:
-     * <p>
-     * As DER requires the constructed, definite-length model to
-     * be used for structured types, this varies slightly from the
-     * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
-     * we also have to specify CONSTRUCTED, and the objects length.
-     */
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-        Enumeration             e = this.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            Object    obj = e.nextElement();
-
-            dOut.writeObject(obj);
-        }
-
-        dOut.close();
-
-        byte[]  bytes = bOut.toByteArray();
-
-        out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERConstructedSet.java b/azureus2/src/org/bouncycastle/asn1/DERConstructedSet.java
deleted file mode 100644
index 695cef3..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERConstructedSet.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * 
- * @deprecated use DERSet
- */
-public class DERConstructedSet
-    extends ASN1Set
-{
-    public DERConstructedSet()
-    {
-    }
-
-    /**
-     * @param obj - a single object that makes up the set.
-     */
-    public DERConstructedSet(
-        DEREncodable   obj)
-    {
-        this.addObject(obj);
-    }
-
-    /**
-     * @param v - a vector of objects making up the set.
-     */
-    public DERConstructedSet(
-        DEREncodableVector   v)
-    {
-        for (int i = 0; i != v.size(); i++)
-        {
-            this.addObject(v.get(i));
-        }
-    }
-
-    public void addObject(
-        DEREncodable    obj)
-    {
-        super.addObject(obj);
-    }
-
-    public int getSize()
-    {
-        return size();
-    }
-
-    /*
-     * A note on the implementation:
-     * <p>
-     * As DER requires the constructed, definite-length model to
-     * be used for structured types, this varies slightly from the
-     * ASN.1 descriptions given. Rather than just outputing SET,
-     * we also have to specify CONSTRUCTED, and the objects length.
-     */
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-        Enumeration             e = this.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            Object    obj = e.nextElement();
-
-            dOut.writeObject(obj);
-        }
-
-        dOut.close();
-
-        byte[]  bytes = bOut.toByteArray();
-
-        out.writeEncoded(SET | CONSTRUCTED, bytes);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DEREncodable.java b/azureus2/src/org/bouncycastle/asn1/DEREncodable.java
deleted file mode 100644
index d89305a..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DEREncodable.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.bouncycastle.asn1;
-
-public interface DEREncodable
-{
-    public DERObject getDERObject();
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DEREncodableVector.java b/azureus2/src/org/bouncycastle/asn1/DEREncodableVector.java
deleted file mode 100644
index 60d0bd2..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DEREncodableVector.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.util.Vector;
-
-/**
- * a general class for building up a vector of DER encodable objects -
- * this will eventually be superceded by ASN1EncodableVector so you should
- * use that class in preference.
- */
-public class DEREncodableVector
-{
-    private Vector  v = new Vector();
-
-    /**
-     * @deprecated use ASN1EncodableVector instead.
-     */
-    public DEREncodableVector()
-    {
-
-    }
-    
-    public void add(
-        DEREncodable   obj)
-    {
-        v.addElement(obj);
-    }
-
-    public DEREncodable get(
-        int i)
-    {
-        return (DEREncodable)v.elementAt(i);
-    }
-
-    public int size()
-    {
-        return v.size();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DEREnumerated.java b/azureus2/src/org/bouncycastle/asn1/DEREnumerated.java
deleted file mode 100644
index 9881352..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DEREnumerated.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.math.BigInteger;
-
-public class DEREnumerated
-    extends ASN1Object
-{
-    byte[]      bytes;
-
-    /**
-     * return an integer from the passed in object
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DEREnumerated getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DEREnumerated)
-        {
-            return (DEREnumerated)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DEREnumerated(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return an Enumerated from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DEREnumerated getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-
-    public DEREnumerated(
-        int         value)
-    {
-        bytes = BigInteger.valueOf(value).toByteArray();
-    }
-
-    public DEREnumerated(
-        BigInteger   value)
-    {
-        bytes = value.toByteArray();
-    }
-
-    public DEREnumerated(
-        byte[]   bytes)
-    {
-        this.bytes = bytes;
-    }
-
-    public BigInteger getValue()
-    {
-        return new BigInteger(bytes);
-    }
-
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        out.writeEncoded(ENUMERATED, bytes);
-    }
-    
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DEREnumerated))
-        {
-            return false;
-        }
-
-        DEREnumerated other = (DEREnumerated)o;
-
-        if (bytes.length != other.bytes.length)
-        {
-            return false;
-        }
-
-        for (int i = 0; i != bytes.length; i++)
-        {
-            if (bytes[i] != other.bytes[i])
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-    
-    public int hashCode()
-    {
-        return this.getValue().hashCode();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERGeneralString.java b/azureus2/src/org/bouncycastle/asn1/DERGeneralString.java
deleted file mode 100644
index 1992cf3..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERGeneralString.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DERGeneralString 
-    extends ASN1Object implements DERString
-{
-    private String string;
-
-    public static DERGeneralString getInstance(
-        Object obj) 
-    {
-        if (obj == null || obj instanceof DERGeneralString) 
-        {
-            return (DERGeneralString) obj;
-        }
-        if (obj instanceof ASN1OctetString) 
-        {
-            return new DERGeneralString(((ASN1OctetString) obj).getOctets());
-        }
-        if (obj instanceof ASN1TaggedObject) 
-        {
-            return getInstance(((ASN1TaggedObject) obj).getObject());
-        }
-        throw new IllegalArgumentException("illegal object in getInstance: "
-                + obj.getClass().getName());
-    }
-
-    public static DERGeneralString getInstance(
-        ASN1TaggedObject obj, 
-        boolean explicit) 
-    {
-        return getInstance(obj.getObject());
-    }
-
-    public DERGeneralString(byte[] string) 
-    {
-        char[] cs = new char[string.length];
-        for (int i = 0; i != cs.length; i++)
-        {
-            cs[i] = (char)(string[i] & 0xff);
-        }
-        this.string = new String(cs);
-    }
-
-    public DERGeneralString(String string) 
-    {
-        this.string = string;
-    }
-    
-    public String getString() 
-    {
-        return string;
-    }
-
-    public String toString()
-    {
-        return string;
-    }
-
-    public byte[] getOctets() 
-    {
-        char[] cs = string.toCharArray();
-        byte[] bs = new byte[cs.length];
-        for (int i = 0; i != cs.length; i++) 
-        {
-            bs[i] = (byte) cs[i];
-        }
-        return bs;
-    }
-    
-    void encode(DEROutputStream out) 
-        throws IOException 
-    {
-        out.writeEncoded(GENERAL_STRING, this.getOctets());
-    }
-    
-    public int hashCode() 
-    {
-        return this.getString().hashCode();
-    }
-    
-    boolean asn1Equals(DERObject o)
-    {
-        if (!(o instanceof DERGeneralString)) 
-        {
-            return false;
-        }
-        DERGeneralString s = (DERGeneralString) o;
-        return this.getString().equals(s.getString());
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERGeneralizedTime.java b/azureus2/src/org/bouncycastle/asn1/DERGeneralizedTime.java
deleted file mode 100644
index c1cf6c5..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERGeneralizedTime.java
+++ /dev/null
@@ -1,294 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.SimpleTimeZone;
-import java.util.TimeZone;
-
-/**
- * Generalized time object.
- */
-public class DERGeneralizedTime
-    extends ASN1Object
-{
-    String      time;
-
-    /**
-     * return a generalized time from the passed in object
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERGeneralizedTime getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERGeneralizedTime)
-        {
-            return (DERGeneralizedTime)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERGeneralizedTime(((ASN1OctetString)obj).getOctets());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return a Generalized Time object from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERGeneralizedTime getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-    
-    /**
-     * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
-     * for local time, or Z+-HHMM on the end, for difference between local
-     * time and UTC time. The fractional second amount f must consist of at
-     * least one number with trailing zeroes removed.
-     *
-     * @param time the time string.
-     * @exception IllegalArgumentException if String is an illegal format.
-     */
-    public DERGeneralizedTime(
-        String  time)
-    {
-        this.time = time;
-        try
-        {
-            this.getDate();
-        }
-        catch (ParseException e)
-        {
-            throw new IllegalArgumentException("invalid date string: " + e.getMessage());
-        }
-    }
-
-    /**
-     * base constructer from a java.util.date object
-     */
-    public DERGeneralizedTime(
-        Date time)
-    {
-        SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
-
-        dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
-        this.time = dateF.format(time);
-    }
-
-    DERGeneralizedTime(
-        byte[]  bytes)
-    {
-        //
-        // explicitly convert to characters
-        //
-        char[]  dateC = new char[bytes.length];
-
-        for (int i = 0; i != dateC.length; i++)
-        {
-            dateC[i] = (char)(bytes[i] & 0xff);
-        }
-
-        this.time = new String(dateC);
-    }
-
-    /**
-     * Return the time.
-     * @return The time string as it appeared in the encoded object.
-     */
-    public String getTimeString()
-    {
-        return time;
-    }
-    
-    /**
-     * return the time - always in the form of 
-     *  YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
-     * <p>
-     * Normally in a certificate we would expect "Z" rather than "GMT",
-     * however adding the "GMT" means we can just use:
-     * <pre>
-     *     dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
-     * </pre>
-     * To read in the time and get a date which is compatible with our local
-     * time zone.
-     */
-    public String getTime()
-    {
-        //
-        // standardise the format.
-        //             
-        if (time.charAt(time.length() - 1) == 'Z')
-        {
-            return time.substring(0, time.length() - 1) + "GMT+00:00";
-        }
-        else
-        {
-            int signPos = time.length() - 5;
-            char sign = time.charAt(signPos);
-            if (sign == '-' || sign == '+')
-            {
-                return time.substring(0, signPos)
-                    + "GMT"
-                    + time.substring(signPos, signPos + 3)
-                    + ":"
-                    + time.substring(signPos + 3);
-            }
-            else
-            {
-                signPos = time.length() - 3;
-                sign = time.charAt(signPos);
-                if (sign == '-' || sign == '+')
-                {
-                    return time.substring(0, signPos)
-                        + "GMT"
-                        + time.substring(signPos)
-                        + ":00";
-                }
-            }
-        }            
-        return time + calculateGMTOffset();
-    }
-
-    private String calculateGMTOffset()
-    {
-        String sign = "+";
-        TimeZone timeZone = TimeZone.getDefault();
-        int offset = timeZone.getRawOffset();
-        if (offset < 0)
-        {
-            sign = "-";
-            offset = -offset;
-        }
-        int hours = offset / (60 * 60 * 1000);
-        int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
-
-        try
-        {
-            if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
-            {
-                hours += sign.equals("+") ? 1 : -1;
-            }
-        }
-        catch (ParseException e)
-        {
-            // we'll do our best and ignore daylight savings
-        }
-
-        return "GMT" + sign + convert(hours) + ":" + convert(minutes);
-    }
-
-    private String convert(int time)
-    {
-        if (time < 10)
-        {
-            return "0" + time;
-        }
-
-        return Integer.toString(time);
-    }
-
-    public Date getDate()
-        throws ParseException
-    {
-        SimpleDateFormat dateF;
-        String d = time;
-
-        if (time.endsWith("Z"))
-        {
-            if (hasFractionalSeconds())
-            {
-                dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSS'Z'");
-            }
-            else
-            {
-                dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
-            }
-
-            dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
-        }
-        else if (time.indexOf('-') > 0 || time.indexOf('+') > 0)
-        {
-            d = this.getTime();
-            if (hasFractionalSeconds())
-            {
-                dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSSz");
-            }
-            else
-            {
-                dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
-            }
-
-            dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
-        }
-        else
-        {
-            if (hasFractionalSeconds())
-            {
-                dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSS");
-            }
-            else
-            {
-                dateF = new SimpleDateFormat("yyyyMMddHHmmss");
-            }
-
-            dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
-        }
-
-        return dateF.parse(d);
-    }
-
-    private boolean hasFractionalSeconds()
-    {
-        return time.indexOf('.') == 14;
-    }
-
-    private byte[] getOctets()
-    {
-        char[]  cs = time.toCharArray();
-        byte[]  bs = new byte[cs.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            bs[i] = (byte)cs[i];
-        }
-
-        return bs;
-    }
-
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        out.writeEncoded(GENERALIZED_TIME, this.getOctets());
-    }
-    
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERGeneralizedTime))
-        {
-            return false;
-        }
-
-        return time.equals(((DERGeneralizedTime)o).time);
-    }
-    
-    public int hashCode()
-    {
-        return time.hashCode();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERGenerator.java b/azureus2/src/org/bouncycastle/asn1/DERGenerator.java
deleted file mode 100644
index 3006d0b..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERGenerator.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public abstract class DERGenerator
-    extends ASN1Generator
-{       
-    private boolean      _tagged = false;
-    private boolean      _isExplicit;
-    private int          _tagNo;
-    
-    protected DERGenerator(
-        OutputStream out)
-    {
-        super(out);
-    }
-
-    public DERGenerator(
-        OutputStream out,
-        int          tagNo,
-        boolean      isExplicit)
-    { 
-        super(out);
-        
-        _tagged = true;
-        _isExplicit = isExplicit;
-        _tagNo = tagNo;
-    }
-
-    private void writeLength(
-        OutputStream out,
-        int          length)
-        throws IOException
-    {
-        if (length > 127)
-        {
-            int size = 1;
-            int val = length;
-
-            while ((val >>>= 8) != 0)
-            {
-                size++;
-            }
-
-            out.write((byte)(size | 0x80));
-
-            for (int i = (size - 1) * 8; i >= 0; i -= 8)
-            {
-                out.write((byte)(length >> i));
-            }
-        }
-        else
-        {
-            out.write((byte)length);
-        }
-    }
-
-    void writeDEREncoded(
-        OutputStream out,
-        int          tag,
-        byte[]       bytes)
-        throws IOException
-    {
-        out.write(tag);
-        writeLength(out, bytes.length);
-        out.write(bytes);
-    }
-
-    void writeDEREncoded(
-        int       tag,
-        byte[]    bytes)
-        throws IOException
-    {
-        if (_tagged)
-        {
-            int tagNum = _tagNo | DERTags.TAGGED;
-            
-            if (_isExplicit)
-            {
-                int newTag = _tagNo | DERTags.CONSTRUCTED | DERTags.TAGGED;
-
-                ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-                
-                writeDEREncoded(bOut, tag, bytes);
-                
-                writeDEREncoded(_out, newTag, bOut.toByteArray());
-            }
-            else
-            {   
-                if ((tag & DERTags.CONSTRUCTED) != 0)
-                {
-                    writeDEREncoded(_out, tagNum | DERTags.CONSTRUCTED, bytes);
-                }
-                else
-                {
-                    writeDEREncoded(_out, tagNum, bytes);
-                }
-            }
-        }
-        else
-        {
-            writeDEREncoded(_out, tag, bytes);
-        }
-    }
-    
-    void writeDEREncoded(
-        OutputStream out,
-        int          tag,
-        InputStream  in)
-        throws IOException
-    {
-        out.write(tag);
-        
-        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-        
-        int b = 0;
-        while ((b = in.read()) >= 0)
-        {
-            bOut.write(b);
-        }
-        
-        byte[] bytes = bOut.toByteArray();
-        
-        writeLength(out, bytes.length);
-        out.write(bytes);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERIA5String.java b/azureus2/src/org/bouncycastle/asn1/DERIA5String.java
deleted file mode 100644
index c8dd70e..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERIA5String.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER IA5String object - this is an ascii string.
- */
-public class DERIA5String
-    extends ASN1Object
-    implements DERString
-{
-    String  string;
-
-    /**
-     * return a IA5 string from the passed in object
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERIA5String getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERIA5String)
-        {
-            return (DERIA5String)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERIA5String(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return an IA5 String from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERIA5String getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-
-    /**
-     * basic constructor - with bytes.
-     */
-    public DERIA5String(
-        byte[]   string)
-    {
-        char[]  cs = new char[string.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            cs[i] = (char)(string[i] & 0xff);
-        }
-
-        this.string = new String(cs);
-    }
-
-    /**
-     * basic constructor - without validation.
-     */
-    public DERIA5String(
-        String   string)
-    {
-        this(string, false);
-    }
-
-    /**
-     * Constructor with optional validation.
-     *
-     * @param string the base string to wrap.
-     * @param validate whether or not to check the string.
-     * @throws IllegalArgumentException if validate is true and the string
-     * contains characters that should not be in an IA5String.
-     */
-    public DERIA5String(
-        String   string,
-        boolean  validate)
-    {
-        if (validate && !isIA5String(string))
-        {
-            throw new IllegalArgumentException("string contains illegal characters");
-        }
-
-        this.string = string;
-    }
-
-    public String getString()
-    {
-        return string;
-    }
-
-    public String toString()
-    {
-        return string;
-    }
-
-    public byte[] getOctets()
-    {
-        char[]  cs = string.toCharArray();
-        byte[]  bs = new byte[cs.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            bs[i] = (byte)cs[i];
-        }
-
-        return bs; 
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        out.writeEncoded(IA5_STRING, this.getOctets());
-    }
-
-    public int hashCode()
-    {
-        return this.getString().hashCode();
-    }
-
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERIA5String))
-        {
-            return false;
-        }
-
-        DERIA5String  s = (DERIA5String)o;
-
-        return this.getString().equals(s.getString());
-    }
-
-    /**
-     * return true if the passed in String can be represented without
-     * loss as an IA5String, false otherwise.
-     *
-     * @return true if in printable set, false otherwise.
-     */
-    public static boolean isIA5String(
-        String  str)
-    {
-        for (int i = str.length() - 1; i >= 0; i--)
-        {
-            char    ch = str.charAt(i);
-
-            if (ch > 0x007f)
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERInputStream.java b/azureus2/src/org/bouncycastle/asn1/DERInputStream.java
deleted file mode 100644
index 51f5505..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERInputStream.java
+++ /dev/null
@@ -1,272 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.EOFException;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Don't use this class. It will eventually disappear, use ASN1InputStream.
- * <br>
- * This class is scheduled for removal.
- * @deprecated use ASN1InputStream
- */
-public class DERInputStream
-    extends FilterInputStream implements DERTags
-{
-    /**
-     * @deprecated use ASN1InputStream
-     */
-    public DERInputStream(
-        InputStream is)
-    {
-        super(is);
-    }
-
-    protected int readLength()
-        throws IOException
-    {
-        int length = read();
-        if (length < 0)
-        {
-            throw new IOException("EOF found when length expected");
-        }
-
-        if (length == 0x80)
-        {
-            return -1;      // indefinite-length encoding
-        }
-
-        if (length > 127)
-        {
-            int size = length & 0x7f;
-
-            if (size > 4)
-            {
-                throw new IOException("DER length more than 4 bytes");
-            }
-            
-            length = 0;
-            for (int i = 0; i < size; i++)
-            {
-                int next = read();
-
-                if (next < 0)
-                {
-                    throw new IOException("EOF found reading length");
-                }
-
-                length = (length << 8) + next;
-            }
-            
-            if (length < 0)
-            {
-                throw new IOException("corrupted stream - negative length found");
-            }
-        }
-
-        return length;
-    }
-
-    protected void readFully(
-        byte[]  bytes)
-        throws IOException
-    {
-        int     left = bytes.length;
-
-        if (left == 0)
-        {
-            return;
-        }
-
-        while (left > 0)
-        {
-            int    l = read(bytes, bytes.length - left, left);
-            
-            if (l < 0)
-            {
-                throw new EOFException("unexpected end of stream");
-            }
-            
-            left -= l;
-        }
-    }
-
-    /**
-     * build an object given its tag and a byte stream to construct it
-     * from.
-     */
-    protected DERObject buildObject(
-        int       tag,
-        byte[]    bytes)
-        throws IOException
-    {
-        switch (tag)
-        {
-        case NULL:
-            return null;   
-        case SEQUENCE | CONSTRUCTED:
-            ByteArrayInputStream    bIn = new ByteArrayInputStream(bytes);
-            BERInputStream          dIn = new BERInputStream(bIn);
-            DERConstructedSequence  seq = new DERConstructedSequence();
-
-            try
-            {
-                for (;;)
-                {
-                    DERObject   obj = dIn.readObject();
-
-                    seq.addObject(obj);
-                }
-            }
-            catch (EOFException ex)
-            {
-                return seq;
-            }
-        case SET | CONSTRUCTED:
-            bIn = new ByteArrayInputStream(bytes);
-            dIn = new BERInputStream(bIn);
-
-            ASN1EncodableVector    v = new ASN1EncodableVector();
-
-            try
-            {
-                for (;;)
-                {
-                    DERObject   obj = dIn.readObject();
-
-                    v.add(obj);
-                }
-            }
-            catch (EOFException ex)
-            {
-                return new DERConstructedSet(v);
-            }
-        case BOOLEAN:
-            return new DERBoolean(bytes);
-        case INTEGER:
-            return new DERInteger(bytes);
-        case ENUMERATED:
-            return new DEREnumerated(bytes);
-        case OBJECT_IDENTIFIER:
-            return new DERObjectIdentifier(bytes);
-        case BIT_STRING:
-            int     padBits = bytes[0];
-            byte[]  data = new byte[bytes.length - 1];
-
-            System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
-
-            return new DERBitString(data, padBits);
-        case UTF8_STRING:
-            return new DERUTF8String(bytes);
-        case PRINTABLE_STRING:
-            return new DERPrintableString(bytes);
-        case IA5_STRING:
-            return new DERIA5String(bytes);
-        case T61_STRING:
-            return new DERT61String(bytes);
-        case VISIBLE_STRING:
-            return new DERVisibleString(bytes);
-        case UNIVERSAL_STRING:
-            return new DERUniversalString(bytes);
-        case GENERAL_STRING:
-            return new DERGeneralString(bytes);
-        case BMP_STRING:
-            return new DERBMPString(bytes);
-        case OCTET_STRING:
-            return new DEROctetString(bytes);
-        case UTC_TIME:
-            return new DERUTCTime(bytes);
-        case GENERALIZED_TIME:
-            return new DERGeneralizedTime(bytes);
-        default:
-            //
-            // with tagged object tag number is bottom 5 bits
-            //
-            if ((tag & TAGGED) != 0)  
-            {
-                if ((tag & 0x1f) == 0x1f)
-                {
-                    throw new IOException("unsupported high tag encountered");
-                }
-
-                if (bytes.length == 0)        // empty tag!
-                {
-                    if ((tag & CONSTRUCTED) == 0)
-                    {
-                        return new DERTaggedObject(false, tag & 0x1f, new DERNull());
-                    }
-                    else
-                    {
-                        return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
-                    }
-                }
-
-                //
-                // simple type - implicit... return an octet string
-                //
-                if ((tag & CONSTRUCTED) == 0)
-                {
-                    return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
-                }
-
-                bIn = new ByteArrayInputStream(bytes);
-                dIn = new BERInputStream(bIn);
-
-                DEREncodable dObj = dIn.readObject();
-
-                //
-                // explicitly tagged (probably!) - if it isn't we'd have to
-                // tell from the context
-                //
-                if (dIn.available() == 0)
-                {
-                    return new DERTaggedObject(tag & 0x1f, dObj);
-                }
-
-                //
-                // another implicit object, we'll create a sequence...
-                //
-                seq = new DERConstructedSequence();
-
-                seq.addObject(dObj);
-
-                try
-                {
-                    for (;;)
-                    {
-                        dObj = dIn.readObject();
-
-                        seq.addObject(dObj);
-                    }
-                }
-                catch (EOFException ex)
-                {
-                    // ignore --
-                }
-
-                return new DERTaggedObject(false, tag & 0x1f, seq);
-            }
-
-            return new DERUnknownTag(tag, bytes);
-        }
-    }
-
-    public DERObject readObject()
-        throws IOException
-    {
-        int tag = read();
-        if (tag == -1)
-        {
-            throw new EOFException();
-        }
-
-        int     length = readLength();
-        byte[]  bytes = new byte[length];
-
-        readFully(bytes);
-
-        return buildObject(tag, bytes);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERInteger.java b/azureus2/src/org/bouncycastle/asn1/DERInteger.java
deleted file mode 100644
index 059617c..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERInteger.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.math.BigInteger;
-
-public class DERInteger
-    extends ASN1Object
-{
-    byte[]      bytes;
-
-    /**
-     * return an integer from the passed in object
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERInteger getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERInteger)
-        {
-            return (DERInteger)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERInteger(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return an Integer from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERInteger getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-
-    public DERInteger(
-        int         value)
-    {
-        bytes = BigInteger.valueOf(value).toByteArray();
-    }
-
-    public DERInteger(
-        BigInteger   value)
-    {
-        bytes = value.toByteArray();
-    }
-
-    public DERInteger(
-        byte[]   bytes)
-    {
-        this.bytes = bytes;
-    }
-
-    public BigInteger getValue()
-    {
-        return new BigInteger(bytes);
-    }
-
-    /**
-     * in some cases positive values get crammed into a space,
-     * that's not quite big enough...
-     */
-    public BigInteger getPositiveValue()
-    {
-        return new BigInteger(1, bytes);
-    }
-
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        out.writeEncoded(INTEGER, bytes);
-    }
-    
-    public int hashCode()
-    {
-         int     value = 0;
- 
-         for (int i = 0; i != bytes.length; i++)
-         {
-             value ^= (bytes[i] & 0xff) << (i % 4);
-         }
- 
-         return value;
-    }
-
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERInteger))
-        {
-            return false;
-        }
-
-        DERInteger other = (DERInteger)o;
-
-        if (bytes.length != other.bytes.length)
-        {
-            return false;
-        }
-
-        for (int i = 0; i != bytes.length; i++)
-        {
-            if (bytes[i] != other.bytes[i])
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    public String toString()
-    {
-      return getValue().toString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERNull.java b/azureus2/src/org/bouncycastle/asn1/DERNull.java
deleted file mode 100644
index 5d020c7..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERNull.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * A NULL object.
- */
-public class DERNull
-    extends ASN1Null
-{
-    public static final DERNull INSTANCE = new DERNull();
-
-    byte[]  zeroBytes = new byte[0];
-
-    public DERNull()
-    {
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        out.writeEncoded(NULL, zeroBytes);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERNumericString.java b/azureus2/src/org/bouncycastle/asn1/DERNumericString.java
deleted file mode 100644
index 3c72193..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERNumericString.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
- */
-public class DERNumericString
-    extends ASN1Object
-    implements DERString
-{
-    String  string;
-
-    /**
-     * return a Numeric string from the passed in object
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERNumericString getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERNumericString)
-        {
-            return (DERNumericString)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERNumericString(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return an Numeric String from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERNumericString getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-
-    /**
-     * basic constructor - with bytes.
-     */
-    public DERNumericString(
-        byte[]   string)
-    {
-        char[]  cs = new char[string.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            cs[i] = (char)(string[i] & 0xff);
-        }
-
-        this.string = new String(cs);
-    }
-
-    /**
-     * basic constructor -  without validation..
-     */
-    public DERNumericString(
-        String   string)
-    {
-        this(string, false);
-    }
-
-    /**
-     * Constructor with optional validation.
-     *
-     * @param string the base string to wrap.
-     * @param validate whether or not to check the string.
-     * @throws IllegalArgumentException if validate is true and the string
-     * contains characters that should not be in a NumericString.
-     */
-    public DERNumericString(
-        String   string,
-        boolean  validate)
-    {
-        if (validate && !isNumericString(string))
-        {
-            throw new IllegalArgumentException("string contains illegal characters");
-        }
-
-        this.string = string;
-    }
-
-    public String getString()
-    {
-        return string;
-    }
-
-    public String toString()
-    {
-        return string;
-    }
-
-    public byte[] getOctets()
-    {
-        char[]  cs = string.toCharArray();
-        byte[]  bs = new byte[cs.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            bs[i] = (byte)cs[i];
-        }
-
-        return bs; 
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        out.writeEncoded(NUMERIC_STRING, this.getOctets());
-    }
-
-    public int hashCode()
-    {
-        return this.getString().hashCode();
-    }
-
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERNumericString))
-        {
-            return false;
-        }
-
-        DERNumericString  s = (DERNumericString)o;
-
-        return this.getString().equals(s.getString());
-    }
-
-    /**
-     * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
-     *
-     * @param str string to validate.
-     * @return true if numeric, fale otherwise.
-     */
-    public static boolean isNumericString(
-        String  str)
-    {
-        for (int i = str.length() - 1; i >= 0; i--)
-        {
-            char    ch = str.charAt(i);
-
-            if (ch > 0x007f)
-            {
-                return false;
-            }
-
-            if (('0' <= ch && ch <= '9') || ch == ' ')
-            {
-                continue;
-            }
-
-            return false;
-        }
-
-        return true;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERObject.java b/azureus2/src/org/bouncycastle/asn1/DERObject.java
deleted file mode 100644
index 42e2487..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERObject.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public abstract class DERObject
-    extends ASN1Encodable
-    implements DERTags
-{
-    public DERObject toASN1Object()
-    {
-        return this;
-    }
-    
-    public abstract int hashCode();
-    
-    public abstract boolean equals(Object o);
-    
-    abstract void encode(DEROutputStream out)
-        throws IOException;
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERObjectIdentifier.java b/azureus2/src/org/bouncycastle/asn1/DERObjectIdentifier.java
deleted file mode 100644
index 1ba6b2d..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERObjectIdentifier.java
+++ /dev/null
@@ -1,293 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.math.BigInteger;
-
-public class DERObjectIdentifier
-    extends ASN1Object
-{
-    String      identifier;
-
-    /**
-     * return an OID from the passed in object
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERObjectIdentifier getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERObjectIdentifier)
-        {
-            return (DERObjectIdentifier)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERObjectIdentifier(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return an Object Identifier from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERObjectIdentifier getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-    
-
-    DERObjectIdentifier(
-        byte[]  bytes)
-    {
-        StringBuffer    objId = new StringBuffer();
-        long            value = 0;
-        BigInteger      bigValue = null;
-        boolean         first = true;
-
-        for (int i = 0; i != bytes.length; i++)
-        {
-            int b = bytes[i] & 0xff;
-
-            if (value < 0x80000000000000L) 
-            {
-                value = value * 128 + (b & 0x7f);
-                if ((b & 0x80) == 0)             // end of number reached
-                {
-                    if (first)
-                    {
-                        switch ((int)value / 40)
-                        {
-                        case 0:
-                            objId.append('0');
-                            break;
-                        case 1:
-                            objId.append('1');
-                            value -= 40;
-                            break;
-                        default:
-                            objId.append('2');
-                            value -= 80;
-                        }
-                        first = false;
-                    }
-
-                    objId.append('.');
-                    objId.append(value);
-                    value = 0;
-                }
-            } 
-            else 
-            {
-                if (bigValue == null)
-                {
-                    bigValue = BigInteger.valueOf(value);
-                }
-                bigValue = bigValue.shiftLeft(7);
-                bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
-                if ((b & 0x80) == 0) 
-                {
-                    objId.append('.');
-                    objId.append(bigValue);
-                    bigValue = null;
-                    value = 0;
-                }
-            }
-        }
-
-        this.identifier = objId.toString();
-    }
-
-    public DERObjectIdentifier(
-        String  identifier)
-    {
-        if (!isValidIdentifier(identifier))
-        {
-            throw new IllegalArgumentException("string " + identifier + " not an OID");
-        }
-
-        this.identifier = identifier;
-    }
-
-    public String getId()
-    {
-        return identifier;
-    }
-
-    private void writeField(
-        OutputStream    out,
-        long            fieldValue)
-        throws IOException
-    {
-        if (fieldValue >= (1L << 7))
-        {
-            if (fieldValue >= (1L << 14))
-            {
-                if (fieldValue >= (1L << 21))
-                {
-                    if (fieldValue >= (1L << 28))
-                    {
-                        if (fieldValue >= (1L << 35))
-                        {
-                            if (fieldValue >= (1L << 42))
-                            {
-                                if (fieldValue >= (1L << 49))
-                                {
-                                    if (fieldValue >= (1L << 56))
-                                    {
-                                        out.write((int)(fieldValue >> 56) | 0x80);
-                                    }
-                                    out.write((int)(fieldValue >> 49) | 0x80);
-                                }
-                                out.write((int)(fieldValue >> 42) | 0x80);
-                            }
-                            out.write((int)(fieldValue >> 35) | 0x80);
-                        }
-                        out.write((int)(fieldValue >> 28) | 0x80);
-                    }
-                    out.write((int)(fieldValue >> 21) | 0x80);
-                }
-                out.write((int)(fieldValue >> 14) | 0x80);
-            }
-            out.write((int)(fieldValue >> 7) | 0x80);
-        }
-        out.write((int)fieldValue & 0x7f);
-    }
-
-    private void writeField(
-        OutputStream    out,
-        BigInteger      fieldValue)
-        throws IOException
-    {
-        int byteCount = (fieldValue.bitLength()+6)/7;
-        if (byteCount == 0) 
-        {
-            out.write(0);
-        }  
-        else 
-        {
-            BigInteger tmpValue = fieldValue;
-            byte[] tmp = new byte[byteCount];
-            for (int i = byteCount-1; i >= 0; i--) 
-            {
-                tmp[i] = (byte) ((tmpValue.intValue() & 0x7f) | 0x80);
-                tmpValue = tmpValue.shiftRight(7); 
-            }
-            tmp[byteCount-1] &= 0x7f;
-            out.write(tmp);
-        }
-
-    }
-
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        OIDTokenizer            tok = new OIDTokenizer(identifier);
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-
-        writeField(bOut, 
-                    Integer.parseInt(tok.nextToken()) * 40
-                    + Integer.parseInt(tok.nextToken()));
-
-        while (tok.hasMoreTokens())
-        {
-            String token = tok.nextToken();
-            if (token.length() < 18) 
-            {
-                writeField(bOut, Long.parseLong(token));
-            }
-            else
-            {
-                writeField(bOut, new BigInteger(token));
-            }
-        }
-
-        dOut.close();
-
-        byte[]  bytes = bOut.toByteArray();
-
-        out.writeEncoded(OBJECT_IDENTIFIER, bytes);
-    }
-
-    public int hashCode()
-    {
-        return identifier.hashCode();
-    }
-
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERObjectIdentifier))
-        {
-            return false;
-        }
-
-        return identifier.equals(((DERObjectIdentifier)o).identifier);
-    }
-
-    public String toString()
-    {
-        return getId();
-    }
-
-    private static boolean isValidIdentifier(
-        String identifier)
-    {
-        if (identifier.length() < 3
-            || identifier.charAt(1) != '.')
-        {
-            return false;
-        }
-
-        char first = identifier.charAt(0);
-        if (first < '0' || first > '2')
-        {
-            return false;
-        }
-
-        boolean periodAllowed = false;
-        for (int i = identifier.length() - 1; i >= 2; i--)
-        {
-            char ch = identifier.charAt(i);
-
-            if ('0' <= ch && ch <= '9')
-            {
-                periodAllowed = true;
-                continue;
-            }
-
-            if (ch == '.')
-            {
-                if (!periodAllowed)
-                {
-                    return false;
-                }
-
-                periodAllowed = false;
-                continue;
-            }
-
-            return false;
-        }
-
-        return periodAllowed;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DEROctetString.java b/azureus2/src/org/bouncycastle/asn1/DEROctetString.java
deleted file mode 100644
index bf7a86b..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DEROctetString.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DEROctetString
-    extends ASN1OctetString
-{
-    /**
-     * @param string the octets making up the octet string.
-     */
-    public DEROctetString(
-        byte[]  string)
-    {
-        super(string);
-    }
-
-    public DEROctetString(
-        DEREncodable  obj)
-    {
-        super(obj);
-    }
-
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        out.writeEncoded(OCTET_STRING, string);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DEROutputStream.java b/azureus2/src/org/bouncycastle/asn1/DEROutputStream.java
deleted file mode 100644
index 69150e0..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DEROutputStream.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class DEROutputStream
-    extends FilterOutputStream implements DERTags
-{
-    public DEROutputStream(
-        OutputStream    os)
-    {
-        super(os);
-    }
-
-    private void writeLength(
-        int length)
-        throws IOException
-    {
-        if (length > 127)
-        {
-            int size = 1;
-            int val = length;
-
-            while ((val >>>= 8) != 0)
-            {
-                size++;
-            }
-
-            write((byte)(size | 0x80));
-
-            for (int i = (size - 1) * 8; i >= 0; i -= 8)
-            {
-                write((byte)(length >> i));
-            }
-        }
-        else
-        {
-            write((byte)length);
-        }
-    }
-
-    void writeEncoded(
-        int     tag,
-        byte[]  bytes)
-        throws IOException
-    {
-        write(tag);
-        writeLength(bytes.length);
-        write(bytes);
-    }
-
-    protected void writeNull()
-        throws IOException
-    {
-        write(NULL);
-        write(0x00);
-    }
-
-    public void write(byte[] buf)
-        throws IOException
-    {
-        out.write(buf, 0, buf.length);
-    }
-
-    public void write(byte[] buf, int offSet, int len)
-        throws IOException
-    {
-        out.write(buf, offSet, len);
-    }
-
-    public void writeObject(
-        Object    obj)
-        throws IOException
-    {
-        if (obj == null)
-        {
-            writeNull();
-        }
-        else if (obj instanceof DERObject)
-        {
-            ((DERObject)obj).encode(this);
-        }
-        else if (obj instanceof DEREncodable)
-        {
-            ((DEREncodable)obj).getDERObject().encode(this);
-        }
-        else 
-        {
-            throw new IOException("object not DEREncodable");
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERPrintableString.java b/azureus2/src/org/bouncycastle/asn1/DERPrintableString.java
deleted file mode 100644
index 032823d..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERPrintableString.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER PrintableString object.
- */
-public class DERPrintableString
-    extends ASN1Object
-    implements DERString
-{
-    String  string;
-
-    /**
-     * return a printable string from the passed in object.
-     * 
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERPrintableString getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERPrintableString)
-        {
-            return (DERPrintableString)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERPrintableString(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return a Printable String from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERPrintableString getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-
-    /**
-     * basic constructor - byte encoded string.
-     */
-    public DERPrintableString(
-        byte[]   string)
-    {
-        char[]  cs = new char[string.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            cs[i] = (char)(string[i] & 0xff);
-        }
-
-        this.string = new String(cs);
-    }
-
-    /**
-     * basic constructor - this does not validate the string
-     */
-    public DERPrintableString(
-        String   string)
-    {
-        this(string, false);
-    }
-
-    /**
-     * Constructor with optional validation.
-     *
-     * @param string the base string to wrap.
-     * @param validate whether or not to check the string.
-     * @throws IllegalArgumentException if validate is true and the string
-     * contains characters that should not be in a PrintableString.
-     */
-    public DERPrintableString(
-        String   string,
-        boolean  validate)
-    {
-        if (validate && !isPrintableString(string))
-        {
-            throw new IllegalArgumentException("string contains illegal characters");
-        }
-
-        this.string = string;
-    }
-
-    public String getString()
-    {
-        return string;
-    }
-
-    public byte[] getOctets()
-    {
-        char[]  cs = string.toCharArray();
-        byte[]  bs = new byte[cs.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            bs[i] = (byte)cs[i];
-        }
-
-        return bs; 
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        out.writeEncoded(PRINTABLE_STRING, this.getOctets());
-    }
-
-    public int hashCode()
-    {
-        return this.getString().hashCode();
-    }
-
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERPrintableString))
-        {
-            return false;
-        }
-
-        DERPrintableString  s = (DERPrintableString)o;
-
-        return this.getString().equals(s.getString());
-    }
-
-    public String toString()
-    {
-        return string;
-    }
-
-    /**
-     * return true if the passed in String can be represented without
-     * loss as a PrintableString, false otherwise.
-     *
-     * @return true if in printable set, false otherwise.
-     */
-    public static boolean isPrintableString(
-        String  str)
-    {
-        for (int i = str.length() - 1; i >= 0; i--)
-        {
-            char    ch = str.charAt(i);
-
-            if (ch > 0x007f)
-            {
-                return false;
-            }
-
-            if ('a' <= ch && ch <= 'z')
-            {
-                continue;
-            }
-
-            if ('A' <= ch && ch <= 'Z')
-            {
-                continue;
-            }
-
-            if ('0' <= ch && ch <= '9')
-            {
-                continue;
-            }
-
-            switch (ch)
-            {
-            case ' ':
-            case '\'':
-            case '(':
-            case ')':
-            case '+':
-            case '-':
-            case '.':
-            case ':':
-            case '=':
-            case '?':
-            case '/':
-            case ',':
-                continue;
-            }
-
-            return false;
-        }
-
-        return true;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERSequence.java b/azureus2/src/org/bouncycastle/asn1/DERSequence.java
deleted file mode 100644
index 1cfd38d..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERSequence.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-
-public class DERSequence
-    extends ASN1Sequence
-{
-    /**
-     * create an empty sequence
-     */
-    public DERSequence()
-    {
-    }
-
-    /**
-     * create a sequence containing one object
-     */
-    public DERSequence(
-        DEREncodable    obj)
-    {
-        this.addObject(obj);
-    }
-
-    /**
-     * create a sequence containing a vector of objects.
-     */
-    public DERSequence(
-        DEREncodableVector   v)
-    {
-        for (int i = 0; i != v.size(); i++)
-        {
-            this.addObject(v.get(i));
-        }
-    }
-
-    /**
-     * create a sequence containing an array of objects.
-     */
-    public DERSequence(
-        ASN1Encodable[]   a)
-    {
-        for (int i = 0; i != a.length; i++)
-        {
-            this.addObject(a[i]);
-        }
-    }
-    
-    /*
-     * A note on the implementation:
-     * <p>
-     * As DER requires the constructed, definite-length model to
-     * be used for structured types, this varies slightly from the
-     * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
-     * we also have to specify CONSTRUCTED, and the objects length.
-     */
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-        Enumeration             e = this.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            Object    obj = e.nextElement();
-
-            dOut.writeObject(obj);
-        }
-
-        dOut.close();
-
-        byte[]  bytes = bOut.toByteArray();
-
-        out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERSequenceGenerator.java b/azureus2/src/org/bouncycastle/asn1/DERSequenceGenerator.java
deleted file mode 100644
index 458dcdc..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERSequenceGenerator.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class DERSequenceGenerator
-    extends DERGenerator
-{
-    private final ByteArrayOutputStream _bOut = new ByteArrayOutputStream();
-
-    public DERSequenceGenerator(
-        OutputStream out)
-        throws IOException
-    {
-        super(out);
-    }
-
-    public DERSequenceGenerator(
-        OutputStream out,
-        int          tagNo,
-        boolean      isExplicit)
-        throws IOException
-    {
-        super(out, tagNo, isExplicit);
-    }
-
-    public void addObject(
-        DEREncodable object) 
-        throws IOException
-    {
-        object.getDERObject().encode(new DEROutputStream(_bOut));
-    }
-    
-    public OutputStream getRawOutputStream()
-    {
-        return _bOut;
-    }
-    
-    public void close() 
-        throws IOException
-    {
-        writeDEREncoded(DERTags.CONSTRUCTED | DERTags.SEQUENCE, _bOut.toByteArray());
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERSet.java b/azureus2/src/org/bouncycastle/asn1/DERSet.java
deleted file mode 100644
index e1aa1d5..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERSet.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * A DER encoded set object
- */
-public class DERSet
-    extends ASN1Set
-{
-    /**
-     * create an empty set
-     */
-    public DERSet()
-    {
-    }
-
-    /**
-     * @param obj - a single object that makes up the set.
-     */
-    public DERSet(
-        DEREncodable   obj)
-    {
-        this.addObject(obj);
-    }
-
-    /**
-     * @param v - a vector of objects making up the set.
-     */
-    public DERSet(
-        DEREncodableVector   v)
-    {
-        this(v, true);
-    }
-    
-    /**
-     * create a set from an array of objects.
-     */
-    public DERSet(
-        ASN1Encodable[]   a)
-    {
-        for (int i = 0; i != a.length; i++)
-        {
-            this.addObject(a[i]);
-        }
-        
-        this.sort();
-    }
-    
-    /**
-     * @param v - a vector of objects making up the set.
-     */
-    DERSet(
-        DEREncodableVector   v,
-        boolean              needsSorting)
-    {
-        for (int i = 0; i != v.size(); i++)
-        {
-            this.addObject(v.get(i));
-        }
-
-        if (needsSorting)
-        {
-            this.sort();
-        }
-    }
-
-    /*
-     * A note on the implementation:
-     * <p>
-     * As DER requires the constructed, definite-length model to
-     * be used for structured types, this varies slightly from the
-     * ASN.1 descriptions given. Rather than just outputing SET,
-     * we also have to specify CONSTRUCTED, and the objects length.
-     */
-    void encode(
-        DEROutputStream out)
-        throws IOException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-        Enumeration             e = this.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            Object    obj = e.nextElement();
-
-            dOut.writeObject(obj);
-        }
-
-        dOut.close();
-
-        byte[]  bytes = bOut.toByteArray();
-
-        out.writeEncoded(SET | CONSTRUCTED, bytes);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERString.java b/azureus2/src/org/bouncycastle/asn1/DERString.java
deleted file mode 100644
index 3143be9..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERString.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * basic interface for DER string objects.
- */
-public interface DERString
-{
-    public String getString();
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERT61String.java b/azureus2/src/org/bouncycastle/asn1/DERT61String.java
deleted file mode 100644
index 09039fc..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERT61String.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER T61String (also the teletex string)
- */
-public class DERT61String
-    extends ASN1Object
-    implements DERString
-{
-    String  string;
-
-    /**
-     * return a T61 string from the passed in object.
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERT61String getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERT61String)
-        {
-            return (DERT61String)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERT61String(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return an T61 String from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERT61String getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-
-    /**
-     * basic constructor - with bytes.
-     */
-    public DERT61String(
-        byte[]   string)
-    {
-        char[]  cs = new char[string.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            cs[i] = (char)(string[i] & 0xff);
-        }
-
-        this.string = new String(cs);
-    }
-
-    /**
-     * basic constructor - with string.
-     */
-    public DERT61String(
-        String   string)
-    {
-        this.string = string;
-    }
-
-    public String getString()
-    {
-        return string;
-    }
-
-    public String toString()
-    {
-        return string;
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        out.writeEncoded(T61_STRING, this.getOctets());
-    }
-    
-    public byte[] getOctets()
-    {
-        char[]  cs = string.toCharArray();
-        byte[]  bs = new byte[cs.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            bs[i] = (byte)cs[i];
-        }
-
-        return bs; 
-    }
-
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERT61String))
-        {
-            return false;
-        }
-
-        return this.getString().equals(((DERT61String)o).getString());
-    }
-    
-    public int hashCode()
-    {
-        return this.getString().hashCode();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERTaggedObject.java b/azureus2/src/org/bouncycastle/asn1/DERTaggedObject.java
deleted file mode 100644
index d42f0d6..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERTaggedObject.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * DER TaggedObject - in ASN.1 nottation this is any object proceeded by
- * a [n] where n is some number - these are assume to follow the construction
- * rules (as with sequences).
- */
-public class DERTaggedObject
-    extends ASN1TaggedObject
-{
-    /**
-     * @param tagNo the tag number for this object.
-     * @param obj the tagged object.
-     */
-    public DERTaggedObject(
-        int             tagNo,
-        DEREncodable    obj)
-    {
-        super(tagNo, obj);
-    }
-
-    /**
-     * @param explicit true if an explicitly tagged object.
-     * @param tagNo the tag number for this object.
-     * @param obj the tagged object.
-     */
-    public DERTaggedObject(
-        boolean         explicit,
-        int             tagNo,
-        DEREncodable    obj)
-    {
-        super(explicit, tagNo, obj);
-    }
-
-    /**
-     * create an implicitly tagged object that contains a zero
-     * length sequence.
-     */
-    public DERTaggedObject(
-        int             tagNo)
-    {
-        super(false, tagNo, new DERSequence());
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        if (!empty)
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            DEROutputStream         dOut = new DEROutputStream(bOut);
-
-            dOut.writeObject(obj);
-            dOut.close();
-
-            byte[]  bytes = bOut.toByteArray();
-
-            if (explicit)
-            {
-                out.writeEncoded(CONSTRUCTED | TAGGED | tagNo, bytes);
-            }
-            else
-            {
-                //
-                // need to mark constructed types...
-                //
-                if ((bytes[0] & CONSTRUCTED) != 0)
-                {
-                    bytes[0] = (byte)(CONSTRUCTED | TAGGED | tagNo);
-                }
-                else
-                {
-                    bytes[0] = (byte)(TAGGED | tagNo);
-                }
-
-                out.write(bytes);
-            }
-        }
-        else
-        {
-            out.writeEncoded(CONSTRUCTED | TAGGED | tagNo, new byte[0]);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERTags.java b/azureus2/src/org/bouncycastle/asn1/DERTags.java
deleted file mode 100644
index ef441ef..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERTags.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.asn1;
-
-public interface DERTags
-{
-    public static final int BOOLEAN             = 0x01;
-    public static final int INTEGER             = 0x02;
-    public static final int BIT_STRING          = 0x03;
-    public static final int OCTET_STRING        = 0x04;
-    public static final int NULL                = 0x05;
-    public static final int OBJECT_IDENTIFIER   = 0x06;
-    public static final int EXTERNAL            = 0x08;
-    public static final int ENUMERATED          = 0x0a;
-    public static final int SEQUENCE            = 0x10;
-    public static final int SEQUENCE_OF         = 0x10; // for completeness
-    public static final int SET                 = 0x11;
-    public static final int SET_OF              = 0x11; // for completeness
-
-
-    public static final int NUMERIC_STRING      = 0x12;
-    public static final int PRINTABLE_STRING    = 0x13;
-    public static final int T61_STRING          = 0x14;
-    public static final int VIDEOTEX_STRING     = 0x15;
-    public static final int IA5_STRING          = 0x16;
-    public static final int UTC_TIME            = 0x17;
-    public static final int GENERALIZED_TIME    = 0x18;
-    public static final int GRAPHIC_STRING      = 0x19;
-    public static final int VISIBLE_STRING      = 0x1a;
-    public static final int GENERAL_STRING      = 0x1b;
-    public static final int UNIVERSAL_STRING    = 0x1c;
-    public static final int BMP_STRING          = 0x1e;
-    public static final int UTF8_STRING         = 0x0c;
-    
-    public static final int CONSTRUCTED         = 0x20;
-    public static final int APPLICATION         = 0x40;
-    public static final int TAGGED              = 0x80;
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERUTCTime.java b/azureus2/src/org/bouncycastle/asn1/DERUTCTime.java
deleted file mode 100644
index 7a05664..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERUTCTime.java
+++ /dev/null
@@ -1,254 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.SimpleTimeZone;
-
-/**
- * UTC time object.
- */
-public class DERUTCTime
-    extends ASN1Object
-{
-    String      time;
-
-    /**
-     * return an UTC Time from the passed in object.
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERUTCTime getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERUTCTime)
-        {
-            return (DERUTCTime)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERUTCTime(((ASN1OctetString)obj).getOctets());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return an UTC Time from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERUTCTime getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-    
-    /**
-     * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
-     * never encoded. When you're creating one of these objects from scratch, that's
-     * what you want to use, otherwise we'll try to deal with whatever gets read from
-     * the input stream... (this is why the input format is different from the getTime()
-     * method output).
-     * <p>
-     *
-     * @param time the time string.
-     */
-    public DERUTCTime(
-        String  time)
-    {
-        this.time = time;
-        try
-        {
-            this.getDate();
-        }
-        catch (ParseException e)
-        {
-            throw new IllegalArgumentException("invalid date string: " + e.getMessage());
-        }
-    }
-
-    /**
-     * base constructer from a java.util.date object
-     */
-    public DERUTCTime(
-        Date time)
-    {
-        SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
-
-        dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
-        this.time = dateF.format(time);
-    }
-
-    DERUTCTime(
-        byte[]  bytes)
-    {
-        //
-        // explicitly convert to characters
-        //
-        char[]  dateC = new char[bytes.length];
-
-        for (int i = 0; i != dateC.length; i++)
-        {
-            dateC[i] = (char)(bytes[i] & 0xff);
-        }
-
-        this.time = new String(dateC);
-    }
-
-    /**
-     * return the time as a date based on whatever a 2 digit year will return. For
-     * standardised processing use getAdjustedDate().
-     *
-     * @return the resulting date
-     * @exception ParseException if the date string cannot be parsed.
-     */
-    public Date getDate()
-        throws ParseException
-    {
-        SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
-
-        return dateF.parse(getTime());
-    }
-
-    /**
-     * return the time as an adjusted date
-     * in the range of 1950 - 2049.
-     *
-     * @return a date in the range of 1950 to 2049.
-     * @exception ParseException if the date string cannot be parsed.
-     */
-    public Date getAdjustedDate()
-        throws ParseException
-    {
-        SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
-
-        dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
-
-        return dateF.parse(getAdjustedTime());
-    }
-
-    /**
-     * return the time - always in the form of 
-     *  YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
-     * <p>
-     * Normally in a certificate we would expect "Z" rather than "GMT",
-     * however adding the "GMT" means we can just use:
-     * <pre>
-     *     dateF = new SimpleDateFormat("yyMMddHHmmssz");
-     * </pre>
-     * To read in the time and get a date which is compatible with our local
-     * time zone.
-     * <p>
-     * <b>Note:</b> In some cases, due to the local date processing, this
-     * may lead to unexpected results. If you want to stick the normal
-     * convention of 1950 to 2049 use the getAdjustedTime() method.
-     */
-    public String getTime()
-    {
-        //
-        // standardise the format.
-        //
-        if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
-        {
-            if (time.length() == 11)
-            {
-                return time.substring(0, 10) + "00GMT+00:00";
-            }
-            else
-            {
-                return time.substring(0, 12) + "GMT+00:00";
-            }
-        }
-        else
-        {
-            int index = time.indexOf('-');
-            if (index < 0)
-            {
-                index = time.indexOf('+');
-            }
-            String d = time;
-
-            if (index == time.length() - 3)
-            {
-                d += "00";
-            }
-
-            if (index == 10)
-            {
-                return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
-            }
-            else
-            {
-                return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" +  d.substring(15, 17);
-            }
-        }
-    }
-
-    /**
-     * return a time string as an adjusted date with a 4 digit year. This goes
-     * in the range of 1950 - 2049.
-     */
-    public String getAdjustedTime()
-    {
-        String   d = this.getTime();
-
-        if (d.charAt(0) < '5')
-        {
-            return "20" + d;
-        }
-        else
-        {
-            return "19" + d;
-        }
-    }
-
-    private byte[] getOctets()
-    {
-        char[]  cs = time.toCharArray();
-        byte[]  bs = new byte[cs.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            bs[i] = (byte)cs[i];
-        }
-
-        return bs;
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        out.writeEncoded(UTC_TIME, this.getOctets());
-    }
-    
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERUTCTime))
-        {
-            return false;
-        }
-
-        return time.equals(((DERUTCTime)o).time);
-    }
-    
-    public int hashCode()
-    {
-        return time.hashCode();
-    }
-
-    public String toString() 
-    {
-      return time;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERUTF8String.java b/azureus2/src/org/bouncycastle/asn1/DERUTF8String.java
deleted file mode 100644
index 082aa63..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERUTF8String.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.bouncycastle.asn1;
-
-import org.bouncycastle.util.Strings;
-
-import java.io.IOException;
-
-/**
- * DER UTF8String object.
- */
-public class DERUTF8String
-    extends ASN1Object
-    implements DERString
-{
-    String string;
-
-    /**
-     * return an UTF8 string from the passed in object.
-     * 
-     * @exception IllegalArgumentException
-     *                if the object cannot be converted.
-     */
-    public static DERUTF8String getInstance(Object obj)
-    {
-        if (obj == null || obj instanceof DERUTF8String)
-        {
-            return (DERUTF8String)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERUTF8String(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: "
-                + obj.getClass().getName());
-    }
-
-    /**
-     * return an UTF8 String from a tagged object.
-     * 
-     * @param obj
-     *            the tagged object holding the object we want
-     * @param explicit
-     *            true if the object is meant to be explicitly tagged false
-     *            otherwise.
-     * @exception IllegalArgumentException
-     *                if the tagged object cannot be converted.
-     */
-    public static DERUTF8String getInstance(
-        ASN1TaggedObject obj,
-        boolean explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-
-    /**
-     * basic constructor - byte encoded string.
-     */
-    DERUTF8String(byte[] string)
-    {
-        this.string = Strings.fromUTF8ByteArray(string);
-    }
-
-    /**
-     * basic constructor
-     */
-    public DERUTF8String(String string)
-    {
-        this.string = string;
-    }
-
-    public String getString()
-    {
-        return string;
-    }
-
-    public String toString()
-    {
-        return string;
-    }
-
-    public int hashCode()
-    {
-        return this.getString().hashCode();
-    }
-
-    boolean asn1Equals(DERObject o)
-    {
-        if (!(o instanceof DERUTF8String))
-        {
-            return false;
-        }
-
-        DERUTF8String s = (DERUTF8String)o;
-
-        return this.getString().equals(s.getString());
-    }
-
-    void encode(DEROutputStream out)
-        throws IOException
-    {
-        out.writeEncoded(UTF8_STRING, Strings.toUTF8ByteArray(string));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERUniversalString.java b/azureus2/src/org/bouncycastle/asn1/DERUniversalString.java
deleted file mode 100644
index 68be9a0..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERUniversalString.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * DER UniversalString object.
- */
-public class DERUniversalString
-    extends ASN1Object
-    implements DERString
-{
-    private static final char[]  table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-    private byte[] string;
-    
-    /**
-     * return a Universal String from the passed in object.
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERUniversalString getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERUniversalString)
-        {
-            return (DERUniversalString)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERUniversalString(((ASN1OctetString)obj).getOctets());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return a Universal String from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERUniversalString getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-
-    /**
-     * basic constructor - byte encoded string.
-     */
-    public DERUniversalString(
-        byte[]   string)
-    {
-        this.string = string;
-    }
-
-    public String getString()
-    {
-        StringBuffer    buf = new StringBuffer("#");
-        ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
-        ASN1OutputStream            aOut = new ASN1OutputStream(bOut);
-        
-        try
-        {
-            aOut.writeObject(this);
-        }
-        catch (IOException e)
-        {
-           throw new RuntimeException("internal error encoding BitString");
-        }
-        
-        byte[]    string = bOut.toByteArray();
-        
-        for (int i = 0; i != string.length; i++)
-        {
-            buf.append(table[(string[i] >>> 4) & 0xf]);
-            buf.append(table[string[i] & 0xf]);
-        }
-        
-        return buf.toString();
-    }
-
-    public String toString()
-    {
-        return getString();
-    }
-
-    public byte[] getOctets()
-    {
-        return string;
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        out.writeEncoded(UNIVERSAL_STRING, this.getOctets());
-    }
-    
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERUniversalString))
-        {
-            return false;
-        }
-
-        return this.getString().equals(((DERUniversalString)o).getString());
-    }
-    
-    public int hashCode()
-    {
-        return this.getString().hashCode();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERUnknownTag.java b/azureus2/src/org/bouncycastle/asn1/DERUnknownTag.java
deleted file mode 100644
index 6570d34..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERUnknownTag.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * We insert one of these when we find a tag we don't recognise.
- */
-public class DERUnknownTag
-    extends DERObject
-{
-    int         tag;
-    byte[]      data;
-
-    /**
-     * @param tag the tag value.
-     * @param data the octets making up the time.
-     */
-    public DERUnknownTag(
-        int     tag,
-        byte[]  data)
-    {
-        this.tag = tag;
-        this.data = data;
-    }
-
-    public int getTag()
-    {
-        return tag;
-    }
-
-    public byte[] getData()
-    {
-        return data;
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        out.writeEncoded(tag, data);
-    }
-    
-    public boolean equals(
-        Object o)
-    {
-        if (!(o instanceof DERUnknownTag))
-        {
-            return false;
-        }
-        
-        DERUnknownTag other = (DERUnknownTag)o;
-        
-        if (tag != other.tag)
-        {
-            return false;
-        }
-        
-        if (data.length != other.data.length)
-        {
-            return false;
-        }
-        
-        for (int i = 0; i < data.length; i++) 
-        {
-            if(data[i] != other.data[i])
-            {
-                return false;
-            }
-        }
-        
-        return true;
-    }
-    
-    public int hashCode()
-    {
-        byte[]  b = this.getData();
-        int     value = 0;
-
-        for (int i = 0; i != b.length; i++)
-        {
-            value ^= (b[i] & 0xff) << (i % 4);
-        }
-
-        return value ^ this.getTag();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DERVisibleString.java b/azureus2/src/org/bouncycastle/asn1/DERVisibleString.java
deleted file mode 100644
index 9d0c991..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DERVisibleString.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER VisibleString object.
- */
-public class DERVisibleString
-    extends ASN1Object
-    implements DERString
-{
-    String  string;
-
-    /**
-     * return a Visible String from the passed in object.
-     *
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static DERVisibleString getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DERVisibleString)
-        {
-            return (DERVisibleString)obj;
-        }
-
-        if (obj instanceof ASN1OctetString)
-        {
-            return new DERVisibleString(((ASN1OctetString)obj).getOctets());
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * return a Visible String from a tagged object.
-     *
-     * @param obj the tagged object holding the object we want
-     * @param explicit true if the object is meant to be explicitly
-     *              tagged false otherwise.
-     * @exception IllegalArgumentException if the tagged object cannot
-     *               be converted.
-     */
-    public static DERVisibleString getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject());
-    }
-
-    /**
-     * basic constructor - byte encoded string.
-     */
-    public DERVisibleString(
-        byte[]   string)
-    {
-        char[]  cs = new char[string.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            cs[i] = (char)(string[i] & 0xff);
-        }
-
-        this.string = new String(cs);
-    }
-
-    /**
-     * basic constructor
-     */
-    public DERVisibleString(
-        String   string)
-    {
-        this.string = string;
-    }
-
-    public String getString()
-    {
-        return string;
-    }
-
-    public String toString()
-    {
-        return string;
-    }
-
-    public byte[] getOctets()
-    {
-        char[]  cs = string.toCharArray();
-        byte[]  bs = new byte[cs.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            bs[i] = (byte)cs[i];
-        }
-
-        return bs;
-    }
-
-    void encode(
-        DEROutputStream  out)
-        throws IOException
-    {
-        out.writeEncoded(VISIBLE_STRING, this.getOctets());
-    }
-    
-    boolean asn1Equals(
-        DERObject  o)
-    {
-        if (!(o instanceof DERVisibleString))
-        {
-            return false;
-        }
-
-        return this.getString().equals(((DERVisibleString)o).getString());
-    }
-    
-    public int hashCode()
-    {
-        return this.getString().hashCode();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/DefiniteLengthInputStream.java b/azureus2/src/org/bouncycastle/asn1/DefiniteLengthInputStream.java
deleted file mode 100644
index 9a805d2..0000000
--- a/azureus2/src/org/bouncycastle/asn1/DefiniteLengthInputStream.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.EOFException;
-import java.io.InputStream;
-import java.io.IOException;
-
-class DefiniteLengthInputStream
-        extends LimitedInputStream
-{
-    private int               _length;
-
-    DefiniteLengthInputStream(
-        InputStream in,
-        int         length)
-    {
-        super(in);
-
-        if (length < 0)
-        {
-            throw new IllegalArgumentException("negative lengths not allowed");
-        }
-
-        this._length = length;
-    }
-
-    public int read()
-        throws IOException
-    {
-        if (_length > 0)
-        {
-            int b = _in.read();
-
-            if (b < 0)
-            {
-                throw new EOFException();
-            }
-
-            --_length;
-            return b;
-        }
-
-        setParentEofDetect(true);
-
-        return -1;
-    }
-
-    public int read(byte[] buf, int off, int len)
-        throws IOException
-    {
-        if (_length > 0)
-        {
-            int toRead = Math.min(len, _length);
-            int numRead = _in.read(buf, off, toRead);
-
-            if (numRead < 0)
-                throw new EOFException();
-
-            _length -= numRead;
-            return numRead;
-        }
-
-        setParentEofDetect(true);
-
-        return -1;
-    }
-
-    byte[] toByteArray()
-        throws IOException
-    {
-        byte[] bytes = new byte[_length];
-
-        if (_length > 0)
-        {
-            int pos = 0;
-            do
-            {
-                int read = _in.read(bytes, pos, _length - pos);
-
-                if (read < 0)
-                {
-                    throw new EOFException();
-                }
-
-                pos += read;
-            }
-            while (pos < _length);
-
-            _length = 0;
-        }
-
-        setParentEofDetect(true);
-
-        return bytes;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/IndefiniteLengthInputStream.java b/azureus2/src/org/bouncycastle/asn1/IndefiniteLengthInputStream.java
deleted file mode 100644
index 87208b5..0000000
--- a/azureus2/src/org/bouncycastle/asn1/IndefiniteLengthInputStream.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-class IndefiniteLengthInputStream
-    extends LimitedInputStream
-{
-    private int _b1;
-    private int _b2;
-    private boolean _eofReached = false;
-    private boolean _eofOn00 = true;
-
-    IndefiniteLengthInputStream(
-        InputStream in)
-        throws IOException
-    {
-        super(in);
-
-        _b1 = in.read();
-        _b2 = in.read();
-        _eofReached = (_b2 < 0);
-    }
-
-    void setEofOn00(
-        boolean eofOn00)
-    {
-        _eofOn00 = eofOn00;
-    }
-
-    boolean checkForEof()
-    {
-        if (_eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
-        {
-            _eofReached = true;
-            setParentEofDetect(true);
-        }
-        return _eofReached;
-    }
-
-    public int read(byte[] b, int off, int len)
-        throws IOException
-    {
-        // Only use this optimisation if we aren't checking for 00
-        if (_eofOn00 || len < 3)
-        {
-            return super.read(b, off, len);
-        }
-
-        if (_eofReached)
-        {
-            return -1;
-        }
-
-        int numRead = _in.read(b, off + 2, len - 2);
-
-        if (numRead < 0)
-        {
-//          throw new EOFException();
-            _eofReached = true;
-            return -1;
-        }
-
-        b[off] = (byte)_b1;
-        b[off + 1] = (byte)_b2;
-
-        _b1 = _in.read();
-        _b2 = _in.read();
-
-        if (_b2 < 0)
-        {
-            // Corrupted stream
-//            throw new EOFException();
-            _eofReached = true;
-            // Just fall thru...
-        }
-
-        return numRead + 2;
-    }
-
-    public int read()
-        throws IOException
-    {
-        if (checkForEof())
-        {
-            return -1;
-        }
-
-        int b = _in.read();
-
-        //
-        // strictly speaking we should return b1 and b2, but if this happens the stream
-        // is corrupted so we are already in trouble.
-        //
-        if (b < 0)
-        {
-            // Corrupted stream
-//            throw new EOFException();
-            _eofReached = true;
-
-            return -1;
-        }
-
-        int v = _b1;
-
-        _b1 = _b2;
-        _b2 = b;
-
-        return v;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/LimitedInputStream.java b/azureus2/src/org/bouncycastle/asn1/LimitedInputStream.java
deleted file mode 100644
index 027a87f..0000000
--- a/azureus2/src/org/bouncycastle/asn1/LimitedInputStream.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-
-abstract class LimitedInputStream
-        extends InputStream
-{
-    protected final InputStream _in;
-
-    LimitedInputStream(
-        InputStream in)
-    {
-        this._in = in;
-    }
-
-    InputStream getUnderlyingStream()
-    {
-        return _in;
-    }
-
-    protected void setParentEofDetect(boolean on)
-    {
-        if (_in instanceof IndefiniteLengthInputStream)
-        {
-            ((IndefiniteLengthInputStream)_in).setEofOn00(on);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/OIDTokenizer.java b/azureus2/src/org/bouncycastle/asn1/OIDTokenizer.java
deleted file mode 100644
index 5467944..0000000
--- a/azureus2/src/org/bouncycastle/asn1/OIDTokenizer.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * class for breaking up an OID into it's component tokens, ala
- * java.util.StringTokenizer. We need this class as some of the
- * lightweight Java environment don't support classes like
- * StringTokenizer.
- */
-public class OIDTokenizer
-{
-    private String  oid;
-    private int     index;
-
-    public OIDTokenizer(
-        String oid)
-    {
-        this.oid = oid;
-        this.index = 0;
-    }
-
-    public boolean hasMoreTokens()
-    {
-        return (index != -1);
-    }
-
-    public String nextToken()
-    {
-        if (index == -1)
-        {
-            return null;
-        }
-
-        String  token;
-        int     end = oid.indexOf('.', index);
-
-        if (end == -1)
-        {
-            token = oid.substring(index);
-            index = -1;
-            return token;
-        }
-
-        token = oid.substring(index, end);
-
-        index = end + 1;
-        return token;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java b/azureus2/src/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
deleted file mode 100644
index 2e6b312..0000000
--- a/azureus2/src/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-
-public interface CMSObjectIdentifiers
-{
-    static final DERObjectIdentifier    data = PKCSObjectIdentifiers.data;
-    static final DERObjectIdentifier    signedData = PKCSObjectIdentifiers.signedData;
-    static final DERObjectIdentifier    envelopedData = PKCSObjectIdentifiers.envelopedData;
-    static final DERObjectIdentifier    signedAndEnvelopedData = PKCSObjectIdentifiers.signedAndEnvelopedData;
-    static final DERObjectIdentifier    digestedData = PKCSObjectIdentifiers.digestedData;
-    static final DERObjectIdentifier    encryptedData = PKCSObjectIdentifiers.encryptedData;
-    static final DERObjectIdentifier    compressedData = PKCSObjectIdentifiers.id_ct_compressedData;
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/cms/ContentInfo.java b/azureus2/src/org/bouncycastle/asn1/cms/ContentInfo.java
deleted file mode 100644
index 76801a3..0000000
--- a/azureus2/src/org/bouncycastle/asn1/cms/ContentInfo.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.asn1.cms;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.BERTaggedObject;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-public class ContentInfo
-    extends ASN1Encodable
-    implements CMSObjectIdentifiers
-{
-    private DERObjectIdentifier contentType;
-    private DEREncodable        content;
-
-    public static ContentInfo getInstance(
-        Object  obj)
-    {
-        if (obj instanceof ContentInfo)
-        {
-            return (ContentInfo)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new ContentInfo((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
-    }
-
-    public ContentInfo(
-        ASN1Sequence  seq)
-    {
-        Enumeration   e = seq.getObjects();
-
-        contentType = (DERObjectIdentifier)e.nextElement();
-
-        if (e.hasMoreElements())
-        {
-            content = ((ASN1TaggedObject)e.nextElement()).getObject();
-        }
-    }
-
-    public ContentInfo(
-        DERObjectIdentifier contentType,
-        DEREncodable        content)
-    {
-        this.contentType = contentType;
-        this.content = content;
-    }
-
-    public DERObjectIdentifier getContentType()
-    {
-        return contentType;
-    }
-
-    public DEREncodable getContent()
-    {
-        return content;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * ContentInfo ::= SEQUENCE {
-     *          contentType ContentType,
-     *          content
-     *          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(contentType);
-
-        if (content != null)
-        {
-            v.add(new BERTaggedObject(0, content));
-        }
-
-        return new BERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/misc/CAST5CBCParameters.java b/azureus2/src/org/bouncycastle/asn1/misc/CAST5CBCParameters.java
deleted file mode 100644
index b2390dc..0000000
--- a/azureus2/src/org/bouncycastle/asn1/misc/CAST5CBCParameters.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.*;
-
-public class CAST5CBCParameters
-    implements DEREncodable
-{
-    DERInteger      keyLength;
-    ASN1OctetString iv;
-
-    public static CAST5CBCParameters getInstance(
-        Object  o)
-    {
-        if (o instanceof CAST5CBCParameters)
-        {
-            return (CAST5CBCParameters)o;
-        }
-        else if (o instanceof ASN1Sequence)
-        {
-            return new CAST5CBCParameters((ASN1Sequence)o);
-        }
-
-        throw new IllegalArgumentException("unknown object in CAST5CBCParameter factory");
-    }
-
-    public CAST5CBCParameters(
-        byte[]  iv,
-        int     keyLength)
-    {
-        this.iv = new DEROctetString(iv);
-        this.keyLength = new DERInteger(keyLength);
-    }
-
-    public CAST5CBCParameters(
-        ASN1Sequence  seq)
-    {
-        iv = (ASN1OctetString)seq.getObjectAt(0);
-        keyLength = (DERInteger)seq.getObjectAt(1);
-    }
-
-    public byte[] getIV()
-    {
-        return iv.getOctets();
-    }
-
-    public int getKeyLength()
-    {
-        return keyLength.getValue().intValue();
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * cast5CBCParameters ::= SEQUENCE {
-     *                           iv         OCTET STRING DEFAULT 0,
-     *                                  -- Initialization vector
-     *                           keyLength  INTEGER
-     *                                  -- Key length, in bits
-     *                      }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(iv);
-        v.add(keyLength);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/misc/IDEACBCPar.java b/azureus2/src/org/bouncycastle/asn1/misc/IDEACBCPar.java
deleted file mode 100644
index 49b752e..0000000
--- a/azureus2/src/org/bouncycastle/asn1/misc/IDEACBCPar.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.*;
-
-public class IDEACBCPar
-    implements DEREncodable
-{
-    ASN1OctetString  iv;
-
-    public static IDEACBCPar getInstance(
-        Object  o)
-    {
-        if (o instanceof IDEACBCPar)
-        {
-            return (IDEACBCPar)o;
-        }
-        else if (o instanceof ASN1Sequence)
-        {
-            return new IDEACBCPar((ASN1Sequence)o);
-        }
-
-        throw new IllegalArgumentException("unknown object in IDEACBCPar factory");
-    }
-
-    public IDEACBCPar(
-        byte[]  iv)
-    {
-        this.iv = new DEROctetString(iv);
-    }
-
-    public IDEACBCPar(
-        ASN1Sequence  seq)
-    {
-        if (seq.size() == 1)
-        {
-            iv = (ASN1OctetString)seq.getObjectAt(0);
-        }
-        else
-        {
-            iv = null;
-        }
-    }
-
-    public byte[] getIV()
-    {
-        if (iv != null)
-        {
-            return iv.getOctets();
-        }
-        else
-        {
-            return null;
-        }
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * IDEA-CBCPar ::= SEQUENCE {
-     *                      iv    OCTET STRING OPTIONAL -- exactly 8 octets
-     *                  }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        if (iv != null)
-        {
-            v.add(iv);
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java b/azureus2/src/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
deleted file mode 100644
index b2d46e2..0000000
--- a/azureus2/src/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-public interface MiscObjectIdentifiers
-{
-    //
-    // Netscape
-    //       iso/itu(2) joint-assign(16) us(840) uscompany(1) netscape(113730) cert-extensions(1) }
-    //
-    static final String                 netscape                = "2.16.840.1.113730.1";
-    static final DERObjectIdentifier    netscapeCertType        = new DERObjectIdentifier(netscape + ".1");
-    static final DERObjectIdentifier    netscapeBaseURL         = new DERObjectIdentifier(netscape + ".2");
-    static final DERObjectIdentifier    netscapeRevocationURL   = new DERObjectIdentifier(netscape + ".3");
-    static final DERObjectIdentifier    netscapeCARevocationURL = new DERObjectIdentifier(netscape + ".4");
-    static final DERObjectIdentifier    netscapeRenewalURL      = new DERObjectIdentifier(netscape + ".7");
-    static final DERObjectIdentifier    netscapeCApolicyURL     = new DERObjectIdentifier(netscape + ".8");
-    static final DERObjectIdentifier    netscapeSSLServerName   = new DERObjectIdentifier(netscape + ".12");
-    static final DERObjectIdentifier    netscapeCertComment     = new DERObjectIdentifier(netscape + ".13");
-    //
-    // Verisign
-    //       iso/itu(2) joint-assign(16) us(840) uscompany(1) verisign(113733) cert-extensions(1) }
-    //
-    static final String                 verisign                = "2.16.840.1.113733.1";
-
-    //
-    // CZAG - country, zip, age, and gender
-    //
-    static final DERObjectIdentifier    verisignCzagExtension   = new DERObjectIdentifier(verisign + ".6.3");
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/misc/NetscapeCertType.java b/azureus2/src/org/bouncycastle/asn1/misc/NetscapeCertType.java
deleted file mode 100644
index 61a851a..0000000
--- a/azureus2/src/org/bouncycastle/asn1/misc/NetscapeCertType.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.*;
-
-/**
- * The NetscapeCertType object.
- * <pre>
- *    NetscapeCertType ::= BIT STRING {
- *         SSLClient               (0),
- *         SSLServer               (1),
- *         S/MIME                  (2),
- *         Object Signing          (3),
- *         Reserved                (4),
- *         SSL CA                  (5),
- *         S/MIME CA               (6),
- *         Object Signing CA       (7) }
- * </pre>
- */
-public class NetscapeCertType
-    extends DERBitString
-{
-    public static final int        sslClient        = (1 << 7); 
-    public static final int        sslServer        = (1 << 6);
-    public static final int        smime            = (1 << 5);
-    public static final int        objectSigning    = (1 << 4);
-    public static final int        reserved         = (1 << 3);
-    public static final int        sslCA            = (1 << 2);
-    public static final int        smimeCA          = (1 << 1);
-    public static final int        objectSigningCA  = (1 << 0);
-
-    /**
-     * Basic constructor.
-     * 
-     * @param usage - the bitwise OR of the Key Usage flags giving the
-     * allowed uses for the key.
-     * e.g. (X509NetscapeCertType.sslCA | X509NetscapeCertType.smimeCA)
-     */
-    public NetscapeCertType(
-        int usage)
-    {
-        super(getBytes(usage), getPadBits(usage));
-    }
-
-    public NetscapeCertType(
-        DERBitString usage)
-    {
-        super(usage.getBytes(), usage.getPadBits());
-    }
-
-    public String toString()
-    {
-        return "NetscapeCertType: 0x" + Integer.toHexString(data[0] & 0xff);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java b/azureus2/src/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java
deleted file mode 100644
index ba35d08..0000000
--- a/azureus2/src/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.*;
-
-public class NetscapeRevocationURL
-    extends DERIA5String
-{
-    public NetscapeRevocationURL(
-        DERIA5String str)
-    {
-        super(str.getString());
-    }
-
-    public String toString()
-    {
-        return "NetscapeRevocationURL: " + this.getString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/misc/VerisignCzagExtension.java b/azureus2/src/org/bouncycastle/asn1/misc/VerisignCzagExtension.java
deleted file mode 100644
index 5066ec5..0000000
--- a/azureus2/src/org/bouncycastle/asn1/misc/VerisignCzagExtension.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.asn1.misc;
-
-import org.bouncycastle.asn1.*;
-
-public class VerisignCzagExtension
-    extends DERIA5String
-{
-    public VerisignCzagExtension(
-        DERIA5String str)
-    {
-        super(str.getString());
-    }
-
-    public String toString()
-    {
-        return "VerisignCzagExtension: " + this.getString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/misc/package.html b/azureus2/src/org/bouncycastle/asn1/misc/package.html
deleted file mode 100644
index e3bda64..0000000
--- a/azureus2/src/org/bouncycastle/asn1/misc/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Miscellaneous object identifiers and objects.
-</body>
-</html>
diff --git a/azureus2/src/org/bouncycastle/asn1/package.html b/azureus2/src/org/bouncycastle/asn1/package.html
deleted file mode 100644
index 1ac16a5..0000000
--- a/azureus2/src/org/bouncycastle/asn1/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-A library for parsing and writing ASN.1 objects. Support is provided for DER and BER encoding.
-</body>
-</html>
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/Attribute.java b/azureus2/src/org/bouncycastle/asn1/pkcs/Attribute.java
deleted file mode 100644
index 69ede00..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/Attribute.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-public class Attribute
-    implements DEREncodable
-{
-	private DERObjectIdentifier attrType;
-	private ASN1Set             attrValues;
-
-    /**
-     * return an Attribute object from the given object.
-     *
-     * @param o the object we want converted.
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-	public static Attribute getInstance(
-        Object o)
-    {
-		if (o == null || o instanceof Attribute)
-        {
-			return (Attribute)o;
-		}
-		
-		if (o instanceof ASN1Sequence)
-        {
-			return new Attribute((ASN1Sequence)o);
-		}
-
-        throw new IllegalArgumentException("unknown object in factory");
-	}
-	
-	public Attribute(
-        ASN1Sequence seq)
-    {
-		attrType = (DERObjectIdentifier)seq.getObjectAt(0);
-		attrValues = (ASN1Set)seq.getObjectAt(1);
-	}
-
-	public Attribute(
-	    DERObjectIdentifier attrType,
-	    ASN1Set             attrValues)
-    {
-		this.attrType = attrType;
-		this.attrValues = attrValues;
-	}
-
-	public DERObjectIdentifier getAttrType()
-    {
-		return attrType;
-	}
-	
-	public ASN1Set getAttrValues()
-    {
-		return attrValues;
-	}
-
-    /** 
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * Attribute ::= SEQUENCE {
-     * 	attrType OBJECT IDENTIFIER,
-     * 	attrValues SET OF AttributeValue
-     * }
-     * </pre>
-     */
-	public DERObject getDERObject()
-    {
-		ASN1EncodableVector v = new ASN1EncodableVector();
-
-		v.add(attrType);
-		v.add(attrValues);
-
-		return new DERSequence(v);
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java b/azureus2/src/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java
deleted file mode 100644
index 48f6ddc..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-
-public class AuthenticatedSafe
-    implements DEREncodable
-{
-    ContentInfo[]    info;
-
-    public AuthenticatedSafe(
-        ASN1Sequence  seq)
-    {
-        info = new ContentInfo[seq.size()];
-
-        for (int i = 0; i != info.length; i++)
-        {
-            info[i] = ContentInfo.getInstance(seq.getObjectAt(i));
-        }
-    }
-
-    public AuthenticatedSafe(
-        ContentInfo[]       info)
-    {
-        this.info = info;
-    }
-
-    public ContentInfo[] getContentInfo()
-    {
-        return info;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        for (int i = 0; i != info.length; i++)
-        {
-            v.add(info[i]);
-        }
-
-        return new BERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/CertBag.java b/azureus2/src/org/bouncycastle/asn1/pkcs/CertBag.java
deleted file mode 100644
index 4cb659c..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/CertBag.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class CertBag
-    implements DEREncodable
-{
-	ASN1Sequence		seq;
-    DERObjectIdentifier         certId;
-    DERObject                   certValue;
-
-	public CertBag(
-		ASN1Sequence	seq)
-	{
-        this.seq = seq;
-        this.certId = (DERObjectIdentifier)seq.getObjectAt(0);
-        this.certValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject();
-	}
-
-    public CertBag(
-        DERObjectIdentifier certId,
-        DERObject           certValue)
-    {
-        this.certId = certId;
-        this.certValue = certValue;
-    }
-
-	public DERObjectIdentifier getCertId()
-	{
-		return certId;
-	}
-
-    public DERObject getCertValue()
-    {
-		return certValue;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(certId);
-        v.add(new DERTaggedObject(0, certValue));
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/CertificationRequest.java b/azureus2/src/org/bouncycastle/asn1/pkcs/CertificationRequest.java
deleted file mode 100644
index 9197e84..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/CertificationRequest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * PKCS10 Certfication request object.
- * <pre>
- * CertificationRequest ::= SEQUENCE {
- *   certificationRequestInfo  CertificationRequestInfo,
- *   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
- *   signature                 BIT STRING
- * }
- * </pre>
- */
-public class CertificationRequest
-    implements DEREncodable
-{
-    protected CertificationRequestInfo reqInfo = null;
-    protected AlgorithmIdentifier sigAlgId = null;
-    protected DERBitString sigBits = null;
-
-    protected CertificationRequest()
-    {
-    }
-
-    public CertificationRequest(
-        CertificationRequestInfo requestInfo,
-        AlgorithmIdentifier     algorithm,
-        DERBitString            signature)
-    {
-        this.reqInfo = requestInfo;
-        this.sigAlgId = algorithm;
-        this.sigBits = signature;
-    }
-
-    public CertificationRequest(
-        ASN1Sequence seq)
-    {
-        reqInfo = CertificationRequestInfo.getInstance(seq.getObjectAt(0));
-        sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
-        sigBits = (DERBitString)seq.getObjectAt(2);
-    }
-
-    public CertificationRequestInfo getCertificationRequestInfo()
-    {
-        return reqInfo;
-    }
-
-    public AlgorithmIdentifier getSignatureAlgorithm()
-    {
-        return sigAlgId;
-    }
-
-    public DERBitString getSignature()
-    {
-        return sigBits;
-    }
-
-    public DERObject getDERObject()
-    {
-        // Construct the CertificateRequest
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(reqInfo);
-        v.add(sigAlgId);
-        v.add(sigBits);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java b/azureus2/src/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java
deleted file mode 100644
index 4f7d833..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.X509Name;
-
-/**
- * PKCS10 CertificationRequestInfo object.
- * <pre>
- *  CertificationRequestInfo ::= SEQUENCE {
- *   version             INTEGER { v1(0) } (v1,...),
- *   subject             Name,
- *   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
- *   attributes          [0] Attributes{{ CRIAttributes }}
- *  }
- *
- *  Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
- *
- *  Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
- *    type    ATTRIBUTE.&id({IOSet}),
- *    values  SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
- *  }
- * </pre>
- */
-public class CertificationRequestInfo
-    implements DEREncodable
-{
-    DERInteger              version = new DERInteger(0);
-    X509Name                subject;
-    SubjectPublicKeyInfo    subjectPKInfo;
-    ASN1Set                 attributes = null;
-
-    public static CertificationRequestInfo getInstance(
-        Object  obj)
-    {
-        if (obj instanceof CertificationRequestInfo)
-        {
-            return (CertificationRequestInfo)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new CertificationRequestInfo((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public CertificationRequestInfo(
-        X509Name                subject,
-        SubjectPublicKeyInfo    pkInfo,
-        ASN1Set                 attributes)
-    {
-        this.subject = subject;
-        this.subjectPKInfo = pkInfo;
-        this.attributes = attributes;
-
-        if ((subject == null) || (version == null) || (subjectPKInfo == null))
-        {
-            throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
-        }
-    }
-
-    public CertificationRequestInfo(
-        ASN1Sequence  seq)
-    {
-        version = (DERInteger)seq.getObjectAt(0);
-
-        subject = X509Name.getInstance(seq.getObjectAt(1));
-        subjectPKInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(2));
-
-        //
-        // some CertificationRequestInfo objects seem to treat this field
-        // as optional.
-        //
-        if (seq.size() > 3)
-        {
-            DERTaggedObject tagobj = (DERTaggedObject)seq.getObjectAt(3);
-            attributes = ASN1Set.getInstance(tagobj, false);
-        }
-
-        if ((subject == null) || (version == null) || (subjectPKInfo == null))
-        {
-            throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
-        }
-    }
-
-    public DERInteger getVersion()
-    {
-        return version;
-    }
-
-    public X509Name getSubject()
-    {
-        return subject;
-    }
-
-    public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
-    {
-        return subjectPKInfo;
-    }
-
-    public ASN1Set getAttributes()
-    {
-        return attributes;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(version);
-        v.add(subject);
-        v.add(subjectPKInfo);
-
-        if (attributes != null)
-        {
-            v.add(new DERTaggedObject(false, 0, attributes));
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/ContentInfo.java b/azureus2/src/org/bouncycastle/asn1/pkcs/ContentInfo.java
deleted file mode 100644
index 4f9e675..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/ContentInfo.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.BERTaggedObject;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class ContentInfo
-    implements DEREncodable, PKCSObjectIdentifiers
-{
-    private DERObjectIdentifier contentType;
-    private DEREncodable        content;
-
-    public static ContentInfo getInstance(
-        Object  obj)
-    {
-        if (obj instanceof ContentInfo)
-        {
-            return (ContentInfo)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new ContentInfo((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public ContentInfo(
-        ASN1Sequence  seq)
-    {
-        Enumeration   e = seq.getObjects();
-
-        contentType = (DERObjectIdentifier)e.nextElement();
-
-        if (e.hasMoreElements())
-        {
-            content = ((DERTaggedObject)e.nextElement()).getObject();
-        }
-    }
-
-    public ContentInfo(
-        DERObjectIdentifier contentType,
-        DEREncodable        content)
-    {
-        this.contentType = contentType;
-        this.content = content;
-    }
-
-    public DERObjectIdentifier getContentType()
-    {
-        return contentType;
-    }
-
-    public DEREncodable getContent()
-    {
-        return content;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * ContentInfo ::= SEQUENCE {
-     *          contentType ContentType,
-     *          content
-     *          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(contentType);
-
-        if (content != null)
-        {
-            v.add(new BERTaggedObject(0, content));
-        }
-
-        return new BERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/DHParameter.java b/azureus2/src/org/bouncycastle/asn1/pkcs/DHParameter.java
deleted file mode 100644
index 8998c51..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/DHParameter.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class DHParameter
-    implements DEREncodable
-{
-    DERInteger      p, g, l;
-
-    public DHParameter(
-        BigInteger  p,
-        BigInteger  g,
-        int         l)
-    {
-        this.p = new DERInteger(p);
-        this.g = new DERInteger(g);
-
-        if (l != 0)
-        {
-            this.l = new DERInteger(l);
-        }
-        else
-        {
-            this.l = null;
-        }
-    }
-
-    public DHParameter(
-        ASN1Sequence  seq)
-    {
-        Enumeration     e = seq.getObjects();
-
-        p = (DERInteger)e.nextElement();
-        g = (DERInteger)e.nextElement();
-
-        if (e.hasMoreElements())
-        {
-            l = (DERInteger)e.nextElement();
-        }
-        else
-        {
-            l = null;
-        }
-    }
-
-    public BigInteger getP()
-    {
-        return p.getPositiveValue();
-    }
-
-    public BigInteger getG()
-    {
-        return g.getPositiveValue();
-    }
-
-    public BigInteger getL()
-    {
-        if (l == null)
-        {
-            return null;
-        }
-
-        return l.getPositiveValue();
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(p);
-        v.add(g);
-
-        if (this.getL() != null)
-        {
-            v.add(l);
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/EncryptedData.java b/azureus2/src/org/bouncycastle/asn1/pkcs/EncryptedData.java
deleted file mode 100644
index cdabf1e..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/EncryptedData.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.*;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * The EncryptedData object.
- * <pre>
- *      EncryptedData ::= SEQUENCE {
- *           version Version,
- *           encryptedContentInfo EncryptedContentInfo
- *      }
- *
- *
- *      EncryptedContentInfo ::= SEQUENCE {
- *          contentType ContentType,
- *          contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
- *          encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
- *    }
- *
- *    EncryptedContent ::= OCTET STRING
- * </pre>
- */
-public class EncryptedData
-    implements DEREncodable
-{
-    ASN1Sequence                data;
-    DERObjectIdentifier         bagId;
-    DERObject                   bagValue;
-
-	public static EncryptedData getInstance(
-		 Object  obj)
-	{
-		 if (obj instanceof EncryptedData)
-		 {
-			 return (EncryptedData)obj;
-		 }
-		 else if (obj instanceof ASN1Sequence)
-		 {
-			 return new EncryptedData((ASN1Sequence)obj);
-		 }
-
-		 throw new IllegalArgumentException("unknown object in factory");
-	}
-	 
-    public EncryptedData(
-        ASN1Sequence seq)
-    {
-        int version = ((DERInteger)seq.getObjectAt(0)).getValue().intValue();
-
-        if (version != 0)
-        {
-            throw new IllegalArgumentException("sequence not version 0");
-        }
-
-        this.data = (ASN1Sequence)seq.getObjectAt(1);
-    }
-
-    public EncryptedData(
-        DERObjectIdentifier     contentType,
-        AlgorithmIdentifier     encryptionAlgorithm,
-        DEREncodable            content)
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(contentType);
-        v.add(encryptionAlgorithm.getDERObject());
-        v.add(new BERTaggedObject(false, 0, content));
-
-        data = new BERSequence(v);
-    }
-        
-    public DERObjectIdentifier getContentType()
-    {
-        return (DERObjectIdentifier)data.getObjectAt(0);
-    }
-
-    public AlgorithmIdentifier getEncryptionAlgorithm()
-    {
-        return AlgorithmIdentifier.getInstance(data.getObjectAt(1));
-    }
-
-    public ASN1OctetString getContent()
-    {
-        if (data.size() == 3)
-        {
-            DERTaggedObject o = (DERTaggedObject)data.getObjectAt(2);
-
-            return ASN1OctetString.getInstance(o.getObject());
-        }
-
-        return null;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(new DERInteger(0));
-        v.add(data);
-
-        return new BERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java b/azureus2/src/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java
deleted file mode 100644
index 7221871..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class EncryptedPrivateKeyInfo
-    implements PKCSObjectIdentifiers, DEREncodable
-{
-    private AlgorithmIdentifier algId;
-    private ASN1OctetString     data;
-
-    public EncryptedPrivateKeyInfo(
-        ASN1Sequence  seq)
-    {
-        Enumeration e = seq.getObjects();
-
-        algId = new AlgorithmIdentifier((ASN1Sequence)e.nextElement());
-        data = (ASN1OctetString)e.nextElement();
-    }
-
-    public EncryptedPrivateKeyInfo(
-        AlgorithmIdentifier algId,
-        byte[]              encoding)
-    {
-        this.algId = algId;
-        this.data = new DEROctetString(encoding);
-    }
-
-    public AlgorithmIdentifier getEncryptionAlgorithm()
-    {
-        return algId;
-    }
-
-    public byte[] getEncryptedData()
-    {
-        return data.getOctets();
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * EncryptedPrivateKeyInfo ::= SEQUENCE {
-     *      encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
-     *      encryptedData EncryptedData
-     * }
-     *
-     * EncryptedData ::= OCTET STRING
-     *
-     * KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
-     *          ... -- For local profiles
-     * }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(algId);
-        v.add(data);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/EncryptionScheme.java b/azureus2/src/org/bouncycastle/asn1/pkcs/EncryptionScheme.java
deleted file mode 100644
index eb9b326..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/EncryptionScheme.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class EncryptionScheme
-    extends AlgorithmIdentifier
-{   
-    DERObject   objectId;
-    DERObject   obj;
-
-    EncryptionScheme(
-        ASN1Sequence  seq)
-    {   
-        super(seq);
-        
-        objectId = (DERObject)seq.getObjectAt(0);
-        obj = (DERObject)seq.getObjectAt(1);
-    }
-
-    public DERObject getObject()
-    {
-        return obj;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(objectId);
-        v.add(obj);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java b/azureus2/src/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java
deleted file mode 100644
index 47892e8..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.X509Name;
-
-public class IssuerAndSerialNumber
-    implements DEREncodable
-{
-    X509Name    name;
-    DERInteger  certSerialNumber;
-
-    public static IssuerAndSerialNumber getInstance(
-        Object  obj)
-    {
-        if (obj instanceof IssuerAndSerialNumber)
-        {
-            return (IssuerAndSerialNumber)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new IssuerAndSerialNumber((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public IssuerAndSerialNumber(
-        ASN1Sequence    seq)
-    {
-        this.name = X509Name.getInstance(seq.getObjectAt(0));
-        this.certSerialNumber = (DERInteger)seq.getObjectAt(1);
-    }
-
-    public IssuerAndSerialNumber(
-        X509Name    name,
-        BigInteger  certSerialNumber)
-    {
-        this.name = name;
-        this.certSerialNumber = new DERInteger(certSerialNumber);
-    }
-
-    public IssuerAndSerialNumber(
-        X509Name    name,
-        DERInteger  certSerialNumber)
-    {
-        this.name = name;
-        this.certSerialNumber = certSerialNumber;
-    }
-
-    public X509Name getName()
-    {
-        return name;
-    }
-
-    public DERInteger getCertificateSerialNumber()
-    {
-        return certSerialNumber;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector    v = new ASN1EncodableVector();
-
-        v.add(name);
-        v.add(certSerialNumber);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java b/azureus2/src/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java
deleted file mode 100644
index 0da52d3..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-public class KeyDerivationFunc
-    extends AlgorithmIdentifier
-{
-    KeyDerivationFunc(
-        ASN1Sequence  seq)
-    {
-        super(seq);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/MacData.java b/azureus2/src/org/bouncycastle/asn1/pkcs/MacData.java
deleted file mode 100644
index 57b6bf6..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/MacData.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.DigestInfo;
-
-public class MacData
-    implements DEREncodable
-{
-    DigestInfo                  digInfo;
-    byte[]                      salt;
-    BigInteger                  iterationCount;
-
-    public static MacData getInstance(
-        Object  obj)
-    {
-        if (obj instanceof MacData)
-        {
-            return (MacData)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new MacData((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public MacData(
-        ASN1Sequence seq)
-    {
-        this.digInfo = DigestInfo.getInstance(seq.getObjectAt(0));
-
-        this.salt = ((ASN1OctetString)seq.getObjectAt(1)).getOctets();
-
-        if (seq.size() == 3)
-        {
-            this.iterationCount = ((DERInteger)seq.getObjectAt(2)).getValue();
-        }
-        else
-        {
-            this.iterationCount = BigInteger.valueOf(1);
-        }
-    }
-
-    public MacData(
-        DigestInfo  digInfo,
-        byte[]      salt,
-        int         iterationCount)
-    {
-        this.digInfo = digInfo;
-        this.salt = salt;
-        this.iterationCount = BigInteger.valueOf(iterationCount);
-    }
-
-    public DigestInfo getMac()
-    {
-        return digInfo;
-    }
-
-    public byte[] getSalt()
-    {
-        return salt;
-    }
-
-    public BigInteger getIterationCount()
-    {
-        return iterationCount;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(digInfo);
-        v.add(new DEROctetString(salt));
-        v.add(new DERInteger(iterationCount));
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java b/azureus2/src/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java
deleted file mode 100644
index b79f878..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * @deprecated - use AlgorithmIdentifier and PBES2Params
- */
-public class PBES2Algorithms
-    extends AlgorithmIdentifier implements PKCSObjectIdentifiers
-{
-    private DERObjectIdentifier objectId;
-    private KeyDerivationFunc   func;
-    private EncryptionScheme    scheme;
-
-    public PBES2Algorithms(
-        ASN1Sequence  obj)
-    {
-        super(obj);
-
-        Enumeration     e = obj.getObjects();
-
-        objectId = (DERObjectIdentifier)e.nextElement();
-
-        ASN1Sequence seq = (ASN1Sequence)e.nextElement();
-
-        e = seq.getObjects();
-
-        ASN1Sequence  funcSeq = (ASN1Sequence)e.nextElement();
-
-        if (funcSeq.getObjectAt(0).equals(id_PBKDF2))
-        {
-            func = new PBKDF2Params(funcSeq);
-        }
-        else
-        {
-            func = new KeyDerivationFunc(funcSeq);
-        }
-
-        scheme = new EncryptionScheme((ASN1Sequence)e.nextElement());
-    }
-
-    public DERObjectIdentifier getObjectId()
-    {
-        return objectId;
-    }
-
-    public KeyDerivationFunc getKeyDerivationFunc()
-    {
-        return func;
-    }
-
-    public EncryptionScheme getEncryptionScheme()
-    {
-        return scheme;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-        ASN1EncodableVector  subV = new ASN1EncodableVector();
-
-        v.add(objectId);
-
-        subV.add(func);
-        subV.add(scheme);
-        v.add(new DERSequence(subV));
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/PBES2Parameters.java b/azureus2/src/org/bouncycastle/asn1/pkcs/PBES2Parameters.java
deleted file mode 100644
index 2b43ea1..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/PBES2Parameters.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class PBES2Parameters
-    implements PKCSObjectIdentifiers, DEREncodable
-{
-    private KeyDerivationFunc   func;
-    private EncryptionScheme    scheme;
-
-    public PBES2Parameters(
-        ASN1Sequence  obj)
-    {
-        Enumeration e = obj.getObjects();
-        ASN1Sequence  funcSeq = (ASN1Sequence)e.nextElement();
-
-        if (funcSeq.getObjectAt(0).equals(id_PBKDF2))
-        {
-            func = new PBKDF2Params(funcSeq);
-        }
-        else
-        {
-            func = new KeyDerivationFunc(funcSeq);
-        }
-
-        scheme = new EncryptionScheme((ASN1Sequence)e.nextElement());
-    }
-
-    public KeyDerivationFunc getKeyDerivationFunc()
-    {
-        return func;
-    }
-
-    public EncryptionScheme getEncryptionScheme()
-    {
-        return scheme;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(func);
-        v.add(scheme);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/PBKDF2Params.java b/azureus2/src/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
deleted file mode 100644
index f074a78..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-public class PBKDF2Params
-    extends KeyDerivationFunc
-{
-    DERObjectIdentifier id;
-    ASN1OctetString     octStr;
-    DERInteger          iterationCount;
-    DERInteger          keyLength;
-
-    PBKDF2Params(
-        ASN1Sequence  seq)
-    {
-        super(seq);
-
-        Enumeration e = seq.getObjects();
-
-        id = (DERObjectIdentifier)e.nextElement();
-
-        ASN1Sequence  params = (ASN1Sequence)e.nextElement();
-
-        e = params.getObjects();
-
-        octStr = (ASN1OctetString)e.nextElement();
-        iterationCount = (DERInteger)e.nextElement();
-
-        if (e.hasMoreElements())
-        {
-            keyLength = (DERInteger)e.nextElement();
-        }
-        else
-        {
-            keyLength = null;
-        }
-    }
-
-    public byte[] getSalt()
-    {
-        return octStr.getOctets();
-    }
-
-    public BigInteger getIterationCount()
-    {
-        return iterationCount.getValue();
-    }
-
-    public BigInteger getKeyLength()
-    {
-        if (keyLength != null)
-        {
-            return keyLength.getValue();
-        }
-
-        return null;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-        ASN1EncodableVector  subV = new ASN1EncodableVector();
-
-        v.add(id);
-        subV.add(octStr);
-        subV.add(iterationCount);
-
-        if (keyLength != null)
-        {
-            subV.add(keyLength);
-        }
-
-        v.add(new DERSequence(subV));
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java b/azureus2/src/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java
deleted file mode 100644
index 7c46205..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-
-public class PKCS12PBEParams
-    implements DEREncodable
-{
-    DERInteger      iterations;
-    ASN1OctetString iv;
-
-    public PKCS12PBEParams(
-        byte[]      salt,
-        int         iterations)
-    {
-        this.iv = new DEROctetString(salt);
-        this.iterations = new DERInteger(iterations);
-    }
-
-    public PKCS12PBEParams(
-        ASN1Sequence  seq)
-    {
-        iv = (ASN1OctetString)seq.getObjectAt(0);
-        iterations = (DERInteger)seq.getObjectAt(1);
-    }
-
-    public static PKCS12PBEParams getInstance(
-        Object  obj)
-    {
-        if (obj instanceof PKCS12PBEParams)
-        {
-            return (PKCS12PBEParams)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new PKCS12PBEParams((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public BigInteger getIterations()
-    {
-        return iterations.getValue();
-    }
-
-    public byte[] getIV()
-    {
-        return iv.getOctets();
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(iv);
-        v.add(iterations);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java b/azureus2/src/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
deleted file mode 100644
index 707fd46..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-public interface PKCSObjectIdentifiers
-{
-    //
-    // pkcs-1 OBJECT IDENTIFIER ::= {
-    //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
-    //
-    static final String                 pkcs_1                  = "1.2.840.113549.1.1";
-    static final DERObjectIdentifier    rsaEncryption           = new DERObjectIdentifier(pkcs_1 + ".1");
-    static final DERObjectIdentifier    md2WithRSAEncryption    = new DERObjectIdentifier(pkcs_1 + ".2");
-    static final DERObjectIdentifier    md4WithRSAEncryption    = new DERObjectIdentifier(pkcs_1 + ".3");
-    static final DERObjectIdentifier    md5WithRSAEncryption    = new DERObjectIdentifier(pkcs_1 + ".4");
-    static final DERObjectIdentifier    sha1WithRSAEncryption   = new DERObjectIdentifier(pkcs_1 + ".5");
-    static final DERObjectIdentifier    srsaOAEPEncryptionSET   = new DERObjectIdentifier(pkcs_1 + ".6");
-    static final DERObjectIdentifier    sha256WithRSAEncryption   = new DERObjectIdentifier(pkcs_1 + ".11");
-    static final DERObjectIdentifier    sha384WithRSAEncryption   = new DERObjectIdentifier(pkcs_1 + ".12");
-    static final DERObjectIdentifier    sha512WithRSAEncryption   = new DERObjectIdentifier(pkcs_1 + ".13");
-
-    //
-    // pkcs-3 OBJECT IDENTIFIER ::= {
-    //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
-    //
-    static final String                 pkcs_3                  = "1.2.840.113549.1.3";
-    static final DERObjectIdentifier    dhKeyAgreement          = new DERObjectIdentifier(pkcs_3 + ".1");
-
-    //
-    // pkcs-5 OBJECT IDENTIFIER ::= {
-    //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 }
-    //
-    static final String                 pkcs_5                  = "1.2.840.113549.1.5";
-
-    static final DERObjectIdentifier    id_PBES2                = new DERObjectIdentifier(pkcs_5 + ".13");
-
-    static final DERObjectIdentifier    id_PBKDF2               = new DERObjectIdentifier(pkcs_5 + ".12");
-
-    //
-    // encryptionAlgorithm OBJECT IDENTIFIER ::= {
-    //       iso(1) member-body(2) us(840) rsadsi(113549) 3 }
-    //
-    static final String                 encryptionAlgorithm     = "1.2.840.113549.3";
-
-    static final DERObjectIdentifier    des_EDE3_CBC            = new DERObjectIdentifier(encryptionAlgorithm + ".7");
-    static final DERObjectIdentifier    RC2_CBC                 = new DERObjectIdentifier(encryptionAlgorithm + ".2");
-
-    //
-    // object identifiers for digests
-    //
-
-    //
-    // md2 OBJECT IDENTIFIER ::=
-    //      {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 2}
-    //
-    static final DERObjectIdentifier    md2                     = new DERObjectIdentifier("1.2.840.113549.2.2");
-
-    //
-    // md5 OBJECT IDENTIFIER ::=
-    //      {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
-    //
-    static final DERObjectIdentifier    md5                     = new DERObjectIdentifier("1.2.840.113549.2.5");
-
-    //
-    // pkcs-7 OBJECT IDENTIFIER ::= {
-    //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 }
-    //
-    static final String                 pkcs_7                  = "1.2.840.113549.1.7";
-    static final DERObjectIdentifier    data                    = new DERObjectIdentifier(pkcs_7 + ".1");
-    static final DERObjectIdentifier    signedData              = new DERObjectIdentifier(pkcs_7 + ".2");
-    static final DERObjectIdentifier    envelopedData           = new DERObjectIdentifier(pkcs_7 + ".3");
-    static final DERObjectIdentifier    signedAndEnvelopedData  = new DERObjectIdentifier(pkcs_7 + ".4");
-    static final DERObjectIdentifier    digestedData            = new DERObjectIdentifier(pkcs_7 + ".5");
-    static final DERObjectIdentifier    encryptedData           = new DERObjectIdentifier(pkcs_7 + ".6");
-
-    //
-    // pkcs-9 OBJECT IDENTIFIER ::= {
-    //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
-    //
-    static final String                 pkcs_9                  = "1.2.840.113549.1.9";
-
-    static final DERObjectIdentifier    pkcs_9_at_emailAddress  = new DERObjectIdentifier(pkcs_9 + ".1");
-    static final DERObjectIdentifier    pkcs_9_at_unstructuredName = new DERObjectIdentifier(pkcs_9 + ".2");
-    static final DERObjectIdentifier    pkcs_9_at_contentType = new DERObjectIdentifier(pkcs_9 + ".3");
-    static final DERObjectIdentifier    pkcs_9_at_messageDigest = new DERObjectIdentifier(pkcs_9 + ".4");
-    static final DERObjectIdentifier    pkcs_9_at_signingTime = new DERObjectIdentifier(pkcs_9 + ".5");
-    static final DERObjectIdentifier    pkcs_9_at_counterSignature = new DERObjectIdentifier(pkcs_9 + ".6");
-    static final DERObjectIdentifier    pkcs_9_at_challengePassword = new DERObjectIdentifier(pkcs_9 + ".7");
-    static final DERObjectIdentifier    pkcs_9_at_unstructuredAddress = new DERObjectIdentifier(pkcs_9 + ".8");
-    static final DERObjectIdentifier    pkcs_9_at_extendedCertificateAttributes = new DERObjectIdentifier(pkcs_9 + ".9");
-
-    static final DERObjectIdentifier    pkcs_9_at_signingDescription = new DERObjectIdentifier(pkcs_9 + ".13");
-    static final DERObjectIdentifier    pkcs_9_at_extensionRequest = new DERObjectIdentifier(pkcs_9 + ".14");
-    static final DERObjectIdentifier    pkcs_9_at_smimeCapabilities = new DERObjectIdentifier(pkcs_9 + ".15");
-
-    static final DERObjectIdentifier    pkcs_9_at_friendlyName  = new DERObjectIdentifier(pkcs_9 + ".20");
-    static final DERObjectIdentifier    pkcs_9_at_localKeyId    = new DERObjectIdentifier(pkcs_9 + ".21");
-
-    static final DERObjectIdentifier    x509certType            = new DERObjectIdentifier(pkcs_9 + ".22.1");
-
-    static final DERObjectIdentifier    id_ct_compressedData    = new DERObjectIdentifier(pkcs_9 + ".16.1.9");
-    
-	static final DERObjectIdentifier    id_alg_PWRI_KEK    = new DERObjectIdentifier(pkcs_9 + ".16.3.9");
-
-    //
-    // SMIME capability sub oids.
-    //
-    static final DERObjectIdentifier    preferSignedData        = new DERObjectIdentifier(pkcs_9 + ".15.1");
-    static final DERObjectIdentifier    canNotDecryptAny        = new DERObjectIdentifier(pkcs_9 + ".15.2");
-    static final DERObjectIdentifier    sMIMECapabilitiesVersions = new DERObjectIdentifier(pkcs_9 + ".15.3");
-
-    //
-    // other SMIME attributes
-    //
-
-	//
-	// id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
-	// rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)}
-	//
-	static String id_aa = "1.2.840.113549.1.9.16.2";
-	
-	/*
-	 * id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11}
-	 * 
-	 */
-	static DERObjectIdentifier id_aa_encrypKeyPref = new DERObjectIdentifier(id_aa + ".11");
-
-    //
-    // pkcs-12 OBJECT IDENTIFIER ::= {
-    //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 }
-    //
-    static final String                 pkcs_12                  = "1.2.840.113549.1.12";
-    static final String                 bagtypes                 = pkcs_12 + ".10.1";
-
-    static final DERObjectIdentifier    keyBag                  = new DERObjectIdentifier(bagtypes + ".1");
-    static final DERObjectIdentifier    pkcs8ShroudedKeyBag     = new DERObjectIdentifier(bagtypes + ".2");
-    static final DERObjectIdentifier    certBag                 = new DERObjectIdentifier(bagtypes + ".3");
-    static final DERObjectIdentifier    crlBag                  = new DERObjectIdentifier(bagtypes + ".4");
-    static final DERObjectIdentifier    secretBag               = new DERObjectIdentifier(bagtypes + ".5");
-    static final DERObjectIdentifier    safeContentsBag         = new DERObjectIdentifier(bagtypes + ".6");
-}
-
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/Pfx.java b/azureus2/src/org/bouncycastle/asn1/pkcs/Pfx.java
deleted file mode 100644
index 06bff8c..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/Pfx.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-
-/**
- * the infamous Pfx from PKCS12
- */
-public class Pfx
-    implements DEREncodable, PKCSObjectIdentifiers
-{
-    private ContentInfo             contentInfo;
-    private MacData                 macData = null;
-
-    public Pfx(
-        ASN1Sequence   seq)
-    {
-        BigInteger  version = ((DERInteger)seq.getObjectAt(0)).getValue();
-        if (version.intValue() != 3)
-        {
-            throw new IllegalArgumentException("wrong version for PFX PDU");
-        }
-
-        contentInfo = ContentInfo.getInstance(seq.getObjectAt(1));
-
-        if (seq.size() == 3)
-        {
-            macData = MacData.getInstance(seq.getObjectAt(2));
-        }
-    }
-
-    public Pfx(
-        ContentInfo     contentInfo,
-        MacData         macData)
-    {
-        this.contentInfo = contentInfo;
-        this.macData = macData;
-    }
-
-    public ContentInfo getAuthSafe()
-    {
-        return contentInfo;
-    }
-
-    public MacData getMacData()
-    {
-        return macData;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(new DERInteger(3));
-        v.add(contentInfo);
-
-        if (macData != null)
-        {
-            v.add(macData);
-        }
-
-        return new BERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java b/azureus2/src/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java
deleted file mode 100644
index a00332f..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-public class PrivateKeyInfo
-    extends ASN1Encodable
-{
-    private DERObject               privKey;
-    private AlgorithmIdentifier     algId;
-    private ASN1Set                 attributes;
-
-    public static PrivateKeyInfo getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static PrivateKeyInfo getInstance(
-        Object  obj)
-    {
-        if (obj instanceof PrivateKeyInfo)
-        {
-            return (PrivateKeyInfo)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new PrivateKeyInfo((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-        
-    public PrivateKeyInfo(
-        AlgorithmIdentifier algId,
-        DERObject           privateKey)
-    {
-        this(algId, privateKey, null);
-    }
-
-    public PrivateKeyInfo(
-        AlgorithmIdentifier algId,
-        DERObject           privateKey,
-        ASN1Set             attributes)
-    {
-        this.privKey = privateKey;
-        this.algId = algId;
-        this.attributes = attributes;
-    }
-
-    public PrivateKeyInfo(
-        ASN1Sequence  seq)
-    {
-        Enumeration e = seq.getObjects();
-
-        BigInteger  version = ((DERInteger)e.nextElement()).getValue();
-        if (version.intValue() != 0)
-        {
-            throw new IllegalArgumentException("wrong version for private key info");
-        }
-
-        algId = new AlgorithmIdentifier((ASN1Sequence)e.nextElement());
-
-        try
-        {
-            ASN1InputStream         aIn = new ASN1InputStream(((ASN1OctetString)e.nextElement()).getOctets());
-
-            privKey = aIn.readObject();
-        }
-        catch (IOException ex)
-        {
-            throw new IllegalArgumentException("Error recoverying private key from sequence");
-        }
-        
-        if (e.hasMoreElements())
-        {
-           attributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
-        }
-    }
-
-    public AlgorithmIdentifier getAlgorithmId()
-    {
-        return algId;
-    }
-
-    public DERObject getPrivateKey()
-    {
-        return privKey;
-    }
-    
-    public ASN1Set getAttributes()
-    {
-        return attributes;
-    }
-
-    /**
-     * write out an RSA private key with it's asscociated information
-     * as described in PKCS8.
-     * <pre>
-     *      PrivateKeyInfo ::= SEQUENCE {
-     *                              version Version,
-     *                              privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
-     *                              privateKey PrivateKey,
-     *                              attributes [0] IMPLICIT Attributes OPTIONAL 
-     *                          }
-     *      Version ::= INTEGER {v1(0)} (v1,...)
-     *
-     *      PrivateKey ::= OCTET STRING
-     *
-     *      Attributes ::= SET OF Attribute
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(new DERInteger(0));
-        v.add(algId);
-        v.add(new DEROctetString(privKey));
-
-        if (attributes != null)
-        {
-            v.add(new DERTaggedObject(false, 0, attributes));
-        }
-        
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java b/azureus2/src/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java
deleted file mode 100644
index a76337a..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-
-public class RC2CBCParameter
-    implements DEREncodable
-{
-    DERInteger      version;
-    ASN1OctetString iv;
-
-    public static RC2CBCParameter getInstance(
-        Object  o)
-    {
-        if (o instanceof ASN1Sequence)
-        {
-            return new RC2CBCParameter((ASN1Sequence)o);
-        }
-
-        throw new IllegalArgumentException("unknown object in RC2CBCParameter factory");
-    }
-
-    public RC2CBCParameter(
-        byte[]  iv)
-    {
-        this.version = null;
-        this.iv = new DEROctetString(iv);
-    }
-
-    public RC2CBCParameter(
-        int     parameterVersion,
-        byte[]  iv)
-    {
-        this.version = new DERInteger(parameterVersion);
-        this.iv = new DEROctetString(iv);
-    }
-
-    public RC2CBCParameter(
-        ASN1Sequence  seq)
-    {
-        if (seq.size() == 1)
-        {
-            version = null;
-            iv = (ASN1OctetString)seq.getObjectAt(0);
-        }
-        else
-        {
-            version = (DERInteger)seq.getObjectAt(0);
-            iv = (ASN1OctetString)seq.getObjectAt(1);
-        }
-    }
-
-    public BigInteger getRC2ParameterVersion()
-    {
-        if (version == null)
-        {
-            return null;
-        }
-
-        return version.getValue();
-    }
-
-    public byte[] getIV()
-    {
-        return iv.getOctets();
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        if (version != null)
-        {
-            v.add(version);
-        }
-
-        v.add(iv);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java b/azureus2/src/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java
deleted file mode 100644
index 998b7c6..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class RSAPrivateKeyStructure
-    extends ASN1Encodable
-{
-    private int         version;
-    private BigInteger  modulus;
-    private BigInteger  publicExponent;
-    private BigInteger  privateExponent;
-    private BigInteger  prime1;
-    private BigInteger  prime2;
-    private BigInteger  exponent1;
-    private BigInteger  exponent2;
-    private BigInteger  coefficient;
-    private ASN1Sequence otherPrimeInfos = null;
-
-    public static RSAPrivateKeyStructure getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static RSAPrivateKeyStructure getInstance(
-        Object  obj)
-    {
-        if (obj instanceof RSAPrivateKeyStructure)
-        {
-            return (RSAPrivateKeyStructure)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new RSAPrivateKeyStructure((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-    
-    public RSAPrivateKeyStructure(
-        BigInteger  modulus,
-        BigInteger  publicExponent,
-        BigInteger  privateExponent,
-        BigInteger  prime1,
-        BigInteger  prime2,
-        BigInteger  exponent1,
-        BigInteger  exponent2,
-        BigInteger  coefficient)
-    {
-        this.version = 0;
-        this.modulus = modulus;
-        this.publicExponent = publicExponent;
-        this.privateExponent = privateExponent;
-        this.prime1 = prime1;
-        this.prime2 = prime2;
-        this.exponent1 = exponent1;
-        this.exponent2 = exponent2;
-        this.coefficient = coefficient;
-    }
-
-    public RSAPrivateKeyStructure(
-        ASN1Sequence  seq)
-    {
-        Enumeration e = seq.getObjects();
-
-        BigInteger  v = ((DERInteger)e.nextElement()).getValue();
-        if (v.intValue() != 0 && v.intValue() != 1)
-        {
-            throw new IllegalArgumentException("wrong version for RSA private key");
-        }
-
-        version = v.intValue();
-        modulus = ((DERInteger)e.nextElement()).getValue();
-        publicExponent = ((DERInteger)e.nextElement()).getValue();
-        privateExponent = ((DERInteger)e.nextElement()).getValue();
-        prime1 = ((DERInteger)e.nextElement()).getValue();
-        prime2 = ((DERInteger)e.nextElement()).getValue();
-        exponent1 = ((DERInteger)e.nextElement()).getValue();
-        exponent2 = ((DERInteger)e.nextElement()).getValue();
-        coefficient = ((DERInteger)e.nextElement()).getValue();
-        
-        if (e.hasMoreElements())
-        {
-            otherPrimeInfos = (ASN1Sequence)e.nextElement();
-        }
-    }
-
-    public int getVersion()
-    {
-        return version;
-    }
-    
-    public BigInteger getModulus()
-    {
-        return modulus;
-    }
-
-    public BigInteger getPublicExponent()
-    {
-        return publicExponent;
-    }
-
-    public BigInteger getPrivateExponent()
-    {
-        return privateExponent;
-    }
-
-    public BigInteger getPrime1()
-    {
-        return prime1;
-    }
-
-    public BigInteger getPrime2()
-    {
-        return prime2;
-    }
-
-    public BigInteger getExponent1()
-    {
-        return exponent1;
-    }
-
-    public BigInteger getExponent2()
-    {
-        return exponent2;
-    }
-
-    public BigInteger getCoefficient()
-    {
-        return coefficient;
-    }
-
-    /**
-     * This outputs the key in PKCS1v2 format.
-     * <pre>
-     *      RSAPrivateKey ::= SEQUENCE {
-     *                          version Version,
-     *                          modulus INTEGER, -- n
-     *                          publicExponent INTEGER, -- e
-     *                          privateExponent INTEGER, -- d
-     *                          prime1 INTEGER, -- p
-     *                          prime2 INTEGER, -- q
-     *                          exponent1 INTEGER, -- d mod (p-1)
-     *                          exponent2 INTEGER, -- d mod (q-1)
-     *                          coefficient INTEGER, -- (inverse of q) mod p
-     *                          otherPrimeInfos OtherPrimeInfos OPTIONAL
-     *                      }
-     *
-     *      Version ::= INTEGER { two-prime(0), multi(1) }
-     *        (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
-     * </pre>
-     * <p>
-     * This routine is written to output PKCS1 version 2.1, private keys.
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(new DERInteger(version));                       // version
-        v.add(new DERInteger(getModulus()));
-        v.add(new DERInteger(getPublicExponent()));
-        v.add(new DERInteger(getPrivateExponent()));
-        v.add(new DERInteger(getPrime1()));
-        v.add(new DERInteger(getPrime2()));
-        v.add(new DERInteger(getExponent1()));
-        v.add(new DERInteger(getExponent2()));
-        v.add(new DERInteger(getCoefficient()));
-
-        if (otherPrimeInfos != null)
-        {
-            v.add(otherPrimeInfos);
-        }
-        
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/SafeBag.java b/azureus2/src/org/bouncycastle/asn1/pkcs/SafeBag.java
deleted file mode 100644
index ebf15fb..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/SafeBag.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class SafeBag
-    implements DEREncodable
-{
-    DERObjectIdentifier         bagId;
-    DERObject                   bagValue;
-    ASN1Set                     bagAttributes;
-
-    public SafeBag(
-        DERObjectIdentifier     oid,
-        DERObject               obj)
-    {
-        this.bagId = oid;
-        this.bagValue = obj;
-        this.bagAttributes = null;
-    }
-
-    public SafeBag(
-        DERObjectIdentifier     oid,
-        DERObject               obj,
-        ASN1Set                 bagAttributes)
-    {
-        this.bagId = oid;
-        this.bagValue = obj;
-        this.bagAttributes = bagAttributes;
-    }
-
-	public SafeBag(
-		ASN1Sequence	seq)
-	{
-		this.bagId = (DERObjectIdentifier)seq.getObjectAt(0);
-		this.bagValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject();
-        if (seq.size() == 3)
-        {
-            this.bagAttributes = (ASN1Set)seq.getObjectAt(2);
-        }
-	}
-
-	public DERObjectIdentifier getBagId()
-	{
-		return bagId;
-	}
-
-    public DERObject getBagValue()
-    {
-		return bagValue;
-    }
-
-    public ASN1Set getBagAttributes()
-    {
-		return bagAttributes;
-    }
-
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(bagId);
-        v.add(new DERTaggedObject(0, bagValue));
-
-        if (bagAttributes != null)
-        {
-            v.add(bagAttributes);
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/SignedData.java b/azureus2/src/org/bouncycastle/asn1/pkcs/SignedData.java
deleted file mode 100644
index e3b51b0..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/SignedData.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.BERSequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * a PKCS#7 signed data object.
- */
-public class SignedData
-    implements DEREncodable, PKCSObjectIdentifiers
-{
-    private DERInteger              version;
-    private ASN1Set                 digestAlgorithms;
-    private ContentInfo             contentInfo;
-    private ASN1Set                 certificates;
-    private ASN1Set                 crls;
-    private ASN1Set                 signerInfos;
-
-    public static SignedData getInstance(
-        Object  o)
-    {
-        if (o instanceof SignedData)
-        {
-            return (SignedData)o;
-        }
-        else if (o instanceof ASN1Sequence)
-        {
-            return new SignedData((ASN1Sequence)o);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory: " + o);
-    }
-
-	public SignedData(
-		DERInteger        _version,
-		ASN1Set           _digestAlgorithms,
-		ContentInfo       _contentInfo,
-		ASN1Set           _certificates,
-		ASN1Set           _crls,
-		ASN1Set           _signerInfos)
-	{
-		version          = _version;
-		digestAlgorithms = _digestAlgorithms;
-		contentInfo      = _contentInfo;
-		certificates     = _certificates;
-		crls             = _crls;
-		signerInfos      = _signerInfos;
-	}
-	
-    public SignedData(
-        ASN1Sequence seq)
-    {
-        Enumeration     e = seq.getObjects();
-
-        version = (DERInteger)e.nextElement();
-        digestAlgorithms = ((ASN1Set)e.nextElement());
-        contentInfo = ContentInfo.getInstance(e.nextElement());
-
-        while (e.hasMoreElements())
-        {
-            DERObject o = (DERObject)e.nextElement();
-
-            //
-            // an interesting feature of SignedData is that there appear to be varying implementations...
-            // for the moment we ignore anything which doesn't fit.
-            //
-            if (o instanceof DERTaggedObject)
-            {
-                DERTaggedObject tagged = (DERTaggedObject)o;
-
-                switch (tagged.getTagNo())
-                {
-                case 0:
-                    certificates = ASN1Set.getInstance(tagged, false);
-                    break;
-                case 1:
-                    crls = ASN1Set.getInstance(tagged, false);
-                    break;
-                default:
-                    throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo());
-                }
-            }
-            else
-            {
-                signerInfos = (ASN1Set)o;
-            }
-        }
-    }
-
-    public DERInteger getVersion()
-    {
-        return version;
-    }
-
-    public ASN1Set getDigestAlgorithms()
-    {
-        return digestAlgorithms;
-    }
-
-    public ContentInfo getContentInfo()
-    {
-        return contentInfo;
-    }
-
-    public ASN1Set getCertificates()
-    {
-        return certificates;
-    }
-
-    public ASN1Set getCRLs()
-    {
-        return crls;
-    }
-
-    public ASN1Set getSignerInfos()
-    {
-        return signerInfos;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  SignedData ::= SEQUENCE {
-     *      version Version,
-     *      digestAlgorithms DigestAlgorithmIdentifiers,
-     *      contentInfo ContentInfo,
-     *      certificates
-     *          [0] IMPLICIT ExtendedCertificatesAndCertificates
-     *                   OPTIONAL,
-     *      crls
-     *          [1] IMPLICIT CertificateRevocationLists OPTIONAL,
-     *      signerInfos SignerInfos }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(version);
-        v.add(digestAlgorithms);
-        v.add(contentInfo);
-
-        if (certificates != null)
-        {
-            v.add(new DERTaggedObject(false, 0, certificates));
-        }
-
-        if (crls != null)
-        {
-            v.add(new DERTaggedObject(false, 1, crls));
-        }
-
-        v.add(signerInfos);
-
-        return new BERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/SignerInfo.java b/azureus2/src/org/bouncycastle/asn1/pkcs/SignerInfo.java
deleted file mode 100644
index ee9b3c4..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/SignerInfo.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package org.bouncycastle.asn1.pkcs;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.*;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-
-/**
- * a PKCS#7 signer info object.
- */
-public class SignerInfo
-    implements DEREncodable
-{
-    private DERInteger              version;
-    private IssuerAndSerialNumber   issuerAndSerialNumber;
-    private AlgorithmIdentifier     digAlgorithm;
-    private ASN1Set                 authenticatedAttributes;
-    private AlgorithmIdentifier     digEncryptionAlgorithm;
-    private ASN1OctetString         encryptedDigest;
-    private ASN1Set                 unauthenticatedAttributes;
-
-    public static SignerInfo getInstance(
-        Object  o)
-    {
-        if (o instanceof SignerInfo)
-        {
-            return (SignerInfo)o;
-        }
-        else if (o instanceof ASN1Sequence)
-        {
-            return new SignerInfo((ASN1Sequence)o);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public SignerInfo(
-        DERInteger              version,
-        IssuerAndSerialNumber   issuerAndSerialNumber,
-        AlgorithmIdentifier     digAlgorithm,
-        ASN1Set                 authenticatedAttributes,
-        AlgorithmIdentifier     digEncryptionAlgorithm,
-        ASN1OctetString         encryptedDigest,
-        ASN1Set                 unauthenticatedAttributes)
-    {
-        this.version = version;
-        this.issuerAndSerialNumber = issuerAndSerialNumber;
-        this.digAlgorithm = digAlgorithm;
-        this.authenticatedAttributes = authenticatedAttributes;
-        this.digEncryptionAlgorithm = digEncryptionAlgorithm;
-        this.encryptedDigest = encryptedDigest;
-        this.unauthenticatedAttributes = unauthenticatedAttributes;
-    }
-
-    public SignerInfo(
-        ASN1Sequence seq)
-    {
-        Enumeration     e = seq.getObjects();
-
-        version = (DERInteger)e.nextElement();
-        issuerAndSerialNumber = IssuerAndSerialNumber.getInstance(e.nextElement());
-        digAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
-
-        Object obj = e.nextElement();
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            authenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)obj, false);
-
-            digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
-        }
-        else
-        {
-            authenticatedAttributes = null;
-            digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(obj);
-        }
-
-        encryptedDigest = DEROctetString.getInstance(e.nextElement());
-
-        if (e.hasMoreElements())
-        {
-            unauthenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
-        }
-        else
-        {
-            unauthenticatedAttributes = null;
-        }
-    }
-
-    public DERInteger getVersion()
-    {
-        return version;
-    }
-
-    public IssuerAndSerialNumber getIssuerAndSerialNumber()
-    {
-        return issuerAndSerialNumber;
-    }
-
-    public ASN1Set getAuthenticatedAttributes()
-    {
-        return authenticatedAttributes;
-    }
-
-    public AlgorithmIdentifier getDigestAlgorithm()
-    {
-        return digAlgorithm;
-    }
-
-    public ASN1OctetString getEncryptedDigest()
-    {
-        return encryptedDigest;
-    }
-
-    public AlgorithmIdentifier getDigestEncryptionAlgorithm()
-    {
-        return digEncryptionAlgorithm;
-    }
-
-    public ASN1Set getUnauthenticatedAttributes()
-    {
-        return unauthenticatedAttributes;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  SignerInfo ::= SEQUENCE {
-     *      version Version,
-     *      issuerAndSerialNumber IssuerAndSerialNumber,
-     *      digestAlgorithm DigestAlgorithmIdentifier,
-     *      authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
-     *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
-     *      encryptedDigest EncryptedDigest,
-     *      unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
-     *  }
-     *
-     *  EncryptedDigest ::= OCTET STRING
-     *
-     *  DigestAlgorithmIdentifier ::= AlgorithmIdentifier
-     *
-     *  DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(version);
-        v.add(issuerAndSerialNumber);
-        v.add(digAlgorithm);
-
-        if (authenticatedAttributes != null)
-        {
-            v.add(new DERTaggedObject(false, 0, authenticatedAttributes));
-        }
-
-        v.add(digEncryptionAlgorithm);
-        v.add(encryptedDigest);
-
-        if (unauthenticatedAttributes != null)
-        {
-            v.add(new DERTaggedObject(false, 1, unauthenticatedAttributes));
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/pkcs/package.html b/azureus2/src/org/bouncycastle/asn1/pkcs/package.html
deleted file mode 100644
index ab800f4..0000000
--- a/azureus2/src/org/bouncycastle/asn1/pkcs/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting the various RSA PKCS documents.
-</body>
-</html>
diff --git a/azureus2/src/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java b/azureus2/src/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java
deleted file mode 100644
index 67f19f9..0000000
--- a/azureus2/src/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.bouncycastle.asn1.sec;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-/**
- * the elliptic curve private key object from SEC 1
- */
-public class ECPrivateKeyStructure
-    extends ASN1Encodable
-{
-    private ASN1Sequence  seq;
-
-    public ECPrivateKeyStructure(
-        ASN1Sequence  seq)
-    {
-        this.seq = seq;
-    }
-
-    public ECPrivateKeyStructure(
-        BigInteger  key)
-    {
-        byte[]  bytes = key.toByteArray();
-
-        if (bytes[0] == 0)
-        {
-            byte[]  tmp = new byte[bytes.length - 1];
-
-            System.arraycopy(bytes, 1, tmp, 0, tmp.length);
-            bytes = tmp;
-        }
-
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(new DERInteger(1));
-        v.add(new DEROctetString(bytes));
-
-        seq = new DERSequence(v);
-    }
-
-    public BigInteger getKey()
-    {
-        ASN1OctetString  octs = (ASN1OctetString)seq.getObjectAt(1);
-
-        return new BigInteger(1, octs.getOctets());
-    }
-
-    public DERBitString getPublicKey()
-    {
-        return (DERBitString)getObjectInTag(1);
-    }
-
-    public ASN1Object getParameters()
-    {
-        return getObjectInTag(0);
-    }
-
-    private ASN1Object getObjectInTag(int tagNo)
-    {
-        Enumeration e = seq.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            DEREncodable obj = (DEREncodable)e.nextElement();
-
-            if (obj instanceof ASN1TaggedObject)
-            {
-                ASN1TaggedObject tag = (ASN1TaggedObject)obj;
-                if (tag.getTagNo() == tagNo)
-                {
-                    return (ASN1Object)((DEREncodable)tag.getObject()).getDERObject();
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * ECPrivateKey ::= SEQUENCE {
-     *     version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
-     *     privateKey OCTET STRING,
-     *     parameters [0] Parameters OPTIONAL,
-     *     publicKey [1] BIT STRING OPTIONAL }
-     */
-    public DERObject toASN1Object()
-    {
-        return seq;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/sec/package.html b/azureus2/src/org/bouncycastle/asn1/sec/package.html
deleted file mode 100644
index 5e34dec..0000000
--- a/azureus2/src/org/bouncycastle/asn1/sec/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for support of the SEC standard for Elliptic Curve.
-</body>
-</html>
diff --git a/azureus2/src/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java b/azureus2/src/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
deleted file mode 100644
index aeb4a31..0000000
--- a/azureus2/src/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.asn1.teletrust;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-public interface TeleTrusTObjectIdentifiers
-{
-    static final String teleTrusTAlgorithm = "1.3.36.3";
-
-    static final DERObjectIdentifier    ripemd160           = new DERObjectIdentifier(teleTrusTAlgorithm + ".2.1");
-    static final DERObjectIdentifier    ripemd128           = new DERObjectIdentifier(teleTrusTAlgorithm + ".2.2");
-    static final DERObjectIdentifier    ripemd256           = new DERObjectIdentifier(teleTrusTAlgorithm + ".2.3");
-
-	static final String teleTrusTRSAsignatureAlgorithm = teleTrusTAlgorithm + ".3.1";
-	
-    static final DERObjectIdentifier    rsaSignatureWithripemd160           = new DERObjectIdentifier(teleTrusTRSAsignatureAlgorithm + ".2");
-    static final DERObjectIdentifier    rsaSignatureWithripemd128           = new DERObjectIdentifier(teleTrusTRSAsignatureAlgorithm + ".3");
-    static final DERObjectIdentifier    rsaSignatureWithripemd256           = new DERObjectIdentifier(teleTrusTRSAsignatureAlgorithm + ".4");
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/util/ASN1Dump.java b/azureus2/src/org/bouncycastle/asn1/util/ASN1Dump.java
deleted file mode 100644
index 17e5419..0000000
--- a/azureus2/src/org/bouncycastle/asn1/util/ASN1Dump.java
+++ /dev/null
@@ -1,274 +0,0 @@
-package org.bouncycastle.asn1.util;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.*;
-import org.bouncycastle.util.encoders.Hex;
-
-public class ASN1Dump
-{
-    private static String  TAB = "    ";
-
-    /**
-     * dump a DER object as a formatted string with indentation
-     *
-     * @param obj the DERObject to be dumped out.
-     */
-    public static String _dumpAsString(
-        String      indent,
-        DERObject   obj)
-    {
-        if (obj instanceof ASN1Sequence)
-        {
-            StringBuffer    buf = new StringBuffer();
-            Enumeration     e = ((ASN1Sequence)obj).getObjects();
-            String          tab = indent + TAB;
-
-            buf.append(indent);
-			if (obj instanceof BERConstructedSequence)
-			{
-	            buf.append("BER ConstructedSequence");
-			}
-            else if (obj instanceof DERConstructedSequence)
-			{
-	            buf.append("DER ConstructedSequence");
-			}
-            else if (obj instanceof DERSequence)
-            {
-	            buf.append("DER Sequence");
-            }
-            else if (obj instanceof BERSequence)
-            {
-	            buf.append("BER Sequence");
-            }
-			else
-			{
-	            buf.append("Sequence");
-			}
-
-            buf.append(System.getProperty("line.separator"));
-
-            while (e.hasMoreElements())
-            {
-                Object  o = e.nextElement();
-
-                if (o == null || o.equals(new DERNull()))
-                {
-                    buf.append(tab);
-                    buf.append("NULL");
-                    buf.append(System.getProperty("line.separator"));
-                }
-                else if (o instanceof DERObject)
-                {
-                    buf.append(_dumpAsString(tab, (DERObject)o));
-                }
-                else
-                {
-                    buf.append(_dumpAsString(tab, ((DEREncodable)o).getDERObject()));
-                }
-            }
-            return buf.toString();
-        }
-        else if (obj instanceof DERTaggedObject)
-        {
-            StringBuffer    buf = new StringBuffer();
-            String          tab = indent + TAB;
-
-            buf.append(indent);
-			if (obj instanceof BERTaggedObject)
-			{
-            	buf.append("BER Tagged [");
-			}
-			else
-			{
-            	buf.append("Tagged [");
-			}
-
-            DERTaggedObject o = (DERTaggedObject)obj;
-
-            buf.append(Integer.toString(o.getTagNo()));
-            buf.append("]");
-
-            if (!o.isExplicit())
-            {
-                buf.append(" IMPLICIT ");
-            }
-
-            buf.append(System.getProperty("line.separator"));
-
-            if (o.isEmpty())
-            {
-                buf.append(tab);
-                buf.append("EMPTY");
-                buf.append(System.getProperty("line.separator"));
-            }
-            else
-            {
-                buf.append(_dumpAsString(tab, o.getObject()));
-            }
-
-            return buf.toString();
-        }
-        else if (obj instanceof DERConstructedSet)
-        {
-            StringBuffer    buf = new StringBuffer();
-            Enumeration     e = ((ASN1Set)obj).getObjects();
-            String          tab = indent + TAB;
-
-            buf.append(indent);
-            buf.append("ConstructedSet");
-            buf.append(System.getProperty("line.separator"));
-
-            while (e.hasMoreElements())
-            {
-                Object  o = e.nextElement();
-
-                if (o == null)
-                {
-                    buf.append(tab);
-                    buf.append("NULL");
-                    buf.append(System.getProperty("line.separator"));
-                }
-                else if (o instanceof DERObject)
-                {
-                    buf.append(_dumpAsString(tab, (DERObject)o));
-                }
-                else
-                {
-                    buf.append(_dumpAsString(tab, ((DEREncodable)o).getDERObject()));
-                }
-            }
-            return buf.toString();
-        }
-        else if (obj instanceof BERSet)
-        {
-            StringBuffer    buf = new StringBuffer();
-            Enumeration     e = ((ASN1Set)obj).getObjects();
-            String          tab = indent + TAB;
-
-            buf.append(indent);
-            buf.append("BER Set");
-            buf.append(System.getProperty("line.separator"));
-
-            while (e.hasMoreElements())
-            {
-                Object  o = e.nextElement();
-
-                if (o == null)
-                {
-                    buf.append(tab);
-                    buf.append("NULL");
-                    buf.append(System.getProperty("line.separator"));
-                }
-                else if (o instanceof DERObject)
-                {
-                    buf.append(_dumpAsString(tab, (DERObject)o));
-                }
-                else
-                {
-                    buf.append(_dumpAsString(tab, ((DEREncodable)o).getDERObject()));
-                }
-            }
-            return buf.toString();
-        }
-        else if (obj instanceof DERSet)
-        {
-            StringBuffer    buf = new StringBuffer();
-            Enumeration     e = ((ASN1Set)obj).getObjects();
-            String          tab = indent + TAB;
-
-            buf.append(indent);
-            buf.append("DER Set");
-            buf.append(System.getProperty("line.separator"));
-
-            while (e.hasMoreElements())
-            {
-                Object  o = e.nextElement();
-
-                if (o == null)
-                {
-                    buf.append(tab);
-                    buf.append("NULL");
-                    buf.append(System.getProperty("line.separator"));
-                }
-                else if (o instanceof DERObject)
-                {
-                    buf.append(_dumpAsString(tab, (DERObject)o));
-                }
-                else
-                {
-                    buf.append(_dumpAsString(tab, ((DEREncodable)o).getDERObject()));
-                }
-            }
-            return buf.toString();
-        }
-        else if (obj instanceof DERObjectIdentifier)
-        {
-            return indent + "ObjectIdentifier(" + ((DERObjectIdentifier)obj).getId() + ")" + System.getProperty("line.separator");
-        }
-        else if (obj instanceof DERBoolean)
-        {
-            return indent + "Boolean(" + ((DERBoolean)obj).isTrue() + ")" + System.getProperty("line.separator");
-        }
-        else if (obj instanceof DERInteger)
-        {
-            return indent + "Integer(" + ((DERInteger)obj).getValue() + ")" + System.getProperty("line.separator");
-        }
-        else if (obj instanceof DEROctetString)
-        {
-            return indent + obj.toString() + "[" + ((ASN1OctetString)obj).getOctets().length + "] " + System.getProperty("line.separator");
-        }
-        else if (obj instanceof DERIA5String)
-        {
-            return indent + "IA5String(" + ((DERIA5String)obj).getString() + ") " + System.getProperty("line.separator");
-        }
-        else if (obj instanceof DERPrintableString)
-        {
-            return indent + "PrintableString(" + ((DERPrintableString)obj).getString() + ") " + System.getProperty("line.separator");
-        }
-        else if (obj instanceof DERVisibleString)
-        {
-            return indent + "VisibleString(" + ((DERVisibleString)obj).getString() + ") " + System.getProperty("line.separator");
-        }
-        else if (obj instanceof DERBMPString)
-        {
-            return indent + "BMPString(" + ((DERBMPString)obj).getString() + ") " + System.getProperty("line.separator");
-        }
-        else if (obj instanceof DERT61String)
-        {
-            return indent + "T61String(" + ((DERT61String)obj).getString() + ") " + System.getProperty("line.separator");
-        }
-        else if (obj instanceof DERUTCTime)
-        {
-            return indent + "UTCTime(" + ((DERUTCTime)obj).getTime() + ") " + System.getProperty("line.separator");
-        }
-        else if (obj instanceof DERUnknownTag)
-        {
-            return indent + "Unknown " + Integer.toString(((DERUnknownTag)obj).getTag(), 16) + " " + new String(Hex.encode(((DERUnknownTag)obj).getData())) + System.getProperty("line.separator");
-        }
-        else
-        {
-            return indent + obj.toString() + System.getProperty("line.separator");
-        }
-    }
-
-    /**
-     * dump out a DER object as a formatted string
-     *
-     * @param obj the DERObject to be dumped out.
-     */
-    public static String dumpAsString(
-        Object   obj)
-    {
-		if (obj instanceof DERObject)
-		{
-        	return _dumpAsString("", (DERObject)obj);
-		}
-		else if (obj instanceof DEREncodable)
-		{
-        	return _dumpAsString("", ((DEREncodable)obj).getDERObject());
-		}
-
-		return "unknown object type " + obj.toString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/util/DERDump.java b/azureus2/src/org/bouncycastle/asn1/util/DERDump.java
deleted file mode 100644
index e9d307a..0000000
--- a/azureus2/src/org/bouncycastle/asn1/util/DERDump.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.bouncycastle.asn1.util;
-
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-
-/**
- * @deprecated use ASN1Dump.
- */
-public class DERDump
-    extends ASN1Dump
-{
-    /**
-     * dump out a DER object as a formatted string
-     *
-     * @param obj the DERObject to be dumped out.
-     */
-    public static String dumpAsString(
-        DERObject   obj)
-    {
-        return _dumpAsString("", obj);
-    }
-
-    /**
-     * dump out a DER object as a formatted string
-     *
-     * @param obj the DERObject to be dumped out.
-     */
-    public static String dumpAsString(
-        DEREncodable   obj)
-    {
-        return _dumpAsString("", obj.getDERObject());
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/util/Dump.java b/azureus2/src/org/bouncycastle/asn1/util/Dump.java
deleted file mode 100644
index 27a37f3..0000000
--- a/azureus2/src/org/bouncycastle/asn1/util/Dump.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.asn1.util;
-
-import java.io.FileInputStream;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-
-public class Dump
-{
-    public static void main(
-        String args[])
-        throws Exception
-    {
-        FileInputStream fIn = new FileInputStream(args[0]);
-        ASN1InputStream bIn = new ASN1InputStream(fIn);
-        Object          obj = null;
-
-        while ((obj = bIn.readObject()) != null)
-        {
-            System.out.println(ASN1Dump.dumpAsString(obj));
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/util/package.html b/azureus2/src/org/bouncycastle/asn1/util/package.html
deleted file mode 100644
index 1db893d..0000000
--- a/azureus2/src/org/bouncycastle/asn1/util/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-An ASN.1 dump utility.
-</body>
-</html>
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/AccessDescription.java b/azureus2/src/org/bouncycastle/asn1/x509/AccessDescription.java
deleted file mode 100644
index ae13f55..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/AccessDescription.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * The AccessDescription object.
- * <pre>
- * AccessDescription  ::=  SEQUENCE {
- *       accessMethod          OBJECT IDENTIFIER,
- *       accessLocation        GeneralName  }
- * </pre>
- */
-public class AccessDescription
-    extends ASN1Encodable
-{
-    public final static DERObjectIdentifier id_ad_caIssuers = new DERObjectIdentifier("1.3.6.1.5.5.7.48.2");
-    
-    public final static DERObjectIdentifier id_ad_ocsp = new DERObjectIdentifier("1.3.6.1.5.5.7.48.1");
-        
-    DERObjectIdentifier accessMethod = null;
-    GeneralName accessLocation = null;
-
-    public static AccessDescription getInstance(
-        Object  obj)
-    {
-        if (obj instanceof AccessDescription)
-        {
-            return (AccessDescription)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new AccessDescription((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
- 
-    public AccessDescription(
-        ASN1Sequence   seq)
-    {
-        if (seq.size() != 2) 
-        {
-            throw new IllegalArgumentException("wrong number of elements in inner sequence");
-        }
-        
-        accessMethod = DERObjectIdentifier.getInstance(seq.getObjectAt(0));
-        accessLocation = GeneralName.getInstance(seq.getObjectAt(1));
-    }
-
-    /**
-     * create an AccessDescription with the oid and location provided.
-     */
-    public AccessDescription(
-        DERObjectIdentifier oid,
-        GeneralName location)
-    {
-        accessMethod = oid;
-        accessLocation = location;
-    }
-
-    /**
-     * 
-     * @return the access method.
-     */
-    public DERObjectIdentifier getAccessMethod()
-    {
-        return accessMethod;
-    }
-    
-    /**
-     * 
-     * @return the access location
-     */
-    public GeneralName getAccessLocation()
-    {
-        return accessLocation;
-    }
-    
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector accessDescription  = new ASN1EncodableVector();
-        
-        accessDescription.add(accessMethod);
-        accessDescription.add(accessLocation);
-
-        return new DERSequence(accessDescription);
-    }
-
-    public String toString()
-    {
-        return ("AccessDescription: Oid(" + this.accessMethod.getId() + ")");
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java b/azureus2/src/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java
deleted file mode 100644
index 501dc9c..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-public class AlgorithmIdentifier
-    extends ASN1Encodable
-{
-    private DERObjectIdentifier objectId;
-    private DEREncodable        parameters;
-    private boolean             parametersDefined = false;
-
-    public static AlgorithmIdentifier getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-    
-    public static AlgorithmIdentifier getInstance(
-        Object  obj)
-    {
-        if (obj== null || obj instanceof AlgorithmIdentifier)
-        {
-            return (AlgorithmIdentifier)obj;
-        }
-        
-        if (obj instanceof DERObjectIdentifier)
-        {
-            return new AlgorithmIdentifier((DERObjectIdentifier)obj);
-        }
-
-        if (obj instanceof String)
-        {
-            return new AlgorithmIdentifier((String)obj);
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            return new AlgorithmIdentifier((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public AlgorithmIdentifier(
-        DERObjectIdentifier     objectId)
-    {
-        this.objectId = objectId;
-    }
-
-    public AlgorithmIdentifier(
-        String     objectId)
-    {
-        this.objectId = new DERObjectIdentifier(objectId);
-    }
-
-    public AlgorithmIdentifier(
-        DERObjectIdentifier     objectId,
-        DEREncodable            parameters)
-    {
-        parametersDefined = true;
-        this.objectId = objectId;
-        this.parameters = parameters;
-    }
-
-    public AlgorithmIdentifier(
-        ASN1Sequence   seq)
-    {
-        if (seq.size() < 1 || seq.size() > 2)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                    + seq.size());
-        }
-        
-        objectId = DERObjectIdentifier.getInstance(seq.getObjectAt(0));
-
-        if (seq.size() == 2)
-        {
-            parametersDefined = true;
-            parameters = seq.getObjectAt(1);
-        }
-        else
-        {
-            parameters = null;
-        }
-    }
-
-    public DERObjectIdentifier getObjectId()
-    {
-        return objectId;
-    }
-
-    public DEREncodable getParameters()
-    {
-        return parameters;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *      AlgorithmIdentifier ::= SEQUENCE {
-     *                            algorithm OBJECT IDENTIFIER,
-     *                            parameters ANY DEFINED BY algorithm OPTIONAL }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(objectId);
-
-        if (parametersDefined)
-        {
-            v.add(parameters);
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/AttCertIssuer.java b/azureus2/src/org/bouncycastle/asn1/x509/AttCertIssuer.java
deleted file mode 100644
index 010a6ff..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/AttCertIssuer.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class AttCertIssuer
-    extends ASN1Encodable
-    implements ASN1Choice
-{
-    ASN1Encodable   obj;
-    DERObject       choiceObj;
-    
-    public static AttCertIssuer getInstance(
-        Object  obj)
-    {
-        if (obj instanceof AttCertIssuer)
-        {
-            return (AttCertIssuer)obj;
-        }
-        else if (obj instanceof V2Form)
-        {
-            return new AttCertIssuer(V2Form.getInstance(obj));
-        }
-        else if (obj instanceof GeneralNames)
-        {
-            return new AttCertIssuer((GeneralNames)obj);
-        }
-        else if (obj instanceof ASN1TaggedObject)
-        {
-            return new AttCertIssuer(V2Form.getInstance((ASN1TaggedObject)obj, false));
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new AttCertIssuer(GeneralNames.getInstance(obj));
-        }
-
-        throw new IllegalArgumentException("unknown object in factory: " + obj.getClass());
-    }
-    
-    public static AttCertIssuer getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject()); // must be explictly tagged
-    }
-
-    /**
-     * Don't use this one if you are trying to be RFC 3281 compliant.
-     * Use it for v1 attribute certificates only.
-     * 
-     * @param names our GeneralNames structure
-     */
-    public AttCertIssuer(
-        GeneralNames  names)
-    {
-        obj = names;
-        choiceObj = obj.getDERObject();
-    }
-    
-    public AttCertIssuer(
-        V2Form  v2Form)
-    {
-        obj = v2Form;
-        choiceObj = new DERTaggedObject(false, 0, obj);
-    }
-
-    public ASN1Encodable getIssuer()
-    {
-        return obj;
-    }
-    
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  AttCertIssuer ::= CHOICE {
-     *       v1Form   GeneralNames,  -- MUST NOT be used in this
-     *                               -- profile
-     *       v2Form   [0] V2Form     -- v2 only
-     *  }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        return choiceObj;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java b/azureus2/src/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java
deleted file mode 100644
index de4e684..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class AttCertValidityPeriod
-    extends ASN1Encodable
-{
-    DERGeneralizedTime  notBeforeTime;
-    DERGeneralizedTime  notAfterTime;
-
-    public static AttCertValidityPeriod getInstance(
-            Object  obj)
-    {
-        if (obj instanceof AttCertValidityPeriod)
-        {
-            return (AttCertValidityPeriod)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new AttCertValidityPeriod((ASN1Sequence)obj);
-        }
-        
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-    
-    public AttCertValidityPeriod(
-        ASN1Sequence    seq)
-    {
-        if (seq.size() != 2)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                    + seq.size());
-        }
-
-        notBeforeTime = DERGeneralizedTime.getInstance(seq.getObjectAt(0));
-        notAfterTime = DERGeneralizedTime.getInstance(seq.getObjectAt(1));
-    }
-
-    /**
-     * @param notBeforeTime
-     * @param notAfterTime
-     */
-    public AttCertValidityPeriod(
-        DERGeneralizedTime notBeforeTime,
-        DERGeneralizedTime notAfterTime)
-    {
-        this.notBeforeTime = notBeforeTime;
-        this.notAfterTime = notAfterTime;
-    }
-
-    public DERGeneralizedTime getNotBeforeTime()
-    {
-        return notBeforeTime;
-    }
-
-    public DERGeneralizedTime getNotAfterTime()
-    {
-        return notAfterTime;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  AttCertValidityPeriod  ::= SEQUENCE {
-     *       notBeforeTime  GeneralizedTime,
-     *       notAfterTime   GeneralizedTime
-     *  } 
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(notBeforeTime);
-        v.add(notAfterTime);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/Attribute.java b/azureus2/src/org/bouncycastle/asn1/x509/Attribute.java
deleted file mode 100644
index c8cbcf7..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/Attribute.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-public class Attribute
-    extends ASN1Encodable
-{
-    private DERObjectIdentifier attrType;
-    private ASN1Set             attrValues;
-
-    /**
-     * return an Attribute object from the given object.
-     *
-     * @param o the object we want converted.
-     * @exception IllegalArgumentException if the object cannot be converted.
-     */
-    public static Attribute getInstance(
-        Object o)
-    {
-        if (o == null || o instanceof Attribute)
-        {
-            return (Attribute)o;
-        }
-        
-        if (o instanceof ASN1Sequence)
-        {
-            return new Attribute((ASN1Sequence)o);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-    
-    public Attribute(
-        ASN1Sequence seq)
-    {
-        if (seq.size() != 2)
-        {
-            throw new IllegalArgumentException("Bad sequence size: " + seq.size());
-        }
-
-        attrType = DERObjectIdentifier.getInstance(seq.getObjectAt(0));
-        attrValues = ASN1Set.getInstance(seq.getObjectAt(1));
-    }
-
-    public Attribute(
-        DERObjectIdentifier attrType,
-        ASN1Set             attrValues)
-    {
-        this.attrType = attrType;
-        this.attrValues = attrValues;
-    }
-
-    public DERObjectIdentifier getAttrType()
-    {
-        return attrType;
-    }
-    
-    public ASN1Set getAttrValues()
-    {
-        return attrValues;
-    }
-
-    /** 
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * Attribute ::= SEQUENCE {
-     *     attrType OBJECT IDENTIFIER,
-     *     attrValues SET OF AttributeValue
-     * }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(attrType);
-        v.add(attrValues);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/AttributeCertificate.java b/azureus2/src/org/bouncycastle/asn1/x509/AttributeCertificate.java
deleted file mode 100644
index 6dcb7c6..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/AttributeCertificate.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class AttributeCertificate
-    extends ASN1Encodable
-{
-    AttributeCertificateInfo    acinfo;
-    AlgorithmIdentifier         signatureAlgorithm;
-    DERBitString                signatureValue;
-
-    /**
-     * @param obj
-     * @return an AttributeCertificate object
-     */
-    public static AttributeCertificate getInstance(Object obj)
-    {
-        if (obj instanceof AttributeCertificate)
-        {
-            return (AttributeCertificate)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new AttributeCertificate((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-    
-    public AttributeCertificate(
-        AttributeCertificateInfo    acinfo,
-        AlgorithmIdentifier         signatureAlgorithm,
-        DERBitString                signatureValue)
-    {
-        this.acinfo = acinfo;
-        this.signatureAlgorithm = signatureAlgorithm;
-        this.signatureValue = signatureValue;
-    }
-    
-    public AttributeCertificate(
-        ASN1Sequence    seq)
-    {
-        if (seq.size() != 3)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                    + seq.size());
-        }
-
-        this.acinfo = AttributeCertificateInfo.getInstance(seq.getObjectAt(0));
-        this.signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
-        this.signatureValue = DERBitString.getInstance(seq.getObjectAt(2));
-    }
-    
-    public AttributeCertificateInfo getAcinfo()
-    {
-        return acinfo;
-    }
-
-    public AlgorithmIdentifier getSignatureAlgorithm()
-    {
-        return signatureAlgorithm;
-    }
-
-    public DERBitString getSignatureValue()
-    {
-        return signatureValue;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  AttributeCertificate ::= SEQUENCE {
-     *       acinfo               AttributeCertificateInfo,
-     *       signatureAlgorithm   AlgorithmIdentifier,
-     *       signatureValue       BIT STRING
-     *  }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(acinfo);
-        v.add(signatureAlgorithm);
-        v.add(signatureValue);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java b/azureus2/src/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
deleted file mode 100644
index 74770f5..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class AttributeCertificateInfo
-    extends ASN1Encodable
-{
-    private DERInteger              version;
-    private Holder                  holder;
-    private AttCertIssuer           issuer;
-    private AlgorithmIdentifier     signature;
-    private DERInteger              serialNumber;
-    private AttCertValidityPeriod   attrCertValidityPeriod;
-    private ASN1Sequence            attributes;
-    private DERBitString            issuerUniqueID;
-    private X509Extensions          extensions;
-
-    public static AttributeCertificateInfo getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static AttributeCertificateInfo getInstance(
-        Object  obj)
-    {
-        if (obj instanceof AttributeCertificateInfo)
-        {
-            return (AttributeCertificateInfo)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new AttributeCertificateInfo((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public AttributeCertificateInfo(
-        ASN1Sequence   seq)
-    {
-        if (seq.size() < 7 || seq.size() > 9)
-        {
-            throw new IllegalArgumentException("Bad sequence size: " + seq.size());
-        }
-
-        this.version = DERInteger.getInstance(seq.getObjectAt(0));
-        this.holder = Holder.getInstance(seq.getObjectAt(1));
-        this.issuer = AttCertIssuer.getInstance(seq.getObjectAt(2));
-        this.signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(3));
-        this.serialNumber = DERInteger.getInstance(seq.getObjectAt(4));
-        this.attrCertValidityPeriod = AttCertValidityPeriod.getInstance(seq.getObjectAt(5));
-        this.attributes = ASN1Sequence.getInstance(seq.getObjectAt(6));
-        
-        for (int i = 7; i < seq.size(); i++)
-        {
-            ASN1Encodable    obj = (ASN1Encodable)seq.getObjectAt(i);
-
-            if (obj instanceof DERBitString)
-            {
-                this.issuerUniqueID = DERBitString.getInstance(seq.getObjectAt(i));
-            }
-            else if (obj instanceof ASN1Sequence || obj instanceof X509Extensions)
-            {
-                this.extensions = X509Extensions.getInstance(seq.getObjectAt(i));
-            }
-        }
-    }
-    
-    public DERInteger getVersion()
-    {
-        return version;
-    }
-
-    public Holder getHolder()
-    {
-        return holder;
-    }
-
-    public AttCertIssuer getIssuer()
-    {
-        return issuer;
-    }
-
-    public AlgorithmIdentifier getSignature()
-    {
-        return signature;
-    }
-
-    public DERInteger getSerialNumber()
-    {
-        return serialNumber;
-    }
-
-    public AttCertValidityPeriod getAttrCertValidityPeriod()
-    {
-        return attrCertValidityPeriod;
-    }
-
-    public ASN1Sequence getAttributes()
-    {
-        return attributes;
-    }
-
-    public DERBitString getIssuerUniqueID()
-    {
-        return issuerUniqueID;
-    }
-
-    public X509Extensions getExtensions()
-    {
-        return extensions;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  AttributeCertificateInfo ::= SEQUENCE {
-     *       version              AttCertVersion -- version is v2,
-     *       holder               Holder,
-     *       issuer               AttCertIssuer,
-     *       signature            AlgorithmIdentifier,
-     *       serialNumber         CertificateSerialNumber,
-     *       attrCertValidityPeriod   AttCertValidityPeriod,
-     *       attributes           SEQUENCE OF Attribute,
-     *       issuerUniqueID       UniqueIdentifier OPTIONAL,
-     *       extensions           Extensions OPTIONAL
-     *  }
-     *
-     *  AttCertVersion ::= INTEGER { v2(1) }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(version);
-        v.add(holder);
-        v.add(issuer);
-        v.add(signature);
-        v.add(serialNumber);
-        v.add(attrCertValidityPeriod);
-        v.add(attributes);
-        
-        if (issuerUniqueID != null)
-        {
-            v.add(issuerUniqueID);
-        }
-        
-        if (extensions != null)
-        {
-            v.add(extensions);
-        }
-        
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java b/azureus2/src/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java
deleted file mode 100644
index c331645..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * The AuthorityInformationAccess object.
- * <pre>
- * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
- *
- * AuthorityInfoAccessSyntax  ::=
- *      SEQUENCE SIZE (1..MAX) OF AccessDescription
- * AccessDescription  ::=  SEQUENCE {
- *       accessMethod          OBJECT IDENTIFIER,
- *       accessLocation        GeneralName  }
- *
- * id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
- * id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
- * id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
- * </pre>
- */
-public class AuthorityInformationAccess
-    extends ASN1Encodable
-{
-    private AccessDescription[]    descriptions;
-
-    public static AuthorityInformationAccess getInstance(
-        Object  obj)
-    {
-        if (obj instanceof AuthorityInformationAccess)
-        {
-            return (AuthorityInformationAccess)obj;
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            return new AuthorityInformationAccess((ASN1Sequence)obj);
-        }
-
-        if (obj instanceof X509Extension)
-        {
-            return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
- 
-    public AuthorityInformationAccess(
-        ASN1Sequence   seq)
-    {
-        descriptions = new AccessDescription[seq.size()];
-        
-        for (int i = 0; i != seq.size(); i++)
-        {
-            descriptions[i] = AccessDescription.getInstance(seq.getObjectAt(i));
-        }
-    }
-
-    /**
-     * create an AuthorityInformationAccess with the oid and location provided.
-     */
-    public AuthorityInformationAccess(
-        DERObjectIdentifier oid,
-        GeneralName location)
-    {
-        descriptions = new AccessDescription[1];
-        
-        descriptions[0] = new AccessDescription(oid, location);
-    }
-
-
-    /**
-     * 
-     * @return the access descriptions contained in this object.
-     */
-    public AccessDescription[] getAccessDescriptions()
-    {
-        return descriptions;
-    }
-    
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector vec = new ASN1EncodableVector();
-        
-        for (int i = 0; i != descriptions.length; i++)
-        {
-            vec.add(descriptions[i]);
-        }
-        
-        return new DERSequence(vec);
-    }
-
-    public String toString()
-    {
-        return ("AuthorityInformationAccess: Oid(" + this.descriptions[0].getAccessMethod().getId() + ")");
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java b/azureus2/src/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
deleted file mode 100644
index 4ef5490..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
+++ /dev/null
@@ -1,231 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-/**
- * The AuthorityKeyIdentifier object.
- * <pre>
- * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
- *
- *   AuthorityKeyIdentifier ::= SEQUENCE {
- *      keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
- *      authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
- *      authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
- *
- *   KeyIdentifier ::= OCTET STRING
- * </pre>
- *
- */
-public class AuthorityKeyIdentifier
-    extends ASN1Encodable
-{
-    ASN1OctetString keyidentifier=null;
-    GeneralNames certissuer=null;
-    DERInteger certserno=null;
-
-    public static AuthorityKeyIdentifier getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static AuthorityKeyIdentifier getInstance(
-        Object  obj)
-    {
-        if (obj instanceof AuthorityKeyIdentifier)
-        {
-            return (AuthorityKeyIdentifier)obj;
-        }
-        if (obj instanceof ASN1Sequence)
-        {
-            return new AuthorityKeyIdentifier((ASN1Sequence)obj);
-        }
-        if (obj instanceof X509Extension)
-        {
-            return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public AuthorityKeyIdentifier(
-        ASN1Sequence   seq)
-    {
-        Enumeration     e = seq.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            ASN1TaggedObject o = DERTaggedObject.getInstance(e.nextElement());
-
-            switch (o.getTagNo())
-            {
-            case 0:
-                this.keyidentifier = ASN1OctetString.getInstance(o, false);
-                break;
-            case 1:
-                this.certissuer = GeneralNames.getInstance(o, false);
-                break;
-            case 2:
-                this.certserno = DERInteger.getInstance(o, false);
-                break;
-            default:
-                throw new IllegalArgumentException("illegal tag");
-            }
-        }
-    }
-
-    /**
-     *
-     * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
-     * from SubjectPublicKeyInfo as defined in RFC2459.
-     *
-     * Example of making a AuthorityKeyIdentifier:
-     * <pre>
-     *   SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
-     *       publicKey.getEncoded()).readObject());
-     *   AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
-     * </pre>
-     *
-     **/
-    public AuthorityKeyIdentifier(
-        SubjectPublicKeyInfo    spki)
-    {
-        Digest  digest = new SHA1Digest();
-        byte[]  resBuf = new byte[digest.getDigestSize()];
-
-        byte[] bytes = spki.getPublicKeyData().getBytes();
-        digest.update(bytes, 0, bytes.length);
-        digest.doFinal(resBuf, 0);
-        this.keyidentifier = new DEROctetString(resBuf);
-    }
-
-    /**
-     * create an AuthorityKeyIdentifier with the GeneralNames tag and
-     * the serial number provided as well.
-     */
-    public AuthorityKeyIdentifier(
-        SubjectPublicKeyInfo    spki,
-        GeneralNames            name,
-        BigInteger              serialNumber)
-    {
-        Digest  digest = new SHA1Digest();
-        byte[]  resBuf = new byte[digest.getDigestSize()];
-
-        byte[] bytes = spki.getPublicKeyData().getBytes();
-        digest.update(bytes, 0, bytes.length);
-        digest.doFinal(resBuf, 0);
-
-        this.keyidentifier = new DEROctetString(resBuf);
-        this.certissuer = GeneralNames.getInstance(name.toASN1Object());
-        this.certserno = new DERInteger(serialNumber);
-    }
-
-    /**
-     * create an AuthorityKeyIdentifier with the GeneralNames tag and
-     * the serial number provided.
-     */
-    public AuthorityKeyIdentifier(
-        GeneralNames            name,
-        BigInteger              serialNumber)
-    {
-        this.keyidentifier = null;
-        this.certissuer = GeneralNames.getInstance(name.toASN1Object());
-        this.certserno = new DERInteger(serialNumber);
-    }
-
-    /**
-      * create an AuthorityKeyIdentifier with a precomupted key identifier
-      */
-     public AuthorityKeyIdentifier(
-         byte[]                  keyIdentifier)
-     {
-         this.keyidentifier = new DEROctetString(keyIdentifier);
-         this.certissuer = null;
-         this.certserno = null;
-     }
-
-    /**
-     * create an AuthorityKeyIdentifier with a precomupted key identifier
-     * and the GeneralNames tag and the serial number provided as well.
-     */
-    public AuthorityKeyIdentifier(
-        byte[]                  keyIdentifier,
-        GeneralNames            name,
-        BigInteger              serialNumber)
-    {
-        this.keyidentifier = new DEROctetString(keyIdentifier);
-        this.certissuer = GeneralNames.getInstance(name.toASN1Object());
-        this.certserno = new DERInteger(serialNumber);
-    }
-    
-    public byte[] getKeyIdentifier()
-    {
-        if (keyidentifier != null)
-        {
-            return keyidentifier.getOctets();
-        }
-
-        return null;
-    }
-
-    public GeneralNames getAuthorityCertIssuer()
-    {
-        return certissuer;
-    }
-    
-    public BigInteger getAuthorityCertSerialNumber()
-    {
-        if (certserno != null)
-        {
-            return certserno.getValue();
-        }
-        
-        return null;
-    }
-    
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        if (keyidentifier != null)
-        {
-            v.add(new DERTaggedObject(false, 0, keyidentifier));
-        }
-
-        if (certissuer != null)
-        {
-            v.add(new DERTaggedObject(false, 1, certissuer));
-        }
-
-        if (certserno != null)
-        {
-            v.add(new DERTaggedObject(false, 2, certserno));
-        }
-
-
-        return new DERSequence(v);
-    }
-
-    public String toString()
-    {
-        return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/BasicConstraints.java b/azureus2/src/org/bouncycastle/asn1/x509/BasicConstraints.java
deleted file mode 100644
index 839a747..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/BasicConstraints.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBoolean;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-import java.math.BigInteger;
-
-public class BasicConstraints
-    extends ASN1Encodable
-{
-    DERBoolean  cA = new DERBoolean(false);
-    DERInteger  pathLenConstraint = null;
-
-    public static BasicConstraints getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static BasicConstraints getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof BasicConstraints)
-        {
-            return (BasicConstraints)obj;
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            return new BasicConstraints((ASN1Sequence)obj);
-        }
-
-        if (obj instanceof X509Extension)
-        {
-            return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-    
-    public BasicConstraints(
-        ASN1Sequence   seq)
-    {
-        if (seq.size() == 0)
-        {
-            this.cA = null;
-            this.pathLenConstraint = null;
-        }
-        else
-        {
-            if (seq.getObjectAt(0) instanceof DERBoolean)
-            {
-                this.cA = DERBoolean.getInstance(seq.getObjectAt(0));
-            }
-            else
-            {
-                this.cA = null;
-                this.pathLenConstraint = DERInteger.getInstance(seq.getObjectAt(0));
-            }
-            if (seq.size() > 1)
-            {
-                if (this.cA != null)
-                {
-                    this.pathLenConstraint = DERInteger.getInstance(seq.getObjectAt(1));
-                }
-                else
-                {
-                    throw new IllegalArgumentException("wrong sequence in constructor");
-                }
-            }
-        }
-    }
-
-    /**
-     * @deprecated use one of the other two unambigous constructors.
-     * @param cA
-     * @param pathLenConstraint
-     */
-    public BasicConstraints(
-        boolean cA,
-        int     pathLenConstraint)
-    {
-        if (cA)
-        {
-            this.cA = new DERBoolean(cA);
-            this.pathLenConstraint = new DERInteger(pathLenConstraint);
-        }
-        else
-        {
-            this.cA = null;
-            this.pathLenConstraint = null;
-        }
-    }
-
-    public BasicConstraints(
-        boolean cA)
-    {
-        if (cA)
-        {
-            this.cA = new DERBoolean(true);
-        }
-        else
-        {
-            this.cA = null;
-        }
-        this.pathLenConstraint = null;
-    }
-
-    /**
-     * create a cA=true object for the given path length constraint.
-     * 
-     * @param pathLenConstraint
-     */
-    public BasicConstraints(
-        int     pathLenConstraint)
-    {
-        this.cA = new DERBoolean(true);
-        this.pathLenConstraint = new DERInteger(pathLenConstraint);
-    }
-
-    public boolean isCA()
-    {
-        return (cA != null) && cA.isTrue();
-    }
-
-    public BigInteger getPathLenConstraint()
-    {
-        if (pathLenConstraint != null)
-        {
-            return pathLenConstraint.getValue();
-        }
-
-        return null;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * BasicConstraints := SEQUENCE {
-     *    cA                  BOOLEAN DEFAULT FALSE,
-     *    pathLenConstraint   INTEGER (0..MAX) OPTIONAL
-     * }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        if (cA != null)
-        {
-            v.add(cA);
-        }
-
-        if (pathLenConstraint != null)  // yes some people actually do this when cA is false...
-        {
-            v.add(pathLenConstraint);
-        }
-
-        return new DERSequence(v);
-    }
-
-    public String toString()
-    {
-        if (pathLenConstraint == null)
-        {
-            if (cA == null)
-            {
-                return "BasicConstraints: isCa(false)";
-            }
-            return "BasicConstraints: isCa(" + this.isCA() + ")";
-        }
-        return "BasicConstraints: isCa(" + this.isCA() + "), pathLenConstraint = " + pathLenConstraint.getValue();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/CRLDistPoint.java b/azureus2/src/org/bouncycastle/asn1/x509/CRLDistPoint.java
deleted file mode 100644
index 0eecc6a..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/CRLDistPoint.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class CRLDistPoint
-    extends ASN1Encodable
-{
-    ASN1Sequence  seq = null;
-
-    public static CRLDistPoint getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static CRLDistPoint getInstance(
-        Object  obj)
-    {
-        if (obj instanceof CRLDistPoint || obj == null)
-        {
-            return (CRLDistPoint)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new CRLDistPoint((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public CRLDistPoint(
-        ASN1Sequence seq)
-    {
-        this.seq = seq;
-    }
-    
-    public CRLDistPoint(
-        DistributionPoint[] points)
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        for (int i = 0; i != points.length; i++)
-        {
-            v.add(points[i]);
-        }
-
-        seq = new DERSequence(v);
-    }
-
-    /**
-     * Return the distribution points making up the sequence.
-     * 
-     * @return DistributionPoint[]
-     */
-    public DistributionPoint[] getDistributionPoints()
-    {
-        DistributionPoint[]    dp = new DistributionPoint[seq.size()];
-        
-        for (int i = 0; i != seq.size(); i++)
-        {
-            dp[i] = DistributionPoint.getInstance(seq.getObjectAt(i));
-        }
-        
-        return dp;
-    }
-    
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * CRLDistPoint ::= SEQUENCE SIZE {1..MAX} OF DistributionPoint
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        return seq;
-    }
-
-    public String toString()
-    {
-        StringBuffer buf = new StringBuffer();
-        String       sep = System.getProperty("line.separator");
-
-        buf.append("CRLDistPoint:");
-        buf.append(sep);
-        DistributionPoint dp[] = getDistributionPoints();
-        for (int i = 0; i != dp.length; i++)
-        {
-            buf.append("    ");
-            buf.append(dp[i]);
-            buf.append(sep);
-        }
-        return buf.toString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/CRLNumber.java b/azureus2/src/org/bouncycastle/asn1/x509/CRLNumber.java
deleted file mode 100644
index 5c74abf..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/CRLNumber.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DERInteger;
-
-import java.math.BigInteger;
-
-/**
- * The CRLNumber object.
- * <pre>
- * CRLNumber::= INTEGER(0..MAX)
- * </pre>
- */
-public class CRLNumber
-    extends DERInteger
-{
-
-    public CRLNumber(
-        BigInteger number)
-    {
-        super(number);
-    }
-
-    public BigInteger getCRLNumber()
-    {
-        return getPositiveValue();
-    }
-
-    public String toString()
-    {
-        return "CRLNumber: " + getCRLNumber();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/CRLReason.java b/azureus2/src/org/bouncycastle/asn1/x509/CRLReason.java
deleted file mode 100644
index dfbccda..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/CRLReason.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DEREnumerated;
-
-/**
- * The CRLReason enumeration.
- * <pre>
- * CRLReason ::= ENUMERATED {
- *  unspecified             (0),
- *  keyCompromise           (1),
- *  cACompromise            (2),
- *  affiliationChanged      (3),
- *  superseded              (4),
- *  cessationOfOperation    (5),
- *  certificateHold         (6),
- *  removeFromCRL           (8),
- *  privilegeWithdrawn      (9),
- *  aACompromise           (10)
- * }
- * </pre>
- */
-public class CRLReason
-    extends DEREnumerated
-{
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int UNSPECIFIED = 0;
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int KEY_COMPROMISE = 1;
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int CA_COMPROMISE = 2;
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int AFFILIATION_CHANGED = 3;
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int SUPERSEDED = 4;
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int CESSATION_OF_OPERATION  = 5;
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int CERTIFICATE_HOLD = 6;
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int REMOVE_FROM_CRL = 8;
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int PRIVILEGE_WITHDRAWN = 9;
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int AA_COMPROMISE = 10;
-
-    public static final int unspecified = 0;
-    public static final int keyCompromise = 1;
-    public static final int cACompromise = 2;
-    public static final int affiliationChanged = 3;
-    public static final int superseded = 4;
-    public static final int cessationOfOperation  = 5;
-    public static final int certificateHold = 6;
-    // 7 -> unknown
-    public static final int removeFromCRL = 8;
-    public static final int privilegeWithdrawn = 9;
-    public static final int aACompromise = 10;
-
-    private static final String[] reasonString =
-    {
-        "unspecified", "keyCompromise", "cACompromise", "affiliationChanged",
-        "superseded", "cessationOfOperation", "certificateHold", "unknown",
-        "removeFromCRL", "privilegeWithdrawn", "aACompromise"
-    };
-
-    public CRLReason(
-        int reason)
-    {
-        super(reason);
-    }
-
-    public CRLReason(
-        DEREnumerated reason)
-    {
-        super(reason.getValue().intValue());
-    }
-
-    public String toString()
-    {
-        String str;
-        int reason = getValue().intValue();
-        if (reason < 0 || reason > 10)
-        {
-            str = "invalid";
-        }
-        else
-        {
-            str = reasonString[reason];
-        }
-        return "CRLReason: " + str;
-    }    
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/CertPolicyId.java b/azureus2/src/org/bouncycastle/asn1/x509/CertPolicyId.java
deleted file mode 100644
index 3e85dbd..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/CertPolicyId.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-
-/**
- * CertPolicyId, used in the CertificatePolicies and PolicyMappings
- * X509V3 Extensions.
- *
- * <pre>
- *     CertPolicyId ::= OBJECT IDENTIFIER
- * </pre>
- */
-public class CertPolicyId extends DERObjectIdentifier 
-{
-   public CertPolicyId (String id) 
-   {
-     super(id);
-   }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/CertificateList.java b/azureus2/src/org/bouncycastle/asn1/x509/CertificateList.java
deleted file mode 100644
index c7f890b..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/CertificateList.java
+++ /dev/null
@@ -1,119 +0,0 @@
-
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * PKIX RFC-2459
- *
- * The X.509 v2 CRL syntax is as follows.  For signature calculation,
- * the data that is to be signed is ASN.1 DER encoded.
- *
- * <pre>
- * CertificateList  ::=  SEQUENCE  {
- *      tbsCertList          TBSCertList,
- *      signatureAlgorithm   AlgorithmIdentifier,
- *      signatureValue       BIT STRING  }
- * </pre>
- */
-public class CertificateList
-    extends ASN1Encodable
-{
-    TBSCertList            tbsCertList;
-    AlgorithmIdentifier    sigAlgId;
-    DERBitString           sig;
-
-    public static CertificateList getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static CertificateList getInstance(
-        Object  obj)
-    {
-        if (obj instanceof CertificateList)
-        {
-            return (CertificateList)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new CertificateList((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public CertificateList(
-        ASN1Sequence seq)
-    {
-        if (seq.size() == 3)
-        {
-            tbsCertList = TBSCertList.getInstance(seq.getObjectAt(0));
-            sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
-            sig = DERBitString.getInstance(seq.getObjectAt(2));
-        }
-        else
-        {
-            throw new IllegalArgumentException("sequence wrong size for CertificateList");
-        }
-    }
-
-    public TBSCertList getTBSCertList()
-    {
-        return tbsCertList;
-    }
-
-    public TBSCertList.CRLEntry[] getRevokedCertificates()
-    {
-        return tbsCertList.getRevokedCertificates();
-    }
-
-    public AlgorithmIdentifier getSignatureAlgorithm()
-    {
-        return sigAlgId;
-    }
-
-    public DERBitString getSignature()
-    {
-        return sig;
-    }
-
-    public int getVersion()
-    {
-        return tbsCertList.getVersion();
-    }
-
-    public X509Name getIssuer()
-    {
-        return tbsCertList.getIssuer();
-    }
-
-    public Time getThisUpdate()
-    {
-        return tbsCertList.getThisUpdate();
-    }
-
-    public Time getNextUpdate()
-    {
-        return tbsCertList.getNextUpdate();
-    }
-
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(tbsCertList);
-        v.add(sigAlgId);
-        v.add(sig);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/CertificatePair.java b/azureus2/src/org/bouncycastle/asn1/x509/CertificatePair.java
deleted file mode 100644
index bd9d25c..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/CertificatePair.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-import java.util.Enumeration;
-
-/**
- * This class helps to support crossCerfificatePairs in a LDAP directory
- * according RFC 2587
- * 
- * <pre>
- *     crossCertificatePairATTRIBUTE::={
- *       WITH SYNTAX   CertificatePair
- *       EQUALITY MATCHING RULE certificatePairExactMatch
- *       ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
- * </pre>
- * 
- * <blockquote> The forward elements of the crossCertificatePair attribute of a
- * CA's directory entry shall be used to store all, except self-issued
- * certificates issued to this CA. Optionally, the reverse elements of the
- * crossCertificatePair attribute, of a CA's directory entry may contain a
- * subset of certificates issued by this CA to other CAs. When both the forward
- * and the reverse elements are present in a single attribute value, issuer name
- * in one certificate shall match the subject name in the other and vice versa,
- * and the subject public key in one certificate shall be capable of verifying
- * the digital signature on the other certificate and vice versa.
- * 
- * When a reverse element is present, the forward element value and the reverse
- * element value need not be stored in the same attribute value; in other words,
- * they can be stored in either a single attribute value or two attribute
- * values. </blockquote>
- * 
- * <pre>
- *       CertificatePair ::= SEQUENCE {
- *         forward        [0]    Certificate OPTIONAL,
- *         reverse        [1]    Certificate OPTIONAL,
- *         -- at least one of the pair shall be present -- } 
- * </pre>
- */
-public class CertificatePair
-    extends ASN1Encodable
-{
-    private X509CertificateStructure forward;
-
-    private X509CertificateStructure reverse;
-
-    public static CertificatePair getInstance(Object obj)
-    {
-        if (obj == null || obj instanceof CertificatePair)
-        {
-            return (CertificatePair)obj;
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            return new CertificatePair((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: "
-            + obj.getClass().getName());
-    }
-
-    /**
-     * Constructor from ASN1Sequence.
-     * <p/>
-     * The sequence is of type CertificatePair:
-     * <p/>
-     * <pre>
-     *       CertificatePair ::= SEQUENCE {
-     *         forward        [0]    Certificate OPTIONAL,
-     *         reverse        [1]    Certificate OPTIONAL,
-     *         -- at least one of the pair shall be present -- }
-     * </pre>
-     *
-     * @param seq The ASN.1 sequence.
-     */
-    private CertificatePair(ASN1Sequence seq)
-    {
-        if (seq.size() != 1 && seq.size() != 2)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                + seq.size());
-        }
-
-        Enumeration e = seq.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
-            if (o.getTagNo() == 0)
-            {
-                forward = X509CertificateStructure.getInstance(o, true);
-            }
-            else if (o.getTagNo() == 1)
-            {
-                reverse = X509CertificateStructure.getInstance(o, true);
-            }
-            else
-            {
-                throw new IllegalArgumentException("Bad tag number: "
-                    + o.getTagNo());
-            }
-        }
-    }
-
-    /**
-     * Constructor from a given details.
-     *
-     * @param forward Certificates issued to this CA.
-     * @param reverse Certificates issued by this CA to other CAs.
-     */
-    public CertificatePair(X509CertificateStructure forward, X509CertificateStructure reverse)
-    {
-        this.forward = forward;
-        this.reverse = reverse;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <p/>
-     * Returns:
-     * <p/>
-     * <pre>
-     *       CertificatePair ::= SEQUENCE {
-     *         forward        [0]    Certificate OPTIONAL,
-     *         reverse        [1]    Certificate OPTIONAL,
-     *         -- at least one of the pair shall be present -- }
-     * </pre>
-     *
-     * @return a DERObject
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector vec = new ASN1EncodableVector();
-
-        if (forward != null)
-        {
-            vec.add(new DERTaggedObject(0, forward));
-        }
-        if (reverse != null)
-        {
-            vec.add(new DERTaggedObject(1, reverse));
-        }
-
-        return new DERSequence(vec);
-    }
-
-    /**
-     * @return Returns the forward.
-     */
-    public X509CertificateStructure getForward()
-    {
-        return forward;
-    }
-
-    /**
-     * @return Returns the reverse.
-     */
-    public X509CertificateStructure getReverse()
-    {
-        return reverse;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/CertificatePolicies.java b/azureus2/src/org/bouncycastle/asn1/x509/CertificatePolicies.java
deleted file mode 100644
index b59e08e..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/CertificatePolicies.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-public class CertificatePolicies
-    extends ASN1Encodable
-{
-    static final DERObjectIdentifier anyPolicy = new DERObjectIdentifier("2.5.29.32.0");
-
-    Vector policies = new Vector();
-
-/**
- * @deprecated use an ASN1Sequence of PolicyInformation
- */
-    public static CertificatePolicies getInstance(
-        ASN1TaggedObject obj,
-        boolean explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-/**
- * @deprecated use an ASN1Sequence of PolicyInformation
- */
-    public static CertificatePolicies getInstance(
-        Object  obj)
-    {
-        if (obj instanceof CertificatePolicies)
-        {
-            return (CertificatePolicies)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new CertificatePolicies((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-/**
- * @deprecated use an ASN1Sequence of PolicyInformation
- */
-    public CertificatePolicies(
-        ASN1Sequence   seq)
-    {
-        Enumeration e = seq.getObjects();
-        while (e.hasMoreElements())
-        {
-            ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement());
-            policies.addElement(s.getObjectAt(0));
-        }
-        // For now we just don't handle PolicyQualifiers
-    }
-
-    /**
-     * create a certificate policy with the given OID.
-     * @deprecated use an ASN1Sequence of PolicyInformation
-     */
-    public CertificatePolicies(
-        DERObjectIdentifier p)
-    {
-        policies.addElement(p);
-    }
-
-    /**
-     * create a certificate policy with the policy given by the OID represented
-     * by the string p.
-     * @deprecated use an ASN1Sequence of PolicyInformation
-     */
-    public CertificatePolicies(
-        String p)
-    {
-        this(new DERObjectIdentifier(p));
-    }
-
-    public void addPolicy(
-        String p)
-    {
-        policies.addElement(new DERObjectIdentifier(p));
-    }
-
-    public String getPolicy(int nr)
-    {
-        if (policies.size() > nr)
-        {
-            return ((DERObjectIdentifier)policies.elementAt(nr)).getId();
-        }
-        
-        return null;
-    }
-
-    /**
-     * <pre>
-     * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
-     *
-     * PolicyInformation ::= SEQUENCE {
-     *   policyIdentifier   CertPolicyId,
-     *   policyQualifiers   SEQUENCE SIZE (1..MAX) OF
-     *                           PolicyQualifierInfo OPTIONAL }
-     *
-     * CertPolicyId ::= OBJECT IDENTIFIER
-     *
-     * PolicyQualifierInfo ::= SEQUENCE {
-     *   policyQualifierId  PolicyQualifierId,
-     *   qualifier          ANY DEFINED BY policyQualifierId }
-     *
-     * PolicyQualifierId ::=
-     *   OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice)
-     * </pre>
-     * @deprecated use an ASN1Sequence of PolicyInformation
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        // We only do policyIdentifier yet...
-        for (int i=0;i<policies.size();i++)
-        {
-            v.add(new DERSequence((DERObjectIdentifier)policies.elementAt(i)));
-        }
-
-        return new DERSequence(v);
-    }
-
-    public String toString()
-    {
-        String p = null;
-        for (int i=0;i<policies.size();i++)
-        {
-            if (p != null)
-            {
-                p += ", ";
-            }
-            p += ((DERObjectIdentifier)policies.elementAt(i)).getId();
-        }
-        return "CertificatePolicies: "+p;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/DSAParameter.java b/azureus2/src/org/bouncycastle/asn1/x509/DSAParameter.java
deleted file mode 100644
index 50822d6..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/DSAParameter.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class DSAParameter
-    extends ASN1Encodable
-{
-    DERInteger      p, q, g;
-
-    public static DSAParameter getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static DSAParameter getInstance(
-        Object obj)
-    {
-        if(obj == null || obj instanceof DSAParameter) 
-        {
-            return (DSAParameter)obj;
-        }
-        
-        if(obj instanceof ASN1Sequence) 
-        {
-            return new DSAParameter((ASN1Sequence)obj);
-        }
-        
-        throw new IllegalArgumentException("Invalid DSAParameter: " + obj.getClass().getName());
-    }
-
-    public DSAParameter(
-        BigInteger  p,
-        BigInteger  q,
-        BigInteger  g)
-    {
-        this.p = new DERInteger(p);
-        this.q = new DERInteger(q);
-        this.g = new DERInteger(g);
-    }
-
-    public DSAParameter(
-        ASN1Sequence  seq)
-    {
-        if (seq.size() != 3)
-        {
-            throw new IllegalArgumentException("Bad sequence size: " + seq.size());
-        }
-        
-        Enumeration     e = seq.getObjects();
-
-        p = DERInteger.getInstance(e.nextElement());
-        q = DERInteger.getInstance(e.nextElement());
-        g = DERInteger.getInstance(e.nextElement());
-    }
-
-    public BigInteger getP()
-    {
-        return p.getPositiveValue();
-    }
-
-    public BigInteger getQ()
-    {
-        return q.getPositiveValue();
-    }
-
-    public BigInteger getG()
-    {
-        return g.getPositiveValue();
-    }
-
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(p);
-        v.add(q);
-        v.add(g);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/DigestInfo.java b/azureus2/src/org/bouncycastle/asn1/x509/DigestInfo.java
deleted file mode 100644
index 882e71e..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/DigestInfo.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * The DigestInfo object.
- * <pre>
- * DigestInfo::=SEQUENCE{
- *          digestAlgorithm  AlgorithmIdentifier,
- *          digest OCTET STRING }
- * </pre>
- */
-public class DigestInfo
-    extends ASN1Encodable
-{
-    private byte[]                  digest;
-    private AlgorithmIdentifier     algId;
-
-    public static DigestInfo getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static DigestInfo getInstance(
-        Object  obj)
-    {
-        if (obj instanceof DigestInfo)
-        {
-            return (DigestInfo)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new DigestInfo((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public DigestInfo(
-        AlgorithmIdentifier  algId,
-        byte[]               digest)
-    {
-        this.digest = digest;
-        this.algId = algId;
-    }
-
-    public DigestInfo(
-        ASN1Sequence  obj)
-    {
-        Enumeration             e = obj.getObjects();
-
-        algId = AlgorithmIdentifier.getInstance(e.nextElement());
-        digest = ASN1OctetString.getInstance(e.nextElement()).getOctets();
-    }
-
-    public AlgorithmIdentifier getAlgorithmId()
-    {
-        return algId;
-    }
-
-    public byte[] getDigest()
-    {
-        return digest;
-    }
-
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(algId);
-        v.add(new DEROctetString(digest));
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/DisplayText.java b/azureus2/src/org/bouncycastle/asn1/x509/DisplayText.java
deleted file mode 100644
index 90b025e..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/DisplayText.java
+++ /dev/null
@@ -1,165 +0,0 @@
-
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERBMPString;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERUTF8String;
-import org.bouncycastle.asn1.DERVisibleString;
-import org.bouncycastle.asn1.DERString;
-
-/**
- * <code>DisplayText</code> class, used in
- * <code>CertificatePolicies</code> X509 V3 extensions (in policy qualifiers).
- *
- * <p>It stores a string in a chosen encoding. 
- * <pre>
- * DisplayText ::= CHOICE {
- *      ia5String        IA5String      (SIZE (1..200)),
- *      visibleString    VisibleString  (SIZE (1..200)),
- *      bmpString        BMPString      (SIZE (1..200)),
- *      utf8String       UTF8String     (SIZE (1..200)) }
- * </pre>
- * @see PolicyQualifierInfo
- * @see PolicyInformation
- */
-public class DisplayText 
-    extends ASN1Encodable
-    implements ASN1Choice
-{
-   /**
-    * Constant corresponding to ia5String encoding. 
-    *
-    */
-   public static final int CONTENT_TYPE_IA5STRING = 0;
-   /**
-    * Constant corresponding to bmpString encoding. 
-    *
-    */
-   public static final int CONTENT_TYPE_BMPSTRING = 1;
-   /**
-    * Constant corresponding to utf8String encoding. 
-    *
-    */
-   public static final int CONTENT_TYPE_UTF8STRING = 2;
-   /**
-    * Constant corresponding to visibleString encoding. 
-    *
-    */
-   public static final int CONTENT_TYPE_VISIBLESTRING = 3;
-
-   /**
-    * Describe constant <code>DISPLAY_TEXT_MAXIMUM_SIZE</code> here.
-    *
-    */
-   public static final int DISPLAY_TEXT_MAXIMUM_SIZE = 200;
-   
-   int contentType;
-   DERString contents;
-   
-   /**
-    * Creates a new <code>DisplayText</code> instance.
-    *
-    * @param type the desired encoding type for the text. 
-    * @param text the text to store. Strings longer than 200
-    * characters are truncated. 
-    */
-   public DisplayText (int type, String text) 
-   {
-      if (text.length() > DISPLAY_TEXT_MAXIMUM_SIZE)
-      {
-         // RFC3280 limits these strings to 200 chars
-         // truncate the string
-         text = text.substring (0, DISPLAY_TEXT_MAXIMUM_SIZE);
-      }
-     
-      contentType = type;
-      switch (type)
-      {
-         case CONTENT_TYPE_IA5STRING:
-            contents = (DERString)new DERIA5String (text);
-            break;
-         case CONTENT_TYPE_UTF8STRING:
-            contents = (DERString)new DERUTF8String(text);
-            break;
-         case CONTENT_TYPE_VISIBLESTRING:
-            contents = (DERString)new DERVisibleString(text);
-            break;
-         case CONTENT_TYPE_BMPSTRING:
-            contents = (DERString)new DERBMPString(text);
-            break;
-         default:
-            contents = (DERString)new DERUTF8String(text);
-            break;
-      }
-   }
-   
-   /**
-    * Creates a new <code>DisplayText</code> instance.
-    *
-    * @param text the text to encapsulate. Strings longer than 200
-    * characters are truncated. 
-    */
-   public DisplayText (String text) 
-   {
-      // by default use UTF8String
-      if (text.length() > DISPLAY_TEXT_MAXIMUM_SIZE)
-      {
-         text = text.substring(0, DISPLAY_TEXT_MAXIMUM_SIZE);
-      }
-      
-      contentType = CONTENT_TYPE_UTF8STRING;
-      contents = new DERUTF8String(text);
-   }
-
-   /**
-    * Creates a new <code>DisplayText</code> instance.
-    * <p>Useful when reading back a <code>DisplayText</code> class
-    * from it's ASN1Encodable/DEREncodable form. 
-    *
-    * @param de a <code>DEREncodable</code> instance. 
-    */
-   public DisplayText(DERString de)
-   {
-      contents = de;
-   }
-
-   public static DisplayText getInstance(Object de) 
-   {
-      if (de instanceof DERString)
-      {
-          return new DisplayText((DERString)de);
-      }
-      else if (de instanceof DisplayText)
-      {
-          return (DisplayText)de;
-      }
-
-      throw new IllegalArgumentException("illegal object in getInstance");
-   }
-
-   public static DisplayText getInstance(
-       ASN1TaggedObject obj,
-       boolean          explicit)
-   {
-       return getInstance(obj.getObject()); // must be explicitly tagged
-   }
-   
-   public DERObject toASN1Object() 
-   {
-      return (DERObject)contents;
-   }
-
-   /**
-    * Returns the stored <code>String</code> object. 
-    *
-    * @return the stored text as a <code>String</code>. 
-    */
-   public String getString() 
-   {
-      return contents.getString();
-   }   
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/DistributionPoint.java b/azureus2/src/org/bouncycastle/asn1/x509/DistributionPoint.java
deleted file mode 100644
index e57c408..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/DistributionPoint.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * The DistributionPoint object.
- * <pre>
- * DistributionPoint ::= SEQUENCE {
- *      distributionPoint [0] DistributionPointName OPTIONAL,
- *      reasons           [1] ReasonFlags OPTIONAL,
- *      cRLIssuer         [2] GeneralNames OPTIONAL
- * }
- * </pre>
- */
-public class DistributionPoint
-    extends ASN1Encodable
-{
-    DistributionPointName       distributionPoint;
-    ReasonFlags                 reasons;
-    GeneralNames                cRLIssuer;
-
-    public static DistributionPoint getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static DistributionPoint getInstance(
-        Object obj)
-    {
-        if(obj == null || obj instanceof DistributionPoint) 
-        {
-            return (DistributionPoint)obj;
-        }
-        
-        if(obj instanceof ASN1Sequence) 
-        {
-            return new DistributionPoint((ASN1Sequence)obj);
-        }
-        
-        throw new IllegalArgumentException("Invalid DistributionPoint: " + obj.getClass().getName());
-    }
-
-    public DistributionPoint(
-        ASN1Sequence seq)
-    {
-        for (int i = 0; i != seq.size(); i++)
-        {
-            ASN1TaggedObject    t = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
-            switch (t.getTagNo())
-            {
-            case 0:
-                distributionPoint = DistributionPointName.getInstance(t, true);
-                break;
-            case 1:
-                reasons = new ReasonFlags(DERBitString.getInstance(t, false));
-                break;
-            case 2:
-                cRLIssuer = GeneralNames.getInstance(t, false);
-            }
-        }
-    }
-    
-    public DistributionPoint(
-        DistributionPointName distributionPoint,
-        ReasonFlags                 reasons,
-        GeneralNames            cRLIssuer)
-    {
-        this.distributionPoint = distributionPoint;
-        this.reasons = reasons;
-        this.cRLIssuer = cRLIssuer;
-    }
-    
-    public DistributionPointName getDistributionPoint()
-    {
-        return distributionPoint;
-    }
-
-    public ReasonFlags getReasons()
-    {
-        return reasons;
-    }
-    
-    public GeneralNames getCRLIssuer()
-    {
-        return cRLIssuer;
-    }
-    
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-        
-        if (distributionPoint != null)
-        {
-            //
-            // as this is a CHOICE it must be explicitly tagged
-            //
-            v.add(new DERTaggedObject(0, distributionPoint));
-        }
-
-        if (reasons != null)
-        {
-            v.add(new DERTaggedObject(false, 1, reasons));
-        }
-
-        if (cRLIssuer != null)
-        {
-            v.add(new DERTaggedObject(false, 2, cRLIssuer));
-        }
-
-        return new DERSequence(v);
-    }
-
-    public String toString()
-    {
-        String       sep = System.getProperty("line.separator");
-        StringBuffer buf = new StringBuffer();
-        buf.append("DistributionPoint: [");
-        buf.append(sep);
-        if (distributionPoint != null)
-        {
-            appendObject(buf, sep, "distributionPoint", distributionPoint.toString());
-        }
-        if (reasons != null)
-        {
-            appendObject(buf, sep, "reasons", reasons.toString());
-        }
-        if (cRLIssuer != null)
-        {
-            appendObject(buf, sep, "cRLIssuer", cRLIssuer.toString());
-        }
-        buf.append("]");
-        buf.append(sep);
-        return buf.toString();
-    }
-
-    private void appendObject(StringBuffer buf, String sep, String name, String value)
-    {
-        String       indent = "    ";
-
-        buf.append(indent);
-        buf.append(name);
-        buf.append(":");
-        buf.append(sep);
-        buf.append(indent);
-        buf.append(indent);
-        buf.append(value);
-        buf.append(sep);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/DistributionPointName.java b/azureus2/src/org/bouncycastle/asn1/x509/DistributionPointName.java
deleted file mode 100644
index 47c69a1..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/DistributionPointName.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * The DistributionPointName object.
- * <pre>
- * DistributionPointName ::= CHOICE {
- *     fullName                 [0] GeneralNames,
- *     nameRelativeToCRLIssuer  [1] RelativeDistinguishedName
- * }
- * </pre>
- */
-public class DistributionPointName
-    extends ASN1Encodable
-    implements ASN1Choice
-{
-    DEREncodable        name;
-    int                 type;
-
-    public static final int FULL_NAME = 0;
-    public static final int NAME_RELATIVE_TO_CRL_ISSUER = 1;
-
-    public static DistributionPointName getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1TaggedObject.getInstance(obj, true));
-    }
-
-    public static DistributionPointName getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof DistributionPointName)
-        {
-            return (DistributionPointName)obj;
-        }
-        else if (obj instanceof ASN1TaggedObject)
-        {
-            return new DistributionPointName((ASN1TaggedObject)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    /*
-     * @deprecated use ASN1Encodable
-     */
-    public DistributionPointName(
-        int             type,
-        DEREncodable    name)
-    {
-        this.type = type;
-        this.name = name;
-    }
-
-    public DistributionPointName(
-        int             type,
-        ASN1Encodable   name)
-    {
-        this.type = type;
-        this.name = name;
-    }
-    
-    /**
-     * Return the tag number applying to the underlying choice.
-     * 
-     * @return the tag number for this point name.
-     */
-    public int getType()
-    {
-        return this.type;
-    }
-    
-    /**
-     * Return the tagged object inside the distribution point name.
-     * 
-     * @return the underlying choice item.
-     */
-    public ASN1Encodable getName()
-    {
-        return (ASN1Encodable)name;
-    }
-    
-    public DistributionPointName(
-        ASN1TaggedObject    obj)
-    {
-        this.type = obj.getTagNo();
-        
-        if (type == 0)
-        {
-            this.name = GeneralNames.getInstance(obj, false);
-        }
-        else
-        {
-            this.name = ASN1Set.getInstance(obj, false);
-        }
-    }
-    
-    public DERObject toASN1Object()
-    {
-        return new DERTaggedObject(false, type, name);
-    }
-
-    public String toString()
-    {
-        String       sep = System.getProperty("line.separator");
-        StringBuffer buf = new StringBuffer();
-        buf.append("DistributionPointName: [");
-        buf.append(sep);
-        if (type == FULL_NAME)
-        {
-            appendObject(buf, sep, "fullName", name.toString());
-        }
-        else
-        {
-            appendObject(buf, sep, "nameRelativeToCRLIssuer", name.toString());
-        }
-        buf.append("]");
-        buf.append(sep);
-        return buf.toString();
-    }
-
-    private void appendObject(StringBuffer buf, String sep, String name, String value)
-    {
-        String       indent = "    ";
-
-        buf.append(indent);
-        buf.append(name);
-        buf.append(":");
-        buf.append(sep);
-        buf.append(indent);
-        buf.append(indent);
-        buf.append(value);
-        buf.append(sep);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java b/azureus2/src/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
deleted file mode 100644
index 0811df5..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * The extendedKeyUsage object.
- * <pre>
- *      extendedKeyUsage ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
- * </pre>
- */
-public class ExtendedKeyUsage
-    extends ASN1Encodable
-{
-    Hashtable     usageTable = new Hashtable();
-    ASN1Sequence  seq;
-
-    public static ExtendedKeyUsage getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static ExtendedKeyUsage getInstance(
-        Object obj)
-    {
-        if (obj instanceof ExtendedKeyUsage) 
-        {
-            return (ExtendedKeyUsage)obj;
-        }
-        
-        if(obj instanceof ASN1Sequence) 
-        {
-            return new ExtendedKeyUsage((ASN1Sequence)obj);
-        }
-
-        if (obj instanceof X509Extension)
-        {
-            return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
-        }
-
-        throw new IllegalArgumentException("Invalid ExtendedKeyUsage: " + obj.getClass().getName());
-    }
-
-    public ExtendedKeyUsage(
-        KeyPurposeId  usage)
-    {
-        this.seq = new DERSequence(usage);
-
-        this.usageTable.put(usage, usage);
-    }
-    
-    public ExtendedKeyUsage(
-        ASN1Sequence  seq)
-    {
-        this.seq = seq;
-
-        Enumeration e = seq.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            Object  o = e.nextElement();
-            if (!(o instanceof DERObjectIdentifier))
-            {
-                throw new IllegalArgumentException("Only DERObjectIdentifiers allowed in ExtendedKeyUsage.");
-            }
-            this.usageTable.put(o, o);
-        }
-    }
-
-    public ExtendedKeyUsage(
-        Vector  usages)
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-        Enumeration         e = usages.elements();
-
-        while (e.hasMoreElements())
-        {
-            DERObject  o = (DERObject)e.nextElement();
-
-            v.add(o);
-            this.usageTable.put(o, o);
-        }
-
-        this.seq = new DERSequence(v);
-    }
-
-    public boolean hasKeyPurposeId(
-        KeyPurposeId keyPurposeId)
-    {
-        return (usageTable.get(keyPurposeId) != null);
-    }
-    
-    /**
-     * Returns all extended key usages.
-     * The returned vector contains DERObjectIdentifiers.
-     * @return A vector with all key purposes.
-     */
-    public Vector getUsages()
-    {
-        Vector temp = new Vector();
-        for (Enumeration it = usageTable.elements(); it.hasMoreElements();)
-        {
-            temp.addElement(it.nextElement());
-        }
-        return temp;
-    }
-
-    public int size()
-    {
-        return usageTable.size();
-    }
-    
-    public DERObject toASN1Object()
-    {
-        return seq;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/GeneralName.java b/azureus2/src/org/bouncycastle/asn1/x509/GeneralName.java
deleted file mode 100644
index 577f5cc..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/GeneralName.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.util.IPAddress;
-import org.bouncycastle.util.Strings;
-
-/**
- * The GeneralName object.
- * <pre>
- * GeneralName ::= CHOICE {
- *      otherName                       [0]     OtherName,
- *      rfc822Name                      [1]     IA5String,
- *      dNSName                         [2]     IA5String,
- *      x400Address                     [3]     ORAddress,
- *      directoryName                   [4]     Name,
- *      ediPartyName                    [5]     EDIPartyName,
- *      uniformResourceIdentifier       [6]     IA5String,
- *      iPAddress                       [7]     OCTET STRING,
- *      registeredID                    [8]     OBJECT IDENTIFIER}
- *
- * OtherName ::= SEQUENCE {
- *      type-id    OBJECT IDENTIFIER,
- *      value      [0] EXPLICIT ANY DEFINED BY type-id }
- *
- * EDIPartyName ::= SEQUENCE {
- *      nameAssigner            [0]     DirectoryString OPTIONAL,
- *      partyName               [1]     DirectoryString }
- * 
- * Name ::= CHOICE { RDNSequence }
- * </pre>
- */
-public class GeneralName
-    extends ASN1Encodable
-    implements ASN1Choice
-{
-    public static final int otherName                     = 0;
-    public static final int rfc822Name                    = 1;
-    public static final int dNSName                       = 2;
-    public static final int x400Address                   = 3;
-    public static final int directoryName                 = 4;
-    public static final int ediPartyName                  = 5;
-    public static final int uniformResourceIdentifier     = 6;
-    public static final int iPAddress                     = 7;
-    public static final int registeredID                  = 8;
-
-    DEREncodable      obj;
-    int               tag;
-   
-    public GeneralName(
-        X509Name  dirName)
-    {
-        this.obj = dirName;
-        this.tag = 4;
-    }
-
-    /**
-     * @deprecated this constructor seems the wrong way round! Use GeneralName(tag, name).
-     */
-    public GeneralName(
-        DERObject name, int tag)
-    {
-        this.obj = name;
-        this.tag = tag;
-    }
-
-    /**
-     * When the subjectAltName extension contains an Internet mail address,
-     * the address MUST be included as an rfc822Name. The format of an
-     * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
-     *
-     * When the subjectAltName extension contains a domain name service
-     * label, the domain name MUST be stored in the dNSName (an IA5String).
-     * The name MUST be in the "preferred name syntax," as specified by RFC
-     * 1034 [RFC 1034].
-     *
-     * When the subjectAltName extension contains a URI, the name MUST be
-     * stored in the uniformResourceIdentifier (an IA5String). The name MUST
-     * be a non-relative URL, and MUST follow the URL syntax and encoding
-     * rules specified in [RFC 1738].  The name must include both a scheme
-     * (e.g., "http" or "ftp") and a scheme-specific-part.  The scheme-
-     * specific-part must include a fully qualified domain name or IP
-     * address as the host.
-     *
-     * When the subjectAltName extension contains a iPAddress, the address
-     * MUST be stored in the octet string in "network byte order," as
-     * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
-     * each octet is the LSB of the corresponding byte in the network
-     * address. For IP Version 4, as specified in RFC 791, the octet string
-     * MUST contain exactly four octets.  For IP Version 6, as specified in
-     * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
-     * 1883].
-     */
-    public GeneralName(
-        int           tag,
-        ASN1Encodable name)
-    {
-        this.obj = name;
-        this.tag = tag;
-    }
-    
-    /**
-     * Create a GeneralName for the given tag from the passed in String.
-     * <p>
-     * This constructor can handle:
-     * <ul>
-     * <li>rfc822Name
-     * <li>iPAddress
-     * <li>directoryName
-     * <li>dNSName
-     * <li>uniformResourceIdentifier
-     * <li>registeredID
-     * </ul>
-     * For x400Address, otherName and ediPartyName there is no common string
-     * format defined.
-     * <p>
-     * Note: A directory name can be encoded in different ways into a byte
-     * representation. Be aware of this if the byte representation is used for
-     * comparing results.
-     *
-     * @param tag tag number
-     * @param name string representation of name
-     * @throws IllegalArgumentException if the string encoding is not correct or     *             not supported.
-     */
-    public GeneralName(
-        int       tag,
-        String    name)
-    {
-        this.tag = tag;
-
-        if (tag == rfc822Name || tag == dNSName || tag == uniformResourceIdentifier)
-        {
-            this.obj = new DERIA5String(name);
-        }
-        else if (tag == registeredID)
-        {
-            this.obj = new DERObjectIdentifier(name);
-        }
-        else if (tag == directoryName)
-        {
-            this.obj = new X509Name(name);
-        }
-        else if (tag == iPAddress)
-        {
-            if (IPAddress.isValid(name))
-            {
-                this.obj = new DEROctetString(Strings.toUTF8ByteArray(name));
-            }
-            else
-            {
-                throw new IllegalArgumentException("IP Address is invalid");
-            }
-        }
-        else
-        {
-            throw new IllegalArgumentException("can't process String for tag: " + tag);
-        }
-    }
-    
-    public static GeneralName getInstance(
-        Object obj)
-    {
-        if (obj == null || obj instanceof GeneralName)
-        {
-            return (GeneralName)obj;
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            ASN1TaggedObject    tagObj = (ASN1TaggedObject)obj;
-            int                 tag = tagObj.getTagNo();
-
-            switch (tag)
-            {
-            case otherName:
-                return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, false));
-            case rfc822Name:
-                return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
-            case dNSName:
-                return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
-            case x400Address:
-                throw new IllegalArgumentException("unknown tag: " + tag);
-            case directoryName:
-                return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, true));
-            case ediPartyName:
-                return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, false));
-            case uniformResourceIdentifier:
-                return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
-            case iPAddress:
-                return new GeneralName(tag, ASN1OctetString.getInstance(tagObj, false));
-            case registeredID:
-                return new GeneralName(tag, DERObjectIdentifier.getInstance(tagObj, false));
-            }
-        }
-
-        throw new IllegalArgumentException("unknown object in getInstance");
-    }
-
-    public static GeneralName getInstance(
-        ASN1TaggedObject tagObj,
-        boolean          explicit)
-    {
-        return GeneralName.getInstance(ASN1TaggedObject.getInstance(tagObj, true));
-    }
-
-    public int getTagNo()
-    {
-        return tag;
-    }
-
-    public DEREncodable getName()
-    {
-        return obj;
-    }
-
-    public String toString()
-    {
-        StringBuffer buf = new StringBuffer();
-
-        buf.append(tag);
-        buf.append(": ");
-        switch (tag)
-        {
-        case rfc822Name:
-        case dNSName:
-        case uniformResourceIdentifier:
-            buf.append(DERIA5String.getInstance(obj).getString());
-            break;
-        case directoryName:
-            buf.append(X509Name.getInstance(obj).toString());
-            break;
-        default:
-            buf.append(obj.toString());
-        }
-        return buf.toString();
-    }
-
-    public DERObject toASN1Object()
-    {
-        if (tag == directoryName)       // directoryName is explicitly tagged as it is a CHOICE
-        {
-            return new DERTaggedObject(true, tag, obj);
-        }
-        else
-        {
-            return new DERTaggedObject(false, tag, obj);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/GeneralNames.java b/azureus2/src/org/bouncycastle/asn1/x509/GeneralNames.java
deleted file mode 100644
index a2af508..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/GeneralNames.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class GeneralNames
-    extends ASN1Encodable
-{
-    ASN1Sequence            seq;
-
-    public static GeneralNames getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof GeneralNames)
-        {
-            return (GeneralNames)obj;
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            return new GeneralNames((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    public static GeneralNames getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    /**
-     * Construct a GeneralNames object containing one GeneralName.
-     * 
-     * @param name the name to be contained.
-     */
-    public GeneralNames(
-        GeneralName  name)
-    {
-        this.seq = new DERSequence(name);
-    }
-    
-    public GeneralNames(
-        ASN1Sequence  seq)
-    {
-        this.seq = seq;
-    }
-
-    public GeneralName[] getNames()
-    {
-        GeneralName[]   names = new GeneralName[seq.size()];
-        
-        for (int i = 0; i != seq.size(); i++)
-        {
-            names[i] = GeneralName.getInstance(seq.getObjectAt(i));
-        }
-        
-        return names;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * GeneralNames ::= SEQUENCE SIZE {1..MAX} OF GeneralName
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        return seq;
-    }
-
-    public String toString()
-    {
-        StringBuffer  buf = new StringBuffer();
-        String        sep = System.getProperty("line.separator");
-        GeneralName[] names = getNames();
-
-        buf.append("GeneralNames:");
-        buf.append(sep);
-
-        for (int i = 0; i != names.length; i++)
-        {
-            buf.append("    ");
-            buf.append(names[i]);
-            buf.append(sep);
-        }
-        return buf.toString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/GeneralSubtree.java b/azureus2/src/org/bouncycastle/asn1/x509/GeneralSubtree.java
deleted file mode 100644
index 326ee20..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/GeneralSubtree.java
+++ /dev/null
@@ -1,200 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-import java.math.BigInteger;
-
-/**
- * Class for containing a restriction object subtrees in NameConstraints. See
- * RFC 3280.
- * 
- * <pre>
- *       
- *       GeneralSubtree ::= SEQUENCE 
- *       {
- *         base                    GeneralName,
- *         minimum         [0]     BaseDistance DEFAULT 0,
- *         maximum         [1]     BaseDistance OPTIONAL 
- *       }
- * </pre>
- * 
- * @see org.bouncycastle.asn1.x509.NameConstraints
- * 
- */
-public class GeneralSubtree 
-    extends ASN1Encodable 
-{
-    private static final BigInteger ZERO = BigInteger.valueOf(0);
-
-    private GeneralName base;
-
-    private DERInteger minimum;
-
-    private DERInteger maximum;
-
-    public GeneralSubtree(
-        ASN1Sequence seq) 
-    {
-        base = GeneralName.getInstance(seq.getObjectAt(0));
-
-        switch (seq.size()) 
-        {
-        case 1:
-            break;
-        case 2:
-            ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
-            switch (o.getTagNo()) 
-            {
-            case 0:
-                minimum = DERInteger.getInstance(o, false);
-                break;
-            case 1:
-                maximum = DERInteger.getInstance(o, false);
-                break;
-            default:
-                throw new IllegalArgumentException("Bad tag number: "
-                        + o.getTagNo());
-            }
-            break;
-        case 3:
-            minimum = DERInteger.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(1)));
-            maximum = DERInteger.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(2)));
-            break;
-        default:
-            throw new IllegalArgumentException("Bad sequence size: "
-                    + seq.size());
-        }
-    }
-
-    /**
-     * Constructor from a given details.
-     * 
-     * According RFC 3280, the minimum and maximum fields are not used with any
-     * name forms, thus minimum MUST be zero, and maximum MUST be absent.
-     * <p>
-     * If minimum is <code>null</code>, zero is assumed, if
-     * maximum is <code>null</code>, maximum is absent.
-     * 
-     * @param base
-     *            A restriction.
-     * @param minimum
-     *            Minimum
-     * 
-     * @param maximum
-     *            Maximum
-     */
-    public GeneralSubtree(
-        GeneralName base,
-        BigInteger minimum,
-        BigInteger maximum)
-    {
-        this.base = base;
-        if (maximum != null)
-        {
-            this.maximum = new DERInteger(maximum);
-        }
-        if (minimum == null)
-        {
-            this.minimum = null;
-        }
-        else
-        {
-            this.minimum = new DERInteger(minimum);
-        }
-    }
-
-    public GeneralSubtree(GeneralName base)
-    {
-        this(base, null, null);
-    }
-
-    public static GeneralSubtree getInstance(
-        ASN1TaggedObject o,
-        boolean explicit)
-    {
-        return new GeneralSubtree(ASN1Sequence.getInstance(o, explicit));
-    }
-
-    public static GeneralSubtree getInstance(
-        Object obj)
-    {
-        if (obj == null)
-        {
-            return null;
-        }
-
-        if (obj instanceof GeneralSubtree)
-        {
-            return (GeneralSubtree) obj;
-        }
-
-        return new GeneralSubtree(ASN1Sequence.getInstance(obj));
-    }
-
-    public GeneralName getBase()
-    {
-        return base;
-    }
-
-    public BigInteger getMinimum()
-    {
-        if (minimum == null)
-        {
-            return ZERO;
-        }
-
-        return minimum.getValue();
-    }
-
-    public BigInteger getMaximum()
-    {
-        if (maximum == null)
-        {
-            return null;
-        }
-
-        return maximum.getValue();
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * 
-     * Returns:
-     * 
-     * <pre>
-     *       GeneralSubtree ::= SEQUENCE 
-     *       {
-     *         base                    GeneralName,
-     *         minimum         [0]     BaseDistance DEFAULT 0,
-     *         maximum         [1]     BaseDistance OPTIONAL 
-     *       }
-     * </pre>
-     * 
-     * @return a DERObject
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(base);
-
-        if (minimum != null && !minimum.getValue().equals(ZERO))
-        {
-            v.add(new DERTaggedObject(false, 0, minimum));
-        }
-
-        if (maximum != null)
-        {
-            v.add(new DERTaggedObject(false, 1, maximum));
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/Holder.java b/azureus2/src/org/bouncycastle/asn1/x509/Holder.java
deleted file mode 100644
index f7727de..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/Holder.java
+++ /dev/null
@@ -1,242 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * The Holder object.
- * <p>
- * For an v2 attribute certificate this is:
- * 
- * <pre>
- *            Holder ::= SEQUENCE {
- *                  baseCertificateID   [0] IssuerSerial OPTIONAL,
- *                           -- the issuer and serial number of
- *                           -- the holder's Public Key Certificate
- *                  entityName          [1] GeneralNames OPTIONAL,
- *                           -- the name of the claimant or role
- *                  objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
- *                           -- used to directly authenticate the holder,
- *                           -- for example, an executable
- *            }
- * </pre>
- * 
- * <p>
- * For an v1 attribute certificate this is:
- * 
- * <pre>
- *         subject CHOICE {
- *          baseCertificateID [0] IssuerSerial,
- *          -- associated with a Public Key Certificate
- *          subjectName [1] GeneralNames },
- *          -- associated with a name
- * </pre>
- */
-public class Holder
-    extends ASN1Encodable
-{
-    IssuerSerial baseCertificateID;
-
-    GeneralNames entityName;
-
-    ObjectDigestInfo objectDigestInfo;
-
-    private int version = 1;
-
-    public static Holder getInstance(Object obj)
-    {
-        if (obj instanceof Holder)
-        {
-            return (Holder)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new Holder((ASN1Sequence)obj);
-        }
-        else if (obj instanceof ASN1TaggedObject)
-        {
-            return new Holder((ASN1TaggedObject)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    /**
-     * Constructor for a holder for an v1 attribute certificate.
-     * 
-     * @param tagObj The ASN.1 tagged holder object.
-     */
-    public Holder(ASN1TaggedObject tagObj)
-    {
-        switch (tagObj.getTagNo())
-        {
-        case 0:
-            baseCertificateID = IssuerSerial.getInstance(tagObj, false);
-            break;
-        case 1:
-            entityName = GeneralNames.getInstance(tagObj, false);
-            break;
-        default:
-            throw new IllegalArgumentException("unknown tag in Holder");
-        }
-        version = 0;
-    }
-
-    /**
-     * Constructor for a holder for an v2 attribute certificate. *
-     * 
-     * @param seq The ASN.1 sequence.
-     */
-    public Holder(ASN1Sequence seq)
-    {
-        if (seq.size() > 3)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                + seq.size());
-        }
-
-        for (int i = 0; i != seq.size(); i++)
-        {
-            ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(seq
-                .getObjectAt(i));
-
-            switch (tObj.getTagNo())
-            {
-            case 0:
-                baseCertificateID = IssuerSerial.getInstance(tObj, false);
-                break;
-            case 1:
-                entityName = GeneralNames.getInstance(tObj, false);
-                break;
-            case 2:
-                objectDigestInfo = ObjectDigestInfo.getInstance(tObj, false);
-                break;
-            default:
-                throw new IllegalArgumentException("unknown tag in Holder");
-            }
-        }
-        version = 1;
-    }
-
-    public Holder(IssuerSerial baseCertificateID)
-    {
-        this.baseCertificateID = baseCertificateID;
-    }
-
-    /**
-     * Constructs a holder from a IssuerSerial.
-     * @param baseCertificateID The IssuerSerial.
-     * @param version The version of the attribute certificate. 
-     */
-    public Holder(IssuerSerial baseCertificateID, int version)
-    {
-        this.baseCertificateID = baseCertificateID;
-        this.version = version;
-    }
-    
-    /**
-     * Returns 1 for v2 attribute certificates or 0 for v1 attribute
-     * certificates. 
-     * @return The version of the attribute certificate.
-     */
-    public int getVersion()
-    {
-        return version;
-    }
-
-    /**
-     * Constructs a holder with an entityName for v2 attribute certificates or
-     * with a subjectName for v1 attribute certificates.
-     * 
-     * @param entityName The entity or subject name.
-     */
-    public Holder(GeneralNames entityName)
-    {
-        this.entityName = entityName;
-    }
-
-    /**
-     * Constructs a holder with an entityName for v2 attribute certificates or
-     * with a subjectName for v1 attribute certificates.
-     * 
-     * @param entityName The entity or subject name.
-     * @param version The version of the attribute certificate. 
-     */
-    public Holder(GeneralNames entityName, int version)
-    {
-        this.entityName = entityName;
-        this.version = version;
-    }
-    
-    /**
-     * Constructs a holder from an object digest info.
-     * 
-     * @param objectDigestInfo The object digest info object.
-     */
-    public Holder(ObjectDigestInfo objectDigestInfo)
-    {
-        this.objectDigestInfo = objectDigestInfo;
-    }
-
-    public IssuerSerial getBaseCertificateID()
-    {
-        return baseCertificateID;
-    }
-
-    /**
-     * Returns the entityName for an v2 attribute certificate or the subjectName
-     * for an v1 attribute certificate.
-     * 
-     * @return The entityname or subjectname.
-     */
-    public GeneralNames getEntityName()
-    {
-        return entityName;
-    }
-
-    public ObjectDigestInfo getObjectDigestInfo()
-    {
-        return objectDigestInfo;
-    }
-
-    public DERObject toASN1Object()
-    {
-        if (version == 1)
-        {
-            ASN1EncodableVector v = new ASN1EncodableVector();
-
-            if (baseCertificateID != null)
-            {
-                v.add(new DERTaggedObject(false, 0, baseCertificateID));
-            }
-
-            if (entityName != null)
-            {
-                v.add(new DERTaggedObject(false, 1, entityName));
-            }
-
-            if (objectDigestInfo != null)
-            {
-                v.add(new DERTaggedObject(false, 2, objectDigestInfo));
-            }
-
-            return new DERSequence(v);
-        }
-        else
-        {
-            if (entityName != null)
-            {
-                return new DERTaggedObject(false, 1, entityName);
-            }
-            else
-            {
-                return new DERTaggedObject(false, 0, baseCertificateID);
-            }
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/IetfAttrSyntax.java b/azureus2/src/org/bouncycastle/asn1/x509/IetfAttrSyntax.java
deleted file mode 100644
index 07e07cf..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/IetfAttrSyntax.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTF8String;
-
-/**
- * Implementation of <code>IetfAttrSyntax</code> as specified by RFC3281.
- */
-public class IetfAttrSyntax
-    extends ASN1Encodable
-{
-    public static final int VALUE_OCTETS    = 1;
-    public static final int VALUE_OID       = 2;
-    public static final int VALUE_UTF8      = 3;
-    GeneralNames            policyAuthority = null;
-    Vector                  values          = new Vector();
-    int                     valueChoice     = -1;
-
-    /**
-     *  
-     */
-    public IetfAttrSyntax(ASN1Sequence seq)
-    {
-        int i = 0;
-
-        if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
-        {
-            policyAuthority = GeneralNames.getInstance(((ASN1TaggedObject)seq.getObjectAt(0)), false);
-            i++;
-        }
-        else if (seq.size() == 2)
-        { // VOMS fix
-            policyAuthority = GeneralNames.getInstance(seq.getObjectAt(0));
-            i++;
-        }
-
-        if (!(seq.getObjectAt(i) instanceof ASN1Sequence))
-        {
-            throw new IllegalArgumentException("Non-IetfAttrSyntax encoding");
-        }
-
-        seq = (ASN1Sequence)seq.getObjectAt(i);
-
-        for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
-        {
-            DERObject obj = (DERObject)e.nextElement();
-            int type;
-
-            if (obj instanceof DERObjectIdentifier)
-            {
-                type = VALUE_OID;
-            }
-            else if (obj instanceof DERUTF8String)
-            {
-                type = VALUE_UTF8;
-            }
-            else if (obj instanceof DEROctetString)
-            {
-                type = VALUE_OCTETS;
-            }
-            else
-            {
-                throw new IllegalArgumentException("Bad value type encoding IetfAttrSyntax");
-            }
-
-            if (valueChoice < 0)
-            {
-                valueChoice = type;
-            }
-
-            if (type != valueChoice)
-            {
-                throw new IllegalArgumentException("Mix of value types in IetfAttrSyntax");
-            }
-
-            values.addElement(obj);
-        }
-    }
-
-    public GeneralNames getPolicyAuthority()
-    {
-        return policyAuthority;
-    }
-
-    public int getValueType()
-    {
-        return valueChoice;
-    }
-
-    public Object[] getValues()
-    {
-        if (this.getValueType() == VALUE_OCTETS)
-        {
-            ASN1OctetString[] tmp = new ASN1OctetString[values.size()];
-            
-            for (int i = 0; i != tmp.length; i++)
-            {
-                tmp[i] = (ASN1OctetString)values.elementAt(i);
-            }
-            
-            return tmp;
-        }
-        else if (this.getValueType() == VALUE_OID)
-        {
-            DERObjectIdentifier[] tmp = new DERObjectIdentifier[values.size()];
-            
-            for (int i = 0; i != tmp.length; i++)
-            {
-                tmp[i] = (DERObjectIdentifier)values.elementAt(i);
-            }
-            
-            return tmp;
-        }
-        else
-        {
-            DERUTF8String[] tmp = new DERUTF8String[values.size()];
-            
-            for (int i = 0; i != tmp.length; i++)
-            {
-                tmp[i] = (DERUTF8String)values.elementAt(i);
-            }
-            
-            return tmp;
-        }
-    }
-
-    /**
-     * 
-     * <pre>
-     * 
-     *  IetfAttrSyntax ::= SEQUENCE {
-     *    policyAuthority [0] GeneralNames OPTIONAL,
-     *    values SEQUENCE OF CHOICE {
-     *      octets OCTET STRING,
-     *      oid OBJECT IDENTIFIER,
-     *      string UTF8String
-     *    }
-     *  }
-     *  
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        if (policyAuthority != null)
-        {
-            v.add(new DERTaggedObject(0, policyAuthority));
-        }
-
-        ASN1EncodableVector v2 = new ASN1EncodableVector();
-
-        for (Enumeration i = values.elements(); i.hasMoreElements();)
-        {
-            v2.add((ASN1Encodable)i.nextElement());
-        }
-
-        v.add(new DERSequence(v2));
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/IssuerSerial.java b/azureus2/src/org/bouncycastle/asn1/x509/IssuerSerial.java
deleted file mode 100644
index ceb639f..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/IssuerSerial.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class IssuerSerial
-    extends ASN1Encodable
-{
-    GeneralNames            issuer;
-    DERInteger              serial;
-    DERBitString            issuerUID;
-
-    public static IssuerSerial getInstance(
-            Object  obj)
-    {
-        if (obj == null || obj instanceof IssuerSerial)
-        {
-            return (IssuerSerial)obj;
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            return new IssuerSerial((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    public static IssuerSerial getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-    
-    public IssuerSerial(
-        ASN1Sequence    seq)
-    {
-        if (seq.size() != 2 && seq.size() != 3)
-        {
-            throw new IllegalArgumentException("Bad sequence size: " + seq.size());
-        }
-        
-        issuer = GeneralNames.getInstance(seq.getObjectAt(0));
-        serial = DERInteger.getInstance(seq.getObjectAt(1));
-
-        if (seq.size() == 3)
-        {
-            issuerUID = DERBitString.getInstance(seq.getObjectAt(2));
-        }
-    }
-    
-    public IssuerSerial(
-        GeneralNames    issuer,
-        DERInteger      serial)
-    {
-        this.issuer = issuer;
-        this.serial = serial;
-    }
-
-    public GeneralNames getIssuer()
-    {
-        return issuer;
-    }
-
-    public DERInteger getSerial()
-    {
-        return serial;
-    }
-
-    public DERBitString getIssuerUID()
-    {
-        return issuerUID;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  IssuerSerial  ::=  SEQUENCE {
-     *       issuer         GeneralNames,
-     *       serial         CertificateSerialNumber,
-     *       issuerUID      UniqueIdentifier OPTIONAL
-     *  }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(issuer);
-        v.add(serial);
-
-        if (issuerUID != null)
-        {
-            v.add(issuerUID);
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java b/azureus2/src/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java
deleted file mode 100644
index 4962ade..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java
+++ /dev/null
@@ -1,256 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBoolean;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * <pre>
- * IssuingDistributionPoint ::= SEQUENCE { 
- *   distributionPoint          [0] DistributionPointName OPTIONAL, 
- *   onlyContainsUserCerts      [1] BOOLEAN DEFAULT FALSE, 
- *   onlyContainsCACerts        [2] BOOLEAN DEFAULT FALSE, 
- *   onlySomeReasons            [3] ReasonFlags OPTIONAL, 
- *   indirectCRL                [4] BOOLEAN DEFAULT FALSE,
- *   onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
- * </pre>
- */
-public class IssuingDistributionPoint
-    extends ASN1Encodable
-{
-    private DistributionPointName distributionPoint;
-
-    private boolean onlyContainsUserCerts;
-
-    private boolean onlyContainsCACerts;
-
-    private ReasonFlags onlySomeReasons;
-
-    private boolean indirectCRL;
-
-    private boolean onlyContainsAttributeCerts;
-
-    private ASN1Sequence seq;
-
-    public static IssuingDistributionPoint getInstance(
-        ASN1TaggedObject obj,
-        boolean explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static IssuingDistributionPoint getInstance(
-        Object obj)
-    {
-        if (obj == null || obj instanceof IssuingDistributionPoint)
-        {
-            return (IssuingDistributionPoint)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new IssuingDistributionPoint((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    /**
-     * Constructor from given details.
-     * 
-     * @param distributionPoint
-     *            May contain an URI as pointer to most current CRL.
-     * @param onlyContainsUserCerts Covers revocation information for end certificates.
-     * @param onlyContainsCACerts Covers revocation information for CA certificates.
-     * 
-     * @param onlySomeReasons
-     *            Which revocation reasons does this point cover.
-     * @param indirectCRL
-     *            If <code>true</code> then the CRL contains revocation
-     *            information about certificates ssued by other CAs.
-     * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
-     */
-    public IssuingDistributionPoint(
-        DistributionPointName distributionPoint,
-        boolean onlyContainsUserCerts,
-        boolean onlyContainsCACerts,
-        ReasonFlags onlySomeReasons,
-        boolean indirectCRL,
-        boolean onlyContainsAttributeCerts)
-    {
-        this.distributionPoint = distributionPoint;
-        this.indirectCRL = indirectCRL;
-        this.onlyContainsAttributeCerts = onlyContainsAttributeCerts;
-        this.onlyContainsCACerts = onlyContainsCACerts;
-        this.onlyContainsUserCerts = onlyContainsUserCerts;
-        this.onlySomeReasons = onlySomeReasons;
-
-        ASN1EncodableVector vec = new ASN1EncodableVector();
-        if (distributionPoint != null)
-        {                                    // CHOICE item so explicitly tagged
-            vec.add(new DERTaggedObject(true, 0, distributionPoint));
-        }
-        if (!onlyContainsUserCerts)
-        {
-            vec.add(new DERTaggedObject(false, 1, new DERBoolean(true)));
-        }
-        if (!onlyContainsCACerts)
-        {
-            vec.add(new DERTaggedObject(false, 2, new DERBoolean(true)));
-        }
-        if (onlySomeReasons != null)
-        {
-            vec.add(new DERTaggedObject(false, 3, onlySomeReasons));
-        }
-        if (!indirectCRL)
-        {
-            vec.add(new DERTaggedObject(false, 4, new DERBoolean(true)));
-        }
-        if (!onlyContainsAttributeCerts)
-        {
-            vec.add(new DERTaggedObject(false, 5, new DERBoolean(true)));
-        }
-
-        seq = new DERSequence(vec);
-    }
-
-    /**
-     * Constructor from ASN1Sequence
-     */
-    public IssuingDistributionPoint(
-        ASN1Sequence seq)
-    {
-        this.seq = seq;
-
-        for (int i = 0; i != seq.size(); i++)
-        {
-            ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
-
-            switch (o.getTagNo())
-            {
-            case 0:
-                                                    // CHOICE so explicit
-                distributionPoint = DistributionPointName.getInstance(o, true);
-                break;
-            case 1:
-                onlyContainsUserCerts = DERBoolean.getInstance(o, false).isTrue();
-                break;
-            case 2:
-                onlyContainsCACerts = DERBoolean.getInstance(o, false).isTrue();
-                break;
-            case 3:
-                onlySomeReasons = new ReasonFlags(ReasonFlags.getInstance(o, false));
-                break;
-            case 4:
-                indirectCRL = DERBoolean.getInstance(o, false).isTrue();
-                break;
-            case 5:
-                onlyContainsAttributeCerts = DERBoolean.getInstance(o, false).isTrue();
-                break;
-            default:
-                throw new IllegalArgumentException(
-                        "unknown tag in IssuingDistributionPoint");
-            }
-        }
-    }
-
-    public boolean onlyContainsUserCerts()
-    {
-        return onlyContainsUserCerts;
-    }
-
-    public boolean onlyContainsCACerts()
-    {
-        return onlyContainsCACerts;
-    }
-
-    public boolean isIndirectCRL()
-    {
-        return indirectCRL;
-    }
-
-    public boolean onlyContainsAttributeCerts()
-    {
-        return onlyContainsAttributeCerts;
-    }
-
-    /**
-     * @return Returns the distributionPoint.
-     */
-    public DistributionPointName getDistributionPoint()
-    {
-        return distributionPoint;
-    }
-
-    /**
-     * @return Returns the onlySomeReasons.
-     */
-    public ReasonFlags getOnlySomeReasons()
-    {
-        return onlySomeReasons;
-    }
-
-    public DERObject toASN1Object()
-    {
-        return seq;
-    }
-
-    public String toString()
-    {
-        String       sep = System.getProperty("line.separator");
-        StringBuffer buf = new StringBuffer();
-
-        buf.append("IssuingDistributionPoint: [");
-        buf.append(sep);
-        if (distributionPoint != null)
-        {
-            appendObject(buf, sep, "distributionPoint", distributionPoint.toString());
-        }
-        if (onlyContainsUserCerts)
-        {
-            appendObject(buf, sep, "onlyContainsUserCerts", booleanToString(onlyContainsUserCerts));
-        }
-        if (onlyContainsCACerts)
-        {
-            appendObject(buf, sep, "onlyContainsCACerts", booleanToString(onlyContainsCACerts));
-        }
-        if (onlySomeReasons != null)
-        {
-            appendObject(buf, sep, "onlySomeReasons", onlySomeReasons.toString());
-        }
-        if (onlyContainsAttributeCerts)
-        {
-            appendObject(buf, sep, "onlyContainsAttributeCerts", booleanToString(onlyContainsAttributeCerts));
-        }
-        if (indirectCRL)
-        {
-            appendObject(buf, sep, "indirectCRL", booleanToString(indirectCRL));
-        }
-        buf.append("]");
-        buf.append(sep);
-        return buf.toString();
-    }
-
-    private void appendObject(StringBuffer buf, String sep, String name, String value)
-    {
-        String       indent = "    ";
-
-        buf.append(indent);
-        buf.append(name);
-        buf.append(":");
-        buf.append(sep);
-        buf.append(indent);
-        buf.append(indent);
-        buf.append(value);
-        buf.append(sep);
-    }
-
-    private String booleanToString(boolean value)
-    {
-        return value ? "true" : "false";
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/KeyPurposeId.java b/azureus2/src/org/bouncycastle/asn1/x509/KeyPurposeId.java
deleted file mode 100644
index b247e09..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/KeyPurposeId.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-/**
- * The KeyPurposeId object.
- * <pre>
- *     KeyPurposeId ::= OBJECT IDENTIFIER
- * </pre>
- */
-public class KeyPurposeId
-    extends DERObjectIdentifier
-{
-    private static final String id_kp = "1.3.6.1.5.5.7.3";
-
-    private KeyPurposeId(
-        String  id)
-    {
-        super(id);
-    }
-
-    public static final KeyPurposeId anyExtendedKeyUsage = new KeyPurposeId(X509Extensions.ExtendedKeyUsage.getId() + ".0");
-    public static final KeyPurposeId id_kp_serverAuth = new KeyPurposeId(id_kp + ".1");
-    public static final KeyPurposeId id_kp_clientAuth = new KeyPurposeId(id_kp + ".2");
-    public static final KeyPurposeId id_kp_codeSigning = new KeyPurposeId(id_kp + ".3");
-    public static final KeyPurposeId id_kp_emailProtection = new KeyPurposeId(id_kp + ".4");
-    public static final KeyPurposeId id_kp_ipsecEndSystem = new KeyPurposeId(id_kp + ".5");
-    public static final KeyPurposeId id_kp_ipsecTunnel = new KeyPurposeId(id_kp + ".6");
-    public static final KeyPurposeId id_kp_ipsecUser = new KeyPurposeId(id_kp + ".7");
-    public static final KeyPurposeId id_kp_timeStamping = new KeyPurposeId(id_kp + ".8");
-    public static final KeyPurposeId id_kp_OCSPSigning = new KeyPurposeId(id_kp + ".9");
-
-    //
-    // microsoft key purpose ids
-    //
-    public static final KeyPurposeId id_kp_smartcardlogon = new KeyPurposeId("1.3.6.1.4.1.311.20.2.2");
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/KeyUsage.java b/azureus2/src/org/bouncycastle/asn1/x509/KeyUsage.java
deleted file mode 100644
index 3ffd94b..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/KeyUsage.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DERBitString;
-
-/**
- * The KeyUsage object.
- * <pre>
- *    id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
- *
- *    KeyUsage ::= BIT STRING {
- *         digitalSignature        (0),
- *         nonRepudiation          (1),
- *         keyEncipherment         (2),
- *         dataEncipherment        (3),
- *         keyAgreement            (4),
- *         keyCertSign             (5),
- *         cRLSign                 (6),
- *         encipherOnly            (7),
- *         decipherOnly            (8) }
- * </pre>
- */
-public class KeyUsage
-    extends DERBitString
-{
-    public static final int        digitalSignature = (1 << 7); 
-    public static final int        nonRepudiation   = (1 << 6);
-    public static final int        keyEncipherment  = (1 << 5);
-    public static final int        dataEncipherment = (1 << 4);
-    public static final int        keyAgreement     = (1 << 3);
-    public static final int        keyCertSign      = (1 << 2);
-    public static final int        cRLSign          = (1 << 1);
-    public static final int        encipherOnly     = (1 << 0);
-    public static final int        decipherOnly     = (1 << 15);
-
-    public static DERBitString getInstance(Object obj)   // needs to be DERBitString for other VMs
-    {
-        if (obj instanceof KeyUsage)
-        {
-            return (KeyUsage)obj;
-        }
-
-        if (obj instanceof X509Extension)
-        {
-            return new KeyUsage(DERBitString.getInstance(X509Extension.convertValueToObject((X509Extension)obj)));
-        }
-
-        return new KeyUsage(DERBitString.getInstance(obj));
-    }
-    
-    /**
-     * Basic constructor.
-     * 
-     * @param usage - the bitwise OR of the Key Usage flags giving the
-     * allowed uses for the key.
-     * e.g. (KeyUsage.keyEncipherment | KeyUsage.dataEncipherment)
-     */
-    public KeyUsage(
-        int usage)
-    {
-        super(getBytes(usage), getPadBits(usage));
-    }
-
-    public KeyUsage(
-        DERBitString usage)
-    {
-        super(usage.getBytes(), usage.getPadBits());
-    }
-
-    public String toString()
-    {
-        if (data.length == 1)
-        {
-            return "KeyUsage: 0x" + Integer.toHexString(data[0] & 0xff);
-        }
-        return "KeyUsage: 0x" + Integer.toHexString((data[1] & 0xff) << 8 | (data[0] & 0xff));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/NameConstraints.java b/azureus2/src/org/bouncycastle/asn1/x509/NameConstraints.java
deleted file mode 100644
index 1383d39..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/NameConstraints.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class NameConstraints
-    extends ASN1Encodable
-{
-    private ASN1Sequence permitted, excluded;
-
-    public NameConstraints(ASN1Sequence seq)
-    {
-        Enumeration e = seq.getObjects();
-        while (e.hasMoreElements())
-        {
-            ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
-            switch (o.getTagNo())
-            {
-            case 0:
-                permitted = ASN1Sequence.getInstance(o, false);
-                break;
-            case 1:
-                excluded = ASN1Sequence.getInstance(o, false);
-                break;
-            }
-        }
-    }
-
-    /**
-     * Constructor from a given details.
-     * 
-     * <p>
-     * permitted and excluded are Vectors of GeneralSubtree objects.
-     * 
-     * @param permitted
-     *            Permitted subtrees
-     * @param excluded
-     *            Excludes subtrees
-     */
-    public NameConstraints(
-        Vector permitted,
-        Vector excluded)
-    {
-        if (permitted != null)
-        {
-            this.permitted = createSequence(permitted);
-        }
-        if (excluded != null)
-        {
-            this.excluded = createSequence(excluded);
-        }
-    }
-
-    private DERSequence createSequence(Vector subtree)
-    {
-        ASN1EncodableVector vec = new ASN1EncodableVector();
-        Enumeration e = subtree.elements(); 
-        while (e.hasMoreElements())
-        {
-            vec.add((GeneralSubtree)e.nextElement());
-        }
-        
-        return new DERSequence(vec);
-    }
-
-    public ASN1Sequence getPermittedSubtrees() 
-    {
-        return permitted;
-    }
-
-    public ASN1Sequence getExcludedSubtrees() 
-    {
-        return excluded;
-    }
-
-    /*
-     * NameConstraints ::= SEQUENCE { permittedSubtrees [0] GeneralSubtrees
-     * OPTIONAL, excludedSubtrees [1] GeneralSubtrees OPTIONAL }
-     */
-    public DERObject toASN1Object() 
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        if (permitted != null) 
-        {
-            v.add(new DERTaggedObject(false, 0, permitted));
-        }
-
-        if (excluded != null) 
-        {
-            v.add(new DERTaggedObject(false, 1, excluded));
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/NoticeReference.java b/azureus2/src/org/bouncycastle/asn1/x509/NoticeReference.java
deleted file mode 100644
index 0bc639a..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/NoticeReference.java
+++ /dev/null
@@ -1,155 +0,0 @@
-
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <code>NoticeReference</code> class, used in
- * <code>CertificatePolicies</code> X509 V3 extensions
- * (in policy qualifiers).
- * 
- * <pre>
- *  NoticeReference ::= SEQUENCE {
- *      organization     DisplayText,
- *      noticeNumbers    SEQUENCE OF INTEGER }
- *
- * </pre> 
- * 
- * @see PolicyQualifierInfo
- * @see PolicyInformation
- */
-public class NoticeReference 
-    extends ASN1Encodable
-{
-   private DisplayText organization;
-   private ASN1Sequence noticeNumbers;
-
-   /**
-    * Creates a new <code>NoticeReference</code> instance.
-    *
-    * @param orgName a <code>String</code> value
-    * @param numbers a <code>Vector</code> value
-    */
-   public NoticeReference(
-       String orgName,
-       Vector numbers) 
-   {
-      organization = new DisplayText(orgName);
-
-      Object o = numbers.elementAt(0);
-
-      ASN1EncodableVector av = new ASN1EncodableVector();
-      if (o instanceof Integer)
-      {
-         Enumeration it = numbers.elements();
-
-         while (it.hasMoreElements())
-         {
-            Integer nm = (Integer) it.nextElement();
-               DERInteger di = new DERInteger(nm.intValue());
-            av.add (di);
-         }
-      }
-
-      noticeNumbers = new DERSequence(av);
-   }
-
-   /**
-    * Creates a new <code>NoticeReference</code> instance.
-    *
-    * @param orgName a <code>String</code> value
-    * @param numbers an <code>ASN1EncodableVector</code> value
-    */
-   public NoticeReference(
-       String orgName, 
-       ASN1Sequence numbers) 
-   {
-       organization = new DisplayText (orgName);
-       noticeNumbers = numbers;
-   }
-
-   /**
-    * Creates a new <code>NoticeReference</code> instance.
-    *
-    * @param displayTextType an <code>int</code> value
-    * @param orgName a <code>String</code> value
-    * @param numbers an <code>ASN1EncodableVector</code> value
-    */
-   public NoticeReference(
-       int displayTextType,
-       String orgName,
-       ASN1Sequence numbers) 
-   {
-       organization = new DisplayText(displayTextType, 
-                                     orgName);
-       noticeNumbers = numbers;
-   }
-
-   /**
-    * Creates a new <code>NoticeReference</code> instance.
-    * <p>Useful for reconstructing a <code>NoticeReference</code>
-    * instance from its encodable/encoded form. 
-    *
-    * @param as an <code>ASN1Sequence</code> value obtained from either
-    * calling @{link toASN1Object()} for a <code>NoticeReference</code>
-    * instance or from parsing it from a DER-encoded stream. 
-    */
-   public NoticeReference(
-       ASN1Sequence as) 
-   {
-       if (as.size() != 2)
-       {
-            throw new IllegalArgumentException("Bad sequence size: "
-                    + as.size());
-       }
-
-       organization = DisplayText.getInstance(as.getObjectAt(0));
-       noticeNumbers = ASN1Sequence.getInstance(as.getObjectAt(1));
-   }
-
-   public static NoticeReference getInstance(
-       Object as) 
-   {
-      if (as instanceof NoticeReference)
-      {
-          return (NoticeReference)as;
-      }
-      else if (as instanceof ASN1Sequence)
-      {
-          return new NoticeReference((ASN1Sequence)as);
-      }
-
-      throw new IllegalArgumentException("unknown object in getInstance.");
-   }
-   
-   public DisplayText getOrganization()
-   {
-       return organization;
-   }
-   
-   public ASN1Sequence getNoticeNumbers()
-   {
-       return noticeNumbers;
-   }
-   
-   /**
-    * Describe <code>toASN1Object</code> method here.
-    *
-    * @return a <code>DERObject</code> value
-    */
-   public DERObject toASN1Object() 
-   {
-      ASN1EncodableVector av = new ASN1EncodableVector();
-      av.add (organization);
-      av.add (noticeNumbers);
-      return new DERSequence (av);
-   }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/ObjectDigestInfo.java b/azureus2/src/org/bouncycastle/asn1/x509/ObjectDigestInfo.java
deleted file mode 100644
index b881509..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/ObjectDigestInfo.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DEREnumerated;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * ObjectDigestInfo ASN.1 structure used in v2 attribute certificates.
- * 
- * <pre>
- *  
- *    ObjectDigestInfo ::= SEQUENCE {
- *         digestedObjectType  ENUMERATED {
- *                 publicKey            (0),
- *                 publicKeyCert        (1),
- *                 otherObjectTypes     (2) },
- *                         -- otherObjectTypes MUST NOT
- *                         -- be used in this profile
- *         otherObjectTypeID   OBJECT IDENTIFIER OPTIONAL,
- *         digestAlgorithm     AlgorithmIdentifier,
- *         objectDigest        BIT STRING
- *    }
- *   
- * </pre>
- * 
- */
-public class ObjectDigestInfo
-    extends ASN1Encodable
-{
-    /**
-     * The public key is hashed.
-     */
-    public final static int publicKey = 0;
-
-    /**
-     * The public key certificate is hashed.
-     */
-    public final static int publicKeyCert = 1;
-
-    /**
-     * An other object is hashed.
-     */
-    public final static int otherObjectDigest = 2;
-
-    DEREnumerated digestedObjectType;
-
-    DERObjectIdentifier otherObjectTypeID;
-
-    AlgorithmIdentifier digestAlgorithm;
-
-    DERBitString objectDigest;
-
-    public static ObjectDigestInfo getInstance(
-        Object obj)
-    {
-        if (obj == null || obj instanceof ObjectDigestInfo)
-        {
-            return (ObjectDigestInfo)obj;
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            return new ObjectDigestInfo((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: "
-            + obj.getClass().getName());
-    }
-
-    public static ObjectDigestInfo getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    /**
-     * Constructor from given details.
-     * <p>
-     * If <code>digestedObjectType</code> is not {@link #publicKeyCert} or
-     * {@link #publicKey} <code>otherObjectTypeID</code> must be given,
-     * otherwise it is ignored.
-     * 
-     * @param digestedObjectType The digest object type.
-     * @param otherObjectTypeID The object type ID for
-     *            <code>otherObjectDigest</code>.
-     * @param digestAlgorithm The algorithm identifier for the hash.
-     * @param objectDigest The hash value.
-     */
-    public ObjectDigestInfo(
-        int digestedObjectType,
-        String otherObjectTypeID,
-        AlgorithmIdentifier digestAlgorithm,
-        byte[] objectDigest)
-    {
-        this.digestedObjectType = new DEREnumerated(digestedObjectType);
-        if (digestedObjectType == otherObjectDigest)
-        {
-            this.otherObjectTypeID = new DERObjectIdentifier(otherObjectTypeID);
-        }
-
-        this.digestAlgorithm = digestAlgorithm; 
-
-        this.objectDigest = new DERBitString(objectDigest);
-    }
-
-    private ObjectDigestInfo(
-        ASN1Sequence seq)
-    {
-        if (seq.size() > 4 || seq.size() < 3)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                + seq.size());
-        }
-
-        digestedObjectType = DEREnumerated.getInstance(seq.getObjectAt(0));
-
-        int offset = 0;
-
-        if (seq.size() == 4)
-        {
-            otherObjectTypeID = DERObjectIdentifier.getInstance(seq.getObjectAt(1));
-            offset++;
-        }
-
-        digestAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1 + offset));
-
-        objectDigest = DERBitString.getInstance(seq.getObjectAt(2 + offset));
-    }
-
-    public DEREnumerated getDigestedObjectType()
-    {
-        return digestedObjectType;
-    }
-
-    public DERObjectIdentifier getOtherObjectTypeID()
-    {
-        return otherObjectTypeID;
-    }
-
-    public AlgorithmIdentifier getDigestAlgorithm()
-    {
-        return digestAlgorithm;
-    }
-
-    public DERBitString getObjectDigest()
-    {
-        return objectDigest;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * 
-     * <pre>
-     *  
-     *    ObjectDigestInfo ::= SEQUENCE {
-     *         digestedObjectType  ENUMERATED {
-     *                 publicKey            (0),
-     *                 publicKeyCert        (1),
-     *                 otherObjectTypes     (2) },
-     *                         -- otherObjectTypes MUST NOT
-     *                         -- be used in this profile
-     *         otherObjectTypeID   OBJECT IDENTIFIER OPTIONAL,
-     *         digestAlgorithm     AlgorithmIdentifier,
-     *         objectDigest        BIT STRING
-     *    }
-     *   
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(digestedObjectType);
-
-        if (otherObjectTypeID != null)
-        {
-            v.add(otherObjectTypeID);
-        }
-
-        v.add(digestAlgorithm);
-        v.add(objectDigest);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/PolicyInformation.java b/azureus2/src/org/bouncycastle/asn1/x509/PolicyInformation.java
deleted file mode 100644
index b4373b0..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/PolicyInformation.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-public class PolicyInformation
-    extends ASN1Encodable
-{
-    private DERObjectIdentifier   policyIdentifier;
-    private ASN1Sequence          policyQualifiers;
-
-    public PolicyInformation(
-        ASN1Sequence seq)
-    {
-        if (seq.size() < 1 || seq.size() > 2)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                    + seq.size());
-        }
-
-        policyIdentifier = DERObjectIdentifier.getInstance(seq.getObjectAt(0));
-
-        if (seq.size() > 1)
-        {
-            policyQualifiers = ASN1Sequence.getInstance(seq.getObjectAt(1));
-        }
-    }
-
-    public PolicyInformation(
-        DERObjectIdentifier policyIdentifier)
-    {
-        this.policyIdentifier = policyIdentifier;
-    }
-
-    public PolicyInformation(
-        DERObjectIdentifier policyIdentifier,
-        ASN1Sequence        policyQualifiers)
-    {
-        this.policyIdentifier = policyIdentifier;
-        this.policyQualifiers = policyQualifiers;
-    }
-
-    public static PolicyInformation getInstance(
-        Object obj)
-    {
-        if (obj == null || obj instanceof PolicyInformation)
-        {
-            return (PolicyInformation)obj;
-        }
-
-        return new PolicyInformation(ASN1Sequence.getInstance(obj));
-    }
-
-    public DERObjectIdentifier getPolicyIdentifier()
-    {
-        return policyIdentifier;
-    }
-    
-    public ASN1Sequence getPolicyQualifiers()
-    {
-        return policyQualifiers;
-    }
-    
-    /* 
-     * PolicyInformation ::= SEQUENCE {
-     *      policyIdentifier   CertPolicyId,
-     *      policyQualifiers   SEQUENCE SIZE (1..MAX) OF
-     *              PolicyQualifierInfo OPTIONAL }
-     */ 
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-        
-        v.add(policyIdentifier);
-
-        if (policyQualifiers != null)
-        {
-            v.add(policyQualifiers);
-        }
-        
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/PolicyMappings.java b/azureus2/src/org/bouncycastle/asn1/x509/PolicyMappings.java
deleted file mode 100644
index df78ec4..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/PolicyMappings.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Hashtable;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * PolicyMappings V3 extension, described in RFC3280.
- * <pre>
- *    PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
- *      issuerDomainPolicy      CertPolicyId,
- *      subjectDomainPolicy     CertPolicyId }
- * </pre>
- *
- * @see <a href="http://www.faqs.org/rfc/rfc3280.txt">RFC 3280, section 4.2.1.6</a>
- */
-public class PolicyMappings
-    extends ASN1Encodable
-{
-   ASN1Sequence seq = null;
-
-   /**
-    * Creates a new <code>PolicyMappings</code> instance.
-    *
-    * @param seq an <code>ASN1Sequence</code> constructed as specified
-    * in RFC 3280
-    */
-   public PolicyMappings (ASN1Sequence seq) 
-      {
-         this.seq = seq;
-      }
-
-   /**
-    * Creates a new <code>PolicyMappings</code> instance.
-    *
-    * @param mappings a <code>HashMap</code> value that maps
-    * <code>String</code> oids
-    * to other <code>String</code> oids. 
-    */
-   public PolicyMappings (Hashtable mappings) 
-      {
-         ASN1EncodableVector dev = new ASN1EncodableVector();
-         Enumeration it = mappings.keys();
-
-         while (it.hasMoreElements())
-         {
-            String idp = (String) it.nextElement();
-            String sdp = (String) mappings.get(idp);
-            ASN1EncodableVector dv = new ASN1EncodableVector();
-            dv.add(new DERObjectIdentifier(idp));
-            dv.add(new DERObjectIdentifier(sdp));
-            dev.add(new DERSequence(dv));
-         }
-
-         seq = new DERSequence(dev);
-      }
-
-   public DERObject toASN1Object() 
-      {
-         return seq;
-      }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/PolicyQualifierId.java b/azureus2/src/org/bouncycastle/asn1/x509/PolicyQualifierId.java
deleted file mode 100644
index 2678057..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/PolicyQualifierId.java
+++ /dev/null
@@ -1,31 +0,0 @@
-
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-/**
- * PolicyQualifierId, used in the CertificatePolicies
- * X509V3 extension.
- * 
- * <pre>
- *    id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
- *    id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
- *    id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
- *  PolicyQualifierId ::=
- *       OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice)
- * </pre>
- */
-public class PolicyQualifierId extends DERObjectIdentifier 
-{
-   private static final String id_qt = "1.3.6.1.5.5.7.2";
-
-   private PolicyQualifierId(String id) 
-      {
-         super(id);
-      }
-   
-   public static final PolicyQualifierId id_qt_cps =
-       new PolicyQualifierId(id_qt + ".1");
-   public static final PolicyQualifierId id_qt_unotice =
-       new PolicyQualifierId(id_qt + ".2");
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java b/azureus2/src/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java
deleted file mode 100644
index 6e97f70..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * Policy qualifiers, used in the X509V3 CertificatePolicies
- * extension.
- * 
- * <pre>
- *   PolicyQualifierInfo ::= SEQUENCE {
- *       policyQualifierId  PolicyQualifierId,
- *       qualifier          ANY DEFINED BY policyQualifierId }
- * </pre>
- */
-public class PolicyQualifierInfo
-    extends ASN1Encodable
-{
-   private DERObjectIdentifier policyQualifierId;
-   private DEREncodable        qualifier;
-
-   /**
-    * Creates a new <code>PolicyQualifierInfo</code> instance.
-    *
-    * @param policyQualifierId a <code>PolicyQualifierId</code> value
-    * @param qualifier the qualifier, defined by the above field.
-    */
-   public PolicyQualifierInfo(
-       DERObjectIdentifier policyQualifierId,
-       DEREncodable qualifier) 
-   {
-      this.policyQualifierId = policyQualifierId;
-      this.qualifier = qualifier;
-   }
-
-   /**
-    * Creates a new <code>PolicyQualifierInfo</code> containing a
-    * cPSuri qualifier.
-    *
-    * @param cps the CPS (certification practice statement) uri as a
-    * <code>String</code>.
-    */
-   public PolicyQualifierInfo(
-       String cps) 
-   {
-      policyQualifierId = PolicyQualifierId.id_qt_cps;
-      qualifier = new DERIA5String (cps);
-   }
-
-   /**
-    * Creates a new <code>PolicyQualifierInfo</code> instance.
-    *
-    * @param as <code>PolicyQualifierInfo</code> X509 structure
-    * encoded as an ASN1Sequence. 
-    */
-   public PolicyQualifierInfo(
-       ASN1Sequence as)
-   {
-        if (as.size() != 2)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                    + as.size());
-        }
-
-        policyQualifierId = DERObjectIdentifier.getInstance(as.getObjectAt(0));
-        qualifier = as.getObjectAt(1);
-   }
-
-   public static PolicyQualifierInfo getInstance(
-       Object as) 
-   {
-        if (as instanceof PolicyQualifierInfo)
-        {
-            return (PolicyQualifierInfo)as;
-        }
-        else if (as instanceof ASN1Sequence)
-        {
-            return new PolicyQualifierInfo((ASN1Sequence)as);
-        }
-
-        throw new IllegalArgumentException("unknown object in getInstance.");
-   }
-
-
-   public DERObjectIdentifier getPolicyQualifierId()
-   {
-       return policyQualifierId;
-   }
-
-   public DEREncodable getQualifier()
-   {
-       return qualifier;
-   }
-   
-   /**
-    * Returns a DER-encodable representation of this instance. 
-    *
-    * @return a <code>DERObject</code> value
-    */
-   public DERObject toASN1Object() 
-   {
-      ASN1EncodableVector dev = new ASN1EncodableVector();
-      dev.add(policyQualifierId);
-      dev.add(qualifier);
-
-      return new DERSequence(dev);
-   }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java b/azureus2/src/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java
deleted file mode 100644
index b9db18f..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-import java.util.Enumeration;
-
-/**
- * <pre>
- *    PrivateKeyUsagePeriod ::= SEQUENCE {
- *      notBefore       [0]     GeneralizedTime OPTIONAL,
- *      notAfter        [1]     GeneralizedTime OPTIONAL }
- * </pre>
- */
-public class PrivateKeyUsagePeriod
-    extends ASN1Encodable
-{
-    public static PrivateKeyUsagePeriod getInstance(Object obj)
-    {
-        if (obj instanceof PrivateKeyUsagePeriod)
-        {
-            return (PrivateKeyUsagePeriod)obj;
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            return new PrivateKeyUsagePeriod((ASN1Sequence)obj);
-        }
-
-        if (obj instanceof X509Extension)
-        {
-            return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
-        }
-
-        throw new IllegalArgumentException("unknown object in getInstance");
-    }
-
-    private DERGeneralizedTime _notBefore, _notAfter;
-
-    private PrivateKeyUsagePeriod(ASN1Sequence seq)
-    {
-        Enumeration en = seq.getObjects();
-        while (en.hasMoreElements())
-        {
-            ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
-
-            if (tObj.getTagNo() == 0)
-            {
-                _notBefore = DERGeneralizedTime.getInstance(tObj, false);
-            }
-            else if (tObj.getTagNo() == 1)
-            {
-                _notAfter = DERGeneralizedTime.getInstance(tObj, false);
-            }
-        }
-    }
-
-    public DERGeneralizedTime getNotBefore()
-    {
-        return _notBefore;
-    }
-
-    public DERGeneralizedTime getNotAfter()
-    {
-        return _notAfter;
-    }
-
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        if (_notBefore != null)
-        {
-            v.add(new DERTaggedObject(false, 0, _notBefore));
-        }
-        if (_notAfter != null)
-        {
-            v.add(new DERTaggedObject(false, 1, _notAfter));
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java b/azureus2/src/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java
deleted file mode 100644
index 0047f6a..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-public class RSAPublicKeyStructure
-    extends ASN1Encodable
-{
-    private BigInteger  modulus;
-    private BigInteger  publicExponent;
-
-    public static RSAPublicKeyStructure getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static RSAPublicKeyStructure getInstance(
-        Object obj)
-    {
-        if(obj == null || obj instanceof RSAPublicKeyStructure) 
-        {
-            return (RSAPublicKeyStructure)obj;
-        }
-        
-        if(obj instanceof ASN1Sequence) 
-        {
-            return new RSAPublicKeyStructure((ASN1Sequence)obj);
-        }
-        
-        throw new IllegalArgumentException("Invalid RSAPublicKeyStructure: " + obj.getClass().getName());
-    }
-    
-    public RSAPublicKeyStructure(
-        BigInteger  modulus,
-        BigInteger  publicExponent)
-    {
-        this.modulus = modulus;
-        this.publicExponent = publicExponent;
-    }
-
-    public RSAPublicKeyStructure(
-        ASN1Sequence  seq)
-    {
-        if (seq.size() != 2)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                    + seq.size());
-        }
-
-        Enumeration e = seq.getObjects();
-
-        modulus = DERInteger.getInstance(e.nextElement()).getPositiveValue();
-        publicExponent = DERInteger.getInstance(e.nextElement()).getPositiveValue();
-    }
-
-    public BigInteger getModulus()
-    {
-        return modulus;
-    }
-
-    public BigInteger getPublicExponent()
-    {
-        return publicExponent;
-    }
-
-    /**
-     * This outputs the key in PKCS1v2 format.
-     * <pre>
-     *      RSAPublicKey ::= SEQUENCE {
-     *                          modulus INTEGER, -- n
-     *                          publicExponent INTEGER, -- e
-     *                      }
-     * </pre>
-     * <p>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(new DERInteger(getModulus()));
-        v.add(new DERInteger(getPublicExponent()));
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/ReasonFlags.java b/azureus2/src/org/bouncycastle/asn1/x509/ReasonFlags.java
deleted file mode 100644
index 612e2c5..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/ReasonFlags.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DERBitString;
-
-/**
- * The ReasonFlags object.
- * <pre>
- * ReasonFlags ::= BIT STRING {
- *      unused                  (0),
- *      keyCompromise           (1),
- *      cACompromise            (2),
- *      affiliationChanged      (3),
- *      superseded              (4),
- *      cessationOfOperation    (5),
- *      certificateHold         (6),
- *      privilegeWithdrawn      (7),
- *      aACompromise            (8) }
- * </pre>
- */
-public class ReasonFlags
-    extends DERBitString
-{
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int UNUSED                  = (1 << 7);
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int KEY_COMPROMISE          = (1 << 6);
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int CA_COMPROMISE           = (1 << 5);
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int AFFILIATION_CHANGED     = (1 << 4);
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int SUPERSEDED              = (1 << 3);
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int CESSATION_OF_OPERATION  = (1 << 2);
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int CERTIFICATE_HOLD        = (1 << 1);
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int PRIVILEGE_WITHDRAWN     = (1 << 0);
-    /**
-     * @deprecated use lower case version
-     */
-    public static final int AA_COMPROMISE           = (1 << 15);
-    
-    public static final int unused                  = (1 << 7);
-    public static final int keyCompromise           = (1 << 6);
-    public static final int cACompromise            = (1 << 5);
-    public static final int affiliationChanged      = (1 << 4);
-    public static final int superseded              = (1 << 3);
-    public static final int cessationOfOperation    = (1 << 2);
-    public static final int certificateHold         = (1 << 1);
-    public static final int privilegeWithdrawn      = (1 << 0);
-    public static final int aACompromise            = (1 << 15);
-
-    /**
-     * @param reasons - the bitwise OR of the Key Reason flags giving the
-     * allowed uses for the key.
-     */
-    public ReasonFlags(
-        int reasons)
-    {
-        super(getBytes(reasons), getPadBits(reasons));
-    }
-
-    public ReasonFlags(
-        DERBitString reasons)
-    {
-        super(reasons.getBytes(), reasons.getPadBits());
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/RoleSyntax.java b/azureus2/src/org/bouncycastle/asn1/x509/RoleSyntax.java
deleted file mode 100644
index 2811fe7..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/RoleSyntax.java
+++ /dev/null
@@ -1,236 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERString;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * Implementation of the RoleSyntax object as specified by the RFC3281.
- * 
- * <pre>
- * RoleSyntax ::= SEQUENCE {
- *                 roleAuthority  [0] GeneralNames OPTIONAL,
- *                 roleName       [1] GeneralName
- *           } 
- * </pre>
- */
-public class RoleSyntax 
-    extends ASN1Encodable
-{
-    private GeneralNames roleAuthority;
-    private GeneralName roleName;
-
-    /**
-     * RoleSyntax factory method.
-     * @param obj the object used to construct an instance of <code>
-     * RoleSyntax</code>. It must be an instance of <code>RoleSyntax
-     * </code> or <code>ASN1Sequence</code>.
-     * @return the instance of <code>RoleSyntax</code> built from the
-     * supplied object.
-     * @throws java.lang.IllegalArgumentException if the object passed
-     * to the factory is not an instance of <code>RoleSyntax</code> or
-     * <code>ASN1Sequence</code>.
-     */
-    public static RoleSyntax getInstance(
-        Object obj)
-    {
-        
-        if(obj == null || obj instanceof RoleSyntax)
-        {
-            return (RoleSyntax)obj;
-        }
-        else if(obj instanceof ASN1Sequence)
-        {
-            return new RoleSyntax((ASN1Sequence)obj);
-        }
-        throw new IllegalArgumentException("Unknown object in RoleSyntax factory.");
-    }
-    
-    /**
-     * Constructor.
-     * @param roleAuthority the role authority of this RoleSyntax.
-     * @param roleName    the role name of this RoleSyntax.
-     */
-    public RoleSyntax(
-        GeneralNames roleAuthority,
-        GeneralName roleName)
-    {
-        if(roleName == null || 
-                roleName.getTagNo() != GeneralName.uniformResourceIdentifier ||
-                ((DERString)roleName.getName()).getString().equals(""))
-        {
-            throw new IllegalArgumentException("the role name MUST be non empty and MUST " +
-                    "use the URI option of GeneralName");
-        }
-        this.roleAuthority = roleAuthority;
-        this.roleName = roleName;
-    }
-    
-    /**
-     * Constructor. Invoking this constructor is the same as invoking
-     * <code>new RoleSyntax(null, roleName)</code>.
-     * @param roleName    the role name of this RoleSyntax.
-     */
-    public RoleSyntax(
-        GeneralName roleName)
-    {
-        this(null, roleName);
-    }
-
-    /**
-     * Utility constructor. Takes a <code>String</code> argument representing
-     * the role name, builds a <code>GeneralName</code> to hold the role name
-     * and calls the constructor that takes a <code>GeneralName</code>.
-     * @param roleName
-     */
-    public RoleSyntax(
-        String roleName)
-    {
-        this(new GeneralName(GeneralName.uniformResourceIdentifier,
-                (roleName == null)? "": roleName));
-    }
-    
-    /**
-     * Constructor that builds an instance of <code>RoleSyntax</code> by
-     * extracting the encoded elements from the <code>ASN1Sequence</code>
-     * object supplied.
-     * @param seq    an instance of <code>ASN1Sequence</code> that holds
-     * the encoded elements used to build this <code>RoleSyntax</code>.
-     */
-    public RoleSyntax(
-        ASN1Sequence seq)
-    {
-        if (seq.size() < 1 || seq.size() > 2)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                    + seq.size());
-        }
-
-        for (int i = 0; i != seq.size(); i++)
-        {
-            ASN1TaggedObject taggedObject = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
-            switch (taggedObject.getTagNo())
-            {
-            case 0:
-                roleAuthority = GeneralNames.getInstance(taggedObject, false);
-                break;
-            case 1:
-                roleName = GeneralName.getInstance(taggedObject, false);
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown tag in RoleSyntax");
-            }
-        }
-    }
-
-    /**
-     * Gets the role authority of this RoleSyntax.
-     * @return    an instance of <code>GeneralNames</code> holding the
-     * role authority of this RoleSyntax.
-     */
-    public GeneralNames getRoleAuthority()
-    {
-        return this.roleAuthority;
-    }
-    
-    /**
-     * Gets the role name of this RoleSyntax.
-     * @return    an instance of <code>GeneralName</code> holding the
-     * role name of this RoleSyntax.
-     */
-    public GeneralName getRoleName()
-    {
-        return this.roleName;
-    }
-    
-    /**
-     * Gets the role name as a <code>java.lang.String</code> object.
-     * @return    the role name of this RoleSyntax represented as a 
-     * <code>java.lang.String</code> object.
-     */
-    public String getRoleNameAsString()
-    {
-        DERString str = (DERString)this.roleName.getName();
-        
-        return str.getString();
-    }
-    
-    /**
-     * Gets the role authority as a <code>String[]</code> object.
-     * @return the role authority of this RoleSyntax represented as a
-     * <code>String[]</code> array.
-     */
-    public String[] getRoleAuthorityAsString() 
-    {
-        if(roleAuthority == null) 
-        {
-            return new String[0];
-        }
-        
-        GeneralName[] names = roleAuthority.getNames();
-        String[] namesString = new String[names.length];
-        for(int i = 0; i < names.length; i++) 
-        {
-            DEREncodable value = names[i].getName();
-            if(value instanceof DERString)
-            {
-                namesString[i] = ((DERString)value).getString();
-            }
-            else
-            {
-                namesString[i] = value.toString();
-            }
-        }
-        return namesString;
-    }
-    
-    /**
-     * Implementation of the method <code>toASN1Object</code> as
-     * required by the superclass <code>ASN1Encodable</code>.
-     * 
-     * <pre>
-     * RoleSyntax ::= SEQUENCE {
-     *                 roleAuthority  [0] GeneralNames OPTIONAL,
-     *                 roleName       [1] GeneralName
-     *           } 
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-        if(this.roleAuthority != null)
-        {
-            v.add(new DERTaggedObject(false, 0, roleAuthority));
-        }
-        v.add(new DERTaggedObject(false, 1, roleName));
-        
-        return new DERSequence(v);
-    }
-    
-    public String toString() 
-    {
-        StringBuffer buff = new StringBuffer("Name: " + this.getRoleNameAsString() +
-                " - Auth: ");
-        if(this.roleAuthority == null || roleAuthority.getNames().length == 0)
-        {
-            buff.append("N/A");
-        }
-        else 
-        {
-            String[] names = this.getRoleAuthorityAsString();
-            buff.append('[').append(names[0]);
-            for(int i = 1; i < names.length; i++) 
-            {
-                    buff.append(", ").append(names[i]);
-            }
-            buff.append(']');
-        }
-        return buff.toString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java b/azureus2/src/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java
deleted file mode 100644
index 3dede65..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * This extension may contain further X.500 attributes of the subject. See also
- * RFC 3039.
- * 
- * <pre>
- *     SubjectDirectoryAttributes ::= Attributes
- *     Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
- *     Attribute ::= SEQUENCE 
- *     {
- *       type AttributeType 
- *       values SET OF AttributeValue 
- *     }
- *     
- *     AttributeType ::= OBJECT IDENTIFIER
- *     AttributeValue ::= ANY DEFINED BY AttributeType
- * </pre>
- * 
- * @see org.bouncycastle.asn1.x509.X509Name for AttributeType ObjectIdentifiers.
- */
-public class SubjectDirectoryAttributes 
-    extends ASN1Encodable
-{
-    private Vector attributes = new Vector();
-
-    public static SubjectDirectoryAttributes getInstance(
-        Object obj)
-    {
-        if (obj == null || obj instanceof SubjectDirectoryAttributes)
-        {
-            return (SubjectDirectoryAttributes)obj;
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            return new SubjectDirectoryAttributes((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * Constructor from ASN1Sequence.
-     * 
-     * The sequence is of type SubjectDirectoryAttributes:
-     * 
-     * <pre>
-     *      SubjectDirectoryAttributes ::= Attributes
-     *      Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
-     *      Attribute ::= SEQUENCE 
-     *      {
-     *        type AttributeType 
-     *        values SET OF AttributeValue 
-     *      }
-     *      
-     *      AttributeType ::= OBJECT IDENTIFIER
-     *      AttributeValue ::= ANY DEFINED BY AttributeType
-     * </pre>
-     * 
-     * @param seq
-     *            The ASN.1 sequence.
-     */
-    public SubjectDirectoryAttributes(ASN1Sequence seq)
-    {
-        Enumeration e = seq.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement());
-            attributes.addElement(new Attribute(s));
-        }
-    }
-
-    /**
-     * Constructor from a vector of attributes.
-     * 
-     * The vector consists of attributes of type {@link Attribute Attribute}
-     * 
-     * @param attributes
-     *            The attributes.
-     * 
-     */
-    public SubjectDirectoryAttributes(Vector attributes)
-    {
-        Enumeration e = attributes.elements();
-
-        while (e.hasMoreElements())
-        {
-            this.attributes.addElement(e.nextElement());
-        }
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * 
-     * Returns:
-     * 
-     * <pre>
-     *      SubjectDirectoryAttributes ::= Attributes
-     *      Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
-     *      Attribute ::= SEQUENCE 
-     *      {
-     *        type AttributeType 
-     *        values SET OF AttributeValue 
-     *      }
-     *      
-     *      AttributeType ::= OBJECT IDENTIFIER
-     *      AttributeValue ::= ANY DEFINED BY AttributeType
-     * </pre>
-     * 
-     * @return a DERObject
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector vec = new ASN1EncodableVector();
-        Enumeration e = attributes.elements();
-
-        while (e.hasMoreElements())
-        {
-
-            vec.add((Attribute)e.nextElement());
-        }
-
-        return new DERSequence(vec);
-    }
-
-    /**
-     * @return Returns the attributes.
-     */
-    public Vector getAttributes()
-    {
-        return attributes;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java b/azureus2/src/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java
deleted file mode 100644
index 357b578..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-
-/**
- * The SubjectKeyIdentifier object.
- * <pre>
- * SubjectKeyIdentifier::= OCTET STRING
- * </pre>
- */
-public class SubjectKeyIdentifier
-    extends ASN1Encodable
-{
-    private byte[] keyidentifier;
-
-    public static SubjectKeyIdentifier getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1OctetString.getInstance(obj, explicit));
-    }
-
-    public static SubjectKeyIdentifier getInstance(
-        Object obj)
-    {
-        if (obj instanceof SubjectKeyIdentifier)
-        {
-            return (SubjectKeyIdentifier)obj;
-        }
-        
-        if (obj instanceof SubjectPublicKeyInfo) 
-        {
-            return new SubjectKeyIdentifier((SubjectPublicKeyInfo)obj);
-        }
-        
-        if (obj instanceof ASN1OctetString) 
-        {
-            return new SubjectKeyIdentifier((ASN1OctetString)obj);
-        }
-
-        if (obj instanceof X509Extension)
-        {
-            return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
-        }
-
-        throw new IllegalArgumentException("Invalid SubjectKeyIdentifier: " + obj.getClass().getName());
-    }
-    
-    public SubjectKeyIdentifier(
-        byte[] keyid)
-    {
-        this.keyidentifier=keyid;
-    }
-
-    public SubjectKeyIdentifier(
-        ASN1OctetString  keyid)
-    {
-        this.keyidentifier=keyid.getOctets();
-
-    }
-
-    /**
-     *
-     * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
-     * from SubjectPublicKeyInfo as defined in RFC2459.
-     *
-     **/
-    public SubjectKeyIdentifier(
-        SubjectPublicKeyInfo    spki)
-    {
-        Digest  digest = new SHA1Digest();
-        byte[]  resBuf = new byte[digest.getDigestSize()];
-
-        byte[] bytes = spki.getPublicKeyData().getBytes();
-        digest.update(bytes, 0, bytes.length);
-        digest.doFinal(resBuf, 0);
-        this.keyidentifier=resBuf;
-    }
-
-    public byte[] getKeyIdentifier()
-    {
-        return keyidentifier;
-    }
-
-    public DERObject toASN1Object()
-    {
-        return new DEROctetString(keyidentifier);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java b/azureus2/src/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java
deleted file mode 100644
index a733727..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * The object that contains the public key stored in a certficate.
- * <p>
- * The getEncoded() method in the public keys in the JCE produces a DER
- * encoded one of these.
- */
-public class SubjectPublicKeyInfo
-    extends ASN1Encodable
-{
-    private AlgorithmIdentifier     algId;
-    private DERBitString            keyData;
-
-    public static SubjectPublicKeyInfo getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static SubjectPublicKeyInfo getInstance(
-        Object  obj)
-    {
-        if (obj instanceof SubjectPublicKeyInfo)
-        {
-            return (SubjectPublicKeyInfo)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new SubjectPublicKeyInfo((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public SubjectPublicKeyInfo(
-        AlgorithmIdentifier algId,
-        DEREncodable        publicKey)
-    {
-        this.keyData = new DERBitString(publicKey);
-        this.algId = algId;
-    }
-
-    public SubjectPublicKeyInfo(
-        AlgorithmIdentifier algId,
-        byte[]              publicKey)
-    {
-        this.keyData = new DERBitString(publicKey);
-        this.algId = algId;
-    }
-
-    public SubjectPublicKeyInfo(
-        ASN1Sequence  seq)
-    {
-        if (seq.size() != 2)
-        {
-            throw new IllegalArgumentException("Bad sequence size: "
-                    + seq.size());
-        }
-
-        Enumeration         e = seq.getObjects();
-
-        this.algId = AlgorithmIdentifier.getInstance(e.nextElement());
-        this.keyData = DERBitString.getInstance(e.nextElement());
-    }
-
-    public AlgorithmIdentifier getAlgorithmId()
-    {
-        return algId;
-    }
-
-    /**
-     * for when the public key is an encoded object - if the bitstring
-     * can't be decoded this routine throws an IOException.
-     *
-     * @exception IOException - if the bit string doesn't represent a DER
-     * encoded object.
-     */
-    public DERObject getPublicKey()
-        throws IOException
-    {
-        ASN1InputStream         aIn = new ASN1InputStream(keyData.getBytes());
-
-        return aIn.readObject();
-    }
-
-    /**
-     * for when the public key is raw bits...
-     */
-    public DERBitString getPublicKeyData()
-    {
-        return keyData;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * SubjectPublicKeyInfo ::= SEQUENCE {
-     *                          algorithm AlgorithmIdentifier,
-     *                          publicKey BIT STRING }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(algId);
-        v.add(keyData);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/TBSCertList.java b/azureus2/src/org/bouncycastle/asn1/x509/TBSCertList.java
deleted file mode 100644
index 6c5afd8..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/TBSCertList.java
+++ /dev/null
@@ -1,212 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTCTime;
-
-/**
- * PKIX RFC-2459 - TBSCertList object.
- * <pre>
- * TBSCertList  ::=  SEQUENCE  {
- *      version                 Version OPTIONAL,
- *                                   -- if present, shall be v2
- *      signature               AlgorithmIdentifier,
- *      issuer                  Name,
- *      thisUpdate              Time,
- *      nextUpdate              Time OPTIONAL,
- *      revokedCertificates     SEQUENCE OF SEQUENCE  {
- *           userCertificate         CertificateSerialNumber,
- *           revocationDate          Time,
- *           crlEntryExtensions      Extensions OPTIONAL
- *                                         -- if present, shall be v2
- *                                }  OPTIONAL,
- *      crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
- *                                         -- if present, shall be v2
- *                                }
- * </pre>
- */
-public class TBSCertList
-    extends ASN1Encodable
-{
-    public class CRLEntry
-        extends ASN1Encodable
-    {
-        ASN1Sequence  seq;
-
-        DERInteger          userCertificate;
-        Time                revocationDate;
-        X509Extensions      crlEntryExtensions;
-
-        public CRLEntry(
-            ASN1Sequence  seq)
-        {
-            if (seq.size() < 2 || seq.size() > 3)
-            {
-                throw new IllegalArgumentException("Bad sequence size: " + seq.size());
-            }
-            
-            this.seq = seq;
-
-            userCertificate = DERInteger.getInstance(seq.getObjectAt(0));
-            revocationDate = Time.getInstance(seq.getObjectAt(1));
-            if (seq.size() == 3)
-            {
-                crlEntryExtensions = X509Extensions.getInstance(seq.getObjectAt(2));
-            }
-        }
-
-        public DERInteger getUserCertificate()
-        {
-            return userCertificate;
-        }
-
-        public Time getRevocationDate()
-        {
-            return revocationDate;
-        }
-
-        public X509Extensions getExtensions()
-        {
-            return crlEntryExtensions;
-        }
-
-        public DERObject toASN1Object()
-        {
-            return seq;
-        }
-    }
-
-    ASN1Sequence     seq;
-
-    DERInteger              version;
-    AlgorithmIdentifier     signature;
-    X509Name                issuer;
-    Time                    thisUpdate;
-    Time                    nextUpdate;
-    CRLEntry[]              revokedCertificates;
-    X509Extensions          crlExtensions;
-
-    public static TBSCertList getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static TBSCertList getInstance(
-        Object  obj)
-    {
-        if (obj instanceof TBSCertList)
-        {
-            return (TBSCertList)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new TBSCertList((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public TBSCertList(
-        ASN1Sequence  seq)
-    {
-        if (seq.size() < 3 || seq.size() > 7)
-        {
-            throw new IllegalArgumentException("Bad sequence size: " + seq.size());
-        }
-
-        int seqPos = 0;
-
-        this.seq = seq;
-
-        if (seq.getObjectAt(seqPos) instanceof DERInteger)
-        {
-            version = DERInteger.getInstance(seq.getObjectAt(seqPos++));
-        }
-        else
-        {
-            version = new DERInteger(0);
-        }
-
-        signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqPos++));
-        issuer = X509Name.getInstance(seq.getObjectAt(seqPos++));
-        thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
-
-        if (seqPos < seq.size()
-            && (seq.getObjectAt(seqPos) instanceof DERUTCTime
-               || seq.getObjectAt(seqPos) instanceof DERGeneralizedTime
-               || seq.getObjectAt(seqPos) instanceof Time))
-        {
-            nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
-        }
-
-        if (seqPos < seq.size()
-            && !(seq.getObjectAt(seqPos) instanceof DERTaggedObject))
-        {
-            ASN1Sequence certs = ASN1Sequence.getInstance(seq.getObjectAt(seqPos++));
-            revokedCertificates = new CRLEntry[certs.size()];
-
-            for (int i = 0; i < revokedCertificates.length; i++)
-            {
-                revokedCertificates[i] = new CRLEntry(ASN1Sequence.getInstance(certs.getObjectAt(i)));
-            }
-        }
-
-        if (seqPos < seq.size()
-            && seq.getObjectAt(seqPos) instanceof DERTaggedObject)
-        {
-            crlExtensions = X509Extensions.getInstance(seq.getObjectAt(seqPos++));
-        }
-    }
-
-    public int getVersion()
-    {
-        return version.getValue().intValue() + 1;
-    }
-
-    public DERInteger getVersionNumber()
-    {
-        return version;
-    }
-
-    public AlgorithmIdentifier getSignature()
-    {
-        return signature;
-    }
-
-    public X509Name getIssuer()
-    {
-        return issuer;
-    }
-
-    public Time getThisUpdate()
-    {
-        return thisUpdate;
-    }
-
-    public Time getNextUpdate()
-    {
-        return nextUpdate;
-    }
-
-    public CRLEntry[] getRevokedCertificates()
-    {
-        return revokedCertificates;
-    }
-
-    public X509Extensions getExtensions()
-    {
-        return crlExtensions;
-    }
-
-    public DERObject toASN1Object()
-    {
-        return seq;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/TBSCertificateStructure.java b/azureus2/src/org/bouncycastle/asn1/x509/TBSCertificateStructure.java
deleted file mode 100644
index cc3c0e4..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/TBSCertificateStructure.java
+++ /dev/null
@@ -1,193 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-
-/**
- * The TBSCertificate object.
- * <pre>
- * TBSCertificate ::= SEQUENCE {
- *      version          [ 0 ]  Version DEFAULT v1(0),
- *      serialNumber            CertificateSerialNumber,
- *      signature               AlgorithmIdentifier,
- *      issuer                  Name,
- *      validity                Validity,
- *      subject                 Name,
- *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
- *      issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
- *      subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
- *      extensions        [ 3 ] Extensions OPTIONAL
- *      }
- * </pre>
- * <p>
- * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
- * will parse them, but you really shouldn't be creating new ones.
- */
-public class TBSCertificateStructure
-    extends ASN1Encodable
-    implements X509ObjectIdentifiers, PKCSObjectIdentifiers
-{
-    ASN1Sequence            seq;
-
-    DERInteger              version;
-    DERInteger              serialNumber;
-    AlgorithmIdentifier     signature;
-    X509Name                issuer;
-    Time                    startDate, endDate;
-    X509Name                subject;
-    SubjectPublicKeyInfo    subjectPublicKeyInfo;
-    DERBitString            issuerUniqueId;
-    DERBitString            subjectUniqueId;
-    X509Extensions          extensions;
-
-    public static TBSCertificateStructure getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static TBSCertificateStructure getInstance(
-        Object  obj)
-    {
-        if (obj instanceof TBSCertificateStructure)
-        {
-            return (TBSCertificateStructure)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new TBSCertificateStructure((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public TBSCertificateStructure(
-        ASN1Sequence  seq)
-    {
-        int         seqStart = 0;
-
-        this.seq = seq;
-
-        //
-        // some certficates don't include a version number - we assume v1
-        //
-        if (seq.getObjectAt(0) instanceof DERTaggedObject)
-        {
-            version = DERInteger.getInstance(seq.getObjectAt(0));
-        }
-        else
-        {
-            seqStart = -1;          // field 0 is missing!
-            version = new DERInteger(0);
-        }
-
-        serialNumber = DERInteger.getInstance(seq.getObjectAt(seqStart + 1));
-
-        signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2));
-        issuer = X509Name.getInstance(seq.getObjectAt(seqStart + 3));
-
-        //
-        // before and after dates
-        //
-        ASN1Sequence  dates = (ASN1Sequence)seq.getObjectAt(seqStart + 4);
-
-        startDate = Time.getInstance(dates.getObjectAt(0));
-        endDate = Time.getInstance(dates.getObjectAt(1));
-
-        subject = X509Name.getInstance(seq.getObjectAt(seqStart + 5));
-
-        //
-        // public key info.
-        //
-        subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6));
-
-        for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--)
-        {
-            DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras);
-
-            switch (extra.getTagNo())
-            {
-            case 1:
-                issuerUniqueId = DERBitString.getInstance(extra, false);
-                break;
-            case 2:
-                subjectUniqueId = DERBitString.getInstance(extra, false);
-                break;
-            case 3:
-                extensions = X509Extensions.getInstance(extra);
-            }
-        }
-    }
-
-    public int getVersion()
-    {
-        return version.getValue().intValue() + 1;
-    }
-
-    public DERInteger getVersionNumber()
-    {
-        return version;
-    }
-
-    public DERInteger getSerialNumber()
-    {
-        return serialNumber;
-    }
-
-    public AlgorithmIdentifier getSignature()
-    {
-        return signature;
-    }
-
-    public X509Name getIssuer()
-    {
-        return issuer;
-    }
-
-    public Time getStartDate()
-    {
-        return startDate;
-    }
-
-    public Time getEndDate()
-    {
-        return endDate;
-    }
-
-    public X509Name getSubject()
-    {
-        return subject;
-    }
-
-    public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
-    {
-        return subjectPublicKeyInfo;
-    }
-
-    public DERBitString getIssuerUniqueId()
-    {
-        return issuerUniqueId;
-    }
-
-    public DERBitString getSubjectUniqueId()
-    {
-        return subjectUniqueId;
-    }
-
-    public X509Extensions getExtensions()
-    {
-        return extensions;
-    }
-
-    public DERObject toASN1Object()
-    {
-        return seq;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/Target.java b/azureus2/src/org/bouncycastle/asn1/x509/Target.java
deleted file mode 100644
index 4d3b672..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/Target.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * Target structure used in target information extension for attribute
- * certificates from RFC 3281.
- * 
- * <pre>
- *     Target  ::= CHOICE {
- *       targetName          [0] GeneralName,
- *       targetGroup         [1] GeneralName,
- *       targetCert          [2] TargetCert
- *     }
- * </pre>
- * 
- * <p>
- * The targetCert field is currently not supported and must not be used
- * according to RFC 3281.
- */
-public class Target
-    extends ASN1Encodable
-    implements ASN1Choice
-{
-    public static final int targetName = 0;
-    public static final int targetGroup = 1;
-
-    private GeneralName targName;
-    private GeneralName targGroup;
-
-    /**
-     * Creates an instance of a Target from the given object.
-     * <p>
-     * <code>obj</code> can be a Target or a {@link ASN1TaggedObject}
-     * 
-     * @param obj The object.
-     * @return A Target instance.
-     * @throws IllegalArgumentException if the given object cannot be
-     *             interpreted as Target.
-     */
-    public static Target getInstance(Object obj)
-    {
-        if (obj instanceof Target)
-        {
-            return (Target) obj;
-        }
-        else if (obj instanceof ASN1TaggedObject)
-        {
-            return new Target((ASN1TaggedObject)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory: "
-            + obj.getClass());
-    }
-
-    /**
-     * Constructor from ASN1TaggedObject.
-     * 
-     * @param tagObj The tagged object.
-     * @throws IllegalArgumentException if the encoding is wrong.
-     */
-    private Target(ASN1TaggedObject tagObj)
-    {
-        switch (tagObj.getTagNo())
-        {
-        case targetName:     // GeneralName is already a choice so explicit
-            targName = GeneralName.getInstance(tagObj, true);
-            break;
-        case targetGroup:
-            targGroup = GeneralName.getInstance(tagObj, true);
-            break;
-        default:
-            throw new IllegalArgumentException("unknown tag: " + tagObj.getTagNo());
-        }
-    }
-
-    /**
-     * Constructor from given details.
-     * <p>
-     * Exactly one of the parameters must be not <code>null</code>.
-     *
-     * @param type the choice type to apply to the name.
-     * @param name the general name.
-     * @throws IllegalArgumentException if type is invalid.
-     */
-    public Target(int type, GeneralName name)
-    {
-        this(new DERTaggedObject(type, name));
-    }
-
-    /**
-     * @return Returns the targetGroup.
-     */
-    public GeneralName getTargetGroup()
-    {
-        return targGroup;
-    }
-
-    /**
-     * @return Returns the targetName.
-     */
-    public GeneralName getTargetName()
-    {
-        return targName;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * 
-     * Returns:
-     * 
-     * <pre>
-     *     Target  ::= CHOICE {
-     *       targetName          [0] GeneralName,
-     *       targetGroup         [1] GeneralName,
-     *       targetCert          [2] TargetCert
-     *     }
-     * </pre>
-     * 
-     * @return a DERObject
-     */
-    public DERObject toASN1Object()
-    {
-        // GeneralName is a choice already so most be explicitly tagged
-        if (targName != null)
-        {
-            return new DERTaggedObject(true, 0, targName);
-        }
-        else
-        {
-            return new DERTaggedObject(true, 1, targGroup);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/TargetInformation.java b/azureus2/src/org/bouncycastle/asn1/x509/TargetInformation.java
deleted file mode 100644
index 7608b22..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/TargetInformation.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-import java.util.Enumeration;
-
-/**
- * Target information extension for attributes certificates according to RFC
- * 3281.
- * 
- * <pre>
- *           SEQUENCE OF Targets
- * </pre>
- * 
- */
-public class TargetInformation
-    extends ASN1Encodable
-{
-    private ASN1Sequence targets;
-
-    /**
-     * Creates an instance of a TargetInformation from the given object.
-     * <p>
-     * <code>obj</code> can be a TargetInformation or a {@link ASN1Sequence}
-     * 
-     * @param obj The object.
-     * @return A TargetInformation instance.
-     * @throws IllegalArgumentException if the given object cannot be
-     *             interpreted as TargetInformation.
-     */
-    public static TargetInformation getInstance(Object obj)
-    {
-        if (obj instanceof TargetInformation)
-        {
-            return (TargetInformation) obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new TargetInformation((ASN1Sequence) obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory: "
-            + obj.getClass());
-    }
-
-    /**
-     * Constructor from a ASN1Sequence.
-     * 
-     * @param seq The ASN1Sequence.
-     * @throws IllegalArgumentException if the sequence does not contain
-     *             correctly encoded Targets elements.
-     */
-    private TargetInformation(ASN1Sequence seq)
-    {
-        targets = seq;
-    }
-
-    /**
-     * Returns the targets in this target information extension.
-     * 
-     * @return Returns the targets.
-     */
-    public Targets[] getTargetsObjects()
-    {
-        Targets[] copy = new Targets[targets.size()];
-        int count = 0;
-        for (Enumeration e = targets.getObjects(); e.hasMoreElements();)
-        {
-            copy[count++] = Targets.getInstance(e.nextElement());
-        }
-        return copy;
-    }
-
-    /**
-     * Constructs a target information from a single targets element. 
-     * According to RFC 3281 only one targets element must be produced.
-     * 
-     * @param targets A Targets instance.
-     */
-    public TargetInformation(Targets targets)
-    {
-        this.targets = new DERSequence(targets);
-    }
-
-    /**
-     * According to RFC 3281 only one targets element must be produced. If
-     * multiple targets are given they must be merged in
-     * into one targets element.
-     *
-     * @param targets An array with {@link Targets}.
-     */
-    public TargetInformation(Target[] targets)
-    {
-        this(new Targets(targets));
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * 
-     * Returns:
-     * 
-     * <pre>
-     *          SEQUENCE OF Targets
-     * </pre>
-     * 
-     * <p>
-     * According to RFC 3281 only one targets element must be produced. If
-     * multiple targets are given in the constructor they are merged into one
-     * targets element. If this was produced from a
-     * {@link org.bouncycastle.asn1.ASN1Sequence} the encoding is kept.
-     * 
-     * @return a DERObject
-     */
-    public DERObject toASN1Object()
-    {
-        return targets;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/Targets.java b/azureus2/src/org/bouncycastle/asn1/x509/Targets.java
deleted file mode 100644
index 2fead07..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/Targets.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-import java.util.Enumeration;
-
-/**
- * Targets structure used in target information extension for attribute
- * certificates from RFC 3281.
- * 
- * <pre>
- *            Targets ::= SEQUENCE OF Target
- *           
- *            Target  ::= CHOICE {
- *              targetName          [0] GeneralName,
- *              targetGroup         [1] GeneralName,
- *              targetCert          [2] TargetCert
- *            }
- *           
- *            TargetCert  ::= SEQUENCE {
- *              targetCertificate    IssuerSerial,
- *              targetName           GeneralName OPTIONAL,
- *              certDigestInfo       ObjectDigestInfo OPTIONAL
- *            }
- * </pre>
- * 
- * @see org.bouncycastle.asn1.x509.Target
- * @see org.bouncycastle.asn1.x509.TargetInformation
- */
-public class Targets
-    extends ASN1Encodable
-{
-    private ASN1Sequence targets;
-
-    /**
-     * Creates an instance of a Targets from the given object.
-     * <p>
-     * <code>obj</code> can be a Targets or a {@link ASN1Sequence}
-     * 
-     * @param obj The object.
-     * @return A Targets instance.
-     * @throws IllegalArgumentException if the given object cannot be
-     *             interpreted as Target.
-     */
-    public static Targets getInstance(Object obj)
-    {
-        if (obj instanceof Targets)
-        {
-            return (Targets)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new Targets((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory: "
-            + obj.getClass());
-    }
-
-    /**
-     * Constructor from ASN1Sequence.
-     * 
-     * @param targets The ASN.1 SEQUENCE.
-     * @throws IllegalArgumentException if the contents of the sequence are
-     *             invalid.
-     */
-    private Targets(ASN1Sequence targets)
-    {
-        this.targets = targets;
-    }
-
-    /**
-     * Constructor from given targets.
-     * <p>
-     * The vector is copied.
-     * 
-     * @param targets A <code>Vector</code> of {@link Target}s.
-     * @see Target
-     * @throws IllegalArgumentException if the vector contains not only Targets.
-     */
-    public Targets(Target[] targets)
-    {
-        this.targets = new DERSequence(targets);
-    }
-
-    /**
-     * Returns the targets in a <code>Vector</code>.
-     * <p>
-     * The vector is cloned before it is returned.
-     * 
-     * @return Returns the targets.
-     */
-    public Target[] getTargets()
-    {
-        Target[] targs = new Target[targets.size()];
-        int count = 0;
-        for (Enumeration e = targets.getObjects(); e.hasMoreElements();)
-        {
-            targs[count++] = Target.getInstance(e.nextElement());
-        }
-        return targs;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * 
-     * Returns:
-     * 
-     * <pre>
-     *            Targets ::= SEQUENCE OF Target
-     * </pre>
-     * 
-     * @return a DERObject
-     */
-    public DERObject toASN1Object()
-    {
-        return targets;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/Time.java b/azureus2/src/org/bouncycastle/asn1/x509/Time.java
deleted file mode 100644
index 258a23f..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/Time.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Choice;
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERUTCTime;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.SimpleTimeZone;
-
-public class Time
-    extends ASN1Encodable
-    implements ASN1Choice
-{
-    DERObject   time;
-
-    public static Time getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(obj.getObject()); // must be explicitly tagged
-    }
-
-    public Time(
-        DERObject   time)
-    {
-        if (!(time instanceof DERUTCTime)
-            && !(time instanceof DERGeneralizedTime))
-        {
-            throw new IllegalArgumentException("unknown object passed to Time");
-        }
-
-        this.time = time; 
-    }
-
-    /**
-     * creates a time object from a given date - if the date is between 1950
-     * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
-     * is used.
-     */
-    public Time(
-        Date    date)
-    {
-        SimpleTimeZone      tz = new SimpleTimeZone(0, "Z");
-        SimpleDateFormat    dateF = new SimpleDateFormat("yyyyMMddHHmmss");
-
-        dateF.setTimeZone(tz);
-
-        String  d = dateF.format(date) + "Z";
-        int     year = Integer.parseInt(d.substring(0, 4));
-
-        if (year < 1950 || year > 2049)
-        {
-            time = new DERGeneralizedTime(d);
-        }
-        else
-        {
-            time = new DERUTCTime(d.substring(2));
-        }
-    }
-
-    public static Time getInstance(
-        Object  obj)
-    {
-        if (obj instanceof Time)
-        {
-            return (Time)obj;
-        }
-        else if (obj instanceof DERUTCTime)
-        {
-            return new Time((DERUTCTime)obj);
-        }
-        else if (obj instanceof DERGeneralizedTime)
-        {
-            return new Time((DERGeneralizedTime)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public String getTime()
-    {
-        if (time instanceof DERUTCTime)
-        {
-            return ((DERUTCTime)time).getAdjustedTime();
-        }
-        else
-        {
-            return ((DERGeneralizedTime)time).getTime();
-        }
-    }
-
-    public Date getDate()
-    {
-        try
-        {
-            if (time instanceof DERUTCTime)
-            {
-                return ((DERUTCTime)time).getAdjustedDate();
-            }
-            else
-            {
-                return ((DERGeneralizedTime)time).getDate();
-            }
-        }
-        catch (ParseException e)
-        {         // this should never happen
-            throw new IllegalStateException("invalid date string: " + e.getMessage());
-        }
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * Time ::= CHOICE {
-     *             utcTime        UTCTime,
-     *             generalTime    GeneralizedTime }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        return time;
-    }
-
-    public String toString()
-    {
-        return getTime();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/UserNotice.java b/azureus2/src/org/bouncycastle/asn1/x509/UserNotice.java
deleted file mode 100644
index b3785ff..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/UserNotice.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * <code>UserNotice</code> class, used in
- * <code>CertificatePolicies</code> X509 extensions (in policy
- * qualifiers).
- * <pre>
- * UserNotice ::= SEQUENCE {
- *      noticeRef        NoticeReference OPTIONAL,
- *      explicitText     DisplayText OPTIONAL}
- *
- * </pre>
- * 
- * @see PolicyQualifierId
- * @see PolicyInformation
- */
-public class UserNotice 
-    extends ASN1Encodable 
-{
-    private NoticeReference noticeRef;
-    private DisplayText     explicitText;
-   
-    /**
-     * Creates a new <code>UserNotice</code> instance.
-     *
-     * @param noticeRef a <code>NoticeReference</code> value
-     * @param explicitText a <code>DisplayText</code> value
-     */
-    public UserNotice(
-        NoticeReference noticeRef, 
-        DisplayText explicitText) 
-    {
-        this.noticeRef = noticeRef;
-        this.explicitText = explicitText;
-    }
-
-    /**
-     * Creates a new <code>UserNotice</code> instance.
-     *
-     * @param noticeRef a <code>NoticeReference</code> value
-     * @param str the explicitText field as a String. 
-     */
-    public UserNotice(
-        NoticeReference noticeRef, 
-        String str) 
-    {
-        this.noticeRef = noticeRef;
-        this.explicitText = new DisplayText(str);
-    }
-
-    /**
-     * Creates a new <code>UserNotice</code> instance.
-     * <p>Useful from reconstructing a <code>UserNotice</code> instance
-     * from its encodable/encoded form. 
-     *
-     * @param as an <code>ASN1Sequence</code> value obtained from either
-     * calling @{link toASN1Object()} for a <code>UserNotice</code>
-     * instance or from parsing it from a DER-encoded stream. 
-     */
-    public UserNotice(
-       ASN1Sequence as) 
-    {
-       if (as.size() == 2)
-       {
-           noticeRef = NoticeReference.getInstance(as.getObjectAt(0));
-           explicitText = DisplayText.getInstance(as.getObjectAt(1));
-       }
-       else if (as.size() == 1)
-       {
-           if (as.getObjectAt(0).getDERObject() instanceof ASN1Sequence)
-           {
-               noticeRef = NoticeReference.getInstance(as.getObjectAt(0));
-           }
-           else
-           {
-               explicitText = DisplayText.getInstance(as.getObjectAt(0));
-           }
-       }
-       else
-       {
-           throw new IllegalArgumentException("Bad sequence size: " + as.size());
-       }
-    }
-   
-    public NoticeReference getNoticeRef()
-    {
-        return noticeRef;
-    }
-    
-    public DisplayText getExplicitText()
-    {
-        return explicitText;
-    }
-    
-    public DERObject toASN1Object() 
-    {
-        ASN1EncodableVector av = new ASN1EncodableVector();
-      
-        if (noticeRef != null)
-        {
-            av.add(noticeRef);
-        }
-        
-        if (explicitText != null)
-        {
-            av.add(explicitText);
-        }
-         
-        return new DERSequence(av);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java b/azureus2/src/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java
deleted file mode 100644
index 53505d1..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTCTime;
-
-/**
- * Generator for Version 1 TBSCertificateStructures.
- * <pre>
- * TBSCertificate ::= SEQUENCE {
- *      version          [ 0 ]  Version DEFAULT v1(0),
- *      serialNumber            CertificateSerialNumber,
- *      signature               AlgorithmIdentifier,
- *      issuer                  Name,
- *      validity                Validity,
- *      subject                 Name,
- *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
- *      }
- * </pre>
- *
- */
-public class V1TBSCertificateGenerator
-{
-    DERTaggedObject         version = new DERTaggedObject(0, new DERInteger(0));
-
-    DERInteger              serialNumber;
-    AlgorithmIdentifier     signature;
-    X509Name                issuer;
-    Time                    startDate, endDate;
-    X509Name                subject;
-    SubjectPublicKeyInfo    subjectPublicKeyInfo;
-
-    public V1TBSCertificateGenerator()
-    {
-    }
-
-    public void setSerialNumber(
-        DERInteger  serialNumber)
-    {
-        this.serialNumber = serialNumber;
-    }
-
-    public void setSignature(
-        AlgorithmIdentifier    signature)
-    {
-        this.signature = signature;
-    }
-
-    public void setIssuer(
-        X509Name    issuer)
-    {
-        this.issuer = issuer;
-    }
-
-    public void setStartDate(
-        Time startDate)
-    {
-        this.startDate = startDate;
-    }
-
-    public void setStartDate(
-        DERUTCTime startDate)
-    {
-        this.startDate = new Time(startDate);
-    }
-
-    public void setEndDate(
-        Time endDate)
-    {
-        this.endDate = endDate;
-    }
-
-    public void setEndDate(
-        DERUTCTime endDate)
-    {
-        this.endDate = new Time(endDate);
-    }
-
-    public void setSubject(
-        X509Name    subject)
-    {
-        this.subject = subject;
-    }
-
-    public void setSubjectPublicKeyInfo(
-        SubjectPublicKeyInfo    pubKeyInfo)
-    {
-        this.subjectPublicKeyInfo = pubKeyInfo;
-    }
-
-    public TBSCertificateStructure generateTBSCertificate()
-    {
-        if ((serialNumber == null) || (signature == null)
-            || (issuer == null) || (startDate == null) || (endDate == null)
-            || (subject == null) || (subjectPublicKeyInfo == null))
-        {
-            throw new IllegalStateException("not all mandatory fields set in V1 TBScertificate generator");
-        }
-
-        ASN1EncodableVector  seq = new ASN1EncodableVector();
-
-        // seq.add(version); - not required as default value.
-        seq.add(serialNumber);
-        seq.add(signature);
-        seq.add(issuer);
-
-        //
-        // before and after dates
-        //
-        ASN1EncodableVector  validity = new ASN1EncodableVector();
-
-        validity.add(startDate);
-        validity.add(endDate);
-
-        seq.add(new DERSequence(validity));
-
-        seq.add(subject);
-
-        seq.add(subjectPublicKeyInfo);
-
-        return new TBSCertificateStructure(new DERSequence(seq));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java b/azureus2/src/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java
deleted file mode 100644
index ed8412e..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERSet;
-
-/**
- * Generator for Version 2 AttributeCertificateInfo
- * <pre>
- * AttributeCertificateInfo ::= SEQUENCE {
- *       version              AttCertVersion -- version is v2,
- *       holder               Holder,
- *       issuer               AttCertIssuer,
- *       signature            AlgorithmIdentifier,
- *       serialNumber         CertificateSerialNumber,
- *       attrCertValidityPeriod   AttCertValidityPeriod,
- *       attributes           SEQUENCE OF Attribute,
- *       issuerUniqueID       UniqueIdentifier OPTIONAL,
- *       extensions           Extensions OPTIONAL
- * }
- * </pre>
- *
- */
-public class V2AttributeCertificateInfoGenerator
-{
-    private DERInteger version;
-    private Holder holder;
-    private AttCertIssuer issuer;
-    private AlgorithmIdentifier signature;
-    private DERInteger serialNumber;
-    private ASN1EncodableVector attributes;
-    private DERBitString issuerUniqueID;
-    private X509Extensions extensions;
-
-    // Note: validity period start/end dates stored directly
-    //private AttCertValidityPeriod attrCertValidityPeriod;
-    private DERGeneralizedTime startDate, endDate; 
-
-    public V2AttributeCertificateInfoGenerator()
-    {
-        this.version = new DERInteger(1);
-        attributes = new ASN1EncodableVector();
-    }
-    
-    public void setHolder(Holder holder)
-    {
-        this.holder = holder;
-    }
-    
-    public void addAttribute(String oid, ASN1Encodable value) 
-    {
-        attributes.add(new Attribute(new DERObjectIdentifier(oid), new DERSet(value)));
-    }
-
-    /**
-     * @param attribute
-     */
-    public void addAttribute(Attribute attribute)
-    {
-        attributes.add(attribute);
-    }
-    
-    public void setSerialNumber(
-        DERInteger  serialNumber)
-    {
-        this.serialNumber = serialNumber;
-    }
-
-    public void setSignature(
-        AlgorithmIdentifier    signature)
-    {
-        this.signature = signature;
-    }
-
-    public void setIssuer(
-        AttCertIssuer    issuer)
-    {
-        this.issuer = issuer;
-    }
-
-    public void setStartDate(
-        DERGeneralizedTime startDate)
-    {
-        this.startDate = startDate;
-    }
-
-    public void setEndDate(
-        DERGeneralizedTime endDate)
-    {
-        this.endDate = endDate;
-    }
-
-    public void setIssuerUniqueID(
-        DERBitString    issuerUniqueID)
-    {
-        this.issuerUniqueID = issuerUniqueID;
-    }
-
-    public void setExtensions(
-        X509Extensions    extensions)
-    {
-        this.extensions = extensions;
-    }
-
-    public AttributeCertificateInfo generateAttributeCertificateInfo()
-    {
-        if ((serialNumber == null) || (signature == null)
-            || (issuer == null) || (startDate == null) || (endDate == null)
-            || (holder == null) || (attributes == null))
-        {
-            throw new IllegalStateException("not all mandatory fields set in V2 AttributeCertificateInfo generator");
-        }
-
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(version);
-        v.add(holder);
-        v.add(issuer);
-        v.add(signature);
-        v.add(serialNumber);
-    
-        //
-        // before and after dates => AttCertValidityPeriod
-        //
-        AttCertValidityPeriod validity = new AttCertValidityPeriod(startDate, endDate);
-        v.add(validity);
-        
-        // Attributes
-        v.add(new DERSequence(attributes));
-        
-        if (issuerUniqueID != null)
-        {
-            v.add(issuerUniqueID);
-        }
-    
-        if (extensions != null)
-        {
-            v.add(extensions);
-        }
-
-        return new AttributeCertificateInfo(new DERSequence(v));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/V2Form.java b/azureus2/src/org/bouncycastle/asn1/x509/V2Form.java
deleted file mode 100644
index 6a229dd..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/V2Form.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-public class V2Form
-    extends ASN1Encodable
-{
-    GeneralNames        issuerName;
-    IssuerSerial        baseCertificateID;
-    ObjectDigestInfo    objectDigestInfo;
-
-    public static V2Form getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static V2Form getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof V2Form)
-        {
-            return (V2Form)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new V2Form((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-    
-    public V2Form(
-        GeneralNames    issuerName)
-    {
-        this.issuerName = issuerName;
-    }
-    
-    public V2Form(
-        ASN1Sequence seq)
-    {
-        if (seq.size() > 3)
-        {
-            throw new IllegalArgumentException("Bad sequence size: " + seq.size());
-        }
-        
-        int    index = 0;
-
-        if (!(seq.getObjectAt(0) instanceof ASN1TaggedObject))
-        {
-            index++;
-            this.issuerName = GeneralNames.getInstance(seq.getObjectAt(0));
-        }
-
-        for (int i = index; i != seq.size(); i++)
-        {
-            ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
-            if (o.getTagNo() == 0)
-            {
-                baseCertificateID = IssuerSerial.getInstance(o, false);
-            }
-            else if (o.getTagNo() == 1)
-            {
-                objectDigestInfo = ObjectDigestInfo.getInstance(o, false);
-            }
-            else 
-            {
-                throw new IllegalArgumentException("Bad tag number: "
-                        + o.getTagNo());
-            }
-        }
-    }
-    
-    public GeneralNames getIssuerName()
-    {
-        return issuerName;
-    }
-
-    public IssuerSerial getBaseCertificateID()
-    {
-        return baseCertificateID;
-    }
-
-    public ObjectDigestInfo getObjectDigestInfo()
-    {
-        return objectDigestInfo;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  V2Form ::= SEQUENCE {
-     *       issuerName            GeneralNames  OPTIONAL,
-     *       baseCertificateID     [0] IssuerSerial  OPTIONAL,
-     *       objectDigestInfo      [1] ObjectDigestInfo  OPTIONAL
-     *         -- issuerName MUST be present in this profile
-     *         -- baseCertificateID and objectDigestInfo MUST NOT
-     *         -- be present in this profile
-     *  }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        if (issuerName != null)
-        {
-            v.add(issuerName);
-        }
-
-        if (baseCertificateID != null)
-        {
-            v.add(new DERTaggedObject(false, 0, baseCertificateID));
-        }
-
-        if (objectDigestInfo != null)
-        {
-            v.add(new DERTaggedObject(false, 1, objectDigestInfo));
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java b/azureus2/src/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java
deleted file mode 100644
index f50a3b8..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTCTime;
-
-/**
- * Generator for Version 2 TBSCertList structures.
- * <pre>
- *  TBSCertList  ::=  SEQUENCE  {
- *       version                 Version OPTIONAL,
- *                                    -- if present, shall be v2
- *       signature               AlgorithmIdentifier,
- *       issuer                  Name,
- *       thisUpdate              Time,
- *       nextUpdate              Time OPTIONAL,
- *       revokedCertificates     SEQUENCE OF SEQUENCE  {
- *            userCertificate         CertificateSerialNumber,
- *            revocationDate          Time,
- *            crlEntryExtensions      Extensions OPTIONAL
- *                                          -- if present, shall be v2
- *                                 }  OPTIONAL,
- *       crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
- *                                          -- if present, shall be v2
- *                                 }
- * </pre>
- *
- * <b>Note: This class may be subject to change</b>
- */
-public class V2TBSCertListGenerator
-{
-    DERInteger version = new DERInteger(1);
-
-    AlgorithmIdentifier     signature;
-    X509Name                issuer;
-    Time                    thisUpdate, nextUpdate=null;
-    X509Extensions          extensions=null;
-    private Vector          crlentries=null;
-
-    public V2TBSCertListGenerator()
-    {
-    }
-
-
-    public void setSignature(
-        AlgorithmIdentifier    signature)
-    {
-        this.signature = signature;
-    }
-
-    public void setIssuer(
-        X509Name    issuer)
-    {
-        this.issuer = issuer;
-    }
-
-    public void setThisUpdate(
-        DERUTCTime thisUpdate)
-    {
-        this.thisUpdate = new Time(thisUpdate);
-    }
-
-    public void setNextUpdate(
-        DERUTCTime nextUpdate)
-    {
-        this.nextUpdate = new Time(nextUpdate);
-    }
-
-    public void setThisUpdate(
-        Time thisUpdate)
-    {
-        this.thisUpdate = thisUpdate;
-    }
-
-    public void setNextUpdate(
-        Time nextUpdate)
-    {
-        this.nextUpdate = nextUpdate;
-    }
-
-    public void addCRLEntry(
-        ASN1Sequence crlEntry)
-    {
-        if (crlentries == null)
-        {
-            crlentries = new Vector();
-        }
-        
-        crlentries.addElement(crlEntry);
-    }
-
-    public void addCRLEntry(DERInteger userCertificate, DERUTCTime revocationDate, int reason)
-    {
-        addCRLEntry(userCertificate, new Time(revocationDate), reason);
-    }
-
-    public void addCRLEntry(DERInteger userCertificate, Time revocationDate, int reason)
-    {
-        addCRLEntry(userCertificate, revocationDate, reason, null);
-    }
-
-    public void addCRLEntry(DERInteger userCertificate, Time revocationDate, int reason, DERGeneralizedTime invalidityDate)
-    {
-        Vector extOids = new Vector();
-        Vector extValues = new Vector();
-        
-        if (reason != 0)
-        {
-            CRLReason crlReason = new CRLReason(reason);
-            
-            try
-            {
-                extOids.addElement(X509Extensions.ReasonCode);
-                extValues.addElement(new X509Extension(false, new DEROctetString(crlReason.getEncoded())));
-            }
-            catch (IOException e)
-            {
-                throw new IllegalArgumentException("error encoding reason: " + e);
-            }
-        }
-
-        if (invalidityDate != null)
-        {
-            try
-            {
-                extOids.addElement(X509Extensions.InvalidityDate);
-                extValues.addElement(new X509Extension(false, new DEROctetString(invalidityDate.getEncoded())));
-            }
-            catch (IOException e)
-            {
-                throw new IllegalArgumentException("error encoding invalidityDate: " + e);
-            }
-        }
-        
-        if (extOids.size() != 0)
-        {
-            addCRLEntry(userCertificate, revocationDate, new X509Extensions(extOids, extValues));
-        }
-        else
-        {
-            addCRLEntry(userCertificate, revocationDate, null);
-        }
-    }
-
-    public void addCRLEntry(DERInteger userCertificate, Time revocationDate, X509Extensions extensions)
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(userCertificate);
-        v.add(revocationDate);
-        
-        if (extensions != null)
-        {
-            v.add(extensions);
-        }
-        
-        addCRLEntry(new DERSequence(v));
-    }
-    
-    public void setExtensions(
-        X509Extensions    extensions)
-    {
-        this.extensions = extensions;
-    }
-
-    public TBSCertList generateTBSCertList()
-    {
-        if ((signature == null) || (issuer == null) || (thisUpdate == null))
-        {
-            throw new IllegalStateException("Not all mandatory fields set in V2 TBSCertList generator.");
-        }
-
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(version);
-        v.add(signature);
-        v.add(issuer);
-
-        v.add(thisUpdate);
-        if (nextUpdate != null)
-        {
-            v.add(nextUpdate);
-        }
-
-        // Add CRLEntries if they exist
-        if (crlentries != null)
-        {
-            ASN1EncodableVector certs = new ASN1EncodableVector();
-            Enumeration it = crlentries.elements();
-            while(it.hasMoreElements())
-            {
-                certs.add((ASN1Sequence)it.nextElement());
-            }
-            v.add(new DERSequence(certs));
-        }
-
-        if (extensions != null)
-        {
-            v.add(new DERTaggedObject(0, extensions));
-        }
-
-        return new TBSCertList(new DERSequence(v));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java b/azureus2/src/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java
deleted file mode 100644
index ec076d4..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERUTCTime;
-
-/**
- * Generator for Version 3 TBSCertificateStructures.
- * <pre>
- * TBSCertificate ::= SEQUENCE {
- *      version          [ 0 ]  Version DEFAULT v1(0),
- *      serialNumber            CertificateSerialNumber,
- *      signature               AlgorithmIdentifier,
- *      issuer                  Name,
- *      validity                Validity,
- *      subject                 Name,
- *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
- *      issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
- *      subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
- *      extensions        [ 3 ] Extensions OPTIONAL
- *      }
- * </pre>
- *
- */
-public class V3TBSCertificateGenerator
-{
-    DERTaggedObject         version = new DERTaggedObject(0, new DERInteger(2));
-
-    DERInteger              serialNumber;
-    AlgorithmIdentifier     signature;
-    X509Name                issuer;
-    Time                    startDate, endDate;
-    X509Name                subject;
-    SubjectPublicKeyInfo    subjectPublicKeyInfo;
-    X509Extensions          extensions;
-
-    private boolean altNamePresentAndCritical;
-
-    public V3TBSCertificateGenerator()
-    {
-    }
-
-    public void setSerialNumber(
-        DERInteger  serialNumber)
-    {
-        this.serialNumber = serialNumber;
-    }
-
-    public void setSignature(
-        AlgorithmIdentifier    signature)
-    {
-        this.signature = signature;
-    }
-
-    public void setIssuer(
-        X509Name    issuer)
-    {
-        this.issuer = issuer;
-    }
-
-    public void setStartDate(
-        DERUTCTime startDate)
-    {
-        this.startDate = new Time(startDate);
-    }
-
-    public void setStartDate(
-        Time startDate)
-    {
-        this.startDate = startDate;
-    }
-
-    public void setEndDate(
-        DERUTCTime endDate)
-    {
-        this.endDate = new Time(endDate);
-    }
-
-    public void setEndDate(
-        Time endDate)
-    {
-        this.endDate = endDate;
-    }
-
-    public void setSubject(
-        X509Name    subject)
-    {
-        this.subject = subject;
-    }
-
-    public void setSubjectPublicKeyInfo(
-        SubjectPublicKeyInfo    pubKeyInfo)
-    {
-        this.subjectPublicKeyInfo = pubKeyInfo;
-    }
-
-    public void setExtensions(
-        X509Extensions    extensions)
-    {
-        this.extensions = extensions;
-        if (extensions != null)
-        {
-            X509Extension altName = extensions.getExtension(X509Extensions.SubjectAlternativeName);
-
-            if (altName != null && altName.isCritical())
-            {
-                altNamePresentAndCritical = true;
-            }
-        }
-    }
-
-    public TBSCertificateStructure generateTBSCertificate()
-    {
-        if ((serialNumber == null) || (signature == null)
-            || (issuer == null) || (startDate == null) || (endDate == null)
-            || (subject == null && !altNamePresentAndCritical) || (subjectPublicKeyInfo == null))
-        {
-            throw new IllegalStateException("not all mandatory fields set in V3 TBScertificate generator");
-        }
-
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(version);
-        v.add(serialNumber);
-        v.add(signature);
-        v.add(issuer);
-
-        //
-        // before and after dates
-        //
-        ASN1EncodableVector  validity = new ASN1EncodableVector();
-
-        validity.add(startDate);
-        validity.add(endDate);
-
-        v.add(new DERSequence(validity));
-
-        if (subject != null)
-        {
-            v.add(subject);
-        }
-        else
-        {
-            v.add(new DERSequence());
-        }
-
-        v.add(subjectPublicKeyInfo);
-
-        if (extensions != null)
-        {
-            v.add(new DERTaggedObject(3, extensions));
-        }
-
-        return new TBSCertificateStructure(new DERSequence(v));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/X509Attributes.java b/azureus2/src/org/bouncycastle/asn1/x509/X509Attributes.java
deleted file mode 100644
index 8ea18fa..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/X509Attributes.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-public class X509Attributes
-{
-    public static final DERObjectIdentifier RoleSyntax = new DERObjectIdentifier("2.5.4.72");
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/X509CertificateStructure.java b/azureus2/src/org/bouncycastle/asn1/x509/X509CertificateStructure.java
deleted file mode 100644
index 599db32..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/X509CertificateStructure.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-
-/**
- * an X509Certificate structure.
- * <pre>
- *  Certificate ::= SEQUENCE {
- *      tbsCertificate          TBSCertificate,
- *      signatureAlgorithm      AlgorithmIdentifier,
- *      signature               BIT STRING
- *  }
- * </pre>
- */
-public class X509CertificateStructure
-    extends ASN1Encodable
-    implements X509ObjectIdentifiers, PKCSObjectIdentifiers
-{
-    ASN1Sequence  seq;
-    TBSCertificateStructure tbsCert;
-    AlgorithmIdentifier     sigAlgId;
-    DERBitString            sig;
-
-    public static X509CertificateStructure getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static X509CertificateStructure getInstance(
-        Object  obj)
-    {
-        if (obj instanceof X509CertificateStructure)
-        {
-            return (X509CertificateStructure)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new X509CertificateStructure((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory");
-    }
-
-    public X509CertificateStructure(
-        ASN1Sequence  seq)
-    {
-        this.seq = seq;
-
-        //
-        // correct x509 certficate
-        //
-        if (seq.size() == 3)
-        {
-            tbsCert = TBSCertificateStructure.getInstance(seq.getObjectAt(0));
-            sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
-
-            sig = DERBitString.getInstance(seq.getObjectAt(2));
-        }
-        else
-        {
-            throw new IllegalArgumentException("sequence wrong size for a certificate");
-        }
-    }
-
-    public TBSCertificateStructure getTBSCertificate()
-    {
-        return tbsCert;
-    }
-
-    public int getVersion()
-    {
-        return tbsCert.getVersion();
-    }
-
-    public DERInteger getSerialNumber()
-    {
-        return tbsCert.getSerialNumber();
-    }
-
-    public X509Name getIssuer()
-    {
-        return tbsCert.getIssuer();
-    }
-
-    public Time getStartDate()
-    {
-        return tbsCert.getStartDate();
-    }
-
-    public Time getEndDate()
-    {
-        return tbsCert.getEndDate();
-    }
-
-    public X509Name getSubject()
-    {
-        return tbsCert.getSubject();
-    }
-
-    public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
-    {
-        return tbsCert.getSubjectPublicKeyInfo();
-    }
-
-    public AlgorithmIdentifier getSignatureAlgorithm()
-    {
-        return sigAlgId;
-    }
-
-    public DERBitString getSignature()
-    {
-        return sig;
-    }
-
-    public DERObject toASN1Object()
-    {
-        return seq;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java b/azureus2/src/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java
deleted file mode 100644
index f9801c5..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DERGeneralizedTime;
-import org.bouncycastle.asn1.DERIA5String;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.asn1.DERUTF8String;
-
-import java.io.IOException;
-
-/**
- * The default converter for X509 DN entries when going from their
- * string value to ASN.1 strings.
- */
-public class X509DefaultEntryConverter
-    extends X509NameEntryConverter
-{
-    /**
-     * Apply default coversion for the given value depending on the oid
-     * and the character range of the value.
-     * 
-     * @param oid the object identifier for the DN entry
-     * @param value the value associated with it
-     * @return the ASN.1 equivalent for the string value.
-     */
-    public DERObject getConvertedValue(
-        DERObjectIdentifier  oid,
-        String               value)
-    {
-        if (value.length() != 0 && value.charAt(0) == '#')
-        {
-            try
-            {
-                return convertHexEncoded(value, 1);
-            }
-            catch (IOException e)
-            {
-                throw new RuntimeException("can't recode value for oid " + oid.getId());
-            }
-        }
-        else if (oid.equals(X509Name.EmailAddress) || oid.equals(X509Name.DC))
-        {
-            return new DERIA5String(value);
-        }
-        else if (oid.equals(X509Name.DATE_OF_BIRTH))  // accept time string as well as # (for compatibility)
-        {
-            return new DERGeneralizedTime(value);
-        }
-        else if (oid.equals(X509Name.C) || oid.equals(X509Name.SN) || oid.equals(X509Name.DN_QUALIFIER))
-        {
-             return new DERPrintableString(value);
-        }        
-        
-        return new DERUTF8String(value);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/X509Extension.java b/azureus2/src/org/bouncycastle/asn1/x509/X509Extension.java
deleted file mode 100644
index 02ac76b..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/X509Extension.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.DERBoolean;
-
-import java.io.IOException;
-
-/**
- * an object for the elements in the X.509 V3 extension block.
- */
-public class X509Extension
-{
-    boolean             critical;
-    ASN1OctetString      value;
-
-    public X509Extension(
-        DERBoolean              critical,
-        ASN1OctetString         value)
-    {
-        this.critical = critical.isTrue();
-        this.value = value;
-    }
-
-    public X509Extension(
-        boolean                 critical,
-        ASN1OctetString         value)
-    {
-        this.critical = critical;
-        this.value = value;
-    }
-
-    public boolean isCritical()
-    {
-        return critical;
-    }
-
-    public ASN1OctetString getValue()
-    {
-        return value;
-    }
-
-    public int hashCode()
-    {
-        if (this.isCritical())
-        {
-            return this.getValue().hashCode();
-        }
-
-        
-        return ~this.getValue().hashCode();
-    }
-
-    public boolean equals(
-        Object  o)
-    {
-        if (!(o instanceof X509Extension))
-        {
-            return false;
-        }
-
-        X509Extension   other = (X509Extension)o;
-
-        return other.getValue().equals(this.getValue())
-            && (other.isCritical() == this.isCritical());
-    }
-
-    /**
-     * Convert the value of the passed in extension to an object
-     * @param ext the extension to parse
-     * @return the object the value string contains
-     * @exception IllegalArgumentException if conversion is not possible
-     */
-    public static ASN1Object convertValueToObject(
-        X509Extension ext)
-        throws IllegalArgumentException
-    {
-        try
-        {
-            return ASN1Object.fromByteArray(ext.getValue().getOctets());
-        }
-        catch (IOException e)
-        {
-            throw new IllegalArgumentException("can't convert extension: " +  e);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/X509Extensions.java b/azureus2/src/org/bouncycastle/asn1/x509/X509Extensions.java
deleted file mode 100644
index 38af70b..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/X509Extensions.java
+++ /dev/null
@@ -1,393 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERBoolean;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-public class X509Extensions
-    extends ASN1Encodable
-{
-    /**
-     * Subject Directory Attributes
-     */
-    public static final DERObjectIdentifier SubjectDirectoryAttributes = new DERObjectIdentifier("2.5.29.9");
-    
-    /**
-     * Subject Key Identifier 
-     */
-    public static final DERObjectIdentifier SubjectKeyIdentifier = new DERObjectIdentifier("2.5.29.14");
-
-    /**
-     * Key Usage 
-     */
-    public static final DERObjectIdentifier KeyUsage = new DERObjectIdentifier("2.5.29.15");
-
-    /**
-     * Private Key Usage Period 
-     */
-    public static final DERObjectIdentifier PrivateKeyUsagePeriod = new DERObjectIdentifier("2.5.29.16");
-
-    /**
-     * Subject Alternative Name 
-     */
-    public static final DERObjectIdentifier SubjectAlternativeName = new DERObjectIdentifier("2.5.29.17");
-
-    /**
-     * Issuer Alternative Name 
-     */
-    public static final DERObjectIdentifier IssuerAlternativeName = new DERObjectIdentifier("2.5.29.18");
-
-    /**
-     * Basic Constraints 
-     */
-    public static final DERObjectIdentifier BasicConstraints = new DERObjectIdentifier("2.5.29.19");
-
-    /**
-     * CRL Number 
-     */
-    public static final DERObjectIdentifier CRLNumber = new DERObjectIdentifier("2.5.29.20");
-
-    /**
-     * Reason code 
-     */
-    public static final DERObjectIdentifier ReasonCode = new DERObjectIdentifier("2.5.29.21");
-
-    /**
-     * Hold Instruction Code 
-     */
-    public static final DERObjectIdentifier InstructionCode = new DERObjectIdentifier("2.5.29.23");
-
-    /**
-     * Invalidity Date 
-     */
-    public static final DERObjectIdentifier InvalidityDate = new DERObjectIdentifier("2.5.29.24");
-
-    /**
-     * Delta CRL indicator 
-     */
-    public static final DERObjectIdentifier DeltaCRLIndicator = new DERObjectIdentifier("2.5.29.27");
-
-    /**
-     * Issuing Distribution Point 
-     */
-    public static final DERObjectIdentifier IssuingDistributionPoint = new DERObjectIdentifier("2.5.29.28");
-
-    /**
-     * Certificate Issuer 
-     */
-    public static final DERObjectIdentifier CertificateIssuer = new DERObjectIdentifier("2.5.29.29");
-
-    /**
-     * Name Constraints 
-     */
-    public static final DERObjectIdentifier NameConstraints = new DERObjectIdentifier("2.5.29.30");
-
-    /**
-     * CRL Distribution Points 
-     */
-    public static final DERObjectIdentifier CRLDistributionPoints = new DERObjectIdentifier("2.5.29.31");
-
-    /**
-     * Certificate Policies 
-     */
-    public static final DERObjectIdentifier CertificatePolicies = new DERObjectIdentifier("2.5.29.32");
-
-    /**
-     * Policy Mappings 
-     */
-    public static final DERObjectIdentifier PolicyMappings = new DERObjectIdentifier("2.5.29.33");
-
-    /**
-     * Authority Key Identifier 
-     */
-    public static final DERObjectIdentifier AuthorityKeyIdentifier = new DERObjectIdentifier("2.5.29.35");
-
-    /**
-     * Policy Constraints 
-     */
-    public static final DERObjectIdentifier PolicyConstraints = new DERObjectIdentifier("2.5.29.36");
-
-    /**
-     * Extended Key Usage 
-     */
-    public static final DERObjectIdentifier ExtendedKeyUsage = new DERObjectIdentifier("2.5.29.37");
-
-    /**
-     * Freshest CRL
-     */
-    public static final DERObjectIdentifier FreshestCRL = new DERObjectIdentifier("2.5.29.46");
-     
-    /**
-     * Inhibit Any Policy
-     */
-    public static final DERObjectIdentifier InhibitAnyPolicy = new DERObjectIdentifier("2.5.29.54");
-
-    /**
-     * Authority Info Access
-     */
-    public static final DERObjectIdentifier AuthorityInfoAccess = new DERObjectIdentifier("1.3.6.1.5.5.7.1.1");
-
-    /**
-     * Subject Info Access
-     */
-    public static final DERObjectIdentifier SubjectInfoAccess = new DERObjectIdentifier("1.3.6.1.5.5.7.1.11");
-    
-    /**
-     * Logo Type
-     */
-    public static final DERObjectIdentifier LogoType = new DERObjectIdentifier("1.3.6.1.5.5.7.1.12");
-
-    /**
-     * BiometricInfo
-     */
-    public static final DERObjectIdentifier BiometricInfo = new DERObjectIdentifier("1.3.6.1.5.5.7.1.2");
-    
-    /**
-     * QCStatements
-     */
-    public static final DERObjectIdentifier QCStatements = new DERObjectIdentifier("1.3.6.1.5.5.7.1.3");
-
-    /**
-     * Audit identity extension in attribute certificates.
-     */
-    public static final DERObjectIdentifier AuditIdentity = new DERObjectIdentifier("1.3.6.1.5.5.7.1.4");
-    
-    /**
-     * NoRevAvail extension in attribute certificates.
-     */
-    public static final DERObjectIdentifier NoRevAvail = new DERObjectIdentifier("2.5.29.56");
-
-    /**
-     * TargetInformation extension in attribute certificates.
-     */
-    public static final DERObjectIdentifier TargetInformation = new DERObjectIdentifier("2.5.29.55");
-    
-    private Hashtable               extensions = new Hashtable();
-    private Vector                  ordering = new Vector();
-
-    public static X509Extensions getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static X509Extensions getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof X509Extensions)
-        {
-            return (X509Extensions)obj;
-        }
-
-        if (obj instanceof ASN1Sequence)
-        {
-            return new X509Extensions((ASN1Sequence)obj);
-        }
-
-        if (obj instanceof ASN1TaggedObject)
-        {
-            return getInstance(((ASN1TaggedObject)obj).getObject());
-        }
-
-        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
-    }
-
-    /**
-     * Constructor from ASN1Sequence.
-     *
-     * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
-     */
-    public X509Extensions(
-        ASN1Sequence  seq)
-    {
-        Enumeration e = seq.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            ASN1Sequence            s = ASN1Sequence.getInstance(e.nextElement());
-
-            if (s.size() == 3)
-            {
-                extensions.put(s.getObjectAt(0), new X509Extension(DERBoolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2))));
-            }
-            else if (s.size() == 2)
-            {
-                extensions.put(s.getObjectAt(0), new X509Extension(false, ASN1OctetString.getInstance(s.getObjectAt(1))));
-            }
-            else
-            {
-                throw new IllegalArgumentException("Bad sequence size: " + s.size());
-            }
-
-            ordering.addElement(s.getObjectAt(0));
-        }
-    }
-
-    /**
-     * constructor from a table of extensions.
-     * <p>
-     * it's is assumed the table contains OID/String pairs.
-     */
-    public X509Extensions(
-        Hashtable  extensions)
-    {
-        this(null, extensions);
-    }
-
-    /**
-     * Constructor from a table of extensions with ordering.
-     * <p>
-     * It's is assumed the table contains OID/String pairs.
-     */
-    public X509Extensions(
-        Vector      ordering,
-        Hashtable   extensions)
-    {
-        Enumeration e;
-
-        if (ordering == null)
-        {
-            e = extensions.keys();
-        }
-        else
-        {
-            e = ordering.elements();
-        }
-
-        while (e.hasMoreElements())
-        {
-            this.ordering.addElement(e.nextElement()); 
-        }
-
-        e = this.ordering.elements();
-
-        while (e.hasMoreElements())
-        {
-            DERObjectIdentifier     oid = (DERObjectIdentifier)e.nextElement();
-            X509Extension           ext = (X509Extension)extensions.get(oid);
-
-            this.extensions.put(oid, ext);
-        }
-    }
-
-    /**
-     * Constructor from two vectors
-     * 
-     * @param objectIDs a vector of the object identifiers.
-     * @param values a vector of the extension values.
-     */
-    public X509Extensions(
-        Vector      objectIDs,
-        Vector      values)
-    {
-        Enumeration e = objectIDs.elements();
-
-        while (e.hasMoreElements())
-        {
-            this.ordering.addElement(e.nextElement()); 
-        }
-
-        int count = 0;
-        
-        e = this.ordering.elements();
-
-        while (e.hasMoreElements())
-        {
-            DERObjectIdentifier     oid = (DERObjectIdentifier)e.nextElement();
-            X509Extension           ext = (X509Extension)values.elementAt(count);
-
-            this.extensions.put(oid, ext);
-            count++;
-        }
-    }
-    
-    /**
-     * return an Enumeration of the extension field's object ids.
-     */
-    public Enumeration oids()
-    {
-        return ordering.elements();
-    }
-
-    /**
-     * return the extension represented by the object identifier
-     * passed in.
-     *
-     * @return the extension if it's present, null otherwise.
-     */
-    public X509Extension getExtension(
-        DERObjectIdentifier oid)
-    {
-        return (X509Extension)extensions.get(oid);
-    }
-
-    /**
-     * <pre>
-     *     Extensions        ::=   SEQUENCE SIZE (1..MAX) OF Extension
-     *
-     *     Extension         ::=   SEQUENCE {
-     *        extnId            EXTENSION.&id ({ExtensionSet}),
-     *        critical          BOOLEAN DEFAULT FALSE,
-     *        extnValue         OCTET STRING }
-     * </pre>
-     */
-    public DERObject toASN1Object()
-    {
-        ASN1EncodableVector     vec = new ASN1EncodableVector();
-        Enumeration             e = ordering.elements();
-
-        while (e.hasMoreElements())
-        {
-            DERObjectIdentifier     oid = (DERObjectIdentifier)e.nextElement();
-            X509Extension           ext = (X509Extension)extensions.get(oid);
-            ASN1EncodableVector     v = new ASN1EncodableVector();
-
-            v.add(oid);
-
-            if (ext.isCritical())
-            {
-                v.add(new DERBoolean(true));
-            }
-
-            v.add(ext.getValue());
-
-            vec.add(new DERSequence(v));
-        }
-
-        return new DERSequence(vec);
-    }
-
-    public boolean equivalent(
-        X509Extensions other)
-    {
-        if (extensions.size() != other.extensions.size())
-        {
-            return false;
-        }
-
-        Enumeration     e1 = extensions.keys();
-
-        while (e1.hasMoreElements())
-        {
-            Object  key = e1.nextElement();
-
-            if (!extensions.get(key).equals(other.extensions.get(key)))
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java b/azureus2/src/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java
deleted file mode 100644
index b319e2b..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DEROutputStream;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * Generator for X.509 extensions
- */
-public class X509ExtensionsGenerator
-{
-    private Hashtable extensions = new Hashtable();
-    private Vector extOrdering = new Vector();
-
-    /**
-     * Reset the generator
-     */
-    public void reset()
-    {
-        extensions = new Hashtable();
-        extOrdering = new Vector();
-    }
-
-    /**
-     * Add an extension with the given oid and the passed in value to be included
-     * in the OCTET STRING associated with the extension.
-     *
-     * @param oid  OID for the extension.
-     * @param critical  true if critical, false otherwise.
-     * @param value the ASN.1 object to be included in the extension.
-     */
-    public void addExtension(
-        DERObjectIdentifier oid,
-        boolean             critical,
-        DEREncodable        value)
-    {
-        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-        DEROutputStream dOut = new DEROutputStream(bOut);
-
-        try
-        {
-            dOut.writeObject(value);
-        }
-        catch (IOException e)
-        {
-            throw new IllegalArgumentException("error encoding value: " + e);
-        }
-
-        this.addExtension(oid, critical, bOut.toByteArray());
-    }
-
-    /**
-     * Add an extension with the given oid and the passed in byte array to be wrapped in the
-     * OCTET STRING associated with the extension.
-     *
-     * @param oid OID for the extension.
-     * @param critical true if critical, false otherwise.
-     * @param value the byte array to be wrapped.
-     */
-    public void addExtension(
-        DERObjectIdentifier oid,
-        boolean             critical,
-        byte[]              value)
-    {
-        if (extensions.containsKey(oid))
-        {
-            throw new IllegalArgumentException("extension " + oid + " already added");
-        }
-
-        extOrdering.addElement(oid);
-        extensions.put(oid, new X509Extension(critical, new DEROctetString(value)));
-    }
-
-    /**
-     * Return true if there are no extension present in this generator.
-     *
-     * @return true if empty, false otherwise
-     */
-    public boolean isEmpty()
-    {
-        return extOrdering.isEmpty();
-    }
-
-    /**
-     * Generate an X509Extensions object based on the current state of the generator.
-     *
-     * @return  an X09Extensions object.
-     */
-    public X509Extensions generate()
-    {
-        return new X509Extensions(extOrdering, extensions);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/X509Name.java b/azureus2/src/org/bouncycastle/asn1/x509/X509Name.java
deleted file mode 100644
index 11913b2..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/X509Name.java
+++ /dev/null
@@ -1,1158 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.DERString;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Hex;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * <pre>
- *     RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- *
- *     RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
- *
- *     AttributeTypeAndValue ::= SEQUENCE {
- *                                   type  OBJECT IDENTIFIER,
- *                                   value ANY }
- * </pre>
- */
-public class X509Name
-    extends ASN1Encodable
-{
-    /**
-     * country code - StringType(SIZE(2))
-     */
-    public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6");
-
-    /**
-     * organization - StringType(SIZE(1..64))
-     */
-    public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10");
-
-    /**
-     * organizational unit name - StringType(SIZE(1..64))
-     */
-    public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11");
-
-    /**
-     * Title
-     */
-    public static final DERObjectIdentifier T = new DERObjectIdentifier("2.5.4.12");
-
-    /**
-     * common name - StringType(SIZE(1..64))
-     */
-    public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3");
-
-    /**
-     * device serial number name - StringType(SIZE(1..64))
-     */
-    public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5");
-
-    /**
-     * street - StringType(SIZE(1..64))
-     */
-    public static final DERObjectIdentifier STREET = new DERObjectIdentifier("2.5.4.9");
-    
-    /**
-     * device serial number name - StringType(SIZE(1..64))
-     */
-    public static final DERObjectIdentifier SERIALNUMBER = SN;
-
-    /**
-     * locality name - StringType(SIZE(1..64))
-     */
-    public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7");
-
-    /**
-     * state, or province name - StringType(SIZE(1..64))
-     */
-    public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8");
-
-    /**
-     * Naming attributes of type X520name
-     */
-    public static final DERObjectIdentifier SURNAME = new DERObjectIdentifier("2.5.4.4");
-    public static final DERObjectIdentifier GIVENNAME = new DERObjectIdentifier("2.5.4.42");
-    public static final DERObjectIdentifier INITIALS = new DERObjectIdentifier("2.5.4.43");
-    public static final DERObjectIdentifier GENERATION = new DERObjectIdentifier("2.5.4.44");
-    public static final DERObjectIdentifier UNIQUE_IDENTIFIER = new DERObjectIdentifier("2.5.4.45");
-
-    /**
-     * businessCategory - DirectoryString(SIZE(1..128)
-     */
-    public static final DERObjectIdentifier BUSINESS_CATEGORY = new DERObjectIdentifier(
-                    "2.5.4.15");
-
-    /**
-     * postalCode - DirectoryString(SIZE(1..40)
-     */
-    public static final DERObjectIdentifier POSTAL_CODE = new DERObjectIdentifier(
-                    "2.5.4.17");
-    
-    /**
-     * dnQualifier - DirectoryString(SIZE(1..64)
-     */
-    public static final DERObjectIdentifier DN_QUALIFIER = new DERObjectIdentifier(
-                    "2.5.4.46");
-
-    /**
-     * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
-     */
-    public static final DERObjectIdentifier PSEUDONYM = new DERObjectIdentifier(
-                    "2.5.4.65");
-
-
-    /**
-     * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
-     */
-    public static final DERObjectIdentifier DATE_OF_BIRTH = new DERObjectIdentifier(
-                    "1.3.6.1.5.5.7.9.1");
-
-    /**
-     * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
-     */
-    public static final DERObjectIdentifier PLACE_OF_BIRTH = new DERObjectIdentifier(
-                    "1.3.6.1.5.5.7.9.2");
-
-    /**
-     * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
-     */
-    public static final DERObjectIdentifier GENDER = new DERObjectIdentifier(
-                    "1.3.6.1.5.5.7.9.3");
-
-    /**
-     * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
-     * codes only
-     */
-    public static final DERObjectIdentifier COUNTRY_OF_CITIZENSHIP = new DERObjectIdentifier(
-                    "1.3.6.1.5.5.7.9.4");
-
-    /**
-     * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
-     * codes only
-     */
-    public static final DERObjectIdentifier COUNTRY_OF_RESIDENCE = new DERObjectIdentifier(
-                    "1.3.6.1.5.5.7.9.5");
-
-
-    /**
-     * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
-     */
-    public static final DERObjectIdentifier NAME_AT_BIRTH =  new DERObjectIdentifier("1.3.36.8.3.14");
-
-    /**
-     * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
-     * DirectoryString(SIZE(1..30))
-     */
-    public static final DERObjectIdentifier POSTAL_ADDRESS = new DERObjectIdentifier(
-                    "2.5.4.16");
-
-    /**
-     * Email address (RSA PKCS#9 extension) - IA5String.
-     * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
-     */
-    public static final DERObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress;
-    
-    /**
-     * more from PKCS#9
-     */
-    public static final DERObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName;
-    public static final DERObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress;
-    
-    /**
-     * email address in Verisign certificates
-     */
-    public static final DERObjectIdentifier E = EmailAddress;
-    
-    /*
-     * others...
-     */
-    public static final DERObjectIdentifier DC = new DERObjectIdentifier("0.9.2342.19200300.100.1.25");
-
-    /**
-     * LDAP User id.
-     */
-    public static final DERObjectIdentifier UID = new DERObjectIdentifier("0.9.2342.19200300.100.1.1");
-
-    /**
-     * look up table translating OID values into their common symbols - this static is scheduled for deletion
-     */
-    public static Hashtable OIDLookUp = new Hashtable();
-
-    /**
-     * determines whether or not strings should be processed and printed
-     * from back to front.
-     */
-    public static boolean DefaultReverse = false;
-
-    /**
-     * default look up table translating OID values into their common symbols following
-     * the convention in RFC 2253 with a few extras
-     */
-    public static Hashtable DefaultSymbols = OIDLookUp;
-
-    /**
-     * look up table translating OID values into their common symbols following the convention in RFC 2253
-     * 
-     */
-    public static Hashtable RFC2253Symbols = new Hashtable();
-
-    /**
-     * look up table translating OID values into their common symbols following the convention in RFC 1779
-     * 
-     */
-    public static Hashtable RFC1779Symbols = new Hashtable();
-
-    /**
-     * look up table translating string values into their OIDS -
-     * this static is scheduled for deletion
-     */
-    public static Hashtable SymbolLookUp = new Hashtable();
-
-    /**
-     * look up table translating common symbols into their OIDS.
-     */
-    public static Hashtable DefaultLookUp = SymbolLookUp;
-
-    private static final Boolean TRUE = new Boolean(true); // for J2ME compatibility
-    private static final Boolean FALSE = new Boolean(false);
-
-    static
-    {
-        DefaultSymbols.put(C, "C");
-        DefaultSymbols.put(O, "O");
-        DefaultSymbols.put(T, "T");
-        DefaultSymbols.put(OU, "OU");
-        DefaultSymbols.put(CN, "CN");
-        DefaultSymbols.put(L, "L");
-        DefaultSymbols.put(ST, "ST");
-        DefaultSymbols.put(SN, "SERIALNUMBER");
-        DefaultSymbols.put(EmailAddress, "E");
-        DefaultSymbols.put(DC, "DC");
-        DefaultSymbols.put(UID, "UID");
-        DefaultSymbols.put(STREET, "STREET");
-        DefaultSymbols.put(SURNAME, "SURNAME");
-        DefaultSymbols.put(GIVENNAME, "GIVENNAME");
-        DefaultSymbols.put(INITIALS, "INITIALS");
-        DefaultSymbols.put(GENERATION, "GENERATION");
-        DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress");
-        DefaultSymbols.put(UnstructuredName, "unstructuredName");
-        DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier");
-        DefaultSymbols.put(DN_QUALIFIER, "DN");
-        DefaultSymbols.put(PSEUDONYM, "Pseudonym");
-        DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress");
-        DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth");
-        DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship");
-        DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence");
-        DefaultSymbols.put(GENDER, "Gender");
-        DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth");
-        DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth");
-        DefaultSymbols.put(POSTAL_CODE, "PostalCode");
-        DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
-
-        RFC2253Symbols.put(C, "C");
-        RFC2253Symbols.put(O, "O");
-        RFC2253Symbols.put(OU, "OU");
-        RFC2253Symbols.put(CN, "CN");
-        RFC2253Symbols.put(L, "L");
-        RFC2253Symbols.put(ST, "ST");
-        RFC2253Symbols.put(STREET, "STREET");
-        RFC2253Symbols.put(DC, "DC");
-        RFC2253Symbols.put(UID, "UID");
-
-        RFC1779Symbols.put(C, "C");
-        RFC1779Symbols.put(O, "O");
-        RFC1779Symbols.put(OU, "OU");
-        RFC1779Symbols.put(CN, "CN");
-        RFC1779Symbols.put(L, "L");
-        RFC1779Symbols.put(ST, "ST");
-        RFC1779Symbols.put(STREET, "STREET");
-
-        DefaultLookUp.put("c", C);
-        DefaultLookUp.put("o", O);
-        DefaultLookUp.put("t", T);
-        DefaultLookUp.put("ou", OU);
-        DefaultLookUp.put("cn", CN);
-        DefaultLookUp.put("l", L);
-        DefaultLookUp.put("st", ST);
-        DefaultLookUp.put("sn", SN);
-        DefaultLookUp.put("serialnumber", SN);
-        DefaultLookUp.put("street", STREET);
-        DefaultLookUp.put("emailaddress", E);
-        DefaultLookUp.put("dc", DC);
-        DefaultLookUp.put("e", E);
-        DefaultLookUp.put("uid", UID);
-        DefaultLookUp.put("surname", SURNAME);
-        DefaultLookUp.put("givenname", GIVENNAME);
-        DefaultLookUp.put("initials", INITIALS);
-        DefaultLookUp.put("generation", GENERATION);
-        DefaultLookUp.put("unstructuredaddress", UnstructuredAddress);
-        DefaultLookUp.put("unstructuredname", UnstructuredName);
-        DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER);
-        DefaultLookUp.put("dn", DN_QUALIFIER);
-        DefaultLookUp.put("pseudonym", PSEUDONYM);
-        DefaultLookUp.put("postaladdress", POSTAL_ADDRESS);
-        DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH);
-        DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP);
-        DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE);
-        DefaultLookUp.put("gender", GENDER);
-        DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH);
-        DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH);
-        DefaultLookUp.put("postalcode", POSTAL_CODE);
-        DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
-    }
-
-    private X509NameEntryConverter  converter = null;
-    private Vector                  ordering = new Vector();
-    private Vector                  values = new Vector();
-    private Vector                  added = new Vector();
-    
-    private ASN1Sequence            seq;
-
-    /**
-     * Return a X509Name based on the passed in tagged object.
-     * 
-     * @param obj tag object holding name.
-     * @param explicit true if explicitly tagged false otherwise.
-     * @return the X509Name
-     */
-    public static X509Name getInstance(
-        ASN1TaggedObject obj,
-        boolean          explicit)
-    {
-        return getInstance(ASN1Sequence.getInstance(obj, explicit));
-    }
-
-    public static X509Name getInstance(
-        Object  obj)
-    {
-        if (obj == null || obj instanceof X509Name)
-        {
-            return (X509Name)obj;
-        }
-        else if (obj instanceof ASN1Sequence)
-        {
-            return new X509Name((ASN1Sequence)obj);
-        }
-
-        throw new IllegalArgumentException("unknown object in factory \"" + obj.getClass().getName()+"\"");
-    }
-
-    /**
-     * Constructor from ASN1Sequence
-     *
-     * the principal will be a list of constructed sets, each containing an (OID, String) pair.
-     */
-    public X509Name(
-        ASN1Sequence  seq)
-    {
-        this.seq = seq;
-
-        Enumeration e = seq.getObjects();
-
-        while (e.hasMoreElements())
-        {
-            ASN1Set         set = ASN1Set.getInstance(e.nextElement());
-
-            for (int i = 0; i < set.size(); i++) 
-            {
-                   ASN1Sequence s = ASN1Sequence.getInstance(set.getObjectAt(i));
-
-                   if (s.size() != 2)
-                   {
-                       throw new IllegalArgumentException("badly sized pair");
-                   }
-
-                   ordering.addElement(DERObjectIdentifier.getInstance(s.getObjectAt(0)));
-                   
-                   DEREncodable value = s.getObjectAt(1);
-                   if (value instanceof DERString)
-                   {
-                       values.addElement(((DERString)value).getString());
-                   }
-                   else
-                   {
-                       values.addElement("#" + bytesToString(Hex.encode(value.getDERObject().getDEREncoded())));
-                   }
-                   added.addElement((i != 0) ? TRUE : FALSE);  // to allow earlier JDK compatibility
-            }
-        }
-    }
-
-    /**
-     * constructor from a table of attributes.
-     * <p>
-     * it's is assumed the table contains OID/String pairs, and the contents
-     * of the table are copied into an internal table as part of the
-     * construction process.
-     * <p>
-     * <b>Note:</b> if the name you are trying to generate should be
-     * following a specific ordering, you should use the constructor
-     * with the ordering specified below.
-     * @deprecated use an ordered constructor! The hashtable ordering is rarely correct
-     */
-    public X509Name(
-        Hashtable  attributes)
-    {
-        this(null, attributes);
-    }
-
-    /**
-     * Constructor from a table of attributes with ordering.
-     * <p>
-     * it's is assumed the table contains OID/String pairs, and the contents
-     * of the table are copied into an internal table as part of the
-     * construction process. The ordering vector should contain the OIDs
-     * in the order they are meant to be encoded or printed in toString.
-     */
-    public X509Name(
-        Vector      ordering,
-        Hashtable   attributes)
-    {
-        this(ordering, attributes, new X509DefaultEntryConverter());
-    }
-
-    /**
-     * Constructor from a table of attributes with ordering.
-     * <p>
-     * it's is assumed the table contains OID/String pairs, and the contents
-     * of the table are copied into an internal table as part of the
-     * construction process. The ordering vector should contain the OIDs
-     * in the order they are meant to be encoded or printed in toString.
-     * <p>
-     * The passed in converter will be used to convert the strings into their
-     * ASN.1 counterparts.
-     */
-    public X509Name(
-        Vector                   ordering,
-        Hashtable                attributes,
-        X509NameEntryConverter   converter)
-    {
-        this.converter = converter;
-
-        if (ordering != null)
-        {
-            for (int i = 0; i != ordering.size(); i++)
-            {
-                this.ordering.addElement(ordering.elementAt(i));
-                this.added.addElement(FALSE);
-            }
-        }
-        else
-        {
-            Enumeration     e = attributes.keys();
-
-            while (e.hasMoreElements())
-            {
-                this.ordering.addElement(e.nextElement());
-                this.added.addElement(FALSE);
-            }
-        }
-
-        for (int i = 0; i != this.ordering.size(); i++)
-        {
-            DERObjectIdentifier     oid = (DERObjectIdentifier)this.ordering.elementAt(i);
-
-            if (attributes.get(oid) == null)
-            {
-                throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name");
-            }
-
-            this.values.addElement(attributes.get(oid)); // copy the hash table
-        }
-    }
-
-    /**
-     * Takes two vectors one of the oids and the other of the values.
-     */
-    public X509Name(
-        Vector  oids,
-        Vector  values)
-    {
-        this(oids, values, new X509DefaultEntryConverter());
-    }
-
-    /**
-     * Takes two vectors one of the oids and the other of the values.
-     * <p>
-     * The passed in converter will be used to convert the strings into their
-     * ASN.1 counterparts.
-     */
-    public X509Name(
-        Vector                  oids,
-        Vector                  values,
-        X509NameEntryConverter  converter)
-    {
-        this.converter = converter;
-
-        if (oids.size() != values.size())
-        {
-            throw new IllegalArgumentException("oids vector must be same length as values.");
-        }
-
-        for (int i = 0; i < oids.size(); i++)
-        {
-            this.ordering.addElement(oids.elementAt(i));
-            this.values.addElement(values.elementAt(i));
-            this.added.addElement(FALSE);
-        }
-    }
-
-    /**
-     * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
-     * some such, converting it into an ordered set of name attributes.
-     */
-    public X509Name(
-        String  dirName)
-    {
-        this(DefaultReverse, DefaultLookUp, dirName);
-    }
-
-    /**
-     * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
-     * some such, converting it into an ordered set of name attributes with each
-     * string value being converted to its associated ASN.1 type using the passed
-     * in converter.
-     */
-    public X509Name(
-        String                  dirName,
-        X509NameEntryConverter  converter)
-    {
-        this(DefaultReverse, DefaultLookUp, dirName, converter);
-    }
-
-    /**
-     * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
-     * some such, converting it into an ordered set of name attributes. If reverse
-     * is true, create the encoded version of the sequence starting from the
-     * last element in the string.
-     */
-    public X509Name(
-        boolean reverse,
-        String  dirName)
-    {
-        this(reverse, DefaultLookUp, dirName);
-    }
-
-    /**
-     * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
-     * some such, converting it into an ordered set of name attributes with each
-     * string value being converted to its associated ASN.1 type using the passed
-     * in converter. If reverse is true the ASN.1 sequence representing the DN will
-     * be built by starting at the end of the string, rather than the start.
-     */
-    public X509Name(
-        boolean                 reverse,
-        String                  dirName,
-        X509NameEntryConverter  converter)
-    {
-        this(reverse, DefaultLookUp, dirName, converter);
-    }
-
-    /**
-     * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
-     * some such, converting it into an ordered set of name attributes. lookUp
-     * should provide a table of lookups, indexed by lowercase only strings and
-     * yielding a DERObjectIdentifier, other than that OID. and numeric oids
-     * will be processed automatically.
-     * <br>
-     * If reverse is true, create the encoded version of the sequence
-     * starting from the last element in the string.
-     * @param reverse true if we should start scanning from the end (RFC 2553).
-     * @param lookUp table of names and their oids.
-     * @param dirName the X.500 string to be parsed.
-     */
-    public X509Name(
-        boolean     reverse,
-        Hashtable   lookUp,
-        String      dirName)
-    {
-        this(reverse, lookUp, dirName, new X509DefaultEntryConverter());
-    }
-
-    private DERObjectIdentifier decodeOID(
-        String      name,
-        Hashtable   lookUp)
-    {
-        if (Strings.toUpperCase(name).startsWith("OID."))
-        {
-            return new DERObjectIdentifier(name.substring(4));
-        }
-        else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
-        {
-            return new DERObjectIdentifier(name);
-        }
-
-        DERObjectIdentifier oid = (DERObjectIdentifier)lookUp.get(Strings.toLowerCase(name));
-        if (oid == null)
-        {
-            throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
-        }
-
-        return oid;
-    }
-
-    /**
-     * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
-     * some such, converting it into an ordered set of name attributes. lookUp
-     * should provide a table of lookups, indexed by lowercase only strings and
-     * yielding a DERObjectIdentifier, other than that OID. and numeric oids
-     * will be processed automatically. The passed in converter is used to convert the
-     * string values to the right of each equals sign to their ASN.1 counterparts.
-     * <br>
-     * @param reverse true if we should start scanning from the end, false otherwise.
-     * @param lookUp table of names and oids.
-     * @param dirName the string dirName
-     * @param converter the converter to convert string values into their ASN.1 equivalents
-     */
-    public X509Name(
-        boolean                 reverse,
-        Hashtable               lookUp,
-        String                  dirName,
-        X509NameEntryConverter  converter)
-    {
-        this.converter = converter;
-        X509NameTokenizer   nTok = new X509NameTokenizer(dirName);
-
-        while (nTok.hasMoreTokens())
-        {
-            String  token = nTok.nextToken();
-            int     index = token.indexOf('=');
-
-            if (index == -1)
-            {
-                throw new IllegalArgumentException("badly formated directory string");
-            }
-
-            String              name = token.substring(0, index);
-            String              value = token.substring(index + 1);
-            DERObjectIdentifier oid = decodeOID(name, lookUp);
-
-            if (value.indexOf('+') > 0)
-            {
-                X509NameTokenizer   vTok = new X509NameTokenizer(value, '+');
-
-                this.ordering.addElement(oid);
-                this.values.addElement(vTok.nextToken());
-                this.added.addElement(FALSE);
-
-                while (vTok.hasMoreTokens())
-                {
-                    String  sv = vTok.nextToken();
-                    int     ndx = sv.indexOf('=');
-
-                    String  nm = sv.substring(0, ndx);
-                    String  vl = sv.substring(ndx + 1);
-                    this.ordering.addElement(decodeOID(nm, lookUp));
-                    this.values.addElement(vl);
-                    this.added.addElement(TRUE);
-                }
-            }
-            else
-            {
-                this.ordering.addElement(oid);
-                this.values.addElement(value);
-                this.added.addElement(FALSE);
-            }
-        }
-
-        if (reverse)
-        {
-            Vector  o = new Vector();
-            Vector  v = new Vector();
-            Vector  a = new Vector();
-            int count = 1;
-
-            for (int i = 0; i < this.ordering.size(); i++)
-            {
-                if (((Boolean)this.added.elementAt(i)).booleanValue())
-                {
-                    o.insertElementAt(this.ordering.elementAt(i), count);
-                    v.insertElementAt(this.values.elementAt(i), count);
-                    a.insertElementAt(this.added.elementAt(i), count);
-                    count++;
-                }
-                else
-                {
-                    o.insertElementAt(this.ordering.elementAt(i), 0);
-                    v.insertElementAt(this.values.elementAt(i), 0);
-                    a.insertElementAt(this.added.elementAt(i), 0);
-                    count = 1;
-                }
-            }
-
-            this.ordering = o;
-            this.values = v;
-            this.added = a;
-        }
-    }
-
-    /**
-     * return a vector of the oids in the name, in the order they were found.
-     */
-    public Vector getOIDs()
-    {
-        Vector  v = new Vector();
-
-        for (int i = 0; i != ordering.size(); i++)
-        {
-            v.addElement(ordering.elementAt(i));
-        }
-
-        return v;
-    }
-
-    /**
-     * return a vector of the values found in the name, in the order they
-     * were found.
-     */
-    public Vector getValues()
-    {
-        Vector  v = new Vector();
-
-        for (int i = 0; i != values.size(); i++)
-        {
-            v.addElement(values.elementAt(i));
-        }
-
-        return v;
-    }
-
-    /**
-     * return a vector of the values found in the name, in the order they
-     * were found, with the DN label corresponding to passed in oid.
-     */
-    public Vector getValues(
-        DERObjectIdentifier oid)
-    {
-        Vector  v = new Vector();
-
-        for (int i = 0; i != values.size(); i++)
-        {
-            if (ordering.elementAt(i).equals(oid))
-            {
-                v.addElement(values.elementAt(i));
-            }
-        }
-
-        return v;
-    }
-
-    public DERObject toASN1Object()
-    {
-        if (seq == null)
-        {
-            ASN1EncodableVector  vec = new ASN1EncodableVector();
-            ASN1EncodableVector  sVec = new ASN1EncodableVector();
-            DERObjectIdentifier  lstOid = null;
-            
-            for (int i = 0; i != ordering.size(); i++)
-            {
-                ASN1EncodableVector     v = new ASN1EncodableVector();
-                DERObjectIdentifier     oid = (DERObjectIdentifier)ordering.elementAt(i);
-
-                v.add(oid);
-
-                String  str = (String)values.elementAt(i);
-
-                v.add(converter.getConvertedValue(oid, str));
- 
-                if (lstOid == null 
-                    || ((Boolean)this.added.elementAt(i)).booleanValue())
-                {
-                    sVec.add(new DERSequence(v));
-                }
-                else
-                {
-                    vec.add(new DERSet(sVec));
-                    sVec = new ASN1EncodableVector();
-                    
-                    sVec.add(new DERSequence(v));
-                }
-                
-                lstOid = oid;
-            }
-            
-            vec.add(new DERSet(sVec));
-            
-            seq = new DERSequence(vec);
-        }
-
-        return seq;
-    }
-
-    /**
-     * @param inOrder if true the order of both X509 names must be the same,
-     * as well as the values associated with each element.
-     */
-    public boolean equals(Object obj, boolean inOrder)
-    {
-        if (!inOrder)
-        {
-            return this.equals(obj);
-        }
-
-        if (obj == this)
-        {
-            return true;
-        }
-
-        if (!(obj instanceof X509Name || obj instanceof ASN1Sequence))
-        {
-            return false;
-        }
-
-        DERObject derO = ((DEREncodable)obj).getDERObject();
-
-        if (this.getDERObject().equals(derO))
-        {
-            return true;
-        }
-
-        X509Name other;
-
-        try
-        {
-            other = X509Name.getInstance(obj);
-        }
-        catch (IllegalArgumentException e)
-        {
-            return false;
-        }
-
-        int      orderingSize = ordering.size();
-
-        if (orderingSize != other.ordering.size())
-        {
-            return false;
-        }
-
-        for (int i = 0; i < orderingSize; i++)
-        {
-            DERObjectIdentifier  oid = (DERObjectIdentifier)ordering.elementAt(i);
-            DERObjectIdentifier  oOid = (DERObjectIdentifier)other.ordering.elementAt(i);
-
-            if (oid.equals(oOid))
-            {
-                String value = (String)values.elementAt(i);
-                String oValue = (String)other.values.elementAt(i);
-
-                if (!equivalentStrings(value, oValue))
-                {
-                    return false;
-                }
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * test for equality - note: case is ignored.
-     */
-    public boolean equals(Object obj)
-    {
-        if (obj == this)
-        {
-            return true;
-        }
-
-        if (!(obj instanceof X509Name || obj instanceof ASN1Sequence))
-        {
-            return false;
-        }
-        
-        DERObject derO = ((DEREncodable)obj).getDERObject();
-        
-        if (this.getDERObject().equals(derO))
-        {
-            return true;
-        }
-
-        X509Name other;
-
-        try
-        {
-            other = X509Name.getInstance(obj);
-        }
-        catch (IllegalArgumentException e)
-        { 
-            return false;
-        }
-
-        int      orderingSize = ordering.size();
-
-        if (orderingSize != other.ordering.size())
-        {
-            return false;
-        }
-        
-        boolean[] indexes = new boolean[orderingSize];
-        int       start, end, delta;
-
-        if (ordering.elementAt(0).equals(other.ordering.elementAt(0)))   // guess forward
-        {
-            start = 0;
-            end = orderingSize;
-            delta = 1;
-        }
-        else  // guess reversed - most common problem
-        {
-            start = orderingSize - 1;
-            end = -1;
-            delta = -1;
-        }
-
-        for (int i = start; i != end; i += delta)
-        {
-            boolean              found = false;
-            DERObjectIdentifier  oid = (DERObjectIdentifier)ordering.elementAt(i);
-            String               value = (String)values.elementAt(i);
-            
-            for (int j = 0; j < orderingSize; j++)
-            {
-                if (indexes[j])
-                {
-                    continue;
-                }
-                
-                DERObjectIdentifier oOid = (DERObjectIdentifier)other.ordering.elementAt(j);
-
-                if (oid.equals(oOid))
-                {
-                    String oValue = (String)other.values.elementAt(j);
-
-                    if (equivalentStrings(value, oValue))
-                    {
-                        indexes[j] = true;
-                        found      = true;
-                        break;
-                    }
-                }
-            }
-
-            if (!found)
-            {
-                return false;
-            }
-        }
-        
-        return true;
-    }
-
-    private boolean equivalentStrings(String s1, String s2)
-    {
-        String value = Strings.toLowerCase(s1.trim());
-        String oValue = Strings.toLowerCase(s2.trim());
-
-        if (!value.equals(oValue))
-        {
-            value = stripInternalSpaces(value);
-            oValue = stripInternalSpaces(oValue);
-
-            if (!value.equals(oValue))
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    private String stripInternalSpaces(
-        String str)
-    {
-        StringBuffer res = new StringBuffer();
-
-        if (str.length() != 0)
-        {
-            char    c1 = str.charAt(0);
-
-            res.append(c1);
-
-            for (int k = 1; k < str.length(); k++)
-            {
-                char    c2 = str.charAt(k);
-                if (!(c1 == ' ' && c2 == ' '))
-                {
-                    res.append(c2);
-                }
-                c1 = c2;
-            }
-        }
-
-        return res.toString();
-    }
-
-    public int hashCode()
-    {
-        ASN1Sequence  seq = (ASN1Sequence)this.getDERObject();
-        Enumeration   e = seq.getObjects();
-        int           hashCode = 0;
-
-        while (e.hasMoreElements())
-        {
-            hashCode ^= e.nextElement().hashCode();
-        }
-
-        return hashCode;
-    }
-
-    private void appendValue(
-        StringBuffer        buf,
-        Hashtable           oidSymbols,
-        DERObjectIdentifier oid,
-        String              value)
-    {
-        String  sym = (String)oidSymbols.get(oid);
-
-        if (sym != null)
-        {
-            buf.append(sym);
-        }
-        else
-        {
-            buf.append(oid.getId());
-        }
-
-        buf.append('=');
-
-        int     index = buf.length();
-
-        buf.append(value);
-
-        int     end = buf.length();
-
-        while (index != end)
-        {
-            if ((buf.charAt(index) == ',')
-               || (buf.charAt(index) == '"')
-               || (buf.charAt(index) == '\\')
-               || (buf.charAt(index) == '+')
-               || (buf.charAt(index) == '<')
-               || (buf.charAt(index) == '>')
-               || (buf.charAt(index) == ';'))
-            {
-                buf.insert(index, "\\");
-                index++;
-                end++;
-            }
-
-            index++;
-        }
-    }
-
-    /**
-     * convert the structure to a string - if reverse is true the
-     * oids and values are listed out starting with the last element
-     * in the sequence (ala RFC 2253), otherwise the string will begin
-     * with the first element of the structure. If no string definition
-     * for the oid is found in oidSymbols the string value of the oid is
-     * added. Two standard symbol tables are provided DefaultSymbols, and
-     * RFC2253Symbols as part of this class.
-     *
-     * @param reverse if true start at the end of the sequence and work back.
-     * @param oidSymbols look up table strings for oids.
-     */
-    public String toString(
-        boolean     reverse,
-        Hashtable   oidSymbols)
-    {
-        StringBuffer            buf = new StringBuffer();
-        Vector                  components = new Vector();
-        boolean                 first = true;
-
-        StringBuffer ava = null;
-
-        for (int i = 0; i < ordering.size(); i++)
-        {
-            if (((Boolean)added.elementAt(i)).booleanValue())
-            {
-                ava.append('+');
-                appendValue(ava, oidSymbols,
-                    (DERObjectIdentifier)ordering.elementAt(i),
-                    (String)values.elementAt(i));
-            }
-            else
-            {
-                ava = new StringBuffer();
-                appendValue(ava, oidSymbols,
-                    (DERObjectIdentifier)ordering.elementAt(i),
-                    (String)values.elementAt(i));
-                components.addElement(ava);
-            }
-        }
-
-        if (reverse)
-        {
-            for (int i = components.size() - 1; i >= 0; i--)
-            {
-                if (first)
-                {
-                    first = false;
-                }
-                else
-                {
-                    buf.append(',');
-                }
-
-                buf.append(components.elementAt(i).toString());
-            }
-        }
-        else
-        {
-            for (int i = 0; i < components.size(); i++)
-            {
-                if (first)
-                {
-                    first = false;
-                }
-                else
-                {
-                    buf.append(',');
-                }
-
-                buf.append(components.elementAt(i).toString());
-            }
-        }
-
-        return buf.toString();
-    }
-
-    private String bytesToString(
-        byte[] data)
-    {
-        char[]  cs = new char[data.length];
-
-        for (int i = 0; i != cs.length; i++)
-        {
-            cs[i] = (char)(data[i] & 0xff);
-        }
-
-        return new String(cs);
-    }
-    
-    public String toString()
-    {
-        return toString(DefaultReverse, DefaultSymbols);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/X509NameEntryConverter.java b/azureus2/src/org/bouncycastle/asn1/x509/X509NameEntryConverter.java
deleted file mode 100644
index 5011322..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/X509NameEntryConverter.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERPrintableString;
-import org.bouncycastle.util.Strings;
-
-import java.io.IOException;
-
-/**
- * It turns out that the number of standard ways the fields in a DN should be 
- * encoded into their ASN.1 counterparts is rapidly approaching the
- * number of machines on the internet. By default the X509Name class 
- * will produce UTF8Strings in line with the current recommendations (RFC 3280).
- * <p>
- * An example of an encoder look like below:
- * <pre>
- * public class X509DirEntryConverter
- *     extends X509NameEntryConverter
- * {
- *     public DERObject getConvertedValue(
- *         DERObjectIdentifier  oid,
- *         String               value)
- *     {
- *         if (str.length() != 0 && str.charAt(0) == '#')
- *         {
- *             return convertHexEncoded(str, 1);
- *         }
- *         if (oid.equals(EmailAddress))
- *         {
- *             return new DERIA5String(str);
- *         }
- *         else if (canBePrintable(str))
- *         {
- *             return new DERPrintableString(str);
- *         }
- *         else if (canBeUTF8(str))
- *         {
- *             return new DERUTF8String(str);
- *         }
- *         else
- *         {
- *             return new DERBMPString(str);
- *         }
- *     }
- * }
- */
-public abstract class X509NameEntryConverter
-{
-    /**
-     * Convert an inline encoded hex string rendition of an ASN.1
-     * object back into its corresponding ASN.1 object.
-     * 
-     * @param str the hex encoded object
-     * @param off the index at which the encoding starts
-     * @return the decoded object
-     */
-    protected DERObject convertHexEncoded(
-        String  str,
-        int     off)
-        throws IOException
-    {
-        str = Strings.toLowerCase(str);
-        byte[] data = new byte[(str.length() - off) / 2];
-        for (int index = 0; index != data.length; index++)
-        {
-            char left = str.charAt((index * 2) + off);
-            char right = str.charAt((index * 2) + off + 1);
-            
-            if (left < 'a')
-            {
-                data[index] = (byte)((left - '0') << 4);
-            }
-            else
-            {
-                data[index] = (byte)((left - 'a' + 10) << 4);
-            }
-            if (right < 'a')
-            {
-                data[index] |= (byte)(right - '0');
-            }
-            else
-            {
-                data[index] |= (byte)(right - 'a' + 10);
-            }
-        }
-
-        ASN1InputStream aIn = new ASN1InputStream(data);
-                                            
-        return aIn.readObject();
-    }
-    
-    /**
-     * return true if the passed in String can be represented without
-     * loss as a PrintableString, false otherwise.
-     */
-    protected boolean canBePrintable(
-        String  str)
-    {
-        return DERPrintableString.isPrintableString(str);
-    }
-    
-    /**
-     * Convert the passed in String value into the appropriate ASN.1
-     * encoded object.
-     * 
-     * @param oid the oid associated with the value in the DN.
-     * @param value the value of the particular DN component.
-     * @return the ASN.1 equivalent for the value.
-     */
-    public abstract DERObject getConvertedValue(DERObjectIdentifier oid, String value);
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/X509NameTokenizer.java b/azureus2/src/org/bouncycastle/asn1/x509/X509NameTokenizer.java
deleted file mode 100644
index 035e924..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/X509NameTokenizer.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-/**
- * class for breaking up an X500 Name into it's component tokens, ala
- * java.util.StringTokenizer. We need this class as some of the
- * lightweight Java environment don't support classes like
- * StringTokenizer.
- */
-public class X509NameTokenizer
-{
-    private String          value;
-    private int             index;
-    private char            seperator;
-    private StringBuffer    buf = new StringBuffer();
-
-    public X509NameTokenizer(
-        String  oid)
-    {
-        this(oid, ',');
-    }
-    
-    public X509NameTokenizer(
-        String  oid,
-        char    seperator)
-    {
-        this.value = oid;
-        this.index = -1;
-        this.seperator = seperator;
-    }
-
-    public boolean hasMoreTokens()
-    {
-        return (index != value.length());
-    }
-
-    public String nextToken()
-    {
-        if (index == value.length())
-        {
-            return null;
-        }
-
-        int     end = index + 1;
-        boolean quoted = false;
-        boolean escaped = false;
-
-        buf.setLength(0);
-
-        while (end != value.length())
-        {
-            char    c = value.charAt(end);
-
-            if (c == '"')
-            {
-                if (!escaped)
-                {
-                    quoted = !quoted;
-                }
-                else
-                {
-                    buf.append(c);
-                }
-                escaped = false;
-            }
-            else
-            {
-                if (escaped || quoted)
-                {
-                    buf.append(c);
-                    escaped = false;
-                }
-                else if (c == '\\')
-                {
-                    escaped = true;
-                }
-                else if (c == seperator)
-                {
-                    break;
-                }
-                else
-                {
-                    buf.append(c);
-                }
-            }
-            end++;
-        }
-
-        index = end;
-        return buf.toString().trim();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java b/azureus2/src/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
deleted file mode 100644
index ae48c42..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.bouncycastle.asn1.x509;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-public interface X509ObjectIdentifiers
-{
-    //
-    // base id
-    //
-    static final String                 id                      = "2.5.4";
-
-    static final DERObjectIdentifier    commonName              = new DERObjectIdentifier(id + ".3");
-    static final DERObjectIdentifier    countryName             = new DERObjectIdentifier(id + ".6");
-    static final DERObjectIdentifier    localityName            = new DERObjectIdentifier(id + ".7");
-    static final DERObjectIdentifier    stateOrProvinceName     = new DERObjectIdentifier(id + ".8");
-    static final DERObjectIdentifier    organization            = new DERObjectIdentifier(id + ".10");
-    static final DERObjectIdentifier    organizationalUnitName  = new DERObjectIdentifier(id + ".11");
-
-    // id-SHA1 OBJECT IDENTIFIER ::=    
-    //   {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 }    //
-    static final DERObjectIdentifier    id_SHA1                 = new DERObjectIdentifier("1.3.14.3.2.26");
-
-    //
-    // ripemd160 OBJECT IDENTIFIER ::=
-    //      {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RIPEMD-160(1)}
-    //
-    static final DERObjectIdentifier    ripemd160               = new DERObjectIdentifier("1.3.36.3.2.1");
-
-    //
-    // ripemd160WithRSAEncryption OBJECT IDENTIFIER ::=
-    //      {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) }
-    //
-    static final DERObjectIdentifier    ripemd160WithRSAEncryption = new DERObjectIdentifier("1.3.36.3.3.1.2");
-
-
-    static final DERObjectIdentifier    id_ea_rsa = new DERObjectIdentifier("2.5.8.1.1");
-    
-    // id-pkix
-    static final DERObjectIdentifier id_pkix = new DERObjectIdentifier("1.3.6.1.5.5.7");
-
-    //
-    // private internet extensions
-    //
-    static final DERObjectIdentifier  id_pe = new DERObjectIdentifier(id_pkix + ".1");
-
-    //
-    // authority information access
-    //
-    static final DERObjectIdentifier  id_ad = new DERObjectIdentifier(id_pkix + ".48");
-    static final DERObjectIdentifier  id_ad_caIssuers = new DERObjectIdentifier(id_ad + ".2");
-    static final DERObjectIdentifier  id_ad_ocsp = new DERObjectIdentifier(id_ad + ".1");
-
-    //
-    //    OID for ocsp and crl uri in AuthorityInformationAccess extension
-    //
-    static final DERObjectIdentifier ocspAccessMethod = id_ad_ocsp;
-    static final DERObjectIdentifier crlAccessMethod = id_ad_caIssuers;
-}
-
diff --git a/azureus2/src/org/bouncycastle/asn1/x509/package.html b/azureus2/src/org/bouncycastle/asn1/x509/package.html
deleted file mode 100644
index 728921a..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x509/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and processing X.509 certificates.
-</body>
-</html>
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/KeySpecificInfo.java b/azureus2/src/org/bouncycastle/asn1/x9/KeySpecificInfo.java
deleted file mode 100644
index 02eaaaa..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/KeySpecificInfo.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * ASN.1 def for Diffie-Hellman key exchange KeySpecificInfo structure. See
- * RFC 2631, or X9.42, for further details.
- */
-public class KeySpecificInfo
-    implements DEREncodable
-{
-    private DERObjectIdentifier algorithm;
-    private ASN1OctetString      counter;
-
-    public KeySpecificInfo(
-        DERObjectIdentifier algorithm,
-        ASN1OctetString      counter)
-    {
-        this.algorithm = algorithm;
-        this.counter = counter;
-    }
-
-    public KeySpecificInfo(
-        ASN1Sequence  seq)
-    {
-        Enumeration e = seq.getObjects();
-
-        algorithm = (DERObjectIdentifier)e.nextElement();
-        counter = (ASN1OctetString)e.nextElement();
-    }
-
-    public DERObjectIdentifier getAlgorithm()
-    {
-        return algorithm;
-    }
-
-    public ASN1OctetString getCounter()
-    {
-        return counter;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  KeySpecificInfo ::= SEQUENCE {
-     *      algorithm OBJECT IDENTIFIER,
-     *      counter OCTET STRING SIZE (4..4)
-     *  }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(algorithm);
-        v.add(counter);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/OtherInfo.java b/azureus2/src/org/bouncycastle/asn1/x9/OtherInfo.java
deleted file mode 100644
index f7a5f63..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/OtherInfo.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERTaggedObject;
-
-/**
- * ANS.1 def for Diffie-Hellman key exchange OtherInfo structure. See
- * RFC 2631, or X9.42, for further details.
- */
-public class OtherInfo
-    implements DEREncodable
-{
-    private KeySpecificInfo     keyInfo;
-    private ASN1OctetString     partyAInfo;
-    private ASN1OctetString     suppPubInfo;
-
-    public OtherInfo(
-        KeySpecificInfo     keyInfo,
-        ASN1OctetString     partyAInfo,
-        ASN1OctetString     suppPubInfo)
-    {
-        this.keyInfo = keyInfo;
-        this.partyAInfo = partyAInfo;
-        this.suppPubInfo = suppPubInfo;
-    }
-
-    public OtherInfo(
-        ASN1Sequence  seq)
-    {
-        Enumeration e = seq.getObjects();
-
-        keyInfo = new KeySpecificInfo((ASN1Sequence)e.nextElement());
-
-        while (e.hasMoreElements())
-        {
-            DERTaggedObject o = (DERTaggedObject)e.nextElement();
-
-            if (o.getTagNo() == 0)
-            {
-                partyAInfo = (ASN1OctetString)o.getObject();
-            }
-            else if (o.getTagNo() == 2)
-            {
-                suppPubInfo = (ASN1OctetString)o.getObject();
-            }
-        }
-    }
-
-    public KeySpecificInfo getKeyInfo()
-    {
-        return keyInfo;
-    }
-
-    public ASN1OctetString getPartyAInfo()
-    {
-        return partyAInfo;
-    }
-
-    public ASN1OctetString getSuppPubInfo()
-    {
-        return suppPubInfo;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  OtherInfo ::= SEQUENCE {
-     *      keyInfo KeySpecificInfo,
-     *      partyAInfo [0] OCTET STRING OPTIONAL,
-     *      suppPubInfo [2] OCTET STRING
-     *  }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(keyInfo);
-
-        if (partyAInfo != null)
-        {
-            v.add(new DERTaggedObject(0, partyAInfo));
-        }
-
-        v.add(new DERTaggedObject(2, suppPubInfo));
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/X962NamedCurves.java b/azureus2/src/org/bouncycastle/asn1/x9/X962NamedCurves.java
deleted file mode 100644
index 9826a35..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/X962NamedCurves.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Set;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.util.encoders.Hex;
-
-
-/**
- * table of the current named curves defined in X.962 EC-DSA.
- */
-public class X962NamedCurves
-{
-    static final ECCurve cFp192v1 = new ECCurve.Fp(
-        new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
-        new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
-        new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16));
-
-    static final X9ECParameters prime192v1 = new X9ECParameters(
-        cFp192v1,
-        cFp192v1.decodePoint(
-            Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")),
-        new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16),
-        BigInteger.valueOf(1),
-        Hex.decode("3045AE6FC8422f64ED579528D38120EAE12196D5"));
-
-    static final ECCurve cFp192v2 = new ECCurve.Fp(
-        new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
-        new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
-        new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16));
-
-    static final X9ECParameters prime192v2 = new X9ECParameters(
-        cFp192v2,
-        cFp192v2.decodePoint(
-            Hex.decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")),
-        new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", 16),	// parg fixed F->E...
-        BigInteger.valueOf(1),
-        Hex.decode("31a92ee2029fd10d901b113e990710f0d21ac6b6"));
-
-    static final ECCurve cFp192v3 = new ECCurve.Fp(
-        new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
-        new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
-        new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16));
-
-    static final X9ECParameters prime192v3 = new X9ECParameters(
-        cFp192v3,
-        cFp192v3.decodePoint(
-            Hex.decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")),
-        new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16),
-        BigInteger.valueOf(1),
-        Hex.decode("c469684435deb378c4b65ca9591e2a5763059a2e"));
-
-    static final ECCurve cFp239v1 = new ECCurve.Fp(
-        new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
-        new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
-        new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16));
-
-    static final X9ECParameters prime239v1 = new X9ECParameters(
-        cFp239v1,
-        cFp239v1.decodePoint(
-            Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")),
-        new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16),
-        BigInteger.valueOf(1),
-        Hex.decode("e43bb460f0b80cc0c0b075798e948060f8321b7d"));
-
-    static final ECCurve cFp239v2 = new ECCurve.Fp(
-        new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
-        new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
-        new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16));
-
-    static final X9ECParameters prime239v2 = new X9ECParameters(
-        cFp239v2,
-        cFp239v2.decodePoint(
-            Hex.decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")),
-        new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16),
-        BigInteger.valueOf(1),
-        Hex.decode("e8b4011604095303ca3b8099982be09fcb9ae616"));
-
-    static final ECCurve cFp239v3 = new ECCurve.Fp(
-        new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
-        new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
-        new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16));
-
-    static final X9ECParameters prime239v3 = new X9ECParameters(
-        cFp239v3,
-        cFp239v3.decodePoint(
-            Hex.decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")),
-        new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16),
-        BigInteger.valueOf(1),
-        Hex.decode("7d7374168ffe3471b60a857686a19475d3bfa2ff"));
-
-    static final ECCurve cFp256v1 = new ECCurve.Fp(
-        new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"),
-        new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16),
-        new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16));
-
-    static final X9ECParameters prime256v1 = new X9ECParameters(
-        cFp256v1,
-        cFp256v1.decodePoint(
-            Hex.decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")),
-        new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16),
-        BigInteger.valueOf(1),
-        Hex.decode("c49d360886e704936a6678e1139d26b7819f7e90"));
-
-    static final Hashtable objIds = new Hashtable();
-    static final Hashtable curves = new Hashtable();
-    static final Hashtable names = new Hashtable();
-
-    static
-    {
-        objIds.put("prime192v1", X9ObjectIdentifiers.prime192v1);       
-        objIds.put("prime192v2", X9ObjectIdentifiers.prime192v2);       
-        objIds.put("prime192v3", X9ObjectIdentifiers.prime192v3);       
-        objIds.put("prime239v1", X9ObjectIdentifiers.prime239v1);       
-        objIds.put("prime239v2", X9ObjectIdentifiers.prime239v2);       
-        objIds.put("prime239v3", X9ObjectIdentifiers.prime239v3);       
-        objIds.put("prime256v1", X9ObjectIdentifiers.prime256v1);       
-
-        names.put(X9ObjectIdentifiers.prime192v1, "prime192v1");       
-        names.put(X9ObjectIdentifiers.prime192v2, "prime192v2");       
-        names.put(X9ObjectIdentifiers.prime192v3, "prime192v3");       
-        names.put(X9ObjectIdentifiers.prime239v1, "prime239v1");       
-        names.put(X9ObjectIdentifiers.prime239v2, "prime239v2");       
-        names.put(X9ObjectIdentifiers.prime239v3, "prime239v3");       
-        names.put(X9ObjectIdentifiers.prime256v1, "prime256v1");       
-
-        curves.put(X9ObjectIdentifiers.prime192v1, prime192v1);       
-        curves.put(X9ObjectIdentifiers.prime192v2, prime192v2);       
-        curves.put(X9ObjectIdentifiers.prime192v3, prime192v3);       
-        curves.put(X9ObjectIdentifiers.prime239v1, prime239v1);       
-        curves.put(X9ObjectIdentifiers.prime239v2, prime239v2);       
-        curves.put(X9ObjectIdentifiers.prime239v3, prime239v3);       
-        curves.put(X9ObjectIdentifiers.prime256v1, prime256v1);       
-    }
-
-    private static Set<String>	missing_oids = new HashSet<String>();
-    
-    public static X9ECParameters getByName(
-        String  name)
-    {
-        DERObjectIdentifier oid = (DERObjectIdentifier)objIds.get(name);
-
-        if (oid != null)
-        {
-            return (X9ECParameters)curves.get(oid);
-        }
-
-        return null;
-    }
-
-    /**
-     * return the X9ECParameters object for the named curve represented by
-     * the passed in object identifier. Null if the curve isn't present.
-     *
-     * @param oid an object identifier representing a named curve, if present.
-     */
-    public static X9ECParameters getByOID(
-        DERObjectIdentifier  oid)
-    {
-    	X9ECParameters result = (X9ECParameters)curves.get(oid);
-    	
-        if ( result == null ){
-        	
-        	String id = oid.getId();
-        	
-        	if ( !missing_oids.contains( id )){
-        		
-        		missing_oids.add( id );
-        		
-        		new Exception( "Missing named curve: " + id ).printStackTrace();
-        	}
-        }
-        
-        return( result );
-    }
-
-    /**
-     * return the object identifier signified by the passed in name. Null
-     * if there is no object identifier associated with name.
-     *
-     * @return the object identifier associated with name, if present.
-     */
-    public static DERObjectIdentifier getOID(
-        String  name)
-    {
-        return (DERObjectIdentifier)objIds.get(name);
-    }
-
-    /**
-     * return the named curve name represented by the given object identifier.
-     */
-    public static String getName(
-        DERObjectIdentifier  oid)
-    {
-        return (String)names.get(oid);
-    }
-
-    /**
-     * returns an enumeration containing the name strings for curves
-     * contained in this structure.
-     */
-    public static Enumeration getNames()
-    {
-        return objIds.keys();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/X962Parameters.java b/azureus2/src/org/bouncycastle/asn1/x9/X962Parameters.java
deleted file mode 100644
index bd88954..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/X962Parameters.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-public class X962Parameters
-    implements DEREncodable
-{
-    private DERObject           params = null;
-
-    public X962Parameters(
-        X9ECParameters      ecParameters)
-    {
-        this.params = ecParameters.getDERObject();
-    }
-
-    public X962Parameters(
-        DERObjectIdentifier  namedCurve)
-    {
-        this.params = namedCurve;
-    }
-
-    public X962Parameters(
-        DERObject           obj)
-    {
-        this.params = obj;
-    }
-
-    public boolean isNamedCurve()
-    {
-        return (params instanceof DERObjectIdentifier);
-    }
-
-    public DERObject getParameters()
-    {
-        return params;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     * Parameters ::= CHOICE {
-     *    ecParameters ECParameters,
-     *    namedCurve   CURVES.&id({CurveNames}),
-     *    implicitlyCA NULL
-     * }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        return params;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/X9Curve.java b/azureus2/src/org/bouncycastle/asn1/x9/X9Curve.java
deleted file mode 100644
index 70d07ac..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/X9Curve.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.math.ec.ECCurve;
-
-/**
- * ASN.1 def for Elliptic-Curve Curve structure. See
- * X9.62, for further details.
- */
-public class X9Curve
-    implements DEREncodable, X9ObjectIdentifiers
-{
-    private ECCurve     curve;
-    private byte[]      seed;
-
-	public X9Curve(
-		ECCurve     curve)
-	{
-        this.curve = curve;
-        this.seed = null;
-	}
-
-	public X9Curve(
-		ECCurve     curve,
-        byte[]      seed)
-	{
-        this.curve = curve;
-        this.seed = seed;
-	}
-
-    public X9Curve(
-        X9FieldID     fieldID,
-        ASN1Sequence  seq)
-    {
-        if (fieldID.getIdentifier().equals(prime_field))
-        {
-            BigInteger      q = ((DERInteger)fieldID.getParameters()).getValue();
-            X9FieldElement  x9A = new X9FieldElement(true, q, (ASN1OctetString)seq.getObjectAt(0));
-            X9FieldElement  x9B = new X9FieldElement(true, q, (ASN1OctetString)seq.getObjectAt(1));
-            curve = new ECCurve.Fp(q, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
-        }
-        else
-        {
-            throw new RuntimeException("not implemented");
-        }
-
-        if (seq.size() == 3)
-        {
-            seed = ((DERBitString)seq.getObjectAt(2)).getBytes();
-        }
-    }
-
-    public ECCurve  getCurve()
-    {
-        return curve;
-    }
-
-    public byte[]   getSeed()
-    {
-        return seed;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  Curve ::= SEQUENCE {
-     *      a               FieldElement,
-     *      b               FieldElement,
-     *      seed            BIT STRING      OPTIONAL
-     *  }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(new X9FieldElement(curve.getA()).getDERObject());
-        v.add(new X9FieldElement(curve.getB()).getDERObject());
-
-        if (seed != null)
-        {
-            v.add(new DERBitString(seed));
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/X9ECParameters.java b/azureus2/src/org/bouncycastle/asn1/x9/X9ECParameters.java
deleted file mode 100644
index 220084f..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/X9ECParameters.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * ASN.1 def for Elliptic-Curve ECParameters structure. See
- * X9.62, for further details.
- */
-public class X9ECParameters
-    implements DEREncodable, X9ObjectIdentifiers
-{
-    private static BigInteger   ONE = BigInteger.valueOf(1);
-
-    private X9FieldID           fieldID;
-	private ECCurve             curve;
-	private ECPoint             g;
-	private BigInteger          n;
-	private BigInteger          h;
-    private byte[]              seed;
-
-	public X9ECParameters(
-        ASN1Sequence  seq)
-    {
-        if (!(seq.getObjectAt(0) instanceof DERInteger)
-           || !((DERInteger)seq.getObjectAt(0)).getValue().equals(ONE))
-        {
-            throw new IllegalArgumentException("bad version in X9ECParameters");
-        }
-
-        X9Curve     x9c = new X9Curve(
-                        new X9FieldID((ASN1Sequence)seq.getObjectAt(1)),
-                        (ASN1Sequence)seq.getObjectAt(2));
-
-        this.curve = x9c.getCurve();
-		this.g = new X9ECPoint(curve, (ASN1OctetString)seq.getObjectAt(3)).getPoint();
-		this.n = ((DERInteger)seq.getObjectAt(4)).getValue();
-        this.seed = x9c.getSeed();
-
-        if (seq.size() == 6)
-        {
-		    this.h = ((DERInteger)seq.getObjectAt(5)).getValue();
-        }
-        else
-        {
-            this.h = ONE;
-        }
-    }
-
-	public X9ECParameters(
-		ECCurve     curve,
-		ECPoint     g,
-		BigInteger  n)
-	{
-        this(curve, g, n, ONE, null);
-	}
-
-	public X9ECParameters(
-		ECCurve     curve,
-		ECPoint     g,
-		BigInteger  n,
-        BigInteger  h)
-	{
-        this(curve, g, n, h, null);
-	}
-
-	public X9ECParameters(
-		ECCurve     curve,
-		ECPoint     g,
-		BigInteger  n,
-        BigInteger  h,
-        byte[]      seed)
-	{
-		this.curve = curve;
-		this.g = g;
-		this.n = n;
-		this.h = h;
-        this.seed = seed;
-
-        if (curve instanceof ECCurve.Fp)
-        {
-            this.fieldID = new X9FieldID(prime_field, ((ECCurve.Fp)curve).getQ());
-        }
-        else
-        {
-            this.fieldID = new X9FieldID(characteristic_two_field, null);
-        }
-	}
-
-	public ECCurve getCurve()
-	{
-		return curve;
-	}
-
-	public ECPoint getG()
-	{
-		return g;
-	}
-
-	public BigInteger getN()
-	{
-		return n;
-	}
-
-	public BigInteger getH()
-	{
-		return h;
-	}
-
-	public byte[] getSeed()
-	{
-		return seed;
-	}
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  ECParameters ::= SEQUENCE {
-     *      version         INTEGER { ecpVer1(1) } (ecpVer1),
-     *      fieldID         FieldID {{FieldTypes}},
-     *      curve           X9Curve,
-     *      base            X9ECPoint,
-     *      order           INTEGER,
-     *      cofactor        INTEGER OPTIONAL
-     *  }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(new DERInteger(1));
-        v.add(fieldID);
-        v.add(new X9Curve(curve, seed));
-        v.add(new X9ECPoint(g));
-        v.add(new DERInteger(n));
-
-        if (!h.equals(BigInteger.valueOf(1)))
-        {
-            v.add(new DERInteger(h));
-        }
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/X9ECPoint.java b/azureus2/src/org/bouncycastle/asn1/x9/X9ECPoint.java
deleted file mode 100644
index b91f022..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/X9ECPoint.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * class for describing an ECPoint as a DER object.
- */
-public class X9ECPoint
-    implements DEREncodable
-{
-    ECPoint p;
-
-    public X9ECPoint(
-        ECPoint p)
-    {
-        this.p = p;
-    }
-
-    public X9ECPoint(
-        ECCurve          c,
-        ASN1OctetString  s)
-    {
-        this.p = c.decodePoint(s.getOctets());
-    }
-
-    public ECPoint getPoint()
-    {
-        return p;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  ECPoint ::= OCTET STRING
-     * </pre>
-     * <p>
-     * Octet string produced using ECPoint.getEncoded().
-     */
-    public DERObject getDERObject()
-    {
-        return new DEROctetString(p.getEncoded());
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/X9FieldElement.java b/azureus2/src/org/bouncycastle/asn1/x9/X9FieldElement.java
deleted file mode 100644
index bc8cbde..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/X9FieldElement.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.math.ec.ECFieldElement;
-
-/**
- * class for processing an FieldElement as a DER object.
- */
-public class X9FieldElement
-    implements DEREncodable
-{
-    private ECFieldElement  f;
-
-    public X9FieldElement(
-        ECFieldElement  f)
-    {
-        this.f = f;
-    }
-
-    public X9FieldElement(
-        boolean          fP,
-        BigInteger       q,
-        ASN1OctetString  s)
-    {
-        if (fP)
-        {
-            this.f = new ECFieldElement.Fp(q, new BigInteger(1, s.getOctets()));
-        }
-        else
-        {
-            throw new RuntimeException("not implemented");
-        }
-    }
-
-    public ECFieldElement getValue()
-    {
-        return f;
-    }
-
-    /**
-     * Produce an object suitable for an ASN1OutputStream.
-     * <pre>
-     *  FieldElement ::= OCTET STRING
-     * </pre>
-     * <p>
-     * <ol>
-     * <li> if <i>q</i> is an odd prime then the field element is
-     * processed as an Integer and converted to an octet string
-     * according to x 9.62 4.3.1.</li>
-     * <li> if <i>q</i> is 2<sup>m</sup> then the bit string
-     * contained in the field element is converted into an octet
-     * string with the same ordering padded at the front if necessary.
-     * </li>
-     * </ol>
-     */
-    public DERObject getDERObject()
-    {
-        return new DEROctetString(f.toBigInteger().toByteArray());
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/X9FieldID.java b/azureus2/src/org/bouncycastle/asn1/x9/X9FieldID.java
deleted file mode 100644
index baf4b85..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/X9FieldID.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * ASN.1 def for Elliptic-Curve Field ID structure. See
- * X9.62, for further details.
- */
-public class X9FieldID
-    implements DEREncodable, X9ObjectIdentifiers
-{
-    private DERObjectIdentifier     id;
-    private DERObject               parameters;
-
-	public X9FieldID(
-        DERObjectIdentifier id,
-		BigInteger          primeP)
-	{
-        this.id = id;
-        this.parameters = new DERInteger(primeP);
-	}
-
-    public X9FieldID(
-        ASN1Sequence  seq)
-    {
-        this.id = (DERObjectIdentifier)seq.getObjectAt(0);
-        this.parameters = (DERObject)seq.getObjectAt(1);
-    }
-
-    public DERObjectIdentifier getIdentifier()
-    {
-        return id;
-    }
-
-    public DERObject getParameters()
-    {
-        return parameters;
-    }
-
-    /**
-     * Produce a DER encoding of the following structure.
-     * <pre>
-     *  FieldID ::= SEQUENCE {
-     *      fieldType       FIELD-ID.&id({IOSet}),
-     *      parameters      FIELD-ID.&Type({IOSet}{@fieldType})
-     *  }
-     * </pre>
-     */
-    public DERObject getDERObject()
-    {
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-        v.add(this.id);
-        v.add(this.parameters);
-
-        return new DERSequence(v);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/X9IntegerConverter.java b/azureus2/src/org/bouncycastle/asn1/x9/X9IntegerConverter.java
deleted file mode 100644
index ae820ab..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/X9IntegerConverter.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECFieldElement;
-
-import java.math.BigInteger;
-
-public class X9IntegerConverter
-{
-    public int getByteLength(
-        ECCurve c)
-    {
-        return (c.getFieldSize() + 7) / 8;
-    }
-
-    public int getByteLength(
-        ECFieldElement fe)
-    {
-        return (fe.getFieldSize() + 7) / 8;
-    }
-
-    public byte[] integerToBytes(
-        BigInteger s,
-        int        qLength)
-    {
-        byte[] bytes = s.toByteArray();
-        
-        if (qLength < bytes.length)
-        {
-            byte[] tmp = new byte[qLength];
-        
-            System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length);
-            
-            return tmp;
-        }
-        else if (qLength > bytes.length)
-        {
-            byte[] tmp = new byte[qLength];
-        
-            System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length);
-            
-            return tmp; 
-        }
-    
-        return bytes;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java b/azureus2/src/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
deleted file mode 100644
index a10bc81..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.asn1.x9;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-public interface X9ObjectIdentifiers
-{
-    //
-    // X9.62
-    //
-    // ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
-    //            us(840) ansi-x962(10045) }
-    //
-    static final String    ansi_X9_62 = "1.2.840.10045";
-    static final String    id_fieldType = ansi_X9_62 + ".1";
-
-    static final DERObjectIdentifier    prime_field
-                    = new DERObjectIdentifier(id_fieldType + ".1");
-
-    static final DERObjectIdentifier    characteristic_two_field
-                    = new DERObjectIdentifier(id_fieldType + ".2");
-
-    static final DERObjectIdentifier    gnBasis
-                    = new DERObjectIdentifier(id_fieldType + ".2.3.1");
-
-    static final DERObjectIdentifier    tpBasis
-                    = new DERObjectIdentifier(id_fieldType + ".2.3.2");
-
-    static final DERObjectIdentifier    ppBasis
-                    = new DERObjectIdentifier(id_fieldType + ".2.3.3");
-
-    static final String    id_ecSigType = ansi_X9_62 + ".4";
-
-    static final DERObjectIdentifier    ecdsa_with_SHA1
-                    = new DERObjectIdentifier(id_ecSigType + ".1");
-
-    static final String    id_publicKeyType = ansi_X9_62 + ".2";
-
-    static final DERObjectIdentifier    id_ecPublicKey
-                    = new DERObjectIdentifier(id_publicKeyType + ".1");
-
-    //
-    // named curves
-    //
-    static final String    ellipticCurve = ansi_X9_62 + ".3";
-
-    //
-    // Prime
-    //
-    static final String    primeCurve = ellipticCurve + ".1";
-
-    static final DERObjectIdentifier    prime192v1 =
-                    new DERObjectIdentifier(primeCurve + ".1");
-    static final DERObjectIdentifier    prime192v2 =
-                    new DERObjectIdentifier(primeCurve + ".2");
-    static final DERObjectIdentifier    prime192v3 =
-                    new DERObjectIdentifier(primeCurve + ".3");
-    static final DERObjectIdentifier    prime239v1 =
-                    new DERObjectIdentifier(primeCurve + ".4");
-    static final DERObjectIdentifier    prime239v2 =
-                    new DERObjectIdentifier(primeCurve + ".5");
-    static final DERObjectIdentifier    prime239v3 =
-                    new DERObjectIdentifier(primeCurve + ".6");
-    static final DERObjectIdentifier    prime256v1 =
-                    new DERObjectIdentifier(primeCurve + ".7");
-
-    //
-    // Diffie-Hellman
-    //
-    // dhpublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
-    //            us(840) ansi-x942(10046) number-type(2) 1 }
-    //
-    static final DERObjectIdentifier    dhpublicnumber = new DERObjectIdentifier("1.2.840.10046.2.1");
-
-    //
-    // DSA
-    //
-    // dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
-    //            us(840) ansi-x957(10040) number-type(4) 1 }
-    static final DERObjectIdentifier    id_dsa = new DERObjectIdentifier("1.2.840.10040.4.1");
-
-    /**
-     *   id-dsa-with-sha1 OBJECT IDENTIFIER ::=  { iso(1) member-body(2)
-     *         us(840) x9-57 (10040) x9cm(4) 3 }
-     */
-    public static final DERObjectIdentifier id_dsa_with_sha1 = new DERObjectIdentifier("1.2.840.10040.4.3");
-}
-
diff --git a/azureus2/src/org/bouncycastle/asn1/x9/package.html b/azureus2/src/org/bouncycastle/asn1/x9/package.html
deleted file mode 100644
index 42fc97c..0000000
--- a/azureus2/src/org/bouncycastle/asn1/x9/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Support classes useful for encoding and supporting X9.62 elliptic curve.
-</body>
-</html>
diff --git a/azureus2/src/org/bouncycastle/crypto/AsymmetricBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/AsymmetricBlockCipher.java
deleted file mode 100644
index 565effc..0000000
--- a/azureus2/src/org/bouncycastle/crypto/AsymmetricBlockCipher.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.bouncycastle.crypto;
-
-
-/**
- * base interface that a public/private key block cipher needs
- * to conform to.
- */
-public interface AsymmetricBlockCipher
-{
-    /**
-     * initialise the cipher.
-     *
-     * @param forEncryption if true the cipher is initialised for 
-     *  encryption, if false for decryption.
-     * @param param the key and other data required by the cipher.
-     */
-    public void init(boolean forEncryption, CipherParameters param);
-
-    /**
-     * returns the largest size an input block can be.
-     *
-     * @return maximum size for an input block.
-     */
-    public int getInputBlockSize();
-
-    /**
-     * returns the maximum size of the block produced by this cipher.
-     *
-     * @return maximum size of the output block produced by the cipher.
-     */
-    public int getOutputBlockSize();
-
-    /**
-     * process the block of len bytes stored in in from offset inOff.
-     *
-     * @param in the input data
-     * @param inOff offset into the in array where the data starts
-     * @param len the length of the block to be processed.
-     * @return the resulting byte array of the encryption/decryption process.
-     * @exception InvalidCipherTextException data decrypts improperly.
-     * @exception DataLengthException the input data is too large for the cipher.
-     */
-    public byte[] processBlock(byte[] in, int inOff, int len)
-        throws InvalidCipherTextException;
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java b/azureus2/src/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java
deleted file mode 100644
index 85bec73..0000000
--- a/azureus2/src/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * a holding class for public/private parameter pairs.
- */
-public class AsymmetricCipherKeyPair
-{
-    private CipherParameters    publicParam;
-    private CipherParameters    privateParam;
-
-    /**
-     * basic constructor.
-     *
-     * @param publicParam a public key parameters object.
-     * @param privateParam the corresponding private key parameters.
-     */
-    public AsymmetricCipherKeyPair(
-        CipherParameters    publicParam,
-        CipherParameters    privateParam)
-    {
-        this.publicParam = publicParam;
-        this.privateParam = privateParam;
-    }
-
-    /**
-     * return the public key parameters.
-     *
-     * @return the public key parameters.
-     */
-    public CipherParameters getPublic()
-    {
-        return publicParam;
-    }
-
-    /**
-     * return the private key parameters.
-     *
-     * @return the private key parameters.
-     */
-    public CipherParameters getPrivate()
-    {
-        return privateParam;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java b/azureus2/src/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java
deleted file mode 100644
index 236ebbe..0000000
--- a/azureus2/src/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * interface that a public/private key pair generator should conform to.
- */
-public interface AsymmetricCipherKeyPairGenerator
-{
-    /**
-     * intialise the key pair generator.
-     *
-     * @param the parameters the key pair is to be initialised with.
-     */
-    public void init(KeyGenerationParameters param);
-
-    /**
-     * return an AsymmetricCipherKeyPair containing the generated keys.
-     *
-     * @return an AsymmetricCipherKeyPair containing the generated keys.
-     */
-    public AsymmetricCipherKeyPair generateKeyPair();
-}
-
diff --git a/azureus2/src/org/bouncycastle/crypto/BasicAgreement.java b/azureus2/src/org/bouncycastle/crypto/BasicAgreement.java
deleted file mode 100644
index 4907427..0000000
--- a/azureus2/src/org/bouncycastle/crypto/BasicAgreement.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto;
-
-import java.math.BigInteger;
-
-/**
- * The basic interface that basic Diffie-Hellman implementations
- * conforms to.
- */
-public interface BasicAgreement
-{
-    /**
-     * initialise the agreement engine.
-     */
-    public void init(CipherParameters param);
-
-    /**
-     * given a public key from a given party calculate the next
-     * message in the agreement sequence. 
-     */
-    public BigInteger calculateAgreement(CipherParameters pubKey);
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/BlockCipher.java b/azureus2/src/org/bouncycastle/crypto/BlockCipher.java
deleted file mode 100644
index 1594e6d..0000000
--- a/azureus2/src/org/bouncycastle/crypto/BlockCipher.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.bouncycastle.crypto;
-
-
-/**
- * Block cipher engines are expected to conform to this interface.
- */
-public interface BlockCipher
-{
-    /**
-     * Initialise the cipher.
-     *
-     * @param forEncryption if true the cipher is initialised for
-     *  encryption, if false for decryption.
-     * @param param the key and other data required by the cipher.
-     * @exception IllegalArgumentException if the params argument is
-     * inappropriate.
-     */
-    public void init(boolean forEncryption, CipherParameters params)
-        throws IllegalArgumentException;
-
-    /**
-     * Return the name of the algorithm the cipher implements.
-     *
-     * @return the name of the algorithm the cipher implements.
-     */
-    public String getAlgorithmName();
-
-    /**
-     * Return the block size for this cipher (in bytes).
-     *
-     * @return the block size for this cipher in bytes.
-     */
-    public int getBlockSize();
-
-    /**
-     * Process one block of input from the array in and write it to
-     * the out array.
-     *
-     * @param in the array containing the input data.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the output data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
-        throws DataLengthException, IllegalStateException;
-
-    /**
-     * Reset the cipher. After resetting the cipher is in the same state
-     * as it was after the last init (if there was one).
-     */
-    public void reset();
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java
deleted file mode 100644
index 591d6cf..0000000
--- a/azureus2/src/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * a buffer wrapper for an asymmetric block cipher, allowing input
- * to be accumulated in a piecemeal fashion until final processing.
- */
-public class BufferedAsymmetricBlockCipher
-{
-	protected byte[]        buf;
-	protected int           bufOff;
-
-    private boolean                 forEncryption;
-    private AsymmetricBlockCipher   cipher;
-
-    /**
-     * base constructor.
-     *
-     * @param cipher the cipher this buffering object wraps.
-     */
-	public BufferedAsymmetricBlockCipher(
-        AsymmetricBlockCipher     cipher)
-	{
-        this.cipher = cipher;
-	}
-
-    /**
-     * return the underlying cipher for the buffer.
-     *
-     * @return the underlying cipher for the buffer.
-     */
-    public AsymmetricBlockCipher getUnderlyingCipher()
-    {
-        return cipher;
-    }
-
-    /**
-     * return the amount of data sitting in the buffer.
-     *
-     * @return the amount of data sitting in the buffer.
-     */
-    public int getBufferPosition()
-    {
-        return bufOff;
-    }
-
-    /**
-     * initialise the buffer and the underlying cipher.
-     *
-     * @param forEncryption if true the cipher is initialised for
-     *  encryption, if false for decryption.
-     * @param param the key and other data required by the cipher.
-     */
-    public void init(
-        boolean             forEncryption,
-        CipherParameters    params)
-    {
-        this.forEncryption = forEncryption;
-
-        reset();
-
-        cipher.init(forEncryption, params);
-
-        buf = new byte[cipher.getInputBlockSize()];
-        bufOff = 0;
-    }
-
-    /**
-     * returns the largest size an input block can be.
-     *
-     * @return maximum size for an input block.
-     */
-	public int getInputBlockSize()
-	{
-		return cipher.getInputBlockSize();
-	}
-
-    /**
-     * returns the maximum size of the block produced by this cipher.
-     *
-     * @return maximum size of the output block produced by the cipher.
-     */
-	public int getOutputBlockSize()
-	{
-		return cipher.getOutputBlockSize();
-	}
-
-    /**
-     * add another byte for processing.
-     * 
-     * @param in the input byte.
-     */
-	public void processByte(
-        byte        in)
-    {
-        if (bufOff > buf.length)
-        {
-            throw new DataLengthException("attempt to process message to long for cipher");
-        }
-
-        buf[bufOff++] = in;
-    }
-
-    /**
-     * add len bytes to the buffer for processing.
-     *
-     * @param in the input data
-     * @param inOff offset into the in array where the data starts
-     * @param len the length of the block to be processed.
-     */
-	public void processBytes(
-		byte[]      in,
-		int         inOff,
-		int         len)
-	{
-        if (len == 0)
-        {
-            return;
-        }
-
-        if (len < 0)
-        {
-            throw new IllegalArgumentException("Can't have a negative input length!");
-        }
-
-        if (bufOff + len > buf.length)
-        {
-            throw new DataLengthException("attempt to process message to long for cipher");
-        }
-
-        System.arraycopy(in, inOff, buf, bufOff, len);
-        bufOff += len;
-	}
-
-    /**
-     * process the contents of the buffer using the underlying
-     * cipher.
-     *
-     * @return the result of the encryption/decryption process on the
-     * buffer.
-     * @exception InvalidCipherTextException if we are given a garbage block.
-     */
-	public byte[] doFinal()
-        throws InvalidCipherTextException
-	{
-        byte[] out = cipher.processBlock(buf, 0, bufOff);
-
-        reset();
-
-        return out;
-	}
-
-	/**
-	 * Reset the buffer and the underlying cipher.
-	 */
-	public void reset()
-	{
-        /*
-         * clean the buffer.
-         */
-        if (buf != null)
-        {
-            for (int i = 0; i < buf.length; i++)
-            {
-                buf[0] = 0;
-            }
-        }
-
-        bufOff = 0;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/BufferedBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/BufferedBlockCipher.java
deleted file mode 100644
index 9af929f..0000000
--- a/azureus2/src/org/bouncycastle/crypto/BufferedBlockCipher.java
+++ /dev/null
@@ -1,324 +0,0 @@
-package org.bouncycastle.crypto;
-
-
-/**
- * A wrapper class that allows block ciphers to be used to process data in
- * a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
- * buffer is full and more data is being added, or on a doFinal.
- * <p>
- * Note: in the case where the underlying cipher is either a CFB cipher or an
- * OFB one the last block may not be a multiple of the block size.
- */
-public class BufferedBlockCipher
-{
-	protected byte[]        buf;
-	protected int           bufOff;
-
-    protected boolean       forEncryption;
-    protected BlockCipher   cipher;
-
-    protected boolean       partialBlockOkay;
-    protected boolean       pgpCFB;
-
-    /**
-     * constructor for subclasses
-     */
-    protected BufferedBlockCipher()
-    {
-    }
-
-    /**
-     * Create a buffered block cipher without padding.
-     *
-     * @param cipher the underlying block cipher this buffering object wraps.
-     * @param padded true if the buffer should add, or remove, pad bytes,
-     * false otherwise.
-     */
-	public BufferedBlockCipher(
-        BlockCipher     cipher)
-	{
-        this.cipher = cipher;
-
-        buf = new byte[cipher.getBlockSize()];
-        bufOff = 0;
-
-        //
-        // check if we can handle partial blocks on doFinal.
-        //
-        String  name = cipher.getAlgorithmName();
-        int     idx = name.indexOf('/') + 1;
-
-        pgpCFB = (idx > 0 && name.startsWith("PGP", idx));
-
-        if (pgpCFB)
-        {
-            partialBlockOkay = true;
-        }
-        else
-        {
-            partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx)));
-        }
-	}
-
-    /**
-     * return the cipher this object wraps.
-     *
-     * @return the cipher this object wraps.
-     */
-    public BlockCipher getUnderlyingCipher()
-    {
-        return cipher;
-    }
-
-    /**
-     * initialise the cipher.
-     *
-     * @param forEncryption if true the cipher is initialised for
-     *  encryption, if false for decryption.
-     * @param param the key and other data required by the cipher.
-     * @exception IllegalArgumentException if the params argument is
-     * inappropriate.
-     */
-    public void init(
-        boolean             forEncryption,
-        CipherParameters    params)
-        throws IllegalArgumentException
-    {
-        this.forEncryption = forEncryption;
-
-        reset();
-
-        cipher.init(forEncryption, params);
-    }
-
-    /**
-     * return the blocksize for the underlying cipher.
-     *
-     * @return the blocksize for the underlying cipher.
-     */
-	public int getBlockSize()
-	{
-		return cipher.getBlockSize();
-	}
-
-    /**
-     * return the size of the output buffer required for an update 
-     * an input of len bytes.
-     *
-     * @param len the length of the input.
-     * @return the space required to accommodate a call to update
-     * with len bytes of input.
-     */
-    public int getUpdateOutputSize(
-        int len)
-    {
-        int total       = len + bufOff;
-        int leftOver;
-
-        if (pgpCFB)
-        {
-            leftOver    = total % buf.length - (cipher.getBlockSize() + 2);
-        }
-        else
-        {
-            leftOver    = total % buf.length;
-        }
-
-        return total - leftOver;
-    }
-
-    /**
-     * return the size of the output buffer required for an update plus a
-     * doFinal with an input of len bytes.
-     *
-     * @param len the length of the input.
-     * @return the space required to accommodate a call to update and doFinal
-     * with len bytes of input.
-     */
-    public int getOutputSize(
-        int len)
-    {
-        int total       = len + bufOff;
-        int leftOver;
-
-        if (pgpCFB)
-        {
-            leftOver    = total % buf.length - (cipher.getBlockSize() + 2);
-        }
-        else
-        {
-            leftOver    = total % buf.length;
-            if (leftOver == 0)
-            {
-                return total;
-            }
-        }
-
-        return total - leftOver + buf.length;
-    }
-
-    /**
-     * process a single byte, producing an output block if neccessary.
-     *
-     * @param in the input byte.
-     * @param out the space for any output that might be produced.
-     * @param outOff the offset from which the output will be copied.
-     * @return the number of output bytes copied to out.
-     * @exception DataLengthException if there isn't enough space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     */
-	public int processByte(
-        byte        in,
-		byte[]      out,
-		int         outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        int         resultLen = 0;
-
-        buf[bufOff++] = in;
-
-        if (bufOff == buf.length)
-        {
-            resultLen = cipher.processBlock(buf, 0, out, outOff);
-            bufOff = 0;
-        }
-
-        return resultLen;
-    }
-
-    /**
-     * process an array of bytes, producing output if necessary.
-     *
-     * @param in the input byte array.
-     * @param inOff the offset at which the input data starts.
-     * @param len the number of bytes to be copied out of the input array.
-     * @param out the space for any output that might be produced.
-     * @param outOff the offset from which the output will be copied.
-     * @return the number of output bytes copied to out.
-     * @exception DataLengthException if there isn't enough space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     */
-	public int processBytes(
-		byte[]      in,
-		int         inOff,
-		int         len,
-		byte[]      out,
-		int         outOff)
-        throws DataLengthException, IllegalStateException
-	{
-        if (len < 0)
-        {
-            throw new IllegalArgumentException("Can't have a negative input length!");
-        }
-
-        int blockSize   = getBlockSize();
-        int length      = getUpdateOutputSize(len);
-        
-        if (length > 0)
-        {
-            if ((outOff + length) > out.length)
-            {
-                throw new DataLengthException("output buffer too short");
-            }
-        }
-
-		int resultLen = 0;
-        int gapLen = buf.length - bufOff;
-
-        if (len > gapLen)
-        {
-            System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
-            resultLen += cipher.processBlock(buf, 0, out, outOff);
-
-            bufOff = 0;
-            len -= gapLen;
-            inOff += gapLen;
-
-            while (len > buf.length)
-            {
-                resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
-
-                len -= blockSize;
-                inOff += blockSize;
-            }
-        }
-
-        System.arraycopy(in, inOff, buf, bufOff, len);
-
-        bufOff += len;
-
-        if (bufOff == buf.length)
-        {
-            resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
-            bufOff = 0;
-        }
-
-        return resultLen;
-	}
-
-    /**
-     * Process the last block in the buffer.
-     *
-     * @param out the array the block currently being held is copied into.
-     * @param outOff the offset at which the copying starts.
-     * @return the number of output bytes copied to out.
-     * @exception DataLengthException if there is insufficient space in out for
-     * the output, or the input is not block size aligned and should be.
-     * @exception IllegalStateException if the underlying cipher is not
-     * initialised.
-     * @exception InvalidCipherTextException if padding is expected and not found.
-     * @exception DataLengthException if the input is not block size
-     * aligned.
-     */
-	public int doFinal(
-        byte[]  out,
-        int     outOff)
-        throws DataLengthException, IllegalStateException, InvalidCipherTextException
-	{
-        int resultLen = 0;
-
-        if (outOff + bufOff > out.length)
-        {
-            throw new DataLengthException("output buffer too short for doFinal()");
-        }
-
-        if (bufOff != 0 && partialBlockOkay)
-        {
-            cipher.processBlock(buf, 0, buf, 0);
-            resultLen = bufOff;
-            bufOff = 0;
-            System.arraycopy(buf, 0, out, outOff, resultLen);
-        }
-        else if (bufOff != 0)
-        {
-            throw new DataLengthException("data not block size aligned");
-        }
-
-        reset();
-
-		return resultLen;
-	}
-
-    /**
-     * Reset the buffer and cipher. After resetting the object is in the same
-     * state as it was after the last init (if there was one).
-     */
-	public void reset()
-	{
-        //
-        // clean the buffer.
-        //
-        for (int i = 0; i < buf.length; i++)
-        {
-            buf[i] = 0;
-        }
-
-        bufOff = 0;
-
-        //
-        // reset the underlying cipher.
-        //
-        cipher.reset();
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/CipherKeyGenerator.java b/azureus2/src/org/bouncycastle/crypto/CipherKeyGenerator.java
deleted file mode 100644
index 451f8e8..0000000
--- a/azureus2/src/org/bouncycastle/crypto/CipherKeyGenerator.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.bouncycastle.crypto;
-
-import java.security.SecureRandom;
-
-/**
- * The base class for symmetric, or secret, cipher key generators.
- */
-public class CipherKeyGenerator
-{
-    protected SecureRandom  random;
-    protected int           strength;
-
-    /**
-     * initialise the key generator.
-     *
-     * @param param the parameters to be used for key generation
-     */
-    public void init(
-        KeyGenerationParameters param)
-    {
-        this.random = param.getRandom();
-        this.strength = (param.getStrength() + 7) / 8;
-    }
-
-    /**
-     * generate a secret key.
-     *
-     * @return a byte array containing the key value.
-     */
-    public byte[] generateKey()
-    {
-        byte[]  key = new byte[strength];
-
-        random.nextBytes(key);
-
-        return key;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/CipherParameters.java b/azureus2/src/org/bouncycastle/crypto/CipherParameters.java
deleted file mode 100644
index 5be8730..0000000
--- a/azureus2/src/org/bouncycastle/crypto/CipherParameters.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * all parameter classes implement this.
- */
-public interface CipherParameters
-{
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/CryptoException.java b/azureus2/src/org/bouncycastle/crypto/CryptoException.java
deleted file mode 100644
index 566ba38..0000000
--- a/azureus2/src/org/bouncycastle/crypto/CryptoException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * the foundation class for the hard exceptions thrown by the crypto packages.
- */
-public class CryptoException 
-    extends Exception
-{
-	
-    /**
-     * base constructor.
-     */
-    public CryptoException()
-    {
-    }
-
-    /**
-     * create a CryptoException with the given message.
-     *
-     * @param message the message to be carried with the exception.
-     */
-    public CryptoException(
-        String  message)
-    {
-        super(message);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/DSA.java b/azureus2/src/org/bouncycastle/crypto/DSA.java
deleted file mode 100644
index f0e1f99..0000000
--- a/azureus2/src/org/bouncycastle/crypto/DSA.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.crypto;
-
-import java.math.BigInteger;
-
-/**
- * interface for classes implementing the Digital Signature Algorithm
- */
-public interface DSA
-{
-    /**
-     * initialise the signer for signature generation or signature
-     * verification.
-     *
-     * @param forSigning true if we are generating a signature, false
-     * otherwise.
-     * @param param key parameters for signature generation.
-     */
-	public void init(boolean forSigning, CipherParameters param);
-
-    /**
-     * sign the passed in message (usually the output of a hash function).
-     *
-     * @param message the message to be signed.
-     * @return two big integers representing the r and s values respectively.
-     */
-	public BigInteger[] generateSignature(byte[] message);
-
-    /**
-     * verify the message message against the signature values r and s.
-     *
-     * @param message the message that was supposed to have been signed.
-     * @param r the r signature value.
-     * @param s the s signature value.
-     */
-	public boolean verifySignature(byte[] message, BigInteger  r, BigInteger s);
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/DataLengthException.java b/azureus2/src/org/bouncycastle/crypto/DataLengthException.java
deleted file mode 100644
index f36d1b5..0000000
--- a/azureus2/src/org/bouncycastle/crypto/DataLengthException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * this exception is thrown if a buffer that is meant to have output
- * copied into it turns out to be too short, or if we've been given 
- * insufficient input. In general this exception will get thrown rather
- * than an ArrayOutOfBounds exception.
- */
-public class DataLengthException 
-    extends RuntimeCryptoException
-{
-	
-    /**
-     * base constructor.
-     */
-    public DataLengthException()
-    {
-    }
-
-    /**
-     * create a DataLengthException with the given message.
-     *
-     * @param message the message to be carried with the exception.
-     */
-    public DataLengthException(
-        String  message)
-    {
-        super(message);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/DerivationFunction.java b/azureus2/src/org/bouncycastle/crypto/DerivationFunction.java
deleted file mode 100644
index ef6e29e..0000000
--- a/azureus2/src/org/bouncycastle/crypto/DerivationFunction.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * base interface for general purpose byte derivation functions.
- */
-public interface DerivationFunction
-{
-    public void init(DerivationParameters param);
-
-    /**
-     * return the message digest used as the basis for the function
-     */
-    public Digest getDigest();
-
-    public int generateBytes(byte[] out, int outOff, int len)
-        throws DataLengthException, IllegalArgumentException;
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/DerivationParameters.java b/azureus2/src/org/bouncycastle/crypto/DerivationParameters.java
deleted file mode 100644
index e11eb86..0000000
--- a/azureus2/src/org/bouncycastle/crypto/DerivationParameters.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * Parameters for key/byte stream derivation classes
- */
-public interface DerivationParameters
-{
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/Digest.java b/azureus2/src/org/bouncycastle/crypto/Digest.java
deleted file mode 100644
index 844c28b..0000000
--- a/azureus2/src/org/bouncycastle/crypto/Digest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * interface that a message digest conforms to.
- */
-public interface Digest
-{
-    /**
-     * return the algorithm name
-     *
-     * @return the algorithm name
-     */
-    public String getAlgorithmName();
-
-    /**
-     * return the size, in bytes, of the digest produced by this message digest.
-     *
-     * @return the size, in bytes, of the digest produced by this message digest.
-     */
-	public int getDigestSize();
-
-    /**
-     * update the message digest with a single byte.
-     *
-     * @param in the input byte to be entered.
-     */
-	public void update(byte in);
-
-    /**
-     * update the message digest with a block of bytes.
-     *
-     * @param in the byte array containing the data.
-     * @param inOff the offset into the byte array where the data starts.
-     * @param len the length of the data.
-     */
-	public void update(byte[] in, int inOff, int len);
-
-    /**
-     * close the digest, producing the final digest value. The doFinal
-     * call leaves the digest reset.
-     *
-     * @param out the array the digest is to be copied into.
-     * @param outOff the offset into the out array the digest is to start at.
-     */
-	public int doFinal(byte[] out, int outOff);
-
-    /**
-     * reset the digest back to it's initial state.
-     */
-    public void reset();
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/InvalidCipherTextException.java b/azureus2/src/org/bouncycastle/crypto/InvalidCipherTextException.java
deleted file mode 100644
index 59e4b26..0000000
--- a/azureus2/src/org/bouncycastle/crypto/InvalidCipherTextException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * this exception is thrown whenever we find something we don't expect in a
- * message.
- */
-public class InvalidCipherTextException 
-    extends CryptoException
-{
-    /**
-     * base constructor.
-     */
-    public InvalidCipherTextException()
-    {
-    }
-
-    /**
-     * create a InvalidCipherTextException with the given message.
-     *
-     * @param message the message to be carried with the exception.
-     */
-    public InvalidCipherTextException(
-        String  message)
-    {
-        super(message);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/KeyGenerationParameters.java b/azureus2/src/org/bouncycastle/crypto/KeyGenerationParameters.java
deleted file mode 100644
index 9a63522..0000000
--- a/azureus2/src/org/bouncycastle/crypto/KeyGenerationParameters.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.bouncycastle.crypto;
-
-import java.security.SecureRandom;
-
-/**
- * The base class for parameters to key generators.
- */
-public class KeyGenerationParameters
-{
-    private SecureRandom    random;
-    private int             strength;
-
-    /**
-     * initialise the generator with a source of randomness
-     * and a strength (in bits).
-     *
-     * @param random the random byte source.
-     * @param strength the size, in bits, of the keys we want to produce.
-     */
-    public KeyGenerationParameters(
-        SecureRandom    random,
-        int             strength)
-    {
-        this.random = random;
-        this.strength = strength;
-    }
-
-    /**
-     * return the random source associated with this
-     * generator.
-     *
-     * @return the generators random source.
-     */
-    public SecureRandom getRandom()
-    {
-        return random;
-    }
-
-    /**
-     * return the bit strength for keys produced by this generator,
-     *
-     * @return the strength of the keys this generator produces (in bits).
-     */
-    public int getStrength()
-    {
-        return strength;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/Mac.java b/azureus2/src/org/bouncycastle/crypto/Mac.java
deleted file mode 100644
index 281b189..0000000
--- a/azureus2/src/org/bouncycastle/crypto/Mac.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.bouncycastle.crypto;
-
-
-/**
- * The base interface for implementations of message authentication codes (MACs).
- */
-public interface Mac
-{
-    /**
-     * Initialise the MAC.
-     *
-     * @param param the key and other data required by the MAC.
-     * @exception IllegalArgumentException if the params argument is
-     * inappropriate.
-     */
-    public void init(CipherParameters params)
-        throws IllegalArgumentException;
-
-    /**
-     * Return the name of the algorithm the MAC implements.
-     *
-     * @return the name of the algorithm the MAC implements.
-     */
-    public String getAlgorithmName();
-
-    /**
-     * Return the block size for this cipher (in bytes).
-     *
-     * @return the block size for this cipher in bytes.
-     */
-	public int getMacSize();
-
-    /**
-     * add a single byte to the mac for processing.
-     *
-     * @param in the byte to be processed.
-     * @exception IllegalStateException if the MAC is not initialised.
-     */
-	public void update(byte in)
-        throws IllegalStateException;
-
-    /**
-     * @param in the array containing the input.
-     * @param inOff the index in the array the data begins at.
-     * @param len the length of the input starting at inOff.
-     * @exception IllegalStateException if the MAC is not initialised.
-     * @exception DataLengthException if there isn't enough data in in.
-     */
-	public void update(byte[] in, int inOff, int len)
-        throws DataLengthException, IllegalStateException;
-
-    /**
-     * Compute the final statge of the MAC writing the output to the out
-     * parameter.
-     * <p>
-     * doFinal leaves the MAC in the same state it was after the last init.
-     *
-     * @param out the array the MAC is to be output to.
-     * @param outOff the offset into the out buffer the output is to start at.
-     * @exception DataLengthException if there isn't enough space in out.
-     * @exception IllegalStateException if the MAC is not initialised.
-     */
-	public int doFinal(byte[] out, int outOff)
-        throws DataLengthException, IllegalStateException;
-
-    /**
-     * Reset the MAC. At the end of resetting the MAC should be in the
-     * in the same state it was after the last init (if there was one).
-     */
-	public void reset();
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/PBEParametersGenerator.java b/azureus2/src/org/bouncycastle/crypto/PBEParametersGenerator.java
deleted file mode 100644
index 8fb2abd..0000000
--- a/azureus2/src/org/bouncycastle/crypto/PBEParametersGenerator.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * super class for all Password Based Encyrption (PBE) parameter generator classes.
- */
-public abstract class PBEParametersGenerator
-{
-    protected byte[]  password;
-    protected byte[]  salt;
-    protected int     iterationCount;
-
-    /**
-     * base constructor.
-     */
-    protected PBEParametersGenerator()
-    {
-    }
-
-    /**
-     * initialise the PBE generator.
-     *
-     * @param password the password converted into bytes (see below).
-     * @param salt the salt to be mixed with the password.
-     * @param iterationCount the number of iterations the "mixing" function
-     * is to be applied for.
-     */
-    public void init(
-        byte[]  password,
-        byte[]  salt,
-        int     iterationCount)
-    {
-        this.password = password;
-        this.salt = salt;
-        this.iterationCount = iterationCount;
-    }
-
-    /**
-     * return the password byte array.
-     *
-     * @return the password byte array.
-     */
-    public byte[] getPassword()
-    {
-        return password;
-    }
-
-    /**
-     * return the salt byte array.
-     *
-     * @return the salt byte array.
-     */
-    public byte[] getSalt()
-    {
-        return salt;
-    }
-
-    /**
-     * return the iteration count.
-     *
-     * @return the iteration count.
-     */
-    public int getIterationCount()
-    {
-        return iterationCount;
-    }
-
-    /**
-     * generate derived parameters for a key of length keySize.
-     *
-     * @param keySize the length, in bits, of the key required.
-     * @return a parameters object representing a key.
-     */
-    public abstract CipherParameters generateDerivedParameters(int keySize);
-
-    /**
-     * generate derived parameters for a key of length keySize, and
-     * an initialisation vector (IV) of length ivSize.
-     *
-     * @param keySize the length, in bits, of the key required.
-     * @param ivSize the length, in bits, of the iv required.
-     * @return a parameters object representing a key and an IV.
-     */
-    public abstract CipherParameters generateDerivedParameters(int keySize, int ivSize);
-
-    /**
-     * generate derived parameters for a key of length keySize, specifically
-     * for use with a MAC.
-     *
-     * @param keySize the length, in bits, of the key required.
-     * @return a parameters object representing a key.
-     */
-    public abstract CipherParameters generateDerivedMacParameters(int keySize);
-
-    /**
-     * converts a password to a byte array according to the scheme in
-     * PKCS5 (ascii, no padding)
-     *
-     * @param password a character array reqpresenting the password.
-     * @return a byte array representing the password.
-     */
-    public static byte[] PKCS5PasswordToBytes(
-        char[]  password)
-    {
-        byte[]  bytes = new byte[password.length];
-
-        for (int i = 0; i != bytes.length; i++)
-        {
-            bytes[i] = (byte)password[i];
-        }
-
-        return bytes;
-    }
-
-    /**
-     * converts a password to a byte array according to the scheme in
-     * PKCS12 (unicode, big endian, 2 zero pad bytes at the end).
-     *
-     * @param password a character array reqpresenting the password.
-     * @return a byte array representing the password.
-     */
-    public static byte[] PKCS12PasswordToBytes(
-        char[]  password)
-    {
-        if (password.length > 0)
-        {
-                                       // +1 for extra 2 pad bytes.
-            byte[]  bytes = new byte[(password.length + 1) * 2];
-
-            for (int i = 0; i != password.length; i ++)
-            {
-                bytes[i * 2] = (byte)(password[i] >>> 8);
-                bytes[i * 2 + 1] = (byte)password[i];
-            }
-
-            return bytes;
-        }
-        else
-        {
-            return new byte[0];
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/RuntimeCryptoException.java b/azureus2/src/org/bouncycastle/crypto/RuntimeCryptoException.java
deleted file mode 100644
index 612734b..0000000
--- a/azureus2/src/org/bouncycastle/crypto/RuntimeCryptoException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * the foundation class for the exceptions thrown by the crypto packages.
- */
-public class RuntimeCryptoException 
-    extends RuntimeException
-{	
-    /**
-     * base constructor.
-     */
-    public RuntimeCryptoException()
-    {
-    }
-
-    /**
-     * create a RuntimeCryptoException with the given message.
-     *
-     * @param message the message to be carried with the exception.
-     */
-    public RuntimeCryptoException(
-        String  message)
-    {
-        super(message);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/StreamBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/StreamBlockCipher.java
deleted file mode 100644
index bea3b6a..0000000
--- a/azureus2/src/org/bouncycastle/crypto/StreamBlockCipher.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * a wrapper for block ciphers with a single byte block size, so that they
- * can be treated like stream ciphers.
- */
-public class StreamBlockCipher
-    implements StreamCipher
-{
-    private BlockCipher  cipher;
-
-    private byte[]  oneByte = new byte[1];
-
-    /**
-     * basic constructor.
-     *
-     * @param cipher the block cipher to be wrapped.
-     * @exception IllegalArgumentException if the cipher has a block size other than
-     * one.
-     */
-    public StreamBlockCipher(
-        BlockCipher cipher)
-    {
-        if (cipher.getBlockSize() != 1)
-        {
-            throw new IllegalArgumentException("block cipher block size != 1.");
-        }
-
-        this.cipher = cipher;
-    }
-
-    /**
-     * initialise the underlying cipher.
-     *
-     * @param forEncryption true if we are setting up for encryption, false otherwise.
-     * @param param the necessary parameters for the underlying cipher to be initialised.
-     */
-    public void init(
-        boolean forEncryption,
-        CipherParameters params)
-    {
-        cipher.init(forEncryption, params);
-    }
-
-    /**
-     * return the name of the algorithm we are wrapping.
-     *
-     * @return the name of the algorithm we are wrapping.
-     */
-    public String getAlgorithmName()
-    {
-        return cipher.getAlgorithmName();
-    }
-
-    /**
-     * encrypt/decrypt a single byte returning the result.
-     *
-     * @param in the byte to be processed.
-     * @return the result of processing the input byte.
-     */
-    public byte returnByte(
-        byte    in)
-    {
-        oneByte[0] = in;
-
-        cipher.processBlock(oneByte, 0, oneByte, 0);
-
-        return oneByte[0];
-    }
-
-    /**
-     * process a block of bytes from in putting the result into out.
-     * 
-     * @param in the input byte array.
-     * @param inOff the offset into the in array where the data to be processed starts.
-     * @param len the number of bytes to be processed.
-     * @param out the output buffer the processed bytes go into.   
-     * @param outOff the offset into the output byte array the processed data stars at.
-     * @exception DataLengthException if the output buffer is too small.
-     */
-    public void processBytes(
-        byte[]  in,
-        int     inOff,
-        int     len,
-        byte[]  out,
-        int     outOff)
-        throws DataLengthException
-    {
-        if (outOff + len > out.length)
-        {
-            throw new DataLengthException("output buffer too small in processBytes()");
-        }
-
-        for (int i = 0; i != len; i++)
-        {
-                cipher.processBlock(in, inOff + i, out, outOff + i);
-        }
-    }
-
-    /**
-     * reset the underlying cipher. This leaves it in the same state
-     * it was at after the last init (if there was one).
-     */
-    public void reset()
-    {
-        cipher.reset();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/StreamCipher.java b/azureus2/src/org/bouncycastle/crypto/StreamCipher.java
deleted file mode 100644
index 6886e8c..0000000
--- a/azureus2/src/org/bouncycastle/crypto/StreamCipher.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto;
-
-/**
- * the interface stream ciphers conform to.
- */
-public interface StreamCipher
-{
-    /**
-     * Initialise the cipher.
-     *
-     * @param forEncryption if true the cipher is initialised for
-     *  encryption, if false for decryption.
-     * @param param the key and other data required by the cipher.
-     * @exception IllegalArgumentException if the params argument is
-     * inappropriate.
-     */
-    public void init(boolean forEncryption, CipherParameters params)
-        throws IllegalArgumentException;
-
-    /**
-     * Return the name of the algorithm the cipher implements.
-     *
-     * @return the name of the algorithm the cipher implements.
-     */
-    public String getAlgorithmName();
-
-    /**
-     * encrypt/decrypt a single byte returning the result.
-     *
-     * @param in the byte to be processed.
-     * @return the result of processing the input byte.
-     */
-    public byte returnByte(byte in);
-
-    /**
-     * process a block of bytes from in putting the result into out.
-     *
-     * @param in the input byte array.
-     * @param inOff the offset into the in array where the data to be processed starts.
-     * @param len the number of bytes to be processed.
-     * @param out the output buffer the processed bytes go into.
-     * @param outOff the offset into the output byte array the processed data stars at.
-     * @exception DataLengthException if the output buffer is too small.
-     */
-    public void processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
-        throws DataLengthException;
-
-    /**
-     * reset the cipher. This leaves it in the same state
-     * it was at after the last init (if there was one).
-     */
-    public void reset();
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/Wrapper.java b/azureus2/src/org/bouncycastle/crypto/Wrapper.java
deleted file mode 100644
index 3956a6f..0000000
--- a/azureus2/src/org/bouncycastle/crypto/Wrapper.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.bouncycastle.crypto;
-
-public interface Wrapper
-{
-    public void init(boolean forWrapping, CipherParameters param);
-
-    /**
-     * Return the name of the algorithm the wrapper implements.
-     *
-     * @return the name of the algorithm the wrapper implements.
-     */
-    public String getAlgorithmName();
-
-    public byte[] wrap(byte[] in, int inOff, int inLen);
-
-    public byte[] unwrap(byte[] in, int inOff, int inLen)
-        throws InvalidCipherTextException;
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java b/azureus2/src/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
deleted file mode 100644
index abd120f..0000000
--- a/azureus2/src/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.crypto.agreement;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECPoint;
-
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-
-/**
- * P1363 7.2.1 ECSVDP-DH
- *
- * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive,
- * Diffie-Hellman version. It is based on the work of [DH76], [Mil86],
- * and [Kob87]. This primitive derives a shared secret value from one
- * party's private key and another party's public key, where both have
- * the same set of EC domain parameters. If two parties correctly
- * execute this primitive, they will produce the same output. This
- * primitive can be invoked by a scheme to derive a shared secret key;
- * specifically, it may be used with the schemes ECKAS-DH1 and
- * DL/ECKAS-DH2. It assumes that the input keys are valid (see also
- * Section 7.2.2).
- */
-public class ECDHBasicAgreement
-    implements BasicAgreement
-{
-	private ECPrivateKeyParameters key;
-
-	public void init(
-        CipherParameters key)
-	{
-		this.key = (ECPrivateKeyParameters)key;
-	}
-
-	public BigInteger calculateAgreement(
-        CipherParameters pubKey)
-	{
-        ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
-		ECPoint P = pub.getQ().multiply(key.getD());
-
-		// if ( p.isInfinity() ) throw new RuntimeException("d*Q == infinity");
-
-		return P.getX().toBigInteger();
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6Client.java b/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6Client.java
deleted file mode 100644
index 4df9023..0000000
--- a/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6Client.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.bouncycastle.crypto.agreement.srp;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-
-/**
- * Implements the client side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
- * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
- * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
- */
-public class SRP6Client
-{
-    protected BigInteger N;
-    protected BigInteger g;
-
-    protected BigInteger a;
-    protected BigInteger A;
-
-    protected BigInteger B;
-
-    protected BigInteger x;
-    protected BigInteger u;
-    protected BigInteger S;
-
-    protected Digest digest;
-    protected SecureRandom random;
-
-    public SRP6Client()
-    {
-    }
-
-    /**
-     * Initialises the client to begin new authentication attempt
-     * @param N The safe prime associated with the client's verifier
-     * @param g The group parameter associated with the client's verifier
-     * @param digest The digest algorithm associated with the client's verifier
-     * @param random For key generation
-     */
-    public void init(BigInteger N, BigInteger g, Digest digest, SecureRandom random)
-    {
-        this.N = N;
-        this.g = g;
-        this.digest = digest;
-        this.random = random;
-    }
-
-    /**
-     * Generates client's credentials given the client's salt, identity and password
-     * @param salt The salt used in the client's verifier.
-     * @param identity The user's identity (eg. username)
-     * @param password The user's password
-     * @return Client's public value to send to server
-     */
-    public BigInteger generateClientCredentials(byte[] salt, byte[] identity, byte[] password)
-    {
-        this.x = SRP6Util.calculateX(digest, N, salt, identity, password);
-        this.a = selectPrivateValue();
-        this.A = g.modPow(a, N);
-
-        return A;
-    }
-
-    /**
-     * Generates client's verification message given the server's credentials
-     * @param serverB The server's credentials
-     * @return Client's verification message for the server
-     * @throws CryptoException If server's credentials are invalid
-     */
-    public BigInteger calculateSecret(BigInteger serverB) throws CryptoException
-    {
-        this.B = SRP6Util.validatePublicValue(N, serverB);
-        this.u = SRP6Util.calculateU(digest, N, A, B);
-        this.S = calculateS();
-
-        return S;
-    }
-
-    protected BigInteger selectPrivateValue()
-    {
-        return SRP6Util.generatePrivateValue(digest, N, g, random);        
-    }
-
-    private BigInteger calculateS()
-    {
-        BigInteger k = SRP6Util.calculateK(digest, N, g);
-        BigInteger exp = u.multiply(x).add(a);
-        BigInteger tmp = g.modPow(x, N).multiply(k).mod(N);
-        return B.subtract(tmp).mod(N).modPow(exp, N);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6Server.java b/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6Server.java
deleted file mode 100644
index fb20838..0000000
--- a/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6Server.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.bouncycastle.crypto.agreement.srp;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-
-/**
- * Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
- * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
- * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
- */
-public class SRP6Server
-{
-    protected BigInteger N;
-    protected BigInteger g;
-    protected BigInteger v;
-
-    protected SecureRandom random;
-    protected Digest digest;
-
-    protected BigInteger A;
-
-    protected BigInteger b;
-    protected BigInteger B;
-
-    protected BigInteger u;
-    protected BigInteger S;
-
-    public SRP6Server()
-    {
-    }
-
-    /**
-     * Initialises the server to accept a new client authentication attempt
-     * @param N The safe prime associated with the client's verifier
-     * @param g The group parameter associated with the client's verifier
-     * @param v The client's verifier
-     * @param digest The digest algorithm associated with the client's verifier
-     * @param random For key generation
-     */
-    public void init(BigInteger N, BigInteger g, BigInteger v, Digest digest, SecureRandom random)
-    {
-        this.N = N;
-        this.g = g;
-        this.v = v;
-
-        this.random = random;
-        this.digest = digest;
-    }
-
-    /**
-     * Generates the server's credentials that are to be sent to the client.
-     * @return The server's public value to the client
-     */
-    public BigInteger generateServerCredentials()
-    {
-        BigInteger k = SRP6Util.calculateK(digest, N, g);
-        this.b = selectPrivateValue();
-        this.B = k.multiply(v).mod(N).add(g.modPow(b, N)).mod(N);
-
-        return B;
-    }
-
-    /**
-     * Processes the client's credentials. If valid the shared secret is generated and returned.
-     * @param clientA The client's credentials
-     * @return A shared secret BigInteger
-     * @throws CryptoException If client's credentials are invalid
-     */
-    public BigInteger calculateSecret(BigInteger clientA) throws CryptoException
-    {
-        this.A = SRP6Util.validatePublicValue(N, clientA);
-        this.u = SRP6Util.calculateU(digest, N, A, B);
-        this.S = calculateS();
-
-        return S;
-    }
-
-    protected BigInteger selectPrivateValue()
-    {
-        return SRP6Util.generatePrivateValue(digest, N, g, random);        
-    }
-
-    private BigInteger calculateS()
-    {
-        return v.modPow(u, N).multiply(A).mod(N).modPow(b, N);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6Util.java b/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6Util.java
deleted file mode 100644
index ad5ceac..0000000
--- a/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6Util.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.bouncycastle.crypto.agreement.srp;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CryptoException;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.util.BigIntegers;
-
-public class SRP6Util
-{
-    private static BigInteger ZERO = BigInteger.valueOf(0);
-    private static BigInteger ONE = BigInteger.valueOf(1);
-
-    public static BigInteger calculateK(Digest digest, BigInteger N, BigInteger g)
-    {
-        return hashPaddedPair(digest, N, N, g);
-    }
-
-    public static BigInteger calculateU(Digest digest, BigInteger N, BigInteger A, BigInteger B)
-    {
-        return hashPaddedPair(digest, N, A, B);
-    }
-
-    public static BigInteger calculateX(Digest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
-    {
-        byte[] output = new byte[digest.getDigestSize()];
-
-        digest.update(identity, 0, identity.length);
-        digest.update((byte)':');
-        digest.update(password, 0, password.length);
-        digest.doFinal(output, 0);
-
-        digest.update(salt, 0, salt.length);
-        digest.update(output, 0, output.length);
-        digest.doFinal(output, 0);
-
-        return new BigInteger(1, output);
-    }
-
-    public static BigInteger generatePrivateValue(Digest digest, BigInteger N, BigInteger g, SecureRandom random)
-    {
-        int minBits = Math.min(256, N.bitLength() / 2);
-        BigInteger min = ONE.shiftLeft(minBits - 1);
-        BigInteger max = N.subtract(ONE);
-
-        return BigIntegers.createRandomInRange(min, max, random);
-    }
-
-    public static BigInteger validatePublicValue(BigInteger N, BigInteger val)
-        throws CryptoException
-    {
-        val = val.mod(N);
-
-        // Check that val % N != 0
-        if (val.equals(ZERO))
-        {
-            throw new CryptoException("Invalid public value: 0");
-        }
-
-        return val;
-    }
-
-    private static BigInteger hashPaddedPair(Digest digest, BigInteger N, BigInteger n1, BigInteger n2)
-    {
-        int padLength = (N.bitLength() + 7) / 8;
-
-        byte[] n1_bytes = getPadded(n1, padLength);
-        byte[] n2_bytes = getPadded(n2, padLength);
-
-        digest.update(n1_bytes, 0, n1_bytes.length);
-        digest.update(n2_bytes, 0, n2_bytes.length);
-
-        byte[] output = new byte[digest.getDigestSize()];
-        digest.doFinal(output, 0);
-
-        return new BigInteger(1, output);
-    }
-
-    private static byte[] getPadded(BigInteger n, int length)
-    {
-        byte[] bs = BigIntegers.asUnsignedByteArray(n);
-        if (bs.length < length)
-        {
-            byte[] tmp = new byte[length];
-            System.arraycopy(bs, 0, tmp, length - bs.length, bs.length);
-            bs = tmp;
-        }
-        return bs;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java b/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java
deleted file mode 100644
index 631ecc6..0000000
--- a/azureus2/src/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.bouncycastle.crypto.agreement.srp;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * Generates new SRP verifier for user
- */
-public class SRP6VerifierGenerator
-{
-    protected BigInteger N;
-    protected BigInteger g;
-    protected Digest digest;
-
-    public SRP6VerifierGenerator()
-    {
-    }
-
-    /**
-     * Initialises generator to create new verifiers
-     * @param N The safe prime to use (see DHParametersGenerator)
-     * @param g The group parameter to use (see DHParametersGenerator)
-     * @param digest The digest to use. The same digest type will need to be used later for the actual authentication
-     * attempt. Also note that the final session key size is dependent on the chosen digest.
-     */
-    public void init(BigInteger N, BigInteger g, Digest digest)
-    {
-        this.N = N;
-        this.g = g;
-        this.digest = digest;
-    }
-
-    /**
-     * Creates a new SRP verifier
-     * @param salt The salt to use, generally should be large and random
-     * @param identity The user's identifying information (eg. username)
-     * @param password The user's password
-     * @return A new verifier for use in future SRP authentication
-     */
-    public BigInteger generateVerifier(byte[] salt, byte[] identity, byte[] password)
-    {
-        BigInteger x = SRP6Util.calculateX(digest, N, salt, identity, password);
-
-        return g.modPow(x, N);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/GeneralDigest.java b/azureus2/src/org/bouncycastle/crypto/digests/GeneralDigest.java
deleted file mode 100644
index 2d319b7..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/GeneralDigest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * base implementation of MD4 family style digest as outlined in
- * "Handbook of Applied Cryptography", pages 344 - 347.
- */
-public abstract class GeneralDigest
-    implements Digest
-{
-    private byte[]  xBuf;
-    private int     xBufOff;
-
-    private long    byteCount;
-
-	/**
-	 * Standard constructor
-	 */
-	protected GeneralDigest()
-	{
-		xBuf = new byte[4];
-		xBufOff = 0;
-	}
-
-	/**
-	 * Copy constructor.  We are using copy constructors in place
-	 * of the Object.clone() interface as this interface is not
-	 * supported by J2ME.
-	 */
-	protected GeneralDigest(GeneralDigest t)
-	{
-        xBuf = new byte[t.xBuf.length];
-		System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
-
-		xBufOff = t.xBufOff;
-		byteCount = t.byteCount;
-	}
-
-    public void update(
-        byte in)
-    {
-        xBuf[xBufOff++] = in;
-
-        if (xBufOff == xBuf.length)
-        {
-            processWord(xBuf, 0);
-            xBufOff = 0;
-        }
-
-        byteCount++;
-    }
-
-    public void update(
-        byte[]  in,
-        int     inOff,
-        int     len)
-    {
-        //
-        // fill the current word
-        //
-        while ((xBufOff != 0) && (len > 0))
-        {
-            update(in[inOff]);
-
-            inOff++;
-            len--;
-        }
-
-        //
-        // process whole words.
-        //
-        while (len > xBuf.length)
-        {
-            processWord(in, inOff);
-
-            inOff += xBuf.length;
-            len -= xBuf.length;
-            byteCount += xBuf.length;
-        }
-
-        //
-        // load in the remainder.
-        //
-        while (len > 0)
-        {
-            update(in[inOff]);
-
-            inOff++;
-            len--;
-        }
-    }
-
-    public void finish()
-    {
-        long    bitLength = (byteCount << 3);
-
-        //
-        // add the pad bytes.
-        //
-        update((byte)128);
-
-        while (xBufOff != 0)
-        {
-            update((byte)0);
-        }
-
-        processLength(bitLength);
-
-        processBlock();
-    }
-
-    public void reset()
-    {
-        byteCount = 0;
-
-        xBufOff = 0;
-		for ( int i = 0; i < xBuf.length; i++ ) {
-			xBuf[i] = 0;
-		}
-    }
-
-    protected abstract void processWord(byte[] in, int inOff);
-
-    protected abstract void processLength(long bitLength);
-
-    protected abstract void processBlock();
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/LongDigest.java b/azureus2/src/org/bouncycastle/crypto/digests/LongDigest.java
deleted file mode 100644
index f3e0043..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/LongDigest.java
+++ /dev/null
@@ -1,346 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * Base class for SHA-384 and SHA-512.
- */
-public abstract class LongDigest
-    implements Digest
-{
-    private byte[]  xBuf;
-    private int     xBufOff;
-
-    private long    byteCount1;
-    private long    byteCount2;
-
-    protected long    H1, H2, H3, H4, H5, H6, H7, H8;
-
-    private long[]  W = new long[80];
-    private int     wOff;
-
-	/**
-	 * Constructor for variable length word
-	 */
-	protected LongDigest()
-	{
-		xBuf = new byte[8];
-		xBufOff = 0;
-
-        reset();
-	}
-
-	/**
-	 * Copy constructor.  We are using copy constructors in place
-	 * of the Object.clone() interface as this interface is not
-	 * supported by J2ME.
-	 */
-	protected LongDigest(LongDigest t)
-	{
-        xBuf = new byte[t.xBuf.length];
-		System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
-
-		xBufOff = t.xBufOff;
-		byteCount1 = t.byteCount1;
-		byteCount2 = t.byteCount2;
-
-		H1 = t.H1;
-		H2 = t.H2;
-		H3 = t.H3;
-		H4 = t.H4;
-		H5 = t.H5;
-		H6 = t.H6;
-		H7 = t.H7;
-		H8 = t.H8;
-
-		System.arraycopy(t.W, 0, W, 0, t.W.length);
-		wOff = t.wOff;
-	}
-
-    public void update(
-        byte in)
-    {
-        xBuf[xBufOff++] = in;
-
-        if (xBufOff == xBuf.length)
-        {
-            processWord(xBuf, 0);
-            xBufOff = 0;
-        }
-
-        byteCount1++;
-    }
-
-    public void update(
-        byte[]  in,
-        int     inOff,
-        int     len)
-    {
-        //
-        // fill the current word
-        //
-        while ((xBufOff != 0) && (len > 0))
-        {
-            update(in[inOff]);
-
-            inOff++;
-            len--;
-        }
-
-        //
-        // process whole words.
-        //
-        while (len > xBuf.length)
-        {
-            processWord(in, inOff);
-
-            inOff += xBuf.length;
-            len -= xBuf.length;
-            byteCount1 += xBuf.length;
-        }
-
-        //
-        // load in the remainder.
-        //
-        while (len > 0)
-        {
-            update(in[inOff]);
-
-            inOff++;
-            len--;
-        }
-    }
-
-    public void finish()
-    {
-        adjustByteCounts();
-
-        long    lowBitLength = byteCount1 << 3;
-        long    hiBitLength = byteCount2;
-
-        //
-        // add the pad bytes.
-        //
-        update((byte)128);
-
-        while (xBufOff != 0)
-        {
-            update((byte)0);
-        }
-
-        processLength(lowBitLength, hiBitLength);
-
-        processBlock();
-    }
-
-    public void reset()
-    {
-        byteCount1 = 0;
-        byteCount2 = 0;
-
-        xBufOff = 0;
-		for ( int i = 0; i < xBuf.length; i++ ) {
-			xBuf[i] = 0;
-		}
-
-        wOff = 0;
-        for (int i = 0; i != W.length; i++)
-        {
-            W[i] = 0;
-        }
-    }
-
-    protected void processWord(
-        byte[]  in,
-        int     inOff)
-    {
-        W[wOff++] = ((long)(in[inOff] & 0xff) << 56)
-					| ((long)(in[inOff + 1] & 0xff) << 48)
-                    | ((long)(in[inOff + 2] & 0xff) << 40)
-					| ((long)(in[inOff + 3] & 0xff) << 32)
-        			| ((long)(in[inOff + 4] & 0xff) << 24)
-					| ((long)(in[inOff + 5] & 0xff) << 16)
-                    | ((long)(in[inOff + 6] & 0xff) << 8)
-					| ((in[inOff + 7] & 0xff)); 
-
-        if (wOff == 16)
-        {
-            processBlock();
-        }
-    }
-
-    protected void unpackWord(
-        long    word,
-        byte[]  out,
-        int     outOff)
-    {
-        out[outOff]     = (byte)(word >>> 56);
-        out[outOff + 1] = (byte)(word >>> 48);
-        out[outOff + 2] = (byte)(word >>> 40);
-        out[outOff + 3] = (byte)(word >>> 32);
-        out[outOff + 4] = (byte)(word >>> 24);
-        out[outOff + 5] = (byte)(word >>> 16);
-        out[outOff + 6] = (byte)(word >>> 8);
-        out[outOff + 7] = (byte)word;
-    }
-
-    /**
-     * adjust the byte counts so that byteCount2 represents the
-     * upper long (less 3 bits) word of the byte count.
-     */
-    private void adjustByteCounts()
-    {
-        if (byteCount1 > 0x1fffffffffffffffL)
-        {
-            byteCount2 += (byteCount1 >>> 61);
-            byteCount1 &= 0x1fffffffffffffffL;
-        }
-    }
-
-    protected void processLength(
-        long    lowW,
-        long    hiW)
-    {
-        if (wOff > 14)
-        {
-            processBlock();
-        }
-
-        W[14] = hiW;
-        W[15] = lowW;
-    }
-
-    protected void processBlock()
-    {
-        adjustByteCounts();
-
-        //
-        // expand 16 word block into 80 word blocks.
-        //
-        for (int t = 16; t <= 79; t++)
-        {
-            W[t] = Sigma1(W[t - 2]) + W[t - 7] + Sigma0(W[t - 15]) + W[t - 16];
-        }
-
-        //
-        // set up working variables.
-        //
-        long     a = H1;
-        long     b = H2;
-        long     c = H3;
-        long     d = H4;
-        long     e = H5;
-        long     f = H6;
-        long     g = H7;
-        long     h = H8;
-
-		for (int t = 0; t <= 79; t++)
-		{
-			long	T1, T2;
-
-			T1 = h + Sum1(e) + Ch(e, f, g) + K[t] + W[t];
-			T2 = Sum0(a) + Maj(a, b, c);
-			h = g;
-			g = f;
-			f = e;
-			e = d + T1;
-			d = c;
-			c = b;
-			b = a;
-			a = T1 + T2;
-		}
-
-        H1 += a;
-        H2 += b;
-        H3 += c;
-        H4 += d;
-        H5 += e;
-        H6 += f;
-        H7 += g;
-        H8 += h;
-
-        //
-        // reset the offset and clean out the word buffer.
-        //
-        wOff = 0;
-        for (int i = 0; i != W.length; i++)
-        {
-            W[i] = 0;
-        }
-    }
-
-    private long rotateRight(
-        long   x,
-        int    n)
-    {
-        return (x >>> n) | (x << (64 - n));
-    }
-
-	/* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
-    private long Ch(
-        long    x,
-        long    y,
-        long    z)
-    {
-        return ((x & y) ^ ((~x) & z));
-    }
-
-    private long Maj(
-        long    x,
-        long    y,
-        long    z)
-    {
-        return ((x & y) ^ (x & z) ^ (y & z));
-    }
-
-    private long Sum0(
-        long    x)
-    {
-        return rotateRight(x, 28) ^ rotateRight(x, 34) ^ rotateRight(x, 39);
-    }
-
-    private long Sum1(
-        long    x)
-    {
-        return rotateRight(x, 14) ^ rotateRight(x, 18) ^ rotateRight(x, 41);
-    }
-
-    private long Sigma0(
-        long    x)
-    {
-        return rotateRight(x, 1) ^ rotateRight(x, 8) ^ (x >>> 7);
-    }
-
-    private long Sigma1(
-        long    x)
-    {
-        return rotateRight(x, 19) ^ rotateRight(x, 61) ^ (x >>> 6);
-    }
-
-	/* SHA-384 and SHA-512 Constants
-	 * (represent the first 64 bits of the fractional parts of the
-     * cube roots of the first sixty-four prime numbers)
-	 */
-	static final long K[] = {
-0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
-0x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
-0xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
-0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
-0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
-0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
-0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
-0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L,
-0x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
-0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL,
-0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
-0xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
-0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
-0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
-0x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
-0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
-0xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
-0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL,
-0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
-0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L
-	};
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/MD2Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/MD2Digest.java
deleted file mode 100644
index 51e3e3c..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/MD2Digest.java
+++ /dev/null
@@ -1,230 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.Digest;
-/**
- * implementation of MD2
- * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
- */
-public class MD2Digest
-    implements Digest
-{
-    private static final int DIGEST_LENGTH = 16;
-
-    /* X buffer */
-    private byte[]   X = new byte[48];
-    private int     xOff;
-
    /* M buffer */
-
    private byte[]   M = new byte[16];
-    private int     mOff;
-
    /* check sum */
-
    private byte[]   C = new byte[16];
-    private int COff;
-
-    public MD2Digest()
-    {
-        reset();
-    }
-	public MD2Digest(MD2Digest t)
-	{
-		System.arraycopy(t.X, 0, X, 0, t.X.length);
-		xOff = t.xOff;
-		System.arraycopy(t.M, 0, M, 0, t.M.length);
-		mOff = t.mOff;
-		System.arraycopy(t.C, 0, C, 0, t.C.length);
-		COff = t.COff;
-	}
-    /**
-     * return the algorithm name
-     *
-     * @return the algorithm name
-     */
-    public String getAlgorithmName()
-    {
-        return "MD2";
-    }
-    /**
-     * return the size, in bytes, of the digest produced by this message digest.
-     *
-     * @return the size, in bytes, of the digest produced by this message digest.
-     */
-	public int getDigestSize()
-    {
-        return DIGEST_LENGTH;
-    }
-    /**
-     * close the digest, producing the final digest value. The doFinal
-     * call leaves the digest reset.
-     *
-     * @param out the array the digest is to be copied into.
-     * @param outOff the offset into the out array the digest is to start at.
-     */
-	public int doFinal(byte[] out, int outOff)
-    {
-        // add padding
-        byte paddingByte = (byte)(M.length-mOff);
-        for (int i=mOff;i<M.length;i++)
-        {
-            M[i] = paddingByte;
-        }
-        //do final check sum
-        processCheckSum(M);
-        // do final block process
-        processBlock(M);
-
-        processBlock(C);
-
-        System.arraycopy(X,xOff,out,outOff,16);
-
-        reset();
-
-        return DIGEST_LENGTH;
-    }
-    /**
-     * reset the digest back to it's initial state.
-     */
-    public void reset()
-    {
-        xOff = 0;
-        for (int i = 0; i != X.length; i++)
-        {
-            X[i] = 0;
-        }
-        mOff = 0;
-        for (int i = 0; i != M.length; i++)
-        {
-            M[i] = 0;
-        }
-        COff = 0;
-        for (int i = 0; i != C.length; i++)
-        {
-            C[i] = 0;
-        }
-    }
-    /**
-     * update the message digest with a single byte.
-     *
-     * @param in the input byte to be entered.
-     */
-	public void update(byte in)
-    {
-        M[mOff++] = in;
-
-        if (mOff == 16)
-        {
-            processCheckSum(M);
-            processBlock(M);
-            mOff = 0;
-        }
-    }
-
-    /**
-     * update the message digest with a block of bytes.
-     *
-     * @param in the byte array containing the data.
-     * @param inOff the offset into the byte array where the data starts.
-     * @param len the length of the data.
-     */
-	public void update(byte[] in, int inOff, int len)
-    {
-        //
-        // fill the current word
-        //
-        while ((mOff != 0) && (len > 0))
-        {
-            update(in[inOff]);
-            inOff++;
-            len--;
-        }
-
-        //
-        // process whole words.
-        //
-        while (len > 16)
-        {
-            System.arraycopy(in,inOff,M,0,16);
-            processCheckSum(M);
-            processBlock(M);
-            len -= 16;
-            inOff += 16;
-        }
-
-        //
-        // load in the remainder.
-        //
-        while (len > 0)
-        {
-            update(in[inOff]);
-            inOff++;
-            len--;
-        }
-    }
-    protected void processCheckSum(byte[] m)
-    {
-        int L = C[15];
-        for (int i=0;i<16;i++)
-        {
-            C[i] ^= S[(m[i] ^ L) & 0xff];
-            L = C[i];
-        }
-    }
-    protected void processBlock(byte[] m)
-    {
-        for (int i=0;i<16;i++)
-        {
-            X[i+16] = m[i];
-            X[i+32] = (byte)(m[i] ^ X[i]);
-        }
-        // encrypt block
-        int t = 0;
-
-        for (int j=0;j<18;j++)
-        {
-            for (int k=0;k<48;k++)
-            {
-                t = X[k] ^= S[t];
-                t = t & 0xff;
-            }
-            t = (t + j)%256;
-        }
-     }
-     // 256-byte random permutation constructed from the digits of PI
-    private static final byte[] S = {
-      (byte)41,(byte)46,(byte)67,(byte)201,(byte)162,(byte)216,(byte)124,
-      (byte)1,(byte)61,(byte)54,(byte)84,(byte)161,(byte)236,(byte)240,
-      (byte)6,(byte)19,(byte)98,(byte)167,(byte)5,(byte)243,(byte)192,
-      (byte)199,(byte)115,(byte)140,(byte)152,(byte)147,(byte)43,(byte)217,
-      (byte)188,(byte)76,(byte)130,(byte)202,(byte)30,(byte)155,(byte)87,
-      (byte)60,(byte)253,(byte)212,(byte)224,(byte)22,(byte)103,(byte)66,
-      (byte)111,(byte)24,(byte)138,(byte)23,(byte)229,(byte)18,(byte)190,
-      (byte)78,(byte)196,(byte)214,(byte)218,(byte)158,(byte)222,(byte)73,
-      (byte)160,(byte)251,(byte)245,(byte)142,(byte)187,(byte)47,(byte)238,
-      (byte)122,(byte)169,(byte)104,(byte)121,(byte)145,(byte)21,(byte)178,
-      (byte)7,(byte)63,(byte)148,(byte)194,(byte)16,(byte)137,(byte)11,
-      (byte)34,(byte)95,(byte)33,(byte)128,(byte)127,(byte)93,(byte)154,
-      (byte)90,(byte)144,(byte)50,(byte)39,(byte)53,(byte)62,(byte)204,
-      (byte)231,(byte)191,(byte)247,(byte)151,(byte)3,(byte)255,(byte)25,
-      (byte)48,(byte)179,(byte)72,(byte)165,(byte)181,(byte)209,(byte)215,
-      (byte)94,(byte)146,(byte)42,(byte)172,(byte)86,(byte)170,(byte)198,
-      (byte)79,(byte)184,(byte)56,(byte)210,(byte)150,(byte)164,(byte)125,
-      (byte)182,(byte)118,(byte)252,(byte)107,(byte)226,(byte)156,(byte)116,
-      (byte)4,(byte)241,(byte)69,(byte)157,(byte)112,(byte)89,(byte)100,
-      (byte)113,(byte)135,(byte)32,(byte)134,(byte)91,(byte)207,(byte)101,
-      (byte)230,(byte)45,(byte)168,(byte)2,(byte)27,(byte)96,(byte)37,
-      (byte)173,(byte)174,(byte)176,(byte)185,(byte)246,(byte)28,(byte)70,
-      (byte)97,(byte)105,(byte)52,(byte)64,(byte)126,(byte)15,(byte)85,
-      (byte)71,(byte)163,(byte)35,(byte)221,(byte)81,(byte)175,(byte)58,
-      (byte)195,(byte)92,(byte)249,(byte)206,(byte)186,(byte)197,(byte)234,
-      (byte)38,(byte)44,(byte)83,(byte)13,(byte)110,(byte)133,(byte)40,
-      (byte)132, 9,(byte)211,(byte)223,(byte)205,(byte)244,(byte)65,
-      (byte)129,(byte)77,(byte)82,(byte)106,(byte)220,(byte)55,(byte)200,
-      (byte)108,(byte)193,(byte)171,(byte)250,(byte)36,(byte)225,(byte)123,
-      (byte)8,(byte)12,(byte)189,(byte)177,(byte)74,(byte)120,(byte)136,
-      (byte)149,(byte)139,(byte)227,(byte)99,(byte)232,(byte)109,(byte)233,
-      (byte)203,(byte)213,(byte)254,(byte)59,(byte)0,(byte)29,(byte)57,
-      (byte)242,(byte)239,(byte)183,(byte)14,(byte)102,(byte)88,(byte)208,
-      (byte)228,(byte)166,(byte)119,(byte)114,(byte)248,(byte)235,(byte)117,
-      (byte)75,(byte)10,(byte)49,(byte)68,(byte)80,(byte)180,(byte)143,
-      (byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51,
-      (byte)159,(byte)17,(byte)131,(byte)20
-    };
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/MD4Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/MD4Digest.java
deleted file mode 100644
index 4a482e2..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/MD4Digest.java
+++ /dev/null
@@ -1,270 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-/**
- * implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for
- * Computer Science and RSA Data Security, Inc.
- * <p>
- * <b>NOTE</b>: This algorithm is only included for backwards compatability
- * with legacy applications, it's not secure, don't use it for anything new!
- */
-public class MD4Digest
-    extends GeneralDigest
-{
-    private static final int    DIGEST_LENGTH = 16;
-
-    private int     H1, H2, H3, H4;         // IV's
-
-    private int[]   X = new int[16];
-    private int     xOff;
-
-	/**
-	 * Standard constructor
-	 */
-    public MD4Digest()
-    {
-        reset();
-    }
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public MD4Digest(MD4Digest t)
-	{
-		super(t);
-
-		H1 = t.H1;
-		H2 = t.H2;
-		H3 = t.H3;
-		H4 = t.H4;
-
-		System.arraycopy(t.X, 0, X, 0, t.X.length);
-		xOff = t.xOff;
-	}
-
-    public String getAlgorithmName()
-    {
-        return "MD4";
-    }
-
-    public int getDigestSize()
-    {
-        return DIGEST_LENGTH;
-    }
-
-    protected void processWord(
-        byte[]  in,
-        int     inOff)
-    {
-        X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
-            | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 
-
-        if (xOff == 16)
-        {
-            processBlock();
-        }
-    }
-
-    protected void processLength(
-        long    bitLength)
-    {
-        if (xOff > 14)
-        {
-            processBlock();
-        }
-
-        X[14] = (int)(bitLength & 0xffffffff);
-        X[15] = (int)(bitLength >>> 32);
-    }
-
-    private void unpackWord(
-        int     word,
-        byte[]  out,
-        int     outOff)
-    {
-        out[outOff]     = (byte)word;
-        out[outOff + 1] = (byte)(word >>> 8);
-        out[outOff + 2] = (byte)(word >>> 16);
-        out[outOff + 3] = (byte)(word >>> 24);
-    }
-
-    public int doFinal(
-        byte[]  out,
-        int     outOff)
-    {
-        finish();
-
-        unpackWord(H1, out, outOff);
-        unpackWord(H2, out, outOff + 4);
-        unpackWord(H3, out, outOff + 8);
-        unpackWord(H4, out, outOff + 12);
-
-        reset();
-
-        return DIGEST_LENGTH;
-    }
-
-    /**
-     * reset the chaining variables to the IV values.
-     */
-    public void reset()
-    {
-        super.reset();
-
-        H1 = 0x67452301;
-        H2 = 0xefcdab89;
-        H3 = 0x98badcfe;
-        H4 = 0x10325476;
-
-        xOff = 0;
-
-        for (int i = 0; i != X.length; i++)
-        {
-            X[i] = 0;
-        }
-    }
-
-    //
-    // round 1 left rotates
-    //
-    private static final int S11 = 3;
-    private static final int S12 = 7;
-    private static final int S13 = 11;
-    private static final int S14 = 19;
-
-    //
-    // round 2 left rotates
-    //
-    private static final int S21 = 3;
-    private static final int S22 = 5;
-    private static final int S23 = 9;
-    private static final int S24 = 13;
-
-    //
-    // round 3 left rotates
-    //
-    private static final int S31 = 3;
-    private static final int S32 = 9;
-    private static final int S33 = 11;
-    private static final int S34 = 15;
-
-    /*
-     * rotate int x left n bits.
-     */
-    private int rotateLeft(
-        int x,
-        int n)
-    {
-        return (x << n) | (x >>> (32 - n));
-    }
-
-    /*
-     * F, G, H and I are the basic MD4 functions.
-     */
-    private int F(
-        int u,
-        int v,
-        int w)
-    {
-        return (u & v) | (~u & w);
-    }
-
-    private int G(
-        int u,
-        int v,
-        int w)
-    {
-        return (u & v) | (u & w) | (v & w);
-    }
-
-    private int H(
-        int u,
-        int v,
-        int w)
-    {
-        return u ^ v ^ w;
-    }
-
-    protected void processBlock()
-    {
-        int a = H1;
-        int b = H2;
-        int c = H3;
-        int d = H4;
-
-        //
-        // Round 1 - F cycle, 16 times.
-        //
-        a = rotateLeft((a + F(b, c, d) + X[ 0]), S11);
-        d = rotateLeft((d + F(a, b, c) + X[ 1]), S12);
-        c = rotateLeft((c + F(d, a, b) + X[ 2]), S13);
-        b = rotateLeft((b + F(c, d, a) + X[ 3]), S14);
-        a = rotateLeft((a + F(b, c, d) + X[ 4]), S11);
-        d = rotateLeft((d + F(a, b, c) + X[ 5]), S12);
-        c = rotateLeft((c + F(d, a, b) + X[ 6]), S13);
-        b = rotateLeft((b + F(c, d, a) + X[ 7]), S14);
-        a = rotateLeft((a + F(b, c, d) + X[ 8]), S11);
-        d = rotateLeft((d + F(a, b, c) + X[ 9]), S12);
-        c = rotateLeft((c + F(d, a, b) + X[10]), S13);
-        b = rotateLeft((b + F(c, d, a) + X[11]), S14);
-        a = rotateLeft((a + F(b, c, d) + X[12]), S11);
-        d = rotateLeft((d + F(a, b, c) + X[13]), S12);
-        c = rotateLeft((c + F(d, a, b) + X[14]), S13);
-        b = rotateLeft((b + F(c, d, a) + X[15]), S14);
-
-        //
-        // Round 2 - G cycle, 16 times.
-        //
-        a = rotateLeft((a + G(b, c, d) + X[ 0] + 0x5a827999), S21);
-        d = rotateLeft((d + G(a, b, c) + X[ 4] + 0x5a827999), S22);
-        c = rotateLeft((c + G(d, a, b) + X[ 8] + 0x5a827999), S23);
-        b = rotateLeft((b + G(c, d, a) + X[12] + 0x5a827999), S24);
-        a = rotateLeft((a + G(b, c, d) + X[ 1] + 0x5a827999), S21);
-        d = rotateLeft((d + G(a, b, c) + X[ 5] + 0x5a827999), S22);
-        c = rotateLeft((c + G(d, a, b) + X[ 9] + 0x5a827999), S23);
-        b = rotateLeft((b + G(c, d, a) + X[13] + 0x5a827999), S24);
-        a = rotateLeft((a + G(b, c, d) + X[ 2] + 0x5a827999), S21);
-        d = rotateLeft((d + G(a, b, c) + X[ 6] + 0x5a827999), S22);
-        c = rotateLeft((c + G(d, a, b) + X[10] + 0x5a827999), S23);
-        b = rotateLeft((b + G(c, d, a) + X[14] + 0x5a827999), S24);
-        a = rotateLeft((a + G(b, c, d) + X[ 3] + 0x5a827999), S21);
-        d = rotateLeft((d + G(a, b, c) + X[ 7] + 0x5a827999), S22);
-        c = rotateLeft((c + G(d, a, b) + X[11] + 0x5a827999), S23);
-        b = rotateLeft((b + G(c, d, a) + X[15] + 0x5a827999), S24);
-
-        //
-        // Round 3 - H cycle, 16 times.
-        //
-        a = rotateLeft((a + H(b, c, d) + X[ 0] + 0x6ed9eba1), S31);
-        d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x6ed9eba1), S32);
-        c = rotateLeft((c + H(d, a, b) + X[ 4] + 0x6ed9eba1), S33);
-        b = rotateLeft((b + H(c, d, a) + X[12] + 0x6ed9eba1), S34);
-        a = rotateLeft((a + H(b, c, d) + X[ 2] + 0x6ed9eba1), S31);
-        d = rotateLeft((d + H(a, b, c) + X[10] + 0x6ed9eba1), S32);
-        c = rotateLeft((c + H(d, a, b) + X[ 6] + 0x6ed9eba1), S33);
-        b = rotateLeft((b + H(c, d, a) + X[14] + 0x6ed9eba1), S34);
-        a = rotateLeft((a + H(b, c, d) + X[ 1] + 0x6ed9eba1), S31);
-        d = rotateLeft((d + H(a, b, c) + X[ 9] + 0x6ed9eba1), S32);
-        c = rotateLeft((c + H(d, a, b) + X[ 5] + 0x6ed9eba1), S33);
-        b = rotateLeft((b + H(c, d, a) + X[13] + 0x6ed9eba1), S34);
-        a = rotateLeft((a + H(b, c, d) + X[ 3] + 0x6ed9eba1), S31);
-        d = rotateLeft((d + H(a, b, c) + X[11] + 0x6ed9eba1), S32);
-        c = rotateLeft((c + H(d, a, b) + X[ 7] + 0x6ed9eba1), S33);
-        b = rotateLeft((b + H(c, d, a) + X[15] + 0x6ed9eba1), S34);
-
-        H1 += a;
-        H2 += b;
-        H3 += c;
-        H4 += d;
-
-        //
-        // reset the offset and clean out the word buffer.
-        //
-        xOff = 0;
-        for (int i = 0; i != X.length; i++)
-        {
-            X[i] = 0;
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/MD5Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/MD5Digest.java
deleted file mode 100644
index c21461a..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/MD5Digest.java
+++ /dev/null
@@ -1,302 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-/**
- * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
- */
-public class MD5Digest
-    extends GeneralDigest
-{
-    private static final int    DIGEST_LENGTH = 16;
-
-    private int     H1, H2, H3, H4;         // IV's
-
-    private int[]   X = new int[16];
-    private int     xOff;
-
-	/**
-	 * Standard constructor
-	 */
-    public MD5Digest()
-    {
-        reset();
-    }
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public MD5Digest(MD5Digest t)
-	{
-		super(t);
-
-		H1 = t.H1;
-		H2 = t.H2;
-		H3 = t.H3;
-		H4 = t.H4;
-
-		System.arraycopy(t.X, 0, X, 0, t.X.length);
-		xOff = t.xOff;
-	}
-
-    public String getAlgorithmName()
-    {
-        return "MD5";
-    }
-
-    public int getDigestSize()
-    {
-        return DIGEST_LENGTH;
-    }
-
-    protected void processWord(
-        byte[]  in,
-        int     inOff)
-    {
-        X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
-            | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 
-
-        if (xOff == 16)
-        {
-            processBlock();
-        }
-    }
-
-    protected void processLength(
-        long    bitLength)
-    {
-        if (xOff > 14)
-        {
-            processBlock();
-        }
-
-        X[14] = (int)(bitLength & 0xffffffff);
-        X[15] = (int)(bitLength >>> 32);
-    }
-
-    private void unpackWord(
-        int     word,
-        byte[]  out,
-        int     outOff)
-    {
-        out[outOff]     = (byte)word;
-        out[outOff + 1] = (byte)(word >>> 8);
-        out[outOff + 2] = (byte)(word >>> 16);
-        out[outOff + 3] = (byte)(word >>> 24);
-    }
-
-    public int doFinal(
-        byte[]  out,
-        int     outOff)
-    {
-        finish();
-
-        unpackWord(H1, out, outOff);
-        unpackWord(H2, out, outOff + 4);
-        unpackWord(H3, out, outOff + 8);
-        unpackWord(H4, out, outOff + 12);
-
-        reset();
-
-        return DIGEST_LENGTH;
-    }
-
-    /**
-     * reset the chaining variables to the IV values.
-     */
-    public void reset()
-    {
-        super.reset();
-
-        H1 = 0x67452301;
-        H2 = 0xefcdab89;
-        H3 = 0x98badcfe;
-        H4 = 0x10325476;
-
-        xOff = 0;
-
-        for (int i = 0; i != X.length; i++)
-        {
-            X[i] = 0;
-        }
-    }
-
-    //
-    // round 1 left rotates
-    //
-    private static final int S11 = 7;
-    private static final int S12 = 12;
-    private static final int S13 = 17;
-    private static final int S14 = 22;
-
-    //
-    // round 2 left rotates
-    //
-    private static final int S21 = 5;
-    private static final int S22 = 9;
-    private static final int S23 = 14;
-    private static final int S24 = 20;
-
-    //
-    // round 3 left rotates
-    //
-    private static final int S31 = 4;
-    private static final int S32 = 11;
-    private static final int S33 = 16;
-    private static final int S34 = 23;
-
-    //
-    // round 4 left rotates
-    //
-    private static final int S41 = 6;
-    private static final int S42 = 10;
-    private static final int S43 = 15;
-    private static final int S44 = 21;
-
-    /*
-     * rotate int x left n bits.
-     */
-    private int rotateLeft(
-        int x,
-        int n)
-    {
-        return (x << n) | (x >>> (32 - n));
-    }
-
-    /*
-     * F, G, H and I are the basic MD5 functions.
-     */
-    private int F(
-        int u,
-        int v,
-        int w)
-    {
-        return (u & v) | (~u & w);
-    }
-
-    private int G(
-        int u,
-        int v,
-        int w)
-    {
-        return (u & w) | (v & ~w);
-    }
-
-    private int H(
-        int u,
-        int v,
-        int w)
-    {
-        return u ^ v ^ w;
-    }
-
-    private int K(
-        int u,
-        int v,
-        int w)
-    {
-        return v ^ (u | ~w);
-    }
-
-    protected void processBlock()
-    {
-        int a = H1;
-        int b = H2;
-        int c = H3;
-        int d = H4;
-
-        //
-        // Round 1 - F cycle, 16 times.
-        //
-        a = rotateLeft((a + F(b, c, d) + X[ 0] + 0xd76aa478), S11) + b;
-        d = rotateLeft((d + F(a, b, c) + X[ 1] + 0xe8c7b756), S12) + a;
-        c = rotateLeft((c + F(d, a, b) + X[ 2] + 0x242070db), S13) + d;
-        b = rotateLeft((b + F(c, d, a) + X[ 3] + 0xc1bdceee), S14) + c;
-        a = rotateLeft((a + F(b, c, d) + X[ 4] + 0xf57c0faf), S11) + b;
-        d = rotateLeft((d + F(a, b, c) + X[ 5] + 0x4787c62a), S12) + a;
-        c = rotateLeft((c + F(d, a, b) + X[ 6] + 0xa8304613), S13) + d;
-        b = rotateLeft((b + F(c, d, a) + X[ 7] + 0xfd469501), S14) + c;
-        a = rotateLeft((a + F(b, c, d) + X[ 8] + 0x698098d8), S11) + b;
-        d = rotateLeft((d + F(a, b, c) + X[ 9] + 0x8b44f7af), S12) + a;
-        c = rotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), S13) + d;
-        b = rotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), S14) + c;
-        a = rotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), S11) + b;
-        d = rotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), S12) + a;
-        c = rotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), S13) + d;
-        b = rotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), S14) + c;
-
-        //
-        // Round 2 - G cycle, 16 times.
-        //
-        a = rotateLeft((a + G(b, c, d) + X[ 1] + 0xf61e2562), S21) + b;
-        d = rotateLeft((d + G(a, b, c) + X[ 6] + 0xc040b340), S22) + a;
-        c = rotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), S23) + d;
-        b = rotateLeft((b + G(c, d, a) + X[ 0] + 0xe9b6c7aa), S24) + c;
-        a = rotateLeft((a + G(b, c, d) + X[ 5] + 0xd62f105d), S21) + b;
-        d = rotateLeft((d + G(a, b, c) + X[10] + 0x02441453), S22) + a;
-        c = rotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), S23) + d;
-        b = rotateLeft((b + G(c, d, a) + X[ 4] + 0xe7d3fbc8), S24) + c;
-        a = rotateLeft((a + G(b, c, d) + X[ 9] + 0x21e1cde6), S21) + b;
-        d = rotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), S22) + a;
-        c = rotateLeft((c + G(d, a, b) + X[ 3] + 0xf4d50d87), S23) + d;
-        b = rotateLeft((b + G(c, d, a) + X[ 8] + 0x455a14ed), S24) + c;
-        a = rotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), S21) + b;
-        d = rotateLeft((d + G(a, b, c) + X[ 2] + 0xfcefa3f8), S22) + a;
-        c = rotateLeft((c + G(d, a, b) + X[ 7] + 0x676f02d9), S23) + d;
-        b = rotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), S24) + c;
-
-        //
-        // Round 3 - H cycle, 16 times.
-        //
-        a = rotateLeft((a + H(b, c, d) + X[ 5] + 0xfffa3942), S31) + b;
-        d = rotateLeft((d + H(a, b, c) + X[ 8] + 0x8771f681), S32) + a;
-        c = rotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), S33) + d;
-        b = rotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), S34) + c;
-        a = rotateLeft((a + H(b, c, d) + X[ 1] + 0xa4beea44), S31) + b;
-        d = rotateLeft((d + H(a, b, c) + X[ 4] + 0x4bdecfa9), S32) + a;
-        c = rotateLeft((c + H(d, a, b) + X[ 7] + 0xf6bb4b60), S33) + d;
-        b = rotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), S34) + c;
-        a = rotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), S31) + b;
-        d = rotateLeft((d + H(a, b, c) + X[ 0] + 0xeaa127fa), S32) + a;
-        c = rotateLeft((c + H(d, a, b) + X[ 3] + 0xd4ef3085), S33) + d;
-        b = rotateLeft((b + H(c, d, a) + X[ 6] + 0x04881d05), S34) + c;
-        a = rotateLeft((a + H(b, c, d) + X[ 9] + 0xd9d4d039), S31) + b;
-        d = rotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), S32) + a;
-        c = rotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), S33) + d;
-        b = rotateLeft((b + H(c, d, a) + X[ 2] + 0xc4ac5665), S34) + c;
-
-        //
-        // Round 4 - K cycle, 16 times.
-        //
-        a = rotateLeft((a + K(b, c, d) + X[ 0] + 0xf4292244), S41) + b;
-        d = rotateLeft((d + K(a, b, c) + X[ 7] + 0x432aff97), S42) + a;
-        c = rotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), S43) + d;
-        b = rotateLeft((b + K(c, d, a) + X[ 5] + 0xfc93a039), S44) + c;
-        a = rotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), S41) + b;
-        d = rotateLeft((d + K(a, b, c) + X[ 3] + 0x8f0ccc92), S42) + a;
-        c = rotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), S43) + d;
-        b = rotateLeft((b + K(c, d, a) + X[ 1] + 0x85845dd1), S44) + c;
-        a = rotateLeft((a + K(b, c, d) + X[ 8] + 0x6fa87e4f), S41) + b;
-        d = rotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), S42) + a;
-        c = rotateLeft((c + K(d, a, b) + X[ 6] + 0xa3014314), S43) + d;
-        b = rotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), S44) + c;
-        a = rotateLeft((a + K(b, c, d) + X[ 4] + 0xf7537e82), S41) + b;
-        d = rotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), S42) + a;
-        c = rotateLeft((c + K(d, a, b) + X[ 2] + 0x2ad7d2bb), S43) + d;
-        b = rotateLeft((b + K(c, d, a) + X[ 9] + 0xeb86d391), S44) + c;
-
-        H1 += a;
-        H2 += b;
-        H3 += c;
-        H4 += d;
-
-        //
-        // reset the offset and clean out the word buffer.
-        //
-        xOff = 0;
-        for (int i = 0; i != X.length; i++)
-        {
-            X[i] = 0;
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD128Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD128Digest.java
deleted file mode 100644
index 00195a4..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD128Digest.java
+++ /dev/null
@@ -1,461 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-/**
- * implementation of RIPEMD128
- */
-public class RIPEMD128Digest
-    extends GeneralDigest
-{
-	private static final int DIGEST_LENGTH = 16;
-
-	private int H0, H1, H2, H3; // IV's
-
-	private int[] X = new int[16];
-	private int xOff;
-
-	/**
-	 * Standard constructor
-	 */
-	public RIPEMD128Digest()
-	{
-		reset();
-	}
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public RIPEMD128Digest(RIPEMD128Digest t)
-	{
-		super(t);
-
-		H0 = t.H0;
-		H1 = t.H1;
-		H2 = t.H2;
-		H3 = t.H3;
-
-		System.arraycopy(t.X, 0, X, 0, t.X.length);
-		xOff = t.xOff;
-	}
-
-	public String getAlgorithmName()
-	{
-		return "RIPEMD128";
-	}
-
-	public int getDigestSize()
-	{
-		return DIGEST_LENGTH;
-	}
-
-	protected void processWord(
-		byte[] in,
-		int inOff)
-	{
-		X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
-			| ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 
-
-		if (xOff == 16)
-		{
-			processBlock();
-		}
-	}
-
-	protected void processLength(
-		long bitLength)
-	{
-		if (xOff > 14)
-		{
-		processBlock();
-		}
-
-		X[14] = (int)(bitLength & 0xffffffff);
-		X[15] = (int)(bitLength >>> 32);
-	}
-
-	private void unpackWord(
-		int word,
-		byte[] out,
-		int outOff)
-	{
-		out[outOff]     = (byte)word;
-		out[outOff + 1] = (byte)(word >>> 8);
-		out[outOff + 2] = (byte)(word >>> 16);
-		out[outOff + 3] = (byte)(word >>> 24);
-	}
-
-	public int doFinal(
-		byte[] out,
-		int outOff)
-	{
-		finish();
-
-		unpackWord(H0, out, outOff);
-		unpackWord(H1, out, outOff + 4);
-		unpackWord(H2, out, outOff + 8);
-		unpackWord(H3, out, outOff + 12);
-
-		reset();
-
-		return DIGEST_LENGTH;
-	}
-
-	/**
-	* reset the chaining variables to the IV values.
-	*/
-	public void reset()
-	{
-		super.reset();
-
-		H0 = 0x67452301;
-		H1 = 0xefcdab89;
-		H2 = 0x98badcfe;
-		H3 = 0x10325476;
-
-		xOff = 0;
-
-		for (int i = 0; i != X.length; i++)
-		{
-			X[i] = 0;
-		}
-	}
-
-	/*
-	 * rotate int x left n bits.
-	 */
-	private final int RL(
-		int x,
-		int n)
-	{
-		return (x << n) | (x >>> (32 - n));
-	}
-
-	/*
-	 * f1,f2,f3,f4 are the basic RIPEMD128 functions.
-	 */
-
-	/*
-	 * F
-	 */
-	private final int f1(
-		int x,
-		int y,
-		int z)
-	{
-		return x ^ y ^ z;
-	}
-
-	/*
-	 * G
-	 */
-	private final int f2(
-		int x,
-		int y,
-		int z)
-	{
-		return (x & y) | (~x & z);
-	}
-
-	/*
-	 * H
-	 */
-	private final int f3(
-		int x,
-		int y,
-		int z)
-	{
-		return (x | ~y) ^ z;
-	}
-
-	/*
-	 * I
-	 */
-	private final int f4(
-		int x,
-		int y,
-		int z)
-	{
-		return (x & z) | (y & ~z);
-	}
-
-    private final int F1(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-        return RL(a + f1(b, c, d) + x, s);
-    }
-
-    private final int F2(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-        return RL(a + f2(b, c, d) + x + 0x5a827999, s);
-    }
-
-    private final int F3(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-        return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s);
-    }
-
-    private final int F4(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-        return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s);
-    }
-
-    private final int FF1(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-        return RL(a + f1(b, c, d) + x, s);
-    }
-
-    private final int FF2(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-      return RL(a + f2(b, c, d) + x + 0x6d703ef3, s);
-    }
-
-    private final int FF3(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-      return RL(a + f3(b, c, d) + x + 0x5c4dd124, s);
-    }
-
-    private final int FF4(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-      return RL(a + f4(b, c, d) + x + 0x50a28be6, s);
-    }
-
-	protected void processBlock()
-	{
-		int a, aa;
-		int b, bb;
-		int c, cc;
-		int d, dd;
-
-		a = aa = H0;
-		b = bb = H1;
-		c = cc = H2;
-		d = dd = H3;
-
-		//
-		// Round 1
-		//
-        a = F1(a, b, c, d, X[ 0], 11);
-        d = F1(d, a, b, c, X[ 1], 14);
-        c = F1(c, d, a, b, X[ 2], 15);
-        b = F1(b, c, d, a, X[ 3], 12);
-        a = F1(a, b, c, d, X[ 4],  5);
-        d = F1(d, a, b, c, X[ 5],  8);
-        c = F1(c, d, a, b, X[ 6],  7);
-        b = F1(b, c, d, a, X[ 7],  9);
-        a = F1(a, b, c, d, X[ 8], 11);
-        d = F1(d, a, b, c, X[ 9], 13);
-        c = F1(c, d, a, b, X[10], 14);
-        b = F1(b, c, d, a, X[11], 15);
-        a = F1(a, b, c, d, X[12],  6);
-        d = F1(d, a, b, c, X[13],  7);
-        c = F1(c, d, a, b, X[14],  9);
-        b = F1(b, c, d, a, X[15],  8);
-
-		//
-		// Round 2
-		//
-        a = F2(a, b, c, d, X[ 7],  7);
-        d = F2(d, a, b, c, X[ 4],  6);
-        c = F2(c, d, a, b, X[13],  8);
-        b = F2(b, c, d, a, X[ 1], 13);
-        a = F2(a, b, c, d, X[10], 11);
-        d = F2(d, a, b, c, X[ 6],  9);
-        c = F2(c, d, a, b, X[15],  7);
-        b = F2(b, c, d, a, X[ 3], 15);
-        a = F2(a, b, c, d, X[12],  7);
-        d = F2(d, a, b, c, X[ 0], 12);
-        c = F2(c, d, a, b, X[ 9], 15);
-        b = F2(b, c, d, a, X[ 5],  9);
-        a = F2(a, b, c, d, X[ 2], 11);
-        d = F2(d, a, b, c, X[14],  7);
-        c = F2(c, d, a, b, X[11], 13);
-        b = F2(b, c, d, a, X[ 8], 12);
-
-        //
-        // Round 3
-        //
-        a = F3(a, b, c, d, X[ 3], 11);
-        d = F3(d, a, b, c, X[10], 13);
-        c = F3(c, d, a, b, X[14],  6);
-        b = F3(b, c, d, a, X[ 4],  7);
-        a = F3(a, b, c, d, X[ 9], 14);
-        d = F3(d, a, b, c, X[15],  9);
-        c = F3(c, d, a, b, X[ 8], 13);
-        b = F3(b, c, d, a, X[ 1], 15);
-        a = F3(a, b, c, d, X[ 2], 14);
-        d = F3(d, a, b, c, X[ 7],  8);
-        c = F3(c, d, a, b, X[ 0], 13);
-        b = F3(b, c, d, a, X[ 6],  6);
-        a = F3(a, b, c, d, X[13],  5);
-        d = F3(d, a, b, c, X[11], 12);
-        c = F3(c, d, a, b, X[ 5],  7);
-        b = F3(b, c, d, a, X[12],  5);
-
-        //
-        // Round 4
-        //
-        a = F4(a, b, c, d, X[ 1], 11);
-        d = F4(d, a, b, c, X[ 9], 12);
-        c = F4(c, d, a, b, X[11], 14);
-        b = F4(b, c, d, a, X[10], 15);
-        a = F4(a, b, c, d, X[ 0], 14);
-        d = F4(d, a, b, c, X[ 8], 15);
-        c = F4(c, d, a, b, X[12],  9);
-        b = F4(b, c, d, a, X[ 4],  8);
-        a = F4(a, b, c, d, X[13],  9);
-        d = F4(d, a, b, c, X[ 3], 14);
-        c = F4(c, d, a, b, X[ 7],  5);
-        b = F4(b, c, d, a, X[15],  6);
-        a = F4(a, b, c, d, X[14],  8);
-        d = F4(d, a, b, c, X[ 5],  6);
-        c = F4(c, d, a, b, X[ 6],  5);
-        b = F4(b, c, d, a, X[ 2], 12);
-
-        //
-        // Parallel round 1
-        //
-        aa = FF4(aa, bb, cc, dd, X[ 5],  8);
-        dd = FF4(dd, aa, bb, cc, X[14],  9);
-        cc = FF4(cc, dd, aa, bb, X[ 7],  9);
-        bb = FF4(bb, cc, dd, aa, X[ 0], 11);
-        aa = FF4(aa, bb, cc, dd, X[ 9], 13);
-        dd = FF4(dd, aa, bb, cc, X[ 2], 15);
-        cc = FF4(cc, dd, aa, bb, X[11], 15);
-        bb = FF4(bb, cc, dd, aa, X[ 4],  5);
-        aa = FF4(aa, bb, cc, dd, X[13],  7);
-        dd = FF4(dd, aa, bb, cc, X[ 6],  7);
-        cc = FF4(cc, dd, aa, bb, X[15],  8);
-        bb = FF4(bb, cc, dd, aa, X[ 8], 11);
-        aa = FF4(aa, bb, cc, dd, X[ 1], 14);
-        dd = FF4(dd, aa, bb, cc, X[10], 14);
-        cc = FF4(cc, dd, aa, bb, X[ 3], 12);
-        bb = FF4(bb, cc, dd, aa, X[12],  6);
-
-        //
-        // Parallel round 2
-        //
-        aa = FF3(aa, bb, cc, dd, X[ 6],  9);
-        dd = FF3(dd, aa, bb, cc, X[11], 13);
-        cc = FF3(cc, dd, aa, bb, X[ 3], 15);
-        bb = FF3(bb, cc, dd, aa, X[ 7],  7);
-        aa = FF3(aa, bb, cc, dd, X[ 0], 12);
-        dd = FF3(dd, aa, bb, cc, X[13],  8);
-        cc = FF3(cc, dd, aa, bb, X[ 5],  9);
-        bb = FF3(bb, cc, dd, aa, X[10], 11);
-        aa = FF3(aa, bb, cc, dd, X[14],  7);
-        dd = FF3(dd, aa, bb, cc, X[15],  7);
-        cc = FF3(cc, dd, aa, bb, X[ 8], 12);
-        bb = FF3(bb, cc, dd, aa, X[12],  7);
-        aa = FF3(aa, bb, cc, dd, X[ 4],  6);
-        dd = FF3(dd, aa, bb, cc, X[ 9], 15);
-        cc = FF3(cc, dd, aa, bb, X[ 1], 13);
-        bb = FF3(bb, cc, dd, aa, X[ 2], 11);
-
-        //
-        // Parallel round 3
-        //
-        aa = FF2(aa, bb, cc, dd, X[15],  9);
-        dd = FF2(dd, aa, bb, cc, X[ 5],  7);
-        cc = FF2(cc, dd, aa, bb, X[ 1], 15);
-        bb = FF2(bb, cc, dd, aa, X[ 3], 11);
-        aa = FF2(aa, bb, cc, dd, X[ 7],  8);
-        dd = FF2(dd, aa, bb, cc, X[14],  6);
-        cc = FF2(cc, dd, aa, bb, X[ 6],  6);
-        bb = FF2(bb, cc, dd, aa, X[ 9], 14);
-        aa = FF2(aa, bb, cc, dd, X[11], 12);
-        dd = FF2(dd, aa, bb, cc, X[ 8], 13);
-        cc = FF2(cc, dd, aa, bb, X[12],  5);
-        bb = FF2(bb, cc, dd, aa, X[ 2], 14);
-        aa = FF2(aa, bb, cc, dd, X[10], 13);
-        dd = FF2(dd, aa, bb, cc, X[ 0], 13);
-        cc = FF2(cc, dd, aa, bb, X[ 4],  7);
-        bb = FF2(bb, cc, dd, aa, X[13],  5);
-
-        //
-        // Parallel round 4
-        //
-        aa = FF1(aa, bb, cc, dd, X[ 8], 15);
-        dd = FF1(dd, aa, bb, cc, X[ 6],  5);
-        cc = FF1(cc, dd, aa, bb, X[ 4],  8);
-        bb = FF1(bb, cc, dd, aa, X[ 1], 11);
-        aa = FF1(aa, bb, cc, dd, X[ 3], 14);
-        dd = FF1(dd, aa, bb, cc, X[11], 14);
-        cc = FF1(cc, dd, aa, bb, X[15],  6);
-        bb = FF1(bb, cc, dd, aa, X[ 0], 14);
-        aa = FF1(aa, bb, cc, dd, X[ 5],  6);
-        dd = FF1(dd, aa, bb, cc, X[12],  9);
-        cc = FF1(cc, dd, aa, bb, X[ 2], 12);
-        bb = FF1(bb, cc, dd, aa, X[13],  9);
-        aa = FF1(aa, bb, cc, dd, X[ 9], 12);
-        dd = FF1(dd, aa, bb, cc, X[ 7],  5);
-        cc = FF1(cc, dd, aa, bb, X[10], 15);
-        bb = FF1(bb, cc, dd, aa, X[14],  8);
-
-        dd += c + H1;               // final result for H0
-
-        //
-        // combine the results
-        //
-        H1 = H2 + d + aa;
-        H2 = H3 + a + bb;
-        H3 = H0 + b + cc;
-        H0 = dd;
-
-		//
-		// reset the offset and clean out the word buffer.
-		//
-		xOff = 0;
-		for (int i = 0; i != X.length; i++)
-		{
-			X[i] = 0;
-		}
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD160Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD160Digest.java
deleted file mode 100644
index 377b7b7..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD160Digest.java
+++ /dev/null
@@ -1,422 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-/**
- * implementation of RIPEMD see,
- * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
- */
-public class RIPEMD160Digest
-    extends GeneralDigest
-{
-	private static final int DIGEST_LENGTH = 20;
-
-	private int H0, H1, H2, H3, H4; // IV's
-
-	private int[] X = new int[16];
-	private int xOff;
-
-	/**
-	 * Standard constructor
-	 */
-	public RIPEMD160Digest()
-	{
-		reset();
-	}
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public RIPEMD160Digest(RIPEMD160Digest t)
-	{
-		super(t);
-
-		H0 = t.H0;
-		H1 = t.H1;
-		H2 = t.H2;
-		H3 = t.H3;
-		H4 = t.H4;
-
-		System.arraycopy(t.X, 0, X, 0, t.X.length);
-		xOff = t.xOff;
-	}
-
-	public String getAlgorithmName()
-	{
-		return "RIPEMD160";
-	}
-
-	public int getDigestSize()
-	{
-		return DIGEST_LENGTH;
-	}
-
-	protected void processWord(
-		byte[] in,
-		int inOff)
-	{
-		X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
-			| ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 
-
-		if (xOff == 16)
-		{
-			processBlock();
-		}
-	}
-
-	protected void processLength(
-		long bitLength)
-	{
-		if (xOff > 14)
-		{
-		processBlock();
-		}
-
-		X[14] = (int)(bitLength & 0xffffffff);
-		X[15] = (int)(bitLength >>> 32);
-	}
-
-	private void unpackWord(
-		int word,
-		byte[] out,
-		int outOff)
-	{
-		out[outOff]     = (byte)word;
-		out[outOff + 1] = (byte)(word >>> 8);
-		out[outOff + 2] = (byte)(word >>> 16);
-		out[outOff + 3] = (byte)(word >>> 24);
-	}
-
-	public int doFinal(
-		byte[] out,
-		int outOff)
-	{
-		finish();
-
-		unpackWord(H0, out, outOff);
-		unpackWord(H1, out, outOff + 4);
-		unpackWord(H2, out, outOff + 8);
-		unpackWord(H3, out, outOff + 12);
-		unpackWord(H4, out, outOff + 16);
-
-		reset();
-
-		return DIGEST_LENGTH;
-	}
-
-	/**
-	* reset the chaining variables to the IV values.
-	*/
-	public void reset()
-	{
-		super.reset();
-
-		H0 = 0x67452301;
-		H1 = 0xefcdab89;
-		H2 = 0x98badcfe;
-		H3 = 0x10325476;
-		H4 = 0xc3d2e1f0;
-
-		xOff = 0;
-
-		for (int i = 0; i != X.length; i++)
-		{
-			X[i] = 0;
-		}
-	}
-
-	/*
-	 * rotate int x left n bits.
-	 */
-	private final int RL(
-		int x,
-		int n)
-	{
-		return (x << n) | (x >>> (32 - n));
-	}
-
-	/*
-	 * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions.
-	 */
-
-	/*
-	 * rounds 0-15
-	 */
-	private final int f1(
-		int x,
-		int y,
-		int z)
-	{
-		return x ^ y ^ z;
-	}
-
-	/*
-	 * rounds 16-31
-	 */
-	private final int f2(
-		int x,
-		int y,
-		int z)
-	{
-		return (x & y) | (~x & z);
-	}
-
-	/*
-	 * rounds 32-47
-	 */
-	private final int f3(
-		int x,
-		int y,
-		int z)
-	{
-		return (x | ~y) ^ z;
-	}
-
-	/*
-	 * rounds 48-63
-	 */
-	private final int f4(
-		int x,
-		int y,
-		int z)
-	{
-		return (x & z) | (y & ~z);
-	}
-
-	/*
-	 * rounds 64-79
-	 */
-	private final int f5(
-		int x,
-		int y,
-		int z)
-	{
-		return x ^ (y | ~z);
-	}
-
-	protected void processBlock()
-	{
-		int a, aa;
-		int b, bb;
-		int c, cc;
-		int d, dd;
-		int e, ee;
-
-		a = aa = H0;
-		b = bb = H1;
-		c = cc = H2;
-		d = dd = H3;
-		e = ee = H4;
-
-		//
-		// Rounds 1 - 16
-		//
-		// left
-		a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10);
-		e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10);
-		d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10);
-		c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10);
-		b = RL(b + f1(c,d,e) + X[ 4],  5) + a; d = RL(d, 10);
-		a = RL(a + f1(b,c,d) + X[ 5],  8) + e; c = RL(c, 10);
-		e = RL(e + f1(a,b,c) + X[ 6],  7) + d; b = RL(b, 10);
-		d = RL(d + f1(e,a,b) + X[ 7],  9) + c; a = RL(a, 10);
-		c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10);
-		b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10);
-		a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10);
-		e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10);
-		d = RL(d + f1(e,a,b) + X[12],  6) + c; a = RL(a, 10);
-		c = RL(c + f1(d,e,a) + X[13],  7) + b; e = RL(e, 10);
-		b = RL(b + f1(c,d,e) + X[14],  9) + a; d = RL(d, 10);
-		a = RL(a + f1(b,c,d) + X[15],  8) + e; c = RL(c, 10);
-
-		// right
-		aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6,  8) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6,  9) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6,  9) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6,  5) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6,  7) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6,  7) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6,  8) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6,  6) + ee; cc = RL(cc, 10);
-
-		//
-		// Rounds 16-31
-		//
-		// left
-		e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999,  7) + d; b = RL(b, 10);
-		d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999,  6) + c; a = RL(a, 10);
-		c = RL(c + f2(d,e,a) + X[13] + 0x5a827999,  8) + b; e = RL(e, 10);
-		b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10);
-		a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10);
-		e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999,  9) + d; b = RL(b, 10);
-		d = RL(d + f2(e,a,b) + X[15] + 0x5a827999,  7) + c; a = RL(a, 10);
-		c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10);
-		b = RL(b + f2(c,d,e) + X[12] + 0x5a827999,  7) + a; d = RL(d, 10);
-		a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10);
-		e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10);
-		d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999,  9) + c; a = RL(a, 10);
-		c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10);
-		b = RL(b + f2(c,d,e) + X[14] + 0x5a827999,  7) + a; d = RL(d, 10);
-		a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10);
-		e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10);
-
-		// right
-		ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124,  9) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124,  7) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124,  8) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124,  9) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124,  7) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124,  7) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124,  7) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124,  6) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10);
-
-		//
-		// Rounds 32-47
-		//
-		// left
-		d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10);
-		c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
-		b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1,  6) + a; d = RL(d, 10);
-		a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1,  7) + e; c = RL(c, 10);
-		e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10);
-		d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1,  9) + c; a = RL(a, 10);
-		c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
-		b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10);
-		a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10);
-		e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1,  8) + d; b = RL(b, 10);
-		d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10);
-		c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1,  6) + b; e = RL(e, 10);
-		b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1,  5) + a; d = RL(d, 10);
-		a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10);
-		e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1,  7) + d; b = RL(b, 10);
-		d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1,  5) + c; a = RL(a, 10);
-
-		// right
-		dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3,  9) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3,  7) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3,  8) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3,  6) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3,  6) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3,  5) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3,  7) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3,  5) + cc; aa = RL(aa, 10);
-
-		//
-		// Rounds 48-63
-		//
-		// left
-		c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10);
-		b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10);
-		a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10);
-		e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10);
-		d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
-		c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10);
-		b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc,  9) + a; d = RL(d, 10);
-		a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc,  8) + e; c = RL(c, 10);
-		e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc,  9) + d; b = RL(b, 10);
-		d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
-		c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc,  5) + b; e = RL(e, 10);
-		b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc,  6) + a; d = RL(d, 10);
-		a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc,  8) + e; c = RL(c, 10);
-		e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc,  6) + d; b = RL(b, 10);
-		d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc,  5) + c; a = RL(a, 10);
-		c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10);
-
-		// right
-		cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9,  5) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9,  8) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9,  6) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9,  6) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9,  9) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9,  9) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9,  5) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9,  8) + bb; ee = RL(ee, 10);
-
-		//
-		// Rounds 64-79
-		//
-		// left
-		b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e,  9) + a; d = RL(d, 10);
-		a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10);
-		e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e,  5) + d; b = RL(b, 10);
-		d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10);
-		c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e,  6) + b; e = RL(e, 10);
-		b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e,  8) + a; d = RL(d, 10);
-		a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10);
-		e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10);
-		d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e,  5) + c; a = RL(a, 10);
-		c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10);
-		b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10);
-		a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10);
-		e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10);
-		d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e,  8) + c; a = RL(a, 10);
-		c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e,  5) + b; e = RL(e, 10);
-		b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e,  6) + a; d = RL(d, 10);
-
-		// right
-		bb = RL(bb + f1(cc,dd,ee) + X[12],  8) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f1(bb,cc,dd) + X[15],  5) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f1(ee,aa,bb) + X[ 4],  9) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f1(cc,dd,ee) + X[ 5],  5) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f1(aa,bb,cc) + X[ 7],  6) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f1(ee,aa,bb) + X[ 6],  8) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f1(cc,dd,ee) + X[13],  6) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f1(bb,cc,dd) + X[14],  5) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10);
-
-		dd += c + H1;
-		H1 = H2 + d + ee;
-		H2 = H3 + e + aa;
-		H3 = H4 + a + bb;
-		H4 = H0 + b + cc;
-		H0 = dd;
-
-		//
-		// reset the offset and clean out the word buffer.
-		//
-		xOff = 0;
-		for (int i = 0; i != X.length; i++)
-		{
-			X[i] = 0;
-		}
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD256Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD256Digest.java
deleted file mode 100644
index 7030e4a..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD256Digest.java
+++ /dev/null
@@ -1,476 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-/**
- * implementation of RIPEMD256.
- * <p>
- * <b>note:</b> this algorithm offers the same level of security as RIPEMD128.
- */
-public class RIPEMD256Digest
-    extends GeneralDigest
-{
-	private static final int DIGEST_LENGTH = 32;
-
-	private int H0, H1, H2, H3, H4, H5, H6, H7; // IV's
-
-	private int[] X = new int[16];
-	private int xOff;
-
-	/**
-	 * Standard constructor
-	 */
-	public RIPEMD256Digest()
-	{
-		reset();
-	}
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public RIPEMD256Digest(RIPEMD256Digest t)
-	{
-		super(t);
-
-		H0 = t.H0;
-		H1 = t.H1;
-		H2 = t.H2;
-		H3 = t.H3;
-		H4 = t.H4;
-		H5 = t.H5;
-		H6 = t.H6;
-		H7 = t.H7;
-
-		System.arraycopy(t.X, 0, X, 0, t.X.length);
-		xOff = t.xOff;
-	}
-
-	public String getAlgorithmName()
-	{
-		return "RIPEMD256";
-	}
-
-	public int getDigestSize()
-	{
-		return DIGEST_LENGTH;
-	}
-
-	protected void processWord(
-		byte[] in,
-		int inOff)
-	{
-		X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
-			| ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 
-
-		if (xOff == 16)
-		{
-			processBlock();
-		}
-	}
-
-	protected void processLength(
-		long bitLength)
-	{
-		if (xOff > 14)
-		{
-			processBlock();
-		}
-
-		X[14] = (int)(bitLength & 0xffffffff);
-		X[15] = (int)(bitLength >>> 32);
-	}
-
-	private void unpackWord(
-		int word,
-		byte[] out,
-		int outOff)
-	{
-		out[outOff]     = (byte)word;
-		out[outOff + 1] = (byte)(word >>> 8);
-		out[outOff + 2] = (byte)(word >>> 16);
-		out[outOff + 3] = (byte)(word >>> 24);
-	}
-
-	public int doFinal(
-		byte[] out,
-		int outOff)
-	{
-		finish();
-
-		unpackWord(H0, out, outOff);
-		unpackWord(H1, out, outOff + 4);
-		unpackWord(H2, out, outOff + 8);
-		unpackWord(H3, out, outOff + 12);
-		unpackWord(H4, out, outOff + 16);
-		unpackWord(H5, out, outOff + 20);
-		unpackWord(H6, out, outOff + 24);
-		unpackWord(H7, out, outOff + 28);
-
-		reset();
-
-		return DIGEST_LENGTH;
-	}
-
-	/**
-	* reset the chaining variables to the IV values.
-	*/
-	public void reset()
-	{
-		super.reset();
-
-		H0 = 0x67452301;
-		H1 = 0xefcdab89;
-		H2 = 0x98badcfe;
-		H3 = 0x10325476; 
-		H4 = 0x76543210; 
-		H5 = 0xFEDCBA98; 
-		H6 = 0x89ABCDEF; 
-		H7 = 0x01234567;
-		
-		xOff = 0;
-
-		for (int i = 0; i != X.length; i++)
-		{
-			X[i] = 0;
-		}
-	}
-
-	/*
-	 * rotate int x left n bits.
-	 */
-	private final int RL(
-		int x,
-		int n)
-	{
-		return (x << n) | (x >>> (32 - n));
-	}
-
-	/*
-	 * f1,f2,f3,f4 are the basic RIPEMD128 functions.
-	 */
-
-	/*
-	 * F
-	 */
-	private final int f1(
-		int x,
-		int y,
-		int z)
-	{
-		return x ^ y ^ z;
-	}
-
-	/*
-	 * G
-	 */
-	private final int f2(
-		int x,
-		int y,
-		int z)
-	{
-		return (x & y) | (~x & z);
-	}
-
-	/*
-	 * H
-	 */
-	private final int f3(
-		int x,
-		int y,
-		int z)
-	{
-		return (x | ~y) ^ z;
-	}
-
-	/*
-	 * I
-	 */
-	private final int f4(
-		int x,
-		int y,
-		int z)
-	{
-		return (x & z) | (y & ~z);
-	}
-
-    private final int F1(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-        return RL(a + f1(b, c, d) + x, s);
-    }
-
-    private final int F2(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-        return RL(a + f2(b, c, d) + x + 0x5a827999, s);
-    }
-
-    private final int F3(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-        return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s);
-    }
-
-    private final int F4(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-        return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s);
-    }
-
-    private final int FF1(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-        return RL(a + f1(b, c, d) + x, s);
-    }
-
-    private final int FF2(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-      return RL(a + f2(b, c, d) + x + 0x6d703ef3, s);
-    }
-
-    private final int FF3(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-      return RL(a + f3(b, c, d) + x + 0x5c4dd124, s);
-    }
-
-    private final int FF4(
-        int a,
-        int b,
-        int c,
-        int d,
-        int x,
-        int s)
-    {
-      return RL(a + f4(b, c, d) + x + 0x50a28be6, s);
-    }
-
-	protected void processBlock()
-	{
-		int a, aa;
-		int b, bb;
-		int c, cc;
-		int d, dd;
-		int t;
-		
-		a = H0;
-		b = H1;
-		c = H2;
-		d = H3;
-		aa = H4;
-		bb = H5;
-		cc = H6;
-		dd = H7;
-
-		//
-		// Round 1
-		//
-		
-		a = F1(a, b, c, d, X[ 0], 11);
-        d = F1(d, a, b, c, X[ 1], 14);
-        c = F1(c, d, a, b, X[ 2], 15);
-        b = F1(b, c, d, a, X[ 3], 12);
-        a = F1(a, b, c, d, X[ 4],  5);
-        d = F1(d, a, b, c, X[ 5],  8);
-        c = F1(c, d, a, b, X[ 6],  7);
-        b = F1(b, c, d, a, X[ 7],  9);
-        a = F1(a, b, c, d, X[ 8], 11);
-        d = F1(d, a, b, c, X[ 9], 13);
-        c = F1(c, d, a, b, X[10], 14);
-        b = F1(b, c, d, a, X[11], 15);
-        a = F1(a, b, c, d, X[12],  6);
-        d = F1(d, a, b, c, X[13],  7);
-        c = F1(c, d, a, b, X[14],  9);
-        b = F1(b, c, d, a, X[15],  8);
-
-		aa = FF4(aa, bb, cc, dd, X[ 5],  8);
-        dd = FF4(dd, aa, bb, cc, X[14],  9);
-        cc = FF4(cc, dd, aa, bb, X[ 7],  9);
-        bb = FF4(bb, cc, dd, aa, X[ 0], 11);
-        aa = FF4(aa, bb, cc, dd, X[ 9], 13);
-        dd = FF4(dd, aa, bb, cc, X[ 2], 15);
-        cc = FF4(cc, dd, aa, bb, X[11], 15);
-        bb = FF4(bb, cc, dd, aa, X[ 4],  5);
-        aa = FF4(aa, bb, cc, dd, X[13],  7);
-        dd = FF4(dd, aa, bb, cc, X[ 6],  7);
-        cc = FF4(cc, dd, aa, bb, X[15],  8);
-        bb = FF4(bb, cc, dd, aa, X[ 8], 11);
-        aa = FF4(aa, bb, cc, dd, X[ 1], 14);
-        dd = FF4(dd, aa, bb, cc, X[10], 14);
-        cc = FF4(cc, dd, aa, bb, X[ 3], 12);
-        bb = FF4(bb, cc, dd, aa, X[12],  6);
-
-		t = a; a = aa; aa = t;
-		
-		//
-		// Round 2
-		//
-        a = F2(a, b, c, d, X[ 7],  7);
-        d = F2(d, a, b, c, X[ 4],  6);
-        c = F2(c, d, a, b, X[13],  8);
-        b = F2(b, c, d, a, X[ 1], 13);
-        a = F2(a, b, c, d, X[10], 11);
-        d = F2(d, a, b, c, X[ 6],  9);
-        c = F2(c, d, a, b, X[15],  7);
-        b = F2(b, c, d, a, X[ 3], 15);
-        a = F2(a, b, c, d, X[12],  7);
-        d = F2(d, a, b, c, X[ 0], 12);
-        c = F2(c, d, a, b, X[ 9], 15);
-        b = F2(b, c, d, a, X[ 5],  9);
-        a = F2(a, b, c, d, X[ 2], 11);
-        d = F2(d, a, b, c, X[14],  7);
-        c = F2(c, d, a, b, X[11], 13);
-        b = F2(b, c, d, a, X[ 8], 12);
-
-        aa = FF3(aa, bb, cc, dd, X[ 6],  9);
-        dd = FF3(dd, aa, bb, cc, X[ 11], 13);
-        cc = FF3(cc, dd, aa, bb, X[3], 15);
-        bb = FF3(bb, cc, dd, aa, X[ 7],  7);
-        aa = FF3(aa, bb, cc, dd, X[0], 12);
-        dd = FF3(dd, aa, bb, cc, X[13],  8);
-        cc = FF3(cc, dd, aa, bb, X[5],  9);
-        bb = FF3(bb, cc, dd, aa, X[10], 11);
-        aa = FF3(aa, bb, cc, dd, X[14],  7);
-        dd = FF3(dd, aa, bb, cc, X[15],  7);
-        cc = FF3(cc, dd, aa, bb, X[ 8], 12);
-        bb = FF3(bb, cc, dd, aa, X[12],  7);
-        aa = FF3(aa, bb, cc, dd, X[ 4],  6);
-        dd = FF3(dd, aa, bb, cc, X[ 9], 15);
-        cc = FF3(cc, dd, aa, bb, X[ 1], 13);
-        bb = FF3(bb, cc, dd, aa, X[ 2], 11);
-
-		t = b; b = bb; bb = t;
-		
-        //
-        // Round 3
-        //
-        a = F3(a, b, c, d, X[ 3], 11);
-        d = F3(d, a, b, c, X[10], 13);
-        c = F3(c, d, a, b, X[14],  6);
-        b = F3(b, c, d, a, X[ 4],  7);
-        a = F3(a, b, c, d, X[ 9], 14);
-        d = F3(d, a, b, c, X[15],  9);
-        c = F3(c, d, a, b, X[ 8], 13);
-        b = F3(b, c, d, a, X[ 1], 15);
-        a = F3(a, b, c, d, X[ 2], 14);
-        d = F3(d, a, b, c, X[ 7],  8);
-        c = F3(c, d, a, b, X[ 0], 13);
-        b = F3(b, c, d, a, X[ 6],  6);
-        a = F3(a, b, c, d, X[13],  5);
-        d = F3(d, a, b, c, X[11], 12);
-        c = F3(c, d, a, b, X[ 5],  7);
-        b = F3(b, c, d, a, X[12],  5);
-
-        aa = FF2(aa, bb, cc, dd, X[ 15], 9);
-        dd = FF2(dd, aa, bb, cc, X[5], 7);
-        cc = FF2(cc, dd, aa, bb, X[1], 15);
-        bb = FF2(bb, cc, dd, aa, X[ 3],  11);
-        aa = FF2(aa, bb, cc, dd, X[ 7], 8);
-        dd = FF2(dd, aa, bb, cc, X[14],  6);
-        cc = FF2(cc, dd, aa, bb, X[ 6], 6);
-        bb = FF2(bb, cc, dd, aa, X[ 9], 14);
-        aa = FF2(aa, bb, cc, dd, X[11], 12);
-        dd = FF2(dd, aa, bb, cc, X[ 8], 13);
-        cc = FF2(cc, dd, aa, bb, X[12],  5);
-        bb = FF2(bb, cc, dd, aa, X[ 2], 14);
-        aa = FF2(aa, bb, cc, dd, X[10], 13);
-        dd = FF2(dd, aa, bb, cc, X[ 0], 13);
-        cc = FF2(cc, dd, aa, bb, X[ 4],  7);
-        bb = FF2(bb, cc, dd, aa, X[13],  5);
-
-		t = c; c = cc; cc = t;
-
-        //
-        // Round 4
-        //
-        a = F4(a, b, c, d, X[ 1], 11);
-        d = F4(d, a, b, c, X[ 9], 12);
-        c = F4(c, d, a, b, X[11], 14);
-        b = F4(b, c, d, a, X[10], 15);
-        a = F4(a, b, c, d, X[ 0], 14);
-        d = F4(d, a, b, c, X[ 8], 15);
-        c = F4(c, d, a, b, X[12],  9);
-        b = F4(b, c, d, a, X[ 4],  8);
-        a = F4(a, b, c, d, X[13],  9);
-        d = F4(d, a, b, c, X[ 3], 14);
-        c = F4(c, d, a, b, X[ 7],  5);
-        b = F4(b, c, d, a, X[15],  6);
-        a = F4(a, b, c, d, X[14],  8);
-        d = F4(d, a, b, c, X[ 5],  6);
-        c = F4(c, d, a, b, X[ 6],  5);
-        b = F4(b, c, d, a, X[ 2], 12);
-
-        aa = FF1(aa, bb, cc, dd, X[ 8], 15);
-        dd = FF1(dd, aa, bb, cc, X[ 6],  5);
-        cc = FF1(cc, dd, aa, bb, X[ 4],  8);
-        bb = FF1(bb, cc, dd, aa, X[ 1], 11);
-        aa = FF1(aa, bb, cc, dd, X[ 3], 14);
-        dd = FF1(dd, aa, bb, cc, X[11], 14);
-        cc = FF1(cc, dd, aa, bb, X[15],  6);
-        bb = FF1(bb, cc, dd, aa, X[ 0], 14);
-        aa = FF1(aa, bb, cc, dd, X[ 5],  6);
-        dd = FF1(dd, aa, bb, cc, X[12],  9);
-        cc = FF1(cc, dd, aa, bb, X[ 2],  12);
-        bb = FF1(bb, cc, dd, aa, X[13],  9);
-        aa = FF1(aa, bb, cc, dd, X[ 9],  12);
-        dd = FF1(dd, aa, bb, cc, X[ 7],  5);
-        cc = FF1(cc, dd, aa, bb, X[10],  15);
-        bb = FF1(bb, cc, dd, aa, X[14], 8);
-
-		t = d; d = dd; dd = t;
-
-		H0 += a; 
-		H1 += b; 
-		H2 += c; 
-		H3 += d;
-		H4 += aa; 
-		H5 += bb; 
-		H6 += cc; 
-		H7 += dd;
-		
-		//
-		// reset the offset and clean out the word buffer.
-		//
-		xOff = 0;
-		for (int i = 0; i != X.length; i++)
-		{
-			X[i] = 0;
-		}
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD320Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD320Digest.java
deleted file mode 100644
index 819df25..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/RIPEMD320Digest.java
+++ /dev/null
@@ -1,461 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-/**
- * implementation of RIPEMD 320.
- * <p>
- * <b>Note:</b> this implementation offers the same level of security
- * as RIPEMD 160.
- */
-public class RIPEMD320Digest
-    extends GeneralDigest
-{
-	private static final int DIGEST_LENGTH = 40;
-
-	private int H0, H1, H2, H3, H4, H5, H6, H7, H8, H9; // IV's
-
-	private int[] X = new int[16];
-	private int xOff;
-
-	/**
-	 * Standard constructor
-	 */
-	public RIPEMD320Digest()
-	{
-		reset();
-	}
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public RIPEMD320Digest(RIPEMD320Digest t)
-	{
-		super(t);
-
-		H0 = t.H0;
-		H1 = t.H1;
-		H2 = t.H2;
-		H3 = t.H3;
-		H4 = t.H4;
-		H5 = t.H5;
-		H6 = t.H6;
-		H7 = t.H7;
-		H8 = t.H8;
-		H9 = t.H9;
-		
-		System.arraycopy(t.X, 0, X, 0, t.X.length);
-		xOff = t.xOff;
-	}
-
-	public String getAlgorithmName()
-	{
-		return "RIPEMD320";
-	}
-
-	public int getDigestSize()
-	{
-		return DIGEST_LENGTH;
-	}
-
-	protected void processWord(
-		byte[] in,
-		int inOff)
-	{
-		X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
-			| ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24); 
-
-		if (xOff == 16)
-		{
-			processBlock();
-		}
-	}
-
-	protected void processLength(
-		long bitLength)
-	{
-		if (xOff > 14)
-		{
-		processBlock();
-		}
-
-		X[14] = (int)(bitLength & 0xffffffff);
-		X[15] = (int)(bitLength >>> 32);
-	}
-
-	private void unpackWord(
-		int word,
-		byte[] out,
-		int outOff)
-	{
-		out[outOff]     = (byte)word;
-		out[outOff + 1] = (byte)(word >>> 8);
-		out[outOff + 2] = (byte)(word >>> 16);
-		out[outOff + 3] = (byte)(word >>> 24);
-	}
-
-	public int doFinal(
-		byte[] out,
-		int outOff)
-	{
-		finish();
-
-		unpackWord(H0, out, outOff);
-		unpackWord(H1, out, outOff + 4);
-		unpackWord(H2, out, outOff + 8);
-		unpackWord(H3, out, outOff + 12);
-		unpackWord(H4, out, outOff + 16);
-		unpackWord(H5, out, outOff + 20);
-		unpackWord(H6, out, outOff + 24);
-		unpackWord(H7, out, outOff + 28);
-		unpackWord(H8, out, outOff + 32);
-		unpackWord(H9, out, outOff + 36);
-
-		reset();
-
-		return DIGEST_LENGTH;
-	}
-
-	/**
-	* reset the chaining variables to the IV values.
-	*/
-	public void reset()
-	{
-		super.reset();
-
-		H0 = 0x67452301;
-		H1 = 0xefcdab89;
-		H2 = 0x98badcfe;
-		H3 = 0x10325476;
-		H4 = 0xc3d2e1f0;
-		H5 = 0x76543210; 
-		H6 = 0xFEDCBA98;
-		H7 = 0x89ABCDEF; 
-		H8 = 0x01234567; 
-		H9 = 0x3C2D1E0F;
-
-		xOff = 0;
-
-		for (int i = 0; i != X.length; i++)
-		{
-			X[i] = 0;
-		}
-	}
-
-	/*
-	 * rotate int x left n bits.
-	 */
-	private final int RL(
-		int x,
-		int n)
-	{
-		return (x << n) | (x >>> (32 - n));
-	}
-
-	/*
-	 * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions.
-	 */
-
-	/*
-	 * rounds 0-15
-	 */
-	private final int f1(
-		int x,
-		int y,
-		int z)
-	{
-		return x ^ y ^ z;
-	}
-
-	/*
-	 * rounds 16-31
-	 */
-	private final int f2(
-		int x,
-		int y,
-		int z)
-	{
-		return (x & y) | (~x & z);
-	}
-
-	/*
-	 * rounds 32-47
-	 */
-	private final int f3(
-		int x,
-		int y,
-		int z)
-	{
-		return (x | ~y) ^ z;
-	}
-
-	/*
-	 * rounds 48-63
-	 */
-	private final int f4(
-		int x,
-		int y,
-		int z)
-	{
-		return (x & z) | (y & ~z);
-	}
-
-	/*
-	 * rounds 64-79
-	 */
-	private final int f5(
-		int x,
-		int y,
-		int z)
-	{
-		return x ^ (y | ~z);
-	}
-
-	protected void processBlock()
-	{
-		int a, aa;
-		int b, bb;
-		int c, cc;
-		int d, dd;
-		int e, ee;
-        int t;
-
-		a = H0;
-		b = H1;
-		c = H2;
-		d = H3;
-		e = H4;
-		aa = H5;
-		bb = H6;
-		cc = H7;
-		dd = H8;
-		ee = H9;
-		
-		//
-		// Rounds 1 - 16
-		//
-		// left
-		a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10);
-		e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10);
-		d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10);
-		c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10);
-		b = RL(b + f1(c,d,e) + X[ 4],  5) + a; d = RL(d, 10);
-		a = RL(a + f1(b,c,d) + X[ 5],  8) + e; c = RL(c, 10);
-		e = RL(e + f1(a,b,c) + X[ 6],  7) + d; b = RL(b, 10);
-		d = RL(d + f1(e,a,b) + X[ 7],  9) + c; a = RL(a, 10);
-		c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10);
-		b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10);
-		a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10);
-		e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10);
-		d = RL(d + f1(e,a,b) + X[12],  6) + c; a = RL(a, 10);
-		c = RL(c + f1(d,e,a) + X[13],  7) + b; e = RL(e, 10);
-		b = RL(b + f1(c,d,e) + X[14],  9) + a; d = RL(d, 10);
-		a = RL(a + f1(b,c,d) + X[15],  8) + e; c = RL(c, 10);
-
-		// right
-		aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6,  8) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6,  9) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6,  9) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6,  5) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6,  7) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6,  7) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6,  8) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6,  6) + ee; cc = RL(cc, 10);
-
-        t = a; a = aa; aa = t;
-
-		//
-		// Rounds 16-31
-		//
-		// left
-		e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999,  7) + d; b = RL(b, 10);
-		d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999,  6) + c; a = RL(a, 10);
-		c = RL(c + f2(d,e,a) + X[13] + 0x5a827999,  8) + b; e = RL(e, 10);
-		b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10);
-		a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10);
-		e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999,  9) + d; b = RL(b, 10);
-		d = RL(d + f2(e,a,b) + X[15] + 0x5a827999,  7) + c; a = RL(a, 10);
-		c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10);
-		b = RL(b + f2(c,d,e) + X[12] + 0x5a827999,  7) + a; d = RL(d, 10);
-		a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10);
-		e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10);
-		d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999,  9) + c; a = RL(a, 10);
-		c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10);
-		b = RL(b + f2(c,d,e) + X[14] + 0x5a827999,  7) + a; d = RL(d, 10);
-		a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10);
-		e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10);
-
-		// right
-		ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124,  9) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124,  7) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124,  8) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124,  9) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124,  7) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124,  7) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124,  7) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124,  6) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10);
-
-        t = b; b = bb; bb = t;
-
-		//
-		// Rounds 32-47
-		//
-		// left
-		d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10);
-		c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
-		b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1,  6) + a; d = RL(d, 10);
-		a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1,  7) + e; c = RL(c, 10);
-		e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10);
-		d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1,  9) + c; a = RL(a, 10);
-		c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
-		b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10);
-		a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10);
-		e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1,  8) + d; b = RL(b, 10);
-		d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10);
-		c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1,  6) + b; e = RL(e, 10);
-		b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1,  5) + a; d = RL(d, 10);
-		a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10);
-		e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1,  7) + d; b = RL(b, 10);
-		d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1,  5) + c; a = RL(a, 10);
-
-		// right
-		dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3,  9) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3,  7) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3,  8) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3,  6) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3,  6) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3,  5) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3,  7) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3,  5) + cc; aa = RL(aa, 10);
-
-        t = c; c = cc; cc = t;
-
-		//
-		// Rounds 48-63
-		//
-		// left
-		c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10);
-		b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10);
-		a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10);
-		e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10);
-		d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
-		c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10);
-		b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc,  9) + a; d = RL(d, 10);
-		a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc,  8) + e; c = RL(c, 10);
-		e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc,  9) + d; b = RL(b, 10);
-		d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
-		c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc,  5) + b; e = RL(e, 10);
-		b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc,  6) + a; d = RL(d, 10);
-		a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc,  8) + e; c = RL(c, 10);
-		e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc,  6) + d; b = RL(b, 10);
-		d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc,  5) + c; a = RL(a, 10);
-		c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10);
-
-		// right
-		cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9,  5) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9,  8) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9,  6) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9,  6) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9,  9) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9,  9) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9,  5) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9,  8) + bb; ee = RL(ee, 10);
-
-       t = d; d = dd; dd = t;
-
-		//
-		// Rounds 64-79
-		//
-		// left
-		b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e,  9) + a; d = RL(d, 10);
-		a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10);
-		e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e,  5) + d; b = RL(b, 10);
-		d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10);
-		c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e,  6) + b; e = RL(e, 10);
-		b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e,  8) + a; d = RL(d, 10);
-		a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10);
-		e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10);
-		d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e,  5) + c; a = RL(a, 10);
-		c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10);
-		b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10);
-		a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10);
-		e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10);
-		d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e,  8) + c; a = RL(a, 10);
-		c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e,  5) + b; e = RL(e, 10);
-		b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e,  6) + a; d = RL(d, 10);
-
-		// right
-		bb = RL(bb + f1(cc,dd,ee) + X[12],  8) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f1(bb,cc,dd) + X[15],  5) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f1(ee,aa,bb) + X[ 4],  9) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f1(cc,dd,ee) + X[ 5],  5) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f1(aa,bb,cc) + X[ 7],  6) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f1(ee,aa,bb) + X[ 6],  8) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f1(cc,dd,ee) + X[13],  6) + aa; dd = RL(dd, 10);
-		aa = RL(aa + f1(bb,cc,dd) + X[14],  5) + ee; cc = RL(cc, 10);
-		ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10);
-		dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10);
-		cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10);
-		bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10);
-
-        //
-        // do (e, ee) swap as part of assignment.
-        //
-
-		H0 += a;
-		H1 += b;
-		H2 += c;
-		H3 += d;
-		H4 += ee;
-		H5 += aa;
-		H6 += bb;
-		H7 += cc;
-		H8 += dd;
-		H9 += e;
-		
-		//
-		// reset the offset and clean out the word buffer.
-		//
-		xOff = 0;
-		for (int i = 0; i != X.length; i++)
-		{
-			X[i] = 0;
-		}
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/SHA1Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/SHA1Digest.java
deleted file mode 100644
index 0a3fad7..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/SHA1Digest.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-/**
- * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
- *
- * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
- * is the "endienness" of the word processing!
- */
-public class SHA1Digest
-    extends GeneralDigest
-{
-    private static final int    DIGEST_LENGTH = 20;
-
-    private int     H1, H2, H3, H4, H5;
-
-    private int[]   X = new int[80];
-    private int     xOff;
-
-	/**
-	 * Standard constructor
-	 */
-    public SHA1Digest()
-    {
-        reset();
-    }
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public SHA1Digest(SHA1Digest t)
-	{
-		super(t);
-
-		H1 = t.H1;
-		H2 = t.H2;
-		H3 = t.H3;
-		H4 = t.H4;
-		H5 = t.H5;
-
-		System.arraycopy(t.X, 0, X, 0, t.X.length);
-		xOff = t.xOff;
-	}
-
-    public String getAlgorithmName()
-    {
-        return "SHA-1";
-    }
-
-    public int getDigestSize()
-    {
-        return DIGEST_LENGTH;
-    }
-
-    protected void processWord(
-        byte[]  in,
-        int     inOff)
-    {
-        X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16)
-                    | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff)); 
-
-        if (xOff == 16)
-        {
-            processBlock();
-        }
-    }
-
-    private void unpackWord(
-        int     word,
-        byte[]  out,
-        int     outOff)
-    {
-        out[outOff]     = (byte)(word >>> 24);
-        out[outOff + 1] = (byte)(word >>> 16);
-        out[outOff + 2] = (byte)(word >>> 8);
-        out[outOff + 3] = (byte)word;
-    }
-
-    protected void processLength(
-        long    bitLength)
-    {
-        if (xOff > 14)
-        {
-            processBlock();
-        }
-
-        X[14] = (int)(bitLength >>> 32);
-        X[15] = (int)(bitLength & 0xffffffff);
-    }
-
-    public int doFinal(
-        byte[]  out,
-        int     outOff)
-    {
-        finish();
-
-        unpackWord(H1, out, outOff);
-        unpackWord(H2, out, outOff + 4);
-        unpackWord(H3, out, outOff + 8);
-        unpackWord(H4, out, outOff + 12);
-        unpackWord(H5, out, outOff + 16);
-
-        reset();
-
-        return DIGEST_LENGTH;
-    }
-
-    /**
-     * reset the chaining variables
-     */
-    public void reset()
-    {
-        super.reset();
-
-        H1 = 0x67452301;
-        H2 = 0xefcdab89;
-        H3 = 0x98badcfe;
-        H4 = 0x10325476;
-        H5 = 0xc3d2e1f0;
-
-        xOff = 0;
-        for (int i = 0; i != X.length; i++)
-        {
-            X[i] = 0;
-        }
-    }
-
-    //
-    // Additive constants
-    //
-    private static final int    Y1 = 0x5a827999;
-    private static final int    Y2 = 0x6ed9eba1;
-    private static final int    Y3 = 0x8f1bbcdc;
-    private static final int    Y4 = 0xca62c1d6;
-
-    private int f(
-        int    u,
-        int    v,
-        int    w)
-    {
-        return ((u & v) | ((~u) & w));
-    }
-
-    private int h(
-        int    u,
-        int    v,
-        int    w)
-    {
-        return (u ^ v ^ w);
-    }
-
-    private int g(
-        int    u,
-        int    v,
-        int    w)
-    {
-        return ((u & v) | (u & w) | (v & w));
-    }
-
-    private int rotateLeft(
-        int    x,
-        int    n)
-    {
-        return (x << n) | (x >>> (32 - n));
-    }
-
-    protected void processBlock()
-    {
-        //
-        // expand 16 word block into 80 word block.
-        //
-        for (int i = 16; i <= 79; i++)
-        {
-            X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1);
-        }
-
-        //
-        // set up working variables.
-        //
-        int     A = H1;
-        int     B = H2;
-        int     C = H3;
-        int     D = H4;
-        int     E = H5;
-
-        //
-        // round 1
-        //
-        for (int j = 0; j <= 19; j++)
-        {
-            int     t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1;
-
-            E = D;
-            D = C;
-            C = rotateLeft(B, 30);
-            B = A;
-            A = t;
-        }
-
-        //
-        // round 2
-        //
-        for (int j = 20; j <= 39; j++)
-        {
-            int     t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2;
-
-            E = D;
-            D = C;
-            C = rotateLeft(B, 30);
-            B = A;
-            A = t;
-        }
-
-        //
-        // round 3
-        //
-        for (int j = 40; j <= 59; j++)
-        {
-            int     t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3;
-
-            E = D;
-            D = C;
-            C = rotateLeft(B, 30);
-            B = A;
-            A = t;
-        }
-
-        //
-        // round 4
-        //
-        for (int j = 60; j <= 79; j++)
-        {
-            int     t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4;
-
-            E = D;
-            D = C;
-            C = rotateLeft(B, 30);
-            B = A;
-            A = t;
-        }
-
-        H1 += A;
-        H2 += B;
-        H3 += C;
-        H4 += D;
-        H5 += E;
-
-        //
-        // reset the offset and clean out the word buffer.
-        //
-        xOff = 0;
-        for (int i = 0; i != X.length; i++)
-        {
-            X[i] = 0;
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/SHA256Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/SHA256Digest.java
deleted file mode 100644
index 9e7e55b..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/SHA256Digest.java
+++ /dev/null
@@ -1,268 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-/**
- * Draft FIPS 180-2 implementation of SHA-256. <b>Note:</b> As this is
- * based on a draft this implementation is subject to change.
- *
- * <pre>
- *         block  word  digest
- * SHA-1   512    32    160
- * SHA-256 512    32    256
- * SHA-384 1024   64    384
- * SHA-512 1024   64    512
- * </pre>
- */
-public class SHA256Digest
-    extends GeneralDigest
-{
-    private static final int    DIGEST_LENGTH = 32;
-
-    private int     H1, H2, H3, H4, H5, H6, H7, H8;
-
-    private int[]   X = new int[64];
-    private int     xOff;
-
-	/**
-	 * Standard constructor
-	 */
-    public SHA256Digest()
-    {
-        reset();
-    }
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public SHA256Digest(SHA256Digest t)
-	{
-		super(t);
-
-		H1 = t.H1;
-		H2 = t.H2;
-		H3 = t.H3;
-		H4 = t.H4;
-		H5 = t.H5;
-		H6 = t.H6;
-		H7 = t.H7;
-		H8 = t.H8;
-
-		System.arraycopy(t.X, 0, X, 0, t.X.length);
-		xOff = t.xOff;
-	}
-
-    public String getAlgorithmName()
-    {
-        return "SHA-256";
-    }
-
-    public int getDigestSize()
-    {
-        return DIGEST_LENGTH;
-    }
-
-    protected void processWord(
-        byte[]  in,
-        int     inOff)
-    {
-        X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16)
-                    | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff)); 
-
-        if (xOff == 16)
-        {
-            processBlock();
-        }
-    }
-
-    private void unpackWord(
-        int     word,
-        byte[]  out,
-        int     outOff)
-    {
-        out[outOff]     = (byte)(word >>> 24);
-        out[outOff + 1] = (byte)(word >>> 16);
-        out[outOff + 2] = (byte)(word >>> 8);
-        out[outOff + 3] = (byte)word;
-    }
-
-    protected void processLength(
-        long    bitLength)
-    {
-        if (xOff > 14)
-        {
-            processBlock();
-        }
-
-        X[14] = (int)(bitLength >>> 32);
-        X[15] = (int)(bitLength & 0xffffffff);
-    }
-
-    public int doFinal(
-        byte[]  out,
-        int     outOff)
-    {
-        finish();
-
-        unpackWord(H1, out, outOff);
-        unpackWord(H2, out, outOff + 4);
-        unpackWord(H3, out, outOff + 8);
-        unpackWord(H4, out, outOff + 12);
-        unpackWord(H5, out, outOff + 16);
-        unpackWord(H6, out, outOff + 20);
-        unpackWord(H7, out, outOff + 24);
-        unpackWord(H8, out, outOff + 28);
-
-        reset();
-
-        return DIGEST_LENGTH;
-    }
-
-    /**
-     * reset the chaining variables
-     */
-    public void reset()
-    {
-        super.reset();
-
-		/* SHA-256 initial hash value
-		 * The first 32 bits of the fractional parts of the square roots
-		 * of the first eight prime numbers
-		 */
-
-		H1 = 0x6a09e667;
-		H2 = 0xbb67ae85;
-		H3 = 0x3c6ef372;
-		H4 = 0xa54ff53a;
-		H5 = 0x510e527f;
-		H6 = 0x9b05688c;
-		H7 = 0x1f83d9ab;
-		H8 = 0x5be0cd19;
-
-        xOff = 0;
-        for (int i = 0; i != X.length; i++)
-        {
-            X[i] = 0;
-        }
-    }
-
-    protected void processBlock()
-    {
-        //
-        // expand 16 word block into 64 word blocks.
-        //
-        for (int t = 16; t <= 63; t++)
-        {
-            X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
-        }
-
-        //
-        // set up working variables.
-        //
-        int     a = H1;
-        int     b = H2;
-        int     c = H3;
-        int     d = H4;
-        int     e = H5;
-        int     f = H6;
-        int     g = H7;
-        int     h = H8;
-
-		for (int t = 0; t <= 63; t++)
-		{
-			int		T1, T2;
-
-			T1 = h + Sum1(e) + Ch(e, f, g) + K[t] + X[t];
-			T2 = Sum0(a) + Maj(a, b, c);
-			h = g;
-			g = f;
-			f = e;
-			e = d + T1;
-			d = c;
-			c = b;
-			b = a;
-			a = T1 + T2;
-		}
-
-        H1 += a;
-        H2 += b;
-        H3 += c;
-        H4 += d;
-        H5 += e;
-        H6 += f;
-        H7 += g;
-        H8 += h;
-
-        //
-        // reset the offset and clean out the word buffer.
-        //
-        xOff = 0;
-        for (int i = 0; i != X.length; i++)
-        {
-            X[i] = 0;
-        }
-    }
-
-    private int rotateRight(
-        int    x,
-        int    n)
-    {
-        return (x >>> n) | (x << (32 - n));
-    }
-
-	/* SHA-256 functions */
-    private int Ch(
-        int    x,
-        int    y,
-        int    z)
-    {
-        return ((x & y) ^ ((~x) & z));
-    }
-
-    private int Maj(
-        int    x,
-        int    y,
-        int    z)
-    {
-        return ((x & y) ^ (x & z) ^ (y & z));
-    }
-
-    private int Sum0(
-        int    x)
-    {
-        return rotateRight(x, 2) ^ rotateRight(x, 13) ^ rotateRight(x, 22);
-    }
-
-    private int Sum1(
-        int    x)
-    {
-        return rotateRight(x, 6) ^ rotateRight(x, 11) ^ rotateRight(x, 25);
-    }
-
-    private int Theta0(
-        int    x)
-    {
-        return rotateRight(x, 7) ^ rotateRight(x, 18) ^ (x >>> 3);
-    }
-
-    private int Theta1(
-        int    x)
-    {
-        return rotateRight(x, 17) ^ rotateRight(x, 19) ^ (x >>> 10);
-    }
-
-	/* SHA-256 Constants
-	 * (represent the first 32 bits of the fractional parts of the
-     * cube roots of the first sixty-four prime numbers)
-	 */
-	static final int K[] = {
-		0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
-		0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
-		0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
-		0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
-		0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
-		0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
-		0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-	};
-}
-
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/SHA384Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/SHA384Digest.java
deleted file mode 100644
index 06998b1..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/SHA384Digest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-/**
- * Draft FIPS 180-2 implementation of SHA-384. <b>Note:</b> As this is
- * based on a draft this implementation is subject to change.
- *
- * <pre>
- *         block  word  digest
- * SHA-1   512    32    160
- * SHA-256 512    32    256
- * SHA-384 1024   64    384
- * SHA-512 1024   64    512
- * </pre>
- */
-public class SHA384Digest
-    extends LongDigest
-{
-
-	private static final int	DIGEST_LENGTH = 48;
-
-	/**
-	 * Standard constructor
-	 */
-    public SHA384Digest()
-    {
-    }
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public SHA384Digest(SHA384Digest t)
-	{
-		super(t);
-	}
-
-    public String getAlgorithmName()
-	{
-		return "SHA-384";
-	}
-
-	public int getDigestSize()
-	{
-		return DIGEST_LENGTH;
-	}
-
-    public int doFinal(
-        byte[]  out,
-        int     outOff)
-    {
-        finish();
-
-        unpackWord(H1, out, outOff);
-        unpackWord(H2, out, outOff + 8);
-        unpackWord(H3, out, outOff + 16);
-        unpackWord(H4, out, outOff + 24);
-        unpackWord(H5, out, outOff + 32);
-        unpackWord(H6, out, outOff + 40);
-
-        reset();
-
-        return DIGEST_LENGTH;
-    }
-
-    /**
-     * reset the chaining variables
-     */
-    public void reset()
-    {
-        super.reset();
-
-		/* SHA-384 initial hash value
-		 * The first 64 bits of the fractional parts of the square roots
-		 * of the 9th through 16th prime numbers
-		 */
-		H1 = 0xcbbb9d5dc1059ed8l;
-		H2 = 0x629a292a367cd507l;
-		H3 = 0x9159015a3070dd17l;
-		H4 = 0x152fecd8f70e5939l;
-		H5 = 0x67332667ffc00b31l;
-		H6 = 0x8eb44a8768581511l;
-		H7 = 0xdb0c2e0d64f98fa7l;
-		H8 = 0x47b5481dbefa4fa4l;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/SHA512Digest.java b/azureus2/src/org/bouncycastle/crypto/digests/SHA512Digest.java
deleted file mode 100644
index 82d7f86..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/SHA512Digest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-
-/**
- * Draft FIPS 180-2 implementation of SHA-512. <b>Note:</b> As this is
- * based on a draft this implementation is subject to change.
- *
- * <pre>
- *         block  word  digest
- * SHA-1   512    32    160
- * SHA-256 512    32    256
- * SHA-384 1024   64    384
- * SHA-512 1024   64    512
- * </pre>
- */
-public class SHA512Digest
-    extends LongDigest
-{
-    private static final int    DIGEST_LENGTH = 64;
-
-	/**
-	 * Standard constructor
-	 */
-    public SHA512Digest()
-    {
-    }
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public SHA512Digest(SHA512Digest t)
-	{
-		super(t);
-	}
-
-    public String getAlgorithmName()
-    {
-        return "SHA-512";
-    }
-
-    public int getDigestSize()
-    {
-        return DIGEST_LENGTH;
-    }
-
-    public int doFinal(
-        byte[]  out,
-        int     outOff)
-    {
-        finish();
-
-        unpackWord(H1, out, outOff);
-        unpackWord(H2, out, outOff + 8);
-        unpackWord(H3, out, outOff + 16);
-        unpackWord(H4, out, outOff + 24);
-        unpackWord(H5, out, outOff + 32);
-        unpackWord(H6, out, outOff + 40);
-        unpackWord(H7, out, outOff + 48);
-        unpackWord(H8, out, outOff + 56);
-
-        reset();
-
-        return DIGEST_LENGTH;
-    }
-
-    /**
-     * reset the chaining variables
-     */
-    public void reset()
-    {
-        super.reset();
-
-		/* SHA-512 initial hash value
-		 * The first 64 bits of the fractional parts of the square roots
-		 * of the first eight prime numbers
-		 */
-		H1 = 0x6a09e667f3bcc908l;
-		H2 = 0xbb67ae8584caa73bl;
-		H3 = 0x3c6ef372fe94f82bl;
-		H4 = 0xa54ff53a5f1d36f1l;
-		H5 = 0x510e527fade682d1l;
-		H6 = 0x9b05688c2b3e6c1fl;
-		H7 = 0x1f83d9abfb41bd6bl;
-		H8 = 0x5be0cd19137e2179L;
-    }
-}
-
diff --git a/azureus2/src/org/bouncycastle/crypto/digests/TigerDigest.java b/azureus2/src/org/bouncycastle/crypto/digests/TigerDigest.java
deleted file mode 100644
index 04d62b2..0000000
--- a/azureus2/src/org/bouncycastle/crypto/digests/TigerDigest.java
+++ /dev/null
@@ -1,859 +0,0 @@
-package org.bouncycastle.crypto.digests;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * implementation of Tiger based on:
- * <a href="http://www.cs.technion.ac.il/~biham/Reports/Tiger">
- *  http://www.cs.technion.ac.il/~biham/Reports/Tiger</a>
- */
-public class TigerDigest
-    implements Digest
-{
-    /*
-     * S-Boxes.
-     */
-    private static final long[] t1 = {
-        0x02AAB17CF7E90C5EL   /*    0 */,    0xAC424B03E243A8ECL   /*    1 */,
-        0x72CD5BE30DD5FCD3L   /*    2 */,    0x6D019B93F6F97F3AL   /*    3 */,
-        0xCD9978FFD21F9193L   /*    4 */,    0x7573A1C9708029E2L   /*    5 */,
-        0xB164326B922A83C3L   /*    6 */,    0x46883EEE04915870L   /*    7 */,
-        0xEAACE3057103ECE6L   /*    8 */,    0xC54169B808A3535CL   /*    9 */,
-        0x4CE754918DDEC47CL   /*   10 */,    0x0AA2F4DFDC0DF40CL   /*   11 */,
-        0x10B76F18A74DBEFAL   /*   12 */,    0xC6CCB6235AD1AB6AL   /*   13 */,
-        0x13726121572FE2FFL   /*   14 */,    0x1A488C6F199D921EL   /*   15 */,
-        0x4BC9F9F4DA0007CAL   /*   16 */,    0x26F5E6F6E85241C7L   /*   17 */,
-        0x859079DBEA5947B6L   /*   18 */,    0x4F1885C5C99E8C92L   /*   19 */,
-        0xD78E761EA96F864BL   /*   20 */,    0x8E36428C52B5C17DL   /*   21 */,
-        0x69CF6827373063C1L   /*   22 */,    0xB607C93D9BB4C56EL   /*   23 */,
-        0x7D820E760E76B5EAL   /*   24 */,    0x645C9CC6F07FDC42L   /*   25 */,
-        0xBF38A078243342E0L   /*   26 */,    0x5F6B343C9D2E7D04L   /*   27 */,
-        0xF2C28AEB600B0EC6L   /*   28 */,    0x6C0ED85F7254BCACL   /*   29 */,
-        0x71592281A4DB4FE5L   /*   30 */,    0x1967FA69CE0FED9FL   /*   31 */,
-        0xFD5293F8B96545DBL   /*   32 */,    0xC879E9D7F2A7600BL   /*   33 */,
-        0x860248920193194EL   /*   34 */,    0xA4F9533B2D9CC0B3L   /*   35 */,
-        0x9053836C15957613L   /*   36 */,    0xDB6DCF8AFC357BF1L   /*   37 */,
-        0x18BEEA7A7A370F57L   /*   38 */,    0x037117CA50B99066L   /*   39 */,
-        0x6AB30A9774424A35L   /*   40 */,    0xF4E92F02E325249BL   /*   41 */,
-        0x7739DB07061CCAE1L   /*   42 */,    0xD8F3B49CECA42A05L   /*   43 */,
-        0xBD56BE3F51382F73L   /*   44 */,    0x45FAED5843B0BB28L   /*   45 */,
-        0x1C813D5C11BF1F83L   /*   46 */,    0x8AF0E4B6D75FA169L   /*   47 */,
-        0x33EE18A487AD9999L   /*   48 */,    0x3C26E8EAB1C94410L   /*   49 */,
-        0xB510102BC0A822F9L   /*   50 */,    0x141EEF310CE6123BL   /*   51 */,
-        0xFC65B90059DDB154L   /*   52 */,    0xE0158640C5E0E607L   /*   53 */,
-        0x884E079826C3A3CFL   /*   54 */,    0x930D0D9523C535FDL   /*   55 */,
-        0x35638D754E9A2B00L   /*   56 */,    0x4085FCCF40469DD5L   /*   57 */,
-        0xC4B17AD28BE23A4CL   /*   58 */,    0xCAB2F0FC6A3E6A2EL   /*   59 */,
-        0x2860971A6B943FCDL   /*   60 */,    0x3DDE6EE212E30446L   /*   61 */,
-        0x6222F32AE01765AEL   /*   62 */,    0x5D550BB5478308FEL   /*   63 */,
-        0xA9EFA98DA0EDA22AL   /*   64 */,    0xC351A71686C40DA7L   /*   65 */,
-        0x1105586D9C867C84L   /*   66 */,    0xDCFFEE85FDA22853L   /*   67 */,
-        0xCCFBD0262C5EEF76L   /*   68 */,    0xBAF294CB8990D201L   /*   69 */,
-        0xE69464F52AFAD975L   /*   70 */,    0x94B013AFDF133E14L   /*   71 */,
-        0x06A7D1A32823C958L   /*   72 */,    0x6F95FE5130F61119L   /*   73 */,
-        0xD92AB34E462C06C0L   /*   74 */,    0xED7BDE33887C71D2L   /*   75 */,
-        0x79746D6E6518393EL   /*   76 */,    0x5BA419385D713329L   /*   77 */,
-        0x7C1BA6B948A97564L   /*   78 */,    0x31987C197BFDAC67L   /*   79 */,
-        0xDE6C23C44B053D02L   /*   80 */,    0x581C49FED002D64DL   /*   81 */,
-        0xDD474D6338261571L   /*   82 */,    0xAA4546C3E473D062L   /*   83 */,
-        0x928FCE349455F860L   /*   84 */,    0x48161BBACAAB94D9L   /*   85 */,
-        0x63912430770E6F68L   /*   86 */,    0x6EC8A5E602C6641CL   /*   87 */,
-        0x87282515337DDD2BL   /*   88 */,    0x2CDA6B42034B701BL   /*   89 */,
-        0xB03D37C181CB096DL   /*   90 */,    0xE108438266C71C6FL   /*   91 */,
-        0x2B3180C7EB51B255L   /*   92 */,    0xDF92B82F96C08BBCL   /*   93 */,
-        0x5C68C8C0A632F3BAL   /*   94 */,    0x5504CC861C3D0556L   /*   95 */,
-        0xABBFA4E55FB26B8FL   /*   96 */,    0x41848B0AB3BACEB4L   /*   97 */,
-        0xB334A273AA445D32L   /*   98 */,    0xBCA696F0A85AD881L   /*   99 */,
-        0x24F6EC65B528D56CL   /*  100 */,    0x0CE1512E90F4524AL   /*  101 */,
-        0x4E9DD79D5506D35AL   /*  102 */,    0x258905FAC6CE9779L   /*  103 */,
-        0x2019295B3E109B33L   /*  104 */,    0xF8A9478B73A054CCL   /*  105 */,
-        0x2924F2F934417EB0L   /*  106 */,    0x3993357D536D1BC4L   /*  107 */,
-        0x38A81AC21DB6FF8BL   /*  108 */,    0x47C4FBF17D6016BFL   /*  109 */,
-        0x1E0FAADD7667E3F5L   /*  110 */,    0x7ABCFF62938BEB96L   /*  111 */,
-        0xA78DAD948FC179C9L   /*  112 */,    0x8F1F98B72911E50DL   /*  113 */,
-        0x61E48EAE27121A91L   /*  114 */,    0x4D62F7AD31859808L   /*  115 */,
-        0xECEBA345EF5CEAEBL   /*  116 */,    0xF5CEB25EBC9684CEL   /*  117 */,
-        0xF633E20CB7F76221L   /*  118 */,    0xA32CDF06AB8293E4L   /*  119 */,
-        0x985A202CA5EE2CA4L   /*  120 */,    0xCF0B8447CC8A8FB1L   /*  121 */,
-        0x9F765244979859A3L   /*  122 */,    0xA8D516B1A1240017L   /*  123 */,
-        0x0BD7BA3EBB5DC726L   /*  124 */,    0xE54BCA55B86ADB39L   /*  125 */,
-        0x1D7A3AFD6C478063L   /*  126 */,    0x519EC608E7669EDDL   /*  127 */,
-        0x0E5715A2D149AA23L   /*  128 */,    0x177D4571848FF194L   /*  129 */,
-        0xEEB55F3241014C22L   /*  130 */,    0x0F5E5CA13A6E2EC2L   /*  131 */,
-        0x8029927B75F5C361L   /*  132 */,    0xAD139FABC3D6E436L   /*  133 */,
-        0x0D5DF1A94CCF402FL   /*  134 */,    0x3E8BD948BEA5DFC8L   /*  135 */,
-        0xA5A0D357BD3FF77EL   /*  136 */,    0xA2D12E251F74F645L   /*  137 */,
-        0x66FD9E525E81A082L   /*  138 */,    0x2E0C90CE7F687A49L   /*  139 */,
-        0xC2E8BCBEBA973BC5L   /*  140 */,    0x000001BCE509745FL   /*  141 */,
-        0x423777BBE6DAB3D6L   /*  142 */,    0xD1661C7EAEF06EB5L   /*  143 */,
-        0xA1781F354DAACFD8L   /*  144 */,    0x2D11284A2B16AFFCL   /*  145 */,
-        0xF1FC4F67FA891D1FL   /*  146 */,    0x73ECC25DCB920ADAL   /*  147 */,
-        0xAE610C22C2A12651L   /*  148 */,    0x96E0A810D356B78AL   /*  149 */,
-        0x5A9A381F2FE7870FL   /*  150 */,    0xD5AD62EDE94E5530L   /*  151 */,
-        0xD225E5E8368D1427L   /*  152 */,    0x65977B70C7AF4631L   /*  153 */,
-        0x99F889B2DE39D74FL   /*  154 */,    0x233F30BF54E1D143L   /*  155 */,
-        0x9A9675D3D9A63C97L   /*  156 */,    0x5470554FF334F9A8L   /*  157 */,
-        0x166ACB744A4F5688L   /*  158 */,    0x70C74CAAB2E4AEADL   /*  159 */,
-        0xF0D091646F294D12L   /*  160 */,    0x57B82A89684031D1L   /*  161 */,
-        0xEFD95A5A61BE0B6BL   /*  162 */,    0x2FBD12E969F2F29AL   /*  163 */,
-        0x9BD37013FEFF9FE8L   /*  164 */,    0x3F9B0404D6085A06L   /*  165 */,
-        0x4940C1F3166CFE15L   /*  166 */,    0x09542C4DCDF3DEFBL   /*  167 */,
-        0xB4C5218385CD5CE3L   /*  168 */,    0xC935B7DC4462A641L   /*  169 */,
-        0x3417F8A68ED3B63FL   /*  170 */,    0xB80959295B215B40L   /*  171 */,
-        0xF99CDAEF3B8C8572L   /*  172 */,    0x018C0614F8FCB95DL   /*  173 */,
-        0x1B14ACCD1A3ACDF3L   /*  174 */,    0x84D471F200BB732DL   /*  175 */,
-        0xC1A3110E95E8DA16L   /*  176 */,    0x430A7220BF1A82B8L   /*  177 */,
-        0xB77E090D39DF210EL   /*  178 */,    0x5EF4BD9F3CD05E9DL   /*  179 */,
-        0x9D4FF6DA7E57A444L   /*  180 */,    0xDA1D60E183D4A5F8L   /*  181 */,
-        0xB287C38417998E47L   /*  182 */,    0xFE3EDC121BB31886L   /*  183 */,
-        0xC7FE3CCC980CCBEFL   /*  184 */,    0xE46FB590189BFD03L   /*  185 */,
-        0x3732FD469A4C57DCL   /*  186 */,    0x7EF700A07CF1AD65L   /*  187 */,
-        0x59C64468A31D8859L   /*  188 */,    0x762FB0B4D45B61F6L   /*  189 */,
-        0x155BAED099047718L   /*  190 */,    0x68755E4C3D50BAA6L   /*  191 */,
-        0xE9214E7F22D8B4DFL   /*  192 */,    0x2ADDBF532EAC95F4L   /*  193 */,
-        0x32AE3909B4BD0109L   /*  194 */,    0x834DF537B08E3450L   /*  195 */,
-        0xFA209DA84220728DL   /*  196 */,    0x9E691D9B9EFE23F7L   /*  197 */,
-        0x0446D288C4AE8D7FL   /*  198 */,    0x7B4CC524E169785BL   /*  199 */,
-        0x21D87F0135CA1385L   /*  200 */,    0xCEBB400F137B8AA5L   /*  201 */,
-        0x272E2B66580796BEL   /*  202 */,    0x3612264125C2B0DEL   /*  203 */,
-        0x057702BDAD1EFBB2L   /*  204 */,    0xD4BABB8EACF84BE9L   /*  205 */,
-        0x91583139641BC67BL   /*  206 */,    0x8BDC2DE08036E024L   /*  207 */,
-        0x603C8156F49F68EDL   /*  208 */,    0xF7D236F7DBEF5111L   /*  209 */,
-        0x9727C4598AD21E80L   /*  210 */,    0xA08A0896670A5FD7L   /*  211 */,
-        0xCB4A8F4309EBA9CBL   /*  212 */,    0x81AF564B0F7036A1L   /*  213 */,
-        0xC0B99AA778199ABDL   /*  214 */,    0x959F1EC83FC8E952L   /*  215 */,
-        0x8C505077794A81B9L   /*  216 */,    0x3ACAAF8F056338F0L   /*  217 */,
-        0x07B43F50627A6778L   /*  218 */,    0x4A44AB49F5ECCC77L   /*  219 */,
-        0x3BC3D6E4B679EE98L   /*  220 */,    0x9CC0D4D1CF14108CL   /*  221 */,
-        0x4406C00B206BC8A0L   /*  222 */,    0x82A18854C8D72D89L   /*  223 */,
-        0x67E366B35C3C432CL   /*  224 */,    0xB923DD61102B37F2L   /*  225 */,
-        0x56AB2779D884271DL   /*  226 */,    0xBE83E1B0FF1525AFL   /*  227 */,
-        0xFB7C65D4217E49A9L   /*  228 */,    0x6BDBE0E76D48E7D4L   /*  229 */,
-        0x08DF828745D9179EL   /*  230 */,    0x22EA6A9ADD53BD34L   /*  231 */,
-        0xE36E141C5622200AL   /*  232 */,    0x7F805D1B8CB750EEL   /*  233 */,
-        0xAFE5C7A59F58E837L   /*  234 */,    0xE27F996A4FB1C23CL   /*  235 */,
-        0xD3867DFB0775F0D0L   /*  236 */,    0xD0E673DE6E88891AL   /*  237 */,
-        0x123AEB9EAFB86C25L   /*  238 */,    0x30F1D5D5C145B895L   /*  239 */,
-        0xBB434A2DEE7269E7L   /*  240 */,    0x78CB67ECF931FA38L   /*  241 */,
-        0xF33B0372323BBF9CL   /*  242 */,    0x52D66336FB279C74L   /*  243 */,
-        0x505F33AC0AFB4EAAL   /*  244 */,    0xE8A5CD99A2CCE187L   /*  245 */,
-        0x534974801E2D30BBL   /*  246 */,    0x8D2D5711D5876D90L   /*  247 */,
-        0x1F1A412891BC038EL   /*  248 */,    0xD6E2E71D82E56648L   /*  249 */,
-        0x74036C3A497732B7L   /*  250 */,    0x89B67ED96361F5ABL   /*  251 */,
-        0xFFED95D8F1EA02A2L   /*  252 */,    0xE72B3BD61464D43DL   /*  253 */,
-        0xA6300F170BDC4820L   /*  254 */,    0xEBC18760ED78A77AL   /*  255 */,
-    };
-
-    private static final long[] t2 = {
-        0xE6A6BE5A05A12138L   /*  256 */,    0xB5A122A5B4F87C98L   /*  257 */,
-        0x563C6089140B6990L   /*  258 */,    0x4C46CB2E391F5DD5L   /*  259 */,
-        0xD932ADDBC9B79434L   /*  260 */,    0x08EA70E42015AFF5L   /*  261 */,
-        0xD765A6673E478CF1L   /*  262 */,    0xC4FB757EAB278D99L   /*  263 */,
-        0xDF11C6862D6E0692L   /*  264 */,    0xDDEB84F10D7F3B16L   /*  265 */,
-        0x6F2EF604A665EA04L   /*  266 */,    0x4A8E0F0FF0E0DFB3L   /*  267 */,
-        0xA5EDEEF83DBCBA51L   /*  268 */,    0xFC4F0A2A0EA4371EL   /*  269 */,
-        0xE83E1DA85CB38429L   /*  270 */,    0xDC8FF882BA1B1CE2L   /*  271 */,
-        0xCD45505E8353E80DL   /*  272 */,    0x18D19A00D4DB0717L   /*  273 */,
-        0x34A0CFEDA5F38101L   /*  274 */,    0x0BE77E518887CAF2L   /*  275 */,
-        0x1E341438B3C45136L   /*  276 */,    0xE05797F49089CCF9L   /*  277 */,
-        0xFFD23F9DF2591D14L   /*  278 */,    0x543DDA228595C5CDL   /*  279 */,
-        0x661F81FD99052A33L   /*  280 */,    0x8736E641DB0F7B76L   /*  281 */,
-        0x15227725418E5307L   /*  282 */,    0xE25F7F46162EB2FAL   /*  283 */,
-        0x48A8B2126C13D9FEL   /*  284 */,    0xAFDC541792E76EEAL   /*  285 */,
-        0x03D912BFC6D1898FL   /*  286 */,    0x31B1AAFA1B83F51BL   /*  287 */,
-        0xF1AC2796E42AB7D9L   /*  288 */,    0x40A3A7D7FCD2EBACL   /*  289 */,
-        0x1056136D0AFBBCC5L   /*  290 */,    0x7889E1DD9A6D0C85L   /*  291 */,
-        0xD33525782A7974AAL   /*  292 */,    0xA7E25D09078AC09BL   /*  293 */,
-        0xBD4138B3EAC6EDD0L   /*  294 */,    0x920ABFBE71EB9E70L   /*  295 */,
-        0xA2A5D0F54FC2625CL   /*  296 */,    0xC054E36B0B1290A3L   /*  297 */,
-        0xF6DD59FF62FE932BL   /*  298 */,    0x3537354511A8AC7DL   /*  299 */,
-        0xCA845E9172FADCD4L   /*  300 */,    0x84F82B60329D20DCL   /*  301 */,
-        0x79C62CE1CD672F18L   /*  302 */,    0x8B09A2ADD124642CL   /*  303 */,
-        0xD0C1E96A19D9E726L   /*  304 */,    0x5A786A9B4BA9500CL   /*  305 */,
-        0x0E020336634C43F3L   /*  306 */,    0xC17B474AEB66D822L   /*  307 */,
-        0x6A731AE3EC9BAAC2L   /*  308 */,    0x8226667AE0840258L   /*  309 */,
-        0x67D4567691CAECA5L   /*  310 */,    0x1D94155C4875ADB5L   /*  311 */,
-        0x6D00FD985B813FDFL   /*  312 */,    0x51286EFCB774CD06L   /*  313 */,
-        0x5E8834471FA744AFL   /*  314 */,    0xF72CA0AEE761AE2EL   /*  315 */,
-        0xBE40E4CDAEE8E09AL   /*  316 */,    0xE9970BBB5118F665L   /*  317 */,
-        0x726E4BEB33DF1964L   /*  318 */,    0x703B000729199762L   /*  319 */,
-        0x4631D816F5EF30A7L   /*  320 */,    0xB880B5B51504A6BEL   /*  321 */,
-        0x641793C37ED84B6CL   /*  322 */,    0x7B21ED77F6E97D96L   /*  323 */,
-        0x776306312EF96B73L   /*  324 */,    0xAE528948E86FF3F4L   /*  325 */,
-        0x53DBD7F286A3F8F8L   /*  326 */,    0x16CADCE74CFC1063L   /*  327 */,
-        0x005C19BDFA52C6DDL   /*  328 */,    0x68868F5D64D46AD3L   /*  329 */,
-        0x3A9D512CCF1E186AL   /*  330 */,    0x367E62C2385660AEL   /*  331 */,
-        0xE359E7EA77DCB1D7L   /*  332 */,    0x526C0773749ABE6EL   /*  333 */,
-        0x735AE5F9D09F734BL   /*  334 */,    0x493FC7CC8A558BA8L   /*  335 */,
-        0xB0B9C1533041AB45L   /*  336 */,    0x321958BA470A59BDL   /*  337 */,
-        0x852DB00B5F46C393L   /*  338 */,    0x91209B2BD336B0E5L   /*  339 */,
-        0x6E604F7D659EF19FL   /*  340 */,    0xB99A8AE2782CCB24L   /*  341 */,
-        0xCCF52AB6C814C4C7L   /*  342 */,    0x4727D9AFBE11727BL   /*  343 */,
-        0x7E950D0C0121B34DL   /*  344 */,    0x756F435670AD471FL   /*  345 */,
-        0xF5ADD442615A6849L   /*  346 */,    0x4E87E09980B9957AL   /*  347 */,
-        0x2ACFA1DF50AEE355L   /*  348 */,    0xD898263AFD2FD556L   /*  349 */,
-        0xC8F4924DD80C8FD6L   /*  350 */,    0xCF99CA3D754A173AL   /*  351 */,
-        0xFE477BACAF91BF3CL   /*  352 */,    0xED5371F6D690C12DL   /*  353 */,
-        0x831A5C285E687094L   /*  354 */,    0xC5D3C90A3708A0A4L   /*  355 */,
-        0x0F7F903717D06580L   /*  356 */,    0x19F9BB13B8FDF27FL   /*  357 */,
-        0xB1BD6F1B4D502843L   /*  358 */,    0x1C761BA38FFF4012L   /*  359 */,
-        0x0D1530C4E2E21F3BL   /*  360 */,    0x8943CE69A7372C8AL   /*  361 */,
-        0xE5184E11FEB5CE66L   /*  362 */,    0x618BDB80BD736621L   /*  363 */,
-        0x7D29BAD68B574D0BL   /*  364 */,    0x81BB613E25E6FE5BL   /*  365 */,
-        0x071C9C10BC07913FL   /*  366 */,    0xC7BEEB7909AC2D97L   /*  367 */,
-        0xC3E58D353BC5D757L   /*  368 */,    0xEB017892F38F61E8L   /*  369 */,
-        0xD4EFFB9C9B1CC21AL   /*  370 */,    0x99727D26F494F7ABL   /*  371 */,
-        0xA3E063A2956B3E03L   /*  372 */,    0x9D4A8B9A4AA09C30L   /*  373 */,
-        0x3F6AB7D500090FB4L   /*  374 */,    0x9CC0F2A057268AC0L   /*  375 */,
-        0x3DEE9D2DEDBF42D1L   /*  376 */,    0x330F49C87960A972L   /*  377 */,
-        0xC6B2720287421B41L   /*  378 */,    0x0AC59EC07C00369CL   /*  379 */,
-        0xEF4EAC49CB353425L   /*  380 */,    0xF450244EEF0129D8L   /*  381 */,
-        0x8ACC46E5CAF4DEB6L   /*  382 */,    0x2FFEAB63989263F7L   /*  383 */,
-        0x8F7CB9FE5D7A4578L   /*  384 */,    0x5BD8F7644E634635L   /*  385 */,
-        0x427A7315BF2DC900L   /*  386 */,    0x17D0C4AA2125261CL   /*  387 */,
-        0x3992486C93518E50L   /*  388 */,    0xB4CBFEE0A2D7D4C3L   /*  389 */,
-        0x7C75D6202C5DDD8DL   /*  390 */,    0xDBC295D8E35B6C61L   /*  391 */,
-        0x60B369D302032B19L   /*  392 */,    0xCE42685FDCE44132L   /*  393 */,
-        0x06F3DDB9DDF65610L   /*  394 */,    0x8EA4D21DB5E148F0L   /*  395 */,
-        0x20B0FCE62FCD496FL   /*  396 */,    0x2C1B912358B0EE31L   /*  397 */,
-        0xB28317B818F5A308L   /*  398 */,    0xA89C1E189CA6D2CFL   /*  399 */,
-        0x0C6B18576AAADBC8L   /*  400 */,    0xB65DEAA91299FAE3L   /*  401 */,
-        0xFB2B794B7F1027E7L   /*  402 */,    0x04E4317F443B5BEBL   /*  403 */,
-        0x4B852D325939D0A6L   /*  404 */,    0xD5AE6BEEFB207FFCL   /*  405 */,
-        0x309682B281C7D374L   /*  406 */,    0xBAE309A194C3B475L   /*  407 */,
-        0x8CC3F97B13B49F05L   /*  408 */,    0x98A9422FF8293967L   /*  409 */,
-        0x244B16B01076FF7CL   /*  410 */,    0xF8BF571C663D67EEL   /*  411 */,
-        0x1F0D6758EEE30DA1L   /*  412 */,    0xC9B611D97ADEB9B7L   /*  413 */,
-        0xB7AFD5887B6C57A2L   /*  414 */,    0x6290AE846B984FE1L   /*  415 */,
-        0x94DF4CDEACC1A5FDL   /*  416 */,    0x058A5BD1C5483AFFL   /*  417 */,
-        0x63166CC142BA3C37L   /*  418 */,    0x8DB8526EB2F76F40L   /*  419 */,
-        0xE10880036F0D6D4EL   /*  420 */,    0x9E0523C9971D311DL   /*  421 */,
-        0x45EC2824CC7CD691L   /*  422 */,    0x575B8359E62382C9L   /*  423 */,
-        0xFA9E400DC4889995L   /*  424 */,    0xD1823ECB45721568L   /*  425 */,
-        0xDAFD983B8206082FL   /*  426 */,    0xAA7D29082386A8CBL   /*  427 */,
-        0x269FCD4403B87588L   /*  428 */,    0x1B91F5F728BDD1E0L   /*  429 */,
-        0xE4669F39040201F6L   /*  430 */,    0x7A1D7C218CF04ADEL   /*  431 */,
-        0x65623C29D79CE5CEL   /*  432 */,    0x2368449096C00BB1L   /*  433 */,
-        0xAB9BF1879DA503BAL   /*  434 */,    0xBC23ECB1A458058EL   /*  435 */,
-        0x9A58DF01BB401ECCL   /*  436 */,    0xA070E868A85F143DL   /*  437 */,
-        0x4FF188307DF2239EL   /*  438 */,    0x14D565B41A641183L   /*  439 */,
-        0xEE13337452701602L   /*  440 */,    0x950E3DCF3F285E09L   /*  441 */,
-        0x59930254B9C80953L   /*  442 */,    0x3BF299408930DA6DL   /*  443 */,
-        0xA955943F53691387L   /*  444 */,    0xA15EDECAA9CB8784L   /*  445 */,
-        0x29142127352BE9A0L   /*  446 */,    0x76F0371FFF4E7AFBL   /*  447 */,
-        0x0239F450274F2228L   /*  448 */,    0xBB073AF01D5E868BL   /*  449 */,
-        0xBFC80571C10E96C1L   /*  450 */,    0xD267088568222E23L   /*  451 */,
-        0x9671A3D48E80B5B0L   /*  452 */,    0x55B5D38AE193BB81L   /*  453 */,
-        0x693AE2D0A18B04B8L   /*  454 */,    0x5C48B4ECADD5335FL   /*  455 */,
-        0xFD743B194916A1CAL   /*  456 */,    0x2577018134BE98C4L   /*  457 */,
-        0xE77987E83C54A4ADL   /*  458 */,    0x28E11014DA33E1B9L   /*  459 */,
-        0x270CC59E226AA213L   /*  460 */,    0x71495F756D1A5F60L   /*  461 */,
-        0x9BE853FB60AFEF77L   /*  462 */,    0xADC786A7F7443DBFL   /*  463 */,
-        0x0904456173B29A82L   /*  464 */,    0x58BC7A66C232BD5EL   /*  465 */,
-        0xF306558C673AC8B2L   /*  466 */,    0x41F639C6B6C9772AL   /*  467 */,
-        0x216DEFE99FDA35DAL   /*  468 */,    0x11640CC71C7BE615L   /*  469 */,
-        0x93C43694565C5527L   /*  470 */,    0xEA038E6246777839L   /*  471 */,
-        0xF9ABF3CE5A3E2469L   /*  472 */,    0x741E768D0FD312D2L   /*  473 */,
-        0x0144B883CED652C6L   /*  474 */,    0xC20B5A5BA33F8552L   /*  475 */,
-        0x1AE69633C3435A9DL   /*  476 */,    0x97A28CA4088CFDECL   /*  477 */,
-        0x8824A43C1E96F420L   /*  478 */,    0x37612FA66EEEA746L   /*  479 */,
-        0x6B4CB165F9CF0E5AL   /*  480 */,    0x43AA1C06A0ABFB4AL   /*  481 */,
-        0x7F4DC26FF162796BL   /*  482 */,    0x6CBACC8E54ED9B0FL   /*  483 */,
-        0xA6B7FFEFD2BB253EL   /*  484 */,    0x2E25BC95B0A29D4FL   /*  485 */,
-        0x86D6A58BDEF1388CL   /*  486 */,    0xDED74AC576B6F054L   /*  487 */,
-        0x8030BDBC2B45805DL   /*  488 */,    0x3C81AF70E94D9289L   /*  489 */,
-        0x3EFF6DDA9E3100DBL   /*  490 */,    0xB38DC39FDFCC8847L   /*  491 */,
-        0x123885528D17B87EL   /*  492 */,    0xF2DA0ED240B1B642L   /*  493 */,
-        0x44CEFADCD54BF9A9L   /*  494 */,    0x1312200E433C7EE6L   /*  495 */,
-        0x9FFCC84F3A78C748L   /*  496 */,    0xF0CD1F72248576BBL   /*  497 */,
-        0xEC6974053638CFE4L   /*  498 */,    0x2BA7B67C0CEC4E4CL   /*  499 */,
-        0xAC2F4DF3E5CE32EDL   /*  500 */,    0xCB33D14326EA4C11L   /*  501 */,
-        0xA4E9044CC77E58BCL   /*  502 */,    0x5F513293D934FCEFL   /*  503 */,
-        0x5DC9645506E55444L   /*  504 */,    0x50DE418F317DE40AL   /*  505 */,
-        0x388CB31A69DDE259L   /*  506 */,    0x2DB4A83455820A86L   /*  507 */,
-        0x9010A91E84711AE9L   /*  508 */,    0x4DF7F0B7B1498371L   /*  509 */,
-        0xD62A2EABC0977179L   /*  510 */,    0x22FAC097AA8D5C0EL   /*  511 */,
-    };
-
-    private static final long[] t3 = {
-        0xF49FCC2FF1DAF39BL   /*  512 */,    0x487FD5C66FF29281L   /*  513 */,
-        0xE8A30667FCDCA83FL   /*  514 */,    0x2C9B4BE3D2FCCE63L   /*  515 */,
-        0xDA3FF74B93FBBBC2L   /*  516 */,    0x2FA165D2FE70BA66L   /*  517 */,
-        0xA103E279970E93D4L   /*  518 */,    0xBECDEC77B0E45E71L   /*  519 */,
-        0xCFB41E723985E497L   /*  520 */,    0xB70AAA025EF75017L   /*  521 */,
-        0xD42309F03840B8E0L   /*  522 */,    0x8EFC1AD035898579L   /*  523 */,
-        0x96C6920BE2B2ABC5L   /*  524 */,    0x66AF4163375A9172L   /*  525 */,
-        0x2174ABDCCA7127FBL   /*  526 */,    0xB33CCEA64A72FF41L   /*  527 */,
-        0xF04A4933083066A5L   /*  528 */,    0x8D970ACDD7289AF5L   /*  529 */,
-        0x8F96E8E031C8C25EL   /*  530 */,    0xF3FEC02276875D47L   /*  531 */,
-        0xEC7BF310056190DDL   /*  532 */,    0xF5ADB0AEBB0F1491L   /*  533 */,
-        0x9B50F8850FD58892L   /*  534 */,    0x4975488358B74DE8L   /*  535 */,
-        0xA3354FF691531C61L   /*  536 */,    0x0702BBE481D2C6EEL   /*  537 */,
-        0x89FB24057DEDED98L   /*  538 */,    0xAC3075138596E902L   /*  539 */,
-        0x1D2D3580172772EDL   /*  540 */,    0xEB738FC28E6BC30DL   /*  541 */,
-        0x5854EF8F63044326L   /*  542 */,    0x9E5C52325ADD3BBEL   /*  543 */,
-        0x90AA53CF325C4623L   /*  544 */,    0xC1D24D51349DD067L   /*  545 */,
-        0x2051CFEEA69EA624L   /*  546 */,    0x13220F0A862E7E4FL   /*  547 */,
-        0xCE39399404E04864L   /*  548 */,    0xD9C42CA47086FCB7L   /*  549 */,
-        0x685AD2238A03E7CCL   /*  550 */,    0x066484B2AB2FF1DBL   /*  551 */,
-        0xFE9D5D70EFBF79ECL   /*  552 */,    0x5B13B9DD9C481854L   /*  553 */,
-        0x15F0D475ED1509ADL   /*  554 */,    0x0BEBCD060EC79851L   /*  555 */,
-        0xD58C6791183AB7F8L   /*  556 */,    0xD1187C5052F3EEE4L   /*  557 */,
-        0xC95D1192E54E82FFL   /*  558 */,    0x86EEA14CB9AC6CA2L   /*  559 */,
-        0x3485BEB153677D5DL   /*  560 */,    0xDD191D781F8C492AL   /*  561 */,
-        0xF60866BAA784EBF9L   /*  562 */,    0x518F643BA2D08C74L   /*  563 */,
-        0x8852E956E1087C22L   /*  564 */,    0xA768CB8DC410AE8DL   /*  565 */,
-        0x38047726BFEC8E1AL   /*  566 */,    0xA67738B4CD3B45AAL   /*  567 */,
-        0xAD16691CEC0DDE19L   /*  568 */,    0xC6D4319380462E07L   /*  569 */,
-        0xC5A5876D0BA61938L   /*  570 */,    0x16B9FA1FA58FD840L   /*  571 */,
-        0x188AB1173CA74F18L   /*  572 */,    0xABDA2F98C99C021FL   /*  573 */,
-        0x3E0580AB134AE816L   /*  574 */,    0x5F3B05B773645ABBL   /*  575 */,
-        0x2501A2BE5575F2F6L   /*  576 */,    0x1B2F74004E7E8BA9L   /*  577 */,
-        0x1CD7580371E8D953L   /*  578 */,    0x7F6ED89562764E30L   /*  579 */,
-        0xB15926FF596F003DL   /*  580 */,    0x9F65293DA8C5D6B9L   /*  581 */,
-        0x6ECEF04DD690F84CL   /*  582 */,    0x4782275FFF33AF88L   /*  583 */,
-        0xE41433083F820801L   /*  584 */,    0xFD0DFE409A1AF9B5L   /*  585 */,
-        0x4325A3342CDB396BL   /*  586 */,    0x8AE77E62B301B252L   /*  587 */,
-        0xC36F9E9F6655615AL   /*  588 */,    0x85455A2D92D32C09L   /*  589 */,
-        0xF2C7DEA949477485L   /*  590 */,    0x63CFB4C133A39EBAL   /*  591 */,
-        0x83B040CC6EBC5462L   /*  592 */,    0x3B9454C8FDB326B0L   /*  593 */,
-        0x56F56A9E87FFD78CL   /*  594 */,    0x2DC2940D99F42BC6L   /*  595 */,
-        0x98F7DF096B096E2DL   /*  596 */,    0x19A6E01E3AD852BFL   /*  597 */,
-        0x42A99CCBDBD4B40BL   /*  598 */,    0xA59998AF45E9C559L   /*  599 */,
-        0x366295E807D93186L   /*  600 */,    0x6B48181BFAA1F773L   /*  601 */,
-        0x1FEC57E2157A0A1DL   /*  602 */,    0x4667446AF6201AD5L   /*  603 */,
-        0xE615EBCACFB0F075L   /*  604 */,    0xB8F31F4F68290778L   /*  605 */,
-        0x22713ED6CE22D11EL   /*  606 */,    0x3057C1A72EC3C93BL   /*  607 */,
-        0xCB46ACC37C3F1F2FL   /*  608 */,    0xDBB893FD02AAF50EL   /*  609 */,
-        0x331FD92E600B9FCFL   /*  610 */,    0xA498F96148EA3AD6L   /*  611 */,
-        0xA8D8426E8B6A83EAL   /*  612 */,    0xA089B274B7735CDCL   /*  613 */,
-        0x87F6B3731E524A11L   /*  614 */,    0x118808E5CBC96749L   /*  615 */,
-        0x9906E4C7B19BD394L   /*  616 */,    0xAFED7F7E9B24A20CL   /*  617 */,
-        0x6509EADEEB3644A7L   /*  618 */,    0x6C1EF1D3E8EF0EDEL   /*  619 */,
-        0xB9C97D43E9798FB4L   /*  620 */,    0xA2F2D784740C28A3L   /*  621 */,
-        0x7B8496476197566FL   /*  622 */,    0x7A5BE3E6B65F069DL   /*  623 */,
-        0xF96330ED78BE6F10L   /*  624 */,    0xEEE60DE77A076A15L   /*  625 */,
-        0x2B4BEE4AA08B9BD0L   /*  626 */,    0x6A56A63EC7B8894EL   /*  627 */,
-        0x02121359BA34FEF4L   /*  628 */,    0x4CBF99F8283703FCL   /*  629 */,
-        0x398071350CAF30C8L   /*  630 */,    0xD0A77A89F017687AL   /*  631 */,
-        0xF1C1A9EB9E423569L   /*  632 */,    0x8C7976282DEE8199L   /*  633 */,
-        0x5D1737A5DD1F7ABDL   /*  634 */,    0x4F53433C09A9FA80L   /*  635 */,
-        0xFA8B0C53DF7CA1D9L   /*  636 */,    0x3FD9DCBC886CCB77L   /*  637 */,
-        0xC040917CA91B4720L   /*  638 */,    0x7DD00142F9D1DCDFL   /*  639 */,
-        0x8476FC1D4F387B58L   /*  640 */,    0x23F8E7C5F3316503L   /*  641 */,
-        0x032A2244E7E37339L   /*  642 */,    0x5C87A5D750F5A74BL   /*  643 */,
-        0x082B4CC43698992EL   /*  644 */,    0xDF917BECB858F63CL   /*  645 */,
-        0x3270B8FC5BF86DDAL   /*  646 */,    0x10AE72BB29B5DD76L   /*  647 */,
-        0x576AC94E7700362BL   /*  648 */,    0x1AD112DAC61EFB8FL   /*  649 */,
-        0x691BC30EC5FAA427L   /*  650 */,    0xFF246311CC327143L   /*  651 */,
-        0x3142368E30E53206L   /*  652 */,    0x71380E31E02CA396L   /*  653 */,
-        0x958D5C960AAD76F1L   /*  654 */,    0xF8D6F430C16DA536L   /*  655 */,
-        0xC8FFD13F1BE7E1D2L   /*  656 */,    0x7578AE66004DDBE1L   /*  657 */,
-        0x05833F01067BE646L   /*  658 */,    0xBB34B5AD3BFE586DL   /*  659 */,
-        0x095F34C9A12B97F0L   /*  660 */,    0x247AB64525D60CA8L   /*  661 */,
-        0xDCDBC6F3017477D1L   /*  662 */,    0x4A2E14D4DECAD24DL   /*  663 */,
-        0xBDB5E6D9BE0A1EEBL   /*  664 */,    0x2A7E70F7794301ABL   /*  665 */,
-        0xDEF42D8A270540FDL   /*  666 */,    0x01078EC0A34C22C1L   /*  667 */,
-        0xE5DE511AF4C16387L   /*  668 */,    0x7EBB3A52BD9A330AL   /*  669 */,
-        0x77697857AA7D6435L   /*  670 */,    0x004E831603AE4C32L   /*  671 */,
-        0xE7A21020AD78E312L   /*  672 */,    0x9D41A70C6AB420F2L   /*  673 */,
-        0x28E06C18EA1141E6L   /*  674 */,    0xD2B28CBD984F6B28L   /*  675 */,
-        0x26B75F6C446E9D83L   /*  676 */,    0xBA47568C4D418D7FL   /*  677 */,
-        0xD80BADBFE6183D8EL   /*  678 */,    0x0E206D7F5F166044L   /*  679 */,
-        0xE258A43911CBCA3EL   /*  680 */,    0x723A1746B21DC0BCL   /*  681 */,
-        0xC7CAA854F5D7CDD3L   /*  682 */,    0x7CAC32883D261D9CL   /*  683 */,
-        0x7690C26423BA942CL   /*  684 */,    0x17E55524478042B8L   /*  685 */,
-        0xE0BE477656A2389FL   /*  686 */,    0x4D289B5E67AB2DA0L   /*  687 */,
-        0x44862B9C8FBBFD31L   /*  688 */,    0xB47CC8049D141365L   /*  689 */,
-        0x822C1B362B91C793L   /*  690 */,    0x4EB14655FB13DFD8L   /*  691 */,
-        0x1ECBBA0714E2A97BL   /*  692 */,    0x6143459D5CDE5F14L   /*  693 */,
-        0x53A8FBF1D5F0AC89L   /*  694 */,    0x97EA04D81C5E5B00L   /*  695 */,
-        0x622181A8D4FDB3F3L   /*  696 */,    0xE9BCD341572A1208L   /*  697 */,
-        0x1411258643CCE58AL   /*  698 */,    0x9144C5FEA4C6E0A4L   /*  699 */,
-        0x0D33D06565CF620FL   /*  700 */,    0x54A48D489F219CA1L   /*  701 */,
-        0xC43E5EAC6D63C821L   /*  702 */,    0xA9728B3A72770DAFL   /*  703 */,
-        0xD7934E7B20DF87EFL   /*  704 */,    0xE35503B61A3E86E5L   /*  705 */,
-        0xCAE321FBC819D504L   /*  706 */,    0x129A50B3AC60BFA6L   /*  707 */,
-        0xCD5E68EA7E9FB6C3L   /*  708 */,    0xB01C90199483B1C7L   /*  709 */,
-        0x3DE93CD5C295376CL   /*  710 */,    0xAED52EDF2AB9AD13L   /*  711 */,
-        0x2E60F512C0A07884L   /*  712 */,    0xBC3D86A3E36210C9L   /*  713 */,
-        0x35269D9B163951CEL   /*  714 */,    0x0C7D6E2AD0CDB5FAL   /*  715 */,
-        0x59E86297D87F5733L   /*  716 */,    0x298EF221898DB0E7L   /*  717 */,
-        0x55000029D1A5AA7EL   /*  718 */,    0x8BC08AE1B5061B45L   /*  719 */,
-        0xC2C31C2B6C92703AL   /*  720 */,    0x94CC596BAF25EF42L   /*  721 */,
-        0x0A1D73DB22540456L   /*  722 */,    0x04B6A0F9D9C4179AL   /*  723 */,
-        0xEFFDAFA2AE3D3C60L   /*  724 */,    0xF7C8075BB49496C4L   /*  725 */,
-        0x9CC5C7141D1CD4E3L   /*  726 */,    0x78BD1638218E5534L   /*  727 */,
-        0xB2F11568F850246AL   /*  728 */,    0xEDFABCFA9502BC29L   /*  729 */,
-        0x796CE5F2DA23051BL   /*  730 */,    0xAAE128B0DC93537CL   /*  731 */,
-        0x3A493DA0EE4B29AEL   /*  732 */,    0xB5DF6B2C416895D7L   /*  733 */,
-        0xFCABBD25122D7F37L   /*  734 */,    0x70810B58105DC4B1L   /*  735 */,
-        0xE10FDD37F7882A90L   /*  736 */,    0x524DCAB5518A3F5CL   /*  737 */,
-        0x3C9E85878451255BL   /*  738 */,    0x4029828119BD34E2L   /*  739 */,
-        0x74A05B6F5D3CECCBL   /*  740 */,    0xB610021542E13ECAL   /*  741 */,
-        0x0FF979D12F59E2ACL   /*  742 */,    0x6037DA27E4F9CC50L   /*  743 */,
-        0x5E92975A0DF1847DL   /*  744 */,    0xD66DE190D3E623FEL   /*  745 */,
-        0x5032D6B87B568048L   /*  746 */,    0x9A36B7CE8235216EL   /*  747 */,
-        0x80272A7A24F64B4AL   /*  748 */,    0x93EFED8B8C6916F7L   /*  749 */,
-        0x37DDBFF44CCE1555L   /*  750 */,    0x4B95DB5D4B99BD25L   /*  751 */,
-        0x92D3FDA169812FC0L   /*  752 */,    0xFB1A4A9A90660BB6L   /*  753 */,
-        0x730C196946A4B9B2L   /*  754 */,    0x81E289AA7F49DA68L   /*  755 */,
-        0x64669A0F83B1A05FL   /*  756 */,    0x27B3FF7D9644F48BL   /*  757 */,
-        0xCC6B615C8DB675B3L   /*  758 */,    0x674F20B9BCEBBE95L   /*  759 */,
-        0x6F31238275655982L   /*  760 */,    0x5AE488713E45CF05L   /*  761 */,
-        0xBF619F9954C21157L   /*  762 */,    0xEABAC46040A8EAE9L   /*  763 */,
-        0x454C6FE9F2C0C1CDL   /*  764 */,    0x419CF6496412691CL   /*  765 */,
-        0xD3DC3BEF265B0F70L   /*  766 */,    0x6D0E60F5C3578A9EL   /*  767 */,
-    };
-
-    private static final long[] t4 = {
-        0x5B0E608526323C55L   /*  768 */,    0x1A46C1A9FA1B59F5L   /*  769 */,
-        0xA9E245A17C4C8FFAL   /*  770 */,    0x65CA5159DB2955D7L   /*  771 */,
-        0x05DB0A76CE35AFC2L   /*  772 */,    0x81EAC77EA9113D45L   /*  773 */,
-        0x528EF88AB6AC0A0DL   /*  774 */,    0xA09EA253597BE3FFL   /*  775 */,
-        0x430DDFB3AC48CD56L   /*  776 */,    0xC4B3A67AF45CE46FL   /*  777 */,
-        0x4ECECFD8FBE2D05EL   /*  778 */,    0x3EF56F10B39935F0L   /*  779 */,
-        0x0B22D6829CD619C6L   /*  780 */,    0x17FD460A74DF2069L   /*  781 */,
-        0x6CF8CC8E8510ED40L   /*  782 */,    0xD6C824BF3A6ECAA7L   /*  783 */,
-        0x61243D581A817049L   /*  784 */,    0x048BACB6BBC163A2L   /*  785 */,
-        0xD9A38AC27D44CC32L   /*  786 */,    0x7FDDFF5BAAF410ABL   /*  787 */,
-        0xAD6D495AA804824BL   /*  788 */,    0xE1A6A74F2D8C9F94L   /*  789 */,
-        0xD4F7851235DEE8E3L   /*  790 */,    0xFD4B7F886540D893L   /*  791 */,
-        0x247C20042AA4BFDAL   /*  792 */,    0x096EA1C517D1327CL   /*  793 */,
-        0xD56966B4361A6685L   /*  794 */,    0x277DA5C31221057DL   /*  795 */,
-        0x94D59893A43ACFF7L   /*  796 */,    0x64F0C51CCDC02281L   /*  797 */,
-        0x3D33BCC4FF6189DBL   /*  798 */,    0xE005CB184CE66AF1L   /*  799 */,
-        0xFF5CCD1D1DB99BEAL   /*  800 */,    0xB0B854A7FE42980FL   /*  801 */,
-        0x7BD46A6A718D4B9FL   /*  802 */,    0xD10FA8CC22A5FD8CL   /*  803 */,
-        0xD31484952BE4BD31L   /*  804 */,    0xC7FA975FCB243847L   /*  805 */,
-        0x4886ED1E5846C407L   /*  806 */,    0x28CDDB791EB70B04L   /*  807 */,
-        0xC2B00BE2F573417FL   /*  808 */,    0x5C9590452180F877L   /*  809 */,
-        0x7A6BDDFFF370EB00L   /*  810 */,    0xCE509E38D6D9D6A4L   /*  811 */,
-        0xEBEB0F00647FA702L   /*  812 */,    0x1DCC06CF76606F06L   /*  813 */,
-        0xE4D9F28BA286FF0AL   /*  814 */,    0xD85A305DC918C262L   /*  815 */,
-        0x475B1D8732225F54L   /*  816 */,    0x2D4FB51668CCB5FEL   /*  817 */,
-        0xA679B9D9D72BBA20L   /*  818 */,    0x53841C0D912D43A5L   /*  819 */,
-        0x3B7EAA48BF12A4E8L   /*  820 */,    0x781E0E47F22F1DDFL   /*  821 */,
-        0xEFF20CE60AB50973L   /*  822 */,    0x20D261D19DFFB742L   /*  823 */,
-        0x16A12B03062A2E39L   /*  824 */,    0x1960EB2239650495L   /*  825 */,
-        0x251C16FED50EB8B8L   /*  826 */,    0x9AC0C330F826016EL   /*  827 */,
-        0xED152665953E7671L   /*  828 */,    0x02D63194A6369570L   /*  829 */,
-        0x5074F08394B1C987L   /*  830 */,    0x70BA598C90B25CE1L   /*  831 */,
-        0x794A15810B9742F6L   /*  832 */,    0x0D5925E9FCAF8C6CL   /*  833 */,
-        0x3067716CD868744EL   /*  834 */,    0x910AB077E8D7731BL   /*  835 */,
-        0x6A61BBDB5AC42F61L   /*  836 */,    0x93513EFBF0851567L   /*  837 */,
-        0xF494724B9E83E9D5L   /*  838 */,    0xE887E1985C09648DL   /*  839 */,
-        0x34B1D3C675370CFDL   /*  840 */,    0xDC35E433BC0D255DL   /*  841 */,
-        0xD0AAB84234131BE0L   /*  842 */,    0x08042A50B48B7EAFL   /*  843 */,
-        0x9997C4EE44A3AB35L   /*  844 */,    0x829A7B49201799D0L   /*  845 */,
-        0x263B8307B7C54441L   /*  846 */,    0x752F95F4FD6A6CA6L   /*  847 */,
-        0x927217402C08C6E5L   /*  848 */,    0x2A8AB754A795D9EEL   /*  849 */,
-        0xA442F7552F72943DL   /*  850 */,    0x2C31334E19781208L   /*  851 */,
-        0x4FA98D7CEAEE6291L   /*  852 */,    0x55C3862F665DB309L   /*  853 */,
-        0xBD0610175D53B1F3L   /*  854 */,    0x46FE6CB840413F27L   /*  855 */,
-        0x3FE03792DF0CFA59L   /*  856 */,    0xCFE700372EB85E8FL   /*  857 */,
-        0xA7BE29E7ADBCE118L   /*  858 */,    0xE544EE5CDE8431DDL   /*  859 */,
-        0x8A781B1B41F1873EL   /*  860 */,    0xA5C94C78A0D2F0E7L   /*  861 */,
-        0x39412E2877B60728L   /*  862 */,    0xA1265EF3AFC9A62CL   /*  863 */,
-        0xBCC2770C6A2506C5L   /*  864 */,    0x3AB66DD5DCE1CE12L   /*  865 */,
-        0xE65499D04A675B37L   /*  866 */,    0x7D8F523481BFD216L   /*  867 */,
-        0x0F6F64FCEC15F389L   /*  868 */,    0x74EFBE618B5B13C8L   /*  869 */,
-        0xACDC82B714273E1DL   /*  870 */,    0xDD40BFE003199D17L   /*  871 */,
-        0x37E99257E7E061F8L   /*  872 */,    0xFA52626904775AAAL   /*  873 */,
-        0x8BBBF63A463D56F9L   /*  874 */,    0xF0013F1543A26E64L   /*  875 */,
-        0xA8307E9F879EC898L   /*  876 */,    0xCC4C27A4150177CCL   /*  877 */,
-        0x1B432F2CCA1D3348L   /*  878 */,    0xDE1D1F8F9F6FA013L   /*  879 */,
-        0x606602A047A7DDD6L   /*  880 */,    0xD237AB64CC1CB2C7L   /*  881 */,
-        0x9B938E7225FCD1D3L   /*  882 */,    0xEC4E03708E0FF476L   /*  883 */,
-        0xFEB2FBDA3D03C12DL   /*  884 */,    0xAE0BCED2EE43889AL   /*  885 */,
-        0x22CB8923EBFB4F43L   /*  886 */,    0x69360D013CF7396DL   /*  887 */,
-        0x855E3602D2D4E022L   /*  888 */,    0x073805BAD01F784CL   /*  889 */,
-        0x33E17A133852F546L   /*  890 */,    0xDF4874058AC7B638L   /*  891 */,
-        0xBA92B29C678AA14AL   /*  892 */,    0x0CE89FC76CFAADCDL   /*  893 */,
-        0x5F9D4E0908339E34L   /*  894 */,    0xF1AFE9291F5923B9L   /*  895 */,
-        0x6E3480F60F4A265FL   /*  896 */,    0xEEBF3A2AB29B841CL   /*  897 */,
-        0xE21938A88F91B4ADL   /*  898 */,    0x57DFEFF845C6D3C3L   /*  899 */,
-        0x2F006B0BF62CAAF2L   /*  900 */,    0x62F479EF6F75EE78L   /*  901 */,
-        0x11A55AD41C8916A9L   /*  902 */,    0xF229D29084FED453L   /*  903 */,
-        0x42F1C27B16B000E6L   /*  904 */,    0x2B1F76749823C074L   /*  905 */,
-        0x4B76ECA3C2745360L   /*  906 */,    0x8C98F463B91691BDL   /*  907 */,
-        0x14BCC93CF1ADE66AL   /*  908 */,    0x8885213E6D458397L   /*  909 */,
-        0x8E177DF0274D4711L   /*  910 */,    0xB49B73B5503F2951L   /*  911 */,
-        0x10168168C3F96B6BL   /*  912 */,    0x0E3D963B63CAB0AEL   /*  913 */,
-        0x8DFC4B5655A1DB14L   /*  914 */,    0xF789F1356E14DE5CL   /*  915 */,
-        0x683E68AF4E51DAC1L   /*  916 */,    0xC9A84F9D8D4B0FD9L   /*  917 */,
-        0x3691E03F52A0F9D1L   /*  918 */,    0x5ED86E46E1878E80L   /*  919 */,
-        0x3C711A0E99D07150L   /*  920 */,    0x5A0865B20C4E9310L   /*  921 */,
-        0x56FBFC1FE4F0682EL   /*  922 */,    0xEA8D5DE3105EDF9BL   /*  923 */,
-        0x71ABFDB12379187AL   /*  924 */,    0x2EB99DE1BEE77B9CL   /*  925 */,
-        0x21ECC0EA33CF4523L   /*  926 */,    0x59A4D7521805C7A1L   /*  927 */,
-        0x3896F5EB56AE7C72L   /*  928 */,    0xAA638F3DB18F75DCL   /*  929 */,
-        0x9F39358DABE9808EL   /*  930 */,    0xB7DEFA91C00B72ACL   /*  931 */,
-        0x6B5541FD62492D92L   /*  932 */,    0x6DC6DEE8F92E4D5BL   /*  933 */,
-        0x353F57ABC4BEEA7EL   /*  934 */,    0x735769D6DA5690CEL   /*  935 */,
-        0x0A234AA642391484L   /*  936 */,    0xF6F9508028F80D9DL   /*  937 */,
-        0xB8E319A27AB3F215L   /*  938 */,    0x31AD9C1151341A4DL   /*  939 */,
-        0x773C22A57BEF5805L   /*  940 */,    0x45C7561A07968633L   /*  941 */,
-        0xF913DA9E249DBE36L   /*  942 */,    0xDA652D9B78A64C68L   /*  943 */,
-        0x4C27A97F3BC334EFL   /*  944 */,    0x76621220E66B17F4L   /*  945 */,
-        0x967743899ACD7D0BL   /*  946 */,    0xF3EE5BCAE0ED6782L   /*  947 */,
-        0x409F753600C879FCL   /*  948 */,    0x06D09A39B5926DB6L   /*  949 */,
-        0x6F83AEB0317AC588L   /*  950 */,    0x01E6CA4A86381F21L   /*  951 */,
-        0x66FF3462D19F3025L   /*  952 */,    0x72207C24DDFD3BFBL   /*  953 */,
-        0x4AF6B6D3E2ECE2EBL   /*  954 */,    0x9C994DBEC7EA08DEL   /*  955 */,
-        0x49ACE597B09A8BC4L   /*  956 */,    0xB38C4766CF0797BAL   /*  957 */,
-        0x131B9373C57C2A75L   /*  958 */,    0xB1822CCE61931E58L   /*  959 */,
-        0x9D7555B909BA1C0CL   /*  960 */,    0x127FAFDD937D11D2L   /*  961 */,
-        0x29DA3BADC66D92E4L   /*  962 */,    0xA2C1D57154C2ECBCL   /*  963 */,
-        0x58C5134D82F6FE24L   /*  964 */,    0x1C3AE3515B62274FL   /*  965 */,
-        0xE907C82E01CB8126L   /*  966 */,    0xF8ED091913E37FCBL   /*  967 */,
-        0x3249D8F9C80046C9L   /*  968 */,    0x80CF9BEDE388FB63L   /*  969 */,
-        0x1881539A116CF19EL   /*  970 */,    0x5103F3F76BD52457L   /*  971 */,
-        0x15B7E6F5AE47F7A8L   /*  972 */,    0xDBD7C6DED47E9CCFL   /*  973 */,
-        0x44E55C410228BB1AL   /*  974 */,    0xB647D4255EDB4E99L   /*  975 */,
-        0x5D11882BB8AAFC30L   /*  976 */,    0xF5098BBB29D3212AL   /*  977 */,
-        0x8FB5EA14E90296B3L   /*  978 */,    0x677B942157DD025AL   /*  979 */,
-        0xFB58E7C0A390ACB5L   /*  980 */,    0x89D3674C83BD4A01L   /*  981 */,
-        0x9E2DA4DF4BF3B93BL   /*  982 */,    0xFCC41E328CAB4829L   /*  983 */,
-        0x03F38C96BA582C52L   /*  984 */,    0xCAD1BDBD7FD85DB2L   /*  985 */,
-        0xBBB442C16082AE83L   /*  986 */,    0xB95FE86BA5DA9AB0L   /*  987 */,
-        0xB22E04673771A93FL   /*  988 */,    0x845358C9493152D8L   /*  989 */,
-        0xBE2A488697B4541EL   /*  990 */,    0x95A2DC2DD38E6966L   /*  991 */,
-        0xC02C11AC923C852BL   /*  992 */,    0x2388B1990DF2A87BL   /*  993 */,
-        0x7C8008FA1B4F37BEL   /*  994 */,    0x1F70D0C84D54E503L   /*  995 */,
-        0x5490ADEC7ECE57D4L   /*  996 */,    0x002B3C27D9063A3AL   /*  997 */,
-        0x7EAEA3848030A2BFL   /*  998 */,    0xC602326DED2003C0L   /*  999 */,
-        0x83A7287D69A94086L   /* 1000 */,    0xC57A5FCB30F57A8AL   /* 1001 */,
-        0xB56844E479EBE779L   /* 1002 */,    0xA373B40F05DCBCE9L   /* 1003 */,
-        0xD71A786E88570EE2L   /* 1004 */,    0x879CBACDBDE8F6A0L   /* 1005 */,
-        0x976AD1BCC164A32FL   /* 1006 */,    0xAB21E25E9666D78BL   /* 1007 */,
-        0x901063AAE5E5C33CL   /* 1008 */,    0x9818B34448698D90L   /* 1009 */,
-        0xE36487AE3E1E8ABBL   /* 1010 */,    0xAFBDF931893BDCB4L   /* 1011 */,
-        0x6345A0DC5FBBD519L   /* 1012 */,    0x8628FE269B9465CAL   /* 1013 */,
-        0x1E5D01603F9C51ECL   /* 1014 */,    0x4DE44006A15049B7L   /* 1015 */,
-        0xBF6C70E5F776CBB1L   /* 1016 */,    0x411218F2EF552BEDL   /* 1017 */,
-        0xCB0C0708705A36A3L   /* 1018 */,    0xE74D14754F986044L   /* 1019 */,
-        0xCD56D9430EA8280EL   /* 1020 */,    0xC12591D7535F5065L   /* 1021 */,
-        0xC83223F1720AEF96L   /* 1022 */,    0xC3A0396F7363A51FL   /* 1023 */
-    };
-
-    private static final int    DIGEST_LENGTH = 24;
-
-    //
-    // registers
-    //
-    private long    a, b, c;
-    private long    byteCount;
-
-    //
-    // buffers
-    //
-    private byte[]  buf = new byte[8];
-    private int     bOff = 0;
-
-    private long[]  x = new long[8];
-    private int     xOff = 0;
-
-	/**
-	 * Standard constructor
-	 */
-    public TigerDigest()
-    {
-        reset();
-    }
-
-	/**
-	 * Copy constructor.  This will copy the state of the provided
-	 * message digest.
-	 */
-	public TigerDigest(TigerDigest t)
-	{
-		a = t.a;
-		b = t.b;
-		c = t.c;
-
-		System.arraycopy(t.x, 0, x, 0, t.x.length);
-		xOff = t.xOff;
-
-		System.arraycopy(t.buf, 0, buf, 0, t.buf.length);
-		bOff = t.bOff;
-
-        byteCount = t.byteCount;
-	}
-
-    public String getAlgorithmName()
-    {
-        return "Tiger";
-    }
-
-    public int getDigestSize()
-    {
-        return DIGEST_LENGTH;
-    }
-
-    private void processWord(
-        byte[]  b,
-        int     off)
-    {
-        x[xOff++] = ((long)(b[off + 7] & 0xff) << 56)
-             | ((long)(b[off + 6] & 0xff) << 48)
-             | ((long)(b[off + 5] & 0xff) << 40)
-             | ((long)(b[off + 4] & 0xff) << 32)
-             | ((long)(b[off + 3] & 0xff) << 24)
-             | ((long)(b[off + 2] & 0xff) << 16)
-             | ((long)(b[off + 1] & 0xff) << 8)
-             | ((b[off + 0] & 0xff));
-
-        if (xOff == x.length)
-        {
-            processBlock();
-        }
-
-        bOff = 0;
-    }
-
-    public void update(
-        byte in)
-    {
-        buf[bOff++] = in;
-
-        if (bOff == buf.length)
-        {
-            processWord(buf, 0);
-        }
-
-        byteCount++;
-    }
-
-    public void update(
-        byte[]  in,
-        int     inOff,
-        int     len)
-    {
-        //
-        // fill the current word
-        //
-        while ((bOff != 0) && (len > 0))
-        {
-            update(in[inOff]);
-
-            inOff++;
-            len--;
-        }
-
-        //
-        // process whole words.
-        //
-        while (len > 8)
-        {
-            processWord(in, inOff);
-
-            inOff += 8;
-            len -= 8;
-            byteCount += 8;
-        }
-
-        //
-        // load in the remainder.
-        //
-        while (len > 0)
-        {
-            update(in[inOff]);
-
-            inOff++;
-            len--;
-        }
-    }
-
-    private void roundABC(
-        long    x,
-        long    mul)
-    {
-         c ^= x ;
-         a -= t1[(int)c & 0xff] ^ t2[(int)(c >> 16) & 0xff]
-                ^ t3[(int)(c >> 32) & 0xff] ^ t4[(int)(c >> 48) & 0xff];
-         b += t4[(int)(c >> 8) & 0xff] ^ t3[(int)(c >> 24) & 0xff]
-                ^ t2[(int)(c >> 40) & 0xff] ^ t1[(int)(c >> 56) & 0xff];
-         b *= mul;
-    }
-
-    private void roundBCA(
-        long    x,
-        long    mul)
-    {
-         a ^= x ;
-         b -= t1[(int)a & 0xff] ^ t2[(int)(a >> 16) & 0xff]
-                ^ t3[(int)(a >> 32) & 0xff] ^ t4[(int)(a >> 48) & 0xff];
-         c += t4[(int)(a >> 8) & 0xff] ^ t3[(int)(a >> 24) & 0xff]
-                ^ t2[(int)(a >> 40) & 0xff] ^ t1[(int)(a >> 56) & 0xff];
-         c *= mul;
-    }
-
-    private void roundCAB(
-        long    x,
-        long    mul)
-    {
-         b ^= x ;
-         c -= t1[(int)b & 0xff] ^ t2[(int)(b >> 16) & 0xff]
-                ^ t3[(int)(b >> 32) & 0xff] ^ t4[(int)(b >> 48) & 0xff];
-         a += t4[(int)(b >> 8) & 0xff] ^ t3[(int)(b >> 24) & 0xff]
-                ^ t2[(int)(b >> 40) & 0xff] ^ t1[(int)(b >> 56) & 0xff];
-         a *= mul;
-    }
-
-    private void keySchedule()
-    {
-        x[0] -= x[7] ^ 0xA5A5A5A5A5A5A5A5L; 
-        x[1] ^= x[0]; 
-        x[2] += x[1]; 
-        x[3] -= x[2] ^ ((~x[1]) << 19); 
-        x[4] ^= x[3]; 
-        x[5] += x[4]; 
-        x[6] -= x[5] ^ ((~x[4]) >>> 23); 
-        x[7] ^= x[6]; 
-        x[0] += x[7]; 
-        x[1] -= x[0] ^ ((~x[7]) << 19); 
-        x[2] ^= x[1]; 
-        x[3] += x[2]; 
-        x[4] -= x[3] ^ ((~x[2]) >>> 23); 
-        x[5] ^= x[4]; 
-        x[6] += x[5]; 
-        x[7] -= x[6] ^ 0x0123456789ABCDEFL;
-    }
-
-    private void processBlock()
-    {
-        //
-        // save abc
-        //
-        long aa = a;
-        long bb = b;
-        long cc = c;
-
-        //
-        // rounds and schedule
-        //
-        roundABC(x[0], 5);
-        roundBCA(x[1], 5);
-        roundCAB(x[2], 5);
-        roundABC(x[3], 5);
-        roundBCA(x[4], 5);
-        roundCAB(x[5], 5);
-        roundABC(x[6], 5);
-        roundBCA(x[7], 5);
-
-        keySchedule();
-
-        roundCAB(x[0], 7);
-        roundABC(x[1], 7);
-        roundBCA(x[2], 7);
-        roundCAB(x[3], 7);
-        roundABC(x[4], 7);
-        roundBCA(x[5], 7);
-        roundCAB(x[6], 7);
-        roundABC(x[7], 7);
-
-        keySchedule();
-
-        roundBCA(x[0], 9);
-        roundCAB(x[1], 9);
-        roundABC(x[2], 9);
-        roundBCA(x[3], 9);
-        roundCAB(x[4], 9);
-        roundABC(x[5], 9);
-        roundBCA(x[6], 9);
-        roundCAB(x[7], 9);
-
-        //
-        // feed forward
-        //
-        a ^= aa;
-        b -= bb;
-        c += cc;
-
-        //
-        // clear the x buffer
-        //
-        xOff = 0;
-        for (int i = 0; i != x.length; i++)
-        {
-            x[i] = 0;
-        }
-    }
-
-    public void unpackWord(
-        long    r,
-        byte[]  out,
-        int     outOff)
-    {
-        out[outOff + 7]     = (byte)(r >> 56);
-        out[outOff + 6] = (byte)(r >> 48);
-        out[outOff + 5] = (byte)(r >> 40);
-        out[outOff + 4] = (byte)(r >> 32);
-        out[outOff + 3] = (byte)(r >> 24);
-        out[outOff + 2] = (byte)(r >> 16);
-        out[outOff + 1] = (byte)(r >> 8);
-        out[outOff] = (byte)r;
-    }
-        
-    private void processLength(
-        long    bitLength)
-    {
-        x[7] = bitLength;
-    }
-
-    private void finish()
-    {
-        long    bitLength = (byteCount << 3);
-
-        update((byte)0x01);
-
-        while (bOff != 0)
-        {
-            update((byte)0);
-        }
-
-        processLength(bitLength);
-
-        processBlock();
-    }
-
-    public int doFinal(
-        byte[]  out,
-        int     outOff)
-    {
-        finish();
-
-        unpackWord(a, out, outOff);
-        unpackWord(b, out, outOff + 8);
-        unpackWord(c, out, outOff + 16);
-
-        reset();
-
-        return DIGEST_LENGTH;
-    }
-
-    /**
-     * reset the chaining variables
-     */
-    public void reset()
-    {
-        a = 0x0123456789ABCDEFL;
-        b = 0xFEDCBA9876543210L;
-        c = 0xF096A5B4C3B2E187L;
-
-        xOff = 0;
-        for (int i = 0; i != x.length; i++)
-        {
-            x[i] = 0;
-        }
-
-        bOff = 0;
-        for (int i = 0; i != buf.length; i++)
-        {
-            buf[i] = 0;
-        }
-
-        byteCount = 0;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java b/azureus2/src/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java
deleted file mode 100644
index 7e30023..0000000
--- a/azureus2/src/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java
+++ /dev/null
@@ -1,251 +0,0 @@
-package org.bouncycastle.crypto.encodings;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-
-/**
- * ISO 9796-1 padding. Note in the light of recent results you should
- * only use this with RSA (rather than the "simpler" Rabin keys) and you
- * should never use it with anything other than a hash (ie. even if the 
- * message is small don't sign the message, sign it's hash) or some "random"
- * value. See your favorite search engine for details.
- */
-public class ISO9796d1Encoding
-    implements AsymmetricBlockCipher
-{
-    private static byte[]    shadows = { 0xe, 0x3, 0x5, 0x8, 0x9, 0x4, 0x2, 0xf,
-                                    0x0, 0xd, 0xb, 0x6, 0x7, 0xa, 0xc, 0x1 };
-    private static byte[]    inverse = { 0x8, 0xf, 0x6, 0x1, 0x5, 0x2, 0xb, 0xc,
-                                    0x3, 0x4, 0xd, 0xa, 0xe, 0x9, 0x0, 0x7 };
-
-    private AsymmetricBlockCipher   engine;
-    private boolean                 forEncryption;
-    private int                     bitSize;
-    private int                     padBits = 0;
-
-    public ISO9796d1Encoding(
-        AsymmetricBlockCipher   cipher)
-    {
-        this.engine = cipher;
-    }   
-
-    public AsymmetricBlockCipher getUnderlyingCipher()
-    {
-        return engine;
-    }
-
-    public void init(
-        boolean             forEncryption,
-        CipherParameters    param)
-    {
-        RSAKeyParameters  kParam = null;
-
-        if (param instanceof ParametersWithRandom)
-        {
-            ParametersWithRandom    rParam = (ParametersWithRandom)param;
-
-            kParam = (RSAKeyParameters)rParam.getParameters();
-        }
-        else
-        {
-            kParam = (RSAKeyParameters)param;
-        }
-
-        engine.init(forEncryption, kParam);
-
-        bitSize = kParam.getModulus().bitLength();
-
-        this.forEncryption = forEncryption;
-    }
-
-    /**
-     * return the input block size. The largest message we can process
-     * is (key_size_in_bits + 3)/16, which in our world comes to 
-     * key_size_in_bytes / 2.
-     */
-    public int getInputBlockSize()
-    {
-        int     baseBlockSize = engine.getInputBlockSize();
-
-        if (forEncryption)
-        {
-            return (baseBlockSize + 1) / 2;
-        }
-        else
-        {
-            return baseBlockSize;
-        }
-    }
-
-    /**
-     * return the maximum possible size for the output.
-     */
-    public int getOutputBlockSize()
-    {
-        int     baseBlockSize = engine.getOutputBlockSize();
-
-        if (forEncryption)
-        {
-            return baseBlockSize;
-        }
-        else
-        {
-            return (baseBlockSize + 1) / 2;
-        }
-    }
-
-    /**
-     * set the number of bits in the next message to be treated as 
-     * pad bits.
-     */
-    public void setPadBits(
-        int     padBits)
-    {
-        if (padBits > 7)
-        {
-            throw new IllegalArgumentException("padBits > 7");
-        }
-
-        this.padBits = padBits;
-    }
-
-    /**
-     * retrieve the number of pad bits in the last decoded message.
-     */
-    public int getPadBits()
-    {
-        return padBits;
-    }
-
-    public byte[] processBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-        throws InvalidCipherTextException
-    {
-        if (forEncryption)
-        {
-            return encodeBlock(in, inOff, inLen);
-        }
-        else
-        {
-            return decodeBlock(in, inOff, inLen);
-        }
-    }
-
-    private byte[] encodeBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-        throws InvalidCipherTextException
-    {
-        byte[]  block = new byte[(bitSize + 7) / 8];
-        int     r = padBits + 1;
-        int     z = inLen;
-        int     t = (bitSize + 13) / 16;
-
-        for (int i = 0; i < t; i += z)
-        {
-            if (i > t - z)
-            {
-                System.arraycopy(in, inOff + inLen - (t - i),
-                                    block, block.length - t, t - i);
-            }
-            else
-            {
-                System.arraycopy(in, inOff, block, block.length - (i + z), z);
-            }
-        }
-
-        for (int i = block.length - 2 * t; i != block.length; i += 2)
-        {
-            byte    val = block[block.length - t + i / 2];
-            
-            block[i] = (byte)((shadows[(val & 0xff) >>> 4] << 4)
-                                                | shadows[val & 0x0f]);
-            block[i + 1] = val;
-        }
-
-        block[block.length - 2 * z] ^= r;
-        block[block.length - 1] = (byte)((block[block.length - 1] << 4) | 0x06);
-
-        int maxBit = (8 - (bitSize - 1) % 8);
-        int offSet = 0;
-
-        if (maxBit != 8)
-        {
-            block[0] &= 0xff >>> maxBit;
-            block[0] |= 0x80 >>> maxBit;
-        }
-        else
-        {
-            block[0] = 0x00;
-            block[1] |= 0x80;
-            offSet = 1;
-        }
-
-        return engine.processBlock(block, offSet, block.length - offSet);
-    }
-
-    /**
-     * @exception InvalidCipherTextException if the decrypted block is not a valid ISO 9796 bit string
-     */
-    private byte[] decodeBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-        throws InvalidCipherTextException
-    {
-        byte[]  block = engine.processBlock(in, inOff, inLen);
-        int     r = 1;
-        int     t = (bitSize + 13) / 16;
-
-        if ((block[block.length - 1] & 0x0f) != 0x6)
-        {
-            throw new InvalidCipherTextException("invalid forcing byte in block");
-        }
-
-        block[block.length - 1] = (byte)(((block[block.length - 1] & 0xff) >>> 4) | ((inverse[(block[block.length - 2] & 0xff) >> 4]) << 4));
-        block[0] = (byte)((shadows[(block[1] & 0xff) >>> 4] << 4)
-                                                | shadows[block[1] & 0x0f]);
-
-        boolean boundaryFound = false;
-        int     boundary = 0;
-        
-        for (int i = block.length - 1; i >= block.length - 2 * t; i -= 2)
-        {
-            int val = ((shadows[(block[i] & 0xff) >>> 4] << 4)
-                                        | shadows[block[i] & 0x0f]);
-            
-            if (((block[i - 1] ^ val) & 0xff) != 0)
-            {
-                if (!boundaryFound)
-                {
-                    boundaryFound = true;
-                    r = (block[i - 1] ^ val) & 0xff;
-                    boundary = i - 1;
-                }
-                else
-                {
-                    throw new InvalidCipherTextException("invalid tsums in block");
-                }
-            }
-        }
-
-        block[boundary] = 0;
-
-        byte[]  nblock = new byte[(block.length - boundary) / 2];
-
-        for (int i = 0; i < nblock.length; i++)
-        {
-            nblock[i] = block[2 * i + boundary + 1];
-        }
-
-        padBits = r - 1;
-
-        return nblock;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/encodings/OAEPEncoding.java b/azureus2/src/org/bouncycastle/crypto/encodings/OAEPEncoding.java
deleted file mode 100644
index 961c3cb..0000000
--- a/azureus2/src/org/bouncycastle/crypto/encodings/OAEPEncoding.java
+++ /dev/null
@@ -1,342 +0,0 @@
-package org.bouncycastle.crypto.encodings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2.
- */
-public class OAEPEncoding
-    implements AsymmetricBlockCipher
-{
-    private byte[]          defHash;
-    private Digest      	  hash;
-
-    private AsymmetricBlockCipher   engine;
-    private SecureRandom            random;
-    private boolean                 forEncryption;
-
-    public OAEPEncoding(
-        AsymmetricBlockCipher   cipher)
-    {
-        this(cipher, new SHA1Digest(), null);
-    }
-    
-	public OAEPEncoding(
-		AsymmetricBlockCipher   	cipher,
-		Digest							hash)
-	{
-		this(cipher, hash, null);
-	}
-    
-	public OAEPEncoding(
-		AsymmetricBlockCipher   	cipher,
-		Digest							hash,
-		byte[]							encodingParams)
-	{
-		this.engine = cipher;
-		this.hash = hash;
-		this.defHash = new byte[hash.getDigestSize()];
-        
-        if (encodingParams != null)
-        {
-        	hash.update(encodingParams, 0, encodingParams.length);
-        }
-        
-		hash.doFinal(defHash, 0);
-	}
-	
-    public AsymmetricBlockCipher getUnderlyingCipher()
-    {
-        return engine;
-    }
-
-    public void init(
-        boolean             forEncryption,
-        CipherParameters    param)
-    {
-        AsymmetricKeyParameter  kParam;
-
-        if (param instanceof ParametersWithRandom)
-        {
-            ParametersWithRandom  rParam = (ParametersWithRandom)param;
-
-            this.random = rParam.getRandom();
-            kParam = (AsymmetricKeyParameter)rParam.getParameters();
-        }
-        else
-        {   
-            this.random = new SecureRandom();
-            kParam = (AsymmetricKeyParameter)param;
-        }
-
-        engine.init(forEncryption, kParam);
-
-        this.forEncryption = forEncryption;
-    }
-
-    public int getInputBlockSize()
-    {
-        int     baseBlockSize = engine.getInputBlockSize();
-
-        if (forEncryption)
-        {
-            return baseBlockSize - 1 - 2 * defHash.length;
-        }
-        else
-        {
-            return baseBlockSize;
-        }
-    }
-
-    public int getOutputBlockSize()
-    {
-        int     baseBlockSize = engine.getOutputBlockSize();
-
-        if (forEncryption)
-        {
-            return baseBlockSize;
-        }
-        else
-        {
-            return baseBlockSize - 1 - 2 * defHash.length;
-        }
-    }
-
-    public byte[] processBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-        throws InvalidCipherTextException
-    {
-        if (forEncryption)
-        {
-            return encodeBlock(in, inOff, inLen);
-        }
-        else
-        {
-            return decodeBlock(in, inOff, inLen);
-        }
-    }
-
-    public byte[] encodeBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-        throws InvalidCipherTextException
-    {
-        byte[]  block = new byte[getInputBlockSize() + 1 + 2 * defHash.length];
-
-        //
-        // copy in the message
-        //
-        System.arraycopy(in, inOff, block, block.length - inLen, inLen);
-
-        //
-        // add sentinel
-        //
-        block[block.length - inLen - 1] = 0x01;
-
-        //
-        // as the block is already zeroed - there's no need to add PS (the >= 0 pad of 0)
-        //
-
-        //
-        // add the hash of the encoding params.
-        //
-        System.arraycopy(defHash, 0, block, defHash.length, defHash.length);
-
-        //
-        // generate the seed.
-        //
-        byte[]  seed = new byte[defHash.length];
-
-        random.nextBytes(seed);
-
-        //
-        // mask the message block.
-        //
-        byte[]  mask = maskGeneratorFunction1(seed, 0, seed.length, block.length - defHash.length);
-
-        for (int i = defHash.length; i != block.length; i++)
-        {
-            block[i] ^= mask[i - defHash.length];
-        }
-
-        //
-        // add in the seed
-        //
-        System.arraycopy(seed, 0, block, 0, defHash.length);
-
-        //
-        // mask the seed.
-        //
-        mask = maskGeneratorFunction1(
-                        block, defHash.length, block.length - defHash.length, defHash.length);
-
-        for (int i = 0; i != defHash.length; i++)
-        {
-            block[i] ^= mask[i];
-        }
-
-        return engine.processBlock(block, 0, block.length);
-    }
-
-    /**
-     * @exception InvalidCipherTextException if the decryypted block turns out to
-     * be badly formatted.
-     */
-    public byte[] decodeBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-        throws InvalidCipherTextException
-    {
-        byte[]  data = engine.processBlock(in, inOff, inLen);
-        byte[]  block = null;
-
-        //
-        // as we may have zeros in our leading bytes for the block we produced
-        // on encryption, we need to make sure our decrypted block comes back
-        // the same size.
-        //
-        if (data.length < engine.getOutputBlockSize())
-        {
-            block = new byte[engine.getOutputBlockSize()];
-
-            System.arraycopy(data, 0, block, block.length - data.length, data.length);
-        }
-        else
-        {
-            block = data;
-        }
-
-        if (block.length < (2 * defHash.length) + 1)
-        {
-            throw new InvalidCipherTextException("data too short");
-        }
-
-        //
-        // unmask the seed.
-        //
-        byte[] mask = maskGeneratorFunction1(
-                    block, defHash.length, block.length - defHash.length, defHash.length);
-
-        for (int i = 0; i != defHash.length; i++)
-        {
-            block[i] ^= mask[i];
-        }
-
-        //
-        // unmask the message block.
-        //
-        mask = maskGeneratorFunction1(block, 0, defHash.length, block.length - defHash.length);
-
-        for (int i = defHash.length; i != block.length; i++)
-        {
-            block[i] ^= mask[i - defHash.length];
-        }
-
-        //
-        // check the hash of the encoding params.
-        //
-        for (int i = 0; i != defHash.length; i++)
-        {
-            if (defHash[i] != block[defHash.length + i])
-            {
-                throw new InvalidCipherTextException("data hash wrong");
-            }
-        }
-
-        //
-        // find the data block
-        //
-        int start;
-
-        for (start = 2 * defHash.length; start != block.length; start++)
-        {
-            if (block[start] == 1 || block[start] != 0)
-            {
-                break;
-            }
-        }
-
-        if (start >= (block.length - 1) || block[start] != 1)
-        {
-            throw new InvalidCipherTextException("data start wrong " + start);
-        }
-
-        start++;
-
-        //
-        // extract the data block
-        //
-        byte[]  output = new byte[block.length - start];
-
-        System.arraycopy(block, start, output, 0, output.length);
-
-        return output;
-    }
-
-    /**
-     * int to octet string.
-     */
-    private void ItoOSP(
-        int     i,
-        byte[]  sp)
-    {
-        sp[0] = (byte)(i >>> 24);
-        sp[1] = (byte)(i >>> 16);
-        sp[2] = (byte)(i >>> 8);
-        sp[3] = (byte)(i >>> 0);
-    }
-
-    /**
-     * mask generator function, as described in PKCS1v2.
-     */
-    private byte[] maskGeneratorFunction1(
-        byte[]  Z,
-        int     zOff,
-        int     zLen,
-        int     length)
-    {
-        byte[]  mask = new byte[length];
-        byte[]  hashBuf = new byte[defHash.length];
-        byte[]  C = new byte[4];
-        int     counter = 0;
-
-        hash.reset();
-
-        do
-        {
-            ItoOSP(counter, C);
-
-            hash.update(Z, zOff, zLen);
-            hash.update(C, 0, C.length);
-            hash.doFinal(hashBuf, 0);
-
-            System.arraycopy(hashBuf, 0, mask, counter * defHash.length, defHash.length);
-        }
-        while (++counter < (length / defHash.length));
-
-        if ((counter * defHash.length) < length)
-        {
-            ItoOSP(counter, C);
-
-            hash.update(Z, zOff, zLen);
-            hash.update(C, 0, C.length);
-            hash.doFinal(hashBuf, 0);
-
-            System.arraycopy(hashBuf, 0, mask, counter * defHash.length, mask.length - (counter * defHash.length));
-        }
-
-        return mask;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/azureus2/src/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
deleted file mode 100644
index 7f18e0b..0000000
--- a/azureus2/src/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package org.bouncycastle.crypto.encodings;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-
-/**
- * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
- * depends on your application - see PKCS1 Version 2 for details.
- */
-public class PKCS1Encoding
-    implements AsymmetricBlockCipher
-{
-    private static int      HEADER_LENGTH = 10;
-
-    private SecureRandom            random;
-    private AsymmetricBlockCipher   engine;
-    private boolean                 forEncryption;
-    private boolean                 forPrivateKey;
-
-    public PKCS1Encoding(
-        AsymmetricBlockCipher   cipher)
-    {
-        this.engine = cipher;
-    }   
-
-    public AsymmetricBlockCipher getUnderlyingCipher()
-    {
-        return engine;
-    }
-
-    public void init(
-        boolean             forEncryption,
-        CipherParameters    param)
-    {
-        AsymmetricKeyParameter  kParam;
-
-        if (param instanceof ParametersWithRandom)
-        {
-            ParametersWithRandom    rParam = (ParametersWithRandom)param;
-
-            this.random = rParam.getRandom();
-            kParam = (AsymmetricKeyParameter)rParam.getParameters();
-        }
-        else
-        {
-            this.random = new SecureRandom();
-            kParam = (AsymmetricKeyParameter)param;
-        }
-
-        engine.init(forEncryption, kParam);
-
-        this.forPrivateKey = kParam.isPrivate();
-        this.forEncryption = forEncryption;
-    }
-
-    public int getInputBlockSize()
-    {
-        int     baseBlockSize = engine.getInputBlockSize();
-
-        if (forEncryption)
-        {
-            return baseBlockSize - HEADER_LENGTH;
-        }
-        else
-        {
-            return baseBlockSize;
-        }
-    }
-
-    public int getOutputBlockSize()
-    {
-        int     baseBlockSize = engine.getOutputBlockSize();
-
-        if (forEncryption)
-        {
-            return baseBlockSize;
-        }
-        else
-        {
-            return baseBlockSize - HEADER_LENGTH;
-        }
-    }
-
-    public byte[] processBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-        throws InvalidCipherTextException
-    {
-        if (forEncryption)
-        {
-            return encodeBlock(in, inOff, inLen);
-        }
-        else
-        {
-            return decodeBlock(in, inOff, inLen);
-        }
-    }
-
-    private byte[] encodeBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-        throws InvalidCipherTextException
-    {
-        byte[]  block = new byte[engine.getInputBlockSize()];
-
-        if (forPrivateKey)
-        {
-            block[0] = 0x01;                        // type code 1
-
-            for (int i = 1; i != block.length - inLen - 1; i++)
-            {
-                block[i] = (byte)0xFF;
-            }
-        }
-        else
-        {
-            random.nextBytes(block);                // random fill
-
-            block[0] = 0x02;                        // type code 2
-
-            //
-            // a zero byte marks the end of the padding, so all
-            // the pad bytes must be non-zero.
-            //
-            for (int i = 1; i != block.length - inLen - 1; i++)
-            {
-                while (block[i] == 0)
-                {
-                    block[i] = (byte)random.nextInt();
-                }
-            }
-        }
-
-        block[block.length - inLen - 1] = 0x00;       // mark the end of the padding
-        System.arraycopy(in, inOff, block, block.length - inLen, inLen);
-
-        return engine.processBlock(block, 0, block.length);
-    }
-
-    /**
-     * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
-     */
-    private byte[] decodeBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-        throws InvalidCipherTextException
-    {
-        byte[]  block = engine.processBlock(in, inOff, inLen);
-
-        if (block.length < getOutputBlockSize())
-        {
-            throw new InvalidCipherTextException("block truncated");
-        }
-
-        if (block[0] != 1 && block[0] != 2)
-        {
-            throw new InvalidCipherTextException("unknown block type");
-        }
-
-        //
-        // find and extract the message block.
-        //
-        int start;
-
-        for (start = 1; start != block.length; start++)
-        {
-            if (block[start] == 0)
-            {
-                break;
-            }
-        }
-
-        start++;           // data should start at the next byte
-
-        if (start >= block.length || start < HEADER_LENGTH)
-        {
-            throw new InvalidCipherTextException("no data in block");
-        }
-
-        byte[]  result = new byte[block.length - start];
-
-        System.arraycopy(block, start, result, 0, result.length);
-
-        return result;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/encodings/package.html b/azureus2/src/org/bouncycastle/crypto/encodings/package.html
deleted file mode 100644
index fc56f63..0000000
--- a/azureus2/src/org/bouncycastle/crypto/encodings/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Block encodings for asymmetric ciphers.
-</body>
-</html>
diff --git a/azureus2/src/org/bouncycastle/crypto/engines/IESEngine.java b/azureus2/src/org/bouncycastle/crypto/engines/IESEngine.java
deleted file mode 100644
index e31b88e..0000000
--- a/azureus2/src/org/bouncycastle/crypto/engines/IESEngine.java
+++ /dev/null
@@ -1,245 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.params.IESParameters;
-import org.bouncycastle.crypto.params.IESWithCipherParameters;
-import org.bouncycastle.crypto.params.KDFParameters;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-/**
- * support class for constructing intergrated encryption ciphers
- * for doing basic message exchanges on top of key agreement ciphers
- */
-public class IESEngine
-{
-    BasicAgreement      agree;
-    DerivationFunction  kdf;
-    Mac                 mac;
-    BufferedBlockCipher cipher;
-    byte[]              macBuf;
-
-    boolean                     forEncryption;
-    CipherParameters            privParam, pubParam;
-    IESParameters               param;
-
-    /**
-     * set up for use with stream mode, where the key derivation function
-     * is used to provide a stream of bytes to xor with the message.
-     *
-     * @param agree the key agreement used as the basis for the encryption
-     * @param kdf the key derivation function used for byte generation
-     * @param mac the message authentication code generator for the message
-     */
-    public IESEngine(
-        BasicAgreement      agree,
-        DerivationFunction  kdf,
-        Mac                 mac)
-    {
-        this.agree = agree;
-        this.kdf = kdf;
-        this.mac = mac;
-        this.macBuf = new byte[mac.getMacSize()];
-        this.cipher = null;
-    }
-
-    /**
-     * set up for use in conjunction with a block cipher to handle the
-     * message.
-     *
-     * @param agree the key agreement used as the basis for the encryption
-     * @param kdf the key derivation function used for byte generation
-     * @param mac the message authentication code generator for the message
-     * @param cipher the cipher to used for encrypting the message
-     */
-    public IESEngine(
-        BasicAgreement      agree,
-        DerivationFunction  kdf,
-        Mac                 mac,
-        BufferedBlockCipher cipher)
-    {
-        this.agree = agree;
-        this.kdf = kdf;
-        this.mac = mac;
-        this.macBuf = new byte[mac.getMacSize()];
-        this.cipher = cipher;
-    }
-
-    /**
-     * Initialise the encryptor.
-     *
-     * @param forEncryption whether or not this is encryption/decryption.
-     * @param privParam our private key parameters
-     * @param pubParam the recipient's/sender's public key parameters
-     * @param param encoding and derivation parameters.
-     */
-    public void init(
-        boolean                     forEncryption,
-        CipherParameters            privParam,
-        CipherParameters            pubParam,
-        CipherParameters            param)
-    {
-        this.forEncryption = forEncryption;
-        this.privParam = privParam;
-        this.pubParam = pubParam;
-        this.param = (IESParameters)param;
-    }
-
-    private byte[] decryptBlock(
-        byte[]  in_enc,
-        int     inOff,
-        int     inLen,
-        byte[]  z)
-        throws InvalidCipherTextException
-    {
-        byte[]          M = null;
-        KeyParameter    macKey = null;
-        KDFParameters   kParam = new KDFParameters(z, param.getDerivationV());
-        int             macKeySize = param.getMacKeySize();
-
-        kdf.init(kParam);
-
-	    inLen -= mac.getMacSize();
-	
-        if (cipher == null)     // stream mode
-        {
-            byte[]  buf = new byte[inLen + (macKeySize / 8)];
-
-            M = new byte[inLen];
-
-            kdf.generateBytes(buf, 0, buf.length);
-
-            for (int i = 0; i != inLen; i++)
-            {
-                M[i] = (byte)(in_enc[inOff + i] ^ buf[i]);
-            }
-
-            macKey = new KeyParameter(buf, inLen, (macKeySize / 8));
-        }
-        else
-        {
-            int     cipherKeySize = ((IESWithCipherParameters)param).getCipherKeySize();
-            byte[]  buf = new byte[(cipherKeySize / 8) + (macKeySize / 8)];
-
-            cipher.init(false, new KeyParameter(buf, 0, (cipherKeySize / 8)));
-
-            byte[] tmp = new byte[cipher.getOutputSize(inLen)];
-
-            int off = cipher.processBytes(in_enc, inOff, inLen, tmp, 0);
-
-            off += cipher.doFinal(tmp, off);
-
-            M = new byte[off];
-
-            System.arraycopy(tmp, 0, M, 0, off);
-
-            macKey = new KeyParameter(buf, (cipherKeySize / 8), (macKeySize / 8));
-        }
-
-        byte[]  macIV = param.getEncodingV();
-
-        mac.init(macKey);
-        mac.update(in_enc, inOff, inLen);
-        mac.update(macIV, 0, macIV.length);
-	    mac.doFinal(macBuf, 0);
-	
-        inOff += inLen;
-
-        for (int t = 0; t < macBuf.length; t++)
-	    {	       
-            if (macBuf[t] != in_enc[inOff + t])
-		    {
-			    throw (new InvalidCipherTextException("Mac codes failed to equal."));
-		    }
-	    }
-	   
-        return M;
-    }
-
-    private byte[] encryptBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen,
-        byte[]  z)
-        throws InvalidCipherTextException
-    {
-        byte[]          C = null;
-        KeyParameter    macKey = null;
-        KDFParameters   kParam = new KDFParameters(z, param.getDerivationV());
-	    int             c_text_length = 0;
-        int             macKeySize = param.getMacKeySize();
-
-        kdf.init(kParam);
-
-        if (cipher == null)     // stream mode
-        {
-            byte[]  buf = new byte[inLen + (macKeySize / 8)];
-
-            C = new byte[inLen + mac.getMacSize()];
-	        c_text_length = inLen;
-
-            kdf.generateBytes(buf, 0, buf.length);
-
-            for (int i = 0; i != inLen; i++)
-            {
-                C[i] = (byte)(in[inOff + i] ^ buf[i]);
-            }
-
-            macKey = new KeyParameter(buf, inLen, (macKeySize / 8));
-        }
-        else
-        {
-            int     cipherKeySize = ((IESWithCipherParameters)param).getCipherKeySize();
-            byte[]  buf = new byte[(cipherKeySize / 8) + (macKeySize / 8)];
-
-            cipher.init(true, new KeyParameter(buf, 0, (cipherKeySize / 8)));
-
-            c_text_length = cipher.getOutputSize(inLen);
-
-            C = new byte[c_text_length + mac.getMacSize()];
-
-            int off = cipher.processBytes(in, inOff, inLen, C, 0);
-
-            cipher.doFinal(C, off);
-
-            macKey = new KeyParameter(buf, (cipherKeySize / 8), (macKeySize / 8));
-        }
-
-        byte[]  macIV = param.getEncodingV();
-
-        mac.init(macKey);
-        mac.update(C, 0, c_text_length);
-        mac.update(macIV, 0, macIV.length);
-        //
-        // return the message and it's MAC
-        //
-        mac.doFinal(C, c_text_length);
-        return C;
-    }
-
-    public byte[] processBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-        throws InvalidCipherTextException
-    {
-        agree.init(privParam);
-
-        BigInteger  z = agree.calculateAgreement(pubParam);
-
-        if (forEncryption)
-        {
-            return encryptBlock(in, inOff, inLen, z.toByteArray());
-        }
-        else
-        {
-            return decryptBlock(in, inOff, inLen, z.toByteArray());
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/engines/RC4Engine.java b/azureus2/src/org/bouncycastle/crypto/engines/RC4Engine.java
deleted file mode 100644
index f511afa..0000000
--- a/azureus2/src/org/bouncycastle/crypto/engines/RC4Engine.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.StreamCipher;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-public class RC4Engine implements StreamCipher
-{
-    private final static int STATE_LENGTH = 256;
-
-    /*
-     * variables to hold the state of the RC4 engine
-     * during encryption and decryption
-     */
-
-    private byte[]      engineState = null;
-    private int         x = 0;
-    private int         y = 0;
-    private byte[]      workingKey = null;
-
-    /**
-     * initialise a RC4 cipher.
-     *
-     * @param forEncryption whether or not we are for encryption.
-     * @param params the parameters required to set up the cipher.
-     * @exception IllegalArgumentException if the params argument is
-     * inappropriate.
-     */
-    public void init(
-        boolean             forEncryption, 
-        CipherParameters     params
-    )
-    {
-        if (params instanceof KeyParameter)
-        {
-            /* 
-             * RC4 encryption and decryption is completely
-             * symmetrical, so the 'forEncryption' is 
-             * irrelevant.
-             */
-            workingKey = ((KeyParameter)params).getKey();
-            setKey(workingKey);
-
-            return;
-        }
-
-        throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName());
-    }
-
-    public String getAlgorithmName()
-    {
-        return "RC4";
-    }
-
-    public byte returnByte(byte in)
-    {
-        x = (x + 1) & 0xff;
-        y = (engineState[x] + y) & 0xff;
-
-        // swap
-        byte tmp = engineState[x];
-        engineState[x] = engineState[y];
-        engineState[y] = tmp;
-
-        // xor
-        return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
-    }
-
-    public void processBytes(
-        byte[]     in, 
-        int     inOff, 
-        int     len, 
-        byte[]     out, 
-        int     outOff )
-    {
-        for (int i = 0; i < len ; i++)
-        {
-            x = (x + 1) & 0xff;
-            y = (engineState[x] + y) & 0xff;
-
-            // swap
-            byte tmp = engineState[x];
-            engineState[x] = engineState[y];
-            engineState[y] = tmp;
-
-            // xor
-            out[i+outOff] = (byte)(in[i + inOff]
-                    ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
-        }
-    }
-    
-    /*
-    public void 
-    processBytes(
-        byte[]     in, 
-        byte[]     out )
-    {
-    	int	len = in.length;
-    	
-        for (int i = 0; i < len ; i++)
-        {
-            x = (x + 1) & 0xff;
-            y = (engineState[x] + y) & 0xff;
-
-            // swap
-            byte tmp = engineState[x];
-            engineState[x] = engineState[y];
-            engineState[y] = tmp;
-
-            // xor
-            out[i] = (byte)(in[i] ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
-        }
-    }
-	*/
-    
-    public void reset()
-    {
-        setKey(workingKey);
-    }
-
-    // Private implementation
-
-    private void setKey(byte[] keyBytes)
-    {
-        workingKey = keyBytes;
-
-        // System.out.println("the key length is ; "+ workingKey.length);
-
-        x = 0;
-        y = 0;
-
-        if (engineState == null)
-        {
-            engineState = new byte[STATE_LENGTH];
-        }
-
-        // reset the state of the engine
-        for (int i=0; i < STATE_LENGTH; i++)
-        {
-            engineState[i] = (byte)i;
-        }
-        
-        int i1 = 0;
-        int i2 = 0;
-
-        for (int i=0; i < STATE_LENGTH; i++)
-        {
-            i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;
-            // do the byte-swap inline
-            byte tmp = engineState[i];
-            engineState[i] = engineState[i2];
-            engineState[i2] = tmp;
-            i1 = (i1+1) % keyBytes.length; 
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/engines/RSAEngine.java b/azureus2/src/org/bouncycastle/crypto/engines/RSAEngine.java
deleted file mode 100644
index e8d4128..0000000
--- a/azureus2/src/org/bouncycastle/crypto/engines/RSAEngine.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-
-/**
- * this does your basic RSA algorithm. 
- */
-public class RSAEngine
-    implements AsymmetricBlockCipher
-{
-    private RSAKeyParameters        key;
-    private boolean                 forEncryption;
-
-    /**
-     * initialise the RSA engine.
-     *
-     * @param forEncryption true if we are encrypting, false otherwise.
-     * @param param the necessary RSA key parameters.
-     */
-    public void init(
-        boolean             forEncryption,
-        CipherParameters    param)
-    {
-        this.key = (RSAKeyParameters)param;
-        this.forEncryption = forEncryption;
-    }
-
-    /**
-     * Return the maximum size for an input block to this engine.
-     * For RSA this is always one byte less than the key size on
-     * encryption, and the same length as the key size on decryption.
-     *
-     * @return maximum size for an input block.
-     */
-    public int getInputBlockSize()
-    {
-        int     bitSize = key.getModulus().bitLength();
-
-        if (forEncryption)
-        {
-            return (bitSize + 7) / 8 - 1;
-        }
-        else
-        {
-            return (bitSize + 7) / 8;
-        }
-    }
-
-    /**
-     * Return the maximum size for an output block to this engine.
-     * For RSA this is always one byte less than the key size on
-     * decryption, and the same length as the key size on encryption.
-     *
-     * @return maximum size for an output block.
-     */
-    public int getOutputBlockSize()
-    {
-        int     bitSize = key.getModulus().bitLength();
-
-        if (forEncryption)
-        {
-            return (bitSize + 7) / 8;
-        }
-        else
-        {
-            return (bitSize + 7) / 8 - 1;
-        }
-    }
-
-    /**
-     * Process a single block using the basic RSA algorithm.
-     *
-     * @param in the input array.
-     * @param inOff the offset into the input buffer where the data starts.
-     * @param inLen the length of the data to be processed.
-     * @return the result of the RSA process.
-     * @exception DataLengthException the input block is too large.
-     */
-    public byte[] processBlock(
-        byte[]  in,
-        int     inOff,
-        int     inLen)
-    {
-        if (inLen > (getInputBlockSize() + 1))
-        {
-            throw new DataLengthException("input too large for RSA cipher.\n");
-        }
-        else if (inLen == (getInputBlockSize() + 1) && (in[inOff] & 0x80) != 0)
-        {
-            throw new DataLengthException("input too large for RSA cipher.\n");
-        }
-
-        byte[]  block;
-
-        if (inOff != 0 || inLen != in.length)
-        {
-            block = new byte[inLen];
-
-            System.arraycopy(in, inOff, block, 0, inLen);
-        }
-        else
-        {
-            block = in;
-        }
-
-        BigInteger  input = new BigInteger(1, block);
-        byte[]      output;
-
-        if (key instanceof RSAPrivateCrtKeyParameters)
-        {
-            //
-            // we have the extra factors, use the Chinese Remainder Theorem - the author
-            // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for 
-            // advice regarding the expression of this.
-            //
-            RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key;
-
-            BigInteger p = crtKey.getP();
-            BigInteger q = crtKey.getQ();
-            BigInteger dP = crtKey.getDP();
-            BigInteger dQ = crtKey.getDQ();
-            BigInteger qInv = crtKey.getQInv();
-    
-            BigInteger mP, mQ, h, m;
-    
-            // mP = ((input mod p) ^ dP)) mod p
-            mP = (input.remainder(p)).modPow(dP, p);
-    
-            // mQ = ((input mod q) ^ dQ)) mod q
-            mQ = (input.remainder(q)).modPow(dQ, q);
-    
-            // h = qInv * (mP - mQ) mod p
-            h = mP.subtract(mQ);
-            h = h.multiply(qInv);
-            h = h.mod(p);               // mod (in Java) returns the positive residual
-    
-            // m = h * q + mQ
-            m = h.multiply(q);
-            m = m.add(mQ);
-    
-            output = m.toByteArray();
-        }
-        else
-        {
-            output = input.modPow(
-                        key.getExponent(), key.getModulus()).toByteArray();
-        }
-
-        if (forEncryption)
-        {
-            if (output[0] == 0 && output.length > getOutputBlockSize())        // have ended up with an extra zero byte, copy down.
-            {
-                byte[]  tmp = new byte[output.length - 1];
-
-                System.arraycopy(output, 1, tmp, 0, tmp.length);
-
-                return tmp;
-            }
-
-            if (output.length < getOutputBlockSize())     // have ended up with less bytes than normal, lengthen
-            {
-                byte[]  tmp = new byte[getOutputBlockSize()];
-
-                System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
-
-                return tmp;
-            }
-        }
-        else
-        {
-            if (output[0] == 0)        // have ended up with an extra zero byte, copy down.
-            {
-                byte[]  tmp = new byte[output.length - 1];
-
-                System.arraycopy(output, 1, tmp, 0, tmp.length);
-
-                return tmp;
-            }
-        }
-        return output;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
deleted file mode 100644
index 268ae9b..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.params.ISO18033KDFParameters;
-import org.bouncycastle.crypto.params.KDFParameters;
-
-/**
- * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
- * <br>
- * This implementation is based on ISO 18033/P1363a.
- */
-public class BaseKDFBytesGenerator
-    implements DerivationFunction
-{
-    private int     counterStart;
-    private Digest  digest;
-    private byte[]  shared;
-    private byte[]  iv;
-
-    /**
-     * Construct a KDF Parameters generator.
-     * <p>
-     * @param counterStart value of counter.
-     * @param digest the digest to be used as the source of derived keys.
-     */
-    protected BaseKDFBytesGenerator(
-        int     counterStart,
-        Digest  digest)
-    {
-        this.counterStart = counterStart;
-        this.digest = digest;
-    }
-
-    public void init(
-        DerivationParameters    param)
-    {
-        if (param instanceof KDFParameters)
-        {
-            KDFParameters   p = (KDFParameters)param;
-
-            shared = p.getSharedSecret();
-            iv = p.getIV();
-        }
-        else if (param instanceof ISO18033KDFParameters)
-        {
-            ISO18033KDFParameters p = (ISO18033KDFParameters)param;
-            
-            shared = p.getSeed();
-            iv = null;
-        }
-        else
-        {
-            throw new IllegalArgumentException("KDF parameters required for KDF2Generator");
-        }
-    }
-
-    /**
-     * return the underlying digest.
-     */
-    public Digest getDigest()
-    {
-        return digest;
-    }
-
-    /**
-     * fill len bytes of the output buffer with bytes generated from
-     * the derivation function.
-     *
-     * @throws IllegalArgumentException if the size of the request will cause an overflow.
-     * @throws DataLengthException if the out buffer is too small.
-     */
-    public int generateBytes(
-        byte[]  out,
-        int     outOff,
-        int     len)
-        throws DataLengthException, IllegalArgumentException
-    {
-        if ((out.length - len) < outOff)
-        {
-            throw new DataLengthException("output buffer too small");
-        }
-
-        long    oBytes = len;
-        int     outLen = digest.getDigestSize(); 
-
-        //
-        // this is at odds with the standard implementation, the
-        // maximum value should be hBits * (2^32 - 1) where hBits
-        // is the digest output size in bits. We can't have an
-        // array with a long index at the moment...
-        //
-        if (oBytes > ((2L << 32) - 1))
-        {
-            throw new IllegalArgumentException("Output length too large");
-        }
-
-        int cThreshold = (int)((oBytes + outLen - 1) / outLen);
-
-        byte[] dig = null;
-
-        dig = new byte[digest.getDigestSize()];
-
-        int counter = counterStart;
-        
-        for (int i = 0; i < cThreshold; i++)
-        {
-            digest.update(shared, 0, shared.length);
-
-            digest.update((byte)(counter >> 24));
-            digest.update((byte)(counter >> 16));
-            digest.update((byte)(counter >> 8));
-            digest.update((byte)counter);
-            
-            if (iv != null)
-            {
-                digest.update(iv, 0, iv.length);
-            }
-
-            digest.doFinal(dig, 0);
-
-            if (len > outLen)
-            {
-                System.arraycopy(dig, 0, out, outOff, outLen);
-                outOff += outLen;
-                len -= outLen;
-            }
-            else
-            {
-                System.arraycopy(dig, 0, out, outOff, len);
-            }
-            
-            counter++;
-        }
-    
-        digest.reset();
-
-        return len;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/DESKeyGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/DESKeyGenerator.java
deleted file mode 100644
index bb3f6d0..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/DESKeyGenerator.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.CipherKeyGenerator;
-import org.bouncycastle.crypto.params.DESParameters;
-
-public class DESKeyGenerator
-    extends CipherKeyGenerator
-{
-    public byte[] generateKey()
-    {
-        byte[]  newKey = new byte[DESParameters.DES_KEY_LENGTH];
-
-        do
-        {
-            random.nextBytes(newKey);
-
-            DESParameters.setOddParity(newKey);
-        }
-        while (DESParameters.isWeakKey(newKey, 0));
-
-        return newKey;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java
deleted file mode 100644
index 101dc37..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.DESedeParameters;
-
-public class DESedeKeyGenerator
-    extends DESKeyGenerator
-{
-    /**
-     * initialise the key generator - if strength is set to zero
-     * the key generated will be 192 bits in size, otherwise
-     * strength can be 128 or 192 (or 112 or 168 if you don't count
-     * parity bits), depending on whether you wish to do 2-key or 3-key
-     * triple DES.
-     *
-     * @param param the parameters to be used for key generation
-     */
-    public void init(
-        KeyGenerationParameters param)
-    {
-        super.init(param);
-
-        if (strength == 0 || strength == (168 / 8))
-        {
-            strength = DESedeParameters.DES_EDE_KEY_LENGTH;
-        }
-        else if (strength == (112 / 8))
-        {
-            strength = 2 * DESedeParameters.DES_KEY_LENGTH;
-        }
-        else if (strength != DESedeParameters.DES_EDE_KEY_LENGTH
-                && strength != (2 * DESedeParameters.DES_KEY_LENGTH))
-        {
-            throw new IllegalArgumentException("DESede key must be "
-                + (DESedeParameters.DES_EDE_KEY_LENGTH * 8) + " or "
-                + (2 * 8 * DESedeParameters.DES_KEY_LENGTH)
-                + " bits long.");
-        }
-    }
-
-    public byte[] generateKey()
-    {
-        byte[]  newKey = new byte[strength];
-
-        do
-        {
-            random.nextBytes(newKey);
-
-            DESedeParameters.setOddParity(newKey);
-        }
-        while (DESedeParameters.isWeakKey(newKey, 0, newKey.length));
-
-        return newKey;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java
deleted file mode 100644
index 2fbf02c..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-
-/**
- * a basic Diffie-Helman key pair generator.
- *
- * This generates keys consistent for use with the basic algorithm for
- * Diffie-Helman.
- */
-public class DHBasicKeyPairGenerator
-    implements AsymmetricCipherKeyPairGenerator
-{
-    private DHKeyGenerationParameters param;
-
-    public void init(
-        KeyGenerationParameters param)
-    {
-        this.param = (DHKeyGenerationParameters)param;
-    }
-
-    public AsymmetricCipherKeyPair generateKeyPair()
-    {
-        BigInteger      p, g, x, y;
-        int             qLength = param.getStrength() - 1;
-        DHParameters    dhParams = param.getParameters();
-
-        p = dhParams.getP();
-        g = dhParams.getG();
-   
-        //
-        // calculate the private key
-        //
-		x = new BigInteger(qLength, param.getRandom());
-		
-        //
-        // calculate the public key.
-        //
-        y = g.modPow(x, p);
-
-        return new AsymmetricCipherKeyPair(
-                new DHPublicKeyParameters(y, dhParams),
-                new DHPrivateKeyParameters(x, dhParams));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java
deleted file mode 100644
index 9e53eab..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-
-/**
- * a Diffie-Helman key pair generator.
- *
- * This generates keys consistent for use in the MTI/A0 key agreement protocol
- * as described in "Handbook of Applied Cryptography", Pages 516-519.
- */
-public class DHKeyPairGenerator
-    implements AsymmetricCipherKeyPairGenerator
-{
-    private DHKeyGenerationParameters param;
-
-    public void init(
-        KeyGenerationParameters param)
-    {
-        this.param = (DHKeyGenerationParameters)param;
-    }
-
-    public AsymmetricCipherKeyPair generateKeyPair()
-    {
-        BigInteger      p, g, x, y;
-        int             qLength = param.getStrength() - 1;
-        DHParameters    dhParams = param.getParameters();
-
-        p = dhParams.getP();
-        g = dhParams.getG();
-    
-        //
-        // calculate the private key
-        //
-		x = new BigInteger(qLength, param.getRandom());
-
-        //
-        // calculate the public key.
-        //
-        y = g.modPow(x, p);
-
-        return new AsymmetricCipherKeyPair(
-                new DHPublicKeyParameters(y, dhParams),
-                new DHPrivateKeyParameters(x, dhParams));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/DHParametersGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/DHParametersGenerator.java
deleted file mode 100644
index 152682c..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/DHParametersGenerator.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.params.DHParameters;
-
-public class DHParametersGenerator
-{
-    private int             size;
-    private int             certainty;
-    private SecureRandom    random;
-
-    private static BigInteger ONE = BigInteger.valueOf(1);
-    private static BigInteger TWO = BigInteger.valueOf(2);
-
-    public void init(
-        int             size,
-        int             certainty,
-        SecureRandom    random)
-    {
-        this.size = size;
-        this.certainty = certainty;
-        this.random = random;
-    }
-
-    /**
-     * which generates the p and g values from the given parameters,
-     * returning the DHParameters object.
-     * <p>
-     * Note: can take a while...
-     */
-    public DHParameters generateParameters()
-    {
-        BigInteger      g, p, q;
-        int             qLength = size - 1;
-
-        //
-        // find a safe prime p where p = 2*q + 1, where p and q are prime.
-        //
-		for (;;)
-		{
-			q = new BigInteger(qLength, certainty, random);
-            p = q.multiply(TWO).add(ONE);
-            if (p.isProbablePrime(certainty))
-            {
-                break;
-            }
-		}
-
-		//
-		// calculate the generator g - the advantage of using the 2q+1 
-        // approach is that we know the prime factorisation of (p - 1)...
-	    //
-        for (;;)
-        {
-            g = new BigInteger(qLength, random);
-
-            if (g.modPow(TWO, p).equals(ONE))
-            {
-                continue;
-            }
-
-            if (g.modPow(q, p).equals(ONE))
-            {
-                continue;
-            }
-
-            break;
-        }
-
-        return new DHParameters(p, g, q, 2);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java
deleted file mode 100644
index e1a9655..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
-
-/**
- * a DSA key pair generator.
- *
- * This generates DSA keys in line with the method described 
- * in FIPS 186-2.
- */
-public class DSAKeyPairGenerator
-    implements AsymmetricCipherKeyPairGenerator
-{
-    private static BigInteger ZERO = BigInteger.valueOf(0);
-
-    private DSAKeyGenerationParameters param;
-
-    public void init(
-        KeyGenerationParameters param)
-    {
-        this.param = (DSAKeyGenerationParameters)param;
-    }
-
-    public AsymmetricCipherKeyPair generateKeyPair()
-    {
-        BigInteger      p, q, g, x, y;
-        DSAParameters   dsaParams = param.getParameters();
-        SecureRandom    random = param.getRandom();
-
-        q = dsaParams.getQ();
-        p = dsaParams.getP();
-        g = dsaParams.getG();
-
-        do
-        {
-            x = new BigInteger(160, random);
-        }
-        while (x.equals(ZERO)  || x.compareTo(q) >= 0);
-
-        //
-        // calculate the public key.
-        //
-        y = g.modPow(x, p);
-
-        return new AsymmetricCipherKeyPair(
-                new DSAPublicKeyParameters(y, dsaParams),
-                new DSAPrivateKeyParameters(x, dsaParams));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/DSAParametersGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
deleted file mode 100644
index d29040b..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAValidationParameters;
-
-/**
- * generate suitable parameters for DSA, in line with FIPS 186-2.
- */
-public class DSAParametersGenerator
-{
-    private int             size;
-    private int             certainty;
-    private SecureRandom    random;
-
-    private static BigInteger ONE = BigInteger.valueOf(1);
-    private static BigInteger TWO = BigInteger.valueOf(2);
-
-    /**
-     * initialise the key generator.
-     *
-     * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments)
-     * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
-     * @param random random byte source.
-     */
-    public void init(
-        int             size,
-        int             certainty,
-        SecureRandom    random)
-    {
-        this.size = size;
-        this.certainty = certainty;
-        this.random = random;
-    }
-
-    /**
-     * add value to b, returning the result in a. The a value is treated
-     * as a BigInteger of length (a.length * 8) bits. The result is
-     * modulo 2^a.length in case of overflow.
-     */
-    private void add(
-        byte[]  a,
-        byte[]  b,
-        int     value)
-    {
-        int     x = (b[b.length - 1] & 0xff) + value;
-
-        a[b.length - 1] = (byte)x;
-        x >>>= 8;
-
-        for (int i = b.length - 2; i >= 0; i--)
-        {
-            x += (b[i] & 0xff);
-            a[i] = (byte)x;
-            x >>>= 8;
-        }
-    }
-
-    /**
-     * which generates the p and g values from the given parameters,
-     * returning the DSAParameters object.
-     * <p>
-     * Note: can take a while...
-     */
-    public DSAParameters generateParameters()
-    {
-        byte[]          seed = new byte[20];
-        byte[]          part1 = new byte[20];
-        byte[]          part2 = new byte[20];
-        byte[]          u = new byte[20];
-        SHA1Digest      sha1 = new SHA1Digest();
-        int             n = (size - 1) / 160;
-        byte[]          w = new byte[size / 8];
-
-        BigInteger      q = null, p = null, g = null;
-        int             counter = 0;
-        boolean         primesFound = false;
-
-        while (!primesFound)
-        {
-            do
-            {
-                random.nextBytes(seed);
-
-                sha1.update(seed, 0, seed.length);
-
-                sha1.doFinal(part1, 0);
-
-                System.arraycopy(seed, 0, part2, 0, seed.length);
-
-                add(part2, seed, 1);
-
-                sha1.update(part2, 0, part2.length);
-
-                sha1.doFinal(part2, 0);
-
-                for (int i = 0; i != u.length; i++)
-                {
-                    u[i] = (byte)(part1[i] ^ part2[i]);
-                }
-
-                u[0] |= (byte)0x80;
-                u[19] |= (byte)0x01;
-
-                q = new BigInteger(1, u);
-            }
-            while (!q.isProbablePrime(certainty));
-
-            counter = 0;
-
-            int offset = 2;
-
-            while (counter < 4096)
-            {
-                for (int k = 0; k < n; k++)
-                {
-                    add(part1, seed, offset + k);
-                    sha1.update(part1, 0, part1.length);
-                    sha1.doFinal(part1, 0);
-                    System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length);
-                }
-
-                add(part1, seed, offset + n);
-                sha1.update(part1, 0, part1.length);
-                sha1.doFinal(part1, 0);
-                System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length);
-
-                w[0] |= (byte)0x80;
-
-                BigInteger  x = new BigInteger(1, w);
-
-                BigInteger  c = x.mod(q.multiply(TWO));
-
-                p = x.subtract(c.subtract(ONE));
-
-                if (p.testBit(size - 1))
-                {
-                    if (p.isProbablePrime(certainty))
-                    {
-                        primesFound = true;
-                        break;
-                    }
-                }
-
-                counter += 1;
-                offset += n + 1;
-            }
-		}
-
-		//
-		// calculate the generator g
-	    //
-        BigInteger  pMinusOneOverQ = p.subtract(ONE).divide(q);
-
-        for (;;)
-        {
-            BigInteger h = new BigInteger(size, random);
-            
-            if (h.compareTo(ONE) <= 0 || h.compareTo(p.subtract(ONE)) >= 0)
-            {
-                continue;
-            }
-
-            g = h.modPow(pMinusOneOverQ, p);
-            if (g.compareTo(ONE) <= 0)
-            {
-                continue;
-            }
-
-            break;
-        }
-
-        return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
deleted file mode 100644
index 6ce15ea..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECPoint;
-
-public class ECKeyPairGenerator
-    implements AsymmetricCipherKeyPairGenerator, ECConstants
-{
-	ECDomainParameters  params;
-	SecureRandom        random;
-
-	public void init(
-        KeyGenerationParameters param)
-    {
-        ECKeyGenerationParameters  ecP = (ECKeyGenerationParameters)param;
-
-        this.random = ecP.getRandom();
-        this.params = ecP.getDomainParameters();
-    }
-
-    /**
-     * Given the domain parameters this routine generates an EC key
-     * pair in accordance with X9.62 section 5.2.1 pages 26, 27.
-     */
-    public AsymmetricCipherKeyPair generateKeyPair()
-    {
-		BigInteger n = params.getN();
-		int			  nBitLength = n.bitLength();
-		BigInteger d;
-
-		do
-		{
-			d = new BigInteger(nBitLength, random);
-		}
-		while (d.equals(ZERO)  || (d.compareTo(n) >= 0));
-
-		ECPoint Q = params.getG().multiply(d);
-
-		return new AsymmetricCipherKeyPair(
-            new ECPublicKeyParameters(Q, params),
-			new ECPrivateKeyParameters(d, params));
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java
deleted file mode 100644
index 33ec23c..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters;
-import org.bouncycastle.crypto.params.ElGamalParameters;
-import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
-
-/**
- * a ElGamal key pair generator.
- * <p>
- * This generates keys consistent for use with ElGamal as described in
- * page 164 of "Handbook of Applied Cryptography".
- */
-public class ElGamalKeyPairGenerator
-    implements AsymmetricCipherKeyPairGenerator
-{
-    private ElGamalKeyGenerationParameters param;
-
-    public void init(
-        KeyGenerationParameters param)
-    {
-        this.param = (ElGamalKeyGenerationParameters)param;
-    }
-
-    public AsymmetricCipherKeyPair generateKeyPair()
-    {
-        BigInteger           p, g, x, y;
-        int                  qLength = param.getStrength() - 1;
-        ElGamalParameters    elParams = param.getParameters();
-
-        p = elParams.getP();
-        g = elParams.getG();
-    
-        //
-        // calculate the private key
-        //
-		x = new BigInteger(qLength, param.getRandom());
-
-        //
-        // calculate the public key.
-        //
-        y = g.modPow(x, p);
-
-        return new AsymmetricCipherKeyPair(
-                new ElGamalPublicKeyParameters(y, elParams),
-                new ElGamalPrivateKeyParameters(x, elParams));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java
deleted file mode 100644
index 62e63f1..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.params.ElGamalParameters;
-
-public class ElGamalParametersGenerator
-{
-    private int             size;
-    private int             certainty;
-    private SecureRandom    random;
-
-    private static BigInteger ONE = BigInteger.valueOf(1);
-    private static BigInteger TWO = BigInteger.valueOf(2);
-
-    public void init(
-        int             size,
-        int             certainty,
-        SecureRandom    random)
-    {
-        this.size = size;
-        this.certainty = certainty;
-        this.random = random;
-    }
-
-    /**
-     * which generates the p and g values from the given parameters,
-     * returning the ElGamalParameters object.
-     * <p>
-     * Note: can take a while...
-     */
-    public ElGamalParameters generateParameters()
-    {
-        BigInteger      g, p, q;
-        int             qLength = size - 1;
-
-        //
-        // find a safe prime p where p = 2*q + 1, where p and q are prime.
-        //
-		for (;;)
-		{
-			q = new BigInteger(qLength, 1, random);
-			
-			if (q.bitLength() != qLength)
-			{
-				continue;
-			}
-			
-			if (!q.isProbablePrime(certainty))
-			{
-				continue;
-			}
-			
-            p = q.multiply(TWO).add(ONE);
-            if (p.isProbablePrime(certainty))
-            {
-                break;
-            }
-		}
-
-		//
-		// calculate the generator g - the advantage of using the 2q+1 
-        // approach is that we know the prime factorisation of (p - 1)...
-	    //
-        for (;;)
-        {
-            g = new BigInteger(qLength, random);
-
-            if (g.modPow(TWO, p).equals(ONE))
-            {
-                continue;
-            }
-
-            if (g.modPow(q, p).equals(ONE))
-            {
-                continue;
-            }
-
-            break;
-        }
-
-        return new ElGamalParameters(p, g);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java
deleted file mode 100644
index cab05ac..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.Digest;
-
-/**
- * KFD2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
- * <br>
- * This implementation is based on IEEE P1363/ISO 18033.
- */
-public class KDF2BytesGenerator
-    extends BaseKDFBytesGenerator
-{
-    /**
-     * Construct a KDF2 bytes generator. Generates key material
-     * according to IEEE P1363 or ISO 18033 depending on the initialisation.
-     * <p>
-     * @param digest the digest to be used as the source of derived keys.
-     */
-    public KDF2BytesGenerator(
-        Digest  digest)
-    {
-        super(1, digest);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java
deleted file mode 100644
index 106ef10..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.DerivationFunction;
-import org.bouncycastle.crypto.DerivationParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.params.MGFParameters;
-
-/**
- * Generator for MGF1 as defined in PKCS 1v2
- */
-public class MGF1BytesGenerator
-    implements DerivationFunction
-{
-    private Digest  digest;
-    private byte[]  seed;
-    private int     hLen;
-
-    /**
-     * @param digest the digest to be used as the source of generated bytes
-     */
-    public MGF1BytesGenerator(
-        Digest  digest)
-    {
-        this.digest = digest;
-        this.hLen = digest.getDigestSize();
-    }
-
-    public void init(
-        DerivationParameters    param)
-    {
-        if (!(param instanceof MGFParameters))
-        {
-            throw new IllegalArgumentException("MGF parameters required for MGF1Generator");
-        }
-
-        MGFParameters   p = (MGFParameters)param;
-
-        seed = p.getSeed();
-    }
-
-    /**
-     * return the underlying digest.
-     */
-    public Digest getDigest()
-    {
-        return digest;
-    }
-
-    /**
-     * int to octet string.
-     */
-    private void ItoOSP(
-        int     i,
-        byte[]  sp)
-    {
-        sp[0] = (byte)(i >>> 24);
-        sp[1] = (byte)(i >>> 16);
-        sp[2] = (byte)(i >>> 8);
-        sp[3] = (byte)(i >>> 0);
-    }
-
-    /**
-     * fill len bytes of the output buffer with bytes generated from
-     * the derivation function.
-     *
-     * @throws IllegalArgumentException if the size of the request will cause an overflow.
-     * @throws DataLengthException if the out buffer is too small.
-     */
-    public int generateBytes(
-        byte[]  out,
-        int     outOff,
-        int     len)
-        throws DataLengthException, IllegalArgumentException
-    {
-        byte[]  hashBuf = new byte[hLen];
-        byte[]  C = new byte[4];
-        int     counter = 0;
-
-        digest.reset();
-
-        do
-        {
-            ItoOSP(counter, C);
-
-            digest.update(seed, 0, seed.length);
-            digest.update(C, 0, C.length);
-            digest.doFinal(hashBuf, 0);
-
-            System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, hLen);
-        }
-        while (++counter < (len / hLen));
-
-        if ((counter * hLen) < len)
-        {
-            ItoOSP(counter, C);
-
-            digest.update(seed, 0, seed.length);
-            digest.update(C, 0, C.length);
-            digest.doFinal(hashBuf, 0);
-
-            System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, len - (counter * hLen));
-        }
-
-        return len;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
deleted file mode 100644
index 8a4d28a..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.digests.MD5Digest;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Generator for PBE derived keys and ivs as usd by OpenSSL.
- * <p>
- * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
- * iteration count of 1.
- * <p>
- */
-public class OpenSSLPBEParametersGenerator
-    extends PBEParametersGenerator
-{
-    private Digest  digest = new MD5Digest();
-
-    /**
-     * Construct a OpenSSL Parameters generator. 
-     */
-    public OpenSSLPBEParametersGenerator()
-    {
-    }
-
-    /**
-     * Initialise - note the iteration count for this algorithm is fixed at 1.
-     * 
-     * @param password password to use.
-     * @param salt salt to use.
-     */
-    public void init(
-       byte[] password,
-       byte[] salt)
-    {
-        super.init(password, salt, 1);
-    }
-    
-    /**
-     * the derived key function, the ith hash of the password and the salt.
-     */
-    private byte[] generateDerivedKey(
-        int bytesNeeded)
-    {
-        byte[]  buf = new byte[digest.getDigestSize()];
-        byte[]  key = new byte[bytesNeeded];
-        int     offset = 0;
-        
-        for (;;)
-        {
-            digest.update(password, 0, password.length);
-            digest.update(salt, 0, salt.length);
-
-            digest.doFinal(buf, 0);
-            
-            int len = (bytesNeeded > buf.length) ? buf.length : bytesNeeded;
-            System.arraycopy(buf, 0, key, offset, len);
-            offset += len;
-
-            // check if we need any more
-            bytesNeeded -= len;
-            if (bytesNeeded == 0)
-            {
-                break;
-            }
-
-            // do another round
-            digest.reset();
-            digest.update(buf, 0, buf.length);
-        }
-        
-        return key;
-    }
-
-    /**
-     * Generate a key parameter derived from the password, salt, and iteration
-     * count we are currently initialised with.
-     *
-     * @param keySize the size of the key we want (in bits)
-     * @return a KeyParameter object.
-     * @exception IllegalArgumentException if the key length larger than the base hash size.
-     */
-    public CipherParameters generateDerivedParameters(
-        int keySize)
-    {
-        keySize = keySize / 8;
-
-        byte[]  dKey = generateDerivedKey(keySize);
-
-        return new KeyParameter(dKey, 0, keySize);
-    }
-
-    /**
-     * Generate a key with initialisation vector parameter derived from
-     * the password, salt, and iteration count we are currently initialised
-     * with.
-     *
-     * @param keySize the size of the key we want (in bits)
-     * @param ivSize the size of the iv we want (in bits)
-     * @return a ParametersWithIV object.
-     * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
-     */
-    public CipherParameters generateDerivedParameters(
-        int     keySize,
-        int     ivSize)
-    {
-        keySize = keySize / 8;
-        ivSize = ivSize / 8;
-
-        byte[]  dKey = generateDerivedKey(keySize + ivSize);
-
-        return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
-    }
-
-    /**
-     * Generate a key parameter for use with a MAC derived from the password,
-     * salt, and iteration count we are currently initialised with.
-     *
-     * @param keySize the size of the key we want (in bits)
-     * @return a KeyParameter object.
-     * @exception IllegalArgumentException if the key length larger than the base hash size.
-     */
-    public CipherParameters generateDerivedMacParameters(
-        int keySize)
-    {
-        return generateDerivedParameters(keySize);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java
deleted file mode 100644
index f8db28f..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java
+++ /dev/null
@@ -1,233 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.digests.MD5Digest;
-import org.bouncycastle.crypto.digests.RIPEMD160Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Generator for PBE derived keys and ivs as defined by PKCS 12 V1.0.
- * <p>
- * The document this implementation is based on can be found at
- * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-12/index.html>
- * RSA's PKCS12 Page</a>
- */
-public class PKCS12ParametersGenerator
-    extends PBEParametersGenerator
-{
-    public static final int KEY_MATERIAL = 1;
-    public static final int IV_MATERIAL  = 2;
-    public static final int MAC_MATERIAL = 3;
-
-    private Digest digest;
-
-    private int     u;
-    private int     v;
-
-    /**
-     * Construct a PKCS 12 Parameters generator. This constructor will
-     * accept MD5, SHA1, and RIPEMD160.
-     *
-     * @param digest the digest to be used as the source of derived keys.
-     * @exception IllegalArgumentException if an unknown digest is passed in.
-     */
-    public PKCS12ParametersGenerator(
-        Digest  digest)
-    {
-        this.digest = digest;
-        if (digest instanceof MD5Digest)
-        {
-            u = 128 / 8;
-            v = 512 / 8;
-        }
-        else if (digest instanceof SHA1Digest)
-        {
-            u = 160 / 8;
-            v = 512 / 8;
-        }
-        else if (digest instanceof RIPEMD160Digest)
-        {
-            u = 160 / 8;
-            v = 512 / 8;
-        }
-        else
-        {
-            throw new IllegalArgumentException("Digest " + digest.getAlgorithmName() + " unsupported");
-        }
-    }
-
-    /**
-     * add a + b + 1, returning the result in a. The a value is treated
-     * as a BigInteger of length (b.length * 8) bits. The result is 
-     * modulo 2^b.length in case of overflow.
-     */
-    private void adjust(
-        byte[]  a,
-        int     aOff,
-        byte[]  b)
-    {
-        int  x = (b[b.length - 1] & 0xff) + (a[aOff + b.length - 1] & 0xff) + 1;
-
-        a[aOff + b.length - 1] = (byte)x;
-        x >>>= 8;
-
-        for (int i = b.length - 2; i >= 0; i--)
-        {
-            x += (b[i] & 0xff) + (a[aOff + i] & 0xff);
-            a[aOff + i] = (byte)x;
-            x >>>= 8;
-        }
-    }
-
-    /**
-     * generation of a derived key ala PKCS12 V1.0.
-     */
-    private byte[] generateDerivedKey(
-        int idByte,
-        int n)
-    {
-        byte[]  D = new byte[v];
-        byte[]  dKey = new byte[n];
-
-        for (int i = 0; i != D.length; i++)
-        {
-            D[i] = (byte)idByte;
-        }
-
-        byte[]  S;
-
-        if ((salt != null) && (salt.length != 0))
-        {
-            S = new byte[v * ((salt.length + v - 1) / v)];
-
-            for (int i = 0; i != S.length; i++)
-            {
-                S[i] = salt[i % salt.length];
-            }
-        }
-        else
-        {
-            S = new byte[0];
-        }
-
-        byte[]  P;
-
-        if ((password != null) && (password.length != 0))
-        {
-            P = new byte[v * ((password.length + v - 1) / v)];
-
-            for (int i = 0; i != P.length; i++)
-            {
-                P[i] = password[i % password.length];
-            }
-        }
-        else
-        {
-            P = new byte[0];
-        }
-
-        byte[]  I = new byte[S.length + P.length];
-
-        System.arraycopy(S, 0, I, 0, S.length);
-        System.arraycopy(P, 0, I, S.length, P.length);
-
-        byte[]  B = new byte[v];
-        int     c = (n + u - 1) / u;
-
-        for (int i = 1; i <= c; i++)
-        {
-            byte[]  A = new byte[u];
-
-            digest.update(D, 0, D.length);
-            digest.update(I, 0, I.length);
-            digest.doFinal(A, 0);
-            for (int j = 1; j != iterationCount; j++)
-            {
-                digest.update(A, 0, A.length);
-                digest.doFinal(A, 0);
-            }
-
-            for (int j = 0; j != B.length; j++)
-            {
-                B[j] = A[j % A.length];
-            }
-
-            for (int j = 0; j != I.length / v; j++)
-            {
-                adjust(I, j * v, B);
-            }
-
-            if (i == c)
-            {
-                System.arraycopy(A, 0, dKey, (i - 1) * u, dKey.length - ((i - 1) * u));
-            }
-            else
-            {
-                System.arraycopy(A, 0, dKey, (i - 1) * u, A.length);
-            }
-        }
-
-        return dKey;
-    }
-
-    /**
-     * Generate a key parameter derived from the password, salt, and iteration
-     * count we are currently initialised with.
-     *
-     * @param keySize the size of the key we want (in bits)
-     * @return a KeyParameter object.
-     */
-    public CipherParameters generateDerivedParameters(
-        int keySize)
-    {
-        keySize = keySize / 8;
-
-        byte[]  dKey = generateDerivedKey(KEY_MATERIAL, keySize);
-
-        return new KeyParameter(dKey, 0, keySize);
-    }
-
-    /**
-     * Generate a key with initialisation vector parameter derived from
-     * the password, salt, and iteration count we are currently initialised
-     * with.
-     *
-     * @param keySize the size of the key we want (in bits)
-     * @param ivSize the size of the iv we want (in bits)
-     * @return a ParametersWithIV object.
-     */
-    public CipherParameters generateDerivedParameters(
-        int     keySize,
-        int     ivSize)
-    {
-        keySize = keySize / 8;
-        ivSize = ivSize / 8;
-
-        byte[]  dKey = generateDerivedKey(KEY_MATERIAL, keySize);
-
-        byte[]  iv = generateDerivedKey(IV_MATERIAL, ivSize);
-
-        return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), iv, 0, ivSize);
-    }
-
-    /**
-     * Generate a key parameter for use with a MAC derived from the password,
-     * salt, and iteration count we are currently initialised with.
-     *
-     * @param keySize the size of the key we want (in bits)
-     * @return a KeyParameter object.
-     */
-    public CipherParameters generateDerivedMacParameters(
-        int keySize)
-    {
-        keySize = keySize / 8;
-
-        byte[]  dKey = generateDerivedKey(MAC_MATERIAL, keySize);
-
-        return new KeyParameter(dKey, 0, keySize);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java
deleted file mode 100644
index 1c62ecc..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 1.
- * Note this generator is limited to the size of the hash produced by the
- * digest used to drive it.
- * <p>
- * The document this implementation is based on can be found at
- * <a href=http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html>
- * RSA's PKCS5 Page</a>
- */
-public class PKCS5S1ParametersGenerator
-    extends PBEParametersGenerator
-{
-    private Digest  digest;
-
-    /**
-     * Construct a PKCS 5 Scheme 1 Parameters generator. 
-     *
-     * @param digest the digest to be used as the source of derived keys.
-     */
-    public PKCS5S1ParametersGenerator(
-        Digest  digest)
-    {
-        this.digest = digest;
-    }
-
-    /**
-     * the derived key function, the ith hash of the password and the salt.
-     */
-    private byte[] generateDerivedKey()
-    {
-        byte[] digestBytes = new byte[digest.getDigestSize()];
-
-        digest.update(password, 0, password.length);
-        digest.update(salt, 0, salt.length);
-
-        digest.doFinal(digestBytes, 0);
-        for (int i = 1; i < iterationCount; i++)
-        {
-            digest.update(digestBytes, 0, digestBytes.length);
-            digest.doFinal(digestBytes, 0);
-        }
-
-        return digestBytes;
-    }
-
-    /**
-     * Generate a key parameter derived from the password, salt, and iteration
-     * count we are currently initialised with.
-     *
-     * @param keySize the size of the key we want (in bits)
-     * @return a KeyParameter object.
-     * @exception IllegalArgumentException if the key length larger than the base hash size.
-     */
-    public CipherParameters generateDerivedParameters(
-        int keySize)
-    {
-        keySize = keySize / 8;
-
-        if (keySize > digest.getDigestSize())
-        {
-            throw new IllegalArgumentException(
-                   "Can't generate a derived key " + keySize + " bytes long.");
-        }
-
-        byte[]  dKey = generateDerivedKey();
-
-        return new KeyParameter(dKey, 0, keySize);
-    }
-
-    /**
-     * Generate a key with initialisation vector parameter derived from
-     * the password, salt, and iteration count we are currently initialised
-     * with.
-     *
-     * @param keySize the size of the key we want (in bits)
-     * @param ivSize the size of the iv we want (in bits)
-     * @return a ParametersWithIV object.
-     * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
-     */
-    public CipherParameters generateDerivedParameters(
-        int     keySize,
-        int     ivSize)
-    {
-        keySize = keySize / 8;
-        ivSize = ivSize / 8;
-
-        if ((keySize + ivSize) > digest.getDigestSize())
-        {
-            throw new IllegalArgumentException(
-                   "Can't generate a derived key " + (keySize + ivSize) + " bytes long.");
-        }
-
-        byte[]  dKey = generateDerivedKey();
-
-        return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
-    }
-
-    /**
-     * Generate a key parameter for use with a MAC derived from the password,
-     * salt, and iteration count we are currently initialised with.
-     *
-     * @param keySize the size of the key we want (in bits)
-     * @return a KeyParameter object.
-     * @exception IllegalArgumentException if the key length larger than the base hash size.
-     */
-    public CipherParameters generateDerivedMacParameters(
-        int keySize)
-    {
-        return generateDerivedParameters(keySize);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java b/azureus2/src/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
deleted file mode 100644
index 8c33c01..0000000
--- a/azureus2/src/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
-import org.bouncycastle.crypto.KeyGenerationParameters;
-import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-
-/**
- * an RSA key pair generator.
- */
-public class RSAKeyPairGenerator
-    implements AsymmetricCipherKeyPairGenerator
-{
-    private static BigInteger ONE = BigInteger.valueOf(1);
-
-    private RSAKeyGenerationParameters param;
-
-    public void init(
-        KeyGenerationParameters param)
-    {
-        this.param = (RSAKeyGenerationParameters)param;
-    }
-
-    public AsymmetricCipherKeyPair generateKeyPair()
-    {
-        BigInteger    p, q, n, d, e, pSub1, qSub1, phi;
-
-        //
-        // p and q values should have a length of half the strength in bits
-        //
-        int pbitlength = (param.getStrength() + 1) / 2;
-		int qbitlength = (param.getStrength() - pbitlength);
-		e = param.getPublicExponent();
-
-        //
-        // generate p, prime and (p-1) relatively prime to e
-        //
-		for (;;)
-		{
-			p = new BigInteger(pbitlength, 1, param.getRandom());
-			
-			if (p.mod(e).equals(ONE))
-			{
-				continue;
-			}
-			
-			if (!p.isProbablePrime(param.getCertainty()))
-			{
-				continue;
-			}
-			
-			if (e.gcd(p.subtract(ONE)).equals(ONE)) 
-			{
-				break;
-			}
-		}
-
-        //
-        // generate a modulus of the required length
-		//
-        for (;;)
-        {
-		    // generate q, prime and (q-1) relatively prime to e,
-		    // and not equal to p
-		    //
-            for (;;)
-            {
-                q = new BigInteger(qbitlength, 1, param.getRandom());
-                
-                if (q.equals(p))
-                {
-                	continue;
-                }
-                
-				if (q.mod(e).equals(ONE))
-				{
-					continue;
-				}
-			
-				if (!q.isProbablePrime(param.getCertainty()))
-				{
-					continue;
-				}
-			
-			    if (e.gcd(q.subtract(ONE)).equals(ONE)) 
-			    {
-			    	break;
-			    } 
-            }
-
-            //
-            // calculate the modulus
-            //
-            n = p.multiply(q);
-
-            if (n.bitLength() == param.getStrength()) 
-            {
-            	break;
-            } 
-
-            //
-            // if we get here our primes aren't big enough, make the largest
-            // of the two p and try again
-            //
-            p = p.max(q);
-        }
-
-        if (p.compareTo(q) < 0)
-        {
-            phi = p;
-            p = q;
-            q = phi;
-        }
-
-        pSub1 = p.subtract(ONE);
-        qSub1 = q.subtract(ONE);
-        phi = pSub1.multiply(qSub1);
-
-        //
-        // calculate the private exponent
-        //
-        d = e.modInverse(phi);
-
-        //
-        // calculate the CRT factors
-        //
-        BigInteger    dP, dQ, qInv;
-
-        dP = d.remainder(pSub1);
-        dQ = d.remainder(qSub1);
-        qInv = q.modInverse(p);
-
-        return new AsymmetricCipherKeyPair(
-                new RSAKeyParameters(false, n, e),
-                new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/macs/HMac.java b/azureus2/src/org/bouncycastle/crypto/macs/HMac.java
deleted file mode 100644
index a3a6dda..0000000
--- a/azureus2/src/org/bouncycastle/crypto/macs/HMac.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package org.bouncycastle.crypto.macs;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.Mac;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-/**
- * HMAC implementation based on RFC2104
- *
- * H(K XOR opad, H(K XOR ipad, text))
- */
-public class HMac
-implements Mac
-{
-	private final static int BLOCK_LENGTH = 64;
-
-	private final static byte IPAD = (byte)0x36;
-	private final static byte OPAD = (byte)0x5C;
-
-	private Digest digest;
-	private int digestSize;
-    private byte[] inputPad = new byte[BLOCK_LENGTH];
-	private byte[] outputPad = new byte[BLOCK_LENGTH];
-
-	public HMac(
-		Digest digest)
-	{
-		this.digest = digest;
-		digestSize = digest.getDigestSize();
-	}
-
-	public String getAlgorithmName()
-	{
-		return digest.getAlgorithmName() + "/HMAC";
-	}
-
-    public Digest getUnderlyingDigest()
-    {
-        return digest;
-    }
-
-	public void init(
-		CipherParameters params)
-	{
-		digest.reset();
-
-		byte[] key = ((KeyParameter)params).getKey();
-
-		if (key.length > BLOCK_LENGTH)
-		{
-			digest.update(key, 0, key.length);
-			digest.doFinal(inputPad, 0);
-		    for (int i = digestSize; i < inputPad.length; i++)
-            {
-                inputPad[i] = 0;
-            }
-		}
-		else
-		{
-			System.arraycopy(key, 0, inputPad, 0, key.length);
-		    for (int i = key.length; i < inputPad.length; i++)
-            {
-                inputPad[i] = 0;
-            }
-		}
-
-		outputPad = new byte[inputPad.length];
-        System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length);
-
-		for (int i = 0; i < inputPad.length; i++)
-		{
-			inputPad[i] ^= IPAD;
-		}
-
-		for (int i = 0; i < outputPad.length; i++)
-		{
-			outputPad[i] ^= OPAD;
-		}
-
-		digest.update(inputPad, 0, inputPad.length);
-	}
-
-	public int getMacSize()
-	{
-		return digestSize;
-	}
-
-	public void update(
-		byte in)
-	{
-		digest.update(in);
-	}
-
-	public void update(
-		byte[] in,
-		int inOff,
-		int len)
-	{
-		digest.update(in, inOff, len);
-	}
-
-	public int doFinal(
-		byte[] out,
-		int outOff)
-	{
-		byte[] tmp = new byte[digestSize];
-		digest.doFinal(tmp, 0);
-
-		digest.update(outputPad, 0, outputPad.length);
-		digest.update(tmp, 0, tmp.length);
-
-        int     len = digest.doFinal(out, outOff);
-
-        reset();
-
-		return len;
-	}
-
-	/**
-	 * Reset the mac generator.
-	 */
-	public void reset()
-	{
-		/*
-		 * reset the underlying digest.
-		 */
-		digest.reset();
-
-        /*
-         * reinitialize the digest.
-         */
-		digest.update(inputPad, 0, inputPad.length);
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/modes/CBCBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/modes/CBCBlockCipher.java
deleted file mode 100644
index 2a197d7..0000000
--- a/azureus2/src/org/bouncycastle/crypto/modes/CBCBlockCipher.java
+++ /dev/null
@@ -1,233 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher.
- */
-public class CBCBlockCipher
-    implements BlockCipher
-{
-	private byte[]          IV;
-	private byte[]          cbcV;
-	private byte[]          cbcNextV;
-
-    private int             blockSize;
-    private BlockCipher     cipher = null;
-    private boolean         encrypting;
-
-    /**
-     * Basic constructor.
-     *
-     * @param cipher the block cipher to be used as the basis of chaining.
-     */
-    public CBCBlockCipher(
-        BlockCipher cipher)
-    {
-        this.cipher = cipher;
-        this.blockSize = cipher.getBlockSize();
-
-        this.IV = new byte[blockSize];
-        this.cbcV = new byte[blockSize];
-        this.cbcNextV = new byte[blockSize];
-    }
-
-    /**
-     * return the underlying block cipher that we are wrapping.
-     *
-     * @return the underlying block cipher that we are wrapping.
-     */
-    public BlockCipher getUnderlyingCipher()
-    {
-        return cipher;
-    }
-
-    /**
-     * Initialise the cipher and, possibly, the initialisation vector (IV).
-     * If an IV isn't passed as part of the parameter, the IV will be all zeros.
-     *
-     * @param forEncryption if true the cipher is initialised for
-     *  encryption, if false for decryption.
-     * @param param the key and other data required by the cipher.
-     * @exception IllegalArgumentException if the params argument is
-     * inappropriate.
-     */
-    public void init(
-        boolean             encrypting,
-        CipherParameters    params)
-        throws IllegalArgumentException
-    {
-        this.encrypting = encrypting;
-        
-        if (params instanceof ParametersWithIV)
-        {
-                ParametersWithIV ivParam = (ParametersWithIV)params;
-                byte[]      iv = ivParam.getIV();
-
-                if (iv.length != blockSize)
-                {
-                    throw new IllegalArgumentException("initialisation vector must be the same length as block size");
-                }
-
-                System.arraycopy(iv, 0, IV, 0, iv.length);
-
-                reset();
-
-                cipher.init(encrypting, ivParam.getParameters());
-        }
-        else
-        {
-                reset();
-
-                cipher.init(encrypting, params);
-        }
-    }
-
-    /**
-     * return the algorithm name and mode.
-     *
-     * @return the name of the underlying algorithm followed by "/CBC".
-     */
-    public String getAlgorithmName()
-    {
-        return cipher.getAlgorithmName() + "/CBC";
-    }
-
-    /**
-     * return the block size of the underlying cipher.
-     *
-     * @return the block size of the underlying cipher.
-     */
-    public int getBlockSize()
-    {
-        return cipher.getBlockSize();
-    }
-
-    /**
-     * Process one block of input from the array in and write it to
-     * the out array.
-     *
-     * @param in the array containing the input data.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the output data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    public int processBlock(
-        byte[]      in,
-        int         inOff,
-        byte[]      out,
-        int         outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
-    }
-
-    /**
-     * reset the chaining vector back to the IV and reset the underlying
-     * cipher.
-     */
-    public void reset()
-    {
-        System.arraycopy(IV, 0, cbcV, 0, IV.length);
-
-        cipher.reset();
-    }
-
-    /**
-     * Do the appropriate chaining step for CBC mode encryption.
-     *
-     * @param in the array containing the data to be encrypted.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the encrypted data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    private int encryptBlock(
-        byte[]      in,
-        int         inOff,
-        byte[]      out,
-        int         outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        /*
-         * XOR the cbcV and the input,
-         * then encrypt the cbcV
-         */
-        for (int i = 0; i < blockSize; i++)
-        {
-            cbcV[i] ^= in[inOff + i];
-        }
-
-        int length = cipher.processBlock(cbcV, 0, out, outOff);
-
-        /*
-         * copy ciphertext to cbcV
-         */
-        System.arraycopy(out, outOff, cbcV, 0, cbcV.length);
-
-        return length;
-    }
-
-    /**
-     * Do the appropriate chaining step for CBC mode decryption.
-     *
-     * @param in the array containing the data to be decrypted.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the decrypted data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    private int decryptBlock(
-        byte[]      in,
-        int         inOff,
-        byte[]      out,
-        int         outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        System.arraycopy(in, inOff, cbcNextV, 0, blockSize);
-
-        int length = cipher.processBlock(in, inOff, out, outOff);
-
-        /*
-         * XOR the cbcV and the output
-         */
-        for (int i = 0; i < blockSize; i++)
-        {
-            out[outOff + i] ^= cbcV[i];
-        }
-
-        /*
-         * swap the back up buffer into next position
-         */
-        byte[]  tmp;
-
-        tmp = cbcV;
-        cbcV = cbcNextV;
-        cbcNextV = tmp;
-
-		return length;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/modes/CFBBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/modes/CFBBlockCipher.java
deleted file mode 100644
index 8b321e4..0000000
--- a/azureus2/src/org/bouncycastle/crypto/modes/CFBBlockCipher.java
+++ /dev/null
@@ -1,250 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
- */
-public class CFBBlockCipher
-    implements BlockCipher
-{
-	private byte[]          IV;
-	private byte[]          cfbV;
-	private byte[]          cfbOutV;
-
-    private int             blockSize;
-    private BlockCipher     cipher = null;
-    private boolean         encrypting;
-
-    /**
-     * Basic constructor.
-     *
-     * @param cipher the block cipher to be used as the basis of the
-     * feedback mode.
-     * @param blockSize the block size in bits (note: a multiple of 8)
-     */
-    public CFBBlockCipher(
-        BlockCipher cipher,
-        int         bitBlockSize)
-    {
-        this.cipher = cipher;
-        this.blockSize = bitBlockSize / 8;
-
-        this.IV = new byte[cipher.getBlockSize()];
-        this.cfbV = new byte[cipher.getBlockSize()];
-        this.cfbOutV = new byte[cipher.getBlockSize()];
-    }
-
-    /**
-     * return the underlying block cipher that we are wrapping.
-     *
-     * @return the underlying block cipher that we are wrapping.
-     */
-    public BlockCipher getUnderlyingCipher()
-    {
-        return cipher;
-    }
-
-    /**
-     * Initialise the cipher and, possibly, the initialisation vector (IV).
-     * If an IV isn't passed as part of the parameter, the IV will be all zeros.
-     * An IV which is too short is handled in FIPS compliant fashion.
-     *
-     * @param forEncryption if true the cipher is initialised for
-     *  encryption, if false for decryption.
-     * @param param the key and other data required by the cipher.
-     * @exception IllegalArgumentException if the params argument is
-     * inappropriate.
-     */
-    public void init(
-        boolean             encrypting,
-        CipherParameters    params)
-        throws IllegalArgumentException
-    {
-        this.encrypting = encrypting;
-        
-        if (params instanceof ParametersWithIV)
-        {
-                ParametersWithIV ivParam = (ParametersWithIV)params;
-                byte[]      iv = ivParam.getIV();
-
-                if (iv.length < IV.length)
-                {
-					// prepend the supplied IV with zeros (per FIPS PUB 81)
-                    System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
-					for (int i = 0; i < IV.length - iv.length; i++)
-					{
-						IV[i] = 0;
-					}
-                }
-                else
-                {
-                    System.arraycopy(iv, 0, IV, 0, IV.length);
-                }
-
-                reset();
-
-                cipher.init(true, ivParam.getParameters());
-        }
-        else
-        {
-                reset();
-
-                cipher.init(true, params);
-        }
-    }
-
-    /**
-     * return the algorithm name and mode.
-     *
-     * @return the name of the underlying algorithm followed by "/CFB"
-     * and the block size in bits.
-     */
-    public String getAlgorithmName()
-    {
-        return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8);
-    }
-
-    /**
-     * return the block size we are operating at.
-     *
-     * @return the block size we are operating at (in bytes).
-     */
-    public int getBlockSize()
-    {
-        return blockSize;
-    }
-
-    /**
-     * Process one block of input from the array in and write it to
-     * the out array.
-     *
-     * @param in the array containing the input data.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the output data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    public int processBlock(
-        byte[]      in,
-        int         inOff,
-        byte[]      out,
-        int         outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
-    }
-
-    /**
-     * Do the appropriate processing for CFB mode encryption.
-     *
-     * @param in the array containing the data to be encrypted.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the encrypted data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    public int encryptBlock(
-        byte[]      in,
-        int         inOff,
-        byte[]      out,
-        int         outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        if ((outOff + blockSize) > out.length)
-        {
-            throw new DataLengthException("output buffer too short");
-        }
-
-        cipher.processBlock(cfbV, 0, cfbOutV, 0);
-
-        //
-        // XOR the cfbV with the plaintext producing the cipher text
-        //
-        for (int i = 0; i < blockSize; i++)
-        {
-            out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]);
-        }
-
-        //
-        // change over the input block.
-        //
-        System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
-        System.arraycopy(out, outOff, cfbV, cfbV.length - blockSize, blockSize);
-
-        return blockSize;
-    }
-
-    /**
-     * Do the appropriate processing for CFB mode decryption.
-     *
-     * @param in the array containing the data to be decrypted.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the encrypted data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    public int decryptBlock(
-        byte[]      in,
-        int         inOff,
-        byte[]      out,
-        int         outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        if ((outOff + blockSize) > out.length)
-        {
-            throw new DataLengthException("output buffer too short");
-        }
-
-        cipher.processBlock(cfbV, 0, cfbOutV, 0);
-
-        //
-        // change over the input block.
-        //
-        System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
-        System.arraycopy(in, inOff, cfbV, cfbV.length - blockSize, blockSize);
-
-        //
-        // XOR the cfbV with the plaintext producing the plain text
-        //
-        for (int i = 0; i < blockSize; i++)
-        {
-            out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]);
-        }
-
-        return blockSize;
-    }
-
-    /**
-     * reset the chaining vector back to the IV and reset the underlying
-     * cipher.
-     */
-    public void reset()
-    {
-        System.arraycopy(IV, 0, cfbV, 0, IV.length);
-
-        cipher.reset();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/modes/CTSBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/modes/CTSBlockCipher.java
deleted file mode 100644
index 30ba4cb..0000000
--- a/azureus2/src/org/bouncycastle/crypto/modes/CTSBlockCipher.java
+++ /dev/null
@@ -1,260 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-
-/**
- * A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
- * be used to produce cipher text which is the same length as the plain text.
- */
-public class CTSBlockCipher
-    extends BufferedBlockCipher
-{
-    private int     blockSize;
-
-    /**
-     * Create a buffered block cipher that uses Cipher Text Stealing
-     *
-     * @param cipher the underlying block cipher this buffering object wraps.
-     */
-	public CTSBlockCipher(
-        BlockCipher     cipher)
-	{
-        if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher))
-        {
-            throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers");
-        }
-
-        this.cipher = cipher;
-
-        blockSize = cipher.getBlockSize();
-
-        buf = new byte[blockSize * 2];
-        bufOff = 0;
-	}
-
-    /**
-     * return the size of the output buffer required for an update 
-     * an input of len bytes.
-     *
-     * @param len the length of the input.
-     * @return the space required to accommodate a call to update
-     * with len bytes of input.
-     */
-    public int getUpdateOutputSize(
-        int len)
-    {
-        int total       = len + bufOff;
-        int leftOver    = total % buf.length;
-
-        if (leftOver == 0)
-        {
-            return total - buf.length;
-        }
-
-        return total - leftOver;
-    }
-
-    /**
-     * return the size of the output buffer required for an update plus a
-     * doFinal with an input of len bytes.
-     *
-     * @param len the length of the input.
-     * @return the space required to accommodate a call to update and doFinal
-     * with len bytes of input.
-     */
-    public int getOutputSize(
-        int len)
-    {
-        return len + bufOff;
-    }
-
-    /**
-     * process a single byte, producing an output block if neccessary.
-     *
-     * @param in the input byte.
-     * @param out the space for any output that might be produced.
-     * @param outOff the offset from which the output will be copied.
-     * @return the number of output bytes copied to out.
-     * @exception DataLengthException if there isn't enough space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     */
-	public int processByte(
-        byte        in,
-		byte[]      out,
-		int         outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        int         resultLen = 0;
-
-        if (bufOff == buf.length)
-        {
-            resultLen = cipher.processBlock(buf, 0, out, outOff);
-            System.arraycopy(buf, blockSize, buf, 0, blockSize);
-
-            bufOff = blockSize;
-        }
-
-        buf[bufOff++] = in;
-
-        return resultLen;
-    }
-
-    /**
-     * process an array of bytes, producing output if necessary.
-     *
-     * @param in the input byte array.
-     * @param inOff the offset at which the input data starts.
-     * @param len the number of bytes to be copied out of the input array.
-     * @param out the space for any output that might be produced.
-     * @param outOff the offset from which the output will be copied.
-     * @return the number of output bytes copied to out.
-     * @exception DataLengthException if there isn't enough space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     */
-	public int processBytes(
-		byte[]      in,
-		int         inOff,
-		int         len,
-		byte[]      out,
-		int         outOff)
-        throws DataLengthException, IllegalStateException
-	{
-        if (len < 0)
-        {
-            throw new IllegalArgumentException("Can't have a negative input length!");
-        }
-
-        int blockSize   = getBlockSize();
-        int length      = getUpdateOutputSize(len);
-        
-        if (length > 0)
-        {
-            if ((outOff + length) > out.length)
-            {
-                throw new DataLengthException("output buffer too short");
-            }
-        }
-
-		int resultLen = 0;
-        int gapLen = buf.length - bufOff;
-
-        if (len > gapLen)
-        {
-            System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
-            resultLen += cipher.processBlock(buf, 0, out, outOff);
-            System.arraycopy(buf, blockSize, buf, 0, blockSize);
-
-            bufOff = blockSize;
-
-            len -= gapLen;
-            inOff += gapLen;
-
-            while (len > blockSize)
-            {
-                System.arraycopy(in, inOff, buf, bufOff, blockSize);
-                resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
-                System.arraycopy(buf, blockSize, buf, 0, blockSize);
-
-                len -= blockSize;
-                inOff += blockSize;
-            }
-        }
-
-        System.arraycopy(in, inOff, buf, bufOff, len);
-
-        bufOff += len;
-
-        return resultLen;
-	}
-
-    /**
-     * Process the last block in the buffer.
-     *
-     * @param out the array the block currently being held is copied into.
-     * @param outOff the offset at which the copying starts.
-     * @return the number of output bytes copied to out.
-     * @exception DataLengthException if there is insufficient space in out for
-     * the output.
-     * @exception IllegalStateException if the underlying cipher is not
-     * initialised.
-     * @exception InvalidCipherTextException if cipher text decrypts wrongly (in
-     * case the exception will never get thrown).
-     */
-	public int doFinal(
-        byte[]  out,
-        int     outOff)
-        throws DataLengthException, IllegalStateException, InvalidCipherTextException
-	{
-        if (bufOff + outOff > out.length)
-        {
-            throw new DataLengthException("output buffer to small in doFinal");
-        }
-
-        int     blockSize = cipher.getBlockSize();
-        int     len = bufOff - blockSize;
-        byte[]  block = new byte[blockSize];
-
-        if (forEncryption)
-        {
-            cipher.processBlock(buf, 0, block, 0);
-
-            for (int i = bufOff; i != buf.length; i++)
-            {
-                buf[i] = block[i - blockSize];
-            }
-
-            for (int i = blockSize; i != bufOff; i++)
-            {
-                buf[i] ^= block[i - blockSize];
-            }
-
-            if (cipher instanceof CBCBlockCipher)
-            {
-                BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
-
-                c.processBlock(buf, blockSize, out, outOff);
-            }
-            else
-            {
-                cipher.processBlock(buf, blockSize, out, outOff);
-            }
-
-            System.arraycopy(block, 0, out, outOff + blockSize, len);
-        }
-        else
-        {
-            byte[]  lastBlock = new byte[blockSize];
-
-            if (cipher instanceof CBCBlockCipher)
-            {
-                BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
-
-                c.processBlock(buf, 0, block, 0);
-            }
-            else
-            {
-                cipher.processBlock(buf, 0, block, 0);
-            }
-
-            for (int i = blockSize; i != bufOff; i++)
-            {
-                lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
-            }
-
-            System.arraycopy(buf, blockSize, block, 0, len);
-
-            cipher.processBlock(block, 0, out, outOff);
-            System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
-        }
-
-        int offset = bufOff;
-
-        reset();
-
-		return offset;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/modes/OFBBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/modes/OFBBlockCipher.java
deleted file mode 100644
index b8d9756..0000000
--- a/azureus2/src/org/bouncycastle/crypto/modes/OFBBlockCipher.java
+++ /dev/null
@@ -1,182 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * implements a Output-FeedBack (OFB) mode on top of a simple cipher.
- */
-public class OFBBlockCipher
-    implements BlockCipher
-{
-	private byte[]          IV;
-	private byte[]          ofbV;
-	private byte[]          ofbOutV;
-
-    private int             blockSize;
-    private BlockCipher     cipher = null;
-    private boolean         encrypting;
-
-    /**
-     * Basic constructor.
-     *
-     * @param cipher the block cipher to be used as the basis of the
-     * feedback mode.
-     * @param blockSize the block size in bits (note: a multiple of 8)
-     */
-    public OFBBlockCipher(
-        BlockCipher cipher,
-        int         blockSize)
-    {
-        this.cipher = cipher;
-        this.blockSize = blockSize / 8;
-
-        this.IV = new byte[cipher.getBlockSize()];
-        this.ofbV = new byte[cipher.getBlockSize()];
-        this.ofbOutV = new byte[cipher.getBlockSize()];
-    }
-
-    /**
-     * return the underlying block cipher that we are wrapping.
-     *
-     * @return the underlying block cipher that we are wrapping.
-     */
-    public BlockCipher getUnderlyingCipher()
-    {
-        return cipher;
-    }
-
-    /**
-     * Initialise the cipher and, possibly, the initialisation vector (IV).
-     * If an IV isn't passed as part of the parameter, the IV will be all zeros.
-     * An IV which is too short is handled in FIPS compliant fashion.
-     *
-     * @param forEncryption if true the cipher is initialised for
-     *  encryption, if false for decryption.
-     * @param param the key and other data required by the cipher.
-     * @exception IllegalArgumentException if the params argument is
-     * inappropriate.
-     */
-    public void init(
-        boolean             encrypting,
-        CipherParameters    params)
-        throws IllegalArgumentException
-    {
-        this.encrypting = encrypting;
-        
-        if (params instanceof ParametersWithIV)
-        {
-                ParametersWithIV ivParam = (ParametersWithIV)params;
-                byte[]      iv = ivParam.getIV();
-
-                if (iv.length < IV.length)
-                {
-					// prepend the supplied IV with zeros (per FIPS PUB 81)
-                    System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length); 
-					for (int i = 0; i < IV.length - iv.length; i++)
-					{
-						IV[i] = 0;
-					}
-                }
-                else
-                {
-                    System.arraycopy(iv, 0, IV, 0, IV.length);
-                }
-
-                reset();
-
-                cipher.init(true, ivParam.getParameters());
-        }
-        else
-        {
-                reset();
-
-                cipher.init(true, params);
-        }
-    }
-
-    /**
-     * return the algorithm name and mode.
-     *
-     * @return the name of the underlying algorithm followed by "/OFB"
-     * and the block size in bits
-     */
-    public String getAlgorithmName()
-    {
-        return cipher.getAlgorithmName() + "/OFB" + (blockSize * 8);
-    }
-
-    
-    /**
-     * return the block size we are operating at (in bytes).
-     *
-     * @return the block size we are operating at (in bytes).
-     */
-    public int getBlockSize()
-    {
-        return blockSize;
-    }
-
-    /**
-     * Process one block of input from the array in and write it to
-     * the out array.
-     *
-     * @param in the array containing the input data.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the output data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    public int processBlock(
-        byte[]      in,
-        int         inOff,
-        byte[]      out,
-        int         outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        if ((outOff + blockSize) > out.length)
-        {
-            throw new DataLengthException("output buffer too short");
-        }
-
-        cipher.processBlock(ofbV, 0, ofbOutV, 0);
-
-        //
-        // XOR the ofbV with the plaintext producing the cipher text (and
-        // the next input block).
-        //
-        for (int i = 0; i < blockSize; i++)
-        {
-            out[outOff + i] = (byte)(ofbOutV[i] ^ in[inOff + i]);
-        }
-
-        //
-        // change over the input block.
-        //
-        System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize);
-        System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize);
-
-        return blockSize;
-    }
-
-    /**
-     * reset the feedback vector back to the IV and reset the underlying
-     * cipher.
-     */
-    public void reset()
-    {
-        System.arraycopy(IV, 0, ofbV, 0, IV.length);
-
-        cipher.reset();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java
deleted file mode 100644
index a8c8c7b..0000000
--- a/azureus2/src/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java
+++ /dev/null
@@ -1,322 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-
-/**
- * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode
- * on top of a simple cipher. This class assumes the IV has been prepended
- * to the data stream already, and just accomodates the reset after
- * (blockSize + 2) bytes have been read.
- * <p>
- * For further info see <a href="http://www.ietf.org/rfc/rfc2440.html">RFC 2440</a>.
- */
-public class OpenPGPCFBBlockCipher
-    implements BlockCipher
-{
-    private byte[] IV;
-    private byte[] FR;
-    private byte[] FRE;
-    private byte[] tmp;
-
-    private BlockCipher cipher;
-
-    private int count;
-    private int blockSize;
-    private boolean forEncryption;
-    
-    /**
-     * Basic constructor.
-     *
-     * @param cipher the block cipher to be used as the basis of the
-     * feedback mode.
-     */
-    public OpenPGPCFBBlockCipher(
-        BlockCipher cipher)
-    {
-        this.cipher = cipher;
-
-        this.blockSize = cipher.getBlockSize();
-        this.IV = new byte[blockSize];
-        this.FR = new byte[blockSize];
-        this.FRE = new byte[blockSize];
-        this.tmp = new byte[blockSize];
-    }
-
-    /**
-     * return the underlying block cipher that we are wrapping.
-     *
-     * @return the underlying block cipher that we are wrapping.
-     */
-    public BlockCipher getUnderlyingCipher()
-    {
-        return cipher;
-    }
-    
-    /**
-     * return the algorithm name and mode.
-     *
-     * @return the name of the underlying algorithm followed by "/PGPCFB"
-     * and the block size in bits.
-     */
-    public String getAlgorithmName()
-    {
-        return cipher.getAlgorithmName() + "/OpenPGPCFB";
-    }
-    
-    /**
-     * return the block size we are operating at.
-     *
-     * @return the block size we are operating at (in bytes).
-     */
-    public int getBlockSize()
-    {
-        return cipher.getBlockSize();
-    }
-
-    /**
-     * Process one block of input from the array in and write it to
-     * the out array.
-     *
-     * @param in the array containing the input data.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the output data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    public int processBlock(
-        byte[] in,
-        int inOff,
-        byte[] out,
-        int outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
-    }
-    
-    /**
-     * reset the chaining vector back to the IV and reset the underlying
-     * cipher.
-     */
-    public void reset()
-    {
-        count = 0;
-
-        for (int i = 0; i != FR.length; i++)
-        {
-            FR[i] = IV[i];
-        }
-
-        cipher.reset();
-    }
-
-    /**
-     * Initialise the cipher and, possibly, the initialisation vector (IV).
-     * If an IV isn't passed as part of the parameter, the IV will be all zeros.
-     * An IV which is too short is handled in FIPS compliant fashion.
-     *
-     * @param forEncryption if true the cipher is initialised for
-     *  encryption, if false for decryption.
-     * @param param the key and other data required by the cipher.
-     * @exception IllegalArgumentException if the params argument is
-     * inappropriate.
-     */
-    public void init(
-        boolean forEncryption,
-        CipherParameters params)
-        throws IllegalArgumentException
-    {
-        this.forEncryption = forEncryption;
-     
-        reset();
-
-        cipher.init(true, params);
-    }
-    
-    /**
-     * Encrypt one byte of data according to CFB mode.
-     * @param data the byte to encrypt
-     * @param where am i in the current block, determines when to resync the block
-     * @returns the encrypted byte
-     */
-    private byte encryptByte(byte data, int blockOff)
-    {
-        return (byte)(FRE[blockOff] ^ data);
-    }
-    
-    /**
-     * Do the appropriate processing for CFB IV mode encryption.
-     *
-     * @param in the array containing the data to be encrypted.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the encrypted data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    private int encryptBlock(
-        byte[] in,
-        int inOff,
-        byte[] out,
-        int outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        if ((outOff + blockSize) > out.length)
-        {
-            throw new DataLengthException("output buffer too short");
-        }
-        
-        if (count > blockSize)
-        {
-            FR[blockSize - 2] = out[outOff] = encryptByte(in[inOff], blockSize - 2);
-            FR[blockSize - 1] = out[outOff + 1] = encryptByte(in[inOff + 1], blockSize - 1);
-
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            for (int n = 2; n < blockSize; n++) 
-            {
-                out[outOff + n] = encryptByte(in[inOff + n], n - 2);
-            }
-            
-            System.arraycopy(out, outOff + 2, FR, 0, blockSize - 2);
-        }
-        else if (count == 0)
-        {
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            for (int n = 0; n < blockSize; n++) 
-            {
-                out[outOff + n] = encryptByte(in[inOff + n], n);
-            }
-            
-            System.arraycopy(out, outOff, FR, 0, blockSize);
-
-            count += blockSize;
-        }
-        else if (count == blockSize)
-        {
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            out[outOff] = encryptByte(in[inOff], 0);
-            out[outOff + 1] = encryptByte(in[inOff + 1], 1);
-
-            //
-            // do reset
-            //
-            System.arraycopy(FR, 2, FR, 0, blockSize - 2);
-            System.arraycopy(out, outOff, FR, blockSize - 2, 2);
-
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            for (int n = 2; n < blockSize; n++) 
-            {
-                out[outOff + n] = encryptByte(in[inOff + n], n - 2);
-            }
-
-            System.arraycopy(out, outOff + 2, FR, 0, blockSize - 2);
-
-            count += blockSize;
-        }
-        
-        return blockSize;
-    }
-
-    /**
-     * Do the appropriate processing for CFB IV mode decryption.
-     *
-     * @param in the array containing the data to be decrypted.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the encrypted data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    private int decryptBlock(
-        byte[] in,
-        int inOff,
-        byte[] out,
-        int outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        if ((outOff + blockSize) > out.length)
-        {
-            throw new DataLengthException("output buffer too short");
-        }
-        
-        if (count > blockSize)
-        {
-            // copy in buffer so that this mode works if in and out are the same 
-            System.arraycopy(in, inOff, tmp, 0, blockSize);
-
-            out[outOff + 0] = encryptByte(tmp[0], blockSize - 2);
-            out[outOff + 1] = encryptByte(tmp[1], blockSize - 1);
-
-            System.arraycopy(tmp, 0, FR, blockSize - 2, 2);
-
-            cipher.processBlock(FR, 0, FRE, 0);
-            
-            for (int n = 2; n < blockSize; n++) 
-            {
-                out[outOff + n] = encryptByte(tmp[n], n - 2);
-            }
-            
-            System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
-        } 
-        else if (count == 0)
-        {
-			cipher.processBlock(FR, 0, FRE, 0);
-			
-            for (int n = 0; n < blockSize; n++) 
-            {
-                FR[n] = in[inOff + n];
-                out[n] = encryptByte(in[inOff + n], n);
-            }
-            
-            count += blockSize;
-        }
-        else if (count == blockSize)
-        {
-			System.arraycopy(in, inOff, tmp, 0, blockSize);
-			
-			cipher.processBlock(FR, 0, FRE, 0);
-
-			out[outOff + 0] = encryptByte(tmp[0], 0);
-			out[outOff + 1] = encryptByte(tmp[1], 1);
-			
-            System.arraycopy(FR, 2, FR, 0, blockSize - 2);
-            
-            FR[blockSize - 2] = tmp[0];
-            FR[blockSize - 1] = tmp[1];
-
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            for (int n = 2; n < blockSize; n++) 
-            {
-                FR[n - 2] = in[inOff + n];
-                out[outOff + n] = encryptByte(in[inOff + n], n - 2);
-            }
-
-            count += blockSize;;
-        }
-        
-        return blockSize;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
deleted file mode 100644
index 1ab6089..0000000
--- a/azureus2/src/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
+++ /dev/null
@@ -1,439 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode on top of a simple cipher. For further info see <a href="http://www.ietf.org/rfc/rfc2440.html">RFC 2440</a>.
- */
-public class PGPCFBBlockCipher
-    implements BlockCipher
-{
-    private byte[] IV;
-    private byte[] FR;
-    private byte[] FRE;
-    private byte[] tmp;
-
-    private BlockCipher cipher;
-
-    private int count;
-    private int blockSize;
-    private boolean forEncryption;
-    
-    private boolean inlineIv; // if false we don't need to prepend an IV
-
-    /**
-     * Basic constructor.
-     *
-     * @param cipher the block cipher to be used as the basis of the
-     * feedback mode.
-     * @param inlineIv if true this is for PGP CFB with a prepended iv.
-     */
-    public PGPCFBBlockCipher(
-        BlockCipher cipher,
-        boolean     inlineIv)
-    {
-        this.cipher = cipher;
-        this.inlineIv = inlineIv;
-
-        this.blockSize = cipher.getBlockSize();
-        this.IV = new byte[blockSize];
-        this.FR = new byte[blockSize];
-        this.FRE = new byte[blockSize];
-        this.tmp = new byte[blockSize];
-    }
-
-    /**
-     * return the underlying block cipher that we are wrapping.
-     *
-     * @return the underlying block cipher that we are wrapping.
-     */
-    public BlockCipher getUnderlyingCipher()
-    {
-        return cipher;
-    }
-    
-    /**
-     * return the algorithm name and mode.
-     *
-     * @return the name of the underlying algorithm followed by "/PGPCFB"
-     * and the block size in bits.
-     */
-    public String getAlgorithmName()
-    {
-        if (inlineIv)
-        {
-            return cipher.getAlgorithmName() + "/PGPCFBwithIV";
-        }
-        else
-        {
-            return cipher.getAlgorithmName() + "/PGPCFB";
-        }
-    }
-    
-    /**
-     * return the block size we are operating at.
-     *
-     * @return the block size we are operating at (in bytes).
-     */
-    public int getBlockSize()
-    {
-        return cipher.getBlockSize();
-    }
-
-    /**
-     * Process one block of input from the array in and write it to
-     * the out array.
-     *
-     * @param in the array containing the input data.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the output data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    public int processBlock(
-        byte[] in,
-        int inOff,
-        byte[] out,
-        int outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if (inlineIv)
-        {
-            return (forEncryption) ? encryptBlockWithIV(in, inOff, out, outOff) : decryptBlockWithIV(in, inOff, out, outOff);
-        }
-        else
-        {
-            return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
-        }
-    }
-    
-    /**
-     * reset the chaining vector back to the IV and reset the underlying
-     * cipher.
-     */
-    public void reset()
-    {
-        count = 0;
-
-        for (int i = 0; i != FR.length; i++)
-        {
-                if (inlineIv)
-                    FR[i] = 0;
-                else
-                    FR[i] = IV[i]; // if simple mode, key is IV (even if this is zero)
-        }
-
-        cipher.reset();
-    }
-
-    /**
-     * Initialise the cipher and, possibly, the initialisation vector (IV).
-     * If an IV isn't passed as part of the parameter, the IV will be all zeros.
-     * An IV which is too short is handled in FIPS compliant fashion.
-     *
-     * @param forEncryption if true the cipher is initialised for
-     *  encryption, if false for decryption.
-     * @param param the key and other data required by the cipher.
-     * @exception IllegalArgumentException if the params argument is
-     * inappropriate.
-     */
-    public void init(
-        boolean forEncryption,
-        CipherParameters params)
-        throws IllegalArgumentException
-    {
-        this.forEncryption = forEncryption;
-     
-        if (params instanceof ParametersWithIV)
-        {
-                ParametersWithIV ivParam = (ParametersWithIV)params;
-                byte[]      iv = ivParam.getIV();
-
-                if (iv.length < IV.length)
-                {
-                    // prepend the supplied IV with zeros (per FIPS PUB 81)
-                    System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
-                    for (int i = 0; i < IV.length - iv.length; i++)
-                    {
-                            IV[i] = 0;
-                    }
-                }
-                else
-                {
-                    System.arraycopy(iv, 0, IV, 0, IV.length);
-                }
-
-                reset();
-
-                cipher.init(true, ivParam.getParameters());
-        }
-        else
-        {
-                reset();
-
-                cipher.init(true, params);
-        }
-    }
-    
-    /**
-     * Encrypt one byte of data according to CFB mode.
-     * @param data the byte to encrypt
-     * @param where am i in the current block, determines when to resync the block
-     * @returns the encrypted byte
-     */
-    private byte encryptByte(byte data, int blockOff)
-    {
-        return (byte)(FRE[blockOff] ^ data);
-    }
-    
-    /**
-     * Do the appropriate processing for CFB IV mode encryption.
-     *
-     * @param in the array containing the data to be encrypted.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the encrypted data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    private int encryptBlockWithIV(
-        byte[] in,
-        int inOff,
-        byte[] out,
-        int outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        if ((outOff + blockSize) > out.length)
-        {
-            throw new DataLengthException("output buffer too short");
-        }
-        
-        if (count == 0)
-        {
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            for (int n = 0; n < blockSize; n++) 
-            {
-                out[outOff + n] = encryptByte(IV[n], n);
-            }
-            
-            System.arraycopy(out, outOff, FR, 0, blockSize);
-
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            out[outOff + blockSize] = encryptByte(IV[blockSize - 2], 0);
-            out[outOff + blockSize + 1] = encryptByte(IV[blockSize - 1], 1);
-
-            System.arraycopy(out, outOff + 2, FR, 0, blockSize);
-            
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            for (int n = 0; n < blockSize; n++) 
-            {
-                out[outOff + blockSize + 2 + n] = encryptByte(in[inOff + n], n);
-            }
-
-            System.arraycopy(out, outOff + blockSize + 2, FR, 0, blockSize);
-
-            count += 2 * blockSize + 2;
-
-            return 2 * blockSize + 2;
-        }
-        else if (count >= blockSize + 2)
-        {
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            for (int n = 0; n < blockSize; n++) 
-            {
-                out[outOff + n] = encryptByte(in[inOff + n], n);
-            }
-            
-            System.arraycopy(out, outOff, FR, 0, blockSize);
-        }
-        
-        return blockSize;
-    }
-
-    /**
-     * Do the appropriate processing for CFB IV mode decryption.
-     *
-     * @param in the array containing the data to be decrypted.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the encrypted data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    private int decryptBlockWithIV(
-        byte[] in,
-        int inOff,
-        byte[] out,
-        int outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        if ((outOff + blockSize) > out.length)
-        {
-            throw new DataLengthException("output buffer too short");
-        }
-        
-        if (count == 0)
-        {
-            for (int n = 0; n < blockSize; n++) 
-            {
-                FR[n] = in[inOff + n];
-            }
-            
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            count += blockSize;
-
-            return 0;
-        }
-        else if (count == blockSize)
-        {
-            // copy in buffer so that this mode works if in and out are the same 
-            System.arraycopy(in, inOff, tmp, 0, blockSize);
-        
-            System.arraycopy(FR, 2, FR, 0, blockSize - 2);
-            
-            FR[blockSize - 2] = tmp[0];
-            FR[blockSize - 1] = tmp[1];
-
-            cipher.processBlock(FR, 0, FRE, 0);
-
-            for (int n = 0; n < blockSize - 2; n++) 
-            {
-                out[outOff + n] = encryptByte(tmp[n + 2], n);
-            }
-
-            System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
-
-            count += 2;
-
-            return blockSize - 2;
-        }
-        else if (count >= blockSize + 2)
-        {
-            // copy in buffer so that this mode works if in and out are the same 
-            System.arraycopy(in, inOff, tmp, 0, blockSize);
-
-            out[outOff + 0] = encryptByte(tmp[0], blockSize - 2);
-            out[outOff + 1] = encryptByte(tmp[1], blockSize - 1);
-
-            System.arraycopy(tmp, 0, FR, blockSize - 2, 2);
-
-            cipher.processBlock(FR, 0, FRE, 0);
-            
-            for (int n = 0; n < blockSize - 2; n++) 
-            {
-                out[outOff + n + 2] = encryptByte(tmp[n + 2], n);
-            }
-            
-            System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
-            
-        } 
-        
-        return blockSize;
-    }
-    
-    /**
-     * Do the appropriate processing for CFB mode encryption.
-     *
-     * @param in the array containing the data to be encrypted.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the encrypted data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    private int encryptBlock(
-        byte[] in,
-        int inOff,
-        byte[] out,
-        int outOff)
-        throws DataLengthException, IllegalStateException
-    {        
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        if ((outOff + blockSize) > out.length)
-        {
-            throw new DataLengthException("output buffer too short");
-        }
-        
-        
-        cipher.processBlock(FR, 0, FRE, 0);
-        for (int n = 0; n < blockSize; n++) 
-            out[outOff + n] = encryptByte(in[inOff + n], n);
-        
-        for (int n = 0; n < blockSize; n++) 
-            FR[n] = out[outOff + n];
-        
-        return blockSize;
-        
-    }
-    
-    /**
-     * Do the appropriate processing for CFB mode decryption.
-     *
-     * @param in the array containing the data to be decrypted.
-     * @param inOff offset into the in array the data starts at.
-     * @param out the array the encrypted data will be copied into.
-     * @param outOff the offset into the out array the output will start at.
-     * @exception DataLengthException if there isn't enough data in in, or
-     * space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     * @return the number of bytes processed and produced.
-     */
-    private int decryptBlock(
-        byte[] in,
-        int inOff,
-        byte[] out,
-        int outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        if ((inOff + blockSize) > in.length)
-        {
-            throw new DataLengthException("input buffer too short");
-        }
-
-        if ((outOff + blockSize) > out.length)
-        {
-            throw new DataLengthException("output buffer too short");
-        }
-        
-        cipher.processBlock(FR, 0, FRE, 0);
-        for (int n = 0; n < blockSize; n++) 
-            out[outOff + n] = encryptByte(in[inOff + n], n);
-        
-        for (int n = 0; n < blockSize; n++) 
-            FR[n] = in[inOff + n];
-        
-        return blockSize;
-        
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/modes/PaddedBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/modes/PaddedBlockCipher.java
deleted file mode 100644
index 0571cbb..0000000
--- a/azureus2/src/org/bouncycastle/crypto/modes/PaddedBlockCipher.java
+++ /dev/null
@@ -1,253 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.BufferedBlockCipher;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-
-/**
- * A wrapper class that allows block ciphers to be used to process data in
- * a piecemeal fashion with PKCS5/PKCS7 padding. The PaddedBlockCipher
- * outputs a block only when the buffer is full and more data is being added,
- * or on a doFinal (unless the current block in the buffer is a pad block).
- * The padding mechanism used is the one outlined in PKCS5/PKCS7.
- *
- * @deprecated use org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher instead.
- */
-public class PaddedBlockCipher
-    extends BufferedBlockCipher
-{
-    /**
-     * Create a buffered block cipher with, or without, padding.
-     *
-     * @param cipher the underlying block cipher this buffering object wraps.
-     */
-	public PaddedBlockCipher(
-        BlockCipher     cipher)
-	{
-        this.cipher = cipher;
-
-        buf = new byte[cipher.getBlockSize()];
-        bufOff = 0;
-	}
-
-    /**
-     * return the size of the output buffer required for an update plus a
-     * doFinal with an input of len bytes.
-     *
-     * @param len the length of the input.
-     * @return the space required to accommodate a call to update and doFinal
-     * with len bytes of input.
-     */
-    public int getOutputSize(
-        int len)
-    {
-        int total       = len + bufOff;
-        int leftOver    = total % buf.length;
-
-        if (leftOver == 0)
-        {
-            if (forEncryption)
-            {
-                return total + buf.length;
-            }
-
-            return total;
-        }
-
-        return total - leftOver + buf.length;
-    }
-
-    /**
-     * return the size of the output buffer required for an update 
-     * an input of len bytes.
-     *
-     * @param len the length of the input.
-     * @return the space required to accommodate a call to update
-     * with len bytes of input.
-     */
-    public int getUpdateOutputSize(
-        int len)
-    {
-        int total       = len + bufOff;
-        int leftOver    = total % buf.length;
-
-        if (leftOver == 0)
-        {
-            return total - buf.length;
-        }
-
-        return total - leftOver;
-    }
-
-    /**
-     * process a single byte, producing an output block if neccessary.
-     *
-     * @param in the input byte.
-     * @param out the space for any output that might be produced.
-     * @param outOff the offset from which the output will be copied.
-     * @exception DataLengthException if there isn't enough space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     */
-	public int processByte(
-        byte        in,
-		byte[]      out,
-		int         outOff)
-        throws DataLengthException, IllegalStateException
-    {
-        int         resultLen = 0;
-
-        if (bufOff == buf.length)
-        {
-            resultLen = cipher.processBlock(buf, 0, out, outOff);
-            bufOff = 0;
-        }
-
-        buf[bufOff++] = in;
-
-        return resultLen;
-    }
-
-    /**
-     * process an array of bytes, producing output if necessary.
-     *
-     * @param in the input byte array.
-     * @param inOff the offset at which the input data starts.
-     * @param len the number of bytes to be copied out of the input array.
-     * @param out the space for any output that might be produced.
-     * @param outOff the offset from which the output will be copied.
-     * @exception DataLengthException if there isn't enough space in out.
-     * @exception IllegalStateException if the cipher isn't initialised.
-     */
-	public int processBytes(
-		byte[]      in,
-		int         inOff,
-		int         len,
-		byte[]      out,
-		int         outOff)
-        throws DataLengthException, IllegalStateException
-	{
-        if (len < 0)
-        {
-            throw new IllegalArgumentException("Can't have a negative input length!");
-        }
-
-        int blockSize   = getBlockSize();
-        int length      = getUpdateOutputSize(len);
-        
-        if (length > 0)
-        {
-            if ((outOff + length) > out.length)
-            {
-                throw new DataLengthException("output buffer too short");
-            }
-        }
-
-		int resultLen = 0;
-        int gapLen = buf.length - bufOff;
-
-        if (len > gapLen)
-        {
-            System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
-            resultLen += cipher.processBlock(buf, 0, out, outOff);
-
-            bufOff = 0;
-            len -= gapLen;
-            inOff += gapLen;
-
-            while (len > buf.length)
-            {
-                resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
-
-                len -= blockSize;
-                inOff += blockSize;
-            }
-        }
-
-        System.arraycopy(in, inOff, buf, bufOff, len);
-
-        bufOff += len;
-
-        return resultLen;
-	}
-
-    /**
-     * Process the last block in the buffer. If the buffer is currently
-     * full and padding needs to be added a call to doFinal will produce
-     * 2 * getBlockSize() bytes.
-     *
-     * @param out the array the block currently being held is copied into.
-     * @param outOff the offset at which the copying starts.
-     * @exception DataLengthException if there is insufficient space in out for
-     * the output or we are decrypting and the input is not block size aligned.
-     * @exception IllegalStateException if the underlying cipher is not
-     * initialised.
-     * @exception InvalidCipherTextException if padding is expected and not found.
-     */
-	public int doFinal(
-        byte[]  out,
-        int     outOff)
-        throws DataLengthException, IllegalStateException, InvalidCipherTextException
-	{
-        int blockSize = cipher.getBlockSize();
-        int resultLen = 0;
-
-        if (forEncryption)
-        {
-            if (bufOff == blockSize)
-            {
-                if ((outOff + 2 * blockSize) > out.length)
-                {
-                    throw new DataLengthException("output buffer too short");
-                }
-
-                resultLen = cipher.processBlock(buf, 0, out, outOff);
-                bufOff = 0;
-            }
-
-            //
-            // add PKCS7 padding
-            //
-            byte code = (byte)(blockSize - bufOff);
-
-            while (bufOff < blockSize)
-            {
-                buf[bufOff] = code;
-                bufOff++;
-            }
-
-            resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
-        }
-        else
-        {
-            if (bufOff == blockSize)
-            {
-                resultLen = cipher.processBlock(buf, 0, buf, 0);
-                bufOff = 0;
-            }
-            else
-            {
-                throw new DataLengthException("last block incomplete in decryption");
-            }
-
-            //
-            // remove PKCS7 padding
-            //
-            int count = buf[blockSize - 1] & 0xff;
-
-            if ((count < 0) || (count > blockSize))
-            {
-                throw new InvalidCipherTextException("pad block corrupted");
-            }
-
-            resultLen -= count;
-
-            System.arraycopy(buf, 0, out, outOff, resultLen);
-        }
-
-        reset();
-
-		return resultLen;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/modes/SICBlockCipher.java b/azureus2/src/org/bouncycastle/crypto/modes/SICBlockCipher.java
deleted file mode 100644
index 3ae36d2..0000000
--- a/azureus2/src/org/bouncycastle/crypto/modes/SICBlockCipher.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.bouncycastle.crypto.modes;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-
-/**
- * Implements the Segmented Integer Counter (SIC) mode on top of a simple
- * block cipher. This mode is also known as CTR mode.
- */
-public class SICBlockCipher implements BlockCipher
-{
-  private BlockCipher     cipher = null;
-  private int             blockSize;
-  private byte[]          IV;
-  private byte[]          counter;
-  private byte[]          counterOut;
-  private boolean         encrypting;
-
-
-  /**
-   * Basic constructor.
-   *
-   * @param c the block cipher to be used.
-   */
-  public SICBlockCipher(BlockCipher c) {
-    this.cipher = c;
-    this.blockSize = cipher.getBlockSize();
-    this.IV = new byte[blockSize];
-    this.counter = new byte[blockSize];
-    this.counterOut = new byte[blockSize];
-  }
-
-
-  /**
-   * return the underlying block cipher that we are wrapping.
-   *
-   * @return the underlying block cipher that we are wrapping.
-   */
-  public BlockCipher getUnderlyingCipher() {
-    return cipher;
-  }
-
-
-  public void init(boolean forEncryption, CipherParameters params)
-      throws IllegalArgumentException {
-    this.encrypting = forEncryption;
-
-    if (params instanceof ParametersWithIV) {
-      ParametersWithIV ivParam = (ParametersWithIV)params;
-      byte[]           iv      = ivParam.getIV();
-      System.arraycopy(iv, 0, IV, 0, IV.length);
-
-      reset();
-      cipher.init(true, ivParam.getParameters());
-    }
-  }
-
-
-  public String getAlgorithmName() {
-    return cipher.getAlgorithmName() + "/SIC";
-  }
-
-
-  public int getBlockSize() {
-    return cipher.getBlockSize();
-  }
-
-
-  public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
-      throws DataLengthException, IllegalStateException {
-    cipher.processBlock(counter, 0, counterOut, 0);
-
-    //
-    // XOR the counterOut with the plaintext producing the cipher text
-    //
-    for (int i = 0; i < counterOut.length; i++) {
-      out[outOff + i] = (byte)(counterOut[i] ^ in[inOff + i]);
-    }
-
-	int	carry = 1;
-	
-	for (int i = counter.length - 1; i >= 0; i--)
-	{
-		int	x = (counter[i] & 0xff) + carry;
-		
-		if (x > 0xff)
-		{
-			carry = 1;
-		}
-		else
-		{
-			carry = 0;
-		}
-		
-		counter[i] = (byte)x;
-	}
-
-    return counter.length;
-  }
-
-
-  public void reset() {
-    System.arraycopy(IV, 0, counter, 0, counter.length);
-    cipher.reset();
-  }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/modes/package.html b/azureus2/src/org/bouncycastle/crypto/modes/package.html
deleted file mode 100644
index 5402df4..0000000
--- a/azureus2/src/org/bouncycastle/crypto/modes/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Modes for symmetric ciphers.
-</body>
-</html>
diff --git a/azureus2/src/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java b/azureus2/src/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java
deleted file mode 100644
index 5710395..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class AsymmetricKeyParameter
-	implements CipherParameters
-{
-    boolean privateKey;
-
-    public AsymmetricKeyParameter(
-        boolean privateKey)
-    {
-        this.privateKey = privateKey;
-    }
-
-    public boolean isPrivate()
-    {
-        return privateKey;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DESParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DESParameters.java
deleted file mode 100644
index 5bee360..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DESParameters.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class DESParameters
-    extends KeyParameter
-{
-    public DESParameters(
-        byte[]  key)
-    {
-        super(key);
-
-        if (isWeakKey(key, 0))
-        {
-            throw new IllegalArgumentException("attempt to create weak DES key");
-        }
-    }
-
-    /*
-     * DES Key length in bytes.
-     */
-    static public final int DES_KEY_LENGTH = 8;
-
-    /*
-     * Table of weak and semi-weak keys taken from Schneier pp281
-     */
-    static private final int N_DES_WEAK_KEYS = 16;
-
-    static private byte[] DES_weak_keys =
-    {
-        /* weak keys */
-        (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
-        (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
-        (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
-        (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
-
-        /* semi-weak keys */
-        (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
-        (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
-        (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
-        (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
-        (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
-        (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
-        (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
-        (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
-        (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
-        (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
-        (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
-        (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
-    };
-
-    /**
-     * DES has 16 weak keys.  This method will check
-     * if the given DES key material is weak or semi-weak.
-     * Key material that is too short is regarded as weak.
-     * <p>
-     * See <a href="http://www.counterpane.com/applied.html">"Applied
-     * Cryptography"</a> by Bruce Schneier for more information.
-     *
-     * @return true if the given DES key material is weak or semi-weak,
-     *     false otherwise.
-     */
-    public static boolean isWeakKey(
-        byte[] key,
-        int offset)
-    {
-        if (key.length - offset < DES_KEY_LENGTH)
-        {
-            throw new IllegalArgumentException("key material too short.");
-        }
-
-        nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++)
-        {
-            for (int j = 0; j < DES_KEY_LENGTH; j++)
-            {
-                if (key[j + offset] != DES_weak_keys[i * DES_KEY_LENGTH + j])
-                {
-                    continue nextkey;
-                }
-            }
-
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * DES Keys use the LSB as the odd parity bit.  This can
-     * be used to check for corrupt keys.
-     *
-     * @param bytes the byte array to set the parity on.
-     */
-    public static void setOddParity(
-        byte[] bytes)
-    {
-        for (int i = 0; i < bytes.length; i++)
-        {
-            int b = bytes[i];
-            bytes[i] = (byte)((b & 0xfe) |
-                            ((((b >> 1) ^
-                            (b >> 2) ^
-                            (b >> 3) ^
-                            (b >> 4) ^
-                            (b >> 5) ^
-                            (b >> 6) ^
-                            (b >> 7)) ^ 0x01) & 0x01));
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DESedeParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DESedeParameters.java
deleted file mode 100644
index d424fc1..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DESedeParameters.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class DESedeParameters
-    extends DESParameters
-{
-    /*
-     * DES-EDE Key length in bytes.
-     */
-    static public final int DES_EDE_KEY_LENGTH = 24;
-
-    public DESedeParameters(
-        byte[]  key)
-    {
-        super(key);
-
-        if (isWeakKey(key, 0, 0))
-        {
-            throw new IllegalArgumentException("attempt to create weak DESede key");
-        }
-    }
-
-    /**
-     * return true if the passed in key is a DES-EDE weak key.
-     *
-     * @param key bytes making up the key
-     * @param offset offset into the byte array the key starts at
-     * @param length number of bytes making up the key
-     */
-    public static boolean isWeakKey(
-        byte[]  key,
-        int     offset,
-        int     length)
-    {
-        for (int i = offset; i < length; i += DES_KEY_LENGTH)
-        {
-            if (DESParameters.isWeakKey(key, i))
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * return true if the passed in key is a DES-EDE weak key.
-     *
-     * @param key bytes making up the key
-     * @param offset offset into the byte array the key starts at
-     */
-    public static boolean isWeakKey(
-        byte[]  key,
-        int     offset)
-    {
-        return isWeakKey(key, offset, key.length - offset);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java
deleted file mode 100644
index 76c8037..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class DHKeyGenerationParameters
-    extends KeyGenerationParameters
-{
-    private DHParameters    params;
-
-    public DHKeyGenerationParameters(
-        SecureRandom    random,
-        DHParameters    params)
-    {
-        super(random, params.getP().bitLength() - 1);
-
-        this.params = params;
-    }
-
-    public DHParameters getParameters()
-    {
-        return params;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DHKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DHKeyParameters.java
deleted file mode 100644
index aceadde..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DHKeyParameters.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-
-public class DHKeyParameters
-    extends AsymmetricKeyParameter
-{
-    private DHParameters    params;
-
-    protected DHKeyParameters(
-        boolean         isPrivate,
-        DHParameters    params)
-    {
-        super(isPrivate);
-
-        this.params = params;
-    }   
-
-    public DHParameters getParameters()
-    {
-        return params;
-    }
-
-    public boolean equals(
-        Object  obj)
-    {
-        if (!(obj instanceof DHKeyParameters))
-        {
-            return false;
-        }
-
-        DHKeyParameters    dhKey = (DHKeyParameters)obj;
-
-        return (params != null && !params.equals(dhKey.getParameters()));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DHParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DHParameters.java
deleted file mode 100644
index 40f77ab..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DHParameters.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class DHParameters
-    implements CipherParameters
-{
-    private BigInteger              g;
-    private BigInteger              p;
-    private BigInteger              q;
-    private int                     j;
-    private DHValidationParameters  validation;
-
-    public DHParameters(
-        BigInteger  p,
-        BigInteger  g)
-    {
-        this.g = g;
-        this.p = p;
-    }
-
-    public DHParameters(
-        BigInteger  p,
-        BigInteger  g,
-        BigInteger  q,
-        int         j)
-    {
-        this.g = g;
-        this.p = p;
-        this.q = q;
-        this.j = j;
-    }   
-
-    public DHParameters(
-        BigInteger              p,
-        BigInteger              g,
-        BigInteger              q,
-        int                     j,
-        DHValidationParameters  validation)
-    {
-        this.g = g;
-        this.p = p;
-        this.q = q;
-        this.j = j;
-    }   
-
-    public BigInteger getP()
-    {
-        return p;
-    }
-
-    public BigInteger getG()
-    {
-        return g;
-    }
-
-    public BigInteger getQ()
-    {
-        return q;
-    }
-
-    public int getJ()
-    {
-        return j;
-    }
-
-    public DHValidationParameters getValidationParameters()
-    {
-        return validation;
-    }
-
-    public boolean equals(
-        Object  obj)
-    {
-        if (!(obj instanceof DHParameters))
-        {
-            return false;
-        }
-
-        DHParameters    pm = (DHParameters)obj;
-
-        if (this.getValidationParameters() != null)
-        {
-            if (!this.getValidationParameters().equals(pm.getValidationParameters()))
-            {
-                return false;
-            }
-        }
-        else
-        {
-            if (pm.getValidationParameters() != null)
-            {
-                return false;
-            }
-        }
-
-        if (this.getQ() != null)
-        {
-            if (!this.getQ().equals(pm.getQ()))
-            {
-                return false;
-            }
-        }
-        else
-        {
-            if (pm.getQ() != null)
-            {
-                return false;
-            }
-        }
-        
-        return (j == pm.getJ()) && pm.getP().equals(p) && pm.getG().equals(g);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java
deleted file mode 100644
index 523f9a0..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class DHPrivateKeyParameters
-    extends DHKeyParameters
-{
-    private BigInteger      x;
-
-    public DHPrivateKeyParameters(
-        BigInteger      x,
-        DHParameters    params)
-    {
-        super(true, params);
-
-        this.x = x;
-    }   
-
-    public BigInteger getX()
-    {
-        return x;
-    }
-
-    public boolean equals(
-        Object  obj)
-    {
-        if (!(obj instanceof DHPrivateKeyParameters))
-        {
-            return false;
-        }
-
-        DHPrivateKeyParameters  pKey = (DHPrivateKeyParameters)obj;
-
-        if (!pKey.getX().equals(x))
-        {
-            return false;
-        }
-
-        return super.equals(obj);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DHPublicKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DHPublicKeyParameters.java
deleted file mode 100644
index 4f308ed..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DHPublicKeyParameters.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class DHPublicKeyParameters
-    extends DHKeyParameters
-{
-    private BigInteger      y;
-
-    public DHPublicKeyParameters(
-        BigInteger      y,
-        DHParameters    params)
-    {
-        super(false, params);
-
-        this.y = y;
-    }   
-
-    public BigInteger getY()
-    {
-        return y;
-    }
-
-    public boolean equals(
-        Object  obj)
-    {
-        if (!(obj instanceof DHPublicKeyParameters))
-        {
-            return false;
-        }
-
-        DHPublicKeyParameters   pKey = (DHPublicKeyParameters)obj;
-
-        if (!pKey.getY().equals(y))
-        {
-            return false;
-        }
-
-        return super.equals(obj);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DHValidationParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DHValidationParameters.java
deleted file mode 100644
index fa3cf56..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DHValidationParameters.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class DHValidationParameters
-{
-    private byte[]  seed;
-    private int     counter;
-
-    public DHValidationParameters(
-        byte[]  seed,
-        int     counter)
-    {
-        this.seed = seed;
-        this.counter = counter;
-    }
-
-    public boolean equals(
-        Object o)
-    {
-        if (o == null || !(o instanceof DHValidationParameters))
-        {
-            return false;
-        }
-
-        DHValidationParameters  other = (DHValidationParameters)o;
-
-        if (other.counter != this.counter)
-        {
-            return false;
-        }
-
-        if (other.seed.length != this.seed.length)
-        {
-            return false;
-        }
-
-        for (int i = 0; i != other.seed.length; i++)
-        {
-            if (other.seed[i] != this.seed[i])
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java
deleted file mode 100644
index 29fa91e..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class DSAKeyGenerationParameters
-    extends KeyGenerationParameters
-{
-    private DSAParameters    params;
-
-    public DSAKeyGenerationParameters(
-        SecureRandom    random,
-        DSAParameters   params)
-    {
-        super(random, params.getP().bitLength() - 1);
-
-        this.params = params;
-    }
-
-    public DSAParameters getParameters()
-    {
-        return params;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DSAKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DSAKeyParameters.java
deleted file mode 100644
index 11bb9d9..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DSAKeyParameters.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class DSAKeyParameters
-    extends AsymmetricKeyParameter
-{
-    private DSAParameters    params;
-
-    public DSAKeyParameters(
-        boolean         isPrivate,
-        DSAParameters   params)
-    {
-        super(isPrivate);
-
-        this.params = params;
-    }   
-
-    public DSAParameters getParameters()
-    {
-        return params;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DSAParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DSAParameters.java
deleted file mode 100644
index 02e054b..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DSAParameters.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class DSAParameters
-    implements CipherParameters
-{
-    private BigInteger              g;
-    private BigInteger              q;
-    private BigInteger              p;
-    private DSAValidationParameters validation;
-
-    public DSAParameters(
-        BigInteger  p,
-        BigInteger  q,
-        BigInteger  g)
-    {
-        this.g = g;
-        this.p = p;
-        this.q = q;
-    }   
-
-    public DSAParameters(
-        BigInteger              p,
-        BigInteger              q,
-        BigInteger              g,
-        DSAValidationParameters params)
-    {
-        this.g = g;
-        this.p = p;
-        this.q = q;
-        this.validation = params;
-    }   
-
-    public BigInteger getP()
-    {
-        return p;
-    }
-
-    public BigInteger getQ()
-    {
-        return q;
-    }
-
-    public BigInteger getG()
-    {
-        return g;
-    }
-
-    public DSAValidationParameters getValidationParameters()
-    {
-        return validation;
-    }
-
-    public boolean equals(
-        Object  obj)
-    {
-        if (!(obj instanceof DSAParameters))
-        {
-            return false;
-        }
-
-        DSAParameters    pm = (DSAParameters)obj;
-
-        return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getG().equals(g));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java
deleted file mode 100644
index 3bef3f4..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class DSAPrivateKeyParameters
-    extends DSAKeyParameters
-{
-    private BigInteger      x;
-
-    public DSAPrivateKeyParameters(
-        BigInteger      x,
-        DSAParameters   params)
-    {
-        super(true, params);
-
-        this.x = x;
-    }   
-
-    public BigInteger getX()
-    {
-        return x;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java
deleted file mode 100644
index c006656..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class DSAPublicKeyParameters
-    extends DSAKeyParameters
-{
-    private BigInteger      y;
-
-    public DSAPublicKeyParameters(
-        BigInteger      y,
-        DSAParameters   params)
-    {
-        super(false, params);
-
-        this.y = y;
-    }   
-
-    public BigInteger getY()
-    {
-        return y;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/DSAValidationParameters.java b/azureus2/src/org/bouncycastle/crypto/params/DSAValidationParameters.java
deleted file mode 100644
index 5cc67c2..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/DSAValidationParameters.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class DSAValidationParameters
-{
-    private byte[]  seed;
-    private int     counter;
-
-    public DSAValidationParameters(
-        byte[]  seed,
-        int     counter)
-    {
-        this.seed = seed;
-        this.counter = counter;
-    }
-
-    public int getCounter()
-    {
-        return counter;
-    }
-
-    public byte[] getSeed()
-    {
-        return seed;
-    }
-
-    public boolean equals(
-        Object o)
-    {
-        if (o == null || !(o instanceof DSAValidationParameters))
-        {
-            return false;
-        }
-
-        DSAValidationParameters  other = (DSAValidationParameters)o;
-
-        if (other.counter != this.counter)
-        {
-            return false;
-        }
-
-        if (other.seed.length != this.seed.length)
-        {
-            return false;
-        }
-
-        for (int i = 0; i != other.seed.length; i++)
-        {
-            if (other.seed[i] != this.seed[i])
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ECDomainParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ECDomainParameters.java
deleted file mode 100644
index 32889c4..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ECDomainParameters.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-
-public class ECDomainParameters
-    implements ECConstants
-{
-	ECCurve     curve;
-	byte[]      seed;
-	ECPoint     G;
-	BigInteger  n;
-	BigInteger  h;
-
-	public ECDomainParameters(
-		ECCurve     curve,
-		ECPoint     G,
-		BigInteger  n)
-	{
-		this.curve = curve;
-		this.G = G;
-		this.n = n;
-        this.h = ONE;
-        this.seed = null;
-	}
-
-	public ECDomainParameters(
-		ECCurve     curve,
-		ECPoint     G,
-		BigInteger  n,
-        BigInteger  h)
-	{
-		this.curve = curve;
-		this.G = G;
-		this.n = n;
-		this.h = h;
-        this.seed = null;
-	}
-
-	public ECDomainParameters(
-		ECCurve     curve,
-		ECPoint     G,
-		BigInteger  n,
-        BigInteger  h,
-        byte[]      seed)
-	{
-		this.curve = curve;
-		this.G = G;
-		this.n = n;
-		this.h = h;
-        this.seed = seed;
-	}
-
-	public ECCurve getCurve()
-	{
-		return curve;
-	}
-
-	public ECPoint getG()
-	{
-		return G;
-	}
-
-	public BigInteger getN()
-	{
-		return n;
-	}
-
-	public BigInteger getH()
-	{
-		return h;
-	}
-
-	public byte[] getSeed()
-	{
-		return seed;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java
deleted file mode 100644
index 0d8b206..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class ECKeyGenerationParameters
-    extends KeyGenerationParameters
-{
-	private ECDomainParameters  domainParams;
-
-    public ECKeyGenerationParameters(
-		ECDomainParameters		domainParams,
-        SecureRandom            random)
-    {
-        super(random, domainParams.getN().bitLength());
-
-		this.domainParams = domainParams;
-    }
-
-	public ECDomainParameters getDomainParameters()
-	{
-		return domainParams;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ECKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ECKeyParameters.java
deleted file mode 100644
index cb12b60..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ECKeyParameters.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-public class ECKeyParameters
-    extends AsymmetricKeyParameter
-{
-	ECDomainParameters params;
-
-	protected ECKeyParameters(
-        boolean             isPrivate,
-        ECDomainParameters  params)
-	{
-        super(isPrivate);
-
-		this.params = params;
-	}
-
-	public ECDomainParameters getParameters()
-	{
-		return params;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java
deleted file mode 100644
index 3e49983..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class ECPrivateKeyParameters
-    extends ECKeyParameters
-{
-    BigInteger d;
-
-    public ECPrivateKeyParameters(
-        BigInteger          d,
-        ECDomainParameters  params)
-    {
-        super(true, params);
-        this.d = d;
-    }
-
-    public BigInteger getD()
-    {
-        return d;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ECPublicKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
deleted file mode 100644
index 5fbea19..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.math.ec.ECPoint;
-
-public class ECPublicKeyParameters
-    extends ECKeyParameters
-{
-    ECPoint Q;
-
-    public ECPublicKeyParameters(
-        ECPoint             Q,
-        ECDomainParameters  params)
-    {
-        super(false, params);
-        this.Q = Q;
-    }
-
-    public ECPoint getQ()
-    {
-        return Q;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java
deleted file mode 100644
index ffcc04d..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class ElGamalKeyGenerationParameters
-    extends KeyGenerationParameters
-{
-    private ElGamalParameters    params;
-
-    public ElGamalKeyGenerationParameters(
-        SecureRandom        random,
-        ElGamalParameters   params)
-    {
-        super(random, params.getP().bitLength() - 1);
-
-        this.params = params;
-    }
-
-    public ElGamalParameters getParameters()
-    {
-        return params;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ElGamalKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ElGamalKeyParameters.java
deleted file mode 100644
index 3e42647..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ElGamalKeyParameters.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-
-public class ElGamalKeyParameters
-    extends AsymmetricKeyParameter
-{
-    private ElGamalParameters    params;
-
-    protected ElGamalKeyParameters(
-        boolean         isPrivate,
-        ElGamalParameters    params)
-    {
-        super(isPrivate);
-
-        this.params = params;
-    }   
-
-    public ElGamalParameters getParameters()
-    {
-        return params;
-    }
-
-    public boolean equals(
-        Object  obj)
-    {
-        if (!(obj instanceof ElGamalKeyParameters))
-        {
-            return false;
-        }
-
-        ElGamalKeyParameters    dhKey = (ElGamalKeyParameters)obj;
-
-        return (params != null && !params.equals(dhKey.getParameters()));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ElGamalParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ElGamalParameters.java
deleted file mode 100644
index a9a0f0f..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ElGamalParameters.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class ElGamalParameters
-    implements CipherParameters
-{
-    private BigInteger              g;
-    private BigInteger              p;
-
-    public ElGamalParameters(
-        BigInteger  p,
-        BigInteger  g)
-    {
-        this.g = g;
-        this.p = p;
-    }
-
-    public BigInteger getP()
-    {
-        return p;
-    }
-
-    /**
-     * return the generator - g
-     */
-    public BigInteger getG()
-    {
-        return g;
-    }
-
-    public boolean equals(
-        Object  obj)
-    {
-        if (!(obj instanceof ElGamalParameters))
-        {
-            return false;
-        }
-
-        ElGamalParameters    pm = (ElGamalParameters)obj;
-
-        return pm.getP().equals(p) && pm.getG().equals(g);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java
deleted file mode 100644
index 58c8a7a..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class ElGamalPrivateKeyParameters
-    extends ElGamalKeyParameters
-{
-    private BigInteger      x;
-
-    public ElGamalPrivateKeyParameters(
-        BigInteger      x,
-        ElGamalParameters    params)
-    {
-        super(true, params);
-
-        this.x = x;
-    }   
-
-    public BigInteger getX()
-    {
-        return x;
-    }
-
-    public boolean equals(
-        Object  obj)
-    {
-        if (!(obj instanceof ElGamalPrivateKeyParameters))
-        {
-            return false;
-        }
-
-        ElGamalPrivateKeyParameters  pKey = (ElGamalPrivateKeyParameters)obj;
-
-        if (!pKey.getX().equals(x))
-        {
-            return false;
-        }
-
-        return super.equals(obj);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java
deleted file mode 100644
index 83ef293..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class ElGamalPublicKeyParameters
-    extends ElGamalKeyParameters
-{
-    private BigInteger      y;
-
-    public ElGamalPublicKeyParameters(
-        BigInteger      y,
-        ElGamalParameters    params)
-    {
-        super(false, params);
-
-        this.y = y;
-    }   
-
-    public BigInteger getY()
-    {
-        return y;
-    }
-
-    public boolean equals(
-        Object  obj)
-    {
-        if (!(obj instanceof ElGamalPublicKeyParameters))
-        {
-            return false;
-        }
-
-        ElGamalPublicKeyParameters   pKey = (ElGamalPublicKeyParameters)obj;
-
-        if (!pKey.getY().equals(y))
-        {
-            return false;
-        }
-
-        return super.equals(obj);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/IESParameters.java b/azureus2/src/org/bouncycastle/crypto/params/IESParameters.java
deleted file mode 100644
index 0600b34..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/IESParameters.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-/**
- * parameters for using an integrated cipher in stream mode.
- */
-public class IESParameters
-    implements CipherParameters
-{
-    private byte[]  derivation;
-    private byte[]  encoding;
-    private int     macKeySize;
-
-    /**
-     * @param derivation the derivation parameter for the KDF function.
-     * @param encoding the encoding parameter for the KDF function.
-     * @param macKeySize the size of the MAC key (in bits).
-     */
-    public IESParameters(
-        byte[]  derivation,
-        byte[]  encoding,
-        int     macKeySize)
-    {
-        this.derivation = derivation;
-        this.encoding = encoding;
-        this.macKeySize = macKeySize;
-    }
-
-    public byte[] getDerivationV()
-    {
-        return derivation;
-    }
-
-    public byte[] getEncodingV()
-    {
-        return encoding;
-    }
-
-    public int getMacKeySize()
-    {
-        return macKeySize;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/IESWithCipherParameters.java b/azureus2/src/org/bouncycastle/crypto/params/IESWithCipherParameters.java
deleted file mode 100644
index ef61b2c..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/IESWithCipherParameters.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-
-public class IESWithCipherParameters
-    extends IESParameters
-{
-    private int cipherKeySize;
-
-    /**
-     * @param derivation the derivation parameter for the KDF function.
-     * @param encoding the encoding parameter for the KDF function.
-     * @param macKeySize the size of the MAC key (in bits).
-     * @param cipherKeySize the size of the associated Cipher key (in bits).
-     */
-    public IESWithCipherParameters(
-        byte[]  derivation,
-        byte[]  encoding,
-        int     macKeySize,
-        int     cipherKeySize)
-    {
-        super(derivation, encoding, macKeySize);
-
-        this.cipherKeySize = cipherKeySize;
-    }
-
-    public int getCipherKeySize()
-    {
-        return cipherKeySize;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ISO18033KDFParameters.java b/azureus2/src/org/bouncycastle/crypto/params/ISO18033KDFParameters.java
deleted file mode 100644
index 8dffe2e..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ISO18033KDFParameters.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.DerivationParameters;
-
-/**
- * parameters for Key derivation functions for ISO-18033
- */
-public class ISO18033KDFParameters
-    implements DerivationParameters
-{
-    byte[]  seed;
-
-    public ISO18033KDFParameters(
-        byte[]  seed)
-    {
-        this.seed = seed;
-    }
-
-    public byte[] getSeed()
-    {
-        return seed;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/KDFParameters.java b/azureus2/src/org/bouncycastle/crypto/params/KDFParameters.java
deleted file mode 100644
index b27089c..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/KDFParameters.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.DerivationParameters;
-
-/**
- * parameters for Key derivation functions.
- */
-public class KDFParameters
-    implements DerivationParameters
-{
-    byte[]  iv;
-    byte[]  shared;
-
-    public KDFParameters(
-        byte[]  shared,
-        byte[]  iv)
-    {
-        this.shared = shared;
-        this.iv = iv;
-    }
-
-    public byte[] getSharedSecret()
-    {
-        return shared;
-    }
-
-    public byte[] getIV()
-    {
-        return iv;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/KeyParameter.java b/azureus2/src/org/bouncycastle/crypto/params/KeyParameter.java
deleted file mode 100644
index 5a1c39d..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/KeyParameter.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class KeyParameter
-	implements CipherParameters
-{
-    private byte[]  key;
-
-    public KeyParameter(
-        byte[]  key)
-    {
-        this(key, 0, key.length);
-    }
-
-    public KeyParameter(
-        byte[]  key,
-        int     keyOff,
-        int     keyLen)
-    {
-        this.key = new byte[keyLen];
-
-        System.arraycopy(key, keyOff, this.key, 0, keyLen);
-    }
-
-    public byte[] getKey()
-    {
-        return key;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/MGFParameters.java b/azureus2/src/org/bouncycastle/crypto/params/MGFParameters.java
deleted file mode 100644
index 8c1ea5e..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/MGFParameters.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.DerivationParameters;
-
-/**
- * parameters for mask derivation functions.
- */
-public class MGFParameters
-    implements DerivationParameters
-{
-    byte[]  seed;
-
-    public MGFParameters(
-        byte[]  seed)
-    {
-        this.seed = seed;
-    }
-
-    public MGFParameters(
-        byte[]  seed,
-        int     off,
-        int     len)
-    {
-        this.seed = new byte[len];
-        System.arraycopy(seed, off, this.seed, 0, len);
-    }
-
-    public byte[] getSeed()
-    {
-        return seed;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ParametersWithIV.java b/azureus2/src/org/bouncycastle/crypto/params/ParametersWithIV.java
deleted file mode 100644
index 4a1e6e9..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ParametersWithIV.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class ParametersWithIV
-    implements CipherParameters
-{
-    private byte[]              iv;
-    private CipherParameters    parameters;
-
-    public ParametersWithIV(
-        CipherParameters    parameters,
-        byte[]              iv)
-    {
-        this(parameters, iv, 0, iv.length);
-    }
-
-    public ParametersWithIV(
-        CipherParameters    parameters,
-        byte[]              iv,
-        int                 ivOff,
-        int                 ivLen)
-    {
-        this.iv = new byte[ivLen];
-        this.parameters = parameters;
-
-        System.arraycopy(iv, ivOff, this.iv, 0, ivLen);
-    }
-
-    public byte[] getIV()
-    {
-        return iv;
-    }
-
-    public CipherParameters getParameters()
-    {
-        return parameters;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/ParametersWithRandom.java b/azureus2/src/org/bouncycastle/crypto/params/ParametersWithRandom.java
deleted file mode 100644
index f8b7c82..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/ParametersWithRandom.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class ParametersWithRandom
-    implements CipherParameters
-{
-    private SecureRandom        random;
-    private CipherParameters    parameters;
-
-    public ParametersWithRandom(
-        CipherParameters    parameters,
-        SecureRandom        random)
-    {
-        this.random = random;
-        this.parameters = parameters;
-    }
-
-    public ParametersWithRandom(
-        CipherParameters    parameters)
-    {
-        this.random = null;
-        this.parameters = parameters;
-    }
-
-    public SecureRandom getRandom()
-    {
-        if (random == null)
-        {
-            random = new SecureRandom();
-        }
-        return random;
-    }
-
-    public CipherParameters getParameters()
-    {
-        return parameters;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/RC2Parameters.java b/azureus2/src/org/bouncycastle/crypto/params/RC2Parameters.java
deleted file mode 100644
index 2bfcf69..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/RC2Parameters.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class RC2Parameters
-	implements CipherParameters
-{
-    private byte[]  key;
-    private int     bits;
-
-    public RC2Parameters(
-        byte[]  key)
-    {
-        this(key, (key.length > 128) ? 1024 : (key.length * 8));
-    }
-
-    public RC2Parameters(
-        byte[]  key,
-        int     bits)
-    {
-        this.key = new byte[key.length];
-        this.bits = bits;
-
-        System.arraycopy(key, 0, this.key, 0, key.length);
-    }
-
-    public byte[] getKey()
-    {
-        return key;
-    }
-
-    public int getEffectiveKeyBits()
-    {
-        return bits;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/RC5Parameters.java b/azureus2/src/org/bouncycastle/crypto/params/RC5Parameters.java
deleted file mode 100644
index cca0c51..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/RC5Parameters.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import org.bouncycastle.crypto.CipherParameters;
-
-public class RC5Parameters
-	implements CipherParameters
-{
-    private byte[]  key;
-    private int     rounds;
-
-    public RC5Parameters(
-        byte[]  key,
-        int     rounds)
-    {
-        if (key.length > 255)
-        {
-            throw new IllegalArgumentException("RC5 key length can be no greater than 255");
-        }
-
-        this.key = new byte[key.length];
-        this.rounds = rounds;
-
-        System.arraycopy(key, 0, this.key, 0, key.length);
-    }
-
-    public byte[] getKey()
-    {
-        return key;
-    }
-
-    public int getRounds()
-    {
-        return rounds;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java b/azureus2/src/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java
deleted file mode 100644
index 22db224..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.KeyGenerationParameters;
-
-public class RSAKeyGenerationParameters
-    extends KeyGenerationParameters
-{
-	private BigInteger publicExponent;
-    private int certainty;
-
-    public RSAKeyGenerationParameters(
-		BigInteger		publicExponent,
-        SecureRandom    random,
-        int             strength,
-        int             certainty)
-    {
-        super(random, strength);
-
-		this.publicExponent = publicExponent;
-        this.certainty = certainty;
-    }
-
-	public BigInteger getPublicExponent()
-	{
-		return publicExponent;
-	}
-
-    public int getCertainty()
-    {
-        return certainty;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/RSAKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/RSAKeyParameters.java
deleted file mode 100644
index 4a2d935..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/RSAKeyParameters.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class RSAKeyParameters
-    extends AsymmetricKeyParameter
-{
-    private BigInteger      modulus;
-    private BigInteger      exponent;
-
-    public RSAKeyParameters(
-        boolean     isPrivate,
-        BigInteger  modulus,
-        BigInteger  exponent)
-    {
-        super(isPrivate);
-
-        this.modulus = modulus;
-        this.exponent = exponent;
-    }   
-
-    public BigInteger getModulus()
-    {
-        return modulus;
-    }
-
-    public BigInteger getExponent()
-    {
-        return exponent;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java b/azureus2/src/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java
deleted file mode 100644
index b61cb5c..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.bouncycastle.crypto.params;
-
-import java.math.BigInteger;
-
-public class RSAPrivateCrtKeyParameters
-    extends RSAKeyParameters
-{
-    private BigInteger  e;
-    private BigInteger  p;
-    private BigInteger  q;
-    private BigInteger  dP;
-    private BigInteger  dQ;
-    private BigInteger  qInv;
-
-    /**
-     * 
-     */
-    public RSAPrivateCrtKeyParameters(
-        BigInteger  modulus,
-        BigInteger  publicExponent,
-        BigInteger  privateExponent,
-        BigInteger  p,
-        BigInteger  q,
-        BigInteger  dP,
-        BigInteger  dQ,
-        BigInteger  qInv)
-    {
-        super(true, modulus, privateExponent);
-
-        this.e = publicExponent;
-        this.p = p;
-        this.q = q;
-        this.dP = dP;
-        this.dQ = dQ;
-        this.qInv = qInv;
-    }
-
-    public BigInteger getPublicExponent()
-    {
-        return e;
-    }
-
-    public BigInteger getP()
-    {
-        return p;
-    }
-
-    public BigInteger getQ()
-    {
-        return q;
-    }
-
-    public BigInteger getDP()
-    {
-        return dP;
-    }
-
-    public BigInteger getDQ()
-    {
-        return dQ;
-    }
-
-    public BigInteger getQInv()
-    {
-        return qInv;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/crypto/params/package.html b/azureus2/src/org/bouncycastle/crypto/params/package.html
deleted file mode 100644
index 4e00a75..0000000
--- a/azureus2/src/org/bouncycastle/crypto/params/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Classes for parameter objects for ciphers and generators.
-</body>
-</html>
diff --git a/azureus2/src/org/bouncycastle/crypto/signers/ECDSASigner.java b/azureus2/src/org/bouncycastle/crypto/signers/ECDSASigner.java
deleted file mode 100644
index 1cecf7d..0000000
--- a/azureus2/src/org/bouncycastle/crypto/signers/ECDSASigner.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.bouncycastle.crypto.signers;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
-import org.bouncycastle.crypto.params.ECKeyParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * EC-DSA as described in X9.62
- */
-public class ECDSASigner
-    implements ECConstants, DSA
-{
-	ECKeyParameters key;
-
-	SecureRandom    random;
-
-	public void init(
-        boolean                 forSigning,
-        CipherParameters        param)
-	{
-        if (forSigning)
-        {
-            if (param instanceof ParametersWithRandom)
-            {
-                ParametersWithRandom    rParam = (ParametersWithRandom)param;
-
-                this.random = rParam.getRandom();
-                this.key = (ECPrivateKeyParameters)rParam.getParameters();
-            }
-            else
-            {
-                this.random = new SecureRandom();
-                this.key = (ECPrivateKeyParameters)param;
-            }
-        }
-        else
-        {
-		    this.key = (ECPublicKeyParameters)param;
-        }
-	}
-
-	// 5.3 pg 28
-    /**
-     * generate a signature for the given message using the key we were
-     * initialised with. For conventional DSA the message should be a SHA-1
-     * hash of the message of interest.
-     *
-     * @param message the message that will be verified later.
-     */
-	public BigInteger[] generateSignature(
-        byte[] message)
-	{
-		BigInteger e = new BigInteger(1, message);
-		BigInteger n = key.getParameters().getN();
-
-		BigInteger r = null;
-		BigInteger s = null;
-
-		// 5.3.2
-		do // generate s
-		{
-			BigInteger k = null;
-			int			nBitLength = n.bitLength();
-
-			do // generate r
-			{
-				do
-				{
-					k = new BigInteger(nBitLength, random);
-				}
-				while (k.equals(ZERO));
-
-				ECPoint p = key.getParameters().getG().multiply(k);
-
-				// 5.3.3
-				BigInteger x = p.getX().toBigInteger();
-
-				r = x.mod(n);
-			}
-			while ( r.equals(ZERO) );
-
-			BigInteger d = ((ECPrivateKeyParameters)key).getD();
-
-			s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
-		}
-		while ( s.equals(ZERO) );
-
-        BigInteger[]  res = new BigInteger[2];
-
-        res[0] = r;
-        res[1] = s;
-
-        return res;
-	}
-
-	// 5.4 pg 29
-    /**
-     * return true if the value r and s represent a DSA signature for
-     * the passed in message (for standard DSA the message should be
-     * a SHA-1 hash of the real message to be verified).
-     */
-	public boolean verifySignature(
-        byte[]      message,
-        BigInteger  r,
-        BigInteger  s)
-	{
-		BigInteger e = new BigInteger(1, message);
-		BigInteger n = key.getParameters().getN();
-
-		// r in the range [1,n-1]
-		if ( r.compareTo(ONE) < 0 || r.compareTo(n) >= 0 )
-		{
-			return false;
-		}
-
-		// s in the range [1,n-1]
-		if ( s.compareTo(ONE) < 0 || s.compareTo(n) >= 0 )
-		{
-			return false;
-		}
-
-		BigInteger c = s.modInverse(n);
-
-		BigInteger u1 = e.multiply(c).mod(n);
-		BigInteger u2 = r.multiply(c).mod(n);
-
-		ECPoint G = key.getParameters().getG();
-		ECPoint Q = ((ECPublicKeyParameters)key).getQ();
-
-		ECPoint point = G.multiply(u1).add(Q.multiply(u2));
-
-		BigInteger v = point.getX().toBigInteger().mod(n);
-
-		return v.equals(r);
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/jce/ECNamedCurveTable.java b/azureus2/src/org/bouncycastle/jce/ECNamedCurveTable.java
deleted file mode 100644
index ef80efd..0000000
--- a/azureus2/src/org/bouncycastle/jce/ECNamedCurveTable.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.bouncycastle.jce;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.x9.X962NamedCurves;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
-
-/**
- * a table of locally supported named curves.
- */
-public class ECNamedCurveTable
-{
-    /**
-     * return a parameter spec representing the passed in named
-     * curve. The routine returns null if the curve is not present.
-     * 
-     * @param name the name of the curve requested
-     * @return a parameter spec for the curve, null if it is not available.
-     */
-    public static ECNamedCurveParameterSpec getParameterSpec(
-        String  name)
-    {
-        X9ECParameters  ecP = X962NamedCurves.getByName(name);
-        if (ecP == null)
-        {
-            return null;
-        }
-
-        return new ECNamedCurveParameterSpec(
-                                        name,
-                                        ecP.getCurve(),
-                                        ecP.getG(),
-                                        ecP.getN(),
-                                        ecP.getH(),
-                                        ecP.getSeed());
-
-    }
-
-    /**
-     * return an enumeration of the names of the available curves.
-     *
-     * @return an enumeration of the names of the available curves.
-     */
-    public static Enumeration getNames()
-    {
-        return X962NamedCurves.getNames();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/PKCS10CertificationRequest.java b/azureus2/src/org/bouncycastle/jce/PKCS10CertificationRequest.java
deleted file mode 100644
index 36348a6..0000000
--- a/azureus2/src/org/bouncycastle/jce/PKCS10CertificationRequest.java
+++ /dev/null
@@ -1,311 +0,0 @@
-package org.bouncycastle.jce;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERInputStream;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.pkcs.CertificationRequest;
-import org.bouncycastle.asn1.pkcs.CertificationRequestInfo;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
-/**
- * A class for verifying and creating PKCS10 Certification requests. 
- * <pre>
- * CertificationRequest ::= SEQUENCE {
- *   certificationRequestInfo  CertificationRequestInfo,
- *   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
- *   signature                 BIT STRING
- * }
- *
- * CertificationRequestInfo ::= SEQUENCE {
- *   version             INTEGER { v1(0) } (v1,...),
- *   subject             Name,
- *   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
- *   attributes          [0] Attributes{{ CRIAttributes }}
- *  }
- *
- *  Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
- *
- *  Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
- *    type    ATTRIBUTE.&id({IOSet}),
- *    values  SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
- *  }
- * </pre>
- */
-public class PKCS10CertificationRequest
-    extends CertificationRequest
-{
-    private static Hashtable            algorithms = new Hashtable();
-    private static Hashtable            oids = new Hashtable();
-
-    static
-    {
-        algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
-        algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
-        algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
-        algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
-        algorithms.put("RSAWITHMD5", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
-        algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
-        algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
-        algorithms.put("RSAWITHSHA1", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
-        algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2"));
-        algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2"));
-        algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3"));
-        algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3"));
-        algorithms.put("SHA1WITHECDSA", new DERObjectIdentifier("1.2.840.10045.4.1"));
-        algorithms.put("ECDSAWITHSHA1", new DERObjectIdentifier("1.2.840.10045.4.1"));
-
-        //
-        // reverse mappings
-        //
-        oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA");
-        oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA");
-        oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA");
-        oids.put(new DERObjectIdentifier("1.2.840.10040.4.3"), "DSAWITHSHA1");
-    }
-
-    private static ASN1Sequence toDERSequence(
-        byte[]  bytes)
-    {
-        try
-        {
-            ByteArrayInputStream    bIn = new ByteArrayInputStream(bytes);
-            DERInputStream          dIn = new DERInputStream(bIn);
-
-            return (ASN1Sequence)dIn.readObject();
-        }
-        catch (Exception e)
-        {
-            throw new IllegalArgumentException("badly encoded request");
-        }
-    }
-
-    /**
-     * construct a PKCS10 certification request from a DER encoded
-     * byte stream.
-     */
-    public PKCS10CertificationRequest(
-        byte[]  bytes)
-    {
-        super(toDERSequence(bytes));
-    }
-
-    public PKCS10CertificationRequest(
-        ASN1Sequence  sequence)
-    {
-        super(sequence);
-    }
-
-    /**
-     * create a PKCS10 certfication request using the BC provider.
-     */
-    public PKCS10CertificationRequest(
-        String              signatureAlgorithm,
-        X509Name            subject,
-        PublicKey           key,
-        ASN1Set             attributes,
-        PrivateKey          signingKey)
-        throws NoSuchAlgorithmException, NoSuchProviderException,
-                InvalidKeyException, SignatureException
-    {
-        this(signatureAlgorithm, subject, key, attributes, signingKey, BouncyCastleProvider.PROVIDER_NAME);
-    }
-
-    /**
-     * create a PKCS10 certfication request using the named provider.
-     */
-    public PKCS10CertificationRequest(
-        String              signatureAlgorithm,
-        X509Name            subject,
-        PublicKey           key,
-        ASN1Set             attributes,
-        PrivateKey          signingKey,
-        String              provider)
-        throws NoSuchAlgorithmException, NoSuchProviderException,
-                InvalidKeyException, SignatureException
-    {
-        DERObjectIdentifier sigOID = (DERObjectIdentifier)algorithms.get(signatureAlgorithm.toUpperCase());
-
-        if (sigOID == null)
-        {
-            throw new IllegalArgumentException("Unknown signature type requested");
-        }
-
-        if (subject == null)
-        {
-            throw new IllegalArgumentException("subject must not be null");
-        }
-
-        if (key == null)
-        {
-            throw new IllegalArgumentException("public key must not be null");
-        }
-
-        this.sigAlgId = new AlgorithmIdentifier(sigOID, null);
-
-        byte[]                  bytes = key.getEncoded();
-        ByteArrayInputStream    bIn = new ByteArrayInputStream(bytes);
-        DERInputStream          dIn = new DERInputStream(bIn);
-
-        try
-        {
-            this.reqInfo = new CertificationRequestInfo(subject, new SubjectPublicKeyInfo((ASN1Sequence)dIn.readObject()), attributes);
-        }
-        catch (IOException e)
-        {
-            throw new IllegalArgumentException("can't encode public key");
-        }
-
-        Signature sig = null;
-        
-        try
-        {
-            sig = Signature.getInstance(sigAlgId.getObjectId().getId(), provider);
-        }
-        catch (NoSuchAlgorithmException e)
-        {
-            sig = Signature.getInstance(signatureAlgorithm, provider);
-        }
-
-        sig.initSign(signingKey);
-
-        try
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            DEROutputStream         dOut = new DEROutputStream(bOut);
-
-            dOut.writeObject(reqInfo);
-
-            sig.update(bOut.toByteArray());
-        }
-        catch (Exception e)
-        {
-            throw new SecurityException("exception encoding TBS cert request - " + e);
-        }
-
-        this.sigBits = new DERBitString(sig.sign());
-    }
-
-    /**
-     * return the public key associated with the certification request -
-     * the public key is created using the BC provider.
-     */
-    public PublicKey getPublicKey()
-        throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
-    {
-        return getPublicKey(BouncyCastleProvider.PROVIDER_NAME);
-    }
-
-    public PublicKey getPublicKey(
-        String  provider)
-        throws NoSuchAlgorithmException, NoSuchProviderException,
-                InvalidKeyException
-    {
-        SubjectPublicKeyInfo    subjectPKInfo = reqInfo.getSubjectPublicKeyInfo();
-
-        try
-        {
-            X509EncodedKeySpec      xspec = new X509EncodedKeySpec(new DERBitString(subjectPKInfo).getBytes());
-            AlgorithmIdentifier     keyAlg = subjectPKInfo.getAlgorithmId ();
-
-            return KeyFactory.getInstance(keyAlg.getObjectId().getId (), provider).generatePublic(xspec);
-        }
-        catch (InvalidKeySpecException e)
-        {
-            throw new InvalidKeyException("error encoding public key");
-        }
-    }
-
-    /**
-     * verify the request using the BC provider.
-     */
-    public boolean verify()
-        throws NoSuchAlgorithmException, NoSuchProviderException,
-                InvalidKeyException, SignatureException
-    {
-        return verify(BouncyCastleProvider.PROVIDER_NAME);
-    }
-
-    public boolean verify(
-        String provider)
-        throws NoSuchAlgorithmException, NoSuchProviderException,
-                InvalidKeyException, SignatureException
-    {
-        Signature   sig = null;
-
-        try
-        {
-            sig = Signature.getInstance(sigAlgId.getObjectId().getId(), provider);
-        }
-        catch (NoSuchAlgorithmException e)
-        {
-            //
-            // try an alternate
-            //
-            if (oids.get(sigAlgId.getObjectId().getId()) != null)
-            {
-                String  signatureAlgorithm = (String)oids.get(sigAlgId.getObjectId().getId());
-
-                sig = Signature.getInstance(signatureAlgorithm, provider);
-            }
-        }
-
-        sig.initVerify(this.getPublicKey(provider));
-
-        try
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            DEROutputStream         dOut = new DEROutputStream(bOut);
-
-            dOut.writeObject(reqInfo);
-
-            sig.update(bOut.toByteArray());
-        }
-        catch (Exception e)
-        {
-            throw new SecurityException("exception encoding TBS cert request - " + e);
-        }
-
-        return sig.verify(sigBits.getBytes());
-    }
-
-    /**
-     * return a DER encoded byte array representing this object
-     */
-    public byte[] getEncoded()
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-
-        try
-        {
-            dOut.writeObject(this);
-        }
-        catch (IOException e)
-        {
-            throw new RuntimeException(e.toString());
-        }
-
-        return bOut.toByteArray();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/PKCS7SignedData.java b/azureus2/src/org/bouncycastle/jce/PKCS7SignedData.java
deleted file mode 100644
index d7bf42d..0000000
--- a/azureus2/src/org/bouncycastle/jce/PKCS7SignedData.java
+++ /dev/null
@@ -1,597 +0,0 @@
-package org.bouncycastle.jce;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.cert.CRL;
-import java.security.cert.CRLException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.X509CRL;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.bouncycastle.asn1.*;
-import org.bouncycastle.asn1.pkcs.ContentInfo;
-import org.bouncycastle.asn1.pkcs.IssuerAndSerialNumber;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.SignedData;
-import org.bouncycastle.asn1.pkcs.SignerInfo;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.CertificateList;
-import org.bouncycastle.asn1.x509.X509CertificateStructure;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.provider.X509CRLObject;
-import org.bouncycastle.jce.provider.X509CertificateObject;
-
-/**
- * Represents a PKCS#7 object - specifically the "Signed Data"
- * type.
- * <p>
- * How to use it? To verify a signature, do:
- * <pre>
- * PKCS7SignedData pkcs7 = new PKCS7SignedData(der_bytes);		// Create it
- * pkcs7.update(bytes, 0, bytes.length);	// Update checksum
- * boolean verified = pkcs7.verify();		// Does it add up?
- *
- * To sign, do this:
- * PKCS7SignedData pkcs7 = new PKCS7SignedData(privKey, certChain, "MD5");
- * pkcs7.update(bytes, 0, bytes.length);	// Update checksum
- * pkcs7.sign();				// Create digest
- *
- * bytes = pkcs7.getEncoded();			// Write it somewhere
- * </pre>
- * <p>
- * This class is pretty close to obsolete, for a much better (and more complete)
- * implementation of PKCS7 have a look at the org.bouncycastle.cms package.
- */
-public class PKCS7SignedData
-    implements PKCSObjectIdentifiers
-{
-    private int version, signerversion;
-    private Set digestalgos;
-    private Collection certs, crls;
-    private X509Certificate signCert;
-    private byte[] digest;
-    private String digestAlgorithm, digestEncryptionAlgorithm;
-    private Signature sig;
-    private transient PrivateKey privKey;
-
-    private final String ID_PKCS7_DATA = "1.2.840.113549.1.7.1";
-    private final String ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2";
-    private final String ID_MD5 = "1.2.840.113549.2.5";
-    private final String ID_MD2 = "1.2.840.113549.2.2";
-    private final String ID_SHA1 = "1.3.14.3.2.26";
-    private final String ID_RSA = "1.2.840.113549.1.1.1";
-    private final String ID_DSA = "1.2.840.10040.4.1";
-
-    /**
-     * Read an existing PKCS#7 object from a DER encoded byte array using
-     * the BC provider.
-     */
-    public PKCS7SignedData(
-        byte[]  in)
-        throws SecurityException, CRLException, InvalidKeyException,
-        CertificateException, NoSuchProviderException, NoSuchAlgorithmException
-    {
-        this(in, BouncyCastleProvider.PROVIDER_NAME);
-    }
-
-    /**
-     * Read an existing PKCS#7 object from a DER encoded byte array 
-     */
-    public PKCS7SignedData(
-        byte[]  in,
-        String  provider)
-        throws SecurityException, CRLException, InvalidKeyException,
-        CertificateException, NoSuchProviderException, NoSuchAlgorithmException
-    {
-        DERInputStream din = new DERInputStream(new ByteArrayInputStream(in));
-
-        //
-        // Basic checks to make sure it's a PKCS#7 SignedData Object
-        //
-        DERObject pkcs;
-
-        try
-        {
-            pkcs = din.readObject();
-        }
-        catch (IOException e)
-        {
-            throw new SecurityException("can't decode PKCS7SignedData object");
-        }
-
-        if (!(pkcs instanceof ASN1Sequence))
-        {
-            throw new SecurityException("Not a valid PKCS#7 object - not a sequence");
-        }
-
-        ContentInfo content = ContentInfo.getInstance(pkcs);
-
-        if (!content.getContentType().equals(signedData))
-        {
-            throw new SecurityException("Not a valid PKCS#7 signed-data object - wrong header " + content.getContentType().getId());
-        }
-
-
-        SignedData  data = SignedData.getInstance(content.getContent());
-
-        certs = new ArrayList();
-
-        if (data.getCertificates() != null)
-        {
-            Enumeration ec = ASN1Set.getInstance(data.getCertificates()).getObjects();
-
-            while (ec.hasMoreElements())
-            {
-                certs.add(new X509CertificateObject(X509CertificateStructure.getInstance(ec.nextElement())));
-            }
-        }
-
-        crls = new ArrayList();
-
-        if (data.getCRLs() != null)
-        {
-            Enumeration ec = ASN1Set.getInstance(data.getCRLs()).getObjects();
-            while (ec.hasMoreElements())
-            {
-                crls.add(new X509CRLObject(CertificateList.getInstance(ec.nextElement())));
-            }
-        }
-
-        version = data.getVersion().getValue().intValue();
-
-        //
-        // Get the digest algorithm
-        //
-        digestalgos = new HashSet();
-        Enumeration e = data.getDigestAlgorithms().getObjects();
-
-        while (e.hasMoreElements())
-        {
-            ASN1Sequence s = (ASN1Sequence)e.nextElement();
-            DERObjectIdentifier o = (DERObjectIdentifier)s.getObjectAt(0);
-            digestalgos.add(o.getId());
-        }
-
-        //
-        // Get the SignerInfo
-        //
-        ASN1Set signerinfos = data.getSignerInfos();
-        if (signerinfos.size() != 1)
-        {
-            throw new SecurityException("This PKCS#7 object has multiple SignerInfos - only one is supported at this time");
-        }
-
-        SignerInfo signerInfo = SignerInfo.getInstance(signerinfos.getObjectAt(0));
-
-        signerversion = signerInfo.getVersion().getValue().intValue();
-
-        IssuerAndSerialNumber isAnds = signerInfo.getIssuerAndSerialNumber();
-
-        //
-        // Get the signing certificate
-        //
-        BigInteger      serialNumber = isAnds.getCertificateSerialNumber().getValue();
-        X509Principal   issuer = new X509Principal(isAnds.getName());
-
-        for (Iterator i = certs.iterator();i.hasNext();)
-        {
-            X509Certificate cert = (X509Certificate)i.next();
-            if (serialNumber.equals(cert.getSerialNumber())
-                    && issuer.equals(cert.getIssuerDN()))
-            {
-                signCert = cert;
-                break;
-            }
-        }
-
-        if (signCert == null)
-        {
-            throw new SecurityException("Can't find signing certificate with serial "+serialNumber.toString(16)); 
-        }
-
-        digestAlgorithm = signerInfo.getDigestAlgorithm().getObjectId().getId();
-
-        digest = signerInfo.getEncryptedDigest().getOctets();
-        digestEncryptionAlgorithm = signerInfo.getDigestEncryptionAlgorithm().getObjectId().getId();
-
-        sig = Signature.getInstance(getDigestAlgorithm(), provider);
-
-        sig.initVerify(signCert.getPublicKey());
-    }
-
-    /**
-     * Create a new PKCS#7 object from the specified key using the BC provider.
-     *
-     * @param the private key to be used for signing.
-     * @param the certifiacate chain associated with the private key.
-     * @param hashAlgorithm the hashing algorithm used to compute the message digest. Must be "MD5", "MD2", "SHA1" or "SHA"
-     */
-    public PKCS7SignedData(
-        PrivateKey      privKey,
-        Certificate[]   certChain,
-        String          hashAlgorithm)
-        throws SecurityException, InvalidKeyException,
-        NoSuchProviderException, NoSuchAlgorithmException
-    {
-        this(privKey, certChain, hashAlgorithm, BouncyCastleProvider.PROVIDER_NAME);
-    }
-
-    /**
-     * Create a new PKCS#7 object from the specified key.
-     *
-     * @param privKey the private key to be used for signing.
-     * @param certChain the certificate chain associated with the private key.
-     * @param hashAlgorithm the hashing algorithm used to compute the message digest. Must be "MD5", "MD2", "SHA1" or "SHA"
-     * @param provider the provider to use.
-     */
-    public PKCS7SignedData(
-        PrivateKey      privKey,
-        Certificate[]   certChain,
-        String          hashAlgorithm,
-        String          provider)
-        throws SecurityException, InvalidKeyException,
-        NoSuchProviderException, NoSuchAlgorithmException
-    {
-        this(privKey, certChain, null, hashAlgorithm, provider);
-    }
-
-    /**
-     * Create a new PKCS#7 object from the specified key.
-     *
-     * @param privKey the private key to be used for signing.
-     * @param certChain the certificate chain associated with the private key.
-     * @param crlList the crl list associated with the private key.
-     * @param hashAlgorithm the hashing algorithm used to compute the message digest. Must be "MD5", "MD2", "SHA1" or "SHA"
-     * @param provider the provider to use.
-     */
-    public PKCS7SignedData(
-        PrivateKey      privKey,
-        Certificate[]   certChain,
-        CRL[]           crlList,
-        String          hashAlgorithm,
-        String          provider)
-        throws SecurityException, InvalidKeyException,
-        NoSuchProviderException, NoSuchAlgorithmException
-    {
-        this.privKey = privKey;
-
-        if (hashAlgorithm.equals("MD5"))
-        {
-            digestAlgorithm = ID_MD5;
-        }
-        else if (hashAlgorithm.equals("MD2"))
-        {
-            digestAlgorithm = ID_MD2;
-        }
-        else if (hashAlgorithm.equals("SHA"))
-        {
-            digestAlgorithm = ID_SHA1;
-        }
-        else if (hashAlgorithm.equals("SHA1"))
-        {
-            digestAlgorithm = ID_SHA1;
-        }
-        else
-        {
-            throw new NoSuchAlgorithmException("Unknown Hash Algorithm "+hashAlgorithm);
-        }
-
-        version = signerversion = 1;
-        certs = new ArrayList();
-        crls = new ArrayList();
-        digestalgos = new HashSet();
-        digestalgos.add(digestAlgorithm);
-
-        //
-        // Copy in the certificates and crls used to sign the private key.
-        //
-        signCert = (X509Certificate)certChain[0];
-        for (int i = 0;i < certChain.length;i++)
-        {
-            certs.add(certChain[i]);
-        }
-
-        if (crlList != null)
-        {
-            for (int i = 0;i < crlList.length;i++)
-            {
-                crls.add(crlList[i]);
-            }
-        }
-
-        //
-        // Now we have private key, find out what the digestEncryptionAlgorithm is.
-        //
-        digestEncryptionAlgorithm = privKey.getAlgorithm();
-        if (digestEncryptionAlgorithm.equals("RSA"))
-        {
-            digestEncryptionAlgorithm = ID_RSA;
-        }
-        else if (digestEncryptionAlgorithm.equals("DSA"))
-        {
-            digestEncryptionAlgorithm = ID_DSA;
-        }
-        else
-        {
-            throw new NoSuchAlgorithmException("Unknown Key Algorithm "+digestEncryptionAlgorithm);
-        }
-
-        sig = Signature.getInstance(getDigestAlgorithm(), provider);
-
-        sig.initSign(privKey);
-    }
-
-    /**
-     * Get the algorithm used to calculate the message digest
-     */
-    public String getDigestAlgorithm()
-    {
-        String da = digestAlgorithm;
-        String dea = digestEncryptionAlgorithm;
-
-        if (digestAlgorithm.equals(ID_MD5))
-        {
-            da = "MD5";
-        }
-	    else if (digestAlgorithm.equals(ID_MD2))
-        {
-            da = "MD2";
-        }
-	    else if (digestAlgorithm.equals(ID_SHA1))
-        {
-            da = "SHA1";
-        }
-
-        if (digestEncryptionAlgorithm.equals(ID_RSA))
-        {
-            dea = "RSA";
-        }
-	    else if (digestEncryptionAlgorithm.equals(ID_DSA))
-        {
-            dea = "DSA";
-        }
-
-        return da + "with" + dea;
-    }
-
-    /**
-     * Resets the PKCS7SignedData object to it's initial state, ready
-     * to sign or verify a new buffer.
-     */
-    public void reset()
-    {
-        try
-        {
-            if (privKey==null)
-            {
-                sig.initVerify(signCert.getPublicKey());
-            }
-            else
-            {
-                sig.initSign(privKey);
-            }
-        }
-        catch (Exception e)
-        {
-            throw new RuntimeException(e.toString());
-        }
-    }
-
-    /**
-     * Get the X.509 certificates associated with this PKCS#7 object
-     */
-    public Certificate[] getCertificates()
-    {
-        return (X509Certificate[])certs.toArray(new X509Certificate[certs.size()]);
-    }
-
-    /**
-     * Get the X.509 certificate revocation lists associated with this PKCS#7 object
-     */
-    public Collection getCRLs()
-    {
-        return crls;
-    }
-    
-    /**
-     * Get the X.509 certificate actually used to sign the digest.
-     */
-    public X509Certificate getSigningCertificate()
-    {
-        return signCert;
-    }
-
-    /**
-     * Get the version of the PKCS#7 object. Always 1
-     */
-    public int getVersion()
-    {
-        return version;
-    }
-
-    /**
-     * Get the version of the PKCS#7 "SignerInfo" object. Always 1
-     */
-    public int getSigningInfoVersion()
-    {
-        return signerversion;
-    }
-
-    /**
-     * Update the digest with the specified byte. This method is used both for signing and verifying
-     */
-    public void update(byte buf)
-        throws SignatureException
-    {
-        sig.update(buf);
-    }
-
-    /**
-     * Update the digest with the specified bytes. This method is used both for signing and verifying
-     */
-    public void update(byte[] buf, int off, int len)
-        throws SignatureException
-    {
-        sig.update(buf, off, len);
-    }
-
-    /**
-     * Verify the digest
-     */
-    public boolean verify()
-        throws SignatureException
-    {
-        return sig.verify(digest);
-    }
-
-    /**
-     * Get the "issuer" from the TBSCertificate bytes that are passed in
-     */
-    private DERObject getIssuer(byte[] enc)
-    {
-        try
-        {
-            DERInputStream in = new DERInputStream(new ByteArrayInputStream(enc));
-            ASN1Sequence seq = (ASN1Sequence)in.readObject();
-            return (DERObject)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 3 : 2);
-        }
-        catch (IOException e)
-        {
-            throw new Error("IOException reading from ByteArray: "+e);
-	    }
-    }
-
-    /**
-     * return the bytes for the PKCS7SignedData object.
-     */
-    public byte[] getEncoded()
-    {
-        try
-        {
-        
-            digest = sig.sign();
-
-            // Create the set of Hash algorithms. I've assumed this is the
-            // set of all hash agorithms used to created the digest in the
-            // "signerInfo" structure. I may be wrong.
-            //
-            ASN1EncodableVector v = new ASN1EncodableVector();
-            for (Iterator i = digestalgos.iterator(); i.hasNext();)
-            {
-                AlgorithmIdentifier a = new AlgorithmIdentifier(
-                            new DERObjectIdentifier((String)i.next()),
-                            null);
-                
-                v.add(a);
-            }
-
-            DERSet algos = new DERSet(v);
-
-            // Create the contentInfo. Empty, I didn't implement this bit
-            //
-            DERSequence contentinfo = new DERSequence(
-                                        new DERObjectIdentifier(ID_PKCS7_DATA));
-
-            // Get all the certificates
-            //
-            v = new ASN1EncodableVector();
-            for (Iterator i = certs.iterator();i.hasNext();)
-            {
-                DERInputStream tempstream = new DERInputStream(new ByteArrayInputStream(((X509Certificate)i.next()).getEncoded()));
-                v.add(tempstream.readObject());
-            }
-
-            DERSet dercertificates = new DERSet(v);
-
-            // Create signerinfo structure.
-            //
-            ASN1EncodableVector signerinfo = new ASN1EncodableVector();
-
-            // Add the signerInfo version
-            //
-            signerinfo.add(new DERInteger(signerversion));
-
-            IssuerAndSerialNumber isAnds = new IssuerAndSerialNumber(
-                        new X509Name((ASN1Sequence)getIssuer(signCert.getTBSCertificate())),
-                        new DERInteger(signCert.getSerialNumber()));
-            signerinfo.add(isAnds);
-
-            // Add the digestAlgorithm
-            //
-            signerinfo.add(new AlgorithmIdentifier(
-                                new DERObjectIdentifier(digestAlgorithm),
-                                new DERNull()));
-
-            //
-            // Add the digestEncryptionAlgorithm
-            //
-            signerinfo.add(new AlgorithmIdentifier(
-                                new DERObjectIdentifier(digestEncryptionAlgorithm),
-                                new DERNull()));
-
-            //
-            // Add the digest
-            //
-            signerinfo.add(new DEROctetString(digest));
-
-
-            //
-            // Finally build the body out of all the components above
-            //
-            ASN1EncodableVector body = new ASN1EncodableVector();
-            body.add(new DERInteger(version));
-            body.add(algos);
-            body.add(contentinfo);
-            body.add(new DERTaggedObject(false, 0, dercertificates));
-
-            if (crls.size()>0) {
-                v = new ASN1EncodableVector();
-                for (Iterator i = crls.iterator();i.hasNext();) {
-                    DERInputStream t = new DERInputStream(new ByteArrayInputStream((((X509CRL)i.next()).getEncoded())));
-                    v.add(t.readObject());
-                }
-                DERSet dercrls = new DERSet(v);
-                body.add(new DERTaggedObject(false, 1, dercrls));
-            }
-
-            // Only allow one signerInfo
-            //
-            body.add(new DERSet(new DERSequence(signerinfo)));
-
-            // Now we have the body, wrap it in it's PKCS7Signed shell
-            // and return it
-            //
-            ASN1EncodableVector whole = new ASN1EncodableVector();
-            whole.add(new DERObjectIdentifier(ID_PKCS7_SIGNED_DATA));
-            whole.add(new DERTaggedObject(0, new DERSequence(body)));
-
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-
-            DEROutputStream dout = new DEROutputStream(bOut);
-            dout.writeObject(new DERSequence(whole));
-            dout.close();
-
-            return bOut.toByteArray();
-        }
-        catch (Exception e)
-        {
-            throw new RuntimeException(e.toString());
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/PrincipalUtil.java b/azureus2/src/org/bouncycastle/jce/PrincipalUtil.java
deleted file mode 100644
index 0ccaf2c..0000000
--- a/azureus2/src/org/bouncycastle/jce/PrincipalUtil.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.bouncycastle.jce;
-
-import java.io.*;
-import java.security.cert.*;
-
-import org.bouncycastle.asn1.*;
-import org.bouncycastle.asn1.x509.*;
-
-/**
- * a utility class that will extract X509Principal objects from X.509 certificates.
- */
-public class PrincipalUtil
-{
-    /**
-     * return the issuer of the given cert as an X509PrincipalObject.
-     */
-    public static X509Principal getIssuerX509Principal(
-        X509Certificate cert)
-        throws CertificateEncodingException
-    {
-        try
-        {
-            ByteArrayInputStream    bIn = new ByteArrayInputStream(
-                cert.getTBSCertificate());
-            ASN1InputStream         aIn = new ASN1InputStream(bIn);
-            TBSCertificateStructure tbsCert = new TBSCertificateStructure(
-                                            (ASN1Sequence)aIn.readObject());
-
-            return new X509Principal(tbsCert.getIssuer());
-        }
-        catch (IOException e)
-        {
-            throw new CertificateEncodingException(e.toString());
-        }
-    }
-
-    /**
-     * return the subject of the given cert as an X509PrincipalObject.
-     */
-    public static X509Principal getSubjectX509Principal(
-        X509Certificate cert)
-        throws CertificateEncodingException
-    {
-        try
-        {
-            ByteArrayInputStream    bIn = new ByteArrayInputStream(
-                cert.getTBSCertificate());
-            ASN1InputStream         aIn = new ASN1InputStream(bIn);
-            TBSCertificateStructure tbsCert = new TBSCertificateStructure(
-                                            (ASN1Sequence)aIn.readObject());
-
-            return new X509Principal(tbsCert.getSubject());
-        }
-        catch (IOException e)
-        {
-            throw new CertificateEncodingException(e.toString());
-        }
-    }
-    
-	/**
-	 * return the issuer of the given CRL as an X509PrincipalObject.
-	 */
-	public static X509Principal getIssuerX509Principal(
-		X509CRL crl)
-		throws CRLException
-	{
-		try
-		{
-			ByteArrayInputStream    bIn = new ByteArrayInputStream(
-				crl.getTBSCertList());
-			ASN1InputStream         aIn = new ASN1InputStream(bIn);
-			TBSCertList tbsCertList = new TBSCertList(
-											(ASN1Sequence)aIn.readObject());
-
-			return new X509Principal(tbsCertList.getIssuer());
-		}
-		catch (IOException e)
-		{
-			throw new CRLException(e.toString());
-		}
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/jce/X509KeyUsage.java b/azureus2/src/org/bouncycastle/jce/X509KeyUsage.java
deleted file mode 100644
index 11a7f64..0000000
--- a/azureus2/src/org/bouncycastle/jce/X509KeyUsage.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.bouncycastle.jce;
-
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.x509.KeyUsage;
-
-/**
- * A holding class for constructing an X509 Key Usage extension.
- *
- * <pre>
- *    id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
- *
- *    KeyUsage ::= BIT STRING {
- *         digitalSignature        (0),
- *         nonRepudiation          (1),
- *         keyEncipherment         (2),
- *         dataEncipherment        (3),
- *         keyAgreement            (4),
- *         keyCertSign             (5),
- *         cRLSign                 (6),
- *         encipherOnly            (7),
- *         decipherOnly            (8) }
- * </pre>
- */
-public class X509KeyUsage
-    implements DEREncodable
-{
-    public static final int        digitalSignature = (1 << 7); 
-    public static final int        nonRepudiation   = (1 << 6);
-    public static final int        keyEncipherment  = (1 << 5);
-    public static final int        dataEncipherment = (1 << 4);
-    public static final int        keyAgreement     = (1 << 3);
-    public static final int        keyCertSign      = (1 << 2);
-    public static final int        cRLSign          = (1 << 1);
-    public static final int        encipherOnly     = (1 << 0);
-    public static final int        decipherOnly     = (1 << 15);
-
-    private int usage = 0;
-
-    /**
-     * Basic constructor.
-     * 
-     * @param usage - the bitwise OR of the Key Usage flags giving the
-     * allowed uses for the key.
-     * e.g. (X509KeyUsage.keyEncipherment | X509KeyUsage.dataEncipherment)
-     */
-    public X509KeyUsage(
-        int usage)
-    {
-        this.usage = usage;
-    }
-
-    public DERObject getDERObject()
-    {
-        return new KeyUsage(usage);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/X509Principal.java b/azureus2/src/org/bouncycastle/jce/X509Principal.java
deleted file mode 100644
index 3cdd548..0000000
--- a/azureus2/src/org/bouncycastle/jce/X509Principal.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.bouncycastle.jce;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.Principal;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.x509.X509Name;
-
-public class X509Principal
-    extends X509Name
-    implements Principal
-{
-    /**
-     * Constructor from an encoded byte array.
-     */
-    public X509Principal(
-        byte[]  bytes)
-        throws IOException
-    {
-        super((ASN1Sequence)(new ASN1InputStream(new ByteArrayInputStream(bytes)).readObject()));
-    }
-
-    /**
-     * Constructor from an X509Name object.
-     */
-    public X509Principal(
-        X509Name  name)
-    {
-        super((ASN1Sequence)name.getDERObject());
-    }
-
-    /**
-     * constructor from a table of attributes.
-     * <p>
-     * it's is assumed the table contains OID/String pairs.
-     */
-    public X509Principal(
-        Hashtable  attributes)
-    {
-        super(attributes);
-    }
-
-    /**
-     * constructor from a table of attributes and a vector giving the
-     * specific ordering required for encoding or conversion to a string.
-     * <p>
-     * it's is assumed the table contains OID/String pairs.
-     */
-    public X509Principal(
-        Vector      ordering,
-        Hashtable   attributes)
-    {
-        super(ordering, attributes);
-    }
-
-    /**
-     * constructor from a vector of attribute values and a vector of OIDs.
-     */
-    public X509Principal(
-        Vector      oids,
-        Vector      values)
-    {
-        super(oids, values);
-    }
-
-    /**
-     * takes an X509 dir name as a string of the format "C=AU,ST=Victoria", or
-     * some such, converting it into an ordered set of name attributes.
-     */
-    public X509Principal(
-        String  dirName)
-    {
-        super(dirName);
-    }
-
-    /**
-     * Takes an X509 dir name as a string of the format "C=AU,ST=Victoria", or
-     * some such, converting it into an ordered set of name attributes. If reverse
-     * is false the dir name will be encoded in the order of the (name, value) pairs 
-     * presented, otherwise the encoding will start with the last (name, value) pair
-     * and work back.
-     */
-    public X509Principal(
-        boolean reverse,
-        String  dirName)
-    {
-        super(reverse, dirName);
-    }
-
-    /**
-     * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
-     * some such, converting it into an ordered set of name attributes. lookUp 
-     * should provide a table of lookups, indexed by lowercase only strings and
-     * yielding a DERObjectIdentifier, other than that OID. and numeric oids
-     * will be processed automatically.
-     * <p>
-     * If reverse is true, create the encoded version of the sequence starting
-     * from the last element in the string.
-     */
-    public X509Principal(
-        boolean     reverse,
-        Hashtable   lookUp,
-        String      dirName)
-    {
-        super(reverse, lookUp, dirName);
-    }
-
-    public String getName()
-    {
-        return this.toString();
-    }
-
-    /**
-     * return a DER encoded byte array representing this object
-     */
-    public byte[] getEncoded()
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-
-        try
-        {
-            dOut.writeObject(this);
-        }
-        catch (IOException e)
-        {
-            throw new RuntimeException(e.toString());
-        }
-
-        return bOut.toByteArray();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/X509V1CertificateGenerator.java b/azureus2/src/org/bouncycastle/jce/X509V1CertificateGenerator.java
deleted file mode 100644
index 6060cc7..0000000
--- a/azureus2/src/org/bouncycastle/jce/X509V1CertificateGenerator.java
+++ /dev/null
@@ -1,261 +0,0 @@
-package org.bouncycastle.jce;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.cert.X509Certificate;
-import java.util.Date;
-import java.util.Hashtable;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERInputStream;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.TBSCertificateStructure;
-import org.bouncycastle.asn1.x509.Time;
-import org.bouncycastle.asn1.x509.V1TBSCertificateGenerator;
-import org.bouncycastle.asn1.x509.X509CertificateStructure;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.provider.X509CertificateObject;
-
-/**
- * class to produce an X.509 Version 1 certificate.
- */
-public class X509V1CertificateGenerator
-{
-    private V1TBSCertificateGenerator   tbsGen;
-    private DERObjectIdentifier         sigOID;
-    private AlgorithmIdentifier         sigAlgId;
-    private String                      signatureAlgorithm;
-
-    private static Hashtable            algorithms = new Hashtable();
-
-    static
-    {
-		algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
-		algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
-		algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
-		algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
-		algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
-		algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
-		algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2"));
-		algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2"));
-		algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3"));
-		algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3"));
-		algorithms.put("SHA1WITHECDSA", new DERObjectIdentifier("1.2.840.10045.4.1"));
-		algorithms.put("ECDSAWITHSHA1", new DERObjectIdentifier("1.2.840.10045.4.1"));
-    }
-
-    public X509V1CertificateGenerator()
-    {
-        tbsGen = new V1TBSCertificateGenerator();
-    }
-
-    /**
-     * reset the generator
-     */
-    public void reset()
-    {
-        tbsGen = new V1TBSCertificateGenerator();
-    }
-
-    /**
-     * set the serial number for the certificate.
-     */
-    public void setSerialNumber(
-        BigInteger      serialNumber)
-    {
-        tbsGen.setSerialNumber(new DERInteger(serialNumber));
-    }
-
-    /**
-     * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
-     * certificate.
-     */
-    public void setIssuerDN(
-        X509Name   issuer)
-    {
-        tbsGen.setIssuer(issuer);
-    }
-
-    public void setNotBefore(
-        Date    date)
-    {
-        tbsGen.setStartDate(new Time(date));
-    }
-
-    public void setNotAfter(
-        Date    date)
-    {
-        tbsGen.setEndDate(new Time(date));
-    }
-
-    /**
-     * Set the subject distinguished name. The subject describes the entity associated with the public key.
-     */
-    public void setSubjectDN(
-        X509Name   subject)
-    {
-        tbsGen.setSubject(subject);
-    }
-
-    public void setPublicKey(
-        PublicKey       key)
-    {
-        try
-        {
-            tbsGen.setSubjectPublicKeyInfo(new SubjectPublicKeyInfo((ASN1Sequence)new DERInputStream(
-                                new ByteArrayInputStream(key.getEncoded())).readObject()));
-        }
-        catch (Exception e)
-        {
-            throw new IllegalArgumentException("unable to process key - " + e.toString());
-        }
-    }
-
-    public void setSignatureAlgorithm(
-        String  signatureAlgorithm)
-    {
-        this.signatureAlgorithm = signatureAlgorithm;
-
-        sigOID = (DERObjectIdentifier)algorithms.get(signatureAlgorithm.toUpperCase());
-
-        if (sigOID == null)
-        {
-            throw new IllegalArgumentException("Unknown signature type requested");
-        }
-
-        sigAlgId = new AlgorithmIdentifier(this.sigOID, new DERNull());
-
-        tbsGen.setSignature(sigAlgId);
-    }
-
-    /**
-     * generate an X509 certificate, based on the current issuer and subject
-     * using the default provider "BC".
-     */
-    public X509Certificate generateX509Certificate(
-        PrivateKey      key)
-        throws SecurityException, SignatureException, InvalidKeyException
-    {
-        try
-        {
-            return generateX509Certificate(key, BouncyCastleProvider.PROVIDER_NAME, null);
-        }
-        catch (NoSuchProviderException e)
-        {
-            throw new SecurityException("BC provider not installed!");
-        }
-    }
-
-    /**
-     * generate an X509 certificate, based on the current issuer and subject
-     * using the default provider "BC" and the passed in source of randomness
-     */
-    public X509Certificate generateX509Certificate(
-        PrivateKey      key,
-        SecureRandom    random)
-        throws SecurityException, SignatureException, InvalidKeyException
-    {
-        try
-        {
-            return generateX509Certificate(key, BouncyCastleProvider.PROVIDER_NAME, random);
-        }
-        catch (NoSuchProviderException e)
-        {
-            throw new SecurityException("BC provider not installed!");
-        }
-    }
-
-    /**
-     * generate an X509 certificate, based on the current issuer and subject,
-     * using the passed in provider for the signing, and the passed in source
-     * of randomness (if required).
-     */
-    public X509Certificate generateX509Certificate(
-        PrivateKey      key,
-        String          provider)
-        throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
-    {
-        return generateX509Certificate(key, provider, null);
-    }
-
-    /**
-     * generate an X509 certificate, based on the current issuer and subject,
-     * using the passed in provider for the signing, and the passed in source
-     * of randomness (if required).
-     */
-    public X509Certificate generateX509Certificate(
-        PrivateKey      key,
-        String          provider,
-        SecureRandom    random)
-        throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
-    {
-        Signature sig = null;
-
-        try
-        {
-            sig = Signature.getInstance(sigOID.getId(), provider);
-        }
-        catch (NoSuchAlgorithmException ex)
-        {
-            try
-            {
-                sig = Signature.getInstance(signatureAlgorithm, provider);
-            }
-            catch (NoSuchAlgorithmException e)
-            {
-                throw new SecurityException("exception creating signature: " + e.toString());
-            }
-        }
-
-        if (random != null)
-        {
-            sig.initSign(key, random);
-        }
-        else
-        {
-            sig.initSign(key);
-        }
-
-        TBSCertificateStructure tbsCert = tbsGen.generateTBSCertificate();
-
-        try
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            DEROutputStream         dOut = new DEROutputStream(bOut);
-
-            dOut.writeObject(tbsCert);
-
-            sig.update(bOut.toByteArray());
-        }
-        catch (Exception e)
-        {
-            throw new SecurityException("exception encoding TBS cert - " + e);
-        }
-
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(tbsCert);
-        v.add(sigAlgId);
-        v.add(new DERBitString(sig.sign()));
-
-        return new X509CertificateObject(new X509CertificateStructure(new DERSequence(v)));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/X509V2CRLGenerator.java b/azureus2/src/org/bouncycastle/jce/X509V2CRLGenerator.java
deleted file mode 100644
index 3e48ae7..0000000
--- a/azureus2/src/org/bouncycastle/jce/X509V2CRLGenerator.java
+++ /dev/null
@@ -1,323 +0,0 @@
-package org.bouncycastle.jce;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.cert.X509CRL;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Hashtable;
-import java.util.SimpleTimeZone;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERUTCTime;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.CertificateList;
-import org.bouncycastle.asn1.x509.TBSCertList;
-import org.bouncycastle.asn1.x509.V2TBSCertListGenerator;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.provider.X509CRLObject;
-
-/**
- * class to produce an X.509 Version 2 CRL.
- * <p>
- * <b>Note:</b> This class may be subject to change.
- */
-public class X509V2CRLGenerator
-{
-    private SimpleDateFormat            dateF = new SimpleDateFormat("yyMMddHHmmss");
-    private SimpleTimeZone              tz = new SimpleTimeZone(0, "Z");
-    private V2TBSCertListGenerator      tbsGen;
-    private DERObjectIdentifier         sigOID;
-    private AlgorithmIdentifier         sigAlgId;
-    private String                      signatureAlgorithm;
-    private Hashtable                   extensions = null;
-    private Vector                      extOrdering = null;
-
-    private static Hashtable            algorithms = new Hashtable();
-
-    static
-    {
-        algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
-        algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
-        algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
-        algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
-        algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
-        algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
-        algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2"));
-        algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2"));
-        algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3"));
-        algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3"));
-        algorithms.put("SHA1WITHECDSA", new DERObjectIdentifier("1.2.840.10045.4.1"));
-        algorithms.put("ECDSAWITHSHA1", new DERObjectIdentifier("1.2.840.10045.4.1"));
-    }
-
-    public X509V2CRLGenerator()
-    {
-        dateF.setTimeZone(tz);
-
-        tbsGen = new V2TBSCertListGenerator();
-    }
-
-    /**
-     * reset the generator
-     */
-    public void reset()
-    {
-        tbsGen = new V2TBSCertListGenerator();
-    }
-
-
-    /**
-     * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
-     * certificate.
-     */
-    public void setIssuerDN(
-        X509Name   issuer)
-    {
-        tbsGen.setIssuer(issuer);
-    }
-
-    public void setThisUpdate(
-        Date    date)
-    {
-        tbsGen.setThisUpdate(new DERUTCTime(dateF.format(date) + "Z"));
-    }
-
-    public void setNextUpdate(
-        Date    date)
-    {
-        tbsGen.setNextUpdate(new DERUTCTime(dateF.format(date) + "Z"));
-    }
-
-    /**
-     * Reason being as indicated by ReasonFlags, i.e. ReasonFlags.KEY_COMPROMISE
-     * or 0 if ReasonFlags are not to be used
-     **/
-    public void addCRLEntry(BigInteger userCertificate, Date revocationDate, int reason)
-    {
-        tbsGen.addCRLEntry(new DERInteger(userCertificate), new DERUTCTime(dateF.format(revocationDate) + "Z"), reason);
-    }
-
-    public void setSignatureAlgorithm(
-        String  signatureAlgorithm)
-    {
-        this.signatureAlgorithm = signatureAlgorithm;
-
-        sigOID = (DERObjectIdentifier)algorithms.get(signatureAlgorithm.toUpperCase());
-
-        if (sigOID == null)
-        {
-            throw new IllegalArgumentException("Unknown signature type requested");
-        }
-
-        sigAlgId = new AlgorithmIdentifier(this.sigOID, null);
-
-        tbsGen.setSignature(sigAlgId);
-    }
-
-    /**
-     * add a given extension field for the standard extensions tag (tag 3)
-     */
-    public void addExtension(
-        String          OID,
-        boolean         critical,
-        DEREncodable    value)
-    {
-        this.addExtension(new DERObjectIdentifier(OID), critical, value);
-    }
-
-    /**
-     * add a given extension field for the standard extensions tag (tag 0)
-     */
-    public void addExtension(
-        DERObjectIdentifier OID,
-        boolean             critical,
-        DEREncodable        value)
-    {
-        if (extensions == null)
-        {
-            extensions = new Hashtable();
-            extOrdering = new Vector();
-        }
-
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-
-        try
-        {
-            dOut.writeObject(value);
-        }
-        catch (IOException e)
-        {
-            throw new IllegalArgumentException("error encoding value: " + e);
-        }
-
-        this.addExtension(OID, critical, bOut.toByteArray());
-    }
-
-    /**
-     * add a given extension field for the standard extensions tag (tag 0)
-     */
-    public void addExtension(
-        String          OID,
-        boolean         critical,
-        byte[]          value)
-    {
-        this.addExtension(new DERObjectIdentifier(OID), critical, value);
-    }
-
-    /**
-     * add a given extension field for the standard extensions tag (tag 0)
-     */
-    public void addExtension(
-        DERObjectIdentifier OID,
-        boolean             critical,
-        byte[]              value)
-    {
-        if (extensions == null)
-        {
-            extensions = new Hashtable();
-            extOrdering = new Vector();
-        }
-
-        extensions.put(OID, new X509Extension(critical, new DEROctetString(value)));
-        extOrdering.addElement(OID);
-    }
-
-    /**
-     * generate an X509 CRL, based on the current issuer and subject
-     * using the default provider "BC".
-     */
-    public X509CRL generateX509CRL(
-        PrivateKey      key)
-        throws SecurityException, SignatureException, InvalidKeyException
-    {
-        try
-        {
-            return generateX509CRL(key, BouncyCastleProvider.PROVIDER_NAME, null);
-        }
-        catch (NoSuchProviderException e)
-        {
-            throw new SecurityException("BC provider not installed!");
-        }
-    }
-
-    /**
-     * generate an X509 CRL, based on the current issuer and subject
-     * using the default provider "BC" and an user defined SecureRandom object as
-     * source of randomness.
-     */
-    public X509CRL generateX509CRL(
-        PrivateKey      key,
-        SecureRandom    random)
-        throws SecurityException, SignatureException, InvalidKeyException
-    {
-        try
-        {
-            return generateX509CRL(key, BouncyCastleProvider.PROVIDER_NAME, random);
-        }
-        catch (NoSuchProviderException e)
-        {
-            throw new SecurityException("BC provider not installed!");
-        }
-    }
-
-    /**
-     * generate an X509 certificate, based on the current issuer and subject
-     * using the passed in provider for the signing.
-     */
-    public X509CRL generateX509CRL(
-        PrivateKey      key,
-        String          provider)
-        throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
-    {
-        return generateX509CRL(key, provider, null);
-    }
-
-    /**
-     * generate an X509 CRL, based on the current issuer and subject,
-     * using the passed in provider for the signing.
-     */
-    public X509CRL generateX509CRL(
-        PrivateKey      key,
-        String          provider,
-        SecureRandom    random)
-        throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
-    {
-        Signature sig = null;
-
-        try
-        {
-            sig = Signature.getInstance(sigOID.getId(), provider);
-        }
-        catch (NoSuchAlgorithmException ex)
-        {
-            try
-            {
-                sig = Signature.getInstance(signatureAlgorithm, provider);
-            }
-            catch (NoSuchAlgorithmException e)
-            {
-                throw new SecurityException("exception creating signature: " + e.toString());
-            }
-        }
-
-        if (random != null)
-        {
-            sig.initSign(key, random);
-        }
-        else
-        {
-            sig.initSign(key);
-        }
-
-        if (extensions != null)
-        {
-            tbsGen.setExtensions(new X509Extensions(extOrdering, extensions));
-        }
-
-        TBSCertList tbsCrl = tbsGen.generateTBSCertList();
-
-        try
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            DEROutputStream         dOut = new DEROutputStream(bOut);
-
-            dOut.writeObject(tbsCrl);
-
-            sig.update(bOut.toByteArray());
-        }
-        catch (Exception e)
-        {
-            throw new SecurityException("exception encoding TBS cert - " + e);
-        }
-
-        // Construct the CRL
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(tbsCrl);
-        v.add(sigAlgId);
-        v.add(new DERBitString(sig.sign()));
-
-        return new X509CRLObject(new CertificateList(new DERSequence(v)));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/X509V3CertificateGenerator.java b/azureus2/src/org/bouncycastle/jce/X509V3CertificateGenerator.java
deleted file mode 100644
index 2a18079..0000000
--- a/azureus2/src/org/bouncycastle/jce/X509V3CertificateGenerator.java
+++ /dev/null
@@ -1,342 +0,0 @@
-package org.bouncycastle.jce;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.cert.X509Certificate;
-import java.util.Date;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.*;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x509.TBSCertificateStructure;
-import org.bouncycastle.asn1.x509.Time;
-import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
-import org.bouncycastle.asn1.x509.X509CertificateStructure;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.asn1.x509.X509Name;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.provider.X509CertificateObject;
-
-/**
- * class to produce an X.509 Version 3 certificate.
- */
-public class X509V3CertificateGenerator
-{
-    private V3TBSCertificateGenerator   tbsGen;
-    private DERObjectIdentifier         sigOID;
-    private AlgorithmIdentifier         sigAlgId;
-    private String                      signatureAlgorithm;
-    private Hashtable                   extensions = null;
-    private Vector                      extOrdering = null;
-
-    private static Hashtable            algorithms = new Hashtable();
-
-    static
-    {
-		algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
-		algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
-		algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
-		algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
-		algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
-		algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
-		algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2"));
-		algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2"));
-		algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3"));
-		algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3"));
-		algorithms.put("SHA1WITHECDSA", new DERObjectIdentifier("1.2.840.10045.4.1"));
-		algorithms.put("ECDSAWITHSHA1", new DERObjectIdentifier("1.2.840.10045.4.1"));
-    }
-
-    public X509V3CertificateGenerator()
-    {
-        tbsGen = new V3TBSCertificateGenerator();
-    }
-
-    /**
-     * reset the generator
-     */
-    public void reset()
-    {
-        tbsGen = new V3TBSCertificateGenerator();
-        extensions = null;
-        extOrdering = null;
-    }
-
-    /**
-     * set the serial number for the certificate.
-     */
-    public void setSerialNumber(
-        BigInteger      serialNumber)
-    {
-        tbsGen.setSerialNumber(new DERInteger(serialNumber));
-    }
-
-    /**
-     * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
-     * certificate.
-     */
-    public void setIssuerDN(
-        X509Name   issuer)
-    {
-        tbsGen.setIssuer(issuer);
-    }
-
-    public void setNotBefore(
-        Date    date)
-    {
-        tbsGen.setStartDate(new Time(date));
-    }
-
-    public void setNotAfter(
-        Date    date)
-    {
-        tbsGen.setEndDate(new Time(date));
-    }
-
-    /**
-     * Set the subject distinguished name. The subject describes the entity associated with the public key.
-     */
-    public void setSubjectDN(
-        X509Name   subject)
-    {
-        tbsGen.setSubject(subject);
-    }
-
-    public void setPublicKey(
-        PublicKey       key)
-    {
-        try
-        {
-            tbsGen.setSubjectPublicKeyInfo(new SubjectPublicKeyInfo((ASN1Sequence)new DERInputStream(
-                                new ByteArrayInputStream(key.getEncoded())).readObject()));
-        }
-        catch (Exception e)
-        {
-            throw new IllegalArgumentException("unable to process key - " + e.toString());
-        }
-    }
-
-    public void setSignatureAlgorithm(
-        String  signatureAlgorithm)
-    {
-        this.signatureAlgorithm = signatureAlgorithm;
-
-        sigOID = (DERObjectIdentifier)algorithms.get(signatureAlgorithm.toUpperCase());
-
-        if (sigOID == null)
-        {
-            throw new IllegalArgumentException("Unknown signature type requested");
-        }
-
-        sigAlgId = new AlgorithmIdentifier(this.sigOID, new DERNull());
-
-        tbsGen.setSignature(sigAlgId);
-    }
-
-    /**
-     * add a given extension field for the standard extensions tag (tag 3)
-     */
-    public void addExtension(
-        String          OID,
-        boolean         critical,
-        DEREncodable    value)
-    {
-        this.addExtension(new DERObjectIdentifier(OID), critical, value);
-    }
-
-    /**
-     * add a given extension field for the standard extensions tag (tag 3)
-     */
-    public void addExtension(
-        DERObjectIdentifier OID,
-        boolean             critical,
-        DEREncodable        value)
-    {
-        if (extensions == null)
-        {
-            extensions = new Hashtable();
-            extOrdering = new Vector();
-        }
-
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-
-        try
-        {
-            dOut.writeObject(value);
-        }
-        catch (IOException e)
-        {
-            throw new IllegalArgumentException("error encoding value: " + e);
-        }
-
-        this.addExtension(OID, critical, bOut.toByteArray());
-    }
-
-    /**
-     * add a given extension field for the standard extensions tag (tag 3)
-     * The value parameter becomes the contents of the octet string associated
-     * with the extension.
-     */
-    public void addExtension(
-        String          OID,
-        boolean         critical,
-        byte[]          value)
-    {
-        this.addExtension(new DERObjectIdentifier(OID), critical, value);
-    }
-
-    /**
-     * add a given extension field for the standard extensions tag (tag 3)
-     */
-    public void addExtension(
-        DERObjectIdentifier OID,
-        boolean             critical,
-        byte[]              value)
-    {
-        if (extensions == null)
-        {
-            extensions = new Hashtable();
-            extOrdering = new Vector();
-        }
-
-        extensions.put(OID, new X509Extension(critical, new DEROctetString(value)));
-        extOrdering.addElement(OID);
-    }
-
-    /**
-     * generate an X509 certificate, based on the current issuer and subject
-     * using the default provider "BC".
-     */
-    public X509Certificate generateX509Certificate(
-        PrivateKey      key)
-        throws SecurityException, SignatureException, InvalidKeyException
-    {
-        try
-        {
-            return generateX509Certificate(key, BouncyCastleProvider.PROVIDER_NAME, null);
-        }
-        catch (NoSuchProviderException e)
-        {
-            throw new SecurityException("BC provider not installed!");
-        }
-    }
-
-    /**
-     * generate an X509 certificate, based on the current issuer and subject
-     * using the default provider "BC", and the passed in source of randomness
-     * (if required).
-     */
-    public X509Certificate generateX509Certificate(
-        PrivateKey      key,
-        SecureRandom    random)
-        throws SecurityException, SignatureException, InvalidKeyException
-    {
-        try
-        {
-            return generateX509Certificate(key, BouncyCastleProvider.PROVIDER_NAME, random);
-        }
-        catch (NoSuchProviderException e)
-        {
-            throw new SecurityException("BC provider not installed!");
-        }
-    }
-
-    /**
-     * generate an X509 certificate, based on the current issuer and subject,
-     * using the passed in provider for the signing.
-     */
-    public X509Certificate generateX509Certificate(
-        PrivateKey      key,
-        String          provider)
-        throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
-    {
-        return generateX509Certificate(key, provider, null);
-    }
-
-    /**
-     * generate an X509 certificate, based on the current issuer and subject,
-     * using the passed in provider for the signing and the supplied source
-     * of randomness, if required.
-     */
-    public X509Certificate generateX509Certificate(
-        PrivateKey      key,
-        String          provider,
-        SecureRandom    random)
-        throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
-    {
-        Signature sig = null;
-
-        if (sigOID == null)
-        {
-            throw new IllegalStateException("no signature algorithm specified");
-        }
-
-        try
-        {
-            sig = Signature.getInstance(sigOID.getId(), provider);
-        }
-        catch (NoSuchAlgorithmException ex)
-        {
-            try
-            {
-                sig = Signature.getInstance(signatureAlgorithm, provider);
-            }
-            catch (NoSuchAlgorithmException e)
-            {
-                throw new SecurityException("exception creating signature: " + e.toString());
-            }
-        }
-
-        if (random != null)
-        {
-            sig.initSign(key, random);
-        }
-        else
-        {
-            sig.initSign(key);
-        }
-
-        if (extensions != null)
-        {
-            tbsGen.setExtensions(new X509Extensions(extOrdering, extensions));
-        }
-
-        TBSCertificateStructure tbsCert = tbsGen.generateTBSCertificate();
-
-        try
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            DEROutputStream         dOut = new DEROutputStream(bOut);
-
-            dOut.writeObject(tbsCert);
-
-            sig.update(bOut.toByteArray());
-        }
-        catch (Exception e)
-        {
-            throw new SecurityException("exception encoding TBS cert - " + e);
-        }
-
-        ASN1EncodableVector  v = new ASN1EncodableVector();
-
-        v.add(tbsCert);
-        v.add(sigAlgId);
-        v.add(new DERBitString(sig.sign()));
-
-        return new X509CertificateObject(new X509CertificateStructure(new DERSequence(v)));
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/interfaces/BCKeyStore.java b/azureus2/src/org/bouncycastle/jce/interfaces/BCKeyStore.java
deleted file mode 100644
index a36abbb..0000000
--- a/azureus2/src/org/bouncycastle/jce/interfaces/BCKeyStore.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.bouncycastle.jce.interfaces;
-
-import java.security.SecureRandom;
-
-/**
- * all BC provider keystores implement this interface.
- */
-public interface BCKeyStore
-{
-    /**
-     * set the random source for the key store
-     */
-    public void setRandom(SecureRandom random);
-}
diff --git a/azureus2/src/org/bouncycastle/jce/interfaces/ECKey.java b/azureus2/src/org/bouncycastle/jce/interfaces/ECKey.java
deleted file mode 100644
index 1c02816..0000000
--- a/azureus2/src/org/bouncycastle/jce/interfaces/ECKey.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.bouncycastle.jce.interfaces;
-
-import org.bouncycastle.jce.spec.ECParameterSpec;
-
-/**
- * generic interface for an Elliptic Curve Key.
- */
-public interface ECKey
-{
-    /**
-     * return a parameter specification representing the EC domain parameters
-     * for the key.
-     */
-	public ECParameterSpec getParams();
-}
diff --git a/azureus2/src/org/bouncycastle/jce/interfaces/ECPrivateKey.java b/azureus2/src/org/bouncycastle/jce/interfaces/ECPrivateKey.java
deleted file mode 100644
index 39d80c3..0000000
--- a/azureus2/src/org/bouncycastle/jce/interfaces/ECPrivateKey.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.bouncycastle.jce.interfaces;
-
-import java.math.BigInteger;
-import java.security.PrivateKey;
-
-/**
- * interface for Elliptic Curve Private keys.
- */
-public interface ECPrivateKey
-    extends ECKey, PrivateKey
-{
-    /**
-     * return the private value D.
-     */
-    public BigInteger getD();
-}
diff --git a/azureus2/src/org/bouncycastle/jce/interfaces/ECPublicKey.java b/azureus2/src/org/bouncycastle/jce/interfaces/ECPublicKey.java
deleted file mode 100644
index db2ecdc..0000000
--- a/azureus2/src/org/bouncycastle/jce/interfaces/ECPublicKey.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bouncycastle.jce.interfaces;
-
-import java.security.PublicKey;
-
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * interface for elliptic curve public keys.
- */
-public interface ECPublicKey
-    extends ECKey, PublicKey
-{
-    /**
-     * return the public point Q
-     */
-    public ECPoint getQ();
-}
diff --git a/azureus2/src/org/bouncycastle/jce/interfaces/ElGamalKey.java b/azureus2/src/org/bouncycastle/jce/interfaces/ElGamalKey.java
deleted file mode 100644
index 2f17804..0000000
--- a/azureus2/src/org/bouncycastle/jce/interfaces/ElGamalKey.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.bouncycastle.jce.interfaces;
-
-import org.bouncycastle.jce.spec.ElGamalParameterSpec;
-
-public interface ElGamalKey
-{
-    public ElGamalParameterSpec getParams();
-}
diff --git a/azureus2/src/org/bouncycastle/jce/interfaces/ElGamalPrivateKey.java b/azureus2/src/org/bouncycastle/jce/interfaces/ElGamalPrivateKey.java
deleted file mode 100644
index 609a2a8..0000000
--- a/azureus2/src/org/bouncycastle/jce/interfaces/ElGamalPrivateKey.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.jce.interfaces;
-
-import java.math.BigInteger;
-import java.security.PrivateKey;
-
-public interface ElGamalPrivateKey
-    extends ElGamalKey, PrivateKey
-{
-    public BigInteger getX();
-}
diff --git a/azureus2/src/org/bouncycastle/jce/interfaces/ElGamalPublicKey.java b/azureus2/src/org/bouncycastle/jce/interfaces/ElGamalPublicKey.java
deleted file mode 100644
index c9fe35e..0000000
--- a/azureus2/src/org/bouncycastle/jce/interfaces/ElGamalPublicKey.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.jce.interfaces;
-
-import java.math.BigInteger;
-import java.security.PublicKey;
-
-public interface ElGamalPublicKey
-    extends ElGamalKey, PublicKey
-{
-    public BigInteger getY();
-}
diff --git a/azureus2/src/org/bouncycastle/jce/interfaces/IESKey.java b/azureus2/src/org/bouncycastle/jce/interfaces/IESKey.java
deleted file mode 100644
index f1d7901..0000000
--- a/azureus2/src/org/bouncycastle/jce/interfaces/IESKey.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.bouncycastle.jce.interfaces;
-
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-/**
- * key pair for use with an integrated encryptor
- */
-public interface IESKey
-    extends Key
-{
-    /**
-     * return the intended recipient's/sender's public key.
-     */
-    public PublicKey getPublic();
-
-    /**
-     * return the local private key.
-     */
-    public PrivateKey getPrivate();
-}
diff --git a/azureus2/src/org/bouncycastle/jce/interfaces/PKCS12BagAttributeCarrier.java b/azureus2/src/org/bouncycastle/jce/interfaces/PKCS12BagAttributeCarrier.java
deleted file mode 100644
index c5dd664..0000000
--- a/azureus2/src/org/bouncycastle/jce/interfaces/PKCS12BagAttributeCarrier.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.bouncycastle.jce.interfaces;
-
-import java.util.Enumeration;
-
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-
-/**
- * allow us to set attributes on objects that can go into a PKCS12 store.
- */
-public interface PKCS12BagAttributeCarrier
-{
-    public void setBagAttribute(
-        DERObjectIdentifier oid,
-        DEREncodable        attribute);
-
-    public DEREncodable getBagAttribute(
-        DERObjectIdentifier oid);
-
-    public Enumeration getBagAttributeKeys();
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/BouncyCastleProvider.java b/azureus2/src/org/bouncycastle/jce/provider/BouncyCastleProvider.java
deleted file mode 100644
index 2686f36..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/BouncyCastleProvider.java
+++ /dev/null
@@ -1,588 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.Provider;
-
-/**
- * To add the provider at runtime use:
- * <pre>
- * import java.security.Security;
- * import org.bouncycastle.jce.provider.BouncyCastleProvider;
- *
- * Security.addProvider(new BouncyCastleProvider());
- * </pre>
- * The provider can also be configured as part of your environment via
- * static registration by adding an entry to the java.security properties
- * file (found in $JAVA_HOME/jre/lib/security/java.security, where
- * $JAVA_HOME is the location of your JDK/JRE distribution). You'll find
- * detailed instructions in the file but basically it comes down to adding
- * a line:
- * <pre>
- * <code>
- *    security.provider.<n>=org.bouncycastle.jce.provider.BouncyCastleProvider
- * </code>
- * </pre>
- * Where <n> is the preference you want the provider at (1 being the
- * most prefered).
- * <p>Note: JCE algorithm names should be uppercase only so the case insensitive
- * test for getInstance works.
- */
-public final class BouncyCastleProvider extends Provider
-{
-	private static String info = "BouncyCastle Security Provider v1.23";
-
-    public static String PROVIDER_NAME = "BC_VUZE";
-
-	/**
-	 * Construct a new provider.  This should only be required when
-	 * using runtime registration of the provider using the
-	 * <code>Security.addProvider()</code> mechanism.
-	 */
-	public BouncyCastleProvider()
-	{
-		super(PROVIDER_NAME, 1.23, info);
-
-        //
-        // KeyStore
-        //
-        put("KeyStore.BKS", "org.bouncycastle.jce.provider.JDKKeyStore");
-        put("KeyStore.BouncyCastle", "org.bouncycastle.jce.provider.JDKKeyStore$BouncyCastleStore");
-        put("KeyStore.PKCS12", "org.bouncycastle.jce.provider.JDKPKCS12KeyStore$BCPKCS12KeyStore");
-		put("KeyStore.BCPKCS12", "org.bouncycastle.jce.provider.JDKPKCS12KeyStore$BCPKCS12KeyStore");
-        put("KeyStore.PKCS12-DEF", "org.bouncycastle.jce.provider.JDKPKCS12KeyStore$DefPKCS12KeyStore");
-        put("Alg.Alias.KeyStore.UBER", "BouncyCastle");
-        put("Alg.Alias.KeyStore.BOUNCYCASTLE", "BouncyCastle");
-        put("Alg.Alias.KeyStore.bouncycastle", "BouncyCastle");
-
-        //
-        // certificate factories.
-        //
-        put("CertificateFactory.X.509", "org.bouncycastle.jce.provider.JDKX509CertificateFactory");
-		put("Alg.Alias.CertificateFactory.X509", "X.509");
-
-        //
-        // algorithm parameter generators
-        //
-        put("AlgorithmParameterGenerator.DH", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DH");
-        put("AlgorithmParameterGenerator.DSA", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DSA");
-        put("AlgorithmParameterGenerator.ELGAMAL", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$ElGamal");
-        put("AlgorithmParameterGenerator.DES", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DES");
-        put("AlgorithmParameterGenerator.DESEDE", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DES");
-        put("AlgorithmParameterGenerator.1.2.840.113549.3.7", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DES");
-        put("AlgorithmParameterGenerator.1.3.14.3.2.7", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$DES");
-        put("AlgorithmParameterGenerator.IDEA", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$IDEA");
-        put("AlgorithmParameterGenerator.1.3.6.1.4.1.188.7.1.1.2", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$IDEA");
-        put("AlgorithmParameterGenerator.RC2", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$RC2");
-        put("AlgorithmParameterGenerator.1.2.840.113549.3.2", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$RC2");
-        put("AlgorithmParameterGenerator.CAST5", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$CAST5");
-        put("AlgorithmParameterGenerator.1.2.840.113533.7.66.10", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$CAST5");
-        put("AlgorithmParameterGenerator.AES", "org.bouncycastle.jce.provider.JDKAlgorithmParameterGenerator$AES");
-        put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.2", "AES");  // these first 3 are wrong, but seem to have got around
-        put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.22", "AES");
-        put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.42", "AES");
-		put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.1.2", "AES");
-		put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.1.22", "AES");
-		put("Alg.Alias.AlgorithmParameterGenerator.2.16.840.1.101.3.4.1.42", "AES");
-        //
-        // algorithm parameters
-        //
-        put("AlgorithmParameters.DH", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$DH");
-        put("AlgorithmParameters.DSA", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$DSA");
-        put("AlgorithmParameters.ELGAMAL", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$ElGamal");
-        put("AlgorithmParameters.IES", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IES");
-        put("AlgorithmParameters.PKCS12PBE", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$PKCS12PBE");
-        put("AlgorithmParameters.1.2.840.113549.3.7", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("AlgorithmParameters.IDEA", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IDEAAlgorithmParameters");
-        put("AlgorithmParameters.1.3.6.1.4.1.188.7.1.1.2", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IDEAAlgorithmParameters");
-        put("AlgorithmParameters.CAST5", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$CAST5AlgorithmParameters");
-        put("AlgorithmParameters.1.2.840.113533.7.66.10", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$CAST5AlgorithmParameters");
-        put("Alg.Alias.AlgorithmParameters.PBEWITHSHA1ANDRC2", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND3-KEYTRIPLEDES", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.PBEWITHSHAAND2-KEYTRIPLEDES", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDRC2", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDRC4", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDTWOFISH", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.PBEWITHSHAANDIDEA", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.1", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.2", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.3", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.4", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.5", "PKCS12PBE");
-        put("Alg.Alias.AlgorithmParameters.1.2.840.113549.1.12.1.6", "PKCS12PBE");
-
-        //
-        // key agreement
-        //
-        put("KeyAgreement.DH", "org.bouncycastle.jce.provider.JCEDHKeyAgreement");
-        put("KeyAgreement.ECDH", "org.bouncycastle.jce.provider.JCEECDHKeyAgreement$DH");
-        put("KeyAgreement.ECDHC", "org.bouncycastle.jce.provider.JCEECDHKeyAgreement$DHC");
-
-		//
-		// cipher engines
-		//
-		put("Cipher.DES", "org.bouncycastle.jce.provider.JCEBlockCipher$DES");
-		put("Cipher.DESEDE", "org.bouncycastle.jce.provider.JCEBlockCipher$DESede");
-		put("Cipher.1.2.840.113549.3.7", "org.bouncycastle.jce.provider.JCEBlockCipher$DESedeCBC");
-		put("Cipher.1.3.14.3.2.7", "org.bouncycastle.jce.provider.JCEBlockCipher$DESCBC");
-        put("Cipher.DESEDEWRAP", "org.bouncycastle.jce.provider.WrapCipherSpi$DESEDEWrap");
-        put("Cipher.1.2.840.113549.1.9.16.3.6", "org.bouncycastle.jce.provider.WrapCipherSpi$DESEDEWrap");
-		put("Cipher.SKIPJACK", "org.bouncycastle.jce.provider.JCEBlockCipher$Skipjack");
-		put("Cipher.BLOWFISH", "org.bouncycastle.jce.provider.JCEBlockCipher$Blowfish");
-		put("Cipher.TWOFISH", "org.bouncycastle.jce.provider.JCEBlockCipher$Twofish");
-		put("Cipher.RC2", "org.bouncycastle.jce.provider.JCEBlockCipher$RC2");
-        put("Cipher.RC2WRAP", "org.bouncycastle.jce.provider.WrapCipherSpi$RC2Wrap");
-        put("Cipher.1.2.840.113549.1.9.16.3.7", "org.bouncycastle.jce.provider.WrapCipherSpi$RC2Wrap");
-        put("Cipher.ARC4", "org.bouncycastle.jce.provider.JCEStreamCipher$RC4");
-        put("Cipher.RC4", "org.bouncycastle.jce.provider.JCEStreamCipher$RC4");
-		put("Alg.Alias.Cipher.1.2.840.113549.3.4", "RC4");
-		put("Cipher.RC5", "org.bouncycastle.jce.provider.JCEBlockCipher$RC5");
-		put("Cipher.1.2.840.113549.3.2", "org.bouncycastle.jce.provider.JCEBlockCipher$RC2CBC");
-		put("Alg.Alias.Cipher.RC5-32", "RC5");
-		put("Cipher.RC5-64", "org.bouncycastle.jce.provider.JCEBlockCipher$RC564");
-		put("Cipher.RC6", "org.bouncycastle.jce.provider.JCEBlockCipher$RC6");
-		put("Cipher.RIJNDAEL", "org.bouncycastle.jce.provider.JCEBlockCipher$Rijndael");
-		put("Cipher.AES", "org.bouncycastle.jce.provider.JCEBlockCipher$AES");
-		put("Alg.Alias.Cipher.2.16.840.1.101.3.4.2", "AES");
-		put("Alg.Alias.Cipher.2.16.840.1.101.3.4.22", "AES");
-		put("Alg.Alias.Cipher.2.16.840.1.101.3.4.42", "AES");
-		put("Cipher.2.16.840.1.101.3.4.1.2", "org.bouncycastle.jce.provider.JCEBlockCipher$AESCBC");
-		put("Cipher.2.16.840.1.101.3.4.1.22", "org.bouncycastle.jce.provider.JCEBlockCipher$AESCBC");
-		put("Cipher.2.16.840.1.101.3.4.1.42", "org.bouncycastle.jce.provider.JCEBlockCipher$AESCBC");
-		put("Cipher.AESWRAP", "org.bouncycastle.jce.provider.WrapCipherSpi$AESWrap");
-		put("Cipher.SERPENT", "org.bouncycastle.jce.provider.JCEBlockCipher$Serpent");
-		put("Cipher.CAST5", "org.bouncycastle.jce.provider.JCEBlockCipher$CAST5");
-		put("Cipher.1.2.840.113533.7.66.10", "org.bouncycastle.jce.provider.JCEBlockCipher$CAST5CBC");
-		put("Cipher.CAST6", "org.bouncycastle.jce.provider.JCEBlockCipher$CAST6");
-		put("Cipher.IDEA", "org.bouncycastle.jce.provider.JCEBlockCipher$IDEA");
-		put("Cipher.1.3.6.1.4.1.188.7.1.1.2", "org.bouncycastle.jce.provider.JCEBlockCipher$IDEACBC");
-
-/*
-		put("Cipher.DES/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$DES_CFB8");
-		put("Cipher.DESEDE/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$DESede_CFB8");
-		put("Cipher.SKIPJACK/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Skipjack_CFB8");
-		put("Cipher.BLOWFISH/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Blowfish_CFB8");
-		put("Cipher.TWOFISH/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Twofish_CFB8");
-		put("Cipher.IDEA/CFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$IDEA_CFB8");
-
-		put("Alg.Alias.Cipher.DES/CFB8/NOPADDING", "DES/CFB8");
-		put("Alg.Alias.Cipher.DESEDE/CFB8/NOPADDING", "DESEDE/CFB8");
-		put("Alg.Alias.Cipher.SKIPJACK/CFB8/NOPADDING", "SKIPJACK/CFB8");
-		put("Alg.Alias.Cipher.BLOWFISH/CFB8/NOPADDING", "Blowfish/CFB8");
-		put("Alg.Alias.Cipher.TWOFISH/CFB8/NOPADDING", "Twofish/CFB8");
-		put("Alg.Alias.Cipher.IDEA/CFB8/NOPADDING", "IDEA/CFB8");
-
-		put("Cipher.DES/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$DES_OFB8");
-		put("Cipher.DESEDE/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$DESede_OFB8");
-		put("Cipher.SKIPJACK/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Skipjack_OFB8");
-		put("Cipher.BLOWFISH/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Blowfish_OFB8");
-		put("Cipher.TWOFISH/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$Twofish_OFB8");
-		put("Cipher.IDEA/OFB8", "org.bouncycastle.jce.provider.JCEStreamCipher$IDEA_OFB8");
-
-		put("Alg.Alias.Cipher.DES/OFB8/NOPADDING", "DES/OFB8");
-		put("Alg.Alias.Cipher.DESEDE/OFB8/NOPADDING", "DESEDE/OFB8");
-		put("Alg.Alias.Cipher.SKIPJACK/OFB8/NOPADDING", "SKIPJACK/OFB8");
-		put("Alg.Alias.Cipher.BLOWFISH/OFB8/NOPADDING", "BLOWFISH/OFB8");
-		put("Alg.Alias.Cipher.TWOFISH/OFB8/NOPADDING", "TWOFISH/OFB8");
-		put("Alg.Alias.Cipher.IDEA/OFB8/NOPADDING", "IDEA/OFB8");
-*/
-
-		put("Cipher.RSA", "org.bouncycastle.jce.provider.JCERSACipher$NoPadding");
-		put("Cipher.RSA/RAW", "org.bouncycastle.jce.provider.JCERSACipher$NoPadding");
-		put("Cipher.RSA/PKCS1", "org.bouncycastle.jce.provider.JCERSACipher$PKCS1v1_5Padding");
-		put("Cipher.1.2.840.113549.1.1.1", "org.bouncycastle.jce.provider.JCERSACipher$PKCS1v1_5Padding");
-		put("Cipher.2.5.8.1.1", "org.bouncycastle.jce.provider.JCERSACipher$PKCS1v1_5Padding");
-		put("Cipher.RSA/1", "org.bouncycastle.jce.provider.JCERSACipher$PKCS1v1_5Padding_PrivateOnly");
-		put("Cipher.RSA/2", "org.bouncycastle.jce.provider.JCERSACipher$PKCS1v1_5Padding_PublicOnly");
-		put("Cipher.RSA/OAEP", "org.bouncycastle.jce.provider.JCERSACipher$OAEPPadding");
-		put("Cipher.1.2.840.113549.1.1.7", "org.bouncycastle.jce.provider.JCERSACipher$OAEPPadding");
-		put("Cipher.RSA/ISO9796-1", "org.bouncycastle.jce.provider.JCERSACipher$ISO9796d1Padding");
-
-		put("Cipher.ECIES", "org.bouncycastle.jce.provider.JCEIESCipher$ECIES");
-		put("Cipher.ELGAMAL", "org.bouncycastle.jce.provider.JCEElGamalCipher$NoPadding");
-		put("Cipher.ELGAMAL/PKCS1", "org.bouncycastle.jce.provider.JCEElGamalCipher$PKCS1v1_5Padding");
-
-		put("Alg.Alias.Cipher.RSA//RAW", "RSA");
-		put("Alg.Alias.Cipher.RSA//NOPADDING", "RSA");
-		put("Alg.Alias.Cipher.RSA//PKCS1PADDING", "RSA/PKCS1");
-		put("Alg.Alias.Cipher.RSA//OAEPPADDING", "RSA/OAEP");
-		put("Alg.Alias.Cipher.RSA//ISO9796-1PADDING", "RSA/ISO9796-1");
-		put("Alg.Alias.Cipher.RSA/ECB/NOPADDING", "RSA");
-		put("Alg.Alias.Cipher.RSA/ECB/PKCS1PADDING", "RSA/PKCS1");
-		put("Alg.Alias.Cipher.RSA/ECB/OAEPPADDING", "RSA/OAEP");
-		put("Alg.Alias.Cipher.RSA/ECB/ISO9796-1PADDING", "RSA/ISO9796-1");
-		put("Alg.Alias.Cipher.RSA/NONE/NOPADDING", "RSA");
-		put("Alg.Alias.Cipher.RSA/NONE/PKCS1PADDING", "RSA/PKCS1");
-		put("Alg.Alias.Cipher.RSA/NONE/OAEPPADDING", "RSA/OAEP");
-		put("Alg.Alias.Cipher.RSA/NONE/ISO9796-1PADDING", "RSA/ISO9796-1");
-		put("Alg.Alias.Cipher.RSA/1/PCKS1PADDING", "RSA/1");
-		put("Alg.Alias.Cipher.RSA/2/PCKS1PADDING", "RSA/2");
-		
-		put("Alg.Alias.Cipher.ELGAMAL/ECB/PKCS1PADDING", "ELGAMAL/PKCS1");
-		put("Alg.Alias.Cipher.ELGAMAL/NONE/PKCS1PADDING", "ELGAMAL/PKCS1");
-
-        put("Cipher.PBEWITHMD5ANDDES", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithMD5AndDES");
-        put("Cipher.BROKENPBEWITHMD5ANDDES", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithMD5AndDES");
-        put("Cipher.PBEWITHMD5ANDRC2", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithMD5AndRC2");
-        put("Cipher.PBEWITHSHA1ANDDES", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHA1AndDES");
-        put("Cipher.BROKENPBEWITHSHA1ANDDES", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithSHA1AndDES");
-        put("Cipher.PBEWITHSHA1ANDRC2", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHA1AndRC2");
-        put("Cipher.PBEWITHSHAAND3-KEYTRIPLEDES-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAndDES3Key");
-        put("Cipher.BROKENPBEWITHSHAAND3-KEYTRIPLEDES-CBC", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithSHAAndDES3Key");
-        put("Cipher.OLDPBEWITHSHAAND3-KEYTRIPLEDES-CBC", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$OldPBEWithSHAAndDES3Key");
-        put("Cipher.PBEWITHSHAAND2-KEYTRIPLEDES-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAndDES2Key");
-        put("Cipher.BROKENPBEWITHSHAAND2-KEYTRIPLEDES-CBC", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$BrokePBEWithSHAAndDES2Key");
-        put("Cipher.PBEWITHSHAAND128BITRC2-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAnd128BitRC2");
-        put("Cipher.PBEWITHSHAAND40BITRC2-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAnd40BitRC2");
-        put("Cipher.PBEWITHSHAAND128BITRC4", "org.bouncycastle.jce.provider.JCEStreamCipher$PBEWithSHAAnd128BitRC4");
-        put("Cipher.PBEWITHSHAAND40BITRC4", "org.bouncycastle.jce.provider.JCEStreamCipher$PBEWithSHAAnd40BitRC4");
-
-        put("Cipher.PBEWITHSHAANDTWOFISH-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAndTwofish");
-        put("Cipher.OLDPBEWITHSHAANDTWOFISH-CBC", "org.bouncycastle.jce.provider.BrokenJCEBlockCipher$OldPBEWithSHAAndTwofish");
-        put("Cipher.PBEWITHSHAANDIDEA-CBC", "org.bouncycastle.jce.provider.JCEBlockCipher$PBEWithSHAAndIDEA");
-
-        put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.1", "PBEWITHSHAAND128BITRC4");
-        put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.2", "PBEWITHSHAAND40BITRC4");
-        put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.3", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC");
-        put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.4", "PBEWITHSHAAND2-KEYTRIPLEDES-CBC");
-        put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.5", "PBEWITHSHAAND128BITRC2-CBC");
-        put("Alg.Alias.Cipher.1.2.840.113549.1.12.1.6", "PBEWITHSHAAND40BITRC2-CBC");
-
-        //
-        // key generators.
-        //
-        put("KeyGenerator.DES", "org.bouncycastle.jce.provider.JCEKeyGenerator$DES");
-        put("Alg.Alias.KeyGenerator.1.3.14.3.2.7", "DES");
-        put("KeyGenerator.DESEDE", "org.bouncycastle.jce.provider.JCEKeyGenerator$DESede");
-        put("KeyGenerator.1.2.840.113549.3.7", "org.bouncycastle.jce.provider.JCEKeyGenerator$DESede3");
-        put("KeyGenerator.DESEDEWRAP", "org.bouncycastle.jce.provider.JCEKeyGenerator$DESede");
-        put("KeyGenerator.SKIPJACK", "org.bouncycastle.jce.provider.JCEKeyGenerator$Skipjack");
-        put("KeyGenerator.BLOWFISH", "org.bouncycastle.jce.provider.JCEKeyGenerator$Blowfish");
-        put("KeyGenerator.TWOFISH", "org.bouncycastle.jce.provider.JCEKeyGenerator$Twofish");
-        put("KeyGenerator.RC2", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC2");
-        put("KeyGenerator.1.2.840.113549.3.2", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC2");
-        put("KeyGenerator.RC4", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC4");
-        put("Alg.Alias.KeyGenerator.ARC4", "RC4");
-        put("Alg.Alias.KeyGenerator.1.2.840.113549.3.4", "RC4");
-        put("KeyGenerator.RC5", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC5");
-        put("Alg.Alias.KeyGenerator.RC5-32", "RC5");
-        put("KeyGenerator.RC5-64", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC564");
-        put("KeyGenerator.RC6", "org.bouncycastle.jce.provider.JCEKeyGenerator$RC6");
-        put("KeyGenerator.RIJNDAEL", "org.bouncycastle.jce.provider.JCEKeyGenerator$Rijndael");
-        put("KeyGenerator.AES", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES");
-        put("KeyGenerator.2.16.840.1.101.3.4.2", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES128");
-        put("KeyGenerator.2.16.840.1.101.3.4.22", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES192");
-        put("KeyGenerator.2.16.840.1.101.3.4.42", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES256");
-		put("KeyGenerator.2.16.840.1.101.3.4.1.2", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES128");
-		put("KeyGenerator.2.16.840.1.101.3.4.1.22", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES192");
-		put("KeyGenerator.2.16.840.1.101.3.4.1.42", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES256");
-        put("KeyGenerator.AESWRAP", "org.bouncycastle.jce.provider.JCEKeyGenerator$AES");
-        put("KeyGenerator.SERPENT", "org.bouncycastle.jce.provider.JCEKeyGenerator$Serpent");
-        put("KeyGenerator.CAST5", "org.bouncycastle.jce.provider.JCEKeyGenerator$CAST5");
-        put("KeyGenerator.1.2.840.113533.7.66.10", "org.bouncycastle.jce.provider.JCEKeyGenerator$CAST5");
-        put("KeyGenerator.CAST6", "org.bouncycastle.jce.provider.JCEKeyGenerator$CAST6");
-        put("KeyGenerator.IDEA", "org.bouncycastle.jce.provider.JCEKeyGenerator$IDEA");
-        put("KeyGenerator.1.3.6.1.4.1.188.7.1.1.2", "org.bouncycastle.jce.provider.JCEKeyGenerator$IDEA");
-        put("KeyGenerator.HMACMD2", "org.bouncycastle.jce.provider.JCEKeyGenerator$MD2HMAC");
-        put("KeyGenerator.HMACMD4", "org.bouncycastle.jce.provider.JCEKeyGenerator$MD4HMAC");
-        put("KeyGenerator.HMACMD5", "org.bouncycastle.jce.provider.JCEKeyGenerator$MD5HMAC");
-        put("KeyGenerator.HMACRIPEMD128", "org.bouncycastle.jce.provider.JCEKeyGenerator$RIPEMD128HMAC");
-        put("KeyGenerator.HMACRIPEMD160", "org.bouncycastle.jce.provider.JCEKeyGenerator$RIPEMD160HMAC");
-        put("KeyGenerator.HMACSHA1", "org.bouncycastle.jce.provider.JCEKeyGenerator$HMACSHA1");
-        put("KeyGenerator.HMACTIGER", "org.bouncycastle.jce.provider.JCEKeyGenerator$HMACTIGER");
-
-        //
-        // key pair generators.
-        //
-        put("KeyPairGenerator.RSA", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$RSA");
-        put("KeyPairGenerator.DH", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$DH");
-        put("KeyPairGenerator.DSA", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$DSA");
-        put("KeyPairGenerator.ELGAMAL", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$ElGamal");
-        put("KeyPairGenerator.ECDSA", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$ECDSA");
-        put("KeyPairGenerator.ECDH", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$ECDH");
-        put("KeyPairGenerator.ECDHC", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$ECDHC");
-        put("KeyPairGenerator.ECIES", "org.bouncycastle.jce.provider.JDKKeyPairGenerator$ECDH");
-
-        put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1.1", "RSA");
-
-        //
-        // key factories
-        //
-        put("KeyFactory.RSA", "org.bouncycastle.jce.provider.JDKKeyFactory$RSA");
-        put("KeyFactory.DH", "org.bouncycastle.jce.provider.JDKKeyFactory$DH");
-        put("KeyFactory.DSA", "org.bouncycastle.jce.provider.JDKKeyFactory$DSA");
-        put("KeyFactory.ELGAMAL", "org.bouncycastle.jce.provider.JDKKeyFactory$ElGamal");
-        put("KeyFactory.ElGamal", "org.bouncycastle.jce.provider.JDKKeyFactory$ElGamal");
-        put("KeyFactory.EC", "org.bouncycastle.jce.provider.JDKKeyFactory$EC");
-        put("KeyFactory.ECDSA", "org.bouncycastle.jce.provider.JDKKeyFactory$ECDSA");
-        put("KeyFactory.ECDH", "org.bouncycastle.jce.provider.JDKKeyFactory$ECDH");
-        put("KeyFactory.ECDHC", "org.bouncycastle.jce.provider.JDKKeyFactory$ECDHC");
-
-        put("Alg.Alias.KeyFactory.1.2.840.113549.1.1.1", "RSA");
-        put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA");
-
-        //
-        // Algorithm parameters
-        //
-        put("AlgorithmParameters.DES", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("Alg.Alias.AlgorithmParameters.1.3.14.3.2.7", "DES");
-        put("AlgorithmParameters.DESEDE", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("AlgorithmParameters.1.2.840.113549.3.7", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("AlgorithmParameters.RC2", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$RC2AlgorithmParameters");
-        put("AlgorithmParameters.1.2.840.113549.3.2", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$RC2AlgorithmParameters");
-        put("AlgorithmParameters.RC5", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("AlgorithmParameters.RC6", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("AlgorithmParameters.IDEA", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IDEAAlgorithmParameters");
-        put("AlgorithmParameters.BLOWFISH", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("AlgorithmParameters.TWOFISH", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("AlgorithmParameters.SKIPJACK", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("AlgorithmParameters.RIJNDAEL", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("AlgorithmParameters.AES", "org.bouncycastle.jce.provider.JDKAlgorithmParameters$IVAlgorithmParameters");
-        put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.2", "AES");
-        put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.22", "AES");
-        put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.42", "AES");
-		put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.1.2", "AES");
-		put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.1.22", "AES");
-		put("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.1.42", "AES");
-		
-        //
-        // secret key factories.
-        //
-        put("SecretKeyFactory.PBE/PKCS5", "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBE_PKCS5");
-        put("SecretKeyFactory.PBE/PKCS12", "org.bouncycastle.jce.provider.JCESecretKeyFactory$PBE_PKCS12");
-        put("SecretKeyFactory.DES", "org.bouncycastle.jce.provider.JCESecretKeyFactory$DES");
-        put("SecretKeyFactory.DESEDE", "org.bouncycastle.jce.provider.JCESecretKeyFactory$DESede");
-        put("SecretKeyFactory.DESEDE", "org.bouncycastle.jce.provider.JCESecretKeyFactory$DESede");
-
-        put("Alg.Alias.SecretKeyFactory.PBE", "PBE/PKCS5");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHMD5ANDDES", "PBE/PKCS5");
-        put("Alg.Alias.SecretKeyFactory.BROKENPBEWITHMD5ANDDES", "PBE/PKCS5");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHMD5ANDRC2", "PBE/PKCS5");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHSHA1ANDDES", "PBE/PKCS5");
-        put("Alg.Alias.SecretKeyFactory.BROKENPBEWITHSHA1ANDDES", "PBE/PKCS5");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHSHA1ANDRC2", "PBE/PKCS5");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND3-KEYTRIPLEDES-CBC", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.OLDPBEWITHSHAAND3-KEYTRIPLEDES-CBC", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.BROKENPBEWITHSHAAND3-KEYTRIPLEDES-CBC", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND2-KEYTRIPLEDES-CBC", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.BROKENPBEWITHSHAAND2-KEYTRIPLEDES-CBC", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND128BITRC4", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND40BITRC4", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND128BITRC2-CBC", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHSHAAND40BITRC2-CBC", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHSHAANDTWOFISH-CBC", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.OLDPBEWITHSHAANDTWOFISH-CBC", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHSHAANDIDEA-CBC", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHHMACSHA", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.PBEWITHHMACRIPEMD160", "PBE/PKCS12");
-
-        put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.1", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.2", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.3", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.4", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.5", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.1.2.840.113549.1.12.1.6", "PBE/PKCS12");
-        put("Alg.Alias.SecretKeyFactory.1.3.14.3.2.26", "PBE/PKCS12");
-
-        //
-        // MAC's
-        //
-        put("Mac.DESMAC", "org.bouncycastle.jce.provider.JCEMac$DES");
-        put("Alg.Alias.Mac.DES", "DESMAC");
-        put("Mac.DESMAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$DESCFB8");
-        put("Alg.Alias.Mac.DES/CFB8", "DESMAC/CFB8");
-
-        put("Mac.DESEDEMAC", "org.bouncycastle.jce.provider.JCEMac$DESede");
-        put("Alg.Alias.Mac.DESEDE", "DESEDEMAC");
-        put("Mac.DESEDEMAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$DESedeCFB8");
-        put("Alg.Alias.Mac.DESEDE/CFB8", "DESEDEMAC/CFB8");
-
-        put("Mac.SKIPJACKMAC", "org.bouncycastle.jce.provider.JCEMac$Skipjack");
-        put("Alg.Alias.Mac.SKIPJACK", "SKIPJACKMAC");
-        put("Mac.SKIPJACKMAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$SkipjackCFB8");
-        put("Alg.Alias.Mac.SKIPJACK/CFB8", "SKIPJACKMAC/CFB8");
-
-        put("Mac.IDEAMAC", "org.bouncycastle.jce.provider.JCEMac$IDEA");
-        put("Alg.Alias.Mac.IDEA", "IDEAMAC");
-        put("Mac.IDEAMAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$IDEACFB8");
-        put("Alg.Alias.Mac.IDEA/CFB8", "IDEAMAC/CFB8");
-
-        put("Mac.RC2MAC", "org.bouncycastle.jce.provider.JCEMac$RC2");
-        put("Alg.Alias.Mac.RC2", "RC2MAC");
-        put("Mac.RC2MAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$RC2CFB8");
-        put("Alg.Alias.Mac.RC2/CFB8", "RC2MAC/CFB8");
-
-        put("Mac.RC5MAC", "org.bouncycastle.jce.provider.JCEMac$RC5");
-        put("Alg.Alias.Mac.RC5", "RC5MAC");
-        put("Mac.RC5MAC/CFB8", "org.bouncycastle.jce.provider.JCEMac$RC5CFB8");
-        put("Alg.Alias.Mac.RC5/CFB8", "RC5MAC/CFB8");
-
-        put("Mac.HMACMD2", "org.bouncycastle.jce.provider.JCEMac$MD2");
-        put("Alg.Alias.Mac.HMAC-MD2", "HMACMD2");
-        put("Alg.Alias.Mac.HMAC/MD2", "HMACMD2");
-
-        put("Mac.HMACMD4", "org.bouncycastle.jce.provider.JCEMac$MD4");
-        put("Alg.Alias.Mac.HMAC-MD4", "HMACMD4");
-        put("Alg.Alias.Mac.HMAC/MD4", "HMACMD4");
-
-        put("Mac.HMACMD5", "org.bouncycastle.jce.provider.JCEMac$MD5");
-        put("Alg.Alias.Mac.HMAC-MD5", "HMACMD5");
-        put("Alg.Alias.Mac.HMAC/MD5", "HMACMD5");
-
-        put("Mac.HMACRIPEMD128", "org.bouncycastle.jce.provider.JCEMac$RIPEMD128");
-        put("Alg.Alias.Mac.HMAC-RIPEMD128", "HMACRIPEMD128");
-        put("Alg.Alias.Mac.HMAC/RIPEMD128", "HMACRIPEMD128");
-
-        put("Mac.HMACRIPEMD160", "org.bouncycastle.jce.provider.JCEMac$RIPEMD160");
-        put("Alg.Alias.Mac.HMAC-RIPEMD160", "HMACRIPEMD160");
-        put("Alg.Alias.Mac.HMAC/RIPEMD160", "HMACRIPEMD160");
-
-        put("Mac.HMACSHA1", "org.bouncycastle.jce.provider.JCEMac$SHA1");
-        put("Alg.Alias.Mac.HMAC-SHA1", "HMACSHA1");
-        put("Alg.Alias.Mac.HMAC/SHA1", "HMACSHA1");
-
-        put("Mac.HMACSHA256", "org.bouncycastle.jce.provider.JCEMac$SHA256");
-        put("Alg.Alias.Mac.HMAC-SHA256", "HMACSHA256");
-        put("Alg.Alias.Mac.HMAC/SHA256", "HMACSHA256");
-
-        put("Mac.HMACSHA384", "org.bouncycastle.jce.provider.JCEMac$SHA384");
-        put("Alg.Alias.Mac.HMAC-SHA384", "HMACSHA384");
-        put("Alg.Alias.Mac.HMAC/SHA384", "HMACSHA384");
-
-        put("Mac.HMACSHA512", "org.bouncycastle.jce.provider.JCEMac$SHA512");
-        put("Alg.Alias.Mac.HMAC-SHA512", "HMACSHA512");
-        put("Alg.Alias.Mac.HMAC/SHA512", "HMACSHA512");
-
-        put("Mac.HMACTiger", "org.bouncycastle.jce.provider.JCEMac$Tiger");
-        put("Alg.Alias.Mac.HMAC-Tiger", "HMACTiger");
-        put("Alg.Alias.Mac.HMAC/Tiger", "HMACTiger");
-
-        put("Mac.PBEWITHHMACSHA", "org.bouncycastle.jce.provider.JCEMac$PBEWithSHA");
-        put("Mac.PBEWITHHMACRIPEMD160", "org.bouncycastle.jce.provider.JCEMac$PBEWithRIPEMD160");
-        put("Alg.Alias.Mac.1.3.14.3.2.26", "PBEWITHHMACSHA");
-
-        //
-        // MessageDigests
-        //
-        put("MessageDigest.SHA-1", "org.bouncycastle.jce.provider.JDKMessageDigest$SHA1");
-        put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
-        put("Alg.Alias.MessageDigest.SHA", "SHA-1");
-        put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA-1");
-        put("MessageDigest.SHA-256", "org.bouncycastle.jce.provider.JDKMessageDigest$SHA256");
-        put("MessageDigest.SHA-384", "org.bouncycastle.jce.provider.JDKMessageDigest$SHA384");
-        put("MessageDigest.SHA-512", "org.bouncycastle.jce.provider.JDKMessageDigest$SHA512");
-        put("MessageDigest.MD2", "org.bouncycastle.jce.provider.JDKMessageDigest$MD2");
-        put("MessageDigest.MD4", "org.bouncycastle.jce.provider.JDKMessageDigest$MD4");
-        put("MessageDigest.MD5", "org.bouncycastle.jce.provider.JDKMessageDigest$MD5");
-        put("MessageDigest.1.2.840.113549.2.5", "org.bouncycastle.jce.provider.JDKMessageDigest$MD5");
-        put("MessageDigest.RIPEMD128", "org.bouncycastle.jce.provider.JDKMessageDigest$RIPEMD128");
-        put("MessageDigest.RIPEMD160", "org.bouncycastle.jce.provider.JDKMessageDigest$RIPEMD160");
-		put("MessageDigest.RIPEMD256", "org.bouncycastle.jce.provider.JDKMessageDigest$RIPEMD256");
-		put("MessageDigest.RIPEMD320", "org.bouncycastle.jce.provider.JDKMessageDigest$RIPEMD320");
-        put("MessageDigest.Tiger", "org.bouncycastle.jce.provider.JDKMessageDigest$Tiger");
-
-        //
-        // signature algorithms.
-        //
-        put("Signature.MD2WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$MD2WithRSAEncryption");
-        put("Signature.MD5WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$MD5WithRSAEncryption");
-        put("Signature.SHA1WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$SHA1WithRSAEncryption");
-        put("Signature.RIPEMD160WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$RIPEMD160WithRSAEncryption");
-		put("Signature.RIPEMD128WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$RIPEMD128WithRSAEncryption");
-		put("Signature.RIPEMD256WithRSAEncryption", "org.bouncycastle.jce.provider.JDKDigestSignature$RIPEMD256WithRSAEncryption");
-        put("Signature.DSA", "org.bouncycastle.jce.provider.JDKDSASigner$stdDSA");
-        put("Signature.ECDSA", "org.bouncycastle.jce.provider.JDKDSASigner$ecDSA");
-        put("Signature.SHA1withRSA/ISO9796-2", "org.bouncycastle.jce.provider.JDKISOSignature$SHA1WithRSAEncryption");
-        put("Signature.MD5withRSA/ISO9796-2", "org.bouncycastle.jce.provider.JDKISOSignature$MD5WithRSAEncryption");
-        put("Signature.RIPEMD160withRSA/ISO9796-2", "org.bouncycastle.jce.provider.JDKISOSignature$RIPEMD160WithRSAEncryption");
-
-		put("Signature.SHA1withRSA/PSS", "org.bouncycastle.jce.provider.JDKPSSSigner$SHA1withRSA");
-		put("Signature.SHA256withRSA/PSS", "org.bouncycastle.jce.provider.JDKPSSSigner$SHA256withRSA");
-		put("Signature.SHA384withRSA/PSS", "org.bouncycastle.jce.provider.JDKPSSSigner$SHA384withRSA");
-		put("Signature.SHA512withRSA/PSS", "org.bouncycastle.jce.provider.JDKPSSSigner$SHA512withRSA");
-
-		put("Alg.Alias.Signature.MD2withRSAEncryption", "MD2WithRSAEncryption");
-		put("Alg.Alias.Signature.MD5withRSAEncryption", "MD5WithRSAEncryption");
-		put("Alg.Alias.Signature.SHA1withRSAEncryption", "SHA1WithRSAEncryption");
-
-		put("Alg.Alias.Signature.SHA256withRSAEncryption", "SHA256withRSA/PSS");
-		put("Alg.Alias.Signature.SHA384withRSAEncryption", "SHA384withRSA/PSS");
-		put("Alg.Alias.Signature.SHA512withRSAEncryption", "SHA512withRSA/PSS");
-
-		put("Alg.Alias.Signature.SHA256WithRSAEncryption", "SHA256withRSA/PSS");
-		put("Alg.Alias.Signature.SHA384WithRSAEncryption", "SHA384withRSA/PSS");
-		put("Alg.Alias.Signature.SHA512WithRSAEncryption", "SHA512withRSA/PSS");
-
-		put("Alg.Alias.Signature.SHA256WITHRSAENCRYPTION", "SHA256withRSA/PSS");
-		put("Alg.Alias.Signature.SHA384WITHRSAENCRYPTION", "SHA384withRSA/PSS");
-		put("Alg.Alias.Signature.SHA512WITHRSAENCRYPTION", "SHA512withRSA/PSS");
-
-		put("Alg.Alias.Signature.RIPEMD160withRSAEncryption", "RIPEMD160WithRSAEncryption");
-
-		put("Alg.Alias.Signature.1.2.840.113549.1.1.2", "MD2WithRSAEncryption");
-		put("Alg.Alias.Signature.MD2WithRSA", "MD2WithRSAEncryption");
-		put("Alg.Alias.Signature.MD2withRSA", "MD2WithRSAEncryption");
-		put("Alg.Alias.Signature.MD2/RSA", "MD2WithRSAEncryption");
-		put("Alg.Alias.Signature.MD5WithRSA", "MD5WithRSAEncryption");
-		put("Alg.Alias.Signature.MD5withRSA", "MD5WithRSAEncryption");
-		put("Alg.Alias.Signature.MD5/RSA", "MD5WithRSAEncryption");
-		put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5WithRSAEncryption");
-		put("Alg.Alias.Signature.SHA1WithRSA", "SHA1WithRSAEncryption");
-		put("Alg.Alias.Signature.SHA1withRSA", "SHA1WithRSAEncryption");
-		put("Alg.Alias.Signature.SHA1/RSA", "SHA1WithRSAEncryption");
-		put("Alg.Alias.Signature.SHA-1/RSA", "SHA1WithRSAEncryption");
-		put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1WithRSAEncryption");
-		put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.1", "SHA1WithRSAEncryption");
-		put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.5", "SHA1WithRSAEncryption");
-		put("Alg.Alias.Signature.1.2.840.113549.2.5with1.2.840.113549.1.1.1", "MD5WithRSAEncryption");
-		put("Alg.Alias.Signature.RIPEMD160WithRSA", "RIPEMD160WithRSAEncryption");
-		put("Alg.Alias.Signature.RIPEMD160withRSA", "RIPEMD160WithRSAEncryption");
-		put("Alg.Alias.Signature.RIPEMD128WithRSA", "RIPEMD128WithRSAEncryption");
-		put("Alg.Alias.Signature.RIPEMD128withRSA", "RIPEMD128WithRSAEncryption");
-		put("Alg.Alias.Signature.RIPEMD256WithRSA", "RIPEMD256WithRSAEncryption");
-		put("Alg.Alias.Signature.RIPEMD256withRSA", "RIPEMD256WithRSAEncryption");
-		put("Alg.Alias.Signature.RIPEMD-160/RSA", "RIPEMD160WithRSAEncryption");
-		put("Alg.Alias.Signature.RMD160withRSA", "RIPEMD160WithRSAEncryption");
-		put("Alg.Alias.Signature.RMD160/RSA", "RIPEMD160WithRSAEncryption");
-		put("Alg.Alias.Signature.1.3.36.3.3.1.2", "RIPEMD160WithRSAEncryption");
-		put("Alg.Alias.Signature.1.3.36.3.3.1.3", "RIPEMD128WithRSAEncryption");
-		put("Alg.Alias.Signature.1.3.36.3.3.1.4", "RIPEMD256WithRSAEncryption");
-		
-		put("Alg.Alias.Signature.MD2WITHRSAENCRYPTION", "MD2WithRSAEncryption");
-		put("Alg.Alias.Signature.MD5WITHRSAENCRYPTION", "MD5WithRSAEncryption");
-		put("Alg.Alias.Signature.SHA1WITHRSAENCRYPTION", "SHA1WithRSAEncryption");
-		put("Alg.Alias.Signature.RIPEMD160WITHRSAENCRYPTION", "RIPEMD160WithRSAEncryption");
-
-		put("Alg.Alias.Signature.MD5WITHRSA", "MD5WithRSAEncryption");
-		put("Alg.Alias.Signature.SHA1WITHRSA", "SHA1WithRSAEncryption");
-		put("Alg.Alias.Signature.RIPEMD160WITHRSA", "RIPEMD160WithRSAEncryption");
-		put("Alg.Alias.Signature.RMD160WITHRSA", "RIPEMD160WithRSAEncryption");
-		put("Alg.Alias.Signature.RIPEMD160WITHRSA", "RIPEMD160WithRSAEncryption");
-
-		put("Alg.Alias.Signature.SHA1withECDSA", "ECDSA");
-		put("Alg.Alias.Signature.ECDSAwithSHA1", "ECDSA");
-		put("Alg.Alias.Signature.SHA1WITHECDSA", "ECDSA");
-		put("Alg.Alias.Signature.ECDSAWITHSHA1", "ECDSA");
-		put("Alg.Alias.Signature.SHA1WithECDSA", "ECDSA");
-		put("Alg.Alias.Signature.ECDSAWithSHA1", "ECDSA");
-        put("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA");
-		put("Alg.Alias.Signature.SHA/DSA", "DSA");
-		put("Alg.Alias.Signature.SHA1withDSA", "DSA");
-		put("Alg.Alias.Signature.SHA1WITHDSA", "DSA");
-		put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.1", "DSA");
-		put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.3", "DSA");
-		put("Alg.Alias.Signature.DSAwithSHA1", "DSA");
-		put("Alg.Alias.Signature.DSAWITHSHA1", "DSA");
-		put("Alg.Alias.Signature.SHA1WithDSA", "DSA");
-		put("Alg.Alias.Signature.DSAWithSHA1", "DSA");
-        put("Alg.Alias.Signature.1.2.840.10040.4.3", "DSA");
-        put("Alg.Alias.Signature.MD5WithRSA/ISO9796-2", "MD5withRSA/ISO9796-2");
-        put("Alg.Alias.Signature.SHA1WithRSA/ISO9796-2", "SHA1withRSA/ISO9796-2");
-        put("Alg.Alias.Signature.RIPEMD160WithRSA/ISO9796-2", "RIPEMD160withRSA/ISO9796-2");
-
-	// Certification Path API
-	put("CertPathValidator.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi" );
-	put("CertPathValidator.PKIX ValidationAlgorithm", "RFC2459");
-	put("CertPathBuilder.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi" );
-	put("CertPathBuilder.PKIX ValidationAlgorithm", "RFC2459");
-	put("CertStore.Collection", "org.bouncycastle.jce.provider.CertStoreCollectionSpi" );
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/CertStoreCollectionSpi.java b/azureus2/src/org/bouncycastle/jce/provider/CertStoreCollectionSpi.java
deleted file mode 100644
index 7549955..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/CertStoreCollectionSpi.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.cert.CRL;
-import java.security.cert.CRLSelector;
-import java.security.cert.CertSelector;
-import java.security.cert.CertStoreException;
-import java.security.cert.CertStoreParameters;
-import java.security.cert.CertStoreSpi;
-import java.security.cert.Certificate;
-import java.security.cert.CollectionCertStoreParameters;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-public class CertStoreCollectionSpi extends CertStoreSpi
-{
-    private CollectionCertStoreParameters params;
-
-    public CertStoreCollectionSpi(CertStoreParameters params)
-        throws InvalidAlgorithmParameterException
-	{
-	    super(params);
-
-	    if (!(params instanceof CollectionCertStoreParameters))
-        {
-            throw new InvalidAlgorithmParameterException( "org.bouncycastle.jce.provider.CertStoreCollectionSpi: parameter must be a CollectionCertStoreParameters object\n" +  params.toString() );
-        }
-
-	    this.params = (CollectionCertStoreParameters)params;
-	}
-
-    public Collection engineGetCertificates(
-        CertSelector selector)
-        throws CertStoreException 
-	{
-	    Set         col = new HashSet();
-	    Iterator    iter = params.getCollection().iterator();
-
-        if (selector == null)
-        {
-            while (iter.hasNext())
-            {
-                Object obj = iter.next();
-
-                if (obj instanceof Certificate)
-                {
-                    col.add(obj);
-                }
-            }
-        }
-        else
-        {
-            while (iter.hasNext())
-            {
-                Object obj = iter.next();
-
-                if ((obj instanceof Certificate) && selector.match((Certificate)obj))
-                {
-                    col.add(obj);
-                }
-            }
-        }
-	    
-	    return col;
-	}
-    
-
-    public Collection engineGetCRLs(
-        CRLSelector selector)
-        throws CertStoreException 
-	{
-	    Set         col = new HashSet();
-	    Iterator    iter = params.getCollection().iterator();
-
-        if (selector == null)
-        {
-            while (iter.hasNext())
-            {
-                Object obj = iter.next();
-
-                if (obj instanceof CRL)
-                {
-                    col.add(obj);
-                }
-            }
-        }
-        else
-        {
-            while (iter.hasNext())
-            {
-                Object obj = iter.next();
-
-                if ((obj instanceof CRL) && selector.match((CRL)obj))
-                {
-                    col.add(obj);
-                }
-            }
-        }
-	    
-	    return col;
-	}    
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/DHUtil.java b/azureus2/src/org/bouncycastle/jce/provider/DHUtil.java
deleted file mode 100644
index 2470af9..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/DHUtil.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.InvalidKeyException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import javax.crypto.interfaces.DHPrivateKey;
-import javax.crypto.interfaces.DHPublicKey;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DHPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DHPublicKeyParameters;
-
-/**
- * utility class for converting jce/jca DH objects
- * objects into their org.bouncycastle.crypto counterparts.
- */
-public class DHUtil
-{
-    static public AsymmetricKeyParameter generatePublicKeyParameter(
-        PublicKey    key)
-        throws InvalidKeyException
-    {
-        if (key instanceof DHPublicKey)
-        {
-            DHPublicKey    k = (DHPublicKey)key;
-
-            return new DHPublicKeyParameters(k.getY(),
-                new DHParameters(k.getParams().getP(), k.getParams().getG(), null, k.getParams().getL()));
-        }
-
-        throw new InvalidKeyException("can't identify DH public key.");
-    }
-
-    static public AsymmetricKeyParameter generatePrivateKeyParameter(
-        PrivateKey    key)
-        throws InvalidKeyException
-    {
-        if (key instanceof DHPrivateKey)
-        {
-            DHPrivateKey    k = (DHPrivateKey)key;
-
-            return new DHPrivateKeyParameters(k.getX(),
-                new DHParameters(k.getParams().getP(), k.getParams().getG(), null, k.getParams().getL()));
-        }
-                        
-        throw new InvalidKeyException("can't identify DH private key.");
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/DSAUtil.java b/azureus2/src/org/bouncycastle/jce/provider/DSAUtil.java
deleted file mode 100644
index 5cf3c22..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/DSAUtil.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.InvalidKeyException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.DSAPublicKey;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
-import org.bouncycastle.crypto.params.DSAPublicKeyParameters;
-
-/**
- * utility class for converting jce/jca DSA objects
- * objects into their org.bouncycastle.crypto counterparts.
- */
-public class DSAUtil
-{
-    static public AsymmetricKeyParameter generatePublicKeyParameter(
-        PublicKey    key)
-        throws InvalidKeyException
-    {
-        if (key instanceof DSAPublicKey)
-        {
-            DSAPublicKey    k = (DSAPublicKey)key;
-
-            return new DSAPublicKeyParameters(k.getY(),
-                new DSAParameters(k.getParams().getP(), k.getParams().getQ(), k.getParams().getG()));
-        }
-
-        throw new InvalidKeyException("can't identify DSA public key: " + key.getClass().getName());
-    }
-
-    static public AsymmetricKeyParameter generatePrivateKeyParameter(
-        PrivateKey    key)
-        throws InvalidKeyException
-    {
-        if (key instanceof DSAPrivateKey)
-        {
-            DSAPrivateKey    k = (DSAPrivateKey)key;
-
-            return new DSAPrivateKeyParameters(k.getX(),
-                new DSAParameters(k.getParams().getP(), k.getParams().getQ(), k.getParams().getG()));
-        }
-                        
-        throw new InvalidKeyException("can't identify DSA private key.");
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/ECUtil.java b/azureus2/src/org/bouncycastle/jce/provider/ECUtil.java
deleted file mode 100644
index 849db16..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/ECUtil.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.InvalidKeyException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.jce.interfaces.ECPrivateKey;
-import org.bouncycastle.jce.interfaces.ECPublicKey;
-import org.bouncycastle.jce.spec.ECParameterSpec;
-
-/**
- * utility class for converting jce/jca ECDSA, ECDH, and ECDHC
- * objects into their org.bouncycastle.crypto counterparts.
- */
-public class ECUtil
-{
-    static public AsymmetricKeyParameter generatePublicKeyParameter(
-        PublicKey    key)
-        throws InvalidKeyException
-    {
-        if (key instanceof ECPublicKey)
-        {
-            ECPublicKey    k = (ECPublicKey)key;
-            ECParameterSpec s = k.getParams();
-
-            return new ECPublicKeyParameters(
-                            k.getQ(),
-                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN()));
-        }
-
-        throw new InvalidKeyException("can't identify EC public key.");
-    }
-
-    static public AsymmetricKeyParameter generatePrivateKeyParameter(
-        PrivateKey    key)
-        throws InvalidKeyException
-    {
-        if (key instanceof ECPrivateKey)
-        {
-            ECPrivateKey    k = (ECPrivateKey)key;
-            ECParameterSpec s = k.getParams();
-
-            return new ECPrivateKeyParameters(
-                            k.getD(),
-                            new ECDomainParameters(s.getCurve(), s.getG(), s.getN()));
-        }
-                        
-        throw new InvalidKeyException("can't identify EC private key.");
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/ElGamalUtil.java b/azureus2/src/org/bouncycastle/jce/provider/ElGamalUtil.java
deleted file mode 100644
index f89c656..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/ElGamalUtil.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.InvalidKeyException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
-import org.bouncycastle.crypto.params.ElGamalParameters;
-import org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
-import org.bouncycastle.jce.interfaces.ElGamalPrivateKey;
-import org.bouncycastle.jce.interfaces.ElGamalPublicKey;
-
-/**
- * utility class for converting jce/jca ElGamal objects
- * objects into their org.bouncycastle.crypto counterparts.
- */
-public class ElGamalUtil
-{
-    static public AsymmetricKeyParameter generatePublicKeyParameter(
-        PublicKey    key)
-        throws InvalidKeyException
-    {
-        if (key instanceof ElGamalPublicKey)
-        {
-            ElGamalPublicKey    k = (ElGamalPublicKey)key;
-
-            return new ElGamalPublicKeyParameters(k.getY(),
-                new ElGamalParameters(k.getParams().getP(), k.getParams().getG()));
-        }
-
-        throw new InvalidKeyException("can't identify ElGamal public key.");
-    }
-
-    static public AsymmetricKeyParameter generatePrivateKeyParameter(
-        PrivateKey    key)
-        throws InvalidKeyException
-    {
-        if (key instanceof ElGamalPrivateKey)
-        {
-            ElGamalPrivateKey    k = (ElGamalPrivateKey)key;
-
-            return new ElGamalPrivateKeyParameters(k.getX(),
-                new ElGamalParameters(k.getParams().getP(), k.getParams().getG()));
-        }
-                        
-        throw new InvalidKeyException("can't identify ElGamal private key.");
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JCEECDHKeyAgreement.java b/azureus2/src/org/bouncycastle/jce/provider/JCEECDHKeyAgreement.java
deleted file mode 100644
index 174c0e4..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JCEECDHKeyAgreement.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.spec.AlgorithmParameterSpec;
-
-import javax.crypto.KeyAgreementSpi;
-import javax.crypto.SecretKey;
-import javax.crypto.ShortBufferException;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.bouncycastle.crypto.BasicAgreement;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
-//import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
-import org.bouncycastle.jce.interfaces.ECPrivateKey;
-import org.bouncycastle.jce.interfaces.ECPublicKey;
-
-/**
- * Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363
- * both the simple one, and the simple one with cofactors are supported.
- */
-public class JCEECDHKeyAgreement
-    extends KeyAgreementSpi
-{
-    private BigInteger          result;
-    private CipherParameters    privKey;
-    private BasicAgreement      agreement;
-
-    protected JCEECDHKeyAgreement(
-        BasicAgreement  agreement)
-    {
-        this.agreement = agreement;
-    }
-
-    public Key
-    doPhase(
-    	Key		key,
-    	boolean	lastPhase )
-    
-    	throws InvalidKeyException, IllegalStateException
-    {
-    	return( engineDoPhase( key, lastPhase ));
-    }
-    
-    protected Key engineDoPhase(
-        Key     key,
-        boolean lastPhase) 
-        throws InvalidKeyException, IllegalStateException
-    {
-        if (privKey == null)
-        {
-            throw new IllegalStateException("EC Diffie-Hellman not initialised.");
-        }
-
-        if (!lastPhase)
-        {
-            throw new IllegalStateException("EC Diffie-Hellman can only be between two parties.");
-        }
-
-        if (!(key instanceof ECPublicKey))
-        {
-            throw new InvalidKeyException("EC Key Agreement doPhase requires ECPublicKey");
-        }
-
-        CipherParameters pubKey = ECUtil.generatePublicKeyParameter((PublicKey)key);
-
-        result = agreement.calculateAgreement(pubKey);
-
-        return null;
-    }
-
-    public byte[] 
-    generateSecret() 
-    	throws IllegalStateException
-    {
-    	return( engineGenerateSecret());
-    }
-    
-    protected byte[] engineGenerateSecret() 
-        throws IllegalStateException
-    {
-        return result.toByteArray();
-    }
-
-    protected int engineGenerateSecret(
-        byte[]  sharedSecret,
-        int     offset) 
-        throws IllegalStateException, ShortBufferException
-    {
-        byte[]  secret = result.toByteArray();
-
-        if (sharedSecret.length - offset < secret.length)
-        {
-            throw new ShortBufferException("ECKeyAgreement - buffer too short");
-        }
-
-        System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
-
-        return secret.length;
-    }
-
-    protected SecretKey engineGenerateSecret(
-        String algorithm) 
-    {
-        return new SecretKeySpec(result.toByteArray(), algorithm);
-    }
-
-    public void
-    init(
-    	Key		key )
-    
-    	throws InvalidKeyException, InvalidAlgorithmParameterException
-    {
-    	engineInit( key, null );
-    }
-    
-    protected void engineInit(
-        Key                     key,
-        AlgorithmParameterSpec  params,
-        SecureRandom            random) 
-        throws InvalidKeyException, InvalidAlgorithmParameterException
-    {
-        if (!(key instanceof ECPrivateKey))
-        {
-            throw new InvalidKeyException("ECKeyAgreement requires ECPrivateKey for initialisation");
-        }
-
-        privKey = ECUtil.generatePrivateKeyParameter((PrivateKey)key);
-
-        agreement.init(privKey);
-    }
-
-    protected void engineInit(
-        Key             key,
-        SecureRandom    random) 
-        throws InvalidKeyException
-    {
-        if (!(key instanceof ECPrivateKey))
-        {
-            throw new InvalidKeyException("ECKeyAgreement requires ECPrivateKey");
-        }
-
-        privKey = ECUtil.generatePrivateKeyParameter((PrivateKey)key);
-
-        agreement.init(privKey);
-    }
-
-    public static class DH
-        extends JCEECDHKeyAgreement
-    {
-        public DH()
-        {
-            super(new ECDHBasicAgreement());
-        }
-    }
-
-    /*
-    public static class DHC
-        extends JCEECDHKeyAgreement
-    {
-        public DHC()
-        {
-            super(new ECDHCBasicAgreement());
-        }
-    }
-    */
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JCEECPrivateKey.java b/azureus2/src/org/bouncycastle/jce/provider/JCEECPrivateKey.java
deleted file mode 100644
index 3109be5..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JCEECPrivateKey.java
+++ /dev/null
@@ -1,270 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.sec.ECPrivateKeyStructure;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x9.X962NamedCurves;
-import org.bouncycastle.asn1.x9.X962Parameters;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.jce.interfaces.ECPrivateKey;
-import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
-import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
-import org.bouncycastle.jce.spec.ECParameterSpec;
-import org.bouncycastle.jce.spec.ECPrivateKeySpec;
-
-public class JCEECPrivateKey
-    implements ECPrivateKey, PKCS12BagAttributeCarrier
-{
-    private String          algorithm = "EC";
-    private BigInteger      d;
-    private ECParameterSpec ecSpec;
-
-    private Hashtable   pkcs12Attributes = new Hashtable();
-    private Vector      pkcs12Ordering = new Vector();
-
-    protected JCEECPrivateKey()
-    {
-    }
-
-    JCEECPrivateKey(
-        ECPrivateKey    key)
-    {
-        this.d = key.getD();
-        this.algorithm = key.getAlgorithm();
-        this.ecSpec = key.getParams();
-    }
-
-    JCEECPrivateKey(
-        String              algorithm,
-        ECPrivateKeySpec    spec)
-    {
-        this.algorithm = algorithm;
-        this.d = spec.getD();
-        this.ecSpec = spec.getParams();
-    }
-
-    JCEECPrivateKey(
-        String                  algorithm,
-        ECPrivateKeyParameters  params,
-        ECParameterSpec         spec)
-    {
-        ECDomainParameters      dp = params.getParameters();
-
-        this.algorithm = algorithm;
-        this.d = params.getD();
-
-        if (spec == null)
-        {
-            this.ecSpec = new ECParameterSpec(
-                            dp.getCurve(),
-                            dp.getG(),
-                            dp.getN(),
-                            dp.getH(),
-                            dp.getSeed());
-        }
-        else
-        {
-            this.ecSpec = spec;
-        }
-    }
-
-    JCEECPrivateKey(
-        PrivateKeyInfo      info)
-    {
-        X962Parameters      params = new X962Parameters((DERObject)info.getAlgorithmId().getParameters());
-
-        if (params.isNamedCurve())
-        {
-            DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters();
-            X9ECParameters      ecP = X962NamedCurves.getByOID(oid);
-
-            ecSpec = new ECNamedCurveParameterSpec(
-                                        X962NamedCurves.getName(oid),
-                                        ecP.getCurve(),
-                                        ecP.getG(),
-                                        ecP.getN(),
-                                        ecP.getH(),
-                                        ecP.getSeed());
-        }
-        else
-        {
-            X9ECParameters          ecP = new X9ECParameters((ASN1Sequence)params.getParameters());
-            ecSpec = new ECParameterSpec(ecP.getCurve(),
-                                            ecP.getG(),
-                                            ecP.getN(),
-                                            ecP.getH(),
-                                            ecP.getSeed());
-        }
-
-        if (info.getPrivateKey() instanceof DERInteger)
-        {
-            DERInteger          derD = (DERInteger)info.getPrivateKey();
-
-            this.d = derD.getValue();
-        }
-        else
-        {
-            ECPrivateKeyStructure   ec = new ECPrivateKeyStructure((ASN1Sequence)info.getPrivateKey());
-
-            this.d = ec.getKey();
-        }
-    }
-
-    public String getAlgorithm()
-    {
-        return algorithm;
-    }
-
-    /**
-     * return the encoding format we produce in getEncoded().
-     *
-     * @return the string "PKCS#8"
-     */
-    public String getFormat()
-    {
-        return "PKCS#8";
-    }
-
-    /**
-     * Return a PKCS8 representation of the key. The sequence returned
-     * represents a full PrivateKeyInfo object.
-     *
-     * @return a PKCS8 representation of the key.
-     */
-    public byte[] getEncoded()
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-        X962Parameters          params = null;
-
-        if (ecSpec instanceof ECNamedCurveParameterSpec)
-        {
-            params = new X962Parameters(X962NamedCurves.getOID(((ECNamedCurveParameterSpec)ecSpec).getName()));
-        }
-        else
-        {
-            X9ECParameters          ecP = new X9ECParameters(
-                                            ecSpec.getCurve(),
-                                            ecSpec.getG(),
-                                            ecSpec.getN(),
-                                            ecSpec.getH(),
-                                            ecSpec.getSeed());
-            params = new X962Parameters(ecP);
-        }
-
-        PrivateKeyInfo          info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.getDERObject()), new ECPrivateKeyStructure(this.getD()).getDERObject());
-
-        try
-        {
-            dOut.writeObject(info);
-            dOut.close();
-        }
-        catch (IOException e)
-        {
-            throw new RuntimeException("Error encoding EC private key");
-        }
-
-        return bOut.toByteArray();
-    }
-
-    public ECParameterSpec getParams()
-    {
-        return ecSpec;
-    }
-
-    public BigInteger getD()
-    {
-        return d;
-    }
-
-/*
-    private void readObject(
-        ObjectInputStream   in)
-        throws IOException, ClassNotFoundException
-    {
-        in.defaultReadObject();
-
-        boolean named = in.readBoolean();
-
-        if (named)
-        {
-            ecSpec = new ECNamedCurveParameterSpec(
-                        in.readUTF(),
-                        (ECCurve)in.readObject(),
-                        (ECPoint)in.readObject(),
-                        (BigInteger)in.readObject(),
-                        (BigInteger)in.readObject(),
-                        (byte[])in.readObject());
-        }
-        else
-        {
-            ecSpec = new ECParameterSpec(
-                        (ECCurve)in.readObject(),
-                        (ECPoint)in.readObject(),
-                        (BigInteger)in.readObject(),
-                        (BigInteger)in.readObject(),
-                        (byte[])in.readObject());
-        }
-    }
-
-    private void writeObject(
-        ObjectOutputStream  out)
-        throws IOException
-    {
-        out.defaultWriteObject();
-
-        if (this.ecSpec instanceof ECNamedCurveParameterSpec)
-        {
-            ECNamedCurveParameterSpec   namedSpec = (ECNamedCurveParameterSpec)ecSpec;
-
-            out.writeBoolean(true);
-            out.writeUTF(namedSpec.getName());
-        }
-        else
-        {
-            out.writeBoolean(false);
-        }
-
-        out.writeObject(ecSpec.getCurve());
-        out.writeObject(ecSpec.getG());
-        out.writeObject(ecSpec.getN());
-        out.writeObject(ecSpec.getH());
-        out.writeObject(ecSpec.getSeed());
-    }
-*/
-
-    public void setBagAttribute(
-        DERObjectIdentifier oid,
-        DEREncodable        attribute)
-    {
-        pkcs12Attributes.put(oid, attribute);
-        pkcs12Ordering.addElement(oid);
-    }
-
-    public DEREncodable getBagAttribute(
-        DERObjectIdentifier oid)
-    {
-        return (DEREncodable)pkcs12Attributes.get(oid);
-    }
-
-    public Enumeration getBagAttributeKeys()
-    {
-        return pkcs12Ordering.elements();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JCEECPublicKey.java b/azureus2/src/org/bouncycastle/jce/provider/JCEECPublicKey.java
deleted file mode 100644
index de35093..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JCEECPublicKey.java
+++ /dev/null
@@ -1,273 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.bouncycastle.asn1.ASN1OctetString;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERInputStream;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x9.X962NamedCurves;
-import org.bouncycastle.asn1.x9.X962Parameters;
-import org.bouncycastle.asn1.x9.X9ECParameters;
-import org.bouncycastle.asn1.x9.X9ECPoint;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.jce.interfaces.ECPublicKey;
-import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
-import org.bouncycastle.jce.spec.ECParameterSpec;
-import org.bouncycastle.jce.spec.ECPublicKeySpec;
-import org.bouncycastle.math.ec.ECPoint;
-
-public class JCEECPublicKey
-    implements ECPublicKey
-{
-    private String                  algorithm = "EC";
-    private ECPoint                 q;
-    private ECParameterSpec         ecSpec;
-
-    JCEECPublicKey(
-        String              algorithm,
-        ECPublicKeySpec     spec)
-    {
-        this.algorithm = algorithm;
-        this.q = spec.getQ();
-        this.ecSpec = spec.getParams();
-    }
-
-    JCEECPublicKey(
-        String                  algorithm,
-        ECPublicKeyParameters   params,
-        ECParameterSpec         spec)
-    {
-        ECDomainParameters      dp = params.getParameters();
-
-        this.algorithm = algorithm;
-        this.q = params.getQ();
-
-        if (spec == null)
-        {
-            this.ecSpec = new ECParameterSpec(
-                            dp.getCurve(),
-                            dp.getG(),
-                            dp.getN(),
-                            dp.getH(),
-                            dp.getSeed());
-        }
-        else
-        {
-            this.ecSpec = spec;
-        }
-    }
-
-    JCEECPublicKey(
-        String          algorithm,
-        ECPublicKey     key)
-    {
-        this.q = key.getQ();
-        this.algorithm = key.getAlgorithm();
-        this.ecSpec = key.getParams();
-    }
-
-    JCEECPublicKey(
-        String            algorithm,
-        ECPoint           q,
-        ECParameterSpec   ecSpec)
-    {
-        this.algorithm = algorithm;
-        this.q = q;
-        this.ecSpec = ecSpec;
-    }
-
-    JCEECPublicKey(
-        SubjectPublicKeyInfo    info)
-    {
-        X962Parameters          params = new X962Parameters((DERObject)info.getAlgorithmId().getParameters());
-
-        if (params.isNamedCurve())
-        {
-            DERObjectIdentifier oid = (DERObjectIdentifier)params.getParameters();
-            X9ECParameters      ecP = X962NamedCurves.getByOID(oid);
-
-            ecSpec = new ECNamedCurveParameterSpec(
-                                        X962NamedCurves.getName(oid),
-                                        ecP.getCurve(),
-                                        ecP.getG(),
-                                        ecP.getN(),
-                                        ecP.getH(),
-                                        ecP.getSeed());
-        }
-        else
-        {
-            X9ECParameters ecP = new X9ECParameters(
-                        (ASN1Sequence)params.getParameters());
-            ecSpec = new ECParameterSpec(
-                                        ecP.getCurve(),
-                                        ecP.getG(),
-                                        ecP.getN(),
-                                        ecP.getH(),
-                                        ecP.getSeed());
-        }
-
-        DERBitString    bits = info.getPublicKeyData();
-        byte[]          data = bits.getBytes();
-		ASN1OctetString	key = new DEROctetString(data);
-
-        //
-        // extra octet string - one of our old certs...
-        //
-        if (data[0] == 0x04 && data[1] == data.length - 2 
-            && (data[2] == 0x02 || data[2] == 0x03))
-        {
-            try
-            {
-                ByteArrayInputStream    bIn = new ByteArrayInputStream(data);
-                DERInputStream          dIn = new DERInputStream(bIn);
-
-                key = (ASN1OctetString)dIn.readObject();
-            }
-            catch (IOException ex)
-            {
-                throw new IllegalArgumentException("error recovering public key");
-            }
-        }
-
-        X9ECPoint       derQ = new X9ECPoint(ecSpec.getCurve(), key);
-
-        this.q = derQ.getPoint();
-    }
-
-    public String getAlgorithm()
-    {
-        return algorithm;
-    }
-
-    public String getFormat()
-    {
-        return "X.509";
-    }
-
-    public byte[] getEncoded()
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-        X962Parameters          params = null;
-
-        if (ecSpec instanceof ECNamedCurveParameterSpec)
-        {
-            params = new X962Parameters(X962NamedCurves.getOID(((ECNamedCurveParameterSpec)ecSpec).getName()));
-        }
-        else
-        {
-            X9ECParameters          ecP = new X9ECParameters(
-                                            ecSpec.getCurve(),
-                                            ecSpec.getG(),
-                                            ecSpec.getN(),
-                                            ecSpec.getH(),
-                                            ecSpec.getSeed());
-            params = new X962Parameters(ecP);
-        }
-
-        ASN1OctetString    p = (ASN1OctetString)(new X9ECPoint(this.getQ()).getDERObject());
-
-        SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, params.getDERObject()), p.getOctets());
-
-        try
-        {
-            dOut.writeObject(info);
-            dOut.close();
-        }
-        catch (IOException e)
-        {
-            throw new RuntimeException("Error encoding EC public key");
-        }
-
-        return bOut.toByteArray();
-    }
-
-    public ECParameterSpec getParams()
-    {
-        return ecSpec;
-    }
-
-    public ECPoint getQ()
-    {
-        return q;
-    }
-
-    public String toString()
-    {
-        StringBuffer    buf = new StringBuffer();
-        String          nl = System.getProperty("line.separator");
-
-        buf.append("EC Public Key" + nl);
-        buf.append("            X: " + this.getQ().getX().toBigInteger().toString(16) + nl);
-        buf.append("            Y: " + this.getQ().getY().toBigInteger().toString(16) + nl);
-
-        return buf.toString();
-
-    }
-/*
-    private void readObject(
-        ObjectInputStream   in)
-        throws IOException, ClassNotFoundException
-    {
-        in.defaultReadObject();
-
-        boolean named = in.readBoolean();
-
-        if (named)
-        {
-            ecSpec = new ECNamedCurveParameterSpec(
-                        in.readUTF(),
-                        (ECCurve)in.readObject(),
-                        (ECPoint)in.readObject(),
-                        (BigInteger)in.readObject(),
-                        (BigInteger)in.readObject(),
-                        (byte[])in.readObject());
-        }
-        else
-        {
-            ecSpec = new ECParameterSpec(
-                        (ECCurve)in.readObject(),
-                        (ECPoint)in.readObject(),
-                        (BigInteger)in.readObject(),
-                        (BigInteger)in.readObject(),
-                        (byte[])in.readObject());
-        }
-    }
-
-    private void writeObject(
-        ObjectOutputStream  out)
-        throws IOException
-    {
-        out.defaultWriteObject();
-
-        if (this.ecSpec instanceof ECNamedCurveParameterSpec)
-        {
-            ECNamedCurveParameterSpec   namedSpec = (ECNamedCurveParameterSpec)ecSpec;
-
-            out.writeBoolean(true);
-            out.writeUTF(namedSpec.getName());
-        }
-        else
-        {
-            out.writeBoolean(false);
-        }
-
-        out.writeObject(ecSpec.getCurve());
-        out.writeObject(ecSpec.getG());
-        out.writeObject(ecSpec.getN());
-        out.writeObject(ecSpec.getH());
-        out.writeObject(ecSpec.getSeed());
-    }
-*/
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JCEIESCipher.java b/azureus2/src/org/bouncycastle/jce/provider/JCEIESCipher.java
deleted file mode 100644
index 3908d87..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JCEIESCipher.java
+++ /dev/null
@@ -1,371 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.io.ByteArrayOutputStream;
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.SecureRandom;
-import java.security.spec.AlgorithmParameterSpec;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.interfaces.DHPrivateKey;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-//import org.bouncycastle.crypto.agreement.DHBasicAgreement;
-import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.engines.IESEngine;
-import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
-import org.bouncycastle.crypto.macs.HMac;
-import org.bouncycastle.crypto.params.IESParameters;
-import org.bouncycastle.jce.interfaces.ECPrivateKey;
-import org.bouncycastle.jce.interfaces.IESKey;
-import org.bouncycastle.jce.spec.IESParameterSpec;
-
-public class JCEIESCipher //extends WrapCipherSpi
-{
-    private IESEngine               cipher;
-    private int                     state = -1;
-    private ByteArrayOutputStream   buffer = new ByteArrayOutputStream();
-    private AlgorithmParameters     engineParam = null;
-    private IESParameterSpec        engineParams = null;
-
-    //
-    // specs we can handle.
-    //
-    private Class[]                 availableSpecs =
-                                    {
-                                        IESParameterSpec.class
-                                    };
-
-    public JCEIESCipher(
-        IESEngine   engine)
-    {
-        cipher = engine;
-    }
-
-    protected int engineGetBlockSize() 
-    {
-        return 0;
-    }
-
-    protected byte[] engineGetIV() 
-    {
-        return null;
-    }
-
-    protected int engineGetKeySize(
-        Key     key) 
-    {
-        IESKey   ieKey = (IESKey)key;
-
-        if (ieKey.getPrivate() instanceof DHPrivateKey)
-        {
-            DHPrivateKey   k = (DHPrivateKey)ieKey.getPrivate();
-
-            return k.getX().bitLength();
-        }
-        else if (ieKey.getPrivate() instanceof ECPrivateKey)
-        {
-            ECPrivateKey   k = (ECPrivateKey)ieKey.getPrivate();
-
-            return k.getD().bitLength();
-        }
-
-        throw new IllegalArgumentException("not an IE key!");
-    }
-
-    protected int engineGetOutputSize(
-        int     inputLen) 
-    {
-        if (state == Cipher.ENCRYPT_MODE || state == Cipher.WRAP_MODE)
-        {
-            return buffer.size() + inputLen + 20; /* SHA1 MAC size */
-        }
-        else if (state == Cipher.DECRYPT_MODE || state == Cipher.UNWRAP_MODE)
-        {
-            return buffer.size() + inputLen - 20;
-        }
-        else
-        {
-            throw new IllegalStateException("cipher not initialised");
-        }
-    }
-
-    protected AlgorithmParameters engineGetParameters() 
-    {
-        if (engineParam == null)
-        {
-            if (engineParams != null)
-            {
-                String  name = "IES";
-
-                try
-                {
-                    engineParam = AlgorithmParameters.getInstance(name, BouncyCastleProvider.PROVIDER_NAME);
-                    engineParam.init(engineParams);
-                }
-                catch (Exception e)
-                {
-                    throw new RuntimeException(e.toString());
-                }
-            }
-        }
-
-        return engineParam;
-    }
-
-    protected void engineSetMode(
-        String  mode) 
-    {
-        throw new IllegalArgumentException("can't support mode " + mode);
-    }
-
-    protected void engineSetPadding(
-        String  padding) 
-        throws NoSuchPaddingException
-    {
-        throw new NoSuchPaddingException(padding + " unavailable with RSA.");
-    }
-
-    public void engineInit(
-        int                     opmode,
-        Key                     key,
-        AlgorithmParameterSpec  params,
-        SecureRandom            random) 
-    throws InvalidKeyException, InvalidAlgorithmParameterException
-    {
-        if (!(key instanceof IESKey))
-        {
-            throw new InvalidKeyException("must be passed IE key");
-        }
-
-        if (params == null && (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE))
-        {
-            //
-            // if nothing is specified we set up for a 128 bit mac, with
-            // 128 bit derivation vectors.
-            //
-            byte[]  d = new byte[16];
-            byte[]  e = new byte[16];
-
-            if (random == null)
-            {
-                random = new SecureRandom();
-            }
-
-            random.nextBytes(d);
-            random.nextBytes(e);
-
-            params = new IESParameterSpec(d, e, 128);
-        }
-        else if (!(params instanceof IESParameterSpec))
-        {
-            throw new InvalidAlgorithmParameterException("must be passed IES parameters");
-        }
-
-        IESKey       ieKey = (IESKey)key;
-
-        CipherParameters pubKey;
-        CipherParameters privKey;
-
-        if (ieKey.getPublic() instanceof JCEECPublicKey)
-        {
-            pubKey = ECUtil.generatePublicKeyParameter(ieKey.getPublic());
-            privKey = ECUtil.generatePrivateKeyParameter(ieKey.getPrivate());
-        }
-        else
-        {
-            pubKey = DHUtil.generatePublicKeyParameter(ieKey.getPublic());
-            privKey = DHUtil.generatePrivateKeyParameter(ieKey.getPrivate());
-        }
-
-        this.engineParams = (IESParameterSpec)params;
-
-        IESParameters       p = new IESParameters(engineParams.getDerivationV(), engineParams.getEncodingV(), engineParams.getMacKeySize());
-
-        this.state = opmode;
-
-        buffer.reset();
-
-        switch (opmode)
-        {
-        case Cipher.ENCRYPT_MODE:
-		case Cipher.WRAP_MODE:
-            cipher.init(true, privKey, pubKey, p);
-            break;
-        case Cipher.DECRYPT_MODE:
-		case Cipher.UNWRAP_MODE:
-            cipher.init(false, privKey, pubKey, p);
-            break;
-        default:
-            System.out.println("eeek!");
-        }
-    }
-
-    protected void engineInit(
-        int                 opmode,
-        Key                 key,
-        AlgorithmParameters params,
-        SecureRandom        random) 
-    throws InvalidKeyException, InvalidAlgorithmParameterException
-    {
-        AlgorithmParameterSpec  paramSpec = null;
-
-        if (params != null)
-        {
-            for (int i = 0; i != availableSpecs.length; i++)
-            {
-                try
-                {
-                    paramSpec = params.getParameterSpec(availableSpecs[i]);
-                    break;
-                }
-                catch (Exception e)
-                {
-                    continue;
-                }
-            }
-
-            if (paramSpec == null)
-            {
-                throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString());
-            }
-        }
-
-        engineParam = params;
-        engineInit(opmode, key, paramSpec, random);
-    }
-
-    protected void engineInit(
-        int                 opmode,
-        Key                 key,
-        SecureRandom        random) 
-    throws InvalidKeyException
-    {
-        if (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE)
-        {
-            try
-            {
-                engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
-                return;
-            }
-            catch (InvalidAlgorithmParameterException e)
-            {
-                // fall through...
-            }
-        }
-
-        throw new IllegalArgumentException("can't handle null parameter spec in IES");
-    }
-
-    public byte[] engineUpdate(
-        byte[]  input,
-        int     inputOffset,
-        int     inputLen) 
-    {
-        buffer.write(input, inputOffset, inputLen);
-        return null;
-    }
-
-    public int engineUpdate(
-        byte[]  input,
-        int     inputOffset,
-        int     inputLen,
-        byte[]  output,
-        int     outputOffset) 
-    {
-        buffer.write(input, inputOffset, inputLen);
-        return 0;
-    }
-
-    public byte[] engineDoFinal(
-        byte[]  input,
-        int     inputOffset,
-        int     inputLen) 
-        throws IllegalBlockSizeException, BadPaddingException
-    {
-        if (inputLen != 0)
-        {
-            buffer.write(input, inputOffset, inputLen);
-        }
-
-        try
-        {
-            byte[]  buf = buffer.toByteArray();
-
-            buffer.reset();
-
-            return cipher.processBlock(buf, 0, buf.length);
-        }
-        catch (InvalidCipherTextException e)
-        {
-            throw new BadPaddingException(e.getMessage());
-        }
-    }
-
-    public int engineDoFinal(
-        byte[]  input,
-        int     inputOffset,
-        int     inputLen,
-        byte[]  output,
-        int     outputOffset) 
-        throws IllegalBlockSizeException, BadPaddingException
-    {
-        if (inputLen != 0)
-        {
-            buffer.write(input, inputOffset, inputLen);
-        }
-
-        try
-        {
-            byte[]  buf = buffer.toByteArray();
-
-            buffer.reset();
-
-            buf = cipher.processBlock(buf, 0, buf.length);
-
-            System.arraycopy(buf, 0, output, outputOffset, buf.length);
-
-            return buf.length;
-        }
-        catch (InvalidCipherTextException e)
-        {
-            throw new BadPaddingException(e.getMessage());
-        }
-    }
-
-    /**
-     * classes that inherit from us.
-     */
-    static public class ECIES
-        extends JCEIESCipher
-    {
-        public ECIES()
-        {
-            super(new IESEngine(
-                   new ECDHBasicAgreement(),
-                   new KDF2BytesGenerator(new SHA1Digest()),
-                   new HMac(new SHA1Digest())));
-        }
-    }
-
-    /*
-    static public class IES
-        extends JCEIESCipher
-    {
-        public IES()
-        {
-            super(new IESEngine(
-                   new DHBasicAgreement(),
-                   new KDF2BytesGenerator(new SHA1Digest()),
-                   new HMac(new SHA1Digest())));
-        }
-    }
-    */
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JCERSAPublicKey.java b/azureus2/src/org/bouncycastle/jce/provider/JCERSAPublicKey.java
deleted file mode 100644
index 79cf8ab..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JCERSAPublicKey.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.RSAPublicKeySpec;
-
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-
-public class JCERSAPublicKey
-    implements RSAPublicKey
-{
-    private BigInteger modulus;
-    private BigInteger publicExponent;
-
-    JCERSAPublicKey(
-        RSAKeyParameters key)
-    {
-        this.modulus = key.getModulus();
-        this.publicExponent = key.getExponent();
-    }
-
-    JCERSAPublicKey(
-        RSAPublicKeySpec spec)
-    {
-        this.modulus = spec.getModulus();
-        this.publicExponent = spec.getPublicExponent();
-    }
-
-    JCERSAPublicKey(
-        RSAPublicKey key)
-    {
-        this.modulus = key.getModulus();
-        this.publicExponent = key.getPublicExponent();
-    }
-
-    JCERSAPublicKey(
-        SubjectPublicKeyInfo    info)
-    {
-        try
-        {
-            RSAPublicKeyStructure   pubKey = new RSAPublicKeyStructure((ASN1Sequence)info.getPublicKey());
-
-            this.modulus = pubKey.getModulus();
-            this.publicExponent = pubKey.getPublicExponent();
-		}
-        catch (IOException e)
-        {
-			throw new IllegalArgumentException("invalid info structure in RSA public key");
-        }
-    }
-
-    /**
-     * return the modulus.
-     *
-     * @return the modulus.
-     */
-    public BigInteger getModulus()
-    {
-        return modulus;
-    }
-
-    /**
-     * return the public exponent.
-     *
-     * @return the public exponent.
-     */
-    public BigInteger getPublicExponent()
-    {
-        return publicExponent;
-    }
-
-    public String getAlgorithm()
-    {
-        return "RSA";
-    }
-
-    public String getFormat()
-    {
-        return "X.509";
-    }
-
-    public byte[] getEncoded()
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-        SubjectPublicKeyInfo    info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, new DERNull()), new RSAPublicKeyStructure(getModulus(), getPublicExponent()).getDERObject());
-
-        try
-        {
-            dOut.writeObject(info);
-            dOut.close();
-        }
-        catch (IOException e)
-        {
-            throw new RuntimeException("Error encoding RSA public key");
-        }
-
-        return bOut.toByteArray();
-
-    }
-
-	public boolean equals(Object o)
-	{
-		if ( !(o instanceof RSAPublicKey) )
-		{
-			return false;
-		}
-
-		if ( o == this )
-		{
-			return true;
-		}
-
-		RSAPublicKey key = (RSAPublicKey)o;
-
-		return getModulus().equals(key.getModulus())
-			&& getPublicExponent().equals(key.getPublicExponent());
-	}
-
-    public String toString()
-    {
-        StringBuffer    buf = new StringBuffer();
-        String          nl = System.getProperty("line.separator");
-
-        buf.append("RSA Public Key" + nl);
-        buf.append("            modulus: " + this.getModulus().toString(16) + nl);
-        buf.append("    public exponent: " + this.getPublicExponent().toString(16) + nl);
-
-        return buf.toString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JDKAlgorithmParameterGenerator.java b/azureus2/src/org/bouncycastle/jce/provider/JDKAlgorithmParameterGenerator.java
deleted file mode 100644
index 403d824..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JDKAlgorithmParameterGenerator.java
+++ /dev/null
@@ -1,385 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.AlgorithmParameterGeneratorSpi;
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.SecureRandom;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.DSAParameterSpec;
-
-import javax.crypto.spec.DHGenParameterSpec;
-import javax.crypto.spec.DHParameterSpec;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.RC2ParameterSpec;
-
-import org.bouncycastle.crypto.generators.DHParametersGenerator;
-import org.bouncycastle.crypto.generators.DSAParametersGenerator;
-import org.bouncycastle.crypto.generators.ElGamalParametersGenerator;
-import org.bouncycastle.crypto.params.DHParameters;
-import org.bouncycastle.crypto.params.DSAParameters;
-import org.bouncycastle.crypto.params.ElGamalParameters;
-import org.bouncycastle.jce.spec.ElGamalParameterSpec;
-
-public abstract class JDKAlgorithmParameterGenerator
-    extends AlgorithmParameterGeneratorSpi
-{
-    protected SecureRandom  random;
-    protected int           strength = 1024;
-
-    protected void engineInit(
-        int             strength,
-        SecureRandom    random)
-    {
-        this.strength = strength;
-        this.random = random;
-    }
-
-    public static class DH
-        extends JDKAlgorithmParameterGenerator
-    {
-        private int l = 0;
-
-        protected void engineInit(
-            AlgorithmParameterSpec  genParamSpec,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            if (!(genParamSpec instanceof DHGenParameterSpec))
-            {
-                throw new InvalidAlgorithmParameterException("DH parameter generator requires a DHGenParameterSpec for initialisation");
-            }
-            DHGenParameterSpec  spec = (DHGenParameterSpec)genParamSpec;
-
-            this.strength = spec.getPrimeSize();
-            this.l = spec.getExponentSize();
-            this.random = random;
-        }
-
-        protected AlgorithmParameters engineGenerateParameters()
-        {
-            DHParametersGenerator        pGen = new DHParametersGenerator();
-
-			if ( random != null )
-			{
-				pGen.init(strength, 20, random);
-			}
-			else
-			{
-				pGen.init(strength, 20, new SecureRandom());
-			}
-
-            DHParameters                p = pGen.generateParameters();
-
-            AlgorithmParameters params;
-
-            try
-            {
-                params = AlgorithmParameters.getInstance("DH", BouncyCastleProvider.PROVIDER_NAME);
-                params.init(new DHParameterSpec(p.getP(), p.getG(), l));
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException(e.getMessage());
-            }
-
-            return params;
-        }
-    }
-
-    public static class DSA
-        extends JDKAlgorithmParameterGenerator
-    {
-        protected void engineInit(
-            AlgorithmParameterSpec  genParamSpec,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for DSA parameter generation.");
-        }
-
-        protected AlgorithmParameters engineGenerateParameters()
-        {
-            DSAParametersGenerator pGen = new DSAParametersGenerator();
-
-			if ( random != null )
-			{
-				pGen.init(strength, 20, random);
-			}
-			else
-			{
-				pGen.init(strength, 20, new SecureRandom());
-			}
-
-            DSAParameters p = pGen.generateParameters();
-
-            AlgorithmParameters params;
-
-            try
-            {
-                params = AlgorithmParameters.getInstance("DSA", BouncyCastleProvider.PROVIDER_NAME);
-                params.init(new DSAParameterSpec(p.getP(), p.getQ(), p.getG()));
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException(e.getMessage());
-            }
-
-            return params;
-        }
-    }
-
-    public static class ElGamal
-        extends JDKAlgorithmParameterGenerator
-    {
-        protected void engineInit(
-            AlgorithmParameterSpec  genParamSpec,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for ElGamal parameter generation.");
-        }
-
-        protected AlgorithmParameters engineGenerateParameters()
-        {
-            ElGamalParametersGenerator pGen = new ElGamalParametersGenerator();
-
-			if ( random != null )
-			{
-				pGen.init(strength, 20, random);
-			}
-			else
-			{
-				pGen.init(strength, 20, new SecureRandom());
-			}
-
-            ElGamalParameters p = pGen.generateParameters();
-
-            AlgorithmParameters params;
-
-            try
-            {
-                params = AlgorithmParameters.getInstance("ElGamal", BouncyCastleProvider.PROVIDER_NAME);
-                params.init(new ElGamalParameterSpec(p.getP(), p.getG()));
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException(e.getMessage());
-            }
-
-            return params;
-        }
-    }
-
-    public static class DES
-        extends JDKAlgorithmParameterGenerator
-    {
-        protected void engineInit(
-            AlgorithmParameterSpec  genParamSpec,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for DES parameter generation.");
-        }
-
-        protected AlgorithmParameters engineGenerateParameters()
-        {
-            byte[]  iv = new byte[8];
-
-			if (random == null)
-			{
-                random = new SecureRandom();
-			}
-
-            random.nextBytes(iv);
-
-            AlgorithmParameters params;
-
-            try
-            {
-                params = AlgorithmParameters.getInstance("DES", BouncyCastleProvider.PROVIDER_NAME);
-                params.init(new IvParameterSpec(iv));
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException(e.getMessage());
-            }
-
-            return params;
-        }
-    }
-
-    public static class RC2
-        extends JDKAlgorithmParameterGenerator
-    {
-        RC2ParameterSpec    spec = null;
-
-        protected void engineInit(
-            AlgorithmParameterSpec  genParamSpec,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            if (genParamSpec instanceof RC2ParameterSpec)
-            {
-                spec = (RC2ParameterSpec)genParamSpec;
-                return;
-            }
-
-            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for RC2 parameter generation.");
-        }
-
-        protected AlgorithmParameters engineGenerateParameters()
-        {
-            AlgorithmParameters params;
-
-            if (spec == null)
-            {
-                byte[]  iv = new byte[8];
-
-                if (random == null)
-                {
-                    random = new SecureRandom();
-                }
-
-                random.nextBytes(iv);
-
-                try
-                {
-                    params = AlgorithmParameters.getInstance("RC2", BouncyCastleProvider.PROVIDER_NAME);
-                    params.init(new IvParameterSpec(iv));
-                }
-                catch (Exception e)
-                {
-                    throw new RuntimeException(e.getMessage());
-                }
-            }
-            else
-            {
-                try
-                {
-                    params = AlgorithmParameters.getInstance("RC2", BouncyCastleProvider.PROVIDER_NAME);
-                    params.init(spec);
-                }
-                catch (Exception e)
-                {
-                    throw new RuntimeException(e.getMessage());
-                }
-            }
-
-            return params;
-        }
-    }
-
-    public static class AES
-        extends JDKAlgorithmParameterGenerator
-    {
-        protected void engineInit(
-            AlgorithmParameterSpec  genParamSpec,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for AES parameter generation.");
-        }
-
-        protected AlgorithmParameters engineGenerateParameters()
-        {
-            byte[]  iv = new byte[16];
-
-			if (random == null)
-			{
-                random = new SecureRandom();
-			}
-
-            random.nextBytes(iv);
-
-            AlgorithmParameters params;
-
-            try
-            {
-                params = AlgorithmParameters.getInstance("AES", BouncyCastleProvider.PROVIDER_NAME);
-                params.init(new IvParameterSpec(iv));
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException(e.getMessage());
-            }
-
-            return params;
-        }
-    }
-
-    public static class IDEA
-        extends JDKAlgorithmParameterGenerator
-    {
-        protected void engineInit(
-            AlgorithmParameterSpec  genParamSpec,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for IDEA parameter generation.");
-        }
-
-        protected AlgorithmParameters engineGenerateParameters()
-        {
-            byte[]  iv = new byte[8];
-
-			if (random == null)
-			{
-                random = new SecureRandom();
-			}
-
-            random.nextBytes(iv);
-
-            AlgorithmParameters params;
-
-            try
-            {
-                params = AlgorithmParameters.getInstance("IDEA", BouncyCastleProvider.PROVIDER_NAME);
-                params.init(new IvParameterSpec(iv));
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException(e.getMessage());
-            }
-
-            return params;
-        }
-    }
-
-    public static class CAST5
-        extends JDKAlgorithmParameterGenerator
-    {
-        protected void engineInit(
-            AlgorithmParameterSpec  genParamSpec,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            throw new InvalidAlgorithmParameterException("No supported AlgorithmParameterSpec for CAST5 parameter generation.");
-        }
-
-        protected AlgorithmParameters engineGenerateParameters()
-        {
-            byte[]  iv = new byte[8];
-
-			if (random == null)
-			{
-                random = new SecureRandom();
-			}
-
-            random.nextBytes(iv);
-
-            AlgorithmParameters params;
-
-            try
-            {
-                params = AlgorithmParameters.getInstance("CAST5", BouncyCastleProvider.PROVIDER_NAME);
-                params.init(new IvParameterSpec(iv));
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException(e.getMessage());
-            }
-
-            return params;
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JDKDSASigner.java b/azureus2/src/org/bouncycastle/jce/provider/JDKDSASigner.java
deleted file mode 100644
index a27ceb4..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JDKDSASigner.java
+++ /dev/null
@@ -1,269 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.interfaces.DSAKey;
-import java.security.spec.AlgorithmParameterSpec;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInputStream;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.DSA;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-//import org.bouncycastle.crypto.signers.DSASigner;
-import org.bouncycastle.crypto.signers.ECDSASigner;
-import org.bouncycastle.jce.interfaces.ECKey;
-
-public class JDKDSASigner
-    extends Signature implements PKCSObjectIdentifiers, X509ObjectIdentifiers
-{
-    private Digest                  digest;
-    private DSA                     signer;
-    private SecureRandom            random;
-
-    protected JDKDSASigner(
-        String                  name,
-        Digest                  digest,
-        DSA                     signer)
-    {
-        super(name);
-
-        this.digest = digest;
-        this.signer = signer;
-    }
-
-    protected void engineInitVerify(
-        PublicKey   publicKey)
-        throws InvalidKeyException
-    {
-        CipherParameters    param = null;
-
-        if (publicKey instanceof ECKey)
-        {
-            param = ECUtil.generatePublicKeyParameter(publicKey);
-        }
-        else if (publicKey instanceof DSAKey)
-        {
-            param = DSAUtil.generatePublicKeyParameter(publicKey);
-        }
-        else
-        {
-            try
-            {
-            	/*
-                byte[]  bytes = publicKey.getEncoded();
-
-                publicKey = JDKKeyFactory.createPublicKeyFromDERStream(
-                                        new ByteArrayInputStream(bytes));
-
-                if (publicKey instanceof ECKey)
-                {
-                    param = ECUtil.generatePublicKeyParameter(publicKey);
-                }
-                else if (publicKey instanceof DSAKey)
-                {
-                    param = DSAUtil.generatePublicKeyParameter(publicKey);
-                }
-                else
-                {
-                */
-                    throw new InvalidKeyException("can't recognise key type in DSA based signer");
-                //}
-            }
-            catch (Exception e)
-            {
-                throw new InvalidKeyException("can't recognise key type in DSA based signer");
-            }
-        }
-
-        digest.reset();
-        signer.init(false, param);
-    }
-
-    protected void engineInitSign(
-        PrivateKey      privateKey,
-        SecureRandom    random)
-        throws InvalidKeyException
-    {
-        this.random = random;
-        engineInitSign(privateKey);
-    }
-
-    protected void engineInitSign(
-        PrivateKey  privateKey)
-        throws InvalidKeyException
-    {
-        CipherParameters    param = null;
-
-        if (privateKey instanceof ECKey)
-        {
-            param = ECUtil.generatePrivateKeyParameter(privateKey);
-        }
-        else
-        {
-            param = DSAUtil.generatePrivateKeyParameter(privateKey);
-        }
-
-        digest.reset();
-
-        if (random != null)
-        {
-            signer.init(true, new ParametersWithRandom(param, random));
-        }
-        else
-        {
-            signer.init(true, param);
-        }
-    }
-
-    protected void engineUpdate(
-        byte    b)
-        throws SignatureException
-    {
-        digest.update(b);
-    }
-
-    protected void engineUpdate(
-        byte[]  b,
-        int     off,
-        int     len) 
-        throws SignatureException
-    {
-        digest.update(b, off, len);
-    }
-
-    protected byte[] engineSign()
-        throws SignatureException
-    {
-        byte[]  hash = new byte[digest.getDigestSize()];
-
-        digest.doFinal(hash, 0);
-
-        try
-        {
-            BigInteger[]    sig = signer.generateSignature(hash);
-
-            return derEncode(sig[0], sig[1]);
-        }
-        catch (Exception e)
-        {
-            throw new SignatureException(e.toString());
-        }
-    }
-
-    protected boolean engineVerify(
-        byte[]  sigBytes) 
-        throws SignatureException
-    {
-        byte[]  hash = new byte[digest.getDigestSize()];
-
-        digest.doFinal(hash, 0);
-
-        BigInteger[]    sig;
-
-        try
-        {
-            sig = derDecode(sigBytes);
-        }
-        catch (Exception e)
-        {
-            throw new SignatureException("error decoding signature bytes.");
-        }
-
-        return signer.verifySignature(hash, sig[0], sig[1]);
-    }
-
-    protected void engineSetParameter(
-        AlgorithmParameterSpec params)
-    {
-        throw new UnsupportedOperationException("engineSetParameter unsupported");
-    }
-
-    /**
-     * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
-     */
-    protected void engineSetParameter(
-        String  param,
-        Object  value)
-    {
-        throw new UnsupportedOperationException("engineSetParameter unsupported");
-    }
-
-    /**
-     * @deprecated
-     */
-    protected Object engineGetParameter(
-        String      param)
-    {
-        throw new UnsupportedOperationException("engineSetParameter unsupported");
-    }
-
-    private byte[] derEncode(
-        BigInteger  r,
-        BigInteger  s)
-        throws IOException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-        ASN1EncodableVector     v = new ASN1EncodableVector();
-
-        v.add(new DERInteger(r));
-        v.add(new DERInteger(s));
-
-        dOut.writeObject(new DERSequence(v));
-
-        return bOut.toByteArray();
-    }
-
-    private BigInteger[] derDecode(
-        byte[]  encoding)
-        throws IOException
-    {
-        ByteArrayInputStream    bIn = new ByteArrayInputStream(encoding);
-        DERInputStream          dIn = new DERInputStream(bIn);
-        ASN1Sequence            s = (ASN1Sequence)dIn.readObject();
-
-        BigInteger[]            sig = new BigInteger[2];
-
-        sig[0] = ((DERInteger)s.getObjectAt(0)).getValue();
-        sig[1] = ((DERInteger)s.getObjectAt(1)).getValue();
-
-        return sig;
-    }
-
-    /*
-    static public class stdDSA
-        extends JDKDSASigner
-    {
-        public stdDSA()
-        {
-            super("SHA1withDSA", new SHA1Digest(), new DSASigner());
-        }
-    }
-	*/
-    
-    static public class ecDSA
-        extends JDKDSASigner
-    {
-        public ecDSA()
-        {
-            super("SHA1withECDSA", new SHA1Digest(), new ECDSASigner());
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JDKDigestSignature.java b/azureus2/src/org/bouncycastle/jce/provider/JDKDigestSignature.java
deleted file mode 100644
index da0e9ee..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JDKDigestSignature.java
+++ /dev/null
@@ -1,271 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.InvalidKeyException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.AlgorithmParameterSpec;
-
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInputStream;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.DigestInfo;
-import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
-import org.bouncycastle.crypto.AsymmetricBlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.MD2Digest;
-import org.bouncycastle.crypto.digests.MD5Digest;
-import org.bouncycastle.crypto.digests.RIPEMD128Digest;
-import org.bouncycastle.crypto.digests.RIPEMD160Digest;
-import org.bouncycastle.crypto.digests.RIPEMD256Digest;
-import org.bouncycastle.crypto.digests.SHA1Digest;
-import org.bouncycastle.crypto.encodings.PKCS1Encoding;
-import org.bouncycastle.crypto.engines.RSAEngine;
-
-public class JDKDigestSignature
-    extends Signature implements PKCSObjectIdentifiers, X509ObjectIdentifiers
-{
-    private Digest                  digest;
-    private AsymmetricBlockCipher   cipher;
-    private AlgorithmIdentifier     algId;
-
-    protected JDKDigestSignature(
-        String                  name,
-        DERObjectIdentifier     objId,
-        Digest                  digest,
-        AsymmetricBlockCipher   cipher)
-    {
-        super(name);
-
-        this.digest = digest;
-        this.cipher = cipher;
-        this.algId = new AlgorithmIdentifier(objId, null);
-    }
-
-    protected void engineInitVerify(
-        PublicKey   publicKey)
-        throws InvalidKeyException
-    {
-		if ( !(publicKey instanceof RSAPublicKey) )
-		{
-			throw new InvalidKeyException("Supplied key is not a RSAPublicKey instance");
-		}
-
-        CipherParameters    param = RSAUtil.generatePublicKeyParameter((RSAPublicKey)publicKey);
-
-        digest.reset();
-        cipher.init(false, param);
-    }
-
-    protected void engineInitSign(
-        PrivateKey  privateKey)
-        throws InvalidKeyException
-    {
-		if ( !(privateKey instanceof RSAPrivateKey) )
-		{
-			throw new InvalidKeyException("Supplied key is not a RSAPrivateKey instance");
-		}
-
-        CipherParameters    param = RSAUtil.generatePrivateKeyParameter((RSAPrivateKey)privateKey);
-
-        digest.reset();
-
-        cipher.init(true, param);
-    }
-
-    protected void engineUpdate(
-        byte    b)
-        throws SignatureException
-    {
-        digest.update(b);
-    }
-
-    protected void engineUpdate(
-        byte[]  b,
-        int     off,
-        int     len) 
-        throws SignatureException
-    {
-        digest.update(b, off, len);
-    }
-
-    protected byte[] engineSign()
-        throws SignatureException
-    {
-        byte[]  hash = new byte[digest.getDigestSize()];
-
-        digest.doFinal(hash, 0);
-
-        try
-        {
-            byte[]  bytes = derEncode(hash);
-
-            return cipher.processBlock(bytes, 0, bytes.length);
-        }
-        catch (ArrayIndexOutOfBoundsException e)
-        {
-            throw new SignatureException("key too small for signature type");
-        }
-        catch (Exception e)
-        {
-            throw new SignatureException(e.toString());
-        }
-    }
-
-    protected boolean engineVerify(
-        byte[]  sigBytes) 
-        throws SignatureException
-    {
-        byte[]  hash = new byte[digest.getDigestSize()];
-
-        digest.doFinal(hash, 0);
-
-        DigestInfo  digInfo;
-        byte[]      sig;
-
-        try
-        {
-            sig = cipher.processBlock(sigBytes, 0, sigBytes.length);
-            digInfo = derDecode(sig);
-        }
-        catch (Exception e)
-        {
-            return false;
-        }
-
-        if (!digInfo.getAlgorithmId().equals(algId))
-        {
-            return false;
-        }
-
-        byte[]  sigHash = digInfo.getDigest();
-
-        if (hash.length != sigHash.length)
-        {
-            return false;
-        }
-
-        for (int i = 0; i < hash.length; i++)
-        {
-            if (sigHash[i] != hash[i])
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    protected void engineSetParameter(
-        AlgorithmParameterSpec params)
-    {
-        throw new UnsupportedOperationException("engineSetParameter unsupported");
-    }
-
-    /**
-     * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
-     */
-    protected void engineSetParameter(
-        String  param,
-        Object  value)
-    {
-        throw new UnsupportedOperationException("engineSetParameter unsupported");
-    }
-
-    /**
-     * @deprecated
-     */
-    protected Object engineGetParameter(
-        String      param)
-    {
-        throw new UnsupportedOperationException("engineSetParameter unsupported");
-    }
-
-    private byte[] derEncode(
-        byte[]  hash)
-        throws IOException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-        DigestInfo              dInfo = new DigestInfo(algId, hash);
-
-        dOut.writeObject(dInfo);
-
-        return bOut.toByteArray();
-    }
-
-    private DigestInfo derDecode(
-        byte[]  encoding)
-        throws IOException
-    {
-        ByteArrayInputStream    bIn = new ByteArrayInputStream(encoding);
-        DERInputStream          dIn = new DERInputStream(bIn);
-
-        return new DigestInfo((ASN1Sequence)dIn.readObject());
-    }
-
-    static public class SHA1WithRSAEncryption
-        extends JDKDigestSignature
-    {
-        public SHA1WithRSAEncryption()
-        {
-            super("SHA1withRSA", id_SHA1, new SHA1Digest(), new PKCS1Encoding(new RSAEngine()));
-        }
-    }
-
-    static public class MD2WithRSAEncryption
-        extends JDKDigestSignature
-    {
-        public MD2WithRSAEncryption()
-        {
-            super("MD2withRSA", md2, new MD2Digest(), new PKCS1Encoding(new RSAEngine()));
-        }
-    }
-
-    static public class MD5WithRSAEncryption
-        extends JDKDigestSignature
-    {
-        public MD5WithRSAEncryption()
-        {
-            super("MD5withRSA", md5, new MD5Digest(), new PKCS1Encoding(new RSAEngine()));
-        }
-    }
-
-    static public class RIPEMD160WithRSAEncryption
-        extends JDKDigestSignature
-    {
-        public RIPEMD160WithRSAEncryption()
-        {
-            super("RIPEMD160withRSA", TeleTrusTObjectIdentifiers.ripemd160, new RIPEMD160Digest(), new PKCS1Encoding(new RSAEngine()));
-        }
-    }
-    
-	static public class RIPEMD128WithRSAEncryption
-		extends JDKDigestSignature
-	{
-		public RIPEMD128WithRSAEncryption()
-		{
-			super("RIPEMD128withRSA", TeleTrusTObjectIdentifiers.ripemd128, new RIPEMD128Digest(), new PKCS1Encoding(new RSAEngine()));
-		}
-	}
-	
-	static public class RIPEMD256WithRSAEncryption
-		extends JDKDigestSignature
-	{
-		public RIPEMD256WithRSAEncryption()
-		{
-			super("RIPEMD256withRSA", TeleTrusTObjectIdentifiers.ripemd256, new RIPEMD256Digest(), new PKCS1Encoding(new RSAEngine()));
-		}
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JDKKeyFactory.java b/azureus2/src/org/bouncycastle/jce/provider/JDKKeyFactory.java
deleted file mode 100644
index 3f3a905..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JDKKeyFactory.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Created on 08-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 org.bouncycastle.jce.provider;
-
-/**
- * @author parg
- *
- */
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.KeyFactorySpi;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.DSAPublicKey;
-import java.security.interfaces.RSAPrivateCrtKey;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.RSAPrivateCrtKeySpec;
-import java.security.spec.RSAPrivateKeySpec;
-import java.security.spec.RSAPublicKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-
-import javax.crypto.interfaces.DHPrivateKey;
-import javax.crypto.interfaces.DHPublicKey;
-
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInputStream;
-import org.bouncycastle.asn1.x509.*;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.jce.interfaces.ElGamalPrivateKey;
-import org.bouncycastle.jce.interfaces.ElGamalPublicKey;
-import org.bouncycastle.jce.spec.ECPrivateKeySpec;
-import org.bouncycastle.jce.spec.ECPublicKeySpec;
-import org.gudy.azureus2.core3.util.Debug;
-
-public abstract class 
-JDKKeyFactory 
-	extends KeyFactorySpi
-{
-    protected KeySpec engineGetKeySpec(
-            Key    key,
-            Class    spec)
-        throws InvalidKeySpecException
-        {
-           if (spec.isAssignableFrom(PKCS8EncodedKeySpec.class) && key.getFormat().equals("PKCS#8"))
-           {
-                   return new PKCS8EncodedKeySpec(key.getEncoded());
-           }
-           else if (spec.isAssignableFrom(X509EncodedKeySpec.class) && key.getFormat().equals("X.509"))
-           {
-                   return new X509EncodedKeySpec(key.getEncoded());
-           }
-           else if (spec.isAssignableFrom(RSAPublicKeySpec.class) && key instanceof RSAPublicKey)
-           {
-                RSAPublicKey    k = (RSAPublicKey)key;
-
-                return new RSAPublicKeySpec(k.getModulus(), k.getPublicExponent());
-           }
-           else if (spec.isAssignableFrom(RSAPrivateKeySpec.class) && key instanceof RSAPrivateKey)
-           {
-                RSAPrivateKey    k = (RSAPrivateKey)key;
-
-                return new RSAPrivateKeySpec(k.getModulus(), k.getPrivateExponent());
-           }
-           else if (spec.isAssignableFrom(RSAPrivateCrtKeySpec.class) && key instanceof RSAPrivateCrtKey)
-           {
-                RSAPrivateCrtKey    k = (RSAPrivateCrtKey)key;
-
-                return new RSAPrivateCrtKeySpec(
-                                k.getModulus(), k.getPublicExponent(),
-                                k.getPrivateExponent(),
-                                k.getPrimeP(), k.getPrimeQ(),
-                                k.getPrimeExponentP(), k.getPrimeExponentQ(),
-                                k.getCrtCoefficient());
-           }
-
-
-            throw new RuntimeException("not implemented yet " + key + " " + spec);
-        }
-
-        protected Key engineTranslateKey(
-            Key    key)
-            throws InvalidKeyException
-        {
-            if (key instanceof RSAPublicKey)
-            {
-                return new JCERSAPublicKey((RSAPublicKey)key);
-            }
-            else if (key instanceof RSAPrivateCrtKey)
-            {
-                //return new JCERSAPrivateCrtKey((RSAPrivateCrtKey)key);
-            }
-            else if (key instanceof RSAPrivateKey)
-            {
-                //return new JCERSAPrivateKey((RSAPrivateKey)key);
-            }
-            else if (key instanceof DHPublicKey)
-            {
-                //return new JCEDHPublicKey((DHPublicKey)key);
-            }
-            else if (key instanceof DHPrivateKey)
-            {
-                //return new JCEDHPrivateKey((DHPrivateKey)key);
-            }
-            else if (key instanceof DSAPublicKey)
-            {
-                //return new JDKDSAPublicKey((DSAPublicKey)key);
-            }
-            else if (key instanceof DSAPrivateKey)
-            {
-                //return new JDKDSAPrivateKey((DSAPrivateKey)key);
-            }
-            else if (key instanceof ElGamalPublicKey)
-            {
-                //return new JCEElGamalPublicKey((ElGamalPublicKey)key);
-            }
-            else if (key instanceof ElGamalPrivateKey)
-            {
-                //return new JCEElGamalPrivateKey((ElGamalPrivateKey)key);
-            }
-
-            throw new InvalidKeyException("key type unknown");
-        }
-	
-	
-	   static PublicKey createPublicKeyFromDERStream(
-		        InputStream         in)
-		        throws IOException
-		    {
-		        return createPublicKeyFromPublicKeyInfo(
-		                new SubjectPublicKeyInfo((ASN1Sequence)(new DERInputStream(in).readObject())));
-		    }
-	   
-    static PublicKey createPublicKeyFromPublicKeyInfo(
-        SubjectPublicKeyInfo         info)
-    {
-        AlgorithmIdentifier     algId = info.getAlgorithmId();
-        
-        if (algId.getObjectId().equals(PKCSObjectIdentifiers.rsaEncryption)
-        	|| algId.getObjectId().equals(X509ObjectIdentifiers.id_ea_rsa))
-        {
-              return new JCERSAPublicKey(info);
-        }
-        else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey))
-        {
-              return new JCEECPublicKey(info);
-        }
-        else
-        {
-            throw new RuntimeException("algorithm identifier in key not recognised");
-        }
-    }
-    
-    static PrivateKey createPrivateKeyFromDERStream(
-            InputStream         in)
-            throws IOException
-        {
-            return createPrivateKeyFromPrivateKeyInfo(
-                    new PrivateKeyInfo((ASN1Sequence)(new DERInputStream(in).readObject())));
-        }
-
-        /**
-         * create a private key from the given public key info object.
-         */ 
-        static PrivateKey createPrivateKeyFromPrivateKeyInfo(
-            PrivateKeyInfo      info)
-        {
-            AlgorithmIdentifier     algId = info.getAlgorithmId();
-            
-            /*
-            if (algId.getObjectId().equals(PKCSObjectIdentifiers.rsaEncryption))
-            {
-                  return new JCERSAPrivateCrtKey(info);
-            }
-            else if (algId.getObjectId().equals(PKCSObjectIdentifiers.dhKeyAgreement))
-            {
-                  return new JCEDHPrivateKey(info);
-            }
-            else if (algId.getObjectId().equals(OIWObjectIdentifiers.elGamalAlgorithm))
-            {
-                  return new JCEElGamalPrivateKey(info);
-            }
-            else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_dsa))
-            {
-                  return new JDKDSAPrivateKey(info);
-            }
-            else */
-            if (algId.getObjectId().equals(X9ObjectIdentifiers.id_ecPublicKey))
-            {
-                  return new JCEECPrivateKey(info);
-            }
-            else
-            {
-                throw new RuntimeException("algorithm identifier in key not recognised");
-            }
-        }
-    
-    public static class EC
-    extends JDKKeyFactory
-	{
-	    String  algorithm;
-	
-	    public EC()
-	    
-	    	throws NoSuchAlgorithmException
-	    {
-	        this("EC");
-	        
-	        	// PARG - bail if we're constructing an X509 cert for SSL as the BC SSL impl is old and doesn't have recent named curves
-	        	// If we allow this to continue it borks constructing the EC public key and takes the whole SSL process down with
-	        	// utimately a 
-	        	// Caused by: java.io.IOException: subject key, java.lang.NullPointerException
-	        	// at sun.security.x509.X509Key.parse(X509Key.java:157)
-	    		// at sun.security.x509.CertificateX509Key.<init>(CertificateX509Key.java:58)
-	    		// at sun.security.x509.X509CertInfo.parse(X509CertInfo.java:688)
-	    		// at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:152)
-	        
-	        try{
-	        	StackTraceElement[] elements = new Exception().getStackTrace();
-	        
-	        	boolean	ssl 	= false;
-	        	boolean	x509	= false;
-	        	
-	        	for ( StackTraceElement elt: elements ){
-	        	
-	        		String name = elt.getClassName() + "." + elt.getMethodName();
-	        		
-	        		if ( name.contains( "SSLSocketFactory" ) || name.contains( "KeyStore.load" )){
-	        			
-	        			ssl = true;
-	        		}else if ( name.contains( "X509" )){
-	        			
-	        			
-	        			x509 = true;
-	        		}
-	        	}
-	        	
-	        	if( ssl && x509 ){
-	        		
-	        		//Debug.out( "Hacking SSL EC" );
-	        		
-	        		throw( new NoSuchAlgorithmException());
-	        	}
-	        }catch( NoSuchAlgorithmException e ){
-	        	
-	        	throw( e );
-	        	
-	        }catch( Throwable e ){
-	        	
-	        	Debug.out( e );
-	        }
-	    }
-	
-	    public EC(
-	        String  algorithm)
-	    {
-	        this.algorithm = algorithm;
-	    }
-	
-	    protected PrivateKey engineGeneratePrivate(
-	        KeySpec    keySpec)
-	        throws InvalidKeySpecException
-	    {
-	        if (keySpec instanceof PKCS8EncodedKeySpec)
-	        {
-	            try
-	            {
-	                return JDKKeyFactory.createPrivateKeyFromDERStream(
-	                            new ByteArrayInputStream(((PKCS8EncodedKeySpec)keySpec).getEncoded()));
-	            }
-	            catch (Exception e)
-	            {
-	                throw new InvalidKeySpecException(e.toString());
-	            }
-	        }
-	        else if (keySpec instanceof ECPrivateKeySpec)
-	        {
-	            return new JCEECPrivateKey(algorithm, (ECPrivateKeySpec)keySpec);
-	        }
-	
-	        throw new InvalidKeySpecException("Unknown KeySpec type.");
-	    }
-	
-	    protected PublicKey engineGeneratePublic(
-	        KeySpec    keySpec)
-	        throws InvalidKeySpecException
-	    {
-	        if (keySpec instanceof X509EncodedKeySpec)
-	        {
-	            try
-	            {
-	                return JDKKeyFactory.createPublicKeyFromDERStream(
-	                            new ByteArrayInputStream(((X509EncodedKeySpec)keySpec).getEncoded()));
-	            }
-	            catch (Exception e)
-	            {
-	                throw new InvalidKeySpecException(e.toString());
-	            }
-	        }
-	        else if (keySpec instanceof ECPublicKeySpec)
-	        {
-	            return new JCEECPublicKey(algorithm, (ECPublicKeySpec)keySpec);
-	        }
-	
-	        throw new InvalidKeySpecException("Unknown KeySpec type.");
-	    }
-	}
-    
-    public static class ECDSA
-    extends EC
-    {
-	    public ECDSA()
-	    {
-	        super("ECDSA");
-	    }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JDKKeyPairGenerator.java b/azureus2/src/org/bouncycastle/jce/provider/JDKKeyPairGenerator.java
deleted file mode 100644
index 21c55e1..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JDKKeyPairGenerator.java
+++ /dev/null
@@ -1,381 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.SecureRandom;
-import java.security.spec.AlgorithmParameterSpec;
-import java.util.Hashtable;
-
-import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
-import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
-import org.bouncycastle.crypto.params.*;
-import org.bouncycastle.jce.ECNamedCurveTable;
-import org.bouncycastle.jce.spec.ECParameterSpec;
-
-public abstract class JDKKeyPairGenerator
-    extends KeyPairGenerator
-{
-    public JDKKeyPairGenerator(
-        String              algorithmName)
-    {
-        super(algorithmName);
-    }
-
-    public abstract void initialize(int strength, SecureRandom random);
-
-    public abstract KeyPair generateKeyPair();
-
-    /* PARG removed
-    public static class RSA
-        extends JDKKeyPairGenerator
-    {
-		final static BigInteger defaultPublicExponent = BigInteger.valueOf(0x10001);
-		final static int defaultTests = 8;
-
-        RSAKeyGenerationParameters  param;
-        RSAKeyPairGenerator         engine;
-
-        public RSA()
-        {
-            super("RSA");
-
-            engine = new RSAKeyPairGenerator();
-            param = new RSAKeyGenerationParameters(defaultPublicExponent,
-                            new SecureRandom(), 2048, defaultTests);
-            engine.init(param);
-        }
-
-        public void initialize(
-            int             strength,
-            SecureRandom    random)
-        {
-            param = new RSAKeyGenerationParameters(defaultPublicExponent,
-                            random, strength, defaultTests);
-
-            engine.init(param);
-        }
-
-        public void initialize(
-            AlgorithmParameterSpec  params,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            if (!(params instanceof RSAKeyGenParameterSpec))
-            {
-                throw new InvalidAlgorithmParameterException("parameter object not a RSAKeyGenParameterSpec");
-            }
-            RSAKeyGenParameterSpec     rsaParams = (RSAKeyGenParameterSpec)params;
-
-            param = new RSAKeyGenerationParameters(
-                            rsaParams.getPublicExponent(),
-                            random, rsaParams.getKeysize(), defaultTests);
-
-            engine.init(param);
-        }
-
-        public KeyPair generateKeyPair()
-        {
-            AsymmetricCipherKeyPair     pair = engine.generateKeyPair();
-            RSAKeyParameters            pub = (RSAKeyParameters)pair.getPublic();
-            RSAPrivateCrtKeyParameters  priv = (RSAPrivateCrtKeyParameters)pair.getPrivate();
-
-            return new KeyPair(new JCERSAPublicKey(pub),
-                               new JCERSAPrivateCrtKey(priv));
-        }
-    }
-
-    public static class DH
-        extends JDKKeyPairGenerator
-    {
-        DHKeyGenerationParameters  param;
-        DHBasicKeyPairGenerator    engine = new DHBasicKeyPairGenerator();
-        int                        strength = 1024;
-        int                        certainty = 20;
-        SecureRandom               random = new SecureRandom();
-        boolean                    initialised = false;
-
-        public DH()
-        {
-            super("DH");
-        }
-
-        public void initialize(
-            int             strength,
-            SecureRandom    random)
-        {
-            this.strength = strength;
-            this.random = random;
-        }
-
-        public void initialize(
-            AlgorithmParameterSpec  params,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            if (!(params instanceof DHParameterSpec))
-            {
-                throw new InvalidAlgorithmParameterException("parameter object not a DHParameterSpec");
-            }
-            DHParameterSpec     dhParams = (DHParameterSpec)params;
-
-            param = new DHKeyGenerationParameters(random, new DHParameters(dhParams.getP(), dhParams.getG()));
-
-            engine.init(param);
-            initialised = true;
-        }
-
-        public KeyPair generateKeyPair()
-        {
-            if (!initialised)
-            {
-                DHParametersGenerator   pGen = new DHParametersGenerator();
-
-                pGen.init(strength, certainty, random);
-                param = new DHKeyGenerationParameters(random, pGen.generateParameters());
-                engine.init(param);
-                initialised = true;
-            }
-
-            AsymmetricCipherKeyPair   pair = engine.generateKeyPair();
-            DHPublicKeyParameters     pub = (DHPublicKeyParameters)pair.getPublic();
-            DHPrivateKeyParameters priv = (DHPrivateKeyParameters)pair.getPrivate();
-
-            return new KeyPair(new JCEDHPublicKey(pub),
-                               new JCEDHPrivateKey(priv));
-        }
-    }
-
-    public static class DSA
-        extends JDKKeyPairGenerator
-    {
-        DSAKeyGenerationParameters param;
-        DSAKeyPairGenerator        engine = new DSAKeyPairGenerator();
-        int                        strength = 1024;
-        int                        certainty = 20;
-        SecureRandom               random = new SecureRandom();
-        boolean                    initialised = false;
-
-        public DSA()
-        {
-            super("DSA");
-        }
-
-        public void initialize(
-            int             strength,
-            SecureRandom    random)
-        {
-            this.strength = strength;
-            this.random = random;
-        }
-
-        public void initialize(
-            AlgorithmParameterSpec  params,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            if (!(params instanceof DSAParameterSpec))
-            {
-                throw new InvalidAlgorithmParameterException("parameter object not a DSAParameterSpec");
-            }
-            DSAParameterSpec     dsaParams = (DSAParameterSpec)params;
-
-            param = new DSAKeyGenerationParameters(random, new DSAParameters(dsaParams.getP(), dsaParams.getQ(), dsaParams.getG()));
-
-            engine.init(param);
-            initialised = true;
-        }
-
-        public KeyPair generateKeyPair()
-        {
-            if (!initialised)
-            {
-                DSAParametersGenerator   pGen = new DSAParametersGenerator();
-
-                pGen.init(strength, certainty, random);
-                param = new DSAKeyGenerationParameters(random, pGen.generateParameters());
-                engine.init(param);
-                initialised = true;
-            }
-
-            AsymmetricCipherKeyPair   pair = engine.generateKeyPair();
-            DSAPublicKeyParameters     pub = (DSAPublicKeyParameters)pair.getPublic();
-            DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)pair.getPrivate();
-
-            return new KeyPair(new JDKDSAPublicKey(pub),
-                               new JDKDSAPrivateKey(priv));
-        }
-    }
-
-    public static class ElGamal
-        extends JDKKeyPairGenerator
-    {
-        ElGamalKeyGenerationParameters  param;
-        ElGamalKeyPairGenerator         engine = new ElGamalKeyPairGenerator();
-        int                             strength = 1024;
-        int                             certainty = 20;
-        SecureRandom                    random = new SecureRandom();
-        boolean                         initialised = false;
-
-        public ElGamal()
-        {
-            super("ElGamal");
-        }
-
-        public void initialize(
-            int             strength,
-            SecureRandom    random)
-        {
-            this.strength = strength;
-            this.random = random;
-        }
-
-        public void initialize(
-            AlgorithmParameterSpec  params,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            if (!(params instanceof ElGamalParameterSpec))
-            {
-                throw new InvalidAlgorithmParameterException("parameter object not a ElGamalParameterSpec");
-            }
-            ElGamalParameterSpec     elParams = (ElGamalParameterSpec)params;
-
-            param = new ElGamalKeyGenerationParameters(random, new ElGamalParameters(elParams.getP(), elParams.getG()));
-
-            engine.init(param);
-            initialised = true;
-        }
-
-        public KeyPair generateKeyPair()
-        {
-            if (!initialised)
-            {
-                ElGamalParametersGenerator   pGen = new ElGamalParametersGenerator();
-
-                pGen.init(strength, certainty, random);
-                param = new ElGamalKeyGenerationParameters(random, pGen.generateParameters());
-                engine.init(param);
-                initialised = true;
-            }
-
-            AsymmetricCipherKeyPair         pair = engine.generateKeyPair();
-            ElGamalPublicKeyParameters      pub = (ElGamalPublicKeyParameters)pair.getPublic();
-            ElGamalPrivateKeyParameters     priv = (ElGamalPrivateKeyParameters)pair.getPrivate();
-
-            return new KeyPair(new JCEElGamalPublicKey(pub),
-                               new JCEElGamalPrivateKey(priv));
-        }
-    }
-	*/
-    public static class EC
-        extends JDKKeyPairGenerator
-    {
-        ECKeyGenerationParameters   param;
-        ECKeyPairGenerator          engine = new ECKeyPairGenerator();
-        ECParameterSpec             ecParams = null;
-        int                         strength = 239;
-        int                         certainty = 50;
-        SecureRandom                random = new SecureRandom();
-        boolean                     initialised = false;
-        String                      algorithm;
-
-        static private Hashtable    ecParameters;
-
-        static {
-            ecParameters = new Hashtable();
-
-            ecParameters.put(new Integer(192), 
-                    ECNamedCurveTable.getParameterSpec("prime192v1"));
-            ecParameters.put(new Integer(239), 
-                    ECNamedCurveTable.getParameterSpec("prime239v1"));
-            ecParameters.put(new Integer(256), 
-                    ECNamedCurveTable.getParameterSpec("prime256v1"));
-        }
-
-
-        public EC(
-            String  algorithm)
-        {
-            super(algorithm);
-            this.algorithm = algorithm;
-        }
-
-        public void initialize(
-            int             strength,
-            SecureRandom    random)
-        {
-            this.strength = strength;
-            this.random = random;
-            this.ecParams = (ECParameterSpec)ecParameters.get(new Integer(strength));
-
-            if (ecParams != null)
-            {
-                param = new ECKeyGenerationParameters(new ECDomainParameters(ecParams.getCurve(), ecParams.getG(), ecParams.getN()), random);
-
-                engine.init(param);
-                initialised = true;
-            }
-        }
-
-        public void initialize(
-            AlgorithmParameterSpec  params,
-            SecureRandom            random)
-            throws InvalidAlgorithmParameterException
-        {
-            if (!(params instanceof ECParameterSpec))
-            {
-                throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec");
-            }
-
-            this.ecParams = (ECParameterSpec)params;
-
-            param = new ECKeyGenerationParameters(new ECDomainParameters(ecParams.getCurve(), ecParams.getG(), ecParams.getN()), random);
-
-            engine.init(param);
-            initialised = true;
-        }
-
-        public KeyPair generateKeyPair()
-        {
-            if (!initialised)
-            {
-                throw new IllegalStateException("EC Key Pair Generator not initialised");
-            }
-
-            AsymmetricCipherKeyPair     pair = engine.generateKeyPair();
-            ECPublicKeyParameters       pub = (ECPublicKeyParameters)pair.getPublic();
-            ECPrivateKeyParameters      priv = (ECPrivateKeyParameters)pair.getPrivate();
-
-            return new KeyPair(new JCEECPublicKey(algorithm, pub, ecParams),
-                               new JCEECPrivateKey(algorithm, priv, ecParams));
-        }
-    }
-
-    public static class ECDSA
-        extends EC
-    {
-        public ECDSA()
-        {
-            super("ECDSA");
-        }
-    }
-
-    public static class ECDH
-        extends EC
-    {
-        public ECDH()
-        {
-            super("ECDH");
-        }
-    }
-
-    public static class ECDHC
-        extends EC
-    {
-        public ECDHC()
-        {
-            super("ECDHC");
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JDKMessageDigest.java b/azureus2/src/org/bouncycastle/jce/provider/JDKMessageDigest.java
deleted file mode 100644
index 9e18d25..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JDKMessageDigest.java
+++ /dev/null
@@ -1,279 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.MessageDigest;
-
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.*;
-
-public class JDKMessageDigest
-    extends MessageDigest
-{
-    Digest  digest;
-
-    protected JDKMessageDigest(
-        Digest  digest)
-    {
-        super(digest.getAlgorithmName());
-
-        this.digest = digest;
-    }
-
-    public void engineReset() 
-    {
-        digest.reset();
-    }
-
-    public void engineUpdate(
-        byte    input) 
-    {
-        digest.update(input);
-    }
-
-    public void engineUpdate(
-        byte[]  input,
-        int     offset,
-        int     len) 
-    {
-        digest.update(input, offset, len);
-    }
-
-    public byte[] engineDigest() 
-    {
-        byte[]  digestBytes = new byte[digest.getDigestSize()];
-
-        digest.doFinal(digestBytes, 0);
-
-        return digestBytes;
-    }
-
-    /**
-     * classes that extend directly off us.
-     */
-    static public class SHA1
-        extends JDKMessageDigest
-		implements Cloneable
-    {
-        public SHA1()
-        {
-            super(new SHA1Digest());
-        }
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			SHA1 d = (SHA1)super.clone();
-			d.digest = new SHA1Digest((SHA1Digest)digest);
-
-			return d;
-		}
-    }
-
-    static public class SHA256
-        extends JDKMessageDigest
-		implements Cloneable
-    {
-        public SHA256()
-        {
-            super(new SHA256Digest());
-        }
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			SHA256 d = (SHA256)super.clone();
-			d.digest = new SHA256Digest((SHA256Digest)digest);
-
-			return d;
-		}
-    }
-
-    static public class SHA384
-        extends JDKMessageDigest
-		implements Cloneable
-    {
-        public SHA384()
-        {
-            super(new SHA384Digest());
-        }
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			SHA384 d = (SHA384)super.clone();
-			d.digest = new SHA384Digest((SHA384Digest)digest);
-
-			return d;
-		}
-    }
-
-    static public class SHA512
-        extends JDKMessageDigest
-		implements Cloneable
-    {
-        public SHA512()
-        {
-            super(new SHA512Digest());
-        }
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			SHA512 d = (SHA512)super.clone();
-			d.digest = new SHA512Digest((SHA512Digest)digest);
-
-			return d;
-		}
-    }
-
-    static public class MD2
-        extends JDKMessageDigest
-		implements Cloneable
-    {
-        public MD2()
-        {
-            super(new MD2Digest());
-        }
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			MD2 d = (MD2)super.clone();
-			d.digest = new MD2Digest((MD2Digest)digest);
-
-			return d;
-		}
-    }
-
-    static public class MD4
-        extends JDKMessageDigest
-		implements Cloneable
-    {
-        public MD4()
-        {
-            super(new MD4Digest());
-        }
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			MD4 d = (MD4)super.clone();
-			d.digest = new MD4Digest((MD4Digest)digest);
-
-			return d;
-		}
-    }
-
-    static public class MD5
-        extends JDKMessageDigest
-		implements Cloneable
-    {
-        public MD5()
-        {
-            super(new MD5Digest());
-        }
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			MD5 d = (MD5)super.clone();
-			d.digest = new MD5Digest((MD5Digest)digest);
-
-			return d;
-		}
-    }
-
-    static public class RIPEMD128
-        extends JDKMessageDigest
-		implements Cloneable
-    {
-        public RIPEMD128()
-        {
-            super(new RIPEMD128Digest());
-        }
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			RIPEMD128 d = (RIPEMD128)super.clone();
-			d.digest = new RIPEMD128Digest((RIPEMD128Digest)digest);
-
-			return d;
-		}
-    }
-
-    static public class RIPEMD160
-        extends JDKMessageDigest
-		implements Cloneable
-    {
-        public RIPEMD160()
-        {
-            super(new RIPEMD160Digest());
-        }
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			RIPEMD160 d = (RIPEMD160)super.clone();
-			d.digest = new RIPEMD160Digest((RIPEMD160Digest)digest);
-
-			return d;
-		}
-    }
-    
-	static public class RIPEMD256
-		extends JDKMessageDigest
-		implements Cloneable
-	{
-		public RIPEMD256()
-		{
-			super(new RIPEMD256Digest());
-		}
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			RIPEMD256 d = (RIPEMD256)super.clone();
-			d.digest = new RIPEMD256Digest((RIPEMD256Digest)digest);
-
-			return d;
-		}
-	}
-	
-	static public class RIPEMD320
-		extends JDKMessageDigest
-		implements Cloneable
-	{
-		public RIPEMD320()
-		{
-			super(new RIPEMD320Digest());
-		}
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			RIPEMD320 d = (RIPEMD320)super.clone();
-			d.digest = new RIPEMD320Digest((RIPEMD320Digest)digest);
-
-			return d;
-		}
-	}
-	
-    static public class Tiger
-        extends JDKMessageDigest
-		implements Cloneable
-    {
-        public Tiger()
-        {
-            super(new TigerDigest());
-        }
-
-		public Object clone()
-		throws CloneNotSupportedException
-		{
-			Tiger d = (Tiger)super.clone();
-			d.digest = new TigerDigest((TigerDigest)digest);
-
-			return d;
-		}
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/JDKX509CertificateFactory.java b/azureus2/src/org/bouncycastle/jce/provider/JDKX509CertificateFactory.java
deleted file mode 100644
index 2da33d4..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/JDKX509CertificateFactory.java
+++ /dev/null
@@ -1,360 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.cert.CRL;
-import java.security.cert.CRLException;
-import java.security.cert.CertPath;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactorySpi;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.BERInputStream;
-import org.bouncycastle.asn1.DERInputStream;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.SignedData;
-import org.bouncycastle.asn1.x509.CertificateList;
-import org.bouncycastle.asn1.x509.X509CertificateStructure;
-import org.bouncycastle.util.encoders.Base64;
-
-/**
- * class for dealing with X509 certificates.
- * <p>
- * At the moment this will deal with "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----"
- * base 64 encoded certs, as well as the BER binaries of certificates and some classes of PKCS#7
- * objects.
- */
-public class JDKX509CertificateFactory
-    extends CertificateFactorySpi
-{
-	private SignedData	sData = null;
-	private int				sDataObjectCount = 0;
-	
-    private String readLine(
-        InputStream in)
-        throws IOException
-    {
-        int             c;
-        StringBuffer    l = new StringBuffer();
-
-        while (((c = in.read()) != '\n') && (c >= 0))
-        {
-            if (c == '\r')
-            {
-                continue;
-            }
-
-            l.append((char)c);
-        }
-
-        if (c < 0)
-        {
-            return null;
-        }
-
-        return l.toString();
-    }
-
-    private Certificate readDERCertificate(
-        InputStream in)
-        throws IOException
-    {
-        DERInputStream  dIn = new DERInputStream(in);
-        ASN1Sequence    seq = (ASN1Sequence)dIn.readObject();
-
-        if (seq.size() > 1
-                && seq.getObjectAt(0) instanceof DERObjectIdentifier)
-        {
-            if (seq.getObjectAt(0).equals(PKCSObjectIdentifiers.signedData))
-            {
-                sData = new SignedData(ASN1Sequence.getInstance(
-                                (ASN1TaggedObject)seq.getObjectAt(1), true));
-
-                return new X509CertificateObject(
-                            X509CertificateStructure.getInstance(
-                                    sData.getCertificates().getObjectAt(sDataObjectCount++)));
-            }
-        }
-
-        return new X509CertificateObject(
-                            X509CertificateStructure.getInstance(seq));
-    }
-
-    /**
-     * read in a BER encoded PKCS7 certificate.
-     */
-    private Certificate readPKCS7Certificate(
-        InputStream  in)
-        throws IOException
-    {
-        BERInputStream  dIn = new BERInputStream(in);
-        ASN1Sequence seq = (ASN1Sequence)dIn.readObject();
-
-		if (seq.size() > 1
-				&& seq.getObjectAt(0) instanceof DERObjectIdentifier)
-		{
-	        if (seq.getObjectAt(0).equals(PKCSObjectIdentifiers.signedData))
-	        {
-				sData = new SignedData(ASN1Sequence.getInstance(
-								(ASN1TaggedObject)seq.getObjectAt(1), true));
-	
-				return new X509CertificateObject(
-							X509CertificateStructure.getInstance(
-									sData.getCertificates().getObjectAt(sDataObjectCount++)));
-	        }
-		}
-
-		return new X509CertificateObject(
-					 X509CertificateStructure.getInstance(seq));
-    }
-
-    private Certificate readPEMCertificate(
-        InputStream  in)
-        throws IOException
-    {
-        String          line;
-        StringBuffer    pemBuf = new StringBuffer();
-
-        while ((line = readLine(in)) != null)
-        {
-            if (line.equals("-----BEGIN CERTIFICATE-----")
-                || line.equals("-----BEGIN X509 CERTIFICATE-----"))
-            {
-                break;
-            }
-        }
-
-        while ((line = readLine(in)) != null)
-        {
-            if (line.equals("-----END CERTIFICATE-----")
-                || line.equals("-----END X509 CERTIFICATE-----"))
-            {
-                break;
-            }
-
-            pemBuf.append(line);
-        }
-
-        if (pemBuf.length() != 0)
-        {
-            ByteArrayInputStream bIn = new ByteArrayInputStream(Base64.decode(pemBuf.toString()));
-            return readDERCertificate(bIn);
-        }
-
-        return null;
-    }
-
-    private CRL readDERCRL(
-        InputStream in)
-        throws IOException
-    {
-        DERInputStream  dIn = new DERInputStream(in);
-
-        return new X509CRLObject(new CertificateList((ASN1Sequence)dIn.readObject()));
-    }
-
-    private CRL readPEMCRL(
-        InputStream  in)
-        throws IOException
-    {
-        String          line;
-        StringBuffer    pemBuf = new StringBuffer();
-
-        while ((line = readLine(in)) != null)
-        {
-            if (line.equals("-----BEGIN CRL-----")
-                || line.equals("-----BEGIN X509 CRL-----"))
-            {
-                break;
-            }
-        }
-
-        while ((line = readLine(in)) != null)
-        {
-            if (line.equals("-----END CRL-----")
-                || line.equals("-----END X509 CRL-----"))
-            {
-                break;
-            }
-
-            pemBuf.append(line);
-        }
-
-        if (pemBuf.length() != 0)
-        {
-            ByteArrayInputStream bIn = new ByteArrayInputStream(Base64.decode(pemBuf.toString()));
-            return readDERCRL(bIn);
-        }
-
-        return null;
-    }
-
-    /**
-     * Generates a certificate object and initializes it with the data
-     * read from the input stream inStream.
-     */
-    public Certificate engineGenerateCertificate(
-        InputStream in) 
-        throws CertificateException
-    {
-    	if (sData != null && sDataObjectCount != sData.getCertificates().size())
-    	{
-			return new X509CertificateObject(
-						X509CertificateStructure.getInstance(
-								sData.getCertificates().getObjectAt(sDataObjectCount++)));
-    	}
-    	
-        if (!in.markSupported())
-        {
-            in = new BufferedInputStream(in);
-        }
-
-        try
-        {
-            in.mark(10);
-            int	tag = in.read();
-            
-            if (tag == -1)
-            {
-            	return null;
-            }
-            
-            if (tag != 0x30)  // assume ascii PEM encoded.
-            {
-                in.reset();
-                return readPEMCertificate(in);
-            }
-            else if (in.read() == 0x80)    // assume BER encoded.
-            {
-                in.reset();
-                return readPKCS7Certificate(in);
-            }
-            else
-            {
-                in.reset();
-                return readDERCertificate(in);
-            }
-        }
-        catch (IOException e)
-        {
-            throw new CertificateException(e.toString());
-        }
-    }
-
-    /**
-     * Returns a (possibly empty) collection view of the certificates
-     * read from the given input stream inStream.
-     */
-    public Collection engineGenerateCertificates(
-        InputStream inStream) 
-        throws CertificateException
-    {
-        Certificate     cert;
-        ArrayList       certs = new ArrayList();
-
-        while ((cert = engineGenerateCertificate(inStream)) != null)
-        {
-            certs.add(cert);
-        }
-
-        return certs;
-    }
-
-    /**
-     * Generates a certificate revocation list (CRL) object and initializes
-     * it with the data read from the input stream inStream.
-     */
-    public CRL engineGenerateCRL(
-        InputStream inStream) 
-		throws CRLException
-    {
-        if (!inStream.markSupported())
-        {
-            inStream = new BufferedInputStream(inStream);
-        }
-
-        try
-        {
-            inStream.mark(10);
-            if (inStream.read() != 0x30)  // assume ascii PEM encoded.
-            {
-                inStream.reset();
-                return readPEMCRL(inStream);
-            }
-            else
-            {
-                inStream.reset();
-                return readDERCRL(inStream);
-            }
-        }
-        catch (IOException e)
-        {
-            throw new CRLException(e.toString());
-        }
-    }
-
-    /**
-     * Returns a (possibly empty) collection view of the CRLs read from
-     * the given input stream inStream.
-	 *
-	 * The inStream may contain a sequence of DER-encoded CRLs, or
-	 * a PKCS#7 CRL set.  This is a PKCS#7 SignedData object, with the
-	 * only signficant field being crls.  In particular the signature
-	 * and the contents are ignored.
-     */
-    public Collection engineGenerateCRLs(
-        InputStream inStream) 
-		throws CRLException
-    {
-        return null;
-    }
-
-    public Iterator engineGetCertPathEncodings()
-    {
-	return PKIXCertPath.certPathEncodings.iterator();
-    }
-
-    public CertPath engineGenerateCertPath(
-        InputStream inStream)
-	throws CertificateException
-    {
-        return engineGenerateCertPath( inStream, "PkiPath" );
-    }
-
-    public CertPath engineGenerateCertPath(
-        InputStream inStream,
-		String encoding)
-	throws CertificateException
-    {
-        return new PKIXCertPath( inStream, encoding );
-    }
-
-    public CertPath engineGenerateCertPath(
-        List certificates)
-	throws CertificateException
-    {
-        Iterator iter = certificates.iterator();
-        Object obj;
-        while ( iter.hasNext() )
-        {
-            obj = iter.next();
-            if ( obj != null ) {
-                if ( ! ( obj instanceof X509Certificate ) )
-                {
-                    throw new CertificateException( "list contains none X509Certificate object while creating CertPath\n" + obj.toString() );
-                }
-            }
-        }
-        return new PKIXCertPath( certificates );
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/PKIXCertPath.java b/azureus2/src/org/bouncycastle/jce/provider/PKIXCertPath.java
deleted file mode 100644
index d105a00..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/PKIXCertPath.java
+++ /dev/null
@@ -1,222 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.NoSuchProviderException;
-import java.security.cert.CertPath;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInputStream;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.DERSequence;
-
-/**
- * CertPath implementation for X.509 certificates.
- * <br />
- * <b>TODO: add PKCS #7 encoding support</b>
- **/
-public  class PKIXCertPath
-	extends CertPath
-{
-    static final List certPathEncodings;
-
-    static
-    {
-	List encodings = new ArrayList();
-	encodings.add("PkiPath");
-	certPathEncodings = Collections.unmodifiableList( encodings );
-    }
-
-    private List certificates;
-
-	/**
-	 * Creates a CertPath of the specified type.
-	 * This constructor is protected because most users should use
-	 * a CertificateFactory to create CertPaths.
-	 * @param type the standard name of the type of Certificatesin this path
-	 **/
-    PKIXCertPath( List certificates )
-    {
-	super("X.509");
-	this.certificates = new ArrayList( certificates );
-    }
-
-	/**
-	 * Creates a CertPath of the specified type.
-	 * This constructor is protected because most users should use
-	 * a CertificateFactory to create CertPaths.
-	 *
-	 * <b>TODO: implement PKCS7 decoding</b>
-	 *
-	 * @param type the standard name of the type of Certificatesin this path
-	 **/
-    PKIXCertPath( InputStream inStream, String encoding)
-	throws CertificateException
-    {
-	super("X.509");
-	try {
-	    if ( encoding.equals( "PkiPath" ) )
-	    {
-		DERInputStream derInStream = new DERInputStream(inStream);
-		DERObject derObject = derInStream.readObject();
-		if ( derObject == null || ! ( derObject instanceof ASN1Sequence ) )
-		{
-		    throw new CertificateException("input stream does not contain a ASN1 SEQUENCE while reading PkiPath encoded data to load CertPath" );
-		}
-		Enumeration enumx = ((ASN1Sequence)derObject).getObjects();
-		InputStream certInStream;
-		ByteArrayOutputStream outStream;
-		DEROutputStream derOutStream;
-		certificates = new ArrayList();
-		CertificateFactory certFactory= CertificateFactory.getInstance( "X.509", BouncyCastleProvider.PROVIDER_NAME );
-		while ( enumx.hasMoreElements() ) {
-		    outStream = new ByteArrayOutputStream();
-		    derOutStream = new DEROutputStream(outStream);
-    
-        	    derOutStream.writeObject(enumx.nextElement());
-        	    derOutStream.close();
-
-		    certInStream = new ByteArrayInputStream(outStream.toByteArray());
-		    certificates.add(0,certFactory.generateCertificate(certInStream));
-		}
-	    }
-	    else
-	    {
-		throw new CertificateException( "unsupported encoding" );
-	    }
-	} catch ( IOException ex ) {
-	    throw new CertificateException( "IOException throw while decoding CertPath:\n" + ex.toString() ); 
-	} catch ( NoSuchProviderException ex ) {
-	    throw new CertificateException( "BouncyCastle provider not found while trying to get a CertificateFactory:\n" + ex.toString() ); 
-	}
-    }
-    
-	/**
-	 * Returns an iteration of the encodings supported by this
-	 * certification path, with the default encoding
-	 * first. Attempts to modify the returned Iterator via its
-	 * remove method result in an UnsupportedOperationException.
-	 *
-	 * @return an Iterator over the names of the supported encodings (as Strings)
-	 **/
-    public Iterator getEncodings()
-    {
-	return certPathEncodings.iterator();
-    }
-
-	/**
-	 * Returns the encoded form of this certification path, using
-	 * the default encoding.
-	 *
-	 * @return the encoded bytes
-	 * @exception CertificateEncodingException if an encoding error occurs
-	 **/
-    public byte[] getEncoded()
-	throws CertificateEncodingException
-    {
-	Iterator iter = getEncodings();
-	if ( iter.hasNext() )
-	{
-	    Object enc = iter.next();
-	    if ( enc instanceof String )
-	    {
-		return getEncoded((String)enc);
-	    }
-	}
-	return null;
-    }
-
-	/**
-	 * Returns the encoded form of this certification path, using
-	 * the specified encoding.
-	 *
-	 * <b>TODO: implement PKCS7 decoding</b>
-	 *
-	 * @param encoding the name of the encoding to use
-	 * @return the encoded bytes
-	 * @exception CertificateEncodingException if an encoding error
-	 * occurs or the encoding requested is not supported
-	 *
-	 **/
-    public byte[] getEncoded(String encoding)
-	throws CertificateEncodingException
-    {
-	DERObject encoded = null;
-	if ( encoding.equals("PkiPath") )
-	{
-        ASN1EncodableVector v = new ASN1EncodableVector();
-
-		// TODO check ListIterator  implementation for JDK 1.1
-	    ListIterator iter = certificates.listIterator(certificates.size());
-	    while ( iter.hasPrevious() )
-	    {
-		    v.add(getEncodedX509Certificate((X509Certificate)iter.previous()));
-	    }
-
-        encoded = new DERSequence(v);
-	}
-	else
-	    throw new CertificateEncodingException( "unsupported encoding" );
-
-	if ( encoded == null )
-	    return null;
-
-	ByteArrayOutputStream outStream = new ByteArrayOutputStream();
-        DEROutputStream derOutStream = new DEROutputStream(outStream);
-
-	try {
-	    derOutStream.writeObject( encoded );
-	    derOutStream.close();
-	} catch ( IOException ex ) {
-	    throw new CertificateEncodingException( "IOExeption thrown: " + ex.toString() );
-	}
-
-        return outStream.toByteArray();
-    }
-
-	/**
-	 * Returns the list of certificates in this certification
-	 * path. The List returned must be immutable and thread-safe. 
-	 *
-	 * <b>TODO: return immutable List</b>
-	 *
-	 * @return an immutable List of Certificates (may be empty, but not null)
-	 **/
-    public List getCertificates()
-    {
-	return new ArrayList( certificates );
-    }
-
-	/**
-	 * Return a DERObject containing the encoded certificate.
-	 *
-	 * @param cert the X509Certificate object to be encoded
-	 *
-	 * @return the DERObject
-	 **/
-    private DERObject getEncodedX509Certificate( X509Certificate cert )
-	throws CertificateEncodingException
-    {
-	try {
-	    ByteArrayInputStream inStream = new ByteArrayInputStream( cert.getEncoded() );
-	    DERInputStream derInStream = new DERInputStream( inStream );
-	    return derInStream.readObject();
-	} catch ( IOException ex ) {
-	    throw new CertificateEncodingException( "IOException caught while encoding certificate\n" + ex.toString() );
-	}
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/PKIXPolicyNode.java b/azureus2/src/org/bouncycastle/jce/provider/PKIXPolicyNode.java
deleted file mode 100644
index 4e33bb8..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/PKIXPolicyNode.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.cert.PolicyNode;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-public class PKIXPolicyNode
-    implements PolicyNode
-{
-	protected List       children;
-	protected int        depth;
-	protected Set        expectedPolicies;
-	protected PolicyNode parent;
-	protected Set        policyQualifiers;
-	protected String     validPolicy;
-	protected boolean    critical;
-	
-	/*  
-	 *  
-	 *  CONSTRUCTORS
-	 *  
-	 */ 
-	
-	public PKIXPolicyNode(
-        List       _children,
-        int        _depth,
-        Set        _expectedPolicies,
-        PolicyNode _parent,
-        Set        _policyQualifiers,
-        String     _validPolicy,
-        boolean    _critical)
-    {
-		children         = _children;
-		depth            = _depth;
-		expectedPolicies = _expectedPolicies;
-		parent           = _parent;
-		policyQualifiers = _policyQualifiers;
-		validPolicy      = _validPolicy;
-		critical         = _critical;
-	}
-	
-	public void addChild(
-        PKIXPolicyNode _child)
-    {
-		children.add(_child);
-		_child.setParent(this);
-	}
-	
-	public Iterator getChildren()
-    {
-		return children.iterator();
-	}
-	
-	public int getDepth()
-    {
-		return depth;
-	}
-	
-	public Set getExpectedPolicies()
-    {
-		return expectedPolicies;
-	}
-	
-	public PolicyNode getParent()
-    {
-		return parent;
-	}
-	
-	public Set getPolicyQualifiers()
-    {
-		return policyQualifiers;
-	}
-	
-	public String getValidPolicy()
-    {
-		return validPolicy;
-	}
-	
-	public boolean hasChildren()
-    {
-		return !children.isEmpty();
-	}
-	
-	public boolean isCritical()
-    {
-		return critical;
-	}
-	
-	public void removeChild(PKIXPolicyNode _child)
-    {
-		children.remove(_child);
-	}
-	
-	public void setCritical(boolean _critical)
-    {
-		critical = _critical;
-	}
-	
-	public void setParent(PKIXPolicyNode _parent)
-    {
-		parent = _parent;
-	}
-	
-	public String toString()
-    {
-		return toString("");
-	}
-	
-	public String toString(String _indent)
-    {
-		StringBuffer _buf = new StringBuffer();
-		_buf.append(_indent);
-		_buf.append(validPolicy);
-		_buf.append(" {\n");
-		
-		for(int i = 0; i < children.size(); i++) {
-			_buf.append(((PKIXPolicyNode)children.get(i)).toString(_indent + "    "));
-		}
-		
-		_buf.append(_indent);
-		_buf.append("}\n");
-		return _buf.toString();
-	}
-	
-	public Object clone()
-    {
-		return copy();
-	}
-	
-	public PKIXPolicyNode copy()
-    {
-		HashSet _expectedPolicies = new HashSet();
-		Iterator _iter = expectedPolicies.iterator();
-		while (_iter.hasNext())
-        {
-			_expectedPolicies.add(new String((String)_iter.next()));
-		}
-		
-		HashSet _policyQualifiers = new HashSet();
-		_iter = policyQualifiers.iterator();
-		while (_iter.hasNext())
-        {
-			_policyQualifiers.add(new String((String)_iter.next()));
-		}
-		
-		PKIXPolicyNode _node = new PKIXPolicyNode(new ArrayList(),
-		                                          depth,
-		                                          _expectedPolicies,
-		                                          null,
-		                                          _policyQualifiers,
-		                                          new String(validPolicy),
-		                                          critical);
-		
-		_iter = children.iterator();
-		while (_iter.hasNext())
-        {
-			PKIXPolicyNode _child = ((PKIXPolicyNode)_iter.next()).copy();
-			_child.setParent(_node);
-			_node.addChild(_child);
-		}
-		
-		return _node;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/RSAUtil.java b/azureus2/src/org/bouncycastle/jce/provider/RSAUtil.java
deleted file mode 100644
index f7f0411..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/RSAUtil.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.security.interfaces.RSAPrivateCrtKey;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-
-import org.bouncycastle.crypto.params.RSAKeyParameters;
-import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
-
-/**
- * utility class for converting java.security RSA objects into their
- * org.bouncycastle.crypto counterparts.
- */
-public class RSAUtil
-{
-    static public RSAKeyParameters generatePublicKeyParameter(
-        RSAPublicKey    key)
-    {
-        return new RSAKeyParameters(false, key.getModulus(), key.getPublicExponent());
-
-    }
-
-    static public RSAKeyParameters generatePrivateKeyParameter(
-        RSAPrivateKey    key)
-    {
-        if (key instanceof RSAPrivateCrtKey)
-        {
-            RSAPrivateCrtKey    k = (RSAPrivateCrtKey)key;
-
-            return new RSAPrivateCrtKeyParameters(k.getModulus(),
-                k.getPublicExponent(), k.getPrivateExponent(),
-                k.getPrimeP(), k.getPrimeQ(), k.getPrimeExponentP(),                            k.getPrimeExponentQ(), k.getCrtCoefficient());
-        }
-        else
-        {
-            RSAPrivateKey    k = key;
-
-            return new RSAKeyParameters(true, k.getModulus(), k.getPrivateExponent());
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/X509CRLEntryObject.java b/azureus2/src/org/bouncycastle/jce/provider/X509CRLEntryObject.java
deleted file mode 100644
index f6b5573..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/X509CRLEntryObject.java
+++ /dev/null
@@ -1,168 +0,0 @@
-
-package org.bouncycastle.jce.provider;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.cert.CRLException;
-import java.security.cert.X509CRLEntry;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.x509.TBSCertList;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.X509Extensions;
-
-/**
- * The following extensions are listed in RFC 2459 as relevant to CRL Entries
- *
- * ReasonCode
- * Hode Instruction Code
- * Invalidity Date
- * Certificate Issuer (critical)
- */
-public class X509CRLEntryObject extends X509CRLEntry
-{
-	private TBSCertList.CRLEntry c;
-
-	public X509CRLEntryObject(
-		TBSCertList.CRLEntry c)
-	{
-		this.c = c;
-	}
-
-	/**
-	 * Will return true if any extensions are present and marked
-	 * as critical as we currently dont handle any extensions!
-	 */
-    public boolean hasUnsupportedCriticalExtension()
-	{
-		Set extns = getCriticalExtensionOIDs();
-		if ( extns != null && !extns.isEmpty() )
-		{
-			return true;
-		}
-
-		return false;
-	}
-
-	private Set getExtensionOIDs(boolean critical)
-	{
-		X509Extensions extensions = c.getExtensions();
-
-		if ( extensions != null )
-		{
-			HashSet			set = new HashSet();
-			Enumeration		e = extensions.oids();
-
-			while (e.hasMoreElements())
-			{
-				DERObjectIdentifier	oid = (DERObjectIdentifier)e.nextElement();
-				X509Extension		ext = extensions.getExtension(oid);
-
-				if (critical == ext.isCritical())
-				{
-					set.add(oid.getId());
-				}
-			}
-
-			return set;
-		}
-
-		return null;
-	}
-
-    public Set getCriticalExtensionOIDs()
-	{
-		return getExtensionOIDs(true);
-	}
-
-    public Set getNonCriticalExtensionOIDs()
-	{
-		return getExtensionOIDs(false);
-	}
-
-    public byte[] getExtensionValue(String oid)
-	{
-		X509Extensions exts = c.getExtensions();
-
-		if (exts != null)
-		{
-			X509Extension ext = exts.getExtension(new DERObjectIdentifier(oid));
-
-			if (ext != null)
-			{
-				return ext.getValue().getOctets();
-			}
-		}
-
-		return null;
-	}
-
-    public byte[] getEncoded()
-		throws CRLException
-	{
-		ByteArrayOutputStream	bOut = new ByteArrayOutputStream();
-		DEROutputStream			dOut = new DEROutputStream(bOut);
-
-		try
-		{
-			dOut.writeObject(c);
-
-			return bOut.toByteArray();
-		}
-		catch (IOException e)
-		{
-			throw new CRLException(e.toString());
-		}
-	}
-
-    public BigInteger getSerialNumber()
-	{
-		return c.getUserCertificate().getValue();
-	}
-
-    public Date getRevocationDate()
-	{
-		return c.getRevocationDate().getDate();
-	}
-
-    public boolean hasExtensions()
-	{
-		return c.getExtensions() != null;
-	}
-
-    public String toString()
-	{
-		StringBuffer buf = new StringBuffer();
-		String nl = System.getProperty("line.separator");
-
-		buf.append("      userCertificate: " + this.getSerialNumber() + nl);
-		buf.append("       revocationDate: " + this.getRevocationDate() + nl);
-
-
-		X509Extensions extensions = c.getExtensions();
-
-		if ( extensions != null )
-		{
-			Enumeration e = extensions.oids();
-			if ( e.hasMoreElements() )
-			{
-				buf.append("   crlEntryExtensions:" + nl);
-
-				while ( e.hasMoreElements() )
-				{
-					DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
-					X509Extension ext = extensions.getExtension(oid);
-					buf.append(ext);
-				}
-			}
-		}
-
-		return buf.toString();
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/jce/provider/X509CRLObject.java b/azureus2/src/org/bouncycastle/jce/provider/X509CRLObject.java
deleted file mode 100644
index 51071fc..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/X509CRLObject.java
+++ /dev/null
@@ -1,379 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Principal;
-import java.security.Provider;
-import java.security.PublicKey;
-import java.security.Security;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.cert.CRLException;
-import java.security.cert.Certificate;
-import java.security.cert.X509CRL;
-import java.security.cert.X509CRLEntry;
-import java.security.cert.X509Certificate;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.security.auth.x500.X500Principal;
-
-import org.bouncycastle.asn1.ASN1OutputStream;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.x509.CertificateList;
-import org.bouncycastle.asn1.x509.TBSCertList;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.jce.X509Principal;
-
-/**
- * The following extensions are listed in RFC 2459 as relevant to CRLs
- *
- * Authority Key Identifier
- * Issuer Alternative Name
- * CRL Number
- * Delta CRL Indicator (critical)
- * Issuing Distribution Point (critical)
- */
-public class X509CRLObject
-    extends X509CRL
-{
-    private CertificateList c;
-
-    public X509CRLObject(
-        CertificateList c)
-    {
-        this.c = c;
-    }
-
-	/**
-	 * Will return true if any extensions are present and marked
-	 * as critical as we currently dont handle any extensions!
-	 */
-    public boolean hasUnsupportedCriticalExtension()
-	{
-		Set extns = getCriticalExtensionOIDs();
-		if ( extns != null && !extns.isEmpty() )
-		{
-			return true;
-		}
-
-		return false;
-	}
-
-	private Set getExtensionOIDs(boolean critical)
-	{
-		if (this.getVersion() == 2)
-		{
-			HashSet         set = new HashSet();
-			X509Extensions  extensions = c.getTBSCertList().getExtensions();
-			Enumeration     e = extensions.oids();
-
-			while (e.hasMoreElements())
-			{
-				DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
-				X509Extension       ext = extensions.getExtension(oid);
-
-				if (critical == ext.isCritical())
-				{
-					set.add(oid.getId());
-				}
-			}
-
-			return set;
-		}
-
-		return null;
-	}
-
-    public Set getCriticalExtensionOIDs()
-	{
-		return getExtensionOIDs(true);
-	}
-
-    public Set getNonCriticalExtensionOIDs()
-	{
-		return getExtensionOIDs(false);
-	}
-
-    public byte[] getExtensionValue(String oid)
-	{
-		X509Extensions exts = c.getTBSCertList().getExtensions();
-
-		if (exts != null)
-		{
-			X509Extension   ext = exts.getExtension(new DERObjectIdentifier(oid));
-
-			if (ext != null)
-			{
-                ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-                DEROutputStream dOut = new DEROutputStream(bOut);
-
-                try
-                {
-                    dOut.writeObject(ext.getValue());
-
-                    return bOut.toByteArray();
-                }
-                catch (Exception e)
-                {
-                    throw new RuntimeException("error encoding " + e.toString());
-                }
-			}
-		}
-
-		return null;
-	}
-
-    public byte[] getEncoded()
-        throws CRLException
-	{
-		ByteArrayOutputStream	bOut = new ByteArrayOutputStream();
-		DEROutputStream			dOut = new DEROutputStream(bOut);
-
-		try
-		{
-			dOut.writeObject(c);
-
-			return bOut.toByteArray();
-		}
-		catch (IOException e)
-		{
-			throw new CRLException(e.toString());
-		}
-	}
-
-    public void verify(PublicKey key)
-        throws CRLException,  NoSuchAlgorithmException,
-        InvalidKeyException, NoSuchProviderException,
-        SignatureException
-	{
-		verify(key, BouncyCastleProvider.PROVIDER_NAME);
-	}
-
-    public void verify(PublicKey key, String sigProvider)
-        throws CRLException, NoSuchAlgorithmException,
-        InvalidKeyException, NoSuchProviderException,
-        SignatureException
-	{
-		if ( !c.getSignatureAlgorithm().equals(c.getTBSCertList().getSignature()) )
-		{
-			throw new CRLException("Signature algorithm on CertifcateList does not match TBSCertList.");
-		}
-
-		Signature sig = Signature.getInstance(getSigAlgName(), sigProvider);
-
-		sig.initVerify(key);
-		sig.update(this.getTBSCertList());
-		if ( !sig.verify(this.getSignature()) )
-		{
-			throw new SignatureException("CRL does not verify with supplied public key.");
-		}
-	}
-
-    public int getVersion()
-	{
-		return c.getVersion();
-	}
-
-    public Principal getIssuerDN()
-	{
-		return new X509Principal(c.getIssuer());
-	}
-
-    public X500Principal getIssuerX500Principal()
-    {
-        try
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            ASN1OutputStream        aOut = new ASN1OutputStream(bOut);
-
-            aOut.writeObject(c.getIssuer());
-
-            return new X500Principal(bOut.toByteArray());
-        }
-        catch (IOException e)
-        {
-            throw new IllegalStateException("can't encode issuer DN");
-        }
-    }
-
-    public Date getThisUpdate()
-	{
-		return c.getThisUpdate().getDate();
-	}
-
-    public Date getNextUpdate()
-	{
-		if (c.getNextUpdate() != null)
-		{
-			return c.getNextUpdate().getDate();
-		}
-
-		return null;
-	}
-
-    public X509CRLEntry getRevokedCertificate(BigInteger serialNumber)
-	{
-		TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
-
-		if ( certs != null )
-		{
-			for ( int i = 0; i < certs.length; i++ )
-			{
-				if ( certs[i].getUserCertificate().getValue().equals(serialNumber) ) {
-					return new X509CRLEntryObject(certs[i]);
-				}
-			}
-		}
-
-		return null;
-	}
-  
-    public Set getRevokedCertificates()
-	{
-		TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
-
-		if ( certs != null )
-		{
-			HashSet set = new HashSet();
-			for ( int i = 0; i < certs.length; i++ )
-			{
-				set.add(new X509CRLEntryObject(certs[i]));
-
-			}
-
-			return set;
-		}
-
-		return null;
-	}
-  
-    public byte[] getTBSCertList()
-		throws CRLException
-	{
-		ByteArrayOutputStream	bOut = new ByteArrayOutputStream();
-		DEROutputStream			dOut = new DEROutputStream(bOut);
-
-		try
-		{
-			dOut.writeObject(c.getTBSCertList());
-
-			return bOut.toByteArray();
-		}
-		catch (IOException e)
-		{
-			throw new CRLException(e.toString());
-		}
-	}
-
-    public byte[] getSignature()
-	{
-		return c.getSignature().getBytes();
-	}
-
-    public String getSigAlgName()
-	{
-		Provider	prov = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
-		String		algName = prov.getProperty("Alg.Alias.Signature." + this.getSigAlgOID());
-
-		if ( algName != null )
-		{
-			return algName;
-		}
-
-		Provider[] provs = Security.getProviders();
-
-		//
-		// search every provider looking for a real algorithm
-		//
-		for (int i = 0; i != provs.length; i++)
-		{
-			algName = provs[i].getProperty("Alg.Alias.Signature." + this.getSigAlgOID());
-			if ( algName != null )
-			{
-				return algName;
-			}
-		}
-
-		return this.getSigAlgOID();
-	}
-
-    public String getSigAlgOID()
-	{
-		return c.getSignatureAlgorithm().getObjectId().getId();
-	}
-
-    public byte[] getSigAlgParams()
-	{
-		ByteArrayOutputStream	bOut = new ByteArrayOutputStream();
-
-		if ( c.getSignatureAlgorithm().getParameters() != null )
-		{
-			try
-			{
-				DEROutputStream	dOut = new DEROutputStream(bOut);
-
-				dOut.writeObject(c.getSignatureAlgorithm().getParameters());
-			}
-			catch (Exception e)
-			{
-				throw new RuntimeException("exception getting sig parameters " + e);
-			}
-
-			return bOut.toByteArray();
-		}
-
-		return null;
-	}
-
-    /**
-     * Returns a string representation of this CRL.
-     *
-     * @return a string representation of this CRL.
-     */
-    public String toString()
-	{
-		return "X.509 CRL";
-	}
-
-    /**
-     * Checks whether the given certificate is on this CRL.
-     *
-     * @param cert the certificate to check for.
-     * @return true if the given certificate is on this CRL,
-     * false otherwise.
-     */
-    public boolean isRevoked(Certificate cert)
-	{
-		if ( !cert.getType().equals("X.509") )
-		{
-			throw new RuntimeException("X.509 CRL used with non X.509 Cert");
-		}
-
-		TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
-
-		if ( certs != null )
-		{
-			BigInteger serial = ((X509Certificate)cert).getSerialNumber();
-
-			for ( int i = 0; i < certs.length; i++ )
-			{
-				if ( certs[i].getUserCertificate().getValue().equals(serial) )
-				{
-					return true;
-				}
-			}
-		}
-
-		return false;
-	}
-}
-
diff --git a/azureus2/src/org/bouncycastle/jce/provider/X509CertificateObject.java b/azureus2/src/org/bouncycastle/jce/provider/X509CertificateObject.java
deleted file mode 100644
index 4bb593b..0000000
--- a/azureus2/src/org/bouncycastle/jce/provider/X509CertificateObject.java
+++ /dev/null
@@ -1,679 +0,0 @@
-package org.bouncycastle.jce.provider;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Principal;
-import java.security.Provider;
-import java.security.PublicKey;
-import java.security.Security;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Set;
-import java.util.Vector;
-
-import javax.security.auth.x500.X500Principal;
-
-import org.bouncycastle.asn1.*;
-import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
-import org.bouncycastle.asn1.misc.NetscapeCertType;
-import org.bouncycastle.asn1.misc.NetscapeRevocationURL;
-import org.bouncycastle.asn1.misc.VerisignCzagExtension;
-import org.bouncycastle.asn1.util.ASN1Dump;
-import org.bouncycastle.asn1.x509.BasicConstraints;
-import org.bouncycastle.asn1.x509.KeyUsage;
-import org.bouncycastle.asn1.x509.X509CertificateStructure;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.jce.X509Principal;
-import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
-import org.bouncycastle.util.encoders.Hex;
-
-public class X509CertificateObject
-    extends X509Certificate
-    implements PKCS12BagAttributeCarrier
-{
-    private X509CertificateStructure    c;
-    private Hashtable                   pkcs12Attributes = new Hashtable();
-    private Vector                      pkcs12Ordering = new Vector();
-
-    public X509CertificateObject(
-        X509CertificateStructure    c)
-    {
-        this.c = c;
-    }
-
-    public void checkValidity()
-        throws CertificateExpiredException, CertificateNotYetValidException
-    {
-        this.checkValidity(new Date());
-    }
-
-    public void checkValidity(
-        Date    date)
-        throws CertificateExpiredException, CertificateNotYetValidException
-    {
-        if (date.after(this.getNotAfter()))
-        {
-            throw new CertificateExpiredException("certificate expired on " + c.getEndDate().getTime());
-        }
-
-        if (date.before(this.getNotBefore()))
-        {
-            throw new CertificateNotYetValidException("certificate not valid till " + c.getStartDate().getTime());
-        }
-    }
-
-    public int getVersion()
-    {
-        return c.getVersion();
-    }
-
-    public BigInteger getSerialNumber()
-    {
-        return c.getSerialNumber().getValue();
-    }
-
-    public Principal getIssuerDN()
-    {
-        return new X509Principal(c.getIssuer());
-    }
-
-    public X500Principal getIssuerX500Principal()
-    {
-        try
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            ASN1OutputStream        aOut = new ASN1OutputStream(bOut);
-
-            aOut.writeObject(c.getIssuer());
-
-            return new X500Principal(bOut.toByteArray());
-        }
-        catch (IOException e)
-        {
-            throw new IllegalStateException("can't encode issuer DN");
-        }
-    }
-
-    public Principal getSubjectDN()
-    {
-        return new X509Principal(c.getSubject());
-    }
-
-    public X500Principal getSubjectX500Principal()
-    {
-        try
-        {
-            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-            ASN1OutputStream        aOut = new ASN1OutputStream(bOut);
-
-            aOut.writeObject(c.getSubject());
-
-            return new X500Principal(bOut.toByteArray());
-        }
-        catch (IOException e)
-        {
-            throw new IllegalStateException("can't encode issuer DN");
-        }
-    }
-
-    public Date getNotBefore()
-    {
-        return c.getStartDate().getDate();
-    }
-
-    public Date getNotAfter()
-    {
-        return c.getEndDate().getDate();
-    }
-
-    public byte[] getTBSCertificate()
-        throws CertificateEncodingException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-
-        try
-        {
-            dOut.writeObject(c.getTBSCertificate());
-
-            return bOut.toByteArray();
-        }
-        catch (IOException e)
-        {
-            throw new CertificateEncodingException(e.toString());
-        }
-    }
-
-    public byte[] getSignature()
-    {
-        return c.getSignature().getBytes();
-    }
-
-    /**
-     * return a more "meaningful" representation for the signature algorithm used in
-     * the certficate.
-     */
-    public String getSigAlgName()
-    {
-        Provider    prov = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
-        String      algName = prov.getProperty("Alg.Alias.Signature." + this.getSigAlgOID());
-
-        if (algName != null)
-        {
-            return algName;
-        }
-
-        Provider[] provs = Security.getProviders();
-
-        //
-        // search every provider looking for a real algorithm
-        //
-        for (int i = 0; i != provs.length; i++)
-        {
-            algName = provs[i].getProperty("Alg.Alias.Signature." + this.getSigAlgOID());
-            if (algName != null)
-            {
-                return algName;
-            }
-        }
-
-        return this.getSigAlgOID();
-    }
-
-    /**
-     * return the object identifier for the signature.
-     */
-    public String getSigAlgOID()
-    {
-        return c.getSignatureAlgorithm().getObjectId().getId();
-    }
-
-    /**
-     * return the signature parameters, or null if there aren't any.
-     */
-    public byte[] getSigAlgParams()
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-
-        if (c.getSignatureAlgorithm().getParameters() != null)
-        {
-            try
-            {
-                DEROutputStream         dOut = new DEROutputStream(bOut);
-
-                dOut.writeObject(c.getSignatureAlgorithm().getParameters());
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException("exception getting sig parameters " + e);
-            }
-
-            return bOut.toByteArray();
-        }
-        else
-        {
-            return null;
-        }
-    }
-
-    public boolean[] getIssuerUniqueID()
-    {
-        DERBitString    id = c.getTBSCertificate().getIssuerUniqueId();
-
-        if (id != null)
-        {
-            byte[]          bytes = id.getBytes();
-            boolean[]       boolId = new boolean[bytes.length * 8 - id.getPadBits()];
-
-            for (int i = 0; i != boolId.length; i++)
-            {
-                boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
-            }
-
-            return boolId;
-        }
-            
-        return null;
-    }
-
-    public boolean[] getSubjectUniqueID()
-    {
-        DERBitString    id = c.getTBSCertificate().getSubjectUniqueId();
-
-        if (id != null)
-        {
-            byte[]          bytes = id.getBytes();
-            boolean[]       boolId = new boolean[bytes.length * 8 - id.getPadBits()];
-
-            for (int i = 0; i != boolId.length; i++)
-            {
-                boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
-            }
-
-            return boolId;
-        }
-            
-        return null;
-    }
-
-    public boolean[] getKeyUsage()
-    {
-        byte[]  bytes = this.getExtensionBytes("2.5.29.15");
-        int     length = 0;
-
-        if (bytes != null)
-        {
-            try
-            {
-                DERInputStream  dIn = new DERInputStream(new ByteArrayInputStream(bytes));
-                DERBitString    bits = (DERBitString)dIn.readObject();
-
-                bytes = bits.getBytes();
-                length = (bytes.length * 8) - bits.getPadBits();
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException("error processing key usage extension");
-            }
-
-            boolean[]       keyUsage = new boolean[(length < 9) ? 9 : length];
-
-            for (int i = 0; i != length; i++)
-            {
-                keyUsage[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
-            }
-
-            return keyUsage;
-        }
-
-        return null;
-    }
-
-    public int getBasicConstraints()
-    {
-        byte[]  bytes = this.getExtensionBytes("2.5.29.19");
-
-        if (bytes != null)
-        {
-            try
-            {
-                DERInputStream  dIn = new DERInputStream(new ByteArrayInputStream(bytes));
-                ASN1Sequence    seq = (ASN1Sequence)dIn.readObject();
-
-                if (seq.size() == 2)
-                {
-                    if (((DERBoolean)seq.getObjectAt(0)).isTrue())
-                    {
-                        return ((DERInteger)seq.getObjectAt(1)).getValue().intValue();
-                    }
-                    else
-                    {
-                        return -1;
-                    }
-                }
-                else if (seq.size() == 1)
-                {
-                    if (seq.getObjectAt(0) instanceof DERBoolean)
-                    {
-                        if (((DERBoolean)seq.getObjectAt(0)).isTrue())
-                        {
-                            return Integer.MAX_VALUE;
-                        }
-                        else
-                        {
-                            return -1;
-                        }
-                    }
-                    else
-                    {
-                        return -1;
-                    }
-                }
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException("error processing key usage extension");
-            }
-        }
-
-        return -1;
-    }
-
-    public Set getCriticalExtensionOIDs() 
-    {
-        if (this.getVersion() == 3)
-        {
-            HashSet         set = new HashSet();
-            X509Extensions  extensions = c.getTBSCertificate().getExtensions();
-
-            if (extensions != null)
-            {
-                Enumeration     e = extensions.oids();
-
-                while (e.hasMoreElements())
-                {
-                    DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
-                    X509Extension       ext = extensions.getExtension(oid);
-
-                    if (ext.isCritical())
-                    {
-                        set.add(oid.getId());
-                    }
-                }
-
-                return set;
-            }
-        }
-
-        return null;
-    }
-
-    private byte[] getExtensionBytes(String oid)
-    {
-        X509Extensions exts = c.getTBSCertificate().getExtensions();
-
-        if (exts != null)
-        {
-            X509Extension   ext = exts.getExtension(new DERObjectIdentifier(oid));
-            if (ext != null)
-            {
-                return ext.getValue().getOctets();
-            }
-        }
-
-        return null;
-    }
-
-    public byte[] getExtensionValue(String oid) 
-    {
-        X509Extensions exts = c.getTBSCertificate().getExtensions();
-
-        if (exts != null)
-        {
-            X509Extension   ext = exts.getExtension(new DERObjectIdentifier(oid));
-
-            if (ext != null)
-            {
-                ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
-                DEROutputStream            dOut = new DEROutputStream(bOut);
-                
-                try
-                {
-                    dOut.writeObject(ext.getValue());
-
-                    return bOut.toByteArray();
-                }
-                catch (Exception e)
-                {
-                    throw new RuntimeException("error encoding " + e.toString());
-                }
-            }
-        }
-
-        return null;
-    }
-
-    public Set getNonCriticalExtensionOIDs() 
-    {
-        if (this.getVersion() == 3)
-        {
-            HashSet         set = new HashSet();
-            X509Extensions  extensions = c.getTBSCertificate().getExtensions();
-
-            if (extensions != null)
-            {
-                Enumeration     e = extensions.oids();
-
-                while (e.hasMoreElements())
-                {
-                    DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
-                    X509Extension       ext = extensions.getExtension(oid);
-
-                    if (!ext.isCritical())
-                    {
-                        set.add(oid.getId());
-                    }
-                }
-
-                return set;
-            }
-        }
-
-        return null;
-    }
-
-    public boolean hasUnsupportedCriticalExtension()
-    {
-        if (this.getVersion() == 3)
-        {
-            X509Extensions  extensions = c.getTBSCertificate().getExtensions();
-
-            if (extensions != null)
-            {
-                Enumeration     e = extensions.oids();
-
-                while (e.hasMoreElements())
-                {
-                    DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
-                    if (oid.getId().equals("2.5.29.15")
-                       || oid.getId().equals("2.5.29.19"))
-                    {
-                        continue;
-                    }
-
-                    X509Extension       ext = extensions.getExtension(oid);
-
-                    if (ext.isCritical())
-                    {
-                        return true;
-                    }
-                }
-            }
-        }
-
-        return false;
-    }
-
-    public PublicKey getPublicKey()
-    {
-        return JDKKeyFactory.createPublicKeyFromPublicKeyInfo(c.getSubjectPublicKeyInfo());
-    }
-
-    public byte[] getEncoded()
-        throws CertificateEncodingException
-    {
-        ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
-        DEROutputStream         dOut = new DEROutputStream(bOut);
-
-        try
-        {
-            dOut.writeObject(c);
-
-            return bOut.toByteArray();
-        }
-        catch (IOException e)
-        {
-            throw new CertificateEncodingException(e.toString());
-        }
-    }
-
-    public void setBagAttribute(
-        DERObjectIdentifier oid,
-        DEREncodable        attribute)
-    {
-        pkcs12Attributes.put(oid, attribute);
-        pkcs12Ordering.addElement(oid);
-    }
-
-    public DEREncodable getBagAttribute(
-        DERObjectIdentifier oid)
-    {
-        return (DEREncodable)pkcs12Attributes.get(oid);
-    }
-
-    public Enumeration getBagAttributeKeys()
-    {
-        return pkcs12Ordering.elements();
-    }
-
-    public String toString()
-    {
-        StringBuffer    buf = new StringBuffer();
-        String          nl = System.getProperty("line.separator");
-
-        buf.append("  [0]         Version: " + this.getVersion() + nl);
-        buf.append("         SerialNumber: " + this.getSerialNumber() + nl);
-        buf.append("             IssuerDN: " + this.getIssuerDN() + nl);
-        buf.append("           Start Date: " + this.getNotBefore() + nl);
-        buf.append("           Final Date: " + this.getNotAfter() + nl);
-        buf.append("            SubjectDN: " + this.getSubjectDN() + nl);
-        buf.append("           Public Key: " + this.getPublicKey() + nl);
-        buf.append("  Signature Algorithm: " + this.getSigAlgName() + nl);
-
-        byte[]  sig = this.getSignature();
-
-        buf.append("            Signature: " + new String(Hex.encode(sig, 0, 20)) + nl);
-        for (int i = 20; i < sig.length; i += 20)
-        {
-            if (i < sig.length - 20)
-            {
-                buf.append("                       " + new String(Hex.encode(sig, i, 20)) + nl);
-            }
-            else
-            {
-                buf.append("                       " + new String(Hex.encode(sig, i, sig.length - i)) + nl);
-            }
-        }
-
-        X509Extensions  extensions = c.getTBSCertificate().getExtensions();
-
-        if (extensions != null)
-        {
-            Enumeration     e = extensions.oids();
-
-            if (e.hasMoreElements())
-            {
-                buf.append("       Extensions: \n");
-            }
-
-            while (e.hasMoreElements())
-            {
-                DERObjectIdentifier     oid = (DERObjectIdentifier)e.nextElement();
-                X509Extension           ext = extensions.getExtension(oid);
-
-                if (ext.getValue() != null)
-                {
-                    byte[]                  octs = ext.getValue().getOctets();
-                    ByteArrayInputStream    bIn = new ByteArrayInputStream(octs);
-                    DERInputStream          dIn = new DERInputStream(bIn);
-                    buf.append("                       critical(" + ext.isCritical() + ") ");
-                    try
-                    {
-                        if (oid.equals(X509Extensions.BasicConstraints))
-                        {
-                            buf.append(new BasicConstraints((ASN1Sequence)dIn.readObject()) + nl);
-                        }
-                        else if (oid.equals(X509Extensions.KeyUsage))
-                        {
-                            buf.append(new KeyUsage((DERBitString)dIn.readObject()) + nl);
-                        }
-                        else if (oid.equals(MiscObjectIdentifiers.netscapeCertType))
-                        {
-                            buf.append(new NetscapeCertType((DERBitString)dIn.readObject()) + nl);
-                        }
-                        else if (oid.equals(MiscObjectIdentifiers.netscapeRevocationURL))
-                        {
-                            buf.append(new NetscapeRevocationURL((DERIA5String)dIn.readObject()) + nl);
-                        }
-                        else if (oid.equals(MiscObjectIdentifiers.verisignCzagExtension))
-                        {
-                            buf.append(new VerisignCzagExtension((DERIA5String)dIn.readObject()) + nl);
-                        }
-                        else 
-                        {
-                            buf.append(oid.getId());
-                            buf.append(" value = " + ASN1Dump.dumpAsString(dIn.readObject()) + nl);
-                            //buf.append(" value = " + "*****" + nl);
-                        }
-                    }
-                    catch (Exception ex)
-                    {
-                        buf.append(oid.getId());
-                   //     buf.append(" value = " + new String(Hex.encode(ext.getValue().getOctets())) + nl);
-                        buf.append(" value = " + "*****" + nl);
-                    }
-                }
-                else
-                {
-                    buf.append(nl);
-                }
-            }
-        }
-
-        return buf.toString();
-    }
-
-    public final void verify(
-        PublicKey   key)
-        throws CertificateException, NoSuchAlgorithmException,
-        InvalidKeyException, NoSuchProviderException, SignatureException
-    {
-        Signature   signature = null;
-
-        if (!c.getSignatureAlgorithm().equals(c.getTBSCertificate().getSignature()))
-        {
-            throw new CertificateException("signature algorithm in TBS cert not same as outer cert");
-        }
-
-        try
-        {
-            signature = Signature.getInstance(c.getSignatureAlgorithm().getObjectId().getId(), BouncyCastleProvider.PROVIDER_NAME);
-        }
-        catch (Exception e)
-        {
-            signature = Signature.getInstance(c.getSignatureAlgorithm().getObjectId().getId());
-        }
-
-        signature.initVerify(key);
-
-        signature.update(this.getTBSCertificate());
-
-        if (!signature.verify(this.getSignature()))
-        {
-            throw new InvalidKeyException("Public key presented not for certificate signature");
-        }
-    }
-
-    public final void verify(
-        PublicKey   key,
-        String      sigProvider)
-        throws CertificateException, NoSuchAlgorithmException,
-        InvalidKeyException, NoSuchProviderException, SignatureException
-    {
-        Signature signature = Signature.getInstance(c.getSignatureAlgorithm().getObjectId().getId(), sigProvider);
-
-        signature.initVerify(key);
-
-        signature.update(this.getTBSCertificate());
-
-        if (!signature.verify(this.getSignature()))
-        {
-            throw new InvalidKeyException("Public key presented not for certificate signature");
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/ECKeySpec.java b/azureus2/src/org/bouncycastle/jce/spec/ECKeySpec.java
deleted file mode 100644
index 28ac5dd..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/ECKeySpec.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.security.spec.KeySpec;
-
-/**
- * base class for an Elliptic Curve Key Spec
- */
-public class ECKeySpec
-    implements KeySpec
-{
-	private ECParameterSpec     spec;
-
-	protected ECKeySpec(
-        ECParameterSpec spec)
-	{
-		this.spec = spec;
-	}
-
-    /**
-     * return the domain parameters for the curve
-     */
-    public ECParameterSpec getParams()
-    {
-        return spec;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java b/azureus2/src/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java
deleted file mode 100644
index 0e5148c..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/ECNamedCurveParameterSpec.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * specification signifying that the curve parameters can also be
- * refered to by name.
- */
-public class ECNamedCurveParameterSpec
-	extends ECParameterSpec
-{
-    private String  name;
-
-	public ECNamedCurveParameterSpec(
-        String      name,
-		ECCurve     curve,
-		ECPoint     G,
-		BigInteger  n)
-	{
-        super(curve, G, n);
-
-        this.name = name;
-	}
-
-	public ECNamedCurveParameterSpec(
-        String      name,
-		ECCurve     curve,
-		ECPoint     G,
-		BigInteger  n,
-        BigInteger  h)
-	{
-        super(curve, G, n, h);
-
-        this.name = name;
-	}
-
-	public ECNamedCurveParameterSpec(
-        String      name,
-		ECCurve     curve,
-		ECPoint     G,
-		BigInteger  n,
-        BigInteger  h,
-        byte[]      seed)
-	{
-        super(curve, G, n, h, seed);
-
-        this.name = name;
-	}
-
-    /**
-     * return the name of the curve the EC domain parameters belong to.
-     */
-	public String getName()
-	{
-		return name;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/ECParameterSpec.java b/azureus2/src/org/bouncycastle/jce/spec/ECParameterSpec.java
deleted file mode 100644
index 1326793..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/ECParameterSpec.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.math.BigInteger;
-import java.security.spec.AlgorithmParameterSpec;
-
-import org.bouncycastle.math.ec.ECCurve;
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * basic domain parameters for an Elliptic Curve public or private key.
- */
-public class ECParameterSpec
-	implements AlgorithmParameterSpec
-{
-	private ECCurve     curve;
-	private byte[]      seed;
-	private ECPoint     G;
-	private BigInteger  n;
-	private BigInteger  h;
-
-	public ECParameterSpec(
-		ECCurve     curve,
-		ECPoint     G,
-		BigInteger  n)
-	{
-		this.curve = curve;
-		this.G = G;
-		this.n = n;
-        this.h = BigInteger.valueOf(1);
-        this.seed = null;
-	}
-
-	public ECParameterSpec(
-		ECCurve     curve,
-		ECPoint     G,
-		BigInteger  n,
-        BigInteger  h)
-	{
-		this.curve = curve;
-		this.G = G;
-		this.n = n;
-		this.h = h;
-        this.seed = null;
-	}
-
-	public ECParameterSpec(
-		ECCurve     curve,
-		ECPoint     G,
-		BigInteger  n,
-        BigInteger  h,
-        byte[]      seed)
-	{
-		this.curve = curve;
-		this.G = G;
-		this.n = n;
-		this.h = h;
-		this.seed = seed;
-	}
-
-    /**
-     * return the curve along which the base point lies.
-     */
-    public ECCurve getCurve()
-    {
-        return curve;
-    }
-
-    /**
-     * return the base point we are using for these domain parameters.
-     */
-	public ECPoint getG()
-	{
-		return G;
-	}
-
-    /**
-     * return the order N of G
-     */
-	public BigInteger getN()
-	{
-		return n;
-	}
-
-    /**
-     * return the cofactor H to the order of G.
-     */
-	public BigInteger getH()
-	{
-		return h;
-	}
-
-    /**
-     * return the seed used to generate this curve (if available).
-     */
-	public byte[] getSeed()
-	{
-		return seed;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/ECPrivateKeySpec.java b/azureus2/src/org/bouncycastle/jce/spec/ECPrivateKeySpec.java
deleted file mode 100644
index 8a44018..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/ECPrivateKeySpec.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.math.BigInteger;
-
-/**
- * Elliptic Curve private key specification.
- */
-public class ECPrivateKeySpec
-    extends ECKeySpec
-{
-    private BigInteger    d;
-
-    /**
-     * base constructor
-     *
-     * @param d the private number for the key.
-     * @param spec the domain parameters for the curve being used.
-     */
-	public ECPrivateKeySpec(
-        BigInteger      d,
-		ECParameterSpec spec)
-	{
-		super(spec);
-
-        this.d = d;
-	}
-
-    /**
-     * return the private number D
-     */
-    public BigInteger getD()
-    {
-        return d;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/ECPublicKeySpec.java b/azureus2/src/org/bouncycastle/jce/spec/ECPublicKeySpec.java
deleted file mode 100644
index 532f065..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/ECPublicKeySpec.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import org.bouncycastle.math.ec.ECPoint;
-
-/**
- * Elliptic Curve public key specification
- */
-public class ECPublicKeySpec
-    extends ECKeySpec
-{
-    private ECPoint    q;
-
-    /**
-     * base constructor
-     *
-     * @param q the public point on the curve.
-     * @param spec the domain parameters for the curve.
-     */
-	public ECPublicKeySpec(
-        ECPoint         q,
-		ECParameterSpec spec)
-	{
-		super(spec);
-
-        this.q = q;
-	}
-
-    /**
-     * return the public point q
-     */
-    public ECPoint getQ()
-    {
-        return q;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/ElGamalGenParameterSpec.java b/azureus2/src/org/bouncycastle/jce/spec/ElGamalGenParameterSpec.java
deleted file mode 100644
index 200d2b4..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/ElGamalGenParameterSpec.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.security.spec.AlgorithmParameterSpec;
-
-public class ElGamalGenParameterSpec
-    implements AlgorithmParameterSpec
-{
-    private int primeSize;
-
-    /*
-     * @param primeSize the size (in bits) of the prime modulus.
-     */
-    public ElGamalGenParameterSpec(
-        int     primeSize)
-    {
-        this.primeSize = primeSize;
-    }
-
-    /**
-     * Returns the size in bits of the prime modulus.
-     *
-     * @return the size in bits of the prime modulus
-     */
-    public int getPrimeSize()
-    {
-        return primeSize;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/ElGamalKeySpec.java b/azureus2/src/org/bouncycastle/jce/spec/ElGamalKeySpec.java
deleted file mode 100644
index 5e3eb66..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/ElGamalKeySpec.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.security.spec.KeySpec;
-
-public class ElGamalKeySpec
-    implements KeySpec
-{
-    private ElGamalParameterSpec  spec;
-
-    public ElGamalKeySpec(
-        ElGamalParameterSpec  spec)
-    {
-        this.spec = spec;
-    }
-
-    public ElGamalParameterSpec getParams()
-    {
-        return spec;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/ElGamalParameterSpec.java b/azureus2/src/org/bouncycastle/jce/spec/ElGamalParameterSpec.java
deleted file mode 100644
index 10ed1c5..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/ElGamalParameterSpec.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.math.BigInteger;
-import java.security.spec.AlgorithmParameterSpec;
-
-public class ElGamalParameterSpec
-    implements AlgorithmParameterSpec
-{
-    private BigInteger  p;
-    private BigInteger  g;
-
-    /**
-     * Constructs a parameter set for Diffie-Hellman, using a prime modulus
-     * <code>p</code> and a base generator <code>g</code>.
-     * 
-     * @param p the prime modulus
-     * @param g the base generator
-     */
-    public ElGamalParameterSpec(
-        BigInteger  p,
-        BigInteger  g)
-    {
-        this.p = p;
-        this.g = g;
-    }
-
-    /**
-     * Returns the prime modulus <code>p</code>.
-     *
-     * @return the prime modulus <code>p</code>
-     */
-    public BigInteger getP()
-    {
-        return p;
-    }
-
-    /**
-     * Returns the base generator <code>g</code>.
-     *
-     * @return the base generator <code>g</code>
-     */
-    public BigInteger getG()
-    {
-        return g;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/ElGamalPrivateKeySpec.java b/azureus2/src/org/bouncycastle/jce/spec/ElGamalPrivateKeySpec.java
deleted file mode 100644
index 3a3c6e4..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/ElGamalPrivateKeySpec.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.math.BigInteger;
-
-/**
- * This class specifies an ElGamal private key with its associated parameters.
- *
- * @see ElGamalPublicKeySpec
- */
-public class ElGamalPrivateKeySpec
-    extends ElGamalKeySpec
-{
-    private BigInteger  x;
-
-    public ElGamalPrivateKeySpec(
-        BigInteger              x,
-        ElGamalParameterSpec    spec)
-    {
-        super(spec);
-
-        this.x = x;
-    }
-
-    /**
-     * Returns the private value <code>x</code>.
-     *
-     * @return the private value <code>x</code>
-     */
-    public BigInteger getX()
-    {
-        return x;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/ElGamalPublicKeySpec.java b/azureus2/src/org/bouncycastle/jce/spec/ElGamalPublicKeySpec.java
deleted file mode 100644
index c0e6dba..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/ElGamalPublicKeySpec.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.math.BigInteger;
-
-/**
- * This class specifies an ElGamal public key with its associated parameters.
- *
- * @see ElGamalPrivateKeySpec
- */
-public class ElGamalPublicKeySpec
-    extends ElGamalKeySpec
-{
-    private BigInteger  y;
-
-    public ElGamalPublicKeySpec(
-        BigInteger              y,
-        ElGamalParameterSpec    spec)
-    {
-        super(spec);
-
-        this.y = y;
-    }
-
-    /**
-     * Returns the public value <code>y</code>.
-     *
-     * @return the public value <code>y</code>
-     */
-    public BigInteger getY()
-    {
-        return y;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/IEKeySpec.java b/azureus2/src/org/bouncycastle/jce/spec/IEKeySpec.java
deleted file mode 100644
index 9859a22..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/IEKeySpec.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.spec.KeySpec;
-
-import org.bouncycastle.jce.interfaces.IESKey;
-
-/**
- * key pair for use with an integrated encryptor - together
- * they provide what's required to generate the message.
- */
-public class IEKeySpec
-    implements KeySpec, IESKey
-{
-    private PublicKey   pubKey;
-    private PrivateKey  privKey;
-
-    /**
-     * @param privKey our private key.
-     * @param pubKey the public key of the sender/recipient.
-     */
-    public IEKeySpec(
-        PrivateKey  privKey,
-        PublicKey   pubKey)
-    {
-        this.privKey = privKey;
-        this.pubKey = pubKey;
-    }
-
-    /**
-     * return the intended recipient's/sender's public key.
-     */
-    public PublicKey getPublic()
-    {
-        return pubKey;
-    }
-
-    /**
-     * return the local private key.
-     */
-    public PrivateKey getPrivate()
-    {
-        return privKey;
-    }
-
-    /**
-     * return "IES"
-     */
-    public String getAlgorithm()
-    {
-        return "IES";
-    }
-
-    /**
-     * return null
-     */
-    public String getFormat()
-    {
-        return null;
-    }
-
-    /**
-     * returns null
-     */
-    public byte[] getEncoded()
-    {
-        return null;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/jce/spec/IESParameterSpec.java b/azureus2/src/org/bouncycastle/jce/spec/IESParameterSpec.java
deleted file mode 100644
index 97c7d3a..0000000
--- a/azureus2/src/org/bouncycastle/jce/spec/IESParameterSpec.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bouncycastle.jce.spec;
-
-import java.security.spec.AlgorithmParameterSpec;
-
-/**
- * Parameter spec for an integrated encryptor, as in IEEE P1363a
- */
-public class IESParameterSpec
-    implements AlgorithmParameterSpec
-{
-    private byte[]  derivation;
-    private byte[]  encoding;
-    private int     macKeySize;
-
-    public IESParameterSpec(
-        byte[]  derivation,
-        byte[]  encoding,
-        int     macKeySize)
-    {
-        this.derivation = new byte[derivation.length];
-        System.arraycopy(derivation, 0, this.derivation, 0, derivation.length);
-
-        this.encoding = new byte[encoding.length];
-        System.arraycopy(encoding, 0, this.encoding, 0, encoding.length);
-
-        this.macKeySize = macKeySize;           
-    }
-
-    /**
-     * return the derivation vector.
-     */
-    public byte[] getDerivationV()
-    {
-        return derivation;
-    }
-
-    /**
-     * return the encoding vector.
-     */
-    public byte[] getEncodingV()
-    {
-        return encoding;
-    }
-
-    /**
-     * return the key size in bits for the MAC used with the message
-     */
-    public int getMacKeySize()
-    {
-        return macKeySize;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/ECConstants.java b/azureus2/src/org/bouncycastle/math/ec/ECConstants.java
deleted file mode 100644
index 864f746..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/ECConstants.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-public interface ECConstants
-{
-    public static final BigInteger ZERO = BigInteger.valueOf(0);
-    public static final BigInteger ONE = BigInteger.valueOf(1);
-    public static final BigInteger TWO = BigInteger.valueOf(2);
-    public static final BigInteger THREE = BigInteger.valueOf(3);
-    public static final BigInteger FOUR = BigInteger.valueOf(4);
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/ECCurve.java b/azureus2/src/org/bouncycastle/math/ec/ECCurve.java
deleted file mode 100644
index 4db07d5..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/ECCurve.java
+++ /dev/null
@@ -1,660 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-import java.util.Random;
-
-/**
- * base class for an elliptic curve
- */
-public abstract class ECCurve
-{
-    ECFieldElement a, b;
-
-    public abstract int getFieldSize();
-
-    public abstract ECFieldElement fromBigInteger(BigInteger x);
-
-    public abstract ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression);
-
-    public abstract ECPoint decodePoint(byte[] encoded);
-
-    public abstract ECPoint getInfinity();
-
-    public ECFieldElement getA()
-    {
-        return a;
-    }
-
-    public ECFieldElement getB()
-    {
-        return b;
-    }
-
-    /**
-     * Elliptic curve over Fp
-     */
-    public static class Fp extends ECCurve
-    {
-        BigInteger q;
-        ECPoint.Fp infinity;
-
-        public Fp(BigInteger q, BigInteger a, BigInteger b)
-        {
-            this.q = q;
-            this.a = fromBigInteger(a);
-            this.b = fromBigInteger(b);
-            this.infinity = new ECPoint.Fp(this, null, null);
-        }
-
-        public BigInteger getQ()
-        {
-            return q;
-        }
-
-        public int getFieldSize()
-        {
-            return q.bitLength();
-        }
-
-        public ECFieldElement fromBigInteger(BigInteger x)
-        {
-            return new ECFieldElement.Fp(this.q, x);
-        }
-
-        public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
-        {
-            return new ECPoint.Fp(this, fromBigInteger(x), fromBigInteger(y), withCompression);
-        }
-
-        /**
-         * Decode a point on this curve from its ASN.1 encoding. The different
-         * encodings are taken account of, including point compression for
-         * <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17).
-         * @return The decoded point.
-         */
-        public ECPoint decodePoint(byte[] encoded)
-        {
-            ECPoint p = null;
-
-            switch (encoded[0])
-            {
-                // infinity
-            case 0x00:
-                p = getInfinity();
-                break;
-                // compressed
-            case 0x02:
-            case 0x03:
-                int ytilde = encoded[0] & 1;
-                byte[]  i = new byte[encoded.length - 1];
-
-                System.arraycopy(encoded, 1, i, 0, i.length);
-
-                ECFieldElement x = new ECFieldElement.Fp(this.q, new BigInteger(1, i));
-                ECFieldElement alpha = x.multiply(x.square().add(a)).add(b);
-                ECFieldElement beta = alpha.sqrt();
-
-                //
-                // if we can't find a sqrt we haven't got a point on the
-                // curve - run!
-                //
-                if (beta == null)
-                {
-                    throw new RuntimeException("Invalid point compression");
-                }
-
-                int bit0 = (beta.toBigInteger().testBit(0) ? 1 : 0);
-
-                if (bit0 == ytilde)
-                {
-                    p = new ECPoint.Fp(this, x, beta, true);
-                }
-                else
-                {
-                    p = new ECPoint.Fp(this, x,
-                        new ECFieldElement.Fp(this.q, q.subtract(beta.toBigInteger())), true);
-                }
-                break;
-                // uncompressed
-            case 0x04:
-                // hybrid
-            case 0x06:
-            case 0x07:
-                byte[]  xEnc = new byte[(encoded.length - 1) / 2];
-                byte[]  yEnc = new byte[(encoded.length - 1) / 2];
-
-                System.arraycopy(encoded, 1, xEnc, 0, xEnc.length);
-                System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length);
-
-                p = new ECPoint.Fp(this,
-                        new ECFieldElement.Fp(this.q, new BigInteger(1, xEnc)),
-                        new ECFieldElement.Fp(this.q, new BigInteger(1, yEnc)));
-                break;
-            default:
-                throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16));
-            }
-
-            return p;
-        }
-
-        public ECPoint getInfinity()
-        {
-            return infinity;
-        }
-
-        public boolean equals(
-            Object anObject) 
-        {
-            if (anObject == this) 
-            {
-                return true;
-            }
-
-            if (!(anObject instanceof ECCurve.Fp)) 
-            {
-                return false;
-            }
-
-            ECCurve.Fp other = (ECCurve.Fp) anObject;
-
-            return this.q.equals(other.q) 
-                    && a.equals(other.a) && b.equals(other.b);
-        }
-
-        public int hashCode() 
-        {
-            return a.hashCode() ^ b.hashCode() ^ q.hashCode();
-        }
-    }
-
-    /**
-     * Elliptic curves over F2m. The Weierstrass equation is given by
-     * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
-     */
-    public static class F2m extends ECCurve
-    {
-        /**
-         * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
-         */
-        private int m;  // can't be final - JDK 1.1
-
-        /**
-         * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
-         * x<sup>k</sup> + 1</code> represents the reduction polynomial
-         * <code>f(z)</code>.<br>
-         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.<br>
-         */
-        private int k1;  // can't be final - JDK 1.1
-
-        /**
-         * TPB: Always set to <code>0</code><br>
-         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.<br>
-         */
-        private int k2;  // can't be final - JDK 1.1
-
-        /**
-         * TPB: Always set to <code>0</code><br>
-         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.<br>
-         */
-        private int k3;  // can't be final - JDK 1.1
-
-        /**
-         * The order of the base point of the curve.
-         */
-        private BigInteger n;  // can't be final - JDK 1.1
-
-        /**
-         * The cofactor of the curve.
-         */
-        private BigInteger h;  // can't be final - JDK 1.1
-        
-         /**
-         * The point at infinity on this curve.
-         */
-        private ECPoint.F2m infinity;  // can't be final - JDK 1.1
-
-        /**
-         * The parameter <code>μ</code> of the elliptic curve if this is
-         * a Koblitz curve.
-         */
-        private byte mu = 0;
-
-        /**
-         * The auxiliary values <code>s<sub>0</sub></code> and
-         * <code>s<sub>1</sub></code> used for partial modular reduction for
-         * Koblitz curves.
-         */
-        private BigInteger[] si = null;
-
-        /**
-         * Constructor for Trinomial Polynomial Basis (TPB).
-         * @param m  The exponent <code>m</code> of
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
-         * x<sup>k</sup> + 1</code> represents the reduction
-         * polynomial <code>f(z)</code>.
-         * @param a The coefficient <code>a</code> in the Weierstrass equation
-         * for non-supersingular elliptic curves over
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param b The coefficient <code>b</code> in the Weierstrass equation
-         * for non-supersingular elliptic curves over
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         */
-        public F2m(
-            int m,
-            int k,
-            BigInteger a,
-            BigInteger b)
-        {
-            this(m, k, 0, 0, a, b, null, null);
-        }
-
-        /**
-         * Constructor for Trinomial Polynomial Basis (TPB).
-         * @param m  The exponent <code>m</code> of
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
-         * x<sup>k</sup> + 1</code> represents the reduction
-         * polynomial <code>f(z)</code>.
-         * @param a The coefficient <code>a</code> in the Weierstrass equation
-         * for non-supersingular elliptic curves over
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param b The coefficient <code>b</code> in the Weierstrass equation
-         * for non-supersingular elliptic curves over
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param n The order of the main subgroup of the elliptic curve.
-         * @param h The cofactor of the elliptic curve, i.e.
-         * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
-         */
-        public F2m(
-            int m, 
-            int k, 
-            BigInteger a, 
-            BigInteger b,
-            BigInteger n,
-            BigInteger h)
-        {
-            this(m, k, 0, 0, a, b, n, h);
-        }
-
-        /**
-         * Constructor for Pentanomial Polynomial Basis (PPB).
-         * @param m  The exponent <code>m</code> of
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.
-         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.
-         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.
-         * @param a The coefficient <code>a</code> in the Weierstrass equation
-         * for non-supersingular elliptic curves over
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param b The coefficient <code>b</code> in the Weierstrass equation
-         * for non-supersingular elliptic curves over
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         */
-        public F2m(
-            int m,
-            int k1,
-            int k2,
-            int k3,
-            BigInteger a,
-            BigInteger b)
-        {
-            this(m, k1, k2, k3, a, b, null, null);
-        }
-
-        /**
-         * Constructor for Pentanomial Polynomial Basis (PPB).
-         * @param m  The exponent <code>m</code> of
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.
-         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.
-         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.
-         * @param a The coefficient <code>a</code> in the Weierstrass equation
-         * for non-supersingular elliptic curves over
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param b The coefficient <code>b</code> in the Weierstrass equation
-         * for non-supersingular elliptic curves over
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param n The order of the main subgroup of the elliptic curve.
-         * @param h The cofactor of the elliptic curve, i.e.
-         * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
-         */
-        public F2m(
-            int m, 
-            int k1, 
-            int k2, 
-            int k3,
-            BigInteger a, 
-            BigInteger b,
-            BigInteger n,
-            BigInteger h)
-        {
-            this.m = m;
-            this.k1 = k1;
-            this.k2 = k2;
-            this.k3 = k3;
-            this.n = n;
-            this.h = h;
-
-            if (k1 == 0)
-            {
-                throw new IllegalArgumentException("k1 must be > 0");
-            }
-
-            if (k2 == 0)
-            {
-                if (k3 != 0)
-                {
-                    throw new IllegalArgumentException("k3 must be 0 if k2 == 0");
-                }
-            }
-            else
-            {
-                if (k2 <= k1)
-                {
-                    throw new IllegalArgumentException("k2 must be > k1");
-                }
-
-                if (k3 <= k2)
-                {
-                    throw new IllegalArgumentException("k3 must be > k2");
-                }
-            }
-
-            this.a = fromBigInteger(a);
-            this.b = fromBigInteger(b);
-            this.infinity = new ECPoint.F2m(this, null, null);
-        }
-
-        public int getFieldSize()
-        {
-            return m;
-        }
-
-        public ECFieldElement fromBigInteger(BigInteger x)
-        {
-            return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x);
-        }
-
-        public ECPoint createPoint(BigInteger x, BigInteger y, boolean withCompression)
-        {
-            return new ECPoint.F2m(this, fromBigInteger(x), fromBigInteger(y), withCompression);
-        }
-
-        /* (non-Javadoc)
-         * @see org.bouncycastle.math.ec.ECCurve#decodePoint(byte[])
-         */
-        public ECPoint decodePoint(byte[] encoded)
-        {
-            ECPoint p = null;
-
-            switch (encoded[0])
-            {
-                // infinity
-            case 0x00:
-                p = getInfinity();
-                break;
-                // compressed
-            case 0x02:
-            case 0x03:
-                byte[] enc = new byte[encoded.length - 1];
-                System.arraycopy(encoded, 1, enc, 0, enc.length);
-                if (encoded[0] == 0x02) 
-                {
-                        p = decompressPoint(enc, 0);
-                }
-                else 
-                {
-                        p = decompressPoint(enc, 1);
-                }
-                break;
-                // uncompressed
-            case 0x04:
-                // hybrid
-            case 0x06:
-            case 0x07:
-                byte[] xEnc = new byte[(encoded.length - 1) / 2];
-                byte[] yEnc = new byte[(encoded.length - 1) / 2];
-
-                System.arraycopy(encoded, 1, xEnc, 0, xEnc.length);
-                System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length);
-
-                p = new ECPoint.F2m(this,
-                    new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3,
-                        new BigInteger(1, xEnc)),
-                    new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3,
-                        new BigInteger(1, yEnc)), false);
-                break;
-
-            default:
-                throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16));
-            }
-
-            return p;
-        }
-
-        public ECPoint getInfinity()
-        {
-            return infinity;
-        }
-
-        /**
-         * Returns true if this is a Koblitz curve (ABC curve).
-         * @return true if this is a Koblitz curve (ABC curve), false otherwise
-         */
-        public boolean isKoblitz()
-        {
-            return ((n != null) && (h != null) &&
-                    ((a.toBigInteger().equals(ECConstants.ZERO)) ||
-                    (a.toBigInteger().equals(ECConstants.ONE))) &&
-                    (b.toBigInteger().equals(ECConstants.ONE)));
-        }
-
-        /**
-         * Returns the parameter <code>μ</code> of the elliptic curve.
-         * @return <code>μ</code> of the elliptic curve.
-         * @throws IllegalArgumentException if the given ECCurve is not a
-         * Koblitz curve.
-         */
-        synchronized byte getMu()
-        {
-            if (mu == 0)
-            {
-                mu = Tnaf.getMu(this);
-            }
-            return mu;
-        }
-
-        /**
-         * @return the auxiliary values <code>s<sub>0</sub></code> and
-         * <code>s<sub>1</sub></code> used for partial modular reduction for
-         * Koblitz curves.
-         */
-        synchronized BigInteger[] getSi()
-        {
-            if (si == null)
-            {
-                si = Tnaf.getSi(this);
-            }
-            return si;
-        }
-
-        /**
-         * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
-         * 
-         * @param xEnc
-         *            The encoding of field element xp.
-         * @param ypBit
-         *            ~yp, an indication bit for the decompression of yp.
-         * @return the decompressed point.
-         */
-        private ECPoint decompressPoint(
-            byte[] xEnc, 
-            int ypBit)
-        {
-            ECFieldElement xp = new ECFieldElement.F2m(
-                    this.m, this.k1, this.k2, this.k3, new BigInteger(1, xEnc));
-            ECFieldElement yp = null;
-            if (xp.toBigInteger().equals(ECConstants.ZERO))
-            {
-                yp = (ECFieldElement.F2m)b;
-                for (int i = 0; i < m - 1; i++)
-                {
-                    yp = yp.square();
-                }
-            }
-            else
-            {
-                ECFieldElement beta = xp.add(a).add(
-                        b.multiply(xp.square().invert()));
-                ECFieldElement z = solveQuadradicEquation(beta);
-                if (z == null)
-                {
-                    throw new RuntimeException("Invalid point compression");
-                }
-                int zBit = 0;
-                if (z.toBigInteger().testBit(0))
-                {
-                    zBit = 1;
-                }
-                if (zBit != ypBit)
-                {
-                    z = z.add(new ECFieldElement.F2m(this.m, this.k1, this.k2,
-                            this.k3, ECConstants.ONE));
-                }
-                yp = xp.multiply(z);
-            }
-            
-            return new ECPoint.F2m(this, xp, yp);
-        }
-        
-        /**
-         * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
-         * D.1.6) The other solution is <code>z + 1</code>.
-         * 
-         * @param beta
-         *            The value to solve the qradratic equation for.
-         * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
-         *         <code>null</code> if no solution exists.
-         */
-        private ECFieldElement solveQuadradicEquation(ECFieldElement beta)
-        {
-            ECFieldElement zeroElement = new ECFieldElement.F2m(
-                    this.m, this.k1, this.k2, this.k3, ECConstants.ZERO);
-
-            if (beta.toBigInteger().equals(ECConstants.ZERO))
-            {
-                return zeroElement;
-            }
-
-            ECFieldElement z = null;
-            ECFieldElement gamma = zeroElement;
-
-            Random rand = new Random();
-            do
-            {
-                ECFieldElement t = new ECFieldElement.F2m(this.m, this.k1,
-                        this.k2, this.k3, new BigInteger(m, rand));
-                z = zeroElement;
-                ECFieldElement w = beta;
-                for (int i = 1; i <= m - 1; i++)
-                {
-                    ECFieldElement w2 = w.square();
-                    z = z.square().add(w2.multiply(t));
-                    w = w2.add(beta);
-                }
-                if (!w.toBigInteger().equals(ECConstants.ZERO))
-                {
-                    return null;
-                }
-                gamma = z.square().add(z);
-            }
-            while (gamma.toBigInteger().equals(ECConstants.ZERO));
-
-            return z;
-        }
-        
-        public boolean equals(
-            Object anObject)
-        {
-            if (anObject == this) 
-            {
-                return true;
-            }
-
-            if (!(anObject instanceof ECCurve.F2m)) 
-            {
-                return false;
-            }
-
-            ECCurve.F2m other = (ECCurve.F2m)anObject;
-            
-            return (this.m == other.m) && (this.k1 == other.k1)
-                && (this.k2 == other.k2) && (this.k3 == other.k3)
-                && a.equals(other.a) && b.equals(other.b);
-        }
-
-        public int hashCode()
-        {
-            return this.a.hashCode() ^ this.b.hashCode() ^ m ^ k1 ^ k2 ^ k3;
-        }
-
-        public int getM()
-        {
-            return m;
-        }
-
-        /**
-         * Return true if curve uses a Trinomial basis.
-         * 
-         * @return true if curve Trinomial, false otherwise.
-         */
-        public boolean isTrinomial()
-        {
-            return k2 == 0 && k3 == 0;
-        }
-        
-        public int getK1()
-        {
-            return k1;
-        }
-
-        public int getK2()
-        {
-            return k2;
-        }
-
-        public int getK3()
-        {
-            return k3;
-        }
-
-        public BigInteger getN()
-        {
-            return n;
-        }
-
-        public BigInteger getH()
-        {
-            return h;
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/ECFieldElement.java b/azureus2/src/org/bouncycastle/math/ec/ECFieldElement.java
deleted file mode 100644
index b4b9b0a..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/ECFieldElement.java
+++ /dev/null
@@ -1,1194 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-import java.util.Random;
-
-public abstract class ECFieldElement
-    implements ECConstants
-{
-
-    public abstract BigInteger     toBigInteger();
-    public abstract String         getFieldName();
-    public abstract int            getFieldSize();
-    public abstract ECFieldElement add(ECFieldElement b);
-    public abstract ECFieldElement subtract(ECFieldElement b);
-    public abstract ECFieldElement multiply(ECFieldElement b);
-    public abstract ECFieldElement divide(ECFieldElement b);
-    public abstract ECFieldElement negate();
-    public abstract ECFieldElement square();
-    public abstract ECFieldElement invert();
-    public abstract ECFieldElement sqrt();
-
-    public String toString()
-    {
-        return this.toBigInteger().toString(2);
-    }
-
-    public static class Fp extends ECFieldElement
-    {
-        BigInteger x;
-
-        BigInteger q;
-        
-        public Fp(BigInteger q, BigInteger x)
-        {
-            this.x = x;
-            
-            if (x.compareTo(q) >= 0)
-            {
-                throw new IllegalArgumentException("x value too large in field element");
-            }
-
-            this.q = q;
-        }
-
-        public BigInteger toBigInteger()
-        {
-            return x;
-        }
-
-        /**
-         * return the field name for this field.
-         *
-         * @return the string "Fp".
-         */
-        public String getFieldName()
-        {
-            return "Fp";
-        }
-
-        public int getFieldSize()
-        {
-            return q.bitLength();
-        }
-
-        public BigInteger getQ()
-        {
-            return q;
-        }
-        
-        public ECFieldElement add(ECFieldElement b)
-        {
-            return new Fp(q, x.add(b.toBigInteger()).mod(q));
-        }
-
-        public ECFieldElement subtract(ECFieldElement b)
-        {
-            return new Fp(q, x.subtract(b.toBigInteger()).mod(q));
-        }
-
-        public ECFieldElement multiply(ECFieldElement b)
-        {
-            return new Fp(q, x.multiply(b.toBigInteger()).mod(q));
-        }
-
-        public ECFieldElement divide(ECFieldElement b)
-        {
-            return new Fp(q, x.multiply(b.toBigInteger().modInverse(q)).mod(q));
-        }
-
-        public ECFieldElement negate()
-        {
-            return new Fp(q, x.negate().mod(q));
-        }
-
-        public ECFieldElement square()
-        {
-            return new Fp(q, x.multiply(x).mod(q));
-        }
-
-        public ECFieldElement invert()
-        {
-            return new Fp(q, x.modInverse(q));
-        }
-
-        // D.1.4 91
-        /**
-         * return a sqrt root - the routine verifies that the calculation
-         * returns the right value - if none exists it returns null.
-         */
-        public ECFieldElement sqrt()
-        {
-            if (!q.testBit(0))
-            {
-                throw new RuntimeException("not done yet");
-            }
-
-            // p mod 4 == 3
-            if (q.testBit(1))
-            {
-                // z = g^(u+1) + p, p = 4u + 3
-                ECFieldElement z = new Fp(q, x.modPow(q.shiftRight(2).add(ONE), q));
-
-                return z.square().equals(this) ? z : null;
-            }
-
-            // p mod 4 == 1
-            BigInteger qMinusOne = q.subtract(ECConstants.ONE);
-
-            BigInteger legendreExponent = qMinusOne.shiftRight(1);
-            if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE)))
-            {
-                return null;
-            }
-
-            BigInteger u = qMinusOne.shiftRight(2);
-            BigInteger k = u.shiftLeft(1).add(ECConstants.ONE);
-
-            BigInteger Q = this.x;
-            BigInteger fourQ = Q.shiftLeft(2).mod(q);
-
-            BigInteger U, V;
-            Random rand = new Random();
-            do
-            {
-                BigInteger P;
-                do
-                {
-                    P = new BigInteger(q.bitLength(), rand);
-                }
-                while (P.compareTo(q) >= 0
-                    || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne)));
-
-                BigInteger[] result = lucasSequence(q, P, Q, k);
-                U = result[0];
-                V = result[1];
-
-                if (V.multiply(V).mod(q).equals(fourQ))
-                {
-                    // Integer division by 2, mod q
-                    if (V.testBit(0))
-                    {
-                        V = V.add(q);
-                    }
-
-                    V = V.shiftRight(1);
-
-                    //assert V.multiply(V).mod(q).equals(x);
-
-                    return new ECFieldElement.Fp(q, V);
-                }
-            }
-            while (U.equals(ECConstants.ONE) || U.equals(qMinusOne));
-
-            return null;
-
-//            BigInteger qMinusOne = q.subtract(ECConstants.ONE);
-//            BigInteger legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO);
-//            if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE)))
-//            {
-//                return null;
-//            }
-//
-//            Random rand = new Random();
-//            BigInteger fourX = x.shiftLeft(2);
-//
-//            BigInteger r;
-//            do
-//            {
-//                r = new BigInteger(q.bitLength(), rand);
-//            }
-//            while (r.compareTo(q) >= 0
-//                || !(r.multiply(r).subtract(fourX).modPow(legendreExponent, q).equals(qMinusOne)));
-//
-//            BigInteger n1 = qMinusOne.shiftRight(2); //.divide(ECConstants.FOUR);
-//            BigInteger n2 = n1.add(ECConstants.ONE); //q.add(ECConstants.THREE).divide(ECConstants.FOUR);
-//
-//            BigInteger wOne = WOne(r, x, q);
-//            BigInteger wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q);
-//            BigInteger twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r);
-//
-//            BigInteger root = twoR.modPow(q.subtract(ECConstants.TWO), q)
-//                .multiply(x).mod(q)
-//                .multiply(wSum).mod(q);
-//
-//            return new Fp(q, root);
-        }
-
-//        private static BigInteger W(BigInteger n, BigInteger wOne, BigInteger p)
-//        {
-//            if (n.equals(ECConstants.ONE))
-//            {
-//                return wOne;
-//            }
-//            boolean isEven = !n.testBit(0);
-//            n = n.shiftRight(1);//divide(ECConstants.TWO);
-//            if (isEven)
-//            {
-//                BigInteger w = W(n, wOne, p);
-//                return w.multiply(w).subtract(ECConstants.TWO).mod(p);
-//            }
-//            BigInteger w1 = W(n.add(ECConstants.ONE), wOne, p);
-//            BigInteger w2 = W(n, wOne, p);
-//            return w1.multiply(w2).subtract(wOne).mod(p);
-//        }
-//
-//        private BigInteger WOne(BigInteger r, BigInteger x, BigInteger p)
-//        {
-//            return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p);
-//        }
-
-        private static BigInteger[] lucasSequence(
-            BigInteger  p,
-            BigInteger  P,
-            BigInteger  Q,
-            BigInteger  k)
-        {
-            int n = k.bitLength();
-            int s = k.getLowestSetBit();
-
-            BigInteger Uh = ECConstants.ONE;
-            BigInteger Vl = ECConstants.TWO;
-            BigInteger Vh = P;
-            BigInteger Ql = ECConstants.ONE;
-            BigInteger Qh = ECConstants.ONE;
-
-            for (int j = n - 1; j >= s + 1; --j)
-            {
-                Ql = Ql.multiply(Qh).mod(p);
-
-                if (k.testBit(j))
-                {
-                    Qh = Ql.multiply(Q).mod(p);
-                    Uh = Uh.multiply(Vh).mod(p);
-                    Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
-                    Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p);
-                }
-                else
-                {
-                    Qh = Ql;
-                    Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
-                    Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
-                    Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
-                }
-            }
-
-            Ql = Ql.multiply(Qh).mod(p);
-            Qh = Ql.multiply(Q).mod(p);
-            Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
-            Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
-            Ql = Ql.multiply(Qh).mod(p);
-
-            for (int j = 1; j <= s; ++j)
-            {
-                Uh = Uh.multiply(Vl).mod(p);
-                Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
-                Ql = Ql.multiply(Ql).mod(p);
-            }
-
-            return new BigInteger[]{ Uh, Vl };
-        }
-        
-        public boolean equals(Object other)
-        {
-            if (other == this)
-            {
-                return true;
-            }
-
-            if (!(other instanceof ECFieldElement.Fp))
-            {
-                return false;
-            }
-            
-            ECFieldElement.Fp o = (ECFieldElement.Fp)other;
-            return q.equals(o.q) && x.equals(o.x);
-        }
-
-        public int hashCode()
-        {
-            return q.hashCode() ^ x.hashCode();
-        }
-    }
-
-//    /**
-//     * Class representing the Elements of the finite field
-//     * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
-//     * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial
-//     * basis representations are supported. Gaussian normal basis (GNB)
-//     * representation is not supported.
-//     */
-//    public static class F2m extends ECFieldElement
-//    {
-//        BigInteger x;
-//
-//        /**
-//         * Indicates gaussian normal basis representation (GNB). Number chosen
-//         * according to X9.62. GNB is not implemented at present.
-//         */
-//        public static final int GNB = 1;
-//
-//        /**
-//         * Indicates trinomial basis representation (TPB). Number chosen
-//         * according to X9.62.
-//         */
-//        public static final int TPB = 2;
-//
-//        /**
-//         * Indicates pentanomial basis representation (PPB). Number chosen
-//         * according to X9.62.
-//         */
-//        public static final int PPB = 3;
-//
-//        /**
-//         * TPB or PPB.
-//         */
-//        private int representation;
-//
-//        /**
-//         * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
-//         */
-//        private int m;
-//
-//        /**
-//         * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
-//         * x<sup>k</sup> + 1</code> represents the reduction polynomial
-//         * <code>f(z)</code>.<br>
-//         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
-//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-//         * represents the reduction polynomial <code>f(z)</code>.<br>
-//         */
-//        private int k1;
-//
-//        /**
-//         * TPB: Always set to <code>0</code><br>
-//         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
-//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-//         * represents the reduction polynomial <code>f(z)</code>.<br>
-//         */
-//        private int k2;
-//
-//        /**
-//         * TPB: Always set to <code>0</code><br>
-//         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
-//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-//         * represents the reduction polynomial <code>f(z)</code>.<br>
-//         */
-//        private int k3;
-//        
-//        /**
-//         * Constructor for PPB.
-//         * @param m  The exponent <code>m</code> of
-//         * <code>F<sub>2<sup>m</sup></sub></code>.
-//         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
-//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-//         * represents the reduction polynomial <code>f(z)</code>.
-//         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
-//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-//         * represents the reduction polynomial <code>f(z)</code>.
-//         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
-//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-//         * represents the reduction polynomial <code>f(z)</code>.
-//         * @param x The BigInteger representing the value of the field element.
-//         */
-//        public F2m(
-//            int m, 
-//            int k1, 
-//            int k2, 
-//            int k3,
-//            BigInteger x)
-//        {
-////            super(x);
-//            this.x = x;
-//
-//            if ((k2 == 0) && (k3 == 0))
-//            {
-//                this.representation = TPB;
-//            }
-//            else
-//            {
-//                if (k2 >= k3)
-//                {
-//                    throw new IllegalArgumentException(
-//                            "k2 must be smaller than k3");
-//                }
-//                if (k2 <= 0)
-//                {
-//                    throw new IllegalArgumentException(
-//                            "k2 must be larger than 0");
-//                }
-//                this.representation = PPB;
-//            }
-//
-//            if (x.signum() < 0)
-//            {
-//                throw new IllegalArgumentException("x value cannot be negative");
-//            }
-//
-//            this.m = m;
-//            this.k1 = k1;
-//            this.k2 = k2;
-//            this.k3 = k3;
-//        }
-//
-//        /**
-//         * Constructor for TPB.
-//         * @param m  The exponent <code>m</code> of
-//         * <code>F<sub>2<sup>m</sup></sub></code>.
-//         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
-//         * x<sup>k</sup> + 1</code> represents the reduction
-//         * polynomial <code>f(z)</code>.
-//         * @param x The BigInteger representing the value of the field element.
-//         */
-//        public F2m(int m, int k, BigInteger x)
-//        {
-//            // Set k1 to k, and set k2 and k3 to 0
-//            this(m, k, 0, 0, x);
-//        }
-//
-//        public BigInteger toBigInteger()
-//        {
-//            return x;
-//        }
-//
-//        public String getFieldName()
-//        {
-//            return "F2m";
-//        }
-//
-//        public int getFieldSize()
-//        {
-//            return m;
-//        }
-//
-//        /**
-//         * Checks, if the ECFieldElements <code>a</code> and <code>b</code>
-//         * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
-//         * (having the same representation).
-//         * @param a field element.
-//         * @param b field element to be compared.
-//         * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
-//         * are not elements of the same field
-//         * <code>F<sub>2<sup>m</sup></sub></code> (having the same
-//         * representation). 
-//         */
-//        public static void checkFieldElements(
-//            ECFieldElement a,
-//            ECFieldElement b)
-//        {
-//            if ((!(a instanceof F2m)) || (!(b instanceof F2m)))
-//            {
-//                throw new IllegalArgumentException("Field elements are not "
-//                        + "both instances of ECFieldElement.F2m");
-//            }
-//
-//            if ((a.toBigInteger().signum() < 0) || (b.toBigInteger().signum() < 0))
-//            {
-//                throw new IllegalArgumentException(
-//                        "x value may not be negative");
-//            }
-//
-//            ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a;
-//            ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b;
-//
-//            if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1)
-//                    || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3))
-//            {
-//                throw new IllegalArgumentException("Field elements are not "
-//                        + "elements of the same field F2m");
-//            }
-//
-//            if (aF2m.representation != bF2m.representation)
-//            {
-//                // Should never occur
-//                throw new IllegalArgumentException(
-//                        "One of the field "
-//                                + "elements are not elements has incorrect representation");
-//            }
-//        }
-//
-//        /**
-//         * Computes <code>z * a(z) mod f(z)</code>, where <code>f(z)</code> is
-//         * the reduction polynomial of <code>this</code>.
-//         * @param a The polynomial <code>a(z)</code> to be multiplied by
-//         * <code>z mod f(z)</code>.
-//         * @return <code>z * a(z) mod f(z)</code>
-//         */
-//        private BigInteger multZModF(final BigInteger a)
-//        {
-//            // Left-shift of a(z)
-//            BigInteger az = a.shiftLeft(1);
-//            if (az.testBit(this.m)) 
-//            {
-//                // If the coefficient of z^m in a(z) equals 1, reduction
-//                // modulo f(z) is performed: Add f(z) to to a(z):
-//                // Step 1: Unset mth coeffient of a(z)
-//                az = az.clearBit(this.m);
-//
-//                // Step 2: Add r(z) to a(z), where r(z) is defined as
-//                // f(z) = z^m + r(z), and k1, k2, k3 are the positions of
-//                // the non-zero coefficients in r(z)
-//                az = az.flipBit(0);
-//                az = az.flipBit(this.k1);
-//                if (this.representation == PPB) 
-//                {
-//                    az = az.flipBit(this.k2);
-//                    az = az.flipBit(this.k3);
-//                }
-//            }
-//            return az;
-//        }
-//
-//        public ECFieldElement add(final ECFieldElement b)
-//        {
-//            // No check performed here for performance reasons. Instead the
-//            // elements involved are checked in ECPoint.F2m
-//            // checkFieldElements(this, b);
-//            if (b.toBigInteger().signum() == 0)
-//            {
-//                return this;
-//            }
-//
-//            return new F2m(this.m, this.k1, this.k2, this.k3, this.x.xor(b.toBigInteger()));
-//        }
-//
-//        public ECFieldElement subtract(final ECFieldElement b)
-//        {
-//            // Addition and subtraction are the same in F2m
-//            return add(b);
-//        }
-//
-//
-//        public ECFieldElement multiply(final ECFieldElement b)
-//        {
-//            // Left-to-right shift-and-add field multiplication in F2m
-//            // Input: Binary polynomials a(z) and b(z) of degree at most m-1
-//            // Output: c(z) = a(z) * b(z) mod f(z)
-//
-//            // No check performed here for performance reasons. Instead the
-//            // elements involved are checked in ECPoint.F2m
-//            // checkFieldElements(this, b);
-//            final BigInteger az = this.x;
-//            BigInteger bz = b.toBigInteger();
-//            BigInteger cz;
-//
-//            // Compute c(z) = a(z) * b(z) mod f(z)
-//            if (az.testBit(0)) 
-//            {
-//                cz = bz;
-//            } 
-//            else 
-//            {
-//                cz = ECConstants.ZERO;
-//            }
-//
-//            for (int i = 1; i < this.m; i++) 
-//            {
-//                // b(z) := z * b(z) mod f(z)
-//                bz = multZModF(bz);
-//
-//                if (az.testBit(i)) 
-//                {
-//                    // If the coefficient of x^i in a(z) equals 1, b(z) is added
-//                    // to c(z)
-//                    cz = cz.xor(bz);
-//                }
-//            }
-//            return new ECFieldElement.F2m(m, this.k1, this.k2, this.k3, cz);
-//        }
-//
-//
-//        public ECFieldElement divide(final ECFieldElement b)
-//        {
-//            // There may be more efficient implementations
-//            ECFieldElement bInv = b.invert();
-//            return multiply(bInv);
-//        }
-//
-//        public ECFieldElement negate()
-//        {
-//            // -x == x holds for all x in F2m
-//            return this;
-//        }
-//
-//        public ECFieldElement square()
-//        {
-//            // Naive implementation, can probably be speeded up using modular
-//            // reduction
-//            return multiply(this);
-//        }
-//
-//        public ECFieldElement invert()
-//        {
-//            // Inversion in F2m using the extended Euclidean algorithm
-//            // Input: A nonzero polynomial a(z) of degree at most m-1
-//            // Output: a(z)^(-1) mod f(z)
-//
-//            // u(z) := a(z)
-//            BigInteger uz = this.x;
-//            if (uz.signum() <= 0) 
-//            {
-//                throw new ArithmeticException("x is zero or negative, " +
-//                        "inversion is impossible");
-//            }
-//
-//            // v(z) := f(z)
-//            BigInteger vz = ECConstants.ZERO.setBit(m);
-//            vz = vz.setBit(0);
-//            vz = vz.setBit(this.k1);
-//            if (this.representation == PPB) 
-//            {
-//                vz = vz.setBit(this.k2);
-//                vz = vz.setBit(this.k3);
-//            }
-//
-//            // g1(z) := 1, g2(z) := 0
-//            BigInteger g1z = ECConstants.ONE;
-//            BigInteger g2z = ECConstants.ZERO;
-//
-//            // while u != 1
-//            while (!(uz.equals(ECConstants.ZERO))) 
-//            {
-//                // j := deg(u(z)) - deg(v(z))
-//                int j = uz.bitLength() - vz.bitLength();
-//
-//                // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j
-//                if (j < 0) 
-//                {
-//                    final BigInteger uzCopy = uz;
-//                    uz = vz;
-//                    vz = uzCopy;
-//
-//                    final BigInteger g1zCopy = g1z;
-//                    g1z = g2z;
-//                    g2z = g1zCopy;
-//
-//                    j = -j;
-//                }
-//
-//                // u(z) := u(z) + z^j * v(z)
-//                // Note, that no reduction modulo f(z) is required, because
-//                // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z)))
-//                // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z))
-//                // = deg(u(z))
-//                uz = uz.xor(vz.shiftLeft(j));
-//
-//                // g1(z) := g1(z) + z^j * g2(z)
-//                g1z = g1z.xor(g2z.shiftLeft(j));
-////                if (g1z.bitLength() > this.m) {
-////                    throw new ArithmeticException(
-////                            "deg(g1z) >= m, g1z = " + g1z.toString(2));
-////                }
-//            }
-//            return new ECFieldElement.F2m(
-//                    this.m, this.k1, this.k2, this.k3, g2z);
-//        }
-//
-//        public ECFieldElement sqrt()
-//        {
-//            throw new RuntimeException("Not implemented");
-//        }
-//
-//        /**
-//         * @return the representation of the field
-//         * <code>F<sub>2<sup>m</sup></sub></code>, either of
-//         * TPB (trinomial
-//         * basis representation) or
-//         * PPB (pentanomial
-//         * basis representation).
-//         */
-//        public int getRepresentation()
-//        {
-//            return this.representation;
-//        }
-//
-//        /**
-//         * @return the degree <code>m</code> of the reduction polynomial
-//         * <code>f(z)</code>.
-//         */
-//        public int getM()
-//        {
-//            return this.m;
-//        }
-//
-//        /**
-//         * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
-//         * x<sup>k</sup> + 1</code> represents the reduction polynomial
-//         * <code>f(z)</code>.<br>
-//         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
-//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-//         * represents the reduction polynomial <code>f(z)</code>.<br>
-//         */
-//        public int getK1()
-//        {
-//            return this.k1;
-//        }
-//
-//        /**
-//         * @return TPB: Always returns <code>0</code><br>
-//         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
-//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-//         * represents the reduction polynomial <code>f(z)</code>.<br>
-//         */
-//        public int getK2()
-//        {
-//            return this.k2;
-//        }
-//
-//        /**
-//         * @return TPB: Always set to <code>0</code><br>
-//         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
-//         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-//         * represents the reduction polynomial <code>f(z)</code>.<br>
-//         */
-//        public int getK3()
-//        {
-//            return this.k3;
-//        }
-//
-//        public boolean equals(Object anObject)
-//        {
-//            if (anObject == this) 
-//            {
-//                return true;
-//            }
-//
-//            if (!(anObject instanceof ECFieldElement.F2m)) 
-//            {
-//                return false;
-//            }
-//
-//            ECFieldElement.F2m b = (ECFieldElement.F2m)anObject;
-//            
-//            return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2)
-//                && (this.k3 == b.k3)
-//                && (this.representation == b.representation)
-//                && (this.x.equals(b.x)));
-//        }
-//
-//        public int hashCode()
-//        {
-//            return x.hashCode() ^ m ^ k1 ^ k2 ^ k3;
-//        }
-//    }
-
-    /**
-     * Class representing the Elements of the finite field
-     * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
-     * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial
-     * basis representations are supported. Gaussian normal basis (GNB)
-     * representation is not supported.
-     */
-    public static class F2m extends ECFieldElement
-    {
-        /**
-         * Indicates gaussian normal basis representation (GNB). Number chosen
-         * according to X9.62. GNB is not implemented at present.
-         */
-        public static final int GNB = 1;
-
-        /**
-         * Indicates trinomial basis representation (TPB). Number chosen
-         * according to X9.62.
-         */
-        public static final int TPB = 2;
-
-        /**
-         * Indicates pentanomial basis representation (PPB). Number chosen
-         * according to X9.62.
-         */
-        public static final int PPB = 3;
-
-        /**
-         * TPB or PPB.
-         */
-        private int representation;
-
-        /**
-         * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
-         */
-        private int m;
-
-        /**
-         * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
-         * x<sup>k</sup> + 1</code> represents the reduction polynomial
-         * <code>f(z)</code>.<br>
-         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.<br>
-         */
-        private int k1;
-
-        /**
-         * TPB: Always set to <code>0</code><br>
-         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.<br>
-         */
-        private int k2;
-
-        /**
-         * TPB: Always set to <code>0</code><br>
-         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.<br>
-         */
-        private int k3;
-
-        /**
-         * The <code>IntArray</code> holding the bits.
-         */
-        private IntArray x;
-
-        /**
-         * The number of <code>int</code>s required to hold <code>m</code> bits.
-         */
-        private int t;
-
-        /**
-         * Constructor for PPB.
-         * @param m  The exponent <code>m</code> of
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.
-         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.
-         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.
-         * @param x The BigInteger representing the value of the field element.
-         */
-        public F2m(
-            int m, 
-            int k1, 
-            int k2, 
-            int k3,
-            BigInteger x)
-        {
-            // t = m / 32 rounded up to the next integer
-            t = (m + 31) >> 5;
-            this.x = new IntArray(x, t);
-
-            if ((k2 == 0) && (k3 == 0))
-            {
-                this.representation = TPB;
-            }
-            else
-            {
-                if (k2 >= k3)
-                {
-                    throw new IllegalArgumentException(
-                            "k2 must be smaller than k3");
-                }
-                if (k2 <= 0)
-                {
-                    throw new IllegalArgumentException(
-                            "k2 must be larger than 0");
-                }
-                this.representation = PPB;
-            }
-
-            if (x.signum() < 0)
-            {
-                throw new IllegalArgumentException("x value cannot be negative");
-            }
-
-            this.m = m;
-            this.k1 = k1;
-            this.k2 = k2;
-            this.k3 = k3;
-        }
-
-        /**
-         * Constructor for TPB.
-         * @param m  The exponent <code>m</code> of
-         * <code>F<sub>2<sup>m</sup></sub></code>.
-         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
-         * x<sup>k</sup> + 1</code> represents the reduction
-         * polynomial <code>f(z)</code>.
-         * @param x The BigInteger representing the value of the field element.
-         */
-        public F2m(int m, int k, BigInteger x)
-        {
-            // Set k1 to k, and set k2 and k3 to 0
-            this(m, k, 0, 0, x);
-        }
-
-        private F2m(int m, int k1, int k2, int k3, IntArray x)
-        {
-            t = (m + 31) >> 5;
-            this.x = x;
-            this.m = m;
-            this.k1 = k1;
-            this.k2 = k2;
-            this.k3 = k3;
-
-            if ((k2 == 0) && (k3 == 0))
-            {
-                this.representation = TPB;
-            }
-            else
-            {
-                this.representation = PPB;
-            }
-
-        }
-
-        public BigInteger toBigInteger()
-        {
-            return x.toBigInteger();
-        }
-
-        public String getFieldName()
-        {
-            return "F2m";
-        }
-
-        public int getFieldSize()
-        {
-            return m;
-        }
-
-        /**
-         * Checks, if the ECFieldElements <code>a</code> and <code>b</code>
-         * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
-         * (having the same representation).
-         * @param a field element.
-         * @param b field element to be compared.
-         * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
-         * are not elements of the same field
-         * <code>F<sub>2<sup>m</sup></sub></code> (having the same
-         * representation). 
-         */
-        public static void checkFieldElements(
-            ECFieldElement a,
-            ECFieldElement b)
-        {
-            if ((!(a instanceof F2m)) || (!(b instanceof F2m)))
-            {
-                throw new IllegalArgumentException("Field elements are not "
-                        + "both instances of ECFieldElement.F2m");
-            }
-
-            ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a;
-            ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b;
-
-            if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1)
-                    || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3))
-            {
-                throw new IllegalArgumentException("Field elements are not "
-                        + "elements of the same field F2m");
-            }
-
-            if (aF2m.representation != bF2m.representation)
-            {
-                // Should never occur
-                throw new IllegalArgumentException(
-                        "One of the field "
-                                + "elements are not elements has incorrect representation");
-            }
-        }
-
-        public ECFieldElement add(final ECFieldElement b)
-        {
-            // No check performed here for performance reasons. Instead the
-            // elements involved are checked in ECPoint.F2m
-            // checkFieldElements(this, b);
-            IntArray iarrClone = (IntArray)this.x.clone();
-            F2m bF2m = (F2m)b;
-            iarrClone.addShifted(bF2m.x, 0);
-            return new F2m(m, k1, k2, k3, iarrClone);
-        }
-
-        public ECFieldElement subtract(final ECFieldElement b)
-        {
-            // Addition and subtraction are the same in F2m
-            return add(b);
-        }
-
-        public ECFieldElement multiply(final ECFieldElement b)
-        {
-            // Right-to-left comb multiplication in the IntArray
-            // Input: Binary polynomials a(z) and b(z) of degree at most m-1
-            // Output: c(z) = a(z) * b(z) mod f(z)
-
-            // No check performed here for performance reasons. Instead the
-            // elements involved are checked in ECPoint.F2m
-            // checkFieldElements(this, b);
-            F2m bF2m = (F2m)b;
-            IntArray mult = x.multiply(bF2m.x, m);
-            mult.reduce(m, new int[]{k1, k2, k3});
-            return new F2m(m, k1, k2, k3, mult);
-        }
-
-        public ECFieldElement divide(final ECFieldElement b)
-        {
-            // There may be more efficient implementations
-            ECFieldElement bInv = b.invert();
-            return multiply(bInv);
-        }
-
-        public ECFieldElement negate()
-        {
-            // -x == x holds for all x in F2m
-            return this;
-        }
-
-        public ECFieldElement square()
-        {
-            IntArray squared = x.square(m);
-            squared.reduce(m, new int[]{k1, k2, k3});
-            return new F2m(m, k1, k2, k3, squared);
-        }
-
-
-        public ECFieldElement invert()
-        {
-            // Inversion in F2m using the extended Euclidean algorithm
-            // Input: A nonzero polynomial a(z) of degree at most m-1
-            // Output: a(z)^(-1) mod f(z)
-
-            // u(z) := a(z)
-            IntArray uz = (IntArray)this.x.clone();
-
-            // v(z) := f(z)
-            IntArray vz = new IntArray(t);
-            vz.setBit(m);
-            vz.setBit(0);
-            vz.setBit(this.k1);
-            if (this.representation == PPB) 
-            {
-                vz.setBit(this.k2);
-                vz.setBit(this.k3);
-            }
-
-            // g1(z) := 1, g2(z) := 0
-            IntArray g1z = new IntArray(t);
-            g1z.setBit(0);
-            IntArray g2z = new IntArray(t);
-
-            // while u != 0
-            while (!uz.isZero())
-//            while (uz.getUsedLength() > 0)
-//            while (uz.bitLength() > 1)
-            {
-                // j := deg(u(z)) - deg(v(z))
-                int j = uz.bitLength() - vz.bitLength();
-
-                // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j
-                if (j < 0) 
-                {
-                    final IntArray uzCopy = uz;
-                    uz = vz;
-                    vz = uzCopy;
-
-                    final IntArray g1zCopy = g1z;
-                    g1z = g2z;
-                    g2z = g1zCopy;
-
-                    j = -j;
-                }
-
-                // u(z) := u(z) + z^j * v(z)
-                // Note, that no reduction modulo f(z) is required, because
-                // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z)))
-                // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z))
-                // = deg(u(z))
-                // uz = uz.xor(vz.shiftLeft(j));
-                // jInt = n / 32
-                int jInt = j >> 5;
-                // jInt = n % 32
-                int jBit = j & 0x1F;
-                IntArray vzShift = vz.shiftLeft(jBit);
-                uz.addShifted(vzShift, jInt);
-
-                // g1(z) := g1(z) + z^j * g2(z)
-//                g1z = g1z.xor(g2z.shiftLeft(j));
-                IntArray g2zShift = g2z.shiftLeft(jBit);
-                g1z.addShifted(g2zShift, jInt);
-                
-            }
-            return new ECFieldElement.F2m(
-                    this.m, this.k1, this.k2, this.k3, g2z);
-        }
-
-        public ECFieldElement sqrt()
-        {
-            throw new RuntimeException("Not implemented");
-        }
-
-        /**
-         * @return the representation of the field
-         * <code>F<sub>2<sup>m</sup></sub></code>, either of
-         * TPB (trinomial
-         * basis representation) or
-         * PPB (pentanomial
-         * basis representation).
-         */
-        public int getRepresentation()
-        {
-            return this.representation;
-        }
-
-        /**
-         * @return the degree <code>m</code> of the reduction polynomial
-         * <code>f(z)</code>.
-         */
-        public int getM()
-        {
-            return this.m;
-        }
-
-        /**
-         * @return TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
-         * x<sup>k</sup> + 1</code> represents the reduction polynomial
-         * <code>f(z)</code>.<br>
-         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.<br>
-         */
-        public int getK1()
-        {
-            return this.k1;
-        }
-
-        /**
-         * @return TPB: Always returns <code>0</code><br>
-         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.<br>
-         */
-        public int getK2()
-        {
-            return this.k2;
-        }
-
-        /**
-         * @return TPB: Always set to <code>0</code><br>
-         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
-         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
-         * represents the reduction polynomial <code>f(z)</code>.<br>
-         */
-        public int getK3()
-        {
-            return this.k3;
-        }
-
-        public boolean equals(Object anObject)
-        {
-            if (anObject == this) 
-            {
-                return true;
-            }
-
-            if (!(anObject instanceof ECFieldElement.F2m)) 
-            {
-                return false;
-            }
-
-            ECFieldElement.F2m b = (ECFieldElement.F2m)anObject;
-            
-            return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2)
-                && (this.k3 == b.k3)
-                && (this.representation == b.representation)
-                && (this.x.equals(b.x)));
-        }
-
-        public int hashCode()
-        {
-            return x.hashCode() ^ m ^ k1 ^ k2 ^ k3;
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/ECMultiplier.java b/azureus2/src/org/bouncycastle/math/ec/ECMultiplier.java
deleted file mode 100644
index 4d72e33..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/ECMultiplier.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Interface for classes encapsulating a point multiplication algorithm
- * for <code>ECPoint</code>s.
- */
-interface ECMultiplier
-{
-    /**
-     * Multiplies the <code>ECPoint p</code> by <code>k</code>, i.e.
-     * <code>p</code> is added <code>k</code> times to itself.
-     * @param p The <code>ECPoint</code> to be multiplied.
-     * @param k The factor by which <code>p</code> i multiplied.
-     * @return <code>p</code> multiplied by <code>k</code>.
-     */
-    ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo);
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/ECPoint.java b/azureus2/src/org/bouncycastle/math/ec/ECPoint.java
deleted file mode 100644
index 2d38ee4..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/ECPoint.java
+++ /dev/null
@@ -1,594 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-import org.bouncycastle.asn1.x9.X9IntegerConverter;
-
-/**
- * base class for points on elliptic curves.
- */
-public abstract class ECPoint
-{
-    ECCurve        curve;
-    ECFieldElement x;
-    ECFieldElement y;
-
-    protected boolean withCompression;
-
-    protected ECMultiplier multiplier = null;
-
-    protected PreCompInfo preCompInfo = null;
-
-    private static X9IntegerConverter converter = new X9IntegerConverter();
-
-    protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
-    {
-        this.curve = curve;
-        this.x = x;
-        this.y = y;
-    }
-    
-    public ECCurve getCurve()
-    {
-        return curve;
-    }
-    
-    public ECFieldElement getX()
-    {
-        return x;
-    }
-
-    public ECFieldElement getY()
-    {
-        return y;
-    }
-
-    public boolean isInfinity()
-    {
-        return x == null && y == null;
-    }
-
-    public boolean isCompressed()
-    {
-        return withCompression;
-    }
-
-    public boolean equals(
-        Object  other)
-    {
-        if (other == this)
-        {
-            return true;
-        }
-
-        if (!(other instanceof ECPoint))
-        {
-            return false;
-        }
-
-        ECPoint o = (ECPoint)other;
-
-        if (this.isInfinity())
-        {
-            return o.isInfinity();
-        }
-
-        return x.equals(o.x) && y.equals(o.y);
-    }
-
-    public int hashCode()
-    {
-        if (this.isInfinity())
-        {
-            return 0;
-        }
-        
-        return x.hashCode() ^ y.hashCode();
-    }
-
-//    /**
-//     * Mainly for testing. Explicitly set the <code>ECMultiplier</code>.
-//     * @param multiplier The <code>ECMultiplier</code> to be used to multiply
-//     * this <code>ECPoint</code>.
-//     */
-//    public void setECMultiplier(ECMultiplier multiplier)
-//    {
-//        this.multiplier = multiplier;
-//    }
-
-    /**
-     * Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s
-     * to save the precomputation for this <code>ECPoint</code> to store the
-     * precomputation result for use by subsequent multiplication.
-     * @param preCompInfo The values precomputed by the
-     * <code>ECMultiplier</code>.
-     */
-    void setPreCompInfo(PreCompInfo preCompInfo)
-    {
-        this.preCompInfo = preCompInfo;
-    }
-
-    public abstract byte[] getEncoded();
-
-    public abstract ECPoint add(ECPoint b);
-    public abstract ECPoint subtract(ECPoint b);
-    public abstract ECPoint negate();
-    public abstract ECPoint twice();
-
-    /**
-     * Sets the default <code>ECMultiplier</code>, unless already set. 
-     */
-    synchronized void assertECMultiplier()
-    {
-        if (this.multiplier == null)
-        {
-            this.multiplier = new FpNafMultiplier();
-        }
-    }
-
-    /**
-     * Multiplies this <code>ECPoint</code> by the given number.
-     * @param k The multiplicator.
-     * @return <code>k * this</code>.
-     */
-    public ECPoint multiply(BigInteger k)
-    {
-        if (this.isInfinity())
-        {
-            return this;
-        }
-
-        if (k.signum() == 0)
-        {
-            return this.curve.getInfinity();
-        }
-
-        assertECMultiplier();
-        return this.multiplier.multiply(this, k, preCompInfo);
-    }
-
-    /**
-     * Elliptic curve points over Fp
-     */
-    public static class Fp extends ECPoint
-    {
-        
-        /**
-         * Create a point which encodes with point compression.
-         * 
-         * @param curve the curve to use
-         * @param x affine x co-ordinate
-         * @param y affine y co-ordinate
-         */
-        public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y)
-        {
-            this(curve, x, y, false);
-        }
-
-        /**
-         * Create a point that encodes with or without point compresion.
-         * 
-         * @param curve the curve to use
-         * @param x affine x co-ordinate
-         * @param y affine y co-ordinate
-         * @param withCompression if true encode with point compression
-         */
-        public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
-        {
-            super(curve, x, y);
-
-            if ((x != null && y == null) || (x == null && y != null))
-            {
-                throw new IllegalArgumentException("Exactly one of the field elements is null");
-            }
-
-            this.withCompression = withCompression;
-        }
-         
-        /**
-         * return the field element encoded with point compression. (S 4.3.6)
-         */
-        public byte[] getEncoded()
-        {
-            if (this.isInfinity()) 
-            {
-                return new byte[1];
-            }
-
-            int qLength = converter.getByteLength(x);
-            
-            if (withCompression)
-            {
-                byte    PC;
-    
-                if (this.getY().toBigInteger().testBit(0))
-                {
-                    PC = 0x03;
-                }
-                else
-                {
-                    PC = 0x02;
-                }
-    
-                byte[]  X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
-                byte[]  PO = new byte[X.length + 1];
-    
-                PO[0] = PC;
-                System.arraycopy(X, 0, PO, 1, X.length);
-    
-                return PO;
-            }
-            else
-            {
-                byte[]  X = converter.integerToBytes(this.getX().toBigInteger(), qLength);
-                byte[]  Y = converter.integerToBytes(this.getY().toBigInteger(), qLength);
-                byte[]  PO = new byte[X.length + Y.length + 1];
-                
-                PO[0] = 0x04;
-                System.arraycopy(X, 0, PO, 1, X.length);
-                System.arraycopy(Y, 0, PO, X.length + 1, Y.length);
-
-                return PO;
-            }
-        }
-
-        // B.3 pg 62
-        public ECPoint add(ECPoint b)
-        {
-            if (this.isInfinity())
-            {
-                return b;
-            }
-
-            if (b.isInfinity())
-            {
-                return this;
-            }
-
-            // Check if b = this or b = -this
-            if (this.x.equals(b.x))
-            {
-                if (this.y.equals(b.y))
-                {
-                    // this = b, i.e. this must be doubled
-                    return this.twice();
-                }
-
-                // this = -b, i.e. the result is the point at infinity
-                return this.curve.getInfinity();
-            }
-
-            ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x));
-
-            ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x);
-            ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
-
-            return new ECPoint.Fp(curve, x3, y3);
-        }
-
-        // B.3 pg 62
-        public ECPoint twice()
-        {
-            if (this.isInfinity())
-            {
-                // Twice identity element (point at infinity) is identity
-                return this;
-            }
-
-            if (this.y.toBigInteger().signum() == 0) 
-            {
-                // if y1 == 0, then (x1, y1) == (x1, -y1)
-                // and hence this = -this and thus 2(x1, y1) == infinity
-                return this.curve.getInfinity();
-            }
-
-            ECFieldElement TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
-            ECFieldElement THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
-            ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO));
-
-            ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO));
-            ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
-                
-            return new ECPoint.Fp(curve, x3, y3, this.withCompression);
-        }
-
-        // D.3.2 pg 102 (see Note:)
-        public ECPoint subtract(ECPoint b)
-        {
-            if (b.isInfinity())
-            {
-                return this;
-            }
-
-            // Add -b
-            return add(b.negate());
-        }
-
-        public ECPoint negate()
-        {
-            return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression);
-        }
-
-        // TODO Uncomment this to enable WNAF algorithm for Fp point multiplication
-//        /**
-//         * Sets the default <code>ECMultiplier</code>, unless already set. 
-//         */
-//        synchronized void assertECMultiplier()
-//        {
-//            if (this.multiplier == null)
-//            {
-//                this.multiplier = new WNafMultiplier();
-//            }
-//        }
-    }
-
-    /**
-     * Elliptic curve points over F2m
-     */
-    public static class F2m extends ECPoint
-    {
-        /**
-         * @param curve base curve
-         * @param x x point
-         * @param y y point
-         */
-        public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y)
-        {
-            this(curve, x, y, false);
-        }
-        
-        /**
-         * @param curve base curve
-         * @param x x point
-         * @param y y point
-         * @param withCompression true if encode with point compression.
-         */
-        public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression)
-        {
-            super(curve, x, y);
-
-            if ((x != null && y == null) || (x == null && y != null))
-            {
-                throw new IllegalArgumentException("Exactly one of the field elements is null");
-            }
-            
-            if (x != null)
-            {
-                // Check if x and y are elements of the same field
-                ECFieldElement.F2m.checkFieldElements(this.x, this.y);
-    
-                // Check if x and a are elements of the same field
-                if (curve != null)
-                {
-                    ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA());
-                }
-            }
-            
-            this.withCompression = withCompression;
-        }
-
-        /**
-         * @deprecated use ECCurve.getInfinity()
-         * Constructor for point at infinity
-         */
-        public F2m(ECCurve curve)
-        {
-            super(curve, null, null);
-        }
-
-        /* (non-Javadoc)
-         * @see org.bouncycastle.math.ec.ECPoint#getEncoded()
-         */
-        public byte[] getEncoded()
-        {
-            if (this.isInfinity()) 
-            {
-                return new byte[1];
-            }
-
-            int byteCount = converter.getByteLength(this.x);
-            byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount);
-            byte[] PO;
-
-            if (withCompression)
-            {
-                // See X9.62 4.3.6 and 4.2.2
-                PO = new byte[byteCount + 1];
-
-                PO[0] = 0x02;
-                // X9.62 4.2.2 and 4.3.6:
-                // if x = 0 then ypTilde := 0, else ypTilde is the rightmost
-                // bit of y * x^(-1)
-                // if ypTilde = 0, then PC := 02, else PC := 03
-                // Note: PC === PO[0]
-                if (!(this.getX().toBigInteger().equals(ECConstants.ZERO)))
-                {
-                    if (this.getY().multiply(this.getX().invert())
-                            .toBigInteger().testBit(0))
-                    {
-                        // ypTilde = 1, hence PC = 03
-                        PO[0] = 0x03;
-                    }
-                }
-
-                System.arraycopy(X, 0, PO, 1, byteCount);
-            }
-            else
-            {
-                byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount);
-    
-                PO = new byte[byteCount + byteCount + 1];
-    
-                PO[0] = 0x04;
-                System.arraycopy(X, 0, PO, 1, byteCount);
-                System.arraycopy(Y, 0, PO, byteCount + 1, byteCount);    
-            }
-
-            return PO;
-        }
-
-        /**
-         * Check, if two <code>ECPoint</code>s can be added or subtracted.
-         * @param a The first <code>ECPoint</code> to check.
-         * @param b The second <code>ECPoint</code> to check.
-         * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
-         * cannot be added.
-         */
-        private static void checkPoints(ECPoint a, ECPoint b)
-        {
-            // Check, if points are on the same curve
-            if (!(a.curve.equals(b.curve)))
-            {
-                throw new IllegalArgumentException("Only points on the same "
-                        + "curve can be added or subtracted");
-            }
-
-//            ECFieldElement.F2m.checkFieldElements(a.x, b.x);
-        }
-
-        /* (non-Javadoc)
-         * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint)
-         */
-        public ECPoint add(ECPoint b)
-        {
-            checkPoints(this, b);
-            return addSimple((ECPoint.F2m)b);
-        }
-
-        /**
-         * Adds another <code>ECPoints.F2m</code> to <code>this</code> without
-         * checking if both points are on the same curve. Used by multiplication
-         * algorithms, because there all points are a multiple of the same point
-         * and hence the checks can be omitted.
-         * @param b The other <code>ECPoints.F2m</code> to add to
-         * <code>this</code>.
-         * @return <code>this + b</code>
-         */
-        public ECPoint.F2m addSimple(ECPoint.F2m b)
-        {
-            ECPoint.F2m other = b;
-            if (this.isInfinity())
-            {
-                return other;
-            }
-
-            if (other.isInfinity())
-            {
-                return this;
-            }
-
-            ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX();
-            ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY();
-
-            // Check if other = this or other = -this
-            if (this.x.equals(x2))
-            {
-                if (this.y.equals(y2))
-                {
-                    // this = other, i.e. this must be doubled
-                    return (ECPoint.F2m)this.twice();
-                }
-
-                // this = -other, i.e. the result is the point at infinity
-                return (ECPoint.F2m)this.curve.getInfinity();
-            }
-
-            ECFieldElement.F2m lambda
-                = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2));
-
-            ECFieldElement.F2m x3
-                = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA());
-
-            ECFieldElement.F2m y3
-                = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y);
-
-            return new ECPoint.F2m(curve, x3, y3, withCompression);
-        }
-
-        /* (non-Javadoc)
-         * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint)
-         */
-        public ECPoint subtract(ECPoint b)
-        {
-            checkPoints(this, b);
-            return subtractSimple((ECPoint.F2m)b);
-        }
-
-        /**
-         * Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
-         * without checking if both points are on the same curve. Used by
-         * multiplication algorithms, because there all points are a multiple
-         * of the same point and hence the checks can be omitted.
-         * @param b The other <code>ECPoints.F2m</code> to subtract from
-         * <code>this</code>.
-         * @return <code>this - b</code>
-         */
-        public ECPoint.F2m subtractSimple(ECPoint.F2m b)
-        {
-            if (b.isInfinity())
-            {
-                return this;
-            }
-
-            // Add -b
-            return addSimple((ECPoint.F2m)b.negate());
-        }
-
-        /* (non-Javadoc)
-         * @see org.bouncycastle.math.ec.ECPoint#twice()
-         */
-        public ECPoint twice()
-        {
-            if (this.isInfinity()) 
-            {
-                // Twice identity element (point at infinity) is identity
-                return this;
-            }
-
-            if (this.x.toBigInteger().signum() == 0) 
-            {
-                // if x1 == 0, then (x1, y1) == (x1, x1 + y1)
-                // and hence this = -this and thus 2(x1, y1) == infinity
-                return this.curve.getInfinity();
-            }
-
-            ECFieldElement.F2m lambda
-                = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x));
-
-            ECFieldElement.F2m x3
-                = (ECFieldElement.F2m)lambda.square().add(lambda).
-                    add(this.curve.getA());
-
-            ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE);
-            ECFieldElement.F2m y3
-                = (ECFieldElement.F2m)this.x.square().add(
-                    x3.multiply(lambda.add(ONE)));
-
-            return new ECPoint.F2m(this.curve, x3, y3, withCompression);
-        }
-
-        public ECPoint negate()
-        {
-            return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression);
-        }
-
-        // TODO Uncomment this to enable WNAF/WTNAF F2m point multiplication
-//        /**
-//         * Sets the appropriate <code>ECMultiplier</code>, unless already set. 
-//         */
-//        synchronized void assertECMultiplier()
-//        {
-//            if (this.multiplier == null)
-//            {
-//                if (((ECCurve.F2m)(this.curve)).isKoblitz())
-//                {
-//                    this.multiplier = new WTauNafMultiplier();
-//                }
-//                else
-//                {
-//                    this.multiplier = new WNafMultiplier();
-//                }
-//            }
-//        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/FpNafMultiplier.java b/azureus2/src/org/bouncycastle/math/ec/FpNafMultiplier.java
deleted file mode 100644
index 35e601d..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/FpNafMultiplier.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm.
- */
-class FpNafMultiplier implements ECMultiplier
-{
-    /**
-     * D.3.2 pg 101
-     * @see org.bouncycastle.math.ec.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger)
-     */
-    public ECPoint multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
-    {
-        // TODO Probably should try to add this
-        // BigInteger e = k.mod(n); // n == order of p
-        BigInteger e = k;
-        BigInteger h = e.multiply(BigInteger.valueOf(3));
-
-        ECPoint neg = p.negate();
-        ECPoint R = p;
-
-        for (int i = h.bitLength() - 2; i > 0; --i)
-        {             
-            R = R.twice();
-
-            boolean hBit = h.testBit(i);
-            boolean eBit = e.testBit(i);
-
-            if (hBit != eBit)
-            {
-                R = R.add(hBit ? p : neg);
-            }
-        }
-
-        return R;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/IntArray.java b/azureus2/src/org/bouncycastle/math/ec/IntArray.java
deleted file mode 100644
index 6cfc36c..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/IntArray.java
+++ /dev/null
@@ -1,518 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import org.bouncycastle.util.Arrays;
-
-import java.math.BigInteger;
-
-class IntArray
-{
-    // TODO make m fixed for the IntArray, and hence compute T once and for all
-
-    private int[] m_ints;
-
-    public IntArray(int intLen)
-    {
-        m_ints = new int[intLen];
-    }
-
-    public IntArray(int[] ints)
-    {
-        m_ints = ints;
-    }
-
-    public IntArray(BigInteger bigInt)
-    {
-        this(bigInt, 0);
-    }
-
-    public IntArray(BigInteger bigInt, int minIntLen)
-    {
-        if (bigInt.signum() == -1)
-        {
-            throw new IllegalArgumentException("Only positive Integers allowed");
-        }
-        if (bigInt.equals(ECConstants.ZERO))
-        {
-            m_ints = new int[] { 0 };
-            return;
-        }
-
-        byte[] barr = bigInt.toByteArray();
-        int barrLen = barr.length;
-        int barrStart = 0;
-        if (barr[0] == 0)
-        {
-            // First byte is 0 to enforce highest (=sign) bit is zero.
-            // In this case ignore barr[0].
-            barrLen--;
-            barrStart = 1;
-        }
-        int intLen = (barrLen + 3) / 4;
-        if (intLen < minIntLen)
-        {
-            m_ints = new int[minIntLen];
-        }
-        else
-        {
-            m_ints = new int[intLen];
-        }
-
-        int iarrJ = intLen - 1;
-        int rem = barrLen % 4 + barrStart;
-        int temp = 0;
-        int barrI = barrStart;
-        if (barrStart < rem)
-        {
-            for (; barrI < rem; barrI++)
-            {
-                temp <<= 8;
-                int barrBarrI = barr[barrI];
-                if (barrBarrI < 0)
-                {
-                    barrBarrI += 256;
-                }
-                temp |= barrBarrI;
-            }
-            m_ints[iarrJ--] = temp;
-        }
-
-        for (; iarrJ >= 0; iarrJ--)
-        {
-            temp = 0;
-            for (int i = 0; i < 4; i++)
-            {
-                temp <<= 8;
-                int barrBarrI = barr[barrI++];
-                if (barrBarrI < 0)
-                {
-                    barrBarrI += 256;
-                }
-                temp |= barrBarrI;
-            }
-            m_ints[iarrJ] = temp;
-        }
-    }
-
-    public boolean isZero()
-    {
-        return m_ints.length == 0
-            || (m_ints[0] == 0 && getUsedLength() == 0);
-    }
-
-    public int getUsedLength()
-    {
-        int highestIntPos = m_ints.length;
-
-        if (highestIntPos < 1)
-        {
-            return 0;
-        }
-
-        // Check if first element will act as sentinel
-        if (m_ints[0] != 0)
-        {
-            while (m_ints[--highestIntPos] == 0)
-            {
-            }
-            return highestIntPos + 1;
-        }
-
-        do
-        {
-            if (m_ints[--highestIntPos] != 0)
-            {
-                return highestIntPos + 1;
-            }
-        }
-        while (highestIntPos > 0);
-
-        return 0;
-    }
-
-    public int bitLength()
-    {
-        // JDK 1.5: see Integer.numberOfLeadingZeros()
-        int intLen = getUsedLength();
-        if (intLen == 0)
-        {
-            return 0;
-        }
-
-        int last = intLen - 1;
-        int highest = m_ints[last];
-        int bits = (last << 5) + 1;
-
-        // A couple of binary search steps
-        if ((highest & 0xffff0000) != 0)
-        {
-            if ((highest & 0xff000000) != 0)
-            {
-                bits += 24;
-                highest >>>= 24;
-            }
-            else
-            {
-                bits += 16;
-                highest >>>= 16;
-            }
-        }
-        else if (highest > 0x000000ff)
-        {
-            bits += 8;
-            highest >>>= 8;
-        }
-
-        while (highest != 1)
-        {
-            ++bits;
-            highest >>>= 1;
-        }
-
-        return bits;
-    }
-
-    private int[] resizedInts(int newLen)
-    {
-        int[] newInts = new int[newLen];
-        int oldLen = m_ints.length;
-        int copyLen = oldLen < newLen ? oldLen : newLen;
-        System.arraycopy(m_ints, 0, newInts, 0, copyLen);
-        return newInts;
-    }
-
-    public BigInteger toBigInteger()
-    {
-        int usedLen = getUsedLength();
-        if (usedLen == 0)
-        {
-            return ECConstants.ZERO;
-        }
-
-        int highestInt = m_ints[usedLen - 1];
-        byte[] temp = new byte[4];
-        int barrI = 0;
-        boolean trailingZeroBytesDone = false;
-        for (int j = 3; j >= 0; j--)
-        {
-            byte thisByte = (byte) (highestInt >>> (8 * j));
-            if (trailingZeroBytesDone || (thisByte != 0))
-            {
-                trailingZeroBytesDone = true;
-                temp[barrI++] = thisByte;
-            }
-        }
-
-        int barrLen = 4 * (usedLen - 1) + barrI;
-        byte[] barr = new byte[barrLen];
-        for (int j = 0; j < barrI; j++)
-        {
-            barr[j] = temp[j];
-        }
-        // Highest value int is done now
-
-        for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
-        {
-            for (int j = 3; j >= 0; j--)
-            {
-                barr[barrI++] = (byte) (m_ints[iarrJ] >>> (8 * j));
-            }
-        }
-        return new BigInteger(1, barr);
-    }
-
-    public void shiftLeft()
-    {
-        int usedLen = getUsedLength();
-        if (usedLen == 0)
-        {
-            return;
-        }
-        if (m_ints[usedLen - 1] < 0)
-        {
-            // highest bit of highest used byte is set, so shifting left will
-            // make the IntArray one byte longer
-            usedLen++;
-            if (usedLen > m_ints.length)
-            {
-                // make the m_ints one byte longer, because we need one more
-                // byte which is not available in m_ints
-                m_ints = resizedInts(m_ints.length + 1);
-            }
-        }
-
-        boolean carry = false;
-        for (int i = 0; i < usedLen; i++)
-        {
-            // nextCarry is true if highest bit is set
-            boolean nextCarry = m_ints[i] < 0;
-            m_ints[i] <<= 1;
-            if (carry)
-            {
-                // set lowest bit
-                m_ints[i] |= 1;
-            }
-            carry = nextCarry;
-        }
-    }
-
-    public IntArray shiftLeft(int n)
-    {
-        int usedLen = getUsedLength();
-        if (usedLen == 0)
-        {
-            return this;
-        }
-
-        if (n == 0)
-        {
-            return this;
-        }
-
-        if (n > 31)
-        {
-            throw new IllegalArgumentException("shiftLeft() for max 31 bits "
-                + ", " + n + "bit shift is not possible");
-        }
-
-        int[] newInts = new int[usedLen + 1];
-
-        int nm32 = 32 - n;
-        newInts[0] = m_ints[0] << n;
-        for (int i = 1; i < usedLen; i++)
-        {
-            newInts[i] = (m_ints[i] << n) | (m_ints[i - 1] >>> nm32);
-        }
-        newInts[usedLen] = m_ints[usedLen - 1] >>> nm32;
-
-        return new IntArray(newInts);
-    }
-
-    public void addShifted(IntArray other, int shift)
-    {
-        int usedLenOther = other.getUsedLength();
-        int newMinUsedLen = usedLenOther + shift;
-        if (newMinUsedLen > m_ints.length)
-        {
-            m_ints = resizedInts(newMinUsedLen);
-            //System.out.println("Resize required");
-        }
-
-        for (int i = 0; i < usedLenOther; i++)
-        {
-            m_ints[i + shift] ^= other.m_ints[i];
-        }
-    }
-
-    public int getLength()
-    {
-        return m_ints.length;
-    }
-
-    public boolean testBit(int n)
-    {
-        // theInt = n / 32
-        int theInt = n >> 5;
-        // theBit = n % 32
-        int theBit = n & 0x1F;
-        int tester = 1 << theBit;
-        return ((m_ints[theInt] & tester) != 0);
-    }
-
-    public void flipBit(int n)
-    {
-        // theInt = n / 32
-        int theInt = n >> 5;
-        // theBit = n % 32
-        int theBit = n & 0x1F;
-        int flipper = 1 << theBit;
-        m_ints[theInt] ^= flipper;
-    }
-
-    public void setBit(int n)
-    {
-        // theInt = n / 32
-        int theInt = n >> 5;
-        // theBit = n % 32
-        int theBit = n & 0x1F;
-        int setter = 1 << theBit;
-        m_ints[theInt] |= setter;
-    }
-
-    public IntArray multiply(IntArray other, int m)
-    {
-        // Lenght of c is 2m bits rounded up to the next int (32 bit)
-        int t = (m + 31) >> 5;
-        if (m_ints.length < t)
-        {
-            m_ints = resizedInts(t);
-        }
-
-        IntArray b = new IntArray(other.resizedInts(other.getLength() + 1));
-        IntArray c = new IntArray((m + m + 31) >> 5);
-        // IntArray c = new IntArray(t + t);
-        int testBit = 1;
-        for (int k = 0; k < 32; k++)
-        {
-            for (int j = 0; j < t; j++)
-            {
-                if ((m_ints[j] & testBit) != 0)
-                {
-                    // The kth bit of m_ints[j] is set
-                    c.addShifted(b, j);
-                }
-            }
-            testBit <<= 1;
-            b.shiftLeft();
-        }
-        return c;
-    }
-
-    // public IntArray multiplyLeftToRight(IntArray other, int m) {
-    // // Lenght of c is 2m bits rounded up to the next int (32 bit)
-    // int t = (m + 31) / 32;
-    // if (m_ints.length < t) {
-    // m_ints = resizedInts(t);
-    // }
-    //
-    // IntArray b = new IntArray(other.resizedInts(other.getLength() + 1));
-    // IntArray c = new IntArray((m + m + 31) / 32);
-    // // IntArray c = new IntArray(t + t);
-    // int testBit = 1 << 31;
-    // for (int k = 31; k >= 0; k--) {
-    // for (int j = 0; j < t; j++) {
-    // if ((m_ints[j] & testBit) != 0) {
-    // // The kth bit of m_ints[j] is set
-    // c.addShifted(b, j);
-    // }
-    // }
-    // testBit >>>= 1;
-    // if (k > 0) {
-    // c.shiftLeft();
-    // }
-    // }
-    // return c;
-    // }
-
-    // TODO note, redPol.length must be 3 for TPB and 5 for PPB
-    public void reduce(int m, int[] redPol)
-    {
-        for (int i = m + m - 2; i >= m; i--)
-        {
-            if (testBit(i))
-            {
-                int bit = i - m;
-                flipBit(bit);
-                flipBit(i);
-                int l = redPol.length;
-                while (--l >= 0)
-                {
-                    flipBit(redPol[l] + bit);
-                }
-            }
-        }
-        m_ints = resizedInts((m + 31) >> 5);
-    }
-
-    public IntArray square(int m)
-    {
-        // TODO make the table static final
-        final int[] table = { 0x0, 0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15, 0x40,
-            0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 };
-
-        int t = (m + 31) >> 5;
-        if (m_ints.length < t)
-        {
-            m_ints = resizedInts(t);
-        }
-
-        IntArray c = new IntArray(t + t);
-
-        // TODO twice the same code, put in separate private method
-        for (int i = 0; i < t; i++)
-        {
-            int v0 = 0;
-            for (int j = 0; j < 4; j++)
-            {
-                v0 = v0 >>> 8;
-                int u = (m_ints[i] >>> (j * 4)) & 0xF;
-                int w = table[u] << 24;
-                v0 |= w;
-            }
-            c.m_ints[i + i] = v0;
-
-            v0 = 0;
-            int upper = m_ints[i] >>> 16;
-            for (int j = 0; j < 4; j++)
-            {
-                v0 = v0 >>> 8;
-                int u = (upper >>> (j * 4)) & 0xF;
-                int w = table[u] << 24;
-                v0 |= w;
-            }
-            c.m_ints[i + i + 1] = v0;
-        }
-        return c;
-    }
-
-    public boolean equals(Object o)
-    {
-        if (!(o instanceof IntArray))
-        {
-            return false;
-        }
-        IntArray other = (IntArray) o;
-        int usedLen = getUsedLength();
-        if (other.getUsedLength() != usedLen)
-        {
-            return false;
-        }
-        for (int i = 0; i < usedLen; i++)
-        {
-            if (m_ints[i] != other.m_ints[i])
-            {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public int hashCode()
-    {
-        int usedLen = getUsedLength();
-        int hash = 0;
-        for (int i = 0; i < usedLen; i++)
-        {
-            hash ^= m_ints[i];
-        }
-        return hash;
-    }
-
-    public Object clone()
-    {
-        return new IntArray(Arrays.clone(m_ints));
-    }
-
-    public String toString()
-    {
-        int usedLen = getUsedLength();
-        if (usedLen == 0)
-        {
-            return "0";
-        }
-
-        StringBuffer sb = new StringBuffer(Integer
-            .toBinaryString(m_ints[usedLen - 1]));
-        for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
-        {
-            String hexString = Integer.toBinaryString(m_ints[iarrJ]);
-
-            // Add leading zeroes, except for highest significant int
-            for (int i = hexString.length(); i < 8; i++)
-            {
-                hexString = "0" + hexString;
-            }
-            sb.append(hexString);
-        }
-        return sb.toString();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/PreCompInfo.java b/azureus2/src/org/bouncycastle/math/ec/PreCompInfo.java
deleted file mode 100644
index 804dcf7..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/PreCompInfo.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.bouncycastle.math.ec;
-
-/**
- * Interface for classes storing precomputation data for multiplication
- * algorithms. Used as a Memento (see GOF patterns) for
- * <code>WNafMultiplier</code>.
- */
-interface PreCompInfo
-{
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/SimpleBigDecimal.java b/azureus2/src/org/bouncycastle/math/ec/SimpleBigDecimal.java
deleted file mode 100644
index 2aea166..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/SimpleBigDecimal.java
+++ /dev/null
@@ -1,253 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class representing a simple version of a big decimal. A
- * <code>SimpleBigDecimal</code> is basically a
- * {@link java.math.BigInteger BigInteger} with a few digits on the right of
- * the decimal point. The number of (binary) digits on the right of the decimal
- * point is called the <code>scale</code> of the <code>SimpleBigDecimal</code>.
- * Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted
- * automatically, but must be set manually. All <code>SimpleBigDecimal</code>s
- * taking part in the same arithmetic operation must have equal scale. The
- * result of a multiplication of two <code>SimpleBigDecimal</code>s returns a
- * <code>SimpleBigDecimal</code> with double scale.
- */
-class SimpleBigDecimal
-    //extends Number   // not in J2ME - add compatibility class?
-{
-    private static final long serialVersionUID = 1L;
-
-    private final BigInteger bigInt;
-    private final int scale;
-
-    /**
-     * Returns a <code>SimpleBigDecimal</code> representing the same numerical
-     * value as <code>value</code>.
-     * @param value The value of the <code>SimpleBigDecimal</code> to be
-     * created. 
-     * @param scale The scale of the <code>SimpleBigDecimal</code> to be
-     * created. 
-     * @return The such created <code>SimpleBigDecimal</code>.
-     */
-    public static SimpleBigDecimal getInstance(BigInteger value, int scale)
-    {
-        return new SimpleBigDecimal(value.shiftLeft(scale), scale);
-    }
-
-    /**
-     * Constructor for <code>SimpleBigDecimal</code>. The value of the
-     * constructed <code>SimpleBigDecimal</code> equals <code>bigInt / 
-     * 2<sup>scale</sup></code>.
-     * @param bigInt The <code>bigInt</code> value parameter.
-     * @param scale The scale of the constructed <code>SimpleBigDecimal</code>.
-     */
-    public SimpleBigDecimal(BigInteger bigInt, int scale)
-    {
-        if (scale < 0)
-        {
-            throw new IllegalArgumentException("scale may not be negative");
-        }
-
-        this.bigInt = bigInt;
-        this.scale = scale;
-    }
-
-    private SimpleBigDecimal(SimpleBigDecimal limBigDec)
-    {
-        bigInt = limBigDec.bigInt;
-        scale = limBigDec.scale;
-    }
-
-    private void checkScale(SimpleBigDecimal b)
-    {
-        if (scale != b.scale)
-        {
-            throw new IllegalArgumentException("Only SimpleBigDecimal of " +
-                "same scale allowed in arithmetic operations");
-        }
-    }
-
-    public SimpleBigDecimal adjustScale(int newScale)
-    {
-        if (newScale < 0)
-        {
-            throw new IllegalArgumentException("scale may not be negative");
-        }
-
-        if (newScale == scale)
-        {
-            return new SimpleBigDecimal(this);
-        }
-
-        return new SimpleBigDecimal(bigInt.shiftLeft(newScale - scale),
-                newScale);
-    }
-
-    public SimpleBigDecimal add(SimpleBigDecimal b)
-    {
-        checkScale(b);
-        return new SimpleBigDecimal(bigInt.add(b.bigInt), scale);
-    }
-
-    public SimpleBigDecimal add(BigInteger b)
-    {
-        return new SimpleBigDecimal(bigInt.add(b.shiftLeft(scale)), scale);
-    }
-
-    public SimpleBigDecimal negate()
-    {
-        return new SimpleBigDecimal(bigInt.negate(), scale);
-    }
-
-    public SimpleBigDecimal subtract(SimpleBigDecimal b)
-    {
-        return add(b.negate());
-    }
-
-    public SimpleBigDecimal subtract(BigInteger b)
-    {
-        return new SimpleBigDecimal(bigInt.subtract(b.shiftLeft(scale)),
-                scale);
-    }
-
-    public SimpleBigDecimal multiply(SimpleBigDecimal b)
-    {
-        checkScale(b);
-        return new SimpleBigDecimal(bigInt.multiply(b.bigInt), scale + scale);
-    }
-
-    public SimpleBigDecimal multiply(BigInteger b)
-    {
-        return new SimpleBigDecimal(bigInt.multiply(b), scale);
-    }
-
-    public SimpleBigDecimal divide(SimpleBigDecimal b)
-    {
-        checkScale(b);
-        BigInteger dividend = bigInt.shiftLeft(scale);
-        return new SimpleBigDecimal(dividend.divide(b.bigInt), scale);
-    }
-
-    public SimpleBigDecimal divide(BigInteger b)
-    {
-        return new SimpleBigDecimal(bigInt.divide(b), scale);
-    }
-
-    public SimpleBigDecimal shiftLeft(int n)
-    {
-        return new SimpleBigDecimal(bigInt.shiftLeft(n), scale);
-    }
-
-    public int compareTo(SimpleBigDecimal val)
-    {
-        checkScale(val);
-        return bigInt.compareTo(val.bigInt);
-    }
-
-    public int compareTo(BigInteger val)
-    {
-        return bigInt.compareTo(val.shiftLeft(scale));
-    }
-
-    public BigInteger floor()
-    {
-        return bigInt.shiftRight(scale);
-    }
-
-    public BigInteger round()
-    {
-        SimpleBigDecimal oneHalf = new SimpleBigDecimal(ECConstants.ONE, 1);
-        return add(oneHalf.adjustScale(scale)).floor();
-    }
-
-    public int intValue()
-    {
-        return floor().intValue();
-    }
-    
-    public long longValue()
-    {
-        return floor().longValue();
-    }
-
-    public double doubleValue()
-    {
-        return Double.valueOf(toString()).doubleValue();
-    }
-
-    public float floatValue()
-    {
-        return Float.valueOf(toString()).floatValue();
-    }
-
-    public int getScale()
-    {
-        return scale;
-    }
-
-    public String toString()
-    {
-        if (scale == 0)
-        {
-            return bigInt.toString();
-        }
-
-        BigInteger floorBigInt = floor();
-        
-        BigInteger fract = bigInt.subtract(floorBigInt.shiftLeft(scale));
-        if (bigInt.signum() == -1)
-        {
-            fract = ECConstants.ONE.shiftLeft(scale).subtract(fract);
-        }
-
-        if ((floorBigInt.signum() == -1) && (!(fract.equals(ECConstants.ZERO))))
-        {
-            floorBigInt = floorBigInt.add(ECConstants.ONE);
-        }
-        String leftOfPoint = floorBigInt.toString();
-
-        char[] fractCharArr = new char[scale];
-        String fractStr = fract.toString(2);
-        int fractLen = fractStr.length();
-        int zeroes = scale - fractLen;
-        for (int i = 0; i < zeroes; i++)
-        {
-            fractCharArr[i] = '0';
-        }
-        for (int j = 0; j < fractLen; j++)
-        {
-            fractCharArr[zeroes + j] = fractStr.charAt(j);
-        }
-        String rightOfPoint = new String(fractCharArr);
-
-        StringBuffer sb = new StringBuffer(leftOfPoint);
-        sb.append(".");
-        sb.append(rightOfPoint);
-
-        return sb.toString();
-    }
-
-    public boolean equals(Object o)
-    {
-        if (this == o)
-        {
-            return true;
-        }
-
-        if (!(o instanceof SimpleBigDecimal))
-        {
-            return false;
-        }
-
-        SimpleBigDecimal other = (SimpleBigDecimal)o;
-        return ((bigInt.equals(other.bigInt)) && (scale == other.scale));
-    }
-
-    public int hashCode()
-    {
-        return bigInt.hashCode() ^ scale;
-    }
-
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/Tnaf.java b/azureus2/src/org/bouncycastle/math/ec/Tnaf.java
deleted file mode 100644
index af4355f..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/Tnaf.java
+++ /dev/null
@@ -1,844 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class holding methods for point multiplication based on the window
- * τ-adic nonadjacent form (WTNAF). The algorithms are based on the
- * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
- * by Jerome A. Solinas. The paper first appeared in the Proceedings of
- * Crypto 1997.
- */
-class Tnaf
-{
-    private static final BigInteger MINUS_ONE = ECConstants.ONE.negate();
-    private static final BigInteger MINUS_TWO = ECConstants.TWO.negate();
-    private static final BigInteger MINUS_THREE = ECConstants.THREE.negate();
-
-    /**
-     * The window width of WTNAF. The standard value of 4 is slightly less
-     * than optimal for running time, but keeps space requirements for
-     * precomputation low. For typical curves, a value of 5 or 6 results in
-     * a better running time. When changing this value, the
-     * <code>α<sub>u</sub></code>'s must be computed differently, see
-     * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
-     * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
-     * p. 121-122
-     */
-    public static final byte WIDTH = 4;
-
-    /**
-     * 2<sup>4</sup>
-     */
-    public static final byte POW_2_WIDTH = 16;
-
-    /**
-     * The <code>α<sub>u</sub></code>'s for <code>a=0</code> as an array
-     * of <code>ZTauElement</code>s.
-     */
-    public static final ZTauElement[] alpha0 = {
-        null,
-        new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
-        new ZTauElement(MINUS_THREE, MINUS_ONE), null,
-        new ZTauElement(MINUS_ONE, MINUS_ONE), null,
-        new ZTauElement(ECConstants.ONE, MINUS_ONE), null
-    };
-
-    /**
-     * The <code>α<sub>u</sub></code>'s for <code>a=0</code> as an array
-     * of TNAFs.
-     */
-    public static final byte[][] alpha0Tnaf = {
-        null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, 1}
-    };
-
-    /**
-     * The <code>α<sub>u</sub></code>'s for <code>a=1</code> as an array
-     * of <code>ZTauElement</code>s.
-     */
-    public static final ZTauElement[] alpha1 = {null,
-        new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
-        new ZTauElement(MINUS_THREE, ECConstants.ONE), null,
-        new ZTauElement(MINUS_ONE, ECConstants.ONE), null,
-        new ZTauElement(ECConstants.ONE, ECConstants.ONE), null
-    };
-
-    /**
-     * The <code>α<sub>u</sub></code>'s for <code>a=1</code> as an array
-     * of TNAFs.
-     */
-    public static final byte[][] alpha1Tnaf = {
-        null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, -1}
-    };
-
-    /**
-     * Computes the norm of an element <code>λ</code> of
-     * <code><b>Z</b>[τ]</code>.
-     * @param mu The parameter <code>μ</code> of the elliptic curve.
-     * @param lambda The element <code>λ</code> of
-     * <code><b>Z</b>[τ]</code>.
-     * @return The norm of <code>λ</code>.
-     */
-    public static BigInteger norm(final byte mu, ZTauElement lambda)
-    {
-        BigInteger norm;
-
-        // s1 = u^2
-        BigInteger s1 = lambda.u.multiply(lambda.u);
-
-        // s2 = u * v
-        BigInteger s2 = lambda.u.multiply(lambda.v);
-
-        // s3 = 2 * v^2
-        BigInteger s3 = lambda.v.multiply(lambda.v).shiftLeft(1);
-
-        if (mu == 1)
-        {
-            norm = s1.add(s2).add(s3);
-        }
-        else if (mu == -1)
-        {
-            norm = s1.subtract(s2).add(s3);
-        }
-        else
-        {
-            throw new IllegalArgumentException("mu must be 1 or -1");
-        }
-
-        return norm;
-    }
-
-    /**
-     * Computes the norm of an element <code>λ</code> of
-     * <code><b>R</b>[τ]</code>, where <code>λ = u + vτ</code>
-     * and <code>u</code> and <code>u</code> are real numbers (elements of
-     * <code><b>R</b></code>). 
-     * @param mu The parameter <code>μ</code> of the elliptic curve.
-     * @param u The real part of the element <code>λ</code> of
-     * <code><b>R</b>[τ]</code>.
-     * @param v The <code>τ</code>-adic part of the element
-     * <code>λ</code> of <code><b>R</b>[τ]</code>.
-     * @return The norm of <code>λ</code>.
-     */
-    public static SimpleBigDecimal norm(final byte mu, SimpleBigDecimal u,
-            SimpleBigDecimal v)
-    {
-        SimpleBigDecimal norm;
-
-        // s1 = u^2
-        SimpleBigDecimal s1 = u.multiply(u);
-
-        // s2 = u * v
-        SimpleBigDecimal s2 = u.multiply(v);
-
-        // s3 = 2 * v^2
-        SimpleBigDecimal s3 = v.multiply(v).shiftLeft(1);
-
-        if (mu == 1)
-        {
-            norm = s1.add(s2).add(s3);
-        }
-        else if (mu == -1)
-        {
-            norm = s1.subtract(s2).add(s3);
-        }
-        else
-        {
-            throw new IllegalArgumentException("mu must be 1 or -1");
-        }
-
-        return norm;
-    }
-
-    /**
-     * Rounds an element <code>λ</code> of <code><b>R</b>[τ]</code>
-     * to an element of <code><b>Z</b>[τ]</code>, such that their difference
-     * has minimal norm. <code>λ</code> is given as
-     * <code>λ = λ<sub>0</sub> + λ<sub>1</sub>τ</code>.
-     * @param lambda0 The component <code>λ<sub>0</sub></code>.
-     * @param lambda1 The component <code>λ<sub>1</sub></code>.
-     * @param mu The parameter <code>μ</code> of the elliptic curve. Must
-     * equal 1 or -1.
-     * @return The rounded element of <code><b>Z</b>[τ]</code>.
-     * @throws IllegalArgumentException if <code>lambda0</code> and
-     * <code>lambda1</code> do not have same scale.
-     */
-    public static ZTauElement round(SimpleBigDecimal lambda0,
-            SimpleBigDecimal lambda1, byte mu)
-    {
-        int scale = lambda0.getScale();
-        if (lambda1.getScale() != scale)
-        {
-            throw new IllegalArgumentException("lambda0 and lambda1 do not " +
-                    "have same scale");
-        }
-
-        if (!((mu == 1) || (mu == -1)))
-        {
-            throw new IllegalArgumentException("mu must be 1 or -1");
-        }
-
-        BigInteger f0 = lambda0.round();
-        BigInteger f1 = lambda1.round();
-
-        SimpleBigDecimal eta0 = lambda0.subtract(f0);
-        SimpleBigDecimal eta1 = lambda1.subtract(f1);
-
-        // eta = 2*eta0 + mu*eta1
-        SimpleBigDecimal eta = eta0.add(eta0);
-        if (mu == 1)
-        {
-            eta = eta.add(eta1);
-        }
-        else
-        {
-            // mu == -1
-            eta = eta.subtract(eta1);
-        }
-
-        // check1 = eta0 - 3*mu*eta1
-        // check2 = eta0 + 4*mu*eta1
-        SimpleBigDecimal threeEta1 = eta1.add(eta1).add(eta1);
-        SimpleBigDecimal fourEta1 = threeEta1.add(eta1);
-        SimpleBigDecimal check1;
-        SimpleBigDecimal check2;
-        if (mu == 1)
-        {
-            check1 = eta0.subtract(threeEta1);
-            check2 = eta0.add(fourEta1);
-        }
-        else
-        {
-            // mu == -1
-            check1 = eta0.add(threeEta1);
-            check2 = eta0.subtract(fourEta1);
-        }
-
-        byte h0 = 0;
-        byte h1 = 0;
-
-        // if eta >= 1
-        if (eta.compareTo(ECConstants.ONE) >= 0)
-        {
-            if (check1.compareTo(MINUS_ONE) < 0)
-            {
-                h1 = mu;
-            }
-            else
-            {
-                h0 = 1;
-            }
-        }
-        else
-        {
-            // eta < 1
-            if (check2.compareTo(ECConstants.TWO) >= 0)
-            {
-                h1 = mu;
-            }
-        }
-
-        // if eta < -1
-        if (eta.compareTo(MINUS_ONE) < 0)
-        {
-            if (check1.compareTo(ECConstants.ONE) >= 0)
-            {
-                h1 = (byte)-mu;
-            }
-            else
-            {
-                h0 = -1;
-            }
-        }
-        else
-        {
-            // eta >= -1
-            if (check2.compareTo(MINUS_TWO) < 0)
-            {
-                h1 = (byte)-mu;
-            }
-        }
-
-        BigInteger q0 = f0.add(BigInteger.valueOf(h0));
-        BigInteger q1 = f1.add(BigInteger.valueOf(h1));
-        return new ZTauElement(q0, q1);
-    }
-
-    /**
-     * Approximate division by <code>n</code>. For an integer
-     * <code>k</code>, the value <code>λ = s k / n</code> is
-     * computed to <code>c</code> bits of accuracy.
-     * @param k The parameter <code>k</code>.
-     * @param s The curve parameter <code>s<sub>0</sub></code> or
-     * <code>s<sub>1</sub></code>.
-     * @param vm The Lucas Sequence element <code>V<sub>m</sub></code>.
-     * @param a The parameter <code>a</code> of the elliptic curve.
-     * @param m The bit length of the finite field
-     * <code><b>F</b><sub>m</sub></code>.
-     * @param c The number of bits of accuracy, i.e. the scale of the returned
-     * <code>SimpleBigDecimal</code>.
-     * @return The value <code>λ = s k / n</code> computed to
-     * <code>c</code> bits of accuracy.
-     */
-    public static SimpleBigDecimal approximateDivisionByN(BigInteger k,
-            BigInteger s, BigInteger vm, byte a, int m, int c)
-    {
-        int _k = (m + 5)/2 + c;
-        BigInteger ns = k.shiftRight(m - _k - 2 + a);
-
-        BigInteger gs = s.multiply(ns);
-
-        BigInteger hs = gs.shiftRight(m);
-
-        BigInteger js = vm.multiply(hs);
-
-        BigInteger gsPlusJs = gs.add(js);
-        BigInteger ls = gsPlusJs.shiftRight(_k-c);
-        if (gsPlusJs.testBit(_k-c-1))
-        {
-            // round up
-            ls = ls.add(ECConstants.ONE);
-        }
-
-        return new SimpleBigDecimal(ls, c);
-    }
-
-    /**
-     * Computes the <code>τ</code>-adic NAF (non-adjacent form) of an
-     * element <code>λ</code> of <code><b>Z</b>[τ]</code>.
-     * @param mu The parameter <code>μ</code> of the elliptic curve.
-     * @param lambda The element <code>λ</code> of
-     * <code><b>Z</b>[τ]</code>.
-     * @return The <code>τ</code>-adic NAF of <code>λ</code>.
-     */
-    public static byte[] tauAdicNaf(byte mu, ZTauElement lambda)
-    {
-        if (!((mu == 1) || (mu == -1)))
-        {
-            throw new IllegalArgumentException("mu must be 1 or -1");
-        }
-        
-        BigInteger norm = norm(mu, lambda);
-
-        // Ceiling of log2 of the norm 
-        int log2Norm = norm.bitLength();
-
-        // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
-        int maxLength = log2Norm > 30 ? log2Norm + 4 : 34;
-
-        // The array holding the TNAF
-        byte[] u = new byte[maxLength];
-        int i = 0;
-
-        // The actual length of the TNAF
-        int length = 0;
-
-        BigInteger r0 = lambda.u;
-        BigInteger r1 = lambda.v;
-
-        while(!((r0.equals(ECConstants.ZERO)) && (r1.equals(ECConstants.ZERO))))
-        {
-            // If r0 is odd
-            if (r0.testBit(0))
-            {
-                u[i] = (byte) ECConstants.TWO.subtract((r0.subtract(r1.shiftLeft(1))).mod(ECConstants.FOUR)).intValue();
-
-                // r0 = r0 - u[i]
-                if (u[i] == 1)
-                {
-                    r0 = r0.clearBit(0);
-                }
-                else
-                {
-                    // u[i] == -1
-                    r0 = r0.add(ECConstants.ONE);
-                }
-                length = i;
-            }
-            else
-            {
-                u[i] = 0;
-            }
-
-            BigInteger t = r0;
-            BigInteger s = r0.shiftRight(1);
-            if (mu == 1)
-            {
-                r0 = r1.add(s);
-            }
-            else
-            {
-                // mu == -1
-                r0 = r1.subtract(s);
-            }
-
-            r1 = t.shiftRight(1).negate();
-            i++;
-        }
-
-        length++;
-
-        // Reduce the TNAF array to its actual length
-        byte[] tnaf = new byte[length];
-        System.arraycopy(u, 0, tnaf, 0, length);
-        return tnaf;
-    }
-
-    /**
-     * Applies the operation <code>τ()</code> to an
-     * <code>ECPoint.F2m</code>. 
-     * @param p The ECPoint.F2m to which <code>τ()</code> is applied.
-     * @return <code>τ(p)</code>
-     */
-    public static ECPoint.F2m tau(ECPoint.F2m p)
-    {
-        if (p.isInfinity())
-        {
-            return p;
-        }
-
-        ECFieldElement x = p.getX();
-        ECFieldElement y = p.getY();
-
-        return new ECPoint.F2m(p.getCurve(), x.square(), y.square(), p.isCompressed());
-    }
-
-    /**
-     * Returns the parameter <code>μ</code> of the elliptic curve.
-     * @param curve The elliptic curve from which to obtain <code>μ</code>.
-     * The curve must be a Koblitz curve, i.e. <code>a</code> equals
-     * <code>0</code> or <code>1</code> and <code>b</code> equals
-     * <code>1</code>. 
-     * @return <code>μ</code> of the elliptic curve.
-     * @throws IllegalArgumentException if the given ECCurve is not a Koblitz
-     * curve.
-     */
-    public static byte getMu(ECCurve.F2m curve)
-    {
-        BigInteger a = curve.getA().toBigInteger();
-        byte mu;
-
-        if (a.equals(ECConstants.ZERO))
-        {
-            mu = -1;
-        }
-        else if (a.equals(ECConstants.ONE))
-        {
-            mu = 1;
-        }
-        else
-        {
-            throw new IllegalArgumentException("No Koblitz curve (ABC), " +
-                    "TNAF multiplication not possible");
-        }
-        return mu;
-    }
-
-    /**
-     * Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
-     * <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
-     * <code>V<sub>k</sub></code>.
-     * @param mu The parameter <code>μ</code> of the elliptic curve.
-     * @param k The index of the second element of the Lucas Sequence to be
-     * returned.
-     * @param doV If set to true, computes <code>V<sub>k-1</sub></code> and
-     * <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and
-     * <code>U<sub>k</sub></code>.
-     * @return An array with 2 elements, containing <code>U<sub>k-1</sub></code>
-     * and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code>
-     * and <code>V<sub>k</sub></code>.
-     */
-    public static BigInteger[] getLucas(byte mu, int k, boolean doV)
-    {
-        if (!((mu == 1) || (mu == -1)))
-        {
-            throw new IllegalArgumentException("mu must be 1 or -1");
-        }
-
-        BigInteger u0;
-        BigInteger u1;
-        BigInteger u2;
-
-        if (doV)
-        {
-            u0 = ECConstants.TWO;
-            u1 = BigInteger.valueOf(mu);
-        }
-        else
-        {
-            u0 = ECConstants.ZERO;
-            u1 = ECConstants.ONE;
-        }
-
-        for (int i = 1; i < k; i++)
-        {
-            // u2 = mu*u1 - 2*u0;
-            BigInteger s = null;
-            if (mu == 1)
-            {
-                s = u1;
-            }
-            else
-            {
-                // mu == -1
-                s = u1.negate();
-            }
-            
-            u2 = s.subtract(u0.shiftLeft(1));
-            u0 = u1;
-            u1 = u2;
-//            System.out.println(i + ": " + u2);
-//            System.out.println();
-        }
-
-        BigInteger[] retVal = {u0, u1};
-        return retVal;
-    }
-
-    /**
-     * Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is
-     * 4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for
-     * <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code> 
-     * @param mu The parameter <code>μ</code> of the elliptic curve.
-     * @param w The window width of the WTNAF.
-     * @return the auxiliary value <code>t<sub>w</sub></code>
-     */
-    public static BigInteger getTw(byte mu, int w)
-    {
-        if (w == 4)
-        {
-            if (mu == 1)
-            {
-                return BigInteger.valueOf(6);
-            }
-            else
-            {
-                // mu == -1
-                return BigInteger.valueOf(10);
-            }
-        }
-        else
-        {
-            // For w <> 4, the values must be computed
-            BigInteger[] us = getLucas(mu, w, false);
-            BigInteger twoToW = ECConstants.ZERO.setBit(w);
-            BigInteger u1invert = us[1].modInverse(twoToW);
-            BigInteger tw;
-            tw = ECConstants.TWO.multiply(us[0]).multiply(u1invert).mod(twoToW);
-//            System.out.println("mu = " + mu);
-//            System.out.println("tw = " + tw);
-            return tw;
-        }
-    }
-
-    /**
-     * Computes the auxiliary values <code>s<sub>0</sub></code> and
-     * <code>s<sub>1</sub></code> used for partial modular reduction. 
-     * @param curve The elliptic curve for which to compute
-     * <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>.
-     * @throws IllegalArgumentException if <code>curve</code> is not a
-     * Koblitz curve (Anomalous Binary Curve, ABC).
-     */
-    public static BigInteger[] getSi(ECCurve.F2m curve)
-    {
-        if (!curve.isKoblitz())
-        {
-            throw new IllegalArgumentException("si is defined for Koblitz curves only");
-        }
-
-        int m = curve.getM();
-        int a = curve.getA().toBigInteger().intValue();
-        byte mu = curve.getMu();
-        int h = curve.getH().intValue();
-        int index = m + 3 - a;
-        BigInteger[] ui = getLucas(mu, index, false);
-
-        BigInteger dividend0;
-        BigInteger dividend1;
-        if (mu == 1)
-        {
-            dividend0 = ECConstants.ONE.subtract(ui[1]);
-            dividend1 = ECConstants.ONE.subtract(ui[0]);
-        }
-        else if (mu == -1)
-        {
-            dividend0 = ECConstants.ONE.add(ui[1]);
-            dividend1 = ECConstants.ONE.add(ui[0]);
-        }
-        else
-        {
-            throw new IllegalArgumentException("mu must be 1 or -1");
-        }
-
-        BigInteger[] si = new BigInteger[2];
-
-        if (h == 2)
-        {
-            si[0] = dividend0.shiftRight(1);
-            si[1] = dividend1.shiftRight(1).negate();
-        }
-        else if (h == 4)
-        {
-            si[0] = dividend0.shiftRight(2);
-            si[1] = dividend1.shiftRight(2).negate();
-        }
-        else
-        {
-            throw new IllegalArgumentException("h (Cofactor) must be 2 or 4");
-        }
-
-        return si;
-    }
-
-    /**
-     * Partial modular reduction modulo
-     * <code>(τ<sup>m</sup> - 1)/(τ - 1)</code>.
-     * @param k The integer to be reduced.
-     * @param m The bitlength of the underlying finite field.
-     * @param a The parameter <code>a</code> of the elliptic curve.
-     * @param s The auxiliary values <code>s<sub>0</sub></code> and
-     * <code>s<sub>1</sub></code>.
-     * @param mu The parameter μ of the elliptic curve.
-     * @param c The precision (number of bits of accuracy) of the partial
-     * modular reduction.
-     * @return <code>ρ := k partmod (τ<sup>m</sup> - 1)/(τ - 1)</code>
-     */
-    public static ZTauElement partModReduction(BigInteger k, int m, byte a,
-            BigInteger[] s, byte mu, byte c)
-    {
-        // d0 = s[0] + mu*s[1]; mu is either 1 or -1
-        BigInteger d0;
-        if (mu == 1)
-        {
-            d0 = s[0].add(s[1]);
-        }
-        else
-        {
-            d0 = s[0].subtract(s[1]);
-        }
-
-        BigInteger[] v = getLucas(mu, m, true);
-        BigInteger vm = v[1];
-
-        SimpleBigDecimal lambda0 = approximateDivisionByN(
-                k, s[0], vm, a, m, c);
-        
-        SimpleBigDecimal lambda1 = approximateDivisionByN(
-                k, s[1], vm, a, m, c);
-
-        ZTauElement q = round(lambda0, lambda1, mu);
-
-        // r0 = n - d0*q0 - 2*s1*q1
-        BigInteger r0 = k.subtract(d0.multiply(q.u)).subtract(
-                BigInteger.valueOf(2).multiply(s[1]).multiply(q.v));
-
-        // r1 = s1*q0 - s0*q1
-        BigInteger r1 = s[1].multiply(q.u).subtract(s[0].multiply(q.v));
-        
-        return new ZTauElement(r0, r1);
-    }
-
-    /**
-     * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
-     * by a <code>BigInteger</code> using the reduced <code>τ</code>-adic
-     * NAF (RTNAF) method.
-     * @param p The ECPoint.F2m to multiply.
-     * @param k The <code>BigInteger</code> by which to multiply <code>p</code>.
-     * @return <code>k * p</code>
-     */
-    public static ECPoint.F2m multiplyRTnaf(ECPoint.F2m p, BigInteger k)
-    {
-        ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
-        int m = curve.getM();
-        byte a = (byte) curve.getA().toBigInteger().intValue();
-        byte mu = curve.getMu();
-        BigInteger[] s = curve.getSi();
-        ZTauElement rho = partModReduction(k, m, a, s, mu, (byte)10);
-
-        return multiplyTnaf(p, rho);
-    }
-
-    /**
-     * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
-     * by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
-     * using the <code>τ</code>-adic NAF (TNAF) method.
-     * @param p The ECPoint.F2m to multiply.
-     * @param lambda The element <code>λ</code> of
-     * <code><b>Z</b>[τ]</code>.
-     * @return <code>λ * p</code>
-     */
-    public static ECPoint.F2m multiplyTnaf(ECPoint.F2m p, ZTauElement lambda)
-    {
-        ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
-        byte mu = curve.getMu();
-        byte[] u = tauAdicNaf(mu, lambda);
-
-        ECPoint.F2m q = multiplyFromTnaf(p, u);
-
-        return q;
-    }
-
-    /**
-    * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m}
-    * by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
-    * using the <code>τ</code>-adic NAF (TNAF) method, given the TNAF
-    * of <code>λ</code>.
-    * @param p The ECPoint.F2m to multiply.
-    * @param u The the TNAF of <code>λ</code>..
-    * @return <code>λ * p</code>
-    */
-    public static ECPoint.F2m multiplyFromTnaf(ECPoint.F2m p, byte[] u)
-    {
-        ECCurve.F2m curve = (ECCurve.F2m)p.getCurve();
-        ECPoint.F2m q = (ECPoint.F2m) curve.getInfinity();
-        for (int i = u.length - 1; i >= 0; i--)
-        {
-            q = tau(q);
-            if (u[i] == 1)
-            {
-                q = (ECPoint.F2m)q.addSimple(p);
-            }
-            else if (u[i] == -1)
-            {
-                q = (ECPoint.F2m)q.subtractSimple(p);
-            }
-        }
-        return q;
-    }
-
-    /**
-     * Computes the <code>[τ]</code>-adic window NAF of an element
-     * <code>λ</code> of <code><b>Z</b>[τ]</code>.
-     * @param mu The parameter μ of the elliptic curve.
-     * @param lambda The element <code>λ</code> of
-     * <code><b>Z</b>[τ]</code> of which to compute the
-     * <code>[τ]</code>-adic NAF.
-     * @param width The window width of the resulting WNAF.
-     * @param pow2w 2<sup>width</sup>.
-     * @param tw The auxiliary value <code>t<sub>w</sub></code>.
-     * @param alpha The <code>α<sub>u</sub></code>'s for the window width.
-     * @return The <code>[τ]</code>-adic window NAF of
-     * <code>λ</code>.
-     */
-    public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda,
-            byte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha)
-    {
-        if (!((mu == 1) || (mu == -1)))
-        {
-            throw new IllegalArgumentException("mu must be 1 or -1");
-        }
-
-        BigInteger norm = norm(mu, lambda);
-
-        // Ceiling of log2 of the norm 
-        int log2Norm = norm.bitLength();
-
-        // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
-        int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width;
-
-        // The array holding the TNAF
-        byte[] u = new byte[maxLength];
-
-        // 2^(width - 1)
-        BigInteger pow2wMin1 = pow2w.shiftRight(1);
-
-        // Split lambda into two BigIntegers to simplify calculations
-        BigInteger r0 = lambda.u;
-        BigInteger r1 = lambda.v;
-        int i = 0;
-
-        // while lambda <> (0, 0)
-        while (!((r0.equals(ECConstants.ZERO))&&(r1.equals(ECConstants.ZERO))))
-        {
-            // if r0 is odd
-            if (r0.testBit(0))
-            {
-                // uUnMod = r0 + r1*tw mod 2^width
-                BigInteger uUnMod
-                    = r0.add(r1.multiply(tw)).mod(pow2w);
-                
-                byte uLocal;
-                // if uUnMod >= 2^(width - 1)
-                if (uUnMod.compareTo(pow2wMin1) >= 0)
-                {
-                    uLocal = (byte) uUnMod.subtract(pow2w).intValue();
-                }
-                else
-                {
-                    uLocal = (byte) uUnMod.intValue();
-                }
-                // uLocal is now in [-2^(width-1), 2^(width-1)-1]
-
-                u[i] = uLocal;
-                boolean s = true;
-                if (uLocal < 0)
-                {
-                    s = false;
-                    uLocal = (byte)-uLocal;
-                }
-                // uLocal is now >= 0
-
-                if (s)
-                {
-                    r0 = r0.subtract(alpha[uLocal].u);
-                    r1 = r1.subtract(alpha[uLocal].v);
-                }
-                else
-                {
-                    r0 = r0.add(alpha[uLocal].u);
-                    r1 = r1.add(alpha[uLocal].v);
-                }
-            }
-            else
-            {
-                u[i] = 0;
-            }
-
-            BigInteger t = r0;
-
-            if (mu == 1)
-            {
-                r0 = r1.add(r0.shiftRight(1));
-            }
-            else
-            {
-                // mu == -1
-                r0 = r1.subtract(r0.shiftRight(1));
-            }
-            r1 = t.shiftRight(1).negate();
-            i++;
-        }
-        return u;
-    }
-
-    /**
-     * Does the precomputation for WTNAF multiplication.
-     * @param p The <code>ECPoint</code> for which to do the precomputation.
-     * @param a The parameter <code>a</code> of the elliptic curve.
-     * @return The precomputation array for <code>p</code>. 
-     */
-    public static ECPoint.F2m[] getPreComp(ECPoint.F2m p, byte a)
-    {
-        ECPoint.F2m[] pu;
-        pu = new ECPoint.F2m[16];
-        pu[1] = p;
-        byte[][] alphaTnaf;
-        if (a == 0)
-        {
-            alphaTnaf = Tnaf.alpha0Tnaf;
-        }
-        else
-        {
-            // a == 1
-            alphaTnaf = Tnaf.alpha1Tnaf;
-        }
-
-        int precompLen = alphaTnaf.length;
-        for (int i = 3; i < precompLen; i = i + 2)
-        {
-            pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]);
-        }
-        
-        return pu;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/math/ec/ZTauElement.java b/azureus2/src/org/bouncycastle/math/ec/ZTauElement.java
deleted file mode 100644
index 7402f22..0000000
--- a/azureus2/src/org/bouncycastle/math/ec/ZTauElement.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.bouncycastle.math.ec;
-
-import java.math.BigInteger;
-
-/**
- * Class representing an element of <code><b>Z</b>[τ]</code>. Let
- * <code>λ</code> be an element of <code><b>Z</b>[τ]</code>. Then
- * <code>λ</code> is given as <code>λ = u + vτ</code>. The
- * components <code>u</code> and <code>v</code> may be used directly, there
- * are no accessor methods.
- * Immutable class.
- */
-class ZTauElement
-{
-    /**
-     * The "real" part of <code>λ</code>.
-     */
-    public final BigInteger u;
-
-    /**
-     * The "<code>τ</code>-adic" part of <code>λ</code>.
-     */
-    public final BigInteger v;
-
-    /**
-     * Constructor for an element <code>λ</code> of
-     * <code><b>Z</b>[τ]</code>.
-     * @param u The "real" part of <code>λ</code>.
-     * @param v The "<code>τ</code>-adic" part of
-     * <code>λ</code>.
-     */
-    public ZTauElement(BigInteger u, BigInteger v)
-    {
-        this.u = u;
-        this.v = v;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/openssl/PEMReader.java b/azureus2/src/org/bouncycastle/openssl/PEMReader.java
deleted file mode 100644
index dbd15e2..0000000
--- a/azureus2/src/org/bouncycastle/openssl/PEMReader.java
+++ /dev/null
@@ -1,543 +0,0 @@
-package org.bouncycastle.openssl;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.cms.ContentInfo;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.sec.ECPrivateKeyStructure;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import org.bouncycastle.jce.ECNamedCurveTable;
-import org.bouncycastle.jce.PKCS10CertificationRequest;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.x509.X509AttributeCertificate;
-import org.bouncycastle.x509.X509V2AttributeCertificate;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.Reader;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PublicKey;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509CRL;
-import java.security.cert.X509Certificate;
-import java.security.spec.DSAPrivateKeySpec;
-import java.security.spec.DSAPublicKeySpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.RSAPrivateCrtKeySpec;
-import java.security.spec.RSAPublicKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.StringTokenizer;
-
-/**
- * Class for reading OpenSSL PEM encoded streams containing 
- * X509 certificates, PKCS8 encoded keys and PKCS7 objects.
- * <p>
- * In the case of PKCS7 objects the reader will return a CMS ContentInfo object. Keys and
- * Certificates will be returned using the appropriate java.security type.
- */
-public class PEMReader extends BufferedReader
-{
-    private final PasswordFinder    pFinder;
-    private final String            provider;
-
-    /**
-     * Create a new PEMReader
-     *
-     * @param reader the Reader
-     */
-    public PEMReader(
-        Reader reader)
-    {
-        this(reader, null, BouncyCastleProvider.PROVIDER_NAME);
-    }
-
-    /**
-     * Create a new PEMReader with a password finder
-     *
-     * @param reader the Reader
-     * @param pFinder the password finder
-     */
-    public PEMReader(
-        Reader          reader,
-        PasswordFinder  pFinder)
-    {
-        this(reader, pFinder, BouncyCastleProvider.PROVIDER_NAME);
-    }
-
-    /**
-     * Create a new PEMReader with a password finder
-     *
-     * @param reader the Reader
-     * @param pFinder the password finder
-     * @param provider the cryptography provider to use
-     */
-    public PEMReader(
-        Reader          reader,
-        PasswordFinder  pFinder,
-        String          provider)
-    {
-        super(reader);
-
-        this.pFinder = pFinder;
-        this.provider = provider;
-    }
-
-    public Object readObject()
-        throws IOException
-    {
-        String  line;
-
-        while ((line = readLine()) != null)
-        {
-            if (line.indexOf("-----BEGIN PUBLIC KEY") != -1)
-            {
-                return readPublicKey("-----END PUBLIC KEY");
-            }
-            if (line.indexOf("-----BEGIN RSA PUBLIC KEY") != -1)
-            {
-                return readRSAPublicKey("-----END RSA PUBLIC KEY");
-            }
-            if (line.indexOf("-----BEGIN CERTIFICATE REQUEST") != -1)
-            {
-                return readCertificateRequest("-----END CERTIFICATE REQUEST");
-            }
-            if (line.indexOf("-----BEGIN NEW CERTIFICATE REQUEST") != -1)
-            {
-                return readCertificateRequest("-----END NEW CERTIFICATE REQUEST");
-            }
-            if (line.indexOf("-----BEGIN CERTIFICATE") != -1)
-            {
-                return readCertificate("-----END CERTIFICATE");
-            }
-            if (line.indexOf("-----BEGIN PKCS7") != -1)
-            {
-               return readPKCS7("-----END PKCS7");
-            } 
-            if (line.indexOf("-----BEGIN X509 CERTIFICATE") != -1)
-            {
-                return readCertificate("-----END X509 CERTIFICATE");
-            }
-            if (line.indexOf("-----BEGIN X509 CRL") != -1)
-            {
-                return readCRL("-----END X509 CRL");
-            }
-            if (line.indexOf("-----BEGIN ATTRIBUTE CERTIFICATE") != -1)
-            {
-                return readAttributeCertificate("-----END ATTRIBUTE CERTIFICATE");
-            }
-            if (line.indexOf("-----BEGIN RSA PRIVATE KEY") != -1)
-            {
-                try
-                {
-                    return readKeyPair("RSA", "-----END RSA PRIVATE KEY");
-                }
-                catch (Exception e)
-                {
-                    throw new IOException(
-                        "problem creating RSA private key: " + e.toString());
-                }
-            }
-            if (line.indexOf("-----BEGIN DSA PRIVATE KEY") != -1)
-            {
-                try
-                {
-                    return readKeyPair("DSA", "-----END DSA PRIVATE KEY");
-                }
-                catch (Exception e)
-                {
-                    throw new IOException(
-                        "problem creating DSA private key: " + e.toString());
-                }
-            }
-            if (line.indexOf("-----BEGIN EC PARAMETERS-----") != -1)
-            {
-                return readECParameters("-----END EC PARAMETERS-----");
-            }
-            if (line.indexOf("-----BEGIN EC PRIVATE KEY-----") != -1)
-            {
-                return readECPrivateKey("-----END EC PRIVATE KEY-----");
-            }
-        }
-
-        return null;
-    }
-
-    private byte[] readBytes(String endMarker)
-        throws IOException
-    {
-        String          line;
-        StringBuffer    buf = new StringBuffer();
-  
-        while ((line = readLine()) != null)
-        {
-            if (line.indexOf(endMarker) != -1)
-            {
-                break;
-            }
-            buf.append(line.trim());
-        }
-
-        if (line == null)
-        {
-            throw new IOException(endMarker + " not found");
-        }
-
-        return Base64.decode(buf.toString());
-    }
-
-    private PublicKey readRSAPublicKey(String endMarker) 
-        throws IOException 
-    {
-        ByteArrayInputStream bAIS = new ByteArrayInputStream(readBytes(endMarker));
-        ASN1InputStream ais = new ASN1InputStream(bAIS);
-        Object asnObject = ais.readObject();
-        ASN1Sequence sequence = (ASN1Sequence) asnObject;
-        RSAPublicKeyStructure rsaPubStructure = new RSAPublicKeyStructure(sequence);
-        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(
-                    rsaPubStructure.getModulus(), 
-                    rsaPubStructure.getPublicExponent());
-
-        try 
-        {
-            KeyFactory keyFact = KeyFactory.getInstance("RSA", provider);
-
-            return keyFact.generatePublic(keySpec);
-        }
-        catch (NoSuchProviderException e)
-        {
-            throw new IOException("can't find provider " + provider);
-        }
-        catch (Exception e)
-        {
-            throw new IOException("problem extracting key: " + e.toString());
-        }
-    }
-
-    private PublicKey readPublicKey(String endMarker)
-        throws IOException
-    {
-        KeySpec keySpec = new X509EncodedKeySpec(readBytes(endMarker));
-        String[] algorithms = { "DSA", "RSA" };
-        for (int i = 0; i < algorithms.length; i++) 
-        {
-            try 
-            {
-                KeyFactory keyFact = KeyFactory.getInstance(algorithms[i],
-                                provider);
-                PublicKey pubKey = keyFact.generatePublic(keySpec);
-                
-                return pubKey;
-            }
-            catch (NoSuchAlgorithmException e) 
-            { 
-                // ignore
-            }
-            catch (InvalidKeySpecException e) 
-            { 
-                // ignore
-            }
-            catch (NoSuchProviderException e)
-            {
-                throw new RuntimeException("can't find provider " + provider);
-            }
-        }
-        
-        return null;
-    }
-
-    /**
-     * Reads in a X509Certificate.
-     *
-     * @return the X509Certificate
-     * @throws IOException if an I/O error occured
-     */
-    private X509Certificate readCertificate(
-        String  endMarker)
-        throws IOException
-    {
-        ByteArrayInputStream    bIn = new ByteArrayInputStream(readBytes(endMarker));
-
-        try
-        {
-            CertificateFactory certFact
-                    = CertificateFactory.getInstance("X.509", provider);
-
-            return (X509Certificate)certFact.generateCertificate(bIn);
-        }
-        catch (Exception e)
-        {
-            throw new IOException("problem parsing cert: " + e.toString());
-        }
-    }
-
-    /**
-     * Reads in a X509CRL.
-     *
-     * @return the X509Certificate
-     * @throws IOException if an I/O error occured
-     */
-    private X509CRL readCRL(
-        String  endMarker)
-        throws IOException
-    {
-        ByteArrayInputStream    bIn = new ByteArrayInputStream(readBytes(endMarker));
-
-        try
-        {
-            CertificateFactory certFact
-                    = CertificateFactory.getInstance("X.509", provider);
-
-            return (X509CRL)certFact.generateCRL(bIn);
-        }
-        catch (Exception e)
-        {
-            throw new IOException("problem parsing cert: " + e.toString());
-        }
-    }
-
-    /**
-     * Reads in a PKCS10 certification request.
-     *
-     * @return the certificate request.
-     * @throws IOException if an I/O error occured
-     */
-    private PKCS10CertificationRequest readCertificateRequest(
-        String  endMarker)
-        throws IOException
-    {
-        try
-        {
-            return new PKCS10CertificationRequest(readBytes(endMarker));
-        }
-        catch (Exception e)
-        {
-            throw new IOException("problem parsing cert: " + e.toString());
-        }
-    }
-
-    /**
-     * Reads in a X509 Attribute Certificate.
-     *
-     * @return the X509 Attribute Certificate
-     * @throws IOException if an I/O error occured
-     */
-    private X509AttributeCertificate readAttributeCertificate(
-        String  endMarker)
-        throws IOException
-    {
-        return new X509V2AttributeCertificate(readBytes(endMarker));
-    }
-    
-    /**
-     * Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS
-     * API.
-     *
-     * @return the X509Certificate
-     * @throws IOException if an I/O error occured
-     */
-    private ContentInfo readPKCS7(
-        String  endMarker)
-        throws IOException
-    {
-        String                                  line;
-        StringBuffer                        buf = new StringBuffer();
-        ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
-  
-        while ((line = readLine()) != null)
-        {
-            if (line.indexOf(endMarker) != -1)
-            {
-                break;
-            }
-            
-            line = line.trim();
-            
-            buf.append(line.trim());
-            
-            Base64.decode(buf.substring(0, (buf.length() / 4) * 4), bOut);
-
-            buf.delete(0, (buf.length() / 4) * 4);
-        }
-
-        if (buf.length() != 0)
-        {
-            throw new RuntimeException("base64 data appears to be truncated");
-        }
-        
-        if (line == null)
-        {
-            throw new IOException(endMarker + " not found");
-        }
-
-        ByteArrayInputStream    bIn = new ByteArrayInputStream(bOut.toByteArray());
-
-        try
-        {
-            ASN1InputStream aIn = new ASN1InputStream(bIn);
-
-            return ContentInfo.getInstance(aIn.readObject());
-        }
-        catch (Exception e)
-        {
-            throw new IOException("problem parsing PKCS7 object: " + e.toString());
-        }
-    }
-
-    /**
-     * Read a Key Pair
-     */
-    private KeyPair readKeyPair(
-        String  type,
-        String  endMarker)
-        throws Exception
-    {
-        boolean         isEncrypted = false;
-        String          line = null;
-        String          dekInfo = null;
-        StringBuffer    buf = new StringBuffer();
-
-        while ((line = readLine()) != null)
-        {
-            if (line.startsWith("Proc-Type: 4,ENCRYPTED"))
-            {
-                isEncrypted = true;
-            }
-            else if (line.startsWith("DEK-Info:"))
-            {
-                dekInfo = line.substring(10);
-            }
-            else if (line.indexOf(endMarker) != -1)
-            {
-                break;
-            }
-            else
-            {
-                buf.append(line.trim());
-            }
-        }
-
-        //
-        // extract the key
-        //
-        byte[] keyBytes = Base64.decode(buf.toString());
-
-        if (isEncrypted)
-        {
-            if (pFinder == null)
-            {
-                throw new IOException("No password finder specified, but a password is required");
-            }
-
-            char[] password = pFinder.getPassword();
-
-            if (password == null)
-            {
-                throw new IOException("Password is null, but a password is required");
-            }
-
-            StringTokenizer tknz = new StringTokenizer(dekInfo, ",");
-            String          dekAlgName = tknz.nextToken();
-            byte[]          iv = Hex.decode(tknz.nextToken());
-
-            keyBytes = PEMUtilities.crypt(false, provider, keyBytes, password, dekAlgName, iv);
-        }
-
-
-        KeySpec                 pubSpec, privSpec;
-        ByteArrayInputStream    bIn = new ByteArrayInputStream(keyBytes);
-        ASN1InputStream         aIn = new ASN1InputStream(bIn);
-        ASN1Sequence            seq = (ASN1Sequence)aIn.readObject();
-
-        if (type.equals("RSA"))
-        {
-//            DERInteger              v = (DERInteger)seq.getObjectAt(0);
-            DERInteger              mod = (DERInteger)seq.getObjectAt(1);
-            DERInteger              pubExp = (DERInteger)seq.getObjectAt(2);
-            DERInteger              privExp = (DERInteger)seq.getObjectAt(3);
-            DERInteger              p1 = (DERInteger)seq.getObjectAt(4);
-            DERInteger              p2 = (DERInteger)seq.getObjectAt(5);
-            DERInteger              exp1 = (DERInteger)seq.getObjectAt(6);
-            DERInteger              exp2 = (DERInteger)seq.getObjectAt(7);
-            DERInteger              crtCoef = (DERInteger)seq.getObjectAt(8);
-
-            pubSpec = new RSAPublicKeySpec(
-                        mod.getValue(), pubExp.getValue());
-            privSpec = new RSAPrivateCrtKeySpec(
-                    mod.getValue(), pubExp.getValue(), privExp.getValue(),
-                    p1.getValue(), p2.getValue(),
-                    exp1.getValue(), exp2.getValue(),
-                    crtCoef.getValue());
-        }
-        else    // "DSA"
-        {
-//            DERInteger              v = (DERInteger)seq.getObjectAt(0);
-            DERInteger              p = (DERInteger)seq.getObjectAt(1);
-            DERInteger              q = (DERInteger)seq.getObjectAt(2);
-            DERInteger              g = (DERInteger)seq.getObjectAt(3);
-            DERInteger              y = (DERInteger)seq.getObjectAt(4);
-            DERInteger              x = (DERInteger)seq.getObjectAt(5);
-
-            privSpec = new DSAPrivateKeySpec(
-                        x.getValue(), p.getValue(),
-                            q.getValue(), g.getValue());
-            pubSpec = new DSAPublicKeySpec(
-                        y.getValue(), p.getValue(),
-                            q.getValue(), g.getValue());
-        }
-
-        KeyFactory          fact = KeyFactory.getInstance(type, provider);
-
-        return new KeyPair(
-                    fact.generatePublic(pubSpec),
-                    fact.generatePrivate(privSpec));
-    }
-
-    private ECNamedCurveParameterSpec readECParameters(String endMarker)
-        throws IOException
-    {
-        DERObjectIdentifier oid = (DERObjectIdentifier)ASN1Object.fromByteArray(readBytes(endMarker));
-
-        return ECNamedCurveTable.getParameterSpec(oid.getId());
-    }
-
-    private KeyPair readECPrivateKey(String endMarker)
-        throws IOException
-    {
-        try
-        {
-            ECPrivateKeyStructure pKey = new ECPrivateKeyStructure((ASN1Sequence)ASN1Object.fromByteArray(readBytes(endMarker)));
-            AlgorithmIdentifier   algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, pKey.getParameters());
-            PrivateKeyInfo        privInfo = new PrivateKeyInfo(algId, pKey.getDERObject());
-            SubjectPublicKeyInfo  pubInfo = new SubjectPublicKeyInfo(algId, pKey.getPublicKey().getBytes());
-            PKCS8EncodedKeySpec   privSpec = new PKCS8EncodedKeySpec(privInfo.getEncoded());
-            X509EncodedKeySpec    pubSpec = new X509EncodedKeySpec(pubInfo.getEncoded());
-            KeyFactory            fact = KeyFactory.getInstance("ECDSA", provider);
-
-            return new KeyPair(fact.generatePublic(pubSpec), fact.generatePrivate(privSpec));
-        }
-        catch (ClassCastException e)
-        { 
-            throw new IOException("wrong ASN.1 object found in stream");
-        }
-        catch (Exception e)
-        {
-            throw new IOException("problem parsing EC private key: " + e);
-        }
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/openssl/PEMUtilities.java b/azureus2/src/org/bouncycastle/openssl/PEMUtilities.java
deleted file mode 100644
index 3262243..0000000
--- a/azureus2/src/org/bouncycastle/openssl/PEMUtilities.java
+++ /dev/null
@@ -1,185 +0,0 @@
-package org.bouncycastle.openssl;
-
-import org.bouncycastle.crypto.PBEParametersGenerator;
-import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
-import org.bouncycastle.crypto.params.KeyParameter;
-
-import javax.crypto.Cipher;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.RC2ParameterSpec;
-import java.io.IOException;
-import java.security.Key;
-import java.security.spec.AlgorithmParameterSpec;
-
-final class PEMUtilities
-{
-    static byte[] crypt(
-        boolean encrypt,
-        String  provider,
-        byte[]  bytes,
-        char[]  password,
-        String  dekAlgName,
-        byte[]  iv)
-        throws IOException
-    {
-        AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
-        String                 alg;
-        String                 blockMode = "CBC";
-        String                 padding = "PKCS5Padding";
-        Key                    sKey;
-
-
-        // Figure out block mode and padding.
-        if (dekAlgName.endsWith("-CFB"))
-        {
-            blockMode = "CFB";
-            padding = "NoPadding";
-        }
-        if (dekAlgName.endsWith("-ECB") ||
-            "DES-EDE".equals(dekAlgName) ||
-            "DES-EDE3".equals(dekAlgName))
-        {
-            // ECB is actually the default (though seldom used) when OpenSSL
-            // uses DES-EDE (des2) or DES-EDE3 (des3).
-            blockMode = "ECB";
-            paramSpec = null;
-        }
-        if (dekAlgName.endsWith("-OFB"))
-        {
-            blockMode = "OFB";
-            padding = "NoPadding";
-        }
-
-
-        // Figure out algorithm and key size.
-        if (dekAlgName.startsWith("DES-EDE"))
-        {
-            alg = "DESede";
-            // "DES-EDE" is actually des2 in OpenSSL-speak!
-            // "DES-EDE3" is des3.
-            boolean des2 = !dekAlgName.startsWith("DES-EDE3");
-            sKey = getKey(password, alg, 24, iv, des2);
-        }
-        else if (dekAlgName.startsWith("DES-"))
-        {
-            alg = "DES";
-            sKey = getKey(password, alg, 8, iv);
-        }
-        else if (dekAlgName.startsWith("BF-"))
-        {
-            alg = "Blowfish";
-            sKey = getKey(password, alg, 16, iv);
-        }
-        else if (dekAlgName.startsWith("RC2-"))
-        {
-            alg = "RC2";
-            int keyBits = 128;
-            if (dekAlgName.startsWith("RC2-40-"))
-            {
-                keyBits = 40;
-            }
-            else if (dekAlgName.startsWith("RC2-64-"))
-            {
-                keyBits = 64;
-            }
-            sKey = getKey(password, alg, keyBits / 8, iv);
-            if (paramSpec == null) // ECB block mode
-            {
-                paramSpec = new RC2ParameterSpec(keyBits);
-            }
-            else
-            {
-                paramSpec = new RC2ParameterSpec(keyBits, iv);
-            }
-        }
-        else if (dekAlgName.startsWith("AES-"))
-        {
-            alg = "AES";
-            byte[] salt = iv;
-            if (salt.length > 8)
-            {
-                salt = new byte[8];
-                System.arraycopy(iv, 0, salt, 0, 8);
-            }
-
-            int keyBits;
-            if (dekAlgName.startsWith("AES-128-"))
-            {
-                keyBits = 128;
-            }
-            else if (dekAlgName.startsWith("AES-192-"))
-            {
-                keyBits = 192;
-            }
-            else if (dekAlgName.startsWith("AES-256-"))
-            {
-                keyBits = 256;
-            }
-            else
-            {
-                throw new IOException("unknown AES encryption with private key");
-            }
-            sKey = getKey(password, "AES", keyBits / 8, salt);
-        }
-        else
-        {
-            throw new IOException("unknown encryption with private key");
-        }
-
-        String transformation = alg + "/" + blockMode + "/" + padding;
-
-        try
-        {
-            Cipher c = Cipher.getInstance(transformation, provider);
-            int    mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
-
-            if (paramSpec == null) // ECB block mode
-            {
-                c.init(mode, sKey);
-            }
-            else
-            {
-                c.init(mode, sKey, paramSpec);
-            }
-            return c.doFinal(bytes);
-        }
-        catch (Exception e)
-        {
-            throw new IOException("exception using cipher: " + e.toString());
-        }
-    }
-
-    private static SecretKey getKey(
-        char[]  password,
-        String  algorithm,
-        int     keyLength,
-        byte[]  salt)
-        throws IOException
-    {
-        return getKey(password, algorithm, keyLength, salt, false);
-    }
-
-    private static SecretKey getKey(
-        char[]  password,
-        String  algorithm,
-        int     keyLength,
-        byte[]  salt,
-        boolean des2)
-        throws IOException
-    {
-        OpenSSLPBEParametersGenerator   pGen = new OpenSSLPBEParametersGenerator();
-
-        pGen.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), salt);
-
-        KeyParameter keyParam;
-        keyParam = (KeyParameter) pGen.generateDerivedParameters(keyLength * 8);
-        byte[] key = keyParam.getKey();
-        if (des2 && key.length >= 24)
-        {
-            // For DES2, we must copy first 8 bytes into the last 8 bytes.
-            System.arraycopy(key, 0, key, 16, 8);
-        }
-        return new javax.crypto.spec.SecretKeySpec(key, algorithm);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/openssl/PEMWriter.java b/azureus2/src/org/bouncycastle/openssl/PEMWriter.java
deleted file mode 100644
index 0a7218c..0000000
--- a/azureus2/src/org/bouncycastle/openssl/PEMWriter.java
+++ /dev/null
@@ -1,312 +0,0 @@
-package org.bouncycastle.openssl;
-
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Object;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.cms.ContentInfo;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;
-import org.bouncycastle.asn1.x509.DSAParameter;
-import org.bouncycastle.jce.PKCS10CertificationRequest;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.Strings;
-import org.bouncycastle.util.encoders.Base64;
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.x509.X509AttributeCertificate;
-import org.bouncycastle.x509.X509V2AttributeCertificate;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.Writer;
-import java.math.BigInteger;
-import java.security.Key;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.cert.CRLException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509CRL;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.DSAParams;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.RSAPrivateCrtKey;
-import java.security.interfaces.RSAPrivateKey;
-
-/**
- * General purpose writer for OpenSSL PEM objects.
- */
-public class PEMWriter
-    extends BufferedWriter
-{
-    private String provider;
-
-    /**
-     * Base constructor.
-     * 
-     * @param out output stream to use.
-     */
-    public PEMWriter(Writer out)
-    {
-        this(out, BouncyCastleProvider.PROVIDER_NAME);
-    }
-
-    public PEMWriter(
-        Writer  out,
-        String  provider)
-    {
-        super(out);
-
-        this.provider = provider;
-    }
-
-    private void writeHexEncoded(byte[] bytes)
-        throws IOException
-    {
-        bytes = Hex.encode(bytes);
-        
-        for (int i = 0; i != bytes.length; i++)
-        {
-            this.write((char)bytes[i]);
-        }
-    }
-
-    private void writeEncoded(byte[] bytes) 
-        throws IOException
-    {
-        char[]  buf = new char[64];
-        
-        bytes = Base64.encode(bytes);
-        
-        for (int i = 0; i < bytes.length; i += buf.length)
-        {
-            int index = 0;
-            
-            while (index != buf.length)
-            {
-                if ((i + index) >= bytes.length)
-                {
-                    break;
-                }
-                buf[index] = (char)bytes[i + index];
-                index++;
-            }
-            this.write(buf, 0, index);
-            this.newLine();
-        }
-    }
-    
-    public void writeObject(
-        Object  o) 
-        throws IOException
-    {
-        String  type;
-        byte[]  encoding;
-        
-        if (o instanceof X509Certificate)
-        {
-            type = "CERTIFICATE";
-            try
-            {
-                encoding = ((X509Certificate)o).getEncoded();
-            }
-            catch (CertificateEncodingException e)
-            {
-                throw new IOException("Cannot encode object: " + e.toString());
-            }
-        }
-        else if (o instanceof X509CRL)
-        {
-            type = "X509 CRL";
-            try
-            {
-                encoding = ((X509CRL)o).getEncoded();
-            }
-            catch (CRLException e)
-            {
-                throw new IOException("Cannot encode object: " + e.toString());
-            }
-        }
-        else if (o instanceof KeyPair)
-        {
-            writeObject(((KeyPair)o).getPrivate());
-            return;
-        }
-        else if (o instanceof PrivateKey)
-        {
-            PrivateKeyInfo info = new PrivateKeyInfo(
-                (ASN1Sequence) ASN1Object.fromByteArray(((Key)o).getEncoded()));
-
-            if (o instanceof RSAPrivateKey)
-            {
-                type = "RSA PRIVATE KEY";
-
-                encoding = info.getPrivateKey().getEncoded();
-            }
-            else if (o instanceof DSAPrivateKey)
-            {
-                type = "DSA PRIVATE KEY";
-                
-                DSAParameter        p = DSAParameter.getInstance(info.getAlgorithmId().getParameters());
-                ASN1EncodableVector v = new ASN1EncodableVector();
-                
-                v.add(new DERInteger(0));
-                v.add(new DERInteger(p.getP()));
-                v.add(new DERInteger(p.getQ()));
-                v.add(new DERInteger(p.getG()));
-                
-                BigInteger x = ((DSAPrivateKey)o).getX();
-                BigInteger y = p.getG().modPow(x, p.getP());
-                
-                v.add(new DERInteger(y));
-                v.add(new DERInteger(x));
-
-                encoding = new DERSequence(v).getEncoded();
-            }
-            else
-            {
-                throw new IOException("Cannot identify private key");
-            }
-        }
-        else if (o instanceof PublicKey)
-        {
-            type = "PUBLIC KEY";
-            
-            encoding = ((PublicKey)o).getEncoded();
-        }
-        else if (o instanceof X509AttributeCertificate)
-        {
-            type = "ATTRIBUTE CERTIFICATE";
-            encoding = ((X509V2AttributeCertificate)o).getEncoded();
-        }
-        else if (o instanceof PKCS10CertificationRequest)
-        {
-            type = "CERTIFICATE REQUEST";
-            encoding = ((PKCS10CertificationRequest)o).getEncoded();
-        }
-        else if (o instanceof ContentInfo)
-        {
-            type = "PKCS7";
-            encoding = ((ContentInfo)o).getEncoded();
-        }
-        else
-        {
-            throw new IOException("unknown object passed - can't encode.");
-        }
-
-        writeHeader(type);
-        writeEncoded(encoding);
-        writeFooter(type);
-    }
-
-    public void writeObject(
-        Object       obj,
-        String       algorithm,
-        char[]       password,
-        SecureRandom random)
-        throws IOException
-    {
-        if (obj instanceof KeyPair)
-        {
-            writeObject(((KeyPair)obj).getPrivate());
-            return;
-        }
-
-
-        String type = null;
-        byte[] keyData = null;
-
-        if (obj instanceof RSAPrivateCrtKey)
-        {
-            type = "RSA PRIVATE KEY";
-
-            RSAPrivateCrtKey k = (RSAPrivateCrtKey)obj;
-
-            RSAPrivateKeyStructure keyStruct = new RSAPrivateKeyStructure(
-                k.getModulus(),
-                k.getPublicExponent(),
-                k.getPrivateExponent(),
-                k.getPrimeP(),
-                k.getPrimeQ(),
-                k.getPrimeExponentP(),
-                k.getPrimeExponentQ(),
-                k.getCrtCoefficient());
-
-            // convert to bytearray
-            keyData = keyStruct.getEncoded();
-        }
-        else if (obj instanceof DSAPrivateKey)
-        {
-            type = "DSA PRIVATE KEY";
-
-            DSAPrivateKey       k = (DSAPrivateKey)obj;
-            DSAParams           p = k.getParams();
-            ASN1EncodableVector v = new ASN1EncodableVector();
-
-            v.add(new DERInteger(0));
-            v.add(new DERInteger(p.getP()));
-            v.add(new DERInteger(p.getQ()));
-            v.add(new DERInteger(p.getG()));
-
-            BigInteger x = k.getX();
-            BigInteger y = p.getG().modPow(x, p.getP());
-
-            v.add(new DERInteger(y));
-            v.add(new DERInteger(x));
-
-            keyData = new DERSequence(v).getEncoded();
-        }
-
-        if (type == null || keyData == null)
-        {
-            // TODO Support other types?
-            throw new IllegalArgumentException("Object type not supported: " + obj.getClass().getName());
-        }
-
-
-        String dekAlgName = Strings.toUpperCase(algorithm);
-
-        // Note: For backward compatibility
-        if (dekAlgName.equals("DESEDE"))
-        {
-            dekAlgName = "DES-EDE3-CBC";
-        }
-
-        int ivLength = dekAlgName.startsWith("AES-") ? 16 : 8;
-
-        byte[] iv = new byte[ivLength];
-        random.nextBytes(iv);
-
-        byte[] encData = PEMUtilities.crypt(true, provider, keyData, password, dekAlgName, iv);
-
-
-        // write the data
-        writeHeader(type);
-        this.write("Proc-Type: 4,ENCRYPTED");
-        this.newLine();
-        this.write("DEK-Info: " + dekAlgName + ",");
-        this.writeHexEncoded(iv);
-        this.newLine();
-        this.newLine();
-        this.writeEncoded(encData);
-        writeFooter(type);
-    }
-
-    private void writeHeader(
-        String type)
-        throws IOException
-    {
-        this.write("-----BEGIN " + type + "-----");
-        this.newLine();
-    }
-
-    private void writeFooter(
-        String type)
-        throws IOException
-    {
-        this.write("-----END " + type + "-----");
-        this.newLine();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/openssl/PasswordFinder.java b/azureus2/src/org/bouncycastle/openssl/PasswordFinder.java
deleted file mode 100644
index fb89cf0..0000000
--- a/azureus2/src/org/bouncycastle/openssl/PasswordFinder.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.openssl;
-
-/**
- * call back to allow a password to be fetched when one is requested.
- */
-public interface PasswordFinder
-{
-    public char[] getPassword();
-}
diff --git a/azureus2/src/org/bouncycastle/util/Arrays.java b/azureus2/src/org/bouncycastle/util/Arrays.java
deleted file mode 100644
index 59aed3e..0000000
--- a/azureus2/src/org/bouncycastle/util/Arrays.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package org.bouncycastle.util;
-
-/**
- * General array utilities.
- */
-public final class Arrays
-{
-    private Arrays() 
-    {
-        // static class, hide constructor
-    }
-    
-    public static boolean areEqual(
-        byte[]  a,
-        byte[]  b)
-    {
-        if (a == b)
-        {
-            return true;
-        }
-
-        if (a == null || b == null)
-        {
-            return false;
-        }
-
-        if (a.length != b.length)
-        {
-            return false;
-        }
-
-        for (int i = 0; i != a.length; i++)
-        {
-            if (a[i] != b[i])
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    public static boolean areEqual(
-        int[]  a,
-        int[]  b)
-    {
-        if (a == b)
-        {
-            return true;
-        }
-
-        if (a == null || b == null)
-        {
-            return false;
-        }
-
-        if (a.length != b.length)
-        {
-            return false;
-        }
-
-        for (int i = 0; i != a.length; i++)
-        {
-            if (a[i] != b[i])
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    public static void fill(
-        byte[] array,
-        byte value)
-    {
-        for (int i = 0; i < array.length; i++)
-        {
-            array[i] = value;
-        }
-    }
-    
-    public static void fill(
-        long[] array,
-        long value)
-    {
-        for (int i = 0; i < array.length; i++)
-        {
-            array[i] = value;
-        }
-    }
-
-    public static void fill(
-        short[] array, 
-        short value)
-    {
-        for (int i = 0; i < array.length; i++)
-        {
-            array[i] = value;
-        }
-    }
-
-    public static int hashCode(byte[] data)
-    {
-        int value = 0;
-
-        if (data != null)
-        {
-            for (int i = 0; i != data.length; i++)
-            {
-                value ^= (data[i] & 0xff) << (i % 4);
-            }
-        }
-
-        return value;
-    }
-
-    public static byte[] clone(byte[] data)
-    {
-        byte[] copy = new byte[data.length];
-
-        System.arraycopy(data, 0, copy, 0, data.length);
-
-        return copy;
-    }
-
-    public static int[] clone(int[] data)
-    {
-        int[] copy = new int[data.length];
-
-        System.arraycopy(data, 0, copy, 0, data.length);
-
-        return copy;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/util/BigIntegers.java b/azureus2/src/org/bouncycastle/util/BigIntegers.java
deleted file mode 100644
index 2115799..0000000
--- a/azureus2/src/org/bouncycastle/util/BigIntegers.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.util;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * BigInteger utilities.
- */
-public final class BigIntegers
-{
-    private static final int MAX_ITERATIONS = 1000;
-    private static final BigInteger ZERO = BigInteger.valueOf(0);
-
-    /**
-     * Return the passed in value as an unsigned byte array.
-     * 
-     * @param value value to be converted.
-     * @return a byte array without a leading zero byte if present in the signed encoding.
-     */
-    public static byte[] asUnsignedByteArray(
-        BigInteger value)
-    {
-        byte[] bytes = value.toByteArray();
-        
-        if (bytes[0] == 0)
-        {
-            byte[] tmp = new byte[bytes.length - 1];
-            
-            System.arraycopy(bytes, 1, tmp, 0, tmp.length);
-            
-            return tmp;
-        }
-        
-        return bytes;
-    }
-
-    /**
-     * Return a random BigInteger not less than 'min' and not greater than 'max'
-     * 
-     * @param min the least value that may be generated
-     * @param max the greatest value that may be generated
-     * @param random the source of randomness
-     * @return a random BigInteger value in the range [min,max]
-     */
-    public static BigInteger createRandomInRange(
-        BigInteger      min,
-        BigInteger      max,
-        SecureRandom    random)
-    {
-        int cmp = min.compareTo(max);
-        if (cmp >= 0)
-        {
-            if (cmp > 0)
-            {
-                throw new IllegalArgumentException("'min' may not be greater than 'max'");
-            }
-
-            return min;
-        }
-
-        if (min.bitLength() > max.bitLength() / 2)
-        {
-            return createRandomInRange(ZERO, max.subtract(min), random).add(min);
-        }
-
-        for (int i = 0; i < MAX_ITERATIONS; ++i)
-        {
-            BigInteger x = new BigInteger(max.bitLength(), random);
-            if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0)
-            {
-                return x;
-            }
-        }
-
-        // fall back to a faster (restricted) method
-        return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/util/IPAddress.java b/azureus2/src/org/bouncycastle/util/IPAddress.java
deleted file mode 100644
index 5b8ce04..0000000
--- a/azureus2/src/org/bouncycastle/util/IPAddress.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.bouncycastle.util;
-
-import java.math.BigInteger;
-
-public class IPAddress
-{
-    private static final BigInteger ZERO = BigInteger.valueOf(0);
-    /**
-     * Validate the given IPv4 or IPv6 address.
-     * 
-     * @param address the IP address as a String.
-     * 
-     * @return true if a valid address, false otherwise
-     */
-    public static boolean isValid(
-        String address)
-    {
-        return isValidIPv4(address) || isValidIPv6(address);
-    }
-
-    /**
-     * Validate the given IPv4 address.
-     * 
-     * @param address the IP address as a String.
-     *
-     * @return true if a valid IPv4 address, false otherwise
-     */
-    private static boolean isValidIPv4(
-        String address)
-    {
-        if (address.length() == 0)
-        {
-            return false;
-        }
-
-        BigInteger octet;
-        int octets = 0;
-        
-        String temp = address+".";
-
-        int pos;
-        int start = 0;
-        while (start < temp.length()
-            && (pos = temp.indexOf('.', start)) > start)
-        {
-            if (octets == 4)
-            {
-                return false;
-            }
-            try
-            {
-                octet = (new BigInteger(temp.substring(start, pos)));
-            }
-            catch (NumberFormatException ex)
-            {
-                return false;
-            }
-            if (octet.compareTo(ZERO) == -1
-                || octet.compareTo(BigInteger.valueOf(255)) == 1)
-            {
-                return false;
-            }
-            start = pos + 1;
-            octets++;
-        }
-
-        return octets == 4;
-    }
-
-    /**
-     * Validate the given IPv6 address.
-     *
-     * @param address the IP address as a String.
-     *
-     * @return true if a valid IPv4 address, false otherwise
-     */
-    private static boolean isValidIPv6(
-        String address)
-    {
-        if (address.length() == 0)
-        {
-            return false;
-        }
-
-        BigInteger octet;
-        int octets = 0;
-
-        String temp = address + ":";
-        
-        int pos;
-        int start = 0;
-        while (start < temp.length()
-            && (pos = temp.indexOf(':', start)) > start)
-        {
-            if (octets == 8)
-            {
-                return false;
-            }
-            try
-            {
-                octet = (new BigInteger(temp.substring(start, pos), 16));
-            }
-            catch (NumberFormatException ex)
-            {
-                return false;
-            }
-            if (octet.compareTo(ZERO) == -1
-                || octet.compareTo(BigInteger.valueOf(0xFFFF)) == 1)
-            {
-                return false;
-            }
-            start = pos + 1;
-            octets++;
-        }
-
-        return octets == 8;
-    }
-}
-
-
diff --git a/azureus2/src/org/bouncycastle/util/Selector.java b/azureus2/src/org/bouncycastle/util/Selector.java
deleted file mode 100644
index 7ad86bf..0000000
--- a/azureus2/src/org/bouncycastle/util/Selector.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.bouncycastle.util;
-
-public interface Selector
-    extends Cloneable
-{
-    boolean match(Object obj);
-
-    Object clone();
-}
diff --git a/azureus2/src/org/bouncycastle/util/Strings.java b/azureus2/src/org/bouncycastle/util/Strings.java
deleted file mode 100644
index 5e1c069..0000000
--- a/azureus2/src/org/bouncycastle/util/Strings.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package org.bouncycastle.util;
-
-import java.io.ByteArrayOutputStream;
-import java.util.Vector;
-
-public final class Strings
-{
-    public static String fromUTF8ByteArray(byte[] bytes)
-    {
-        int i = 0;
-        int length = 0;
-
-        while (i < bytes.length)
-        {
-            length++;
-            if ((bytes[i] & 0xf0) == 0xf0)
-            {
-                // surrogate pair
-                length++;
-                i += 4;
-            }
-            else if ((bytes[i] & 0xe0) == 0xe0)
-            {
-                i += 3;
-            }
-            else if ((bytes[i] & 0xc0) == 0xc0)
-            {
-                i += 2;
-            }
-            else
-            {
-                i += 1;
-            }
-        }
-
-        char[] cs = new char[length];
-
-        i = 0;
-        length = 0;
-
-        while (i < bytes.length)
-        {
-            char ch;
-
-            if ((bytes[i] & 0xf0) == 0xf0)
-            {
-                int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F);
-                int U = codePoint - 0x10000;
-                char W1 = (char)(0xD800 | (U >> 10));
-                char W2 = (char)(0xDC00 | (U & 0x3FF));
-                cs[length++] = W1;
-                ch = W2;
-                i += 4;
-            }
-            else if ((bytes[i] & 0xe0) == 0xe0)
-            {
-                ch = (char)(((bytes[i] & 0x0f) << 12)
-                        | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
-                i += 3;
-            }
-            else if ((bytes[i] & 0xd0) == 0xd0)
-            {
-                ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
-                i += 2;
-            }
-            else if ((bytes[i] & 0xc0) == 0xc0)
-            {
-                ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
-                i += 2;
-            }
-            else
-            {
-                ch = (char)(bytes[i] & 0xff);
-                i += 1;
-            }
-
-            cs[length++] = ch;
-        }
-
-        return new String(cs);
-    }
-    
-    public static byte[] toUTF8ByteArray(String string)
-    {
-        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-        char[] c = string.toCharArray();
-        int i = 0;
-
-        while (i < c.length)
-        {
-            char ch = c[i];
-
-            if (ch < 0x0080)
-            {
-                bOut.write(ch);
-            }
-            else if (ch < 0x0800)
-            {
-                bOut.write(0xc0 | (ch >> 6));
-                bOut.write(0x80 | (ch & 0x3f));
-            }
-            // surrogate pair
-            else if (ch >= 0xD800 && ch <= 0xDFFF)
-            {
-                // in error - can only happen, if the Java String class has a
-                // bug.
-                if (i + 1 >= c.length)
-                {
-                    throw new IllegalStateException("invalid UTF-16 codepoint");
-                }
-                char W1 = ch;
-                ch = c[++i];
-                char W2 = ch;
-                // in error - can only happen, if the Java String class has a
-                // bug.
-                if (W1 > 0xDBFF)
-                {
-                    throw new IllegalStateException("invalid UTF-16 codepoint");
-                }
-                int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000;
-                bOut.write(0xf0 | (codePoint >> 18));
-                bOut.write(0x80 | ((codePoint >> 12) & 0x3F));
-                bOut.write(0x80 | ((codePoint >> 6) & 0x3F));
-                bOut.write(0x80 | (codePoint & 0x3F));
-            }
-            else
-            {
-                bOut.write(0xe0 | (ch >> 12));
-                bOut.write(0x80 | ((ch >> 6) & 0x3F));
-                bOut.write(0x80 | (ch & 0x3F));
-            }
-
-            i++;
-        }
-        
-        return bOut.toByteArray();
-    }
-    
-    /**
-     * A locale independent version of toUpperCase.
-     * 
-     * @param string input to be converted
-     * @return a US Ascii uppercase version
-     */
-    public static String toUpperCase(String string)
-    {
-        boolean changed = false;
-        char[] chars = string.toCharArray();
-        
-        for (int i = 0; i != chars.length; i++)
-        {
-            char ch = chars[i];
-            if ('a' <= ch && 'z' >= ch)
-            {
-                changed = true;
-                chars[i] = (char)(ch - 'a' + 'A');
-            }
-        }
-        
-        if (changed)
-        {
-            return new String(chars);
-        }
-        
-        return string;
-    }
-    
-    /**
-     * A locale independent version of toLowerCase.
-     * 
-     * @param string input to be converted
-     * @return a US ASCII lowercase version
-     */
-    public static String toLowerCase(String string)
-    {
-        boolean changed = false;
-        char[] chars = string.toCharArray();
-        
-        for (int i = 0; i != chars.length; i++)
-        {
-            char ch = chars[i];
-            if ('A' <= ch && 'Z' >= ch)
-            {
-                changed = true;
-                chars[i] = (char)(ch - 'A' + 'a');
-            }
-        }
-        
-        if (changed)
-        {
-            return new String(chars);
-        }
-        
-        return string;
-    }
-
-    public static byte[] toByteArray(String string)
-    {
-        byte[] bytes = new byte[string.length()];
-
-        for (int i = 0; i != bytes.length; i++)
-        {
-            char ch = string.charAt(i);
-
-            bytes[i] = (byte)ch;
-        }
-
-        return bytes;
-    }
-
-    public static String[] split(String input, char delimiter)
-    {
-        Vector           v = new Vector();
-        boolean moreTokens = true;
-        String subString;
-
-        while (moreTokens)
-        {
-            int tokenLocation = input.indexOf(delimiter);
-            if (tokenLocation > 0)
-            {
-                subString = input.substring(0, tokenLocation);
-                v.addElement(subString);
-                input = input.substring(tokenLocation + 1);
-            }
-            else
-            {
-                moreTokens = false;
-                v.addElement(input);
-            }
-        }
-
-        String[] res = new String[v.size()];
-
-        for (int i = 0; i != res.length; i++)
-        {
-            res[i] = (String)v.elementAt(i);
-        }
-        return res;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/util/encoders/Base64.java b/azureus2/src/org/bouncycastle/util/encoders/Base64.java
deleted file mode 100644
index 5a352f0..0000000
--- a/azureus2/src/org/bouncycastle/util/encoders/Base64.java
+++ /dev/null
@@ -1,345 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class Base64
-{
-	private static final byte[] encodingTable =
-		{
-		    (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
-            (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
-            (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
-            (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
-		    (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
-            (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
-            (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
-            (byte)'v',
-		    (byte)'w', (byte)'x', (byte)'y', (byte)'z',
-		    (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
-            (byte)'7', (byte)'8', (byte)'9',
-		    (byte)'+', (byte)'/'
-		};
-
-	/**
-	 * encode the input data producong a base 64 encoded byte array.
-	 *
-	 * @return a byte array containing the base 64 encoded data.
-	 */
-	public static byte[] encode(
-		byte[]	data)
-	{
-		byte[]	bytes;
-		
-		int modulus = data.length % 3;
-		if (modulus == 0)
-		{
-			bytes = new byte[4 * data.length / 3];
-		}
-		else
-		{
-			bytes = new byte[4 * ((data.length / 3) + 1)];
-		}
-
-        int dataLength = (data.length - modulus);
-		int a1, a2, a3;
-		for (int i = 0, j = 0; i < dataLength; i += 3, j += 4)
-		{
-			a1 = data[i] & 0xff;
-			a2 = data[i + 1] & 0xff;
-			a3 = data[i + 2] & 0xff;
-
-			bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];
-			bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];
-			bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];
-			bytes[j + 3] = encodingTable[a3 & 0x3f];
-		}
-
-		/*
-		 * process the tail end.
-		 */
-		int	b1, b2, b3;
-		int	d1, d2;
-
-		switch (modulus)
-		{
-		case 0:		/* nothing left to do */
-			break;
-		case 1:
-			d1 = data[data.length - 1] & 0xff;
-			b1 = (d1 >>> 2) & 0x3f;
-			b2 = (d1 << 4) & 0x3f;
-
-			bytes[bytes.length - 4] = encodingTable[b1];
-			bytes[bytes.length - 3] = encodingTable[b2];
-			bytes[bytes.length - 2] = (byte)'=';
-			bytes[bytes.length - 1] = (byte)'=';
-			break;
-		case 2:
-			d1 = data[data.length - 2] & 0xff;
-			d2 = data[data.length - 1] & 0xff;
-
-			b1 = (d1 >>> 2) & 0x3f;
-			b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
-			b3 = (d2 << 2) & 0x3f;
-
-			bytes[bytes.length - 4] = encodingTable[b1];
-			bytes[bytes.length - 3] = encodingTable[b2];
-			bytes[bytes.length - 2] = encodingTable[b3];
-			bytes[bytes.length - 1] = (byte)'=';
-			break;
-		}
-
-		return bytes;
-	}
-
-	/*
-	 * set up the decoding table.
-	 */
-	private static final byte[] decodingTable;
-
-	static
-	{
-		decodingTable = new byte[128];
-
-		for (int i = 'A'; i <= 'Z'; i++)
-		{
-			decodingTable[i] = (byte)(i - 'A');
-		}
-
-		for (int i = 'a'; i <= 'z'; i++)
-		{
-			decodingTable[i] = (byte)(i - 'a' + 26);
-		}
-
-		for (int i = '0'; i <= '9'; i++)
-		{
-			decodingTable[i] = (byte)(i - '0' + 52);
-		}
-
-		decodingTable['+'] = 62;
-		decodingTable['/'] = 63;
-	}
-
-	/**
-	 * decode the base 64 encoded input data.
-	 *
-	 * @return a byte array representing the decoded data.
-	 */
-	public static byte[] decode(
-		byte[]	data)
-	{
-			// PARG - fix up for zero length encodes/decodes
-		
-		if ( data.length == 0 ){
-			return( data );
-		}
-		
-		byte[]	bytes;
-		byte	b1, b2, b3, b4;
-
-		if (data[data.length - 2] == '=')
-		{
-			bytes = new byte[(((data.length / 4) - 1) * 3) + 1];
-		}
-		else if (data[data.length - 1] == '=')
-		{
-			bytes = new byte[(((data.length / 4) - 1) * 3) + 2];
-		}
-		else
-		{
-			bytes = new byte[((data.length / 4) * 3)];
-		}
-
-		for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3)
-		{
-			b1 = decodingTable[data[i]];
-			b2 = decodingTable[data[i + 1]];
-			b3 = decodingTable[data[i + 2]];
-			b4 = decodingTable[data[i + 3]];
-
-			bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
-			bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
-			bytes[j + 2] = (byte)((b3 << 6) | b4);
-		}
-
-		if (data[data.length - 2] == '=')
-		{
-			b1 = decodingTable[data[data.length - 4]];
-			b2 = decodingTable[data[data.length - 3]];
-
-			bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
-		}
-		else if (data[data.length - 1] == '=')
-		{
-			b1 = decodingTable[data[data.length - 4]];
-			b2 = decodingTable[data[data.length - 3]];
-			b3 = decodingTable[data[data.length - 2]];
-
-			bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
-			bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
-		}
-		else
-		{
-			b1 = decodingTable[data[data.length - 4]];
-			b2 = decodingTable[data[data.length - 3]];
-			b3 = decodingTable[data[data.length - 2]];
-			b4 = decodingTable[data[data.length - 1]];
-
-			bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
-			bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
-			bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
-		}
-
-		return bytes;
-	}
-
-	/**
-	 * decode the base 64 encoded String data.
-	 *
-	 * @return a byte array representing the decoded data.
-	 */
-	public static byte[] decode(
-		String	data)
-	{
-			// PARG - fix up for zero length encodes/decodes
-		
-		if ( data.length() == 0 ){
-			
-			return( new byte[0] );
-		}
-		
-		byte[]	bytes;
-		byte	b1, b2, b3, b4;
-
-		if (data.charAt(data.length() - 2) == '=')
-		{
-			bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];
-		}
-		else if (data.charAt(data.length() - 1) == '=')
-		{
-			bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];
-		}
-		else
-		{
-			bytes = new byte[((data.length() / 4) * 3)];
-		}
-
-		for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3)
-		{
-			b1 = decodingTable[data.charAt(i)];
-			b2 = decodingTable[data.charAt(i + 1)];
-			b3 = decodingTable[data.charAt(i + 2)];
-			b4 = decodingTable[data.charAt(i + 3)];
-
-			bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
-			bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
-			bytes[j + 2] = (byte)((b3 << 6) | b4);
-		}
-
-		if (data.charAt(data.length() - 2) == '=')
-		{
-			b1 = decodingTable[data.charAt(data.length() - 4)];
-			b2 = decodingTable[data.charAt(data.length() - 3)];
-
-			bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
-		}
-		else if (data.charAt(data.length() - 1) == '=')
-		{
-			b1 = decodingTable[data.charAt(data.length() - 4)];
-			b2 = decodingTable[data.charAt(data.length() - 3)];
-			b3 = decodingTable[data.charAt(data.length() - 2)];
-
-			bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
-			bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
-		}
-		else
-		{
-			b1 = decodingTable[data.charAt(data.length() - 4)];
-			b2 = decodingTable[data.charAt(data.length() - 3)];
-			b3 = decodingTable[data.charAt(data.length() - 2)];
-			b4 = decodingTable[data.charAt(data.length() - 1)];
-
-			bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
-			bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
-			bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
-		}
-
-		return bytes;
-	}
-	
-	/**
-	 * decode the base 64 encoded String data writing it to the given output stream
-	 *
-	 * @return the number of bytes produced.
-	 */
-	public static int decode(
-		String				data,
-		OutputStream	out) 
-		throws IOException
-	{
-			// PARG
-		if ( data.length()== 0 ){
-			
-			return( 0 );
-		}
-		
-		byte	b1, b2, b3, b4;
-		int		length;
-
-		if (data.charAt(data.length() - 2) == '=')
-		{
-			length = (((data.length() / 4) - 1) * 3) + 1;
-		}
-		else if (data.charAt(data.length() - 1) == '=')
-		{
-			length = (((data.length() / 4) - 1) * 3) + 2;
-		}
-		else
-		{
-			length = ((data.length() / 4) * 3);
-		}
-		
-		for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3)
-		{
-			b1 = decodingTable[data.charAt(i)];
-			b2 = decodingTable[data.charAt(i + 1)];
-			b3 = decodingTable[data.charAt(i + 2)];
-			b4 = decodingTable[data.charAt(i + 3)];
-
-			out.write((b1 << 2) | (b2 >> 4));
-			out.write((b2 << 4) | (b3 >> 2));
-			out.write((b3 << 6) | b4);
-		}
-
-		if (data.charAt(data.length() - 2) == '=')
-		{
-			b1 = decodingTable[data.charAt(data.length() - 4)];
-			b2 = decodingTable[data.charAt(data.length() - 3)];
-
-			out.write((b1 << 2) | (b2 >> 4));
-		}
-		else if (data.charAt(data.length() - 1) == '=')
-		{
-			b1 = decodingTable[data.charAt(data.length() - 4)];
-			b2 = decodingTable[data.charAt(data.length() - 3)];
-			b3 = decodingTable[data.charAt(data.length() - 2)];
-
-			out.write((b1 << 2) | (b2 >> 4));
-			out.write((b2 << 4) | (b3 >> 2));
-		}
-		else
-		{
-			b1 = decodingTable[data.charAt(data.length() - 4)];
-			b2 = decodingTable[data.charAt(data.length() - 3)];
-			b3 = decodingTable[data.charAt(data.length() - 2)];
-			b4 = decodingTable[data.charAt(data.length() - 1)];
-
-			out.write((b1 << 2) | (b2 >> 4));
-			out.write((b2 << 4) | (b3 >> 2));
-			out.write((b3 << 6) | b4);
-		}
-
-		return length;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/util/encoders/BufferedDecoder.java b/azureus2/src/org/bouncycastle/util/encoders/BufferedDecoder.java
deleted file mode 100644
index 9df63c4..0000000
--- a/azureus2/src/org/bouncycastle/util/encoders/BufferedDecoder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-
-/**
- * a buffering class to allow translation from one format to another to
- * be done in discrete chunks.
- */
-public class BufferedDecoder
-{
-	protected byte[]        buf;
-	protected int           bufOff;
-
-    protected Translator    translator;
-
-    /**
-     * @param translator the translator to use.
-     * @param bufSize amount of input to buffer for each chunk.
-     */
-	public BufferedDecoder(
-        Translator  translator,
-        int         bufSize)
-	{
-        this.translator = translator;
-
-        if ((bufSize % translator.getEncodedBlockSize()) != 0)
-        {
-            throw new IllegalArgumentException("buffer size not multiple of input block size");
-        }
-
-        buf = new byte[bufSize];
-        bufOff = 0;
-	}
-
-	public int processByte(
-        byte        in,
-		byte[]      out,
-		int         outOff)
-    {
-        int         resultLen = 0;
-
-        buf[bufOff++] = in;
-
-        if (bufOff == buf.length)
-        {
-            resultLen = translator.decode(buf, 0, buf.length, out, outOff);
-            bufOff = 0;
-        }
-
-        return resultLen;
-    }
-
-	public int processBytes(
-		byte[]      in,
-		int         inOff,
-		int         len,
-		byte[]      out,
-		int         outOff)
-	{
-        if (len < 0)
-        {
-            throw new IllegalArgumentException("Can't have a negative input length!");
-        }
-
-		int resultLen = 0;
-        int gapLen = buf.length - bufOff;
-
-        if (len > gapLen)
-        {
-            System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
-            resultLen += translator.decode(buf, 0, buf.length, out, outOff);
-
-            bufOff = 0;
-
-            len -= gapLen;
-            inOff += gapLen;
-            outOff += resultLen;
-
-            int chunkSize = len - (len % buf.length);
-
-            resultLen += translator.decode(in, inOff, chunkSize, out, outOff);
-
-            len -= chunkSize;
-            inOff += chunkSize;
-        }
-
-        if (len != 0)
-        {
-            System.arraycopy(in, inOff, buf, bufOff, len);
-
-            bufOff += len;
-        }
-
-        return resultLen;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/util/encoders/BufferedEncoder.java b/azureus2/src/org/bouncycastle/util/encoders/BufferedEncoder.java
deleted file mode 100644
index 1db8a05..0000000
--- a/azureus2/src/org/bouncycastle/util/encoders/BufferedEncoder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-
-/**
- * a buffering class to allow translation from one format to another to
- * be done in discrete chunks.
- */
-public class BufferedEncoder
-{
-	protected byte[]        buf;
-	protected int           bufOff;
-
-    protected Translator    translator;
-
-    /**
-     * @param translator the translator to use.
-     * @param bufSize amount of input to buffer for each chunk.
-     */
-	public BufferedEncoder(
-        Translator  translator,
-        int         bufSize)
-	{
-        this.translator = translator;
-
-        if ((bufSize % translator.getEncodedBlockSize()) != 0)
-        {
-            throw new IllegalArgumentException("buffer size not multiple of input block size");
-        }
-
-        buf = new byte[bufSize];
-        bufOff = 0;
-	}
-
-	public int processByte(
-        byte        in,
-		byte[]      out,
-		int         outOff)
-    {
-        int         resultLen = 0;
-
-        buf[bufOff++] = in;
-
-        if (bufOff == buf.length)
-        {
-            resultLen = translator.encode(buf, 0, buf.length, out, outOff);
-            bufOff = 0;
-        }
-
-        return resultLen;
-    }
-
-	public int processBytes(
-		byte[]      in,
-		int         inOff,
-		int         len,
-		byte[]      out,
-		int         outOff)
-	{
-        if (len < 0)
-        {
-            throw new IllegalArgumentException("Can't have a negative input length!");
-        }
-
-		int resultLen = 0;
-        int gapLen = buf.length - bufOff;
-
-        if (len > gapLen)
-        {
-            System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
-            resultLen += translator.encode(buf, 0, buf.length, out, outOff);
-
-            bufOff = 0;
-
-            len -= gapLen;
-            inOff += gapLen;
-            outOff += resultLen;
-
-            int chunkSize = len - (len % buf.length);
-
-            resultLen += translator.encode(in, inOff, chunkSize, out, outOff);
-
-            len -= chunkSize;
-            inOff += chunkSize;
-        }
-
-        if (len != 0)
-        {
-            System.arraycopy(in, inOff, buf, bufOff, len);
-
-            bufOff += len;
-        }
-
-        return resultLen;
-	}
-}
diff --git a/azureus2/src/org/bouncycastle/util/encoders/Hex.java b/azureus2/src/org/bouncycastle/util/encoders/Hex.java
deleted file mode 100644
index d2bc3f7..0000000
--- a/azureus2/src/org/bouncycastle/util/encoders/Hex.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * Converters for going from hex to binary and back.
- * <p>
- * Note: this class assumes ASCII processing.
- */
-public class Hex
-{
-    private static HexTranslator   encoder = new HexTranslator();
-
-    private static final byte[]   hexTable = 
-        { 
-            (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
-            (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
-        };
-
-    public static byte[] encode(
-        byte[]  array)
-    {
-        return encode(array, 0, array.length);
-    }
-
-    public static byte[] encode(
-        byte[]  array,
-        int     off,
-        int     length)
-    {
-        byte[]      enc = new byte[length * 2];
-
-        encoder.encode(array, off, length, enc, 0);
-
-        return enc;
-    }
-
-    public static byte[] decode(
-        String  string)
-    {
-        byte[]          bytes = new byte[string.length() / 2];
-        String          buf = string.toLowerCase();
-		
-        for (int i = 0; i < buf.length(); i += 2)
-        {
-			char    left  = buf.charAt(i);
-			char    right = buf.charAt(i+1);
-            int     index = i / 2;
-			
-            if (left < 'a')
-            {
-                bytes[index] = (byte)((left - '0') << 4);
-            }
-            else
-            {
-                bytes[index] = (byte)((left - 'a' + 10) << 4);
-            }
-            if (right < 'a')
-            {
-                bytes[index] += (byte)(right - '0');
-            }
-            else
-            {
-                bytes[index] += (byte)(right - 'a' + 10);
-            }
-        }
-
-        return bytes;
-    }
-
-    public static byte[] decode(
-        byte[]  array)
-    {
-        byte[]          bytes = new byte[array.length / 2];
-
-        encoder.decode(array, 0, array.length, bytes, 0);
-
-        return bytes;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/util/encoders/HexTranslator.java b/azureus2/src/org/bouncycastle/util/encoders/HexTranslator.java
deleted file mode 100644
index a306102..0000000
--- a/azureus2/src/org/bouncycastle/util/encoders/HexTranslator.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * Converters for going from hex to binary and back. Note: this class assumes ASCII processing.
- */
-public class HexTranslator
-    implements Translator
-{
-    private static final byte[]   hexTable = 
-        { 
-            (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
-            (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
-        };
-
-    /**
-     * size of the output block on encoding produced by getDecodedBlockSize()
-     * bytes.
-     */
-    public int getEncodedBlockSize()
-    {
-        return 2;
-    }
-
-    public int encode(
-        byte[]  in,
-        int     inOff,
-        int     length,
-        byte[]  out,
-        int     outOff)
-    {
-        for (int i = 0, j = 0; i < length; i++, j += 2)
-        {
-            out[outOff + j] = hexTable[(in[inOff] >> 4) & 0x0f];
-            out[outOff + j + 1] = hexTable[in[inOff] & 0x0f];
-
-            inOff++;
-        }
-
-        return length * 2;
-    }
-
-    /**
-     * size of the output block on decoding produced by getEncodedBlockSize()
-     * bytes.
-     */
-    public int getDecodedBlockSize()
-    {
-        return 1;
-    }
-
-    public int decode(
-        byte[]  in,
-        int     inOff,
-        int     length,
-        byte[]  out,
-        int     outOff)
-    {
-		int halfLength = length / 2;
-		byte left, right;
-        for (int i = 0; i < halfLength; i++)
-        {
-			left  = in[inOff + i * 2];
-			right = in[inOff + i * 2 + 1];
-			
-            if (left < (byte)'a')
-            {
-                out[outOff] = (byte)((left - '0') << 4);
-            }
-            else
-            {
-                out[outOff] = (byte)((left - 'a' + 10) << 4);
-            }
-            if (right < (byte)'a')
-            {
-                out[outOff] += (byte)(right - '0');
-            }
-            else
-            {
-                out[outOff] += (byte)(right - 'a' + 10);
-            }
-
-            outOff++;
-        }
-
-        return halfLength;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/util/encoders/Translator.java b/azureus2/src/org/bouncycastle/util/encoders/Translator.java
deleted file mode 100644
index a3a0cb8..0000000
--- a/azureus2/src/org/bouncycastle/util/encoders/Translator.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * general interface for an translator.
- */
-public interface Translator
-{
-    /**
-     * size of the output block on encoding produced by getDecodedBlockSize()
-     * bytes.
-     */
-    public int getEncodedBlockSize();
-
-    public int encode(byte[] in, int inOff, int length, byte[] out, int outOff);
-
-    /**
-     * size of the output block on decoding produced by getEncodedBlockSize()
-     * bytes.
-     */
-    public int getDecodedBlockSize();
-
-    public int decode(byte[] in, int inOff, int length, byte[] out, int outOff);
-}
diff --git a/azureus2/src/org/bouncycastle/x509/AttributeCertificateHolder.java b/azureus2/src/org/bouncycastle/x509/AttributeCertificateHolder.java
deleted file mode 100644
index 6f8bba5..0000000
--- a/azureus2/src/org/bouncycastle/x509/AttributeCertificateHolder.java
+++ /dev/null
@@ -1,419 +0,0 @@
-package org.bouncycastle.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.Holder;
-import org.bouncycastle.asn1.x509.IssuerSerial;
-import org.bouncycastle.asn1.x509.ObjectDigestInfo;
-import org.bouncycastle.jce.PrincipalUtil;
-import org.bouncycastle.jce.X509Principal;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Selector;
-
-import javax.security.auth.x500.X500Principal;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.MessageDigest;
-import java.security.Principal;
-import java.security.cert.CertSelector;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateParsingException;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * The Holder object.
- * 
- * <pre>
- *          Holder ::= SEQUENCE {
- *                baseCertificateID   [0] IssuerSerial OPTIONAL,
- *                         -- the issuer and serial number of
- *                         -- the holder's Public Key Certificate
- *                entityName          [1] GeneralNames OPTIONAL,
- *                         -- the name of the claimant or role
- *                objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
- *                         -- used to directly authenticate the holder,
- *                         -- for example, an executable
- *          }
- * </pre>
- * 
- */
-public class AttributeCertificateHolder
-    implements CertSelector, Selector
-{
-    final Holder holder;
-
-    AttributeCertificateHolder(ASN1Sequence seq)
-    {
-        holder = Holder.getInstance(seq);
-    }
-
-    public AttributeCertificateHolder(X509Principal issuerName,
-        BigInteger serialNumber)
-    {
-        holder = new org.bouncycastle.asn1.x509.Holder(new IssuerSerial(
-            new GeneralNames(new DERSequence(new GeneralName(issuerName))),
-            new DERInteger(serialNumber)));
-    }
-
-    public AttributeCertificateHolder(X500Principal issuerName,
-        BigInteger serialNumber)
-    {
-        this(X509Util.convertPrincipal(issuerName), serialNumber);
-    }
-
-    public AttributeCertificateHolder(X509Certificate cert)
-        throws CertificateParsingException
-    {
-        X509Principal name;
-
-        try
-        {
-            name = PrincipalUtil.getIssuerX509Principal(cert);
-        }
-        catch (Exception e)
-        {
-            throw new CertificateParsingException(e.getMessage());
-        }
-
-        holder = new Holder(new IssuerSerial(generateGeneralNames(name),
-            new DERInteger(cert.getSerialNumber())));
-    }
-
-    public AttributeCertificateHolder(X509Principal principal)
-    {
-        holder = new Holder(generateGeneralNames(principal));
-    }
-
-    public AttributeCertificateHolder(X500Principal principal)
-    {
-        this(X509Util.convertPrincipal(principal));
-    }
-
-    /**
-     * Constructs a holder for v2 attribute certificates with a hash value for
-     * some type of object.
-     * <p>
-     * <code>digestedObjectType</code> can be one of the following:
-     * <ul>
-     * <li>0 - publicKey - A hash of the public key of the holder must be
-     * passed.
-     * <li>1 - publicKeyCert - A hash of the public key certificate of the
-     * holder must be passed.
-     * <li>2 - otherObjectDigest - A hash of some other object type must be
-     * passed. <code>otherObjectTypeID</code> must not be empty.
-     * </ul>
-     * <p>
-     * This cannot be used if a v1 attribute certificate is used.
-     * 
-     * @param digestedObjectType The digest object type.
-     * @param digestAlgorithm The algorithm identifier for the hash.
-     * @param otherObjectTypeID The object type ID if
-     *            <code>digestedObjectType</code> is
-     *            <code>otherObjectDigest</code>.
-     * @param objectDigest The hash value.
-     */
-    public AttributeCertificateHolder(int digestedObjectType,
-        String digestAlgorithm, String otherObjectTypeID, byte[] objectDigest)
-    {
-        holder = new Holder(new ObjectDigestInfo(digestedObjectType,
-            otherObjectTypeID, new AlgorithmIdentifier(digestAlgorithm), Arrays
-                .clone(objectDigest)));
-    }
-
-    /**
-     * Returns the digest object type if an object digest info is used.
-     * <p>
-     * <ul>
-     * <li>0 - publicKey - A hash of the public key of the holder must be
-     * passed.
-     * <li>1 - publicKeyCert - A hash of the public key certificate of the
-     * holder must be passed.
-     * <li>2 - otherObjectDigest - A hash of some other object type must be
-     * passed. <code>otherObjectTypeID</code> must not be empty.
-     * </ul>
-     * 
-     * @return The digest object type or -1 if no object digest info is set.
-     */
-    public int getDigestedObjectType()
-    {
-        if (holder.getObjectDigestInfo() != null)
-        {
-            return holder.getObjectDigestInfo().getDigestedObjectType()
-                .getValue().intValue();
-        }
-        return -1;
-    }
-
-    /**
-     * Returns the other object type ID if an object digest info is used.
-     * 
-     * @return The other object type ID or <code>null</code> if no object
-     *         digest info is set.
-     */
-    public String getDigestAlgorithm()
-    {
-        if (holder.getObjectDigestInfo() != null)
-        {
-            holder.getObjectDigestInfo().getDigestAlgorithm().getObjectId()
-                .getId();
-        }
-        return null;
-    }
-
-    /**
-     * Returns the hash if an object digest info is used.
-     * 
-     * @return The hash or <code>null</code> if no object digest info is set.
-     */
-    public byte[] getObjectDigest()
-    {
-        if (holder.getObjectDigestInfo() != null)
-        {
-            holder.getObjectDigestInfo().getObjectDigest().getBytes();
-        }
-        return null;
-    }
-
-    /**
-     * Returns the digest algorithm ID if an object digest info is used.
-     * 
-     * @return The digest algorithm ID or <code>null</code> if no object
-     *         digest info is set.
-     */
-    public String getOtherObjectTypeID()
-    {
-        if (holder.getObjectDigestInfo() != null)
-        {
-            holder.getObjectDigestInfo().getOtherObjectTypeID().getId();
-        }
-        return null;
-    }
-
-    private GeneralNames generateGeneralNames(X509Principal principal)
-    {
-        return new GeneralNames(new DERSequence(new GeneralName(principal)));
-    }
-
-    private boolean matchesDN(X509Principal subject, GeneralNames targets)
-    {
-        GeneralName[] names = targets.getNames();
-
-        for (int i = 0; i != names.length; i++)
-        {
-            GeneralName gn = names[i];
-
-            if (gn.getTagNo() == GeneralName.directoryName)
-            {
-                try
-                {
-                    if (new X509Principal(((ASN1Encodable)gn.getName())
-                        .getEncoded()).equals(subject))
-                    {
-                        return true;
-                    }
-                }
-                catch (IOException e)
-                {
-                }
-            }
-        }
-
-        return false;
-    }
-
-    private Object[] getNames(GeneralName[] names)
-    {
-        List l = new ArrayList(names.length);
-
-        for (int i = 0; i != names.length; i++)
-        {
-            if (names[i].getTagNo() == GeneralName.directoryName)
-            {
-                try
-                {
-                    l.add(new X500Principal(
-                        ((ASN1Encodable)names[i].getName()).getEncoded()));
-                }
-                catch (IOException e)
-                {
-                    throw new RuntimeException("badly formed Name object");
-                }
-            }
-        }
-
-        return l.toArray(new Object[l.size()]);
-    }
-
-    private Principal[] getPrincipals(GeneralNames names)
-    {
-        Object[] p = this.getNames(names.getNames());
-        List l = new ArrayList();
-
-        for (int i = 0; i != p.length; i++)
-        {
-            if (p[i] instanceof Principal)
-            {
-                l.add(p[i]);
-            }
-        }
-
-        return (Principal[])l.toArray(new Principal[l.size()]);
-    }
-
-    /**
-     * Return any principal objects inside the attribute certificate holder
-     * entity names field.
-     * 
-     * @return an array of Principal objects (usually X500Principal), null if no
-     *         entity names field is set.
-     */
-    public Principal[] getEntityNames()
-    {
-        if (holder.getEntityName() != null)
-        {
-            return getPrincipals(holder.getEntityName());
-        }
-
-        return null;
-    }
-
-    /**
-     * Return the principals associated with the issuer attached to this holder
-     * 
-     * @return an array of principals, null if no BaseCertificateID is set.
-     */
-    public Principal[] getIssuer()
-    {
-        if (holder.getBaseCertificateID() != null)
-        {
-            return getPrincipals(holder.getBaseCertificateID().getIssuer());
-        }
-
-        return null;
-    }
-
-    /**
-     * Return the serial number associated with the issuer attached to this
-     * holder.
-     * 
-     * @return the certificate serial number, null if no BaseCertificateID is
-     *         set.
-     */
-    public BigInteger getSerialNumber()
-    {
-        if (holder.getBaseCertificateID() != null)
-        {
-            return holder.getBaseCertificateID().getSerial().getValue();
-        }
-
-        return null;
-    }
-
-    public Object clone()
-    {
-        return new AttributeCertificateHolder((ASN1Sequence)holder
-            .toASN1Object());
-    }
-
-    public boolean match(Certificate cert)
-    {
-        if (!(cert instanceof X509Certificate))
-        {
-            return false;
-        }
-
-        X509Certificate x509Cert = (X509Certificate)cert;
-
-        try
-        {
-            if (holder.getBaseCertificateID() != null)
-            {
-                return holder.getBaseCertificateID().getSerial().getValue().equals(x509Cert.getSerialNumber())
-                    && matchesDN(PrincipalUtil.getIssuerX509Principal(x509Cert), holder.getBaseCertificateID().getIssuer());
-            }
-
-            if (holder.getEntityName() != null)
-            {
-                if (matchesDN(PrincipalUtil.getSubjectX509Principal(x509Cert),
-                    holder.getEntityName()))
-                {
-                    return true;
-                }
-            }
-            if (holder.getObjectDigestInfo() != null)
-            {
-                MessageDigest md = null;
-                try
-                {
-                    md = MessageDigest.getInstance(getDigestAlgorithm(), BouncyCastleProvider.PROVIDER_NAME);
-
-                }
-                catch (Exception e)
-                {
-                    return false;
-                }
-                switch (getDigestedObjectType())
-                {
-                case ObjectDigestInfo.publicKey:
-                    // TODO: DSA Dss-parms
-                    md.update(cert.getPublicKey().getEncoded());
-                    break;
-                case ObjectDigestInfo.publicKeyCert:
-                    md.update(cert.getEncoded());
-                    break;
-                }
-                if (!Arrays.areEqual(md.digest(), getObjectDigest()))
-                {
-                    return false;
-                }
-            }
-        }
-        catch (CertificateEncodingException e)
-        {
-            return false;
-        }
-
-        return false;
-    }
-
-    public boolean equals(Object obj)
-    {
-        if (obj == this)
-        {
-            return true;
-        }
-
-        if (!(obj instanceof AttributeCertificateHolder))
-        {
-            return false;
-        }
-
-        AttributeCertificateHolder other = (AttributeCertificateHolder)obj;
-
-        return this.holder.equals(other.holder);
-    }
-
-    public int hashCode()
-    {
-        return this.holder.hashCode();
-    }
-
-    public boolean match(Object obj)
-    {
-        if (!(obj instanceof X509Certificate))
-        {
-            return false;
-        }
-
-        return match((Certificate)obj);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/x509/AttributeCertificateIssuer.java b/azureus2/src/org/bouncycastle/x509/AttributeCertificateIssuer.java
deleted file mode 100644
index c20e0d9..0000000
--- a/azureus2/src/org/bouncycastle/x509/AttributeCertificateIssuer.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package org.bouncycastle.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.x509.AttCertIssuer;
-import org.bouncycastle.asn1.x509.GeneralName;
-import org.bouncycastle.asn1.x509.GeneralNames;
-import org.bouncycastle.asn1.x509.V2Form;
-import org.bouncycastle.jce.X509Principal;
-import org.bouncycastle.util.Selector;
-
-import javax.security.auth.x500.X500Principal;
-import java.io.IOException;
-import java.security.Principal;
-import java.security.cert.CertSelector;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Carrying class for an attribute certificate issuer.
- */
-public class AttributeCertificateIssuer
-    implements CertSelector, Selector
-{
-    final ASN1Encodable form;
-
-    /**
-     * Set the issuer directly with the ASN.1 structure.
-     * 
-     * @param issuer The issuer
-     */
-    AttributeCertificateIssuer(AttCertIssuer issuer)
-    {
-        form = issuer.getIssuer();
-    }
-
-    public AttributeCertificateIssuer(X500Principal principal)
-        throws IOException
-    {
-        this(new X509Principal(principal.getEncoded()));
-    }
-
-    public AttributeCertificateIssuer(X509Principal principal)
-    {
-        form = new V2Form(new GeneralNames(new DERSequence(new GeneralName(principal))));
-    }
-
-    private Object[] getNames()
-    {
-        GeneralNames name;
-
-        if (form instanceof V2Form)
-        {
-            name = ((V2Form)form).getIssuerName();
-        }
-        else
-        {
-            name = (GeneralNames)form;
-        }
-
-        GeneralName[] names = name.getNames();
-
-        List l = new ArrayList(names.length);
-
-        for (int i = 0; i != names.length; i++)
-        {
-            if (names[i].getTagNo() == GeneralName.directoryName)
-            {
-                try
-                {
-                    l.add(new X500Principal(
-                        ((ASN1Encodable)names[i].getName()).getEncoded()));
-                }
-                catch (IOException e)
-                {
-                    throw new RuntimeException("badly formed Name object");
-                }
-            }
-        }
-
-        return l.toArray(new Object[l.size()]);
-    }
-
-    /**
-     * Return any principal objects inside the attribute certificate issuer
-     * object.
-     * 
-     * @return an array of Principal objects (usually X500Principal)
-     */
-    public Principal[] getPrincipals()
-    {
-        Object[] p = this.getNames();
-        List l = new ArrayList();
-
-        for (int i = 0; i != p.length; i++)
-        {
-            if (p[i] instanceof Principal)
-            {
-                l.add(p[i]);
-            }
-        }
-
-        return (Principal[])l.toArray(new Principal[l.size()]);
-    }
-
-    private boolean matchesDN(X500Principal subject, GeneralNames targets)
-    {
-        GeneralName[] names = targets.getNames();
-
-        for (int i = 0; i != names.length; i++)
-        {
-            GeneralName gn = names[i];
-
-            if (gn.getTagNo() == GeneralName.directoryName)
-            {
-                try
-                {
-                    if (new X500Principal(((ASN1Encodable)gn.getName()).getEncoded()).equals(subject))
-                    {
-                        return true;
-                    }
-                }
-                catch (IOException e)
-                {
-                }
-            }
-        }
-
-        return false;
-    }
-
-    public Object clone()
-    {
-        return new AttributeCertificateIssuer(AttCertIssuer.getInstance(form));
-    }
-
-    public boolean match(Certificate cert)
-    {
-        if (!(cert instanceof X509Certificate))
-        {
-            return false;
-        }
-
-        X509Certificate x509Cert = (X509Certificate)cert;
-
-        if (form instanceof V2Form)
-        {
-            V2Form issuer = (V2Form)form;
-            if (issuer.getBaseCertificateID() != null)
-            {
-                return issuer.getBaseCertificateID().getSerial().getValue().equals(x509Cert.getSerialNumber())
-                    && matchesDN(x509Cert.getIssuerX500Principal(), issuer.getBaseCertificateID().getIssuer());
-            }
-
-            GeneralNames name = issuer.getIssuerName();
-            if (matchesDN(x509Cert.getSubjectX500Principal(), name))
-            {
-                return true;
-            }
-        }
-        else
-        {
-            GeneralNames name = (GeneralNames)form;
-            if (matchesDN(x509Cert.getSubjectX500Principal(), name))
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public boolean equals(Object obj)
-    {
-        if (obj == this)
-        {
-            return true;
-        }
-
-        if (!(obj instanceof AttributeCertificateIssuer))
-        {
-            return false;
-        }
-
-        AttributeCertificateIssuer other = (AttributeCertificateIssuer)obj;
-
-        return this.form.equals(other.form);
-    }
-
-    public int hashCode()
-    {
-        return this.form.hashCode();
-    }
-
-    public boolean match(Object obj)
-    {
-        if (!(obj instanceof X509Certificate))
-        {
-            return false;
-        }
-
-        return match((Certificate)obj);
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/x509/X509Attribute.java b/azureus2/src/org/bouncycastle/x509/X509Attribute.java
deleted file mode 100644
index f4c65ab..0000000
--- a/azureus2/src/org/bouncycastle/x509/X509Attribute.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.bouncycastle.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.x509.Attribute;
-
-/**
- * Class for carrying the values in an X.509 Attribute.
- */
-public class X509Attribute
-    extends ASN1Encodable
-{
-    Attribute    attr;
-    
-    /**
-     * @param at an object representing an attribute.
-     */
-    X509Attribute(
-        ASN1Encodable   at)
-    {
-        this.attr = Attribute.getInstance(at);
-    }
-
-    /**
-     * Create an X.509 Attribute with the type given by the passed in oid and
-     * the value represented by an ASN.1 Set containing value.
-     * 
-     * @param oid type of the attribute
-     * @param value value object to go into the atribute's value set.
-     */
-    public X509Attribute(
-        String          oid,
-        ASN1Encodable   value)
-    {
-        this.attr = new Attribute(new DERObjectIdentifier(oid), new DERSet(value));
-    }
-    
-    /**
-     * Create an X.59 Attribute with the type given by the passed in oid and the
-     * value represented by an ASN.1 Set containing the objects in value.
-     * 
-     * @param oid type of the attribute
-     * @param value vector of values to go in the attribute's value set.
-     */
-    public X509Attribute(
-        String              oid,
-        ASN1EncodableVector value)
-    {
-        this.attr = new Attribute(new DERObjectIdentifier(oid), new DERSet(value));
-    }
-    
-    public String getOID()
-    {
-        return attr.getAttrType().getId();
-    }
-    
-    public ASN1Encodable[] getValues()
-    {
-        ASN1Set         s = attr.getAttrValues();
-        ASN1Encodable[] values = new ASN1Encodable[s.size()];
-        
-        for (int i = 0; i != s.size(); i++)
-        {
-            values[i] = (ASN1Encodable)s.getObjectAt(i);
-        }
-        
-        return values;
-    }
-    
-    public DERObject toASN1Object()
-    {
-        return attr.toASN1Object();
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/x509/X509AttributeCertificate.java b/azureus2/src/org/bouncycastle/x509/X509AttributeCertificate.java
deleted file mode 100644
index 48a825f..0000000
--- a/azureus2/src/org/bouncycastle/x509/X509AttributeCertificate.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.bouncycastle.x509;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PublicKey;
-import java.security.SignatureException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Extension;
-import java.util.Date;
-
-/**
- * Interface for an X.509 Attribute Certificate.
- */
-public interface X509AttributeCertificate
-    extends X509Extension
-{   
-    /**
-     * Return the version number for the certificate.
-     * 
-     * @return the version number.
-     */
-    public int getVersion();
-    
-    /**
-     * Return the serial number for the certificate.
-     * 
-     * @return the serial number.
-     */
-    public BigInteger getSerialNumber();
-    
-    /**
-     * Return the date before which the certificate is not valid.
-     * 
-     * @return the "not valid before" date.
-     */
-    public Date getNotBefore();
-    
-    /**
-     * Return the date after which the certificate is not valid.
-     * 
-     * @return the "not valid afer" date.
-     */
-    public Date getNotAfter();
-    
-    /**
-     * Return the holder of the certificate.
-     * 
-     * @return the holder.
-     */
-    public AttributeCertificateHolder getHolder();
-    
-    /**
-     * Return the issuer details for the certificate.
-     * 
-     * @return the issuer details.
-     */
-    public AttributeCertificateIssuer getIssuer();
-    
-    /**
-     * Return the attributes contained in the attribute block in the certificate.
-     * 
-     * @return an array of attributes.
-     */
-    public X509Attribute[] getAttributes();
-    
-    /**
-     * Return the attributes with the same type as the passed in oid.
-     * 
-     * @param oid the object identifier we wish to match.
-     * @return an array of matched attributes, null if there is no match.
-     */
-    public X509Attribute[] getAttributes(String oid);
-    
-    public boolean[] getIssuerUniqueID();
-    
-    public void checkValidity()
-        throws CertificateExpiredException, CertificateNotYetValidException;
-    
-    public void checkValidity(Date date)
-        throws CertificateExpiredException, CertificateNotYetValidException;
-    
-    public byte[] getSignature();
-    
-    public void verify(PublicKey key, String provider)
-            throws CertificateException, NoSuchAlgorithmException,
-            InvalidKeyException, NoSuchProviderException, SignatureException;
-    
-    /**
-     * Return an ASN.1 encoded byte array representing the attribute certificate.
-     * 
-     * @return an ASN.1 encoded byte array.
-     * @throws IOException if the certificate cannot be encoded.
-     */
-    public byte[] getEncoded()
-        throws IOException;
-}
diff --git a/azureus2/src/org/bouncycastle/x509/X509Util.java b/azureus2/src/org/bouncycastle/x509/X509Util.java
deleted file mode 100644
index 6a9a4ec..0000000
--- a/azureus2/src/org/bouncycastle/x509/X509Util.java
+++ /dev/null
@@ -1,411 +0,0 @@
-package org.bouncycastle.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.DEREncodable;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-//import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
-//import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
-//import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-//import org.bouncycastle.asn1.pkcs.RSASSAPSSparams;
-import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
-import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import org.bouncycastle.jce.X509Principal;
-import org.bouncycastle.util.Strings;
-
-import javax.security.auth.x500.X500Principal;
-import java.io.IOException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.Provider;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-class X509Util
-{
-    private static Hashtable algorithms = new Hashtable();
-    private static Hashtable params = new Hashtable();
-    private static Set       noParams = new HashSet();
-    
-    static
-    {   
-        algorithms.put("MD2WITHRSAENCRYPTION", PKCSObjectIdentifiers.md2WithRSAEncryption);
-        algorithms.put("MD2WITHRSA", PKCSObjectIdentifiers.md2WithRSAEncryption);
-        algorithms.put("MD5WITHRSAENCRYPTION", PKCSObjectIdentifiers.md5WithRSAEncryption);
-        algorithms.put("MD5WITHRSA", PKCSObjectIdentifiers.md5WithRSAEncryption);
-        algorithms.put("SHA1WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha1WithRSAEncryption);
-        algorithms.put("SHA1WITHRSA", PKCSObjectIdentifiers.sha1WithRSAEncryption);
-     //   algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption);
-     //   algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption);
-        algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption);
-        algorithms.put("SHA256WITHRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption);
-        algorithms.put("SHA384WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha384WithRSAEncryption);
-        algorithms.put("SHA384WITHRSA", PKCSObjectIdentifiers.sha384WithRSAEncryption);
-        algorithms.put("SHA512WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha512WithRSAEncryption);
-        algorithms.put("SHA512WITHRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption);
-    //    algorithms.put("SHA1WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
-    //    algorithms.put("SHA224WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
-    //    algorithms.put("SHA256WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
-    //    algorithms.put("SHA384WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
-    //    algorithms.put("SHA512WITHRSAANDMGF1", PKCSObjectIdentifiers.id_RSASSA_PSS);
-        algorithms.put("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
-        algorithms.put("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160);
-        algorithms.put("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
-        algorithms.put("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128);
-        algorithms.put("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
-        algorithms.put("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256);
-        algorithms.put("SHA1WITHDSA", X9ObjectIdentifiers.id_dsa_with_sha1);
-        algorithms.put("DSAWITHSHA1", X9ObjectIdentifiers.id_dsa_with_sha1);
-    //    algorithms.put("SHA224WITHDSA", NISTObjectIdentifiers.dsa_with_sha224);
-    //    algorithms.put("SHA256WITHDSA", NISTObjectIdentifiers.dsa_with_sha256);
-        algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1);
-        algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1);
-    //    algorithms.put("SHA224WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA224);
-    //    algorithms.put("SHA256WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256);
-    //    algorithms.put("SHA384WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384);
-    //    algorithms.put("SHA512WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512);
-    //    algorithms.put("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
-    //    algorithms.put("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
-    //    algorithms.put("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
-    //    algorithms.put("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
-    //    algorithms.put("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
-
-        //
-        // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field. 
-        // The parameters field SHALL be NULL for RSA based signature algorithms.
-        //
-        noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA1);
-    //    noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA224);
-    //    noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA256);
-    //    noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA384);
-    //    noParams.add(X9ObjectIdentifiers.ecdsa_with_SHA512);
-        noParams.add(X9ObjectIdentifiers.id_dsa_with_sha1);
-   //     noParams.add(NISTObjectIdentifiers.dsa_with_sha224);
-   //     noParams.add(NISTObjectIdentifiers.dsa_with_sha256);
-
-        //
-        // RFC 4491
-        //
-   //     noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94);
-   //     noParams.add(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001);
-
-        //
-        // explicit params
-        //
-        /*
-        AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, new DERNull());
-        params.put("SHA1WITHRSAANDMGF1", creatPSSParams(sha1AlgId, 20));
-
-        AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha224, new DERNull());
-        params.put("SHA224WITHRSAANDMGF1", creatPSSParams(sha224AlgId, 28));
-
-        AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, new DERNull());
-        params.put("SHA256WITHRSAANDMGF1", creatPSSParams(sha256AlgId, 32));
-
-        AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha384, new DERNull());
-        params.put("SHA384WITHRSAANDMGF1", creatPSSParams(sha384AlgId, 48));
-
-        AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha512, new DERNull());
-        params.put("SHA512WITHRSAANDMGF1", creatPSSParams(sha512AlgId, 64));
-        */
-    }
-
-    /* PARG - commented out a lot of these
-    private static RSASSAPSSparams creatPSSParams(AlgorithmIdentifier hashAlgId, int saltSize)
-    {
-        return new RSASSAPSSparams(
-            hashAlgId,
-            new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgId),
-            new DERInteger(saltSize),
-            new DERInteger(1));
-    }
-	*/
-    
-    static DERObjectIdentifier getAlgorithmOID(
-        String algorithmName)
-    {
-        algorithmName = Strings.toUpperCase(algorithmName);
-        
-        if (algorithms.containsKey(algorithmName))
-        {
-            return (DERObjectIdentifier)algorithms.get(algorithmName);
-        }
-        
-        return new DERObjectIdentifier(algorithmName);
-    }
-    
-    static AlgorithmIdentifier getSigAlgID(
-        DERObjectIdentifier sigOid,
-        String              algorithmName)
-    {
-        if (noParams.contains(sigOid))
-        {
-            return new AlgorithmIdentifier(sigOid);
-        }
-
-        algorithmName = Strings.toUpperCase(algorithmName);
-
-        if (params.containsKey(algorithmName))
-        {
-            return new AlgorithmIdentifier(sigOid, (DEREncodable)params.get(algorithmName));
-        }
-        else
-        {
-            return new AlgorithmIdentifier(sigOid, new DERNull());
-        }
-    }
-    
-    static Iterator getAlgNames()
-    {
-        Enumeration e = algorithms.keys();
-        List        l = new ArrayList();
-        
-        while (e.hasMoreElements())
-        {
-            l.add(e.nextElement());
-        }
-        
-        return l.iterator();
-    }
-
-    static Signature getSignatureInstance(
-        String algorithm)
-        throws NoSuchAlgorithmException
-    {
-        return Signature.getInstance(algorithm);
-    }
-
-    static Signature getSignatureInstance(
-        String algorithm,
-        String provider)
-        throws NoSuchProviderException, NoSuchAlgorithmException
-    {
-        if (provider != null)
-        {
-            return Signature.getInstance(algorithm, provider);
-        }
-        else
-        {
-            return Signature.getInstance(algorithm);
-        }
-    }
-
-    static byte[] calculateSignature(
-        DERObjectIdentifier sigOid,
-        String              sigName,
-        PrivateKey          key,
-        SecureRandom        random,
-        ASN1Encodable       object)
-        throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException
-    {
-        Signature sig;
-
-        if (sigOid == null)
-        {
-            throw new IllegalStateException("no signature algorithm specified");
-        }
-
-        sig = X509Util.getSignatureInstance(sigName);
-
-        if (random != null)
-        {
-            sig.initSign(key, random);
-        }
-        else
-        {
-            sig.initSign(key);
-        }
-
-        sig.update(object.getEncoded(ASN1Encodable.DER));
-
-        return sig.sign();
-    }
-
-    static byte[] calculateSignature(
-        DERObjectIdentifier sigOid,
-        String              sigName,
-        String              provider,
-        PrivateKey          key,
-        SecureRandom        random,
-        ASN1Encodable       object)
-        throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, SignatureException
-    {
-        Signature sig;
-
-        if (sigOid == null)
-        {
-            throw new IllegalStateException("no signature algorithm specified");
-        }
-
-        sig = X509Util.getSignatureInstance(sigName, provider);
-
-        if (random != null)
-        {
-            sig.initSign(key, random);
-        }
-        else
-        {
-            sig.initSign(key);
-        }
-
-        sig.update(object.getEncoded(ASN1Encodable.DER));
-
-        return sig.sign();
-    }
-
-    static X509Principal convertPrincipal(
-        X500Principal principal)
-    {
-        try
-        {
-            return new X509Principal(principal.getEncoded());
-        }
-        catch (IOException e)
-        {
-            throw new IllegalArgumentException("cannot convert principal");
-        }
-    }
-
-    static class Implementation
-    {
-        Object      engine;
-        Provider provider;
-
-        Implementation(
-            Object      engine,
-            Provider    provider)
-        {
-            this.engine = engine;
-            this.provider = provider;
-        }
-
-        Object getEngine()
-        {
-            return engine;
-        }
-
-        Provider getProvider()
-        {
-            return provider;
-        }
-    }
-
-    /**
-     * see if we can find an algorithm (or its alias and what it represents) in
-     * the property table for the given provider.
-     */
-    static Implementation getImplementation(
-        String      baseName,
-        String      algorithm,
-        Provider    prov)
-        throws NoSuchAlgorithmException
-    {
-        algorithm = Strings.toUpperCase(algorithm);
-
-        String      alias;
-
-        while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null)
-        {
-            algorithm = alias;
-        }
-
-        String      className = prov.getProperty(baseName + "." + algorithm);
-
-        if (className != null)
-        {
-            try
-            {
-                Class       cls;
-                ClassLoader clsLoader = prov.getClass().getClassLoader();
-
-                if (clsLoader != null)
-                {
-                    cls = clsLoader.loadClass(className);
-                }
-                else
-                {
-                    cls = Class.forName(className);
-                }
-
-                return new Implementation(cls.newInstance(), prov);
-            }
-            catch (ClassNotFoundException e)
-            {
-                throw new IllegalStateException(
-                    "algorithm " + algorithm + " in provider " + prov.getName() + " but no class \"" + className + "\" found!");
-            }
-            catch (Exception e)
-            {
-                throw new IllegalStateException(
-                    "algorithm " + algorithm + " in provider " + prov.getName() + " but class \"" + className + "\" inaccessible!");
-            }
-        }
-
-        throw new NoSuchAlgorithmException("cannot find implementation " + algorithm + " for provider " + prov.getName());
-    }
-
-    /**
-     * return an implementation for a given algorithm/provider.
-     * If the provider is null, we grab the first avalaible who has the required algorithm.
-     */
-    static Implementation getImplementation(
-        String      baseName,
-        String      algorithm)
-        throws NoSuchAlgorithmException
-    {
-        Provider[] prov = Security.getProviders();
-
-        //
-        // search every provider looking for the algorithm we want.
-        //
-        for (int i = 0; i != prov.length; i++)
-        {
-            //
-            // try case insensitive
-            //
-            Implementation imp = getImplementation(baseName, Strings.toUpperCase(algorithm), prov[i]);
-            if (imp != null)
-            {
-                return imp;
-            }
-
-            try
-            {
-                imp = getImplementation(baseName, algorithm, prov[i]);
-            }
-            catch (NoSuchAlgorithmException e)
-            {
-                // continue
-            }
-        }
-
-        throw new NoSuchAlgorithmException("cannot find implementation " + algorithm);
-    }
-
-    static Provider getProvider(String provider)
-        throws NoSuchProviderException
-    {
-        Provider prov = Security.getProvider(provider);
-
-        if (prov == null)
-        {
-            throw new NoSuchProviderException("Provider " + provider + " not found");
-        }
-
-        return prov;
-    }
-}
diff --git a/azureus2/src/org/bouncycastle/x509/X509V2AttributeCertificate.java b/azureus2/src/org/bouncycastle/x509/X509V2AttributeCertificate.java
deleted file mode 100644
index 304d79f..0000000
--- a/azureus2/src/org/bouncycastle/x509/X509V2AttributeCertificate.java
+++ /dev/null
@@ -1,346 +0,0 @@
-package org.bouncycastle.x509;
-
-import org.bouncycastle.asn1.ASN1Encodable;
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.DERBitString;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROutputStream;
-import org.bouncycastle.asn1.x509.AttributeCertificate;
-import org.bouncycastle.asn1.x509.X509Extension;
-import org.bouncycastle.asn1.x509.X509Extensions;
-import org.bouncycastle.util.Arrays;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PublicKey;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * An implementation of a version 2 X.509 Attribute Certificate.
- */
-public class X509V2AttributeCertificate
-    implements X509AttributeCertificate
-{
-    private AttributeCertificate    cert;
-    private Date                    notBefore;
-    private Date                    notAfter;
-    
-    public X509V2AttributeCertificate(
-        InputStream encIn)
-        throws IOException
-    {
-        this(AttributeCertificate.getInstance(new ASN1InputStream(encIn).readObject()));
-    }
-    
-    public X509V2AttributeCertificate(
-        byte[]  encoded)
-        throws IOException
-    {
-        this(new ByteArrayInputStream(encoded));
-    }
-    
-    X509V2AttributeCertificate(
-        AttributeCertificate    cert)
-        throws IOException
-    {
-        this.cert = cert;
-        
-        try
-        {
-            this.notAfter = cert.getAcinfo().getAttrCertValidityPeriod().getNotAfterTime().getDate();
-            this.notBefore = cert.getAcinfo().getAttrCertValidityPeriod().getNotBeforeTime().getDate();
-        }
-        catch (ParseException e)
-        {
-            throw new IOException("invalid data structure in certificate!");
-        }
-    }
-    
-    public int getVersion()
-    {
-        return cert.getAcinfo().getVersion().getValue().intValue();
-    }
-    
-    public BigInteger getSerialNumber()
-    {
-        return cert.getAcinfo().getSerialNumber().getValue();
-    }
-    
-    public AttributeCertificateHolder getHolder()
-    {
-        return new AttributeCertificateHolder((ASN1Sequence)cert.getAcinfo().getHolder().toASN1Object());
-    }
-    
-    public AttributeCertificateIssuer getIssuer()
-    {
-        return new AttributeCertificateIssuer(cert.getAcinfo().getIssuer());
-    }
-    
-    public Date getNotBefore()
-    {
-        return notBefore;
-    }
-    
-    public Date getNotAfter()
-    {
-        return notAfter;
-    }
-    
-    public boolean[] getIssuerUniqueID()
-    {
-        DERBitString    id = cert.getAcinfo().getIssuerUniqueID();
-
-        if (id != null)
-        {
-            byte[]          bytes = id.getBytes();
-            boolean[]       boolId = new boolean[bytes.length * 8 - id.getPadBits()];
-
-            for (int i = 0; i != boolId.length; i++)
-            {
-                boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
-            }
-
-            return boolId;
-        }
-            
-        return null;
-    }
-    
-    public void checkValidity() 
-        throws CertificateExpiredException, CertificateNotYetValidException
-    {
-        this.checkValidity(new Date());
-    }
-    
-    public void checkValidity(
-        Date    date)
-        throws CertificateExpiredException, CertificateNotYetValidException
-    {
-        if (date.after(this.getNotAfter()))
-        {
-            throw new CertificateExpiredException("certificate expired on " + this.getNotAfter());
-        }
-
-        if (date.before(this.getNotBefore()))
-        {
-            throw new CertificateNotYetValidException("certificate not valid till " + this.getNotBefore());
-        }
-    }
-    
-    public byte[] getSignature()
-    {
-        return cert.getSignatureValue().getBytes();
-    }
-    
-    public final void verify(
-            PublicKey   key,
-            String      provider)
-            throws CertificateException, NoSuchAlgorithmException,
-            InvalidKeyException, NoSuchProviderException, SignatureException
-    {
-        Signature   signature = null;
-
-        if (!cert.getSignatureAlgorithm().equals(cert.getAcinfo().getSignature()))
-        {
-            throw new CertificateException("Signature algorithm in certificate info not same as outer certificate");
-        }
-
-        signature = Signature.getInstance(cert.getSignatureAlgorithm().getObjectId().getId(), provider);
-
-        signature.initVerify(key);
-
-        try
-        {
-            signature.update(cert.getAcinfo().getEncoded());
-        }
-        catch (IOException e)
-        {
-            throw new SignatureException("Exception encoding certificate info object");
-        }
-
-        if (!signature.verify(this.getSignature()))
-        {
-            throw new InvalidKeyException("Public key presented not for certificate signature");
-        }
-    }
-    
-    public byte[] getEncoded()
-        throws IOException
-    {
-        return cert.getEncoded();
-    }
-
-    public byte[] getExtensionValue(String oid) 
-    {
-        X509Extensions  extensions = cert.getAcinfo().getExtensions();
-
-        if (extensions != null)
-        {
-            X509Extension   ext = extensions.getExtension(new DERObjectIdentifier(oid));
-
-            if (ext != null)
-            {
-                ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
-                DEROutputStream            dOut = new DEROutputStream(bOut);
-                
-                try
-                {
-                    dOut.writeObject(ext.getValue());
-
-                    return bOut.toByteArray();
-                }
-                catch (Exception e)
-                {
-                    throw new RuntimeException("error encoding " + e.toString());
-                }
-            }
-        }
-
-        return null;
-    }
-
-    private Set getExtensionOIDs(
-        boolean critical) 
-    {
-        X509Extensions  extensions = cert.getAcinfo().getExtensions();
-
-        if (extensions != null)
-        {
-            Set             set = new HashSet();
-            Enumeration     e = extensions.oids();
-
-            while (e.hasMoreElements())
-            {
-                DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
-                X509Extension       ext = extensions.getExtension(oid);
-
-                if (ext.isCritical() == critical)
-                {
-                    set.add(oid.getId());
-                }
-            }
-
-            return set;
-        }
-
-        return null;
-    }
-    
-    public Set getNonCriticalExtensionOIDs() 
-    {
-        return getExtensionOIDs(false);
-    }
-
-    public Set getCriticalExtensionOIDs() 
-    {
-        return getExtensionOIDs(true);
-    }
-    
-    public boolean hasUnsupportedCriticalExtension()
-    {
-        Set  extensions = getCriticalExtensionOIDs();
-
-        return extensions != null && !extensions.isEmpty();
-    }
-
-    public X509Attribute[] getAttributes()
-    {
-        ASN1Sequence    seq = cert.getAcinfo().getAttributes();
-        X509Attribute[] attrs = new X509Attribute[seq.size()];
-        
-        for (int i = 0; i != seq.size(); i++)
-        {
-            attrs[i] = new X509Attribute((ASN1Encodable)seq.getObjectAt(i));
-        }
-        
-        return attrs;
-    }
-    
-    public X509Attribute[] getAttributes(String oid)
-    {
-        ASN1Sequence    seq = cert.getAcinfo().getAttributes();
-        List            list = new ArrayList();
-        
-        for (int i = 0; i != seq.size(); i++)
-        {
-            X509Attribute attr = new X509Attribute((ASN1Encodable)seq.getObjectAt(i));
-            if (attr.getOID().equals(oid))
-            {
-                list.add(attr);
-            }
-        }
-        
-        if (list.size() == 0)
-        {
-            return null;
-        }
-        
-        return (X509Attribute[])list.toArray(new X509Attribute[list.size()]);
-    }
-
-    public boolean equals(
-        Object o)
-    {
-        if (o == this)
-        {
-            return true;
-        }
-
-        if (!(o instanceof X509AttributeCertificate))
-        {
-            return false;
-        }
-
-        X509AttributeCertificate other = (X509AttributeCertificate)o;
-
-        try
-        {
-            byte[] b1 = this.getEncoded();
-            byte[] b2 = other.getEncoded();
-
-            return Arrays.areEqual(b1, b2);
-        }
-        catch (IOException e)
-        {
-            return false;
-        }
-    }
-
-    public int hashCode()
-    {
-        try
-        {
-            byte[]  b = this.getEncoded();
-            int     value = 0;
-
-            for (int i = 0; i != b.length; i++)
-            {
-                value ^= (b[i] & 0xff) << (i % 4);
-            }
-
-            return value;
-        }
-        catch (IOException e)
-        {
-            return 0;
-        }
-    }
-}
diff --git a/azureus2/src/org/gudy/azureus2/core3/category/Category.java b/azureus2/src/org/gudy/azureus2/core3/category/Category.java
index 7bfcd0b..b408fd3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/category/Category.java
+++ b/azureus2/src/org/gudy/azureus2/core3/category/Category.java
@@ -6,7 +6,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/category/CategoryListener.java b/azureus2/src/org/gudy/azureus2/core3/category/CategoryListener.java
index 73b1838..9915a40 100644
--- a/azureus2/src/org/gudy/azureus2/core3/category/CategoryListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/category/CategoryListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/category/CategoryManager.java b/azureus2/src/org/gudy/azureus2/core3/category/CategoryManager.java
index 62bdf90..ef60830 100644
--- a/azureus2/src/org/gudy/azureus2/core3/category/CategoryManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/category/CategoryManager.java
@@ -6,7 +6,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/category/CategoryManagerListener.java b/azureus2/src/org/gudy/azureus2/core3/category/CategoryManagerListener.java
index c58e0ad..a29c26c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/category/CategoryManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/category/CategoryManagerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/category/impl/CategoryImpl.java b/azureus2/src/org/gudy/azureus2/core3/category/impl/CategoryImpl.java
index bf599ea..adf3616 100644
--- a/azureus2/src/org/gudy/azureus2/core3/category/impl/CategoryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/category/impl/CategoryImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -21,7 +22,6 @@
 
 package org.gudy.azureus2.core3.category.impl;
 
-import java.util.HashSet;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Map;
@@ -108,6 +108,8 @@ CategoryImpl
 	  }
   };  
   
+  private boolean destroyed;
+  
   private static final int LDT_CATEGORY_DMADDED     = 1;
   private static final int LDT_CATEGORY_DMREMOVED   = 2;
 	private ListenerManager<CategoryListener>	category_listeners = ListenerManager.createManager(
@@ -148,7 +150,9 @@ CategoryImpl
   }
 
   public void addCategoryListener(CategoryListener l) {
-	  category_listeners.addListener( l );
+  	if (!category_listeners.hasListener(l)) {
+  		category_listeners.addListener( l );
+  	}
   }
 
   public void removeCategoryListener(CategoryListener l) {
@@ -530,10 +534,12 @@ CategoryImpl
   getTaggedDownloads()
   {
   	AzureusCore core = AzureusCoreFactory.getSingleton();
-  	if (!core.isStarted()) {
+  	
+  	if ( !core.isStarted()){
+  		
   		return new IdentityHashSet<DownloadManager>();
   	}
-	 return( new IdentityHashSet<DownloadManager>(getDownloadManagers( core.getGlobalManager().getDownloadManagers())));
+	return( new IdentityHashSet<DownloadManager>(getDownloadManagers( core.getGlobalManager().getDownloadManagers())));
   }
   
   public Set<Taggable> 
@@ -552,7 +558,34 @@ CategoryImpl
 	hasTaggable(
 		Taggable	t )
 	{
-		return( getTagged().contains( t ));
+		if ( !( t instanceof DownloadManager )){
+			
+			return( false );
+		}
+			  	
+	  	if ( type == Category.TYPE_USER ){
+	  		
+	  		return( managers.contains( t ));
+	  		
+	  	}else if ( type == Category.TYPE_ALL ){
+	  		
+	  		return( true );
+	  		
+	  	}else{
+	  		
+	  		DownloadManager dm = (DownloadManager)t;
+	  		
+	  		Category cat = dm.getDownloadState().getCategory();
+	  		
+	  		if ( cat == null || cat.getType() == Category.TYPE_UNCATEGORIZED ){
+	  			
+	  			return( true );
+	  			
+	  		}else{
+	  			
+	  			return( false );
+	  		}
+	  	}
 	}
 	
 	public int
@@ -585,7 +618,12 @@ CategoryImpl
   protected void
   destroy()
   {
-	  removeTag();
+	  if ( !destroyed ){
+		  
+		  destroyed = true;
+	  
+		  removeTag();
+	  }
   }
   
   public int compareTo(Object b)
diff --git a/azureus2/src/org/gudy/azureus2/core3/category/impl/CategoryManagerImpl.java b/azureus2/src/org/gudy/azureus2/core3/category/impl/CategoryManagerImpl.java
index 1614372..c0052b3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/category/impl/CategoryManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/category/impl/CategoryManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -586,7 +587,7 @@ CategoryManagerImpl
 				
 				pw.println( "<guid>" + hash_str + "</guid>" );
 				
-				String magnet_url = escape( UrlUtils.getMagnetURI( download.getName(), torrent ));
+				String magnet_url = escape( UrlUtils.getMagnetURI( download ));
 
 				pw.println( "<link>" + magnet_url + "</link>" );
 				
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/COConfigurationListener.java b/azureus2/src/org/gudy/azureus2/core3/config/COConfigurationListener.java
index 822ebf2..8dca9dd 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/COConfigurationListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/COConfigurationListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/COConfigurationManager.java b/azureus2/src/org/gudy/azureus2/core3/config/COConfigurationManager.java
index 6e6916f..6c3a913 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/COConfigurationManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/COConfigurationManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -198,7 +199,8 @@ COConfigurationManager
 			  	
 			  	System.setProperty("sun.net.inetaddr.ttl", "60");
 			  	System.setProperty("networkaddress.cache.ttl", "60");
-			  	
+			  	System.setProperty("sun.net.inetaddr.negative.ttl", "300" );
+			  	System.setProperty("networkaddress.cache.negative.ttl", "300" );
 			  	
 			  	// flick AWT into headless mode, which is supposed to make it more lightweight
 			  	// don't do this as it borks (for example) swing based plugins, java webstart installer,
@@ -228,6 +230,13 @@ COConfigurationManager
 			    	//}
 			    }
 			    
+			    //if ( Constants.IS_CVS_VERSION && ( Constants.isOSX || Constants.isWindows )){
+			    // everyone gets this as we use it to force prevent resolution when running socks
+			    
+			    System.setProperty("sun.net.spi.nameservice.provider.1","dns,aednsproxy");
+			    
+			    //}
+			    
 			    SystemProperties.determineApplicationName();
 			    
 			}catch( Throwable e ){
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/ParameterListener.java b/azureus2/src/org/gudy/azureus2/core3/config/ParameterListener.java
index a0d5982..442d0b5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/ParameterListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/ParameterListener.java
@@ -1,6 +1,6 @@
 /*
  * Created on 24.11.2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/PriorityParameterListener.java b/azureus2/src/org/gudy/azureus2/core3/config/PriorityParameterListener.java
index 0173f74..3ff4957 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/PriorityParameterListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/PriorityParameterListener.java
@@ -1,36 +1,35 @@
-/*
- * Created on Jan 28, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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.core3.config;
-
-/**
- * Instances of this will be invoked before any ParameterListeners are. 
- * The purpose of this is to allow safe caching of parameter values in the light of other
- * listeners that may use the cached values and hence must be invoked after the cached value
- * has been updated. Therefore only ever use this type of listener for this purpose!
- * @author Paul
- *
- */
-public interface 
-PriorityParameterListener
-	extends ParameterListener
-{
-}
+/*
+ * Created on Jan 28, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.config;
+
+/**
+ * Instances of this will be invoked before any ParameterListeners are. 
+ * The purpose of this is to allow safe caching of parameter values in the light of other
+ * listeners that may use the cached values and hence must be invoked after the cached value
+ * has been updated. Therefore only ever use this type of listener for this purpose!
+ * @author Paul
+ *
+ */
+public interface 
+PriorityParameterListener
+	extends ParameterListener
+{
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/StringIterator.java b/azureus2/src/org/gudy/azureus2/core3/config/StringIterator.java
index 2609c92..f426806 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/StringIterator.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/StringIterator.java
@@ -2,11 +2,12 @@
  * Created on 24 sept. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/StringList.java b/azureus2/src/org/gudy/azureus2/core3/config/StringList.java
index d92b4c3..51ed2ee 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/StringList.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/StringList.java
@@ -2,11 +2,12 @@
  * Created on 24 sept. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationChecker.java b/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationChecker.java
index 8376322..749ded3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationChecker.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationChecker.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -22,7 +23,6 @@
 package org.gudy.azureus2.core3.config.impl;
 
 
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Properties;
@@ -34,6 +34,9 @@ import org.gudy.azureus2.core3.config.*;
 import org.gudy.azureus2.core3.security.*;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.core3.logging.*;
+import org.gudy.azureus2.platform.PlatformManager;
+import org.gudy.azureus2.platform.PlatformManagerCapabilities;
+import org.gudy.azureus2.platform.PlatformManagerFactory;
 
 import com.aelitis.azureus.core.custom.CustomizationManagerFactory;
 import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerImpl;
@@ -756,6 +759,48 @@ ConfigurationChecker
 	    	changed = true;
 	    }
       
+	    	// 5601 propagate swt crash settings 
+	    {
+	    	if ( System.getProperty( "azureus.internal.browser.disable", "0" ).equals( "1" )){
+	    		
+	    		if ( !COConfigurationManager.getBooleanParameter( "browser.internal.disable", false )){
+	    		
+	    			COConfigurationManager.setParameter( "browser.internal.disable", true );
+				
+	    			changed = true;
+	    		}
+	    	}
+	    	
+			if ( COConfigurationManager.getBooleanParameter( "azpromo.dump.disable.plugin", false )){
+	
+					// plugin has detected a crash
+				
+				if ( !COConfigurationManager.doesParameterNonDefaultExist( "browser.internal.disable" )){
+					
+					COConfigurationManager.setParameter( "browser.internal.disable", true );
+					
+					changed = true;
+				}
+			}
+			
+			COConfigurationManager.addAndFireParameterListener(
+				"browser.internal.disable",
+				new ParameterListener() {
+					
+					public void
+					parameterChanged(
+						String parameterName) 
+					{
+						if ( COConfigurationManager.getBooleanParameter( "browser.internal.disable", false )){
+							
+							COConfigurationManager.setParameter( "azpromo.dump.disable.plugin", true );
+							
+							COConfigurationManager.setDirty();
+						}
+					}
+				});
+	    }
+	    
 	    if ( FeatureAvailability.isAutoSpeedDefaultClassic()){
 	    
 	    	ConfigurationDefaults.getInstance().addParameter( SpeedManagerImpl.CONFIG_VERSION, 1 );	// 1 == classic, 2 == beta
@@ -829,7 +874,10 @@ ConfigurationChecker
 	    
 	    if(changed) {
 	      COConfigurationManager.save();
-	    } 
+	    }
+	    
+	    setupVerifier();
+	    
   	}finally{
   		
   		class_mon.exit();
@@ -838,6 +886,72 @@ ConfigurationChecker
   	ConfigurationDefaults.getInstance().runVerifiers();
   }
   	
+  private static void
+  setupVerifier()
+  {
+	  SimpleTimer.addEvent(
+			"ConfigCheck:ver",
+			SystemTime.getOffsetTime( 10*1000 ),
+			new TimerEventPerformer() {
+				
+				private TimerEventPeriodic event;
+				
+				public void 
+				perform(
+					TimerEvent ev )
+				{
+					runVerifier();
+					
+					if ( event == null ){
+						
+						long freq = COConfigurationManager.getLongParameter( "Config Verify Frequency" );
+						
+						if ( freq > 0 ){
+						
+							freq = Math.max( freq,  5*60*1000 );
+								
+							event = 
+								SimpleTimer.addPeriodicEvent(
+									"ConfigCheck:ver",
+									freq,
+									this );
+						}
+					}
+				}
+			});
+  }
+  
+  private static void
+  runVerifier()
+  {
+	  try{
+		  PlatformManager pm = PlatformManagerFactory.getPlatformManager();
+		  
+		  if ( pm.hasCapability( PlatformManagerCapabilities.RunAtLogin )){
+			
+			  boolean	start_on_login = COConfigurationManager.getBooleanParameter( "Start On Login" );
+			  
+			  if ( pm.getRunAtLogin() != start_on_login ){
+				  
+				  pm.setRunAtLogin( start_on_login );
+			  }
+		  }
+		  
+		  if ( pm.hasCapability(PlatformManagerCapabilities.RegisterFileAssociations )){
+			  
+			  boolean	auto_reg = COConfigurationManager.getBooleanParameter( "Auto Register App" );
+
+			  if ( auto_reg ){
+				  
+				  pm.registerApplication();
+			  }
+		  }
+	  }catch( Throwable e ){
+		  
+		  Debug.out( e );
+	  }
+  }
+  
 	public static final boolean
 	isNewInstall()
 	{
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationDefaults.java b/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationDefaults.java
index bbd81f3..e023617 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationDefaults.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationDefaults.java
@@ -3,7 +3,7 @@
  * ConfigurationDefaults.java
  *
  * Created on 31. Juli 2003, 21:31
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -17,9 +17,6 @@
  * 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.config.impl;
@@ -212,6 +209,7 @@ public class ConfigurationDefaults {
     def.put("On Resume Recheck All", FALSE);
     def.put("Save Resume Interval", new Long(5));
     def.put("Check Pieces on Completion", TRUE);
+    def.put("Merge Same Size Files", TRUE );
     def.put("Stop Ratio", new Float(0));
     def.put("Stop Peers Ratio", ZERO);
     def.put("Disconnect Seed", TRUE);
@@ -243,6 +241,8 @@ public class ConfigurationDefaults {
     
     def.put("Start On Login", FALSE );
     def.put("Start In Low Resource Mode", FALSE );
+    def.put("Auto Register App", FALSE );
+    
     def.put("Pause Downloads On Exit", FALSE );
     def.put("Resume Downloads On Start", FALSE );
     def.put("On Downloading Complete Do", "Nothing" );
@@ -275,12 +275,15 @@ public class ConfigurationDefaults {
 	}
 	
 	def.put("Default save path", f.getAbsolutePath());
-    
+	def.put("saveTo_list.max_entries", new Long(15));
+	
     def.put("update.start",TRUE);
     def.put("update.periodic",TRUE);
     def.put("update.opendialog",TRUE);
     def.put("update.autodownload", FALSE);
 
+    def.put( "Config Verify Frequency", new Long( 30*60*1000 ));
+    
     def.put("Send Version Info", TRUE);
     
     // Logging
@@ -309,7 +312,9 @@ public class ConfigurationDefaults {
     def.put( "Proxy.Check.On.Start", TRUE );
     def.put( "Proxy.SOCKS.ShowIcon", TRUE );
     def.put( "Proxy.SOCKS.ShowIcon.FlagIncoming", TRUE );
-    	
+    def.put( "Proxy.SOCKS.Tracker.DNS.Disable", TRUE );
+    def.put( "Proxy.SOCKS.disable.plugin.proxies", TRUE );
+    
     	// data proxy defaults
     def.put( "Proxy.Data.Enable", FALSE);
     def.put( "Proxy.Data.SOCKS.version", "V4" );
@@ -361,7 +366,8 @@ public class ConfigurationDefaults {
     
     //default torrent directory option
     def.put( "Save Torrent Files", TRUE );
-    def.put("General_sDefaultTorrent_Directory", SystemProperties.getUserPath()+"torrents");
+    def.put( "General_sDefaultTorrent_Directory", SystemProperties.getUserPath()+"torrents");
+    def.put( "Delete Original Torrent Files", FALSE );
 
   
     def.put( "Bind IP", "" );
@@ -378,6 +384,7 @@ public class ConfigurationDefaults {
     def.put( "Stats File", StatsWriterPeriodic.DEFAULT_STATS_FILE_NAME );
     def.put( "long.term.stats.enable", TRUE );
     def.put( "Stats Smoothing Secs", new Long( 2*60 ));
+    def.put( "File.Torrent.AutoSkipExtensions", "" );
     def.put( "File.Torrent.IgnoreFiles", TOTorrent.DEFAULT_IGNORE_FILES );
     def.put( "File.save.peers.max", new Long( TRTrackerAnnouncer.DEFAULT_PEERS_TO_CACHE ) );
     
@@ -669,6 +676,8 @@ public class ConfigurationDefaults {
     def.put( "Show Options In Side Bar", FALSE );
     
     def.put( "Share Ratio Progress Interval", 1000L );	// thousandths
+    
+    def.put( "installer.mode", "" );		// the type of the last installer used (see installer code for values)
 }
   
   protected 
@@ -717,7 +726,7 @@ public class ConfigurationDefaults {
   
   public int getIntParameter(String p) throws ConfigurationParameterNotFoundException {
 	    checkParameterExists(p);
-	    return ((Long) def.get(p)).intValue();
+	    return ((Number) def.get(p)).intValue();
   }
   
   public long getLongParameter(String p) throws ConfigurationParameterNotFoundException {
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationManager.java b/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationManager.java
index 5e71384..9804856 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationManager.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 20, 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config.impl;
 
@@ -238,7 +235,7 @@ ConfigurationManager
       	if (key == null) {
       		continue;
       	}
-  			if (key.startsWith("SideBar.Expanded.Category.") || key.startsWith("NameColumn.wrapText.")) {
+  			if (key.startsWith("SideBar.Expanded.AutoOpen.") || key.startsWith("NameColumn.wrapText.")) {
   				removeParameter(key);
   			}
   		}
@@ -1229,6 +1226,7 @@ ConfigurationManager
   		
 		if ( 	key.startsWith( CryptoManager.CRYPTO_CONFIG_PREFIX ) || 
 				lc_key.equals( "id" ) ||
+				lc_key.equals( "azbuddy.dchat.optsmap" ) || 
 				lc_key.endsWith( ".privx" ) ||
 				lc_key.endsWith( ".user" ) ||
 				lc_key.contains( "password" ) ||
@@ -1238,6 +1236,26 @@ ConfigurationManager
 			return( true );
 		}
 			
+		Object	value	= propertiesMap.get(key);
+
+		if ( value instanceof byte[] ){
+			
+			try{
+				value = new String((byte[])value, "UTF-8" );
+				
+			}catch( Throwable e ){
+				
+			}
+		}
+		
+		if ( value instanceof String ){
+			
+			if (((String)value).toLowerCase( Locale.US ).endsWith( ".b32.i2p" )){
+				
+				return( true );
+			}
+		}
+		
 		return( false );
   	}
   	
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationParameterNotFoundException.java b/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationParameterNotFoundException.java
index 27a9746..7b8bb9e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationParameterNotFoundException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/impl/ConfigurationParameterNotFoundException.java
@@ -2,7 +2,7 @@
  * ConfigurationParameterNotFoundException.java
  *
  * Created on 22. August 2003, 19:18
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.config.impl;
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/impl/StringIteratorImpl.java b/azureus2/src/org/gudy/azureus2/core3/config/impl/StringIteratorImpl.java
index 7c01b14..63721ad 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/impl/StringIteratorImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/impl/StringIteratorImpl.java
@@ -2,11 +2,12 @@
  * Created on 24 sept. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.config.impl;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/impl/StringListImpl.java b/azureus2/src/org/gudy/azureus2/core3/config/impl/StringListImpl.java
index 307e42f..75010d7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/impl/StringListImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/impl/StringListImpl.java
@@ -2,11 +2,12 @@
  * Created on 24 sept. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.config.impl;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/config/impl/TransferSpeedValidator.java b/azureus2/src/org/gudy/azureus2/core3/config/impl/TransferSpeedValidator.java
index 1b51a8e..1c5cf10 100644
--- a/azureus2/src/org/gudy/azureus2/core3/config/impl/TransferSpeedValidator.java
+++ b/azureus2/src/org/gudy/azureus2/core3/config/impl/TransferSpeedValidator.java
@@ -3,7 +3,7 @@ package org.gudy.azureus2.core3.config.impl;
 /*
  * Created on 13-Feb-2005
  * Created by James Yeh
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -17,9 +17,6 @@ package org.gudy.azureus2.core3.config.impl;
  * 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.
- *
  */
 
 import org.gudy.azureus2.core3.config.*;
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManager.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManager.java
index e4a21d4..fec3ef7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -211,6 +212,9 @@ DiskManager
 	getPieceLength(
 		int	piece_number );
 	
+	/**
+	 * Get remaining bytes to completion *including* DND files
+	 */
 	public long
 	getRemaining();
 	
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerCheckRequest.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerCheckRequest.java
index 98cf344..4189a02 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerCheckRequest.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerCheckRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerCheckRequestListener.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerCheckRequestListener.java
index fc585d2..e8c8548 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerCheckRequestListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerCheckRequestListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Oct-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerException.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerException.java
index 89d7e51..2009160 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerException.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.disk;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFactory.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFactory.java
index 48317f3..6a6ae4d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfo.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfo.java
index 7df497a..08212d1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfo.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfo.java
@@ -3,7 +3,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfoListener.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfoListener.java
index ea21db1..c78949e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfoListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfoListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Apr-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfoSet.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfoSet.java
index 3252b12..52fe193 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfoSet.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerFileInfoSet.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.disk;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerListener.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerListener.java
index e877d1c..dcb1cce 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerPiece.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerPiece.java
index 4204b99..f7ac27e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerPiece.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerPiece.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Oct-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerReadRequest.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerReadRequest.java
index 49cf97a..de3b16e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerReadRequest.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerReadRequest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.disk;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerReadRequestListener.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerReadRequestListener.java
index da4e85a..39fe046 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerReadRequestListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerReadRequestListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 19, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerRequest.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerRequest.java
index 730106d..0557a99 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerRequest.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerWriteRequest.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerWriteRequest.java
index 7420f6f..9686dcb 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerWriteRequest.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerWriteRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerWriteRequestListener.java b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerWriteRequestListener.java
index bbaf681..48fcb8c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerWriteRequestListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/DiskManagerWriteRequestListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Oct-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerAllocationScheduler.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerAllocationScheduler.java
index 078f788..60a9f49 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerAllocationScheduler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerAllocationScheduler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoHelper.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoHelper.java
index 5f04be8..5ffcb03 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoHelper.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoHelper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Oct-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoImpl.java
index 3bd9654..911fd8d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoSetImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoSetImpl.java
index db52497..6318379 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoSetImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerFileInfoSetImpl.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.disk.impl;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerHelper.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerHelper.java
index 89923f5..818e03d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerHelper.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerHelper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerImpl.java
index 9aec3a4..f3abe3a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerImpl.java
@@ -2,7 +2,8 @@
  * Azureus - a Java Bittorrent client
  *
  * This program is free software; you can redistribute it and/or modify
- * the Free Software Foundation; either version 2 of the License.
+ * 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
@@ -16,7 +17,7 @@
  * Created on Oct 18, 2003
  * Created by Paul Gardner
  * Modified Apr 13, 2004 by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, All Rights Reserved.
  *
  */
 
@@ -1014,7 +1015,7 @@ DiskManagerImpl
 
                 if ( file_set.contains( file_key )){
 
-                    this.errorMessage = "File occurs more than once in download: " + data_file.toString();
+                    this.errorMessage = "File occurs more than once in download: " + data_file.toString() + ".\nRename one of the files in Files view via the right-click menu.";
 
                     setState( FAULTY );
 
@@ -1557,8 +1558,9 @@ DiskManagerImpl
                     if ( file_done == file_length ){
                          
                     	try{
+                      		DownloadManagerState state = download_manager.getDownloadState();
+
                     		try{
-	                      		DownloadManagerState state = download_manager.getDownloadState();
 	                    		
 	                    		String suffix = state.getAttribute( DownloadManagerState.AT_INCOMP_FILE_SUFFIX );
 	                    		
@@ -1638,6 +1640,13 @@ DiskManagerImpl
 
                                		this_file.setAccessMode( DiskManagerFileInfo.READ );
                                	}
+                             	
+                             		// only record completion during normal downloading, not rechecking etc
+                             	
+                             	if ( getState() == READY ){
+                             	
+                             		state.setLongParameter( DownloadManagerState.PARAM_DOWNLOAD_FILE_COMPLETED_TIME, SystemTime.getCurrentTime());
+                             	}
                     		}
                         }catch ( Throwable e ){
                         
@@ -2922,7 +2931,8 @@ DiskManagerImpl
 
                             // only delete the dir if there's only this torrent's files in it!
 
-                        if ( countFiles( new File(dir)) == countDataFiles( torrent, torrent_save_dir, torrent_save_file )){
+                        int numDataFiles = countDataFiles( torrent, torrent_save_dir, torrent_save_file );
+                        if ( countFiles( new File(dir), numDataFiles) == numDataFiles){
 
                             mgr.performRecoverableFileDelete( dir );
 
@@ -2949,7 +2959,8 @@ DiskManagerImpl
 
     private static int
     countFiles(
-        File    f )
+        File    f, 
+        int stopAfterCount )
     {
         if ( f.isFile()){
 
@@ -2964,7 +2975,11 @@ DiskManagerImpl
 
                 for (int i=0;i<files.length;i++){
 
-                    res += countFiles( files[i] );
+                    res += countFiles( files[i], stopAfterCount );
+                    
+                    if (res > stopAfterCount) {
+                    	break;
+                    }
                 }
             }
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerPieceImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerPieceImpl.java
index d6719bc..ad0676a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerPieceImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerPieceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Oct-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerRecheckInstance.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerRecheckInstance.java
index 4fddfbe..778f09b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerRecheckInstance.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerRecheckInstance.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerRecheckScheduler.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerRecheckScheduler.java
index beb9bef..1a9ef08 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerRecheckScheduler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerRecheckScheduler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerUtil.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerUtil.java
index e4a6752..dfaa14b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerUtil.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/DiskManagerUtil.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -257,21 +254,33 @@ DiskManagerUtil
 	
 	        }else{
 	
-                if ( FileUtil.deleteWithRecycle( 
-            		existing_file,
-            		download_manager.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE ))){
-	
-	                    // new file, recheck
-	
-	                download_manager.recheckFile( file_info );
-	
-	            }else{
-	
-	                Logger.log(new LogAlert(download_manager, LogAlert.REPEATABLE, LogAlert.AT_ERROR,
-	                        "Failed to delete '" + existing_file.toString() + "'"));
-	
-	                return( false );
-	            }
+	        	Object	skip_delete = download_manager.getUserData( "set_link_dont_delete_existing" );
+	        	
+	        		// user is manually re-targetting a file - this hack is to stop us from deleting the old file which 
+	        		// we really have no right to go and delete
+	        	
+	        	if ( ( skip_delete instanceof Boolean ) && (Boolean)skip_delete ){
+	        		
+	        		 download_manager.recheckFile( file_info );
+	        		 
+	        	}else{
+	        		
+	                if ( FileUtil.deleteWithRecycle( 
+	            		existing_file,
+	            		download_manager.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE ))){
+		
+		                    // new file, recheck
+		
+		                download_manager.recheckFile( file_info );
+		
+		            }else{
+		
+		                Logger.log(new LogAlert(download_manager, LogAlert.REPEATABLE, LogAlert.AT_ERROR,
+		                        "Failed to delete '" + existing_file.toString() + "'"));
+		
+		                return( false );
+		            }
+	        	}
 	        }
 	    }else{
 	
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMAccessFactory.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMAccessFactory.java
index 45fb485..edd64e8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMAccessFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMAccessFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMChecker.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMChecker.java
index f47e704..b37adde 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMChecker.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMChecker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMReader.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMReader.java
index 04959fb..26aba3e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMReader.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMReader.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMWriter.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMWriter.java
index 13195df..ded90f7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMWriter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/DMWriter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMCheckerImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMCheckerImpl.java
index b86fc80..c8d113e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMCheckerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMCheckerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMReaderImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMReaderImpl.java
index 74316ca..709e954 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMReaderImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMReaderImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMWriterImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMWriterImpl.java
index 6e04711..98aa432 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMWriterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DMWriterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerCheckRequestImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerCheckRequestImpl.java
index ec11266..bcb012c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerCheckRequestImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerCheckRequestImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerReadRequestImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerReadRequestImpl.java
index 3f9304f..ccb7b55 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerReadRequestImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerReadRequestImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerRequestImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerRequestImpl.java
index 74ba016..40b78a0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerRequestImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerRequestImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerWriteRequestImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerWriteRequestImpl.java
index 0ff0a8a..4f6fb45 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerWriteRequestImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/access/impl/DiskManagerWriteRequestImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
  
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceList.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceList.java
index 4211e09..06cc045 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceList.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceList.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMap.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMap.java
index 88ec300..9545bdb 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMap.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMap.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 15, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapEntry.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapEntry.java
index 3dee05c..708f1e8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapEntry.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapEntry.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
  
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapper.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapper.java
index 57717ad..dd4860b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapper.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapperFactory.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapperFactory.java
index 9dc99fe..d47aad8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapperFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapperFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapperFile.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapperFile.java
index 1d2973e..20cbc68 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapperFile.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/DMPieceMapperFile.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/DMPieceMapImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/DMPieceMapImpl.java
index 0adc149..93432f1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/DMPieceMapImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/DMPieceMapImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 15, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/DMPieceMapSimple.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/DMPieceMapSimple.java
index 17376c3..036e315 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/DMPieceMapSimple.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/DMPieceMapSimple.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 15, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceListImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceListImpl.java
index bfc3af0..701cf4a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceListImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceListImpl.java
@@ -1,6 +1,6 @@
 /*
  * Created on Sep 1, 2003 
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.disk.impl.piecemapper.impl;
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapEntryImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapEntryImpl.java
index 853df96..6732080 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapEntryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapEntryImpl.java
@@ -1,6 +1,6 @@
 /*
  * Created on Sep 1, 2003 
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.disk.impl.piecemapper.impl;
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapperImpl.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapperImpl.java
index fc5d482..24d544e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapperImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/piecemapper/impl/PieceMapperImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/disk/impl/resume/RDResumeHandler.java b/azureus2/src/org/gudy/azureus2/core3/disk/impl/resume/RDResumeHandler.java
index d4cd86d..47267bd 100644
--- a/azureus2/src/org/gudy/azureus2/core3/disk/impl/resume/RDResumeHandler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/disk/impl/resume/RDResumeHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 31-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManager.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManager.java
index 11c6a48..b16aa5b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -512,6 +513,13 @@ DownloadManager
         File    new_parent_dir )
 
         throws DownloadManagerException;
+    
+    public void
+    copyDataFiles(
+    	File	parent_dir )
+    
+    	throws DownloadManagerException;
+    
     /**
      * Rename the download - this means the name of the file being downloaded (for single
      * file torrents), or the name of the directory holding the files (in a multi-file torrent).
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerActivationListener.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerActivationListener.java
index cf7ee26..eaa78be 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerActivationListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerActivationListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerAvailability.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerAvailability.java
new file mode 100644
index 0000000..d742dbf
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerAvailability.java
@@ -0,0 +1,35 @@
+/*
+ * Created on Jun 16, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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 org.gudy.azureus2.core3.download;
+
+import java.util.List;
+
+import com.aelitis.azureus.core.tracker.TrackerPeerSource;
+
+public interface 
+DownloadManagerAvailability 
+{
+	public List<TrackerPeerSource>
+	getTrackerPeerSources();
+	
+	public void
+	destroy();
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerDiskListener.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerDiskListener.java
index 95d35c4..65e5469 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerDiskListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerDiskListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerException.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerException.java
index 99be91d..27aff32 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerFactory.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerFactory.java
index 237b043..83a0a78 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -30,6 +31,7 @@ import java.util.List;
 
 import org.gudy.azureus2.core3.download.impl.*;
 import org.gudy.azureus2.core3.global.*;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
 
 public class 
 DownloadManagerFactory 
@@ -69,4 +71,14 @@ DownloadManagerFactory
 	{
 		return( new DownloadManagerImpl( gm, torrent_hash, torrentFileName, torrent_save_dir, torrent_save_file, initialState, persistent, recovered, false, has_ever_been_started, file_priorities, null ));
 	}
+	
+	public static DownloadManagerAvailability
+	getAvailability(
+		TOTorrent				torrent,
+		List<List<String>>		updated_trackers,
+		String[]				enabled_peer_sources,
+		String[]				enabled_networks )
+	{
+		return( new DownloadManagerAvailabilityImpl( torrent, updated_trackers, enabled_peer_sources, enabled_networks ));
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerInitialisationAdapter.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerInitialisationAdapter.java
index 13e2fe6..a980d6d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerInitialisationAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerInitialisationAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Feb-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerListener.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerListener.java
index 772e2c0..7cbb313 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerPeerListener.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerPeerListener.java
index 9015f12..0a8a252 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerPeerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerPeerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerPieceListener.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerPieceListener.java
index 42c780b..007a4e3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerPieceListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerPieceListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerState.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerState.java
index 4675413..e103940 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerState.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerState.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -77,6 +74,7 @@ DownloadManagerState
 	public static final String AT_DL_FILE_ALERTS			= "df_alerts";
 	public static final String AT_SHARE_RATIO_PROGRESS		= "sr.prog";		// long: left word - timestamp in secs, right word sr in 1000ths
 	public static final String AT_FILES_EXPANDED			= "file.expand";	// boolean
+	public static final String AT_MERGED_DATA				= "mergedata";		// long
 
 
 	public static Object[][] ATTRIBUTE_DEFAULTS = {
@@ -111,6 +109,8 @@ DownloadManagerState
 	public static final String	PARAM_STATS_COUNTED						= "stats.counted";
 	public static final String	PARAM_DOWNLOAD_ADDED_TIME				= "stats.download.added.time";
 	public static final String	PARAM_DOWNLOAD_COMPLETED_TIME			= "stats.download.completed.time";
+	public static final String	PARAM_DOWNLOAD_FILE_COMPLETED_TIME		= "stats.download.file.completed.time";
+	public static final String	PARAM_DOWNLOAD_LAST_ACTIVE_TIME				= "stats.download.last.active.time";
 	public static final String	PARAM_MAX_UPLOAD_WHEN_BUSY				= "max.upload.when.busy";
 	public static final String  PARAM_DND_FLAGS							= "dndflags";
 	public static final String  PARAM_RANDOM_SEED						= "rand";
@@ -132,7 +132,9 @@ DownloadManagerState
 		{ PARAM_MAX_UPLOADS_WHEN_SEEDING_ENABLED, 	new Boolean( false ) },
 		{ PARAM_STATS_COUNTED, 						new Boolean( false ) },
 		{ PARAM_DOWNLOAD_ADDED_TIME,				new Long( 0 ) },
+		{ PARAM_DOWNLOAD_FILE_COMPLETED_TIME, 		new Long( 0 ) },
 		{ PARAM_DOWNLOAD_COMPLETED_TIME, 			new Long( 0 ) },
+		{ PARAM_DOWNLOAD_LAST_ACTIVE_TIME, new Long( 0 ) },
 		{ PARAM_MAX_UPLOAD_WHEN_BUSY,				new Long( 0 ) },
 		{ PARAM_DND_FLAGS, 							new Long( 0 ) },
 		{ PARAM_RANDOM_SEED, 						new Long( 0 ) },
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateAttributeListener.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateAttributeListener.java
index 2cfa87e..c0900ad 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateAttributeListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateAttributeListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.download;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateEvent.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateEvent.java
index f9ec909..feead7b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateEvent.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateFactory.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateFactory.java
index 9af1c3b..6ac713c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateListener.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateListener.java
index b964e34..ee2a3cd 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStateListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStats.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStats.java
index 6009a72..1d8ad5e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStats.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -40,7 +41,7 @@ DownloadManagerStats
 	public int
 	getCompleted();
 
-  /** Retrieve the level of download completion.
+  /** Retrieve the level of download completion, *including* DND files.
    * <P>
    * To understand the bLive parameter, you must know a bit about the
    * Torrent activation process:<BR>
@@ -69,9 +70,19 @@ DownloadManagerStats
 	getDownloadCompleted(boolean bLive);
 	
 	public void 
-	setDownloadCompleted(int completed);
-				
-  
+	setDownloadCompletedBytes(long completedBytes);
+	
+	/**
+	 * Get the number of bytes of the download that we currently have.
+	 * <P>
+	 * Includes bytes downloaded for files marked as DND/Skipped
+	 */
+	public long
+	getDownloadCompletedBytes();
+
+	public void
+	recalcDownloadCompleteBytes();
+
   /**
    * Get the total number of bytes ever downloaded.
    * @return total bytes downloaded
@@ -106,7 +117,7 @@ DownloadManagerStats
 	public void resetTotalBytesSentReceived( long sent, long received );
 
 	/**
-	 * Returns the bytes remaining.  Excludes DND files only if there is a DiskManager!
+	 * Returns the bytes remaining.  *Includes* DND files
 	 */
 	public long getRemaining();
 	
@@ -125,7 +136,10 @@ DownloadManagerStats
 	public int
 	getShareRatio();
 	
- 
+	public void
+	setShareRatio(
+		int		ratio );
+	
 	public long getDataReceiveRate();
   
 	public long getProtocolReceiveRate();
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerTPSListener.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerTPSListener.java
index 34de2cf..eadecd7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerTPSListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerTPSListener.java
@@ -1,29 +1,28 @@
-/*
- * Created on Dec 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 org.gudy.azureus2.core3.download;
-
-public interface 
-DownloadManagerTPSListener 
-{
-	public void
-	trackerPeerSourcesChanged();
-}
+/*
+ * Created on Dec 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.download;
+
+public interface 
+DownloadManagerTPSListener 
+{
+	public void
+	trackerPeerSourcesChanged();
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerTrackerListener.java b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerTrackerListener.java
index ea528d5..21439e4 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerTrackerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/DownloadManagerTrackerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/ForceRecheckListener.java b/azureus2/src/org/gudy/azureus2/core3/download/ForceRecheckListener.java
index 1e3e44f..9bee775 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/ForceRecheckListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/ForceRecheckListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.download;
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerAdapter.java b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerAdapter.java
index d598d88..6ec3f3c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerAdapter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerAvailabilityImpl.java b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerAvailabilityImpl.java
new file mode 100644
index 0000000..5a458b2
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerAvailabilityImpl.java
@@ -0,0 +1,717 @@
+/*
+ * Created on Jun 16, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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 org.gudy.azureus2.core3.download.impl;
+
+import java.net.URL;
+import java.util.*;
+
+import org.gudy.azureus2.core3.download.DownloadManagerAvailability;
+import org.gudy.azureus2.core3.peer.PEPeerSource;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerDataProvider;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerFactory;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.core3.util.TorrentUtils;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.ipc.IPCException;
+import org.gudy.azureus2.plugins.ipc.IPCInterface;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.networkmanager.NetworkManager;
+import com.aelitis.azureus.core.tracker.TrackerPeerSource;
+import com.aelitis.azureus.core.tracker.TrackerPeerSourceAdapter;
+import com.aelitis.azureus.plugins.extseed.ExternalSeedPlugin;
+import com.aelitis.azureus.plugins.tracker.dht.DHTTrackerPlugin;
+
+public class 
+DownloadManagerAvailabilityImpl
+	implements DownloadManagerAvailability
+{
+	private  List<TrackerPeerSource>	peer_sources = new ArrayList<TrackerPeerSource>();
+	
+	private TRTrackerAnnouncer	tracker_client;
+	
+	public
+	DownloadManagerAvailabilityImpl(
+		TOTorrent				to_torrent,
+		List<List<String>>		updated_trackers,
+		final String[]			_enabled_peer_sources,
+		final String[]			_enabled_networks )
+	{
+		if ( to_torrent == null ){
+			
+			return;
+		}
+	
+		final Set<String>	enabled_peer_sources = new HashSet<String>( Arrays.asList( _enabled_peer_sources ));
+		final Set<String>	enabled_networks	 = new HashSet<String>( Arrays.asList( _enabled_networks ));
+				
+		if ( enabled_peer_sources.contains( PEPeerSource.PS_BT_TRACKER)){
+			
+			TOTorrentAnnounceURLSet[] sets;
+			
+			if ( updated_trackers == null ){
+				
+				sets = to_torrent.getAnnounceURLGroup().getAnnounceURLSets();
+				
+			}else{
+				
+				sets = TorrentUtils.listToAnnounceSets( updated_trackers, to_torrent );
+				
+				try{
+					to_torrent = TorrentUtils.cloneTorrent( to_torrent );
+				
+					TorrentUtils.setMemoryOnly( to_torrent, true );
+					
+					to_torrent.getAnnounceURLGroup().setAnnounceURLSets( sets );
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+				
+			if ( sets.length == 0 ){
+				
+				sets = new TOTorrentAnnounceURLSet[]{ to_torrent.getAnnounceURLGroup().createAnnounceURLSet( new URL[]{ to_torrent.getAnnounceURL()})};
+			}
+				  
+			try{
+				tracker_client = 
+						TRTrackerAnnouncerFactory.create( 
+							to_torrent, 
+							new TRTrackerAnnouncerFactory.DataProvider()
+							{
+								public String[] 
+								getNetworks()
+								{
+									return( _enabled_networks );
+								}
+							});
+			
+				final long torrent_size = to_torrent.getSize();
+				
+				tracker_client.setAnnounceDataProvider(
+			    		new TRTrackerAnnouncerDataProvider()
+			    		{
+			    			public String
+			    			getName()
+			    			{
+			    				return( "Availability checker" );
+			    			}
+			    			
+			    			public long
+			    			getTotalSent()
+			    			{
+			    				return( 0 );
+			    			}
+			    			
+			    			public long
+			    			getTotalReceived()
+			    			{
+			    				return( 0 );
+			    			}
+			    			
+			    			public long
+			    			getRemaining()
+			    			{
+			    				return( torrent_size );
+			    			}
+			    			
+			    			public long
+			    			getFailedHashCheck()
+			    			{
+			    				return( 0 );
+			    			}
+	
+			    			public String
+			    			getExtensions()
+			    			{
+			    				return( null );
+			    			}
+			    			
+			    			public int
+			    			getMaxNewConnectionsAllowed()
+			    			{
+			    				return( 1 );	// num-want -> 1
+			    			}
+			    			
+			    			public int
+			    			getPendingConnectionCount()
+			    			{
+			    				return( 0 );
+			    			}
+			    			
+			    			public int
+			    			getConnectedConnectionCount()
+			    			{
+			    				return( 0 );
+			    			}
+			    			
+			    			public int
+			    			getUploadSpeedKBSec(
+			    				boolean	estimate )
+			    			{
+			    				return( 0 );
+			    			}
+			    			
+			    			public int
+			    			getCryptoLevel()
+			    			{
+			    				return( NetworkManager.CRYPTO_OVERRIDE_NONE );
+			    			}
+			    			
+			    			public boolean
+			    			isPeerSourceEnabled(
+			    				String		peer_source )
+			    			{
+			    				return( true );
+			    			}
+			    			
+			    			public void
+			    			setPeerSources(
+			    				String[]	allowed_sources )
+			    			{	
+			    			}
+			    		});
+				
+				tracker_client.update( true );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+			
+					// source per set
+				
+			for ( final TOTorrentAnnounceURLSet set: sets ){
+				
+				final URL[] urls = set.getAnnounceURLs();
+				
+				if ( urls.length == 0 || TorrentUtils.isDecentralised( urls[0] )){
+					
+					continue;
+				}
+				
+				peer_sources.add( 
+					new TrackerPeerSource()
+					{
+						private TrackerPeerSource _delegate;
+						
+	 					private TRTrackerAnnouncer		ta;
+	  					private long					ta_fixup;
+	
+	  					private long					last_scrape_fixup_time;
+	  					private Object[]				last_scrape;
+	  					
+						private TrackerPeerSource
+						fixup()
+						{
+							long	now = SystemTime.getMonotonousTime();
+							
+							if ( now - ta_fixup > 1000 ){
+								
+								TRTrackerAnnouncer current_ta = tracker_client;
+								
+								if ( current_ta == ta ){
+									
+									if ( current_ta != null && _delegate == null ){
+										
+										_delegate = current_ta.getTrackerPeerSource( set );
+									}
+								}else{
+									
+									if ( current_ta == null ){
+										
+										_delegate = null;
+										
+									}else{
+										
+										_delegate = current_ta.getTrackerPeerSource( set );
+									}
+									
+									ta = current_ta;
+								}
+								
+								ta_fixup	= now;
+							}
+							
+							return( _delegate );
+						}
+						
+						protected Object[]
+						getScrape()
+						{
+							long now = SystemTime.getMonotonousTime();
+							
+							if ( now - last_scrape_fixup_time > 30*1000 || last_scrape == null ){
+	
+								
+								
+								last_scrape = new Object[]{ -1, -1, -1, -1, -1, "" }; 
+								
+								last_scrape_fixup_time = now;
+							}
+							
+							return( last_scrape );
+						}
+						
+						public int
+						getType()
+						{
+							return( TrackerPeerSource.TP_TRACKER );
+						}
+						
+						public String
+						getName()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return( urls[0].toExternalForm());
+							}
+							
+							return( delegate.getName());
+						}
+						
+						public int 
+						getStatus()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return( ST_STOPPED );
+							}
+							
+							return( delegate.getStatus());
+						}
+						
+						public String 
+						getStatusString()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return( (String)getScrape()[5] );
+							}
+							
+							return( delegate.getStatusString());
+						}
+						
+						public int
+						getSeedCount()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return((Integer)getScrape()[0] );
+							}
+							
+							int seeds = delegate.getSeedCount();
+							
+							if ( seeds < 0 ){
+								
+								seeds = (Integer)getScrape()[0];
+							}
+							
+							return( seeds );
+						}
+						
+						public int
+						getLeecherCount()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return( (Integer)getScrape()[1] );
+							}
+							
+							int leechers = delegate.getLeecherCount();
+							
+							if ( leechers < 0 ){
+								
+								leechers = (Integer)getScrape()[1];
+							}
+							
+							return( leechers );						
+						}
+	
+						public int
+						getCompletedCount()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return( (Integer)getScrape()[4] );
+							}
+							
+							int comp = delegate.getCompletedCount();
+							
+							if ( comp < 0 ){
+								
+								comp = (Integer)getScrape()[4];
+							}
+							
+							return( comp );						
+						}
+						
+						public int
+						getPeers()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return( -1 );
+							}
+							
+								// we only asked for 1 peer so if we have a scrape value then we'll leave this blank
+								// to avoid confusion
+							
+							if ( delegate.getSeedCount() > 0 || delegate.getLeecherCount() > 0 ){
+								
+								return( -1 );
+							}
+							
+							return( delegate.getPeers());
+						}
+	
+						public int
+						getInterval()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								Object[] si = getScrape();
+								
+								int	last 	= (Integer)si[2];
+								int next	= (Integer)si[3];
+								
+								if ( last > 0 && next < Integer.MAX_VALUE && last < next ){
+									
+									return( next - last );
+								}
+								
+								return( -1 );
+							}
+							
+							return( delegate.getInterval());							
+						}
+						
+						public int
+						getMinInterval()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return( -1 );
+							}
+							
+							return( delegate.getMinInterval());							
+						}
+						
+						public boolean
+						isUpdating()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return( false );
+							}
+							
+							return( delegate.isUpdating());							
+						}
+						
+						public int 
+						getLastUpdate() 
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return( (Integer)getScrape()[2] );
+							}
+							
+							return( delegate.getLastUpdate());
+						}
+						
+						public int
+						getSecondsToUpdate()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+							
+								return( -1 );
+							}
+							
+							return( delegate.getSecondsToUpdate());
+						}
+						
+						public boolean
+						canManuallyUpdate()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate == null ){
+								
+								return( false );
+							}
+							
+							return( delegate.canManuallyUpdate());
+						}
+						
+						public void
+						manualUpdate()
+						{
+							TrackerPeerSource delegate = fixup();
+							
+							if ( delegate != null ){
+								
+								delegate.manualUpdate();
+							}
+						}
+						
+						public boolean
+						canDelete()
+						{
+							return( false );
+						}
+						
+						public void
+						delete()
+						{
+						}
+					});
+			}
+		}
+		
+		Torrent	torrent = PluginCoreUtils.wrap( to_torrent );
+
+			// http seeds
+			
+		try{
+			ExternalSeedPlugin esp = DownloadManagerController.getExternalSeedPlugin();
+			
+			if ( esp != null ){
+				  	
+				TrackerPeerSource ext_ps = esp.getTrackerPeerSource( torrent );
+				
+				if ( ext_ps.getSeedCount() > 0 ){
+				
+					peer_sources.add( ext_ps );
+				}
+			}
+		}catch( Throwable e ){
+		}
+		
+		if ( 	enabled_peer_sources.contains( PEPeerSource.PS_DHT) &&
+				enabled_networks.contains( AENetworkClassifier.AT_PUBLIC )){
+
+				// dht
+			
+			if ( !torrent.isPrivate()){
+				
+				try{
+					
+					PluginInterface dht_pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass(DHTTrackerPlugin.class);
+		
+				    if ( dht_pi != null ){
+				    	
+				    	peer_sources.addAll( Arrays.asList(((DHTTrackerPlugin)dht_pi.getPlugin()).getTrackerPeerSources( torrent )));
+				    }
+				}catch( Throwable e ){
+				}
+			}
+		}
+		
+		if ( 	enabled_peer_sources.contains( PEPeerSource.PS_DHT)){
+				// enabled_networks.contains( AENetworkClassifier.AT_I2P )){
+
+				// always do this availability check for the moment
+			
+			if ( !torrent.isPrivate()){
+			
+				try{
+					PluginInterface i2p_pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( "azneti2phelper", true );
+					
+					if ( i2p_pi != null ){
+						
+						IPCInterface ipc = i2p_pi.getIPC();
+						
+						Map<String,Object>	options = new HashMap<String, Object>();
+						
+						options.put( "peer_networks", _enabled_networks );
+						
+						final int[] lookup_status = new int[]{ TrackerPeerSource.ST_INITIALISING, -1, -1, -1 };
+						
+						IPCInterface callback =
+							new IPCInterface()
+							{
+								public Object 
+								invoke(
+									String methodName, 
+									Object[] params) 
+										
+									throws IPCException
+								{
+									synchronized( lookup_status ){
+										
+										lookup_status[0] = (Integer)params[0];
+										
+										if ( params.length >= 4 ){
+											
+											lookup_status[1] = (Integer)params[1];
+											lookup_status[2] = (Integer)params[2];
+											lookup_status[3] = (Integer)params[3];
+										}
+									}
+									
+									return( null );
+								}
+	
+								public boolean 
+								canInvoke( 
+									String methodName, 
+									Object[] params )
+								{
+									return( true );
+								}
+							};
+							
+						TrackerPeerSource	ps = new
+							TrackerPeerSourceAdapter() 
+							{
+								public int
+								getType()
+								{
+									return( TP_DHT );
+								}
+								
+								public String
+								getName()
+								{
+									return( "I2P DHT" );
+								}
+								
+								public int
+								getStatus()
+								{
+									synchronized( lookup_status ){
+										
+										return( lookup_status[0] );
+									}
+								}
+								
+								public int
+								getSeedCount()
+								{
+									synchronized( lookup_status ){
+									
+										int	seeds 		= lookup_status[1];
+										int peers 		= lookup_status[3];
+										
+										if ( seeds == 0 && peers > 0 ){
+											
+											return( -1 );
+										}
+										
+										return( seeds );
+									}
+								}
+								
+								public int
+								getLeecherCount()
+								{
+									synchronized( lookup_status ){
+										
+										int leechers 	= lookup_status[2];
+										int peers 		= lookup_status[3];
+										
+										if ( leechers == 0 && peers > 0 ){
+											
+											return( -1 );
+										}
+										
+										return( leechers );
+									}
+								}
+								
+								public int
+								getPeers()
+								{
+									synchronized( lookup_status ){
+										
+										int peers = lookup_status[3];
+										
+										return( peers==0?-1:peers );
+									}
+								}
+							};
+							
+							
+						ipc.invoke(
+							"lookupTorrent",
+							new Object[]{
+								"Availability lookup for '" + torrent.getName() + "'",
+								torrent.getHash(),
+								options,
+								callback 
+							});
+						
+						peer_sources.add( ps );
+					}
+				}catch( Throwable e ){
+				}
+			}
+		}
+	}
+	
+	public List<TrackerPeerSource>
+	getTrackerPeerSources()
+	{
+		return( peer_sources );
+	}
+	
+	public void
+	destroy()
+	{
+		if ( tracker_client != null ){
+			
+			tracker_client.destroy();
+		}
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerController.java b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerController.java
index 657b6f8..310d1f1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerController.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerController.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -34,6 +31,7 @@ import org.gudy.azureus2.core3.disk.*;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerDiskListener;
 import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.core3.download.DownloadManagerStateAttributeListener;
 import org.gudy.azureus2.core3.download.ForceRecheckListener;
 import org.gudy.azureus2.core3.global.GlobalManager;
 import org.gudy.azureus2.core3.global.GlobalManagerStats;
@@ -189,6 +187,7 @@ DownloadManagerController
 	private boolean         		cached_values_set;
 	
 	private Set<String>				cached_networks;
+	private Object					cached_networks_lock = new Object();
 	
 	private PeerManagerRegistration	peer_manager_registration;
 	private PEPeerManager 			peer_manager;
@@ -695,7 +694,7 @@ DownloadManagerController
 
 			  					fileFacadeSet.makeSureFilesFacadeFilled(true);
 
-			  					stats.setDownloadCompleted(stats.getDownloadCompleted(true));
+			  					stats.recalcDownloadCompleteBytes();
 			  						
 			  					download_manager.setAssumedComplete(isDownloadComplete(false));
 			  				}
@@ -1001,6 +1000,9 @@ DownloadManagerController
 					  
 					  stats.saveSessionTotals();
 
+						DownloadManagerState dmState = download_manager.getDownloadState();
+						dmState.setLongParameter( DownloadManagerState.PARAM_DOWNLOAD_LAST_ACTIVE_TIME, SystemTime.getCurrentTime());
+
 					  SimpleTimer.removeTickReceiver( this );
 
 					  DownloadManagerRateController.removePeerManager( peer_manager );
@@ -1045,7 +1047,7 @@ DownloadManagerController
 						}
 						
 						stats.setCompleted(stats.getCompleted());
-						stats.setDownloadCompleted(stats.getDownloadCompleted(true));
+  					stats.recalcDownloadCompleteBytes();
 			      
 					  		// we don't want to update the torrent if we're seeding
 					  
@@ -1362,7 +1364,54 @@ DownloadManagerController
 	private void
 	cacheNetworks()
 	{
-		 cached_networks = new HashSet<String>( Arrays.asList( download_manager.getDownloadState().getNetworks()));
+		synchronized( cached_networks_lock ){
+			
+			if ( cached_networks != null ){
+				
+				return;
+			}
+		
+			DownloadManagerState state = download_manager.getDownloadState();
+			
+			cached_networks = new HashSet<String>( Arrays.asList( state.getNetworks()));
+			
+			state.addListener( 
+				new DownloadManagerStateAttributeListener()
+				{
+					public void 
+					attributeEventOccurred(
+						DownloadManager 	download,
+						String 				attribute, 
+						int 				event_type ) 
+					{
+						DownloadManagerState state = download_manager.getDownloadState();
+
+						synchronized( cached_networks_lock ){
+
+							cached_networks = new HashSet<String>( Arrays.asList( state.getNetworks()));
+						}
+						
+						PEPeerManager	pm = peer_manager;
+						
+						if ( pm != null ){
+							
+							List<PEPeer> peers = pm.getPeers();
+							
+							for ( PEPeer peer: peers ){
+								
+								String net = AENetworkClassifier.categoriseAddress( peer.getIp());
+								
+								if ( !isNetworkEnabled( net )){
+									
+									pm.removePeer( peer, "Network not enabled" );
+								}
+							}
+						}
+					}
+				},
+				DownloadManagerState.AT_NETWORKS, 
+				DownloadManagerStateAttributeListener.WRITTEN );
+		}
 	}
 	
 	public boolean
@@ -1380,6 +1429,20 @@ DownloadManagerController
 		}
 	}
 	
+	public String[] 
+	getEnabledNetworks() 
+	{
+		Set<String>	cache = cached_networks;
+		
+		if ( cache == null ){
+			
+			return( download_manager.getDownloadState().getNetworks());
+			
+		}else{
+			
+			return( cache.toArray( new String[ cache.size()]));
+		}
+	}
 		// secrets for inbound connections, support all
 	
 	public byte[][]
@@ -1617,7 +1680,7 @@ DownloadManagerController
 				activation_bloom = bloom = BloomFilterFactory.createAddRemove4Bit( BLOOM_SIZE );
 			}
 			
-			byte[]	address_bytes = address.getAddress().getAddress();
+			byte[]	address_bytes = AddressUtils.getAddressBytes(address);
 					
 			int	hit_count = bloom.add( address_bytes );
 			
@@ -1665,7 +1728,7 @@ DownloadManagerController
 		
 		if ( bloom != null ){
 		
-			byte[]	address_bytes = address.getAddress().getAddress();
+			byte[]	address_bytes = AddressUtils.getAddressBytes( address );
 
 			int	count = bloom.count( address_bytes);
 			
@@ -1923,7 +1986,7 @@ DownloadManagerController
 		// So, if we have no DND files, use calculation from stats, which
 		// remembers things like whether the file was once complete
 		if (!cached_has_dnd_files) {
-			return stats.getDownloadCompleted(false) == 1000;
+			return stats.getRemaining() == 0;
 		}
 
 		// We have DND files.  If we have an existing diskmanager, then it
@@ -3006,7 +3069,7 @@ DownloadManagerController
 
 				force_start = wasForceStarted;
 
-				stats.setDownloadCompleted(stats.getDownloadCompleted(true));
+				stats.recalcDownloadCompleteBytes();
 
 				if (newDMState == DiskManager.READY) {
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerImpl.java b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerImpl.java
index 5e04f33..1294d25 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -60,6 +61,7 @@ import org.gudy.azureus2.core3.torrent.TOTorrentListener;
 import org.gudy.azureus2.core3.tracker.client.*;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.download.Download;
 import org.gudy.azureus2.plugins.download.DownloadAnnounceResult;
 import org.gudy.azureus2.plugins.download.DownloadScrapeResult;
 import org.gudy.azureus2.plugins.download.savelocation.SaveLocationChange;
@@ -512,7 +514,7 @@ DownloadManagerImpl
 	
 	private long						scrape_random_seed	= SystemTime.getCurrentTime();
 
-	private Map		data;
+	private volatile Map<Object,Object>		data;
   
 	private boolean data_already_allocated = false;
   
@@ -545,6 +547,7 @@ DownloadManagerImpl
     
 	// Only call this with STATE_QUEUED, STATE_WAITING, or STATE_STOPPED unless you know what you are doing
 	
+    private volatile boolean	removing;
 	private volatile boolean	destroyed;
 	
 	public 
@@ -728,12 +731,22 @@ DownloadManagerImpl
 					 		}else if (attribute_name.equals(DownloadManagerState.AT_PARAMETERS)){
 					 			
 					 			readParameters();
-						 }
-					 }
-				 };
+					 			
+					 		}else if (attribute_name.equals(DownloadManagerState.AT_NETWORKS)){
+					 		
+					 			TRTrackerAnnouncer tc = tracker_client;
+					 			
+					 			if ( tc != null ){
+					 			
+					 				tc.resetTrackerUrl( false );
+					 			}
+							}
+						}
+					};
 
 				 download_manager_state.addListener(attr_listener, DownloadManagerState.AT_FILE_LINKS2, DownloadManagerStateAttributeListener.WRITTEN);
 				 download_manager_state.addListener(attr_listener, DownloadManagerState.AT_PARAMETERS, DownloadManagerStateAttributeListener.WRITTEN);
+				 download_manager_state.addListener(attr_listener, DownloadManagerState.AT_NETWORKS, DownloadManagerStateAttributeListener.WRITTEN);
 						
 				 torrent	= download_manager_state.getTorrent();
 				 
@@ -1010,7 +1023,7 @@ DownloadManagerImpl
 					 
 					  // download_manager_state.clearTrackerResponseCache();
 						
-					  stats.setDownloadCompleted(1000);
+					  stats.setDownloadCompletedBytes(getSize());
 				  
 					  setAssumedComplete(true);
 				  
@@ -1435,9 +1448,19 @@ DownloadManagerImpl
 					continue;
 				}
 				
+				try{
+					to = to.getCanonicalFile();
+				}catch( Throwable e ){
+				}
+				
 				int		file_index 	= entry.getIndex();
 				File	from 		= entry.getFromFile();
 
+				try{
+					from = from.getCanonicalFile();
+				}catch( Throwable e ){
+				}
+				
 				String  from_s  = from.getAbsolutePath();
 				String  to_s    = to.getAbsolutePath();
 		
@@ -1484,6 +1507,7 @@ DownloadManagerImpl
 			}
 			
 			//System.out.println( "   adding " + old_path + " -> null" );
+			
 			from_indexes.add( 0 );
 			from_links.add( new File(old_path));
 			to_links.add( null );
@@ -1492,7 +1516,28 @@ DownloadManagerImpl
 				// alternate location (only a single file after all this is simplest implementation). Unfortunately links can
 				// actually still be set (e.g. to add an 'incomplete' suffix to a file) so we still need to support link-rewriting
 				// properly
-			String to_loc_to_use = FileUtil.translateMoveFilePath(old_path, new_path, to_loc);
+			
+				// both old_path and new_path are the full name of the download file, that is they aren't
+				// directories they are files - grab the parent directories as the link translation needs to
+				// be relative to this
+			
+			String old_path_parent;
+			int	pos = old_path.lastIndexOf( File.separatorChar );
+			if ( pos != -1 ){
+				old_path_parent = old_path.substring( 0, pos ); 
+			}else{
+				old_path_parent = old_path;
+			}
+			
+			String new_path_parent;
+			pos = new_path.lastIndexOf( File.separatorChar );
+			if ( pos != -1 ){
+				new_path_parent = new_path.substring( 0, pos ); 
+			}else{
+				new_path_parent = new_path;
+			}
+			
+			String to_loc_to_use = FileUtil.translateMoveFilePath(old_path_parent, new_path_parent, to_loc);
 			
 			if ( to_loc_to_use == null ){
 				
@@ -1867,6 +1912,11 @@ DownloadManagerImpl
 		boolean		remove_data,
 		boolean		for_removal )
 	{
+		if ( for_removal ){
+			
+			removing = true;
+		}
+		
 		try {
 			boolean closing = state_after_stopping == DownloadManager.STATE_CLOSED;
 			int curState = getState();
@@ -3490,31 +3540,82 @@ DownloadManagerImpl
 	    
 	public void setData (String key, Object value){ setUserData( key, value ); }
 	
-  /** To retreive arbitrary objects against a download. */
-  public Object getUserData (Object key) {
-  	if (data == null) return null;
-    return data.get(key);
-  }
+		/** To retreive arbitrary objects against a download. */
+  
+	public Object 
+	getUserData(
+		Object key ) 
+	{
+		Map<Object,Object> data_ref = data;
+		
+		if ( data_ref == null ){
+			
+			return null;
+		}
+		
+		return( data_ref.get(key));
+	}
 
-  /** To store arbitrary objects against a download. */
-  public void setUserData (Object key, Object value) {
-  	try{
-  		peer_listeners_mon.enter();
-  	
-	  	if (data == null) {
-	  	  data = new LightHashMap();
-	  	}
-	    if (value == null) {
-	      if (data.containsKey(key))
-	        data.remove(key);
-	    } else {
-	      data.put(key, value);
-	    }
-  	}finally{
-  		
-  		peer_listeners_mon.exit();
-  	}
-  }
+		/** To store arbitrary objects against a download. */
+	
+	public void 
+	setUserData(
+		Object 		key, 
+		Object 		value) 
+	{
+		try{
+				// copy-on-write
+			
+			peer_listeners_mon.enter();
+
+			Map<Object,Object> data_ref = data;
+			
+			if ( data_ref == null && value == null ){
+				
+				return;
+			}
+
+			if ( value == null ){
+
+					// removal, data_ref not null here
+				
+				if ( data_ref.containsKey(key)){
+
+					if ( data_ref.size() == 1 ){
+						
+						data_ref = null;
+						
+					}else{
+						
+						data_ref = new LightHashMap<Object,Object>( data_ref );
+						
+						data_ref.remove( key );
+					}
+				}else{
+					
+					return;
+				}
+			}else{
+
+				if ( data_ref == null ){
+					
+					data_ref = new LightHashMap<Object,Object>();
+					
+				}else{
+				
+					data_ref = new LightHashMap<Object,Object>( data_ref );
+				}
+				
+				data_ref.put( key, value );
+			}
+			
+			data = data_ref;
+			
+		}finally{
+
+			peer_listeners_mon.exit();
+		}
+	}
   
   
   public boolean 
@@ -3832,6 +3933,115 @@ DownloadManagerImpl
 	  }
   }
   
+  public void
+  copyDataFiles(
+  	File	parent_dir )
+  
+  	throws DownloadManagerException
+  {
+	  if ( parent_dir.exists()){
+		  
+		  if ( !parent_dir.isDirectory()){
+			
+			  throw( new DownloadManagerException( "'" + parent_dir + "' is not a directory" ));
+		  }
+	  }else{
+		  
+		  if ( !parent_dir.mkdirs()){
+			  
+			  throw( new DownloadManagerException( "failed to create '" + parent_dir + "'" ));
+		  }
+	  }
+	  
+	  DiskManagerFileInfo[] files = controller.getDiskManagerFileInfoSet().getFiles();
+	  
+	  if ( torrent.isSimpleTorrent()){
+		  
+		  File file_from = files[0].getFile( true );
+		  
+		  try{
+			  File file_to = new File( parent_dir, file_from.getName());
+			  
+			  if ( file_to.exists()){
+				  
+				  if ( file_to.length() != file_from.length()){
+					  
+					  throw( new Exception( "target file '" + file_to + " already exists" ));
+				  }
+			  }else{
+			  
+				  FileUtil.copyFileWithException( file_from, file_to );
+			  }
+		  }catch( Throwable e ){
+			  
+			  throw( new DownloadManagerException( "copy of '" + file_from + "' failed", e ));
+		  }
+	  }else{
+	  
+		  try{
+			  File sl_file = getSaveLocation();
+			  
+			  String save_location = sl_file.getCanonicalPath();
+			  
+			  if ( !save_location.endsWith( File.separator )){
+				  
+				  save_location += File.separator;
+			  }
+			  
+			  parent_dir = new File( parent_dir, sl_file.getName());
+			  
+			  if ( !parent_dir.isDirectory()){
+				  
+				  parent_dir.mkdirs();
+			  }
+			  
+			  for ( DiskManagerFileInfo file: files ){
+				  
+				  if ( !file.isSkipped() && file.getDownloaded() == file.getLength()){
+					  
+					  File file_from = file.getFile( true );
+					  
+					  try{
+						  String file_path = file_from.getCanonicalPath();
+						  
+						  if ( file_path.startsWith( save_location )){
+							  
+							  File file_to = new File( parent_dir, file_path.substring( save_location.length()));
+							  
+							  if ( file_to.exists()){
+								  
+								  if ( file_to.length() != file_from.length()){
+									  
+									  throw( new Exception( "target file '" + file_to + " already exists" ));
+								  }
+							  }else{
+							  
+								  File parent = file_to.getParentFile();
+								  
+								  if ( !parent.exists()){
+									  
+									  if ( !parent.mkdirs()){
+										  
+										  throw( new Exception( "Failed to make directory '" + parent + "'" ));
+									  }
+								  }
+								  
+								  FileUtil.copyFileWithException( file_from, file_to );
+							  }
+						  }
+					  }catch( Throwable e ){
+						  
+						  throw( new DownloadManagerException( "copy of '" + file_from + "' failed", e ));
+					  }
+				  }
+			  }
+		  }catch( Throwable e ){
+			  
+			  throw( new DownloadManagerException( "copy failed", e ));
+		  }
+	  }
+  }
+  
   public void moveTorrentFile(File new_parent_dir) throws DownloadManagerException {
 	  this.moveTorrentFile(new_parent_dir, null);
   }
@@ -4079,6 +4289,13 @@ DownloadManagerImpl
 					
   				setUserData( TPS_Key, new Object[]{ tps, tol });
 
+  				Download plugin_download = PluginCoreUtils.wrap( this );
+  				
+  				if ( isDestroyed() || plugin_download == null ){
+  					
+  					return( tps );
+  				}
+  				
   					// tracker peer sources
   				
   				final TOTorrent t = getTorrent();
@@ -4113,8 +4330,8 @@ DownloadManagerImpl
 			 					private TRTrackerAnnouncer		ta;
 			  					private long					ta_fixup;
 
-			  					private long		last_scrape_fixup_time;
-			  					private int[]		last_scrape;
+			  					private long					last_scrape_fixup_time;
+			  					private Object[]				last_scrape;
 			  					
 								private TrackerPeerSource
 								fixup()
@@ -4151,7 +4368,7 @@ DownloadManagerImpl
 									return( _delegate );
 								}
 								
-								protected int[]
+								protected Object[]
 								getScrape()
 								{
 									long now = SystemTime.getMonotonousTime();
@@ -4166,6 +4383,10 @@ DownloadManagerImpl
 										int max_time 	= 0;
 										int	min_scrape	= Integer.MAX_VALUE;
 										
+										String status_str = null;
+										
+										boolean	found_usable = false;
+										
 										for ( URL u: urls ){
 										
 											TRTrackerScraperResponse resp = scraper.peekScrape(torrent, u );
@@ -4174,6 +4395,8 @@ DownloadManagerImpl
 												
 												if ( !resp.isDHTBackup()){
 													
+													found_usable = true;
+													
 													int peers 	= resp.getPeers();
 													int seeds 	= resp.getSeeds();
 													int comp	= resp.getCompleted();
@@ -4195,6 +4418,8 @@ DownloadManagerImpl
 													
 													if ( resp.getStatus() != TRTrackerScraperResponse.ST_INITIALIZING ){
 													
+														status_str = resp.getStatusString();
+														
 														int	time	= resp.getScrapeTime();
 
 														if ( time > max_time ){
@@ -4218,7 +4443,12 @@ DownloadManagerImpl
 											}
 										}
 										
-										last_scrape = new int[]{ max_seeds, max_peers, max_time, min_scrape, max_comp }; 
+											// don't overwrite an old status if this time around we haven't found anything usable
+										
+										if ( found_usable || last_scrape == null ){
+										
+											last_scrape = new Object[]{ max_seeds, max_peers, max_time, min_scrape, max_comp, status_str };
+										}
 										
 										last_scrape_fixup_time = now;
 									}
@@ -4265,7 +4495,7 @@ DownloadManagerImpl
 									
 									if ( delegate == null ){
 									
-										return( null );
+										return( (String)getScrape()[5] );
 									}
 									
 									return( delegate.getStatusString());
@@ -4278,14 +4508,14 @@ DownloadManagerImpl
 									
 									if ( delegate == null ){
 									
-										return( getScrape()[0] );
+										return((Integer)getScrape()[0] );
 									}
 									
 									int seeds = delegate.getSeedCount();
 									
 									if ( seeds < 0 ){
 										
-										seeds = getScrape()[0];
+										seeds = (Integer)getScrape()[0];
 									}
 									
 									return( seeds );
@@ -4298,14 +4528,14 @@ DownloadManagerImpl
 									
 									if ( delegate == null ){
 									
-										return( getScrape()[1] );
+										return( (Integer)getScrape()[1] );
 									}
 									
 									int leechers = delegate.getLeecherCount();
 									
 									if ( leechers < 0 ){
 										
-										leechers = getScrape()[1];
+										leechers = (Integer)getScrape()[1];
 									}
 									
 									return( leechers );						
@@ -4318,14 +4548,14 @@ DownloadManagerImpl
 									
 									if ( delegate == null ){
 									
-										return( getScrape()[4] );
+										return( (Integer)getScrape()[4] );
 									}
 									
 									int comp = delegate.getCompletedCount();
 									
 									if ( comp < 0 ){
 										
-										comp = getScrape()[4];
+										comp = (Integer)getScrape()[4];
 									}
 									
 									return( comp );						
@@ -4351,10 +4581,10 @@ DownloadManagerImpl
 									
 									if ( delegate == null ){
 									
-										int[] si = getScrape();
+										Object[] si = getScrape();
 										
-										int	last 	= si[2];
-										int next	= si[3];
+										int	last 	= (Integer)si[2];
+										int next	= (Integer)si[3];
 										
 										if ( last > 0 && next < Integer.MAX_VALUE && last < next ){
 											
@@ -4400,7 +4630,7 @@ DownloadManagerImpl
 									
 									if ( delegate == null ){
 									
-										return( getScrape()[2] );
+										return( (Integer)getScrape()[2] );
 									}
 									
 									return( delegate.getLastUpdate());
@@ -4460,7 +4690,7 @@ DownloadManagerImpl
 										rem.add( u.toExternalForm());
 									}
 									
-									lists = TorrentUtils.removeAnnounceURLs2( lists, rem );
+									lists = TorrentUtils.removeAnnounceURLs2( lists, rem, false );
 									
 									TorrentUtils.listToAnnounceGroups( lists, t );
 								}
@@ -4574,7 +4804,7 @@ DownloadManagerImpl
 	  				
 	  				if ( esp != null ){
 	  					  					
-						tps.add( esp.getTrackerPeerSource( PluginCoreUtils.wrap( this ) ));
+						tps.add( esp.getTrackerPeerSource( plugin_download ));
 	 				}
 	  			}catch( Throwable e ){
 	  			}
@@ -4587,7 +4817,7 @@ DownloadManagerImpl
 	
 	  			    if ( dht_pi != null ){
 	  			    	
-	  			    	tps.add(((DHTTrackerPlugin)dht_pi.getPlugin()).getTrackerPeerSource( PluginCoreUtils.wrap( this )));
+	  			    	tps.add(((DHTTrackerPlugin)dht_pi.getPlugin()).getTrackerPeerSource( plugin_download ));
 	  			    }
 				}catch( Throwable e ){
 	  			}
@@ -4600,7 +4830,7 @@ DownloadManagerImpl
 	
 					if ( lt_pi != null ){
 						
-	  			    	tps.add(((LocalTrackerPlugin)lt_pi.getPlugin()).getTrackerPeerSource( PluginCoreUtils.wrap( this )));
+	  			    	tps.add(((LocalTrackerPlugin)lt_pi.getPlugin()).getTrackerPeerSource( plugin_download ));
 					
 					}
 					
@@ -4612,7 +4842,7 @@ DownloadManagerImpl
 				
 				try{
 				
-					tps.add(((DownloadImpl)PluginCoreUtils.wrap( this )).getTrackerPeerSource());
+					tps.add(((DownloadImpl)plugin_download).getTrackerPeerSource());
 					
 				}catch( Throwable e ){
 					
@@ -4928,12 +5158,14 @@ DownloadManagerImpl
 	public String toString() {
 		String hash = "<unknown>";
 
-		try {
-			hash = ByteFormatter.encodeString(torrent.getHash());
-
-		} catch (Throwable e) {
+		if ( torrent != null ){
+			try {
+				hash = ByteFormatter.encodeString(torrent.getHash());
+	
+			} catch (Throwable e) {
+			}
 		}
-
+		
 		String status = DisplayFormatters.formatDownloadStatus(this);
 		if (status.length() > 10) {
 			status = status.substring(0, 10);
@@ -5106,7 +5338,7 @@ DownloadManagerImpl
 	public boolean 
 	isDestroyed() 
 	{
-		return( destroyed );
+		return( destroyed || removing );
 	}
 	
 	public int[] getStorageType(DiskManagerFileInfo[] info) {
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerMoveHandler.java b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerMoveHandler.java
index b78c89a..eae1586 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerMoveHandler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerMoveHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.download.impl;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerMoveHandlerUtils.java b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerMoveHandlerUtils.java
index 277007f..5f76bf4 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerMoveHandlerUtils.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerMoveHandlerUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.download.impl;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerRateController.java b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerRateController.java
index 1232b5f..d5db93e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerRateController.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerRateController.java
@@ -2,20 +2,19 @@
  * Created on May 12, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerStateImpl.java b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerStateImpl.java
index 0861e15..5956850 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerStateImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerStateImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -542,16 +539,14 @@ DownloadManagerStateImpl
 		
 		if ( source_state_dir.exists()){
 			
-			File	target_state_dir = new File( ACTIVE_DIR, hash_str );
-
 			try{		
-				FileUtil.copyFileOrDirectory( source_state_dir, target_state_dir );
+				FileUtil.copyFileOrDirectory( source_state_dir, ACTIVE_DIR );
 				
 			}catch( Throwable e ){
 				
 				target_state_file.delete();
 				
-				throw( new DownloadManagerException( "Failed to copy state dir: " + source_dir + " -> " + target_state_dir, e ));
+				throw( new DownloadManagerException( "Failed to copy state dir: " + source_dir + " -> " + ACTIVE_DIR, e ));
 			}
 		}		
 	}
@@ -877,10 +872,8 @@ DownloadManagerStateImpl
 			File	existing_state_dir = new File( ACTIVE_DIR, hash_str );
 			
 			if ( existing_state_dir.exists()){
-				
-				File	target_state_dir = new File( target_dir, hash_str );
-
-				FileUtil.copyFileOrDirectory( existing_state_dir, target_state_dir );
+							
+				FileUtil.copyFileOrDirectory( existing_state_dir, target_dir );
 			}
 			
 			return( true );
diff --git a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerStatsImpl.java b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerStatsImpl.java
index d3524cf..18407cd 100644
--- a/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/download/impl/DownloadManagerStatsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -30,7 +31,6 @@ import org.gudy.azureus2.core3.config.ParameterListener;
 import org.gudy.azureus2.core3.download.*;
 import org.gudy.azureus2.core3.peer.*;
 import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.IndentWriter;
 import org.gudy.azureus2.core3.util.SystemTime;
 import org.gudy.azureus2.core3.disk.*;
@@ -60,7 +60,6 @@ DownloadManagerStatsImpl
 		//Completed (used for auto-starting purposes)
 		
 	private int completed;
-	private int downloadCompleted;
 	
 		// saved downloaded and uploaded
 	private long saved_data_bytes_downloaded;
@@ -86,6 +85,8 @@ DownloadManagerStatsImpl
 	
 	private long saved_skipped_file_set_size;
 	private long saved_skipped_but_downloaded;
+	
+	private long saved_completed_download_bytes = -1;
 
 	private int max_upload_rate_bps = 0;  //0 for unlimited
 	private int max_download_rate_bps = 0;  //0 for unlimited
@@ -260,15 +261,14 @@ DownloadManagerStatsImpl
 	        state == DownloadManager.STATE_INITIALIZING)
 	      return completed;
 	    else
-	      return downloadCompleted;
+	      return getDownloadCompleted(true);
 	  }
 	  if (dm.getState() == DiskManager.ALLOCATING || 
 	      dm.getState() == DiskManager.CHECKING || 
 	      dm.getState() == DiskManager.INITIALIZING)
       return dm.getPercentDone();
 	  else {
-      long total = dm.getTotalLength();
-      return total == 0 ? 0 : (int) ((1000 * (total - dm.getRemaining())) / total);
+      return getDownloadCompleted(true);
 	  }
 	}
 
@@ -280,49 +280,65 @@ DownloadManagerStatsImpl
 	getDownloadCompleted(
 		boolean bLive ) 
 	{
-		DiskManager	dm = download_manager.getDiskManager();
-		
-			// no disk manager -> not running -> use stored value
-		
-		if ( dm == null ){
-			
-		   return downloadCompleted;
-		}
-		
-	    int state = dm.getState();
-
-	    boolean	transient_state = 
-	    		state == DiskManager.INITIALIZING ||
-	            state == DiskManager.ALLOCATING   ||
-	            state == DiskManager.CHECKING;
-	    
-	    long total = dm.getTotalLength();
-	    
-	    int computed_completion = (total == 0) ? 0 : (int) ((1000 * (total - dm.getRemaining())) / total);
-
-	    	// use non-transient values to update the record of download completion
-	    
-	    if ( !transient_state ){
-	    	
-	    	downloadCompleted = computed_completion;
-	    }
-	    
-	    if ( bLive ){
-	    
-	    		// return the transient completion level
-	    	
+		if (bLive) {
+  		DiskManager	dm = download_manager.getDiskManager();
+  		
+  			// no disk manager -> not running -> use stored value
+  		
+  		if ( dm != null ){
+  		
+  	    int state = dm.getState();
+  
+  	    boolean	transient_state = 
+  	    		state == DiskManager.INITIALIZING ||
+  	            state == DiskManager.ALLOCATING   ||
+  	            state == DiskManager.CHECKING;
+  	    
+  	    long total = dm.getTotalLength();
+  	    
+  	    long completed_download_bytes = total - dm.getRemaining();
+  	    int computed_completion = (total == 0) ? 0 : (int) ((1000 * completed_download_bytes) / total);
+  
+ 	    	// use non-transient values to update the record of download completion
+  	    if ( !transient_state ){
+  	    	
+  	    	saved_completed_download_bytes = completed_download_bytes;
+  	    }
+  	    
+    		// return the transient completion level
 	    	return computed_completion;
+  		}
+		}
 	    	
-	    }else{
-	    	
-	    		// return the non-transient one
-	    	
-	    	return( downloadCompleted );
-	    }
+    long total = download_manager.getSize();
+		int computed_completion = total == 0 ? 0 : (int) (1000 * getDownloadCompletedBytes() / total);
+		return computed_completion;
 	}
   
-	public void setDownloadCompleted(int _completed) {
-		downloadCompleted = _completed;
+	public void setDownloadCompletedBytes(long completedBytes) {
+		saved_completed_download_bytes = completedBytes;
+	}
+	
+	public void recalcDownloadCompleteBytes() {
+		DiskManager	dm = getDiskManagerIfNotTransient();
+		if (dm != null) {
+	    long total = dm.getTotalLength();
+    	saved_completed_download_bytes = total - dm.getRemaining();
+		}
+		if (saved_completed_download_bytes < 0) {
+			// recalc
+			DiskManagerFileInfo[] files = download_manager.getDiskManagerFileInfoSet().getFiles();
+			long total_size = 0;
+			for (DiskManagerFileInfo file : files) {
+				total_size += file.getDownloaded();
+			}
+			saved_completed_download_bytes = total_size;
+		}
+	}
+	
+	public long getDownloadCompletedBytes() {
+		recalcDownloadCompleteBytes();
+		return saved_completed_download_bytes;
 	}
 
 	public String getElapsedTime() {
@@ -660,19 +676,33 @@ DownloadManagerStatsImpl
 	public long 
 	getRemaining()
 	{
-		DiskManager disk_manager = download_manager.getDiskManager();
-		
-	    if ( disk_manager == null ){
-	    	
-	    	return download_manager.getSize() - 
-		             ((long)getDownloadCompleted(false) * download_manager.getSize() / 1000L);
-		
-	    }else{
-		     
-	    	return disk_manager.getRemainingExcludingDND();
+		DiskManager disk_manager = getDiskManagerIfNotTransient();
+
+		if (disk_manager == null) {
+
+			long size = download_manager.getSize();
+
+			return size - getDownloadCompletedBytes();
+
+		} else {
+
+			return disk_manager.getRemaining();
 		}
 	}
 	
+	private DiskManager getDiskManagerIfNotTransient() {
+		DiskManager dm = download_manager.getDiskManager();
+		if (dm == null) {
+			return null;
+		}
+
+		int state = dm.getState();
+
+		boolean transient_state = state == DiskManager.INITIALIZING
+				|| state == DiskManager.ALLOCATING || state == DiskManager.CHECKING;
+		return transient_state ? null : dm;
+	}
+
 	public long 
 	getDiscarded()
 	{
@@ -759,6 +789,58 @@ DownloadManagerStatsImpl
 		return (int) ((1000 * uploaded) / downloaded);
 	}
 	
+	public void
+	setShareRatio(
+		int		ratio )
+	{
+		if ( ratio < 0 ){
+			ratio = 0;
+		}
+		
+		if ( ratio > 1000000 ){
+			ratio = 1000000;
+		}
+		
+		DiskManagerFileInfo[] files = download_manager.getDiskManagerFileInfoSet().getFiles();
+		
+		long total_size = 0;
+		
+		for ( DiskManagerFileInfo file: files ){
+			
+			if ( !file.isSkipped()){
+				
+				total_size += file.getLength();
+			}
+		}
+		
+		if ( total_size == 0 ){
+			
+				// can't do much if they have no files selected (which would be stupid anyway)
+			
+			return;
+		}
+		
+		saved_hashfails				= 0;
+		saved_discarded				= 0;
+		saved_data_bytes_downloaded	= 0;
+		saved_data_bytes_uploaded	= 0;
+		
+		long downloaded	= getTotalGoodDataBytesReceived();
+		long uploaded	= getTotalDataBytesSent();
+
+			// manipulate by updating downloaded to be one full copy and then uploaded as required
+		
+		long	target_downloaded 	= total_size;
+		long	target_uploaded 	= ( ratio * total_size ) / 1000;
+		
+		saved_data_bytes_downloaded	= target_downloaded - downloaded;
+		saved_data_bytes_uploaded	= target_uploaded - uploaded;
+		
+		if ( download_manager.getPeerManager() == null ){
+
+			saveSessionTotals();
+		}
+	}
   
 	public long 
 	getSecondsDownloading() 
@@ -1074,6 +1156,7 @@ DownloadManagerStatsImpl
 			return 0;
 		}
 		float pct = (sizeExcludingDND - getRemainingExcludingDND()) / (float) sizeExcludingDND;
+
 		return (int) (1000 * pct);
 	}
 
@@ -1093,7 +1176,7 @@ DownloadManagerStatsImpl
 				",discard=" + getDiscarded() + ",hash_fails=" + getHashFailCount() + "/" + getHashFailBytes() +
 				",comp=" + getCompleted() 
 				+ "[live:" + getDownloadCompleted(true) + "/" + getDownloadCompleted( false) 
-				+ "],dl_comp=" + downloadCompleted
+				+ "]"
 				+ ",remaining=" + getRemaining());
 	
 			writer.println( "down_lim=" + getDownloadRateLimitBytesPerSecond() +
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManager.java b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManager.java
index 7757ea6..805dbd1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerAdapter.java b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerAdapter.java
index f055e83..28d2dbc 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerDownloadRemovalVetoException.java b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerDownloadRemovalVetoException.java
index 48bb06f..ec5ddce 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerDownloadRemovalVetoException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerDownloadRemovalVetoException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerDownloadWillBeRemovedListener.java b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerDownloadWillBeRemovedListener.java
index a9abc6d..843a0af 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerDownloadWillBeRemovedListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerDownloadWillBeRemovedListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerEvent.java b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerEvent.java
index bff7a60..6262895 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerEvent.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerEvent.java
@@ -2,20 +2,19 @@
  * Created on Jul 6, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerEventListener.java b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerEventListener.java
index 9121ff9..6d3df8e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerEventListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerEventListener.java
@@ -2,20 +2,19 @@
  * Created on Jul 6, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerFactory.java b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerFactory.java
index beef24b..ecc44b6 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerListener.java b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerListener.java
index 203530f..133bdf9 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerStats.java b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerStats.java
index fb4db25..286dbf5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerStats.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/GlobalManagerStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -48,6 +49,9 @@ GlobalManagerStats
 	  
 	public int getDataAndProtocolSendRate();
 	
+	public long	getSmoothedSendRate();
+	public long	getSmoothedReceiveRate();
+	
 	public int getDataSendRateAtClose();
   
 	public long getTotalDataBytesReceived();
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/GlobalMangerProgressListener.java b/azureus2/src/org/gudy/azureus2/core3/global/GlobalMangerProgressListener.java
index 3ab156f..c207975 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/GlobalMangerProgressListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/GlobalMangerProgressListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerFileMerger.java b/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerFileMerger.java
new file mode 100644
index 0000000..e50ef22
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerFileMerger.java
@@ -0,0 +1,1362 @@
+/*
+ * Created on Feb 2, 2015
+ * Created by Paul Gardner
+ * 
+ * Copyright 2015 Azureus Software, 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 org.gudy.azureus2.core3.global.impl;
+
+import java.util.*;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
+import org.gudy.azureus2.core3.disk.DiskManager;
+import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.core3.disk.DiskManagerFileInfoListener;
+import org.gudy.azureus2.core3.disk.DiskManagerPiece;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerPeerListener;
+import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.core3.global.GlobalManagerAdapter;
+import org.gudy.azureus2.core3.logging.LogAlert;
+import org.gudy.azureus2.core3.logging.Logger;
+import org.gudy.azureus2.core3.peer.PEPeer;
+import org.gudy.azureus2.core3.peer.PEPeerManager;
+import org.gudy.azureus2.core3.peer.PEPeerManagerListenerAdapter;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
+import org.gudy.azureus2.core3.util.Base32;
+import org.gudy.azureus2.core3.util.DelayedEvent;
+import org.gudy.azureus2.core3.util.DirectByteBuffer;
+import org.gudy.azureus2.core3.util.DirectByteBufferPool;
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.core3.util.HashWrapper;
+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.core3.util.TimerEventPeriodic;
+import org.gudy.azureus2.plugins.PluginAdapter;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+
+
+public class 
+GlobalManagerFileMerger 
+{
+	private static final boolean	TRACE = false;
+	
+	
+	private static final int MIN_PIECES				= 5;
+	private static final int HASH_FAILS_BEFORE_QUIT	= 3;
+	
+	private static final int TIMER_PERIOD		= 5*1000;
+	private static final int SYNC_TIMER_PERIOD	= 60*1000;
+	private static final int SYNC_TIMER_TICKS	= SYNC_TIMER_PERIOD/TIMER_PERIOD;
+	
+	private static final Object merged_data_lock = new Object();
+	
+	private GlobalManagerImpl		gm;
+	
+	private boolean	initialised;
+	private boolean	enabled;
+	
+	private Map<HashWrapper,DownloadManager>		dm_map = new HashMap<HashWrapper, DownloadManager>();
+	
+	private List<SameSizeFiles>				sames = new ArrayList<SameSizeFiles>();
+	
+	private AsyncDispatcher		read_write_dispatcher = new AsyncDispatcher( "GMFM" );
+	
+	private TimerEventPeriodic	timer_event;
+	
+	protected
+	GlobalManagerFileMerger(
+		GlobalManagerImpl			_gm )
+	{
+		gm		= _gm;
+		
+		PluginInitializer.getDefaultInterface().addListener(
+			new PluginAdapter()
+			{
+				public void
+				initializationComplete()
+				{
+					new DelayedEvent( 
+						"GMFM:delay",
+						30*1000,
+						new AERunnable() {
+							
+							@Override
+							public void 
+							runSupport() 
+							{
+								initialise();
+							}
+						});
+				}
+			});
+	}
+	
+	private void
+	initialise()
+	{
+		COConfigurationManager.addAndFireParameterListener(
+			"Merge Same Size Files",
+			new ParameterListener(){
+				
+				public void 
+				parameterChanged(
+					String name ) 
+				{
+					enabled = COConfigurationManager.getBooleanParameter( name );
+					
+					if ( initialised ){
+						
+						syncFileSets();
+					}
+				}
+			});
+		
+		gm.addListener(
+			new GlobalManagerAdapter()
+			{				
+				public void 
+				downloadManagerAdded(
+					DownloadManager dm ) 
+				{
+					syncFileSets();
+				}
+				
+				public void 
+				downloadManagerRemoved(
+					DownloadManager dm ) 
+				{		
+					syncFileSets();
+				}
+			},
+			false );
+		
+		syncFileSets();
+		
+		initialised = true;
+	}
+	
+	private void
+	syncFileSets()
+	{
+		List<DownloadManager> dms = gm.getDownloadManagers();
+				
+		synchronized( dm_map ){
+
+			boolean	changed = false;
+
+			Set<HashWrapper>	existing_dm_hashes = new HashSet<HashWrapper>( dm_map.keySet());
+			
+			if ( enabled ){
+				
+				for ( DownloadManager dm: dms ){
+					
+					if ( !dm.isPersistent()){
+						
+						continue;
+					}
+					
+					DownloadManagerState state = dm.getDownloadState();
+					
+					if ( 	state.getFlag( DownloadManagerState.FLAG_LOW_NOISE ) ||
+							state.getFlag( DownloadManagerState.FLAG_METADATA_DOWNLOAD )){
+						
+						continue;
+					}
+					
+					if ( !dm.isDownloadComplete( false )){
+					
+						TOTorrent torrent = dm.getTorrent();
+						
+						if ( torrent != null ){
+											
+							try{
+								HashWrapper hw = torrent.getHashWrapper();
+								
+								if ( dm_map.containsKey( hw )){
+									
+									existing_dm_hashes.remove( hw );
+									
+								}else{
+									
+									dm_map.put( hw, dm );
+									
+									changed = true;
+								}
+							}catch( Throwable e ){
+							}
+						}
+					}
+				}
+			}
+			
+			if ( existing_dm_hashes.size() > 0 ){
+				
+				changed = true;
+				
+				for ( HashWrapper hw: existing_dm_hashes ){
+					
+					dm_map.remove( hw );
+				}
+			}
+		
+			if ( changed ){
+							
+				List<Set<DiskManagerFileInfo>>	interesting = new ArrayList<Set<DiskManagerFileInfo>>();
+				
+				Map<Long,Set<DiskManagerFileInfo>>		size_map = new HashMap<Long, Set<DiskManagerFileInfo>>();
+				
+				for ( DownloadManager dm: dm_map.values()){
+					
+					TOTorrent torrent = dm.getTorrent();
+					
+					if ( torrent == null ){
+						
+						continue;
+					}
+										
+					DiskManagerFileInfo[] files = dm.getDiskManagerFileInfoSet().getFiles();
+					
+					for ( DiskManagerFileInfo file: files ){
+						
+							// filter out small files
+							
+						if ( file.getNbPieces() < MIN_PIECES ){
+							
+							continue;
+						}
+						
+						long len = file.getLength();
+						
+						
+						Set<DiskManagerFileInfo> set = size_map.get( len );
+						
+						if ( set == null ){
+							
+							set = new HashSet<DiskManagerFileInfo>();
+							
+							size_map.put( len, set );
+						}
+						
+						boolean same_dm = false;
+						
+						for ( DiskManagerFileInfo existing: set ){
+							
+							if ( existing.getDownloadManager() == dm ){
+								
+								same_dm = true;
+								
+								break;
+							}
+						}
+						
+						if ( !same_dm ){
+							
+							set.add( file );
+							
+							if ( set.size() == 2 ){
+								
+								interesting.add( set );
+							}
+						}
+					}
+				}
+				
+				List<SameSizeFiles>	sames_copy = new ArrayList<SameSizeFiles>( sames );
+
+				for ( Set<DiskManagerFileInfo> set: interesting ){
+					
+					boolean	found = false;
+										
+					Iterator<SameSizeFiles>	sames_it = sames_copy.iterator();
+					
+					while( sames_it.hasNext()){
+						
+						SameSizeFiles same = sames_it.next();
+						
+						if ( same.sameAs( set )){
+							
+							found = true;
+							
+							sames_it.remove();
+							
+							break;
+						}
+					}
+					
+					if ( !found ){
+						
+						sames.add( new SameSizeFiles( set ));
+					}
+				}
+				
+				for ( SameSizeFiles dead: sames_copy ){
+					
+					dead.destroy();
+					
+					sames.remove( dead );
+				}
+			
+				if ( sames.size() > 0 ){
+					
+					if ( timer_event == null ){
+						
+						timer_event = 
+							SimpleTimer.addPeriodicEvent(
+								"GMFM:sync",
+								TIMER_PERIOD,
+								new TimerEventPerformer()
+								{
+									private int	tick_count = 0;
+									
+									public void 
+									perform(
+										TimerEvent event) 
+									{
+										tick_count++;
+										
+										synchronized( dm_map ){
+											
+											for ( SameSizeFiles s: sames ){
+												
+												s.sync( tick_count );
+											}
+										}
+									}
+								});
+					}
+				}else{
+					
+					if ( timer_event != null ){
+						
+						timer_event.cancel();
+						
+						timer_event = null;
+					}
+				}
+			}
+		}
+	}
+	
+	private class
+	SameSizeFiles
+	{
+		final private Set<DiskManagerFileInfo>		files;
+		final private Set<SameSizeFileWrapper>		file_wrappers;
+		
+		private boolean	completion_logged;
+		
+		private volatile boolean	dl_has_restarted;
+		
+		private volatile boolean	destroyed;
+		
+		private
+		SameSizeFiles(
+			Set<DiskManagerFileInfo>		_files )
+		{
+			files 	= _files;
+			
+			file_wrappers = new HashSet<SameSizeFileWrapper>();
+			
+			for ( final DiskManagerFileInfo file: files ){
+				
+				final SameSizeFileWrapper file_wrapper = new SameSizeFileWrapper( file );
+				
+				DownloadManager dm = file_wrapper.getDownloadManager();
+				
+				file_wrappers.add( file_wrapper );
+					
+				DownloadManagerPeerListenerEx dmpl =
+					new DownloadManagerPeerListenerEx(){
+						
+						AsyncDispatcher dispatcher = new AsyncDispatcher( "GMFM:serial" );
+						
+						private Object		lock = this;
+								
+						private DiskManager	current_disk_manager;
+						
+						private boolean	pm_removed;
+						
+						final DiskManagerFileInfoListener file_listener =
+							new DiskManagerFileInfoListener() {
+							
+								public void 
+								dataWritten(
+									long offset, 
+									long length ) 
+								{
+									if ( destroyed ){
+										
+										file.removeListener( this );
+										
+										return;
+									}
+									
+									file_wrapper.dataWritten( offset, length );
+								}
+								
+								public void 
+								dataChecked(
+									long offset, 
+									long length ) 
+								{
+									if ( destroyed ){
+										
+										file.removeListener( this );
+										
+										return;
+									}
+								}
+							};
+							
+						public void
+						sync()
+						{
+							if ( destroyed ){
+								
+								return;
+							}
+						
+							dispatcher.dispatch(
+								new AERunnable()
+								{
+									public void
+									runSupport()
+									{
+										if ( destroyed ){
+											
+											return;
+										}
+										
+										synchronized( lock ){
+											
+											if ( current_disk_manager != null ){
+												
+												file.removeListener( file_listener );
+												
+											}else{
+												
+												return;
+											}
+										}
+							
+										file.addListener( file_listener );
+									}
+								});
+						}
+						
+						public void 
+						peerManagerAdded(
+							final PEPeerManager manager ) 
+						{
+							if ( destroyed ){
+								
+								return;
+							}
+							
+							dispatcher.dispatch(
+								new AERunnable()
+								{
+									public void
+									runSupport()
+									{
+										if ( destroyed ){
+											
+											return;
+										}
+										
+										if ( pm_removed ){
+											
+											dl_has_restarted = true;
+										}
+										
+										manager.addListener(
+											new PEPeerManagerListenerAdapter(){
+												
+												public void 
+												pieceCorrupted( 
+													PEPeerManager 	manager, 
+													int 			piece_number )
+												{
+													if ( destroyed ){
+														
+														manager.removeListener( this );
+														
+														return;
+													}
+													
+													file_wrapper.pieceCorrupt( piece_number );
+												}
+											});
+										
+										synchronized( lock ){
+											
+											if ( current_disk_manager != null ){
+												
+												file.removeListener( file_listener );
+											}
+											
+											current_disk_manager = manager.getDiskManager();
+											
+											if ( current_disk_manager == null ){
+												
+												return;
+											}
+										}
+										
+										file.addListener( file_listener );
+									}
+								});
+						}
+
+						public void 
+						peerManagerRemoved(
+							PEPeerManager manager) 
+						{
+							dispatcher.dispatch(
+								new AERunnable()
+								{
+									public void
+									runSupport()
+									{
+										synchronized( lock ){
+											
+											pm_removed = true;
+											
+											if ( current_disk_manager != null ){
+												
+												file.removeListener( file_listener );
+												
+												current_disk_manager = null;
+											}
+										}
+									}
+								});
+						}	
+						
+						public void 
+						peerAdded(
+							PEPeer peer ) 
+						{
+						}
+						
+						public void 
+						peerRemoved(
+							PEPeer peer ) 
+						{
+						}
+						
+						public void 
+						peerManagerWillBeAdded(
+							PEPeerManager manager ) 
+						{
+						}
+					};
+										
+				dm.setUserData( this, dmpl );
+				
+				dm.addPeerListener( dmpl );
+			}
+			
+			dl_has_restarted = true;
+			
+			if ( TRACE )System.out.println( "created " + getString());
+		}
+			
+		private void
+		sync(
+			int		tick_count )
+		{
+			if ( read_write_dispatcher.getQueueSize() > 0 ){
+				
+					// stuff is going on, ignore sync until things are idle
+				
+				return;
+			}
+			
+			if ( dl_has_restarted ){
+				
+				dl_has_restarted = false;
+				
+			}else{
+				
+				if ( tick_count % SYNC_TIMER_TICKS != 0 ){
+					
+					return;
+				}
+			}
+			
+			List<DiskManagerFileInfo>	active = new ArrayList<DiskManagerFileInfo>();
+			
+			int		num_incomplete	= 0;
+			
+			for ( DiskManagerFileInfo file: files ){
+				
+				if ( file.isSkipped()){
+					
+					continue;
+				}
+				
+				int dl_state = file.getDownloadManager().getState();
+				
+				if ( dl_state == DownloadManager.STATE_DOWNLOADING || dl_state ==  DownloadManager.STATE_SEEDING ){
+					
+					active.add( file );
+					
+					if ( file.getLength() != file.getDownloaded()){
+				
+						num_incomplete++;
+					}
+				}
+			}
+			
+			if ( num_incomplete > 0 &&  active.size() > 1 ){
+				
+				for ( DiskManagerFileInfo file: active ){
+					
+					DownloadManager	dm = file.getDownloadManager();
+					
+					DownloadManagerPeerListenerEx dmpl = (DownloadManagerPeerListenerEx)dm.getUserData( this );
+					
+					if ( dmpl != null ){
+						
+						dmpl.sync();
+					}
+				}
+			}
+			
+			if ( !completion_logged ){
+				
+				boolean	all_done 		= true;
+				long	total_merged	= 0;
+				
+				for ( SameSizeFileWrapper ssf: file_wrappers ){
+					
+					if ( ssf.isSkipped()){
+						
+						continue;
+					}
+					
+					total_merged += ssf.getMergedByteCount();
+
+					if ( !ssf.isComplete()){
+					
+						all_done = false;
+					}
+				}
+				
+				if ( all_done ){
+					
+					completion_logged	= true;
+					
+					if ( total_merged > 0 ){
+						
+						String msg = "Successfully merged files:\n";
+						
+						for ( SameSizeFileWrapper file: file_wrappers ){
+							
+							long	merged = file.getMergedByteCount();
+							
+							if ( merged > 0 ){
+								
+								DownloadManager dm = file.getDownloadManager();
+								
+								msg += dm.getDisplayName();
+								
+								if ( !dm.getTorrent().isSimpleTorrent()){
+																	
+									msg += " - " + file.getFile().getTorrentFile().getRelativePath();
+								}
+								
+								msg +=  ": " + DisplayFormatters.formatByteCountToKiBEtc( merged ) + "\n";
+							}
+						}
+							
+						msg += "\nTotal: " + DisplayFormatters.formatByteCountToKiBEtc( total_merged );
+						
+						Logger.log(					
+								new LogAlert(
+									true,
+									LogAlert.AT_INFORMATION,
+									msg ));	
+					}
+				}
+			}
+		}
+			
+		private boolean
+		sameAs(
+			Set<DiskManagerFileInfo>		_others )
+		{
+			return( files.equals( _others ));
+		}
+
+		private void
+		abandon(
+			SameSizeFileWrapper		failed )
+		{
+			destroy();
+			
+			String msg = "Abandoned attempt to merge files:\n";
+			
+			for ( SameSizeFileWrapper file: file_wrappers ){
+				
+				msg += file.getDownloadManager().getDisplayName() + " - " + file.getFile().getTorrentFile().getRelativePath() + "\n";
+			}
+			msg += "\nToo many hash fails in " + failed.getDownloadManager().getDisplayName();
+			
+			Logger.log(					
+					new LogAlert(
+						true,
+						LogAlert.AT_INFORMATION,
+						msg ));	
+		}
+		
+		private void
+		destroy()
+		{
+			destroyed = true;
+			
+			for ( DiskManagerFileInfo file: files ){
+				
+				DownloadManager	dm = file.getDownloadManager();
+				
+				DownloadManagerPeerListenerEx dmpl = (DownloadManagerPeerListenerEx)dm.getUserData( this );
+				
+				if ( dmpl != null ){
+				
+					dm.removePeerListener( dmpl );
+				}
+			}
+			
+			if ( TRACE )System.out.println( "destroyed " + getString());
+		}
+		
+		private String
+		getString()
+		{
+			String str = "";
+			
+			long	size = -1;
+			
+			for ( DiskManagerFileInfo file: files ){
+				
+				size = file.getLength();
+				
+				str += (str.length()==0?"":", ") + file.getTorrentFile().getRelativePath();
+			}
+			
+			str += " - length " + size;
+			
+			return( str );
+		}
+	
+		
+		private class
+		SameSizeFileWrapper
+		{
+			private final DiskManagerFileInfo		file;
+			
+			private final DownloadManager			download_manager;
+			
+			private final long						file_byte_offset;
+			
+			private final String					id;
+			
+			private long							merged_byte_counnt;
+			
+			private final boolean[]					modified_pieces;
+			
+			private int	pieces_completed;
+			private int	pieces_corrupted;
+			
+			private 
+			SameSizeFileWrapper(
+				DiskManagerFileInfo		_file )
+			{
+				file	= _file;
+				
+				modified_pieces	= new boolean[ file.getNbPieces()];
+				
+				download_manager = file.getDownloadManager();
+				
+				int	file_index = file.getIndex();
+					
+				long fbo = 0;
+				
+				if ( file_index > 0){
+										
+					DiskManagerFileInfo[] f = download_manager.getDiskManagerFileInfoSet().getFiles();
+					
+					for ( int i=0;i<file_index;i++ ){
+						
+						fbo += f[i].getLength();
+					}
+				}
+				
+				String _id;
+				
+				try{
+					_id = Base32.encode( download_manager.getTorrent().getHash()) + "/" + file.getIndex();
+					
+				}catch( Throwable e ){
+					
+					_id = download_manager.getDisplayName() + "/" + file.getIndex();
+				}
+				
+				id	= _id;
+				
+				file_byte_offset = fbo;
+			}
+			
+			private DiskManagerFileInfo
+			getFile()
+			{
+				return( file );
+			}
+			
+			private boolean
+			isSkipped()
+			{
+				return( file.isSkipped());
+			}
+			
+			private boolean
+			isComplete()
+			{
+				return( file.getLength() == file.getDownloaded());
+			}
+			
+			private DownloadManager
+			getDownloadManager()
+			{
+				return( download_manager );
+			}
+			
+			private DiskManager
+			getDiskManager()
+			{
+				return( file.getDiskManager());
+			}
+			
+			private PEPeerManager
+			getPeerManager()
+			{
+				return( download_manager.getPeerManager());
+			}
+			
+			private long
+			getFileByteOffset()
+			{
+				return( file_byte_offset );
+			}
+			
+			private String
+			getID()
+			{
+				return( id );
+			}
+			
+			private void 
+			dataWritten(
+				long 						offset, 
+				long 						length ) 
+			{
+				if ( TRACE )System.out.println( "written: " + offset + "/" + length );
+				
+				final DiskManager		disk_manager	= getDiskManager();
+				final PEPeerManager	peer_manager 		= getPeerManager();
+				
+				if ( disk_manager == null || peer_manager == null ){
+					
+					return;
+				}
+				
+				final DiskManagerPiece[]	pieces = disk_manager.getPieces();
+							
+				final long piece_length 	= disk_manager.getPieceLength();
+				
+				long	written_start 				= file_byte_offset + offset;
+				long	written_end_inclusive		= written_start + length - 1;
+				
+				int	first_piece_num = (int)( written_start/piece_length );
+				int	last_piece_num 	= (int)( written_end_inclusive/piece_length );
+				
+				DiskManagerPiece	first_piece 	= pieces[first_piece_num];
+				DiskManagerPiece	last_piece 		= pieces[last_piece_num];
+				
+				int	first_block = (int)( written_start % piece_length )/DiskManager.BLOCK_SIZE;
+				int	last_block 	= (int)( written_end_inclusive % piece_length )/DiskManager.BLOCK_SIZE;
+				
+				if ( first_block > 0 ){
+					boolean[] written = first_piece.getWritten();
+					if ( first_piece.isDone() || ( written != null && written[first_block-1])){
+						first_block--;
+					}
+				}else{
+					if ( first_piece_num > 0 ){
+						DiskManagerPiece	prev_piece 	= pieces[first_piece_num-1];
+						boolean[] written = prev_piece.getWritten();
+						int	nb = prev_piece.getNbBlocks();
+						
+						if ( prev_piece.isDone() || ( written != null && written[nb-1])){
+							first_piece_num--;
+							first_block	= nb-1;
+						}
+					}
+				}
+				
+				if ( last_block < last_piece.getNbBlocks()-1 ){
+					boolean[] written = last_piece.getWritten();
+					if ( last_piece.isDone() || ( written != null && written[last_block+1])){
+						last_block++;
+					}
+				}else{
+					if ( last_piece_num < pieces.length-1 ){
+						DiskManagerPiece	next_piece 	= pieces[last_piece_num+1];
+						boolean[] written = next_piece.getWritten();
+	
+						if ( next_piece.isDone() || ( written != null && written[0])){
+							last_piece_num++;
+							last_block = 0;
+						}
+					}
+				}
+				
+					// we've widened the effective write by one block each way where possible to handle block
+					// misalignment across downloads
+				
+				final long	avail_start 			= ( first_piece_num * piece_length ) + ( first_block * DiskManager.BLOCK_SIZE );
+				final long	avail_end_inclusive 	= ( last_piece_num  * piece_length ) + ( last_block * DiskManager.BLOCK_SIZE ) + pieces[last_piece_num].getBlockSize( last_block ) - 1;
+					
+				if ( TRACE )System.out.println( first_piece_num + "/" + first_block + " - " + last_piece_num + "/" + last_block  + ": " + avail_start + "-" + avail_end_inclusive );
+				
+				for ( final SameSizeFileWrapper other_file: file_wrappers ){
+					
+					if ( other_file == this || other_file.isSkipped() || other_file.isComplete()){
+						
+						continue;
+					}
+					
+					final DiskManager 		other_disk_manager = other_file.getDiskManager();
+					final PEPeerManager 	other_peer_manager = other_file.getPeerManager();
+					
+					if ( other_disk_manager == null || other_peer_manager == null ){
+						
+						continue;
+					}
+					
+					read_write_dispatcher.dispatch(
+						new AERunnable()
+						{
+							public void
+							runSupport()
+							{		
+								if ( other_file.isComplete()){
+									
+									return;
+								}
+								
+								DiskManagerPiece[]	other_pieces = other_disk_manager.getPieces();
+								
+								long other_piece_length 	= other_disk_manager.getPieceLength();
+				
+								long	skew = file_byte_offset - other_file.getFileByteOffset();
+								
+								if ( skew % DiskManager.BLOCK_SIZE == 0 ){
+									
+										// special case of direct block->block mapping
+									
+									for ( long block_start = avail_start; block_start <= avail_end_inclusive; block_start += DiskManager.BLOCK_SIZE ){
+				
+										if ( destroyed ){
+											
+											break;
+										}
+										
+										int	origin_piece_num 	= (int)( block_start/piece_length );
+										int	origin_block_num	= (int)(( block_start % piece_length ) / DiskManager.BLOCK_SIZE );
+										
+										long target_offset = block_start - skew;
+										
+										int	target_piece_num 	= (int)( target_offset/other_piece_length );
+										int	target_block_num	= (int)(( target_offset % other_piece_length ) / DiskManager.BLOCK_SIZE );
+				
+										DiskManagerPiece	origin_piece = pieces[origin_piece_num];
+										DiskManagerPiece	target_piece = other_pieces[target_piece_num];
+										
+										boolean[]	written = target_piece.getWritten();
+										
+										if ( target_piece.isDone() || (written != null && written[target_block_num])){
+											
+											// already written
+											
+										}else{
+											
+											if ( origin_piece.getBlockSize( origin_block_num ) == target_piece.getBlockSize( target_block_num )){
+												
+												DirectByteBuffer buffer = disk_manager.readBlock( origin_piece_num, origin_block_num*DiskManager.BLOCK_SIZE, origin_piece.getBlockSize( origin_block_num ));
+				
+												if ( buffer == null ){
+													
+													continue;
+												}
+												
+
+												written = target_piece.getWritten();
+												
+												if ( target_piece.isDone() || (written != null && written[target_block_num])){
+													
+													continue;
+												}
+											
+												try{
+												
+													boolean completed_piece = target_piece.getNbWritten() == target_piece.getNbBlocks() - 1;
+													
+													if ( TRACE )System.out.println( "Write from " + origin_piece_num + "/" + origin_block_num + " to " + target_piece_num + "/" + target_block_num );
+
+													if ( other_file.writeBlock( target_piece_num, target_block_num, buffer )){
+									
+														buffer = null;
+														
+														if ( completed_piece ){
+															
+															pieces_completed++;
+															
+															if ( pieces_completed < 5 ){
+																
+																try{
+																	Thread.sleep(500);
+																	
+																}catch( Throwable e ){
+																	
+																}
+															}
+														}													
+													}else{
+														
+														break;
+													}
+												}finally{
+													
+													if ( buffer != null ){
+														
+														buffer.returnToPool();
+													}
+												}
+											}
+										}
+									}
+								}else{
+										// need two blocks from source to consider writing to target
+										// unless this is the last block and short enough 
+									
+									DirectByteBuffer	prev_block 		= null;
+									int					prev_block_pn	= 0;
+									int					prev_block_bn	= 0;
+									
+									try{										
+										for ( long block_start=avail_start; block_start <= avail_end_inclusive; block_start += DiskManager.BLOCK_SIZE ){
+											
+											if ( destroyed ){
+												
+												break;
+											}
+											
+											long	origin_start 			= block_start;
+											
+											long target_offset = origin_start - skew;
+											
+											target_offset =  (( target_offset + DiskManager.BLOCK_SIZE - 1 ) / DiskManager.BLOCK_SIZE ) * DiskManager.BLOCK_SIZE;
+											
+											long origin_offset = target_offset + skew;
+														
+											int	target_piece_num 	= (int)( target_offset/other_piece_length );
+											int	target_block_num	= (int)(( target_offset % other_piece_length ) / DiskManager.BLOCK_SIZE );
+					
+											DiskManagerPiece	target_piece = other_pieces[target_piece_num];
+					
+											boolean[]	target_written = target_piece.getWritten();
+															
+											if ( target_piece.isDone() || (target_written != null && ( target_block_num >= target_written.length || target_written[target_block_num]))){
+												
+												// already written or no such block
+												
+											}else{
+											
+												int target_block_size = target_piece.getBlockSize( target_block_num );
+												
+												if ( 	origin_offset >= file_byte_offset &&
+														origin_offset + target_block_size <= avail_end_inclusive + 1){
+												
+													int	origin1_piece_number 	= (int)( origin_start/piece_length );
+													int	origin1_block_num		= (int)(( origin_start % piece_length ) / DiskManager.BLOCK_SIZE );
+					
+													DiskManagerPiece	origin1_piece = pieces[origin1_piece_number];
+													
+													if ( !origin1_piece.isWritten( origin1_block_num )){
+														
+														continue;	// might have failed
+													}
+													
+													DirectByteBuffer read_block1	= null;
+													DirectByteBuffer read_block2	= null;
+													DirectByteBuffer write_block	= null;
+													
+													try{
+														if ( 	prev_block != null &&
+																prev_block_pn == origin1_piece_number &&
+																prev_block_bn == origin1_block_num ){
+															
+															read_block1 = prev_block;
+															prev_block	= null;
+																	
+														}else{
+														
+															read_block1 = disk_manager.readBlock( origin1_piece_number , origin1_block_num*DiskManager.BLOCK_SIZE, origin1_piece.getBlockSize( origin1_block_num ));
+															
+															if ( read_block1 == null ){
+																
+																continue;
+															}
+														}
+														
+														write_block = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_EXTERNAL, target_block_size );
+														
+														final byte SS = DirectByteBuffer.SS_EXTERNAL;
+																
+														int	delta = (int)( origin_offset - origin_start );
+														
+														read_block1.position( SS, delta );
+														
+															// readblock1 could have more bytes in it than the writeblock if writeblock is the last
+															// block of the file
+														
+														int rb1_rem =  read_block1.remaining( SS );
+														
+														if ( rb1_rem > target_block_size ){
+															
+															read_block1.limit( SS, delta + target_block_size );
+														}
+														
+														write_block.limit( SS, read_block1.remaining( SS ));
+														
+														write_block.put( SS, read_block1 );
+														
+														write_block.limit( SS, target_block_size );
+														
+														read_block1.returnToPool();
+														
+														read_block1 = null;
+														
+														if ( write_block.hasRemaining( SS )){
+																												
+															int	origin2_piece_number 	= origin1_piece_number;
+															int	origin2_block_num		= origin1_block_num + 1;
+															
+															if ( origin2_block_num >= origin1_piece.getNbBlocks()){
+																
+																origin2_piece_number++;
+																
+																origin2_block_num = 0;
+															}
+							
+															if ( origin2_piece_number < pieces.length ){
+																
+																DiskManagerPiece	origin2_piece = pieces[origin2_piece_number];
+								
+																if ( !origin2_piece.isWritten( origin2_block_num )){
+																	
+																	continue;
+																}
+																
+																read_block2 = disk_manager.readBlock( origin2_piece_number , origin2_block_num*DiskManager.BLOCK_SIZE, origin2_piece.getBlockSize( origin2_block_num ));
+																
+																if ( read_block2 == null ){
+																	
+																	continue;
+																}
+																
+																read_block2.limit( SS, write_block.remaining( SS ));
+																
+																write_block.put( SS, read_block2 );
+																
+																read_block2.position( SS, 0 );
+																read_block2.limit( SS, read_block2.capacity( SS ));
+																
+																prev_block 		= read_block2;
+																prev_block_pn	= origin2_piece_number;
+																prev_block_bn	= origin2_block_num;
+																		
+																read_block2	= null;
+															}
+														}
+														
+														if ( write_block.hasRemaining( SS )){
+															
+															continue;
+															
+														}else{
+															
+															write_block.flip( SS );
+																
+															target_written = target_piece.getWritten();
+																														
+															if ( target_piece.isDone() || (target_written != null && target_written[target_block_num])){
+
+																	// seems to have been done in the meantime
+																
+															}else{
+																boolean completed_piece = target_piece.getNbWritten() == target_piece.getNbBlocks() - 1;
+																
+																if ( TRACE )System.out.println( "Write from " + origin_offset + "/" + delta + "/" + target_block_size + " to " + target_piece_num + "/" + target_block_num );
+		
+																if ( other_file.writeBlock( target_piece_num, target_block_num, write_block )){
+																	
+																	write_block = null;
+																			
+																	if ( completed_piece ){
+																		
+																		pieces_completed++;
+																		
+																		if ( pieces_completed < 5 ){
+																			
+																			try{
+																				Thread.sleep(500);
+																				
+																			}catch( Throwable e ){
+																				
+																			}
+																		}
+																	}
+																}else{
+																	
+																	break;
+																}
+															}
+														}
+													}finally{
+														
+														if ( read_block1 != null ){
+															
+															read_block1.returnToPool();
+														}
+														
+														if ( read_block2 != null ){
+															
+															read_block2.returnToPool();
+														}
+														
+														if ( write_block != null ){
+															
+															write_block.returnToPool();
+														}
+													}
+												}
+											}
+										}
+									}finally{
+										
+										if ( prev_block != null ){
+											
+											prev_block.returnToPool();
+										}
+									}
+								}
+							}
+						});
+				}
+			}
+			
+			private boolean
+			writeBlock(
+				int					piece_number,
+				int					block_number,
+				DirectByteBuffer	buffer )
+			{
+				PEPeerManager pm = getPeerManager();
+			
+				if ( pm == null ){
+					
+					return( false );
+				}
+				
+				modified_pieces[ piece_number - file.getFirstPieceNumber() ] = true;
+				
+				int	length = buffer.remaining( DirectByteBuffer.SS_EXTERNAL );
+				
+				synchronized( merged_data_lock ){
+					
+					DownloadManagerState dms = download_manager.getDownloadState();
+					
+					long merged = dms.getLongAttribute( DownloadManagerState.AT_MERGED_DATA );
+					
+					merged += length;
+					
+					dms.setLongAttribute( DownloadManagerState.AT_MERGED_DATA, merged );
+				}
+				
+				merged_byte_counnt += length;
+				
+				pm.writeBlock( piece_number, block_number*DiskManager.BLOCK_SIZE, buffer, "block-xfer from " + getID(), true );
+				
+				return( true );
+			}
+
+			private void
+			pieceCorrupt(
+				int		piece_number )
+			{
+				int	first_piece = file.getFirstPieceNumber();
+				
+				if ( piece_number >= first_piece && piece_number <= file.getLastPieceNumber()){
+					
+					if ( modified_pieces[ piece_number - first_piece ] ){
+						
+						pieces_corrupted++;
+						
+						if ( pieces_corrupted >= HASH_FAILS_BEFORE_QUIT ){
+							
+							abandon( this );
+						}
+					}
+				}
+			}
+			
+			private long
+			getMergedByteCount()
+			{
+				return( merged_byte_counnt );
+			}
+		}
+	}
+	
+	private interface
+	DownloadManagerPeerListenerEx
+		extends DownloadManagerPeerListener
+	{
+		public void
+		sync();
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerHostSupport.java b/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerHostSupport.java
index 3dd6862..ccaa5b0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerHostSupport.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerHostSupport.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerImpl.java b/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerImpl.java
index dfb11fb..c7fc46b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -175,8 +176,8 @@ public class GlobalManagerImpl
 				}
 			});
 	
-	private List<DownloadManager> 		managers_cow	= new ArrayList<DownloadManager>();
-	private AEMonitor	managers_mon	= new AEMonitor( "GM:Managers" );
+	private volatile List<DownloadManager> 		managers_cow	= new ArrayList<DownloadManager>();
+	private AEMonitor							managers_mon	= new AEMonitor( "GM:Managers" );
 	
 	private Map		manager_map			= new HashMap();
 		
@@ -197,7 +198,7 @@ public class GlobalManagerImpl
 	private GlobalManagerHostSupport	host_support;
   
 		// for non-persistent downloads
-	private Map<HashWrapper,Map>							saved_download_manager_state	= new HashMap<HashWrapper,Map>();
+	private Map<HashWrapper,Map>		saved_download_manager_state	= new HashMap<HashWrapper,Map>();
 	
 	
 	private int							next_seed_piece_recheck_index;
@@ -214,6 +215,7 @@ public class GlobalManagerImpl
 	private volatile boolean 	isStopping;
 	private volatile boolean	destroyed;
 	private volatile boolean 	needsSaving = false;
+	private volatile long		needsSavingCozStateChanged;
   
 	private boolean seeding_only_mode 				= false;
 	private boolean potentially_seeding_only_mode	= false;
@@ -292,10 +294,39 @@ public class GlobalManagerImpl
 	        
 	        determineSaveResumeDataInterval();
 	        
-	        if (	( loopFactor % saveResumeLoopCount == 0 ) || 
-	        		( needsSaving && loadingComplete && loopFactor > initSaveResumeLoopCount )) {
-	          	
+	        if (( loopFactor % saveResumeLoopCount == 0 )){
+	        	
 	        	saveDownloads( true );
+	        	
+	        }else if ( loadingComplete && loopFactor > initSaveResumeLoopCount ){
+	          	
+	        	if ( needsSavingCozStateChanged > 0 ){
+	        	
+	        		int num_downloads = managers_cow.size();
+	        		
+	        		boolean	do_save = false;
+	        		
+	        		if ( num_downloads < 10 ){
+	        		
+	        			do_save = true;
+	        			
+	        		}else{
+	        		
+	        				// this save isn't that important so back off based on number of downloads as saving a lot of download's state
+	        				// takes some resources...
+	        			
+	        			long	now = SystemTime.getMonotonousTime();
+	        			
+	        			long	elapsed_secs = ( now - needsSavingCozStateChanged )/1000;
+	        			
+	        			do_save = elapsed_secs > num_downloads;
+	        		}
+	        		
+	        		if ( do_save ){
+	        		
+	        			saveDownloads( true );
+	        		}
+	        	}
 	        }
 	        	        
 	        if ((loopFactor % natCheckLoopCount == 0)) {
@@ -473,6 +504,20 @@ public class GlobalManagerImpl
     			return( false );
     		}
     		
+    		public String[]
+			getEnabledNetworks(
+				HashWrapper	hash )
+    		{
+       			DownloadManager	dm = getDownloadManager(hash);
+    			
+    			if ( dm == null ){
+    				
+    				return( null );
+    			}
+    			
+    			return( dm.getDownloadState().getNetworks());
+    		}
+    		
     		public int[] 
     		getCachedScrape(
     			HashWrapper hash )
@@ -641,6 +686,8 @@ public class GlobalManagerImpl
     
     	new DownloadStateTagger( this );
     }
+    
+    new GlobalManagerFileMerger( this );
   }
   
   public void loadExistingTorrentsNow(boolean async)
@@ -858,6 +905,10 @@ public class GlobalManagerImpl
 				    	}
 					}
 				}
+				
+				if ( TorrentUtils.shouldDeleteTorrentFileAfterAdd( fDest, persistent )){
+					deleteDest = true;
+				}
 			}
 		} catch (IOException e) {
 			System.out.println("DownloadManager::addDownloadManager: fails - td = "
@@ -965,7 +1016,7 @@ public class GlobalManagerImpl
 	        
 	        Long lDownloaded = (Long) save_download_state.get("downloaded");
 	        Long lUploaded = (Long) save_download_state.get("uploaded");
-	        Long lCompleted = (Long) save_download_state.get("completed");
+	        Long lCompletedBytes = (Long) save_download_state.get("completedbytes");
 	        Long lDiscarded = (Long) save_download_state.get("discarded");
 	        Long lHashFailsCount = (Long) save_download_state.get("hashfails");	// old method, number of fails
 	        Long lHashFailsBytes = (Long) save_download_state.get("hashfailbytes");	// new method, bytes failed
@@ -988,8 +1039,8 @@ public class GlobalManagerImpl
 	        dm_stats.setDownloadRateLimitBytesPerSecond( maxDL );
 	        dm_stats.setUploadRateLimitBytesPerSecond( maxUL );
 	        
-	        if (lCompleted != null) {
-	          dm_stats.setDownloadCompleted(lCompleted.intValue());
+	        if (lCompletedBytes != null) {
+	          dm_stats.setDownloadCompletedBytes(lCompletedBytes.longValue());
 	        }
 	        
 	        if (lDiscarded != null) {
@@ -1360,86 +1411,94 @@ public class GlobalManagerImpl
    */
   public void 
   stopGlobalManager() {
-  	try{
-  		managers_mon.enter();
-  		
-  		if ( isStopping ){
-  			
-  			return;
-  		}
-  		
-  		isStopping	= true;
-  		
-  	}finally{
-  		
-  		managers_mon.exit();
-  	}
-  		
-  	stats.save();
-  	
-	informDestroyInitiated();
-	
-	if ( host_support != null ){
-		host_support.destroy();
-	}
-  
-  torrent_folder_watcher.destroy();
-	
-		// kick off a non-daemon task. This will ensure that we hang around
-		// for at least LINGER_PERIOD to run other non-daemon tasks such as writing
-		// torrent resume data...
-	
-	try{
-    	NonDaemonTaskRunner.run(
-    			new NonDaemonTask()
-    			{
-    				public Object
-    				run()
-    				{	
-    					return( null );
-    				}
-    				
-    				public String
-    				getName()
-    				{
-    					return( "Stopping global manager" );
-    				}
-    			});
-	}catch( Throwable e ){
-		Debug.printStackTrace( e );
-	}
-	
-  checker.stopIt();
-  
-  if ( COConfigurationManager.getBooleanParameter("Pause Downloads On Exit" )){
-	  
-	  pauseDownloads( true );
-	  
-	  	// do this before save-downloads so paused state gets saved
-	  
-	  stopAllDownloads( true );
-	  
-	  saveDownloads( true );
+	  try{
+		  managers_mon.enter();
 
-  }else{
-  
-	  saveDownloads( true );
-  
-	  stopAllDownloads( true );
-  }
- 
-  if ( stats_writer != null ){
-  	
-  	stats_writer.destroy();
-  }
-  
-  DownloadManagerStateFactory.saveGlobalStateCache();
-  
-  managers_cow	= new ArrayList();
-  
-  manager_map.clear();
-  
-  informDestroyed();
+		  if ( isStopping ){
+
+			  return;
+		  }
+
+		  isStopping	= true;
+
+	  }finally{
+
+		  managers_mon.exit();
+	  }
+
+	  stats.save();
+
+	  informDestroyInitiated();
+
+	  if ( host_support != null ){
+		  host_support.destroy();
+	  }
+
+	  torrent_folder_watcher.destroy();
+
+	  // kick off a non-daemon task. This will ensure that we hang around
+	  // for at least LINGER_PERIOD to run other non-daemon tasks such as writing
+	  // torrent resume data...
+
+	  try{
+		  NonDaemonTaskRunner.run(
+				  new NonDaemonTask()
+				  {
+					  public Object
+					  run()
+					  {	
+						  return( null );
+					  }
+
+					  public String
+					  getName()
+					  {
+						  return( "Stopping global manager" );
+					  }
+				  });
+	  }catch( Throwable e ){
+		  Debug.printStackTrace( e );
+	  }
+
+	  checker.stopIt();
+
+	  if ( COConfigurationManager.getBooleanParameter("Pause Downloads On Exit" )){
+
+		  pauseDownloads( true );
+
+		  // do this before save-downloads so paused state gets saved
+
+		  stopAllDownloads( true );
+
+		  saveDownloads( true );
+
+	  }else{
+
+		  saveDownloads( true );
+
+		  stopAllDownloads( true );
+	  }
+
+	  if ( stats_writer != null ){
+
+		  stats_writer.destroy();
+	  }
+
+	  DownloadManagerStateFactory.saveGlobalStateCache();
+
+	  try{
+		  managers_mon.enter();
+
+		  managers_cow	= new ArrayList<DownloadManager>();
+
+		  manager_map.clear();
+
+	  }finally{  
+
+		  managers_mon.exit();
+	  }
+
+	  informDestroyed();
   }
 
   public void stopAllDownloads() {
@@ -2075,7 +2134,9 @@ public class GlobalManagerImpl
 
     //    if(Boolean.getBoolean("debug")) return;
 
-	  needsSaving = false;
+	  needsSaving 					= false;
+	  needsSavingCozStateChanged 	= 0;
+	  
 	  if (this.cripple_downloads_config) {
 		  return;
 	  }
@@ -2083,14 +2144,21 @@ public class GlobalManagerImpl
   	try{
   		managers_mon.enter();
   		
-	    Collections.sort(managers_cow, new Comparator () {
-        public final int compare (Object a, Object b) {
-        	return ((DownloadManager) a).getPosition()
-							- ((DownloadManager) b).getPosition();
-        }
-      });
+  		List<DownloadManager>	managers_temp = new ArrayList<DownloadManager>( managers_cow );
+
+	    Collections.sort(
+	    	managers_temp, 
+	    	new Comparator () 
+	    	{
+	    		public final int 
+	    		compare(Object a, Object b) {
+	    			return ((DownloadManager) a).getPosition() - ((DownloadManager) b).getPosition();
+	    		}
+	    	});
   	
-      if (Logger.isEnabled())
+	    managers_cow = managers_temp;
+	    
+	    if (Logger.isEnabled())
 				Logger.log(new LogEvent(LOGID, "Saving Download List ("
 						+ managers_cow.size() + " items)"));
 	    Map map = new HashMap();
@@ -2295,7 +2363,7 @@ public class GlobalManagerImpl
 	boolean				internal_export )
   {
 	  DownloadManagerStats dm_stats = dm.getStats();
-	  Map dmMap = new HashMap();
+	  Map<String, Object> dmMap = new HashMap<String, Object>();
 	  TOTorrent	torrent = dm.getTorrent();
 
 	  if ( torrent != null ){
@@ -2345,7 +2413,7 @@ public class GlobalManagerImpl
 	  }
 	  dmMap.put("downloaded", new Long(dm_stats.getTotalDataBytesReceived()));
 	  dmMap.put("uploaded", new Long(dm_stats.getTotalDataBytesSent()));
-	  dmMap.put("completed", new Long(dm_stats.getDownloadCompleted(true)));
+	  dmMap.put("completedbytes", new Long(dm_stats.getDownloadCompletedBytes()));
 	  dmMap.put("discarded", new Long(dm_stats.getDiscarded()));
 	  dmMap.put("hashfailbytes", new Long(dm_stats.getHashFailBytes()));
 	  dmMap.put("forceStart", new Long(dm.isForceStart() && (dm.getState() != DownloadManager.STATE_CHECKING) ? 1 : 0));
@@ -2537,7 +2605,13 @@ public class GlobalManagerImpl
       
       	int posComplete = 1;
       	int posIncomplete = 1;
-		    Collections.sort(managers_cow, new Comparator () {
+		
+  		List<DownloadManager>	managers_temp = new ArrayList<DownloadManager>( managers_cow );
+
+      	Collections.sort(
+      		managers_temp, 
+      		new Comparator() 
+      		{
 	          public final int compare (Object a, Object b) {
 	            int i = ((DownloadManager)a).getPosition() - ((DownloadManager)b).getPosition();
 	            if (i != 0) {
@@ -2554,6 +2628,9 @@ public class GlobalManagerImpl
 	            return 0;
 	          }
 	        } );
+      	
+      	managers_cow = managers_temp;
+      	
         for (int i = 0; i < managers_cow.size(); i++) {
           DownloadManager dm = (DownloadManager) managers_cow.get(i);
           if (dm.isDownloadComplete(false))
@@ -2748,7 +2825,10 @@ public class GlobalManagerImpl
 	DownloadManager 	manager, 
 	int 				new_state ) 
   {
-	  needsSaving = true;  //make sure we update 'downloads.config' on state changes
+	  if ( needsSavingCozStateChanged == 0  ){
+		  
+		  needsSavingCozStateChanged = SystemTime.getMonotonousTime(); //make sure we update 'downloads.config' on state changes
+	  }
 
 	  //run seeding-only-mode check
 
@@ -3889,6 +3969,11 @@ public class GlobalManagerImpl
 					
 					tag_incomplete.removeTaggable( manager );
 				}
+				
+				if ( tag_paused.hasTaggable( manager )){
+
+					tag_paused.removeTaggable( manager );
+				}
 			}	
 		}
 		
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerStatsImpl.java b/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerStatsImpl.java
index 354e495..f201324 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerStatsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -29,14 +30,28 @@ package org.gudy.azureus2.core3.global.impl;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.global.*;
 import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.util.SimpleTimer.TimerTickReceiver;
+
+import com.aelitis.azureus.core.util.GeneralUtils;
+import com.aelitis.azureus.core.util.average.MovingImmediateAverage;
 
 
 public class 
 GlobalManagerStatsImpl
-	implements GlobalManagerStats
+	implements GlobalManagerStats, TimerTickReceiver
 {
 	private GlobalManagerImpl		manager;
 	
+	private long smooth_last_sent;
+	private long smooth_last_received;
+	
+	private int current_smoothing_window 	= GeneralUtils.getSmoothUpdateWindow();
+	private int current_smoothing_interval 	= GeneralUtils.getSmoothUpdateInterval();
+	
+	private MovingImmediateAverage smoothed_receive_rate 	= GeneralUtils.getSmoothAverage();
+	private MovingImmediateAverage smoothed_send_rate 		= GeneralUtils.getSmoothAverage();
+	
+	
 	private long total_data_bytes_received;
     private long total_protocol_bytes_received;
     
@@ -65,6 +80,8 @@ GlobalManagerStatsImpl
 		manager = _manager;
 		
 		load();
+		
+		SimpleTimer.addTickReceiver( this );
 	}
   
 	protected void
@@ -198,4 +215,43 @@ GlobalManagerStatsImpl
     	return( manager.getTotalSwarmsPeerRate(downloading,seeding));
     }
 
+	public void
+	tick(
+		long		mono_now,
+		int			tick_count )
+	{
+		if ( tick_count % current_smoothing_interval == 0 ){
+
+			int	current_window = GeneralUtils.getSmoothUpdateWindow();
+			
+			if ( current_smoothing_window != current_window ){
+			
+				current_smoothing_window 	= current_window;
+				current_smoothing_interval	= GeneralUtils.getSmoothUpdateInterval();
+				smoothed_receive_rate 		= GeneralUtils.getSmoothAverage();
+				smoothed_send_rate 			= GeneralUtils.getSmoothAverage();
+			}
+			
+			long	up 		= total_data_bytes_sent + total_protocol_bytes_sent;
+			long	down 	= total_data_bytes_received + total_protocol_bytes_received;
+			
+			smoothed_send_rate.update( up - smooth_last_sent );
+			smoothed_receive_rate.update( down - smooth_last_received );
+			
+			smooth_last_sent 		= up;
+			smooth_last_received 	= down;
+		}
+	}
+	
+	public long
+	getSmoothedSendRate()
+	{
+		return((long)(smoothed_send_rate.getAverage()/current_smoothing_interval));
+	}
+	
+	public long
+	getSmoothedReceiveRate()
+	{
+		return((long)(smoothed_receive_rate.getAverage()/current_smoothing_interval));
+	}
 }
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerStatsWriter.java b/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerStatsWriter.java
index a29c849..13f8275 100644
--- a/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerStatsWriter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/global/impl/GlobalManagerStatsWriter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/html/HTMLChunk.java b/azureus2/src/org/gudy/azureus2/core3/html/HTMLChunk.java
index 68c3f3c..916f570 100644
--- a/azureus2/src/org/gudy/azureus2/core3/html/HTMLChunk.java
+++ b/azureus2/src/org/gudy/azureus2/core3/html/HTMLChunk.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/html/HTMLException.java b/azureus2/src/org/gudy/azureus2/core3/html/HTMLException.java
index 65f7031..83a8b78 100644
--- a/azureus2/src/org/gudy/azureus2/core3/html/HTMLException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/html/HTMLException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/html/HTMLPage.java b/azureus2/src/org/gudy/azureus2/core3/html/HTMLPage.java
index 5dda167..83d49ba 100644
--- a/azureus2/src/org/gudy/azureus2/core3/html/HTMLPage.java
+++ b/azureus2/src/org/gudy/azureus2/core3/html/HTMLPage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/html/HTMLPageFactory.java b/azureus2/src/org/gudy/azureus2/core3/html/HTMLPageFactory.java
index 59a9d41..a3ecd40 100644
--- a/azureus2/src/org/gudy/azureus2/core3/html/HTMLPageFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/html/HTMLPageFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/html/HTMLUtils.java b/azureus2/src/org/gudy/azureus2/core3/html/HTMLUtils.java
index 66f1b37..9afddd7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/html/HTMLUtils.java
+++ b/azureus2/src/org/gudy/azureus2/core3/html/HTMLUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/html/impl/HTMLChunkImpl.java b/azureus2/src/org/gudy/azureus2/core3/html/impl/HTMLChunkImpl.java
index b844efd..36a4cbe 100644
--- a/azureus2/src/org/gudy/azureus2/core3/html/impl/HTMLChunkImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/html/impl/HTMLChunkImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/html/impl/HTMLPageImpl.java b/azureus2/src/org/gudy/azureus2/core3/html/impl/HTMLPageImpl.java
index 25d5665..81a8e8b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/html/impl/HTMLPageImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/html/impl/HTMLPageImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/internat/IntegratedResourceBundle.java b/azureus2/src/org/gudy/azureus2/core3/internat/IntegratedResourceBundle.java
index fe29467..fec16ed 100644
--- a/azureus2/src/org/gudy/azureus2/core3/internat/IntegratedResourceBundle.java
+++ b/azureus2/src/org/gudy/azureus2/core3/internat/IntegratedResourceBundle.java
@@ -1,6 +1,6 @@
 /*
  * Created on 29.11.2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.internat;
diff --git a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleTorrentUtil.java b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleTorrentUtil.java
index ffa0ad8..2b3f6c7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleTorrentUtil.java
+++ b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleTorrentUtil.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 30, 2006 7:32:56 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.internat;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtil.java b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtil.java
index 1727be6..2141067 100644
--- a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtil.java
+++ b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtil.java
@@ -1,9 +1,10 @@
 /**
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.internat;
diff --git a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoder.java b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoder.java
index bb1a809..d4c7a04 100644
--- a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoder.java
+++ b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderCandidate.java b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderCandidate.java
index 9c4c0e6..eb66c03 100644
--- a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderCandidate.java
+++ b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderCandidate.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderFallback.java b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderFallback.java
index cdddce3..ea63c33 100644
--- a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderFallback.java
+++ b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderFallback.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderReal.java b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderReal.java
index 458ded0..320b22d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderReal.java
+++ b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilDecoderReal.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilEncodingException.java b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilEncodingException.java
index a1a1fc1..a4dccc0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilEncodingException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilEncodingException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilListener.java b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilListener.java
index 83752de..58e66c0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/internat/LocaleUtilListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/internat/MessageText.java b/azureus2/src/org/gudy/azureus2/core3/internat/MessageText.java
index ad889a5..c0b661e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/internat/MessageText.java
+++ b/azureus2/src/org/gudy/azureus2/core3/internat/MessageText.java
@@ -1,6 +1,6 @@
 /*
  * Created on 24.07.2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.internat;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPChecker.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPChecker.java
index 8a70022..7eec858 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPChecker.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPChecker.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerFactory.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerFactory.java
index 07e60ad..16fe5a5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerService.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerService.java
index 1887fbd..cb261bb 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerService.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerService.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerServiceListener.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerServiceListener.java
index 78db9b4..dbf8a37 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerServiceListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/ExternalIPCheckerServiceListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerImpl.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerImpl.java
index f67a28c..7044740 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceDiscoveryVIP.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceDiscoveryVIP.java
index 55a6c4c..a50f5be 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceDiscoveryVIP.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceDiscoveryVIP.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceDynDNS.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceDynDNS.java
index f4d9825..23c8f10 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceDynDNS.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceDynDNS.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceImpl.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceImpl.java
index db1986a..3ff4579 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceNoLookup.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceNoLookup.java
index bd7efde..81b8a68 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceNoLookup.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceNoLookup.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceSimple.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceSimple.java
index 24d506f..6730dc1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceSimple.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/extipchecker/impl/ExternalIPCheckerServiceSimple.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/natchecker/NatChecker.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/natchecker/NatChecker.java
index 3c15d35..470640c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/natchecker/NatChecker.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/natchecker/NatChecker.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipchecker/natchecker/NatCheckerServer.java b/azureus2/src/org/gudy/azureus2/core3/ipchecker/natchecker/NatCheckerServer.java
index d284779..ca37359 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipchecker/natchecker/NatCheckerServer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipchecker/natchecker/NatCheckerServer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/BadIp.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/BadIp.java
index 9eccde3..affa6ee 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/BadIp.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/BadIp.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/BadIps.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/BadIps.java
index f5fd5c6..7de2628 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/BadIps.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/BadIps.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/BannedIp.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/BannedIp.java
index 2df70c6..71d914f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/BannedIp.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/BannedIp.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/BlockedIp.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/BlockedIp.java
index c0cb107..57ddce1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/BlockedIp.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/BlockedIp.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/IPFilterListener.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/IPFilterListener.java
index d04ed96..a59cdec 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/IPFilterListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/IPFilterListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Aug-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilter.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilter.java
index 181a990..13785d8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilterManager.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilterManager.java
index db381b0..30860d4 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilterManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilterManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilterManagerFactory.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilterManagerFactory.java
index 6875550..7d9efc7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilterManagerFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpFilterManagerFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpRange.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpRange.java
index c4f8a96..1e10f79 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpRange.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/IpRange.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BadIpImpl.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BadIpImpl.java
index 34f82ae..61271a0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BadIpImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BadIpImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BadIpsImpl.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BadIpsImpl.java
index dc54d06..bb21fe7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BadIpsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BadIpsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BannedIpImpl.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BannedIpImpl.java
index 42f744e..48685e4 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BannedIpImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BannedIpImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BlockedIpImpl.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BlockedIpImpl.java
index f6bf06b..528fb67 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BlockedIpImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/BlockedIpImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IPAddressRangeManager.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IPAddressRangeManager.java
index 831e2fb..80483cf 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IPAddressRangeManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IPAddressRangeManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterAutoLoaderImpl.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterAutoLoaderImpl.java
index 9566668..1a11155 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterAutoLoaderImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterAutoLoaderImpl.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.ipfilter.impl;
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterImpl.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterImpl.java
index 8c8b8ef..2ca5c8a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterManagerImpl.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterManagerImpl.java
index eb810d0..2a5c0aa 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpFilterManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpRangeImpl.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpRangeImpl.java
index 730a35d..c7ce30c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpRangeImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/IpRangeImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/tests/FakeTrackerResponseGenerator.java b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/tests/FakeTrackerResponseGenerator.java
index 6063b73..cfa1354 100644
--- a/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/tests/FakeTrackerResponseGenerator.java
+++ b/azureus2/src/org/gudy/azureus2/core3/ipfilter/impl/tests/FakeTrackerResponseGenerator.java
@@ -2,11 +2,12 @@
  * Created on 30 sept. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.ipfilter.impl.tests;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/ILogAlertListener.java b/azureus2/src/org/gudy/azureus2/core3/logging/ILogAlertListener.java
index b30b485..6382179 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/ILogAlertListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/ILogAlertListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.logging;
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/ILogEventListener.java b/azureus2/src/org/gudy/azureus2/core3/logging/ILogEventListener.java
index 60809a2..e5f8244 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/ILogEventListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/ILogEventListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.logging;
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/LogAlert.java b/azureus2/src/org/gudy/azureus2/core3/logging/LogAlert.java
index a37a535..174b9df 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/LogAlert.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/LogAlert.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.logging;
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/LogEvent.java b/azureus2/src/org/gudy/azureus2/core3/logging/LogEvent.java
index 197cca5..bb2fa81 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/LogEvent.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/LogEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.logging;
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/LogIDs.java b/azureus2/src/org/gudy/azureus2/core3/logging/LogIDs.java
index ce26c3e..0d9ceda 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/LogIDs.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/LogIDs.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.logging;
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/LogRelation.java b/azureus2/src/org/gudy/azureus2/core3/logging/LogRelation.java
index 4c1d7ed..b12986a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/LogRelation.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/LogRelation.java
@@ -3,11 +3,12 @@
  * Created : Nov 29, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.logging;
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/LogRelationUtils.java b/azureus2/src/org/gudy/azureus2/core3/logging/LogRelationUtils.java
index d3d0c19..29ad3c0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/LogRelationUtils.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/LogRelationUtils.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.logging;
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/Logger.java b/azureus2/src/org/gudy/azureus2/core3/logging/Logger.java
index 39bcaaa..c1cf84e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/Logger.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/Logger.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.logging;
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/impl/FileLogging.java b/azureus2/src/org/gudy/azureus2/core3/logging/impl/FileLogging.java
index 13364e0..f5d3e21 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/impl/FileLogging.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/impl/FileLogging.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.logging.impl;
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/impl/FileLoggingAdapter.java b/azureus2/src/org/gudy/azureus2/core3/logging/impl/FileLoggingAdapter.java
index cb04bac..18b480b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/impl/FileLoggingAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/impl/FileLoggingAdapter.java
@@ -1,6 +1,6 @@
 /*
  * Created on Feb 28, 2006 2:41:30 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.logging.impl;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/logging/impl/LoggerImpl.java b/azureus2/src/org/gudy/azureus2/core3/logging/impl/LoggerImpl.java
index 629fa53..243a460 100644
--- a/azureus2/src/org/gudy/azureus2/core3/logging/impl/LoggerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/logging/impl/LoggerImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.logging.impl;
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeer.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeer.java
index 7520d18..ee67d84 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -249,6 +250,22 @@ PEPeer
 		boolean				upload );
 	
 	public void
+	setUploadDisabled(
+		Object				key,
+		boolean				disabled );
+	
+	public void
+	setDownloadDisabled(
+		Object				key,
+		boolean				disabled );
+
+	public boolean
+	isUploadDisabled();
+	
+	public boolean
+	isDownloadDisabled();
+	
+	public void
 	updateAutoUploadPriority(
 		Object	key,
 		boolean	inc );
@@ -415,4 +432,7 @@ PEPeer
 	public boolean isPriorityConnection();
 	
 	public void setPriorityConnection( boolean is_priority ); 
+	
+	public boolean
+	isClosed();
 }
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerListener.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerListener.java
index 3e7e05b..da86e62 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 25, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManager.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManager.java
index da86435..b3f566c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -250,7 +251,13 @@ PEPeerManager
 		boolean 	use_crypto,
 		Map			user_data );
   
-	
+	public void
+	peerDiscovered(
+		String		peer_source,
+		String 		ip_address, 
+		int			tcp_port, 
+		int			udp_port,
+		boolean 	use_crypto );
 	
 	public void
 	removePeer(
@@ -293,11 +300,11 @@ PEPeerManager
 	
 	public void 
 	writeBlock(
-		int 		pieceNumber, 
-		int 		offset, 
+		int 				pieceNumber, 
+		int 				offset, 
 		DirectByteBuffer 	data,
-		PEPeer 		sender,
-        boolean     cancel);		
+		Object 				sender,			// either a PEPeer or a String
+        boolean     		cancel);		
   
 //  public void writeBlockAndCancelOutstanding(int pieceNumber, int offset, DirectByteBuffer data,PEPeer sender);
   
@@ -399,6 +406,10 @@ PEPeerManager
 	isPeerSourceEnabled(
 		String	peer_source );
 	
+	public boolean
+	isNetworkEnabled(
+		String	network );
+	
 	public int
 	getPartitionID();
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerAdapter.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerAdapter.java
index eb271c1..7c0cb57 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Dec-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -185,6 +182,9 @@ PEPeerManagerAdapter
 	isNetworkEnabled(
 		String	network );
 	
+	public String[]
+	getEnabledNetworks();
+	
 	public void
 	priorityConnectionChanged(
 		boolean	added );
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerFactory.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerFactory.java
index 64bc1e2..1cf06b3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerListener.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerListener.java
index b75ba74..de0f3db 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -61,5 +62,7 @@ PEPeerManagerListener
   
   public void peerSentBadData( PEPeerManager manager, PEPeer peer, int piece_number );
   
+  public void pieceCorrupted( PEPeerManager manager, int piece_number );
+  
   public void destroyed();
 }
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerListenerAdapter.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerListenerAdapter.java
new file mode 100644
index 0000000..f030a34
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerListenerAdapter.java
@@ -0,0 +1,50 @@
+/*
+ * File    : PEPeerManagerListener.java
+ * Created : 22-Nov-2003
+ * 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, 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 ( 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.core3.peer;
+
+import com.aelitis.azureus.core.peermanager.peerdb.PeerItem;
+
+/**
+ * @author parg
+ *
+ */
+public class 
+PEPeerManagerListenerAdapter 
+	implements PEPeerManagerListener
+{
+  public void peerAdded( PEPeerManager manager, PEPeer peer ){}
+  
+  public void peerRemoved( PEPeerManager manager, PEPeer peer ){}
+  
+  public void pieceAdded( PEPeerManager manager, PEPiece piece, PEPeer for_peer ){}
+  
+  public void pieceRemoved( PEPeerManager manager, PEPiece piece ){}
+  
+  public void peerDiscovered( PEPeerManager manager, PeerItem peer, PEPeer finder ){}
+  
+  public void peerSentBadData( PEPeerManager manager, PEPeer peer, int piece_number ){}
+  
+  public void pieceCorrupted( PEPeerManager manager, int piece_number ){}
+  
+  public void destroyed(){}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerStats.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerStats.java
index 00a59f1..9eff9ed 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerStats.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerManagerStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerSource.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerSource.java
index 5a80750..b9d97c1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerSource.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerSource.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerStats.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerStats.java
index 87ee8c5..1c591d2 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerStats.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPeerStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/PEPiece.java b/azureus2/src/org/gudy/azureus2/core3/peer/PEPiece.java
index 26d6be8..70c2cf0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/PEPiece.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/PEPiece.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -120,7 +121,7 @@ PEPiece
 	public void			setResumePriority(int p);
 
 	public String[] 	getWriters();
-	public void			setWritten(PEPeer peer, int blockNumber);
+	public void			setWritten(String peer, int blockNumber);
 	public boolean 		isWritten();
 	public boolean 		isWritten( int blockNumber);
 	
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerControl.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerControl.java
index 0d09980..3e4b845 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerControl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerControl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -112,6 +113,14 @@ PEPeerControl
 		PEPeerTransport		originator,
 		int					piece_number );
 	
+	public boolean
+	isFastExtensionPermitted(
+		PEPeerTransport		originator );
+	
+	public void
+	reportBadFastExtensionUse(
+		PEPeerTransport		originator );
+	
 	public void
 	statsRequest(
 		PEPeerTransport		originator,
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerControlFactory.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerControlFactory.java
index 5bb4c38..381f8b7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerControlFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerControlFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerManagerStatsImpl.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerManagerStatsImpl.java
index bd8301b..890b8f1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerManagerStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerManagerStatsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerStatsImpl.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerStatsImpl.java
index 572515e..0785238 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerStatsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransport.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransport.java
index 9643f5e..c324800 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransport.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransport.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -126,6 +127,9 @@ PEPeerTransport
 	public boolean
 	transferAvailable();
 	
+	public long
+	getLastMessageSentTime();
+	
 	public List
 	getExpiredRequests();
   	
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransportExtensionHandler.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransportExtensionHandler.java
index aaf2cbf..754a8c0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransportExtensionHandler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransportExtensionHandler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransportFactory.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransportFactory.java
index 038250d..f98e3d3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransportFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPeerTransportFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPieceImpl.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPieceImpl.java
index e6a8675..f0a3f6b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPieceImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPieceImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -212,12 +213,12 @@ public class PEPieceImpl
     }
     
 	/** This marks a given block as having been written by the given peer
-	 * @param peer the PEPeer that sent the data
+	 * @param peer the peer that sent the data
 	 * @param blockNumber the block we're operating on
 	 */
-	public void setWritten(PEPeer peer, int blockNumber)
+	public void setWritten(String peer, int blockNumber)
 	{
-		writers[blockNumber] =peer.getIp();
+		writers[blockNumber] =peer;
 		dmPiece.setWritten(blockNumber);
 	}
 	
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPieceWriteImpl.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPieceWriteImpl.java
index 0bfce7b..3e7b8e9 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPieceWriteImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/PEPieceWriteImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/PEPeerControlImpl.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/PEPeerControlImpl.java
index 5f6e5c6..e10a98c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/PEPeerControlImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/PEPeerControlImpl.java
@@ -2,7 +2,7 @@
  * Created by Olivier Chalouhi
  * Modified Apr 13, 2004 by Alon Rohter
  * Heavily modified Sep 2005 by Joseph Bridgewater
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.peer.impl.control;
@@ -180,7 +177,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 	private volatile boolean	is_running 		= false;  
 	private volatile boolean	is_destroyed 	= false;  
 
-	private volatile ArrayList<PEPeer>	peer_transports_cow = new ArrayList<PEPeer>();	// Copy on write!
+	private volatile ArrayList<PEPeerTransport>	peer_transports_cow = new ArrayList<PEPeerTransport>();	// Copy on write!
 	private final AEMonitor     peer_transports_mon	= new AEMonitor( "PEPeerControl:PT");
 
 	protected final PEPeerManagerAdapter	adapter;
@@ -226,6 +223,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 	private static final int MAINLOOP_ONE_SECOND_INTERVAL = 1000 / PeerControlScheduler.SCHEDULE_PERIOD_MILLIS;
 	private static final int MAINLOOP_FIVE_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 5;
 	private static final int MAINLOOP_TEN_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 10;
+	private static final int MAINLOOP_TWENTY_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 20;
 	private static final int MAINLOOP_THIRTY_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 30;
 	private static final int MAINLOOP_SIXTY_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 60;
 	private static final int MAINLOOP_TEN_MINUTE_INTERVAL = MAINLOOP_SIXTY_SECOND_INTERVAL * 10;
@@ -260,7 +258,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 	private int	connections_unchoked;
 	
 
-	private List<PEPeer> sweepList = Collections.emptyList();
+	private List<PEPeerTransport> sweepList = Collections.emptyList();
 	private int nextPEXSweepIndex = 0;
 
 
@@ -270,7 +268,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 		}
 
 		public ArrayList<PEPeer> getAllPeers() {
-			return( peer_transports_cow );
+			return( (ArrayList)peer_transports_cow );
 		}		
 
 		public boolean isSeeding() {
@@ -375,6 +373,13 @@ DiskManagerCheckRequestListener, IPFilterListener
 	
 	private long			last_seed_disconnect_time;
 	
+	private BloomFilter		naughty_fast_extension_bloom = 
+			BloomFilterFactory.createRotating(
+				BloomFilterFactory.createAddRemove4Bit( 2000 ), 2 );
+	
+	
+	
+	
 	public 
 	PEPeerControlImpl(
 		byte[]					_peer_id,
@@ -390,7 +395,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 		boolean is_private = false;
 		
 		try{
-			disk_mgr.getTorrent().getPrivate();
+			is_private = disk_mgr.getTorrent().getPrivate();
 			
 		}catch( Throwable e ){
 			
@@ -741,7 +746,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 	public List<PEPeer>
 	getPeers()
 	{
-		return( peer_transports_cow );
+		return( (List)peer_transports_cow );
 	}
 
 	public List<PEPeer>
@@ -750,11 +755,11 @@ DiskManagerCheckRequestListener, IPFilterListener
 	{		
 		List<PEPeer>	result = new ArrayList<PEPeer>();
 
-		Iterator<PEPeer>	it = peer_transports_cow.iterator();
+		Iterator<PEPeerTransport>	it = peer_transports_cow.iterator();
 
 		while( it.hasNext()){
 
-			PEPeerTransport	peer = (PEPeerTransport)it.next();
+			PEPeerTransport	peer = it.next();
 
 			if ( peer.getIp().equals( address )){
 
@@ -786,7 +791,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 	public void
 	addPeer(
-			PEPeer		_transport )
+		PEPeer		_transport )
 	{
 		if ( !( _transport instanceof PEPeerTransport )){
 
@@ -797,7 +802,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 		if (!ip_filter.isInRange(transport.getIp(), getDisplayName(), getTorrentHash())) {
 
-			final ArrayList peer_transports = peer_transports_cow;
+			final ArrayList<PEPeerTransport> peer_transports = peer_transports_cow;
 
 			if ( !peer_transports.contains(transport)){
 
@@ -881,21 +886,21 @@ DiskManagerCheckRequestListener, IPFilterListener
 	}
 
 	private void closeAndRemoveAllPeers( String reason, boolean reconnect ) {
-		ArrayList peer_transports;
+		List<PEPeerTransport> peer_transports;
 
 		try{
 			peer_transports_mon.enter();
 
 			peer_transports = peer_transports_cow;
 
-			peer_transports_cow = new ArrayList( 0 );  
+			peer_transports_cow = new ArrayList<PEPeerTransport>( 0 );  
 		}
 		finally{
 			peer_transports_mon.exit();
 		}
 
 		for( int i=0; i < peer_transports.size(); i++ ) {
-			final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i );
+			final PEPeerTransport peer = peer_transports.get( i );
 
 			try{
 
@@ -920,7 +925,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 		if( reconnect ) {
 			for( int i=0; i < peer_transports.size(); i++ ) {
-				final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i );
+				final PEPeerTransport peer = peer_transports.get( i );
 
 				PEPeerTransport	reconnected_peer = peer.reconnect(false, false);
 			}
@@ -967,7 +972,53 @@ DiskManagerCheckRequestListener, IPFilterListener
 		}
 	}
 
+	public void
+	peerDiscovered(
+		String		peer_source,
+		String 		ip_address, 
+		int			tcp_port, 
+		int			udp_port,
+		boolean 	use_crypto )
+	{
+		if ( peer_database != null ){
+
+			final ArrayList<PEPeerTransport> peer_transports = peer_transports_cow;
+
+			for( int x=0; x < peer_transports.size(); x++ ){
+				
+				PEPeer transport = peer_transports.get( x );
+
+					// allow loopback connects for co-located proxy-based connections and testing
+
+				if ( ip_address.equals( transport.getIp())){
+
+					boolean same_allowed = COConfigurationManager.getBooleanParameter( "Allow Same IP Peers" ) ||
+					
+					transport.getIp().equals( "127.0.0.1" );
+
+					if ( !same_allowed || tcp_port == transport.getPort()){
+						
+						return;
+					}
+				}
+			}
+
+			byte type = use_crypto ? PeerItemFactory.HANDSHAKE_TYPE_CRYPTO : PeerItemFactory.HANDSHAKE_TYPE_PLAIN;
 
+			PeerItem item = PeerItemFactory.createPeerItem( 
+					ip_address, 
+					tcp_port, 
+					PeerItem.convertSourceID( peer_source ), 
+					type, 
+					udp_port, 
+					PeerItemFactory.CRYPTO_LEVEL_1,
+					0 );
+
+			peerDiscovered( null, item );
+			
+			peer_database.addDiscoveredPeer( item );
+		}
+	}
 
 	private void 
 	addPeersFromTracker(
@@ -977,12 +1028,12 @@ DiskManagerCheckRequestListener, IPFilterListener
 		for (int i = 0; i < peers.length; i++){
 			final TRTrackerAnnouncerResponsePeer	peer = peers[i];
 
-			final ArrayList peer_transports = peer_transports_cow;
+			final List<PEPeerTransport> peer_transports = peer_transports_cow;
 
 			boolean already_connected = false;
 
 			for( int x=0; x < peer_transports.size(); x++ ) {
-				final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( x );
+				final PEPeerTransport transport = peer_transports.get( x );
 
 				// allow loopback connects for co-located proxy-based connections and testing
 
@@ -1362,11 +1413,11 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 		lastNeededUndonePieceChange =piecePicker.getNeededUndonePieceChange();
 
-		final ArrayList peer_transports = peer_transports_cow;
+		final List<PEPeerTransport> peer_transports = peer_transports_cow;
 		int cntPeersSnubbed =0;	// recount # snubbed peers while we're at it
 		for (int i =0; i <peer_transports.size(); i++)
 		{
-			final PEPeerTransport peer =(PEPeerTransport)peer_transports.get(i);
+			final PEPeerTransport peer =peer_transports.get(i);
 			peer.checkInterested();
 			if (peer.isSnubbed())
 				cntPeersSnubbed++;
@@ -1571,6 +1622,60 @@ DiskManagerCheckRequestListener, IPFilterListener
 		bad_piece_reported = piece_number;
 	}
 	
+	private static final int FE_EVENT_LIMIT	= 5;	// don't make > 15 without changing bloom!S
+	
+		/*
+		 * We keep track of both peer connection events and attempts to re-download the same fast piece
+		 * for a given peer to prevent an attack whereby a peer connects and repeatedly downloads the same
+		 * fast piece, or alternatively connects, downloads some fast pieces, disconnects, then does so 
+		 * again.
+		 */
+	
+	public boolean
+	isFastExtensionPermitted(
+		PEPeerTransport		originator )
+	{
+		try{
+			byte[] key = originator.getIp().getBytes( Constants.BYTE_ENCODING );
+			
+			synchronized( naughty_fast_extension_bloom ){
+			
+				int events = naughty_fast_extension_bloom.add( key );
+				
+				if ( events < FE_EVENT_LIMIT ){
+					
+					return( true );
+				}
+				
+				Logger.log(new LogEvent(disk_mgr.getTorrent(), LOGID,
+						"Fast extension disabled for " + originator.getIp() + " due to repeat connections" ));
+			}
+			
+		}catch( Throwable e ){
+		}
+		
+		return( false );
+	}
+	
+	public void
+	reportBadFastExtensionUse(
+		PEPeerTransport		originator )
+	{
+		try{
+			byte[] key = originator.getIp().getBytes( Constants.BYTE_ENCODING );
+			
+			synchronized( naughty_fast_extension_bloom ){
+				
+				if ( naughty_fast_extension_bloom.add( key ) == FE_EVENT_LIMIT ){
+					
+					Logger.log(new LogEvent(disk_mgr.getTorrent(), LOGID,
+							"Fast extension disabled for " + originator.getIp() + " due to repeat requests for the same pieces" ));
+				}
+			}
+		}catch( Throwable e ){
+		}
+	}
+	
 	public void
 	setStatsReceiver(
 		PEPeerManager.StatsReceiver	receiver )
@@ -1629,12 +1734,12 @@ DiskManagerCheckRequestListener, IPFilterListener
 				adapter.setStateFinishing();
 
 			_timeFinished = SystemTime.getCurrentTime();
-			final ArrayList peer_transports = peer_transports_cow;
+			final List<PEPeerTransport> peer_transports = peer_transports_cow;
 
 			//remove previous snubbing
 			for (int i =0; i <peer_transports.size(); i++ )
 			{
-				final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i);
+				final PEPeerTransport pc = peer_transports.get(i);
 				pc.setSnubbed(false);
 			}
 			setNbPeersSnubbed(0);
@@ -1768,10 +1873,10 @@ DiskManagerCheckRequestListener, IPFilterListener
 		final long now =SystemTime.getCurrentTime();
 
 		//for every connection
-		final ArrayList peer_transports = peer_transports_cow;
+		final List<PEPeerTransport> peer_transports = peer_transports_cow;
 		for (int i =peer_transports.size() -1; i >=0 ; i--)
 		{
-			final PEPeerTransport pc =(PEPeerTransport)peer_transports.get(i);
+			final PEPeerTransport pc = peer_transports.get(i);
 			if (pc.getPeerState() ==PEPeer.TRANSFERING)
 			{
 				final List expired = pc.getExpiredRequests();
@@ -1996,7 +2101,29 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 				final boolean refresh = mainloop_loop_count % MAINLOOP_THIRTY_SECOND_INTERVAL == 0;
 
-				unchoker.calculateUnchokes( max_to_unchoke, peer_transports, refresh, adapter.hasPriorityConnection());
+				boolean	do_high_latency_peers =  mainloop_loop_count % MAINLOOP_TWENTY_SECOND_INTERVAL == 0 ;
+				
+				if ( do_high_latency_peers ){
+					
+					boolean ok = false;
+					
+					for ( String net: AENetworkClassifier.AT_NON_PUBLIC ){
+					
+						if ( adapter.isNetworkEnabled( net )){
+							
+							ok = true;
+							
+							break;
+						}
+					}
+					
+					if ( !ok ){
+						
+						do_high_latency_peers = false;
+					}
+				}
+				
+				unchoker.calculateUnchokes( max_to_unchoke, peer_transports, refresh, adapter.hasPriorityConnection(), do_high_latency_peers );
 
 				ArrayList	chokes 		= unchoker.getChokes();
 				ArrayList	unchokes	= unchoker.getUnchokes();
@@ -2020,9 +2147,9 @@ DiskManagerCheckRequestListener, IPFilterListener
 	addFastUnchokes(
 		ArrayList	peers_to_unchoke )
 	{
-		for( Iterator it=peer_transports_cow.iterator();it.hasNext();) {
+		for( Iterator<PEPeerTransport> it=peer_transports_cow.iterator();it.hasNext();) {
 
-			PEPeerTransport peer = (PEPeerTransport)it.next();
+			PEPeerTransport peer = it.next();
 
 			if ( 	peer.getConnectionState() != PEPeerTransport.CONNECTION_FULLY_ESTABLISHED ||
 					!UnchokerUtil.isUnchokable( peer, true ) ||
@@ -2048,11 +2175,11 @@ DiskManagerCheckRequestListener, IPFilterListener
 //	send the have requests out
 	private void sendHave(int pieceNumber) {
 		//fo
-		final ArrayList peer_transports = peer_transports_cow;
+		final List<PEPeerTransport> peer_transports = peer_transports_cow;
 
 		for (int i = 0; i < peer_transports.size(); i++) {
 			//get a peer connection
-			final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i);
+			final PEPeerTransport pc = peer_transports.get(i);
 			//send the have message
 			pc.sendHave(pieceNumber);
 		}
@@ -2069,11 +2196,11 @@ DiskManagerCheckRequestListener, IPFilterListener
 			return;
 		}
 
-		ArrayList to_close = null;
+		List<PEPeerTransport> to_close = null;
 
-		final ArrayList peer_transports = peer_transports_cow;
+		final List<PEPeerTransport> peer_transports = peer_transports_cow;
 		for (int i = 0; i < peer_transports.size(); i++) {
-			final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i);
+			final PEPeerTransport pc = peer_transports.get(i);
 
 			if (pc != null && pc.getPeerState() == PEPeer.TRANSFERING && ((isSeeding() && pc.isSeed()) || pc.isRelativeSeed())) {
 				if( to_close == null )  to_close = new ArrayList();
@@ -2083,7 +2210,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 		if( to_close != null ) {		
 			for( int i=0; i < to_close.size(); i++ ) {  			
-				closeAndRemovePeer( (PEPeerTransport)to_close.get(i), "disconnect other seed when seeding", false );
+				closeAndRemovePeer( to_close.get(i), "disconnect other seed when seeding", false );
 			}
 		}
 	}
@@ -2100,7 +2227,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 		stats_tick_count++;
 		
 		//calculate seeds vs peers
-		final ArrayList<PEPeer> peer_transports = peer_transports_cow;
+		final ArrayList<PEPeerTransport> peer_transports = peer_transports_cow;
 
 		int	new_pending_tcp_connections 	= 0;
 		int new_connecting_tcp_connections	= 0;
@@ -2116,9 +2243,9 @@ DiskManagerCheckRequestListener, IPFilterListener
 		int con_blocked		= 0;
 		int con_unchoked	= 0;
 		
-		for ( Iterator<PEPeer> it=peer_transports.iterator();it.hasNext();){
+		for ( Iterator<PEPeerTransport> it=peer_transports.iterator();it.hasNext();){
 			
-			final PEPeerTransport pc = (PEPeerTransport) it.next();
+			final PEPeerTransport pc = it.next();
 			
 			if ( pc.getPeerState() == PEPeer.TRANSFERING) {
 				
@@ -2326,9 +2453,26 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 			final PEPiece pePiece =pePieces[pieceNumber];
 
-			if (pePiece !=null){
+			if ( pePiece != null ){
 
-				pePiece.setWritten((PEPeer)request.getUserData(), request.getOffset() /DiskManager.BLOCK_SIZE );
+				Object user_data = request.getUserData();
+				
+				String key;
+				
+				if ( user_data instanceof String ){
+					
+					key = (String)user_data;
+					
+				}else if ( user_data instanceof PEPeer ){
+					
+					key = ((PEPeer)user_data).getIp();
+					
+				}else{
+					
+					key = "<none>";
+				}
+				
+				pePiece.setWritten( key, request.getOffset() /DiskManager.BLOCK_SIZE );
 
 			}else{
 
@@ -2363,7 +2507,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 	 * @param sender peer that sent this data
 	 * @param cancel if cancels definatly need to be sent to all peers for this request
 	 */
-	public void writeBlock(int pieceNumber, int offset, DirectByteBuffer data, PEPeer sender, boolean cancel)
+	public void writeBlock(int pieceNumber, int offset, DirectByteBuffer data, Object sender, boolean cancel)
 	{
 		final int blockNumber =offset /DiskManager.BLOCK_SIZE;
 		final DiskManagerPiece dmPiece =dm_pieces[pieceNumber];
@@ -2388,10 +2532,10 @@ DiskManagerCheckRequestListener, IPFilterListener
 		if (cancel ||piecePicker.isInEndGameMode())
 		{   // cancel any matching outstanding download requests
 			//For all connections cancel the request
-			final ArrayList peer_transports = peer_transports_cow;
+			final List<PEPeerTransport> peer_transports = peer_transports_cow;
 			for (int i=0;i<peer_transports.size();i++)
 			{
-				final PEPeerTransport connection =(PEPeerTransport) peer_transports.get(i);
+				final PEPeerTransport connection = peer_transports.get(i);
 				final DiskManagerReadRequest dmr =disk_mgr.createReadRequest(pieceNumber, offset, dmPiece.getBlockSize(blockNumber));
 				connection.sendCancel( dmr );
 			}
@@ -2506,10 +2650,10 @@ DiskManagerCheckRequestListener, IPFilterListener
 				return;
 			//for all peers
 
-			final ArrayList peer_transports = peer_transports_cow;
+			final List<PEPeerTransport> peer_transports = peer_transports_cow;
 
 			for (int i = peer_transports.size() - 1; i >= 0; i--) {
-				final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i);
+				final PEPeerTransport pc = peer_transports.get(i);
 				if (pc !=pcOrigin &&pc.getPeerState() ==PEPeer.TRANSFERING &&pc.isPieceAvailable(pieceNumber))
 					((PEPeerStatsImpl)pc.getStats()).statisticalSentPiece(pieceLength / availability);
 			}
@@ -2561,11 +2705,11 @@ DiskManagerCheckRequestListener, IPFilterListener
 	{
 		int	res = 0;
 
-		Iterator it = peer_transports_cow.iterator();
+		Iterator<PEPeerTransport> it = peer_transports_cow.iterator();
 
 		while( it.hasNext()){
 
-			PEPeerTransport transport = (PEPeerTransport)it.next();
+			PEPeerTransport transport = it.next();
 
 			if ( transport.isStalledPendingLoad()){
 
@@ -2736,7 +2880,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 		LimitedRateGroup	group,
 		boolean				upload )
 	{
-		List<PEPeer>	transports;
+		List<PEPeerTransport>	transports;
 
 		try{
 			peer_transports_mon.enter();
@@ -2770,7 +2914,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 		LimitedRateGroup	group,
 		boolean				upload )
 	{
-		List	transports;
+		List<PEPeerTransport>	transports;
 
 		try{
 			peer_transports_mon.enter();
@@ -2808,7 +2952,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 		for (int i=0;i<transports.size();i++){
 
-			((PEPeerTransport)transports.get(i)).removeRateLimiter( group, upload );
+			transports.get(i).removeRateLimiter( group, upload );
 		}	
 	}
 
@@ -2857,7 +3001,8 @@ DiskManagerCheckRequestListener, IPFilterListener
 					boolean wasIPv6;
 					try
 					{
-						wasIPv6 = InetAddress.getByName(ip) instanceof Inet6Address;
+						
+						wasIPv6 = AddressUtils.getByName(ip) instanceof Inet6Address;
 					} catch (UnknownHostException e)
 					{
 						wasIPv6 = false;
@@ -3045,6 +3190,9 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 	protected void addPiece(final PEPiece piece, final int pieceNumber, final boolean force_add, PEPeer for_peer )
 	{
+		if ( piece == null || pePieces[pieceNumber] != null ){
+			Debug.out( "piece state inconsistent" );
+		}
 		pePieces[pieceNumber] =(PEPieceImpl)piece;
 		nbPiecesActive++;
 		if ( is_running || force_add ){
@@ -3072,15 +3220,23 @@ DiskManagerCheckRequestListener, IPFilterListener
 	 */
 	public void removePiece(PEPiece pePiece, int pieceNumber) {
 		if ( pePiece != null ){
-		adapter.removePiece(pePiece);
+			adapter.removePiece(pePiece);
 		} else {
 			pePiece = pePieces[pieceNumber];
 		}
-		pePieces[pieceNumber] =null;
-		nbPiecesActive--;
 		
-		if (pePiece == null) {
-			Debug.outNoStack("Trying to remove piece " + pieceNumber + " when piece is null");
+			// only decrement num-active if this piece was active (see comment below as to why this might no be the case)
+		
+		if ( pePieces[pieceNumber] != null ){
+			pePieces[pieceNumber] = null;
+			nbPiecesActive--;
+		}
+		
+		if ( pePiece == null ){
+			// we can get here without the piece actually being active when we have a very slow peer that is sent a request for the last
+			// block of a piece, doesn't reply, the request gets cancelled, (and piece marked as inactive) and then it sends the block
+			// and our 'recover block as useful' logic kicks in, writes the block, completes the piece, triggers a piece check and here we are
+			
 			return;
 		}
 		
@@ -3341,6 +3497,19 @@ DiskManagerCheckRequestListener, IPFilterListener
 		
 				//    the piece is corrupt
 					
+				Iterator<PEPeerManagerListener> it = peer_manager_listeners_cow.iterator();
+
+				while( it.hasNext()){
+					
+					try{
+						it.next().pieceCorrupted( this, pieceNumber );
+								
+					}catch( Throwable e ){
+						
+						Debug.printStackTrace(e);
+					}
+				}
+				
 				if ( pePiece != null ){
 
 					try{
@@ -3457,8 +3626,10 @@ DiskManagerCheckRequestListener, IPFilterListener
 				}else{
 					
 						// no active piece for some reason, clear down DM piece anyway
+						// one reason for getting here is that blocks are being injected directly from another
+						// download with the same file (well, turns out it isn't the same file if getting hash fails);
 					
-					Debug.out(getDisplayName() + "Piece #" +pieceNumber +" failed check and no active piece, resetting..." );
+					// Debug.out(getDisplayName() + ": Piece #" +pieceNumber +" failed check and no active piece, resetting..." );
 
 					dm_pieces[pieceNumber].reset();
 				}
@@ -3595,13 +3766,13 @@ DiskManagerCheckRequestListener, IPFilterListener
 			int				offset,
 			int				length )
 	{
-		ArrayList peer_transports = peer_transports_cow;
+		List<PEPeerTransport> peer_transports = peer_transports_cow;
 
 		DiskManagerReadRequest	request = null;
 
 		for (int i=0; i < peer_transports.size(); i++) {
 
-			PEPeerTransport conn = (PEPeerTransport)peer_transports.get( i );
+			PEPeerTransport conn = peer_transports.get( i );
 
 			if ( conn.getIp().equals( peer_ip )){
 
@@ -3762,15 +3933,15 @@ DiskManagerCheckRequestListener, IPFilterListener
 	checkForBannedConnections()
 	{
 		if ( ip_filter.isEnabled()){  //if ipfiltering is enabled, remove any existing filtered connections    	
-			ArrayList to_close = null;
+			List<PEPeerTransport> to_close = null;
 
-			final ArrayList	peer_transports = peer_transports_cow;
+			final List<PEPeerTransport>	peer_transports = peer_transports_cow;
 
 			String name 	= getDisplayName();
 			byte[]	hash	= getTorrentHash();
 
 			for (int i=0; i < peer_transports.size(); i++) {
-				final PEPeerTransport conn = (PEPeerTransport)peer_transports.get( i );
+				final PEPeerTransport conn = peer_transports.get( i );
 
 				if ( ip_filter.isInRange( conn.getIp(), name, hash )) {        	
 					if( to_close == null )  to_close = new ArrayList();
@@ -3780,7 +3951,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 			if( to_close != null ) {		
 				for( int i=0; i < to_close.size(); i++ ) {  			
-					closeAndRemovePeer( (PEPeerTransport)to_close.get(i), "IPFilter banned IP address", true );
+					closeAndRemovePeer( to_close.get(i), "IPFilter banned IP address", true );
 				}
 			}
 		}
@@ -3863,11 +4034,11 @@ DiskManagerCheckRequestListener, IPFilterListener
 			// turning on/off super-seeding, gotta kick all connected peers so they get the
 			// "right" bitfield
 
-			ArrayList peer_transports = peer_transports_cow;
+			List<PEPeerTransport> peer_transports = peer_transports_cow;
 
 			for (int i=0; i < peer_transports.size(); i++) {
 
-				PEPeerTransport conn = (PEPeerTransport)peer_transports.get( i );
+				PEPeerTransport conn = peer_transports.get( i );
 
 				closeAndRemovePeer( conn, "Turning on super-seeding", false );
 			}
@@ -3900,21 +4071,21 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 
 		//Find an available Peer
-		PEPeer selectedPeer = null;
-		List sortedPeers = null;
+		PEPeerTransport selectedPeer = null;
+		List<SuperSeedPeer> sortedPeers = null;
 
-		final ArrayList	peer_transports = peer_transports_cow;
+		final List<PEPeerTransport>	peer_transports = peer_transports_cow;
 
-		sortedPeers = new ArrayList(peer_transports.size());
-		Iterator iter = peer_transports.iterator();
-		while(iter.hasNext()) {
-			sortedPeers.add(new SuperSeedPeer((PEPeer)iter.next()));
+		sortedPeers = new ArrayList<SuperSeedPeer>(peer_transports.size());
+		Iterator<PEPeerTransport> iter1 = peer_transports.iterator();
+		while(iter1.hasNext()) {
+			sortedPeers.add(new SuperSeedPeer(iter1.next()));
 		}      
 
 		Collections.sort(sortedPeers);
-		iter = sortedPeers.iterator();
-		while(iter.hasNext()) {
-			final PEPeer peer = ((SuperSeedPeer)iter.next()).peer;
+		Iterator<SuperSeedPeer> iter2 = sortedPeers.iterator();
+		while(iter2.hasNext()) {
+			final PEPeerTransport peer = ((SuperSeedPeer)iter2.next()).peer;
 			if((peer.getUniqueAnnounce() == -1) && (peer.getPeerState() == PEPeer.TRANSFERING)) {
 				selectedPeer = peer;
 				break;
@@ -3971,7 +4142,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 		selectedPeer.setUniqueAnnounce(piece.getPieceNumber());
 		superSeedModeNumberOfAnnounces++;
 		piece.pieceRevealedToPeer();
-		((PEPeerTransport)selectedPeer).sendHave(piece.getPieceNumber());		
+		selectedPeer.sendHave(piece.getPieceNumber());		
 	}
 
 	public void updateSuperSeedPiece(PEPeer peer,int pieceNumber) {
@@ -4134,14 +4305,14 @@ DiskManagerCheckRequestListener, IPFilterListener
 	{
 		//every 1 second
 		if ( mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL == 0 ){
-			final ArrayList peer_transports = peer_transports_cow;
+			final List<PEPeerTransport> peer_transports = peer_transports_cow;
 
 			int num_waiting_establishments = 0;
 
 			int udp_connections = 0;
 
 			for( int i=0; i < peer_transports.size(); i++ ) {
-				final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( i );
+				final PEPeerTransport transport = peer_transports.get( i );
 
 				//update waiting count
 				final int state = transport.getConnectionState();
@@ -4169,7 +4340,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 					for( int i=peer_transports.size()-1; i >= 0 && to_disconnect > 0; i-- ){
 
-						final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( i );
+						final PEPeerTransport transport = peer_transports.get( i );
 
 						if ( transport.isSeed()){
 
@@ -4288,10 +4459,10 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 		//every 5 seconds
 		if ( mainloop_loop_count % MAINLOOP_FIVE_SECOND_INTERVAL == 0 ) {
-			final ArrayList peer_transports = peer_transports_cow;
+			final List<PEPeerTransport> peer_transports = peer_transports_cow;
 
 			for( int i=0; i < peer_transports.size(); i++ ) {
-				final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( i );
+				final PEPeerTransport transport = peer_transports.get( i );
 
 				//check for timeouts
 				if( transport.doTimeoutChecks() )  continue;
@@ -4338,18 +4509,91 @@ DiskManagerCheckRequestListener, IPFilterListener
 		
 		for( int i=nextPEXSweepIndex; i < goal && i < sweepList.size(); i++) {
 			//System.out.println(mainloop_loop_count+" %:"+percentage+" start:"+nextPEXSweepIndex+" current:"+i+" <"+goal+"/"+sweepList.size());
-			final PEPeerTransport peer = (PEPeerTransport)sweepList.get( i );
+			final PEPeerTransport peer = sweepList.get( i );
 			peer.updatePeerExchange();
 		}
 
 		nextPEXSweepIndex = goal;
+		
+			// kick duplicate outbound connections - some users experience increasing numbers of connections to the same IP address sitting there in a 'connecting' state
+			// not sure of the exact cause unfortunately so adding this as a stop gap measure (parg, 2015/01/11)
+			// I have a suspicion this is caused by an outbound connection failing (possibly with TCP+uTP dual connects) and not resulting in overall disconnect
+			// as the user has a bunch of 'bind' exceptions in their log
+		
+		if ( mainloop_loop_count % MAINLOOP_SIXTY_SECOND_INTERVAL == 0 ){
+			
+			List<PEPeerTransport> peer_transports = peer_transports_cow;
+			
+			if ( peer_transports.size() > 1 ){
+				
+				Map<String,List<PEPeerTransport>>	peer_map = new HashMap<String, List<PEPeerTransport>>();
+				
+				for ( PEPeerTransport peer: peer_transports ){
+					
+					if ( peer.isIncoming()){
+						
+						continue;
+					}
+					
+					if ( 	peer.getPeerState() == PEPeer.CONNECTING &&
+							peer.getConnectionState() == PEPeerTransport.CONNECTION_CONNECTING &&
+							peer.getLastMessageSentTime() != 0 ){
+						
+						String key = peer.getIp() + ":" + peer.getPort();
+						
+						List<PEPeerTransport> list = peer_map.get( key );
+						
+						if ( list == null ){
+							
+							list = new ArrayList<PEPeerTransport>(1);
+							
+							peer_map.put( key, list );
+						}
+						
+						list.add( peer );
+					}
+				}
+				
+				for ( List<PEPeerTransport> list: peer_map.values()){
+					
+					if ( list.size() >= 2 ){
+						
+						long			newest_time = Long.MIN_VALUE;
+						PEPeerTransport	newest_peer	= null;
+						
+						for ( PEPeerTransport peer: list ){
+							
+							long	last_sent = peer.getLastMessageSentTime();
+							
+							if ( last_sent > newest_time ){
+								
+								newest_time = last_sent;
+								newest_peer	= peer;
+							}
+						}
+						
+						for ( PEPeerTransport peer: list ){
+							
+							if ( peer != newest_peer ){
+								
+								if ( 	peer.getPeerState() == PEPeer.CONNECTING &&
+										peer.getConnectionState() == PEPeerTransport.CONNECTION_CONNECTING ){
+								
+									closeAndRemovePeer( peer, "Removing old duplicate connection", false );
+								}
+							}
+						}
+					}
+				}
+			}
+		}
 	}
 	
 	private void
 	doUDPConnectionChecks(
 		int		number )
 	{
-		List	new_connections = null;
+		List<PEPeerTransport>	new_connections = null;
 		
 		try{
 			peer_transports_mon.enter();
@@ -4360,9 +4604,9 @@ DiskManagerCheckRequestListener, IPFilterListener
 				
 				last_udp_reconnect = now;
 				
-				Iterator it = udp_reconnects.values().iterator();
-				
-				PEPeerTransport	peer = (PEPeerTransport)it.next();
+				Iterator<PEPeerTransport> it = udp_reconnects.values().iterator();
+				 
+				PEPeerTransport	peer = it.next();
 
 				it.remove();
 
@@ -4372,7 +4616,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 				if ( new_connections == null ){
 					
-					new_connections = new ArrayList();
+					new_connections = new ArrayList<PEPeerTransport>();
 				}
 				
 				new_connections.add( peer );
@@ -4417,19 +4661,26 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 			int	to_do = Math.min( number, avail );
 
-			Iterator	it = pending_nat_traversals.values().iterator();
+			Iterator<PEPeerTransport>	it = pending_nat_traversals.values().iterator();
 
 			while( to_do > 0 && it.hasNext()){
 
-				to_do--;
-
-				final PEPeerTransport	peer = (PEPeerTransport)it.next();
+				final PEPeerTransport	peer = it.next();
 
 				it.remove();
 
+				String peer_ip = peer.getPeerItemIdentity().getAddressString();
+				
+				if ( AENetworkClassifier.categoriseAddress( peer_ip ) != AENetworkClassifier.AT_PUBLIC ){
+					
+					continue;
+				}
+				
+				to_do--;
+
 				PeerNATTraverser.getSingleton().create(
 						this,
-						new InetSocketAddress( peer.getPeerItemIdentity().getAddressString(), peer.getPeerItemIdentity().getUDPPort() ),
+						new InetSocketAddress( peer_ip, peer.getPeerItemIdentity().getUDPPort() ),
 						new PeerNATTraversalAdapter()
 						{
 							private boolean	done;
@@ -4483,7 +4734,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 				
 				for (int i=0;i<new_connections.size();i++){
 			
-					PEPeerTransport	peer_item = (PEPeerTransport)new_connections.get(i);
+					PEPeerTransport	peer_item = new_connections.get(i);
 
 						// don't call when holding monitor - deadlock potential
 					peer_item.reconnect(true, false);
@@ -4499,7 +4750,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 	public boolean doOptimisticDisconnect( boolean	pending_lan_local_peer, boolean force )
 	{
 		
-		final ArrayList peer_transports = peer_transports_cow;
+		final List<PEPeerTransport> peer_transports = peer_transports_cow;
 		PEPeerTransport max_transport = null;
 		PEPeerTransport max_seed_transport		= null;
 		PEPeerTransport max_non_lan_transport 	= null;
@@ -4514,7 +4765,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 		int	lan_peer_count	= 0;
 
 		for( int i=0; i < peer_transports.size(); i++ ) {
-			final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i );
+			final PEPeerTransport peer = peer_transports.get( i );
 
 			if( peer.getConnectionState() == PEPeerTransport.CONNECTION_FULLY_ESTABLISHED ) {
 
@@ -4680,7 +4931,7 @@ DiskManagerCheckRequestListener, IPFilterListener
 			
 			if ( peer_transports.size() > 0 ){
 				
-				PEPeerTransport pt = (PEPeerTransport)peer_transports.get( new Random().nextInt( peer_transports.size()));
+				PEPeerTransport pt = peer_transports.get( new Random().nextInt( peer_transports.size()));
 				
 				closeAndRemovePeer( pt, "force removal of random peer in doOptimisticDisconnect()", true );
 				
@@ -4718,9 +4969,9 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 
 	private boolean isAlreadyConnected( PeerItem peer_id ) {
-		final ArrayList peer_transports = peer_transports_cow;
+		final List<PEPeerTransport> peer_transports = peer_transports_cow;
 		for( int i=0; i < peer_transports.size(); i++ ) {
-			final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i );
+			final PEPeerTransport peer = peer_transports.get( i );
 			if( peer.getPeerItemIdentity().equals( peer_id ) )  return true;
 		}
 		return false;
@@ -4761,14 +5012,14 @@ DiskManagerCheckRequestListener, IPFilterListener
 	}
 	
 	public void IPBlockedListChanged(IpFilter filter) {
-		Iterator	it = peer_transports_cow.iterator();
+		Iterator<PEPeerTransport>	it = peer_transports_cow.iterator();
 		
 		String	name 	= getDisplayName();
 		byte[]	hash	= getTorrentHash();
 		
 		while( it.hasNext()){
 			try {
-  			PEPeerTransport	peer = (PEPeerTransport)it.next();
+  			PEPeerTransport	peer = it.next();
   			
   			if (filter.isInRange(peer.getIp(), name, hash )) {
   				peer.closeConnection( "IP address blocked by filters" );
@@ -4889,9 +5140,9 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 
 	public PEPeerTransport getTransportFromIdentity( byte[] peer_id ) {
-		final ArrayList	peer_transports = peer_transports_cow;      	
+		final List<PEPeerTransport>	peer_transports = peer_transports_cow;      	
 		for( int i=0; i < peer_transports.size(); i++ ) {
-			final PEPeerTransport conn = (PEPeerTransport)peer_transports.get( i );			
+			final PEPeerTransport conn = peer_transports.get( i );			
 			if( Arrays.equals( peer_id, conn.getId() ) )   return conn;
 		}
 		return null;
@@ -4914,10 +5165,10 @@ DiskManagerCheckRequestListener, IPFilterListener
 
 	public PEPeerTransport getTransportFromAddress(String peer)
 	{
-		final ArrayList peer_transports =peer_transports_cow;
+		final List<PEPeerTransport> peer_transports =peer_transports_cow;
 		for (int i =0; i <peer_transports.size(); i++)
 		{
-			final PEPeerTransport pt =(PEPeerTransport) peer_transports.get(i);
+			final PEPeerTransport pt = peer_transports.get(i);
 			if (peer.equals(pt.getIp()))
 				return pt;
 		}
@@ -4965,6 +5216,13 @@ DiskManagerCheckRequestListener, IPFilterListener
 		return( adapter.isPeerSourceEnabled( peer_source ));
 	}
 	
+	public boolean 
+	isNetworkEnabled(
+		String net ) 
+	{
+		return( adapter.isNetworkEnabled( net ));
+	}
+	
 	public void
 	peerDiscovered(
 		PEPeerTransport		finder,
@@ -5036,11 +5294,11 @@ DiskManagerCheckRequestListener, IPFilterListener
 		try{
 			peer_transports_mon.enter();
 
-			Iterator	it = pending_nat_traversals.values().iterator();
+			Iterator<PEPeerTransport>	it = pending_nat_traversals.values().iterator();
 			
 			while( it.hasNext()){
 			
-				PEPeerTransport peer = (PEPeerTransport)it.next();
+				PEPeerTransport peer = it.next();
 			
 				pending_udp += (pending_udp.length()==0?"":",") + peer.getPeerItemIdentity().getAddressString() + ":" + peer.getPeerItemIdentity().getUDPPort();
 			}
@@ -5058,13 +5316,13 @@ DiskManagerCheckRequestListener, IPFilterListener
 		
 		String	active_udp = "";
 		
-		Iterator it = traversals.iterator();
+		Iterator it1 = traversals.iterator();
 		
-		while( it.hasNext()){
+		while( it1.hasNext()){
 			
-			InetSocketAddress ad = (InetSocketAddress)it.next();
+			InetSocketAddress ad = (InetSocketAddress)it1.next();
 			
-			active_udp += (active_udp.length()==0?"":",") + ad.getAddress().getHostAddress() + ":" + ad.getPort();
+			active_udp += (active_udp.length()==0?"":",") + AddressUtils.getHostAddress( ad ) + ":" + ad.getPort();
 		}
 		
 		if ( active_udp.length() > 0 ){
@@ -5167,11 +5425,11 @@ DiskManagerCheckRequestListener, IPFilterListener
 			try{
 				writer.indent();
 
-				it = peer_transports_cow.iterator();
+				Iterator<PEPeerTransport> it2 = peer_transports_cow.iterator();
 
-				while( it.hasNext()){
+				while( it2.hasNext()){
 
-					PEPeerTransport	peer = (PEPeerTransport)it.next();
+					PEPeerTransport	peer = it2.next();
 
 					peer.generateEvidence( writer );
 				}
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/SuperSeedPeer.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/SuperSeedPeer.java
index 8eb90f7..e300c22 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/SuperSeedPeer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/SuperSeedPeer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -21,6 +22,7 @@
 package org.gudy.azureus2.core3.peer.impl.control;
 
 import org.gudy.azureus2.core3.peer.PEPeer;
+import org.gudy.azureus2.core3.peer.impl.PEPeerTransport;
 
 /**
  * @author Olivier
@@ -28,9 +30,9 @@ import org.gudy.azureus2.core3.peer.PEPeer;
  */
 public class SuperSeedPeer implements Comparable{
 
-  public PEPeer peer;
+  public PEPeerTransport peer;
   
-  public SuperSeedPeer(PEPeer peer) {
+  public SuperSeedPeer(PEPeerTransport peer) {
     this.peer = peer;
   }
   
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/SuperSeedPiece.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/SuperSeedPiece.java
index 6047118..74eac6c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/SuperSeedPiece.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/control/SuperSeedPiece.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportDebugger.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportDebugger.java
index 48164ff..0822603 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportDebugger.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportDebugger.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Oct-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportProtocol.java b/azureus2/src/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportProtocol.java
index 459f318..2de4c55 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportProtocol.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/impl/transport/PEPeerTransportProtocol.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -52,6 +53,7 @@ import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager;
 import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager;
 import com.aelitis.azureus.core.peermanager.messaging.Message;
 import com.aelitis.azureus.core.peermanager.messaging.MessageManager;
+import com.aelitis.azureus.core.peermanager.messaging.MessageStreamEncoder;
 import com.aelitis.azureus.core.peermanager.messaging.azureus.*;
 import com.aelitis.azureus.core.peermanager.messaging.bittorrent.*;
 import com.aelitis.azureus.core.peermanager.messaging.bittorrent.ltep.*;
@@ -61,6 +63,7 @@ import com.aelitis.azureus.core.peermanager.peerdb.PeerItemFactory;
 import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker;
 import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags;
 import com.aelitis.azureus.core.peermanager.utils.*;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
 import com.aelitis.azureus.core.tag.TaggableResolver;
 
 
@@ -160,11 +163,11 @@ implements PEPeerTransport
 	//Spread time (0 secs , fake default)
 	private int spreadTimeHint = 0 * 1000;
 
-	protected long last_message_sent_time = 0;
-	protected long last_message_received_time = 0;
-	protected long last_data_message_received_time = -1;
-	protected long last_good_data_time =-1;			// time data written to disk was recieved
-	protected long last_data_message_sent_time = -1;
+	private long last_message_sent_time = 0;
+	private long last_message_received_time = 0;
+	private long last_data_message_received_time = -1;
+	private long last_good_data_time =-1;			// time data written to disk was recieved
+	private long last_data_message_sent_time = -1;
 
 	private long connection_established_time = 0;
 
@@ -355,8 +358,12 @@ implements PEPeerTransport
 	// allow reconnect if we've sent or recieved at least 1 piece over the current connection
 	private boolean allowReconnect; 
 
-	
 
+	private Set<Object>		upload_disabled_set;
+	private Set<Object>		download_disabled_set;
+	private boolean			is_upload_disabled;
+	private boolean			is_download_disabled;
+	
 	private boolean is_optimistic_unchoke = false;
 
 	private PeerExchangerItem peer_exchange_item = null;
@@ -401,7 +408,7 @@ implements PEPeerTransport
 
 		InetSocketAddress notional_address = _connection.getEndpoint().getNotionalAddress();
 
-		ip    = notional_address.getAddress().getHostAddress();
+		ip    = AddressUtils.getHostAddress( notional_address );
 		port  = notional_address.getPort();
 		
 		peer_item_identity = PeerItemFactory.createPeerItem( ip, port, PeerItem.convertSourceID( _peer_source ), PeerItemFactory.HANDSHAKE_TYPE_PLAIN, 0, PeerItemFactory.CRYPTO_LEVEL_1, 0 );  //this will be recreated upon az handshake decode
@@ -473,6 +480,13 @@ implements PEPeerTransport
 						closeConnectionInternally( "connection exception: " + error.getMessage(), false, true );
 					}
 
+					public Object 
+					getConnectionProperty( 
+						String property_name )
+					{
+						return( null );
+					}
+					
 					public String
 					getDescription()
 					{
@@ -548,25 +562,41 @@ implements PEPeerTransport
     			NetworkManager.getCryptoRequired( manager.getAdapter().getCryptoLevel()); 
 
 		boolean	lan_local = isLANLocal();
-		
-		if ( lan_local ){
+
+		boolean public_net = peer_item_identity.getNetwork() == AENetworkClassifier.AT_PUBLIC;
+
+		if ( lan_local || !public_net ){
 			
-			use_crypto = false;  //dont bother with PHE for lan peers
+			use_crypto = false; // dont bother with PHE for lan peers 
+								// or non-public networks. one reason for this is that it doesn't work with i2psnark for some reason
+								// (actually the reason is that it blocks peers that send a bad message (ConnectionAcceptor:MAX_BAD) which
+								// causes the subsequent plain connection to be dropped)
+								// AND it causes a raw-message to be submitted to the outgoing message queue which
+								// then bypasses i2phelp plugin handshake modifications...
+								// note also that incoming non-public connections also ignore crypto settings
+								
 		}
 
 		InetSocketAddress	endpoint_address;
 		ProtocolEndpoint	pe1;
 		ProtocolEndpoint	pe2 = null;
-
+		
 		if ( _use_tcp ){
 
 			boolean utp_available = ProtocolEndpointFactory.isHandlerRegistered( ProtocolEndpoint.PROTOCOL_UTP );
 			
 			boolean socks_active = NetworkAdmin.getSingleton().isSocksActive();
+						
+			if ( public_net ){
+				
+				endpoint_address = new InetSocketAddress( ip, tcp_listen_port );
+				
+			}else{
+				
+				endpoint_address = InetSocketAddress.createUnresolved( ip, tcp_listen_port );
+			}
 			
-			endpoint_address = new InetSocketAddress( ip, tcp_listen_port );
-			
-			if ( lan_local || !utp_available ){
+			if ( lan_local || !utp_available || !public_net ){
 				
 				pe1 = ProtocolEndpointFactory.createEndpoint( ProtocolEndpoint.PROTOCOL_TCP, endpoint_address );
 				
@@ -588,7 +618,14 @@ implements PEPeerTransport
 			}
 		}else{
 
-			endpoint_address = new InetSocketAddress( ip, udp_listen_port );
+			if ( public_net ){
+				
+				endpoint_address = new InetSocketAddress( ip, udp_listen_port );
+				
+			}else{
+				
+				endpoint_address = InetSocketAddress.createUnresolved( ip, udp_listen_port );
+			}
 
 			pe1 = ProtocolEndpointFactory.createEndpoint( ProtocolEndpoint.PROTOCOL_UDP, endpoint_address );
 		}
@@ -757,6 +794,18 @@ implements PEPeerTransport
 						closeConnectionInternally( "connection exception: " + error.getMessage(), !connect_ok, true );
 					}
     			
+					public Object 
+					getConnectionProperty( 
+						String property_name )
+					{
+						if ( property_name == AEProxyFactory.PO_PEER_NETWORKS ){
+							
+							return( manager.getAdapter().getEnabledNetworks());
+						}
+						
+						return( null );
+					}
+					
 					public String
 					getDescription()
 					{
@@ -928,6 +977,12 @@ implements PEPeerTransport
 			recentlyDisconnected.put(mySessionID, this);
 	}
 	
+	public boolean
+	isClosed()
+	{
+		return( closing );
+	}
+	
 	public PEPeerTransport reconnect(boolean tryUDP, boolean tryIPv6) {
 		
 		boolean use_tcp = isTCP() && !(tryUDP && getUDPListenPort() > 0);
@@ -1114,7 +1169,7 @@ implements PEPeerTransport
 		
 		NetworkAdmin na = NetworkAdmin.getSingleton();
 		
-		if ( !na.isSocksActive()){
+		if ( peer_item_identity.getNetwork() == AENetworkClassifier.AT_PUBLIC && !na.isSocksActive()){
 				// don't send public address in handshake
 			InetAddress defaultV6 = na.hasIPV6Potential(true) ? na.getDefaultPublicAddressV6() : null;
 			
@@ -1166,7 +1221,7 @@ implements PEPeerTransport
 		
 		NetworkAdmin na = NetworkAdmin.getSingleton();
 		
-		if ( !na.isSocksActive()){
+		if ( peer_item_identity.getNetwork() == AENetworkClassifier.AT_PUBLIC && !na.isSocksActive()){
 				// don't send public address in handshake
 			defaultV6 = na.hasIPV6Potential(true) ? na.getDefaultPublicAddressV6() : null;
 		}
@@ -1532,31 +1587,48 @@ implements PEPeerTransport
 	 */
 	public void checkInterested()
 	{
-		if (closing ||peerHavePieces ==null ||peerHavePieces.nbSet ==0)
+		if ( closing || peerHavePieces ==null || peerHavePieces.nbSet == 0 ){
+			
 			return;
-
+		}
+		
 		boolean is_interesting = false;
-		if (piecePicker.hasDownloadablePiece())
-		{   // there is a piece worth being interested in
-			if (!isSeed() && !isRelativeSeed())
-			{   // check individually if don't have all
-				for (int i =peerHavePieces.start; i <=peerHavePieces.end; i++ )
-				{
-					if (peerHavePieces.flags[i] && diskManager.isInteresting(i))
-					{
-						is_interesting = true;
-						break;
+		
+		if ( !is_download_disabled ){
+			
+			if ( piecePicker.hasDownloadablePiece()){
+				
+					// there is a piece worth being interested in
+				
+				if (!isSeed() && !isRelativeSeed()){
+					
+						// check individually if don't have all
+					
+					for (int i = peerHavePieces.start; i <= peerHavePieces.end; i++ ){
+						
+						if ( peerHavePieces.flags[i] && diskManager.isInteresting(i)){
+							
+							is_interesting = true;
+							
+							break;
+						}
 					}
+				}else{
+					
+					is_interesting = true;
 				}
-			} else
-				is_interesting =true;
+			}
 		}
-
-		if (is_interesting &&!interested_in_other_peer)
+		
+		if ( is_interesting && !interested_in_other_peer ){
+			
 			connection.getOutgoingMessageQueue().addMessage(new BTInterested(other_peer_interested_version), false);
-		else if (!is_interesting &&interested_in_other_peer)
+			
+		}else if ( !is_interesting && interested_in_other_peer ){
+			
 			connection.getOutgoingMessageQueue().addMessage(new BTUninterested(other_peer_uninterested_version), false);
-
+		}
+		
 		interested_in_other_peer = is_interesting;
 	}
 
@@ -2104,9 +2176,10 @@ implements PEPeerTransport
 
 
 	public String toString() {
-		if( connection != null && connection.isConnected() ) {
-			return connection + (isTCP()?" [":"(UDP) [") + client+ "]";
-		}
+		// parg: removed this as we want to see the peer's IP/host, not (e.g.) a SOCKS server address if in use
+		//if( connection != null && connection.isConnected() ) {
+		//	return connection + (isTCP()?" [":"(UDP) [") + client+ "]";
+		//}
 		return (isIncoming() ? "R: " : "L: ")+ ip + ":" + port + (isTCP()?" [":"(UDP) [") + client+ "]";
 	}
 
@@ -2575,7 +2648,16 @@ implements PEPeerTransport
 			 * it we receive it repeatedly. So there - we can initialise the connection
 			 * right now. :P
 			 */
-			this.initPostConnection(handshake);
+			
+				// UNLESS (PARG, 2014/9/11) this is a metadata download in which case we MUST
+				// receive the LT handshake (with the metadata size in it) before transitioning
+				// to active...
+			
+			if ( !is_metadata_download ){
+			
+				this.initPostConnection(handshake);
+			}
+			
 			this.sendLTHandshake();
 		}
 		else {
@@ -2710,10 +2792,16 @@ implements PEPeerTransport
 				  
 				  spoofMDAvailability( mds );
 			  }
+		  }  
+		
+		  if ( current_peer_state != PEPeer.TRANSFERING ){
+			  
+			  	// this was deferred in the BT handshake decode for metadata downloads...
+			  
+			  initPostConnection( null );
 		  }
 	  }
 	  
-	  
 	  /**
 	   * Grr... this is one thing which I'm sure I had figured out much better than it is here...
 	   * Basically, we "initialise" the connection at the BT handshake stage, because the LT handshake
@@ -2901,7 +2989,9 @@ implements PEPeerTransport
 		changePeerState(PEPeer.TRANSFERING);
 		connection_state = PEPeerTransport.CONNECTION_FULLY_ESTABLISHED;
 		sendBitField();
-		handshake.destroy();
+		if ( handshake != null ){
+			handshake.destroy();
+		}
 		addAvailability();
 		sendMainlineDHTPort();
   	}
@@ -3107,8 +3197,10 @@ implements PEPeerTransport
 		MainlineDHTProvider provider = getDHTProvider();
 		if (provider == null) {return;}
 		
-		try {provider.notifyOfIncomingPort(getIp(), i_port);}
-		catch (Throwable t) {Debug.printStackTrace(t);}	
+		if ( AENetworkClassifier.categoriseAddress( getIp()) == AENetworkClassifier.AT_PUBLIC ){
+			try {provider.notifyOfIncomingPort(getIp(), i_port);}
+			catch (Throwable t) {Debug.printStackTrace(t);}	
+		}
 	}
 
 	protected void decodeChoke( BTChoke choke ) {    
@@ -3152,6 +3244,7 @@ implements PEPeerTransport
 		other_peer_interested_in_me = !(isSeed() || isRelativeSeed());
 		
 		if ( 	other_peer_interested_in_me && 
+				!is_upload_disabled && 
 				fast_unchoke_new_peers &&
 				isChokedByMe() && 
 				getData( "fast_unchoke_done" ) == null ){
@@ -3199,7 +3292,7 @@ implements PEPeerTransport
 
 		if (!peerHavePieces.flags[pieceNumber])
 		{
-			if (!interested_in_other_peer &&diskManager.isInteresting(pieceNumber))
+			if (!interested_in_other_peer &&diskManager.isInteresting(pieceNumber)&&!is_download_disabled)
 			{
                 connection.getOutgoingMessageQueue().addMessage(new BTInterested(other_peer_interested_version), false);
 				interested_in_other_peer =true;
@@ -3255,7 +3348,7 @@ implements PEPeerTransport
         
 	        	new_have	= true;
 	        	
-	            if (	!( send_interested || interested_in_other_peer ) &&
+	            if (	!( send_interested || interested_in_other_peer || is_download_disabled ) &&
 	            		diskManager.isInteresting(pieceNumber)){
 
 	            	send_interested = true;
@@ -3401,45 +3494,52 @@ implements PEPeerTransport
 			return;
 		}
 		
-		boolean	request_ok = false;
+		boolean	request_ok = !is_upload_disabled;
 		
-		if ( choking_other_peer ){
+		if ( request_ok ){
 			
-			try{
-				general_mon.enter();
-				
-				int[][] pieces = (int[][])getUserData( KEY_ALLOWED_FAST_SENT );
-				
-				if ( pieces != null ){
+			if ( choking_other_peer ){
 				
-					for (int i=0;i<pieces.length;i++){
-						
-						if ( pieces[i][0] == number ){
+				try{
+					general_mon.enter();
+					
+					int[][] pieces = (int[][])getUserData( KEY_ALLOWED_FAST_SENT );
+					
+					if ( pieces != null ){
+					
+						for (int i=0;i<pieces.length;i++){
 							
-							if ( pieces[i][1] >= length ){
+							if ( pieces[i][0] == number ){
 								
-								 pieces[i][1] -= length;
-								 
-								 if ( DEBUG_FAST ){
-									 System.out.println( "Permitting fast-allowed request for " + number + "/" + offset + "/" + length + " to " + getIp());
-								 }
-								 
-								 request_ok = true;
-								 
-								 createPieceMessageHandler();
-								 
-								 break;
+								if ( pieces[i][1] >= length ){
+									
+									 pieces[i][1] -= length;
+									 
+									 if ( DEBUG_FAST ){
+										 System.out.println( "Permitting fast-allowed request for " + number + "/" + offset + "/" + length + " to " + getIp());
+									 }
+									 
+									 request_ok = true;
+									 
+									 createPieceMessageHandler();
+									 								 
+									 break;
+									 
+								}else{
+									
+									manager.reportBadFastExtensionUse( this );
+								}
 							}
-						}
-					}			
+						}			
+					}
+				}finally{
+					
+					general_mon.exit();
 				}
-			}finally{
+			}else{
 				
-				general_mon.exit();
+				request_ok = true;
 			}
-		}else{
-			
-			request_ok = true;
 		}
 		
 		if ( request_ok ){
@@ -3828,6 +3928,7 @@ implements PEPeerTransport
 		BitFlags	flags )
 	{		
 		if ( 	fast_extension_enabled &&
+				!is_upload_disabled &&
 				!(isSeed() || isRelativeSeed()) &&
 				PeerClassifier.fullySupportsFE( client_peer_id )){
 			
@@ -3838,6 +3939,11 @@ implements PEPeerTransport
 				return;
 			}
 			
+			if ( !manager.isFastExtensionPermitted( this )){
+				
+				return;
+			}
+			
 			int[][] pieces;
 			
 			try{
@@ -4064,6 +4170,13 @@ implements PEPeerTransport
 						return true;
 					}
 
+						// generic handling of az-style PEX (e.g. used by non-public net)
+					
+					if ( message instanceof AZStylePeerExchange ){
+						decodePeerExchange((AZStylePeerExchange)message );
+						return true;
+					}
+					
 					if( message_id.equals( AZMessage.ID_AZ_REQUEST_HINT ) ) {        	
 						decodeAZRequestHint( (AZRequestHint)message );
 						return true;
@@ -4207,6 +4320,154 @@ implements PEPeerTransport
 		connection.removeRateLimiter( limiter, upload );
 	}
 
+	public void
+	setUploadDisabled(
+		Object		key,
+		boolean		disabled )
+	{
+		synchronized( this ){
+			
+			if ( upload_disabled_set == null ){
+				
+				if ( disabled ){
+					
+					upload_disabled_set = new HashSet<Object>();
+					
+					upload_disabled_set.add( key );
+					
+				}else{
+					
+					Debug.out( "derp" );
+				}
+			}else{
+				
+				if ( disabled ){
+					
+					if ( !upload_disabled_set.add( key )){
+						
+						Debug.out( "derp" );
+					}
+					
+				}else{
+					
+					if ( !upload_disabled_set.remove( key )){
+						
+						Debug.out( "derp" );
+					}
+					
+					if ( upload_disabled_set.size() == 0 ){
+						
+						upload_disabled_set = null;
+					}
+				}
+			}
+						
+			is_upload_disabled = upload_disabled_set != null;
+					
+			//System.out.println( "setUploadDisabled " + getIp() + " -> " + (upload_disabled_set==null?0:upload_disabled_set.size()));
+		}	
+	}
+	
+	public void
+	setDownloadDisabled(
+		Object		key,
+		boolean		disabled )
+	{
+		boolean	check = false;
+		
+		synchronized( this ){
+			
+			if ( download_disabled_set == null ){
+				
+				if ( disabled ){
+					
+					download_disabled_set = new HashSet<Object>();
+					
+					download_disabled_set.add( key );
+					
+				}else{
+					
+					Debug.out( "derp" );
+				}
+			}else{
+				
+				if ( disabled ){
+					
+					if ( !download_disabled_set.add( key )){
+						
+						Debug.out( "derp" );
+					}
+					
+				}else{
+					
+					if ( !download_disabled_set.remove( key )){
+						
+						Debug.out( "derp" );
+					}
+					
+					if ( download_disabled_set.size() == 0 ){
+						
+						download_disabled_set = null;
+					}
+				}
+			}
+		
+			boolean	old = is_download_disabled;
+			
+			is_download_disabled = download_disabled_set != null;
+			
+			check = old != is_download_disabled;
+			
+			//System.out.println( "setDownloadDisabled " + getIp() + " -> " + (download_disabled_set==null?0:download_disabled_set.size()));
+		}
+		
+		if ( check ){
+			checkInterested();
+		}
+	}
+	
+	public boolean
+	isUploadDisabled()
+	{
+		return( is_upload_disabled );
+	}
+	
+	public boolean
+	isUploadDisabled(
+		Object		key )
+	{
+		synchronized( this ){
+			
+			if ( upload_disabled_set == null ){
+		
+				return( false );
+			}
+			
+			return( upload_disabled_set.contains( key ));
+		}
+	}
+	
+	public boolean
+	isDownloadDisabled()
+	{
+		return( is_download_disabled );
+	}
+	
+	public boolean
+	isDownloadDisabled(
+		Object		key )
+	{
+		synchronized( this ){
+			
+			if ( download_disabled_set == null ){
+		
+				return( false );
+			}
+			
+			return( download_disabled_set.contains( key ));
+		}
+	}
+	
 	public Connection getPluginConnection() {
 		return plugin_connection;
 	}
@@ -4370,15 +4631,33 @@ implements PEPeerTransport
 				pex_item = peer_exchange_item = manager.createPeerExchangeConnection( this );
 			}
 			
-			if( pex_item != null ) {
-				//check for peer exchange support
-				if(ut_pex_enabled || peerSupportsMessageType(AZMessage.ID_AZ_PEER_EXCHANGE)) {
+			if ( pex_item != null ){
+				
+					//check for peer exchange support
+				
+				if ( ut_pex_enabled || peerSupportsMessageType(AZMessage.ID_AZ_PEER_EXCHANGE )){
+					
 					peer_exchange_supported = true;
 					
 					pex_item.enableStateMaintenance();
-				}
-				else {  //no need to maintain internal states as we wont be sending/receiving peer exchange messages
-					pex_item.disableStateMaintenance();
+					
+				}else{
+					
+					MessageStreamEncoder encoder = connection.getOutgoingMessageQueue().getEncoder();
+					
+					if ( 	encoder instanceof LTMessageEncoder && 
+							((LTMessageEncoder)encoder).hasCustomExtensionHandler( LTMessageEncoder.CET_PEX )){
+						
+						peer_exchange_supported = true;
+						
+						pex_item.enableStateMaintenance();
+						
+					}else{
+				
+							//no need to maintain internal states as we wont be sending/receiving peer exchange messages
+						
+						pex_item.disableStateMaintenance();
+					}
 				}
 			}
 		}
@@ -4441,15 +4720,27 @@ implements PEPeerTransport
 	    PeerExchangerItem pex_item = peer_exchange_item;
 
 		if( pex_item != null && manager.isPeerExchangeEnabled()) {
-			final PeerItem[] adds = pex_item.getNewlyAddedPeerConnections();
-			final PeerItem[] drops = pex_item.getNewlyDroppedPeerConnections();  
-
-			if( (adds != null && adds.length > 0) || (drops != null && drops.length > 0) ) {
-				if (ut_pex_enabled) {
-					connection.getOutgoingMessageQueue().addMessage( new UTPeerExchange(adds, drops, null, (byte)0), false);
+			
+			if ( peer_item_identity.getNetwork() == AENetworkClassifier.AT_PUBLIC ){
+		
+				final PeerItem[] adds = pex_item.getNewlyAddedPeerConnections( AENetworkClassifier.AT_PUBLIC );
+				final PeerItem[] drops = pex_item.getNewlyDroppedPeerConnections( AENetworkClassifier.AT_PUBLIC );  
+	
+				if( (adds != null && adds.length > 0) || (drops != null && drops.length > 0) ) {
+					if (ut_pex_enabled) {
+						connection.getOutgoingMessageQueue().addMessage( new UTPeerExchange(adds, drops, null, (byte)0), false);
+					}
+					else {
+						connection.getOutgoingMessageQueue().addMessage( new AZPeerExchange( manager.getHash(), adds, drops, other_peer_pex_version ), false );
+					}
 				}
-				else {
-					connection.getOutgoingMessageQueue().addMessage( new AZPeerExchange( manager.getHash(), adds, drops, other_peer_pex_version ), false );
+			}else{
+				
+				MessageStreamEncoder encoder = connection.getOutgoingMessageQueue().getEncoder();
+				
+				if ( encoder instanceof LTMessageEncoder ){
+
+					((LTMessageEncoder)encoder).handleCustomExtension( LTMessageEncoder.CET_PEX, new Object[]{ pex_item });
 				}
 			}
 		}
@@ -4906,6 +5197,12 @@ implements PEPeerTransport
 		return( connection.getOutgoingMessageQueue().getPercentDoneOfCurrentMessage());
 	}
 
+	public long
+	getLastMessageSentTime()
+	{
+		return( last_message_sent_time );
+	}
+	
 	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.core3.logging.LogRelation#getLogRelationText()
 	 */
@@ -4959,11 +5256,85 @@ implements PEPeerTransport
 	}
 
 
-	public void setUploadRateLimitBytesPerSecond( int bytes ){ connection.setUploadLimit( bytes ); }
-	public void setDownloadRateLimitBytesPerSecond( int bytes ){ connection.setDownloadLimit( bytes ); }
-	public int getUploadRateLimitBytesPerSecond(){ return connection.getUploadLimit(); }
-	public int getDownloadRateLimitBytesPerSecond(){ return connection.getDownloadLimit(); }
+	public void 
+	setUploadRateLimitBytesPerSecond( 
+		int 	bytes )
+	{ 
+		if ( bytes == -1 ){
+			
+			if ( !isUploadDisabled( PEPeerTransport.class )){
+				
+				setUploadDisabled( PEPeerTransport.class, true );
+			
+				connection.setUploadLimit( 0 );
+			}
+		}else{
+		
+			if ( is_upload_disabled ){
+				
+				if ( isUploadDisabled( PEPeerTransport.class )){
+				
+					setUploadDisabled( PEPeerTransport.class, false );
+				}
+			}
+			
+			connection.setUploadLimit( bytes );
+		}
+	}
+	
+	public int 
+	getUploadRateLimitBytesPerSecond()
+	{ 
+		if ( is_upload_disabled ){
+			
+			if ( isUploadDisabled( PEPeerTransport.class )){
+				
+				return( -1 );
+			}
+		}
+		
+		return connection.getUploadLimit(); 
+	}
+	
+	public void 
+	setDownloadRateLimitBytesPerSecond( 
+		int 	bytes )
+	{ 
+		if ( bytes == -1 ){
+			
+			if ( !isDownloadDisabled( PEPeerTransport.class )){
+				
+				setDownloadDisabled( PEPeerTransport.class, true );
+			
+				connection.setDownloadLimit( 0 );
+			}
+		}else{
+		
+			if ( is_download_disabled ){
+				
+				if ( isDownloadDisabled( PEPeerTransport.class )){
+				
+					setDownloadDisabled( PEPeerTransport.class, false );
+				}
+			}
+			
+			connection.setDownloadLimit( bytes );
+		}
+	}
 	
+	public int 
+	getDownloadRateLimitBytesPerSecond()
+	{ 
+		if ( is_download_disabled ){
+			
+			if ( isDownloadDisabled( PEPeerTransport.class )){
+				
+				return( -1 );
+			}
+		}
+		
+		return connection.getDownloadLimit(); 
+	}
 	
 	public String getClientNameFromPeerID() {return this.client_peer_id;}
 	public String getClientNameFromExtensionHandshake() {
@@ -5013,41 +5384,44 @@ implements PEPeerTransport
 		List<Integer>	res = new ArrayList<Integer>();
 							
 		try{
-			byte[]	address = InetAddress.getByName( ip ).getAddress();
-			
-				// no IPv6 support yet
-
-			if ( address.length == 4 ){
-				
-				byte[]	bytes = new byte[24];
-				
-				System.arraycopy( address, 0, bytes, 0, 3 );
-				System.arraycopy( hash, 0, bytes, 4, 20 );
+			if ( AENetworkClassifier.categoriseAddress( ip ) == AENetworkClassifier.AT_PUBLIC ){
 				
-				num_required = Math.min( num_required, num_pieces );
+				byte[]	address = InetAddress.getByName( ip ).getAddress();
 				
-				while( res.size() < num_required ){
+					// no IPv6 support yet
+	
+				if ( address.length == 4 ){
 					
-					bytes = new SHA1Simple().calculateHash( bytes );
+					byte[]	bytes = new byte[24];
 					
-					int	pos = 0;
-				
-					while( pos < 20 && res.size() < num_required ){
-						
-						long	index = (bytes[pos++] << 24 )&0xff000000L | 
-										(bytes[pos++] << 16 )&0x00ff0000L | 
-										(bytes[pos++] << 8  )&0x0000ff00L | 
-										bytes[pos++]&0x000000ffL;
-		
-						Integer i = new Integer((int)( index%num_pieces ));
+					System.arraycopy( address, 0, bytes, 0, 3 );
+					System.arraycopy( hash, 0, bytes, 4, 20 );
+					
+					num_required = Math.min( num_required, num_pieces );
+					
+					while( res.size() < num_required ){
 						
-						if ( !res.contains(i)){
+						bytes = new SHA1Simple().calculateHash( bytes );
 						
-							res.add( i );
+						int	pos = 0;
+					
+						while( pos < 20 && res.size() < num_required ){
+							
+							long	index = (bytes[pos++] << 24 )&0xff000000L | 
+											(bytes[pos++] << 16 )&0x00ff0000L | 
+											(bytes[pos++] << 8  )&0x0000ff00L | 
+											bytes[pos++]&0x000000ffL;
+			
+							Integer i = new Integer((int)( index%num_pieces ));
+							
+							if ( !res.contains(i)){
+							
+								res.add( i );
+							}
 						}
 					}
 				}
-			}
+			}	
 		}catch( Throwable e ){
 			
 			Debug.out( "Fast set generation failed", e );
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerIdentityDataID.java b/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerIdentityDataID.java
index c4aa4fe..bd53ec0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerIdentityDataID.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerIdentityDataID.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Oct-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerIdentityManager.java b/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerIdentityManager.java
index f0523fe..1c04b70 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerIdentityManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerIdentityManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Mar 18, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peer.util;
diff --git a/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerUtils.java b/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerUtils.java
index 195bd07..339bf75 100644
--- a/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerUtils.java
+++ b/azureus2/src/org/gudy/azureus2/core3/peer/util/PeerUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on Mar 20, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.peer.util;
@@ -26,14 +23,18 @@ import java.util.*;
 
 import org.gudy.azureus2.core3.config.*;
 import org.gudy.azureus2.core3.peer.PEPeer;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.CRC32C;
 import org.gudy.azureus2.core3.util.Constants;
 import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.HostNameToIPResolver;
 import org.gudy.azureus2.core3.util.SystemTime;
 import org.gudy.azureus2.plugins.peers.Peer;
 import org.gudy.azureus2.plugins.utils.LocationProvider;
 import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
 
 import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
 
 
 /**
@@ -77,6 +78,258 @@ public class PeerUtils {
   	   	
   	MAX_CONNECTIONS_TOTAL = COConfigurationManager.getIntParameter(CONFIG_MAX_CONN_TOTAL);
    }
+   
+   private static final NetworkAdmin	network_admin;
+   
+   private static volatile long		na_last_ip4_time;
+   private static volatile long		na_last_ip6_time;
+   private static volatile byte[]	na_last_ip4;
+   private static volatile byte[]	na_last_ip6;
+
+   private static int	na_tcp_port;
+   
+   static{
+	   NetworkAdmin temp = null;
+	   
+	   try{
+		   temp = NetworkAdmin.getSingleton();
+		   
+	   }catch( Throwable e ){
+	   }
+	   
+	   network_admin = temp;
+	   
+	   COConfigurationManager.addAndFireParameterListener(
+			 "TCP.Listen.Port",
+			 new ParameterListener() 
+			 {	
+				public void 
+				parameterChanged(
+					String parameterName ) 
+				{
+					na_tcp_port = COConfigurationManager.getIntParameter( parameterName );
+				}
+			});
+   }
+   
+   public static int
+   getPeerPriority(
+	   String 	address,
+	   int		port )
+   {
+	   if ( network_admin == null ){
+		   
+		   return( 0 );
+	   }
+	   
+	   try{
+	   
+		   InetAddress ia = HostNameToIPResolver.syncResolve( address );
+		   
+		   if ( ia != null ){
+			   
+			   return( getPeerPriority( ia, port ));
+		   }
+		   
+	   }catch( Throwable e ){
+	   }
+	   
+	   return( 0 );
+   }
+   
+
+   
+   public static int
+   getPeerPriority(
+		InetAddress		address,
+		int				peer_port )
+   { 
+	  return( getPeerPriority( address.getAddress(), peer_port ));
+   }
+   
+   public static int
+   getPeerPriority(
+		byte[]		peer_address,
+		short		peer_port )
+   {
+	   return( getPeerPriority( peer_address, ((int)peer_port)&0xffff ));
+   }
+   
+   public static int
+   getPeerPriority(
+		byte[]		peer_address,
+		int			peer_port )
+   {
+	   if ( network_admin == null ){
+		   
+		   return( 0 );
+	   }
+
+	   if ( peer_address == null ){
+		   
+		   return( 0 );
+	   }
+	   
+	   byte[] my_address = null;
+	   
+	   long now = SystemTime.getMonotonousTime();
+	   
+	   if ( peer_address.length == 4 ){
+		   
+		   if ( na_last_ip4 != null && now - na_last_ip4_time < 120*1000 ){
+			   
+			   my_address = na_last_ip4;
+			   
+		   }else{
+			  
+			   if ( na_last_ip4_time == 0 || now - na_last_ip4_time > 10*1000 ){
+			   
+				   na_last_ip4_time = now;
+				   
+				   InetAddress ia = network_admin.getDefaultPublicAddress( true );
+				   
+				   if ( ia != null ){
+					   
+					   byte[] iab = ia.getAddress();
+					   
+					   if ( iab != null ){
+						   
+						   na_last_ip4 = my_address = ia.getAddress();
+					   }
+				   }
+			   }
+		   }  
+		   
+		   if ( my_address == null ){
+			   
+			   my_address = na_last_ip4;
+		   }
+	   }else if ( peer_address.length == 16 ){
+		   
+		   if ( na_last_ip6 != null && now - na_last_ip6_time < 120*1000 ){
+			   
+			   my_address = na_last_ip6;
+			   
+		   }else{
+			  
+			   if ( na_last_ip6_time == 0 || now - na_last_ip6_time > 10*1000 ){
+			   
+				   na_last_ip6_time = now;
+				   
+				   InetAddress ia = network_admin.getDefaultPublicAddressV6( true );
+				   
+				   if ( ia != null ){
+					   
+					   byte[] iab = ia.getAddress();
+					   
+					   if ( iab != null ){
+						   
+						   na_last_ip6 = my_address = ia.getAddress();
+					   }
+				   }
+			   }
+		   } 
+		   
+		   if ( my_address == null ){
+			   
+			   my_address = na_last_ip6;
+		   }
+	   }else{
+		   
+		   return( 0 );
+	   }
+	   
+	   if ( my_address != null && my_address.length == peer_address.length ){
+		   
+		   return( getPeerPriority( my_address, na_tcp_port, peer_address, peer_port ));
+		   
+	   }else{
+		   
+		   return( 0 );
+	   }
+   }
+   
+   private static int
+   getPeerPriority(
+		 byte[]		a1,
+		 int		port1,
+		 byte[]		a2,
+		 int		port2 )
+   {
+	   		// http://www.bittorrent.org/beps/bep_0040.html
+	   	   
+	   byte[] a1_masked = new byte[a1.length];
+	   byte[] a2_masked = new byte[a2.length];
+	   	   
+	   /*
+	   The formula to be used in prioritizing peers is this:
+
+	   priority = crc32-c(sort(masked_client_ip, masked_peer_ip))
+	   If the IP addresses are the same, the port numbers (16-bit integers) should be used instead:
+
+	   priority = crc32-c(sort(client_port, peer_port))
+	   For an IPv4 address, the mask to be used should be FF.FF.55.55 unless the IP addresses are in the same /16. 
+	   In that case, the mask to be used should be FF.FF.FF.55. If the IP addresses are in the same /24, the entire address should be used (mask FF.FF.FF.FF).
+
+	   For an IPv6 address, the mask should be derived in the same way, beginning with FFFF:FFFF:FFFF:5555:5555:5555:5555:5555. 
+	   If the IP addresses are in the same /48, the mask to be used should be FFFF:FFFF:FFFF:FF55:5555:5555:5555:5555. 
+	   If the IP addresses are in the same /56, the mask to be used should be FFFF:FFFF:FFFF:FFFF:5555:5555:5555:5555, etc...
+	   */
+	   
+	   int x = a1_masked.length==4?1:5;
+	   
+	   boolean	same = true;
+
+	   int order = 0;
+	   
+	   for ( int i=0;i<a1_masked.length;i++){
+		   byte	a1_byte = a1[i];
+		   byte	a2_byte = a2[i];
+
+		   if ( i < x || same ){
+			   a1_masked[i] = a1_byte;
+			   a2_masked[i] = a2_byte;
+		   }else{
+			   a1_masked[i] = (byte)(a1_byte&0x55);
+			   a2_masked[i] = (byte)(a2_byte&0x55);
+		   }
+		   
+		   if ( i >= x && same ){
+			   same = a1_byte == a2_byte;
+		   }
+		   
+		   if ( order == 0 ){
+			  			   
+			   order = (a1_masked[i]&0xff) - (a2_masked[i]&0xff);
+		   }
+	   }
+	   
+	   if ( same ){
+		   
+		   a1_masked = new byte[]{ (byte)(port1>>8), (byte)port1 };
+		   a2_masked = new byte[]{ (byte)(port2>>8), (byte)port2 };
+		   
+		   order = port1 - port2;
+	   }
+	   
+	   CRC32C crc32 = new CRC32C();
+	   
+	   if ( order < 0 ){
+		   
+		   crc32.updateWord( a1_masked, true );
+		   crc32.updateWord( a2_masked, true );
+		   
+	   }else{
+		   
+		   crc32.updateWord( a2_masked, true );
+		   crc32.updateWord( a1_masked, true );
+	   }
+	   
+	   long res = crc32.getValue();
+	   
+	   return( (int)res );
+   }
+   
   /**
    * Get the number of new peer connections allowed for the given data item,
    * within the configured per-torrent and global connection limits.
@@ -292,19 +545,36 @@ public class PeerUtils {
 			
 			if ( lp != null ){
 				
-				try{				
-					InetAddress peer_address = InetAddress.getByName( peer.getIp());
-					
-					String code = lp.getISO3166CodeForIP( peer_address );
-					String name = lp.getCountryNameForIP( peer_address, Locale.getDefault());
-					
-					if ( code != null && name != null ){
+				try{
+					String ip = peer.getIp();
+										
+					if ( HostNameToIPResolver.isDNSName( ip )){
 						
-						details = new String[]{ code, name };
+						InetAddress peer_address = HostNameToIPResolver.syncResolve( ip );
 						
+						String code = lp.getISO3166CodeForIP( peer_address );
+						String name = lp.getCountryNameForIP( peer_address, Locale.getDefault());
+						
+						if ( code != null && name != null ){
+							
+							details = new String[]{ code, name };
+							
+						}else{
+							
+							details = new String[0];
+						}
 					}else{
 						
-						details = new String[0];
+						String cat =  AENetworkClassifier.categoriseAddress( ip );
+						
+						if ( cat != AENetworkClassifier.AT_PUBLIC ){
+							
+							details = new String[]{ cat, cat };
+							
+						}else{
+							
+							details = new String[0];
+						}
 					}
 					
 					peer.setUserData( country_key, details );
@@ -316,4 +586,38 @@ public class PeerUtils {
 		
 		return( details );
 	}
+	
+	/*
+	public static void
+	main(
+		String[]	args )
+	{
+	
+		// If the client is 123.213.32.10 and the peer is 98.76.54.32, the hash that they should both arrive at is crc32-c(624C14007BD50000) or BB97323E.
+		// If the client is 123.213.32.10 and the peer is 123.213.32.234, the hash that they should both arrive at is crc32-c[(7BD5200A7BD520EA) or C816B840.
+	
+		
+		CRC32C crc = new CRC32C();
+		
+		crc.update("The quick brown fox jumps over the lazy dog".getBytes());
+		
+		System.out.println( Long.toString( crc.getValue(), 16 ));
+		
+		try{
+			if ( getPeerPriority( InetAddress.getByName( "123.213.32.10" ).getAddress(), 10,   InetAddress.getByName( "98.76.54.32" ).getAddress(), 10 ) != 0xBB97323E ){
+				
+				System.out.println( "derp1" );
+			}
+			if ( getPeerPriority( InetAddress.getByName( "123.213.32.10" ).getAddress(), 10,   InetAddress.getByName( "123.213.32.234" ).getAddress(), 10 ) != 0xC816B840 ){
+				System.out.println( "derp2" );
+			}
+			if ( getPeerPriority( InetAddress.getByName( "123.213.32.10" ).getAddress(), 10,   InetAddress.getByName( "123.213.32.10" ).getAddress(), 20 ) != 1879809021 ){
+				System.out.println( "derp3" );
+			}
+		}catch( Throwable e ){
+			e.printStackTrace();
+			
+		}
+	}
+	*/
 }
diff --git a/azureus2/src/org/gudy/azureus2/core3/security/SECertificateListener.java b/azureus2/src/org/gudy/azureus2/core3/security/SECertificateListener.java
index e46d95b..fd9b998 100644
--- a/azureus2/src/org/gudy/azureus2/core3/security/SECertificateListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/security/SECertificateListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/security/SEKeyDetails.java b/azureus2/src/org/gudy/azureus2/core3/security/SEKeyDetails.java
index 5a72e4b..30ab224 100644
--- a/azureus2/src/org/gudy/azureus2/core3/security/SEKeyDetails.java
+++ b/azureus2/src/org/gudy/azureus2/core3/security/SEKeyDetails.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/security/SEPasswordListener.java b/azureus2/src/org/gudy/azureus2/core3/security/SEPasswordListener.java
index 330c42a..e0739ef 100644
--- a/azureus2/src/org/gudy/azureus2/core3/security/SEPasswordListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/security/SEPasswordListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/security/SESecurityManager.java b/azureus2/src/org/gudy/azureus2/core3/security/SESecurityManager.java
index 9069e2e..8cd1a94 100644
--- a/azureus2/src/org/gudy/azureus2/core3/security/SESecurityManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/security/SESecurityManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -98,6 +99,12 @@ SESecurityManager
 		return( SESecurityManagerImpl.getSingleton().getSSLServerSocketFactory());
 	}
 	
+	public static TrustManagerFactory
+	getTrustManagerFactory()
+	{
+		return( SESecurityManagerImpl.getSingleton().getTrustManagerFactory());
+	}
+	
 	public static SSLSocketFactory
 	getSSLSocketFactory()
 	{
diff --git a/azureus2/src/org/gudy/azureus2/core3/security/impl/SESecurityManagerBC.java b/azureus2/src/org/gudy/azureus2/core3/security/impl/SESecurityManagerBC.java
index 97997fe..05065dd 100644
--- a/azureus2/src/org/gudy/azureus2/core3/security/impl/SESecurityManagerBC.java
+++ b/azureus2/src/org/gudy/azureus2/core3/security/impl/SESecurityManagerBC.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/security/impl/SESecurityManagerImpl.java b/azureus2/src/org/gudy/azureus2/core3/security/impl/SESecurityManagerImpl.java
index d82120e..092e564 100644
--- a/azureus2/src/org/gudy/azureus2/core3/security/impl/SESecurityManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/security/impl/SESecurityManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -469,36 +470,50 @@ SESecurityManagerImpl
 		String		host,
 		int			port )
 	{
-			// special case for socks auth when user is explicitly "<none>" as some servers seem to cause
-			// a password prompt when no auth defined and java doesn't cache a successful blank response
-			// thus causing repetitive prompts
-		
-		if ( protocol.toLowerCase().startsWith( "socks" )){
-
-			String	socks_user 	= COConfigurationManager.getStringParameter( "Proxy.Username" ).trim();
-			String	socks_pw	= COConfigurationManager.getStringParameter( "Proxy.Password" ).trim();
-
-			if ( socks_user.equalsIgnoreCase( "<none>" )){
-				
-				return( new PasswordAuthentication( "", "".toCharArray()));
-			}
+		try{
+			URL	tracker_url = new URL( protocol + "://" + host + ":" + port + "/" );
 			
-				// actually getting all sorts of problems with Java not caching socks passwords
-				// properly so I've abandoned prompting for them and always use the defined
-				// password
+				// special case for socks auth when user is explicitly "<none>" as some servers seem to cause
+				// a password prompt when no auth defined and java doesn't cache a successful blank response
+				// thus causing repetitive prompts
 			
-			if ( socks_user.length() == 0 ){
+			if ( protocol.toLowerCase().startsWith( "socks" )){
+	
+					// give explicit thread-based listeners a chance to override the hack			
+				
+				SEPasswordListener	thread_listener = (SEPasswordListener)tls.get();
+				
+				if ( thread_listener != null ){
+					
+					PasswordAuthentication temp = thread_listener.getAuthentication( realm, tracker_url);
+					
+					if ( temp != null ){
+						
+						return( temp );
+					}
+				}
+
+				String	socks_user 	= COConfigurationManager.getStringParameter( "Proxy.Username" ).trim();
+				String	socks_pw	= COConfigurationManager.getStringParameter( "Proxy.Password" ).trim();
+	
+				if ( socks_user.equalsIgnoreCase( "<none>" )){
+					
+					return( new PasswordAuthentication( "", "".toCharArray()));
+				}
+				
+					// actually getting all sorts of problems with Java not caching socks passwords
+					// properly so I've abandoned prompting for them and always use the defined
+					// password
 				
-				Logger.log(
-					new LogAlert(false, LogAlert.AT_WARNING, "Socks server is requesting authentication, please setup user and password in config" ));
+				if ( socks_user.length() == 0 ){
+					
+					Logger.log(
+						new LogAlert(false, LogAlert.AT_WARNING, "Socks server is requesting authentication, please setup user and password in config" ));
+				}
+				
+				return( new PasswordAuthentication(  socks_user, socks_pw.toCharArray()));
 			}
-			
-			return( new PasswordAuthentication(  socks_user, socks_pw.toCharArray()));
-		}
-		
-		try{			
-			URL	tracker_url = new URL( protocol + "://" + host + ":" + port + "/" );
-		
+				
 			return( getPasswordAuthentication( realm, tracker_url ));
 			
 		}catch( MalformedURLException e ){
@@ -766,6 +781,32 @@ SESecurityManagerImpl
 		return( SESecurityManagerBC.createSelfSignedCertificate( this, alias, cert_dn, strength ));
 	}
 	
+	public TrustManagerFactory
+	getTrustManagerFactory()
+	{
+		try{
+			this_mon.enter();
+		
+			KeyStore keystore = getTrustStore();
+						
+			TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+			
+			tmf.init(keystore);
+			
+			return( tmf );
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( null );
+			
+		}finally{
+			
+			this_mon.exit();
+		}	
+	}
+	
 	public SSLSocketFactory
 	getSSLSocketFactory()
 	{
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterFactory.java b/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterFactory.java
index 76949d7..863b10e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterPeriodic.java b/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterPeriodic.java
index 8f3f392..51e5aed 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterPeriodic.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterPeriodic.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterStreamer.java b/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterStreamer.java
index 62aa4b1..2d8bcee 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterStreamer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/StatsWriterStreamer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterImpl.java b/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterImpl.java
index f976df3..d3a8211 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterPeriodicImpl.java b/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterPeriodicImpl.java
index 3aec5f4..4637b7c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterPeriodicImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterPeriodicImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterStreamerImpl.java b/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterStreamerImpl.java
index 193e6d8..5d6dc11 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterStreamerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/impl/StatsWriterStreamerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/GeneralStats.java b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/GeneralStats.java
index 2b81fa3..f308323 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/GeneralStats.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/GeneralStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/LongTermStats.java b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/LongTermStats.java
index 8c1c4d6..fbac67d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/LongTermStats.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/LongTermStats.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/LongTermStatsListener.java b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/LongTermStatsListener.java
index 68c9d21..4d5a869 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/LongTermStatsListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/LongTermStatsListener.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/OverallStats.java b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/OverallStats.java
index 104cff3..d5b2054 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/OverallStats.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/OverallStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/StatsFactory.java b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/StatsFactory.java
index a58d566..3189236 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/StatsFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/StatsFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/impl/LongTermStatsImpl.java b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/impl/LongTermStatsImpl.java
index 0b9590f..a3a773e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/impl/LongTermStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/impl/LongTermStatsImpl.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/impl/OverallStatsImpl.java b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/impl/OverallStatsImpl.java
index 6c810fa..38d5a92 100644
--- a/azureus2/src/org/gudy/azureus2/core3/stats/transfer/impl/OverallStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/stats/transfer/impl/OverallStatsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrent.java b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrent.java
index fedd3b7..1de78c8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrent.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrent.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentAnnounceURLGroup.java b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentAnnounceURLGroup.java
index 4a91417..992717a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentAnnounceURLGroup.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentAnnounceURLGroup.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentAnnounceURLSet.java b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentAnnounceURLSet.java
index 798d49e..2272fa5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentAnnounceURLSet.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentAnnounceURLSet.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentCreator.java b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentCreator.java
index e0252a8..1306f1d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentCreator.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentCreator.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentException.java b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentException.java
index 3fa0c89..e4522f4 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentFactory.java b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentFactory.java
index 7ce0eec..9ed9622 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentFile.java b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentFile.java
index fe058b6..83a3957 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentFile.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentFile.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -21,6 +22,8 @@
 
 package org.gudy.azureus2.core3.torrent;
 
+import java.util.Map;
+
 public interface 
 TOTorrentFile 
 {
@@ -46,4 +49,7 @@ TOTorrentFile
 	
 	public int
 	getNumberOfPieces();
+	
+	public Map
+	getAdditionalProperties();
 }
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentListener.java b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentListener.java
index 383fabe..47b42bd 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentListener.java
@@ -1,33 +1,32 @@
-/*
- * Created on Dec 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 org.gudy.azureus2.core3.torrent;
-
-public interface 
-TOTorrentListener 
-{
-	public static final int CT_ANNOUNCE_URLS	= 1;
-	
-	public void
-	torrentChanged(
-		TOTorrent		torrent,
-		int				change_type );
-}
+/*
+ * Created on Dec 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.torrent;
+
+public interface 
+TOTorrentListener 
+{
+	public static final int CT_ANNOUNCE_URLS	= 1;
+	
+	public void
+	torrentChanged(
+		TOTorrent		torrent,
+		int				change_type );
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentProgressListener.java b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentProgressListener.java
index 6f0229a..c940519 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentProgressListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/TOTorrentProgressListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentAnnounceURLGroupImpl.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentAnnounceURLGroupImpl.java
index 520c86f..f218ab6 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentAnnounceURLGroupImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentAnnounceURLGroupImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentAnnounceURLSetImpl.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentAnnounceURLSetImpl.java
index 05773dc..412ab7b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentAnnounceURLSetImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentAnnounceURLSetImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentCreateImpl.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentCreateImpl.java
index 796e7a4..35365a9 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentCreateImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentCreateImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -199,9 +200,13 @@ TOTorrentCreateImpl
 	
 		throws TOTorrentException
 	{			
-		constructFixed( torrent_base, piece_length );
+		int ignored = constructFixed( torrent_base, piece_length );
 		
-		if ( linkage_map.size() != linked_tf_map.size()){
+			// linkage map doesn't include ignored files, if it is supplied, so take account of this when
+			// checking that linkages have resolved correctly
+		
+		if ( 	linkage_map.size() > 0 &&
+				linkage_map.size() != ( linked_tf_map.size() + ignored )){
 			
 			throw( new TOTorrentException( "TOTorrentCreate: unresolved linkages: required=" + linkage_map + ", resolved=" + linked_tf_map,
 					TOTorrentException.RT_DECODE_FAILS));
@@ -243,7 +248,7 @@ TOTorrentCreateImpl
 		}
 	}
 	
-	protected void
+	private int
 	constructFixed(
 		File		_torrent_base,
 		long		_piece_length )
@@ -284,6 +289,8 @@ TOTorrentCreateImpl
 					(int)_piece_length, 
 					progress_listeners.size()==0?null:this );
 		
+		int	ignored = 0;
+		
 		try{
 			if ( cancelled ){
 				
@@ -310,7 +317,7 @@ TOTorrentCreateImpl
 			
 				List<TOTorrentFileImpl>	encoded = new ArrayList<TOTorrentFileImpl>();
 			
-				processDir( file_hasher, _torrent_base, encoded, _torrent_base.getName(), "" );
+				ignored = processDir( file_hasher, _torrent_base, encoded, _torrent_base.getName(), "" );
 			
 				TOTorrentFileImpl[] files = new TOTorrentFileImpl[ encoded.size()];
 			
@@ -332,13 +339,16 @@ TOTorrentCreateImpl
 				//System.out.println( "overall:sha1 = " + ByteFormatter.nicePrint( sha1_digest, true));
 				//System.out.println( "overall:ed2k = " + ByteFormatter.nicePrint( ed2k_digest, true));
 			}
+			
+			return( ignored );
+			
 		}finally{
 			
 			file_hasher = null;
 		}
 	}
 	
-	protected void
+	private int
 	processDir(
 		TOTorrentFileHasher			hasher,
 		File						dir,
@@ -372,6 +382,8 @@ TOTorrentCreateImpl
 		
 		long	offset	= 0;
 		
+		int	ignored = 0;
+		
 		for (int i=0;i<file_list.size();i++){
 			
 			File	file = (File)file_list.get(i);
@@ -387,12 +399,16 @@ TOTorrentCreateImpl
 						file_name = root + File.separator + file_name ;
 					}
 					
-					processDir( hasher, file, encoded, base_name, file_name );
+					ignored += processDir( hasher, file, encoded, base_name, file_name );
 					
 				}else{
 						
-					if ( !ignoreFile( file_name )){
-								
+					if ( ignoreFile( file_name )){
+						
+						ignored++;
+						
+					}else{
+						
 						if ( root.length() > 0 ){
 						
 							file_name = root + File.separator + file_name;
@@ -428,6 +444,8 @@ TOTorrentCreateImpl
 				}
 			}
 		}
+		
+		return( ignored );
 	}
 	
 	public void
@@ -654,7 +672,7 @@ TOTorrentCreateImpl
 		}
 	}
 	
-	protected boolean
+	private boolean
 	ignoreFile(
 		String		file )
 	{
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentCreatorImpl.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentCreatorImpl.java
index 686d2dd..4dcf3e5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentCreatorImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentCreatorImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java
index d5e2cef..f265af2 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentDeserialiseImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -25,6 +26,7 @@ package org.gudy.azureus2.core3.torrent.impl;
 import java.io.*;
 import java.net.*;
 import java.util.*;
+import java.util.zip.GZIPInputStream;
 
 import org.gudy.azureus2.core3.html.HTMLUtils;
 import org.gudy.azureus2.core3.internat.MessageText;
@@ -65,7 +67,7 @@ TOTorrentDeserialiseImpl
 			// However, this as been exceeded! (see bug 826617)
 			// As there is no technical reason for this limit I have removed it
 		
-		FileInputStream fis = null;
+		InputStream fis = null;
 		
 		try{
 				
@@ -75,9 +77,26 @@ TOTorrentDeserialiseImpl
 	
 		}catch( Throwable e ){
 			
-			throw( new TOTorrentException( "Error reading torrent file '" + file.toString() + " - " + Debug.getNestedExceptionMessage(e),
-											TOTorrentException.RT_READ_FAILS ));
+				// added automatic handling of gzipped files here as some users seem to be ending up 
+				// with then and it isn't a big deal to try 
 			
+			try{
+				if ( fis != null ){
+					
+					fis.close();
+					
+					fis = null;
+				}
+				
+				fis = new GZIPInputStream( new FileInputStream( file ));
+				
+				construct( fis );
+								
+			}catch( Throwable f ){	
+			
+				throw( new TOTorrentException( "Error reading torrent file '" + file.toString() + " - " + Debug.getNestedExceptionMessage(e),
+											TOTorrentException.RT_READ_FAILS ));
+			}
 		}finally{
 			
 			if ( fis != null ){
@@ -100,7 +119,39 @@ TOTorrentDeserialiseImpl
 		
 		throws TOTorrentException
 	{		
-		construct( is );
+			// while we could do this I don't like it because we end up with yet another copy of the
+			// torrent data in memory (could in theory be a 50MB torrent...) - we already cache the entire
+			// torrent in a bytearrayoutputstream in 'construct' later and in theory this could be coming
+			
+		
+		if ( false && is.markSupported()){
+						
+			is.mark( Integer.MAX_VALUE );
+			
+			BufferedInputStream bis = new BufferedInputStream( is );	// supports independent 'mark/reset'
+			
+			try{
+				construct( bis );
+				
+			}catch( TOTorrentException e ){
+				
+				try{
+				
+					is.reset();
+					
+					bis = new BufferedInputStream( new GZIPInputStream( is ));
+					
+					construct( bis );
+					
+				}catch( Throwable f ){
+					
+					throw( e );
+				}
+			}
+		}else{
+		
+			construct( is );
+		}
 	}
 	
 	public
@@ -126,7 +177,7 @@ TOTorrentDeserialiseImpl
 	
 		throws TOTorrentException
 	{
-		ByteArrayOutputStream metaInfo = new ByteArrayOutputStream();
+		ByteArrayOutputStream metaInfo = new ByteArrayOutputStream( 64*1024 );
 		
 		try{
 			byte[] buf = new byte[32*1024];	// raised this limit as 2k was rather too small
@@ -256,7 +307,7 @@ TOTorrentDeserialiseImpl
 					
 					announce_url = readStringFromMetaData( meta_data, TK_ANNOUNCE );
 					
-					if ( announce_url == null ){
+					if ( announce_url == null || announce_url.trim().length() == 0 ){
 						
 						bad_announce = true;
 						
@@ -493,6 +544,30 @@ TOTorrentDeserialiseImpl
 				setAnnounceURL( TorrentUtils.getDecentralisedEmptyURL());
 			}
 
+				// last ditch attempt to patch things up
+			
+			if ( getAnnounceURL() == null ){
+				
+				boolean done = false;
+		
+				if ( got_announce_list ){
+					
+					TOTorrentAnnounceURLSet[] sets = getAnnounceURLGroup().getAnnounceURLSets();
+					
+					if ( sets.length > 0 ){
+						
+						setAnnounceURL( sets[0].getAnnounceURLs()[0]);
+						
+						done = true;
+					}
+				}
+				
+				if ( !done ){
+					
+					setAnnounceURL( TorrentUtils.getDecentralisedEmptyURL());
+				}
+			}
+			
 			Map	info = (Map)meta_data.get( TK_INFO );
 
 			if ( info == null ){
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileHasher.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileHasher.java
index d36dc35..947cd85 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileHasher.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileHasher.java
@@ -2,7 +2,7 @@
  * Created on Oct 5, 2003
  * Created by Paul Gardner
  * Modified Apr 13, 2004 by Alon Rohter
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.
  * 
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileHasherListener.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileHasherListener.java
index a8f346d..e3c49a2 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileHasherListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileHasherListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java
index 3c7088f..34dd23f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentFileImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -236,7 +237,7 @@ TOTorrentFileImpl
 		additional_properties_maybe_null.put( name, value );
 	}
 	
-	protected Map
+	public Map
 	getAdditionalProperties()
 	{
 		return( additional_properties_maybe_null );
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java
index b318bce..c18b530 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentXMLDeserialiser.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentXMLDeserialiser.java
index 746ebc7..84c08ba 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentXMLDeserialiser.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentXMLDeserialiser.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentXMLSerialiser.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentXMLSerialiser.java
index b8ba1c8..7baedae 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentXMLSerialiser.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TOTorrentXMLSerialiser.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TorrentOpenFileOptions.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TorrentOpenFileOptions.java
index b5b50d9..1dfded2 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TorrentOpenFileOptions.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TorrentOpenFileOptions.java
@@ -46,6 +46,8 @@ public class TorrentOpenFileOptions
 	private String destFileName;
 	private String destPathName;
 
+	private boolean	didManualRename;
+	
 	/** @todo: getter/setters */
 	private final int iIndex;
 
@@ -63,16 +65,25 @@ public class TorrentOpenFileOptions
 	 * @param torrentFile
 	 * @param iIndex
 	 */
-	public TorrentOpenFileOptions(TorrentOpenOptions parent, TOTorrentFile torrentFile,
-			int iIndex) {
-		this.parent = parent;
-		lSize = torrentFile.getLength();
-		this.iIndex = iIndex;
-		setToDownload(true);
-		isValid = true;
+	public 
+	TorrentOpenFileOptions(
+		TorrentOpenOptions 	parent, 
+		int 				iIndex,
+		String				orgFullName,
+		String				orgFileName,
+		long				lSize,
+		boolean				wanted )
+	{
+		this.parent 		= parent;
+		this.iIndex 		= iIndex;
+		this.orgFullName	= orgFullName;
+		this.orgFileName	= orgFileName;
 		
-		orgFullName = torrentFile.getRelativePath(); // translated to locale
-		orgFileName = new File(orgFullName).getName();
+		this.lSize 	= lSize;
+		
+		setToDownload( wanted );
+		
+		isValid = true;
 	}
 	
 	public int
@@ -86,13 +97,13 @@ public class TorrentOpenFileOptions
 		if(newFullName == null)
 		{
 			setDestPathName(null);
-			setDestFileName(null);
+			setDestFileName(null,true);
 			return;
 		}
 			
 		File newPath = new File(newFullName);
 		setDestPathName(newPath.getParent());
-		setDestFileName(newPath.getName());
+		setDestFileName(newPath.getName(),true);
 	}
 	
 	public void setDestPathName(String newPath)
@@ -103,12 +114,15 @@ public class TorrentOpenFileOptions
 			destPathName = newPath;
 	}
 	
-	public void setDestFileName (String newFileName)
+	public void setDestFileName (String newFileName, boolean manualRename )
 	{
-		if(orgFileName.equals(newFileName))
+		if(orgFileName.equals(newFileName)){
 			destFileName = null;
-		else
-			destFileName = newFileName;			
+			didManualRename = false;
+		}else{
+			destFileName = newFileName;
+			didManualRename = manualRename;
+		}
 	}
 
 	public String getDestPathName() {
@@ -121,6 +135,12 @@ public class TorrentOpenFileOptions
 		return new File(parent.getDataDir(), orgFullName).getParent();
 	}
 	
+	public boolean
+	isManualRename()
+	{
+		return( didManualRename );
+	}
+	
 	public String getDestFileName() {
 		return destFileName == null ? orgFileName : destFileName;
 	}
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TorrentOpenOptions.java b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TorrentOpenOptions.java
index 316d974..742ec69 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TorrentOpenOptions.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrent/impl/TorrentOpenOptions.java
@@ -18,16 +18,16 @@
 package org.gudy.azureus2.core3.torrent.impl;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.*;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerState;
 import org.gudy.azureus2.core3.internat.LocaleTorrentUtil;
+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.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.AETemporaryFileHandler;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.FileUtil;
@@ -36,6 +36,7 @@ import org.gudy.azureus2.core3.util.TorrentUtils;
 import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.tag.Tag;
 import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.plugins.I2PHelpers;
 
 
 /**
@@ -73,10 +74,14 @@ public class TorrentOpenOptions
 
 	private String sDestDir;
 
+	private String manualRename;	// if user has manually renamed the top level folder
+	
 	/** for multifiletorrents and change location */
 	/** @todo: getter/setters */
 	private String sDestSubDir;
-
+	
+	private boolean explicitDataDir;
+	
 	/** @todo: getter/setters */
 	private TOTorrent torrent;
 
@@ -103,12 +108,19 @@ public class TorrentOpenOptions
 
 	private CopyOnWriteList<FileListener> fileListeners = new CopyOnWriteList<FileListener>(1);
 
-	public Map<String, Boolean> peerSource = new HashMap<String, Boolean>();
+	public Map<String, Boolean> peerSource 		= new HashMap<String, Boolean>();
+	
+	private Map<String, Boolean> enabledNetworks = new HashMap<String, Boolean>();
 	
 	private List<Tag>	initialTags = new ArrayList<Tag>();
 
 	private List<List<String>>	updatedTrackers;
 	
+	private int max_up;
+	private int max_down;
+	
+	private boolean	hide_errors;
+	
 		// add stuff here -> update the clone constructor
 	
 	/**
@@ -132,6 +144,15 @@ public class TorrentOpenOptions
 		iQueueLocation = QUEUELOCATION_BOTTOM;
 		isValid = true;
 		this.sDestDir = COConfigurationManager.getStringParameter(PARAM_DEFSAVEPATH);
+		
+		for (int i = 0; i < AENetworkClassifier.AT_NETWORKS.length; i++) {
+
+			String nn = AENetworkClassifier.AT_NETWORKS[i];
+
+			String config_name = "Network Selection Default." + nn;
+			
+			enabledNetworks.put( nn, COConfigurationManager.getBooleanParameter( config_name ));
+		}
 	}
 
 	/**
@@ -152,6 +173,7 @@ public class TorrentOpenOptions
 		// this.initial_linkage_map = ... // no clone
 		// this.files = ... // no clone
 		this.peerSource = toBeCloned.peerSource == null ? null : new HashMap<String, Boolean>(toBeCloned.peerSource);
+		this.enabledNetworks = toBeCloned.enabledNetworks == null ? null : new HashMap<String, Boolean>(toBeCloned.enabledNetworks);
 		this.initialTags = toBeCloned.initialTags == null ? null : new ArrayList<Tag>(toBeCloned.initialTags);
 		
 		if ( toBeCloned.updatedTrackers != null ){
@@ -160,6 +182,9 @@ public class TorrentOpenOptions
 				updatedTrackers.add( new ArrayList<String>( l ));
 			}
 		}
+		this.max_up 		= toBeCloned.max_up;
+		this.max_down 		= toBeCloned.max_down;	
+		this.hide_errors	= toBeCloned.hide_errors;
 	}
 
 	public static int getDefaultStartMode() {
@@ -180,6 +205,19 @@ public class TorrentOpenOptions
 		parentDirChanged();
 	}
 
+	public void
+	setManualRename(
+		String	manualRename )
+	{
+		this.manualRename = manualRename;
+	}
+	
+	public String
+	getManualRename()
+	{
+		return( manualRename );
+	}
+	
 	public String
 	getSubDir()
 	{
@@ -187,10 +225,22 @@ public class TorrentOpenOptions
 	}
 	
 	public void
-	setSubDir(
-		String		dir )
+	setExplicitDataDir(
+		String		parent_dir,
+		String		sub_dir )
 	{
-		sDestSubDir	= dir;
+		sDestDir 	= parent_dir;
+		sDestSubDir	= sub_dir;
+		
+		explicitDataDir	= true;
+		
+		parentDirChanged();
+	}
+	
+	public boolean
+	isExplicitDataDir()
+	{
+		return( explicitDataDir );
 	}
 	
 	public boolean
@@ -199,6 +249,20 @@ public class TorrentOpenOptions
 		return( torrent.isSimpleTorrent());
 	}
 	
+	public Map<String, Boolean>
+	getEnabledNetworks()
+	{
+		return( new HashMap<String, Boolean>( enabledNetworks ));
+	}
+	
+	public void
+	setNetworkEnabled(
+		String		net,
+		boolean		enabled )
+	{
+		enabledNetworks.put( net, enabled );
+	}
+	
 	public String getDataDir() {
 		if (torrent.isSimpleTorrent())
 			return sDestDir;
@@ -351,12 +415,71 @@ public class TorrentOpenOptions
 		updatedTrackers = trackers;
 	}
 	
+	public void
+	setMaxUploadSpeed(
+		int		kbs )
+	{
+		max_up	= kbs;
+	}
+	
+	public int
+	getMaxUploadSpeed()
+	{
+		return( max_up );
+	}
+	
+	public void
+	setMaxDownloadSpeed(
+		int		kbs )
+	{
+		max_down	= kbs;
+	}
+	
+	public int
+	getMaxDownloadSpeed()
+	{
+		return( max_down );
+	}
+	public void
+	setHideErrors(
+		boolean		h )
+	{
+		hide_errors	= h;
+	}
+	
+	public boolean
+	getHideErrors()
+	{
+		return( hide_errors );
+	}
+	
 	public TorrentOpenFileOptions[] getFiles() {
 		if (files == null && torrent != null) {
 			TOTorrentFile[] tfiles = torrent.getFiles();
 			files = new TorrentOpenFileOptions[tfiles.length];
+			
+			Set<String>	skip_extensons = TorrentUtils.getSkipExtensionsSet();
 			for (int i = 0; i < files.length; i++) {
-				files[i] = new TorrentOpenFileOptions(this, tfiles[i], i);
+				TOTorrentFile	torrentFile = tfiles[i];
+				
+				String 	orgFullName = torrentFile.getRelativePath(); // translated to locale
+				String	orgFileName = new File(orgFullName).getName();
+
+				boolean	wanted = true;
+				
+				if ( skip_extensons.size() > 0 ){
+					
+					int	pos = orgFileName.lastIndexOf( '.' );
+					
+					if ( pos != -1 ){
+						
+						String	ext = orgFileName.substring( pos+1 );
+						
+						wanted = !skip_extensons.contains( ext );
+					}
+				}
+				
+				files[i] = new TorrentOpenFileOptions( this, i, orgFullName, orgFileName, torrentFile.getLength(), wanted );
 			}
 		}
 
@@ -443,7 +566,7 @@ public class TorrentOpenOptions
 							+ info.getDestFileName());
 				}
 
-				info.setDestFileName(file.getName());
+				info.setDestFileName(file.getName(),false);
 			}
 		}
 	}
@@ -523,6 +646,154 @@ public class TorrentOpenOptions
 				e.printStackTrace();
 			}
 
+			Set<String> tracker_hosts = TorrentUtils.getUniqueTrackerHosts( torrent );
+			
+			final Set<String>	networks = new HashSet<String>();
+				
+			boolean	decentralised = false;
+			
+			for ( String host: tracker_hosts ){
+			
+				if ( TorrentUtils.isDecentralised( host )){
+					
+					decentralised = true;
+					
+				}else{
+					
+					String network = AENetworkClassifier.categoriseAddress( host );
+					
+					networks.add( network );
+				}
+			}
+			
+			List<String> network_cache = TorrentUtils.getNetworkCache( torrent );
+
+			networks.addAll( network_cache );
+			
+				// could do something here if multiple networks to get user to decide what to do...
+			
+			boolean	enable_i2p = networks.contains( AENetworkClassifier.AT_I2P );
+			String enable_i2p_reason = null;
+			
+			if ( enable_i2p ){
+				
+				enable_i2p_reason = MessageText.getString("azneti2phelper.install.reason.i2ptracker");
+				
+			} else {
+
+					// if torrent is purely decentralised then we don't really know what network so enable it
+			
+				if ( tracker_hosts.size() == 1 && decentralised ){
+				
+					// 2015/02/27 - holding off on this for the moment as unsure of the number of purely-dht
+					// torrents out there (e.g. old VHDN content is purely-dht...)
+					
+					//enable_i2p_reason = MessageText.getString("azneti2phelper.install.reason.decentralised");					
+					//enable_i2p = true;
+				}
+			}
+			
+			if ( enabledNetworks.get(AENetworkClassifier.AT_I2P)){
+				
+				// case where use chooses I2P network as default.  We want to prompt for plugin install
+
+				enable_i2p = true;
+			}
+			
+			if ( enable_i2p ){
+									
+				String[]	providers = { "azneti2p", "azneti2phelper" };
+				
+				boolean	found = false;
+				
+				for ( String provider: providers ){
+				
+					if ( AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( provider ) != null ){
+						
+						found = true;
+						
+						break;
+					}
+				}
+				
+				if ( found ){
+														
+					enabledNetworks.put( AENetworkClassifier.AT_I2P, true );
+					
+						// disable public if purely i2p
+					
+					if ( networks.contains( AENetworkClassifier.AT_I2P ) && networks.size() == 1 ){
+						
+						enabledNetworks.put( AENetworkClassifier.AT_PUBLIC, false );
+					}					
+				}else{
+					
+					final boolean[]	install_outcome = { false };
+
+					if ( I2PHelpers.installI2PHelper(
+							enable_i2p_reason,
+							"azneti2phelper.install.open.torrent",
+							install_outcome,
+							new Runnable()
+							{
+								public void
+								run()
+								{
+									if ( !install_outcome[0] ){
+									
+										// could try and revert settings but can't
+										// be bothered atm as it needs additional stuff to
+										// update the UI check boxes...
+										
+									}
+								}
+							})){
+						
+							// here installation has at least started so assume it'll complete
+						
+						enabledNetworks.put( AENetworkClassifier.AT_I2P, true );
+						
+							// disable public if purely i2p
+					
+						if ( networks.contains( AENetworkClassifier.AT_I2P ) && networks.size() == 1 ){
+							
+							enabledNetworks.put( AENetworkClassifier.AT_PUBLIC, false );
+						}	
+					};
+				}
+			}
+			
+			boolean	enable_tor = networks.contains( AENetworkClassifier.AT_TOR );
+
+			if ( enable_tor ){
+				
+				String[]	providers = { "aznettor" };
+				
+				boolean	found = false;
+				
+				for ( String provider: providers ){
+				
+					if ( AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( provider ) != null ){
+						
+						found = true;
+						
+						break;
+					}
+				}
+				
+				if ( found ){
+														
+					enabledNetworks.put( AENetworkClassifier.AT_TOR, true );
+					
+						// disable public if not selected
+					
+					if ( !networks.contains( AENetworkClassifier.AT_PUBLIC )){
+						
+						enabledNetworks.put( AENetworkClassifier.AT_PUBLIC, false );
+					}					
+				}
+			}
+			
 			renameDuplicates();
 		}
 	}
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloader.java b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloader.java
index a642bb0..fb3a9cf 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloader.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloader.java
@@ -2,7 +2,7 @@
  * TorrentDownloaderInfo.java
  *
  * Created on 2. November 2003, 01:48
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.torrentdownloader;
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderCallBackInterface.java b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderCallBackInterface.java
index 1f733b8..62abe31 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderCallBackInterface.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderCallBackInterface.java
@@ -2,7 +2,7 @@
  * TorrentDownloaderCallBackInterface.java
  *
  * Created on 2. November 2003, 01:32
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.torrentdownloader;
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderException.java b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderException.java
index a3cfa35..26231e8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderFactory.java b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderFactory.java
index 75c0d7e..11df353 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/TorrentDownloaderFactory.java
@@ -2,7 +2,7 @@
  * TorrentDownloaderFactory.java
  *
  * Created on 2. November 2003, 03:52
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.torrentdownloader;
@@ -30,7 +27,9 @@ import java.util.Map;
 import org.gudy.azureus2.core3.global.GlobalManager;
 import org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloaderImpl;
 import org.gudy.azureus2.core3.torrentdownloader.impl.TorrentDownloaderManager;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.TorrentUtils;
 import org.gudy.azureus2.core3.util.UrlUtils;
 
 import com.aelitis.azureus.core.proxy.AEProxyFactory;
@@ -288,6 +287,11 @@ public class TorrentDownloaderFactory {
   								state == STATE_DUPLICATE ||
   								state == STATE_CANCELLED ){
   					
+  							if ( state == STATE_FINISHED  && proxy_tried ){
+  								
+  								TorrentUtils.setObtainedFrom( delegate.getFile(), url );
+  							}
+  							
 							if ( original_callback != null ){
   								
   								original_callback.TorrentDownloaderEvent( state, TorrentDownloadRetrier.this );
@@ -306,12 +310,33 @@ public class TorrentDownloaderFactory {
   								
   								proxy_tried = true;
   								
-  	  							if ( lc_url.startsWith( "http" )){
+  								boolean	tor_hack = lc_url.startsWith( "tor:" );
+  								
+  	  							if ( lc_url.startsWith( "http" ) || tor_hack ){
 
   	  								try{
-  	  									URL original_url = new URL( url );
+  	  									URL original_url;
+  	  									
+  	  									if ( tor_hack ){
+  	  										
+  	  										original_url = new URL( url.substring( 4 ));
+  	  										
+  	  										Map<String,Object>	options = new HashMap<String,Object>();
+  	  								
+  	  										options.put( AEProxyFactory.PO_PEER_NETWORKS, new String[]{ AENetworkClassifier.AT_TOR });
+  	  							
+		  	  								plugin_proxy = 
+		  	  									AEProxyFactory.getPluginProxy( 
+		  	  										"torrent download",
+		  	  										original_url,
+		  	  										options,
+		  	  										true );
+		  	  							}else{
+  	  									
+		  	  								original_url = new URL( url );
+		  	  							}
   	  									
-  	  									plugin_proxy = AEProxyFactory.getPluginProxy( "loading plugin details", original_url );
+  	  									plugin_proxy = AEProxyFactory.getPluginProxy( "torrent download", original_url );
   	  									
   	  									if ( plugin_proxy != null ){
   	  										
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderImpl.java b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderImpl.java
index 3d0fd56..c8171ad 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderImpl.java
@@ -4,7 +4,7 @@
  * HTTPDownloader.java
  * 
  * Created on 17. August 2003, 22:22
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -17,9 +17,6 @@
  * 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.torrentdownloader.impl;
@@ -55,6 +52,7 @@ import org.gudy.azureus2.core3.util.protocol.magnet.MagnetConnection;
 import org.gudy.azureus2.core3.util.protocol.magnet.MagnetConnection2;
 import org.gudy.azureus2.core3.torrent.*;
 import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderException;
+import org.gudy.azureus2.pluginsimpl.local.utils.xml.rss.RSSUtils;
 
 import com.aelitis.azureus.core.proxy.AEProxyFactory;
 import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
@@ -191,9 +189,9 @@ public class TorrentDownloaderImpl extends AEThread implements TorrentDownloader
     	// hack here - the magnet download process requires an additional paramter to cause it to
     	// stall on error so the error can be reported
 	  
-    	if ( protocol.equals( "magnet" ) || protocol.equals( "dht" )){
+    	if ( protocol.equals( "magnet" ) || protocol.equals( "maggot" ) || protocol.equals( "dht" )){
 		  
-    		url = AddressUtils.adjustURL( new URL(url_str+"&pause_on_error=true"));
+    		url = AddressUtils.adjustURL( new URL(url_str+(url_str.contains("?")?"&":"?") + "pause_on_error=true"));
     	}
 	  
 		Set<String>	redirect_urls = new HashSet<String>();
@@ -937,11 +935,19 @@ public class TorrentDownloaderImpl extends AEThread implements TorrentDownloader
 	
 		        	  if ( !is_vuze_file ){
 	
-		        		  Debug.printStackTrace( e );
+		        		  if ( !RSSUtils.isRSSFeed( file )){
+		        		  
+		        			  Debug.printStackTrace( e );
+		        		  }
 		        	  }
 		          }
 		          
-		          TorrentUtils.setObtainedFrom( file, original_url );
+		          	// proxy will report this with the correct URL if active
+		          
+		          if ( proxy == null ){
+		          
+		        	  TorrentUtils.setObtainedFrom( file, original_url );
+		          }
 	
 		          this.state = STATE_FINISHED;
 		        }
diff --git a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderManager.java b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderManager.java
index 26a5ae4..dc86caa 100644
--- a/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/torrentdownloader/impl/TorrentDownloaderManager.java
@@ -2,7 +2,7 @@
  * TorrentDownloaderManagerImpl.java
  *
  * Created on 2. November 2003, 04:29
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.torrentdownloader.impl;
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncer.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncer.java
index a470c24..3b19376 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerDataProvider.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerDataProvider.java
index 213af39..55b6371 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerDataProvider.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerDataProvider.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerException.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerException.java
index 402a010..05fc770 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerFactory.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerFactory.java
index 20c4910..38b05c3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerFactoryListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerFactoryListener.java
index 848e465..dbedec5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerFactoryListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerFactoryListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerListener.java
index 373bed6..e18b392 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerResponse.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerResponse.java
index 5b70a2a..f5008c6 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerResponse.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerResponse.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerResponsePeer.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerResponsePeer.java
index 5738da8..dec696c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerResponsePeer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerAnnouncerResponsePeer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraper.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraper.java
index d87ade6..d75ab5d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraper.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraper.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperClientResolver.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperClientResolver.java
index 5dfa23d..e3d1c8a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperClientResolver.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperClientResolver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -72,6 +69,10 @@ TRTrackerScraperClientResolver
 		HashWrapper	hash,
 		URL			url );
 	
+	public String[]
+	getEnabledNetworks(
+		HashWrapper	hash );
+	
 		/**
 		 * Two kinds of extensions: entry [0] = String (or null) that gets passed with the scrape verbotem after infohash
 		 * entry [1] = Character - status of download, aggregated into a single String passed with scrape
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperFactory.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperFactory.java
index 0669cd9..24993a8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperListener.java
index 7d1ce74..4073c6f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperResponse.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperResponse.java
index 5899446..54ed8f0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperResponse.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/TRTrackerScraperResponse.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerFactoryImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerFactoryImpl.java
index a83892a..8a31b3d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerFactoryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerFactoryImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerHelper.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerHelper.java
index beca167..a42e5ab 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerHelper.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerHelper.java
@@ -1,45 +1,44 @@
-/*
- * Created on Dec 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 org.gudy.azureus2.core3.tracker.client.impl;
-
-import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
-import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
-
-public interface 
-TRTrackerAnnouncerHelper
-	extends TRTrackerAnnouncer
-{
-	public TOTorrentAnnounceURLSet[]
-	getAnnounceSets();
-		
-	public boolean
-	isUpdating();
-	
-	public long
-	getInterval();
-	
-	public long
-	getMinInterval();
-	
-	public int
-	getTimeUntilNextUpdate();
-}
+/*
+ * Created on Dec 8, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.tracker.client.impl;
+
+import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
+
+public interface 
+TRTrackerAnnouncerHelper
+	extends TRTrackerAnnouncer
+{
+	public TOTorrentAnnounceURLSet[]
+	getAnnounceSets();
+		
+	public boolean
+	isUpdating();
+	
+	public long
+	getInterval();
+	
+	public long
+	getMinInterval();
+	
+	public int
+	getTimeUntilNextUpdate();
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerImpl.java
index dd17097..54fd61b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerMuxer.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerMuxer.java
index e3b19cb..b19452c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerMuxer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerMuxer.java
@@ -1,1734 +1,1783 @@
-/*
- * Created on Dec 4, 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.core3.tracker.client.impl;
-
-import java.net.URL;
-import java.util.*;
-
-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.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.TRTrackerAnnouncerDataProvider;
-import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerException;
-import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerFactory;
-import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse;
-import org.gudy.azureus2.core3.tracker.client.impl.bt.TRTrackerBTAnnouncerImpl;
-import org.gudy.azureus2.core3.tracker.client.impl.dht.TRTrackerDHTAnnouncerImpl;
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.IndentWriter;
-import org.gudy.azureus2.core3.util.SimpleTimer;
-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.TorrentUtils;
-import org.gudy.azureus2.plugins.download.DownloadAnnounceResult;
-
-import com.aelitis.azureus.core.tracker.TrackerPeerSource;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-public class 
-TRTrackerAnnouncerMuxer
-	extends TRTrackerAnnouncerImpl
-{
-	private static final int ACT_CHECK_INIT_DELAY			= 2500;
-	private static final int ACT_CHECK_INTERIM_DELAY		= 10*1000;
-	private static final int ACT_CHECK_IDLE_DELAY			= 30*1000;
-	private static final int ACT_CHECK_SEEDING_SHORT_DELAY		= 60*1000;
-	private static final int ACT_CHECK_SEEDING_LONG_DELAY		= 3*60*1000;
-	
-	
-	private TRTrackerAnnouncerFactory.DataProvider		f_provider;
-	private boolean										is_manual;
-	
-	private long				create_time = SystemTime.getMonotonousTime();
-	
-	private CopyOnWriteList<TRTrackerAnnouncerHelper>	announcers 	= new CopyOnWriteList<TRTrackerAnnouncerHelper>();
-	private Set<TRTrackerAnnouncerHelper>				activated	= new HashSet<TRTrackerAnnouncerHelper>();
-	private long										last_activation_time;
-	private Set<String>									failed_urls	= new HashSet<String>();
-	
-	private volatile TimerEvent					event;
-	
-	private TRTrackerAnnouncerDataProvider		provider;
-	private String								ip_override;
-	private boolean								complete;
-	private boolean								stopped;
-	private boolean								destroyed;
-	
-	private TRTrackerAnnouncerHelper			last_best_active;
-	private long								last_best_active_set_time;
-	
-	private Map<String,StatusSummary>			recent_responses = new HashMap<String,StatusSummary>();
-	
-	private TRTrackerAnnouncerResponse			last_response_informed;
-
-	
-	protected
-	TRTrackerAnnouncerMuxer(
-		TOTorrent								_torrent,
-		TRTrackerAnnouncerFactory.DataProvider	_f_provider,
-		boolean									_manual )
-	
-		throws TRTrackerAnnouncerException
-	{
-		super( _torrent );
-		
-		try{	
-			last_response_informed = new TRTrackerAnnouncerResponseImpl( null, _torrent.getHashWrapper(), TRTrackerAnnouncerResponse.ST_OFFLINE, TRTrackerAnnouncer.REFRESH_MINIMUM_SECS, "Initialising" );
-			
-		}catch( TOTorrentException e ){
-			
-			Logger.log(new LogEvent( _torrent, LOGID, "Torrent hash retrieval fails", e));
-			
-			throw( new TRTrackerAnnouncerException( "TRTrackerAnnouncer: URL encode fails"));	
-		}
-
-		is_manual 	= _manual;
-		f_provider	= _f_provider;
-		
-		split();
-	}
-	
-	protected void
-	split()
-	
-		throws TRTrackerAnnouncerException
-	{
-		String[]	networks = f_provider==null?null:f_provider.getNetworks();
-		
-		TRTrackerAnnouncerHelper to_activate = null;
-		
-		synchronized( this ){
-			
-			if ( stopped || destroyed ){
-				
-				return;
-			}
-			
-			TOTorrent torrent = getTorrent();
-					
-			TOTorrentAnnounceURLSet[]	sets = torrent.getAnnounceURLGroup().getAnnounceURLSets();
-			
-				// sanitise dht entries
-			
-			if ( sets.length == 0 ){
-				
-				sets = new TOTorrentAnnounceURLSet[]{ torrent.getAnnounceURLGroup().createAnnounceURLSet( new URL[]{ torrent.getAnnounceURL()})};
-				
-			}else{
-				
-				boolean	found_decentralised = false;
-				boolean	modified			= false;
-				
-				for ( int i=0;i<sets.length;i++ ){
-					
-					TOTorrentAnnounceURLSet set = sets[i];
-					
-					URL[] urls = set.getAnnounceURLs().clone();
-					
-					for (int j=0;j<urls.length;j++){
-						
-						URL u = urls[j];
-						
-						if ( u != null && TorrentUtils.isDecentralised( u )){
-														
-							if ( found_decentralised ){
-								
-								modified = true;
-								
-								urls[j] = null;
-								
-							}else{
-								
-								found_decentralised = true;
-							}
-						}
-					}
-				}
-				
-				if ( modified ){
-					
-					List<TOTorrentAnnounceURLSet> s_list = new ArrayList<TOTorrentAnnounceURLSet>();
-					
-					for ( TOTorrentAnnounceURLSet set: sets ){
-						
-						URL[] urls = set.getAnnounceURLs();
-						
-						List<URL> u_list = new ArrayList<URL>( urls.length );
-						
-						for ( URL u: urls ){
-							
-							if ( u != null ){
-								
-								u_list.add( u );
-							}
-						}
-						
-						if ( u_list.size() > 0 ){
-							
-							s_list.add( torrent.getAnnounceURLGroup().createAnnounceURLSet( u_list.toArray( new URL[ u_list.size() ])));
-						}
-					}
-					
-					sets = s_list.toArray( new TOTorrentAnnounceURLSet[ s_list.size() ]);
-				}
-			}
-			
-			List<TOTorrentAnnounceURLSet[]>	new_sets = new ArrayList<TOTorrentAnnounceURLSet[]>();
-			
-			if ( is_manual || sets.length < 2 ){
-					
-				new_sets.add( sets );
-				
-			}else{
-				
-				List<TOTorrentAnnounceURLSet> list = new ArrayList<TOTorrentAnnounceURLSet>( Arrays.asList( sets ));
-				
-					// often we have http:/xxxx/ and udp:/xxxx/ as separate groups - keep these together
-								
-				while( list.size() > 0 ){
-					
-					TOTorrentAnnounceURLSet set1 = list.remove(0);
-					
-					boolean	done = false;
-					
-					URL[] urls1 = set1.getAnnounceURLs();
-					
-					if ( urls1.length == 1 ){
-						
-						URL url1 = urls1[0];
-						
-						String prot1 = url1.getProtocol().toLowerCase();
-						String host1	= url1.getHost();
-						
-						for (int i=0;i<list.size();i++){
-							
-							TOTorrentAnnounceURLSet set2 = list.get(i);
-							
-							URL[] urls2 = set2.getAnnounceURLs();
-							
-							if ( urls2.length == 1 ){
-								
-								URL url2 = urls2[0];
-								
-								String prot2 = url2.getProtocol().toLowerCase();
-								String host2 = url2.getHost();
-				
-								if ( host1.equals( host2 )){
-									
-									if (	( prot1.equals( "udp" ) && prot2.startsWith( "http" )) ||
-											( prot2.equals( "udp" ) && prot1.startsWith( "http" ))){
-										
-										list.remove( i );
-										
-										new_sets.add( new TOTorrentAnnounceURLSet[]{ set1, set2 });
-										
-										done	= true;
-									}
-								}
-							}
-						}
-					}
-					
-					if ( !done ){
-						
-						new_sets.add( new TOTorrentAnnounceURLSet[]{ set1 });
-					}
-				}
-			}
-			
-				// work out the difference
-			
-			Iterator<TOTorrentAnnounceURLSet[]> ns_it = new_sets.iterator();
-			
-				// need to copy list as we modify it and returned list ain't thread safe
-			
-			List<TRTrackerAnnouncerHelper> existing_announcers 	= new ArrayList<TRTrackerAnnouncerHelper>( announcers.getList());
-			
-			List<TRTrackerAnnouncerHelper> new_announcers 		= new ArrayList<TRTrackerAnnouncerHelper>();
-			
-				// first look for unchanged sets
-			
-			while( ns_it.hasNext()){
-				
-				TOTorrentAnnounceURLSet[] ns = ns_it.next();
-				
-				Iterator<TRTrackerAnnouncerHelper> a_it = existing_announcers.iterator();
-					
-				while( a_it.hasNext()){
-					
-					TRTrackerAnnouncerHelper a = a_it.next();
-					
-					TOTorrentAnnounceURLSet[] os = a.getAnnounceSets();
-					
-					if ( same( ns, os )){
-						
-						ns_it.remove();
-						a_it.remove();
-						
-						new_announcers.add( a );
-						
-						break;
-					}
-				}
-			}
-								
-				// first remove dht ones from the equation
-			
-			TRTrackerAnnouncerHelper 	existing_dht_announcer 	= null;
-			TOTorrentAnnounceURLSet[]	new_dht_set				= null;
-
-			ns_it = new_sets.iterator();
-			
-			while( ns_it.hasNext()){
-				
-				TOTorrentAnnounceURLSet[] x = ns_it.next();
-				
-				if ( TorrentUtils.isDecentralised( x[0].getAnnounceURLs()[0])){
-					
-					new_dht_set = x;
-						
-					ns_it.remove();
-					
-					break;
-				}
-			}
-			
-			Iterator<TRTrackerAnnouncerHelper>	an_it = existing_announcers.iterator();
-			
-			while( an_it.hasNext()){
-				
-				TRTrackerAnnouncerHelper a = an_it.next();
-				
-				TOTorrentAnnounceURLSet[] x = a.getAnnounceSets();
-				
-				if ( TorrentUtils.isDecentralised( x[0].getAnnounceURLs()[0])){
-					
-					existing_dht_announcer = a;
-						
-					an_it.remove();
-					
-					break;
-				}
-			}
-	
-			if ( existing_dht_announcer != null && new_dht_set != null ){
-				
-				new_announcers.add( existing_dht_announcer );
-				
-			}else if ( existing_dht_announcer != null ){
-				
-				activated.remove( existing_dht_announcer );
-				
-				existing_dht_announcer.destroy();
-				
-			}else if ( new_dht_set != null ){
-				
-				TRTrackerAnnouncerHelper a = create( torrent, networks, new_dht_set );
-				
-				new_announcers.add( a );
-			}
-			
-				// create any new ones required
-			
-			ns_it = new_sets.iterator();
-			
-			while( ns_it.hasNext()){
-				
-				TOTorrentAnnounceURLSet[] s = ns_it.next();
-				
-				TRTrackerAnnouncerHelper a = create( torrent, networks, s );
-				
-				new_announcers.add( a );
-			}
-			
-				// finally fix up the announcer list to represent the new state
-			
-			Iterator<TRTrackerAnnouncerHelper>	a_it = announcers.iterator();
-				
-			while( a_it.hasNext()){
-				
-				TRTrackerAnnouncerHelper a = a_it.next();
-				
-				if ( !new_announcers.contains( a )){
-					
-					a_it.remove();
-					
-					try{
-						if ( 	activated.contains( a ) &&
-								torrent.getPrivate() && 
-								a instanceof TRTrackerBTAnnouncerImpl ){
-							
-							URL url = a.getTrackerURL();
-						
-							if ( url != null ){
-								
-								forceStop((TRTrackerBTAnnouncerImpl)a, networks, url );
-							}
-						}
-					}finally{
-						
-						if (Logger.isEnabled()) {
-							Logger.log(new LogEvent(getTorrent(), LOGID, "Deactivating " + getString( a.getAnnounceSets())));
-						}
-
-						activated.remove( a );
-												
-						a.destroy();
-					}
-				}
-			}
-			
-			a_it = new_announcers.iterator();
-			
-			while( a_it.hasNext()){
-				
-				TRTrackerAnnouncerHelper a = a_it.next();
-				
-				if ( !announcers.contains( a )){
-					
-					announcers.add( a );
-				}
-			}
-			
-			if ( !is_manual && announcers.size() > 0 ){
-				
-				if ( activated.size() == 0 ){
-					
-					TRTrackerAnnouncerHelper a = announcers.get(0);
-					
-					if (Logger.isEnabled()) {
-						Logger.log(new LogEvent(getTorrent(), LOGID, "Activating " + getString( a.getAnnounceSets())));
-					}
-
-					activated.add( a );
-					
-					last_activation_time = SystemTime.getMonotonousTime();
-					
-					if ( provider != null ){
-						
-						to_activate = a;
-					}
-				}
-				
-				setupActivationCheck( ACT_CHECK_INIT_DELAY );
-			}
-		}
-		
-		if ( to_activate != null ){
-			
-			if ( complete ){
-				
-				to_activate.complete( true );
-				
-			}else{
-				
-				to_activate.update( false );
-			}
-		}
-	}
-	
-	protected void
-	setupActivationCheck(
-		int		delay )
-	{
-		if ( announcers.size() > activated.size()){
-			
-			event = SimpleTimer.addEvent(
-				"TRMuxer:check",
-				SystemTime.getOffsetTime( delay ),
-				new TimerEventPerformer()
-				{
-					public void 
-					perform(
-						TimerEvent event )
-					{
-						checkActivation( false );
-					}
-				});
-		}
-	}
-	
-	protected void
-	checkActivation(
-		boolean		force )
-	{
-		synchronized( this ){
-			
-			int	next_check_delay;
-			
-			if ( 	destroyed || 
-					stopped || 
-					announcers.size() <= activated.size()){
-
-				return;
-			}
-			
-			if ( provider == null ){
-				
-				next_check_delay = ACT_CHECK_INIT_DELAY;
-				
-			}else{
-
-				boolean	activate = force;
-														
-				boolean	seeding = provider.getRemaining() == 0;
-
-				if ( seeding && activated.size() > 0 ){
-				
-						// when seeding we only activate on tracker fail or major lack of connections
-						// as normally we rely on downloaders rotating and finding us
-
-					int	connected	= provider.getConnectedConnectionCount();
-
-					if ( connected < 1 ){
-						
-						activate = SystemTime.getMonotonousTime() - last_activation_time >= 60*1000;
-						
-						next_check_delay = ACT_CHECK_SEEDING_SHORT_DELAY;
-						
-					}else if ( connected < 3 ){
-						
-						next_check_delay = ACT_CHECK_SEEDING_LONG_DELAY;
-						
-					}else{
-						
-						next_check_delay = 0;
-					}
-				}else{
-					
-					int	allowed		= provider.getMaxNewConnectionsAllowed();	
-					int	pending		= provider.getPendingConnectionCount();
-					int	connected	= provider.getConnectedConnectionCount();
-					
-					int	online = 0;
-					
-					for ( TRTrackerAnnouncerHelper a: activated ){
-						
-						TRTrackerAnnouncerResponse response = a.getLastResponse();
-						
-						if ( 	response != null && 
-								response.getStatus() == TRTrackerAnnouncerResponse.ST_ONLINE ){
-							
-							online++;
-						}
-					}
-					
-					/*
-					System.out.println( 
-						"checkActivation: announcers=" + announcers.size() + 
-						", active=" + activated.size() +
-						", online=" + online +
-						", allowed=" + allowed +
-						", pending=" + pending +
-						", connected=" + connected +
-						", seeding=" + seeding );
-					*/
-					
-					if ( online == 0 ){
-						
-						activate = true;
-						
-							// no trackers online, start next and recheck soon
-						
-						next_check_delay = ACT_CHECK_INIT_DELAY;
-						
-					}else{
-						
-						int	potential = connected + pending;
-						
-						if ( potential < 10 ){
-							
-								// minimal connectivity 
-							
-							activate = true;
-							
-							next_check_delay = ACT_CHECK_INIT_DELAY;
-
-						}else if ( allowed >= 5 && pending < 3*allowed/4 ){
-							
-								// not enough to fulfill our needs
-							
-							activate = true;
-							
-							next_check_delay = ACT_CHECK_INTERIM_DELAY;
-							
-						}else{
-								// things look good, recheck in a bit
-							
-							next_check_delay = ACT_CHECK_IDLE_DELAY;
-						}
-					}
-				}
-					
-				if ( activate ){
-					
-					for ( TRTrackerAnnouncerHelper a: announcers ){
-						
-						if ( !activated.contains( a )){
-							
-							if (Logger.isEnabled()) {
-								Logger.log(new LogEvent(getTorrent(), LOGID, "Activating " + getString( a.getAnnounceSets())));
-							}
-							
-							activated.add( a );
-							
-							last_activation_time = SystemTime.getMonotonousTime();
-							
-							if ( complete ){
-								
-								a.complete( true );
-								
-							}else{
-								
-								a.update( false );
-							}
-							
-							break;
-						}
-					}
-				}
-			}
-			
-			if ( next_check_delay > 0 ){
-			
-				setupActivationCheck( next_check_delay );
-			}
-		}
-	}
-	
-	private String
-	getString(
-		TOTorrentAnnounceURLSet[]	sets )
-	{
-		StringBuffer str = new StringBuffer();
-		
-		str.append( "[" );
-		
-		int	num1 = 0;
-		
-		for ( TOTorrentAnnounceURLSet s: sets ){
-			
-			if ( num1++ > 0 ){
-				str.append( ", ");
-			}
-			
-			str.append( "[" );
-
-			URL[]	urls = s.getAnnounceURLs();
-			
-			int	num2 = 0;
-			
-			for ( URL u: urls ){
-				
-				if ( num2++ > 0 ){
-					str.append( ", ");
-				}
-				
-				str.append( u.toExternalForm());
-			}
-			
-			str.append( "]" );
-		}
-		
-		str.append( "]" );
-		
-		return( str.toString());
-	}
-	
-	private boolean
-	same(
-		TOTorrentAnnounceURLSet[]	s1,
-		TOTorrentAnnounceURLSet[]	s2 )
-	{
-		boolean	res = sameSupport( s1, s2 );
-		
-		// System.out.println( "same->" + res + ": " + getString(s1) + "/" + getString(s2));
-		
-		return( res );
-	}
-	
-	private boolean
-	sameSupport(
-		TOTorrentAnnounceURLSet[]	s1,
-		TOTorrentAnnounceURLSet[]	s2 )
-	{
-		if ( s1.length != s2.length ){
-			
-			return( false );
-		}
-		
-		for (int i=0;i<s1.length;i++){
-			
-			URL[] u1 = s1[i].getAnnounceURLs();
-			URL[] u2 = s2[i].getAnnounceURLs();
-			
-			if ( u1.length != u2.length ){
-				
-				return( false );
-			}
-			
-			if ( u1.length == 1 ){
-				
-				return( u1[0].toExternalForm().equals( u2[0].toExternalForm()));
-			}
-			
-			Set<String> set1 = new HashSet<String>();
-			
-			for ( URL u: u1 ){
-				
-				set1.add( u.toExternalForm());
-			}
-			
-			Set<String> set2 = new HashSet<String>();
-			
-			for ( URL u: u2 ){
-				
-				set2.add( u.toExternalForm());
-			}
-			
-			if ( !set1.equals( set2 )){
-				
-				return( false );
-			}
-		}
-		
-		return( true );
-	}
-	
-	protected void
-	forceStop(
-		final TRTrackerBTAnnouncerImpl		announcer,
-		final String[]						networks,
-		final URL							url )
-	{
-		if (Logger.isEnabled()) {
-			Logger.log(new LogEvent(getTorrent(), LOGID, "Force stopping " + url + " as private torrent" ));
-		}
-		
-		new AEThread2( "TRMux:fs", true )
-		{
-			public void
-			run()
-			{
-				try{
-					TRTrackerBTAnnouncerImpl an = 
-						new TRTrackerBTAnnouncerImpl( getTorrent(), new TOTorrentAnnounceURLSet[0], networks, true, getHelper());
-					
-					an.cloneFrom( announcer );
-					
-					an.setTrackerURL( url );
-					
-					an.stop( false );
-					
-					an.destroy();
-					
-				}catch( Throwable e ){
-					
-				}
-			}
-		}.start();
-	}
-	
-	private TRTrackerAnnouncerHelper
-	create(
-		TOTorrent						torrent,
-		String[]						networks,
-		TOTorrentAnnounceURLSet[]		sets )
-	
-		throws TRTrackerAnnouncerException
-	{
-		TRTrackerAnnouncerHelper announcer;
-		
-		boolean	decentralised;
-		
-		if ( sets.length == 0 ){
-			
-			decentralised = TorrentUtils.isDecentralised( torrent.getAnnounceURL());
-			
-		}else{
-			
-			decentralised = TorrentUtils.isDecentralised( sets[0].getAnnounceURLs()[0]);
-		}
-		
-		if ( decentralised ){
-			
-			announcer	= new TRTrackerDHTAnnouncerImpl( torrent, networks, is_manual, getHelper());
-			
-		}else{
-			
-			announcer = new TRTrackerBTAnnouncerImpl( torrent, sets, networks, is_manual, getHelper());
-		}
-		
-		for ( TOTorrentAnnounceURLSet set: sets ){
-			
-			URL[] urls = set.getAnnounceURLs();
-			
-			for ( URL u: urls ){
-				
-				String key = u.toExternalForm();
-				
-				StatusSummary summary = recent_responses.get( key );
-				
-				if ( summary == null ){
-					
-					summary = new StatusSummary( announcer, u );
-										
-					recent_responses.put( key, summary );
-					
-				}else{
-					
-					summary.setHelper( announcer );
-				}
-			}
-		}
-		
-		if ( provider != null ){
-			
-			announcer.setAnnounceDataProvider( provider );
-		}
-		
-		if ( ip_override != null ){
-			
-			announcer.setIPOverride( ip_override );
-		}
-		
-		return( announcer );
-	}
-	
-	
-	public TRTrackerAnnouncerResponse
-	getLastResponse()
-	{
-		TRTrackerAnnouncerResponse	result = null;
-		
-		TRTrackerAnnouncerHelper best = getBestActive();
-		
-		if ( best != null ){
-			
-			result = best.getLastResponse();
-		}
-		
-		if ( result == null ){
-			
-			result = last_response_informed;
-		}
-		
-		return( result );
-	}
-	
-
-	@Override
-	protected void
-	informResponse(
-		TRTrackerAnnouncerHelper		helper,
-		TRTrackerAnnouncerResponse		response )
-	{
-		URL	url = response.getURL();
-		
-			// can be null for external plugins (e.g. mldht...)
-		
-		if ( url != null ){
-			
-			synchronized( this ){
-				
-				String key = url.toExternalForm();
-				
-				StatusSummary summary = recent_responses.get( key );
-			
-				if ( summary != null ){
-				
-					summary.updateFrom( response );
-				}
-			}
-		}
-		
-		last_response_informed = response;
-		
-			// force recalc of best active next time
-		
-		last_best_active_set_time = 0;
-		
-		super.informResponse( helper, response );
-		
-		if ( response.getStatus() != TRTrackerAnnouncerResponse.ST_ONLINE ){
-			
-			URL	u = response.getURL();
-			
-			if ( u != null ){
-				
-				String s = u.toExternalForm();
-				
-				synchronized( failed_urls ){
-					
-					if ( failed_urls.contains( s )){
-						
-						return;
-					}
-					
-					failed_urls.add( s );
-				}
-			}
-			
-			checkActivation( true );
-		}
-	}
-	
-	public boolean
-	isManual()
-	{
-		return( is_manual );
-	}
-
-	public void
-	setAnnounceDataProvider(
-		TRTrackerAnnouncerDataProvider		_provider )
-	{
-		List<TRTrackerAnnouncerHelper>	to_set;
-		
-		synchronized( this ){
-			
-			provider	= _provider;
-			
-			to_set = announcers.getList();
-		}
-		
-		for ( TRTrackerAnnouncer announcer: to_set ){
-		
-			announcer.setAnnounceDataProvider( provider );
-		}
-	}
-	
-	protected TRTrackerAnnouncerHelper
-	getBestActive()
-	{
-		long	now = SystemTime.getMonotonousTime();
-		
-		if ( now - last_best_active_set_time < 1000 ){
-			
-			return( last_best_active );
-		}
-		
-		last_best_active = getBestActiveSupport();
-		
-		last_best_active_set_time = now;
-		
-		return( last_best_active );
-	}
-	
-	protected TRTrackerAnnouncerHelper
-	getBestActiveSupport()
-	{
-		List<TRTrackerAnnouncerHelper> x = announcers.getList();
-		
-		TRTrackerAnnouncerHelper error_resp = null;
-		
-		for ( TRTrackerAnnouncerHelper announcer: x ){
-			
-			TRTrackerAnnouncerResponse response = announcer.getLastResponse();
-			
-			if ( response != null ){
-				
-				int	resp_status = response.getStatus();
-				
-				if ( resp_status == TRTrackerAnnouncerResponse.ST_ONLINE ){
-					
-					return( announcer );
-					
-				}else if ( error_resp == null && resp_status == TRTrackerAnnouncerResponse.ST_REPORTED_ERROR ){
-					
-					error_resp = announcer;
-				}
-			}
-		}
-		
-		if ( error_resp != null ){
-			
-			return( error_resp );
-		}
-		
-		if ( x.size() > 0 ){
-			
-			return( x.get(0));
-		}
-		
-		return( null );
-	}
-	
-	public URL
-	getTrackerURL()
-	{
-		TRTrackerAnnouncerHelper	active = getBestActive();
-		
-		if ( active != null ){
-			
-			return( active.getTrackerURL());
-		}
-		
-		return( null );
-	}
-	
-	public void
-	setTrackerURL(
-		URL		url )
-	{
-		List<List<String>> groups = new ArrayList<List<String>>();
-		
-		List<String> group = new ArrayList<String>();
-		
-		group.add( url.toExternalForm());
-		
-		groups.add( group );
-		
-		TorrentUtils.listToAnnounceGroups( groups, getTorrent());
-		
-		resetTrackerUrl( false );
-	}
-	
-	public void
-	resetTrackerUrl(
-		boolean	shuffle )
-	{
-		try{
-			split();
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-		
-		for ( TRTrackerAnnouncer announcer: announcers ){
-		
-			announcer.resetTrackerUrl( shuffle );
-		}
-	}
-	
-	public void
-	setIPOverride(
-		String		override )
-	{
-		List<TRTrackerAnnouncerHelper>	to_set;
-		
-		synchronized( this ){
-			
-			to_set	= announcers.getList();
-			
-			ip_override	= override;
-		}
-		
-		for ( TRTrackerAnnouncer announcer: to_set ){
-		
-			announcer.setIPOverride( override );
-		}
-	}
-	
-	public void
-	clearIPOverride()
-	{
-		List<TRTrackerAnnouncerHelper>	to_clear;
-		
-		synchronized( this ){
-			
-			to_clear	= announcers.getList();
-			
-			ip_override	= null;
-		}
-		
-		for ( TRTrackerAnnouncer announcer: to_clear ){
-		
-			announcer.clearIPOverride();
-		}
-	}
-	
-	public void
-	setRefreshDelayOverrides(
-		int		percentage )
-	{
-		for ( TRTrackerAnnouncer announcer: announcers ){
-		
-			announcer.setRefreshDelayOverrides( percentage );
-		}
-	}
-	
-	public int
-	getTimeUntilNextUpdate()
-	{
-		TRTrackerAnnouncerHelper	active = getBestActive();
-
-		if ( active != null ){
-			
-			return( active.getTimeUntilNextUpdate());
-		}
-		
-		return( Integer.MAX_VALUE );
-	}
-	
-	public int
-	getLastUpdateTime()
-	{
-		TRTrackerAnnouncerHelper	active = getBestActive();
-
-		if ( active != null ){
-			
-			return( active.getLastUpdateTime());
-		}
-		
-		return( 0 );
-	}	
-	
-	public void
-	update(
-		boolean	force )
-	{
-		List<TRTrackerAnnouncerHelper> to_update;
-		
-		synchronized( this ){
-						
-			to_update = is_manual?announcers.getList():new ArrayList<TRTrackerAnnouncerHelper>( activated );
-		}
-		
-		for ( TRTrackerAnnouncer announcer: to_update ){
-		
-			announcer.update(force);
-		}
-	}
-	
-	public void
-	complete(
-		boolean	already_reported )
-	{
-		List<TRTrackerAnnouncerHelper> to_complete;
-		
-		synchronized( this ){
-			
-			complete	= true;
-			
-			to_complete = is_manual?announcers.getList():new ArrayList<TRTrackerAnnouncerHelper>( activated );
-		}
-		
-		for ( TRTrackerAnnouncer announcer: to_complete ){
-		
-			announcer.complete( already_reported );
-		}
-	}
-	
-	public void
-	stop(
-		boolean	for_queue )
-	{
-		List<TRTrackerAnnouncerHelper> to_stop;
-		
-		synchronized( this ){
-			
-			stopped	= true;
-			
-			to_stop = is_manual?announcers.getList():new ArrayList<TRTrackerAnnouncerHelper>( activated );
-			
-			activated.clear();
-		}
-		
-		for ( TRTrackerAnnouncer announcer: to_stop ){
-		
-			announcer.stop( for_queue );
-		}
-	}
-	
-	public void
-	destroy()
-	{
-		TRTrackerAnnouncerFactoryImpl.destroy( this );
-
-		List<TRTrackerAnnouncerHelper> to_destroy;
-		
-		synchronized( this ){
-			
-			destroyed = true;
-			
-			to_destroy = announcers.getList();
-		}
-		
-		for ( TRTrackerAnnouncer announcer: to_destroy ){
-		
-			announcer.destroy();
-		}
-		
-		TimerEvent	ev = event;
-		
-		if ( ev != null ){
-			
-			ev.cancel();
-		}
-	}
-	
-	public int
-	getStatus()
-	{
-		TRTrackerAnnouncer	max_announcer = getBestAnnouncer();
-		
-		return( max_announcer==null?-1:max_announcer.getStatus());
-	}
-		
-	public String
-	getStatusString()
-	{		
-		TRTrackerAnnouncer	max_announcer = getBestAnnouncer();
-		
-		return( max_announcer==null?"":max_announcer.getStatusString());
-	}
-	
-	public TRTrackerAnnouncer
-	getBestAnnouncer()
-	{
-		int	max = -1;
-		
-		TRTrackerAnnouncer	max_announcer = null;
-		
-		for ( TRTrackerAnnouncer announcer: announcers ){
-			
-			int	status = announcer.getStatus();
-			
-			if ( status > max ){
-				
-				max_announcer 	= announcer;
-				max				= status;
-			}
-		}
-		
-		return( max_announcer==null?this:max_announcer );
-	}
-	
-	public void
-	refreshListeners()
-	{
-		informURLRefresh();
-	}
-	
-	public void
-	setAnnounceResult(
-		DownloadAnnounceResult	result )
-	{
-			// this is only used for setting DHT results
-		
-		for ( TRTrackerAnnouncer announcer: announcers ){
-			
-			if ( announcer instanceof TRTrackerDHTAnnouncerImpl ){
-				
-				announcer.setAnnounceResult( result );
-				
-				return;
-			}
-		}
-		
-			// TODO: we should always create a DHT entry and have it denote DHT tracking for all circustances
-			// have the DHT plugin set it to offline if disabled
-		
-		List<TRTrackerAnnouncerHelper> x = announcers.getList();
-		
-		if ( x.size() > 0 ){
-			
-			x.get(0).setAnnounceResult( result );
-		}
-	}
-		
-	protected int
-	getPeerCacheLimit()
-	{
-		synchronized( this ){
-			
-			if ( activated.size() < announcers.size()){
-				
-				return( 0 );
-			}
-		}
-		
-		if ( SystemTime.getMonotonousTime() - create_time < 15*1000 ){
-			
-			return( 0 );
-		}
-		
-		TRTrackerAnnouncer active = getBestActive();
-		
-		if ( active != null && provider != null && active.getStatus() == TRTrackerAnnouncerResponse.ST_ONLINE ){
-			
-			if ( 	provider.getMaxNewConnectionsAllowed() > 0 &&
-					provider.getPendingConnectionCount() == 0 ){
-				
-				return( 5 );
-				
-			}else{
-				
-				return( 0 );
-			}
-		}
-		
-		return( 10 );
-	}
-	
-	public TrackerPeerSource 
-	getTrackerPeerSource(
-		final TOTorrentAnnounceURLSet		set )
-	{
-		URL[]	urls = set.getAnnounceURLs();
-		
-		final String[] url_strs = new String[ urls.length ];
-		
-		for ( int i=0;i<urls.length;i++ ){
-			
-			url_strs[i] = urls[i].toExternalForm();
-		}
-		
-		return( 
-			new TrackerPeerSource()
-			{
-				private StatusSummary		_summary;
-				private boolean				enabled;
-				private long				fixup_time;
-				
-				private StatusSummary
-				fixup()
-				{
-					long now = SystemTime.getMonotonousTime();
-					
-					if ( now - fixup_time > 1000 ){
-												
-						long			most_recent	= 0;
-						StatusSummary	summary	 	= null;
-						
-						synchronized( TRTrackerAnnouncerMuxer.this ){
-						
-							for ( String str: url_strs ){
-							
-								StatusSummary s = recent_responses.get( str );
-								
-								if ( s != null ){
-									
-									if ( summary == null || s.getTime() > most_recent ){
-										
-										summary		= s;
-										most_recent	= s.getTime();
-									}
-								}
-							}	
-						}
-						
-						if ( provider != null ){
-						
-							enabled = provider.isPeerSourceEnabled( PEPeerSource.PS_BT_TRACKER );
-						}
-						
-						if ( summary != null ){
-							
-							_summary = summary;
-						}
-						
-						fixup_time = now;
-					}
-					
-					return( _summary );
-				}
-				
-				public int
-				getType()
-				{
-					return( TrackerPeerSource.TP_TRACKER );
-				}
-				
-				public String
-				getName()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null ){
-						
-						String str =summary.getURL().toExternalForm();
-						
-						int pos = str.indexOf( '?' );
-						
-						if ( pos != -1 ){
-							
-							str = str.substring( 0, pos );
-						}
-						
-						return( str );
-					}
-					
-					return( url_strs[0] );
-				}
-				
-				public int
-				getStatus()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( !enabled ){
-						
-						return( ST_DISABLED );
-					}
-					
-					if ( summary != null ){
-						
-						return( summary.getStatus());
-					}
-					
-					return( ST_QUEUED );
-				}
-				
-				public String
-				getStatusString()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null && enabled ){
-						
-						return( summary.getStatusString());
-					}
-					
-					return( null );
-				}
-						
-				public int
-				getSeedCount()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null ){
-						
-						return( summary.getSeedCount());
-					}
-					
-					return( -1 );
-				}
-				
-				public int
-				getLeecherCount()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null ){
-						
-						return( summary.getLeecherCount());
-					}
-					
-					return( -1 );
-				}			
-				
-				public int
-				getCompletedCount()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null ){
-						
-						return( summary.getCompletedCount());
-					}
-					
-					return( -1 );
-				}			
-				
-				public int
-				getPeers()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null ){
-						
-						return( summary.getPeers());
-					}
-					
-					return( -1 );
-				}			
-
-				public int 
-				getLastUpdate() 
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null ){
-						
-						long time = summary.getTime();
-						
-						if ( time == 0 ){
-							
-							return( 0 );
-						}
-						
-						long elapsed = SystemTime.getMonotonousTime() - time;
-						
-						return((int)( (SystemTime.getCurrentTime() - elapsed ) / 1000 ));
-					}
-					
-					return( 0 );
-				}
-				
-				public int
-				getSecondsToUpdate()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null ){
-						
-						return( summary.getSecondsToUpdate());
-					}
-					
-					return( -1 );
-				}
-				
-				public int
-				getInterval()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null ){
-						
-						return( summary.getInterval());
-					}
-					
-					return( -1 );
-				}
-				
-				public int
-				getMinInterval()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null && enabled ){
-						
-						return( summary.getMinInterval());
-					}
-					
-					return( -1 );
-				}
-				
-				public boolean
-				isUpdating()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null && enabled  ){
-						
-						return( summary.isUpdating());
-					}
-					
-					return( false );
-				}
-				
-				public boolean
-				canManuallyUpdate()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary == null ){
-						
-						return( false );
-					}
-					
-					return( summary.canManuallyUpdate());
-				}
-				
-				public void
-				manualUpdate()
-				{
-					StatusSummary summary = fixup();
-					
-					if ( summary != null ){
-						
-						summary.manualUpdate();
-					}
-				}
-				
-				public boolean
-				canDelete()
-				{
-					return( false );
-				}
-				
-				public void
-				delete()
-				{
-					Debug.out( "derp" );
-				}
-			});
-	}
-	
-	public void 
-	generateEvidence(
-		IndentWriter writer )
-	{
-		for ( TRTrackerAnnouncer announcer: announcers ){
-		
-			announcer.generateEvidence(writer);
-		}
-	}
-	
-	private static class
-	StatusSummary
-	{
-		private TRTrackerAnnouncerHelper		helper;
-		
-		private long		time;
-		private URL			url;
-		private int			status;
-		private String		status_str;
-		private int			seeds		= -1;
-		private int			leechers	= -1;
-		private int			peers		= -1;
-		private int			completed	= -1;
-		
-		private int			interval;
-		private int			min_interval;
-		
-		protected 
-		StatusSummary(
-			TRTrackerAnnouncerHelper		_helper,
-			URL								_url )
-		{
-			helper	= _helper;
-			url		= _url;
-			
-			status = TrackerPeerSource.ST_QUEUED;
-		}
-		
-		protected void
-		setHelper(
-			TRTrackerAnnouncerHelper		_helper )
-		{
-			helper	= _helper;
-		}
-		
-		protected void
-		updateFrom(
-			TRTrackerAnnouncerResponse		response )
-		{			
-			time	= SystemTime.getMonotonousTime();
-			
-			int	state = response.getStatus();
-			
-			if ( state == TRTrackerAnnouncerResponse.ST_ONLINE ){
-				
-				status = TrackerPeerSource.ST_ONLINE;
-			
-				seeds		= response.getScrapeCompleteCount();
-				leechers	= response.getScrapeIncompleteCount();
-				completed	= response.getScrapeDownloadedCount();
-				peers		= response.getPeers().length;
-				
-			}else{
-				
-				status = TrackerPeerSource.ST_ERROR;
-			}
-			
-			status_str = response.getStatusString();
-			
-			interval 		= (int)helper.getInterval();
-			min_interval 	= (int)helper.getMinInterval();
-		}
-		
-		public long
-		getTime()
-		{
-			return( time );
-		}
-		
-		public URL
-		getURL()
-		{
-			return( url );
-		}
-		
-		public int
-		getStatus()
-		{
-			return( status );
-		}
-		
-		public String
-		getStatusString()
-		{
-			return( status_str );
-		}
-		
-		public int
-		getSeedCount()
-		{
-			return( seeds );
-		}
-		
-		public int
-		getLeecherCount()
-		{
-			return( leechers );
-		}
-		
-		public int
-		getCompletedCount()
-		{
-			return( completed );
-		}
-		
-		public int
-		getPeers()
-		{
-			return( peers );
-		}
-		
-		public boolean
-		isUpdating()
-		{
-			return( helper.isUpdating());
-		}
-		
-		public int
-		getInterval()
-		{
-			return( interval );
-		}
-		
-		public int
-		getMinInterval()
-		{
-			return( min_interval );
-		}
-		
-		public int
-		getSecondsToUpdate()
-		{
-			return( helper.getTimeUntilNextUpdate());
-		}
-		
-		public boolean
-		canManuallyUpdate()
-		{
-			return( ((SystemTime.getCurrentTime() / 1000 - helper.getLastUpdateTime() >= TRTrackerAnnouncer.REFRESH_MINIMUM_SECS)));
-		}
-		
-		public void
-		manualUpdate()
-		{
-			helper.update( true );
-		}
-	}
-}
+/*
+ * Created on Dec 4, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.tracker.client.impl;
+
+import java.net.URL;
+import java.util.*;
+
+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.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.TRTrackerAnnouncerDataProvider;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerException;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerFactory;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse;
+import org.gudy.azureus2.core3.tracker.client.impl.bt.TRTrackerBTAnnouncerImpl;
+import org.gudy.azureus2.core3.tracker.client.impl.dht.TRTrackerDHTAnnouncerImpl;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.IndentWriter;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+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.TorrentUtils;
+import org.gudy.azureus2.plugins.download.DownloadAnnounceResult;
+
+import com.aelitis.azureus.core.tracker.TrackerPeerSource;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
+public class 
+TRTrackerAnnouncerMuxer
+	extends TRTrackerAnnouncerImpl
+{
+	private static final int ACT_CHECK_INIT_DELAY			= 2500;
+	private static final int ACT_CHECK_INTERIM_DELAY		= 10*1000;
+	private static final int ACT_CHECK_IDLE_DELAY			= 30*1000;
+	private static final int ACT_CHECK_SEEDING_SHORT_DELAY		= 60*1000;
+	private static final int ACT_CHECK_SEEDING_LONG_DELAY		= 3*60*1000;
+	
+	
+	private TRTrackerAnnouncerFactory.DataProvider		f_provider;
+	private boolean										is_manual;
+	
+	private long				create_time = SystemTime.getMonotonousTime();
+	
+	private CopyOnWriteList<TRTrackerAnnouncerHelper>	announcers 	= new CopyOnWriteList<TRTrackerAnnouncerHelper>();
+	private Set<TRTrackerAnnouncerHelper>				activated	= new HashSet<TRTrackerAnnouncerHelper>();
+	private long										last_activation_time;
+	private Set<String>									failed_urls	= new HashSet<String>();
+	
+	private volatile TimerEvent					event;
+	
+	private TRTrackerAnnouncerDataProvider		provider;
+	private String								ip_override;
+	private boolean								complete;
+	private boolean								stopped;
+	private boolean								destroyed;
+	
+	private String[]							current_networks;
+	
+	private TRTrackerAnnouncerHelper			last_best_active;
+	private long								last_best_active_set_time;
+	
+	private Map<String,StatusSummary>			recent_responses = new HashMap<String,StatusSummary>();
+	
+	private TRTrackerAnnouncerResponse			last_response_informed;
+
+	
+	protected
+	TRTrackerAnnouncerMuxer(
+		TOTorrent								_torrent,
+		TRTrackerAnnouncerFactory.DataProvider	_f_provider,
+		boolean									_manual )
+	
+		throws TRTrackerAnnouncerException
+	{
+		super( _torrent );
+		
+		try{	
+			last_response_informed = new TRTrackerAnnouncerResponseImpl( null, _torrent.getHashWrapper(), TRTrackerAnnouncerResponse.ST_OFFLINE, TRTrackerAnnouncer.REFRESH_MINIMUM_SECS, "Initialising" );
+			
+		}catch( TOTorrentException e ){
+			
+			Logger.log(new LogEvent( _torrent, LOGID, "Torrent hash retrieval fails", e));
+			
+			throw( new TRTrackerAnnouncerException( "TRTrackerAnnouncer: URL encode fails"));	
+		}
+
+		is_manual 	= _manual;
+		f_provider	= _f_provider;
+		
+		split( true );
+	}
+	
+	protected void
+	split(
+		boolean	first_time )
+	
+		throws TRTrackerAnnouncerException
+	{
+		String[]	networks = f_provider==null?null:f_provider.getNetworks();
+		
+		boolean	force_recreate = false;
+		
+		if ( !first_time ){
+			
+			if ( current_networks != networks ){
+			
+				if ( current_networks == null || networks == null ){
+					
+					force_recreate = true;
+					
+				}else{
+					
+					if ( networks.length != current_networks.length ){
+						
+						force_recreate = true;
+						
+					}else{
+						
+						for ( String net1: current_networks ){
+							
+							boolean	match = false;
+							
+							for ( String net2: networks ){
+								
+								if ( net1 == net2 ){
+									
+									match = true;
+								}
+							}
+							
+							if ( !match ){
+								
+								force_recreate = true;
+								
+								break;
+							}
+						}
+					}
+				}
+			}
+		}
+		
+		current_networks = networks;
+		
+		TRTrackerAnnouncerHelper to_activate = null;
+		
+		synchronized( this ){
+			
+			if ( stopped || destroyed ){
+				
+				return;
+			}
+			
+			TOTorrent torrent = getTorrent();
+					
+			TOTorrentAnnounceURLSet[]	sets = torrent.getAnnounceURLGroup().getAnnounceURLSets();
+			
+				// sanitise dht entries
+			
+			if ( sets.length == 0 ){
+				
+				sets = new TOTorrentAnnounceURLSet[]{ torrent.getAnnounceURLGroup().createAnnounceURLSet( new URL[]{ torrent.getAnnounceURL()})};
+				
+			}else{
+				
+				boolean	found_decentralised = false;
+				boolean	modified			= false;
+				
+				for ( int i=0;i<sets.length;i++ ){
+					
+					TOTorrentAnnounceURLSet set = sets[i];
+					
+					URL[] urls = set.getAnnounceURLs().clone();
+					
+					for (int j=0;j<urls.length;j++){
+						
+						URL u = urls[j];
+						
+						if ( u != null && TorrentUtils.isDecentralised( u )){
+														
+							if ( found_decentralised ){
+								
+								modified = true;
+								
+								urls[j] = null;
+								
+							}else{
+								
+								found_decentralised = true;
+							}
+						}
+					}
+				}
+				
+				if ( modified ){
+					
+					List<TOTorrentAnnounceURLSet> s_list = new ArrayList<TOTorrentAnnounceURLSet>();
+					
+					for ( TOTorrentAnnounceURLSet set: sets ){
+						
+						URL[] urls = set.getAnnounceURLs();
+						
+						List<URL> u_list = new ArrayList<URL>( urls.length );
+						
+						for ( URL u: urls ){
+							
+							if ( u != null ){
+								
+								u_list.add( u );
+							}
+						}
+						
+						if ( u_list.size() > 0 ){
+							
+							s_list.add( torrent.getAnnounceURLGroup().createAnnounceURLSet( u_list.toArray( new URL[ u_list.size() ])));
+						}
+					}
+					
+					sets = s_list.toArray( new TOTorrentAnnounceURLSet[ s_list.size() ]);
+				}
+			}
+			
+			List<TOTorrentAnnounceURLSet[]>	new_sets = new ArrayList<TOTorrentAnnounceURLSet[]>();
+			
+			if ( is_manual || sets.length < 2 ){
+					
+				new_sets.add( sets );
+				
+			}else{
+				
+				List<TOTorrentAnnounceURLSet> list = new ArrayList<TOTorrentAnnounceURLSet>( Arrays.asList( sets ));
+				
+					// often we have http:/xxxx/ and udp:/xxxx/ as separate groups - keep these together
+								
+				while( list.size() > 0 ){
+					
+					TOTorrentAnnounceURLSet set1 = list.remove(0);
+					
+					boolean	done = false;
+					
+					URL[] urls1 = set1.getAnnounceURLs();
+					
+					if ( urls1.length == 1 ){
+						
+						URL url1 = urls1[0];
+						
+						String prot1 = url1.getProtocol().toLowerCase();
+						String host1	= url1.getHost();
+						
+						for (int i=0;i<list.size();i++){
+							
+							TOTorrentAnnounceURLSet set2 = list.get(i);
+							
+							URL[] urls2 = set2.getAnnounceURLs();
+							
+							if ( urls2.length == 1 ){
+								
+								URL url2 = urls2[0];
+								
+								String prot2 = url2.getProtocol().toLowerCase();
+								String host2 = url2.getHost();
+				
+								if ( host1.equals( host2 )){
+									
+									if (	( prot1.equals( "udp" ) && prot2.startsWith( "http" )) ||
+											( prot2.equals( "udp" ) && prot1.startsWith( "http" ))){
+										
+										list.remove( i );
+										
+										new_sets.add( new TOTorrentAnnounceURLSet[]{ set1, set2 });
+										
+										done	= true;
+									}
+								}
+							}
+						}
+					}
+					
+					if ( !done ){
+						
+						new_sets.add( new TOTorrentAnnounceURLSet[]{ set1 });
+					}
+				}
+			}
+			
+				// work out the difference
+			
+			Iterator<TOTorrentAnnounceURLSet[]> ns_it = new_sets.iterator();
+			
+				// need to copy list as we modify it and returned list ain't thread safe
+			
+			List<TRTrackerAnnouncerHelper> existing_announcers 	= new ArrayList<TRTrackerAnnouncerHelper>( announcers.getList());
+			
+			List<TRTrackerAnnouncerHelper> new_announcers 		= new ArrayList<TRTrackerAnnouncerHelper>();
+			
+				// first look for unchanged sets
+			
+			if ( !force_recreate ){
+				
+				while( ns_it.hasNext()){
+					
+					TOTorrentAnnounceURLSet[] ns = ns_it.next();
+					
+					Iterator<TRTrackerAnnouncerHelper> a_it = existing_announcers.iterator();
+						
+					while( a_it.hasNext()){
+						
+						TRTrackerAnnouncerHelper a = a_it.next();
+						
+						TOTorrentAnnounceURLSet[] os = a.getAnnounceSets();
+						
+						if ( same( ns, os )){
+							
+							ns_it.remove();
+							a_it.remove();
+							
+							new_announcers.add( a );
+							
+							break;
+						}
+					}
+				}
+			}
+								
+				// first remove dht ones from the equation
+			
+			TRTrackerAnnouncerHelper 	existing_dht_announcer 	= null;
+			TOTorrentAnnounceURLSet[]	new_dht_set				= null;
+
+			ns_it = new_sets.iterator();
+			
+			while( ns_it.hasNext()){
+				
+				TOTorrentAnnounceURLSet[] x = ns_it.next();
+				
+				if ( TorrentUtils.isDecentralised( x[0].getAnnounceURLs()[0])){
+					
+					new_dht_set = x;
+						
+					ns_it.remove();
+					
+					break;
+				}
+			}
+			
+			Iterator<TRTrackerAnnouncerHelper>	an_it = existing_announcers.iterator();
+			
+			while( an_it.hasNext()){
+				
+				TRTrackerAnnouncerHelper a = an_it.next();
+				
+				TOTorrentAnnounceURLSet[] x = a.getAnnounceSets();
+				
+				if ( TorrentUtils.isDecentralised( x[0].getAnnounceURLs()[0])){
+					
+					existing_dht_announcer = a;
+						
+					an_it.remove();
+					
+					break;
+				}
+			}
+	
+			if ( existing_dht_announcer != null && new_dht_set != null ){
+				
+				new_announcers.add( existing_dht_announcer );
+				
+			}else if ( existing_dht_announcer != null ){
+				
+				activated.remove( existing_dht_announcer );
+				
+				existing_dht_announcer.destroy();
+				
+			}else if ( new_dht_set != null ){
+				
+				TRTrackerAnnouncerHelper a = create( torrent, networks, new_dht_set );
+				
+				new_announcers.add( a );
+			}
+			
+				// create any new ones required
+			
+			ns_it = new_sets.iterator();
+			
+			while( ns_it.hasNext()){
+				
+				TOTorrentAnnounceURLSet[] s = ns_it.next();
+				
+				TRTrackerAnnouncerHelper a = create( torrent, networks, s );
+				
+				new_announcers.add( a );
+			}
+			
+				// finally fix up the announcer list to represent the new state
+			
+			Iterator<TRTrackerAnnouncerHelper>	a_it = announcers.iterator();
+				
+			while( a_it.hasNext()){
+				
+				TRTrackerAnnouncerHelper a = a_it.next();
+				
+				if ( !new_announcers.contains( a )){
+					
+					a_it.remove();
+					
+					try{
+						if ( 	activated.contains( a ) &&
+								torrent.getPrivate() && 
+								a instanceof TRTrackerBTAnnouncerImpl ){
+							
+							URL url = a.getTrackerURL();
+						
+							if ( url != null ){
+								
+								forceStop((TRTrackerBTAnnouncerImpl)a, networks, url );
+							}
+						}
+					}finally{
+						
+						if (Logger.isEnabled()) {
+							Logger.log(new LogEvent(getTorrent(), LOGID, "Deactivating " + getString( a.getAnnounceSets())));
+						}
+
+						activated.remove( a );
+												
+						a.destroy();
+					}
+				}
+			}
+			
+			a_it = new_announcers.iterator();
+			
+			while( a_it.hasNext()){
+				
+				TRTrackerAnnouncerHelper a = a_it.next();
+				
+				if ( !announcers.contains( a )){
+					
+					announcers.add( a );
+				}
+			}
+			
+			if ( !is_manual && announcers.size() > 0 ){
+				
+				if ( activated.size() == 0 ){
+					
+					TRTrackerAnnouncerHelper a = announcers.get(0);
+					
+					if (Logger.isEnabled()) {
+						Logger.log(new LogEvent(getTorrent(), LOGID, "Activating " + getString( a.getAnnounceSets())));
+					}
+
+					activated.add( a );
+					
+					last_activation_time = SystemTime.getMonotonousTime();
+					
+					if ( provider != null ){
+						
+						to_activate = a;
+					}
+				}
+				
+				setupActivationCheck( ACT_CHECK_INIT_DELAY );
+			}
+		}
+		
+		if ( to_activate != null ){
+			
+			if ( complete ){
+				
+				to_activate.complete( true );
+				
+			}else{
+				
+				to_activate.update( false );
+			}
+		}
+	}
+	
+	protected void
+	setupActivationCheck(
+		int		delay )
+	{
+		if ( announcers.size() > activated.size()){
+			
+			event = SimpleTimer.addEvent(
+				"TRMuxer:check",
+				SystemTime.getOffsetTime( delay ),
+				new TimerEventPerformer()
+				{
+					public void 
+					perform(
+						TimerEvent event )
+					{
+						checkActivation( false );
+					}
+				});
+		}
+	}
+	
+	protected void
+	checkActivation(
+		boolean		force )
+	{
+		synchronized( this ){
+			
+			int	next_check_delay;
+			
+			if ( 	destroyed || 
+					stopped || 
+					announcers.size() <= activated.size()){
+
+				return;
+			}
+			
+			if ( provider == null ){
+				
+				next_check_delay = ACT_CHECK_INIT_DELAY;
+				
+			}else{
+
+				boolean	activate = force;
+														
+				boolean	seeding = provider.getRemaining() == 0;
+
+				if ( seeding && activated.size() > 0 ){
+				
+						// when seeding we only activate on tracker fail or major lack of connections
+						// as normally we rely on downloaders rotating and finding us
+
+					int	connected	= provider.getConnectedConnectionCount();
+
+					if ( connected < 1 ){
+						
+						activate = SystemTime.getMonotonousTime() - last_activation_time >= 60*1000;
+						
+						next_check_delay = ACT_CHECK_SEEDING_SHORT_DELAY;
+						
+					}else if ( connected < 3 ){
+						
+						next_check_delay = ACT_CHECK_SEEDING_LONG_DELAY;
+						
+					}else{
+						
+						next_check_delay = 0;
+					}
+				}else{
+					
+					int	allowed		= provider.getMaxNewConnectionsAllowed();	// -1 -> unlimited
+					int	pending		= provider.getPendingConnectionCount();
+					int	connected	= provider.getConnectedConnectionCount();
+					
+					int	online = 0;
+					
+					for ( TRTrackerAnnouncerHelper a: activated ){
+						
+						TRTrackerAnnouncerResponse response = a.getLastResponse();
+						
+						if ( 	response != null && 
+								response.getStatus() == TRTrackerAnnouncerResponse.ST_ONLINE ){
+							
+							online++;
+						}
+					}
+					
+					/*
+					System.out.println( 
+						"checkActivation: announcers=" + announcers.size() + 
+						", active=" + activated.size() +
+						", online=" + online +
+						", allowed=" + allowed +
+						", pending=" + pending +
+						", connected=" + connected +
+						", seeding=" + seeding );
+					*/
+					
+					if ( online == 0 ){
+						
+						activate = true;
+						
+							// no trackers online, start next and recheck soon
+						
+						next_check_delay = ACT_CHECK_INIT_DELAY;
+						
+					}else{
+						
+						int	potential = connected + pending;
+						
+						if ( potential < 10 ){
+							
+								// minimal connectivity 
+							
+							activate = true;
+							
+							next_check_delay = ACT_CHECK_INIT_DELAY;
+
+						}else if ( allowed < 0 || ( allowed >= 5 && pending < 3*allowed/4 )){
+							
+								// not enough to fulfill our needs
+							
+							activate = true;
+							
+							next_check_delay = ACT_CHECK_INTERIM_DELAY;
+							
+						}else{
+								// things look good, recheck in a bit
+							
+							next_check_delay = ACT_CHECK_IDLE_DELAY;
+						}
+					}
+				}
+					
+				if ( activate ){
+					
+					for ( TRTrackerAnnouncerHelper a: announcers ){
+						
+						if ( !activated.contains( a )){
+							
+							if (Logger.isEnabled()) {
+								Logger.log(new LogEvent(getTorrent(), LOGID, "Activating " + getString( a.getAnnounceSets())));
+							}
+							
+							activated.add( a );
+							
+							last_activation_time = SystemTime.getMonotonousTime();
+							
+							if ( complete ){
+								
+								a.complete( true );
+								
+							}else{
+								
+								a.update( false );
+							}
+							
+							break;
+						}
+					}
+				}
+			}
+			
+			if ( next_check_delay > 0 ){
+			
+				setupActivationCheck( next_check_delay );
+			}
+		}
+	}
+	
+	private String
+	getString(
+		TOTorrentAnnounceURLSet[]	sets )
+	{
+		StringBuffer str = new StringBuffer();
+		
+		str.append( "[" );
+		
+		int	num1 = 0;
+		
+		for ( TOTorrentAnnounceURLSet s: sets ){
+			
+			if ( num1++ > 0 ){
+				str.append( ", ");
+			}
+			
+			str.append( "[" );
+
+			URL[]	urls = s.getAnnounceURLs();
+			
+			int	num2 = 0;
+			
+			for ( URL u: urls ){
+				
+				if ( num2++ > 0 ){
+					str.append( ", ");
+				}
+				
+				str.append( u.toExternalForm());
+			}
+			
+			str.append( "]" );
+		}
+		
+		str.append( "]" );
+		
+		return( str.toString());
+	}
+	
+	private boolean
+	same(
+		TOTorrentAnnounceURLSet[]	s1,
+		TOTorrentAnnounceURLSet[]	s2 )
+	{
+		boolean	res = sameSupport( s1, s2 );
+		
+		// System.out.println( "same->" + res + ": " + getString(s1) + "/" + getString(s2));
+		
+		return( res );
+	}
+	
+	private boolean
+	sameSupport(
+		TOTorrentAnnounceURLSet[]	s1,
+		TOTorrentAnnounceURLSet[]	s2 )
+	{
+		if ( s1.length != s2.length ){
+			
+			return( false );
+		}
+		
+		for (int i=0;i<s1.length;i++){
+			
+			URL[] u1 = s1[i].getAnnounceURLs();
+			URL[] u2 = s2[i].getAnnounceURLs();
+			
+			if ( u1.length != u2.length ){
+				
+				return( false );
+			}
+			
+			if ( u1.length == 1 ){
+				
+				return( u1[0].toExternalForm().equals( u2[0].toExternalForm()));
+			}
+			
+			Set<String> set1 = new HashSet<String>();
+			
+			for ( URL u: u1 ){
+				
+				set1.add( u.toExternalForm());
+			}
+			
+			Set<String> set2 = new HashSet<String>();
+			
+			for ( URL u: u2 ){
+				
+				set2.add( u.toExternalForm());
+			}
+			
+			if ( !set1.equals( set2 )){
+				
+				return( false );
+			}
+		}
+		
+		return( true );
+	}
+	
+	protected void
+	forceStop(
+		final TRTrackerBTAnnouncerImpl		announcer,
+		final String[]						networks,
+		final URL							url )
+	{
+		if (Logger.isEnabled()) {
+			Logger.log(new LogEvent(getTorrent(), LOGID, "Force stopping " + url + " as private torrent" ));
+		}
+		
+		new AEThread2( "TRMux:fs", true )
+		{
+			public void
+			run()
+			{
+				try{
+					TRTrackerBTAnnouncerImpl an = 
+						new TRTrackerBTAnnouncerImpl( getTorrent(), new TOTorrentAnnounceURLSet[0], networks, true, getHelper());
+					
+					an.cloneFrom( announcer );
+					
+					an.setTrackerURL( url );
+					
+					an.stop( false );
+					
+					an.destroy();
+					
+				}catch( Throwable e ){
+					
+				}
+			}
+		}.start();
+	}
+	
+	private TRTrackerAnnouncerHelper
+	create(
+		TOTorrent						torrent,
+		String[]						networks,
+		TOTorrentAnnounceURLSet[]		sets )
+	
+		throws TRTrackerAnnouncerException
+	{
+		TRTrackerAnnouncerHelper announcer;
+		
+		boolean	decentralised;
+		
+		if ( sets.length == 0 ){
+			
+			decentralised = TorrentUtils.isDecentralised( torrent.getAnnounceURL());
+			
+		}else{
+			
+			decentralised = TorrentUtils.isDecentralised( sets[0].getAnnounceURLs()[0]);
+		}
+		
+		if ( decentralised ){
+			
+			announcer	= new TRTrackerDHTAnnouncerImpl( torrent, networks, is_manual, getHelper());
+			
+		}else{
+			
+			announcer = new TRTrackerBTAnnouncerImpl( torrent, sets, networks, is_manual, getHelper());
+		}
+		
+		for ( TOTorrentAnnounceURLSet set: sets ){
+			
+			URL[] urls = set.getAnnounceURLs();
+			
+			for ( URL u: urls ){
+				
+				String key = u.toExternalForm();
+				
+				StatusSummary summary = recent_responses.get( key );
+				
+				if ( summary == null ){
+					
+					summary = new StatusSummary( announcer, u );
+										
+					recent_responses.put( key, summary );
+					
+				}else{
+					
+					summary.setHelper( announcer );
+				}
+			}
+		}
+		
+		if ( provider != null ){
+			
+			announcer.setAnnounceDataProvider( provider );
+		}
+		
+		if ( ip_override != null ){
+			
+			announcer.setIPOverride( ip_override );
+		}
+		
+		return( announcer );
+	}
+	
+	
+	public TRTrackerAnnouncerResponse
+	getLastResponse()
+	{
+		TRTrackerAnnouncerResponse	result = null;
+		
+		TRTrackerAnnouncerHelper best = getBestActive();
+		
+		if ( best != null ){
+			
+			result = best.getLastResponse();
+		}
+		
+		if ( result == null ){
+			
+			result = last_response_informed;
+		}
+		
+		return( result );
+	}
+	
+
+	@Override
+	protected void
+	informResponse(
+		TRTrackerAnnouncerHelper		helper,
+		TRTrackerAnnouncerResponse		response )
+	{
+		URL	url = response.getURL();
+		
+			// can be null for external plugins (e.g. mldht...)
+		
+		if ( url != null ){
+			
+			synchronized( this ){
+				
+				String key = url.toExternalForm();
+				
+				StatusSummary summary = recent_responses.get( key );
+			
+				if ( summary != null ){
+				
+					summary.updateFrom( response );
+				}
+			}
+		}
+		
+		last_response_informed = response;
+		
+			// force recalc of best active next time
+		
+		last_best_active_set_time = 0;
+		
+		super.informResponse( helper, response );
+		
+		if ( response.getStatus() != TRTrackerAnnouncerResponse.ST_ONLINE ){
+			
+			URL	u = response.getURL();
+			
+			if ( u != null ){
+				
+				String s = u.toExternalForm();
+				
+				synchronized( failed_urls ){
+					
+					if ( failed_urls.contains( s )){
+						
+						return;
+					}
+					
+					failed_urls.add( s );
+				}
+			}
+			
+			checkActivation( true );
+		}
+	}
+	
+	public boolean
+	isManual()
+	{
+		return( is_manual );
+	}
+
+	public void
+	setAnnounceDataProvider(
+		TRTrackerAnnouncerDataProvider		_provider )
+	{
+		List<TRTrackerAnnouncerHelper>	to_set;
+		
+		synchronized( this ){
+			
+			provider	= _provider;
+			
+			to_set = announcers.getList();
+		}
+		
+		for ( TRTrackerAnnouncer announcer: to_set ){
+		
+			announcer.setAnnounceDataProvider( provider );
+		}
+	}
+	
+	protected TRTrackerAnnouncerHelper
+	getBestActive()
+	{
+		long	now = SystemTime.getMonotonousTime();
+		
+		if ( now - last_best_active_set_time < 1000 ){
+			
+			return( last_best_active );
+		}
+		
+		last_best_active = getBestActiveSupport();
+		
+		last_best_active_set_time = now;
+		
+		return( last_best_active );
+	}
+	
+	protected TRTrackerAnnouncerHelper
+	getBestActiveSupport()
+	{
+		List<TRTrackerAnnouncerHelper> x = announcers.getList();
+		
+		TRTrackerAnnouncerHelper error_resp = null;
+		
+		for ( TRTrackerAnnouncerHelper announcer: x ){
+			
+			TRTrackerAnnouncerResponse response = announcer.getLastResponse();
+			
+			if ( response != null ){
+				
+				int	resp_status = response.getStatus();
+				
+				if ( resp_status == TRTrackerAnnouncerResponse.ST_ONLINE ){
+					
+					return( announcer );
+					
+				}else if ( error_resp == null && resp_status == TRTrackerAnnouncerResponse.ST_REPORTED_ERROR ){
+					
+					error_resp = announcer;
+				}
+			}
+		}
+		
+		if ( error_resp != null ){
+			
+			return( error_resp );
+		}
+		
+		if ( x.size() > 0 ){
+			
+			return( x.get(0));
+		}
+		
+		return( null );
+	}
+	
+	public URL
+	getTrackerURL()
+	{
+		TRTrackerAnnouncerHelper	active = getBestActive();
+		
+		if ( active != null ){
+			
+			return( active.getTrackerURL());
+		}
+		
+		return( null );
+	}
+	
+	public void
+	setTrackerURL(
+		URL		url )
+	{
+		List<List<String>> groups = new ArrayList<List<String>>();
+		
+		List<String> group = new ArrayList<String>();
+		
+		group.add( url.toExternalForm());
+		
+		groups.add( group );
+		
+		TorrentUtils.listToAnnounceGroups( groups, getTorrent());
+		
+		resetTrackerUrl( false );
+	}
+	
+	public void
+	resetTrackerUrl(
+		boolean	shuffle )
+	{
+		try{
+			split( false );
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+		
+		for ( TRTrackerAnnouncer announcer: announcers ){
+		
+			announcer.resetTrackerUrl( shuffle );
+		}
+	}
+	
+	public void
+	setIPOverride(
+		String		override )
+	{
+		List<TRTrackerAnnouncerHelper>	to_set;
+		
+		synchronized( this ){
+			
+			to_set	= announcers.getList();
+			
+			ip_override	= override;
+		}
+		
+		for ( TRTrackerAnnouncer announcer: to_set ){
+		
+			announcer.setIPOverride( override );
+		}
+	}
+	
+	public void
+	clearIPOverride()
+	{
+		List<TRTrackerAnnouncerHelper>	to_clear;
+		
+		synchronized( this ){
+			
+			to_clear	= announcers.getList();
+			
+			ip_override	= null;
+		}
+		
+		for ( TRTrackerAnnouncer announcer: to_clear ){
+		
+			announcer.clearIPOverride();
+		}
+	}
+	
+	public void
+	setRefreshDelayOverrides(
+		int		percentage )
+	{
+		for ( TRTrackerAnnouncer announcer: announcers ){
+		
+			announcer.setRefreshDelayOverrides( percentage );
+		}
+	}
+	
+	public int
+	getTimeUntilNextUpdate()
+	{
+		TRTrackerAnnouncerHelper	active = getBestActive();
+
+		if ( active != null ){
+			
+			return( active.getTimeUntilNextUpdate());
+		}
+		
+		return( Integer.MAX_VALUE );
+	}
+	
+	public int
+	getLastUpdateTime()
+	{
+		TRTrackerAnnouncerHelper	active = getBestActive();
+
+		if ( active != null ){
+			
+			return( active.getLastUpdateTime());
+		}
+		
+		return( 0 );
+	}	
+	
+	public void
+	update(
+		boolean	force )
+	{
+		List<TRTrackerAnnouncerHelper> to_update;
+		
+		synchronized( this ){
+						
+			to_update = is_manual?announcers.getList():new ArrayList<TRTrackerAnnouncerHelper>( activated );
+		}
+		
+		for ( TRTrackerAnnouncer announcer: to_update ){
+		
+			announcer.update(force);
+		}
+	}
+	
+	public void
+	complete(
+		boolean	already_reported )
+	{
+		List<TRTrackerAnnouncerHelper> to_complete;
+		
+		synchronized( this ){
+			
+			complete	= true;
+			
+			to_complete = is_manual?announcers.getList():new ArrayList<TRTrackerAnnouncerHelper>( activated );
+		}
+		
+		for ( TRTrackerAnnouncer announcer: to_complete ){
+		
+			announcer.complete( already_reported );
+		}
+	}
+	
+	public void
+	stop(
+		boolean	for_queue )
+	{
+		List<TRTrackerAnnouncerHelper> to_stop;
+		
+		synchronized( this ){
+			
+			stopped	= true;
+			
+			to_stop = is_manual?announcers.getList():new ArrayList<TRTrackerAnnouncerHelper>( activated );
+			
+			activated.clear();
+		}
+		
+		for ( TRTrackerAnnouncer announcer: to_stop ){
+		
+			announcer.stop( for_queue );
+		}
+	}
+	
+	public void
+	destroy()
+	{
+		TRTrackerAnnouncerFactoryImpl.destroy( this );
+
+		List<TRTrackerAnnouncerHelper> to_destroy;
+		
+		synchronized( this ){
+			
+			destroyed = true;
+			
+			to_destroy = announcers.getList();
+		}
+		
+		for ( TRTrackerAnnouncer announcer: to_destroy ){
+		
+			announcer.destroy();
+		}
+		
+		TimerEvent	ev = event;
+		
+		if ( ev != null ){
+			
+			ev.cancel();
+		}
+	}
+	
+	public int
+	getStatus()
+	{
+		TRTrackerAnnouncer	max_announcer = getBestAnnouncer();
+		
+		return( max_announcer==null?-1:max_announcer.getStatus());
+	}
+		
+	public String
+	getStatusString()
+	{		
+		TRTrackerAnnouncer	max_announcer = getBestAnnouncer();
+		
+		return( max_announcer==null?"":max_announcer.getStatusString());
+	}
+	
+	public TRTrackerAnnouncer
+	getBestAnnouncer()
+	{
+		int	max = -1;
+		
+		TRTrackerAnnouncer	max_announcer = null;
+		
+		for ( TRTrackerAnnouncer announcer: announcers ){
+			
+			int	status = announcer.getStatus();
+			
+			if ( status > max ){
+				
+				max_announcer 	= announcer;
+				max				= status;
+			}
+		}
+		
+		return( max_announcer==null?this:max_announcer );
+	}
+	
+	public void
+	refreshListeners()
+	{
+		informURLRefresh();
+	}
+	
+	public void
+	setAnnounceResult(
+		DownloadAnnounceResult	result )
+	{
+			// this is only used for setting DHT results
+		
+		for ( TRTrackerAnnouncer announcer: announcers ){
+			
+			if ( announcer instanceof TRTrackerDHTAnnouncerImpl ){
+				
+				announcer.setAnnounceResult( result );
+				
+				return;
+			}
+		}
+		
+			// TODO: we should always create a DHT entry and have it denote DHT tracking for all circustances
+			// have the DHT plugin set it to offline if disabled
+		
+		List<TRTrackerAnnouncerHelper> x = announcers.getList();
+		
+		if ( x.size() > 0 ){
+			
+			x.get(0).setAnnounceResult( result );
+		}
+	}
+		
+	protected int
+	getPeerCacheLimit()
+	{
+		synchronized( this ){
+			
+			if ( activated.size() < announcers.size()){
+				
+				return( 0 );
+			}
+		}
+		
+		if ( SystemTime.getMonotonousTime() - create_time < 15*1000 ){
+			
+			return( 0 );
+		}
+		
+		TRTrackerAnnouncer active = getBestActive();
+		
+		if ( active != null && provider != null && active.getStatus() == TRTrackerAnnouncerResponse.ST_ONLINE ){
+			
+			if ( 	provider.getMaxNewConnectionsAllowed() != 0 &&
+					provider.getPendingConnectionCount() == 0 ){
+				
+				return( 5 );
+				
+			}else{
+				
+				return( 0 );
+			}
+		}
+		
+		return( 10 );
+	}
+	
+	public TrackerPeerSource 
+	getTrackerPeerSource(
+		final TOTorrentAnnounceURLSet		set )
+	{
+		URL[]	urls = set.getAnnounceURLs();
+		
+		final String[] url_strs = new String[ urls.length ];
+		
+		for ( int i=0;i<urls.length;i++ ){
+			
+			url_strs[i] = urls[i].toExternalForm();
+		}
+		
+		return( 
+			new TrackerPeerSource()
+			{
+				private StatusSummary		_summary;
+				private boolean				enabled;
+				private long				fixup_time;
+				
+				private StatusSummary
+				fixup()
+				{
+					long now = SystemTime.getMonotonousTime();
+					
+					if ( now - fixup_time > 1000 ){
+												
+						long			most_recent	= 0;
+						StatusSummary	summary	 	= null;
+						
+						synchronized( TRTrackerAnnouncerMuxer.this ){
+						
+							for ( String str: url_strs ){
+							
+								StatusSummary s = recent_responses.get( str );
+								
+								if ( s != null ){
+									
+									if ( summary == null || s.getTime() > most_recent ){
+										
+										summary		= s;
+										most_recent	= s.getTime();
+									}
+								}
+							}	
+						}
+						
+						if ( provider != null ){
+						
+							enabled = provider.isPeerSourceEnabled( PEPeerSource.PS_BT_TRACKER );
+						}
+						
+						if ( summary != null ){
+							
+							_summary = summary;
+						}
+						
+						fixup_time = now;
+					}
+					
+					return( _summary );
+				}
+				
+				public int
+				getType()
+				{
+					return( TrackerPeerSource.TP_TRACKER );
+				}
+				
+				public String
+				getName()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null ){
+						
+						String str =summary.getURL().toExternalForm();
+						
+						int pos = str.indexOf( '?' );
+						
+						if ( pos != -1 ){
+							
+							str = str.substring( 0, pos );
+						}
+						
+						return( str );
+					}
+					
+					return( url_strs[0] );
+				}
+				
+				public int
+				getStatus()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( !enabled ){
+						
+						return( ST_DISABLED );
+					}
+					
+					if ( summary != null ){
+						
+						return( summary.getStatus());
+					}
+					
+					return( ST_QUEUED );
+				}
+				
+				public String
+				getStatusString()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null && enabled ){
+						
+						return( summary.getStatusString());
+					}
+					
+					return( null );
+				}
+						
+				public int
+				getSeedCount()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null ){
+						
+						return( summary.getSeedCount());
+					}
+					
+					return( -1 );
+				}
+				
+				public int
+				getLeecherCount()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null ){
+						
+						return( summary.getLeecherCount());
+					}
+					
+					return( -1 );
+				}			
+				
+				public int
+				getCompletedCount()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null ){
+						
+						return( summary.getCompletedCount());
+					}
+					
+					return( -1 );
+				}			
+				
+				public int
+				getPeers()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null ){
+						
+						return( summary.getPeers());
+					}
+					
+					return( -1 );
+				}			
+
+				public int 
+				getLastUpdate() 
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null ){
+						
+						long time = summary.getTime();
+						
+						if ( time == 0 ){
+							
+							return( 0 );
+						}
+						
+						long elapsed = SystemTime.getMonotonousTime() - time;
+						
+						return((int)( (SystemTime.getCurrentTime() - elapsed ) / 1000 ));
+					}
+					
+					return( 0 );
+				}
+				
+				public int
+				getSecondsToUpdate()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null ){
+						
+						return( summary.getSecondsToUpdate());
+					}
+					
+					return( -1 );
+				}
+				
+				public int
+				getInterval()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null ){
+						
+						return( summary.getInterval());
+					}
+					
+					return( -1 );
+				}
+				
+				public int
+				getMinInterval()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null && enabled ){
+						
+						return( summary.getMinInterval());
+					}
+					
+					return( -1 );
+				}
+				
+				public boolean
+				isUpdating()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null && enabled  ){
+						
+						return( summary.isUpdating());
+					}
+					
+					return( false );
+				}
+				
+				public boolean
+				canManuallyUpdate()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary == null ){
+						
+						return( false );
+					}
+					
+					return( summary.canManuallyUpdate());
+				}
+				
+				public void
+				manualUpdate()
+				{
+					StatusSummary summary = fixup();
+					
+					if ( summary != null ){
+						
+						summary.manualUpdate();
+					}
+				}
+				
+				public boolean
+				canDelete()
+				{
+					return( false );
+				}
+				
+				public void
+				delete()
+				{
+					Debug.out( "derp" );
+				}
+			});
+	}
+	
+	public void 
+	generateEvidence(
+		IndentWriter writer )
+	{
+		for ( TRTrackerAnnouncer announcer: announcers ){
+		
+			announcer.generateEvidence(writer);
+		}
+	}
+	
+	private static class
+	StatusSummary
+	{
+		private TRTrackerAnnouncerHelper		helper;
+		
+		private long		time;
+		private URL			url;
+		private int			status;
+		private String		status_str;
+		private int			seeds		= -1;
+		private int			leechers	= -1;
+		private int			peers		= -1;
+		private int			completed	= -1;
+		
+		private int			interval;
+		private int			min_interval;
+		
+		protected 
+		StatusSummary(
+			TRTrackerAnnouncerHelper		_helper,
+			URL								_url )
+		{
+			helper	= _helper;
+			url		= _url;
+			
+			status = TrackerPeerSource.ST_QUEUED;
+		}
+		
+		protected void
+		setHelper(
+			TRTrackerAnnouncerHelper		_helper )
+		{
+			helper	= _helper;
+		}
+		
+		protected void
+		updateFrom(
+			TRTrackerAnnouncerResponse		response )
+		{			
+			time	= SystemTime.getMonotonousTime();
+			
+			int	state = response.getStatus();
+			
+			if ( state == TRTrackerAnnouncerResponse.ST_ONLINE ){
+				
+				status = TrackerPeerSource.ST_ONLINE;
+			
+				seeds		= response.getScrapeCompleteCount();
+				leechers	= response.getScrapeIncompleteCount();
+				completed	= response.getScrapeDownloadedCount();
+				peers		= response.getPeers().length;
+				
+			}else{
+				
+				status = TrackerPeerSource.ST_ERROR;
+			}
+			
+			status_str = response.getStatusString();
+			
+			interval 		= (int)helper.getInterval();
+			min_interval 	= (int)helper.getMinInterval();
+		}
+		
+		public long
+		getTime()
+		{
+			return( time );
+		}
+		
+		public URL
+		getURL()
+		{
+			return( url );
+		}
+		
+		public int
+		getStatus()
+		{
+			return( status );
+		}
+		
+		public String
+		getStatusString()
+		{
+			return( status_str );
+		}
+		
+		public int
+		getSeedCount()
+		{
+			return( seeds );
+		}
+		
+		public int
+		getLeecherCount()
+		{
+			return( leechers );
+		}
+		
+		public int
+		getCompletedCount()
+		{
+			return( completed );
+		}
+		
+		public int
+		getPeers()
+		{
+			return( peers );
+		}
+		
+		public boolean
+		isUpdating()
+		{
+			return( helper.isUpdating());
+		}
+		
+		public int
+		getInterval()
+		{
+			return( interval );
+		}
+		
+		public int
+		getMinInterval()
+		{
+			return( min_interval );
+		}
+		
+		public int
+		getSecondsToUpdate()
+		{
+			return( helper.getTimeUntilNextUpdate());
+		}
+		
+		public boolean
+		canManuallyUpdate()
+		{
+			return( ((SystemTime.getCurrentTime() / 1000 - helper.getLastUpdateTime() >= TRTrackerAnnouncer.REFRESH_MINIMUM_SECS)));
+		}
+		
+		public void
+		manualUpdate()
+		{
+			helper.update( true );
+		}
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerResponseImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerResponseImpl.java
index 140b0f8..82c4cb1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerResponseImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerResponseImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerResponsePeerImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerResponsePeerImpl.java
index 7d46dd9..c739f5e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerResponsePeerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerAnnouncerResponsePeerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperImpl.java
index 8445b3c..c2e4e1c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -270,6 +271,18 @@ TRTrackerScraperImpl
 		return( client_resolver.isNetworkEnabled( hash, url ));
 	}
 	
+	public String[]
+	getEnabledNetworks(
+		HashWrapper	hash )
+	{
+		if ( client_resolver == null ){
+			
+			return( null );
+		}
+		
+		return( client_resolver.getEnabledNetworks( hash ));
+	}
+	
 	public Object[]
 	getExtensions(
 		HashWrapper	hash )
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperResponseImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperResponseImpl.java
index cf0cce6..dbc7b21 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperResponseImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/TRTrackerScraperResponseImpl.java
@@ -1,6 +1,6 @@
 /*
  * Created on 22 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.tracker.client.impl;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTAnnouncerImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTAnnouncerImpl.java
index f5c872e..a4949e0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTAnnouncerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTAnnouncerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -65,6 +66,9 @@ 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.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxySelector;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
 import com.aelitis.azureus.core.tracker.TrackerPeerSource;
 import com.aelitis.net.udp.uc.*;
 
@@ -1225,7 +1229,7 @@ TRTrackerBTAnnouncerImpl
 			  			
 			  			if ( !failed ){
 			  			
-			  				failure_reason = announceHTTP( tracker_url, reqUrl, message );
+			  				failure_reason = announceHTTP( tracker_url, reqUrl, message, i==0 );
 			  			}
 			  		}
 	
@@ -1321,11 +1325,62 @@ TRTrackerBTAnnouncerImpl
 		}
   	}
   
- 	
- 	protected String
+	private String
  	announceHTTP(
  		URL[]					tracker_url,	// overwritten if redirected
  		URL						original_reqUrl,
+ 		ByteArrayOutputStream	message,
+ 		boolean					first_effort )
+ 	
+ 		throws Exception
+ 	{
+		try{
+			return( announceHTTPSupport( tracker_url, original_reqUrl, null, message ));
+			
+		}catch( Exception e ){
+							
+			if ( 	first_effort &&
+					AENetworkClassifier.categoriseAddress( original_reqUrl.getHost() ) != AENetworkClassifier.AT_PUBLIC ){
+							
+				Map<String,Object>	opts = new HashMap<String, Object>();
+				
+				if ( peer_networks != null ){
+				
+					opts.put( AEProxyFactory.PO_PEER_NETWORKS, peer_networks );
+				}
+				
+				PluginProxy proxy = AEProxyFactory.getPluginProxy( "Tracker update", original_reqUrl, opts, true );
+				
+				if ( proxy != null ){
+					
+					boolean	ok = false;
+					
+					try{
+						
+						String result =  announceHTTPSupport( tracker_url, proxy.getURL(), proxy.getProxy(), message );
+						
+						ok = true;
+								
+						return( result );
+						
+					}catch( Throwable f ){
+						
+					}finally{
+						
+						proxy.setOK( ok );
+					}
+				}
+			}
+			
+			throw( e );
+		}
+	}
+	
+ 	private String
+ 	announceHTTPSupport(
+ 		URL[]					tracker_url,	// overwritten if redirected
+ 		URL						original_reqUrl,
+ 		Proxy					proxy,
  		ByteArrayOutputStream	message )
  	
  		throws IOException
@@ -1350,7 +1405,10 @@ TRTrackerBTAnnouncerImpl
  		Properties	http_properties = new Properties();
  		
  		http_properties.put( ClientIDGenerator.PR_URL, reqUrl );
- 		
+ 		if ( proxy != null ){
+ 			http_properties.put( ClientIDGenerator.PR_PROXY, proxy );
+ 		}
+ 	
  		try{
  			ClientIDManagerImpl.getSingleton().generateHTTPProperties( http_properties );
  			
@@ -1365,7 +1423,17 @@ TRTrackerBTAnnouncerImpl
  			
  			// see ConfigurationChecker for SSL client defaults
  			
- 			HttpsURLConnection ssl_con = (HttpsURLConnection)reqUrl.openConnection();
+ 			HttpsURLConnection ssl_con;
+ 			
+ 			if ( proxy == null ){
+ 				
+ 				ssl_con = (HttpsURLConnection)reqUrl.openConnection();
+ 				
+ 			}else{
+ 				
+ 				ssl_con = (HttpsURLConnection)reqUrl.openConnection( proxy );
+
+ 			}
  			
  			// allow for certs that contain IP addresses rather than dns names
  			
@@ -1386,9 +1454,15 @@ TRTrackerBTAnnouncerImpl
  			
  		}else{
  			
- 			con = (HttpURLConnection) reqUrl.openConnection();
+ 			if ( proxy == null ){
+ 			
+ 				con = (HttpURLConnection) reqUrl.openConnection();
+ 				
+ 			}else{
+ 				
+				con = (HttpURLConnection) reqUrl.openConnection( proxy );
+ 			}
  		}
- 		
  					
 			// we want this true but some plugins (grrr) set the global default not to follow
 			// redirects
@@ -1410,7 +1484,13 @@ TRTrackerBTAnnouncerImpl
  		
  		try{
  			
- 			con.connect();
+ 			try{
+ 				con.connect();
+ 			
+			}catch( AEProxyFactory.UnknownHostException e ){
+				
+				throw( new UnknownHostException( e.getMessage()));
+			}
  			
  			InputStream is = null;
  			
@@ -1863,7 +1943,14 @@ TRTrackerBTAnnouncerImpl
   		class_name = class_name.substring(pos+1);
   	}
   	
-  	String str = class_name + ":" + Debug.getNestedExceptionMessage(e);
+  	pos = class_name.indexOf( '$' );
+  	
+  	if ( pos != -1 ){
+  		
+  		class_name = class_name.substring(pos+1);
+  	}
+  	
+  	String str = class_name + ": " + Debug.getNestedExceptionMessage(e);
   	
   	if ( str.indexOf( "timed out") != -1 ){
   		
@@ -2147,7 +2234,7 @@ TRTrackerBTAnnouncerImpl
 		
 		tail = "";
 		
-		for ( String str: new String[]{ "info_hash", "peer_id", "port", "ip", "uploaded", "downloaded", "left", "compact", "event" }){
+		for ( String str: new String[]{ "info_hash", "peer_id", "port", "ip", "uploaded", "downloaded", "left", "compact", "event", "numwant" }){
 			
 			String val = map.get( str );
 			
@@ -2472,6 +2559,10 @@ TRTrackerBTAnnouncerImpl
 					long	time_to_wait;
 										
 					try {
+						if ( !metaData.containsKey( "interval" )){
+							throw( new Exception( "interval missing" ));
+						}
+						
 						tracker_interval = time_to_wait = ((Long) metaData.get("interval")).longValue();
 						
 						Long raw_min_interval = (Long) metaData.get("min interval");
@@ -2948,7 +3039,19 @@ TRTrackerBTAnnouncerImpl
 					
 									//get the peer ip address
 								
-								String ip = new String((byte[]) s_ip, Constants.DEFAULT_ENCODING); 
+								String base_ip = new String((byte[]) s_ip, Constants.DEFAULT_ENCODING); 
+								
+								String ip = AddressUtils.convertToShortForm( base_ip );
+								
+								if ( ip == null ){
+									
+									// corrupt address, skip
+									
+									Logger.log(new LogEvent(torrent, LOGID, LogEvent.LT_ERROR,
+                            				"Skipping invalid address: " + base_ip ));
+									
+									continue;
+								}
 								
 									//get the peer port number - should be Long but have seen byte[] on occasion
 								
@@ -3043,7 +3146,7 @@ TRTrackerBTAnnouncerImpl
 			  					System.arraycopy( meta_peers, i, i2p_id, 0, 32 );
 			  					System.arraycopy( meta_peers, i, peer_peer_id, 0, 20 );
 			  					
-			  					String hostname = Base32.encode( i2p_id ) + ".b32.i2p";
+			  					String hostname = Base32.encode( i2p_id ).toLowerCase(Locale.US) + ".b32.i2p";
 			  					
 					    		TRTrackerAnnouncerResponsePeerImpl peer = 
 					    			new TRTrackerAnnouncerResponsePeerImpl( 
@@ -3169,7 +3272,8 @@ TRTrackerBTAnnouncerImpl
 				    	
 				    		// 	we got nothing useful under peers and no peers6 either
 				    	
-						throw( new IOException( "peers missing from response" ));
+				    	// meh, seen a tracker that doesn't return anything when it has nothing
+						// throw( new IOException( "peers missing from response" ));
 				    }
 			    	
 			    	
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTScraperImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTScraperImpl.java
index bec2c00..10e2513 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTScraperImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTScraperImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTScraperResponseImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTScraperResponseImpl.java
index 993b16f..6528996 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTScraperResponseImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TRTrackerBTScraperResponseImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerChecker.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerChecker.java
index 917a9c0..c66b962 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerChecker.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerChecker.java
@@ -1,6 +1,6 @@
 /*
  * Created on 22 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.tracker.client.impl.bt;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerLoadTester.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerLoadTester.java
index 0f8c426..f7ecabd 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerLoadTester.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerLoadTester.java
@@ -2,11 +2,12 @@
  * Created on 1 f�vr. 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.tracker.client.impl.bt;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerStatus.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerStatus.java
index 418170f..bb1c4da 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerStatus.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/bt/TrackerStatus.java
@@ -1,6 +1,6 @@
 /*
  * Created on 22 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.tracker.client.impl.bt;
 
@@ -54,6 +51,8 @@ import org.gudy.azureus2.plugins.clientid.ClientIDGenerator;
 import org.gudy.azureus2.pluginsimpl.local.clientid.ClientIDManagerImpl;
 
 import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
 import com.aelitis.net.udp.uc.PRUDPPacket;
 import com.aelitis.net.udp.uc.PRUDPPacketHandler;
 import com.aelitis.net.udp.uc.PRUDPPacketHandlerException;
@@ -388,7 +387,8 @@ public class TrackerStatus {
 
 				String flags = "";
 				
-				List hashesForUDP = new ArrayList();
+				List<HashWrapper> hashesInQuery = new ArrayList<HashWrapper>(responses.size());
+				List<HashWrapper> hashesForUDP 	= new ArrayList<HashWrapper>();
 				
 				for (int i = 0; i < responses.size(); i++) {
 					TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) responses.get(i);
@@ -458,6 +458,8 @@ public class TrackerStatus {
 							flags += TRTrackerScraperClientResolver.FL_NONE;
 						}
 						
+						hashesInQuery.add( hash );
+						
 						one_of_the_responses = response;
 						one_of_the_hashes = hash;
 						
@@ -567,8 +569,10 @@ public class TrackerStatus {
 			  		
 			  		scrapeCount++;
 			  		
-			  		if(udpScrapeURL == null)
-			  			redirect_url = scrapeHTTP(reqUrl, message);
+			  		if ( udpScrapeURL == null ){
+			  			
+			  			redirect_url = scrapeHTTP(hashesInQuery,reqUrl, message);
+			  		}
 				}finally{
 					
 					TorrentUtils.setTLSTorrentHash( null );
@@ -780,10 +784,13 @@ public class TrackerStatus {
 						// System.out.println("scrape: hash missing from reply");
 					} else {
 						// retrieve values
-						int seeds = ((Long) scrapeMap.get("complete")).intValue();
-						int peers = ((Long) scrapeMap.get("incomplete")).intValue();
-						Long comp = (Long) scrapeMap.get("downloaded");
-						int completed = comp == null ? -1 : comp.intValue();
+						Long l_seeds 	= (Long)scrapeMap.get("complete");
+						Long l_peers 	= (Long)scrapeMap.get("incomplete");
+						Long l_comp 	= (Long)scrapeMap.get("downloaded");
+						
+						int seeds 		= l_seeds==null?0:l_seeds.intValue();	// expected but deal with missing as some trackers ommit :(
+						int peers 		= l_peers==null?0:l_peers.intValue();	// expected but deal with missing
+						int completed 	= l_comp==null?-1:l_comp.intValue();	// optional
 
 						// make sure we dont use invalid replies
 						if (seeds < 0 || peers < 0 || completed < -1) {
@@ -999,13 +1006,25 @@ public class TrackerStatus {
 			hashes_mon.exit();
 		}
 
-		String msg = e.getLocalizedMessage();
+		String msg;
 		
-		if(e instanceof BEncodingException)
-			if(msg.indexOf("html") != -1)
-				msg = "could not decode response, appears to be a website instead of tracker scrape: "+msg.replace('\n', ' ');
-			else msg = "bencoded response malformed:"+msg;
+		if ( e instanceof BEncodingException ){
+			
+			msg = e.getLocalizedMessage();
 
+			if ( msg.indexOf("html") != -1 ){
+				
+				msg = "Could not decode response, appears to be a website instead of tracker scrape: " + msg.replace('\n', ' ');
+				
+			}else{
+				
+				msg = "Bencoded response malformed: " + msg;
+			}
+		}else{
+			
+			msg =  Debug.getNestedExceptionMessage( e );
+		}
+		
 		for (int i = 0; i < values.length; i++) {
 			TRTrackerScraperResponseImpl response = (TRTrackerScraperResponseImpl) values[i];
 
@@ -1020,16 +1039,132 @@ public class TrackerStatus {
 			response.setNextScrapeStartTime(SystemTime.getCurrentTime()
 					+ FAULTY_SCRAPE_RETRY_INTERVAL);
 			response.setStatus(TRTrackerScraperResponse.ST_ERROR,StringInterner.intern(
-					MessageText.getString(SS + "error") + msg + " (IO)"));
+					MessageText.getString(SS + "error") + msg ));
 			// notifiy listeners
 			scraper.scrapeReceived(response);
 		}
 	}
-
-
-	protected URL 
-	scrapeHTTP(
+	  
+	private URL
+ 	scrapeHTTP(
+ 		List<HashWrapper>		hashesInQuery,
+ 		URL 					reqUrl, 
+ 		ByteArrayOutputStream 	message )
+
+ 		throws Exception
+ 	{
+		try{
+			return( scrapeHTTPSupport( reqUrl, null, message ));
+			
+		}catch( Exception e ){
+			
+			if ( AENetworkClassifier.categoriseAddress( reqUrl.getHost() ) != AENetworkClassifier.AT_PUBLIC ){
+			
+				Map<String,Object>	opts = new HashMap<String, Object>();
+				
+				if ( hashesInQuery.size() == 1 ){
+					
+					opts.put( AEProxyFactory.PO_PEER_NETWORKS, scraper.getEnabledNetworks( hashesInQuery.get(0)));
+					
+				}else{
+					
+					String[] current_nets = null;
+					
+					for ( HashWrapper hash: hashesInQuery ){
+						
+						String[] nets = scraper.getEnabledNetworks( hash );
+						
+						if ( nets == null ){
+							
+							nets = new String[0];
+						}
+						
+						if ( current_nets == null ){
+							
+							current_nets = nets;
+							
+						}else{
+							
+							boolean	ok = false;
+							
+							if ( nets.length == current_nets.length ){
+								
+								ok = true;
+								
+								for ( String net1: nets ){
+									
+									boolean match = false;
+									
+									for ( String net2: current_nets ){
+										
+										if ( net1 == net2 ){
+											
+											match = true;
+											
+											break;
+										}
+									}
+									
+									if ( !match ){
+										
+										ok = false;
+										
+										break;
+									}
+								}
+							}else{
+								
+								ok = false;
+								
+							}
+							
+							if ( !ok ){
+								
+								bSingleHashScrapes = true;
+							
+								throw( new Exception( "Mixed networks, forcing single-hash scrapes" ));
+							}
+						}
+					}
+					
+					if ( current_nets != null ){
+						
+						opts.put( AEProxyFactory.PO_PEER_NETWORKS, current_nets );
+					}
+				}
+				
+				PluginProxy proxy = AEProxyFactory.getPluginProxy( "Tracker scrape", reqUrl, opts, true );
+				
+				if ( proxy != null ){
+					
+					boolean	ok = false;
+					
+					try{
+						
+						URL result =  scrapeHTTPSupport( proxy.getURL(), proxy.getProxy(), message );
+						
+						ok = true;
+								
+						return( result );
+						
+					}catch( Throwable f ){
+						
+					}finally{
+						
+						proxy.setOK( ok );
+					}
+				}
+			}
+			
+			throw( e );
+		}
+	}
+	
+	
+	private URL 
+	scrapeHTTPSupport(
 		URL 					reqUrl, 
+		Proxy					proxy,
 		ByteArrayOutputStream 	message )
 
 		throws IOException
@@ -1051,7 +1186,10 @@ public class TrackerStatus {
 			Properties	http_properties = new Properties();
 
 			http_properties.put( ClientIDGenerator.PR_URL, reqUrl );
-
+			if ( proxy != null ){
+				http_properties.put( ClientIDGenerator.PR_PROXY, proxy );
+			}
+			
 			try{
 				ClientIDManagerImpl.getSingleton().generateHTTPProperties( http_properties );
 
@@ -1071,7 +1209,16 @@ public class TrackerStatus {
 
 					// see ConfigurationChecker for SSL client defaults
 
-					HttpsURLConnection ssl_con = (HttpsURLConnection)reqUrl.openConnection();
+					HttpsURLConnection ssl_con;
+					
+					if ( proxy == null ){
+						
+						ssl_con = (HttpsURLConnection)reqUrl.openConnection();
+						
+					}else{
+						
+						ssl_con = (HttpsURLConnection)reqUrl.openConnection( proxy );
+					}
 
 					// allow for certs that contain IP addresses rather than dns names
 
@@ -1086,7 +1233,14 @@ public class TrackerStatus {
 
 				}else{
 					
-					con = (HttpURLConnection) reqUrl.openConnection();
+					if ( proxy == null ){
+						
+						con = (HttpURLConnection) reqUrl.openConnection();
+						
+					}else{
+						
+						con = (HttpURLConnection) reqUrl.openConnection( proxy );
+					}
 				}
 					
 					// we want this true but some plugins (grrr) set the global default not to follow
@@ -1107,8 +1261,14 @@ public class TrackerStatus {
 
 				con.setRequestProperty("Connection", "close" );
 
-				con.connect();
+				try{
+					con.connect();
 
+				}catch( AEProxyFactory.UnknownHostException e ){
+					
+					throw( new UnknownHostException( e.getMessage()));
+				}
+				
 				is = con.getInputStream();
 
 				String	resulting_url_str = con.getURL().toString();
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTAnnouncerImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTAnnouncerImpl.java
index bcc5ca4..f3be3dd 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTAnnouncerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTAnnouncerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,21 +14,13 @@
  * 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.tracker.client.impl.dht;
 
 import java.net.URL;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.*;
 
 
 import org.gudy.azureus2.core3.internat.MessageText;
@@ -311,20 +303,26 @@ TRTrackerDHTAnnouncerImpl
 		}else{
 			DownloadAnnounceResultPeer[]	ext_peers = result.getPeers();
 			
-			TRTrackerAnnouncerResponsePeerImpl[] peers = new TRTrackerAnnouncerResponsePeerImpl[ext_peers.length];
+			List<TRTrackerAnnouncerResponsePeerImpl> peers_list = new ArrayList<TRTrackerAnnouncerResponsePeerImpl>( ext_peers.length );
 				
 			for (int i=0;i<ext_peers.length;i++){
 				
 				DownloadAnnounceResultPeer	ext_peer	= ext_peers[i];
 				
-				if (Logger.isEnabled())
+				if ( ext_peer == null){
+					
+					continue;
+				}
+				
+				if (Logger.isEnabled()){
 					Logger.log(new LogEvent(torrent, LOGID, "EXTERNAL PEER DHT: ip="
 							+ ext_peer.getAddress() + ",port=" + ext_peer.getPort() +",prot=" + ext_peer.getProtocol()));
-
+				}
+				
 				int		http_port	= 0;
 				byte	az_version 	= TRTrackerAnnouncer.AZ_TRACKER_VERSION_1;
 				
-				peers[i] = new TRTrackerAnnouncerResponsePeerImpl( 
+				peers_list.add( new TRTrackerAnnouncerResponsePeerImpl( 
 									ext_peer.getSource(),
 									ext_peer.getPeerID(),
 									ext_peer.getAddress(), 
@@ -333,9 +331,11 @@ TRTrackerDHTAnnouncerImpl
 									http_port,
 									ext_peer.getProtocol(),
 									az_version,
-									(short)0 );
+									(short)0 ));
 			}
 			
+			TRTrackerAnnouncerResponsePeerImpl[]	peers = peers_list.toArray( new TRTrackerAnnouncerResponsePeerImpl[peers_list.size()] );
+			
 			helper.addToTrackerCache( peers);
 		
 			tracker_status_str = MessageText.getString("PeerManager.status.ok");
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperImpl.java
index 26822fa..52bed07 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperResponseImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperResponseImpl.java
index 92b286e..794826d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperResponseImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/client/impl/dht/TRTrackerDHTScraperResponseImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHost.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHost.java
index e2cde74..dc9df74 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHost.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHost.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostAuthenticationListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostAuthenticationListener.java
index 7c9c620..19850b6 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostAuthenticationListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostAuthenticationListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostException.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostException.java
index ea3e527..bcbb1e9 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostFactory.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostFactory.java
index 1acce43..b6dc9e7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostListener.java
index f0736f9..fda06ee 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostListener2.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostListener2.java
index ef09acf..fee5046 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostListener2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostListener2.java
@@ -1,36 +1,35 @@
-/*
- * Created on Jul 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 org.gudy.azureus2.core3.tracker.host;
-
-import java.io.IOException;
-
-import org.gudy.azureus2.core3.tracker.server.TRTrackerServerListener2;
-
-public interface 
-TRHostListener2 
-{
-	public boolean
-	handleExternalRequest(
-		TRTrackerServerListener2.ExternalRequest		request )
-	
-		throws IOException;
-}
+/*
+ * Created on Jul 1, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.tracker.host;
+
+import java.io.IOException;
+
+import org.gudy.azureus2.core3.tracker.server.TRTrackerServerListener2;
+
+public interface 
+TRHostListener2 
+{
+	public boolean
+	handleExternalRequest(
+		TRTrackerServerListener2.ExternalRequest		request )
+	
+		throws IOException;
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostPeer.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostPeer.java
index 7f80db4..b93f839 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostPeer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostPeer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrent.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrent.java
index 8580de7..b179f4b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrent.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrent.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentFinder.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentFinder.java
index c7a7c9a..4b01974 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentFinder.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentFinder.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentListener.java
index d57a767..14ca927 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentRemovalVetoException.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentRemovalVetoException.java
index 599e2ad..5d27e5d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentRemovalVetoException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentRemovalVetoException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentRequest.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentRequest.java
index 42e2fd7..d179c11 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentRequest.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentRequest.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentWillBeRemovedListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentWillBeRemovedListener.java
index abd4b49..0a922bb 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentWillBeRemovedListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/TRHostTorrentWillBeRemovedListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostConfigImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostConfigImpl.java
index e5c4f15..515e716 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostConfigImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostConfigImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostExternalTorrent.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostExternalTorrent.java
index 85fb702..77207c9 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostExternalTorrent.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostExternalTorrent.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostImpl.java
index 9e0492e..f6ba4a1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -1063,6 +1064,9 @@ TRHostImpl
 		return( lookupHostTorrent( torrent ));
 	}
 	
+	/**
+	 * Add and fire listener for each torrent already hosted
+	 */
 	public void
 	addListener(
 		TRHostListener	l )
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostPeerHostImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostPeerHostImpl.java
index 002afb5..81ba4f6 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostPeerHostImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostPeerHostImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostPeerPublishImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostPeerPublishImpl.java
index 6738693..bd3aea5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostPeerPublishImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostPeerPublishImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentHostImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentHostImpl.java
index 731af36..4a69328 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentHostImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentHostImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentPublishImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentPublishImpl.java
index 1de0859..79ae3d5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentPublishImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentPublishImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentRequestImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentRequestImpl.java
index 86f3a2d..2cb4df7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentRequestImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/host/impl/TRHostTorrentRequestImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/PRHelpers.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/PRHelpers.java
index 5e68c7d..d1ea309 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/PRHelpers.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/PRHelpers.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyAnnounce.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyAnnounce.java
index 40b4a25..c9666ff 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyAnnounce.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyAnnounce.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyAnnounce2.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyAnnounce2.java
index b39c094..5a0e454 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyAnnounce2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyAnnounce2.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyConnect.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyConnect.java
index 1e8d0bb..0edbf15 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyConnect.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyConnect.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyError.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyError.java
index 4ecb84e..bcaeb89 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyError.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyError.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyScrape.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyScrape.java
index 75954fd..ea9f74a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyScrape.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyScrape.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyScrape2.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyScrape2.java
index 52b7fed..81b26e4 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyScrape2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketReplyScrape2.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestAnnounce.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestAnnounce.java
index a06a943..af1ba8f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestAnnounce.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestAnnounce.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestAnnounce2.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestAnnounce2.java
index f235b70..f0940f2 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestAnnounce2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestAnnounce2.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestConnect.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestConnect.java
index e737dfb..69019fc 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestConnect.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestConnect.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestScrape.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestScrape.java
index db6ff72..822f900 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestScrape.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketRequestScrape.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketTracker.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketTracker.java
index d01bed9..f88e427 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketTracker.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPPacketTracker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPTrackerCodecs.java b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPTrackerCodecs.java
index 730444a..17a83c5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPTrackerCodecs.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/protocol/udp/PRUDPTrackerCodecs.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServer.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServer.java
index a2eaa41..09c0b9c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerAuthenticationListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerAuthenticationListener.java
index 2384a13..836e64d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerAuthenticationListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerAuthenticationListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerException.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerException.java
index 690e2d3..7edcf9a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerFactory.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerFactory.java
index aaa5375..f8336cf 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -23,6 +24,7 @@ package org.gudy.azureus2.core3.tracker.server;
 
 
 import java.net.InetAddress;
+import java.util.Map;
 
 import org.gudy.azureus2.core3.tracker.server.impl.*;
 
@@ -42,7 +44,7 @@ TRTrackerServerFactory
 		
 		throws TRTrackerServerException
 	{
-		return( TRTrackerServerFactoryImpl.create( "<none>", protocol, port, null, false, apply_ip_filter, main_tracker, true ));
+		return( TRTrackerServerFactoryImpl.create( "<none>", protocol, port, null, false, apply_ip_filter, main_tracker, true, null ));
 	}
 	
 	public static TRTrackerServer
@@ -54,7 +56,7 @@ TRTrackerServerFactory
 		
 		throws TRTrackerServerException
 	{
-		return( TRTrackerServerFactoryImpl.create( "<none>", protocol, port, null, true, apply_ip_filter, main_tracker, true ));
+		return( TRTrackerServerFactoryImpl.create( "<none>", protocol, port, null, true, apply_ip_filter, main_tracker, true, null ));
 	}
 	
 	public static TRTrackerServer
@@ -67,7 +69,7 @@ TRTrackerServerFactory
 		
 		throws TRTrackerServerException
 	{
-		return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, false, apply_ip_filter, main_tracker, true ));
+		return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, false, apply_ip_filter, main_tracker, true, null ));
 	}
 	
 	public static TRTrackerServer
@@ -81,7 +83,7 @@ TRTrackerServerFactory
 		
 		throws TRTrackerServerException
 	{
-		return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, false, apply_ip_filter, main_tracker, start_up_ready ));
+		return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, false, apply_ip_filter, main_tracker, start_up_ready, null ));
 	}
 	
 	public static TRTrackerServer
@@ -94,7 +96,7 @@ TRTrackerServerFactory
 		
 		throws TRTrackerServerException
 	{
-		return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, true, apply_ip_filter, main_tracker, true ));
+		return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, true, apply_ip_filter, main_tracker, true, null ));
 	}
 	
 	public static TRTrackerServer
@@ -108,7 +110,7 @@ TRTrackerServerFactory
 		
 		throws TRTrackerServerException
 	{
-		return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, true, apply_ip_filter, main_tracker, startup_ready ));
+		return( TRTrackerServerFactoryImpl.create( name, protocol, port, null, true, apply_ip_filter, main_tracker, startup_ready, null ));
 	}
 	
 	public static TRTrackerServer
@@ -122,7 +124,7 @@ TRTrackerServerFactory
 		
 		throws TRTrackerServerException
 	{
-		return( TRTrackerServerFactoryImpl.create( name, protocol, port, bind_ip, false, apply_ip_filter, main_tracker, true ));
+		return( TRTrackerServerFactoryImpl.create( name, protocol, port, bind_ip, false, apply_ip_filter, main_tracker, true, null ));
 	}
 	
 	public static TRTrackerServer
@@ -136,7 +138,37 @@ TRTrackerServerFactory
 		
 		throws TRTrackerServerException
 	{
-		return( TRTrackerServerFactoryImpl.create( name, protocol, port, bind_ip, true, apply_ip_filter, main_tracker, true ));
+		return( TRTrackerServerFactoryImpl.create( name, protocol, port, bind_ip, true, apply_ip_filter, main_tracker, true, null ));
+	}
+	
+	public static TRTrackerServer
+	create(
+		String					name,
+		int						protocol,
+		int						port,
+		InetAddress				bind_ip,
+		boolean					apply_ip_filter,
+		boolean					main_tracker,
+		Map<String,Object>		properties )
+		
+		throws TRTrackerServerException
+	{
+		return( TRTrackerServerFactoryImpl.create( name, protocol, port, bind_ip, false, apply_ip_filter, main_tracker, true, properties ));
+	}
+	
+	public static TRTrackerServer
+	createSSL(
+		String					name,
+		int						protocol,
+		int						port,
+		InetAddress				bind_ip,
+		boolean					apply_ip_filter,
+		boolean					main_tracker,
+		Map<String,Object>		properties )
+		
+		throws TRTrackerServerException
+	{
+		return( TRTrackerServerFactoryImpl.create( name, protocol, port, bind_ip, true, apply_ip_filter, main_tracker, true, properties ));
 	}
 	
 	public static void
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerFactoryListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerFactoryListener.java
index bdb8638..0b44021 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerFactoryListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerFactoryListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerListener.java
index 4b45065..d807666 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerListener2.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerListener2.java
index dca6d08..9c86759 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerListener2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerListener2.java
@@ -1,79 +1,81 @@
-/*
- * Created on Jul 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 org.gudy.azureus2.core3.tracker.server;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.URL;
-
-import org.gudy.azureus2.core3.util.AsyncController;
-
-public interface 
-TRTrackerServerListener2 
-{
-	public boolean
-	handleExternalRequest(
-		ExternalRequest		request )
-	
-		throws IOException;
-	
-	
-	public interface
-	ExternalRequest
-	{
-		public InetSocketAddress
-		getClientAddress();
-		
-		public InetSocketAddress
-		getLocalAddress();
-
-		public String
-		getUser();
-		
-		public String
-		getURL();
-		
-		public URL
-		getAbsoluteURL();
-		
-		public String
-		getHeader();
-		
-		public InputStream
-		getInputStream();
-		
-		public OutputStream
-		getOutputStream();
-		
-		public AsyncController
-		getAsyncController();
-		
-		public boolean
-		canKeepAlive();
-		
-		public void
-		setKeepAlive(
-			boolean		ka );
-	}
-}
+/*
+ * Created on Jul 1, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.tracker.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.URL;
+
+import org.gudy.azureus2.core3.util.AsyncController;
+
+public interface 
+TRTrackerServerListener2 
+{
+	public boolean
+	handleExternalRequest(
+		ExternalRequest		request )
+	
+		throws IOException;
+	
+	
+	public interface
+	ExternalRequest
+	{
+		public InetSocketAddress
+		getClientAddress();
+		
+		public InetSocketAddress
+		getLocalAddress();
+
+		public String
+		getUser();
+		
+		public String
+		getURL();
+		
+		public URL
+		getAbsoluteURL();
+		
+		public String
+		getHeader();
+		
+		public InputStream
+		getInputStream();
+		
+		public OutputStream
+		getOutputStream();
+		
+		public boolean
+		isActive();
+		
+		public AsyncController
+		getAsyncController();
+		
+		public boolean
+		canKeepAlive();
+		
+		public void
+		setKeepAlive(
+			boolean		ka );
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerPeer.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerPeer.java
index d02882a..de8af8e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerPeer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerPeer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerPeerBase.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerPeerBase.java
index c48d608..082aa82 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerPeerBase.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerPeerBase.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jun 5, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerRequest.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerRequest.java
index 4d96ef5..5f484e1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerRequest.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerRequest.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerRequestListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerRequestListener.java
index 5040f39..6d5e234 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerRequestListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerRequestListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerStats.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerStats.java
index e063212..2eaa8d9 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerStats.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrent.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrent.java
index 4c39b5c..20718dd 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrent.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrent.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentListener.java
index 70c8125..25f4696 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 01-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentPeerListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentPeerListener.java
index e5c828a..a163022 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentPeerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentPeerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18 May 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentStats.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentStats.java
index c3aaf2b..ee27f93 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentStats.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/TRTrackerServerTorrentStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerFactoryImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerFactoryImpl.java
index 5d0dcff..1340530 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerFactoryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerFactoryImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -45,6 +46,7 @@ import org.gudy.azureus2.core3.tracker.server.impl.tcp.nonblocking.TRNonBlocking
 import org.gudy.azureus2.core3.tracker.server.impl.udp.*;
 import org.gudy.azureus2.core3.util.AEMonitor;
 import org.gudy.azureus2.core3.util.AsyncController;
+import org.gudy.azureus2.plugins.tracker.Tracker;
 
 import com.aelitis.azureus.core.stats.AzureusCoreStats;
 import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider;
@@ -128,17 +130,25 @@ TRTrackerServerFactoryImpl
 	
 	public static TRTrackerServer
 	create(
-		String		name,
-		int			protocol,
-		int			port,
-		InetAddress	bind_ip,
-		boolean		ssl,
-		boolean		apply_ip_filter,
-		boolean		main_tracker,
-		boolean		start_up_ready )
+		String					name,
+		int						protocol,
+		int						port,
+		InetAddress				bind_ip,
+		boolean					ssl,
+		boolean					apply_ip_filter,
+		boolean					main_tracker,
+		boolean					start_up_ready,
+		Map<String,Object>		properties )
 	
 		throws TRTrackerServerException
 	{
+		if ( properties == null ){
+			
+			properties = new HashMap<String, Object>();
+		}
+		
+		Boolean	pr_non_blocking = (Boolean)properties.get(Tracker.PR_NON_BLOCKING );
+		
 		try{
 			class_mon.enter();
 		
@@ -146,9 +156,15 @@ TRTrackerServerFactoryImpl
 			
 			if ( protocol == TRTrackerServerFactory.PR_TCP ){
 				
-				if ( COConfigurationManager.getBooleanParameter( "Tracker TCP NonBlocking" ) && main_tracker && !ssl ){
+				boolean explicit_non_blocking = pr_non_blocking != null && pr_non_blocking;
+				
+				boolean non_blocking = 
+						( COConfigurationManager.getBooleanParameter( "Tracker TCP NonBlocking" ) && main_tracker ) ||
+						( explicit_non_blocking );
+				
+				if ( non_blocking && !ssl ){
 					
-					server = 
+					TRNonBlockingServer nb_server =
 						new TRNonBlockingServer( 
 							name, 
 							port, 
@@ -166,6 +182,13 @@ TRTrackerServerFactoryImpl
 
 								}
 							});
+					
+					server = nb_server;
+					
+					if ( explicit_non_blocking ){
+						
+						nb_server.setRestrictNonBlocking( false );
+					}
 				}else{
 					
 					server = new TRBlockingServer( name, port, bind_ip, ssl, apply_ip_filter, start_up_ready );
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerImpl.java
index 6ab432e..67ad25d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerNATChecker.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerNATChecker.java
index 991d42c..7d9d1b7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerNATChecker.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerNATChecker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerNatCheckerListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerNatCheckerListener.java
index 9d7eaa1..1935569 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerNatCheckerListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerNatCheckerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerPeerImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerPeerImpl.java
index b48ca77..665ef12 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerPeerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerPeerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerProcessor.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerProcessor.java
index fae45f5..3887127 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerProcessor.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerProcessor.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerRequestImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerRequestImpl.java
index 6da71e3..be9016e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerRequestImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerRequestImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerSimplePeer.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerSimplePeer.java
index 5be1b72..a5a6765 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerSimplePeer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerSimplePeer.java
@@ -1,66 +1,65 @@
-/*
- * Created on Feb 20, 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.core3.tracker.server.impl;
-
-import org.gudy.azureus2.core3.util.HashWrapper;
-
-import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
-
-public interface 
-TRTrackerServerSimplePeer 
-{
-	public byte[]
-	getIPAsRead();
-	
-	public byte[]
-	getIPAddressBytes();
-
-	public HashWrapper
-   	getPeerId();
-
-	public int
-	getTCPPort();
-	
-	public int
-	getUDPPort();
-	
-	public int
-	getHTTPPort();
-	
-	public boolean
-	isSeed();
-	
-	public boolean
-	isBiased();
-	
-	public byte
-	getCryptoLevel();
-	
-	public byte
-	getAZVer();
-	
-	public int
-	getUpSpeed();
-	
-	public DHTNetworkPosition
-	getNetworkPosition();
-}
+/*
+ * Created on Feb 20, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.tracker.server.impl;
+
+import org.gudy.azureus2.core3.util.HashWrapper;
+
+import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
+
+public interface 
+TRTrackerServerSimplePeer 
+{
+	public byte[]
+	getIPAsRead();
+	
+	public byte[]
+	getIPAddressBytes();
+
+	public HashWrapper
+   	getPeerId();
+
+	public int
+	getTCPPort();
+	
+	public int
+	getUDPPort();
+	
+	public int
+	getHTTPPort();
+	
+	public boolean
+	isSeed();
+	
+	public boolean
+	isBiased();
+	
+	public byte
+	getCryptoLevel();
+	
+	public byte
+	getAZVer();
+	
+	public int
+	getUpSpeed();
+	
+	public DHTNetworkPosition
+	getNetworkPosition();
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerStatsImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerStatsImpl.java
index 7a75509..ba3edbf 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerStatsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerTorrentImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerTorrentImpl.java
index 6fee94b..f38c5de 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerTorrentImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerTorrentImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerTorrentStatsImpl.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerTorrentStatsImpl.java
index 9eef0a5..1abc808 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerTorrentStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/TRTrackerServerTorrentStatsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/dht/TRTrackerServerDHT.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/dht/TRTrackerServerDHT.java
index 47781f3..04a1ad1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/dht/TRTrackerServerDHT.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/dht/TRTrackerServerDHT.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/TRTrackerServerProcessorTCP.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/TRTrackerServerProcessorTCP.java
index c4588f1..7e444d3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/TRTrackerServerProcessorTCP.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/TRTrackerServerProcessorTCP.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -955,6 +956,12 @@ TRTrackerServerProcessorTCP
 	}
 		
 	protected boolean
+	isActive()
+	{
+		return( true );
+	}
+	
+	protected boolean
 	handleExternalRequest(
 		InetSocketAddress	local_address,
 		InetSocketAddress	remote_address,
@@ -970,6 +977,6 @@ TRTrackerServerProcessorTCP
 	{
 		URL	absolute_url = new URL( server_url + (url.startsWith("/")?url:("/"+url)));
 			
-		return( server.handleExternalRequest( local_address, remote_address, user,url,absolute_url,header, is, os, async, keep_alive ));
+		return( server.handleExternalRequest( this, local_address, remote_address, user,url,absolute_url,header, is, os, async, keep_alive ));
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/TRTrackerServerTCP.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/TRTrackerServerTCP.java
index 888790e..aa22fca 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/TRTrackerServerTCP.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/TRTrackerServerTCP.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -27,7 +28,6 @@ import java.io.*;
 import java.text.SimpleDateFormat;
 import java.util.*;
 
-
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.core3.config.*;
 import org.gudy.azureus2.core3.tracker.server.*;
@@ -61,6 +61,8 @@ TRTrackerServerTCP
 	private int		port;
 	private boolean	apply_ip_filter;
 	
+	private boolean restrict_non_blocking_requests = TRTrackerServerImpl.restrict_non_blocking_requests;
+	
 	private ThreadPool	thread_pool;
 	
 	public
@@ -99,6 +101,19 @@ TRTrackerServerTCP
 		return( apply_ip_filter );
 	}
 	
+	public boolean
+	getRestrictNonBlocking()
+	{
+		return( restrict_non_blocking_requests );
+	}
+	
+	public void
+	setRestrictNonBlocking(
+		boolean restrict )
+	{
+		restrict_non_blocking_requests = restrict;
+	}
+	
 	static boolean	LOG_DOS_TO_FILE	= false;
 	
 	static{
@@ -297,16 +312,17 @@ TRTrackerServerTCP
 	
 	protected boolean
 	handleExternalRequest(
-		final InetSocketAddress		local_address,
-		final InetSocketAddress		client_address,
-		final String				user,
-		final String				url,
-		final URL					absolute_url,
-		final String				header,
-		final InputStream			is,
-		final OutputStream			os,
-		final AsyncController		async,
-		final boolean[]				keep_alive )		
+		final TRTrackerServerProcessorTCP	processor,
+		final InetSocketAddress				local_address,
+		final InetSocketAddress				client_address,
+		final String						user,
+		final String						url,
+		final URL							absolute_url,
+		final String						header,
+		final InputStream					is,
+		final OutputStream					os,
+		final AsyncController				async,
+		final boolean[]						keep_alive )		
 		
 		throws IOException
 	{
@@ -393,6 +409,12 @@ TRTrackerServerTCP
 					{
 						keep_alive[0] = original_ka && ka;
 					}
+					
+					public boolean 
+					isActive() 
+					{
+						return( processor.isActive());
+					}
 				};
 			
 			if ( listener.handleExternalRequest( request )){
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServer.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServer.java
index 24a9fad..5ecc666 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -259,7 +256,7 @@ TRBlockingServer
 			
 			try{				
 				Socket socket = ss.accept();
-					
+									
 				successfull_accepts++;
 				
 				String	ip = socket.getInetAddress().getHostAddress();
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServerProcessor.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServerProcessor.java
index af01ab1..cf64b5f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServerProcessor.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/blocking/TRBlockingServerProcessor.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -458,6 +455,23 @@ TRBlockingServerProcessor
 	
 	}
 	
+	public boolean
+	isActive()
+	{
+		try{
+				// not really much use anyway as the default for keep alive timer is 2 hours or more...
+			
+			if ( !socket.getKeepAlive()){
+			
+				socket.setKeepAlive( true );
+			}
+			
+		}catch( Throwable e ){			
+		}
+
+		return( !socket.isClosed());
+	}
+	
 	public void
 	interruptTask()
 	{
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServer.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServer.java
index ad5826f..0898a19 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -139,12 +136,7 @@ TRNonBlockingServer
 		write_selector 		= new VirtualChannelSelector( _name + ":" + _port, VirtualChannelSelector.OP_WRITE, true );
 
 		boolean	ok = false;
-		
-		if ( _port == 0 ){
-			
-			throw( new TRTrackerServerException( "port of 0 not currently supported"));
-		}
-		
+				
 		try{
 			InetSocketAddress	address;
 			
@@ -170,9 +162,14 @@ TRNonBlockingServer
 			}
 			
 			accept_server = VirtualServerChannelSelectorFactory.createBlocking( address, 0, this );
-			
+						
 			accept_server.start();
-		      
+		    
+			if ( _port == 0 ){
+			
+				setPort( accept_server.getPort());
+			}
+			
 			AEThread	read_thread = 
 				new AEThread( "TRTrackerServer:readSelector")
 				{
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServerProcessor.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServerProcessor.java
index f9edde9..c6e9ef5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServerProcessor.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServerProcessor.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -30,7 +27,6 @@ import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
 
-import org.gudy.azureus2.core3.tracker.server.impl.TRTrackerServerImpl;
 import org.gudy.azureus2.core3.tracker.server.impl.tcp.TRTrackerServerProcessorTCP;
 import org.gudy.azureus2.core3.tracker.server.impl.tcp.TRTrackerServerTCP;
 import org.gudy.azureus2.core3.util.AESemaphore;
@@ -84,7 +80,7 @@ TRNonBlockingServerProcessor
 		start_time	= SystemTime.getCurrentTime(); 
 		
 		read_buffer = ByteBuffer.allocate( READ_BUFFER_INITIAL );
-		
+				
 		// System.out.println( "create: " + System.currentTimeMillis());
 	}
 	
@@ -395,7 +391,7 @@ TRNonBlockingServerProcessor
 								lc_request_header,
 								url, 
 								(InetSocketAddress)socket_channel.socket().getRemoteSocketAddress(),
-								TRTrackerServerImpl.restrict_non_blocking_requests,
+								getServer().getRestrictNonBlocking(),
 								new ByteArrayInputStream(new byte[0]),
 								async_control );
 				
@@ -497,6 +493,12 @@ TRNonBlockingServerProcessor
 		keep_alive	= k;
 	}
 	
+	public boolean
+	isActive()
+	{
+		return( !socket_channel.socket().isClosed());
+	}
+	
 	public void
 	interruptTask()
 	{
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServerProcessorFactory.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServerProcessorFactory.java
index 2217d9f..bc08ef3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServerProcessorFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/tcp/nonblocking/TRNonBlockingServerProcessorFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/udp/TRTrackerServerProcessorUDP.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/udp/TRTrackerServerProcessorUDP.java
index 9256573..f27e34c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/udp/TRTrackerServerProcessorUDP.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/udp/TRTrackerServerProcessorUDP.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/udp/TRTrackerServerUDP.java b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/udp/TRTrackerServerUDP.java
index 7fb7a9e..835091f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/udp/TRTrackerServerUDP.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/server/impl/udp/TRTrackerServerUDP.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/util/TRTrackerUtils.java b/azureus2/src/org/gudy/azureus2/core3/tracker/util/TRTrackerUtils.java
index a729a03..f5c963f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/util/TRTrackerUtils.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/util/TRTrackerUtils.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/tracker/util/TRTrackerUtilsListener.java b/azureus2/src/org/gudy/azureus2/core3/tracker/util/TRTrackerUtilsListener.java
index 207c033..99aca5f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/tracker/util/TRTrackerUtilsListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/tracker/util/TRTrackerUtilsListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AECallback.java b/azureus2/src/org/gudy/azureus2/core3/util/AECallback.java
index 2c59698..3f00429 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AECallback.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AECallback.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.util;
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnostics.java b/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnostics.java
index 7a1ba15..a5e5060 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnostics.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnostics.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -36,6 +33,9 @@ import org.gudy.azureus2.platform.PlatformManagerFactory;
  *
  */
 
+
+
+
 import java.io.*;
 import java.util.*;
 
@@ -120,6 +120,8 @@ AEDiagnostics
 	
 	private static List<AEDiagnosticsEvidenceGenerator>		evidence_generators	= new ArrayList<AEDiagnosticsEvidenceGenerator>();
 		
+	private static final AESemaphore	dump_check_done_sem = new AESemaphore( "dumpcheckcomplete" );
+	
 	public static synchronized void
 	startup(
 		boolean	_enable_pending )
@@ -456,53 +458,81 @@ AEDiagnostics
 				}
 			}
 			
-			File app_dir = new File( SystemProperties.getApplicationPath());
+			List<File>	fdirs_to_check = new ArrayList<File>();
 			
-			if ( app_dir.canRead()){
+			fdirs_to_check.add( new File( SystemProperties.getApplicationPath()));
+			
+			try{
+				File temp_file = File.createTempFile( "AZU", "tmp" );
 				
-				File[]	files = app_dir.listFiles();
+				fdirs_to_check.add( temp_file.getParentFile());
 				
-				File	most_recent_dump 	= null;
-				long	most_recent_time	= 0;
+				temp_file.delete();
 				
-				long	now = SystemTime.getCurrentTime();
+			}catch( Throwable e ){
 				
-				long	one_week_ago = now - 7*24*60*60*1000;
-				
-				for (int i=0;i<files.length;i++){
-					
-					File	f = files[i];
+			}
+			
+			File	most_recent_dump 	= null;
+			long	most_recent_time	= 0;
+
+			for ( File dir: fdirs_to_check ){
+			
+				if ( dir.canRead()){
 					
-					String	name = f.getName();
+					File[]	files = dir.listFiles(
+							new FilenameFilter() {
+								
+								public boolean 
+								accept(
+									File dir, 
+									String name) 
+								{
+									return( name.startsWith( "hs_err_pid" ) && name.endsWith( ".log" ));
+								}
+							});
 					
-					if ( name.startsWith( "hs_err_pid" )){
+					if ( files != null ){
+						
+						long	now = SystemTime.getCurrentTime();
 						
-						long	last_mod = f.lastModified();
+						long	one_week_ago = now - 7*24*60*60*1000;
 						
-						if ( last_mod > most_recent_time && last_mod > one_week_ago){
+						for (int i=0;i<files.length;i++){
 							
-							most_recent_dump 	= f;
-							most_recent_time	= last_mod;
+							File	f = files[i];
+																						
+							long	last_mod = f.lastModified();
+							
+							if ( last_mod > most_recent_time && last_mod > one_week_ago){
+								
+								most_recent_dump 	= f;
+								most_recent_time	= last_mod;
+							}
 						}
 					}
 				}
+			}
+		
+			if ( most_recent_dump!= null ){
+				
+				long	last_done = 
+					COConfigurationManager.getLongParameter( "diagnostics.dump.lasttime", 0 ); 
 				
-				if ( most_recent_dump!= null ){
+				if ( last_done < most_recent_time ){
 					
-					long	last_done = 
-						COConfigurationManager.getLongParameter( "diagnostics.dump.lasttime", 0 ); 
+					COConfigurationManager.setParameter( "diagnostics.dump.lasttime", most_recent_time );
 					
-					if ( last_done < most_recent_time ){
-						
-						COConfigurationManager.setParameter( "diagnostics.dump.lasttime", most_recent_time );
-						
-						analyseDump( most_recent_dump );
-					}
+					analyseDump( most_recent_dump );
 				}
 			}
 		}catch( Throwable e ){
 			
 			Debug.printStackTrace(e);
+			
+		}finally{
+			
+			dump_check_done_sem.releaseForever();
 		}
 	}
 	
@@ -516,7 +546,9 @@ AEDiagnostics
 			LineNumberReader lnr = new LineNumberReader( new FileReader( file ));
 			
 			try{
-				boolean	float_excep	= false;
+				boolean	float_excep		= false;
+				boolean	swt_crash		= false;
+				boolean	browser_crash	= false;
 				
 				String[]	bad_dlls_uc = new String[bad_dlls.length];
 				
@@ -548,6 +580,29 @@ AEDiagnostics
 						
 					}else{
 						
+						if ( line.startsWith( "# C" ) && line.contains( "[SWT-WIN32" )){
+							
+							swt_crash = true;
+						
+						}else if ( line.contains( "CURRENT THREAD" ) && line.contains( "SWT THREAD" )){
+							
+							swt_crash = true;
+							
+						}else if ( 	line.startsWith( "# C" ) && 
+									( 	line.contains( "[IEFRAME" ) || 
+										line.contains( "[JSCRIPT" ) ||
+										line.contains( "[MSHTML" ))){
+								
+							swt_crash = browser_crash = true;
+
+						}else if ( 	( line.startsWith( "J " ) && line.contains( "SWT.BROWSER")) ||
+									( line.startsWith( "C " ) && line.contains( "[IEFRAME" )) ||
+									( line.startsWith( "C " ) && line.contains( "[MSHTML" )) ||
+									( line.startsWith( "C " ) && line.contains( "[JSCRIPT" ))){
+							
+							browser_crash = true;
+						}
+						
 						for (int i=0;i<bad_dlls_uc.length;i++){
 							
 							String b_uc = bad_dlls_uc[i];
@@ -585,6 +640,25 @@ AEDiagnostics
 									"platform.win32.baddll.info" ),	
 							new String[]{ dll + ".dll", detail });
 				}
+				
+				if ( swt_crash && browser_crash ){
+					
+					if ( Constants.isWindows ){
+						
+						if ( !COConfigurationManager.getBooleanParameter( "browser.internal.disable", false )){
+
+							COConfigurationManager.setParameter( "browser.internal.disable", true );
+							
+							COConfigurationManager.save();
+							
+							Logger.logTextResource(
+									new LogAlert(
+											LogAlert.REPEATABLE, 
+											LogAlert.AT_WARNING,
+											"browser.internal.auto.disabled" ));
+						}
+					}
+				}
 			}finally{
 				
 				lnr.close();
@@ -596,6 +670,13 @@ AEDiagnostics
 	}
 	
 	public static void
+	waitForDumpChecks(
+		long	max_wait )
+	{
+		dump_check_done_sem.reserve( max_wait );
+	}
+	
+	public static void
 	addEvidenceGenerator(
 		AEDiagnosticsEvidenceGenerator	gen )
 	{
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnosticsEvidenceGenerator.java b/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnosticsEvidenceGenerator.java
index a66f4da..5e70146 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnosticsEvidenceGenerator.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnosticsEvidenceGenerator.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnosticsLogger.java b/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnosticsLogger.java
index 7941a4b..f29db15 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnosticsLogger.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEDiagnosticsLogger.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEJavaManagement.java b/azureus2/src/org/gudy/azureus2/core3/util/AEJavaManagement.java
index bd52d27..10ad04b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEJavaManagement.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEJavaManagement.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEMonSem.java b/azureus2/src/org/gudy/azureus2/core3/util/AEMonSem.java
index cc7ba73..38354da 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEMonSem.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEMonSem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEMonitor.java b/azureus2/src/org/gudy/azureus2/core3/util/AEMonitor.java
index ad5ec88..819bd5a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEMonitor.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEMonitor.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -274,7 +271,10 @@ AEMonitor
 	public boolean
 	isHeld()
 	{
-		return( owner == Thread.currentThread());
+		synchronized( this ){
+		
+			return( owner == Thread.currentThread());
+		}
 	}
 	
 	public boolean
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEMonitor2.java b/azureus2/src/org/gudy/azureus2/core3/util/AEMonitor2.java
index bdad626..f8d0a3c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEMonitor2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEMonitor2.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AENetworkClassifier.java b/azureus2/src/org/gudy/azureus2/core3/util/AENetworkClassifier.java
index 9a5da64..e3e572d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AENetworkClassifier.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AENetworkClassifier.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,14 +14,12 @@
  * 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;
 
+import java.net.InetSocketAddress;
 import java.net.URL;
 import java.util.*;
 
@@ -49,12 +47,19 @@ AENetworkClassifier
 	public static final String[]	AT_NETWORKS =
 		{ AT_PUBLIC, AT_I2P, AT_TOR };
 	
+	public static final String[] AT_NON_PUBLIC = { AT_I2P, AT_TOR };
+	
 	private static List	listeners = new ArrayList();
 	
 	public static String
 	categoriseAddress(
 		String	str )
 	{
+		if ( str == null ){
+			
+			return( AT_PUBLIC );	// woreva
+		}
+		
 		int	last_dot = str.lastIndexOf('.');
 		
 		if ( last_dot == -1 ){
@@ -62,7 +67,7 @@ AENetworkClassifier
 			return( AT_PUBLIC );	// no idea really, treat as normal
 		}
 		
-		String	dom = str.substring(last_dot+1).toLowerCase();
+		String	dom = str.substring(last_dot+1).toLowerCase(Locale.US);
 		
 		if ( dom.equals( "i2p" )){
 			
@@ -76,6 +81,35 @@ AENetworkClassifier
 		return( AT_PUBLIC );
 	}
 	
+	public static String
+	internalise(
+		String	str )
+	{
+		if ( str == null ){
+			
+			return( null );
+			
+		}else{
+			
+			for ( String net: AT_NETWORKS ){
+				
+				if ( str.equalsIgnoreCase( net )){
+					
+					return( net );
+				}
+			}
+		}
+		
+		return( null );
+	}
+	
+	public static String
+	categoriseAddress(
+		InetSocketAddress		isa )
+	{
+		return( categoriseAddress( AddressUtils.getHostAddress( isa )));
+	}
+	
 	public static String[]
 	getNetworks(
 		TOTorrent	torrent,
@@ -83,7 +117,7 @@ AENetworkClassifier
 	{
 			// go through all the announce URL and find all networks
 		
-		List	urls = new ArrayList();
+		List<URL>	urls = new ArrayList();
 		
 		urls.add( torrent.getAnnounceURL());
 		
@@ -99,7 +133,7 @@ AENetworkClassifier
 			}
 		}
 		
-		List	available_networks = new ArrayList();
+		List<String>	available_networks = new ArrayList<String>();
 		
 		for (int i=0;i<urls.size();i++){
 			
@@ -121,7 +155,7 @@ AENetworkClassifier
 		
 		boolean	prompt = COConfigurationManager.getBooleanParameter( "Network Selection Prompt" );
 		
-		List	res = new ArrayList();
+		List<String>	res = new ArrayList<String>();
 
 		if ( prompt && listeners.size() > 0 ){
 
@@ -169,6 +203,26 @@ AENetworkClassifier
 		return( x );
 	}
 	
+	public static String[]
+	getDefaultNetworks()
+	{
+		List<String>	res = new ArrayList<String>();
+
+		for ( String net: AT_NETWORKS ){
+			
+			if ( COConfigurationManager.getBooleanParameter( "Network Selection Default." + net )){
+		
+				res.add( net );
+			}
+		}
+	
+		String[]	x = new String[res.size()];
+		
+		res.toArray( x );
+		
+		return( x );
+	}
+	
 	public static void
 	addListener(
 		AENetworkClassifierListener	l )
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AENetworkClassifierListener.java b/azureus2/src/org/gudy/azureus2/core3/util/AENetworkClassifierListener.java
index 14aff85..321161f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AENetworkClassifierListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AENetworkClassifierListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AERunStateHandler.java b/azureus2/src/org/gudy/azureus2/core3/util/AERunStateHandler.java
index a9d7e4a..63a1833 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AERunStateHandler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AERunStateHandler.java
@@ -2,20 +2,19 @@
  * Created on Sep 18, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AERunnable.java b/azureus2/src/org/gudy/azureus2/core3/util/AERunnable.java
index 9bf5d29..7be47a3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AERunnable.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AERunnable.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AERunnableBoolean.java b/azureus2/src/org/gudy/azureus2/core3/util/AERunnableBoolean.java
index 1ac5c8e..1903525 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AERunnableBoolean.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AERunnableBoolean.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.util;
@@ -28,7 +25,7 @@ package org.gudy.azureus2.core3.util;
 public abstract class AERunnableBoolean
 	implements Runnable
 {
-	private boolean[] returnValueObject;
+	private Boolean[] returnValueObject;
 
 	private AESemaphore sem;
 
@@ -53,7 +50,7 @@ public abstract class AERunnableBoolean
 		}
 	}
 
-	public void setupReturn(String ID, boolean[] returnValueObject,
+	public void setupReturn(String ID, Boolean[] returnValueObject,
 			AESemaphore sem) {
 		id = ID;
 		this.returnValueObject = returnValueObject;
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AERunnableObject.java b/azureus2/src/org/gudy/azureus2/core3/util/AERunnableObject.java
index 6ee5fb2..f4948e5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AERunnableObject.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AERunnableObject.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.util;
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AERunnableWithCallback.java b/azureus2/src/org/gudy/azureus2/core3/util/AERunnableWithCallback.java
index 4c20d12..ea1f958 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AERunnableWithCallback.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AERunnableWithCallback.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.util;
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AESemaphore.java b/azureus2/src/org/gudy/azureus2/core3/util/AESemaphore.java
index 02662d0..46cbf14 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AESemaphore.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AESemaphore.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AESemaphore2.java b/azureus2/src/org/gudy/azureus2/core3/util/AESemaphore2.java
index fb5fbbe..d4536c1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AESemaphore2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AESemaphore2.java
@@ -1,48 +1,47 @@
-/*
- * Created on Mar 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 org.gudy.azureus2.core3.util;
-
-import java.util.concurrent.Semaphore;
-
-public class 
-AESemaphore2 
-{
-	private Semaphore		sem = new Semaphore(0);
-	
-	public 
-	AESemaphore2(
-		String		name )
-	{
-	}
-	
-	public void
-	reserve()
-	{
-		sem.acquireUninterruptibly();
-	}
-	
-	public void
-	release()
-	{
-		sem.release();
-	}
-}
+/*
+ * Created on Mar 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.util;
+
+import java.util.concurrent.Semaphore;
+
+public class 
+AESemaphore2 
+{
+	private Semaphore		sem = new Semaphore(0);
+	
+	public 
+	AESemaphore2(
+		String		name )
+	{
+	}
+	
+	public void
+	reserve()
+	{
+		sem.acquireUninterruptibly();
+	}
+	
+	public void
+	release()
+	{
+		sem.release();
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AETemporaryFileHandler.java b/azureus2/src/org/gudy/azureus2/core3/util/AETemporaryFileHandler.java
index aa0deca..64dcb09 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AETemporaryFileHandler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AETemporaryFileHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Oct-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEThread.java b/azureus2/src/org/gudy/azureus2/core3/util/AEThread.java
index af36a24..1a35029 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEThread.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEThread.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEThread2.java b/azureus2/src/org/gudy/azureus2/core3/util/AEThread2.java
index 14606c8..034b674 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEThread2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEThread2.java
@@ -1,7 +1,7 @@
 /*
  * Created on Nov 9, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEVerifier.java b/azureus2/src/org/gudy/azureus2/core3/util/AEVerifier.java
index 630d56c..8a30be7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEVerifier.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEVerifier.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AEVerifierException.java b/azureus2/src/org/gudy/azureus2/core3/util/AEVerifierException.java
index 758f94a..1678952 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AEVerifierException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AEVerifierException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AddressUtils.java b/azureus2/src/org/gudy/azureus2/core3/util/AddressUtils.java
index 2448a1f..0056bfc 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AddressUtils.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AddressUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -27,11 +24,17 @@ import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.URL;
 import java.net.UnknownHostException;
+import java.security.MessageDigest;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
+import org.bouncycastle.util.encoders.Base64;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
+
 import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.instancemanager.AZInstance;
 import com.aelitis.azureus.core.instancemanager.AZInstanceManager;
@@ -43,6 +46,22 @@ AddressUtils
 	public static final byte LAN_LOCAL_MAYBE	= 0;
 	public static final byte LAN_LOCAL_YES		= 1;
 	public static final byte LAN_LOCAL_NO		= 2;
+
+	private static boolean	i2p_is_lan_limit;
+	
+	static{
+		COConfigurationManager.addAndFireParameterListener(
+			"Plugin.azi2phelper.azi2phelper.rates.use.lan",
+			new ParameterListener()
+			{	
+				public void 
+				parameterChanged(
+					String parameterName ) 
+				{
+					i2p_is_lan_limit = COConfigurationManager.getBooleanParameter( "Plugin.azi2phelper.azi2phelper.rates.use.lan", false );
+				}
+			});
+	}
 	
 	private static AZInstanceManager	instance_manager;
 	
@@ -310,6 +329,20 @@ AddressUtils
 		return is_lan_local;
 	}
 	
+	public static boolean
+	applyLANRateLimits(
+		InetSocketAddress			address )
+	{
+		if ( i2p_is_lan_limit ){
+			
+			if ( address.isUnresolved()){
+		
+				return( AENetworkClassifier.categoriseAddress( address ) == AENetworkClassifier.AT_I2P );
+			}
+		}
+		
+		return( false );
+	}
 	/**
 	 * checks if the provided address is a global-scope ipv6 unicast address
 	 */
@@ -365,4 +398,159 @@ AddressUtils
 		return bestPick;
 	}
 	
+	public static InetAddress
+	getByName(
+		String		host )
+		
+		throws UnknownHostException
+	{
+		if ( AENetworkClassifier.categoriseAddress( host ) == AENetworkClassifier.AT_PUBLIC ){
+		
+			return( InetAddress.getByName( host ));
+		}
+		
+		throw( new UnknownHostException( host ));
+	}
+	
+	public static InetAddress[]
+	getAllByName(
+		String		host )
+		
+		throws UnknownHostException
+	{
+		if ( AENetworkClassifier.categoriseAddress( host ) == AENetworkClassifier.AT_PUBLIC ){
+		
+			return( InetAddress.getAllByName( host ));
+		}
+		
+		throw( new UnknownHostException( host ));
+	}
+	
+	public static byte[]
+	getAddressBytes(
+		InetSocketAddress	address )
+	{
+		if ( address.isUnresolved()){
+			
+			try{
+				return( address.getHostName().getBytes( "ISO8859-1" ));
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				return( null );
+			}
+		}else{
+			
+			return( address.getAddress().getAddress());
+		}
+	}
+	
+	public static String
+	getHostAddress(
+		InetSocketAddress	address )
+	{
+		if ( address.isUnresolved()){
+			
+			return( address.getHostName());
+			
+		}else{
+			
+			return( address.getAddress().getHostAddress());
+		}
+	}
+	
+	public static String
+	getHostNameNoResolve(
+		InetSocketAddress	address )
+	{
+		InetAddress i_address = address.getAddress();
+		
+		if ( i_address == null ){
+			
+			return( address.getHostName());
+			
+		}else{
+			
+				// only way I can see (short of reflection) of getting access to unresolved host name
+				// toString returns (hostname or "")/getHostAddress()
+			
+			String str = i_address.toString();
+			
+			int	pos = str.indexOf( '/' );
+
+			if ( pos == -1 ){
+				
+				// darn it, borkage
+				
+				System.out.println( "InetAddress::toString not returning expected result: " + str );
+				
+				return( i_address.getHostAddress());
+			}
+			
+			if ( pos > 0  ){
+				
+				return( str.substring( 0, pos ));
+				
+			}else{
+				
+				return( str.substring( pos+1 ));
+			}
+		}
+	}
+	
+	public static String
+	convertToShortForm(
+		String		address )
+	{
+		int	address_length = address.length();
+		
+		if ( address_length > 256  ){
+			
+			String to_decode;
+			
+			if ( address.endsWith( ".i2p" )){
+				
+				to_decode = address.substring( 0, address.length() - 4 );
+				
+			}else if ( address.indexOf( '.' ) == -1 ){
+				
+				to_decode = address;
+				
+			}else{
+				
+				return( address );
+			}
+			
+			try{
+					// unfortunately we have an incompatible base64 standard in i2p, they replaced / with ~ and + with -
+				
+				char[]	encoded = to_decode.toCharArray();
+				
+				for ( int i=0;i<encoded.length;i++){
+					
+					char c = encoded[i];
+					
+					if ( c == '~' ){
+						encoded[i] = '/';
+					}else if( c == '-' ){
+						encoded[i] = '+';
+					}
+				}
+				
+				byte[] decoded = Base64.decode( encoded );
+				
+				byte[] hash = MessageDigest.getInstance( "SHA-256" ).digest( decoded );
+				
+				return( Base32.encode( hash ).toLowerCase( Locale.US ) + ".b32.i2p" );
+				
+			}catch( Throwable e ){
+				
+				return( null );
+			}
+		}
+			
+		return( address );
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AsyncController.java b/azureus2/src/org/gudy/azureus2/core3/util/AsyncController.java
index 3d0f4c4..676273b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AsyncController.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AsyncController.java
@@ -1,32 +1,31 @@
-/*
- * Created on Sep 12, 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.core3.util;
-
-public interface
-AsyncController 
-{
-	public void
-	setAsyncStart();
-	
-	public void
-	setAsyncComplete();
-}
+/*
+ * Created on Sep 12, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.util;
+
+public interface
+AsyncController 
+{
+	public void
+	setAsyncStart();
+	
+	public void
+	setAsyncComplete();
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/AsyncDispatcher.java b/azureus2/src/org/gudy/azureus2/core3/util/AsyncDispatcher.java
index c834eab..4bf2e75 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/AsyncDispatcher.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/AsyncDispatcher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/Average.java b/azureus2/src/org/gudy/azureus2/core3/util/Average.java
index d2ca899..92903c8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/Average.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/Average.java
@@ -1,6 +1,6 @@
 /*
  * Created on june 12th, 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/BDecoder.java b/azureus2/src/org/gudy/azureus2/core3/util/BDecoder.java
index 49fd4fa..b70cfed 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/BDecoder.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/BDecoder.java
@@ -2,7 +2,7 @@
  * BeDecoder.java
  *
  * Created on May 30, 2003, 2:44 PM
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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;
@@ -72,7 +69,7 @@ public class BDecoder
 		PORTABLE_ROOT = portable;
 	}
 	
-	public static Map
+	public static Map<String,Object>
 	decode(
 		byte[]	data )
 
@@ -81,7 +78,7 @@ public class BDecoder
 		return( new BDecoder().decodeByteArray( data ));
 	}
 
-	public static Map
+	public static Map<String,Object>
 	decode(
 		byte[]	data,
 		int		offset,
@@ -92,7 +89,7 @@ public class BDecoder
 		return( new BDecoder().decodeByteArray( data, offset, length ));
 	}
 
-	public static Map
+	public static Map<String,Object>
 	decode(
 		BufferedInputStream	is  )
 
@@ -107,7 +104,7 @@ public class BDecoder
 	{	
 	}
 
-	public Map 
+	public Map<String,Object>
 	decodeByteArray(
 		byte[] data) 
 
@@ -116,7 +113,7 @@ public class BDecoder
 		return( decode(new BDecoderInputStreamArray(data),true));
 	}
 
-	public Map 
+	public Map<String, Object> 
 	decodeByteArray(
 		byte[] 	data,
 		int		offset,
@@ -127,7 +124,7 @@ public class BDecoder
 		return( decode(new BDecoderInputStreamArray(data, offset, length ),true));
 	}
 	
-	public Map 
+	public Map<String, Object> 
 	decodeByteArray(
 		byte[] 	data,
 		int		offset,
@@ -140,14 +137,14 @@ public class BDecoder
 	}
 	
 	// used externally 
-	public Map decodeByteBuffer(ByteBuffer buffer, boolean internKeys) throws IOException {
+	public Map<String, Object> decodeByteBuffer(ByteBuffer buffer, boolean internKeys) throws IOException {
 		InputStream is = new BDecoderInputStreamArray(buffer);
-		Map result = decode(is,internKeys);
+		Map<String,Object> result = decode(is,internKeys);
 		buffer.position(buffer.limit()-is.available());
 		return result;
 	}
 	
-	public Map 
+	public Map<String, Object> 
 	decodeStream(
 		BufferedInputStream data )  
 
@@ -156,7 +153,7 @@ public class BDecoder
 		return decodeStream(data, true);
 	}
 
-	public Map 
+	public Map<String, Object> 
 	decodeStream(
 		BufferedInputStream data,
 		boolean internKeys)  
@@ -174,10 +171,10 @@ public class BDecoder
 			throw( new BEncodingException( "BDecoder: top level isn't a Map" ));
 		}
 
-		return((Map)res );
+		return((Map<String,Object>)res );
 	}
 
-	private Map 
+	private Map<String, Object> 
 	decode(
 		InputStream data, boolean internKeys ) 
 
@@ -194,7 +191,7 @@ public class BDecoder
 			throw( new BEncodingException( "BDecoder: top level isn't a Map" ));
 		}
 
-		return((Map)res );
+		return((Map<String, Object>)res );
 	}
 	
 	// reuseable objects for key decoding
@@ -251,13 +248,13 @@ public class BDecoder
 
 					int keyLength = (int)getPositiveNumberFromStream(dbis, ':');
 
+					int skipBytes = 0;
+					
 					if ( keyLength > MAX_MAP_KEY_SIZE ){
-						byte[] remaining = new byte[128];
-						getByteArrayFromStream(dbis, 128, remaining);
-						String msg = "dictionary key is too large - " + keyLength + ":, max=" + MAX_MAP_KEY_SIZE + ": value=" + new String(remaining);
-						System.err.println( msg );
+						skipBytes = keyLength - MAX_MAP_KEY_SIZE;
+						keyLength = MAX_MAP_KEY_SIZE;
 						//new Exception().printStackTrace();
-						throw( new IOException( msg ));
+						//throw( new IOException( msg ));
 					}
 					
 					if(keyLength < keyBytesBuffer.capacity())
@@ -269,7 +266,11 @@ public class BDecoder
 						keyCharsBuffer = CharBuffer.allocate(keyLength);
 					}
 					
-					getByteArrayFromStream(dbis, keyLength, keyBytesBuffer.array());						
+					getByteArrayFromStream(dbis, keyLength, keyBytesBuffer.array());
+					
+					if (skipBytes > 0) {
+						dbis.skip(skipBytes);
+					}
 					
 					if ( verify_map_order ){
 						
@@ -331,7 +332,6 @@ public class BDecoder
 					if (internKeys)
 						key = StringInterner.intern( key );
 					
-					
 
 					//decode value
 
@@ -357,10 +357,20 @@ public class BDecoder
 						
 						break;
 					}
-				
-					if ( tempMap.put( key, value) != null ){
-						
-						Debug.out( "BDecoder: key '" + key + "' already exists!" );
+					
+					if (skipBytes > 0) {
+
+						String msg = "dictionary key is too large - "
+								+ (keyLength + skipBytes) + ":, max=" + MAX_MAP_KEY_SIZE
+								+ ": skipping key starting with " + new String(key.substring(0, 128));
+						System.err.println( msg );
+
+					} else {
+  				
+  					if ( tempMap.put( key, value) != null ){
+  						
+  						Debug.out( "BDecoder: key '" + key + "' already exists!" );
+  					}
 					}
 				}
 
@@ -1095,12 +1105,33 @@ public class BDecoder
     		
      	}else if ( obj instanceof String ){
       		
+ 			String s = (String)obj;
+
      		try{
-     			return(((String)obj).getBytes( "UTF-8" ));
+     			
+     			int	len = s.length();
+     			
+     			if ( len >= 6 && s.startsWith( "\\x" ) && s.endsWith( "\\x" )){			
+     				
+     				byte[]	result = new byte[(len-4)/2];
+     				
+     				int	pos = 2;
+     				
+     				for ( int i=0;i<result.length;i++){
+     					
+     					result[i] = (byte)Integer.parseInt( s.substring( pos, pos+2 ), 16 );
+     					
+     					pos += 2;
+     				}
+     				
+     				return( result );
+     			}
+     			
+     			return(s.getBytes( "UTF-8" ));
      			
      		}catch( Throwable e ){
      			
-     			return(((String)obj).getBytes());
+     			return(s.getBytes());
      		}
       		
      	}else if ( obj instanceof Long ){
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/BEncodableObject.java b/azureus2/src/org/gudy/azureus2/core3/util/BEncodableObject.java
index 4637733..5462e47 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/BEncodableObject.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/BEncodableObject.java
@@ -1,6 +1,6 @@
 /*
  * Created on Oct 24, 2009 10:21:17 PM
- * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/BEncoder.java b/azureus2/src/org/gudy/azureus2/core3/util/BEncoder.java
index c1c77e9..dd3990a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/BEncoder.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/BEncoder.java
@@ -2,7 +2,7 @@
  * BEncoder.java
  *
  * Created on June 4, 2003, 10:17 PM
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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;
@@ -260,13 +257,6 @@ BEncoder
             writeChar('i');
             writeLong(tempLong.longValue());
             writeChar('e');
-         }else if(object instanceof Integer){
-         	
-			Integer tempInteger = (Integer)object;         
-			//write out the l       
-			writeChar('i');
-			writeInt(tempInteger.intValue());
-			writeChar('e');
 			
        }else if(object instanceof byte[]){
        	
@@ -278,8 +268,24 @@ BEncoder
             }else{
             	writeBytes(tempByteArray);
             }
-            
-       }else if(object instanceof ByteBuffer ){
+
+       }else if ( object instanceof Integer ){
+        	
+			Integer tempInteger = (Integer)object;         
+			//write out the l       
+			writeChar('i');
+			writeInt(tempInteger.intValue());
+			writeChar('e');
+
+       }else if (object instanceof Byte ){
+        	
+			byte temp = (Byte)object;         
+		    
+			writeChar('i');
+			writeInt( temp & 0x000000ff );
+			writeChar('e');
+
+       }else if( object instanceof ByteBuffer ){
        	
        		ByteBuffer  bb = (ByteBuffer)object;
        		writeInt(bb.limit());
@@ -507,7 +513,38 @@ BEncoder
        		o = String.valueOf((Double)o);
        	}else if ( o instanceof byte[] ){    		
        		try{
-       			o = new String((byte[])o,"UTF-8");			
+       			byte[] b = (byte[])o;
+       			
+       			String s = new String(b,"UTF-8");		
+       			
+       			byte[] temp = s.getBytes( "UTF-8" );
+       			
+       				// if converting the raw byte array into a UTF string and back again doesn't result in
+       				// the same bytes then things ain't gonna work dump as a demarked hex string that
+       				// can be recognized and handled in BDecoder appropriately
+       			
+       			if ( !Arrays.equals( b, temp )){
+       				
+       				StringBuffer sb = new StringBuffer( b.length * 2 + 4 );
+       				
+					sb.append("\\x");
+
+       				for ( byte x: b ){
+       					String ss=Integer.toHexString(x&0xff);
+    					for(int k=0;k<2-ss.length();k++){
+    						sb.append('0');
+    					}
+    					sb.append(ss);
+       				}
+       				
+					sb.append("\\x");
+
+       				o = sb.toString();
+       				
+       			}else{
+       			
+       				o = s;
+       			}
        		}catch( Throwable e ){
        		}
        	}
@@ -783,6 +820,11 @@ BEncoder
     encodeToJSONArray(
     	List		b_list )
     {
+    	if ( b_list == null ){
+        	
+    		return( null );
+    	}
+    	
     	JSONArray	j_list = new JSONArray();
     	
     	for ( Object o: b_list ){
@@ -798,6 +840,11 @@ BEncoder
     encodeToJSONObject(
     	Map<Object,Object>		b_map )
     {
+    	if ( b_map == null ){
+        	
+    		return( null );
+    	}
+    	
     	JSONObject	j_map = new JSONObject();
     	
     	for ( Map.Entry<Object,Object> entry: b_map.entrySet()){
@@ -814,7 +861,12 @@ BEncoder
     public static String
     encodeToJSON(
     	Map	b_map )
-    {
+    {	
+    	if ( b_map == null ){
+    	
+    		return( null );
+    	}
+    	
     	JSONObject j_map = encodeToJSONObject( b_map );
     	
     	return( JSONUtils.encodeToJSON( j_map ));
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/BEncodingException.java b/azureus2/src/org/gudy/azureus2/core3/util/BEncodingException.java
index 729670b..781b32e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/BEncodingException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/BEncodingException.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.util;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/Base32.java b/azureus2/src/org/gudy/azureus2/core3/util/Base32.java
index e9024f3..db8b844 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/Base32.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/Base32.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/BrokenMd5Hasher.java b/azureus2/src/org/gudy/azureus2/core3/util/BrokenMd5Hasher.java
index 61f425d..407498c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/BrokenMd5Hasher.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/BrokenMd5Hasher.java
@@ -6,7 +6,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ByteArrayHashMap.java b/azureus2/src/org/gudy/azureus2/core3/util/ByteArrayHashMap.java
index b24d127..bae772a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ByteArrayHashMap.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ByteArrayHashMap.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Feb-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  * This is a hack based on Sun's implemenetation below to just support byte[] efficiently
  *  * @(#)HashMap.java	1.57 03/01/23
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ByteEncodedKeyHashMap.java b/azureus2/src/org/gudy/azureus2/core3/util/ByteEncodedKeyHashMap.java
index fe85e8d..80e0e70 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ByteEncodedKeyHashMap.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ByteEncodedKeyHashMap.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ByteFormatter.java b/azureus2/src/org/gudy/azureus2/core3/util/ByteFormatter.java
index c79717c..612d9a1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ByteFormatter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ByteFormatter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 2 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/CRC32C.java b/azureus2/src/org/gudy/azureus2/core3/util/CRC32C.java
new file mode 100644
index 0000000..ab8708c
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/core3/util/CRC32C.java
@@ -0,0 +1,99 @@
+/*
+ * Created on Feb 20, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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 org.gudy.azureus2.core3.util;
+
+public class
+CRC32C
+{
+	private static final long[] CONSTANTS = {
+		0x00000000L, 0xf26b8303L, 0xe13b70f7L, 0x1350f3f4L, 0xc79a971fL, 0x35f1141cL, 0x26a1e7e8L, 0xd4ca64ebL,
+		0x8ad958cfL, 0x78b2dbccL, 0x6be22838L, 0x9989ab3bL, 0x4d43cfd0L, 0xbf284cd3L, 0xac78bf27L, 0x5e133c24L,
+		0x105ec76fL, 0xe235446cL, 0xf165b798L, 0x030e349bL, 0xd7c45070L, 0x25afd373L, 0x36ff2087L, 0xc494a384L,
+		0x9a879fa0L, 0x68ec1ca3L, 0x7bbcef57L, 0x89d76c54L, 0x5d1d08bfL, 0xaf768bbcL, 0xbc267848L, 0x4e4dfb4bL,
+		0x20bd8edeL, 0xd2d60dddL, 0xc186fe29L, 0x33ed7d2aL, 0xe72719c1L, 0x154c9ac2L, 0x061c6936L, 0xf477ea35L,
+		0xaa64d611L, 0x580f5512L, 0x4b5fa6e6L, 0xb93425e5L, 0x6dfe410eL, 0x9f95c20dL, 0x8cc531f9L, 0x7eaeb2faL,
+		0x30e349b1L, 0xc288cab2L, 0xd1d83946L, 0x23b3ba45L, 0xf779deaeL, 0x05125dadL, 0x1642ae59L, 0xe4292d5aL,
+		0xba3a117eL, 0x4851927dL, 0x5b016189L, 0xa96ae28aL, 0x7da08661L, 0x8fcb0562L, 0x9c9bf696L, 0x6ef07595L,
+		0x417b1dbcL, 0xb3109ebfL, 0xa0406d4bL, 0x522bee48L, 0x86e18aa3L, 0x748a09a0L, 0x67dafa54L, 0x95b17957L,
+		0xcba24573L, 0x39c9c670L, 0x2a993584L, 0xd8f2b687L, 0x0c38d26cL, 0xfe53516fL, 0xed03a29bL, 0x1f682198L,
+		0x5125dad3L, 0xa34e59d0L, 0xb01eaa24L, 0x42752927L, 0x96bf4dccL, 0x64d4cecfL, 0x77843d3bL, 0x85efbe38L,
+		0xdbfc821cL, 0x2997011fL, 0x3ac7f2ebL, 0xc8ac71e8L, 0x1c661503L, 0xee0d9600L, 0xfd5d65f4L, 0x0f36e6f7L,
+		0x61c69362L, 0x93ad1061L, 0x80fde395L, 0x72966096L, 0xa65c047dL, 0x5437877eL, 0x4767748aL, 0xb50cf789L,
+		0xeb1fcbadL, 0x197448aeL, 0x0a24bb5aL, 0xf84f3859L, 0x2c855cb2L, 0xdeeedfb1L, 0xcdbe2c45L, 0x3fd5af46L,
+		0x7198540dL, 0x83f3d70eL, 0x90a324faL, 0x62c8a7f9L, 0xb602c312L, 0x44694011L, 0x5739b3e5L, 0xa55230e6L,
+		0xfb410cc2L, 0x092a8fc1L, 0x1a7a7c35L, 0xe811ff36L, 0x3cdb9bddL, 0xceb018deL, 0xdde0eb2aL, 0x2f8b6829L,
+		0x82f63b78L, 0x709db87bL, 0x63cd4b8fL, 0x91a6c88cL, 0x456cac67L, 0xb7072f64L, 0xa457dc90L, 0x563c5f93L,
+		0x082f63b7L, 0xfa44e0b4L, 0xe9141340L, 0x1b7f9043L, 0xcfb5f4a8L, 0x3dde77abL, 0x2e8e845fL, 0xdce5075cL,
+		0x92a8fc17L, 0x60c37f14L, 0x73938ce0L, 0x81f80fe3L, 0x55326b08L, 0xa759e80bL, 0xb4091bffL, 0x466298fcL,
+		0x1871a4d8L, 0xea1a27dbL, 0xf94ad42fL, 0x0b21572cL, 0xdfeb33c7L, 0x2d80b0c4L, 0x3ed04330L, 0xccbbc033L,
+		0xa24bb5a6L, 0x502036a5L, 0x4370c551L, 0xb11b4652L, 0x65d122b9L, 0x97baa1baL, 0x84ea524eL, 0x7681d14dL,
+		0x2892ed69L, 0xdaf96e6aL, 0xc9a99d9eL, 0x3bc21e9dL, 0xef087a76L, 0x1d63f975L, 0x0e330a81L, 0xfc588982L,
+		0xb21572c9L, 0x407ef1caL, 0x532e023eL, 0xa145813dL, 0x758fe5d6L, 0x87e466d5L, 0x94b49521L, 0x66df1622L,
+		0x38cc2a06L, 0xcaa7a905L, 0xd9f75af1L, 0x2b9cd9f2L, 0xff56bd19L, 0x0d3d3e1aL, 0x1e6dcdeeL, 0xec064eedL,
+		0xc38d26c4L, 0x31e6a5c7L, 0x22b65633L, 0xd0ddd530L, 0x0417b1dbL, 0xf67c32d8L, 0xe52cc12cL, 0x1747422fL,
+		0x49547e0bL, 0xbb3ffd08L, 0xa86f0efcL, 0x5a048dffL, 0x8ecee914L, 0x7ca56a17L, 0x6ff599e3L, 0x9d9e1ae0L,
+		0xd3d3e1abL, 0x21b862a8L, 0x32e8915cL, 0xc083125fL, 0x144976b4L, 0xe622f5b7L, 0xf5720643L, 0x07198540L,
+		0x590ab964L, 0xab613a67L, 0xb831c993L, 0x4a5a4a90L, 0x9e902e7bL, 0x6cfbad78L, 0x7fab5e8cL, 0x8dc0dd8fL,
+		0xe330a81aL, 0x115b2b19L, 0x020bd8edL, 0xf0605beeL, 0x24aa3f05L, 0xd6c1bc06L, 0xc5914ff2L, 0x37faccf1L,
+		0x69e9f0d5L, 0x9b8273d6L, 0x88d28022L, 0x7ab90321L, 0xae7367caL, 0x5c18e4c9L, 0x4f48173dL, 0xbd23943eL,
+		0xf36e6f75L, 0x0105ec76L, 0x12551f82L, 0xe03e9c81L, 0x34f4f86aL, 0xc69f7b69L, 0xd5cf889dL, 0x27a40b9eL,
+		0x79b737baL, 0x8bdcb4b9L, 0x988c474dL, 0x6ae7c44eL, 0xbe2da0a5L, 0x4c4623a6L, 0x5f16d052L, 0xad7d5351L,
+	};
+
+
+	private long value = 0xffffffffL;
+
+	public void 
+	update(
+		byte[]	bytes )
+	{
+		for ( int i=0; i<bytes.length; i++ ){
+
+			int index = (int)((value^bytes[i])&0xff);
+				    
+			value = (CONSTANTS[index]^(value>>8))&0xffffffffL;
+		}
+	}
+	
+	public void 
+	updateWord(
+		byte[]	bytes,
+		boolean	reverse )
+	{
+		if ( reverse ){
+			
+			for ( int i=bytes.length-1; i>=0; i-- ){
+	
+				int index = (int)((value^bytes[i])&0xff);
+					    
+				value = (CONSTANTS[index]^(value>>8))&0xffffffffL;
+			}
+		}else{
+			update( bytes );
+		}
+	}
+	
+	public long
+	getValue()
+	{
+		return( value^0xffffffffL );
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHashMapWrapper.java b/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHashMapWrapper.java
index e6a204d..90f2bec 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHashMapWrapper.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHashMapWrapper.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2014 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -39,7 +38,7 @@ ConcurrentHashMapWrapper<S,T>
 	private final S	S_NULL = (S)NULL;
 	private final T	T_NULL = (T)NULL;
 	
-	private ConcurrentHashMap<S,T>	map;
+	private final ConcurrentHashMap<S,T>	map;
 	
 	public 
 	ConcurrentHashMapWrapper(
@@ -65,11 +64,11 @@ ConcurrentHashMapWrapper<S,T>
 	
 	public 
 	ConcurrentHashMapWrapper(
-		Map<S,T>	map )
+		Map<S,T>	init_map )
 	{
-		map = new ConcurrentHashMap<S,T>( map.size());
+		map = new ConcurrentHashMap<S,T>( init_map.size());
 		
-		putAll( map );
+		putAll( init_map );
 	}
 	
 	public void
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasher.java b/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasher.java
index 9cd0fca..6fa02c2 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasher.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasherRequest.java b/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasherRequest.java
index cc99c4c..f27c65b 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasherRequest.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasherRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasherRequestListener.java b/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasherRequestListener.java
index e879598..2cf4507 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasherRequestListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ConcurrentHasherRequestListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/Constants.java b/azureus2/src/org/gudy/azureus2/core3/util/Constants.java
index b8d9eb4..5b20748 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/Constants.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/Constants.java
@@ -1,6 +1,6 @@
 /*
  * Created on 16 juin 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
@@ -136,10 +133,10 @@ Constants
   public static final String AZUREUS_NAME	  					= "Azureus";
   public static final String AZUREUS_PROTOCOL_NAME_PRE_4813	  	= "Azureus";
   public static final String AZUREUS_PROTOCOL_NAME	  			= "Vuze";
-  public static final String AZUREUS_VERSION  = "5.3.0.0";
+  public static final String AZUREUS_VERSION  = "5.6.1.2";
   public static final String BUILD_VERSION  = "@build.version@";   //Ant replace
   public static final String AZUREUS_SUBVER	  = "";
-  public static final byte[] VERSION_ID       = ("-" + "AZ" + "5300" + "-").getBytes();  //MUST be 8 chars long!
+  public static final byte[] VERSION_ID       = ("-" + "AZ" + "5612" + "-").getBytes();  //MUST be 8 chars long!
 
   private static final boolean FORCE_NON_CVS = System.getProperty( "az.force.noncvs", "0" ).equals( "1" );
   
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/Debug.java b/azureus2/src/org/gudy/azureus2/core3/util/Debug.java
index 59d796d..ac3e110 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/Debug.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/Debug.java
@@ -2,7 +2,7 @@
  * Created on Nov 19, 2003
  * Created by Alon Rohter
  *
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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;
 
@@ -239,10 +236,14 @@ public class Debug {
 					break;
 				}
 				// Formatted so it's clickable in eclipse
+				// sbStackTrace.append(st[i].toString());
+				
+				// Shorter version  method(filename.java:1234)
 				sbStackTrace.append(st[i].getMethodName());
+				// the space is needed otherwise Eclipse tries to look up method name
 				sbStackTrace.append(" (");
-				sbStackTrace.append(classname);
-				sbStackTrace.append(".java:");
+				sbStackTrace.append(st[i].getFileName());
+				sbStackTrace.append(':');
 				sbStackTrace.append(st[i].getLineNumber());
 				sbStackTrace.append(')');
 			} else {
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/DebugLight.java b/azureus2/src/org/gudy/azureus2/core3/util/DebugLight.java
index 52a1a77..a544818 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/DebugLight.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/DebugLight.java
@@ -1,7 +1,7 @@
 /*
  * Created on 01-Feb-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/DebugWeakList.java b/azureus2/src/org/gudy/azureus2/core3/util/DebugWeakList.java
index 511338b..8be21bc 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/DebugWeakList.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/DebugWeakList.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/DelayedEvent.java b/azureus2/src/org/gudy/azureus2/core3/util/DelayedEvent.java
index 85047c7..33f8fef 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/DelayedEvent.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/DelayedEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBuffer.java b/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBuffer.java
index 1ba4116..3eee5c8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBuffer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBuffer.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 21, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBufferPool.java b/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBufferPool.java
index e65252a..d3a5460 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBufferPool.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBufferPool.java
@@ -3,7 +3,7 @@
  * Created by Alon Rohter
  * Copyright (C) 2004, 2005, 2006 Alon Rohter, All Rights Reserved.
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -16,9 +16,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBufferPoolReal.java b/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBufferPoolReal.java
index aa78665..323c1d9 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBufferPoolReal.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/DirectByteBufferPoolReal.java
@@ -1,1090 +1,1089 @@
-/*
- * Created on Nov 4, 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.core3.util;
-
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.disk.DiskManager;
-import org.gudy.azureus2.core3.logging.LogAlert;
-import org.gudy.azureus2.core3.logging.Logger;
-
-import com.aelitis.azureus.core.diskmanager.cache.CacheFileManager;
-import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerFactory;
-import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerStats;
-
-public class 
-DirectByteBufferPoolReal 
-	extends DirectByteBufferPool
-{
-	private static final boolean disable_gc = System.getProperty( "az.disable.explicit.gc", "0" ).equals( "1" );
-	
-	static{
-	
-		if ( disable_gc ){
-	
-			System.out.println( "Explicit GC disabled" );
-		}
-	}
-	
-	protected static final boolean				DEBUG_TRACK_HANDEDOUT	= AEDiagnostics.TRACE_DBB_POOL_USAGE;
-	protected static final boolean				DEBUG_PRINT_MEM			= AEDiagnostics.PRINT_DBB_POOL_USAGE;
-	
-	protected static final int					DEBUG_PRINT_TIME		= 120 * 1000;
-	
-	protected static final boolean				DEBUG_HANDOUT_SIZES		= false;
-	protected static final boolean				DEBUG_FREE_SIZES		= false;
-	
-	
-	
-	
-	
-	  // There is no point in allocating buffers smaller than 4K,
-	  // as direct ByteBuffers are page-aligned to the underlying
-	  // system, which is 4096 byte pages under most OS's.
-	  // If we want to save memory, we can distribute smaller-than-4K
-	  // buffers by using the slice() method to break up a standard buffer
-	  // into smaller chunks, but that's more work.
-	
-	private static final int START_POWER = 12;    // 4096
-	private static final int END_POWER   = 25;    // 33554432
-  
-  		// without an extra bucket here we get lots of wastage with the file cache as typically
-  		// 16K data reads result in a buffer slightly bigger than 16K due to protocol header
-  		// This means we would bump up to 32K pool entries, hence wasting 16K per 16K entry
-  	
-	private static final int[]	EXTRA_BUCKETS = { DiskManager.BLOCK_SIZE + 128 };
-  
-  
-	public static final int MAX_SIZE = BigInteger.valueOf(2).pow(END_POWER).intValue();
-  
-	private static final DirectByteBufferPoolReal pool = new DirectByteBufferPoolReal();
-  
-
-	private final Map buffersMap = new LinkedHashMap(END_POWER - START_POWER + 1);
-  
-	private final Object poolsLock = new Object();
-
-	private static final int	SLICE_END_SIZE				= 2048;	
-	private static final int    SLICE_ALLOC_CHUNK_SIZE		= 4096;
-  
-
-	private static final short[]		SLICE_ENTRY_SIZES		= { 8, 16, 32, 64, 128, 256, 512, 1024, SLICE_END_SIZE };
-	private static final short[]		SLICE_ALLOC_MAXS		= { 256, 256, 128, 64, 64,  64,  64,  64,   64 };
-	
-	private static final short[]		SLICE_ENTRY_ALLOC_SIZES = new short[SLICE_ENTRY_SIZES.length];
-	private static final List[]			slice_entries 			= new List[SLICE_ENTRY_SIZES.length];
-	private static final boolean[][]	slice_allocs 			= new boolean[SLICE_ENTRY_SIZES.length][];
-	private static final boolean[]		slice_alloc_fails		= new boolean[SLICE_ENTRY_SIZES.length];
-	
-	static{
-		
-		int mult = COConfigurationManager.getIntParameter( "memory.slice.limit.multiplier" );
-		
-		if ( mult > 1 ){
-			
-			for (int i=0;i<SLICE_ALLOC_MAXS.length;i++){
-				
-				SLICE_ALLOC_MAXS[i] *= mult;
-			}
-		}
-		
-		for (int i=0;i<SLICE_ENTRY_SIZES.length;i++){
-			
-			SLICE_ENTRY_ALLOC_SIZES[i] = (short)(SLICE_ALLOC_CHUNK_SIZE/SLICE_ENTRY_SIZES[i]);
-					
-			slice_allocs[i] = new boolean[SLICE_ALLOC_MAXS[i]];
-			
-			slice_entries[i] = new LinkedList();
-		}
-	}
-	
-	private static final long[]			slice_use_count 	= new long[SLICE_ENTRY_SIZES.length];
-  
-	private final Map handed_out	= new IdentityHashMap();	// for debugging (ByteBuffer has .equals defined on contents, hence IdentityHashMap)
-	
-	private final Map	size_counts	= new TreeMap();
- 
-	private static final long COMPACTION_CHECK_PERIOD = 2*60*1000; //2 min
-	private static final long MAX_FREE_BYTES = 10*1024*1024; //10 MB
-	private static final long MIN_FREE_BYTES = 1*1024*1024; // 1 MB
-  
-	private long bytesIn = 0;
-	private long bytesOut = 0;
-  
-  
-	protected 
-	DirectByteBufferPoolReal() 
-	{
-	    //create the buffer pool for each buffer size
-	  	
-	  	ArrayList	list = new ArrayList();
-	  	
-	    for (int p=START_POWER; p <= END_POWER; p++) {
-	    	
-	    	list.add( new Integer(BigInteger.valueOf(2).pow(p).intValue()));
-	    }
-	    
-	    for (int i=0;i<EXTRA_BUCKETS.length;i++){
-	    	       
-	        list.add( new Integer(EXTRA_BUCKETS[i]));
-	    }
-	    
-	    Integer[]	sizes = new Integer[ list.size() ];
-	    list.toArray( sizes );
-	    Arrays.sort( sizes);
-	    
-	    for (int i=0;i<sizes.length;i++){
-	    	
-	    	ArrayList bufferPool = new ArrayList();
-	    	
-	    	buffersMap.put(sizes[i], bufferPool);
-	    }
-	    
-	    //initiate periodic timer to check free memory usage
-	    SimpleTimer.addPeriodicEvent(
-	    	"DirectBB:compact",
-	        COMPACTION_CHECK_PERIOD,
-	        new TimerEventPerformer() {
-	          public void perform( TimerEvent ev ) {
-	       
-	            compactBuffers();
-	          }
-	        }
-	     );
-	    
-	    if( DEBUG_PRINT_MEM ) {
-	      Timer printer = new Timer("printer");
-	      printer.addPeriodicEvent(
-	          DEBUG_PRINT_TIME,
-	          new TimerEventPerformer() {
-	            public void perform( TimerEvent ev ) {
-	              printInUse( false );
-	            }
-	          }
-	      );
-	    }
-	}
-
-  
-  /**
-   * Allocate and return a new direct ByteBuffer.
-   */
-  private ByteBuffer allocateNewBuffer(final int _size) {
-    try {
-      return ByteBuffer.allocateDirect(_size);
-    }
-    catch (OutOfMemoryError e) {
-       //Debug.out("Running garbage collector...");
-       
-       clearBufferPools();
-       
-       runGarbageCollection();
-
-       try {
-       		return ByteBuffer.allocateDirect(_size);
-       	
-       }catch (OutOfMemoryError ex) {
-       	
-         String msg = "Memory allocation failed: Out of direct memory space.\n"
-                    + "To fix: Use the -XX:MaxDirectMemorySize=512m command line option,\n"
-                    + "or upgrade your Java JRE to version 1.4.2_05 or 1.5 series or newer.";
-       	 Debug.out( msg );
-       	 
-       	 Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, msg));
-         
-         printInUse( true );
-         
-         throw( ex );
-       }
-    }
-  }
-
-  
-  /**
-   * Retrieve a buffer from the buffer pool of size at least
-   * <b>length</b>, and no larger than <b>DirectByteBufferPool.MAX_SIZE</b>
-   */
-  protected DirectByteBuffer 
-  getBufferSupport(
-  	byte	_allocator,
-  	int 	_length) 
-  {
-    if (_length < 1) {
-        Debug.out("requested length [" +_length+ "] < 1");
-        return null;
-    }
-
-    if (_length > MAX_SIZE) {
-        Debug.out("requested length [" +_length+ "] > MAX_SIZE [" +MAX_SIZE+ "]");
-        return null;
-    }
-    
-    return pool.getBufferHelper(_allocator,_length);
-  }
-  
-  
-  /**
-   * Retrieve an appropriate buffer from the free pool, or
-   * create a new one if the pool is empty.
-   */
-  
-  
-  	private DirectByteBuffer 
-  	getBufferHelper(
-		byte	_allocator,
-		int 	_length) 
-	{
-		DirectByteBuffer	res;
-		
-		if ( _length <= SLICE_END_SIZE ){
-
-			res = getSliceBuffer( _allocator, _length );
-			
-		}else{
-				
-			ByteBuffer	buff = null;
-			
-			Integer reqVal = new Integer(_length);
-	    
-				//loop through the buffer pools to find a buffer big enough
-	    
-			Iterator it = buffersMap.keySet().iterator();
-	    
-			while (it.hasNext()) {
-	    	
-				Integer keyVal = (Integer)it.next();
-	
-					//	check if the buffers in this pool are big enough
-	      
-				if ( reqVal.compareTo(keyVal) <= 0 ){
-	      	
-					ArrayList bufferPool = (ArrayList)buffersMap.get(keyVal);
-	        
-					while( true ){
-						
-						synchronized ( poolsLock ) { 
-		        
-							// make sure we don't remove a buffer when running compaction
-							// if there are no free buffers in the pool, create a new one.
-							// otherwise use one from the pool
-		        	
-							if ( bufferPool.isEmpty()){
-		          	
-								buff = allocateNewBuffer(keyVal.intValue());
-		            
-								if ( buff == null ){
-									
-									Debug.out( "allocateNewBuffer for " + _length + " returned null" );
-								}
-								
-								break;
-								
-							}else{
-		          	
-								synchronized ( bufferPool ) {
-		            	
-									buff = (ByteBuffer)bufferPool.remove(bufferPool.size() - 1);
-								}
-								
-								if ( buff == null ){
-									
-									Debug.out( "buffer pool for " + _length + " contained null entry" ); 
-									
-								}else{
-									
-									break;
-								}
-							}
-						}
-					}
-					
-					break;
-				}
-			}
-		
-			if ( buff == null ){
-					
-				String str = "Unable to find an appropriate buffer pool for " + _length;
-				
-			    Debug.out( str );
-			    
-			    throw( new RuntimeException( str ));
-			}
-			
-			res = new DirectByteBuffer( _allocator, buff, this );		   
-		}
-			
-        	// clear doesn't actually zero the data, it just sets pos to 0 etc.
-        
-		ByteBuffer buff = res.getBufferInternal();
-		
-        buff.clear();   //scrub the buffer
-        
-		buff.limit( _length );
-		
-        bytesOut += buff.capacity();
-                                
-        if ( DEBUG_PRINT_MEM || DEBUG_TRACK_HANDEDOUT ){
-        	
-        	synchronized( handed_out ){
-        	        	
-				if ( DEBUG_HANDOUT_SIZES ){
-					
-					int	trim_size;
-					
-					if ( _length < 32 ){
-						
-						trim_size = 4;
-					}else{
-						
-						trim_size = 16;
-					}
-					
-					int	trim = ((_length+trim_size-1)/trim_size)*trim_size;
-					
-					Long count = (Long)size_counts.get(new Integer(trim));
-					
-					if ( count == null ){
-						
-						size_counts.put( new Integer( trim ), new Long(1));
-						
-					}else{
-						
-						size_counts.put( new Integer( trim), new Long( count.longValue() + 1 ));
-					}
-				}
-				
-        		if ( handed_out.put( buff, res ) != null ){
-          		
-        			Debug.out( "buffer handed out twice!!!!");
-          		
-        			throw( new RuntimeException( "Buffer handed out twice" ));
-        		}
-        	
-				//System.out.println( "[" + handed_out.size() + "] -> " + buff + ", bytesIn = " + bytesIn + ", bytesOut = " + bytesOut );
-          	}
-        }
-        
-        // addInUse( dbb.capacity() );
-        
-        return( res );
-    }
-  
-  
-	  /**
-	   * Return the given buffer to the appropriate pool.
-	   */
-	
-	protected void 
-	returnBufferSupport(
-		DirectByteBuffer ddb ) 
-	{		
-		ByteBuffer	buff = ddb.getBufferInternal();
-		
-		if ( buff == null ){
-			
-			Debug.out( "Returned dbb has null delegate" );
-			
-			throw( new RuntimeException( "Returned dbb has null delegate" ));
-		}
-		
-		int	capacity = buff.capacity();
-
-		bytesIn += capacity;
-		    
-	  	if ( DEBUG_TRACK_HANDEDOUT ){
-	  		
-	  		synchronized( handed_out ){
-
-	  			if ( handed_out.remove( buff ) == null ){
-	  				
-	  				Debug.out( "buffer not handed out" );
-	  				
-	  				throw( new RuntimeException( "Buffer not handed out" ));
-	  			}
-	  			
-	       		// System.out.println( "[" + handed_out.size() + "] <- " + buffer + ", bytesIn = " + bytesIn + ", bytesOut = " + bytesOut );
-	  		}
-	  	}
-	  	
-	    // remInUse( buffer.capacity() );
-		
-		if ( capacity <= SLICE_END_SIZE ){
-			
-			freeSliceBuffer( ddb );
-			
-		}else{
-		    Integer buffSize = new Integer(capacity);
-		    
-		    ArrayList bufferPool = (ArrayList)buffersMap.get(buffSize);
-		    
-		    if (bufferPool != null) {
-				
-				//no need to sync around 'poolsLock', as adding during compaction is ok
-				
-		      synchronized ( bufferPool ){
-				  
-		        bufferPool.add(buff);
-		      }
-		    }else{
-				
-		      Debug.out("Invalid buffer given; could not find proper buffer pool");
-		    }
-		}
-	}
-  
-  
-  /**
-   * Clears the free buffer pools so that currently
-   * unused buffers can be garbage collected.
-   */
-  private void clearBufferPools() {
-    Iterator it = buffersMap.values().iterator();
-    while (it.hasNext()) {
-        ArrayList bufferPool = (ArrayList)it.next();
-        bufferPool.clear();
-    }
-  }
-  
-  
-  /**
-   * Force system garbage collection.
-   */
-  private void runGarbageCollection() {
-	if ( !disable_gc ){
-	    if( DEBUG_PRINT_MEM ) {
-	      System.out.println( "runGarbageCollection()" );
-	    }
-	    System.runFinalization();
-	    System.gc();
-	}
-  }
-  
-  
-  /**
-   * Checks memory usage of free buffers in buffer pools,
-   * and calls the compaction method if necessary.
-   */
-  private void compactBuffers() {
-	  
-	  nonsliecd: synchronized (poolsLock)
-		{
-			long freeSize = bytesFree();
-			
-			if (freeSize < MIN_FREE_BYTES)
-				break nonsliecd;
-			
-			// apply cleanup pressure based on filling degree
-			float remainingFactor;
-			if (freeSize > MAX_FREE_BYTES) // downsize to 50% of the limit (not the current capacity!) if we're overlimit 
-				remainingFactor = 0.5f * MAX_FREE_BYTES / (float) freeSize;
-			else // reduce to something between 50% (full: maximum reduction) and 100% (empty: no reduction)  
-				remainingFactor = 1.0f - 0.5f * freeSize / (float) MAX_FREE_BYTES;
-			
-			if (DEBUG_PRINT_MEM)
-				System.out.println("Performing cleanup, reducing to " + remainingFactor * 100 + "%");
-			
-			ArrayList pools = new ArrayList(buffersMap.values());
-			for (int i = pools.size() - 1; i >= 0; i--)
-			{
-				ArrayList pool = (ArrayList) pools.get(i);
-				int limit = (int) (pool.size() * remainingFactor); // floor(), this way we can reach 0 at some point
-				for (int j = pool.size() - 1; j >= limit; j--)
-					pool.remove(j);
-			}
-			
-			runGarbageCollection();
-			
-			if (DEBUG_PRINT_MEM)
-			{
-				printInUse(false);
-				System.out.println("Cleanup done\n");
-			}
-		}
-  
-		compactSlices();
-	}
- 
-  
-  
-  private long bytesFree() {
-    long bytesUsed = 0;
-    synchronized( poolsLock ) {
-      //count up total bytes used by free buffers
-      Iterator it = buffersMap.keySet().iterator();
-      while (it.hasNext()) {
-        Integer keyVal = (Integer)it.next();
-        ArrayList bufferPool = (ArrayList)buffersMap.get(keyVal);
-      
-        bytesUsed += keyVal.intValue() * bufferPool.size();
-      }
-    }
-    return bytesUsed;
-  }
-  
-  
-  /*
-  private final HashMap in_use_counts = new HashMap();
-  
-  private void addInUse( int size ) {
-    Integer key = new Integer( size );
-    synchronized( in_use_counts ) {
-      Integer count = (Integer)in_use_counts.get( key );
-      if( count == null )  count = new Integer( 1 );
-      else  count = new Integer( count.intValue() + 1 );
-      in_use_counts.put( key, count );
-    }
-  }
-  
-  private void remInUse( int size ) {
-    Integer key = new Integer( size );
-    synchronized( in_use_counts ) {
-      Integer count = (Integer)in_use_counts.get( key );
-      if( count == null ) System.out.println("count = null");
-      if( count.intValue() == 0 ) System.out.println("count = 0");
-      in_use_counts.put( key, new Integer( count.intValue() - 1 ) );
-    }
-  }
-  
-  private void printInUse() {
-    synchronized( in_use_counts ) {
-      for( Iterator i = in_use_counts.keySet().iterator(); i.hasNext(); ) {
-        Integer key = (Integer)i.next();
-        int count = ((Integer)in_use_counts.get( key )).intValue();
-        int size = key.intValue();
-        if( count > 0 ) {
-          if( size < 1024 )  System.out.print("[" +size+ " x " +count+ "] ");
-          else  System.out.print("[" +size/1024+ "K x " +count+ "] ");
-        }
-      }
-      System.out.println();
-    }
-  }
-  */
-  
-  	private void
-	printInUse(
-		boolean		verbose )
-  	{
-  		if ( DEBUG_PRINT_MEM ){
-  			
-            System.out.print("DIRECT: given=" +bytesOut/1024/1024+ "MB, returned=" +bytesIn/1024/1024+ "MB, ");
-            
-            long in_use = bytesOut - bytesIn;
-            if( in_use < 1024*1024 ) System.out.print( "in use=" +in_use+ "B, " );
-            else System.out.print( "in use=" +in_use/1024/1024+ "MB, " );
-            
-            long free = bytesFree();
-            if( free < 1024*1024 ) System.out.print( "free=" +free+ "B" );
-            else System.out.print( "free=" +free/1024/1024+ "MB" );
-
-  			System.out.println();
-  			
-	  		CacheFileManager cm	= null;
-	  		
-			try{
-	 			cm = CacheFileManagerFactory.getSingleton();
-	 			
-			}catch( Throwable e ){
-					
-				Debug.printStackTrace( e );
-			}
-	 
-	  		synchronized( handed_out ){
-	    	
-	  			Iterator	it = handed_out.values().iterator();
-	  			
-	  			Map	cap_map		= new TreeMap();
-	  			Map	alloc_map	= new TreeMap();
-	  			
-	  			while( it.hasNext()){
-	  				
-	  				DirectByteBuffer	db = (DirectByteBuffer)it.next();
-	  				
-	  				if ( verbose ){
-		  				String	trace = db.getTraceString();
-		  				
-		  				if ( trace != null ){
-		  					
-		  					System.out.println( trace );
-		  				}
-	  				}
-	  				
-	  				Integer cap 	= new Integer( db.getBufferInternal().capacity());
-	  				Byte	alloc 	= new Byte( db.getAllocator());
-	  				
-	  				myInteger	c = (myInteger)cap_map.get(cap);
-	  				
-	  				if ( c == null ){
-	  					
-	  					c	= new myInteger();
-	  					
-	  					cap_map.put( cap, c );
-	  				}
-	  				
-	  				c.value++;
-	  				
-					myInteger	a = (myInteger)alloc_map.get(alloc);
-	  				
-	  				if ( a == null ){
-	  					
-	  					a	= new myInteger();
-	  					
-	  					alloc_map.put( alloc, a );
-	  				}
-	  				
-	  				a.value++;				
-	  			}
-	  			
-	  			it = cap_map.keySet().iterator();
-	  			
-	  			while( it.hasNext()){
-	  				
-	  				Integer		key 	= (Integer)it.next();
-	  				myInteger	count 	= (myInteger)cap_map.get( key );
-	  				
-	  		        if( key.intValue() < 1024 ){
-	  		        	
-	  		        	System.out.print("[" +key.intValue()+ " x " +count.value+ "] ");
-	  		        	
-	  		        }else{  
-	  		        	
-	  		        	System.out.print("[" +key.intValue()/1024+ "K x " +count.value+ "] ");
-	  		        }
-	  			}
-	  			
-	  			System.out.println();
-	  			
-				it = alloc_map.keySet().iterator();
-	  			
-	  			while( it.hasNext()){
-	  				
-	  				Byte		key 	= (Byte)it.next();
-	  				myInteger	count 	= (myInteger)alloc_map.get( key );
-	  				
-	  	        	System.out.print("[" + DirectByteBuffer.AL_DESCS[key.intValue()]+ " x " +count.value+ "] ");
-	  			}
-	  			
-	  			if ( cm != null ){
-	  				
-	  				CacheFileManagerStats stats = cm.getStats();
-	  				
-	  				System.out.print( " - Cache: " );
-	  	  			
-	  				
-					System.out.print( "sz=" + stats.getSize());
-					System.out.print( ",us=" + stats.getUsedSize());
-					System.out.print( ",cw=" + stats.getBytesWrittenToCache());
-					System.out.print( ",cr=" + stats.getBytesReadFromCache());
-					System.out.print( ",fw=" + stats.getBytesWrittenToFile());
-					System.out.print( ",fr=" + stats.getBytesReadFromFile());
-					
-	  			}
-	  			
-	  			System.out.println();
-				
-				if ( DEBUG_HANDOUT_SIZES ){
-					it = size_counts.entrySet().iterator();
-					
-					String	str = "";
-						
-					while( it.hasNext()){
-						
-						Map.Entry	entry = (Map.Entry)it.next();
-						
-						str += (str.length()==0?"":",") + entry.getKey() + "=" + entry.getValue();
-					}
-					
-					System.out.println( str );
-				}
-				
-				String str = "";
-				
-				for (int i=0;i<slice_entries.length;i++){
-				
-					boolean[]	allocs = slice_allocs[i];
-					int	alloc_count = 0;
-					for (int j=0;j<allocs.length;j++){
-						if( allocs[j]){
-							alloc_count++;
-						}
-					}
-					str += (i==0?"":",") + "["+SLICE_ENTRY_SIZES[i]+"]f=" +slice_entries[i].size()+",a=" + (alloc_count*SLICE_ENTRY_ALLOC_SIZES[i]) + ",u=" +slice_use_count[i];
-				}
-				
-				System.out.println( "slices: " + str );
-
-	  		}
-	  		
-	  		if(DEBUG_FREE_SIZES)
-	  		{
-	  			System.out.print("free block sizes: ");
-	  			
-	  			synchronized (poolsLock)
-				{
-					Iterator it = buffersMap.keySet().iterator();
-					while (it.hasNext())
-					{
-						Integer keyVal = (Integer) it.next();
-						ArrayList bufferPool = (ArrayList) buffersMap.get(keyVal);
-						
-						int blocksize = keyVal.intValue();
-						int blockfootprint = keyVal.intValue() * bufferPool.size();
-						if(blockfootprint == 0)
-							continue;
-						String blocksuffix = ""; 
-						if(blocksize > 1024) { blocksize /= 1024; blocksuffix = "k";}
-						if(blocksize > 1024) { blocksize /= 1024; blocksuffix = "M";}
-						String footsuffix = ""; 
-						if(blockfootprint > 1024) { blockfootprint /= 1024; footsuffix = "k";}
-						if(blockfootprint > 1024) { blockfootprint /= 1024; footsuffix = "M";}
-						
-						
-						System.out.print("["+ blocksize + blocksuffix + ":" + blockfootprint + footsuffix + "] ");
-					}
-				}
-	  			
-	  			System.out.println();
-	  		}
-	  		
-            long free_mem = Runtime.getRuntime().freeMemory() /1024/1024;
-            long max_mem = Runtime.getRuntime().maxMemory() /1024/1024;
-            long total_mem = Runtime.getRuntime().totalMemory() /1024/1024;
-            System.out.println("HEAP: max=" +max_mem+ "MB, total=" +total_mem+ "MB, free=" +free_mem+ "MB");
-            System.out.println();
-  		}
-  	}
-  	
-	
-		// Slice buffer management
-	
-  	private DirectByteBuffer
-	getSliceBuffer(
-		byte		_allocator,
-		int			_length )
-	{
-		int	slice_index = getSliceIndex( _length );
-		
-		List		my_slice_entries 	= slice_entries[slice_index];
-
-		synchronized( my_slice_entries ){
-	
-			boolean[]	my_allocs			= slice_allocs[slice_index];
-			
-			sliceBuffer	sb = null;
-			
-			if ( my_slice_entries.size() > 0 ){
-				
-				sb = (sliceBuffer)my_slice_entries.remove(0);
-				
-				slice_use_count[slice_index]++;
-				
-			}else{
-				
-					// find a free slot
-				
-				short	slot = -1;
-				
-				for (short i=0;i<my_allocs.length;i++){
-					
-					if( !my_allocs[i]){
-						
-						slot	= i;
-			
-						break;
-					}
-				}
-				
-				if ( slot != -1 ){
-					
-					short	slice_entry_size 	= SLICE_ENTRY_SIZES[slice_index];
-					short	slice_entry_count	= SLICE_ENTRY_ALLOC_SIZES[slice_index];
-					
-					ByteBuffer	chunk = ByteBuffer.allocateDirect(  slice_entry_size*slice_entry_count  );
-					
-					my_allocs[slot] = true;
-					
-					for (short i=0;i<slice_entry_count;i++){
-						
-						chunk.limit((i+1)*slice_entry_size);
-						chunk.position(i*slice_entry_size);
-						
-						ByteBuffer	slice = chunk.slice();
-						
-						sliceBuffer new_buffer = new sliceBuffer( slice, slot, i );
-						
-						if ( i == 0 ){
-							
-							sb = new_buffer;
-							
-							slice_use_count[slice_index]++;
-							
-						}else{
-							
-							my_slice_entries.add( new_buffer );
-						}
-					}
-				}else{
-					
-					if ( !slice_alloc_fails[slice_index] ){
-						
-						slice_alloc_fails[slice_index]	= true;
-						
-						Debug.out( "Run out of slice space for '" + SLICE_ENTRY_SIZES[slice_index] + ", reverting to normal allocation" );
-					}
-					
-					ByteBuffer buff = ByteBuffer.allocate( _length );
-					
-				    return( new DirectByteBuffer( _allocator, buff, this ));
-
-				}
-			}
-			
-			sliceDBB dbb = new sliceDBB( _allocator, sb );
-
-			return( dbb );
-		}
-	}
-	
-  	private void
-	freeSliceBuffer(
-		DirectByteBuffer	ddb )
-	{		
-		if ( ddb instanceof sliceDBB ){
-			
-			int	slice_index = getSliceIndex( ddb.getBufferInternal().capacity());
-
-			List		my_slice_entries 	= slice_entries[slice_index];
-
-			synchronized( my_slice_entries ){
-			
-				my_slice_entries.add( 0, ((sliceDBB)ddb).getSliceBuffer());
-			}
-		}
-	}
-	
-  	private void
-	compactSlices()
-	{
-			// we don't maintain the buffers in sorted order as this is too costly. however, we
-			// always allocate and free from the start of the free list, so unused buffer space
-			// will be at the end of the list. we periodically sort this list into allocate block
-			// order so that if an entire block isn't used for one compaction cycle all of
-			// its elements will end up together, if you see what I mean :P
-		
-			// when we find an entire block is unused then we just drop them from the list to
-			// permit them (and the underlying block) to be garbage collected
-		
-		for (int i=0;i<slice_entries.length;i++){
-			
-			int			entries_per_alloc 	= SLICE_ENTRY_ALLOC_SIZES[i];
-	
-			List	l = slice_entries[i];
-	
-				// no point in trying gc if not enough entries
-			
-			if ( l.size() >= entries_per_alloc ){
-			
-				synchronized( l ){
-					
-					Collections.sort( l,
-						new Comparator()
-						{
-							public int
-							compare(
-								Object	o1,
-								Object	o2 )
-							{
-								sliceBuffer	sb1 = (sliceBuffer)o1;
-								sliceBuffer	sb2 = (sliceBuffer)o2;
-								
-								int	res = sb1.getAllocID() - sb2.getAllocID();
-								
-								if ( res == 0 ){
-									
-									res = sb1.getSliceID() - sb2.getSliceID();
-								}
-								
-								return( res );
-							}
-						});
-			
-					boolean[]	allocs				= slice_allocs[i];
-			
-					Iterator	it = l.iterator();
-					
-					int	current_alloc 	= -1;
-					int entry_count		= 0;
-			
-					boolean	freed_one	= false;
-					
-					while( it.hasNext()){
-						
-						sliceBuffer	sb = (sliceBuffer)it.next();
-						
-						int	aid = sb.getAllocID();
-						
-						if ( aid != current_alloc ){
-							
-							if ( entry_count == entries_per_alloc ){
-								
-								// System.out.println( "CompactSlices[" + SLICE_ENTRY_SIZES[i]+"] freeing " + aid );
-								
-								freed_one	= true;
-								
-								allocs[aid]	= false;					
-							}
-							
-							current_alloc	= aid;
-							
-							entry_count		= 1;
-							
-						}else{
-							
-							entry_count++;
-						}
-					}
-					
-					if ( entry_count == entries_per_alloc ){
-						
-						// System.out.println( "CompactSlices[" + SLICE_ENTRY_SIZES[i]+"] freeing " + current_alloc );
-						
-						freed_one	= true;
-						
-						allocs[current_alloc]	= false;					
-					}
-					
-					if ( freed_one ){
-						
-						it = l.iterator();
-						
-						while( it.hasNext()){
-							
-							sliceBuffer	sb = (sliceBuffer)it.next();
-							
-							if ( !allocs[ sb.getAllocID()]){
-								
-								it.remove();
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-	
-  	private int
-	getSliceIndex( 
-		int	_length )
-	{
-		for (int i=0;i<SLICE_ENTRY_SIZES.length;i++){
-			
-			if ( _length <= SLICE_ENTRY_SIZES[i] ){
-				
-				return( i );
-			}
-		}
-		
-		Debug.out( "eh?");
-		
-		return( 0 );
-	}
-	
-  	private static class
-	sliceBuffer
-	{
-		private ByteBuffer	buffer;
-		private short		alloc_id;
-		private short		slice_id;
-		
-		protected
-		sliceBuffer(
-			ByteBuffer	_buffer,
-			short		_alloc_id,
-			short		_slice_id )
-		{
-			buffer		= _buffer;
-			alloc_id	= _alloc_id;
-			slice_id	= _slice_id;
-		}
-		
-		protected ByteBuffer
-		getBuffer()
-		{
-			return( buffer );
-		}
-		
-		protected short
-		getAllocID()
-		{
-			return( alloc_id );
-		}
-		
-		protected short
-		getSliceID()
-		{
-			return( slice_id );
-		}
-	}
-	
-  	private static class
-	sliceDBB
-		extends DirectByteBuffer
-	{
-		private sliceBuffer	slice_buffer;
-
-		protected
-		sliceDBB(
-			byte		_allocator,
-			sliceBuffer	_sb )
-		{	
-			super( _allocator, _sb.getBuffer(), pool );
-	
-			slice_buffer	= _sb;
-		}
-		
-		protected sliceBuffer
-		getSliceBuffer()
-		{
-			return( slice_buffer );
-		}
-	}
-	
-  	private static class
-	myInteger
-  	{
-  		int	value;
-  	}
-}
+/*
+ * Created on Nov 4, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.util;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.disk.DiskManager;
+import org.gudy.azureus2.core3.logging.LogAlert;
+import org.gudy.azureus2.core3.logging.Logger;
+
+import com.aelitis.azureus.core.diskmanager.cache.CacheFileManager;
+import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerFactory;
+import com.aelitis.azureus.core.diskmanager.cache.CacheFileManagerStats;
+
+public class 
+DirectByteBufferPoolReal 
+	extends DirectByteBufferPool
+{
+	private static final boolean disable_gc = System.getProperty( "az.disable.explicit.gc", "0" ).equals( "1" );
+	
+	static{
+	
+		if ( disable_gc ){
+	
+			System.out.println( "Explicit GC disabled" );
+		}
+	}
+	
+	protected static final boolean				DEBUG_TRACK_HANDEDOUT	= AEDiagnostics.TRACE_DBB_POOL_USAGE;
+	protected static final boolean				DEBUG_PRINT_MEM			= AEDiagnostics.PRINT_DBB_POOL_USAGE;
+	
+	protected static final int					DEBUG_PRINT_TIME		= 120 * 1000;
+	
+	protected static final boolean				DEBUG_HANDOUT_SIZES		= false;
+	protected static final boolean				DEBUG_FREE_SIZES		= false;
+	
+	
+	
+	
+	
+	  // There is no point in allocating buffers smaller than 4K,
+	  // as direct ByteBuffers are page-aligned to the underlying
+	  // system, which is 4096 byte pages under most OS's.
+	  // If we want to save memory, we can distribute smaller-than-4K
+	  // buffers by using the slice() method to break up a standard buffer
+	  // into smaller chunks, but that's more work.
+	
+	private static final int START_POWER = 12;    // 4096
+	private static final int END_POWER   = 25;    // 33554432
+  
+  		// without an extra bucket here we get lots of wastage with the file cache as typically
+  		// 16K data reads result in a buffer slightly bigger than 16K due to protocol header
+  		// This means we would bump up to 32K pool entries, hence wasting 16K per 16K entry
+  	
+	private static final int[]	EXTRA_BUCKETS = { DiskManager.BLOCK_SIZE + 128 };
+  
+  
+	public static final int MAX_SIZE = BigInteger.valueOf(2).pow(END_POWER).intValue();
+  
+	private static final DirectByteBufferPoolReal pool = new DirectByteBufferPoolReal();
+  
+
+	private final Map buffersMap = new LinkedHashMap(END_POWER - START_POWER + 1);
+  
+	private final Object poolsLock = new Object();
+
+	private static final int	SLICE_END_SIZE				= 2048;	
+	private static final int    SLICE_ALLOC_CHUNK_SIZE		= 4096;
+  
+
+	private static final short[]		SLICE_ENTRY_SIZES		= { 8, 16, 32, 64, 128, 256, 512, 1024, SLICE_END_SIZE };
+	private static final short[]		SLICE_ALLOC_MAXS		= { 256, 256, 128, 64, 64,  64,  64,  64,   64 };
+	
+	private static final short[]		SLICE_ENTRY_ALLOC_SIZES = new short[SLICE_ENTRY_SIZES.length];
+	private static final List[]			slice_entries 			= new List[SLICE_ENTRY_SIZES.length];
+	private static final boolean[][]	slice_allocs 			= new boolean[SLICE_ENTRY_SIZES.length][];
+	private static final boolean[]		slice_alloc_fails		= new boolean[SLICE_ENTRY_SIZES.length];
+	
+	static{
+		
+		int mult = COConfigurationManager.getIntParameter( "memory.slice.limit.multiplier" );
+		
+		if ( mult > 1 ){
+			
+			for (int i=0;i<SLICE_ALLOC_MAXS.length;i++){
+				
+				SLICE_ALLOC_MAXS[i] *= mult;
+			}
+		}
+		
+		for (int i=0;i<SLICE_ENTRY_SIZES.length;i++){
+			
+			SLICE_ENTRY_ALLOC_SIZES[i] = (short)(SLICE_ALLOC_CHUNK_SIZE/SLICE_ENTRY_SIZES[i]);
+					
+			slice_allocs[i] = new boolean[SLICE_ALLOC_MAXS[i]];
+			
+			slice_entries[i] = new LinkedList();
+		}
+	}
+	
+	private static final long[]			slice_use_count 	= new long[SLICE_ENTRY_SIZES.length];
+  
+	private final Map handed_out	= new IdentityHashMap();	// for debugging (ByteBuffer has .equals defined on contents, hence IdentityHashMap)
+	
+	private final Map	size_counts	= new TreeMap();
+ 
+	private static final long COMPACTION_CHECK_PERIOD = 2*60*1000; //2 min
+	private static final long MAX_FREE_BYTES = 10*1024*1024; //10 MB
+	private static final long MIN_FREE_BYTES = 1*1024*1024; // 1 MB
+  
+	private long bytesIn = 0;
+	private long bytesOut = 0;
+  
+  
+	protected 
+	DirectByteBufferPoolReal() 
+	{
+	    //create the buffer pool for each buffer size
+	  	
+	  	ArrayList	list = new ArrayList();
+	  	
+	    for (int p=START_POWER; p <= END_POWER; p++) {
+	    	
+	    	list.add( new Integer(BigInteger.valueOf(2).pow(p).intValue()));
+	    }
+	    
+	    for (int i=0;i<EXTRA_BUCKETS.length;i++){
+	    	       
+	        list.add( new Integer(EXTRA_BUCKETS[i]));
+	    }
+	    
+	    Integer[]	sizes = new Integer[ list.size() ];
+	    list.toArray( sizes );
+	    Arrays.sort( sizes);
+	    
+	    for (int i=0;i<sizes.length;i++){
+	    	
+	    	ArrayList bufferPool = new ArrayList();
+	    	
+	    	buffersMap.put(sizes[i], bufferPool);
+	    }
+	    
+	    //initiate periodic timer to check free memory usage
+	    SimpleTimer.addPeriodicEvent(
+	    	"DirectBB:compact",
+	        COMPACTION_CHECK_PERIOD,
+	        new TimerEventPerformer() {
+	          public void perform( TimerEvent ev ) {
+	       
+	            compactBuffers();
+	          }
+	        }
+	     );
+	    
+	    if( DEBUG_PRINT_MEM ) {
+	      Timer printer = new Timer("printer");
+	      printer.addPeriodicEvent(
+	          DEBUG_PRINT_TIME,
+	          new TimerEventPerformer() {
+	            public void perform( TimerEvent ev ) {
+	              printInUse( false );
+	            }
+	          }
+	      );
+	    }
+	}
+
+  
+  /**
+   * Allocate and return a new direct ByteBuffer.
+   */
+  private ByteBuffer allocateNewBuffer(final int _size) {
+    try {
+      return ByteBuffer.allocateDirect(_size);
+    }
+    catch (OutOfMemoryError e) {
+       //Debug.out("Running garbage collector...");
+       
+       clearBufferPools();
+       
+       runGarbageCollection();
+
+       try {
+       		return ByteBuffer.allocateDirect(_size);
+       	
+       }catch (OutOfMemoryError ex) {
+       	
+         String msg = "Memory allocation failed: Out of direct memory space.\n"
+                    + "To fix: Use the -XX:MaxDirectMemorySize=512m command line option,\n"
+                    + "or upgrade your Java JRE to version 1.4.2_05 or 1.5 series or newer.";
+       	 Debug.out( msg );
+       	 
+       	 Logger.log(new LogAlert(LogAlert.UNREPEATABLE, LogAlert.AT_ERROR, msg));
+         
+         printInUse( true );
+         
+         throw( ex );
+       }
+    }
+  }
+
+  
+  /**
+   * Retrieve a buffer from the buffer pool of size at least
+   * <b>length</b>, and no larger than <b>DirectByteBufferPool.MAX_SIZE</b>
+   */
+  protected DirectByteBuffer 
+  getBufferSupport(
+  	byte	_allocator,
+  	int 	_length) 
+  {
+    if (_length < 1) {
+        Debug.out("requested length [" +_length+ "] < 1");
+        return null;
+    }
+
+    if (_length > MAX_SIZE) {
+        Debug.out("requested length [" +_length+ "] > MAX_SIZE [" +MAX_SIZE+ "]");
+        return null;
+    }
+    
+    return pool.getBufferHelper(_allocator,_length);
+  }
+  
+  
+  /**
+   * Retrieve an appropriate buffer from the free pool, or
+   * create a new one if the pool is empty.
+   */
+  
+  
+  	private DirectByteBuffer 
+  	getBufferHelper(
+		byte	_allocator,
+		int 	_length) 
+	{
+		DirectByteBuffer	res;
+		
+		if ( _length <= SLICE_END_SIZE ){
+
+			res = getSliceBuffer( _allocator, _length );
+			
+		}else{
+				
+			ByteBuffer	buff = null;
+			
+			Integer reqVal = new Integer(_length);
+	    
+				//loop through the buffer pools to find a buffer big enough
+	    
+			Iterator it = buffersMap.keySet().iterator();
+	    
+			while (it.hasNext()) {
+	    	
+				Integer keyVal = (Integer)it.next();
+	
+					//	check if the buffers in this pool are big enough
+	      
+				if ( reqVal.compareTo(keyVal) <= 0 ){
+	      	
+					ArrayList bufferPool = (ArrayList)buffersMap.get(keyVal);
+	        
+					while( true ){
+						
+						synchronized ( poolsLock ) { 
+		        
+							// make sure we don't remove a buffer when running compaction
+							// if there are no free buffers in the pool, create a new one.
+							// otherwise use one from the pool
+		        	
+							if ( bufferPool.isEmpty()){
+		          	
+								buff = allocateNewBuffer(keyVal.intValue());
+		            
+								if ( buff == null ){
+									
+									Debug.out( "allocateNewBuffer for " + _length + " returned null" );
+								}
+								
+								break;
+								
+							}else{
+		          	
+								synchronized ( bufferPool ) {
+		            	
+									buff = (ByteBuffer)bufferPool.remove(bufferPool.size() - 1);
+								}
+								
+								if ( buff == null ){
+									
+									Debug.out( "buffer pool for " + _length + " contained null entry" ); 
+									
+								}else{
+									
+									break;
+								}
+							}
+						}
+					}
+					
+					break;
+				}
+			}
+		
+			if ( buff == null ){
+					
+				String str = "Unable to find an appropriate buffer pool for " + _length;
+				
+			    Debug.out( str );
+			    
+			    throw( new RuntimeException( str ));
+			}
+			
+			res = new DirectByteBuffer( _allocator, buff, this );		   
+		}
+			
+        	// clear doesn't actually zero the data, it just sets pos to 0 etc.
+        
+		ByteBuffer buff = res.getBufferInternal();
+		
+        buff.clear();   //scrub the buffer
+        
+		buff.limit( _length );
+		
+        bytesOut += buff.capacity();
+                                
+        if ( DEBUG_PRINT_MEM || DEBUG_TRACK_HANDEDOUT ){
+        	
+        	synchronized( handed_out ){
+        	        	
+				if ( DEBUG_HANDOUT_SIZES ){
+					
+					int	trim_size;
+					
+					if ( _length < 32 ){
+						
+						trim_size = 4;
+					}else{
+						
+						trim_size = 16;
+					}
+					
+					int	trim = ((_length+trim_size-1)/trim_size)*trim_size;
+					
+					Long count = (Long)size_counts.get(new Integer(trim));
+					
+					if ( count == null ){
+						
+						size_counts.put( new Integer( trim ), new Long(1));
+						
+					}else{
+						
+						size_counts.put( new Integer( trim), new Long( count.longValue() + 1 ));
+					}
+				}
+				
+        		if ( handed_out.put( buff, res ) != null ){
+          		
+        			Debug.out( "buffer handed out twice!!!!");
+          		
+        			throw( new RuntimeException( "Buffer handed out twice" ));
+        		}
+        	
+				//System.out.println( "[" + handed_out.size() + "] -> " + buff + ", bytesIn = " + bytesIn + ", bytesOut = " + bytesOut );
+          	}
+        }
+        
+        // addInUse( dbb.capacity() );
+        
+        return( res );
+    }
+  
+  
+	  /**
+	   * Return the given buffer to the appropriate pool.
+	   */
+	
+	protected void 
+	returnBufferSupport(
+		DirectByteBuffer ddb ) 
+	{		
+		ByteBuffer	buff = ddb.getBufferInternal();
+		
+		if ( buff == null ){
+			
+			Debug.out( "Returned dbb has null delegate" );
+			
+			throw( new RuntimeException( "Returned dbb has null delegate" ));
+		}
+		
+		int	capacity = buff.capacity();
+
+		bytesIn += capacity;
+		    
+	  	if ( DEBUG_TRACK_HANDEDOUT ){
+	  		
+	  		synchronized( handed_out ){
+
+	  			if ( handed_out.remove( buff ) == null ){
+	  				
+	  				Debug.out( "buffer not handed out" );
+	  				
+	  				throw( new RuntimeException( "Buffer not handed out" ));
+	  			}
+	  			
+	       		// System.out.println( "[" + handed_out.size() + "] <- " + buffer + ", bytesIn = " + bytesIn + ", bytesOut = " + bytesOut );
+	  		}
+	  	}
+	  	
+	    // remInUse( buffer.capacity() );
+		
+		if ( capacity <= SLICE_END_SIZE ){
+			
+			freeSliceBuffer( ddb );
+			
+		}else{
+		    Integer buffSize = new Integer(capacity);
+		    
+		    ArrayList bufferPool = (ArrayList)buffersMap.get(buffSize);
+		    
+		    if (bufferPool != null) {
+				
+				//no need to sync around 'poolsLock', as adding during compaction is ok
+				
+		      synchronized ( bufferPool ){
+				  
+		        bufferPool.add(buff);
+		      }
+		    }else{
+				
+		      Debug.out("Invalid buffer given; could not find proper buffer pool");
+		    }
+		}
+	}
+  
+  
+  /**
+   * Clears the free buffer pools so that currently
+   * unused buffers can be garbage collected.
+   */
+  private void clearBufferPools() {
+    Iterator it = buffersMap.values().iterator();
+    while (it.hasNext()) {
+        ArrayList bufferPool = (ArrayList)it.next();
+        bufferPool.clear();
+    }
+  }
+  
+  
+  /**
+   * Force system garbage collection.
+   */
+  private void runGarbageCollection() {
+	if ( !disable_gc ){
+	    if( DEBUG_PRINT_MEM ) {
+	      System.out.println( "runGarbageCollection()" );
+	    }
+	    System.runFinalization();
+	    System.gc();
+	}
+  }
+  
+  
+  /**
+   * Checks memory usage of free buffers in buffer pools,
+   * and calls the compaction method if necessary.
+   */
+  private void compactBuffers() {
+	  
+	  nonsliecd: synchronized (poolsLock)
+		{
+			long freeSize = bytesFree();
+			
+			if (freeSize < MIN_FREE_BYTES)
+				break nonsliecd;
+			
+			// apply cleanup pressure based on filling degree
+			float remainingFactor;
+			if (freeSize > MAX_FREE_BYTES) // downsize to 50% of the limit (not the current capacity!) if we're overlimit 
+				remainingFactor = 0.5f * MAX_FREE_BYTES / (float) freeSize;
+			else // reduce to something between 50% (full: maximum reduction) and 100% (empty: no reduction)  
+				remainingFactor = 1.0f - 0.5f * freeSize / (float) MAX_FREE_BYTES;
+			
+			if (DEBUG_PRINT_MEM)
+				System.out.println("Performing cleanup, reducing to " + remainingFactor * 100 + "%");
+			
+			ArrayList pools = new ArrayList(buffersMap.values());
+			for (int i = pools.size() - 1; i >= 0; i--)
+			{
+				ArrayList pool = (ArrayList) pools.get(i);
+				int limit = (int) (pool.size() * remainingFactor); // floor(), this way we can reach 0 at some point
+				for (int j = pool.size() - 1; j >= limit; j--)
+					pool.remove(j);
+			}
+			
+			runGarbageCollection();
+			
+			if (DEBUG_PRINT_MEM)
+			{
+				printInUse(false);
+				System.out.println("Cleanup done\n");
+			}
+		}
+  
+		compactSlices();
+	}
+ 
+  
+  
+  private long bytesFree() {
+    long bytesUsed = 0;
+    synchronized( poolsLock ) {
+      //count up total bytes used by free buffers
+      Iterator it = buffersMap.keySet().iterator();
+      while (it.hasNext()) {
+        Integer keyVal = (Integer)it.next();
+        ArrayList bufferPool = (ArrayList)buffersMap.get(keyVal);
+      
+        bytesUsed += keyVal.intValue() * bufferPool.size();
+      }
+    }
+    return bytesUsed;
+  }
+  
+  
+  /*
+  private final HashMap in_use_counts = new HashMap();
+  
+  private void addInUse( int size ) {
+    Integer key = new Integer( size );
+    synchronized( in_use_counts ) {
+      Integer count = (Integer)in_use_counts.get( key );
+      if( count == null )  count = new Integer( 1 );
+      else  count = new Integer( count.intValue() + 1 );
+      in_use_counts.put( key, count );
+    }
+  }
+  
+  private void remInUse( int size ) {
+    Integer key = new Integer( size );
+    synchronized( in_use_counts ) {
+      Integer count = (Integer)in_use_counts.get( key );
+      if( count == null ) System.out.println("count = null");
+      if( count.intValue() == 0 ) System.out.println("count = 0");
+      in_use_counts.put( key, new Integer( count.intValue() - 1 ) );
+    }
+  }
+  
+  private void printInUse() {
+    synchronized( in_use_counts ) {
+      for( Iterator i = in_use_counts.keySet().iterator(); i.hasNext(); ) {
+        Integer key = (Integer)i.next();
+        int count = ((Integer)in_use_counts.get( key )).intValue();
+        int size = key.intValue();
+        if( count > 0 ) {
+          if( size < 1024 )  System.out.print("[" +size+ " x " +count+ "] ");
+          else  System.out.print("[" +size/1024+ "K x " +count+ "] ");
+        }
+      }
+      System.out.println();
+    }
+  }
+  */
+  
+  	private void
+	printInUse(
+		boolean		verbose )
+  	{
+  		if ( DEBUG_PRINT_MEM ){
+  			
+            System.out.print("DIRECT: given=" +bytesOut/1024/1024+ "MB, returned=" +bytesIn/1024/1024+ "MB, ");
+            
+            long in_use = bytesOut - bytesIn;
+            if( in_use < 1024*1024 ) System.out.print( "in use=" +in_use+ "B, " );
+            else System.out.print( "in use=" +in_use/1024/1024+ "MB, " );
+            
+            long free = bytesFree();
+            if( free < 1024*1024 ) System.out.print( "free=" +free+ "B" );
+            else System.out.print( "free=" +free/1024/1024+ "MB" );
+
+  			System.out.println();
+  			
+	  		CacheFileManager cm	= null;
+	  		
+			try{
+	 			cm = CacheFileManagerFactory.getSingleton();
+	 			
+			}catch( Throwable e ){
+					
+				Debug.printStackTrace( e );
+			}
+	 
+	  		synchronized( handed_out ){
+	    	
+	  			Iterator	it = handed_out.values().iterator();
+	  			
+	  			Map	cap_map		= new TreeMap();
+	  			Map	alloc_map	= new TreeMap();
+	  			
+	  			while( it.hasNext()){
+	  				
+	  				DirectByteBuffer	db = (DirectByteBuffer)it.next();
+	  				
+	  				if ( verbose ){
+		  				String	trace = db.getTraceString();
+		  				
+		  				if ( trace != null ){
+		  					
+		  					System.out.println( trace );
+		  				}
+	  				}
+	  				
+	  				Integer cap 	= new Integer( db.getBufferInternal().capacity());
+	  				Byte	alloc 	= new Byte( db.getAllocator());
+	  				
+	  				myInteger	c = (myInteger)cap_map.get(cap);
+	  				
+	  				if ( c == null ){
+	  					
+	  					c	= new myInteger();
+	  					
+	  					cap_map.put( cap, c );
+	  				}
+	  				
+	  				c.value++;
+	  				
+					myInteger	a = (myInteger)alloc_map.get(alloc);
+	  				
+	  				if ( a == null ){
+	  					
+	  					a	= new myInteger();
+	  					
+	  					alloc_map.put( alloc, a );
+	  				}
+	  				
+	  				a.value++;				
+	  			}
+	  			
+	  			it = cap_map.keySet().iterator();
+	  			
+	  			while( it.hasNext()){
+	  				
+	  				Integer		key 	= (Integer)it.next();
+	  				myInteger	count 	= (myInteger)cap_map.get( key );
+	  				
+	  		        if( key.intValue() < 1024 ){
+	  		        	
+	  		        	System.out.print("[" +key.intValue()+ " x " +count.value+ "] ");
+	  		        	
+	  		        }else{  
+	  		        	
+	  		        	System.out.print("[" +key.intValue()/1024+ "K x " +count.value+ "] ");
+	  		        }
+	  			}
+	  			
+	  			System.out.println();
+	  			
+				it = alloc_map.keySet().iterator();
+	  			
+	  			while( it.hasNext()){
+	  				
+	  				Byte		key 	= (Byte)it.next();
+	  				myInteger	count 	= (myInteger)alloc_map.get( key );
+	  				
+	  	        	System.out.print("[" + DirectByteBuffer.AL_DESCS[key.intValue()]+ " x " +count.value+ "] ");
+	  			}
+	  			
+	  			if ( cm != null ){
+	  				
+	  				CacheFileManagerStats stats = cm.getStats();
+	  				
+	  				System.out.print( " - Cache: " );
+	  	  			
+	  				
+					System.out.print( "sz=" + stats.getSize());
+					System.out.print( ",us=" + stats.getUsedSize());
+					System.out.print( ",cw=" + stats.getBytesWrittenToCache());
+					System.out.print( ",cr=" + stats.getBytesReadFromCache());
+					System.out.print( ",fw=" + stats.getBytesWrittenToFile());
+					System.out.print( ",fr=" + stats.getBytesReadFromFile());
+					
+	  			}
+	  			
+	  			System.out.println();
+				
+				if ( DEBUG_HANDOUT_SIZES ){
+					it = size_counts.entrySet().iterator();
+					
+					String	str = "";
+						
+					while( it.hasNext()){
+						
+						Map.Entry	entry = (Map.Entry)it.next();
+						
+						str += (str.length()==0?"":",") + entry.getKey() + "=" + entry.getValue();
+					}
+					
+					System.out.println( str );
+				}
+				
+				String str = "";
+				
+				for (int i=0;i<slice_entries.length;i++){
+				
+					boolean[]	allocs = slice_allocs[i];
+					int	alloc_count = 0;
+					for (int j=0;j<allocs.length;j++){
+						if( allocs[j]){
+							alloc_count++;
+						}
+					}
+					str += (i==0?"":",") + "["+SLICE_ENTRY_SIZES[i]+"]f=" +slice_entries[i].size()+",a=" + (alloc_count*SLICE_ENTRY_ALLOC_SIZES[i]) + ",u=" +slice_use_count[i];
+				}
+				
+				System.out.println( "slices: " + str );
+
+	  		}
+	  		
+	  		if(DEBUG_FREE_SIZES)
+	  		{
+	  			System.out.print("free block sizes: ");
+	  			
+	  			synchronized (poolsLock)
+				{
+					Iterator it = buffersMap.keySet().iterator();
+					while (it.hasNext())
+					{
+						Integer keyVal = (Integer) it.next();
+						ArrayList bufferPool = (ArrayList) buffersMap.get(keyVal);
+						
+						int blocksize = keyVal.intValue();
+						int blockfootprint = keyVal.intValue() * bufferPool.size();
+						if(blockfootprint == 0)
+							continue;
+						String blocksuffix = ""; 
+						if(blocksize > 1024) { blocksize /= 1024; blocksuffix = "k";}
+						if(blocksize > 1024) { blocksize /= 1024; blocksuffix = "M";}
+						String footsuffix = ""; 
+						if(blockfootprint > 1024) { blockfootprint /= 1024; footsuffix = "k";}
+						if(blockfootprint > 1024) { blockfootprint /= 1024; footsuffix = "M";}
+						
+						
+						System.out.print("["+ blocksize + blocksuffix + ":" + blockfootprint + footsuffix + "] ");
+					}
+				}
+	  			
+	  			System.out.println();
+	  		}
+	  		
+            long free_mem = Runtime.getRuntime().freeMemory() /1024/1024;
+            long max_mem = Runtime.getRuntime().maxMemory() /1024/1024;
+            long total_mem = Runtime.getRuntime().totalMemory() /1024/1024;
+            System.out.println("HEAP: max=" +max_mem+ "MB, total=" +total_mem+ "MB, free=" +free_mem+ "MB");
+            System.out.println();
+  		}
+  	}
+  	
+	
+		// Slice buffer management
+	
+  	private DirectByteBuffer
+	getSliceBuffer(
+		byte		_allocator,
+		int			_length )
+	{
+		int	slice_index = getSliceIndex( _length );
+		
+		List		my_slice_entries 	= slice_entries[slice_index];
+
+		synchronized( my_slice_entries ){
+	
+			boolean[]	my_allocs			= slice_allocs[slice_index];
+			
+			sliceBuffer	sb = null;
+			
+			if ( my_slice_entries.size() > 0 ){
+				
+				sb = (sliceBuffer)my_slice_entries.remove(0);
+				
+				slice_use_count[slice_index]++;
+				
+			}else{
+				
+					// find a free slot
+				
+				short	slot = -1;
+				
+				for (short i=0;i<my_allocs.length;i++){
+					
+					if( !my_allocs[i]){
+						
+						slot	= i;
+			
+						break;
+					}
+				}
+				
+				if ( slot != -1 ){
+					
+					short	slice_entry_size 	= SLICE_ENTRY_SIZES[slice_index];
+					short	slice_entry_count	= SLICE_ENTRY_ALLOC_SIZES[slice_index];
+					
+					ByteBuffer	chunk = ByteBuffer.allocateDirect(  slice_entry_size*slice_entry_count  );
+					
+					my_allocs[slot] = true;
+					
+					for (short i=0;i<slice_entry_count;i++){
+						
+						chunk.limit((i+1)*slice_entry_size);
+						chunk.position(i*slice_entry_size);
+						
+						ByteBuffer	slice = chunk.slice();
+						
+						sliceBuffer new_buffer = new sliceBuffer( slice, slot, i );
+						
+						if ( i == 0 ){
+							
+							sb = new_buffer;
+							
+							slice_use_count[slice_index]++;
+							
+						}else{
+							
+							my_slice_entries.add( new_buffer );
+						}
+					}
+				}else{
+					
+					if ( !slice_alloc_fails[slice_index] ){
+						
+						slice_alloc_fails[slice_index]	= true;
+						
+						Debug.out( "Run out of slice space for '" + SLICE_ENTRY_SIZES[slice_index] + ", reverting to normal allocation" );
+					}
+					
+					ByteBuffer buff = ByteBuffer.allocate( _length );
+					
+				    return( new DirectByteBuffer( _allocator, buff, this ));
+
+				}
+			}
+			
+			sliceDBB dbb = new sliceDBB( _allocator, sb );
+
+			return( dbb );
+		}
+	}
+	
+  	private void
+	freeSliceBuffer(
+		DirectByteBuffer	ddb )
+	{		
+		if ( ddb instanceof sliceDBB ){
+			
+			int	slice_index = getSliceIndex( ddb.getBufferInternal().capacity());
+
+			List		my_slice_entries 	= slice_entries[slice_index];
+
+			synchronized( my_slice_entries ){
+			
+				my_slice_entries.add( 0, ((sliceDBB)ddb).getSliceBuffer());
+			}
+		}
+	}
+	
+  	private void
+	compactSlices()
+	{
+			// we don't maintain the buffers in sorted order as this is too costly. however, we
+			// always allocate and free from the start of the free list, so unused buffer space
+			// will be at the end of the list. we periodically sort this list into allocate block
+			// order so that if an entire block isn't used for one compaction cycle all of
+			// its elements will end up together, if you see what I mean :P
+		
+			// when we find an entire block is unused then we just drop them from the list to
+			// permit them (and the underlying block) to be garbage collected
+		
+		for (int i=0;i<slice_entries.length;i++){
+			
+			int			entries_per_alloc 	= SLICE_ENTRY_ALLOC_SIZES[i];
+	
+			List	l = slice_entries[i];
+	
+				// no point in trying gc if not enough entries
+			
+			if ( l.size() >= entries_per_alloc ){
+			
+				synchronized( l ){
+					
+					Collections.sort( l,
+						new Comparator()
+						{
+							public int
+							compare(
+								Object	o1,
+								Object	o2 )
+							{
+								sliceBuffer	sb1 = (sliceBuffer)o1;
+								sliceBuffer	sb2 = (sliceBuffer)o2;
+								
+								int	res = sb1.getAllocID() - sb2.getAllocID();
+								
+								if ( res == 0 ){
+									
+									res = sb1.getSliceID() - sb2.getSliceID();
+								}
+								
+								return( res );
+							}
+						});
+			
+					boolean[]	allocs				= slice_allocs[i];
+			
+					Iterator	it = l.iterator();
+					
+					int	current_alloc 	= -1;
+					int entry_count		= 0;
+			
+					boolean	freed_one	= false;
+					
+					while( it.hasNext()){
+						
+						sliceBuffer	sb = (sliceBuffer)it.next();
+						
+						int	aid = sb.getAllocID();
+						
+						if ( aid != current_alloc ){
+							
+							if ( entry_count == entries_per_alloc ){
+								
+								// System.out.println( "CompactSlices[" + SLICE_ENTRY_SIZES[i]+"] freeing " + aid );
+								
+								freed_one	= true;
+								
+								allocs[aid]	= false;					
+							}
+							
+							current_alloc	= aid;
+							
+							entry_count		= 1;
+							
+						}else{
+							
+							entry_count++;
+						}
+					}
+					
+					if ( entry_count == entries_per_alloc ){
+						
+						// System.out.println( "CompactSlices[" + SLICE_ENTRY_SIZES[i]+"] freeing " + current_alloc );
+						
+						freed_one	= true;
+						
+						allocs[current_alloc]	= false;					
+					}
+					
+					if ( freed_one ){
+						
+						it = l.iterator();
+						
+						while( it.hasNext()){
+							
+							sliceBuffer	sb = (sliceBuffer)it.next();
+							
+							if ( !allocs[ sb.getAllocID()]){
+								
+								it.remove();
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	
+  	private int
+	getSliceIndex( 
+		int	_length )
+	{
+		for (int i=0;i<SLICE_ENTRY_SIZES.length;i++){
+			
+			if ( _length <= SLICE_ENTRY_SIZES[i] ){
+				
+				return( i );
+			}
+		}
+		
+		Debug.out( "eh?");
+		
+		return( 0 );
+	}
+	
+  	private static class
+	sliceBuffer
+	{
+		private ByteBuffer	buffer;
+		private short		alloc_id;
+		private short		slice_id;
+		
+		protected
+		sliceBuffer(
+			ByteBuffer	_buffer,
+			short		_alloc_id,
+			short		_slice_id )
+		{
+			buffer		= _buffer;
+			alloc_id	= _alloc_id;
+			slice_id	= _slice_id;
+		}
+		
+		protected ByteBuffer
+		getBuffer()
+		{
+			return( buffer );
+		}
+		
+		protected short
+		getAllocID()
+		{
+			return( alloc_id );
+		}
+		
+		protected short
+		getSliceID()
+		{
+			return( slice_id );
+		}
+	}
+	
+  	private static class
+	sliceDBB
+		extends DirectByteBuffer
+	{
+		private sliceBuffer	slice_buffer;
+
+		protected
+		sliceDBB(
+			byte		_allocator,
+			sliceBuffer	_sb )
+		{	
+			super( _allocator, _sb.getBuffer(), pool );
+	
+			slice_buffer	= _sb;
+		}
+		
+		protected sliceBuffer
+		getSliceBuffer()
+		{
+			return( slice_buffer );
+		}
+	}
+	
+  	private static class
+	myInteger
+  	{
+  		int	value;
+  	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/DisplayFormatters.java b/azureus2/src/org/gudy/azureus2/core3/util/DisplayFormatters.java
index 90819f0..e3faa74 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/DisplayFormatters.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/DisplayFormatters.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ED2KHasher.java b/azureus2/src/org/gudy/azureus2/core3/util/ED2KHasher.java
index 03f82fd..a460238 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ED2KHasher.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ED2KHasher.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/FileIsADirectoryException.java b/azureus2/src/org/gudy/azureus2/core3/util/FileIsADirectoryException.java
index 93122fd..139bb35 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/FileIsADirectoryException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/FileIsADirectoryException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09.11.2003
  *
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/FileUtil.java b/azureus2/src/org/gudy/azureus2/core3/util/FileUtil.java
index db5d323..00d8ed2 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/FileUtil.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/FileUtil.java
@@ -1,7 +1,7 @@
  /*
  * Created on Oct 10, 2003
  * Modified Apr 14, 2004 by Alon Rohter
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  * 
  */
 
@@ -30,6 +27,7 @@ import java.net.URL;
 import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.zip.GZIPInputStream;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.logging.LogEvent;
@@ -576,6 +574,10 @@ public class FileUtil {
  				( use_backups && new File( parent_dir, name + ".bak" ).exists()));
   	}
   
+	/**
+	 * 
+ 	 * @return Map read from config file, or empty HashMap if error
+	 */
 	public static Map
 	readResilientConfigFile(
 		String		file_name )
@@ -587,6 +589,10 @@ public class FileUtil {
  		return( readResilientFile( parent_dir, file_name, use_backups ));
 	}
 	
+	/**
+	 * 
+ 	 * @return Map read from config file, or empty HashMap if error
+	 */
 	public static Map
 	readResilientConfigFile(
 		String		file_name,
@@ -609,6 +615,10 @@ public class FileUtil {
  		return( readResilientFile( parent_dir, file_name, use_backups ));
 	}
 	
+	/**
+	 * 
+ 	 * @return Map read from config file, or empty HashMap if error
+	 */
 	public static Map
 	readResilientFile(
 		File		file )
@@ -616,6 +626,10 @@ public class FileUtil {
 		return( readResilientFile( file.getParentFile(),file.getName(),false, true));
 	}
 	
+	/**
+	 * 
+ 	 * @return Map read from config file, or empty HashMap if error
+	 */
  	public static Map
 	readResilientFile(
 		File		parent_dir,
@@ -625,6 +639,15 @@ public class FileUtil {
  		return readResilientFile(parent_dir, file_name, use_backup, true);
  	}
  	
+ 	/**
+ 	 * 
+ 	 * @param parent_dir
+ 	 * @param file_name
+ 	 * @param use_backup
+ 	 * @param intern_keys
+ 	 * 
+ 	 * @return Map read from config file, or empty HashMap if error
+ 	 */
  	public static Map
 	readResilientFile(
 		File		parent_dir,
@@ -1197,10 +1220,10 @@ public class FileUtil {
     		
     		if ( !(is instanceof BufferedInputStream )){
     			
-    			is = new BufferedInputStream(is);
+    			is = new BufferedInputStream(is,128*1024);
     		}
     		
-    		byte[]	buffer = new byte[65536*2];
+    		byte[]	buffer = new byte[128*1024];
 			
     		while(true){
     			
@@ -1843,6 +1866,12 @@ public class FileUtil {
 		return f.mkdirs();
 	}
 	
+	/**
+	 * Gets the extension of a file name, ensuring we don't go into the path
+	 * 
+	 * @param fName  File name
+	 * @return extension, with the '.'
+	 */
 	public static String getExtension(String fName) {
 		final int fileSepIndex = fName.lastIndexOf(File.separator);
 		final int fileDotIndex = fName.lastIndexOf('.');
@@ -1888,6 +1917,24 @@ public class FileUtil {
 	}
 		
 	public static String
+	readGZippedFileAsString(
+		File	file,
+		int		size_limit )
+	
+		throws IOException
+	{
+		FileInputStream fis = new FileInputStream(file);
+				
+		try {
+			GZIPInputStream zis = new GZIPInputStream( fis );
+
+			return readInputStreamAsString(zis, size_limit);
+		} finally {
+
+			fis.close();
+		}
+	}
+	public static String
 	readInputStreamAsString(
 		InputStream is,
 		int		size_limit )
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/FrequencyLimitedDispatcher.java b/azureus2/src/org/gudy/azureus2/core3/util/FrequencyLimitedDispatcher.java
index 53f8762..effa840 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/FrequencyLimitedDispatcher.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/FrequencyLimitedDispatcher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 9 Aug 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/HashWrapper.java b/azureus2/src/org/gudy/azureus2/core3/util/HashWrapper.java
index 5f05fc2..51d7384 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/HashWrapper.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/HashWrapper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22 juil. 2003
  *
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/HashWrapper2.java b/azureus2/src/org/gudy/azureus2/core3/util/HashWrapper2.java
index 497ba17..ec07799 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/HashWrapper2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/HashWrapper2.java
@@ -1,109 +1,126 @@
-/*
- * Created on May 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 org.gudy.azureus2.core3.util;
-
-
-/**
- * This class DOES NOT COPY THE UNDERLYING BYTES AND ONLY SUPPORTS Short.MAX_VALUE bytes
- * @author Azureus
- *
- */
-
-public class 
-HashWrapper2 
-{
-	final private byte[] 	hash;
-	final private short		offset;
-	final private short		length;
-	final private int		hash_code;
-
-	public 
-	HashWrapper2(
-		byte[] hash ) 
-	{
-		this( hash, 0, hash.length );
-	}
-
-	public 
-	HashWrapper2(
-		byte[] 	_hash, 
-		int 	_offset,
-		int 	_length ) 
-	{
-		if ( _offset >= Short.MAX_VALUE ){
-			throw( new RuntimeException( "Illegal value - offset too large" ));
-		}
-		
-		if ( _length >= Short.MAX_VALUE ){
-			throw( new RuntimeException( "Illegal value - length too large" ));
-		}
-
-		hash	= _hash;
-		offset	= (short)_offset;
-		length	= (short)_length;
-		
-		int	hc = 0;
-		
-		for (int i=offset; i<offset+length; i++) {
-
-			hc = 31*hc + hash[i];
-		}
-		
-		hash_code = hc;
-	}
-
-	public final boolean 
-	equals(
-		Object o) 
-	{
-		if( !( o instanceof HashWrapper2 )){
-			
-			return false;
-		}
-		
-		HashWrapper2 other = (HashWrapper2)o;
-		
-		if ( other.length != length ){
-			
-			return( false );
-		}
-		
-		byte[]	other_hash 		= other.hash;
-		int		other_offset	= other.offset;
-		
-		for ( int i=0;i<length;i++){
-			
-			if ( hash[offset+i] != other_hash[other_offset+i] ){
-				
-				return( false );
-			}
-		}
-		
-		return( true );
-	}
-
-	public int	 
-	hashCode() 
-	{
-		return( hash_code );
-	}
-}
+/*
+ * Created on May 27, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.util;
+
+
+/**
+ * This class DOES NOT COPY THE UNDERLYING BYTES AND ONLY SUPPORTS Short.MAX_VALUE bytes
+ * @author Azureus
+ *
+ */
+
+public class 
+HashWrapper2 
+{
+	final private byte[] 	hash;
+	final private short		offset;
+	final private short		length;
+	final private int		hash_code;
+
+	public 
+	HashWrapper2(
+		byte[] hash ) 
+	{
+		this( hash, 0, hash.length );
+	}
+
+	public 
+	HashWrapper2(
+		byte[] 	_hash, 
+		int 	_offset,
+		int 	_length ) 
+	{
+		if ( _offset >= Short.MAX_VALUE ){
+			throw( new RuntimeException( "Illegal value - offset too large" ));
+		}
+		
+		if ( _length >= Short.MAX_VALUE ){
+			throw( new RuntimeException( "Illegal value - length too large" ));
+		}
+
+		hash	= _hash;
+		offset	= (short)_offset;
+		length	= (short)_length;
+		
+		int	hc = 0;
+		
+		for (int i=offset; i<offset+length; i++) {
+
+			hc = 31*hc + hash[i];
+		}
+		
+		hash_code = hc;
+	}
+
+	public byte[]
+	getBytes()
+	{
+		return( hash );
+	}
+	
+	public short
+	getOffset()
+	{
+		return( offset );
+	}
+	
+	public short
+	getLength()
+	{
+		return( length );
+	}
+	
+	public final boolean 
+	equals(
+		Object o) 
+	{
+		if( !( o instanceof HashWrapper2 )){
+			
+			return false;
+		}
+		
+		HashWrapper2 other = (HashWrapper2)o;
+		
+		if ( other.length != length ){
+			
+			return( false );
+		}
+		
+		byte[]	other_hash 		= other.hash;
+		int		other_offset	= other.offset;
+		
+		for ( int i=0;i<length;i++){
+			
+			if ( hash[offset+i] != other_hash[other_offset+i] ){
+				
+				return( false );
+			}
+		}
+		
+		return( true );
+	}
+
+	public int	 
+	hashCode() 
+	{
+		return( hash_code );
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolver.java b/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolver.java
index b0289d9..f3cc8f1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolver.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -43,7 +40,12 @@ HostNameToIPResolver
 
 	static protected AESemaphore	request_semaphore	= new AESemaphore("HostNameToIPResolver");
 	
-
+	public static boolean
+	isDNSName(
+		String	host )
+	{
+		return( AENetworkClassifier.categoriseAddress( host ) == AENetworkClassifier.AT_PUBLIC );
+	}
 	
 	public static boolean
 	isNonDNSName(
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolverException.java b/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolverException.java
index 58077f4..d053b43 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolverException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolverException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolverListener.java b/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolverListener.java
index c3c6f04..f8c3e88 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolverListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/HostNameToIPResolverListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolver.java b/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolver.java
index a5ae8e4..b645904 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolver.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -92,15 +89,23 @@ IPToHostNameResolver
 									
 									if ( listener != null ){
 										
-										try{
-											InetAddress addr = InetAddress.getByName( req.getIP());
+										String ip = req.getIP();
+										
+										if ( AENetworkClassifier.categoriseAddress( ip ) == AENetworkClassifier.AT_PUBLIC ){
+											
+											try{
+												InetAddress addr = InetAddress.getByName( ip );
+													
+												req.getListener().IPResolutionComplete( addr.getHostName(), true );
+													
+											}catch( Throwable e ){
 												
-											req.getListener().IPResolutionComplete( addr.getHostName(), true );
+												req.getListener().IPResolutionComplete( ip, false );
 												
-										}catch( Throwable e ){
-											
-											req.getListener().IPResolutionComplete( req.getIP(), false );
+											}
+										}else{
 											
+											req.getListener().IPResolutionComplete( ip, true );
 										}
 									}
 								}catch( Throwable e ){
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolverListener.java b/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolverListener.java
index f13c549..ee90ba5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolverListener.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolverListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolverRequest.java b/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolverRequest.java
index c559546..6460841 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolverRequest.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/IPToHostNameResolverRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/Ignore.java b/azureus2/src/org/gudy/azureus2/core3/util/Ignore.java
index 9c45959..f22f12f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/Ignore.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/Ignore.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Sep-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/IndentWriter.java b/azureus2/src/org/gudy/azureus2/core3/util/IndentWriter.java
index c748fa2..b890073 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/IndentWriter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/IndentWriter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Apr-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/LightHashMap.java b/azureus2/src/org/gudy/azureus2/core3/util/LightHashMap.java
index afdf309..4d60a00 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/LightHashMap.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/LightHashMap.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.util;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/LightHashMapEx.java b/azureus2/src/org/gudy/azureus2/core3/util/LightHashMapEx.java
index 090d5e4..ec62ffa 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/LightHashMapEx.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/LightHashMapEx.java
@@ -2,20 +2,19 @@
  * Created on Feb 28, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/LightHashSet.java b/azureus2/src/org/gudy/azureus2/core3/util/LightHashSet.java
index 3fafa6d..0a216d8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/LightHashSet.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/LightHashSet.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.core3.util;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ListenerManager.java b/azureus2/src/org/gudy/azureus2/core3/util/ListenerManager.java
index 9ffe39d..79f19ed 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ListenerManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ListenerManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -260,6 +261,20 @@ ListenerManager<T>
 					// current listeners here. Any subsequent change won't affect our listeners
 												
 				dispatch_queue.add(new Object[]{listeners, new Integer(type), value, sem });
+				
+				if ( async_thread == null ){
+					
+					async_thread = new AEThread2( name, true )
+						{
+							public void
+							run()
+							{
+								dispatchLoop();
+							}
+						};
+											
+					async_thread.start();
+				}
 			}
 			
 			dispatch_sem.release();
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ListenerManagerDispatcher.java b/azureus2/src/org/gudy/azureus2/core3/util/ListenerManagerDispatcher.java
index 4550ea7..d60cc7c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ListenerManagerDispatcher.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ListenerManagerDispatcher.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ListenerManagerDispatcherWithException.java b/azureus2/src/org/gudy/azureus2/core3/util/ListenerManagerDispatcherWithException.java
index fc0fe54..013679a 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ListenerManagerDispatcherWithException.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ListenerManagerDispatcherWithException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/MD4Hasher.java b/azureus2/src/org/gudy/azureus2/core3/util/MD4Hasher.java
index 54a6aa9..025d6aa 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/MD4Hasher.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/MD4Hasher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/NonDaemonTask.java b/azureus2/src/org/gudy/azureus2/core3/util/NonDaemonTask.java
index 1805b06..fa1f031 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/NonDaemonTask.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/NonDaemonTask.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/NonDaemonTaskRunner.java b/azureus2/src/org/gudy/azureus2/core3/util/NonDaemonTaskRunner.java
index e0c33f8..e5d6c92 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/NonDaemonTaskRunner.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/NonDaemonTaskRunner.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/PausableAverage.java b/azureus2/src/org/gudy/azureus2/core3/util/PausableAverage.java
index 379d4f6..8b26b18 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/PausableAverage.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/PausableAverage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Sep-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/RARTOCDecoder.java b/azureus2/src/org/gudy/azureus2/core3/util/RARTOCDecoder.java
index 5b1c8fa..88587dc 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/RARTOCDecoder.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/RARTOCDecoder.java
@@ -2,20 +2,19 @@
  * Created on Oct 8, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 package org.gudy.azureus2.core3.util;
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/RandomUtils.java b/azureus2/src/org/gudy/azureus2/core3/util/RandomUtils.java
index 277d7fc..c32cb55 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/RandomUtils.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/RandomUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on Dec 30, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/RealTimeInfo.java b/azureus2/src/org/gudy/azureus2/core3/util/RealTimeInfo.java
index 6c068e8..045a523 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/RealTimeInfo.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/RealTimeInfo.java
@@ -1,7 +1,7 @@
 /*
  * Created on Nov 8, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ReferenceCountedDirectByteBuffer.java b/azureus2/src/org/gudy/azureus2/core3/util/ReferenceCountedDirectByteBuffer.java
index f11b700..f4a9ec7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ReferenceCountedDirectByteBuffer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ReferenceCountedDirectByteBuffer.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 26, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/SHA1.java b/azureus2/src/org/gudy/azureus2/core3/util/SHA1.java
index 659819b..cb3be34 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/SHA1.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/SHA1.java
@@ -2,7 +2,7 @@
  * Created on Apr 12, 2004
  * Created by Olivier Chalouhi
  * Modified Apr 13, 2004 by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.
  * 
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/SHA1Hasher.java b/azureus2/src/org/gudy/azureus2/core3/util/SHA1Hasher.java
index 10a9445..33e3f7e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/SHA1Hasher.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/SHA1Hasher.java
@@ -1,7 +1,7 @@
  /*
  * Created on Apr 13, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  * 
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/SHA1Simple.java b/azureus2/src/org/gudy/azureus2/core3/util/SHA1Simple.java
index 07ec6bf..7d613e3 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/SHA1Simple.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/SHA1Simple.java
@@ -2,7 +2,7 @@
  * Created on Apr 12, 2004
  * Created by Olivier Chalouhi
  * Modified Apr 13, 2004 by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.
  * 
  */
  
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ShellUtilityFinder.java b/azureus2/src/org/gudy/azureus2/core3/util/ShellUtilityFinder.java
index 3aaec87..3c0ea8e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ShellUtilityFinder.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ShellUtilityFinder.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.core3.util;
 
 import java.io.File;
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/SimpleTimer.java b/azureus2/src/org/gudy/azureus2/core3/util/SimpleTimer.java
index 1e8d19b..8857bad 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/SimpleTimer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/SimpleTimer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/StringInterner.java b/azureus2/src/org/gudy/azureus2/core3/util/StringInterner.java
index 6cc78fb..f3a0f88 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/StringInterner.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/StringInterner.java
@@ -2,7 +2,7 @@
 
  * Created on Jun 8, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/SystemProperties.java b/azureus2/src/org/gudy/azureus2/core3/util/SystemProperties.java
index 334401a..37925d5 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/SystemProperties.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/SystemProperties.java
@@ -3,7 +3,7 @@
  * Created by Alon Rohter
  * Copyright (C) 2004, 2005, 2006 Alon Rohter, All Rights Reserved.
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -16,9 +16,6 @@
  * 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;
 
@@ -105,7 +102,8 @@ public class SystemProperties {
 				
 				if ( dot_pos == -1 ){
 					
-					System.out.println( "SystemProperties: determineApplicationName -  can't determine application name from " + classpath );
+					// probably console UI
+					// System.out.println( "SystemProperties: determineApplicationName -  can't determine application name from " + classpath );
 					
 				}else{
 					
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/SystemTime.java b/azureus2/src/org/gudy/azureus2/core3/util/SystemTime.java
index bab7b7b..05d4429 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/SystemTime.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/SystemTime.java
@@ -1,6 +1,6 @@
 /*
- * Created on Apr 16, 2004 Created by Alon Rohter Copyright (C) 2004, 2005, 2006
- * Aelitis, All Rights Reserved.
+ * Created on Apr 16, 2004 Created by Alon Rohter
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ThreadPool.java b/azureus2/src/org/gudy/azureus2/core3/util/ThreadPool.java
index 9b76cc7..de08eeb 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ThreadPool.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ThreadPool.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/ThreadPoolTask.java b/azureus2/src/org/gudy/azureus2/core3/util/ThreadPoolTask.java
index 594bfd6..961cff0 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/ThreadPoolTask.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/ThreadPoolTask.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/TimeFormatter.java b/azureus2/src/org/gudy/azureus2/core3/util/TimeFormatter.java
index 1bf4335..39ab86e 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/TimeFormatter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/TimeFormatter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 27 juin 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/TimeLimitedTask.java b/azureus2/src/org/gudy/azureus2/core3/util/TimeLimitedTask.java
index d71155e..d53c760 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/TimeLimitedTask.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/TimeLimitedTask.java
@@ -1,120 +1,119 @@
-/*
- * Created on Jun 4, 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.core3.util;
-
-import org.gudy.azureus2.core3.security.SESecurityManager;
-
-public class 
-TimeLimitedTask 
-{
-	private String		name;
-	private int			max_millis;
-	private int			priority;
-	private task		t;
-	
-	public
-	TimeLimitedTask(
-		String			_name,
-		int				_max_millis,
-		int				_priority,
-		task			_t )
-	{
-		name		= _name;
-		max_millis	= _max_millis;
-		priority	= _priority;
-		t			= _t;
-	}
-	
-	public Object
-	run()
-	
-		throws Throwable
-	{
-		final Object[]	result	= { null };
-		
-		final AESemaphore sem = new AESemaphore( name );
-		
-		final Thread thread = 
-			new Thread( name )
-			{
-				public void
-				run()
-				{
-					try{
-						result[0] = t.run();
-						
-					}catch( Throwable e ){
-						
-						result[0] = e;
-						
-					}finally{
-						
-						t = null;
-						
-						sem.releaseForever();
-					}
-				}
-			};
-		
-		DelayedEvent ev = 
-			new DelayedEvent(
-				name, 
-				max_millis,
-				new AERunnable()
-				{
-					public void
-					runSupport()
-					{
-						if ( !sem.isReleasedForever()){
-							
-							SESecurityManager.stopThread( thread );
-						}
-					}
-				});
-
-		thread.setPriority( priority );
-		
-		thread.setDaemon( true );
-		
-		thread.start();
-		
-		sem.reserve();
-		
-		ev.cancel();
-		
-		if ( result[0] instanceof Throwable ){
-			
-			throw((Throwable)result[0] );
-		}
-		
-		return( result[0] );
-	}
-	
-	public interface
-	task
-	{
-		public Object
-		run()
-		
-			throws Exception;
-	}
-}
+/*
+ * Created on Jun 4, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.core3.util;
+
+import org.gudy.azureus2.core3.security.SESecurityManager;
+
+public class 
+TimeLimitedTask 
+{
+	private String		name;
+	private int			max_millis;
+	private int			priority;
+	private task		t;
+	
+	public
+	TimeLimitedTask(
+		String			_name,
+		int				_max_millis,
+		int				_priority,
+		task			_t )
+	{
+		name		= _name;
+		max_millis	= _max_millis;
+		priority	= _priority;
+		t			= _t;
+	}
+	
+	public Object
+	run()
+	
+		throws Throwable
+	{
+		final Object[]	result	= { null };
+		
+		final AESemaphore sem = new AESemaphore( name );
+		
+		final Thread thread = 
+			new Thread( name )
+			{
+				public void
+				run()
+				{
+					try{
+						result[0] = t.run();
+						
+					}catch( Throwable e ){
+						
+						result[0] = e;
+						
+					}finally{
+						
+						t = null;
+						
+						sem.releaseForever();
+					}
+				}
+			};
+		
+		DelayedEvent ev = 
+			new DelayedEvent(
+				name, 
+				max_millis,
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						if ( !sem.isReleasedForever()){
+							
+							SESecurityManager.stopThread( thread );
+						}
+					}
+				});
+
+		thread.setPriority( priority );
+		
+		thread.setDaemon( true );
+		
+		thread.start();
+		
+		sem.reserve();
+		
+		ev.cancel();
+		
+		if ( result[0] instanceof Throwable ){
+			
+			throw((Throwable)result[0] );
+		}
+		
+		return( result[0] );
+	}
+	
+	public interface
+	task
+	{
+		public Object
+		run()
+		
+			throws Exception;
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/Timer.java b/azureus2/src/org/gudy/azureus2/core3/util/Timer.java
index c6282f9..38174c1 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/Timer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/Timer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/TimerEvent.java b/azureus2/src/org/gudy/azureus2/core3/util/TimerEvent.java
index 224cb8c..e9b0769 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/TimerEvent.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/TimerEvent.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/TimerEventPerformer.java b/azureus2/src/org/gudy/azureus2/core3/util/TimerEventPerformer.java
index fef5471..4d479bb 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/TimerEventPerformer.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/TimerEventPerformer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/TimerEventPeriodic.java b/azureus2/src/org/gudy/azureus2/core3/util/TimerEventPeriodic.java
index 132ad1e..de014ca 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/TimerEventPeriodic.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/TimerEventPeriodic.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/TorrentUtils.java b/azureus2/src/org/gudy/azureus2/core3/util/TorrentUtils.java
index 5554418..0614107 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/TorrentUtils.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/TorrentUtils.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -34,6 +35,8 @@ import java.util.regex.Pattern;
 import java.util.zip.GZIPInputStream;
 
 import com.aelitis.azureus.core.*;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
 import com.aelitis.azureus.core.util.CopyOnWriteList;
 import com.aelitis.azureus.core.util.DNSUtils;
 
@@ -44,6 +47,7 @@ import org.gudy.azureus2.core3.logging.LogRelation;
 import org.gudy.azureus2.core3.torrent.*;
 import org.gudy.azureus2.core3.disk.*;
 import org.gudy.azureus2.core3.download.*;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
 import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl;
 
 
@@ -113,8 +117,10 @@ TorrentUtils
 	private static final String		TORRENT_AZ_PROP_PLUGINS					= "plugins";
 	
 	public static final String		TORRENT_AZ_PROP_OBTAINED_FROM			= "obtained_from";
-	public static final String		TORRENT_AZ_PROP_PEER_CACHE				= "peer_cache";
-	public static final String		TORRENT_AZ_PROP_PEER_CACHE_VALID		= "peer_cache_valid";
+	private static final String		TORRENT_AZ_PROP_NETWORK_CACHE			= "network_cache";
+	private static final String		TORRENT_AZ_PROP_TAG_CACHE				= "tag_cache";
+	private static final String		TORRENT_AZ_PROP_PEER_CACHE				= "peer_cache";
+	private static final String		TORRENT_AZ_PROP_PEER_CACHE_VALID		= "peer_cache_valid";
 	public static final String		TORRENT_AZ_PROP_INITIAL_LINKAGE			= "initial_linkage";
 	public static final String		TORRENT_AZ_PROP_INITIAL_LINKAGE2		= "initial_linkage2";
 	
@@ -135,7 +141,8 @@ TorrentUtils
 			}
 		};
 		
-	private static volatile Set<String>		ignore_set;
+	private static volatile Set<String>		ignore_files_set;
+	private static volatile Set<String>		skip_extensions_set;
 	
 	private static boolean bSaveTorrentBackup;
 	
@@ -320,6 +327,15 @@ TorrentUtils
 		return( torrent );
 	}
 	
+	public static TOTorrent
+	cloneTorrent(
+		TOTorrent	torrent )
+		
+		throws TOTorrentException
+	{
+		return( TOTorrentFactory.deserialiseFromMap( torrent.serialiseToMap()));
+	}
+
 	public static void
 	setMemoryOnly(
 		TOTorrent			torrent,
@@ -491,9 +507,14 @@ TorrentUtils
 	    		return;
 	    	}
 	    	
-	    	if ( !new File(str).delete()){
+	    	File file = new File(str);
+	    	
+	    	if ( !file.delete()){
 	    		
-	    		throw( new TOTorrentException("TorrentUtils::delete: failed to delete '" + str + "'", TOTorrentException.RT_WRITE_FAILS));
+	    		if ( file.exists()){
+	    		
+	    			throw( new TOTorrentException("TorrentUtils::delete: failed to delete '" + str + "'", TOTorrentException.RT_WRITE_FAILS));
+	    		}
 	    	}
 		
 	    	new File( str + ".bak" ).delete();
@@ -511,7 +532,10 @@ TorrentUtils
 	{
 		if ( !FileUtil.deleteWithRecycle( torrent_file, force_no_recycle )){
 			
-    		Debug.out( "TorrentUtils::delete: failed to delete '" + torrent_file + "'" );
+			if ( torrent_file.exists()){
+    		
+				Debug.out( "TorrentUtils::delete: failed to delete '" + torrent_file + "'" );
+			}
     	}
 	
     	new File( torrent_file.toString() + ".bak" ).delete();
@@ -604,7 +628,12 @@ TorrentUtils
 			
 			if ( announce_url != null ){
 			
-				hosts.add( announce_url.getHost().toLowerCase( Locale.US ));
+				String host = announce_url.getHost();
+				
+				if ( host != null ){
+				
+					hosts.add( host.toLowerCase( Locale.US ));
+				}
 			}
 			
 			TOTorrentAnnounceURLGroup group = torrent.getAnnounceURLGroup();
@@ -617,7 +646,12 @@ TorrentUtils
 					
 				for ( URL u: urls ){
 					
-					hosts.add( u.getHost().toLowerCase( Locale.US ));
+					String host = u.getHost();
+					
+					if ( host != null ){
+					
+						hosts.add( host.toLowerCase( Locale.US ));
+					}
 				}
 			}
 		}
@@ -822,6 +856,42 @@ TorrentUtils
 		return( groups );
 	}
 	
+		/**
+		 * This method DOES NOT MODIFY THE TORRENT
+		 * @param groups
+		 * @param torrent
+		 * @return
+		 */
+	
+	public static TOTorrentAnnounceURLSet[]
+	listToAnnounceSets(
+		List<List<String>>		groups,
+		TOTorrent				torrent )
+	{
+		List<TOTorrentAnnounceURLSet> sets = new ArrayList<TOTorrentAnnounceURLSet>();
+		
+		for ( List<String> group: groups ){
+			
+			List<URL> urls = new ArrayList<URL>( group.size());
+			
+			for ( String s: group ){
+				
+				try{
+					urls.add( new URL( s));
+					
+				}catch( Throwable e ){		
+				}
+			}
+			
+			if ( urls.size() > 0 ){
+			
+				sets.add( torrent.getAnnounceURLGroup().createAnnounceURLSet(urls.toArray( new URL[urls.size()])));
+			}
+		}
+		
+		return( sets.toArray( new TOTorrentAnnounceURLSet[sets.size()]));
+	}
+	
 	public static void
 	listToAnnounceGroups(
 		List<List<String>>		groups,
@@ -1212,7 +1282,8 @@ TorrentUtils
 	public static List<List<String>>
 	removeAnnounceURLs(
 		List<List<String>> 	base_urls,
-		List<List<String>>	remove_urls )
+		List<List<String>>	remove_urls,
+		boolean				use_prefix_match )
 	{
 		base_urls = getClone( base_urls );
 		if ( remove_urls == null ){
@@ -1221,7 +1292,9 @@ TorrentUtils
 		Set<String> removeSet = new HashSet<String>();
 		removeSet.add( NO_VALID_URL_URL );	// this results in removal of this dummy url if present
 		for ( List<String> l: remove_urls ){
-			removeSet.addAll(l);
+			for ( String s: l ){
+				removeSet.add( s.toLowerCase( Locale.US ));
+			}
 		}
 		Iterator<List<String>> it1 = base_urls.iterator();
 		while( it1.hasNext()){
@@ -1232,13 +1305,21 @@ TorrentUtils
 				if ( url.equals( NO_VALID_URL_URL )){
 					it2.remove();
 				}else{
-					for ( String s: removeSet ){
-						
-						if ( url.toLowerCase().startsWith( s )){
+					url = url.toLowerCase( Locale.US );
+					
+					if ( use_prefix_match ){
+												
+						for ( String s: removeSet ){
 							
+							if ( url.startsWith( s )){
+								
+								it2.remove();
+							}
+						}
+					}else{
+						if ( removeSet.contains( url )){
+								
 							it2.remove();
-							
-							break;
 						}
 					}
 				}
@@ -1254,42 +1335,19 @@ TorrentUtils
 	public static List<List<String>>
 	removeAnnounceURLs2(
 		List<List<String>> 	base_urls,
-		List<String>		remove_urls )
+		List<String>		remove_urls,
+		boolean				use_prefix_match )
 	{
-		base_urls = getClone( base_urls );
 		if ( remove_urls == null ){
-			return( base_urls );
+				// general semantics are to return a clone so caller can modify
+			return( getClone( base_urls ) );
 		}
-		Set<String> removeSet = new HashSet<String>();
-		removeSet.add( NO_VALID_URL_URL );	// this results in removal of this dummy url if present
-		removeSet.addAll(remove_urls);
+
+		List<List<String>> temp = new ArrayList<List<String>>(1);
 		
-		Iterator<List<String>> it1 = base_urls.iterator();
-		while( it1.hasNext()){
-			List<String> l = it1.next();
-			Iterator<String> it2 = l.iterator();
-			while( it2.hasNext()){
-				String url = it2.next();
-				if ( url.equals( NO_VALID_URL_URL )){
-					it2.remove();
-				}else{
-					for ( String s: removeSet ){
-						
-						if ( url.toLowerCase().startsWith( s )){
-							
-							it2.remove();
-							
-							break;
-						}
-					}
-				}
-			}
-			if ( l.isEmpty()){
-				it1.remove();
-			}
-		}
+		temp.add( remove_urls );
 		
-		return( base_urls );
+		return( removeAnnounceURLs( base_urls, temp, use_prefix_match ));
 	}
 	
 	public static List<List<String>>
@@ -1406,6 +1464,12 @@ TorrentUtils
 		tls.get().put( "hash", hash );
 	}
 	
+	public static HashWrapper
+	getTLSTorrentHash()
+	{
+		return((HashWrapper)tls.get().get( "hash" ));
+	}
+	
 	public static TOTorrent
 	getTLSTorrent()
 	{
@@ -1544,6 +1608,18 @@ TorrentUtils
 		return( url.getProtocol().equalsIgnoreCase( "dht" ));
 	}
 	
+	public static boolean
+	isDecentralised(
+		String		host )
+	{
+		if ( host == null ){
+			
+			return( false );
+		}
+		
+		return( host.endsWith( ".dht" ));
+	}
+	
 	private static Map
 	getAzureusProperties(
 		TOTorrent	torrent )
@@ -1683,6 +1759,116 @@ TorrentUtils
 	}
 	
 	public static void
+	setNetworkCache(
+		TOTorrent		torrent,
+		List<String>	networks )
+	{
+		Map	m = getAzureusPrivateProperties( torrent );
+			
+		try{
+			m.put( TORRENT_AZ_PROP_NETWORK_CACHE, networks );
+						
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+		}
+	}
+	
+	public static List<String>
+	getNetworkCache(
+		TOTorrent		torrent )
+	{
+		List<String>	result = new ArrayList<String>();
+		
+		Map	m = getAzureusPrivateProperties( torrent );
+			
+		try{
+			List l = (List)m.get( TORRENT_AZ_PROP_NETWORK_CACHE );
+				
+			if ( l != null ){
+				
+				for (Object o: l ){
+					
+					if ( o instanceof String ){
+						
+						result.add((String)o);
+						
+					}else if ( o instanceof byte[] ){
+						
+						String s = new String((byte[])o, "UTF-8" );
+						
+						for ( String x: AENetworkClassifier.AT_NETWORKS ){
+							
+							if ( s.equals( x )){
+								
+								result.add( x );
+								
+								break;
+							}
+						}
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+		}
+		
+		return( result );
+	}
+	
+	public static void
+	setTagCache(
+		TOTorrent		torrent,
+		List<String>	networks )
+	{
+		Map	m = getAzureusPrivateProperties( torrent );
+			
+		try{
+			m.put( TORRENT_AZ_PROP_TAG_CACHE, networks );
+						
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+		}
+	}
+	
+	public static List<String>
+	getTagCache(
+		TOTorrent		torrent )
+	{
+		List<String>	result = new ArrayList<String>();
+		
+		Map	m = getAzureusPrivateProperties( torrent );
+			
+		try{
+			List l = (List)m.get( TORRENT_AZ_PROP_TAG_CACHE );
+				
+			if ( l != null ){
+				
+				for (Object o: l ){
+					
+					if ( o instanceof String ){
+						
+						result.add((String)o);
+						
+					}else if ( o instanceof byte[] ){
+						
+						String s = new String((byte[])o, "UTF-8" );
+						
+						result.add( s );
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+		}
+		
+		return( result );
+	}
+	
+	public static void
 	setPeerCache(
 		TOTorrent		torrent,
 		Map				pc )
@@ -1691,7 +1877,9 @@ TorrentUtils
 			
 		try{
 			m.put( TORRENT_AZ_PROP_PEER_CACHE, pc );
-						
+			
+			setPeerCacheValid( torrent );
+			
 		}catch( Throwable e ){
 			
 			Debug.printStackTrace(e);
@@ -1783,22 +1971,22 @@ TorrentUtils
 			
 			if ( pp != null ){
 				
-				Map<String,String> links;
+				Map<String,Object> _links;
 				
 				byte[]	g_data = (byte[])pp.get( TorrentUtils.TORRENT_AZ_PROP_INITIAL_LINKAGE2 );
 				
 				if ( g_data == null ){
 				
-					links = (Map<String,String>)pp.get( TorrentUtils.TORRENT_AZ_PROP_INITIAL_LINKAGE );
+					_links = (Map<String,Object>)pp.get( TorrentUtils.TORRENT_AZ_PROP_INITIAL_LINKAGE );
 					
 				}else{
 					
-					links = (Map<String,String>)BDecoder.decode(new BufferedInputStream( new GZIPInputStream( new ByteArrayInputStream( g_data ))));
+					_links = BDecoder.decode(new BufferedInputStream( new GZIPInputStream( new ByteArrayInputStream( g_data ))));
 
 				}
-				if ( links != null ){//&& TorrentUtils.isCreatedTorrent( torrent )){
+				if ( _links != null ){//&& TorrentUtils.isCreatedTorrent( torrent )){
 					
-					links = BDecoder.decodeStrings( links );
+					Map<String,String> links = (Map<String,String>)BDecoder.decodeStrings( _links );
 					
 					for ( Map.Entry<String,String> entry: links.entrySet()){
 						
@@ -1988,15 +2176,38 @@ TorrentUtils
 	}
 		
 	
-	public static boolean isReallyPrivate(TOTorrent torrent) {
+	public static boolean 
+	isReallyPrivate(
+		TOTorrent torrent) 
+	{
 		if ( torrent == null ){
 			
 			return( false );
 		}	
 		
-		if ( UrlUtils.containsPasskey( torrent.getAnnounceURL())){
+		URL url = torrent.getAnnounceURL();
+		
+		if ( url == null ){
+	
+			TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets();
+			
+			if ( sets != null && sets.length > 0 ){
+				
+				URL[] urls = sets[0].getAnnounceURLs();
+				
+				if ( urls.length > 0 ){
 				
-			return torrent.getPrivate();
+					url = urls[0];
+				}
+			}
+		}
+		
+		if ( url != null ){
+			
+			if ( UrlUtils.containsPasskey( url )){
+					
+				return torrent.getPrivate();
+			}
 		}
 		
 		return false;
@@ -2033,23 +2244,107 @@ TorrentUtils
 		}
 	}
 	
+		// skip extensions
+	
+	
+	public static Set<String>
+	getSkipExtensionsSet()
+	{
+		return(getSkipExtensionsSetSupport(false));
+	}
+	
+	private static synchronized Set<String>
+	getSkipExtensionsSetSupport(
+		boolean	force )
+	{
+		if ( skip_extensions_set == null || force ){
+			
+			Set<String>		new_skip_set	= new HashSet<String>();
+		    
+			String	skip_list = COConfigurationManager.getStringParameter( "File.Torrent.AutoSkipExtensions" );
+			
+			skip_list = skip_list.replace( ',', ';' );
+			
+			if ( skip_extensions_set == null ){
+				
+					// first time - add the listener
+				
+				COConfigurationManager.addParameterListener(
+					"File.Torrent.AutoSkipExtensions",
+					new ParameterListener()
+					{
+						public void 
+						parameterChanged(
+							String parameterName)
+						{
+							getSkipExtensionsSetSupport( true );
+						}
+					});
+			}
+			
+			int	pos = 0;
+			
+			while( true ){
+				
+				int	p1 = skip_list.indexOf( ";", pos );
+				
+				String	bit;
+				
+				if ( p1 == -1 ){
+					
+					bit = skip_list.substring(pos);
+					
+				}else{
+					
+					bit	= skip_list.substring( pos, p1 );
+					
+					pos	= p1+1;
+				}
+				
+				String ext = bit.trim().toLowerCase(); 	// use default locale as we're dealing with local file names
+				
+				if ( ext.startsWith(".")){
+					
+					ext = ext.substring(1);
+				}
+				
+				if ( ext.length() > 0 ){
+				
+					new_skip_set.add( ext );
+				}
+				
+				if ( p1 == -1 ){
+					
+					break;
+				}
+			}
+			
+			skip_extensions_set = new_skip_set;
+		}
+		
+		return( skip_extensions_set );
+	}
+	
+	
+		// ignore files
+	
 	public static Set<String>
 	getIgnoreSet()
 	{
 		return(getIgnoreSetSupport(false));
 	}
 	
-	public static synchronized Set<String>
+	private static synchronized Set<String>
 	getIgnoreSetSupport(
 		boolean	force )
 	{
-		if ( ignore_set == null || force ){
+		if ( ignore_files_set == null || force ){
 			
 			Set<String>		new_ignore_set	= new HashSet<String>();
 		    
 			String	ignore_list = COConfigurationManager.getStringParameter( "File.Torrent.IgnoreFiles", TOTorrent.DEFAULT_IGNORE_FILES );
 			
-			if ( ignore_set == null ){
+			if ( ignore_files_set == null ){
 				
 					// first time - add the listener
 				
@@ -2085,7 +2380,7 @@ TorrentUtils
 					pos	= p1+1;
 				}
 				
-				new_ignore_set.add(bit.trim().toLowerCase());
+				new_ignore_set.add(bit.trim().toLowerCase());	// use default locale as we're dealing with local file names
 				
 				if ( p1 == -1 ){
 					
@@ -2093,10 +2388,10 @@ TorrentUtils
 				}
 			}
 			
-			ignore_set = new_ignore_set;
+			ignore_files_set = new_ignore_set;
 		}
 		
-		return( ignore_set );
+		return( ignore_files_set );
 	}
 	
 	
@@ -3083,9 +3378,53 @@ TorrentUtils
 			throw new IOException("File copy failed");
 		}
 
+		if ( shouldDeleteTorrentFileAfterAdd( f, persistent )){
+			
+			f.delete();
+		}
+		
 		return fDest;
 	}
 
+	public static boolean
+	shouldDeleteTorrentFileAfterAdd(
+		File		f,
+		boolean		persistent )
+	{
+		if ( !persistent ){
+			
+			return( false );
+		}
+		
+		boolean delTorrents = COConfigurationManager.getBooleanParameter("Delete Original Torrent Files");
+
+		if ( !delTorrents ){
+			
+			return( false );
+		}
+		
+		boolean saveTorrents = COConfigurationManager.getBooleanParameter("Save Torrent Files");
+		
+		if ( saveTorrents ){
+			
+			try{
+				File torrentDir = new File(COConfigurationManager.getDirectoryParameter("General_sDefaultTorrent_Directory"));
+				
+				if ( torrentDir.isDirectory() && torrentDir.equals( f.getParentFile())){
+					
+					return( false );
+				}
+			}catch( Throwable e ){
+				
+				return( false );
+			}
+		}
+		
+		File active_dir = FileUtil.getUserFile( "active" );
+		
+		return( !active_dir.equals( f.getParentFile()));
+	}
+			
 	/**
 	 * Get the DownloadManager related to a torrent's hashBytes
 	 * 
@@ -3294,11 +3633,55 @@ TorrentUtils
 	
 		throws IOException
 	{
+		return( download( url, 0 ));
+	}
+	
+	public static TOTorrent
+	download(
+		URL		url,
+		long	timeout )
+	
+		throws IOException
+	{
 		try{
-			byte[] bytes = FileUtil.readInputStreamAsByteArray( new ResourceDownloaderFactoryImpl().create( url ).download(), BDecoder.MAX_BYTE_ARRAY_SIZE );
-			
-			return( TOTorrentFactory.deserialiseFromBEncodedByteArray( bytes ));
-			
+			PluginProxy	plugin_proxy = null;
+
+			try{
+				if ( AENetworkClassifier.categoriseAddress( url.getHost()) != AENetworkClassifier.AT_PUBLIC ){
+					
+					plugin_proxy = AEProxyFactory.getPluginProxy( "torrent download", url );
+				}
+				
+				ResourceDownloader rd;
+				
+				if ( plugin_proxy == null ){
+				
+					rd = new ResourceDownloaderFactoryImpl().create( url );
+					
+				}else{
+					
+					rd = new ResourceDownloaderFactoryImpl().create( plugin_proxy.getURL(), plugin_proxy.getProxy());
+					
+					rd.setProperty( "URL_HOST", url.getHost());
+				}
+				
+				if ( timeout > 0 ){
+				
+					rd.setProperty( "URL_Connect_Timeout", timeout );
+					rd.setProperty( "URL_Read_Timeout", timeout );
+				}
+				
+				byte[] bytes = FileUtil.readInputStreamAsByteArray( rd.download(), BDecoder.MAX_BYTE_ARRAY_SIZE );
+				
+				return( TOTorrentFactory.deserialiseFromBEncodedByteArray( bytes ));
+				
+			}finally{
+				
+				if (plugin_proxy != null ){
+					
+					plugin_proxy.setOK( true );
+				}
+			}
 		}catch( IOException e ){
 			
 			throw((IOException)e);
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/TrackersUtil.java b/azureus2/src/org/gudy/azureus2/core3/util/TrackersUtil.java
index e86eb41..59372a8 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/TrackersUtil.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/TrackersUtil.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/UnresolvableHostManager.java b/azureus2/src/org/gudy/azureus2/core3/util/UnresolvableHostManager.java
index 29b648a..2bf3694 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/UnresolvableHostManager.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/UnresolvableHostManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Oct-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/UrlUtils.java b/azureus2/src/org/gudy/azureus2/core3/util/UrlUtils.java
index 12631fe..6286705 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/UrlUtils.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/UrlUtils.java
@@ -1,6 +1,6 @@
 /*
  * Created on Mar 21, 2006 3:09:00 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
@@ -25,21 +22,26 @@ import java.io.UnsupportedEncodingException;
 import java.net.*;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 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.plugins.download.Download;
 import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.plugins.torrent.TorrentAnnounceURLList;
 import org.gudy.azureus2.plugins.torrent.TorrentAnnounceURLListSet;
 import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
 import org.gudy.azureus2.plugins.utils.resourceuploader.ResourceUploader;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
 
-import com.aelitis.net.magneturi.MagnetURIHandler;
 
 /**
  * @author TuxPaper
@@ -60,7 +62,8 @@ public class UrlUtils
 			"ftp://",
 			"dht://",
 			"magnet:?",
-			"magnet://?" };
+			"magnet://?",
+			"maggot://" };
 
 	private static int MAGNETURL_STARTS_AT = 3;	// dht:// is a form of magnet URL
 	
@@ -81,10 +84,174 @@ public class UrlUtils
 
 	public static String
 	getMagnetURI(
+		byte[]		hash,
+		String		name,
+		String[]	networks )
+	{
+		String magnet_uri = getMagnetURI( hash );
+					
+		magnet_uri += encodeName( name );
+					
+		magnet_uri += encodeNetworks( networks );
+		
+		return( magnet_uri );
+	}
+
+	private static String
+	encodeName(
+		String	name )
+	{
+		if ( name == null ){
+			
+			return( "" );
+			
+		}else{
+			
+			return( "&dn=" + UrlUtils.encode(name));
+		}
+	}
+	
+	private static String
+	encodeNetworks(
+		String[]	networks )
+	{
+		String	net_str = "";
+
+		if ( networks != null && networks.length > 0 ){
+						
+			for ( String net: networks ){
+				
+				if ( net == AENetworkClassifier.AT_PUBLIC && networks.length == 1 ){
+						
+					break;
+				}
+				
+				net_str += "&net=" + net;
+			}
+		}
+		
+		return( net_str );
+	}
+	
+	public static Set<String>
+	extractNetworks(
+		String[]		magnet_uri )
+	{
+		String magnet_uri_in = magnet_uri[0];
+		
+		Set<String>	result = new HashSet<String>();
+		
+		int	pos = magnet_uri_in.indexOf( '?' );
+		
+		if ( pos != -1 ){
+		
+			String magnet_uri_out = magnet_uri_in.substring( 0, pos+1 );
+
+			String[] bits = magnet_uri_in.substring( pos+1 ).split( "&" );
+			
+			for ( String bit: bits ){
+				
+				String[] temp = bit.split( "=", 2 );
+				
+				boolean	remove = false;
+				
+				if ( temp.length == 2 ){
+					
+					String	lhs = temp[0];
+					
+					if ( lhs.equalsIgnoreCase( "net" )){
+					
+						String	rhs = decode( temp[1] );
+					
+						result.add( AENetworkClassifier.internalise( rhs ));
+						
+						remove = true;
+					}
+				}
+				
+				if ( !remove ){
+					
+					if ( !magnet_uri_out.endsWith( "?" )){
+						
+						magnet_uri_out += "&";
+					}
+					
+					magnet_uri_out += bit;		
+				}
+			}
+			
+			if ( result.size() > 0 ){
+			
+				magnet_uri[0] = magnet_uri_out;
+			}
+		}
+		
+		return( result );
+	}
+	
+	public static String
+	getMagnetURI(
+		Download		download )
+	{
+		return( getMagnetURI( PluginCoreUtils.unwrap(download)));
+	}
+	
+	public static String
+	getMagnetURI(
+		Download		download,
+		int				max_name_len )
+	{
+		return( getMagnetURI( PluginCoreUtils.unwrap(download), max_name_len ));
+	}
+	
+	public static String
+	getMagnetURI(
+		DownloadManager		dm )
+	{
+		return( getMagnetURI( dm, Integer.MAX_VALUE ));
+	}
+	
+	public static String
+	getMagnetURI(
+		DownloadManager		dm,
+		int					max_name_len )
+	{
+		if ( dm == null ){
+			
+			return( null );
+		}
+		
+		TOTorrent to_torrent = dm.getTorrent();
+		
+		if ( to_torrent == null ){
+		
+			return( null );
+		}
+		
+		String name = dm.getDisplayName();
+		
+		if ( name.length() > max_name_len ){
+			
+			name = name.substring( 0, max_name_len-3) + "...";
+		}
+		
+		String magnet_uri = getMagnetURI( name, PluginCoreUtils.wrap( to_torrent ));
+		
+		String[]	networks = dm.getDownloadState().getNetworks();
+		
+		magnet_uri += encodeNetworks( networks );
+		
+		return( magnet_uri );
+	}
+	
+	public static String
+	getMagnetURI(
 		String		name,
 		Torrent		torrent )
 	{
-		String	magnet_str = getMagnetURI( torrent.getHash()) + "&dn=" + UrlUtils.encode(name);
+		String	magnet_str = getMagnetURI( torrent.getHash());
+		
+		magnet_str += encodeName( name);
 
 		List<String>	tracker_urls = new ArrayList<String>();
 		
@@ -255,6 +422,18 @@ public class UrlUtils
 			return null;
 		}
 
+		text = text.trim();
+		
+		if ( text.startsWith( "azplug:" )){
+			
+			return( text );
+		}
+		
+		if ( text.startsWith( "chat:" )){
+			
+			return( "azplug:?id=azbuddy&arg=" + UrlUtils.encode( text ));
+		}
+		
 		String href = parseHTMLforURL(text);
 		if (href != null) {
 			return href;
@@ -262,12 +441,12 @@ public class UrlUtils
 
 		try {
 			text = text.trim();
-			text = URLDecoder.decode(text);
+			text = decodeIfNeeded(text);
 		} catch (Exception e) {
 			// sometimes fires a IllegalArgumentException
 			// catch everything and ignore.
 		}
-
+		
 		String textLower;
 		try {
 			textLower = text.toLowerCase();
@@ -303,6 +482,20 @@ public class UrlUtils
 			return null;
 		}
 
+			// be lenient for raw anon addresses
+		
+		try{
+			URL u = new URL( "http://" + text );
+		
+			String host = u.getHost();
+			
+			if ( host != null && AENetworkClassifier.categoriseAddress( host ) != AENetworkClassifier.AT_PUBLIC ){
+				
+				return( u.toExternalForm());
+			}
+		}catch( Throwable e ){
+		}
+		
 		if (accept_magnets
 				&& (text.startsWith("bc://") || text.startsWith("bctp://"))) {
 			return parseTextForMagnets(text);
@@ -350,7 +543,7 @@ public class UrlUtils
 	parseTextForMagnets(
 		String		text )
 	{
-		if (text.startsWith("magnet:")) {
+		if (text.startsWith("magnet:") || text.startsWith( "maggot:" )){
 			return text;
 		}
 
@@ -376,6 +569,12 @@ public class UrlUtils
 			return matcher.group();
 		}
 
+		pattern = Pattern.compile("maggot://[a-z0-9]+:[a-z0-9]", Pattern.CASE_INSENSITIVE);
+		matcher = pattern.matcher(text);
+		if (matcher.find()) {
+			return matcher.group();
+		}
+		
 		pattern = Pattern.compile("bc://bt/([a-z0-9=\\+/]+)", Pattern.CASE_INSENSITIVE);
 		matcher = pattern.matcher(text.replaceAll(" ", "+"));
 		if (matcher.find()) {
@@ -462,7 +661,7 @@ public class UrlUtils
 		if (m.find()) {
 			String sURL = m.group(1);
 			try {
-				sURL = URLDecoder.decode(sURL);
+				sURL = decodeIfNeeded(sURL);
 			} catch (Exception e) {
 				// sometimes fires a IllegalArgumentException
 				// catch everything and ignore.
@@ -473,43 +672,7 @@ public class UrlUtils
 		return null;
 	}
 
-	public static void main(String[] args) {
-		
-		MagnetURIHandler.getSingleton();
-		byte[] infohash = ByteFormatter.decodeString("1234567890123456789012345678901234567890");
-		String[] test = {
-				"http://moo.com",
-				"http%3A%2F/moo%2Ecom",
-				"magnet:?moo",
-				"magnet%3A%3Fxt=urn:btih:26",
-				"magnet%3A//%3Fmooo",
-				"magnet:?xt=urn:btih:" + Base32.encode(infohash),
-				"aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd",
-				"magnet:?dn=OpenOffice.org_2.0.3_Win32Intel_install.exe&xt=urn:sha1:PEMIGLKMNFI4HZ4CCHZNPKZJNMAAORKN&xt=urn:tree:tiger:JMIJVWHCQUX47YYH7O4XIBCORNU2KYKHBBC6DHA&xt=urn:ed2k:1c0804541f34b6583a383bb8f2cec682&xl=96793015&xs=http://mirror.switch.ch/ftp/mirror/OpenOffice/stable/2.0.3/OOo_2.0.3_Win32Intel_install.exe",
-				};
-		for (int i = 0; i < test.length; i++) {
-			System.out.println("URLDecoder.decode: " + test[i] + " -> " + URLDecoder.decode(test[i]));
-			System.out.println("decode: " + test[i] + " -> " + decode(test[i]));
-			System.out.println("isURL: " + test[i] + " -> " + isURL(test[i]));
-			System.out.println("parse: " + test[i] + " -> " + parseTextForURL(test[i], true));
-		}
 
-		String[] testEncode = {
-			"a b"
-		};
-		for (int i = 0; i < testEncode.length; i++) {
-			String txt = testEncode[i];
-			try {
-				System.out.println("URLEncoder.encode: " + txt + " -> "
-						+ URLEncoder.encode(txt, "UTF8"));
-			} catch (UnsupportedEncodingException e) {
-			}
-			System.out.println("URLEncoder.encode: " + txt + " -> "
-					+ URLEncoder.encode(txt));
-			System.out.println("encode: " + txt + " -> " + encode(txt));
-		}
-
-	}
 
 	/**
 	 * Like URLEncoder.encode, except translates spaces into %20 instead of +
@@ -532,12 +695,68 @@ public class UrlUtils
 			return "";
 		}
 		try {
-			return( URLDecoder.decode(s, "UTF-8"));
+			try{
+				return( URLDecoder.decode(s, "UTF-8"));
+				
+			}catch( IllegalArgumentException e ){
+				
+					// handle truncated encodings somewhat gracefully
+				
+				int pos = s.lastIndexOf( "%" );
+				
+				if ( pos >= s.length()-2 ){
+					
+					return( URLDecoder.decode(s.substring( 0, pos ), "UTF-8"));
+				}
+				
+				throw( e );
+			}
 		} catch (UnsupportedEncodingException e) {
+			
 			return( URLDecoder.decode(s));
 		}
 	}
 	
+	/**
+	 * Unfortunately we have code that mindlessly decoded URLs (FileDownloadWindow) which borked (in the case I discovered) magnet uris with encoded 
+	 * parameters (e.g. the &tr= parameter) - doing so screws stuff up later if, for example, the parameter included an encoded '&'
+	 * @param s
+	 * @return
+	 */
+	
+	public static String 
+	decodeIfNeeded(
+		String s ) 
+	{
+		if ( s == null ){
+			
+			return( "" );
+		}
+		
+		try{
+				// of course someone prolly added the blind URLDecode for a reason so try and just deal with the borkage
+				// which means looking for &a=b elements and ensure we don't URLDecode the 'b'
+			
+				// only have issues if there's a naked '?' there
+			
+			int	q_pos = s.indexOf( '?' );
+			int a_pos = s.indexOf( '&' );
+			
+			if ( q_pos == -1 && a_pos == -1 ){
+				
+				return( decode( s ));
+			}
+			
+			int start = Math.min( q_pos, a_pos );
+			
+			return( decode( s.substring( 0, start )) + s.substring( start ));
+			
+		}catch( Throwable e ){
+			
+			return( s );
+		}
+	}
+	
 	public static String escapeXML(String s) {
 		if (s == null) {
 			return "";
@@ -859,6 +1078,11 @@ public class UrlUtils
 	containsPasskey(
 		URL		url )
 	{
+		if ( url == null ){
+			
+			return( false );
+		}
+		
 		String url_str = url.toExternalForm();
 		
 		return( url_str.matches(".*[0-9a-z]{20,40}.*"));
@@ -1057,7 +1281,7 @@ public class UrlUtils
 		URL	url )
 	{
 		try{
-			InetAddress[] addresses = InetAddress.getAllByName( url.getHost());
+			InetAddress[] addresses = AddressUtils.getAllByName( url.getHost());
 			
 			if ( addresses.length > 0 ){
 				
@@ -1111,4 +1335,49 @@ public class UrlUtils
 		
 		return( res );
 	}
+	
+	
+	
+	public static void main(String[] args) {
+		
+		//MagnetURIHandler.getSingleton();
+		
+		System.out.println( URLEncoder.encode( "http://a.b.c/fred?a=10&b=20"));
+		
+		byte[] infohash = ByteFormatter.decodeString("1234567890123456789012345678901234567890");
+		String[] test = {
+				"http://moo.com",
+				"http%3A%2F/moo%2Ecom",
+				"magnet:?moo",
+				"magnet%3A%3Fxt=urn:btih:26",
+				"magnet%3A//%3Fmooo",
+				"magnet:?xt=urn:btih:" + Base32.encode(infohash),
+				"aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd",
+				"magnet:?dn=OpenOffice.org_2.0.3_Win32Intel_install.exe&xt=urn:sha1:PEMIGLKMNFI4HZ4CCHZNPKZJNMAAORKN&xt=urn:tree:tiger:JMIJVWHCQUX47YYH7O4XIBCORNU2KYKHBBC6DHA&xt=urn:ed2k:1c0804541f34b6583a383bb8f2cec682&xl=96793015&xs=http://mirror.switch.ch/ftp/mirror/OpenOffice/stable/2.0.3/OOo_2.0.3_Win32Intel_install.exe%3Fa%3D10%26b%3D20",
+				};
+		for (int i = 0; i < test.length; i++) {
+			System.out.println( test[i] );
+			System.out.println("URLDecoder.decode: -> " + URLDecoder.decode(test[i]));
+			System.out.println("decode:            -> " + decode(test[i]));
+			System.out.println("decodeIf:          -> " + decodeIfNeeded(test[i]));
+			System.out.println("isURL:             -> " + isURL(test[i]));
+			System.out.println("parse:             -> " + parseTextForURL(test[i], true));
+		}
+
+		String[] testEncode = {
+			"a b"
+		};
+		for (int i = 0; i < testEncode.length; i++) {
+			String txt = testEncode[i];
+			try {
+				System.out.println("URLEncoder.encode: " + txt + " -> "
+						+ URLEncoder.encode(txt, "UTF8"));
+			} catch (UnsupportedEncodingException e) {
+			}
+			System.out.println("URLEncoder.encode: " + txt + " -> "
+					+ URLEncoder.encode(txt));
+			System.out.println("encode: " + txt + " -> " + encode(txt));
+		}
+
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarBuilder.java b/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarBuilder.java
index 495246c..5a77311 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarBuilder.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarBuilder.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarReader.java b/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarReader.java
index f5f6b00..8275de7 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarReader.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarReader.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarSigner.java b/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarSigner.java
index 62e413c..a844e73 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarSigner.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarSigner.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarSigner2.java b/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarSigner2.java
index 7a9148a..0023652 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarSigner2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/jar/AEJarSigner2.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Oct-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/jman/AEMemoryMonitor.java b/azureus2/src/org/gudy/azureus2/core3/util/jman/AEMemoryMonitor.java
index dd7d6a9..7e7e7ee 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/jman/AEMemoryMonitor.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/jman/AEMemoryMonitor.java
@@ -2,20 +2,19 @@
  * Created on Sep 9, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/jman/AEThreadMonitor.java b/azureus2/src/org/gudy/azureus2/core3/util/jman/AEThreadMonitor.java
index b59cc9e..31779ee 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/jman/AEThreadMonitor.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/jman/AEThreadMonitor.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
@@ -29,8 +26,14 @@ import java.lang.management.ThreadInfo;
 import java.lang.management.ThreadMXBean;
 import java.util.*;
 
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.logging.LogAlert;
+import org.gudy.azureus2.core3.logging.Logger;
 import org.gudy.azureus2.core3.util.*;
 
+import com.aelitis.azureus.core.util.average.AverageFactory;
+import com.aelitis.azureus.core.util.average.MovingAverage;
+
 public class 
 AEThreadMonitor 
 	implements AEJavaManagement.ThreadStuff
@@ -155,7 +158,12 @@ AEThreadMonitor
 		
 		Map<Long,Long>	last_times = new HashMap<Long,Long>();
 		
-		long	time_available = 10000;
+		final int	time_available = 10*1000;
+		
+		long	start_mono = SystemTime.getMonotonousTime();
+		
+		MovingAverage 	high_usage_history 	= AverageFactory.MovingAverage(2*60*1000/time_available);
+		boolean			huh_mon_active		= false;
 		
 		while( true ){
 			
@@ -221,6 +229,29 @@ AEThreadMonitor
 			
 			log.log( "Thread state: elapsed=" + elapsed + ",cpu=" + total_diffs + ",max=" + thread_name + "(" + biggest_diff + "/" + percent + "%),mem:max=" + (rt.maxMemory()/1024)+",tot=" + (rt.totalMemory()/1024) +",free=" + (rt.freeMemory()/1024));
 			
+			if ( huh_mon_active ){
+			
+					// ESET version 8 seems to be triggering high CPU in this thread
+				
+				boolean interesting = percent > 5 && thread_name.equals( "PRUDPPacketHandler:sender" );
+						
+				double temp = high_usage_history.update( interesting?1:0 );
+			
+				if ( temp >= 0.5 ){
+					
+					Logger.log(					
+						new LogAlert(
+							false,
+							LogAlert.AT_WARNING,
+							"High CPU usage detected in networking code - see <a href=\"http://wiki.vuze.com/w/High_CPU_Usage\">The Wiki</a> for possible solutions" ));
+
+				}
+				
+			}else{
+				
+				huh_mon_active = SystemTime.getMonotonousTime() - start_mono > 2*60*1000;
+			}
+			
 			if ( biggest_diff > time_available/4 ){
 				
 				info = bean.getThreadInfo( ids[biggest_index ], 255 );
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/AzURLStreamHandlerFactory.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/AzURLStreamHandlerFactory.java
index a313c8c..161338f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/AzURLStreamHandlerFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/AzURLStreamHandlerFactory.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -11,9 +11,6 @@
  * 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 org.gudy.azureus2.core3.util.protocol;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/azplug/AZPluginConnection.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/azplug/AZPluginConnection.java
index a198976..1d9616d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/azplug/AZPluginConnection.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/azplug/AZPluginConnection.java
@@ -1,7 +1,7 @@
-/*
+ /*
  * Created on 06-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,28 +14,28 @@
  * 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.protocol.azplug;
 
 import java.util.*;
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLDecoder;
 
-
 import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.UrlUtils;
 import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.ipc.IPCException;
 import org.gudy.azureus2.plugins.ipc.IPCInterface;
 
 import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.util.AZ3Functions;
+import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
 
 /**
  * @author parg
@@ -88,7 +88,7 @@ AZPluginConnection
 			if ( x.length == 2 ){
 				
 				String	lhs = x[0];
-				String	rhs = URLDecoder.decode(x[1], "UTF-8" );
+				String	rhs = UrlUtils.decode(x[1] );
 				
 				args.put( lhs.toLowerCase(), rhs );
 			}
@@ -104,38 +104,73 @@ AZPluginConnection
 		String	plugin_name = (String)args.get( "name" );
 		String	arg			= (String)args.get( "arg" );
 		
-		String plugin_str = plugin_id + (plugin_name==null?"":( " (" + plugin_name + ")" ));
+		if ( arg == null ){
+			
+			arg = "";
+		}
 		
-		// AZPluginConnection is called via reflection
-		// Let's just assume that the Core is avail..
-		PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( plugin_id );
+		String plugin_str;
 		
-		if ( pi == null ){
+		if ( plugin_name == null ){
 			
-			throw( new IOException( "Plugin id " + plugin_str + " not installed" ));
+			plugin_str = "with id '" + plugin_id + "'"; 
+			
+		}else{
+			
+			plugin_str = "'" + plugin_name + "' (id " + plugin_id + ")";
 		}
 		
-		IPCInterface ipc = pi.getIPC();
-		
-		try{
-			if ( ipc.canInvoke( "handleURLProtocol", new Object[]{ this, arg })){
-					
-				input_stream = (InputStream)ipc.invoke( "handleURLProtocol", new Object[]{ this, arg });
-
-			}else{
+		if ( plugin_id.equals( "subscription" )){
+			
+			AZ3Functions.provider az3 = AZ3Functions.getProvider();
 			
-				input_stream = (InputStream)ipc.invoke( "handleURLProtocol", new Object[]{ arg });
+			if ( az3 == null ){
+				
+				throw( new IOException( "Subscriptions are not available" ));
 			}
-		}catch( IPCException ipce ){
 			
-			Throwable e = ipce;
+			try{
+				az3.subscribeToSubscription( arg );
 			
-			if ( e.getCause() != null ){
+				input_stream = new ByteArrayInputStream( VuzeFileHandler.getSingleton().create().exportToBytes());
+				
+			}catch( Throwable e ){
 				
-				e = e.getCause();
+				throw( new IOException( "Subscription addition failed: " + Debug.getNestedExceptionMessage( e )));
 			}
+		}else{
+			// AZPluginConnection is called via reflection
+			// Let's just assume that the Core is avail..
+			
+			PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( plugin_id );
 			
-			throw( new IOException( "Communication error with plugin '" + plugin_str + "': " + Debug.getNestedExceptionMessage(e)));
+			if ( pi == null ){
+				
+				throw( new IOException( "Plugin " + plugin_str + " is required - go to 'Tools->Plugins->Installation Wizard' to install." ));
+			}
+			
+			IPCInterface ipc = pi.getIPC();
+			
+			try{
+				if ( ipc.canInvoke( "handleURLProtocol", new Object[]{ this, arg })){
+						
+					input_stream = (InputStream)ipc.invoke( "handleURLProtocol", new Object[]{ this, arg });
+	
+				}else{
+				
+					input_stream = (InputStream)ipc.invoke( "handleURLProtocol", new Object[]{ arg });
+				}
+			}catch( IPCException ipce ){
+				
+				Throwable e = ipce;
+				
+				if ( e.getCause() != null ){
+					
+					e = e.getCause();
+				}
+				
+				throw( new IOException( "Communication error with plugin '" + plugin_str + "': " + Debug.getNestedExceptionMessage(e)));
+			}
 		}
 	}
 	
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/azplug/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/azplug/Handler.java
index 7b85160..4a03c27 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/azplug/Handler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/azplug/Handler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/bc/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/bc/Handler.java
index 7f5c8fe..c8da359 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/bc/Handler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/bc/Handler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/dht/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/dht/Handler.java
index 204b4dd..68565a4 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/dht/Handler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/dht/Handler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/i2p/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/i2p/Handler.java
index 0b33fe1..16ac2ba 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/i2p/Handler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/i2p/Handler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -38,6 +39,8 @@ Handler
 	public URLConnection 
 	openConnection(URL u)
 	{	
+		// 2014/9/24: parg - not sure what the usecase for this is...
+		
 		String	str = u.toString();
 		
 		str = "http" + str.substring( 3 );
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/maggot/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/maggot/Handler.java
new file mode 100644
index 0000000..3e055be
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/maggot/Handler.java
@@ -0,0 +1,122 @@
+/*
+ * File    : Handler.java
+ * Created : 19-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, 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 ( 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.core3.util.protocol.maggot;
+
+/**
+ * @author parg
+ *
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.*;
+
+import org.gudy.azureus2.core3.util.Base32;
+import org.gudy.azureus2.core3.util.ByteFormatter;
+import org.gudy.azureus2.core3.util.protocol.magnet.MagnetConnection2;
+
+import com.aelitis.net.magneturi.MagnetURIHandler;
+
+
+public class 
+Handler 
+	extends URLStreamHandler 
+{
+	public URLConnection 
+	openConnection(URL u)
+	{		
+		return(
+			new MagnetConnection2( 
+				u,
+				new MagnetConnection2.MagnetHandler()
+				{
+					
+					public void 
+					process(
+						URL 			maggot, 
+						OutputStream	os) 
+						
+						throws IOException
+					{
+							// convert into magnet lookalike
+						
+						String maggot_str = maggot.toExternalForm();
+						
+						int pos = maggot_str.indexOf( '?' );
+							
+						String rem;
+						
+						if ( pos == -1 ){
+							
+							rem = "";
+							
+						}else{
+							
+							rem = "&" + maggot_str.substring( pos+1 );
+							
+							maggot_str = maggot_str.substring( 0, pos );
+						}
+						
+						pos = maggot_str.lastIndexOf( "/" );
+						
+						maggot_str = maggot_str.substring( pos+1 );
+						
+						String[] bits = maggot_str.split( ":" );
+						
+						String btih_str = bits[0];
+						String sha1_str	= bits[1];
+					
+						String	magnet_str = "magnet:?xt=urn:btih:" + Base32.encode( ByteFormatter.decodeString( btih_str ));
+						
+						magnet_str += rem + "&maggot_sha1=" + sha1_str;
+						
+						URL magnet = new URL( magnet_str );
+						
+						String	get = "/download/" + magnet.toString().substring( 7 ) + " HTTP/1.0\r\n\r\n";
+						
+						MagnetURIHandler.getSingleton().process( get, new ByteArrayInputStream(new byte[0]), os );
+					}
+				}));
+	}
+	
+	 protected void 
+	 parseURL(
+		URL 		u, 
+		String 		spec, 
+		int 		start, 
+		int 		limit ) 
+	 {
+		 	// need to override this as the <ih>:<sha1> format of maggot URIs isn't compatible with the 
+		 	// usual <host>:<port>.... - turn it all into the host
+		 
+		 spec = spec.substring( start );
+		 
+		 while( spec.length() > 0 && "/?".indexOf( spec.charAt(0)) != -1 ){
+			 
+			 spec = spec.substring(1);
+		 }
+		 
+		 setURL(u, "maggot", spec, -1, spec, null, "", null, null );
+	 }
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/Handler.java
index 0945d0f..8078f50 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/Handler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/Handler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -26,8 +27,13 @@ package org.gudy.azureus2.core3.util.protocol.magnet;
  *
  */
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
 import java.net.*;
 
+import com.aelitis.net.magneturi.MagnetURIHandler;
+
 
 public class 
 Handler 
@@ -39,7 +45,24 @@ Handler
 			// some anti-virus apps blocking loopback connection we initially used
 			// in MagnetConnection so created variant based on direct communication to
 			// the magnet handler
-		
-		return( new MagnetConnection2( u ));
+				
+		return(
+			new MagnetConnection2( 
+				u,
+				new MagnetConnection2.MagnetHandler()
+				{
+					
+					public void 
+					process(
+						URL 			magnet, 
+						OutputStream	os) 
+						
+						throws IOException
+					{
+						String	get = "/download/" + magnet.toString().substring( 7 ) + " HTTP/1.0\r\n\r\n";
+	
+						MagnetURIHandler.getSingleton().process( get, new ByteArrayInputStream(new byte[0]), os );
+					}
+				}));
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/MagnetConnection.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/MagnetConnection.java
index 7dfec27..ed3e38c 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/MagnetConnection.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/MagnetConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/MagnetConnection2.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/MagnetConnection2.java
index 1f84833..417f757 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/MagnetConnection2.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/magnet/MagnetConnection2.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,11 @@
  * 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.protocol.magnet;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -38,7 +34,6 @@ import org.gudy.azureus2.core3.util.TimerEvent;
 import org.gudy.azureus2.core3.util.TimerEventPerformer;
 import org.gudy.azureus2.core3.util.TimerEventPeriodic;
 
-import com.aelitis.net.magneturi.MagnetURIHandler;
 
 /**
  * @author parg
@@ -108,32 +103,34 @@ MagnetConnection2
 		}
 	}
 	
+	private MagnetHandler	handler;
 	private OutputStream 	output_stream;
 	private InputStream 	input_stream;
 	
 	private LinkedList<String>	status_list = new LinkedList<String>();
 	
-	protected
+	public
 	MagnetConnection2(
-		URL		_url )
+		URL		_url,
+		MagnetHandler		_handler )
 	{
 		super( _url );
+		
+		handler	= _handler;
 	}
 	
 	public void
 	connect()
-		throws IOException
-		
-	{				
-		String	get = "/download/" + getURL().toString().substring( 7 ) + " HTTP/1.0" + NL + NL;
-		
+	
+		throws IOException	
+	{						
 		MagnetOutputStream 	mos = new MagnetOutputStream();
 		MagnetInputStream 	mis = new MagnetInputStream( mos );
 					
 		input_stream	= mis;
 		output_stream 	= mos;
 		
-		MagnetURIHandler.getSingleton().process( get, new ByteArrayInputStream(new byte[0]), mos );
+		handler.process( getURL(), mos );
 	}
 	
 	public InputStream
@@ -599,4 +596,15 @@ MagnetConnection2
 			out.close();
 		}
 	}
+	
+	public interface
+	MagnetHandler
+	{
+		public void
+		process(
+			URL					magnet,
+			OutputStream		os )
+			
+			throws IOException;	
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/socks5/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/socks5/Handler.java
index bc888f5..4a2406d 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/socks5/Handler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/socks5/Handler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/socks5/Socks5URLConnection.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/socks5/Socks5URLConnection.java
index 6de454f..0f81e26 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/socks5/Socks5URLConnection.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/socks5/Socks5URLConnection.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/tcp/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/tcp/Handler.java
index b56575c..4f2a729 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/tcp/Handler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/tcp/Handler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/tcp/TCPURLConnection.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/tcp/TCPURLConnection.java
index 75584c5..7bda140 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/tcp/TCPURLConnection.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/tcp/TCPURLConnection.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/tor/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/tor/Handler.java
new file mode 100644
index 0000000..cfa74b1
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/tor/Handler.java
@@ -0,0 +1,56 @@
+/*
+ * File    : Handler.java
+ * Created : 19-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, 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 ( 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.core3.util.protocol.tor;
+
+/**
+ * @author parg
+ *
+ */
+
+import java.io.IOException;
+import java.net.*;
+
+
+public class 
+Handler 
+	extends URLStreamHandler 
+{
+	public URLConnection 
+	openConnection(
+		URL 		u )
+	
+		throws IOException
+	{	
+		throw( new IOException( "tor: URIs can't be used directly" ));
+	}
+
+	public URLConnection 
+	openConnection(
+		URL 		u,
+		Proxy		proxy )
+	
+		throws IOException
+	{
+		throw( new IOException( "tor: URIs can't be used directly" ));
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/udp/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/udp/Handler.java
index 6b2df3a..fd250d4 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/udp/Handler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/udp/Handler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/udp/UDPURLConnection.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/udp/UDPURLConnection.java
index 5350ba0..47d05fe 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/udp/UDPURLConnection.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/udp/UDPURLConnection.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/vuze/Handler.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/vuze/Handler.java
index bacf6c1..c688032 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/vuze/Handler.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/vuze/Handler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/protocol/vuze/VuzeURLConnection.java b/azureus2/src/org/gudy/azureus2/core3/util/protocol/vuze/VuzeURLConnection.java
index 138ce62..60c1748 100644
--- a/azureus2/src/org/gudy/azureus2/core3/util/protocol/vuze/VuzeURLConnection.java
+++ b/azureus2/src/org/gudy/azureus2/core3/util/protocol/vuze/VuzeURLConnection.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/core3/util/spi/AENameServiceDescriptor.java b/azureus2/src/org/gudy/azureus2/core3/util/spi/AENameServiceDescriptor.java
new file mode 100644
index 0000000..eed924b
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/core3/util/spi/AENameServiceDescriptor.java
@@ -0,0 +1,342 @@
+/*
+ * Created on Aug 18, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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 org.gudy.azureus2.core3.util.spi;
+
+import java.io.IOException;
+import java.lang.reflect.*;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.gudy.azureus2.core3.config.COConfigurationListener;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.TorrentUtils;
+
+import sun.net.spi.nameservice.*;
+import sun.net.spi.nameservice.dns.*;
+
+/*
+ * This proxy is controlled by the setting in ConfigurationManager
+ * 
+ * 		System.setProperty("sun.net.spi.nameservice.provider.1","dns,aednsproxy");
+ * 
+ * and also requires META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor to contain the text
+ * 
+ *  	org.gudy.azureus2.core3.util.spi.AENameServiceDescriptor
+ * 
+ * On OSX you will need to do the following to get things to compile:
+ * 
+ * Windows -> Preferences -> Java -> Compiler -> Errors/Warnings -> Deprecated and restricted API -> Forbidden reference (access rules): -> change to warning
+ * 
+ */
+
+public class 
+AENameServiceDescriptor 
+	implements NameServiceDescriptor 
+{
+		// used in NetworkAdminImpl - not direct fixup due to loading issues observed...
+	
+	private static final String 		TEST_HOST	= "dns.test.client.vuze.com";
+	
+	private final static NameService 	delegate_ns;
+	private final static Method 		delegate_ns_method_lookupAllHostAddr;
+	
+	private final static Object		 	delegate_iai;
+	private final static Method 		delegate_iai_method_lookupAllHostAddr;
+
+	
+	private final static NameService proxy_name_service;
+
+	static{
+		NameService default_ns 					= null;
+		Method		default_lookupAllHostAddr	= null;
+		
+		NameService new_ns = null;
+		
+		try{
+			default_ns = new DNSNameService();
+			
+			if ( default_ns != null ){
+				
+				default_lookupAllHostAddr = default_ns.getClass().getMethod( "lookupAllHostAddr", String.class );
+				
+				new_ns = 
+						(NameService)Proxy.newProxyInstance(
+							NameService.class.getClassLoader(),
+							new Class[]{ NameService.class },
+							new NameServiceProxy());				
+			}
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+		}
+		
+		/*
+		 * It almost works by delegating the the DNSNameService directly apart from InetAddress.getLocalHost() - rather than returning something sensible
+		 * it fails with unknown host. However, if we directly grab the InetAddressImpl and use this (which has already been set up to use the default name server)
+		 * things work better :( Hacked to support both at the moment...
+		 */
+		
+		Object	iai						= null;
+		Method	iai_lookupAllHostAddr	= null;
+
+		try{
+			Field field = InetAddress.class.getDeclaredField( "impl" );
+			
+			field.setAccessible( true );
+			
+			iai = field.get( null );
+			
+			iai_lookupAllHostAddr = iai.getClass().getMethod( "lookupAllHostAddr", String.class );
+			
+			iai_lookupAllHostAddr.setAccessible( true );
+
+		}catch( Throwable e ){
+			
+			System.err.println( "Issue resolving the default name service..." );
+		}	
+		
+		proxy_name_service						= new_ns;
+		delegate_ns 							= default_ns;
+		delegate_ns_method_lookupAllHostAddr 	= default_lookupAllHostAddr;
+		delegate_iai 							= iai;
+		delegate_iai_method_lookupAllHostAddr 	= iai_lookupAllHostAddr;
+	}
+
+	private static boolean 				config_listener_added;
+	private static volatile boolean 	tracker_dns_disabled;
+	private static volatile boolean		tracker_plugin_proxies_permit;
+	
+	public NameService
+	createNameService() 
+	
+		throws Exception
+	{
+		if ( proxy_name_service == null ){
+			
+			throw( new Exception( "Failed to create proxy name service" ));
+		}
+		
+		return( proxy_name_service );
+	}
+	
+	public String
+	getType()
+	{
+		return( "dns" );
+	}
+	
+	public String
+	getProviderName() 
+	{
+		return( "aednsproxy" ); 
+	}
+
+	private static class 
+	NameServiceProxy 
+		implements InvocationHandler 
+	{
+		public Object
+		invoke(
+			Object		proxy, 
+			Method 		method, 
+			Object[]	args ) 
+				
+			throws Throwable 
+		{	
+			String method_name = method.getName();
+
+			if ( method_name.equals( "lookupAllHostAddr" )){
+
+				String host_name = (String)args[0];
+				
+				if ( host_name.equals( TEST_HOST )){
+					
+					if ( delegate_ns == null ){
+						
+						throw( new RuntimeException( "Delegate Name Service unavailable" ));
+					}
+					
+					host_name = "www.google.com";
+					
+					try{
+						Object result = null;
+						
+						if ( delegate_iai_method_lookupAllHostAddr != null ){
+							
+							try{
+								result = delegate_iai_method_lookupAllHostAddr.invoke(  delegate_iai, host_name );
+	
+							}catch( Throwable e ){
+							}
+						}
+						
+						if ( result == null ){
+						
+							result = delegate_ns_method_lookupAllHostAddr.invoke( delegate_ns, host_name );
+						}
+						
+						
+						
+					}catch( Throwable e ){
+						
+						if ( e instanceof UnknownHostException ){
+							
+							// guess their DNS might be down - don't treat as complete fail
+						
+							System.err.println( "DNS resolution of " + host_name + " failed, DNS unavailable?" );
+							
+						}else{
+						
+							throw( new RuntimeException( "Delegate lookup failed", e ));
+						}
+					}
+					
+					// byte[][] or InetAddress[]
+					
+					Class ret_type = method.getReturnType();
+					
+					if ( ret_type.equals( byte[][].class )){
+					
+						return( new byte[][]{ {127,0,0,1}});
+						
+					}else{
+						
+						return( new InetAddress[]{ InetAddress.getByAddress( new byte[]{ 127, 0, 0, 1 })});
+					}
+				}
+			
+				boolean tracker_request = TorrentUtils.getTLSTorrentHash() != null;
+	
+				if ( tracker_request ){
+										
+					synchronized( this ){
+						
+						if ( !config_listener_added ){
+							
+							config_listener_added = true;
+							
+							COConfigurationManager.addAndFireListener(
+									new COConfigurationListener()
+									{
+										public void 
+										configurationSaved()
+										{					
+											boolean	enable_proxy 	= COConfigurationManager.getBooleanParameter("Enable.Proxy");
+										    boolean enable_socks	= COConfigurationManager.getBooleanParameter("Enable.SOCKS");
+										    boolean prevent_dns		= COConfigurationManager.getBooleanParameter("Proxy.SOCKS.Tracker.DNS.Disable");
+										    
+											tracker_plugin_proxies_permit = 
+													enable_proxy&&
+													enable_socks&&
+													!COConfigurationManager.getBooleanParameter( "Proxy.SOCKS.disable.plugin.proxies" );
+
+										    tracker_dns_disabled = enable_proxy&&enable_socks&&prevent_dns;
+										}
+									});
+						}
+					}
+					
+					if ( tracker_plugin_proxies_permit ){
+					
+							// in this case we want non-public addresses to be sent to the plugin proxy, not handed
+							// unresolved to a SOCKS proxy, so use a runtime exception to
+							// prevent this (UnknownHostException causes SOCKS usage)
+						
+						if ( AENetworkClassifier.categoriseAddress( host_name ) != AENetworkClassifier.AT_PUBLIC ){
+							
+							throw( new RuntimeException( "Plugin proxies enabled for SOCKS"));
+						}
+					}
+					
+					if ( tracker_dns_disabled ){
+						
+							// this will normally result in the address being marked as 'unresolved' and
+							// therefore be passed through socks 4a/5 for remote resolution 
+						
+						throw( new UnknownHostException( host_name ));
+					}
+				}
+			}
+			
+			return( invokeSupport( method_name, args ));
+		}
+		
+		private Object
+		invokeSupport(
+			String		method_name,
+			Object[]	args ) 
+				
+			throws Throwable 
+		{										
+			if ( method_name.equals( "getHostByAddr" )){
+			
+				byte[] address_bytes = (byte[])args[0];
+				
+				//System.out.println( method_name + ": " + ByteFormatter.encodeString( address_bytes ));
+				
+				return delegate_ns.getHostByAddr( address_bytes );
+				
+			}else if ( method_name.equals( "lookupAllHostAddr" )){
+
+				String host_name = (String)args[0];
+
+				//System.out.println( method_name + ": " + host_name );
+				
+				if ( host_name == null || host_name.equals( "null" )){
+						
+					// get quite a few of these from 3rd party libs :(
+					// new Exception("Bad DNS lookup: " + host_name).printStackTrace();
+										
+				}else if ( host_name.endsWith( ".i2p" ) || host_name.endsWith( ".onion" )){
+					
+					//new Exception( "Prevented DNS leak for " + host_name ).printStackTrace();
+					
+					throw( new UnknownHostException( host_name ));
+				}
+				
+				// System.out.println( "DNS: " + host_name );
+				
+				try{
+					if ( delegate_iai_method_lookupAllHostAddr != null ){
+						
+						try{
+							return( delegate_iai_method_lookupAllHostAddr.invoke(  delegate_iai, host_name ));
+
+						}catch( Throwable e ){
+						}
+					}
+					
+					return( delegate_ns_method_lookupAllHostAddr.invoke( delegate_ns, host_name ));
+
+				}catch( InvocationTargetException e ){
+					
+					throw(((InvocationTargetException)e).getTargetException());
+				}
+				
+			}else{		
+			
+				throw( new IllegalArgumentException( "Unknown method '" + method_name + "'" ));
+			}
+		}
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/core3/xml/simpleparser/SimpleXMLParserDocumentFactory.java b/azureus2/src/org/gudy/azureus2/core3/xml/simpleparser/SimpleXMLParserDocumentFactory.java
index 4bc5b4e..0f2f035 100644
--- a/azureus2/src/org/gudy/azureus2/core3/xml/simpleparser/SimpleXMLParserDocumentFactory.java
+++ b/azureus2/src/org/gudy/azureus2/core3/xml/simpleparser/SimpleXMLParserDocumentFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -22,6 +23,7 @@
 package org.gudy.azureus2.core3.xml.simpleparser;
 
 import java.io.*;
+import java.net.URL;
 
 import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument;
 import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException;
@@ -39,13 +41,29 @@ SimpleXMLParserDocumentFactory
 		return( new SimpleXMLParserDocumentImpl( file ));
 	}
 	
+	/**
+	 * @deprecated
+	 * @param is
+	 * @return
+	 * @throws SimpleXMLParserDocumentException
+	 */
 	public static SimpleXMLParserDocument
 	create(
 		InputStream		is )
 		
 		throws SimpleXMLParserDocumentException
 	{
-		return( new SimpleXMLParserDocumentImpl( is ));
+		return( new SimpleXMLParserDocumentImpl( null, is ));
+	}
+	
+	public static SimpleXMLParserDocument
+	create(
+		URL				source_url,
+		InputStream		is )
+		
+		throws SimpleXMLParserDocumentException
+	{
+		return( new SimpleXMLParserDocumentImpl( source_url, is ));
 	}
 	
 	public static SimpleXMLParserDocument
diff --git a/azureus2/src/org/gudy/azureus2/core3/xml/util/XMLElement.java b/azureus2/src/org/gudy/azureus2/core3/xml/util/XMLElement.java
index 697a427..b6cacbc 100644
--- a/azureus2/src/org/gudy/azureus2/core3/xml/util/XMLElement.java
+++ b/azureus2/src/org/gudy/azureus2/core3/xml/util/XMLElement.java
@@ -1,7 +1,7 @@
 /**
  * Created on 10-Jan-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.xml.util;
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/xml/util/XMLEscapeWriter.java b/azureus2/src/org/gudy/azureus2/core3/xml/util/XMLEscapeWriter.java
index 0bf7b06..fa5409f 100644
--- a/azureus2/src/org/gudy/azureus2/core3/xml/util/XMLEscapeWriter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/xml/util/XMLEscapeWriter.java
@@ -2,20 +2,19 @@
  * Created on Jan 5, 2011
  * Created by Paul Gardner
  * 
- * Copyright 2011 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/core3/xml/util/XUXmlWriter.java b/azureus2/src/org/gudy/azureus2/core3/xml/util/XUXmlWriter.java
index 0ec0cca..f2414c4 100644
--- a/azureus2/src/org/gudy/azureus2/core3/xml/util/XUXmlWriter.java
+++ b/azureus2/src/org/gudy/azureus2/core3/xml/util/XUXmlWriter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle.properties
index e73146c..fd1c04d 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle.properties
@@ -150,7 +150,8 @@ ConfigView.section.server=Connection
 ConfigView.section.global=General
 ConfigView.label.disconnetseed=Disconnect seeds when seeding
 ConfigView.label.switchpriority=Auto-switch to low-priority when seeding
-ConfigView.label.maxdownloads=Max simultaneous downloads [0: unlimited]\n - Cannot be higher than the number of max active torrents
+ConfigView.label.maxdownloads.short=Max simultaneous downloads [0: unlimited]
+ConfigView.label.maxdownloads={ConfigView.label.maxdownloads.short}\n - Cannot be higher than the number of max active torrents
 ConfigView.label.maxdownloads.tooltip=You will always be able to actively download the number you provide here, with one exception.\nA completed torrent matching First Priority may take over an active download slot if absolutely required.
 ConfigView.label.maxactivetorrents=Max active torrents [0: unlimited]\n - New torrents won\'t start if you are downloading/seeding more
 ConfigView.label.priorityExtensions=Auto-prioritize files with \n - eg: .txt;.nfo;.jpg
@@ -1293,8 +1294,8 @@ MyTorrentsView.menu.setSpeed.unlimit=No limit
 MyTorrentsView.menu.setSpeed.unlimited=Unlimited
 MyTorrentsView.menu.setSpeed.disable=Disable Upload
 MyTorrentsView.menu.setSpeed.disabled=Disabled
-MyTorrentsView.menu.setSpeed.in=in
-MyTorrentsView.menu.setSpeed.slots=slots of
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 in %2 slots of %3
 GeneralView.label.maxuploadspeed=Up Limit
 GeneralView.label.maxuploadspeed.tooltip=max upload speed [0 : unlimited]
 MyTorrents.items.UpSpeedLimit.disabled=No upload
@@ -1318,11 +1319,11 @@ FilesView.remaining=Remaining pieces
 TableColumn.header.trackername=Tracker Name
 TableColumn.header.trackername.info=Name of the tracker based on announce URL
 ConfigView.group.override=Override Options
-ConfigView.section.proxy=Proxy Options
 ConfigView.section.file.perf.cache.notsmallerthan=Do not cache files smaller than this (in %1)
 PeersView.menu.blockupload=Block Upload
 PeersView.menu.kickandban=Kick and Ban
 PeersView.menu.kickandban.reason=Peer manually banned
+PeersView.menu.kick=Kick
 PeersView.state=State
 PeersView.state.info=State of the peer connection
 PeersView.state.pending=Pending
@@ -2091,6 +2092,8 @@ MainWindow.menu.view.iconbar=Toolbar
 MyTorrentsView.menu.rename=Rename...
 MyTorrentsView.menu.rename.displayed=Rename Displayed Name
 MyTorrentsView.menu.rename.save_path=Rename Save Path
+#used by torrentnameutils plugin
+MyTorrentsView.menu.rename.displayed_and_save_path=Rename Displayed Name and Save Path
 
 AdvRenameWindow.title=Rename Download 
 AdvRenameWindow.message=Enter a new name for this download.
@@ -2702,7 +2705,7 @@ ConfigView.section.style.forceMozilla=Force Vuze to use Mozilla for Browser widg
 ConfigView.section.style.xulRunnerPath=Specify XulRunner / Firefox path manually [required for FF3; restart required]
 
 azbuddy.name=Friends
-azbuddy.enabled=Enabled
+azbuddy.enabled=Classic Enabled
 azbuddy.disabled=Plugin is disabled, see plugin config to change.
 azbuddy.nickname=Your Nickname
 azbuddy.msglog.title=Friend Information
@@ -2760,6 +2763,7 @@ Button.bar.edit=Edit
 Button.bar.edit.cancel=Done Editing
 
 v3.MainWindow.menu.view.pluginbar=Plugin Bar
+v3.MainWindow.menu.view.pluginbar.keybinding=F8
 
 MainWindow.dialog.select.vuze.file=Select Vuze File
 MainWindow.menu.file.open.vuze=Vuze File...
@@ -2904,6 +2908,7 @@ MainWindow.menu.community.wiki=Community &Wiki && FAQ
 MainWindow.menu.community.forums=Community Fo&rums
 MainWindow.menu.community.blog=Vuze &Blog
 MainWindow.menu.help.support=&Help and Support
+MainWindow.menu.community.chat=Community &Chat
 
 
 externalLogin.title=Login Required
@@ -3101,18 +3106,18 @@ ConfigView.section.interface.legacy=Legacy
 
 v3.MainWindow.menu.contentnetworks.manage=&Manage HD Networks
 
-azbuddy.ui.table.loc_cat=Cats out
-azbuddy.ui.table.rem_cat=Cats in
-azbuddy.ui.menu.cat=Categories
-azbuddy.ui.menu.cat.share=Enable subscriptions with friend(s)
-azbuddy.ui.menu.cat.set=Enter categories
-azbuddy.ui.menu.cat.set_msg=Comma separated list of categories, or 'All'
+azbuddy.ui.table.loc_cat=Tags/Cats out
+azbuddy.ui.table.rem_cat=Tags/Cats in
+azbuddy.ui.menu.cat=Tags/Categories
+azbuddy.ui.menu.cat.share=Enable Subscriptions With Friend(s)
+azbuddy.ui.menu.cat.set=Enter tags/categories
+azbuddy.ui.menu.cat.set_msg=Comma separated list of tags, categories or 'All'
 azbuddy.ui.menu.cat_subs=Subscribe
 
 subs.prop.update_period=Update period
-azbuddy.enable_cat_pub=Public categories that ALL your friends can subscribe to (',' separated) 
+azbuddy.enable_cat_pub=Public tags/categories that ALL your friends can subscribe to (',' separated) 
 
-azbuddy.ui.table.read_cat=Cat read
+azbuddy.ui.table.read_cat=Tag/Cat read
 
 TableColumn.header.#=Order
 TableColumn.header.#.info=Priority/Position/Ordering Number
@@ -3126,7 +3131,7 @@ TableColumn.header.unopened.info=Flag to indicate whether the torrent has been p
 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.
-TableColumn.header.size.info=Size of torrent's content on disk
+TableColumn.header.size.info=Size of torrent's chosen content on disk
 TableColumn.header.azsubs.ui.column.subs.info=Button that allows you to subscribe to feed containing related torrents
 TableColumn.header.upspeed.info=Current upload speed 
 TableColumn.header.downspeed.info=Current download speed 
@@ -3143,8 +3148,6 @@ TableColumn.header.upload.info=Amount of data we have sent to the peer
 TableColumn.header.downloadspeed.info=Rate at which we are are getting from the peer
 TableColumn.header.uploadspeed.info=Rate at which we are sending data to the peer
 TableColumn.header.lan.info=Flag indicating if the peer is on your LAN
-TableColumn.header.maxdownspeed.info=Download speed limit set on peer
-TableColumn.header.maxupspeed.info=Upload speed limit set on peer
 TableColumn.header.downloadspeedoverall.info=Estimated download rate of peer
 Peers.column.pieces.info=Graphical bar representing which pieces the peer has downloaded
 TableColumn.header.TableColumnNameInfo=Column Name and Description
@@ -3415,7 +3418,7 @@ 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.initialising=Initializing
 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 
@@ -4188,7 +4191,7 @@ library.tag.header=Tag '%1'
 label.tags=Tags
 label.add.tag=Add Tag...
 label.show.tag=Show Tag
-TagAddWindow.message=Enter a new tag name
+TagAddWindow.message=Enter a new tag name:
 TagAddWindow.title=Add New Tag
 TagRenameWindow.message=Enter a new name for the tag
 TagRenameWindow.title=Rename Tag
@@ -4208,7 +4211,7 @@ tag.type.ds.incomp={label.incomplete}
 
 tag.type.man=Manual
 label.show.all=Show All
-tag.type.ipset=IP Set
+tag.type.ipset=Peer Set
 label.complete=Complete
 label.incomplete=Incomplete
 
@@ -4275,6 +4278,7 @@ TableColumn.header.tag.type={MySharesView.type}
 tags.view.heading=Tags Overview
 mdi.entry.tagsoverview={tags.view.heading}
 TableColumn.header.tag.public={ConfigView.pluginlist.column.type.shared}
+TableColumn.header.tag.public.info={tag.share}
 MainWindow.menu.view.tagsoverview={tags.view.heading}
 TableColumn.header.tag.uprate={TableColumn.header.upspeed}
 TableColumn.header.tag.downrate={TableColumn.header.downspeed}
@@ -4337,7 +4341,6 @@ OpenTorrentOptions.title=Open Torrent Options
 OpenTorrentOptions.header.torrentinfo=Torrent Information
 OpenTorrentOptions.header.filesInfo.all=%1 Files: %3
 OpenTorrentOptions.header.filesInfo.some=%1 of %2 Files: %3
-OpenTorrentOptions.header.torrentinfo=Torrent Information
 OpenTorrentOptions.header.saveto=Save Location: %1
 OpenTorrentOptions.header.startoptions=Start Options: %1
 OpenTorrentOptions.header.peeroptions=Tracker, Peer & Connection Options
@@ -4421,28 +4424,23 @@ menu.max.share.ratio=Target Share Ratio (%1)...
 max.sr.window.message=Enter target share ratio [0:disabled]
 max.sr.window.title=Target Share Ratio
 TableColumn.header.max_sr={max.sr.window.title}
-
 ConfigView.section.mode.beginner.text1=All you need to download torrents - great for new users learning about the client and torrents.
 ConfigView.section.mode.intermediate.text1=More features for controlling, optimizing and visualizing downloads.
 ConfigView.section.mode.advanced.text1=Full access to all settings and features.
-
 label.current.equals={label.current} %1
 label.tracker.templates=Tracker Templates
 tag.property.tracker_templates={label.tracker.templates}
 label.reapply=Reapply
-
 ConfigView.section.security.resetcerts=Reset certificate store (will restart Vuze)
 ConfigView.section.security.resetcerts.warning.title=Data Loss Warning
 ConfigView.section.security.resetcerts.warning.msg=Are you sure you want to reset the certificate store? If you have created a self-signed certificate or manually imported any certificates these will be lost!
 ConfigView.section.security.resetcerts.error.title={ConfigView.section.security.resetkey.error.title}
 ConfigView.section.security.resetcerts.error.msg=Failed to reset the certificate store for an unknown reason, please see the forums for help
-
 TableColumn.header.sr_prog=Share Ratio Progress
 TableColumn.header.sr_prog.info=Shows the date on which a download's share ratio attained certain values
 TableColumn.menu.sr_prog.interval=Set Progress Interval...
 sr_prog.window.title=Progress Interval
 sr_prog.window.message=Enter share ratio progress recording interval (e.g. 1.0 = every full copy)
-
 ConfigView.section.queue.downloading={ManagerItem.downloading}
 ConfigView.label.downloading.info=Automatic adjustment of downloading queue position works best when you have set a reasonably accurate overall download speed limit based on your network capacity 
 ConfigView.label.downloading.autoReposition=Reposition queued downloads to optimize downloading
@@ -4461,18 +4459,14 @@ TableColumn.header.readrate=Read Rate
 TableColumn.header.readrate.info=File Read Rate
 TableColumn.header.writerate=Write Rate
 TableColumn.header.writerate.info=File Write Rate
-
 TableColumn.header.file_eta={TableColumn.header.eta}
 TableColumn.header.file_eta.info=Estimated time until file has completed downloading
-
 label.force.piece=Force Piece
 label.rerequest.blocks=Re-request blocks
 tag.show.overview=Show Tag Overview...
-
 config.internal.browser=Internal Browser
 config.internal.browser.info1=The internal browser is used to display web content embedded into the client, for example the Vuze HD Network page
 config.internal.browser.info2=By default Internet Explorer is used on Windows, Safari on Mac. *Limited* versions of Firefox can be used instead - see the following options
-
 config.external.browser=External Browser
 config.external.browser.info1=The external browser is used to display web content outside of the client in a separate browser, for example search result details pages
 config.external.browser.info2=Your computer's default browser is normally used. You can change this to use a specific browser, or that provided by a plugin (e.g. the Tor Browser plugin)
@@ -4482,7 +4476,6 @@ external.browser.manual=Manual
 config.external.browser.select=Browser selection
 config.external.browser.prog=Browser executable
 config.external.browser.test=Test external browser configuration
-
 external.browser.failed=External Browser Failed
 xmwebui.required=You need to install the 'Vuze Web Remote' plugin for this to work\n\nSee Tools->Plugins->Installation Wizard...
 config.external.browser.switch.feature=Feature
@@ -4492,16 +4485,374 @@ config.external.browser.switch.search=Search results
 config.external.browser.switch.search.inf=Requires 'Vuze Web Remote' plugin; No web results; No template editing features; No subscription creation from results; No referrer setting on download links
 config.external.browser.switch.subs={ConfigView.section.Subscriptions}
 config.external.browser.switch.subs.inf=Requires 'Vuze Web Remote' plugin; Results not set as 'read' when downloaded; No referrer setting on download links
-
-
 label.bar.trans=Bar transparency [0=opaque;100=transparent]
 subs.ext.view.info=You have configured Vuze to use an external browser to display subscription results
 subs.ext.view.launch.info=Press this button to launch a browser
 delete.partial.files=When removing a download from the library delete any partial files for those selected as 'do not download' or 'delete'
 config.internal.browser.proxy.select=Browser proxy
 config.internal.browser.info3=A proxy can be used to cause the content to be fetched indirectly, when installed (e.g. provided by the Tor Helper plugin)
-
 play.select.content=Select Content To Play
 ConfigView.label.defaultstarttorrentsstoppedandpause=When a torrent is added in a stopped state automatically pause it
 
+wizard.maketorrents.force=Force start the torrent
+wizard.maketorrents.superseed=Use super-seeding
+menu.max.share.ratio2=Set Target Share Ratio...
+menu.min.share.ratio2=Set Minimum Share Ratio...
+MainWindow.menu.tools.netstat={Views.plugins.aznetstatus.title}...
+plugin.aznetstatus.logfull=Full Logging
+label.test.internet=Test your internet connection
+label.test.types=Test Types
+label.outbound=Outbound
+label.inbound=Inbound
+label.nat.proxies=NAT/Proxies
+label.bt.connect=BT Connect
+label.vuze.services=Vuze Services
+label.indirect.connect=Indirect Connect
+label.contraints=Constraints...
+UpdateConstraint.message=Enter the constraints to be applied to the tag - see the Wiki for details.
+UpdateConstraint.title=Update Constraints
+tag.property.constraint=Constraint
+
+label.copy.on.comp=Copy On Complete
+TableColumn.header.tag.copyoncomp={label.copy.on.comp}
+alert.copy.on.comp.fail=Download %1\nError copying completed files to '%2': %3
+alert.copy.on.comp.done=Download %1\nFiles successfully copied to '%2'
+
+TableColumn.header.sha1=SHA1
+TableColumn.header.sha1.info=SHA1 hash for the file (must be fully downloaded; click to calculate)
+FilesView.sha1.calculate=Calculate SHA1 hash(s)
+
+ConfigView.section.file.bgdefaultdir.ask=Best guess default
+
+TableColumn.header.DateFileCompleted=File Completed
+TableColumn.header.DateFileCompleted.info=Most recent file completion date in the torrent
+wizard.maketorrents.init.tags=Initial tags (',' separated)
+
+label.monitor.clipboard=Monitor Clipboard For Torrent Links
+
+ConfigView.label.bStartNoMoreSeedsWhenUpLimitMet=Don't start any more torrents for seeding when global active upload limit is met
+ConfigView.label.bStartNoMoreSeedsWhenUpLimitMetSlack=Upload limit approximation (percentage or absolute reduction in KB/sec)
+ConfigView.label.bStartNoMoreSeedsWhenUpLimitMetPercent=The above approximation is a percentage (deselect for absolute)
+
+apply.to.current=Apply To Current
+webui.i2p_dest=I2P address
+webui.tor_dest=Tor address
+
+pairing.group.optional=Optional Attributes
+pairing.nets.enable=Enable registration of non-public network service addresses
+
+label.check.avail={GeneralView.section.availability}
+torrent.avail.title=Sources for '%1'
+TrackerAvail.column.type={Trackers.column.type}
+TrackerAvail.column.name={Trackers.column.name}
+TrackerAvail.column.status={Trackers.column.status}
+TrackerAvail.column.seeds={Trackers.column.seeds}
+TrackerAvail.column.seeds.info={Trackers.column.seeds.info}
+TrackerAvail.column.leechers={Trackers.column.leechers}
+TrackerAvail.column.leechers.info={Trackers.column.leechers.info}
+TrackerAvail.column.peers={Trackers.column.peers}
+TrackerAvail.column.peers.info={Trackers.column.peers.info}
+label.checking.sources=Checking download source availability
+
+ConfigView.section.style.ShowCatButtons=Show Category Buttons in Library
+ConfigView.section.style.ShowTagButtons=Show Tag Buttons in Library
+ConfigView.label.show.cat.but=Show Category Buttons
+ConfigView.label.show.tag.but=Show Tag Buttons
+
+MyTorrentsView.menu.moreColHidden=(%1 More Hidden...)
+MyTorrentsView.menu.setSpeed.down.disable=Disable Download
+
+dhttracker.alt_group=Alternative Tracking
+dhttracker.enable_alt={ConfigView.section.stats.enable}
+dhttracker.alt_port=Port [0: random]
+
+AllPeers.column.#=#
+Peers.column.#=#
+label.show.selected.rates=Show Selected Item Rates
+
+label.set.shortcut=Set Shortcut
+config.dialog.shortcut.title=Set Keyboard Shortcut
+config.dialog.shortcut.text=Enter character for 'control+' combination for this section, blank to remove
+ConfigView.section.style.ShowTagButtons.CompOnly=Only show in the Complete section of the Library
+
+label.visible=Visible
+TableColumn.header.tag.visible={label.visible}
+MyTorrentsView.menu.group=Group...
+TagGroupWindow.title=Set Tag Group
+TagGroupWindow.message=Entry group name
+TableColumn.header.tag.group=Group
+
+rss.internal.enable.low.noise=Enable low-noise downloads (internal downloads etc.)
+
+subscription.request.add.title={subscriptions.add.tooltip}
+subscription.request.add.message=%1 is an RSS feed\n\nAdd a new subscription?
+OpenTorrentWindow.tlf.remove=Remove Top Level Folder
+OpenTorrentFileView.header={ConfigView.section.files}
+OpenTorrentWindow.tlf.rename=Rename Torrent On Top Level Folder Change
+ConfigView.label.save_list.max_entries=Save location history size
+ConfigView.label.save_list.clear=Remove history
+label.no.suggestions=No Suggestions
+label.ctrl.space.for.suggestion=Hit Ctrl+<space> or Shift+<space> for suggestions
+
+network.admin.bind.enforce.fail='Enforce IP Bindings' is selected but no bindings have been specified\n\nSee Tools->Options->Connection->Advanced Network Settings
+network.admin.dns.spi.fail=Failed to install DNS manager\n\nThis will impact functions such as forced DNS resolution prevention with SOCKS\n\nError: %1
+
+ConfigView.section.proxy.no.local.dns=Prevent local DNS lookups
+ConfigView.section.proxy.disable.plugin.proxies=Disable plugin proxies (e.g. Tor/I2P Helper plugins) when a SOCKS server is configured
+
+tag.discovery.view.heading=Tag Discoveries
+TableColumn.header.tag.discovery.name=Tag Suggestion
+TableColumn.header.tag.discovery.torrent=Torrent Suggested For
+TableColumn.header.tag.discovery.addedon=Found On
+TagDiscoveriesView.menu.tagit=Assign Tag
+mdi.entry.tagdiscovery={tag.discovery.view.heading}
+Generic.words.scan=Scan
+
+tags.view.infobar.text1=Discover Tags 
+tags.view.infobar.text2=View and assign tags assigned by other users with the Tag Discoveries view, located in the View menu.
+tag.discovery.view.options=Options
+
+label.classic=Classic
+label.beta=Beta
+label.anon=Anonymous
+label.anon.i2p=Anonymous (I2P)
+label.chat=Chat
+label.mute=Mute
+label.listen=Listen
+label.pin=Pin
+label.unpin=Unpin
+label.private.chat=Private Chat
+label.public.chat=Public Chat
+label.anon.chat=Anonymous Chat
+label.public={subs.prop.is_public}
+label.help=Help
+azbuddy.beta.enabled=Beta Enabled
+azbuddy.beta.msgsync.missing=You need to install the 'Message Sync' plugin
+
+azbuddy.dchat.link.url=http://wiki.vuze.com/w/Decentralized_Chat
+azbuddy.dchat.info=Decentralized chat allows you to talk to other Vuze users directly and, optionally, anonymously.
+azbuddy.dchat.decentralized=Decentralized Chat
+azbuddy.dchat.decentralized.enabled={azbuddy.dchat.decentralized} Enabled
+azbuddy.dchat.public.nick=Shared public nickname
+azbuddy.dchat.anon.nick=Shared anonymous nickname
+azbuddy.dchat.public.beta=Public beta chat
+azbuddy.dchat.anon.beta=Anonyous beta chat (I2P)
+azbuddy.dchat.custom=Custom Channels
+azbuddy.dchat.create.join.key=Create/join custom channel: key
+azbuddy.dchat.open.in.vuze=Open In Vuze
+azbuddy.dchat.open.in.browser=Open In Browser
+azbuddy.dchat.nick.shared=Nickname: shared
+azbuddy.dchat.pc.enable=Enable private chat
+azbuddy.dchat.pc.pinned.only=Only accept chats from pinned participants
+azbuddy.dchat.anon.share.endpoint=Share anonymous torrent and chat destination
+azbuddy.dchat.anon.share.endpoint.info=Unfortunately using separate destinations is currently unreliable
+azbuddy.dchat.node.status=%1%2Nodes=%3, Requests=%4
+azbuddy.dchat.user.status=Online: %1, Posted: %2
+azbuddy.dchat.status.noplugin=Error: Message Sync Plugin not installed
+azbuddy.dchat.status.nohandler=Error: No message handler available
+azbuddy.dchat.status.notavail=No status available yet 
+azbuddy.dchat.status.destroyed=Destroyed
+azbuddy.dchat.copy.channel.key=Channel Key
+azbuddy.dchat.copy.channel.url=Channel URL
+azbuddy.dchat.copy.channel.pk=Public Key
+azbuddy.dchat.rchans=Related Channels
+azbuddy.dchat.rchans.managed=New Managed Channel
+azbuddy.dchat.rchans.ro=New Read-Only Channel
+azbuddy.dchat.ro=Read only channel
+azbuddy.dchat.copy.channel.export=Channel Backup
+azbuddy.dchat.cannel.import=Channel Restore
+azbuddy.dchat.import.data=Previously exported backup data
+azbuddy.dchat.nick=Nick
+azbuddy.dchat.rchans.anon=Anonymous Channel
+azbuddy.dchat.rchans.pub=Public Channel
+azbuddy.dchat.general.chats=General Chats
+azbuddy.dchat.fave.chats=Favorite Chats
+azbuddy.dchat.noti.sound=Play a sound when a message is received
+tag.azbuddy.dchat.shares=Chat Shares
+
+label.set.share.ratio={set.share.ratio.win.title}...
+set.share.ratio.win.title=Set Share Ratio
+set.share.ratio.win.msg=Setting a share ratio adjusts download/upload totals as necessary
+label.pop.out=Pop out
+label.shared=Shared
+label.chat.type=Chat Type
+label.favorites=Favorites
+label.announce=Announce
+label.tag.selection=Tag Selection
+label.fave=Favorite
+label.public.short=P
+label.anon.short=A
+label.none.assigned=None Assigned
+label.pinned.only=Pinned Only
+ConfigView.option.dm.dblclick.launch.qv={MainWindow.menu.quick_view} / {iconBar.run}
+
+azbuddy.dchat.ftux.welcome=Welcome to Chat
+azbuddy.dchat.ftux.footer=Any use of Vuze\u00AE or Vuze+\u2122 that violates the rights of any person or entity is not allowed.
+faq.legal.url=http://wiki.vuze.com/w/FAQ_Legal
+label.accept=Accept
+label.no.messages=No Messages
+label.right.click.for.options=Right-click for options
+azbuddy.dchat.save.messages=Save Messages Across Restarts
+label.see.x.for.help=See %1 for help
+label.open.all=Open All
+chats.view.heading=Chat Overview
+mdi.entry.chatsoverview={chats.view.heading}
+TableColumn.header.chat.name=Chat Name
+TableColumn.header.chat.msg.out=Message Waiting
+TableColumn.header.chat.status={TableColumn.header.status}
+TableColumn.header.chat.fave={label.fave}
+TableColumn.header.chat.user.count=User Count
+TableColumn.header.chat.user.count.info=Estimated number of users online (excluding you)
+TableColumn.header.chat.msg.count=Message Count
+TableColumn.header.chat.msg.count.info=Message count from other users (not your own)
+chats.view.infobar.text1=Chat Overview 
+chats.view.infobar.text2=This view shows information about the various chats that you are monitoring/participating in. Visit the Wiki for more information by <a href="{azbuddy.dchat.link.url}">clicking here...</a>
+azbuddy.dchat.copy.rss.url=RSS URL
+azbuddy.dchat.share.fail.title=Sharing Failed
+azbuddy.dchat.share.fail.msg=Failed to share %1:\n\n%2
+
+label.spam=Spammer
+label.not.spam=Not Spammer
+subscriptions.config.ratelimits=Rate limits: list of <host>=<minimum minutes> pairs, comma separated
+subscriptions.enter.freq=Enter refresh frequency in minutes
+config.external.browser.non.pub=Always use the %1 for non-public content
+aznettorbrowser.install=Install Tor Browser Plugin
+aznettorbrowser.install.subtitle=Installing Tor Browser Plugin
+aznettorbrowser.install.description=Please wait while the Tor Browser Plugin is installed
+aznettorbrowser.install.text=Install the Tor Browser Plugin to support browsing .onion and .i2p web content?
+
+azneti2phelper.install=Install I2P Plugin
+azneti2phelper.install.subtitle=Installing I2P Plugin
+azneti2phelper.install.description=Please wait while the I2P Plugin is installed
+azneti2phelper.install.text=Install the I2P Plugin to support access to the I2P anonymous network?\n\n<a href="http://wiki.vuze.com/w/I2PHelper_HowTo">Click here for more information</a>\n\nNote that on installation it can take several minutes for the\nnetwork to become available - be patient!
+azbuddy.dchat.not.installed=Support for anonymous chat is not currently installed
+ConfigView.section.file.torrent.autoskipfiles=Extensions of files to auto-skip when adding a torrent [; separated]
+FilesView.hide.dnd=Hide files not selected for download
+label.comments=Comments
+torrent.comments.title=Comments/Ratings for '%1'
+torrent.comments.info=Comments and ratings are retrieved from other users that have downloaded this torrent.\nThis can take some time, especially if you have just started Vuze.\n\nActive networks: [%1] - change this via the 'Connection Options' settings.
+label.checking.comments=Checking availability of user comments and ratings
+label.searching=Searching...
+torrent.comment.rat1=Average Rating: %1 (scores: %2)
+torrent.comment.rat2=Comment(s): %1
+torrent.comment.azrating.install=Rating Plugin is not installed - see Tools->Plugins->Installation Wizard
+torrent.comment.azmsgsync.install=Message Sync Plugin is not installed or chat is disabled - see Tools->Plugins->Friends
+
+azmsgsync.install.text=The 'Message Sync' Plugin is required for decentralized chat [disabled if already installed]
+azmsgsync.install=Install Message Sync Plugin
+azmsgsync.install.subtitle=Installing Message Sync Plugin
+azmsgsync.install.description=Please wait while the Message Sync Plugin is installed
+azmsgsync.install.ok.msg=Message Sync Plugin installed successfully
+azmsgsync.install.fail.msg=Message Sync Plugin installation failed: %1
+azbuddy.dchat.shared.tooltip=Shared means that the same nick is used across all channels by default\nPublic and Anonymous channels have separate default settings. 
+label.keep.alive=Keep Alive
+azbuddy.dchat.open.i2p.magnet=Open I2P-Only Magnet In Vuze
+azbuddy.dchat.open.magnet=Open Magnet In Vuze
+azbuddy.dchat.copy.i2p.magnet=Copy I2P-Only Magnet To Clipboard
+azbuddy.dchat.copy.magnet=Copy Magnet To Clipboard
+azbuddy.dchat.log.messages=Log Messages To File
+azbuddy.dchat.ui.max.lines=Max messages per chat window
+azbuddy.dchat.ui.max.kb=Max characters per chat window [KB]
+azbuddy.dchat.rchans.rand=Random Sub-Channel
+label.copy.to.clipboard=Copy To Clipboard
+devices.xcode.tagshare=Share Transcodes With Tag
+label.tracker.selection=Tracker Selection
+
+MyTorrentsView.menu.downSpeedLimit=Download Speed Limit
+MyTorrentsView.menu.upSpeedLimit=Upload Speed Limit
+ConfigView.section.style.ShowFancyMenu=Show Fancy Menu (Requires Restart)
+label.reset.piece=Reset Piece
+ConfigView.section.file.merge.same.size=Attempt to merge incomplete files that are the same size
+TableColumn.header.mergeddata=Swarm Merge
+TableColumn.header.mergeddata.info=Amount of data merged into this download via swarm merging
+chat.view.create.chat=Create Chat
+chat.view.enter.key.title=Enter Channel Key
+chat.view.enter.key.msg=Enter the channel key for your chat
+MainWindow.menu.vote=Suggest a Feature
+vote.vuze.url=http://vote.vuze.com/
+label.quick.config=Quick Config
+
+FancyMenu.Header.Control=Control
+FancyMenu.Header.Content=Content
+FancyMenu.Header.Organize=Organize
+FancyMenu.Header.Social=Social
+FancyMenu.Header.Other=Other
+tag.search=Search Community...
+
+TagAddWindow.public.info=Tag sharing will help other users organize their downloads.
+TagAddWindow.subtitle=You can manage all your tags and categories via View->{tags.view.heading}, and discover new tags via View->{tag.discovery.view.heading}.
+TagAddWindow.public.checkbox=Share tag anonymously with community
+
+azneti2phelper.install.reason.decentralised=The torrent you are adding is purely decentralized. It's possible that this torrent's swarm is only on I2P.
+azneti2phelper.install.reason.i2ptracker=The torrent you are adding has an I2P tracker.
+
+tagtype.discovered=Discovered Tag
+MyTorrentsSubView.title.full=Torrents
+azbuddy.dchat.auto.mute=Auto Mute New Users
+
+TagSettingsView.title=Settings
+TagSettings.viewInSideBar=View In Sidebar
+
+Peers.column.network=Network
+TableColumn.header.sizewithdnd=Torrent Size
+TableColumn.header.sizewithdnd.info=Size of torrent's data, if you were to download all the files
+
+menu.pop.out=Pop Out...
+menu.copy.hash.to.clipboard=Copy Hash To Clipboard
+view.one.download.only=Select one download to display this view
+MyTorrentsView.menu.browse={azbuddy.dchat.open.in.browser}
+
+config.browser.internal.disable=Disable all use of the internal browser.
+config.browser.internal.disable.info=This will impact all views that use it, although some can be switched to use an external browser - see above
+browser.internal.disabled.info=The internal browser is disabled.\n\nThis is either because you explicitly disabled it via\n\n\tTools->Options->Interface->Display: Internal Browser\n\nor it has automatically been disabled due to the detection of crashes seemingly caused by the component.\n\nThe current link is shown below (the page may not display correctly due to client dependencies)
+browser.internal.auto.disabled=The internal browser has been automatically disabled to prevent Vuze from crashing.\n\nYou can re-enable this via Tools->Options->Interface->Display: Internal Browser\n\nFor more information see <A HREF="http://wiki.vuze.com/w/Vuze_disappears#SWT_Browser_Issues">The Wiki</A>
+
+TableColumn.header.DateTorrentLastActive=Last Active
+TableColumn.header.DateTorrentLastActive.info=Date that the torrent was last active.  Doesn't update until the torrent is queued or stopped.
+
+MyTorrentsView.menu.editTrackerMerge=Edit Tracker URLs Together
+label.exec.on.assign=Execute On Assign
+ConfigView.option.dm.dblclick.open.browser={MyTorrentsView.menu.browse}
+library.launch.web.in.browser=Override this for downloads contain a website and open in browser
+library.launch.web.in.browser.anon=Browse anonymously
+library.launch.web.in.browser.dir.list=Always Show File List
+
+tag.constraints.info=See <A HREF="https://wiki.vuze.com/w/Tags#Constraints">Tag Constraints</A> wiki page
+label.copy.url.to.clip=Copy URL To Clipboard
+
+archivedlsview.view.heading=Archived Downloads
+mdi.entry.archiveddownloadsview={archivedlsview.view.heading}
+MyTorrentsView.menu.archive=Archive
+MyTorrentsView.menu.restore={br.restore}
+MyTorrentsView.menu.restore.and=Restore And...
+ArchivedDownloadsView.header={archivedlsview.view.heading}
+label.restored=Restored
+archive.info.title=Downloads Archived
+archive.info.text=The selected downloads have been archived and are available under the 'Archived Downloads' view available from the 'View' menu.\n\nSee <a href=\"http://wiki.vuze.com/w/Archiving_Downloads\">the Wiki</a> for more information.
+archive.failed.title=Download Archive Failed
+archive.failed.text=One or more downloads were not in an archivable state.\n\nSee <a href=\"http://wiki.vuze.com/w/Archiving_Downloads\">the Wiki</a> for more information.
+
+TableColumn.header.archive.date=Archive Date
+
+ArchivedFilesView.title.full={FilesView.title.full}
+ArchivedFilesView.title.short={FilesView.title.short}
+ArchivedFilesView.name={FilesView.name}
+ArchivedFilesView.size={FilesView.size}
+v3.deleteContent.or.archive=Alternatively, cancel this operation and archive your downloads for easy retrieval later - see 'Archived Downloads' in the View menu
+archivedls.view.infobar.text1=Archived Downloads 
+archivedls.view.infobar.text2=Keep your completed and stopped downloads handy by archiving them - use the right-click menu to archive; restore to the Library with a single click.\nArchived downloads use minimal resources within Vuze. For more information <a href=\"http://wiki.vuze.com/w/Archiving_Downloads\">click here to visit the Wiki...</a>
+
+UpdateWindow.columns.currentversion={label.current}
+
+menu.bencode.to.json=Convert BEncoded File To JSON...
+menu.json.to.bencode=Convert JSON File To BEncoded...
+bencode.file.browse=Open BEncoded File
+json.file.browse=Open JSON File
+ConfigView.label.deletetorrents=Delete original .torrent files after download added 
+
+azbuddy.dchat.ui.standalone.windows=Use independent windows for pop-out chats
+azbuddy.dchat.ui.hide.ratings=Hide automatically generated ratings, comments and swarm merge messages
+
+label.copy.uri.to.clip=Copy URI To Clipboard
+
 #PLEASE LEAVE ME AT VERY BOTTOM!
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_bg_BG.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_bg_BG.properties
index d49618b..a1e2a5a 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_bg_BG.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_bg_BG.properties
@@ -1258,6 +1258,8 @@ MyTorrentsView.menu.setSpeed.disable=\u0411\u0435\u0437 \u043a\u0430\u0447\u0432
 MyTorrentsView.menu.setSpeed.disabled=\u0411\u0435\u0437
 MyTorrentsView.menu.setSpeed.in=\u0432
 MyTorrentsView.menu.setSpeed.slots=\u0433\u043d\u0435\u0437\u0434\u0430 \u043f\u043e
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=\u041c\u0430\u043a\u0441. \u041a\u0447.
 GeneralView.label.maxuploadspeed.tooltip=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u043d\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442 \u043d\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e]
 MyTorrents.items.UpSpeedLimit.disabled=\u041d\u044f\u043c\u0430 \u043a\u0430\u0447\u0432\u0430\u043d\u0435
@@ -2663,16 +2665,7 @@ ConfigView.label.systray=\u0421\u0438\u0441\u0442\u0435\u043c\u0435\u043d \u043a
 ConfigView.label.systray._mac=\u0418\u043a\u043e\u043d\u0430 \u0432 \u043b\u0435\u043d\u0442\u0430\u0442\u0430 \u043d\u0430 \u0441\u044a\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u0442\u043e
 ConfigView.section.interface.legacy=\u041f\u0440\u0435\u0434\u0438\u0448\u0435\u043d
 v3.MainWindow.menu.contentnetworks.manage=&\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 HD \u043c\u0440\u0435\u0436\u0438
-azbuddy.ui.table.loc_cat=\u0418\u0437\u0445. \u043a\u0430\u0442.
-azbuddy.ui.table.rem_cat=\u0412\u0445. \u043a\u0430\u0442.
-azbuddy.ui.menu.cat=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438
-azbuddy.ui.menu.cat.share=\u0412\u043a\u043b\u044e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u0430\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442\u0438 \u0441 \u0434\u0440\u0443\u0436\u043a\u0438
-azbuddy.ui.menu.cat.set=\u0412\u044a\u0432\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438
-azbuddy.ui.menu.cat.set_msg=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438 \u0441\u044a\u0441 \u0437\u0430\u043f\u0435\u0442\u0430\u0438, \u0438\u043b\u0438 '\u0432\u0441\u0438\u0447\u043a\u0438'
-azbuddy.ui.menu.cat_subs=\u0410\u0431\u043e\u043d\u0430\u043c\u0435\u043d\u0442
 subs.prop.update_period=\u041f\u0435\u0440\u0438\u043e\u0434 \u043d\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f
-azbuddy.enable_cat_pub=\u041e\u0431\u0449\u043e\u0434\u043e\u0441\u0442\u044a\u043f\u043d\u0438 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0437\u0430 \u043a\u043e\u0438\u0442\u043e \u043c\u043e\u0433\u0430\u0442 \u0434\u0430 \u0441\u0435 \u0430\u0431\u043e\u043d\u0438\u0440\u0430\u0442 \u0432\u0441\u0438\u0447\u043a\u0438 \u0434\u0440\u0443\u0436\u043a\u0438 (',' \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438) 
-azbuddy.ui.table.read_cat=\u041f\u0440\u043e\u0447\u0435\u0442\u0435\u043d\u0438 \u043a\u0430\u0442.
 TableColumn.header.#=\u2116
 TableColumn.header.#.info=\u2116 \u043d\u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u044f/\u043f\u043e\u0434\u0440\u0435\u0436\u0434\u0430\u043d\u0435
 TableColumn.header.category.info=\u0418\u043c\u0430 \u043d\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f, \u043a\u044a\u043c \u043a\u043e\u044f\u0442\u043e \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438 \u0442\u043e\u0440\u0435\u043d\u0442\u044a\u0442
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ca_AD.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ca_AD.properties
index 020e7d7..7c44352 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ca_AD.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ca_AD.properties
@@ -1286,6 +1286,8 @@ MyTorrentsView.menu.setSpeed.disable=Inhabilita la c\u00e0rrega
 MyTorrentsView.menu.setSpeed.disabled=Inhabilitat
 MyTorrentsView.menu.setSpeed.in=entrada
 MyTorrentsView.menu.setSpeed.slots=canals de
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=M\u00e0x. c\u00e0rrega
 GeneralView.label.maxuploadspeed.tooltip=velocitat m\u00e0xima de c\u00e0rrega [0: il\u00b7limitat]
 MyTorrents.items.UpSpeedLimit.disabled=No carreguis
@@ -2700,13 +2702,7 @@ ConfigView.label.systray=Safata del sistema
 ConfigView.label.systray._mac=Icona de la barra d'estat
 ConfigView.section.interface.legacy=Llegat
 v3.MainWindow.menu.contentnetworks.manage=&Gestiona les xarxes HD
-azbuddy.ui.menu.cat=Categories 
-azbuddy.ui.menu.cat.share=Habilita les subscripcions amb amics
-azbuddy.ui.menu.cat.set=Introdu\u00efu les categories
-azbuddy.ui.menu.cat.set_msg=Separeu les categories a la llista per comes, o 'All' ('Tots')
-azbuddy.ui.menu.cat_subs=Subscriu-m'hi
 subs.prop.update_period=Per\u00edode d'actualitzaci\u00f3
-azbuddy.enable_cat_pub=Categories p\u00fabliques a les quals TOTS els amics es poden subscriure (separades per ',') 
 TableColumn.header.#=Nre.
 TableColumn.header.#.info=N\u00famero de posici\u00f3/ordre
 TableColumn.header.category.info=Nom de la categoria a la qual pertany el torrent
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_cs_CZ.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_cs_CZ.properties
index df1e081..0cbdc32 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_cs_CZ.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_cs_CZ.properties
@@ -1231,6 +1231,8 @@ MyTorrentsView.menu.setSpeed.disable=Zak\u00e1zat Stahov\u00e1n\u00ed
 MyTorrentsView.menu.setSpeed.disabled=Zak\u00e1zan\u00fd
 MyTorrentsView.menu.setSpeed.in=v
 MyTorrentsView.menu.setSpeed.slots=pozice 
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Limit odes.
 GeneralView.label.maxuploadspeed.tooltip=Maxim\u00e1ln\u00ed rychlost odes\u00edl\u00e1n\u00ed [0 : neomezen\u011b]
 MyTorrents.items.UpSpeedLimit.disabled=\u017d\u00e1dn\u00e9 odes\u00edl\u00e1n\u00ed
@@ -2590,16 +2592,7 @@ ConfigView.label.systray=Syst\u00e9mov\u00e1 Li\u0161ta
 ConfigView.label.systray._mac=Ikona Li\u0161ty Stavu
 ConfigView.section.interface.legacy=Zastaral\u00e9
 v3.MainWindow.menu.contentnetworks.manage=Spravovat &HD S\u00edt\u011b
-azbuddy.ui.table.loc_cat=Odeslan\u00e9 Kat
-azbuddy.ui.table.rem_cat=Doru\u010den\u00e9 Kat
-azbuddy.ui.menu.cat=Kategorie
-azbuddy.ui.menu.cat.share=Povolit odb\u011bry s p\u0159\u00e1teli
-azbuddy.ui.menu.cat.set=Zadejte kategorie
-azbuddy.ui.menu.cat.set_msg=Seznam kategori\u00ed odd\u011blen\u00fdch \u010d\u00e1rkou, nebo 'V\u0161e'
-azbuddy.ui.menu.cat_subs=Po\u017e\u00e1dat o odb\u011br
 subs.prop.update_period=Interval aktualizace
-azbuddy.enable_cat_pub=Ve\u0159ejn\u00e9 kategorie, kter\u00e9 V\u0160ICHNI Va\u0161i p\u0159\u00e1tel\u00e9 mohou odeb\u00edrat (odd\u011blen\u00e9 '.')
-azbuddy.ui.table.read_cat=P\u0159e\u010dten\u00e1 Kat
 TableColumn.header.#=\u010c.
 TableColumn.header.#.info=\u010c\u00edslo Pozice/Po\u0159ad\u00ed
 TableColumn.header.category.info=Jm\u00e9no kategorie, do kter\u00e9 torrent pat\u0159\u00ed
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_da_DK.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_da_DK.properties
index ab81e00..2763ff2 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_da_DK.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_da_DK.properties
@@ -1253,6 +1253,8 @@ MyTorrentsView.menu.setSpeed.disable=Deaktiver Upload
 MyTorrentsView.menu.setSpeed.disabled=Deaktiveret
 MyTorrentsView.menu.setSpeed.in=i
 MyTorrentsView.menu.setSpeed.slots=slots af
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Maksimum Op
 GeneralView.label.maxuploadspeed.tooltip=maksimum upload hastighed (0 = ubegr\u00e6nset)
 MyTorrents.items.UpSpeedLimit.disabled=Ingen Upload
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_de_DE.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_de_DE.properties
index cce1768..4c4f62c 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_de_DE.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_de_DE.properties
@@ -1196,6 +1196,8 @@ MyTorrentsView.menu.setSpeed.disable=Deaktiviere Upload
 MyTorrentsView.menu.setSpeed.disabled=Deaktiviert
 MyTorrentsView.menu.setSpeed.in=in 
 MyTorrentsView.menu.setSpeed.slots=slots von
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Up-Limit
 GeneralView.label.maxuploadspeed.tooltip=max. Upload-Geschwindigkeit
 MyTorrents.items.UpSpeedLimit.disabled=Kein Upload
@@ -2514,16 +2516,7 @@ ConfigView.label.autoopen.detailstab=Automatisches \u00d6ffnen der Details, wenn
 ConfigView.label.systray=
 ConfigView.label.systray._mac=Statusleisten-Symbol
 v3.MainWindow.menu.contentnetworks.manage=&Verwalte HD-Netzwerke
-azbuddy.ui.table.loc_cat=Kat. raus
-azbuddy.ui.table.rem_cat=Kat. rein
-azbuddy.ui.menu.cat=Kategorien
-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
 subs.prop.update_period=Aktualisierungsperiode
-azbuddy.enable_cat_pub=\u00d6ffentliche Kategorien, die ALLE Freunde abonnieren k\u00f6nnen (getrennt durch Komma)
-azbuddy.ui.table.read_cat=Kat. gelesen
 TableColumn.header.#.info=Position/Ordnungsnummer
 TableColumn.header.category.info=Name der Kategorie des Torrents
 TableColumn.header.DateCompleted.info=Zeitpunkt der Vervollst\u00e4ndigung des Downloads
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_es_ES.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_es_ES.properties
index b7f9ed0..fe4b16d 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_es_ES.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_es_ES.properties
@@ -45,7 +45,7 @@ MainWindow.dialog.choose.savepath_forallfiles=Selecciona la carpeta para las des
 MainWindow.status.latestversion=Ultima versi\u00f3n
 MainWindow.status.latestversion.clickupdate=Clic para actualizar
 MainWindow.status.unknown=Desconocido
-MainWindow.status.checking=Comprobando
+MainWindow.status.checking=comprobando
 TableColumn.header.name=Nombre
 TableColumn.header.size=Tama\u00f1o
 TableColumn.header.done=Completado
@@ -402,7 +402,7 @@ configureWizard.nat.test=Probar
 configureWizard.nat.testing=Probando puerto
 configureWizard.nat.ok=\u00a1Correcto!
 configureWizard.nat.ko=Error de NAT
-configureWizard.nat.unable=Prueba imposible: O el puerto no es v\u00e1lido, o ha fallado el servicio de prueba ha fallado.\nPuede ser que otra aplicaci\u00f3n ya estuviera usando este puerto
+configureWizard.nat.unable=Prueba imposible: O el puerto no es v\u00e1lido, o el servicio de prueba ha fallado.\nPuede ser que otra aplicaci\u00f3n ya estuviera usando este puerto.
 configureWizard.file.title=Torrents/archivos
 configureWizard.file.message1=Vuze guardar\u00e1 los .torrent abiertos en una carpeta espec\u00edfica, puedes elegir esta carpeta aqu\u00ed:
 configureWizard.file.path=Ruta
@@ -457,7 +457,7 @@ importTorrentWizard.process.unknownfail.title=Error inesperado
 ConfigView.label.bindip=Vincularse a la direcci\u00f3n IP local o interfaz
 ConfigView.label.xfs.allocation=Asignar espacio para los nuevos archivos mediante un m\u00e9todo espec\u00edfico al sistema de archivos XFS
 ConfigView.label.xfs.allocation.tooltip=Por favor, aseg\u00farese de que /usr/sbin/xfs_io est\u00e1 adecuadamente instalado en su sistema. En la mayor\u00eda de las distrbuciones Linux est\u00e1 incluida en el paquete "xfsprogs".
-xfs.allocation.xfs_io.not.found=La asignaci\u00f3n de espacio XFS ha fallado porque no se puede ejecutar /usr/sbin/xfs_io. Aseg\u00farese de que est\u00e1 adecuadamente instalado en su sistema. El error original fu\u00e9 : "%1".
+xfs.allocation.xfs_io.not.found=La asignaci\u00f3n de espacio XFS ha fallado porque no se puede ejecutar /usr/sbin/xfs_io. Aseg\u00farate de que est\u00e1 adecuadamente instalado en tu sistema. El error original fue \u00ab%1\u00bb.
 ConfigView.label.zeronewfiles=Al crear nuevos archivos, reservar espacio y rellenarlo con ceros.
 ConfigView.label.zeronewfiles.tooltip=Minimiza la fragmentaci\u00f3n
 ConfigView.section.stats=Estad\u00edsticas
@@ -1218,6 +1218,8 @@ MyTorrentsView.menu.setSpeed.disable=Desactivar subida
 MyTorrentsView.menu.setSpeed.disabled=Desactivado
 MyTorrentsView.menu.setSpeed.in=en
 MyTorrentsView.menu.setSpeed.slots=puestos de
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=L\u00edmite de subida
 GeneralView.label.maxuploadspeed.tooltip=velocidad m\u00e1xima de subida [0: ilimitada]
 MyTorrents.items.UpSpeedLimit.disabled=No enviar
@@ -2524,6 +2526,7 @@ externalLogin.auth_method_proxy=Usa m\u00e9todo de captura de galletas extendido
 externalLogin.wait=Cargando p\u00e1gina; por favor, espere...
 TableColumn.menu.date_added.time=Mostrar u ocultar fecha
 sidebar.VuzeHDNetwork=Red Vuze HD
+subs.prop.next_scan=Pr\u00f3ximo escaneo
 subs.prop.assoc=Asociaciones
 subs.prop.version=Versi\u00f3n
 subscriptions.column.name=Suscripci\u00f3n
@@ -2698,11 +2701,13 @@ device.itunes.install_problem=Parece que hay un problema con la integraci\u00f3n
 devices.downloading=Descargando
 TableColumn.header.duration=Duraci\u00f3n
 TableColumn.header.resolution=Resoluci\u00f3n
+devices.xcode.autoStart=Autoiniciar cuando sea necesario
 option.askeverytime=Preguntar siempre
 option.rememberthis=Recordar esta opci\u00f3n
 devices.associate=Asociar con
 devices.associate.already=Ya asociado
 devices.always.cache=Memorizar archivos no transcodificados
+devices.choose.device.title=Selecciona un disp. de reproducci\u00f3n para este v\u00eddeo:
 devices.choose.profile.info.title.selected=%1 detalles:
 device.view.heading=Medios para %1
 devices.choose.device.info.title=Info de dispositivo
@@ -2831,10 +2836,12 @@ Trackers.column.updatein.info=Siguiente actualizaci\u00f3n en
 tps.status.available=Disponible
 tps.status.unavailable=No disponible
 tps.lan.details=%1 clientes locales descubiertos
+tps.pex.details=Conectado a %1 pares (pendientes: pex=%2, otros=%3)
 tps.tracker.cache=Cach\u00e9 de pares
 tps.tracker.cache1=Cach\u00e9 de pares: usado=%1
 dht.status.disabled=Deshabilitada; base de datos distribuida no disponible
 tps.type.incoming=Entrante
+tps.incoming.details=Actual: TCP=%1, UDP=%2; total=%3
 tps.type.plugin=Complemento
 ConfigView.label.autoadjust=Ajustar autom\u00e1ticamente estas opciones bas\u00e1ndose en la veloc. de conexi\u00f3n
 ConfigView.label.start=Inicio
@@ -2856,6 +2863,7 @@ ConfigView.label.pauseresume=Autopausa/reanudar
 update.now.title=Se necesita actualizaci\u00f3n
 update.now.desc=Vuze necesita aplicar actualizaciones para completar la migraci\u00f3n.\n\nDespu\u00e9s de cerrar este di\u00e1logo Windows podr\u00eda preguntarte si completar el proceso.\n\nNO se requerir\u00e1 reiniciar Vuze.
 ConfigView.label.jvm=Opciones de Java
+platform.jvmopt.sunonly=Solo se soportan Sun/Oracle JVM (vendedor actual=%1)
 platform.jvmopt.configerror=No pueden administrarse las opciones JVM por un error de configuraci\u00f3n
 platform.jvmopt.nolinkfile=No pueden administrarse las opciones JVM porque la migraci\u00f3n no est\u00e1 completa
 platform.jvmopt.nolink=No pueden administrarse las opciones JVM porque la configuraci\u00f3n actual no lo permite
@@ -3057,6 +3065,7 @@ ConfigView.section.style.units=Mostrar unidades
 ConfigView.section.style.CatInSidebar=Mostrar categor\u00edas en la barra lateral
 library.category.header=Categor\u00eda \u00ab%1\u00bb
 device.import.title=\u00bfImportar dispositivo?
+device.import.desc=\u00bfEst\u00e1s seguro de querer importar el disp. \u00ab%1\u00bb?
 device.import.dup.title=Duplicar dispositivo
 device.import.dup.desc=Dispositivo '%1' ya presente.
 stream.analysing.media=Analizando medios
@@ -3253,6 +3262,7 @@ label.con_prob=Problemas de conexi\u00f3n
 proxy.info.title=Info de proxy
 proxy.socks.bad.incoming=\u00a1Conexiones entrantes sin proxy detectadas!
 wizard.newtorrent.showtorrent=Ir al archivo torrent generado
+ConfigView.section.proxy.show_icon.flag.incoming=Mostrar conexiones internas no locales y no SOCKS como estado de error
 label.connections=Conexiones
 label.routing=Enrutamiento
 label.route=Ruta
@@ -3264,6 +3274,7 @@ label.missing=Faltante
 ConfigView.section.file.subfolder.dnd=Mover archivos no seleccionados para descarga en subcarpeta
 ConfigView.label.showuptime=Mostrar tiempo de subida
 devices.copy.device.auto=Copiar archivos a dispositivo autom\u00e1ticamente
+devices.xcode.autoCopy.device=Copiar a dispositivo autom\u00e1ticamente
 devices.info.copypending3=%1 archivo(s) en espera para copiar; habilita autocopiado o selecciona copia manual
 label.num_selected=%1 seleccionada/s
 MainWindow.menu.transfers.pausetransfersfor=Pausar durante...
@@ -3273,12 +3284,17 @@ dialog.pause.for.period.text2=Autorreanudaci\u00f3n activa: %1 restante...
 Trackers.column.last_update=\u00daltima actualizaci\u00f3n
 pairing.srp.state=Estado: %1
 pairing.srp.setpw.doit=Cambiar
+pairing.srp.pw.req=Contrase\u00f1a requerida: \u00a1nada va a funcionar sin esto!
 pairing.srp.registering=Registrando...
 security.crypto.pw.title=Introducir contrase\u00f1a
 label.more.info.here=Clica para m\u00e1s informaci\u00f3n
 label.num_queued=%1 en cola
 ConfigView.section.connection.group.webseed=Semillas web/HTTP
+ConfigView.section.connection.webseed.act.on.avail=Activar semillas Web/HTTP para descargar cuando haya poca disponibilidad
 stats.snapshot.group=Instant\u00e1nea
+stats.longterm.group=Largo plazo
+ConfigView.label.info.in.window.title=Mostrar \u00edndices actuales, etc., en la barra de t\u00edtulo
+ConfigView.label.hap=M\u00e1scara t\u00e9rmino descarga
 ConfigView.label.hap.tooltip=Ocultar trozo completado
 Button.swarmit=\u00a1Al enjambre!
 show.config.changes=Mostrar cambios de configuraci\u00f3n...
@@ -3364,4 +3380,51 @@ menu.selectfilesinfolder=Selec. todos los archivos en %1
 label.current=Actual
 label.limit=L\u00edmite
 label.showhide.tag=Mostrar/ocultar etiqueta/s
-# The remaining keys were not in MessagesBundle.properties
+label.dismiss.all=Descartar todos
+ConfigView.label.show.win.on.add=Mostrar la ventana principal cuando otra aplicaci\u00f3n a\u00f1ada otra descarga
+label.current_ip=Direcci\u00f3n IP actual:
+label.trackers=Rastreadores
+label.untagged=Sin etiquetas
+OpenTorrentFile.column.size.info=Peso
+OpenTorrentWindow.mb.invaliddefsave.title=Ubicaci\u00f3n no v\u00e1lida
+OpenTorrentWindow.mb.invaliddefsave.text=La ubicaci\u00f3n \u00ab%1\u00bb no es v\u00e1lida.\n\nCuando cierres este di\u00e1logo se te pedir\u00e1 que la cambies.\n\nLa ubicaci\u00f3n de guardado predeterminada puede ser configurada en Herramientas > Opciones > Archivos.
+Button.mark=Marcar
+Button.unmark=Desmarcar
+TableColumn.header.sessionup.info=Bytes subidos esta sesi\u00f3n
+TableColumn.header.sessiondown.info=Bytes descargados esta sesi\u00f3n
+ConfigView.section.file.showopentorrentoptions.sep=Usar un di\u00e1logo aparte por torrent
+label.n.will.be.downloaded=%1 ser\u00e1 descargado
+label.edit.trackers=Editar rastreadores
+label.replace=Remplazar
+apply.selected.template=Aplicar plantilla seleccionada
+OpenTorrentWindow.fileList.changeDestination.all=Cambiar destino de %1 archivos a la misma carpeta
+menu.max.share.ratio=Ratio de subida l\u00edmite (%1)...
+max.sr.window.message=Introducir ratio de subida l\u00edmite [0:desactivado]
+max.sr.window.title=Ratio de subida l\u00edmite
+label.reapply=Reaplicar
+ConfigView.section.security.resetcerts.warning.title=Aviso de p\u00e9rdida de datos
+TableColumn.header.sr_prog=Progreso de ratio de subida
+ConfigView.label.downloading.testTime=Per\u00edodo evaluaci\u00f3n velocidad descargar [s]
+ConfigView.label.downloading.reTest=Reevaluar descargas cada [min; 0=nunca]
+TableColumn.header.DownloadingRank=Rango de descarga
+tray.options=Opciones de barra
+ConfigView.label.enableSystrayToolTipNextETA=Mostrar pr\u00f3xima descarga en completarse
+menu.change.url=Cambiar URL...
+change.url.msg.title=Cambiar URL por \u00ab%1\u00bb
+TableColumn.header.readrate=Tasa de lectura
+TableColumn.header.readrate.info=Tasa de lectura de archivo
+label.rerequest.blocks=Resolicitar bloques
+config.internal.browser=Navegador interno
+config.internal.browser.info2=Se usa Internet Explorer predeterminadamente en Windows, Safari en Mac. Versiones *limitadas* de Firefox pueden usarse en su lugar; ver las opciones siguientes
+config.external.browser=Navegador externo
+config.external.browser.info1=El navegador externo se usa para mostrar contenido web fuera del cliente, en un explorador aparte, como p\u00e1ginas de detalles de resultados
+config.external.browser.info2=Tu navegador predeterminado suele usarse. Puedes cambiar esto para usar un navegador espec\u00edfico, o uno de un complemento (p. ej., el Tor Browser)
+config.external.browser.switch.info=Puedes alternar entre navegador interno y externo para algunas caracter\u00edsticas, aunque algo de funcionalidad podr\u00eda perderse
+config.external.browser.select=Selecci\u00f3n de navegador
+config.external.browser.prog=Ejecutable del navegador
+config.external.browser.test=Probar config. navegador externo
+config.external.browser.switch.feature=Caracter\u00edstica
+config.external.browser.switch.external=Externo
+config.external.browser.switch.implic=Implicaciones
+config.external.browser.switch.search=Resultados de b\u00fasqueda
+delete.partial.files=Cuando se elimina una descarga de la biblioteca, eliminar cualquier archivo parcial para aquellos seleccionados como \u00abNo descargar\u00bb o \u00abEliminar\u00bb
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_eu.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_eu.properties
index c0a8248..973545d 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_eu.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_eu.properties
@@ -1,3741 +1,4215 @@
-#There is a plugin to help with internationalizing these bundles at http://plugins.vuze.com/plugin_list.php
-MainWindow.menu.file.open.torrent=Torrent Agiria...
-Main.parameter.usage=Erabilera: java org.gudy.azureus2.cl.Nagusia [neurriak] "agiria.torrent" "gordetze helburua"
-Main.parameter.maxUploads=Geh aldibereko igoera zenbatekoa
-Main.parameter.maxSpeed=Geh igoera abiadura byte/seg-ko
-MainWindow.menu.file=&Agiria
-MainWindow.menu.file.open=&Ireki
-MainWindow.menu.file.create=&Torrent Berria...
-MainWindow.menu.file.create.fromfile=&Agiri &batetik
-MainWindow.menu.file.create.fromdir=Zuzenbide &batetik
-MainWindow.menu.file.export=E&sportatu XML Torrenta...
-MainWindow.menu.file.export.keybinding.mac=Meta+Shit+E
-MainWindow.menu.file.import=I&nportatu XML Torrenta...
-MainWindow.menu.file.closetab=Itxi &Hegatsa
-MainWindow.menu.file.closewindow=Itxi &Leihoa
-MainWindow.menu.file.exit=I&rten
-MainWindow.dialog.choose.file=Hautatu torrent agiria
-MainWindow.menu.file.folder=&Agiritegia...
-MainWindow.menu.file.folder.keybinding=Meta+Shift+0
-MainWindow.dialog.choose.folder=Hautatu torrent agiriaren zuzenbidea
-MainWindow.menu.view=&Ikusi
-MainWindow.menu.view.show=Erakutsi
-MainWindow.menu.view.mytorrents=&Liburutegia
-MainWindow.menu.view.open_global_transfer_bar=Eskualdaketa &Barra
-MainWindow.menu.view.configuration=A&ukerak...
-MainWindow.menu.view.console=Kontsola
-MainWindow.menu.view.allpeers=Hartzaile Guztiak
-MainWindow.menu.view.detailedlist=&Zerrenda Zehatza
-MainWindow.menu.closealldetails=Itxi &Xehetasun Guztiak
-MainWindow.menu.closealldownloadbars=Itxi &Jeisketa Barra Guztiak
-MainWindow.menu.language=&Hizkuntza
-ConfigView.section.language=Hizkuntza
-MainWindow.menu.window=&Leihoa
-MainWindow.menu.window.minimize=&Ikurtu
-MainWindow.menu.window.zoom=&Zooma
-MainWindow.menu.window.alltofront=Mugitu denak &aurrera
-MainWindow.menu.help=&Laguntza
-MainWindow.menu.help.about=Vuzeri buruz
-MainWindow.menu.torrent=T&orrenta
-MainWindow.about.title=Honi buruz
-MainWindow.about.section.system=Sistema
-MainWindow.about.internet.homepage=Vuze Webgunea
-MainWindow.about.internet.sourceforge=Sourceforge Egitasmoaren Webgunea
-MainWindow.about.internet.bugreports=Akatsen Jakinarazpena
-MainWindow.about.internet.forumdiscussion=Eztabaidaguneak
-MainWindow.about.internet.wiki=Vuzeren Wiki SEG
-MainWindow.dialog.choose.savepath=Hautatu gordetze helburua
-MainWindow.dialog.choose.savepath_forallfiles=Hautatu agiri GUZTIEN gordetze helburua
-MainWindow.status.latestversion=Azkena
-MainWindow.status.latestversion.clickupdate=Egin klik eguneratzeko
-MainWindow.status.unknown=ezezaguna
-MainWindow.status.checking=egiaztatzen
-MyTorrentsView.mytorrents=Liburutegia
-TableColumn.header.name=Izena
-TableColumn.header.size=Neurria
-TableColumn.header.done=Eginda
-TableColumn.header.done.info=Uneko eginkizunetik buruturiko ehunekoa
-TableColumn.header.status=Egoera
-TableColumn.header.status.info=Torrenta egiten ari dena
-TableColumn.header.seeds=Emaritzak
-TableColumn.header.seeds.info=Elkarketatutako emaritza Zenbatekoa (Zenbat emaritza guztira)
-TableColumn.header.peers=Hartzaileak
-TableColumn.header.peers.info=Zenbat hartzaile elkarketaturik (Zenbat hartzaile guztira)
-TableColumn.header.completed=Osatuta
-TableColumn.header.completed.info=Torrentaren jeisketa amaitu duten hartzailea zenbatekoa, aztarnariaren arabera
-TableColumn.header.downspeed=Jeisketa Abiadura
-TableColumn.header.upspeed=Igoera Abiadura
-TableColumn.header.eta=UED
-TableColumn.header.tracker=Aztarnari Egoera
-TableColumn.header.tracker.info=Aztarnariaren Egoera
-TableColumn.header.trackernextaccess=Hurrengo Aztarnariaren Atzipena
-TableColumn.header.trackernextaccess.info=Hurrengo aztarnariaren atzipena noiz gertatuko den
-TableColumn.header.priority=Lehentasuna
-TableColumn.header.priority.info=Torrentari ematen zaion banda zabalera finkatzen du
-TableColumn.header.seeds.fullcopycalc=%1 hartzailek onartutako %2 kopia oso
-MyTorrentsView.menu.showdetails=Erakutsi &Xehetasunak
-MyTorrentsView.menu.showdownloadbar=Erakutsi &Jeisketa Barra
-MyTorrentsView.menu.open=&Ireki Agiria
-MyTorrentsView.menu.setpriority=Ezarri &Lehentasuna
-MyTorrentsView.menu.setpriority.high=&Handia
-MyTorrentsView.menu.setpriority.low=&Txikia
-MyTorrentsView.menu.start=&Hasi
-MyTorrentsView.menu.stop=&Gelditu
-MyTorrentsView.menu.remove=K&endu
-MyTorrentsView.menu.changeTracker=Gehitu aztarnari URL-a(k)
-TrayWindow.menu.exit=I&rten
-TrayWindow.menu.show=&Erakutsi Vuze
-SystemTray.menu.exit=I&rten
-SystemTray.menu.closealldownloadbars=Itxi &Jeisketa Barra Guztiak
-SystemTray.menu.open_global_transfer_bar=Erakutsi Eskualdaketa Barra
-SystemTray.menu.show=&Erakutsi Vuze
-PeersView.ip=IP-a
-PeersView.ip.info=Hartzailearen IP-a
-PeersView.port=Ataka
-PeersView.port.info=Erabiltzen ari den ataka
-PeersView.T=ELK
-PeersView.T.info=L (tokikoa): zuk ezarri duzu elkarketa, R (hurrunekoa): hartzaileak ezarri du elkarketa.
-PeersView.T.L.tooltip=Zuk ezarri duzu elkarketa
-PeersView.T.R.tooltip=Hartzaileak ezarri du elkarketa
-PeersView.I1=I (Interesgarria hartzailearentzat)
-PeersView.I1.info=Interesaturik zaude beste hartzaile batek duen agirian?
-PeersView.C1=IT (Hartzaileak itota)
-PeersView.C1.info=Hartzaileak jeisketa galarazten badizu
-PeersView.pieces=Atalak
-PeersView.%=Jeitsitako Ehunekoa
-PeersView.downloadspeed=Jeisketa Abiadura
-PeersView.download=Jeisketa
-PeersView.download.info=Hartzailearengandik jeitsitakoa guztira.
-PeersView.I2=I (Interesgarria hartzailearentzat)
-PeersView.I2.info=Hartzailea zure agiriren batean interesaturik dago?
-PeersView.C2=IT (Hartzailea itotzen)
-PeersView.C2.info=Hartzaileari jeisketa galarazten badiozu
-PeersView.uploadspeed=Igoera Abiadura
-PeersView.uploadspeed.info=Zure igoera abiadura hartzailera
-PeersView.upload=Igoera
-PeersView.upload.info=Zure igoera osoa hartzailera.
-PeersView.statup=Bataz-besteko Igoera
-PeersView.statup.info=Hartzailearen igoera abiaduraren ustezko balioa
-PeersView.S=Baztertuta
-PeersView.S.info=Baztertuta: Hartzaile bat eskuz "baztertu" daiteke, edo berezgaitasunez (datuak abiadura geldoegian bidaltzeagatik)
-PeersView.downloadspeedoverall=Jeisketa Abiadura Guztira
-PeersView.optunchoke=Auk. Itogabe
-PeersView.client=Bezeroa
-PeersView.client.info=Hartzaileak erabiltzen duen BT bezero mota 
-PeersView.menu.snubbed=&Errefusatuta
-PeersView.title.short=Hartzaileak
-PeersView.title.full=Hartzaileak
-AllPeersView.title.full=Hartzaile Guztiak
-ConfigView.section.files=Agiriak
-ConfigView.label.usefastresume=Erabili Berrekite Azkarreko aukera
-ConfigView.label.incrementalfile=Gaitu agirien sorrera inkrementala  [beharrezkoa Linux-en FAT32 erabiliz gero]
-ConfigView.label.defaultsavepath=Gorde berezko datu zuzenbidean
-ConfigView.button.browse=&Bilatu...
-ConfigView.dialog.choosedefaultsavepath=Mesedez hautatu berezko gordetze zuzenbidea
-ConfigView.section.server=Elkarketa
-ConfigView.section.global=Orokorra
-ConfigView.label.disconnetseed=Eten emaritzak emaritzean
-ConfigView.label.switchpriority=Berez-aldatu lehentasun apalera emaritzean
-ConfigView.label.maxdownloads=Gehienezko jeisketa aldiberean [0: mugagabea]\n - Ezin da izan torrent eraginduena baino handiagoa
-ConfigView.label.maxdownloads.tooltip=Hemen erabaki duzun kopurua eraginkortasunez jeitsi ahal izango duzu beti, salbuespen batekin.\nLehentasun handiena duen torrent osatu batek jeisketa eraginkor baten tokia hartu dezake guztiz beharrezkoa bada.
-ConfigView.label.maxactivetorrents=Gehienezko Torrent lanean [0: mugagabea]\n - Torrent berriak ez dira abian jarriko gehiago jeisten/emaritzen ari bazara
-ConfigView.label.priorityExtensions=Berez-lehenetsi agiri mota hauek: \n - adib: .txt; .nfo; .jpg
-ConfigView.section.transfer=Eskualdaketa
-ConfigView.label.maxuploads=Geh igoera ahoak torrent bakoitzeko berez
-ConfigView.label.maxuploadspeed=KB/s gehienezko abiadura igoera orokorrentzat [0: mugagabea]
-ConfigView.label.saveresumeinterval=Eguneratu berrekite datuak betik
-ConfigView.unlimited=Mugagabea
-ConfigView.section.display=Ikusi
-ConfigView.label.opendetails=Berez ireki xehetasunen hegatsa
-ConfigView.label.openbar=Berez irekitze jeisketa barra
-ConfigView.label.use_old_speed_menus=Erabili estilo zaharreko abiadura menuak [berrabiaraztea beharrezkoa]
-ConfigView.label.closetotray=Itxik Sistemaren Erretilura ikurtzen du
-ConfigView.label.minimizetotray='Ikurtu' aukerak Sistemaren Erretilura ikurtzen du
-ConfigView.section.general=Orokorra
-ConfigView.section.start=Hasi
-ConfigView.label.showsplash=Erakutsi zipriztin ikusleihoa
-ConfigView.label.autoupdate=Ireki berritze leihoa bertsio berri bat eskuragarri dagoenean
-ConfigView.label.openconsole=Ireki kontsola abiatzean
-ConfigView.label.openconfig=Ireki aukeren leihoa abiatzean
-ConfigView.label.startminimized=Hasi ikurtuta
-ConfigView.label.ircwiki=Mesedez irakurri http://azureuswiki.com/index.php/Rules_for_IRC
-ConfigView.label.ircserver=Zerbitzaria
-ConfigView.label.ircchannel=Kanala
-ConfigView.label.irclogin=Izenordea
-ConfigView.group.irctitle=IRC Ezarpenak
-ConfigView.boolean.ircsendinfo=Baimendu zure ezarpenak bidaltzea (modu izengabean)\n kanal eragileei, laguntza eman ahal diezazuten
-ConfigView.boolean.irclog=Gaitu kanal jardueraren datuen erregistratzea (IRC_log.htm)
-ConfigView.section.security=Segurtasuna
-ConfigView.label.password=Babestu Vuze sarhitza erabiliz\n - Ikurtutakoan eta hasterakoan galdetuko du.
-ConfigView.label.passwordconfirm=Sarhitza (baieztatu)
-ConfigView.label.passwordmatch=Sarhitza eraginda:
-ConfigView.label.passwordmatchnone=Ez
-ConfigView.label.passwordmatchno=Ez / Sarhitza ez da zuzena
-ConfigView.label.passwordmatchyes=Bai
-ConfigView.button.save=Gorde
-ConfigView.title.short=Aukerak
-ConfigView.title.full=Aukerak
-ConfigView.title.full._mac=Hobespenak
-ConsoleView.title.short=Kontsola
-ConsoleView.title.full=Kontsola
-FileItem.write=Idatzi
-FileItem.read=Irakurri
-FileItem.normal=Arrunta
-FileItem.high=Handia
-FileItem.donotdownload=Ez jeitsi
-FileItem.delete=Ezabatu
-FilesView.name=Izena
-FilesView.name.fastRename=Berrizendatze azkarra
-FilesView.size=Neurria
-FilesView.done=Eginda
-FilesView.%=% 
-FilesView.firstpiece=Lehen atala 
-FilesView.numberofpieces=Atal zenbatekoa
-FilesView.pieces=Atalak
-FilesView.mode=Modua
-FilesView.priority=Lehentasuna
-FilesView.menu.open=&Ireki
-FilesView.menu.setpriority=&Ezarri Lehentasuna
-FilesView.menu.setpriority.high=&Handia
-FilesView.menu.setpriority.normal=&Arrunta
-FilesView.menu.setpriority.skipped=&Ez jeitsi
-FilesView.title.short=Agiriak
-FilesView.title.full=Agiriak
-GeneralView.section.downloaded=Jeitsita
-GeneralView.label.status.file=Agiriaren Egoera
-GeneralView.label.status.pieces=Atalen Egoera
-GeneralView.section.availability=Eskuragarritasuna
-GeneralView.label.status.pieces_available=Atalen Egoera
-GeneralView.section.transfer=Eskualdaketa
-GeneralView.section.info=Argibideak
-GeneralView.title.short=Orokorra
-GeneralView.title.full=Orokorra
-GeneralView.label.timeelapsed=Igarotako denbora: 
-GeneralView.label.remaining=Gelditzen da: 
-GeneralView.label.downloaded=Jeitsita:
-GeneralView.label.downloadspeed=Jeisketa Abiadura:
-GeneralView.label.maxuploads=Igoera Ahoak:
-GeneralView.label.maxuploads.tooltip=Une jakin batean itogabe izango diren gehienezko hartzaile zenbatekoa.
-GeneralView.label.uploaded=Igota:
-GeneralView.label.uploadspeed=Igoera Abiadura:
-GeneralView.label.seeds=Emaritzak: 
-GeneralView.label.peers=Hartzaileak:
-GeneralView.label.completed=Osatuta: 
-GeneralView.label.totalspeed=Erletaldearen Abiadura:
-GeneralView.label.totalspeed.tooltip=Zurekin elkarketatuta dauden bezero guztien abiadura osoa (eta bataz-bestekoa).
-GeneralView.label.averagespeed=bataz-bestekoa
-GeneralView.label.filename=Izena: 
-GeneralView.label.totalsize=Neurria Guztira:
-GeneralView.label.savein=Gordeta Hemen:
-GeneralView.label.hash=Hasha: 
-GeneralView.label.numberofpieces=Atal Zenbatekoa:
-GeneralView.label.size=Neurria:
-GeneralView.label.tracker=Aztarnariaren Egoera: 
-GeneralView.label.updatein=Eguneraketa:
-GeneralView.label.trackerurl=Aztarnariaren URL-a:
-GeneralView.label.trackerurlupdate=Eguneratu &Aztarnaria
-GeneralView.label.comment=Torrentaren Aipamena:
-GeneralView.label.user_comment=Erabiltzailearen Aipamena:
-GeneralView.label.status=Egoera:
-ManagerItem.waiting=Itxaroten
-ManagerItem.allocating=Esleitzen
-ManagerItem.checking=Egiaztatzen
-ManagerItem.ready=Beste torrenta(k) itxaroten Lerrokatzeko
-ManagerItem.downloading=Jeisten
-ManagerItem.seeding=Emaritzen
-ManagerItem.stopped=Geldituta
-ManagerItem.error=Akatsa
-ManagerItem.high=Handia
-ManagerItem.low=Txikia
-MinimizedWindow.name=Izena:
-MinimizedWindow.all_transfers=Vuze Eskualdaketak
-PiecesView.#=Atal Zenbatekoa
-PiecesView.size=Neurria
-PiecesView.numberofblocks=Bloke Zenbatekoa
-PiecesView.blocks=Blokeak
-PiecesView.completed=Osatuta
-PiecesView.availability=Eskuragarritasuna
-PiecesView.reservedby=Gordeta
-PiecesView.writers=Blokearen Emaleak
-PiecesView.title.short=Atalak
-PiecesView.title.full=Atalak
-SystemTray.tooltip.seeding=%1 emaritzen,
-SystemTray.tooltip.downloading=%1 jeisten,
-DownloadManager.error.filenotfound=Agiria Ez da Aurkitu
-DownloadManager.error.fileempty=Torrent agiria hutsik dago
-DownloadManager.error.filetoobig=Torrent agiria handiegia da
-DownloadManager.error.filewithouttorrentinfo=Ez da torrent argibiderik aurkitu agirian
-DownloadManager.error.unsupportedencoding=Kodeaketa Okerra
-DownloadManager.error.ioerror=S/I Akatsa
-DownloadManager.error.sha1=(SHA1) akatsa , ez dago Algoritmoa
-PeerManager.status.offline=Elkarketa Akatsa
-PeerManager.status.ok=Ongi
-PeerManager.status.checking=Egiaztatzen
-PeerManager.status.finished=Amaitua
-PeerManager.status.finishedin=Amaituta
-MainWindow.upgrade.assistant=Berritze Laguntzailea
-MainWindow.upgrade.newerversion=Vuzeren bertsio berri bat dago eskuragarri
-MainWindow.upgrade.explanation=Laguntzaile honek bertsio berria jeitsiko du zure ordenagailuko Vuze agiritegira eta Vuze berrabiaraziko du
-MainWindow.upgrade.explanation.manual=Eskuz eguneratu dezakezu Vuze itxiz, bertsio berria jeitsiz eta Vuze berrabiaraziz
-MainWindow.upgrade.step1=1. urratsa: Jeitsi bertsio berria
-MainWindow.upgrade.step2=2. urratsa: Bertsio hau itxi eta Vuzeren bertsio berria berrabiarazi
-MainWindow.upgrade.hint1=Aholkua:\t Amaitu botoia sakatuz dena berezgaitasunez egingo da
-MainWindow.upgrade.hint2=Aholkua:\u005cGero Vuze itxi nahi baduzu, sakatu Ezeztatu eta\n\titxi ondoren Azureus2-new.jar berrizendatu Azureus2.jar bezala
-MainWindow.upgrade.error.downloading.hint=Akatsa:\tEzin izan da bertsio berria jeitsi, mesedez eguneratu eskuz
-MainWindow.upgrade.section.info=Bertsio Berria Eskuragarri
-MainWindow.upgrade.section.manual=Eskuzko Eguneraketa 
-MainWindow.upgrade.section.automatic=Berezgaitasunezko Eguneraketa
-MainWindow.upgrade.tooltip.progressbar=Jeisketaren garapena hemen erakusten da
-Button.next=Hurrengoa
-Button.finish=Amaitu
-Button.cancel=E&zeztatu
-LocaleUtil.title=Hautatu kodeaketa
-LocaleUtil.section.chooseencoding=Hautatu kodeaketa agiri izenerako
-LocaleUtil.label.chooseencoding=Hautatu kodeaketarik egokiena
-LocaleUtil.label.hint.doubleclick=Aholkua: lerro batean bi aldiz klik eginez kodeaketa hautatzen da eta leihoa isten da
-LocaleUtil.label.checkbox.rememberdecision=Gogoratu erabakia gelditzen diren agiri-izenetarako
-LocaleUtil.column.encoding=Kodeaketa
-IrcClient.defaultChannel=#Azureus-Erabiltzaileak
-IrcClient.copyright=PircBot Java IRC API erabiltzen - http://www.jibble.org/pircbot.php
-IrcClient.connecting=Elkarketatzen hona:
-IrcClient.connected=Elkarketaturik hona:
-IrcClient.joining=Bategiten
-IrcClient.channel=Kanala
-IrcClient.joined=bat eginda
-IrcClient.error=Akatsa
-IrcClient.hasjoined=bat egin du
-IrcClient.haskicked=kanporatua izan da
-IrcClient.hasleft=utzi egin du
-IrcClient.nowknown=orain honela ezagutua da:
-IrcClient.topicforchannel=Gaia kanalerako
-IrcClient.disconnected=Etenda hemendik:
-IrcClient.noNick=Ez da Izenorderik Adierazi. Mesedez joan 'Aukerak' Ikusi-ra
-IrcView.actionnotsupported=Ekintza hau ez dago sostengatuta
-IrcView.clientsconnected=erabiltzaileak
-IrcView.privateto=Hona:
-IrcView.privatefrom=Hemendik
-IrcView.noticefrom=Oharra:
-IrcView.errormsg=Hitzjoskera Okerra /msg : /msg erabiltzaile idazkia
-IrcView.help=Baliozko aginduak hauek dira:\n . /help: mezu hau erakusten du\n . /nickname | /name: zure izena aldatzen du \n . /me action: ekintza bat bidaltzen du \n . /msg nick message: mezu pribatua bidaltzen dio <nick>-(e)ri\n . /r message: azken mezu pribatuari erantzuten dio\n . /join #channelB (ez egin klik hemen, adibide bat da): uneko kanaletik BKanalera aldatzen du
-PasswordWindow.title=Vuze itxita dago
-PasswordWindow.passwordprotected=Vuze sarhitzez babestuta dago.\nVuzeren leihoa erakusteko, mesedez sartu zure sarhitza hemen:
-Button.ok=&Ongi
-TrackerChangerWindow.title=Gehitu Aztarnaria
-TrackerChangerWindow.newtracker=Sartu aztarnari berriaren URL-a
-PeersView.discarded=Baztertua
-PeersView.discarded.info=Nolabait jaso duzun datua, nahiz eta beharrezkoa ez izan, eta baztertu duzuna.
-discarded=baztertuta
-MyTorrentsView.#=Zbk.
-MyTorrentsView.menu.move=&Mugitu
-MyTorrentsView.menu.moveUp=&Gora
-MyTorrentsView.menu.moveDown=&Behera
-GeneralView.label.hashfails=Hash Hutsegiteak: 
-GeneralView.label.shareRatio=Elkarbanatze Maila: 
-ConfigView.section.downloadManagement=Jeisketa Kudeaketa
-ConfigView.label.startRatioPeers=Hasi emaritzen emale bat baino gutxiago dagoenean
-ConfigView.text.neverStop=Ez Gelditu Inoiz
-ConfigView.text.neverStart=Ez Hasi Inoiz
-ConfigView.text.peers=Hartzaile
-ConfigView.label.checkOncompletion=Egiaztatu berriro atalak jeisketa egin ondoren
-wizard.title=Sortu torrent bat
-wizard.previous=< Atzera
-wizard.next=&Hurrena >
-wizard.finish=A&maitu
-wizard.mode=Aztarnaria / Modua
-wizard.tracker=Aztarnaria:
-wizard.invalidurl=URL hau baliogabea da
-wizard.singlefile=Agiri bakarra
-wizard.singlefile.help=Sortu torrenta agiri bakarretik
-wizard.directory=Zuzenbidea
-wizard.directory.help=Sortu torrenta zuzenbide batetik
-wizard.choosefile=Hautatu agiria
-wizard.file=Agiria:
-wizard.browse=Bilatu
-wizard.choosedirectory=Hautatu zuzenbidea
-wizard.invalidfile=Baliogabeko Agiria!
-wizard.invaliddirectory=Baliogabeko Zuzenbidea!
-wizard.torrentFile=Torrent Agiria
-wizard.choosetorrent=Mesedez hautatu sortzeko torrent agiria
-wizard.information=Argibideak
-wizard.notimplemented=Garatu gabea
-wizard.progresstitle=Torrent agiria sortzen
-wizard.savingfile=Agiria gordetzen...
-wizard.filesaved=Agiria gordeta.
-wizard.close=Itxi
-Torrent.create.progress.piecelength=Atalen luzera: 
-Torrent.create.progress.piececount=Atal zenbatekoa: 
-Torrent.create.progress.totalfilesize=Agiriaren neurri osoa:
-Torrent.create.progress.totalfilecount=Agiri zenbateko osoa: 
-Torrent.create.progress.parsingfiles=Agiriak aztertzen
-Torrent.create.progress.hashing=Agirien hasha sortzen
-MainWindow.upgrade.downloadingfrom=Jeisten hemendik: 
-MainWindow.menu.view.ipFilter=IP Iragazkiak
-ConfigView.section.ipfilter=IP iragazkiak
-ConfigView.section.ipfilter.description=Azalpena
-ConfigView.section.ipfilter.start=Hasierako IP-a
-ConfigView.section.ipfilter.end=Amaierako IP-a
-ConfigView.section.ipfilter.add=Gehitu
-ConfigView.section.ipfilter.remove=Kendu
-ConfigView.section.ipfilter.edit=Editatu
-ConfigView.section.ipfilter.save=Gorde
-ConfigView.section.ipfilter.editFilter=Iragazkia Editatu 
-ConfigView.section.ipfilter.enable=Gaitu
-PeersView.menu.close=&Itxi
-seedmore.title=Torrenta ez dago nahikoa emarituta
-seedmore.shareratio=Zure elkarbanatze maila torrent honentzat hau da: 
-seedmore.uploadmore=Ehuneko 100 elkarbanatze maila baino txikiagoa edukitzea ez da ona torrent sarearentzat.\nTorrent honi apur bat gehiago emaritzen utzi beharko zenioke.\nZihur jarraitu nahi duzula?
-ConfigView.label.showpopuponclose=Erakutsi baieztapen leihoa 1 azpitik dagoen elkarbanatze maila duen emaritzea gelditzean
-ConfigView.label.startNumSeeds=\nHasi emaritzen hauek baino gutxiago daudenean:\n - Beste arau guztiak gainidazten ditu
-ConfigView.label.seeds=Emaritza
-ConfigView.section.seeding=Emaritzen
-#Used by the webui plugin
-MyTorrentsView.menu.removeand.deletetorrent=Ezabatu &Torrent Agiria
-#Used by the webui plugin
-MyTorrentsView.menu.removeand.deletedata=Ezabatu &Datuak
-#Used by the webui plugin
-MyTorrentsView.menu.removeand.deleteboth=Ezabatu &Biak
-deletedata.title=Ezabatu edukia
-# used for more than just "delete data"
-deletedata.noprompt=Ez galdetu berriro
-MainWindow.menu.file.configure=Itxurapen &Laguntzailea...
-configureWizard.title=Itxurapen Laguntzailea
-configureWizard.welcome.title=Ongi etorri Vuzeren Itxurapen Laguntzailera
-configureWizard.welcome.message=Laguntzaile honek zure Vuze modu egokian erabiltzen lagunduko dizu. Itxurapena sakonago aldatu nahi baduzu, erabili Tresnak->Aukerak menua.
-configureWizard.transfer.title=Eskualdaketa eta Elkarketa ezarpenak
-configureWizard.transfer.hint=Aholkua: hautatu zure linearen abiadura baino apur bat txikiagoa.
-configureWizard.transfer.message=Hautatu azpian adierazitako elkarketetako bat. Kontuan izan igoera abiadura aski handia ahalbidetzen ez bada, jeisketa abiadura motela izango dela. Igoera abiadura torrent BAKOITZEKO bakarrik zenbatzen denez, torrent gehiegi aldi berean jeisteak ere abiadura moteldu dezake. Gutxienezko HERTSI gisa, torrent bakoitzeko 5KB/s erabiltzea aholkatzen dugu. Azkarrago igotzen baduzu, azkarrago jeitsiko duzu (torrentaren abiadurarekin alderatuz gero).
-configureWizard.transfer.connection=Linea
-configureWizard.transfer.connection.0=Norbererara
-configureWizard.transfer.connection.1=modema
-configureWizard.transfer.connection.2=adsl/xxx kablea/128 kbs-koa
-configureWizard.transfer.connection.3=adsl/xxx kablea/256 kbs-koa
-configureWizard.transfer.connection.4=adsl/xxx kablea/384 kbs-koa
-configureWizard.transfer.connection.5=adsl/xxx kablea/512 kbs-koa
-configureWizard.transfer.connection.6=adsl/xxx kablea/768 kbs-koa
-configureWizard.transfer.connection.7=adsl/xxx kablea/1024 kbs-koa
-configureWizard.transfer.maxUpSpeed=Gehienezko Igotze Abiadura (KB/s)
-configureWizard.transfer.maxActiveTorrents=Gehienez Eraginda
-configureWizard.transfer.maxDownloads=Gehienezko Jeisketak
-configureWizard.transfer.maxUploadsPerTorrent=Gehienezko Igoera Torrnet bakoitzeko
-configureWizard.nat.test=Aztertu
-configureWizard.nat.testing=Ataka aztertzen
-configureWizard.nat.ok=Ongi!
-configureWizard.nat.ko=NAT Akatsa
-configureWizard.nat.unable=Ezin izan da azterketa egin: Okerreko ataka eman da, edo azterketarako zerbitzuak huts egin du.\nAgian beste aplikazioren bat ataka hau erabiltzen ari da.
-configureWizard.file.title=Torrentak / Agiriak
-configureWizard.file.message1=Vuzek irekitako torrentak agiritegi batean gordeko dira, agiritegi hori hemen adierazi dezakezu:
-configureWizard.file.path=Helburua:
-configureWizard.file.browse=Bilatu
-configureWizard.file.message2=Vuzek berehala berrabiarazi ditzake zure agiriak, zure torrentei berrabiarazte datuak eransten badizkiozu. Ezaugarri hau erabiliz, zati bat jeitsitako atalak ere berrabiaraziko dituzu.
-configureWizard.file.fastResume=Gaitu Berrekite azkarra
-configureWizard.file.invalidPath=Zuzenbide okerra
-configureWizard.finish.title=Osatuta
-configureWizard.finish.message=Orain Vuze itxuratuta dago, ondo izan !
-wizard.close.confirmation=Baieztapena
-wizard.close.message=Nahi duzu laguntzaile hau gertatzea Vuze abiarazten den hurrengoan?
-exportTorrentWizard.title=Esportatu XML torrenta
-exportTorrentWizard.torrentfile.title=Sarrerako Torrentaren Hautapena
-exportTorrentWizard.torrentfile.message=Hautatu esportatuko den torrent agiria
-exportTorrentWizard.torrentfile.path=Helburua:
-exportTorrentWizard.torrentfile.browse=Bilatu
-exportTorrentWizard.torrentfile.invalidPath=Torrent agiri baliogabea
-exportTorrentWizard.exportfile.title=Hautatu Esportatzeko Agiria
-exportTorrentWizard.exportfile.message=Sartu esportatzeko xml agiria
-exportTorrentWizard.exportfile.path=Helburua:
-exportTorrentWizard.exportfile.browse=Bilatu
-exportTorrentWizard.exportfile.invalidPath=Esportazio agiri baliogabea
-exportTorrentWizard.finish.title=Osatua
-exportTorrentWizard.finish.message=Esportazioa ongi burutu da
-exportTorrentWizard.process.inputfilebad.title=Torrent Agiri Baliogabea
-exportTorrentWizard.process.inputfilebad.message=Hutsegitea gertatu da hurrengo sarrera agiria atzitzean:
-exportTorrentWizard.process.outputfileexists.title=Agiria Badago
-exportTorrentWizard.process.outputfileexists.message=Irteerako agiria badago - gainidatzi?
-exportTorrentWizard.process.torrentfail.title=Torrentaren Irakurketan Hutsegitea
-exportTorrentWizard.process.exportfail.title=Torrentaren Esportazio Hutsegitea
-exportTorrentWizard.process.unknownfail.title=Ustekabeko Akatsa
-importTorrentWizard.title=Inportatu XML torrenta
-importTorrentWizard.torrentfile.title=Sarrerako Torrentaren Hautapena
-importTorrentWizard.torrentfile.message=Adierazi inportatu nahi duzun torrent agiria
-importTorrentWizard.torrentfile.path=Helburua:
-importTorrentWizard.torrentfile.browse=Bilatu
-importTorrentWizard.torrentfile.invalidPath=Torrent agiri baliogabea
-importTorrentWizard.importfile.title=Inportazio Agiri Hautapena
-importTorrentWizard.importfile.message=Hautatu inportatuko den xml agiria
-importTorrentWizard.importfile.path=Helburua:
-importTorrentWizard.importfile.browse=Bilatu
-importTorrentWizard.importfile.invalidPath=Inportazio agiri baliogabea
-importTorrentWizard.finish.title=Osatuta
-importTorrentWizard.finish.message=Inportazioa ongi burutu da
-importTorrentWizard.process.inputfilebad.title=Inportazio Agiri Baliogabea
-importTorrentWizard.process.inputfilebad.message=Hutsegitea gertatu da hurrengo sarrera agiria atzitzean:
-importTorrentWizard.process.outputfileexists.title=Agiria Badago
-importTorrentWizard.process.outputfileexists.message=Irteerako agiria badago - gainidatzi?
-importTorrentWizard.process.torrentfail.title=Torrentaren Idazketa Hutsegitea
-importTorrentWizard.process.importfail.title=Torrentaren inportazioak huts egin du
-importTorrentWizard.process.unknownfail.title=Ustekabeko Hutsegitea
-ConfigView.label.bindip=Lotu tokiko IP helbidera edo interfazera
-ConfigView.label.xfs.allocation=Esleitu agiri berriak XFS agiri-erabide bereizia den bide bat erabiliz
-ConfigView.label.xfs.allocation.tooltip=Mesedez zihurtatu /usr/sbin/xfs_io zure sisteman ongi ezarrita dagoela. Linux banaketa gehienetan "xfsprogs" paketean dago.
-xfs.allocation.xfs_io.not.found=XFS agiriaren esleipenak huts egin du ezin izan delako /usr/sbin/xfs_io exekutatu. Zihurtatu zure sisteman ongi ezarrita dagoela. Jatorrizko akatsa hau izan da: "%1".
-ConfigView.label.zeronewfiles=Esleitu eta hasieratu agiri berriak, haiek sortzen direnean
-ConfigView.label.zeronewfiles.tooltip=Zatikatzea gutxiagotzen du
-ConfigView.section.stats=Estatistikak
-ConfigView.section.stats.enable=Gaitu
-ConfigView.section.stats.defaultsavepath=Estatistikak gordetzeko zuzenbidea
-ConfigView.section.stats.choosedefaultsavepath=Mesedez hautatu estatistikak gordetzeko zuzenbidea
-ConfigView.section.stats.savefreq=Gordetze maiztasuna
-ConfigView.section.stats.minutes=min.
-ConfigView.section.stats.hours=ordu
-ConfigView.section.stats.seconds=seg.
-ConfigView.section.stats.savefile=Estatistiken agiri izena
-ConfigView.section.stats.graph_update_dividers=Erakutsi lerro zutia 60 eguneraketa bakoitzetik
-MyTorrentsView.menu.export=XML Torrenta...
-MyTorrentsView.menu.host=&Hostalaria...
-ManagerItem.finishing=Amaitzen
-ConfigView.dialog.choosedefaulttorrentpath=Mesedez hautatu berezko torrent zuzenbidea
-ConfigView.dialog.choosemovepath=Mesedez hautatu zein zuzenbidera mugituko den
-ConfigView.label.movecompleted=Mugitu osatutako agiriak (jeitsi ondoren)
-ConfigView.label.moveremoved=Mugitu osatutako agiriak (kentzerakoan)
-ConfigView.label.savetorrents=Gorde .torrent agiriak
-MainWindow.menu.view.mytracker=Nire &Aztarnaria
-MyTrackerView.title.full=Nire aztarnaria
-MyTrackerView.name=Izena
-MyTrackerView.tracker=Aztarnaria
-MyTrackerView.status=Egoera
-MyTrackerView.status.started=Lanean
-MyTrackerView.status.stopped=Geldituta
-MyTrackerView.peers=Hartzaileak
-MyTrackerView.seeds=Emaritzak
-MyTrackerView.announces=Iragarleak
-MyTrackerView.uploaded=Igota
-MyTrackerView.downloaded=Jeitsita
-MyTrackerView.left=Egiteke
-ConfigView.section.style=Interfazea
-ConfigView.label.set_ui_transfer_speeds=Gainidatzi eskualdaketa abiadura hautagarriak
-ConfigView.label.set_ui_transfer_speeds.description=Eskuz zehaztu ditzakezu erabidearen erretiluko egoera barran eskuragarri egongo diren berezko igoera eta jeisketa abiadurak.\nBalioak kakotxaz bananduta idatzi behar dira.
-ConfigView.label.set_ui_transfer_speeds.description.download=Ezarri jeisketa abiadurak (KB/s)
-ConfigView.label.set_ui_transfer_speeds.description.upload=Ezarri igoera abiadurak (KB/s)
-ConfigView.section.style.useCustomTabs=Erabili itxi daitezkeen hegatsak (berrabiaraztea beharrezkoa)
-MainWindow.menu.view.plugins=&Pluginak
-fileDownloadWindow.saveTorrentIn=Gorde torrent agiria hemen:
-fileDownloadWindow.title=Vuze - Torrent jeistzailea
-fileDownloadWindow.downloading=Hemendik Jeisten:
-fileDownloadWindow.status=Egoera:
-fileDownloadWindow.state_initializing=Abiarazten
-fileDownloadWindow.state_downloading=Jeisten
-fileDownloadWindow.state_error=Akatsa:
-MainWindow.menu.file.open.url=&Kokalekua...
-openUrl.title=Ireki Kokalekua
-openUrl.url=URL-a:
-MyTorrentsView.menu.host.error.title=Torrentaren Hostatutzeak Huts egin du
-MyTorrentsView.menu.host.error.message=Torrenta hostatatzean hurrengo akatsa gertatu da
-ConfigView.section.tracker=Aztarnaria
-ConfigView.section.tracker.pollinterval=Aztarnariaren bezeroa zenbatero zundatuko den (segundoak)
-ConfigView.section.tracker.publishenable=Argitaratu torrent-aren xehetasunak "<tracker_url>"-era
-ConfigView.section.tracker.ip=Aztarnariaren kanpoko IP helbidea
-ConfigView.section.style.enableXPStyle=Gaitu XP estiloa (berrabiaraztea beharrezkoa)
-IPChecker.external.service.dyndns.description=DNS Sare Zerbitzu Dinamikoak, LLC
-ConfigView.section.tracker.checkip=Berez-aurkitu kanpoko IP helbidea...
-ipCheckerWizard.title=IP Egiaztapen Laguntzailea
-ipCheckerWizard.service=Zerbitzua
-ipCheckerWizard.chooseService=Hautatu IP Egiaztapen Zerbitzu bat zerrendatutako zerbitzuetatik
-ipCheckerWizard.explanations=Zure kanpoko IP helbidea zein den aurkitzeko erabil dezakezu laguntzaile hau. Zure IP helbidea dinamikoa bada, DNS Zerbitzu Dinamiko batekin kontua irekitzea aholkatzen dizugu. Beheko zerrendan zerbitzu horietako zenbait ematen ditugu, erabili loturak kontu bat sortzeko (sostengatuta dagoen tokietan). Ondoren, bete IP helbidearen eremua zure hostatatze-izen dinamikoarekin (adib. nireizena.dyndns.org). Aplikazio bat beharko duzu zure DNS Zerbitzu Dinamikoa ber [...]
-ipCheckerWizard.service.description=Azalpena:
-ipCheckerWizard.service.url=Lotura:
-ipCheckerWizard.progresstitle=IP-a Egiaztatzen
-ipCheckerWizard.checkComplete=IP osatua:
-ipCheckerWizard.checkFailed=Huts egin du, zergaitia:
-wizard.tracker.local=Erabili Vuze Barneko Aztarnaria
-wizard.tracker.external=Erabili kanpoko aztarnaria
-wizard.tracker.howToLocal=\tJoan 'Tresnak->Aukerak->Aztarnaria' hura gaitzeko
-wizard.announceUrl=Iragarpen URL-a:
-IPChecker.external.service.discoveryvip.description=Discoveryvip - IP helbidearen egiaztatzea bakarrik
-IPChecker.external.httpinvalidresponse=HTTP erantzun baliogabea
-IPChecker.external.loadingwebpage=Web orrialdea gertatzen
-IPChecker.external.analysingresponse=Erantzuna aztertzen
-IPChecker.external.addressextracted=Erauzitako IP helbidea
-IPChecker.external.httploadfail=Orrialdea gertatzeak huts egin du
-IPChecker.external.timeout=Denboraz kanpo gelditu da
-IPChecker.external.ipnotfound=IP helbidea ez da aurkitu
-ConfigView.section.tracker.pollintervalmin=Gutxienez
-ConfigView.section.tracker.pollintervalmax=Gehienez
-ConfigView.section.tracker.pollintervalincby=Handitu honenbeste:
-ConfigView.section.tracker.pollintervalincper='z' bezerotik behin
-splash.loadingImages=Irudiak Gertatzen
-splash.initializeGui=Leiho Nagusia Abiarazten
-splash.openViews=Ikuspegiak Irekitzen
-splash.plugin=Plugina Gertatzen:
-configureWizard.nat.tooManyPorts=Aztertzeko ataka gehiegi (9 gehienez)
-ConfigView.section.color=Margo Itxurapena
-MyTorrentsView.menu.publish=A&rgitaratu...
-MyTrackerView.status.published=Argitaratuta
-MyTrackerView.completed=Osatuta
-MainWindow.menu.file.open.torrentnodefault=Torrent agiria... (Ez Gorde Lehenespenez)
-MainWindow.menu.file.open.torrentnodefault.keybinding.mac=Meta+Auk+O
-wizard.comment=Aipamena:
-ConfigView.label.movetorrent=Mugitu .torrenta
-ConfigView.label.movepartialdownloads=Mugitu agiri batzuk "Ez jeitsi" ikurra eduki arren
-ConfigView.label.subdir_is_in_default=Jeisketak zuzenbide berezko batean ba ote diren aztertzean, aztertu azpizuzenbideak ere. 
-ConfigView.section.file.decoder.label=Berezko torrent kodeaketa hautaketak horrela eskatzen duenean
-ConfigView.section.file.decoder.nodecoder=Bat ere ez
-IPChecker.external.service.no-ip.name=Ez-IP
-IPChecker.external.service.no-ip.description=DNS zerbitzu dinamiko eta estatikoen hornitzailea (ez du 'egiaztatu helbidea' zerbitzu askerik)
-ConfigView.section.tracker.publicenable=Gaitu kanpoko torrentak
-ConfigView.label.playdownloadspeech=Hitz egin jeisketa amaitutakoan
-#
-# Tooltips
-#
-GeneralView.label.status.pieces_available.tooltip=Erakutsi atal bakoitzaren kopia eskuragarrien zenbatekoa.\nEskuineko zenbakia 1 baino txikiagoa bada, ez zaude ikusten agiriaren kopia oso bat (eta arazoak egon daitezke jeisketa burutzeko).
-GeneralView.label.trackerurl.tooltip=Egin klik iragarpen URL-a gakora kopiatzeko
-GeneralView.label.trackerurlopen.tooltip=Egin klik aztarnariaren orri nagusia irekitzeko
-#
-# 2.0.4.4
-#
-ConfigView.section.style.guiUpdate=Eguneratu EIG betik
-ConfigView.section.style.inactiveUpdate=Eguneratu leiho nagusia EIG-aren Z eguneratzetik behin, leiho eragilea ez denean 
-ConfigView.section.style.graphicsUpdate=Eguneratu Grafika barrak EIG-aren Z eguneratzetik behin
-ConfigView.section.style.reOrderDelay=Berrantolatu taulak EIG-aren Z eguneratzetik behin [0: inoiz ez]
-ConfigView.section.style.reOrderDelay.never=Inoiz Ez
-ConfigView.section.logging=Oharketa
-ConfigView.section.logging.enable=Gaitu agirira ohartzea
-ConfigView.section.logging.logdir=Saio agiri zuzenbidea
-ConfigView.section.logging.choosedefaultsavepath=Hautatu gordetze zuzenbidea
-GeneralView.label.updatein.querying=Eskabidetzen...
-configureWizard.nat.sharePort=Erabili sarrerako ataka elkarbanatu bakarra torrent guztientzako
-ConfigView.section.logging.maxsize=Gehienezko ohar agiriaren neurria
-ConfigView.section.tracker.passwordenableweb=Gaitu sarhitza aztarnariaren webean
-ConfigView.section.tracker.passwordenabletorrent=Gaitu sarhitza torrentetan
-ConfigView.section.tracker.username=Erabiltzaile izena
-ConfigView.section.tracker.password=Sarhitza
-columnChooser.title=Hautatu ikusiko diren zutabeak
-columnChooser.move=Arrastatu lerroak berrantolatzeko
-columnChooser.apply=Ezarri
-columnChooser.columnname=Zutabe Izena
-columnChooser.columndescription=Azalpena
-TableColumn.header.shareRatio=Elkarbanatze Maila
-MyTorrentsView.menu.editTableColumns=&Zutabearen Ezarpenak
-wizard.operationfailed=Eragiketak huts egin du
-authenticator.title=Egiaztapena Beharrezkoa da
-authenticator.realm=Eremua
-authenticator.tracker=Aztarnaria
-authenticator.user=Erabiltzaile izena
-authenticator.password=Sarhitza
-ConfigView.label.allowSendVersion=Ahalbidetu Vuzeri bertsio zenbakia eta zorizko id izengabeak bidaltzen bertsio berriaren bila ari denean 
-ConfigView.label.version.info.link=Ikusi hau bertsioak egiaztatzen dituen zerbitzarira bidaltzen diren datuen xehetasunak ezagutzeko
-wizard.hint.mode=Aholkua: Agiri bat edo zuzenbide bat Arrastatu eta Askatu dezakezu\n\t  laguntzaile honetan agiria edo zuzenbidea hautatzeko
-wizard.hint.file=Aholkua: Arrastatu eta Askatuz hautatu dezakezu agiri bat
-wizard.hint.directory=Aholkua: Arrastatu eta Askatuz hautatu dezakezu zuzenbide bat
-MainWindow.menu.help.checkupdate=Bilatu Eguneraketak...
-TableColumn.header.down=Jeitsita
-TableColumn.header.up=Igota
-ConfigView.section.tracker.passwordenabletorrent.info=BitTorrent bezero egokia (adibidez Vuze) behar da
-ConfigView.section.style.confirmationOnExit=Erakutsi berrespen leihoa irtetzerakoan
-MainWindow.dialog.exitconfirmation.title=Irten Vuzetik
-MainWindow.dialog.exitconfirmation.text=Egitan nahi duzu Vuzetik irtetzea?
-SystemTray.menu.stopalltransfers=Gelditu &Eskualdaketa Guztiak
-TrayWindow.menu.stopalldownloads=Gelditu &Jeisketa Denak
-ConfigView.section.tracker.sslport.info=Ikusi SEG argibide gehiagorako
-wizard.tracker.ssl=Erabili SSL
-ConfigView.label.playdownloadfinished=Jo soinu bat jeisketa burutzen denean
-ConfigView.label.popupdownloadfinished=Erakutsi alerta leihoa jeisketa burutzen denean
-ConfigView.label.popupfilefinished=Erakutsi alerta leihoa agiria amaituta dagoenean
-TableColumn.header.pieces=Atalak
-TableColumn.header.pieces.info=Grafika barrak jeitsi dituzun atalak adierazten ditu
-TableColumn.header.completion=Osaketa
-TableColumn.header.completion.info=Jeitsitako ehunekoa adierazten duen grafikoa
-ConfigView.section.style.showdownloadbasket=Erakutsi Jeisketa Saskia (Arrastatu eta Askatu .torrentak)
-ConfigView.section.style.alwaysShowTorrentFiles=Erakutsi betik torrent agiriak Xehetasunak/Agiriak atalean
-wizard.multitracker=Gehitu Aztarnari-Anitzaren argibideak torrentari
-wizard.multitracker.title=Aztarnari-Anitz
-wizard.multitracker.configuration=Aztarnari-Anitzaren Ezarpenak
-wizard.multitracker.new=Berria...
-wizard.multitracker.edit=Editatu...
-wizard.multitracker.delete=Ezabatu
-wizard.multitracker.group=Aztarnari Taldea
-wizard.multitracker.edit.title=Aztarnari-Anitz Editatzailea
-wizard.multitracker.edit.name=Izena
-wizard.multitracker.edit.save=Gorde
-wizard.multitracker.edit.newgroup=Talde Berria
-wizard.multitracker.edit.deletegroup=Ezabatu
-wizard.multitracker.edit.newtracker=Aztarnari Berria
-wizard.multitracker.edit.deletetracker=Ezabatu
-wizard.multitracker.edit.edit=Editatu
-wizard.addingmt=Aztarnari-Anitzaren argibideak gehitzen
-wizard.multitracker.noannounce=Zure aztarnarien zerrendan ez dago iragarpen URL-rik
-MyTorrentsView.menu.recheck=Behar&tu Berregiaztapena
-iconBar.showDownloadBar.tooltip=Erakutsi Jeisketa Barra
-iconBar.start.tooltip=Hasi hautatutako torrenta(k)
-iconBar.stop.tooltip=Gelditu hautatutako torrenta(k)
-iconBar.remove.tooltip=Kendu hautatutako torrentak
-iconBar.openNoDefault.tooltip=Ireki .torrent agiria (ez gorde berez)
-iconBar.openURL.tooltip=Ireki URL-a
-iconBar.openFolder.tooltip=Ireki Agiritegi bat
-iconBar.new.tooltip=Sortu torrent bat
-iconBar.up.tooltip=Mugitu gora
-iconBar.down.tooltip=Mugitu behera
-iconBar.run.tooltip=Ireki berezko programa erabiliz
-iconBar.host.tooltip=Hostalaria
-iconBar.publish.tooltip=Argitaratu
-iconBar.editcolumns.tooltip=Zutabe Ezarpena
-MyTorrentsView.menu.editTracker=Editatu aztarnari URL-ak
-GeneralView.menu.selectTracker=Hautatu
-ConfigView.section.stats.xslfile=XSL agiri izena
-ConfigView.section.stats.xslfiledetails=Hau estatistiken agiriaren idazburuan sartuko da <?xml-estilo-orria> etiketa erabiliz
-ConfigView.label.savetorrentbackup=Gorde babeskopia
-ConfigView.section.tracker.forceport=Behartu hostatutako kanpoko torrentak berezko ataka erabil dezaten
-ConfigView.section.ipfilter.allow=AHALBIDETU maila hauek (berezko balioa UKATZEA da)
-ConfigView.section.ipfilter.list.inrange=barrutian zegoen 
-ConfigView.section.ipfilter.list.notinrange=ez zegoen inolako barrutitan
-ConfigView.section.ipfilter.list.title=Eragotzitako IP-ak
-ConfigView.label.allowsameip=Ahalbidetu elkarketa anitz IP beretik
-ConfigView.label.allowsameip.tooltip=Egiaztatu BEHAR baduzu bakarrik.\nHau izainen aurkako babesa da (ezgaituta dagoenean).
-ManagerItem.superseeding=Gain-E&maritza
-ConfigView.label.userSuperSeeding=Erabili Gain Emaritza
-PeersView.uniquepiece=Atala (Gain-Emaritze modua)
-PeersView.uniquepiece.none=Bat ere ez
-PeersView.timetosend=Atala birbidaltzeko denbora (Gain-Emaritze Modua)
-ConfigView.section.style.addurlsilently=Ireki pasatutako URL-ak modu isilean
-ConfigView.section.style.addurlsilently.tooltip=Berezgaitasunez jeitsi pasatutako/askatutako .torrenten URL-ak elkarrizketa kutxa ireki gabe.
-ConfigView.section.file.decoder.prompt=Galdetu beti kodeaketa aukera eskuragarri dagoenean
-ConfigView.section.file.decoder.prompt.tooltip=Erakutsi betik elkarrizketa kodeaketa aukera eskuragarri dagoenean
-MyTorrentsView.menu.moveTop=&Goren
-MyTorrentsView.menu.moveEnd=&Beheren
-ConfigView.label.moveonlyusingdefaultsave=Datuen berezko zuzenbidean bada bakarrik
-ConfigView.label.moveonlyusingdefaultsave.tooltip=Mugitu bakarrik jeitsitako datuak berezko datuen zuzenbide badaude
-ConfigView.label.watchtorrentfolder=Inportatu .torrent berriak berezgaitasunez 
-ConfigView.label.watchtorrentfolder.tooltip=Bilatu .torrent berriak aldizka
-ConfigView.label.watchtorrentfolderinterval=Tartea
-ConfigView.label.watchtorrentfolderinterval.tooltip=Agiritegia berriro mihatu arteko pausaldia
-ConfigView.dialog.choosewatchtorrentfolderpath=Mesedez hautatu .torrenten inportazio-zuzenbidea
-ConfigView.label.startwatchedtorrentsstopped=Hasi geldituta
-ConfigView.label.startwatchedtorrentsstopped.tooltip=Gehitu .torrent berria GELDITUTA egoeran
-ConfigView.section.plugins=Pluginak
-wizard.maketorrent.filesize=Agiri(en) Neurria
-wizard.maketorrent.piececount=Atal Zenbatekoa
-wizard.maketorrent.piecesize=Atalen neurria
-wizard.maketorrent.auto=Berez
-MainWindow.menu.view.stats=Estatistikak
-SpeedView.title.full=Jarduera
-SpeedView.downloadSpeed.title=Jeisketa Abiadura
-SpeedView.uploadSpeed.title=Igoera Abiadura
-ConfigView.section.style.useSIUnits=Erabili IEC Batasunak (KB -> KiB, etab.)
-iconBar.top.tooltip=Mugitu lehen tokira
-iconBar.bottom.tooltip=Mugitu beheren
-TableColumn.header.health=Osasuna
-MyTorrentsView.menu.health=Osasunari buruz
-health.explain.grey=Esanahi du zure torrenta ez dagoela (ez jeisten ez igotzen)
-health.explain.red=Esanahi du ez zaudela inolako hartzailera elkarketaturik jeisketan zehar
-health.explain.blue=Emaritzean, esanahi du ez zaudela inolako hartzailera elkarketaturik.\nJeistean, esanahi du zenbait hartzaileetara elkarketaturik zaudela, baina aztarnaria bertan behera dagoela
-health.explain.yellow=Esanahi du aztarnaria ongi dagoela, hartzaileetara elkarketaturik zaudela, baina ez duzula hurruneko elkarketarik\nZure torrentak etengabe egoera orian badaude, agian NAT arazo bat duzu
-health.explain.green=Esanahi du dena ongi doala
-ConfigView.section.style.alwaysRefreshMyTorrents=Betik berritu Liburutegia
-ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Aukera honek Liburutegi ikuspegia berritzen du nahiz eta begien aurrean ez egon (erabilgarria zenbait mirc pluginentzako)
-#
-#2.0.7.0
-#
-security.certtruster.title=Segurtasun Egiaztagiri Oharra
-security.certtruster.intro=Segurtasun Egiaztagiria fidagarritasunik onartu ez diozun baltzu batek jaulki du
-security.certtruster.resource=Baliabidea:
-security.certtruster.issuedto=Nori Jaulkia:
-security.certtruster.issuedby=Nork Jaulkia:
-security.certtruster.prompt=Fidagarritasuna onartu nahi diozu?
-security.certtruster.yes=Bai
-security.certtruster.no=Ez
-ConfigView.section.tracker.torrentsperpage=Zenbat torrent orrialdeko?  [0: mugagabea]
-MainWindow.menu.file.share=&Elkarbanatu
-MainWindow.menu.file.share.file=&Agiria...
-MainWindow.menu.file.share.dir=A&giritegia...
-MainWindow.menu.file.share.dircontents=Agiritegi &Edukiak...
-MainWindow.menu.file.share.dircontentsrecursive=Agiritegiko Edukiak... (&Baliabideak)
-MainWindow.dialog.share.sharefile=Hautatu Elkarbanatzeko Agiria
-MainWindow.dialog.share.sharedir=Hautatu Elkarbanatzeko Agiritegia
-MainWindow.dialog.share.sharedircontents=Hautatu Elkarbanatzeko Agiritegiko Edukia 
-MainWindow.dialog.share.sharedircontents.recursive=Jarraia
-globalmanager.download.remove.veto=Kenketa Ekintza Eragitza
-plugin.sharing.download.remove.veto=Jeisketa hau elkarbanatze baliabide baten emaitza da.\nJeisketa kentzeko elkartutako elkarbanatzea kendu: joan Tresnak->Nire Elkarbanatzeak.
-ConfigView.section.tracker.main=Nagusia
-ConfigView.section.tracker.web=Webgunea
-ConfigView.label.prioritizefirstpiece=Lehentasuna eman agiriko lehen eta azken atalari
-ConfigView.label.prioritizefirstpiece.tooltip=Lehen agiri baten hasiera eta amaiera jeisteko saiakerak.\nAurreikuspen hasierak sostengatzeko.
-ConfigView.section.file.delete.include_files_outside_save_dir=Datuak ezabatzerakoan, ahalbidetu torrentetik kanpo lotura duten agiriek zuzenbidea gordetzea hauek ere ezabatuak izateko 
-TrayWindow.menu.startalldownloads=Hasi Jeisketa Denak
-SystemTray.menu.startalltransfers=Hasi Eskualdaketa Denak
-sharing.progress.title=Klasikoen-Elkarbanatze Garapena
-sharing.progress.hide=Ezkutatu
-MainWindow.menu.view.myshares=Nire Elkarbanatzeak
-MySharesView.title.full=Nire Elkarbanatzeak
-MySharesView.name=Izena
-MySharesView.type=Mota
-MySharesView.type.file=Agiria
-MySharesView.type.dir=Zuzenbidea
-MySharesView.type.dircontents=Zuzenbide edukiak
-MySharesView.type.dircontentsrecursive=Zuzenbide edukiak (baliabidea)
-MySharesView.menu.remove=Kendu
-ConfigView.section.tracker.extensions=Hedapenak
-ConfigView.section.tracker.sendpeerids=Bidali hartzailearen nortasuna jeistzaileetara
-ConfigView.section.tracker.enableudp=Gaitu UDP aztarnari hartuemana
-plugin.sharing.torrent.remove.veto=Aztarnari erregistro hau elkarbanatze baliabide baten emaitza da.\nJeisketa kentzeko elkartutako elkarbanatzea kendu: joan Tresnak->Nire Elkarbanatzeak
-plugin.download.remove.veto.notstopped=Jeisketa ezin da kendu ez delako gelditzen
-plugin.sharing.remove.veto=Elkarbanatze hau elkarbanatze 'zuzenbide edukiak' azpi-elkarbanatze bat da eta ezin da ezabatua izan.\n Ezabatu erro elkarbanatze
-GeneralView.label.hash.tooltip=Egin klik hasha gakoan kopiatzeko
-ConfigView.section.tracker.maxpeersreturned=Gehienezko hartzaile itzulita [0: mugagabe]
-ConfigView.label.serverport=Sarrerako TCP / UDP aditze ataka
-ConfigView.label.serverport.tooltip=Ataka 1-65535 artekoa izan behar da, eta ez 6880 Vuzeren barne erabilpenerako gordea dagoena.
-configureWizard.nat.server.tcp_listen_port=Sarrerako TCP Aditze Ataka
-ConfigView.section.sharing=Elkarbanatzen
-ConfigView.section.sharing.usessl=Erabili SSL elkarbanatze  iturburuentzat (beharrezkoa Aztarnari itxurapena)
-ConfigView.section.style.dropdiraction=Arrastatu eta Askatu ekintza zuzenbideentzat
-ConfigView.section.style.dropdiraction.opentorrents=Ireki Torrentak
-ConfigView.section.style.dropdiraction.sharefolder=Elkarbanatze Zuzenbidea
-ConfigView.section.style.dropdiraction.sharefoldercontents=Elkarbanatze Edukiak
-#
-# 2.0.7.x
-#
-Categories.all=Denak
-Categories.uncategorized=Kategoriatu gabeak
-CategoryAddWindow.message=Sartu kategoria izen berri bat
-CategoryAddWindow.title=Gehitu Kategori Berria
-ConfigView.label.autoSeedingIgnoreInfo=Baztertutako torrentak emaritzen lerroko beherenera doaz. Ez dira berezgaitasunez hasiko.\nEzikusi arauak ez dira Lehentasun Nagusia irizpidea duten torrentei ezartzen.\nAlderantzizkoa adierazten ez bada, erabili 0 balio bat araua ezgaitzeko.
-ConfigView.label.directory=Zuzenbidea
-ConfigView.label.disconnetseed.tooltip=Torrent bat emaritzerakoan, eten emaritzen ari diren bezeroak.\nBeraiek ez dute behar zurekin hitzegiten egotea.
-ConfigView.label.ignoreCase=Ez bereiztu Larri-xehez
-ConfigView.label.ignoreSeeds=Ez egin kasu gutxienean dauden torrentei
-ConfigView.label.importdirectory=Inportatu Zuzenbidea
-ConfigView.label.minPeersToBoostNoSeeds.tooltip=Emaritzen ez dagoen edozein torrent eta zuk adierazitakoa baino hartzaile gutxiagorekin\nlerroaren beherenera mugituak izango dira.
-ConfigView.label.minPeersToBoostNoSeeds=Emaritzen Maila Txikiena emaritzen ari ez diren torrententzat eta hau baino gutxiago
-ConfigView.label.minSeedingTime.tooltip=Emaritzen Lerruna sarri aldatu daiteke denbora epe labur batean, batzuetan torrenta berezgaitasunez abiaraztea eraginez, ondoren berehala gelditua eta lerrokatua izateko..\nHonek arazoa arintzen du torrenta emaletzan egotera behartuz denbora batez.  Oraindikan eskuz gelditu dezakezu nahi baduzu.
-ConfigView.label.minSeedingTime=Gutxienezko emaritza denbora segundutan
-ConfigView.label.minSpeedForActiveDL.tooltip=Jeisketa aho bat betik da erabilia lehen 30 segundutan\nosatugabeko torrenta hasi ondoren.
-ConfigView.label.minSpeedForActiveDL=Ez zenbatu jeisketa ahoa erabiltzen ari den torrenta abiadura hau baino txikiagoa bada
-ConfigView.label.peers=Hartzaile
-ConfigView.label.queue.debuglog=Gorde garbiketa argibideak
-ConfigView.label.queue.debuglog.info=Gehitu lerro garbiketa argibideak kontsola/ohar agirira.\nEnkriptatuta izanda ere, garbiketa argibideak esaten dizu torrentaren egoera eta zergaitik dauden/ez dauden abiatzen/lerrokatzen.
-ConfigView.label.queue.minQueueingShareRatio=Ez lerrokatu edo gelditu torrenta bere elkarbanatze maila lortu arte
-ConfigView.label.ratio=maila
-ConfigView.label.removeOnStop=Kendu torrenta zerrendatik berezgaitasunez gelditu ondoren
-ConfigView.label.savedirectory=Gordetze Zuzenbidea
-ConfigView.label.seeding.autoReposition.tooltip=Gaituta badago, torrenteen ordena (Z zutabea) aldatu egingo da Emaritzen Lerrunarekin bat egin dezan.\nHau erabilgarria da zuk ez badituzu nahi ikusi Emaritzan Lerrunaren zenbakiak, baina jakin nahi duzu osatutako torrentak abiaraziko diren ordena.
-ConfigView.label.seeding.autoReposition=Berezgaitasunez birjarri Emaritza Lerrunean ohinarrituriko torrentak
-ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Sarri, emaritza zenbateko apala eta hartzaile zenbateko handia duten torrentak, zihurrenik esannahi du ez dela hartzaile arteko kopia oso bat.\nHortaz, badaiteke zuk ez nahi izatea emaletza arauak kopia oso bat izatea (eta hortaz okerra bere lerrunaren murrizketan)
-ConfigView.label.seeding.fakeFullCopySeedStart=baina gutxienez duten torrententzat bakarrik 
-ConfigView.label.seeding.ignore=Baztertu Arauak
-ConfigView.label.seeding.ignore0Peers=Baztertu 0 hartzaileko torrentak
-ConfigView.label.seeding.ignoreRatioPeers=Baztertu bakoitzeko emaritza 1 duten torrentak
-ConfigView.label.seeding.ignoreShareRatio=Baztetu elkarbanatze maila hau duten torrentak
-ConfigView.label.seeding.ignore.header.evenFirstPriority=Baztertu  baita ere \nLehentasun Nagusia arauak ezarrita dituzten torrentak
-ConfigView.label.seeding.ignore.header.rule=Araua
-ConfigView.label.seeding.ignore.header.value=Balioa
-ConfigView.label.seeding.firstPriority.info=Lehentasun nagusiko torrentak betik egongo dira lerroaren gorenaldean\nLehentasun Nagusia irizpidea betetzen duen edozein torrent ez da berezgaitasunez gelditua eta lerrokatua izango.\nLehentasun Nagusia irizpidea duen torrentak Aldibereko Jeisketa ahoa hartu dezake behar izanez gero.
-ConfigView.label.seeding.firstPriority.FP=Lehentasun Nagusia
-ConfigView.label.seeding.firstPriority=Lehentasun nagusia doa hau duten torrentetatik
-ConfigView.label.seeding.firstPriority.following=hurrengoetara:
-ConfigView.label.seeding.firstPriority.shareRatio=Elkarbanatze maila honen azpitik
-ConfigView.label.seeding.firstPriority.seedingMinutes=Igarotako denbora jeisten emaritzara aldatu denetik
-ConfigView.label.seeding.firstPriority.DLMinutes=Igarotako denbora jeisten hastetik
-ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Kopia oso 1 X hartzaileko dela saiatuz, hartzaile zenbateko handia duten torrenteen lerruna murrizten duzu.\nZihurrena da, hartzaile zenbateko handiena duten torrentak dutela ere joan-etorri handiena.\nHonek ez du aldatzen erakutsitako 'emaritzen Z' bat ere.
-ConfigView.label.seeding.numPeersAsFullCopy=Saiatu kopia oso Bat izaten denentzat\n(0 : Ez Saiatu)
-ConfigView.label.seeding.preferLargerSwarms.tooltip=Nagusiki 'buxatuta' dauden hartzaileekin emaritzen ari bazara torrentak, nahiago izatea erletalde handiagoak zentzua du\nNagusiki eskuragarritasun handiko torrentak emaritzen ari zarenean, nahiago izatea erletalde txikiak zentzua du.
-ConfigView.label.seeding.preferLargerSwarms=Torrentak lerrun bera dutenean, nahiago izan erletalde handiak
-ConfigView.label.seeding.rankType.none.tooltip=Antolakuntza ohinarrituta Z zutabean
-ConfigView.label.seeding.rankType.none=Bat ere ez
-ConfigView.label.seeding.rankType.peer.tooltip=hartzaile gehiago eta emaritza gutxiago = lerrun handiagoa\nLerrun honek gutxiagotu egiten du eraginda eduki behar diren torrent zenbatekoa igoera gehieneratzeko.
-ConfigView.label.seeding.rankType.peer=Berdingarritutako Hartzaile Zenbaketa
-ConfigView.label.seeding.rankType.peerSeed.options=Hartzaile:Emaritza Maila Aukerak
-ConfigView.label.seeding.rankType.peerSeed.tooltip=Maila Handiena = Lerrun Handiena
-ConfigView.label.seeding.rankType.peerSeed=Hartzaileak: Emaritza Maila
-ConfigView.label.seeding.rankType.seed.fallback=Hartzaileentzako Gordeta: Emaritza Maila ondoren  \n(0 : Inoiz Ez Gordeta)
-ConfigView.label.seeding.rankType.seed.options=Emaritza Zenbaketa Bakarrik Aukerak
-ConfigView.label.seeding.rankType.seed.tooltip=Emaritza Gutxiago = Lerrun Handiagoa
-ConfigView.label.seeding.rankType.seed=Emaritza Zenbaketa Bakarrik
-ConfigView.label.seeding.rankType.timedRotation.tooltip=Lerrokatutako torrent osatu guzitiak emaletzen moduan itzulikatuko dira.\nEmaletze denbora 'Gutxiengo Emaletza Denbora' bidez ezartzen da
-ConfigView.label.seeding.rankType.timedRotation=Denboratutako Itzulikapena
-ConfigView.label.seeding.rankType.tooltip=Lerrun handiena duten torrentak berezgaitasunez hasten dira.\nBeste torrent batek lerrun handiagoa lortzen duenean, lerrun txikienekoa gelditu eta lerrora itzultzen da.\n\nLerrokatuta egoeran dauden torrentak bakarrik daude baliagarri berezgaitasunez hasteko.\nGelditutako torrentak ez dira inoiz berezgaitasunez hasten.
-ConfigView.label.seeding.rankType=Lerrun osatutako torrentak berez-hasteko ohinarriturik:
-ConfigView.label.stopAfterMinutes=Behin emaritzari elkarketaturik, gelditu aldibatez
-ConfigView.label.switchpriority.tooltip=Lehentasun txikiak torrentari izendaturiko igoera bandazabalera zenbatekoa murrizten du
-ConfigView.pluginlist.info=Hurrengo pluginak ezagutu dira. Plugin batzuek badaiteke ez izatea itxurapen hegatsik.
-ConfigView.pluginlist.noplugins=Ez pluginik aurkitu
-ConfigView.section.pluginslist=Zerrenda
-ConfigView.section.queue.seeding=Emaritzen
-ConfigView.section.queue.seeding.autoStarting=Berez Abiatzea
-ConfigView.section.queue.seeding.ignore=Baztertu Arauak 
-ConfigView.section.queue.seeding.firstPriority=Lehentasun Nagusia
-ConfigView.section.queue.main=Nagusia
-ConfigView.section.queue=Lerroa
-ConfigView.section.torrents=Torrentak
-ConfigView.text.all=denak
-ConfigView.text.hours=ordu
-ConfigView.text.ignoreRule=Baztertu Arauak
-ConfigView.text.ignore=Baztertu
-ConfigView.text.minutes=minutu
-ConfigView.text.neverIgnore=Ez Baztertu Inoiz
-ConfigView.text.any=edozein
-DownloadManager.error.datamissing=Datuak Ez daude
-MainWindow.menu.file.open.torrentforseeding=Torrent Agiria... (Emaritzarako)
-MainWindow.menu.language.refresh=&Berritu
-ManagerItem.forced=Behartuta
-ManagerItem.queued=Lerrokatuta
-MySeedersView.header=Osatutako Torrentak
-TableColumn.header.availability.info=Zenbat kopia oso izan diren ikusiak
-TableColumn.header.availability=Eskuragarritasuna
-TableColumn.header.category=Kategoria
-MyTorrentsView.header=Torrent Osatugabeak
-TableColumn.header.maxuploads=Geh. Igoera Zenbatekoa
-MyTorrentsView.menu.category.delete=&Ezabatu Kategoria
-MyTorrentsView.menu.forceStart=&Behartu Hastera
-MyTorrentsView.menu.queue=&Lerrokatu
-MyTorrentsView.menu.setCategory.add=&Gehitu Kategoria...
-MyTorrentsView.menu.setCategory=E&zarri Kategoria
-TableColumn.header.savepath=Gordetze Helburua
-TableColumn.header.SeedingRank=Emaritza Maila
-TableColumn.header.totalspeed.info=Hona elkarketaturik dauden hartzaile guztien Abiadura Guztira
-TableColumn.header.totalspeed=Abiadura Guztira
-splash.initializePlugins=Pluginak Abiarazten
-StartStopRules.SPratioMet=S:P Maila Ongi
-StartStopRules.FP0Peers=FP / 0 Hartzaile
-StartStopRules.0Peers=0 Hartzaile
-StartStopRules.numSeedsMet=Emaritzak Ongi
-StartStopRules.ratioMet=Hartzaileak:Emaritza Ongi
-StartStopRules.shareRatioMet=Elkarbanatze Maila Ongi
-StartStopRules.waiting=Itxaroten
-StartStopRules.firstPriority=1. Lehentasuna
-ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Elkarbanatze Edukiak (Baliabidegarria)
-DownloadManager.error.unabletostartserver=Ezgaitu Hasi Zerbitzaria - egiaztatu sarrera atakaren ezarpenak / suhesi baimenak aplikazioa zerbitzari bezala jarduteko
-GeneralView.label.creationdate=Sortua:
-ConfigView.section.tracker.announcescrapepercentage=Zuritu tartea  % iragarpen epea\nadib. 200 = 2:1. 0 = zer erabaki hartzaile artean
-ManagerItem.stopping=Gelditzen
-ConfigView.section.tracker.announcecacheperiod=Iragarle katxea (milaen)
-ConfigView.section.tracker.scrapecacheperiod=Zuripen katxea (smilaen)
-ConfigView.section.tracker.scrapeandcache=Zuripena eta katxea
-ConfigView.section.tracker.announcecacheminpeers=Iragarle katxeak hartzaile muga gaitzen du
-MyTrackerView.scrapes=Zurituak
-fileDownloadWindow.retry=Saiatu berriz
-MyTrackerView.bytesin=Sar. Byte
-MyTrackerView.bytesinave=Sar. Bat.best.
-MyTrackerView.bytesout=Irt. Byte
-MyTrackerView.bytesoutave=Irt. Bat.best.
-ConfigView.section.file.max_open_files=Gehienezko agiri ireki irakurtzeko/idazteko\n[0: mugagabea]
-ConfigView.section.file.max_open_files.tooltip=Erabili ehundaka/milaka agiriko torrentak jeisketen badituzu, eta SE-ren agiri eskuragarri mugara heltzen ari bazara.
-ConfigView.section.proxy=Proxy Aukerak
-ConfigView.section.proxy.enable_proxy=Gaitu proxya aztarnariarekiko harremanetarako [berrabiaraztea beharrezkoa]
-ConfigView.section.proxy.host=Hostalaria
-ConfigView.section.proxy.port=Ataka
-ConfigView.section.proxy.username=Erabiltzaile izena
-ConfigView.section.proxy.password=Sarhitza
-ConfigView.section.proxy.enable_socks=Nik SOCKS proxy bat dut
-wizard.createtorrent.extrahashes=Gehitu hashak beste sare batzuetatik (adib. Gnutella2, eDonkey2000)
-GeneralView.label.connected=elkarketaturik
-GeneralView.label.in_swarm=erletaldean
-ManagerItem.initializing=Abiarazten
-AlertMessageBox.error=Akatsa
-AlertMessageBox.warning=Kontuz
-AlertMessageBox.comment=Aipamena
-AlertMessageBox.information=Argibideak
-AlertMessageBox.unread=Irakurri gabeko mezu alertak dituzu - klikatu hemen ikusteko.
-SharedPortServer.alert.selectorfailed=Huts egin du sarrerako datuen aditze ezartzeak.\nEgiaztatu suhesi ezarpenak java(w).exe baimentzen duen 'zerbitzari' bezala ekiteko
-Tracker.alert.listenfail=Hutsegitea aditzea ataka honetan %1 ezartzerakoan.\nEgiaztatu beste aplikazioak ez daudela ataka hau erabiltzen.\nEgiaztatu ere lanean diharduten Vuzeren beste kopiak.
-DiskManager.alert.movefileexists=Akatsa osatutako agiria mugitzerakoan\nAgiria %1 jadanik badago Mugitu Hona helbide zuz
-DiskManager.alert.movefilefails=Akatsa osatutako agiria mugitzerakoan\nAgiri mugitua %1 huts eginda\u005c, %2
-DiskManager.alert.movefilerecoveryfails=Berreskurapen akatsa mugitzeak hutsegin ondoren\nAgiri berreskurapena %1 huts eginda, %2
-ConfigView.section.tracker.logenable=Ohar-agiritu aldizkako estatistikak 'aztarnari.oharrak'-rako
-SpeedView.stats.title=Estatistikak
-SpeedView.stats.total=Guztira:
-SpeedView.stats.session=Saio Honetan:
-SpeedView.stats.session.tooltip=Guztira (Protokoloa)
-SpeedView.stats.downloaded=Jeisketa (Hartuemana)
-SpeedView.stats.uploaded=Igoera (Hartuemana)
-SpeedView.stats.ratio=Maila
-SpeedView.stats.uptime=Denbora
-SpeedView.stats.now=Orain:
-SpeedView.stats.now.tooltip=Guztira (Protokoloa)
-AutoMigration.useralert=Vuzek agiri/helbide itxurapen berez-migraketa erabiltzen du, emaitzak:\n\n%1\nHutsegite batzuk eskuz migratu behar dira.\nEZ AHAZTU EGUNERATZEAZ GORDETAKO ZURE HELBURUAK ITXURAPENEAN MIGRATU EGIN BADUTE!
-#
-# > 2.0.8.0
-#
-OpenTorrentWindow.title=Ireki Torrenta(k)
-# Not used, but could be renamed in all translation files to label.experimental :)
-OpenTorrentWindow.message=Esperimentala
-OpenTorrentWindow.addFiles=&Gehitu Agiriak
-OpenTorrentWindow.dataLocation=Datuak gordetzeko helbidea:
-OpenTorrentWindow.startMode=Gehitu Modua
-OpenTorrentWindow.startMode.queued=Lerrokatuta
-OpenTorrentWindow.startMode.stopped=Geldituta
-OpenTorrentWindow.startMode.forceStarted=Behartu Hastea
-OpenTorrentWindow.addPosition=Lerroko Kokapena
-OpenTorrentWindow.addPosition.first=Lehena
-OpenTorrentWindow.addPosition.last=Azkena
-TableColumn.header.remaining.info=Jeisteke dagoenaren zenbatekoa
-TableColumn.header.remaining=Egiteke
-ConfigView.section.tracker.enablecompact=Gaitu iragarpen harreman trinkoa
-ConfigView.section.tracker.enablekey=Gaitu giltza sartzea aztarnariarentzat segurtasuna hobetzeko
-ConfigView.section.file.perf=Egintza Aukerak
-ConfigView.section.file.perf.explain=Kontuz - Neurri hauen aldaketek kalterako eragin dezakete jeisketan. Berrabiarazpena beharrezkoa da.\n'oraimen gabe' arazoak badituzu torrent elkarketak mugatzea kontuan hartu beharko duzu. (Ikusi Eskualdaketa itxurapena)
-ConfigView.section.file.max_open_files.explain=Agiri asko irekitzeak arazoak eragin ditzake sistema eragilean, baliabide mugapena agiri eskuratzean bezalakoak. Honek aldiberean irekita egon daitezkeen agiriak mugatzen ditu.
-popup.error.hide=Ezkutatu
-popup.error.details=Xehetasunak
-ConfigView.section.style.colorOverrides=Margo Ezabatuak
-ConfigView.section.style.colorOverride.progressBar=Garapen Barra
-ConfigView.section.style.colorOverride.error=Akatsa
-MainWindow.status.tooOld=zaharra da, mesedez eguneratu ezazu
-ConfigView.section.style.colorOverride.warning=Kontuz
-ConfigView.section.style.colorOverride.altRow=Aldizkako Lerroak
-ConfigView.section.file.save.peers.enable=Gorde hartzaile elkarketak berrelkarketa azkarretarako
-ConfigView.section.file.save.peers.max=Gehienezko hartzaile gordetzeko [0:mugagabe]
-ConfigView.section.file.save.peers.pertorrent=torrent bakoitzeko
-ConfigView.label.max_peers_per_torrent=Geh elkarketa torrent bakoitzeko [0: mugagabea]
-ConfigView.label.max_peers_total=Geh.elkarketa orokorrean [0: mugagabea]
-ConfigView.section.style.colorOverrides.reset=Berrezarri Margoa
-ConfigView.section.language.info=Gaituta dagoenean,  eguneratze egiaztapena Vuze abiarazten den bakoitzean egingo da.
-ConfigView.section.language.enableUpdate=Gaitu Web Eguneraketa
-ConfigView.section.language.UpdateURL=Eguneratu URL-a
-ConfigView.section.language.UpdateNow=Eguneratu Orain!
-Button.revert=Jauzi atzera
-MyTorrentsView.menu.changeDirectory=Aldatu Datu Zuzenbidea
-GenericText.column=zutabea
-MyTorrentsView.menu.thisColumn.remove=Kendu Zutabea
-MyTorrentsView.menu.thisColumn.toClipboard=Kopiatu Idatzia Gakoan
-MyTorrentsView.menu.thisColumn.autoTooltip=Betik erakutsi tresnen argibideak
-MyTorrentsView.menu.tracker=Aztarnaria/&Torrenta
-ConfigView.download.abbreviated=J:
-ConfigView.upload.abbreviated=I:
-ConfigView.complete.abbreviated=O:
-TableColumn.header.secondsseeding=Emaritzen
-TableColumn.header.secondsseeding.info=Emaritzen egon zaren denboraren zenbatekoa guztira
-TableColumn.header.secondsdownloading=Jeisten
-TableColumn.header.secondsdownloading.info=Jeisten egon zaren denboraren zenbatekoa guztira.
-ConfigView.section.tracker.udpversion=UDP Protokolo Bertsioa (1 edo 2)
-window.updateswt.title=Zure SWT Bertsio zaharregia da!
-window.updateswt.text=Zure SWT Bertsioa zaharregia da!\nSWT Vuzek erabiltzen duen grafika liburutegia da eta zuk duzun bertsioa zaharregia da Vuzeren azken bertsioarekin lan egiteko. Klikatu 'Ongi' botoia zure SWT-a eguneratzeko.
-window.updateswt.status=Egoera
-window.updateswt.failed=Eguneratzeak huts egin du, sakatu Ongi berriro berrabiarazteko.
-window.updateswt.status.downloading.updater=Eguneratze Moduloa Jeisten
-window.updateswt.status.finding=SWT Betsio berriena bilatzen
-window.updateswt.status.downloading=SWT Bertsio Berriena Jeisten
-window.updateswt.status.done=Berrabiarazten
-window.updateswt.ok=Ongi
-window.updateswt.cancel=Ezeztatu
-swt.updater.downloader.downloading=SWT hemendik jeisten
-swt.updater.urlsgetter.downloading=Ispilu zerrenda bat lortu hemendik
-swt.updater.urlsgetter.platform=Plataformarako SWT-a:
-window.updateswt.ignore=Ez ikusi
-ConfigView.section.style.useFancyTabs=Erabili Apain Hegatsak
-splash.initializeGM=Torrent Kudeatzaile Orokorra Abiarazten
-splash.loadingTorrents=Torrentak Gertatzen
-MyTorrentsView.menu.thisColumn.sort=&Antolatu
-Scrape.status.ok=Zuritzea Ongi
-Scrape.status.error=Zuritze Akatsa:
-Scrape.status.error.badURL=Iragarle URL-ak ez ditu zuritze zehaztapenak jarraitzen.
-Scrape.status.error.nohash=Hasha erantzun gabe.
-Scrape.status.error.invalid=Erantzun okerra.
-Scrape.status.nextScrapeAt=Hurrengo zuritzea %1
-Scrape.status.scraping=Zuritzen...
-Scrape.status.initializing=Zuritzeko itxaroten...
-Scrape.status.scraping.queued=Lerrokatuak zuritzen...
-ConfigView.label.minSpeedForActiveSeeding=Ez zenbatu osatutako torrentik aho bat erabiltzen ari bada abiadura honen azpitik
-ConfigView.section.stats.exportpeers=Esportatu hartzaile xehetasunak
-MainWindow.menu.view.irc.moved=Irc orain eskuragarri dago plugin bezala, ikusi http://plugins.vuze.com/plugin_list.php. Ezarritakoan erabili ikuspegi hau ->pluginak->IRC sarbide menua.
-MyTrackerView.webui.contextmenu.copyurl=Kopiatu torrentaren URL-a gakoan
-ConfigView.section.file.torrent.ignorefiles=Baztertzeko agiriak torrentak sortzen/ezabatzen direnean\n - adib. .DS_Store; Thumbs.db
-Torrent.create.progress.ignoringfile=Agiria baztertzen
-ConfigView.section.style.useUnitsRateBits=Erabili bitak byten ordez byte-ohin neurri balioetan  (KiB/s->Kibit/s etab.)
-ConfigView.section.interface.resetassoc=Leheneratu explorer agiri elkartzea (.torrent) eta erakarpen kudeatzailea (magnet:?xt=...)
-ConfigView.section.interface.resetassocbutton=Berrezarri
-ConfigView.section.interface.checkassoc=Egiaztatu elkartzeak hasitakoan
-dialog.associations.title=Elkartze Egiaztapena
-Button.yes=&Bai
-Button.no=&Ez
-ConfigView.label.seeding.autoStart0Peers=Berez Hasi 0 hartzaile duten osaturiko torrent denak
-ConfigView.label.seeding.autoStart0Peers.tooltip=Piztu nahi baduzu aztarnariak betik zerrendatzea emaritzak 0 hartzaile torrenteko.
-dialog.associations.prompt=Vuze ez da BitTorrent agirientzako berezko aplikazioa.\nNahi duzu .torrent agiriak Vuzerekin elkartzea
-dialog.associations.askagain=Egiaztatu hasitakoan
-ConfigView.section.plugins.update=Plugin Eguneratzea
-Plugin.pluginupdate.enablecheck=Gaitu plugin eguneratze egiaztapena
-plugins.basicview.status=Egoera:
-plugins.basicview.activity=Jarduera:
-plugins.basicview.progress=Garapena:
-plugins.basicview.log=Saioa:
-ConfigView.label.maxdownloadspeed=KB/s geh. jeisketa abiadura orokorra [0: mugagabea]
-splash.loadingTorrent=Torrenta Gertatzen
-splash.of=.
-UpdateWindow.title=Vuze Eguneratzailea
-UpdateWindow.header=Hurrengo osagaiek eguneraketa behar dute:
-UpdateWindow.columns.install=Ezarri
-UpdateWindow.columns.name=Izena
-UpdateWindow.columns.version=Bertsioa
-UpdateWindow.columns.size=Neurria
-UpdateWindow.cancel=Ezeztatu
-UpdateWindow.quit=Irten
-UpdateWindow.close=Itxi
-UpdateWindow.ok=Eguneratu
-UpdateWindow.restart=Berrabiarazi Vuze Orain
-UpdateWindow.status.downloading=Jeisten
-UpdateWindow.status.done=Eginda
-UpdateWindow.status.failed=Huts egin du
-UpdateWindow.status.restartNeeded=Berrabiaraztea beharrezkoa da!
-ConfigView.pluginlist.broken=Hautsita
-ConfigView.pluginlist.whereToPut=Ezarri erabiltzaile osagarri bereiziak zeure zuzenbidean: 
-ConfigView.pluginlist.whereToPutOr=Elkarbanatutako pluginentzat erabili:
-MainWindow.statusText.checking=Bilatu Eguneraketak
-TableColumn.header.OnlyCDing4=CDing4 Bakarrik
-TableColumn.header.OnlyCDing4.info=Torrenta emaritzan bakarrik egon den denbora. Kenduta torrenta jeisten (eta emaletzan) egon den denbora.
-UpdateWindow.status.restartMaybeNeeded=Berrabiaraztea beharrezkoa izan daiteke
-ConfigView.pluginlist.shared=elkarbanatuta
-PeersView.host=Hostalari Izena
-PeersView.host.info=Hartzailearen hostalari izena, eskuragarria denean (egintzari eragin diezaioke)
-MainWindow.menu.help.whatsnew=Zer Berri
-ConfigView.label.checkonstart=Egiaztatu azken bertsioa dudala Vuze abiatzerakoan
-ConfigView.label.periodiccheck=Egiaztatu aldizka azken bertsioa ezarrita dagoela
-ConfigView.label.opendialog=Berezgaitasunez ireki Eguneratze Laguntzailea eguneraketa eskuragarri dagoenean
-MainWindow.updateavail=Egin klik hemen eguneraketak bilatzeko
-MainWindow.status.latestversionunchecked=Bertsio egiaztapena ezgaiturik
-GeneralView.label.updatein.stopped=Geldituta
-StartStopRules.menu.viewDebug=Ikusi Garbiketa Argibideak
-ConfigView.section.style.doNotUseGB=Ez erabili GB batasunik
-ConfigView.section.style.doNotUseGB.tooltip=Hautaturik badago, Vuzek jarraitu dezake erabiltzen MB baita 1024 MB baino handiagoak diren neurriekin
-MainWindow.menu.help.plugins=Lortu Pluginak
-ConfigView.section.plugins.TrackerWeb=Aztarnari Webgunea
-ConfigView.section.tracker.enablecategories=Banandu torrentak kategoriatan
-health.explain.share=Esanahi du torrenta ongi hostatuta edo argitaratuta dagoela
-ConfigView.section.tracker.createcert=Sortu bere-izenpetze egiaztagiria
-ConfigView.section.tracker.createbutton=Sortu
-security.certcreate.title=Sortu Bere-Sinatze Egiaztagiria
-security.certcreate.intro=Elkarrizketa honek bere-sinatze egiaztagiri bat sortzea ahalbidetzen ditzu
-security.certcreate.alias=Ezizena
-security.certcreate.strength=Indarra
-security.certcreate.firstlastname=Lehen eta bigarren  izena
-security.certcreate.orgunit=Erakunde Batasuna
-security.certcreate.org=Erakundea
-security.certcreate.city=Hiria edo Herria
-security.certcreate.state=Estatua edo Herrialdea
-security.certcreate.country=Bi hizkiko estatu kodea
-security.certcreate.ok=Sortu
-security.certcreate.cancel=Ezeztatu
-security.certcreate.createok=Egiaztagiria ongi sortu da
-security.certcreate.createfail=Egiaztaturiko sortzeak huts egin du
-ConfigView.section.plugins.webui=Swing Web Interfazea
-ConfigView.section.plugins.xml_http_if=XML/HTTP Interfazea
-webui.passwordenable=Gaitu sarhitza
-webui.user=Erabiltzaile izena
-webui.password=Sarhitza
-webui.port=Ataka
-webui.protocol=Hartuemana
-webui.homepage=Etxeko orrialdea
-webui.rootdir=Erro zuzenbidea
-webui.rootres=Erro baliabidea
-webui.mode=Modua
-webui.mode.info=Modua izan daiteke\n\t"osoa"\t= eragiketa guztiak egingarri (berezkoa)\n\t"ikusi"\t= ikusi bakarrik (baina berritze maiztasuna eguneratu dezake)
-webui.access=Sarbidea
-webui.access.info=Sarbidea izan daiteke\n\t"tokikoa"\t= tokiko gailua bakarrik elkarketatu daitekela\n\t"denak"\t= eragozpen gabeko sarbidea (berezkoa)\n\tIP-a\t= adib. 192.168.0.2\t\t\u005c IP-a bakarrik\n\tIP1-IP2\t= adib. 192.168.0.1-192.168.0.255\u005cIP eremuak barne
-GeneralView.label.maxdownloadspeed=Jeisketa Muga
-Security.keystore.corrupt='%1' giltzabiltegiak huts egin du, mesedez ezabatu hura eta birsortu/bir-inportatu egiaztagiriak
-Security.keystore.empty=Giltzabiltegia hutsik dago. Mesedez sortu berez-izenemate egiaztagiri bat (ikusi Tresnak->Aukerak->Segurtasuna) edo inportatu '%1'-ra jadanik  baduzun egiaztagiri bat 
-GeneralView.label.maxdownloadspeed.tooltip=geh. jeisketa abiadura [0: mugagabea]
-upnp.enable=Gaitu UPnP
-upnp.info=Plug and Play Unibertsalak (UPnP) ahalbidetzen du berezgaitasunezko ataka izendatzea gaituriko UPnP routerretan.
-upnp.mapping.dataport=Sarrerako Hartzaile Datu Ataka
-upnp.mapping.tcptrackerport=TCP Aztarnari Ataka
-upnp.mapping.udptrackerport=UDP Aztarnari Ataka
-upnp.alert.differenthost=UPnP: '%1'izendapena honek hartuta dago '%2' - mesedez aukeratu ataka ezberdin bat
-upnp.alert.mappingok=UPnP: Izendapena '%1' ezarrita
-upnp.alert.mappingfailed=UPnP: Izendapenak '%1' huts egin du
-upnp.alertsuccess=Jakinarazi zuzen egindako izendapenak
-upnp.alert.lostdevice=UPnP: Zerbitzuarekin elkarketa etenda '%1' UPnP gailuan '%2'
-upnp.grabports=Ataken mapaketa egin beste ordenagailu batekoak izanda ere
-upnp.refresh.label=Berritu mapaketak
-upnp.refresh.button=Berritu
-upnp.alert.mappinggrabbed=UPnP: Izendapena '%1' ezarrita - helduta '%2'
-upnp.mapping.tcpssltrackerport=TCP SSL Aztarnari Ataka
-upnp.alertothermappings=Beste ordenagailuetako ataken berri eman
-upnp.alertdeviceproblems=Jakinarazi UPnP gailuarekin izandako arazoak
-upnp.trace_to_log=Irteerako garbiketa argibide osoa saioa hasteko
-upnp.wiki_link=Vuze Wiki orrialdea UPnP-n
-upnp.refresh_mappings_on_bad_nat=Berezgaitasunez berritu izendapenak  NAT egoera "suhesiturik" denean
-blank.resource=Baliabidea
-ConfigView.pluginlist.coreplugins=Hurrengo baterapen pluginak gertatu dira:
-Peers.column.DLedFromOthers=Beste Batzuetatik
-Peers.column.DLedFromOthers.info=Zurekin elkarketatutakoan beste batzuengandik jeitsitako datu zenbatekoa
-Peers.column.UpDownRatio=Igota:Jeitsita
-Peers.column.UpDownRatio.info=Hartzailearen "Igota:Jeitsita" Maila
-Peers.column.UpRatio=Igoera Maila
-Peers.column.UpRatio.info=Hartzailearen "Zuretik Igota : Besteetatik Igota" Maila
-upnp.releasemappings=Askatu mapaketak itxieran
-webui.upnpenable=Gaitu UPnP ataka honentzat
-ConfigView.section.file.friendly.hashchecking=Lagunarteko hash egiaztapena
-ConfigView.section.file.friendly.hashchecking.tooltip=Atal hashegiaztepen modu astiroagoa baina estutasun gutxiagokoa cpu/sistemarentzat.
-ConfigView.section.tracker.seedretention=Geh. emaritza atxikia torrent bakoitzeko [0:mugagabea]
-ConfigView.section.tracker.seedretention.info=Oharra: Igoera estatistikak galdu egin daitezke emaritza ez-atxikietan
-ConfigView.section.tracker.port=Gaitu aztarnaria HTTP atakan
-ConfigView.section.tracker.sslport=Gaitu aztarnaria HTTPS atakan
-ConfigView.section.tracker.publicenable.info=Honek besteei ahalbidetzen die zure aztarnaria erabiltzen duten torrentak sortzea\nzuk haiek hostaturatu/argitaratu gabe
-Button.clear=Garbitu
-MainWindow.IPs.tooltip=Iragazki zerrendaren azken eguneratzea: %1\nGuztira IP Iragazkiak zerrendan - Itxitako/eragotzitako/gaitz IP-ak saio honetan.\nKlik bikoitza xehetasunak ikusteko.
-ConfigView.section.ipfilter.list.banned=Eragotzia izan da
-ConfigView.section.ipfilter.list.baddata=datu gaitzak bidali ditu.: gertaerak =
-Button.reset=Berrezarri
-ConfigView.section.ipfilter.bannedinfo=Datu gaitzak bidaltzen dituzten IP-ak - eragotzi muga gainditzen badute
-ConfigView.section.ipfilter.blockedinfo=IP iragazkiengaitik itxiak izan diren IP-ak
-download.removerules.name=Kenketa Arauak
-download.removerules.unauthorised.info=Baimengabeko torrentak dira iragarri erantzunean "ez baimendua" edo "baimengabea" dutenak "hutsegite erantzunean" 
-download.removerules.unauthorised=Berezgaitasunez kendu baimengabeko torrentak
-download.removerules.unauthorised.seedingonly=\tEmaritzan bakarrik
-download.removerules.removed.ok=Ongi buruturiko torrenteen '%1' berezgaitasunezko kenketa . Hau torrenteen kenketa arauengaitik zen.
-download.removerules.updatetorrents=Kendu Vuze eguneratze torrentak erletaldeak eskatzen badu
-ConfigView.label.defaultstarttorrentsstopped=Lehenespenez gehitu torrent berriak geldituta egoera batean
-ConfigView.section.server.enableudp=Gaitu UDP aztarnari bezero hartuemana
-upnp.mapping.dataportudp=UDP aztarnari bezero ataka
-ConfigView.section.file.decoder.showlax=Erakutsi aukera gutxieneko kodeaketak
-ConfigView.section.file.decoder.showall=Kontuan izan ahalezko kodeaketa denak
-MainWindow.status.updowndetails.tooltip=Jeisketa/Igoera abiadura xehatasunak\nEskuin-klikatu aldatzeko, Klik Bikoitza estatistikak irekitzeko
-TrackerClient.announce.warningmessage=Aztarnaria '%1' larri itzuli da '%2'
-ConfigView.section.tracker.natcheckenable=Egiaztatu 'sarrera datu ataka' elkarketagarritasuna eta jakinarazi akatsak hartzaileei
-ConfigView.section.tracker.publishenabledetails=Argitaratu torrent guztien xehetasunak
-ConfigView.section.tracker.publishenablepeerdetails=Argitaratu hartzaile xehetasunak
-MyTrackerView.badnat=NAT Gaitzak
-MyTrackerView.badnat.info=NAT egiaztapen bat huts eginda duten Emaritza/Hartzaileak, gaituta badago
-ConfigView.section.tracker.natchecktimeout=Egiaztatu itxaronaldia (seg)
-ConfigView.section.file.perf.cache.enable=Gaitu diska katxea
-ConfigView.section.file.perf.cache.size=Katxe neurria %1
-MainWindow.menu.transfers=&Eskualdaketak
-MainWindow.menu.transfers.startalltransfers=&Hasi Denak
-MainWindow.menu.transfers.stopalltransfers=&Gelditu Denak
-MainWindow.menu.transfers.pausetransfers=&Pausatu
-MainWindow.menu.transfers.resumetransfers=&Berrekin
-ConfigView.label.experimental.osx.kernel.panic.fix=Zuzenketa esperimentala kernel panics dual-cpu OSX sistemarentzat [berrabiaraztea beharrezkoa]
-SystemTray.menu.pausetransfers=Pausarazi Eskualdaketak
-SystemTray.menu.resumetransfers=Berrekin Eskualdaketak
-ConfigView.section.file.truncate.too.large=Moztu handiegiak diren agiriak
-ConfigView.section.file.perf.cache.trace=Marraztu katxe eragiketak igarpen asmoetarako
-ConfigView.section.interface.enabletray=Gaitu Erabide Erretilua [berrabiaraztea beharrezkoa]
-PeerManager.status.error=Akatsa
-Stats.title.full=Estatistikak
-TransferStatsView.title.full=Eskualdaketak
-CacheView.title.full=Katxea
-CacheView.general.size=Neurria Guztira
-CacheView.general.inUse=Erabiltzen
-CacheView.general.title=Katxe Argibideak
-CacheView.reads.title=S/I Irakurriak
-CacheView.reads.fromFile=Agiritik
-CacheView.reads.fromCache=Katxetik
-CacheView.reads.hits=Kolpeak
-CacheView.writes.title=S/I Idatziak
-CacheView.writes.toCache=Katxera
-CacheView.writes.toFile=Agirira
-CacheView.writes.hits=Gordeta
-CacheView.speeds.title=Datu Neurriak
-CacheView.speeds.reads=Irakurriak
-CacheView.speeds.writes=Idatziak
-CacheView.speeds.fromCache=Katxetik/Katxera
-CacheView.speeds.fromFile=Agiritik/Agirira
-CacheView.reads.#=Zenb.
-CacheView.reads.amount=Zenbatekoa
-CacheView.reads.avgsize=Neurri Bataz-bestekoa
-openUrl.referrer=Orrialde URL-ari dagozkionak:
-openUrl.referrer.info=Beharrezkoa bakarrik eskatzen duten webguneetan
-ConfigView.label.maxuploadspeedseeding=Ordezpen maila emaritzan bakarrik dagoenean
-ConfigView.label.transfer.ignorepeerports=Baztertu datu ataka hauek dituzten hartzaileak (';' bananduta, adib. 0;25)
-ConfigView.section.proxy.enable_socks.peer=Gaitu proxya hartzaileekiko harremanetarako (kanporako elkarketak bakarrik) [berrabiaraztea beharrezkoa]
-ConfigView.section.proxy.peer.informtracker=Jakinarazi aztarnariari mugapena
-ConfigView.section.proxy.socks.version=SOCKS bertsioa
-PiecesView.legend.written=Idatzia
-PiecesView.legend.requested=Eskabidetuta
-PiecesView.legend.downloaded=Jeitsita, idazketa itxaroten
-PiecesView.legend.incache=Datua Katxean dago
-PiecesView.typeItem.0=Astiroa
-PiecesView.typeItem.1=Azkarra
-PiecesView.type=Mota
-Security.jar.tools_not_found=JAR sinadura okerra - 'tools.jar' ez da aurkitu hemen: %1. Ikusi Tresnak->Aukerak->Segurtasuna xehetasunetarako.
-Security.jar.signfail=JAR sinadura okerra - %1
-ConfigView.section.security.toolsinfo=JAR agiri izenpetuak plugin batzuk laguntzeko erabiltzen dira, adibidez Swing Web Interfazea (hori egiteko itxuratzen denean).\nJAR agiriak izenpetzeko asmoarekin beharrezkoa da Sun JDK (ez JRE) ezarpenarekin datorren 'tools.jar' agirira sarbidea izatea.\nJRE bakarrik baduzu ezarrita mesedez ezarri ezazu JDK.\nVuzek agiria zure ordez bilatu dezake. Horrela ere, honek huts egiten badu zeuk agerian ezarri dezakezu hemen edukiaren zuzenbidea.
-ConfigView.section.security.toolsdir='tresnak.jar' dituen zuzenbidea
-ConfigView.section.security.choosetoolssavedir=Hautatu 'tools.jar' duen agiritegia
-authenticator.torrent=Torrenta
-ConfigView.section.proxy.peer.same=Erabili proxy ezarpen berberak aztarnari eta hartzaileekiko harreman proxyan
-ConfigView.section.connection.network.max.simultaneous.connect.attempts=Gehienezko aldibereko irteera elkarketa ahalegin
-ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Gehienezko irteera elkarketa berri ezartzen saiatu behar den Vuze une jakin batean.\nOHARRA: WindowsXP Service Pack 2 (SP2)-k ezartzen du erabide guztiarentzako aldibereko 10 elkarketa ahalegineko muga..\nBerezko balioa 8 da.
-ConfigView.section.file.perf.cache.size.explain=Katxea diska gogorrean egiten diren irakurketa/idazketa kopurua gutxiagotzeko erabiltzen da. Javaren '-XX:MaxDirectMemorySize' aukera erabili ezean katxearentzako eskuragarri dagoen oroimena eta sarearen S/I erabilpena agerian ezartzeko, balio hau zure VM-aren gehienezko neurriaren %1 azpitik eduki behar duzu. Oraingo VM-aren gehienezko neurria %2 da. Hau nola aldatu jarraipideak lortzeko, ikusi MemoryUsage wikian %3. Ezarpen sentikorretan  [...]
-MyTorrentsView.menu.setSpeed.unlimit=Mugagabea
-MyTorrentsView.menu.setSpeed.unlimited=Mugagabea
-MyTorrentsView.menu.setSpeed.disable=Ezgaitu Igoera
-MyTorrentsView.menu.setSpeed.disabled=Ezgaiturik
-MyTorrentsView.menu.setSpeed.in=*
-MyTorrentsView.menu.setSpeed.slots=ahoak
-GeneralView.label.maxuploadspeed=Igoera Muga
-GeneralView.label.maxuploadspeed.tooltip=geh. igoera abiadura [0 : mugagabea]
-MyTorrents.items.UpSpeedLimit.disabled=Ez igo
-MyTorrents.items.UpSpeedLimit.unlimited=Mugagabe
-TableColumn.header.maxupspeed=Geh. Igoera Abiadura
-TableColumn.header.maxupspeed.info=Hartzailean ezarritako igoera abiadura muga
-ConfigView.section.file.perf.cache.enable.write=Katxeak datuak jeisten ditu diskaren idazketak gutxitzeko eta baita ere gutxitzen du diskak atal egiaztapenerako egin behar dituen irakurketak
-ConfigView.section.file.perf.cache.enable.read=Egin irakurri-aurrera diskaren irakurketak gutxitzeko igotzen ari zarenean
-ConfigView.section.tracker.separatepeerids=Erabili hartzaile nortasun ezberdinak aztarnariarentzat eta datu harremanerako
-ConfigView.section.tracker.separatepeerids.info=Izengabeko jarduera handituz jeisketa/emaritza izengabean\nez-izengabeko aztarnari elkarketa erabiltzen den bitartean
-ConfigView.section.interface.wavlocation=Helbidea .wav agiriarentzat
-ConfigView.section.interface.wavlocation.info=Hautatu .wav agiria edo utzi hutsik berezko soinuarentzat
-ConfigView.section.tracker.server=Zerbitzaria
-ConfigView.section.tracker.client=Bezeroa
-ConfigView.section.tracker.client.connecttimeout=Elkarketa itxaronaldia (seg)
-ConfigView.section.tracker.client.readtimeout=Irakur itxaronaldia (seg)
-MainWindow.menu.tools=&Tresnak
-FilesView.path=Helburua:
-FilesView.fullpath=Erakusi Helburu Osoa
-FilesView.remaining=Gelditzen diren atalak
-TableColumn.header.trackername=Aztarnariaren Izena
-TableColumn.header.trackername.info=URL iragarpenean ohinarrituriko aztarnariaren izena
-ConfigView.group.override=Ezeztatu Aukerak
-ConfigView.section.file.perf.cache.notsmallerthan=Ez hau baino katxe agiri txikiagoak (%1)
-PeersView.menu.blockupload=Blokeatu Igoera
-PeersView.menu.kickandban=Ostikada eta Eragotzi
-PeersView.menu.kickandban.reason=Hartzailea eskuz eragotzia
-PeersView.state=Egoera
-PeersView.state.info=Hartzaile elkarketaren egoera
-PeersView.state.pending=Zain
-PeersView.state.connecting=Elkarketatzen
-PeersView.state.handshake=Eskuematearen zain
-PeersView.state.established=Osoki ezarrita
-ConfigView.section.tracker.processinglimits=Mugak prozesatzen
-ConfigView.section.tracker.maxgettime=Geh. denbora GET jardunerako (seg) [0: mugagabea]
-ConfigView.section.tracker.maxgettime.info=Iragarle eta zuritzetarako erabilia
-ConfigView.section.tracker.maxposttimemultiplier=GET denbora biderkatzailea POST jardunerako [0: mugagabea]
-ConfigView.section.tracker.maxposttimemultiplier.info=Azpieginkizunetarako eta igoeretarako erabilia
-ConfigView.section.tracker.maxthreads=Geh. eskabide aldiberean
-DownloadManager.error.operationcancancelled=Eragiketa ezeztatuta
-Torrent.create.progress.cancelled=Eragiketa ezeztatua
-sharing.progress.cancel=Ezeztatu
-wizard.maketorrents.autoopen=Ireki torrenta emaritzarako egindakoan
-ConfigView.section.sharing.rescanenable=Gaitu aldizkako birmihaketak elkarbanatzetan aldaketentzat
-ConfigView.section.sharing.rescanperiod=Birmihaketa aldia (seg)
-ConfigView.section.connection.advanced=Sare Ezarpen Aurreratua
-ConfigView.section.connection.advanced.url=http://wiki.vuze.com/w/UG_Options#Sare_Ezarpen_Aurreratuak
-ConfigView.section.connection.advanced.mtu=Gehienezko Eskualdaketa Batasuna Bidea (GEB)
-ConfigView.section.connection.advanced.mtu.tooltip=Sare bateko mugarri batean eskualdatu daitekeen pakete baten gehienezko neurria.\nVuzek MTU-40 (MSS) erabiltzen du paketeen-zamaerabilgarri igoera hoberenduenak egiteko.\nBalio gomendatuak:\n  576 - Urritizkin elkarketatarako\n1492 - PPPoE bandazabaleko elkarketetarako\n1500 - Ethernet, DSL eta Kable bandazabaleko elkarketetarako.
-ConfigView.section.connection.advanced.SO_RCVBUF=Hartunea SE_RCVBUF neurria [0: erabili SE berez]
-ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=SO_RCVBUF indar hartune estandarra ezartzen du, balioa (byte-tan), esanahi da, TCP leihoaren harrera eta eskala neurria.\nVuzek ezarri gabe uzten du berez, esanahi da azpiko SE-arentzako balio aurrezarriak erabili egiten dira.\nOHARRA; Linux bikoiztu egiten du emaniko balioa.
-ConfigView.section.connection.advanced.SO_SNDBUF=Hartune SO_SNDBUF neurria [0: erabili SE berez]
-ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=SO_SNDBUF indar hartune estandarra ezartzen du, balioa (byte-tan), esanahi da, TCP leihoaren harrera eta eskala neurria.\nVuzek ezarri gabe uzten du berez, esanahi da azpiko SE-arentzako balio aurrezarriak erabili egiten dira.\nOHARRA; Linux bikoiztu egiten du emaniko balioa.
-ConfigView.section.connection.advanced.IPDiffServ=Irteera pakete DiffServ balioa (TOS eremua)
-ConfigView.section.connection.advanced.IPDiffServ.tooltip=Zerbitzu Mota (TOS) eremuaren DiffServ atala ezartzen du IP buruan irteerako paketeentzat.\nBalio Hexadezimalak aurrezenbaki batez adierazi daitezke '0x', adib. 0x10.\nVuzek hau berez ezarrigabe uzten du, esanahi da azpiko SE-rentzako balio aurrezarriak erabili egiten dira\nOHARRA: Azpiko sarebideak balio hauek baztertu ditzake, hortaz aukera hau SE eta JavaRuntimeEnvironmet (JRE) bertsioaren oso araberakoa da.
-TableColumn.header.seed_to_peer_ratio=Emaritza-Hartzaile harremana
-TableColumn.header.seed_to_peer_ratio.info=Erletaldeko emaritza eta hartzaile arteko maila guztira
-PeersView.connected_time=Elkarketaturiko Denbora
-PeersView.connected_time.info=Hartzailearekin elkarketaturik emaniko denbora guztia
-TableColumn.header.maxdownspeed=Geh. Jeisketa Abiadura
-TableColumn.header.maxdownspeed.info=Hartzailean ezarritako jeisketa abiadura muga
-PeersGraphicView.title.full=Erletaldea
-ConfigView.section.tracker.passwordwebhttpsonly=HTTPS bidez bakarrik eskuratzea ahalbidetuta
-TableColumn.header.torrentpath=Torrent Helbidea
-TableColumn.header.torrentpath.info=Torrentak diskan duen helbidea
-ConfigView.section.sharing.torrentcomment=Sortutako torrententzako aipamenak
-ConfigView.label.copyanddeleteratherthanmove=Kopiatu eta orduan ezabatu jatorrizko datuak eragiketa bakar batean mugitu beharrean - lagundu dezake datuen galera eragozten agiri erabide batzuetan
-ConfigView.label.openstatsonstart=Ireki Estatistikak hasitakoan
-swt.install.window.title=Vuze Osagai/Plugin Ezartzailea
-swt.install.window.ok=Ezarri
-swt.install.window.header=Hurrengo osagaiak ezarriak izateko hautatuak izan dira:
-swt.uninstall.window.title=Vuze Osagai/Plugin Kentzailea
-swt.uninstall.window.ok=Kendu
-swt.uninstall.window.header=Hurrengo osagaiak kenduak izaeko hautatuak izan dira:
-installPluginsWizard.title=Ezarri Pluginak
-installPluginsWizard.mode.title=Mesedez hautatu ezarpen bide bat
-installPluginsWizard.mode.list=Sourceforge.net-eko zerrendatik
-installPluginsWizard.list.title=Plugin Ezarrigarrien Zerrenda
-installPluginsWizard.list.loading=Mesedez itxaron Plugin zerrenda gertatzen den bitartean.
-installPluginsWizard.list.loaded=Mesedez hautatu ezarri nahi dituzun pluginak.
-installPluginsWizard.list.name=Izena
-installPluginsWizard.list.version=Bertsioa
-installPluginsWizard.list.description=Pluginaren azalpena
-installPluginsWizard.finish.title=Ezarpena Garatzen
-installPluginsWizard.finish.explanation=Hautatutako Pluginak Eguneratze Laguntzailea erabiliz ezarri daitezke.\n\nMesedez lasai hartu, denbora apur bat behar izan dezake agertzeko.\n\nGarapenaren berri izateko, egin klik bikoitza egoera barraren ezkerraldean.
-installPluginsWizard.details.loading=Xehetasunak gertatzen, mesedez itxaron...
-installPluginsWizard.mode.file=Agiritik
-installPluginsWizard.installMode.title=Mesedez hautatu ezarpen mota
-installPluginsWizard.installMode.user=Ezarri plugina(k) zuretzat bakarrik
-installPluginsWizard.installMode.shared=Ezarri plugina(k) erabiltzaile guztientzat
-installPluginsWizard.file.title=Mesedez bilatu ezarri nahi duzun plugina
-installPluginsWizard.file.file=Agiria:
-installPluginsWizard.file.invalidfile=Agiria ez da baliozko Vuze plugina.
-installPluginsWizard.file.no_such_file=Ez dago emandako izenik duen agiririk
-installPluginsWizard.file.browse=Bilatu...
-uninstallPluginsWizard.title=Kendu Pluginak
-uninstallPluginsWizard.list.title=Ezarritako Plugin Zerrenda
-uninstallPluginsWizard.list.loaded=Mesedez hautatu kendu nahi dituzun pluginak
-installPluginsWizard.list.nullversion=Bertsiorik ez
-uninstallPluginsWizard.finish.title=Kentzearen Garapena
-uninstallPluginsWizard.finish.explanation=Hautaturiko Pluginak Eguneratze Laguntzailea erabiliz kendu daitezke
-MainWindow.menu.plugins.installPlugins=E&zarpen Laguntzailea...
-MainWindow.menu.plugins.uninstallPlugins=Ezarpena &Kentzeko Laguntzailea...
-ConfigView.section.ipfilter.totalIPs=%1 IP itxita guztira,  internetekoak %2 
-update.instance.install=Ezarpena Egiaztatzen
-update.instance.uninstall=Kentzea Egiaztatzen
-update.instance.update=Eguneraketak Egiaztatzen
-MainWindow.status.update.tooltip=Klik bikoitza garapen argibideak ikusteko
-updater.progress.window.title=Oraingo Ezarpen Eginkizunak
-updater.progress.window.info=Sakatu 'Utzi' egiteke dauden eginkizun guztiak amaitzeko
-Button.abort=Utzi
-ConfigView.section.ipfilter.enablebanning=Itxi datu gaitzak etengabe bildaltzen dituzten hartzaileak
-Network.alert.acceptfail=Huts egite zenbait izan da %1, %2 atakatan - aurrerabidea utzita dago. Mesedez egiaztatu ataka honentzat suhesi ezarpenak zihurtatzeko gaituta dagoela elkarketak jasotzeko.
-MyShares.column.category=Kategoria
-UpdateWindow.restartLater=Berrabiarazi Vuze Geroago
-MainWindow.menu.file.restart=Berrabiarazi &Vuze
-MainWindow.dialog.restartconfirmation.title=Berrabiarazi Vuze
-MainWindow.dialog.restartconfirmation.text=Egitan nahi duzu Vuze berrabiaraztea
-ConfigView.label.prioritizemostcompletedfiles=Gainontzeko agiriei lehentasun Handia eman osatutako % -aren eta agiri neurriaren arabera
-splash.plugin.init=Plugina Abiarazten:
-splash.plugin.UIinit=EIG Plugina Abiarazten: %1  
-ConfigView.section.style.osx_small_fonts=Erabili iturri txikiak [berrabiaraztea beharrezkoa]
-ConfigView.section.tracker.tcpnonblocking=Erabili S/I ez-itxipena TCP aztarnari jardunerako. Aukera hau hautatzeak web aztarnaia ataka altenatibo batean lanean izatea eskatzen du. Esperimentala!
-ConfigView.section.tracker.nonblocking=Ez-blokeatze aukerak
-ConfigView.section.tracker.nonblockingconcmax=Geh. aldibereko elkarketa [0: mugagabea]
-MyTorrentsView.menu.exportmenu=Esportatu
-MyTorrentsView.menu.exporttorrent=Torrenta...
-ConfigView.group.scrape=Zuritzea
-ConfigView.section.tracker.client.scrapeinfo=Zuritzea ezgaituz torrent askoren lerrokatzea saihestu daiteke, lanerako erletaldeko argibideak berreskuratzean aztarnariak zurituz ohinarritzen baitira.
-ConfigView.section.tracker.client.scrapeenable=Gaitu zuriketa
-ConfigView.section.tracker.client.scrapestoppedenable=Zuritu torrentak lanean ez daudenean
-Scrape.status.disabled=Zuritzea Ezgaituta
-MyTorrentsView.menu.explore=Erakutsi Agiria
-MyTorrentsView.menu.explore._mac=Erakutsi Finderren
-MyTorrentsView.menu.explore._windows=Erakutsi Ex&plorerrean
-wizard.maketorrents.autohost=Hostatu torrenta aztarnariaren barne
-ConfigView.label.overrideip=Ezeztatu aztarnari iragarpen IP-a(k) - punttu eta kakotxaz banaduta sare ezberdinetarako bada
-ConfigView.label.overrideip.tooltip=Jakinarazi aztarnariari irteera paketeetatik datozen IP helbide ezberdinak. Utzi hutsik aukera hau ez erabiltzeko.
-ConfigView.section.connection.group.networks=Sareak
-ConfigView.section.connection.group.networks.info=Hautatu berez baimendutako sareak hartzaile-hartzaile datu igorpenerako
-ConfigView.section.connection.networks.prompt=Galdetu hautatzeko jeisterakoan izengabeko aztarnari bat gehitzen denean
-ConfigView.section.connection.networks.Public=IP sare publikoa (ez izengabea)
-ConfigView.section.connection.networks.I2P=I&2P sarea
-ConfigView.section.connection.networks.Tor=The Onion Router (Tor) sarea
-TableColumn.header.networks=Sareak
-TableColumn.header.networks.info=Hartzaile-hartzaile harremanerako baimenduriko sareak
-Scrape.status.networkdisabled=Gaitu gabeko sarea
-ConfigView.section.tracker.server.group.networks=Sareak
-ConfigView.section.tracker.server.group.networks.info=Hautatu aztarnariak hartzaileak onartuko dituen sarebidea
-window.networkselection.title=Sare Hautapena
-window.networkselection.info=Behean zerrendaturiko torrentak ondorengo sareak sostengatzen dituzten aztarnariak dituzte.\nHautatu itzazu gaitzeko aztarnari eta hartzaile harremanerako.\nBezero publikoak sostengatzen dituen aztarnari izengabe bat bada gaitu biak izengabea eta sare publikoak.\nSare publikoa gaitzeak jakina izengabetasuna kentzea du ondorio!
-window.networkselection.description=Torrenta :
-plugins.basicview.clear=Garbitu
-ConfigView.section.connection.group.peersources=Hartzaile Iturriak
-ConfigView.section.connection.group.peersources.info=Hautatu berez baimedutako iturburuak hartzaileen elkarketetatik
-ConfigView.section.connection.peersource.Tracker=Aztarnaritik
-ConfigView.section.connection.peersource.DHT=Zentralizatu gabeko aztarnaritza
-ConfigView.section.connection.peersource.PeerExchange=Beste hartzaile batez lortua
-ConfigView.section.connection.peersource.Plugin=Pluginari gehitua
-ConfigView.section.connection.peersource.Incoming=Sarrera elkarketak
-PeersView.source=Iturburua
-PeersView.source.info=Hartzaile honen iturburua
-TableColumn.header.peersources=Hartzaile Iturburuak
-TableColumn.header.peersources.info=Hartzaile iturburu baimenduak hartzaileekiko elkarketak ezartzeko
-wizard.tracker.dht=Zentralizatu gabea (Vuzeko bezeroak bakarrik)
-MyTorrentsView.menu.advancedmenu=Aurreratua
-MyTorrentsView.menu.networks=Sareak
-MyTorrentsView.menu.peersource=Hartzaile Iturburuak
-ConfigView.section.sharing.permitdht=Baimendu zentralizatu gabeko jarraipena aztarnaria eskuraezina denean
-ConfigView.section.sharing.protocol=Elkarbanaturiko iturburuentzako hartuemana
-PeersView.Messaging=Mezularitza
-PeersView.Messaging.info=Adierazten du zein mezularitza erabide erabiltzen ari zaren
-ConfigView.label.queue.newseedsmovetop=Mugitu osatutako torrent berrienak emaritzen zerrendaren aurrealdera
-ConfigView.label.seeding.firstPriority.ignore.info=Kontuan izan arau hauek erabiliz torrenta gelditzea gertatu daitekela\njeisketa amaitu bezain laister.
-ConfigView.label.seeding.firstPriority.ignore=Baztertu Lehentasun Nagusia arauen gainekoa hauentzat:
-ConfigView.label.seeding.firstPriority.ignoreSPRatio=Emaritza-Hartzaile maila gehiago duten torrentak
-ConfigView.label.seeding.firstPriority.ignore0Peer=0 Hartzaileko Torrentak
-ConfigView.section.tracker.sendjavaversionandos=Bidali Java bertsioa eta Sistema Eragile izena
-MagnetPlugin.contextmenu.exporturi=Kopiatu Magnet &URI-a Gakora
-ConfigView.section.plugins.dht=Banaturiko DB
-dht.info=Plugin honek zentralizatu gabeko aztarnapena sostengatzen du, beste gauza batzuen artean, - ezgaituz gero zure jeisteko gaitasuna murriztuko da
-dht.enabled=Gaitu banaturiko datubasea
-dht.portdefault=Erabili berezko ataka
-dht.port=Datubasearen UDP ataka
-dht.execute.command=Igarpen komandoa
-dht.execute.info=Sakatu komandoa exekutatzeko
-dht.execute=Ekin
-dht.logging=Gaitu jarduera gardentasuna
-ConfigView.section.plugins.dhttracker=Banaturiko Aztarnaria
-dhttracker.tracknormalwhenoffline=Torrent arruntak beren aztarnaria eskuragarria ez dagoenean bakarrik bideratu
-ConfigView.section.file.nativedelete._mac=Erabili Zakarrontzia agirak ezabatzerakoan
-ConfigView.section.file.nativedelete._windows=Mugitu ezabatutako agiriak Birziklapen Gunera
-ConfigView.section.logging.generatediagnostics=Sortu
-ConfigView.section.logging.netinfo=Sortu sare argibideak
-ConfigView.section.logging.statsinfo=Sortu egoera argibideak
-ConfigView.section.logging.generatediagnostics.info=Sortu igarpen argibideak eta kopiatu gakora eta ohar agira, ezarrita badago
-ConfigView.section.sharing.privatetorrent=Torrent pribatua - aztarnariaren hartzaileak besterik ez ditu onartzen
-MainWindow.menu.tools.nattest=NAT/Suhesi Azterketa...
-Button.apply=Ezarri
-Button.close=Itxi
-window.welcome.title=Ongi etorri Vuzera %1
-#file can be a URL or a path in the jar
-MainWindow.menu.help.releasenotes=Argitalpen Oharrak
-dht.reseed.label=Arrunt birremaritzen Banaturiko Datubasea ez da beharrezkoa. Horrela ere, elkarketen zenbatekoa apala bada izan daiteke erabilia bir-baterapenerako.\nOrri zuria bereznahiko elkartutako hartzaileentzako edo sartu IP-a eta ataka hartzaile ezagun batetik bereznahikotzeko.
-dht.reseed.group=Birremaritu
-dht.reseed.ip=IP helbidea
-dht.reseed.port=Ataka
-dht.reseed=Birremaritu
-dht.reseed.info=Birremaritu datubasea
-dht.diagnostics.group=Igarpenak
-DHTView.title.full=Banaturiko Datubasea
-DHTView.title.fullcvs=Banaturiko Datubasea CVS
-DHTView.general.title=Orokorra
-DHTView.general.uptime=Jardun denb.:
-DHTView.general.users=Erabiltz.:
-DHTView.general.nodes=Elkarguneak:
-DHTView.general.leaves=Orriak:
-DHTView.general.contacts=Harremanak:
-DHTView.general.replacements=Ordezkap.:
-DHTView.general.live=Bizirik:
-DHTView.general.unknown=Ezezaguna
-DHTView.general.dying=Azkenetan:
-DHTView.transport.title=Garraio Xehetasunak
-DHTView.transport.packets=Paketeak
-DHTView.transport.bytes=Byte
-DHTView.transport.received=Jasota
-DHTView.transport.sent=Bidalita
-DHTView.transport.in=Sarrera:
-DHTView.transport.out=Irteera:
-DHTView.operations.title=Eragiketa Xehetasunak
-DHTView.operations.sent=Bidalia
-DHTView.operations.ok=Ongi
-DHTView.operations.failed=Huts egin du
-DHTView.operations.received=Jasoa
-DHTView.operations.ping=Ping (Int. Pak. Eskuzt.)
-DHTView.operations.findNode=Elkargune Bilaketa
-DHTView.operations.findValue=Bilaketa Balioa
-DHTView.operations.store=Biltegia
-DHTView.activity.title=Jarduera
-DHTView.activity.status=Egoera
-DHTView.activity.status.true=Lerrokatuta
-DHTView.activity.status.false=Lanean
-DHTView.activity.type=Mota
-DHTView.activity.type.1=Barne Lorpena
-DHTView.activity.type.2=Kanpo Lorpena
-DHTView.activity.type.3=Barne Ezarpena
-DHTView.activity.type.4=Kanpo Ezarpena
-DHTView.activity.target=Xedea
-DHTView.activity.details=Xehetasunak
-DHTView.db.title=Datubasea
-DHTView.db.keys=Giltzak
-DHTView.db.values=Balioak
-DHTView.db.local=Tokikoa
-DHTView.db.direct=Zuzen
-DHTView.db.indirect=Zeharka
-DHTView.db.divfreq=Maiztasun Dib.
-DHTView.db.divsize=Neurri Dib.
-MainWindow.dht.status.tooltip=Banaturiko Datubasea lanean dagoenean honek uneko online erabiltzaile zenbatekoa erakusten du
-MainWindow.dht.status.disabled=DHT-a Ezgaiturik
-MainWindow.dht.status.failed=DHT-ak Huts egin du
-MainWindow.dht.status.initializing=DHT-a Abiarazten
-MainWindow.dht.status.users=%1 erabiltzaile
-MainWindow.dht.status.unreachable=DHT-a Suhesiturik
-MainWindow.dht.status.unreachabletooltip=Badirudi arazo bat dagoela Banaturiko Datubasearen UDP ataka mapaketarekin (NAT/suhesia)
-MyTorrentsView.menu.setUpSpeed=E&zarri Igoera Abiadura
-MyTorrentsView.menu.setDownSpeed=Ezarri &Jeisketa Abiadura
-ConfigView.section.tracker.client.showwarnings=Erakutsi aztarnariek bidalitako kontuz! mezuak
-dht.advanced=Gaitu ezarpen aurreratuak
-dht.advanced.group=Ezarpen aurreratuak
-dht.advanced.label=Aldatu bakarrik balio hauek egitan zer egiten ari zaren badakizu
-dht.override.ip=Ezabatu kanpoko IP helbideak
-ConfigView.section.logging.loggerenable=Gaitu oharketa
-ConfigView.section.ipfilter.blockbanning=256 helbideko bloke baten eragozpena gutxienez zenbateko hau blokean eragotzia izan denean 
-MyTrackerView.passive=Pasiboa
-TableColumn.header.swarm_average_speed=Erletaldearen Bataz-besteko Abiadura
-TableColumn.header.swarm_average_speed.info=Erletaldeko hartzaileen bataz-besteko abiadura
-TableColumn.header.comment=Aipamena
-TableColumn.header.comment.info=Jeisketarako erabiltzaile-zehaztuaren aipamena
-TableColumn.header.commenticon=Aipamen Ikurra
-TableColumn.header.commenticon.info=Erakutsi ikurra jeisketak erabiltzaile-zehaztu baten aipamena badu
-MyTrackerView.category=Kategoria
-MainWindow.menu.file.open.torrentfortracking=T&orrent Agiria... (Aztanaritza Bakarrik)
-VivaldiView.title.full=Vivaldia
-VivaldiView.title.fullcvs=Vivaldi CVS-a
-VivaldiView.title.full_v6=Vivaldi IPv6-a
-MyTrackerView.date_added=Gehituta
-ConfigView.section.tracker.portbackup=Babeskopia atakak (';' bananduta)
-ConfigView.label.playfilespeech=Hitzegin agiri batek amaitu duenean
-ConfigView.label.playfilefinished=Jo soinu bat agiri batek amaitu duenean
-ConfigView.label.backupconfigfiles=Babeskopia itxurapen agiriak berreskurapen asmoekin
-ConfigView.section.tracker.client.scrapesingleonly=Ezgaitu aztarnari-bakoitzeko zuritze gehiketa (lagundu dezake 'URL oso luzea' duten aztarnariekin' (414) akatsak) 
-dht.ipfilter.log=Ohartu  IP Iragazki bortxaketez
-ConfigView.label.seeding.addForSeedingDLCopyCount=Hartu 'emaritzarako gehitutako' jeisketatzat kopia zenbateko hau duten jeitsierak
-ActivityView.legend.limit=Neurri muga
-ActivityView.legend.achieved=Erdietsitako neurria
-ActivityView.legend.overhead=Burugain neurria
-ActivityView.legend.peeraverage=Bataz-bestekoa
-ActivityView.legend.swarmaverage=Erletalde bataz-bestekoa
-ActivityView.legend.trimmed=Murrizpena (izpilduta)
-MyTorrentsView.menu.movemenu=Mugitu Agiriak
-MyTorrentsView.menu.movedata=Mugitu Datu Agiriak...
-MyTorrentsView.menu.movetorrent=Mugitu &Torrent Agiria...
-MyTorrentsView.menu.movedata.dialog=Hautatu helbide berria
-DHTView.operations.data=Datua
-DHTView.general.reachable=Eskurag.:
-DHTView.general.rendezvous=Hitzordua:
-ConfigView.label.queue.maxactivetorrentswhenseeding=Geh. emaritzen bakarrik [0:mugagabea]
-Views.plugins.IRC.title=IRC - Onlineko Laguntza Teknikoa
-Formats.units.alot=Pilo bat!!!
-ConfigView.section.ipfilter.persistblocking=Gorde itxitako IP xehetasunak berrabiarazpenetan
-FilesView.menu.rename=Berrizendatu edo Birxedetu
-FilesView.menu.rename_only=Berrizendapen Azkarra
-FilesView.menu.retarget=Mugitu Agiriak
-FilesView.rename.choose.path=Hautatu dagoen agiria edo berri bat
-FilesView.rename.choose.path.dir=Hautatu zuzenbide berri bat edo lehendik dagoen bat
-FilesView.rename.confirm.delete.title=Baieztatu Ezabaketa
-FilesView.rename.confirm.delete.text=Baieztatu jatorrizko agiriaren ezabapena '%1'
-FilesView.rename.filename.title=Berrizendatu agiria
-FilesView.rename.filename.text=Hautatu izen berri bat agiriarentzat
-ConfigView.higher.mode.available=Aukera asko erabiltzaile modu askotan dira eskuragarriak
-ConfigView.section.mode=Modua
-ConfigView.section.mode.title=Erabiltzaile Gaitasuna
-ConfigView.section.mode.beginner=Hasiberria
-ConfigView.section.mode.beginner.wiki.definitions=BitTorrent hiztegia
-ConfigView.section.mode.intermediate=Tartekoa
-ConfigView.section.mode.intermediate.wiki.host=Agiriak Hostatzen
-ConfigView.section.mode.intermediate.wiki.publish=Agiriak Argitaratzen
-ConfigView.section.mode.advanced=Aurreratua
-ConfigView.section.mode.advanced.wiki.main=Wiki Orrialde Nagusia
-ConfigView.section.mode.beginner.text=Torrentak jeisteko behar duzun guztia.\nErabili modu hau nahi duzun guztia zure torrentak kudeatzea bada.
-ConfigView.section.mode.intermediate.text=Sartu aztarnari eginkizunetan.\nErabili modu hau zeure aztarnaria sortzea eta zure agiriak hostatzea/argitaratzea nahi baduzu.
-ConfigView.section.mode.advanced.text=Sartu sare ezarpenetara.\nErabili modu hau jakitea nahi baduzu zein GIB (Gehienezko Igorpen Batasuna) edo S/I ez itxiak dauden
-Files.column.storagetype=Biltegiratze Mota
-Files.column.fileext=Mota
-FileItem.storage.linear=Lerrotua
-FileItem.storage.compact=Trinkotua
-MessageBoxWindow.rememberdecision=Gogoratu nire erabakia
-ConfigView.section.interface.cleardecisions=Garbitu gogoraturiko elkarrizketa erabakiak
-ConfigView.section.interface.cleardecisionsbutton=Garbitu
-ConfigView.section.interface.cleartrackers=Garbitu gogoraturiko aztarnariak
-ConfigView.section.interface.cleartrackersbutton=Garbitu
-ConfigView.section.interface.clearsavepaths=Garbitu gogoraturiko helburu gordeak
-ConfigView.section.interface.clearsavepathsbutton=Garbitu
-configureWizard.welcome.usermodes=Erabiltzaile Eskumen ezarpen honek zehaztuko du ondoren agertzen diren aukeren maila Tresnak > Aukerak. Zure interes hoberenean da zuzen ezartzea.
-FilesView.skip.confirm.delete.text=Moztu '%1' agiria tokia gordetzeko?
-FilesView.rename.failed.title=Berrizendatze/Birxedetzeak huts egin du
-FilesView.rename.failed.text=Eragiketak huts egin du, zihurrenik xede hautaketa okerragaitik
-diagnostics.log_found=Vuze ez da zuzen itzali. Egiaztau <A HREF="%1">igarpen ohar agiriak</A>. Irakurri ere wikiko idazlana <A HREF="http://wiki.vuze.com/w/Vuze_disappears">Vuze Ezagertzea</A> argibide gehiagorako.
-ManagerItem.paused=Pausaturik
-Utils.link.visit=Mesedez ikusi
-ConfigView.section.connection.serverport.wiki=Hautatutako ataka onak
-ConfigView.section.transfer.speeds.wiki=Abiadura oneko ezarpenak
-installPluginsWizard.installMode.info.title=Argibideak
-installPluginsWizard.installMode.info.text=Ez duzu pluginik behar Vuzerekin egoki lan egiteko, astialdi, berezgaitasuntze edo hurruneko aginte ezaugarri osagarriak eskaintzen dutenak.\nMesedez irakurri plugin bakoitzaren azalpenak ezartzea erabaki aurretik.\nPlugin gehienak zihurrak dira probatzeko, baina ez gainzamatu zure itxurapena erabiliko ez duzun pluginekin.
-Views.plugins.Distributed.DB.title=Banaturiko DB
-Views.plugins.Distributed.Tracker.title=Banaturiko Aztarnaria
-Views.plugins.Plugin.Update.title=Plugin Eguneratzea
-Views.plugins.UPnP.title=UPnP-a
-Views.plugins.UPnP.title.tooltip=Plug and Play Unibertsala
-openUrl.url.info=Sostengaturik http, https, magnet eta raw hex infohash kateak
-TableColumn.header.swarm_average_completion=Hartzaileen Bataz-besteko Osatua
-TableColumn.header.swarm_average_completion.info=Erletaldeko hartzaileen osaketa ehunekoaren bataz-bestekoa
-GeneralView.label.swarm_average_completion=Bataz-besteko Osaketa:
-GeneralView.label.swarm_average_completion.tooltip=Erletaldeko hartzaileen osaketa bataz-besteko ehunekoa
-MainWindow.nat.status.tooltip.unknown=Suhesi/NAT eskuragarritasun egoera ezezaguna (TCP)
-MainWindow.nat.status.ok=NAT Ongi
-MainWindow.nat.status.tooltip.ok=Eskuragarritasuna Ongi (TCP)
-MainWindow.nat.status.probok=NAT Ongi?
-MainWindow.nat.status.tooltip.probok=Eskuragarritasuna Ona zen, horrela ere ez dago TCP elkarketa sarrera berririk
-MainWindow.nat.status.bad=Suhesiturik
-MainWindow.nat.status.tooltip.bad=Suhesi/NAT (TCP) eskuragarritasun arazoa. Joan Wikira laguntza lortzeko
-plugin.installer.recommended.plugin=Plugina gomendatuta - mesedez berrikusi eta ezarri beharrezkoa bada
-LoggerView.pause=Pausatu Saio hastea
-LoggerView.clear=&Garbitu
-LoggerView.filter=Iragazkia
-LoggerView.filter.uncheckAll=Ez Hautatu Kategoria Guztiak
-LoggerView.filter.checkAll=Hautatu Kategoria Guztiak
-LoggerView.loggingDisabled=Saio hastea ez dago gaituta.
-LoggerView.includeOnly=Erakutsi bakarrik adierazpide honekin bat datozen lerroak:
-LoggerView.excludeAll=Ez erakutsi adierazpide honekin bat datozen lerroak:
-ConfigView.section.logging.log0type=Argibide
-ConfigView.section.logging.log1type=Kontuz
-ConfigView.section.logging.log2type=Akats
-ConfigView.section.logging.filter=Iragazi agirira ohartzerakoan
-ConfigView.section.logging.level=Ohar Maila
-ConfigView.section.logging.showLogsFor=Erakutsi  %1 oharrak hurrengo kategorientzat:
-ConfigView.pluginlist.column.loadAtStartup=Gertatu Abiatzerakoan
-ConfigView.pluginlist.column.type=Mota
-ConfigView.pluginlist.column.type.perUser=Erabiltzaileko
-ConfigView.pluginlist.column.type.shared=Elkarbanatuta
-ConfigView.pluginlist.column.type.builtIn=Barne Eraikita
-ConfigView.pluginlist.column.name=Izena
-ConfigView.pluginlist.column.version=Bertsioa
-ConfigView.pluginlist.column.directory=Zuzenbidea
-ConfigView.pluginlist.column.isOperational=Eragiketakor?
-PeersView.BlockView.Avail.Have=Biok duzue
-PeersView.BlockView.Avail.NoHave=Hartzaileak du; Zuk ez
-PeersView.BlockView.NoAvail.Have=Zuk duzu; Hartzaileak ez
-PeersView.BlockView.NoAvail.NoHave=Inork ez du
-PeersView.BlockView.Transfer=Eskualdatzen
-PeersView.BlockView.NextRequest=Hurrrengo Eskabidea
-PeersView.BlockView.title=Atal Mapa
-PeersView.BlockView.AvailCount=Eskuragarritasun Zenbatekoa
-MyTorrentsView.dialog.NumberError.title=Zenbaki Baliogabea edo Ezezaguna
-MyTorrentsView.dialog.NumberError.text=Sartu duzun zenbakia baliogabea edo ezezaguna da.
-MyTorrentsView.menu.manual=&Eskuz...
-MyTorrentsView.menu.manual.per_torrent=Eskuz (torrenteko)
-MyTorrentsView.menu.manual.shared_torrents=Eskuz (torrent artean)
-MyTorrentsView.dialog.setSpeed.title=Ezarri %1 abiadura
-# %1 = "in kbps" or ""; %2 = "upload" or "download"
-MyTorrentsView.dialog.setNumber.text=Sartu %1 zenbaki bat aldatzeko %2era:
-MyTorrentsView.dialog.setNumber.upload=igo
-MyTorrentsView.dialog.setNumber.download=jeitsi
-MyTorrentsView.dialog.setNumber.inKbps=%1
-OpenTorrentWindow.torrentLocation=Jeitsitako torrenta(k):
-OpenTorrentWindow.addFiles.URL=Gehitu &URL-a
-OpenTorrentWindow.addFiles.Folder=Gehitu &Agiritegia
-OpenTorrentWindow.addFiles.Clipboard=Gehitu Ga&kotik
-OpenTorrentWindow.changeDestination=Aldatu Helmuga
-OpenTorrentWindow.fileList=Agiri torrentetan:
-OpenTorrentWindow.torrentTable.name=Izena
-OpenTorrentWindow.torrentTable.saveLocation=Gordetze Kokalekua
-OpenTorrentWindow.fileTable.fileName=Agiri Izena
-OpenTorrentWindow.fileTable.size=Neurria
-OpenTorrentWindow.fileTable.destinationName=Helmuga Izena
-OpenTorrentWindow.startMode.seeding=Emaritzen
-OpenTorrentWindow.fileList.changeDestination=Aldatu Helmuga
-OpenTorrentWindow.mb.badSize.title=Agiri Bateraezina
-OpenTorrentWindow.mb.badSize.text='%1' ez da '%2' eta ezin da emaritzarako erabili
-OpenTorrentWindow.mb.alreadyExists.text=<A HREF="%1">%3</A> jadanik gehituta dago '%2' bezala
-OpenTorrentWindow.mb.alreadyExists.default.name=Hedabidea
-OpenTorrentWindow.mb.alreadyExists.title=Jadanik badago
-OpenTorrentWindow.mb.openError.title=Irekitze Akatsa
-OpenTorrentWindow.mb.openError.text='%1' ezin izan du ireki:
-OpenTorrentWindow.torrent.remove=Kendu torrenta zerrendatik
-OpenTorrentWindow.torrent.options=Hurrengo ezarpenak gainean hautaturiko torrentei ezarriko zaie:
-OpenTorrentWindow.xOfTotal=(%1 %2-tik)
-iconBar.open.tooltip=Ireki Torrenta(k)
-LocaleUtil.column.text=Idatzi Ezezaguna
-Tracker.tooltip.MultiSupport=Aztarnari honek hash zuriketa anitz sostengatzen ditu eskabide bakoitzeko
-Tracker.tooltip.NoMultiSupport=Aztarnari honek ez ditu hash zuriketa anitz sostengatzen eskabide bakoitzeko./nHonek ez du eragiten zure egintzan baina gainzama bat ezartzen du aztarnarian.
-ConfigView.label.lazybitfield=Erabili biteremu alperra (laguntzen du emaritzan biteremu-itxipenean ohinarritzen diren sareetan)
-LoggerView.realtime=Eguneratu egizko denboran
-ConfigView.section.file.perf.cache.flushpieces=Idatzi atal osatuak berehala diskan. Honek diska sarbidea lehuntzen du baina idaz eragiketa gehiago egin daitezke 
-ConfigView.section.file.writemblimit=Gehienezko idaz eskabide lerrokatuta (%1)
-ConfigView.section.file.writemblimit.explain=Diskaren idazketa abiadura jeisketa abiadura bezain motela denean neurri honek mugatzen du zenbat datu lerrokatu daitekeen jeisketa abiadura murriztua izan aurretik.
-ConfigView.section.file.readmblimit=Gehienezko irakurketa eskabide lerrokatuta (%1)
-ConfigView.section.file.readmblimit.explain=Neurri honek prozesatzeke dauden irakurketak biltegiratzeko zenbat oroimen erabiliko den mugatzen du 
-Button.moveUp=Mugitu &Gora
-Button.moveDown=Mugitu &Behera
-ConfigView.notAvailableForMode=Atal hau %1 moduarentzat edo handiagoarentzat da. Ez da eskuragarria %2 moduan.
-health.explain.error=Arazo bat dago torrent honekin. Ikusi Egoera zutabea, edo ikurreko akats argibidea.
-GeneralView.label.trackerscrapeupdate=Zuritu Aztarnaria
-PeersView.piece=Atal
-PeersView.piece.info=Hartzaile honetatik eskabideturiko # azken atala
-PiecesView.priority=Lehentasuna
-PiecesView.priority.info=Atal honen osaketa lehentasuna, baina ez jarri harreta askorik horretan
-PiecesView.speed=Abiadura
-PiecesView.speed.info=Hartzaile geldoenek eragotzita dute atal askoz azkarragoekin nahastea
-TableColumn.header.AvgAvail.info=Atal eskuragarritasuna bananduta Z ataletan, bananduta Z elkarketatan
-TableColumn.header.AvgAvail=Batez-besteko Eskurg/atal
-ConfigView.label.strictfilelocking=Betearazi bazterketa agiri idazketa sarbide itxipena torrenteetan
-MyTorrentsView.menu.checkfilesexist=Egiaztatu Dauden Agiriak
-MyTorrentsView.menu.rescanfile=Aldizka Berregiaztatu Osatugabeko Atalak
-MyTorrentsView.menu.clear_resume_data=Garbitu &Datuak Jarraitzeko
-Plugin.extseed.name=Kanpoko Emaritzak
-Plugin.localtracker.name=LAN Hartzaile Bilatzailea
-Plugin.localtracker.info=LAN hartzaile bilatzaileak Vuzeren kopia anitz ahalbidetzen ditu suhesi baten atzean eta sare arrunt batean\ntorrentak modu eraginkorrean jeisteko beraien arteko elkarketa zuzenak gaituz.
-Plugin.localtracker.enable=Gaitu LAN hartzaile bilatzailea
-azinstancehandler.alert.portclash=Ataka gatazka atzeman da LAN-ean: %1 jadanik erabilpenean du beste Vuze erabiltzaile batek, hautatu zorizko beste ataka eragozteko TCP / UDP aditzea [%2 eta %3 artean]. 
-ConfigView.section.transfer.lan=LAN (Tokiko Sarbide Sarea)
-ConfigView.section.transfer.lan.tooltip=LAN-bereiziko Ezarpenak
-ConfigView.section.transfer.lan.uploadrate=KB/s LAN geh. igoera abiadura [0: mugagabea]
-ConfigView.section.transfer.lan.uploadrate.tooltip=Barneko LAN bera ez duten hartzaile elkarketek igoera muga neurria banandua dute
-ConfigView.section.transfer.lan.downloadrate=KB/s LAN geh. jeisketa abiadura [0: mugagabea]
-ConfigView.section.transfer.lan.downloadrate.tooltip=Barneko LAN bera ez duten hartzaile elkarketek jeisketa muga neurria banandua dute
-TorrentOptionsView.title.short=Aukerak
-TorrentOptionsView.title.full=Aukerak
-TorrentOptionsView.param.max.peers=Geh. elkarketa zenbatekoa [0: mugagabea]
-ConfigView.section.connection.encryption.require_encrypted_transport=Garraio enkriptatua beharrezkoa
-ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Behartu enkriptatutako elkarketak erabiltzera beste hartzaile batzuekin
-ConfigView.section.connection.encryption.min_encryption_level=Gutxienezko enkriptaketa maila
-ConfigView.section.connection.encryption.min_encryption_level.tooltip=Laua- eskuematea bakarrik\nRC4 - jario osoa\nEnkriptaketa handiagoak CPU gehiago behar du .
-Peers.column.Encryption=Enkriptaketa
-Peers.column.Encryption.info=Erabilitako enkriptaketa maila
-ConfigView.section.connection.encryption.encrypt.info=Enkriptaketa gaituta badago ezingo duzu bezero bateraezinekin elkarketarik egin ordezko aukerak gaitu ezean
-ConfigView.section.connection.encryption.encrypt.info.link=Mesedez ikusi hemen xehetasunak
-MainWindow.sr.status.tooltip.ok=Elkarbanatze Maila %1 Ongi
-MainWindow.sr.status.tooltip.poor=Elkarbanatze Maila %1 gutxi: < 0.9
-MainWindow.sr.status.tooltip.bad=Elkarbanatze Maila %1 gaizki: < 0.5
-ConfigView.section.style.status=Egoera Eremua:
-ConfigView.section.style.status.show_sr=Elkarbanatze Maila
-ConfigView.section.style.status.show_nat=NAT Egoera
-ConfigView.section.style.status.show_ddb=DDB Egoera
-ConfigView.section.style.status.show_ipf=IP Iragazki Egoera
-ConfigView.section.connection.encryption.encrypt.group=Garraio Enkriptazioa/Itsutzea
-ConfigView.section.connection.encryption.encrypt.fallback_info=Ordezko aukera gaitzeak bezero bateraezinekin elkarketak ahalbidetuko ditu BAINA elkarketa enkriptatu-gabeak izango dira
-ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Ahalbidetu enkriptatu-gabeko irteera elkarketak enkripatutako elkarketa saiakerak huts egiten badu
-ConfigView.section.connection.encryption.encrypt.fallback_incoming=Ahalbidetu enkriptatu-gabeko sarrera elkarketak
-ConfigView.section.connection.encryption=Garraio Enkriptaketa
-upnp.selectedinterfaces=Hautaturiko interfazeak (';' banandurik, adib. eth0;eth1) [blank: all]
-ConfigView.section.style.defaultSortOrder=Berezko Antolakuntza
-ConfigView.section.style.defaultSortOrder.desc=Beherantz
-ConfigView.section.style.defaultSortOrder.asc=Gorantz
-ConfigView.section.style.defaultSortOrder.flip=Aurreko antolakuntzaren alderantziz
-LoggerView.autoscroll=Berez-irriskatu
-Button.selectAll=Hautatu Denak
-Button.markSelected=Markatu Hautatua
-Button.unmarkSelected=Desmarkatu Hautatua
-plugins.basicview.config=Itxuratu
-TorrentOptionsView.param.max.uploads=Geh. igoera aho zenbatekoa [gutxienez: 2]
-MyTorrentsView.dialog.setPosition.title=Ezarri Kokapena
-MyTorrentsView.dialog.setPosition.text=Sartu kokapena hautatutako torrentak ezartzeko:
-MyTorrentsView.menu.reposition.manual=Birjar&pena...
-ConfigView.section.connection.advanced.info.link=Mesedez ikusi hemen xehetasunak
-ConfigView.section.connection.advanced.socket.group=Hartune Aukerak
-ConfigView.section.connection.advanced.bind_port=Lotu tokiko atakara [0: ezgaituta]
-ConfigView.section.connection.advanced.bind_port.tooltip=Irteera hartune elkarketak tokiko mailan behartuta egongo dira emaniko atakan.\nHau gaitzeak NAT bideratzailearen ezarpenarekin lagundu dezake .
-ConfigView.section.proxy.group.tracker=Aztarnari Harremanak
-ConfigView.section.proxy.group.peer=Hartzaile Harremanak
-Pieces.column.Requested=Eskabidetuta
-Pieces.column.Requested.info=Erakusten du atalean eskabide gehiago egin daitezkeen edo ez (*)
-ConfigView.label.maxuploadsseeding=Ordezpen berezkoa emaritzan dagoenean
-MyTorrentsView.filter=Iragazkia
-popup.error.hideall=Ezkutatu Denak
-ConfigView.section.style.dataStatsOnly=Erakutsi datu estatistikak bakarrik (ezkutatu harreman estatistikak)
-ConfigView.section.style.separateProtDataStats=Erakutsi banandurik datu eta hartueman estatistikak 'datu (hartueman)' bezala
-MyTorrentsView.dialog.setFilter.title=Aldatu Iragazkia
-MyTorrentsView.dialog.setFilter.text=%1 atala iragazia izan daiteke adierazi duzun idatzirako. Erabili  | (barra-zutia) ikurra iragazteko esaldi askoren artean.
-MyTorrentsView.filter.tooltip=Ktrl+X aldatzeko RegEx eta bilaketa arrunt moduaren artean.\nErabili | (barra-zutia) ikurra iragazteko esaldi askotan.
-MyTorrentsView.clearFilter.tooltip=Garbitu Iragazkia
-MyTorrentsView.menu.filter=Iragazki Zerrenda...
-ConfigView.section.file.resume.recheck.all=Berrabiarazte-hutsegitean egiaztatu agiri guztia atal osatuak bilatzeko (Bestela azken gordeketan eraginda zeuden atalak bakarrik egiaztatuko dira)
-ConfigureWizard.language.choose=Hautatu hizkuntza beheko zerrendatik:
-popup.closing.in=Leihoaren berez-istea  %1 segundutan
-popup.more.waiting=%1 mezu gehiago...
-# > 2402
-popup.download.finished="%1" jeisketa amaituta.
-popup.file.finished="%1" jeisketa amaituta
-ConfigView.auto=Berez
-Plugin.localtracker.autoadd.info=Berezgaitasunez gehitu tokiko hartzaile hauek [helbideak ';' bananduta, adib. 1.2.3.4]
-Plugin.localtracker.autoadd=Ageriko hartzaileak
-Plugin.localtracker.networks.info=Hartu honako sare hauek tokikotzat [sareak ';' bananduta, adib. 145.227.*.*]
-Plugin.localtracker.networks=Tokiko sareak
-MainWindow.menu.view.plugins.logViews=Saio Ik&uspegiak
-SpeedView.stats.autospeed=Berezgaitasunezko Igoera Abiadura (Erakusten %1 sm)
-SpeedView.stats.autospeed.disabled=Aukera hau ez dago gaiturik (DHT-a behar duzu) edo ez zaude erabilitzen (eskuzko igoera abiadura hautatuta)
-SpeedView.stats.idlePing=Idle Ping-a:
-SpeedView.stats.maxPing=Geh. Ping-a:
-SpeedView.stats.currentPing=Oraingo Ping-a:
-SpeedView.stats.maxUp=Geh. Igoera Abiadura:
-ConfigView.pluginlist.unloadSelected=Ezgertatu Hautatua
-ConfigView.pluginlist.scan=Mihatu Plugin berrien bila
-ConfigView.section.transfer.autospeed=Berez-Abiadura (klasikoa)
-ConfigView.section.transfer.autospeed.tooltip=Berez-abiadura ezarpen bereziak
-ConfigView.section.transfer.autospeed.info=Berez-abiadurak berezgaitasunez zehazten du igoera muga sare elkarketaren gainzamatzea saihesteko\n\nMuga hauek berezgaitasunezko igoera abiadura gaituta dagoenean bakarrik ezarri daitezke eta behar du baita ere banaturiko datubasea gaituta egotea.\n
-ConfigView.section.transfer.autospeed.minupload=%1 gutxienezko igoera abidadura
-ConfigView.section.transfer.autospeed.minupload.tooltip=Igoera abiadura ez da arrunt berez beheratuko muga honen azpitik
-ConfigView.section.transfer.autospeed.maxupload=%1 gehienezko igoera abiadura [0: mugagabea]
-ConfigView.section.transfer.autospeed.maxupload.tooltip=Igoera abiadura ez da berez goratzen muga honen gainetik
-ConfigView.section.transfer.autospeed.chokeping=Itopen ping aldiak [segundu milaenetan] 
-ConfigView.section.transfer.autospeed.chokeping.tooltip=Ping aldiak balio honen gainetik sare betekada adierazletzat hartuko dira
-ConfigView.section.transfer.autospeed.enableauto=Gaitu jeisten eta emaritzen 
-ConfigView.section.transfer.autospeed.enableautoseeding=Gaitu emaritzan bakarrik dagoenean
-ConfigView.pluginlist.column.unloadable=Gertaezina
-ConfigView.section.transfer.lan.enable=Gaitu abiadura muga bananduak LAN elkarketentzat
-Plugin.localtracker.wellknownlocals=Berezgaitasunez barneratzen du bigiztapena/lotura/tokiko sareak gunea (192.168 e.a)
-TableColumn.header.filesdone=Agiri Eginda
-TableColumn.header.filesdone.info=Agiri eginda/Agiriak guztira *edo*  Jauzi-gabeko agiri eginda (Agiri eginda)/Jauzi-gabeko agiriak guztira (Agiriak guztira)
-MagnetPlugin.private_torrent=<torrent pribatua>
-MagnetPlugin.decentral_disabled=<zentralizatu gabeko aztarnaritza ezgaituta>
-MagnetPlugin.decentral_backup_disabled=<zentralizatu gabeko babeskopia ezgaituta>
-MagnetPlugin.report.waiting_ddb=DDB abiarazpena itxaroten...
-MagnetPlugin.report.searching=bilatzen...
-MagnetPlugin.report.found=aurkituta %1
-MagnetPlugin.report.alive=%1 bizirik
-MagnetPlugin.report.dead=%1 hilda
-MagnetPlugin.report.tunnel=azpibideratzen %1 
-MagnetPlugin.report.downloading=Hemendik jeisten %1
-MagnetPlugin.report.error=akatsa %1
-MagnetURLHandler.report.no_sources=ez da baliabiderik aurkitu torrentarentzat
-MagnetURLHandler.report.torrent_size=torrent neurria: %1
-MagnetURLHandler.report.percent=osaturik: %1%
-MagnetURLHandler.report.error=akatsa %1
-DHTTransport.report.request_all=eskabidetzen eskualdaketa osoa %1
-DHTTransport.report.received_bit=jasota %1  %2  %3
-DHTTransport.report.complete=osatuta
-DHTTransport.report.timeout=denborazkanpo, erantzunik ez %1
-DHTTransport.report.rerequest_all=bir-eskabidetzen eskualdaketa osoa  %1
-DHTTransport.report.rerequest_bit=bir-eskabidetzen %1  %2  %3 
-DHTTransport.report.timeout_some=denborazkanpo, %1 pakete jasota %2-tik baina osatugabe
-DHTTransport.report.sending=datuak bidaltzen
-DHTTransport.report.resending=datuak birbidaltzen
-DHTTransport.report.send_complete=bidali osorik
-DHTTransport.report.send_timeout=bidalketa itxaronaldia
-ConfigView.section.transfer.autospeed.enabledebug=Ohar garbiketa argibideak
-TableColumn.header.date_added=Gehitze Eguna
-TableColumn.header.date_added.info=Torrentaren gehitze eguna
-ConfigView.section.file.hashchecking.smallestfirst=Berregiaztatu jeisketa txikienak lehenik
-platform.win32.baddll.info=Vuzek '%1' egona atzeman du. Hau '%2'  zati da eta ezaguna da programaren blokeoa eta CPU erabilpen handia bezalako arazo larriak eragiteagaitik. Aurkitzen baduzu mesedez softwarea kendu edo ezarri Vuzeri eragiten ez dion moduan.
-platform.win32.baddll.niphk=Norman Birus-aurkakoa
-platform.win32.baddll.nvappfilter=NVidia Suhesia
-platform.win32.baddll.netdog=Armor2net Suhesi Pertsonala
-platform.win32.baddll.vlsp=Venturi Suhesia
-platform.win32.baddll.imon=NOD32 Birus-aurkakoa
-platform.win32.baddll.sarah=ONDATUTA! Aplikazio Geruza Suhesia
-platform.win32.baddll.MxAVLsp=VCom Fix-It Erabilgarriak
-platform.win32.baddll.mclsp=McAfee Pribatutasun Zerbitzua
-platform.win32.baddll.radhslib=Naomi Internet Iragazkia (Dizdiratsua)
-platform.win32.baddll.nl_lsp=NetMugatzailea
-platform.win32.baddll.winsflt=Interneteko Eduki Garbi Iragazkia
-platform.win32.baddll.AxShlex=Alkohola %120
-platform.win32.baddll.iFW_Xfilter=iolo Suhesi Pertsonala
-platform.win32.baddll.WSOCKHK=Sare Babeslea
-platform.win32.baddll.InjHook12=Torrent Maila Zaintzailea
-platform.win32.baddll.FPServiceProvider=FoxyProxy Bideo Erabilgarria
-platform.win32.baddll.SBLSP=SPEEDBit Bideo Bizkortzailea
-upnp.ignorebaddevices=Baztertu zuzen erantzuten ez duten gailuak
-upnp.ignorebaddevices.info=Orain baztertutako gailuak: %1
-upnp.ignorebaddevices.reset=Berrezarri bazterturiko gailu zerrenda
-upnp.ignorebaddevices.reset.action=Berrezarri
-upnp.ignorebaddevices.alert=UPnP gailu helbidea %1 bazterturik dago etengabeko akatsengaitik. Ikusi UPnP plugin ezarpenak eragiketa honi buruzko aukerentzako.
-TorrentOptionsView.param.max.uploads.when.busy=KB/s geh. igoera abiadura igoera muga orokorra lortu denean [0: ezgaituta]
-UpdateMonitor.messagebox.verification.failed.title=Ezarpen Egiaztapenak Huts egin du
-UpdateMonitor.messagebox.verification.failed.text=Egiaztapena '%1' hutseginda: %2
-UpdateMonitor.messagebox.accept.unverified.title=Onartu Egiaztatugabeko Ezarpena
-UpdateMonitor.messagebox.accept.unverified.text='%1' ez da Vuzeren plugin ofizial bezala egiaztu ahal izan.\nJarraitu behar EZ duen plugina bada.\nEzarpena egin?
-FileView.BlockView.title=Agiri Atalak
-FileView.BlockView.Done=Eginda
-FileView.BlockView.Skipped=Jauzita
-FileView.BlockView.Active=Jardunean
-FileView.BlockView.Outstanding=Egikete
-ConfigView.label.tcplistenport=Sarrera TCP aditze ataka
-ConfigView.label.udplistenport=UDP aditze ataka
-upnp.portchange.alert=Hurrengo atakek aldatu egin dira UPnP gailuetan arazoak saihesteko: %1 [ataka zaharra=%2] %3 [ataka zaharra=%4]
-ConfigView.section.proxy.username.info=Proxy zerbitzariak egiaztapena eskatzen badu baita zehaztua ez denean, erabili kate hau "<inor ez>" erabiltzaile izen(ak) bezala
-ConfigView.label.maxuploadswhenbusymin=Torrent bakoitzeko geh. igoera abiadura hartuta denboragailuan dagoenean [seg]
-MainWindow.menu.help.debug=Sortu Garbiketa Argibideak (Matxura oharra)
-DownloadManager.error.badsize=Neurri Okerra
-natpmp.info=NAT-PMP Apple-n UPnP aukera da eta berriki Hegazkaietan ere sostengatua da\n\nJakin ezazu orain duzun UPnP gaituta dagoela NAT-PMP gaitzeko NAT-PMP gailu bezala UPnP gailu mota berezitzat hartzen da 
-natpmp.enable=Gaitu (jakin ezazu  lan egiteko hegazkaiko itxurapenean ere gaituta egon behar dela )
-ConfigView.section.tracker.host.addurls=Zihurtatu aztarnari hauen URL-ak hostatutako torrenteetan daudela
-ConfigView.filter=idatzi iragazteko hitza(k)
-ConfigView.section.files.move=Osaketa Mugitzen
-ConfigView.section.file.defaultdir.section=Berezko Zuzenbide Aukerak
-ConfigView.section.file.defaultdir.auto=Berezgaitasunez jeitsi berezko zuzenbidera (Ez Garaionekoa)
-ConfigView.section.file.defaultdir.bestguess=Erabili ustezko hoberena gordetzeko zuzenbide berezkoa hautatzerakoan
-ConfigView.section.file.defaultdir.ask=Berezko zuzenbidea:
-ConfigView.section.file.defaultdir.lastused=Eguneratu berezko zuzenbidea gordetako azken helbidera
-ConfigView.section.file.config.section=Itxurapen Ezarpenak:
-ConfigView.section.file.config.currentdir=Oraingo itxurapen zuzenbidea:
-ConfigView.section.torrent.decoding=Dekodeaketa Ezaugarri Ezarpenak
-ConfigView.section.logging.udptransport=Gaitu UDP garraio aztarna aditzea 
-Tracker.announce.ignorePeerSeed=Baztertzen Hartzaile/Emaritza zenbaketa. %1
-ConfigView.section.connection.encryption.use_crypto_port=Erabili 'kriptoataka' aztarnari hedapena sarrera lauko elkarketa saiakerak saihesteko. Aztaranari batzuek ez dute onartzen hau eta  honelako akatsak dituzte "Atata Okerra' edo 'Legezkanpoko gatazka'
-TorrentOptionsView.param.reset.to.default=Ezarri aukerak berezko balioetan
-TorrentOptionsView.param.reset.button=Berrezarri
-natpmp.routeraddress=Geltoki helbidea [blank: auto]
-ConfigView.section.style.disableAlertSliding=Ezgaitu labantze biziduna/goren eran alerta mezuentzat
-ConfigView.section.transfer.autospeed.maxinc=%1 gehienezko gorapena aldi bakoitzeko
-ConfigView.section.transfer.autospeed.maxdec=%1 gehienezko beherapena aldi bakoitzeko
-ConfigView.section.transfer.autospeed.enabledownadj=Gaitu jeisketa abiadura neurriratzea
-ConfigView.section.transfer.autospeed.downadjratio=Jeisketa: Igoera abiadura maila (adib. 2.0 -> jeisketa abiadura muga igoera mugaren bikoitza da)
-ConfigView.section.transfer.autospeed.latencyfactor=Ezkutuko aldaketak abiadura aldaketekin lotzeko erabiltzen den ezaugarria (zenbaki luzeek sentikortasuna murrizten dute)
-ConfigView.section.transfer.autospeed.reset=Berrezarri balio aurreratuak
-ConfigView.section.transfer.autospeed.reset.button=Berrezarri
-PeerColumn.activationCount=Elkarketa egiten saiatzen diren hartzaileak: %1
-TableColumn.header.timesincedownload.info=Datua torrenterako jeitsi zenetik igarotako denbora
-TableColumn.header.timesincedownload=Jeisketa Idle-a
-TableColumn.header.timesinceupload.info=Datua torrenterako igo zenetik igarotako denbora
-TableColumn.header.timesinceupload=Igoera Idlea
-PeersView.incomingreqcount=Sarrera Eskabidea
-PeersView.incomingreqcount.info=Hartzaileek eginiko sarrera eskabide zenbatekoa
-PeersView.outgoingreqcount=Irteera Eskabidea
-PeersView.outgoingreqcount.info=Hartzaileari egindako irteera eskabideen zenbatekoa
-upnp.mapping.trackerclientudp=UDP Aztarnari Bezero Ataka
-upnp.mapping.dhtudp=Banaturiko Datubasea
-ConfigView.section.connection.nondata.udp.same=Erabili UDP ataka bera Banaturiko Datubaserako eta UDP Aztarnarirako
-ConfigView.section.connection.tcp.enable=Gaitu TCP-a
-ConfigView.section.connection.udp.enable=Gaitu UDP-a
-ConfigView.section.style.showiconbar=Erakutsi Tresnabarra
-MainWindow.menu.view.iconbar=Tresnabarra
-MyTorrentsView.menu.rename=Berrizendatu...
-MyTorrentsView.menu.rename.displayed=Berrizendatu Erakutsitako Izena
-MyTorrentsView.menu.rename.save_path=Berrizendatu Gordetzeko Helburua
-AdvRenameWindow.title=Berrizendatu Jeisketa
-AdvRenameWindow.message=Idatzi izen berri bat jeisketa honi.
-AdvRenameWindow.rename.torrent=Berrizendatu Torrenta
-MyTorrentsView.menu.rename.displayed.enter.title=Berrizendatu Erakutsitako Izena
-MyTorrentsView.menu.rename.displayed.enter.message=Sartu jeisketa honentzat erakusteko izen berri bat.
-MyTorrentsView.menu.edit_comment=Aipamena Editatu
-MyTorrentsView.menu.edit_comment.enter.title=Aipamena Argitaratu
-MyTorrentsView.menu.edit_comment.enter.message=Sartu aipamen bat jeisketa honentzat.
-UIDebugGenerator.messageask.title=Garbiketa Sorgailua
-UIDebugGenerator.messageask.text=Mesedez sartuzazu jakinarazten ari zaren akatsaren azalpen bat
-UIDebugGenerator.complete.title=Garbiketa Sortzea Ezeztaturik
-UIDebugGenerator.complete.text=Garbiketa agiria ezin da aurkitu '%1'.\n\nKlikatu Ongi agiri honentzat erabide-agiri leiho bat irekitzeko. 
-ConfigView.section.style.showProgramIcon=Erakutsi programaren ikurra izen zutabean
-ConfigView.section.style.showProgramIcon.tooltip=Ikusik bir-irekitzea behar izan dezake aldaketak eragina izan dezaten
-swt.alert.cant.update="%3" -tik hartutako SWT liburutegia ezin da berezgaitasunez eguneratua izan %1 -> %2 bertsiora  ("%4"-tik egon behar du gertaturik). Mesedez ikusi <A HREF="http://wiki.vuze.com/w/SWT_Cant_Auto_Update">the wiki</A> xehetasunetarako.
-authenticator.savepassword=Gogoratu nire sarhitza
-ConfigView.section.security.clearpasswords=Berrezarri gogoraturiko sarhitzak
-ConfigView.section.security.clearpasswords.button=Berrezarri
-TorrentInfoView.torrent.encoding=Torrent kodeaketa
-TorrentInfoView.columns='{library.name}' Zutabeak ikusi
-progress.window.title=Eragiketa Garatzen
-progress.window.msg.filemove=Mesedez itxaron agiri mugitze/berrizendatzea burutzen den bitartean
-ConfigView.label.popup.timestamp=Gehitu ordu-irarketa alerta oharrei
-ConfigView.label.popup.autohide=Berezgaitasunez ezkutatu akatsenak ez diren ohar alertak x segundu ondoren (ezarri 0 berez ezkutatzea ezgaitzeko)
-ConfigView.label.please.visit.here=Mesedez ikusi hemen xehetasunak
-ConfigView.section.ipfilter.enable.descriptionCache=Bildu IP azalpenak urratu agirian
-ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Ezgaituta dagoenean, azalpenak ez dira gogoratuko
-OpenTorrentWindow.filesInfo=%1 %2-tik izango dira jeitsiak.
-OpenTorrentWindow.diskUsage=%1 %2-tik
-ConfigView.label.openmytorrents=Ireki Liburutegia hasitakoan
-ConfigView.label.open_transfer_bar_on_start=Ireki Eskualdaketa Barra hasieran
-ConfigView.section.style.DNDalwaysInIncomplete=Erakutsi betik Liburutegiko Osatugabe sailean  'Ez Jeitsi' duten agiriak
-OpenTorrentWindow.mb.noGlobalDestDir.title=Helmuga Zuzenbidea ez da aurkitu
-OpenTorrentWindow.mb.noGlobalDestDir.text=%1' helmuga zuzenbidea baliogabea da.
-OpenTorrentWindow.mb.noDestDir.title=Helmuga Zuzenbidea ez da aurkitu
-OpenTorrentWindow.mb.noDestDir.text='%2' torrentarentzako '%1' helmuga zuzenbidea ez dago edo baliogabea da.
-OpenTorrentWindow.mb.notValid.title=Torrent Irekitze Hutsegitea
-OpenTorrentWindow.mb.notValid.text=Ezin da '%1' torrenta ireki. Emaritzan moduan irekitzen ari bazara, mesedez zihurtatu zaitez torrentaren datu agiria badagoela.
-OpenTorrentWindow.mb.notTorrent.title=Ireki Huts egin duen Torrenta 
-OpenTorrentWindow.mb.notTorrent.text=Ezin da '%1' ireki. Ez dirudi .torrent agiri bat denik.\n\nJasotako datu batzuk:\n%2
-ConfigView.label.pause.downloads.on.exit=Gelditu jeisketak irtetzerakoan
-ConfigView.label.resume.downloads.on.start=Berrekin pausaturiko jeisketak hasterakoan abiatzea osatuta dagoenean
-UIDebugGenerator.message.cancel.title=Garbiketa Argibidea Sortzea Ezeztatuta
-UIDebugGenerator.message.cancel.text=Ez duzu jakinarazten saiatzen ari zaren akatsaren azalpenik. Zure akatsa argia izan daiteke zuretzat, baina azalpen bat izan gabe, zure arazoaz guk egin dezakeguna asmatzea besterik ez litzake.\n\nGarbiketa Argibide Sortzea ezeztatua izan da.
-ConfigView.section.connection.group.http.info=Sostengua HTTP emaritzarako
-ConfigView.section.connection.http.enable=Gaitu
-ConfigView.section.connection.http.port=Sarrera ataka zenbakia
-ConfigView.section.connection.http.portoverride=Aztarnariaren HTTP ataka ezabatu [0: bat ere ez]
-window.update.noupdates.title=Egiaztatu Eguneraketa Emaitzak
-window.update.noupdates.text=Ez dago eguneraketa berririk eskuragarri.\n\nZorionak!
-ConfigView.label.bindip.details=Adibidea: 192.168.1.5;eth0;eth1[2]  behartu dezake IP bereizi bat, 1. interfazearen IP guztietara eta 2. interfazearen 3. IP-ra .\n1. IP-a zerbitzu guztietarako erabilitzen da, beste guztiak zama orekatzeko erabiltzen dira\nHurrengo interfazeak daude baliagarri:\n%1
-ConfigView.label.mindownloads=Gutx. aldibereko jeisketa
-UI.cannot_submit_blank_text=Balio bat sartu behar duzu.
-crypto.alert.as.warning='%1' sarea ezaguna da joan-etorri eraketak ezartzeagaitik jeisketa egitea murriztuz. Garraio enkriptaketa berezgaitasunez gaitzen da - Hau ezgaitu/aldatu daiteke itxurapenaren bidez.
-ConfigView.section.interface.alerts=Alertak
-ConfigView.label.popupdownloadadded=Ohar alerta jeisketa gehitzen denean
-popup.download.added="%1" zure jeisketa zerrendara gehitu da.
-MessageBoxWindow.nomoreprompting=Ez galdetu berriro
-TorrentOptionsView.param.max.seeds=Geh. emaritza elkarketak [0: elkarketa muga]
-TorrentOptionsView.param.alternative.value.enable=Txandakatu balioa emaritzan
-ConfigView.section.proxy.check.on.start=Egiaztatu proxyaren egoera hasterakoan
-TransferStatsView.legend.pingaverage=Bataz-bestekoa
-TransferStatsView.legend.ping1=1 Xedea
-TransferStatsView.legend.ping2=2 Xedea
-TransferStatsView.legend.ping3=3 Xedea
-ConfigView.section.interface.enabletray._mac=Gaitu Egoera Barra Ikurra [berrabiaraztea beharrezkoa]
-ConfigView.label.closetotray._mac=Itxi txikiagotuak Egoera Barra Ikurrera
-ConfigView.label.minimizetotray._mac=Egoera Barrako Ikurreratzen du
-OpenTorrentWindow.mb.existingFiles.title=Agiria jadanik badago!
-OpenTorrentWindow.mb.existingFiles.text=Agirietako batzuk jadanik badaude adierazitako agiritegian:\n\n%1\nJarraitzen baduzu, Vuzek datu zuzenak lortzeko agirien gaineko egiaztapena egin dezake eta gainidatzi beharrezkoa bada.
-splash.unloadingTorrents=Torrentak Ezgertatzen
-splash.unloadingTorrent=Torrenta Ezgertatzen
-ConfigView.section.file.defaultdir.autorename=Berez berrizendatu torrent datuak agiriak helburuan ezberdinak ikusten badira
-ConfigView.section.file.defaultdir.autorename.tooltip=Honek izenak berdinak direnean torrent batek beste torrent baten agiriak gainidaztea  saihesten du
-alert.raised.at.close=(Mezua aurretik itxitako Vuzetik)
-Plugin.trackerpeerauth.name=Aztarnari Hartzaile Baimena
-Plugin.trackerpeerauth.info=Plugin honek lan egiten du aztarnariekin hartzaileak erletaldeko kide baliagarriak direla egiaztatzeko 
-Peers.column.maxupspeed=Geh. Igoera Abiadura
-Peers.column.maxdownspeed=Geh. Jeisketa Abiadura
-MyTorrents.items.DownSpeedLimit.disabled=Ez jeitsi
-Peers.column.lan=LAN (Tokiko Sarbide Sarea)
-upnp.selectedaddresses=Helbideak (';' banandurik, '-' aurrizkia=ukatu, '+' =ahalbidetu) [hutsik: ezer ez]
-upnp.alert.multipledevice.warning=UPnP gailu anitz atzeman dira - egiaztatu denak behar duten ataka izendapena (ikusi UPnP sarrera eta itxurapena)
-UpdateMonitor.messagebox.restart.title=Software Eguneraketa
-UpdateMonitor.messagebox.restart.text=Vuzek eguneraketa garrantzitsu baten jeisketa burutu du eta orain berrabiarazia izan behar da eguneraketa ezarria ahal izateko
-PiecesView.BlockView.Have=Duzu
-PiecesView.BlockView.NoHave=Ez Duzu
-PiecesView.BlockView.Header=%1 zutabe, %2 lerro, %3 atal
-ConfigView.section.update.autodownload=Berez jeitsi eguneraketak eta galdetu ezarpena gertu dagoenean 
-Peers.column.peer_id=Hartzaile ID-a
-Peers.column.peer_id.info=Hartzailearen ID-a era irakurgarrian
-Peers.column.peer_byte_id=Hartzaile ID-a
-Peers.column.peer_byte_id.info=Hartzailearen ID-a byte eran
-Peers.column.handshake_reserved=Eskuemateak Gordetako Byteak
-Peers.column.handshake_reserved.info=Adierazten du zein bit izan ziren ezarriak BT eskuematean
-Peers.column.client_identification=Bezero Nortasuna
-Peers.column.client_identification.info=Adierazten du Vuzetik jasoriko bezero izenak - erabilgarria garbiketarako
-dht.warn.user=Jakinarazi balizko NAT/ ataka mapaketa arazoak
-ConfigView.label.openbar.incomplete=Jeisketa barrak: berez ireki jeisketak
-ConfigView.label.openbar.complete=berez ireki emaritzak
-ConfigView.label.transferbar.remember_location=Gogoratu eskualdaketa barraren azken kokapena
-ConfigView.section.transfer.autospeed.forcemin=%1 igoera abiadura behartuta ohinbideratze elkarketan
-MainWindow.menu.tools.speedtest=Abiadura Azterketa...
-speedtest.wizard.title=Abiadura Azterketa
-speedtest.wizard.run=Egin abiadura azterketa bat
-speedtest.wizard.test.mode.updown=igoera eta jeisketa
-speedtest.wizard.test.mode.up=igo
-speedtest.wizard.test.mode.down=jeitsi
-SpeedTestWizard.test.panel.currinfo=BitTorrent bandazabalera aztertzen.
-SpeedTestWizard.test.panel.label=Vuze abiadura azterketa:
-SpeedTestWizard.test.panel.already.running=Azteketa jadanik lanean!
-SpeedTestWizard.test.panel.not.accepted=Azterketa eskabidea ez da onartu:
-SpeedTestWizard.test.panel.abort=Utzi
-SpeedTestWizard.test.panel.abort.countdown=Azterketa hemen utzita:
-SpeedTestWizard.test.panel.test.countdown=azterketa amaituko da:
-SpeedTestWizard.test.panel.testfailed=Azterketak huts egin du
-SpeedTestWizard.test.panel.aborted=Azterketa eskuz utzita
-SpeedTestWizard.test.panel.enc.label=Sakatu enkriptaketarekin aztertzeko: 
-SpeedTestWizard.test.panel.standard=irizpidea
-SpeedTestWizard.test.panel.encrypted=enkriptatuta
-SpeedTestWizard.set.upload.button.apply=Ezarri
-SpeedTestWizard.set.upload.result=Azken Azterketaren Emaitza
-SpeedTestWizard.set.upload.bytes.per.sec=kByte/seg
-SpeedTestWizard.set.upload.bits.per.sec=bit/seg
-SpeedTestWizard.finish.panel.title=Abiadura Azterketa Amaiturik!
-SpeedTestWizard.finish.panel.click.close=Amaitu duzu abiadura azterketa laguntzailea. Klikatu itxi irtetzeko
-SpeedTestWizard.finish.panel.max.upload=Geh. igoera:
-SpeedTestWizard.finish.panel.max.seeding.upload=Geh. igoera emaritzen:
-SpeedTestWizard.finish.panel.max.download=Geh. jeisketa:
-SpeedTestWizard.finish.panel.enabled=gaiturik
-SpeedTestWizard.finish.panel.disabled=ezgaiturik
-SpeedTestWizard.abort.message.scheduled.in=azteketa egitarauturik ... %1 segundutan
-SpeedTestWizard.abort.message.unsupported.type=Azterketa mota ez dago sostengatuta!!!!
-SpeedTestWizard.abort.message.manual.abort=Eskuz utzita
-SpeedTestWizard.abort.message.scheduling.failed=Azterketaren egitaraupenak huts egin du
-SpeedTestWizard.abort.message.download.added=Azterketan gehitutako %1 jeitsi
-SpeedTestWizard.abort.message.entered.error=Aztertu osoki jeitsitako akats egoera '%1'
-SpeedTestWizard.abort.message.entered.queued=Aztertu osoki jeitsitako lerrokatuta/geldituta egoera
-SpeedTestWizard.abort.message.interrupted=TorrentAbiaduraAzterketaLeihoMezua eten egin da azterketa amaitu aurretik
-SpeedTestWizard.abort.message.execution.failed=Azterketa egiteak huts egin du
-SpeedTestWizard.abort.message.failed.peers=Hutsegitea hartzaileekin elkarketatzean
-SpeedTestWizard.abort.message.insufficient.slots=Ezin da igo edozein hartzailetara - ez dago nahikoa igoera aho?
-SpeedTestWizard.abort.message.not.unchoked=Ezin da inoiz itogabetu ez diren hartzaieletatik jeitsi
-SpeedTestWizard.stage.message.requesting=azterketa eskabidean...
-SpeedTestWizard.stage.message.preparing=azterketa gertatzen...
-SpeedTestWizard.stage.message.starting=azterketa hasten...
-SpeedTestWizard.stage.message.connect.stats=Elkarketa estatistikak: hartzaileak=%1, jeisketa_ongi=%2, igoera_ongi=%3
-window.uiswitcher.title=Vuze EI Hautatzailea
-window.uiswitcher.text=Mesedez hautatu zure beharretara hobekien egokitzen den erabiltzaile interfaze bat.
-window.uiswitcher.NewUI.text=* Gomendatua hasiberrientzat eta erabilltzaile berrientzat.\n\n* Erraza, ikusizko grafika interfazea 
-window.uiswitcher.ClassicUI.title=Interfaze Klasikoa
-window.uiswitcher.ClassicUI.text=*Bezeroaren eginkortasun 2.x serieak gordetzen ditu\n\n* Hegats erakuste klasikoa
-iconBar.switch.tooltip=Vuze UI Hautatzailea
-VivaldiView.notAvailable=Vivaldi Ikuspena ez dago eskuragarri
-restart.error=Berrabiarazteak huts egin du\n%1\nIkusi <A HREF="{restart.error.url}">berrabiarazte gaiak</a>.
-restart.error.oom=Oroimenetik kanpo
-restart.error.fnf='%1' ez da aurkitu '%2'
-restart.error.pnf='%1' Helburua ez da aurkitu
-restart.error.bad=Agiri heuskarri okerra '%1'
-restart.error.denied=Sarbidea ukatua izan da '%1' abiarazten saiatzean. Zihur zaude programa hau abiarazteko eskubidea duzula.
-TableColumn.header.date_completed=Osaturik
-TableColumn.menu.date_added.reset=Berrezarri Eguna
-ConfigView.section.ipfilter.discardbanning=Itxi hartzaileak baztertutako datuak/datu onak bataz-bestekoa gainditzen badu  [0: ezgaituta]
-ConfigView.section.ipfilter.discardminkb=Gutxienez %1 baztertuta bataz-bestekoa ezarri aurretik
-ConfigView.interface.start.advanced=Hasi Ikuspegi Aurreratuan (AZ 2.x)
-MyTorrents.column.ColumnQuality=Ontasuna
-MyTorrents.column.ColumnSpeed=Abiadura
-MyTorrents.column.ColumnProgressETA.2ndLine=UED: %1
-MyTorrents.column.ColumnProgressETA.StreamReady=Jarioa Gertu
-MyTorrents.column.ColumnProgressETA.PlayableIn=Irakurgarri %1
-TableColumn.header.Quality=Ontasuna
-TableColumn.header.Speed=Abiadura
-TableColumn.header.RateIt=Maila
-TableColumn.header.Rating=Mailatzen
-TableColumn.header.SpeedGraphic=Abiadura
-TableColumn.header.AzProduct=Hemendik
-TableColumn.header.MediaThumb=Hedabidea
-TableColumn.header.ProgressETA=Garapena
-TableColumn.header.name.ext=Agiri Mota: %1
-TableColumn.header.DateCompleted=Eguna
-v3.MainWindow.tab.home=Tresnategia
-v3.MainWindow.tab.browse=Vuzen
-v3.MainWindow.tab.library=Liburutegia
-v3.MainWindow.tab.publish=Argitaratu
-v3.MainWindow.tab.advanced=Aurreratua
-v3.MainWindow.menu.home=&Tresnategia
-v3.MainWindow.menu.browse=&Vuzen
-v3.MainWindow.menu.library=&Liburutegia
-v3.MainWindow.menu.publish=&Argitaratu
-v3.MainWindow.menu.advanced=&Aurreratua
-v3.MainWindow.menu.view.searchbar=Bilaketa Barra
-v3.MainWindow.currentDL=Orain Jeisten
-v3.MainWindow.button.stream=Jarioa
-v3.MainWindow.button.stop=Gelditu
-v3.MainWindow.button.start=Hasi
-v3.MainWindow.button.pause=Pausatu
-v3.MainWindow.button.resume=Berrekin
-v3.MainWindow.button.delete=Ezabatu
-v3.MainWindow.button.comment=Aipamena
-v3.MainWindow.button.viewdetails=Ikusi Xehetasunak
-v3.MainWindow.button.play=Irakurri
-v3.MainWindow.button.cancel=Ezeztatu
-v3.MainWindow.button.preview=Aurreikuspena
-v3.MainWindow.view.wait=Ikuspena abiarazten, mesedez itxaron
-v3.MainWindow.xofx=%1 %2 -tik
-v3.MainWindow.Loading=Gertatzen... Mesedez Itxaron
-v3.filter-bar=Izenburu Iragazkia:
-v3.MainWindow.search.defaultText=Bilatu Torrentak...
-v3.mb.delPublished.title=Gelditu Eduki Emaritza
-v3.mb.delPublished.text=KONTUZ: Ekintza honek EZ du argitaraturiko zure edukia kenduko '%1' hemendik <A HREF="%2">%3</A> .\n\nKlikatu "Ezabatu" zure edukiak argitaraturik eta jeisgarri nahi badituzu bakarrik, baina zure bandazabalera askatzea nahi baduzu. Egin aurretik zihurtatu zaitez igoera aurrerabidea burutu dela (<A HREF="%4">nola</A>?).\n\nKlikatu "Ezeztatu" argitaraturiko zure edukiak erabat kentzea nahi badituzu %3, eta erabili (X) botoia Argitaraturiko Edukia leihoan Argitalpen  [...]
-v3.mb.delPublished.delete=&Ezabatu
-v3.mb.delPublished.cancel=E&zeztatu
-v3.mb.PlayFileNotFound.title=Agira Ez da Aurkitu
-v3.mb.PlayFileNotFound.text=Hemengo agiriak '%1' ezabaturik edo galduta daude.
-v3.mb.PlayFileNotFound.button.remove=Kendu Vuzetik
-v3.mb.PlayFileNotFound.button.redownload=Birjeitsi Datuak
-v3.mb.PlayFileNotFound.button.find=Eskuzko Bilaketa.
-v3.topbar.menu.show.logo=Logoa
-v3.topbar.menu.show.plugin=Plugin Gunea
-v3.topbar.menu.show.search=Bilatu
-v3.topbar.menu.show.frog=Da Igel Urdina
-splash.initializeCore=Core-a abiarazten
-splash.initializeUIElements=EI Osagaiak Abiarazten
-ConfigView.section.transfer.autospeedbeta=Berez-Abiadura-Beta
-ConfigView.section.ipfilter.peerblocking.group=Hartzaile Itxipena
-ConfigView.section.ipfilter.autoload.group=Berez Gertatzen
-ConfigView.section.ipfilter.autoload.file=IP iragazki agiria berezgertatzeko
-ConfigView.section.ipfilter.autoload.info=DAT (eMule), P2P (PeerGuardian, splist), eta P2B v1,2,3 (PeerGuardian 2) heuskarriak sostengatzen ditu. Agiria tokikoa izan daiteke edo URL, zip'd, gzip'd edo idazki laua. URL-ak berezgaitasunez birjeitsiko dira 7 egun ondoren, aldiz agiriak ordeztua/ikutua izan eta minutu batera birgertatzen dira.
-ConfigView.section.ipfilter.autoload.loadnow=Gertatu Orain
-splash.loadIpFilters=IP Iragazkiak Gertatzen...
-SpeedTestWizard.set.upload.title=Ezarri Igoera eta Jeisketa Mugak
-SpeedTestWizard.set.download.label=Jeisketa Abiadura Muga:
-SpeedTestWizard.set.upload.label=Igoera Abiadura Muga:
-SpeedTestWizard.name.conf.level.absolute=Osoa
-SpeedTestWizard.name.conf.level.high=Handia
-SpeedTestWizard.name.conf.level.med=Ertaina
-SpeedTestWizard.name.conf.level.low=Txikia
-SpeedTestWizard.name.conf.level.none=Ez
-ConfigView.section.transfer.select=Berez-Abiadura
-ConfigView.section.transfer.select.v2=Berez-Abiadura (beta)
-mb.azmustclose.title=Abiatze Akatsa
-mb.azmustclose.text=Vuzek amaitu beharra du arazo bat dagoelako Vuzeren (bir)abiaraztean zihurrenik programa erabiltzaile administrari bezala exekutatu izanak eragin duena.\n\nVuze itxi ondoren, mesedez bir-ireki eskuz.
-network.ipv6.prefer.addresses=Hobetsi IPv6 helbideak biak IPv6 eta IPv4 eskuragarri daudenean
-network.bindError=Lotura zerbitzariaren ahoak huts egin du helbide eskuragarririk ez dagoelako, mesedez egiaztatu zure IP loturen ezarpenak.
-network.enforce.ipbinding=Betearazi IP loturak baita interfazeak eskuragarri ez direnean, saihestu edozein elkarketa adierazitako interfazeetako bat ere eskuragarria ez denean
-DHTView.title.full_v6=Banaturiko Datubasea IPv6
-ConfigView.pluginlist.loadSelected=Gertatu Hautatua
-SpeedView.stats.asn=Sarea:
-SpeedView.stats.estupcap=Igoera muga:
-SpeedView.stats.estdowncap=Jeisketa muga:
-SpeedView.stats.unknown=Ezezaguna
-SpeedView.stats.estimate=Irizpena
-SpeedView.stats.measured=Neurtuta
-SpeedView.stats.measuredmin=Neurtuta Gutx.
-SpeedView.stats.manual=Finkatuta
-ConfigView.section.transfer.autospeed.networks=Sare Xehetasunak
-ConfigView.section.transfer.autospeed.resetnetwork=Berrezarri sare xehetasunak
-ConfigView.section.transfer.autospeed.network.info=Gaineko mugak arrunt berezgaitasunez kalkulatzen dira jeisketan zehar edo abiadura azterketa baten emaitza dira. Eskuz adieraztea nahi badituzu erabili beheko aukerak.\nBeste muga guztiak 'finkoak' ondoren ezarriko dira berezgaitasunez beharrezkoa bada \nSartu balioa eta hautatu mota. Kontuan izan abiadurak direla %1.
-dialog.uiswitcher.restart.title=EI Aldatzailea: Vuze Berrabiaraztea Beharrezkoa
-dialog.uiswitcher.restart.text=Vuzek berrabiaraztea behar du EI modu berrira aldatzeko.
-TrayWindow.menu.close=Itxi Jeisketa Saskia
-# Used for peers which we can't determine.
-PeerSocket.unknown=Ezezaguna
-PeerSocket.fake_client=USTELA
-PeerSocket.bad_peer_id=hartzaile txar ID-a
-PeerSocket.mismatch_id=ez dator bat
-PeerSocket.unknown_az_style=Ezezaguna %1 %2
-PeerSocket.unknown_shadow_style=Ezezaguna  %1 %2
-OpenTorrentWindow.mb.askCreateDir.title=Helmuga Zuzenbidea ez dago
-OpenTorrentWindow.mb.askCreateDir.text='%1' helmuga zuzenbidea ez dago.\n\nOrain sortu?
-SpeedView.stats.estimatechoke=Irizpena (itopena)
-ConfigTransferAutoSpeed.upload.capacity.usage=Igoera Gaitasun Erabilia
-ConfigTransferAutoSpeed.mode=Era:
-ConfigTransferAutoSpeed.capacity.used=%  Gaitasun Erabilia 
-ConfigTransferAutoSpeed.while.downloading=Jeisten:
-ConfigTransferAutoSpeed.set.dht.ping=DHT Ping Ezarpena:
-ConfigTransferAutoSpeed.set.point=zehazte puntua (sm)
-ConfigTransferAutoSpeed.set.tolerance=jasangarritasuna (sm)
-ConfigTransferAutoSpeed.ping.time.good=Ona:
-ConfigTransferAutoSpeed.ping.time.bad=Gaitza:
-ConfigTransferAutoSpeed.adjustment.interval=Zehaztu tarteak:
-ConfigTransferAutoSpeed.skip.after.adjust=Jauzi zehaztu ondoren:
-GeneralView.label.distributedCopies=Banatutako Kopiak:
-PiecesView.DistributionView.title=Atalen Banaketa
-PiecesView.DistributionView.NoAvl=Atal Eskuraezinak
-PiecesView.DistributionView.SeedAvl=Emaritza Eskur.Ekarpena
-PiecesView.DistributionView.PeerAvl=Hartzaile Eskur.Ekarpena
-PiecesView.DistributionView.RarestAvl=Atal Arraroak: %1 (Eskur:%2)
-PiecesView.DistributionView.weHave=Dituzun atalak
-PiecesView.DistributionView.theyHave=Hartzaileak dituen atalak
-PiecesView.DistributionView.weDownload=Jeisten ari zaren atalak
-PeersView.gain=Irabazia
-PeersView.gain.info=Jeitsitako-igotako datu zenbatekoa
-unix.script.new.title=Vuzeren Abiarazpen Eskript Berria eskuragarri
-unix.script.new.text=Vuzeren abiarazte script berri bat eskuragarri dago, eta hemen gordea izan da '%1'.\n\nOso gomendagarria da Vuzetik irtetzea eta eskript honetara aldatzea ('%2').\n\nOso eraldatua baduzu zure Vuze abiarazte eskripta, mesedez ikusi <A HREF="{unix.script.new.manual.url}">VuzeWiki: Unix Script</A>.\n\nVuze distro batetik ezarri bazenuen (yum, apt-get, e.a), Gomendatzen da Vuze berrabiaraztea erabiliz  hemen dagoen pakete hau <AHREF="http://www.vuze.com/download/">Vuze D [...]
-unix.script.new.button.quit=Utzi Orain
-unix.script.new.button.continue=Gero Egingo Dut
-unix.script.new.button.asknomore=Ez Esan Berriro
-unix.script.new.auto.title=Vuzeren Abiarazpen Eskript Berria
-unix.script.new.auto.text=Vuzeren Abiarazpen Eskript berria eskuragarri.\n\nOso gomendagarria da zure Vuze berrabiarazia izatea orain.
-Content.alert.notuploaded.button.abort=&Ez Irten
-ConfigView.label.checkOnSeeding=Egin baliabide gutxiko atalen egiaztapena emaritzan
-ConfigView.label.ui_switcher=Erakutsi Vuze EI Hautatzailea
-ConfigView.label.ui_switcher_button=Erakutsi
-SpeedTestWizard.test.panel.explain=Neurtu zure Vuze protokoloaren abiadura. Hautatu abiadura azterketa mota eta enkriptaketa modua. Ikusi Vuzeren wiki orrialdea azterketa honi buruzko xehetasunetarako. Azterketa berezgaitasunez gelditu daiteke bi minutu baino gehiago luzatzen bada. Ohiko azterketak minutu bat baino gutxiagoan amaitzen dira.
-SpeedTestWizard.set.upload.hint=Ezarri Vuzeren BerezAbiadura algoritmoan erabiliko dire igoera eta jeisketa mugak.
-SpeedTestWizard.set.upload.panel.explain=Hemen ezarritako mugak Vuzeren BerezAbiadura algoritmorako erabiltzen dira. Ezarri eskualdaketa mugak eta segurtasun mugak.\n\nKontuan izan bide abiadurak maiz "bit segunduko" neurrian ematen direla - horrela ere behean erakusten diren balioak "kilobyte segunduko" neurrian ematen dira.
-SpeedTestWizard.set.limit.conf.level=Segurtasuna
-SpeedTestWizard.finish.panel.auto.speed=Berez-Abiadura da:
-SpeedTestWizard.finish.panel.auto.speed.seeding=BerezAbiadura emaritzan da:
-ConfigTransferAutoSpeed.add.comment.to.log.group=Gehitu aipamena garbiketa saioan
-ConfigTransferAutoSpeed.add.comment.to.log=Gehitu aipamena:
-ConfigTransferAutoSpeed.log.button=Laburpena
-ConfigTransferAutoSpeed.algorithm.selector=Berez-Abiadura hautagailua
-ConfigTransferAutoSpeed.algorithm=Algoritmoa:
-ConfigTransferAutoSpeed.auto.speed.classic=Berez-Abiadura (klasikoa)
-ConfigTransferAutoSpeed.auto.speed.beta=Berez-Abiadura (beta)
-ConfigTransferAutoSpeed.data.update.frequency=Eguneratze Maiztasuna
-Alert.failed.update=Huts egin du gutxienez osagai baten ezarpenak. Ikusi  <A HREF="{Alert.failed.update.url}">AzureusWiki: Failed Update</A> [%1]
-Alert.failed.update.url=http://wiki.vuze.com/w/Failed_Update\u005c
-OpenTorrentWindow.mb.existingFiles.partialList=(Zerrenda osatugabea  Agiri gehieago jadanik badaude)
-TableColumn.header.bad_avail_time.info=Jeisketaren kopia oso bat eskuragarria izan zen azken aldia
-TableColumn.header.bad_avail_time=Kopia Osoa Ikusita
-MyTorrentsView.menu.exporthttpseeds=Esportatu HTTP emaritza URL-ak gakora
-SWT.alert.erroringuithread=Kudeatu ezinezko akats bat gertatu da EIG-an, akats gehiago egon daiteke.
-ConfigView.label.minannounce=Gutxienezko denbora aztarnariaren iragarpenen artean segundutan
-ConfigView.label.maxnumwant=Mugatu itzul daitezkeen aztarnari hartzaile zenbatekoa 
-ConfigView.label.announceport=Ordeztu iragarritako TCP ataka aztarnari iragarletzatarako, pex eta dht\n[utzi hutsik: ez ezeztatu, 0: sarrera elkarketarik ez]
-ConfigView.label.noportannounce=Ez iragarri aztarnariari aditze ataka (honek ez die hauei eragiten: pex, dht )
-ConfigView.label.maxseedspertorrent=Geh. emale torrent bakoitzeko [0: mugagabea] 
-wizard.webseed=Gehitu HTTP Emaritzak torrentetik
-wizard.webseed.title=HTTP Emaritzak
-wizard.webseed.configuration=HTTP Emaritza Itxurapena
-wizard.webseed.adding=HTTP Emaritzak Gehitzen
-GeneralView.label.private=Torrent Pribatua:
-GeneralView.yes=Bai
-GeneralView.no=Ez
-ConfigView.label.userequestlimiting=Erabili eskabide mugapena irakur atzerapenaren ordez jeisketa abiadura mugatzeko [ez du eraginik jeisketa abiadura mugagabea denean]
-ConfigView.label.userequestlimiting.tooltip=Eskabidea mugatzea ez da irakurketa atzerapena bezain lehuna, baina ahalbidetzen du jeisketa lehetasunean ohinarrituz, jeisketako lerro kokapena eta sarearen errendimendua hobetzea
-ConfigView.label.userequestlimitingpriorities=Finkatu jeisketa abiadura jeisketa lerroburuan jeisketa abiadura muga erdiesten denean
-ConfigView.section.logging.timestamp=Denbora irarketa heuskarria ohar agirientzat
-Peers.column.timetocomplete=Gelditzen den Denbora
-Peers.column.timetocomplete.info=Hartzailea osatuta dagoen arte gelditzen den denbora
-ConfigView.section.interface.display.suppress.file.download.dialog=Ezabatu Agiri Jeisketa oharleiho elkarrizketa
-ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Erakutsi agiri guztien jeisketa garapena elkarrizketa leihoko egoera barran 
-FileDownload.canceled=Torrent agiriaren jeisketa ongi ezeztatu da erabiltzailearen ekintzaz: %1
-Progress.reporting.status.canceled=Ezeztaturik
-Progress.reporting.status.finished=Amaiturik
-Progress.reporting.status.retrying=Birsaiatzen...
-Progress.reporting.action.label.retry.tooltip=Birsaiatu eragiketa
-Progress.reporting.action.label.remove.tooltip=Kendu Garapen Ohar hau historiatik
-Progress.reporting.action.label.cancel.tooltip=Ezeztatu eragiketa
-Progress.reporting.action.label.detail=Xehetasunak
-Progress.reporting.default.error=Huts egin du
-Progress.reporting.no.reports.to.display=Une honetan ez dago garapen oharrik erakusteko
-Progress.reporting.no.history.to.display=Ez dago xehetasun mezurik erakusteko.
-Progress.reporting.detail.history.limit=Xehetasun mezu muga (%1) GarapenOhar honentzat gehiegizkoa da; ondorioz mezuak ez dira historiara gehituak izango
-Progress.reporting.statusbar.button.tooltip=Erakutsi Garapen Jakinarazpen Leihoa
-webui.bindip=Lotura IP-a - arrunt ez da beharrezkoa
-v3.MainWindow.text.log.in=Sartu
-v3.MainWindow.text.log.out=Irten
-v3.MainWindow.text.get.started=Izena Eman
-v3.MainWindow.text.my.account=Kontu Argibideak
-v3.MainWindow.text.my.profile=Profila
-OpenTorrentWindow.simple.open=Torren Helbidea (Agiria, URL-a, Hasha)
-Progress.reporting.window.remove.auto=Berezgaitasunez kendu jarduera gabeko gaiak 
-Progress.reporting.window.remove.auto.tooltip=Berez kendu osaturiko, huts eginiko, edo ezeztaturiko aurrerabideak ikuspenetik
-Progress.reporting.window.remove.now=Kendu jarduera gabeko gaiak
-Progress.reporting.window.remove.now.tooltip=Kendu osaturiko, huts eginiko, edo ezeztaturiko aurrerabide guztiak ikuspenetik
-dhttracker.tracklimitedwhenonline=Horrela ere, egin baliabide apalen aztarnapena online daudenean erletaldeko kidegurutzapenerako
-TorrentOptionsView.multi.title.short=Torrent Aukerak/Argibideak
-TorrentOptionsView.multi.title.full=Torrent Aukerak/Argibideak
-MyTorrentsView.menu.open_parent_folder=Ireki Edukiaren Agiritegia
-ConfigView.section.style.use_show_parent_folder=Erabili "%1" ordez "%2" torrent menuetan
-ConfigView.section.style.use_show_parent_folder.tooltip=Aukera hau gaitzeak eduki agiritegia agiri kudeatzaile egokian irekitzea ahalbidetzen dizu.\nHorrela ere, honek esanahi dezake jeisketaren gordetze helbidea ez dela berezgaitasunez hautatua.
-PeerManager.status.ps_disabled=Aztarnari hartzaile iturburua ezgaituta dago
-ConfigView.section.stats.exportfiles=Esportatu agiri xehetasuanak
-updater.cant.write.to.app.title=Ezin da Idatzi Aplikazioaren Agiritegira
-updater.cant.write.to.app.details=Agiritegia "%1" idaztezina da.\n\nHonek etorkizuneko software eguneratzeak ezartzea saihestuko du.\n\nMesedez <a href="http://wiki.vuze.com/w/Failed_Update">ikusi wikia xehetasunetarako</a>.
-plugin.install.class_version_error=Plugin honek Javaren bertsio berriena behar du lan egiteko.
-v3.MainWindow.tab.minilibrary=Jeisketak
-v3.MainWindow.tab.events=Jakinarazpenak
-button.columnsetup.tooltip=Zutabe Ezarpena
-v3.activity.remove.title=Ezabatu Jakinarazpena
-v3.activity.remove.text=Zihur zaude Jakinarazpen hau ezabatzea nahi duzula?\n%1
-v3.MainWindow.menu.file.closewindow=Itxi
-Menu.show.torrent.menu=Erakutsi Torrenten menua
-Menu.show.torrent.menu.tooltip=Erakutsi Torrenten menua menubarraren gorenaldean
-Views.plugins.aznetstatus.title=Sare Egoera
-plugin.aznetstatus.pingtarget=Ping/zantzu bide xedea (Packet INternet Groper=INternetako Pakete Eskuztatzailea)
-ConfigView.section.style.usePathFinder=Erabili 'Helburu Bilatzailea' 'Bilatzailea'-ren ordez
-menu.sortByColumn=Antolatu %1 arabera
-MyTorrentsView.menu.manual.per_peer=Eskuz (hartzaileko)
-MyTorrentsView.menu.manual.shared_peers=Eskuz (hartzaile artean)
-v3.button.removeActivityEntry=Kendu Jakinarazpena
-v3.splash.initSkin=UI Azala abiarazten
-v3.splash.hookPluginUI=Elkarketatzen IU Pluginean
-OpenTorrentWindow.mb.notTorrent.cannot.display=Ezgaitu datuak egoki erakusteko
-MainWindow.menu.window.zoom.maximize=Handitu
-MainWindow.menu.window.zoom.restore=Txikiagotu
-security.crypto.title=Enkriptazio Giltza Sarbidea
-security.crypto.encrypt=Mesedez idatzi sarhitz bat sortu berri duzun enkriptaketa giltza babesteko. Mesedez ez ahaztu sarhitz hau, ez dago berreskuratzeko biderik egiten baduzu!
-security.crypto.decrypt=Mesedez idatzi sarhitza zure enkriptaketa giltza irekitzeko.
-security.crypto.reason=Eragiketa arrazoia
-security.crypto.password=Sarhitza
-security.crypto.password2=Sartu berriro sarhitza
-security.crypto.persist_for=Sarhitzaren iraupen epea
-security.crypto.persist_for.dont_save=Ez gorde
-security.crypto.persist_for.session=Saio hau
-security.crypto.persist_for.day=1 egun
-security.crypto.persist_for.week=1 aste
-security.crypto.persist_for.30days=30 egun
-security.crypto.persist_for.forever=Betirako
-security.crypto.password.mismatch.title=Sarhitz Akatsa
-security.crypto.password.mismatch=Idatzitako sarhitz balioak ezberdinak dira, mesedez sartu berriro.
-ConfigView.section.security.group.crypto=Publikoa/Pribatua Giltzak
-ConfigView.section.security.resetkey=Berrezarri giltzak
-ConfigView.section.security.resetkey.warning.title=Datu Galera Kontuz
-ConfigView.section.security.resetkey.warning=Zihur zaude zure enkriptaketa giltzak leheneratzea nahi dituzula? Egiten baduzu enkriptatutako argibide guztiak BETIRAKO GALDU daitezke. Baita ere, zure giltza publikoa duen edonor hartzaileek ezingo du jadanik zurekin harremandu zure giltza berria lortu arte. Hortaz, egitan zer egiten ari zaren jakin ezean, ezazu hori egin.
-ConfigView.section.security.unlockkey=Irekitze giltza bereziak
-ConfigView.section.security.unlockkey.button=Ireki
-ConfigView.section.security.publickey=Giltza Publikoa
-ConfigView.section.security.publickey.undef=Oraindikan zehaztu gabe
-ConfigView.section.security.resetkey.error.title=Eragiketak Huts egin du
-ConfigView.section.security.resetkey.error=Hutsegitea du giltzak berrezartzean
-ConfigView.section.security.unlockkey.error=Huts egin du giltza irekitzean - sarhitz okerra
-ConfigView.copy.to.clipboard.tooltip=Kopiatu gakoan
-Views.plugins.azbuddy.title=Lagunak
-Browser.popup.error.no.access=Akats bat gertatu da hurruneko baliabide bat atzitzerakoan.\nMesedez saiatu zaitez geroago
-ConfigView.label.queue.stoponcebandwidthmet=Ez hasi beste torrentik igoera/jeisketa abiadura muga lortua dagoenen
-ConfigView.section.style.forceMozilla=Behartu Vuze Mozilla erabiltzera tresnak Bilatzeko [xulrunner edo firefox 3 beharrezkoa; berrabiaraztea beharrezkoa]
-ConfigView.section.style.xulRunnerPath=Adierazi  XulRunner / Firefox helburua eskuz [beharrezkoa FF3-rentzat; berrabiaraztea beharrezkoa]
-azbuddy.name=Lagunak
-azbuddy.enabled=Gaituta
-azbuddy.disabled=Plugina ezgaiturik dago, ikusi plugin itxurapenak aldatzeko.
-azbuddy.nickname=Zure Izenordekoa
-azbuddy.msglog.title=Lagun argibideak
-azbuddy.addtorrent.title=Jeisketa Onartu?
-azbuddy.addtorrent.msg=Laguna '%1' bidali dizu '%2'.\nJeisketa hau gehitzea nahi duzu?
-azbuddy.contextmenu=Bi&dali Lagun Bati
-azbuddy.ui.mykey=Nire giltza:
-azbuddy.ui.add=Gehitu
-azbuddy.ui.new_buddy=Lagun berriaren giltza:
-azbuddy.ui.table.name=Izena
-azbuddy.ui.table.last_ygm=MBD
-azbuddy.ui.table.last_msg=Azken Mezua
-azbuddy.ui.menu.remove=Kendu
-azbuddy.ui.menu.copypk=Kopiatu Giltza Publikoa
-azbuddy.ui.menu.send=Bidali Mezua
-azbuddy.ui.menu.send_msg=Sartu zure lagunari bidaltzeko idazkia
-azbuddy.ui.menu.ping=Ping (INT. Pak. Eskuzt.)
-azbuddy.ui.menu.ygm=Bidali MBD
-azbuddy.ui.menu.enc=Enkriptautu Gakoa
-azbuddy.ui.menu.dec=Dekriptatu Gakoa
-azbuddy.ui.menu.sign=Izenpetu Gakoa
-azbuddy.ui.menu.verify=Egiaztatu Gakoa
-azbuddy.ui.table.lastseen=Azkenaldiz Ikusia
-Button.retry=&Birsaiatu
-Button.ignore=&Ezikusi
-DHTView.general.skew=Bihurria:
-azbuddy.ui.table.msg_in=Mezu Sarrera
-azbuddy.ui.table.msg_out=Mezu Irteera
-v3.MainWindow.menu.view.footer=Orrialde ohina
-azbuddy.downspeed=KB/s geh. lagunen jeisketa abiadura [0: mugagabea]
-azbuddy.ui.table.con=CON
-security.crypto.badpw=Emandako sarhitza ez da zuzena
-ConfigView.section.security.backupkeys=Babeskopia giltza agiri bati
-ConfigView.section.security.backupkeys.button=Babeskopia
-ConfigView.section.security.restorekeys=Leheneratu giltzak agiri batetik
-ConfigView.section.security.restorekeys.button=Leheneratu
-ConfigView.section.security.op.error.title=Eragiketak Huts egin du
-ConfigView.section.security.op.error=Huts egin du eragiketa osatzean:\n    %1
-ConfigView.section.security.restart.title=Berrabiarazpena Beharrezkoa
-ConfigView.section.security.restart.msg=Vuze orain berrabiarazi daiteke eragiketa osatzeko
-ConfigView.section.security.system.managed=Erabide kudeaketa giltza babesa
-azbuddy.ui.table.msg_queued=Lerrokatuta
-azbuddy.ui.menu.chat=Eztabaidagunea
-azbuddy.chat.title=Vuze Eztabaidagunea
-azbuddy.chat.says=%1-ek dio:
-Button.bar.show=Erakutsi
-Button.bar.hide=Ezkutatu
-Button.bar.share=Elkarbanatu
-Button.bar.add=Gehitu
-Button.bar.edit=Editatu
-Button.bar.edit.cancel=Edizioa Eginda
-v3.MainWindow.menu.view.pluginbar=Plugin Barra
-MainWindow.dialog.select.vuze.file=Hautatu Vuze Agiria
-MainWindow.menu.file.open.vuze=Vuze Agiria...
-metasearch.addtemplate.title=Ezarri Eredua Bilatu?
-metasearch.addtemplate.desc=Zihur zaude '%1' izena duen bilaketa eredua ezartzea nahi duzula?
-v3.share.private.title=Torrenta Elkarbanatzen
-v3.share.private.text=Hautaturiko torrenta Torrent Pribatu bezala markaturik dago\n\nEzin duzu torrent pribaturik elkabanatu.
-metasearch.addtemplate.dup.title=Bikoiztu Eredua
-metasearch.addtemplate.dup.desc=%1 Bilatu eredua jadanik ezarrita dago
-metasearch.export.select.template.file=Gorde Eredua
-metasearch.import.select.template.file=Ireki Eredua
-azbuddy.tracker.enabled=Gaitu 'Lagun Kitzikapena' zure lagunekin jeisketak lehenesteko
-azbuddy.protocolspeed=KB/s geh. lagun harremanaren burugain
-v3.MainWindow.button.download=Jeitsi
-v3.MainWindow.button.run=Jaulki Jeitsitako Agiria
-v3.activity.header.downloads=Jeisketak
-v3.activity.header.vuze.news=Vuze Berriak
-message.taking.too.long=Badirudi uste baino denbora gehiago hartzen ari dela\nSakatu 'ESC' eragiketa hau ezeztatzea nahi baduzu
-message.status.success=Gertaerak
-azbuddy.tracker.bbb.status.title=Lagun Kitzikapena
-azbuddy.tracker.bbb.status.title.tooltip=Klik bikoitza xehetasunak ikusteko
-azbuddy.tracker.bbb.status.idle=Kitzikapen Gabe
-azbuddy.tracker.bbb.status.nli=Saioa Hastea Beharrezkoa da.
-azbuddy.tracker.bbb.status.in=Kitzikatua Izan Naiz
-azbuddy.tracker.bbb.status.out=Oraingo Lagun Kitzikapena
-v3.MainWindow.search.go.tooltip=Exekutatu Bilaketa
-v3.MainWindow.search.last.tooltip=Itzuli bilaketa emaitzetara
-metasearch.addtemplate.done.title=Eredua Gehituta
-metasearch.addtemplate.done.desc='%1' eredua ongi gehitu da.\nHurrengo bilaketan erabili dezakezu!
-ConfigView.section.security.nopw=Sarhitzik gabe jarrita
-ConfigView.section.security.nopw_v=Sarhitzik gabe eskuragarri, mesedez izena eman Vuzen
-fileplugininstall.install.title=Plugina Ezarri?
-fileplugininstall.install.desc=Zihur zaude '%1' pluginaren, %2 bertsioa ezarri nahi duzula?
-fileplugininstall.duplicate.title=Bikoiztu Plugina
-fileplugininstall.duplicate.desc='%1' Pluginaren, %2 bertsioa ezarrita dago
-azbuddy.online_status=Online Egoera
-azbuddy.os_away=Batbatekoa
-azbuddy.os_not_avail=Eskuraezina
-azbuddy.os_busy=Lanpetuta
-azbuddy.os_offline=Lineaz-kanpo
-azbuddy.ui.menu.disconnect=Eten
-azbuddy.enable_chat_notif=Gaitu eztabaidagune oharrak
-progress.window.msg.progress=Mesedez itxaron eragiketa burutzen den bitartean
-ConfigView.section.connection.advanced.read_select=Irakurri hautatutako itxaronaldia (milaen, berez %1)
-ConfigView.section.connection.advanced.read_select_min=Irakurri hautatutako gutxiezneko itxaronaldia (milaen, berez %1)
-ConfigView.section.connection.advanced.write_select=Idatzi hautatutako itxaron denbora (milaen, berez %1)
-ConfigView.section.connection.advanced.write_select_min=Idatzi hautatutako gutxienezko itxaronaldia (milaen, berezkoa %1)
-DetailedListView.title=Zerrenda Zehatza
-ConfigView.section.connection.network.max.outstanding.connect.attempts=Geh. egiteke irteera elkarketa
-plugins.init.force_enabled=Vuzek "%1" plugina ezgaiturik dagoela atzeman du - birgaitua izan da Vuzeri zuzen lan egitea ahalbidetzeko.
-ConfigView.section.connection.prefer.udp=Hobetsi UDP elkarketa
-subscript.add.title=Ezarri Harpidetza?
-subscript.add.desc=Zihur zaude '%1' harpidetza ezartzea nahi duzula?
-subscript.add.dup.title=Bikoiztu Harpidetza
-subscript.add.dup.desc='%1' Harpidetza jadanik ezarrita dago.
-subscript.add.upgrade.title=Harpidetza Berritu?
-subscript.add.upgrade.desc=Zihur zaude '%1' harpidetza berritu nahi duzula?
-subscript.add.upgradeto.desc='%2' harpidetzaren %1 Bertsioa eskuragarri dago.\nEguneratzea nahi duzu?
-azsubs.contextmenu.addassoc=Gehitu harpidetza elkarketa
-azsubs.contextmenu.lookupassoc=Bilatu harpidetza elkarketak
-iconBar.start=Hasi
-iconBar.stop=Gelditu
-iconBar.remove=Ezabatu
-iconBar.up=Igoera
-iconBar.down=Jeisketa
-iconBar.run=Ireki
-iconBar.editcolumns=Zutabe Ezarpena
-iconBar.top=Goren
-iconBar.bottom=Beheren
-iconBar.queue=Hasi
-iconBar.open=Gehitu Torrenta
-iconBar.share=Elkarbanatu
-iconBar.share.tooltip=Elkarbanatze Edukia
-iconBar.details=Xehetasunak
-iconBar.comment=Aipamena
-iconBar.play=Irakurri
-iconBar.queue.tooltip=Hasi (lerrokatuta) hautaturiko torrentak
-v3.MainWindow.menu.view.sidebar=Alboko Barra
-v3.MainWindow.menu.view.actionbar=Eragiketa Barra
-v3.MainWindow.menu.view.toolbars=Tresna Barrak
-ump.install=Eguneratze Azkarra Egiten:\nBideo honentzat beharrezkoa den irakur gehigarri txiki bat ezartzen.
-subscriptions.listwindow.title=Harpidetza Bilatzailea
-subscriptions.listwindow.autochecktext=Vuzek zure liburutegiko edukiekin lotura duten harpidetzak bilatu ditzake. Nahi duzu eginkizun hau gaitzea?
-subscriptions.listwindow.loadingtext=Antzeko harpidetzak bilatzen  %1
-subscriptions.listwindow.failed=Ez da harpidetzarik Aurkitu
-subscriptions.listwindow.popularity=Ezaguntasuna
-subscriptions.listwindow.popularity.unknown=Ezezaguna
-subscriptions.listwindow.name=Izena
-subscriptions.listwindow.subscribe=Harpidetu
-TableColumn.header.azsubs.ui.column.subs=Harpidetu
-subscriptions.listwindow.popularity.reading=Irakurtzen...
-PluginDeprecation.log.start=Leiho honek Vuzeren hurrengo bertsioetatik kenduuak izan daitezkeen pluginei buruzko argibideak ditu.\nEz duzu pluginak kendu beharrik, azken bertsiora eguneratu ditzakezu.\nAzken bertsioarekin ari bazara lanean, mesedez kopiatu leiho honetako edukiak eta argitaratu itzazu eztabaidagune honetan:\n \t%1\n\n
-PluginDeprecation.log.details=---------\nIDENTIFKATZAILEA: %1\nCONTEXT: %2\n\n*** AZTARNAKETA HASIERA ***\n%3*** AZTARNAKETA AMAIERA ***\n\n
-PluginDeprecation.view=Plugin Garbiketa
-PluginDeprecation.alert=Plugin bat etorkizunean kenduko den egokitzapen bat erabilitzen saitu da. - mesedez ireki Plugin Garbiketa argibide gehiago ikusteko.
-TableColumn.header.Thumbnail=Ikurra
-TableColumn.header.Thumbnail.info=Vuzeren edukientzako txikirudia; beste eduki guztientzakoak sistema eragileak ematen ditu ikur hauek.
-v3.MainWindow.menu.getting_started=&Lehen Urratsak
-MainWindow.menu.community=&Herkidegoa
-MainWindow.menu.community.wiki=Herkidegoa, Wikia eta SEG
-MainWindow.menu.community.forums=Herkidego Ezta&baidaguneak
-MainWindow.menu.community.blog=Vuze &Bloga
-MainWindow.menu.help.support=&Laguntza eta Sostengua
-externalLogin.title=Izenematea Beharrezkoa
-externalLogin.explanation="%1" ereduak izen-emanda egotea eskatzen du>. Egindakoan leiho hau berezgaitasunez itxiko da. Egiten ez badu mesedez klikatu "eginda".
-externalLogin.explanation.capture=Izena eman behar duzu eredu hau sortzeko. Egindakoan, mesedez klikatu "Eginda".
-Button.done=Eginda
-GeneralView.torrent_created_on_and_by=%1 %2-tik
-Button.continue=Jarraitu
-Button.preview=Aurreikuspena
-Subscription.menu.forcecheck=Eguneratu Orain
-Subscription.menu.clearall=Markatu Emaitza Guztiak Irakurrita Bezala
-Subscription.menu.remove=Ezabatu
-sidebar.Library=Liburutegia
-sidebar.LibraryDL=Jeisten...
-sidebar.LibraryCD=Osatuta
-MySeeders.bigView.header=CDLiburtegia
-MyTorrents.bigView.header=Liburutegia
-authenticator.location=Helbidea
-authenticator.details=Xehetasunak
-v3.MainWindow.menu.showActionBarText=Erakutsi Izena
-subscript.import.fail.title=Inportatzeak Huts egin du
-subscript.import.fail.desc=Xehetasunak: %1
-Subscription.menu.export=Esportatu...
-subscript.export.select.template.file=Gorde Harpidetza
-Button.remove=Kendu
-Button.send=Bidali
-Button.back=Atzera
-sidebar.LibraryUnopened=Berria
-TableColumn.header.unopened=Berria
-Unopened.bigView.header=Berria
-Subscription.menu.deleteall=Ezabatu Emaitza Denak
-Subscription.menu.reset=Berrezarri Hasierako Egoera
-ConfigView.section.Subscriptions=Harpidetzak
-subscriptions.config.maxresults=Harpidetza bakoitzeko atxirikiriko emaitz zenbateko gehiena [0: mugagabea]
-v3.activity.button.readall=Markatu Irakurritako Denak 
-TableColumn.header.activityNew=Berria
-TableColumn.header.activityType=Mota
-TableColumn.header.activityText=Mezua
-TableColumn.header.activityDate=Gehitze Eguna
-TableColumn.header.activityActions=Eragiketak
-Subscription.menu.resetauth=Berrezarri Egiaztapen Xehetasunak
-Search.menu.engines=Ereduak
-Wizard.Subscription.title=Harpidetu
-Wizard.Subscription.optin.title=Gaitu Harpidetzak
-Wizard.Subscription.subscribe.title=Harpidetza Eskuragarriak
-Wizard.Subscription.create.title=Sortu Harpidetza Berria
-Button.search=Bilatu
-Button.save=Gorde
-Button.add=Gehitu
-Button.add.tooltip=Gehitu torrent bat zure liburutegira
-Button.createNewSubscription=Sortu Harpidetza Berri Bat
-Button.availableSubscriptions=Harpidetza Eskuragarria
-Wizard.Subscription.optin.description=Harpidetzak gaitutakoan, Vuzek zure liburutegiko edukien antzeko harpidetzak erakutsiko ditu, eta  jakinaraziko dizu harpideturiko edukiak jeisteko gertu daudenean..\n\nZure harpidetzak gaitzea nahi duzu?
-Wizard.Subscription.create.search=Bilatu
-Wizard.Subscription.search.subtitle1=Idatzi bilaketa bat zure harpidetza sortzen hasteko:
-Wizard.Subscription.search.subtitle2=Zer bilatu dezaket?
-Wizard.Subscription.search.subtitle2.sub1=HD Filmak, TB Ikuskizunak, Filmak, Vuze Sareko Trailerrak
-Wizard.Subscription.search.subtitle2.sub2=Webguneetako torrentak
-Wizard.Subscription.search.subtitle3=Zure harpidetza behin buruturik dagoenean, zuzeneko eguneratzeak jaso ditzakezu zure albobarran emaitza berriak zure bilaketarako eskuragarri dauden bakoitzean.
-Wizard.Subscription.rss.subtitle1=Idatzi edo itsasi URL-a ondoren:
-Wizard.Subscription.rss.subtitle2=Argitaratzaile zenbaitzuk RSS jarioak eskaintzen dituzte beren edukientzat.  Helbiditu  URL-a argitaratzailearen webgunean, kopiatu eta itsati URL-a gaineko eremuan, orduan klikatu Gorde.
-Wizard.Subscription.rss.subtitle3=Behin gordeta, zuzeneko harpidetzak jasoko dituzu zure albobarran zure RSS jarioen bidez emaitza berriak eskuragarri dauden bakoitzean
-Wizard.Subscription.subscribe.library=Zure Liburutegian dago
-Wizard.Subscription.subscribe.subscriptions=Antzeko Harpidetzak
-Wizard.Subscription.subscribe.library.empty=Ez dago harpidetza eskuragarririk?\n \nBilatu margo laranja dizdiratsuko harpidetza botoia Vuze HD Sarean.\n \n<A HREF="http://wiki.vuze.com/w/FAQ_Harpidetzak">Irakurri gehieago</A>
-message.confirm.delete.title=Baieztatu Ezabaketa
-message.confirm.delete.text=Zihur zaude '%1' ezabatzea nahi duzula?
-Subscription.menu.properties=Ezaugarriak...
-props.window.title='%1' -en Ezaugarriak
-subs.prop.enabled=Gaituta
-subs.prop.is_auto=Berez-jeistsi emaitza berriak
-subs.prop.last_scan=Eginiko azken eguneraketa
-subs.prop.last_result=Aurkituriko azken emaitz berriak
-subs.prop.last_error=Azken akatsa
-subs.prop.num_read=Irakurritako emaitz zenbatekoa
-subs.prop.num_unread=Irakurrigabeko emaitz zenbatekoa
-subs.prop.template=Eredua
-subs.prop.auth=Egiaztapena beharrezkoa
-externalLogin.auth_method_proxy=Erabili cookie atzipenbide hedatua. Hutsegiten badu, ezgaitu aukera eta saiatu berriro.
-externalLogin.wait=Orrialdea gertatzen, mesedez itxaron...
-TableColumn.menu.date_added.time=Erakutsi/Ezkutatu Denbora
-MyLibrary.bigView.header=Liburutegia
-sidebar.VuzeHDNetwork=Vuze HD Sarea
-subs.prop.next_scan=Hurrengo mihaketaren epemuga
-subs.prop.assoc=Elkartasunak
-subs.prop.version=Bertsioa
-subscriptions.column.new.info=Adierazi emaitza berri bat edo gehiago badaude
-subscriptions.column.name=Harpidetza
-subscriptions.column.nb-results=Emaitza Denak
-subscriptions.column.nb-new-results=Emaitza Berriak
-subscriptions.column.last-checked=Azken Egiaztapena
-subscriptions.view.title=Harpidetzak
-subs.prop.is_public=Publikoa
-subs.prop.high_version=Aurkitutako bertsio handiena
-Subscription.menu.upgrade=Gaitu Bertsio Handienera Eguneratzea
-metasearch.template.version.bad='%1' Bilaketa eredua ezin da ezarri Vuze eguneratu arte 
-metasearch.addtemplate.failed.title=Ezarpenak Huts egin du
-metasearch.addtemplate.failed.desc=Hutsegitea eredua ezartzerakoan: %1
-subscription.version.bad='%1' Harpidetza ezin da ezarri Vuze eguneratu arte
-statusbar.feedback=Bidali Iruzkina
-statusbar.feedback.tooltip=Klikatu hemen iruzkinak bidaltzeko
-sidebar.Activity=Oharrak
-v3.activity.button.watchall=Markatu Ikusitako Denak
-subscriptions.view.help.1=Gehitu Harpidetzak ikusten dituzun bakoitzean
-subscriptions.view.help.2=Eskuratu dohainik zuzeneko eguneraketak jeisteko eduki berriak eskuragarri dauden bakoitzean.  <A HREF="http://wiki.vuze.com/w/FAQ_Subscriptions">Learn More</A>.
-sidebar.sash.tooltip=F7 albobarra ezkutatu/erakutsi azkarrerako
-sidebar.expand.tooltip=Handitu Albokobarra
-sidebar.dropdown.tooltip=Erakutsi albokobarra menu heuskarrian
-subscript.all.subscribed=Eduki honetara harpideturik zaude
-subscript.some.subscribed=Eduki hau duten harpidetza batzuk dituzu\nKlikatu eskuragarri dauden beste batzuk ikusteko
-subscript.none.subscribed=Egin klik torrent honentzat eskuragarri dauden harpidetzak ikusteko
-v3.iconBar.up=Gora
-v3.iconBar.up.tooltip=Mugitu gora\nEduki saguaren botoia sakatuta gorainok mugitzeko
-v3.iconBar.down=Behera
-v3.iconBar.down.tooltip=Mugitu Behera\nEduki saguaren botoia sakatuta beherainok mugitzeko
-TableColumn.header.azsubs.ui.column.subs_link=Elkartasuna
-TableColumn.header.azsubs.ui.column.subs_link.info=Harpideekin elkartuta
-Button.deleteContent.fromLibrary=Kendu Liburutegitik
-Button.deleteContent.fromComputer=Ezabatu Ordenagailutik
-v3.deleteContent.message=\nEzabatzea nahi duzu '%1' zure ordenagailutik, edo zure Vuze Liburutegitik kentzea besterik ez?
-v3.MainWindow.menu.view.toolbartext=Tresnabarra Izena
-v3.MainWindow.menu.view.asSimpleList=Zerrenda Arrunta
-v3.MainWindow.menu.view.asAdvancedList=Zerrenda Aurreratua
-v3.MainWindow.menu.view.statusbar=Egoera Barra
-Subscription.menu.dirtyall=Markatu Emaitza Denak Ez Irakurrita Bezala
-configureWizard.file.message3=Vuze agiriak adieraziriko agiritegira jeitsi ditzake, agiritegi hori hemen hautatu dezakezu:
-v3.deleteContent.applyToAll=Ezarri eragiketa %1 hautaturiko sarrera guztiei.
-ConfigView.label.seeding.firstPriority.ignoreIdleHours=Ezer igo ez duten torrentak
-v3.MainWindow.menu.contentnetworks=HD &Sareak
-v3.MainWindow.menu.contentnetworks.about=HD Sareei Buruz
-Peers.column.as=SA/SAS
-Peers.column.as.info=Hartzailearen AS (Sistema Autonomoa) xehetasunak
-ConfigTransferAutoSpeed.auto.speed.neural=Neurala (Gudy Alpha)
-ConfigView.label.autoopen.downloadbars=Berez ireki Jeisketa Barrak
-ConfigView.label.autoopen=Berez Irekitzea
-ConfigView.label.autoopen.detailstab=Berez ireki Xehetasun Hegatsa
-ConfigView.label.autoopen.dl=Jeisten
-ConfigView.label.autoopen.cd=Emaritzan
-ConfigView.label.systray=Erabide Erretilua
-ConfigView.label.systray._mac=Egoera Barra Ikurra
-ConfigView.section.interface.legacy=Ondasuna
-v3.MainWindow.menu.contentnetworks.manage=&Kudeatu HD Sareak
-azbuddy.ui.table.loc_cat=Cats irteera
-azbuddy.ui.table.rem_cat=Kat sarrera
-azbuddy.ui.menu.cat=Kategoriak
-azbuddy.ui.menu.cat.share=Gaitu lagunekiko harpidetza
-azbuddy.ui.menu.cat.set=Sartu kategoria
-azbuddy.ui.menu.cat.set_msg=Kategoria zerrenda kakotxaz banandurik, edo 'Denak'
-azbuddy.ui.menu.cat_subs=Harpidetu
-subs.prop.update_period=Eguneratze epea
-azbuddy.enable_cat_pub=Kategoria publikoak dira zure lagunak izeneman daitezkeen GUZTIAK  (',' banandurik) 
-azbuddy.ui.table.read_cat=Kat irakurria
-TableColumn.header.#=Zbk.
-TableColumn.header.#.info=Lehentasun/Kokapen/Antolaketa Zenbakia
-TableColumn.header.category.info=Torrentari dagokion kategoria izena
-TableColumn.header.DateCompleted.info=Torrentaren jeisketa burutu zen eguna
-TableColumn.header.AzProduct.info=Torrentaren Sare edukia hemendik sortua
-TableColumn.header.health.info=Zure elkarketak torrenteen erlateldeko elkarketan duen osasuna
-TableColumn.header.maxuploads.info=Gehienez # hartzaile aldibereko igoeran
-TableColumn.header.name.info=Torrentaren izena
-TableColumn.header.unopened.info=Torrenta irakurria izan den adierazteko ikurra (irekita)
-TableColumn.header.savepath.info=Torrenteen datuentzako helbide agiritegia edo agiria
-TableColumn.header.SeedingRank.info=Torrentak zein gaizkiro behar duen emaritzea adierazten duen balio maila. Balio handiagoak behar handiagoa esanahi du
-TableColumn.header.shareRatio.info=Zenbat igo duzun (elkarbanatu) jeitsi duzunarekin alderaturik
-TableColumn.header.size.info=Diskako torrenteen edukien neurria
-TableColumn.header.azsubs.ui.column.subs.info=Antzeko torrentak dituzten jarioetara harpidetzea ahalbidetzen dizun botoia
-TableColumn.header.upspeed.info=Oraingo igoera abiadura
-TableColumn.header.downspeed.info=Oraingo jeisketa abiadura
-TableColumn.header.up.info=Orain arte beste erabiltzaileei bidalitako datu zenbatekoa
-TableColumn.header.down.info=Beste erabiltzaielengandik orain jasotzen ari zaren datu zenbatekoa
-TableColumn.header.ProgressETA.info=Egoera, Osaketa, UED, eta Jeisketa Abiadura zutabeak lerro-anitzeko zutabe batean batzen ditu
-TableColumn.header.eta.info=Torrenta jeitsi arteko ustezko denbora
-Pieces.column.#=Zenb.
-Pieces.column.#.info=Atal  Zenbakia
-Peers.column.%.info=Orain arte hartzaileak jeitsitako torrentaren ehunekoa
-TableColumn.header.download.info=Hartzailearengandik jasotzen ari zaren datuen zenbatekoa
-TableColumn.header.upload.info=Hartzaileei bidali diegun datu zenbatekoa
-TableColumn.header.downloadspeed.info=Hartzailearengandik jasotzen ari zaren abiaduraren neurria
-TableColumn.header.uploadspeed.info=Hartzaieei datuak bidaltzeko erabiltzen ari garen abiadura
-TableColumn.header.lan.info=Hartzailea zure LAN-ean dagoen adierazten duen ikurra
-TableColumn.header.downloadspeedoverall.info=Hartzailearen ustezko jeisketa neurria
-Peers.column.pieces.info=Hartzailearengandik jeitsi dituzun atalak adierazten dituen grafika barra
-TableColumn.header.TableColumnNameInfo=Zutabe Izena eta Azalpena
-TableColumn.header.TableColumnSample=Lagina
-TableColumn.header.TableColumnInfo=Zutabe Azalpena
-TableColumn.header.TableColumnChosenColumn=Hautatu Zutabea
-subs.prop.is_auto_ok=Berez-jeisketa baimenduta
-label.learnmore=Jakin Gehiago
-ColumnSetup.title=Zutabe Ezarpena '%1'
-ColumnSetup.explain=Esploratu ezkerreko zutabeak, eta gehitu eskuineko zutabe zerrenda ikusgarrira. Handiagotu edo txikiagotu zutabe eskuragarriak ezkerreko botoiko Iragazkia erabiliz. Arrastatu eta Askatu eta teklatu lasterbideak ere sostengatzen dira.
-ColumnSetup.chosencolumns=Zutabe Hautatuak
-ColumnSetup.proficiency=Ontasuna:
-ColumnSetup.categories=Kategoriak:
-ColumnSetup.filters=Iragazkiak
-ColumnSetup.availcolumns=Eskuragarri  %1 zutabe
-ColumnSetup.availcolumns.filteredby=Eskuragarri %1 zutabe iragazita %2
-devices.view.title=Gailuak
-device.renderer.view.title=Egileak
-device.mediaserver.view.title=Multimedia Zerbitzariak
-device.router.view.title=Bideratzaileak
-device.model.desc=Ereduaren azalpena
-device.model.name=Eredu izena
-device.model.num=Eredu zenbakia
-device.manu.desc=Egilea
-device.router.is_mapping=Berezgaitasunezko ataka mapaketa
-device.router.req_map=Mapaketa beharrezkoa
-device.router.configure=Itxuratu UPnP-a
-device.mediaserver.configure=Itxuratu Nire Multimedia Zerbitzaria
-device.hide=Ezkutatu Gailua
-device.show=Erakutsi Ezkutatu Gailuak
-device.search=Bilatu Gailuak
-device.router.con_type=Elkarketa: %1
-device.browse=Bilatu
-device.upnp.desc_url=Gailuaren Azalpena
-device.upnp.present_url=Gailu Administrazioa
-ConfigView.label.maxStalledSeeding=Gehienez 'hesituta' [0:mugagabea]
-ConfigView.section.Devices=Izenburua
-device.search.auto=Berezgaitasunez bilatu gailuak
-devices.sidebar.simple=Ikuspegi Arrunta
-devices.xcode.working_dir=Transkodeaketa eremua
-devices.xcode.prof_def=Berezko transkodeaketa profila
-devices.xcode.profs=Transkodeaketa profilak eskuragarri
-device.lastseen=Azken ikusaldia
-devices.contextmenu.xcode=Gailuarentzako Transkodeaketa
-devices.device=Gailua
-devices.profile=Profila
-General.percent=Ehuneko
-devices.installed=Ezarrita
-devices.comp.missing=Vuze sostengua ezarri gabe dago
-devices.state=Egoera
-MainWindow.menu.help.donate=Eman Dirulaguntza bat
-DonationWindow.noload.title=Egin Diru ekarpen bat
-DonationWindow.noload.text=Dirulaguntza leihoak huts egin du. Mesedez saiatu zaitez geroago.
-devices.xcode.only.show=Erakutsi Bakarrik Transkodeatutako Agiriak Gailuan
-device.quit.transcoding.title=Transkodeaketa garatzen
-device.quit.transcoding.text='%1' da uneko transkodeatzeilea '%2' eta da  %3% osatuta.\nOrain kentzen baduzu beharrezkoa izango da berrabiaraztea hurrengo saio hasieraren abiaratzean.
-download.removerules.unauthorised.data=\tKendu datuak
-device.config.xcode.maxbps=Geh KB/seg transkodeaketa neurria [0: mugagabea]
-device.xcode=Transkodeaketa
-device.xcode.always=Betik
-device.xcode.whenreq=Beharrezkoa denean
-device.xcode.never=Inoiz
-devices.copy.pending=Agiri kopia egiteke
-devices.sidebar.hide.rend.generic=Ezkutatu gailu generikoak
-v3.devicesview.infobar.text2=Eduki bat gailu batera transkodeatzeko, arrastatu edukia zure liburutegitik albobarrako gailura. Transkodeaketa osatuak ikusteko, klikatu banako gailuan eskuinean.
-iconBar.transcode=Gailua
-iconBar.transcode.tooltip=Egin gailurako baliagarri
-device.retry.copy=Birsaiatu Kopiatzen
-devices.copy.fail=Gailura kopiatzeak huts egin du
-devices.on.demand=Eskabidean
-devices.ready=Gertu
-TableColumn.header.trancode_qpos=Zenb.
-TableColumn.header.trancode_qpos.info=Kokapena Transkodeaketa Lerroan
-TableColumn.header.profile=Gailua
-TableColumn.header.profile.info=Erabilitako transkodeaketa profila
-TableColumn.header.copied=Kopiaturik
-TableColumn.header.device=Gailua
-TableColumn.header.device.info=Xede Gailua
-TableColumn.header.trancode_completion=Bihurketaren Garapena
-TableColumn.header.transcode_name=Izena
-TableColumn.header.transcode_status=Egoera
-# This is the beginning of the word "View".  It's right aligned under the icon bar item
-v3.iconBar.view.big=Iku
-v3.iconBar.view.big.tooltip=Ikusi Zerrenda Arrunt bezala
-# This is the end of the word "View".  It's left aligned under the icon bar item
-v3.iconBar.view.small=si
-v3.iconBar.view.small.tooltip=Ikusi Zerrenda Aurreratu bezala
-general.dont.ask.again=Ez galdetu berriro
-general.na.short=E/G
-v3.menu.device.exploreTranscodes=Erakutsi Agiriak
-v3.menu.device.exploreTranscodes._windows=Erakutsi Agiriak Explorer-ean
-v3.menu.device.exploreTranscodes._mac=Erakutsi Agiriak Finder-ean
-v3.menu.device.defaultprofile=Berezko Profila
-devices.button.installitunes=Ezarri iTunes Baterapena
-device.itunes.install=iTunes ezartzeko behar duzu
-device.itunes.start=iTunes abiatzea edo berez-abiatzea behar duzu
-device.itunes.install_problem=Badirudi arazo bat dagoela iTunes bateragarritasunarekin
-devices.downloading=Jeisten
-TableColumn.header.duration=Iraupena
-TableColumn.header.resolution=Bereizmena
-devices.xcode.autoStart=Berezgaitasunez Hazi Beharrezkoa Denean
-option.askeverytime=Galdetu Betik
-option.rememberthis=Gogoratu ezarpen hau
-devices.associate=Honekin elkartuta
-devices.associate.already=Jadanik elkartuta
-devices.always.cache=Transkodeatu-Gabeko Agirientzako Katxea
-devices.turnon.prepageload=Eginkizun hau abiatzeko, osagai gehigarri baten ezarpena beharrezkoa da.
-devices.turnon.itunes=iTunes-entzako sostegua barne (beharrezkoa Apple gailuentzat)
-devices.turnon.qos=Elkarbanatu izengabeko gailu estatistikak Vuzerekin
-devices.turnon.title=Piztu Gailu Sostengua
-devices.choose.device.title=Hautatu irakurgailu bat bideo honentzat:
-devices.choose.profile.title=Izenburua
-devices.choose.profile.info.text=Zure hautaketaren ondoren, Vuzek atzemango du bideo heuskarria hautaturiko irakurgailuan ikusi ahal den, eta gailu-bateragarri kopia bat sortu beharrezkoa bada.\n\nJarri hautatutako gailuaren gainean xehetasun gehiago ikusteko.
-devices.choose.profile.info.title.selected=%1 xehetasunak:
-devices.view.heading=Multimedia bihurgailua irakurgailuarentzat
-device.view.heading=Media   %1
-devices.choose.device.info.title=Gailu Mota
-devices.choose.device.info.text=Hurrengoan, agiriak arrastatu eta askatu arrunt bat gailura edo hautatu itzazu Albobarran.
-label.clickone=Klikatu bat
-Button.turnon=Gaitu
-ConfigView.section.interface.password=Sarhitza
-ConfigView.label.dm.dblclick=Klik bikoitza torrenten ikuspegietan:
-ConfigView.option.dm.dblclick.play=Irakurri Edukia
-ConfigView.option.dm.dblclick.details=Ireki Torrent Xehetasun Ikuspegia
-ConfigView.option.dm.dblclick.show=Erakutsi Agiria
-ConfigView.option.dm.dblclick.show._mac=Erakutsi Agiria(k) Finder-en
-ConfigView.option.dm.dblclick.show._windows=Erakutsi Agiria(k) Explorerren
-subscriptions.column.auto-download=Berez Jeisketa
-xcode.deletedata.title=Ezabatu Transkodeaketa Edukia
-xcode.deletedata.message=Zihur zaude behinbetirako ezabatu nahi duzula '%1' transkodeaketa kopia '%2'%3?
-xcode.deletedata.message.2=\n(hemen kopia bat egon daiteke oraindik '%1')
-v3.deviceview.infobar.line1=Arrastatu eta askatu bideoak zure Liburtegitik hautatzen duzun gailura.
-v3.deviceview.infobar.line2=Ikusi zure bideoak zure pantailetako edozeinetan - iPad, iPhone, iPod, TB
-v3.deviceview.infobar.line1.generic=Arrastatu eta askatu bideoak zure Liburutegitik %1 zure Albobarrara.
-v3.deviceview.infobar.line2.itunes=Bideoak zure iTunes Filmak agiritegian agertuko dira ikusteko gertu daudenean.
-v3.deviceview.infobar.line2.xbox=Jarioatu bideoak zure Xbox 360-ra joanez eta hautatuz Nire XBox -> Bideo Liburutegia -> Vuze.
-v3.deviceview.infobar.line2.ps3=Bideoak jariotu zure PS3-ra joanez eta hautatuz Bideoak -> Vuze.
-devices.copy_url=Kopiatu Jario URL-a Gakora
-devices.converting=Bihurtzen
-Button.reload=Birgertatu
-devices.auto.start=Berez-abiatzea
-Subscription.menu.setcookies=Ezarri Cookiak
-general.enter.cookies=Sartu Cookiak
-device.config.xcode.workdir=Berezko lan zuzenbidea transkodeatutako agirientzat
-MyTorrentsView.menu.clear_alloc_data=Garbitu Izendapen Egoera
-DiskManager.error.nospace=Diskako tokia ez da nahikoa
-DiskManager.error.nospace_fat32={DiskManager.error.nospace} - egiaztatu {wiki.fat32}
-wiki.fat32=http://wiki.vuze.com/w/FAT32_agir_neurri_muga
-ConfigView.section.file.rename.incomplete=Gehitu aurrehizkia osatugabeko agiriei
-subscriptions.config.auto=Berez-jeisketa
-subscriptions.config.autostartdls=Berezgaitasunez hasi jeisketak gehitutakoan (geldituta egoeran jartzearen alderantzizkoa da)
-subscriptions.config.autostart.min=Hasi bakarrik bada >= MB [0: mugagabea]
-subscriptions.config.autostart.max=Hasi bakarrik bada <= MB [0: mugagabea]
-dlg.corewait.title=Core-a Abiarazten
-dlg.corewait.text=Une Bat Mesedez...\n\nZure eskaera Vuzek abiarazpena burutu ondoren bideratuko da.
-library.core.wait=Une Bat Mesedez...\nVuze Bezeroa Abiatzen ari da
-ConfigView.label.StartUIBeforeCore=Hasi EI Core Abiarazpenaren aurretik
-general.add.friends=Gehitu lagun batzuk!
-general.all.friends=Lagun Guztiak
-friend.mod.subs=Eskuin-klikatzea harpidetzak aldatzeko
-TableColumn.header.class=Saila
-device.rss.group=Tokiko RSS Jarioa
-devices.xcode.rsspub=Argitaratu RSS jarioa
-device.rss.enable=Sortu RSS jarioa transkodeaketa edukitik -  honek edukia eskuragarri egiten du RSS jario irakurleentzat
-device.rss.port=RSS jario ataka
-device.rss.view=Egin klik RSS jarioa ikusteko
-device.rss.localonly=Sarbide ukatua ordenagailu honetara bakarrik
-devices.xcode.autoCopy=Berezgaitasunez Kopiatu Agiritegira
-devices.xcode.setcopyto=Ezarri Kopiaketa Agiritegia
-devices.xcode.setcopyto.title=Hautatu kopiaketa helbidea
-devices.copy.folder.auto=Berezgaitasunez kopiatu agiriak agiritegira
-devices.copy.folder.dest=Agiritegira kopiatu
-TableColumn.menu.maxuploads=Geh. Igoera Zenbaketakoa
-devices.xcode.mancopy=Eskuz Kopiatu Agiriak
-devices.xcode.show.cat=Kategoriatan Banandurik
-devices.cat.show=Erakutsi kategoriak
-devices.tivo.machine=TiVo makina izena
-devices.info.copypending=%1 Agiri Itxaroten Kopiatuak Izateko
-device.error.xcodefail=Transkodeaketa Hutsegitea
-device.error.copyfail=Agiri Batek Edo Gehiagok Huts Egin Du Agiritegira Kopiatzean
-device.error.copytonotset='Kopiatu Agiritegira' Ezarri Gabe
-device.error.copytomissing='Kopiatu Agiritegira' "%1" Ez da Aurkitu
-device.error.copytonowrite='Kopiatu Agiritegira' "%1" Ez Idazgarria
-device.error.copyfail2=Agiri Batek Edo Gehiagok Huts Egin Du Gailura Kopiatzean
-v3.deviceview.infobar.line2.tivo=Bideoak jariotu zure TiVo-ra joanez eta Vuze hautatuz zure Uneko Irakur Zerrendan.
-v3.deviceview.infobar.line2.psp=Bideoak zure PSP-ra kopiatu daitezke hau elkarketaturik dagoenean.
-devices.info.copypending2=%1 Agiri Itxaroten Kopiatuak Izateko, Elkarketatu Zure Gailua
-subscriptions.column.nb-subscribers=Harpidetuak
-subscriptions.column.category=Kategoria
-device.offlinedownloader.view.title=Lineaz-kanpoko Jeistzaileak
-device.xcode.group=Kodea
-device.od.group=Izenburua
-device.od.enable=Gaitu lineaz-kanpoko jeisketa gailuak
-device.odauto.enable=Berezgaitasunez kudeatu jeisketak
-device.odpt.enable=Torrent pribatuak barne
-devices.contextmenu.od=Lineaz-kanpo Jeisten
-devices.contextmenu.od.auto=<Berezgaitasunez>
-devices.contextmenu.od.enable=Gaitu
-devices.contextmenu.od.enabled=Gaiturik
-devices.od.view.heading=Lineaz-kanpoko jeisketarako jeisketa egitarautuak
-DevicesOD.column.od_name=Izena
-DevicesOD.column.od_status=Nire Aztarnaria
-DevicesOD.column.od_completion=Eskualdaketa Garapena
-DevicesOD.column.od_remaining=Gelditzen dena
-devices.od.xfering=Eskualdaketa
-devices.od.idle=Hutsik
-device.od.turnon.title=Piztu Lineaz-kanpoko Jeisketa Sostengua
-device.is.disabled=Gailua ezgaiturik dago
-device.configure=Itxuratu...
-device.od.error.notfound=Gailua lineaz-kanpo dagoela dirudi
-device.od.error.opfailstatus=Gailuak huts egin du komando hau prozesatzerakoan %1: egoera %2
-device.od.error.opfailexcep=Gailuak huts egin du komando hau prozesatzerakoan %1: salbuespena %2
-device.od.error.nospace=Ez da tokirik gelditzen gailuan edo ez dago kanpo batasunik elkarketaturik 
-device.od.space=Toki Eskuragarria
-ConfigView.section.style.forceSIValues=Behartu balioak erakutsiak izateko IEK balio bezala ondorengo helburuekin erabilitako erakusleihoa edozein izanda ere. (adib. 1MB = 1MiB = 1048576B)
-ConfigView.label.enableSystrayToolTip=Erakutsi jeisketa estatistikak azalean
-devices.activation=Gailu Eragitketa
-button.nothanks=Ez Mila esker
-devices.od.turnon.text1=Nabaritu dugu hona elkaketaturik zaudela %1.
-devices.od.turnon.text2=Nahi duzu %1 jarraitzea zure agiriak jeisten ordenagailua linez-kanpo dagoenean?
-devices.od.turnon.text3=Mesedez elkarketatu Diska Gogor bat %1 eginkizun hau abiatzeko.
-devices.od.turnon.learn=Jakin gehiago >
-devices.router=bideratzailea
-devices.od=Lineaz-kanpoko jeistzailea
-webui.pairingenable=Gaitu uztarpena plugin honentzat (azterketa aukerak gaituak izan daitezke uneko uztarpen xehetasunak ongi argitaratu direnean)
-webui.group.access=Sarbide Agintea
-ConfigView.section.Pairing=Uztarpena
-pairing.accesscode=Sarbide kodea
-pairing.ac.getnew=Izendatu sarbide kode berri bat
-pairing.ac.getnew.create=Sortu
-pairing.ipv4=IPv4 Helbide publikoa
-pairing.ipv6=IPv6 Helbide publikoa
-pairing.local.ipv4=Tokiko IPv4 helbidea
-pairing.local.ipv6=Tokiko IPv6 helbidea
-pairing.host=Hostalari izena (DNS izena)
-pairing.group.explicit=Ezaugarri Bereiziak
-pairing.explicit.enable=Gaitu
-pairing.explicit.info=Arrunt IP ezaugarriak ez dira adierazi beharrezkoak berezgaitasunez eratorriak izan daitezkeelako.\n'Hostalari' ezaugarria erabilia izan daiteke, adibidez, DynDNS kontu bat baduzu eta software bezero egoki bat zure IP dinamikoa zuzen izen-emanda gordetzeko.
-pairing.op.fail=Uztarpen Eragiketa Hutsegitea
-pairing.alloc.fail=Huts egin du sarbide kode berri bat izendatzerakoan\n%1
-pairing.enable=Gaitu Vuzeren uztarpena eta hurruneko aplikazio/interfazeak
-pairing.status.info=Egoera
-pairing.status.registered=Eguneraketa eginda (%1)
-pairing.status.pending=Eguneraketa burutuko da %1
-pairing.status.initialising=Abiarazten
-pairing.status.disabled=Ezgaiturik
-pairing.view.registered=Klikatu ikusteko uneko izenemate xehetasunak
-webui.pairing.info.n=Uztarpena ezgaiturik dago, ikusi Elkarketa->Uztarpena aukerak ezaugarri honen argibide gehiagorako
-webui.pairing.info.y=Uztarpena gaituta dago, ikusi Elkarketa ->Uztarpena aukerak xehetasun gehiagorako.
-webui.enable=Gaitu
-ConfigView.section.rss=Tokiko RSS etab.
-subscriptions.rss.enable=Sortu RSS Jarioak harpidetzetatik
-device.tivo.enable=Gaitu TiVo sostengua
-Button.removeAll=Kendu Denak
-label.rename=Berrizendatu  %1
-pairing.server.warning.title=Uztarpen Zerbitzuaren Mezua
-wizard.webseedseditor.edit.title=HTTP Emaritza Editorea
-wizard.webseedseditor.edit.newseed=Emaritza Berria
-MyTorrentsView.menu.editWebSeeds=Editatu &HTTP Emaritzak
-ClientStats.title.full=Bezero Estatistika
-ClientStats.column.count=Zenbaketa
-ClientStats.column.discarded=Baztertuta
-ClientStats.column.received=Jasota
-ClientStats.column.sent=Bidalita
-ClientStats.column.name=Izena
-MainWindow.menu.view.clientstats=Bezero Estatistikak
-Scrape.status.cached=Katxe zuritua
-network.ipv6.enable.support=Gaitu IPv6 sostengua (Java7-k beharrezkoa du Windowsekin)
-ConfigView.section.plugins.magnetplugin=Magnet URI Agintea
-MagnetPlugin.use.lookup.service=Erabili Vuzeren bigarren bilaketa zerbitzua DHT bidezko erakarpen bilaketak huts egiten badu
-MagnetPlugin.report.secondarylookup=Bigarren bilaketa zerbitzuarekin saiatzen
-MagnetPlugin.report.secondarylookup.ok=Bigarren bilaketa bat egin da
-MagnetPlugin.report.secondarylookup.fail=Bigarren bilaketak huts egin du: ez da iturbururik aurkitu
-TrackerView.title.short=Iturriak
-TrackerView.title.full=Iturriak
-Trackers.column.type=Mota
-Trackers.column.name=Xehetasunak
-Trackers.column.status=Egoera
-Trackers.column.seeds=Emaritzak
-Trackers.column.seeds.info=Emaritzak erletaldean
-Trackers.column.leechers=Izainak
-Trackers.column.leechers.info=Izainak erletaldean
-Trackers.column.peers=Hartzaileak
-Trackers.column.peers.info=Aztarnariak itzulitako hartzaileak
-Trackers.column.interval=Tartea
-Trackers.column.interval.info=Galdetze tartea segundutan: tartea (gutx. tartea)
-Trackers.column.updatein=Hurrena
-Trackers.column.updatein.info=Hurrengo eguneraketa arteko denbora
-tps.status.available=Eskuragarria
-tps.status.unavailable=Eskuraezina
-tps.type.dht=DHT (Banaturiko Hash Taula)
-tps.type.pex=PEX (Hartzaile Aldaketa)
-tps.lan.details=%1 tokiko bezero aurkituta
-tps.pex.details=Elkarketaturik %1 hartzailera (egiteke: hal=%2, beste=%3)
-tps.tracker.cache=Hartzaile katxea
-tps.tracker.cache1=Hartzaile katxea: erabilita=%1
-dht.status.disabled=Ezgaitu, eskuraezina den banaturiko datubasea
-tps.type.incoming=Barrurantz
-tps.incoming.details=Orain: TCP=%1, UDP=%2; Guztira inoiz=%3
-tps.type.plugin=Plugina
-group.auto=Berez
-ConfigView.label.autoadjust=Berezgaitasunez zehaztu elkarketa abiaduran ohinarrituriko ezarpen hau
-ConfigView.label.start=Abiarazi
-ConfigView.label.stop=Itzali
-ConfigView.label.start.onlogin=Hasi Vuze izena emanda
-ConfigView.label.stop.seedcomp=Emaritza burutu denean
-ConfigView.label.stop.downcomp=Jeisketa burutu denean
-ConfigView.label.stop.Nothing=Ez Egin Ezer
-ConfigView.label.stop.QuitVuze=Itzali Vuze
-ConfigView.label.stop.Sleep=Egoneratu Ordenagailua
-ConfigView.label.stop.Hibernate=Negutu Ordenagailua
-ConfigView.label.stop.Shutdown=Itzali Ordenagailua
-core.shutdown.alert=Ekintza '%1' sugiltzatua %2
-core.shutdown.dl=jeisketak burututa
-core.shutdown.se=emaritza burututa
-pairing.last.error=Azken akatsa
-MainWindow.menu.pairing=Hurruneko Uztarpena
-ConfigView.section.startstop=Hasi eta Gelditu
-ConfigView.label.pauseresume=Berez-pausatu/berrekin
-update.now.title=Eguneraketa Beharrezkoa
-update.now.desc=Vuzek eguneraketak egitea behar du migrazioa osatzeko.\n\nElkarrizketa hau itxi ondoren Windowsi eskatu ahal diozu eguneraketa aurrerabidea osatzeko.\n\nVuzeren berrabiaraztea EZ da beharrezkoa.
-ConfigView.label.jvm=Java Aukerak
-platform.jvmopt.sunonly=Sun JVM-ak bakarrik dira sostengatuta (oraingo hornitzailea=%1)
-platform.jvmopt.configerror=Ezin dira  JVM aukerak kudeatu itxurapen akats bat dagoelako
-platform.jvmopt.nolinkfile=Ezin dira JVM aukerak kudeatu migrazioa osatu gabe dagoelako
-platform.jvmopt.nolink=Ezin dira JVM aukerak kudeatu dagoen itxurapenak eragotzi egiten duelako
-platform.jvmopt.accesserror=Huts egin du JVM aukeratara sartzean: %1
-pairing.status.noservices=Ez dago hurruneko zerbitzurik gaituta
-webui.pairingtest=\tEgin klik uztarpen azterketarako
-webui.connectiontest=\tKlik elkarketa azterketzeko
-ConfigView.section.connection.pairing.url=http://wiki.vuze.com/w/UG_Aukerak#Uztarpena
-jvm.info=Vuzeren berrabiaraztea beharrezkoa da aukerak aldatu badira. *** Kontuz - JVM aukeren aldaketa okerrak Vuze ez abiatzea edo gaizki jardutea eragin dezake ***\n
-jvm.show.file=Tokiko JVM aukera agiria da: '%1' - Berreskurapenerako bakarrik editatu
-jvm.reset=Berrezarri JVM aukerak ezarpenaren berezkoetan
-jvm.error=Akats bat egon da JVM aukeretara sartzean: %1
-jvm.max.mem=Geh Piloaren oroimen neurria [zuri=berez,gutx=%1]
-jvm.min.mem=Gutx Piloaren oroimen neurria [zuri=berez,gutx=%1]
-ConfigView.section.invalid.value.title=Balio Okerra
-ConfigView.section.invalid.value=Balio okerra '%1' sartua '%2': %3
-Button.dismiss=Baztertu
-webui.pairing.autoauth=Gaitu berezko sarhitz babesa: erabiltzaile izena=vuze, sarhitza=<uztarpen sarbide kodea>
-ConfigView.label.stop.autoreset=Berezgaitasunez berrezarri ekintzak '%1' behin eraginduta
-remote.pairing.title=Hurruneko Uztarpena
-remote.pairing.subtitle=Hurruneko Vuzek edozin ordenagailu edo mobiletik Vuzeren agintea hartzeko aukera ematen dizu - edonoiz, edonondik.
-remote.pairing.instruction=Besterik gabe sartu beheko kodea edozein hurruneko gailuk emandako tartean. 
-remote.pairing.functions=<A HREF="clip">Kopiatu kodea gakora</A>   |   <A HREF="new">Eskuratu kode berri bat</A>
-remote.pairing.tip.title=Oharra: Hurruneko Vuze erabiltzeko bi bide erraz:
-remote.pairing.tip.text=Hurruneko Vuze Tresnabarra : Joan hona <A HREF="http://remote.vuze.com/download/">remote.vuze.com/download</A>\nVuze Remote Mobile: Joan hona <A HREF="http://remote.vuze.com/">remote.vuze.com</A> zure mobileko bilatzailean.
-remote.pairing.learnmore=<A HREF="/pairing_learnmore.start">Uztarpena SEG</A>
-remote.pairing.accesscode=Sarbide Kodea:
-remote.pairing.test.running=Hurruneko elkarketagarritasuna aztertzen...
-remote.pairing.test.success=Vuze hurrunetik eskuragarria da.
-remote.pairing.test.unavailable=Ene, ezin izan da zure hurruneko elkarketa zehaztu. <A HREF="retry"> Saiatu berriro</A>
-remote.pairing.test.fail=Vuze eskuraezina da zure tokiko saretik kanpo.  <A HREF="/pairing_error_faq.start">Jakin gehiago</A>
-update.fail.app.changed.title=Eguneratzeak Huts egin du
-update.fail.app.changed=Vuzek eguneratzea behar du baina aurrerabidea ezin daiteke berezgaitasunez osatu aplikazioaren izena aldatua izan delako '%1'.\n\nMesedez joan http://www.vuze.com/-era eta jeitsi azken ezartzailea.
-webui.port.override=Ataka ezeztatua: beharrezkoa da bakarrik NAT-aren itxurapenagaitik ataka publikoa eta barneko egoitza ezberdinak direnean.
-MainWindow.status.warning.tooltip=Egin klik xehetasunak ikusteko
-search.dialog.text=Sartu torrent berriak bilatzeko idazkia:
-core.not.available=Vuze oraindik abiatzen dago, mesedez saiatu berriro eginda dagoenean
-dlg.auth.title=Eragintza
-dlg.auth.enter.subtitle.try.1=Ia han.
-dlg.auth.enter.line.try.1=Sartu zure eragintza kodea behean eta osatu zure Vuze Pluserako berritzea.
-dlg.auth.enter.line.try.2=Barkatu, ezin izan dugu zure eragintza kodea balioztatu. Mesedez egiaztatu zenbakia eta saiatu zaitez berriro sartuz.
-dlg.auth.enter.prompt=Vuze Plus Eragiketa Kodea:
-Button.validate=Balioztatu
-Button.getstarted=Abiaturik
-Button.install=Ongi
-Button.goLibrary=Joan Liburutegira
-dlg.auth.success.subtitle=Zorionak!
-dlg.auth.success.line1=Mila esker Vuze Plus eguneratzeagaitik.
-dlg.auth.success.line2=Orain gai zara DVD grabaketa mugagabe bat egiteko, mihatu zure agiriak birusen aurka, eta jariotu jeisten ari zaren bideoak - dena iragarkirik gabe!
-dlg.auth.trial.success.line1=Vuze gertu dago DVD-ak sortzeko.
-dlg.auth.trial.success.subtitle=DVD Grabaketa Gertu
-dlg.auth.trial.success.info=Arrastatu bideo agiriak zure liburtegitik "Sortu DVD Berria"-ra. Jadanik bideo bat gehituta bazenuen osagaiak ezarri aurretik, mesedez gehitu ezazu berriro.
-dlg.auth.revoked=Eragintza Kodea Indargabetuta
-dlg.auth.revoked.line1=Zure Vuze Plus Eragintza Kodea indargabetua izan da. Mesedez klikatu behean argibide gehiago izateko.
-dlg.auth.revoked.link=<A HREF="info">Eragintza kodeen Indargabetzeari buruzko Argibideak</A>
-dlg.auth.denied=Eragintza Kodea Ukatuta
-dlg.auth.denied.line1=Zure Vuze Plus Eragintza Kodea ukatua izan da. Mesedez klikatu behean argibide gehiago izateko.
-dlg.auth.denied.link=<A HREF="info">Kode Eragintza Ukapenaren Argibideak</A>
-dlg.auth.cancelled=Eragiketa Kodea Ezeztaturik
-dlg.auth.cancelled.line1=Zure Vuze Plus Eragintza ezeztatua izan da.
-dlg.auth.cancelled.line2=Akats bat dela uste baduzu, mesedez jarri zaitez harremanetan sostenguarekin jasotako e-mail helbideen bidez.
-dlg.auth.enter.subtitle.try.2=Balioztapenak huts egin du
-dlg.auth.enter.link.try.2=<A HREF="link">Klikatu hemen</A> oraindik ez baduzu Vuze Plusen kopia bat erosita.
-dlg.auth.enter.link.try.1=Ez duzu eragintza kode bat? <A HREF="upgrade">Berritu orain</A>.
-dlg.auth.enter.expiry=Oraingo eragintza kodea iraungitzen da %1.
-dlg.auth.enter.revoked=Oraingo eragintza kodea indargabetua izan da.
-dlg.auth.enter.cancelled=Oraingo eragintza kodea ezeztatua izan da.
-dlg.auth.enter.denied=Oraingo eragintza kodea ukatua izan da.
-dlg.auth.validating.subtitle=Balioztatzen
-dlg.try.trial.title=Probatu DVD Grabaketa
-dlg.try.trial.text=Vuzek zure bideoetatik DVD grabaketak egin ahal izateko beharrezkoa den plugina ezartzea behar du.  Klikatu Piztu jarraitzeko.
-dlg.auth.tos=Irakurri ditut eta onartzen ditut <A HREF="tos">Zerbitzuaren Baldintzak.</A>
-dlg.auth.install.subtitle.plus=Vuze Plus ezartzen...
-dlg.auth.install.subtitle.trial=DVD Grabaketa ezartzen
-dlg.auth.install.progress=Ezartzen %1 osagai...
-dlg.auth.install.pct=%1% eginda
-mdi.entry.dvdburn=DVD Grabaketa
-mdi.entry.dvdburn.new=Sortu DVD Berria
-menu.register=Vuze Plus Eragiketa
-dlg.auth.trial.title=DVD Grabaketa Proba
-dlg.player.install.subtitle=Ezarpena
-dlg.player.install.description=Irakurketa osagai gehiagarria ezartzen...
-devices.xcode.remove.vetoed='%1' Transkodeaketa garatzen, jeisketa ezin da kendu osatu arte edo transkodeaketa 'Gailuak' orrialdetik ezeztatuta egon arte.
-Button.agree=Onartzen Dut
-dlg.auth.install.failed.title=Eragintza Hutsegitea
-dlg.auth.install.failed.text=Kodearen eragintza '%1' hutsegitea zerbitzari akats bategaitik.\n\nMesedez saitu zaitez eragintzarekin geroago (jakinarazitako akatsa zen '%2')
-device.status.online=Gailua online dago
-device.itunes.status.running=iTunes lanean dago
-device.itunes.status.notrunning=iTunes ez dago lanean
-device.itunes.status.notinstalled=iTunes ez dago ezarrita
-OpenTorrentWindow.mb.notTorrent.retry=Magnet Itxiera
-ConfigView.section.ipfilter.clear.on.reload=Garbitu iragazkiak birgertatzerakoan. Birgertatze aurrerabidean zehar IP-ak ez dira itxiko. Hautatugabe badago, itxigabeko berriek ez dute eraginik izango berrabiarazi arte.
-view.waiting.core=Ikustea eskuragarri egon daiteke Vuze Core gertatzen denean
-devices.profile.direct=Zuzen
-cat.autoxcode=Berez-Gailua
-ConfigView.section.tables=Aurkibideak
-ConfigView.section.style.useTree=Erakutsi Agiriak Liburutegia ikuspegietan  (Berrabiaraztea Beharrezkoa)
-ConfigView.section.mode.resetdefaults=Berrezarri ezarpenak berezko balioetan (berrabiaraztea gomendatzen da)
-resetconfig.warn.title=Baieztatu Eragiketa
-resetconfig.warn=Honek Vuzeren itxurapenean egin dituzun aldaketa guztiak galtzea eragingo du./nJarraitu itxurapen berrezarpenarekin?
-ConfigView.label.xfer.bias_up=Handitu jeisketa abiadurak igoera gaitasunera osatugabeko jeisketetan
-ConfigView.label.xfer.bias_slack=KB/s gutxienez gordeta jeisketa osatuentzat
-ConfigView.label.xfer.bias_no_limit=Bidea ezartzeko saiakera igoera muga orokor eraginkor bat ez dagoenean
-SpeedView.stats.upload=Lerrokatutako igoera datuak:
-SpeedView.stats.con=Elkarketa xehetasunak:
-SpeedView.stats.con_details=guztira=%1, itogabe=%2, lerrokatuta=%3, eragotzita=%4
-SpeedView.stats.upbias=Igoera bideak:
-dlg.install.mlab.subtitle=Ezartzen
-dlg.install.mlab.description=Mesedez itxaron abiadura azterketa osagia ezartzen den bitartean
-dial.up=Urrutizkin bidezko Internet elkarketa
-auto.mode=Berez (gomendatua)
-manual.mode=Eskuz
-configureWizard.transfer2.hint=Zure igoera muga hain goian edo hain behean ezartzeak jeisketan eragin dezake!
-configureWizard.transfer2.message=Bittorrent tit-for-tat hartuemanean ohinarrituta dago - orokorrean zure igoera azkarrena, zure jeisketa azkarrena - zein jeisketa azkarra, eta elkarbanatze maila on bat azkar lortzeko, behar duzu igoera abiadura on bat.\n\nHorrela ere, zure elkarketarako azkarregi igotzen baduzu, gainzamatu egin dezakezu errendimendu orokorra motelagoa izanez eta sarearen baliabideengaitik lehiatzen diren beste aplikazioei eraginez.\n\nHortaz garrantzitsua da zama muga o [...]
-configureWizard.transfer2.group=Modua
-configureWizard.transfer2.test.info=Hautatu azterketa oso bat egiteko abiadura
-configureWizard.transfer2.test=Abiatu Azterketa
-configureWizard.transfer2.mselect=Hautatu zure elkarketaren IGOTZE abiadura muga
-configureWizard.transfer2.mselect.info=xxx/<value> sarrerek nabaritzen dute igoera elkarketa abiadura <value> bit segunduko.\nAdibidez, zuk ADSL elkarketa bat baduzu 768 Kbps-ko jeistejario abiadurarekin eta 384 Kbps-ko igoerajarioarekin, hautatu 'xxx/384 kbit/seg'.\nBorobildu txikira hurbileneko baliora abiadura zehatza erakusten ez bada.
-configureWizard.transfer2.rate.unchanged=Oraingo ezarpenak erabiliak izan daitezke
-configureWizard.transfer2.rate.changed=Elkarketa muga=%1\nEzarritako muga izan daiteke %2 (geh. torrent eraginda =%3, geh. jeisten=%4)
-speedtest.wizard.select.title=Hautatu egin behar den abiadura azterketa mota
-speedtest.wizard.select.group=Azterketa Mota
-speedtest.wizard.select.general=Abiadura azterketa Orokorra (gomendatua)
-speedtest.wizard.select.bt=Bittorrent abiadura azterketa bereizia
-FileItem.storage.reorder=Berrantolatu
-ConfigView.label.piecereorder=Erantsi datuak jeitsitako agiriei eta berrantolatu atalak jeisketa garapen bezala
-ConfigView.label.piecereorderminmb=Berrantolatu bakarrik handiagoak diren agiriak (MB-tan)
-configureWizard.transfer2.current=<Oraingo Ezarpenak>
-ConfigView.section.style.extendedErase=Marraztu saretxo erroak eta bete eremu hutsak
-iconBar.stream=Irakurri Orain
-FilesView.menu.setpriority.numeric=Zenbakizkoa...
-FilesView.dialog.priority.title=Sartu Zenbaki Lehentasuna
-FilesView.dialog.priority.text=0=Arrunta, 1=Handia, 2=Oso Handia...
-beta.wizard.title=Beta Bertsioaren Ezarpena
-beta.wizard.intro.title=Bazkidetasun hautapena
-beta.wizard.info=Vuze beta programan bazkidetuz bezeroan aurrentasuna duzu argitalpenetan.\n\nHonek aukera ematen dizu argitalpen hauek probatzeko eta beren egokitzapenean laguntzeko - zure laguntza oso erabilgarria da guretzat!\n\nBaina beta bertsioak berez ezegonkorrak izan daitezke, horrela ere aukera hau hautatuz argitalpen nahiko egonkorretarako sarrera izango duzu. Nahi baduzu mesedez erabili 'Beta Eguneratze' plugina.
-beta.wizard.link=Egin klik hemen beta argitalpenen webgunera joateko
-beta.wizard.off=Pozik nago argitaraturiko bertsioekin, ez eskerrik asko!
-beta.wizard.on=Eguneratu azken beta bertsio egonkorrarekin mesedez.
-beta.wizard.version=Orain duzun bertsioa %1
-beta.wizard.disable.title=Berrezarpena Beharrezkoa
-beta.wizard.disable.text=Mila esker beta bertsioak probatzeagaitik!\n\nMesedez jeitsi eta ezarri argitaraturiko azken bertsioa beta programa baimentzeko
-beta.wizard.forum=Erabili Vuze eztabaidaguneak jarioak hartzeko akatsen berri izateko
-dlg.install.vuzexcode.subtitle=Multimedia Aztergailu osagaia ezartzen
-dlg.install.vuzexcode.description=Mesedez itxaron Media Aztergailuaren osagaia ezartzen den bitartean
-dlg.install.azemp.subtitle=Azpidatziak
-dlg.install.azemp.description=Azalpena
-TableColumn.header.filecount=Agiriak
-TableColumn.header.torrentspeed=Abiadura
-FileProgress.deleted=Ezabatuta
-FileProgress.stopped=Geldituta
-priority.high=Lehentasun Handia
-priority.normal=Lehentasun Arrunta
-label.wrap.text=Idatzia Erdiratu
-ScrapeInfoView.title=Lehen Aztarnaria
-Column.seedspeers.started=%1 %2-tik
-#connected to more seeds/peers than tracker reports
-library.all.header.p=%1 Gai: %2 Eraginda
-library.incomplete.header.p=%1 gai jeisten, %2 itxaroten jeisteko
-library.unopened.header.p=%1 gai
-library.all.header=%1 Gai: %2 Eraginda
-library.incomplete.header=%1 gai jeisten, %2 itxaroten jeisteko
-library.unopened.header=%1 gai
-ConfigView.section.style.status.show_rategraphs=Erakutsi bataz-besteko historia grafikak jeisketa/igoera idatzien azpian
-device.error.mountrequired="%1" Zure Gailua Tresnatzeko Beharrezkoa
-v3.deviceview.infobar.line2.android=Gaitu USB heuskarria zure urrutizkenean bideoak zuzen eskualdatzeo
-MyTorrents.column.ColumnProgressETA.compon=Osatuta %1
-Sidebar.beta.title=Beta Programa
-MainWindow.menu.beta.on=Gozatu Beta Programa...
-MainWindow.menu.beta.off=Utzi Beta Programa...
-Button.sendNow=Bidali Orain
-Button.sendManual=Eskuzko Bidalketa (sortu .zip)
-deletecontent.also.deletetorrent=Ezabatu .torrent agiria ere
-ConfigView.section.file.deletion.section=Agiri Ezabapena
-ConfigView.section.file.delete.torrent=Berez ezabatu .torrent agiriak edukia ezabatzerakoan
-ConfigView.section.file.delete.confirm=Baieztatu eduki ezabapena Tresnabarraren eta Ezabatu giltzaren bidez
-menu.delete.options=Kendu...
-menu.delete.options.keybinding=EZAB
-MainWindow.menu.view.beta=Beta Programa
-ConfigView.section.server.enableudpprobe=Gaitu UDP aztarnari zunda HTTP aztarnarientzat
-memmon.low.warning=Oroimena geldoki ari da lanean, duzu %1 gelditzen da %2.\nEgintza kaltetua izan daiteke eta azkenean Vuzek lan egiteari utzi diezaioke\nIkusi <a href="http://wiki.vuze.com/w/Java_VM_memory_usage">the Wiki</a> oroimen eskuragarria nola handitzeko xehetasunak.
-jvm.max.mem.current=Oraingo Pilo gehiena da:  %1
-jvm.max.direct.mem=Geh Zuzeneko oroimen neurria [zuri=berez,gutx=%1]
-jvm.max.direct.mem.info=Oharra: hau *Zuzen* oroimen ezarpena da, ohikoagoa da eguneratu behar izatea *Pilo* oroimena gainean
-jvm.options.summary=Oraingo aukeren laburpena:
-memmon.heap.auto.increase.warning=Piloaren oroimena handitu da %1. Vuze berrabiarazitakoan izango du eragina.
-device.showGeneric=Erakutsi Gailu Generikoak
-mdi.entry.games=Jokoak
-v3.MainWindow.menu.games=Jolasak
-Peers.column.Protocol=Hartuemana
-devices.copying=Gailura kopiatzen
-devices.cancel_xcode=Ezeztatu Bihurketa
-sidebar.header.transfers=Agiriak
-sidebar.header.discovery=Eduki Aurkikuntza
-sidebar.header.devices=Irakurketa Gailua
-sidebar.header.subscriptions=Harpidetzak
-sidebar.header.plugins=Pluginak eta Gehigarriak
-sidebar.header.dvd=DVD Grabaketa
-mdi.entry.about.devices=Garatzen
-mdi.entry.about.plugins=Pluginei Buruz
-mdi.entry.about.dvdburn=Hasteko
-ConfigView.section.file.tb.delete=Ezabatzerakoan Ezabatu edo Tresnabarraren bidez:
-ConfigView.tb.delete.ask=Galdetu
-ConfigView.tb.delete.content=Ezabatu galdetu gabe
-ConfigView.tb.delete.torrent=Liburutegitik bakarrik kendu
-search.export.all=Esportatu Bilaketa Eredu Guztiak...
-subscriptions.search.enable=Gaitu harpidetza emaitzetarako bilaketa (berrabiaraztea beharrezkoa)
-devices.cancel_xcode_del=Ezeztatu Bihurketa/Kentzea
-subscriptions.add.tooltip=Gehitu Harpidetza
-subscriptions.overview=Harpidetzen Gainikuspena
-configureWizard.nat.title=NAT / Zerbitzari Ataka Azterketa
-configureWizard.nat.message=Vuzerentzako irteera hoberena izateko osoki gomendatua da internetetik erabat eskuragarri egotea. Tresna honek aztertzea eta / edo sarrerako elkarketen onartzeko ataka aldatzea ahalbidetzen dizu.\n\n OHARRA: TCP 6880 ataka barnean gordea da eta ezin da erabili.
-configureWizard.nat.server.udp_listen_port=Sarrerako UDP Aditze Ataka
-v3.menu.device.defaultprofile.never=Inoiz ez Transkodeatu
-subscriptions.info.avail=Ez duzu harpidetzarik gehitu oraindik. %1 daude eskuragarri zure liburutegirako.
-subscriptions.dl_subs.enable=Jeitsi harpidetzak beste bezeroetatik beharrezkoa denean
-# Will be used for {library.name} in classic view
-library.name._classic=Nire Torrentak
-# Will be used for {library.name} in VuzeUI view
-library.name._vuze=Liburutegia
-ConfigView.section.style.units=Erakutsi Batasunak
-ConfigView.section.style.library=Izena
-ConfigView.section.style.CatInSidebar=Erakutsi Kategoriak Albobarran
-library.category.header=Kategoria '%1'
-device.import.title=Gailua Inportatu?
-device.import.desc=Zihur zaude '%1' gailua inportatu nahi duzula?
-device.import.dup.title=Bikoiztu Gailua
-device.import.dup.desc='%1' Gailua jadanik badago.
-stream.analysing.media=Hedabidea Aztertzen
-device.export.select.template.file=Esportatu Gailua
-dlg.stream.plus.subtext=Asperturik zure jeisketak osatu arte itxaroteaz? Ikusi itzazu lehenago Play Now-rekin, Vuze Plusen ezaugarri bat ahalbidetzen dizuna bideoa ikustea jeisketak jarraitzen duen bitartean.
-dlg.stream.plus.text=Berritu Vuze Plusera eta ikusi zure bideoak jeisten daudela.
-dlg.stream.plus.title=Berritu
-dlg.stream.plus.subtitle=Berritu
-dlg.stream.plus.renew.text=Berritu zure Vuze Plus harpidetza zure bideoak irakurtzen jarraitzeko jeitsita bezala.
-dlg.stream.plus.renew.title=Vuze Plus Berritzea
-dlg.stream.plus.renew.subtitle=Vuze Plus Berritzea
-Button.upgrade=Eguneratu
-Button.renew=Berritu
-iconBar.pstream=Jarioa
-stream.analysing.media.preview=Hedabideak Aztertzen (Aurreikuspen Modua)
-devices.restrict_access=Sarbidea Ukatu...
-devices.restrict_access.prompt=Sarbidea Ukatu '%1'
-devices.restrict_access.msg=IP zerrenda kakotxaz banandurik baimentzeko [edo ukatzeko aurrezenbakia bada -]
-TableColumn.header.TorrentStream=Jarioa
-TableColumn.TorrentStream.tooltip.disabled=Irakurri Orain-ek ez du agiri mota hau sostengatzen
-TableColumn.TorrentStream.tooltip.expand=Handitu lerroa Irakurri Orain ikusteko banakako agirientzat
-table.columns.reset=Berrezarri Zutabeak
-plus.notificaiton.ExpiringEntry.s=Zure Vuze Plus harpidetza epea %1 egun barru amaituko da: <A %2>Berritu Orain</A>
-plus.notificaiton.ExpiringEntry.p=Zure Vuze Plus harpidetza epea %1 egun barru amaituko da: <A %2>Berritu Orain</A>
-plus.notificaiton.ExpiredEntry.s=Zure Vuze Plus harpidetza epea amaitu da: <A %2>Berritu Orain</A>
-plus.notificaiton.OfflineExpiredEntry=Egun gehiegi egon zara lineaz-kanpo. Vuze Plus ez dago eraginda.
-rss.internal.test.url=Klikatu tokiko hasiera orrialdea ikusteko
-cat.rss.gen=Sortu tokiko RSS harpidetza
-dht.backup.only=DHT babeskopia bakarrik
-TableColumn.header.ipfilter=IP Iragazkia Gaituta
-MyTorrentsView.menu.ipf_enable=Gaitu IP Iragazkia
-devices.sidebar.mainheader.tooltip=%1 gailu ezkutatu dira orotarako edo etiketatugabe bezala.\n Erabili eskuin-klika aukerak agerian jartzeko
-device.mediaserver.remove_all=Kendu Multimedia Zerbitzari denak
-device.mediaserver.remove_all.title=Baieztatu Kentzea
-device.mediaserver.remove_all.desc=Zihur zaude multimedia Zerbitzari denak kentzea nahi dituzula?
-device.renderer.remove_all=Kendu Aurkezle denak
-device.renderer.remove_all.desc=Zihur zaude Aurkezle denak ETA beren transkodeaketak kentzea nahi dituzula?
-MyTorrentsView.menu.create_personal_share=Sortu Norbere Elkarbanatzea
-device.tag=Etiketa Gailua
-device.onlyShowTagged=Erakutsi Bakarrik Etiketaturiko Gailuak
-devices.sidebar.show.only.tagged=Erakutsi bakarrik etiketaturiko gailuak
-filter.header.matches1=(Bilaketa emaitzak: %1)
-filter.header.matches2=(Bilaketa emaitzak: %1, %2 jardunean)
-ipfilter.disabled=IP Iragazkiak Ezgaituta
-ipfilter.options=IP Iragazki Aukerak...
-TableColumn.header.eta_next=Hurrengo UED
-subscriptions.column.SubWizRank=Maila
-torrentdownload.error.dl_fail=Hutsegitea '%1' jeistean '%2'-tik: %3
-MainWindow.menu.speed_limits=Abiadura &Mugak
-MainWindow.menu.speed_limits.profile=Sartu Profil Izena
-MainWindow.menu.speed_limits.profiles=Profilak
-MainWindow.menu.speed_limits.load=Ezarri...
-MainWindow.menu.speed_limits.view=Ikusi...
-MainWindow.menu.speed_limits.delete=Ezabatu
-MainWindow.menu.speed_limits.view_current=Ikusi Oraingoa...
-MainWindow.menu.speed_limits.save_current=Gorde Oraingoa Honela...
-MainWindow.menu.speed_limits.reset=G&arbitu Oraingo Mugak
-MainWindow.menu.speed_limits.info.title=Abiadura Muga Xehetasunak
-MainWindow.menu.speed_limits.info.prof=Ezarpenak '%1' profilarentzat
-MainWindow.menu.speed_limits.info.curr=Oraingo ezarpenak
-MainWindow.menu.speed_limits.schedule=Egitaraupena...
-MainWindow.menu.speed_limits.schedule.title=Abiadura Muga Egitarupena
-MainWindow.menu.speed_limits.schedule.msg=Abiadura-muga profilak berezgaitasunez ezartzea agintzen duten oraingo arauak
-MainWindow.menu.speed_limits.schedule.err=Hurrengo akatsak jakinarazi dira, mesedez berreditatu zuzentzeko!
-torrent.decode.info.order.bad=Torrent Oharra: '%1' torrenta oker eginda dago eta hash okerra sortu dezake.\n\nIkusi <a href="http://wiki.vuze.com/w/Torrent_Info_Order_Bad">the Vuze Wiki</a> xehetasun gehiagorako eta ahalezko konponbide baterako
-MainWindow.menu.advanced_tools=A&urreratua
-torrent.fix.corrupt=Zuzendu Torrent Hondatua...
-torrent.fix.corrupt.browse=Ireki Torrenta
-torrent.fix.corrupt.result.title=Eragiketa Emaitza
-torrent.fix.corrupt.result.nothing=Torrenta baliozko bezala agertzen da!
-torrent.fix.corrupt.result.fixed=%1 torrent hash berria kalkulatuta.\nSakatu Ongi torrenta gordetzeko.
-FilesView.header=Izenburua
-MyTorrentsView.menu.sl_add_to_prof=Gehitu/Eguneratu Profila
-MyTorrentsView.menu.sl_remove_from_prof=Kendu Profiletik
-MagnetPlugin.use.md.download=Gaitu jeisketan-ohinarrituriko metadatu eskualdaketa
-MagnetPlugin.use.md.download.delay=\tatzerapena [seg]
-MagnetPlugin.report.md.starts=Metadatu jeisketa sortuta
-MagnetPlugin.report.md.progress=Metadatu jeisketa garapena: %1
-MagnetPlugin.report.md.done=Metadatu jeisketa osatuta
-MagnetPlugin.use.md.download.name=%1-rentzako metadatu jeisketa
-OpenTorrentWindow.addFiles.magnet=Gehitu &Magneta
-MainWindow.menu.file.open.uri=URL-a, Magneta edo Hasha...
-Button.open=Ireki
-plugin.init.load.failed=Akatsa '%1' plugina %2-tik gertatzerakoan
-plugin.init.load.failed.classmissing=Kendu plugina 'Tresnak->Pluginak->Kentze Laguntzailea' bidez eta berriro ezarri.
-v3.MainWindow.search.tooltip=Sartu zure bilaketa gaia, magnet lotura, hasha edo torrentaren URL-a eta sakatu sartu!
-device.playnow.group=Irakurri Orain
-device.playnow.buffer=Buffer neurria irakurketak hasi aurretik [seg]
-device.playnow.min_buffer=Buffer neurria eta birbufferreratze gertaerak [seg]
-ConfigView.section.backuprestore=Babeskopia eta Leheneratzea
-ConfigView.section.br.overview=Itxuratu Vuzerentzako zure babeskopia aukerak. Honek zure itxurapena berreskuratzea ahalbidetuko du, diska matxura bezalako akats larriren bat gertatuz gero.\n\nAhal da gidagailu fisiko banandu batera babeskopiatzea arrunt Vuze erabiltzen duzun batetik!\n\nOhartu eragiketa hauek Vuzeren itxurapen datuei bakarrik ezartzen zaizkiela, jeitsitako agirien babeskopiak zeuk kudeatu beharko dituzu.\n\n
-br.backup=Babeskopia
-br.backup.manual.info=Eskuzko babeskopia itxurapena
-br.backup.folder.title=Hautatu Babeskopia Agiritegia
-br.backup.folder.info=Hautatu babeskopia idatziko den agiritegia
-br.restore=Leheneratu
-br.restore.info=Leheneratu zure itxurapena babeskopia batetik
-br.restore.warning.title=Kontuz Itxurapen Galera!
-br.restore.warning.info=Zure itxurapena leheneratzeak orain duzuna erabat ordeztuko du.\nKontuan izan ekin aurretik hau babeskopiatzea!
-br.backup.progress=Babeskopia/Leheneratze Emaitzak
-br.restore.folder.title=Hautatu Leheneratze Agiritegia
-br.restore.folder.info=Hautatu aurreko babeskopia duen agiritegia
-br.backup.auto.enable=Gaitu berezgaitasunezko babeskopiak
-br.backup.auto.dir.select=Mesedez hautatu berezko babeskopia zuzenbidea
-br.backup.auto.everydays=Babeskopia maiztasuna [egunak]
-br.backup.auto.retain=Heusteko babeskopia zenbatekoa
-br.backup.auto.now=Aztertu berez-babeskopia orain
-br.test=Azterketa
-TorrentOptionsView.param.upload.priority=Igoera lehentasuna [0=berezkoa;1=lehentasunezkoa]
-cat.upload.priority=Igoera Lehentasuna
-cat.options=Oraingo Jeisketa Aukerak...
-br.backup.last.time=Azken babeskopia eginda:
-br.backup.last.error=Azken babeskopia akatsa:
-br.backup.setup.info=Mesedez kontuan izan berezgaitasunezko babeskopia itxurapena ezartzea.\nIkusi Tools->Options->Babeskopia eta  Leheneratzea
-MainWindow.about.internet.contributors=Laguntzaileak
-FilePriority.invalid.title=Lehentasun Baliogabea
-FilePriority.invalid.text=Balio baliogabea sartu da, osoa behar da: %1
-MyTorrentsView.menu.trackername.editprefs=Editatu Hobetsitako Aztarnari Erakuspena...
-trackername.prefs.title=Sartu Aztarnari-Anitzeko Torrententzako Hobetsitako Erakuspena
-trackername.prefs.message=Puntu eta kakotxaz banandutako aztarnari hostalari izenak\nAdibidez: a.b.com; c.d.net
-device.wiki=Wiki Iradokizunak eta Aholkuak...
-MagnetPlugin.report.ddb_disabled=DDB ezgaituta dago
-ConfigView.section.style.enableHeaderHeight=Norbere Idazburu Garaiera
-ConfigView.section.style.customDateFormat=Norbere Egun Heuskarria
-br.backup.notify=Jakinarazi babeskopia osatutakoan
-sidebar.LibraryCD.tooltip=Osatugabeko %1 torrent dago, hauetako %2 orain emaritzan dago/daude
-sidebar.LibraryDL.tooltip=Osatugabeko %1 torrent dago, hauetako %2 orain jeisten dago/daude
-ConfigView.section.style.launch=Abiarazi Laguntzaileak
-ConfigView.label.lh.info=Agiria berez agiriaren motaren arabera erregistraturiko aplikazioarekin abiarazten du.\nEzeztatu jokabide hau aplikazio zehatzak adieraziz emaniko agiri hedapenentzat [kakotxaz banadutako zerrenda].
-ConfigView.label.lh.ext=Hedapenak
-ConfigView.label.lh.prog=Aplikazioa
-pairing.config.icon.show=Erakutsi Hurruneko Vuzeren hurruneko ikurra egoera barran
-pairing.ui.icon.show=Erakutsi Ikurra
-pairing.ui.icon.tip=Vuze Hurruneko Elkarketa Egoera
-ManagerItem.moving=Mugitzen
-wizard.newtorrent.byo=Eraiki Zeurea
-wizard.newtorrent.byo.info=Askatu agiri edo/eta zuzenbide hautapena beheko eremuan torrenta eraikitzeko. Klik-bikoitza edo F2 izenak editatzeko.
-wizard.newtorrent.byo.help=Eraiki zeure torrenta hautaturiko agiri eta zuzenbideetatik
-wizard.newtorrent.byo.editname.title=Editatu Gai Izena
-wizard.newtorrent.byo.editname.text=Sartu gaiaren izena torrentean agertzen den bezala
-wizard.newtorrent.byo.addcontainer.title=Gehitu Edukiontzia
-wizard.newtorrent.byo.addcontainer.text=Sartu edukiontziaren izena torrentean agertzen den bezala
-label.torrent.structure=Torrent Egitura
-label.original.file=Jatorrizko Agiria
-button.add.container=Gehitu &Edukiontzia
-label.container.display=<edukiontzia>
-TableColumn.header.torrentrelpath=Torrent Helburua
-TableColumn.header.torrentrelpath.info=Agiriaren kokaleku erlatiboa torrentean
-TableColumn.header.torrentfileindex=Agiri Aurkibidea
-TableColumn.header.torrentfileindex.info=Agiriaren aurkibidea torrentean
-label.information=Argibideak
-ConfigView.section.tracker.client.enabletcp=Gaitu HTTP/HTTPS aztarnari bezero protokoloa
-label.udp_probe=UDP Proba
-MyTorrentsView.menu.eta.abs=Erakutsi UED denbora oso bat bezala
-ConfigView.label.sleep=Lotarazi
-ConfigView.label.sleep.info=Saihestu ordenagailua lotaratzea/etetea....
-ConfigView.label.sleep.download=Jeisten
-ConfigView.label.sleep.fpseed='Lehentasun Nagusia' emaritza eraginda dago
-TableColumn.header.fileext=Agiri Mota
-TableColumn.header.fileext.info=Jeisketaren lehen agiriaren agiri mota/hedapena 
-TableColumn.header.crc32.info=Agiriarentzako CRC-32 Egiaztapen-batura (osorik jeitsia izan behar da; klikatu kalkulatzeko)
-FilesView.crc32.calculate=Kalkulatu CRC-32 Checksuma(k)
-TableColumn.header.md5.info=Agiriarentzako MD5 hasha (osorik jeitsia izan behar da; klikatu kalkulatzeko)downloaded; click to calculate)
-FilesView.md5.calculate=Kalkulatu MD5 hasha(k)
-FilesView.click=Klikatu...
-FilesView.click.info=Klikatu kalkulatzeko, erabili eskuin-klika menua kalkulo anitzerako
-ConfigView.section.connection.port.rand.enable=Zorizkotu aditze atakak hasterakoan
-ConfigView.section.connection.port.rand.range=Ataka Maila [gutx-geh]
-ConfigView.section.connection.port.rand.together=TCP eta UDP-rako ataka bera
-ConfigView.label.start.inlrm=Hasi baliabide erabilpen gutxiko moduan (EI ezgaitua, sare eta oroimen erabilpen murriztua, etab.)
-wizard.multitracker.edit.text=Edit. Idazkia
-wizard.multitracker.edit.text.title=Sartu Aztarnari Xehetasunak
-wizard.multitracker.edit.text.msg=Sartu aztarnari bat lerroko. Banandu talde ezberdinak (mailak) lerro zuri batekin.
-MainWindow.menu.quick_view=Ikuspen Azkarra
-quick.view.no.files=Ez dago Agiri Egokigarririk
-ConfigView.label.quickviewexts=Agiri luzapen ikuspen azkarra
-ConfigView.label.quickviewmaxkb=Geh. agiri neurria [KB]
-MainWindow.menu.quick_view.msg='%1' agiriaren edukiak '%2' jeitsi gabe
-quick.view.scheduled.title=Egitaraupen Ikuspen Azkarra
-quick.view.scheduled.text=Hautaturiko agiriak lehentasuna du eta berez-irekiko da ikusteko osatutakoan.
-label.dont.show.again=Ez erakutsi mezu hau berriro
-label.plugin.options=Plugin Aukerak...
-TableColumn.header.torrent_created=Torrenta Sortuta
-TableColumn.header.torrent_created.info=Torrenta sortutako eguna, eskuragarri dagoenean
-pairing.ui.icon.tip.no.recent=Ez dago Elkarketa Berririk
-label.access.denied=Sarbidea Ukatuta
-label.date.format=Egun Heuskarria
-label.table.default=Taula Berez
-device.config.xcode.disable_sleep=Saihestu ordenagailuaren lotaratzea transkodeatzerakoan
-label.aggregate.info=Gehitutako Argibideak
-label.options.and.info=A&ukerak/Argibideak...
-ConfigView.section.tracker.client.exclude_lan=Baztertu LAN eskualdaketa datu estatistikak
-ConfigView.pluginlist.uninstallSelected=Kendu Hautatua
-devices.sidebar.onxcodecomplete=Transkodeaketa Osaketan
-devices.sidebar.oxc.nothing=Ezer ez
-devices.sidebar.oxc.closevuze=Utzi Vuze
-devices.sidebar.oxc.pm.1=Itzali
-devices.sidebar.oxc.pm.2=Neguratu
-devices.sidebar.oxc.pm.4=Lotaratu
-core.shutdown.xcode=transkodeaketa osatuta
-torrent.view.info=Ikusi Torrentaren Argibideak...
-torrent.view.info.title=Torrentaren argibideak
-network.check.ipbinding=Egiaztatu IP helbide/interfazea loturarik dagoen abiarazterakoan
-ConfigView.section.proxy.testsocks=Aztertu SOCKS-ak
-ConfigView.section.proxy.testsocks.title=SOCKS elkarketa aztertzen
-MyTorrentsView.menu.torrent.dl=Torrent Jeisketa Lotura
-custom.settings.import.title=Inportatu Itxurapen Ezarpenak?
-custom.settings.import=Zihur zaude '%1'-rako itxurapen ezarpenak inportatzea nahi dituzula?
-custom.settings.import.res.title=Itxurapen Inportazioa Osatuta
-custom.settings.import.res=Inportatuta %1 ezarpen.%2
-ConfigView.section.dns.info=Atal honek aukerazko DNS zerbitzariak adierazten ditu eta noiz erabili behar diren zehazten du.\n\nAdibidez, Googlek DNS zerbitzari bat ekiten du 8.8.8.8 helbidean (eta 8.8.4.4-an osagarri bezala)\n\nHau erabilgarria izan daiteke zure DNS hornitzaileak izenak ongi erabakitzen ez dituenean.\n
-ConfigView.section.dns.alts=Aukerazko DNS zerbitzariak [';' bananduta]
-ConfigView.section.dns.allow_socks=Erabili SOCKS proxy zerbitzariak hutsegiteak bilatzerakoan
-ConfigView.section.proxy.dns.info=Ikusi Elkarketa->DNS itxurapena DNS zerbitzari gehigarria adierazteko proxy erabakirako.
-label.proxy=Proxya
-label.inactive=Jardungabe
-label.in=Hemen
-label.out=Kanpoa
-label.more=Gehiago
-label.fails=Hutsegitea
-label.ago=duela
-label.con_prob=Elkarketa Arazoak
-proxy.info.title=Proxy Argibideak
-ConfigView.section.proxy.show_icon=Erakutsi SOCKS ikurra egoera eremuan gaituta dagoenean
-proxy.socks.ui.icon.tip=SOCKS egoera: %1\nKlik-bikoitza estatistikak.\nEskuin-klika aukerak
-proxy.socks.bad.incoming=Ez-Proxituriko barrurako elkarketak atzeman dira!
-wizard.newtorrent.showtorrent=Bilatu sortutako torrent agiria
-ConfigView.section.proxy.show_icon.flag.incoming=Erakutsi ez-tokiko, ez-SOCKS barrurako elkarketarik akats egoera bezala.
-label.connections=Elkarketak
-label.routing=Biderapena
-label.route=Bidea
-label.outgoing=Kanporantz
-network.admin.maybe.vpn.title=VPN Eraginda?
-network.admin.maybe.vpn.msg=Agertzen da Sare Birtual Pribatu (VPN) bat eraginda eduki dezakezula\n\n\t%1\n\nHorrela bada pribatutasuna handitu dezakezu honetara loturatuz - hautatu BAI egiteko.\n\nHorrela ez bada, edo zihur ez bazaude, hautatu EZ.\n\nIkusi <a href="http://wiki.vuze.com/w/Proxies_And_VPNs#VPN_Configuration">wikia</a> argibide gehiagorako.
-settings.updated.title=Ezarpenak Eguneratuta
-settings.updated.msg=Zure Vuze ezarpenak eguneratu dira.
-network.ipbinding.icon.show=Erakutsi egoera ikurra egoerabarran loturak eraginda daudenean
-label.no.connections=Elkarketarik gabe
-label.missing=Ez dago
-network.admin.binding.state=Loturak: %1, behartu=%2
-ConfigView.section.server.enablednsrecords=Gaitu istripuzko DDOS-ak hobetzeko erabilitako DNS aztarnari grabaketa kudeaketa.
-network.ipv4.prefer.stack=Hobetsi IPv4 piloa - erabili IPv4 eta IPv6 pilo bananduak bitariko-pilo aplikazioaren ordez
-ConfigView.section.file.subfolder.dnd=Mugitu jeisteko ez hautaturiko agiriak azpiagiritegira
-ConfigView.label.showuptime=Erakutsi Jardun-denbora
-label.uptime_coarse=Jardun-denbora%1%2
-devices.copy.device.auto=Berezgaitasunez kopiatu agiriak gailura
-devices.xcode.autoCopy.device=Berezgaitasunez Kopiatu Gailura
-devices.info.copypending3=%1 Agiri Itxaroten Kopiatuak Izateko - Gaitu Berez-Kopiatu Edo Hautatu Eskuzko Kopiatzea
-label.num_selected=%1 Hautaturik
-MainWindow.menu.transfers.pausetransfersfor=Pausatu...
-dialog.pause.for.period.title=Sartu Denbora Epea
-dialog.pause.for.period.text=Pausatu jeisketak eta berezgaitasunez berrekin ondoren [minutu]
-dialog.pause.for.period.text2=Berez-berrekin eragindakoak:  %1 gelditzen da...
-security.cert.auto.install=Berezgaitasunez ezarri SSL egiaztagiri ezezagunak ohartarazi gabe
-Trackers.column.last_update=Azken Eguneraketa
-pairing.group.srp=Uztarpen Seguru Aukerak
-pairing.srp.info=Hurreneko zenbait aplikaziok biak sostengatzen dituzte elkarketagarritasuna eta segurtasun handitzea 'hurruneko segurtasun sarhitza' protokoloa erabiliz eta, aukeran, proxy elkarketak elkarketagarritasuna handitzeko.\n\nBegiratu hurruneko aplikazioaren agiritza honetaz baliatu zaitezkeen ikusteko.
-pairing.srp.enable=Gaitu uztarpen segurua
-pairing.srp.state=Egoera: %1
-pairing.srp.setpw=Eguneratu zure uztarpen seguru sarhitza
-pairing.srp.setpw.doit=Aldatu
-pairing.srp.pw.req=Sarhitza beharrezkoa - ezerk ez du lan egingo hau gabe!
-pairing.srp.registering=Erregistratzen...
-security.crypto.pw.title=Sartu Sarhitza
-label.more.info.here=Klikatu argibide gehiagorako
-label.num_queued=%1 Lerrokatuta
-label.lang.upper.case=Erabili hizki larriak (larri-xehe tekla blokeaturik duten erabiltzaileen jarduera lerrokatzen laguntzen du)
-device.config.ms.maxlines=Multimedia zerbitzari bat bilatzerakoan erakusteko gehienezko sarrerak
-openTorrentWindow.mb.alreadyExists.merge=Nahi duzu aztarnari gehigarriak gehitzea jeisketa berritik dagoen batera?
-ConfigView.section.connection.group.webseed=Web/HTTP Emaritzak
-ConfigView.section.connection.webseed.act.on.avail=Eragin bakarrik Web/HTTP emaritzak jeisketarako eskuragarritasuna apala denean
-stats.snapshot.group=Berehalako-argazkia
-stats.longterm.group=Epe-Luzekoa
-stats.long.weekstart=Asteko zenbaketa hasten da:
-stats.long.monthstart=Hilabeteko zenbaketa hasten da:
-MainWindow.menu.speed_limits.wiki=Wiki Laguntza...
-ConfigView.label.info.in.window.title=Erakutsi oraingo neurriak etab. izenburu barran
-ConfigView.eta.abbreviated=U:
-ConfigView.label.hap=Mozorrotu jeisketa osaketa
-ConfigView.label.hap.tooltip=Ezkutatu osatutako atala
-ConfigView.label.hapds=Eten emaritzak mozorrotutako baina osatutako jeisketei
-Button.swarmit=Erletaldetu!
-Button.swarmit.tooltip=Bilatu neurri bereko agiriak Erletalde Aurkikuntzak erabiliz
-show.config.changes=Erakutsi Itxurapen Aldaketak...
-config.changes.title=Itxurapen Aldaketak
-DHTOpsView.title.full=BDB Grafika
-DHTOpsView.notAvailable=BDB Grafika ez dago eskuragarri
-DHTOpsView.idle=Langabe - jardueraren zain...
-ConfigView.section.style.TagInSidebar=Erakutsi Etiketak Albobarrran
-library.tag.header='%1' Etiketa
-label.tags=Etiketak
-label.add.tag=Gehitu Etiketa...
-label.show.tag=Erakutsi Etiketak
-TagAddWindow.message=Sartu etiketa izen berri bat
-TagAddWindow.title=Gehitu Etiketa Berria
-TagRenameWindow.message=Sartu izen berri bat etiketarentzat
-TagRenameWindow.title=Berrizendatu Etiketa
-tag.type.ds=Jeisketa Egoera
-tag.type.ds.qford=Jeisteko Lerrokatuta
-tag.type.ds.qfors=Emaritzarako Lerrokatuta
-tag.type.man=Eskuzkoa
-label.show.all=Erakutsi Denak
-tag.type.ipset=IP Ezarpena
-label.complete=Osatua
-label.incomplete=Osatugabea
-label.popups=Oharleihoak
-ConfigView.label.dl.add.req.attention=Argitu jeisketa eremua jeisketa bat gehitzen denean
-ColumnProgressETA.showETA=Erakutsi UED
-ColumnProgressETA.showSpeed=Erakutsi Abiadura
-ConfigView.label.queue.retainforce=Aldatu 'behartu hastera' jeisketak 'behartu emaritza'-ra osatutakoan
-TableColumn.header.CountryCode=HK
-TableColumn.header.CountryCode.info=Hartzailea kokaturik dagoen herrialde kodea (ISO 3166)
-TableColumn.header.Country=Herrialdea
-TableColumn.header.Country.info=Hartzailea kokaturik dagoen herrialdea
-TableColumn.header.CountryFlag=Ikurra
-TableColumn.header.CountryFlag.info=Hartzailearen Herrialde Ikurrina
-TableColumn.header.CountryFlagSmall=Ikurra
-TableColumn.header.CountryFlagSmall.info=Hartzailearen Herrialde Ikurrin Txikia
-tag.type.man.featcon=Eduki Ezaugarriak
-label.content=Edukia
-tag.share=Elkarbanatu Etiketapena Herkidegoarekin
-cat.share=Elkarbanatu Kategoriapena Herkidegoarekin
-tag.sharing.enable.title=Elkarbanatu Herkidegoarekin
-tag.sharing.enable.text=Nahi duzu zure etiketa/kategoria esleipenak izengabe herkidegoarekin elkarbanatzea?\n\nHonek beste erabiltzaileei beren jeisketak antolatzen lagunduko die.\n\nEskuin-klikatu etiketak/kategoriak albobarran banakako ezarpenak aldatzeko beharrezkoa bada.
-ConfigView.section.style.ShowTabsInTorrentView=Erakutsi azpi-hegatsak Liburutegi ikuspegietan ({ConfigView.section.security.restart.title})
-label.close.tab=Itxi Hegatsa
-TorrentDetailsView.filter=Bilatu agiriak...
-PeersView.menu.showdownload=Erakutsi Jeisketa &Xehetasunak
-window.update.noupdates.beta.text=Ez dago eguneraketa berririk eskuragarri zuretzat.\n\nAzken beta argitalpen egonkorra (%1) erabiltzen ari zara.\n\nIkusi <a href="http://dev.vuze.com/">Beta Programa gunea</a> argibide gehiagorako bietan argitalpen egonkorra eta ezegonkorra.
-tag.show.stats=Erakutsi Etiketa Estatistikak...
-TagStatsView.title.full=Etiketa Jarduera
-tag.stats.none.defined=Ez dago etiketarik mailatuta hautaturik/zehazturik!
-label.click.to.showhide=Klikatu erakutsi/ezkutatzeko
-label.click.to.change=Klikatu aldatzeko
-iconBar.play.tooltip=Irakurri hautaturiko edukia
-iconBar.startstop.tooltip=Hasi edo Gelditu hautaturiko gaiak
-label.click.to.restore=Klikatu Leheneratzeko
-label.dblclick.to.min=Klik-bikoitza Erretiluratzeko
-label.no.download.selected=Ez da jeisketarik hautatu
-ConfigView.section.style.showRankIcon=Erakutsi Antolaketa Ikurra
-label.color=Margoa
-TableColumn.header.tag.name=Etiketa Izena
-TableColumn.header.tag.count=Z Gai
-tags.view.heading=Etiketa Gainikuspena
-TableColumn.header.tag.xcode=Berez Transkodeatu
-label.toggle.new.marker=Aldatu Markatzaile Berria
-label.tag=Etiketa
-label.no.tag=Etiketarik Ez
-label.move.on.comp=Mugitu Osatutakoan
-label.set=Ezarri...
-label.browser=Nabaigatzailea
-label.various=Askotarikoa
-sidebar.show=Eraskutsi albo barra
-sidebar.top.level.gap=Idazburu lerro arteko tartea ({ConfigView.section.security.restart.title})
-device.config.autohide.old.devices=Berez-ezkutatu berriki ikusi ez diren gailuak [egun, 0: ezgaituta]
-device.autohide.alert=%1 gailua(k) ezkutatu egin d(ir)a online ez egoteagaitik %2 egunez.\nIkusi Tresnak->Aukerak->Gailuak jokabide hau itxuratzeko.\nEskuin-klikatu 'Gailu Irakurketa' albo barran ezkutuko gailuak erakusteko.
-ColumnRenameWindow.title=Berrizendatu Zutabea
-ColumnRenameWindow.message=Sartu zutabearentzako izen berria, hutsik berrezartzeko
-Button.set=Ezarri
-ConfigView.section.transfer.setmark=Ezarri/garbitu marka: eskualdaketa estatistika orokorrak une honetatik aurrera erakutsiko dira (Vuze ezarpen denbora garbituta badago) aurrerantzean
-SpeedView.stats.total.since=Guztira (noiztik: %1)
-TableColumn.header.peakup=Igoera Gailurra
-TableColumn.header.peakup.info=Igoera Abiadura Gailurra
-TableColumn.header.peakdown=Jeisketa Gailurra
-TableColumn.header.peakdown.info=Jeisketa Abiadura Gailurra
-smooth.config=(ikusi itxurapena leiho iraupena ezartzeko)
-TableColumn.header.smoothup=Igoera Lehundua
-TableColumn.header.smoothup.info=Igoera Abiadura Lehundua {smooth.config}
-TableColumn.header.smoothdown=Jeisketa Lehundua
-TableColumn.header.smoothdown.info=Jeiskea Abiadura Lehundua {smooth.config}
-TableColumn.header.smootheta=UED Lehundua
-TableColumn.header.smootheta.info=UED Abiadura Lehundua {smooth.config}
-stats.general.smooth_secs=Lehundutako bataz-besteko leiho neurria [seg]
-DownloadActivityView.legend.up_smooth=Igoera (Lehuna)
-DownloadActivityView.legend.down_smooth=Jeisketa (Lehuna)
-menu.min.share.ratio=Gutxienezko Elkarbanatze Maila (%1)...
-min.sr.window.message=Sartu gutxienezko elkarbanatze maila [0:ezgaituta]
-min.sr.window.title=Gutxinezko Elkarbanatze Maila
-sidebar.show.options=Erakutsi Aukerak Ikuspegia albobarra sarrera bat bezala leiho bereizi batean ordez
-TorrentOptionsView.param.reset.stats=Berrezarri torrent eskualdaketa estatistikak hutsean
-ConfigView.label.moveifsamedrive=Baina hau iturburua eta helmuga agiri sistema ezberdinetan daudenan bakarrik egiten du
-OpenTorrentWindow.pastearea=Sartu URL-a, magnet lotura, edo hasha:
-OpenTorrentWindow.checkbox.showAdvanced=Torrent bat gertatzen denean, utzidazu aukera aurreratuak ezartzen, agiri hautapena eta gordetze kokalekua bezalakoak.
-OpenTorrentFile.column.download=Jeitsi?
-OpenTorrentFile.column.#=Zenb.
-OpenTorrentOptions.title=Ireki Torrenta Aukerak
-OpenTorrentOptions.header.torrentinfo=Torrentaren Argibideak
-OpenTorrentOptions.header.filesInfo.all=%1 Agiri: %3
-OpenTorrentOptions.header.filesInfo.some=%1 -> %2 Agiritik: %3
-OpenTorrentOptions.header.saveto=Gordetze Kokalekua: %1
-OpenTorrentOptions.header.startoptions=Hasiera Aukerak: %1
-OpenTorrentOptions.header.peeroptions=Hartzaile eta Elkarketa Aukerak
-ConfigView.section.file.showopentorrentoptions=Torrent bat irekitzerakoan, erakutsi aukerak elkarrizketa:
-OpenTorrentOptions.show.label=Torrent bat irekitzerakoan, erakutsi elkarrizketa hau:
-OpenTorrentOptions.show.always=betik
-OpenTorrentOptions.show.never=inoiz ez berriro
-OpenTorrentOptions.show.many=agiri 1 baino gehiago dagoenean bakarrik
-Button.rename=Berrizendatu
-Button.retarget=Birxedetu
-label.download.file=Jeitsi Agiria
-menu.selectfilesinfolder=Hautatu %1-ko agiri guztiak
-label.current=Oraingoa
-label.limit=Muga
-label.showhide.tag=Erakutsi / Ezkutatu Etiketa(k)
-MagnetPlugin.current.port=URI Kudeatzaile Ataka
-ConfigView.label.show.win.on.add=Erakutsi leiho nagusia beste aplikazio batek jeisketa bat gehitzen duenean
-label.current_ip=Oraingo IP Helbidea:
-label.properties=Ezaugarriak
-label.trackers=Aztarnariak
-UpdateProperty.title=Eguneratu Ezaugarria
-UpdateProperty.list.message=Sartu balio berria %1-rako. Erabili ',' bat sarrera anitz banantzeko; utzi hutsik garbitzeko
-label.untagged=Etiketatugabe
-ConfigView.label.stop.RunScript=Ekin Eskripta
-ConfigView.label.stop.RunScriptAndClose=Ekin Eskripta + Itzali Vuze
-label.script.to.run=Ekiteko eskripta
-TableColumn.header.tag_colors=Etiketa Margoak
-label.init.save.loc=Hasierako Gordetze Kokalekua
-label.initial_tags=Hasierako Etiketak
-OpenTorrentFile.column.download.info=Jeitsi agiria torrentarekin\nErabili tarte barra hautapen anitz batera aldatzeko
-OpenTorrentWindow.mb.invaliddefsave.title=Gordetze Kokaleku Baliogabea
-OpenTorrentWindow.mb.invaliddefsave.text='%1' gordetze kokalekua baliogabea da.\n\nElkarrizketa hau isten duzunean aldatzeko galdetuko zaizu.\n\nBerezko gordetze kokalekua Tresnak->Aukerak->Agiriak bidez itxuratu daiteke.
-OpenTorrentWindow.set.savepath=Aldatu Goren Mailako Agiritegi Izena
-FilesView.menu.setpriority.numeric.auto=Zenbakizkoa -Berez Gutxiagoratzen
-Button.mark=Markatu
-Button.unmark=Desmarkatu
-TableColumn.header.sessionup=Saio Igoera
-TableColumn.header.sessionup.info=Saio hoentan igotako byteak
-TableColumn.header.sessiondown=Saio Jeitsiera
-TableColumn.header.sessiondown.info=Saio hoentan jeitsitako byteak
-OpenTorrentTorrent.column.#=Z
-ConfigView.section.file.showopentorrentoptions.sep=Erabili elkarrizketa bereizi bat torrent bakoitzeko
-label.n.will.be.downloaded=%1 jeitsiko da
-label.edit.trackers=Editatu Aztarnariak
-wizard.multitracker.template.title=Aztarnari Eredu Editatzailea
-label.replace=Ordeztu
-label.merge=Batu
-apply.selected.template=Ezarri Hautaturiko Eredua
-dialog.add.peers.title=Gehitu Hartzailea(k)
-dialog.add.peers.msg=Sartu hartzaile bakoitzaren helbidea honela <hostalaria>:<ataka> - kakotxaz bananduz sarrera anitz badira
-OpenTorrentWindow.fileList.changeDestination.all=Aldatu %1 Agiriren Helmuga Agiritegi Berdinera
-menu.max.share.ratio=Xede Elkarbanatze Maila (%1)...
-max.sr.window.message=Sartu xede elkarbanatze maila [0:ezgaituta]
-max.sr.window.title=Xede Elkarbanatze Maila
-ConfigView.section.mode.beginner.text1=Torrentak jeisteko behar duzun guztia - Bikaina erabiltzaile berriek bezeroaz eta torrentetaz ikasi dezaten.
-ConfigView.section.mode.intermediate.text1=Ezaugarri gehiago jeisketak agintzeko, hobetzeko eta ikusteko.
-ConfigView.section.mode.advanced.text1=Sarbide osoa ezarpen eta ezaugarri guztietara.
-label.tracker.templates=Aztarnari Ereduak
-label.reapply=Berriro-ezarri
-ConfigView.section.security.resetcerts=Berrezarri egiaztagiri biltegia (Vuze berrabiaraziko du)
-ConfigView.section.security.resetcerts.warning.title=Datu Galtze Oharra
-ConfigView.section.security.resetcerts.warning.msg=Zihur zaude egiaztagiri biltegia berrezartzea nahi duzula? Berez-sinaturiko egiaztagiri bat edo eskuz inportaturiko egiaztagiriak badituzu denak galduko dira!
-ConfigView.section.security.resetcerts.error.msg=Hutsegitea egiaztagiri biltegia berrezartzerakoan zergaiti ezezagun bategaitik, mesedez ikusi eztabaidaguneak laguntzarako
-# The remaining keys were not in MessagesBundle.properties
-rcm.search.provider=Erlataldea
-v3.MainWindow.menu.view.tabbar=Hegats Barra
-RCM.column.rc_level=Maila
-rcm.config.enabled=Gaitu
-RCM.column.rc_actions=Eragiketak
-RCM.column.rc_created=Sortua
-rcm.view.title=Izenburua
-RCM.column.rc_seeds=Emaleak
-rcm.config.max_level=Gehienezko maila
-rcm.rc_title.tt=Klikatu eduki hau bilatzeko
-ConfigView.section.Associations=Izenburua
-RCM.column.rc_lastseen=Azken Ikusialdia
-RCM.column.rc_new=Irekigabe
-rcm.rc_hash.tt=Klikatu eduki hau jeisteko
-RCMView.header=Idazburua
-RCM.column.rc_tracker=Aztarnaria
-rcm.config.max_results=Gehienezko emaitzak
-RCM.column.rc_rank=Maila
-RCM.column.rc_title=Izena
-rcm.rc_tracker.tt=Klikatu aztarnaria bilatzeko
-RCM.column.rc_size=Neurria
-ConfigView.label.alwaysShowLibraryHeader=Betik erakutsi buru/iragazki barra liburutegian
-RCM.column.rc_peers=Hartzaileak
-rcm.view.heading=Erlatalde Aurkituak
-rcm.contextmenu.lookupassoc=Izenburua
-RCM.column.rc_hash=Hasha
+v3.MainWindow.menu.contentnetworks=HD &Sareak
+window.uiswitcher.text=Mesedez hautatu zure beharretara hobekien egokitzen den erabiltzaile interfaze bat.
+plugin.sharing.download.remove.veto=Jeisketa hau elkarbanatze baliabide baten emaitza da.\nJeisketa kentzeko elkartutako elkarbanatzea kendu\: joan Tresnak->Nire Elkarbanatzeak.
+VivaldiView.notAvailable=Vivaldi Ikuspena ez dago eskuragarri
+ConfigView.section.file.showopentorrentoptions.sep=Erabili elkarrizketa bereizi bat torrent bakoitzeko
+sidebar.header.devices=Irakurketa Gailua
+mdi.entry.tagdiscovery={tag.discovery.view.heading}
+speedtest.wizard.run=Egin abiadura azterketa bat
+importTorrentWizard.title=Inportatu XML torrenta
+v3.deviceview.infobar.line2.itunes=Bideoak zure iTunes Filmak agiritegian agertuko dira ikusteko gertu daudenean.
+splash.loadingImages=Irudiak Gertatzen
+CacheView.writes.toFile=Agirira
+unix.script.new.text=Vuzeren abiarazte script berri bat eskuragarri dago, eta hemen gordea izan da '%1'.\n\nOso gomendagarria da Vuzetik irtetzea eta eskript honetara aldatzea ('%2').\n\nOso eraldatua baduzu zure Vuze abiarazte eskripta, mesedez ikusi <A HREF\="{unix.script.new.manual.url}">VuzeWiki\: Unix Script</A>.\n\nVuze distro batetik ezarri bazenuen (yum, apt-get, e.a), Gomendatzen da Vuze berrabiaraztea erabiliz  hemen dagoen pakete hau <AHREF\="http\://www.vuze.com/download/">Vu [...]
+ConfigView.section.style.showRankIcon=Erakutsi Antolaketa Ikurra
+columnChooser.title=Hautatu ikusiko diren zutabeak
+ConfigView.section.tracker.maxgettime=Geh. denbora GET jardunerako (seg) [0\: mugagabea]
+Button.moveDown=Mugitu &Behera
+ConfigView.label.hapds=Eten emaritzak mozorrotutako baina osatutako jeisketei
+tag.stats.none.defined=Ez dago etiketarik mailatuta hautaturik/zehazturik\!
+label.download.file=Jeitsi Agiria
+splash.unloadingTorrent=Torrenta Ezgertatzen
+ManagerItem.forced=Behartuta
+device.search=Bilatu Gailuak
+iconBar.play=Irakurri
+ConfigView.label.seeding.rankType.seed.options=Emaritza Zenbaketa Bakarrik Aukerak
+IPChecker.external.service.discoveryvip.name=Discoveryvip
+RCMView.header=Idazburua
+azbuddy.msglog.title=Lagun argibideak
+MyTorrentsView.menu.rename=Berrizendatu...
+stats.long.monthstart=Hilabeteko zenbaketa hasten da\:
+wizard.tracker.dht=Zentralizatu gabea (Vuzeko bezeroak bakarrik)
+subscript.import.fail.desc=Xehetasunak\: %1
+pairing.ui.icon.tip.no.recent=Ez dago Elkarketa Berririk
+platform.win32.baddll.FPServiceProvider=FoxyProxy Bideo Erabilgarria
+ConfigView.label.prioritizefirstpiece=Lehentasuna eman agiriko lehen eta azken atalari
+Wizard.Subscription.search.subtitle3=Zure harpidetza behin buruturik dagoenean, zuzeneko eguneratzeak jaso ditzakezu zure albobarran emaitza berriak zure bilaketarako eskuragarri dauden bakoitzean.
+Wizard.Subscription.search.subtitle2=Zer bilatu dezaket?
+Wizard.Subscription.search.subtitle1=Idatzi bilaketa bat zure harpidetza sortzen hasteko\:
+Peers.column.peer_id.info=Hartzailearen ID-a era irakurgarrian
+ConfigView.section.connection.peersource.Plugin=Pluginari gehitua
+settings.updated.title=Ezarpenak Eguneratuta
+Button.ignore=&Ezikusi
+ConfigTransferAutoSpeed.set.dht.ping=DHT Ping Ezarpena\:
+ConfigView.section.connection.advanced.mtu.tooltip=Sare bateko mugarri batean eskualdatu daitekeen pakete baten gehienezko neurria.\nVuzek MTU-40 (MSS) erabiltzen du paketeen-zamaerabilgarri igoera hoberenduenak egiteko.\nBalio gomendatuak\:\n  576 - Urritizkin elkarketatarako\n1492 - PPPoE bandazabaleko elkarketetarako\n1500 - Ethernet, DSL eta Kable bandazabaleko elkarketetarako.
+subscriptions.listwindow.subscribe=Harpidetu
+ConfigView.title.full._mac=Hobespenak
+remote.pairing.test.fail=Vuze eskuraezina da zure tokiko saretik kanpo.  <A HREF\="/pairing_error_faq.start">Jakin gehiago</A>
+ipCheckerWizard.chooseService=Hautatu IP Egiaztapen Zerbitzu bat zerrendatutako zerbitzuetatik
+ConfigView.label.downloading.autoReposition=Berkokatu lerrokatutako jeisketak jeisketa hoberentzeko
+iconBar.top=Goren
+configureWizard.welcome.title=Ongi etorri Vuzeren Itxurapen Laguntzailera
+ManagerItem.ready=Beste torrenta(k) itxaroten Lerrokatzeko
+PeersView.BlockView.NoAvail.Have=Zuk duzu; Hartzaileak ez
+label.information=Argibideak
+wizard.tracker.external=Erabili kanpoko aztarnaria
+MagnetPlugin.report.found=aurkituta %1
+MagnetPlugin.report.md.done=Metadatu jeisketa osatuta
+Plugin.trackerpeerauth.info=Plugin honek lan egiten du aztarnariekin hartzaileak erletaldeko kide baliagarriak direla egiaztatzeko 
+FilesView.click.info=Klikatu kalkulatzeko, erabili eskuin-klika menua kalkulo anitzerako
+MyTorrentsView.menu.editWebSeeds=Editatu &HTTP Emaritzak
+Button.yes=&Bai
+MyTorrents.items.UpSpeedLimit.disabled=Ez igo
+ConfigView.section.style.confirmationOnExit=Erakutsi berrespen leihoa irtetzerakoan
+label.num_selected=%1 Hautaturik
+PeersView.gain.info=Jeitsitako-igotako datu zenbatekoa
+MagnetURLHandler.report.percent=osaturik\: %1%
+MyTorrentsView.dialog.NumberError.title=Zenbaki Baliogabea edo Ezezaguna
+ConfigView.section.connection.webseed.act.on.avail=Eragin bakarrik Web/HTTP emaritzak jeisketarako eskuragarritasuna apala denean
+SpeedTestWizard.test.panel.abort.countdown=Azterketa hemen utzita\:
+remote.pairing.tip.title=Oharra\: Hurruneko Vuze erabiltzeko bi bide erraz\:
+Peers.column.as=SA/SAS
+PeersView.state.handshake=Eskuematearen zain
+TableColumn.header.mergeddata=Erletalde Batzea
+upnp.mapping.dataport=Sarrerako Hartzaile Datu Ataka
+crypto.alert.as.warning='%1' sarea ezaguna da joan-etorri eraketak ezartzeagaitik jeisketa egitea murriztuz. Garraio enkriptaketa berezgaitasunez gaitzen da - Hau ezgaitu/aldatu daiteke itxurapenaren bidez.
+network.admin.maybe.vpn.title=VPN Eraginda?
+ConfigView.section.security.restart.msg=Vuze orain berrabiarazi daiteke eragiketa osatzeko
+DevicesOD.column.od_status=Nire Aztarnaria
+library.incomplete.header=%1 gai jeisten, %2 itxaroten jeisteko
+TableColumn.menu.date_added.time=Erakutsi/Ezkutatu Denbora
+ConfigView.section.proxy.testsocks=Aztertu SOCKS-ak
+MainWindow.menu.file.export=E&sportatu XML Torrenta...
+splash.loadingTorrents=Torrentak Gertatzen
+Button.removeAll=Kendu Denak
+devices.copying=Gailura kopiatzen
+tags.view.infobar.text2=Ikusi eta esleitu beste erabiltzaile batzuek esleitutako etiketak Etiketa Aurkikuntza ikuspegiarekin, Ikusi menuan dagoena.
+sidebar.expand.tooltip=Handitu Albokobarra
+tags.view.infobar.text1=Aurkitu Etiketak
+ConfigView.label.stop.RunScriptAndClose=Ekin Eskripta + Itzali Vuze
+v3.MainWindow.view.wait=Ikuspena abiarazten, mesedez itxaron
+openUrl.title=Ireki Kokalekua
+Torrent.create.progress.piececount=Atal zenbatekoa\: 
+ConfigView.section.startstop=Hasi eta Gelditu
+OpenTorrentFile.column.download=Jeitsi?
+authenticator.location=Helbidea
+upnp.alertothermappings=Beste ordenagailuetako ataken berri eman
+ConfigView.section.ipfilter.peerblocking.group=Hartzaile Itxipena
+TableColumn.header.tag.upload_priority={cat.upload.priority}
+SystemTray.menu.startalltransfers=Hasi Eskualdaketa Denak
+health.explain.error=Arazo bat dago torrent honekin. Ikusi Egoera zutabea, edo ikurreko akats argibidea.
+ConfigView.section.Devices=Izenburua
+SpeedView.stats.estimatechoke=Irizpena (itopena)
+MainWindow.dht.status.unreachable=DHT-a Suhesiturik
+Views.plugins.UPnP.title.tooltip=Plug and Play Unibertsala
+dlg.stream.plus.subtext=Asperturik zure jeisketak osatu arte itxaroteaz? Ikusi itzazu lehenago Play Now-rekin, Vuze Plusen ezaugarri bat ahalbidetzen dizuna bideoa ikustea jeisketak jarraitzen duen bitartean.
+MainWindow.menu.view.mytorrents=&Liburutegia
+Wizard.Subscription.subscribe.library=Zure Liburutegian dago
+splash.initializeCore=Core-a abiarazten
+ConfigView.section.transfer.autospeed=Berez-Abiadura (klasikoa)
+iconBar.transcode=Gailua
+ConfigView.section.file.truncate.too.large=Moztu handiegiak diren agiriak
+GeneralView.label.size=Neurria\:
+ConfigView.copy.to.clipboard.tooltip=Kopiatu gakoan
+azbuddy.ui.table.name=Izena
+ConfigView.section.security.resetcerts.warning.title=Datu Galtze Oharra
+SpeedView.stats.maxPing=Geh. Ping-a\:
+TableColumn.header.writerate.info=Agiri Idazketa Neurria
+MainWindow.menu.file.folder.keybinding=Meta+Shift+0
+# The remaining keys were not in MessagesBundle.properties
+rcm.search.provider=Erlataldea
+Subscription.menu.forcecheck=Eguneratu Orain
+ConfigView.text.minutes=minutu
+MainWindow.menu.view.mytracker=Nire &Aztarnaria
+wizard.choosefile=Hautatu agiria
+Button.preview=Aurreikuspena
+menu.min.share.ratio=Gutxienezko Elkarbanatze Maila (%1)...
+MyTorrents.column.ColumnQuality=Ontasuna
+SpeedTestWizard.finish.panel.enabled=gaiturik
+DHTTransport.report.request_all=eskabidetzen eskualdaketa osoa %1
+ConfigView.label.seeding.preferLargerSwarms=Torrentak lerrun bera dutenean, nahiago izan erletalde handiak
+fileDownloadWindow.state_initializing=Abiarazten
+ConfigView.label.ircwiki=Mesedez irakurri http\://azureuswiki.com/index.php/Rules_for_IRC
+azbuddy.dchat.shared.tooltip=Elkarbanatuak esanahi du goitizen berdina erabiltzen dela berez kanal publiko guztietan\nKanal publikoak eta Izengabeak berezko ezarpen bananduak dituzte.
+LoggerView.loggingDisabled=Saio hastea ez dago gaituta.
+FilesView.%=% 
+subs.ext.view.launch.info=Sakatu botoi hau nabigatzaile bat abiarazteko
+MainWindow.dialog.share.sharedircontents.recursive=Jarraia
+Button.deleteContent.fromComputer=Ezabatu Ordenagailutik
+MainWindow.menu.help.checkupdate=Bilatu Eguneraketak...
+Trackers.column.name=Xehetasunak
+health.explain.yellow=Esanahi du aztarnaria ongi dagoela, hartzaileetara elkarketaturik zaudela, baina ez duzula hurruneko elkarketarik\nZure torrentak etengabe egoera orian badaude, agian NAT arazo bat duzu
+dht.portdefault=Erabili berezko ataka
+Button.send=Bidali
+FilesView.mode=Modua
+PeerManager.status.finished=Amaitua
+MyTorrentsView.dialog.setSpeed.title=Ezarri %1 abiadura
+MyTorrentsView.header=Torrent Osatugabeak
+MagnetPlugin.report.dead=%1 hilda
+azbuddy.ui.menu.ping=Ping (INT. Pak. Eskuzt.)
+devices.od.turnon.text3=Mesedez elkarketatu Diska Gogor bat %1 eginkizun hau abiatzeko.
+devices.od.turnon.text2=Nahi duzu %1 jarraitzea zure agiriak jeisten ordenagailua linez-kanpo dagoenean?
+pairing.srp.enable=Gaitu uztarpen segurua
+devices.od.turnon.text1=Nabaritu dugu hona elkaketaturik zaudela %1.
+ConfigView.section.tracker.processinglimits=Mugak prozesatzen
+ConfigView.section.transfer.autospeed.forcemin=%1 igoera abiadura behartuta ohinbideratze elkarketan
+popup.previous=< (%1)
+LocaleUtil.column.encoding=Kodeaketa
+MainWindow.menu.transfers.startalltransfers=&Hasi Denak
+upnp.alert.mappingfailed=UPnP\: Izendapenak '%1' huts egin du
+FileView.BlockView.Active=Jardunean
+authenticator.user=Erabiltzaile izena
+label.torrent.structure=Torrent Egitura
+Button.markSelected=Markatu Hautatua
+sidebar.show.options=Erakutsi Aukerak Ikuspegia albobarra sarrera bat bezala leiho bereizi batean ordez
+subscript.add.upgrade.title=Harpidetza Berritu?
+window.uiswitcher.title=Vuze EI Hautatzailea
+MyTorrentsView.menu.category.delete=&Ezabatu Kategoria
+ConfigView.section.plugins=Pluginak
+v3.MainWindow.menu.file.closewindow.keybinding=Meta+W
+DownloadManager.error.filenotfound=Agiria Ez da Aurkitu
+TableColumn.header.copied=Kopiaturik
+ConfigView.section.security.resetkey.warning.title=Datu Galera Kontuz
+devices.contextmenu.xcode=Gailuarentzako Transkodeaketa
+label.table.default=Taula Berez
+wizard.notimplemented=Garatu gabea
+ConfigView.label.seeding.autoStart0Peers=Berez Hasi 0 hartzaile duten osaturiko torrent denak
+OpenTorrentOptions.header.saveto=Gordetze Kokalekua\: %1
+Torrent.create.progress.ignoringfile=Agiria ezikuste
+label.keep.alive=Heutsi Bizirik
+config.external.browser.switch.subs=Harpidetzak
+TableColumn.header.torrentfileindex=Agiri Aurkibidea
+devices.installed=Ezarrita
+br.backup.auto.enable=Gaitu berezgaitasunezko babeskopiak
+TrackerAvail.column.name={Trackers.column.name}
+device.router.req_map=Mapaketa beharrezkoa
+ConfigView.section.tracker.ip=Aztarnariaren kanpoko IP helbidea
+azbuddy.enable_chat_notif=Gaitu eztabaidagune oharrak
+label.container.display=<edukiontzia>
+TableColumn.header.swarm_average_completion.info=Erletaldeko hartzaileen osaketa ehunekoaren bataz-bestekoa
+dialog.uiswitcher.restart.title=EI Aldatzailea\: Vuze Berrabiaraztea Beharrezkoa
+ConfigView.label.transferbar.remember_location=Gogoratu eskualdaketa barraren azken kokapena
+ConfigView.label.show.win.on.add=Erakutsi leiho nagusia beste aplikazio batek jeisketa bat gehitzen duenean
+wizard.multitracker.group=Aztarnari Taldea
+dlg.auth.enter.line.try.2=Barkatu, ezin izan dugu zure eragintza kodea balioztatu. Mesedez egiaztatu zenbakia eta saiatu zaitez berriro sartuz.
+RCM.column.rc_actions=Eragiketak
+dlg.auth.enter.line.try.1=Sartu zure eragintza kodea behean eta osatu zure Vuze Pluserako berritzea.
+SpeedView.stats.upload_details=%1
+device.status.online=Gailua online dago
+FileItem.write=Idatzi
+label.limit=Muga
+PiecesView.DistributionView.RarestAvl=Atal Arraroak\: %1 (Eskur\:%2)
+PeersView.BlockView.Transfer=Eskualdatzen
+LoggerView.filter.uncheckAll=Ez Hautatu Kategoria Guztiak
+MyTorrentsView.menu.manual.per_torrent=Eskuz (torrenteko)
+MainWindow.menu.file.open.torrentforseeding=Torrent Agiria... (Emaritzarako)
+dialog.associations.title=Elkartze Egiaztapena
+ConfigView.label.jvm=Java Aukerak
+ConfigView.label.playdownloadspeech=Hitz egin jeisketa amaitutakoan
+dlg.auth.install.subtitle.trial=DVD Grabaketa ezartzen
+configureWizard.transfer.title=Eskualdaketa eta Elkarketa ezarpenak
+upnp.ignorebaddevices=Baztertu zuzen erantzuten ez duten gailuak
+label.rerequest.blocks=Ber-eskabidetutako blokeak
+ConfigView.section.ipfilter.remove=Kendu
+OpenTorrentOptions.header.startoptions=Hasiera Aukerak\: %1
+Formats.units.Tibit=Tibit
+window.networkselection.description=Torrenta \:
+configureWizard.transfer.connection=Linea
+PeersView.Messaging.info=Zein mezularitza sistema erabiltzen ari zaren adierazten du.
+general.all.friends=Lagun Guztiak
+IrcClient.joining=Bategiten
+subscriptions.dl_subs.enable=Jeitsi harpidetzak beste bezeroetatik beharrezkoa denean
+ConfigView.section.connection.encryption.encrypt.info=Enkriptaketa gaituta badago ezingo duzu bezero bateraezinekin elkarketarik egin ordezko aukerak gaitu ezean
+ConfigView.section.logging.log2type=Akats
+TableColumn.header.sessionup.info=Saio hoentan igotako byteak
+label.tags=Etiketak
+azneti2phelper.install=Ezarri I2P Plugina
+SpeedTestWizard.finish.panel.auto.speed.seeding=BerezAbiadura emaritzan da\:
+ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Kopia oso 1 X hartzaileko dela saiatuz, hartzaile zenbateko handia duten torrenteen lerruna murrizten duzu.\nZihurrena da, hartzaile zenbateko handiena duten torrentak dutela ere joan-etorri handiena.\nHonek ez du aldatzen erakutsitako 'emaritzen Z' bat ere.
+ConfigView.section.dns.info=Atal honek aukerazko DNS zerbitzariak adierazten ditu eta noiz erabili behar diren zehazten du.\n\nAdibidez, Googlek DNS zerbitzari bat ekiten du 8.8.8.8 helbidean (eta 8.8.4.4-an osagarri bezala)\n\nHau erabilgarria izan daiteke zure DNS hornitzaileak izenak ongi erabakitzen ez dituenean.\n
+TableColumn.header.DateCompleted=Eguna
+dht.backup.only=DHT babeskopia bakarrik
+ConfigView.section.proxy.check.on.start=Egiaztatu proxyaren egoera hasterakoan
+TableColumn.header.date_completed=Osaturik
+UIDebugGenerator.messageask.text=Mesedez sartuzazu jakinarazten ari zaren akatsaren azalpen bat
+Button.deleteContent.fromLibrary=Kendu Liburutegitik
+ConfigView.section.connection.peersource.Tracker=Aztarnaritik
+iconBar.queue=Hasi
+CacheView.reads.avgsize=Neurri Bataz-bestekoa
+ConfigView.section.file.perf.cache.enable.read=Egin irakurri-aurrera diskaren irakurketak gutxitzeko igotzen ari zarenean
+SpeedTestWizard.set.upload.panel.explain=Hemen ezarritako mugak Vuzeren BerezAbiadura algoritmorako erabiltzen dira. Ezarri eskualdaketa mugak eta segurtasun mugak.\n\nKontuan izan bide abiadurak maiz "bit segunduko" neurrian ematen direla - horrela ere behean erakusten diren balioak "kilobyte segunduko" neurrian ematen dira.
+wizard.maketorrent.piececount=Atal Zenbatekoa
+change.url.msg.desc=Honek harpidetza berri bat sortu eta dagoena berrizendatuko du
+CacheView.reads.title=S/I Irakurriak
+ConfigView.section.style.inactiveUpdate=Eguneratu leiho nagusia EIG-aren Z eguneratzetik behin, leiho eragilea ez denean 
+v3.iconBar.up=Gora
+v3.mb.PlayFileNotFound.text=Hemengo agiriak '%1' ezabaturik edo galduta daude.
+plus.notificaiton.OfflineExpiredEntry=Egun gehiegi egon zara lineaz-kanpo. Vuze Plus ez dago eraginda.
+tags.view.heading=Etiketa Gainikuspena
+ConfigView.label.queue.stoponcebandwidthmet=Ez hasi beste torrentik igoera/jeisketa abiadura muga lortua dagoenen
+ConfigView.button.save=Gorde
+Security.keystore.corrupt='%1' giltzabiltegiak huts egin du, mesedez ezabatu hura eta birsortu/bir-inportatu egiaztagiriak
+azbuddy.dchat.pc.pinned.only=Only accept chats from  participants
+UpdateWindow.status.restartNeeded=Berrabiaraztea beharrezkoa da\!
+importTorrentWizard.process.inputfilebad.message=Hutsegitea gertatu da hurrengo sarrera agiria atzitzean\:
+ConfigView.section.security.op.error.title=Eragiketak Huts egin du
+subscript.add.desc=Zihur zaude '%1' harpidetza ezartzea nahi duzula?
+ConfigView.section.tracker.maxgettime.info=Iragarle eta zuritzetarako erabilia
+rcm.config.max_results=Gehienezko emaitzak
+tps.type.plugin=Plugina
+azbuddy.tracker.bbb.status.in=Kitzikatua Izan Naiz
+devices.copy.folder.dest=Agiritegira kopiatu
+ConfigView.text.hours=ordu
+label.monitor.clipboard=Monitore Gakoa Torrent Loturentzat
+#
+# Tooltips
+#
+GeneralView.label.status.pieces_available.tooltip=Erakutsi atal bakoitzaren kopia eskuragarrien zenbatekoa.\nEskuineko zenbakia 1 baino txikiagoa bada, ez zaude ikusten agiriaren kopia oso bat (eta arazoak egon daitezke jeisketa burutzeko).
+GeneralView.label.in_swarm=erletaldean
+MyTrackerView.scrapes=Zurituak
+MainWindow.menu.file.open.torrentfortracking=T&orrent Agiria... (Aztanaritza Bakarrik)
+label.close.tab=Itxi Hegatsa
+window.updateswt.title=Zure SWT Bertsioa zaharregia da\!
+ConfigView.label.autoupdate=Ireki berritze leihoa bertsio berri bat eskuragarri dagoenean
+update.now.title=Eguneraketa Beharrezkoa
+subscript.add.dup.desc='%1' Harpidetza jadanik ezarrita dago.
+upnp.ignorebaddevices.reset=Berrezarri bazterturiko gailu zerrenda
+ManagerItem.downloading=Jeisten
+DiskManager.error.nospace_fat32={DiskManager.error.nospace} - egiaztatu {wiki.fat32}
+Button.retry=&Birsaiatu
+PeersView.state.info=Hartzaile elkarketaren egoera
+device.rss.enable=Sortu RSS jarioa transkodeaketa edukitik -  honek edukia eskuragarri egiten du RSS jario irakurleentzat
+ConfigView.section.ipfilter.allow=AHALBIDETU maila hauek (berezko balioa UKATZEA da)
+progress.window.msg.filemove=Mesedez itxaron agiri mugitze/berrizendatzea burutzen den bitartean
+OpenTorrentWindow.mb.alreadyExists.default.name=Multimedia
+mdi.entry.about.devices=Garatzen
+update.fail.app.changed.title=Eguneratzeak Huts egin du
+pairing.alloc.fail=Huts egin du sarbide kode berri bat izendatzerakoan\n%1
+ConfigView.section.tracker.portbackup=Babeskopia atakak (';' bananduta)
+MinimizedWindow.all_transfers=Vuze Eskualdaketak
+ConfigView.section.tracker.natchecktimeout=Egiaztatu itxaronaldia (seg)
+iconBar.share=Elkarbanatu
+TableColumn.header.sessiondown.info=Saio honetan jeitsitako byteak
+devices.turnon.itunes=iTunes-entzako sostegua barne (beharrezkoa Apple gailuentzat)
+PeersView.menu.showdownload=Erakutsi Jeisketa &Xehetasunak
+SpeedTestWizard.abort.message.entered.queued=Aztertu osoki jeitsitako lerrokatuta/geldituta egoera
+Button.renew=Berritu
+ConfigView.text.any=edozein
+FilesView.sha1.calculate=Kalkulatu SHA1 hasha (k)
+OpenTorrentFile.column.name.info={OpenTorrentWindow.fileTable.fileName}
+PeersView.outgoingreqcount.info=Hartzaileari egindako irteera eskabideen zenbatekoa
+ConfigView.section.style.ShowTagButtons=Erakutsi Etiketa Botoiak Liburutegian
+subscriptions.view.help.2=Eskuratu dohainik zuzeneko eguneraketak jeisteko eduki berriak eskuragarri dauden bakoitzean.  <A HREF\="http\://wiki.vuze.com/w/FAQ_Subscriptions">Learn More</A>.
+subscriptions.view.help.1=Gehitu Harpidetzak ikusten dituzun bakoitzean
+ConfigView.section.proxy.disable.plugin.proxies=Ezagitu plugin proxyak (adib. Tor/I2P Laguntzailea pluginak) SOCKS zerbitzari bat itxuratzen denean
+azbuddy.dchat.open.in.vuze=Ireki Vuzen
+MyTorrentsView.menu.setSpeed.in=*
+TorrentOptionsView.multi.title.short=Torrent Aukerak/Argibideak
+br.backup.auto.now=Aztertu berez-babeskopia orain
+OpenTorrentWindow.checkbox.showAdvanced=Torrent bat gertatzen denean, utzidazu aukera aurreratuak ezartzen, agiri hautapena eta gordetze kokalekua bezalakoak.
+ConfigView.section.proxy.username.info=Proxy zerbitzariak egiaztapena eskatzen badu baita zehaztua ez denean, erabili kate hau "<inor ez>" erabiltzaile izen(ak) bezala
+settings.updated.msg=Zure Vuze ezarpenak eguneratu dira.
+GeneralView.label.numberofpieces=Atal Zenbatekoa\:
+ConfigView.label.enableSystrayToolTipNextETA=Erakutsi hurrengo jeisketa osatutakoan
+splash.plugin=Plugina Gertatzen\:
+Progress.reporting.window.remove.auto.tooltip=Berez kendu osaturiko, huts eginiko, edo ezeztaturiko aurrerabideak ikuspenetik
+ConfigView.label.set_ui_transfer_speeds.description.upload=Ezarri igoera abiadurak (KB/s)
+wizard.webseedseditor.edit.newseed=Emaritza Berria
+wizard.newtorrent.showtorrent=Bilatu sortutako torrent agiria
+installPluginsWizard.details.loading=Xehetasunak gertatzen, mesedez itxaron...
+v3.MainWindow.button.cancel=Ezeztatu
+ConfigView.section.logging.netinfo=Sortu sare argibideak
+importTorrentWizard.process.unknownfail.title=Ustekabeko Hutsegitea
+TableColumn.header.status=Egoera
+MainWindow.menu.community.chat=Herkidegoa eta Txata
+label.pop.out=Irtenaldia
+TableColumn.header.upspeed.info=Oraingo igoera abiadura
+Button.bar.edit.cancel=Edizioa Eginda
+PeersView.C1.info=Hartzaileak jeisketa galarazten badizu
+menu.change.url=Aldatu URL-a...
+Network.alert.acceptfail=Huts egite zenbait izan da %1, %2 atakatan - aurrerabidea utzita dago. Mesedez egiaztatu ataka honentzat suhesi ezarpenak zihurtatzeko gaituta dagoela elkarketak jasotzeko.
+TableColumn.header.activityDate=Gehitze Eguna
+TableColumn.header.priority.info=Torrentari ematen zaion banda zabalera finkatzen du
+GeneralView.label.tracker=Aztarnariaren Egoera\: 
+ConfigView.section.connection.peersource.DHT=Zentralizatu gabeko aztarnaritza
+ConfigView.section.interface.wavlocation=Helbidea .wav agiriarentzat
+ConfigView.section.style.disableAlertSliding=Ezgaitu labantze biziduna/goren eran alerta mezuentzat
+device.od.error.nospace=Ez da tokirik gelditzen gailuan edo ez dago kanpo batasunik elkarketaturik 
+PeersView.uniquepiece=Atala (Gain-Emaritze modua)
+security.certcreate.orgunit=Erakunde Batasuna
+metasearch.addtemplate.desc=Zihur zaude '%1' izena duen bilaketa eredua ezartzea nahi duzula?
+ConfigView.section.transfer.autospeed.maxupload=%1 gehienezko igoera abiadura [0\: mugagabea]
+Formats.units.persec=/s
+# Will be used for {library.name} in VuzeUI view
+library.name._vuze=Liburutegia
+ConfigView.pluginlist.coreplugins=Hurrengo baterapen pluginak gertatu dira\:
+ConfigView.section.transfer.autospeed.maxdec=%1 gehienezko beherapena aldi bakoitzeko
+configureWizard.nat.server.tcp_listen_port=Sarrerako TCP Aditze Ataka
+configureWizard.nat.tooManyPorts=Aztertzeko ataka gehiegi (9 gehienez)
+MyTorrentsView.menu.upSpeedLimit=Igoera Abiadura Muga
+GeneralView.title.full=Orokorra
+UIDebugGenerator.message.cancel.text=Ez duzu jakinarazten saiatzen ari zaren akatsaren azalpenik. Zure akatsa argia izan daiteke zuretzat, baina azalpen bat izan gabe, zure arazoaz guk egin dezakeguna asmatzea besterik ez litzake.\n\nGarbiketa Argibide Sortzea ezeztatua izan da.
+ConfigView.text.all=denak
+MainWindow.menu.tools.nattest=NAT/Suhesi Azterketa...
+ConfigView.section.transfer.autospeed.chokeping.tooltip=Ping aldiak balio honen gainetik sare betekada adierazletzat hartuko dira
+v3.MainWindow.tab.browse=Vuzen
+auto.mode=Berez (gomendatua)
+v3.activity.button.watchall=Markatu Ikusitako Denak
+ConfigView.label.minPeersToBoostNoSeeds=Emaritzen Maila Txikiena emaritzen ari ez diren torrententzat eta hau baino gutxiago
+ConfigView.section.style.defaultSortOrder.flip=Aurreko antolakuntzaren alderantziz
+azbuddy.dchat.rchans=Antzeko Kanalak
+TorrentOptionsView.param.alternative.value.enable=Txandakatu balioa emaritzan
+Trackers.column.last_update=Azken Eguneraketa
+IPChecker.external.httpinvalidresponse=HTTP erantzun baliogabea
+columnChooser.apply=Ezarri
+ConfigView.section.file.perf.cache.trace=Marraztu katxe eragiketak igarpen asmoetarako
+MagnetPlugin.report.alive=%1 bizirik
+TableColumn.header.maxdownspeed=Geh. Jeisketa Abiadura
+ConfigView.section.tracker.torrentsperpage=Zenbat torrent orrialdeko?  [0\: mugagabea]
+platform.win32.baddll.AxShlex=Alkohola %120
+ConfigView.section.ipfilter.bannedinfo=Datu gaitzak bidaltzen dituzten IP-ak - eragotzi muga gainditzen badute
+OpenTorrentWindow.set.savepath=Aldatu Goren Mailako Agiritegi Izena
+Formats.units.Kibit=Kibit
+LoggerView.filter=Iragazkia
+OpenTorrentOptions.header.tags={label.initial_tags}\: %1
+FilesView.rename.failed.text=Eragiketak huts egin du, zihurrenik xede hautaketa okerragaitik
+azbuddy.tracker.bbb.status.out=Oraingo Lagun Kitzikapena
+ConfigView.label.sleep.fpseed='Lehentasun Nagusia' emaritza eraginda dago
+subscriptions.listwindow.autochecktext=Vuzek zure liburutegiko edukiekin lotura duten harpidetzak bilatu ditzake. Nahi duzu eginkizun hau gaitzea?
+discarded=baztertuta
+ConfigTransferAutoSpeed.ping.time.good=Ona\:
+installPluginsWizard.list.name=Izena
+ConfigView.section.backuprestore=Babeskopia eta Leheneratzea
+DownloadActivityView.legend.up_smooth=Igoera (Lehuna)
+devices.contextmenu.od.enable=Gaitu
+pairing.status.registered=Eguneraketa eginda (%1)
+DHTView.activity.details=Xehetasunak
+platform.win32.baddll.WSOCKHK=Sare Babeslea
+ConfigView.label.minSeedingTime.tooltip=Emaritzen Lerruna sarri aldatu daiteke denbora epe labur batean, batzuetan torrenta berezgaitasunez abiaraztea eraginez, ondoren berehala gelditua eta lerrokatua izateko..\nHonek arazoa arintzen du torrenta emaletzan egotera behartuz denbora batez.  Oraindikan eskuz gelditu dezakezu nahi baduzu.
+PeerSocket.fake_client=USTELA
+TrackerChangerWindow.title=Gehitu Aztarnaria
+wizard.savingfile=Agiria gordetzen...
+platform.jvmopt.configerror=Ezin dira  JVM aukerak kudeatu itxurapen akats bat dagoelako
+OpenTorrentFile.column.size.info=Agiri neurria
+ConfigView.section.security.resetkey.error.title=Eragiketak Huts egin du
+ConfigView.section.queue.seeding.autoStarting=Berez Abiatzea
+ConfigView.section.security.restorekeys=Leheneratu giltzak agiri batetik
+MainWindow.menu.file.open.torrent.keybinding=Meta+O
+MainWindow.status.unofficialversion=Vuze Beta
+wizard.operationfailed=Eragiketak huts egin du
+IPChecker.external.timeout=Denboraz kanpo gelditu da
+ipfilter.disabled=IP Iragazkiak Ezgaituta
+TableColumn.header.seeds.info=Elkarketatutako emaritza Zenbatekoa (Zenbat emaritza guztira)
+speedtest.wizard.select.general=Abiadura azterketa Orokorra (gomendatua)
+wizard.comment=Aipamena\:
+unix.script.new.auto.text=Vuzeren Abiarazpen Eskript berria eskuragarri.\n\nOso gomendagarria da zure Vuze berrabiarazia izatea orain.
+installPluginsWizard.file.invalidfile=Agiria ez da baliozko Vuze plugina.
+MyTorrentsView.menu.setSpeed.down.disable=Ezgaitu Jeisketa
+wizard.multitracker.edit.newgroup=Talde Berria
+v3.MainWindow.menu.view.footer=Orrialde ohina
+TableColumn.header.remaining.info=Jeisteke dagoenaren zenbatekoa
+platform.win32.baddll.gapsp=Neoteris
+Pieces.column.Requested=Eskabidetuta
+iconBar.bottom=Beheren
+SpeedTestWizard.abort.message.scheduling.failed=Azterketaren egitaraupenak huts egin du
+TableColumn.header.file_eta={TableColumn.header.eta}
+PeersView.source.info=Hartzaile honen iturburua
+GeneralView.label.totalspeed.tooltip=Zurekin elkarketatuta dauden bezero guztien abiadura osoa (eta bataz-bestekoa).
+FilesView.menu.setpriority.high=&Handia
+tag.type.man.featcon=Eduki Ezaugarriak
+ConfigView.section.dns.alts=Aukerazko DNS zerbitzariak [';' bananduta]
+ConfigView.section.style.dropdiraction.sharefoldercontents=Elkarbanatze Edukiak
+azbuddy.tracker.bbb.status.title.tooltip=Klik bikoitza xehetasunak ikusteko
+speedtest.wizard.select.title=Hautatu egin behar den abiadura azterketa mota
+PeersView.uploadspeed=Igoera Abiadura
+SpeedTestWizard.test.panel.already.running=Azteketa jadanik lanean\!
+table.columns.reset=Berrezarri Zutabeak
+MySeedersView.header=Osatutako Torrentak
+device.renderer.view.title=Egileak
+upnp.mapping.tcpssltrackerport=TCP SSL Aztarnari Ataka
+IrcClient.hasleft=utzi egin du
+TableColumn.header.downspeed=Jeisketa Abiadura
+wizard.newtorrent.byo=Eraiki Zeurea
+MainWindow.menu.community.forums=Herkidego Ezta&baidaguneak
+GeneralView.label.user_comment=Erabiltzailearen Aipamena\:
+MainWindow.IPs.tooltip=Iragazki zerrendaren azken eguneratzea\: %1\nGuztira IP Iragazkiak zerrendan - Itxitako/eragotzitako/gaitz IP-ak saio honetan.\nKlik bikoitza xehetasunak ikusteko.
+OpenTorrentWindow.mb.notTorrent.cannot.display=Ezgaitu datuak egoki erakusteko
+General.percent=Ehuneko
+beta.wizard.disable.text=Mila esker beta bertsioak probatzeagaitik\!\n\nMesedez jeitsi eta ezarri argitaraturiko azken bertsioa beta programa baimentzeko
+Button.turnon=Gaitu
+TableColumn.header.torrentrelpath=Torrent Helburua
+swt.alert.cant.update="%3" -tik hartutako SWT liburutegia ezin da berezgaitasunez eguneratua izan %1 -> %2 bertsiora  ("%4"-tik egon behar du gertaturik). Mesedez ikusi <A HREF\="http\://wiki.vuze.com/w/SWT_Cant_Auto_Update">the wiki</A> xehetasunetarako.
+ConfigView.section.interface.checkassoc=Egiaztatu elkartzeak hasitakoan
+webui.port=Ataka
+subscript.some.subscribed=Eduki hau duten harpidetza batzuk dituzu\nKlikatu eskuragarri dauden beste batzuk ikusteko
+show.tooltip.label=Erakutsi Oharra
+br.backup.auto.everydays=Babeskopia maiztasuna [egunak]
+label.tag.selection=Etiketa Hautapena
+ConfigView.section.security.choosetoolssavedir=Hautatu 'tools.jar' duen agiritegia
+v3.MainWindow.menu.view.toolbars=Tresna Barrak
+subscript.export.select.template.file=Gorde Harpidetza
+window.update.noupdates.beta.title={window.update.noupdates.title}
+TableColumn.header.priority=Lehentasuna
+devices.copy.folder.auto=Berezgaitasunez kopiatu agiriak agiritegira
+TableColumn.header.tag.visible={label.visible}
+MyTorrentsView.\#.info={TableColumn.header.\#.info}
+platform.win32.baddll.radhslib=Naomi Internet Iragazkia (Dizdiratsua)
+Scrape.status.error.nohash=Hasha erantzun gabe.
+MagnetURLHandler.report.torrent_size=torrent neurria\: %1
+Wizard.Subscription.create.title=Sortu Harpidetza Berria
+jvm.max.direct.mem.info=Oharra\: hau *Zuzen* oroimen ezarpena da, ohikoagoa da eguneratu behar izatea *Pilo* oroimena gainean
+azbuddy.chat.says=%1-ek dio\:
+menu.max.share.ratio=Xede Elkarbanatze Maila (%1)...
+device.xcode.group=Kodea
+OpenTorrentWindow.torrent.remove=Kendu torrenta zerrendatik
+ActivityView.legend.swarmaverage=Erletalde bataz-bestekoa
+TableColumn.header.seed_to_peer_ratio=Emaritza-Hartzaile harremana
+MainWindow.menu.window=&Leihoa
+device.router.con_type=Elkarketa\: %1
+SpeedView.stats.estupcap=Igoera muga\:
+importTorrentWizard.torrentfile.title=Sarrerako Torrentaren Hautapena
+ConfigView.label.savedirectory=Gordetze Zuzenbidea
+label.open.all=Ireki Denak
+TableColumn.header.timesincedownload.info=Datua torrenterako jeitsi zenetik igarotako denbora
+DownloadActivityView.title.full=Abiadura
+pairing.ac.getnew=Izendatu sarbide kode berri bat
+Button.apply=Ezarri
+ConfigView.section.style.launch=Abiarazi Laguntzaileak
+TableColumn.header.done.info=Uneko eginkizunetik buruturiko ehunekoa
+GeneralView.label.shareRatio=Elkarbanatze Maila\: 
+SpeedTestWizard.set.upload.bits.per.sec=bit/seg
+FilesView.menu.rename_only=Berrizendapen Azkarra
+MainWindow.menu.view.ipFilter=IP Iragazkiak
+v3.mb.delPublished.cancel=E&zeztatu
+label.click.to.showhide=Klikatu erakutsi/ezkutatzeko
+label.alertnum=Alertak\: %1
+devices.xcode.rsspub=Argitaratu RSS jarioa
+upnp.mapping.tcptrackerport=TCP Aztarnari Ataka
+remote.pairing.test.success=Vuze hurrunetik eskuragarria da.
+sidebar.header.subscriptions=Harpidetzak
+dlg.auth.revoked.link=<A HREF\="info">Eragintza kodeen Indargabetzeari buruzko Argibideak</A>
+TableColumn.header.readrate=Irakurketa Neurria
+ConfigView.section.file.defaultdir.section=Berezko Zuzenbide Aukerak
+Peers.column.peer_byte_id.info=Hartzailearen ID-a byte eran
+label.color=Margoa
+ConfigView.label.seeding.firstPriority.info=Lehentasun nagusiko torrentak betik egongo dira lerroaren gorenaldean\nLehentasun Nagusia irizpidea betetzen duen edozein torrent ez da berezgaitasunez gelditua eta lerrokatua izango.\nLehentasun Nagusia irizpidea duen torrentak Aldibereko Jeisketa ahoa hartu dezake behar izanez gero.
+ConfigView.label.movetorrent=Mugitu .torrenta
+ConfigView.section.tracker.enablecompact=Gaitu iragarpen harreman trinkoa
+ConfigView.label.maxStalledSeeding=Gehienez 'hesituta' [0\:mugagabea]
+azbuddy.ui.menu.send=Bidali Mezua
+jvm.min.mem=Gutx Piloaren oroimen neurria [zuri\=berez,gutx\=%1]
+ConfigView.notAvailableForMode=Atal hau %1 moduarentzat edo handiagoarentzat da. Ez da eskuragarria %2 moduan.
+devices.choose.profile.info.text=Zure hautaketaren ondoren, Vuzek atzemango du bideo heuskarria hautaturiko irakurgailuan ikusi ahal den, eta gailu-bateragarri kopia bat sortu beharrezkoa bada.\n\nJarri hautatutako gailuaren gainean xehetasun gehiago ikusteko.
+ConfigView.label.userequestlimitingpriorities=Finkatu jeisketa abiadura jeisketa lerroburuan jeisketa abiadura muga erdiesten denean
+UpdateWindow.columns.install=Ezarri
+network.admin.maybe.vpn.msg=Agertzen da Sare Birtual Pribatu (VPN) bat eraginda eduki dezakezula\n\n\t%1\n\nHorrela bada pribatutasuna handitu dezakezu honetara loturatuz - hautatu BAI egiteko.\n\nHorrela ez bada, edo zihur ez bazaude, hautatu EZ.\n\nIkusi <a href\="http\://wiki.vuze.com/w/Proxies_And_VPNs\#VPN_Configuration">wikia</a> argibide gehiagorako.
+MainWindow.upgrade.newerversion=Vuzeren bertsio berri bat dago eskuragarri
+ConfigView.label.experimental.osx.kernel.panic.fix=Zuzenketa esperimentala kernel panics dual-cpu OSX sistemarentzat [berrabiaraztea beharrezkoa]
+azbuddy.disabled=Plugina ezgaiturik dago, ikusi plugin itxurapenak aldatzeko.
+unix.script.new.auto.title=Vuzeren Abiarazpen Eskript Berria
+ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=SO_RCVBUF indar hartune estandarra ezartzen du, balioa (byte-tan), esanahi da, TCP leihoaren harrera eta eskala neurria.\nVuzek ezarri gabe uzten du berez, esanahi da azpiko SE-arentzako balio aurrezarriak erabili egiten dira.\nOHARRA; Linux bikoiztu egiten du emaniko balioa.
+ConfigView.section.style.useSIUnits=Erabili IEC Batasunak (KB -> KiB, etab.)
+azbuddy.ui.menu.cat=Kategoriak
+device.config.xcode.maxbps=Geh KB/seg transkodeaketa neurria [0\: mugagabea]
+MainWindow.menu.file.closetab=Itxi &Hegatsa
+ConfigView.label.stop=Itzali
+wizard.invalidfile=Agiri baliogabea\!
+wizard.invaliddirectory=Zuzenbide baligabea\!
+installPluginsWizard.mode.file=Agiritik
+config.external.browser.switch.subs.inf=Behar du 'Vuze Hurruneko Webgunea' plugina; Emaitzak ez dira 'irakurrita' bezala ezartzen jeitsitakoan; Jeitsitako loturatan aipamenik ez
+ConfigView.label.savetorrentbackup=Gorde babeskopia
+quick.view.no.files=Ez dago Agiri Egokigarririk
+UpdateProperty.list.message=Sartu balio berria %1-rako. Erabili ',' bat sarrera anitz banantzeko; utzi hutsik garbitzeko
+ConfigView.section.security.toolsdir='tresnak.jar' dituen zuzenbidea
+ConfigView.section.file.tb.delete=Ezabatzerakoan Ezabatu edo Tresnabarraren bidez\:
+DHTTransport.report.send_complete=bidali osorik
+MainWindow.about.internet.bugreports=Akatsen Jakinarazpena
+azbuddy.downspeed=KB/s geh. lagunen jeisketa abiadura [0\: mugagabea]
+TableColumn.header.timesinceupload.info=Datua torrenterako igo zenetik igarotako denbora
+ConfigView.label.systray._mac=Egoera Barra Ikurra
+v3.deviceview.infobar.line1.generic=Arrastatu eta askatu bideoak zure Liburutegitik %1 zure Albobarrara.
+ConfigView.section.proxy.enable_socks=SOCKS proxy bat dut
+azbuddy.ui.table.lastseen=Azkenaldiz Ikusia
+MyTorrentsView.menu.rescanfile=Aldizka Berregiaztatu Osatugabeko Atalak
+ConfigView.section.mode=Modua
+label.anon=Izengabea
+xcode.deletedata.title=Ezabatu Transkodeaketa Edukia
+ConfigView.label.irclogin=Izenordea
+TableColumn.header.device.info=Xede Gailua
+ConfigView.section.ipfilter.save=Gorde
+wizard.multitracker.delete=Ezabatu
+iconBar.editcolumns=Zutabe Ezarpena
+PiecesView.DistributionView.NoAvl=Atal Eskuraezinak
+sidebar.show=Eraskutsi albo barra
+TableColumn.header.upload.info=Hartzaileei bidali diegun datu zenbatekoa
+ConfigView.section.sharing.privatetorrent=Torrent pribatua - aztarnariaren hartzaileak besterik ez ditu onartzen
+installPluginsWizard.list.loading=Mesedez itxaron Plugin zerrenda gertatzen den bitartean.
+Button.bar.add=Gehitu
+exportTorrentWizard.torrentfile.browse=Bilatu
+MyTrackerView.tracker=Aztarnaria
+devices.associate=Honekin elkartuta
+ConfigView.section.security.backupkeys.button=Babeskopia
+ConfigView.option.dm.dblclick.details=Ireki Torrent Xehetasun Ikuspegia
+dlg.auth.trial.success.subtitle=DVD Grabaketa Gertu
+ConfigView.label.show.tag.but=Erakutsi Etiketa Botoiak
+Button.abort=Utzi
+SpeedView.stats.manual=Finkatuta
+MyTrackerView.completed=Osatuta
+ConfigView.section.interface.cleardecisions=Garbitu gogoraturiko elkarrizketa erabakiak
+iconBar.pstream=Jarioa
+externalLogin.wait=Orrialdea gertatzen, mesedez itxaron...
+ConfigView.section.Subscriptions=Harpidetzak
+TableColumn.header.eta_next=Hurrengo UED
+pairing.srp.pw.req=Sarhitza beharrezkoa - ezerk ez du lan egingo hau gabe\!
+SpeedView.stats.unknown=Ezezaguna
+azbuddy.dchat.import.data=Aurretik esportaturiko babeskopia datuak
+remote.pairing.functions=<A HREF\="clip">Kopiatu kodea gakora</A>   |   <A HREF\="new">Eskuratu kode berri bat</A>
+LocaleUtil.label.chooseencoding=Hautatu kodeaketarik egokiena
+wizard.information=Argibideak
+ConfigView.section.tracker.seedretention.info=Oharra\: Igoera estatistikak galdu egin daitezke emaritza ez-atxikietan
+CacheView.speeds.writes=Idatziak
+window.updateswt.status=Egoera
+config.external.browser.non.pub=Betik erabili %1 eduki ez-publikoentzat
+TorrentOptionsView.param.reset.to.default=Ezarri aukerak berezko balioetan
+TableColumn.header.DownloadingRank=Jeisketa Mailaketa
+device.renderer.remove_all=Kendu Aurkezle denak
+torrentdownload.error.dl_fail=Hutsegitea '%1' jeistean '%2'-tik\: %3
+DHTView.transport.packets=Paketeak
+SpeedView.stats.maxUp=Geh. Igoera Abiadura\:
+tps.tracker.cache=Hartzaile katxea
+label.set=Ezarri...
+splash.initializePlugins=Pluginak Abiarazten
+ConfigView.section.interface.cleardecisionsbutton=Garbitu
+FilesView.dialog.priority.title=Sartu Zenbaki Lehentasuna
+label.no.tag=Etiketarik Ez
+PeersView.upload=Igoera
+TableColumn.header.torrent_created.info=Torrenta sortutako eguna, eskuragarri dagoenean
+wizard.multitracker.configuration=Aztarnari-Anitzaren Ezarpenak
+StartStopRules.shareRatioMet=Elkarbanatze Maila Ongi
+TableColumn.header.azsubs.ui.column.subs=Harpidetu
+ConfigView.label.seeding.autoStart0Peers.tooltip=Piztu nahi baduzu aztarnariak betik zerrendatzea emaritzak 0 hartzaile torrenteko.
+security.certcreate.intro=Elkarrizketa honek bere-sinatze egiaztagiri bat sortzea ahalbidetzen dizu
+device.itunes.install_problem=Badirudi arazo bat dagoela iTunes bateragarritasunarekin
+FilesView.md5.calculate=Kalkulatu MD5 hasha(k)
+min.sr.window.message=Sartu gutxienezko elkarbanatze maila [0\:ezgaituta]
+set.share.ratio.win.title=Ezarri Elkarbanatze Maila
+ConfigView.label.backupconfigfiles=Babeskopia itxurapen agiriak berreskurapen asmoekin
+iconBar.stop=Gelditu
+StartStopRules.SPratioMet=S\:P Maila Ongi
+ConfigView.label.checkOnSeeding=Egin baliabide gutxiko atalen egiaztapena emaritzan
+DiskManager.alert.movefilerecoveryfails=Berreskurapen akatsa mugitzeak hutsegin ondoren\nAgiri berreskurapena %1 huts eginda, %2
+device.ms.group={device.mediaserver.view.title}
+ConfigView.label.seeding.rankType.seed=Emaritza Zenbaketa Bakarrik
+Unopened.bigView.header=Berria
+ConfigView.section.sharing.rescanperiod=Birmihaketa aldia (seg)
+PeerManager.status.checking=Egiaztatzen
+device.xcode=Transkodeaketa
+wizard.progresstitle=Torrent agiria sortzen
+wizard.tracker.howToLocal=\tJoan 'Tresnak->Aukerak->Aztarnaria' hura gaitzeko
+TrayWindow.menu.startalldownloads=Hasi Jeisketa Denak
+ConfigView.section.tracker.client.scrapesingleonly=Ezgaitu aztarnari-bakoitzeko zuritze gehiketa (lagundu dezake 'URL oso luzea' duten aztarnariekin' (414) akatsak) 
+TableColumn.header.availability.info=Zenbat kopia oso izan diren ikusiak
+ConfigView.option.dm.dblclick.launch.qv={MainWindow.menu.quick_view} / {iconBar.run}
+upnp.enable=Gaitu UPnP
+wizard.createtorrent.extrahashes=Gehitu hashak beste sare batzuetatik (adib. Gnutella2, eDonkey2000)
+stats.snapshot.group=Berehalakoa
+v3.iconBar.down=Behera
+label.dont.show.again=Ez erakutsi mezu hau berriro
+azbuddy.ui.table.read_cat=Kat irakurria
+ConfigView.section.connection.network.max.outstanding.connect.attempts=Geh. egiteke irteera elkarketa
+security.certcreate.createok=Egiaztagiria ongi sortu da
+webui.mode.info=Modua izan daiteke\n\t"osoa"\t\= eragiketa guztiak egingarri (berezkoa)\n\t"ikusi"\t\= ikusi bakarrik (baina berritze maiztasuna eguneratu dezake)
+wizard.multitracker.edit=Editatu...
+azneti2phelper.install.description=Mesedez I2P Plugina ezertzen den bitartean
+PeersView.T.L.tooltip=Zuk ezarri duzu elkarketa
+azmsgsync.install.subtitle=Mezu Aldiberetze Plugina ezartzen
+webui.access.info=Sarbidea izan daiteke\n\t"tokikoa"\t\= tokiko gailua bakarrik elkarketatu daitekela\n\t"denak"\t\= eragozpen gabeko sarbidea (berezkoa)\n\tIP-a\t\= adib. 192.168.0.2\t\t\\ IP-a bakarrik\n\tIP1-IP2\t\= adib. 192.168.0.1-192.168.0.255\\IP eremuak barne
+MainWindow.menu.view.console.keybinding=Meta+4
+DownloadManager.error.filewithouttorrentinfo=Ez da torrent argibiderik aurkitu agirian
+TableColumn.header.TableColumnSample=Lagina
+AlertMessageBox.warning=Kontuz
+MyTrackerView.peers=Hartzaileak
+azbuddy.beta.msgsync.missing='Mezu Aldiberetzea' plugina ezarri behar duzu
+SpeedView.stats.measuredmin=Neurtuta Gutx.
+Plugin.localtracker.info=LAN hartzaile bilatzaileak Vuzeren kopia anitz ahalbidetzen ditu suhesi baten atzean eta sare arrunt batean\ntorrentak modu eraginkorrean jeisteko beraien arteko elkarketa zuzenak gaituz.
+azbuddy.dchat.decentralized.enabled={azbuddy.dchat.decentralized} Gaituta
+MainWindow.menu.file.open.torrentnodefault.keybinding.mac=Meta+Auk+O
+ConfigView.section.transfer.lan.tooltip=LAN-bereiziko Ezarpenak
+UpdateMonitor.messagebox.accept.unverified.title=Onartu Egiaztatugabeko Ezarpena
+Formats.units.KiB=KiB
+security.certtruster.prompt=Fidagarritasuna onartu nahi diozu?
+GeneralView.label.distributedCopies=Banatutako Kopiak\:
+label.socks=SOCKS
+ConfigView.section.torrent.decoding=Dekodeaketa Ezaugarri Ezarpenak
+MainWindow.menu.file.open=&Ireki
+MainWindow.menu.speed_limits.schedule.err=Hurrengo akatsak jakinarazi dira, mesedez berreditatu zuzentzeko\!
+v3.MainWindow.menu.getting_started=&Lehen Urratsak
+dlg.auth.success.line2=Orain gai zara DVD grabaketa mugagabe bat egiteko, mihatu zure agiriak birusen aurka, eta jariotu jeisten ari zaren bideoak - dena iragarkirik gabe\!
+ConfigView.section.interface.resetassocbutton=Berrezarri
+dlg.auth.success.line1=Mila esker Vuze Plus eguneratzeagaitik.
+TableColumn.header.peakup.info=Igoera Abiadura Gailurra
+DHTView.title.fullcvs=Banaturiko Datubasea CVS
+webui.rootdir=Erro zuzenbidea
+wizard.multitracker.noannounce=Zure aztarnarien zerrendan ez dago iragarpen URL-rik
+Button.add.tooltip=Gehitu torrent bat zure liburutegira
+ConfigView.label.start.inlrm=Hasi baliabide erabilpen gutxiko moduan (EI ezgaitua, sare eta oroimen erabilpen murriztua, etab.)
+PeersView.statup=Bataz-besteko Igoera
+ConfigView.section.queue.seeding=Emaritzen
+ConsoleView.title.short=Kontsola
+subs.prop.num_read=Irakurritako emaitz zenbatekoa
+ConfigView.label.save_list.max_entries=Gorde kokaleku historia neurria
+ManagerItem.finishing=Amaitzen
+network.admin.bind.enforce.fail='Behartu IP Lotzeak' hautaturik dago baina ez da lotzerik adierazi\n\nIkusi Tresnak->Aukerak->Elkarketa->Sare Ezarpen Aurreratuak
+v3.MainWindow.menu.view.sidebar.keybinding=F7
+TableColumn.header.filesdone=Agiri Eginda
+uninstallPluginsWizard.title=Kendu Pluginak
+MainWindow.menu.help.whatsnew=Zer Berri
+DHTView.operations.data=Datua
+wizard.newtorrent.byo.addcontainer.title=Gehitu Edukiontzia
+StartStopRules.numSeedsMet=Emaritzak Ongi
+config.internal.browser.proxy.select=Nabigatzaile proxya
+TableColumn.header.torrent_created=Torrenta Sortuta
+openTorrentWindow.mb.alreadyExists.merge=Nahi duzu aztarnari gehigarriak gehitzea jeisketa berritik dagoen batera?
+dlg.stream.plus.title=Berritu
+ConfigView.section.tracker.createcert=Sortu bere-izenpetze egiaztagiria
+UIDebugGenerator.complete.text=Garbiketa agiria ezin da aurkitu '%1'.\n\nKlikatu Ongi agiri honentzat sistema-agiri leiho bat irekitzeko. 
+subscriptions.overview=Harpidetzen Gainikuspena
+ConfigView.dialog.choosedefaultsavepath=Mesedez hautatu berezko gordetze zuzenbidea
+v3.MainWindow.menu.showActionBarText=Erakutsi Izena
+azbuddy.dchat.ftux.footer=Norbanako eta erakunde baten eskubideak bortxatzen dituen Vuze\u00AE edo Vuze+\u2122-ren erabilpena ez dago ahalbidetuta.
+TableColumn.header.chat.user.count.info=Ustezko erabiltzaie zenbatekoa online (zeu ezik)
+FilesView.hide.dnd=Ezkutatu jeisteko hautatuta ez dauden agiriak
+subscriptions.listwindow.popularity.unknown=Ezezaguna
+MyTorrentsView.menu.edit_comment.enter.message=Sartu aipamen bat jeisketa honentzat.
+ConfigView.label.autoopen.downloadbars=Berez ireki Jeisketa Barrak
+pairing.ui.icon.show=Erakutsi Ikurra
+MainWindow.menu.closealldownloadbars=Itxi &Jeisketa Barra Guztiak
+network.bindError=Lotze zerbitzariaren ahoak huts egin du helbide eskuragarririk ez dagoelako, mesedez egiaztatu zure IP loturen ezarpenak.
+Plugin.localtracker.networks.info=Hartu honako sare hauek tokikotzat [sareak ';' bananduta, adib. 145.227.*.*]
+network.check.ipbinding=Egiaztatu IP helbide/interfazea loturarik dagoen abiarazterakoan
+label.various=Askotarikoa
+TableColumn.header.ProgressETA.info=Egoera, Osaketa, UED, eta Jeisketa Abiadura zutabeak lerro-anitzeko zutabe batean batzen ditu
+configureWizard.transfer.maxDownloads=Gehienezko Jeisketak
+wizard.browse=Bilatu
+GeneralView.title.short=Orokorra
+FileItem.storage.linear=Lerrotua
+configureWizard.nat.ok=Ongi\!
+TrackerAvail.column.seeds.info={Trackers.column.seeds.info}
+Button.back=Atzera
+dhttracker.tracklimitedwhenonline=Horrela ere, egin baliabide apalen aztarnapena online daudenean erletaldeko kidegurutzapenerako
+ConfigView.section.security.publickey=Giltza Publikoa
+MainWindow.menu.transfers.resumetransfers=&Berrekin
+ConfigView.label.playdownloadfinished=Jo soinu bat jeisketa burutzen denean
+FileItem.read=Irakurri
+TableColumn.header.commenticon.info=Erakutsi ikurra jeisketak erabiltzaile-zehaztu baten aipamena badu
+splash.loadingTorrent=Torrenta Gertatzen
+GenericText.column=zutabea
+OpenTorrentWindow.tlf.remove=Kendu Goiko Mailako Agiritegia
+ConfigView.section.ipfilter.enable=Gaitu
+MyTorrentsView.menu.setCategory.add=&Gehitu Kategoria...
+popup.closing.in=Leihoaren berez-istea  %1 segundutan
+MagnetPlugin.private_torrent=<torrent pribatua>
+pairing.status.disabled=Ezgaiturik
+torrent.fix.corrupt.result.nothing=Torrenta baliozko bezala agertzen da\!
+TableColumn.header.AzProduct.info=Torrentaren Sare edukia hemendik sortua
+plugins.basicview.status=Egoera\:
+label.test.internet=Aztertu zure internet elkarketa
+azbuddy.ui.table.msg_queued=Lerrokatuta
+mdi.entry.dvdburn=DVD Grabaketa
+configureWizard.nat.sharePort=Erabili sarrerako ataka elkarbanatu bakarra torrent guztientzako
+FilesView.pieces=Atalak
+ManagerItem.paused=Pausaturik
+MainWindow.menu.view.irc=&IRC
+PiecesView.\#=Atal Zenbatekoa
+DonationWindow.noload.text=Dirulaguntza leihoak huts egin du. Mesedez saiatu zaitez geroago.
+MainWindow.sr.status.tooltip.ok=Elkarbanatze Maila %1 Ongi
+Torrent.create.progress.cancelled=Eragiketa ezeztatua
+ConfigView.label.subdir_is_in_default=Jeisketak zuzenbide berezko batean ba ote diren aztertzean, aztertu azpizuzenbideak ere. 
+window.uiswitcher.ClassicUI.title=Interfaze Klasikoa
+ConfigView.section.style.showProgramIcon=Erakutsi programaren ikurra izen zutabean
+MainWindow.menu.file.open.vuze=Vuze Agiria...
+ConfigView.section.queue.downloading=Jeisten
+TableColumn.header.tags={label.tags}
+MagnetPlugin.use.md.download.delay=\tatzerapena [seg]
+ConfigView.label.stopAfterMinutes=Behin emaritzari elkarketaturik, gelditu aldibatez
+dht.execute=Ekin
+PiecesView.size=Neurria
+# Will be used for {library.name} in classic view
+library.name._classic=Nire Torrentak
+MainWindow.dialog.exitconfirmation.title=Irten Vuzetik
+device.wiki=Wiki Iradokizunak eta Aholkuak...
+v3.MainWindow.menu.view.searchbar=Bilaketa Barra
+Trackers.column.type=Mota
+OpenTorrentFile.column.name={TableColumn.header.name}
+core.not.available=Vuze oraindik abiatzen dago, mesedez saiatu berriro eginda dagoenean
+GeneralView.label.trackerscrapeupdate=Zuritu Aztarnaria
+ConfigView.section.pluginslist=Zerrenda
+PeersGraphicView.title.full=Erletaldea
+MyTrackerView.badnat=NAT Gaitzak
+iconBar.host.tooltip=Hostalaria
+Column.seedspeers.started.noscrape=%1
+v3.MainWindow.menu.library=&Liburutegia
+Peers.column.Protocol=Hartuemana
+CacheView.speeds.title=Datu Neurriak
+window.uiswitcher.NewUI.text=* Gomendatua hasiberrientzat eta erabilltzaile berrientzat.\n\n* Erraza, ikusizko grafika interfazea 
+StartStopRules.FP0Peers=FP / 0 Hartzaile
+SubscriptionWizard.column.SubWizRank={subscriptions.column.SubWizRank}
+Plugin.localtracker.networks=Tokiko sareak
+PeerManager.status.error=Akatsa
+installPluginsWizard.file.file=Agiria\:
+PeersView.S.info=Baztertuta\: Hartzaile bat eskuz "baztertu" daiteke, edo berezgaitasunez (datuak abiadura geldoegian bidaltzeagatik)
+Scrape.status.scraping.queued=Lerrokatuak zuritzen...
+ConfigView.section.style.extendedErase=Marraztu saretxo erroak eta bete eremu hutsak
+progress.window.msg.progress=Mesedez itxaron eragiketa burutzen den bitartean
+MainWindow.menu.advanced_tools=A&urreratua
+wizard.newtorrent.byo.addcontainer.text=Sartu edukiontziaren izena torrentean agertzen den bezala
+quick.view.scheduled.text=Hautaturiko agiriak lehentasuna du eta berez-irekiko da ikusteko osatutakoan.
+DHTView.general.reachable=Eskurag.\:
+MyTorrentsView.menu.setSpeed.unlimit=Mugagabea
+IPChecker.external.addressextracted=Erauzitako IP helbidea
+ConfigView.label.seeding.ignoreShareRatio=Baztetu elkarbanatze maila hau duten torrentak
+TorrentOptionsView.param.reset.stats=Berrezarri torrent eskualdaketa estatistikak hutsean
+azbuddy.dchat.status.noplugin=Akatsa\: Mezu Aldiberetze Plugina ez dago ezarrita
+Peers.column.DLedFromOthers=Beste Batzuetatik
+tag.type.ds.comp={label.complete}
+ConfigView.section.interface.cleartrackersbutton=Garbitu
+ConfigView.section.tracker.announcescrapepercentage=Zuritu tartea  % iragarpen epea\nadib. 200 \= 2\:1. 0 \= zer erabaki hartzaile artean
+ConfigView.tb.delete.content=Ezabatu galdetu gabe
+MySharesView.menu.remove=Kendu
+DHTView.operations.title=Eragiketa Xehetasunak
+ConfigView.section.ipfilter=IP Iragazkiak
+DHTView.activity.status.true=Lerrokatuta
+azbuddy.nickname=Zure Izenordekoa
+ConfigView.section.tracker.udpversion=UDP Protokolo Bertsioa (1 edo 2)
+ConfigView.section.file.friendly.hashchecking=Lagunarteko hash egiaztapena
+RCM.column.rc_lastseen=Azken Ikusialdia
+ConfigView.section.style.doNotUseGB=Ez erabili GB batasunik
+installPluginsWizard.list.loaded=Mesedez hautatu ezarri nahi dituzun pluginak.
+Security.jar.tools_not_found=JAR sinadura okerra - 'tools.jar' ez da aurkitu hemen\: %1. Ikusi Tresnak->Aukerak->Segurtasuna xehetasunetarako.
+upnp.alert.mappingok=UPnP\: Izendapena '%1' ezarrita
+TableColumn.header.file_eta.info=Ustezko denbora agiriak jeisketa osatu arte
+configureWizard.nat.ko=NAT Akatsa
+Button.goLibrary=Joan Liburutegira
+ManagerItem.high=Handia
+TrackerAvail.column.type={Trackers.column.type}
+ConfigView.section.tracker.client.exclude_lan=Baztertu LAN eskualdaketa datu estatistikak
+stats.longterm.group=Epe-Luzekoa
+upnp.alert.mappinggrabbed=UPnP\: Izendapena '%1' ezarrita - helduta '%2'
+download.removerules.unauthorised.info=Baimengabeko torrentak dira iragarri erantzunean "ez baimendua" edo "baimengabea" dutenak "hutsegite erantzunean" 
+MainWindow.menu.transfers.resumetransfers.keybinding=Meta+R
+ConfigView.text.ignoreRule=Baztertu Arauak
+ConfigView.section.sharing.torrentcomment=Sortutako torrententzako aipamenak
+ConfigView.label.checkonstart=Egiaztatu azken bertsioa dudala Vuze abiatzerakoan
+MyTorrentsView.menu.explore._mac=Erakutsi Finderren
+#connected to more seeds/peers than tracker reports
+library.all.header.p=%1 Gai\: %2 Eraginda
+ConfigView.section.tracker.passwordenabletorrent.info=BitTorrent bezero egokia (adibidez Vuze) behar da
+br.restore.info=Leheneratu zure itxurapena babeskopia batetik
+MyTorrentsView.menu.downSpeedLimit=Jeisketa Abiadura Muga
+ConfigView.label.maxdownloads=Gehienezko jeisketa aldiberean [0\: mugagabea]\n - Ezin da izan torrent eraginduena baino handiagoa
+UpdateMonitor.messagebox.restart.title=Software Eguneraketa
+MyTorrentsView.menu.moreColHidden=(%1 Gehiago Ezkutuan...)
+dlg.auth.cancelled=Eragiketa Kodea Ezeztaturik
+MyTrackerView.status.stopped=Geldituta
+wizard.close.confirmation=Baieztapena
+azbuddy.dchat.copy.rss.url=RSS URL-a
+FilesView.menu.setpriority.numeric=Zenbakizkoa...
+ConfigView.section.transfer.autospeed.tooltip=Berez-abiadura ezarpen bereziak
+subscriptions.listwindow.loadingtext=Antzeko harpidetzak bilatzen  %1
+tag.type.ds.seed={ManagerItem.seeding}
+UI.cannot_submit_blank_text=Balio bat sartu behar duzu.
+RCM.column.rc_size=Neurria
+updater.cant.write.to.app.title=Ezin da Idatzi Aplikazioaren Agiritegira
+OpenTorrentWindow.addFiles.Folder=Gehitu &Agiritegia
+TagGroupWindow.title=Ezarri Etiketa Multzoa
+webui.bindip=Lotura IP-a - arrunt ez da beharrezkoa
+max.sr.window.title=Xede Elkarbanatze Maila
+PeerFilesView.title.short={FilesView.title.short}
+PeersView.I2.info=Hartzailea zure agiriren batean interesaturik dago?
+pairing.local.ipv6=Tokiko IPv6 helbidea
+pairing.local.ipv4=Tokiko IPv4 helbidea
+MainWindow.upgrade.tooltip.progressbar=Jeisketaren garapena hemen erakusten da
+MyTorrentsView.dialog.setNumber.download=jeitsi
+ConfigView.label.startminimized=Hasi ikurtuta
+TableColumn.header.upspeed=Igoera Abiadura
+iconBar.new.tooltip=Sortu torrent bat
+cat.options=Oraingo Jeisketa Aukerak...
+ActivityView.legend.trimmed=Murrizpena (izpilduta)
+SpeedTestWizard.set.upload.label=Igoera Abiadura Muga\:
+v3.MainWindow.text.my.profile=Profila
+ConfigView.label.seeding.rankType.peerSeed.options=Hartzaile\:Emaritza Maila Aukerak
+TableColumn.header.date_added.info=Torrentaren gehitze eguna
+pairing.status.noservices=Ez dago hurruneko zerbitzurik gaituta
+ConfigView.section.ipfilter.enablebanning=Itxi datu gaitzak etengabe bildaltzen dituzten hartzaileak
+PiecesView.BlockView.Have=Duzu
+ConfigView.label.maxactivetorrents=Gehienezko Torrent lanean [0\: mugagabea]\n - Torrent berriak ez dira abian jarriko gehiago jeisten/emaritzen ari bazara
+MyTorrentsView.menu.edit_comment=Aipamena Editatu
+TableColumn.header.TorrentStream=Jarioa
+PiecesView.availability=Eskuragarritasuna
+MySharesView.type.file=Agiria
+TableColumn.header.status.info=Torrenta egiten ari dena
+v3.topbar.menu.show.search=Bilatu
+pairing.group.explicit=Ezaugarri Bereiziak
+TableColumn.header.secondsdownloading.info=Jeisten egon zaren denboraren zenbatekoa guztira.
+MainWindow.upgrade.step2=2. urratsa\: Bertsio hau itxi eta Vuzeren bertsio berria berrabiarazi
+label.original.file=Jatorrizko Agiria
+MainWindow.upgrade.step1=1. urratsa\: Jeitsi bertsio berria
+ConfigView.section.tracker.natcheckenable=Egiaztatu 'sarrera datu ataka' elkarketagarritasuna eta jakinarazi akatsak hartzaileei
+GeneralView.label.maxuploadspeed=Igoera Muga
+ConfigView.label.maxdownloadspeed=KB/s geh. jeisketa abiadura orokorra [0\: mugagabea]
+rss.internal.test.url=Klikatu tokiko hasiera orrialdea ikusteko
+window.networkselection.title=Sare Hautapena
+label.set.share.ratio={set.share.ratio.win.title}...
+PeersView.BlockView.Avail.Have=Biok duzue
+device.error.copytonowrite='Kopiatu Agiritegira' "%1" Ez Idazgarria
+ConfigureWizard.language.choose=Hautatu hizkuntza beheko zerrendatik\:
+SpeedTestWizard.finish.panel.click.close=Amaitu duzu abiadura azterketa laguntzailea. Klikatu itxi irtetzeko
+MainWindow.menu.quick_view=Ikuspen Azkarra
+MagnetPlugin.contextmenu.exporturi=Kopiatu Magnet &URI-a Gakora
+devices.choose.device.title=Hautatu irakurgailu bat bideo honentzat\:
+MainWindow.menu.file.open.torrentnodefault=Torrent agiria... (Ez Gorde Lehenespenez)
+MyTrackerView.seeds=Emaritzak
+ColumnSetup.filters=Iragazkiak
+MainWindow.nat.status.ok=NAT Ongi
+Security.keystore.empty=Giltzabiltegia hutsik dago. Mesedez sortu berez-izenemate egiaztagiri bat (ikusi Tresnak->Aukerak->Segurtasuna) edo inportatu '%1'-ra jadanik  baduzun egiaztagiri bat 
+CategoryAddWindow.message=Sartu kategoria izen berri bat
+GeneralView.label.private=Torrent Pribatua\:
+ConfigView.unlimited=Mugagabea
+ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=SO_SNDBUF indar hartune estandarra ezartzen du, balioa (byte-tan), esanahi da, TCP leihoaren harrera eta eskala neurria.\nVuzek ezarri gabe uzten du berez, esanahi da azpiko SE-arentzako balio aurrezarriak erabili egiten dira.\nOHARRA; Linux bikoiztu egiten du emaniko balioa.
+iconBar.stop.tooltip=Gelditu hautatutako torrenta(k)
+dht.reseed=Birremaritu
+restart.error.fnf='%1' ez da aurkitu '%2'
+v3.MainWindow.button.preview=Aurreikuspena
+AutoMigration.useralert=Vuzek agiri/helbide itxurapen berez-migraketa erabiltzen du, emaitzak\:\n\n%1\nHutsegite batzuk eskuz migratu behar dira.\nEZ AHAZTU EGUNERATZEAZ GORDETAKO ZURE HELBURUAK ITXURAPENEAN MIGRATU EGIN BADUTE\!
+statusbar.feedback=Bidali Iruzkina
+v3.menu.device.exploreTranscodes._mac=Erakutsi Agiriak Finder-ean
+label.shared=Elkarbanatuta
+LoggerView.includeOnly=Erakutsi bakarrik adierazpide honekin bat datozen lerroak\:
+plus.notificaiton.ExpiringEntry.s=Zure Vuze Plus harpidetza epea %1 egun barru amaituko da\: <A %2>Berritu Orain</A>
+device.router.configure=Itxuratu UPnP-a
+plus.notificaiton.ExpiringEntry.p=Zure Vuze Plus harpidetza epea %1 egun barru amaituko da\: <A %2>Berritu Orain</A>
+ConfigView.label.popupfilefinished=Erakutsi alerta leihoa agiria amaituta dagoenean
+ConfigView.section.tracker.server=Zerbitzaria
+v3.activity.header.vuze.news=Vuze Berriak
+metasearch.addtemplate.title=Ezarri Eredua Bilatu?
+plugin.aznetstatus.logfull=Oharreratze Osoa
+dht.ipfilter.log=Ohartu  IP Iragazki bortxaketez
+stream.analysing.media.preview=Multimedia Aztertzen (Aurreikuspen Modua)
+Scrape.status.nextScrapeAt=Hurrengo zuritzea %1
+Scrape.status.error=Zuritze Akatsa\:
+SystemTray.tooltip.seeding=%1 emaritzen,
+TableColumn.TorrentStream.tooltip.disabled=Irakurri Orain-ek ez du agiri mota hau sostengatzen
+webui.passwordenable=Gaitu sarhitza
+updater.progress.window.info=Sakatu 'Utzi' egiteke dauden eginkizun guztiak amaitzeko
+TableColumn.header.tag.discovery.addedon=Aurkituta
+pairing.enable=Gaitu Vuzeren uztarpena eta hurruneko aplikazio/interfazeak
+fileDownloadWindow.title=Vuze - Torrent jeistzailea
+MainWindow.upgrade.explanation=Laguntzaile honek bertsio berria jeitsiko du zure ordenagailuko Vuze agiritegira eta Vuze berrabiaraziko du
+br.restore.folder.info=Hautatu aurreko babeskopia duen agiritegia
+update.fail.app.changed=Vuzek eguneratzea behar du baina aurrerabidea ezin daiteke berezgaitasunez osatu aplikazioaren izena aldatua izan delako '%1'.\n\nMesedez joan http\://www.vuze.com/-era eta jeitsi azken ezartzailea.
+jvm.max.direct.mem=Geh Zuzeneko oroimen neurria [zuri\=berez,gutx\=%1]
+Scrape.status.error.invalid=Erantzun okerra.
+wizard.close=Itxi
+device.config.ms.maxlines=Multimedia zerbitzari bat bilatzerakoan erakusteko gehienezko sarrerak
+azbuddy.dchat.not.installed=Izengabeko txat sostengua ez dago ezarrita une honetan
+ConfigView.label.ui_switcher_button=Erakutsi
+ConfigView.label.lh.prog=Aplikazioa
+FilesView.title.short=Agiriak
+jvm.options.summary=Oraingo aukeren laburpena\:
+restart.error.denied=Sarbidea ukatua izan da '%1' abiarazten saiatzean. Zihur zaude programa hau abiarazteko eskubidea duzula.
+iconBar.open=Gehitu Torrenta
+ConfigView.label.minPeersToBoostNoSeeds.tooltip=Emaritzen ez dagoen edozein torrent eta zuk adierazitakoa baino hartzaile gutxiagorekin\nlerroaren beherenera mugituak izango dira.
+devices.od.view.heading=Lineaz-kanpoko jeisketarako jeisketa egitarautuak
+ConfigView.section.transfer.autospeed.network.info=Gaineko mugak arrunt berezgaitasunez kalkulatzen dira jeisketan zehar edo abiadura azterketa baten emaitza dira. Eskuz adieraztea nahi badituzu erabili beheko aukerak.\nBeste muga guztiak 'finkoak' ondoren ezarriko dira berezgaitasunez beharrezkoa bada \nSartu balioa eta hautatu mota. Kontuan izan abiadurak direla %1.
+sharing.progress.cancel=Ezeztatu
+label.indirect.connect=Zeharkako Elkarketa
+MagnetURLHandler.report.no_sources=ez da baliabiderik aurkitu torrentarentzat
+Button.done=Eginda
+dht.reseed.port=Ataka
+MyTorrentsView.menu.movetorrent=Mugitu &Torrent Agiria...
+v3.MainWindow.menu.contentnetworks.about=HD Sareei Buruz
+AdvRenameWindow.title=Berrizendatu Jeisketa
+wizard.maketorrents.superseed=Erabili gain-emaritza
+MainWindow.menu.view.stats.keybinding=Meta+5
+SystemTray.tooltip.downloading=%1 jeisten,
+importTorrentWizard.process.importfail.title=Torrentaren inportazioak huts egin du
+device.config.autohide.old.devices=Berez-ezkutatu berriki ikusi ez diren gailuak [egun, 0\: ezgaituta]
+custom.settings.import.res.title=Itxurapen Inportazioa Osatuta
+ConfigView.label.userequestlimiting.tooltip=Eskabidea mugatzea ez da irakurketa atzerapena bezain lehuna, baina ahalbidetzen du jeisketa lehetasunean ohinarrituz, jeisketako lerro kokapena eta sarearen errendimendua hobetzea
+CacheView.writes.toCache=Katxera
+SpeedTestWizard.abort.message.download.added=Azterketan gehitutako %1 jeitsi
+OpenTorrentFile.column.download.info=Jeitsi agiria torrentarekin\nErabili tarte barra hautapen anitz batera aldatzeko
+TableColumn.header.chat.status={TableColumn.header.status}
+DownloadActivityView.legend.down_smooth=Jeisketa (Lehuna)
+proxy.info.title=Proxy Argibideak
+MyTorrentsView.menu.recheck=Behar&tu Berregiaztapena
+UpdateProperty.title=Eguneratu Ezaugarria
+TableColumn.header.swarm_average_speed.info=Erletaldeko hartzaileen bataz-besteko abiadura
+PeerSocket.unknown_shadow_style=Ezezaguna  %1 %2
+Button.createNewSubscription=Sortu Harpidetza Berri Bat
+MagnetPlugin.use.lookup.service=Erabili Vuzeren bigarren bilaketa zerbitzua DHT bidezko erakarpen bilaketak huts egiten badu
+mb.azmustclose.title=Abiatze Akatsa
+ConfigView.label.maxseedspertorrent=Geh. emale torrent bakoitzeko [0\: mugagabea] 
+MyTorrentsView.menu.thisColumn.remove=Kendu Zutabea
+download.removerules.name=Kenketa Arauak
+label.rss=RSS
+PeerManager.status.offline=Elkarketa Akatsa
+br.backup.progress=Babeskopia/Leheneratze Emaitzak
+v3.MainWindow.search.tooltip=Sartu zure bilaketa gaia, magnet lotura, hasha edo torrentaren URL-a eta sakatu sartu\!
+azbuddy.dchat.ui.max.lines=Geh. mezu txat leiho bakoitzeko
+menu.min.share.ratio2=Ezarri Gutxienezko Elkarbanatze Maila
+TagStatsView.title.full=Etiketa Jarduera
+config.changes.title=Itxurapen Aldaketak
+TableColumn.header.savepath=Gordetze Helburua
+GeneralView.label.uploadspeed=Igoera Abiadura\:
+MyTorrentsView.menu.networks=Sareak
+ConfigView.label.watchtorrentfolderinterval=Tartea
+Button.install=Ongi
+ConfigView.section.connection.group.http.info=Sostengua HTTP emaritzarako
+ConfigView.label.opendialog=Berezgaitasunez ireki Eguneratze Laguntzailea eguneraketa eskuragarri dagoenean
+device.lastseen=Azken ikusaldia
+TableColumn.header.networks=Sareak
+azbuddy.ui.add=Gehitu
+GeneralView.label.hashfails=Hash Hutsegiteak\: 
+azbuddy.dchat.share.fail.msg=Hutsegitea %1 elkarbanatzerakoan\:\n\n%2
+ConfigView.pluginlist.shared=elkarbanatuta
+ConfigView.section.security.restorekeys.button=Leheneratu
+TableColumn.header.activityNew=Berria
+ColumnSetup.proficiency=Ontasuna\:
+FilesView.skip.confirm.delete.text=Moztu '%1' agiria tokia gordetzeko?
+ConfigView.section.style.separateProtDataStats=Erakutsi banandurik datu eta hartueman estatistikak 'datu (hartueman)' bezala
+configureWizard.welcome.usermodes=Erabiltzaile Eskumen ezarpen honek zehaztuko du ondoren agertzen diren aukeren maila Tresnak > Aukerak. Zure interes hoberenean da zuzen ezartzea.
+plugin.install.class_version_error=Plugin honek Javaren bertsio berriena behar du lan egiteko.
+configureWizard.welcome.message=Laguntzaile honek zure Vuze modu egokian erabiltzen lagunduko dizu. Itxurapena sakonago aldatu nahi baduzu, erabili Tresnak->Aukerak menua.
+window.update.noupdates.beta.text=Ez dago eguneraketa berririk eskuragarri zuretzat.\n\nAzken beta argitalpen egonkorra (%1) erabiltzen ari zara.\n\nIkusi <a href\="http\://dev.vuze.com/">Beta Programa gunea</a> argibide gehiagorako bietan argitalpen egonkorra eta ezegonkorra.
+security.crypto.persist_for.week=1 aste
+MainWindow.nat.status.probok=NAT Ongi?
+azbuddy.dchat.open.i2p.magnet=Ireki I2P-Bakarrik Magneta Vuzen
+ConfigView.section.connection.advanced.read_select_min=Irakurri hautatutako gutxiezneko itxaronaldia (milaen, berez %1)
+SpeedTestWizard.abort.message.entered.error=Aztertu osoki jeitsitako akats egoera '%1'
+TableColumn.header.mergeddata.info=Jeisketa honetan batutako datu kopurua erletalde batzearen bidez
+devices.state=Egoera
+speedtest.wizard.test.mode.up=igo
+Formats.units.alot=Pilo bat\!\!\!
+CacheView.reads.amount=Zenbatekoa
+ConfigView.section.style.ShowTagButtons.CompOnly=Erakutsi Liburutegiko Osatutako zatian bakarrik
+ConfigTransferAutoSpeed.add.comment.to.log.group=Gehitu aipamena garbiketa saioan
+OpenTorrentTorrent.column.\#=Z
+TableColumn.header.peers.info=Zenbat hartzaile elkarketaturik (Zenbat hartzaile guztira)
+Button.next=Hurrengoa
+azbuddy.dchat.custom=Norbere Kanalak
+ColumnProgressETA.showSpeed=Erakutsi Abiadura
+Torrent.create.progress.piecelength=Atalen luzera\: 
+dialog.uiswitcher.restart.text=Vuzek berrabiaraztea behar du EI modu berrira aldatzeko.
+label.favorites=Gogokoenak
+v3.iconBar.down.tooltip=Mugitu Behera\nEduki saguaren botoia sakatuta beherainok mugitzeko
+devices.xcode.autoCopy.device=Berezgaitasunez Kopiatu Gailura
+beta.wizard.forum=Erabili Vuze eztabaidaguneak jarioak hartzeko akatsen berri izateko
+label.replace=Ordeztu
+MainWindow.menu.help=&Laguntza
+TableColumn.header.tag.downrate={TableColumn.header.downspeed}
+ConfigView.section.stats.xslfiledetails=Hau estatistiken agiriaren idazburuan sartuko da <?xml-estilo-orria> etiketa erabiliz
+window.updateswt.status.downloading=SWT Bertsio Berriena Jeisten
+remote.pairing.subtitle=Hurruneko Vuzek edozin ordenagailu edo mobiletik Vuzeren agintea hartzeko aukera ematen dizu - edonoiz, edonondik.
+ConfigView.label.importdirectory=Inportatu Zuzenbidea
+DownloadManager.error.fileempty=Torrent agiria hutsik dago
+MainWindow.menu.community.blog=Vuze &Bloga
+devices.xcode.setcopyto.title=Hautatu kopiaketa helbidea
+TableColumn.header.md5.info=Agiriarentzako MD5 hasha (osorik jeitsia izan behar da; klikatu kalkulatzeko)downloaded; click to calculate)
+TableColumn.header.name=Izena
+ConfigView.label.showpopuponclose=Erakutsi baieztapen leihoa 1 azpitik dagoen elkarbanatze maila duen emaritzea gelditzean
+PeerManager.status.ps_disabled=Aztarnari hartzaile iturburua ezgaituta dago
+MainWindow.menu.view.stats=Estatistikak
+wizard.multitracker.edit.text.msg=Sartu aztarnari bat lerroko. Banandu talde ezberdinak (mailak) lerro zuri batekin.
+ConfigView.higher.mode.available=Aukera asko erabiltzaile modu askotan dira eskuragarriak
+PeersView.download.info=Hartzailearengandik jeitsitakoa guztira.
+seedmore.title=Torrenta ez dago nahikoa emarituta
+ConfigTransferAutoSpeed.algorithm.selector=Berez-Abiadura hautagailua
+MyTorrentsView.menu.thisColumn.sort=&Antolatu
+window.uiswitcher.NewUI.title=Vuze
+ConfigView.section.mode.beginner.text1=Torrentak jeisteko behar duzun guztia - Bikaina erabiltzaile berriek bezeroaz eta torrentetaz ikasi dezaten.
+Menu.show.torrent.menu=Erakutsi Torrenten menua
+xfs.allocation.xfs_io.not.found=XFS agiriaren esleipenak huts egin du ezin izan delako /usr/sbin/xfs_io exekutatu. Zihurtatu zure sisteman ongi ezarrita dagoela. Jatorrizko akatsa hau izan da\: "%1".
+SpeedTestWizard.stage.message.starting=azterketa hasten...
+MyTorrentsView.dialog.setFilter.text=%1 atala iragazia izan daiteke adierazi duzun idatzirako. Erabili  | (barra-zutia) ikurra iragazteko esaldi askoren artean.
+subscriptions.listwindow.name=Izena
+SystemTray.menu.pausetransfers=Pausarazi Eskualdaketak
+openUrl.url=URL-a\:
+sr_prog.window.title=Garapen Tartea
+wizard.newtorrent.byo.info=Askatu agiri edo/eta zuzenbide hautapena beheko eremuan torrenta eraikitzeko. Klik-bikoitza edo F2 izenak editatzeko.
+label.rename=Berrizendatu  %1
+MainWindow.menu.view.configuration=A&ukerak...
+Button.bar.edit=Editatu
+label.public.short=P
+MainWindow.dht.status.failed=DHT-ak Huts egin du
+ConfigView.label.defaultsavepath=Gorde berezko datu zuzenbidean
+OpenTorrentWindow.mb.notValid.title=Torrent Irekitze Hutsegitea
+label.script.to.run=Ekiteko eskripta
+DiskManager.alert.movefilefails=Akatsa osatutako agiria mugitzerakoan\nAgiri mugitua %1 huts eginda\\, %2
+label.public={subs.prop.is_public}
+ConfigView.label.dm.dblclick=Klik bikoitza torrenten ikuspegietan\:
+Utils.link.visit=Mesedez ikusi
+device.od.space=Toki Eskuragarria
+FilesView.crc32.calculate=Kalkulatu CRC-32 Checksuma(k)
+ConfigView.label.stop.QuitVuze=Itzali Vuze
+label.untagged=Etiketatugabe
+installPluginsWizard.list.version=Bertsioa
+ConfigView.section.tracker.username=Erabiltzaile izena
+ConfigView.section.ipfilter.autoload.info=DAT (eMule), P2P (PeerGuardian, splist), eta P2B v1,2,3 (PeerGuardian 2) heuskarriak sostengatzen ditu. Agiria tokikoa izan daiteke edo URL, zip'd, gzip'd edo idazki laua. URL-ak berezgaitasunez birjeitsiko dira 7 egun ondoren, aldiz agiriak ordeztua/ikutua izan eta minutu batera birgertatzen dira.
+sidebar.header.discovery=Eduki Aurkikuntza
+importTorrentWizard.torrentfile.message=Adierazi inportatu nahi duzun torrent agiria
+MainWindow.menu.speed_limits.view=Ikusi...
+ConfigView.section.mode.intermediate.wiki.host=Agiriak Hostatzen
+MainWindow.upgrade.error.downloading.hint=Akatsa\:\tEzin izan da bertsio berria jeitsi, mesedez eguneratu eskuz
+MyTorrentsView.filter.tooltip=Ktrl+X aldatzeko RegEx eta bilaketa arrunt moduaren artean.\nErabili | (barra-zutia) ikurra iragazteko esaldi askotan.
+ConfigView.section.language=Hizkuntza
+ConfigView.label.userSuperSeeding=Erabili Gain Emaritza
+TableColumn.header.smoothup.info=Igoera Abiadura Lehundua {smooth.config}
+PeersView.connected_time=Elkarketaturiko Denbora
+fileDownloadWindow.retry=Saiatu berriz
+TagAddWindow.public.info=Etiketa elkarbanatzeak beste erabiltzaileei beren jeisketak antolatzen lagunduko die.
+openUrl.referrer=Orrialde URL-ari dagozkionak\:
+DHTView.general.title=Orokorra
+PiecesView.legend.incache=Datua Katxean dago
+SpeedView.stats.estdowncap=Jeisketa muga\:
+TableColumn.header.comment=Aipamena
+PeersView.source=Iturburua
+GeneralView.label.maxuploadspeed.tooltip=geh. igoera abiadura [0 \: mugagabea]
+security.crypto.persist_for.forever=Betirako
+ConfigView.label.hap.tooltip=Ezkutatu osatutako atala
+ConfigView.section.connection.group.networks=Sareak
+MainWindow.menu.file.exit.keybinding=Alt+F4
+devices.comp.missing=Vuze sostengua ezarri gabe dago
+SpeedTestWizard.test.panel.abort=Utzi
+ManagerItem.queued=Lerrokatuta
+ConfigView.section.file.nativedelete._mac=Erabili Zakarrontzia agiriak ezabatzerakoan
+subscript.all.subscribed=Eduki honetara harpideturik zaude
+DHTView.transport.title=Garraio Xehetasunak
+tag.type.ds.init={fileDownloadWindow.state_initializing}
+TableColumn.header.completed.info=Torrentaren jeisketa amaitu duten hartzailea zenbatekoa, aztarnariaren arabera
+subscriptions.view.title=Harpidetzak
+CacheView.speeds.reads=Irakurriak
+subscription.request.add.title={subscriptions.add.tooltip}
+ConfigView.label.queue.debuglog.info=Gehitu lerro garbiketa argibideak kontsola/ohar agirira.\nEnkriptatuta izanda ere, garbiketa argibideak esaten dizu torrentaren egoera eta zergaitik dauden/ez dauden abiatzen/lerrokatzen.
+PiecesView.legend.written=Idatzia
+PiecesView.BlockView.Header=%1 zutabe, %2 lerro, %3 atal
+PiecesView.writers=Blokearen Emaleak
+label.comments=Aipamenak
+ConfigView.section.transfer.autospeed.maxinc=%1 gehienezko gorapena aldi bakoitzeko
+TableColumn.header.tag.color={label.color}
+ConfigView.label.minannounce=Gutxienezko denbora aztarnariaren iragarpenen artean segundutan
+azbuddy.dchat.cannel.import=Kanal Leheneratzea
+authenticator.details=Xehetasunak
+ConfigView.section.connection.group.peersources.info=Hautatu berez baimedutako iturburuak hartzaileen elkarketetatik
+configureWizard.file.browse=Bilatu
+OpenTorrentOptions.header.peeroptions=Hartzaile eta Elkarketa Aukerak
+MyTorrentsView.menu.moveEnd=&Beheren
+ConfigView.pluginlist.unloadSelected=Ezgertatu Hautatua
+device.error.mountrequired="%1" Zure Gailua Tresnatzeko Beharrezkoa
+dht.reseed.label=Arrunt birremaritzen Banaturiko Datubasea ez da beharrezkoa. Horrela ere, elkarketen zenbatekoa apala bada izan daiteke erabilia bir-baterapenerako.\nOrri zuria bereznahiko elkartutako hartzaileentzako edo sartu IP-a eta ataka hartzaile ezagun batetik bereznahikotzeko.
+MainWindow.menu.file.import.keybinding.mac=Meta+Shift+I
+tag.show.overview=Erakutsi Etiketa Gainikuspena...
+wizard.next=&Hurrena >
+MainWindow.status.tooOld=zaharra da, mesedez eguneratu ezazu
+TableColumn.header.SpeedGraphic=Abiadura
+ConfigView.section.interface.clearsavepaths=Garbitu gogoraturiko helburu gordeak
+TableColumn.header.filecount=Agiriak
+SpeedView.stats.now=Orain\:
+ConfigView.section.file.bgdefaultdir.ask=Uste hoberena berez
+ConfigView.section.mode.advanced.text=Sartu sare ezarpenetara.\nErabili modu hau jakitea nahi baduzu zein GIB (Gehienezko Igorpen Batasuna) edo S/I ez itxiak dauden
+MyTrackerView.name=Izena
+props.window.title='%1' -en Ezaugarriak
+AlertMessageBox.information=Argibideak
+pairing.nets.enable=Gaitu sare zerbitzu helbide ez-publikoen erregistatzea
+device.is.disabled=Gailua ezgaiturik dago
+TableColumn.header.crc32.info=Agiriarentzako CRC-32 Egiaztapen-batura (osorik jeitsia izan behar da; klikatu kalkulatzeko)
+ConfigView.section.connection.advanced.IPDiffServ.tooltip=Zerbitzu Mota (TOS) eremuaren DiffServ atala ezartzen du IP buruan irteerako paketeentzat.\nBalio Hexadezimalak aurrezenbaki batez adierazi daitezke '0x', adib. 0x10.\nVuzek hau berez ezarrigabe uzten du, esanahi da azpiko SE-rentzako balio aurrezarriak erabili egiten dira\nOHARRA\: Azpiko sarebideak balio hauek baztertu ditzake, hortaz aukera hau SE eta JavaRuntimeEnvironmet (JRE) bertsioaren oso araberakoa da.
+v3.MainWindow.menu.view.pluginbar=Plugin Barra
+ConfigView.label.noportannounce=Ez iragarri aztarnariari aditze ataka (honek ez die hauei eragiten\: pex, dht )
+OpenTorrentWindow.mb.invaliddefsave.title=Gordetze Kokaleku Baliogabea
+azbuddy.protocolspeed=KB/s geh. lagun harremanaren burugain
+view.waiting.core=Ikustea eskuragarri egon daiteke Vuze Core gertatzen denean
+ConfigView.section.transfer.autospeed.resetnetwork=Berrezarri sare xehetasunak
+ConfigView.label.lazybitfield=Erabili biteremu alperra (laguntzen du emaritzan biteremu-itxipenean ohinarritzen diren sareetan)
+ConfigView.section.file.perf.cache.enable.write=Katxeak datuak jeisten ditu diskaren idazketak gutxitzeko eta baita ere gutxitzen du diskak atal egiaztapenerako egin behar dituen irakurketak
+OpenTorrentWindow.mb.askCreateDir.text='%1' helmuga zuzenbidea ez dago.\n\nOrain sortu?
+MagnetPlugin.report.error=akatsa %1
+ConfigView.label.ui_switcher=Erakutsi Vuze EI Hautatzailea
+MainWindow.nat.status.bad=Suhesiturik
+Scrape.status.scraping=Zuritzen...
+SpeedTestWizard.stage.message.connect.stats=Elkarketa estatistikak\: hartzaileak\=%1, jeisketa_ongi\=%2, igoera_ongi\=%3
+azbuddy.ui.menu.cat.set_msg=Kategoria zerrenda kakotxaz banandurik, edo 'Denak'
+MagnetPlugin.report.ddb_disabled=DDB ezgaituta dago
+SpeedTestWizard.abort.message.execution.failed=Azterketa egiteak huts egin du
+TableColumn.header.DateFileCompleted.info=torrenteko agiri osatze berrienaren eguna
+Wizard.Subscription.title=Harpidetu
+rcm.view.title=Izenburua
+Tracker.tooltip.MultiSupport=Aztarnari honek hash zuriketa anitz sostengatzen ditu eskabide bakoitzeko
+unix.script.new.title=Vuzeren Abiarazpen Eskript Berria eskuragarri
+upnp.mapping.dhtudp=Banaturiko Datubasea
+azbuddy.os_away=Batbatekoa
+ConfigView.section.file.rename.incomplete=Gehitu aurrehizkia osatugabeko agiriei
+MainWindow.menu.community=&Herkidegoa
+TableColumn.header.Thumbnail=Ikurra
+TableColumn.header.azsubs.ui.column.subs_link.info=Harpideekin elkartuta
+ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Erakutsi agiri guztien jeisketa garapena elkarrizketa leihoko egoera barran 
+dlg.auth.install.progress=Ezartzen %1 osagai...
+wizard.multitracker.template.title=Aztarnari Eredu Editatzailea
+menu.max.share.ratio2=Ezarri Xede Elkarbanatze Maila...
+ConfigTransferAutoSpeed.auto.speed.neural=Neurala (Gudy Alpha)
+TableColumn.header.trackername.info=URL iragarpenean ohinarrituriko aztarnariaren izena
+jvm.info=Vuzeren berrabiaraztea beharrezkoa da aukerak aldatu badira. *** Kontuz - JVM aukeren aldaketa okerrak Vuze ez abiatzea edo gaizki jardutea eragin dezake ***\n
+SpeedTestWizard.abort.message.unsupported.type=Azterketa mota ez dago sostengatuta\!\!\!\!
+tag.type.ds.down={ManagerItem.downloading}
+plugins.basicview.config=Itxuratu
+SpeedView.stats.asn=Sarea\:
+StartStopRules.ratioMet=Hartzaileak\:Emaritza Ongi
+ConfigView.section.tracker.pollintervalmin=Gutxienez
+PeersView.title.full=Hartzaileak
+wizard.multitracker.edit.name=Izena
+ConfigView.section.plugins.dhttracker=Banaturiko Aztarnaria
+TableColumn.header.networks.info=Hartzaile-hartzaile harremanerako baimenduriko sareak
+TableColumn.header.trackernextaccess=Hurrengo Aztarnariaren Atzipena
+subscriptions.column.nb-results=Emaitza Denak
+TableColumn.header.CountryCode.info=Hartzailea kokaturik dagoen herrialde kodea (ISO 3166)
+installPluginsWizard.installMode.shared=Ezarri plugina(k) erabiltzaile guztientzat
+wizard.previous=< Atzera
+subs.prop.template=Eredua
+Button.unmark=Desmarkatu
+ConfigView.label.maxuploadspeedseeding=Ordezpen maila emaritzan bakarrik dagoenean
+update.instance.install=Ezarpena Egiaztatzen
+OpenTorrentWindow.mb.existingFiles.title=Agiria jadanik badago\!
+natpmp.enable=Gaitu (jakin ezazu  lan egiteko hegazkaiko itxurapenean ere gaituta egon behar dela )
+set.share.ratio.win.msg=Elkarbanatze maila bat ezartzeak jeisketa/igoera orotara beharrezkora zehazten du\r\n
+ConfigView.section.file.defaultdir.bestguess=Erabili ustezko hoberena gordetzeko zuzenbide berezkoa hautatzerakoan
+cat.autoxcode=Berez-Gailua
+MyTorrentsView.menu.advancedmenu=Aurreratua
+stats.long.weekstart=Asteko zenbaketa hasten da\:
+label.content=Edukia
+v3.MainWindow.tab.events=Jakinarazpenak
+CacheView.speeds.fromFile=Agiritik/Agirira
+v3.iconBar.up.tooltip=Mugitu gora\nEduki saguaren botoia sakatuta gorainok mugitzeko
+ConfigView.section.tracker.publishenabledetails=Argitaratu torrent guztien xehetasunak
+openUrl.url.info=Sostengaturik http, https, magnet eta raw hex infohash kateak
+FileProgress.deleted=Ezabatuta
+TrackerView.title.short=Iturriak
+ConfigView.section.tracker.sslport=Gaitu aztarnaria HTTPS atakan
+ConfigView.section.transfer.autospeed.maxupload.tooltip=Igoera abiadura ez da berez goratzen muga honen gainetik
+ColumnProgressETA.showETA=Erakutsi UED
+label.aggregate.info=Gehitutako Argibideak
+ConfigView.section.stats.savefreq=Gordetze maiztasuna
+devices.info.copypending3=%1 Agiri Itxaroten Kopiatuak Izateko - Gaitu Berez-Kopiatu Edo Hautatu Eskuzko Kopiatzea
+tag.type.ds.pau={ManagerItem.paused}
+devices.info.copypending2=%1 Agiri Itxaroten Kopiatuak Izateko, Elkarketatu Zure Gailua
+wizard.title=Sortu torrent bat
+Plugin.pluginupdate.enablecheck=Gaitu plugin eguneratze egiaztapena
+installPluginsWizard.installMode.info.title=Argibideak
+dht.execute.info=Sakatu komandoa exekutatzeko
+ConfigView.section.proxy.no.local.dns=Saihestu tokiko DNS bilaketa
+PiecesView.DistributionView.weDownload=Jeisten ari zaren atalak
+ConfigView.label.seeding.firstPriority.seedingMinutes=Igarotako denbora jeisten emaritzara aldatu denetik
+ConfigView.label.stop.downcomp=Jeisketa burutu denean
+OpenTorrentWindow.addPosition.last=Azkena
+PiecesView.legend.downloaded=Jeitsita, idazketa itxaroten
+ConfigView.label.maxuploadsseeding=Ordezpen berezkoa emaritzan dagoenean
+label.accept=Onartu
+ConfigView.section.tracker.tcpnonblocking=Erabili S/I ez-itxipena TCP aztarnari jardunerako. Aukera hau hautatzeak web aztarnaia ataka altenatibo batean lanean izatea eskatzen du. Esperimentala\!
+azbuddy.ui.table.rem_cat=Kat sarrera
+ConfigView.section.file.torrent.ignorefiles=Baztertzeko agiriak torrentak sortzen/ezabatzen direnean\n - adib. .DS_Store; Thumbs.db
+sidebar.header.vuze=Vuze
+tps.lan.details=%1 tokiko bezero aurkituta
+wizard.announceUrl=Iragarpen URL-a\:
+device.quit.transcoding.text='%1' da uneko transkodeatzeilea '%2' eta da  %3% osatuta.\nOrain kentzen baduzu beharrezkoa izango da berrabiaraztea hurrengo saio hasieraren abiaratzean.
+rss.internal.enable.low.noise=Gaitu zarata-gutxiko jeisketak (barneko jeisketak, etab.)
+platform.win32.baddll.winsflt=PureSight Interneteko Eduki Garbi Iragazkia
+TagRenameWindow.message=Sartu izen berri bat etiketarentzat
+TableColumn.header.torrentname={authenticator.torrent}
+Button.reset=Berrezarri
+ConfigView.upload.abbreviated=I\:
+metasearch.addtemplate.dup.desc=%1 Bilatu eredua jadanik ezarrita dago
+MagnetPlugin.report.md.starts=Metadatu jeisketa sortuta
+CacheView.title.full=Katxea
+label.visible=Ikusgarri
+ConfigView.label.serverport.tooltip=Ataka 1-65535 artekoa izan behar da, eta ez 6880 Vuzeren barne erabilpenerako gordea dagoena.
+azbuddy.tracker.bbb.status.nli=Saioa Hastea Beharrezkoa da.
+device.error.copytonotset='Kopiatu Agiritegira' Ezarri Gabe
+devices.restrict_access=Sarbidea Ukatu...
+configureWizard.nat.testing=Ataka aztertzen
+device.import.dup.desc='%1' Gailua jadanik badago.
+SpeedTestWizard.test.panel.testfailed=Azterketak huts egin du
+ConfigView.section.server.enablednsrecords=Gaitu istripuzko DDOS-ak hobetzeko erabilitako DNS aztarnari grabaketa kudeaketa.
+webui.user=Erabiltzaile izena
+device.itunes.status.notrunning=iTunes ez dago lanean
+sidebar.LibraryDL=Jeisten...
+PeersView.BlockView.title=Atal Mapa
+MyTorrentsView.menu.host.error.title=Torrentaren Hostatutzeak Huts egin du
+TableColumn.header.tag.moveoncomp={label.move.on.comp}
+iconBar.run=Ireki
+IPChecker.external.service.dyndns.description=DNS Sare Zerbitzu Dinamikoak, LLC
+TrackerAvail.column.peers.info={Trackers.column.peers.info}
+UpdateWindow.status.failed=Huts egin du
+ConfigTransferAutoSpeed.skip.after.adjust=Jauzi zehaztu ondoren\:
+label.unpin=Desfinkatu
+MyTorrentsView.menu.setCategory=E&zarri Kategoria
+dlg.auth.enter.denied=Oraingo eragintza kodea ukatua izan da.
+ConfigView.section.ipfilter.autoload.loadnow=Gertatu Orain
+br.backup=Babeskopia
+ConfigView.pluginlist.column.unloadable=Gertaezina
+PeersView.ip=IP-a
+ConfigView.section.security.resetcerts.error.title={ConfigView.section.security.resetkey.error.title}
+ConfigView.label.set_ui_transfer_speeds=Ezeztatu eskualdaketa abiadura hautagarriak
+ManagerItem.superseeding=Gain-E&maritza
+MainWindow.menu.file.create.keybinding=Meta+N
+azbuddy.ui.menu.chat=Eztabaidagunea
+Scrape.status.cached=Katxe zuritua
+UpdateWindow.header=Hurrengo osagaiek eguneraketa behar dute\:
+MyTorrentsView.menu.rename.displayed_and_save_path=Berrizendatu Erakutsitako Izena eta Gorde Helburua
+ConfigView.label.bStartNoMoreSeedsWhenUpLimitMetPercent=Gaineko hurbilketa ehuneko bat da (ezhautatu osorako)
+sidebar.LibraryCD=Osatuta
+TagAddWindow.title=Gehitu Etiketa Berria
+ConfigView.pluginlist.loadSelected=Gertatu Hautatua
+AdvRenameWindow.rename.torrent=Berrizendatu Torrenta
+subscript.add.dup.title=Bikoiztu Harpidetza
+ConfigTransferAutoSpeed.ping.time.bad=Gaitza\:
+IrcClient.connecting=Elkartzen hona\:
+dlg.stream.plus.renew.subtext={dlg.stream.plus.subtext}
+ConfigView.label.overrideip.tooltip=Jakinarazi aztarnariari irteera paketeetatik datozen IP helbide ezberdinak. Utzi hutsik aukera hau ez erabiltzeko.
+tps.type.dht=DHT (Banaturiko Hash Taula)
+ConfigView.section.tracker.sendpeerids=Bidali hartzailearen nortasuna jeistzaileetara
+FileItem.storage.compact=Trinkotua
+tag.property.tracker_templates={label.tracker.templates}
+security.crypto.password2=Sartu berriro sarhitza
+TableColumn.header.comment.info=Jeisketarako erabiltzaile-zehaztuaren aipamena
+ConfigView.boolean.ircsendinfo=Baimendu zure ezarpenak bidaltzea (modu izengabean)\n kanal eragileei, laguntza eman ahal diezazuten
+MainWindow.menu.file=&Agiria
+FilesView.rename.confirm.delete.text=Baieztatu jatorrizko agiriaren ezabapena '%1'
+SpeedView.stats.autospeed=Berezgaitasunezko Igoera Abiadura (Erakusten %1 sm)
+MainWindow.menu.speed_limits.schedule.title=Abiadura Muga Egitarupena
+ConfigView.section.style.library=Izena
+devices.cancel_xcode=Ezeztatu Bihurketa
+ColumnSetup.availcolumns.filteredby=Eskuragarri %1 zutabe iragazita %2
+IrcClient.nowknown=orain honela ezagutua da\:
+ConfigView.section.logging.enable=Gaitu agirira ohartzea
+device.od.group=Izenburua
+PiecesView.title.short=Atalak
+ClientStats.column.name=Izena
+ConfigView.section.interface.alerts=Alertak
+TableColumn.header.totalspeed=Abiadura Guztira
+MainWindow.menu.file.share.file=&Agiria...
+device.playnow.min_buffer=Buffer neurria eta birbufferreratze gertaerak [seg]
+MyTorrentsView.menu.edit_comment.enter.title=Aipamena Argitaratu
+iconBar.share.tooltip=Elkarbanatze Edukia
+UpdateWindow.restart=Berrabiarazi Vuze Orain
+pairing.srp.info=Hurruneko zenbait aplikaziok biak sostengatzen dituzte elkarketagarritasuna eta segurtasun handitzea 'hurruneko segurtasun sarhitza' protokoloa erabiliz eta, aukeran, proxy elkarketak elkarketagarritasuna handitzeko.\n\nBegiratu hurruneko aplikazioaren agiritza honetaz baliatu zaitezkeen ikusteko.
+OpenTorrentWindow.addPosition.first=Lehena
+MainWindow.dialog.share.sharedir=Hautatu Elkarbanatzeko Agiritegia
+security.certtruster.no=Ez
+ConfigView.section.tracker.pollintervalmax=Gehienez
+delete.partial.files=Jeisketa bat liburutegitik kentzerakoan ezabatu agiri zati guztiak 'ez jeitsi' edo 'ezabatu' bezala hautaturiko hauentzat
+PeersView.statup.info=Hartzailearen igoera abiaduraren ustezko balioa
+MainWindow.menu.beta.on=Gozatu Beta Programa...
+SpeedTestWizard.name.conf.level.med=Ertaina
+MagnetPlugin.report.secondarylookup=Bigarren bilaketa zerbitzuarekin saiatzen
+upnp.refresh.button=Berritu
+LoggerView.clear=&Garbitu
+ConfigView.section.stats.exportfiles=Esportatu agiri xehetasuanak
+label.inbound=Barrurakoa
+window.uiswitcher.ClassicUI.text=*Bezeroaren eginkortasun 2.x serieak gordetzen ditu\n\n* Hegats erakuste klasikoa
+tps.type.incoming=Barrurantz
+ConfigView.section.UPnP=UPnP
+PiecesView.legend.requested=Eskabidetuta
+ConfigView.section.tracker.sslport.info=Ikusi SEG argibide gehiagorako
+ConfigView.section.tracker.client.readtimeout=Irakur itxaronaldia (seg)
+TagDiscoveriesView.menu.tagit=Esleitu Etiketa
+ConfigView.section.file.showopentorrentoptions=Torrent bat irekitzerakoan, erakutsi aukerak elkarrizketa\:
+ConfigView.section.file.perf.cache.notsmallerthan=Ez hau baino katxe agiri txikiagoak (%1)
+TrackerAvail.column.leechers={Trackers.column.leechers}
+torrent.fix.corrupt.result.title=Eragiketa Emaitza
+FilesView.remaining=Gelditzen diren atalak
+devices.on.demand=Eskabidean
+ConfigView.section.ipfilter.list.title=Eragotzitako IP-ak
+v3.MainWindow.tab.minilibrary=Jeisketak
+mdi.entry.about.plugins=Pluginei Buruz
+upnp.alert.multipledevice.warning=UPnP gailu anitz atzeman dira - egiaztatu denak behar duten ataka izendapena (ikusi UPnP sarrera eta itxurapena)
+jvm.error=Akats bat egon da JVM aukeretara sartzean\: %1
+TableColumn.header.fileext=Agiri Mota
+xcode.deletedata.message=Zihur zaude behinbetirako ezabatu nahi duzula '%1' transkodeaketa kopia '%2'%3?
+ConfigView.label.max_peers_per_torrent=Geh elkarketa torrent bakoitzeko [0\: mugagabea]
+pairing.srp.setpw=Eguneratu zure uztarpen seguru sarhitza
+ConfigView.section.tracker.web=Webgunea
+MyTrackerView.bytesout=Irt. Byte
+PeersView.pieces=Atalak
+plugin.sharing.torrent.remove.veto=Aztarnari erregistro hau elkarbanatze baliabide baten emaitza da.\nJeisketa kentzeko elkartutako elkarbanatzea kendu\: joan Tresnak->Nire Elkarbanatzeak
+azbuddy.dchat.create.join.key=Sortu/batu norbere kanala\: giltza
+mdi.entry.plus.full=Vuze Plus
+CacheView.general.title=Katxe Argibideak
+beta.wizard.intro.title=Bazkidetasun hautapena
+#
+# 2.0.7.x
+#
+Categories.all=Denak
+security.certcreate.country=Bi hizkiko estatu kodea
+MainWindow.menu.window.zoom=&Zooma
+ConfigView.download.abbreviated=J\:
+MainWindow.menu.plugins.uninstallPlugins=Ezarpena &Kentzeko Laguntzailea...
+subscriptions.column.SubWizName={FilesView.name}
+ConfigView.section.ipfilter.totalIPs=%1 IP itxita guztira,  internetekoak %2 
+TableColumn.header.Speed=Abiadura
+ConfigView.section.tracker.client=Bezeroa
+label.nat.proxies=NAT/Proxyak
+ConfigView.section.file.perf.cache.flushpieces=Idatzi atal osatuak berehala diskan. Honek diska sarbidea lehuntzen du baina idaz eragiketa gehiago egin daitezke 
+MagnetPlugin.report.md.progress=Metadatu jeisketa garapena\: %1
+UIDebugGenerator.complete.title=Garbiketa Sortzea Ezeztaturik
+network.ipv4.prefer.stack=Hobetsi IPv4 piloa - erabili IPv4 eta IPv6 pilo bananduak bitariko-pilo aplikazioaren ordez
+ConfigView.label.set_ui_transfer_speeds.description=Eskuz zehaztu ditzakezu sistemaren erretiluko egoera barran eskuragarri egongo diren berezko igoera eta jeisketa abiadurak.\nBalioak kakotxaz bananduta idatzi behar dira.
+ConfigView.label.maxdownloads.short=Geh. aldibereko jeisketak [0\: mugagabe]
+SpeedTestWizard.test.panel.aborted=Azterketa eskuz utzita
+ConfigView.label.stop.Shutdown=Itzali Ordenagailua
+azmsgsync.install=Ezarri Mezu Aldiberetze Plugina
+FilesView.menu.setpriority=&Ezarri Lehentasuna
+MyTorrentsView.dialog.setPosition.text=Sartu kokapena hautatutako torrentak ezartzeko\:
+device.import.dup.title=Bikoiztu Gailua
+Formats.units.kbit=kbit
+metasearch.addtemplate.done.desc='%1' eredua ongi gehitu da.\nHurrengo bilaketan erabili dezakezu\!
+ConfigView.section.color=Margo Itxurapena
+devices.choose.profile.info.title.selected=%1 xehetasunak\:
+SpeedTestWizard.test.panel.encrypted=enkriptatuta
+Peers.column.client_identification=Bezero Nortasuna
+MainWindow.menu.view.clientstats=Bezero Estatistikak
+label.checking.comments=Erabiltzaile aipamenen eta mailaketen eskuragarritasuna egiaztatzen
+PiecesView.speed.info=Hartzaile geldoenek eragotzita dute atal askoz azkarragoekin nahastea
+FilesView.name=Izena
+MyTorrentsView.menu.checkfilesexist=Egiaztatu Dauden Agiriak
+ConfigView.pluginlist.column.name=Izena
+v3.MainWindow.button.run=Jaulki Jeitsitako Agiria
+configureWizard.transfer.message=Hautatu azpian adierazitako elkarketetako bat. Kontuan izan igoera abiadura aski handia ahalbidetzen ez bada, jeisketa abiadura motela izango dela. Igoera abiadura torrent BAKOITZEKO bakarrik zenbatzen denez, torrent gehiegi aldi berean jeisteak ere abiadura moteldu dezake. Gutxienezko HERTSI gisa, torrent bakoitzeko 5KB/s erabiltzea aholkatzen dugu. Azkarrago igotzen baduzu, azkarrago jeitsiko duzu (torrentaren abiadurarekin alderatuz gero).
+devices.od.turnon.learn=Jakin gehiago >
+MainWindow.menu.help.debug=Sortu Garbiketa Argibideak (Matxura oharra)
+LocaleUtil.section.chooseencoding=Hautatu kodeaketa agiri izenerako
+ConfigView.section.transfer.autospeed.reset=Berrezarri balio aurreratuak
+MainWindow.menu.speed_limits.reset=G&arbitu Oraingo Mugak
+v3.mb.delPublished.text=KONTUZ\: Ekintza honek EZ du argitaraturiko zure edukia kenduko '%1' hemendik <A HREF\="%2">%3</A> .\n\nKlikatu "Ezabatu" zure edukiak argitaraturik eta jeisgarri nahi badituzu bakarrik, baina zure bandazabalera askatzea nahi baduzu. Egin aurretik zihurtatu zaitez igoera aurrerabidea burutu dela (<A HREF\="%4">nola</A>?).\n\nKlikatu "Ezeztatu" argitaraturiko zure edukiak erabat kentzea nahi badituzu %3, eta erabili (X) botoia Argitaraturiko Edukia leihoan Argitalp [...]
+Button.continue=Jarraitu
+ConfigView.label.ircchannel=Kanala
+Torrent.create.progress.hashing=Agirien hasha sortzen
+ConfigView.section.mode.beginner.text=Torrentak jeisteko behar duzun guztia.\nErabili modu hau nahi duzun guztia zure torrentak kudeatzea bada.
+externalLogin.explanation="%1" ereduak izen-emanda egotea eskatzen du>. Egindakoan leiho hau berezgaitasunez itxiko da. Egiten ez badu mesedez klikatu "eginda".
+Menu.show.torrent.menu.tooltip=Erakutsi Torrenten menua menubarraren gorenaldean
+PeerManager.status.finishedin=Amaituta
+security.certtruster.issuedto=Nori Jaulkia\:
+Torrent.create.progress.parsingfiles=Agiriak aztertzen
+Progress.reporting.window.remove.auto=Berezgaitasunez kendu jarduera gabeko gaiak 
+SpeedView.stats.upload=Lerrokatutako igoera datuak\:
+stats.display.group={ConfigView.section.display}
+ConfigView.section.style.osx_small_fonts=Erabili hizki txikiak [berrabiaraztea beharrezkoa]
+UpdateWindow.status.done=Eginda
+platform.win32.baddll.netdog=Armor2net Suhesi Pertsonala
+custom.settings.import=Zihur zaude '%1'-rako itxurapen ezarpenak inportatzea nahi dituzula?
+devices.sidebar.oxc.nothing=Ezer ez
+GeneralView.menu.selectTracker=Hautatu
+devices.associate.already=Jadanik elkartuta
+DHTTransport.report.complete=osatuta
+# > 2402
+popup.download.finished="%1" jeisketa amaituta.
+device.upnp.desc_url=Gailuaren Azalpena
+rcm.rc_hash.tt=Klikatu eduki hau jeisteko
+security.certcreate.alias=Ezizena
+FilesView.menu.rename=Berrizendatu edo Birxedetu
+# This is the end of the word "View".  It's left aligned under the icon bar item
+v3.iconBar.view.small=si
+Tracker.announce.ignorePeerSeed=Baztertzen Hartzaile/Emaritza zenbaketa. %1
+ConfigView.section.tracker.publicenable.info=Honek besteei ahalbidetzen die zure aztarnaria erabiltzen duten torrentak sortzea\nzuk haiek hostaturatu/argitaratu gabe
+MyTrackerView.category=Kategoria
+ConfigView.label.moveonlyusingdefaultsave=Datuen berezko zuzenbidean bada bakarrik
+label.merge=Batu
+MainWindow.menu.file.closewindow.keybinding=Meta+Shift+W
+Progress.reporting.window.remove.now=Kendu jarduera gabeko gaiak
+SpeedTestWizard.finish.panel.auto.speed=Berez-Abiadura da\:
+pairing.srp.registering=Erregistratzen...
+subs.prop.high_version=Aurkitutako bertsio handiena
+ConfigView.section.tracker.logenable=Ohar-agiritu aldizkako estatistikak 'aztarnari.oharrak'-rako
+beta.wizard.title=Beta Bertsioaren Ezarpena
+menu.open.torrent={torrent.fix.corrupt.browse}...
+dlg.install.azemp.subtitle=Azpidatziak
+OpenTorrentWindow.mb.noGlobalDestDir.text=%1' helmuga zuzenbidea baliogabea da.
+ConfigView.label.zeronewfiles.tooltip=Zatikatzea gutxiagotzen du
+MainWindow.dialog.choose.file=Hautatu torrent agiria
+TableColumn.header.name.ext=Agiri Mota\: %1
+window.updateswt.status.downloading.updater=Eguneratze Moduloa Jeisten
+azmsgsync.install.description=Mesedez itxaron Mezu Aldiberetze Plugina ezertzen den bitartean
+DevicesOD.column.od_name=Izena
+v3.mb.PlayFileNotFound.title=Agira Ez da Aurkitu
+ConfigView.section.language.info=Gaituta dagoenean,  eguneratze egiaztapena Vuze abiarazten den bakoitzean egingo da.
+ConfigView.section.stats.xslfile=XSL agiri izena
+core.shutdown.xcode=transkodeaketa osatuta
+TableColumn.header.smootheta=UED Lehundua
+VivaldiView.title.full_v6=Vivaldi IPv6-a
+label.date.format=Egun Heuskarria
+ConfigTransferAutoSpeed.auto.speed.beta=Berez-Abiadura (beta)
+TableColumn.header.health.info=Zure elkarketak torrenteen erlateldeko elkarketan duen osasuna
+ConfigView.text.ignore=Baztertu
+RCM.column.rc_rank=Maila
+configureWizard.transfer.maxUpSpeed=Gehienezko Igotze Abiadura (KB/s)
+label.anon.chat=Txat Izengabea
+IrcView.clientsconnected=erabiltzaileak
+azneti2phelper.install.reason.decentralised=Gehitu duzun torrenta erabat deszentralizatua da. Badaiteke torren honen erletaldea I2P bakarrik izatea.
+dialog.associations.askagain=Egiaztatu hasitakoan
+tag.property.untagged={label.untagged}
+ConfigView.section.security.resetcerts.error.msg=Hutsegitea egiaztagiri biltegia berrezartzerakoan zergaiti ezezagun bategaitik, mesedez ikusi eztabaidaguneak laguntzarako
+GeneralView.label.peers=Hartzaileak\:
+ConfigView.section.connection.networks.Tor=The Onion Router (Tor) sarea
+ConfigView.label.playfilespeech=Hitzegin agiri batek amaitu duenean
+library.tag.header='%1' Etiketa
+jvm.max.mem=Geh Piloaren oroimen neurria [zuri\=berez,gutx\=%1]
+ConfigView.section.ipfilter.autoload.group=Berez Gertatzen
+ConfigView.section.tracker.passwordenableweb=Gaitu sarhitza aztarnariaren webean
+Button.ok=&Ongi
+ConfigView.pluginlist.column.type.perUser=Erabiltzaileko
+MyTorrentsView.menu.setUpSpeed=E&zarri Igoera Abiadura
+OpenTorrentWindow.dataLocation=Datuak gordetzeko helbidea\:
+MyTorrentsView.menu.trackername.editprefs=Editatu Hobetsitako Aztarnari Erakuspena...
+PiecesView.typeItem.1=Azkarra
+AlertMessageBox.error=Akatsa
+PiecesView.typeItem.0=Astiroa
+ConfigView.section.connection.port.rand.range=Ataka Maila [gutx-geh]
+window.update.noupdates.title=Egiaztatu Eguneraketa Emaitzak
+ConfigView.section.style.useFancyTabs=Erabili Apain Hegatsak
+ConfigView.label.seeding.autoReposition=Berezgaitasunez birjarri Emaritza Lerrunean ohinarrituriko torrentak
+beta.wizard.on=Eguneratu azken beta bertsio egonkorrarekin mesedez.
+Peers.column.timetocomplete=Gelditzen den Denbora
+ConfigView.section.proxy.testsocks.title=SOCKS elkarketa aztertzen
+ConfigView.section.downloadManagement=Jeisketa Kudeaketa
+config.external.browser.info2=Arrunt zure ordenagailuaren berezko nabigatzailea erabiltzen da. Hau aldatu dezakezu nabigatzaile bereizi bat erabiltzeko, edo plugin batek hornitzen duena (adib. Tor Nabigatzaile plugina)
+config.external.browser.info1=Kanpoko nabigatzailea web edukiak bezerotik kanpoko nabigatzaile banandu batean erakusteko erabiltzen da, adibidez bilaketa emaitzen xehetasun orrialdeak
+tag.type.man.vhdn={sidebar.VuzeHDNetwork}
+MainWindow.menu.file.open.uri.keybinding=Meta+U
+ActivityView.legend.achieved=Erdietsitako neurria
+dialog.add.peers.title=Gehitu Hartzailea(k)
+devices.choose.device.info.title=Gailu Mota
+installPluginsWizard.list.title=Plugin Ezarrigarrien Zerrenda
+TorrentInfoView.title.full={GeneralView.section.info}
+TableColumn.header.health=Osasuna
+ConfigView.label.sleep.download=Jeisten
+Button.no=&Ez
+Scrape.status.ok=Zuritzea Ongi
+azbuddy.dchat.public.beta=Txat publikoa beta
+pairing.status.info=Egoera
+DownloadActivityView.legend.down=Jeisketa
+fileplugininstall.install.desc=Zihur zaude '%1' pluginaren, %2 bertsioa ezarri nahi duzula?
+MainWindow.menu.speed_limits.view_current=Ikusi Oraingoa...
+azbuddy.dchat.rchans.managed=Kudeatutako Kanal Berria
+IrcClient.noNick=Ez da Izenorderik Adierazi. Mesedez joan 'Aukerak' Ikusi-ra
+Peers.column.client_identification.info=Adierazten du Vuzetik jasoriko bezero izenak - erabilgarria garbiketarako
+MainWindow.menu.transfers.pausetransfers.keybinding=Meta+P
+Categories.uncategorized=Kategoriatu gabeak
+MySharesView.title.full=Nire Elkarbanatzeak
+DiskManager.alert.movefileexists=Akatsa osatutako agiria mugitzerakoan\nAgiria %1 jadanik badago Mugitu Hona helbide zuz
+MyTorrentsView.menu.start=&Hasi
+dht.enabled=Gaitu banaturiko datubasea
+v3.mb.PlayFileNotFound.button.remove=Kendu Vuzetik
+window.updateswt.status.done=Berrabiarazten
+TableColumn.header.transcode_name=Izena
+MainWindow.updateavail=Klikatu hemen eguneraketak bilatzeko
+TableColumn.header.secondsdownloading=Jeisten
+Button.bar.share=Elkarbanatu
+ConfigView.section.transfer.speeds.wiki=Abiadura oneko ezarpenak
+Views.plugins.UPnP.title=UPnP-a
+ConfigView.section.ipfilter.discardminkb=Gutxienez %1 baztertuta bataz-bestekoa ezarri aurretik
+MainWindow.menu.view.open_global_transfer_bar=Eskualdaketa &Barra
+devices.copy.fail=Gailura kopiatzeak huts egin du
+IrcClient.channel=Kanala
+SpeedTestWizard.abort.message.insufficient.slots=Ezin da igo edozein hartzailetara - ez dago nahikoa igoera aho?
+FilesView.rename.choose.path.dir=Hautatu zuzenbide berri bat edo lehendik dagoen bat
+Main.parameter.usage=Erabilera\: java org.gudy.azureus2.cl.Nagusia [neurriak] "agiria.torrent" "gordetze helburua"
+ConfigView.section.mode.intermediate=Tartekoa
+FilesView.header=Izenburua
+label.chat.type=Txat Mota
+ConfigView.section.file.decoder.prompt=Galdetu betik kodeaketa aukera eskuragarri dagoenean
+label.edit.trackers=Editatu Aztarnariak
+torrent.comments.title=Aipamenak/Mailaketak '%1'-rentzat
+v3.MainWindow.menu.view.asSimpleList=Zerrenda Arrunta
+ManagerItem.waiting=Itxaroten
+config.external.browser.select=Nabigatzaile hautapena
+ConfigView.text.peers=Hartzaile
+wizard.maketorrent.auto=Berez
+ConfigView.section.tracker.publicenable=Gaitu kanpoko torrentak
+v3.mb.PlayFileNotFound.button.find=Eskuzko Bilaketa.
+MyTrackerView.left=Egiteke
+azbuddy.dchat.copy.channel.pk=Giltza Publikoa
+GeneralView.section.transfer=Eskualdaketa
+PluginDeprecation.alert=Plugin bat etorkizunean kenduko den egokitzapen bat erabilitzen saitu da. - mesedez ireki Plugin Garbiketa argibide gehiago ikusteko.
+GeneralView.label.trackerurl.tooltip=Egin klik iragarpen URL-a gakora kopiatzeko
+UIDebugGenerator.messageask.title=Garbiketa Sorgailua
+Views.plugins.azbuddy.title=Lagunak
+ConfigView.section.global=Orokorra
+ConfigView.section.style.useUnitsRateBits=Erabili bitak byten ordez byte-ohin neurri balioetan  (KiB/s->Kibit/s etab.)
+ConfigView.label.StartUIBeforeCore=Hasi EI Core Abiarazpenaren aurretik
+device.rss.group=Tokiko RSS Jarioa
+MainWindow.menu.speed_limits.wiki=Wiki Laguntza...
+ConfigView.label.please.visit.here=Mesedez ikusi hemen xehetasunak
+MainWindow.menu.file.exit=I&rten
+device.import.desc=Zihur zaude '%1' gailua inportatu nahi duzula?
+GeneralView.no=Ez
+Tracker.tooltip.NoMultiSupport=Aztarnari honek ez ditu hash zuriketa anitz sostengatzen eskabide bakoitzeko./nHonek ez du eragiten zure egintzan baina gainzama bat ezartzen du aztarnarian.
+MainWindow.dialog.choose.folder=Hautatu torrent agiriaren zuzenbidea
+azbuddy.os_online=Online
+MainWindow.menu.file.configure=Itxurapen &Laguntzailea...
+MainWindow.about.internet.contributors=Laguntzaileak
+azbuddy.dchat.rchans.rand=Zorizko Azpi-Kanala
+ConfigView.label.set_ui_transfer_speeds.description.download=Ezarri jeisketa abiadurak (KB/s)
+ConfigView.label.resume.downloads.on.start=Berrekin pausaturiko jeisketak hasterakoan abiatzea osatuta dagoenean
+ConfigView.section.connection.http.port=Sarrera ataka zenbakia
+ConfigView.section.stats.exportpeers=Esportatu hartzaile xehetasunak
+ConfigView.section.file.subfolder.dnd=Mugitu jeisteko ez hautaturiko agiriak azpiagiritegira
+FilesView.firstpiece=Lehen atala 
+pairing.explicit.info=Arrunt IP ezaugarriak ez dira adierazi beharrezkoak berezgaitasunez eratorriak izan daitezkeelako.\n'Hostalari' ezaugarria erabilia izan daiteke, adibidez, DynDNS kontu bat baduzu eta software bezero egoki bat zure IP dinamikoa zuzen izen-emanda gordetzeko.
+azbuddy.dchat.copy.i2p.magnet=Kopiatu I2P-Bakarrik Magneta Gakora
+Views.plugins.Plugin.Update.title=Plugin Eguneratzea
+ConfigView.section.logging.showLogsFor=Erakutsi  %1 oharrak hurrengo kategorientzat\:
+ConfigView.section.connection.http.portoverride=Aztarnariaren HTTP ataka ezabatu [0\: bat ere ez]
+azbuddy.dchat.anon.share.endpoint.info=Zorigaitzez oraingoz ezinezkoa da helmuga bananduak erabiltzea
+TableColumn.header.chat.fave={label.fave}
+SystemTray.menu.show=&Erakutsi Vuze
+TransferStatsView.legend.pingaverage=Bataz-bestekoa
+subscriptions.listwindow.failed=Ez da harpidetzarik Aurkitu
+iconBar.publish.tooltip=Argitaratu
+torrent.view.info.title=Torrentaren argibideak
+device.xcode.whenreq=Beharrezkoa denean
+TableColumn.TorrentStream.tooltip.expand=Handitu lerroa Irakurri Orain ikusteko banakako agirientzat
+tag.search=Bilatu Herkidegoa...
+aznettorbrowser.install=Ezarri Tor Nabigatzailea Plugina
+UpdateWindow.columns.name=Izena
+dlg.auth.enter.subtitle.try.2=Balioztapenak huts egin du
+v3.MainWindow.menu.view.tabbar=Hegats Barra
+dlg.auth.enter.subtitle.try.1=Ia han.
+azbuddy.ui.menu.disconnect=Eten
+option.askeverytime=Galdetu Betik
+ConfigView.section.language.UpdateNow=Eguneratu Orain\!
+ConfigView.section.file.config.currentdir=Oraingo itxurapen zuzenbidea\:
+TrayWindow.menu.show=&Erakutsi Vuze
+Pieces.column.Requested.info=Erakusten du atalean eskabide gehiago egin daitezkeen edo ez (*)
+ConfigView.label.seeding.ignoreRatioPeers=Ezikusi bakoitzeko emaritza 1 duten torrentak
+PeersView.menu.blockupload=Blokeatu Igoera
+dlg.auth.install.failed.text=Kodearen eragintza '%1' hutsegitea zerbitzari akats bategaitik.\n\nMesedez saitu zaitez eragintzarekin geroago (jakinarazitako akatsa zen '%2')
+Trackers.column.interval.info=Galdetze tartea segundutan\: tartea (gutx. tartea)
+MagnetPlugin.report.searching=bilatzen...
+dht.reseed.info=Birremaritu datubasea
+TableColumn.header.tag.public={ConfigView.pluginlist.column.type.shared}
+config.internal.browser.info3=Proxy bat erabili daiteke edukia ez-zuzenean lortzeko, ezarrita dagoenean (adib. Tor Laguntzailea pluginak hornitua)
+config.internal.browser.info2=Berez Internet Explorer erabiltzen da Windows, Safari eta Mac-en. Firefox-ren bertsioak *Mugatuta* erabili daitezke ordez - ikusi hurrengo aukerak
+Subscription.menu.clearall=Markatu Emaitza Guztiak Irakurrita Bezala
+subscript.add.upgradeto.desc='%2' harpidetzaren %1 Bertsioa eskuragarri dago.\nEguneratzea nahi duzu?
+Wizard.Subscription.subscribe.title=Harpidetza Eskuragarriak
+config.internal.browser.info1=Barneko nabigatzailea erabiltzen da bezeroan barneraturiko web edukia erakusteko, adibidez Vuze HD Sare orrialdea
+ConfigView.section.interface.display.suppress.file.download.dialog=Ezabatu Agiri Jeisketa oharleiho elkarrizketa
+PeersView.piece.info=Hartzaile honetatik eskabideturiko \# azken atala
+DownloadActivityView.legend.up=Igoera
+ConfigView.section.tracker.forceport=Behartu hostatutako kanpoko torrentak berezko ataka erabil dezaten
+v3.topbar.menu.show.frog=Da Igel Urdina
+torrent.comment.azrating.install=Mailaketa Plugina ez dago ezarrita - ikusi Tresnak-> Pluginak-> Ezarpen Laguntzailea
+ConfigView.label.announceport=Ordeztu iragarritako TCP ataka aztarnari iragarletzatarako, pex eta dht\n[utzi hutsik\: ez ezeztatu, 0\: sarrera elkarketarik ez]
+ConfigView.section.stats=Estatistikak
+Column.seedspeers.started=%1 %2-tik
+subscriptions.enter.freq=Sartu berritze maiztasuna minututan
+ConfigView.section.invalid.value.title=Balio Okerra
+DHTView.transport.in=Sarrera\:
+ConfigView.label.seeding.rankType.seed.tooltip=Emaritza Gutxiago \= Lerrun Handiagoa
+azbuddy.enabled=Gaituta
+dhttracker.alt_group=Aukerazko Aztarnaketa
+ConfigView.section.connection.networks.I2P=I&2P sarea
+plugin.init.load.failed=Akatsa '%1' plugina %2-tik gertatzerakoan
+message.confirm.delete.title=Baieztatu Ezabaketa
+dht.reseed.group=Birremaritu
+ConfigView.label.quickviewexts=Agiri luzapen ikuspen azkarra
+sidebar.Library=Liburutegia
+ConfigView.label.switchpriority=Berez-aldatu lehentasun apalera emaritzean
+PeersView.menu.kickandban=Ostikoa eta Eragotzi
+subs.prop.last_scan=Eginiko azken eguneraketa
+IPChecker.external.service.no-ip.description=DNS zerbitzu dinamiko eta estatikoen hornitzailea (ez du 'egiaztatu helbidea' zerbitzu askerik)
+devices.ready=Gertu
+device.od.error.opfailexcep=Gailuak huts egin du komando hau prozesatzerakoan %1\: salbuespena %2
+TableColumn.header.OnlyCDing4=CDing4 Bakarrik
+label.learnmore=Jakin Gehiago
+dlg.install.vuzexcode.subtitle=Multimedia Aztergailu osagaia ezartzen
+TableColumn.header.TableColumnChosenColumn=Hautatu Zutabea
+Subscription.menu.setcookies=Ezarri Cookiak
+iconBar.run.tooltip=Ireki berezko programa erabiliz
+ConfigView.label.stop.RunScript=Ekin Eskripta
+ConfigView.section.tracker.maxposttimemultiplier.info=Azpieginkizunetarako eta igoeretarako erabilia
+azbuddy.tracker.bbb.status.title=Lagun Kitzikapena
+Button.swarmit=Erletaldetu\!
+GeneralView.label.status.file=Agiriaren Egoera
+GeneralView.label.creationdate=Sortua\:
+ipCheckerWizard.service.description=Azalpena\:
+subscription.version.bad='%1' Harpidetza ezin da ezarri Vuze eguneratu arte
+ConfigView.section.tracker.enablekey=Gaitu giltza sartzea aztarnariarentzat segurtasuna hobetzeko
+platform.jvmopt.nolinkfile=Ezin dira JVM aukerak kudeatu migrazioa osatu gabe dagoelako
+ColumnRenameWindow.message=Sartu zutabearentzako izen berria, hutsik berrezartzeko
+upnp.grabports=Ataken mapaketa egin beste ordenagailu batekoak izanda ere
+ConfigView.section.security.clearpasswords.button=Berrezarri
+ConfigView.label.seeding.ignore.header.evenFirstPriority=Baztertu baita ere \nLehentasun Nagusia arauak ezarrita dituzten torrentak
+Button.revert=Jauzi atzera
+uninstallPluginsWizard.list.title=Ezarritako Plugin Zerrenda
+UpdateConstraint.message=Sartu etiketari ezartzeko mugak - ikusi Wikia xehetasunetarako.
+azbuddy.online_status=Online Egoera
+ConfigView.section.logging.log1type=Kontuz
+OpenTorrentOptions.header.filesInfo.all=%1 Agiri\: %3
+ConfigView.section.start=Hasi
+MyTrackerView.title.full=Nire aztarnaria
+devices.copy.device.auto=Berezgaitasunez kopiatu agiriak gailura
+PeersView.discarded=Baztertua
+metasearch.import.select.template.file=Ireki Eredua
+download.removerules.unauthorised.data=\tKendu datuak
+device.onlyShowTagged=Erakutsi Bakarrik Etiketaturiko Gailuak
+MainWindow.sr.status.tooltip.poor=Elkarbanatze Maila %1 gutxi\: < 0.9
+wizard.webseed.title=HTTP Emaritzak
+ConfigView.label.queue.debuglog=Gorde garbiketa argibideak
+ConfigView.section.ipfilter.add=Gehitu
+chat.view.enter.key.msg=Sartu zure txatarentzako kanal giltza
+Button.swarmit.tooltip=Bilatu neurri bereko agiriak Erletalde Aurkikuntzak erabiliz
+ConfigView.label.playfilefinished=Jo soinu bat agiri batek amaitu duenean
+MySharesView.type.dircontents=Zuzenbide edukiak
+importTorrentWizard.importfile.invalidPath=Inportazio agiri baliogabea
+TableColumn.header.trackername=Aztarnariaren Izena
+azbuddy.dchat.status.notavail=Egoera ez dago eskuragarri oraindik
+br.backup.setup.info=Mesedez kontuan izan berezgaitasunezko babeskopia itxurapena ezartzea.\nIkusi Tools->Options->Babeskopia eta  Leheneratzea
+device.itunes.start=iTunes abiatzea edo berez-abiatzea behar duzu
+ConfigView.section.style.DNDalwaysInIncomplete=Erakutsi betik Liburutegiko Osatugabe sailean  'Ez Jeitsi' duten agiriak
+IPChecker.external.httploadfail=Orrialdea gertatzeak huts egin du
+ConfigView.section.rss=Tokiko RSS etab.
+FileView.BlockView.title=Agiri Atalak
+MainWindow.menu.view.detailedlist=&Zerrenda Zehatza
+FilesView.rename.failed.title=Berrizendatze/Birxedetzeak huts egin du
+PeersView.menu.close=&Itxi
+ConfigView.section.proxy.group.peer=Hartzaile Harremanak
+Files.column.fileext=Mota
+Subscription.menu.dirtyall=Markatu Emaitza Denak Ez Irakurrita Bezala
+label.quick.config=Itxurapen Azkarra
+dlg.auth.cancelled.line2=Akats bat dela uste baduzu, mesedez jarri zaitez harremanetan sostenguarekin jasotako e-mail helbideen bidez.
+label.dblclick.to.min=Klik-bikoitza Erretiluratzeko
+ConfigView.option.dm.dblclick.launch={iconBar.run}
+network.admin.dns.spi.fail=Hutsegitea DNS kudeatzailea ezartzerakoan\n\nHonek eragina izango du  DNS erabakitze behartzea saihestea SOCKS-ekin bezalako eginkizunetan\n\nAkatsa\: %1
+dlg.auth.cancelled.line1=Zure Vuze Plus Eragintza ezeztatua izan da.
+azmsgsync.install.fail.msg=Mezu Aldiberetze Plugina ezarpen hutsegitea\: %1
+PeersView.state.established=Osoki ezarrita
+Progress.reporting.action.label.remove.tooltip=Kendu Garapen Ohar hau historiatik
+ConfigView.section.style.CatInSidebar=Erakutsi Kategoriak Albobarran
+ConfigView.section.style.showdownloadbasket=Erakutsi Jeisketa Saskia (Arrastatu eta Askatu .torrentak)
+configureWizard.transfer2.rate.changed=Elkarketa muga\=%1\nEzarritako muga izan daiteke %2 (geh. torrent eraginda \=%3, geh. jeisten\=%4)
+azbuddy.ui.menu.cat_subs=Harpidetu
+v3.menu.device.defaultprofile.never=Inoiz ez Transkodeatu
+columnChooser.move=Arrastatu lerroak berrantolatzeko
+ConsoleView.title.full=Kontsola
+azbuddy.beta.enabled=Beta Gaituta
+Plugin.extseed.name=Kanpoko Emaritzak
+subscriptions.column.auto-download=Berez Jeisketa
+ConfigView.section.file.save.peers.pertorrent=torrent bakoitzeko
+ConfigTransferAutoSpeed.capacity.used=%  Gaitasun Erabilia 
+ConfigView.label.seeding.rankType=Lerrun osatutako torrentak berez-hasteko ohinarriturik\:
+ConfigView.section.mode.intermediate.text=Sartu aztarnari eginkizunetan.\nErabili modu hau zeure aztarnaria sortzea eta zure agiriak hostatzea/argitaratzea nahi baduzu.
+PiecesView.DistributionView.PeerAvl=Hartzaile Eskur.Ekarpena
+configureWizard.transfer2.hint=Zure igoera muga hain goian edo hain behean ezartzeak jeisketan eragin dezake\!
+subs.prop.next_scan=Hurrengo mihaketaren epemuga
+SpeedView.stats.uploaded=Igoera (Hartuemana)
+ConfigView.section.queue.main=Nagusia
+config.external.browser.test=Aztertu kanpoko nabigatzaile itxurapena
+ConfigView.label.copyanddeleteratherthanmove=Kopiatu eta orduan ezabatu jatorrizko datuak eragiketa bakar batean mugitu beharrean - lagundu dezake datuen galera eragozten agiri sistema batzuetan
+# Not used, but could be renamed in all translation files to label.experimental :)
+OpenTorrentWindow.message=Esperimentala
+ConfigView.section.logging.level=Ohar Maila
+ConfigView.section.file.config.section=Itxurapen Ezarpenak\:
+ConfigView.section.transfer.lan=LAN (Tokiko Sarbide Sarea)
+SpeedTestWizard.test.panel.standard=irizpidea
+ConfigView.section.ipfilter.discardbanning=Itxi hartzaileak baztertutako datuak/datu onak bataz-bestekoa gainditzen badu  [0\: ezgaituta]
+ConfigView.section.style.colorOverride.altRow=Aldizkako Lerroak
+SpeedTestWizard.set.upload.hint=Ezarri Vuzeren BerezAbiadura algoritmoan erabiliko dire igoera eta jeisketa mugak.
+PeerFilesView.title.full={FilesView.title.full}
+DHTTransport.report.resending=datuak birbidaltzen
+Torrent.create.progress.totalfilesize=Agiriaren neurri osoa\: 
+GeneralView.label.seeds=Emaritzak\: 
+SpeedTestWizard.test.panel.explain=Neurtu zure Vuze protokoloaren abiadura. Hautatu abiadura azterketa mota eta enkriptaketa modua. Ikusi Vuzeren wiki orrialdea azterketa honi buruzko xehetasunetarako. Azterketa berezgaitasunez gelditu daiteke bi minutu baino gehiago luzatzen bada. Ohiko azterketak minutu bat baino gutxiagoan amaitzen dira.
+TableColumn.header.md5=MD5
+PeerSocket.mismatch_id=ez dator bat
+MagnetPlugin.report.secondarylookup.fail=Bigarren bilaketak huts egin du\: ez da iturbururik aurkitu
+iconBar.startstop.tooltip=Hasi edo Gelditu hautaturiko gaiak
+ConfigView.section.tracker.nonblocking=Ez-blokeatze aukerak
+devices.xcode.show.cat=Kategoriatan Banandurik
+Button.reload=Birgertatu
+wizard.multitracker.edit.deletetracker=Ezabatu
+MainWindow.status.unknown=ezezaguna
+TableColumn.header.tag.rssfeed={label.rss}
+devices.copy_url=Kopiatu Jario URL-a Gakora
+sharing.progress.hide=Ezkutatu
+ConfigView.section.stats.minutes=min.
+devices.router=bideratzailea
+MainWindow.menu.file.import.keybinding=Meta+I
+Formats.units.Mibit=Mibit
+GeneralView.label.hash.tooltip=Egin klik hasha gakoan kopiatzeko
+br.backup.notify=Jakinarazi babeskopia osatutakoan
+Content.alert.notuploaded.button.abort=&Ez Irten
+MyTorrents.column.ColumnProgressETA.StreamReady=Jarioa Gertu
+OpenTorrentWindow.mb.noDestDir.text='%2' torrentarentzako '%1' helmuga zuzenbidea ez dago edo baliogabea da.
+show.config.changes=Erakutsi Itxurapen Aldaketak...
+label.toggle.new.marker=Aldatu Markatzaile Berria
+Wizard.Subscription.create.search=Bilatu
+MainWindow.nat.status.tooltip.unknown=Suhesi/NAT eskuragarritasun egoera ezezaguna (TCP)
+security.cert.auto.install=Berezgaitasunez ezarri SSL egiaztagiri ezezagunak ohartarazi gabe
+ConfigView.section.file.friendly.hashchecking.tooltip=Atal hashegiaztepen modu astiroagoa baina estutasun gutxiagokoa cpu/sistemarentzat.
+ConfigView.section.logging.filter=Iragazi agirira ohartzerakoan
+MainWindow.menu.view.irc.moved=Irc orain eskuragarri dago plugin bezala, ikusi http\://plugins.vuze.com/plugin_list.php. Ezarritakoan erabili ikuspegi hau ->pluginak->IRC sarbide menua.
+SpeedView.stats.uptime=Denbora
+ConfigView.section.connection.encryption.encrypt.fallback_incoming=Ahalbidetu enkriptatu-gabeko sarrera elkarketak
+TableColumn.header.trancode_qpos=Zenb.
+Progress.reporting.statusbar.button.tooltip=Erakutsi Garapen Jakinarazpen Leihoa
+dlg.try.trial.text=Vuzek zure bideoetatik DVD grabaketak egin ahal izateko beharrezkoa den plugina ezartzea behar du.  Klikatu Piztu jarraitzeko.
+ConfigView.section.logging.logdir=Saio agiri zuzenbidea
+MainWindow.menu.quick_view.msg='%1' agiriaren edukiak '%2' jeitsi gabe
+PeersView.client=Bezeroa
+TableColumn.header.secondsseeding.info=Emaritzen egon zaren denboraren zenbatekoa guztira
+SpeedTestWizard.name.conf.level.low=Txikia
+remote.pairing.learnmore=<A HREF\="/pairing_learnmore.start">Uztarpena SEG</A>
+label.listen=Aditu
+ConfigView.label.ignoreCase=Ez bereiztu Larri-xehez
+device.error.copytomissing='Kopiatu Agiritegira' "%1" Ez da Aurkitu
+devices.xcode.profs=Transkodeaketa profilak eskuragarri
+config.dialog.shortcut.text=Sartu hizki bat 'kontrol+' konbinazioarako hautapen honentzat, hutsik kentzeko\r\n
+ConfigView.label.transfer.ignorepeerports=Baztertu datu ataka hauek dituzten hartzaileak (';' bananduta, adib. 0;25)
+exportTorrentWizard.process.torrentfail.title=Torrentaren Irakurketan Hutsegitea
+MagnetPlugin.report.tunnel=azpibideratzen %1 
+ConfigView.section.ipfilter.enable.descriptionCache=Bildu IP azalpenak urratu agirian
+MainWindow.menu.help.donate=Eman Dirulaguntza bat
+device.xcode.always=Betik
+unix.script.new.button.asknomore=Ez Esan Berriro
+MyTorrentsView.menu.setSpeed.disabled=Ezgaiturik
+Button.moveUp=Mugitu &Gora
+MainWindow.menu.file.open.url.keybinding=Meta+L
+DownloadManager.error.sha1=(SHA1) akatsa , ez dago Algoritmoa
+ConfigView.pluginlist.column.directory=Zuzenbidea
+security.certtruster.issuedby=Nork Jaulkia\:
+ConfigView.section.seeding=Emaritzen
+ConfigView.tb.delete.torrent=Liburutegitik bakarrik kendu
+ConfigView.section.sharing.protocol=Elkarbanaturiko iturburuentzako hartuemana
+ConfigView.section.logging.statsinfo=Sortu egoera argibideak
+ConfigView.section.transfer.autospeedbeta=Berez-Abiadura-Beta
+wizard.finish=A&maitu
+ConfigView.section.connection.udp.enable=Gaitu UDP-a
+subs.prop.is_auto_ok=Berez-jeisketa baimenduta
+network.ipv6.enable.support=Gaitu IPv6 sostengua (Java7-k beharrezkoa du Windowsekin)
+DHTView.general.rendezvous=Hitzordua\:
+label.searching=Bilatzen...
+upnp.alert.differenthost=UPnP\: '%1'izendapena honek hartuta dago '%2' - mesedez aukeratu ataka ezberdin bat
+ConfigTransferAutoSpeed.while.downloading=Jeisten\:
+tag.discovery.view.heading=Etiketa Aurkikuntza
+DHTOpsView.title.full=BDB Grafika
+ClientStats.column.sent=Bidalita
+swt.updater.downloader.downloading=SWT hemendik jeisten
+TableColumn.header.MediaThumb=Multimedia
+platform.win32.baddll.info=Vuzek '%1' egona atzeman du. Hau '%2'  zati da eta ezaguna da programaren blokeoa eta CPU erabilpen handia bezalako arazo larriak eragiteagaitik. Aurkitzen baduzu mesedez softwarea kendu edo ezarri Vuzeri eragiten ez dion moduan.
+IrcClient.error=Akatsa
+MyTorrentsView.menu.reposition.manual=Birjar&pena...
+priority.high=Lehentasun Handia
+tag.share=Elkarbanatu Etiketapena Herkidegoarekin
+MyTorrents.items.DownSpeedLimit.disabled=Ez jeitsi
+ConfigView.label.version.info.link=Ikusi hau bertsioak egiaztatzen dituen zerbitzarira bidaltzen diren datuen xehetasunak ezagutzeko
+br.backup.folder.info=Hautatu babeskopia idatziko den agiritegia
+devices.profile.direct=Zuzen
+ConfigView.label.start=Abiarazi
+IrcClient.joined=bat eginda
+ConfigView.section.file.torrent.autoskipfiles=Agirien luzapenak berez-jauzteko torrent bat gehitzerakoan [; bananduta]\r\n
+label.properties=Ezaugarriak
+device.renderer.remove_all.desc=Zihur zaude Aurkezle denak ETA beren transkodeaketak kentzea nahi dituzula?
+azbuddy.dchat.info=Txat deszentralizatuak beste Vuze erabiltzaile batzuekin zuzenean hitz egitea ahalibidetzen dizu, aukeran, izengabe.
+#Used by the webui plugin
+MyTorrentsView.menu.removeand.deletedata=Ezabatu &Datuak
+label.chat=Txata
+ConfigView.section.transfer.autospeed.downadjratio=Jeisketa\: Igoera abiadura maila (adib. 2.0 -> jeisketa abiadura muga igoera mugaren bikoitza da)
+label.lang.upper.case=Erabili hizki larriak (larri-xehe tekla blokeaturik duten erabiltzaileen jarduera lerrokatzen laguntzen du)
+subscriptions.config.maxresults=Harpidetza bakoitzeko atxirikiriko emaitz zenbateko gehiena [0\: mugagabea]
+label.access.denied=Sarbidea Ukatuta
+wizard.multitracker.edit.title=Aztarnari-Anitz Editatzailea
+Scrape.status.networkdisabled=Gaitu gabeko sarea
+wizard.choosetorrent=Mesedez hautatu non gorde torrent agiria
+ConfigView.label.info.in.window.title=Erakutsi oraingo neurriak etab. izenburu barran
+health.explain.green=Esanahi du dena ongi doala
+MainWindow.menu.speed_limits.info.prof=Ezarpenak '%1' profilarentzat
+Peers.column.UpDownRatio=Igota\:Jeitsita
+ConfigView.section.tracker.checkip=Berez-aurkitu kanpoko IP helbidea...
+Formats.units.Gibit=Gibit
+ConfigView.pluginlist.uninstallSelected=Kendu Hautatua
+dlg.auth.validating.subtitle=Balioztatzen
+FilesView.name.fastRename=Berrizendatze azkarra
+security.crypto.reason=Eragiketa arrazoia
+GeneralView.label.totalsize=Neurria Guztira\:
+ConfigView.section.language.UpdateURL=Eguneratu URL-a
+OpenTorrentWindow.mb.notTorrent.title=Ireki Huts egin duen Torrenta 
+GeneralView.label.totalspeed=Erletaldearen Abiadura\:
+ConfigView.label.overrideip=Ezeztatu aztarnari iragarpen IP-a(k) - punttu eta kakotxaz banaduta sare ezberdinetarako bada
+seedmore.shareratio=Zure elkarbanatze maila torrent honentzat hau da\: 
+ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Ahalbidetu enkriptatu-gabeko irteera elkarketak enkripatutako elkarketa saiakerak huts egiten badu
+GeneralView.torrent_created_on_and_by=%1 %2-tik
+MyTorrentsView.menu.manual.shared_torrents=Eskuz (torrent artean)
+ConfigView.section.style.useCustomTabs=Erabili itxi daitezkeen hegatsak (berrabiaraztea beharrezkoa)
+device.mediaserver.configure=Itxuratu Nire Multimedia Zerbitzaria
+filter.header.matches2=(Bilaketa emaitzak\: %1, %2 jardunean)
+webui.upnpenable=Gaitu UPnP ataka honentzat
+filter.header.matches1=(Bilaketa emaitzak\: %1)
+ConfigView.section.mode.intermediate.text1=Ezaugarri gehiago jeisketak agintzeko, hobetzeko eta ikusteko.
+ConfigView.label.open_transfer_bar_on_start=Ireki Eskualdaketa Barra hasieran
+label.no.download.selected=Ez da jeisketarik hautatu
+MainWindow.menu.speed_limits.schedule=Egitaraupena...
+friend.mod.subs=Eskuin-klikatzea harpidetzak aldatzeko
+MainWindow.menu.window.zoom.maximize=Handitu
+ConfigView.section.file.save.peers.enable=Gorde hartzaile elkarketak berrelkarketa azkarretarako
+v3.MainWindow.menu.view.pluginbar.keybinding=F8
+DHTView.transport.received=Jasota
+TableColumn.header.peakdown.info=Jeisketa Abiadura Gailurra
+azbuddy.tracker.enabled=Gaitu 'Lagun Kitzikapena' zure lagunekin jeisketak lehenesteko
+OpenTorrentWindow.startMode.queued=Lerrokatuta
+ConfigView.section.mode.beginner.wiki.definitions=BitTorrent hiztegia
+Wizard.Subscription.optin.description=Harpidetzak gaitutakoan, Vuzek zure liburutegiko edukien antzeko harpidetzak erakutsiko ditu, eta  jakinaraziko dizu harpideturiko edukiak jeisteko gertu daudenean..\n\nZure harpidetzak gaitzea nahi duzu?
+ConfigView.section.tracker.enablecategories=Banandu torrentak kategoriatan
+IPChecker.external.ipnotfound=IP helbidea ez da aurkitu
+tps.type.pex=PEX (Hartzaile Aldaketa)
+remote.pairing.test.running=Hurruneko elkarketagarritasuna aztertzen...
+search.export.all=Esportatu Bilaketa Eredu Guztiak...
+OpenTorrentWindow.simple.open=Torren Helbidea (Agiria, URL-a, Hasha)
+ClientStats.column.discarded=Baztertuta
+GeneralView.label.updatein.stopped=Geldituta
+OpenTorrentWindow.mb.askCreateDir.title=Helmuga Zuzenbidea ez dago
+PeersView.downloadspeed=Jeisketa Abiadura
+security.certtruster.yes=Bai
+ConfigView.label.opendetails=Berez ireki xehetasunen hegatsa
+beta.wizard.version=Orain duzun bertsioa %1
+ipCheckerWizard.title=IP Egiaztapen Laguntzailea
+LoggerView.excludeAll=Ez erakutsi adierazpide honekin bat datozen lerroak\:
+dlg.auth.revoked.line1=Zure Vuze Plus Eragintza Kodea indargabetua izan da. Mesedez klikatu behean argibide gehiago izateko.
+tag.type.ds.incomp={label.incomplete}
+TableColumn.header.tracker=Aztarnari Egoera
+ConfigView.section.file.perf.cache.size.explain=Katxea diska gogorrean egiten diren irakurketa/idazketa kopurua gutxiagotzeko erabiltzen da. Javaren '-XX\:MaxDirectMemorySize' aukera erabili ezean katxearentzako eskuragarri dagoen oroimena eta sarearen S/I erabilpena agerian ezartzeko, balio hau zure VM-aren gehienezko neurriaren %1 azpitik eduki behar duzu. Oraingo VM-aren gehienezko neurria %2 da. Hau nola aldatu jarraipideak lortzeko, ikusi MemoryUsage wikian %3. Ezarpen sentikorretan [...]
+ConfigView.section.proxy.peer.same=Erabili proxy ezarpen berberak aztarnari eta hartzaileekiko harreman proxyan
+download.removerules.unauthorised=Berezgaitasunez kendu baimengabeko torrentak
+device.rss.view=Egin klik RSS jarioa ikusteko
+wizard.addingmt=Aztarnari-Anitzaren argibideak gehitzen
+TableColumn.header.trancode_qpos.info=Kokapena Transkodeaketa Lerroan
+Progress.reporting.action.label.detail=Xehetasunak
+importTorrentWizard.importfile.title=Inportazio Agiri Hautapena
+SpeedView.stats.total=Guztira\:
+PiecesView.numberofblocks=Bloke Zenbatekoa
+MainWindow.menu.view.plugins=&Pluginak
+health.explain.share=Esanahi du torrenta ongi hostatuta edo argitaratuta dagoela
+torrent.fix.corrupt.result.fixed=%1 torrent hash berria kalkulatuta.\nSakatu Ongi torrenta gordetzeko.
+azneti2phelper.install.text=Ezarri I2P Plugina I2P izengabeko sarerako sarbidea sostengatzeko?\\n\\n<a href\="http\://wiki.vuze.com/w/I2PHelper_HowTo">Klikatu hemen argibide gehiagorako</a>\\n\\nOhartu ezarpenak minutu ugari hartu ditzakeela\\nsarea eskuragarri izan arte - hartu lasai\!
+Files.column.storagetype=Biltegiratze Mota
+MainWindow.menu.speed_limits.profiles=Profilak
+ConfigView.section.security.unlockkey.button=Ireki
+LoggerView.autoscroll=Berez-irristatu
+installPluginsWizard.installMode.info.text=Ez duzu pluginik behar Vuzerekin egoki lan egiteko, astialdi, berezgaitasuntze edo hurruneko aginte ezaugarri osagarriak eskaintzen dutenak.\nMesedez irakurri plugin bakoitzaren azalpenak ezartzea erabaki aurretik.\nPlugin gehienak zihurrak dira probatzeko, baina ez gainzamatu zure itxurapena erabiliko ez duzun pluginekin.
+dht.port=Datubasearen UDP ataka
+plugins.basicview.log=Saioa\:
+ConfigView.section.file.max_open_files.explain=Agiri asko irekitzeak arazoak eragin ditzake sistema eragilean, baliabide mugapena agiri eskuratzean bezalakoak. Honek aldiberean irekita egon daitezkeen agiriak mugatzen ditu.
+security.certcreate.ok=Sortu
+webui.password=Sarhitza
+memmon.low.warning=Oroimena geldoki ari da lanean, duzu %1 gelditzen da %2.\nEgintza kaltetua izan daiteke eta azkenean Vuzek lan egiteari utzi diezaioke\nIkusi <a href\="http\://wiki.vuze.com/w/Java_VM_memory_usage">the Wiki</a> oroimen eskuragarria nola handitzeko xehetasunak.
+installPluginsWizard.installMode.user=Ezarri plugina(k) zuretzat bakarrik
+azbuddy.dchat.log.messages=Oharreratu Mezuak Agirira
+TableColumn.header.readrate.info=Agiri Irakurketa Neurria
+MySharesView.name=Izena
+ConfigView.label.passwordconfirm=Sarhitza (baieztatu)
+PiecesView.priority=Lehentasuna
+OpenTorrentWindow.xOfTotal=(%1 %2-tik)
+br.test=Azterketa
+window.updateswt.cancel=Ezeztatu
+ConfigView.label.disconnetseed.tooltip=Torrent bat emaritzerakoan, eten emaritzen ari diren bezeroak.\nBeraiek ez dute behar zurekin hitzegiten egotea.
+configureWizard.file.invalidPath=Zuzenbide okerra
+ConfigView.section.tracker.password=Sarhitza
+v3.deleteContent.applyToAll=Ezarri eragiketa %1 hautaturiko sarrera guztiei.
+MagnetPlugin.report.secondarylookup.ok=Bigarren bilaketa bat egin da
+alert.copy.on.comp.fail=%1 Jeisketa\nAkats osatutako agiriak hona kopiatzeakoan '%2'\: %3
+GeneralView.label.maxuploads.tooltip=Une jakin batean itogabe izango diren gehienezko hartzaile zenbatekoa.
+Scrape.status.error.badURL=Iragarle URL-ak ez ditu zuritze zehaztapenak jarraitzen.
+exportTorrentWizard.process.outputfileexists.message=Irteerako agiria badago - gainidatzi?
+cat.share=Elkarbanatu Kategoriapena Herkidegoarekin
+ConfigView.section.transfer.lan.downloadrate=KB/s LAN geh. jeisketa abiadura [0\: mugagabea]
+Button.remove=Kendu
+MyTorrents.bigView.header=Liburutegia
+ConfigView.section.connection.advanced.IPDiffServ=Irteera pakete DiffServ balioa (TOS eremua)
+SpeedView.stats.now.tooltip=Guztira (Protokoloa)
+ConfigView.label.pause.downloads.on.exit=Gelditu jeisketak irtetzerakoan
+device.export.select.template.file=Esportatu Gailua
+ConfigView.section.security.resetkey.warning=Zihur zaude zure enkriptaketa giltzak leheneratzea nahi dituzula? Egiten baduzu enkriptatutako argibide guztiak BETIRAKO GALDU daitezke. Baita ere, zure giltza publikoa duen edonor hartzaileek ezingo du jadanik zurekin harremandu zure giltza berria lortu arte. Hortaz, egitan zer egiten ari zaren jakin ezean, ezazu hori egin.
+ConfigView.section.connection.nondata.udp.same=Erabili UDP ataka bera Banaturiko Datubaserako eta UDP Aztarnarirako
+label.ctrl.space.for.suggestion=Sakatu Ktrl+<tartea> edo Aldatu+<tartea> iradokizunetarako
+iconBar.up=Igoera
+ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Sarri, emaritza zenbateko apala eta hartzaile zenbateko handia duten torrentak, zihurrenik esannahi du ez dela hartzaile arteko kopia oso bat.\nHortaz, badaiteke zuk ez nahi izatea emaletza arauak kopia oso bat izatea (eta hortaz okerra bere lerrunaren murrizketan)
+ConfigView.section.file.writemblimit.explain=Diskaren idazketa abiadura jeisketa abiadura bezain motela denean neurri honek mugatzen du zenbat datu lerrokatu daitekeen jeisketa abiadura murriztua izan aurretik.
+iconBar.transcode.tooltip=Egin gailurako baliagarri
+SpeedTestWizard.set.download.label=Jeisketa Abiadura Muga\:
+#
+#2.0.7.0
+#
+security.certtruster.title=Segurtasun Egiaztagiri Oharra
+ConfigView.label.downloading.reTest=Jeisketa ber-aztertze epea [min; 0\=inoiz ez]
+general.dont.ask.again=Ez galdetu berriro
+ConfigView.section.style.dataStatsOnly=Erakutsi datu estatistikak bakarrik (ezkutatu harreman estatistikak)
+SpeedView.title.full=Jarduera
+PeersView.download=Jeisketa
+TableColumn.header.chat.user.count=Erabiltzaile Kontua
+tps.status.unavailable=Eskuraezina
+subscriptions.column.category=Kategoria
+resetconfig.warn.title=Baieztatu Eragiketa
+ConfigView.pluginlist.column.type.shared=Elkarbanatuta
+Button.upgrade=Eguneratu
+TorrentOptionsView.param.max.uploads.when.busy=KB/s geh. igoera abiadura igoera muga orokorra lortu denean [0\: ezgaituta]
+authenticator.password=Sarhitza
+v3.deviceview.infobar.line2=Ikusi zure bideoak zure pantailetako edozeinetan - iPad, iPhone, iPod, TB
+v3.deviceview.infobar.line1=Arrastatu eta askatu bideoak zure Liburtegitik hautatzen duzun gailura.
+LocaleUtil.label.hint.doubleclick=Aholkua\: lerro batean bi aldiz klik eginez kodeaketa hautatzen da eta leihoa isten da
+fileDownloadWindow.state_downloading=Jeisten
+v3.MainWindow.tab.advanced=Aurreratua
+openUrl.referrer.info=Beharrezkoa bakarrik eskatzen duten webguneetan
+Wizard.Subscription.subscribe.subscriptions=Antzeko Harpidetzak
+ConfigView.option.dm.dblclick.show._windows=Erakutsi Agiria(k) Explorerren
+MyTorrentsView.menu.manual.per_peer=Eskuz (hartzaileko)
+ConfigView.section.style.colorOverrides=Margo Ezabatuak
+device.itunes.install=iTunes ezartzeko behar duzu
+ConfigView.pluginlist.column.type=Mota
+ConfigView.section.files=Agiriak
+AdvRenameWindow.message=Idatzi izen berri bat jeisketa honi.
+popup.file.finished="%1" jeisketa amaituta
+UpdateWindow.columns.version=Bertsioa
+ManagerItem.moving=Mugitzen
+dhttracker.enable_alt={ConfigView.section.stats.enable}
+wizard.filesaved=Agiria gordeta.
+exportTorrentWizard.exportfile.title=Hautatu Esportatzeko Agiria
+TableColumn.header.seed_to_peer_ratio.info=Erletaldeko emaritza eta hartzaile arteko maila guztira
+ManagerItem.stopping=Gelditzen
+ConfigView.section.proxy.peer.informtracker=Jakinarazi aztarnariari mugapena
+MainWindow.menu.transfers.pausetransfersfor.keybinding=Meta+Shift+P
+ConfigView.label.tcplistenport=Sarrera TCP aditze ataka
+TableColumn.header.unopened=Berria
+wizard.newtorrent.byo.help=Eraiki zeure torrenta hautaturiko agiri eta zuzenbideetatik
+dlg.player.install.subtitle=Ezarpena
+SpeedView.stats.autospeed.disabled=Aukera hau ez dago gaiturik (DHT-a behar duzu) edo ez zaude erabilitzen (eskuzko igoera abiadura hautatuta)
+metasearch.addtemplate.failed.title=Ezarpenak Huts egin du
+wizard.multitracker.edit.edit=Editatu
+ConfigView.label.hap=Mozorrotu jeisketa osaketa
+DHTView.general.unknown=Ezezaguna
+ConfigView.label.ignoreSeeds=Ez egin kasu gutxienean dauden torrentei
+PeersView.I2=I (Interesgarria hartzailearentzat)
+label.not.spam=Ez dago Spamtzailerik
+PeersView.I1=I (Interesgarria hartzailearentzat)
+azbuddy.ui.table.msg_out=Mezu Irteera
+TagAddWindow.subtitle=Zure etiketa eta kategoria guztiak kudeatu ditzakezu Ikusi->{tags.view.heading} bidez, eta etiketa berriak aurkitu ditzakezu Ikusi->{tag.discovery.view.heading} bidez.
+label.connections=Elkarketak
+torrent.fix.corrupt=Zuzendu Torrent Hondatua...
+PasswordWindow.title=Vuze itxita dago
+MainWindow.menu.file.create=&Torrent Berria...
+TrackerAvail.column.peers={Trackers.column.peers}
+ConfigView.section.proxy.host=Hostalaria
+plugins.basicview.clear=Garbitu
+ConfigView.label.passwordmatchnone=Ez
+ConfigView.section.connection.networks.prompt=Galdetu hautatzeko jeisterakoan izengabeko aztarnari bat gehitzen denean
+plugin.download.remove.veto.notstopped=Jeisketa ezin da kendu ez delako gelditzen
+br.backup.auto.retain=Heusteko babeskopia zenbatekoa
+authenticator.torrent=Torrenta
+MainWindow.menu.transfers=&Eskualdaketak
+torrent.comments.info=Aipamenak eta mailaketak torrent hau jeitsi duten beste erabiltzaileengandik eskuratzen dira.\nHonek denbora apur bat hartu dezake, bereziki Vuze abiarazi berri baduzu.\n\nSareak ekinean\: [%1] - aldatu hau 'Elkarketa Aukerak' ezarpenak bidez.
+OpenTorrentWindow.mb.notTorrent.retry=Magnet Itxiera
+DHTView.general.replacements=Ordezkap.\:
+exportTorrentWizard.torrentfile.title=Sarrerako Torrentaren Hautapena
+window.networkselection.info=Behean zerrendaturiko torrentak ondorengo sareak sostengatzen dituzten aztarnariak dituzte.\nHautatu itzazu gaitzeko aztarnari eta hartzaile harremanerako.\nBezero publikoak sostengatzen dituen aztarnari izengabe bat bada gaitu biak izengabea eta sare publikoak.\nSare publikoa gaitzeak jakina izengabetasuna kentzea du ondorio\!
+OpenTorrentWindow.torrentTable.saveLocation=Gordetze Kokalekua
+dlg.stream.plus.subtitle=Berritu
+Alert.failed.update.url=http\://wiki.vuze.com/w/Failed_Update\\
+ConfigView.section.style.enableXPStyle=Gaitu XP estiloa (berrabiaraztea beharrezkoa)
+MainWindow.dialog.choose.savepath=Hautatu gordetze helburua
+dlg.auth.tos=Irakurri ditut eta onartzen ditut <A HREF\="tos">Zerbitzuaren Baldintzak.</A>
+label.fails=Hutsegitea
+wizard.torrentFile=Torrent Agiria
+webui.connectiontest=\tKlik elkarketa azterketzeko
+ConfigView.section.style.colorOverride.error=Akatsa
+TableColumn.header.chat.msg.count=Mezu Zenbatekoa
+speedtest.wizard.select.bt=Bittorrent abiadura azterketa bereizia
+aznettorbrowser.install.description=Mesedez itxaron Tor Nabigatzailea Plugina ezartzen den bitartean
+label.move.on.comp=Mugitu Osatutakoan
+ConfigView.section.style.usePathFinder=Erabili 'Helburu Bilatzailea' 'Bilatzailea'-ren ordez
+ConfigView.tb.delete.ask=Galdetu
+v3.MainWindow.button.start=Hasi
+FilesView.rename.filename.title=Berrizendatu agiria
+Button.agree=Onartzen dut
+ConfigView.label.defaultstarttorrentsstopped=Lehenespenez gehitu torrent berriak geldituta egoera batean
+MyTorrentsView.dialog.setFilter.title=Aldatu Iragazkia
+security.certtruster.resource=Baliabidea\:
+ConfigView.section.connection.encryption=Garraio Enkriptaketa
+TableColumn.header.pieces=Atalak
+Views.plugins.Distributed.DB.title=Banaturiko DB
+upnp.wiki_link=Vuze Wiki orrialdea UPnP-n
+ConfigView.label.queue.minQueueingShareRatio=Ez lerrokatu edo gelditu torrenta bere elkarbanatze maila lortu arte
+ConfigView.section.server.enableudpprobe=Gaitu UDP aztarnari zunda HTTP aztarnarientzat
+TableColumn.header.OnlyCDing4.info=Torrenta emaritzan bakarrik egon den denbora. Kenduta torrenta jeisten (eta emaletzan) egon den denbora.
+label.incomplete=Osatugabea
+torrent.avail.title='%1'-rako iturburuak
+DHTView.db.title=Datubasea
+UpdateWindow.status.downloading=Jeisten
+ConfigView.section.logging.loggerenable=Gaitu oharketa
+azbuddy.ui.table.con=CON
+Peers.column.Encryption=Enkriptaketa
+sidebar.header.plugins=Pluginak eta Gehigarriak
+ConfigView.section.br.overview=Itxuratu Vuzerentzako zure babeskopia aukerak. Honek zure itxurapena berreskuratzea ahalbidetuko du, diska matxura bezalako akats larriren bat gertatuz gero.\n\nAhal da gidagailu fisiko banandu batera babeskopiatzea arrunt Vuze erabiltzen duzun batetik\!\n\nOhartu eragiketa hauek Vuzeren itxurapen datuei bakarrik ezartzen zaizkiela, jeitsitako agirien babeskopiak zeuk kudeatu beharko dituzu.\n\n
+device.showGeneric=Erakutsi Gailu Generikoak
+subscriptions.column.nb-subscribers=Harpidetuak
+ConfigView.section.style.use_show_parent_folder.tooltip=Aukera hau gaitzeak eduki agiritegia agiri kudeatzaile egokian irekitzea ahalbidetzen dizu.\nHorrela ere, honek esanahi dezake jeisketaren gordetze helbidea ez dela berezgaitasunez hautatua.
+PiecesView.DistributionView.title=Atalen Banaketa
+MainWindow.menu.view.mytorrents.keybinding=Meta+1
+window.update.noupdates.text=Ez dago eguneraketa berririk eskuragarri.\n\nZorionak\!
+chat.view.enter.key.title=Sartu Kanal Giltza
+ConfigView.pluginlist.noplugins=Ez da pluginik aurkitu.
+Views.plugins.aznetstatus.title=Sare Egoera
+GeneralView.label.status.pieces_available=Atalen Egoera
+ConfigView.section.file.defaultdir.auto=Berezgaitasunez jeitsi berezko zuzenbidera (Ez Garaionekoa)
+dlg.auth.enter.cancelled=Oraingo eragintza kodea ezeztatua izan da.
+ConfigView.section.mode.intermediate.wiki.publish=Agiriak Argitaratzen
+SpeedTestWizard.abort.message.failed.peers=Hutsegitea hartzaileekin elkarketatzean
+ConfigView.section.interface.password=Sarhitza
+TableColumn.header.down=Jeitsita
+tag.type.ipset=IP Ezarpena
+ConfigView.section.queue.seeding.firstPriority=Lehentasun Nagusia
+SpeedView.stats.title=Estatistikak
+ConfigView.section.transfer.autospeed.minupload.tooltip=Igoera abiadura ez da arrunt berez beheratuko muga honen azpitik
+ConfigView.section.ipfilter.list.banned=Eragotzia izan da
+max.sr.window.message=Sartu xede elkarbanatze maila [0\:ezgaituta]
+ConfigView.section.proxy.username=Erabiltzaile izena
+IPChecker.external.service.dyndns.name=Dyndns
+azbuddy.dchat.save.messages=Gorde Mezuak Berrabiarazteen Artean
+ConfigView.section.connection.advanced.info.link=Mesedez ikusi hemen xehetasunak
+dht.advanced.label=Aldatu bakarrik balio hauek egitan zer egiten ari zaren badakizu
+UpdateWindow.close=Itxi
+wizard.file=Agiria\:
+SpeedTestWizard.test.panel.label=Vuze abiadura azterketa\:
+UpdateMonitor.messagebox.restart.text=Vuzek eguneraketa garrantzitsu baten jeisketa burutu du eta orain berrabiarazia izan behar da eguneraketa ezarria ahal izateko
+DHTView.db.direct=Zuzen
+ConfigView.section.file.readmblimit=Gehienezko irakurketa eskabide lerrokatuta (%1)
+webui.enable=Gaitu
+beta.wizard.disable.title=Berrezarpena Beharrezkoa
+wizard.multitracker.edit.text=Edit. Idazkia
+FancyMenu.Header.Organize=Antolatu
+trackername.prefs.title=Sartu Aztarnari-Anitzeko Torrententzako Hobetsitako Erakuspena
+TableColumn.header.tag.discovery.torrent=Torrentaren Iradokitzailea
+label.reapply=Berriro-ezarri
+Security.jar.signfail=JAR sinadura okerra - %1
+TagAddWindow.message=Sartu etiketa izen berri bat
+v3.activity.remove.text=Zihur zaude Jakinarazpen hau ezabatzea nahi duzula?\n%1
+label.see.x.for.help=Ikusi %1 laguntzarako
+azbuddy.ui.table.online=Online
+TableColumn.header.sessionup=Saio Igoera
+label.public.chat=Txat Publikoa
+upnp.portchange.alert=Hurrengo atakek aldatu egin dira UPnP gailuetan arazoak saihesteko\: %1 [ataka zaharra\=%2] %3 [ataka zaharra\=%4]
+ConfigView.section.transfer=Eskualdaketa
+ConfigView.label.incrementalfile=Gaitu agirien sorrera inkrementala  [beharrezkoa Linux-en FAT32 erabiliz gero]
+menu.delete.options=Kendu...
+azbuddy.dchat.status.destroyed=Suntsituta
+swt.install.window.ok=Ezarri
+fileDownloadWindow.downloading=Hemendik Jeisten\:
+TableColumn.header.AvgAvail.info=Atal eskuragarritasuna bananduta Z ataletan, bananduta Z elkarketatan
+wizard.hint.directory=Aholkua\: Arrastatu eta Askatuz hautatu dezakezu zuzenbide bat
+PeersView.state.pending=Zain
+device.view.heading=Media   %1
+PeersView.incomingreqcount.info=Hartzaileek eginiko sarrera eskabide zenbatekoa
+v3.MainWindow.menu.advanced=&Aurreratua
+ConfigView.label.minimizetotray='Ikurtu' aukerak Sistemaren Erretilura ikurtzen du
+TableColumn.header.ipfilter=IP Iragazkia Gaituta
+device.tag=Etiketa Gailua
+TableColumn.header.path={FilesView.path}
+device.upnp.present_url=Gailu Administrazioa
+azbuddy.dchat.ftux.welcome=Ongi etorri Txatera
+PeersView.C2=IT (Hartzailea itotzen)
+wizard.maketorrent.piecesize=Atalen neurria
+PeersView.C1=IT (Hartzaileak itota)
+ConfigView.section.security.resetcerts.warning.msg=Zihur zaude egiaztagiri biltegia berrezartzea nahi duzula? Berez-sinaturiko egiaztagiri bat edo eskuz inportaturiko egiaztagiriak badituzu denak galduko dira\!
+popup.error.hide=Ezkutatu
+authenticator.savepassword=Gogoratu nire sarhitza
+TableColumn.header.profile.info=Erabilitako transkodeaketa profila
+ConfigView.label.stop.Hibernate=Negutu Ordenagailua
+v3.MainWindow.button.pause=Pausatu
+ConfigView.label.closetotray._mac=Itxi txikiagotuak Egoera Barra Ikurrera
+SpeedView.stats.idlePing=Idle Ping-a\:
+ConfigView.label.showsplash=Erakutsi ongi etorri ikusleihoa
+subscriptions.info.avail=Ez duzu harpidetzarik gehitu oraindik. %1 daude eskuragarri zure liburutegirako.
+webui.protocol=Hartuemana
+label.initial_tags=Hasierako Etiketak
+config.external.browser.switch.implic=Ondorioak
+DHTTransport.report.timeout_some=denboraz-kanpo, %1 pakete jasota %2-tik baina osatugabe
+ConfigView.section.tracker=Aztarnaria
+exportTorrentWizard.process.exportfail.title=Torrentaren Esportazio Hutsegitea
+ConfigView.interface.start.advanced=Hasi Ikuspegi Aurreratuan (AZ 2.x)
+ConfigView.section.style.TagInSidebar=Erakutsi Etiketak Albobarrran
+ConfigView.section.style.status=Egoera Eremua\:
+GeneralView.label.timeelapsed=Igarotako denbora\: 
+ConfigView.label.passwordmatchyes=Bai
+installPluginsWizard.installMode.title=Mesedez hautatu ezarpen mota
+ConfigView.section.connection.group.peersources=Hartzaile Iturriak
+TableColumn.header.tag.properties={label.properties}
+ConfigView.section.interface.wavlocation.info=Hautatu .wav agiria edo utzi hutsik berezko soinuarentzat
+DHTView.db.keys=Giltzak
+ConfigView.section.file.max_open_files.tooltip=Erabili ehundaka/milaka agiriko torrentak jeisketen badituzu, eta SE-ren agiri eskuragarri mugara heltzen ari bazara.
+devices.sidebar.mainheader.tooltip=%1 gailu ezkutatu dira orotarako edo etiketatugabe bezala.\n Erabili eskuin-klika aukerak agerian jartzeko
+ConfigView.label.startNumSeeds=\nHasi emaritzen hauek baino gutxiago daudenean\:\n - Beste arau guztiak gainidazten ditu
+ConfigView.section.file.decoder.showall=Kontuan izan ahalezko kodeaketa denak
+CacheView.writes.hits=Gordeta
+TableColumn.header.sha1.info=Agiriarentzako SHA1 hasha (osorik jeitsi behar da,klikatu kalkulatzeko)
+installPluginsWizard.file.no_such_file=Ez dago emandako izenik duen agiririk
+installPluginsWizard.finish.explanation=Hautatutako Pluginak Eguneratze Laguntzailea erabiliz ezarri daitezke.\n\nMesedez lasai hartu, denbora apur bat behar izan dezake agertzeko.\n\nGarapenaren berri izateko, egin klik bikoitza egoera barraren ezkerraldean.
+label.current.equals={label.current} %1
+configureWizard.nat.test=Aztertu
+PeersView.uniquepiece.none=Bat ere ez
+TableColumn.header.uploadspeed.info=Hartzaieei datuak bidaltzeko erabiltzen ari garen abiadura
+dlg.auth.install.pct=%1% eginda
+TableColumn.header.name.info=Torrentaren izena
+DHTView.title.full=Banaturiko Datubasea
+unix.script.new.button.continue=Gero Egingo Dut
+ConfigView.section.connection.advanced.read_select=Irakurri hautatutako itxaronaldia (milaen, berez %1)
+azneti2phelper.install.subtitle=I2P Plugina ezartzen
+devices.restrict_access.prompt=Sarbidea Ukatu '%1'
+StartStopRules.firstPriority=1. Lehentasuna
+ConfigView.label.stop.Nothing=Ez Egin Ezer
+tps.incoming.details=Orain\: TCP\=%1, UDP\=%2; Guztira inoiz\=%3
+MyTorrentsView.menu.movedata.dialog=Hautatu kokaleku berria
+Peers.column.handshake_reserved=Eskuemateak Gordetako Byteak
+TableColumn.header.shareRatio.info=Zenbat igo duzun (elkarbanatu) jeitsi duzunarekin alderaturik
+dht.override.ip=Ezabatu kanpoko IP helbideak
+MyTorrentsView.menu.open_parent_folder=Ireki Edukiaren Agiritegia
+MyTrackerView.downloaded=Jeitsita
+TransferStatsView.title.full=Eskualdaketak
+azbuddy.dchat.copy.channel.key=Kanal Giltza
+wizard.tracker=Aztarnaria\:
+ConfigView.section.tracker.passwordwebhttpsonly=HTTPS bidez bakarrik eskuratzea ahalbidetuta
+ConfigView.section.style.colorOverride.warning=Kontuz
+v3.MainWindow.text.get.started=Izena Eman
+azbuddy.name=Lagunak
+TableColumn.header.tracker.info=Aztarnariaren Egoera
+config.external.browser.switch.search.inf=Behar du 'Vuze Hurruneko Webgunea' plugina; Web emaitzik ez; Eredu edizio ezaugarririk ez; Emaitzetatik harpidetzak sortzerik ez; Jeisketa loturatan aipamen ezarpenik ez
+GeneralView.section.availability=Eskuragarritasuna
+Progress.reporting.detail.history.limit=Xehetasun mezu muga (%1) GarapenOhar honentzat gehiegizkoa da; ondorioz mezuak ez dira historiara gehituak izango
+Subscription.menu.deleteall=Ezabatu Emaitza Denak
+Trackers.column.leechers=Izainak
+device.configure=Itxuratu...
+MainWindow.status.warning.tooltip=Klikatu hemen xehetasunak ikusteko
+azbuddy.ui.menu.sign=Izenpetu Gakoa
+azbuddy.dchat.rchans.ro=Irakurtzeko-Bakarrik Kanal Berria
+AllPeersView.title.full=Hartzaile Guztiak
+platform.win32.baddll.nvLsp=NVIDIA ntune / Forceware
+torrent.decode.info.order.bad=Torrent Oharra\: '%1' torrenta oker eginda dago eta hash okerra sortu dezake.\n\nIkusi <a href\="http\://wiki.vuze.com/w/Torrent_Info_Order_Bad">the Vuze Wiki</a> xehetasun gehiagorako eta ahalezko konponbide baterako
+DHTOpsView.idle=Langabe - jardueraren zain...
+ConfigView.label.passwordmatch=Sarhitza eraginda\:
+ConfigView.label.ircserver=Zerbitzaria
+LocaleUtil.title=Hautatu kodeaketa
+Plugin.localtracker.wellknownlocals=Berezgaitasunez barneratzen du bigiztapena/lotura/tokiko sareak gunea (192.168 e.a)
+ConfigView.label.minimizetotray._mac=Egoera Barrako Ikurreratzen du
+ConfigView.section.sharing=Elkarbanatzen
+config.external.browser.switch.search=Bilatu emaitzak
+ConfigView.dialog.choosemovepath=Mesedez hautatu zein zuzenbidera mugituko den
+MainWindow.menu.transfers.stopalltransfers=&Gelditu Denak
+GeneralView.label.averagespeed=bataz-bestekoa
+pairing.group.optional=Aukerazko Ezaugarriak
+PiecesView.speed=Abiadura
+Trackers.column.interval=Tartea
+label.pinned.only=Finkatua Bakarrik
+ConfigView.label.movepartialdownloads=Mugitu agiri batzuk "Ez jeitsi" ikurra eduki arren
+ConfigView.section.stats.seconds=seg.
+AllPeers.column.\#=Z
+devices.profile=Profila
+Peers.column.pieces.info=Hartzailearengandik jeitsi dituzun atalak adierazten dituen grafika barra
+Trackers.column.leechers.info=Izainak erletaldean
+azbuddy.dchat.noti.sound=Jo soinu bat mezu bat jasotakoan
+subscript.add.upgrade.desc=Zihur zaude '%1' harpidetza berritu nahi duzula?
+MainWindow.menu.speed_limits.info.title=Abiadura Muga Xehetasunak
+ConfigTransferAutoSpeed.auto.speed.classic=Berez-Abiadura (klasikoa)
+MainWindow.dht.status.unreachabletooltip=Badirudi arazo bat dagoela Banaturiko Datubasearen UDP ataka mapaketarekin (NAT/suhesia)
+TableColumn.header.size.info=Diskako torrenteen edukien neurria
+configureWizard.transfer.hint=Aholkua\: hautatu zure linearen abiadura baino apur bat txikiagoa.
+ConfigView.section.tracker.server.group.networks=Sareak
+subscriptions.config.autostartdls=Berezgaitasunez hasi jeisketak gehitutakoan (geldituta egoeran jartzearen alderantzizkoa da)
+LoggerView.filter.checkAll=Hautatu Kategoria Guztiak
+v3.MainWindow.search.go.tooltip=Exekutatu Bilaketa
+ConfigView.label.popup.autohide=Berezgaitasunez ezkutatu akatsenak ez diren ohar alertak x segundu ondoren (ezarri 0 berez ezkutatzea ezgaitzeko)
+pairing.srp.state=Egoera\: %1
+ConfigView.section.file.deletion.section=Agiri Ezabapena
+DownloadManager.error.ioerror=S/I Akatsa
+dialog.pause.for.period.text=Pausatu jeisketak eta berezgaitasunez berrekin ondoren [minutu]
+TrackerAvail.column.seeds={Trackers.column.seeds}
+TableColumn.header.CountryFlag=Ikurra
+wizard.close.message=Nahi duzu laguntzaile hau gertatzea Vuze abiarazten den hurrengoan?
+devices.od.xfering=Eskualdaketa
+ConfigView.section.style.ShowCatButtons=Erakutsi Kategoira Botoiak Liburutegian
+popup.more.waiting=%1 mezu gehiago...
+ConfigView.section.tracker.pollintervalincby=Handitu honenbeste\:
+ConfigView.section.file.delete.confirm=Baieztatu eduki ezabapena Tresnabarraren eta Ezabatu giltzaren bidez
+MainWindow.status.latestversionunchecked=Bertsio egiaztapena ezgaiturik
+ClientStats.column.count=Zenbaketa
+TableColumn.header.done=Eginda
+v3.MainWindow.button.play=Irakurri
+mdi.entry.about.dvdburn=Hasteko
+device.browse=Bilatu
+ConfigView.section.file.delete.torrent=Berez ezabatu .torrent agiriak edukia ezabatzerakoan
+wizard.maketorrents.force=Behartu torrenta hastea
+ConfigView.section.tracker.main=Nagusia
+Formats.units.B=B
+MyTorrentsView.menu.setpriority.low=&Txikia
+ConfigView.section.style.status.show_ddb=DDB Egoera
+wizard.singlefile=Agiri bakarra
+ConfigView.label.minSpeedForActiveSeeding=Ez zenbatu osatutako torrentik aho bat erabiltzen ari bada abiadura honen azpitik
+SpeedTestWizard.name.conf.level.absolute=Osoa
+MainWindow.about.title=Honi buruz
+LoggerView.realtime=Eguneratu egizko denboran
+Formats.units.kB=kB
+menu.add.peers={dialog.add.peers.title}...
+ConfigView.section.security.clearpasswords=Berrezarri gogoraturiko sarhitzak
+device.rss.port=RSS jario ataka
+remote.pairing.accesscode=Sarbide Kodea\:
+devices.converting=Bihurtzen
+device.error.copyfail2=Agiri Batek Edo Gehiagok Huts Egin Du Gailura Kopiatzean
+authenticator.title=Egiaztapena Beharrezkoa da
+Formats.units.bit=bit
+label.add.tag=Gehitu Etiketa...
+tag.type.ds.qfors=Emaritzarako Lerrokatuta
+plugins.init.force_enabled=Vuzek "%1" plugina ezgaiturik dagoela atzeman du - birgaitua izan da Vuzeri zuzen lan egitea ahalbidetzeko.
+ActivityView.legend.overhead=Burugain neurria
+TableColumn.header.trackernextaccess.info=Hurrengo aztarnariaren atzipena noiz gertatuko den
+ColumnSetup.explain=Esploratu ezkerreko zutabeak, eta gehitu eskuineko zutabe zerrenda ikusgarrira. Handiagotu edo txikiagotu zutabe eskuragarriak ezkerreko botoiko Iragazkia erabiliz. Arrastatu eta Askatu eta teklatu lasterbideak ere sostengatzen dira.
+platform.win32.baddll.imon=NOD32 Birus-aurkakoa
+MainWindow.upgrade.section.manual=Eskuzko Eguneraketa 
+MyTorrentsView.menu.editTableColumns=&Zutabearen Ezarpenak
+window.updateswt.status.finding=SWT Betsio berriena bilatzen
+MagnetPlugin.current.port=URI Kudeatzaile Ataka
+PeersView.state.connecting=Elkarketatzen
+v3.filter-bar=Izenburu Iragazkia\:
+tag.type.ds.qford=Jeisteko Lerrokatuta
+MainWindow.menu.file.share.dir=A&giritegia...
+ConfigView.section.invalid.value=Balio okerra '%1' sartua '%2'\: %3
+br.backup.manual.info=Eskuzko babeskopia itxurapena
+MyTorrentsView.menu.manual=&Eskuz...
+TorrentOptionsView.title.full=Aukerak
+azbuddy.dchat.anon.beta=Izengabeko beta txata (I2P)
+SpeedTestWizard.stage.message.preparing=azterketa gertatzen...
+FilesView.numberofpieces=Atal zenbatekoa
+upnp.alertsuccess=Jakinarazi zuzen egindako izendapenak
+fileplugininstall.duplicate.desc='%1' Pluginaren, %2 bertsioa ezarrita dago
+DHTView.activity.status.false=Lanean
+pairing.group.srp=Uztarpen Seguru Aukerak
+ConfigView.section.security.resetcerts=Berrezarri egiaztagiri biltegia (Vuze berrabiaraziko du)
+plugin.init.load.failed.classmissing=Kendu plugina 'Tresnak->Pluginak->Kentze Laguntzailea' bidez eta berriro ezarri.
+platform.win32.baddll.nl_lsp=NetMugatzailea
+ConfigView.label.directory=Zuzenbidea
+MyTorrentsView.menu.queue=&Lerrokatu
+MainWindow.about.internet.wiki=Vuzeren Wiki SEG
+MainWindow.dialog.choose.savepath_forallfiles=Hautatu agiri GUZTIEN gordetze helburua
+platform.jvmopt.accesserror=Huts egin du JVM aukeratara sartzean\: %1
+VivaldiView.title.full=Vivaldia
+devices.sidebar.show.only.tagged=Erakutsi bakarrik etiketaturiko gailuak
+ConfigView.section.proxy.show_icon.flag.incoming=Erakutsi ez-tokiko, ez-SOCKS barrurako elkarketarik akats egoera bezala.
+ConfigView.label.movecompleted=Mugitu osatutako agiriak (jeitsi ondoren)
+PiecesView.reservedby=Gordeta
+dialog.pause.for.period.text2=Berez-berrekin eragindakoak\:  %1 gelditzen da...
+rcm.config.max_level=Gehienezko maila
+splash.unloadingTorrents=Torrentak Ezgertatzen
+OpenTorrentWindow.tlf.rename=Berrizendatu Torrenta Goiko Mailako Agiritegi Aldaketan
+Peers.column.DLedFromOthers.info=Zurekin elkarketatutakoan beste batzuengandik jeitsitako datu zenbatekoa
+azbuddy.dchat.copy.magnet=Kopiatu Magneta Gakora
+ConfigView.section.security.nopw_v=Sarhitzik gabe eskuragarri, mesedez izena eman Vuzen
+devices.always.cache=Transkodeatu-Gabeko Agirientzako Katxea
+configureWizard.nat.unable=Ezin izan da azterketa egin\: Okerreko ataka eman da, edo azterketarako zerbitzuak huts egin du.\nAgian beste aplikazioren bat ataka hau erabiltzen ari da.
+ConfigView.section.ipfilter.autoload.file=IP iragazki agiria berezgertatzeko
+ConfigView.label.popupdownloadadded=Ohar alerta jeisketa gehitzen denean
+label.private.chat=Txat Pribatua
+azbuddy.ui.table.msg_in=Mezu Sarrera
+DonationWindow.noload.title=Egin Diru ekarpen bat
+MyTorrentsView.menu.export=XML Torrenta...
+TableColumn.header.ProgressETA=Garapena
+window.updateswt.ok=Ongi
+platform.jvmopt.sunonly=Sun JVM-ak bakarrik dira sostengatuta (oraingo hornitzailea\=%1)
+Subscription.menu.properties=Ezaugarriak...
+v3.MainWindow.menu.browse=&Vuzen
+security.certcreate.org=Erakundea
+ConfigView.section.transfer.select=Berez-Abiadura
+ClientStats.column.received=Jasota
+Views.plugins.Distributed.Tracker.title=Banaturiko Aztarnaria
+beta.wizard.info=Vuze beta programan bazkidetuz bezeroan aurrentasuna duzu argitalpenetan.\n\nHonek aukera ematen dizu argitalpen hauek probatzeko eta beren egokitzapenean laguntzeko - zure laguntza oso erabilgarria da guretzat\!\n\nBaina beta bertsioak berez ezegonkorrak izan daitezke, horrela ere aukera hau hautatuz argitalpen nahiko egonkorretarako sarrera izango duzu. Nahi baduzu mesedez erabili 'Beta Eguneratze' plugina.
+security.crypto.password=Sarhitza
+popup.download.added="%1" zure jeisketa zerrendara gehitu da.
+iconBar.remove.tooltip=Kendu hautatutako torrentak
+TableColumn.header.tag.name=Etiketa Izena
+Peers.column.UpRatio=Igoera Maila
+dlg.stream.plus.text=Berritu Vuze Plusera eta ikusi zure bideoak jeisten daudela.
+LocaleUtil.label.checkbox.rememberdecision=Gogoratu erabakia gelditzen diren agiri-izenetarako
+DHTView.operations.received=Jasoa
+download.removerules.removed.ok=Ongi buruturiko torrenteen '%1' berezgaitasunezko kenketa . Hau torrenteen kenketa arauengaitik zen.
+ConfigTransferAutoSpeed.data.update.frequency=Eguneratze Maiztasuna
+TableColumn.header.tag.initsaveloc={label.init.save.loc}
+TableColumn.header.torrentpath=Torrent Helbidea
+MyTorrents.column.ColumnProgressETA.PlayableIn=Irakurgarri %1
+iconBar.showDownloadBar.tooltip=Erakutsi Jeisketa Barra
+dht.execute.command=Igarpen komandoa
+Progress.reporting.default.error=Huts egin du
+TableColumn.header.pieces.info=Grafika barrak jeitsi dituzun atalak adierazten ditu
+SpeedTestWizard.abort.message.manual.abort=Eskuz utzita
+blank.resource=Baliabidea
+DHTView.activity.target=Xedea
+v3.deviceview.infobar.line2.psp=Bideoak zure PSP-ra kopiatu daitezke hau elkarketaturik dagoenean.
+ConfigView.label.maxuploadspeed=KB/s gehienezko abiadura igoera orokorrentzat [0\: mugagabea]
+platform.win32.baddll.nvappfilter=NVidia Suhesia
+IrcClient.defaultChannel=\#Azureus-Erabiltzaileak
+ConfigView.label.passwordmatchno=Ez / Sarhitza ez da zuzena
+devices.cat.show=Erakutsi kategoriak
+MyLibrary.bigView.header=Liburutegia
+configureWizard.finish.title=Osatuta
+ConfigTransferAutoSpeed.adjustment.interval=Zehaztu tarteak\:
+ConfigView.label.peers=Hartzaile
+jvm.show.file=Tokiko JVM aukera agiria da\: '%1' - Berreskurapenerako bakarrik editatu
+MyTorrentsView.menu.setSpeed.unlimited=Mugagabea
+TableColumn.header.downspeed.info=Oraingo jeisketa abiadura
+security.certcreate.strength=Indarra
+ConfigView.label.startwatchedtorrentsstopped=Hasi geldituta
+ConfigView.text.neverStop=Ez Gelditu Inoiz
+UpdateWindow.title=Vuze Eguneratzailea
+MyTorrentsView.\#=Zbk.
+TableColumn.header.RateIt=Maila
+label.show.selected.rates=Erakutsi Hautaturiko Gaien Mailak
+ConfigView.label.seeding.rankType.peer.tooltip=hartzaile gehiago eta emaritza gutxiago \= lerrun handiagoa\nLerrun honek gutxiagotu egiten du eraginda eduki behar diren torrent zenbatekoa igoera gehieneratzeko.
+label.tracker.selection=Aztarnari Hautapena
+subs.prop.enabled=Gaituta
+Main.parameter.maxUploads=Geh aldibereko igoera zenbatekoa
+ConfigView.label.downloading.info=Berezgaitasunez zehaztu jeisketa lerro kokapenak hobeto lan egiten du zure sarearen gaitasunaren araberako jeisketa abiadura muga zehaztasun zuzen bat ezartzen duzunean
+ConfigView.label.bStartNoMoreSeedsWhenUpLimitMetSlack=Igoera muga hurbilketa (murrizpen ehunekoa edo osoa KB/seg-kotan)
+general.enter.cookies=Sartu Cookiak
+wizard.invalidurl=URL hau baliogabea da
+TableColumn.header.maxuploads=Geh. Igoera Zenbatekoa
+ConfigView.section.tracker.client.scrapestoppedenable=Zuritu torrentak lanean ez daudenean
+SpeedView.stats.con_details=guztira\=%1, itogabe\=%2, lerrokatuta\=%3, eragotzita\=%4
+speedtest.wizard.select.group=Azterketa Mota
+PeersView.T.R.tooltip=Hartzaileak ezarri du elkarketa
+config.external.browser=Kanpoko Nabigatzailea
+v3.deviceview.infobar.line2.ps3=Bideoak jariotu zure PS3-ra joanez eta hautatuz Bideoak -> Vuze.
+ConfigView.section.transfer.lan.uploadrate=KB/s LAN geh. igoera abiadura [0\: mugagabea]
+TableColumn.header.Country=Herrialdea
+upnp.selectedaddresses=Helbideak (';' banandurik, '-' aurrizkia\=ukatu, '+' \=ahalbidetu) [hutsik\: ezer ez]
+wizard.newtorrent.byo.editname.text=Sartu gaiaren izena torrentean agertzen den bezala
+fileDownloadWindow.saveTorrentIn=Gorde torrent agiria hemen\:
+label.announce=Iragarri
+devices.choose.profile.title=Izenburua
+StartStopRules.waiting=Itxaroten
+ConfigView.label.seeding.rankType.peerSeed.tooltip=Maila Handiena \= Lerrun Handiena
+cat.upload.priority=Igoera Lehentasuna
+ConfigView.section.transfer.autospeed.enableauto=Gaitu jeisten eta emaritzen 
+PeersView.menu.kickandban.reason=Hartzailea eskuz eragotzia
+FancyMenu.Header.Social=Gizartea
+label.uptime_coarse=Jardun-denbora%1%2
+ConfigView.section.transfer.lan.downloadrate.tooltip=Barneko LAN bera ez duten hartzaile elkarketek jeisketa muga neurria banandua dute
+ConfigView.label.userequestlimiting=Erabili eskabide mugapena irakur atzerapenaren ordez jeisketa abiadura mugatzeko [ez du eraginik jeisketa abiadura mugagabea denean]
+MyTorrentsView.dialog.NumberError.text=Sartu duzun zenbakia baliogabea edo ezezaguna da.
+security.crypto.encrypt=Mesedez idatzi sarhitz bat sortu berri duzun enkriptaketa giltza babesteko. Mesedez ez ahaztu sarhitz hau, ez dago berreskuratzeko biderik egiten baduzu\!
+button.nothanks=Ez Mila esker
+Peers.column.handshake_reserved.info=Adierazten du zein bit izan ziren ezarriak BT eskuematean
+webui.pairingtest=\tEgin klik uztarpen azterketarako
+exportTorrentWizard.torrentfile.path=Helburua\:
+ConfigView.label.queue.retainforce=Aldatu 'behartu hastera' jeisketak 'behartu emaritza'-ra osatutakoan
+UpdateWindow.restartLater=Berrabiarazi Vuze Geroago
+devices.turnon.prepageload=Eginkizun hau abiatzeko, osagai gehigarri baten ezarpena beharrezkoa da.
+min.sr.window.title=Gutxinezko Elkarbanatze Maila
+azbuddy.dchat.anon.share.endpoint=Elkarbanatu izengabe torrent eta txat helmuga
+ConfigView.section.file.max_open_files=Gehienezko agiri ireki irakurtzeko/idazteko\n[0\: mugagabea]
+device.manu.desc=Egilea
+SubscriptionWizard.column.SubWizName={FilesView.name}
+TableColumn.header.eta=UED
+devices.choose.device.info.text=Hurrengoan, agiriak arrastatu eta askatu arrunt bat gailura edo hautatu itzazu Albobarran.
+ConfigView.section.tracker.announcecacheminpeers=Iragarle katxeak hartzaile muga gaitzen du
+ConfigView.label.openconfig=Ireki aukeren leihoa abiatzean
+ConfigView.section.style.defaultSortOrder.asc=Gorantz
+OpenTorrentOptions.header.torrentinfo=Torrentaren Argibideak
+GeneralView.section.downloaded=Jeitsita
+wizard.multitracker.title=Aztarnari-Anitz
+FileItem.donotdownload=Ez jeitsi
+swt.uninstall.window.header=Hurrengo osagaiak kenduak izaeko hautatuak izan dira\:
+FilesView.menu.setpriority.skipped=&Ez jeitsi
+ipCheckerWizard.explanations=Zure kanpoko IP helbidea zein den aurkitzeko erabil dezakezu laguntzaile hau. Zure IP helbidea dinamikoa bada, DNS Zerbitzu Dinamiko batekin kontua irekitzea aholkatzen dizugu. Beheko zerrendan zerbitzu horietako zenbait ematen ditugu, erabili loturak kontu bat sortzeko (sostengatuta dagoen tokietan). Ondoren, bete IP helbidearen eremua zure hostatatze-izen dinamikoarekin (adib. nireizena.dyndns.org). Aplikazio bat beharko duzu zure DNS Zerbitzu Dinamikoa ber [...]
+ConfigView.section.queue=Lerroa
+IrcClient.hasjoined=bat egin du
+MainWindow.menu.speed_limits=Abiadura &Mugak
+TagAddWindow.public.checkbox=Elkarbanatu etiketa izengabe herkidegoarekin
+PeersView.discarded.info=Nolabait jaso duzun datua, nahiz eta beharrezkoa ez izan, eta baztertu duzuna.
+group.auto=Berez
+ConfigView.section.connection.group.networks.info=Hautatu berez baimendutako sareak hartzaile-hartzaile datu igorpenerako
+label.con_prob=Elkarketa Arazoak
+MyTrackerView.status.started=Lanean
+device.config.xcode.disable_sleep=Saihestu ordenagailuaren lotaratzea transkodeatzerakoan
+ConfigView.label.minSpeedForActiveDL.tooltip=Jeisketa aho bat betik da erabilia lehen 30 segundutan\nosatugabeko torrenta hasi ondoren.
+azbuddy.dchat.nick.shared=Goitizena\: elkarbanatuta
+TableColumn.header.eta.info=Torrenta jeitsi arteko ustezko denbora
+MainWindow.menu.transfers.pausetransfersfor=Pausatu...
+MainWindow.menu.torrent=T&orrenta
+exportTorrentWizard.finish.message=Esportazioa ongi burutu da
+label.show.all=Erakutsi Denak
+TableColumn.header.torrentrelpath.info=Agiriaren kokaleku erlatiboa torrentean
+TableColumn.header.tag.uplimit={TableColumn.header.maxupspeed}
+authenticator.realm=Eremua
+MySharesView.type=Mota
+dlg.stream.plus.renew.subtitle=Vuze Plus Berritzea
+PeerSocket.unknown_az_style=Ezezaguna %1 %2
+ConfigView.section.connection.advanced.write_select=Idatzi hautatutako itxaron denbora (milaen, berez %1)
+splash.initializeGui=Leiho Nagusia Abiarazten
+upnp.ignorebaddevices.info=Orain baztertutako gailuak\: %1
+ConfigView.label.seeding.ignore0Peers=Baztertu 0 hartzaileko torrentak
+ConfigView.label.showuptime=Erakutsi Jardun-denbora
+devices.cancel_xcode_del=Ezeztatu Bihurketa/Kentzea
+manual.mode=Eskuz
+label.pin=Finkatu
+ipCheckerWizard.service.url=Lotura\:
+ConfigView.section.proxy.show_icon=Erakutsi SOCKS ikurra egoera eremuan gaituta dagoenean
+splash.of=->
+azbuddy.ui.table.loc_cat=Cats irteera
+OpenTorrentOptions.show.always=betik
+plugins.basicview.progress=Garapena\:
+ConfigView.section.connection.encryption.encrypt.fallback_info=Ordezko aukera gaitzeak bezero bateraezinekin elkarketak ahalbidetuko ditu BAINA elkarketa enkriptatu-gabeak izango dira
+resetconfig.warn=Honek Vuzeren itxurapenean egin dituzun aldaketa guztiak galtzea eragingo du./nJarraitu itxurapen berrezarpenarekin?
+dlg.auth.install.subtitle.plus=Vuze Plus ezartzen...
+OpenTorrentOptions.show.many=agiri 1 baino gehiago dagoenean bakarrik
+ConfigView.pluginlist.column.version=Bertsioa
+MyTorrentsView.menu.exportmenu=Esportatu
+ConfigView.section.connection.encryption.encrypt.info.link=Mesedez ikusi hemen xehetasunak
+MyTorrentsView.menu.moveUp=&Gora
+MyTorrents.column.ColumnProgressETA.2ndLine=UED\: %1
+label.spam=Spamtzailea
+v3.MainWindow.button.delete=Ezabatu
+MainWindow.status.updowndetails.tooltip=Jeisketa/Igoera abiadura xehatasunak\nEskuin-klikatu aldatzeko, Klik Bikoitza estatistikak irekitzeko
+Column.seedspeers.started.over=%1
+exportTorrentWizard.torrentfile.invalidPath=Torrent agiri baliogabea
+MyTorrentsView.menu.rename.save_path=Berrizendatu Gordetzeko Helburua
+Subscription.menu.upgrade=Gaitu Bertsio Handienera Eguneratzea
+installPluginsWizard.file.title=Mesedez bilatu ezarri nahi duzun plugina
+ConfigView.section.security.publickey.undef=Oraindikan zehaztu gabe
+MyTorrentsView.menu.tracker=Aztarnaria/&Torrenta
+MainWindow.statusText.checking=Bilatu Eguneraketak
+upnp.refresh.label=Berritu mapaketak
+swt.install.window.header=Hurrengo osagaiak ezarriak izateko hautatuak izan dira\:
+ManagerItem.stopped=Geldituta
+platform.win32.baddll.InjHook12=Torrent Maila Zaintzailea
+Button.dismiss=Baztertu
+UpdateWindow.ok=Eguneratu
+ConfigView.pluginlist.info=Hurrengo pluginak ezagutu dira. Plugin batzuek badaiteke ez izatea itxurapen hegatsik.
+security.crypto.title=Enkriptazio Giltza Sarbidea
+MainWindow.about.internet.homepage=Vuze Webgunea
+network.enforce.ipbinding=Betearazi IP loturak baita interfazeak eskuragarri ez direnean, saihestu edozein elkarketa adierazitako interfazeetako bat ere eskuragarria ez denean
+dlg.corewait.text=Une Bat Mesedez...\n\nZure eskaera Vuzek abiarazpena burutu ondoren bideratuko da.
+label.num.torrents=%1 {ConfigView.section.torrents}
+StartStopRules.menu.viewDebug=Ikusi Garbiketa Argibideak
+ConfigView.section.transfer.autospeed.enableautoseeding=Gaitu emaritzan bakarrik dagoenean
+FilesView.path=Helburua\:
+br.restore.warning.title=Kontuz Itxurapen Galera\!
+subscriptions.search.enable=Gaitu harpidetza emaitzetarako bilaketa (berrabiaraztea beharrezkoa)
+chat.view.create.chat=Sortu Txata
+ConfigView.label.prioritizefirstpiece.tooltip=Lehen agiri baten hasiera eta amaiera jeisteko saiakerak.\nAurreikuspen hasierak sostengatzeko.
+update.now.desc=Vuzek eguneraketak egitea behar du migrazioa osatzeko.\n\nElkarrizketa hau itxi ondoren Windowsi eskatu ahal diozu eguneraketa aurrerabidea osatzeko.\n\nVuzeren berrabiaraztea EZ da beharrezkoa.
+ConfigView.label.xfer.bias_no_limit=Bidea ezartzeko saiakera igoera muga orokor eraginkor bat ez dagoenean
+iconBar.openURL.tooltip=Ireki URL-a
+CacheView.general.inUse=Erabiltzen
+ConfigView.label.startRatioPeers=Hasi emaritzen emale bat baino gutxiago dagoenean
+TableColumn.header.CountryCode=HK
+Main.parameter.maxSpeed=Geh igoera abiadura byte/seg-ko
+#file can be a URL or a path in the jar
+MainWindow.menu.help.releasenotes=Argitalpen Oharrak
+option.rememberthis=Gogoratu ezarpen hau
+ConfigView.title.short=Aukerak
+FileItem.storage.reorder=Berrantolatu
+TableColumn.header.completion=Osaketa
+subscriptions.config.ratelimits=Maila mugak\: pare <hostalaria>\=<gutxiengo minutuak> zerrendak, kakotxaz bananduta
+TableColumn.header.commenticon=Aipamen Ikurra
+v3.menu.device.exploreTranscodes=Erakutsi Agiriak
+label.help=Laguntza
+pairing.view.registered=Klikatu ikusteko uneko izenemate xehetasunak
+ConfigView.dialog.choosewatchtorrentfolderpath=Mesedez hautatu .torrenten inportazio-zuzenbidea
+ConfigView.label.seeding.preferLargerSwarms.tooltip=Nagusiki 'buxatuta' dauden hartzaileekin emaritzen ari bazara torrentak, nahiago izatea erletalde handiagoak zentzua du\nNagusiki eskuragarritasun handiko torrentak emaritzen ari zarenean, nahiago izatea erletalde txikiak zentzua du.
+ConfigView.section.interface.cleartrackers=Garbitu gogoraturiko aztarnariak
+label.bar.trans=Barra gardentasuna [0\=argikaitza;100\=gardena]
+device.playnow.buffer=Buffer neurria irakurketak hasi aurretik [seg]
+MainWindow.menu.help.plugins=Lortu Pluginak
+proxy.socks.bad.incoming=Ez-Proxituriko barrurako elkarketak atzeman dira\!
+TrackerAvail.column.status={Trackers.column.status}
+v3.activity.remove.title=Ezabatu Jakinarazpena
+sidebar.LibraryDL.tooltip=Osatugabeko %1 torrent dago, hauetako %2 orain jeisten dago/daude
+menu.selectfilesinfolder=Hautatu %1-ko agiri guztiak
+OpenTorrentFile.column.size={TableColumn.header.size}
+devices.activation=Gailu Eragitketa
+MyTrackerView.status=Egoera
+sidebar.top.level.gap=Idazburu lerro arteko tartea ({ConfigView.section.security.restart.title})
+TableColumn.header.filesdone.info=Agiri eginda/Agiriak guztira *edo*  Jauzi-gabeko agiri eginda (Agiri eginda)/Jauzi-gabeko agiriak guztira (Agiriak guztira)
+ConfigView.section.transfer.lan.enable=Gaitu abiadura muga bananduak LAN elkarketentzat
+ConfigView.section.connection.advanced.SO_RCVBUF=Hartunea SE_RCVBUF neurria [0\: erabili SE berez]
+ConfigView.section.connection.advanced=Sare Ezarpen Aurreratua
+TableColumn.header.tag.discovery.name=Etiketa Iradokizuna
+MainWindow.upgrade.section.automatic=Berezgaitasunezko Eguneraketa
+TrackerView.title.full=Iturriak
+azbuddy.dchat.open.in.browser=Ireki Nabigatzailean
+FileItem.delete=Ezabatu
+ConfigView.section.connection.pairing.url=http\://wiki.vuze.com/w/UG_Aukerak\#Uztarpena
+ConfigView.label.bindip=Lotu tokiko IP helbidera edo interfazera
+MyTorrentsView.menu.exporttorrent=Torrenta...
+core.shutdown.se=emaritza burututa
+wizard.hint.file=Aholkua\: Arrastatu eta Askatuz hautatu dezakezu agiri bat
+subs.prop.auth=Egiaztapena beharrezkoa
+Button.sendNow=Bidali Orain
+upnp.mapping.udptrackerport=UDP Aztarnari Ataka
+label.click.to.change=Klikatu aldatzeko
+window.updateswt.text=Zure SWT Bertsioa zaharregia da\!\nSWT Vuzek erabiltzen duen grafika liburutegia da eta zuk duzun bertsioa zaharregia da Vuzeren azken bertsioarekin lan egiteko. Klikatu 'Ongi' botoia zure SWT-a eguneratzeko.
+wizard.tracker.ssl=Erabili SSL
+security.certcreate.cancel=Ezeztatu
+ConfigView.section.tracker.publishenable=Argitaratu torrent-aren xehetasunak "<tracker_url>"-era
+RCM.column.rc_level=Maila
+MyTorrents.column.ColumnSpeed=Abiadura
+deletecontent.also.deletetorrent=Ezabatu .torrent agiria ere
+externalLogin.title=Izenematea Beharrezkoa
+ConfigView.section.tracker.client.showwarnings=Erakutsi aztarnariek bidalitako kontuz\! mezuak
+label.DNS=DNS
+TorrentOptionsView.param.upload.priority=Igoera lehentasuna [0\=berezkoa;1\=lehentasunezkoa]
+dlg.auth.enter.link.try.2=<A HREF\="link">Klikatu hemen</A> oraindik ez baduzu Vuze Plusen kopia bat erosita.
+dlg.auth.enter.link.try.1=Ez duzu eragintza kode bat? <A HREF\="upgrade">Berritu orain</A>.
+chats.view.heading=Txat Gainbegirada
+config.dialog.shortcut.title=Ezarri Lastertekla
+Button.clear=Garbitu
+Peers.column.UpDownRatio.info=Hartzailearen "Igota\:Jeitsita" Maila
+ConfigView.label.seeding.firstPriority.FP=Lehentasun Nagusia
+subs.prop.update_period=Eguneratze epea
+tray.options=Erretilu Aukerak
+GeneralView.label.swarm_average_completion=Bataz-besteko Osaketa\:
+TableColumn.header.azsubs.ui.column.subs_link=Elkartasuna
+ConfigView.section.ipfilter.edit=Editatu
+ConfigView.label.bStartNoMoreSeedsWhenUpLimitMet=Ez hasi torrent gehiago emaritzarako igoera orokor muga erdietsitakoan
+device.od.error.opfailstatus=Gailuak huts egin du komando hau prozesatzerakoan %1\: egoera %2
+OpenTorrentWindow.fileTable.fileName=Agiri Izena
+azbuddy.dchat.open.magnet=Ireki Magneta Vuzen
+ConfigView.section.language.enableUpdate=Gaitu Web Eguneraketa
+dht.info=Plugin honek zentralizatu gabeko aztarnapena sostengatzen du, beste gauza batzuen artean, - ezgaituz gero zure jeisteko gaitasuna murriztuko da
+DevicesOD.column.od_remaining=Gelditzen dena
+library.unopened.header.p=%1 gai
+FileView.BlockView.Outstanding=Egikete
+label.num_queued=%1 Lerrokatuta
+ConfigView.section.file.delete.include_files_outside_save_dir=Datuak ezabatzerakoan, ahalbidetu torrentetik kanpo lotura duten agiriek zuzenbidea gordetzea hauek ere ezabatuak izateko 
+ConfigView.button.browse=&Bilatu...
+device.error.copyfail=Agiri Batek Edo Gehiagok Huts Egin Du Agiritegira Kopiatzean
+PeersView.piece=Atal
+download.removerules.unauthorised.seedingonly=\tEmaritzan bakarrik
+dlg.auth.revoked=Eragintza Kodea Indargabetuta
+br.restore.warning.info=Zure itxurapena leheneratzeak orain duzuna erabat ordeztuko du.\nKontuan izan ekin aurretik hau babeskopiatzea\!
+security.crypto.decrypt=Mesedez idatzi sarhitza zure enkriptaketa giltza irekitzeko.
+custom.settings.import.res=Inportatuta %1 ezarpen.%2
+label.missing=Ez dago
+ConfigView.section.server=Elkarketa
+TrackerChangerWindow.newtracker=Sartu aztarnari berriaren URL-a
+config.external.browser.switch.info=Barneko nabigatzailetik kanpokora aldatu dezakezu zenbait ezaugarrietarako baina eraginkortasun batzuk galdu daitezke
+tag.type.ds=Jeisketa Egoera
+TableColumn.header.transcode_status=Egoera
+security.crypto.persist_for.dont_save=Ez gorde
+general.add.friends=Gehitu lagun batzuk\!
+FilePriority.invalid.title=Lehentasun Baliogabea
+tag.type.ds.act={FileView.BlockView.Active}
+ConfigView.label.seeding.firstPriority.ignoreIdleHours=Ezer igo ez duten torrentak
+ConfigView.section.mode.advanced.wiki.main=Wiki Orrialde Nagusia
+remote.pairing.tip.text=Hurruneko Vuze Tresnabarra \: Joan hona <A HREF\="http\://remote.vuze.com/download/">remote.vuze.com/download</A>\nVuze Hurruneko Sakelekoa\: Joan hona <A HREF\="http\://remote.vuze.com/">remote.vuze.com</A> zure sakeleko nabigatzailean.
+devices.contextmenu.od=Lineaz-kanpo Jeisten
+tps.status.available=Eskuragarria
+MainWindow.menu.view.allpeers=Hartzaile Guztiak
+dht.advanced.group=Ezarpen aurreratuak
+PasswordWindow.passwordprotected=Vuze sarhitzez babestuta dago.\nVuzeren leihoa erakusteko, mesedez sartu zure sarhitza hemen\:
+GeneralView.label.downloaded=Jeitsita\:
+configureWizard.nat.message=Vuzerentzako irteera hoberena izateko osoki gomendatua da internetetik erabat eskuragarri egotea. Tresna honek aztertzea eta / edo sarrerako elkarketen onartzeko ataka aldatzea ahalbidetzen dizu.\n\n OHARRA\: TCP 6880 ataka barnean gordea da eta ezin da erabili.
+TableColumn.header.AzProduct=Hemendik
+ConfigView.complete.abbreviated=O\:
+ConfigView.section.sharing.rescanenable=Gaitu aldizkako birmihaketak elkarbanatzetan aldaketentzat
+azbuddy.dchat.public.nick=Elkarbanatutako goitizen publikoa
+iconBar.details=Xehetasunak
+ConfigView.label.seeds=Emaritza
+Button.save=Gorde
+DHTView.transport.sent=Bidalita
+azneti2phelper.install.reason.i2ptracker=Gehitzen ari zaren torrentak I2P aztarnari bat du.
+SpeedView.uploadSpeed.title=Igoera Abiadura
+TableColumn.header.torrentpath.info=Torrentak diskan duen helbidea
+fileDownloadWindow.state_error=Akatsa\:
+importTorrentWizard.process.outputfileexists.message=Irteerako agiria badago - gainidatzi?
+devices.sidebar.hide.rend.generic=Ezkutatu gailu generikoak
+v3.MainWindow.search.defaultText=Bilatu Torrentak...
+MyTorrentsView.menu.remove=K&endu
+v3.mb.delPublished.delete=&Ezabatu
+dlg.player.install.description=Irakurketa osagai gehigarria ezartzen...
+wizard.newtorrent.byo.editname.title=Editatu Gai Izena
+library.all.header=%1 Gai\: %2 Eraginda
+ConfigView.section.connection.group.webseed=Web/HTTP Emaritzak
+speedtest.wizard.test.mode.updown=igoera eta jeisketa
+ConfigView.section.file.writemblimit=Gehienezko idaz eskabide lerrokatuta (%1)
+ConfigView.section.security.resetkey=Berrezarri giltzak
+devices.turnon.qos=Elkarbanatu izengabeko gailu estatistikak Vuzerekin
+stream.analysing.media=Multimedia Aztertzen
+Button.finish=Amaitu
+v3.share.private.text=Hautaturiko torrenta Torrent Pribatu bezala markaturik dago\n\nEzin duzu torrent pribaturik elkabanatu.
+iconBar.down=Jeisketa
+TableColumn.header.chat.name=Txat Izena
+ConfigView.section.ipfilter.description=Azalpena
+ConfigView.section.file.perf.cache.size=Katxe neurria %1
+v3.mb.PlayFileNotFound.button.redownload=Birjeitsi Datuak
+label.route=Bidea
+torrent.comment.azmsgsync.install=Mezu Aldiberetze Plugina ez dago ezarrita edo txata ezgaituta dago - ikusi Tresnak-> Pluginak->Lagunak
+azbuddy.dchat.ro=Irakurtzeko bakarrik kanala
+devices.xcode.remove.vetoed='%1' Transkodeaketa garatzen, jeisketa ezin da kendu osatu arte edo transkodeaketa 'Gailuak' orrialdetik ezeztatuta egon arte.
+dhttracker.alt_port=Ataka [0\: zorizkoa]
+TableColumn.menu.date_added.reset=Berrezarri Eguna
+MainWindow.menu.window.minimize.keybinding=Meta+M
+ConfigView.section.file.perf.explain=Kontuz - Neurri hauen aldaketek kalterako eragin dezakete jeisketan. Berrabiarazpena beharrezkoa da.\n'oraimen gabe' arazoak badituzu torrent elkarketak mugatzea kontuan hartu beharko duzu. (Ikusi Eskualdaketa itxurapena)
+label.showhide.tag=Erakutsi / Ezkutatu Etiketa(k)
+configureWizard.finish.message=Orain Vuze itxuratuta dago, ondo izan \!
+importTorrentWizard.torrentfile.invalidPath=Torrent agiri baliogabea
+ConfigView.section.tracker.scrapecacheperiod=Zuripen katxea (smilaen)
+PeersView.C2.info=Hartzaileari jeisketa galarazten badiozu
+security.crypto.persist_for.day=1 egun
+MainWindow.menu.view.tagsoverview={tags.view.heading}
+v3.share.private.title=Torrenta Elkarbanatzen
+device.itunes.status.running=iTunes lanean dago
+mdi.entry.games=Jokoak
+importTorrentWizard.finish.message=Inportazioa ongi burutu da
+ConfigView.section.stats.defaultsavepath=Estatistikak gordetzeko zuzenbidea
+externalLogin.explanation.capture=Izena eman behar duzu eredu hau sortzeko. Egindakoan, mesedez klikatu "Eginda".
+ConfigView.section.dns.allow_socks=Erabili SOCKS proxy zerbitzariak hutsegiteak bilatzerakoan
+FilesView.done=Eginda
+security.certcreate.state=Estatua edo Herrialdea
+platform.win32.baddll.vlsp=Venturi Suhesia
+ConfigView.section.logging.choosedefaultsavepath=Hautatu gordetze zuzenbidea
+PluginDeprecation.log.start=Leiho honek Vuzeren hurrengo bertsioetatik kenduuak izan daitezkeen pluginei buruzko argibideak ditu.\nEz duzu pluginak kendu beharrik, azken bertsiora eguneratu ditzakezu.\nAzken bertsioarekin ari bazara lanean, mesedez kopiatu leiho honetako edukiak eta argitaratu itzazu eztabaidagune honetan\:\n \t%1\n\n
+TableColumn.header.peakdown=Jeisketa Gailurra
+Column.seedspeers.notstarted=%2
+Plugin.localtracker.autoadd=Ageriko hartzaileak
+TableColumn.header.Quality=Ontasuna
+ConfigView.label.use_old_speed_menus=Erabili estilo zaharreko abiadura menuak [berrabiaraztea beharrezkoa]
+ConfigView.label.seeding.rankType.seed.fallback=Hartzaileentzako Gordeta\: Emaritza Maila ondoren  \n(0 \: Inoiz Ez Gordeta)
+devices.contextmenu.od.enabled=Gaiturik
+TableColumn.header.totalspeed.info=Hona elkarketaturik dauden hartzaile guztien Abiadura Guztira
+OpenTorrentFile.column.\#=Zenb.
+ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Behartu enkriptatutako elkarketak erabiltzera beste hartzaile batzuekin
+message.confirm.delete.text=Zihur zaude '%1' ezabatzea nahi duzula?
+label.anon.short=A
+azbuddy.dchat.status.nohandler=Akatsa\: Ez dago mezu kudeatzailerik eskuragarri
+chats.view.infobar.text2=Honek monitorizatzen/eskuhatzen ari zaren txat ugariren argibideak erakusten ditu. Ikusi Wikia argibide gehiagorako <a href\="{azbuddy.dchat.link.url}">hemen klikatuz...</a>
+chats.view.infobar.text1=Txat Gainbegirada
+Progress.reporting.status.canceled=Ezeztaturik
+dlg.install.vuzexcode.description=Mesedez itxaron Media Aztergailuaren osagaia ezartzen den bitartean
+iconBar.play.tooltip=Irakurri hautaturiko edukia
+Wizard.Subscription.rss.subtitle3=Behin gordeta, zuzeneko harpidetzak jasoko dituzu zure albobarran zure RSS jarioen bidez emaitza berriak eskuragarri dauden bakoitzean
+SpeedTestWizard.set.limit.conf.level=Segurtasuna
+fileplugininstall.install.title=Plugina Ezarri?
+Wizard.Subscription.rss.subtitle2=Argitaratzaile zenbaitzuk RSS jarioak eskaintzen dituzte beren edukientzat.  Helbiditu  URL-a argitaratzailearen webgunean, kopiatu eta itsati URL-a gaineko eremuan, orduan klikatu Gorde.
+Wizard.Subscription.rss.subtitle1=Idatzi edo itsasi URL-a ondoren\:
+ManagerItem.error=Akatsa
+azbuddy.ui.menu.verify=Egiaztatu Gakoa
+ConfigView.section.connection.port.rand.together=TCP eta UDP-rako ataka bera
+v3.splash.initSkin=EI Azala abiarazten
+OpenTorrentOptions.header.filesInfo.some=%1 -> %2 Agiritik\: %3
+ConfigView.section.style.colorOverrides.reset=Berrezarri Margoa
+restart.error.pnf='%1' Helburua ez da aurkitu
+TableColumn.header.bad_avail_time=Kopia Osoa Ikusita
+ConfigView.section.security.group.crypto=Publikoa/Pribatua Giltzak
+PeersView.I1.info=Interesaturik zaude beste hartzaile batek duen agirian?
+ConfigView.section.files.move=Osaketa Mugitzen
+FileView.BlockView.Skipped=Jauzita
+ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Aukera honek Liburutegi ikuspegia berritzen du nahiz eta begien aurrean ez egon (erabilgarria zenbait mirc pluginentzako)
+TableColumn.header.SeedingRank.info=Torrentak zein gaizkiro behar duen emaritzea adierazten duen balio maila. Balio handiagoak behar handiagoa esanahi du
+MyTorrentsView.menu.setpriority=Ezarri &Lehentasuna
+ConfigView.section.proxy.enable_proxy=Gaitu proxya aztarnariarekiko harremanetarako [berrabiaraztea beharrezkoa]
+ConfigView.label.openstatsonstart=Ireki Estatistikak hasitakoan
+device.model.desc=Ereduaren azalpena
+ConfigView.section.ipfilter.blockbanning=256 helbideko bloke baten eragozpena gutxienez zenbateko hau blokean eragotzia izan denean 
+TorrentOptionsView.title.short=Aukerak
+MainWindow.menu.file.restart=Berrabiarazi &Vuze
+azbuddy.os_busy=Lanpetuta
+ConfigView.section.style.forceSIValues=Behartu balioak erakutsiak izateko IEK balio bezala ondorengo helburuekin erabilitako erakusleihoa edozein izanda ere. (adib. 1MB \= 1MiB \= 1048576B)
+OpenTorrentWindow.startMode=Gehitu Modua
+Button.selectAll=Hautatu Denak
+ManagerItem.checking=Egiaztatzen
+ConfigView.group.scrape=Zuritzea
+v3.deleteContent.message=\nEzabatzea nahi duzu '%1' zure ordenagailutik, edo zure Vuze Liburutegitik kentzea besterik ez?
+TableColumn.header.AvgAvail=Bataz-besteko Eskurg/atal
+popup.next=>
+wizard.mode=Aztarnaria / Modua
+ConfigView.section.transfer.lan.uploadrate.tooltip=Barneko LAN bera ez duten hartzaile elkarketek igoera muga neurria banandua dute
+azbuddy.ui.menu.ygm=Bidali MBD
+SystemTray.menu.stopalltransfers=Gelditu &Eskualdaketa Guztiak
+ConfigView.label.seeding.firstPriority=Lehentasun nagusia doa hau duten torrentetatik
+OpenTorrentOptions.show.never=inoiz ez berriro
+ConfigView.pluginlist.whereToPutOr=Elkarbanatutako pluginentzat erabili\:
+ConfigView.section.style.graphicsUpdate=Eguneratu Grafika barrak EIG-aren Z eguneratzetik behin
+ConfigView.section.security=Segurtasuna
+SpeedTestWizard.test.panel.not.accepted=Azterketa eskabidea ez da onartu\:
+label.copy.to.clipboard=Kopiatu Gakora
+ConfigView.label.seeding.addForSeedingDLCopyCount=Hartu 'emaritzarako gehitutako' jeisketatzat kopia zenbateko hau duten jeitsierak
+ConfigView.label.autoopen=Berez Irekitzea
+CategoryAddWindow.title=Gehitu Kategori Berria
+FileProgress.stopped=Geldituta
+ConfigView.section.transfer.autospeed.chokeping=Itopen ping aldiak [segundu milaenetan] 
+wizard.multitracker.edit.text.title=Sartu Aztarnari Xehetasunak
+FilePriority.invalid.text=Balio baliogabea sartu da, osoa behar da\: %1
+installPluginsWizard.mode.title=Mesedez hautatu ezarpen bide bat
+FilesView.rename.confirm.delete.title=Baieztatu Ezabaketa
+MyTrackerView.webui.contextmenu.copyurl=Kopiatu torrentaren URL-a gakoan
+ConfigView.section.logging.timestamp=Denbora irarketa heuskarria ohar agirientzat
+RCM.column.rc_new=Irekigabe
+TableColumn.header.up=Igota
+configureWizard.transfer2.group=Modua
+ConfigView.label.seeding.ignore.header.rule=Araua
+PeersView.T=ELK
+PeersView.S=Baztertuta
+TableColumn.header.TableColumnNameInfo=Zutabe Izena eta Azalpena
+OpenTorrentWindow.startMode.stopped=Geldituta
+UpdateConstraint.title=Eguneraketa Mugak
+ConfigView.label.seeding.ignore.header.value=Balioa
+v3.deviceview.infobar.line2.xbox=Jarioatu bideoak zure Xbox 360-ra joanez eta hautatuz Nire XBox -> Bideo Liburutegia -> Vuze.
+Formats.units.TB=TB
+beta.wizard.off=Pozik nago argitaraturiko bertsioekin, ez eskerrik asko\!
+SpeedTestWizard.finish.panel.title=Abiadura Azterketa Amaiturik\!
+MyTorrentsView.menu.rename.displayed.enter.message=Sartu jeisketa honentzat erakusteko izen berri bat.
+DHTView.db.values=Balioak
+ConfigView.section.stats.savefile=Estatistiken agiri izena
+MyTorrentsView.menu.showdownloadbar=Erakutsi &Jeisketa Barra
+br.backup.folder.title=Hautatu Babeskopia Agiritegia
+PiecesView.blocks=Blokeak
+apply.selected.template=Ezarri Hautaturiko Eredua
+IrcClient.disconnected=Etenda hemendik\:
+PeersView.optunchoke=Auk. Itogabe
+azbuddy.dchat.general.chats=Txat Orokorrak
+Scrape.status.initializing=Zuritzeko itxaroten...
+ManagerItem.low=Txikia
+TableColumn.header.tag.public.info={tag.share}
+label.beta=Beta
+GeneralView.label.hash=Hasha\: 
+ConfigView.section.style.dropdiraction=Arrastatu eta Askatu ekintza zuzenbideentzat
+pairing.ac.getnew.create=Sortu
+ConfigView.section.file.defaultdir.lastused=Eguneratu berezko zuzenbidea gordetako azken helbidera
+PeersView.%=Jeitsitako Ehunekoa
+MyTorrentsView.menu.eta.abs=Erakutsi UED denbora oso bat bezala
+Progress.reporting.action.label.cancel.tooltip=Ezeztatu eragiketa
+ConfigView.label.udplistenport=UDP aditze ataka
+ConfigView.label.seeding.rankType.timedRotation=Denboratutako Itzulikapena
+jvm.max.mem.current=Oraingo Pilo gehiena da\:  %1
+fileplugininstall.duplicate.title=Bikoiztu Plugina
+ConfigView.section.connection.encryption.use_crypto_port=Erabili 'kriptoataka' aztarnari hedapena sarrera lauko elkarketa saiakerak saihesteko. Aztaranari batzuek ez dute onartzen hau eta  honelako akatsak dituzte "Atata Okerra' edo 'Legezkanpoko gatazka'
+v3.MainWindow.menu.games=Jolasak
+ConfigView.section.display=Ikusi
+ConfigView.section.style.status.show_sr=Elkarbanatze Maila
+label.checking.sources=Jeisketa iturburu eskuragarritasuna egiaztatzen
+FilesView.rename.filename.text=Hautatu izen berri bat agiriarentzat
+exportTorrentWizard.exportfile.browse=Bilatu
+unix.script.new.button.quit=Utzi Orain
+TableColumn.header.sessiondown=Saio Jeitsiera
+label.proxy=Proxya
+exportTorrentWizard.exportfile.invalidPath=Esportazio agiri baliogabea
+MainWindow.menu.view.plugins.logViews=Saio Ik&uspegiak
+v3.MainWindow.tab.publish=Argitaratu
+RCM.column.rc_created=Sortua
+LocaleUtil.column.text=Idatzi Ezezaguna
+label.show.tag=Erakutsi Etiketak
+v3.MainWindow.button.stop=Gelditu
+wizard.webseed.adding=HTTP Emaritzak Gehitzen
+dht.warn.user=Jakinarazi balizko NAT/ ataka mapaketa arazoak
+v3.MainWindow.menu.view.asAdvancedList=Zerrenda Aurreratua
+ConfigView.section.logging.generatediagnostics.info=Sortu igarpen argibideak eta kopiatu gakora eta ohar agira, ezarrita badago
+ConfigView.section.tracker.client.scrapeinfo=Zuritzea ezgaituz torrent askoren lerrokatzea saihestu daiteke, lanerako erletaldeko argibideak berreskuratzean aztarnariak zurituz ohinarritzen baitira.
+ConfigView.section.style.ShowFancyMenu=Erakutsi Fancy Menua (Berrabiaraztea Beharrezkoa)
+device.router.view.title=Bideratzaileak
+TableColumn.header.unopened.info=Torrenta irakurria izan den adierazteko ikurra (irekita)
+ConfigView.label.sleep=Lotarazi
+ConfigView.section.tracker.passwordenabletorrent=Gaitu sarhitza torrentetan
+Pieces.column.\#.info=Atal  Zenbakia
+ConfigView.section.tracker.createbutton=Sortu
+menu.sortByColumn=Antolatu %1 arabera
+devices.button.installitunes=Ezarri iTunes Baterapena
+device.autohide.alert=%1 gailua(k) ezkutatu egin d(ir)a online ez egoteagaitik %2 egunez.\nIkusi Tresnak->Aukerak->Gailuak jokabide hau itxuratzeko.\nEskuin-klikatu 'Gailu Irakurketa' albo barran ezkutuko gailuak erakusteko.
+TableColumn.header.size=Neurria
+ConfigView.section.style=Interfazea
+dlg.corewait.title=Core-a Abiarazten
+ConfigView.section.transfer.select.v2=Berez-Abiadura (beta)
+ConfigView.section.tracker.pollinterval=Aztarnariaren bezeroa zenbatero zundatuko den (segundoak)
+ConfigView.section.tables=Aurkibideak
+CacheView.reads.hits=Kolpeak
+br.backup.auto.dir.select=Mesedez hautatu berezko babeskopia zuzenbidea
+natpmp.info=NAT-PMP Apple-n UPnP aukera da eta berriki Hegazkaietan ere sostengatua da\n\nJakin ezazu orain duzun UPnP gaituta dagoela NAT-PMP gaitzeko NAT-PMP gailu bezala UPnP gailu mota berezitzat hartzen da 
+webui.i2p_dest=I2P helbidea
+UIDebugGenerator.message.cancel.title=Garbiketa Argibidea Sortzea Ezeztatuta
+MyTrackerView.date_added=Gehituta
+MyTorrentsView.menu.setSpeed.disable=Ezgaitu Igoera
+Wizard.Subscription.subscribe.library.empty=Ez dago harpidetza eskuragarririk?\n \nBilatu margo laranja dizdiratsuko harpidetza botoia Vuze HD Sarean.\n \n<A HREF\="http\://wiki.vuze.com/w/FAQ_Harpidetzak">Irakurri gehieago</A>
+ConfigView.label.priorityExtensions=Berez-lehenetsi agiri mota hauek\: \n - adib\: .txt; .nfo; .jpg
+wizard.webseed=Gehitu HTTP Emaritzak torrentetik
+iconBar.openNoDefault.tooltip=Ireki .torrent agiria (ez gorde berez)
+IrcClient.copyright=PircBot Java IRC API erabiltzen - http\://www.jibble.org/pircbot.php
+ConfigView.section.connection.advanced.url=http\://wiki.vuze.com/w/UG_Options\#Sare_Ezarpen_Aurreratuak
+OpenTorrentWindow.mb.badSize.title=Agiri Bateraezina
+custom.settings.import.title=Inportatu Itxurapen Ezarpenak?
+dlg.auth.enter.expiry=Oraingo eragintza kodea iraungitzen da %1.
+MyTorrentsView.menu.host.error.message=Torrenta hostatatzean hurrengo akatsa gertatu da
+azbuddy.ui.menu.remove=Kendu
+DHTView.db.divfreq=Maiztasun Dib.
+ConfigView.section.proxy.dns.info=Ikusi Elkarketa->DNS itxurapena DNS zerbitzari gehigarria adierazteko proxy erabakirako.
+Peers.column.timetocomplete.info=Hartzailea osatuta dagoen arte gelditzen den denbora
+MainWindow.nat.status.unknown=NAT
+OpenTorrentWindow.addFiles.URL=Gehitu &URL-a
+ConfigView.label.seeding.rankType.timedRotation.tooltip=Lerrokatutako torrent osatu guztiak emaletzen moduan itzulikatuko dira.\nEmaletze denbora 'Gutxiengo Emaletza Denbora' bidez ezartzen da
+MyTorrentsView.menu.thisColumn.toClipboard=Kopiatu Idatzia Gakoan
+azbuddy.addtorrent.msg=Laguna '%1' bidali dizu '%2'.\nJeisketa hau gehitzea nahi duzu?
+v3.activity.header.downloads=Jeisketak
+TorrentDetailsView.filter=Bilatu agiriak...
+ConfigView.section.ipfilter.editFilter=Editatu Iragazkia
+mb.azmustclose.text=Vuzek amaitu beharra du arazo bat dagoelako Vuzeren (bir)abiaraztean zihurrenik programa erabiltzaile administrari bezala exekutatu izanak eragin duena.\n\nVuze itxi ondoren, mesedez bir-ireki eskuz.
+MyTorrentsView.menu.movemenu=Mugitu Agiriak
+v3.splash.hookPluginUI=Elkarketatzen IU Pluginean
+v3.MainWindow.tab.home=Tresnategia
+ConfigView.section.security.unlockkey=Irekitze giltza bereziak
+PeersView.connected_time.info=Hartzailearekin elkarketaturik emaniko denbora guztia
+MyTrackerView.bytesin=Sar. Byte
+ConfigView.section.file.perf=Egintza Aukerak
+security.crypto.persist_for.30days=30 egun
+installPluginsWizard.list.description=Pluginaren azalpena
+MainWindow.dialog.select.vuze.file=Hautatu Vuze Agiria
+label.right.click.for.options=Eskuin-klikatu aukeratarako
+ConfigView.section.transfer.autospeed.latencyfactor=Ezkutuko aldaketak abiadura aldaketekin lotzeko erabiltzen den ezaugarria (zenbaki luzeek sentikortasuna murrizten dute)
+label.out=Kanpoa
+Progress.reporting.window.remove.now.tooltip=Kendu osaturiko, huts eginiko, edo ezeztaturiko aurrerabide guztiak ikuspenetik
+ConfigView.section.mode.beginner=Hasiberria
+br.restore.folder.title=Hautatu Leheneratze Agiritegia
+ConfigView.section.plugins.dht=Banaturiko DB
+platform.jvmopt.nolink=Ezin dira JVM aukerak kudeatu dagoen itxurapenak eragotzi egiten duelako
+ConfigView.section.connection.encryption.min_encryption_level=Gutxienezko enkriptaketa maila
+ConfigView.section.transfer.autospeed.minupload=%1 gutxienezko igoera abidadura
+ConfigView.label.seeding.firstPriority.ignoreSPRatio=Emaritza-Hartzaile maila gehiago duten torrentak
+tag.discovery.view.options=Aukerak
+core.shutdown.dl=jeisketak burututa
+label.click.to.restore=Klikatu Leheneratzeko
+ConfigView.section.tracker.scrapeandcache=Zuripena eta katxea
+ConfigView.label.seeding.firstPriority.ignore0Peer=0 Hartzaileko Torrentak
+ConfigView.section.proxy.port=Ataka
+Button.cancel=E&zeztatu
+Peers.column.maxupspeed=Geh. Igoera Abiadura
+label.init.save.loc=Hasierako Gordetze Kokalekua
+TableColumn.header.sr_prog=Elkarbanatze Maila Garapena
+CacheView.reads.\#=Zenb.
+MainWindow.menu.tools.speedtest=Abiadura Azterketa...
+MainWindow.menu.window.alltofront=Mugitu denak &aurrera
+azbuddy.dchat.node.status=%1%2Elkargune\=%3, Eskabideak\=%4
+subs.ext.view.info=Vuze harpidetza emaitzak erakusteko kanpoko nabigatzaile bat erabiltzeko itxuratuta duzu
+azbuddy.ui.menu.cat.set=Sartu kategoria
+ConfigView.label.seeding.rankType.peer=Berdingarritutako Hartzaile Zenbaketa
+OpenTorrentWindow.addFiles.Clipboard=Gehitu Ga&kotik
+plugin.sharing.remove.veto=Elkarbanatze hau elkarbanatze 'zuzenbide edukiak' azpi-elkarbanatze bat da eta ezin da ezabatua izan.\n Ezabatu erro elkarbanatze
+ConfigView.group.irctitle=IRC Ezarpenak
+Torrent.create.progress.totalfilecount=Agiri zenbateko osoa\: 
+download.removerules.updatetorrents=Kendu Vuze eguneratze torrentak erletaldeak eskatzen badu
+TableColumn.header.tag.type={MySharesView.type}
+plugin.aznetstatus.pingtarget=Ping/zantzu bide xedea (Packet INternet Groper\=INternetako Pakete Eskuztatzailea)
+Trackers.column.peers=Hartzaileak
+LoggerView.pause=Pausatu Saio hastea
+ConfigView.label.usefastresume=Erabili Berrekite Azkarreko aukera
+speedtest.wizard.test.mode.down=jeitsi
+MainWindow.menu.window.minimize=&Ikurtu
+devices.xcode.only.show=Erakutsi Bakarrik Transkodeatutako Agiriak Gailuan
+ConfigView.pluginlist.column.isOperational=Eragiketakor?
+ConfigView.label.savetorrents=Gorde .torrent agiriak
+external.browser.failed=Kanpoko Nabigatzaile Hutsegitea
+GeneralView.yes=Bai
+TableColumn.header.tag_colors=Etiketa Margoak
+Wizard.Subscription.optin.title=Gaitu Harpidetzak
+Formats.units.MB=MB
+health.explain.grey=Esanahi du zure torrenta ez dagoela (ez jeisten ez igotzen)
+configureWizard.file.title=Torrentak / Agiriak
+ConfigView.section.style.status.show_rategraphs=Erakutsi bataz-besteko historia grafikak jeisketa/igoera idatzien azpian
+library.incomplete.header.p=%1 gai jeisten, %2 itxaroten jeisteko
+PeersView.client.info=Hartzaileak erabiltzen duen BT bezero mota 
+DownloadManager.error.unabletostartserver=Ezgaitu Hasi Zerbitzaria - egiaztatu sarrera atakaren ezarpenak / suhesi baimenak aplikazioa zerbitzari bezala jarduteko
+exportTorrentWizard.process.inputfilebad.message=Hutsegitea gertatu da hurrengo sarrera agiria atzitzean\:
+ConfigView.label.seeding.firstPriority.DLMinutes=Igarotako denbora jeisten hastetik
+Button.bar.show=Erakutsi
+GeneralView.label.maxuploads=Igoera Ahoak\:
+DHTView.activity.title=Jarduera
+importTorrentWizard.importfile.browse=Bilatu
+ConfigView.label.popupdownloadfinished=Erakutsi alerta leihoa jeisketa burutzen denean
+ConfigView.section.style.status.show_ipf=IP Iragazki Egoera
+TrayWindow.menu.close=Itxi Jeisketa Saskia
+devices.sidebar.oxc.pm.4=Lotaratu
+devices.sidebar.oxc.pm.2=Neguratu
+devices.sidebar.oxc.pm.1=Itzali
+ConfigView.label.quickviewmaxkb=Geh. agiri neurria [KB]
+MainWindow.dht.status.initializing=DHT-a Abiarazten
+security.crypto.pw.title=Sartu Sarhitza
+importTorrentWizard.process.torrentfail.title=Torrentaren Idazketa Hutsegitea
+ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Elkarbanatze Edukiak (Baliabidegarria)
+ConfigView.section.style.units=Erakutsi Batasunak
+TableColumn.header.TableColumnInfo=Zutabe Azalpena
+TrackerClient.announce.warningmessage=Aztarnaria '%1' larri itzuli da '%2'
+ConfigView.pluginlist.whereToPut=Ezarri erabiltzaile osagarri bereiziak zeure zuzenbidean\: 
+message.status.success=Gertaerak
+ConfigView.section.proxy.password=Sarhitza
+MainWindow.menu.window.zoom.restore=Txikiagotu
+ConfigView.section.file.save.peers.max=Gehienezko hartzaile gordetzeko [0\:mugagabe]
+ConfigView.section.file.defaultdir.autorename=Berez berrizendatu torrent datuak agiriak helburuan ezberdinak ikusten badira
+PeersView.downloadspeedoverall=Jeisketa Abiadura Guztira
+PiecesView.DistributionView.weHave=Dituzun atalak
+device.mediaserver.remove_all.title=Baieztatu Kentzea
+Formats.units.KB=KB
+OpenTorrentWindow.filesInfo=%1 %2-tik izango dira jeitsiak.
+device.show=Erakutsi Ezkutatu Gailuak
+#There is a plugin to help with internationalizing these bundles at http://plugins.vuze.com/plugin_list.php
+MainWindow.menu.file.open.torrent=Torrent Agiria...
+uninstallPluginsWizard.finish.title=Kentzearen Garapena
+ConfigView.section.style.forceMozilla=Behartu Vuze Mozilla erabiltzera tresnak Bilatzeko [xulrunner edo firefox 3 beharrezkoa; berrabiaraztea beharrezkoa]
+sidebar.header.transfers=Agiriak
+TagGroupWindow.message=Sartu multzoaren izena
+ConfigView.label.seeding.fakeFullCopySeedStart=baina gutxienez duten torrententzat bakarrik 
+update.instance.update=Eguneraketak Egiaztatzen
+label.plugin.options=Plugin Aukerak...
+UpdateMonitor.messagebox.verification.failed.title=Ezarpen Egiaztapenak Huts egin du
+FileItem.normal=Arrunta
+MyTorrentsView.menu.move=&Mugitu
+FilesView.priority=Lehentasuna
+label.classic=Klasikoa
+upnp.mapping.dataportudp=UDP aztarnari bezero ataka
+DownloadActivityView.legend.peeraverage=Erletaldea
+SpeedTestWizard.set.upload.result=Azken Azterketaren Emaitza
+ConfigView.section.style.showProgramIcon.tooltip=Ikusik bir-irekitzea behar izan dezake aldaketak eragina izan dezaten
+IrcClient.topicforchannel=Gaia kanalerako
+ConfigView.section.logging.maxsize=Gehienezko ohar agiriaren neurria
+ConfigView.label.seeding.firstPriority.ignore.info=Kontuan izan arau hauek erabiliz torrenta gelditzea gertatu daitekela\njeisketa amaitu bezain laister.
+authenticator.tracker=Aztarnaria
+devices.view.title=Gailuak
+azbuddy.ui.mykey=Nire giltza\:
+wizard.maketorrents.init.tags=Hasierako etiketak (','-z bananduta)
+OpenTorrentWindow.fileList=Agiri torrentetan\:
+ConfigView.dialog.choosedefaulttorrentpath=Mesedez hautatu berezko torrent zuzenbidea
+iconBar.queue.tooltip=Hasi (lerrokatuta) hautaturiko torrentak
+installPluginsWizard.file.browse=Bilatu...
+subs.prop.last_error=Azken akatsa
+label.complete=Osatua
+tag.type.ds.inact={label.inactive}
+v3.MainWindow.tab.library=Liburutegia
+MainWindow.status.latestversion=Azkena
+health.explain.red=Esanahi du ez zaudela inolako hartzailera elkarketaturik jeisketan zehar
+installPluginsWizard.title=Ezarri Pluginak
+configureWizard.nat.server.udp_listen_port=Sarrerako UDP Aditze Ataka
+webui.port.override=Ataka ezeztatua\: beharrezkoa da bakarrik NAT-aren itxurapenagaitik ataka publikoa eta barneko egoitza ezberdinak direnean.
+TrackerAvail.column.leechers.info={Trackers.column.leechers.info}
+security.certcreate.title=Sortu Bere-Sinatze Egiaztagiria
+DetailedListView.title=Zerrenda Zehatza
+OpenTorrentWindow.fileTable.destinationName=Helmuga Izena
+ConfigView.label.strictfilelocking=Betearazi bazterketa agiri idazketa sarbide itxipena torrenteetan
+FilesView.menu.setpriority.numeric.auto=Zenbakizkoa -Berez Gutxiagoratzen
+TransferStatsView.legend.ping3=3 Xedea
+TransferStatsView.legend.ping2=2 Xedea
+TransferStatsView.legend.ping1=1 Xedea
+PeersView.port.info=Erabiltzen ari den ataka
+ConfigView.section.connection.network.max.simultaneous.connect.attempts=Gehienezko aldibereko irteera elkarketa ahalegin
+DHTView.general.nodes=Elkarguneak\:
+ConfigView.label.openconsole=Ireki kontsola abiatzean
+MainWindow.menu.file.create.fromfile=&Agiri &batetik
+ConfigView.section.file.perf.cache.enable=Gaitu diska katxea
+VivaldiView.title.fullcvs=Vivaldi CVS-a
+TableColumn.header.SeedingRank=Emaritza Maila
+ConfigView.section.connection.encryption.encrypt.group=Garraio Enkriptazioa/Itsutzea
+SpeedTestWizard.test.panel.enc.label=Sakatu enkriptaketarekin aztertzeko\: 
+Button.sendManual=Eskuzko Bidalketa (sortu .zip)
+MyTorrentsView.menu.create_personal_share=Sortu Norbere Elkarbanatzea
+azbuddy.dchat.share.fail.title=Elkarbanatze Hutsegitea
+dlg.auth.title=Eragintza
+MainWindow.status.latestversion.clickupdate=Egin klik eguneratzeko
+TableColumn.header.availability=Eskuragarritasuna
+IPChecker.external.service.discoveryvip.description=Discoveryvip - IP helbidearen egiaztatzea bakarrik
+MainWindow.upgrade.section.info=Bertsio Berria Eskuragarri
+upnp.alertdeviceproblems=Jakinarazi UPnP gailuarekin izandako arazoak
+PeersView.incomingreqcount=Sarrera Eskabidea
+v3.MainWindow.button.comment=Aipamena
+MainWindow.menu.file.share.dircontents=Agiritegi &Edukiak...
+IrcClient.haskicked=kanporatua izan da
+configureWizard.transfer2.mselect=Hautatu zure elkarketaren IGOTZE abiadura muga
+ConfigView.label.pauseresume=Berez-pausatu/berrekin
+MainWindow.status.update.tooltip=Klik bikoitza garapen argibideak ikusteko
+UpdateMonitor.messagebox.accept.unverified.text='%1' ez da Vuzeren plugin ofizial bezala egiaztu ahal izan.\nJarraitu behar EZ duen plugina bada.\nEzarpena egin?
+swt.uninstall.window.title=Vuze Osagai/Plugin Kentzailea
+MainWindow.menu.closealldetails=Itxi &Xehetasun Guztiak
+Progress.reporting.action.label.retry.tooltip=Birsaiatu eragiketa
+MyTorrentsView.mytorrents=Liburutegia
+Subscription.menu.reset=Berrezarri Hasierako Egoera
+br.restore=Leheneratu
+pairing.status.pending=Eguneraketa burutuko da %1
+ConfigView.option.dm.dblclick.play=Irakurri Edukia
+devices.sidebar.oxc.closevuze=Utzi Vuze
+CacheView.reads.fromCache=Katxetik
+ConfigView.section.ipfilter.end=Amaierako IP-a
+dlg.auth.trial.title=DVD Grabaketa Proba
+PeersView.T.info=L (tokikoa)\: zuk ezarri duzu elkarketa, R (hurrunekoa)\: hartzaileak ezarri du elkarketa.
+tag.sharing.enable.text=Nahi duzu zure etiketa/kategoria esleipenak izengabe herkidegoarekin elkarbanatzea?\n\nHonek beste erabiltzaileei beren jeisketak antolatzen lagunduko die.\n\nEskuin-klikatu etiketak/kategoriak albobarran banakako ezarpenak aldatzeko beharrezkoa bada.
+MyTrackerView.status.published=Argitaratuta
+Formats.units.GB=GB
+PeersView.BlockView.NextRequest=Hurrrengo Eskabidea
+v3.MainWindow.Loading=Gertatzen... Mesedez Itxaron
+azbuddy.ui.menu.send_msg=Sartu zure lagunari bidaltzeko idazkia
+ConfigView.section.file.merge.same.size=Saiatu neurri berdina duten osatugabeko agiriak batzen
+ConfigView.pluginlist.broken=Hautsita
+v3.MainWindow.menu.view.toolbartext=Tresnabarra Izena
+GeneralView.label.filename=Izena\: 
+DownloadManager.error.filetoobig=Torrent agiria handiegia da
+TableColumn.header.maxuploads.info=Gehienez \# hartzaile aldibereko igoeran
+azbuddy.dchat.user.status=Online\: %1, Aurkeztuta\: %2
+webui.mode=Modua
+iconBar.open.tooltip=Ireki Torrenta(k)
+security.crypto.persist_for=Sarhitzaren iraupen epea
+MainWindow.menu.view.myshares=Nire Elkarbanatzeak
+dlg.install.mlab.subtitle=Ezartzen
+rcm.rc_tracker.tt=Klikatu aztarnaria bilatzeko
+TableColumn.header.peersources.info=Hartzaile iturburu baimenduak hartzaileekiko elkarketak ezartzeko
+ipCheckerWizard.progresstitle=IP-a Egiaztatzen
+device.search.auto=Berezgaitasunez bilatu gailuak
+devices.info.copypending=%1 Agiri Itxaroten Kopiatuak Izateko
+splash.openViews=Ikuspegiak Irekitzen
+ConfigView.option.dm.dblclick.show=Erakutsi Agiria
+MainWindow.dialog.exitconfirmation.text=Egitan nahi duzu Vuzetik irtetzea?
+azbuddy.dchat.rchans.pub=Kanal Publikoa
+DHTTransport.report.received_bit=jasota %1  %2  %3
+iconBar.down.tooltip=Mugitu behera
+exportTorrentWizard.finish.title=Osatua
+library.core.wait=Une Bat Mesedez...\nVuze Bezeroa Abiatzen ari da
+label.options.and.info=A&ukerak/Argibideak...
+Progress.reporting.status.finished=Amaiturik
+ConfigView.label.periodiccheck=Egiaztatu aldizka azken bertsioa ezarrita dagoela
+ConfigView.section.file.defaultdir.autorename.tooltip=Honek izenak berdinak direnean torrent batek beste torrent baten agiriak gainidaztea  saihesten du
+TableColumn.header.maxupspeed=Geh. Igoera Abiadura
+plus.notificaiton.ExpiredEntry.s=Zure Vuze Plus harpidetza epea amaitu da\: <A %2>Berritu Orain</A>
+MainWindow.menu.language.refresh=&Berritu
+MessageBoxWindow.rememberdecision=Gogoratu nire erabakia
+plus.notificaiton.ExpiredEntry.p={plus.notificaiton.ExpiredEntry.s}
+configureWizard.nat.title=NAT / Zerbitzari Ataka Azterketa
+ConfigView.section.logging.log0type=Argibide
+label.current_ip=Oraingo IP Helbidea\:
+upnp.refresh_mappings_on_bad_nat=Berezgaitasunez berritu izendapenak  NAT egoera "suhesiturik" denean
+splash.plugin.UIinit=EIG Plugina Abiarazten\: %1  
+DHTView.general.skew=Bihurria\:
+SpeedTestWizard.test.panel.test.countdown=azterketa amaituko da\:
+DHTView.general.users=Erabiltz.\:
+#Used by the webui plugin
+MyTorrentsView.menu.removeand.deletetorrent=Ezabatu &Torrent Agiria
+ConfigView.label.watchtorrentfolder=Inportatu .torrent berriak berezgaitasunez 
+torrent.view.info=Ikusi Torrentaren Argibideak...
+ConfigView.section.tracker.server.group.networks.info=Hautatu aztarnariak hartzaileak onartuko dituen sarebidea
+IrcView.actionnotsupported=Ekintza hau ez dago sostengatuta
+DHTView.operations.findNode=Elkargune Bilaketa
+ConfigView.section.tracker.announcecacheperiod=Iragarle katxea (milaen)
+iconBar.up.tooltip=Mugitu gora
+label.bt.connect=BT Elkarketa
+ConfigView.section.proxy.group.tracker=Aztarnari Harremanak
+MainWindow.menu.vote=Iradoki Ezaugarri bat
+DHTView.operations.ping=Ping (Int. Pak. Eskuzt.)
+ConfigView.label.queue.newseedsmovetop=Mugitu osatutako torrent berrienak emaritzen zerrendaren aurrealdera
+ConfigView.label.disconnetseed=Eten emaritzak emaritzean
+MainWindow.menu.transfers.resumetransfers.keybinding.mac=Meta+Shift+.
+ConfigView.section.connection.group.http=HTTP
+device.retry.copy=Birsaiatu Kopiatzen
+ConfigView.label.enableSystrayToolTip=Erakutsi jeisketa estatistikak azalean
+MainWindow.menu.file.create.fromdir=Zuzenbide &batetik
+ConfigView.section.tracker.maxthreads=Geh. eskabide aldiberean
+ConfigView.section.security.system.managed=Sistema kudeaketa giltza babesa
+MyTorrentsView.menu.sl_remove_from_prof=Kendu Profiletik
+Button.mark=Markatu
+ConfigView.section.connection.advanced.SO_SNDBUF=Hartune SO_SNDBUF neurria [0\: erabili SE berez]
+torrent.fix.corrupt.browse=Ireki Torrenta
+azbuddy.ui.menu.cat.share=Gaitu lagunekiko harpidetza
+memmon.heap.auto.increase.warning=Piloaren oroimena handitu da %1. Vuze berrabiarazitakoan izango du eragina.
+Formats.units.TiB=TiB
+ConfigView.label.seeding.rankType.peerSeed=Hartzaileak\: Emaritza Maila
+platform.win32.baddll.MxAVLsp=VCom Fix-It Erabilgarriak
+DHTView.db.indirect=Zeharka
+PeersView.outgoingreqcount=Irteera Eskabidea
+label.more.dot=Gehiago...
+exportTorrentWizard.exportfile.message=Sartu esportatzeko xml agiria
+DownloadManager.error.unsupportedencoding=Kodeaketa Okerra
+MyTorrentsView.menu.clear_alloc_data=Garbitu Izendapen Egoera
+TorrentOptionsView.multi.title.full=Torrent Aukerak/Argibideak
+ConfigView.section.file.decoder.nodecoder=Bat ere ez
+device.router.is_mapping=Berezgaitasunezko ataka mapaketa
+MyTorrentsView.filter=Bilatu liburutegian...
+configureWizard.transfer2.message=Bittorrent tit-for-tat hartuemanean ohinarrituta dago - orokorrean zure igoera azkarrena, zure jeisketa azkarrena - zein jeisketa azkarra, eta elkarbanatze maila on bat azkar lortzeko, behar duzu igoera abiadura on bat.\n\nHorrela ere, zure elkarketarako azkarregi igotzen baduzu, gainzamatu egin dezakezu errendimendu orokorra motelagoa izanez eta sarearen baliabideengaitik lehiatzen diren beste aplikazioei eraginez.\n\nHortaz garrantzitsua da zama muga o [...]
+ConfigView.section.tracker.client.connecttimeout=Elkarketa itxaronaldia (seg)
+GeneralView.label.maxdownloadspeed.tooltip=geh. jeisketa abiadura [0\: mugagabea]
+azbuddy.ui.menu.enc=Enkriptautu Gakoa
+dial.up=Urrutizkin bidezko Internet elkarketa
+ConfigView.label.piecereorder=Erantsi datuak jeitsitako agiriei eta berrantolatu atalak jeisketa garapen bezala
+MainWindow.dialog.share.sharefile=Hautatu Elkarbanatzeko Agiria
+MainWindow.menu.transfers.pausetransfers=&Pausatu
+device.itunes.status.notinstalled=iTunes ez dago ezarrita
+stats.general.smooth_secs=Lehundutako bataz-besteko leiho neurria [seg]
+DHTView.general.contacts=Harremanak\:
+upnp.ignorebaddevices.reset.action=Berrezarri
+OpenTorrentWindow.mb.existingFiles.text=Agirietako batzuk jadanik badaude adierazitako agiritegian\:\n\n%1\nJarraitzen baduzu, Vuzek datu zuzenak lortzeko agirien gaineko egiaztapena egin dezake eta gainidatzi beharrezkoa bada.
+MainWindow.menu.file.share.dircontentsrecursive=Agiritegiko Edukiak... (&Baliabideak)
+ConfigView.section.security.nopw=Sarhitzik gabe jarrita
+TableColumn.header.min_sr={min.sr.window.title}
+GeneralView.label.downloadspeed=Jeisketa Abiadura\:
+v3.MainWindow.menu.view.sidebar=Alboko Barra
+AlertMessageBox.unread=Irakurri gabeko mezu alertak dituzu - klikatu hemen ikusteko.
+Trackers.column.seeds=Emaritzak
+ConfigView.section.sharing.permitdht=Baimendu zentralizatu gabeko jarraipena aztarnaria eskuraezina denean
+MySeeders.bigView.header=CDLiburutegia
+MainWindow.menu.speed_limits.profile=Sartu Profil Izena
+MainWindow.menu.view=&Ikusi
+beta.wizard.link=Egin klik hemen beta argitalpenen webgunera joateko
+ConfigView.section.style.addurlsilently=Ireki pasatutako URL-ak modu isilean
+ConfigView.section.ipfilter.list.inrange=barrutian zegoen 
+PeersView.host=Hostalari Izena
+TorrentInfoView.columns='{library.name}' Zutabeak ikusi
+ColumnSetup.categories=Kategoriak\:
+MyTrackerView.uploaded=Igota
+network.ipv6.prefer.addresses=Hobetsi IPv6 helbideak biak IPv6 eta IPv4 eskuragarri daudenean
+metasearch.addtemplate.done.title=Eredua Gehituta
+importTorrentWizard.finish.title=Osatuta
+uninstallPluginsWizard.list.loaded=Mesedez hautatu kendu nahi dituzun pluginak
+subscriptions.add.tooltip=Gehitu Harpidetza
+devices.sidebar.onxcodecomplete=Transkodeaketa Osaketan
+label.in=Hemen
+ConfigView.label.autoSeedingIgnoreInfo=Baztertutako torrentak emaritzen lerroko beherenera doaz. Ez dira berezgaitasunez hasiko.\nEzikusi arauak ez dira Lehentasun Nagusia irizpidea duten torrentei ezartzen.\nAlderantzizkoa adierazten ez bada, erabili 0 balio bat araua ezgaitzeko.
+TableColumn.header.\#.info=Lehentasun/Kokapen/Antolaketa Zenbakia
+ConfigView.section.tracker.port=Gaitu aztarnaria HTTP atakan
+search.dialog.text=Sartu torrent berriak bilatzeko idazkia\:
+azbuddy.dchat.ui.max.kb=Geh. hizki txat leiho bakoitzeko [KB]
+UpdateWindow.status.restartMaybeNeeded=Berrabiaraztea beharrezkoa izan daiteke
+ConfigView.group.override=Ezeztatu Aukerak
+fileDownloadWindow.status=Egoera\:
+TableColumn.header.activityType=Mota
+azbuddy.dchat.copy.channel.export=Kanal Babeskopia
+TableColumn.header.activityActions=Eragiketak
+ConfigView.label.xfer.bias_slack=KB/s gutxienez gordeta jeisketa osatuentzat
+MinimizedWindow.name=Izena\:
+Trackers.column.updatein.info=Hurrengo eguneraketa arteko denbora
+aznettorbrowser.install.text=Ezarri Tor Nabigatzailea Plugina .onion eta .i2p web eduki nabigazioa sostengatzeko?
+PeerColumn.activationCount=Elkarketa egiten saiatzen diren hartzaileak\: %1
+ConfigView.section.interface.legacy=Ondasuna
+TableColumn.header.Rating=Mailatzen
+IrcView.title.short=IRC
+ConfigView.section.sharing.usessl=Erabili SSL elkarbanatze  iturburuentzat (beharrezkoa Aztarnari itxurapena)
+ConfigView.label.startwatchedtorrentsstopped.tooltip=Gehitu .torrent berria GELDITUTA egoeran
+FileItem.low={SpeedTestWizard.name.conf.level.low}
+GeneralView.label.swarm_average_completion.tooltip=Erletaldeko hartzaileen osaketa bataz-besteko ehunekoa
+device.odpt.enable=Torrent pribatuak barne
+SWT.alert.erroringuithread=Kudeatu ezinezko akats bat gertatu da EIG-an, akats gehiago egon daiteke.
+metasearch.addtemplate.failed.desc=Hutsegitea eredua ezartzerakoan\: %1
+TableColumn.header.trancode_completion=Bihurketaren Garapena
+ConfigView.section.style.useTree=Erakutsi Agiriak Liburutegia ikuspegietan  (Berrabiaraztea Beharrezkoa)
+message.taking.too.long=Badirudi uste baino denbora gehiago hartzen ari dela\nSakatu 'ESC' eragiketa hau ezeztatzea nahi baduzu
+Button.open=Ireki
+mdi.entry.chatsoverview={chats.view.heading}
+v3.MainWindow.search.last.tooltip=Itzuli bilaketa emaitzetara
+ConfigView.section.tracker.client.enabletcp=Gaitu HTTP/HTTPS aztarnari bezero protokoloa
+exportTorrentWizard.process.inputfilebad.title=Torrent Agiri Baliogabea
+ConfigView.label.closetotray=Itxik Sistemaren Erretilura ikurtzen du
+ConfigView.filter=idatzi iragazteko hitza(k)
+ConfigView.label.zeronewfiles=Esleitu eta hasieratu agiri berriak, haiek sortzen direnean
+tag.sharing.enable.title=Elkarbanatu Herkidegoarekin
+Scrape.status.disabled=Zuritzea Ezgaituta
+ConfigView.section.connection.peersource.Incoming=Sarrera elkarketak
+MainWindow.dialog.share.sharedircontents=Hautatu Elkarbanatzeko Agiritegiko Edukia 
+menu.delete.options.keybinding=EZAB
+label.more=Gehiago
+TagRenameWindow.title=Berrizendatu Etiketa
+MainWindow.menu.view.configuration.keybinding=Meta+,
+devices.od=Lineaz-kanpoko jeistzailea
+ConfigView.section.transfer.autospeed.reset.button=Berrezarri
+DHTView.transport.bytes=Byte
+pairing.explicit.enable=Gaitu
+subscriptions.config.auto=Berez-jeisketa
+DHTView.general.dying=Azkenetan\:
+ConfigView.label.systray=Sistema Erretilua
+Pieces.column.\#=Zenb.
+upnp.releasemappings=Askatu mapaketak itxieran
+sidebar.header.dvd=DVD Grabaketa
+DHTTransport.report.timeout=denboraz-kanpo, erantzunik ez %1
+wizard.hint.mode=Aholkua\: Agiri bat edo zuzenbide bat Arrastatu eta Askatu dezakezu\n\t  laguntzaile honetan agiria edo zuzenbidea hautatzeko
+v3.MainWindow.currentDL=Orain Jeisten
+ConfigView.section.file.decoder.label=Berezko torrent kodeaketa hautaketak horrela eskatzen duenean
+v3.MainWindow.button.stream=Jarioa
+ConfigView.section.tracker.publishenablepeerdetails=Argitaratu hartzaile xehetasunak
+OpenTorrentWindow.fileList.changeDestination.all=Aldatu %1 Agiriren Helmuga Agiritegi Berdinera
+SpeedView.stats.total.since=Guztira (noiztik\: %1)
+ConfigTransferAutoSpeed.set.point=zehazte puntua (sm)
+subscriptions.listwindow.popularity=Ezaguntasuna
+label.more.info.here=Klikatu argibide gehiagorako
+TableColumn.header.completed=Osatuta
+iconBar.start.tooltip=Hasi hautatutako torrenta(k)
+deletedata.title=Ezabatu edukia
+TableColumn.header.maxdownspeed.info=Hartzailean ezarritako jeisketa abiadura muga
+azmsgsync.install.text='Mezu Aldiberetzea' Plugina beharrezkoa da txat deszentralizaturako [ezgaituta jadanik ezarrita badago]
+FilesView.size=Neurria
+GeneralView.label.trackerurl=Aztarnariaren URL-a\:
+ConfigView.section.torrents=Torrentak
+MySharesView.type.dir=Zuzenbidea
+DHTView.activity.type.4=Kanpo Ezarpena
+DHTView.activity.type.3=Barne Ezarpena
+ConfigView.section.tracker.host.addurls=Zihurtatu aztarnari hauen URL-ak hostatutako torrenteetan daudela
+DHTView.activity.type.2=Kanpo Lorpena
+importTorrentWizard.torrentfile.path=Helburua\:
+DHTView.activity.type.1=Barne Lorpena
+exportTorrentWizard.title=Esportatu XML torrenta
+SpeedView.stats.upbias=Igoera bideak\:
+dht.reseed.ip=IP helbidea
+ConfigView.label.openbar.complete=berez ireki emaritzak
+devices.copy.pending=Agiri kopia egiteke
+subs.prop.version=Bertsioa
+dlg.stream.plus.renew.text=Berritu zure Vuze Plus harpidetza zure bideoak irakurtzen jarraitzeko jeitsita bezala.
+label.trackers=Aztarnariak
+webui.homepage=Etxeko orrialdea
+ConfigView.label.prioritizemostcompletedfiles=Gainontzeko agiriei lehentasun Handia eman osatutako % -aren eta agiri neurriaren arabera
+azbuddy.contextmenu=Bi&dali Lagun Bati
+Plugin.trackerpeerauth.name=Aztarnari Hartzaile Baimena
+MainWindow.upgrade.assistant=Berritze Laguntzailea
+updater.progress.window.title=Oraingo Ezarpen Eginkizunak
+devices.sidebar.simple=Ikuspegi Arrunta
+rcm.view.heading=Erlatalde Aurkituak
+ConfigView.section.NATPMP=NAT-PMP
+subscriptions.column.nb-new-results=Emaitza Berriak
+MyTorrentsView.menu.rename.displayed=Berrizendatu Erakutsitako Izena
+ConfigView.section.tracker.client.scrapeenable=Gaitu zuriketa
+ConfigView.label.serverport=Sarrerako TCP / UDP aditze ataka
+Formats.units.GiB=GiB
+GeneralView.label.connected=elkartuta
+importTorrentWizard.process.outputfileexists.title=Agiria Badago
+tps.pex.details=Elkarketaturik %1 hartzailera (egiteke\: hal\=%2, beste\=%3)
+configureWizard.transfer.maxActiveTorrents=Gehienez Eraginda
+configureWizard.file.path=Helburua\:
+OpenTorrentWindow.mb.noDestDir.title=Helmuga Zuzenbidea ez da aurkitu
+remote.pairing.title=Hurruneko Uztarpena
+PeersView.menu.kick=Ostikoa
+MagnetPlugin.report.waiting_ddb=DDB abiarazpena itxaroten...
+MyTrackerView.bytesoutave=Irt. Bat.best.
+ConfigView.label.stop.seedcomp=Emaritza burutu denean
+azbuddy.dchat.rchans.anon=Izengabeko Kanalak
+webui.pairing.info.y=Uztarpena gaituta dago, ikusi Elkarketa ->Uztarpena aukerak xehetasun gehiagorako.
+security.crypto.password.mismatch.title=Sarhitz Akatsa
+wiki.fat32=http\://wiki.vuze.com/w/FAT32_agir_neurri_muga
+ConfigView.label.seeding.rankType.none=Bat ere ez
+webui.pairing.info.n=Uztarpena ezgaiturik dago, ikusi Elkarketa->Uztarpena aukerak ezaugarri honen argibide gehiagorako
+device.xcode.never=Inoiz
+Button.validate=Balioztatu
+quick.view.scheduled.title=Egitaraupen Ikuspen Azkarra
+MainWindow.menu.file.export.keybinding.mac=Meta+Shit+E
+TableColumn.header.completion.info=Jeitsitako ehunekoa adierazten duen grafikoa
+sr_prog.window.message=Sartu elkarbanatze maila garapen grabaketa tartea (adib. 1.0 \= kopia oso guztiak)
+subscript.import.fail.title=Inportatzeak Huts egin du
+Button.add=Gehitu
+StartStopRules.0Peers=0 Hartzaile
+wizard.webseedseditor.edit.title=HTTP Emaritza Editorea
+MainWindow.menu.pairing=Hurruneko Uztarpena
+remote.pairing.instruction2={remote.pairing.instruction} Aukeran, eskaneatu QR kodea zure sakeleko gailura eta jauzi sarbide kodea sartu behar izatea.
+IrcView.noticefrom=Oharra\:
+xmwebui.required='Vuze Hurruneko Webgunea' plugina ezarri behar duzu lan honetarako\n\nIkusi Tresnak->Pluginak->Ezarpen Laguntzailea...
+v3.iconBar.view.small.tooltip=Ikusi Zerrenda Aurreratu bezala
+OpenTorrentWindow.mb.noGlobalDestDir.title=Helmuga Zuzenbidea ez da aurkitu
+SpeedTestWizard.abort.message.scheduled.in=azteketa egitarauturik ... %1 segundutan
+MyTorrentsView.menu.showdetails=Erakutsi &Xehetasunak
+window.updateswt.ignore=Ez ikusi
+devices.xcode.autoCopy=Berezgaitasunez Kopiatu Agiritegira
+PeersView.BlockView.Avail.NoHave=Hartzaileak du; Zuk ez
+pairing.ipv6=IPv6 Helbide publikoa
+Search.menu.engines=Ereduak
+pairing.ipv4=IPv4 Helbide publikoa
+ConfigView.section.security.backupkeys=Babeskopia giltza agiri bati
+azbuddy.ui.new_buddy=Lagun berriaren giltza\:
+#
+# 2.0.4.4
+#
+ConfigView.section.style.guiUpdate=EIG eguneratze epea
+MainWindow.menu.file.export.keybinding=Meta+E
+DHTOpsView.notAvailable=BDB Grafika ez dago eskuragarri
+PiecesView.DistributionView.theyHave=Hartzaileak dituen atalak
+DHTView.title.full_v6=Banaturiko Datubasea IPv6
+subscriptions.listwindow.popularity.reading=Irakurtzen...
+configureWizard.transfer.connection.7=adsl/xxx kablea/1024 kbs-koa
+ConfigView.label.start.onlogin=Hasi Vuze izena emanda
+configureWizard.transfer.connection.6=adsl/xxx kablea/768 kbs-koa
+configureWizard.transfer.connection.5=adsl/xxx kablea/512 kbs-koa
+UpdateWindow.cancel=Ezeztatu
+configureWizard.transfer.connection.4=adsl/xxx kablea/384 kbs-koa
+progress.window.title=Eragiketa Garatzen
+configureWizard.transfer.connection.3=adsl/xxx kablea/256 kbs-koa
+TableColumn.header.resolution=Bereizmena
+configureWizard.transfer.connection.2=adsl/xxx kablea/128 kbs-koa
+configureWizard.transfer.connection.1=modema
+ConfigView.section.security.unlockkey.error=Huts egin du giltza irekitzean - sarhitz okerra
+configureWizard.transfer.connection.0=Norbererara
+ConfigView.option.dm.dblclick.show._mac=Erakutsi Agiria(k) Finder-en
+ConfigView.eta.abbreviated=U\:
+ConfigView.section.DNS={label.DNS}
+tag.type.ds.stop={ManagerItem.stopped}
+device.odauto.enable=Berezgaitasunez kudeatu jeisketak
+ConfigView.label.allowSendVersion=Ahalbidetu Vuzeri bertsio zenbakia eta zorizko id izengabeak bidaltzen bertsio berriaren bila ari denean 
+OpenTorrentFile.column.priority={FilesView.priority}
+tag.property.constraint=Murrizketak
+iconBar.bottom.tooltip=Mugitu beheren
+MainWindow.menu.view.beta=Beta Programa
+dlg.stream.plus.renew.title=Vuze Plus Berritzea
+MainWindow.menu.file.folder=&Agiritegia...
+wizard.choosedirectory=Hautatu zuzenbidea
+TableColumn.header.Country.info=Hartzailea kokaturik dagoen herrialdea
+wizard.multitracker.new=Berria...
+devices.restrict_access.msg=IP zerrenda kakotxaz banandurik baimentzeko [edo ukatzeko aurrezenbakia bada -]
+MyTorrentsView.clearFilter.tooltip=Garbitu Iragazkia
+ConfigView.label.switchpriority.tooltip=Lehentasun txikiak torrentari izendaturiko igoera bandazabalera zenbatekoa murrizten du
+dialog.associations.prompt=Vuze ez da BitTorrent agirientzako berezko aplikazioa.\nNahi duzu .torrent agiriak Vuzerekin elkartzea
+Button.retarget=Birxedetu
+restart.error.oom=Oroimenetik kanpo
+columnChooser.columndescription=Azalpena
+RCM.column.rc_title=Izena
+TableColumn.header.tag.copyoncomp={label.copy.on.comp}
+v3.topbar.menu.show.logo=Logoa
+PeersView.BlockView.NoAvail.NoHave=Inork ez du
+ConfigView.section.tracker.sendjavaversionandos=Bidali Java bertsioa eta Sistema Eragile izena
+configureWizard.title=Itxurapen Laguntzailea
+ConfigView.section.connection.advanced.write_select_min=Idatzi hautatutako gutxienezko itxaronaldia (milaen, berezkoa %1)
+ConfigView.text.neverStart=Ez Hasi Inoiz
+TableColumn.header.remaining=Egiteke
+TableColumn.header.swarm_average_completion=Hartzaileen Bataz-besteko Osatua
+config.external.browser.prog=Nabigatzaile exekutagarria
+swt.uninstall.window.ok=Kendu
+pairing.host=Hostalari izena (DNS izena)
+MyTorrentsView.menu.explore._windows=Erakutsi Ex&plorerrean
+GeneralView.label.completed=Osatuta\: 
+MyTorrentsView.menu.ipf_enable=Gaitu IP Iragazkia
+sidebar.sash.tooltip=F7 albobarra ezkutatu/erakutsi azkarrerako
+azbuddy.ui.table.last_msg=Azken Mezua
+OpenTorrentWindow.changeDestination=Aldatu Helmuga
+GeneralView.label.maxdownloadspeed=Jeisketa Muga
+popup.error.hideall=Ezkutatu Denak
+br.backup.last.time=Azken babeskopia eginda\:
+pairing.op.fail=Uztarpen Eragiketa Hutsegitea
+dialog.add.peers.msg=Sartu hartzaile bakoitzaren helbidea honela <hostalaria>\:<ataka> - kakotxaz bananduz sarrera anitz badira
+DHTView.db.local=Tokikoa
+MainWindow.about.section.system=Sistema
+SystemTray.menu.exit=I&rten
+PeersView.state=Egoera
+MyTorrentsView.menu.exporthttpseeds=Esportatu HTTP emaritza URL-ak gakora
+ConfigView.section.mode.advanced=Aurreratua
+smooth.config=(ikusi itxurapena leiho iraupena ezartzeko)
+health.explain.blue=Emaritzean, esanahi du ez zaudela inolako hartzailera elkarketaturik.\nJeistean, esanahi du zenbait hartzaileetara elkarketaturik zaudela, baina aztarnaria bertan behera dagoela
+ConfigView.section.tracker.maxposttimemultiplier=LORTU denbora biderkatzailea POST jardunerako [0\: mugagabea]
+webui.access=Sarbidea
+wizard.singlefile.help=Sortu torrenta agiri bakarretik
+devices.xcode.tagshare=Elkarbanatu Etiketadun Transkodeaketak
+TableColumn.header.bad_avail_time.info=Jeisketaren kopia oso bat eskuragarria izan zen azken aldia
+SharedPortServer.alert.selectorfailed=Huts egin du sarrerako datuen aditze ezartzeak.\nEgiaztatu suhesi ezarpenak java(w).exe baimentzen duen 'zerbitzari' bezala ekiteko
+ConfigView.section.style.addurlsilently.tooltip=Berezgaitasunez jeitsi pasatutako/askatutako .torrenten URL-ak elkarrizketa kutxa ireki gabe.
+v3.menu.device.defaultprofile=Berezko Profila
+library.category.header=Kategoria '%1'
+ipCheckerWizard.checkFailed=Huts egin du, zergaitia\:
+wizard.maketorrents.autoopen=Ireki torrenta emaritzarako egindakoan
+PiecesView.BlockView.NoHave=Ez Duzu
+TrayWindow.menu.exit=I&rten
+TorrentOptionsView.param.max.peers=Geh. elkarketa zenbatekoa [0\: mugagabea]
+MainWindow.nat.status.tooltip.ok=Eskuragarritasuna Ongi (TCP)
+ConfigView.section.logging.udptransport=Gaitu UDP garraio aztarna aditzea 
+label.no.suggestions=Ez dago Iradokizunik
+exportTorrentWizard.process.unknownfail.title=Ustekabeko Akatsa
+device.model.name=Eredu izena
+SpeedTestWizard.set.upload.button.apply=Ezarri
+v3.iconBar.view.big.tooltip=Ikusi Zerrenda Arrunt bezala
+label.anon.i2p=Izengabekoa (I2P)
+ConfigView.label.maxnumwant=Mugatu itzul daitezkeen aztarnari hartzaile zenbatekoa 
+TableColumn.header.crc32=CRC-32
+OpenTorrentWindow.startMode.seeding=Emaritzen
+label.outbound=Kanporakoa
+ConfigView.auto=Berez
+PeerSocket.bad_peer_id=hartzaile txar ID-a
+TorrentInfoView.torrent.encoding=Torrent kodeaketa
+ConfigView.label.lh.ext=Hedapenak
+ConfigView.section.transfer.autospeed.enabledownadj=Gaitu jeisketa abiadura neurriratzea
+subs.prop.last_result=Aurkituriko azken emaitz berriak
+AlertMessageBox.comment=Aipamena
+webui.tor_dest=Tor helbidea
+azbuddy.dchat.anon.nick=Izengabeko goitizena elkarbanatuta
+ConfigView.section.file.decoder.prompt.tooltip=Erakutsi betik elkarrizketa kodeaketa aukera eskuragarri dagoenean
+DHTTransport.report.sending=datuak bidaltzen
+GeneralView.label.trackerurlopen.tooltip=Egin klik aztarnariaren orri nagusia irekitzeko
+MyTorrentsView.menu.health=Osasunari buruz
+dialog.pause.for.period.title=Sartu Denbora Epea
+SpeedTestWizard.test.panel.currinfo=BitTorrent bandazabalera aztertzen.
+ConfigView.section.connection.encryption.min_encryption_level.tooltip=Laua- eskuematea bakarrik\nRC4 - jario osoa\nEnkriptaketa handiagoak CPU gehiago behar du .
+label.protocol={Peers.column.Protocol}
+ConfigView.label.watchtorrentfolderinterval.tooltip=Agiritegia berriro mihatu arteko pausaldia
+MainWindow.menu.file.closewindow=Itxi &Leihoa
+FilesView.menu.open=&Ireki
+device.mediaserver.remove_all.desc=Zihur zaude multimedia Zerbitzari denak kentzea nahi dituzula?
+Subscription.menu.resetauth=Berrezarri Egiaztapen Xehetasunak
+installPluginsWizard.list.nullversion=Bertsiorik ez
+v3.MainWindow.menu.contentnetworks.manage=&Kudeatu HD Sareak
+OpenTorrentOptions.title=Ireki Torrenta Aukerak
+CacheView.speeds.fromCache=Katxetik/Katxera
+DHTView.operations.sent=Bidalia
+SpeedView.stats.measured=Neurtuta
+label.mute=Mututu
+configureWizard.transfer2.test=Abiatu Azterketa
+ColumnRenameWindow.title=Berrizendatu Zutabea
+device.playnow.group=Irakurri Orain
+Trackers.column.updatein=Hurrena
+ipCheckerWizard.checkComplete=IP osatua\:
+PiecesView.DistributionView.SeedAvl=Emaritza Eskur.Ekarpena
+change.url.msg.title=Aldatu '%1'-rako URL-a
+ConfigView.label.openmytorrents=Ireki Liburutegia hasitakoan
+UpdateWindow.columns.size=Neurria
+network.ipbinding.icon.show=Erakutsi egoera ikurra egoerabarran loturak eraginda daudenean
+MainWindow.dht.status.users=%1 erabiltzaile
+TableColumn.header.alerts={ConfigView.section.interface.alerts}
+FilesView.rename.choose.path=Hautatu dagoen agiria edo berri bat
+ConfigView.section.irc=IRC
+device.import.title=Gailua Inportatu?
+azmsgsync.install.ok.msg=Mezu Aldiberetze Plugina ongi ezarri da
+tag.type.man=Eskuzkoa
+Formats.units.Mbit=Mbit
+MainWindow.sr.status.tooltip.bad=Elkarbanatze Maila %1 gaizki\: < 0.5
+subscription.request.add.message=%1 RSS jario bat da\n\nGehitu harpidetza berri bat?
+ConfigView.section.style.dropdiraction.opentorrents=Ireki Torrentak
+ConfigView.section.file.readmblimit.explain=Neurri honek prozesatzeke dauden irakurketak biltegiratzeko zenbat oroimen erabiliko den mugatzen du 
+xcode.deletedata.message.2=\n(hemen kopia bat egon daiteke oraindik '%1')
+MainWindow.status.checking=egiaztatzen
+IrcView.help=Baliozko aginduak hauek dira\:\n . /help\: mezu hau erakusten du\n . /nickname | /name\: zure izena aldatzen du \n . /me action\: ekintza bat bidaltzen du \n . /msg nick message\: mezu pribatua bidaltzen dio <nick>-(e)ri\n . /r message\: azken mezu pribatuari erantzuten dio\n . /join \#channelB (ez egin klik hemen, adibide bat da)\: uneko kanaletik BKanalera aldatzen du
+TableColumn.header.tag.downlimit={TableColumn.header.maxdownspeed}
+ClientStats.column.percent=%
+DHTView.general.leaves=Orriak\:
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
+MainWindow.menu.plugins.installPlugins=E&zarpen Laguntzailea...
+subscript.add.title=Ezarri Harpidetza?
+ColumnSetup.availcolumns=Eskuragarri  %1 zutabe
+ConfigView.label.seeding.numPeersAsFullCopy=Saiatu kopia oso Bat izaten denentzat\n(0 \: Ez Saiatu)
+ConfigView.section.connection.prefer.udp=Hobetsi UDP elkarketa
+ConfigView.section.ipfilter.clear.on.reload=Garbitu iragazkiak birgertatzerakoan. Birgertatze aurrerabidean zehar IP-ak ez dira itxiko. Hautatugabe badago, itxigabeko berriek ez dute eraginik izango berrabiarazi arte.
+columnChooser.columnname=Zutabe Izena
+RCM.column.rc_hash=Hasha
+OpenTorrentWindow.mb.openError.title=Irekitze Akatsa
+subs.prop.assoc=Elkartasunak
+OpenTorrentWindow.addFiles=&Gehitu Agiriak
+dlg.auth.trial.success.info=Arrastatu bideo agiriak zure liburtegitik "Sortu DVD Berria"-ra. Jadanik bideo bat gehituta bazenuen osagaiak ezarri aurretik, mesedez gehitu ezazu berriro.
+device.mediaserver.view.title=Multimedia Zerbitzariak
+label.no.messages=Ez dago Mezurik
+ConfigView.label.maxuploads=Geh igoera ahoak torrent bakoitzeko berez
+statusbar.feedback.tooltip=Klikatu hemen iruzkinak bidaltzeko
+GeneralView.label.remaining=Gelditzen da\: 
+GeneralView.section.info=Argibideak
+swt.updater.urlsgetter.platform=Plataformarako SWT-a\:
+popup.error.details=Xehetasunak
+Peers.column.lan=LAN (Tokiko Sarbide Sarea)
+OpenTorrentWindow.mb.openError.text='%1' ezin izan du ireki\:
+#
+# > 2.0.8.0
+#
+OpenTorrentWindow.title=Ireki Torrenta(k)
+MainWindow.upgrade.hint2=Aholkua\:\\Gero Vuze itxi nahi baduzu, sakatu Ezeztatu eta\n\titxi ondoren Azureus2-new.jar berrizendatu Azureus2.jar bezala
+webui.pairing.autoauth=Gaitu berezko sarhitz babesa\: erabiltzaile izena\=vuze, sarhitza\=<uztarpen sarbide kodea>
+MainWindow.upgrade.hint1=Aholkua\:\t Amaitu botoia sakatuz dena berezgaitasunez egingo da
+TableColumn.header.peers=Hartzaileak
+PiecesView.completed=Osatuta
+Button.search=Bilatu
+splash.plugin.init=Plugina Abiarazten\:
+platform.win32.baddll.sarah=ONDATUTA\! Aplikazio Geruza Suhesia
+device.model.num=Eredu zenbakia
+MainWindow.menu.speed_limits.load=Ezarri...
+Peers.column.UpRatio.info=Hartzailearen "Zuretik Igota \: Besteetatik Igota" Maila
+ConfigView.label.mindownloads=Gutx. aldibereko jeisketa
+ConfigView.section.style.customDateFormat=Norbere Egun Heuskarria
+mdi.entry.plus.free=Vuze Plus
+Browser.popup.error.no.access=Akats bat gertatu da hurruneko baliabide bat atzitzerakoan.\nMesedez saiatu zaitez geroago
+ConfigView.label.lh.info=Agiria berez agiriaren motaren arabera erregistraturiko aplikazioarekin abiarazten du.\nEzeztatu jokabide hau aplikazio zehatzak adieraziz emaniko agiri hedapenentzat [kakotxaz banadutako zerrenda].
+ConfigView.label.openbar.incomplete=Jeisketa barrak\: berez ireki jeisketak
+ConfigView.label.max_peers_total=Geh.elkarketa orokorrean [0\: mugagabea]
+plugin.installer.recommended.plugin=Plugina gomendatuta - mesedez berrikusi eta ezarri beharrezkoa bada
+dlg.try.trial.title=Probatu DVD Grabaketa
+metasearch.export.select.template.file=Gorde Eredua
+MyTorrentsView.menu.changeDirectory=Aldatu Datu Zuzenbidea
+ConfigView.section.style.defaultSortOrder.desc=Beherantz
+ConfigView.section.tracker.enableudp=Gaitu UDP aztarnari hartuemana
+FancyMenu.Header.Other=Besteak
+ConfigView.section.plugins.magnetplugin=Magnet URI Agintea
+wizard.maketorrents.autohost=Hostatu torrenta aztarnariaren barne
+Trackers.column.seeds.info=Emaritzak erletaldean
+ConfigView.section.style.reOrderDelay.never=Inoiz Ez
+iconBar.editcolumns.tooltip=Zutabe Ezarpena
+Formats.units.MiB=MiB
+v3.MainWindow.text.my.account=Kontu Argibideak
+ConfigTransferAutoSpeed.upload.capacity.usage=Igoera Gaitasun Erabilia
+sidebar.dropdown.tooltip=Erakutsi albokobarra menu heuskarrian
+MainWindow.menu.transfers.pausetransfers.keybinding.mac=Meta+.
+PeersView.timetosend=Atala birbidaltzeko denbora (Gain-Emaritze Modua)
+ConfigView.text.neverIgnore=Ez Baztertu Inoiz
+IrcClient.connected=Elkartuta hona\:
+TableColumn.header.maxupspeed.info=Geh Igoera Abiadura torrent bakoitzeko
+MyTrackerView.passive=Pasiboa
+SpeedTestWizard.finish.panel.max.download=Geh. jeisketa\:
+wizard.multitracker=Gehitu Aztarnari-Anitzaren argibideak torrentari
+importTorrentWizard.importfile.path=Helburua\:
+PeersView.gain=Irabazia
+MyTorrentsView.menu.filter=Iragazi Zerrenda...
+GeneralView.label.savein=Gordeta Hemen\:
+TableColumn.header.activityText=Mezua
+device.tivo.enable=Gaitu TiVo sostengua
+DownloadManager.error.datamissing=Datuak Ez daude
+pairing.config.icon.show=Erakutsi Hurruneko Vuzeren hurruneko ikurra egoera barran
+v3.MainWindow.text.log.out=Irten
+CacheView.general.size=Neurria Guztira
+TableColumn.header.duration=Iraupena
+ConfigView.label.sleep.info=Saihestu ordenagailua lotaratzea/etetea....
+ump.install=Eguneratze Azkarra Egiten\:\nBideo honentzat beharrezkoa den irakur gehigarri txiki bat ezartzen.
+Button.rename=Berrizendatu
+ActivityView.legend.limit=Neurri muga
+ConfigView.section.file.decoder.showlax=Erakutsi aukera gutxieneko kodeaketak
+ConfigView.title.full=Aukerak
+device.offlinedownloader.view.title=Lineaz-kanpoko Jeistzaileak
+TableColumn.header.DateCompleted.info=Torrentaren jeisketa burutu zen eguna
+ConfigView.section.style.ShowTabsInTorrentView=Erakutsi azpi-hegatsak Liburutegi ikuspegietan ({ConfigView.section.security.restart.title})
+ConfigView.section.general=Orokorra
+ConfigView.pluginlist.scan=Mihatu Plugin berrien bila
+mdi.entry.dvdburn.new=Sortu DVD Berria
+ConfigView.label.popup.timestamp=Gehitu ordu-irarketa alerta oharrei
+ConfigView.label.openbar=Berez irekitze jeisketa barra
+OpenTorrentWindow.startMode.forceStarted=Behartu Hastea
+azbuddy.dchat.fave.chats=Txat Gogokoenak
+PeersView.Messaging=Mezularitza
+ConfigView.pluginlist.column.loadAtStartup=Gertatu Abiatzerakoan
+ConfigView.label.downloading.testTime=Jeisketa abiadura azterketa aldia [seg]
+wizard.tracker.local=Erabili Vuze Barneko Aztarnaria
+splash.firstMessageNoI18N=(\: Vuze \:)
+# used for more than just "delete data"
+deletedata.noprompt=Ez galdetu berriro
+TableColumn.header.sr_prog.info=Jeisketaren elkarbanatze mailak balio bat erdiesten duen eguna erakusten du
+MyTorrentsView.dialog.setPosition.title=Ezarri Kokapena
+Stats.title.full=Estatistikak
+Button.unmarkSelected=Desmarkatu Hautatua
+ConfigView.label.show.cat.but=Erakutsi Kategoria Botoiak
+ConfigView.label.checkOncompletion=Egiaztatu berriro atalak jeisketa egin ondoren
+Peers.column.as.info=Hartzailearen AS (Sistema Autonomoa) xehetasunak
+ColumnSetup.chosencolumns=Zutabe Hautatuak
+SpeedTestWizard.set.upload.title=Ezarri Igoera eta Jeisketa Mugak
+PiecesView.priority.info=Atal honen osaketa lehentasuna, baina ez jarri harreta askorik horretan
+GeneralView.label.trackerurlupdate=Eguneratu &Aztarnaria
+DHTTransport.report.rerequest_bit=bir-eskabidetzen %1  %2  %3 
+ConfigView.section.connection.encryption.require_encrypted_transport=Garraio enkriptatua beharrezkoa
+Progress.reporting.no.history.to.display=Ez dago xehetasun mezurik erakusteko.
+OpenTorrentOptions.show.label=Torrent bat irekitzerakoan, erakutsi elkarrizketa hau\:
+ConfigView.section.plugins.irc=IRC
+dlg.auth.denied.link=<A HREF\="info">Kode Eragintza Ukapenaren Argibideak</A>
+Generic.words.scan=Mihatu
+security.certcreate.createfail=Egiaztaturiko sortzeak huts egin du
+azbuddy.tracker.bbb.status.idle=Kitzikapen Gabe
+ConfigView.section.style.use_show_parent_folder=Erabili "%1" ordez "%2" torrent menuetan
+tag.azbuddy.dchat.shares=Txat Elkarbanatzeak
+SpeedTestWizard.finish.panel.disabled=ezgaiturik
+RCM.column.rc_tracker=Aztarnaria
+TableColumn.header.tag.count=Z Gai
+configureWizard.file.fastResume=Gaitu Berrekite azkarra
+RCM.column.rc_peers=Hartzaileak
+ConfigView.section.security.op.error=Huts egin du eragiketa osatzean\:\n    %1
+TableColumn.header.savepath.info=Torrenteen datuentzako helbide agiritegia edo agiria
+remote.pairing.instruction=Besterik gabe sartu beheko kodea edozein hurruneko gailuk emandako tartean. 
+swt.updater.urlsgetter.downloading=Ispilu zerrenda bat lortu hemendik
+devices.auto.start=Berez-abiatzea
+FilesView.menu.setpriority.normal=&Arrunta
+configureWizard.transfer2.mselect.info=xxx/<value> sarrerek nabaritzen dute igoera elkarketa abiadura <value> bit segunduko.\nAdibidez, zuk ADSL elkarketa bat baduzu 768 Kbps-ko jeistejario abiadurarekin eta 384 Kbps-ko igoerajarioarekin, hautatu 'xxx/384 kbit/seg'.\nBorobildu txikira hurbileneko baliora abiadura zehatza erakusten ez bada.
+ConfigView.section.plugins.xml_http_if=XML/HTTP Interfazea
+iconBar.stream=Irakurri Orain
+# This is the beginning of the word "View".  It's right aligned under the icon bar item
+v3.iconBar.view.big=Iku
+MyTorrentsView.menu.stop=&Gelditu
+sidebar.LibraryUnopened=Berria
+MainWindow.menu.help.about=Vuzeri buruz
+MyTorrentsView.menu.explore=Erakutsi Agiria
+MainWindow.nat.status.tooltip.bad=Suhesi/NAT (TCP) eskuragarritasun arazoa. Joan Wikira laguntza lortzeko
+label.none.assigned=Esleitu gabe
+TableColumn.header.category.info=Torrentari dagokion kategoria izena
+DownloadManager.error.operationcancancelled=Eragiketa ezeztatuta
+ConfigView.label.seeding.firstPriority.shareRatio=Elkarbanatze maila honen azpitik
+label.dismiss.all=Baztertu Denak
+IPChecker.external.loadingwebpage=Web orrialdea gertatzen
+device.mediaserver.remove_all=Kendu Multimedia Zerbitzari denak
+TableColumn.header.tag.group=Multzoa
+v3.MainWindow.button.resume=Berrekin
+azsubs.contextmenu.lookupassoc=Bilatu harpidetza elkarketak
+subscriptions.config.autostart.min=Hasi bakarrik bada >\= MB [0\: mugagabea]
+TorrentOptionsView.param.max.seeds=Geh. emaritza elkarketak [0\: elkarketa muga]
+platform.win32.baddll.iFW_Xfilter=iolo Suhesi Pertsonala
+TableColumn.header.\#=Zbk.
+dhttracker.tracknormalwhenoffline=Torrent arruntak beren aztarnaria eskuragarria ez dagoenean bakarrik bideratu
+Peers.column.peer_byte_id=Hartzaile ID-a
+MainWindow.menu.file.open.url=&Kokalekua...
+MainWindow.menu.file.open.uri=URL-a, Magneta edo Hasha...
+torrent.comment.rat2=Aipamena(k)\: %1
+torrent.comment.rat1=Bataz-besteko Maila\: %1 (puntuak\: %2)
+MainWindow.upgrade.explanation.manual=Eskuz eguneratu dezakezu Vuze itxiz, bertsio berria jeitsiz eta Vuze berrabiaraziz
+MainWindow.about.internet.forumdiscussion=Eztabaidaguneak
+pairing.ui.icon.tip=Vuze Hurruneko Elkarketa Egoera
+ConfigView.label.seeding.ignore=Baztertu Arauak
+subscript.none.subscribed=Egin klik torrent honentzat eskuragarri dauden harpidetzak ikusteko
+ConfigView.section.mode.advanced.text1=Sarbide osoa ezarpen eta ezaugarri guztietara.
+TableColumn.header.smoothup=Igoera Lehundua
+FilesView.dialog.priority.text=0\=Arrunta, 1\=Handia, 2\=Oso Handia...
+SystemTray.menu.closealldownloadbars=Itxi &Jeisketa Barra Guztiak
+alert.raised.at.close=(Mezua aurretik itxitako Vuzetik)
+SpeedTestWizard.finish.panel.max.seeding.upload=Geh. igoera emaritzen\:
+ConfigView.section.ipfilter.persistblocking=Gorde itxitako IP xehetasunak berrabiarazpenetan
+PiecesView.type=Mota
+ConfigView.section.plugins.TrackerWeb=Aztarnari Webgunea
+ConfigView.boolean.irclog=Gaitu kanal jardueraren datuen erregistratzea (IRC_log.htm)
+SpeedTestWizard.abort.message.interrupted=TorrentAbiaduraAzterketaLeihoMezua eten egin da azterketa amaitu aurretik
+TableColumn.header.CountryFlag.info=Hartzailearen Herrialde Ikurrina
+ConfigView.section.style.reOrderDelay=Berrantolatu taulak EIG-aren Z eguneratzetik behin [0\: inoiz ez]
+MySharesView.type.dircontentsrecursive=Zuzenbide edukiak (baliabidea)
+GeneralView.label.status=Egoera\:
+GeneralView.label.uploaded=Igota\:
+ConfigView.section.style.alwaysShowTorrentFiles=Erakutsi betik torrent agiriak Xehetasunak/Agiriak atalean
+ConfigView.section.update.autodownload=Berez jeitsi eguneraketak eta galdetu ezarpena gertu dagoenean 
+trackername.prefs.message=Puntu eta kakotxaz banandutako aztarnari hostalari izenak\nAdibidez\: a.b.com; c.d.net
+OpenTorrentWindow.diskUsage=%1 %2-tik
+ConfigView.label.removeOnStop=Kendu torrenta zerrendatik berezgaitasunez gelditu ondoren
+MainWindow.menu.view.myshares.keybinding=Meta+3
+MyTorrentsView.menu.changeTracker=Gehitu aztarnari URL-a(k)
+ConfigView.section.file.nativedelete._windows=Mugitu ezabatutako agiriak Birziklapen Gunera
+device.rss.localonly=Sarbide ukatua ordenagailu honetara bakarrik
+ConfigView.section.connection.port.rand.enable=Zorizkotu aditze atakak hasterakoan
+MagnetPlugin.report.downloading=Hemendik jeisten %1
+MyTorrentsView.dialog.setNumber.upload=igo
+configureWizard.transfer.maxUploadsPerTorrent=Gehienezko Igoera Torrnet bakoitzeko
+FilesView.fullpath=Erakusi Helburu Osoa
+MainWindow.menu.view.mytracker.keybinding=Meta+2
+Formats.units.Tbit=Tbit
+MagnetPlugin.use.md.download.name=%1-rentzako metadatu jeisketa
+ConfigView.section.transfer.setmark=Ezarri/garbitu marka\: eskualdaketa estatistika orokorrak une honetatik aurrera erakutsiko dira (Vuze ezarpen denbora garbituta badago) aurrerantzean
+externalLogin.auth_method_proxy=Erabili cookie atzipenbide hedatua. Hutsegiten badu, ezgaitu aukera eta saiatu berriro.
+IrcView.errormsg=Hitzjoskera Okerra /msg \: /msg erabiltzaile idazkia
+ConfigView.label.autoopen.detailstab=Berez ireki Xehetasun Hegatsa
+ConfigView.label.dl.add.req.attention=Argitu jeisketa eremua jeisketa bat gehitzen denean
+ConfigView.section.plugins.update=Plugin Eguneratzea
+apply.to.current=Ezarri Oraingoari
+OpenTorrentWindow.mb.invaliddefsave.text='%1' gordetze kokalekua baliogabea da.\n\nElkarrizketa hau isten duzunean aldatzeko galdetuko zaizu.\n\nBerezko gordetze kokalekua Tresnak->Aukerak->Agiriak bidez itxuratu daiteke.
+dht.logging=Gaitu jarduera gardentasuna
+label.vuze.services=Vuze Zerbitzuak
+rcm.contextmenu.lookupassoc=Izenburua
+tag.property.trackers={label.trackers}
+MyTorrentsView.menu.setDownSpeed=Ezarri &Jeisketa Abiadura
+ConfigView.section.style.dropdiraction.sharefolder=Elkarbanatze Zuzenbidea
+subs.prop.num_unread=Irakurrigabeko emaitz zenbatekoa
+ConfigView.section.tracker.separatepeerids.info=Izengabeko jarduera handituz jeisketa/emaritza izengabean\nez-izengabeko aztarnari elkarketa erabiltzen den bitartean
+devices.xcode.prof_def=Berezko transkodeaketa profila
+ConfigView.label.piecereorderminmb=Berrantolatu bakarrik handiagoak diren agiriak (MB-tan)
+mdi.entry.tagsoverview={tags.view.heading}
+iconBar.start=Hasi
+Wizard.Subscription.search.subtitle2.sub2=Webguneetako torrentak
+azbuddy.chat.title=Vuze Eztabaidagunea
+iconBar.comment=Aipamena
+Wizard.Subscription.search.subtitle2.sub1=HD Filmak, TB Ikuskizunak, Filmak, Vuze Sareko Trailerrak
+MainWindow.menu.tools.netstat={Views.plugins.aznetstatus.title}...
+GeneralView.label.updatein=Eguneraketa\:
+TableColumn.header.DateFileCompleted=Agiria Osatuta
+TorrentOptionsView.param.max.uploads=Geh. igoera aho zenbatekoa [gutxienez\: 2]
+TableColumn.header.device=Gailua
+ConfigView.section.style.doNotUseGB.tooltip=Hautaturik badago, Vuzek jarraitu dezake erabiltzen MB baita 1024 MB baino handiagoak diren neurriekin
+proxy.socks.ui.icon.tip=SOCKS egoera\: %1\nKlik-bikoitza estatistikak.\nEskuin-klika aukerak
+TableColumn.header.writerate=Idazketa Neurria
+dlg.auth.trial.success.line1=Vuze gertu dago DVD-ak sortzeko.
+TableColumn.header.chat.msg.out=Mezu Itxarotea
+splash.initializeUIElements=EI Osagaiak Abiarazten
+azbuddy.addtorrent.title=Jeisketa Onartu?
+jvm.reset=Berrezarri JVM aukerak ezarpenaren berezkoetan
+MyShares.column.category=Kategoria
+label.fave=Gogokoena
+DHTView.transport.out=Irteera\:
+subs.prop.is_auto=Berez-jeistsi emaitza berriak
+PeersView.menu.snubbed=&Errefusatuta
+ConfigView.section.style.defaultSortOrder=Berezko Antolakuntza
+ConfigView.section.proxy.enable_socks.peer=Gaitu proxya hartzaileekiko harremanetarako (kanporako elkarketak bakarrik) [berrabiaraztea beharrezkoa]
+ConfigView.label.xfs.allocation=Esleitu agiri berriak XFS agiri-sistema bereizia den bide bat erabiliz
+Progress.reporting.no.reports.to.display=Une honetan ez dago garapen oharrik erakusteko
+TableColumn.header.download.info=Hartzailearengandik jasotzen ari zaren datuen zenbatekoa
+label.browser=Nabaigatzailea
+cat.rss.gen=Sortu tokiko RSS harpidetza
+config.internal.browser=Barneko Nabigatzailea
+SpeedView.stats.currentPing=Oraingo Ping-a\:
+DownloadManager.error.badsize=Neurri Okerra
+TableColumn.header.date_added=Gehitze Eguna
+TableColumn.menu.maxuploads=Geh. Igoera Zenbaketakoa
+TableColumn.header.class=Saila
+ConfigView.section.logging=Oharketa
+ConfigView.section.connection.advanced.socket.group=Hartune Aukerak
+speedtest.wizard.title=Abiadura Azterketa
+ConfigView.section.proxy=Proxy Aukerak
+TableColumn.header.tag.uprate={TableColumn.header.upspeed}
+ActivityView.legend.peeraverage=Bataz-bestekoa
+MainWindow.menu.community.wiki=Herkidegoa, Wikia eta SEG
+subscriptions.rss.enable=Sortu RSS Jarioak harpidetzetatik
+MyTrackerView.badnat.info=NAT egiaztapen bat huts eginda duten Emaritza/Hartzaileak, gaituta badago
+ConfigView.section.ipfilter.list.notinrange=ez zegoen inolako barrutitan
+ConfigView.label.bindip.details=Adibidea\: 192.168.1.5;eth0;eth1[2]  behartu dezake IP bereizi bat, 1. interfazearen IP guztietara eta 2. interfazearen 3. IP-ra .\n1. IP-a zerbitzu guztietarako erabilitzen da, beste guztiak zama orekatzeko erabiltzen dira\nHurrengo interfazeak daude baliagarri\:\n%1
+TableColumn.header.seeds=Emaritzak
+button.columnsetup.tooltip=Zutabe Ezarpena
+security.crypto.persist_for.session=Saio hau
+wizard.webseed.configuration=HTTP Emaritza Itxurapena
+azbuddy.dchat.decentralized=Txat Deszentralizatua
+OpenTorrentWindow.mb.notTorrent.text=Ezin da '%1' ireki. Ez dirudi .torrent agiri bat denik.\n\nJasotako datu batzuk\:\n%2
+GeneralView.label.comment=Torrentaren Aipamena\:
+ConfigView.label.save_list.clear=Kendu historia
+remote.pairing.test.unavailable=Ene, ezin izan da zure hurruneko elkarketa zehaztu. <A HREF\="retry"> Saiatu berriro</A>
+label.wrap.text=Idatzia Erdiratu
+TableColumn.header.seeds.fullcopycalc=%1 hartzailek onartutako %2 kopia oso
+iconBar.switch.tooltip=Vuze UI Hautatzailea
+v3.topbar.menu.show.plugin=Plugin Gunea
+v3.menu.device.exploreTranscodes._windows=Erakutsi Agiriak Explorer-ean
+security.certtruster.intro=Segurtasun Egiaztagiria fidagarritasunik onartu ez diozun baltzu batek jaulki du
+ConfigView.section.style.xulRunnerPath=Adierazi  XulRunner / Firefox helburua eskuz [beharrezkoa FF3-rentzat; berrabiaraztea beharrezkoa]
+devices.contextmenu.od.auto=<Berezgaitasunez>
+MyTrackerView.announces=Iragarleak
+azbuddy.dchat.copy.channel.url=Kanal URL-a
+metasearch.template.version.bad='%1' Bilaketa eredua ezin da ezarri Vuze eguneratu arte 
+ConfigView.label.minSeedingTime=Gutxienezko emaritza denbora segundutan
+OpenTorrentWindow.torrent.options=Hurrengo ezarpenak gainean hautaturiko torrentei ezarriko zaie\:
+MyTrackerView.bytesinave=Sar. Bat.best.
+PeersView.upload.info=Zure igoera osoa hartzailera.
+restart.error=Berrabiarazteak huts egin du\n%1\nIkusi <A HREF\="{restart.error.url}">berrabiarazte gaiak</a>.
+Subscription.menu.export=Esportatu...
+ConfigView.label.stop.Sleep=Egoneratu Ordenagailua
+TableColumn.header.CountryFlagSmall.info=Hartzailearen Herrialde Ikurrin Txikia
+DHTTransport.report.send_timeout=bidalketa itxaronaldia
+play.select.content=Hautatu Irakurtzeko Edukia
+label.test.types=Aztertu Motak
+menu.plus=Vuze Plus
+Plugin.localtracker.autoadd.info=Berezgaitasunez gehitu tokiko hartzaile hauek [helbideak ';' bananduta, adib. 1.2.3.4]
+# %1 = "in kbps" or ""; %2 = "upload" or "download"
+MyTorrentsView.dialog.setNumber.text=Sartu %1 zenbaki bat aldatzeko %2era\:
+Trackers.column.status=Egoera
+PeersView.uploadspeed.info=Zure igoera abiadura hartzailera
+TableColumn.header.down.info=Beste erabiltzaielengandik orain jasotzen ari zaren datu zenbatekoa
+MainWindow.dht.status.tooltip=Banaturiko Datubasea lanean dagoenean honek uneko online erabiltzaile zenbatekoa erakusten du
+azinstancehandler.alert.portclash=Ataka gatazka atzeman da LAN-ean\: %1 jadanik erabilpenean du beste Vuze erabiltzaile batek, hautatu zorizko beste ataka eragozteko TCP / UDP aditzea [%2 eta %3 artean]. 
+OpenTorrentWindow.mb.alreadyExists.text=<A HREF\="%1">%3</A> jadanik gehituta dago '%2' bezala
+MainWindow.menu.speed_limits.schedule.msg=Abiadura-muga profilak berezgaitasunez ezartzea agintzen duten oraingo arauak
+PeerManager.status.ok=Ongi
+ConfigView.section.mode.title=Erabiltzaile Gaitasuna
+label.n.will.be.downloaded=%1 jeitsiko da
+external.browser.manual=Eskuz
+ConfigView.section.interface.enabletray=Gaitu Sistema Erretilua [berrabiaraztea beharrezkoa]
+metasearch.addtemplate.dup.title=Bikoiztu Eredua
+PeersView.BlockView.AvailCount=Eskuragarritasun Zenbatekoa
+Plugin.localtracker.name=LAN Hartzaile Bilatzailea
+iconBar.openFolder.tooltip=Ireki Agiritegi bat
+restart.error.bad=Agiri heuskarri okerra '%1'
+CacheView.writes.title=S/I Idatziak
+v3.MainWindow.menu.publish=&Argitaratu
+TableColumn.header.peakup=Igoera Gailurra
+MainWindow.menu.view.show=Erakutsi
+configureWizard.transfer2.test.info=Hautatu azterketa oso bat egiteko abiadura
+subscriptions.config.autostart.max=Hasi bakarrik bada <\= MB [0\: mugagabea]
+library.unopened.header=%1 gai
+ConfigView.section.security.restart.title=Berrabiarazpena Beharrezkoa
+MyTorrentsView.menu.group=Multzoa...
+label.set.shortcut=Ezarri Lasterbidea
+ConfigView.section.connection.tcp.enable=Gaitu TCP-a
+label.reset.piece=Berrezarri Atala
+Peers.column.%=%
+splash.initializeGM=Torrent Kudeatzaile Orokorra Abiarazten
+subscriptions.listwindow.title=Harpidetza Bilatzailea
+MainWindow.menu.tools=&Tresnak
+ConfigView.section.connection.http.enable=Gaitu
+Peers.column.\#=Z
+diagnostics.log_found=Vuze ez da zuzen itzali. Egiaztau <A HREF\="%1">igarpen ohar agiriak</A>. Irakurri ere wikiko idazlana <A HREF\="http\://wiki.vuze.com/w/Vuze_disappears">Vuze Ezagertzea</A> argibide gehiagorako.
+plugins.basicview.activity=Jarduera\:
+natpmp.routeraddress=Geltoki helbidea [blank\: auto]
+dlg.auth.denied.line1=Zure Vuze Plus Eragintza Kodea ukatua izan da. Mesedez klikatu behean argibide gehiago izateko.
+Button.availableSubscriptions=Harpidetza Eskuragarria
+MyTorrentsView.menu.moveDown=&Behera
+UpdateWindow.quit=Irten
+PeersView.host.info=Hartzailearen hostalari izena, eskuragarria denean (egintzari eragin diezaioke)
+wizard.directory.help=Sortu torrenta zuzenbide batetik
+Peers.column.maxdownspeed=Geh. Jeisketa Abiadura
+DHTView.general.uptime=Jardun denb.\:
+MainWindow.menu.help.support=&Laguntza eta Sostengua
+MyTorrentsView.menu.moveTop=&Goren
+ConfigView.label.xfs.allocation.tooltip=Mesedez zihurtatu /usr/sbin/xfs_io zure sisteman ongi ezarrita dagoela. Linux banaketa gehienetan "xfsprogs" paketean dago.
+MyTorrentsView.menu.manual.shared_peers=Eskuz (hartzaile artean)
+PiecesView.title.full=Atalak
+wizard.multitracker.edit.newtracker=Aztarnari Berria
+TorrentOptionsView.param.reset.button=Berrezarri
+menu.register=Vuze Plus Eragiketa
+upnp.mapping.trackerclientudp=UDP Aztarnari Bezero Ataka
+MyTorrentsView.menu.editTracker=Editatu aztarnari URL-ak
+ConfigView.section.connection.networks.Public=IP sare publikoa (ez izengabea)
+IrcView.privatefrom=Hemendik
+ConfigView.section.mode.resetdefaults=Berrezarri ezarpenak berezko balioetan (berrabiaraztea gomendatzen da)
+DHTView.general.live=Bizirik\:
+TableColumn.header.peersources=Hartzaile Iturburuak
+ConfigView.label.moveifsamedrive=Baina hau iturburua eta helmuga agiri sistema ezberdinetan daudenan bakarrik egiten du
+configureWizard.file.message3=Vuze agiriak adieraziriko agiritegira jeitsi ditzake, agiritegi hori hemen hautatu dezakezu\:
+configureWizard.file.message2=Vuzek berehala berrabiarazi ditzake zure agiriak, zure torrentei berrabiarazte datuak eransten badizkiozu. Ezaugarri hau erabiliz, zati bat jeitsitako atalak ere berrabiaraziko dituzu.
+subs.prop.is_public=Publikoa
+configureWizard.file.message1=Vuzek irekitako torrentak agiritegi batean gordeko dira, agiritegi hori hemen adierazi dezakezu\:
+webui.pairingenable=Gaitu uztarpena plugin honentzat (azterketa aukerak gaituak izan daitezke uneko uztarpen xehetasunak ongi argitaratu direnean)
+ConfigView.label.autoadjust=Berezgaitasunez zehaztu ezarpen hau elkarketa abiaduran ohinarrituta
+devices.tivo.machine=TiVo makina izena
+ConfigView.section.ipfilter.start=Hasierako IP-a
+rcm.config.enabled=Gaitu
+wizard.directory=Zuzenbidea
+globalmanager.download.remove.veto=Kenketa Ekintza Eragitza
+ConfigView.section.file.defaultdir.ask=Berezko zuzenbidea\:
+upnp.alert.lostdevice=UPnP\: Zerbitzuarekin elkarketa etenda '%1' UPnP gailuan '%2'
+MyTorrentsView.menu.sl_add_to_prof=Gehitu/Eguneratu Profila
+devices.view.heading=Multimedia bihurgailua irakurgailuarentzat
+azbuddy.ui.table.ss=SS
+SystemTray.menu.open_global_transfer_bar=Erakutsi Eskualdaketa Barra
+RCM.column.rc_seeds=Emaleak
+devices.downloading=Jeisten
+ConfigView.section.stats.graph_update_dividers=Erakutsi lerro zutia 60 eguneraketa bakoitzetik
+Formats.units.Gbit=Gbit
+ConfigView.section.queue.seeding.ignore=Baztertu Arauak 
+TableColumn.header.timesincedownload=Jeisketa Idle-a
+Peers.column.Encryption.info=Erabilitako enkriptaketa maila
+ConfigView.section.connection.advanced.mtu=Gehienezko Eskualdaketa Batasuna Bidea (GEB)
+azsubs.contextmenu.addassoc=Gehitu harpidetza elkarketa
+ConfigView.section.connection.advanced.bind_port=Lotu tokiko atakara [0\: ezgaituta]
+tps.tracker.cache1=Hartzaile katxea\: erabilita\=%1
+aznettorbrowser.install.subtitle=Tor Nabigatzailea Plugina ezartzen
+MainWindow.dialog.restartconfirmation.title=Berrabiarazi Vuze
+ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Ezgaituta dagoenean, azalpenak ez dira gogoratuko
+sidebar.Activity=Oharrak
+upnp.selectedinterfaces=Hautaturiko interfazeak (';' banandurik, adib. eth0;eth1) [blank\: all]
+ConfigView.label.moveonlyusingdefaultsave.tooltip=Mugitu bakarrik jeitsitako datuak berezko datuen zuzenbide badaude
+ConfigTransferAutoSpeed.mode=Era\:
+MagnetURLHandler.report.error=akatsa %1
+tag.show.stats=Erakutsi Etiketa Estatistikak...
+v3.devicesview.infobar.text2=Eduki bat gailu batera transkodeatzeko, arrastatu edukia zure liburutegitik albobarrako gailura. Transkodeaketa osatuak ikusteko, klikatu banako gailuan eskuinean.
+tag.type.ds.err={ManagerItem.error}
+azbuddy.os_not_avail=Eskuraezina
+MyTorrentsView.menu.torrent.dl=Torrent Jeisketa Lotura
+wizard.maketorrent.filesize=Agiri(en) Neurria
+OpenTorrentWindow.mb.existingFiles.partialList=(Zerrenda osatugabea  Agiri gehieago jadanik badaude)
+TableColumn.header.downloadspeedoverall.info=Hartzailearen ustezko jeisketa neurria
+DHTView.operations.store=Biltegia
+subscriptions.column.SubWizRank=Maila
+ConfigView.label.alwaysShowLibraryHeader=Betik erakutsi buru/iragazki barra liburutegian
+FilesView.menu.retarget=Mugitu Agiriak
+TrayWindow.menu.stopalldownloads=Gelditu &Jeisketa Denak
+iconBar.top.tooltip=Mugitu lehen tokira
+MainWindow.dht.status.disabled=DHT-a Ezgaiturik
+SpeedTestWizard.stage.message.requesting=azterketa eskabidean...
+MainWindow.menu.transfers.pausetransfersfor.keybinding.mac=Auk+Ktrl+Aldatu+.
+device.od.enable=Gaitu lineaz-kanpoko jeisketa gailuak
+Button.getstarted=Abiaturik
+SpeedView.stats.estimate=Irizpena
+MainWindow.menu.speed_limits.save_current=Gorde Oraingoa Honela...
+ConfigView.section.interface.clearsavepathsbutton=Garbitu
+MyTorrentsView.menu.movedata=Mugitu Datu Agiriak...
+OpenTorrentWindow.fileList.changeDestination=Aldatu Helmuga
+Progress.reporting.status.retrying=Birsaiatzen...
+ConfigView.section.style.showiconbar=Erakutsi Tresnabarra
+label.current=Oraingoa
+v3.deviceview.infobar.line2.tivo=Bideoak jariotu zure TiVo-ra joanez eta Vuze hautatuz zure Uneko Irakur Zerrendan.
+pairing.accesscode=Sarbide kodea
+MessageBoxWindow.nomoreprompting=Ez galdetu berriro
+SpeedTestWizard.name.conf.level.none=Ez
+devices.xcode.mancopy=Eskuz Kopiatu Agiriak
+MainWindow.menu.file.import=I&nportatu XML Torrenta...
+Tracker.alert.listenfail=Hutsegitea aditzea ataka honetan %1 ezartzerakoan.\nEgiaztatu beste aplikazioak ez daudela ataka hau erabiltzen.\nEgiaztatu ere lanean diharduten Vuzeren beste kopiak.
+v3.MainWindow.menu.file.closewindow=Itxi
+ConfigView.label.minSpeedForActiveDL=Ez zenbatu jeisketa ahoa erabiltzen ari den torrenta abiadura hau baino txikiagoa bada
+importTorrentWizard.torrentfile.browse=Bilatu
+MagnetPlugin.use.md.download=Gaitu jeisketan-ohinarrituriko metadatu eskualdaketa
+label.force.piece=Behartu Atala
+Peers.column.%.info=Orain arte hartzaileak jeitsitako torrentaren ehunekoa
+upnp.info=Plug and Play Unibertsalak (UPnP) ahalbidetzen du berezgaitasunezko ataka izendatzea gaituriko UPnP routerretan.
+ConfigView.section.file.hashchecking.smallestfirst=Berregiaztatu jeisketa txikienak lehenik
+TableColumn.header.chat.msg.count.info=Mezu zenbatekoa beste erabiltzaileengandik (ez zeureak)
+TableColumn.header.profile=Gailua
+label.popups=Oharleihoak
+label.clickone=Klikatu bat
+config.external.browser.switch.feature=Ezaugarria
+PeersView.title.short=Hartzaileak
+ConfigView.label.seeding.rankType.tooltip=Lerrun handiena duten torrentak berezgaitasunez hasten dira.\nBeste torrent batek lerrun handiagoa lortzen duenean, lerrun txikienekoa gelditu eta lerrora itzultzen da.\n\nLerrokatuta egoeran dauden torrentak bakarrik daude baliagarri berezgaitasunez hasteko.\nGelditutako torrentak ez dira inoiz berezgaitasunez hasten.
+OpenTorrentWindow.torrentLocation=Jeitsitako torrenta(k)\:
+network.admin.binding.state=Lotzeak\: %1, behartu\=%2
+ConfigView.section.tracker.maxpeersreturned=Gehienezko hartzaile itzulita [0\: mugagabe]
+label.none={PeersView.uniquepiece.none}
+v3.MainWindow.xofx=%1 %2 -tik
+MyTorrentsView.menu.setpriority.high=&Handia
+ConfigView.label.seeding.autoReposition.tooltip=Gaituta badago, torrenteen ordena (Z zutabea) aldatu egingo da Emaritzen Lerrunarekin bat egin dezan.\nHau erabilgarria da zuk ez badituzu nahi ikusi Emaritzan Lerrunaren zenbakiak, baina jakin nahi duzu osatutako torrentak abiaraziko diren ordena.
+MyTorrentsView.menu.open=&Ireki Agiria
+GeneralView.label.updatein.querying=Eskabidetzen...
+label.routing=Biderapena
+CacheView.reads.fromFile=Agiritik
+ConfigTransferAutoSpeed.algorithm=Algoritmoa\:
+ManagerItem.initializing=Abiarazten
+installPluginsWizard.finish.title=Ezarpena Garatzen
+DHTView.activity.status=Egoera
+ConfigView.section.logging.generatediagnostics=Sortu
+MainWindow.menu.language=&Hizkuntza
+IPChecker.external.service.no-ip.name=Ez-IP
+update.instance.uninstall=Kentzea Egiaztatzen
+MainWindow.menu.view.iconbar=Tresnabarra
+devices.xcode.autoStart=Berezgaitasunez Hazi Beharrezkoa Denean
+ConfigView.section.transfer.autospeed.networks=Sare Xehetasunak
+v3.MainWindow.menu.view.actionbar=Eragiketa Barra
+MainWindow.menu.file.share=&Elkarbanatu
+DHTView.db.divsize=Neurri Dib.
+dht.advanced=Gaitu ezarpen aurreratuak
+label.inactive=Jardungabe
+MagnetPlugin.decentral_backup_disabled=<zentralizatu gabeko babeskopia ezgaituta>
+v3.MainWindow.menu.home=&Tresnategia
+MainWindow.nat.status.tooltip.probok=Eskuragarritasuna Ona zen, horrela ere ez dago TCP elkarketa sarrera berririk
+device.config.xcode.workdir=Berezko lan zuzenbidea transkodeatutako agirientzat
+ConfigView.label.queue.maxactivetorrentswhenseeding=Geh. emaritzen bakarrik [0\:mugagabea]
+DHTView.activity.type=Mota
+button.add.container=Gehitu &Edukiontzia
+ConfigView.section.ipfilter.blockedinfo=IP iragazkiengaitik itxiak izan diren IP-ak
+ConfigView.section.Pairing=Uztarpena
+MyTorrentsView.menu.thisColumn.autoTooltip=Betik erakutsi tresnen argibideak
+security.crypto.badpw=Emandako sarhitza ez da zuzena
+TableColumn.header.azsubs.ui.column.subs.info=Antzeko torrentak dituzten jarioetara harpidetzea ahalbidetzen dizun botoia
+Button.bar.hide=Ezkutatu
+alert.copy.on.comp.done=%1 Jeisketa\nAgiriak ongi kopiatu dira '%2'ra
+window.welcome.title=Ongi etorri Vuzera %1
+pairing.status.initialising=Abiarazten
+config.external.browser.switch.external=Kanpokoa
+ConfigView.section.ipfilter.list.baddata=datu gaitzak bidali ditu.\: gertaerak \=
+#Used by the webui plugin
+MyTorrentsView.menu.removeand.deleteboth=Ezabatu &Biak
+window.updateswt.failed=Eguneratzeak huts egin du, sakatu Ongi berriro berrabiarazteko.
+dlg.install.mlab.description=Mesedez itxaron abiadura azterketa osagia ezartzen den bitartean
+importTorrentWizard.importfile.message=Hautatu inportatuko den xml agiria
+MyTorrentsView.menu.renameColumn={ColumnRenameWindow.title}...
+v3.MainWindow.menu.view.statusbar=Egoera Barra
+label.ago=duela
+dlg.auth.enter.revoked=Oraingo eragintza kodea indargabetua izan da.
+FileView.BlockView.Done=Eginda
+iconBar.remove=Ezabatu
+device.quit.transcoding.title=Transkodeaketa garatzen
+Views.plugins.IRC.title=IRC - Onlineko Laguntza Teknikoa
+DHTView.operations.failed=Huts egin du
+dht.status.disabled=Ezgaitu, eskuraezina den banaturiko datubasea
+UpdateMonitor.messagebox.verification.failed.text=Egiaztapena '%1' hutseginda\: %2
+TableColumn.header.Thumbnail.info=Vuzeren edukientzako txikirudia; beste eduki guztientzakoak sistema eragileak ematen ditu ikur hauek.
+DownloadActivityView.title.short=Abiadura
+subscriptions.column.name=Harpidetza
+Peers.column.peer_id=Hartzaile ID-a
+azbuddy.ui.menu.dec=Dekriptatu Gakoa
+subscriptions.column.new.info=Adierazi emaitza berri bat edo gehiago badaude
+ManagerItem.allocating=Esleitzen
+core.shutdown.alert=Ekintza '%1' sugiltzatua %2
+TableColumn.header.max_sr={max.sr.window.title}
+Sidebar.beta.title=Beta Programa
+MyTorrentsView.dialog.setNumber.inKbps=%1
+seedmore.uploadmore=Ehuneko 100 elkarbanatze maila baino txikiagoa edukitzea ez da ona torrent sarearentzat.\nTorrent honi apur bat gehiago emaritzen utzi beharko zenioke.\nZihur jarraitu nahi duzula?
+device.hide=Ezkutatu Gailua
+priority.normal=Lehentasun Arrunta
+MyTorrents.items.UpSpeedLimit.unlimited=Mugagabe
+MainWindow.about.section.internet=Internet
+TableColumn.header.smootheta.info=UED Abiadura Lehundua {smooth.config}
+Plugin.localtracker.enable=Gaitu LAN hartzaile bilatzailea
+ConfigView.section.interface.resetassoc=Leheneratu explorer agiri elkartzea (.torrent) eta erakarpen kudeatzailea (magnet\:?xt\=...)
+OpenTorrentWindow.mb.notValid.text=Ezin da '%1' torrenta ireki. Emaritzan moduan irekitzen ari bazara, mesedez zihurtatu zaitez torrentaren datu agiria badagoela.
+ipCheckerWizard.service=Zerbitzua
+ConfigView.section.tracker.separatepeerids=Erabili hartzaile nortasun ezberdinak aztarnariarentzat eta datu harremanerako
+SpeedView.stats.session.tooltip=Guztira (Protokoloa)
+swt.install.window.title=Vuze Osagai/Plugin Ezartzailea
+security.certcreate.city=Hiria edo Herria
+ConfigView.section.stats.choosedefaultsavepath=Mesedez hautatu estatistikak gordetzeko zuzenbidea
+ConfigView.section.server.enableudp=Gaitu UDP aztarnari bezero hartuemana
+SpeedView.downloadSpeed.title=Jeisketa Abiadura
+ConfigView.label.defaultstarttorrentsstoppedandpause=Torrent bat gehitzen denean gelditutako egoeran berezgaitasunez gelditu hura
+TableColumn.header.smoothdown.info=Jeiskea Abiadura Lehundua {smooth.config}
+ConfigView.label.allowsameip.tooltip=Egiaztatu BEHAR baduzu bakarrik.\nHau izainen aurkako babesa da (ezgaituta dagoenean).
+SpeedTestWizard.finish.panel.max.upload=Geh. igoera\:
+device.error.xcodefail=Transkodeaketa Hutsegitea
+TableColumn.header.timesinceupload=Igoera Idlea
+ConfigView.label.seeding.rankType.none.tooltip=Antolakuntza ohinarrituta Z zutabean
+device.od.error.notfound=Gailua lineaz-kanpo dagoela dirudi
+ConfigView.section.transfer.autospeed.info=Berez-abiadurak berezgaitasunez zehazten du igoera muga sare elkarketaren gainzamatzea saihesteko\n\nMuga hauek berezgaitasunezko igoera abiadura gaituta dagoenean bakarrik ezarri daitezke eta behar du baita ere banaturiko datubasea gaituta egotea.\n
+sidebar.LibraryCD.tooltip=Osatugabeko %1 torrent dago, hauetako %2 orain emaritzan dago/daude
+exportTorrentWizard.exportfile.path=Helburua\:
+dlg.auth.success.subtitle=Zorionak\!
+pairing.srp.setpw.doit=Aldatu
+MyTorrentsView.menu.clear_resume_data=Garbitu &Datuak Jarraitzeko
+ipfilter.options=IP Iragazki Aukerak...
+security.crypto.password.mismatch=Idatzitako sarhitz balioak ezberdinak dira, mesedez sartu berriro.
+label.contraints=Mugak...
+ConfigView.label.maxuploadswhenbusymin=Torrent bakoitzeko geh. igoera abiadura hartuta denboragailuan dagoenean [seg]
+MainWindow.menu.beta.off=Utzi Beta Programa...
+FancyMenu.Header.Control=Agintea
+ConfigView.section.style.alwaysRefreshMyTorrents=Betik berritu Liburutegia
+PeersView.port=Ataka
+TableColumn.header.lan.info=Hartzailea zure LAN-ean dagoen adierazten duen ikurra
+Button.set=Ezarri
+webui.group.access=Sarbide Agintea
+dlg.auth.install.failed.title=Eragintza Hutsegitea
+ConfigView.label.password=Babestu Vuze sarhitza erabiliz\n - Ikurtutakoan eta hasterakoan galdetuko du.
+configureWizard.transfer2.current=<Oraingo Ezarpenak>
+wizard.multitracker.edit.deletegroup=Ezabatu
+Button.close=Itxi
+ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Gehienezko irteera elkarketa berri ezartzen saiatu behar den Vuze une jakin batean.\nOHARRA\: WindowsXP Service Pack 2 (SP2)-k ezartzen du sistema guztiarentzako aldibereko 10 elkarketa ahalegineko muga..\nBerezko balioa 8 da.
+ConfigView.section.connection.advanced.bind_port.tooltip=Irteera hartune elkarketak tokiko mailan behartuta egongo dira emaniko atakan.\nHau gaitzeak NAT bideratzailearen ezarpenarekin lagundu dezake .
+ConfigView.section.stats.enable=Gaitu
+FilesView.title.full=Agiriak
+TableColumn.menu.sr_prog.interval=Ezarri Garapen Tartea...
+TableColumn.header.tag.xcode=Berez Transkodeatu
+ConfigTransferAutoSpeed.add.comment.to.log=Gehitu aipamena\:
+sidebar.VuzeHDNetwork=Vuze HD Sarea
+br.backup.last.error=Azken babeskopia akatsa\:
+uninstallPluginsWizard.finish.explanation=Hautaturiko Pluginak Eguneratze Laguntzailea erabiliz kendu daitezke
+ConfigView.section.proxy.socks.version=SOCKS bertsioa
+IrcView.privateto=Hona\:
+MainWindow.menu.view.console=Kontsola
+Wizard.Subscription.create.rss=RSS
+SpeedView.stats.session=Saio Honetan\:
+TableColumn.header.sha1=SHA1
+ScrapeInfoView.title=Lehen Aztarnaria
+security.certcreate.firstlastname=Lehen eta bigarren  izena
+ConfigView.section.style.colorOverride.progressBar=Garapen Barra
+MyTorrentsView.menu.host=&Hostalaria...
+SpeedView.stats.downloaded=Jeisketa (Hartuemana)
+SpeedTestWizard.abort.message.not.unchoked=Ezin da inoiz itogabetu ez diren hartzaieletatik jeitsi
+Subscription.menu.remove=Ezabatu
+ConfigView.label.maxdownloads.tooltip=Hemen erabaki duzun kopurua eraginkortasunez jeitsi ahal izango duzu betik, salbuespen batekin.\nLehentasun handiena duen torrent osatu batek jeisketa eraginkor baten tokia hartu dezake guztiz beharrezkoa bada.
+ConfigView.section.tracker.extensions=Hedapenak
+label.check.avail=Eskuragarritasuna
+DiskManager.error.nospace=Diskako tokia ez da nahikoa
+ConfigView.section.security.toolsinfo=JAR agiri izenpetuak plugin batzuk laguntzeko erabiltzen dira, adibidez Swing Web Interfazea (hori egiteko itxuratzen denean).\nJAR agiriak izenpetzeko asmoarekin beharrezkoa da Sun JDK (ez JRE) ezarpenarekin datorren 'tools.jar' agirira sarbidea izatea.\nJRE bakarrik baduzu ezarrita mesedez ezarri ezazu JDK.\nVuzek agiria zure ordez bilatu dezake. Horrela ere, honek huts egiten badu zeuk agerian ezarri dezakezu hemen edukiaren zuzenbidea.
+ConfigView.label.seeding.firstPriority.following=hurrengoetara\:
+OpenTorrentWindow.torrentTable.name=Izena
+ConfigView.label.watchtorrentfolder.tooltip=Bilatu .torrent berriak aldizka
+ConfigView.section.file.resume.recheck.all=Berrabiarazte-hutsegitean egiaztatu agiri guztia atal osatuak bilatzeko (Bestela azken gordeketan eraginda zeuden atalak bakarrik egiaztatuko dira)
+ConfigView.section.connection.peersource.PeerExchange=Beste hartzaile batez lortua
+v3.MainWindow.button.viewdetails=Ikusi Xehetasunak
+ConfigView.label.xfer.bias_up=Handitu jeisketa abiadurak igoera gaitasunera osatugabeko jeisketetan
+general.na.short=E/G
+label.copy.on.comp=Kopiatu Osatutakoan
+ConfigView.section.stats.hours=ordu
+ColumnSetup.title=Zutabe Ezarpena '%1'
+ConfigTransferAutoSpeed.log.button=Laburpena
+ConfigView.label.seeding.firstPriority.ignore=Baztertu Lehentasun Nagusia arauen gainekoa hauentzat\:
+TableColumn.header.torrentfileindex.info=Agiriaren aurkibidea torrentean
+MyTorrentsView.menu.publish=A&rgitaratu...
+DHTView.operations.findValue=Bilaketa Balioa
+dlg.auth.enter.prompt=Vuze Plus Eragiketa Kodea\:
+v3.MainWindow.button.download=Jeitsi
+ConfigView.section.Associations=Izenburua
+window.welcome.file=/changelog.txt
+MainWindow.menu.file.closetab.keybinding=Meta+W
+platform.win32.baddll.SBLSP=SPEEDBit Bideo Bizkortzailea
+MyTorrentsView.menu.setSpeed.slots=ahoak
+updater.cant.write.to.app.details=Agiritegia "%1" idaztezina da.\n\nHonek etorkizuneko software eguneratzeak ezartzea saihestuko du.\n\nMesedez <a href\="http\://wiki.vuze.com/w/Failed_Update">ikusi wikia xehetasunetarako</a>.
+ClientStats.title.full=Bezero Estatistika
+Trackers.column.peers.info=Aztarnariak itzulitako hartzaileak
+MyTorrentsView.menu.peersource=Hartzaile Iturburuak
+splash.loadIpFilters=IP Iragazkiak Gertatzen...
+dht.diagnostics.group=Igarpenak
+OpenTorrentFileView.header={ConfigView.section.files}
+ManagerItem.seeding=Emaritzen
+SpeedView.stats.ratio=Maila
+ConfigView.label.autoopen.dl=Jeisten
+pairing.last.error=Azken akatsa
+ConfigView.section.connection.serverport.wiki=Hautatutako ataka onak
+FilesView.click=Klikatu...
+SystemTray.menu.resumetransfers=Berrekin Eskualdaketak
+MagnetPlugin.decentral_disabled=<zentralizatu gabeko aztarnaritza ezgaituta>
+IPChecker.external.analysingresponse=Erantzuna aztertzen
+devices.od.idle=Hutsik
+upnp.ignorebaddevices.alert=UPnP gailu helbidea %1 bazterturik dago etengabeko akatsengaitik. Ikusi UPnP plugin ezarpenak eragiketa honi buruzko aukerentzako.
+DHTView.operations.ok=Ongi
+OpenTorrentWindow.fileTable.size=Neurria
+exportTorrentWizard.process.outputfileexists.title=Agiria Badago
+azbuddy.ui.table.last_ygm=MBD
+devices.xcode.setcopyto=Ezarri Kopiaketa Agiritegia
+v3.activity.button.readall=Markatu Irakurritako Denak 
+ConfigView.label.stop.autoreset=Berezgaitasunez berrezarri ekintzak '%1' behin eraginduta
+ConfigView.section.plugins.webui=Swing Web Interfazea
+TableColumn.header.category=Kategoria
+webui.rootres=Erro baliabidea
+ConfigView.section.transfer.autospeed.enabledebug=Ohar garbiketa argibideak
+ConfigView.label.autoopen.cd=Emaritzan
+TableColumn.header.smoothdown=Jeisketa Lehundua
+SpeedView.stats.con=Elkarketa xehetasunak\:
+wizard.multitracker.edit.save=Gorde
+ConfigTransferAutoSpeed.set.tolerance=jasangarritasuna (sm)
+Alert.failed.update=Huts egin du gutxienez osagai baten ezarpenak. Ikusi  <A HREF\="{Alert.failed.update.url}">AzureusWiki\: Failed Update</A> [%1]
+ConfigView.label.moveremoved=Mugitu osatutako agiriak (kentzerakoan)
+azbuddy.dchat.nick=Goitizena
+devices.device=Gailua
+ConfigView.label.allowsameip=Ahalbidetu elkarketa anitz IP beretik
+azbuddy.os_offline=Lineaz-kanpo
+dlg.auth.denied=Eragintza Kodea Ukatuta
+TableColumn.header.shareRatio=Elkarbanatze Maila
+subscriptions.column.last-checked=Azken Egiaztapena
+MyTorrentsView.menu.rename.displayed.enter.title=Berrizendatu Erakutsitako Izena
+installPluginsWizard.mode.list=Sourceforge.net-eko zerrendatik
+external.browser.system=Ordenagailuaren Berezkoa
+ConfigView.section.style.status.show_nat=NAT Egoera
+ConfigView.label.ratio=maila
+ConfigView.section.tracker.seedretention=Geh. emaritza atxikia torrent bakoitzeko [0\:mugagabea]
+OpenTorrentWindow.mb.badSize.text='%1' ez da '%2' eta ezin da emaritzarako erabili
+OpenTorrentWindow.addPosition=Lerroko Kokapena
+ConfigView.section.tracker.nonblockingconcmax=Geh. aldibereko elkarketa [0\: mugagabea]
+TableColumn.header.up.info=Orain arte beste erabiltzaileei bidalitako datu zenbatekoa
+azbuddy.ui.menu.copypk=Kopiatu Giltza Publikoa
+ConfigView.section.tracker.pollintervalincper='z' bezerotik behin
+SpeedTestWizard.set.upload.bytes.per.sec=kByte/seg
+label.tracker.templates=Aztarnari Ereduak
+ConfigView.section.interface.enabletray._mac=Gaitu Egoera Barra Ikurra [berrabiaraztea beharrezkoa]
+ConfigView.label.saveresumeinterval=Eguneratu berrekite datuak betik
+TableColumn.header.downloadspeed.info=Hartzailearengandik jasotzen ari zaren abiaduraren neurria
+label.udp_probe=UDP Proba
+OpenTorrentWindow.pastearea=Sartu URL-a, magnet lotura, edo hasha\:
+MainWindow.upgrade.downloadingfrom=Jeisten hemendik\: 
+exportTorrentWizard.torrentfile.message=Hautatu esportatuko den torrent agiria
+TableColumn.header.swarm_average_speed=Erletaldearen Bataz-besteko Abiadura
+pairing.server.warning.title=Uztarpen Zerbitzuaren Mezua
+PeersView.ip.info=Hartzailearen IP-a
+OpenTorrentWindow.mb.alreadyExists.title=Jadanik badago
+DevicesOD.column.od_completion=Eskualdaketa Garapena
+azbuddy.enable_cat_pub=Kategoria publikoak dira zure lagunak izeneman daitezkeen GUZTIAK  (',' banandurik) 
+MyTorrents.column.ColumnProgressETA.compon=Osatuta %1
+importTorrentWizard.process.inputfilebad.title=Inportazio Agiri Baliogabea
+MainWindow.dialog.restartconfirmation.text=Egitan nahi duzu Vuze berrabiaraztea
+TableColumn.header.torrentspeed=Abiadura
+PluginDeprecation.view=Plugin Garbiketa
+v3.button.removeActivityEntry=Kendu Jakinarazpena
+FancyMenu.Header.Content=Edukia
+DHTTransport.report.rerequest_all=bir-eskabidetzen eskualdaketa osoa  %1
+platform.win32.baddll.niphk=Norman Birus-aurkakoa
+MyTorrentsView.menu.forceStart=&Behartu Hastera
+label.no.connections=Elkarketarik gabe
+MainWindow.menu.speed_limits.info.curr=Oraingo ezarpenak
+devices.turnon.title=Piztu Gailu Sostengua
+MainWindow.about.internet.sourceforge=Sourceforge Egitasmoaren Webgunea
+TableColumn.header.secondsseeding=Emaritzen
+v3.mb.delPublished.title=Gelditu Eduki Emaritza
+rcm.rc_title.tt=Klikatu eduki hau bilatzeko
+ConfigView.pluginlist.column.type.builtIn=Barne Eraikita
+configureWizard.transfer2.rate.unchanged=Oraingo ezarpenak erabiliak izan daitezke
+sharing.progress.title=Klasikoen-Elkarbanatze Garapena
+SpeedTestWizard.name.conf.level.high=Handia
+label.outgoing=Kanporantz
+PluginDeprecation.log.details=---------\nEZAGUTARAZLEA\: %1\nHITZINGURUA\: %2\n\n*** AZTARNAKETA HASIERA ***\n%3*** AZTARNAKETA AMAIERA ***\n\n
+platform.win32.baddll.mclsp=McAfee Pribatutasun Zerbitzua
+TableColumn.header.fileext.info=Jeisketaren lehen agiriaren agiri mota/hedapena 
+TableColumn.header.CountryFlagSmall=Ikurra
+ConfigView.section.security.resetkey.error=Hutsegitea du giltzak berrezartzean
+v3.deviceview.infobar.line2.android=Gaitu USB heuskarria zure urrutizkenean bideoak zuzen eskualdatzeo
+device.od.turnon.title=Piztu Lineaz-kanpoko Jeisketa Sostengua
+MainWindow.menu.speed_limits.delete=Ezabatu
+ConfigView.section.style.enableHeaderHeight=Norbere Idazburu Garaiera
+FileItem.high=Handia
+OpenTorrentWindow.addFiles.magnet=Gehitu &Magneta
+devices.xcode.working_dir=Transkodeaketa eremua
+FileDownload.canceled=Torrent agiriaren jeisketa ongi ezeztatu da erabiltzailearen ekintzaz\: %1
+GeneralView.label.status.pieces=Atalen Egoera
+dlg.install.azemp.description=Azalpena
+azbuddy.dchat.pc.enable=Gaitu txat pribatua
+v3.MainWindow.text.log.in=Sartu
+upnp.trace_to_log=Irteerako garbiketa argibide osoa saioa hasteko
+label.tag=Etiketa
+# Used for peers which we can't determine.
+PeerSocket.unknown=Ezezaguna
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fi_FI.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fi_FI.properties
index dfe8695..7397b6e 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fi_FI.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fi_FI.properties
@@ -1248,6 +1248,8 @@ MyTorrentsView.menu.setSpeed.disable=\u00c4l\u00e4 l\u00e4het\u00e4
 MyTorrentsView.menu.setSpeed.disabled=Ei l\u00e4hetet\u00e4
 MyTorrentsView.menu.setSpeed.in=jaettuna
 MyTorrentsView.menu.setSpeed.slots=paikkaan, kullekin
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Enimm\u00e4isl\u00e4hetysnopeus
 GeneralView.label.maxuploadspeed.tooltip=- enimm\u00e4isl\u00e4hetysnopeus (0 = rajoittamaton)
 MyTorrents.items.UpSpeedLimit.disabled=Ei l\u00e4hetet\u00e4
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fr_FR.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fr_FR.properties
index 052cb14..cf1bd22 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fr_FR.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fr_FR.properties
@@ -1,1898 +1,3855 @@
-#There is a plugin to help with internationalizing these bundles at http://azureus.sourceforge.net/plugin_list.php
-MainWindow.menu.file.open.torrent=Fichier .torrent
-Main.parameter.usage=Utilisation: java org.gudy.azureus2.cl.Main [param\u00e8tres] "fichier .torrent" "r\u00e9pertoire de sauvegarde"
-Main.parameter.maxUploads=Nombre max d'envois simultan\u00e9s
-Main.parameter.maxSpeed=Vitesse d'envoi max en octets/s
-MainWindow.menu.file=&Fichier
-MainWindow.menu.file.open=&Ouvrir
-MainWindow.menu.file.create=&Cr\u00e9er un torrent
-MainWindow.menu.file.create.fromfile=\u00c0 &partir d'un fichier
-MainWindow.menu.file.create.fromdir=\u00c0 partir d'un r\u00e9perto&ire
-MainWindow.menu.file.export=&Exporter un torrent en XML...
-MainWindow.menu.file.import=&Importer un torrent XML...
-MainWindow.menu.file.closetab=Fermer l'ongle&t
-MainWindow.menu.file.closewindow=Fermer la &fen\u00eatre
-MainWindow.menu.file.exit=&Quitter
-MainWindow.dialog.choose.file=Choisissez le fichier torrent
-MainWindow.menu.file.folder=R\u00e9pe&rtoire
-MainWindow.dialog.choose.folder=Choisissez le r\u00e9pertoire contenant les .torrent
-MainWindow.menu.view=&Affichage
-MainWindow.menu.view.show=Afficher
-MainWindow.menu.view.mytorrents=M&es torrents
-MainWindow.menu.view.configuration=O&ptions...
-MainWindow.menu.closealldetails=Fermer tous les &d\u00e9tails
-MainWindow.menu.closealldownloadbars=Fermer toutes les &mini-barres
-MainWindow.menu.language=&Langue
-ConfigView.section.language=Langue
-MainWindow.menu.window=&Fen\u00eatre
-MainWindow.menu.window.minimize=&Minimiser
-MainWindow.menu.window.alltofront=A&fficher tout devant
-MainWindow.menu.help=Aid&e
-MainWindow.menu.help.about=\u00c0 &propos...
-MainWindow.about.title=\u00c0 propos de Vuze
-MainWindow.about.section.system=Syst\u00e8me
-MainWindow.about.section.internet=Sur Internet
-MainWindow.about.internet.homepage=Page d'accueil de Vuze
-MainWindow.about.internet.sourceforge=Page Sourceforge
-MainWindow.about.internet.bugreports=Rapporter un bogue
-MainWindow.about.internet.forumdiscussion=Forum g\u00e9n\u00e9ral
-MainWindow.about.internet.wiki=Wiki FAQ Vuze
-MainWindow.dialog.choose.savepath=Choisissez le r\u00e9pertoire de sauvegarde
-MainWindow.dialog.choose.savepath_forallfiles=Choisissez le r\u00e9pertoire de sauvegarde pour TOUS les fichiers
-MainWindow.status.latestversion=Derni\u00e8re
-MainWindow.status.latestversion.clickupdate=Cliquer pour mettre \u00e0 jour
-MainWindow.status.unknown=Inconnue
-MainWindow.status.checking=v\u00e9rification
-MyTorrentsView.mytorrents=Mes torrents
-TableColumn.header.name=Nom
-TableColumn.header.size=Taille
-TableColumn.header.done=Fait
-TableColumn.header.done.info=Pourcentage de la t\u00e2che actuelle compl\u00e9t\u00e9e
-TableColumn.header.status=\u00c9tat
-TableColumn.header.status.info=\u00c9tat du torrent
-TableColumn.header.seeds=Sources
-TableColumn.header.seeds.info=# de source(s) connect\u00e9(s) \u00e0 (# de source(s) total)
-TableColumn.header.peers=Clients
-TableColumn.header.peers.info=# de client(s) connect\u00e9(s) \u00e0 (# de client(s) total)
-TableColumn.header.downspeed=Re\u00e7oit \u00e0
-TableColumn.header.upspeed=Envoie \u00e0
-TableColumn.header.eta=Restant
-TableColumn.header.tracker=Tracker
-TableColumn.header.tracker.info=\u00c9tat du Tracker
-TableColumn.header.trackernextaccess=Prochain acc\u00e8s tracker
-TableColumn.header.trackernextaccess.info=Quand le prochain acc\u00e8s au tracker va avoir lieu
-TableColumn.header.priority=Priorit\u00e9
-TableColumn.header.priority.info=D\u00e9termine la proportion de votre capacit\u00e9 d'envoi r\u00e9serv\u00e9 \u00e0 ce torrent.
-TableColumn.header.seeds.fullcopycalc=%2 copies compl\u00e8tes pour %1 clients
-MyTorrentsView.menu.showdetails=Afficher les d\u00e9&tails
-MyTorrentsView.menu.showdownloadbar=Afficher la &mini-bar
-MyTorrentsView.menu.open=&Ouvrir
-MyTorrentsView.menu.setpriority=Priorit\u00e9
-MyTorrentsView.menu.setpriority.high=&Haute
-MyTorrentsView.menu.setpriority.low=&Basse
-MyTorrentsView.menu.start=&D\u00e9marrer
-MyTorrentsView.menu.stop=&Arr\u00eater
-MyTorrentsView.menu.remove=&Enlever
-MyTorrentsView.menu.changeTracker=C&hanger l'URL du tracker
-TrayWindow.menu.exit=&Quitter
-TrayWindow.menu.show=Afficher Vuze
-SystemTray.menu.exit=&Quitter
-SystemTray.menu.closealldownloadbars=F&ermer toutes les mini-barres
-SystemTray.menu.open_global_transfer_bar=Montrer la barre de transferts
-SystemTray.menu.show=&Afficher Vuze
-PeersView.ip.info=IP du client
-PeersView.port.info=Port utilis\u00e9
-PeersView.T.info=l (local): vous avez \u00e9tabli la connexion, r (distant): un client vous a contact\u00e9.
-PeersView.T.L.tooltip=vous avez \u00e9tabli la connexion
-PeersView.T.R.tooltip=un client vous a contact\u00e9.
-PeersView.I1=I (Int\u00e9ress\u00e9 par le client)
-PeersView.I1.info=\u00cates-vous interess\u00e9 par ce que l'autre client poss\u00e8de\u00a0?
-PeersView.C1=C (Bloqu\u00e9 par le client)
-PeersView.C1.info=Si un client vous emp\u00eache de t\u00e9l\u00e9charger
-PeersView.pieces=Pi\u00e8ces
-PeersView.downloadspeed=Re\u00e7oit \u00e0
-PeersView.download=T\u00e9l\u00e9charg\u00e9
-PeersView.I2=I (Int\u00e9ressant pour le client)
-PeersView.I2.info=Est-ce que le client est interess\u00e9 par vos pi\u00e8ces\u00a0?
-PeersView.C2=C (Bloquant le client)
-PeersView.C2.info=Si vous emp\u00eacher un client de t\u00e9l\u00e9charger
-PeersView.uploadspeed=Envoie \u00e0
-PeersView.uploadspeed.info=Votre vitesse d'envoi actuelle au client.
-PeersView.upload=Envoy\u00e9
-PeersView.upload.info=Votre vitesse moyenne d'envoi au client.
-PeersView.statup=Statistique d'Envoi
-PeersView.statup.info=Valeur estim\u00e9 de la vitesse d'envoi d'un client
-PeersView.S.info=Ignor\u00e9 (Snubbed): Un client peut \u00eatre "ignor\u00e9" manuellement, ou automatiquement (s'il n'envoit pas des donn\u00e9es assez rapidement).
-PeersView.downloadspeedoverall=R\u00e9ception (Vit. Totale de)
-PeersView.client.info=Sorte de logiciel BT le client utilise
-PeersView.menu.snubbed=Ignor\u00e9
-PeersView.title.short=D\u00e9tails
-PeersView.title.full=D\u00e9tails
-AllPeersView.title.full=Tous les pairs
-ConfigView.section.files=Fichiers
-ConfigView.label.usefastresume=Utiliser la reprise rapide
-ConfigView.label.incrementalfile=Cr\u00e9ation incr\u00e9mentale des fichiers
-ConfigView.label.defaultsavepath=R\u00e9pertoire de sauvegarde des donn\u00e9es par d\u00e9faut
-ConfigView.button.browse=Parcourir...
-ConfigView.dialog.choosedefaultsavepath=Choissisez le r\u00e9pertoire d'enregistrement des donn\u00e9es
-ConfigView.section.server=Connexion
-ConfigView.section.global=G\u00e9n\u00e9ral
-ConfigView.label.disconnetseed=Se d\u00e9connecter des sources lorsqu'on est source
-ConfigView.label.switchpriority=Passez en basse priorit\u00e9 lorsque l'on est source
-ConfigView.label.maxdownloads=Nombre de t\u00e9l\u00e9chargements simultan\u00e9s
-ConfigView.label.maxdownloads.tooltip=Vous allez toujours \u00eatre en mesure de t\u00e9l\u00e9charger autant de fichiers que vous sp\u00e9cifiez ici.\n Par contre les torrents identifi\u00e9s "1\u00e8re priorit\u00e9" peuvent voler un emplacement de t\u00e9l\u00e9chargement si c'est absolument n\u00e9cessaire.
-ConfigView.label.maxactivetorrents=Nombre total de torrents actifs [0\u00a0: illimit\u00e9]\n
-ConfigView.label.priorityExtensions=Passez en haute priorit\u00e9 les fichiers dont l'extension est\u00a0:\n(ex: .txt;.nfo;.jpg)
-ConfigView.section.transfer=Transfert
-ConfigView.label.maxuploads=Nombre d'uploads par d\u00e9faut (par torrent)
-ConfigView.label.maxuploadspeed=ko/s Vitesse globale maximale d'envoi [0\u00a0: illimit\u00e9e]
-ConfigView.label.saveresumeinterval=Sauver les donn\u00e9es de 'reprise rapide' toutes les
-ConfigView.unlimited=Illimit\u00e9
-ConfigView.section.display=Affichage
-ConfigView.label.opendetails=Ouverture automatique de la fen\u00eatre D\u00e9tails
-ConfigView.label.openbar=Ouverture automatique des mini-barres
-ConfigView.label.closetotray=Fermer r\u00e9duit dans la barre des t\u00e2ches
-ConfigView.label.minimizetotray=Minimiser r\u00e9duit dans la barre des t\u00e2ches
-ConfigView.section.general=G\u00e9neral
-ConfigView.section.start=Lancement
-ConfigView.label.showsplash=Afficher l'\u00e9cran d'accueil au d\u00e9marrage
-ConfigView.label.autoupdate=Ex\u00e9cuter l'assistant de mise \u00e0 jour quand une nouvelle version est disponible
-ConfigView.label.openconsole=Ouvrir la Console au d\u00e9marrage
-ConfigView.label.openconfig=Ouvrir le menu Options au d\u00e9marrage
-ConfigView.label.startminimized=Lancer minimis\u00e9
-ConfigView.label.ircwiki=Veuillez visiter http://www.azureuswiki.com/index.php/Rules_for_IRC
-ConfigView.label.ircserver=Serveur
-ConfigView.label.ircchannel=Canal
-ConfigView.label.irclogin=Alias
-ConfigView.group.irctitle=R\u00e9glages IRC
-ConfigView.boolean.ircsendinfo=Permettre l'envoi de vos r\u00e9glages aux op\u00e9rateurs\n du canal pour mieux vous aider
-ConfigView.boolean.irclog=Activer la journalisation du canal (dans IRC_log.htm)
-ConfigView.section.security=S\u00e9curit\u00e9
-ConfigView.label.password=Prot\u00e9ger Vuze par un mot de passe\nN\u00e9cessaire pour d\u00e9-iconifier, ainsi qu'au lancement.
-ConfigView.label.passwordconfirm=Mot de passe (confirmation)
-ConfigView.label.passwordmatch=Mot de passe activ\u00e9\u00a0:
-ConfigView.label.passwordmatchnone=Non
-ConfigView.label.passwordmatchno=Non / Les mots de passe ne correspondent pas
-ConfigView.label.passwordmatchyes=Oui
-ConfigView.button.save=Sauver
-FileItem.write=\u00c9criture
-FileItem.read=Lecture
-FileItem.normal=Normale
-FileItem.high=\u00c9lev\u00e9e
-FileItem.donotdownload=Ne pas t\u00e9l\u00e9charger
-FileItem.delete=Supprim\u00e9
-FilesView.name=Nom
-FilesView.size=Taille
-FilesView.done=Fait
-FilesView.firstpiece=n\u00b0 de la premi\u00e8re pi\u00e8ce
-FilesView.numberofpieces=# de pi\u00e8ces
-FilesView.pieces=Pi\u00e8ces
-FilesView.priority=Priorit\u00e9
-FilesView.menu.open=&Ouvrir
-FilesView.menu.setpriority=&Priorit\u00e9
-FilesView.menu.setpriority.high=\u00c9l&ev\u00e9e
-FilesView.menu.setpriority.normal=&Normale
-FilesView.menu.setpriority.skipped=Ne pas &t\u00e9l\u00e9charger
-FilesView.title.short=Fichiers
-FilesView.title.full=Fichiers
-GeneralView.section.downloaded=T\u00e9l\u00e9charg\u00e9
-GeneralView.label.status.file=Fichier
-GeneralView.label.status.pieces=Pi\u00e8ces
-GeneralView.section.availability=Disponibilit\u00e9
-GeneralView.label.status.pieces_available=Pi\u00e8ces\u00a0
-GeneralView.section.transfer=Transfert
-GeneralView.section.info=Informations
-GeneralView.title.short=G\u00e9n\u00e9ral
-GeneralView.title.full=G\u00e9n\u00e9ral
-GeneralView.label.timeelapsed=Temps \u00e9coul\u00e9:
-GeneralView.label.remaining=Temps/Taille restant\u00a0:
-GeneralView.label.downloaded=T\u00e9l\u00e9charg\u00e9\u00a0: 
-GeneralView.label.downloadspeed=Vitesse de t\u00e9l\u00e9chargement\u00a0: 
-GeneralView.label.maxuploads=Max. clients actifs\u00a0:
-GeneralView.label.maxuploads.tooltip=Nombre maximum de clients "unchock\u00e9s" (clients auxquels on est susceptibles d'envoyer des donn\u00e9es) en m\u00eame temps
-GeneralView.label.uploaded=Envoy\u00e9\u00a0:
-GeneralView.label.uploadspeed=Vitesse d'envoi\u00a0:
-GeneralView.label.seeds=Source(s)\u00a0:
-GeneralView.label.peers=Client(s)\u00a0:
-GeneralView.label.completed=Termin\u00e9 :
-GeneralView.label.totalspeed=Vitesse totale\u00a0:
-GeneralView.label.totalspeed.tooltip=Vitesse de r\u00e9ception totale du torrent, redistribu\u00e9e entre tous les clients auxquels vous \u00eates connect\u00e9s.\nPour situer votre vitesse de t\u00e9l\u00e9chargement, vous pouvez calculer la moyenne de vitesse des\nclients en divisant cette vitesse totale par le nombre de clients auxquels vous \u00eates connect\u00e9s.\n
-GeneralView.label.averagespeed=moyenne
-GeneralView.label.filename=Nom\u00a0: 
-GeneralView.label.totalsize=Taille totale\u00a0:
-GeneralView.label.savein=Enregistrer dans\u00a0:
-GeneralView.label.hash=Hash\u00a0: 
-GeneralView.label.numberofpieces=Nombre de pi\u00e8ces\u00a0:
-GeneralView.label.size=Taille d'une pi\u00e8ce\u00a0:
-GeneralView.label.tracker=\u00c9tat du Tracker\u00a0:
-GeneralView.label.updatein=Mise \u00e0 jour dans\u00a0:
-GeneralView.label.trackerurl=URL du Tracker\u00a0:
-GeneralView.label.trackerurlupdate=Mise \u00e0 jour manuelle
-GeneralView.label.comment=Commentaire\u00a0: 
-ManagerItem.waiting=En attente
-ManagerItem.allocating=Allocation
-ManagerItem.checking=V\u00e9rification
-ManagerItem.ready=Pr\u00eat
-ManagerItem.downloading=T\u00e9l\u00e9chargement
-ManagerItem.seeding=Source
-ManagerItem.stopped=Arr\u00eat\u00e9
-ManagerItem.error=Erreur
-ManagerItem.high=Haute
-ManagerItem.low=Basse
-MinimizedWindow.name=Nom\u00a0: 
-PiecesView.size=Taille
-PiecesView.numberofblocks=Nbre de Blocs
-PiecesView.blocks=Blocs
-PiecesView.completed=Faits
-PiecesView.availability=Disponibilit\u00e9
-PiecesView.reservedby=Reserv\u00e9
-PiecesView.writers=Contributeurs au bloc
-PiecesView.title.short=Pi\u00e8ces
-PiecesView.title.full=Pi\u00e8ces
-SystemTray.tooltip.seeding=%1 \u00a0Sources,\u00a0
-SystemTray.tooltip.downloading=%1 \u00a0T\u00e9l\u00e9chargements\n
-DownloadManager.error.filenotfound=Fichier non trouv\u00e9
-DownloadManager.error.fileempty=Fichier .torrent vide
-DownloadManager.error.filetoobig=Fichier .torrent trop gros
-DownloadManager.error.filewithouttorrentinfo=Pas d'information "torrent" dans le fichier
-DownloadManager.error.unsupportedencoding=Format d'encodage non support\u00e9
-DownloadManager.error.ioerror=Erreur d'IO
-DownloadManager.error.sha1=Erreur\u00a0: pas d'algorithme SHA1
-PeerManager.status.offline=Erreur de connexion
-PeerManager.status.ok=ok
-PeerManager.status.checking=en cours
-PeerManager.status.finished=Termin\u00e9
-PeerManager.status.finishedin=Termin\u00e9 en
-MainWindow.upgrade.assistant=Assistant de mise \u00e0 jour
-MainWindow.upgrade.newerversion=Une nouvelle version de Vuze est disponible
-MainWindow.upgrade.explanation=Cet assistant va t\u00e9l\u00e9charger la nouvelle version dans votre r\u00e9pertoire Vuze et relancer le programme
-MainWindow.upgrade.explanation.manual=- \u00c9tape 1: Fermez Vuze n- \u00c9tape 2: T\u00e9l\u00e9chargez la nouvelle du lien ci-dessous dans le r\u00e9pertoire d'installation de Vuze n- \u00c9tape 3: Red\u00e9marrez Vuze
-MainWindow.upgrade.step1=\u00c9tape 1: T\u00e9l\u00e9chargement de la nouvelle version
-MainWindow.upgrade.step2=\u00c9tape 2: Fermeture de cette version et relance de la nouvelle
-MainWindow.upgrade.hint1=Astuce:\tAppuyer sur Terminer rend l'op\u00e9ration automatique
-MainWindow.upgrade.hint2=Astuce:\tSi vous voulez fermer Vuze plus tard, appuyer sur Annuler et\n\trenommez Azureus2-new.jar en Azureus2.jar apr\u00e8s fermeture
-MainWindow.upgrade.error.downloading.hint=Erreur:\tIncapable de t\u00e9l\u00e9charger la nouvelle version, veuillez faire la mise \u00e0 jour manuellement
-MainWindow.upgrade.section.info=Nouvelle version disponible
-MainWindow.upgrade.section.manual=Mise \u00e0 jour manuelle
-MainWindow.upgrade.section.automatic=Mise \u00e0 jour automatique
-MainWindow.upgrade.tooltip.progressbar=\u00c9tat d'avancement du t\u00e9l\u00e9chargement
-Button.next=Suivant
-Button.finish=Terminer
-Button.cancel=Annuler
-LocaleUtil.title=Choisir le codage des caract\u00e8res
-LocaleUtil.section.chooseencoding=Choisir l'encodage pour le nom du fichier
-LocaleUtil.label.chooseencoding=Veuillez choisir l'encodage le plus appropri\u00e9
-LocaleUtil.label.hint.doubleclick=Astuce: Double-cliquer sur une colonne s\u00e9lectionne l'encodage et ferme la fen\u00eatre
-LocaleUtil.label.checkbox.rememberdecision=Se souvenir du r\u00e9glage pour les autres fichiers
-LocaleUtil.column.encoding=Encodage
-IrcClient.defaultChannel=#Azureus-French
-IrcClient.copyright=Utilise l'API Java IRC PircBot - www.jibble.org/pircbot
-IrcClient.connecting=Se connecte \u00e0
-IrcClient.connected=Connect\u00e9 \u00e0
-IrcClient.joining=Rejoint
-IrcClient.channel=Canal
-IrcClient.joined=rejoint
-IrcClient.error=Erreur
-IrcClient.hasjoined=a rejoint le canal
-IrcClient.haskicked=a \u00e9ject\u00e9
-IrcClient.hasleft=est parti
-IrcClient.nowknown=est maintenant
-IrcClient.topicforchannel=Topic pour le canal
-IrcClient.disconnected=D\u00e9connect\u00e9 de
-IrcClient.noNick=Alias non pr\u00e9cis\u00e9. Veuillez remplir le champ correspondant dans le menu 'Options'
-IrcView.actionnotsupported=Cette action n'est pas support\u00e9e
-IrcView.clientsconnected=Utilisateurs
-IrcView.privateto=\u00c0
-IrcView.privatefrom=De
-IrcView.noticefrom=Notice:
-IrcView.errormsg=Erreur de syntaxe /msg : /msg [utilisateur] texte
-IrcView.help=Commandes valides :\n . /help : affiche ce message\n . /nick | /name : change votre alias\n . /me action : envoie une action \n . /msg [utilisateur] message : envoie un message priv\u00e9 \u00e0 <alias>\n . /r message : r\u00e9pond au dernier message priv\u00e9\n . /join #canal : change le canal actuel
-PasswordWindow.title=Vuze est barr\u00e9
-PasswordWindow.passwordprotected=Vuze est prot\u00e9g\u00e9 par un mot de passe.\nPour r\u00e9tablir Vuze veuillez entrer votre mot de passe :
-PeersView.discarded=Rejet\u00e9
-PeersView.discarded.info=Pi\u00e8ces re\u00e7ues alors que vous les aviez d\u00e9j\u00e0. Elimin\u00e9es.
-discarded=rejet\u00e9s
-MyTorrentsView.menu.move=&D\u00e9placer
-MyTorrentsView.menu.moveUp=Vers le h&aut
-MyTorrentsView.menu.moveDown=Vers le ba&s
-GeneralView.label.hashfails=Pi\u00e8ce(s) invalide(s)\u00a0:
-GeneralView.label.shareRatio=Taux de partage\u00a0: 
-ConfigView.section.downloadManagement=Gestion des t\u00e9l\u00e9chargements
-ConfigView.label.startRatioPeers=D\u00e9marrer le torrent quand il y a moins de 1 source pour 
-ConfigView.text.neverStop=Ne jamais arr\u00eater
-ConfigView.text.neverStart=Ne jamais d\u00e9marrer
-ConfigView.text.peers=Clients
-ConfigView.label.checkOncompletion=V\u00e9rifier le fichier \u00e0 la fin du t\u00e9l\u00e9chargement
-wizard.title=Cr\u00e9er un torrent
-wizard.previous=< Retour
-wizard.next=Suivant >
-wizard.finish=Terminer
-wizard.invalidurl=Cette URL n'est pas valide
-wizard.singlefile=Un seul fichier
-wizard.singlefile.help=Cr\u00e9er un torrent \u00e0 partir d'un seul fichier
-wizard.directory=R\u00e9pertoire
-wizard.directory.help=Cr\u00e9er un torrent \u00e0 partir d'un r\u00e9pertoire
-wizard.choosefile=Choisir un fichier
-wizard.file=Fichier:
-wizard.browse=Rechercher...
-wizard.choosedirectory=Choisir un r\u00e9pertoire
-wizard.invalidfile=Fichier non valide\u00a0!
-wizard.invaliddirectory=R\u00e9pertoire non valide\u00a0!
-wizard.torrentFile=Fichier torrent
-wizard.choosetorrent=Veuillez choisir le fichier torrent \u00e0 cr\u00e9er
-wizard.notimplemented=Pas encore impl\u00e9ment\u00e9
-wizard.progresstitle=Cr\u00e9ation du fichier torrent
-wizard.savingfile=Sauvegarde du fichier...
-wizard.filesaved=Fichier sauvegard\u00e9.
-wizard.close=Fermer
-Torrent.create.progress.piecelength=Taille d'une pi\u00e8ce: 
-Torrent.create.progress.piececount=Nombre de pi\u00e8ces: 
-Torrent.create.progress.totalfilesize=Taille totale du fichier: 
-Torrent.create.progress.totalfilecount=Nombre total de fichiers: 
-Torrent.create.progress.parsingfiles=Analyse des fichiers
-Torrent.create.progress.hashing=Calcul du Hash des fichiers
-MainWindow.upgrade.downloadingfrom=T\u00e9l\u00e9chargement depuis : 
-MainWindow.menu.view.ipFilter=Filtres I&P
-ConfigView.section.ipfilter=Filtres IP
-ConfigView.section.ipfilter.start=IP de d\u00e9part
-ConfigView.section.ipfilter.end=IP de fin
-ConfigView.section.ipfilter.add=Ajouter
-ConfigView.section.ipfilter.remove=Enlever
-ConfigView.section.ipfilter.edit=\u00c9diter
-ConfigView.section.ipfilter.save=Sauver
-ConfigView.section.ipfilter.editFilter=\u00c9diter le filtre
-ConfigView.section.ipfilter.enable=Appliquer le filtre
-PeersView.menu.close=Fermer
-seedmore.title=Le torrent a besoin de plus de sources
-seedmore.shareratio=Votre taux de partage sur ce torrent est de  
-seedmore.uploadmore=Un taux de partage inf\u00e9rieur \u00e0 100% est mauvais pour le r\u00e9seau BitTorrent.\nVous devriez continuer \u00e0 partager ce torrent.\n\u00cates-vous s\u00fbr de vouloir continuer\u00a0?
-ConfigView.label.showpopuponclose=Faire apparaitre une fen\u00eatre de confirmation lors de la fermeture d'un torrent avec un taux de partage inf\u00e9rieur \u00e0 1
-ConfigView.label.startNumSeeds=\nD\u00e9marrer la source quand il y a moins de \nA priorit\u00e9 sur les autres r\u00e8gles
-ConfigView.label.seeds=sources
-ConfigView.section.seeding=Gestion des sources
-MyTorrentsView.menu.removeand=E&nlever et
-MyTorrentsView.menu.removeand.deletetorrent=effacer le fichier &torrent
-MyTorrentsView.menu.removeand.deletedata=effacer les &donn\u00e9es
-MyTorrentsView.menu.removeand.deleteboth=e&ffacer tout
-deletedata.title=!!! Attention !!!
-MainWindow.menu.file.configure=&Assistant de configuration
-configureWizard.title=Assistant de Configuration
-configureWizard.welcome.title=Bienvenue dans l'Assistant de Configuration de Vuze
-configureWizard.welcome.message=Cet Assistant va vous permettre de configurer Vuze pour un usage courant. Vous pouvez modifier plus en profondeur la configuration dans le menu:\n\nOutils > Options...
-configureWizard.transfer.title=Transferts et Connexion
-configureWizard.transfer.hint=Astuce\u00a0: Choisir une vitesse l\u00e9g\u00e8rement inf\u00e9rieure \u00e0 votre connexion.
-configureWizard.transfer.message=Veuillez choisir votre connexion ci-dessous. Soyez pr\u00e9venus qu'une faible vitesse d'envoi donnera de pi\u00e8tres performances. Puisque la vitesse d'envoi importe pour chaque torrent, t\u00e9l\u00e9charger trop de torrents \u00e0 la fois donnera \u00e9galement de mauvaises performances. Nous conseillons d'allouer un MINIMUM de 5kB/s par torrent. Plus la vitesse d'envoi est haute, plus la vitesse de t\u00e9l\u00e9chargement sera rapide. (en fonction d [...]
-configureWizard.transfer.connection=Type de connexion
-configureWizard.transfer.connection.0=Personnalis\u00e9e
-configureWizard.transfer.connection.1=Modem/ISDN
-configureWizard.transfer.connection.2=ADSL/Cable xxx/128 kbit/s
-configureWizard.transfer.connection.3=ADSL/Cable xxx/256 kbit/s
-configureWizard.transfer.connection.4=ADSL/Cable xxx/384 kbit/s
-configureWizard.transfer.connection.5=ADSL/Cable xxx/512 kbit/s
-configureWizard.transfer.connection.6=ADSL/Cable xxx/768 kbit/s
-configureWizard.transfer.connection.7=ADSL/Cable xxx/1024 kbit/s
-configureWizard.transfer.maxUpSpeed=Vitesse d'Envoi Max (kbit/s)
-configureWizard.transfer.maxActiveTorrents=Maximum Actifs
-configureWizard.transfer.maxDownloads=T\u00e9l\u00e9chargements Max
-configureWizard.transfer.maxUploadsPerTorrent=Max Envois par Torrent
-configureWizard.nat.title=NAT / Port du Serveur
-configureWizard.nat.test=Test en cours
-configureWizard.nat.testing=Test du port
-configureWizard.nat.ko=Erreur NAT
-configureWizard.nat.unable=Test impossible
-configureWizard.file.title=Torrents / Fichiers
-configureWizard.file.message1=Vuze va sauvegarder vos .torrent actif dans un r\u00e9pertoire sp\u00e9cifique, qui sera\u00a0:
-configureWizard.file.path=\u00a0
-configureWizard.file.browse=...
-configureWizard.file.message2=\nVuze peut reprendre instantan\u00e9ment le t\u00e9l\u00e9chargement de vos fichiers, en ajoutant des informations de reprise dans vos torrents. Gr\u00e2ce \u00e0 cette fonctionnalit\u00e9, vous pourrez \u00e9galement poursuivre le t\u00e9l\u00e9chargement des pi\u00e8ces partiellement re\u00e7ues.\n\n
-configureWizard.file.fastResume=Activer la reprise rapide
-configureWizard.file.invalidPath=R\u00e9pertoire invalide
-configureWizard.finish.title=Termin\u00e9
-configureWizard.finish.message=Vuze est maintenant configur\u00e9, amusez-vous bien\u00a0!
-wizard.close.message=Voulez-vous ex\u00e9cuter cet assistant la prochaine fois qu'Vuze est lanc\u00e9\u00a0?
-exportTorrentWizard.title=Exporter un torrent en XML
-exportTorrentWizard.torrentfile.title=S\u00e9lection du torrent
-exportTorrentWizard.torrentfile.message=S\u00e9lectionner le fichier torrent \u00e0 exporter
-exportTorrentWizard.torrentfile.path=Chemin
-exportTorrentWizard.torrentfile.browse=...
-exportTorrentWizard.torrentfile.invalidPath=Fichier torrent invalide
-exportTorrentWizard.exportfile.title=S\u00e9lection du torrent \u00e0 exporter
-exportTorrentWizard.exportfile.message=Entrer le nom du fichier XML \u00e0 cr\u00e9er
-exportTorrentWizard.exportfile.path=Chemin
-exportTorrentWizard.exportfile.browse=...
-exportTorrentWizard.exportfile.invalidPath=Fichier \u00e0 exporter invalide
-exportTorrentWizard.finish.title=Termin\u00e9
-exportTorrentWizard.finish.message=Exportation termin\u00e9 avec succ\u00e8s
-exportTorrentWizard.process.inputfilebad.title=Fichier torrent invalide
-exportTorrentWizard.process.inputfilebad.message=Une erreur s'est produite en acc\u00e9dant au fichier\u00a0: 
-exportTorrentWizard.process.outputfileexists.title=Le fichier existe d\u00e9j\u00e0
-exportTorrentWizard.process.outputfileexists.message=Le fichier de destination existe d\u00e9j\u00e0\u00a0; le remplacer\u00a0?
-exportTorrentWizard.process.torrentfail.title=La lecture du torrent a \u00e9chou\u00e9
-exportTorrentWizard.process.exportfail.title=L'exportation du torrent a \u00e9chou\u00e9
-exportTorrentWizard.process.unknownfail.title=Erreur inattendue
-importTorrentWizard.title=Importer un torrent
-importTorrentWizard.torrentfile.title=S\u00e9lection du torrent
-importTorrentWizard.torrentfile.message=S\u00e9lectionner le fichier torrent \u00e0 importer
-importTorrentWizard.torrentfile.path=Chemin d'acc\u00e8s
-importTorrentWizard.torrentfile.browse=Rechercher
-importTorrentWizard.torrentfile.invalidPath=Fichier torrent invalide
-importTorrentWizard.importfile.title=S\u00e9lection du fichier \u00e0 importer
-importTorrentWizard.importfile.message=Choissiser le fichier \u00e0 importer:
-importTorrentWizard.importfile.path=Chemin:
-importTorrentWizard.importfile.browse=...
-importTorrentWizard.importfile.invalidPath=Fichier d'importation invalide
-importTorrentWizard.finish.title=Termin\u00e9
-importTorrentWizard.finish.message=Importation termin\u00e9 avec succ\u00e8s
-importTorrentWizard.process.inputfilebad.title=Fichier d'import invalide
-importTorrentWizard.process.inputfilebad.message=Une erreur s'est produite en acc\u00e8dant au fichier \u00e0 importer:
-importTorrentWizard.process.outputfileexists.title=Le fichier existe d\u00e9j\u00e0
-importTorrentWizard.process.outputfileexists.message=Le fichier destination existe d\u00e9j\u00e0\u00a0; le remplacer\u00a0?
-importTorrentWizard.process.torrentfail.title=L'\u00e9criture du torrent a \u00e9chou\u00e9
-importTorrentWizard.process.importfail.title=L'importation du torrent a \u00e9chou\u00e9
-importTorrentWizard.process.unknownfail.title=Erreur inconnue
-ConfigView.label.bindip=Associer \u00e0 l'adresse IP locale ou \u00e0 l'interface
-ConfigView.label.xfs.allocation=Allouer les nouveaux fichiers en utilisant une m\u00e9thode sp\u00e9cifique au syst\u00e8me de fichier XFS
-ConfigView.label.xfs.allocation.tooltip=Assurez-vous que /usr/sbin/xfs_io est correctement install\u00e9 sur votre syst\u00e8me. La plupart des distributions Linux l'incluent dans le paquetage "xfsprogs".
-xfs.allocation.xfs_io.not.found=L'allocation de fichier pour syst\u00e8me de fichiers XFS a \u00e9chou\u00e9 parce que /usr/sbin/xfs_io n'a pu \u00eatre lanc\u00e9. Assurez-vous qu'il est correctement install\u00e9 sur votre syst\u00e8me. L'erreur originelle est : "%1".
-ConfigView.label.zeronewfiles=Allouer les nouveaux fichiers avec des z\u00e9ros
-ConfigView.label.zeronewfiles.tooltip=La console doit \u00eatre ferm\u00e9e
-ConfigView.section.stats=Statistiques
-ConfigView.section.stats.enable=Activer
-ConfigView.section.stats.defaultsavepath=R\u00e9pertoire de sauvegarde des statistiques
-ConfigView.section.stats.choosedefaultsavepath=Veuillez choisir le r\u00e9pertoire de sauvegarde des statistiques 
-ConfigView.section.stats.savefreq=Fr\u00e9quence de sauvegarde
-ConfigView.section.stats.savefile=Nom du fichier de statistiques
-MyTorrentsView.menu.export=Exporter en XML...
-MyTorrentsView.menu.host=H\u00e9&berger...
-ManagerItem.finishing=Ach\u00e8vement
-ConfigView.dialog.choosedefaulttorrentpath=Choissisez le r\u00e9pertoire d'enregistrement des .torrent
-ConfigView.dialog.choosemovepath=Choissisez le r\u00e9pertoire o\u00f9 d\u00e9placer les torrents compl\u00e9t\u00e9s
-ConfigView.label.movecompleted=D\u00e9placer les fichiers achev\u00e9s
-ConfigView.label.savetorrents=Conserver les fichiers .torrent
-MainWindow.menu.view.mytracker=Mon &tracker
-MyTrackerView.title.full=Mon Tracker
-MyTrackerView.name=Nom
-MyTrackerView.status=\u00c9tat
-MyTrackerView.status.started=En marche
-MyTrackerView.status.stopped=Arr\u00eat\u00e9
-MyTrackerView.peers=Clients
-MyTrackerView.seeds=Sources
-MyTrackerView.announces=Annonces
-MyTrackerView.uploaded=Qt\u00e9 envoy\u00e9e
-MyTrackerView.downloaded=Qt\u00e9 re\u00e7ue
-MyTrackerView.left=Restant
-ConfigView.label.set_ui_transfer_speeds.description.download=R\u00e9glage des vitesses de t\u00e9l\u00e9chargement (en Ko / s) 
-ConfigView.label.set_ui_transfer_speeds.description.upload=R\u00e9glage des vitesses de partage (en Ko / s) 
-ConfigView.section.style.useCustomTabs=Utiliser des onglets fermables (n\u00e9cessite un red\u00e9marrage)
-fileDownloadWindow.saveTorrentIn=Sauvegarder le fichier torrent dans
-fileDownloadWindow.title=Vuze - T\u00e9l\u00e9chargeur de torrents
-fileDownloadWindow.downloading=T\u00e9l\u00e9chargement depuis\u00a0:
-fileDownloadWindow.status=\u00c9tat\u00a0: 
-fileDownloadWindow.state_initializing=Initialisation
-fileDownloadWindow.state_downloading=T\u00e9l\u00e9chargement
-fileDownloadWindow.state_error=Erreur\u00a0: 
-MainWindow.menu.file.open.url=&URL
-MainWindow.menu.file.open.url.keybinding=Meta+U
-openUrl.title=Vuze - Ouvrir l'URL
-openUrl.url=URL:
-MyTorrentsView.menu.host.error.title=L'h\u00e9bergement du torrent a \u00e9chou\u00e9
-MyTorrentsView.menu.host.error.message=L'erreur suivante s'est produite lors de l'h\u00e9bergement du torrent
-ConfigView.section.tracker.pollinterval=Intervalle de temps d'interrogation du tracker (secs)
-ConfigView.section.tracker.publishenable=Publier les d\u00e9tails du torrent vers "<tracker_url>/"
-ConfigView.section.tracker.ip=Adresse IP externe du tracker
-ConfigView.section.style.enableXPStyle=Activer le style XP (n\u00e9cessite un red\u00e9marrage)
-IPChecker.external.service.dyndns.url=www.dyndns.org
-ConfigView.section.tracker.checkip=V\u00e9rification de l'adresse...
-ipCheckerWizard.title=Assistant de v\u00e9rification d'IP
-ipCheckerWizard.chooseService=Veuillez choisir un service de v\u00e9rification d'IP ci-dessous:
-ipCheckerWizard.explanations=Cet assistant vous aide \u00e0 d\u00e9terminer votre adresse IP externe. Si votre IP est dynamique, il est conseill\u00e9 d'ouvrir un compte avec un Dynamic DNS Service. De tels services sont list\u00e9s ci-dessous, utiliser le lien fourni pour cr\u00e9er un compte. Remplissez alors le champ IP avec votre nom d'h\u00f4te (e.g. monnomdhote.dyndns.org). Vous aurez besoin d'un programme qui mettra \u00e0 jour Dynamic DNS Service avec votre adresse IP. De cette m [...]
-ipCheckerWizard.service.description=Description:
-ipCheckerWizard.service.url=Lien:
-ipCheckerWizard.progresstitle=V\u00e9rification IP
-ipCheckerWizard.checkComplete=IP trouv\u00e9e :
-ipCheckerWizard.checkFailed=Erreur, raison:
-wizard.tracker.local=Utiliser le tracker int\u00e9gr\u00e9 \u00e0 Vuze
-wizard.tracker.external=Utiliser un tracker externe
-wizard.tracker.howToLocal=\tAller dans 'Options > Tracker' pour l'activer
-wizard.announceUrl=Annonce URL:
-IPChecker.external.service.discoveryvip.url=ip.discoveryvip.com
-IPChecker.external.service.discoveryvip.description=Discoveryvip - v\u00e9rification d'adresses IP seulement
-IPChecker.external.httpinvalidresponse=R\u00e9ponse HTTP non valide
-IPChecker.external.loadingwebpage=Chargement de la page Web
-IPChecker.external.analysingresponse=Analyse de la r\u00e9ponse
-IPChecker.external.addressextracted=Adresse IP extraite
-IPChecker.external.httploadfail=Le chargement de la page a \u00e9chou\u00e9
-IPChecker.external.timeout=Timeout
-IPChecker.external.ipnotfound=Adresse IP introuvable
-ConfigView.section.tracker.pollintervalincby=Augmenter de
-ConfigView.section.tracker.pollintervalincper=Tous les 'n' clients
-splash.loadingImages=Chargement des images...
-splash.initializeGui=Initialisation de la fen\u00eatre principale...
-splash.openViews=Ouverture des onglets...
-splash.plugin=Chargement du Plugin : 
-configureWizard.nat.tooManyPorts=Trop de ports \u00e0 tester (9 max)
-ConfigView.section.color=Th\u00e8me de Couleur
-MyTorrentsView.menu.publish=&Publier...
-MyTrackerView.status.published=Publi\u00e9
-MyTrackerView.completed=Complet\u00e9
-MainWindow.menu.file.open.torrentnodefault=Fichier torrent (sans r\u00e9pertoire par d\u00e9faut)
-wizard.comment=Commentaire
-ConfigView.label.movetorrent=D\u00e9placer le .torrent
-ConfigView.label.movepartialdownloads=D\u00e9placer, m\u00eame si certains fichiers sont marqu\u00e9s "Ne pas t\u00e9l\u00e9charger" 
-ConfigView.section.file.decoder.label=Encodage par d\u00e9faut\nquand un choix est n\u00e9cessaire
-ConfigView.section.file.decoder.nodecoder=Aucun
-IPChecker.external.service.no-ip.url=www.no-ip.com
-IPChecker.external.service.no-ip.description=Fournisseur de services DNS dynamique et statique\n(aucun service de v\u00e9rification d'IP gratuit)
-ConfigView.section.tracker.publicenable=Autoriser les torrents externes
-ConfigView.label.playdownloadspeech=Jouer \u00e0 la fin d'un t\u00e9l\u00e9chargement
-#
-# Tooltips
-#
-GeneralView.label.status.pieces_available.tooltip=Refl\u00e8te le nombre de copies disponibles.\nSi le nombre \u00e0 droite est inf\u00e9rieur \u00e0 1, vous ne voyez pas une copie compl\u00e8te du fichier\net il fortement probable que votre t\u00e9l\u00e9chargement n'aboutisse pas.
-GeneralView.label.trackerurl.tooltip=Cliquer pour copier l'URL d'annonce dans le presse-papier
-GeneralView.label.trackerurlopen.tooltip=Cliquer pour ouvrir la page Web du Tracker
-#
-# 2.0.4.4
-#
-ConfigView.section.style.guiUpdate=Mise \u00e0 jour de l'interface graphique (GUI) toutes les
-ConfigView.section.style.graphicsUpdate=Mise \u00e0 jour des barres graphiques toutes les 'n' mises \u00e0 jour GUI
-ConfigView.section.style.reOrderDelay=R\u00e9-ordonner les tables toutes les 'n' mises \u00e0 jour GUI [0\u00a0: jamais]
-ConfigView.section.style.reOrderDelay.never=Jamais
-ConfigView.section.logging=Journalisation
-ConfigView.section.logging.enable=Activer la journalisation vers un fichier
-ConfigView.section.logging.logdir=R\u00e9pertoire du fichier journal
-ConfigView.section.logging.choosedefaultsavepath=Veuillez choisir le r\u00e9pertoire de sauvegarde
-GeneralView.label.updatein.querying=Requ\u00eate en cours...
-configureWizard.nat.sharePort=N'utiliser qu'un seul port entrant partag\u00e9 pour tous les torrents
-ConfigView.section.logging.maxsize=Taille maximale du fichier de journalisation
-ConfigView.section.tracker.passwordenableweb=Activer mot de passe sur le tracker Web
-ConfigView.section.tracker.passwordenabletorrent=Activer mot de passe sur les torrents
-ConfigView.section.tracker.username=Nom d'utilisateur
-ConfigView.section.tracker.password=Mot de passe
-columnChooser.title=Choisissez les colonnes \u00e0 afficher
-columnChooser.move=D\u00e9placer les lignes pour r\u00e9organiser l'ordre
-columnChooser.apply=Appliquer
-columnChooser.columnname=Nom de la colonne
-TableColumn.header.shareRatio=TP
-MyTorrentsView.menu.editTableColumns=Choix des &colonnes \u00e0 afficher
-wizard.operationfailed=L'op\u00e9ration a \u00e9chou\u00e9e
-authenticator.title=Authentification requise
-authenticator.realm=Domaine
-authenticator.user=Nom d'utilisateur
-authenticator.password=Mot de passe
-ConfigView.label.allowSendVersion=Permettre \u00e0 Vuze d'envoyer un num\u00e9ro de version anonyme et un identifiant al\u00e9atoire lors de la recherche de mise \u00e0 jour (dans un but statistique).
-ConfigView.label.version.info.link=Allez voir ici pour plus de d\u00e9tails sur les donn\u00e9es qui sont envoy\u00e9es \u00e0 la v\u00e9rification de version du serveur 
-wizard.hint.mode=Astuce:\tVous pouvez glisser/d\u00e9placer un fichier ou un r\u00e9pertoire \n\tsur cet assistant pour le s\u00e9lectionner
-wizard.hint.file=Astuce:\tVous pouvez choisir un seul fichier avec le glisser/d\u00e9placer
-wizard.hint.directory=Astuce:\tVous pouvez choisir un seul r\u00e9pertoire avec le glisser/d\u00e9placer
-MainWindow.menu.help.checkupdate=Rechercher une &mise \u00e0 jour de Vuze
-TableColumn.header.down=T\u00e9l\u00e9charg\u00e9
-TableColumn.header.up=Envoy\u00e9
-ConfigView.section.tracker.passwordenabletorrent.info=N\u00e9cessite un client BitTorrent adapt\u00e9 (e.g. Vuze
-ConfigView.section.style.confirmationOnExit=Faire apparaitre une confirmation \u00e0 la fermeture
-MainWindow.dialog.exitconfirmation.title=Fermer Vuze u00a0?
-MainWindow.dialog.exitconfirmation.text=Voulez-vous vraiment fermer Vuze u00a0?
-SystemTray.menu.stopalltransfers=&Arr\u00eater tous les transferts
-TrayWindow.menu.stopalldownloads=&Arr\u00eater tous les t\u00e9l\u00e9chargements
-ConfigView.section.tracker.sslport.info=Voir le FAQ pour plus d'informations
-wizard.tracker.ssl=Utiliser SSL
-ConfigView.label.playdownloadfinished=Jouer un son quand un t\u00e9l\u00e9chargement se termine
-ConfigView.label.popupdownloadfinished=Montrer une alerte 'popup' quand un t\u00e9l\u00e9chargement est termin\u00e9
-ConfigView.label.popupfilefinished=Montrer une alerte 'popup' quand un fichier est termin\u00e9
-TableColumn.header.pieces=Pi\u00e8ces
-TableColumn.header.pieces.info=Barre graphique r\u00e9pr\u00e9sentant quelles pi\u00e8ces vous avez t\u00e9l\u00e9charg\u00e9
-TableColumn.header.completion=\u00c9tat d'avancement
-TableColumn.header.completion.info=Repr\u00e9sentation graphique du % t\u00e9l\u00e9charg\u00e9
-ConfigView.section.style.showdownloadbasket=Afficher le panier de t\u00e9l\u00e9chargements (glisser et d\u00e9placer les .torrent)
-ConfigView.section.style.alwaysShowTorrentFiles=Toujours montrer les fichiers Torrent dans Details/Fichiers
-wizard.multitracker=Ajouter des informations Multi-tracker au torrent
-wizard.multitracker.title=Multi-tracker
-wizard.multitracker.configuration=Configuration du Multi-tracker
-wizard.multitracker.new=Nouveau...
-wizard.multitracker.edit=\u00c9diter..
-wizard.multitracker.delete=Effacer
-wizard.multitracker.group=Groupe de trackers
-wizard.multitracker.edit.title=\u00c9diteur de multi-tracker
-wizard.multitracker.edit.name=Nom
-wizard.multitracker.edit.save=Sauver
-wizard.multitracker.edit.newgroup=Nouveau groupe
-wizard.multitracker.edit.deletegroup=Effacer
-wizard.multitracker.edit.newtracker=Nouveau tracker
-wizard.multitracker.edit.deletetracker=Effacer
-wizard.multitracker.edit.edit=\u00c9diter
-wizard.addingmt=Ajout des infos Multi-tracker
-wizard.multitracker.noannounce=L'URL d'annonce n'est pas pr\u00e9sente dans la liste de tracker
-MyTorrentsView.menu.recheck=Forcer une re-&v\u00e9rification
-iconBar.showDownloadBar.tooltip=Afficher la barre de t\u00e9l\u00e9chargement
-iconBar.start.tooltip=Commencer
-iconBar.stop.tooltip=Arr\u00eater
-iconBar.remove.tooltip=Enlever
-iconBar.openNoDefault.tooltip=Ouvrir un fichier torrent (sans r\u00e9pertoire par d\u00e9faut)
-iconBar.openURL.tooltip=Ouvrir une URL
-iconBar.openFolder.tooltip=Ouvrir un r\u00e9pertoire
-iconBar.new.tooltip=Cr\u00e9er un torrent
-iconBar.up.tooltip=D\u00e9placer vers le haut
-iconBar.down.tooltip=D\u00e9placer vers le bas
-iconBar.run.tooltip=Ouvrir
-iconBar.host.tooltip=H\u00e9berger
-iconBar.publish.tooltip=Publier
-MyTorrentsView.menu.editTracker=\u00c9diter l'(les) &URL(s) du tracker
-GeneralView.menu.selectTracker=S\u00e9lectionner
-ConfigView.section.stats.xslfile=Nom du fichier XSL
-ConfigView.section.stats.xslfiledetails=Ajout\u00e9 aux stats gr\u00e2ce \u00e0 <?xml-stylesheet>
-ConfigView.label.savetorrentbackup=Conserver une sauvegarde
-ConfigView.section.tracker.forceport=Forcer les torrents externes h\u00e9berg\u00e9s sur le port par d\u00e9faut.
-ConfigView.section.ipfilter.allow=AUTORISER ces IP (BLOQUER par d\u00e9faut)
-ConfigView.section.ipfilter.list.inrange=est dans la plage 
-ConfigView.section.ipfilter.list.notinrange=n'est dans aucune plage
-ConfigView.section.ipfilter.list.title=Liste des IP bloqu\u00e9es
-ConfigView.label.allowsameip=Permettre plus d'une connection de la m\u00eame IP
-ConfigView.label.allowsameip.tooltip=\u00c0 n'activer qu'en cas de BESOIN.\nProtection contre les "leechers" (quand d\u00e9sactiv\u00e9).
-ManagerItem.superseeding=Super-Source
-ConfigView.label.userSuperSeeding=Utiliser le mode Super-Source
-PeersView.uniquepiece=Pi\u00e8ce (Mode Super-Source)
-PeersView.uniquepiece.none=Aucune
-PeersView.timetosend=Temps pour redistribuer la pi\u00e8ce (Mode Super-Source)
-ConfigView.section.style.addurlsilently=Ouvrir l'URL discr\u00e8tement (sans boite de dialogue)
-ConfigView.section.style.addurlsilently.tooltip=Attention\u00a0: si activ\u00e9, la fen\u00eatre principale ne sera pas rendue visible\u00a0!\nSi vous perdez l'icone Vuze d\u00e9sactivez cette option.
-ConfigView.section.file.decoder.prompt=Toujours demander quand un choix d'encodage est disponible
-ConfigView.section.file.decoder.prompt.tooltip=Afficher une bo\u00eete de dialogue quand un choix d'encodage est possible
-MyTorrentsView.menu.moveTop=&Haut
-MyTorrentsView.menu.moveEnd=&Bas
-ConfigView.label.moveonlyusingdefaultsave=si dans le r\u00e9p par d\u00e9faut
-ConfigView.label.moveonlyusingdefaultsave.tooltip=Ne d\u00e9placer que si le .torrent est dans le r\u00e9pertoire de sauvegarde par d\u00e9faut
-ConfigView.label.watchtorrentfolder=Importer les nouveaux torrents automatiquement
-ConfigView.label.watchtorrentfolder.tooltip=Recherche les nouveaux .torrent r\u00e9guli\u00e8rement
-ConfigView.label.watchtorrentfolderinterval=Intervale
-ConfigView.label.watchtorrentfolderinterval.tooltip=Intervale de temps entre les rafra\u00eechissements du contenu du r\u00e9pertoire
-ConfigView.dialog.choosewatchtorrentfolderpath=Choissisez le r\u00e9pertoire o\u00f9 importer des .torrent
-ConfigView.label.startwatchedtorrentsstopped=Commencer arr\u00eat\u00e9
-ConfigView.label.startwatchedtorrentsstopped.tooltip=Ajoute les nouveaux torrents en mode ARR\u00caT\u00c9
-wizard.maketorrent.filesize=Taille fichier(s)
-wizard.maketorrent.piececount=Nombre de pi\u00e8ces
-wizard.maketorrent.piecesize=Taille d'une pi\u00e8ce
-wizard.maketorrent.auto=Automatique
-MainWindow.menu.view.stats=&Statistiques
-SpeedView.title.full=Activit\u00e9
-SpeedView.downloadSpeed.title=Vitesse de t\u00e9l\u00e9chargement
-SpeedView.uploadSpeed.title=Vitesse d'envoi
-ConfigView.section.style.useSIUnits=Utiliser les unit\u00e9s du C\u00c9I (ko -> Kio, etc.)
-iconBar.top.tooltip=D\u00e9placer en t\u00eate de file
-iconBar.bottom.tooltip=D\u00e9placer en bas de file
-TableColumn.header.health=Indicateur de sant\u00e9
-MyTorrentsView.menu.health=\u00c0 propos de l'indic&ateur de sant\u00e9
-health.explain.grey=Le torrent n'est pas en route. (ni en t\u00e9l\u00e9chargement ni en envoi)
-health.explain.red=En t\u00e9l\u00e9chargeant, vous n'\u00eates connect\u00e9s \u00e0 aucun client.
-health.explain.blue=Si source, vous n'\u00eates encore connect\u00e9s \u00e0 aucun client\nSi en t\u00e9l\u00e9chargement, vous \u00eates connect\u00e9s \u00e0 des clients mais le tracker est d\u00e9connect\u00e9.
-health.explain.yellow=Le Tracker est OK, vous avez des connexions \u00e0 des clients, mais aucune entrante.\nSi persistant, vous avez vraisemblablement un probl\u00e8me de configuration de routeur ou de pare-feu
-health.explain.green=Tout se passe bien.
-ConfigView.section.style.alwaysRefreshMyTorrents=Toujours rafra\u00eechir 'Mes Torrents'
-ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Cette option force la mise \u00e0 jour de 'Mes torrents' m\u00eame si cet onglet n'est pas affich\u00e9 (utile pour certains plugins Mirc)
-#
-#2.0.7.0
-#
-security.certtruster.title=Avertissement du certificat de s\u00e9curit\u00e9
-security.certtruster.intro=Le certificat de s\u00e9curit\u00e9 provient d'une compagnie \u00e0 laquelle vous ne faites pas confiance
-security.certtruster.resource=Ressource:
-security.certtruster.issuedto=Publi\u00e9 pour:
-security.certtruster.issuedby=Publi\u00e9 par:
-security.certtruster.prompt=Voulez-vous y faire confiance\u00a0?
-security.certtruster.yes=Oui
-security.certtruster.no=Non
-ConfigView.section.tracker.torrentsperpage=Combien de torrents par page\u00a0? [0\u00a0: illimit\u00e9]
-MainWindow.menu.file.share=&Partager
-MainWindow.menu.file.share.file=&Fichier...
-MainWindow.menu.file.share.dir=&R\u00e9pertoire...
-MainWindow.menu.file.share.dircontents=C&ontenu du r\u00e9pertoire...
-MainWindow.menu.file.share.dircontentsrecursive=Contenu du r\u00e9pertoire (inclure &sous-r\u00e9pertoires)...
-MainWindow.dialog.share.sharefile=Selectionner le fichier \u00e0 partager
-MainWindow.dialog.share.sharedir=S\u00e9lectionner le r\u00e9pertoire \u00e0 partager
-MainWindow.dialog.share.sharedircontents=S\u00e9lectionner le contenu du r\u00e9pertoire \u00e0 partager
-MainWindow.dialog.share.sharedircontents.recursive=Inclure les sous-r\u00e9pertoires
-globalmanager.download.remove.veto=V\u00e9to d'arr\u00eat
-plugin.sharing.download.remove.veto=Ce t\u00e9l\u00e9chargement provient d'une ressource partag\u00e9e.\nEnlever le t\u00e9l\u00e9chargement revient \u00e0 priver les autres de la ressource: voir Outils->Mes Partages.
-ConfigView.section.tracker.main=Principal
-ConfigView.label.prioritizefirstpiece=Donner la priorit\u00e9 aux premi\u00e8res pi\u00e8ces de fichiers
-ConfigView.label.prioritizefirstpiece.tooltip=Tente de t\u00e9l\u00e9charger le d\u00e9but d'un fichier en premier.\nPeut permettre la pr\u00e9visualisation.
-TrayWindow.menu.startalldownloads=&D\u00e9marrer tous les t\u00e9l\u00e9chargements
-SystemTray.menu.startalltransfers=&D\u00e9marrer tous les transferts
-sharing.progress.title=\u00c9tat du partage
-sharing.progress.hide=Cacher
-MainWindow.menu.view.myshares=&Mes partages
-MySharesView.title.full=Mes partages
-MySharesView.name=Nom
-MySharesView.type.file=Fichier
-MySharesView.type.dir=R\u00e9pertoire
-MySharesView.type.dircontents=Contenu du r\u00e9pertoire
-MySharesView.type.dircontentsrecursive=Contenu du r\u00e9pertoire (et sous-r\u00e9pertoires)
-MySharesView.menu.remove=Enlever
-ConfigView.section.tracker.sendpeerids=Envoyer le num\u00e9ro de client ("peer ID") aux t\u00e9l\u00e9chargeurs
-ConfigView.section.tracker.enableudp=Activer l'UDP pour le protocole du tracker
-plugin.sharing.torrent.remove.veto=Cet enregistrement au tracker est d\u00fb \u00e0 une ressource partag\u00e9e.\nPour supprimer le t\u00e9l\u00e9chargement vous devez enlever le partage.
-plugin.download.remove.veto.notstopped=Ce t\u00e9l\u00e9chargement ne peut pas \u00eatre enlev\u00e9 car il n'est pas arr\u00eat\u00e9.
-plugin.sharing.remove.veto=Ce partage est inclus dans un contenu de r\u00e9peroire partag\u00e9 et ne peut pas \u00eatre effac\u00e9 seul.\n Veuiller enlever le partage du r\u00e9pertoire racine.
-GeneralView.label.hash.tooltip=Cliquer pour copier le hash dans le presse-papier.
-ConfigView.section.tracker.maxpeersreturned=Nombre maximum de clients renvoy\u00e9s [0\u00a0: illimit\u00e9]
-ConfigView.label.serverport=Port d'\u00e9coute TCP entrant
-ConfigView.label.serverport.tooltip=Le port doit \u00eatre entre 1 et 65535, et diff\u00e9rent de 6880 qu'Vuze utilise en interne.
-configureWizard.nat.server.tcp_listen_port=Port TCP d'\u00e9coute entrant
-ConfigView.section.sharing=Partage
-ConfigView.section.sharing.usessl=Utiliser le SSL pour le partage (n\u00e9cessite de configurer le tracker)
-ConfigView.section.style.dropdiraction=Glisser-d\u00e9placer pour les r\u00e9pertoires
-ConfigView.section.style.dropdiraction.opentorrents=Ouvrir les torrents
-ConfigView.section.style.dropdiraction.sharefolder=R\u00e9pertoire de partage
-ConfigView.section.style.dropdiraction.sharefoldercontents=Contenu partag\u00e9
-#
-# 2.0.7.x
-#
-Categories.all=Tous
-Categories.uncategorized=Non class\u00e9s
-CategoryAddWindow.message=Entrer un nom de cat\u00e9gorie
-CategoryAddWindow.title=Ajouter une nouvelle cat\u00e9gorie
-ConfigView.label.autoSeedingIgnoreInfo=Les torrents ignor\u00e9s sont d\u00e9plac\u00e9s en bas de file.  Ils ne d\u00e9marrent pas automatiquement.  Les r\u00e8gles "Ignorer" ne s'appliquent pas aux torrents de "Premi\u00e8re priorit\u00e9". Utilisez la valeur 0 pour ignorer une r\u00e8gle.\n\n
-ConfigView.label.directory=Dans le r\u00e9pertoire\u00a0:
-ConfigView.label.disconnetseed.tooltip=Lorsque le t\u00e9l\u00e9chargement est termin\u00e9, la communication\navec d'autres sources n'est plus vraiment n\u00e9cessaire.
-ConfigView.label.ignoreCase=Ignorer la case
-ConfigView.label.ignoreSeeds=Ignorer les torrents avec au moins
-ConfigView.label.importdirectory=Dans le r\u00e9pertoire\u00a0:
-ConfigView.label.minPeersToBoostNoSeeds.tooltip=Tout torrent sans source ou avec moins de sources que sp\u00e9cifi\u00e9\nsera plac\u00e9 en bas de file.
-ConfigView.label.minPeersToBoostNoSeeds=Diminuer le "Rang de source" pour les torrents avec moins de
-ConfigView.label.minSeedingTime.tooltip=Le "rang de source" d'un torrent peut varier fortement pendant une courte p\u00e9riode, for\u00e7ant parfois un torrent \u00e0 d\u00e9marrer pour \u00eatre arr\u00eat\u00e9 et mis en attente juste apr\u00e8s.\nCeci all\u00e8ge le probl\u00e8me en for\u00e7ant le torrent \u00e0 rester source pendant un certain temps.  Vous pouvez toujours l'arr\u00eater manuellement.
-ConfigView.label.minSeedingTime=Temps de source minimum en secondes
-ConfigView.label.minSpeedForActiveDL.tooltip=Un cr\u00eaneau de t\u00e9l\u00e9chargement est utilis\u00e9 pendant les 30 premi\u00e8res secondes\nde d\u00e9marrage d'un torrent incomplet.
-ConfigView.label.minSpeedForActiveDL=Ne pas compter de cr\u00eaneau de t\u00e9l\u00e9chargement pour les torrents dont la vitesse est de moins de
-ConfigView.label.peers=clients
-ConfigView.label.queue.debuglog=Journalisation des informations de d\u00e9boguage
-ConfigView.label.queue.debuglog.info=Ajoute les informations de d\u00e9boguage \u00e0 propos de la file d'attente\ndans la console et dans le journal. Quoique cryptiques,\nces informations vous donnent l'\u00e9tat des torrents\net et pourquoi ils sont arr\u00eat\u00e9s/refusent de d\u00e9marrer.
-ConfigView.label.queue.minQueueingShareRatio=Ne pas arr\u00eater ou mettre en attente un torrent tant que son taux de partage n'atteint pas
-ConfigView.label.ratio=taux
-ConfigView.label.removeOnStop=Enlever le torrent de la liste s'il s'arr\u00eate automatiquement
-ConfigView.label.savedirectory=Dans le r\u00e9pertoire\u00a0:
-ConfigView.label.seeding.autoReposition.tooltip=Si activ\u00e9e, l'ordre des torrents (la colonne '#') sera chang\u00e9 pour s'accorder \u00e0 celui des "Rangs de source"\nC'est utile si vous ne voulez pas voir les nombres des rangs de source mais voulez tout de m\u00eame savoir dans quel ordre les torrents compl\u00e9t\u00e9s vont d\u00e9marrer.
-ConfigView.label.seeding.autoReposition=Repositionner automatiquement les torrents en fonction de leur Rang de source
-ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Souvent les torrents avec peu de sources et beaucoup de clients n'ont pas de copie compl\u00e8te parmi les clients.\nOn ne veut pas alors pr\u00e9tendre qu'il y a une copie compl\u00e8te dans ce cas (et ainsi r\u00e9duire injustement la priorit\u00e9 du torrent)
-ConfigView.label.seeding.fakeFullCopySeedStart=mais seulement pour les torrents avec au moins
-ConfigView.label.seeding.ignore=R\u00e8gles Ignorer
-ConfigView.label.seeding.ignore0Peers=Ignorer les torrents avec 0 client
-ConfigView.label.seeding.ignoreRatioPeers=Ignorer les torrents avec au moins 1 source pour
-ConfigView.label.seeding.ignoreShareRatio=Ignorer les torrents avec un taux de partage de
-ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorer un torrent m\u00eame si\nles r\u00e8gles de Premi\u00e8re Priorit\u00e9 s'appliquent
-ConfigView.label.seeding.ignore.header.rule=R\u00e8gle
-ConfigView.label.seeding.ignore.header.value=Valeur
-ConfigView.label.seeding.firstPriority.info=Les torrents de Premi\u00e8re Priorit\u00e9 seront toujours en t\u00eate de liste.  Les torrents class\u00e9s dans "Aucun" ou "Rotation temporelle" correspondant aux crit\u00e8res de "Premi\u00e8re Priorit\u00e9" ne seront pas automatiquement arr\u00eat\u00e9 et mis en attente. Un torrent de premi\u00e8re priorit\u00e9 prendra un cr\u00eaneau de t\u00e9l\u00e9chargement simultan\u00e9 si besoin (un torrent en source a priorit\u00e9 sur un torre [...]
-ConfigView.label.seeding.firstPriority.FP=Premi\u00e8re Priorit\u00e9
-ConfigView.label.seeding.firstPriority=La premi\u00e8re priorit\u00e9 s'applique aux torrents v\u00e9rifiant
-ConfigView.label.seeding.firstPriority.following=conditions suivantes\u00a0:
-ConfigView.label.seeding.firstPriority.shareRatio=Un taux de partage inf\u00e9rieur \u00e0
-ConfigView.label.seeding.firstPriority.seedingMinutes=Un temps \u00e9coul\u00e9 depuis le passage de "t\u00e9l\u00e9chargement" \u00e0 "source"
-ConfigView.label.seeding.firstPriority.DLMinutes=Un temps \u00e9coul\u00e9 depuis le d\u00e9but du t\u00e9l\u00e9chargement
-ConfigView.label.seeding.numPeersAsFullCopy.tooltip=En pr\u00e9tendant qu'il y a 1 copie compl\u00e8te tous les X clients, on diminue le rang des torrents avec beaucoup de clients.\nCes torrents ont g\u00e9n\u00e9ralement beaucoup de trafic.\nCela ne change pas l'affichage du nombre de sources effectives.
-ConfigView.label.seeding.numPeersAsFullCopy=Pr\u00e9tendre qu'il y a 1 copie compl\u00e8te tous les\n(0\u00a0: ne pas pr\u00e9tendre)
-ConfigView.label.seeding.preferLargerSwarms.tooltip=Si vous \u00eates source de principalement des torrents avec des clients "bloqu\u00e9s", pr\u00e9ferer les plus utilis\u00e9s\nSi vous \u00eates source de principalement des torrents \u00e0 haute disponibilit\u00e9, pref\u00e9rer les moins utilis\u00e9s.
-ConfigView.label.seeding.preferLargerSwarms=Quand des torrents ont le m\u00eame rang, pr\u00e9ferer les plus utilis\u00e9s.
-ConfigView.label.seeding.rankType.none.tooltip=Ordre \u00e0 partir de la colonne '#'
-ConfigView.label.seeding.rankType.none=Aucun
-ConfigView.label.seeding.rankType.peerSeed.options=Options de "taux Clients/Sources"
-ConfigView.label.seeding.rankType.peerSeed.tooltip=Taux plus haut = rang plus \u00e9lev\u00e9
-ConfigView.label.seeding.rankType.peerSeed=Taux de Clients/Sources
-ConfigView.label.seeding.rankType.seed.fallback=Revenir au taux Clients/Sources apr\u00e8s\n(0\u00a0: ne pas y revenir)
-ConfigView.label.seeding.rankType.seed.options=Options du "nombre de sources uniquement"
-ConfigView.label.seeding.rankType.seed.tooltip=Nombre de sources faible = Rang plus \u00e9lev\u00e9
-ConfigView.label.seeding.rankType.seed=Nombre de sources uniquement
-ConfigView.label.seeding.rankType.timedRotation.tooltip=Tous les torrents termin\u00e9s et mis en attente passeront source chacun leur tour.\nLa dur\u00e9e de source est d\u00e9finie par 'Temps de source minimum'
-ConfigView.label.seeding.rankType.timedRotation=Rotation temporelle
-ConfigView.label.seeding.rankType.tooltip=Les torrents de plus haut rangs sont d\u00e9marr\u00e9s automatiquement.\nSi un torrent prend un rang plus \u00e9lev\u00e9, l'autre torrent s'arr\u00eate et se remet dans la file d'attente.\n\nSeuls les torrents "En attente..." sont disponibles pour un d\u00e9marrage automatique.\nJamais les torrents arr\u00eat\u00e9s seront d\u00e9marr\u00e9s automatiquement.
-ConfigView.label.seeding.rankType=Pour le d\u00e9marrage automatique, classer les torrents termin\u00e9s en fonction de\u00a0:
-ConfigView.label.stopAfterMinutes=Une fois en mode source, arr\u00eater apr\u00e8s
-ConfigView.label.switchpriority.tooltip=Une faible priorit\u00e9 r\u00e9duit la vitesse d'envoi allou\u00e9e \u00e0 un torrent.
-ConfigView.pluginlist.info=Les plugins suivants ont \u00e9t\u00e9 identifi\u00e9s. Certains plugins peuvent ne pas avoir d'onglet de configuration.
-ConfigView.pluginlist.noplugins=Aucun plugin trouv\u00e9.
-ConfigView.section.pluginslist=Liste
-ConfigView.section.queue.seeding=Source
-ConfigView.section.queue.seeding.autoStarting=D\u00e9marrage automatique
-ConfigView.section.queue.seeding.ignore=R\u00e8gles "Ignorer"
-ConfigView.section.queue.seeding.firstPriority=Premi\u00e8re Priorit\u00e9
-ConfigView.section.queue.main=Principal
-ConfigView.section.queue=File d'attente
-ConfigView.text.all=toutes les
-ConfigView.text.hours=heures
-ConfigView.text.ignoreRule=Ignorer la r\u00e8gle
-ConfigView.text.ignore=Ignorer
-ConfigView.text.neverIgnore=Ne jamais ignorer
-ConfigView.text.any=une des
-DownloadManager.error.datamissing=Donn\u00e9es manquantes
-MainWindow.menu.file.open.torrentforseeding=Fichier .torrent (source)
-MainWindow.menu.language.refresh=&Rafra\u00eechir
-ManagerItem.forced=(Forc\u00e9)
-ManagerItem.queued=En attente
-MySeedersView.header=Torrents complets/en source
-TableColumn.header.availability.info=# de copies compl\u00e8tes vues
-TableColumn.header.availability=Disponibilit\u00e9
-TableColumn.header.category=Cat\u00e9gorie
-MyTorrentsView.header=Torrents incomplets/en t\u00e9l\u00e9chargement
-TableColumn.header.maxuploads=Nb max d'envois
-MyTorrentsView.menu.category.delete=Effacer cette cat\u00e9&gorie
-MyTorrentsView.menu.forceStart=Forcer le d\u00e9&marrage
-MyTorrentsView.menu.queue=Placer en &file d'attente
-MyTorrentsView.menu.setCategory.add=&Ajouter une cat\u00e9gorie..
-MyTorrentsView.menu.setCategory=Classer dans
-TableColumn.header.savepath=Chemin de sauvegarde
-TableColumn.header.SeedingRank=Rang de source
-TableColumn.header.totalspeed.info=Vitesse d'envoi individuelle de tout les autres clients/sources auquel vous \u00eates reli\u00e9s. Votre vitesse de t\u00e9l\u00e9chargement \u00e0 ceux-ci n'est pas compt\u00e9e dans ce total.
-TableColumn.header.totalspeed=Vit. Totale
-splash.initializePlugins=Initialisation des plugins
-StartStopRules.SPratioMet=1\u00e8re P / Taux S:P OK
-StartStopRules.FP0Peers=1\u00e8reP / 0 client
-StartStopRules.0Peers=0 client
-StartStopRules.numSeedsMet=Sources OK
-StartStopRules.ratioMet=Taux C:S OK
-StartStopRules.shareRatioMet=Taux Partage OK
-StartStopRules.waiting=En attente
-StartStopRules.firstPriority=1\u00e8re Priorit\u00e9
-ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Partager le contenu (et les sous-r\u00e9pertoire)
-DownloadManager.error.unabletostartserver=Impossible de d\u00e9marrer le serveur; V\u00e9rifier la configuration du port entrant et/ou les permissions du pare-feu pour permettre \u00e0 l'application de s'ex\u00e9cuter en tant que serveur.
-GeneralView.label.creationdate=Cr\u00e9\u00e9 le\u00a0: 
-ConfigView.section.tracker.announcescrapepercentage=Intervalle de "Scrape" comme %age de l'annonce\ne.g. 200 = 2:1. (0 = laisser le client d\u00e9cider)
-ManagerItem.stopping=En arr\u00eat...
-ConfigView.section.tracker.announcecacheperiod=Cache de l'annonce (ms)
-ConfigView.section.tracker.scrapecacheperiod=Cache du "Scrape" (ms)
-ConfigView.section.tracker.scrapeandcache="Scrape" et cache
-ConfigView.section.tracker.announcecacheminpeers=Seuil de client pour activation du cache de l'annonce
-MyTrackerView.scrapes="Scrapes"
-fileDownloadWindow.retry=R\u00e9-essai
-MyTrackerView.bytesin=Octets Entr\u00e9s
-MyTrackerView.bytesinave=Moyenne Entr\u00e9e
-MyTrackerView.bytesout=Octets Sortis
-MyTrackerView.bytesoutave=Moyenne Sortie
-ConfigView.section.file.max_open_files=Nombre maximum de fichiers ouverts en\nlecture/\u00e9criture (0 = illimit\u00e9)
-ConfigView.section.file.max_open_files.tooltip=Utile si vous t\u00e9l\u00e9chargez des torrents compos\u00e9s de centaines de fichiers, et que vous atteignez la limite de gestion de fichiers du syst\u00e8me d'exploitation.
-ConfigView.section.proxy=Options Proxy
-ConfigView.section.proxy.enable_proxy=Activer un proxy
-ConfigView.section.proxy.host=H\u00f4te
-ConfigView.section.proxy.username=Nom d'utilisateur
-ConfigView.section.proxy.password=Mot de passe
-ConfigView.section.proxy.enable_socks=J'ai un proxy SOCKS
-wizard.createtorrent.extrahashes=Ajoute des "Hash" pour pouvoir utiliser le torrent sur d'autres r\u00e9seaux (e.g. Gnutella2, eDonkey2K).
-GeneralView.label.connected=connect\u00e9(s)
-GeneralView.label.in_swarm=au total
-ManagerItem.initializing=Initialisation
-AlertMessageBox.error=Erreur
-AlertMessageBox.warning=Avertissement
-AlertMessageBox.unread=Vous avez des messages d'alerte non lus - Cliquez ici pour les afficher.
-SharedPortServer.alert.selectorfailed=Ne peut \u00e9tablir d'\u00e9coute pour les donn\u00e9es entrantes.\nV\u00e9rifier que le pare-feu est r\u00e9gl\u00e9 de telle fa\u00e7on \u00e0 ce que java(w).exe puisse s'ex\u00e9cuter en tant que 'serveur'.
-Tracker.alert.listenfail=Ne peut pas \u00e9couter sur le port %1.\nV\u00e9rifiez si d'autres applications ne sont pas en train d'utiliser ce port.\nV\u00e9rifiez \u00e9galement si une autre version de Vuze n'est en cours d'execution.
-DiskManager.alert.movefileexists=Erreur en d\u00e9pla\u00e7ant les fichiers termin\u00e9s\nLe fichier %1 existe d\u00e9j\u00e0 dans le r\u00e9pertoire de destination
-DiskManager.alert.movefilefails=Erreur en d\u00e9pla\u00e7ant les fichiers termin\u00e9s\nLe d\u00e9placement du fichier %1 a \u00e9chou\u00e9, %2
-DiskManager.alert.movefilerecoveryfails=Erreur de r\u00e9cup\u00e9ration apr\u00e8s l'echec du d\u00e9placement\nLa restauration du fichier %1 a \u00e9chou\u00e9, %2
-ConfigView.section.tracker.logenable=Ecrire les statistiques p\u00e9riodiques dans 'tracker.log'
-SpeedView.stats.title=Statistiques
-SpeedView.stats.session=Cette Session
-SpeedView.stats.session.tooltip=Total (Protocole)
-SpeedView.stats.downloaded=T\u00e9l\u00e9charg\u00e9 (Protocole)
-SpeedView.stats.uploaded=Envoy\u00e9 (Protocole)
-SpeedView.stats.ratio=Taux
-SpeedView.stats.uptime=Temps allum\u00e9 (heures)
-SpeedView.stats.now=Maintenant
-AutoMigration.useralert=R\u00e9sultat de la migration des fichiers et r\u00e9pertoires utilisateur de Vuze u00a0:\n\n%1\n%2TOUT D\u00c9PLACEMENT \u00c9CHOU\u00c9 DOIT \u00caTRE FAIT MANUELLEMENT.
-#
-# > 2.0.8.0
-#
-OpenTorrentWindow.title=Ouvrir le(s) torrent(s)
-OpenTorrentWindow.message=Exp\u00e9rimental
-OpenTorrentWindow.addFiles=&Ajouter des fichiers
-OpenTorrentWindow.dataLocation=Emplacement de sauvegarde:
-OpenTorrentWindow.startMode=Ajouter en mode
-OpenTorrentWindow.startMode.queued=En attente
-OpenTorrentWindow.startMode.stopped=Arr\u00eat\u00e9
-OpenTorrentWindow.startMode.forceStarted=D\u00e9marrage forc\u00e9
-OpenTorrentWindow.addPosition=Position dans la file
-OpenTorrentWindow.addPosition.first=Premi\u00e8re
-OpenTorrentWindow.addPosition.last=Derni\u00e8re
-TableColumn.header.remaining.info=Quantit\u00e9 restante \u00e0 t\u00e9l\u00e9charger
-TableColumn.header.remaining=Restant
-ConfigView.section.tracker.enablecompact=Activer l'annonce de protocole compacte
-ConfigView.section.tracker.enablekey=Activer l'envoi d'une cl\u00e9 au tracker pour une meilleure s\u00e9curit\u00e9
-ConfigView.section.file.perf=Options de Performance
-ConfigView.section.file.perf.explain=Attention - Des changements innapropri\u00e9s \u00e0 ces param\u00e8tres peuvent diminuer la vitesse de vos transferts. Si vous avez des probl\u00e8me de\nsaturation de m\u00e9moire, diminuez le nombres de clients connect\u00e9s et/ou  actifs par d\u00e9faut par torrent. (Options > Transfert)
-ConfigView.section.file.max_open_files.explain=Avoir trop de fichiers ouverts simultan\u00e9ment peut causer des probl\u00e8mes de performance du syst\u00e8me.\nVous pouvez limiter le nombre de fichiers ouverts simultan\u00e9ment.\n
-popup.error.hide=Cacher
-popup.error.details=D\u00e9tails
-ConfigView.section.style.colorOverrides=Choix de couleur
-ConfigView.section.style.colorOverride.progressBar=Barre de progession
-ConfigView.section.style.colorOverride.error=Erreur
-MainWindow.status.tooOld=est vieux, veuillez le mettre \u00e0 jour.
-ConfigView.section.style.colorOverride.warning=Attention
-ConfigView.section.style.colorOverride.altRow=Rangs pairs
-ConfigView.section.file.save.peers.enable=Sauvegarder les connexions pour des reconnexions rapides
-ConfigView.section.file.save.peers.max=Nombre maximum de peers \u00e0 sauvegarder [0: illimit\u00e9]
-ConfigView.section.file.save.peers.pertorrent=par torrent
-ConfigView.label.max_peers_per_torrent=Nombre maximum de connexions par torrent [0\u00a0: illimit\u00e9]
-ConfigView.label.max_peers_total=Nombre maximum de connexions en tout [0\u00a0: illimit\u00e9]
-ConfigView.section.style.colorOverrides.reset=R\u00e9initialiser
-ConfigView.section.language.info=Une v\u00e9rification sera faite \u00e0 chaque d\u00e9marrage d'Azureus.
-ConfigView.section.language.enableUpdate=Activer la mise \u00e0 jour par le Web
-ConfigView.section.language.UpdateURL=URL de mise \u00e0 jour
-ConfigView.section.language.UpdateNow=Mettre \u00e0 jour maintenant\u00a0!
-Button.revert=Annuler
-MyTorrentsView.menu.changeDirectory=Changer le r\u00e9pertoire des donn\u00e9es
-GenericText.column=colonne
-MyTorrentsView.menu.thisColumn.remove=Enlever cette colonne
-MyTorrentsView.menu.thisColumn.toClipboard=Copier le texte dans le presse-papiers
-ConfigView.upload.abbreviated=U\u00a0: 
-TableColumn.header.secondsseeding=En source depuis
-TableColumn.header.secondsseeding.info=temps pass\u00e9 en source.
-TableColumn.header.secondsdownloading=T\u00e9l\u00e9charge depuis
-TableColumn.header.secondsdownloading.info=temps pass\u00e9 en t\u00e9l\u00e9chargement.
-ConfigView.section.tracker.udpversion=Version du protocole UDP (1 ou 2)
-window.updateswt.title=Votre version de SWT est d\u00e9pass\u00e9e\u00a0!
-window.updateswt.text=Votre version de SWT est d\u00e9pass\u00e9e\u00a0!\nSWT est le coeur de  l'interface graphique d'Azureus. Appuyez sur OK pour commencer la mise \u00e0 jour de SWT.
-window.updateswt.status=\u00c9tat
-window.updateswt.failed=Mise \u00e0 jour impossible. Appuyez sur OK pour recommencer la proc\u00e9dure.
-window.updateswt.status.downloading.updater=T\u00e9l\u00e9chargement du Module de mise \u00e0 jour
-window.updateswt.status.finding=Recherche de la version la plus r\u00e9cente
-window.updateswt.status.downloading=T\u00e9l\u00e9chargement de la derni\u00e8re version de SWT
-window.updateswt.status.done=Red\u00e9marrage
-window.updateswt.ok=Ok
-window.updateswt.cancel=Annuler
-swt.updater.downloader.downloading=T\u00e9l\u00e9chargement de SWT \u00e0 partir de
-swt.updater.urlsgetter.downloading=Liste des sites mirroirs en provenance de
-swt.updater.urlsgetter.platform=SWT pour:
-window.updateswt.ignore=Ignor\u00e9
-ConfigView.section.style.useFancyTabs=Utiliser le nouveau type d'onglet
-splash.initializeGM=Initialisation du Global Torrent Manager
-splash.loadingTorrents=Chargement des Torrents
-MyTorrentsView.menu.thisColumn.sort=C&lasser
-Scrape.status.ok='Scrape' Ok.
-Scrape.status.error=Erreurs 'Scrape':
-Scrape.status.error.badURL=L'URL d'annonce ne respecte pas les normes du 'scrape'.
-Scrape.status.error.nohash=Le 'Hash' est manquant.
-Scrape.status.error.invalid=R\u00e9ponse invalide.
-Scrape.status.nextScrapeAt='scrape' suivante \u00e0 %1
-Scrape.status.scraping=En 'Scrape'..
-Scrape.status.initializing=En attente
-ConfigView.label.minSpeedForActiveSeeding=Exclure les torrents compl\u00e9t\u00e9s de la file active si la vitesse est moins de
-ConfigView.section.stats.exportpeers=Exporter les details des peers
-MainWindow.menu.view.irc.moved=Irc est d\u00e9sormais disponible en tant que plugin, voir http://azureus.sourceforge.net/plugin_list.php. Une fois install\u00e9, utiliser le menu Affichage->plugins->IRC pour y acc\u00e8der.
-MyTrackerView.webui.contextmenu.copyurl=Copier l'URL du torrent dans le presse-papiers
-ConfigView.section.file.torrent.ignorefiles=Fichiers \u00e0 ignorer en cr\u00e9ant des torrents\ne.g. .DS_Store;Thumbs.db
-Torrent.create.progress.ignoringfile=Ignore le fichier
-ConfigView.section.style.useUnitsRateBits=Utiliser des bits au lieu des octets pour les valeurs des taux (Kio/s->Kibits/s, etc.)
-ConfigView.section.interface.resetassoc=R\u00e9initialiser les associations de fichiers de l'explorateur (.torrent)
-ConfigView.section.interface.resetassocbutton=R\u00e9initialiser
-ConfigView.section.interface.checkassoc=V\u00e9rifier les associations au d\u00e9marrage
-dialog.associations.title=V\u00e9rification de l'association
-Button.yes=Oui
-Button.no=Non
-ConfigView.label.seeding.autoStart0Peers=D\u00e9marrer automatiquement tous les torrents termin\u00e9s qui ont 0 peer.
-ConfigView.label.seeding.autoStart0Peers.tooltip=Activer pour que le tracker liste toujours les torrents avec 0 peer.
-dialog.associations.prompt=Vuze n'est pas l'application BitTorrent par d\u00e9faut.\nVoulez-vous associer les fichiers .torrent \u00e0 Vuze u00a0?
-dialog.associations.askagain=V\u00e9rifier au d\u00e9marrage
-ConfigView.section.plugins.update=Mise \u00e0 jour Plugin
-Plugin.pluginupdate.enablecheck=Activer la v\u00e9rification de mise \u00e0 jour des plugins
-plugins.basicview.status=Statut:
-plugins.basicview.activity=Activit\u00e9:
-plugins.basicview.progress=Progression:
-ConfigView.label.maxdownloadspeed=ko/s vitesse globale maximale de t\u00e9l\u00e9chargement [0\u00a0: illimit\u00e9e]
-splash.loadingTorrent=Chargement du Torrent
-splash.of=sur
-UpdateWindow.title=Mise \u00e0 jour de Vuze
-UpdateWindow.header=Les composants suivants ont besoin d'une mise \u00e0 jour
-UpdateWindow.columns.install=Installation
-UpdateWindow.columns.name=Nom
-UpdateWindow.columns.size=Taille
-UpdateWindow.cancel=Annuler
-UpdateWindow.quit=Quitter
-UpdateWindow.close=Fermer
-UpdateWindow.ok=Ok
-UpdateWindow.restart=Red\u00e9marrer
-UpdateWindow.status.downloading=T\u00e9l\u00e9charge
-UpdateWindow.status.done=Termin\u00e9
-UpdateWindow.status.failed=Echou\u00e9
-UpdateWindow.status.restartNeeded=Un red\u00e9marrage sera n\u00e9cessaire\u00a0!
-ConfigView.pluginlist.broken=Endommag\u00e9
-ConfigView.pluginlist.whereToPut=Placer tout plugin utilisateur dans leur r\u00e9pertoire sp\u00e9cifique sous\u00a0:
-ConfigView.pluginlist.whereToPutOr=Pour un plugin partag\u00e9, utiliser:
-MainWindow.statusText.checking=V\u00e9rification des mises \u00e0 jour
-TableColumn.header.OnlyCDing4=EnSourceDepuis
-TableColumn.header.OnlyCDing4.info=Dur\u00e9e pendant laquelle le torrent n'a fait qu'\u00eatre en source. Ne prend pas en compte le temps de t\u00e9l\u00e9chargement.
-UpdateWindow.status.restartMaybeNeeded=Un red\u00e9marrage sera peut-\u00eatre necessaire
-ConfigView.pluginlist.shared=partag\u00e9
-PeersView.host=Nom d'h\u00f4te
-PeersView.host.info=Le nom d'h\u00f4te du peer, si disponible (peut affecter les performances)
-MainWindow.menu.help.whatsnew=Quoi de neuf
-ConfigView.label.checkonstart=V\u00e9rifier les mises \u00e0 jour au d\u00e9marrage
-ConfigView.label.periodiccheck=V\u00e9rifier les mises \u00e0 jour p\u00e9riodiquement
-ConfigView.label.opendialog=Ouvrir automatiquement l'assistant de mise \u00e0 jour quand une mise \u00e0 jour est disponible
-MainWindow.updateavail=(Mise \u00e0 jour disponible)
-MainWindow.status.latestversionunchecked=V\u00e9rification de mise \u00e0 jour d\u00e9sactiv\u00e9e
-GeneralView.label.updatein.stopped=Arr\u00eat\u00e9
-StartStopRules.menu.viewDebug=Voir les informations de d\u00e9boggage
-ConfigView.section.style.doNotUseGB=Ne pas utiliser l'unit\u00e9 GB
-ConfigView.section.style.doNotUseGB.tooltip=Si activ\u00e9, Vuze utilisera des MB m\u00eame pour des tailles sup\u00e9rieures \u00e0 1024MB
-MainWindow.menu.help.plugins=Plugins
-ConfigView.section.tracker.enablecategories=S\u00e9parer les torrents par cat\u00e9gorie
-health.explain.share=signifie que le torrent est soit h\u00e9berg\u00e9 soit publi\u00e9
-ConfigView.section.tracker.createcert=Cr\u00e9er un certificat auto-sign\u00e9
-ConfigView.section.tracker.createbutton=Cr\u00e9er
-security.certcreate.title=Cr\u00e9er un certificat auto-sign\u00e9
-security.certcreate.intro=Vous permet de cr\u00e9er un certificat auto-sign\u00e9.
-security.certcreate.strength=Puissance
-security.certcreate.firstlastname=Pr\u00e9nom et nom
-security.certcreate.orgunit=Unit\u00e9 d'organisation
-security.certcreate.city=Ville ou Localit\u00e9
-security.certcreate.state=Etat ou Province
-security.certcreate.country=Code Pays (2 lettres)
-security.certcreate.ok=Cr\u00e9er
-security.certcreate.cancel=Annuler
-security.certcreate.createok=Cr\u00e9ation du certificat r\u00e9alis\u00e9e avec succ\u00e8s.
-security.certcreate.createfail=La cr\u00e9ation du certificat a \u00e9chou\u00e9.
-ConfigView.section.plugins.webui=Interface Web Swing
-ConfigView.section.plugins.xml_http_if=Interface XML/HTTP
-webui.passwordenable=Activer le mot de passe
-webui.user=Nom d'utilisateur
-webui.password=Mot de passe
-webui.protocol=Protocole (*)
-webui.homepage=Page d'accueil (*)
-webui.rootdir=R\u00e9pertoire racine  (*)
-webui.rootres=Ressource racine (*)
-webui.mode.info=Mode peut \u00eatre\n\t"full"\t= toutes op\u00e9rations possibles (d\u00e9faut)\n\t"voir"\t= voir seulement (mais peut mettre \u00e0 jour la fr\u00e9quence de rafra\u00eechissement)
-webui.access=Acc\u00e8s (*)
-webui.access.info=L'acc\u00e8s peut \u00eatre\n\t"local"\t= seule la machine locale peut se connecter\n\t"all"\t= acc\u00e8s pour tous (d\u00e9faut)\n\tIP\t= e.g. 192.168.0.2\t\t\tseulement une IP\n\tIP1-IP2\t= e.g. 192.168.0.1-192.168.0.255\tintervalle inclusif d'IPs.
-GeneralView.label.maxdownloadspeed=Vit. T\u00e9l. Max.
-Security.keystore.corrupt=Le lancement de la cl\u00e9 '%1' a \u00e9chou\u00e9, veuillez l'effacer et recr\u00e9er/r\u00e9importer les certificats.
-Security.keystore.empty=La cl\u00e9 est vide. Veuillez cr\u00e9er un certificat auto-sign\u00e9 (voir Options > S\u00e9curit\u00e9) ou importer un certificat existant dans '%1'.
-webui.restart.info=Des changements sur les param\u00e8tres marqu\u00e9s d'une (*) n\u00e9cessite un red\u00e9marrage
-GeneralView.label.maxdownloadspeed.tooltip=Vitesse maximale de t\u00e9l\u00e9chargement [0\u00a0: illimit\u00e9e]
-upnp.enable=Activer l'UPnP
-upnp.info=Universal Plug and Play (UPnP) permet le mapping automatique de ports sur des routeurs supportant l'UPnP.
-upnp.mapping.dataport=Port entrant de donn\u00e9es des clients
-upnp.mapping.tcptrackerport=Port Tracker TCP
-upnp.mapping.udptrackerport=Port Tracker UDP
-upnp.alert.differenthost=UPnP: Mapping '%1' a \u00e9t\u00e9 r\u00e9serv\u00e9 par '%2' - veuillez s\u00e9lectionner un port diff\u00e9rent
-upnp.alert.mappingok=UPnP: Mapping '%1' \u00e9tabli
-upnp.alert.mappingfailed=UPnP: Mapping '%1' a \u00e9chou\u00e9
-upnp.alertsuccess=Rapporter les mappings r\u00e9ussis
-upnp.alert.lostdevice=UPnP: A perdu la connexion '%1' sur l'appareil UPnP '%2'
-upnp.grabports=Mapper les ports m\u00eame s'ils appartiennent \u00e0 un autre ordinateur.
-upnp.refresh.label=Rafra\u00eechir les mappings
-upnp.refresh.button=Rafra\u00eechir
-upnp.alert.mappinggrabbed=UPnP: Mapping '%1' \u00e9tabli - \u00e0 partir de '%2'
-upnp.mapping.tcpssltrackerport=Port Tracker TCP SSL
-upnp.alertothermappings=Rapporter les ports utilis\u00e9s par d'autres ordinateurs
-upnp.alertdeviceproblems=Rapporter les probl\u00e8mes avec l'UPnP
-ConfigView.pluginlist.coreplugins=Les plugins int\u00e9gr\u00e9s suivants sont charg\u00e9s\u00a0:
-Peers.column.DLedFromOthers=Des autres
-Peers.column.DLedFromOthers.info=Quantit\u00e9 de donn\u00e9es t\u00e9l\u00e9charg\u00e9es des autres quand ils \u00e9taient connect\u00e9s \u00e0 vous.
-Peers.column.UpDownRatio=Envoy\u00e9:T\u00e9l\u00e9charg\u00e9
-Peers.column.UpDownRatio.info=Taux "Envoy\u00e9:T\u00e9l\u00e9charg\u00e9" du client
-Peers.column.UpRatio=Ratio de l'envoi
-Peers.column.UpRatio.info=Taux "Envoy\u00e9 par vous:Envoy\u00e9 par les autres" du client
-upnp.releasemappings=Lib\u00e9rer les mappings \u00e0 la fermeture
-webui.upnpenable=Activer l'UPnP pour ce port (*)
-ConfigView.section.file.friendly.hashchecking=V\u00e9rification du hash moins intensive
-ConfigView.section.file.friendly.hashchecking.tooltip=Un mode de v\u00e9rification du hash des pi\u00e8ces plus lent mais beaucoup moins consommateur de m\u00e9moire et de processeur.
-ConfigView.section.tracker.seedretention=Nb max de sources retenues par torrent [0\u00a0: illimit\u00e9] 
-ConfigView.section.tracker.seedretention.info=Note\u00a0: Les statistiques d'envoi seront perdues pour les sources non retenues.
-ConfigView.section.tracker.port=Activer le tracker sur le port HTTP
-ConfigView.section.tracker.sslport=Activer le tracker sur le port HTTPS
-ConfigView.section.tracker.publicenable.info=Ceci permet \u00e0 d'autres d'utiliser votre tracker\nsans avoir \u00e0 les h\u00e9berger ou les publier.
-Button.clear=Effacer
-MainWindow.IPs.tooltip=Nombre de filtres IP - Nombre d'IP bloqu\u00e9es\nDouble-cliquer pour afficher la liste des connexions refus\u00e9es .
-ConfigView.section.ipfilter.list.banned=a \u00e9t\u00e9 banni pour avoir envoy\u00e9 des mauvaises donn\u00e9es
-ConfigView.section.ipfilter.list.baddata=a envoy\u00e9 de mauvaises donn\u00e9es: nombre de fois =
-Button.reset=R\u00e9initialiser
-ConfigView.section.ipfilter.bannedinfo=IPs qui ont envoy\u00e9s de mauvaises donn\u00e9es - bannies si la limite est d\u00e9pass\u00e9e
-ConfigView.section.ipfilter.blockedinfo=IPs bloqu\u00e9es par les filtres IP
-download.removerules.name=R\u00e8gles de suppression
-download.removerules.unauthorised.info=Les torrents non autoris\u00e9s sont ceux qui contiennent dans la \u00ab\u00a0r\u00e9ponse d'erreur\u00a0\u00bb\u00a0: \u00ab\u00a0not authoris(z)ed\u00a0\u00bb or \u00ab\u00a0unauthoris(z)ed\u00a0\u00bb.
-download.removerules.unauthorised=Supprimer automatiquement les torrents non autoris\u00e9s
-download.removerules.unauthorised.seedingonly=\tSeulement si en source
-download.removerules.removed.ok=La suppression automatique du torrent '%1' a \u00e9t\u00e9 effectu\u00e9e avec succ\u00e8s. Ceci est d\u00fb aux r\u00e8gles de suppression.
-download.removerules.updatetorrents=Supprimer les torrents de mise \u00e0 jour de Vuze si n\u00e9cessaire pour le r\u00e9seau
-ConfigView.label.defaultstarttorrentsstopped=Par d\u00e9faut, ajout des nouveaux torrents \u00e0 l'arr\u00eat
-ConfigView.section.server.enableudp=Activer le protocol UDP pour le client tracker. Utilise le m\u00eame port que TCP.
-upnp.mapping.dataportudp=Port UDP du client tracker
-ConfigView.section.file.decoder.showlax=Montrer les encodages moins probables
-ConfigView.section.file.decoder.showall=Consid\u00e9rer tous les encodages possibles
-MainWindow.status.updowndetails.tooltip=Details sur les vitesses de t\u00e9l\u00e9chargement/envoi - changer par clic droit
-TrackerClient.announce.warningmessage=Tracker de '%1' a retourn\u00e9 l'avertissement '%2'
-ConfigView.section.tracker.natcheckenable=V\u00e9rifier les possibilit\u00e9s de connexion sur le "port entrant des donn\u00e9es" et rapporter les erreurs aux clients
-ConfigView.section.tracker.publishenabledetails=Publier le fichier torrent et ses d\u00e9tails
-ConfigView.section.tracker.publishenablepeerdetails=Publier les d\u00e9tails des clients
-MyTrackerView.badnat=NAT mal configur\u00e9
-MyTrackerView.badnat.info=Sources/Clients ayant echou\u00e9s au test NAT, si activ\u00e9
-ConfigView.section.tracker.natchecktimeout=Expiration de la v\u00e9rification (secs)
-ConfigView.section.file.perf.cache.enable=Activer le cache disque
-ConfigView.section.file.perf.cache.size=Taille du cache en %1
-MainWindow.menu.transfers=&Transferts
-MainWindow.menu.transfers.startalltransfers=&D\u00e9marrer tout
-MainWindow.menu.transfers.stopalltransfers=&Arr\u00eater tout
-MainWindow.menu.transfers.resumetransfers=&Reprendre
-ConfigView.label.experimental.osx.kernel.panic.fix=Fix exp\u00e9rimental des kernel panics sur les syst\u00e8mes OSX dual processeurs [n\u00e9cessite un red\u00e9marrage].
-SystemTray.menu.pausetransfers=Pause (tous transferts)
-SystemTray.menu.resumetransfers=Reprendre (tous transferts)
-ConfigView.section.file.truncate.too.large=Tronquer les fichiers existant trop gros
-ConfigView.section.file.perf.cache.trace=Conserver les op\u00e9rations de cache pour \u00e9ventuel diagnostic
-ConfigView.section.interface.enabletray=Activer le system tray
-PeerManager.status.error=Erreur
-Stats.title.full=Statistiques
-TransferStatsView.title.full=Transferts
-CacheView.general.size=Taille totale
-CacheView.general.inUse=Utilisation
-CacheView.general.title=Infos Cache
-CacheView.reads.title=Lectures E/S
-CacheView.reads.fromFile=Depuis Fichier
-CacheView.reads.fromCache=Depuis Cache
-CacheView.writes.title=Ecritures E/S
-CacheView.writes.toCache=Vers Cache
-CacheView.writes.toFile=Vers Fichier
-CacheView.writes.hits=d'\u00e9conomis\u00e9
-CacheView.speeds.title=Taux de donn\u00e9es
-CacheView.speeds.reads=Lectures
-CacheView.speeds.writes=Ecritures
-CacheView.speeds.fromCache=Depuis/Vers Cache
-CacheView.speeds.fromFile=Depuis/Vers Fichier
-CacheView.reads.amount=Quantit\u00e9
-CacheView.reads.avgsize=Taille Moy.
-openUrl.referrer=URL de la page r\u00e9f\u00e9r\u00e9e :
-openUrl.referrer.info=Uniquement pour les sites qui l'exige
-ConfigView.label.maxuploadspeedseeding=Taux diff\u00e9rent quand seulement en source
-ConfigView.label.transfer.ignorepeerports=Ignorer les clients utilisant ces ports (s\u00e9par\u00e9s par ';' e.g. 0;25;100-200)
-ConfigView.section.proxy.enable_socks.peer=Activer le proxy pour les communications entre clients (pour les connexions sortantes uniquement).
-ConfigView.section.proxy.peer.informtracker=Informer le tracker de la limitation.
-ConfigView.section.proxy.socks.version=Version SOCKS
-PiecesView.legend.written=Ecrites
-PiecesView.legend.requested=D\u00e9mand\u00e9es
-PiecesView.legend.downloaded=T\u00e9l\u00e9charg\u00e9e, \u00e9criture en attente
-PiecesView.legend.incache=Donn\u00e9es dans le cache
-PiecesView.typeItem.0=Lent
-PiecesView.typeItem.1=Rapide
-Security.jar.tools_not_found=La signature du JAR a \u00e9chou\u00e9e - 'tools.jar' introuvable dans %1. Se reporter \u00e0 Options/s\u00e9curit\u00e9 pour plus d'information.
-Security.jar.signfail=La signature du JAR a \u00e9chou\u00e9e - %1
-ConfigView.section.security.toolsinfo=Les fichiers JAR sign\u00e9s sont utilis\u00e9s par certains plugins, par exemple l'interface Web Swing (si configur\u00e9e pour).\nPour signer des fichiers JAR, il faut avoir acc\u00e8s \u00e0 'tools.jar' qui d\u00e9pend de l'environnement de d\u00e9veloppement Sun JDK (et pas du simple JRE).\nSi seul le JRE est install\u00e9, veuillez installer le JDK.\nVuze doit pouvoir trouver le fichier pour vous. Sinon, vous pouvez pr\u00e9ciser son chemin d'ac [...]
-ConfigView.section.security.toolsdir=R\u00e9pertoire contenant 'tools.jar'
-ConfigView.section.security.choosetoolssavedir=Selectionner le r\u00e9pertoire contenant 'tools.jar'
-ConfigView.section.proxy.peer.same=Utiliser les m\u00eame r\u00e9glages de proxy pour les communications avec le tracker et les clients.
-ConfigView.section.connection.network.max.simultaneous.connect.attempts=Nombre maximum de connexions sortantes simultan\u00e9es
-ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Nombre maximum de connexions sortantes qu'Vuze tente d'\u00e9tablir \u00e0 un instant donn\u00e9.\nNOTE: WindowsXP Service Pack 2 (SP2) impose une limite au syst\u00e8me de 10 essai simultan\u00e9s.\nValeur par d\u00e9faut: 5.
-ConfigView.section.file.perf.cache.size.explain=Le cache est utilis\u00e9 pour r\u00e9duire les lectures depuis / les \u00e9critures vers le disque. A moins d'utiliser l'option java '-XX:MaxDirectMemerySize' pour sp\u00e9cifier la m\u00e9moire disponible pour le cache et les E/S r\u00e9seau, cette valeur doit rester %1 inf\u00e9rieure \u00e0 la taille maximum de m\u00e9moire virtuelle. La taille maximale actuelle de la m\u00e9moire virtuelle est %2. Pour des instructions sur comment modi [...]
-MyTorrentsView.menu.setSpeed.unlimit=Pas de limite
-MyTorrentsView.menu.setSpeed.unlimited=Illimit\u00e9e
-MyTorrentsView.menu.setSpeed.disable=D\u00e9sactiver l'envoi
-MyTorrentsView.menu.setSpeed.disabled=D\u00e9sactiv\u00e9
-MyTorrentsView.menu.setSpeed.in=en
-MyTorrentsView.menu.setSpeed.slots=cr\u00e9neaux de 
-GeneralView.label.maxuploadspeed=Vit. Env. Max.
-GeneralView.label.maxuploadspeed.tooltip=vitesse maximale d'envoi [0 : illimit\u00e9e]
-MyTorrents.items.UpSpeedLimit.disabled=Pas d'envoi
-MyTorrents.items.UpSpeedLimit.unlimited=Illimit\u00e9
-TableColumn.header.maxupspeed=Vit. Envoi Max.
-TableColumn.header.maxupspeed.info=Vit. Envoi Max. par torrent
-ConfigView.section.file.perf.cache.enable.write=Mettre le t\u00e9l\u00e9chargement en cache pour r\u00e9duire les \u00e9critures disque et les lectures disque pour la v\u00e9rification de pi\u00e8ce.
-ConfigView.section.file.perf.cache.enable.read=Ex\u00e9cuter des lectures en avance pour r\u00e9duire les lectures disque quand en source.
-ConfigView.section.tracker.separatepeerids=Utiliser des identit\u00e9s clients diff\u00e9rentes pour les communications de donn\u00e9es et vers le tracker.
-ConfigView.section.tracker.separatepeerids.info=Augmente l'anonymat si en t\u00e9l\u00e9chargement/source anonyme\nen utilisant une connexion vers le tracker non-anonyme.
-ConfigView.section.interface.wavlocation=Chemin d'acc\u00e8s du fichier .wav
-ConfigView.section.interface.wavlocation.info=S\u00e9lectionner un fichier .wav ou laisser vide pour utiliser le son par d\u00e9faut.
-ConfigView.section.tracker.server=Serveur
-ConfigView.section.tracker.client.connecttimeout=Timeout de connexion (secs)
-ConfigView.section.tracker.client.readtimeout=Timeout de lecture (secs)
-MainWindow.menu.tools=&Outils
-FilesView.path=Chemin d'acc\u00e8s
-FilesView.fullpath=Montrer le chemin d'acc\u00e8s complet
-FilesView.remaining=Pi\u00e8ces restantes
-TableColumn.header.trackername=Nom du tracker
-TableColumn.header.trackername.info=Nom du tracker bas\u00e9 sur l'URL d'annonce
-ConfigView.group.override=Options prioritaires
-ConfigView.section.file.perf.cache.notsmallerthan=Ne pas mettre en cache les fichiers inf\u00e9rieurs \u00e0 (en %1)
-PeersView.menu.blockupload=Bloquer l'envoi
-PeersView.menu.kickandban=Exclure et bannir
-PeersView.menu.kickandban.reason=Client banni manuellement
-PeersView.state=Etat
-PeersView.state.info=Etat de la connexion
-PeersView.state.pending=En cours
-PeersView.state.connecting=Se connecte
-PeersView.state.handshake=Attends le handshake
-PeersView.state.established=Etabli
-ConfigView.section.tracker.processinglimits=Limites de traitement
-ConfigView.section.tracker.maxgettime=Temps maximal pour traiter un GET (en s) [0\u00a0: illimit\u00e9]
-ConfigView.section.tracker.maxgettime.info=Utilis\u00e9s pour les annonces et les scrapes
-ConfigView.section.tracker.maxposttimemultiplier=Multiplicateur du temps GET pour traiter les POST [0\u00a0: illimit\u00e9]
-ConfigView.section.tracker.maxposttimemultiplier.info=Utilis\u00e9 pour des formulaires et des envois
-ConfigView.section.tracker.maxthreads=Requ\u00eates simultan\u00e9es maximales
-DownloadManager.error.operationcancancelled=Op\u00e9ration annul\u00e9e
-Torrent.create.progress.cancelled=Op\u00e9ration annul\u00e9e
-sharing.progress.cancel=Annuler
-wizard.maketorrents.autoopen=Ouvrir le torrent en source \u00e0 la fin
-ConfigView.section.sharing.rescanenable=Activer un scan p\u00e9riodique des partages (pour inclure des changements)
-ConfigView.section.sharing.rescanperiod=P\u00e9riode de scan (s)
-ConfigView.section.connection.advanced=Configuration r\u00e9seau avanc\u00e9e
-ConfigView.section.connection.advanced.mtu=Maximum Transmission Unit (MTU) de la ligne
-ConfigView.section.connection.advanced.mtu.tooltip=Taille maximum d'un paquet pouvant \u00eatre transmis en une seule trame sur le r\u00e9seau.\nVuze utilise MTU-40 (MSS) pour optimiser la charge en envoi.\nValeurs recommand\u00e9es:\n 576 - connexions 56k\n1492 - connexions haut-d\u00e9bit PPPoE\n1500 - connexions haut-d\u00e9bit Ethernet, DSL et Cable.
-ConfigView.section.connection.advanced.SO_RCVBUF=Taille de la socket SO_RCVBUF [0: utilise la valeur par d\u00e9faut du syst\u00e8me d'exploitation]
-ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=R\u00e8gle la taille du socket standard SO_RCVBUF (en octets), soit l'\u00e9chelle et la taille de la fen\u00eatre de reception TCP.\nVuze laisse ce champ vide par d\u00e9faut, donc les valeurs par d\u00e9fault du syst\u00e8me d'exploitation sont utilis\u00e9es.\nNOTE: Linux double la valeur indiqu\u00e9e.
-ConfigView.section.connection.advanced.SO_SNDBUF=Taille de la socket SO_SNDBUF [0: utilise la valeur par d\u00e9faut du syst\u00e8me d'exploitation]
-ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=R\u00e8gle la taille du socket standard SO_SNDBUF (en octets), soit la taille de la fen\u00eatre d'envoi TCP.\nVuze laisse ce champ vide par d\u00e9faut, donc les valeurs par d\u00e9fault du syst\u00e8me d'exploitation sont utilis\u00e9es.\nNOTE: Linux double la valeur indiqu\u00e9e.
-TableColumn.header.seed_to_peer_ratio=TauxSources/Clients
-TableColumn.header.seed_to_peer_ratio.info=Taux global sources/clients du groupe
-PeersView.connected_time=Temps connect\u00e9
-PeersView.connected_time.info=Temps total de connexion avec le client
-TableColumn.header.maxdownspeed=Vit. T\u00e9l. max
-TableColumn.header.maxdownspeed.info=Vitesse maximale de t\u00e9l\u00e9chargement par torrent
-PeersGraphicView.title.full=Essaim
-ConfigView.section.tracker.passwordwebhttpsonly=Ne permet que l'acc\u00e8s par HTTPS
-TableColumn.header.torrentpath=Chemin d'acc\u00e8s du torrent
-TableColumn.header.torrentpath.info=Chemin d'acc\u00e8s du torrent sur le disque
-ConfigView.section.sharing.torrentcomment=Commentaire pour les torrents g\u00e9n\u00e9r\u00e9s
-ConfigView.label.copyanddeleteratherthanmove=Copier et ensuite supprimer les donn\u00e9es (au lieu de le faire en une op\u00e9ration) - peut pr\u00e9venir la perte de donn\u00e9es avec certains syst\u00e8mes de fichiers
-ConfigView.label.openstatsonstart=Ouvrir la vue Statistiques au d\u00e9marrage
-swt.install.window.title=Installeur de plugins pour Vuze
-swt.install.window.ok=Installer
-swt.install.window.header=Les composants suivants ont \u00e9t\u00e9 s\u00e9lectionn\u00e9s pour \u00eatre install\u00e9s :
-swt.uninstall.window.title=D\u00e9sintalleur de plugins pour Vuze
-swt.uninstall.window.ok=Supprimer
-swt.uninstall.window.header=Les compossants suivants ont \u00e9t\u00e9 s\u00e9lectionn\u00e9s pour \u00eatre supprim\u00e9s :
-installPluginsWizard.title=Installation de plugins
-installPluginsWizard.mode.title=Veuillez choisir une m\u00e9thode d'installation
-installPluginsWizard.mode.list=Par liste, depuis sourceforge.net
-installPluginsWizard.list.title=Liste des plugins installables
-installPluginsWizard.list.loading=Veuillez patientez pendant le chargement de la liste des plugins.
-installPluginsWizard.list.loaded=Veuillez choisir les plugins \u00e0 installer.
-installPluginsWizard.list.name=Nom
-installPluginsWizard.list.description=Description du plugin
-installPluginsWizard.finish.title=Installation en cours
-installPluginsWizard.finish.explanation=Les plugins s\u00e9lectionn\u00e9s seront install\u00e9s gr\u00e2ce \u00e0 l'Assistant de mise \u00e0 jour.\n\nSoyez patients, la proc\u00e9dure peut prendre quelques minutes.\n\nPour des informations sur la progression, veuillez double-cliquer \u00e0 gauche dans la barre d'\u00e9tat.
-installPluginsWizard.details.loading=Chargement des d\u00e9tails, veuillez patienter...
-installPluginsWizard.mode.file=Par fichier
-installPluginsWizard.installMode.title=Veuillez choisir le type d'installation
-installPluginsWizard.installMode.user=Installe le(s) plugin(s) pour vous uniquement
-installPluginsWizard.installMode.shared=Installe le(s) plugin(s) pour tous les utilisateurs (partag\u00e9)
-installPluginsWizard.file.title=Veuillez choisir le plugin \u00e0 installer
-installPluginsWizard.file.file=Fichier :
-installPluginsWizard.file.invalidfile=Le fichier n'est pas un plugin valide pour Azureus.
-installPluginsWizard.file.browse=Parcourir...
-uninstallPluginsWizard.title=D\u00e9sinstallation de plugins
-uninstallPluginsWizard.list.title=Liste des plugins install\u00e9s
-uninstallPluginsWizard.list.loaded=Veuillez choisir les plugins \u00e0 d\u00e9sintaller.
-installPluginsWizard.list.nullversion=pas de version
-uninstallPluginsWizard.finish.title=D\u00e9sintallation en cours
-uninstallPluginsWizard.finish.explanation=Les plugins s\u00e9lectionn\u00e9s seront supprim\u00e9s gr\u00e2ce \u00e0 l'assistant de mise \u00e0 jour.
-MainWindow.menu.plugins.installPlugins=Assistant d'installation
-MainWindow.menu.plugins.uninstallPlugins=Assistant de d\u00e9sinstallation
-ConfigView.section.ipfilter.totalIPs=%1 IPs bloqu\u00e9es au total, soit %2 d'internet.
-update.instance.install=V\u00e9rification des installations
-update.instance.uninstall=V\u00e9rification des d\u00e9sinstallations
-update.instance.update=V\u00e9rification des mises \u00e0 jour
-MainWindow.status.update.tooltip=Double-cliquer pour voir la progression
-updater.progress.window.title=Travaux d'installation en cours
-updater.progress.window.info=Appuyer sur 'Abandonner' pour mettre fin aux t\u00e2ches en cours.
-Button.abort=Annuler
-ConfigView.section.ipfilter.enablebanning=Bloquer les clients qui envoient constamment de mauvaises donn\u00e9es
-Network.alert.acceptfail=Trop d'\u00e9checs successifs sur le port %1, %2 - essais stopp\u00e9s.\n Veuillez v\u00e9rifier les r\u00e9glages du pare-feu pour que ce port soit capable de recevoir des connexions.
-MyShares.column.category=Cat\u00e9gorie
-UpdateWindow.restartLater=Red\u00e9marrer plus tard
-MainWindow.menu.file.restart=Red\u00e9marrer
-MainWindow.dialog.restartconfirmation.title=Red\u00e9marrer Vuze u00a0?
-MainWindow.dialog.restartconfirmation.text=Voulez-vous vraiment red\u00e9marrer Vuze u00a0?
-ConfigView.label.prioritizemostcompletedfiles=Donner priorit\u00e9 aux fichiers les plus avanc\u00e9s
-splash.plugin.init=Initialisation du Plugin: 
-ConfigView.section.style.osx_small_fonts=Utiliser une petite police [red\u00e9marrage n\u00e9cessaire]
-ConfigView.section.tracker.tcpnonblocking=Utiliser des E/S non bloquantes pour le tracker TCP. Cette option n\u00e9cessite de faire tourner le racker sur un autre port. Exp\u00e9rimental\u00a0!
-ConfigView.section.tracker.nonblocking=Options non bloquantes
-ConfigView.section.tracker.nonblockingconcmax=Nombre max de connexions simultan\u00e9es [0\u00a0: illimit\u00e9es]
-MyTorrentsView.menu.exportmenu=Exporter
-MyTorrentsView.menu.exporttorrent=Exporter le torrent...
-ConfigView.section.tracker.client.scrapeinfo=D\u00e9sactiver le scrape emp\u00eache les r\u00e8gles de classement de torrents de fonctionner car elles se fondent sur les informations de scrape que renvoient les trackers.
-ConfigView.section.tracker.client.scrapeenable=Activer le scrape
-ConfigView.section.tracker.client.scrapestoppedenable=Utiliser le scrape sur les torrents non actifs
-Scrape.status.disabled=Scrape d\u00e9sactiv\u00e9
-MyTorrentsView.menu.explore=Ouvrir le dossier
-MyTorrentsView.menu.explore._mac=Montrer dans le Finder
-MyTorrentsView.menu.explore._windows=Montrer dans l'exploreur
-wizard.maketorrents.autohost=H\u00e9berger le torrent dans le tracker int\u00e9gr\u00e9
-ConfigView.label.overrideip=Forcer l'IP envoy\u00e9e au tracker (NAT)
-ConfigView.label.overrideip.tooltip=Informe le tracker d'une adresse IP diff\u00e9rente de celle depuis laquelle les paquets sortants arrivent. Laisser vide pour ne pas utiliser cette option.
-ConfigView.section.connection.group.networks=R\u00e9seaux
-ConfigView.section.connection.group.networks.info=S\u00e9lectionner les r\u00e9seaux permis par d\u00e9faut pour les transmissions de donn\u00e9es client-client
-ConfigView.section.connection.networks.prompt=Inviter \u00e0 s\u00e9lectionner quand un t\u00e9l\u00e9chargement avec tracker anonyme est ajout\u00e9
-ConfigView.section.connection.networks.Public=R\u00e9seau IP public (pas anonyme)
-ConfigView.section.connection.networks.I2P=R\u00e9seau I2P
-ConfigView.section.connection.networks.Tor=R\u00e9seau Onion Router (Tor)
-TableColumn.header.networks=R\u00e9seaux
-TableColumn.header.networks.info=R\u00e9seaux permis pour les transmissions de donn\u00e9es client-client
-Scrape.status.networkdisabled=R\u00e9seau non activ\u00e9
-ConfigView.section.tracker.server.group.networks=R\u00e9seaux
-ConfigView.section.tracker.server.group.networks.info=S\u00e9lectionner les r\u00e9seaux desquels le tracker accepte les clients
-window.networkselection.title=S\u00e9lection r\u00e9seau
-window.networkselection.info=Le(s) tracker(s) du torrent affich\u00e9 ci-dessous supporte les r\u00e9seaux suivants.\nS\u00e9lectionner ceux \u00e0 utiliser pour les communications avec le tracker et les clients.\nS'il s'agit d'un tracker anonyme supportant les clients publics, activer \u00e0 la fois les r\u00e9seaux anonyme et public.\nActiver le r\u00e9seau public a pour cons\u00e9quence \u00e9vidente de supprimer l'anonymat.
-plugins.basicview.clear=Vider
-ConfigView.section.connection.group.peersources=Origines des clients
-ConfigView.section.connection.group.peersources.info=S\u00e9lectionner les origines permises par d\u00e9faut pour les connexions clients
-ConfigView.section.connection.peersource.Tracker=D'un tracker
-ConfigView.section.connection.peersource.DHT=Tracking d\u00e9centralis\u00e9
-ConfigView.section.connection.peersource.PeerExchange=Fourni par un autre client
-ConfigView.section.connection.peersource.Plugin=Ajout\u00e9 par un plugin
-ConfigView.section.connection.peersource.Incoming=Connexion entrante
-PeersView.source=Origine
-PeersView.source.info=L'origine de ce client
-TableColumn.header.peersources=Origines des clients
-TableColumn.header.peersources.info=Origines des clients permises pour l'\u00e9tablissement de connexions
-wizard.tracker.dht=D\u00e9centralis\u00e9 (clients Vuze uniquement)
-MyTorrentsView.menu.advancedmenu=Avanc\u00e9
-MyTorrentsView.menu.networks=R\u00e9seaux
-MyTorrentsView.menu.peersource=Origines de clients
-ConfigView.section.sharing.permitdht=Permettre le tracking d\u00e9centralis\u00e9 si le tracker est injoignable
-ConfigView.section.sharing.protocol=Protocole pour les ressources partag\u00e9es (configuration du tracker n\u00e9cessaire)
-PeersView.Messaging.info=Supporte une API de messaging avanc\u00e9e.
-ConfigView.label.queue.newseedsmovetop=D\u00e9placer les torrents r\u00e9cemments termin\u00e9s au d\u00e9but de la liste de sources
-ConfigView.label.seeding.firstPriority.ignore.info=Attention. Utiliser ces r\u00e8gles peut faire en sorte qu'un torrent s'arr\u00eate d\u00e8s qu'il est termin\u00e9.
-ConfigView.label.seeding.firstPriority.ignore=Ignorer les r\u00e8gles de premi\u00e8re priorit\u00e9 pour\u00a0:
-ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents avec un taux sources/clients >
-ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents avec 0 clients
-ConfigView.section.tracker.sendjavaversionandos=Envoyer la version de java et le nom du syst\u00e8me d'exploitation
-MagnetPlugin.contextmenu.exporturi=Copier l'URI Magnet dans le presse-papier
-ConfigView.section.plugins.dht=BdD distribu\u00e9e
-dht.info=Ce plugin supporte le tracking d\u00e9centralis\u00e9, entre autres - le d\u00e9sactiver r\u00e9duit votre habilit\u00e9 \u00e0 t\u00e9l\u00e9charger
-dht.enabled=Activer la base de donn\u00e9es distribu\u00e9e
-dht.portdefault=Utiliser le port par d\u00e9faut
-dht.port=Port UDP pour la base de donn\u00e9es
-dht.execute.command=Commande de diagnostic
-dht.execute.info=Appuyer pour ex\u00e9cuter la commande
-dht.execute=Ex\u00e9cuter
-dht.logging=Activer le tra\u00e7age de l'activit\u00e9
-ConfigView.section.plugins.dhttracker=Tracker distribu\u00e9
-dhttracker.tracknormalwhenoffline=Ne tracker les torrents normaux que lorsque leur tracker est injoignable
-ConfigView.section.file.nativedelete._mac=Utiliser la corbeille en supprimant des fichiers
-ConfigView.section.file.nativedelete._windows=Placer les fichiers effac\u00e9s dans la corbeille
-ConfigView.section.logging.generatediagnostics=G\u00e9n\u00e9rer
-ConfigView.section.logging.generatediagnostics.info=G\u00e9n\u00e8re des informations de diagnostic et les copie dans le presse-papier et le fichier de log, si activ\u00e9
-ConfigView.section.sharing.privatetorrent=Torrents priv\u00e9s - n'accepter que les clients du tracker
-MainWindow.menu.tools.nattest=Test &NAT / Firewall
-Button.apply=Appliquer
-Button.close=Fermer
-window.welcome.title=Bienvenue dans Vuze %1
-#file can be a URL or a path in the jar
-MainWindow.menu.help.releasenotes=Notes
-dht.reseed.label=Normally reseeding of the Distributed Database is not necessary. However, if the number of contacts is low this can be used for re-integratation.\nLeave blank to bootrap off connected peers or enter IP and port to explicitly bootstrap from a known peer.
-dht.reseed.group=Reseeder
-dht.reseed.ip=Adresse IP
-dht.reseed=Reseeder
-dht.reseed.info=Reseeder la base de donnees
-DHTView.title.full=Base de donn\u00e9es distribu\u00e9e
-DHTView.title.fullcvs=Base de donn\u00e9es distribu\u00e9e CVS
-DHTView.general.title=G\u00e9n\u00e9ral
-DHTView.general.uptime=En service\u00a0: 
-DHTView.general.users=Utilisateurs\u00a0: 
-DHTView.general.nodes=Noeuds\u00a0: 
-DHTView.general.leaves=Sorties\u00a0: 
-DHTView.general.contacts=Contacts\u00a0: 
-DHTView.general.replacements=Remplacements\u00a0: 
-DHTView.general.live=En vie\u00a0: 
-DHTView.general.unknown=Inconnu\u00a0: 
-DHTView.general.dying=Expirant\u00a0: 
-DHTView.transport.title=D\u00e9tails de transport
-DHTView.transport.packets=Paquets
-DHTView.transport.bytes=Octets
-DHTView.transport.received=Re\u00e7u
-DHTView.transport.sent=Envoy\u00e9
-DHTView.transport.in=Entrant\u00a0: 
-DHTView.transport.out=Sortant\u00a0: 
-DHTView.operations.title=D\u00e9tails d'op\u00e9ration
-DHTView.operations.sent=Envoy\u00e9
-DHTView.operations.failed=Echec
-DHTView.operations.received=Re\u00e7u
-DHTView.operations.findNode=Noeuds trouv\u00e9s
-DHTView.operations.findValue=Valeurs trouv\u00e9es
-DHTView.operations.store=Enregistrements
-DHTView.activity.title=Activit\u00e9
-DHTView.activity.status=Etat
-DHTView.activity.status.true=En attente
-DHTView.activity.status.false=Lanc\u00e9
-DHTView.activity.type.1=Get Interne
-DHTView.activity.type.2=Get Externe
-DHTView.activity.type.3=Put Interne
-DHTView.activity.type.4=Put Externe
-DHTView.activity.target=Cible
-DHTView.activity.details=D\u00e9tails
-DHTView.db.title=Base de donn\u00e9es
-DHTView.db.keys=Cl\u00e9s
-DHTView.db.values=Valeurs
-DHTView.db.divfreq=Div. Freq.
-DHTView.db.divsize=Div. Taille.
-MainWindow.dht.status.tooltip=Lorsque la base de donn\u00e9e est lanc\u00e9e, nombre estim\u00e9 d'utilisateurs connect\u00e9s (ie ayant lanc\u00e9 la base de donn\u00e9es \u00e9galement)
-MainWindow.dht.status.disabled=D\u00e9sactiv\u00e9
-MainWindow.dht.status.failed=Echec
-MainWindow.dht.status.initializing=Initialisation
-MainWindow.dht.status.users=%1 Utilisateurs
-MainWindow.dht.status.unreachable=DHT derri\u00e8re un pare-feu
-MainWindow.dht.status.unreachabletooltip=Il semble qu'il y ait un probl\u00e8me avec le mapping du port de la base de donn\u00e9es distribu\u00e9e
-MyTorrentsView.menu.setUpSpeed=Vit. d'envoi
-MyTorrentsView.menu.setDownSpeed=Vit. de t\u00e9l.
-ConfigView.section.tracker.client.showwarnings=Afficher les avertissements des trackers
-dht.advanced=Activer les r\u00e9glages avanc\u00e9s
-dht.advanced.group=R\u00e9glages avanc\u00e9s
-dht.advanced.label=Ne pas modifier ces valeurs sans savoir pourquoi
-dht.override.ip=Forcer l'IP externe
-ConfigView.section.logging.loggerenable=Activer la journalisation
-ConfigView.section.ipfilter.blockbanning=Bannit un bloc de 256 adresses si le nombre d'IP bannies dans ce bloc est sup\u00e9rieur \u00e0
-MyTrackerView.passive=Passif
-TableColumn.header.swarm_average_speed=Vit. moy. essaim
-TableColumn.header.swarm_average_speed.info=La vitesse moyenne des peers de l'essaim
-MyTrackerView.category=Cat\u00e9gorie
-MainWindow.menu.file.open.torrentfortracking=Fichier Torrent... (Tracking Uniquement)
-MyTrackerView.date_added=Ajout\u00e9
-ConfigView.section.tracker.portbackup=Ports de r\u00e9serve (s\u00e9par\u00e9s par ';')
-ConfigView.label.playfilespeech=Parler \u00e0 la fin du t\u00e9l\u00e9chargement d'un fichier
-ConfigView.label.playfilefinished=Jouer un son \u00e0 la fin du t\u00e9l\u00e9chargement d'un fichier
-ConfigView.label.backupconfigfiles=Sauvegarder les fichiers de configuration (pour r\u00e9cup\u00e9ration \u00e9ventuelle)
-ConfigView.section.tracker.client.scrapesingleonly=D\u00e9sactiver l'agr\u00e9gation de scrape par tracker (peut \u00e9viter les erreurs du type 'URL too long' (414))
-dht.ipfilter.log=Logger les violations des filtres IP
-ConfigView.label.seeding.addForSeedingDLCopyCount=Consid\u00e9rer les torrents ajout\u00e9s "en source" comme ayant t\u00e9l\u00e9charg\u00e9 ce nombre de copies\u00a0:
-ActivityView.legend.limit=Taux limite
-ActivityView.legend.achieved=Taux atteint
-ActivityView.legend.peeraverage=Moyenne
-ActivityView.legend.swarmaverage=Moyenne Essaim
-ActivityView.legend.trimmed=Tronqu\u00e9 (pointill\u00e9)
-MyTorrentsView.menu.movemenu=D\u00e9placer les fichiers
-MyTorrentsView.menu.movedata=D\u00e9placer les donn\u00e9es...
-MyTorrentsView.menu.movetorrent=D\u00e9placer le torrent...
-MyTorrentsView.menu.movedata.dialog=Choisir la destination
-DHTView.operations.data=Donn\u00e9es
-DHTView.general.reachable=Accessible\u00a0: 
-DHTView.general.rendezvous=Rendez-vous\u00a0: 
-ConfigView.label.queue.maxactivetorrentswhenseeding=Max quand uniquement en source [0\u00a0:illimit\u00e9]
-Views.plugins.IRC.title=IRC - Support Technique en Ligne
-Formats.units.TiB=Tio
-Formats.units.TB=To
-Formats.units.GiB=Gio
-Formats.units.GB=Go
-Formats.units.MiB=Mio
-Formats.units.MB=Mo
-Formats.units.KiB=Kio
-Formats.units.kB=ko
-Formats.units.KB=ko
-Formats.units.B=o
-Formats.units.alot=Beaucoup\u00a0!!!
-ConfigView.section.ipfilter.persistblocking=Sauver les d\u00e9tails des IP bloqu\u00e9es entre sessions
-FilesView.menu.rename=Renommer ou changer de cible
-FilesView.rename.choose.path=Choisir un fichier nouveau ou existant
-FilesView.rename.confirm.delete.title=Confirmer la suppression
-FilesView.rename.confirm.delete.text=Confirmer la suppression du fichier original %1
-ConfigView.higher.mode.available=\t
-ConfigView.section.mode.title=Niveau utilisateur
-ConfigView.section.mode.beginner=D\u00e9butant
-ConfigView.section.mode.beginner.wiki.definitions=Vocabulaire BitTorrent
-ConfigView.section.mode.intermediate=Interm\u00e9diaire
-ConfigView.section.mode.intermediate.wiki.host=H\u00e9berger des fichiers
-ConfigView.section.mode.intermediate.wiki.publish=Publier des fichiers
-ConfigView.section.mode.advanced=Avanc\u00e9
-ConfigView.section.mode.advanced.wiki.main=Page Principale du Wiki
-ConfigView.section.mode.beginner.text=Tout ce dont vous avez besoin pour t\u00e9l\u00e9charger des torrents.\nUtilisez ce mode pour simplement g\u00e9rer vos torrents.
-ConfigView.section.mode.intermediate.text=Donne acc\u00e8s aux fonctions du tracker interne.\nUtilisez ce mode pour cr\u00e9er votre propre tracker et publier/h\u00e9berger vos fichiers.
-ConfigView.section.mode.advanced.text=Donne acc\u00e8s aux r\u00e9glages r\u00e9seau.\nUtilisez ce mode si vous savez ce que sont MTU ou I/O non bloquants...
-Files.column.storagetype=Type de stockage
-FileItem.storage.linear=Lin\u00e9aire
-MessageBoxWindow.rememberdecision=Se souvenir de ma d\u00e9cision
-ConfigView.section.interface.cleardecisions=Vider les "d\u00e9cisions retenues"
-ConfigView.section.interface.cleardecisionsbutton=Vider
-configureWizard.welcome.usermodes=Ce r\u00e9glage du niveau utilisateur d\u00e9termine le niveau des options accessibles dans Outils > Options. Il est recommand\u00e9 de choisir avec sagesse.
-FilesView.skip.confirm.delete.text=Tronquer le fichier \u00ab\u00a0%1\u00a0\u00bb pour sauver de l'espace\u00a0?
-FilesView.rename.failed.title=Echec du renommage/reciblage
-FilesView.rename.failed.text=L'op\u00e9ration a \u00e9chou\u00e9e, probablement \u00e0 cause d'une mauvaise destination
-diagnostics.log_found=Vuze ne s'est pas ferm\u00e9 correctement. Regarder dans %1 pour des fichiers log de diagnostic et envoyer \u00e0 l'\u00e9quipe de Vuze si c'est le r\u00e9sultat d'une erreur de l'application. Penser \u00e0 chercher 'Vuze Disappears' dans le Wiki (voir le menu Aide).
-ManagerItem.paused=En Pause
-Utils.link.visit=Merci de visiter
-ConfigView.section.connection.serverport.wiki=Bon choix de ports
-ConfigView.section.transfer.speeds.wiki=Bons r\u00e9glages de vitesse
-installPluginsWizard.installMode.info.text=Les plugins ne sont pas n\u00e9cessaires pour qu'Vuze fonctionne correctement, ils apportent des fonctions suppl\u00e9mentaires, pour le plaisir, l'automatisation ou le contr\u00f4le \u00e0 distance.\nVeuillez lire attentivement la description du plugin avant de d\u00e9cider de l'installer.\nLa plupart des plugins peuvent \u00eatre test\u00e9s sans risques mais ne surchargez pas inutilement votre configuration avec des plugins que vous n'utilise [...]
-Views.plugins.Distributed.DB.title=BdD distribu\u00e9e
-Views.plugins.Distributed.Tracker.title=Tracker distribu\u00e9
-Views.plugins.Plugin.Update.title=Mise \u00e0 jour Plugins
-openUrl.url.info=Supporte http, https, magnet et l'infohash brut en hexa
-TableColumn.header.swarm_average_completion=Compl\u00e9tion moyenne des clients
-TableColumn.header.swarm_average_completion.info=Pourcentage moyen de compl\u00e9tion des clients connect\u00e9s
-GeneralView.label.swarm_average_completion=Compl\u00e9tion moyenne:
-GeneralView.label.swarm_average_completion.tooltip=Pourcentage moyen de compl\u00e9tion des clients connect\u00e9s
-MainWindow.nat.status.tooltip.unknown=Etat inconnu (TCP) [pare-feu/NAT]
-MainWindow.nat.status.tooltip.ok=Accessibilit\u00e9 OK (TCP)
-MainWindow.nat.status.probok=NAT OK\u00a0?
-MainWindow.nat.status.tooltip.probok=Accessibilit\u00e9 OK, mais pas de connections entrantes (TCP) r\u00e9centes
-MainWindow.nat.status.bad=Bloqu\u00e9 par pare-feu
-MainWindow.nat.status.tooltip.bad=Probl\u00e8me NAT (TCP) possible, voir le Wiki si persistant (double-cliquer)
-plugin.installer.recommended.plugin=Plugin recommand\u00e9 - voir le descriptif
-LoggerView.pause=Mettre en pause
-LoggerView.filter=Filtrer
-LoggerView.filter.uncheckAll=D\u00e9s\u00e9lectionner toutes les cat\u00e9gories
-LoggerView.filter.checkAll=S\u00e9lectionner toutes les cat\u00e9gories
-LoggerView.loggingDisabled=La journalisation n'est pas activ\u00e9e
-ConfigView.section.logging.filter=Filtres
-ConfigView.pluginlist.column.loadAtStartup=Se charge au d\u00e9marrage
-ConfigView.pluginlist.column.type.perUser=Per Utilisateur
-ConfigView.pluginlist.column.type.shared=Partag\u00e9
-ConfigView.pluginlist.column.type.builtIn=Embarqu\u00e9
-ConfigView.pluginlist.column.name=Nom
-ConfigView.pluginlist.column.directory=R\u00e9pertoire
-ConfigView.pluginlist.column.isOperational=Op\u00e9rationel\u00a0?
-PeersView.BlockView.Avail.Have=Les 2 ont
-PeersView.BlockView.Avail.NoHave=Le client a; Pas vous
-PeersView.BlockView.NoAvail.Have=Vous avez; pas le client
-PeersView.BlockView.NoAvail.NoHave=Les 2 n'ont pas
-PeersView.BlockView.Transfer=En transfert
-PeersView.BlockView.NextRequest=Prochaine requ\u00eate
-PeersView.BlockView.title=D\u00e9tails de pi\u00e8ces
-PeersView.BlockView.AvailCount=Disponibilit\u00e9
-MyTorrentsView.dialog.NumberError.title=Nombre non valide ou non reconnu
-MyTorrentsView.dialog.NumberError.text=Le nombre entr\u00e9 n'est pas valide ou pas reconnu
-MyTorrentsView.menu.manual=&Manuellement...
-MyTorrentsView.dialog.setSpeed.title=R\u00e9gler la vitesse de %1
-# %1 = "in kbps" or ""; %2 = "upload" or "download"
-MyTorrentsView.dialog.setNumber.text=Entrer un nombre %1 pour changer %2 vers:
-MyTorrentsView.dialog.setNumber.inKbps=en kbit/s
-OpenTorrentWindow.torrentLocation=fichier(s) torrent:
-OpenTorrentWindow.addFiles.URL=Ajouter &URL
-OpenTorrentWindow.addFiles.Folder=Ajouter &r\u00e9pertoire
-OpenTorrentWindow.addFiles.Clipboard=Ajouter du &presse-papier
-OpenTorrentWindow.changeDestination=Changer l'emplacement de sauvegarde
-OpenTorrentWindow.fileList=Fichiers dans les torrents:
-OpenTorrentWindow.torrentTable.name=Nom
-OpenTorrentWindow.torrentTable.saveLocation=Emplacement de sauvegarde
-OpenTorrentWindow.fileTable.fileName=Fichier
-OpenTorrentWindow.fileTable.size=Taille
-OpenTorrentWindow.fileTable.destinationName=Rep.
-OpenTorrentWindow.startMode.seeding=En source
-OpenTorrentWindow.fileList.changeDestination=Changer l'emplacement de sauvegarde
-OpenTorrentWindow.mb.badSize.title=Fichier incompatible
-OpenTorrentWindow.mb.badSize.text='%1' n'est pas '%2' et ne peut pas \u00eatre utilis\u00e9 pour seeder
-OpenTorrentWindow.mb.alreadyExists.text=Le <A HREF="%1">%3</A> a d\u00e9j\u00e0 \u00e9t\u00e9 ajout\u00e9 en tant que '%2'
-OpenTorrentWindow.mb.alreadyExists.title=Le torrent existe d\u00e9j\u00e0
-OpenTorrentWindow.mb.openError.title=Erreur d'ouverture
-OpenTorrentWindow.mb.openError.text='%1' n'a pas pu \u00eatre ouvert:
-OpenTorrentWindow.torrent.remove=Enlever le torrent de la liste
-OpenTorrentWindow.torrent.options=Les param\u00e8tres suivants seront appliqu\u00e9s aux torrents s\u00e9lectionn\u00e9s ci-dessus
-OpenTorrentWindow.xOfTotal=(%1 sur %2)
-iconBar.open.tooltip=Ouvrir Torrent(s)
-LocaleUtil.column.text=Texte inconnu
-Tracker.tooltip.MultiSupport=Ce tracker supporte plusieurs hash par requ\u00eate.
-Tracker.tooltip.NoMultiSupport=Ce tracker ne supporte pas plusieurs hash par requ\u00eate.
-ConfigView.label.lazybitfield=Utiliser le bitfield "paresseux" (aide \u00e0 seeder sur les r\u00e9seaux bloquant par d\u00e9tection de bitfield)
-LoggerView.realtime=Mettre \u00e0 jour en temps r\u00e9el
-ConfigView.section.file.perf.cache.flushpieces=Ecrit les pi\u00e8ces compl\u00e8tes imm\u00e9diatement sur le disque. Cela rend l'acc\u00e8s disque plus fluide mais engendre plus d'op\u00e9rations d'\u00e9criture.
-ConfigView.section.file.writemblimit=Nombre maximum de requ\u00eates d'\u00e9criture mises en file d'attente (en %1)
-ConfigView.section.file.writemblimit.explain=Lorsque la vitesse d'\u00e9criture sur le disque est inf\u00e9rieure \u00e0 la vitesse de t\u00e9l\u00e9chargement, ce param\u00e8tre limite la quantit\u00e9 de donn\u00e9es mise en attente avant une limitation de la vitesse de t\u00e9l\u00e9chargement.
-ConfigView.section.file.readmblimit=Nombre maximum de requ\u00eates de lecture mises en file d'attente (en %1)
-ConfigView.section.file.readmblimit.explain=Ce param\u00e8tre limite la m\u00e9moire allou\u00e9e aux lectures en cours.
-Button.moveUp=D\u00e9placer vers le haut
-Button.moveDown=D\u00e9placer vers le bas
-ConfigView.notAvailableForMode=Cette section s'adresse au mode %1 ou plus. Elle n'est pas disponible en mode %2.
-health.explain.error=Ce torrent a produit une erreur. Voir la colonne "Etat", ou l'indication sur l'icone de l'erreur.
-PeersView.piece.info=Num\u00e9ro de la derni\u00e8re pi\u00e8ce demand\u00e9e \u00e0 ce client
-PiecesView.priority=Priorit\u00e9
-PiecesView.priority.info=la priorit\u00e9 affect\u00e9e \u00e0 cette pi\u00e8ce (pas tr\u00e8s fiable)
-PiecesView.speed=Vitesse
-PiecesView.speed.info=Les clients lents n'interf\u00e8rent pas avec les pi\u00e8ces rapides
-TableColumn.header.AvgAvail.info=Somme des disponibilit\u00e9s des pi\u00e8ces divis\u00e9e par le nombre de pi\u00e8ces, divis\u00e9e par le nombre de connections
-TableColumn.header.AvgAvail=Dispo. moy./pi\u00e8ce
-ConfigView.label.strictfilelocking=Forcer le verrouillage exclusif de l'acc\u00e8s en \u00e9criture \u00e0 un fichier sur tous les torrents
-MyTorrentsView.menu.rescanfile=Rev\u00e9rifier p\u00e9riodiquement les pi\u00e8ces incompl\u00e8tes
-Plugin.localtracker.name=D\u00e9tecteur de clients sur LAN
-Plugin.localtracker.info=Le d\u00e9tecteur de clients sur LAN permet \u00e0 plusieurs Vuze derri\u00e8re un pare-feu ou sur un m\u00eame r\u00e9seau local\nde t\u00e9l\u00e9charger efficacement un m\u00eame torrent en \u00e9tablissant des connections directes entre eux.
-Plugin.localtracker.enable=Activer la d\u00e9tection des clients sur le LAN
-azinstancehandler.alert.portclash=Conflit de port sur LAN\u00a0: %1 est d\u00e9j\u00e0 utilis\u00e9 par un autre utilisateur, veuillez s\u00e9lectionner un (deux) port(s) au hasard pour l'\u00e9coute TCP/UDP [entre %2 et %3]
-ConfigView.section.transfer.lan.tooltip=R\u00e9glages sp\u00e9cifiques LAN
-ConfigView.section.transfer.lan.uploadrate=ko/s LAN vitesse maximale d'envoi [0\u00a0: illimit\u00e9e]
-ConfigView.section.transfer.lan.uploadrate.tooltip=Limite d'envoi propre aux clients sur un m\u00eame r\u00e9seau local
-ConfigView.section.transfer.lan.downloadrate=ko/s LAN vitesse maximale de t\u00e9l\u00e9chargement [0\u00a0: illimit\u00e9e]
-ConfigView.section.transfer.lan.downloadrate.tooltip=Limite de t\u00e9l\u00e9chargement propre aux clients sur un m\u00eame r\u00e9seau local
-TorrentOptionsView.param.max.peers=Nombre maximum de connections [0: illimit\u00e9]
-ConfigView.section.connection.encryption.require_encrypted_transport=Exiger un flux encrypt\u00e9
-ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Force l'utilisation de connections encrypt\u00e9es avec les autres clients
-ConfigView.section.connection.encryption.min_encryption_level=Niveau d'encryption minimum
-ConfigView.section.connection.encryption.min_encryption_level.tooltip=Simple - handshake seulement\nRC4 - tout le flux\nUne encryption plus forte requiert plus de CPU.
-Peers.column.Encryption.info=Niveau d'encryption utilis\u00e9
-ConfigView.section.connection.encryption.encrypt.info=Si l'encryption est activ\u00e9e, vous ne pourrez pas vous connecter aux clients incompatibles (sauf \u00e0 activer des options de repli)
-ConfigView.section.connection.encryption.encrypt.info.link=Voir ici pour plus de pr\u00e9cisions
-MainWindow.sr.status.tooltip.ok=Taux de partage %1 OK
-MainWindow.sr.status.tooltip.poor=Taux de partage %1 insuffisant: < 0.9
-MainWindow.sr.status.tooltip.bad=Taux de partage %1 mauvais: < 0.5
-ConfigView.section.style.status=Zone d'\u00e9tat\u00a0: 
-ConfigView.section.style.status.show_sr=Tx Partage
-ConfigView.section.style.status.show_nat=\u00e9tat NAT
-ConfigView.section.style.status.show_ddb=\u00e9tat DDB
-ConfigView.section.connection.encryption.encrypt.group=Transfert encrypt\u00e9/obfusqu\u00e9
-ConfigView.section.connection.encryption.encrypt.fallback_info=Activer les options de repli va permettre des connections aux clients non compatibles mais elles seront non encrypt\u00e9es
-ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Permettre les connections sortantes non encrypt\u00e9es si un essai de connection encrypt\u00e9e \u00e9choue
-ConfigView.section.connection.encryption.encrypt.fallback_incoming=Permettre les connections entrantes non encrypt\u00e9es
-ConfigView.section.connection.encryption=Encryption
-upnp.selectedinterfaces=Interfaces s\u00e9lectionn\u00e9es (s\u00e9par\u00e9es par ';' [ex: eth0;eth1]) [vide: toutes]
-ConfigView.section.style.defaultSortOrder=Sens de classement par d\u00e9faut
-ConfigView.section.style.defaultSortOrder.desc=D\u00e9croissant
-ConfigView.section.style.defaultSortOrder.asc=Croissant
-ConfigView.section.style.defaultSortOrder.flip=Inverse du classement pr\u00e9c\u00e9dent
-LoggerView.autoscroll=D\u00e9filement automatique
-Button.selectAll=Tout s\u00e9lectionner
-Button.markSelected=Marquer les s\u00e9lections
-Button.unmarkSelected=D\u00e9marquer les s\u00e9lections
-TorrentOptionsView.param.max.uploads=Nombre maximum d'uploads [minimum: 2]
-MyTorrentsView.dialog.setPosition.title=R\u00e9gler la position
-MyTorrentsView.dialog.setPosition.text=Entrer la position \u00e0 laquelle mettre les torrents s\u00e9lectionn\u00e9s:
-MyTorrentsView.menu.reposition.manual=Repositionner..
-ConfigView.section.connection.advanced.info.link=Voir ici pour plus de pr\u00e9cisions
-ConfigView.section.connection.advanced.bind_port=Lier au port local [0: d\u00e9sactiv\u00e9]
-ConfigView.section.connection.advanced.bind_port.tooltip=Les connections sortantes seront li\u00e9es localement \u00e0 ce port.\nPeut aider avec certaines instabilit\u00e9es NAT des routeurs.
-Pieces.column.Requested=Demand\u00e9
-Pieces.column.Requested.info=Montre si d'autres requ\u00eates peuvent \u00eatre faites sur cette pi\u00e8ce ou pas (*)
-ConfigView.label.maxuploadsseeding=quand en source seulement
-MyTorrentsView.filter=Filtre:
-popup.error.hideall=Tout cacher
-MyTorrentsView.menu.filter=Filtre...
-ConfigView.section.file.resume.recheck.all=Lors d'un red\u00e9marrage apr\u00e8s crash, v\u00e9rifier tout le fichier (sinon seules les pi\u00e8ces actives avant le crash seront v\u00e9rifi\u00e9es)
-ConfigureWizard.language.choose=Choisir une langue dans la liste suivante:
-popup.closing.in=Fermeture automatique de la fen\u00eatre dans %1 seconde(s)
-popup.more.waiting=%1 message(s) restant(s)...
-# > 2402
-popup.download.finished="%1" est termin\u00e9.
-popup.file.finished="%1" est termin\u00e9.
-DownloadManager.error.badsize=Taille incorrecte
-authenticator.savepassword=Retenir mon mot de passe
-Content.alert.notuploaded.text=Le partage  de "% 1" n'est pas termin\u00e9. Si vous avez 2% aujourd'hui, les gens ne seront pas en mesure de t\u00e9l\u00e9charger compl\u00e8tement vos fichiers publi\u00e9s. \n\nVoulez-vous vraiment 2%? 
-Content.alert.notuploaded.multi.text=\t
-Content.alert.notuploaded.stop=arr\u00eater
-Content.alert.notuploaded.quit=Quitter Vuze
-ConfigView.label.popup.show=Voir tous les popups d'alerte enregistr\u00e9s \u00e0 ce jour (le cas \u00e9ch\u00e9ant)
-ConfigView.label.popup.show.button=Montrer
-ConfigView.label.please.visit.here=Pour plus de d\u00e9tails, vous pouvez aller voir ici
-ConfigView.label.openmytorrents=Ouvrir 'Mes Torrents' au d\u00e9marrage
-ConfigView.label.open_transfer_bar_on_start=Ouvrir la Barre de Transfert au d\u00e9marrage
-ConfigView.label.pause.downloads.on.exit=Mettre les t\u00e9l\u00e9chargements en pause \u00e0 la sortie
-ConfigView.label.resume.downloads.on.start=Reprendre des t\u00e9l\u00e9chargements en pause au d\u00e9marrage apr\u00e8s l'initialisation compl\u00e8te 
-ConfigView.label.mindownloads=Nombre minimum de t\u00e9l\u00e9chargements simultan\u00e9s
-ConfigView.label.popupdownloadadded=Montrer une alerte 'popup' quand un t\u00e9l\u00e9chargement est ajout\u00e9
-popup.download.added="%1" a \u00e9t\u00e9 ajout\u00e9 \u00e0 votre liste de t\u00e9l\u00e9chargement.
-alert.raised.at.close=(Message de la pr\u00e9c\u00e9dente fermeture de Vuze)
-speedtest.wizard.title=Test de d\u00e9bit
-speedtest.wizard.run=D\u00e9marrer un test de d\u00e9bit
-speedtest.wizard.test.mode.updown=partage et t\u00e9l\u00e9chargement
-speedtest.wizard.test.mode.up=partage
-speedtest.wizard.test.mode.down=t\u00e9l\u00e9chargement
-ConfigView.interface.start.advanced=D\u00e9marrer en vue avanc\u00e9e (AZ 2.x)
-MyTorrents.column.ColumnQuality=Qualit\u00e9
-MyTorrents.column.ColumnSpeed=Vitesse
-MyTorrents.column.ColumnProgressETA.2ndLine=Reste: %1
-TableColumn.header.Quality=Qualit\u00e9
-TableColumn.header.Speed=Vitesse
-TableColumn.header.RateIt=Noter
-TableColumn.header.Rating=Note
-TableColumn.header.SpeedGraphic=Vitesse
-TableColumn.header.AzProduct=De
-TableColumn.header.ProgressETA=Avancement
-v3.MainWindow.tab.home=Accueil
-v3.MainWindow.tab.browse=Sur Vuze
-v3.MainWindow.tab.library=Biblioth\u00e8que
-v3.MainWindow.tab.publish=Publier
-v3.MainWindow.tab.advanced=Avanc\u00e9
-v3.MainWindow.menu.home=&Accueil
-v3.MainWindow.menu.browse=&Naviguer
-v3.MainWindow.menu.library=$Biblioth\u00e8que
-v3.MainWindow.menu.publish=&Publier
-v3.MainWindow.menu.advanced=A&vanc\u00e9
-v3.MainWindow.menu.view.searchbar=Barre de Recherche
-v3.MainWindow.currentDL=T\u00e9l\u00e9chargements en cours
-v3.MainWindow.button.stream=Jouer
-v3.MainWindow.button.stop=Arr\u00eater
-v3.MainWindow.button.start=D\u00e9marrer
-v3.MainWindow.button.resume=Reprendre
-v3.MainWindow.button.delete=Supprimer
-v3.MainWindow.button.comment=Commenter
-v3.MainWindow.button.viewdetails=D\u00e9tails
-v3.MainWindow.button.play=Ouvrir
-v3.MainWindow.button.cancel=Annuler
-v3.MainWindow.button.preview=Pr\u00e9visualiser
-v3.MainWindow.view.wait=En cours d'initialisation. Veuillez patienter
-v3.MainWindow.xofx=%1 sur %2
-v3.MainWindow.Loading=Chargement en cours.. Merci de bien vouloir patienter
-v3.filter-bar=Filtrer sur le Titre :
-v3.MainWindow.search.defaultText=Rechercher des Fichiers torrents
-v3.mb.delPublished.delete=&Supprimer
-v3.mb.delPublished.cancel=&Annuler
-v3.mb.deletePurchased.button.delete=&Supprimer
-v3.mb.deletePurchased.button.cancel=&Annuler
-# Used for peers which we can't determine.
-PeerSocket.unknown=Inconnu
-Content.alert.notuploaded.button.stop=&Arr\u00eater
-Content.alert.notuploaded.button.continue=&Continuer \u00e0 partager
-Content.alert.notuploaded.button.abort=&Ne pas quitter
-Alert.failed.update=L'installation du dernier composant a \u00e9chou\u00e9. Allez voir: <A HREF="{Alert.failed.update.url}">AzureusWiki: Failed Update</A> [%1] 
-ConfigView.label.minannounce=Temps minimum entre les annonces du tracker en secondes
-ConfigView.label.maxnumwant=Limite le nombre de pairs que le tracker peut envoyer
-ConfigView.label.announceport=Passer outre au port d'annonce du tracker
-ConfigView.label.maxseedspertorrent=Nombre maximum de seed par torrent, par d\u00e9faut: [0: illimit\u00e9]
-Progress.reporting.status.canceled=Annul\u00e9
-Progress.reporting.status.finished=Termin\u00e9
-Progress.reporting.status.retrying=R\u00e9essayer...
-Progress.reporting.action.label.retry.tooltip=R\u00e9essayer cette op\u00e9ration
-Progress.reporting.action.label.cancel.tooltip=Annuler l'op\u00e9ration
-Progress.reporting.action.label.detail=D\u00e9tails
-Progress.reporting.default.error=Erreur
-v3.MainWindow.text.log.in=Se Connecter
-v3.MainWindow.text.log.out=Se D\u00e9connecter
-v3.MainWindow.text.get.started=S'Enregistrer
-v3.MainWindow.text.my.account=Mon Compte
-v3.MainWindow.text.my.profile=Mon Profil
-v3.MainWindow.tab.minilibrary=T\u00e9l\u00e9chargements
-v3.MainWindow.tab.events=Activit\u00e9s
-v3.activity.remove.title=Supprimer l'entr\u00e9e d'activit\u00e9
-v3.activity.remove.text=Etes vous s\u00fbr de vouloir supprimer l'entr\u00e9e d'activit\u00e9 '%1' ?
-v3.MainWindow.menu.file.closewindow=Fermer
-v3.button.removeActivityEntry=Supprimer l'entr\u00e9e d'activit\u00e9
-ConfigView.copy.to.clipboard.tooltip=Copier dans le presse-papier
-Browser.popup.error.no.access=Une erreur s'est produite lors de la tentative d'acc\u00e9der \u00e0 une ressource \u00e9loign\u00e9e. \nR\u00e9essayez ult\u00e9rieurement. \n 
-ConfigView.label.queue.stoponcebandwidthmet=Ne pas d\u00e9marrer plus de torrents quand la vitesse limite de partage/t\u00e9l\u00e9chargement est atteinte
-azbuddy.name=Amis
-azbuddy.enabled=Activ\u00e9
-azbuddy.disabled=Le plugin est d\u00e9sactiv\u00e9, regardez la configuration du plugin pour changer cela.
-azbuddy.nickname=Votre surnom
-azbuddy.msglog.title=Information sur votre ami
-azbuddy.addtorrent.title=Accepter le t\u00e9l\u00e9chargement?
-azbuddy.addtorrent.msg=L'ami '%1' vous a envoy\u00e9 '%2'./nVoulez-vous ajouter ce t\u00e9l\u00e9chargement?
-azbuddy.contextmenu=Envoyer \u00e0 un ami
-azbuddy.ui.mykey=Ma Cl\u00e9
-azbuddy.ui.add=Ajouter
-azbuddy.ui.table.last_msg=Dernier message
-azbuddy.ui.menu.remove=Supprimer
-azbuddy.ui.menu.copypk=Copie de Cl\u00e9 Publique
-azbuddy.ui.menu.send=Envoyer un message
-azbuddy.ui.menu.send_msg=Entrez le texte a envoyer \u00e0 votre (vos) ami(s)
-v3.MainWindow.menu.view.footer=Barre d'Amis
-azbuddy.downspeed=KB/s max vitesse de t\u00e9l\u00e9chargement ami [0: illimit\u00e9]
-azbuddy.chat.says=%1 dit:
-Button.bar.add=Ajouter des Amis
-Button.bar.edit=Modifier
-Button.bar.edit.cancel=Fini de Modifier
-v3.MainWindow.menu.view.pluginbar=Barre de Plugin
-v3.share.private.title=Partage de Torrents
-v3.share.private.text=Le torrent s\u00e9lectionn\u00e9 est marqu\u00e9 comme "priv\u00e9".\n\nVous ne pouvez pas partager des torrents priv\u00e9s
-azbuddy.tracker.enabled=Activer le 'Boost d'Amis' pour t\u00e9l\u00e9charger plus vite avec vos Amis
-v3.MainWindow.button.download=T\u00e9l\u00e9charger
-v3.MainWindow.button.run=Ouvrir le fichier t\u00e9l\u00e9charg\u00e9
-v3.activity.header.downloads=T\u00e9l\u00e9chargements
-v3.activity.header.vuze.news=Nouvelles de Vuze
-message.status.success=Succ\u00e8s
-azbuddy.tracker.bbb.status.title=Boost d'Amis
-azbuddy.tracker.bbb.status.title.tooltip=Double cliquez pour obtenir des d\u00e9tails
-azbuddy.tracker.bbb.status.idle=Pas de Boost
-azbuddy.tracker.bbb.status.nli=Connection Requise
-azbuddy.tracker.bbb.status.in=Je suis Boost\u00e9
-azbuddy.tracker.bbb.status.out=En train de Booster des Amis
-v3.MainWindow.search.go.tooltip=Lancer la Recherche
-v3.MainWindow.search.last.tooltip=Afficher la derni\u00e8re Recherche
-azbuddy.online_status=Statut de connection
-azbuddy.os_online=Connect\u00e9
-azbuddy.os_away=Absent
-azbuddy.os_not_avail=Pas disponible
-azbuddy.os_busy=Occup\u00e9
-azbuddy.os_offline=D\u00e9connect\u00e9
-azbuddy.ui.menu.disconnect=D\u00e9connect\u00e9
-azbuddy.enable_chat_notif=Activer les notifications du chat
-DetailedListView.title=Liste d\u00e9taill\u00e9e
-subscript.add.title=Installer l'abonnement?
-subscript.add.desc=Voulez vous installer l'abonnement '%1'?
-subscript.add.dup.title=Abonnement en double
-subscript.add.dup.desc=L'abonnement '%1' est d\u00e9ja install\u00e9.
-subscript.add.upgrade.title=Mettre \u00e0 jour l'abonnement?
-subscript.add.upgrade.desc=Voulez vous mettre \u00e0 jour l'abonnement '%1'?
-subscript.add.upgradeto.desc=La version %1 de l'abonnement '%2' est disponible.\nVoulez vous mettre a jour?
-iconBar.queue.tooltip=File d'attente
-subscriptions.listwindow.title=Abonnements
-subscriptions.listwindow.autochecktext=Vuze peut trouver des abonnements li\u00e9s au contenu de votre bibliotheque. Voulez vous activer cette option?
-subscriptions.listwindow.loadingtext=Recherche d'abonnements li\u00e9s \u00e0 '%1'
-subscriptions.listwindow.failed=Pas d'abonnements trouv\u00e9s
-subscriptions.listwindow.popularity=Popularit\u00e9
-subscriptions.listwindow.popularity.unknown=Inconnu
-subscriptions.listwindow.name=Nom
-subscriptions.listwindow.subscribe=Abonnement
-subscriptions.listwindow.popularity.reading=Lecture...
-MainWindow.menu.help.faq=&FAQ
-Subscription.menu.forcecheck=Mettre \u00e0 jour
-Subscription.menu.clearall=Marquer tous les r\u00e9sultats lus
-Subscription.menu.remove=Effacer
-sidebar.Library=Biblioth\u00e8que
-sidebar.LibraryDL=T\u00e9l\u00e9chargement
-sidebar.LibraryCD=Termin\u00e9
-authenticator.location=Lieu
-authenticator.details=D\u00e9tails
-Subscription.menu.export=Exporter
-subscript.export.select.template.file=Sauver
-Button.back=Retour
-sidebar.LibraryUnopened=Non visionn\u00e9s
-Subscription.menu.deleteall=Effacer tous les r\u00e9sultats
-Subscription.menu.reset=R\u00e9initialiser
-ConfigView.section.Subscriptions=Abonnements
-subscriptions.config.maxresults=Nombre maximum de r\u00e9sultats memoris\u00e9s par abonnement [0: illimit\u00e9]
-Subscription.menu.resetauth=R\u00e9initialiser les details d'authentification
-Wizard.Subscription.title=Abonnement
-Wizard.Subscription.optin.title=Activer les abonnements
-Wizard.Subscription.subscribe.title=Abonnements disponibles
-Wizard.Subscription.create.title=Cr\u00e9er un nouvel abonnement
-Button.add=Ajouter
-Button.createNewSubscription=Nouvel Abonnement
-Button.availableSubscriptions=Abonnements disponibles
-Wizard.Subscription.optin.description=En activant les abonnements, Vuze vous montrera les abonnements li\u00e9s au contenu de votre biblioth\u00e8que, et vous permettra de savoir quand le contenu de votre abonnement est disponible au t\u00e9l\u00e9chargement.\n\nSouhaitez-vous activer les abonnements?
-Wizard.Subscription.search.subtitle1=Tapez une recherche afin de commencer \u00e0 cr\u00e9er votre abonnement:
-Wizard.Subscription.search.subtitle2=Que puis-je rechercher?
-Wizard.Subscription.search.subtitle2.sub1=HD Movies, TV Shows, Films, Bandes-annonces sur le r\u00e9seau Vuze
-Wizard.Subscription.search.subtitle2.sub2=Torrents \u00e0 travers tout le Web
-Wizard.Subscription.search.subtitle3=Une fois votre abonnement compl\u00e9t\u00e9, vous recevrez des mises \u00e0 jour dans votre barre lat\u00e9rale lorsque de nouveaux r\u00e9sultats sont disponibles pour votre recherche.
-Wizard.Subscription.rss.subtitle1=Tapez ou collez l'URL ci-dessous:
-Wizard.Subscription.rss.subtitle2=De nombreux \u00e9diteurs fournissent des flux RSS de leur contenu. Localiser l'URL sur le site de l'\u00e9diteur, copiez et collez l'URL dans le champ ci-dessus, puis cliquez sur Enregistrer.
-Wizard.Subscription.rss.subtitle3=Une fois enregistr\u00e9, vous recevrez des mises \u00e0 jour dans votre barre lat\u00e9rale lorsque de nouveaux r\u00e9sultats sont disponibles via votre flux RSS.
-Wizard.Subscription.subscribe.library=Contenu dans votre biblioth\u00e8que
-Wizard.Subscription.subscribe.subscriptions=Abonnements connexes
-Wizard.Subscription.subscribe.library.empty=Pas d'abonnement disponible?\n \nCherchez le bouton d'abonnement orange vif sur le r\u00e9seau HD Vuze.\n \n<A HREF="http://wiki.vuze.com/w/FAQ_Subscriptions"> En savoir plus </A>
-message.confirm.delete.title=Confirmer la suppression
-message.confirm.delete.text=\u00cates-vous certain de vouloir supprimer '%1'?
-Subscription.menu.properties=Propri\u00e9t\u00e9s
-props.window.title=Propri\u00e9t\u00e9s pour '%1'
-subscriptions.column.new.info=Indique si plus d'un nouveau r\u00e9sultat
-subscriptions.column.name=Abonnement
-subscriptions.column.nb-results=R\u00e9sultats
-subscriptions.column.nb-new-results=Nouveaux r\u00e9sultats
-subscriptions.column.last-checked=Derniere v\u00e9rification
-subscriptions.view.title=Abonnements
-Subscription.menu.upgrade=Activer la mise \u00e0 jour a une version sup\u00e9rieure
-subscription.version.bad=L'abonnement '%1' ne peut \u00eatre install\u00e9 qu'apres avoir mis Vuze \u00e0 jour
-subscriptions.view.help.1=Ajoutez des abonnement partout o\u00f9 vous voyez
-subscriptions.view.help.2=Obtenez gratuitement des mises \u00e0 jour chaque fois qu'un nouveau contenu est disponible en t\u00e9l\u00e9chargement. <A HREF="http://wiki.vuze.com/w/FAQ_Subscriptions">En savoir plus</A>.
-subscript.some.subscribed=Vous \u00eates abonn\u00e9s \u00e0 un ou plusieurs abonnements pour ce contenu.\nCliquez pour voir tous les abonnements displonibles.
-subscript.none.subscribed=Cliquer pour voir les abonnement disponibles pour ce contenu
-TableColumn.header.azsubs.ui.column.subs_link.info=Associ\u00e9s \u00e0 des abonnements
-Button.deleteContent.fromComputer=Supprimer de votre ordinateur
-Subscription.menu.dirtyall=Marquer tous les r\u00e9sultats non lus
-configureWizard.file.message3=Vuze placera les fichiers t\u00e9l\u00e9charg\u00e9s dans un dossier sp\u00e9cifique, vous pouvez choisir ce dossier ici:
-azbuddy.ui.menu.cat=Cat\u00e9gories
-azbuddy.ui.menu.cat.set=Entrez des cat\u00e9gories
-azbuddy.ui.menu.cat.set_msg=S\u00e9parez la liste des cat\u00e9gories par des virgules, ou marquez "Tous"
-azbuddy.ui.menu.cat_subs=S'abonner
-azbuddy.enable_cat_pub=Cat\u00e9gories publiques auxquelles TOUS vos amis peuvent s'abonner (s\u00e9par\u00e9 par des ',')
-devices.view.title=P\u00e9riph\u00e9riques
-device.browse=Parcourir
-ConfigView.label.maxStalledSeeding=Maximum 'stalled' [0: illimit\u00e9]
-General.percent=Pourcent
-MainWindow.menu.help.donate=Faire une &donation...
-# This is the beginning of the word "View".  It's right aligned under the icon bar item
-# This is the end of the word "View".  It's left aligned under the icon bar item
-general.dont.ask.again=Ne plus me redemander
-device.itunes.install=Vous devez installer iTunes
-device.itunes.start=Vous devez d\u00e9marrer iTunes ou activer le d\u00e9marrage automatique
-device.itunes.install_problem=Il semble y avoir un probl\u00e8me avec l'int\u00e9gration d'iTunes 
-option.askeverytime=Demander \u00e0 chaque fois
-option.rememberthis=Se souvenir de ce r\u00e9glage
-Subscription.menu.setcookies=Configurer les cookies
-subscriptions.config.autostartdls=D\u00e9marrer les t\u00e9l\u00e9chargements automatiquement (sinon ils s'ajoutent arr\u00eat\u00e9s)
-subscriptions.config.autostart.min=Ne d\u00e9marre que si >= Mo [0: illimit\u00e9]
-subscriptions.config.autostart.max=Ne d\u00e9marre que si <= Mo [0: illimit\u00e9]
-subscriptions.column.nb-subscribers=Abonn\u00e9s
-subscriptions.rss.enable=Cr\u00e9er un flux RSS \u00e0 partir d'un abonnement
-
-v3.MainWindow.menu.getting_started=&Premiers Pas
-MainWindow.menu.community=&Communaut\u00e9
-MainWindow.menu.help.faq=Questions &Fr\u00e9quentes (FAQ)
-MainWindow.menu.help.faq.keybinding.mac=Meta+?
-MainWindow.menu.community.wiki=&Wiki Communautaire
-MainWindow.menu.community.forums=Fo&rum Communautaire
-MainWindow.menu.community.blog=&Blog
-MainWindow.menu.help.support=&Aide
-
-mdi.entry.plus.full=Vuze Plus
-mdi.entry.plus.free=Vuze Plus
-mdi.entry.dvdburn=Gravure de DVD
-mdi.entry.dvdburn.new=Nouveau DVD
-
-TableColumn.header.CountryCode=PaysID
-TableColumn.header.Country=Pays
-TableColumn.header.CountryCode.info=Code Pays (ISO 3166) du client
-TableColumn.header.Country.info=Pays du client
-TableColumn.header.CountryFlag=Drapeau
-TableColumn.header.CountryFlag.info=Drapeau du pays du client
-TableColumn.header.CountryFlagSmall=Drapeau
-TableColumn.header.CountryFlag.info=Drapeau du pays du client
-TableColumn.header.CountryFlagSmall.info=Petit drapeau du pays du client
+v3.MainWindow.menu.contentnetworks=HD & R\u00E9seaux
+window.uiswitcher.text=Merci s\u00E9lectionner ci-dessous, l'interface utilisateur qui correspond le mieux \u00E0 vos besoins.
+plugin.sharing.download.remove.veto=Ce t\u00E9l\u00E9chargement provient d'une ressource partag\u00E9e.\nEnlever le t\u00E9l\u00E9chargement revient \u00E0 priver les autres de la ressource\: voir Outils->Mes Partages.
+VivaldiView.notAvailable=La vue Vivaldi n'est pas disponible
+ConfigView.section.file.showopentorrentoptions.sep=Utilisez une bo\u00EEte de dialogue s\u00E9par\u00E9e par torrent
+sidebar.header.devices=P\u00E9riph\u00E9rique de lecture
+speedtest.wizard.run=D\u00E9marrer un test de d\u00E9bit
+importTorrentWizard.title=Importer un torrent
+v3.deviceview.infobar.line2.itunes=Les vid\u00E9os appara\u00EEtront dans le dossier 'Films' d'iTunes d\u00E8s qu'ils seront pr\u00EAts.
+splash.loadingImages=Chargement des images...
+CacheView.writes.toFile=Vers Fichier
+unix.script.new.text=Un nouveau script de d\u00E9marrage de Vuze\u2122 est disponible, et a \u00E9t\u00E9 enregistr\u00E9 dans '%1'.\n\nIl est fortement recommand\u00E9 de quitter Vuze\u2122 maintenant et de basculer vers ce script ('%2').\n\nSi vous avez fortement modifi\u00E9es le script de d\u00E9marrage de Vuze\u2122, merci de consulter <A HREF\="{unix.script.new.manual.url}">VuzeWiki\:. Script Unix</A>\n\nSi vous avez install\u00E9 une distribution de Vuze\u2122 (yum, apt-get , etc) [...]
+ConfigView.section.style.showRankIcon=Afficher l'ic\u00F4ne de tri
+columnChooser.title=Choisissez les colonnes \u00E0 afficher
+ConfigView.section.tracker.maxgettime=Temps maximal pour traiter un GET (en s) [0\u00A0\: illimit\u00E9]
+Button.moveDown=D\u00E9placer vers le bas
+ConfigView.label.hapds=D\u00E9connecter les 'seeds' pour les t\u00E9l\u00E9chargements masqu\u00E9s mais termin\u00E9s
+tag.stats.none.defined=Pas de cat\u00E9gories avec des taux s\u00E9lectionn\u00E9s ou d\u00E9finis \!
+label.download.file=T\u00E9l\u00E9charger le fichier
+splash.unloadingTorrent=D\u00E9chargement du torrent
+ManagerItem.forced=(Forc\u00E9)
+device.search=Rechercher les modification sur les p\u00E9riph\u00E9riques
+iconBar.play=Lire
+ConfigView.label.seeding.rankType.seed.options=Options du "nombre de sources uniquement"
+IPChecker.external.service.discoveryvip.name=Discovery\u2122 Verification IP
+azbuddy.msglog.title=Information sur votre ami
+MyTorrentsView.menu.rename=Renommer...
+stats.long.monthstart=Le mois comptable commence le \:
+wizard.tracker.dht=D\u00E9centralis\u00E9 (clients Vuze\u2122 uniquement)
+subscript.import.fail.desc=D\u00E9tails\: %1
+pairing.ui.icon.tip.no.recent=Aucune connexions r\u00E9centes
+platform.win32.baddll.FPServiceProvider=FoxyProxy Video Utility
+ConfigView.label.prioritizefirstpiece=Donner la priorit\u00E9 aux premi\u00E8res parties de fichiers
+Wizard.Subscription.search.subtitle3=Une fois votre abonnement compl\u00E9t\u00E9, vous recevrez des mises \u00E0 jour dans menu barre lat\u00E9rale lorsque de nouveaux r\u00E9sultats sont disponibles pour votre recherche.
+Wizard.Subscription.search.subtitle2=Que puis-je rechercher?
+Wizard.Subscription.search.subtitle1=Tapez une recherche afin de commencer \u00E0 cr\u00E9er votre abonnement\:
+Peers.column.peer_id.info=ID du pair au format lisible
+ConfigView.section.connection.peersource.Plugin=Ajout\u00E9 par un plugin
+settings.updated.title=Param\u00E8tres Mise \u00E0 jour
+Button.ignore=&Ignorer
+ConfigTransferAutoSpeed.set.dht.ping=Configuration du Ping DHT\:
+ConfigView.section.connection.advanced.mtu.tooltip=Taille maximum d'un paquet pouvant \u00EAtre transmis en une seule trame sur le r\u00E9seau.\nVuze\u2122 utilise MTU-40 (MSS) pour optimiser la charge en envoi.\nValeurs recommand\u00E9es\:\n 576 - connexions 56k\n1492 - connexions haut-d\u00E9bit PPPoE\n1500 - connexions haut-d\u00E9bit Ethernet, DSL et Cable.
+subscriptions.listwindow.subscribe=Abonnement
+ConfigView.title.full._mac=Pr\u00E9f\u00E9rences
+remote.pairing.test.fail=Vuze\u2122 n'est pas accessible en dehors de votre r\u00E9seau local. <A HREF\="/pairing_error_faq.start">En savoir plus</A>
+ipCheckerWizard.chooseService=Veuillez choisir un service de v\u00E9rification d'IP ci-dessous\:
+ConfigView.label.downloading.autoReposition=Repositionner la file d'attente des t\u00E9l\u00E9chargements pour optimiser les performances de t\u00E9l\u00E9chargement
+iconBar.top=Tout en haut
+configureWizard.welcome.title=Bienvenue dans l'assistant de Configuration de Vuze\u2122
+ManagerItem.ready=Pr\u00EAt
+PeersView.BlockView.NoAvail.Have=Vous avez; pas le client
+wizard.tracker.external=Utiliser un tracker externe
+MagnetPlugin.report.found=Trouv\u00E9 %1
+MagnetPlugin.report.md.done=T\u00E9l\u00E9chargement des m\u00E9tadonn\u00E9es termin\u00E9
+Plugin.trackerpeerauth.info=Ce plugin fonctionne avec les trackers pour v\u00E9rifier que les pairs sont membres d'un essaim valide
+FilesView.click.info=Cliquez pour calculer; utiliser le menu contextuel pour un calcul multiple
+MyTorrentsView.menu.editWebSeeds=Modifier les 'Seeds' HTTP
+Button.yes=Oui
+MyTorrents.items.UpSpeedLimit.disabled=Pas d'envoi
+ConfigView.section.style.confirmationOnExit=Faire apparaitre une confirmation \u00E0 la fermeture
+label.num_selected=%1 s\u00E9lectionn\u00E9
+PeersView.gain.info=Nombre de t\u00E9l\u00E9chargement - donn\u00E9es upload\u00E9es
+MagnetURLHandler.report.percent=termin\u00E9\: %1%
+MyTorrentsView.dialog.NumberError.title=Nombre non valide ou non reconnu
+ConfigView.section.connection.webseed.act.on.avail=Activer les 'seeds" Web/HTTP seulement pour le t\u00E9l\u00E9chargement lorsque la disponibilit\u00E9 est faible
+SpeedTestWizard.test.panel.abort.countdown=abandon du test dans\:
+remote.pairing.tip.title=Astuce\: Deux fa\u00E7ons simples d'utiliser Vuze\u2122 \u00E0 distance \:
+Peers.column.as=AS (Syst\u00E8me Autonome)
+PeersView.state.handshake=Attends le handshake
+upnp.mapping.dataport=Port entrant de donn\u00E9es des clients
+crypto.alert.as.warning=R\u00E9seau '%1' est connu pour imposer un formatage du trafic r\u00E9duisant les performances de t\u00E9l\u00E9chargement. Le chiffrement du transport a \u00E9t\u00E9 automatiquement activ\u00E9 - cela peut \u00EAtre d\u00E9sactiv\u00E9 ou modifi\u00E9 via les param\u00E8tres de configuration.
+network.admin.maybe.vpn.title=R\u00E9seau virtuel priv\u00E9 (VPN) actif ?
+ConfigView.section.security.restart.msg=Vuze\u2122 va red\u00E9marrer pour terminer l'op\u00E9ration.
+library.incomplete.header=%1 \u00E9l\u00E9ment en t\u00E9l\u00E9chargement, %2 en attente de t\u00E9l\u00E9chargement
+TableColumn.menu.date_added.time=Afficher/Masquer le temps
+ConfigView.section.proxy.testsocks=Tester SOCKS
+MainWindow.menu.file.export=&Exporter un torrent en XML...
+splash.loadingTorrents=Chargement des Torrents
+Button.removeAll=Supprimer tous
+devices.copying=Copie vers le p\u00E9riph\u00E9rique
+sidebar.expand.tooltip=D\u00E9velopper le menu lat\u00E9rale
+ConfigView.label.stop.RunScriptAndClose=Ex\u00E9cuter le script + Fermer Vuze\u2122
+v3.MainWindow.view.wait=En cours d'initialisation. Veuillez patienter
+openUrl.title=Vuze\u2122 - Ouvrir l'URL
+Torrent.create.progress.piececount=Nombre de pi\u00E8ces\:
+ConfigView.section.startstop={ConfigView.label.start} & {ConfigView.label.stop}
+OpenTorrentFile.column.download=T\u00E9l\u00E9charger ?
+authenticator.location=Lieu
+upnp.alertothermappings=Rapporter les ports utilis\u00E9s par d'autres ordinateurs
+ConfigView.section.ipfilter.peerblocking.group=Blocage des pairs
+SystemTray.menu.startalltransfers=&D\u00E9marrer tous les transferts
+health.explain.error=Ce torrent a produit une erreur. Voir la colonne "\u00C9tat", ou l'indication sur l'ic\u00F4ne de l'erreur.
+IPChecker.external.service.discoveryvip.url=ip.discoveryvip.com
+ConfigView.section.Devices={devices.view.title}
+SpeedView.stats.estimatechoke=Estim\u00E9 (\u00E9touff\u00E9)
+MainWindow.dht.status.unreachable=DHT derri\u00E8re un pare-feu
+Views.plugins.UPnP.title.tooltip=Universal Plug and Play
+dlg.stream.plus.subtext=Fatigu\u00E9 d'attendre que vos t\u00E9l\u00E9chargements de vid\u00E9os se terminent ? Commencer \u00E0 les visionner plus t\u00F4t avec l'option 'Lire Maintenant', une fonctionnalit\u00E9 de Vuze\u2122 Plus qui vous permettra de regarder une vid\u00E9o tout en continuant \u00E0 t\u00E9l\u00E9charger.
+MainWindow.menu.view.mytorrents=M&es torrents
+Wizard.Subscription.subscribe.library=Contenu dans votre biblioth\u00E8que
+splash.initializeCore=Initialisation de base
+ConfigView.section.transfer.autospeed=D\u00E9bit automatique (classique)
+iconBar.transcode=P\u00E9riph\u00E9rique
+ConfigView.section.file.truncate.too.large=Tronquer les fichiers existant trop gros
+GeneralView.label.size=Taille d'une pi\u00E8ce\u00A0\:
+ConfigView.copy.to.clipboard.tooltip=Copier dans le presse-papier
+azbuddy.ui.table.name=Nom
+ConfigView.section.security.resetcerts.warning.title=Avertissement de perte de donn\u00E9es
+SpeedView.stats.maxPing=Pings maximum \:
+TableColumn.header.writerate.info=Taux d'\u00E9criture du fichier
+MainWindow.menu.file.folder.keybinding=Meta+Shift+O
+Subscription.menu.forcecheck=Mettre \u00E0 jour
+ConfigView.text.minutes=minutes
+MainWindow.menu.view.mytracker=Mes &trackers
+wizard.choosefile=Choisir un fichier
+Button.preview=Aper\u00E7u
+menu.min.share.ratio=Taux de partage minimum (%1)...
+MyTorrents.column.ColumnQuality=Qualit\u00E9
+SpeedTestWizard.finish.panel.enabled=Activer
+DHTTransport.report.request_all=Demande de transfert total de %1
+ConfigView.label.seeding.preferLargerSwarms=Quand des torrents ont le m\u00EAme rang, pr\u00E9f\u00E9rer les plus utilis\u00E9s.
+fileDownloadWindow.state_initializing=Initialisation
+ConfigView.label.ircwiki=Veuillez visiter http\://www.azureuswiki.com/index.php/Rules_for_IRC
+LoggerView.loggingDisabled=La journalisation n'est pas activ\u00E9e
+FilesView.%=%
+subs.ext.view.launch.info=Appuyez sur ce bouton pour lancer un navigateur
+MainWindow.dialog.share.sharedircontents.recursive=Inclure les sous-r\u00E9pertoires
+Button.deleteContent.fromComputer=Supprimer de votre ordinateur
+MainWindow.menu.help.checkupdate=Rechercher une &mise \u00E0 jour de Vuze\u2122
+Trackers.column.name=D\u00E9tails
+health.explain.yellow=Le Tracker est OK, vous avez des connexions \u00E0 des clients, mais aucune entrante.\nSi persistant, vous avez vraisemblablement un probl\u00E8me de configuration de routeur ou de pare-feu
+dht.portdefault=Utiliser le port par d\u00E9faut
+Button.send=Envoyer
+FilesView.mode=Mode
+PeerManager.status.finished=Termin\u00E9
+MyTorrentsView.dialog.setSpeed.title=R\u00E9gler la vitesse de %1
+MyTorrentsView.header=Torrents incomplets/en t\u00E9l\u00E9chargement
+MagnetPlugin.report.dead=%1 est mort
+azbuddy.ui.menu.ping=Ping
+devices.od.turnon.text3=Merci de connecter un disque dur \u00E0 %1 pour activer cette fonction.
+devices.od.turnon.text2=Souhaitez-vous que %1 continue de t\u00E9l\u00E9charger vos fichiers lorsque votre ordinateur est hors ligne ?
+pairing.srp.enable=Activer le jumelage s\u00E9curis\u00E9e
+devices.od.turnon.text1=Nous avons remarqu\u00E9 que vous \u00EAtes connect\u00E9 \u00E0 un %1.
+ConfigView.section.tracker.processinglimits=Limites de traitement
+IPChecker.external.service.no-ip.url=www.no-ip.com
+ConfigView.section.transfer.autospeed.forcemin=%1 vitesse d'upload forc\u00E9 quand il s'agit de connexion en 'baseline'
+popup.previous=< (%1)
+LocaleUtil.column.encoding=Encodage
+MainWindow.menu.transfers.startalltransfers=&D\u00E9marrer tout
+upnp.alert.mappingfailed=UPnP\: Mapping '%1' a \u00E9chou\u00E9
+FileView.BlockView.Active=Actif
+authenticator.user=Nom d'utilisateur
+label.torrent.structure=Structure du torrent
+Button.markSelected=Marquer les s\u00E9lections
+sidebar.show.options=Afficher la vue 'Options' comme une entr\u00E9e du menu lat\u00E9ral plut\u00F4t que dans une fen\u00EAtre s\u00E9par\u00E9e
+subscript.add.upgrade.title=Mettre \u00E0 jour l'abonnement?
+window.uiswitcher.title=S\u00E9lecteur d'interface graphique Vuze\u2122
+MyTorrentsView.menu.category.delete=Effacer cette cat\u00E9&gorie
+ConfigView.section.plugins=Plugins
+v3.MainWindow.menu.file.closewindow.keybinding=Meta+W
+DownloadManager.error.filenotfound=Fichier non trouv\u00E9
+TableColumn.header.copied=Copi\u00E9
+ConfigView.section.security.resetkey.warning.title=Avertissement de perte de donn\u00E9es
+devices.contextmenu.xcode=Transcoder pour le p\u00E9riph\u00E9rique
+label.table.default=Tableau par d\u00E9faut
+wizard.notimplemented=Pas encore impl\u00E9ment\u00E9
+ConfigView.label.seeding.autoStart0Peers=D\u00E9marrer automatiquement tous les torrents termin\u00E9s qui ont 0 peer.
+OpenTorrentOptions.header.saveto=Emplacement de l'enregistrement\: %1
+Torrent.create.progress.ignoringfile=Ignore le fichier
+config.external.browser.switch.subs=Abonnements
+TableColumn.header.torrentfileindex=Index de fichier
+devices.installed=Install\u00E9
+br.backup.auto.enable=Activer les sauvegardes automatiques
+device.router.req_map=Mappages requis
+ConfigView.section.tracker.ip=Adresse IP externe du tracker
+azbuddy.enable_chat_notif=Activer les notifications du chat
+label.container.display=<conteneur>
+TableColumn.header.swarm_average_completion.info=Pourcentage moyen de compl\u00E9tion des clients connect\u00E9s
+dialog.uiswitcher.restart.title=Changement d'interface graphique \: Red\u00E9marrage de Vuze\u2122 requis
+ConfigView.label.transferbar.remember_location=Se rappeler de la derni\u00E8re position de la barre de transfert
+ConfigView.label.show.win.on.add=Afficher la fen\u00EAtre principale quand un t\u00E9l\u00E9chargement est ajout\u00E9 par une autre application
+wizard.multitracker.group=Groupe de trackers
+dlg.auth.enter.line.try.2=D\u00E9sol\u00E9, nous n'avons pas pu valider votre code d'activation. Merci de v\u00E9rifier celui-ci puis de le saisir \u00E0 nouveau.
+dlg.auth.enter.line.try.1=Entrez votre code d'activation ci-apr\u00E8s pour compl\u00E9ter votre mise \u00E0 niveau de Vuze\u2122 Plus.
+SpeedView.stats.upload_details=%1
+device.status.online=Le p\u00E9riph\u00E9riques en connect\u00E9
+FileItem.write=\u00C9criture
+label.limit=Limiter
+PiecesView.DistributionView.RarestAvl=Pi\u00E8ces les plus rares\: %1 (Disponible \: %2)
+PeersView.BlockView.Transfer=En transfert
+LoggerView.filter.uncheckAll=D\u00E9s\u00E9lectionner toutes les cat\u00E9gories
+MyTorrentsView.menu.manual.per_torrent=Manuellement (par torrent)
+MainWindow.menu.file.open.torrentforseeding=Fichier .torrent (pour le seeding)
+dialog.associations.title=V\u00E9rification de l'association
+ConfigView.label.jvm=Options de la machines virtuelle Java\u2122
+ConfigView.label.playdownloadspeech=Jouer \u00E0 la fin d'un t\u00E9l\u00E9chargement
+dlg.auth.install.subtitle.trial=Installation de DVD Burn
+configureWizard.transfer.title=Transferts et Connexion
+upnp.ignorebaddevices=Ignorer les p\u00E9riph\u00E9riques qui ne r\u00E9pondent pas correctement
+label.rerequest.blocks=Redemander les blocs
+ConfigView.section.ipfilter.remove=Enlever
+OpenTorrentOptions.header.startoptions=Options de d\u00E9marrage\: %1
+Formats.units.Tibit=Tibit
+window.networkselection.description=Torrent \:
+configureWizard.transfer.connection=Type de connexion
+PeersView.Messaging.info=Supporte une API de messaging avanc\u00E9e.
+general.all.friends=Tous les amis
+IrcClient.joining=Rejoint
+subscriptions.dl_subs.enable=T\u00E9l\u00E9charger les souscriptions des autres clients en cas de besoin
+ConfigView.section.connection.encryption.encrypt.info=Si l'encryptage est activ\u00E9e, vous ne pourrez pas vous connecter aux clients incompatibles (sauf \u00E0 activer des options de repli)
+ConfigView.section.logging.log2type=Erreur
+TableColumn.header.sessionup.info=Octets upload\u00E9s dans cette session
+label.tags=Cat\u00E9gories
+SpeedTestWizard.finish.panel.auto.speed.seeding=Le type de d\u00E9bit automatique en seeding est \:
+ConfigView.label.seeding.numPeersAsFullCopy.tooltip=En pr\u00E9tendant qu'il y a 1 copie compl\u00E8te tous les X clients, on diminue le rang des torrents avec beaucoup de clients.\nCes torrents ont g\u00E9n\u00E9ralement beaucoup de trafic.\nCela ne change pas l'affichage du nombre de sources effectives.
+ConfigView.section.dns.info=Cet article pr\u00E9cise les serveurs DNS alternatifs et d\u00E9finit le moment o\u00F9 ils peuvent \u00EAtre utilis\u00E9s.\n Par exemple, Google utilise un serveur DNS sur l'adresse 8.8.8.8 (et 8.8.4.4 pour la sauvegarde)\n\nCe peut \u00EAtre utile, si votre fournisseur DNS ne r\u00E9sout pas correctement les noms.\n
+dht.backup.only=DHT Backup uniquement
+ConfigView.section.proxy.check.on.start=V\u00E9rifier l'\u00E9tat du proxy au d\u00E9marrage
+TableColumn.header.date_completed=Termin\u00E9
+UIDebugGenerator.messageask.text=Merci d'entrer une description concernant le bug que vous signalez
+Button.deleteContent.fromLibrary=Retirer de la biblioth\u00E8que
+ConfigView.section.connection.peersource.Tracker=D'un tracker
+iconBar.queue=D\u00E9marrer
+CacheView.reads.avgsize=Taille Moy.
+ConfigView.section.file.perf.cache.enable.read=Ex\u00E9cuter des lectures en avance pour r\u00E9duire les lectures disque quand en source.
+SpeedTestWizard.set.upload.panel.explain=Les limites fix\u00E9es ici sont utilis\u00E9s par l'algorithme Vuze\u2122 de D\u00E9bit Automatique\u200B\u200B. D\u00E9finir les limites de transfert et les limites de confiance\n\nNotez que des vitesses lin\u00E9aires sont souvent cit\u00E9es en "bits par seconde" - mais la valeur ci-dessous appara\u00EEt en "kilooctets par seconde".
+wizard.maketorrent.piececount=Nombre de pi\u00E8ces
+change.url.msg.desc=Cela va cr\u00E9er un nouvel abonnement et renommer l'existant
+CacheView.reads.title=Lectures E/S
+ConfigView.section.style.inactiveUpdate=Mettre \u00E0 jour la fen\u00EAtre principale \u00E0 chaque N mise(s) \u00E0 jour de l'interface graphique quand ce n'est pas la fen\u00EAtre active
+v3.mb.PlayFileNotFound.text=Les fichiers pour '%1' sont soit supprim\u00E9s, soit manquants.
+plus.notificaiton.OfflineExpiredEntry=Vous avez \u00E9t\u00E9 d\u00E9connect\u00E9 trop longtemps. Vuze\u2122 Plus a \u00E9t\u00E9 d\u00E9sactiv\u00E9.
+tags.view.heading=Pr\u00E9sentation des cat\u00E9gories
+ConfigView.label.queue.stoponcebandwidthmet=Ne pas d\u00E9marrer plus de torrents quand la vitesse limite de partage/t\u00E9l\u00E9chargement est atteinte
+ConfigView.button.save=Sauver
+Security.keystore.corrupt=Le lancement de la cl\u00E9 '%1' a \u00E9chou\u00E9, veuillez l'effacer et recr\u00E9er/r\u00E9importer les certificats.
+UpdateWindow.status.restartNeeded=Un red\u00E9marrage sera n\u00E9cessaire\u00A0\!
+importTorrentWizard.process.inputfilebad.message=Une erreur s'est produite en acc\u00E9dant au fichier \u00E0 importer\:
+ConfigView.section.security.op.error.title=\u00C9chec de l'op\u00E9ration
+subscript.add.desc=Voulez vous installer l'abonnement '%1'?
+ConfigView.section.tracker.maxgettime.info=Utilis\u00E9s pour les annonces et les scrapes
+tps.type.plugin=Plugin
+azbuddy.tracker.bbb.status.in=Je suis Boost\u00E9
+devices.copy.folder.dest=Copiez le dossier
+ConfigView.text.hours=heures
+label.monitor.clipboard=Surveiller le presse-papiers pour les liens torrent
+GeneralView.label.status.pieces_available.tooltip=Affiche le nombre de copies disponibles de chaque pi\u00E8ce.\nSi le nombre sur la droite est inf\u00E9rieur \u00E0 1, c'est qu'il n'y a pas suffisamment de copie du fichier (et que peut-\u00EAtre le t\u00E9l\u00E9chargement aura du mal \u00E0 se terminer ).
+GeneralView.label.in_swarm=au total
+MyTrackerView.scrapes="Scrapes"
+MainWindow.menu.file.open.torrentfortracking=Fichier .torrent... (Tracking Uniquement)
+label.close.tab=Fermer l'onglet
+window.updateswt.title=Votre version de SWT est d\u00E9pass\u00E9e\u00A0\!
+ConfigView.label.autoupdate=Ex\u00E9cuter l'assistant de mise \u00E0 jour quand une nouvelle version est disponible
+update.now.title=Mise \u00E0 jour requise
+subscript.add.dup.desc=L'abonnement '%1' est d\u00E9j\u00E0 install\u00E9.
+upnp.ignorebaddevices.reset=R\u00E9initialiser la liste des p\u00E9riph\u00E9riques ignor\u00E9s
+ManagerItem.downloading=T\u00E9l\u00E9chargement
+DiskManager.error.nospace_fat32={DiskManager.error.nospace} - contr\u00F4le {wiki.fat32}
+Button.retry=&R\u00E9essayer
+PeersView.state.info=\u00C9tat de la connexion
+device.rss.enable=Cr\u00E9er un flux RSS de contenu transcod\u00E9 - ce qui rend le contenu accessible dans des lecteurs de flux RSS
+ConfigView.section.ipfilter.allow=AUTORISER ces IP (BLOQUER par d\u00E9faut)
+progress.window.msg.filemove=Merci de patienter pendant le d\u00E9placement/renommage du fichier
+OpenTorrentWindow.mb.alreadyExists.default.name=M\u00E9dia
+mdi.entry.about.devices=En cours
+update.fail.app.changed.title=\u00C9chec de la mise \u00E0 jour
+pairing.alloc.fail=\u00C9chec lors de l'allocation d'un nouveau code d'acc\u00E8s\n%1
+ConfigView.section.tracker.portbackup=Ports de r\u00E9serve (s\u00E9par\u00E9s par ';')
+MinimizedWindow.all_transfers=Transferts Vuze\u2122
+ConfigView.section.tracker.natchecktimeout=Expiration de la v\u00E9rification (secs)
+iconBar.share=Partager
+TableColumn.header.sessiondown.info=Octets t\u00E9l\u00E9charg\u00E9s dans cette session
+devices.turnon.itunes=Inclut le support pour iTunes (obligatoire pour les p\u00E9riph\u00E9riques Apple\u2122)
+PeersView.menu.showdownload=Afficher le t\u00E9l\u00E9chargement et les d\u00E9tails
+SpeedTestWizard.abort.message.entered.queued=\u00C9tat d'attente/d'arr\u00EAt du t\u00E9l\u00E9chargement de test indiqu\u00E9e
+Button.renew=Renouveler
+ConfigView.text.any=une des
+FilesView.sha1.calculate=Calculer une ou plusieurs empreintes SHA1
+PeersView.outgoingreqcount.info=Nombre de requ\u00EAtes sortantes effectu\u00E9s \u00E0 destination des pairs
+subscriptions.view.help.2=Obtenez gratuitement des mises \u00E0 jour chaque fois qu'un nouveau contenu est disponible en t\u00E9l\u00E9chargement. <A HREF\="http\://wiki.vuze.com/w/FAQ_Subscriptions">En savoir plus</A>.
+subscriptions.view.help.1=Ajoutez des abonnement partout o\u00F9 vous voyez
+MyTorrentsView.menu.setSpeed.in=en
+TorrentOptionsView.multi.title.short=Options/Info torrent(s)
+br.backup.auto.now=Tester maintenant le fonctionnement de la sauvegarde automatique
+OpenTorrentWindow.checkbox.showAdvanced=Une fois que le torrent est charg\u00E9e, permettez-moi de d\u00E9finir des options avanc\u00E9es, tel que la s\u00E9lection de fichier et l'emplacement.
+ConfigView.section.proxy.username.info=Si le serveur proxy exige une authentification alors qu'aucune n'est d\u00E9fini, utilisez la cha\u00EEne "<none>" comme nom d'utilisateur(s)
+settings.updated.msg=Vos param\u00E8tres Vuze\u2122 ont \u00E9t\u00E9 mis \u00E0 jour.
+GeneralView.label.numberofpieces=Nombre de pi\u00E8ces\u00A0\:
+ConfigView.label.enableSystrayToolTipNextETA=Afficher les prochains t\u00E9l\u00E9chargement qui se terminent
+splash.plugin=Chargement du Plugin \:
+Progress.reporting.window.remove.auto.tooltip=Supprimer automatiquement de la vue toutes les t\u00E2ches termin\u00E9e, \u00E9chou\u00E9es, ou annul\u00E9es
+ConfigView.label.set_ui_transfer_speeds.description.upload=R\u00E9glage des vitesses de partage (en Ko / s)
+wizard.webseedseditor.edit.newseed=Nouveau seed
+wizard.newtorrent.showtorrent=Ouvrir le fichier torrent g\u00E9n\u00E9r\u00E9
+installPluginsWizard.details.loading=Chargement des d\u00E9tails, veuillez patienter...
+v3.MainWindow.button.cancel=Annuler
+ConfigView.section.logging.netinfo=G\u00E9n\u00E9rer des informations r\u00E9seau
+importTorrentWizard.process.unknownfail.title=Erreur inconnue
+TableColumn.header.status=\u00C9tat
+TableColumn.header.upspeed.info=D\u00E9bit de t\u00E9l\u00E9chargement en cours
+Button.bar.edit.cancel=Fini de Modifier
+PeersView.C1.info=Si un client vous emp\u00EAche de t\u00E9l\u00E9charger
+menu.change.url=Changer l'URL...
+Network.alert.acceptfail=Trop d'\u00E9checs successifs sur le port %1, %2 - essais stopp\u00E9s.\n Veuillez v\u00E9rifier les r\u00E9glages du pare-feu pour que ce port soit capable de recevoir des connexions.
+TableColumn.header.activityDate=Date ajout\u00E9
+TableColumn.header.priority.info=D\u00E9termine la proportion de votre capacit\u00E9 d'envoi r\u00E9serv\u00E9 \u00E0 ce torrent.
+GeneralView.label.tracker=\u00C9tat du Tracker\u00A0\:
+ConfigView.section.connection.peersource.DHT=Tracking d\u00E9centralis\u00E9
+ConfigView.section.interface.wavlocation=Chemin d'acc\u00E8s du fichier .wav
+ConfigView.section.style.disableAlertSliding=D\u00E9sactiver l'animation du glissement sur le style des messages d'alerte
+device.od.error.nospace=Espace disponible insuffisant sur le p\u00E9riph\u00E9rique ou aucun disque dur externe connect\u00E9
+PeersView.uniquepiece=Pi\u00E8ce (Mode Super-Source)
+security.certcreate.orgunit=Unit\u00E9 d'organisation
+metasearch.addtemplate.desc=\u00CAtes-vous s\u00FBr de vouloir installer un mod\u00E8le de recherche nomm\u00E9 '%1'?
+ConfigView.section.transfer.autospeed.maxupload=%1 d\u00E9bit d'upload maximum [0\: illimit\u00E9]
+Formats.units.persec=/s
+library.name._vuze=Biblioth\u00E8que
+ConfigView.pluginlist.coreplugins=Les plugins int\u00E9gr\u00E9s suivants sont charg\u00E9s\u00A0\:
+ConfigView.section.transfer.autospeed.maxdec=%1 diminution maximum par cycle
+configureWizard.nat.server.tcp_listen_port=Port TCP d'\u00E9coute entrant
+configureWizard.nat.tooManyPorts=Trop de ports \u00E0 tester (9 max)
+GeneralView.title.full=G\u00E9n\u00E9ral
+UIDebugGenerator.message.cancel.text=Vous n'avez pas saisi de description concernant le bug que vous essayez de reporter. Votre bug peut \u00EAtre \u00E9vident pour vous, mais sans description, nous ne pourrons deviner votre probl\u00E8me.\n\nLa g\u00E9n\u00E9ration de l'information de d\u00E9bogage a \u00E9t\u00E9 annul\u00E9.
+ConfigView.text.all=toutes les
+MainWindow.menu.tools.nattest=Test du routeur et du pare-feu
+ConfigView.section.transfer.autospeed.chokeping.tooltip=Les temps de Ping sup\u00E9rieures \u00E0 cette valeur seront consid\u00E9r\u00E9s comme un indicateur de saturation du r\u00E9seau
+v3.MainWindow.tab.browse=Sur Vuze\u2122
+auto.mode=Auto (recommand\u00E9)
+v3.activity.button.watchall=Marquer tout comme vu
+ConfigView.label.minPeersToBoostNoSeeds=Diminuer le "Rang de source" pour les torrents avec moins de
+ConfigView.section.style.defaultSortOrder.flip=Inverse du classement pr\u00E9c\u00E9dent
+TorrentOptionsView.param.alternative.value.enable=Valeur de remplacement lors du seeding
+Trackers.column.last_update=Derni\u00E8re mise \u00E0 jour
+IPChecker.external.httpinvalidresponse=R\u00E9ponse HTTP non valide
+columnChooser.apply=Appliquer
+ConfigView.section.file.perf.cache.trace=Conserver les op\u00E9rations de cache pour \u00E9ventuel diagnostic
+MagnetPlugin.report.alive=%1 est vivant
+TableColumn.header.maxdownspeed=Vit. T\u00E9l. max
+ConfigView.section.tracker.torrentsperpage=Combien de torrents par page\u00A0? [0\u00A0\: illimit\u00E9]
+platform.win32.baddll.AxShlex=Alcohol 120%
+ConfigView.section.ipfilter.bannedinfo=Les IPs qui ont envoy\u00E9s de mauvaises donn\u00E9es - bannies si la limite est d\u00E9pass\u00E9e
+OpenTorrentWindow.set.savepath=Changer le nom du dossier de niveau sup\u00E9rieur
+Formats.units.Kibit=Kibit
+LoggerView.filter=Filtrer
+OpenTorrentOptions.header.tags={label.initial_tags}\: %1
+FilesView.rename.failed.text=L'op\u00E9ration a \u00E9chou\u00E9e, probablement \u00E0 cause d'une mauvaise destination
+azbuddy.tracker.bbb.status.out=En train de Booster des Amis
+ConfigView.label.sleep.fpseed=Le seeding (si 'Premi\u00E8re priorit\u00E9' est actif)
+subscriptions.listwindow.autochecktext=Vuze\u2122 peut trouver des abonnements li\u00E9s au contenu de votre bibliotheque. Voulez vous activer cette option?
+discarded=rejet\u00E9s
+ConfigTransferAutoSpeed.ping.time.good=Bon\:
+installPluginsWizard.list.name=Nom
+ConfigView.section.backuprestore=Sauvegarde & Restauration
+DownloadActivityView.legend.up_smooth=Haut (Mod\u00E9r\u00E9)
+devices.contextmenu.od.enable=Activer
+pairing.status.registered=Mise \u00E0 jour r\u00E9ussie (%1)
+DHTView.activity.details=D\u00E9tails
+platform.win32.baddll.WSOCKHK=Net Nanny
+ConfigView.label.minSeedingTime.tooltip=Le "rang de source" d'un torrent peut varier fortement pendant une courte p\u00E9riode, for\u00E7ant parfois un torrent \u00E0 d\u00E9marrer pour \u00EAtre arr\u00EAt\u00E9 et mis en attente juste apr\u00E8s.\nCeci all\u00E8ge le probl\u00E8me en for\u00E7ant le torrent \u00E0 rester source pendant un certain temps. Vous pouvez toujours l'arr\u00EAter manuellement.
+PeerSocket.fake_client=FAKE
+TrackerChangerWindow.title=Ajout de Tracker(s)
+wizard.savingfile=Sauvegarde du fichier...
+platform.jvmopt.configerror=Vous ne pouvez pas g\u00E9rer les options en raison d'une erreur de configuration
+OpenTorrentFile.column.size.info=Taille du fichier
+ConfigView.section.security.resetkey.error.title=\u00C9chec de l'op\u00E9ration
+ConfigView.section.queue.seeding.autoStarting=D\u00E9marrage automatique
+ConfigView.section.security.restorekeys=Restaurer la cl\u00E9 depuis un fichier
+MainWindow.menu.file.open.torrent.keybinding=Meta+O
+MainWindow.status.unofficialversion=Vuze\u2122 Beta
+wizard.operationfailed=L'op\u00E9ration a \u00E9chou\u00E9e
+IPChecker.external.timeout=D\u00E9lai d\u00E9pass\u00E9
+ipfilter.disabled=Filtres IP d\u00E9sactiv\u00E9es
+TableColumn.header.seeds.info=\# de source(s) connect\u00E9(s) \u00E0 (\# de source(s) total)
+speedtest.wizard.select.general=Test de vitesse g\u00E9n\u00E9rale (recommand\u00E9)
+wizard.comment=Commentaire
+unix.script.new.auto.text=Un nouveau script de d\u00E9marrage Vuze\u2122 est disponible.\n\nIl est vivement recommand\u00E9 de red\u00E9marrer Vuze\u2122 maintenant.
+installPluginsWizard.file.invalidfile=Le fichier n'est pas un plugin valide pour Azureus.
+wizard.multitracker.edit.newgroup=Nouveau groupe
+v3.MainWindow.menu.view.footer=Barre d'amis
+TableColumn.header.remaining.info=Quantit\u00E9 restante \u00E0 t\u00E9l\u00E9charger
+platform.win32.baddll.gapsp=Neoteris
+Pieces.column.Requested=Demand\u00E9
+iconBar.bottom=Tout en bas
+SpeedTestWizard.abort.message.scheduling.failed=La planification du test a \u00E9chou\u00E9
+PeersView.source.info=L'origine de ce client
+GeneralView.label.totalspeed.tooltip=Vitesse de r\u00E9ception totale du torrent, redistribu\u00E9e entre tous les clients auxquels vous \u00EAtes connect\u00E9s.\nPour situer votre vitesse de t\u00E9l\u00E9chargement, vous pouvez calculer la moyenne de vitesse des\nclients en divisant cette vitesse totale par le nombre de clients auxquels vous \u00EAtes connect\u00E9s.\n
+FilesView.menu.setpriority.high=\u00C9lev\u00E9e
+tag.type.man.featcon=Contenu recommand\u00E9e
+ConfigView.section.dns.alts=Serveurs DNS alternatifs [s\u00E9par\u00E9s par ';']
+ConfigView.section.style.dropdiraction.sharefoldercontents=Contenu partag\u00E9
+azbuddy.tracker.bbb.status.title.tooltip=Double cliquez pour obtenir des d\u00E9tails
+speedtest.wizard.select.title=S\u00E9lectionnez le type de test de vitesse que vous souhaitez ex\u00E9cuter
+PeersView.uploadspeed=Envoie \u00E0
+SpeedTestWizard.test.panel.already.running=Le test est d\u00E9j\u00E0 en cours \!
+table.columns.reset=R\u00E9initialiser les colonnes
+MySeedersView.header=Torrents complets/en source
+device.renderer.view.title=Moteurs de rendu
+upnp.mapping.tcpssltrackerport=Port Tracker TCP SSL
+IrcClient.hasleft=est parti
+TableColumn.header.downspeed=Re\u00E7oit \u00E0
+wizard.newtorrent.byo=Construire votre propre torrent
+MainWindow.menu.community.forums=Fo&rum Communautaire
+GeneralView.label.user_comment=Commentaire de l'utilisateur \:
+MainWindow.IPs.tooltip=Nombre de filtres IP - Nombre d'IP bloqu\u00E9es\nDouble-cliquer pour afficher la liste des connexions refus\u00E9es .
+OpenTorrentWindow.mb.notTorrent.cannot.display=Impossible d'afficher les donn\u00E9es correctement
+General.percent=Pourcent
+beta.wizard.disable.text=Merci d'avoir essay\u00E9 la version b\u00EAta\!\n\nVeuillez t\u00E9l\u00E9charger et installer la derni\u00E8re version stable pour quitter le programme B\u00EAta
+Button.turnon=Activer
+TableColumn.header.torrentrelpath=Chemin du torrent
+swt.alert.cant.update=La biblioth\u00E8que SWT charg\u00E9 depuis "%3" ne peut pas \u00EAtre mis \u00E0 jour de la version %1 \u00E0 la version %2 (doit \u00EAtre charg\u00E9 \u00E0 partir de la version "%4"). Merci de consulter <A HREF\="http\://wiki.vuze.com/w/SWT_Cant_Auto_Update"> le wiki </A> pour plus de d\u00E9tails.
+ConfigView.section.interface.checkassoc=V\u00E9rifier les associations au d\u00E9marrage
+webui.port=Port
+subscript.some.subscribed=Vous \u00EAtes abonn\u00E9s \u00E0 un ou plusieurs abonnements pour ce contenu.\nCliquez pour voir tous les abonnements displonibles.
+show.tooltip.label=Afficher l'infobulle
+br.backup.auto.everydays=Fr\u00E9quence de sauvegarde [jours]
+ConfigView.section.security.choosetoolssavedir=S\u00E9lectionner le r\u00E9pertoire contenant 'tools.jar'
+v3.MainWindow.menu.view.toolbars=Barres d'outils
+subscript.export.select.template.file=Sauver
+TableColumn.header.priority=Priorit\u00E9
+devices.copy.folder.auto=Copier automatiquement les fichiers dans le dossier
+platform.win32.baddll.radhslib=Naomi Internet Filter (Radiant)
+Scrape.status.error.nohash=Le 'Hash' est manquant.
+MagnetURLHandler.report.torrent_size=taille du torrent\: %1
+Wizard.Subscription.create.title=Cr\u00E9er un nouvel abonnement
+jvm.max.direct.mem.info=Remarque\: cela d\u00E9fini la m\u00E9moire 'direct', il est plus courant de d\u00E9finir au pr\u00E9alable la m\u00E9moire du 'tas'
+azbuddy.chat.says=%1 dit\:
+menu.max.share.ratio=Taux de partage cible (%1)...
+OpenTorrentWindow.torrent.remove=Enlever le torrent de la liste
+ActivityView.legend.swarmaverage=Moyenne essaim
+TableColumn.header.seed_to_peer_ratio=TauxSources/Clients
+MainWindow.menu.window=&Fen\u00EAtre
+device.router.con_type=Connexion\: %1
+SpeedView.stats.estupcap=Limite d'upload \:
+importTorrentWizard.torrentfile.title=S\u00E9lection du torrent
+ConfigView.label.savedirectory=Dans le r\u00E9pertoire\u00A0\:
+TableColumn.header.timesincedownload.info=Temps \u00E9coul\u00E9 depuis que les donn\u00E9es ont \u00E9t\u00E9 t\u00E9l\u00E9charg\u00E9es pour le torrent
+pairing.ac.getnew=Allouer un nouveau code d'acc\u00E8s
+Button.apply=Appliquer
+ConfigView.section.style.launch=Lancement des assistants
+TableColumn.header.done.info=Pourcentage de la t\u00E2che actuelle compl\u00E9t\u00E9e
+GeneralView.label.shareRatio=Taux de partage\u00A0\:
+SpeedTestWizard.set.upload.bits.per.sec=bits/sec
+FilesView.menu.rename_only=Renommer rapidement
+MainWindow.menu.view.ipFilter=Filtres I&P
+v3.mb.delPublished.cancel=&Annuler
+label.click.to.showhide=Cliquez pour afficher/masquer
+label.alertnum=Alertes\: %1
+devices.xcode.rsspub=Publier un flux RSS
+upnp.mapping.tcptrackerport=Port Tracker TCP
+remote.pairing.test.success=Vuze\u2122 est accessible via le p\u00E9riph\u00E9rique distant.
+sidebar.header.subscriptions=Abonnements
+dlg.auth.revoked.link=<A HREF\="info"> Informations sur les codes d'activation r\u00E9voqu\u00E9s </A>
+TableColumn.header.readrate=Taux de lecture
+ConfigView.section.file.defaultdir.section=Options du r\u00E9pertoire par d\u00E9faut
+Peers.column.peer_byte_id.info=ID du pair au format d'octet
+label.color=Couleur
+ConfigView.label.seeding.firstPriority.info=Les torrents de Premi\u00E8re Priorit\u00E9 seront toujours en t\u00EAte de liste. Les torrents class\u00E9s dans "Aucun" ou "Rotation temporelle" correspondant aux crit\u00E8res de "Premi\u00E8re Priorit\u00E9" ne seront pas automatiquement arr\u00EAt\u00E9 et mis en attente. Un torrent de premi\u00E8re priorit\u00E9 prendra un cr\u00E9neau de t\u00E9l\u00E9chargement simultan\u00E9 si besoin (un torrent en source a priorit\u00E9 sur un torren [...]
+ConfigView.label.movetorrent=D\u00E9placer le .torrent
+ConfigView.section.tracker.enablecompact=Activer l'annonce de protocole compacte
+ConfigView.label.maxStalledSeeding=Maximum 'stalled' [0\: illimit\u00E9]
+azbuddy.ui.menu.send=Envoyer un message
+jvm.min.mem=Taille minimale de la m\u00E9moire du 'tas'[vide\=d\u00E9faut, min\=%1]
+ConfigView.notAvailableForMode=Cette section s'adresse au mode %1 ou plus. Elle n'est pas disponible en mode %2.
+devices.choose.profile.info.text=Apr\u00E8s votre s\u00E9lection, Vuze\u2122 pourra de d\u00E9tecter si le format de la vid\u00E9o s'affichera sur le p\u00E9riph\u00E9rique que vous avez s\u00E9lectionn\u00E9, et de cr\u00E9er une copie de le p\u00E9riph\u00E9rique compatible si n\u00E9cessaire.\n\nSurvolez le p\u00E9riph\u00E9rique s\u00E9lectionn\u00E9 pour obtenir plus de d\u00E9tails.
+ConfigView.label.userequestlimitingpriorities=Concentrer la vitesse de t\u00E9l\u00E9chargement sur la t\u00EAte de la file d'attente lorsque la limite de vitesse de t\u00E9l\u00E9chargement atteint
+UpdateWindow.columns.install=Installation
+network.admin.maybe.vpn.msg=Il semble que vous ayez un r\u00E9seau virtuel priv\u00E9 (VPN) actif sur\n\n\t%1\n\nSi tel est le cas, vous pouvez renforcer votre vie priv\u00E9e en vous liant explicitement \u00E0 celui-ci - pour ce faire, choisissez 'OUI'\n\nSi non, ou si vous n'\u00EAtes pas s\u00FBr, choisissez 'NON'.\n\nPour plus d'informations, visitez <a href\="http\://wiki.vuze.com/w/Proxies_And_VPNs\#VPN_Configuration">ce wiki</a>.
+MainWindow.upgrade.newerversion=Une nouvelle version de Vuze\u2122 est disponible
+ConfigView.label.experimental.osx.kernel.panic.fix=Correction exp\u00E9rimental des kernel panics sur les syst\u00E8mes OSX dual processeurs [n\u00E9cessite un red\u00E9marrage].
+azbuddy.disabled=Le plugin est d\u00E9sactiv\u00E9, regardez la configuration du plugin pour changer cela.
+unix.script.new.auto.title=Nouveau script de d\u00E9marrage de Vuze\u2122
+ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=R\u00E8gle la taille du socket standard SO_RCVBUF (en octets), soit l'\u00E9chelle et la taille de la fen\u00EAtre de r\u00E9ception TCP.\nVuze\u2122 laisse ce champ vide par d\u00E9faut, donc les valeurs par d\u00E9faut du syst\u00E8me d'exploitation sont utilis\u00E9es.\nNOTE\: Linux double la valeur indiqu\u00E9e.
+ConfigView.section.style.useSIUnits=Utiliser les unit\u00E9s du IEC (Ko -> Kio, etc.)
+azbuddy.ui.menu.cat=Cat\u00E9gories
+device.config.xcode.maxbps=Taux de transcodage maximum en KB/s [0\: illimit\u00E9]
+MainWindow.menu.file.closetab=Fermer l'ongle&t
+ConfigView.label.stop=Fermeture
+wizard.invalidfile=Fichier non valide\u00A0\!
+wizard.invaliddirectory=R\u00E9pertoire non valide\u00A0\!
+installPluginsWizard.mode.file=Par fichier
+config.external.browser.switch.subs.inf=N\u00E9cessite le plugin "Vuze\u2122 Web Remote"; Ne pas d\u00E9finir les r\u00E9sultats comme \u00ABlu\u00BB lorsqu'ils sont t\u00E9l\u00E9charg\u00E9s; Aucun r\u00E9glage de r\u00E9f\u00E9rent sur les liens de t\u00E9l\u00E9chargement
+ConfigView.label.savetorrentbackup=Conserver une sauvegarde
+quick.view.no.files=Aucun fichier applicable
+UpdateProperty.list.message=Entrez une nouvelle valeur pour %1. Utilisez un ',' pour s\u00E9parer plusieurs entr\u00E9es; vide pour effacer
+ConfigView.section.security.toolsdir=R\u00E9pertoire contenant 'tools.jar'
+ConfigView.section.file.tb.delete=Lors de la suppression par la touche 'Suppr' ou la barre d'outils \:
+DHTTransport.report.send_complete=envoi termin\u00E9
+MainWindow.about.internet.bugreports=Rapporter un bogue
+azbuddy.downspeed=KB/s max vitesse de t\u00E9l\u00E9chargement ami [0\: illimit\u00E9]
+TableColumn.header.timesinceupload.info=Temps \u00E9coul\u00E9 depuis que les donn\u00E9es ont \u00E9t\u00E9 t\u00E9l\u00E9charg\u00E9es pour le torrent
+ConfigView.label.systray._mac=Ic\u00F4ne de la barre d'\u00E9tat
+v3.deviceview.infobar.line1.generic=Glisser-d\u00E9poser des vid\u00E9os de votre biblioth\u00E8que vers %1 dans la barre lat\u00E9rale.
+ConfigView.section.proxy.enable_socks=J'ai un proxy SOCKS
+azbuddy.ui.table.lastseen=Derni\u00E8re visite
+MyTorrentsView.menu.rescanfile=Rev\u00E9rifier p\u00E9riodiquement les pi\u00E8ces incompl\u00E8tes
+ConfigView.section.mode=Mode
+xcode.deletedata.title=Suppression du contenu transcod\u00E9
+ConfigView.label.irclogin=Alias
+TableColumn.header.device.info=P\u00E9riph\u00E9rique cible
+ConfigView.section.ipfilter.save=Sauver
+wizard.multitracker.delete=Effacer
+iconBar.editcolumns=Configuration de la colonne
+PiecesView.DistributionView.NoAvl=Pi\u00E8ces non disponibles
+sidebar.show=Afficher le menu lat\u00E9ral
+TableColumn.header.upload.info=Quantit\u00E9 de donn\u00E9es qui a \u00E9t\u00E9 envoy\u00E9 au pair
+ConfigView.section.sharing.privatetorrent=Torrents priv\u00E9s - n'accepter que les clients du tracker
+installPluginsWizard.list.loading=Veuillez patientez pendant le chargement de la liste des plugins.
+Button.bar.add=Ajouter des Amis
+exportTorrentWizard.torrentfile.browse=...
+MyTrackerView.tracker=Tracker
+devices.associate=Associer avec
+ConfigView.section.security.backupkeys.button=Sauvegarder
+ConfigView.option.dm.dblclick.details=Ouvrir la vue de d\u00E9tails des Torrents
+dlg.auth.trial.success.subtitle=DVD Burn est pr\u00EAt
+Button.abort=Annuler
+SpeedView.stats.manual=Fix\u00E9
+MyTrackerView.completed=Compl\u00E9t\u00E9
+ConfigView.section.interface.cleardecisions=Vider les "d\u00E9cisions retenues"
+externalLogin.wait=Chargement de la page, merci patienter...
+ConfigView.section.Subscriptions=Abonnements
+TableColumn.header.eta_next=ETA suivant
+pairing.srp.pw.req=Mot de passe n\u00E9cessaire - rien ne peut fonctionner sans lui \!
+SpeedView.stats.unknown=Inconnu
+remote.pairing.functions=<A HREF\="clip">Copiez le code dans le presse papier</A> | <A HREF\="new">Obtenir un nouveau code</A>
+LocaleUtil.label.chooseencoding=Veuillez choisir l'encodage le plus appropri\u00E9
+wizard.information=Information
+ConfigView.section.tracker.seedretention.info=Note\u00A0\: Les statistiques d'envoi seront perdues pour les sources non retenues.
+CacheView.speeds.writes=\u00C9critures
+window.updateswt.status=\u00C9tat
+TorrentOptionsView.param.reset.to.default=R\u00E9tablir les valeurs par d\u00E9faut
+TableColumn.header.DownloadingRank=Rang du t\u00E9l\u00E9chargement
+device.renderer.remove_all=Supprimer tous les moteurs de rendu
+torrentdownload.error.dl_fail=Impossible de t\u00E9l\u00E9charger '%1' vers '%2'\: %3
+DHTView.transport.packets=Paquets
+SpeedView.stats.maxUp=D\u00E9bit montant max \:
+tps.tracker.cache=Cache de pairs
+label.set=D\u00E9finir...
+splash.initializePlugins=Initialisation des plugins
+ConfigView.section.interface.cleardecisionsbutton=Vider
+FilesView.dialog.priority.title=Entrez une priorit\u00E9 num\u00E9rique
+label.no.tag=Aucune cat\u00E9gorie
+PeersView.upload=Envoy\u00E9
+TableColumn.header.torrent_created.info=Date \u00E0 laquelle le torrent a \u00E9t\u00E9 cr\u00E9\u00E9, si disponible
+wizard.multitracker.configuration=Configuration du Multi-tracker
+StartStopRules.shareRatioMet=Taux Partage OK
+TableColumn.header.azsubs.ui.column.subs=S'abonner
+ConfigView.label.seeding.autoStart0Peers.tooltip=Activer pour que le tracker liste toujours les torrents avec 0 peer.
+security.certcreate.intro=Vous permet de cr\u00E9er un certificat auto-sign\u00E9.
+device.itunes.install_problem=Il semble y avoir un probl\u00E8me avec l'int\u00E9gration d'iTunes
+FilesView.md5.calculate=Calculer une ou plusieurs empreinte MD5
+min.sr.window.message=Entrez un ratio partag\u00E9 minimum [0\: d\u00E9sactiv\u00E9]
+ConfigView.label.backupconfigfiles=Sauvegarder les fichiers de configuration (pour r\u00E9cup\u00E9ration \u00E9ventuelle)
+iconBar.stop=Arr\u00EAter
+StartStopRules.SPratioMet=1\u00E8re P / Taux S\:P OK
+ConfigView.label.checkOnSeeding=Effectuez un nouveau contr\u00F4le des ressources sur les \u00E9l\u00E9ments apr\u00E8s le 'seeding'
+DiskManager.alert.movefilerecoveryfails=Erreur de r\u00E9cup\u00E9ration apr\u00E8s l'\u00E9chec du d\u00E9placement\nLa restauration du fichier %1 a \u00E9chou\u00E9, %2
+ConfigView.label.seeding.rankType.seed=Nombre de sources uniquement
+Unopened.bigView.header=Nouveau
+ConfigView.section.sharing.rescanperiod=P\u00E9riode de scan (s)
+PeerManager.status.checking=en cours
+device.xcode=Transcoder
+wizard.progresstitle=Cr\u00E9ation du fichier torrent
+wizard.tracker.howToLocal=\tAller dans 'Options > Tracker' pour l'activer
+TrayWindow.menu.startalldownloads=&D\u00E9marrer tous les t\u00E9l\u00E9chargements
+ConfigView.section.tracker.client.scrapesingleonly=D\u00E9sactiver l'agr\u00E9gation de scrape par tracker (peut \u00E9viter les erreurs du type 'URL too long' (414))
+TableColumn.header.availability.info=\# de copies compl\u00E8tes vues
+upnp.enable=Activer l'UPnP
+wizard.createtorrent.extrahashes=Ajoute des "Hash" pour pouvoir utiliser le torrent sur d'autres r\u00E9seaux (e.g. Gnutella2, eDonkey2K).
+stats.snapshot.group=Instantan\u00E9
+label.dont.show.again=Ne plus afficher ce message
+azbuddy.ui.table.read_cat=Cat lu
+ConfigView.section.connection.network.max.outstanding.connect.attempts=Max connexions sortantes en cours
+security.certcreate.createok=Cr\u00E9ation du certificat r\u00E9alis\u00E9e avec succ\u00E8s.
+webui.mode.info=Mode peut \u00EAtre\n\t"full"\t\= toutes op\u00E9rations possibles (d\u00E9faut)\n\t"voir"\t\= voir seulement (mais peut mettre \u00E0 jour la fr\u00E9quence de rafra\u00EEchissement)
+wizard.multitracker.edit=\u00C9diter..
+PeersView.T.L.tooltip=vous avez \u00E9tabli la connexion
+webui.access.info=L'acc\u00E8s peut \u00EAtre\n\t"local"\t\= seule la machine locale peut se connecter\n\t"all"\t\= acc\u00E8s pour tous (d\u00E9faut)\n\tIP\t\= e.g. 192.168.0.2\t\t\tseulement une IP\n\tIP1-IP2\t\= e.g. 192.168.0.1-192.168.0.255\tintervalle inclusif d'IPs.
+MainWindow.menu.view.console.keybinding=Meta+4
+DownloadManager.error.filewithouttorrentinfo=Pas d'information "torrent" dans le fichier
+TableColumn.header.TableColumnSample=Exemple
+AlertMessageBox.warning=Avertissement
+MyTrackerView.peers=Clients
+SpeedView.stats.measuredmin=Minimum mesur\u00E9
+Plugin.localtracker.info=Le d\u00E9tecteur de clients sur LAN permet \u00E0 plusieurs Vuze\u2122 derri\u00E8re un pare-feu ou sur un m\u00EAme r\u00E9seau local\nde t\u00E9l\u00E9charger efficacement un m\u00EAme torrent en \u00E9tablissant des connections directes entre eux.
+MainWindow.menu.file.open.torrentnodefault.keybinding.mac=Meta+Opt+O
+ConfigView.section.transfer.lan.tooltip=R\u00E9glages sp\u00E9cifiques LAN
+UpdateMonitor.messagebox.accept.unverified.title=Acceptation de l'installation non v\u00E9rifi\u00E9e
+Formats.units.KiB=Kio
+security.certtruster.prompt=Voulez-vous y faire confiance\u00A0?
+GeneralView.label.distributedCopies=Copies distribu\u00E9es \:
+label.socks=SOCKS
+ConfigView.section.torrent.decoding=Jeux de caract\u00E8res pour le d\u00E9codage
+MainWindow.menu.file.open=&Ouvrir
+MainWindow.menu.speed_limits.schedule.err=Les erreurs suivantes ont \u00E9t\u00E9 signal\u00E9es, merci de les r\u00E9-\u00E9diter afin de les corriger\!
+v3.MainWindow.menu.getting_started=&Premiers Pas
+dlg.auth.success.line2=Vous \u00EAtes d\u00E9sormais en mesure de graver des DVD lisibles illimit\u00E9s, scanner vos fichiers pour les virus, et diffuser les vid\u00E9os que vous t\u00E9l\u00E9chargez - le tous, sans publicit\u00E9 \!
+ConfigView.section.interface.resetassocbutton=R\u00E9initialiser
+dlg.auth.success.line1=Merci pour votre mise \u00E0 niveau vers Vuze\u2122 Plus.
+TableColumn.header.peakup.info=D\u00E9bit d'upload \u00E9lev\u00E9
+DHTView.title.fullcvs=Base de donn\u00E9es distribu\u00E9e CVS
+webui.rootdir=R\u00E9pertoire racine (*)
+wizard.multitracker.noannounce=L'URL d'annonce n'est pas pr\u00E9sente dans la liste de tracker
+Button.add.tooltip=Ajouter un torrent \u00E0 votre biblioth\u00E8que
+ConfigView.label.start.inlrm=Commencez en mode faible utilisation des ressources (UI d\u00E9sactiv\u00E9, utilisation restreinte de la m\u00E9moire et du r\u00E9seau, etc)
+PeersView.statup=Statistique d'envoi
+ConfigView.section.queue.seeding=Source
+ConsoleView.title.short=Console
+subs.prop.num_read=Nombre de r\u00E9sultats lu
+ManagerItem.finishing=Ach\u00E8vement
+v3.MainWindow.menu.view.sidebar.keybinding=F7
+TableColumn.header.filesdone=Fichiers termin\u00E9s
+uninstallPluginsWizard.title=D\u00E9sinstallation de plugins
+MainWindow.menu.help.whatsnew=Quoi de neuf
+DHTView.operations.data=Donn\u00E9es
+wizard.newtorrent.byo.addcontainer.title=Ajout d'un conteneur
+StartStopRules.numSeedsMet=Sources OK
+config.internal.browser.proxy.select=Navigateur proxy \:
+TableColumn.header.torrent_created=Torrent cr\u00E9e
+openTorrentWindow.mb.alreadyExists.merge=Voulez-vous ajouter des trackers suppl\u00E9mentaires depuis le nouveau t\u00E9l\u00E9chargement vers l'existant ?
+ConfigView.section.tracker.createcert=Cr\u00E9er un certificat auto-sign\u00E9
+UIDebugGenerator.complete.text=Le fichier de d\u00E9bogage peut \u00EAtre trouv\u00E9 ici \: '%1'.\n\nCliquez sur OK pour ouvrir cet emplacement.
+subscriptions.overview=Abonnements
+ConfigView.dialog.choosedefaultsavepath=Choisissez le r\u00E9pertoire d'enregistrement des donn\u00E9es
+v3.MainWindow.menu.showActionBarText=Voir le texte
+subscriptions.listwindow.popularity.unknown=Inconnu
+MyTorrentsView.menu.edit_comment.enter.message=Entrez un commentaire pour ce t\u00E9l\u00E9chargement.
+ConfigView.label.autoopen.downloadbars=Ouverture automatique des barres de t\u00E9l\u00E9chargement lorsque
+pairing.ui.icon.show=Afficher l'ic\u00F4ne
+MainWindow.menu.closealldownloadbars=Fermer toutes les &mini-barres
+network.bindError=La liaison au serveur a \u00E9chou\u00E9 car aucune adresse compatibles n'est disponible, merci de v\u00E9rifier vos param\u00E8tres bind-to-IP.
+Plugin.localtracker.networks.info=Consid\u00E8rent les r\u00E9seaux suivants comme \u00E9tant locaux [adresses r\u00E9seaux s\u00E9par\u00E9s par ';', par exemple, 145,227. *. *]
+network.check.ipbinding=V\u00E9rifier que la liaison des adresses IP/interfaces est pr\u00E9sente au d\u00E9marrage
+label.various=Divers
+TableColumn.header.ProgressETA.info=Combiner les colonnes d'\u00E9tat et d'ach\u00E8vement dans une seule colonne de plusieurs lignes.\nConfigurable pour afficher \u00E9galement l'ETA et la vitesse de t\u00E9l\u00E9chargement.
+configureWizard.transfer.maxDownloads=T\u00E9l\u00E9chargements Max
+wizard.browse=Rechercher...
+GeneralView.title.short=G\u00E9n\u00E9ral
+FileItem.storage.linear=Lin\u00E9aire
+configureWizard.nat.ok=OK \!
+Button.back=Retour
+dhttracker.tracklimitedwhenonline=Cependant, effectue un faible suivi des ressources lorsque Vuze\u2122 est en ligne pour peupler une contre-population
+ConfigView.section.security.publickey=Cl\u00E9 publique
+MainWindow.menu.transfers.resumetransfers=&Reprendre
+ConfigView.label.playdownloadfinished=Jouer un son quand un t\u00E9l\u00E9chargement se termine
+FileItem.read=Lecture
+TableColumn.header.commenticon.info=Affiche l'ic\u00F4ne si le t\u00E9l\u00E9chargement a un commentaire d\u00E9finie par l'utilisateur
+splash.loadingTorrent=Chargement du Torrent
+GenericText.column=colonne
+ConfigView.section.ipfilter.enable=Appliquer le filtre
+MyTorrentsView.menu.setCategory.add=&Ajouter une cat\u00E9gorie..
+popup.closing.in=Fermeture automatique de la fen\u00EAtre dans %1 seconde(s)
+MagnetPlugin.private_torrent=<torrent priv\u00E9>
+pairing.status.disabled=D\u00E9sactiver
+torrent.fix.corrupt.result.nothing=Le torrent semble valide \!
+TableColumn.header.AzProduct.info=R\u00E9seau de contenu d'o\u00F9 est issue le torrent
+plugins.basicview.status=Statut\:
+label.test.internet=Testez votre connexion internet
+azbuddy.ui.table.msg_queued=En file d'attente
+mdi.entry.dvdburn=Gravure de DVD
+configureWizard.nat.sharePort=N'utiliser qu'un seul port entrant partag\u00E9 pour tous les torrents
+FilesView.pieces=Pi\u00E8ces
+ManagerItem.paused=En Pause
+MainWindow.menu.view.irc=&IRC
+PiecesView.\#=\#
+DonationWindow.noload.text=\u00C9chec du chargement de la fen\u00EAtre de don. Merci de r\u00E9essayer plus tard.
+MainWindow.sr.status.tooltip.ok=Taux de partage %1 OK
+Torrent.create.progress.cancelled=Op\u00E9ration annul\u00E9e
+ConfigView.label.subdir_is_in_default=Lors de l'examen, si les t\u00E9l\u00E9chargements existent dans un r\u00E9pertoire par d\u00E9faut, examiner \u00E9galement les sous-r\u00E9pertoires
+window.uiswitcher.ClassicUI.title=Interface classique
+ConfigView.section.style.showProgramIcon=Afficher l'ic\u00F4ne du programme dans la colonne nom
+MainWindow.menu.file.open.vuze=Fichier Vuze\u2122
+ConfigView.section.queue.downloading={ManagerItem.downloading}
+MagnetPlugin.use.md.download.delay=\td\u00E9lai [secs]
+ConfigView.label.stopAfterMinutes=Une fois en mode source, arr\u00EAter apr\u00E8s
+dht.execute=Ex\u00E9cuter
+PiecesView.size=Taille
+library.name._classic=Mes Torrents
+MainWindow.dialog.exitconfirmation.title=Fermer Vuze\u2122 ?
+device.wiki=Wiki de conseils et d'astuces...
+v3.MainWindow.menu.view.searchbar=Barre de Recherche
+Trackers.column.type=Type
+core.not.available=Vuze\u2122 est encore en cours d'initialisation, merci de r\u00E9essayer lorsqu'il aura termin\u00E9
+GeneralView.label.trackerscrapeupdate=Scrape Tracker
+ConfigView.section.pluginslist=Liste
+PeersGraphicView.title.full=Essaim
+MyTrackerView.badnat=NAT mal configur\u00E9
+iconBar.host.tooltip=H\u00E9berger
+Column.seedspeers.started.noscrape=%1
+v3.MainWindow.menu.library=&Biblioth\u00E8que
+Peers.column.Protocol=Protocole
+CacheView.speeds.title=Taux de donn\u00E9es
+window.uiswitcher.NewUI.text=* Recommand\u00E9 pour touts les utilisateurs.\n\n* Facile, interface graphique intuitive.\n* Riche en fonctionnalit\u00E9s et configurable.
+StartStopRules.FP0Peers=1\u00E8reP / 0 client
+Plugin.localtracker.networks=\    R\u00E9seaux locaux
+PeerManager.status.error=Erreur
+installPluginsWizard.file.file=Fichier \:
+PeersView.S.info=Ignor\u00E9 (Snubbed)\: Un client peut \u00EAtre "ignor\u00E9" manuellement, ou automatiquement (s'il n'envoie pas des donn\u00E9es assez rapidement).
+Scrape.status.scraping.queued=Scraping en attente...
+ConfigView.section.style.extendedErase=Dessiner une grille et remplir les espaces vides
+progress.window.msg.progress=Merci de patienter jusqu'\u00E0 la fin de l'op\u00E9ration
+MainWindow.menu.advanced_tools=Avanc\u00E9
+wizard.newtorrent.byo.addcontainer.text=Saisir le nom du conteneur tel qu'il appara\u00EEt dans le torrent
+quick.view.scheduled.text=Le fichier s\u00E9lectionn\u00E9 est prioritaire, il sera automatiquement ouverte pour l'affichage une fois termin\u00E9.
+DHTView.general.reachable=Accessible\u00A0\:
+MyTorrentsView.menu.setSpeed.unlimit=Pas de limite
+IPChecker.external.addressextracted=Adresse IP extraite
+ConfigView.label.seeding.ignoreShareRatio=Ignorer les torrents avec un taux de partage de
+TorrentOptionsView.param.reset.stats=R\u00E9initialisation des statistiques de transfert de torrents \u00E0 z\u00E9ro
+Peers.column.DLedFromOthers=Des autres
+ConfigView.section.interface.cleartrackersbutton=Effacer
+ConfigView.section.tracker.announcescrapepercentage=Intervalle de "Scrape" comme %age de l'annonce\ne.g. 200 \= 2\:1. (0 \= laisser le client d\u00E9cider)
+ConfigView.tb.delete.content=Supprimer sans demander
+MySharesView.menu.remove=Enlever
+DHTView.operations.title=D\u00E9tails d'op\u00E9ration
+ConfigView.section.ipfilter=Filtres IP
+DHTView.activity.status.true=En attente
+azbuddy.nickname=Votre surnom
+ConfigView.section.tracker.udpversion=Version du protocole UDP (1 ou 2)
+ConfigView.section.file.friendly.hashchecking=V\u00E9rification du hash moins intensive
+ConfigView.section.style.doNotUseGB=Ne pas utiliser l'unit\u00E9 Go
+installPluginsWizard.list.loaded=Veuillez choisir les plugins \u00E0 installer.
+Security.jar.tools_not_found=La signature du JAR a \u00E9chou\u00E9e - 'tools.jar' introuvable dans %1. Se reporter \u00E0 Options/s\u00E9curit\u00E9 pour plus d'information.
+upnp.alert.mappingok=UPnP\: Mapping '%1' \u00E9tabli
+TableColumn.header.file_eta.info=Temps estim\u00E9 avant que le fichier ait termin\u00E9 le t\u00E9l\u00E9chargement
+configureWizard.nat.ko=Erreur NAT
+Button.goLibrary=Acc\u00E9der \u00E0 {library.name}
+ManagerItem.high=Haute
+ConfigView.section.tracker.client.exclude_lan=Exclure les statistiques du transfert de donn\u00E9es LAN
+stats.longterm.group=\u00C0 long terme
+upnp.alert.mappinggrabbed=UPnP\: Mapping '%1' \u00E9tabli - \u00E0 partir de '%2'
+download.removerules.unauthorised.info=Les torrents non autoris\u00E9s sont ceux qui contiennent dans la \u00AB\u00A0r\u00E9ponse d'erreur\u00A0\u00BB\u00A0\: \u00AB\u00A0not authoris(z)ed\u00A0\u00BB ou \u00AB\u00A0unauthoris(z)ed\u00A0\u00BB.
+MainWindow.menu.transfers.resumetransfers.keybinding=Meta+R
+ConfigView.text.ignoreRule=Ignorer la r\u00E8gle
+ConfigView.section.sharing.torrentcomment=Commentaire pour les torrents g\u00E9n\u00E9r\u00E9s
+ConfigView.label.checkonstart=V\u00E9rifier les mises \u00E0 jour au d\u00E9marrage
+MyTorrentsView.menu.explore._mac=Montrer dans le Finder
+library.all.header.p=%1 \u00E9l\u00E9ments\: %2 actifs
+ConfigView.section.tracker.passwordenabletorrent.info=N\u00E9cessite un client Bittorrent adapt\u00E9 (e.g. Vuze\u2122)
+br.restore.info=Restaurer votre configuration \u00E0 partir d'une sauvegarde
+ConfigView.label.maxdownloads=Nombre de t\u00E9l\u00E9chargements simultan\u00E9s
+UpdateMonitor.messagebox.restart.title=Mise \u00E0 jour logicielle
+dlg.auth.cancelled=Code d'activation annul\u00E9
+MyTrackerView.status.stopped=Arr\u00EAt\u00E9
+wizard.close.confirmation=Confirmation
+FilesView.menu.setpriority.numeric=Num\u00E9rique ...
+ConfigView.section.transfer.autospeed.tooltip=Param\u00E8tres sp\u00E9cifiques au d\u00E9bit automatique
+subscriptions.listwindow.loadingtext=Recherche d'abonnements li\u00E9s \u00E0 '%1'
+UI.cannot_submit_blank_text=Vous devez entrer une valeur.
+updater.cant.write.to.app.title=Impossible d'\u00E9crire dans le dossier de l'application
+OpenTorrentWindow.addFiles.Folder=Ajouter &r\u00E9pertoire
+webui.bindip=Liaison IP - normalement non n\u00E9cessaire
+max.sr.window.title=Ratio Partag\u00E9 Cible
+PeersView.I2.info=Est-ce que le client est int\u00E9ress\u00E9 par vos pi\u00E8ces\u00A0?
+pairing.local.ipv6=Adresse locale IPv6
+pairing.local.ipv4=Adresse locale IPv4
+MainWindow.upgrade.tooltip.progressbar=\u00C9tat d'avancement du t\u00E9l\u00E9chargement
+MyTorrentsView.dialog.setNumber.download=t\u00E9l\u00E9chargement
+ConfigView.label.startminimized=Lancer minimis\u00E9
+TableColumn.header.upspeed=Envoie \u00E0
+iconBar.new.tooltip=Cr\u00E9er un torrent
+cat.options=Torrents actuels Options / Info...
+ActivityView.legend.trimmed=Tronqu\u00E9 (pointill\u00E9)
+SpeedTestWizard.set.upload.label=Limite de vitesse d'upload\:
+v3.MainWindow.text.my.profile=Mon Profil
+ConfigView.label.seeding.rankType.peerSeed.options=Options de "taux Clients/Sources"
+TableColumn.header.date_added.info=Date \u00E0 laquelle le torrent a \u00E9t\u00E9 ajout\u00E9
+pairing.status.noservices=Aucun service \u00E0 distance n'est activ\u00E9
+ConfigView.section.ipfilter.enablebanning=Bloquer les clients qui envoient constamment de mauvaises donn\u00E9es
+PiecesView.BlockView.Have=Pr\u00E9sente
+ConfigView.label.maxactivetorrents=Nombre total de torrents actifs [0\u00A0\: illimit\u00E9]\n
+MyTorrentsView.menu.edit_comment=\u00C9diter le commentaire
+PiecesView.availability=Disponibilit\u00E9
+MySharesView.type.file=Fichier
+TableColumn.header.status.info=\u00C9tat du torrent
+v3.topbar.menu.show.search=Rechercher
+pairing.group.explicit=Attributs explicites
+TableColumn.header.secondsdownloading.info=temps pass\u00E9 en t\u00E9l\u00E9chargement.
+MainWindow.upgrade.step2=\u00C9tape 2\: Fermeture de cette version et relance de la nouvelle
+label.original.file=Fichier d'origine
+MainWindow.upgrade.step1=\u00C9tape 1\: T\u00E9l\u00E9chargement de la nouvelle version
+ConfigView.section.tracker.natcheckenable=V\u00E9rifier les possibilit\u00E9s de connexion sur le "port entrant des donn\u00E9es" et rapporter les erreurs aux clients
+GeneralView.label.maxuploadspeed=Vit. Env. Max.
+ConfigView.label.maxdownloadspeed=ko/s vitesse globale maximale de t\u00E9l\u00E9chargement [0\u00A0\: illimit\u00E9e]
+rss.internal.test.url=Cliquez pour afficher la page d'accueil locale
+window.networkselection.title=S\u00E9lection r\u00E9seau
+PeersView.BlockView.Avail.Have=Les 2 ont
+device.error.copytonowrite='Copier vers le dossier' "%1" Non accessible en \u00E9criture
+ConfigureWizard.language.choose=Choisir une langue dans la liste suivante\:
+SpeedTestWizard.finish.panel.click.close=Vous en avez termin\u00E9 avec l'assistant de test de vitesse. Cliquez sur Fermer pour quitter.
+MainWindow.menu.quick_view=Aper\u00E7u rapide
+MagnetPlugin.contextmenu.exporturi=Copier l'URI Magnet dans le presse-papier
+devices.choose.device.title=S\u00E9lectionnez un p\u00E9riph\u00E9rique qui peut lire cette vid\u00E9o \:
+MainWindow.menu.file.open.torrentnodefault=Fichier .torrent (sans r\u00E9pertoire par d\u00E9faut)
+MyTrackerView.seeds=Sources
+ColumnSetup.filters=Filtres
+MainWindow.nat.status.ok=NAT OK
+Security.keystore.empty=La cl\u00E9 est vide. Veuillez cr\u00E9er un certificat auto-sign\u00E9 (voir Options > S\u00E9curit\u00E9) ou importer un certificat existant dans '%1'.
+CategoryAddWindow.message=Entrer un nom de cat\u00E9gorie
+GeneralView.label.private=Torrent priv\u00E9 \:
+ConfigView.unlimited=Illimit\u00E9
+ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=R\u00E8gle la taille du socket standard SO_SNDBUF (en octets), soit la taille de la fen\u00EAtre d'envoi TCP.\nVuze\u2122 laisse ce champ vide par d\u00E9faut, donc les valeurs par d\u00E9faut du syst\u00E8me d'exploitation sont utilis\u00E9es.\nNOTE\: Linux double la valeur indiqu\u00E9e.
+iconBar.stop.tooltip=Arr\u00EAter
+dht.reseed=Reseeder
+restart.error.fnf='%1' est introuvable dans '%2'
+v3.MainWindow.button.preview=Pr\u00E9visualiser
+AutoMigration.useralert=R\u00E9sultat de la migration automatique des fichiers et r\u00E9pertoires de configuration de l'utilisateur de Vuze\u2122\:\n%1\nToute migration \u00E9chou\u00E9e doit \u00EAtre faite manuellement.\r\nNE PAS OUBLIER DE METTRE \u00C0 JOUR VOS CHEMINS DE SAUVEGARDE DANS LA CONFIGURATION, S'ILS ONT \u00C9T\u00C9 MIGR\u00C9S \!
+statusbar.feedback=Envoyer le commentaire
+v3.menu.device.exploreTranscodes._mac=Afficher les fichiers dans le Finder
+LoggerView.includeOnly=N'afficher que les lignes correspondant \u00E0 cette expression r\u00E9guli\u00E8re\:
+plus.notificaiton.ExpiringEntry.s=Votre abonnement Vuze\u2122 Plus expire dans %1 jours\:<A %2> Renouveler maintenant</A>
+device.router.configure=Configurer l'UPnP
+plus.notificaiton.ExpiringEntry.p=Votre abonnement Vuze\u2122 Plus expire dans %1 jours\:<A %2> Renouveler maintenant</A>
+ConfigView.label.popupfilefinished=Montrer une alerte 'popup' quand un fichier est termin\u00E9
+ConfigView.section.tracker.server=Serveur
+v3.activity.header.vuze.news=Nouvelles de Vuze\u2122
+metasearch.addtemplate.title=Installer le mod\u00E8le de recherche ?
+plugin.aznetstatus.logfull=Journalisation compl\u00E8te
+dht.ipfilter.log=Journaliser les violations des filtres IP
+stream.analysing.media.preview=Analyse du m\u00E9dia (Mode de pr\u00E9visualisation)
+Scrape.status.nextScrapeAt='scrape' suivante \u00E0 %1
+Scrape.status.error=Erreurs 'Scrape'\:
+SystemTray.tooltip.seeding=%1 \u00A0Sources,\u00A0
+TableColumn.TorrentStream.tooltip.disabled='Lire maintenant' ne supporte pas les fichiers de ce type
+webui.passwordenable=Activer le mot de passe
+updater.progress.window.info=Appuyer sur 'Abandonner' pour mettre fin aux t\u00E2ches en cours.
+pairing.enable=Activer le jumelage entre Vuze\u2122 et d'autres applications ou interfaces
+fileDownloadWindow.title=Vuze\u2122 - T\u00E9l\u00E9chargeur de torrents
+MainWindow.upgrade.explanation=Cet assistant va t\u00E9l\u00E9charger la nouvelle version dans votre r\u00E9pertoire Vuze\u2122 et relancer le programme
+br.restore.folder.info=S\u00E9lectionnez le dossier contenant une sauvegarde pr\u00E9c\u00E9dente
+update.fail.app.changed=Vuze\u2122 doit \u00EAtre mis \u00E0 jour, mais cette t\u00E2che ne peut pas \u00EAtre effectu\u00E9e automatiquement car le nom de l'application a \u00E9t\u00E9 modifi\u00E9e \u00E0 '%1'.\n\nMerci de visiter le site 'http\://www.vuze.com/' et de t\u00E9l\u00E9charger le programme d'installation.
+jvm.max.direct.mem=Taille maximale de la m\u00E9moire 'direct'[vide\=d\u00E9faut, min\=%1]
+Scrape.status.error.invalid=R\u00E9ponse invalide.
+wizard.close=Fermer
+device.config.ms.maxlines=Nombre d'entr\u00E9es maximum \u00E0 afficher lors de l'exploration d'un serveur de m\u00E9dias
+ConfigView.label.ui_switcher_button=Afficher
+ConfigView.label.lh.prog=Programme
+FilesView.title.short=Fichiers
+jvm.options.summary=R\u00E9capitulatif des options explicites actuelles\:
+restart.error.denied=Acc\u00E8s refus\u00E9 lors de l'ex\u00E9cution de '%1'. Assurez-vous que vous disposez des droits pour ex\u00E9cuter ce programme.
+iconBar.open=Ajouter un Torrent
+ConfigView.label.minPeersToBoostNoSeeds.tooltip=Tout torrent sans source ou avec moins de sources que sp\u00E9cifi\u00E9\nsera plac\u00E9 en bas de file.
+devices.od.view.heading=T\u00E9l\u00E9chargements pr\u00E9vues pour le t\u00E9l\u00E9chargement hors ligne
+ConfigView.section.transfer.autospeed.network.info=Les limites ci-dessus sont normalement calcul\u00E9s automatiquement lors du t\u00E9l\u00E9chargement ou sont le r\u00E9sultat d'un test de vitesse. Si vous voulez sp\u00E9cifier manuellement les utiliser les options ci-dessous.\n\nLes limite autre que \u00ABfixe\u00BB seront, si n\u00E9cessaire, automatiquement ajust\u00E9es par la suite.\n\nSaisir une valeur, puis s\u00E9lectionnez son type. \u00C0 noter que les vitesses sont en %1.
+sharing.progress.cancel=Annuler
+label.indirect.connect=Connecter indirectement
+MagnetURLHandler.report.no_sources=aucunes sources trouv\u00E9s pour ce torrent
+Button.done=Termin\u00E9
+dht.reseed.port=Port
+MyTorrentsView.menu.movetorrent=D\u00E9placer le torrent...
+v3.MainWindow.menu.contentnetworks.about=\u00C0 propos de HD & R\u00E9seaux
+AdvRenameWindow.title=Renommer le t\u00E9l\u00E9chargement
+wizard.maketorrents.superseed=Utiliser le super-seeding
+MainWindow.menu.view.stats.keybinding=Meta+5
+SystemTray.tooltip.downloading=%1 \u00A0T\u00E9l\u00E9chargements\n
+importTorrentWizard.process.importfail.title=L'importation du torrent a \u00E9chou\u00E9
+device.config.autohide.old.devices=Masquer automatiquement les p\u00E9riph\u00E9riques qui n'ont pas \u00E9t\u00E9 vu r\u00E9cemment [jours, 0\: D\u00E9sactiv\u00E9]
+custom.settings.import.res.title=Importation de la configuration termin\u00E9
+ConfigView.label.userequestlimiting.tooltip=La limitation des demandes n'est pas aussi mod\u00E9r\u00E9 que la lectures diff\u00E9r\u00E9e, mais permet la priorisation du t\u00E9l\u00E9chargement en fonction de sa position dans la file d'attente et peut am\u00E9liorer les performances du r\u00E9seau
+CacheView.writes.toCache=Vers Cache
+SpeedTestWizard.abort.message.download.added=Le t\u00E9l\u00E9charger %1 a \u00E9t\u00E9 ajout\u00E9 durant de l'essai
+OpenTorrentFile.column.download.info=T\u00E9l\u00E9charger le fichier torrent\n Utilisez la barre espace pour cocher/d\u00E9cocher les cases lors d'une s\u00E9lection multiple
+DownloadActivityView.legend.down_smooth=Bas (Mod\u00E9r\u00E9)
+proxy.info.title=Information de Proxy
+MyTorrentsView.menu.recheck=Forcer une re-&v\u00E9rification
+UpdateProperty.title=Mise \u00E0 jour de propri\u00E9t\u00E9
+TableColumn.header.swarm_average_speed.info=La vitesse moyenne des pairs de l'essaim
+PeerSocket.unknown_shadow_style=Inconnu %1 %2
+Button.createNewSubscription=Nouvel Abonnement
+MagnetPlugin.use.lookup.service=Utilisez le service de recherche secondaire de Vuze\u2122 si la recherche de lien magnet par DHT a \u00E9chou\u00E9
+mb.azmustclose.title=Erreur de d\u00E9marrage
+ConfigView.label.maxseedspertorrent=Nombre maximum de seed par torrent, par d\u00E9faut\: [0\: illimit\u00E9]
+MyTorrentsView.menu.thisColumn.remove=Enlever cette colonne
+download.removerules.name=R\u00E8gles de suppression
+label.rss=RSS
+PeerManager.status.offline=Erreur de connexion
+br.backup.progress=R\u00E9sultats de sauvegarde / restauration
+v3.MainWindow.search.tooltip=Entrez les crit\u00E8res de votre recherche, lien Magnet, empreinte hash ou URL de torrent et appuyez sur 'Entr\u00E9e' \!
+menu.min.share.ratio2=D\u00E9finir le taux de partage minimum...
+TagStatsView.title.full=Activit\u00E9 des cat\u00E9gories
+config.changes.title=Changements de la configuration
+TableColumn.header.savepath=Chemin de sauvegarde
+GeneralView.label.uploadspeed=Vitesse d'envoi\u00A0\:
+MyTorrentsView.menu.networks=R\u00E9seaux
+ConfigView.label.watchtorrentfolderinterval=Intervalle
+Button.install={swt.install.window.ok} 
+ConfigView.section.connection.group.http.info=Support pour le 'seeding' HTTP .
+ConfigView.label.opendialog=Ouvrir automatiquement l'assistant de mise \u00E0 jour quand une mise \u00E0 jour est disponible
+device.lastseen=Vu pour la derni\u00E8re fois
+TableColumn.header.networks=R\u00E9seaux
+azbuddy.ui.add=Ajouter
+GeneralView.label.hashfails=Pi\u00E8ce(s) invalide(s)\u00A0\:
+ConfigView.pluginlist.shared=partag\u00E9
+ConfigView.section.security.restorekeys.button=Restaurer
+TableColumn.header.activityNew=Nouveau
+ColumnSetup.proficiency=Comp\u00E9tence\:
+FilesView.skip.confirm.delete.text=Tronquer le fichier \u00AB\u00A0%1\u00A0\u00BB pour sauver de l'espace\u00A0?
+ConfigView.section.style.separateProtDataStats=Afficher de fa\u00E7on distinctes les statistiques de donn\u00E9es et de protocole comme ceci, 'donn\u00E9es (protocole)'
+configureWizard.welcome.usermodes=Ce r\u00E9glage du niveau utilisateur d\u00E9termine le niveau des options accessibles dans Outils > Options. Il est recommand\u00E9 de choisir avec sagesse.
+plugin.install.class_version_error=Ce plugin n\u00E9cessite une version plus r\u00E9cente de la machines virtuelle Java\u2122 pour fonctionner.
+configureWizard.welcome.message=Cet Assistant va vous permettre de configurer Vuze\u2122 pour un usage courant. Vous pouvez modifier plus en profondeur la configuration dans le menu\:\n\nOutils > Options...
+window.update.noupdates.beta.text=Il n'y a pas de nouvelles mises \u00E0 jour disponibles pour vous.\n\nVous utilisez la derni\u00E8re version Beta stable (%1)\n\nPour plus d'informations sur les versions stables et instables, visitez le site du <a href\="http\://dev.vuze.com/">programme Beta</a>.
+security.crypto.persist_for.week=1 semaine
+MainWindow.nat.status.probok=NAT OK\u00A0?
+ConfigView.section.connection.advanced.read_select_min=Attente minimum de la s\u00E9lection de lecture (milliseconde, par d\u00E9faut %1)
+SpeedTestWizard.abort.message.entered.error=\u00C9tat \u200B\u200Bd'erreur du t\u00E9l\u00E9chargement de test indiqu\u00E9e '%1'
+devices.state=\u00C9tat
+speedtest.wizard.test.mode.up=partage
+Formats.units.alot=Beaucoup\u00A0\!\!\!
+CacheView.reads.amount=Quantit\u00E9
+ConfigTransferAutoSpeed.add.comment.to.log.group=Ajouter un commentaire dans le journal de d\u00E9bogage
+OpenTorrentTorrent.column.\#=\#
+TableColumn.header.peers.info=\# de client(s) connect\u00E9(s) \u00E0 (\# de client(s) total)
+Button.next=Suivant
+ColumnProgressETA.showSpeed=Afficher la vitesse
+Torrent.create.progress.piecelength=Taille d'une pi\u00E8ce\:
+dialog.uiswitcher.restart.text=Vuze\u2122 doit red\u00E9marrer afin de passer au nouveau mode de l'interface utilisateur.
+v3.iconBar.down.tooltip=Descendre\n169aintenez le bouton de la souris pour vous d\u00E9placer vers le bas
+devices.xcode.autoCopy.device=Copier automatiquement vers le p\u00E9riph\u00E9rique
+beta.wizard.forum=Utilisez les forums Vuze\u2122 pour proposer des modifications ou signaler un bug
+label.replace=Remplacer
+MainWindow.menu.help=Aid&e
+ConfigView.section.stats.xslfiledetails=Ajout\u00E9 aux stats gr\u00E2ce \u00E0 <?xml-stylesheet>
+window.updateswt.status.downloading=T\u00E9l\u00E9chargement de la derni\u00E8re version de SWT
+remote.pairing.subtitle=Vuze\u2122 \u00E0 distance vous donne le pouvoir de contr\u00F4ler Vuze\u2122 depuis n'importe quel ordinateur, navigateur mobile ou p\u00E9riph\u00E9rique Android.
+ConfigView.label.importdirectory=Dans le r\u00E9pertoire\u00A0\:
+DownloadManager.error.fileempty=Fichier .torrent vide
+MainWindow.menu.community.blog=&Blog
+devices.xcode.setcopyto.title=Choisissez l'emplacement pour la copie
+TableColumn.header.md5.info=Empreinte MD5 du fichier (doit \u00EAtre enti\u00E8rement t\u00E9l\u00E9charg\u00E9, cliquez pour calculer)
+TableColumn.header.name=Nom
+ConfigView.label.showpopuponclose=Faire apparaitre une fen\u00EAtre de confirmation lors de la fermeture d'un torrent avec un taux de partage inf\u00E9rieur \u00E0 1
+PeerManager.status.ps_disabled=La source des pairs de type tracker est d\u00E9sactiv\u00E9
+MainWindow.menu.view.stats=&Statistiques
+wizard.multitracker.edit.text.msg=Entrez un tracker par ligne. S\u00E9parez les diff\u00E9rents groupes (niveaux) par une ligne blanche.
+ConfigView.higher.mode.available=\t
+PeersView.download.info=Votre t\u00E9l\u00E9chargement global depuis le pair.
+seedmore.title=Le torrent a besoin de plus de sources
+ConfigTransferAutoSpeed.algorithm.selector=S\u00E9lecteur de d\u00E9bit automatique
+MyTorrentsView.menu.thisColumn.sort=C&lasser
+window.uiswitcher.NewUI.title=Vuze\u2122
+ConfigView.section.mode.beginner.text1=Tout ce dont vous avez besoin pour t\u00E9l\u00E9charger des torrents - Utilisez ce mode pour g\u00E9rer simplement vos torrents.
+Menu.show.torrent.menu=Afficher le menu Torrents
+xfs.allocation.xfs_io.not.found=L'allocation de fichier pour syst\u00E8me de fichiers XFS a \u00E9chou\u00E9 parce que /usr/sbin/xfs_io n'a pu \u00EAtre lanc\u00E9. Assurez-vous qu'il est correctement install\u00E9 sur votre syst\u00E8me. L'erreur originelle est \: "%1".
+SpeedTestWizard.stage.message.starting=d\u00E9marrage du test...
+MyTorrentsView.dialog.setFilter.text=Les rubriques %1 seront filtr\u00E9es par le texte que vous sp\u00E9cifiez ci-dessous. Utilisez le symbole '|' pour filtrer avec plusieurs expressions.
+subscriptions.listwindow.name=Nom
+SystemTray.menu.pausetransfers=Pause (tous transferts)
+openUrl.url=URL\:
+sr_prog.window.title=Intervalle de progression
+wizard.newtorrent.byo.info=D\u00E9posez une s\u00E9lection de fichiers et/ou de r\u00E9pertoires dans la zone ci-dessous pour cr\u00E9er un torrent. Double-cliquez ou appuyez sur F2 pour modifier les noms.
+label.rename=Renommer %1
+MainWindow.menu.view.configuration=O&ptions...
+Button.bar.edit=Modifier
+MainWindow.dht.status.failed=\u00C9chec DHT
+ConfigView.label.defaultsavepath=R\u00E9pertoire de sauvegarde des donn\u00E9es par d\u00E9faut
+OpenTorrentWindow.mb.notValid.title=\u00C9chec de l'ouverture du torrent
+label.script.to.run=Script \u00E0 ex\u00E9cuter
+DiskManager.alert.movefilefails=Erreur en d\u00E9pla\u00E7ant les fichiers termin\u00E9s\nLe d\u00E9placement du fichier %1 a \u00E9chou\u00E9, %2
+ConfigView.label.dm.dblclick=Double-cliquez dans les vues torrent\:
+Utils.link.visit=Merci de visiter
+device.od.space=Espace disponible
+FilesView.crc32.calculate=Calculez la/les somme(s) de contr\u00F4le CRC-32
+ConfigView.label.stop.QuitVuze=Fermer Vuze\u2122
+label.untagged=Non \u00E9tiquet\u00E9s
+installPluginsWizard.list.version=Version
+ConfigView.section.tracker.username=Nom d'utilisateur
+ConfigView.section.ipfilter.autoload.info=Prise en charge des formats DAT (eMule), P2P (PeerGuardian, SPList), et P2B v1, 2,3 (PeerGuardian 2). Le fichier peut \u00EAtre local ou distant (URL), zip, gzip ou texte brut. Les URLs seront automatiquement ret\u00E9l\u00E9charger apr\u00E8s 7 jours, alors que les fichiers seront recharger apr\u00E8s une minute avant d'\u00EAtre remplac\u00E9.
+sidebar.header.discovery=D\u00E9couverte de contenu
+importTorrentWizard.torrentfile.message=S\u00E9lectionner le fichier torrent \u00E0 importer
+MainWindow.menu.speed_limits.view=Voir...
+ConfigView.section.mode.intermediate.wiki.host=H\u00E9berger des fichiers
+MainWindow.upgrade.error.downloading.hint=Erreur\:\tIncapable de t\u00E9l\u00E9charger la nouvelle version, veuillez faire la mise \u00E0 jour manuellement
+MyTorrentsView.filter.tooltip=Utilisez le symbole '|' pour filtrer plusieurs expressions.\nUtilisez Ctrl+X pour commuter entre le mode RegEx et le mode de recherche normal.\nEn mode RegEx, pr\u00E9fixez avec \:\n\t'\!' pour 'non'\n\t'c\:' pour rechercher dans le commentaires\n\t't\:' pour rechercher dans les trackers\n\t'f\:' pour rechercher dans les noms de fichiers
+ConfigView.section.language=Langue
+ConfigView.label.userSuperSeeding=Utiliser le mode Super-Source
+TableColumn.header.smoothup.info=D\u00E9bit d'upload mod\u00E9r\u00E9 {smooth.config}
+PeersView.connected_time=Temps connect\u00E9
+fileDownloadWindow.retry=R\u00E9-essai
+openUrl.referrer=URL de la page r\u00E9f\u00E9r\u00E9e \:
+DHTView.general.title=G\u00E9n\u00E9ral
+PiecesView.legend.incache=Donn\u00E9es dans le cache
+SpeedView.stats.estdowncap=Limite de t\u00E9l\u00E9chargement \:
+TableColumn.header.comment=Commentaire
+PeersView.source=Origine
+GeneralView.label.maxuploadspeed.tooltip=vitesse maximale d'envoi [0 \: illimit\u00E9e]
+security.crypto.persist_for.forever=Toujours
+ConfigView.label.hap.tooltip=Masquer un \u00E9l\u00E9ment termin\u00E9
+ConfigView.section.connection.group.networks=R\u00E9seaux
+MainWindow.menu.file.exit.keybinding=Alt+F4
+devices.comp.missing='Vuze\u2122 support' n'est pas install\u00E9
+SpeedTestWizard.test.panel.abort=Abandonner
+ManagerItem.queued=En attente
+ConfigView.section.file.nativedelete._mac=Utiliser la corbeille en supprimant des fichiers
+subscript.all.subscribed=Vous \u00EAtes abonn\u00E9 \u00E0 ce contenu
+DHTView.transport.title=D\u00E9tails de transport
+TableColumn.header.completed.info=\# nombre de pairs qui ont termin\u00E9 le t\u00E9l\u00E9chargement du torrent tel que rapport\u00E9 par le tracker
+subscriptions.view.title=Abonnements
+CacheView.speeds.reads=Lectures
+ConfigView.label.queue.debuglog.info=Ajoute les informations de d\u00E9bogage \u00E0 propos de la file d'attente\ndans la console et dans le journal. Quoique cryptiques,\nces informations vous donnent l'\u00E9tat des torrents\net pourquoi ils sont arr\u00EAt\u00E9s/refusent de d\u00E9marrer.
+PiecesView.legend.written=\u00C9crites
+PiecesView.BlockView.Header=%1 colonne(s), %2 ligne(s), %3 pi\u00E8ces
+PiecesView.writers=Contributeurs au bloc
+ConfigView.section.transfer.autospeed.maxinc=%1 augmentation maximum par cycle
+ConfigView.label.minannounce=Temps minimum entre les annonces du tracker en secondes
+authenticator.details=D\u00E9tails
+ConfigView.section.connection.group.peersources.info=S\u00E9lectionner les origines permises par d\u00E9faut pour les connexions clients
+configureWizard.file.browse=...
+OpenTorrentOptions.header.peeroptions=Tracker, Pairs & Options de connexion
+MyTorrentsView.menu.moveEnd=&Bas
+ConfigView.pluginlist.unloadSelected=D\u00E9charger la s\u00E9lection
+device.error.mountrequired="%1" a besoin d'\u00EAtre mont\u00E9 sur votre p\u00E9riph\u00E9rique
+dht.reseed.label=Normalement, le reseeding de la base de donn\u00E9es distribu\u00E9e n'est pas n\u00E9cessaire. Toutefois , si le nombre de contacts est faible ce qui peut \u00EAtre utilis\u00E9 pour la r\u00E9insertion. Laissez ce champ vide pour d\u00E9marrer les pairs connect\u00E9s ou entrer l'IP et le port pour d\u00E9marrer explicitement un pair connu.
+MainWindow.menu.file.import.keybinding.mac=Meta+Shift+I
+tag.show.overview=Afficher la pr\u00E9sentation des cat\u00E9gories...
+wizard.next=Suivant >
+MainWindow.status.tooOld=est vieux, veuillez le mettre \u00E0 jour.
+TableColumn.header.SpeedGraphic=Vitesse
+ConfigView.section.interface.clearsavepaths=Effacer les chemins de sauvegarde r\u00E9cents
+TableColumn.header.filecount=Fichiers
+SpeedView.stats.now=Maintenant
+ConfigView.section.file.bgdefaultdir.ask=Meilleure estimation par d\u00E9faut
+ConfigView.section.mode.advanced.text=Donne acc\u00E8s aux r\u00E9glages r\u00E9seau.\nUtilisez ce mode si vous savez ce que sont MTU ou I/O non bloquants...
+MyTrackerView.name=Nom
+props.window.title=Propri\u00E9t\u00E9s pour '%1'
+AlertMessageBox.information=Information
+device.is.disabled=Le p\u00E9riph\u00E9rique est d\u00E9sactiv\u00E9
+TableColumn.header.crc32.info=Somme de contr\u00F4le CRC-32 du fichier (doit \u00EAtre enti\u00E8rement t\u00E9l\u00E9charg\u00E9, cliquez pour calculer)
+ConfigView.section.connection.advanced.IPDiffServ.tooltip=D\u00E9finit la partie DiffServ de champs TOS (type-of-service) dans l'en-t\u00EAte IP pour les paquets sortants.\nLes valeurs hexad\u00E9cimales peuvent \u00EAtre sp\u00E9cifi\u00E9es en les faisant pr\u00E9c\u00E9der par '0x', par exemple, '0x10'\nPar d\u00E9faut, Vuze\u2122 laisse cette option ind\u00E9finie, ce qui signifie que les valeurs par d\u00E9faut du syst\u00E8me d'exploitation sont utilis\u00E9s\nREMARQUE\: Le r\u00E9 [...]
+v3.MainWindow.menu.view.pluginbar=Barre de Plugin
+ConfigView.label.noportannounce=Ne pas pr\u00E9ciser le port d'\u00E9coute sur le tracker (cela n'affecte pas PEX, DHT)
+OpenTorrentWindow.mb.invaliddefsave.title=L'emplacement d'enregistrement invalide
+azbuddy.protocolspeed=KB/s max de surcharge de protocole ami
+view.waiting.core=La vue sera disponible une fois que Vuze\u2122 sera charger int\u00E9gralement...
+ConfigView.section.transfer.autospeed.resetnetwork=R\u00E9initialiser les d\u00E9tails sur le r\u00E9seau
+ConfigView.label.lazybitfield=Utiliser le bitfield "paresseux" (aide \u00E0 seeder sur les r\u00E9seaux bloquant par d\u00E9tection de bitfield)
+ConfigView.section.file.perf.cache.enable.write=Mettre le t\u00E9l\u00E9chargement en cache pour r\u00E9duire les \u00E9critures disque et les lectures disque pour la v\u00E9rification de pi\u00E8ce.
+OpenTorrentWindow.mb.askCreateDir.text=Le r\u00E9pertoire de destination '%1' n'existe pas.\n\nLe cr\u00E9er maintenant ?
+MagnetPlugin.report.error=Erreur %1
+ConfigView.label.ui_switcher=Afficher le s\u00E9lecteur d'interface graphique Vuze\u2122
+MainWindow.nat.status.bad=Bloqu\u00E9 par pare-feu
+Scrape.status.scraping=En 'Scrape'..
+SpeedTestWizard.stage.message.connect.stats=Statistiques de connexion\: pairs\=%1, down_ok\=%2, up_ok\=%3
+azbuddy.ui.menu.cat.set_msg=S\u00E9parez la liste des cat\u00E9gories par des virgules, ou marquez "Tous"
+MagnetPlugin.report.ddb_disabled=DDB est d\u00E9sactiv\u00E9
+SpeedTestWizard.abort.message.execution.failed=Ex\u00E9cution du test \u00E9chou\u00E9
+TableColumn.header.DateFileCompleted.info=Date d'ach\u00E8vement du fichier la plus r\u00E9cente dans le torrent
+Wizard.Subscription.title=Abonnement
+Tracker.tooltip.MultiSupport=Ce tracker supporte plusieurs hash par requ\u00EAte.
+unix.script.new.title=Nouveau script de d\u00E9marrage de Vuze\u2122 disponible
+upnp.mapping.dhtudp=Base de donn\u00E9es distribu\u00E9e
+azbuddy.os_away=Absent
+ConfigView.section.file.rename.incomplete=Ajouter un suffixe aux fichiers incomplets
+MainWindow.menu.community=&Communaut\u00E9
+TableColumn.header.Thumbnail=Ic\u00F4ne
+TableColumn.header.azsubs.ui.column.subs_link.info=Associ\u00E9s \u00E0 des abonnements
+ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Voir tous progression du t\u00E9l\u00E9chargement de fichier dans la barre d'\u00E9tat au lieu d'une bo\u00EEte de dialogue
+dlg.auth.install.progress=Installation %1 de composants...
+wizard.multitracker.template.title=\u00C9diteur de mod\u00E8le de Tracker
+menu.max.share.ratio2=D\u00E9finir le taux de partage cible...
+ConfigTransferAutoSpeed.auto.speed.neural=Neuronal (Gudy Alpha)
+TableColumn.header.trackername.info=Nom du tracker bas\u00E9 sur l'URL d'annonce
+jvm.info=Si les options sont modifi\u00E9es, un red\u00E9marrage de Vuze\u2122 est n\u00E9cessaire. *** Attention - une modification incorrecte des options de la machines virtuelle Java\u2122 peut provoquer des r\u00E9sultats inattendus, voir l'\u00E9chec du d\u00E9marrage de Vuze\u2122.***\n
+SpeedTestWizard.abort.message.unsupported.type=Type de test non pris en charge le \!
+plugins.basicview.config=Config
+SpeedView.stats.asn=R\u00E9seau \:
+StartStopRules.ratioMet=Taux C\:S OK
+ConfigView.section.tracker.pollintervalmin=Minimum
+PeersView.title.full=D\u00E9tails
+wizard.multitracker.edit.name=Nom
+ConfigView.section.plugins.dhttracker=Tracker distribu\u00E9
+TableColumn.header.networks.info=R\u00E9seaux permis pour les transmissions de donn\u00E9es client-client
+TableColumn.header.trackernextaccess=Prochain acc\u00E8s tracker
+subscriptions.column.nb-results=R\u00E9sultats
+TableColumn.header.CountryCode.info=Code Pays (ISO 3166) du client
+installPluginsWizard.installMode.shared=Installe le(s) plugin(s) pour tous les utilisateurs (partag\u00E9)
+wizard.previous=< Retour
+subs.prop.template=Mod\u00E8le
+Button.unmark=Enlever
+ConfigView.label.maxuploadspeedseeding=Taux diff\u00E9rent quand seulement en source
+update.instance.install=V\u00E9rification des installations
+OpenTorrentWindow.mb.existingFiles.title=Fichier(s) d\u00E9j\u00E0 existant(s) \!
+natpmp.enable=Activer (notez qu'il doit \u00E9galement \u00EAtre activ\u00E9 dans la configuration de l'Airport pour que cela fonctionne)
+ConfigView.section.file.defaultdir.bestguess=Utilisez le meilleure emplacement par d\u00E9faut lors du choix de r\u00E9pertoire de sauvegarde
+cat.autoxcode=D\u00E9tection automatique
+MyTorrentsView.menu.advancedmenu=Avanc\u00E9
+stats.long.weekstart=La semaine comptable commence le \:
+label.content=Contenu
+v3.MainWindow.tab.events=Activit\u00E9s
+CacheView.speeds.fromFile=Depuis/Vers Fichier
+v3.iconBar.up.tooltip=Monter\nMaintenez le bouton de la souris pour vous d\u00E9placer vers le haut
+ConfigView.section.tracker.publishenabledetails=Publier le fichier torrent et ses d\u00E9tails
+openUrl.url.info=Supporte http, https, magnet et l'infohash brut en hexa
+FileProgress.deleted=Supprim\u00E9
+TrackerView.title.short=Sources
+ConfigView.section.tracker.sslport=Activer le tracker sur le port HTTPS
+ConfigView.section.transfer.autospeed.maxupload.tooltip=Le d\u00E9bit d'upload ne sera pas augment\u00E9e automatiquement au-del\u00E0 de cette limite
+ColumnProgressETA.showETA=Afficher ETA
+label.aggregate.info=Informations group\u00E9es
+ConfigView.section.stats.savefreq=Fr\u00E9quence de sauvegarde
+devices.info.copypending3=%1 fichier(s) en attente de copie - Activez la copie automatique ou s\u00E9lectionnez 'Copier manuellement'
+devices.info.copypending2=%1 fichier(s) en attente de copie, Connectez votre p\u00E9riph\u00E9rique
+wizard.title=Cr\u00E9er un torrent
+Plugin.pluginupdate.enablecheck=Activer la v\u00E9rification de mise \u00E0 jour des plugins
+installPluginsWizard.installMode.info.title=Info
+dht.execute.info=Appuyer pour ex\u00E9cuter la commande
+PiecesView.DistributionView.weDownload=Pi\u00E8ces que vous t\u00E9l\u00E9chargez
+ConfigView.label.seeding.firstPriority.seedingMinutes=Un temps \u00E9coul\u00E9 depuis le passage de "t\u00E9l\u00E9chargement" \u00E0 "source"
+ConfigView.label.stop.downcomp=Lorsque le t\u00E9l\u00E9chargement est termin\u00E9
+OpenTorrentWindow.addPosition.last=En dernier
+PiecesView.legend.downloaded=T\u00E9l\u00E9charg\u00E9e, \u00E9criture en attente
+ConfigView.label.maxuploadsseeding=quand en source seulement
+ConfigView.section.tracker.tcpnonblocking=Utiliser des E/S non bloquantes pour le tracker TCP. Cette option n\u00E9cessite de faire tourner le tracker sur un autre port. Exp\u00E9rimental\u00A0\!
+azbuddy.ui.table.rem_cat=Cats entrant
+ConfigView.section.file.torrent.ignorefiles=Fichiers \u00E0 ignorer en cr\u00E9ant des torrents\ne.g. .DS_Store;Thumbs.db
+sidebar.header.vuze=Vuze\u2122
+tps.lan.details=%1 clients locaux d\u00E9couverts
+wizard.announceUrl=Annonce URL\:
+device.quit.transcoding.text='%1' est actuellement en transcodage pour '%2', compl\u00E9t\u00E9 \u00E0 %3%.\nSi vous quitter maintenant vous devrez recommencer depuis le d\u00E9but.
+platform.win32.baddll.winsflt=PureSight Internet Content Filter
+TagRenameWindow.message=Entrez un nouveau nom pour la cat\u00E9gorie
+Button.reset=R\u00E9initialiser
+ConfigView.upload.abbreviated=U\:
+metasearch.addtemplate.dup.desc=Le mod\u00E8le de recherche %1 est d\u00E9j\u00E0 install\u00E9
+MagnetPlugin.report.md.starts=T\u00E9l\u00E9chargement des m\u00E9tadonn\u00E9es cr\u00E9\u00E9
+CacheView.title.full=Cache
+ConfigView.label.serverport.tooltip=Le port doit \u00EAtre entre 1 et 65535, et diff\u00E9rent de 6880 que Vuze\u2122 utilise en interne.
+azbuddy.tracker.bbb.status.nli=Connexion Requise
+device.error.copytonotset='Copier vers le dossier' Non d\u00E9fini
+devices.restrict_access=Restreindre l'acc\u00E8s...
+configureWizard.nat.testing=Test du port
+device.import.dup.desc=Le p\u00E9riph\u00E9rique '%1' est d\u00E9j\u00E0 pr\u00E9sent.
+SpeedTestWizard.test.panel.testfailed=\u00C9chec du test
+ConfigView.section.server.enablednsrecords=Activer la gestion des enregistrements des trackers DNS utilis\u00E9s pour att\u00E9nuer le risque de DDOS accidentelle
+webui.user=Nom d'utilisateur
+device.itunes.status.notrunning=iTunes n'est pas en cours d'ex\u00E9cution
+sidebar.LibraryDL=T\u00E9l\u00E9chargement
+PeersView.BlockView.title=D\u00E9tails de pi\u00E8ces
+MyTorrentsView.menu.host.error.title=L'h\u00E9bergement du torrent a \u00E9chou\u00E9
+iconBar.run=Lancer
+IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC
+UpdateWindow.status.failed=\u00C9chou\u00E9
+ConfigTransferAutoSpeed.skip.after.adjust=Passer apr\u00E8s l'ajustement\:
+MyTorrentsView.menu.setCategory=Classer dans
+dlg.auth.enter.denied=Le code d'activation actuel a \u00E9t\u00E9 refus\u00E9e.
+ConfigView.section.ipfilter.autoload.loadnow=Charger maintenant
+br.backup=Sauvegarde
+ConfigView.pluginlist.column.unloadable=Non chargeable
+PeersView.ip=IP
+ConfigView.section.security.resetcerts.error.title={ConfigView.section.security.resetkey.error.title}
+ConfigView.label.set_ui_transfer_speeds=Remplacer par des vitesses de transfert s\u00E9lectionnables
+ManagerItem.superseeding=Super-Source
+MainWindow.menu.file.create.keybinding=Meta+N
+azbuddy.ui.menu.chat=Discussion
+Scrape.status.cached=Scrape mis en cache
+UpdateWindow.header=Les composants suivants ont besoin d'une mise \u00E0 jour
+sidebar.LibraryCD=Termin\u00E9
+TagAddWindow.title=Ajouter une cat\u00E9gorie
+ConfigView.pluginlist.loadSelected=Charger la s\u00E9lection
+AdvRenameWindow.rename.torrent=Renommer le Torrent
+subscript.add.dup.title=Abonnement en double
+ConfigTransferAutoSpeed.ping.time.bad=Mauvais\:
+IrcClient.connecting=Se connecte \u00E0
+ConfigView.label.overrideip.tooltip=Informe le tracker d'une adresse IP diff\u00E9rente de celle depuis laquelle les paquets sortants arrivent. Laisser vide pour ne pas utiliser cette option.
+tps.type.dht=DHT
+ConfigView.section.tracker.sendpeerids=Envoyer le num\u00E9ro de client ("pair ID") aux t\u00E9l\u00E9chargeurs
+FileItem.storage.compact=Compact
+security.crypto.password2=Ressaisir le mot de passe
+TableColumn.header.comment.info=Commentaire d\u00E9finie par l'utilisateur pour le t\u00E9l\u00E9chargement
+ConfigView.boolean.ircsendinfo=Permettre l'envoi de vos r\u00E9glages aux op\u00E9rateurs\n du canal pour mieux vous aider
+MainWindow.menu.file=&Fichier
+FilesView.rename.confirm.delete.text=Confirmer la suppression du fichier original %1
+SpeedView.stats.autospeed=Vitesse d'upload automatique de (affichage plafonn\u00E9 \u00E0 %1 ms)
+MainWindow.menu.speed_limits.schedule.title=Planification et r\u00E9glages des limites de vitesses
+ConfigView.section.style.library={library.name}
+devices.cancel_xcode=Annuler la conversion
+ColumnSetup.availcolumns.filteredby=%1 colonne(s) disponible(s) filtr\u00E9e(s) par %2
+IrcClient.nowknown=est maintenant
+ConfigView.section.logging.enable=Activer la journalisation vers un fichier
+PiecesView.title.short=Pi\u00E8ces
+ClientStats.column.name={TableColumn.header.name}
+ConfigView.section.interface.alerts=Alertes
+TableColumn.header.totalspeed=Vit. Totale
+MainWindow.menu.file.share.file=&Fichier
+device.playnow.min_buffer=Quantit\u00E9 de la m\u00E9moire tampon apr\u00E8s laquelle la mise en m\u00E9moire tampon se reproduit [sec]
+MyTorrentsView.menu.edit_comment.enter.title=\u00C9diter le commentaire
+iconBar.share.tooltip=Partager du contenu
+UpdateWindow.restart=Red\u00E9marrer
+pairing.srp.info=Certaines applications distantes peuvent obtenir \u00E0 la fois la s\u00E9curit\u00E9 et la connectivit\u00E9 en utilisant le protocole 'Secure Remote Password' et, \u00E9ventuellement, des connexions proxy pour accro\u00EEtre cette connectivit\u00E9.\n\nConsultez la documentation de l'application \u00E0 distance pour voir si vous pouvez en b\u00E9n\u00E9ficier.
+OpenTorrentWindow.addPosition.first=En premier
+MainWindow.dialog.share.sharedir=S\u00E9lectionner le r\u00E9pertoire \u00E0 partager
+security.certtruster.no=Non
+ConfigView.section.tracker.pollintervalmax=Maximum
+delete.partial.files=Lors de la suppression d'un t\u00E9l\u00E9chargement de la biblioth\u00E8que, supprimez les fichiers marqu\u00E9s comme \u00ABne pas t\u00E9l\u00E9charger\u00BB ou \u00ABsupprimer\u00BB
+PeersView.statup.info=Valeur estim\u00E9 de la vitesse d'envoi d'un client
+MainWindow.menu.beta.on=Rejoindre le programme Beta...
+SpeedTestWizard.name.conf.level.med=Moyen
+MagnetPlugin.report.secondarylookup=Essayer avec le service de recherche secondaire
+upnp.refresh.button=Rafra\u00EEchir
+LoggerView.clear=&Effacer tout
+ConfigView.section.stats.exportfiles=Exporter les d\u00E9tails du fichier
+label.inbound=Entrant
+window.uiswitcher.ClassicUI.text=* Conserve les fonctionnalit\u00E9s des versions 2.x\n\n* Affichage classique des onglets\n* Vue h\u00E9rit\u00E9e, fonctionnalit\u00E9s r\u00E9duites.
+tps.type.incoming=Inconnu
+ConfigView.section.UPnP=UPnP
+PiecesView.legend.requested=Demand\u00E9es
+ConfigView.section.tracker.sslport.info=Voir le FAQ pour plus d'informations
+ConfigView.section.tracker.client.readtimeout=D\u00E9lai de lecture (secs)
+ConfigView.section.file.showopentorrentoptions=Lors de l'ouverture d'un torrent, afficher la bo\u00EEte de dialogue des options \:
+ConfigView.section.file.perf.cache.notsmallerthan=Ne pas mettre en cache les fichiers inf\u00E9rieurs \u00E0 (en %1)
+torrent.fix.corrupt.result.title=R\u00E9sultat de l'op\u00E9ration
+FilesView.remaining=Pi\u00E8ces restantes
+devices.on.demand=Sur demande
+ConfigView.section.ipfilter.list.title=Liste des IP bloqu\u00E9es
+v3.MainWindow.tab.minilibrary=T\u00E9l\u00E9chargements
+mdi.entry.about.plugins=\u00C0 propos des plugins
+upnp.alert.multipledevice.warning=Plusieurs p\u00E9riph\u00E9riques UPnP ont \u00E9t\u00E9 d\u00E9tect\u00E9s - v\u00E9rifier si ceux-ci exigent tous le mappage de port (voir le journal UPnP et la configuration)
+jvm.error=Une erreur d'acc\u00E8s aux options de la machines virtuelle Java\u2122 s'est produite\: %1
+TableColumn.header.fileext=Type de fichier
+xcode.deletedata.message=\u00CAtes-vous s\u00FBr de vouloir supprimer d\u00E9finitivement la copie de '%1' transcod\u00E9 pour '%2'%3 ?
+ConfigView.label.max_peers_per_torrent=Nombre maximum de connexions par torrent [0\u00A0\: illimit\u00E9]
+pairing.srp.setpw=Mettez \u00E0 jour votre mot de passe pour le jumelage s\u00E9curis\u00E9e
+ConfigView.section.tracker.web=Web
+MyTrackerView.bytesout=Octets Sortis
+PeersView.pieces=Pi\u00E8ces
+plugin.sharing.torrent.remove.veto=Cet enregistrement au tracker est d\u00FB \u00E0 une ressource partag\u00E9e.\nPour supprimer le t\u00E9l\u00E9chargement vous devez enlever le partage.
+mdi.entry.plus.full=Vuze\u2122 Plus
+CacheView.general.title=Infos Cache
+beta.wizard.intro.title=S\u00E9lection d'adh\u00E9sion
+# 2.0.7.x
+Categories.all=Tous
+security.certcreate.country=Code Pays (2 lettres)
+MainWindow.menu.window.zoom=&Zoom
+ConfigView.download.abbreviated=D\:
+MainWindow.menu.plugins.uninstallPlugins=Assistant de d\u00E9sinstallation
+ConfigView.section.ipfilter.totalIPs=%1 IPs bloqu\u00E9es au total, soit %2 d'internet.
+TableColumn.header.Speed=Vitesse
+ConfigView.section.tracker.client=Client
+label.nat.proxies=NAT/Proxies
+ConfigView.section.file.perf.cache.flushpieces=\u00C9crit les pi\u00E8ces compl\u00E8tes imm\u00E9diatement sur le disque. Cela mod\u00E8re l'acc\u00E8s au disque mais engendre plus d'op\u00E9rations d'\u00E9criture.
+MagnetPlugin.report.md.progress=Progression du t\u00E9l\u00E9chargement des m\u00E9tadonn\u00E9es \: %1
+UIDebugGenerator.complete.title=D\u00E9bogage g\u00E9n\u00E9ral termin\u00E9
+network.ipv4.prefer.stack=Pr\u00E9f\u00E9rez la pile IPv4 - utiliser s\u00E9par\u00E9ment les piles IPv4 et IPv6 au lieu de mettre en \u0153uvre une double pile
+ConfigView.label.set_ui_transfer_speeds.description=Vous pouvez choisir de d\u00E9finir manuellement les vitesses par d\u00E9faut disponible en mati\u00E8re de t\u00E9l\u00E9chargement et d'upload \u00E0 partir de l'ic\u00F4ne de la zone de notification.\nLes valeurs doivent \u00EAtre s\u00E9par\u00E9es par des virgules.
+SpeedTestWizard.test.panel.aborted=Le test a \u00E9t\u00E9 interrompu manuellement.
+ConfigView.label.stop.Shutdown=Arr\u00EAter l'ordinateur
+FilesView.menu.setpriority=&Priorit\u00E9
+MyTorrentsView.dialog.setPosition.text=Entrer la position \u00E0 laquelle mettre les torrents s\u00E9lectionn\u00E9s\:
+device.import.dup.title=P\u00E9riph\u00E9rique en double
+Formats.units.kbit=kbit
+metasearch.addtemplate.done.desc=Mod\u00E8le '%1' ajout\u00E9 avec succ\u00E8s.\nIl sera utilis\u00E9 lors de votre prochaine recherche \!
+ConfigView.section.color=Th\u00E8me de Couleur
+devices.choose.profile.info.title.selected=%1 d\u00E9tails\:
+SpeedTestWizard.test.panel.encrypted=chiffr\u00E9
+Peers.column.client_identification=Identification Client
+PiecesView.speed.info=Les clients lents n'interf\u00E8rent pas avec les pi\u00E8ces rapides
+FilesView.name=Nom
+MyTorrentsView.menu.checkfilesexist=V\u00E9rifiez l'existence du fichier
+ConfigView.pluginlist.column.name=Nom
+v3.MainWindow.button.run=Ouvrir le fichier t\u00E9l\u00E9charg\u00E9
+configureWizard.transfer.message=Veuillez choisir votre connexion ci-dessous. Soyez pr\u00E9venus qu'une faible vitesse d'envoi donnera de pi\u00E8tres performances. Puisque la vitesse d'envoi importe pour chaque torrent, t\u00E9l\u00E9charger trop de torrents \u00E0 la fois donnera \u00E9galement de mauvaises performances. Nous conseillons d'allouer un MINIMUM de 5kB/s par torrent. Plus la vitesse d'envoi est haute, plus la vitesse de t\u00E9l\u00E9chargement sera rapide. (en fonction d [...]
+devices.od.turnon.learn=En savoir plus>
+MainWindow.menu.help.debug=Signaler un bug
+LocaleUtil.section.chooseencoding=Choisir l'encodage pour le nom du fichier
+ConfigView.section.transfer.autospeed.reset=R\u00E9initialiser les valeurs avanc\u00E9es
+MainWindow.menu.speed_limits.reset=Effacer les limites actuelles
+v3.mb.delPublished.text=AVERTISSEMENT\: Cette action ne retirera PAS votre contenu publi\u00E9 '%1' de <A HREF\="%2">%3</A>.\n\nCliquez sur "Supprimer", seulement si vous voulez que votre contenu reste publi\u00E9 et t\u00E9l\u00E9chargeable, mais que vous voulez lib\u00E9rer votre bande passante. Assurez-vous que le processus de t\u00E9l\u00E9chargement est termin\u00E9 avant de le faire (<A HREF\="%4">comment </A>?).\n\nCliquez sur "Annuler" si vous souhaitez retirer compl\u00E8tement  [...]
+Button.continue=Continuer
+ConfigView.label.ircchannel=Canal
+Torrent.create.progress.hashing=Calcul du Hash des fichiers
+ConfigView.section.mode.beginner.text=Tout ce dont vous avez besoin pour t\u00E9l\u00E9charger des torrents.\nUtilisez ce mode pour simplement g\u00E9rer vos torrents.
+externalLogin.explanation=Le mod\u00E8le "%1" requiert votre identification. Une fois connect\u00E9, cette fen\u00EAtre se fermera automatiquement. Si tel n'est pas le cas, merci de cliquer sur "Termin\u00E9".
+Menu.show.torrent.menu.tooltip=Affiche le menu Torrents dans la barre de menu de l'application
+PeerManager.status.finishedin=Termin\u00E9 en
+security.certtruster.issuedto=Publi\u00E9 pour\:
+Torrent.create.progress.parsingfiles=Analyse des fichiers
+Progress.reporting.window.remove.auto=Supprimer automatiquement les \u00E9l\u00E9ments inactifs
+SpeedView.stats.upload=Donn\u00E9e d'upload en attente \:
+ConfigView.section.style.osx_small_fonts=Utiliser une petite police [red\u00E9marrage n\u00E9cessaire]
+UpdateWindow.status.done=Termin\u00E9
+platform.win32.baddll.netdog=Armor2net Personal Firewall
+custom.settings.import=\u00CAtes-vous s\u00FBr de vouloir importer les param\u00E8tres de configuration pour '%1' ?
+GeneralView.menu.selectTracker=S\u00E9lectionner
+devices.associate.already=D\u00E9j\u00E0 associ\u00E9
+DHTTransport.report.complete=termin\u00E9
+# > 2402
+popup.download.finished="%1" est termin\u00E9.
+device.upnp.desc_url=Description du p\u00E9riph\u00E9rique
+security.certcreate.alias=Alias
+FilesView.menu.rename=Renommer ou changer de cible
+v3.iconBar.view.small=e
+Tracker.announce.ignorePeerSeed=Ignore le nombre de pairs et de seeds. %1
+ConfigView.section.tracker.publicenable.info=Ceci permet \u00E0 d'autres d'utiliser votre tracker\nsans avoir \u00E0 les h\u00E9berger ou les publier.
+MyTrackerView.category=Cat\u00E9gorie
+ConfigView.label.moveonlyusingdefaultsave=si dans le r\u00E9p par d\u00E9faut
+label.merge=Fusionner
+MainWindow.menu.file.closewindow.keybinding=Meta+Shift+W
+Progress.reporting.window.remove.now=Supprimer les \u00E9l\u00E9ments inactifs
+SpeedTestWizard.finish.panel.auto.speed=Le type de d\u00E9bit automatique est \:
+pairing.srp.registering=Enregistrement ...
+subs.prop.high_version=Version la plus \u00E9lev\u00E9e rencontr\u00E9e
+ConfigView.section.tracker.logenable=\u00C9crire les statistiques p\u00E9riodiques dans 'tracker.log'
+beta.wizard.title=Installation de la version Beta
+menu.open.torrent={torrent.fix.corrupt.browse}...
+OpenTorrentWindow.mb.noGlobalDestDir.text=Le r\u00E9pertoire de destination '%1' n'est pas valide.
+ConfigView.label.zeronewfiles.tooltip=La console doit \u00EAtre ferm\u00E9e
+MainWindow.dialog.choose.file=Choisissez le fichier torrent
+TableColumn.header.name.ext=Type de fichier\: %1
+window.updateswt.status.downloading.updater=T\u00E9l\u00E9chargement du Module de mise \u00E0 jour
+v3.mb.PlayFileNotFound.title=Fichier introuvable
+ConfigView.section.language.info=Une v\u00E9rification sera faite \u00E0 chaque d\u00E9marrage d'Azureus.
+ConfigView.section.stats.xslfile=Nom du fichier XSL
+core.shutdown.xcode=transcodage termin\u00E9
+TableColumn.header.smootheta=ETA mod\u00E9r\u00E9
+VivaldiView.title.full_v6=Vivaldi IPv6
+label.date.format=Format de date
+ConfigTransferAutoSpeed.auto.speed.beta=D\u00E9bit automatique (beta)
+TableColumn.header.health.info=L'\u00E9tat de sant\u00E9 de votre connexion \u00E0 l'essaim du torrent est
+ConfigView.text.ignore=Ignorer
+configureWizard.transfer.maxUpSpeed=Vitesse d'envoi Max (kbit/s)
+IrcView.clientsconnected=Utilisateurs
+dialog.associations.askagain=V\u00E9rifier au d\u00E9marrage
+ConfigView.section.security.resetcerts.error.msg=\u00C9chec de la r\u00E9initialisation du magasin de certificats pour une raison inconnue, merci de consulter les forums d'aide
+GeneralView.label.peers=Client(s)\u00A0\:
+ConfigView.label.playfilespeech=Parler \u00E0 la fin du t\u00E9l\u00E9chargement d'un fichier
+ConfigView.section.connection.networks.Tor=R\u00E9seau Onion Router (Tor)
+library.tag.header=Cat\u00E9gorie '%1'
+jvm.max.mem=Taille maximale de la m\u00E9moire du 'tas'[vide\=d\u00E9faut, min\=%1]
+ConfigView.section.ipfilter.autoload.group=Chargement automatique
+ConfigView.section.tracker.passwordenableweb=Activer mot de passe sur le tracker Web
+Button.ok=&OK
+ConfigView.pluginlist.column.type.perUser=Par Utilisateur
+MyTorrentsView.menu.setUpSpeed=Vit. d'envoi
+OpenTorrentWindow.dataLocation=Emplacement de sauvegarde\:
+MyTorrentsView.menu.trackername.editprefs=Modifier les Trackers d'affichage pr\u00E9f\u00E9r\u00E9s ...
+PiecesView.typeItem.1=Rapide
+AlertMessageBox.error=Erreur
+PiecesView.typeItem.0=Lent
+ConfigView.section.connection.port.rand.range=Plage de ports [min-max]
+window.update.noupdates.title=R\u00E9sultat de la v\u00E9rification de mises \u00E0 jour
+ConfigView.section.style.useFancyTabs=Utiliser le nouveau type d'onglet
+ConfigView.label.seeding.autoReposition=Repositionner automatiquement les torrents en fonction de leur Rang de source
+beta.wizard.on=Avertissez-moi avec les derni\u00E8res versions b\u00EAta stables s'il vous pla\u00EEt.
+Peers.column.timetocomplete=Temps restant
+ConfigView.section.proxy.testsocks.title=Test de connexion SOCKS
+ConfigView.section.downloadManagement=Gestion des t\u00E9l\u00E9chargements
+config.external.browser.info2=Le navigateur par d\u00E9faut de votre ordinateur est normalement utilis\u00E9. Vous pouvez modifier cette option pour utiliser un navigateur sp\u00E9cifique, ou celle fournie par un plugin (par exemple, le plugin navigateur Tor).
+config.external.browser.info1=Le navigateur externe est utilis\u00E9 pour afficher le contenu web en dehors du client dans un autre navigateur, par exemple les pages de d\u00E9tails des r\u00E9sultats de recherche.
+MainWindow.menu.file.open.uri.keybinding=Meta+U
+ActivityView.legend.achieved=Taux atteint
+dialog.add.peers.title=Ajouter des pair(s)
+devices.choose.device.info.title=Astuce pour glisser-d\u00E9poser des fichiers
+installPluginsWizard.list.title=Liste des plugins installables
+TableColumn.header.health=Indicateur de sant\u00E9
+ConfigView.label.sleep.download=Le t\u00E9l\u00E9chargement
+Button.no=Non
+Scrape.status.ok='Scrape' Ok.
+pairing.status.info=Statut
+fileplugininstall.install.desc=\u00CAtes-vous s\u00FBr de vouloir installer le plugin '%1' version %2 ?
+MainWindow.menu.speed_limits.view_current=Voir les limites actuelles...
+IrcClient.noNick=Alias non pr\u00E9cis\u00E9. Veuillez remplir le champ correspondant dans le menu 'Options'
+Peers.column.client_identification.info=Indique les noms des clients brutes re\u00E7ues par Vuze\u2122 - utile pour le d\u00E9bogage
+MainWindow.menu.transfers.pausetransfers.keybinding=Meta+P
+Categories.uncategorized=Non class\u00E9s
+MySharesView.title.full=Mes partages
+DiskManager.alert.movefileexists=Erreur en d\u00E9pla\u00E7ant les fichiers termin\u00E9s\nLe fichier %1 existe d\u00E9j\u00E0 dans le r\u00E9pertoire de destination
+MyTorrentsView.menu.start=&D\u00E9marrer
+dht.enabled=Activer la base de donn\u00E9es distribu\u00E9e
+v3.mb.PlayFileNotFound.button.remove=Supprimer de Vuze\u2122
+window.updateswt.status.done=Red\u00E9marrage
+MainWindow.updateavail=(Mise \u00E0 jour disponible)
+TableColumn.header.secondsdownloading=T\u00E9l\u00E9charge depuis
+Button.bar.share=Partager
+ConfigView.section.transfer.speeds.wiki=Bons r\u00E9glages de vitesse
+Views.plugins.UPnP.title=UPnP
+ConfigView.section.ipfilter.discardminkb=Minimum %1 \u00E9cart\u00E9 avant d'appliquer le ratio
+MainWindow.menu.view.open_global_transfer_bar=Barre de transfert
+devices.copy.fail=Impossible de copier vers le p\u00E9riph\u00E9rique
+IrcClient.channel=Canal
+SpeedTestWizard.abort.message.insufficient.slots=Impossible d'uploader vers l'un des pairs - emplacements d'upload insuffisance?
+FilesView.rename.choose.path.dir=Choisissez un nouveau r\u00E9pertoire ou un existant
+Main.parameter.usage=Utilisation\: java org.gudy.azureus2.cl.Main [param\u00E8tres] "fichier .torrent" "r\u00E9pertoire de sauvegarde"
+ConfigView.section.mode.intermediate=Interm\u00E9diaire
+ConfigView.section.file.decoder.prompt=Toujours demander quand un choix d'encodage est disponible
+label.edit.trackers=\u00C9diter les trackers
+v3.MainWindow.menu.view.asSimpleList=Liste simplifi\u00E9
+ManagerItem.waiting=En attente
+config.external.browser.select=S\u00E9lection de navigateur \:
+ConfigView.text.peers=Clients
+wizard.maketorrent.auto=Automatique
+ConfigView.section.tracker.publicenable=Autoriser les torrents externes
+v3.mb.PlayFileNotFound.button.find=Trouver manuellement...
+MyTrackerView.left=Restant
+GeneralView.section.transfer=Transfert
+PluginDeprecation.alert=Un plugin a essay\u00E9 d'utiliser une fonctionnalit\u00E9 qui sera supprim\u00E9 dans l'avenir - merci d'ouvrir la vue du journal de d\u00E9bogage du plugin pour plus d'informations.
+GeneralView.label.trackerurl.tooltip=Cliquer pour copier l'URL d'annonce dans le presse-papier
+UIDebugGenerator.messageask.title=G\u00E9n\u00E9rateur de bug
+Views.plugins.azbuddy.title=Amis
+ConfigView.section.global=G\u00E9n\u00E9ral
+ConfigView.section.style.useUnitsRateBits=Utiliser des bits au lieu des octets pour les valeurs des taux (Kio/s->Kibits/s, etc.)
+ConfigView.label.StartUIBeforeCore=Lancer l'interface utilisateur avant l'initialisation de base
+device.rss.group=Flux RSS locale
+MainWindow.menu.speed_limits.wiki=Aide Wiki...
+ConfigView.label.please.visit.here=Pour plus de d\u00E9tails, vous pouvez aller voir ici
+MainWindow.menu.file.exit=&Quitter
+device.import.desc=\u00CAtes-vous s\u00FBr de vouloir importer le p\u00E9riph\u00E9rique '%1' ?
+GeneralView.no=Non
+Tracker.tooltip.NoMultiSupport=Ce tracker ne supporte pas plusieurs hash par requ\u00EAte.
+MainWindow.dialog.choose.folder=Choisissez le r\u00E9pertoire contenant les .torrent
+azbuddy.os_online=Connect\u00E9
+# used for more than just "delete data"
+MainWindow.menu.file.configure=&Assistant de configuration
+MainWindow.about.internet.contributors=Contributeurs
+ConfigView.label.set_ui_transfer_speeds.description.download=R\u00E9glage des vitesses de t\u00E9l\u00E9chargement (en Ko / s)
+ConfigView.label.resume.downloads.on.start=Reprendre des t\u00E9l\u00E9chargements en pause au d\u00E9marrage apr\u00E8s l'initialisation compl\u00E8te
+ConfigView.section.connection.http.port=Num\u00E9ro de port entrant
+ConfigView.section.stats.exportpeers=Exporter les d\u00E9tails des pairs
+ConfigView.section.file.subfolder.dnd=D\u00E9placer les fichiers qui ne sont pas s\u00E9lectionn\u00E9s pour le t\u00E9l\u00E9chargement, dans le sous-dossier
+FilesView.firstpiece=n\u00B0 de la premi\u00E8re pi\u00E8ce
+pairing.explicit.info=Normalement, les attributs des adresses IP n'ont pas besoin d'\u00EAtre explicitement sp\u00E9cifi\u00E9s puisque ceux-ci peuvent \u00EAtre obtenues automatiquement.\nL'attribut 'H\u00F4te' peut, par exemple, \u00EAtre utilis\u00E9 ? Si vous avez un compte DynDNS et le logiciel client appropri\u00E9 pour garder votre IP dynamique enregistr\u00E9 correctement.
+Views.plugins.Plugin.Update.title=Mise \u00E0 jour Plugins
+ConfigView.section.logging.showLogsFor=Afficher %1 des journaux pour les cat\u00E9gories suivantes\:
+ConfigView.section.connection.http.portoverride=Port de remplacement Tracker HTTP [0\: none]
+SystemTray.menu.show=&Afficher Vuze\u2122
+TransferStatsView.legend.pingaverage=Moyenne
+subscriptions.listwindow.failed=Pas d'abonnements trouv\u00E9s
+iconBar.publish.tooltip=Publier
+torrent.view.info.title=Information du torrent
+device.xcode.whenreq=Si n\u00E9cessaire
+TableColumn.TorrentStream.tooltip.expand=D\u00E9velopper la ligne pour voir 'Lire maintenant" individuellement sur chaque fichier
+UpdateWindow.columns.name=Nom
+dlg.auth.enter.subtitle.try.2=La validation a \u00E9chou\u00E9
+dlg.auth.enter.subtitle.try.1=On y est presque.
+azbuddy.ui.menu.disconnect=D\u00E9connect\u00E9
+option.askeverytime=Demander \u00E0 chaque fois
+ConfigView.section.language.UpdateNow=Mettre \u00E0 jour maintenant\u00A0\!
+ConfigView.section.file.config.currentdir=Actuel r\u00E9pertoire de configuration\:
+TrayWindow.menu.show=Afficher Vuze\u2122
+Pieces.column.Requested.info=Montre si d'autres requ\u00EAtes peuvent \u00EAtre faites sur cette pi\u00E8ce ou pas (*)
+ConfigView.label.seeding.ignoreRatioPeers=Ignorer les torrents avec au moins 1 source pour
+PeersView.menu.blockupload=Bloquer l'envoi
+dlg.auth.install.failed.text=L'activation du code '%1' a \u00E9chou\u00E9 en raison d'une erreur de serveur.\n\nMerci de r\u00E9essayer plus tard (l'erreur signal\u00E9e \u00E9tait '%2')
+Trackers.column.interval.info=Intervalle d'actualisation en secondes \: intervalle (intervalle minimum)
+MagnetPlugin.report.searching=recherche...
+dht.reseed.info=Reseeder la base de donn\u00E9es
+config.internal.browser.info3=Un proxy peut \u00EAtre utilis\u00E9e pour forcer le contenu \u00E0 s'extraire indirectement lors de l'installation (par exemple, fourni par le plugin Tor Helper)
+config.internal.browser.info2=Par d\u00E9faut Internet Explorer est utilis\u00E9 sur Windows, Safari sur Mac. Des versions *Limited* de Firefox peuvent \u00EAtre utilis\u00E9s \u00E0 la place - voir les options suivantes
+Subscription.menu.clearall=Marquer tous les r\u00E9sultats lus
+subscript.add.upgradeto.desc=La version %1 de l'abonnement '%2' est disponible.\nVoulez vous mettre a jour?
+Wizard.Subscription.subscribe.title=Abonnements disponibles
+config.internal.browser.info1=Le navigateur interne est utilis\u00E9 pour afficher le contenu web int\u00E9gr\u00E9 dans le client, par exemple la page Vuze\u2122 HD Network.
+ConfigView.section.interface.display.suppress.file.download.dialog=Supprimer la bo\u00EEte de dialogue de t\u00E9l\u00E9chargement de fichier
+PeersView.piece.info=Num\u00E9ro de la derni\u00E8re pi\u00E8ce demand\u00E9e \u00E0 ce client
+ConfigView.section.tracker.forceport=Forcer les torrents externes h\u00E9berg\u00E9s sur le port par d\u00E9faut.
+v3.topbar.menu.show.frog=Da Grenouille Bleue
+ConfigView.label.announceport=Passer outre au port d'annonce du tracker
+ConfigView.section.stats=Statistiques
+Column.seedspeers.started=%1 de %2
+ConfigView.section.invalid.value.title=Valeur invalide
+DHTView.transport.in=Entrant\u00A0\:
+ConfigView.label.seeding.rankType.seed.tooltip=Nombre de sources faible \= Rang plus \u00E9lev\u00E9
+azbuddy.enabled=Activ\u00E9
+ConfigView.section.connection.networks.I2P=R\u00E9seau I2P
+plugin.init.load.failed=Erreur lors du chargement du plugin '%1' depuis %2
+message.confirm.delete.title=Confirmer la suppression
+dht.reseed.group=Reseeder
+ConfigView.label.quickviewexts=Vue rapide des extensions de fichier
+sidebar.Library=Biblioth\u00E8que
+ConfigView.label.switchpriority=Passez en basse priorit\u00E9 lorsque l'on est source
+PeersView.menu.kickandban=Exclure et bannir
+subs.prop.last_scan=Derni\u00E8re mise \u00E0 jour r\u00E9ussie
+IPChecker.external.service.no-ip.description=Fournisseur de services DNS dynamique et statique\n(aucun service de v\u00E9rification d'IP gratuit)
+devices.ready=Pr\u00EAt
+device.od.error.opfailexcep=Le p\u00E9riph\u00E9rique n'a pas pu traiter la commande %1\: exception %2
+TableColumn.header.OnlyCDing4=OnlyCDing4
+IPChecker.external.service.dyndns.url=www.dyndns.org
+label.learnmore=En savoir plus
+dlg.install.vuzexcode.subtitle=Installation du composant 'Media Analyzer'
+TableColumn.header.TableColumnChosenColumn=Colonne choisi
+Subscription.menu.setcookies=Configurer les cookies
+iconBar.run.tooltip=Ouvrir
+ConfigView.label.stop.RunScript=Ex\u00E9cuter le script
+ConfigView.section.tracker.maxposttimemultiplier.info=Utilis\u00E9 pour des formulaires et des envois
+azbuddy.tracker.bbb.status.title=Boost d'amis
+Button.swarmit=Peupler
+GeneralView.label.status.file=Fichier
+GeneralView.label.creationdate=Cr\u00E9\u00E9 le\u00A0\:
+ipCheckerWizard.service.description=Description\:
+subscription.version.bad=L'abonnement '%1' ne peut \u00EAtre install\u00E9 qu'apr\u00E8s avoir mis Vuze\u2122 \u00E0 jour
+ConfigView.section.tracker.enablekey=Activer l'envoi d'une cl\u00E9 au tracker pour une meilleure s\u00E9curit\u00E9
+platform.jvmopt.nolinkfile=Vous ne pouvez pas g\u00E9rer les options de la machines virtuelle Java\u2122 car la migration n'est pas termin\u00E9e
+ColumnRenameWindow.message=Entrez un nouveau nom pour la colonne, vierge pour r\u00E9initialiser
+upnp.grabports=Mapper les ports m\u00EAme s'ils appartiennent \u00E0 un autre ordinateur.
+ConfigView.section.security.clearpasswords.button=R\u00E9initialiser
+ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorer un torrent m\u00EAme si\nles r\u00E8gles de Premi\u00E8re Priorit\u00E9 s'appliquent
+Button.revert=Annuler
+uninstallPluginsWizard.list.title=Liste des plugins install\u00E9s
+UpdateConstraint.message=Entrez les contraintes \u00E0 appliquer \u00E0 la cat\u00E9gorie - visiter le Wiki pour plus de d\u00E9tails.
+azbuddy.online_status=Statut de connexion
+ConfigView.section.logging.log1type=Avertissement
+OpenTorrentOptions.header.filesInfo.all=%1 Fichiers\: %3
+ConfigView.section.start=Lancement
+MyTrackerView.title.full=Mes Trackers
+devices.copy.device.auto=Copier automatiquement les fichiers vers le p\u00E9riph\u00E9rique
+PeersView.discarded=Rejet\u00E9
+metasearch.import.select.template.file=Ouvrir le mod\u00E8le
+download.removerules.unauthorised.data=\tSupprimer les donn\u00E9es
+device.onlyShowTagged=Afficher seulement les p\u00E9riph\u00E9riques \u00E9tiquet\u00E9s
+MainWindow.sr.status.tooltip.poor=Taux de partage %1 insuffisant\: < 0.9
+wizard.webseed.title=Seeds HTTP
+ConfigView.label.queue.debuglog=Journalisation des informations de d\u00E9bogage
+ConfigView.section.ipfilter.add=Ajouter
+Button.swarmit.tooltip=Rechercher des fichiers avec la m\u00EAme taille en utilisant les d\u00E9couvertes de l'essaim
+ConfigView.label.playfilefinished=Jouer un son \u00E0 la fin du t\u00E9l\u00E9chargement d'un fichier
+MySharesView.type.dircontents=Contenu du r\u00E9pertoire
+importTorrentWizard.importfile.invalidPath=Fichier d'importation invalide
+TableColumn.header.trackername=Nom du tracker
+br.backup.setup.info=Merci de mettre en place la configuration automatique de la sauvegarde.\n Voir Outils-> Options-> Sauvegarde & Restauration
+device.itunes.start=Vous devez d\u00E9marrer iTunes ou activer le d\u00E9marrage automatique
+ConfigView.section.style.DNDalwaysInIncomplete=Toujours montrer les torrents marqu\u00E9s comme 'Ne pas t\u00E9l\u00E9charger' dans la section des fichiers incomplets de {library.name}
+IPChecker.external.httploadfail=Le chargement de la page a \u00E9chou\u00E9
+ConfigView.section.rss=RSS local, etc.
+FileView.BlockView.title=Morceaux de fichiers
+MainWindow.menu.view.detailedlist=Liste &D\u00E9taill\u00E9e
+FilesView.rename.failed.title=\u00C9chec du renommage/reciblage
+PeersView.menu.close=Fermer
+ConfigView.section.proxy.group.peer=Communications des paires
+Files.column.fileext=Type
+Subscription.menu.dirtyall=Marquer tous les r\u00E9sultats non lus
+dlg.auth.cancelled.line2=Si vous pensez que c'est une erreur, merci de contacter le support technique en suivant les indications contenues dans le courriel que vous avez re\u00E7u.
+label.dblclick.to.min=Double-cliquez pour r\u00E9duire
+ConfigView.option.dm.dblclick.launch={iconBar.run}
+dlg.auth.cancelled.line1=L'activation Vuze\u2122 \u00E9t\u00E9 annul\u00E9.
+PeersView.state.established=\u00C9tabli
+Progress.reporting.action.label.remove.tooltip=Retirer ce rapport de progression de l'historique
+ConfigView.section.style.CatInSidebar=Afficher les cat\u00E9gories dans le menu lat\u00E9rale
+ConfigView.section.style.showdownloadbasket=Afficher le panier de t\u00E9l\u00E9chargements (glisser et d\u00E9placer les .torrent)
+configureWizard.transfer2.rate.changed=Limite de connexion\=%1\nLa limite appliqu\u00E9e sera de %2 (torrents actifs maximal\=%3, t\u00E9l\u00E9chargement maximal\=%4)
+azbuddy.ui.menu.cat_subs=S'abonner
+v3.menu.device.defaultprofile.never=Ne jamais transcoder
+columnChooser.move=D\u00E9placer les lignes pour r\u00E9organiser l'ordre
+ConsoleView.title.full=Console
+Plugin.extseed.name=Seeds externes
+subscriptions.column.auto-download=T\u00E9l\u00E9chargement automatique
+ConfigView.section.file.save.peers.pertorrent=par torrent
+ConfigTransferAutoSpeed.capacity.used=% Capacit\u00E9 Utilis\u00E9
+ConfigView.label.seeding.rankType=Pour le d\u00E9marrage automatique, classer les torrents termin\u00E9s en fonction de\u00A0\:
+ConfigView.section.mode.intermediate.text=Donne acc\u00E8s aux fonctions du tracker interne.\nUtilisez ce mode pour cr\u00E9er votre propre tracker et publier/h\u00E9berger vos fichiers.
+PiecesView.DistributionView.PeerAvl=Contribution disponible des pairs
+configureWizard.transfer2.hint=Si vous configurez votre limite de t\u00E9l\u00E9chargement de fa\u00E7on trop haute ou trop basse, affectera les performances de t\u00E9l\u00E9chargement \!
+subs.prop.next_scan=analyse suivante
+SpeedView.stats.uploaded=Envoy\u00E9 (Protocole)
+ConfigView.section.queue.main=Principal
+config.external.browser.test=Configuration du navigateur externe de test
+ConfigView.label.copyanddeleteratherthanmove=Copier et ensuite supprimer les donn\u00E9es (au lieu de le faire en une op\u00E9ration) - peut pr\u00E9venir la perte de donn\u00E9es avec certains syst\u00E8mes de fichiers
+# Not used, but could be renamed in all translation files to label.experimental :)
+OpenTorrentWindow.message=Exp\u00E9rimental
+ConfigView.section.logging.level=Niveau de journalisation
+ConfigView.section.file.config.section=Param\u00E8tres de configuration
+ConfigView.section.transfer.lan=LAN
+SpeedTestWizard.test.panel.standard=standard
+ConfigView.section.ipfilter.discardbanning=Bloquer les pairs dont le ratio donn\u00E9es \u00E9cart\u00E9/donn\u00E9es fiables d\u00E9passe [0\: d\u00E9sactiv\u00E9]
+ConfigView.section.style.colorOverride.altRow=Rangs pairs
+SpeedTestWizard.set.upload.hint=D\u00E9finir les limites de t\u00E9l\u00E9chargement et de transfert utilis\u00E9s par l'algorithme Vuze\u2122 de D\u00E9bit Automatique\u200B\u200B.
+DHTTransport.report.resending=renvoi des donn\u00E9es
+Torrent.create.progress.totalfilesize=Taille totale du fichier\:
+GeneralView.label.seeds=Source(s)\u00A0\:
+SpeedTestWizard.test.panel.explain=Mesurez votre vitesse de protocole Vuze\u2122. S\u00E9lectionnez le type de test de vitesse et le mode de chiffrement. Visitez la page wiki de Vuze\u2122 pour plus de d\u00E9tails sur ce test. Le test s'arr\u00EAte automatiquement si cela prend plus de deux minutes. Les tests se terminent habituellement en moins d'une minute.
+TableColumn.header.md5=MD5
+PeerSocket.mismatch_id=inadapt\u00E9
+MagnetPlugin.report.secondarylookup.fail=\u00C9chec de la recherche secondaire\: aucune source trouv\u00E9e
+iconBar.startstop.tooltip=D\u00E9marrer ou arr\u00EAter les \u00E9l\u00E9ments s\u00E9lectionn\u00E9s
+ConfigView.section.tracker.nonblocking=Options non bloquantes
+devices.xcode.show.cat=S\u00E9parer par cat\u00E9gorie
+Button.reload=Recharger
+wizard.multitracker.edit.deletetracker=Effacer
+MainWindow.status.unknown=Inconnue
+devices.copy_url=Copier le flux URL dans le Presse-papiers
+sharing.progress.hide=Cacher
+ConfigView.section.stats.minutes=min
+devices.router=routeur
+MainWindow.menu.file.import.keybinding=Meta+I
+Formats.units.Mibit=Mibit
+GeneralView.label.hash.tooltip=Cliquer pour copier le hash dans le presse-papier.
+br.backup.notify=Notifier lorsque la sauvegarde est termin\u00E9e
+Content.alert.notuploaded.button.abort=&Ne pas quitter
+MyTorrents.column.ColumnProgressETA.StreamReady=Diffusion pr\u00EAte
+OpenTorrentWindow.mb.noDestDir.text=Le r\u00E9pertoire de destination '%1' pour le torrent '%2' n'existe pas ou n'est pas valide.
+show.config.changes=Afficher les modifications de la configuration...
+label.toggle.new.marker=Basculer avec les nouveaux marqueurs
+Wizard.Subscription.create.search=Recherche
+MainWindow.nat.status.tooltip.unknown=\u00C9tat inconnu (TCP) [pare-feu/NAT]
+security.cert.auto.install=Installer automatiquement les certificats SSL inconnus sans demander
+ConfigView.section.file.friendly.hashchecking.tooltip=Un mode de v\u00E9rification du hash des parties de fichier plus lent mais beaucoup moins consommateur de m\u00E9moire et de processeur.
+ConfigView.section.logging.filter=Filtres
+MainWindow.menu.view.irc.moved=Irc est d\u00E9sormais disponible en tant que plugin, voir http\://azureus.sourceforge.net/plugin_list.php. Une fois install\u00E9, utiliser le menu Affichage->plugins->IRC pour y acc\u00E8der.
+SpeedView.stats.uptime=Temps allum\u00E9 (heures)
+ConfigView.section.connection.encryption.encrypt.fallback_incoming=Permettre les connections entrantes non crypt\u00E9es
+TableColumn.header.trancode_qpos=\#
+Progress.reporting.statusbar.button.tooltip=Afficher la fen\u00EAtre de rapport de progression
+dlg.try.trial.text=Vuze\u2122 a besoin d'installer le plugin qui permet de graver les DVD de vos vid\u00E9os. Cliquez sur Activer pour continuer.
+ConfigView.section.logging.logdir=R\u00E9pertoire du fichier journal
+MainWindow.menu.quick_view.msg=Contenu du fichier '%1' au sein du t\u00E9l\u00E9chargement '%2'
+PeersView.client=Client
+TableColumn.header.secondsseeding.info=temps pass\u00E9 en source.
+SpeedTestWizard.name.conf.level.low=Bas
+remote.pairing.learnmore=<A HREF\="/pairing_learnmore.start">Questions fr\u00E9quentes sur le jumelage</A>
+ConfigView.label.ignoreCase=Ignorer la case
+device.error.copytomissing='Copier vers le dossier' "%1" Introuvable
+devices.xcode.profs=Profils de transcodage disponibles
+ConfigView.label.transfer.ignorepeerports=Ignorer les clients utilisant ces ports (s\u00E9par\u00E9s par ';' e.g. 0;25;100-200)
+exportTorrentWizard.process.torrentfail.title=La lecture du torrent a \u00E9chou\u00E9
+MagnetPlugin.report.tunnel=tunnelling de %1
+ConfigView.section.ipfilter.enable.descriptionCache=Descriptions du magasin IP dans le fichier de scratch
+MainWindow.menu.help.donate=Faire une &donation...
+device.xcode.always=Toujours2
+unix.script.new.button.asknomore=Ne plus m'avertir
+MyTorrentsView.menu.setSpeed.disabled=D\u00E9sactiv\u00E9
+Button.moveUp=D\u00E9placer vers le haut
+MainWindow.menu.file.open.url.keybinding=Meta+L
+DownloadManager.error.sha1=Erreur\u00A0\: pas d'algorithme SHA1
+ConfigView.pluginlist.column.directory=R\u00E9pertoire
+security.certtruster.issuedby=Publi\u00E9 par\:
+ConfigView.section.seeding=Gestion des sources
+ConfigView.tb.delete.torrent=Retirer de la biblioth\u00E8que seulement
+ConfigView.section.sharing.protocol=Protocole pour les ressources partag\u00E9es (configuration du tracker n\u00E9cessaire)
+ConfigView.section.logging.statsinfo=G\u00E9n\u00E9rer des informations statistiques
+ConfigView.section.transfer.autospeedbeta=D\u00E9bit automatique (Beta)
+wizard.finish=Terminer
+ConfigView.section.connection.udp.enable=Activer UDP
+subs.prop.is_auto_ok=T\u00E9l\u00E9charger automatiquement autoris\u00E9
+network.ipv6.enable.support=Activer le support IPv6 (sous Windows\u00AE, requiert java\u2122 7)
+DHTView.general.rendezvous=Rendez-vous\u00A0\:
+upnp.alert.differenthost=UPnP\: Mapping '%1' a \u00E9t\u00E9 r\u00E9serv\u00E9 par '%2' - veuillez s\u00E9lectionner un port diff\u00E9rent
+ConfigTransferAutoSpeed.while.downloading=T\u00E9l\u00E9chargement\:
+DHTOpsView.title.full=Graphique DDB
+ClientStats.column.sent={DHTView.transport.sent}
+swt.updater.downloader.downloading=T\u00E9l\u00E9chargement de SWT \u00E0 partir de
+TableColumn.header.MediaThumb=M\u00E9dia
+platform.win32.baddll.info=Vuze\u2122 a d\u00E9tect\u00E9 la pr\u00E9sence de '%1'. Celui-ci fait partie de '%2' et a \u00E9t\u00E9 reconnu comme pouvant causer des probl\u00E8mes graves tels que des crashes de l'application et une utilisation importante du processeur. Si vous rencontrez ce type de probl\u00E8mes, merci alors de d\u00E9sinstaller ce logiciel ou de le configurer pour ne pas affecter Vuze\u2122.
+IrcClient.error=Erreur
+MyTorrentsView.menu.reposition.manual=Repositionner..
+priority.high=Haute priorit\u00E9
+tag.share=Partager vos cat\u00E9gories avec la communaut\u00E9
+MyTorrents.items.DownSpeedLimit.disabled=Pas de t\u00E9l\u00E9chargement
+ConfigView.label.version.info.link=Allez voir ici pour plus de d\u00E9tails sur les donn\u00E9es qui sont envoy\u00E9es \u00E0 la v\u00E9rification de version du serveur
+br.backup.folder.info=Choisissez le dossier dans lequel la sauvegarde sera effectu\u00E9e
+devices.profile.direct=Direct
+ConfigView.label.start=D\u00E9marrage
+IrcClient.joined=rejoint
+label.properties=Propri\u00E9t\u00E9s
+device.renderer.remove_all.desc=\u00CAtes-vous s\u00FBr que vous voulez supprimer tous les moteurs de rendu ET leur transcodage ?
+#Used by the webui plugin
+MyTorrentsView.menu.removeand.deletedata=effacer les &donn\u00E9es
+ConfigView.section.transfer.autospeed.downadjratio=T\u00E9l\u00E9chargement \: rapport de vitesse pour l'upload (par exemple 2.0 -> la limite de vitesse de t\u00E9l\u00E9chargement est le double limite de vitesse d'upload)
+label.lang.upper.case=Utilisez les majuscules (aide \u00E0 aligner l'exp\u00E9rience utilisateur pour ceux qui ont la touche "capslock" bloqu\u00E9e)
+subscriptions.config.maxresults=Nombre maximum de r\u00E9sultats m\u00E9moris\u00E9s par abonnement [0\: illimit\u00E9]
+label.access.denied=Acc\u00E8s refus\u00E9
+# Tooltips
+#GeneralView.label.status.pieces_available.tooltip=Refl�te le nombre de copies disponibles.
+#Si le nombre � droite est inf�rieur � 1, vous ne voyez pas une copie compl�te du fichier
+#et il fortement probable que votre t�l�chargement n'aboutisse pas.
+wizard.multitracker.edit.title=\u00C9diteur de multi-tracker
+Scrape.status.networkdisabled=R\u00E9seau non activ\u00E9
+wizard.choosetorrent=Veuillez choisir le fichier torrent \u00E0 cr\u00E9er
+ConfigView.label.info.in.window.title=Afficher les taux actuels dans la barre de titre
+health.explain.green=Tout se passe bien.
+MainWindow.menu.speed_limits.info.prof=R\u00E9glages pour le profil '%1'
+Peers.column.UpDownRatio=Envoy\u00E9\:T\u00E9l\u00E9charg\u00E9
+ConfigView.section.tracker.checkip=V\u00E9rification de l'adresse...
+Formats.units.Gibit=Gibit
+ConfigView.pluginlist.uninstallSelected=D\u00E9sinstaller la s\u00E9lection
+dlg.auth.validating.subtitle=Validation...
+FilesView.name.fastRename=Renommage rapide
+security.crypto.reason=Motif de l'op\u00E9ration
+GeneralView.label.totalsize=Taille totale\u00A0\:
+ConfigView.section.language.UpdateURL=URL de mise \u00E0 jour
+OpenTorrentWindow.mb.notTorrent.title=\u00C9chec de l'ouverture du torrent
+GeneralView.label.totalspeed=Vitesse totale\u00A0\:
+ConfigView.label.overrideip=Forcer l'IP envoy\u00E9e au tracker (NAT)
+seedmore.shareratio=Votre taux de partage sur ce torrent est de
+ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Permettre les connections sortantes non crypt\u00E9es si un essai de connexion crypt\u00E9e \u00E9choue
+GeneralView.torrent_created_on_and_by=%1 par %2
+MyTorrentsView.menu.manual.shared_torrents=Manuellement (dans les torrents)
+ConfigView.section.style.useCustomTabs=Utiliser des onglets fermables (n\u00E9cessite un red\u00E9marrage)
+device.mediaserver.configure=Configurer mon serveur de m\u00E9dia
+filter.header.matches2=(R\u00E9sultats de la recherche\: %1, %2 actif(s))
+webui.upnpenable=Activer l'UPnP pour ce port (*)
+filter.header.matches1=(R\u00E9sultats de la recherche\: %1)
+ConfigView.section.mode.intermediate.text1=Plus de fonctionnalit\u00E9s pour le contr\u00F4le, l'optimisation et la visualisation de t\u00E9l\u00E9chargements.
+ConfigView.label.open_transfer_bar_on_start=Ouvrir la Barre de Transfert au d\u00E9marrage
+label.no.download.selected=Aucun t\u00E9l\u00E9chargement s\u00E9lectionn\u00E9
+MainWindow.menu.speed_limits.schedule=Planification et r\u00E9glages
+friend.mod.subs=Faites un clic droit pour modifier les abonnements
+MainWindow.menu.window.zoom.maximize=Agrandir
+ConfigView.section.file.save.peers.enable=Sauvegarder les connexions pour des reconnexions rapides
+DHTView.transport.received=Re\u00E7u
+TableColumn.header.peakdown.info=D\u00E9bit de t\u00E9l\u00E9chargement \u00E9lev\u00E9
+azbuddy.tracker.enabled=Activer le 'Boost d'amis' pour t\u00E9l\u00E9charger plus vite avec vos Amis
+OpenTorrentWindow.startMode.queued=En attente
+ConfigView.section.mode.beginner.wiki.definitions=Vocabulaire Bittorrent
+Wizard.Subscription.optin.description=En activant les abonnements, Vuze\u2122 vous montrera les abonnements li\u00E9s au contenu de votre biblioth\u00E8que, et vous permettra de savoir quand le contenu de votre abonnement est disponible au t\u00E9l\u00E9chargement.\n\nSouhaitez-vous activer les abonnements?
+ConfigView.section.tracker.enablecategories=S\u00E9parer les torrents par cat\u00E9gorie
+IPChecker.external.ipnotfound=Adresse IP introuvable
+tps.type.pex=PEX
+remote.pairing.test.running=Test de connectivit\u00E9 \u00E0 distance ...
+search.export.all=Exporter tous les mod\u00E8les de recherche...
+OpenTorrentWindow.simple.open=Emplacement du torrent (fichiers, URL, Hash)
+ClientStats.column.discarded={PeersView.discarded}
+GeneralView.label.updatein.stopped=Arr\u00EAt\u00E9
+OpenTorrentWindow.mb.askCreateDir.title=Le r\u00E9pertoire de destination n'existe pas
+PeersView.downloadspeed=Re\u00E7oit \u00E0
+security.certtruster.yes=Oui
+ConfigView.label.opendetails=Ouverture automatique de la fen\u00EAtre D\u00E9tails
+beta.wizard.version=Vous utilisez actuellement la version %1
+ipCheckerWizard.title=Assistant de v\u00E9rification d'IP
+LoggerView.excludeAll=Ne pas afficher les lignes correspondant \u00E0 cette expression r\u00E9guli\u00E8re\:
+dlg.auth.revoked.line1=Votre code d'activation Vuze\u2122 Plus a \u00E9t\u00E9 r\u00E9voqu\u00E9. Merci de cliquez sur le lien ci-dessous pour obtenir plus d'informations.
+TableColumn.header.tracker=Tracker
+ConfigView.section.file.perf.cache.size.explain=Le cache est utilis\u00E9 pour r\u00E9duire les lectures depuis / les \u00E9critures vers le disque. A moins d'utiliser l'option java '-XX\:MaxDirectMemerySize' pour sp\u00E9cifier la m\u00E9moire disponible pour le cache et les E/S r\u00E9seau, cette valeur doit rester %1 inf\u00E9rieure \u00E0 la taille maximum de m\u00E9moire virtuelle. La taille maximale actuelle de la m\u00E9moire virtuelle est %2. Pour des instructions sur comment mod [...]
+ConfigView.section.proxy.peer.same=Utiliser les m\u00EAme r\u00E9glages de proxy pour les communications avec le tracker et les clients.
+download.removerules.unauthorised=Supprimer automatiquement les torrents non autoris\u00E9s
+device.rss.view=Cliquez pour voir le flux RSS
+wizard.addingmt=Ajout des infos Multi-tracker
+TableColumn.header.trancode_qpos.info=Position dans la file d'attente du transcodage
+Progress.reporting.action.label.detail=D\u00E9tails
+importTorrentWizard.importfile.title=S\u00E9lection du fichier \u00E0 importer
+SpeedView.stats.total=Total
+PiecesView.numberofblocks=Nbre de Blocs
+MainWindow.menu.view.plugins=&Plugins
+health.explain.share=signifie que le torrent est soit h\u00E9berg\u00E9 soit publi\u00E9
+torrent.fix.corrupt.result.fixed=Nouveau hachage de %1 calcul\u00E9.\nCliquer sur 'OK' pour enregistrer le torrent.
+Files.column.storagetype=Type de stockage
+MainWindow.menu.speed_limits.profiles=Profils
+ConfigView.section.security.unlockkey.button=D\u00E9verrouiller
+LoggerView.autoscroll=D\u00E9filement automatique
+installPluginsWizard.installMode.info.text=Les plugins ne sont pas n\u00E9cessaires pour que Vuze\u2122 fonctionne correctement, ils apportent des fonctions suppl\u00E9mentaires, pour le plaisir, l'automatisation ou le contr\u00F4le \u00E0 distance.\nVeuillez lire attentivement la description du plugin avant de d\u00E9cider de l'installer.\nLa plupart des plugins peuvent \u00EAtre test\u00E9s sans risques mais ne surchargez pas inutilement votre configuration avec des plugins que vous n' [...]
+dht.port=Port UDP pour la base de donn\u00E9es
+plugins.basicview.log=Journal\:
+ConfigView.section.file.max_open_files.explain=Avoir trop de fichiers ouverts simultan\u00E9ment peut causer des probl\u00E8mes de performance du syst\u00E8me.\nVous pouvez limiter le nombre de fichiers ouverts simultan\u00E9ment.\n
+security.certcreate.ok=Cr\u00E9er
+webui.password=Mot de passe
+memmon.low.warning=La m\u00E9moire est faible, il vous reste %1 sur %2.\nLes performances peuvent se d\u00E9grad\u00E9es et Vuze\u2122 peut cesser de fonctionner.\nVisitez <a href\="http\://wiki.vuze.com/w/Java_VM_memory_usage">ce Wiki</a> pour plus de d\u00E9tails sur la fa\u00E7on d'augmenter la m\u00E9moire disponible.
+installPluginsWizard.installMode.user=Installe le(s) plugin(s) pour vous uniquement
+TableColumn.header.readrate.info=Taux de lecture du fichier
+MySharesView.name=Nom
+ConfigView.label.passwordconfirm=Mot de passe (confirmation)
+PiecesView.priority=Priorit\u00E9
+OpenTorrentWindow.xOfTotal=(%1 sur %2)
+br.test=Test
+window.updateswt.cancel=Annuler
+ConfigView.label.disconnetseed.tooltip=Lorsque le t\u00E9l\u00E9chargement est termin\u00E9, la communication\navec d'autres sources n'est plus vraiment n\u00E9cessaire.
+configureWizard.file.invalidPath=R\u00E9pertoire invalide
+ConfigView.section.tracker.password=Mot de passe
+v3.deleteContent.applyToAll=Appliquer cette action aux %1 entr\u00E9es s\u00E9lectionn\u00E9es
+MagnetPlugin.report.secondarylookup.ok=R\u00E9ussite de la recherche secondaire
+alert.copy.on.comp.fail=T\u00E9l\u00E9chargement %1\nErreur lors de la copie des fichiers termin\u00E9s vers '%2' \: %3
+GeneralView.label.maxuploads.tooltip=Nombre maximum de clients "unchocked" (clients auxquels on est susceptibles d'envoyer des donn\u00E9es) en m\u00EAme temps
+Scrape.status.error.badURL=L'URL d'annonce ne respecte pas les normes du 'scrape'.
+exportTorrentWizard.process.outputfileexists.message=Le fichier de destination existe d\u00E9j\u00E0\u00A0; le remplacer\u00A0?
+cat.share=Partager cette classification avec la communaut\u00E9
+ConfigView.section.transfer.lan.downloadrate=ko/s LAN vitesse maximale de t\u00E9l\u00E9chargement [0\u00A0\: illimit\u00E9e]
+Button.remove=Supprimer
+MyTorrents.bigView.header={sidebar.LibraryDL}
+ConfigView.section.connection.advanced.IPDiffServ=Valeur DiffServ paquet sortant (champ TOS)
+SpeedView.stats.now.tooltip=Total (Protocole)
+ConfigView.label.pause.downloads.on.exit=Mettre les t\u00E9l\u00E9chargements en pause \u00E0 la sortie
+device.export.select.template.file=Exporter le p\u00E9riph\u00E9rique
+ConfigView.section.security.resetkey.warning=\u00CAtes-vous s\u00FBr de vouloir r\u00E9initialiser vos cl\u00E9s de chiffrement ? Si vous le faites, toutes les informations que vous avez pr\u00E9c\u00E9demment chiffr\u00E9es seront D\u00C9FINITIVEMENT PERDUES. \u00C9galement, tous les autres pairs en possession de votre cl\u00E9 publique ne seront plus en mesure de communiquer avec vous \u00E0 part si ceux-ci sont en possession de votre nouvelle cl\u00E9. Donc, sauf si vous savez vraimen [...]
+ConfigView.section.connection.nondata.udp.same=Utilisez le m\u00EAme port UDP pour la base de donn\u00E9es distribu\u00E9e et le Tracker UDP
+iconBar.up=Haut
+ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Souvent les torrents avec peu de sources et beaucoup de clients n'ont pas de copie compl\u00E8te parmi les clients.\nOn ne veut pas alors pr\u00E9tendre qu'il y a une copie compl\u00E8te dans ce cas (et ainsi r\u00E9duire injustement la priorit\u00E9 du torrent)
+ConfigView.section.file.writemblimit.explain=Lorsque la vitesse d'\u00E9criture sur le disque est inf\u00E9rieure \u00E0 la vitesse de t\u00E9l\u00E9chargement, ce param\u00E8tre limite la quantit\u00E9 de donn\u00E9es mise en attente avant une limitation de la vitesse de t\u00E9l\u00E9chargement.
+iconBar.transcode.tooltip=Faire du m\u00E9dia disponible un p\u00E9riph\u00E9rique
+SpeedTestWizard.set.download.label=D\u00E9bit limite de t\u00E9l\u00E9chargement \:
+#2.0.7.0
+security.certtruster.title=Avertissement du certificat de s\u00E9curit\u00E9
+ConfigView.label.downloading.reTest=R\u00E9-\u00E9valuer les t\u00E9l\u00E9chargements toute les [min; 0 \= jamais]
+# This is the beginning of the word "View".  It's right aligned under the icon bar item
+# This is the end of the word "View".  It's left aligned under the icon bar item
+general.dont.ask.again=Ne plus me redemander
+ConfigView.section.style.dataStatsOnly=Afficher seulement les statistiques li\u00E9es aux donn\u00E9es (masque les statistiques de protocole)
+SpeedView.title.full=Activit\u00E9
+PeersView.download=T\u00E9l\u00E9charg\u00E9
+tps.status.unavailable=Non disponible
+resetconfig.warn.title=Confirmer l'action
+ConfigView.pluginlist.column.type.shared=Partag\u00E9
+# Will be used for {library.name} in classic view
+# Will be used for {library.name} in VuzeUI view
+Button.upgrade=Mettre \u00E0 jour
+TorrentOptionsView.param.max.uploads.when.busy=Vitesse d'upload maximum en KB/s lorsque la limite globale d'upload est atteint [0\: d\u00E9sactiv\u00E9]
+authenticator.password=Mot de passe
+v3.deviceview.infobar.line2=Lire vos vid\u00E9os sur tous vos \u00E9crans - iPad, iPhone, iPod, TV
+v3.deviceview.infobar.line1=Glisser-d\u00E9poser des vid\u00E9os de votre biblioth\u00E8que vers le p\u00E9riph\u00E9rique de votre choix.
+LocaleUtil.label.hint.doubleclick=Astuce\: Double-cliquer sur une colonne s\u00E9lectionne l'encodage et ferme la fen\u00EAtre
+fileDownloadWindow.state_downloading=T\u00E9l\u00E9chargement
+v3.MainWindow.tab.advanced=Avanc\u00E9
+openUrl.referrer.info=Uniquement pour les sites qui l'exige
+Wizard.Subscription.subscribe.subscriptions=Abonnements connexes
+ConfigView.option.dm.dblclick.show._windows=Afficher dans l'explorateur Windows
+MyTorrentsView.menu.manual.per_peer=Manuellement (par pairs)
+ConfigView.section.style.colorOverrides=Choix de couleur
+device.itunes.install=Vous devez installer iTunes
+ConfigView.pluginlist.column.type=Type
+ConfigView.section.files=Fichiers
+AdvRenameWindow.message=Saisir un nouveau nom pour ce t\u00E9l\u00E9chargement.
+popup.file.finished="%1" est termin\u00E9.
+UpdateWindow.columns.version=Version
+ManagerItem.moving=D\u00E9placement
+wizard.filesaved=Fichier sauvegard\u00E9.
+exportTorrentWizard.exportfile.title=S\u00E9lection du torrent \u00E0 exporter
+TableColumn.header.seed_to_peer_ratio.info=Taux global sources/clients du groupe
+ManagerItem.stopping=En arr\u00EAt...
+ConfigView.section.proxy.peer.informtracker=Informer le tracker de la limitation.
+MainWindow.menu.transfers.pausetransfersfor.keybinding=Meta+Shift+P
+ConfigView.label.tcplistenport=Port d'\u00E9coute TCP entrant
+TableColumn.header.unopened=Nouveau
+wizard.newtorrent.byo.help=Construisez votre propre torrent \u00E0 partir d'une s\u00E9lection de fichiers et de r\u00E9pertoires
+dlg.player.install.subtitle=Installation
+SpeedView.stats.autospeed.disabled=Cette fonction est soit d\u00E9sactiv\u00E9 (vous avez besoin la DHT) ou n'est pas en cours d'utilisation (vitesse manuelle de t\u00E9l\u00E9chargement s\u00E9lectionn\u00E9)
+metasearch.addtemplate.failed.title=\u00C9chec de l'installation
+wizard.multitracker.edit.edit=\u00C9diter
+ConfigView.label.hap=Masquer les t\u00E9l\u00E9chargements termin\u00E9s
+DHTView.general.unknown=Inconnu\u00A0\:
+ConfigView.label.ignoreSeeds=Ignorer les torrents avec au moins
+PeersView.I2=I (Int\u00E9ressant pour le client)
+PeersView.I1=I (Int\u00E9ress\u00E9 par le client)
+azbuddy.ui.table.msg_out=Msg sortant
+label.connections=Connexion
+torrent.fix.corrupt=Correction d'un torrent corrompu...
+PasswordWindow.title=Vuze\u2122 est barr\u00E9
+MainWindow.menu.file.create=&Cr\u00E9er un torrent
+ConfigView.section.proxy.host=H\u00F4te
+plugins.basicview.clear=Vider
+ConfigView.label.passwordmatchnone=Non
+ConfigView.section.connection.networks.prompt=Inviter \u00E0 s\u00E9lectionner quand un t\u00E9l\u00E9chargement avec tracker anonyme est ajout\u00E9
+plugin.download.remove.veto.notstopped=Ce t\u00E9l\u00E9chargement ne peut pas \u00EAtre enlev\u00E9 car il n'est pas arr\u00EAt\u00E9.
+br.backup.auto.retain=Nombre de sauvegardes \u00E0 conserver
+authenticator.torrent=Torrent
+MainWindow.menu.transfers=&Transferts
+OpenTorrentWindow.mb.notTorrent.retry=Soumettre de nouveau le lien magnet
+DHTView.general.replacements=Remplacements\u00A0\:
+exportTorrentWizard.torrentfile.title=S\u00E9lection du torrent
+window.networkselection.info=Le(s) tracker(s) du torrent affich\u00E9 ci-dessous supporte les r\u00E9seaux suivants.\nS\u00E9lectionner ceux \u00E0 utiliser pour les communications avec le tracker et les clients.\nS'il s'agit d'un tracker anonyme supportant les clients publics, activer \u00E0 la fois les r\u00E9seaux anonyme et public.\nActiver le r\u00E9seau public a pour cons\u00E9quence \u00E9vidente de supprimer l'anonymat.
+OpenTorrentWindow.torrentTable.saveLocation=Emplacement de sauvegarde
+ConfigView.section.style.enableXPStyle=Activer le style XP (n\u00E9cessite un red\u00E9marrage)
+MainWindow.dialog.choose.savepath=Choisissez le r\u00E9pertoire de sauvegarde
+dlg.auth.tos=J'ai lu et accept\u00E9 les <A HREF\="tos">conditions du service. </A>
+label.fails=\u00C9checs
+wizard.torrentFile=Fichier torrent
+webui.connectiontest=\tCliquez pour tester la connexion
+ConfigView.section.style.colorOverride.error=Erreur
+speedtest.wizard.select.bt=Test de vitesse sp\u00E9cifique Bittorrent
+label.move.on.comp=D\u00E9placer une fois termin\u00E9
+ConfigView.section.style.usePathFinder=Utilisez 'Path Finder' au lieu de 'Finder'
+ConfigView.tb.delete.ask=Demander
+v3.MainWindow.button.start=D\u00E9marrer
+FilesView.rename.filename.title=renommer le fichier
+Button.agree=Je suis d'accord
+ConfigView.label.defaultstarttorrentsstopped=Par d\u00E9faut, ajout des nouveaux torrents \u00E0 l'arr\u00EAt
+MyTorrentsView.dialog.setFilter.title=Modifier le filtre
+security.certtruster.resource=Ressource\:
+ConfigView.section.connection.encryption=Encryptage
+TableColumn.header.pieces=Pi\u00E8ces
+Views.plugins.Distributed.DB.title=Base de donn\u00E9e distribu\u00E9e
+upnp.wiki_link=Page Wiki de Vuze\u2122 sur l'UPnP
+ConfigView.label.queue.minQueueingShareRatio=Ne pas arr\u00EAter ou mettre en attente un torrent tant que son taux de partage n'atteint pas
+ConfigView.section.server.enableudpprobe=Activer le sondage des trackers UDP pour les trackers HTTP
+TableColumn.header.OnlyCDing4.info=Dur\u00E9e pendant laquelle le torrent n'a fait qu'\u00EAtre en source. Ne prend pas en compte le temps de t\u00E9l\u00E9chargement.
+label.incomplete=Incomplet
+DHTView.db.title=Base de donn\u00E9es
+UpdateWindow.status.downloading=T\u00E9l\u00E9charge
+ConfigView.section.logging.loggerenable=Activer la journalisation
+azbuddy.ui.table.con=Connexion
+Peers.column.Encryption=Chiffrement
+sidebar.header.plugins=Plugins & Extras
+ConfigView.section.br.overview=Configurez vos besoins de sauvegarde pour Vuze\u2122. Cela permettra la r\u00E9cup\u00E9ration de votre configuration dans le cas d'une erreur grave, comme une panne de disque.\n\nSi possible, sauvegarder votre configuration vers un disque physique distinct de celui qui est g\u00E9n\u00E9ralement utilis\u00E9 par Vuze\u2122 \!\n\nNotez que les op\u00E9rations suivantes s'appliquent uniquement aux donn\u00E9es de configuration Vuze\u2122, vous devrez g\u00E9 [...]
+device.showGeneric=Afficher les p\u00E9riph\u00E9riques g\u00E9n\u00E9riques
+subscriptions.column.nb-subscribers=Abonn\u00E9s
+ConfigView.section.style.use_show_parent_folder.tooltip=L'activation de cette option vous permettra d'ouvrir le dossier contenant dans l'application de gestionnaire de fichier appropri\u00E9.\nToutefois, cela peut signifier que l'emplacement d'enregistrement des t\u00E9l\u00E9chargements n'est pas automatiquement s\u00E9lectionn\u00E9.
+PiecesView.DistributionView.title=R\u00E9partition des pi\u00E8ces
+MainWindow.menu.view.mytorrents.keybinding=Meta+1
+window.update.noupdates.text=Il n'y a pas de nouvelles mises \u00E0 jour disponibles pour vous.\n\nF\u00E9licitations \!
+ConfigView.pluginlist.noplugins=Aucun plugin trouv\u00E9.
+Views.plugins.aznetstatus.title=\u00C9tat du r\u00E9seau
+GeneralView.label.status.pieces_available=Pi\u00E8ces\u00A0
+ConfigView.section.file.defaultdir.auto=T\u00E9l\u00E9charger automatiquement dans le r\u00E9pertoire par d\u00E9faut (sans pr\u00E9venir)
+dlg.auth.enter.cancelled=Le code d'activation actuelle a \u00E9t\u00E9 annul\u00E9.
+ConfigView.section.mode.intermediate.wiki.publish=Publier des fichiers
+SpeedTestWizard.abort.message.failed.peers=Impossible de se connecter \u00E0 des pairs
+ConfigView.section.interface.password={ConfigView.section.tracker.password}
+TableColumn.header.down=T\u00E9l\u00E9charg\u00E9
+tag.type.ipset=D\u00E9finition de l'IP
+ConfigView.section.queue.seeding.firstPriority=Premi\u00E8re Priorit\u00E9
+SpeedView.stats.title=Statistiques
+ConfigView.section.transfer.autospeed.minupload.tooltip=Le d\u00E9bit d'upload ne sera normalement pas r\u00E9duite automatiquement en dessous de cette limite
+ConfigView.section.ipfilter.list.banned=a \u00E9t\u00E9 banni pour avoir envoy\u00E9 des mauvaises donn\u00E9es
+max.sr.window.message=Entrez un ratio partag\u00E9 cible [0\: d\u00E9sactiv\u00E9]
+ConfigView.section.proxy.username=Nom d'utilisateur
+IPChecker.external.service.dyndns.name=DynDNS
+ConfigView.section.connection.advanced.info.link=Voir ici pour plus de pr\u00E9cisions
+dht.advanced.label=Ne pas modifier ces valeurs sans savoir pourquoi
+UpdateWindow.close=Fermer
+wizard.file=Fichier\:
+SpeedTestWizard.test.panel.label=Test de vitesse de Vuze\u2122 \:
+UpdateMonitor.messagebox.restart.text=Vuze\u2122 vient de terminer le t\u00E9l\u00E9chargement d'une mise \u00E0 jour importante et doit \u00EAtre red\u00E9marr\u00E9 pour que la mise \u00E0 jour soit install\u00E9e.
+DHTView.db.direct=Direct
+ConfigView.section.file.readmblimit=Nombre maximum de requ\u00EAtes de lecture mises en file d'attente (en %1)
+webui.enable=Activer
+beta.wizard.disable.title=R\u00E9installation requise
+wizard.multitracker.edit.text=Modifier comme un texte
+trackername.prefs.title=Saisir l'affichage pratique pour les torrents multi-Tracker
+label.reapply=Appliquer de nouveau
+Security.jar.signfail=La signature du JAR a \u00E9chou\u00E9e - %1
+TagAddWindow.message=Entrez un nouveau nom de cat\u00E9gorie
+v3.activity.remove.text=\u00CAtes vous s\u00FBr de vouloir supprimer l'entr\u00E9e d'activit\u00E9 '%1' ?
+azbuddy.ui.table.online=En ligne
+TableColumn.header.sessionup=Session upload
+upnp.portchange.alert=Les ports suivants ont \u00E9t\u00E9 modifi\u00E9s pour \u00E9viter les probl\u00E8mes de p\u00E9riph\u00E9riques UPnP\: %1 [ancien port \=%2] %3 [ancien port \= %4]
+ConfigView.section.transfer=Transfert
+ConfigView.label.incrementalfile=Cr\u00E9ation incr\u00E9mentale des fichiers
+menu.delete.options={iconBar.remove}...
+swt.install.window.ok=Installer
+fileDownloadWindow.downloading=T\u00E9l\u00E9chargement depuis\u00A0\:
+TableColumn.header.AvgAvail.info=Somme des disponibilit\u00E9s des pi\u00E8ces divis\u00E9e par le nombre de pi\u00E8ces, divis\u00E9e par le nombre de connections
+wizard.hint.directory=Astuce\:\tVous pouvez choisir un seul r\u00E9pertoire avec le glisser/d\u00E9placer
+PeersView.state.pending=En cours
+device.view.heading=M\u00E9dia pour %1
+PeersView.incomingreqcount.info=Nombre de requ\u00EAtes entrantes faites par les pairs
+v3.MainWindow.menu.advanced=A&vanc\u00E9
+ConfigView.label.minimizetotray=R\u00E9duire dans la zone de notification lors de la r\u00E9duction de la fen\u00EAtre
+TableColumn.header.ipfilter=Filtre IP Activ\u00E9
+device.tag=\u00C9tiquette du p\u00E9riph\u00E9rique
+device.upnp.present_url=Administration du p\u00E9riph\u00E9rique
+PeersView.C2=C (Bloquant le client)
+wizard.maketorrent.piecesize=Taille d'une pi\u00E8ce
+PeersView.C1=C (\u00C9touff\u00E9 par le client)
+ConfigView.section.security.resetcerts.warning.msg=\u00CAtes-vous s\u00FBr de vouloir r\u00E9initialiser le magasin de certificats? Si vous avez cr\u00E9\u00E9 un certificat auto-sign\u00E9 ou en import\u00E9 un manuellement, ils seront perdus \!
+popup.error.hide=Cacher
+authenticator.savepassword=Retenir mon mot de passe
+TableColumn.header.profile.info=Profil de transcodage utilis\u00E9
+ConfigView.label.stop.Hibernate=Veille prolong\u00E9e de l'ordinateur
+v3.MainWindow.button.pause=Pause
+ConfigView.label.closetotray._mac=R\u00E9duire dans l'ic\u00F4ne de la barre d'\u00E9tat lors de la fermeture
+SpeedView.stats.idlePing=Ping de veille \:
+ConfigView.label.showsplash=Afficher l'\u00E9cran d'accueil au d\u00E9marrage
+subscriptions.info.avail=Vous n'avez pas encore ajout\u00E9 d'abonnements. %1 sont disponibles pour votre biblioth\u00E8que.
+webui.protocol=Protocole (*)
+label.initial_tags=Cat\u00E9gories initial
+config.external.browser.switch.implic=Cons\u00E9quences
+DHTTransport.report.timeout_some=hors d\u00E9lai, %1 paquets re\u00E7us de %2 mais incomplet
+ConfigView.section.tracker=Tracker
+exportTorrentWizard.process.exportfail.title=L'exportation du torrent a \u00E9chou\u00E9
+ConfigView.interface.start.advanced=D\u00E9marrer en vue avanc\u00E9e (AZ 2.x)
+ConfigView.section.style.TagInSidebar=Afficher des \u00E9tiquettes dans le menu lat\u00E9rale
+ConfigView.section.style.status=Zone d'\u00E9tat\u00A0\:
+GeneralView.label.timeelapsed=Temps \u00E9coul\u00E9\:
+ConfigView.label.passwordmatchyes=Oui
+installPluginsWizard.installMode.title=Veuillez choisir le type d'installation
+ConfigView.section.connection.group.peersources=Origines des clients
+ConfigView.section.interface.wavlocation.info=S\u00E9lectionner un fichier .wav ou laisser vide pour utiliser le son par d\u00E9faut.
+DHTView.db.keys=Cl\u00E9s
+ConfigView.section.file.max_open_files.tooltip=Utile si vous t\u00E9l\u00E9chargez des torrents compos\u00E9s de centaines de fichiers, et que vous atteignez la limite de gestion de fichiers du syst\u00E8me d'exploitation.
+devices.sidebar.mainheader.tooltip=%1 p\u00E9riph\u00E9riques sont cach\u00E9s (car g\u00E9n\u00E9rique ou non marqu\u00E9).\nFaites un clic droit pour voir les options permettant de les r\u00E9v\u00E9ler
+ConfigView.label.startNumSeeds=\nD\u00E9marrer la source quand il y a moins de\nA priorit\u00E9 sur les autres r\u00E8gles
+ConfigView.section.file.decoder.showall=Consid\u00E9rer tous les encodages possibles
+CacheView.writes.hits=Enregistr\u00E9
+TableColumn.header.sha1.info=Empreinte SHA1 du fichier (doit \u00EAtre enti\u00E8rement t\u00E9l\u00E9charg\u00E9, cliquez pour calculer)
+installPluginsWizard.file.no_such_file=Aucun fichier portant le nom sp\u00E9cifi\u00E9 n'existe.
+installPluginsWizard.finish.explanation=Les plugins s\u00E9lectionn\u00E9s seront install\u00E9s gr\u00E2ce \u00E0 l'assistant de mise \u00E0 jour.\n\nSoyez patients, la proc\u00E9dure peut prendre quelques minutes.\n\nPour des informations sur la progression, veuillez double-cliquer \u00E0 gauche dans la barre d'\u00E9tat.
+label.current.equals={label.current} %1
+configureWizard.nat.test=Tester
+PeersView.uniquepiece.none=Aucune
+TableColumn.header.uploadspeed.info=Vitesse \u00E0 laquelle nous envoyons des donn\u00E9es au pair
+dlg.auth.install.pct=%1% termin\u00E9
+TableColumn.header.name.info=Nom du torrent
+DHTView.title.full=Base de donn\u00E9es distribu\u00E9e
+unix.script.new.button.continue=Je le ferai plus tard
+ConfigView.section.connection.advanced.read_select=D\u00E9lai d'attente de la s\u00E9lection de lecture (milliseconde, par d\u00E9faut %1)
+devices.restrict_access.prompt=Restreindre l'acc\u00E8s \u00E0 '%1'
+StartStopRules.firstPriority=1\u00E8re Priorit\u00E9
+ConfigView.label.stop.Nothing=Ne rien faire
+tps.incoming.details=Actuel\: TCP \=%1, UDP \=%2; jamais \= %3
+MyTorrentsView.menu.movedata.dialog=Choisir la destination
+Peers.column.handshake_reserved=Octets r\u00E9serv\u00E9s au protocole de communication
+TableColumn.header.shareRatio.info=Correspond \u00E0 la quantit\u00E9 upload\u00E9 (partag\u00E9) par rapport celle qui a \u00E9t\u00E9 t\u00E9l\u00E9charg\u00E9.
+dht.override.ip=Forcer l'IP externe
+MyTorrentsView.menu.open_parent_folder=Ouvrez le dossier contenant
+MyTrackerView.downloaded=Qt\u00E9 re\u00E7ue
+TransferStatsView.title.full=Transferts
+wizard.tracker=Tracker\:
+ConfigView.section.tracker.passwordwebhttpsonly=Ne permet que l'acc\u00E8s par HTTPS
+ConfigView.section.style.colorOverride.warning=Attention
+v3.MainWindow.text.get.started=S'enregistrer
+azbuddy.name=Amis
+TableColumn.header.tracker.info=\u00C9tat du Tracker
+config.external.browser.switch.search.inf=N\u00E9cessite le plugin "Vuze\u2122 Web Remote"; Aucun r\u00E9sultats web; Aucun fonctions d'\u00E9dition de mod\u00E8le; Pas de cr\u00E9ation d'abonnement \u00E0 partir des r\u00E9sultats; Aucun r\u00E9glage de r\u00E9f\u00E9rent sur les liens de t\u00E9l\u00E9chargement
+GeneralView.section.availability=Disponibilit\u00E9
+Progress.reporting.detail.history.limit=La taille limite du message de d\u00E9tail (%1) pour ce report de progression a \u00E9t\u00E9 d\u00E9pass\u00E9; les messages ult\u00E9rieurs ne seront pas ajout\u00E9s \u00E0 l'historique
+Subscription.menu.deleteall=Effacer tous les r\u00E9sultats
+Trackers.column.leechers=Leechers
+device.configure=Configuration...
+MainWindow.status.warning.tooltip=Cliquez ici pour plus de d\u00E9tails
+azbuddy.ui.menu.sign=Signer le contenu du presse-papier
+AllPeersView.title.full=Tous les pairs
+platform.win32.baddll.nvLsp=NVIDIA nTune / ForceWare
+torrent.decode.info.order.bad=Avertissement Torrent \: le torrent '%1' n'est pas correctement format\u00E9 et peut g\u00E9n\u00E9rer un hachage incorrect\n\nConsulter <a href\="http\://wiki.vuze.com/w/Torrent_Info_Order_Bad">la Wiki Vuze\u2122</a> pour plus de d\u00E9tails (une solution est possible)
+DHTOpsView.idle=Veille - en attente d'activit\u00E9...
+ConfigView.label.passwordmatch=Mot de passe activ\u00E9\u00A0\:
+ConfigView.label.ircserver=Serveur
+LocaleUtil.title=Choisir le codage des caract\u00E8res
+Plugin.localtracker.wellknownlocals=Inclure automatiquement les rebouclage/liens/site (192.168 etc)
+ConfigView.label.minimizetotray._mac=R\u00E9duire dans l'ic\u00F4ne de la barre d'\u00E9tat lors de la r\u00E9duction de la fen\u00EAtre
+ConfigView.section.sharing=Partage
+config.external.browser.switch.search=R\u00E9sultats de la recherche
+ConfigView.dialog.choosemovepath=Choisissez le r\u00E9pertoire o\u00F9 d\u00E9placer les torrents compl\u00E9t\u00E9s
+MainWindow.menu.transfers.stopalltransfers=&Arr\u00EAter tout
+GeneralView.label.averagespeed=moyenne
+PiecesView.speed=Vitesse
+Trackers.column.interval=Intervalle
+ConfigView.label.movepartialdownloads=D\u00E9placer, m\u00EAme si certains fichiers sont marqu\u00E9s "Ne pas t\u00E9l\u00E9charger"
+ConfigView.section.stats.seconds=sec
+devices.profile=Profil
+Peers.column.pieces.info=Barre graphique repr\u00E9sentant quelles pi\u00E8ces le pairs a t\u00E9l\u00E9charg\u00E9
+Trackers.column.leechers.info=Leechers danse l'essaim
+subscript.add.upgrade.desc=Voulez vous mettre \u00E0 jour l'abonnement '%1'?
+MainWindow.menu.speed_limits.info.title=D\u00E9tails de limites de vitesse
+ConfigTransferAutoSpeed.auto.speed.classic=D\u00E9bit automatique (classic)
+MainWindow.dht.status.unreachabletooltip=Il semble qu'il y ait un probl\u00E8me avec le mapping du port de la base de donn\u00E9es distribu\u00E9e
+TableColumn.header.size.info=Taille du contenu du torrent sur le disque
+configureWizard.transfer.hint=Astuce\u00A0\: Choisir un d\u00E9bit l\u00E9g\u00E8rement inf\u00E9rieure \u00E0 votre connexion.
+ConfigView.section.tracker.server.group.networks=R\u00E9seaux
+subscriptions.config.autostartdls=D\u00E9marrer les t\u00E9l\u00E9chargements automatiquement (sinon ils s'ajoutent arr\u00EAt\u00E9s)
+LoggerView.filter.checkAll=S\u00E9lectionner toutes les cat\u00E9gories
+v3.MainWindow.search.go.tooltip=Lancer la Recherche
+ConfigView.label.popup.autohide=Masquer automatiquement apr\u00E8s x secondes les messages d'alerte ne comportant pas d'erreur (mis \u00E0 0 pour d\u00E9sactiver)
+pairing.srp.state=Statut\: %1
+ConfigView.section.file.deletion.section=Suppression de fichiers
+DownloadManager.error.ioerror=Erreur d'E/S
+dialog.pause.for.period.text=Mettre en pause les t\u00E9l\u00E9chargements et reprendre automatiquement dans [minutes]
+TableColumn.header.CountryFlag=Drapeau
+wizard.close.message=Voulez-vous ex\u00E9cuter cet assistant la prochaine fois que Vuze\u2122 est lanc\u00E9\u00A0?
+popup.more.waiting=%1 message(s) restant(s)...
+ConfigView.section.tracker.pollintervalincby=Augmenter de
+ConfigView.section.file.delete.confirm=Confirmer la suppression de contenu via la barre d'outils et la touche 'Suppr'
+MainWindow.status.latestversionunchecked=V\u00E9rification de mise \u00E0 jour d\u00E9sactiv\u00E9e
+ClientStats.column.count=Nombre
+TableColumn.header.done=Fait
+v3.MainWindow.button.play=Lire
+mdi.entry.about.dvdburn=Commencer
+device.browse=Parcourir
+ConfigView.section.file.delete.torrent=Par d\u00E9faut, supprimez le fichier.torrent lors de la suppression du contenu
+wizard.maketorrents.force=Force le lancement du torrent
+ConfigView.section.tracker.main=Principal
+Formats.units.B=o
+MyTorrentsView.menu.setpriority.low=&Basse
+ConfigView.section.style.status.show_ddb=\u00C9tat DDB
+wizard.singlefile=Un seul fichier
+ConfigView.label.minSpeedForActiveSeeding=Exclure les torrents compl\u00E9t\u00E9s de la file active si la vitesse est moins de
+SpeedTestWizard.name.conf.level.absolute=Absolu
+MainWindow.about.title=\u00C0 propos de Vuze\u2122
+LoggerView.realtime=Mettre \u00E0 jour en temps r\u00E9el
+Formats.units.kB=ko
+menu.add.peers={dialog.add.peers.title}...
+ConfigView.section.security.clearpasswords=R\u00E9initialiser les mots de passe r\u00E9cents
+device.rss.port=port de flux RSS
+remote.pairing.accesscode=Code d'acc\u00E8s \:
+devices.converting=Conversion
+device.error.copyfail2=Impossible de copier vers le p\u00E9riph\u00E9rique un ou plusieurs fichiers
+authenticator.title=Authentification requise
+Formats.units.bit=bit
+label.add.tag=Ajouter une cat\u00E9gorie...
+tag.type.ds.qfors=Mis en attente pour le seeding
+plugins.init.force_enabled=Vuze\u2122 a d\u00E9tect\u00E9 que le plugin "%1" a \u00E9t\u00E9 d\u00E9sactiv\u00E9e - il a \u00E9t\u00E9 r\u00E9activ\u00E9e pour permettre \u00E0 Vuze\u2122 de fonctionner correctement.
+ActivityView.legend.overhead=Taux de surcharge
+TableColumn.header.trackernextaccess.info=Quand le prochain acc\u00E8s au tracker va avoir lieu
+ColumnSetup.explain=Explorez les colonnes disponibles sur la gauche, et les ajouter \u00E0 la liste des colonnes visibles sur la droite. Agrandir ou r\u00E9duire la liste des colonnes disponibles en utilisant la section de filtre en bas \u00E0 gauche. Le 'Glisser et d\u00E9poser' et les raccourcis clavier sont \u00E9galement pris en charge.
+platform.win32.baddll.imon=NOD32
+MainWindow.upgrade.section.manual=Mise \u00E0 jour manuelle
+MyTorrentsView.menu.editTableColumns=Choix des &colonnes \u00E0 afficher
+window.updateswt.status.finding=Recherche de la version la plus r\u00E9cente
+MagnetPlugin.current.port=Port du gestionnaire URI
+PeersView.state.connecting=Se connecte
+v3.filter-bar=Filtrer sur le Titre \:
+tag.type.ds.qford=Mis en attente pour le t\u00E9l\u00E9chargement
+MainWindow.menu.file.share.dir=&R\u00E9pertoire
+ConfigView.section.invalid.value=Valeur non valide '%1' entr\u00E9e pour '%2'\: %3
+br.backup.manual.info=Configuration manuelle de la sauvegarde
+MyTorrentsView.menu.manual=&Manuellement...
+TorrentOptionsView.title.full=Options
+SpeedTestWizard.stage.message.preparing=pr\u00E9paration du test...
+FilesView.numberofpieces=\# de pi\u00E8ces
+upnp.alertsuccess=Rapporter les mappings r\u00E9ussis
+fileplugininstall.duplicate.desc=Le plugin '%1' version %2 est d\u00E9j\u00E0 install\u00E9
+DHTView.activity.status.false=Lanc\u00E9
+pairing.group.srp=Options de jumelage s\u00E9curis\u00E9s
+ConfigView.section.security.resetcerts=R\u00E9initialiser le magasin de certificats (n\u00E9cessite le red\u00E9marrage de Vuze\u2122)
+plugin.init.load.failed.classmissing=D\u00E9sinstaller le plugin via 'Outils-> Plugins -> Assistant de d\u00E9sinstallation', puis r\u00E9installez-le.
+platform.win32.baddll.nl_lsp=NetLimiter
+ConfigView.label.directory=Dans le r\u00E9pertoire\u00A0\:
+MyTorrentsView.menu.queue=Placer en &file d'attente
+MainWindow.about.internet.wiki=Wiki FAQ Vuze\u2122
+MainWindow.dialog.choose.savepath_forallfiles=Choisissez le r\u00E9pertoire de sauvegarde pour TOUS les fichiers
+platform.jvmopt.accesserror=Impossible d'acc\u00E9der au fichier d'options de la machines virtuelle Java\u2122\: %1
+VivaldiView.title.full=Vivaldi
+devices.sidebar.show.only.tagged=Afficher seulement les p\u00E9riph\u00E9riques \u00E9tiquet\u00E9s
+ConfigView.section.proxy.show_icon.flag.incoming=Afficher les connexions entrantes non-locales ou non-SOCKS comme \u00E9tant une erreur
+ConfigView.label.movecompleted=D\u00E9placer les fichiers achev\u00E9s
+PiecesView.reservedby=R\u00E9serv\u00E9
+dialog.pause.for.period.text2=Reprise automatique active \: %1 restante(s)...
+splash.unloadingTorrents=D\u00E9chargement des torrents
+Peers.column.DLedFromOthers.info=Quantit\u00E9 de donn\u00E9es t\u00E9l\u00E9charg\u00E9es des autres quand ils \u00E9taient connect\u00E9s \u00E0 vous.
+ConfigView.section.security.nopw_v=Aucun mot de passe disponible, merci de signer dans Vuze\u2122
+devices.always.cache=Cache de fichiers non transcod\u00E9s
+configureWizard.nat.unable=Test impossible
+ConfigView.section.ipfilter.autoload.file=Fichier de filtre IP pour le chargement automatique
+ConfigView.label.popupdownloadadded=Montrer une alerte 'popup' quand un t\u00E9l\u00E9chargement est ajout\u00E9
+DonationWindow.noload.title=Donation
+azbuddy.ui.table.msg_in=Msg entrant
+TableColumn.header.ProgressETA=Avancement
+MyTorrentsView.menu.export=Exporter en XML...
+platform.jvmopt.sunonly=Seules les machines virtuelles Java\u2122 de Sun\u2122 et d'Oracle\u2122 sont support\u00E9s (fournisseur actuel \=%1)
+window.updateswt.ok=Ok
+Subscription.menu.properties=Propri\u00E9t\u00E9s
+v3.MainWindow.menu.browse=&Naviguer
+security.certcreate.org=Organisation
+ConfigView.section.transfer.select=D\u00E9bit automatique
+Views.plugins.Distributed.Tracker.title=Tracker distribu\u00E9
+ClientStats.column.received={DHTView.transport.received}
+beta.wizard.info=L'inscription au programme Beta de Vuze\u2122 vous donne un acc\u00E8s rapide aux fonctions de modification dans le logiciel client\n\nAvec ces fonctionnalit\u00E9s, vous allez pouvoir les exp\u00E9rimenter et nous aider \u00E0 fa\u00E7onner la mani\u00E8re dont ils sont mis en \u0153uvre - nos recommandations nous \u00E9tant extr\u00EAmement utile \!\n\nPar leur nature, les versions b\u00EAta peuvent \u00EAtre instables. Cependant, la s\u00E9lection de cette option vous [...]
+security.crypto.password=Mot de passe
+popup.download.added="%1" a \u00E9t\u00E9 ajout\u00E9 \u00E0 votre liste de t\u00E9l\u00E9chargement.
+TableColumn.header.tag.name=Nom de la cat\u00E9gorie
+iconBar.remove.tooltip=Enlever
+dlg.stream.plus.text=Mettre \u00E0 niveau vers Vuze\u2122 Plus et lire vos vid\u00E9os pendant leur t\u00E9l\u00E9chargement.
+Peers.column.UpRatio=Ratio de l'envoi
+DHTView.operations.received=Re\u00E7u
+LocaleUtil.label.checkbox.rememberdecision=Se souvenir du r\u00E9glage pour les autres fichiers
+download.removerules.removed.ok=La suppression automatique du torrent '%1' a \u00E9t\u00E9 effectu\u00E9e avec succ\u00E8s. Ceci est d\u00FB aux r\u00E8gles de suppression.
+ConfigTransferAutoSpeed.data.update.frequency=Fr\u00E9quence de mise \u00E0 jour
+TableColumn.header.torrentpath=Chemin d'acc\u00E8s du torrent
+MyTorrents.column.ColumnProgressETA.PlayableIn=Visionnable depuis le %1
+iconBar.showDownloadBar.tooltip=Afficher la barre de t\u00E9l\u00E9chargement
+dht.execute.command=Commande de diagnostic
+TableColumn.header.pieces.info=Barre graphique repr\u00E9sentant quelles pi\u00E8ces vous avez t\u00E9l\u00E9charg\u00E9
+Progress.reporting.default.error=Erreur
+SpeedTestWizard.abort.message.manual.abort=Interrompu manuellement
+DHTView.activity.target=Cible
+v3.deviceview.infobar.line2.psp=Les vid\u00E9os seront copi\u00E9s sur votre PSP d\u00E8s qu'il sera connect\u00E9e.
+platform.win32.baddll.nvappfilter=NVidia Firewall
+ConfigView.label.maxuploadspeed=ko/s Vitesse globale maximale d'envoi [0\u00A0\: illimit\u00E9e]
+ConfigView.label.passwordmatchno=Non / Les mots de passe ne correspondent pas
+IrcClient.defaultChannel=\#Azureus-French
+devices.cat.show=Afficher les cat\u00E9gories
+MyLibrary.bigView.header={sidebar.Library}
+configureWizard.finish.title=Termin\u00E9
+ConfigTransferAutoSpeed.adjustment.interval=Intervalle d'ajustement\:
+ConfigView.label.peers=clients
+jvm.show.file=Le fichier local des options de la machines virtuelle Java\u2122 est situ\u00E9 \u00E0 cet emplacement \: '%1' - Fournit seulement \u00E0 des fins de r\u00E9cup\u00E9ration.
+TableColumn.header.downspeed.info=Vitesse de t\u00E9l\u00E9chargement actuelle
+MyTorrentsView.menu.setSpeed.unlimited=Illimit\u00E9e
+security.certcreate.strength=Puissance
+ConfigView.text.neverStop=Ne jamais arr\u00EAter
+ConfigView.label.startwatchedtorrentsstopped=Commencer arr\u00EAt\u00E9
+UpdateWindow.title=Mise \u00E0 jour de Vuze\u2122
+TableColumn.header.RateIt=Noter
+ConfigView.label.seeding.rankType.peer.tooltip=plus de pairs et moins de 'seeds' \=rang sup\u00E9rieur\nCe classement minimise le nombre de torrents qui doivent \u00EAtre maintenus en activit\u00E9 pour maximiser le t\u00E9l\u00E9chargement
+Main.parameter.maxUploads=Nombre max d'envois simultan\u00E9s
+ConfigView.label.downloading.info=Le r\u00E9glage automatique de la position dans la file d'attente de t\u00E9l\u00E9chargement fonctionne mieux lorsque vous avez d\u00E9fini une vitesse limite de t\u00E9l\u00E9chargement qui concorde avec vos capacit\u00E9s de r\u00E9seau
+general.enter.cookies=Entr\u00E9e Cookies
+TableColumn.header.maxuploads=Nb max d'envois
+wizard.invalidurl=Cette URL n'est pas valide
+ConfigView.section.tracker.client.scrapestoppedenable=Utiliser le scrape sur les torrents non actifs
+SpeedView.stats.con_details=total\=%1, d\u00E9bloqu\u00E9\=%2, en attente\=%3, bloqu\u00E9\=%4
+speedtest.wizard.select.group=Type de Test
+PeersView.T.R.tooltip=un client vous a contact\u00E9.
+config.external.browser=Navigateur externe
+v3.deviceview.infobar.line2.ps3=Diffusez des vid\u00E9os en vous rendant dans l'interface graphique de votre PS3 et en s\u00E9lectionnant Vid\u00E9os -> Vuze.
+ConfigView.section.transfer.lan.uploadrate=ko/s LAN vitesse maximale d'envoi [0\u00A0\: illimit\u00E9e]
+TableColumn.header.Country=Pays
+upnp.selectedaddresses=Adresses (s\u00E9par\u00E9 par ';', prefix '-' \= refuser, '+' \= autoriser) [vide\: toutes]
+fileDownloadWindow.saveTorrentIn=Sauvegarder le fichier torrent dans
+wizard.newtorrent.byo.editname.text=Saisir le nom de l'\u00E9l\u00E9ment tel qu'il appara\u00EEt dans le torrent
+StartStopRules.waiting=En attente
+ConfigView.label.seeding.rankType.peerSeed.tooltip=Taux plus haut \= rang plus \u00E9lev\u00E9
+ConfigView.section.transfer.autospeed.enableauto=Activer lors du t\u00E9l\u00E9chargement et du seeding
+cat.upload.priority=Priorit\u00E9 d'upload
+PeersView.menu.kickandban.reason=Client banni manuellement
+label.uptime_coarse=disponibilit\u00E9%1%2
+ConfigView.label.userequestlimiting=Utilisez la limitation des demandes au lieu de lectures diff\u00E9r\u00E9es pour limiter la vitesse de t\u00E9l\u00E9chargement [aucun effet lorsque la vitesse de t\u00E9l\u00E9chargement est illimit\u00E9]
+ConfigView.section.transfer.lan.downloadrate.tooltip=Limite de t\u00E9l\u00E9chargement propre aux clients sur un m\u00EAme r\u00E9seau local
+MyTorrentsView.dialog.NumberError.text=Le nombre entr\u00E9 n'est pas valide ou pas reconnu
+security.crypto.encrypt=Merci de saisir un mot de passe pour prot\u00E9ger votre cl\u00E9 de chiffrement nouvellement g\u00E9n\u00E9r\u00E9. Merci de ne pas oublier ce mot de passe, il n'y a aucun moyen de le r\u00E9cup\u00E9rer \!
+button.nothanks=Non Merci
+webui.pairingtest=\tCliquez pour tester le jumelage
+Peers.column.handshake_reserved.info=Indique que les bits r\u00E9serv\u00E9s sont \u00E9tablis dans le cadre du protocole de communication BT
+exportTorrentWizard.torrentfile.path=Chemin
+UpdateWindow.restartLater=Red\u00E9marrer plus tard
+ConfigView.label.queue.retainforce=Passage des t\u00E9l\u00E9chargements en mode 'Forcer le d\u00E9marrage' en mode 'Forcer le partage' une fois termin\u00E9s
+min.sr.window.title=Ratio partag\u00E9 minimum
+devices.turnon.prepageload=Pour activer cette fonction, l'installation de composants suppl\u00E9mentaires est n\u00E9cessaire.
+ConfigView.section.file.max_open_files=Nombre maximum de fichiers ouverts en\nlecture/\u00E9criture (0 \= illimit\u00E9)
+device.manu.desc=Fabricant
+TableColumn.header.eta=Restant
+devices.choose.device.info.text=La prochaine fois, il suffit de glisser-d\u00E9poser des fichiers sur le p\u00E9riph\u00E9rique de votre choix dans la barre lat\u00E9rale.
+ConfigView.section.tracker.announcecacheminpeers=Seuil de client pour activation du cache de l'annonce
+ConfigView.label.openconfig=Ouvrir le menu Options au d\u00E9marrage
+ConfigView.section.style.defaultSortOrder.asc=Croissant
+OpenTorrentOptions.header.torrentinfo=Information du torrent
+GeneralView.section.downloaded=T\u00E9l\u00E9charg\u00E9
+wizard.multitracker.title=Multi-tracker
+FileItem.donotdownload=Ne pas t\u00E9l\u00E9charger
+swt.uninstall.window.header=Les composants suivants ont \u00E9t\u00E9 s\u00E9lectionn\u00E9s pour \u00EAtre supprim\u00E9s \:
+FilesView.menu.setpriority.skipped=Ne pas &t\u00E9l\u00E9charger
+ipCheckerWizard.explanations=Cet assistant vous aide \u00E0 d\u00E9terminer votre adresse IP externe. Si votre IP est dynamique, il est conseill\u00E9 d'ouvrir un compte avec un Dynamic DNS Service. De tels services sont list\u00E9s ci-dessous, utiliser le lien fourni pour cr\u00E9er un compte. Remplissez alors le champ IP avec votre nom d'h\u00F4te (e.g. monnomdhote.dyndns.org). Vous aurez besoin d'un programme qui mettra \u00E0 jour Dynamic DNS Service avec votre adresse IP. De cette m [...]
+ConfigView.section.queue=File d'attente
+IrcClient.hasjoined=a rejoint le canal
+MainWindow.menu.speed_limits=Limites de vitesse
+PeersView.discarded.info=Pi\u00E8ces re\u00E7ues alors que vous les aviez d\u00E9j\u00E0. Elimin\u00E9es.
+group.auto=Auto
+ConfigView.section.connection.group.networks.info=S\u00E9lectionner les r\u00E9seaux permis par d\u00E9faut pour les transmissions de donn\u00E9es client-client
+label.con_prob=Probl\u00E8mes de connexion
+MyTrackerView.status.started=En marche
+device.config.xcode.disable_sleep=Emp\u00EAcher ordinateur de se mettre en veille lors du transcodage
+ConfigView.label.minSpeedForActiveDL.tooltip=Un cr\u00E9neau de t\u00E9l\u00E9chargement est utilis\u00E9 pendant les 30 premi\u00E8res secondes\nde d\u00E9marrage d'un torrent incomplet.
+TableColumn.header.eta.info=Temps estim\u00E9 avant que le torrent ait termin\u00E9 le t\u00E9l\u00E9chargement
+MainWindow.menu.transfers.pausetransfersfor=Pause pour...
+MainWindow.menu.torrent=T&orrent
+exportTorrentWizard.finish.message=Exportation termin\u00E9 avec succ\u00E8s
+label.show.all=Afficher tout
+TableColumn.header.torrentrelpath.info=Emplacement relatif du fichier dans le torrent
+authenticator.realm=Domaine
+MySharesView.type=Type
+dlg.stream.plus.renew.subtitle=Renouvellement de Vuze\u2122 Plus
+PeerSocket.unknown_az_style=Inconnu %1 %2
+ConfigView.section.connection.advanced.write_select=D\u00E9lai d'attente de la s\u00E9lection d'\u00E9criture (milliseconde, par d\u00E9faut %1)
+splash.initializeGui=Initialisation de la fen\u00EAtre principale...
+upnp.ignorebaddevices.info=P\u00E9riph\u00E9riques actuellement ignor\u00E9s\: %1
+ConfigView.label.seeding.ignore0Peers=Ignorer les torrents avec 0 client
+ConfigView.label.showuptime=Afficher le temps de disponibilit\u00E9
+devices.cancel_xcode_del=Annuler la conversion/Supprimer
+manual.mode=Manuel
+ipCheckerWizard.service.url=Lien\:
+ConfigView.section.proxy.show_icon=Afficher l'ic\u00F4ne SOCKS dans la barre d'\u00E9tat lorsque celui-ci est activ\u00E9
+splash.of=sur
+azbuddy.ui.table.loc_cat=Cats sortant
+OpenTorrentOptions.show.always=\u00E0 chaque fois
+plugins.basicview.progress=Progression\:
+ConfigView.section.connection.encryption.encrypt.fallback_info=Activer les options de repli va permettre des connections aux clients non compatibles mais elles seront non crypt\u00E9es
+resetconfig.warn=Cela entra\u00EEnera la perte de toutes les modifications que vous avez apport\u00E9es \u00E0 votre configuration Vuze\u2122.\nR\u00E9initialiser tout de m\u00EAme la configuration ?
+dlg.auth.install.subtitle.plus=Installation de Vuze\u2122 plus...
+OpenTorrentOptions.show.many=uniquement lorsqu'il y a plus d'1 fichier
+ConfigView.pluginlist.column.version=Version
+MyTorrentsView.menu.exportmenu=Exporter
+ConfigView.section.connection.encryption.encrypt.info.link=Voir ici pour plus de pr\u00E9cisions
+MyTorrentsView.menu.moveUp=Vers le h&aut
+MyTorrents.column.ColumnProgressETA.2ndLine=Reste\: %1
+v3.MainWindow.button.delete=Supprimer
+MainWindow.status.updowndetails.tooltip=D\u00E9tails sur les vitesses de t\u00E9l\u00E9chargement/envoi - changer par clic droit
+#connected to more seeds/peers than tracker reports
+Column.seedspeers.started.over=%1
+exportTorrentWizard.torrentfile.invalidPath=Fichier torrent invalide
+MyTorrentsView.menu.rename.save_path=Renommer le chemin de sauvegarde
+Subscription.menu.upgrade=Activer la mise \u00E0 jour a une version sup\u00E9rieure
+installPluginsWizard.file.title=Veuillez choisir le plugin \u00E0 installer
+ConfigView.section.security.publickey.undef=Pas encore d\u00E9fini
+MyTorrentsView.menu.tracker=Tracker/Torrent
+MainWindow.statusText.checking=V\u00E9rification des mises \u00E0 jour
+upnp.refresh.label=Rafra\u00EEchir les mappings
+swt.install.window.header=Les composants suivants ont \u00E9t\u00E9 s\u00E9lectionn\u00E9s pour \u00EAtre install\u00E9s \:
+ManagerItem.stopped=Arr\u00EAt\u00E9
+platform.win32.baddll.InjHook12=Torrent Ratio Keeper
+Button.dismiss=Rejeter
+UpdateWindow.ok=Ok
+ConfigView.pluginlist.info=Les plugins suivants ont \u00E9t\u00E9 identifi\u00E9s. Certains plugins peuvent ne pas avoir d'onglet de configuration.
+security.crypto.title=Acc\u00E8s \u00E0 la cl\u00E9 de chiffrement
+MainWindow.about.internet.homepage=Page d'accueil de Vuze\u2122
+network.enforce.ipbinding=Appliquer les liaisons IP, m\u00EAme lorsque les interfaces ne sont pas disponibles, emp\u00EAche toute connexion si aucune des interfaces sp\u00E9cifi\u00E9es n'est disponible
+dlg.corewait.text=Un moment, S'il vous pla\u00EEt...\n\nVotre demande sera trait\u00E9e apr\u00E8s que Vuze\u2122 aura termin\u00E9 l'initialisation
+StartStopRules.menu.viewDebug=Voir les informations de d\u00E9bogage
+label.num.torrents=%1 {ConfigView.section.torrents}
+ConfigView.section.transfer.autospeed.enableautoseeding=Activer seulement lors du seeding
+FilesView.path=Chemin d'acc\u00E8s
+br.restore.warning.title=Perte de configuration Attention \!
+subscriptions.search.enable=Activer la recherche de r\u00E9sultats d'abonnement (red\u00E9marrage n\u00E9cessaire)
+ConfigView.label.prioritizefirstpiece.tooltip=Tente de t\u00E9l\u00E9charger le d\u00E9but d'un fichier en premier.\nPeut permettre la pr\u00E9visualisation.
+update.now.desc=Vuze\u2122 doit appliquer des mises \u00E0 jour pour terminer la migration.\n\nApr\u00E8s la fermeture de cette bo\u00EEte de dialogue, Windows pourra vous invit\u00E9 \u00E0 terminer le processus de mise \u00E0 jour.\n\nLe red\u00E9marrage de Vuze\u2122 ne sera pas n\u00E9cessaire.
+ConfigView.label.xfer.bias_no_limit=Tenter d'appliquer l'upload pertinent quand il n'y a pas de limite globale efficace d'upload
+iconBar.openURL.tooltip=Ouvrir une URL
+CacheView.general.inUse=Utilisation
+ConfigView.label.startRatioPeers=D\u00E9marrer le torrent quand il y a moins de 1 source pour
+TableColumn.header.CountryCode=CC
+Main.parameter.maxSpeed=Vitesse d'envoi max en octets/s
+#file can be a URL or a path in the jar
+MainWindow.menu.help.releasenotes=Voir le journal des modifications
+option.rememberthis=Se souvenir de ce r\u00E9glage
+ConfigView.title.short=Options
+FileItem.storage.reorder=R\u00E9organiser
+TableColumn.header.completion=\u00C9tat d'avancement
+TableColumn.header.commenticon=Ic\u00F4ne de commentaire
+v3.menu.device.exploreTranscodes=Afficher les fichiers
+pairing.view.registered=Cliquez pour voir les d\u00E9tails de l'enregistrement actuelle
+ConfigView.dialog.choosewatchtorrentfolderpath=Choisissez le r\u00E9pertoire o\u00F9 importer des .torrent
+ConfigView.label.seeding.preferLargerSwarms.tooltip=Si vous \u00EAtes source de principalement des torrents avec des clients "bloqu\u00E9s", pr\u00E9f\u00E9rer les plus utilis\u00E9s\nSi vous \u00EAtes source de principalement des torrents \u00E0 haute disponibilit\u00E9, pr\u00E9f\u00E9rer les moins utilis\u00E9s.
+ConfigView.section.interface.cleartrackers=Effacer les trackers r\u00E9cents
+label.bar.trans=Transparence de barre [0 \= opaque; 100 \= transparent]
+device.playnow.buffer=Taille de la m\u00E9moire tampon avant que la lecture commence [s]
+MainWindow.menu.help.plugins=Plugins
+proxy.socks.bad.incoming=Connexions entrantes non proxy d\u00E9tect\u00E9es \!
+v3.activity.remove.title=Supprimer l'entr\u00E9e d'activit\u00E9
+sidebar.LibraryDL.tooltip=Il y a %1 torrent(s) incomplet(s), dont %2 est/sont en cours de t\u00E9l\u00E9chargement
+menu.selectfilesinfolder=S\u00E9lectionner tous les fichiers dans%1
+devices.activation=Activation du p\u00E9riph\u00E9rique
+MyTrackerView.status=\u00C9tat
+sidebar.top.level.gap=\u00C9cart entre les en-t\u00EAtes de ligne ({ConfigView.section.security.restart.title})
+TableColumn.header.filesdone.info=Fichiers termin\u00E9s / Total des fichiers * ou * fichiers non ignor\u00E9s et termin\u00E9s (Fichiers termin\u00E9s) / Total des fichiers non ignor\u00E9s (Nombre total de fichiers)
+ConfigView.section.transfer.lan.enable=Activer des limites de vitesse distincts pour les connexions LAN
+ConfigView.section.connection.advanced.SO_RCVBUF=Taille de la socket SO_RCVBUF [0\: utilise la valeur par d\u00E9faut du syst\u00E8me d'exploitation]
+ConfigView.section.connection.advanced=Configuration r\u00E9seau avanc\u00E9e
+MainWindow.upgrade.section.automatic=Mise \u00E0 jour automatique
+TrackerView.title.full=Sources
+FileItem.delete=Supprim\u00E9
+ConfigView.label.bindip=Associer \u00E0 l'adresse IP locale ou \u00E0 l'interface
+MyTorrentsView.menu.exporttorrent=Exporter le torrent...
+core.shutdown.se=seedings termin\u00E9
+Button.sendNow=Envoyer maintenant
+subs.prop.auth=Authentification requise
+wizard.hint.file=Astuce\:\tVous pouvez choisir un seul fichier avec le glisser/d\u00E9placer
+upnp.mapping.udptrackerport=Port Tracker UDP
+label.click.to.change=Cliquez pour changer
+window.updateswt.text=Votre version de SWT est d\u00E9pass\u00E9e\u00A0\!\nSWT est le c\u0153ur de l'interface graphique d'Azureus. Appuyez sur OK pour commencer la mise \u00E0 jour de SWT.
+wizard.tracker.ssl=Utiliser SSL
+security.certcreate.cancel=Annuler
+ConfigView.section.tracker.publishenable=Publier les d\u00E9tails du torrent vers "<tracker_url>/"
+MyTorrents.column.ColumnSpeed=Vitesse
+deletecontent.also.deletetorrent=Supprimer \u00E9galement le fichier .torrent
+externalLogin.title=Identification requise
+ConfigView.section.tracker.client.showwarnings=Afficher les avertissements des trackers
+label.DNS=DNS
+TorrentOptionsView.param.upload.priority=Priorit\u00E9 d'upload [0\=d\u00E9faut; 1\=prioritaire]
+dlg.auth.enter.link.try.2=<A Href\="lien"> Cliquez ici </A> Si vous n'avez pas encore acquis votre copie de Vuze\u2122 Plus.
+dlg.auth.enter.link.try.1=Vous n'avez pas de code d'activation ? <A HREF\="upgrade"> Mettre \u00E0 niveau maintenant </A>.
+Button.clear=Effacer
+Peers.column.UpDownRatio.info=Taux "Envoy\u00E9\:T\u00E9l\u00E9charg\u00E9" du client
+ConfigView.label.seeding.firstPriority.FP=Premi\u00E8re Priorit\u00E9
+subs.prop.update_period=P\u00E9riode de Mise \u00E0 jour
+tray.options=Options de la zone de notification
+GeneralView.label.swarm_average_completion=Compl\u00E9tion moyenne\:
+TableColumn.header.azsubs.ui.column.subs_link=Association
+ConfigView.section.ipfilter.edit=\u00C9diter
+device.od.error.opfailstatus=Le p\u00E9riph\u00E9rique n'a pas pu traiter la commande %1\: \u00E9tat %2
+OpenTorrentWindow.fileTable.fileName=Fichier
+ConfigView.section.language.enableUpdate=Activer la mise \u00E0 jour par le Web
+dht.info=Ce plugin supporte le tracking d\u00E9centralis\u00E9, entre autres - le d\u00E9sactiver r\u00E9duit votre habilit\u00E9 \u00E0 t\u00E9l\u00E9charger
+library.unopened.header.p=%1 \u00E9l\u00E9ments
+label.num_queued=%1 en attente
+FileView.BlockView.Outstanding=En suspens
+ConfigView.section.file.delete.include_files_outside_save_dir=Lors de la suppression des donn\u00E9es, permettre aux fichiers, li\u00E9s en dehors du r\u00E9pertoire de sauvegarde des torrents, de les supprimer \u00E9galement
+ConfigView.button.browse=Parcourir...
+device.error.copyfail=Impossible de copier vers le dossier un ou plusieurs fichiers
+PeersView.piece=Pi\u00E8ce
+download.removerules.unauthorised.seedingonly=\tSeulement si en source
+dlg.auth.revoked=Code d'activation r\u00E9voqu\u00E9
+br.restore.warning.info=La restauration de votre configuration remplacera l'existante.\n 
+security.crypto.decrypt=Merci de saisir le mot de passe pour d\u00E9verrouiller votre cl\u00E9 de chiffrement.
+custom.settings.import.res=%1 param\u00E8tres import\u00E9s.%2
+label.missing=Manquant
+ConfigView.section.server=Connexion
+TrackerChangerWindow.newtracker=Entrez de nouvelle URL(s) de Tracker - s\u00E9par\u00E9 par une virgule
+config.external.browser.switch.info=Vous pouvez basculer d'un navigateur interne \u00E0 un navigateur externe pour certaines fonctions, m\u00EAme si certaines fonctionnalit\u00E9s peuvent \u00EAtre perdues
+tag.type.ds=\u00C9tat des t\u00E9l\u00E9chargement
+security.crypto.persist_for.dont_save=Ne pas enregistrer
+general.add.friends=Ajouter quelques amis \!
+FilePriority.invalid.title=Priorit\u00E9 invalide
+ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrents pour lesquelles ne rien uploader pour
+ConfigView.section.mode.advanced.wiki.main=Page Principale du Wiki
+remote.pairing.tip.text=La barre d'outils 'Vuze\u2122 Remote Toolbar' \: Visitez la page<A HREF\="http\://remote.vuze.com/download/">remote.vuze.com/t\u00E9l\u00E9chargement </A>\n'Vuze\u2122 Remote Mobile' \: Visitez la page <a href \= "http\://remote.vuze.com/">remote.vuze.com</A> dans votre navigateur mobile.
+devices.contextmenu.od=T\u00E9l\u00E9chargement hors ligne
+tps.status.available=Disponible
+configureWizard.nat.message=Afin de tirer le meilleur parti de Vuze\u2122, il est fortement recommand\u00E9 d'\u00EAtre pleinement accessible depuis Internet. Cet outil vous permet de tester et/ou de modifier les ports utilis\u00E9s pour accepter les connexions entrantes\n\nREMARQUE\: le port TCP 6880 est utilis\u00E9 en interne, il ne peut donc \u00EAtre utilis\u00E9.
+PasswordWindow.passwordprotected=Vuze\u2122 est prot\u00E9g\u00E9 par un mot de passe.\nPour r\u00E9tablir Vuze\u2122 veuillez entrer votre mot de passe \:
+GeneralView.label.downloaded=T\u00E9l\u00E9charg\u00E9\u00A0\:
+dht.advanced.group=R\u00E9glages avanc\u00E9s
+MainWindow.menu.view.allpeers=Tous les pairs
+ConfigView.complete.abbreviated=C\:
+TableColumn.header.AzProduct=De
+ConfigView.section.sharing.rescanenable=Activer un scan p\u00E9riodique des partages (pour inclure des changements)
+iconBar.details=D\u00E9tails
+Button.save=Enregistrer
+ConfigView.label.seeds=sources
+DHTView.transport.sent=Envoy\u00E9
+TableColumn.header.torrentpath.info=Chemin d'acc\u00E8s du torrent sur le disque
+SpeedView.uploadSpeed.title=Vitesse d'envoi
+fileDownloadWindow.state_error=Erreur\u00A0\:
+importTorrentWizard.process.outputfileexists.message=Le fichier destination existe d\u00E9j\u00E0\u00A0; le remplacer\u00A0?
+devices.sidebar.hide.rend.generic=Masquer p\u00E9riph\u00E9riques g\u00E9n\u00E9riques
+MyTorrentsView.menu.remove=&Enlever
+v3.MainWindow.search.defaultText=Rechercher des Fichiers torrents
+v3.mb.delPublished.delete=&Supprimer
+wizard.newtorrent.byo.editname.title=Saisie du nom de l'\u00E9l\u00E9ment
+dlg.player.install.description=Installation du composant de lecture suppl\u00E9mentaire ...
+library.all.header=%1 \u00E9l\u00E9ment\: %2 actif
+ConfigView.section.connection.group.webseed='Seeds' Web/HTTP
+speedtest.wizard.test.mode.updown=partage et t\u00E9l\u00E9chargement
+ConfigView.section.file.writemblimit=Nombre maximum de requ\u00EAtes d'\u00E9criture mises en file d'attente (en %1)
+ConfigView.section.security.resetkey=R\u00E9initialiser les cl\u00E9s
+devices.turnon.qos=Partager anonymement les statistiques des p\u00E9riph\u00E9riques avec Vuze\u2122
+stream.analysing.media=Analyse du m\u00E9dia
+Button.finish=Terminer
+iconBar.down=Bas
+v3.share.private.text=Le torrent s\u00E9lectionn\u00E9 est marqu\u00E9 comme "priv\u00E9".\n\nVous ne pouvez pas partager des torrents priv\u00E9s
+ConfigView.section.ipfilter.description=Description
+label.route=Route
+ConfigView.section.file.perf.cache.size=Taille du cache en %1
+v3.mb.PlayFileNotFound.button.redownload=Ret\u00E9l\u00E9charger les donn\u00E9es
+devices.xcode.remove.vetoed=Le transcodage de '%1' est en cours, le t\u00E9l\u00E9chargement ne peut pas \u00EAtre retir\u00E9 tant que le transcodage n'est termin\u00E9 ou annul\u00E9e \u00E0 partir de la page 'P\u00E9riph\u00E9rique'.
+TableColumn.menu.date_added.reset=Date de r\u00E9initialisation
+label.showhide.tag=Afficher/Masquer les cat\u00E9gorie(s)
+MainWindow.menu.window.minimize.keybinding=Meta+M
+ConfigView.section.file.perf.explain=Attention - Des changements inappropri\u00E9s \u00E0 ces param\u00E8tres peuvent diminuer la vitesse de vos transferts. Si vous avez des probl\u00E8me de\nsaturation de m\u00E9moire, diminuez le nombres de clients connect\u00E9s et/ou actifs par d\u00E9faut par torrent. (Options > Transfert)
+configureWizard.finish.message=Vuze\u2122 est maintenant configur\u00E9, amusez-vous bien\u00A0\!
+importTorrentWizard.torrentfile.invalidPath=Fichier torrent invalide
+ConfigView.section.tracker.scrapecacheperiod=Cache du "Scrape" (ms)
+PeersView.C2.info=Si vous emp\u00EAcher un client de t\u00E9l\u00E9charger
+security.crypto.persist_for.day=1 jour
+v3.share.private.title=Partage de Torrents
+device.itunes.status.running=iTunes est en cours d'ex\u00E9cution
+mdi.entry.games=Jeux
+importTorrentWizard.finish.message=Importation termin\u00E9 avec succ\u00E8s
+ConfigView.section.stats.defaultsavepath=R\u00E9pertoire de sauvegarde des statistiques
+externalLogin.explanation.capture=Vous devez vous identifier pour cr\u00E9er ce mod\u00E8le. Une fois connect\u00E9, merci de cliquer sur "Termin\u00E9".
+ConfigView.section.dns.allow_socks=Utilisez lorsque la recherche de serveur proxy SOCKS a \u00E9chou\u00E9
+FilesView.done=Fait
+security.certcreate.state=\u00C9tat ou Province
+platform.win32.baddll.vlsp=Venturi Firewall
+ConfigView.section.logging.choosedefaultsavepath=Veuillez choisir le r\u00E9pertoire de sauvegarde
+PluginDeprecation.log.start=Cette fen\u00EAtre contient des informations sur les plugins qui utilisent des fonctionnalit\u00E9s qui seront supprim\u00E9es dans les prochaines versions de Vuze\u2122.\nVous n'avez pas besoin de d\u00E9sinstaller les plugins, vous devez simplement mettre \u00E0 jour les plugins concern\u00E9s.\nSi d\u00E9j\u00E0 vous utilisez la derni\u00E8re version, merci de copier le contenu de cette fen\u00EAtre et de l'afficher dans le forum situ\u00E9 ici\:\n\t%1\n\n
+TableColumn.header.peakdown=T\u00E9l\u00E9chargement \u00E9lev\u00E9
+Column.seedspeers.notstarted=%2
+Plugin.localtracker.autoadd=\    Pairs explicites
+TableColumn.header.Quality=Qualit\u00E9
+ConfigView.label.seeding.rankType.seed.fallback=Revenir au taux Clients/Sources apr\u00E8s\n(0\u00A0\: ne pas y revenir)
+ConfigView.label.use_old_speed_menus=Utilisez les menus de vitesse dans le style ancien [red\u00E9marrage n\u00E9cessaire]
+devices.contextmenu.od.enabled=Actif
+TableColumn.header.totalspeed.info=Vitesse d'envoi individuelle de tout les autres clients/sources auquel vous \u00EAtes reli\u00E9s. Votre vitesse de t\u00E9l\u00E9chargement \u00E0 ceux-ci n'est pas compt\u00E9e dans ce total.
+OpenTorrentFile.column.\#=\#
+message.confirm.delete.text=\u00CAtes-vous certain de vouloir supprimer '%1'?
+ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=Force l'utilisation de connections crypt\u00E9es avec les autres clients
+Progress.reporting.status.canceled=Annul\u00E9
+dlg.install.vuzexcode.description=Merci de patienter pendant que le composant 'Media Analyzer' s'installe
+iconBar.play.tooltip=Lire le contenu s\u00E9lectionn\u00E9
+Wizard.Subscription.rss.subtitle3=Une fois enregistr\u00E9, vous recevrez des mises \u00E0 jour dans votre menu lat\u00E9rale lorsque de nouveaux r\u00E9sultats sont disponibles via votre flux RSS.
+SpeedTestWizard.set.limit.conf.level=Confiance
+Wizard.Subscription.rss.subtitle2=De nombreux \u00E9diteurs fournissent des flux RSS de leur contenu. Localiser l'URL sur le site de l'\u00E9diteur, copiez et collez l'URL dans le champ ci-dessus, puis cliquez sur Enregistrer.
+fileplugininstall.install.title=Installer le plugin ?
+Wizard.Subscription.rss.subtitle1=Tapez ou collez l'URL ci-dessous\:
+ManagerItem.error=Erreur
+ConfigView.section.connection.port.rand.together=Utiliser le m\u00EAme port pour TCP et UDP
+azbuddy.ui.menu.verify=V\u00E9rifier le contenu du presse-papier
+OpenTorrentOptions.header.filesInfo.some=%1 de %2 Fichiers\: %3
+v3.splash.initSkin=Initialisation de UI Skin
+ConfigView.section.style.colorOverrides.reset=R\u00E9initialiser
+restart.error.pnf=Le chemin '%1' est introuvable
+TableColumn.header.bad_avail_time=Copie int\u00E9grale vue
+ConfigView.section.security.group.crypto=Cl\u00E9s publiques / Cl\u00E9s priv\u00E9es
+PeersView.I1.info=\u00CAtes-vous int\u00E9ress\u00E9 par ce que l'autre client poss\u00E8de\u00A0?
+ConfigView.section.files.move=Ach\u00E8vement du d\u00E9placement
+ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Cette option force la mise \u00E0 jour de la vue '{library.name}' m\u00EAme si cet onglet n'est pas affich\u00E9 (utile pour certains plugins Mirc)
+FileView.BlockView.Skipped=Ignor\u00E9
+TableColumn.header.SeedingRank.info=Classement de valeur qui d\u00E9fini le niveau de seeding du torrent. Une valeur plus \u00E9lev\u00E9e signifie que le torrent n\u00E9cessite un plus grand besoin.
+MyTorrentsView.menu.setpriority=Priorit\u00E9
+device.model.desc=Description du mod\u00E8le
+ConfigView.label.openstatsonstart=Ouvrir la vue Statistiques au d\u00E9marrage
+ConfigView.section.proxy.enable_proxy=Activer un proxy
+ConfigView.section.ipfilter.blockbanning=Bannit un bloc de 256 adresses si le nombre d'IP bannies dans ce bloc est sup\u00E9rieur \u00E0
+MainWindow.menu.file.restart=Red\u00E9marrer
+azbuddy.os_busy=Occup\u00E9
+TorrentOptionsView.title.short=Options
+ConfigView.section.style.forceSIValues=Forcer les valeurs \u00E0 \u00EAtre pr\u00E9sent\u00E9s comme valeurs IEC ind\u00E9pendamment de l'unit\u00E9 d'affichage pour des raisons d'h\u00E9ritage (par exemple, 1 Mo \= 1MiB \= 1048576B)
+OpenTorrentWindow.startMode=Ajouter en mode
+Button.selectAll=Tout s\u00E9lectionner
+ManagerItem.checking=V\u00E9rification
+v3.deleteContent.message=\nVoulez-vous supprimer '%1' de votre ordinateur, ou simplement le retirer de votre biblioth\u00E8que Vuze\u2122 ?
+ConfigView.group.scrape=Scrape
+TableColumn.header.AvgAvail=Dispo. moy./pi\u00E8ce
+popup.next=>
+wizard.mode=Tracker / Mode
+ConfigView.section.transfer.lan.uploadrate.tooltip=Limite d'envoi propre aux clients sur un m\u00EAme r\u00E9seau local
+azbuddy.ui.menu.ygm=Envoyer YGM
+SystemTray.menu.stopalltransfers=&Arr\u00EAter tous les transferts
+ConfigView.label.seeding.firstPriority=La premi\u00E8re priorit\u00E9 s'applique aux torrents v\u00E9rifiant
+OpenTorrentOptions.show.never=jamais plus
+ConfigView.pluginlist.whereToPutOr=Pour un plugin partag\u00E9, utiliser\:
+ConfigView.section.style.graphicsUpdate=Mise \u00E0 jour des barres graphiques toutes les 'n' mises \u00E0 jour GUI
+ConfigView.section.security=S\u00E9curit\u00E9
+SpeedTestWizard.test.panel.not.accepted=La demande de test n'a pas \u00E9t\u00E9 accept\u00E9e \:
+ConfigView.label.seeding.addForSeedingDLCopyCount=Consid\u00E9rer les torrents ajout\u00E9s "en source" comme ayant t\u00E9l\u00E9charg\u00E9 ce nombre de copies\u00A0\:
+ConfigView.label.autoopen=Ouverture automatique
+CategoryAddWindow.title=Ajouter une nouvelle cat\u00E9gorie
+ConfigView.section.transfer.autospeed.chokeping=\u00C9touffement du temps de ping [milliseconde]
+wizard.multitracker.edit.text.title=Saisir les d\u00E9tails du Tracker
+FilePriority.invalid.text=La valeur entr\u00E9e est incorrecte, un nombre entier est requis\: %1
+installPluginsWizard.mode.title=Veuillez choisir une m\u00E9thode d'installation
+FilesView.rename.confirm.delete.title=Confirmer la suppression
+MyTrackerView.webui.contextmenu.copyurl=Copier l'URL du torrent dans le presse-papiers
+ConfigView.section.logging.timestamp=Format de date et d'heure pour les fichiers journaux
+TableColumn.header.up=Envoy\u00E9
+configureWizard.transfer2.group=Mode
+ConfigView.label.seeding.ignore.header.rule=R\u00E8gle
+PeersView.T=T
+PeersView.S=S
+TableColumn.header.TableColumnNameInfo=Nom et description de la colonne
+OpenTorrentWindow.startMode.stopped=Arr\u00EAt\u00E9
+UpdateConstraint.title=Mise \u00E0 jour des contraintes
+ConfigView.label.seeding.ignore.header.value=Valeur
+v3.deviceview.infobar.line2.xbox=Diffusez des vid\u00E9os en vous rendant dans l'interface graphique de votre PS3 et en s\u00E9lectionnant Ma XBox ->Vid\u00E9o - > Vuze.
+Formats.units.TB=To
+beta.wizard.off=Non merci, je suis satisfait des derni\u00E8res versions stables \!
+SpeedTestWizard.finish.panel.title=Test de vitesse termin\u00E9 \!
+MyTorrentsView.menu.rename.displayed.enter.message=Entrez un nouveau nom \u00E0 afficher pour ce t\u00E9l\u00E9chargement.
+DHTView.db.values=Valeurs
+ConfigView.section.stats.savefile=Nom du fichier de statistiques
+MyTorrentsView.menu.showdownloadbar=Afficher la &mini-bar
+br.backup.folder.title=S\u00E9lectionner le dossier de sauvegarde
+PiecesView.blocks=Blocs
+apply.selected.template=Appliquer le mod\u00E8le s\u00E9lectionn\u00E9
+IrcClient.disconnected=D\u00E9connect\u00E9 de
+PeersView.optunchoke=Option ranimation
+Scrape.status.initializing=En attente
+ManagerItem.low=Basse
+ConfigView.section.style.dropdiraction=Glisser-d\u00E9placer pour les r\u00E9pertoires
+GeneralView.label.hash=Hash\u00A0\:
+pairing.ac.getnew.create=Cr\u00E9er
+ConfigView.section.file.defaultdir.lastused=Mettre \u00E0 jour le r\u00E9pertoire par d\u00E9faut \u00E0 l'emplacement du dernier enregistrement de
+MyTorrentsView.menu.eta.abs=Afficher l'ETA en temps absolu
+PeersView.%=%
+ConfigView.label.udplistenport=Port d'\u00E9coute UDP
+Progress.reporting.action.label.cancel.tooltip=Annuler l'op\u00E9ration
+ConfigView.label.seeding.rankType.timedRotation=Rotation temporelle
+jvm.max.mem.current=La taille maximale actuel de la m\u00E9moire du 'tas' est de %1
+fileplugininstall.duplicate.title=Dupliquer le plugin
+ConfigView.section.connection.encryption.use_crypto_port=Utilisez l'extension tracker 'cryptoport' pour emp\u00EAcher les tentatives simples de connexion entrante. Certains trackers n'acceptent pas cela et \u00E9chouent avec des erreurs telles que "Port non valide" ou "Argument non valide"
+ConfigView.section.display=Affichage
+ConfigView.section.style.status.show_sr=Taux de partage
+FilesView.rename.filename.text=Choisissez un nouveau nom pour ce fichier
+exportTorrentWizard.exportfile.browse=...
+unix.script.new.button.quit=Quittez maintenant
+TableColumn.header.sessiondown=Session t\u00E9l\u00E9chargement
+label.proxy=Proxy
+exportTorrentWizard.exportfile.invalidPath=Fichier \u00E0 exporter invalide
+MainWindow.menu.view.plugins.logViews=Vues journaux
+v3.MainWindow.tab.publish=Publier
+label.show.tag=Afficher la cat\u00E9gorie
+LocaleUtil.column.text=Texte inconnu
+v3.MainWindow.button.stop=Arr\u00EAter
+wizard.webseed.adding=Ajout de seeds HTTP
+dht.warn.user=Avertir de potentiels probl\u00E8mes de NAT/Port Mapping
+v3.MainWindow.menu.view.asAdvancedList=Liste avanc\u00E9e
+ConfigView.section.logging.generatediagnostics.info=G\u00E9n\u00E8re des informations de diagnostic et les copie dans le presse-papier et le fichier de log, si activ\u00E9
+ConfigView.section.tracker.client.scrapeinfo=D\u00E9sactiver le scrape emp\u00EAche les r\u00E8gles de classement de torrents de fonctionner car elles se fondent sur les informations de scrape que renvoient les trackers.
+device.router.view.title=Routeurs
+ConfigView.label.sleep=Veille
+TableColumn.header.unopened.info=Indicateur signalant que le torrent a \u00E9t\u00E9 lu (ouvert)
+ConfigView.section.tracker.passwordenabletorrent=Activer mot de passe sur les torrents
+Pieces.column.\#.info=N\u00B0 de pi\u00E8ce
+ConfigView.section.tracker.createbutton=Cr\u00E9er
+menu.sortByColumn=Trier par %1
+devices.button.installitunes=Installer iTunes Integration
+device.autohide.alert=%1 p\u00E9riph\u00E9rique(s) ont \u00E9t\u00E9 masqu\u00E9(s) car ils n'ont pas \u00E9t\u00E9 mis en ligne depuis %2 jours.190 Allez dans 'Outils-> Options-> P\u00E9riph\u00E9rique' pour configurer ce comportement.\n Faites un clic doit sur 'P\u00C9RIPH\u00C9RIQUE DE LECTURE' dans la barre lat\u00E9rale afin de montrer les p\u00E9riph\u00E9riques masqu\u00E9s.
+TableColumn.header.size=Taille
+ConfigView.section.style=Interface Graphique
+dlg.corewait.title=Initialisation de base
+ConfigView.section.transfer.select.v2=D\u00E9bit automatique (beta)
+ConfigView.section.tracker.pollinterval=Intervalle de temps d'interrogation du tracker (secs)
+ConfigView.section.tables=Tableaux
+CacheView.reads.hits=R\u00E9sultats
+br.backup.auto.dir.select=S'il vous pla\u00EEt choisir le r\u00E9pertoire de sauvegarde par d\u00E9faut
+natpmp.info=NAT-PMP est l'alternative d'Apple pour UPnP et est support\u00E9 par les toutes derni\u00E8res stations Airport\n\nNotez qu'actuellement UPnP doit \u00EAtre activ\u00E9 pour permettre au p\u00E9riph\u00E9rique NAT-PMP d'\u00EAtre trait\u00E9 comme un type particulier de dispositif UPnP
+UIDebugGenerator.message.cancel.title=G\u00E9n\u00E9ration des informations de d\u00E9bogage annul\u00E9e
+MyTrackerView.date_added=Ajout\u00E9
+MyTorrentsView.menu.setSpeed.disable=D\u00E9sactiver l'envoi
+Wizard.Subscription.subscribe.library.empty=Pas d'abonnement disponible?\n \nCherchez le bouton d'abonnement orange vif sur le r\u00E9seau HD Vuze\u2122.\n \n<A HREF\="http\://wiki.vuze.com/w/FAQ_Subscriptions"> En savoir plus </A>
+wizard.webseed=Ajoutez des seeds HTTP au torrent
+ConfigView.label.priorityExtensions=Passez en haute priorit\u00E9 les fichiers dont l'extension est\u00A0\:\n(ex\: .txt;.nfo;.jpg)
+iconBar.openNoDefault.tooltip=Ouvrir un fichier torrent (sans r\u00E9pertoire par d\u00E9faut)
+IrcClient.copyright=Utilise l'API Java IRC PircBot - www.jibble.org/pircbot
+OpenTorrentWindow.mb.badSize.title=Fichier incompatible
+custom.settings.import.title=Importer les param\u00E8tres de configuration ?
+dlg.auth.enter.expiry=Le code d'activation actuel expire le %1.
+MyTorrentsView.menu.host.error.message=L'erreur suivante s'est produite lors de l'h\u00E9bergement du torrent
+azbuddy.ui.menu.remove=Supprimer
+DHTView.db.divfreq=Div. Freq.
+ConfigView.section.proxy.dns.info=Aller dans 'Connexion->Configuration DNS' pour sp\u00E9cifier des serveurs DNS suppl\u00E9mentaires pour la r\u00E9solution du proxy.
+Peers.column.timetocomplete.info=Temps restant avant que le pair ait termin\u00E9
+MainWindow.nat.status.unknown=NAT
+ConfigView.label.seeding.rankType.timedRotation.tooltip=Tous les torrents termin\u00E9s et mis en attente passeront source chacun leur tour.\nLa dur\u00E9e de source est d\u00E9finie par 'Temps de source minimum'
+OpenTorrentWindow.addFiles.URL=Ajouter &URL
+MyTorrentsView.menu.thisColumn.toClipboard=Copier le texte dans le presse-papiers
+azbuddy.addtorrent.msg=L'ami '%1' vous a envoy\u00E9 '%2'.\nVoulez-vous ajouter ce t\u00E9l\u00E9chargement ?
+TorrentDetailsView.filter=Rechercher des fichiers...
+v3.activity.header.downloads=T\u00E9l\u00E9chargements
+ConfigView.section.ipfilter.editFilter=\u00C9diter le filtre
+mb.azmustclose.text=Vuze\u2122 doit quitter en raison d'un probl\u00E8me, le (re)d\u00E9marrage de Vuze\u2122 a probablement conduit le programme \u00E0 s'ex\u00E9cuter en tant qu'administrateur.\n\nApr\u00E8s la fermeture Vuze\u2122, merci de d\u00E9marrer l'application manuellement.
+MyTorrentsView.menu.movemenu=D\u00E9placer les fichiers
+v3.splash.hookPluginUI=Raccordement \u00E0 l'interface utilisateur du plugin
+v3.MainWindow.tab.home=Accueil
+ConfigView.section.security.unlockkey=D\u00E9verrouiller explicitement les cl\u00E9s
+PeersView.connected_time.info=Temps total de connexion avec le client
+MyTrackerView.bytesin=Octets Entr\u00E9s
+ConfigView.section.file.perf=Options de Performance
+security.crypto.persist_for.30days=30 jours
+installPluginsWizard.list.description=Description du plugin
+MainWindow.dialog.select.vuze.file=S\u00E9lectionnez un fichier Vuze\u2122
+label.out=Dehors
+ConfigView.section.transfer.autospeed.latencyfactor=Facteur utilis\u00E9 pour lier les changements de temps de latence pour acc\u00E9l\u00E9rer les changements (plus le nombre est grand plus la sensibilit\u00E9 est diminu\u00E9e)
+Progress.reporting.window.remove.now.tooltip=Supprimer de la vue toutes les t\u00E2ches termin\u00E9es, \u00E9chou\u00E9es ou annul\u00E9es
+ConfigView.section.mode.beginner=D\u00E9butant
+br.restore.folder.title=S\u00E9lectionnez le dossier de restauration
+ConfigView.section.plugins.dht=Base de donn\u00E9e distribu\u00E9e
+platform.jvmopt.nolink=Vous ne pouvez pas g\u00E9rer les options de la machines virtuelle Java\u2122 car interdite par la configuration existante
+ConfigView.section.connection.encryption.min_encryption_level=Niveau d'encryptage minimum
+ConfigView.section.transfer.autospeed.minupload=%1 d\u00E9bit d'upload maximum
+ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents avec un taux sources/clients >
+core.shutdown.dl=t\u00E9l\u00E9chargements termin\u00E9s
+label.click.to.restore=Cliquez pour restaurer
+ConfigView.section.tracker.scrapeandcache="Scrape" et cache
+ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents avec 0 clients
+ConfigView.section.proxy.port=Port
+Button.cancel=Annuler
+Peers.column.maxupspeed=D\u00E9bit montant maximum
+label.init.save.loc=Emplacement de sauvegarde initial
+TableColumn.header.sr_prog=Progression du taux de partage
+CacheView.reads.\#=\#
+MainWindow.menu.window.alltofront=A&fficher tout devant
+MainWindow.menu.tools.speedtest=Test de vitesse...
+subs.ext.view.info=Vous avez configur\u00E9 Vuze\u2122 pour afficher les r\u00E9sultats d'abonnements dans un navigateur externe
+azbuddy.ui.menu.cat.set=Entrez des cat\u00E9gories
+ConfigView.label.seeding.rankType.peer=Nombre de pairs pond\u00E9r\u00E9
+OpenTorrentWindow.addFiles.Clipboard=Ajouter du &presse-papier
+plugin.sharing.remove.veto=Ce partage est inclus dans un contenu de r\u00E9pertoire partag\u00E9 et ne peut pas \u00EAtre effac\u00E9 seul.\n Veuillez enlever le partage du r\u00E9pertoire racine.
+ConfigView.group.irctitle=R\u00E9glages IRC
+Torrent.create.progress.totalfilecount=Nombre total de fichiers\:
+download.removerules.updatetorrents=Supprimer les torrents de mise \u00E0 jour de Vuze\u2122 si n\u00E9cessaire pour le r\u00E9seau
+plugin.aznetstatus.pingtarget=Faire un Ping/tracer la route cible
+Trackers.column.peers=Pairs
+LoggerView.pause=Mettre en pause
+ConfigView.label.usefastresume=Utiliser la reprise rapide
+MainWindow.menu.window.minimize=&Minimiser
+speedtest.wizard.test.mode.down=t\u00E9l\u00E9chargement
+devices.xcode.only.show=Afficher seulement les fichiers transcod\u00E9s sur le p\u00E9riph\u00E9rique
+ConfigView.label.savetorrents=Conserver les fichiers .torrent
+ConfigView.pluginlist.column.isOperational=Op\u00E9rationnel\u00A0?
+external.browser.failed=Navigateur externe \u00E9chou\u00E9
+GeneralView.yes=Oui
+TableColumn.header.tag_colors=Couleurs de cat\u00E9gorie
+Wizard.Subscription.optin.title=Activer les abonnements
+Formats.units.MB=Mo
+health.explain.grey=Le torrent n'est pas en route. (ni en t\u00E9l\u00E9chargement ni en envoi)
+configureWizard.file.title=Torrents / Fichiers
+ConfigView.section.style.status.show_rategraphs=Afficher un graphiques repr\u00E9sentant l'historique des graphiques en-dessous du texte t\u00E9l\u00E9chargement / upload
+library.incomplete.header.p=%1 \u00E9l\u00E9ments en t\u00E9l\u00E9chargement, %2 en attente de t\u00E9l\u00E9chargement
+PeersView.client.info=Sorte de logiciel BT le client utilise
+DownloadManager.error.unabletostartserver=Impossible de d\u00E9marrer le serveur; V\u00E9rifier la configuration du port entrant et/ou les permissions du pare-feu pour permettre \u00E0 l'application de s'ex\u00E9cuter en tant que serveur.
+exportTorrentWizard.process.inputfilebad.message=Une erreur s'est produite en acc\u00E9dant au fichier\u00A0\:
+ConfigView.label.seeding.firstPriority.DLMinutes=Un temps \u00E9coul\u00E9 depuis le d\u00E9but du t\u00E9l\u00E9chargement
+Button.bar.show=Afficher
+GeneralView.label.maxuploads=Max. clients actifs\u00A0\:
+DHTView.activity.title=Activit\u00E9
+importTorrentWizard.importfile.browse=...
+ConfigView.label.popupdownloadfinished=Montrer une alerte 'popup' quand un t\u00E9l\u00E9chargement est termin\u00E9
+ConfigView.section.style.status.show_ipf=\u00C9tat du filtre IP
+TrayWindow.menu.close=Fermer le panier de t\u00E9l\u00E9chargement
+ConfigView.label.quickviewmaxkb=Taille maximale du fichier [KB]
+MainWindow.dht.status.initializing=Initialisation
+security.crypto.pw.title=Saisir le mot de passe
+importTorrentWizard.process.torrentfail.title=L'\u00E9criture du torrent a \u00E9chou\u00E9
+ConfigView.section.style.units=Unit\u00E9s d'affichage
+ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Partager le contenu (et les sous-r\u00E9pertoire)
+TableColumn.header.TableColumnInfo=Description de la colonne
+message.status.success=Succ\u00E8s
+ConfigView.pluginlist.whereToPut=Placer tout plugin utilisateur dans leur r\u00E9pertoire sp\u00E9cifique sous\u00A0\:
+TrackerClient.announce.warningmessage=Tracker de '%1' a retourn\u00E9 l'avertissement '%2'
+ConfigView.section.proxy.password=Mot de passe
+MainWindow.menu.window.zoom.restore=Restaurer
+ConfigView.section.file.save.peers.max=Nombre maximum de pairs \u00E0 sauvegarder [0\: illimit\u00E9]
+ConfigView.section.file.defaultdir.autorename=Renommer automatiquement les donn\u00E9es torrent si les fichiers dans le chemin semblent diff\u00E9rents
+PeersView.downloadspeedoverall=R\u00E9ception (Vit. Totale de)
+PiecesView.DistributionView.weHave=Pi\u00E8ces que vous poss\u00E9dez
+device.mediaserver.remove_all.title=Confirmation de la suppression
+Formats.units.KB=ko
+device.show=Afficher les p\u00E9riph\u00E9riques cach\u00E9s
+OpenTorrentWindow.filesInfo=%1 de %2 seront t\u00E9l\u00E9charg\u00E9s
+#There is a plugin to help with internationalizing these bundles at http://plugins.vuze.com/plugin_list.php
+MainWindow.menu.file.open.torrent=Fichier .torrent
+uninstallPluginsWizard.finish.title=D\u00E9sinstallation en cours
+ConfigView.section.style.forceMozilla=Force Vuze\u2122 \u00E0 utiliser Mozilla pour les widgets de navigateur [xulrunner ou firefox 3 requis; red\u00E9marrage n\u00E9cessaire]
+sidebar.header.transfers=Mes Torrents
+ConfigView.label.seeding.fakeFullCopySeedStart=mais seulement pour les torrents avec au moins
+update.instance.update=V\u00E9rification des mises \u00E0 jour
+label.plugin.options=Options des plugins...
+UpdateMonitor.messagebox.verification.failed.title=La v\u00E9rification de l'installation a \u00E9chou\u00E9
+FileItem.normal=Normale
+MyTorrentsView.menu.move=&D\u00E9placer
+FilesView.priority=Priorit\u00E9
+upnp.mapping.dataportudp=Port UDP du client tracker
+SpeedTestWizard.set.upload.result=Dernier r\u00E9sultat de test
+ConfigView.section.style.showProgramIcon.tooltip=Avertir qu'il peut \u00EAtre n\u00E9cessaire de red\u00E9marrer pour que les changements prennent effet
+IrcClient.topicforchannel=Topic pour le canal
+ConfigView.section.logging.maxsize=Taille maximale du fichier de journalisation
+ConfigView.label.seeding.firstPriority.ignore.info=Attention. Utiliser ces r\u00E8gles peut faire en sorte qu'un torrent s'arr\u00EAte d\u00E8s qu'il est termin\u00E9.
+devices.view.title=P\u00E9riph\u00E9riques
+authenticator.tracker=Tracker
+azbuddy.ui.mykey=Ma Cl\u00E9
+wizard.maketorrents.init.tags=Cat\u00E9gories initiales (s\u00E9par\u00E9es par ',' )
+OpenTorrentWindow.fileList=Fichiers dans les torrents\:
+ConfigView.dialog.choosedefaulttorrentpath=Choisissez le r\u00E9pertoire d'enregistrement des .torrent
+iconBar.queue.tooltip=File d'attente
+installPluginsWizard.file.browse=Parcourir...
+subs.prop.last_error=Derni\u00E8re erreur
+label.complete=Termin\u00E9
+v3.MainWindow.tab.library=Biblioth\u00E8que
+health.explain.red=En t\u00E9l\u00E9chargeant, vous n'\u00EAtes connect\u00E9s \u00E0 aucun client.
+MainWindow.status.latestversion=Derni\u00E8re
+configureWizard.nat.server.udp_listen_port=Port d'\u00E9coute UDP
+installPluginsWizard.title=Installation de plugins
+webui.port.override=Port de substitution\: n\u00E9cessaire uniquement si le port public diff\u00E8re du port interne en raison de la configuration NAT
+security.certcreate.title=Cr\u00E9er un certificat auto-sign\u00E9
+DetailedListView.title=Liste d\u00E9taill\u00E9e
+OpenTorrentWindow.fileTable.destinationName=Rep.
+ConfigView.label.strictfilelocking=Forcer le verrouillage exclusif de l'acc\u00E8s en \u00E9criture \u00E0 un fichier sur tous les torrents
+FilesView.menu.setpriority.numeric.auto=Num\u00E9rique - Diminution automatique
+TransferStatsView.legend.ping3=Cible 3
+TransferStatsView.legend.ping2=Cible 2
+TransferStatsView.legend.ping1=Cible 1
+PeersView.port.info=Port utilis\u00E9
+ConfigView.section.connection.network.max.simultaneous.connect.attempts=Nombre maximum de connexions sortantes simultan\u00E9es
+DHTView.general.nodes=N\u0153uds\u00A0\:
+ConfigView.label.openconsole=Ouvrir la Console au d\u00E9marrage
+MainWindow.menu.file.create.fromfile=\u00C0 &partir d'un fichier
+TableColumn.header.SeedingRank=Rang de source
+VivaldiView.title.fullcvs=Vivaldi CVS
+ConfigView.section.file.perf.cache.enable=Activer le cache disque
+ConfigView.section.connection.encryption.encrypt.group=Transfert encrypt\u00E9/obfusqu\u00E9
+SpeedTestWizard.test.panel.enc.label=Appuyez pour tester avec le chiffrement \:
+MyTorrentsView.menu.create_personal_share=Cr\u00E9er un partage personnel
+Button.sendManual=Envoyer manuellement (cr\u00E9er un .zip)
+dlg.auth.title=Activation
+MainWindow.status.latestversion.clickupdate=Cliquer pour mettre \u00E0 jour
+TableColumn.header.availability=Disponibilit\u00E9
+IPChecker.external.service.discoveryvip.description=Discoveryvip - v\u00E9rification d'adresses IP seulement
+MainWindow.upgrade.section.info=Nouvelle version disponible
+PeersView.incomingreqcount=Requ\u00EAtes entrantes
+upnp.alertdeviceproblems=Rapporter les probl\u00E8mes avec l'UPnP
+v3.MainWindow.button.comment=Commenter
+IrcClient.haskicked=a \u00E9ject\u00E9
+configureWizard.transfer2.mselect=S\u00E9lectionnez votre vitesse de connexion maximale pour l'UPLOAD
+MainWindow.menu.file.share.dircontents=C&ontenu d'un r\u00E9pertoire
+ConfigView.label.pauseresume=Pause/reprise automatique
+swt.uninstall.window.title=D\u00E9sinstalleur de plugins pour Vuze\u2122
+UpdateMonitor.messagebox.accept.unverified.text='%1' n'a pas pu \u00EAtre v\u00E9rifi\u00E9e comme un plugin officiel de Vuze\u2122.\nNous vous conseillons de ne pas l'installer\nVoulez-vous poursuivre l'installation ?
+MainWindow.status.update.tooltip=Double-cliquer pour voir la progression
+MainWindow.menu.closealldetails=Fermer tous les &d\u00E9tails
+Progress.reporting.action.label.retry.tooltip=R\u00E9essayer cette op\u00E9ration
+MyTorrentsView.mytorrents=Mes torrents
+Subscription.menu.reset=R\u00E9initialiser
+br.restore=Restauration
+pairing.status.pending=La mise \u00E0 jour sera effectu\u00E9e \u00E0 %1
+ConfigView.option.dm.dblclick.play=Lire les donn\u00E9es
+CacheView.reads.fromCache=Depuis Cache
+ConfigView.section.ipfilter.end=IP de fin
+dlg.auth.trial.title=DVD Burn Version d'essai
+PeersView.T.info=L (local)\: vous avez \u00E9tabli la connexion, R (distant)\: un client vous a contact\u00E9.
+tag.sharing.enable.text=Voulez-vous partager anonymement l'attribution de cat\u00E9gorie avec la communaut\u00E9 ?\n\nCeci aidera d'autres utilisateurs \u00E0 organiser leurs t\u00E9l\u00E9chargements.\n\nFaites un clic droit sur la cat\u00E9gorie dans le menu lat\u00E9rale pour modifier les param\u00E8tres individuels si n\u00E9cessaire.
+MyTrackerView.status.published=Publi\u00E9
+Formats.units.GB=Go
+PeersView.BlockView.NextRequest=Prochaine requ\u00EAte
+v3.MainWindow.Loading=Chargement en cours.. Merci de bien vouloir patienter
+azbuddy.ui.menu.send_msg=Entrez le texte a envoyer \u00E0 votre (vos) ami(s)
+ConfigView.pluginlist.broken=Endommag\u00E9
+v3.MainWindow.menu.view.toolbartext=Texte de la barre d'outils
+GeneralView.label.filename=Nom\u00A0\:
+DownloadManager.error.filetoobig=Fichier .torrent trop gros
+TableColumn.header.maxuploads.info=Nombre maximal \# de pairs pour uploader simultan\u00E9ment vers
+webui.mode=Mode
+security.crypto.persist_for=P\u00E9riode de persistance du mot de passe
+iconBar.open.tooltip=Ouvrir Torrent(s)
+MainWindow.menu.view.myshares=&Mes partages
+dlg.install.mlab.subtitle=Installation
+device.search.auto=Recherche les p\u00E9riph\u00E9riques automatiquement
+devices.info.copypending=%1 fichier(s) en attente de copie
+ipCheckerWizard.progresstitle=V\u00E9rification IP
+TableColumn.header.peersources.info=Origines des clients permises pour l'\u00E9tablissement de connexions
+ConfigView.option.dm.dblclick.show=Afficher le fichier
+splash.openViews=Ouverture des onglets...
+MainWindow.dialog.exitconfirmation.text=Voulez-vous vraiment fermer Vuze\u2122 ?
+exportTorrentWizard.finish.title=Termin\u00E9
+iconBar.down.tooltip=D\u00E9placer vers le bas
+DHTTransport.report.received_bit=re\u00E7u %1/%2 de %3
+library.core.wait=Un moment, s'il vous pla\u00EEt...\nLe client Vuze\u2122 est en cours d'initialisation
+label.options.and.info=Options/Info...
+ConfigView.section.file.defaultdir.autorename.tooltip=Cela emp\u00EAche un torrent d'\u00E9craser les fichiers d'un autre torrent quand les noms de fichiers sont les m\u00EAmes
+ConfigView.label.periodiccheck=V\u00E9rifier les mises \u00E0 jour p\u00E9riodiquement
+Progress.reporting.status.finished=Termin\u00E9
+TableColumn.header.maxupspeed=Vit. Envoi Max.
+plus.notificaiton.ExpiredEntry.s=Votre abonnement Vuze\u2122 Plus a expir\u00E9\: <A %2>Renouveler maintenant</A>
+MainWindow.menu.language.refresh=&Rafra\u00EEchir
+MessageBoxWindow.rememberdecision=Se souvenir de ma d\u00E9cision
+configureWizard.nat.title=Test du routeur et du pare-feu
+ConfigView.section.logging.log0type=Information
+label.current_ip=Adresse IP actuelle\:
+upnp.refresh_mappings_on_bad_nat=Actualiser automatiquement les correspondances lorsque l'\u00E9tat NAT est "pare-feu activ\u00E9"
+splash.plugin.UIinit=Initialisation de l'interface graphique du plugin \: %1
+DHTView.general.skew=Fauss\u00E9 \:
+DHTView.general.users=Utilisateurs\u00A0\:
+SpeedTestWizard.test.panel.test.countdown=le test se termine dans \:
+#Used by the webui plugin
+MyTorrentsView.menu.removeand.deletetorrent=effacer le fichier &torrent
+ConfigView.label.watchtorrentfolder=Importer les nouveaux torrents automatiquement
+torrent.view.info=Voir les informations d'un torrent...
+ConfigView.section.tracker.server.group.networks.info=S\u00E9lectionner les r\u00E9seaux desquels le tracker accepte les clients
+IrcView.actionnotsupported=Cette action n'est pas support\u00E9e
+ConfigView.section.tracker.announcecacheperiod=Cache de l'annonce (ms)
+DHTView.operations.findNode=N\u0153uds trouv\u00E9s
+iconBar.up.tooltip=D\u00E9placer vers le haut
+label.bt.connect=BT Connecter
+ConfigView.section.proxy.group.tracker=Communications des trackers
+DHTView.operations.ping=Ping
+ConfigView.label.queue.newseedsmovetop=D\u00E9placer les torrents r\u00E9cemment termin\u00E9s au d\u00E9but de la liste de sources
+ConfigView.label.disconnetseed=Se d\u00E9connecter des sources lorsqu'on est source
+MainWindow.menu.transfers.resumetransfers.keybinding.mac=Meta+Shift+.
+device.retry.copy=R\u00E9essayez la copie
+ConfigView.section.connection.group.http=HTTP
+ConfigView.label.enableSystrayToolTip=Afficher les statistiques de t\u00E9l\u00E9chargement en pointant la souris sur l'ic\u00F4ne
+ConfigView.section.tracker.maxthreads=Requ\u00EAtes simultan\u00E9es maximales
+MainWindow.menu.file.create.fromdir=\u00C0 partir d'un r\u00E9perto&ire
+ConfigView.section.security.system.managed=Syst\u00E8me de management des clefs de protection
+Button.mark=Marquer
+MyTorrentsView.menu.sl_remove_from_prof=Supprimer du profil
+ConfigView.section.connection.advanced.SO_SNDBUF=Taille de la socket SO_SNDBUF [0\: utilise la valeur par d\u00E9faut du syst\u00E8me d'exploitation]
+torrent.fix.corrupt.browse=Ouvrir le torrent
+azbuddy.ui.menu.cat.share=Activer les abonnements avec ami(s)
+memmon.heap.auto.increase.warning=La m\u00E9moire du tas a \u00E9t\u00E9 augment\u00E9 \u00E0 %1. Cette augmentation prendra effet lorsque Vuze\u2122 aura red\u00E9marr\u00E9.
+Formats.units.TiB=Tio
+ConfigView.label.seeding.rankType.peerSeed=Taux de Clients/Sources
+platform.win32.baddll.MxAVLsp=VCom Fix-It Utilities
+PeersView.outgoingreqcount=Requ\u00EAtes sortantes
+DHTView.db.indirect=Indirect
+label.more.dot=Plus...
+exportTorrentWizard.exportfile.message=Entrer le nom du fichier XML \u00E0 cr\u00E9er
+DownloadManager.error.unsupportedencoding=Format d'encodage non support\u00E9
+MyTorrentsView.menu.clear_alloc_data=Effacer l'\u00E9tat de l'allocation
+TorrentOptionsView.multi.title.full=Options/Information du/des torrent(s)
+ConfigView.section.file.decoder.nodecoder=Aucun
+device.router.is_mapping=Mappage de port automatique
+MyTorrentsView.filter=Filtre\:
+configureWizard.transfer2.message=Bittorrent est bas\u00E9 sur un protocole TFT - en g\u00E9n\u00E9ral, plus vite vous uploadez, plus vite vous t\u00E9l\u00E9chargez - afin de t\u00E9l\u00E9charger rapidement, et d'obtenir vite un bon taux de partage, votre bande passante a besoin d'un bon d\u00E9bit montant\n\nToutefois, si vous bande passante b\u00E9n\u00E9ficie d'un d\u00E9bit montant trop \u00E9lev\u00E9, vous risquez de la surcharger, ce qui provoquera une baisse g\u00E9n\u00E9rale  [...]
+ConfigView.section.tracker.client.connecttimeout=D\u00E9lai de connexion (secs)
+GeneralView.label.maxdownloadspeed.tooltip=Vitesse maximale de t\u00E9l\u00E9chargement [0\u00A0\: illimit\u00E9e]
+azbuddy.ui.menu.enc=Crypter le contenu du presse-papier
+ConfigView.label.piecereorder=Ajouter des donn\u00E9es \u00E0 des fichiers comme si ceux-ci \u00E9taient t\u00E9l\u00E9charg\u00E9es et r\u00E9ordonner les \u00E9l\u00E9ments comme des progressions de t\u00E9l\u00E9chargement.
+dial.up=Composer
+device.itunes.status.notinstalled=iTunes n'est pas install\u00E9
+MainWindow.dialog.share.sharefile=S\u00E9lectionner le fichier \u00E0 partager
+MainWindow.menu.transfers.pausetransfers=&Pause
+stats.general.smooth_secs=Taille moyenne mod\u00E9r\u00E9 de la fen\u00EAtre [secs]
+DHTView.general.contacts=Contacts\u00A0\:
+upnp.ignorebaddevices.reset.action=R\u00E9initialiser
+OpenTorrentWindow.mb.existingFiles.text=Certains de ces fichiers existe d\u00E9j\u00E0 dans le(s) dossier(s) de destination que vous avez sp\u00E9cifi\u00E9(s)\:\n\n%1\nSi vous continuez, Vuze\u2122 v\u00E9rifiera le(s) fichier(s) ci-dessus pour corriger les donn\u00E9es et les remplacer si n\u00E9cessaire.
+ConfigView.section.security.nopw=Aucun mot de passe n'a \u00E9t\u00E9 fourni
+MainWindow.menu.file.share.dircontentsrecursive=Contenu d'un r\u00E9pertoire (inclure les &sous-r\u00E9pertoires)
+GeneralView.label.downloadspeed=Vitesse de t\u00E9l\u00E9chargement\u00A0\:
+v3.MainWindow.menu.view.sidebar=Barre lat\u00E9rale
+AlertMessageBox.unread=Vous avez des messages d'alerte non lus - Cliquez ici pour les afficher.
+Trackers.column.seeds=Seeds
+MySeeders.bigView.header={sidebar.LibraryCD}
+ConfigView.section.sharing.permitdht=Permettre le tracking d\u00E9centralis\u00E9 si le tracker est injoignable
+MainWindow.menu.speed_limits.profile=Saisir le nom du profil
+MainWindow.menu.view=&Affichage
+beta.wizard.link=Cliquez ici pour acc\u00E9der \u00E0 la page Web de la version Beta
+ConfigView.section.style.addurlsilently=Ouvrir l'URL discr\u00E8tement (sans boite de dialogue)
+ConfigView.section.ipfilter.list.inrange=est dans la plage
+PeersView.host=Nom d'h\u00F4te
+TorrentInfoView.columns=Colonnes de la vue '{library.name}'
+ColumnSetup.categories=Cat\u00E9gories\:
+MyTrackerView.uploaded=Qt\u00E9 envoy\u00E9e
+network.ipv6.prefer.addresses=Pr\u00E9f\u00E9rez les adresses IPv6 quand IPv6 et IPv4 sont disponibles
+metasearch.addtemplate.done.title=Mod\u00E8le ajout\u00E9
+importTorrentWizard.finish.title=Termin\u00E9
+uninstallPluginsWizard.list.loaded=Veuillez choisir les plugins \u00E0 d\u00E9sintaller.
+subscriptions.add.tooltip=Ajouter un abonnement
+devices.sidebar.onxcodecomplete=Sur l'ach\u00E8vement du transcodage
+label.in=Dedans
+ConfigView.label.autoSeedingIgnoreInfo=Les torrents ignor\u00E9s sont d\u00E9plac\u00E9s en bas de file. Ils ne d\u00E9marrent pas automatiquement. Les r\u00E8gles "Ignorer" ne s'appliquent pas aux torrents de "Premi\u00E8re priorit\u00E9". Utilisez la valeur 0 pour ignorer une r\u00E8gle.\n\n
+TableColumn.header.\#.info=Priorit\u00E9/Position/Num\u00E9ro de commande
+ConfigView.section.tracker.port=Activer le tracker sur le port HTTP
+search.dialog.text=Entrez du texte pour rechercher de nouveaux torrents\:
+UpdateWindow.status.restartMaybeNeeded=Un red\u00E9marrage sera peut-\u00EAtre n\u00E9cessaire
+ConfigView.group.override=Options prioritaires
+TableColumn.header.activityType=Type
+fileDownloadWindow.status=\u00C9tat\u00A0\:
+TableColumn.header.activityActions=Actions
+ConfigView.label.xfer.bias_slack=KB/s minimum r\u00E9serv\u00E9e aux t\u00E9l\u00E9chargements termin\u00E9s
+MinimizedWindow.name=Nom\u00A0\:
+Trackers.column.updatein.info=D\u00E9lai avant la prochaine mise \u00E0 jour
+PeerColumn.activationCount=Pairs qui tentent de se connecter\: %1
+ConfigView.section.interface.legacy=H\u00E9ritage
+TableColumn.header.Rating=Note
+IrcView.title.short=IRC
+ConfigView.section.sharing.usessl=Utiliser le SSL pour le partage (n\u00E9cessite de configurer le tracker)
+ConfigView.label.startwatchedtorrentsstopped.tooltip=Ajoute les nouveaux torrents en mode ARR\u00CAT\u00C9
+GeneralView.label.swarm_average_completion.tooltip=Pourcentage moyen de compl\u00E9tion des clients connect\u00E9s
+device.odpt.enable=Inclure les torrents priv\u00E9s
+SWT.alert.erroringuithread=Une erreur non g\u00E9r\u00E9e s'est produite dans l'interface graphique, d'autres erreurs peuvent \u00EAtre signal\u00E9es.
+metasearch.addtemplate.failed.desc=\u00C9chec de l'installation du mod\u00E8le de recherche mod\u00E8le \: %1
+ConfigView.section.style.useTree=Afficher les fichiers dans la vue {library.name} (n\u00E9cessite un red\u00E9marrage)
+TableColumn.header.trancode_completion=Progression de la conversion
+message.taking.too.long=Il semble que cela prend plus de temps que pr\u00E9vu\nAppuyez sur la touche 'ESC' si vous souhaitez annuler cette op\u00E9ration
+Button.open=Ouvrir
+v3.MainWindow.search.last.tooltip=Afficher la derni\u00E8re Recherche
+ConfigView.section.tracker.client.enabletcp=Activer les protocoles HTTP / HTTPS du client tracker
+exportTorrentWizard.process.inputfilebad.title=Fichier torrent invalide
+ConfigView.label.closetotray=R\u00E9duire dans la zone de notification lors de la fermeture
+ConfigView.filter=saisir un filtre
+ConfigView.label.zeronewfiles=Allouer les nouveaux fichiers avec des z\u00E9ros
+tag.sharing.enable.title=Partagez avec la communaut\u00E9
+Scrape.status.disabled=Scrape d\u00E9sactiv\u00E9
+ConfigView.section.connection.peersource.Incoming=Connexion entrante
+MainWindow.dialog.share.sharedircontents=S\u00E9lectionner le contenu du r\u00E9pertoire \u00E0 partager
+menu.delete.options.keybinding=SUPPR
+label.more=Plus
+TagRenameWindow.title=Renommer la cat\u00E9gorie
+devices.od=T\u00E9l\u00E9chargeur hors ligne
+MainWindow.menu.view.configuration.keybinding=Meta+,
+ConfigView.section.transfer.autospeed.reset.button=R\u00E9initialiser
+pairing.explicit.enable=Activer
+DHTView.transport.bytes=Octets
+subscriptions.config.auto=T\u00E9l\u00E9chargement automatique
+ConfigView.label.systray=Zone de notification
+DHTView.general.dying=Expirant\u00A0\:
+Pieces.column.\#=\#
+upnp.releasemappings=Lib\u00E9rer les mappings \u00E0 la fermeture
+DHTTransport.report.timeout=hors d\u00E9lai, pas de r\u00E9ponses de %1
+wizard.hint.mode=Astuce\:\tVous pouvez glisser/d\u00E9placer un fichier ou un r\u00E9pertoire\n\tsur cet assistant pour le s\u00E9lectionner
+v3.MainWindow.currentDL=T\u00E9l\u00E9chargements en cours
+ConfigView.section.file.decoder.label=Encodage par d\u00E9faut\nquand un choix est n\u00E9cessaire
+v3.MainWindow.button.stream=Jouer
+ConfigView.section.tracker.publishenablepeerdetails=Publier les d\u00E9tails des clients
+OpenTorrentWindow.fileList.changeDestination.all=Choisir comme emplacement de destination le m\u00EAme dossier que les fichier %1
+SpeedView.stats.total.since=Total (depuis %1)
+ConfigTransferAutoSpeed.set.point=d\u00E9finir le d\u00E9calage (ms)
+subscriptions.listwindow.popularity=Popularit\u00E9
+label.more.info.here=Cliquez pour plus d'informations
+TableColumn.header.completed=Termin\u00E9
+iconBar.start.tooltip=Commencer
+deletedata.title=\!\!\! Attention \!\!\!
+TableColumn.header.maxdownspeed.info=Vitesse maximale de t\u00E9l\u00E9chargement par torrent
+FilesView.size=Taille
+GeneralView.label.trackerurl=URL du Tracker\u00A0\:
+ConfigView.section.torrents=Torrents
+MySharesView.type.dir=R\u00E9pertoire
+DHTView.activity.type.4=Put Externe
+ConfigView.section.tracker.host.addurls=S'assurer que les URL de ce tracker sont pr\u00E9sents dans les torrents h\u00E9berg\u00E9s
+DHTView.activity.type.3=Put Interne
+DHTView.activity.type.2=Get Externe
+DHTView.activity.type.1=Get Interne
+importTorrentWizard.torrentfile.path=Chemin d'acc\u00E8s
+exportTorrentWizard.title=Exporter un torrent en XML
+SpeedView.stats.upbias=Upload pertinent\:
+devices.copy.pending=Copie de fichier en attente
+ConfigView.label.openbar.complete=Ouverture automatique des 'seeds'
+dht.reseed.ip=Adresse IP
+label.trackers=Trackers
+subs.prop.version=Version
+dlg.stream.plus.renew.text=Renouvelez votre abonnement Vuze\u2122 plus pour continuer \u00E0 visionner vos vid\u00E9os pendant leur t\u00E9l\u00E9chargement.
+webui.homepage=Page d'accueil (*)
+ConfigView.label.prioritizemostcompletedfiles=Donner priorit\u00E9 aux fichiers les plus avanc\u00E9s
+azbuddy.contextmenu=Envoyer \u00E0 un ami
+Plugin.trackerpeerauth.name=Autorisation de pair tracker
+MainWindow.upgrade.assistant=Assistant de mise \u00E0 jour
+updater.progress.window.title=Travaux d'installation en cours
+devices.sidebar.simple=Vue simple
+ConfigView.section.NATPMP=NAT-PMP
+subscriptions.column.nb-new-results=Nouveaux r\u00E9sultats
+MyTorrentsView.menu.rename.displayed=Renommez le nom d'affichage
+ConfigView.section.tracker.client.scrapeenable=Activer le scrape
+ConfigView.label.serverport=Port d'\u00E9coute TCP entrant
+Formats.units.GiB=Gio
+GeneralView.label.connected=connect\u00E9(s)
+importTorrentWizard.process.outputfileexists.title=Le fichier existe d\u00E9j\u00E0
+tps.pex.details=Connect\u00E9 \u00E0 %1 pairs (en attente\: pex\=%2, autre\=%3)
+configureWizard.transfer.maxActiveTorrents=Maximum Actifs
+OpenTorrentWindow.mb.noDestDir.title=R\u00E9pertoire de destination introuvable
+configureWizard.file.path=\u00A0
+remote.pairing.title=Jumelage \u00E0 distance
+MagnetPlugin.report.waiting_ddb=Patientez pendant l'initialisation de la base de donn\u00E9e distribu\u00E9e (DDB)...
+MyTrackerView.bytesoutave=Moyenne Sortie
+ConfigView.label.stop.seedcomp=Lorsque le seeding est termin\u00E9
+webui.pairing.info.y=Le jumelage est activ\u00E9, consultez la page de configuration 'Connexion -> Options de jumelage' pour des informations sur cette fonctionnalit\u00E9
+security.crypto.password.mismatch.title=Erreur de mot de passe
+ConfigView.label.seeding.rankType.none=Aucun
+webui.pairing.info.n=Le jumelage est d\u00E9sactiv\u00E9, consultez la page de configuration 'Connexion -> Options de jumelage' pour des informations sur cette fonctionnalit\u00E9
+device.xcode.never=Jamais
+Button.validate=Valider
+quick.view.scheduled.title=Aper\u00E7u rapide programm\u00E9
+MainWindow.menu.file.export.keybinding.mac=Meta+Shift+E
+TableColumn.header.completion.info=Repr\u00E9sentation graphique du % t\u00E9l\u00E9charg\u00E9
+sr_prog.window.message=Saisir l'intervalle d'enregistrement de la progression du ratio partag\u00E9 (par exemple 1.0 \= chaque copie compl\u00E8te)
+Button.add=Ajouter
+subscript.import.fail.title=\u00C9chec de l'importation
+StartStopRules.0Peers=0 client
+wizard.webseedseditor.edit.title=\u00C9diteur de seeds HTTP
+MainWindow.menu.pairing=Jumelage distant
+remote.pairing.instruction2={remote.pairing.instruction} Sinon, scannez le code QR sur votre p\u00E9riph\u00E9rique mobile et ignorez la n\u00E9cessit\u00E9 d'entrer le code d'acc\u00E8s.
+xmwebui.required=Vous devez installer le plugin 'Vuze\u2122 Web Remote' pour que cela fonctionne\nAller dans Outils->Plugins->Assistant d'installation...
+IrcView.noticefrom=Notice\:
+v3.iconBar.view.small.tooltip=Vue compl\u00E8te
+OpenTorrentWindow.mb.noGlobalDestDir.title=R\u00E9pertoire de destination introuvable
+SpeedTestWizard.abort.message.scheduled.in=test planifi\u00E9 dans ... %1 secondes
+MyTorrentsView.menu.showdetails=Afficher les d\u00E9&tails
+window.updateswt.ignore=Ignor\u00E9
+devices.xcode.autoCopy=Copier automatiquement dans le dossier
+PeersView.BlockView.Avail.NoHave=Le client a; Pas vous
+pairing.ipv6=Adresse publique IPv6
+pairing.ipv4=Adresse publique IPv4
+Search.menu.engines=Mod\u00E8les
+ConfigView.section.security.backupkeys=Sauvegarder la cl\u00E9 dans un fichier
+azbuddy.ui.new_buddy=Nouvelle cl\u00E9 ami\:
+# 2.0.4.4
+ConfigView.section.style.guiUpdate=Mise \u00E0 jour de l'interface graphique (GUI) toutes les
+MainWindow.menu.file.export.keybinding=Meta+E
+DHTOpsView.notAvailable=Graphique DDB non disponible
+PiecesView.DistributionView.theyHave=Pi\u00E8ces que les pairs ont
+DHTView.title.full_v6=Base de donn\u00E9es distribu\u00E9e IPv6
+subscriptions.listwindow.popularity.reading=Lecture...
+configureWizard.transfer.connection.7=ADSL/Cable xxx/1024 kbit/s
+ConfigView.label.start.onlogin=Lancer Vuze\u2122 \u00E0 la connexion
+configureWizard.transfer.connection.6=ADSL/Cable xxx/768 kbit/s
+configureWizard.transfer.connection.5=ADSL/Cable xxx/512 kbit/s
+UpdateWindow.cancel=Annuler
+configureWizard.transfer.connection.4=ADSL/Cable xxx/384 kbit/s
+progress.window.title=Op\u00E9ration en cours
+configureWizard.transfer.connection.3=ADSL/Cable xxx/256 kbit/s
+TableColumn.header.resolution=R\u00E9solution
+configureWizard.transfer.connection.2=ADSL/Cable xxx/128 kbit/s
+configureWizard.transfer.connection.1=Modem/ISDN
+ConfigView.section.security.unlockkey.error=\u00C9chec lors du d\u00E9verrouillage de la cl\u00E9 - mot de passe incorrect
+ConfigView.option.dm.dblclick.show._mac=Afficher le(s) fichier(s) dans le Finder
+configureWizard.transfer.connection.0=Personnalis\u00E9e
+ConfigView.eta.abbreviated=E\:
+ConfigView.section.DNS={label.DNS}
+device.odauto.enable=G\u00E9rer automatiquement les t\u00E9l\u00E9chargements
+ConfigView.label.allowSendVersion=Permettre \u00E0 Vuze\u2122 d'envoyer un num\u00E9ro de version anonyme et un identifiant al\u00E9atoire lors de la recherche de mise \u00E0 jour (dans un but statistique).
+tag.property.constraint=Contrainte
+iconBar.bottom.tooltip=D\u00E9placer en bas de file
+dlg.stream.plus.renew.title=Renouvellement de Vuze\u2122 Plus
+MainWindow.menu.view.beta=Programme Beta
+wizard.choosedirectory=Choisir un r\u00E9pertoire
+MainWindow.menu.file.folder=R\u00E9pe&rtoire
+TableColumn.header.Country.info=Pays du client
+wizard.multitracker.new=Nouveau...
+devices.restrict_access.msg=Liste d'adresses IP (s\u00E9par\u00E9es par une virgule) \u00E0 autoriser [ou \u00E0 refuser si le pr\u00E9fixe '-' est utilis\u00E9]
+MyTorrentsView.clearFilter.tooltip=Supprimer le filtre
+ConfigView.label.switchpriority.tooltip=Une faible priorit\u00E9 r\u00E9duit la vitesse d'envoi allou\u00E9e \u00E0 un torrent.
+Button.retarget=Recibler
+dialog.associations.prompt=Vuze\u2122 n'est pas l'application Bittorrent par d\u00E9faut.\nVoulez-vous associer les fichiers .torrent \u00E0 Vuze\u2122 ?
+restart.error.oom=M\u00E9moire insuffisante
+columnChooser.columndescription=Description
+v3.topbar.menu.show.logo=Logo
+configureWizard.title=Assistant de Configuration
+ConfigView.section.tracker.sendjavaversionandos=Envoyer la version de java et le nom du syst\u00E8me d'exploitation
+PeersView.BlockView.NoAvail.NoHave=Les 2 n'ont pas
+ConfigView.section.connection.advanced.write_select_min=Attente minimum de la s\u00E9lection d'\u00E9criture (milliseconde, par d\u00E9faut %1)
+ConfigView.text.neverStart=Ne jamais d\u00E9marrer
+TableColumn.header.remaining=Restant
+TableColumn.header.swarm_average_completion=Compl\u00E9tion moyenne des clients
+config.external.browser.prog=Ex\u00E9cutable \:
+pairing.host=Adresse de l'h\u00F4te (nom DNS)
+swt.uninstall.window.ok=Supprimer
+GeneralView.label.completed=Termin\u00E9 \:
+MyTorrentsView.menu.explore._windows=Montrer dans l'explorateur
+MyTorrentsView.menu.ipf_enable=Activer le filtre IP
+sidebar.sash.tooltip=F7 pour maquer/afficher rapidement le menu lat\u00E9ral
+azbuddy.ui.table.last_msg=Dernier message
+OpenTorrentWindow.changeDestination=Changer l'emplacement de sauvegarde
+GeneralView.label.maxdownloadspeed=Vit. T\u00E9l. Max.
+popup.error.hideall=Tout cacher
+br.backup.last.time=La derni\u00E8re sauvegarde a eu lieu le
+pairing.op.fail=L'op\u00E9ration de jumelage a \u00E9chou\u00E9
+dialog.add.peers.msg=Entrez chaque adresse de pair comme ceci <h\u00F4te>\:<port> - les entr\u00E9es \u00E9tant s\u00E9par\u00E9es par une virgule
+DHTView.db.local=Local
+MainWindow.about.section.system=Syst\u00E8me
+SystemTray.menu.exit=&Quitter
+PeersView.state=\u00C9tat
+MyTorrentsView.menu.exporthttpseeds=Exporter les URLs de seed HTTP dans le presse-papier
+ConfigView.section.mode.advanced=Avanc\u00E9
+smooth.config=(voir la configuration pour d\u00E9finir la dur\u00E9e de la fen\u00EAtre)
+health.explain.blue=Si source, vous n'\u00EAtes encore connect\u00E9s \u00E0 aucun client\nSi en t\u00E9l\u00E9chargement, vous \u00EAtes connect\u00E9s \u00E0 des clients mais le tracker est d\u00E9connect\u00E9.
+ConfigView.section.tracker.maxposttimemultiplier=Multiplicateur du temps GET pour traiter les POST [0\u00A0\: illimit\u00E9]
+webui.access=Acc\u00E8s (*)
+wizard.singlefile.help=Cr\u00E9er un torrent \u00E0 partir d'un seul fichier
+TableColumn.header.bad_avail_time.info=Derni\u00E8re fois que la copie int\u00E9grale du t\u00E9l\u00E9chargement \u00E9tait disponible
+v3.menu.device.defaultprofile=Profil par d\u00E9faut
+SharedPortServer.alert.selectorfailed=Ne peut \u00E9tablir d'\u00E9coute pour les donn\u00E9es entrantes.\nV\u00E9rifier que le pare-feu est r\u00E9gl\u00E9 de telle fa\u00E7on \u00E0 ce que java(w).exe puisse s'ex\u00E9cuter en tant que 'serveur'.
+library.category.header=Cat\u00E9gorie '%1'
+ConfigView.section.style.addurlsilently.tooltip=Attention\u00A0\: si activ\u00E9, la fen\u00EAtre principale ne sera pas rendue visible\u00A0\!\nSi vous perdez l'ic\u00F4ne Vuze\u2122 d\u00E9sactivez cette option.
+ipCheckerWizard.checkFailed=Erreur, raison\:
+wizard.maketorrents.autoopen=Ouvrir le torrent en source \u00E0 la fin
+TrayWindow.menu.exit=&Quitter
+TorrentOptionsView.param.max.peers=Nombre maximum de connections [0\: illimit\u00E9]
+PiecesView.BlockView.NoHave=Absente
+MainWindow.nat.status.tooltip.ok=Accessibilit\u00E9 OK (TCP)
+ConfigView.section.logging.udptransport=Activer le tra\u00E7age d\u00E9taill\u00E9 du transport UDP
+device.model.name=Nom du mod\u00E8le
+exportTorrentWizard.process.unknownfail.title=Erreur inattendue
+SpeedTestWizard.set.upload.button.apply=Appliquer
+v3.iconBar.view.big.tooltip=Vue simplifi\u00E9
+ConfigView.label.maxnumwant=Limite le nombre de pairs que le tracker peut envoyer
+OpenTorrentWindow.startMode.seeding=En source
+TableColumn.header.crc32=CRC-32
+label.outbound=Sortant
+ConfigView.auto=Auto
+PeerSocket.bad_peer_id=mauvais ID de pair
+TorrentInfoView.torrent.encoding=Encodage du Torrent
+ConfigView.label.lh.ext=Extensions
+ConfigView.section.transfer.autospeed.enabledownadj=Activer les r\u00E9glages de la vitesse de t\u00E9l\u00E9chargement
+subs.prop.last_result=Dernier nouveau r\u00E9sultat trouv\u00E9
+AlertMessageBox.comment=Commentaire
+ConfigView.section.file.decoder.prompt.tooltip=Afficher une bo\u00EEte de dialogue quand un choix d'encodage est possible
+GeneralView.label.trackerurlopen.tooltip=Cliquer pour ouvrir la page Web du Tracker
+DHTTransport.report.sending=envoi des donn\u00E9es
+dialog.pause.for.period.title=Entrer une p\u00E9riode de temps
+MyTorrentsView.menu.health=\u00C0 propos de l'indicateur de sant\u00E9
+SpeedTestWizard.test.panel.currinfo=Test de bande passante BitTorrent.
+ConfigView.section.connection.encryption.min_encryption_level.tooltip=Simple - handshake seulement\nRC4 - tout le flux\nUn encryptage plus fort requiert plus de CPU.
+ConfigView.label.watchtorrentfolderinterval.tooltip=Intervalle de temps entre les rafra\u00EEchissements du contenu du r\u00E9pertoire
+device.mediaserver.remove_all.desc=\u00CAtes-vous s\u00FBr de vouloir supprimer tous les serveurs de m\u00E9dia ?
+MainWindow.menu.file.closewindow=Fermer la &fen\u00EAtre
+FilesView.menu.open=&Ouvrir
+Subscription.menu.resetauth=R\u00E9initialiser les d\u00E9tails d'authentification
+installPluginsWizard.list.nullversion=pas de version
+OpenTorrentOptions.title=Options des torrent
+v3.MainWindow.menu.contentnetworks.manage=G\u00E9rer HD & R\u00E9seaux
+DHTView.operations.sent=Envoy\u00E9
+CacheView.speeds.fromCache=Depuis/Vers Cache
+SpeedView.stats.measured=Mesur\u00E9
+ColumnRenameWindow.title=Renommer la colonne
+configureWizard.transfer2.test=Ex\u00E9cuter le test
+device.playnow.group=Lire maintenant
+Trackers.column.updatein=Suivant
+ipCheckerWizard.checkComplete=IP trouv\u00E9e \:
+PiecesView.DistributionView.SeedAvl=Contribution disponible des seeds
+change.url.msg.title=Changer l'URL pour '%1'
+UpdateWindow.columns.size=Taille
+ConfigView.label.openmytorrents=Ouvrir 'Mes Torrents' au d\u00E9marrage
+network.ipbinding.icon.show=Afficher l'ic\u00F4ne d'\u00E9tat dans la barre d'\u00E9tat lorsque les liaisons sont actives
+MainWindow.dht.status.users=%1 Utilisateurs
+FilesView.rename.choose.path=Choisir un fichier nouveau ou existant
+device.import.title=Importer le p\u00E9riph\u00E9rique ?
+ConfigView.section.irc=IRC
+tag.type.man=Manuel
+Formats.units.Mbit=Mbit
+MainWindow.sr.status.tooltip.bad=Taux de partage %1 mauvais\: < 0.5
+ConfigView.section.style.dropdiraction.opentorrents=Ouvrir les torrents
+ConfigView.section.file.readmblimit.explain=Ce param\u00E8tre limite la m\u00E9moire allou\u00E9e aux lectures en cours.
+xcode.deletedata.message.2=\n(une copie peut encore exister dans '%1')
+MainWindow.status.checking=V\u00E9rification
+IrcView.help=Commandes valides \:\n . /help \: affiche ce message\n . /nick | /name \: change votre alias\n . /me action \: envoie une action\n . /msg [utilisateur] message \: envoie un message priv\u00E9 \u00E0 <alias>\n . /r message \: r\u00E9pond au dernier message priv\u00E9\n . /join \#canal \: change le canal actuel
+ClientStats.column.percent=%
+DHTView.general.leaves=Sorties\u00A0\:
+ColumnSetup.availcolumns=%1 colonne(s) disponible(s)
+MainWindow.menu.plugins.installPlugins=Assistant d'installation
+subscript.add.title=Installer l'abonnement?
+ConfigView.section.connection.prefer.udp=Pr\u00E9f\u00E9rer les connexions UDP
+ConfigView.label.seeding.numPeersAsFullCopy=Pr\u00E9tendre qu'il y a 1 copie compl\u00E8te tous les\n(0\u00A0\: ne pas pr\u00E9tendre)
+ConfigView.section.ipfilter.clear.on.reload=Effacer les filtres lors du rechargement. Pendant le processus de rechargement les adresses IP ne seront pas bloqu\u00E9es. Si rien n'est fait, les derni\u00E8res non-blocs ne prendront pas effet avant le red\u00E9marrage.
+columnChooser.columnname=Nom de la colonne
+OpenTorrentWindow.mb.openError.title=Erreur d'ouverture
+subs.prop.assoc=Associations
+OpenTorrentWindow.addFiles=&Ajouter des fichiers
+dlg.auth.trial.success.info=Faites glisser les fichiers vid\u00E9o de votre biblioth\u00E8que dans "Cr\u00E9er un nouveau DVD." Si vous aviez d\u00E9j\u00E0 ajout\u00E9 une vid\u00E9o avant d'installer les composants, merci de l'ajouter \u00E0 nouveau.
+device.mediaserver.view.title=Serveurs de m\u00E9dia
+ConfigView.label.maxuploads=Nombre d'uploads par d\u00E9faut (par torrent)
+statusbar.feedback.tooltip=Cliquez ici pour envoyer votre commentaire
+GeneralView.label.remaining=Temps/Taille restant\u00A0\:
+GeneralView.section.info=Informations
+swt.updater.urlsgetter.platform=SWT pour\:
+popup.error.details=D\u00E9tails
+Peers.column.lan=LAN
+OpenTorrentWindow.mb.openError.text='%1' n'a pas pu \u00EAtre ouvert\:\r\n%2
+webui.pairing.autoauth=Activer par d\u00E9faut la protection par mot de passe \: nom d'utilisateur \= vuze, mot de passe \= <code d'acc\u00E8s du jumelage>
+MainWindow.upgrade.hint2=Astuce\:\tSi vous voulez fermer Vuze\u2122 plus tard, appuyer sur Annuler et\n\trenommez Azureus2-new.jar en Azureus2.jar apr\u00E8s fermeture
+# > 2.0.8.0
+OpenTorrentWindow.title=Ouvrir le(s) torrent(s)
+MainWindow.upgrade.hint1=Astuce\:\tAppuyer sur Terminer rend l'op\u00E9ration automatique
+TableColumn.header.peers=Clients
+PiecesView.completed=Faits
+Button.search=Rechercher
+splash.plugin.init=Initialisation du Plugin\:
+platform.win32.baddll.sarah=FRITZ\! Application Layer Firewall
+device.model.num=Num\u00E9ro de mod\u00E8le
+MainWindow.menu.speed_limits.load=Application...
+Peers.column.UpRatio.info=Taux "Envoy\u00E9 par vous\:Envoy\u00E9 par les autres" du client
+ConfigView.label.mindownloads=Nombre minimum de t\u00E9l\u00E9chargements simultan\u00E9s
+ConfigView.section.style.customDateFormat=Format de date personnalis\u00E9
+mdi.entry.plus.free=Vuze\u2122 Plus
+Browser.popup.error.no.access=Une erreur s'est produite lors de la tentative d'acc\u00E9der \u00E0 une ressource \u00E9loign\u00E9e.\nR\u00E9essayez ult\u00E9rieurement.\n 
+ConfigView.label.lh.info=Par d\u00E9faut, l'ouverture d'un fichier utilise l'application enregistr\u00E9e par votre syst\u00E8me d'exploitation pour chaque type de fichier.\nVous pouvez ignorer ce comportement en d\u00E9finissant des applications explicites pour chaque extensions de fichier donn\u00E9 [liste s\u00E9par\u00E9e par une virgule].
+ConfigView.label.openbar.incomplete=Barres de t\u00E9l\u00E9chargement\: ouverture automatique des t\u00E9l\u00E9chargements
+ConfigView.label.max_peers_total=Nombre maximum de connexions en tout [0\u00A0\: illimit\u00E9]
+plugin.installer.recommended.plugin=Plugin recommand\u00E9 - voir le descriptif
+dlg.try.trial.title=Essayer DVD Burn
+metasearch.export.select.template.file=Enregistrer le mod\u00E8le
+MyTorrentsView.menu.changeDirectory=Changer le r\u00E9pertoire des donn\u00E9es
+ConfigView.section.style.defaultSortOrder.desc=D\u00E9croissant
+ConfigView.section.tracker.enableudp=Activer l'UDP pour le protocole du tracker
+ConfigView.section.plugins.magnetplugin=Gestionnaire de liens magnet
+wizard.maketorrents.autohost=H\u00E9berger le torrent dans le tracker int\u00E9gr\u00E9
+Trackers.column.seeds.info=Seeds dans l'essaim
+ConfigView.section.style.reOrderDelay.never=Jamais
+iconBar.editcolumns.tooltip=Configuration de la colonne
+Formats.units.MiB=Mio
+ConfigTransferAutoSpeed.upload.capacity.usage=Utilisation de la capacit\u00E9 d'upload
+v3.MainWindow.text.my.account=Mon Compte
+sidebar.dropdown.tooltip=Afficher le menu lat\u00E9rale dans le format de menu
+MainWindow.menu.transfers.pausetransfers.keybinding.mac=Meta+.
+PeersView.timetosend=Temps pour redistribuer la pi\u00E8ce (Mode Super-Source)
+ConfigView.text.neverIgnore=Ne jamais ignorer
+TableColumn.header.maxupspeed.info=Vit. Envoi Max. par torrent
+IrcClient.connected=Connect\u00E9 \u00E0
+MyTrackerView.passive=Passif
+SpeedTestWizard.finish.panel.max.download=T\u00E9l\u00E9chargement maximum \:
+wizard.multitracker=Ajouter des informations Multi-tracker au torrent
+importTorrentWizard.importfile.path=Chemin\:
+MyTorrentsView.menu.filter=Filtre...
+PeersView.gain=Gain
+GeneralView.label.savein=Enregistrer dans\u00A0\:
+TableColumn.header.activityText=Message
+device.tivo.enable=Activer l'assistance TiVo
+pairing.config.icon.show=Afficher l'ic\u00F4ne de Vuze\u2122 \u00E0 distance dans la barre de statut
+DownloadManager.error.datamissing=Donn\u00E9es manquantes
+v3.MainWindow.text.log.out=Se D\u00E9connecter
+CacheView.general.size=Taille totale
+TableColumn.header.duration=Dur\u00E9e
+ConfigView.label.sleep.info=Emp\u00EAcher la mise en veille de l'ordinateur pendant ...
+ump.install=Mise \u00E0 jour rapide en cours\:\nInstallation d'un petit lecteur pour cette vid\u00E9o.
+Button.rename=Renommer
+ActivityView.legend.limit=Taux limite
+ConfigView.section.file.decoder.showlax=Montrer les encodages moins probables
+device.offlinedownloader.view.title=T\u00E9l\u00E9chargeurs hors ligne
+ConfigView.title.full=Options
+TableColumn.header.DateCompleted.info=Date \u00E0 laquelle le t\u00E9l\u00E9chargement du torrent a \u00E9t\u00E9 achev\u00E9e
+ConfigView.section.style.ShowTabsInTorrentView=Afficher des sous-onglets dans la vues Biblioth\u00E8que ({ConfigView.section.security.restart.title})
+ConfigView.section.general=G\u00E9n\u00E9ral
+ConfigView.pluginlist.scan=Recherche de nouveaux plugins
+mdi.entry.dvdburn.new=Nouveau DVD
+ConfigView.label.popup.timestamp=Ajouter des dur\u00E9es pour l'apparition des alertes
+ConfigView.label.openbar=Ouverture automatique des mini-barres
+OpenTorrentWindow.startMode.forceStarted=D\u00E9marrage forc\u00E9
+PeersView.Messaging=Messagerie
+ConfigView.label.downloading.testTime=P\u00E9riode d'\u00E9valuation de la vitesse de t\u00E9l\u00E9chargement [en seconde]
+ConfigView.pluginlist.column.loadAtStartup=Se charge au d\u00E9marrage
+wizard.tracker.local=Utiliser le tracker int\u00E9gr\u00E9 \u00E0 Vuze\u2122
+splash.firstMessageNoI18N=(\: Vuze\u2122 \:)
+deletedata.noprompt=Ne plus me redemander
+TableColumn.header.sr_prog.info=Affiche la date \u00E0 laquelle le rapport de partage du t\u00E9l\u00E9chargement atteint une certaines valeurs
+Stats.title.full=Statistiques
+MyTorrentsView.dialog.setPosition.title=R\u00E9gler la position
+Button.unmarkSelected=D\u00E9marquer les s\u00E9lections
+ConfigView.label.checkOncompletion=V\u00E9rifier le fichier \u00E0 la fin du t\u00E9l\u00E9chargement
+Peers.column.as.info=D\u00E9tails du syst\u00E8me Autonome (AS/Autonomous System en anglais) des pairs
+ColumnSetup.chosencolumns=Colonnes choisies
+GeneralView.label.trackerurlupdate=Mise \u00E0 jour manuelle
+PiecesView.priority.info=la priorit\u00E9 affect\u00E9e \u00E0 cette pi\u00E8ce (pas tr\u00E8s fiable)
+SpeedTestWizard.set.upload.title=D\u00E9finir les limites de t\u00E9l\u00E9chargement et d'upload
+ConfigView.section.connection.encryption.require_encrypted_transport=Exiger un flux crypt\u00E9
+DHTTransport.report.rerequest_bit=re-demande %1/%2 de %3
+Progress.reporting.no.history.to.display=Il n'y a pas de messages de d\u00E9tail \u00E0 afficher.
+OpenTorrentOptions.show.label=Afficher cette bo\u00EEte de dialogue lors de l'ouverture d'un torrent \:
+ConfigView.section.plugins.irc=IRC
+dlg.auth.denied.link=<A HREF\="info">Informations sur les codes d'activation refus\u00E9s</A>
+azbuddy.tracker.bbb.status.idle=Pas de Boost
+security.certcreate.createfail=La cr\u00E9ation du certificat a \u00E9chou\u00E9.
+ConfigView.section.style.use_show_parent_folder=Utilisez "%1" au lieu de "%2" dans les menus torrent
+SpeedTestWizard.finish.panel.disabled=D\u00E9sactiver
+TableColumn.header.tag.count=\# \u00C9l\u00E9ments
+configureWizard.file.fastResume=Activer la reprise rapide
+ConfigView.section.security.op.error=Impossible de terminer l'op\u00E9ration\:\n    %1
+remote.pairing.instruction=Il suffit d'entrer le code ci-dessous dans les emplacements pr\u00E9vus par n'importe quelle application \u00E0 distance.
+TableColumn.header.savepath.info=Le dossier ou le fichier de destination pour les donn\u00E9es du torrent
+swt.updater.urlsgetter.downloading=Liste des sites miroirs en provenance de
+devices.auto.start=D\u00E9marrer automatiquement
+FilesView.menu.setpriority.normal=&Normale
+configureWizard.transfer2.mselect.info=Les xxx/<value> entr\u00E9es indiquent une vitesse de connexion de t\u00E9l\u00E9chargement de <value>.\nPar exemple, si vous avez une connexion ADSL descendante de 768 kbit/sec et de 384 kbit/sec en montant, s\u00E9lectionnez 'xxx/384 kbit/sec'.\nArrondissez \u00E0 la valeur la plus proche si votre vitesse exacte n'est pas repr\u00E9sent\u00E9.
+ConfigView.section.plugins.xml_http_if=Interface XML/HTTP
+iconBar.stream=Lire Maintenant
+v3.iconBar.view.big=Vu
+MyTorrentsView.menu.stop=&Arr\u00EAter
+sidebar.LibraryUnopened=Non visionn\u00E9s
+MyTorrentsView.menu.explore=Ouvrir le dossier
+MainWindow.menu.help.about=\u00C0 &propos de Vuze\u2122
+MainWindow.nat.status.tooltip.bad=Probl\u00E8me NAT (TCP) possible, voir le Wiki si persistant (double-cliquer)
+TableColumn.header.category.info=Nom de la cat\u00E9gorie \u00E0 laquelle le torrent appartient
+DownloadManager.error.operationcancancelled=Op\u00E9ration annul\u00E9e
+ConfigView.label.seeding.firstPriority.shareRatio=Un taux de partage inf\u00E9rieur \u00E0
+label.dismiss.all=Rejeter tout
+device.mediaserver.remove_all=Supprimer tous les serveurs de m\u00E9dia
+IPChecker.external.loadingwebpage=Chargement de la page Web
+subscriptions.config.autostart.min=Ne d\u00E9marre que si >\= Mo [0\: illimit\u00E9]
+v3.MainWindow.button.resume=Reprendre
+azsubs.contextmenu.lookupassoc=Consulter les associations d'abonnement
+platform.win32.baddll.iFW_Xfilter=iolo Personal Firewall\u2122
+TorrentOptionsView.param.max.seeds=Nombre maximum de connexions en seed [0\: limite de connexion]
+TableColumn.header.\#=Ordre
+dhttracker.tracknormalwhenoffline=Ne tracker les torrents normaux que lorsque leur tracker est injoignable
+MainWindow.menu.file.open.url=Emplacement
+Peers.column.peer_byte_id=ID du pair
+MainWindow.menu.file.open.uri=URL, Lien Magnet ou empreinte Hash...
+MainWindow.upgrade.explanation.manual=- \u00C9tape 1\: Fermez Vuze\u2122\n- \u00C9tape 2\: T\u00E9l\u00E9chargez la nouvelle du lien ci-dessous dans le r\u00E9pertoire d'installation de Vuze\u2122\n- \u00C9tape 3\: Red\u00E9marrez Vuze\u2122
+MainWindow.about.internet.forumdiscussion=Forum g\u00E9n\u00E9ral
+pairing.ui.icon.tip=\u00C9tat de la connexion de Vuze\u2122 \u00E0 distance
+ConfigView.label.seeding.ignore=R\u00E8gles Ignorer
+subscript.none.subscribed=Cliquer pour voir les abonnement disponibles pour ce contenu
+ConfigView.section.mode.advanced.text1=Acc\u00E8s complet \u00E0 tous les param\u00E8tres et fonctions.
+TableColumn.header.smoothup=Upload mod\u00E9r\u00E9
+FilesView.dialog.priority.text=0 \= Normal, 1 \= Haute, 2 \= Sup\u00E9rieur...
+alert.raised.at.close=(Message de la pr\u00E9c\u00E9dente fermeture de Vuze\u2122)
+SystemTray.menu.closealldownloadbars=F&ermer toutes les mini-barres
+SpeedTestWizard.finish.panel.max.seeding.upload=Upload maximum en seeding \:
+ConfigView.section.ipfilter.persistblocking=Sauver les d\u00E9tails des IP bloqu\u00E9es entre sessions
+PiecesView.type=Type
+ConfigView.section.plugins.TrackerWeb=Tracker Web
+TableColumn.header.CountryFlag.info=Drapeau du pays du client
+ConfigView.boolean.irclog=Activer la journalisation du canal (dans IRC_log.htm)
+SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread a \u00E9t\u00E9 interrompu avant la fin du test
+ConfigView.section.style.reOrderDelay=R\u00E9-ordonner les tables toutes les 'n' mises \u00E0 jour GUI [0\u00A0\: jamais]
+MySharesView.type.dircontentsrecursive=Contenu du r\u00E9pertoire (et sous-r\u00E9pertoires)
+GeneralView.label.status=Statut \:
+GeneralView.label.uploaded=Envoy\u00E9\u00A0\:
+ConfigView.section.style.alwaysShowTorrentFiles=Toujours montrer les fichiers Torrent dans Details/Fichiers
+ConfigView.section.update.autodownload=T\u00E9l\u00E9charger automatiquement les mises \u00E0 jour et m'avertir lorsque l'installation est pr\u00EAte
+trackername.prefs.message=Liste des noms d'h\u00F4tes de tracker s\u00E9par\u00E9e par un point virgule\nPar exemple\: a.b.com; c.d.net
+OpenTorrentWindow.diskUsage=%1 de %2
+ConfigView.label.removeOnStop=Enlever le torrent de la liste s'il s'arr\u00EAte automatiquement
+device.rss.localonly=Restreindre l'acc\u00E8s uniquement \u00E0 cet ordinateur
+MainWindow.menu.view.myshares.keybinding=Meta+3
+MyTorrentsView.menu.changeTracker=C&hanger l'URL du tracker
+ConfigView.section.file.nativedelete._windows=Placer les fichiers effac\u00E9s dans la corbeille
+ConfigView.section.connection.port.rand.enable=Tirer au hasard les ports d'\u00E9coute au d\u00E9marrage
+MagnetPlugin.report.downloading=T\u00E9l\u00E9charg\u00E9 depuis %1
+MyTorrentsView.dialog.setNumber.upload=upload
+configureWizard.transfer.maxUploadsPerTorrent=Max Envois par Torrent
+FilesView.fullpath=Montrer le chemin d'acc\u00E8s complet
+MainWindow.menu.view.mytracker.keybinding=Meta+2
+Formats.units.Tbit=Tbit
+MagnetPlugin.use.md.download.name=T\u00E9l\u00E9chargement des m\u00E9tadonn\u00E9es pour %1
+ConfigView.section.transfer.setmark=D\u00E9finir/effacer le rep\u00E8re\: les statistiques globales de transfert seront affich\u00E9s \u00E0 partir de ce moment-l\u00E0 (au moment de l'installation de Vuze\u2122, si vous y \u00EAtes autoris\u00E9s)
+externalLogin.auth_method_proxy=Utiliser m\u00E9thode de capture prolong\u00E9e de cookie . Si cela ne fonctionne pas, d\u00E9sactivez l'option et r\u00E9essayez.
+IrcView.errormsg=Erreur de syntaxe /msg \: /msg [utilisateur] texte
+ConfigView.label.autoopen.detailstab=Ouverture automatique de l'onglet de d\u00E9tails lorsque
+ConfigView.label.dl.add.req.attention=Clignoter la rubrique t\u00E9l\u00E9chargement lorsqu'un t\u00E9l\u00E9chargement est ajout\u00E9
+ConfigView.section.plugins.update=Mise \u00E0 jour Plugin
+OpenTorrentWindow.mb.invaliddefsave.text=L'emplacement '%1' n'est pas valide.\n\nSi vous fermez cette fen\u00EAtre, vous serez invit\u00E9 \u00E0 le changer.\n\nL'emplacement d'enregistrement par d\u00E9faut peut \u00EAtre configur\u00E9 via le menu 'Outils-> Options-> Fichiers'.
+label.vuze.services=Services Vuze\u2122
+dht.logging=Activer le tra\u00E7age de l'activit\u00E9
+MyTorrentsView.menu.setDownSpeed=Vit. de t\u00E9l.
+ConfigView.section.style.dropdiraction.sharefolder=R\u00E9pertoire de partage
+subs.prop.num_unread=Nombre de r\u00E9sultats non lu
+ConfigView.section.tracker.separatepeerids.info=Augmente l'anonymat si en t\u00E9l\u00E9chargement/source anonyme\nen utilisant une connexion vers le tracker non-anonyme.
+devices.xcode.prof_def=Profil de transcodage par d\u00E9faut
+ConfigView.label.piecereorderminmb=R\u00E9ordonner seulement les fichiers dont la taille est sup\u00E9rieure \u00E0 (en Mo)
+Wizard.Subscription.search.subtitle2.sub2=Torrents \u00E0 travers tout le Web
+iconBar.start=D\u00E9marrer
+Wizard.Subscription.search.subtitle2.sub1=HD Movies, TV Shows, Films, Bandes-annonces sur le r\u00E9seau Vuze\u2122
+azbuddy.chat.title=Discussion Vuze\u2122
+iconBar.comment=Commentaire
+MainWindow.menu.tools.netstat={Views.plugins.aznetstatus.title}...
+TableColumn.header.DateFileCompleted=Fichier termin\u00E9
+GeneralView.label.updatein=Mise \u00E0 jour dans\u00A0\:
+TorrentOptionsView.param.max.uploads=Nombre maximum d'uploads [minimum\: 2]
+TableColumn.header.device=P\u00E9riph\u00E9rique
+ConfigView.section.style.doNotUseGB.tooltip=Si activ\u00E9, Vuze\u2122 utilisera des Mo m\u00EAme pour des tailles sup\u00E9rieures \u00E0 1024MB
+proxy.socks.ui.icon.tip=Statut SOCKS\: %1\nDouble-cliquez pour les stats\nFaites un clic droit pour les options
+TableColumn.header.writerate=Taux d'\u00E9criture
+dlg.auth.trial.success.line1=Vuze\u2122 est pr\u00EAt \u00E0 cr\u00E9er des DVD.
+splash.initializeUIElements=Initialisation des \u00E9l\u00E9ments d'interface
+jvm.reset=R\u00E9initialiser les options de la machines virtuelle Java\u2122 avec les options par d\u00E9faut
+azbuddy.addtorrent.title=Accepter le t\u00E9l\u00E9chargement?
+MyShares.column.category=Cat\u00E9gorie
+DHTView.transport.out=Sortant\u00A0\:
+subs.prop.is_auto=T\u00E9l\u00E9charger automatiquement les nouveaux r\u00E9sultats
+PeersView.menu.snubbed=Ignor\u00E9
+ConfigView.section.style.defaultSortOrder=Sens de classement par d\u00E9faut
+ConfigView.section.proxy.enable_socks.peer=Activer le proxy pour les communications entre clients (pour les connexions sortantes uniquement).
+Progress.reporting.no.reports.to.display=Il n'y a pas de rapports d'activit\u00E9 \u00E0 afficher pour le moment.
+ConfigView.label.xfs.allocation=Allouer les nouveaux fichiers en utilisant une m\u00E9thode sp\u00E9cifique au syst\u00E8me de fichier XFS
+TableColumn.header.download.info=Quantit\u00E9 de donn\u00E9es re\u00E7ues par le pair
+label.browser=Navigateur
+cat.rss.gen=Cr\u00E9er un flux RSS local
+config.internal.browser=Navigateur interne
+SpeedView.stats.currentPing=Ping actuel \:
+DownloadManager.error.badsize=Taille incorrecte
+TableColumn.header.date_added=Date ajout\u00E9
+TableColumn.menu.maxuploads=\# Uploads maximum
+TableColumn.header.class=Classe
+ConfigView.section.logging=Journalisation
+ConfigView.section.connection.advanced.socket.group=Options de Socket
+speedtest.wizard.title=Test de d\u00E9bit
+ConfigView.section.proxy=Options Proxy
+MainWindow.menu.community.wiki=&Wiki Communautaire
+ActivityView.legend.peeraverage=Moyenne
+subscriptions.rss.enable=Cr\u00E9er un flux RSS \u00E0 partir d'un abonnement
+MyTrackerView.badnat.info=Sources/Clients ayant \u00E9chou\u00E9s au test NAT, si activ\u00E9
+ConfigView.label.bindip.details=Exemple\: 192.168.1.5;eth0;eth1[2] liera l'adresse IP sp\u00E9cifi\u00E9e, \u00E0 toutes les adresses de la 1\u00E8re interface et \u00E0 la 3\u00E8me adresse de la 2nd interface.\nLa 1\u00E8re adresse IP sera utilis\u00E9e pour tous les services, toutes les autres seront seulement utilis\u00E9es pour la r\u00E9partition des charges\nLes interfaces suivantes sont disponibles\:\n%1
+ConfigView.section.ipfilter.list.notinrange=n'est dans aucune plage
+TableColumn.header.seeds=Sources
+button.columnsetup.tooltip=Configuration de la colonne
+security.crypto.persist_for.session=le temps de la session
+wizard.webseed.configuration=Configuration des seeds HTTP
+OpenTorrentWindow.mb.notTorrent.text=Impossible d'ouvrir '%1'. Il semble qu'il ne s'agit pas d'un fichier .torrent\n\nUne parties des donn\u00E9es re\u00E7ues \:\n%2
+GeneralView.label.comment=Commentaire\u00A0\:
+label.wrap.text=Envelopper le texte
+remote.pairing.test.unavailable=Oups, impossible de d\u00E9terminer votre connectivit\u00E9 \u00E0 distance. <A HREF\="retry">R\u00E9essayer</A>
+TableColumn.header.seeds.fullcopycalc=%2 copies compl\u00E8tes pour %1 clients
+iconBar.switch.tooltip=S\u00E9lecteur d'interface graphique Vuze\u2122
+v3.topbar.menu.show.plugin=Zone plugin
+v3.menu.device.exploreTranscodes._windows=Afficher les fichiers dans l'explorer Windows\u00AE
+devices.contextmenu.od.auto=<Automatique>
+security.certtruster.intro=Le certificat de s\u00E9curit\u00E9 provient d'une compagnie \u00E0 laquelle vous ne faites pas confiance
+ConfigView.section.style.xulRunnerPath=Indiquez le chemin Xulrunner / Firefox manuellement [requis pour FF3, red\u00E9marrage n\u00E9cessaire]
+MyTrackerView.announces=Annonces
+metasearch.template.version.bad=Le mod\u00E8le de recherche '%1' ne peut pas \u00EAtre install\u00E9, Vuze\u2122 doit \u00EAtre mis \u00E0 jour
+ConfigView.label.minSeedingTime=Temps de source minimum en secondes
+OpenTorrentWindow.torrent.options=Les param\u00E8tres suivants seront appliqu\u00E9s aux torrents s\u00E9lectionn\u00E9s ci-dessus
+PeersView.upload.info=Votre vitesse moyenne d'envoi au client.
+MyTrackerView.bytesinave=Moyenne Entr\u00E9e
+restart.error=Le red\u00E9marrage a \u00E9chou\u00E9\:\n%1\nConsulter la page, <A HREF\="{restart.error.url}">questions concernant le red\u00E9marrage</a>.
+TableColumn.header.CountryFlagSmall.info=Petit drapeau du pays du client
+Subscription.menu.export=Exporter
+ConfigView.label.stop.Sleep=Mettre en veille l'ordinateur
+DHTTransport.report.send_timeout=envoi hors d\u00E9lai
+label.test.types=Types de test
+play.select.content=S\u00E9lectionner le contenu \u00E0 lire
+menu.plus=Vuze\u2122 Plus
+Plugin.localtracker.autoadd.info=Ajouter automatiquement ces pairs locaux [adresses s\u00E9par\u00E9es par ';', par exemple 1.2.3.4;4.5.6.7]
+# %1 = "in kbps" or ""; %2 = "upload" or "download"
+MyTorrentsView.dialog.setNumber.text=Entrer un nombre %1 pour changer %2 vers\:
+Trackers.column.status=Statut
+PeersView.uploadspeed.info=Votre vitesse d'envoi actuelle au client.
+TableColumn.header.down.info=Quantit\u00E9 actuel des donn\u00E9es re\u00E7ues par d'autres utilisateurs
+MainWindow.dht.status.tooltip=Lorsque la Base de donn\u00E9es distribu\u00E9e est en cours d'ex\u00E9cution cela montre le nombre estim\u00E9 d'utilisateurs en ligne
+azinstancehandler.alert.portclash=Conflit de port sur LAN\u00A0\: %1 est d\u00E9j\u00E0 utilis\u00E9 par un autre utilisateur, veuillez s\u00E9lectionner un (deux) port(s) au hasard pour l'\u00E9coute TCP/UDP [entre %2 et %3]
+OpenTorrentWindow.mb.alreadyExists.text=Le <A HREF\="%1">%3</A> a d\u00E9j\u00E0 \u00E9t\u00E9 ajout\u00E9 en tant que '%2'
+MainWindow.menu.speed_limits.schedule.msg=R\u00E8gles actuelles qui contr\u00F4lent l'application automatique de profils de limitation de vitesse
+PeerManager.status.ok=OK
+ConfigView.section.mode.title=Niveau utilisateur
+external.browser.manual=Manuel
+label.n.will.be.downloaded=%1 sera t\u00E9l\u00E9charg\u00E9
+ConfigView.section.interface.enabletray=Activer les options de la zone de notification [D\u00E9marrage de Vuze\u2122 requis]
+metasearch.addtemplate.dup.title=Mod\u00E8le dupliqu\u00E9
+PeersView.BlockView.AvailCount=Disponibilit\u00E9
+iconBar.openFolder.tooltip=Ouvrir un r\u00E9pertoire
+Plugin.localtracker.name=D\u00E9tecteur de clients sur LAN
+restart.error.bad=Format de fichier incorrect pour '%1'
+CacheView.writes.title=\u00C9critures E/S
+v3.MainWindow.menu.publish=&Publier
+TableColumn.header.peakup=Upload \u00E9lev\u00E9
+MainWindow.menu.view.show=Afficher
+configureWizard.transfer2.test.info=S\u00E9lectionner pour effectuer un test de vitesse
+subscriptions.config.autostart.max=Ne d\u00E9marre que si <\= Mo [0\: illimit\u00E9]
+library.unopened.header=%1 \u00E9l\u00E9ment
+ConfigView.section.security.restart.title=Red\u00E9marrage requis
+ConfigView.section.connection.tcp.enable=Activer TCP
+splash.initializeGM=Initialisation du Global Torrent Manager
+subscriptions.listwindow.title=Abonnements
+Peers.column.%=%
+MainWindow.menu.tools=&Outils
+ConfigView.section.connection.http.enable=Activer
+diagnostics.log_found=Vuze\u2122 ne s'est pas ferm\u00E9 correctement. Regarder dans %1 pour des fichiers log de diagnostic et envoyer \u00E0 l'\u00E9quipe de Vuze\u2122 si c'est le r\u00E9sultat d'une erreur de l'application. Penser \u00E0 chercher 'Vuze\u2122 Disappears' dans le Wiki (voir le menu Aide).
+plugins.basicview.activity=Activit\u00E9\:
+natpmp.routeraddress=Adresse de la station [vide\: automatique]
+dlg.auth.denied.line1=Votre code d'activation Vuze\u2122 Plus a \u00E9t\u00E9 refus\u00E9e. Merci de cliquez sur le lien ci-dessous pour obtenir plus d'informations.
+Button.availableSubscriptions=Abonnements disponibles
+MyTorrentsView.menu.moveDown=Vers le ba&s
+UpdateWindow.quit=Quitter
+PeersView.host.info=Le nom d'h\u00F4te du pair, si disponible (peut affecter les performances)
+wizard.directory.help=Cr\u00E9er un torrent \u00E0 partir d'un r\u00E9pertoire
+Peers.column.maxdownspeed=D\u00E9bit descendant maximum
+DHTView.general.uptime=En service\u00A0\:
+MainWindow.menu.help.support=&Aide
+MyTorrentsView.menu.moveTop=&Haut
+ConfigView.label.xfs.allocation.tooltip=Assurez-vous que /usr/sbin/xfs_io est correctement install\u00E9 sur votre syst\u00E8me. La plupart des distributions Linux l'incluent dans le paquetage "xfsprogs".
+MyTorrentsView.menu.manual.shared_peers=Manuellement (dans les pairs)
+wizard.multitracker.edit.newtracker=Nouveau tracker
+PiecesView.title.full=Pi\u00E8ces
+TorrentOptionsView.param.reset.button=R\u00E9initialiser
+menu.register=Activation de Vuze\u2122 Plus
+upnp.mapping.trackerclientudp=Port client de Tracker UDP
+ConfigView.section.connection.networks.Public=R\u00E9seau IP public (pas anonyme)
+MyTorrentsView.menu.editTracker=\u00C9diter l'(les) &URL(s) du tracker
+IrcView.privatefrom=De
+ConfigView.section.mode.resetdefaults=R\u00E9initialiser la configuration avec les valeurs par d\u00E9faut (red\u00E9marrage recommand\u00E9)
+TableColumn.header.peersources=Origines des clients
+DHTView.general.live=En vie\u00A0\:
+ConfigView.label.moveifsamedrive=Mais que faire lorsque la source et la destination sont sur des syst\u00E8mes de fichiers diff\u00E9rents
+configureWizard.file.message3=Vuze\u2122 placera les fichiers t\u00E9l\u00E9charg\u00E9s dans un dossier sp\u00E9cifique, vous pouvez choisir ce dossier ici \:
+configureWizard.file.message2=Vuze\u2122 peut reprendre instantan\u00E9ment le t\u00E9l\u00E9chargement de vos fichiers, en ajoutant des informations de reprise dans vos torrents. Gr\u00E2ce \u00E0 cette fonctionnalit\u00E9, vous pourrez \u00E9galement poursuivre le t\u00E9l\u00E9chargement des pi\u00E8ces partiellement re\u00E7ues.
+subs.prop.is_public=Publique
+configureWizard.file.message1=Vuze\u2122 va sauvegarder vos .torrent actif dans un r\u00E9pertoire sp\u00E9cifique, qui sera\u00A0\:
+webui.pairingenable=Activer le jumelage pour ce plugin (les options de test seront activ\u00E9es une fois que les d\u00E9tails sur le jumelage actuelles seront publi\u00E9s avec succ\u00E8s)
+ConfigView.label.autoadjust=Ajuster automatiquement ces param\u00E8tres en fonction de la vitesse de connexion
+devices.tivo.machine=Nom de la machine TiVo
+ConfigView.section.ipfilter.start=IP de d\u00E9part
+wizard.directory=R\u00E9pertoire
+globalmanager.download.remove.veto=V\u00E9to d'arr\u00EAt
+ConfigView.section.file.defaultdir.ask=R\u00E9pertoire par d\u00E9faut\:
+upnp.alert.lostdevice=UPnP\: A perdu la connexion '%1' sur le p\u00E9riph\u00E9rique UPnP '%2'
+MyTorrentsView.menu.sl_add_to_prof=Ajouter au/Mettre \u00E0 jour le profil
+devices.view.heading=Conversion du m\u00E9dia pour permettre sa lecture par le p\u00E9riph\u00E9rique
+azbuddy.ui.table.ss=SS
+SystemTray.menu.open_global_transfer_bar=Montrer la barre de transferts
+devices.downloading=T\u00E9l\u00E9chargement
+ConfigView.section.stats.graph_update_dividers=Afficher une ligne verticale tous les 60 rafraichissements
+Formats.units.Gbit=Gbit
+ConfigView.section.queue.seeding.ignore=R\u00E8gles "Ignorer"
+TableColumn.header.timesincedownload=T\u00E9l\u00E9chargement bas
+ConfigView.section.connection.advanced.mtu=Maximum Transmission Unit (MTU) de la ligne
+azsubs.contextmenu.addassoc=Ajouter une association d'abonnement
+Peers.column.Encryption.info=Niveau d'encryptage utilis\u00E9
+ConfigView.section.connection.advanced.bind_port=Lier au port local [0\: d\u00E9sactiv\u00E9]
+tps.tracker.cache1=Cache de pairs\: utilis\u00E9\=%1
+MainWindow.dialog.restartconfirmation.title=Red\u00E9marrer Vuze\u2122 ?
+ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Lorsqu'elle est d\u00E9sactiv\u00E9e, les descriptions ne seront pas rappel\u00E9s
+sidebar.Activity=Notifications
+upnp.selectedinterfaces=Interfaces s\u00E9lectionn\u00E9es (s\u00E9par\u00E9es par ';' [ex\: eth0;eth1]) [vide\: toutes]
+ConfigView.label.moveonlyusingdefaultsave.tooltip=Ne d\u00E9placer que si le .torrent est dans le r\u00E9pertoire de sauvegarde par d\u00E9faut
+tag.show.stats=Voir les statistiques de cat\u00E9gories...
+ConfigTransferAutoSpeed.mode=Mode\:
+MagnetURLHandler.report.error=erreur %1
+v3.devicesview.infobar.text2=Pour transcoder du contenu vers un p\u00E9riph\u00E9rique, il suffit de le faire glisser depuis votre biblioth\u00E8que vers un des p\u00E9riph\u00E9riques de la barre lat\u00E9rale. Pour voir si le transcodage est termin\u00E9, cliquez sur le p\u00E9riph\u00E9rique concern\u00E9.
+azbuddy.os_not_avail=Pas disponible
+MyTorrentsView.menu.torrent.dl=Lien de t\u00E9l\u00E9chargement du torrent
+OpenTorrentWindow.mb.existingFiles.partialList=(Liste partielle. Plus de fichiers existent d\u00E9j\u00E0)
+wizard.maketorrent.filesize=Taille fichier(s)
+TableColumn.header.downloadspeedoverall.info=Taux estim\u00E9 de t\u00E9l\u00E9chargement de ce pair
+DHTView.operations.store=Enregistrements
+subscriptions.column.SubWizRank=Rang
+FilesView.menu.retarget=D\u00E9placer les fichiers
+TrayWindow.menu.stopalldownloads=&Arr\u00EAter tous les t\u00E9l\u00E9chargements
+iconBar.top.tooltip=D\u00E9placer en t\u00EAte de file
+MainWindow.dht.status.disabled=D\u00E9sactiv\u00E9
+SpeedTestWizard.stage.message.requesting=demande en cours...
+MainWindow.menu.transfers.pausetransfersfor.keybinding.mac=Opt+Ctrl+Shift+.
+device.od.enable=Activer le p\u00E9riph\u00E9rique de t\u00E9l\u00E9chargement hors ligne
+Button.getstarted=Commencer
+SpeedView.stats.estimate=Estim\u00E9
+MainWindow.menu.speed_limits.save_current=Enregistrer les limites actuelles sous...
+ConfigView.section.interface.clearsavepathsbutton=Effacer
+OpenTorrentWindow.fileList.changeDestination=Changer l'emplacement de sauvegarde
+MyTorrentsView.menu.movedata=D\u00E9placer les donn\u00E9es...
+Progress.reporting.status.retrying=R\u00E9essayer...
+ConfigView.section.style.showiconbar=Afficher la barre d'outils
+label.current=Actuel
+pairing.accesscode=Code d'acc\u00E8s
+v3.deviceview.infobar.line2.tivo=Diffuser des vid\u00E9os en vous rendant dans l'interface graphique de votre TiVo et en s\u00E9lectionnant Vuze\u2122 dans votre liste de lecture en cours.
+MessageBoxWindow.nomoreprompting=Ne plus me redemander
+SpeedTestWizard.name.conf.level.none=Aucun
+devices.xcode.mancopy=Copier les fichiers manuellement
+MainWindow.menu.file.import=&Importer un torrent XML...
+Tracker.alert.listenfail=Ne peut pas \u00E9couter sur le port %1.\nV\u00E9rifiez si d'autres applications ne sont pas en train d'utiliser ce port.\nV\u00E9rifiez \u00E9galement si une autre version de Vuze\u2122 n'est en cours d'execution.
+v3.MainWindow.menu.file.closewindow=Fermer
+ConfigView.label.minSpeedForActiveDL=Ne pas compter de cr\u00E9neau de t\u00E9l\u00E9chargement pour les torrents dont la vitesse est de moins de
+MagnetPlugin.use.md.download=Permettre le transfert de m\u00E9tadonn\u00E9es bas\u00E9 sur le t\u00E9l\u00E9chargement
+importTorrentWizard.torrentfile.browse=Rechercher
+label.force.piece=Forcer
+Peers.column.%.info=Pourcentage du torrent que le pair a t\u00E9l\u00E9charg\u00E9 jusqu'\u00E0 pr\u00E9sent
+upnp.info=Universal Plug and Play (UPnP) permet le mapping automatique de ports sur des routeurs supportant l'UPnP.
+ConfigView.section.file.hashchecking.smallestfirst=V\u00E9rifiez \u00E0 nouveau les plus petits t\u00E9l\u00E9chargements en premier
+label.popups=Popups
+TableColumn.header.profile=P\u00E9riph\u00E9rique
+config.external.browser.switch.feature=Caract\u00E9ristique
+label.clickone=Cliquez sur l'un des choix
+PeersView.title.short=D\u00E9tails
+ConfigView.label.seeding.rankType.tooltip=Les torrents de plus haut rangs sont d\u00E9marr\u00E9s automatiquement.\nSi un torrent prend un rang plus \u00E9lev\u00E9, l'autre torrent s'arr\u00EAte et se remet dans la file d'attente.\n\nSeuls les torrents "En attente..." sont disponibles pour un d\u00E9marrage automatique.\nJamais les torrents arr\u00EAt\u00E9s seront d\u00E9marr\u00E9s automatiquement.
+OpenTorrentWindow.torrentLocation=fichier(s) torrent\:
+network.admin.binding.state=Liaisons \: %1, force\=%2
+ConfigView.section.tracker.maxpeersreturned=Nombre maximum de clients renvoy\u00E9s [0\u00A0\: illimit\u00E9]
+v3.MainWindow.xofx=%1 sur %2
+MyTorrentsView.menu.setpriority.high=&Haute
+ConfigView.label.seeding.autoReposition.tooltip=Si activ\u00E9e, l'ordre des torrents (la colonne '\#') sera chang\u00E9 pour s'accorder \u00E0 celui des "Rangs de source"\nC'est utile si vous ne voulez pas voir les nombres des rangs de source mais voulez tout de m\u00EAme savoir dans quel ordre les torrents compl\u00E9t\u00E9s vont d\u00E9marrer.
+MyTorrentsView.menu.open=&Ouvrir
+label.routing=Routage
+GeneralView.label.updatein.querying=Requ\u00EAte en cours...
+ConfigTransferAutoSpeed.algorithm=Algorithme\:
+CacheView.reads.fromFile=Depuis Fichier
+installPluginsWizard.finish.title=Installation en cours
+ManagerItem.initializing=Initialisation
+ConfigView.section.logging.generatediagnostics=G\u00E9n\u00E9rer
+DHTView.activity.status=\u00C9tat
+MainWindow.menu.language=&Langue
+IPChecker.external.service.no-ip.name=No-IP
+update.instance.uninstall=V\u00E9rification des d\u00E9sinstallations
+MainWindow.menu.view.iconbar=Barre d'outil
+devices.xcode.autoStart=D\u00E9marrer automatiquement si n\u00E9cessaire
+ConfigView.section.transfer.autospeed.networks=D\u00E9tails sur le r\u00E9seau
+v3.MainWindow.menu.view.actionbar=Barre d'action
+MainWindow.menu.file.share=&Partager
+DHTView.db.divsize=Div. Taille.
+dht.advanced=Activer les r\u00E9glages avanc\u00E9s
+label.inactive=Inactif
+MagnetPlugin.decentral_backup_disabled=<sauvegarde d\u00E9centralis\u00E9e d\u00E9sactiv\u00E9>
+v3.MainWindow.menu.home=&Accueil
+MainWindow.nat.status.tooltip.probok=Accessibilit\u00E9 OK, mais pas de connections entrantes (TCP) r\u00E9centes
+device.config.xcode.workdir=R\u00E9pertoire de travail par d\u00E9faut pour les fichiers transcod\u00E9s
+ConfigView.label.queue.maxactivetorrentswhenseeding=Max quand uniquement en source [0\u00A0\:illimit\u00E9]
+DHTView.activity.type=Type
+button.add.container=Ajouter Conteneur
+ConfigView.section.ipfilter.blockedinfo=IPs bloqu\u00E9es par les filtres IP
+ConfigView.section.Pairing=Jumelage
+MyTorrentsView.menu.thisColumn.autoTooltip=Toujours afficher l'infobulle
+security.crypto.badpw=Le mot de passe fourni est incorrect
+TableColumn.header.azsubs.ui.column.subs.info=Bouton qui vous permet de vous abonner \u00E0 des flux qui contiennent des torrents
+Button.bar.hide=Masquer
+alert.copy.on.comp.done=T\u00E9l\u00E9chargement %1\nLes fichiers ont \u00E9t\u00E9 copi\u00E9s avec succ\u00E8s vers '%2'
+window.welcome.title=Bienvenue dans Vuze\u2122 %1
+pairing.status.initialising=Initialisation
+config.external.browser.switch.external=Externe
+ConfigView.section.ipfilter.list.baddata=a envoy\u00E9 de mauvaises donn\u00E9es\: nombre de fois \=
+window.updateswt.failed=Mise \u00E0 jour impossible. Appuyez sur OK pour recommencer la proc\u00E9dure.
+#Used by the webui plugin
+MyTorrentsView.menu.removeand.deleteboth=e&ffacer tout
+dlg.install.mlab.description=Merci de patienter pendant que le composant de test de vitesse s'installe
+importTorrentWizard.importfile.message=Choisissez le fichier \u00E0 importer\:
+MyTorrentsView.menu.renameColumn={ColumnRenameWindow.title}...
+v3.MainWindow.menu.view.statusbar=Barre d'\u00E9tat
+label.ago=depuis
+dlg.auth.enter.revoked=Le code d'activation actuel a \u00E9t\u00E9 r\u00E9voqu\u00E9.
+FileView.BlockView.Done=Termin\u00E9
+iconBar.remove=Supprimer
+device.quit.transcoding.title=Transcodage en cours
+dht.status.disabled=D\u00E9sactiv\u00E9, la base de donn\u00E9es distribu\u00E9e n'est pas disponible
+Views.plugins.IRC.title=IRC - Support Technique en Ligne
+DHTView.operations.failed=\u00C9chec
+UpdateMonitor.messagebox.verification.failed.text=La v\u00E9rification de '%1' a \u00E9chou\u00E9 \: %2
+TableColumn.header.Thumbnail.info=Vignette du contenu Vuze\u2122; pour tous les autres contenus, le syst\u00E8me d'exploitation fournit ces ic\u00F4nes.
+subscriptions.column.name=Abonnement
+subscriptions.column.new.info=Indique si plus d'un nouveau r\u00E9sultat
+azbuddy.ui.menu.dec=D\u00E9crypter le contenu du presse-papier
+Peers.column.peer_id=ID du pair
+ManagerItem.allocating=Allocation
+core.shutdown.alert=Action '%1' d\u00E9clench\u00E9e %2
+Sidebar.beta.title=Programme Beta
+MyTorrentsView.dialog.setNumber.inKbps=en kbit/s
+seedmore.uploadmore=Un taux de partage inf\u00E9rieur \u00E0 100% est mauvais pour le r\u00E9seau BitTorrent.\nVous devriez continuer \u00E0 partager ce torrent.\n\u00CAtes-vous s\u00FBr de vouloir continuer\u00A0?
+device.hide=Masquer le p\u00E9riph\u00E9rique
+priority.normal=Priorit\u00E9 Normal
+MyTorrents.items.UpSpeedLimit.unlimited=Illimit\u00E9
+MainWindow.about.section.internet=Sur Internet
+TableColumn.header.smootheta.info=D\u00E9bit ETA mod\u00E9r\u00E9 {smooth.config}
+Plugin.localtracker.enable=Activer la d\u00E9tection des clients sur le LAN
+OpenTorrentWindow.mb.notValid.text=Impossible d'ouvrir le torrent '%1'. Si vous ouvrez en mode seeding, merci de vous assurez que les fichiers de donn\u00E9es torrent existent.
+ipCheckerWizard.service=Service
+ConfigView.section.tracker.separatepeerids=Utiliser des identit\u00E9s clients diff\u00E9rentes pour les communications de donn\u00E9es et vers le tracker.
+ConfigView.section.interface.resetassoc=R\u00E9initialiser les associations de fichiers de l'explorateur (.torrent)
+SpeedView.stats.session.tooltip=Total (Protocole)
+security.certcreate.city=Ville ou Localit\u00E9
+swt.install.window.title=Installateur de plugins pour Vuze\u2122
+ConfigView.section.server.enableudp=Activer le protocole UDP pour le client tracker. Utilise le m\u00EAme port que TCP.
+ConfigView.section.stats.choosedefaultsavepath=Veuillez choisir le r\u00E9pertoire de sauvegarde des statistiques
+SpeedView.downloadSpeed.title=Vitesse de t\u00E9l\u00E9chargement
+ConfigView.label.defaultstarttorrentsstoppedandpause=Quand un torrent est ajout\u00E9 dans un \u00E9tat arr\u00EAt\u00E9 automatiquement, mettre celui-ci en pause
+TableColumn.header.smoothdown.info=D\u00E9bit de t\u00E9l\u00E9chargement mod\u00E9r\u00E9 {smooth.config}
+ConfigView.label.allowsameip.tooltip=\u00C0 n'activer qu'en cas de BESOIN.\nProtection contre les "leechers" (quand d\u00E9sactiv\u00E9).
+SpeedTestWizard.finish.panel.max.upload=Upload maximum \:
+device.error.xcodefail=\u00C9chec du transcodage
+TableColumn.header.timesinceupload=Upload bas
+ConfigView.label.seeding.rankType.none.tooltip=Ordre \u00E0 partir de la colonne '\#'
+device.od.error.notfound=L'appareil semble \u00EAtre d\u00E9connect\u00E9
+ConfigView.section.transfer.autospeed.info=Le d\u00E9bit automatique ajuste automatiquement la limite de vitesse d'upload pour \u00E9viter de surcharger la connexion r\u00E9seau.\n\nCes limites ne seront appliqu\u00E9es que lorsque la vitesse d'upload automatique et la base de donn\u00E9es distribu\u00E9e sont activ\u00E9es.\n
+sidebar.LibraryCD.tooltip=Il y a %1 torrent(s) incomplet(s), dont %2 est/sont en cours de seeding
+exportTorrentWizard.exportfile.path=Chemin
+dlg.auth.success.subtitle=F\u00E9licitations \!
+pairing.srp.setpw.doit=Changer
+MyTorrentsView.menu.clear_resume_data=Effacer les donn\u00E9es de 'reprise rapide'
+ipfilter.options=Options du Filtre IP...
+security.crypto.password.mismatch=Les valeurs de mot de passe saisies ne correspondent pas, merci de le ressaisir.
+label.contraints=Contraintes ...
+ConfigView.label.maxuploadswhenbusymin=Vitesse maximale d'upload par torrent lorsque le temps n'est pas calcul\u00E9 [en seconde]
+MainWindow.menu.beta.off=Quitter le programme Beta...
+ConfigView.section.style.alwaysRefreshMyTorrents=Toujours rafra\u00EEchir 'Mes Torrents'
+PeersView.port=Port
+TableColumn.header.lan.info=Indicateur signalant si le correspondant est sur votre r\u00E9seau local
+Button.set=D\u00E9finir
+webui.group.access=Contr\u00F4le d'acc\u00E8s
+dlg.auth.install.failed.title=\u00C9chec de l'activation
+ConfigView.label.password=Prot\u00E9ger Vuze\u2122 par un mot de passe\nN\u00E9cessaire pour d\u00E9-iconifier, ainsi qu'au lancement.
+configureWizard.transfer2.current=<R\u00E9glages actuels>
+wizard.multitracker.edit.deletegroup=Effacer
+Button.close=Fermer
+ConfigView.section.connection.advanced.bind_port.tooltip=Les connections sortantes seront li\u00E9es localement \u00E0 ce port.\nPeut aider avec certaines instabilit\u00E9s NAT des routeurs.
+ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=Nombre maximum de connexions sortantes que Vuze\u2122 tente d'\u00E9tablir \u00E0 un instant donn\u00E9.\nNOTE\: Windows XP Service Pack 2 (SP2) impose une limite au syst\u00E8me de 10 essai simultan\u00E9s.\nValeur par d\u00E9faut\: 5.
+ConfigView.section.stats.enable=Activer
+FilesView.title.full=Fichiers
+TableColumn.menu.sr_prog.interval=D\u00E9finir l'intervalle de progression...
+TableColumn.header.tag.xcode=Transcoder automatiquement
+ConfigTransferAutoSpeed.add.comment.to.log=Ajouter un commentaire\:
+sidebar.VuzeHDNetwork=R\u00E9seau HD de Vuze\u2122
+br.backup.last.error=Derni\u00E8re erreur de sauvegarde\:
+ConfigView.section.proxy.socks.version=Version SOCKS
+uninstallPluginsWizard.finish.explanation=Les plugins s\u00E9lectionn\u00E9s seront supprim\u00E9s gr\u00E2ce \u00E0 l'assistant de mise \u00E0 jour.
+IrcView.privateto=\u00C0
+MainWindow.menu.view.console=C&onsole
+Wizard.Subscription.create.rss=RSS
+SpeedView.stats.session=Cette Session
+TableColumn.header.sha1=SHA1
+ScrapeInfoView.title=Tracker primaire
+security.certcreate.firstlastname=Pr\u00E9nom et nom
+ConfigView.section.style.colorOverride.progressBar=Barre de progression
+MyTorrentsView.menu.host=H\u00E9&berger...
+SpeedView.stats.downloaded=T\u00E9l\u00E9charg\u00E9 (Protocole)
+SpeedTestWizard.abort.message.not.unchoked=Impossible de t\u00E9l\u00E9charger \u00E0 partir de l'un des pairs n'ayant jamais \u00E9t\u00E9 ranim\u00E9 par eux
+Subscription.menu.remove=Effacer
+ConfigView.label.maxdownloads.tooltip=Vous allez toujours \u00EAtre en mesure de t\u00E9l\u00E9charger autant de fichiers que vous sp\u00E9cifiez ici.\n Par contre les torrents identifi\u00E9s "1\u00E8re priorit\u00E9" peuvent voler un emplacement de t\u00E9l\u00E9chargement si c'est absolument n\u00E9cessaire.
+ConfigView.section.tracker.extensions=Extensions
+DiskManager.error.nospace=Espace disque insuffisant
+OpenTorrentWindow.torrentTable.name=Nom
+ConfigView.label.seeding.firstPriority.following=conditions suivantes\u00A0\:
+ConfigView.section.security.toolsinfo=Les fichiers JAR sign\u00E9s sont utilis\u00E9s par certains plugins, par exemple l'interface Web Swing (si configur\u00E9e pour).\nPour signer des fichiers JAR, il faut avoir acc\u00E8s \u00E0 'tools.jar' qui d\u00E9pend de l'environnement de d\u00E9veloppement Sun JDK (et pas du simple JRE).\nSi seul le JRE est install\u00E9, veuillez installer le JDK.\nVuze\u2122 doit pouvoir trouver le fichier pour vous. Sinon, vous pouvez pr\u00E9ciser son chemi [...]
+ConfigView.label.watchtorrentfolder.tooltip=Recherche les nouveaux .torrent r\u00E9guli\u00E8rement
+ConfigView.section.file.resume.recheck.all=Lors d'un red\u00E9marrage apr\u00E8s crash, v\u00E9rifier tout le fichier (sinon seules les pi\u00E8ces actives avant le crash seront v\u00E9rifi\u00E9es)
+ConfigView.section.connection.peersource.PeerExchange=Fourni par un autre client
+v3.MainWindow.button.viewdetails=D\u00E9tails
+ConfigView.label.xfer.bias_up=Augmenter les vitesses de t\u00E9l\u00E9chargement en sollicitant la capacit\u00E9 d'upload des t\u00E9l\u00E9chargements non termin\u00E9s
+general.na.short=N/A
+label.copy.on.comp=Copier une fois termin\u00E9
+ConfigView.section.stats.hours=hr
+ColumnSetup.title=Configuration de colonne pour '%1'
+ConfigTransferAutoSpeed.log.button=Journal
+ConfigView.label.seeding.firstPriority.ignore=Ignorer les r\u00E8gles de premi\u00E8re priorit\u00E9 pour\u00A0\:
+TableColumn.header.torrentfileindex.info=Indice du fichier dans le torrent
+MyTorrentsView.menu.publish=&Publier...
+DHTView.operations.findValue=Valeurs trouv\u00E9es
+dlg.auth.enter.prompt=Code d'activation de Vuze\u2122 Plus
+v3.MainWindow.button.download=T\u00E9l\u00E9charger
+window.welcome.file=/changelog.txt
+MainWindow.menu.file.closetab.keybinding=Meta+W
+platform.win32.baddll.SBLSP=SPEEDBit Video Accelerator
+updater.cant.write.to.app.details=Le dossier "%1" n'est pas accessible en \u00E9criture.\n\nCela permettra d'\u00E9viter que de futures mises \u00E0 jour logicielles soient appliqu\u00E9es.\n\nMerci de <a href\="http\://wiki.vuze.com/w/Failed_Update">consulter ce wiki pour plus de d\u00E9tails</a>.
+MyTorrentsView.menu.setSpeed.slots=cr\u00E9neaux de
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
+ClientStats.title.full=Statistiques client
+Trackers.column.peers.info=Pairs retourn\u00E9s par le tracker
+splash.loadIpFilters=Chargement des filtres IP...
+MyTorrentsView.menu.peersource=Origines de clients
+dht.diagnostics.group=Diagnostics
+ManagerItem.seeding=Source
+pairing.last.error=Derni\u00E8re erreur
+ConfigView.label.autoopen.dl={ManagerItem.downloading}
+SpeedView.stats.ratio=Taux
+FilesView.click=Cliquez...
+ConfigView.section.connection.serverport.wiki=Bon choix de ports
+MagnetPlugin.decentral_disabled=<tracking d\u00E9centralis\u00E9e d\u00E9sactiv\u00E9>
+SystemTray.menu.resumetransfers=Reprendre (tous transferts)
+devices.od.idle=Veille
+IPChecker.external.analysingresponse=Analyse de la r\u00E9ponse
+upnp.ignorebaddevices.alert=Le p\u00E9riph\u00E9rique UPnP \u00E0 l'emplacement %1 a \u00E9t\u00E9 ignor\u00E9 en raison d'un nombre r\u00E9p\u00E9t\u00E9 d'\u00E9checs. Voir la configuration du plugin UPnP pour les options concernant cette action.
+DHTView.operations.ok=OK
+OpenTorrentWindow.fileTable.size=Taille
+exportTorrentWizard.process.outputfileexists.title=Le fichier existe d\u00E9j\u00E0
+azbuddy.ui.table.last_ygm=YGM
+devices.xcode.setcopyto=D\u00E9finir Copier dans un dossier...
+ConfigView.label.stop.autoreset=R\u00E9initialiser automatiquement des actions de '%1', une fois d\u00E9clench\u00E9
+v3.activity.button.readall=Marquer tout comme lu
+ConfigView.section.plugins.webui=Interface Web Swing
+TableColumn.header.category=Cat\u00E9gorie
+webui.rootres=Ressource racine (*)
+ConfigView.section.transfer.autospeed.enabledebug=Informations du journal de d\u00E9bogage
+ConfigView.label.autoopen.cd={ManagerItem.seeding}
+TableColumn.header.smoothdown=T\u00E9l\u00E9chargement mod\u00E9r\u00E9
+SpeedView.stats.con=D\u00E9tails de connexion \:
+wizard.multitracker.edit.save=Sauver
+ConfigTransferAutoSpeed.set.tolerance=tol\u00E9rance (ms)
+Alert.failed.update=L'installation du dernier composant a \u00E9chou\u00E9. Allez voir\: <A HREF\="{Alert.failed.update.url}">AzureusWiki\: Failed Update</A> [%1]
+ConfigView.label.moveremoved=D\u00E9placer les fichiers termin\u00E9s (lorsqu'ils sont retir\u00E9s)
+devices.device=P\u00E9riph\u00E9rique
+ConfigView.label.allowsameip=Permettre plus d'une connexion de la m\u00EAme IP
+azbuddy.os_offline=D\u00E9connect\u00E9
+dlg.auth.denied=Code d'activation refus\u00E9
+TableColumn.header.shareRatio=Taux de partage
+subscriptions.column.last-checked=Derni\u00E8re v\u00E9rification
+MyTorrentsView.menu.rename.displayed.enter.title=Renommez le nom d'affichage
+installPluginsWizard.mode.list=Par liste, depuis sourceforge.net
+external.browser.system=Ordinateur par d\u00E9faut
+ConfigView.section.style.status.show_nat=\u00C9tat NAT
+ConfigView.label.ratio=taux
+ConfigView.section.tracker.seedretention=Nombre max de sources retenues par torrent [0\u00A0\: illimit\u00E9]
+OpenTorrentWindow.mb.badSize.text='%1' n'est pas '%2' et ne peut pas \u00EAtre utilis\u00E9 pour seeder
+OpenTorrentWindow.addPosition=Position dans la file
+ConfigView.section.tracker.nonblockingconcmax=Nombre max de connexions simultan\u00E9es [0\u00A0\: illimit\u00E9es]
+TableColumn.header.up.info=Quantit\u00E9 actuel de donn\u00E9es envoy\u00E9 \u00E0 d'autres utilisateurs
+azbuddy.ui.menu.copypk=Copie de Cl\u00E9 Publique
+ConfigView.section.tracker.pollintervalincper=Tous les 'n' clients
+label.tracker.templates=Mod\u00E8les de tracker
+SpeedTestWizard.set.upload.bytes.per.sec=kBytes/sec
+ConfigView.section.interface.enabletray._mac=Activer les options d'ic\u00F4ne de la barre d'\u00E9tat [D\u00E9marrage de Vuze\u2122 requis]
+ConfigView.label.saveresumeinterval=Sauver les donn\u00E9es de 'reprise rapide' toutes les
+TableColumn.header.downloadspeed.info=D\u00E9bit auquel nous recevons de ce pair
+label.udp_probe=Sonde UDP
+OpenTorrentWindow.pastearea=Saisir une URL, un lien magnet ou une empreinte hash \:
+MainWindow.upgrade.downloadingfrom=T\u00E9l\u00E9chargement depuis \:
+exportTorrentWizard.torrentfile.message=S\u00E9lectionner le fichier torrent \u00E0 exporter
+pairing.server.warning.title=Message du serveur de jumelage
+TableColumn.header.swarm_average_speed=Vit. moy. essaim
+PeersView.ip.info=IP du client
+DevicesOD.column.od_completion=Progression du Transfert
+OpenTorrentWindow.mb.alreadyExists.title=Le torrent existe d\u00E9j\u00E0
+azbuddy.enable_cat_pub=Cat\u00E9gories publiques auxquelles TOUS vos amis peuvent s'abonner (s\u00E9par\u00E9 par des ',')
+MyTorrents.column.ColumnProgressETA.compon=Termin\u00E9 le %1
+importTorrentWizard.process.inputfilebad.title=Fichier d'import invalide
+MainWindow.dialog.restartconfirmation.text=Voulez-vous vraiment red\u00E9marrer Vuze\u2122 ?
+TableColumn.header.torrentspeed=D\u00E9bit
+PluginDeprecation.view=D\u00E9bogage des plugins
+v3.button.removeActivityEntry=Supprimer l'entr\u00E9e d'activit\u00E9
+DHTTransport.report.rerequest_all=re-demande du transfert totale de %1
+platform.win32.baddll.niphk=Norman Antivirus
+MyTorrentsView.menu.forceStart=Forcer le d\u00E9&marrage
+label.no.connections=Aucune connexion
+MainWindow.menu.speed_limits.info.curr=R\u00E9glages actuels
+devices.turnon.title=Activer l'assistance pour les p\u00E9riph\u00E9riques
+MainWindow.about.internet.sourceforge=Page Sourceforge
+TableColumn.header.secondsseeding=En source depuis
+v3.mb.delPublished.title=Arr\u00EAter le seeding de contenu
+configureWizard.transfer2.rate.unchanged=Les r\u00E9glages actuels seront utilis\u00E9s
+ConfigView.pluginlist.column.type.builtIn=Embarqu\u00E9
+sharing.progress.title=\u00C9tat du partage
+SpeedTestWizard.name.conf.level.high=\u00C9lev\u00E9
+label.outgoing=Sortant
+PluginDeprecation.log.details=---------\nIDENTIFIER\: %1\nCONTEXT\: %2\n\n*** BEGIN TRACE ***\n%3*** END TRACE ***\n\n
+platform.win32.baddll.mclsp=McAfee Privacy Service
+TableColumn.header.fileext.info=Type de fichier/extension du fichier principal du t\u00E9l\u00E9chargement
+TableColumn.header.CountryFlagSmall=Drapeau
+ConfigView.section.security.resetkey.error=\u00C9chec de la r\u00E9initialisation des cl\u00E9s
+v3.deviceview.infobar.line2.android=Activez le montage USB sur votre t\u00E9l\u00E9phone pour transf\u00E9rer correctement les vid\u00E9os.
+device.od.turnon.title=Activer l'assistance pur le t\u00E9l\u00E9chargement hors ligne
+MainWindow.menu.speed_limits.delete=Supprimer
+ConfigView.section.style.enableHeaderHeight=Hauteur des en-t\u00EAtes personnalis\u00E9e
+OpenTorrentWindow.addFiles.magnet=Ajouter un lien &magnet
+FileItem.high=\u00C9lev\u00E9e
+devices.xcode.working_dir=Zone de transcodage
+FileDownload.canceled=Un t\u00E9l\u00E9chargement de fichier torrent a \u00E9t\u00E9 annul\u00E9 avec succ\u00E8s par une action de l'utilisateur\: %1
+GeneralView.label.status.pieces=Pi\u00E8ces
+v3.MainWindow.text.log.in=Se Connecter
+upnp.trace_to_log=Sortie des informations de d\u00E9bogage complet pour la connexion
+label.tag=Cat\u00E9gorie
+# Used for peers which we can't determine.
+PeerSocket.unknown=Inconnu
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fy_NL.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fy_NL.properties
index ab5046e..4d76994 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fy_NL.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_fy_NL.properties
@@ -1144,6 +1144,8 @@ MyTorrentsView.menu.setSpeed.disable=Schakel Upload uit
 MyTorrentsView.menu.setSpeed.disabled=Uitgeschakeld
 MyTorrentsView.menu.setSpeed.in=yn
 MyTorrentsView.menu.setSpeed.slots=sloten van
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Maks yn
 GeneralView.label.maxuploadspeed.tooltip=max upload snelheid [0 : ongelimiteerd]
 MyTorrents.items.UpSpeedLimit.disabled=Gjin oerbringst
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_hu_HU.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_hu_HU.properties
index 63e3516..ccb9694 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_hu_HU.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_hu_HU.properties
@@ -1214,6 +1214,8 @@ MyTorrentsView.menu.setSpeed.disable=Felt\u00f6lt\u00e9s Kikapcsol\u00e1sa
 MyTorrentsView.menu.setSpeed.disabled=Letiltva
 MyTorrentsView.menu.setSpeed.in=-ben
 MyTorrentsView.menu.setSpeed.slots=sz\u00e1lak
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Max Fel
 GeneralView.label.maxuploadspeed.tooltip=maxim\u00e1lis felt\u00f6lt\u00e9si sebess\u00e9g [0 : korl\u00e1tlan]
 MyTorrents.items.UpSpeedLimit.disabled=Nincs felt\u00f6lt\u00e9s
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_in_ID.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_in_ID.properties
index d507eb9..d049eea 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_in_ID.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_in_ID.properties
@@ -565,6 +565,8 @@ MyTorrentsView.menu.setSpeed.disable=Matikan Unjuk
 MyTorrentsView.menu.setSpeed.disabled=Dimatikan
 MyTorrentsView.menu.setSpeed.in=dalam
 MyTorrentsView.menu.setSpeed.slots=slot dari
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Batas Unjuk
 GeneralView.label.maxuploadspeed.tooltip=kecepatan maksimal unjuk [0 : tidak terbatas]
 MyTorrents.items.UpSpeedLimit.disabled=Tidak mengunjuk
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_it_IT.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_it_IT.properties
index 68eb09f..4978e31 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_it_IT.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_it_IT.properties
@@ -1208,6 +1208,8 @@ MyTorrentsView.menu.setSpeed.unlimited=Illimitato
 MyTorrentsView.menu.setSpeed.disable=Disabilita l'upload
 MyTorrentsView.menu.setSpeed.disabled=Disabilita
 MyTorrentsView.menu.setSpeed.slots=slot di
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Limite di upload
 GeneralView.label.maxuploadspeed.tooltip=Velocit\u00e0 massima di upload [0: illimitata]
 MyTorrents.items.UpSpeedLimit.disabled=Nessun upload
@@ -2566,14 +2568,7 @@ ConfigView.label.systray=Vassoio di sistema
 ConfigView.label.systray._mac=Icona della barra di stato
 ConfigView.section.interface.legacy=Vecchio stile
 v3.MainWindow.menu.contentnetworks.manage=&Gestisci le reti HD
-azbuddy.ui.table.loc_cat=
-azbuddy.ui.menu.cat=Categorie
-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
 subs.prop.update_period=Periodo di aggiornamento
-azbuddy.enable_cat_pub=Categorie pubbliche a cui TUTTI gli amici possono iscriversi (separate da \u00ab,\u00bb)
 TableColumn.header.#=N\u00b0
 TableColumn.header.#.info=Posizione/Numero d'ordine
 TableColumn.header.category.info=Nome della categoria a cui il torrent appartiene
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ja_JP.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ja_JP.properties
index c7ef09c..14b7038 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ja_JP.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ja_JP.properties
@@ -1209,6 +1209,8 @@ MyTorrentsView.menu.setSpeed.disable=\u30a2\u30c3\u30d7\u7981\u6b62
 MyTorrentsView.menu.setSpeed.disabled=\u30a2\u30c3\u30d7\u7981\u6b62
 MyTorrentsView.menu.setSpeed.in=- 
 MyTorrentsView.menu.setSpeed.slots=\u500b\u306f\u305d\u308c\u305e\u308c
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6
 GeneralView.label.maxuploadspeed.tooltip=\u6700\u5927\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u901f\u5ea6 [0: \u7121\u5236\u9650]
 MyTorrents.items.UpSpeedLimit.disabled=\u306a\u3057
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ka_GE.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ka_GE.properties
index f288a86..5da4f47 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ka_GE.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ka_GE.properties
@@ -1020,6 +1020,8 @@ MyTorrentsView.menu.setSpeed.disable=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\
 MyTorrentsView.menu.setSpeed.disabled=\u10d2\u10d0\u10db\u10dd\u10e0\u10d7\u10e3\u10da\u10d8\u10d0
 MyTorrentsView.menu.setSpeed.in=\u10e9\u10d4\u10db\u10dd\u10db\u10d0\u10d5\u10d0\u10da\u10d8
 MyTorrentsView.menu.setSpeed.slots=\u10e1\u10da\u10dd\u10e2\u10d4\u10d1\u10d8
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=\u10db\u10d0\u10e5\u10e1. \u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d0
 GeneralView.label.maxuploadspeed.tooltip=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10db\u10d0\u10e5\u10e1\u10d8\u10db\u10d0\u10da\u10e3\u10e0\u10d8 \u10e1\u10d8\u10e9\u10e5\u10d0\u10e0\u10d4 [0: \u10d2\u10d0\u10dc\u10e3\u10e1\u10d0\u10d6\u10e6\u10d5\u10e0\u10d4\u10da\u10d8]
 MyTorrents.items.UpSpeedLimit.disabled=\u10d0\u10e2\u10d5\u10d8\u10e0\u10d7\u10d5\u10d8\u10e1 \u10d0\u10d9\u10e0\u10eb\u10d0\u10da\u10d5\u10d0
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ko_KR.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ko_KR.properties
index 82c37e4..5db3c81 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ko_KR.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ko_KR.properties
@@ -1241,6 +1241,8 @@ MyTorrentsView.menu.setSpeed.disable=\uc5c5\ub85c\ub4dc \ube44\ud65c\uc131
 MyTorrentsView.menu.setSpeed.disabled=\ube44\ud65c\uc131\ub428
 MyTorrentsView.menu.setSpeed.in=\ub2e4\uc74c\uc5d0\uc11c
 MyTorrentsView.menu.setSpeed.slots=\uc2ac\ub86f, \ub2e4\uc74c\ub9c8\ub2e4
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=\uc5c5 \uc81c\ud55c
 GeneralView.label.maxuploadspeed.tooltip=\ucd5c\ub300 \uc5c5\ub85c\ub4dc \uc18d\ub3c4 [0: \ubb34\uc81c\ud55c]
 MyTorrents.items.UpSpeedLimit.disabled=\uc5c5\ub85c\ub4dc \uc5c6\uc74c
@@ -2611,16 +2613,7 @@ ConfigView.label.systray=\uc2dc\uc2a4\ud15c \ud2b8\ub798\uc774
 ConfigView.label.systray._mac=\uc0c1\ud0dc \ub9c9\ub300 \uc544\uc774\ucf58
 ConfigView.section.interface.legacy=\ub9ac\uac70\uc2dc
 v3.MainWindow.menu.contentnetworks.manage=HD \ub124\ud2b8\uc6cc\ud06c \uad00\ub9ac(&M)
-azbuddy.ui.table.loc_cat=Cats \uc544\uc6c3
-azbuddy.ui.table.rem_cat=Cats \uc778
-azbuddy.ui.menu.cat=\ubd84\ub958
-azbuddy.ui.menu.cat.share=\uce5c\uad6c\uc640 \ud568\uaed8 \uad6c\ub3c5 \ud65c\uc131\ud654
-azbuddy.ui.menu.cat.set=\ubd84\ub958 \uc785\ub825
-azbuddy.ui.menu.cat.set_msg=\ucf64\ub9c8\ub85c \ubd84\ub958 \ubaa9\ub85d\uc744 \ubd84\ub9ac\ud558\uc9c0 \uc54a\uc73c\uba74 '\ubaa8\ub450'
-azbuddy.ui.menu.cat_subs=\uad6c\ub3c5
 subs.prop.update_period=\uc5c5\ub370\uc774\ud2b8 \uac04\uaca9
-azbuddy.enable_cat_pub=*\ubaa8\ub4e0* \uce5c\uad6c\uac00 \uad6c\ub3c5\ud560 \uc218 \uc788\ub294 \uacf5\uac1c \ubd84\ub958 (','\ub85c \uad6c\ubd84)
-azbuddy.ui.table.read_cat=Cat \uc77d\uae30
 TableColumn.header.#=\uc21c\uc11c
 TableColumn.header.#.info=\uc6b0\uc120\uc21c\uc704/\uc704\uce58/\uc815\ub82c \ubc88\ud638\uc785\ub2c8\ub2e4.
 TableColumn.header.category.info=\ud1a0\ub80c\ud2b8\uac00 \uc18d\ud574\uc788\ub294 \ubd84\ub958\uc758 \uc774\ub984\uc785\ub2c8\ub2e4.
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_li_NL.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_li_NL.properties
index 7c24cac..45d9630 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_li_NL.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_li_NL.properties
@@ -1202,6 +1202,8 @@ MyTorrentsView.menu.setSpeed.unlimited=Ongelimiteerd
 MyTorrentsView.menu.setSpeed.disable=Upload oetsjakele
 MyTorrentsView.menu.setSpeed.disabled=Oetgesjakeld
 MyTorrentsView.menu.setSpeed.slots=sjlaote van
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Max. Up
 GeneralView.label.maxuploadspeed.tooltip=Maximum uploadsjnelheid [0 : ongelimiteerd]
 MyTorrents.items.UpSpeedLimit.disabled=G\u00e8nnen upload
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_lt_LT.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_lt_LT.properties
index d100b88..bdcf15e 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_lt_LT.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_lt_LT.properties
@@ -1233,6 +1233,8 @@ MyTorrentsView.menu.setSpeed.disable=I\u0161jungti i\u0161siuntim\u0105
 MyTorrentsView.menu.setSpeed.disabled=I\u0161jungta
 MyTorrentsView.menu.setSpeed.in=-
 MyTorrentsView.menu.setSpeed.slots=lizdai po
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Did\u017e. i\u0161s.
 GeneralView.label.maxuploadspeed.tooltip=Did\u017eiausias i\u0161siuntimo greitis [0: neribojama]
 MyTorrents.items.UpSpeedLimit.disabled=Nei\u0161siuntin\u0117ti
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_nl_NL.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_nl_NL.properties
index e376713..75e4ba7 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_nl_NL.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_nl_NL.properties
@@ -1203,6 +1203,8 @@ MyTorrentsView.menu.setSpeed.unlimited=Ongelimiteerd
 MyTorrentsView.menu.setSpeed.disable=Schakel Upload uit
 MyTorrentsView.menu.setSpeed.disabled=Uitgeschakeld
 MyTorrentsView.menu.setSpeed.slots=sloten van
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Max. Up
 GeneralView.label.maxuploadspeed.tooltip=Max Upload Snelheid [0 : ongelimiteerd]
 MyTorrents.items.UpSpeedLimit.disabled=Geen upload
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_no_NO.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_no_NO.properties
index d5d3257..dd46af7 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_no_NO.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_no_NO.properties
@@ -1197,6 +1197,8 @@ MyTorrentsView.menu.setSpeed.disable=Deaktiver opplasting
 MyTorrentsView.menu.setSpeed.disabled=Deaktivert
 MyTorrentsView.menu.setSpeed.in=inn
 MyTorrentsView.menu.setSpeed.slots='slots' av
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Opp-grense
 GeneralView.label.maxuploadspeed.tooltip=Maks opplastingshastighet [0: ubegrenset]
 MyTorrents.items.UpSpeedLimit.disabled=Ingen opplasting
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_oc.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_oc.properties
index 50b2300..26287c6 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_oc.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_oc.properties
@@ -653,7 +653,6 @@ ConfigView.label.autoopen=Dobrir automaticament
 ConfigView.label.autoopen.detailstab=Dobrir automaticament l'onglet de detalhs quand
 ConfigView.label.autoopen.dl={ManagerItem.downloading} 
 ConfigView.label.autoopen.cd={ManagerItem.seeding} 
-azbuddy.ui.menu.cat=Categorias
 Peers.column.%=% 
 TableColumn.header.TableColumnSample=M\u00f2stra
 ColumnSetup.chosencolumns=Colomnas causidas
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pl_PL.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pl_PL.properties
index e6ce99c..e4002ab 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pl_PL.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pl_PL.properties
@@ -1207,6 +1207,8 @@ MyTorrentsView.menu.setSpeed.disable=Wy\u0142\u0105cz wysy\u0142anie
 MyTorrentsView.menu.setSpeed.disabled=Wy\u0142\u0105czone
 MyTorrentsView.menu.setSpeed.in=w
 MyTorrentsView.menu.setSpeed.slots=gniazdach, po
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Limit wysy\u0142ania
 GeneralView.label.maxuploadspeed.tooltip=maksymalna pr\u0119dko\u015b\u0107 wysy\u0142ania [0: nieograniczona]
 MyTorrents.items.UpSpeedLimit.disabled=Nie wysy\u0142aj
@@ -2555,10 +2557,6 @@ ConfigView.label.systray=Pasek systemowy
 ConfigView.label.systray._mac=Ikona paska statusu
 ConfigView.section.interface.legacy=Zapis
 v3.MainWindow.menu.contentnetworks.manage=&Zarz\u0105dzaj sieciami HD
-azbuddy.ui.menu.cat=Kategorie
-azbuddy.ui.menu.cat.share=W\u0142\u0105cz subskrypcje ze znajomym(i)
-azbuddy.ui.menu.cat.set_msg=Lista kategorii oddzielona przecinkami lub 'Wszyscy'
-azbuddy.ui.menu.cat_subs=Subskrybuj
 subs.prop.update_period=Cykl aktualizacji
 TableColumn.header.#.info=Pozycja/numer porz\u0105dkowy
 TableColumn.header.category.info=Nazwa kategorii, do kt\u00f3rej nale\u017cy torrent
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pt_BR.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pt_BR.properties
index 931a35e..e79f8fe 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pt_BR.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pt_BR.properties
@@ -1,3581 +1,4250 @@
-#There is a plugin to help with internationalizing these bundles at http://plugins.vuze.com/plugin_list.php
-MainWindow.menu.file.open.torrent=Arquivo Torrent...
-Main.parameter.usage=Uso : java org.gudy.azureus2.cl.Main [par\u00e2metros] "arquivo.torrent" "caminho para salvar"
-Main.parameter.maxUploads=N\u00ba m\u00e1ximo de uploads simult\u00e2neos
-Main.parameter.maxSpeed=Velocidade m\u00e1xima de upload em bytes/seg
-MainWindow.menu.file=&Arquivo
-MainWindow.menu.file.open=&Abrir
-MainWindow.menu.file.create=&Novo Torrent...
-MainWindow.menu.file.create.fromfile=De um &Arquivo
-MainWindow.menu.file.create.fromdir=De um &Diret\u00f3rio
-MainWindow.menu.file.export=&Exportar Torrent XML...
-MainWindow.menu.file.import=&Importar Torrent XML...
-MainWindow.menu.file.closetab=Fechar &Aba
-MainWindow.menu.file.closewindow=Fechar &Janela
-MainWindow.menu.file.exit=Sai&r
-MainWindow.dialog.choose.file=Escolha o arquivo torrent
-MainWindow.menu.file.folder=&Pasta...
-MainWindow.dialog.choose.folder=Escolha o diret\u00f3rio contendo os arquivos torrent
-MainWindow.menu.view=&Visualizar
-MainWindow.menu.view.show=Mostrar
-MainWindow.menu.view.mytorrents=&Meus Torrents
-MainWindow.menu.view.open_global_transfer_bar=Barra de Transfer\u00eancias
-MainWindow.menu.view.configuration=&Op\u00e7\u00f5es...
-MainWindow.menu.view.console=C&onsole 
-MainWindow.menu.view.allpeers=Todos os Peers
-MainWindow.menu.view.detailedlist=&Lista Detalhada
-MainWindow.menu.closealldetails=Fechar &Todos os Detalhes
-MainWindow.menu.closealldownloadbars=Fechar Todas as &Barras de Download
-MainWindow.menu.language=&Idioma
-ConfigView.section.language=Idioma
-MainWindow.menu.window=&Janela
-MainWindow.menu.window.minimize=&Minimizar
-MainWindow.menu.window.alltofront=Trazer Todos para a &Frente
-MainWindow.menu.help=&Ajuda
-MainWindow.menu.help.about=Sobre o Vuze
-MainWindow.about.title=Sobre
-MainWindow.about.section.system=Sistema
-MainWindow.about.section.internet=Internet 
-MainWindow.about.internet.homepage=Home page do Vuze
-MainWindow.about.internet.sourceforge=P\u00e1gina do Projeto no Sourceforge
-MainWindow.about.internet.bugreports=Relatar Bugs
-MainWindow.about.internet.forumdiscussion=F\u00f3runs
-MainWindow.about.internet.wiki=FAQ e Wiki do Vuze
-MainWindow.dialog.choose.savepath=Escolha o caminho para salvar
-MainWindow.dialog.choose.savepath_forallfiles=Escolha o caminho para salvar TODOS os arquivos
-MainWindow.status.latestversion=Mais Recentes
-MainWindow.status.latestversion.clickupdate=Clique para atualizar
-MainWindow.status.unknown=desconhecido
-MainWindow.status.checking=verificando
-MyTorrentsView.mytorrents=Meus Torrents 
-TableColumn.header.name=Nome
-TableColumn.header.size=Tamanho
-TableColumn.header.done=Feito
-TableColumn.header.done.info=Porcentagem feita da tarefa atual
-TableColumn.header.status.info=O que o torrent est\u00e1 fazendo
-TableColumn.header.seeds.info=# seeds conectados para (# seeds no total)
-TableColumn.header.peers.info=# peers conectados a (# peers no total)
-TableColumn.header.completed=Completados
-TableColumn.header.completed.info=# dos peers que terminaram de baixar o torrent como reportado pelo tracker
-TableColumn.header.downspeed=Velocidade de Down
-TableColumn.header.upspeed=Velocidade de Up
-TableColumn.header.eta=TEC
-TableColumn.header.tracker=Status do Tracker
-TableColumn.header.tracker.info=Status do tracker
-TableColumn.header.trackernextaccess=Pr\u00f3ximo Acesso do Tracker
-TableColumn.header.trackernextaccess.info=Quando o pr\u00f3ximo acesso do tracker ocorrer\u00e1
-TableColumn.header.priority=Prioridade
-TableColumn.header.priority.info=Determina quanta banda de upload \u00e9 dada ao torrent
-TableColumn.header.seeds.fullcopycalc=%2 c\u00f3pias completas assumidas para %1 peers
-MyTorrentsView.menu.showdetails=Mostrar &Detalhes
-MyTorrentsView.menu.showdownloadbar=Mostrar a Barra de &Download 
-MyTorrentsView.menu.open=&Abrir Arquivo
-MyTorrentsView.menu.setpriority=Definir &Prioridade
-MyTorrentsView.menu.setpriority.high=&Alta
-MyTorrentsView.menu.setpriority.low=&Baixa
-MyTorrentsView.menu.start=&Iniciar
-MyTorrentsView.menu.stop=Par&ar
-MyTorrentsView.menu.remove=&Remover
-MyTorrentsView.menu.changeTracker=&Adicionar a URL do Tracker 
-TrayWindow.menu.exit=S&air
-TrayWindow.menu.show=&Mostrar o Vuze
-SystemTray.menu.exit=S&air
-SystemTray.menu.closealldownloadbars=Fechar &Todas as Barras de Download
-SystemTray.menu.open_global_transfer_bar=Mostrar a Barra de Transfer\u00eancias
-SystemTray.menu.show=&Mostrar o Vuze
-PeersView.ip.info=IP do peer
-PeersView.port=Porta
-PeersView.port.info=Porta sendo usada
-PeersView.T.info=L (local): voc\u00ea estabeleceu a conex\u00e3o, R (remota): o peer estabeleceu a conex\u00e3o.
-PeersView.T.L.tooltip=Voc\u00ea estabeleceu a conex\u00e3o
-PeersView.T.R.tooltip=O peer estabeleceu a conex\u00e3o
-PeersView.I1=I (Interessado pelo peer)
-PeersView.I1.info=Voc\u00ea est\u00e1 interessado no que o outro peer tem?
-PeersView.C1=O (Obstru\u00eddo pelo peer)
-PeersView.C1.info=Ou o peer est\u00e1 impedindo voc\u00ea de baixar
-PeersView.pieces=Peda\u00e7os
-PeersView.%=% 
-PeersView.downloadspeed=Velocidade de Download
-PeersView.download=Download
-PeersView.download.info=Total baixando deste peer.
-PeersView.I2=I (Interessante para o peer)
-PeersView.I2.info=O peer est\u00e1 interessado no que voc\u00ea tem?
-PeersView.C2=O (Obstruindo o peer)
-PeersView.C2.info=Se voc\u00ea est\u00e1 impedindo o peer de baixar
-PeersView.uploadspeed=Velocidade de Upload
-PeersView.uploadspeed.info=A sua velocidade de upload para o peer
-PeersView.upload=Upload
-PeersView.upload.info=Seu upload total para o peer.
-PeersView.statup=Estat\u00edsticas do Upload
-PeersView.statup.info=Um valor estimado da velocidade de upload do peer
-PeersView.S=D
-PeersView.S.info=Desprezado: Um peer pode ser "desprezado" manualmente ou automaticamente (por n\u00e3o entregar os dados a uma taxa alta o bastante)
-PeersView.downloadspeedoverall=Velocidade Global de Download
-PeersView.optunchoke=Desobstru\u00e7\u00e3o Otimista
-PeersView.client=Cliente
-PeersView.client.info=Tipo de cliente BT que o peer est\u00e1 usando
-PeersView.menu.snubbed=&Desprezado
-AllPeersView.title.full=Todos os Peers
-ConfigView.section.files=Arquivos
-ConfigView.label.usefastresume=Usar modo de Resumo R\u00e1pido
-ConfigView.label.incrementalfile=Ativar cria\u00e7\u00e3o incremental de arquivo [Requerido para FAT32 no Linux]
-ConfigView.label.defaultsavepath=Salvar no diret\u00f3rio de dados padr\u00e3o
-ConfigView.button.browse=&Procurar...
-ConfigView.dialog.choosedefaultsavepath=Por favor, escolha o diret\u00f3rio padr\u00e3o para salvar
-ConfigView.section.server=Conex\u00e3o
-ConfigView.section.global=Geral
-ConfigView.label.disconnetseed=Desconectar seeds quando estiver ficando de seed
-ConfigView.label.switchpriority=Auto-trocar para prioridade baixa quando estiver ficando de seed
-ConfigView.label.maxdownloads=M\u00e1ximo de downloads simult\u00e2neos [0: ilimitados]\n - N\u00e3o pode ser maior do que o n\u00famero m\u00e1x. de torrents ativos
-ConfigView.label.maxdownloads.tooltip=Voc\u00ea sempre ser\u00e1 capaz de baixar ativamente o n\u00famero que voc\u00ea p\u00f4r aqui, com uma exce\u00e7\u00e3o.\nUma combina\u00e7\u00e3o de Primeira Prioridade do torrent completado pode tomar o controle de um slot de download ativo se absolutamente necess\u00e1rio.
-ConfigView.label.maxactivetorrents=M\u00e1ximo de torrents ativos [0: ilimitados]\n - Novos torrents n\u00e3o come\u00e7ar\u00e3o se voc\u00ea estiver baixando/ou ficando mais de seed
-ConfigView.label.priorityExtensions=Auto-priorizar os arquivos com - ex: .txt;.nfo;.jpg
-ConfigView.section.transfer=Transfer\u00eancias
-ConfigView.label.maxuploads=M\u00e1ximo de slots de upload padr\u00e3o por torrent
-ConfigView.label.maxuploadspeed=Velocidade m\u00e1xima global de upload em KB/s [0: ilimitada]
-ConfigView.label.saveresumeinterval=Atualizar os dados de resumo a cada
-ConfigView.unlimited=Ilimitado
-ConfigView.section.display=Exibir
-ConfigView.label.opendetails=Auto-abrir a aba de detalhes
-ConfigView.label.openbar=Auto-abrir a barra de download
-ConfigView.label.use_old_speed_menus=Usar menus de velocidade do estilo antigo [requer reiniciar]
-ConfigView.label.closetotray=Fechar minimiza para o Tray do Sistema
-ConfigView.label.minimizetotray=Minimizar minimiza para o Tray do Sistema
-ConfigView.section.general=Geral
-ConfigView.section.start=Iniciar
-ConfigView.label.showsplash=Mostrar a tela de abertura
-ConfigView.label.autoupdate=Abrir o di\u00e1logo de atualiza\u00e7\u00e3o quando uma vers\u00e3o mais nova estiver dispon\u00edvel
-ConfigView.label.openconsole=Abrir o console na inicializa\u00e7\u00e3o
-ConfigView.label.openconfig=Abrir as op\u00e7\u00f5es na inicializa\u00e7\u00e3o
-ConfigView.label.startminimized=Iniciar minimizado 
-ConfigView.section.irc=IRC 
-ConfigView.label.ircwiki=Por favor leia http://azureuswiki.com/index.php/Rules_para o_IRC
-ConfigView.label.ircserver=Servidor
-ConfigView.label.ircchannel=Canal
-ConfigView.label.irclogin=Apelido
-ConfigView.group.irctitle=Configura\u00e7\u00f5es do IRC 
-ConfigView.boolean.ircsendinfo=Permite enviar as suas configura\u00e7\u00f5es (an\u00f4nimo) para\n os operadores do canal para ajud\u00e1-los a ajudar voc\u00ea
-ConfigView.boolean.irclog=Ativar registro da atividade no canal (em IRC_log.htm)
-ConfigView.section.security=Seguran\u00e7a
-ConfigView.label.password=Proteger o Vuze usando uma senha\n- Ser\u00e1 perguntado(a) quando des-iconificar e quando iniciado.
-ConfigView.label.passwordconfirm=Senha (confirmar)
-ConfigView.label.passwordmatch=Senha ativada :
-ConfigView.label.passwordmatchnone=N\u00e3o
-ConfigView.label.passwordmatchno=N\u00e3o / As senhas n\u00e3o combinam
-ConfigView.label.passwordmatchyes=Sim
-ConfigView.button.save=Salvar
-ConfigView.title.short=Op\u00e7\u00f5es
-ConfigView.title.full=Op\u00e7\u00f5es
-ConfigView.title.full._mac=Prefer\u00eancias
-ConsoleView.title.short=Console 
-ConsoleView.title.full=Console 
-FileItem.write=escrita
-FileItem.read=leitura
-FileItem.normal=Normal 
-FileItem.high=alta
-FileItem.donotdownload=N\u00e3o baixar
-FileItem.delete=Apagar
-FilesView.name=Nome
-FilesView.name.fastRename=Renomeamento R\u00e1pido
-FilesView.size=Tamanho
-FilesView.done=Conclu\u00eddo
-FilesView.%=% 
-FilesView.firstpiece=Primeiro peda\u00e7o # 
-FilesView.numberofpieces=# de peda\u00e7os
-FilesView.pieces=Peda\u00e7os
-FilesView.mode=Modo
-FilesView.priority=Prioridade
-FilesView.menu.open=&Abrir
-FilesView.menu.setpriority=&Definir Prioridade 
-FilesView.menu.setpriority.high=&Alta
-FilesView.menu.setpriority.normal=&Normal 
-FilesView.menu.setpriority.skipped=&N\u00e3o baixar
-FilesView.title.short=Arquivos
-FilesView.title.full=Arquivos
-GeneralView.section.downloaded=Baixados
-GeneralView.label.status.file=Status do Arquivo
-GeneralView.label.status.pieces=Status dos Peda\u00e7os
-GeneralView.section.availability=Disponibilidade
-GeneralView.label.status.pieces_available=Status dos Peda\u00e7os
-GeneralView.section.transfer=Transfer\u00eancias
-GeneralView.section.info=Informa\u00e7\u00f5es
-GeneralView.title.short=Geral 
-GeneralView.title.full=Geral 
-GeneralView.label.timeelapsed=Tempo Decorrido : 
-GeneralView.label.remaining=Tempo Restante : 
-GeneralView.label.downloaded=Baixados : 
-GeneralView.label.downloadspeed=Velocidade de Download : 
-GeneralView.label.maxuploads=Slots de Upload :
-GeneralView.label.maxuploads.tooltip=N\u00famero m\u00e1ximo de peers que ser\u00e3o desobstru\u00eddos a qualquer tempo dado.
-GeneralView.label.uploaded=Enviados :
-GeneralView.label.uploadspeed=Velocidade de Upload :
-GeneralView.label.seeds=Seeds:
-GeneralView.label.peers=Peers:
-GeneralView.label.completed=Completado : 
-GeneralView.label.totalspeed=Velocidade Total :
-GeneralView.label.totalspeed.tooltip=Velocidade total (e m\u00e9dia) de todos os clientes aos quais voc\u00ea est\u00e1 conectado.
-GeneralView.label.averagespeed=m\u00e9dia
-GeneralView.label.filename=Nome:
-GeneralView.label.totalsize=Tamanho Total :
-GeneralView.label.savein=Salvar em :
-GeneralView.label.hash=Hash :
-GeneralView.label.numberofpieces=# de Peda\u00e7os : 
-GeneralView.label.size=Tamanho : 
-GeneralView.label.tracker=Status do Tracker : 
-GeneralView.label.updatein=Atualizar em :
-GeneralView.label.trackerurl=URL do tracker : 
-GeneralView.label.trackerurlupdate=Atualizar Tracker
-GeneralView.label.comment=Coment\u00e1rio sobre o Torrent : 
-GeneralView.label.user_comment=Coment\u00e1rio do Usu\u00e1rio : 
-ManagerItem.waiting=Esperando
-ManagerItem.allocating=Alocando
-ManagerItem.checking=Verificando
-ManagerItem.ready=Esperando por outro(s) torrent(s) para requisitar
-ManagerItem.downloading=Baixando
-ManagerItem.seeding=Ficando de seed
-ManagerItem.stopped=Parado
-ManagerItem.error=Erro
-ManagerItem.high=alta
-ManagerItem.low=baixa
-MinimizedWindow.name=Nome: 
-MinimizedWindow.all_transfers=Transfer\u00eancias do Vuze
-PiecesView.#=# 
-PiecesView.size=Tamanho
-PiecesView.numberofblocks=# de Blocos 
-PiecesView.blocks=Blocos
-PiecesView.completed=Completos
-PiecesView.availability=Disponibilidade
-PiecesView.reservedby=Reservado
-PiecesView.writers=Bloquear Contribuidores
-PiecesView.title.short=Peda\u00e7os
-PiecesView.title.full=Peda\u00e7os
-SystemTray.tooltip.seeding=%1 ficando de seed, 
-SystemTray.tooltip.downloading=%1 baixando, 
-DownloadManager.error.filenotfound=Arquivo N\u00e3o Encontrado 
-DownloadManager.error.fileempty=Arquivo torrent est\u00e1 vazio
-DownloadManager.error.filetoobig=Arquivo Torrent \u00e9 muito grande
-DownloadManager.error.filewithouttorrentinfo=Nenhuma informa\u00e7\u00e3o de Torrent encontrada no arquivo
-DownloadManager.error.unsupportedencoding=Codifica\u00e7\u00e3o N\u00e3o Suportada
-DownloadManager.error.ioerror=Erro de Entrada/Sa\u00edda de Dados
-DownloadManager.error.sha1=Erro: Algor\u00edtmo n\u00e3o encontrado (SHA1)
-PeerManager.status.offline=Erro de Conex\u00e3o 
-PeerManager.status.checking=Verificando
-PeerManager.status.finished=Terminado
-PeerManager.status.finishedin=Terminado em 
-MainWindow.upgrade.assistant=Assistente de Atualiza\u00e7\u00e3o
-MainWindow.upgrade.newerversion=Existe uma vers\u00e3o mais nova do Vuze dispon\u00edvel para download 
-MainWindow.upgrade.explanation=Este assistente baixar\u00e1 a nova vers\u00e3o na sua pasta do Vuze e reiniciar\u00e1 o Vuze
-MainWindow.upgrade.explanation.manual=Voc\u00ea pode atualizar manualmente fechando o Vuze, baixando a nova vers\u00e3o e reiniciando o Vuze
-MainWindow.upgrade.step1=Passo 1: Baixar a nova vers\u00e3o 
-MainWindow.upgrade.step2=Passo 2: Fechar esta vers\u00e3o e reiniciar a nova vers\u00e3o do Vuze
-MainWindow.upgrade.hint1=Dica:\tPressionando Terminar faz tudo automaticamente
-MainWindow.upgrade.hint2=Dica:\tSe voc\u00ea deseja fechar o Vuze mais tarde, pressione Cancelar e\n\trenomeie Azureus2-new.jar para Azureus2.jar ap\u00f3s fechar
-MainWindow.upgrade.error.downloading.hint=Erro:\tIncapaz de baixar a nova vers\u00e3o, por favor atualize manualmente
-MainWindow.upgrade.section.info=Nova Vers\u00e3o Dispon\u00edvel 
-MainWindow.upgrade.section.manual=Atualiza\u00e7\u00e3o Manual
-MainWindow.upgrade.section.automatic=Atualiza\u00e7\u00e3o Autom\u00e1tica 
-MainWindow.upgrade.tooltip.progressbar=O progresso do download \u00e9 mostrado aqui
-Button.next=Pr\u00f3ximo
-Button.finish=Terminar
-Button.cancel=&Cancelar
-LocaleUtil.title=Escolher Codifica\u00e7\u00e3o
-LocaleUtil.section.chooseencoding=Escolher codifica\u00e7\u00e3o para o nome do arquivo
-LocaleUtil.label.chooseencoding=Por favor selecione a codifica\u00e7\u00e3o mais apropriada
-LocaleUtil.label.hint.doubleclick=Dica: um duplo clique em uma linha escolhe a codifica\u00e7\u00e3o e fecha a janela 
-LocaleUtil.label.checkbox.rememberdecision=Lembrar a decis\u00e3o para os nomes de arquivos restantes
-LocaleUtil.column.encoding=Codifica\u00e7\u00e3o
-IrcClient.defaultChannel=#Usu\u00e1rios-do-Azureus
-IrcClient.copyright=Usando o PircBot Java IRC API - http://www.jibble.org/pircbot.php
-IrcClient.connecting=Conectando a 
-IrcClient.connected=Conectado a 
-IrcClient.joining=Entrando
-IrcClient.channel=Canal 
-IrcClient.joined=entrou
-IrcClient.error=Erro
-IrcClient.hasjoined=entrou
-IrcClient.haskicked=foi chutado
-IrcClient.hasleft=saiu
-IrcClient.nowknown=\u00e9 agora conhecido como 
-IrcClient.topicforchannel=T\u00f3pico do canal
-IrcClient.disconnected=Desconectado de
-IrcClient.noNick=Nenhum Apelido Especificado. Por favor v\u00e1 para Visualiza\u00e7\u00e3o 'Op\u00e7\u00f5es'
-IrcView.actionnotsupported=Esta a\u00e7\u00e3o n\u00e3o \u00e9 suportada 
-IrcView.clientsconnected=usu\u00e1rios
-IrcView.privateto=Para
-IrcView.privatefrom=De
-IrcView.noticefrom=Notifica\u00e7\u00e3o : 
-IrcView.errormsg=Sintaxe Errada em /msg : /msg usu\u00e1rio texto
-IrcView.help=Os comandos v\u00e1lidos s\u00e3o :\n . /help : exibe esta mensagem\n . /nick | /name : muda o seu nome\n . /me a\u00e7\u00e3o : envia uma a\u00e7\u00e3o\n . /msg mensagem sobre o apelido : envia uma mensagem privada para <nick>\n . /r mensagem : responde a \u00faltima mensagem privada\n . /join #canalB (n\u00e3o clique aqui,\u00e9 uma exemplo) : muda o canal atual\tpara o canalB
-PasswordWindow.title=O Vuze est\u00e1 trancado
-PasswordWindow.passwordprotected=O Vuze est\u00e1 protegido por senha.\nPara mostrar a janela do Vuze, por favor insira a sua senha aqui :
-Button.ok=OK
-TrackerChangerWindow.title=Adicionar Tracker(s)
-TrackerChangerWindow.newtracker=Digite nova url do tracker(es) - separado por v\u00edrgula, se mais de um
-PeersView.discarded=Descartado
-PeersView.discarded.info=Dados que voc\u00ea de alguma forma recebeu embora voc\u00ea n\u00e3o precisasse deles, ent\u00e3o voc\u00ea se livrou deles.
-discarded=descartado
-MyTorrentsView.#=# 
-MyTorrentsView.menu.move=&Mover 
-MyTorrentsView.menu.moveUp=&Para Cima
-MyTorrentsView.menu.moveDown=&Para Baixo
-GeneralView.label.hashfails=Falhas no Hash :
-GeneralView.label.shareRatio=Propor\u00e7\u00e3o de Compartilhamento: 
-ConfigView.section.downloadManagement=Gerenciamento de Download 
-ConfigView.label.startRatioPeers=Come\u00e7ar a ficar de seed quando houver menos de 1 seed para
-ConfigView.text.neverStop=Nunca Parar
-ConfigView.text.neverStart=Nunca Iniciar 
-ConfigView.label.checkOncompletion=Verificar novamente os peda\u00e7os quando o download for conclu\u00eddo
-wizard.title=Criar um torrent 
-wizard.previous=< Voltar 
-wizard.next=Pr\u00f3ximo >
-wizard.finish=Terminar
-wizard.mode=Tracker / Modo 
-wizard.tracker=Tracker: 
-wizard.invalidurl=Esta URL n\u00e3o \u00e9 v\u00e1lida
-wizard.singlefile=Arquivo \u00fanico
-wizard.singlefile.help=Criar um torrent de um arquivo \u00fanico 
-wizard.directory=Diret\u00f3rio
-wizard.directory.help=Criar um torrent de um diret\u00f3rio
-wizard.choosefile=Escolha o arquivo
-wizard.file=Arquivo :
-wizard.browse=Navegar... 
-wizard.choosedirectory=Escolha uma diret\u00f3rio
-wizard.invalidfile=Arquivo Inv\u00e1lido!
-wizard.invaliddirectory=Diret\u00f3rio Inv\u00e1lido!
-wizard.torrentFile=Arquivo Torrent
-wizard.choosetorrent=Por favor escolha o arquivo torrent a criar
-wizard.information=Informa\u00e7\u00e3o
-wizard.notimplemented=Ainda n\u00e3o implementado
-wizard.progresstitle=Criando Arquivo Torrent
-wizard.savingfile=Salvando Arquivo...
-wizard.filesaved=Arquivo Salvo.
-wizard.close=Fechar
-Torrent.create.progress.piecelength=Comprimento do peda\u00e7o: 
-Torrent.create.progress.piececount=Contagem dos peda\u00e7os: 
-Torrent.create.progress.totalfilesize=Tamanho total do arquivo: 
-Torrent.create.progress.totalfilecount=Contagem total de arquivos:
-Torrent.create.progress.parsingfiles=Analizando arquivos
-Torrent.create.progress.hashing=Hasheando arquivos
-MainWindow.upgrade.downloadingfrom=Baixando de : 
-MainWindow.menu.view.ipFilter=&Filtros de IP
-ConfigView.section.ipfilter=Filtros de IP
-ConfigView.section.ipfilter.description=Descri\u00e7\u00e3o
-ConfigView.section.ipfilter.start=IP Inicial
-ConfigView.section.ipfilter.end=IP Final
-ConfigView.section.ipfilter.add=Adicionar
-ConfigView.section.ipfilter.remove=Remover
-ConfigView.section.ipfilter.edit=Editar
-ConfigView.section.ipfilter.save=Salvar
-ConfigView.section.ipfilter.editFilter=Editar Filtro
-ConfigView.section.ipfilter.enable=Ativar
-PeersView.menu.close=&Fechar 
-seedmore.title=O Torrent n\u00e3o est\u00e1 com seeds o bastante
-seedmore.shareratio=Sua propor\u00e7\u00e3o de compartilhamento neste torrent \u00e9 de
-seedmore.uploadmore=Ter uma propor\u00e7\u00e3o de compartilhamento inferior a 100% n\u00e3o \u00e9 uma boa coisa para a rede BitTorrent.\nVoc\u00ea deveria deixar este torrente ficar de seed um pouco mais.\nVoc\u00ea tem certeza que voc\u00ea quer prosseguir?
-ConfigView.label.showpopuponclose=Mostrar janela de confirma\u00e7\u00e3o quando parar de ficar de seed com uma propor\u00e7\u00e3o de compartilhamento menor que 1
-ConfigView.label.startNumSeeds=\nCome\u00e7ar a ficar de seed se houver menos de\n - N\u00e3o leva em conta todas as outras regras
-ConfigView.label.seeds=Sementes
-ConfigView.section.seeding=Ficar de seed
-#Used by the webui plugin
-MyTorrentsView.menu.removeand.deletetorrent=Apagar &Arquivo Torrent 
-#Used by the webui plugin
-MyTorrentsView.menu.removeand.deletedata=Apagar &Dados
-#Used by the webui plugin
-MyTorrentsView.menu.removeand.deleteboth=Apagar &Ambos
-deletedata.title=Aten\u00e7\u00e3o 
-# used for more than just "delete data"
-deletedata.noprompt=N\u00e3o me alertar de novo
-MainWindow.menu.file.configure=Assistente de &Configura\u00e7\u00e3o...
-configureWizard.title=Assistente de Configura\u00e7\u00e3o
-configureWizard.welcome.title=Bem-vindo ao Assistente de Configura\u00e7\u00e3o do Vuze
-configureWizard.welcome.message=Este assistente ajudar\u00e1 voc\u00ea a configurar o Vuze para o uso mais comum. Voc\u00ea pode modificar a configura\u00e7\u00e3o em profundidade usando o menu Ferramentas->Op\u00e7\u00f5es. 
-configureWizard.transfer.title=Configura\u00e7\u00f5es de Transfer\u00eancia e Conex\u00e3o
-configureWizard.transfer.hint=Dica : Usar um pouco menos do que a velocidade da sua linha \u00e9 a melhor configura\u00e7\u00e3o.
-configureWizard.transfer.message=Por favor escolha uma conex\u00e3o abaixo. Esteja ciente que n\u00e3o permitir uma velocidade de upload boa resultar\u00e1 em baixas velocidades de download. Como a velocidade de upload s\u00f3 conta POR torrent que voc\u00ea est\u00e1 baixando, tentar baixar muitos torrents ao mesmo tempo tamb\u00e9m resultar\u00e1 em baixas velocidades. N\u00f3s recomendadmos usar 5 KB/s por torrent como um m\u00ednimo ESTRITO. Quanto mais r\u00e1pido o seu upload, mais [...]
-configureWizard.transfer.connection=Linha
-configureWizard.transfer.connection.0=Personalizado
-configureWizard.transfer.connection.2=adsl/cabo xxx/128 kbps 
-configureWizard.transfer.connection.3=adsl/cabo xxx/256 kbps 
-configureWizard.transfer.connection.4=adsl/cabo xxx/384 kbps 
-configureWizard.transfer.connection.5=adsl/cabo xxx/512 kbps
-configureWizard.transfer.connection.6=adsl/cabo xxx/768 kbps
-configureWizard.transfer.connection.7=adsl/cabo xxx/1024 kbps
-configureWizard.transfer.maxUpSpeed=Velocidade M\u00e1xima de Upload (KB/s)
-configureWizard.transfer.maxActiveTorrents=M\u00e1ximo de Ativos 
-configureWizard.transfer.maxDownloads=M\u00e1ximo de Downloads 
-configureWizard.transfer.maxUploadsPerTorrent=M\u00e1ximo de Uploads por Torrent 
-configureWizard.nat.test=Teste
-configureWizard.nat.testing=Testando porta
-configureWizard.nat.ok=OK! 
-configureWizard.nat.ko=Erro do NAT
-configureWizard.nat.unable=Incapaz de testar: Porta inv\u00e1lida dada, ou o teste do servi\u00e7o falhou.\nOutro aplicativo j\u00e1 pode estar usando esta porta.
-configureWizard.file.title=Torrents / Arquivos
-configureWizard.file.message1=O Vuze salvar\u00e1 os torrents abertos em uma pasta espec\u00edfica, voc\u00ea pode escolher esta pasta aqui:
-configureWizard.file.path=Caminho
-configureWizard.file.browse=Procurar
-configureWizard.file.message2=O Vuze \u00e9 capaz de resumir seus arquivos instant\u00e2neamente, adicionando alguns dados de resumo aos seus torrents. Usando esta fun\u00e7\u00e3o, voc\u00ea ser\u00e1 tamb\u00e9m resumir\u00e1 peda\u00e7os parcialmente baixados.
-configureWizard.file.fastResume=Ativar resumo r\u00e1pido 
-configureWizard.file.invalidPath=Diret\u00f3rio inv\u00e1lido
-configureWizard.finish.title=Completado
-configureWizard.finish.message=O Vuze est\u00e1 agora configurado, divirta-se!
-wizard.close.confirmation=Confirma\u00e7\u00e3o
-wizard.close.message=Voc\u00ea quer que este assistente seja executado na pr\u00f3xima vez que o Vuze for iniciado?
-exportTorrentWizard.title=Exportar um torrent XML
-exportTorrentWizard.torrentfile.title=Sele\u00e7\u00e3o da Entrada de Dados do Torrent
-exportTorrentWizard.torrentfile.message=Selecione o arquivo torrent para exportar
-exportTorrentWizard.torrentfile.path=Caminho
-exportTorrentWizard.torrentfile.browse=Navegar
-exportTorrentWizard.torrentfile.invalidPath=Arquivo torrent inv\u00e1lido
-exportTorrentWizard.exportfile.title=Exportar Sele\u00e7\u00e3o de Arquivos
-exportTorrentWizard.exportfile.message=Insira o arquivo XML para exportar para
-exportTorrentWizard.exportfile.path=Caminho
-exportTorrentWizard.exportfile.browse=Navegar
-exportTorrentWizard.exportfile.invalidPath=Arquivo de exporta\u00e7\u00e3o inv\u00e1lido 
-exportTorrentWizard.finish.title=Conclu\u00eddo
-exportTorrentWizard.finish.message=Exporta\u00e7\u00e3o conclu\u00edda com sucesso 
-exportTorrentWizard.process.inputfilebad.title=Arquivo Torrent Inv\u00e1lido
-exportTorrentWizard.process.inputfilebad.message=Uma falha ocorreu ao acessar o arquivo de entrada de dados:
-exportTorrentWizard.process.outputfileexists.title=O Arquivo Existe
-exportTorrentWizard.process.outputfileexists.message=O arquivo de sa\u00edda de dados existe - sobrescrever? 
-exportTorrentWizard.process.torrentfail.title=Falha na Leitura do Torrent 
-exportTorrentWizard.process.exportfail.title=Falha na Exporta\u00e7\u00e3o do Torrent 
-exportTorrentWizard.process.unknownfail.title=Erro Inesperado 
-importTorrentWizard.title=Importar um torrent XML
-importTorrentWizard.torrentfile.title=Sele\u00e7\u00e3o da Entrada de Dados do Torrent
-importTorrentWizard.torrentfile.message=Insira o arquivo torrent para o qual importar
-importTorrentWizard.torrentfile.path=Caminho
-importTorrentWizard.torrentfile.browse=Navegar
-importTorrentWizard.torrentfile.invalidPath=Arquivo torrent inv\u00e1lido 
-importTorrentWizard.importfile.title=Sele\u00e7\u00e3o do Arquivo para Importa\u00e7\u00e3o
-importTorrentWizard.importfile.message=Selecione o arquivo XML para importar 
-importTorrentWizard.importfile.path=Caminho
-importTorrentWizard.importfile.browse=Navegar
-importTorrentWizard.importfile.invalidPath=Arquivo de importa\u00e7\u00e3o inv\u00e1lido 
-importTorrentWizard.finish.title=Conclu\u00eddo
-importTorrentWizard.finish.message=Importa\u00e7\u00e3o conclu\u00edda com sucesso
-importTorrentWizard.process.inputfilebad.title=Arquivo de Importa\u00e7\u00e3o Inv\u00e1lido
-importTorrentWizard.process.inputfilebad.message=Uma falha ocorreu ao acessar o arquivo de entrada de dados:
-importTorrentWizard.process.outputfileexists.title=O Arquivo Existe
-importTorrentWizard.process.outputfileexists.message=O arquivo de sa\u00edda de dados existe - sobrescrever? 
-importTorrentWizard.process.torrentfail.title=Falha na Escrita do Torrent
-importTorrentWizard.process.importfail.title=Falha na Importa\u00e7\u00e3o do Torrent 
-importTorrentWizard.process.unknownfail.title=Erro Inesperado
-ConfigView.label.bindip=Prender ao endere\u00e7o IP local
-ConfigView.label.xfs.allocation=Alocar novos arquivos usando um m\u00e9todo espec\u00edfico para o sistema de arquivos XFS
-ConfigView.label.xfs.allocation.tooltip=Por favor tenha certeza /usr/sbin/xfs_io est\u00e1 apropriadamente instalado no seu sistema. Na maioria das distribui\u00e7\u00f5es Linux, est\u00e1 inclu\u00eddo no pacote "xfsprogs".
-xfs.allocation.xfs_io.not.found=A aloca\u00e7\u00e3o do arquivo XFS falhou porque /usr/sbin/xfs_io n\u00e3o p\u00f4de ser executado. Tenha certeza de que est\u00e1 apropriadamente instalado no seu sistema. O erro original foi : "%1".
-ConfigView.label.zeronewfiles=Alocar e zerar novos arquivos na cria\u00e7\u00e3o 
-ConfigView.label.zeronewfiles.tooltip=Minimiza a fragmenta\u00e7\u00e3o
-ConfigView.section.stats=Estat\u00edsticas
-ConfigView.section.stats.enable=Ativar 
-ConfigView.section.stats.defaultsavepath=Diret\u00f3rio para salvar as estat\u00edsticas
-ConfigView.section.stats.choosedefaultsavepath=Por favor escolha o diret\u00f3rio para salvar as estat\u00edsticas
-ConfigView.section.stats.savefreq=Freq\u00fc\u00eancia de salvamento
-ConfigView.section.stats.minutes=min 
-ConfigView.section.stats.hours=h
-ConfigView.section.stats.seconds=s
-ConfigView.section.stats.savefile=Nome do arquivo de estat\u00edsticas
-ConfigView.section.stats.graph_update_dividers=Exibir linha vertical a cada 60 segundos
-MyTorrentsView.menu.export=&Torrent XML...
-MyTorrentsView.menu.host=&Servidor...
-ManagerItem.finishing=Terminando
-ConfigView.dialog.choosedefaulttorrentpath=Por favor, escolha o diret\u00f3rio padr\u00e3o dos torrents
-ConfigView.dialog.choosemovepath=Por favor, escolha o diret\u00f3rio para o qual mover
-ConfigView.label.movecompleted=Mover arquivos completados (ap\u00f3s o download)
-ConfigView.label.moveremoved=Mover arquivos completados (quando sendo removidos)
-ConfigView.label.savetorrents=Salvar arquivos .torrent
-MainWindow.menu.view.mytracker=Meu &Tracker
-MyTrackerView.title.full=Meu Tracker
-MyTrackerView.name=Nome
-MyTrackerView.status.started=Rodando
-MyTrackerView.status.stopped=Parado
-MyTrackerView.announces=An\u00fancios
-MyTrackerView.uploaded=Enviados
-MyTrackerView.downloaded=Baixados
-MyTrackerView.left=Restante
-ConfigView.section.style=Interface 
-ConfigView.label.set_ui_transfer_speeds=N\u00e3o levar em conta as velocidades de transfer\u00eancia selecion\u00e1veis
-ConfigView.label.set_ui_transfer_speeds.description=Voc\u00ea pode escolher definir manualmente as velocidades de download e upload dispon\u00edveis na barra de status no tray do sistema.\nOs valores devem estar separados por v\u00edrgula.
-ConfigView.label.set_ui_transfer_speeds.description.download=Definir as velocidades de download (em KB/s)
-ConfigView.label.set_ui_transfer_speeds.description.upload=Definir as velocidades de upload (em KB/s)
-ConfigView.section.style.useCustomTabs=Usar abas que fecham (precisa reiniciar)
-MainWindow.menu.view.plugins=&Plugins 
-fileDownloadWindow.saveTorrentIn=Salvar Arquivo Torrent Em 
-fileDownloadWindow.title=Vuze \u2013 Baixador de Torrents
-fileDownloadWindow.downloading=Baixando de :
-fileDownloadWindow.status=Status:
-fileDownloadWindow.state_initializing=Inicializando
-fileDownloadWindow.state_downloading=Baixando
-fileDownloadWindow.state_error=Erro: 
-MainWindow.menu.file.open.url=&Local...
-openUrl.title=Abrir Local
-openUrl.url=URL: 
-MyTorrentsView.menu.host.error.title=Falha na Hospedagem do Torrent 
-MyTorrentsView.menu.host.error.message=O seguinte erro ocorreu durante a hospedagem do torrent 
-ConfigView.section.tracker=Tracker 
-ConfigView.section.tracker.pollinterval=Intervalo de apura\u00e7\u00e3o dos clientes no tracker (segs)
-ConfigView.section.tracker.publishenable=Publicar detalhes do torrent para "<tracker_url>"
-ConfigView.section.tracker.ip=Endere\u00e7o IP externo do tracker
-ConfigView.section.style.enableXPStyle=Ativar estilo XP (precisa reiniciar)
-IPChecker.external.service.dyndns.name=DynDNS 
-IPChecker.external.service.dyndns.url=http://www.dyndns.org/ 
-IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC 
-ConfigView.section.tracker.checkip=Auto-descobrir endere\u00e7o IP externo...
-ipCheckerWizard.title=Assistente do Verificador de IP 
-ipCheckerWizard.service=Servi\u00e7o
-ipCheckerWizard.chooseService=Por favor escolha um servi\u00e7o de verifica\u00e7\u00e3o IP dos servi\u00e7os listados
-ipCheckerWizard.explanations=Voc\u00ea pode usar este assistente para descobrir qual \u00e9 o seu endere\u00e7o IP externo. Se o seu endere\u00e7o IP \u00e9 din\u00e2mico, n\u00f3s recomendamos que voc\u00ea abra uma conta com um Servi\u00e7o de DNS Din\u00e3mico. Alguns destes servi\u00e7os est\u00e3o listados abaixo, use o link fornecido para criar uma conta (quando suportado). Ent\u00e3o preencha o campo do endere\u00e7o IP com o nome do seu servidor din\u00e2mico (ex: nomedomeuhost.d [...]
-ipCheckerWizard.service.description=Descri\u00e7\u00e3o :
-ipCheckerWizard.service.url=Link: 
-ipCheckerWizard.progresstitle=Verificando IP 
-ipCheckerWizard.checkComplete=IP Completado: 
-ipCheckerWizard.checkFailed=Falhou, raz\u00e3o :
-wizard.tracker.local=Usar o Tracker Embutido do Vuze
-wizard.tracker.external=Usar um tracker externo
-wizard.tracker.howToLocal=\tV\u00e1 em 'Ferramentas->Op\u00e7\u00f5es->Tracker' para ativ\u00e1-lo
-wizard.announceUrl=URL de An\u00fancio :
-IPChecker.external.service.discoveryvip.name=Discoveryvip 
-IPChecker.external.service.discoveryvip.url=http://ip.discoveryvip.com/ 
-IPChecker.external.service.discoveryvip.description=Discoveryvip \u2013 Apenas verifica\u00e7\u00e3o de Endere\u00e7o IP
-IPChecker.external.httpinvalidresponse=Resposta HTTP inv\u00e1lida
-IPChecker.external.loadingwebpage=Carregando p\u00e1gina da web
-IPChecker.external.analysingresponse=Analisando resposta
-IPChecker.external.addressextracted=Endere\u00e7o IP extra\u00eddo
-IPChecker.external.httploadfail=Falha ao carregar a p\u00e1gina
-IPChecker.external.timeout=Ocorreu um esgotamento do tempo
-IPChecker.external.ipnotfound=Endere\u00e7o IP n\u00e3o encontrado
-ConfigView.section.tracker.pollintervalmin=M\u00ednimo
-ConfigView.section.tracker.pollintervalmax=M\u00e1ximo
-ConfigView.section.tracker.pollintervalincby=Aumentar em
-ConfigView.section.tracker.pollintervalincper=A cada 'n' clientes
-splash.loadingImages=Carregando Imagens
-splash.initializeGui=Inicializando a Janela Principal
-splash.openViews=Abrindo as Visualiza\u00e7\u00f5es
-splash.plugin=Carregando o Plugin:  
-configureWizard.nat.tooManyPorts=Muitas portas para testar (m\u00e1x. 9)
-ConfigView.section.color=Esquema de Cores
-MyTorrentsView.menu.publish=Pub&licar...
-MyTrackerView.status.published=Publicado
-MyTrackerView.completed=Completo
-MainWindow.menu.file.open.torrentnodefault=Arquivo Torrent... (Sem Save Padr\u00e3o)
-wizard.comment=Coment\u00e1rio
-ConfigView.label.movetorrent=Mover .torrent
-ConfigView.label.movepartialdownloads=Mover mesmo se alguns arquivos est\u00e3o marcados para "N\u00e3o Baixar"
-ConfigView.label.subdir_is_in_default=Quando considerando se os downloads existem em um diret\u00f3rio padr\u00e3o, tamb\u00e9m considerar os sub-diret\u00f3rios
-ConfigView.section.file.decoder.label=Codifica\u00e7\u00e3o padr\u00e3o do torrent quando requerido pela sele\u00e7\u00e3o
-ConfigView.section.file.decoder.nodecoder=Nenhum
-IPChecker.external.service.no-ip.description=Provedor de servi\u00e7o DNS din\u00e2mico e est\u00e1tico\n(nenhum servi\u00e7o de 'verificar o endre\u00e7o' dispon\u00edvel gratuitamente)
-ConfigView.section.tracker.publicenable=Ativar torrents externos
-ConfigView.label.playdownloadspeech=Falar quando um download est\u00e1 terminado
-#
-# Tooltips
-#
-GeneralView.label.status.pieces_available.tooltip=Exibe o n\u00famero de c\u00f3pias dispon\u00edveis de cada peda\u00e7o.\nSe o n\u00famero a direita for menor que 1, voc\u00ea n\u00e3o est\u00e1 vendo uma c\u00f3pia completa do arquivo (e pode ter problemas para completar o download).
-GeneralView.label.trackerurl.tooltip=Clique para copiar a URL de an\u00fancio para a \u00e1rea de transfer\u00eancia
-GeneralView.label.trackerurlopen.tooltip=Clicar para abrir a p\u00e1gina principal do tracker
-#
-# 2.0.4.4
-#
-ConfigView.section.style.guiUpdate=Atualizar a GUI a cada
-ConfigView.section.style.inactiveUpdate=Atualizar a janela principal a cada atualiza\u00e7\u00e3o(\u00f5es) da N GUI quando n\u00e3o \u00e9 a janela ativa
-ConfigView.section.style.graphicsUpdate=Atualizar as barras gr\u00e1ficas a cada N atualiza\u00e7\u00f5e(s) da GUI
-ConfigView.section.style.reOrderDelay=Reordenar tabelas a cada N atualiza\u00e7\u00f5e(s) da GUI [0: nunca]
-ConfigView.section.style.reOrderDelay.never=Nunca
-ConfigView.section.logging=Registro
-ConfigView.section.logging.enable=Ativar registro para o arquivo
-ConfigView.section.logging.logdir=Diret\u00f3rio do arquivo de log
-ConfigView.section.logging.choosedefaultsavepath=Por favor, escolha o diret\u00f3rio para salvar
-GeneralView.label.updatein.querying=Requisitando...
-configureWizard.nat.sharePort=Usar uma \u00fanica porta de entrada compartilhada para todos os torrents
-ConfigView.section.logging.maxsize=Tamanho m\u00e1ximo do arquivo de log
-ConfigView.section.tracker.passwordenableweb=Ativar senha na rede do tracker
-ConfigView.section.tracker.passwordenabletorrent=Ativar senha nos torrents
-ConfigView.section.tracker.username=Nome de usu\u00e1rio
-ConfigView.section.tracker.password=Senha
-columnChooser.title=Escolher as colunas a exibir
-columnChooser.move=Arraste as linhas para re-orden\u00e1-las
-columnChooser.apply=Aplicar
-columnChooser.columnname=Nome da Coluna
-columnChooser.columndescription=Descri\u00e7\u00e3o
-TableColumn.header.shareRatio=Propor\u00e7\u00e3o do Compartilhamento
-MyTorrentsView.menu.editTableColumns=&Configura\u00e7\u00e3o das Colunas
-wizard.operationfailed=A opera\u00e7\u00e3o falhou
-authenticator.title=Autentica\u00e7\u00e3o Requerida
-authenticator.realm=Dom\u00ednio
-authenticator.user=Nome de Usu\u00e1rio
-authenticator.password=Senha
-ConfigView.label.allowSendVersion=Permitir ao Vuze o envio an\u00f4nimo do n\u00famero da vers\u00e3o e ID aleat\u00f3ria enquanto procura por nova vers\u00e3o
-ConfigView.label.version.info.link=Visite aqui para detalhes sobre quais dados s\u00e3o enviados para o servidor de verifica\u00e7\u00e3o da vers\u00e3o
-wizard.hint.mode=Dica:\tVoc\u00ea pode Arrastar e Soltar um \u00fanico arquivo ou diret\u00f3rio neste assistente\n\tpara escolher um arquivo ou diret\u00f3rio
-wizard.hint.file=Dica:\tVoc\u00ea pode escolher um \u00fanico arquivo com Arrastar e Soltar
-wizard.hint.directory=Dica:\tVoc\u00ea pode escolher um \u00fanico diret\u00f3rio com Arrastar e Soltar
-MainWindow.menu.help.checkupdate=&Procurar por Atualiza\u00e7\u00f5es...
-TableColumn.header.down=Baixado
-TableColumn.header.up=Enviado
-ConfigView.section.tracker.passwordenabletorrent.info=Requer cliente BitTorrent adequado (ex: Vuze)
-ConfigView.section.style.confirmationOnExit=Mostrar janela de confirma\u00e7\u00e3o ao sair
-MainWindow.dialog.exitconfirmation.title=Sair do Vuze?
-MainWindow.dialog.exitconfirmation.text=Voc\u00ea quer realmente sair do Vuze?
-SystemTray.menu.stopalltransfers=Parar &Todas as Transfer\u00eancias
-TrayWindow.menu.stopalldownloads=Parar &Todos os Downloads
-ConfigView.section.tracker.sslport.info=Veja o FAQ para mais informa\u00e7\u00f5es
-wizard.tracker.ssl=Usar SSL
-ConfigView.label.playdownloadfinished=Tocar um som quando um download est\u00e1 terminado
-ConfigView.label.popupdownloadfinished=Mostrar um alerta quando um download estiver conclu\u00eddo
-ConfigView.label.popupfilefinished=Mostrar um alerta quando um arquivo estiver conclu\u00eddo
-TableColumn.header.pieces=Peda\u00e7os
-TableColumn.header.pieces.info=Barra gr\u00e1fica representando quais peda\u00e7os voc\u00ea baixou
-TableColumn.header.completion=Conclus\u00e3o
-TableColumn.header.completion.info=Representa\u00e7\u00e3o gr\u00e1fica dos % baixados
-ConfigView.section.style.showdownloadbasket=Mostrar Cesta de Downloads (Arrastar e Soltar .torrents)
-ConfigView.section.style.alwaysShowTorrentFiles=Sempre mostrar os arquivos Torrent em Detalhes/Arquivos
-wizard.multitracker=Adicionar informa\u00e7\u00e3o Multi-Tracker ao torrent
-wizard.multitracker.configuration=Configura\u00e7\u00e3o do Multi-Tracker
-wizard.multitracker.new=Novo...
-wizard.multitracker.edit=Editar...
-wizard.multitracker.delete=Apagar
-wizard.multitracker.group=Grupo de Trackers
-wizard.multitracker.edit.title=Editor Multi-Tracker
-wizard.multitracker.edit.name=Nome
-wizard.multitracker.edit.save=Salvar
-wizard.multitracker.edit.newgroup=Novo Grupo
-wizard.multitracker.edit.deletegroup=Apagar
-wizard.multitracker.edit.newtracker=Novo Tracker
-wizard.multitracker.edit.deletetracker=Apagar
-wizard.multitracker.edit.edit=Editar
-wizard.addingmt=Adicionando informa\u00e7\u00e3o Multi-Tracker
-wizard.multitracker.noannounce=A URL de an\u00fancio n\u00e3o est\u00e1 presente em sua lista de trackers
-MyTorrentsView.menu.recheck=For\u00e7ar Re-chec&agem
-iconBar.showDownloadBar.tooltip=Mostrar a Barra de Downloads
-iconBar.start.tooltip=Iniciar
-iconBar.stop.tooltip=Interromper
-iconBar.remove.tooltip=Remover
-iconBar.openNoDefault.tooltip=Abrir um arquivo .torrent (sem save padr\u00e3o)
-iconBar.openURL.tooltip=Abrir uma URL
-iconBar.openFolder.tooltip=Abrir uma Pasta
-iconBar.new.tooltip=Criar um torrent
-iconBar.up.tooltip=Mover para cima
-iconBar.down.tooltip=Mover para baixo
-iconBar.run.tooltip=Abrir
-iconBar.host.tooltip=Hospedeiro
-iconBar.publish.tooltip=Publicar
-iconBar.editcolumns.tooltip=Configura\u00e7\u00e3o da Coluna
-MyTorrentsView.menu.editTracker=&Editar URL(s) do Tracker
-GeneralView.menu.selectTracker=Selecionar
-ConfigView.section.stats.xslfile=Nome do arquivo XSL
-ConfigView.section.stats.xslfiledetails=Isto ser\u00e1 inclu\u00eddo no cabe\u00e7alho do arquivo de estat\u00edsticas via tag <?xml-stylesheet>
-ConfigView.label.savetorrentbackup=Salvar Backup
-ConfigView.section.tracker.forceport=For\u00e7ar torrents externos hospedados para a porta padr\u00e3o
-ConfigView.section.ipfilter.allow=PERMITIR estes intervalos (o padr\u00e3o \u00e9 NEGAR)
-ConfigView.section.ipfilter.list.inrange=estava no intervalo
-ConfigView.section.ipfilter.list.notinrange=n\u00e3o estava em qualquer intervalo
-ConfigView.section.ipfilter.list.title=Lista de IPs Bloqueados
-ConfigView.label.allowsameip=Permitir m\u00faltiplas conex\u00f5es do mesmo IP
-ConfigView.label.allowsameip.tooltip=S\u00f3 marque se voc\u00ea PRECISA.\nEsta \u00e9 uma prote\u00e7\u00e3o contra leechers (quando desativado).
-ConfigView.label.userSuperSeeding=Usar Super Seeding
-PeersView.uniquepiece=Peda\u00e7o (modo Super-Seed)
-PeersView.uniquepiece.none=Nenhum
-PeersView.timetosend=Tempo para re-enviar o Peda\u00e7o (Modo Super-Seed)
-ConfigView.section.style.addurlsilently=Abrir URLs passadas silenciosamente
-ConfigView.section.style.addurlsilently.tooltip=Automaticamente baixar URLs dos .torrent passadas/soltas sem abrir a caixa de di\u00e1logo.
-ConfigView.section.file.decoder.prompt=Sempre alertar quando houver uma escolha de codifica\u00e7\u00e3o dispon\u00edvel
-ConfigView.section.file.decoder.prompt.tooltip=Sempre mostrar uma janela quando houver uma escolha de codifica\u00e7\u00e3o estiver dispon\u00edvel
-MyTorrentsView.menu.moveTop=&Topo
-MyTorrentsView.menu.moveEnd=&Fundo
-ConfigView.label.moveonlyusingdefaultsave=apenas se estiver no diret\u00f3rio de dados padr\u00e3o
-ConfigView.label.moveonlyusingdefaultsave.tooltip=Mover apenas se os dados baixados estiverem no diret\u00f3rio de dados padr\u00e3o
-ConfigView.label.watchtorrentfolder=Importar novos .torrents automaticamente
-ConfigView.label.watchtorrentfolder.tooltip=Procurar por novos .torrents regularmente
-ConfigView.label.watchtorrentfolderinterval=Intervalo
-ConfigView.label.watchtorrentfolderinterval.tooltip=Pausa at\u00e9 que a pasta seja verificada novamente
-ConfigView.dialog.choosewatchtorrentfolderpath=Por favor, escolha o diret\u00f3rio de importa\u00e7\u00e3o dos .torrents
-ConfigView.label.startwatchedtorrentsstopped=Iniciar parado
-ConfigView.label.startwatchedtorrentsstopped.tooltip=Adiciona novos .torrents no estado PARADO
-ConfigView.section.plugins=Plugins 
-wizard.maketorrent.filesize=Tamanho do(s) Arquivo(s)
-wizard.maketorrent.piececount=Contagem de Peda\u00e7os
-wizard.maketorrent.piecesize=Tamanho do Peda\u00e7os
-wizard.maketorrent.auto=Autom\u00e1tico
-MainWindow.menu.view.stats=&Estat\u00edsticas
-SpeedView.title.full=Atividade
-SpeedView.downloadSpeed.title=Velocidade de Download
-SpeedView.uploadSpeed.title=Velocidade de Upload
-ConfigView.section.style.useSIUnits=Usar Unidades IEC (KB -> KiB etc.)
-iconBar.top.tooltip=Mover para o topo
-iconBar.bottom.tooltip=Mover para baixo
-TableColumn.header.health=Sa\u00fade
-MyTorrentsView.menu.health=Sobre a Qualidade
-health.explain.grey=significa que o seu torrent n\u00e3o est\u00e1 rodando (baixando ou enviando)
-health.explain.red=significa que voc\u00ea n\u00e3o est\u00e1 conectado a nenhum peer enquanto baixa
-health.explain.blue=quando ficando de seed, significa que voc\u00ea ainda n\u00e3o est\u00e1 conectado a qualquer peer\nquando baixando, significa que voc\u00ea est\u00e1 conectado a alguns peers mas o tracker est\u00e1 inativo
-health.explain.yellow=significa que o tracker est\u00e1 OK, voc\u00ea est\u00e1 conectado a peers, mas voc\u00ea n\u00e3o tem nenhuma conex\u00e3o remota.\nVoc\u00ea pode ter um problema de NAT se seus torrents ficam no estado amarelo o tempo todo
-health.explain.green=significa que tudo vai bem.
-ConfigView.section.style.alwaysRefreshMyTorrents=Sempre atualizar Meus Torrents
-ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Esta op\u00e7\u00e3o atualizar\u00e1 a guia Meus Torrents mesmo se n\u00e3o exibida (\u00fatil para alguns plugins mirc)
-#
-#2.0.7.0
-#
-security.certtruster.title=Alerta do Certificado de Seguran\u00e7a
-security.certtruster.intro=O certificado de seguran\u00e7a foi emitido por uma empresa na qual voc\u00ea n\u00e3o confia
-security.certtruster.resource=Recurso:
-security.certtruster.issuedto=Emitido Para:
-security.certtruster.issuedby=Emitido Por:
-security.certtruster.prompt=Voc\u00ea quer confiar nela?
-security.certtruster.yes=Sim
-security.certtruster.no=N\u00e3o
-ConfigView.section.tracker.torrentsperpage=Quantos torrents por p\u00e1gina?  [0: ilimitados]
-MainWindow.menu.file.share=&Compartilhar
-MainWindow.menu.file.share.file=&Arquivo...
-MainWindow.menu.file.share.dir=P&asta...
-MainWindow.menu.file.share.dircontents=Conte\u00fado &da Pasta...
-MainWindow.menu.file.share.dircontentsrecursive=Conte\u00fados da Pasta... (&Recursivo)
-MainWindow.dialog.share.sharefile=Selecionar Arquivo para Compartilhar
-MainWindow.dialog.share.sharedir=Selecionar Pasta para Compartilhar
-MainWindow.dialog.share.sharedircontents=Selecionar Conte\u00fados da Pasta para Compartilhar
-MainWindow.dialog.share.sharedircontents.recursive=Recursivo
-globalmanager.download.remove.veto=A\u00e7\u00e3o de Remo\u00e7\u00e3o Vetada
-plugin.sharing.download.remove.veto=Este download \u00e9 o resultado de um recurso sendo compartilhado.\nPara remover o download remova o compartilhamento associado: go to Tools->My Classic-Shares.
-ConfigView.section.tracker.main=Principal
-ConfigView.section.tracker.web=Web 
-ConfigView.label.prioritizefirstpiece=Priorizar o primeiro e o \u00faltimo peda\u00e7o do(s) arquivo(s)
-ConfigView.label.prioritizefirstpiece.tooltip=Tenta baixar o come\u00e7o e o fim de um arquivo primeiro.\nPara o suporte de pr\u00e9-visualiza\u00e7\u00e3o.
-ConfigView.section.file.delete.include_files_outside_save_dir=Quando apagar dados, permitir que arquivos ligados fora do diret\u00f3rio do torrent tamb\u00e9m sejam removidos
-TrayWindow.menu.startalldownloads=Iniciar Todos os Downloads
-SystemTray.menu.startalltransfers=Iniciar Todas as Transfer\u00eancias
-sharing.progress.title=Progresso do Compartilhamento
-sharing.progress.hide=Esconder
-MainWindow.menu.view.myshares=Meus Compartilhamentos
-MySharesView.title.full=Meus Compartilhamentos
-MySharesView.name=Nome
-MySharesView.type=Tipo
-MySharesView.type.file=Arquivo
-MySharesView.type.dir=Diret\u00f3rio
-MySharesView.type.dircontents=Conte\u00fado do Diret\u00f3rio
-MySharesView.type.dircontentsrecursive=Conte\u00fado do diret\u00f3rio (recursivo)
-MySharesView.menu.remove=Remover
-ConfigView.section.tracker.extensions=Extens\u00f5es
-ConfigView.section.tracker.sendpeerids=Enviar as identidades dos peers aos que baixam
-ConfigView.section.tracker.enableudp=Ativar o protocolo do tracker UDP
-plugin.sharing.torrent.remove.veto=Este registro de tracker \u00e9 o resultado de um recurso que est\u00e1 sendo compartilhado.\nPara remover o download remova o compartilhamento associado: go to Tools->My Classic-Shares.
-plugin.download.remove.veto.notstopped=O download n\u00e3o pode ser removido se n\u00e3o for parado
-plugin.sharing.remove.veto=Este compartilhamento \u00e9 um sub-compartilhamento de um 'conte\u00fado de diret\u00f3rio' e n\u00e3o pode ser explicitamente apagado.\n Apague o compartilhamento raiz
-GeneralView.label.hash.tooltip=Clique para copiar o hash para a \u00e1rea de transfer\u00eancia
-ConfigView.section.tracker.maxpeersreturned=M\u00e1ximo de peers retornados [0: ilimitados]
-ConfigView.label.serverport=Porta de escuta TCP / UDP de entrada
-ConfigView.label.serverport.tooltip=A porta deve estar dentro de 1-65535, e nunca a 6880 como essa est\u00e1 reservada para o uso interno do Vuze.
-configureWizard.nat.server.tcp_listen_port=Porta de Escuta da Entrada TCP
-ConfigView.section.sharing=Compartilhamento
-ConfigView.section.sharing.usessl=Usar SSL para recursos compartilhados (requer a configura\u00e7\u00e3o do Tracker)
-ConfigView.section.style.dropdiraction=A\u00e7\u00e3o ao Arrastar e Soltar para diret\u00f3rios
-ConfigView.section.style.dropdiraction.opentorrents=Abrir Torrents
-ConfigView.section.style.dropdiraction.sharefolder=Compartilhar Diret\u00f3rio
-ConfigView.section.style.dropdiraction.sharefoldercontents=Compartilhar Conte\u00fado
-#
-# 2.0.7.x
-#
-Categories.all=Todas
-Categories.uncategorized=Sem categoria
-CategoryAddWindow.message=Insira um novo nome de categoria
-CategoryAddWindow.title=Adicionar Nova Categoria
-ConfigView.label.autoSeedingIgnoreInfo=Torrents ignorados v\u00e3o para o final da fila de seeds. Eles n\u00e3o s\u00e3o automaticamente iniciados.\nIgnorar regras n\u00e3o se aplica a torrents que entrem no crit\u00e9rio da Primeira Prioridade.\nA menos que declarado de outro modo, use um valor de 0 para desativar uma regra.
-ConfigView.label.directory=Diret\u00f3rio
-ConfigView.label.disconnetseed.tooltip=Quando estiver ficando de seed com um torrent, desconectar quaisquer clientes que tamb\u00e9m est\u00e3o ficando de seed.\nEles n\u00e3o precisam estar falando com voc\u00ea.
-ConfigView.label.ignoreCase=Ignorar Mai\u00fasculas/Min\u00fasculas
-ConfigView.label.ignoreSeeds=Ignorar torrents com pelo menos
-ConfigView.label.importdirectory=Diret\u00f3rio de Importa\u00e7\u00e3o
-ConfigView.label.minPeersToBoostNoSeeds.tooltip=Quaisquer torrents sem seeds e tendo menos peers do que voc\u00ea especificar\nir\u00e3o para o final da fila.
-ConfigView.label.minPeersToBoostNoSeeds=Rank da Prioridade para Ficar de Seed menor para torrents sem seeds e com menos de
-ConfigView.label.minSeedingTime.tooltip=Os Ranks de Seeding podem flutuar frequentemente em um curto per\u00edodo de tempo, as vezes fazendo o torrent iniciar automaticamente, apenas para ser parado & e posto no fila imediatamente ap\u00f3s isso.\nIsto alivia o problema for\u00e7ando o torrent a ficar de seed por um per\u00edodo dado de tempo.  Voc\u00ea ainda pode par\u00e1-lo manualmente se voc\u00ea quiser.
-ConfigView.label.minSeedingTime=Tempo m\u00ednimo para ficar de seed em segundos
-ConfigView.label.minSpeedForActiveDL.tooltip=Um slot de download \u00e9 sempre usado para os 30 segundos iniciais\nap\u00f3s o torrent incompleto iniciar.
-ConfigView.label.minSpeedForActiveDL=N\u00e3o contar o torrent como usando um slot de download se a velocidade for inferior a
-ConfigView.label.queue.debuglog=Registrar a informa\u00e7\u00e3o de debug
-ConfigView.label.queue.debuglog.info=Adiciona informa\u00e7\u00f5es de debug da fila ao arquivo de console/log.\nEmbora cifradas, as informa\u00e7\u00f5es de debug dizem a voc\u00ea o estado dos torrents e porque eles est\u00e3o/n\u00e3o est\u00e3o iniciando/requerindo.
-ConfigView.label.queue.minQueueingShareRatio=N\u00e3o requerer ou parar um torrent at\u00e9 que a sua propor\u00e7\u00e3o de compartilhamento atinja
-ConfigView.label.ratio=propor\u00e7\u00e3o
-ConfigView.label.removeOnStop=Remover o torrent da lista ap\u00f3s automaticamente parar
-ConfigView.label.savedirectory=Diret\u00f3rio para Salvar
-ConfigView.label.seeding.autoReposition.tooltip=Se ativado, a ordem dos torrents (a coluna '#') ser\u00e1 alterada para combinar com aquela do Rank do Seeding\nIsto \u00e9 \u00fatil se voc\u00ea n\u00e3o gosta de ver os n\u00fameros do Rank de Seeding, mas ainda quer saber a ordem na qual os torrents completados ser\u00e3o iniciados.
-ConfigView.label.seeding.autoReposition=Automaticamente reposicionar torrents baseado no Rank do Seeding
-ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Freq\u00fcentemente, torrents com poucas contagens de seeds e muitas contagens de peers querem dizer que provavelmente n\u00e3o s\u00e3o uma c\u00f3pia completa entre os peers.\nPortanto, voc\u00ea pode n\u00e3o querer que as regras de seeding finjam que h\u00e1 uma c\u00f3pia completa (e assim incorretamente reduzindo o seu rank)
-ConfigView.label.seeding.fakeFullCopySeedStart=mas apenas para os torrents com pelo menos
-ConfigView.label.seeding.ignore=Ignorar Regras
-ConfigView.label.seeding.ignore0Peers=Ignorar torrents com 0 peers
-ConfigView.label.seeding.ignoreRatioPeers=Ignorar torrents que tenham pelo menos 1 seed para cada
-ConfigView.label.seeding.ignoreShareRatio=Ignorar torrents que tenham uma propor\u00e7\u00e3o de compartilhamento de
-ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorar o torrent mesmo se\nas regras de Primeira Prioridade se apliquem
-ConfigView.label.seeding.ignore.header.rule=Regra
-ConfigView.label.seeding.ignore.header.value=Valor
-ConfigView.label.seeding.firstPriority.info=Torrents com Primeira Prioridade sempre estar\u00e3o no topo da fila.\nQuaisquer torrents combinando com o Crit\u00e9rio de Primeira Prioridade n\u00e3o ser\u00e3o automaticamente parados e enfileirados.\nUm torrent combinando com o crit\u00e9rio de Primeira Prioridade tomar\u00e1 um slot de download simult\u00e2neo se ele precisar.
-ConfigView.label.seeding.firstPriority.FP=Primeira Prioridade
-ConfigView.label.seeding.firstPriority=A primeira prioridade vai para os torrents com
-ConfigView.label.seeding.firstPriority.following=os/dos seguintes:
-ConfigView.label.seeding.firstPriority.shareRatio=Uma propor\u00e7\u00e3o de compartilhamento inferior a
-ConfigView.label.seeding.firstPriority.seedingMinutes=Tempo decorrido desde que mudou de baixando para seeding
-ConfigView.label.seeding.firstPriority.DLMinutes=Um tempo decorrido desde o come\u00e7o do download
-ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Fingindo que h\u00e1 1 c\u00f3pia completa por X peers, voc\u00ea reduz o rank dos torrents com alta contagem de peers.\n\u00c9 prov\u00e1vel que os torrents com contagem alta de peers tamb\u00e9m possuam alto tr\u00e1fego.\nIsto n\u00e3o muda quaisquer das exibi\u00e7\u00f5es '# de seeds'.
-ConfigView.label.seeding.numPeersAsFullCopy=Fingir que h\u00e1 1 c\u00f3pia completa para cada\n(0 : N\u00e3o Fingir)
-ConfigView.label.seeding.preferLargerSwarms.tooltip=Se voc\u00ea est\u00e1 ficando de seed principalmente com torrents com peers que est\u00e3o "travados", preferir multid\u00f5es maiores faz sentido\nQuando voc\u00ea est\u00e1 ficando de seed principalmente com torrents com alta disponibilidade, preferir multid\u00f5es menores faz sentido.
-ConfigView.label.seeding.preferLargerSwarms=Quando os torrents tem o mesmo rank, preferir as multid\u00f5es maiores
-ConfigView.label.seeding.rankType.none.tooltip=Ordem baseada na coluna #
-ConfigView.label.seeding.rankType.none=Nenhum
-ConfigView.label.seeding.rankType.peer.tooltip=mais peers e menos seeds = higher rank\nEste ranking minimiza o n\u00famero de torrents que precisam ser mantidos ativos para maximizar o upload
-ConfigView.label.seeding.rankType.peer=Contagem de Peers Pesados
-ConfigView.label.seeding.rankType.peerSeed.options=Op\u00e7\u00f5es da Propor\u00e7\u00e3o dos Peers:Seeds
-ConfigView.label.seeding.rankType.peerSeed.tooltip=Maior Propor\u00e7\u00e3o = Maior Rank
-ConfigView.label.seeding.rankType.peerSeed=Propor\u00e7\u00e3o de Peers:Seed
-ConfigView.label.seeding.rankType.seed.fallback=Reverter para a Propor\u00e7\u00e3o de Peers:Seeds ap\u00f3s\n(0 : Nunca Reverter)
-ConfigView.label.seeding.rankType.seed.options=S\u00f3 Op\u00e7\u00f5es de Contagem dos Seeds
-ConfigView.label.seeding.rankType.seed.tooltip=Menos Seeds = Maior Rank
-ConfigView.label.seeding.rankType.seed=Apenas Contagem de Seeds
-ConfigView.label.seeding.rankType.timedRotation.tooltip=Todos os torrents completados na fila ir\u00e3o para o modo seeding.\nA dura\u00e7\u00e3o do tempo de seeding \u00e9 definida em 'Tempo M\u00ednimo de Seeding'
-ConfigView.label.seeding.rankType.timedRotation=Rota\u00e7\u00e3o Temporarizada
-ConfigView.label.seeding.rankType.tooltip=Torrents mais altos no ranking s\u00e3o iniciados automaticamente.\nQuando outro torrent obt\u00eam um rank maior, o de menor rank para e volta pra fila.\n\nApenas torrents em um estado Na Fila est\u00e3o dispon\u00edveis para in\u00edcio autom\u00e1tico.\nTorrents parados nunca s\u00e3o iniciados automaticamente.
-ConfigView.label.seeding.rankType=Colocar os torrents completados para auto-iniciar baseado em:
-ConfigView.label.stopAfterMinutes=Uma vez trocado para ficar de seed, parar ap\u00f3s uma dura\u00e7\u00e3o de tempo
-ConfigView.label.switchpriority.tooltip=Baixa prioridade reduz a largura de banda de upload fornecida ao torrent.
-ConfigView.pluginlist.info=Os seguintes plugins foram identificados.  Alguns plugins podem n\u00e3o ter abas de configura\u00e7\u00e3o.
-ConfigView.pluginlist.noplugins=Nenhum plugin foi encontrado.
-ConfigView.section.pluginslist=Lista\t 
-ConfigView.section.queue.seeding=Ficar de Seed
-ConfigView.section.queue.seeding.autoStarting=In\u00edcio Autom\u00e1tico
-ConfigView.section.queue.seeding.ignore=Ignorar Regras
-ConfigView.section.queue.seeding.firstPriority=Primeira Prioridade
-ConfigView.section.queue.main=Principal
-ConfigView.section.queue=Filas
-ConfigView.text.all=todos
-ConfigView.text.hours=horas
-ConfigView.text.ignoreRule=Ignorar Regra
-ConfigView.text.ignore=Ignorar
-ConfigView.text.minutes=minutos
-ConfigView.text.neverIgnore=Nunca Ignorar
-ConfigView.text.any=qualquer
-DownloadManager.error.datamissing=Dados Ausentes
-MainWindow.menu.file.open.torrentforseeding=Arquivo Torrent... (Para Ficar de Seed)
-MainWindow.menu.language.refresh=&Atualizar
-ManagerItem.forced=For\u00e7ado
-ManagerItem.queued=Na Fila
-MySeedersView.header=Torrents Completos
-TableColumn.header.availability.info=# de c\u00f3pias completas sendo vistas
-TableColumn.header.availability=Disponibilidade
-TableColumn.header.category=Categoria
-MyTorrentsView.header=Torrents Incompletos
-TableColumn.header.maxuploads=M\u00e1x de # Uploads
-MyTorrentsView.menu.category.delete=&Apagar Categoria
-MyTorrentsView.menu.forceStart=&For\u00e7ar In\u00edcio
-MyTorrentsView.menu.queue=&Fila
-MyTorrentsView.menu.setCategory.add=&Adicionar Categoria...
-MyTorrentsView.menu.setCategory=Designar Categoria
-TableColumn.header.savepath=Caminho para Salvar
-TableColumn.header.SeedingRank=Rank do Seeding
-TableColumn.header.totalspeed.info=Velocidade Total de todos os peers aos quais voc\u00ea est\u00e1 conectado
-TableColumn.header.totalspeed=Velocidade Total
-splash.initializePlugins=Inicializando os Plugins 
-StartStopRules.SPratioMet=Propor\u00e7\u00e3o de S:P OK
-StartStopRules.shareRatioMet=Propor\u00e7\u00e3o de Compartilhamento OK
-StartStopRules.waiting=Aguardando
-StartStopRules.firstPriority=1a Prioridade 
-ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Compartilhar Conte\u00fados (Recursivo)
-DownloadManager.error.unabletostartserver=Incapaz de iniciar o servidor - verifique a configura\u00e7\u00e3o da porta de entrada / e permiss\u00f5es no firewall para que o aplicativo aja como servidor
-GeneralView.label.creationdate=Criado Em :
-ConfigView.section.tracker.announcescrapepercentage=Intervalo do scrape com % da idade do an\u00fancio\nex: 200 = 2:1. 0 = deixar o peer decidir
-ManagerItem.stopping=Parando
-ConfigView.section.tracker.announcecacheperiod=Anunciar o cache (ms)
-ConfigView.section.tracker.scrapecacheperiod=Cache do scrape (ms)
-ConfigView.section.tracker.scrapeandcache=Scrape e cache
-ConfigView.section.tracker.announcecacheminpeers=Anunciar cache e ativar in\u00edcio do peer 
-fileDownloadWindow.retry=Tentar Novamente
-MyTrackerView.bytesin=Bytes Recebidos
-MyTrackerView.bytesinave=M\u00e9dia de Entrada
-MyTrackerView.bytesout=Bytes Enviados
-MyTrackerView.bytesoutave=M\u00e9dia de Sa\u00edda
-ConfigView.section.file.max_open_files=M\u00e1ximo de arquivos abertos para leitura/escrita\n[0: ilimitados]
-ConfigView.section.file.max_open_files.tooltip=\u00datil se voc\u00ea baixa torrents com centenas/milhares de arquivos neles, e se voc\u00ea est\u00e1 atingindo o limite de gerenciamento de arquivos do SO.
-ConfigView.section.proxy=Op\u00e7\u00f5es do Proxy
-ConfigView.section.proxy.enable_proxy=Ativar Proxying de comunica\u00e7\u00f5es com o tracker [requer reiniciar]
-ConfigView.section.proxy.host=Servidor
-ConfigView.section.proxy.port=Porta
-ConfigView.section.proxy.username=Nome de Usu\u00e1rio
-ConfigView.section.proxy.password=Senha
-ConfigView.section.proxy.enable_socks=Eu tenho um Proxy SOCKS
-wizard.createtorrent.extrahashes=Adicionar hashes para as outras redes (ex: Gnutella2, eDonkey2000)
-GeneralView.label.connected=conectado(s)
-GeneralView.label.in_swarm=na multid\u00e3o
-ManagerItem.initializing=Inicializando
-AlertMessageBox.error=Erro
-AlertMessageBox.warning=Aviso
-AlertMessageBox.comment=Informa\u00e7\u00f5es
-AlertMessageBox.information=Informa\u00e7\u00e3o
-AlertMessageBox.unread=Voc\u00ea n\u00e3o leu as mensagens de alerta - clique aqui para exib\u00ed-las.
-SharedPortServer.alert.selectorfailed=Falhou em estabelecer um ouvidor para os dados de entrada.\nVerifique se as configura\u00e7\u00f5es de firewall est\u00e3o permitindo que o java(w).exe ajam como um 'servidor'
-Tracker.alert.listenfail=Falhou em estabelecer a escuta na porta %1.\nVerifique se outros aplicativos j\u00e1 n\u00e3o est\u00e3o usando esta porta.\nVerifique tamb\u00e9m se h\u00e1 outra c\u00f3pia do Vuze rodando.
-DiskManager.alert.movefileexists=Erro ao mover arquivos completos\nO arquivo %1 j\u00e1 existe no diret\u00f3rio de destino MoveTo
-DiskManager.alert.movefilefails=Erro ao mover arquivos completos\nA movimenta\u00e7\u00e3o do arquivo %1 falhou, %2
-DiskManager.alert.movefilerecoveryfails=Erro ao recuperar ap\u00f3s uma falha de movimenta\u00e7\u00e3o\nRestaura\u00e7\u00e3o do arquivo %1 falhou, %2
-ConfigView.section.tracker.logenable=Registrar as estat\u00edsticas per\u00edodicas em 'tracker.log'
-SpeedView.stats.title=Estat\u00edsticas
-SpeedView.stats.session=Esta Sess\u00e3o
-SpeedView.stats.session.tooltip=Total (Protocolo)
-SpeedView.stats.downloaded=Baixado (Protocolo)
-SpeedView.stats.uploaded=Enviado (Protocolo)
-SpeedView.stats.ratio=Propor\u00e7\u00e3o
-SpeedView.stats.uptime=Tempo de Upload
-SpeedView.stats.now=Agora
-SpeedView.stats.now.tooltip=Total (Protocolo)
-AutoMigration.useralert=Arquivos da configura\u00e7\u00e3o do usu\u00e1rio do Vuze/resultados da auto-migra\u00e7\u00e3o dos diret\u00f3rios:\n\n%1\nQuaisquer falhas devem ser migradas manualmente.\nN\u00c3O SE ESQUE\u00c7A DE ATUALIZAR OS CAMINHOS PARA SALVAR NA SUA CONFIGURA\u00c7\u00c3O SE ELES FORAM MIGRADOS!
-#
-# > 2.0.8.0
-#
-OpenTorrentWindow.title=Abrir Torrent(s)
-# Not used, but could be renamed in all translation files to label.experimental :)
-OpenTorrentWindow.addFiles=&Adicionar Arquivos
-OpenTorrentWindow.dataLocation=Local para salvar os dados:
-OpenTorrentWindow.startMode=Adicionar Modo
-OpenTorrentWindow.startMode.queued=Na Fila
-OpenTorrentWindow.startMode.stopped=Parado
-OpenTorrentWindow.startMode.forceStarted=For\u00e7ar In\u00edcio
-OpenTorrentWindow.addPosition=Posi\u00e7\u00e3o na Fila
-OpenTorrentWindow.addPosition.first=Primeiro
-OpenTorrentWindow.addPosition.last=\u00daltimo
-TableColumn.header.remaining.info=Quantia restante para baixar
-TableColumn.header.remaining=Restando
-ConfigView.section.tracker.enablecompact=Ativar o protocolo de an\u00fancio compacto
-ConfigView.section.tracker.enablekey=Ativar a entrega da chave ao tracker para seguran\u00e7a melhorada
-ConfigView.section.file.perf=Op\u00e7\u00f5es de Performance
-ConfigView.section.file.perf.explain=Aviso - Mudan\u00e7as inadequadas destes par\u00e2metros podem afetar adversamente o desempenho do download. Requer reiniciar.\nSe voc\u00ea tem problemas com "falta de mem\u00f3ria" considere limitar as conex\u00f5es por torrent (Veja as configura\u00e7\u00f5es das Transfer\u00eancias)
-ConfigView.section.file.max_open_files.explain=Abrir muitos arquivos pode causar problemas no sistema operacional devido aos recursos limitados dos gerenciadores de arquivos. Isto limita o n\u00famero de arquivos abertos coincidentes.
-popup.error.hide=Esconder
-popup.error.details=Detalhes
-ConfigView.section.style.colorOverrides=N\u00e3o Levar em Conta as Cores
-ConfigView.section.style.colorOverride.progressBar=Barra de Progresso
-ConfigView.section.style.colorOverride.error=Erro
-MainWindow.status.tooOld=\u00e9 antiga, por favor atualize-a.
-ConfigView.section.style.colorOverride.warning=Aviso
-ConfigView.section.style.colorOverride.altRow=Linhas Alternadas
-ConfigView.section.file.save.peers.enable=Salvar as conex\u00f5es com o peer para reconex\u00f5es r\u00e1pidas
-ConfigView.section.file.save.peers.max=M\u00e1ximo de peers a salvar [0: ilimitados]
-ConfigView.section.file.save.peers.pertorrent=por torrent
-ConfigView.label.max_peers_per_torrent=M\u00e1ximo de conex\u00f5es padr\u00e3o por torrent [0: ilimitadas]
-ConfigView.label.max_peers_total=M\u00e1ximo de conex\u00f5es globais [0: ilimitadas]
-ConfigView.section.style.colorOverrides.reset=Redefinir Cor
-ConfigView.section.language.info=Quando ativada, uma verifica\u00e7\u00e3o de atualiza\u00e7\u00e3o ocorrer\u00e1 toda vez que o Vuze iniciar.
-ConfigView.section.language.enableUpdate=Ativar Atualiza\u00e7\u00e3o via Web
-ConfigView.section.language.UpdateURL=URL da Atualiza\u00e7\u00e3o
-ConfigView.section.language.UpdateNow=Atualizar Agora!
-Button.revert=Inverter
-MyTorrentsView.menu.changeDirectory=Mudar o Diret\u00f3rio de Dados
-GenericText.column=coluna
-MyTorrentsView.menu.thisColumn.remove=Remover Coluna
-MyTorrentsView.menu.thisColumn.toClipboard=Copiar o Texto para a \u00c1rea de Transfer\u00eancia
-MyTorrentsView.menu.thisColumn.autoTooltip=Sempre exibir dicas
-TableColumn.header.secondsseeding=Fazendo Seed Por
-TableColumn.header.secondsseeding.info=Quantia total de tempo que voc\u00ea esteve fazendo see.
-TableColumn.header.secondsdownloading=Baixando Para
-TableColumn.header.secondsdownloading.info=Quantia de tempo que voc\u00ea esteve baixando.
-ConfigView.section.tracker.udpversion=Vers\u00e3o do Protocolo UDP (1 ou 2)
-window.updateswt.title=Sua vers\u00e3o da SWT \u00e9 muito antiga!
-window.updateswt.text=Sua vers\u00e3o do SWT \u00e9 muito antiga!\nA SWT \u00e9 a biblioteca gr\u00e1fica usada pelo Vuze, e a vers\u00e3o que voc\u00ea tem \u00e9 muito antiga para rodar a \u00faltima vers\u00e3o do Vuze. Clique no bot\u00e3o OK para atualizar sua SWT.
-window.updateswt.failed=A atualiza\u00e7\u00e3o falhou, pressione OK de novo para reiniciar.
-window.updateswt.status.downloading.updater=Baixando o M\u00f3dulo de Atualiza\u00e7\u00e3o
-window.updateswt.status.finding=Procurando a \u00faltima vers\u00e3o da SWT
-window.updateswt.status.downloading=Baixando a \u00daltima Vers\u00e3o da SWT
-window.updateswt.status.done=Reiniciando
-window.updateswt.cancel=Cancelar
-swt.updater.downloader.downloading=Baixando o SWT de
-swt.updater.urlsgetter.downloading=Obtendo uma lista de mirrors de
-swt.updater.urlsgetter.platform=SWT para a plataforma :
-window.updateswt.ignore=Ignorar
-ConfigView.section.style.useFancyTabs=Usar Abas Extravagantes
-splash.initializeGM=Inicializando o Gerenciador Global de Torrents
-splash.loadingTorrents=Carregando Torrents
-MyTorrentsView.menu.thisColumn.sort=&Ordenar
-Scrape.status.ok=Scrape Ok
-Scrape.status.error=Erro de Scrape:
-Scrape.status.error.badURL=A URL de an\u00fancio n\u00e3o obedece \u00e0s especifica\u00e7\u00f5es de scrape.
-Scrape.status.error.nohash=Hash inexistente na resposta.
-Scrape.status.error.invalid=Reposta inv\u00e1lida.
-Scrape.status.nextScrapeAt=Pr\u00f3xima scrape em %1
-Scrape.status.scraping=Scraping..
-Scrape.status.initializing=Aguardando para Scrape
-Scrape.status.scraping.queued=Scraping na fila...
-ConfigView.label.minSpeedForActiveSeeding=N\u00e3o contar torrent completo como usando um slot se a velocidade for inferior a
-ConfigView.section.stats.exportpeers=Exportar os detalhes dos peers
-MainWindow.menu.view.irc.moved=O Irc est\u00e1 agora dispon\u00edvel como um plugin, veja http://azureus.sourceforge.net/plugin_list.php. Quando instalado, use o menu visualizar->plugins->menu IRC para acess\u00e1-lo
-MyTrackerView.webui.contextmenu.copyurl=Copia a URL do torrent para a \u00c1rea de Transfer\u00eancia
-ConfigView.section.file.torrent.ignorefiles=Arquivos a ignorar quando criar torrents\nex: .DS_Store;Thumbs.db
-Torrent.create.progress.ignoringfile=Ignorando arquivo
-ConfigView.section.style.useUnitsRateBits=Usar bits em vez de bytes para os valores das taxas baseadas em bytes (KiB/s->Kibit/s etc.)
-ConfigView.section.interface.resetassoc=Redefinir associa\u00e7\u00f5es de arquivos do explorer (.torrent)
-ConfigView.section.interface.resetassocbutton=Redefinir
-ConfigView.section.interface.checkassoc=Verificar associa\u00e7\u00f5es ao iniciar
-dialog.associations.title=Verifica\u00e7\u00e3o de Associa\u00e7\u00e3o
-Button.yes=Sim
-Button.no=N\u00e3o
-ConfigView.label.seeding.autoStart0Peers=Auto-Iniciar todos os torrents completados com 0 peers
-ConfigView.label.seeding.autoStart0Peers.tooltip=Marque se voc\u00ea quer que o tracker sempre liste os seeds para torrents com 0 Peers.
-dialog.associations.prompt=O Vuze n\u00e3o \u00e9 o aplicativo padr\u00e3o para arquivos BitTorrent.\nVoc\u00ea gostaria de associar os arquivos .torrent com o Vuze?
-dialog.associations.askagain=Verificar ao iniciar
-ConfigView.section.plugins.update=Atualiza\u00e7\u00e3o dos Plugins
-Plugin.pluginupdate.enablecheck=Ativar a verifica\u00e7\u00e3o por atualiza\u00e7\u00f5es dos plugins
-plugins.basicview.activity=Atividade:
-plugins.basicview.progress=Progresso:
-plugins.basicview.log=Registro:
-ConfigView.label.maxdownloadspeed=Velocidade m\u00e1xima global de download em KB/s [0: ilimitada]
-splash.loadingTorrent=Carregando Torrent
-splash.of=de
-UpdateWindow.title=Atualizador do Vuze
-UpdateWindow.header=Os seguintes componentes precisam de uma atualiza\u00e7\u00e3o :
-UpdateWindow.columns.install=Instalar
-UpdateWindow.columns.name=Nome
-UpdateWindow.columns.version=Vers\u00e3o
-UpdateWindow.columns.size=Tamanho
-UpdateWindow.cancel=Cancelar
-UpdateWindow.quit=Sair
-UpdateWindow.close=Fechar
-UpdateWindow.ok=Atualizar
-UpdateWindow.restart=Reiniciar
-UpdateWindow.status.downloading=Baixando
-UpdateWindow.status.done=Pronto
-UpdateWindow.status.failed=Falha
-UpdateWindow.status.restartNeeded=Reiniciar ser\u00e1 necess\u00e1rio!
-ConfigView.pluginlist.broken=Quebrado
-ConfigView.pluginlist.whereToPut=Colocar quaisquer plugins espec\u00edficos-para-o-usu\u00e1rio em seu pr\u00f3prio diret\u00f3rio:
-ConfigView.pluginlist.whereToPutOr=Para plugins compartilhados usar:
-MainWindow.statusText.checking=Procurando por Atualiza\u00e7\u00f5es
-TableColumn.header.OnlyCDing4=S\u00f3FazendoSeed4
-TableColumn.header.OnlyCDing4.info=Quantia de tempo que o torrent esteve fazendo seed. Exclui o tempo que o torrent estava baixando (e fazendo seed).
-UpdateWindow.status.restartMaybeNeeded=Pode ser necess\u00e1rio reiniciar
-ConfigView.pluginlist.shared=compartilhado
-PeersView.host=Nome do Servidor
-PeersView.host.info=O nome do servidor do peer, quando dispon\u00edvel (pode afetar a performance)
-MainWindow.menu.help.whatsnew=O que h\u00e1 de novo?
-ConfigView.label.checkonstart=Procurar pela \u00faltima vers\u00e3o quando o Vuze iniciar
-ConfigView.label.periodiccheck=Procurar pela \u00faltima vers\u00e3o periodicamente
-ConfigView.label.opendialog=Abrir automaticamente o Assistente de Atualiza\u00e7\u00e3o quando uma atualiza\u00e7\u00e3o estiver dispon\u00edvel
-MainWindow.updateavail=Clique aqui para atualiza\u00e7\u00f5es
-MainWindow.status.unofficialversion=Beta do Vuze
-MainWindow.status.latestversionunchecked=Verifica\u00e7\u00e3o de vers\u00e3o desativada
-GeneralView.label.updatein.stopped=Parado
-StartStopRules.menu.viewDebug=Ver Informa\u00e7\u00f5es de Debug
-ConfigView.section.style.doNotUseGB=N\u00e3o usar a unidade GB
-ConfigView.section.style.doNotUseGB.tooltip=Se marcado, o Vuze continuar\u00e1 a usar MB mesmo para tamanhos maiores do que 1024MB
-MainWindow.menu.help.plugins=Plugins
-ConfigView.section.plugins.TrackerWeb=Web Tracker
-ConfigView.section.tracker.enablecategories=Separar os torrents por categoria
-health.explain.share=significa que o torrent ou est\u00e1 hospedado ou publicado
-ConfigView.section.tracker.createcert=Criar certificado auto-assinado
-ConfigView.section.tracker.createbutton=Criar
-security.certcreate.title=Criar um Certificado Auto-Assinado
-security.certcreate.intro=Este di\u00e1logo permite a voc\u00ea criar um certificado auto-assinado
-security.certcreate.alias=Apelido
-security.certcreate.strength=For\u00e7a
-security.certcreate.firstlastname=Primeiro e \u00faltimo nome
-security.certcreate.orgunit=Unidade Organizacional
-security.certcreate.org=Organiza\u00e7\u00e3o
-security.certcreate.city=Cidade ou Localidade
-security.certcreate.state=Estado ou Prov\u00edncia
-security.certcreate.country=C\u00f3digo do pa\u00eds com duas letras
-security.certcreate.ok=Criar
-security.certcreate.cancel=Cancelar
-security.certcreate.createok=Certificado criado com sucesso
-security.certcreate.createfail=Cria\u00e7\u00e3o do certificado falhou
-ConfigView.section.plugins.webui=Interface Swing Web
-ConfigView.section.plugins.xml_http_if=Interface XML/HTTP
-webui.passwordenable=Ativar senha
-webui.user=Nome de usu\u00e1rio
-webui.password=Senha
-webui.port=Porta (*)
-webui.protocol=Protocolo (*)
-webui.homepage=Home Page (*)
-webui.rootdir=Diret\u00f3rio Raiz (*)
-webui.rootres=Recurso Raiz (*)
-webui.mode=Modo (*)
-webui.mode.info=O modo pode ser\n\t"full"\t= todas as opera\u00e7\u00f5es dispon\u00edveis (padr\u00e3o)\n\t"view"\t= ver apenas (mas pode atualizar a freq\u00fc\u00eancia de atualiza\u00e7\u00e3o)
-webui.access=Accesso (*)
-webui.access.info=O acesso pode ser\n\t"local"\t= significando que apenas a m\u00e1quina local pode conectar-se\n\t"all"\t= acesso irrestrito (default)\n\tIP\t= e.x. 192.168.0.2\t\t\tapenas um IP\n\tIP1-IP2\t= e.x. 192.168.0.1-192.168.0.255\tfaixa de IP inclusiva
-GeneralView.label.maxdownloadspeed=Limite de Down
-Security.keystore.corrupt=Keystore '%1' falhou ao carregar, por favor apague-a e recrie/re-importe os certificados
-Security.keystore.empty=O keystore est\u00e1 vazio. Por favor, crie um certificado auto-assinado (veja Ferramentas->Op\u00e7\u00f5es->Seguran\u00e7a) ou importe um certificado existente para '%1'
-GeneralView.label.maxdownloadspeed.tooltip=Velocidade M\u00e1xima de Download [0: ilimitada]
-upnp.enable=Ativar UPnP
-upnp.info=Universal Plug and Play (UPnP) permite o mapeamento autom\u00e1tico de portas nos roteadores com UPnP ativado.
-upnp.mapping.dataport=Porta de Entrada dos Dados do Peer
-upnp.mapping.tcptrackerport=Porta do Tracker TCP
-upnp.mapping.udptrackerport=Porta do Tracker UDP
-upnp.alert.differenthost=UPnP: O Mapeamento '%1' foi reservado por '%2' - por favor selecione uma porta\tdiferente
-upnp.alert.mappingok=UPnP: Mapeamento '%1' estabelecido
-upnp.alert.mappingfailed=UPnP: Falha no mapeamento '%1'
-upnp.alertsuccess=Relatar mapeamentos bem-sucedidos
-upnp.alert.lostdevice=UPnP: Conex\u00e3o com o servi\u00e7o '%1' no dispositivo UPnP '%2' perdida
-upnp.grabports=Mapear portas mesmo se possu\u00eddas por outro computador
-upnp.refresh.label=Atualizar os mapeamentos
-upnp.refresh.button=Atualizar
-upnp.alert.mappinggrabbed=UPnP: Mapeamento '%1' estabelecido - obtido de '%2'
-upnp.mapping.tcpssltrackerport=Porta do Tracker TCP SSL
-upnp.alertothermappings=Relatar portas possu\u00eddas por outros computadores
-upnp.alertdeviceproblems=Relatar problemas com o dispositivo UPnP
-upnp.trace_to_log=Informa\u00e7\u00e3o de debug completa da sa\u00edda de dados no log
-upnp.wiki_link=P\u00e1gina do wiki do Vuze sobre o UPnP
-upnp.refresh_mappings_on_bad_nat=Automaticamente atualizar os mapeamentos quando o status do NAT \u00e9 "firewalled"
-ConfigView.pluginlist.coreplugins=Os seguintes plugins embutidos est\u00e3o carregados:
-Peers.column.DLedFromOthers=De Outros
-Peers.column.DLedFromOthers.info=Quantidade de dados recebidos de outros enquanto conectados a voc\u00ea
-Peers.column.UpDownRatio.info=A Propor\u00e7\u00e3o "Enviados : Baixados" do Peer
-Peers.column.UpRatio=Propor\u00e7\u00e3o de Upload
-Peers.column.UpRatio.info=A propor\u00e7\u00e3o "Enviar por voc\u00ea : Enviado por outros" do Peer
-upnp.releasemappings=Liberar os mapeamentos ao fechar
-webui.upnpenable=Ativar UPnP para esta porta (*)
-ConfigView.section.file.friendly.hashchecking=Verifica\u00e7\u00e3o de hash amig\u00e1vel
-ConfigView.section.file.friendly.hashchecking.tooltip=Um levemente mais lento, mais muito menos stressante no cpu/sistema, modo de checagem de hash por peda\u00e7o.
-ConfigView.section.tracker.seedretention=M\u00e1ximo de seeds retidos por torrent [0: ilimitados]
-ConfigView.section.tracker.seedretention.info=Nota: As estat\u00edsticas de upload ser\u00e3o perdidas para seeds n\u00e3o retidos
-ConfigView.section.tracker.port=Ativar tracker na porta HTTP
-ConfigView.section.tracker.sslport=Ativar tracker na porta HTTPS
-ConfigView.section.tracker.publicenable.info=Isto permite que outros criem torrents que usem o seu tracker\nsem que voc\u00ea os hospede/publique
-Button.clear=Limpar
-MainWindow.IPs.tooltip=\u00daltima atualiza\u00e7\u00e3o da lista de filtros: %1\nTotal de Filtros IP na lista - N\u00ba de IPs bloqueados/banidos/ruins nesta sess\u00e3o.\nClique duas vezes para detalhes.
-ConfigView.section.ipfilter.list.banned=foi banido
-ConfigView.section.ipfilter.list.baddata=enviou dados ruins: ocorr\u00eancias = 
-Button.reset=Resetar
-ConfigView.section.ipfilter.bannedinfo=IPs que enviaram dados ruins - banidos se os limites excederam
-ConfigView.section.ipfilter.blockedinfo=IPs que foram bloqueados pelos filtros de IP
-download.removerules.name=Regras de Remo\u00e7\u00e3o
-download.removerules.unauthorised.info=Torrents n\u00e3o-autorizados s\u00e3o aqueles nos quais a resposta ao an\u00fancio cont\u00e9m "n\u00e3o-autorizado" ou "desautorizado" na "falha na resposta"
-download.removerules.unauthorised=Remover torrents n\u00e3o-autorizados automaticamente
-download.removerules.unauthorised.seedingonly=\tApenas se ficar de seed
-download.removerules.removed.ok=Remo\u00e7\u00e3o autom\u00e1tica do torrent '%1' bem-sucedida. Isto foi causado pelas regras de remo\u00e7\u00e3o de torrents
-download.removerules.updatetorrents=Remover os torrents de atualiza\u00e7\u00e3o conforme a multid\u00e3o requerir
-ConfigView.label.defaultstarttorrentsstopped=Por padr\u00e3o adicionar novos torrents no estado parado
-ConfigView.section.server.enableudp=Ativar o protocolo do cliente tracker UDP.
-upnp.mapping.dataportudp=Porta do cliente tracker UDP
-ConfigView.section.file.decoder.showlax=Mostrar menos codifica\u00e7\u00f5es
-ConfigView.section.file.decoder.showall=Considerar todas as codifica\u00e7\u00f5es poss\u00edveis
-MainWindow.status.updowndetails.tooltip=Detalhes da velocidade de Download/Upload\nClique com o bot\u00e3o direito para mudar, clique 2 vezes para abrir as estat\u00edsticas
-TrackerClient.announce.warningmessage=O tracker '%1' retornou o aviso '%2'
-ConfigView.section.tracker.natcheckenable=Verifica a conectividade da 'porta de entrada de dados' e reporta as falhas para os peers
-ConfigView.section.tracker.publishenabledetails=Publicar todos os detalhes do torrent
-ConfigView.section.tracker.publishenablepeerdetails=Publica os detalhes do peer
-MyTrackerView.badnat=NAT Ruim
-MyTrackerView.badnat.info=Seeds/Peers que falharam a uma checagem do NAT, se ativados
-ConfigView.section.tracker.natchecktimeout=Verifica o esgotamento do tempo (segs)
-ConfigView.section.file.perf.cache.enable=Ativar cache de disco
-ConfigView.section.file.perf.cache.size=Tamanho do cache em %1
-MainWindow.menu.transfers=T&ransfer\u00eancias
-MainWindow.menu.transfers.startalltransfers=C&ome\u00e7ar Todos
-MainWindow.menu.transfers.stopalltransfers=P&arar Todos
-MainWindow.menu.transfers.pausetransfers=&Pausar
-MainWindow.menu.transfers.resumetransfers=&Resumir
-ConfigView.label.experimental.osx.kernel.panic.fix=Corre\u00e7\u00e3o experimental para os p\u00e2nicos do kernel em sistemas dual-cpu OSX [requer reiniciar]
-SystemTray.menu.pausetransfers=Pausar Transfer\u00eancias
-SystemTray.menu.resumetransfers=Resumir Transfer\u00eancias
-ConfigView.section.file.truncate.too.large=Cortar os arquivos existentes que s\u00e3o muito grandes
-ConfigView.section.file.perf.cache.trace=Rastrear opera\u00e7\u00f5es de cache para fins de diagn\u00f3stico
-ConfigView.section.interface.enabletray=Ativar o Tray do sistema [requer reiniciar]
-PeerManager.status.error=Erro
-Stats.title.full=Estat\u00edsticas
-TransferStatsView.title.full=Transfer\u00eancias
-CacheView.general.size=Total
-CacheView.general.inUse=Em Uso
-CacheView.general.title=Info sobre o Cache
-CacheView.reads.title=Leituras E/S
-CacheView.reads.fromFile=Do Arquivo
-CacheView.reads.fromCache=Do Cache
-CacheView.reads.hits=Acertos
-CacheView.writes.title=Escritas E/S
-CacheView.writes.toCache=Para o Cache
-CacheView.writes.toFile=Para o Arquivo
-CacheView.writes.hits=Salvos
-CacheView.speeds.title=Taxa de Dados
-CacheView.speeds.reads=Leituras
-CacheView.speeds.writes=Escritas
-CacheView.speeds.fromCache=Do/Para o Cache
-CacheView.speeds.fromFile=Do/Para o Arquivo
-CacheView.reads.amount=Quantidade
-CacheView.reads.avgsize=Tamanho M\u00e9dio
-openUrl.referrer=URL da p\u00e1gina de refer\u00eancia:
-openUrl.referrer.info=Requerido apenas para sites da web que os pe\u00e7am
-ConfigView.label.maxuploadspeedseeding=Alternar a taxa apenas quando ficando de seed
-ConfigView.label.transfer.ignorepeerports=Ignorar peers com estas portas de dados (';' separadas, ex: 0;25;100-200)
-ConfigView.section.proxy.enable_socks.peer=Ativar o proxying das comunica\u00e7\u00f5es com os peers (apenas para conex\u00f5es de sa\u00edda) [requer reiniciar]
-ConfigView.section.proxy.peer.informtracker=Informar a limita\u00e7\u00e3o ao tracker
-ConfigView.section.proxy.socks.version=Vers\u00e3o do SOCKS
-PiecesView.legend.written=Escritos
-PiecesView.legend.requested=Requeridos
-PiecesView.legend.downloaded=Baixados, escrita pendente
-PiecesView.legend.incache=Dados est\u00e3o no Cache
-PiecesView.typeItem.0=Lento
-PiecesView.typeItem.1=R\u00e1pido
-PiecesView.type=Tipo
-Security.jar.tools_not_found=Assinatura JAR falhou - 'tools.jar' n\u00e3o encontrado em %1. Veja Ferramentas->Op\u00e7\u00f5es->Seguran\u00e7a para detalhes.
-Security.jar.signfail=Assinatura JAR falhou - %1
-ConfigView.section.security.toolsinfo=Arquivos JAR assinados s\u00e3o usados para ajudar alguns plugins, por exemplo o Swing Web Interface (quando configurado para faz\u00ea-lo).\nPara assinar arquivos JAR \u00e9 necess\u00e1rio ter accesso ao arquivo 'tools.jar' que vem com a instala\u00e7\u00e3o do Sun JDK (n\u00e3o do JRE).\nSe voc\u00ea s\u00f3 tiver instalado o JRE ent\u00e3o por favor instale o JDK.\nNormalmente o Vuze pode achar o arquivo para voc\u00ea. Entretanto, se isto falhar [...]
-ConfigView.section.security.toolsdir=Diret\u00f3rio contendo o arquivo 'tools.jar'
-ConfigView.section.security.choosetoolssavedir=Selecione a pasta contendo o arquivo 'tools.jar'
-ConfigView.section.proxy.peer.same=Usar as mesmas configura\u00e7\u00f5es de proxy para o tracker e para as comunica\u00e7\u00f5es com os peers
-ConfigView.section.connection.network.max.simultaneous.connect.attempts=M\u00e1x. de tentativas de conex\u00f5es de sa\u00edda simult\u00e2neas
-ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=N\u00famero m\u00e1ximo de novos estabelecimentos de conex\u00f5es de sa\u00edda que o Vuze deve tentar a qualquer tempo dado.\nNOTA: O Service Pack 2 do Windows XP (SP2) imp\u00f5e um limite para o sistema de apenas 10 tentativas para conectar simult\u00e2neas.\nO valor padr\u00e3o \u00e9 8.
-ConfigView.section.file.perf.cache.size.explain=O cache \u00e9 usado para reduzir as leituras do/escritas ao disco. A menos que voc\u00ea esteja usando a op\u00e7\u00e3o java '-XX:MaxDirectMemorySize' para explicitamente definir a mem\u00f3ria dispon\u00edvel para ser o cache e a rede IO usar, voc\u00ea deve manter esse valor a pelo menos %1 abaixo do tamanho m\u00e1ximo do seu VM. O tamanho atual m\u00e1ximo do VM \u00e9 %2. Para instru\u00e7\u00f5es sobre como mudar isto, veja MemoryUs [...]
-MyTorrentsView.menu.setSpeed.unlimit=Sem limite
-MyTorrentsView.menu.setSpeed.unlimited=Ilimitado
-MyTorrentsView.menu.setSpeed.disable=Desativar Upload
-MyTorrentsView.menu.setSpeed.disabled=Desativado
-MyTorrentsView.menu.setSpeed.in=entrada
-MyTorrentsView.menu.setSpeed.slots=slots de
-GeneralView.label.maxuploadspeed=Limite de Up
-GeneralView.label.maxuploadspeed.tooltip=velocidade m\u00e1x. de upload [0 : ilimitada]
-MyTorrents.items.UpSpeedLimit.disabled=Sem upload
-MyTorrents.items.UpSpeedLimit.unlimited=Ilimitado
-TableColumn.header.maxupspeed=M\u00e1x de Velocidadde de Up
-TableColumn.header.maxupspeed.info=M\u00e1x de Velocidade de Upload por torrent
-ConfigView.section.file.perf.cache.enable.write=Armazenar os dados de download no cache para reduzir as escritas em disco e tamb\u00e9m diminuir as leituras do disco requeridas para a checagem dos peda\u00e7os
-ConfigView.section.file.perf.cache.enable.read=Realizar leituras adiantadas para reduzir as leituras do disco enquanto faz upload
-ConfigView.section.tracker.separatepeerids=Usar diferentes identidades de peer para o tracker e para a comunica\u00e7\u00e3o de dados
-ConfigView.section.tracker.separatepeerids.info=Aumenta a anonimidade se estiver baixando/enviando anonimamente\nenquanto estiver usando um conex\u00e3o com o tracker n\u00e3o-an\u00f4nima 
-ConfigView.section.interface.wavlocation=Localiza\u00e7\u00e3o do arquivo .wav
-ConfigView.section.interface.wavlocation.info=Selecione o arquivo .wav ou deixe em branco para o som padr\u00e3o
-ConfigView.section.tracker.server=Servidor
-ConfigView.section.tracker.client=Cliente
-ConfigView.section.tracker.client.connecttimeout=A conex\u00e3o expira em (segs)
-ConfigView.section.tracker.client.readtimeout=A leitura expira em (secs)
-MainWindow.menu.tools=&Ferramentas
-FilesView.path=Caminho
-FilesView.fullpath=Mostrar Caminho Completo
-FilesView.remaining=Peda\u00e7os Restantes
-TableColumn.header.trackername=Nome do Tracker
-TableColumn.header.trackername.info=Nome do tracker baseado na URL de an\u00fancio
-ConfigView.group.override=N\u00e3o Levar as Op\u00e7\u00f5es em Conta
-ConfigView.section.file.perf.cache.notsmallerthan=N\u00e3o colocar no cache arquivos menores que isto (em %1)
-PeersView.menu.blockupload=Bloquear Upload
-PeersView.menu.kickandban=Chutar e Banir
-PeersView.menu.kickandban.reason=Peer banido manualmente
-PeersView.state=Estado
-PeersView.state.info=Estado da conex\u00e3o com o peer
-PeersView.state.pending=Pendente
-PeersView.state.connecting=Conectando
-PeersView.state.handshake=Esperando pelo handshake
-PeersView.state.established=Completamente estabelecida
-ConfigView.section.tracker.processinglimits=Limites de processamento
-ConfigView.section.tracker.maxgettime=Tempo m\u00e1x. para processamento GET (segundos) [0:ilimitado]
-ConfigView.section.tracker.maxgettime.info=Usado para an\u00fancio e limpezas
-ConfigView.section.tracker.maxposttimemultiplier=Multiplicador de tempo para processamento POST [0:ilimitado]
-ConfigView.section.tracker.maxposttimemultiplier.info=Usado para formar submiss\u00f5es e uploads
-ConfigView.section.tracker.maxthreads=M\u00e1x. de pedidos coincidentes
-DownloadManager.error.operationcancancelled=Opera\u00e7\u00e3o cancelada
-Torrent.create.progress.cancelled=Opera\u00e7\u00e3o cancelada
-sharing.progress.cancel=Cancelar
-wizard.maketorrents.autoopen=Abrir o torrent para ficar de seed quando completo
-ConfigView.section.sharing.rescanenable=Ativar re-escaneamento peri\u00f3dico dos compartilhados por mudan\u00e7as
-ConfigView.section.sharing.rescanperiod=Per\u00edodo de re-escaneamento (segs)
-ConfigView.section.connection.advanced=Configura\u00e7\u00f5es de Rede Avan\u00e7adas
-ConfigView.section.connection.advanced.url=http://azureuswiki.com/index.php/AdvancedNetworkSettings
-ConfigView.section.connection.advanced.mtu=Unidade de Transmiss\u00e3o M\u00e1xima da Linha (MTU)
-ConfigView.section.connection.advanced.mtu.tooltip=Tamanho m\u00e1ximo de um pacote que pode ser transferido em um frame na rede.\nO Vuze usa MTU-40 (MSS) para otimiza\u00e7\u00f5es de packet-payload de upload.\nValores recomendados:\n  576 - Conex\u00f5es Dial-up\n1492 - Conex\u00f5es de banda larga PPPoE\n1500 - conex\u00f5es de banda larga a Cabo,Ethernet e DSL 
-ConfigView.section.connection.advanced.SO_RCVBUF=Tamanho do Socket SO_RCVBUF [0: usar o padr\u00e3o do SO]
-ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Define o valor do socket padr\u00e3o SO_RCVBUF (em bytes), i.e. tamanho e escala da janela de recebimento TCP.\nO Vuze deixa isto n\u00e3o definido por padr\u00e3o, significando que os padr\u00f5es para o SO b\u00e1sico s\u00e3o usados.\nNOTA: O linux dobra o valor dado.
-ConfigView.section.connection.advanced.SO_SNDBUF=Tamanho do Socket SO_SNDBUF [0: usar o padr\u00e3o do SO]
-ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Define o valor do socket padr\u00e3o SO_SNDBUF (em bytes), i.e. o tamanho da janela de envio TCP.\nO Vuze deixa isto n\u00e3o definido por padr\u00e3o, siginificando que os padr\u00f5es para o SO b\u00e1sico s\u00e3o usados.\nNOTA: O linux dobra o valor dado.
-ConfigView.section.connection.advanced.IPDiffServ=Valor do DiffServ do pacote de sa\u00edda (campo do TOS)
-ConfigView.section.connection.advanced.IPDiffServ.tooltip=Define a parte do DiffServ do campo do tipo-de-servi\u00e7o (TOS) no cabe\u00e7alho do IP para os pacotes de sa\u00edda.\nValores hexadecimais podem ser especificados prefixando eles com '0x', ex: 0x10.\nO Vuze deixa isto n\u00e3o definido por padr\u00e3o, significando que os padr\u00f5es para o SO b\u00e1sico s\u00e3o usados.\nNOTA: As implementa\u00e7\u00e3o da rede b\u00e1sica pode ignorar este valor, ent\u00e3o esta op\u00e7\u [...]
-TableColumn.header.seed_to_peer_ratio=Propor\u00e7\u00e3oSeed2Peer
-TableColumn.header.seed_to_peer_ratio.info=Total da propor\u00e7a\u00f5 de seeds para peers na multid\u00e3o 
-PeersView.connected_time=Tempo Conectado
-PeersView.connected_time.info=Tempo total que est\u00e1 conectado com o peer
-TableColumn.header.maxdownspeed=M\u00e1x de Velocidade de Down
-TableColumn.header.maxdownspeed.info=M\u00e1x de Velocidade de Download por torrent
-PeersGraphicView.title.full=Multid\u00e3o
-ConfigView.section.tracker.passwordwebhttpsonly=S\u00f3 permitir o acesso via HTTPS
-TableColumn.header.torrentpath=Local do Torrent
-TableColumn.header.torrentpath.info=Local do Torrent no disco
-ConfigView.section.sharing.torrentcomment=Coment\u00e1rio para torrents gerados
-ConfigView.label.copyanddeleteratherthanmove=Copia e ent\u00e3o apaga os dados originais en vez de mov\u00ea-los em uma opera\u00e7\u00e3o - pode ajudar a evitar a perda de dados em alguns sistemas de arquivos
-ConfigView.label.openstatsonstart=Abrir as estat\u00edsticas ao iniciar
-swt.install.window.title=Instalador de Plugins do Vuze
-swt.install.window.ok=Instalar
-swt.install.window.header=Os seguintes componentes foram selecionados para a instala\u00e7\u00e3o :
-swt.uninstall.window.title=Removedor de Plugins do Vuze
-swt.uninstall.window.ok=Remover
-swt.uninstall.window.header=Os seguintes componentes foram selecionados para a remo\u00e7\u00e3o :
-installPluginsWizard.title=Instalar Plugins
-installPluginsWizard.mode.title=Por favor, escolha um m\u00e9todo de instala\u00e7\u00e3o
-installPluginsWizard.mode.list=Pela lista do sourceforge.net
-installPluginsWizard.list.title=Lista dos Plugins Instal\u00e1veis
-installPluginsWizard.list.loading=Por favor, espere enquanto a lista de plugins \u00e9 carregada.
-installPluginsWizard.list.loaded=Por favor, escolha os plugins que voc\u00ea quer instalar.
-installPluginsWizard.list.name=Nome
-installPluginsWizard.list.version=Vers\u00e3o
-installPluginsWizard.list.description=Descri\u00e7\u00e3o do plugin
-installPluginsWizard.finish.title=Instala\u00e7\u00e3o em Progresso
-installPluginsWizard.finish.explanation=Os plugins selecionados ser\u00e3o instalados usando o Assistente de Atualiza\u00e7\u00e3o.\n\nPor favor seja paciente, isto pode demorar um pouco para aparecer.\n\nPara um relat\u00f3rio do progresso, clique duas vezes a esquerda da barra de status.
-installPluginsWizard.details.loading=Carregando detalhes, aguarde por favor...
-installPluginsWizard.mode.file=Por arquivo
-installPluginsWizard.installMode.title=Por favor, escolha o tipo de instala\u00e7\u00e3o
-installPluginsWizard.installMode.user=Instalar o(s) plugin(s) somente para voc\u00ea
-installPluginsWizard.installMode.shared=Instalar o(s) plugin(s) para todos os usu\u00e1rios
-installPluginsWizard.file.title=Por favor procure o plugin que voc\u00ea quer instalar
-installPluginsWizard.file.file=Arquivo :
-installPluginsWizard.file.invalidfile=O arquivo n\u00e3o \u00e9 um plugin v\u00e1lido do Vuze.
-installPluginsWizard.file.no_such_file=Nenhum arquivo existe com o nome dado.
-installPluginsWizard.file.browse=Navegar...
-uninstallPluginsWizard.title=Desinstalar Plugins
-uninstallPluginsWizard.list.title=Lista dos Plugins Instalados
-uninstallPluginsWizard.list.loaded=Por favor, escolha os plugins que voc\u00ea quer desinstalar.
-installPluginsWizard.list.nullversion=N\u00ba da Vers\u00e3o
-uninstallPluginsWizard.finish.title=Desinstala\u00e7\u00e3o em Progresso
-uninstallPluginsWizard.finish.explanation=Os plugins selecionados ser\u00e3o desinstalados usando o Assistente de Atualiza\u00e7\u00e3o.
-MainWindow.menu.plugins.installPlugins=Assistente de Instala\u00e7\u00e3o...
-MainWindow.menu.plugins.uninstallPlugins=Assistente de Desinstala\u00e7\u00e3o...
-ConfigView.section.ipfilter.totalIPs=%1 IPs bloqueados no total, que s\u00e3o %2 da internet.
-update.instance.install=Checando a Instala\u00e7\u00e3o
-update.instance.uninstall=Checando a Desinstala\u00e7\u00e3o
-update.instance.update=Checando por Atualiza\u00e7\u00f5es
-MainWindow.status.update.tooltip=Duplo clique para informa\u00e7\u00e3o sobre o progresso
-updater.progress.window.title=Tarefas de Instala\u00e7\u00e3o Atuais
-updater.progress.window.info=Pressione 'Abortar' para terminar todas tarefas pendentes
-Button.abort=Abortar
-ConfigView.section.ipfilter.enablebanning=Bloquear peers que consistentemente mandam dados ruins
-Network.alert.acceptfail=Muitas falhas sucessivas ocorridas na porta %1, %2 - processamento abandonado. Por favor, cheque as configura\u00e7\u00f5es do firewall para esta porta para garantir que est\u00e1 habilitada para receber conex\u00f5es.
-MyShares.column.category=Categoria
-UpdateWindow.restartLater=Reiniciar Mais Tarde
-MainWindow.menu.file.restart=Reiniciar o Vuze
-MainWindow.dialog.restartconfirmation.title=Reiniciar o Vuze?
-MainWindow.dialog.restartconfirmation.text=Voc\u00ea realmente quer reiniciar o Vuze?
-ConfigView.label.prioritizemostcompletedfiles=Priorizar mais os arquivos de alta prioridade de acordo com a % completada e o tamanho do arquivo
-splash.plugin.init=Inicializando o Plugin: 
-splash.plugin.UIinit=Inicializando a GUI do Plugin:  %1
-ConfigView.section.style.osx_small_fonts=Usar fontes pequenas [requer reiniciar]
-ConfigView.section.tracker.tcpnonblocking=Usar I/O n\u00e3o-bloqueador para processamento do tracker TCP. Selecionar esta op\u00e7\u00e3o requer que o tracker seja executado numa porta alternativa. Experimental!
-ConfigView.section.tracker.nonblocking=Op\u00e7\u00f5es n\u00e3o-bloqueadoras
-ConfigView.section.tracker.nonblockingconcmax=M\u00e1x. de conex\u00f5es coincidentes [0: ilimitadas]
-MyTorrentsView.menu.exportmenu=Exportar\t\t\t\t\t\t\t\t\t\t\t\t\t 
-ConfigView.section.tracker.client.scrapeinfo=Desativar o scraping impedir\u00e1 que muitas das regras das filas dos torrents de funcionarem como elas confiam na informa\u00e7\u00e3o da multid\u00e3o obtida pelos trackers de scraping.
-ConfigView.section.tracker.client.scrapeenable=Ativar scraping
-ConfigView.section.tracker.client.scrapestoppedenable=Scrape torrents que n\u00e3o est\u00e3o rodando
-Scrape.status.disabled=Scrape Desativado
-MyTorrentsView.menu.explore=Mostrar Arquivo
-MyTorrentsView.menu.explore._mac=Mostrar no Descobridor
-MyTorrentsView.menu.explore._windows=Mostrar no Explorer
-wizard.maketorrents.autohost=Hospedar o torrent no tracker embutido
-ConfigView.label.overrideip=N\u00e3o levar em conta o(s) IP(s) de an\u00fancio do tracker - semi-v\u00edrgula os separa se h\u00e1 mais de um para diferentes redes
-ConfigView.label.overrideip.tooltip=Informar o tracker de diferentes endere\u00e7o(s) de IP do que aquele de onde os pacotes de sa\u00edda vem. Deixe em branco para n\u00e3o usar a op\u00e7\u00e3o.
-ConfigView.section.connection.group.networks=Redes
-ConfigView.section.connection.group.networks.info=Selecione as redes padr\u00e3o permitidas para a transmiss\u00e3o de dados peer-peer
-ConfigView.section.connection.networks.prompt=Alertar para a sele\u00e7\u00e3o quando um download com um tracker an\u00f4nimo \u00e9 adicionado
-ConfigView.section.connection.networks.Public=Rede de IP p\u00fablica (n\u00e3o an\u00f4nima)
-ConfigView.section.connection.networks.I2P=Rede I2P
-ConfigView.section.connection.networks.Tor=A rede do Onion Router (Tor)
-TableColumn.header.networks=Redes
-TableColumn.header.networks.info=Redes permitidas para a comunica\u00e7\u00e3o de dados peer-peer
-Scrape.status.networkdisabled=Rede n\u00e3o ativada
-ConfigView.section.tracker.server.group.networks=Redes
-ConfigView.section.tracker.server.group.networks.info=Selecione as redes para as quais o tracker aceitar\u00e1 peers
-window.networkselection.title=Sele\u00e7\u00e3o de Rede
-window.networkselection.info=O torrent listado abaixo tem tracker(s) que suportam as seguintes redes.\nSelecione aqueles a ativar para a comunica\u00e7\u00e3o com o tracker e peer.\nSe \u00e9 um tracker an\u00f4nimo que suporta clientes p\u00fablicos ative ambas as redes an\u00f4nima e p\u00fablica.\nAtivar a rede p\u00fablica tem a consequ\u00eancia \u00f3bvia de remover a anonimidade!
-plugins.basicview.clear=Limpar
-ConfigView.section.connection.group.peersources=Fontes Peer
-ConfigView.section.connection.group.peersources.info=Selecione as fontes padr\u00e3o permitidas para a conex\u00e3o com o peer
-ConfigView.section.connection.peersource.Tracker=De um tracker
-ConfigView.section.connection.peersource.DHT=Tracking descentralizado
-ConfigView.section.connection.peersource.PeerExchange=Supridas por outro peer
-ConfigView.section.connection.peersource.Plugin=Adicionadas por um plugin
-ConfigView.section.connection.peersource.Incoming=Conex\u00e3o de entrada
-PeersView.source=Fonte
-PeersView.source.info=A fonte deste peer
-TableColumn.header.peersources=Fontes Peer
-TableColumn.header.peersources.info=Fontes peer permitidas para o estabelecimento das conex\u00f5es com peers
-wizard.tracker.dht=Decentralizado (s\u00f3 clientes Vuze)
-MyTorrentsView.menu.advancedmenu=Avan\u00e7ado
-MyTorrentsView.menu.networks=Redes
-MyTorrentsView.menu.peersource=Fontes Peer
-ConfigView.section.sharing.permitdht=Permitir tracking descentralizado quando o tracker est\u00e1 indispon\u00edvel
-ConfigView.section.sharing.protocol=Protocolo para recursos compartilhados
-PeersView.Messaging=Enviando Mensagens
-PeersView.Messaging.info=Suporta o envio de mensagens avana\u00e7ado API.
-ConfigView.label.queue.newseedsmovetop=Mover torrents completados recentemente para a frente da lista de seeding
-ConfigView.label.seeding.firstPriority.ignore.info=Esteja ciente que usar estas regras pode resultar em parar um torrent\nt\u00e3o r\u00e1pido quanto o download terminar.
-ConfigView.label.seeding.firstPriority.ignore=Ignorar as regras de Primeira Prioridade acima para:
-ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents com uma propor\u00e7\u00e3o de Seeds para Peers de
-ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents com 0 Peers
-ConfigView.section.tracker.sendjavaversionandos=Enviar a vers\u00e3o do Java e o nome do SO
-MagnetPlugin.contextmenu.exporturi=Copiar a URI do Magnet para a \u00c1rea de Transfer\u00eancia
-ConfigView.section.plugins.dht=Base de Dados Distribu\u00edda
-dht.info=Este plugin suporta tracking descentralizado, entre outras coisas, - desativando-o reduzir\u00e1 a sua habilidade de baixar
-dht.enabled=Ativar a base de dados distribu\u00edda
-dht.portdefault=Usar a porta padr\u00e3o
-dht.port=Porta UDP para a base de dados
-dht.execute.command=Comando de diagn\u00f3stico
-dht.execute.info=Pressione para executar o comando
-dht.execute=Executar
-dht.logging=Ativar o rastreamento da atividade
-ConfigView.section.plugins.dhttracker=Tracker Distribu\u00eddo
-dhttracker.tracknormalwhenoffline=S\u00f3 rastrear torrents normais quando o tracker deles est\u00e1 indispon\u00edvel
-ConfigView.section.file.nativedelete._mac=Usar a Lixeira quando apagar os arquivos
-ConfigView.section.file.nativedelete._windows=Mover os arquivos apagados para o Recycle Bin
-ConfigView.section.logging.generatediagnostics=Gerar
-ConfigView.section.logging.netinfo=Gerar info sobre a rede
-ConfigView.section.logging.statsinfo=Gerar info das estat\u00edsticas
-ConfigView.section.logging.generatediagnostics.info=Gerar informa\u00e7\u00e3o de diagn\u00f3stico e copiar para a \u00e1rea de transfer\u00eancia e arquivo log, se configurado
-ConfigView.section.sharing.privatetorrent=Torrent privado - s\u00f3 aceitar peers do tracker
-MainWindow.menu.tools.nattest=&Teste do NAT / Firewall
-Button.apply=Aplicar
-Button.close=Fechar
-window.welcome.title=Bem-Vindo ao Vuze %1
-#file can be a URL or a path in the jar
-MainWindow.menu.help.releasenotes=Notas do Lan\u00e7amento
-dht.reseed.label=Normalmente ficar de seed de novo da Base de Dados Distribu\u00edda n\u00e3o \u00e9 necess\u00e1rio. Contudo, se o n\u00famero de contatos \u00e9 baixo, isto pode ser usado para a re-integra\u00e7\u00e3o.\nDeixe em branco para bootstrap off peers conectados ou insira o IP e porta para explicitamente bootstrap de um peer conhecido.
-dht.reseed.group=Ficar de seed de novo
-dht.reseed.ip=Endere\u00e7o IP
-dht.reseed.port=Porta
-dht.reseed=Ficar de seed de novo
-dht.reseed.info=Ficar de seed da base de dados de novo
-dht.diagnostics.group=Diagn\u00f3sticos
-DHTView.title.full=Base de Dados Distribu\u00edda
-DHTView.title.fullcvs=CVS da Base de Dados Distribu\u00edda
-DHTView.general.title=Geral
-DHTView.general.uptime=Tempo de Upload:
-DHTView.general.users=Usu\u00e1rios:
-DHTView.general.contacts=Contatos:
-DHTView.general.replacements=Substitui\u00e7\u00f5es:
-DHTView.general.live=Ao vivo:
-DHTView.general.unknown=Desconhecido:
-DHTView.general.dying=Morrendo:
-DHTView.transport.title=Detalhes do Transporte
-DHTView.transport.packets=Pacotes
-DHTView.transport.received=Recebidos
-DHTView.transport.sent=Enviados
-DHTView.transport.in=Entrou :
-DHTView.transport.out=Saiu :
-DHTView.operations.title=Detalhes da Opera\u00e7\u00e3o
-DHTView.operations.sent=Enviados
-DHTView.operations.failed=Falhou
-DHTView.operations.received=Recebidos
-DHTView.operations.findNode=Achar Node
-DHTView.operations.findValue=Achar Valor
-DHTView.operations.store=Armazenar
-DHTView.activity.title=Atividade
-DHTView.activity.status.true=Requisitado
-DHTView.activity.status.false=Rodando
-DHTView.activity.type=Tipo
-DHTView.activity.type.1=Get Interno
-DHTView.activity.type.2=Get Externo
-DHTView.activity.type.3=Put Interno
-DHTView.activity.type.4=Put Externo
-DHTView.activity.target=Alvo
-DHTView.activity.details=Detalhes
-DHTView.db.title=Base de Dados
-DHTView.db.keys=Teclas
-DHTView.db.values=Valores
-DHTView.db.direct=Direto
-DHTView.db.indirect=Indireto
-DHTView.db.divsize=Tamanho Div
-MainWindow.dht.status.tooltip=Quando a Base de Dados Distribu\u00edda est\u00e1 rodando isto mostra o n\u00ba estimado de usu\u00e1rios atualmente online
-MainWindow.dht.status.disabled=DHT Desativado
-MainWindow.dht.status.failed=O DHT Falhou
-MainWindow.dht.status.initializing=DHT Inicializando
-MainWindow.dht.status.users=%1 Usu\u00e1rios
-MainWindow.dht.status.unreachable=DHT Atr\u00e1s de Firewall
-MainWindow.dht.status.unreachabletooltip=Aparenta haver um problema com o mapeamento da porta UDP da Base de Dados Distribu\u00edda (NAT/firewall)
-MyTorrentsView.menu.setUpSpeed=Definir Velocidade de Upload
-MyTorrentsView.menu.setDownSpeed=Definir Velocidade de Download
-ConfigView.section.tracker.client.showwarnings=Mostrar mensagens de aviso reportadas pelos trackers
-dht.advanced=Ativar configura\u00e7\u00f5es avan\u00e7adas
-dht.advanced.group=Configura\u00e7\u00f5es avan\u00e7adas
-dht.advanced.label=S\u00f3 corrigir estes valores se voc\u00ea realmente sabe o que voc\u00ea est\u00e1 fazendo
-dht.override.ip=N\u00e3o levar em conta o endere\u00e7o IP externo
-ConfigView.section.logging.loggerenable=Ativar logging
-ConfigView.section.ipfilter.blockbanning=Banir um bloco de 256 endere\u00e7os quando pelo menos muitos no bloco forem banidos
-MyTrackerView.passive=Passivo
-TableColumn.header.swarm_average_speed=Velocidade M\u00e9dia da Multid\u00e3o
-TableColumn.header.swarm_average_speed.info=A velocidade m\u00e9dia dos peers na multid\u00e3o
-TableColumn.header.comment=Coment\u00e1rio
-TableColumn.header.comment.info=Coment\u00e1rio definido-pelo-usu\u00e1rio para o download
-TableColumn.header.commenticon=\u00cdcone do Coment\u00e1rio
-TableColumn.header.commenticon.info=Exibe o \u00edcone se o download tem um coment\u00e1rio definido-pelo-usu\u00e1rio
-MyTrackerView.category=Categoria
-MainWindow.menu.file.open.torrentfortracking=Arquivo Torrent... (Apenas Tracking)
-MyTrackerView.date_added=Adicionado
-ConfigView.section.tracker.portbackup=Fazer backup das portas (';' separadas)
-ConfigView.label.playfilespeech=Falar quando um arquivo est\u00e1 terminado
-ConfigView.label.playfilefinished=Tocar um som quando um arquivo est\u00e1 terminado
-ConfigView.label.backupconfigfiles=Fazer backup dos arquivos de configura\u00e7\u00e3o para prop\u00f3sitos de recupera\u00e7\u00e3o
-ConfigView.section.tracker.client.scrapesingleonly=Desativar agrega\u00e7\u00e3o de scrape por tracker (pode ajudar com os trackers que reportam os erros de 'URL muito longa' (414) ) 
-dht.ipfilter.log=Registrar as viola\u00e7\u00f5es do Filtro de IP
-ConfigView.label.seeding.addForSeedingDLCopyCount=Considerar para 'adicionar para ficar de seed' downloads que baixaram este n\u00famero de c\u00f3pias
-ActivityView.legend.limit=Taxa limite
-ActivityView.legend.achieved=Taxa obtida
-ActivityView.legend.overhead=Taxa elevada
-ActivityView.legend.peeraverage=M\u00e9dia
-ActivityView.legend.swarmaverage=M\u00e9dia da multid\u00e3o
-ActivityView.legend.trimmed=Arrumado (pontuado)
-MyTorrentsView.menu.movemenu=Mover Arquivos
-MyTorrentsView.menu.movedata=Mover Arquivos de Dados...
-MyTorrentsView.menu.movetorrent=Mover Arquivo Torrent...
-MyTorrentsView.menu.movedata.dialog=Escolher novo local
-DHTView.operations.data=Dados
-DHTView.general.reachable=Alcan\u00e7\u00e1vel:
-DHTView.general.rendezvous=Encontro:
-ConfigView.label.queue.maxactivetorrentswhenseeding=M\u00e1x. s\u00f3 quando ficando de seed [0:ilimitados]
-Views.plugins.IRC.title=IRC - Suporte T\u00e9cnico Online
-Formats.units.alot=Muito !!!
-ConfigView.section.ipfilter.persistblocking=Salvar detalhes dos IPs bloqueados durante os rein\u00edcios
-FilesView.menu.rename=Renomear ou Refazer o Alvo
-FilesView.menu.rename_only=Renomear
-FilesView.menu.retarget=Refazer o Alvo
-FilesView.rename.choose.path=Escolher arquivo novo ou existente
-FilesView.rename.choose.path.dir=Escolher diret\u00f3rio novo ou existente
-FilesView.rename.confirm.delete.title=Confirmar Exclus\u00e3o
-FilesView.rename.confirm.delete.text=Confirmar exclus\u00e3o do arquivo original '%1'
-FilesView.rename.filename.title=Renomea arquivo
-FilesView.rename.filename.text=Escolher um novo nome para o arquivo
-ConfigView.higher.mode.available=Mais op\u00e7\u00f5es est\u00e3o dispon\u00edveis em modos de usu\u00e1rios mais altos
-ConfigView.section.mode=Modo
-ConfigView.section.mode.title=Profici\u00eancia do Usu\u00e1rio
-ConfigView.section.mode.beginner=Iniciante
-ConfigView.section.mode.beginner.wiki.definitions=Vocabul\u00e1rio BitTorrent
-ConfigView.section.mode.intermediate=Intermedi\u00e1rio
-ConfigView.section.mode.intermediate.wiki.host=Hospedar Arquivos
-ConfigView.section.mode.intermediate.wiki.publish=Publicar Arquivos
-ConfigView.section.mode.advanced=Avan\u00e7ado
-ConfigView.section.mode.advanced.wiki.main=P\u00e1gina Principal do Wiki
-ConfigView.section.mode.beginner.text=Tudo que voc\u00ea precisa para baixar torrents.\nUse este modo se tudo que voc\u00ea quer \u00e9 gerenciar seus torrents.
-ConfigView.section.mode.intermediate.text=Acesso as fun\u00e7\u00f5es do tracker.\nUse este modo se voc\u00ea quer criar seu pr\u00f3prio tracker e hospedar/publicar seus arquivos.
-ConfigView.section.mode.advanced.text=Acesso as configura\u00e7\u00f5es de rede.\nUse este modo se voc\u00ea sabe o que MTU ou I/O n\u00e3o-bloqueadores s\u00e3o...
-Files.column.storagetype=Tipo de Armazenagem
-Files.column.fileext=Tipo
-FileItem.storage.compact=Compacta
-MessageBoxWindow.rememberdecision=Lembrar minha decis\u00e3o
-ConfigView.section.interface.cleardecisions=Limpar os di\u00e1logos de decis\u00e3o lembrados
-ConfigView.section.interface.cleardecisionsbutton=Limpar
-ConfigView.section.interface.cleartrackers=Limpar os trackers lembrados
-ConfigView.section.interface.cleartrackersbutton=Limpar
-ConfigView.section.interface.clearsavepaths=Limpar os caminhos para salvar recordados
-ConfigView.section.interface.clearsavepathsbutton=Limpar
-configureWizard.welcome.usermodes=Esta configura\u00e7\u00e3o de profici\u00eancia do usu\u00e1rio determinar\u00e1 o n\u00edvel das op\u00e7\u00f5es exibidas em Ferramentas > Op\u00e7\u00f5es. \u00c9 do seu melhor interesse defin\u00ed-la apropriadamente.
-FilesView.skip.confirm.delete.text=Cortar o arquivo '%1' para salvar espa\u00e7o?
-FilesView.rename.failed.title=Renomear/Refazer o Alvo falhou
-FilesView.rename.failed.text=A opera\u00e7\u00e3o falhou, provavelmente devido a sele\u00e7\u00e3o de alvo inv\u00e1lida
-diagnostics.log_found=O Vuze n\u00e3o fechou apropriadamente. Verifique por quaisquer <A HREF="%1">arquivos log de diagn\u00f3stico</A>. Tamb\u00e9m leia o artigo do wiki <A HREF="http://www.azureuswiki.com/index.php/Vuze_disappears"> Vuze Disappears</A> para mais informa\u00e7\u00e3o. 
-ManagerItem.paused=Pausado
-Utils.link.visit=Por favor visite
-ConfigView.section.connection.serverport.wiki=Escolhas de boas portas
-ConfigView.section.transfer.speeds.wiki=Boas configura\u00e7\u00f5es de velocidade
-installPluginsWizard.installMode.info.text=Voc\u00ea n\u00e3o precisa de plugins para o Vuze funcionar apropriadamente, eles trazem op\u00e7\u00f5es complementares para divers\u00e3o, automa\u00e7\u00e3o ou controle remoto.\nEnt\u00e3o por favor leia cada descri\u00e7\u00e3o do plugin cuidadosamente antes de decidir instal\u00e1-lo.\nA maioria dos plugins s\u00e3o seguros para testar, apenas n\u00e3o sobrecarregue a sua configura\u00e7\u00e3o com plugins que voc\u00ea n\u00e3o usar\u00e1.
-Views.plugins.Distributed.DB.title=Base de Dados Distribu\u00edda
-Views.plugins.Distributed.Tracker.title=Tracker Distribu\u00eddo
-Views.plugins.Plugin.Update.title=Atualiza\u00e7\u00e3o do Plugin
-openUrl.url.info=Suporta http, https, magnet e strings de infohash raw hex 
-TableColumn.header.swarm_average_completion=Conclus\u00e3o da M\u00e9dia dos Peers
-TableColumn.header.swarm_average_completion.info=A porcentagem da conclus\u00e3o m\u00e9dia dos peers na multid\u00e3o
-GeneralView.label.swarm_average_completion=Conclus\u00e3o em M\u00e9dia:
-GeneralView.label.swarm_average_completion.tooltip=A porcentagem da conclus\u00e3o dos peers em m\u00e9dia na multid\u00e3o
-MainWindow.nat.status.tooltip.unknown=Status para alcan\u00e7ar Firewall/NAT desconhecido (TCP)
-MainWindow.nat.status.tooltip.ok=OK para Alcan\u00e7ar (TCP)
-MainWindow.nat.status.tooltip.probok=Para alcan\u00e7ar foi OK, contudo sem conex\u00f5es de entrada TCP recentes
-MainWindow.nat.status.bad=Atr\u00e1s de Firewall
-MainWindow.nat.status.tooltip.bad=Problema para alcan\u00e7ar Firewall/NAT (TCP). V\u00e1 at\u00e9 o Wiki por ajuda
-plugin.installer.recommended.plugin=Plugin recomendado - por favor reveja e instale se requerido
-LoggerView.pause=Pausar Logging
-LoggerView.clear=&Limpar
-LoggerView.filter=Filtro
-LoggerView.filter.uncheckAll=Desmarcar Todas as Categorias
-LoggerView.filter.checkAll=Marcar Todas as Categorias
-LoggerView.loggingDisabled=Logging n\u00e3o est\u00e1 ativado.
-LoggerView.includeOnly=S\u00f3 exibir linhas combinando esta express\u00e3o regular:
-LoggerView.excludeAll=N\u00e3o exibir linhas combinando esta express\u00e3o regular:
-ConfigView.section.logging.log0type=Informa\u00e7\u00e3o
-ConfigView.section.logging.log1type=Aviso
-ConfigView.section.logging.log2type=Erro
-ConfigView.section.logging.filter=Filtrar quando registrando no arquivo
-ConfigView.section.logging.level=N\u00edvel do Log
-ConfigView.section.logging.showLogsFor=Mostrar os logs das %1 para as seguintes categorias:
-ConfigView.pluginlist.column.loadAtStartup=Carregar ao at Iniciar
-ConfigView.pluginlist.column.type=Tipo
-ConfigView.pluginlist.column.type.perUser=Por Usu\u00e1rio
-ConfigView.pluginlist.column.type.shared=Compartilhado
-ConfigView.pluginlist.column.type.builtIn=Embutido
-ConfigView.pluginlist.column.name=Nome
-ConfigView.pluginlist.column.version=Vers\u00e3o
-ConfigView.pluginlist.column.directory=Diret\u00f3rio
-ConfigView.pluginlist.column.isOperational=Operacional?
-PeersView.BlockView.Avail.Have=Ambos tem
-PeersView.BlockView.Avail.NoHave=O peer tem; Voc\u00ea n\u00e3o
-PeersView.BlockView.NoAvail.Have=Voc\u00ea tem; O peer n\u00e3o
-PeersView.BlockView.NoAvail.NoHave=Ningu\u00e9m tem
-PeersView.BlockView.Transfer=Transferindo
-PeersView.BlockView.NextRequest=Pr\u00f3ximo Pedido
-PeersView.BlockView.title=Mapa dos Peda\u00e7os
-PeersView.BlockView.AvailCount=Contagem da Disponibilidade
-MyTorrentsView.dialog.NumberError.title=N\u00famero Inv\u00e1lido ou N\u00e3o Reconhecido
-MyTorrentsView.dialog.NumberError.text=O n\u00famero que voc\u00ea inseriu \u00e9 inv\u00e1lido ou n\u00e3o reconhecido.
-MyTorrentsView.menu.manual.per_torrent=Manual (por torrent)
-MyTorrentsView.menu.manual.shared_torrents=Manual (pelos torrents)
-MyTorrentsView.dialog.setSpeed.title=Definir %1 velocidade
-# %1 = "in kbps" or ""; %2 = "upload" or "download"
-MyTorrentsView.dialog.setNumber.text=Insira um n\u00famero %1 para mudar %2 para:
-MyTorrentsView.dialog.setNumber.inKbps=em %1
-OpenTorrentWindow.torrentLocation=Arquivos Torrent:
-OpenTorrentWindow.addFiles.URL=Adicionar &URL
-OpenTorrentWindow.addFiles.Folder=Adicionar &Pasta
-OpenTorrentWindow.addFiles.Clipboard=Adicionar da \u00c1rea de Transfer\u00eancia
-OpenTorrentWindow.changeDestination=Mudar o Destino
-OpenTorrentWindow.fileList=Arquivos nos torrents:
-OpenTorrentWindow.torrentTable.name=Nome
-OpenTorrentWindow.torrentTable.saveLocation=Salvar o Local
-OpenTorrentWindow.fileTable.fileName=Nome do Arquivo
-OpenTorrentWindow.fileTable.size=Tamanho
-OpenTorrentWindow.fileTable.destinationName=Nome do Destino
-OpenTorrentWindow.startMode.seeding=Ficando de Seed
-OpenTorrentWindow.fileList.changeDestination=Mudar o Destino
-OpenTorrentWindow.mb.badSize.title=Arquivo Incompat\u00edvel
-OpenTorrentWindow.mb.badSize.text='%1' n\u00e3o \u00e9 '%2' e n\u00e3o pode ser usado para ficar de seed
-OpenTorrentWindow.mb.alreadyExists.text=<A HREF="%1">%3</A> j\u00e1 foi adicionado como '%2'
-OpenTorrentWindow.mb.alreadyExists.default.name=M\u00eddia
-OpenTorrentWindow.mb.alreadyExists.title=O torrent j\u00e1 existe
-OpenTorrentWindow.mb.openError.title=Erro ao Abrir
-OpenTorrentWindow.mb.openError.text='%1' n\u00e3o p\u00f4de ser aberto:
-OpenTorrentWindow.torrent.remove=Remover torrent da lista
-OpenTorrentWindow.torrent.options=As seguintes configura\u00e7\u00f5es se aplicar\u00e3o aos torrents selecionados abaixo:
-OpenTorrentWindow.xOfTotal=(%1 de %2)
-iconBar.open.tooltip=Abrir Torrent(s)
-LocaleUtil.column.text=Texto Desconhecido
-Tracker.tooltip.MultiSupport=Este tracker suporta m\u00faltiplos hash scrapes por pedido.
-Tracker.tooltip.NoMultiSupport=Este tracker n\u00e3o suporta m\u00faltiplos hash scrapes por pedido.
-ConfigView.label.lazybitfield=Usar lazy bitfield (ajuda a ficar de seed nas redes empregando o bloqueamento baseado no bitfield)
-LoggerView.realtime=Atualizar em tempo real
-ConfigView.section.file.perf.cache.flushpieces=Escrever peda\u00e7os completos no disco imediatamente. Isto suaviza o acesso ao disco mas pode resultar em mais opera\u00e7\u00f5es de escrita.
-ConfigView.section.file.writemblimit=M\u00e1ximo de pedidos de escrita requeridos (em %1)
-ConfigView.section.file.writemblimit.explain=Quando a velocidade de escrita no disco \u00e9 menor do que a velocidade de download este par\u00e2metro limita quantos dados ser\u00e3o requeridos antes que as velocidades de download sejam reduzidas.
-ConfigView.section.file.readmblimit=M\u00e1ximo de pedidos de leitura requeridos (em %1)
-ConfigView.section.file.readmblimit.explain=Este par\u00e2metro limita quanta mem\u00f3ria ser\u00e1 usada para armazenar leituras que ainda est\u00e3o pendentes no processamento.
-Button.moveUp=Mover &pra Cima
-Button.moveDown=Mover &pra Baixo
-ConfigView.notAvailableForMode=Esta se\u00e7\u00e3o \u00e9 destinada para o modo %1 ou mais alto.  N\u00e3o est\u00e1 dispon\u00edvel no modo %2.
-health.explain.error=H\u00e1 um erro com este torrent.  Veja a coluna Status, ou a dica no \u00edcone para o erro.
-GeneralView.label.trackerscrapeupdate=Limpar Tracker
-PeersView.piece=Peda\u00e7o
-PeersView.piece.info=\u00daltimo peda\u00e7o # requesitado deste peer
-PiecesView.priority=Prioridade
-PiecesView.priority.info=a prioridade da conclus\u00e3o deste peda\u00e7o, mas n\u00e3o preste muita aten\u00e7\u00e3o a ele
-PiecesView.speed=Velocidade
-PiecesView.speed.info=Peers mais lento s\u00e3o impedidos de interferir muito com os peda\u00e7os mais r\u00e1pidos 
-TableColumn.header.AvgAvail.info=Soma da disponibilidade dos peda\u00e7os divididos por # peda\u00e7os, divididos por # conex\u00f5es
-TableColumn.header.AvgAvail=M\u00e9dia de Disp/peda\u00e7os
-ConfigView.label.strictfilelocking=Refor\u00e7ar a tranca do acesso de escrita exclusivo do arquivo pelos torrents
-MyTorrentsView.menu.checkfilesexist=Arquivos de Verifica\u00e7\u00e3o Existem
-MyTorrentsView.menu.rescanfile=Periodicamente Re-verifcar os Peda\u00e7os Incompletos
-MyTorrentsView.menu.clear_resume_data=Limmpar Dados de Resumo
-Plugin.extseed.name=Seeds Externos
-Plugin.localtracker.name=Descobridor de Peers em LAN
-Plugin.localtracker.info=O descobridor de peers na LAN permite m\u00faltiplas c\u00f3pias do Vuze atr\u00e1s de um firewall e em uma rede comum para baixar com efici\u00eancia torrents ativando a conex\u00e3o direta entre eles
-Plugin.localtracker.enable=Ativar o descobridor de peers na LAN
-azinstancehandler.alert.portclash=Conflito de portas detectado na LAN: %1 j\u00e1 em uso por outro usu\u00e1rio do Vuze, selecione nova(s) porta(s) aleat\u00f3ria(s) para a escuta TCP  / UDP de entrada [entre %2 e %3]. 
-ConfigView.section.transfer.lan.tooltip=Configura\u00e7\u00f5es espec\u00edficias-pra-LAN
-ConfigView.section.transfer.lan.uploadrate=Velocidade m\u00e1xima de upload na LAN em KB/s [0: ilimitada]
-ConfigView.section.transfer.lan.uploadrate.tooltip=Conex\u00f5es com os peers dentro da mesma LAN interna tem um limite de taxa de upload separado.
-ConfigView.section.transfer.lan.downloadrate=Velocidade m\u00e1xima de download na LAN em KB/s [0: ilimitada]
-ConfigView.section.transfer.lan.downloadrate.tooltip=Conex\u00f5es com os peers dentro da mesma LAN interna tem um limite de taxa de download separado.
-TorrentOptionsView.title.short=Op\u00e7\u00f5es
-TorrentOptionsView.title.full=Op\u00e7\u00f5es
-TorrentOptionsView.param.max.peers=N\u00famero m\u00e1ximo de conex\u00f5es [0: ilimitadas]
-ConfigView.section.connection.encryption.require_encrypted_transport=Requer transporte encriptado
-ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=For\u00e7ar o uso de conex\u00f5es encriptadas com outros peers.
-ConfigView.section.connection.encryption.min_encryption_level=N\u00edvel m\u00ednimo da encripta\u00e7\u00e3o
-ConfigView.section.connection.encryption.min_encryption_level.tooltip=Simples - s\u00f3 handshake\nRC4 - corrente completa\nMaior encripta\u00e7\u00e3o requer mais CPU.
-Peers.column.Encryption=Encripta\u00e7\u00e3o
-Peers.column.Encryption.info=N\u00edvel da encripta\u00e7\u00e3o em uso
-ConfigView.section.connection.encryption.encrypt.info=Se a encripta\u00e7\u00e3o est\u00e1 ativada voc\u00ea n\u00e3o ser\u00e1 capaz de conectar a clientes incompat\u00edveis a menos que voc\u00ea configure as op\u00e7\u00f5es de retorno
-ConfigView.section.connection.encryption.encrypt.info.link=Por favor visite aqui para detalhes
-MainWindow.sr.status.tooltip.ok=Taxa de Compartilhamento %1 OK
-MainWindow.sr.status.tooltip.poor=Taxa de Compartilhamento %1 pobre: < 0.9
-MainWindow.sr.status.tooltip.bad=Taxa de Compartilhamento %1 ruim: < 0.5
-ConfigView.section.style.status=\u00c1rea do Status:
-ConfigView.section.style.status.show_sr=Taxa de Compartilhamento
-ConfigView.section.style.status.show_nat=Status do NAT
-ConfigView.section.style.status.show_ddb=Status do DDB
-ConfigView.section.style.status.show_ipf=Status do IPFilter
-ConfigView.section.connection.encryption.encrypt.group=Encripta\u00e7\u00e3o/Ofusca\u00e7\u00e3o do Transporte
-ConfigView.section.connection.encryption.encrypt.fallback_info=Ativando-a a op\u00e7\u00e3o de retorno permitir\u00e1 conex\u00f5es com clientes incompat\u00edveis MAS resultar\u00e1 em conex\u00f5es n\u00e3o encriptadas
-ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Permitir conex\u00f5es de sa\u00edda n\u00e3o encriptadas se a tentativa de encriptar a conex\u00e3o falhar
-ConfigView.section.connection.encryption.encrypt.fallback_incoming=Permitir conex\u00f5es de entrada n\u00e3o encriptadas
-ConfigView.section.connection.encryption=Encripta\u00e7\u00e3o do Transporte
-upnp.selectedinterfaces=Interfaces selecionadas (';' separadas, ex: eth0;eth1) [em branco: todas]
-ConfigView.section.style.defaultSortOrder=Ordem de Organiza\u00e7\u00e3o Padr\u00e3o
-ConfigView.section.style.defaultSortOrder.desc=Descendente
-ConfigView.section.style.defaultSortOrder.asc=Ascendente
-ConfigView.section.style.defaultSortOrder.flip=Oposto da ordem anterior
-LoggerView.autoscroll=Auto-rolar
-Button.selectAll=Selecionar Todos
-Button.markSelected=Marcar os Selecionados
-Button.unmarkSelected=Desmarcar os Selecionados
-plugins.basicview.config=Config.
-TorrentOptionsView.param.max.uploads=N\u00famero m\u00e1ximo de slots de upload [m\u00ednimo: 2]
-MyTorrentsView.dialog.setPosition.title=Definir Posi\u00e7\u00e3o
-MyTorrentsView.dialog.setPosition.text=Insira a posi\u00e7\u00e3o para definir os torrents selecionados:
-MyTorrentsView.menu.reposition.manual=Reposi\u00e7\u00e3o..
-ConfigView.section.connection.advanced.info.link=Por favor visite aqui para detalhes
-ConfigView.section.connection.advanced.socket.group=Op\u00e7\u00f5es do Socket
-ConfigView.section.connection.advanced.bind_port=Prender a porta local [0: desativado]
-ConfigView.section.connection.advanced.bind_port.tooltip=Conex\u00f5es de socket de sa\u00edda ser\u00e3o localmente presas a porta dada.\nAtivar isto pode ajudar com a instabilidade do roteador NAT.
-ConfigView.section.proxy.group.tracker=Comunica\u00e7\u00f5es do Tracker
-ConfigView.section.proxy.group.peer=Comunica\u00e7\u00f5es do Peer
-Pieces.column.Requested=Requesitado
-Pieces.column.Requested.info=Mostra se mais pedidos podem ser feitos no peda\u00e7o ou n\u00e3o (*)
-ConfigView.label.maxuploadsseeding=Alternar para o padr\u00e3o quando ficando de seed
-MyTorrentsView.filter=Filtro:
-popup.error.hideall=Esconder Todos
-ConfigView.section.style.dataStatsOnly=Mostrar apenas os dados das estat\u00edsticas (esconder as estat\u00edsticas do protocolo)
-ConfigView.section.style.separateProtDataStats=Mostrar dados separados e estat\u00edsticas do protocolo como '(protocolo) de dados'
-MyTorrentsView.dialog.setFilter.title=Modificar Filtro
-MyTorrentsView.dialog.setFilter.text=A se\u00e7\u00e3o %1 ser\u00e1 filtrada pelo texto que voc\u00ea especificar abaixo.  Usar o | s\u00edmbolo (cano) para filtrar m\u00faltiplas frases. 
-MyTorrentsView.filter.tooltip=Ctrl+X para trocar entre RegEx e modos de busca normal.\nUsar o | s\u00edmbolo (cano) para filtrar m\u00faltiplas frases.
-MyTorrentsView.clearFilter.tooltip=Limpar o Filtro
-MyTorrentsView.menu.filter=Lista de Filtros...
-ConfigView.section.file.resume.recheck.all=Quando der pau-reiniciar verificar o arquivo inteiro por peda\u00e7os completados (De outro modo apenas peda\u00e7os ativos do \u00faltimo salvamento s\u00e3o verificados)
-ConfigureWizard.language.choose=Escolha um idioma da lista abaixo:
-popup.closing.in=Auto-fechando a janela em %1 segundos
-popup.more.waiting=%1 mais mensagem(ns)..
-# > 2402
-popup.download.finished="%1" terminou de baixar.
-popup.file.finished="%1" terminou de baixar.
-Plugin.localtracker.autoadd.info=Automaticamente adicionar estes peers locais [';' endere\u00e7os separados, ex: 1.2.3.4]
-Plugin.localtracker.autoadd=Peers expl\u00edcitos
-Plugin.localtracker.networks.info=Considere as seguintes redes serem locais [';' redes separadas, ex: 145.227.*.*]
-Plugin.localtracker.networks=Redes locais
-MainWindow.menu.view.plugins.logViews=Visualiza\u00e7\u00f5es do Log
-SpeedView.stats.autospeed=Velocidade de Upload Autom\u00e1tica
-SpeedView.stats.autospeed.disabled=Esta op\u00e7\u00e3o ou est\u00e1 desativada (voc\u00ea precisa do DHT) ou n\u00e3o est\u00e1 em uso (velocidade manual de upload selecionada)
-SpeedView.stats.idlePing=Ping Inativo:
-SpeedView.stats.maxPing=Ping M\u00e1x:
-SpeedView.stats.currentPing=Ping Atual:
-SpeedView.stats.maxUp=Velocidade M\u00e1x de Upload:
-ConfigView.pluginlist.unloadSelected=Descarregar o Selecionado
-ConfigView.pluginlist.scan=Escanear por novos Plugins
-ConfigView.section.transfer.autospeed=Auto-Velocidade (cl\u00e1ssica)
-ConfigView.section.transfer.autospeed.tooltip=Configura\u00e7\u00f5es espec\u00edficas da Auto-velocidade
-ConfigView.section.transfer.autospeed.info=A auto-velocidade ajusta automaticamente o limite da velocidade de upload para evitar sobrecarregar a conex\u00e3o de rede.\n\nEstes limites s\u00f3 ser\u00e3o aplicados quando a velocidade autom\u00e1tica de upload estiver ativada e tamb\u00e9m requer que a base de dados distribu\u00edda esteja ativada.\n
-ConfigView.section.transfer.autospeed.minupload=Velocidade m\u00ednima de upload em %1
-ConfigView.section.transfer.autospeed.minupload.tooltip=A velocidade de upload n\u00e3o ser\u00e1 normalmente diminu\u00edda abaixo deste limite
-ConfigView.section.transfer.autospeed.maxupload=Velocidade m\u00e1xima de upload em %1 [0: ilimitada]
-ConfigView.section.transfer.autospeed.maxupload.tooltip=A velocidade de upload n\u00e3o ser\u00e1 aumentada automaticamente acima deste limite
-ConfigView.section.transfer.autospeed.chokeping=Tempo para silenciar o ping [milisegundos]
-ConfigView.section.transfer.autospeed.chokeping.tooltip=Os tempos do Ping em excesso deste valor ser\u00e1 considerado como um indicador de satura\u00e7\u00e3o de rede
-ConfigView.section.transfer.autospeed.enableauto=Ativar quando baixando e ficando de seed
-ConfigView.section.transfer.autospeed.enableautoseeding=Ativar apenas quando ficando de seed
-ConfigView.pluginlist.column.unloadable=Descarreg\u00e1vel
-ConfigView.section.transfer.lan.enable=Ativar os limites de velocidade separados para as conex\u00f5es LAN 
-Plugin.localtracker.wellknownlocals=Automaticamente incluir loopback/link/redes locais de site (192.168 etc)
-TableColumn.header.filesdone=Arquivos Feitos
-TableColumn.header.filesdone.info=Arquivos feitos/Total dos arquivos *ou* arquivos n\u00e3o-ignorados feitos (Arquivos feitos)/Total de arquivos n\u00e3o-ignorados (Total de arquivos)
-MagnetPlugin.private_torrent=<torrent privado>
-MagnetPlugin.decentral_disabled=<tracking descentralizado desativado>
-MagnetPlugin.decentral_backup_disabled=<backup descentralizado desativado>
-MagnetPlugin.report.waiting_ddb=esperando pela inicializa\u00e7\u00e3o do DDB...
-MagnetPlugin.report.searching=buscando...
-MagnetPlugin.report.found=achado(s) %1
-MagnetPlugin.report.alive=%1 est\u00e1 vivo
-MagnetPlugin.report.dead=%1 est\u00e1 morto
-MagnetPlugin.report.tunnel=abrindo para %1
-MagnetPlugin.report.downloading=baixando de %1
-MagnetPlugin.report.error=erro %1
-MagnetURLHandler.report.no_sources=nenhuma(s) fonte(s) achada(s) para o torrent
-MagnetURLHandler.report.torrent_size=tamanho do torrent: %1
-MagnetURLHandler.report.percent=completado: %1%
-MagnetURLHandler.report.error=erro %1
-DHTTransport.report.request_all=requisitando a transfer\u00eancia inteira de %1
-DHTTransport.report.received_bit=recebeu %1 para %2 de %3
-DHTTransport.report.complete=completo
-DHTTransport.report.timeout=tempo esgotado, sem respostas de %1
-DHTTransport.report.rerequest_all=re-requisitando transfer\u00eancia inteira de %1
-DHTTransport.report.rerequest_bit=re-requisitando %1 para %2 de %3
-DHTTransport.report.timeout_some=tempo esgotado, %1 pacotes recebidos de %2 mas incompletos
-DHTTransport.report.sending=enviando dados
-DHTTransport.report.resending=re-enviando dados
-DHTTransport.report.send_complete=enviar completados
-DHTTransport.report.send_timeout=tempo de enviar esgotado
-ConfigView.section.transfer.autospeed.enabledebug=Informa\u00e7\u00e3o de debug no Log
-TableColumn.header.date_added=Data adicionada
-TableColumn.header.date_added.info=Data que o torrent foi adicionado
-ConfigView.section.file.hashchecking.smallestfirst=Re-verificar os downloads menores primeiro
-platform.win32.baddll.info=O Vuze detectou a presen\u00e7a de '%1'. Isto \u00e9 parte de '%2' e \u00e9 sabido que causa problemas severos tais como crash no aplicativo e alto uso da CPU.  Se voc\u00ea encontrar estes ent\u00e3o por favor desinstale o software ou configure-o para n\u00e3o afetar o Vuze.
-upnp.ignorebaddevices=Ignorar dispositivos que falham em responder corretamente
-upnp.ignorebaddevices.info=Dispositivos atualmente ignorados: %1
-upnp.ignorebaddevices.reset=Resetar a lista de dispositivos ignorados
-upnp.ignorebaddevices.reset.action=Resetar
-upnp.ignorebaddevices.alert=O dispositivo UPnP no local %1 est\u00e1 sendo ignorado devido a repetidas falhas. Veja a configura\u00e7\u00e3o do plugin UPnP para op\u00e7\u00f5es com respeit a esta a\u00e7\u00e3o.
-TorrentOptionsView.param.max.uploads.when.busy=Velocidade m\u00e1xima de upload em KB/s quando o limite global de upload alcan\u00e7ar [0: desativado]
-UpdateMonitor.messagebox.verification.failed.title=Verifica\u00e7\u00e3o da Instala\u00e7\u00e3o Falhou
-UpdateMonitor.messagebox.verification.failed.text=Verifica\u00e7\u00e3o da '%1' falhou: %2
-UpdateMonitor.messagebox.accept.unverified.title=Aceitar Instala\u00e7\u00e3o N\u00e3o-Verificada
-UpdateMonitor.messagebox.accept.unverified.text='%1' n\u00e3o p\u00f4de ser verificado como um plugin oficial do Vuze.\nSe \u00e9 tal plugin voc\u00ea N\u00c3O deve continuar.\nProsseguir com a instala\u00e7\u00e3o?
-FileView.BlockView.title=Peda\u00e7os do Arquivo
-FileView.BlockView.Done=Conclu\u00eddo
-FileView.BlockView.Skipped=Pulado
-FileView.BlockView.Active=Ativo
-FileView.BlockView.Outstanding=Pendente
-ConfigView.label.tcplistenport=Porta de escuta da entrada TCP
-ConfigView.label.udplistenport=Porta de escuta UDP
-upnp.portchange.alert=As seguintes portas foram mudadas para evitar problemas com dispositivos UPnP: %1 [porta antiga=%2] %3 [porta antiga=%4]
-ConfigView.section.proxy.username.info=Se o servidor proxy exige autentica\u00e7\u00e3o mesmo quando nenhuma est\u00e1 definida, use a string "<nenhuma>" como nome de usu\u00e1rio
-ConfigView.label.maxuploadswhenbusymin=Velocidade m\u00e1xima de upload por torrent quando o timer est\u00e1 ocupado [seg]
-MainWindow.menu.help.debug=Gerar Info de Debug (Crash Log)
-DownloadManager.error.badsize=Tamanho incorreto
-natpmp.info=NAT-PMP \u00e9 a alternativa da Apple para o UPnP e \u00e9 suportada por recentes esta\u00e7\u00f5es de aeroportos\n\nNote que o UPnP tem que estar ativado para ativar o NAT-PMP ja que o dispositivo NAT-PMP \u00e9 tratado como um tipo de dispositivo UPnP especial
-natpmp.enable=Ativar (note que deve tamb\u00e9m estar ativado na configura\u00e7\u00e3o do aeroporto para funcionar)
-ConfigView.section.tracker.host.addurls=Garante que as URLs do tracker est\u00e3o presentes nos torrents hospedados
-ConfigView.filter=procurar op\u00e7\u00f5es aqui
-ConfigView.section.files.move=Conclus\u00e3o da Movimenta\u00e7\u00e3o
-ConfigView.section.file.defaultdir.section=Op\u00e7\u00f5es Padr\u00e3o do Diret\u00f3rio
-ConfigView.section.file.defaultdir.auto=Automaticamente baixar para o diret\u00f3rio padr\u00e3o (Sem Alertar)
-ConfigView.section.file.defaultdir.bestguess=Usar o melhor palpite quando escolher o diret\u00f3rio padr\u00e3o para salvar
-ConfigView.section.file.defaultdir.ask=Diret\u00f3rio padr\u00e3o: 
-ConfigView.section.file.defaultdir.lastused=Atualizar o diret\u00f3rio padr\u00e3o para o local onde salvou pela \u00faltima vez
-ConfigView.section.file.config.section=Configura\u00e7\u00f5es da Configura\u00e7\u00e3o
-ConfigView.section.file.config.currentdir=Diret\u00f3rio da configura\u00e7\u00e3o atual:
-ConfigView.section.torrent.decoding=Decodificar as Defini\u00e7\u00f5es de Caracteres
-ConfigView.section.logging.udptransport=Ativar tra\u00e7o de transporte verboso UDP
-Tracker.announce.ignorePeerSeed=Ignorar Contagem de Peers/Seeds. %1
-ConfigView.section.connection.encryption.use_crypto_port=Usar a extens\u00e3o do tracker 'cryptoport' para impedir tentativas de conex\u00e3o de entrada simples. Alguns trackers n\u00e3o aceitam isto e falham com erros tais como "Porta Inv\u00e1lida" ou "Argumento Ilegal"
-TorrentOptionsView.param.reset.to.default=Definir as op\u00e7\u00f5es de volta aos seus valores padr\u00e3o
-TorrentOptionsView.param.reset.button=Resetar
-natpmp.routeraddress=Endere\u00e7o da esta\u00e7\u00e3o [em branco: auto]
-ConfigView.section.style.disableAlertSliding=Desativar anima\u00e7\u00e3o de sliding/em alto estilo para mensagens de alerta
-ConfigView.section.transfer.autospeed.maxinc=Aumento m\u00e1ximo em %1 por ciclo
-ConfigView.section.transfer.autospeed.maxdec=Diminui\u00e7\u00e3o m\u00e1xima em %1 por ciclo
-ConfigView.section.transfer.autospeed.enabledownadj=Ativar ajuste da velocidade de download
-ConfigView.section.transfer.autospeed.downadjratio=Taxa da velocidade de Download:Upload (ex: 2.0-> o limite da velocidade de download \u00e9 o dobro do limite de upload)
-ConfigView.section.transfer.autospeed.latencyfactor=Fator usado para ligar as mudan\u00e7as de lat\u00eancia as mudan\u00e7as de velocidade (n\u00bas maiores diminuem a sensitividade)
-ConfigView.section.transfer.autospeed.reset=Resetar valores avan\u00e7ados
-ConfigView.section.transfer.autospeed.reset.button=Resetar
-PeerColumn.activationCount=Peers tentando se conectar: %1
-TableColumn.header.timesincedownload.info=O tempo decorrido desde que os dados foram baixados para o torrent
-TableColumn.header.timesincedownload=Inativo pra Baixo
-TableColumn.header.timesinceupload.info=O tempo decorrido desde que os dados foram enviados para o torrent
-TableColumn.header.timesinceupload=Inativo pra Cima
-PeersView.incomingreqcount=Reqs de Entrada
-PeersView.incomingreqcount.info=Contagem dos pedidos de entrada feitos pelo peer
-PeersView.outgoingreqcount=Reqs de Sa\u00edda
-PeersView.outgoingreqcount.info=Contagem dos pedidos de sa\u00edda feitos pelo peer
-upnp.mapping.trackerclientudp=Porta do Cliente Tracker UDP
-upnp.mapping.dhtudp=Base de Dados Distribu\u00edda
-ConfigView.section.connection.nondata.udp.same=Usar a mesma porta UDP para a Base de Dados Distribu\u00edda e o Tracker UDP
-ConfigView.section.connection.tcp.enable=Ativar TCP
-ConfigView.section.connection.udp.enable=Ativar UDP
-ConfigView.section.style.showiconbar=Mostrar a Barra de Ferramentas
-MainWindow.menu.view.iconbar=Barra de Ferramentas
-MyTorrentsView.menu.rename=Renomear
-MyTorrentsView.menu.rename.displayed=Renomear o Nome Exibido
-MyTorrentsView.menu.rename.save_path=Renomearo Caminho para Salvar
-AdvRenameWindow.title=Renomear Download
-AdvRenameWindow.message=Digite um novo nome para este download.
-AdvRenameWindow.rename.torrent=Renomear Torrent
-MyTorrentsView.menu.rename.displayed.enter.title=Renomear o Nome Exibido 
-MyTorrentsView.menu.rename.displayed.enter.message=Inserir um novo nome para exibir para este download.\nSe nenhum texto \u00e9 inserido, o nome original ser\u00e1 usado.
-MyTorrentsView.menu.edit_comment=Editar Coment\u00e1rio
-MyTorrentsView.menu.edit_comment.enter.title=Editar Coment\u00e1rio
-MyTorrentsView.menu.edit_comment.enter.message=Inserir um coment\u00e1rio para este download.
-UIDebugGenerator.messageask.title=Gerador de Debug
-UIDebugGenerator.messageask.text=Por favor insira uma descri\u00e7\u00e3o do bug que voc\u00ea est\u00e1 reportando
-UIDebugGenerator.complete.title=Gera\u00e7\u00e3o de Debug Completa
-UIDebugGenerator.complete.text=Por favor envie o arquivo '%1' para az-bugreports at azureus-inc.com\n\nClique em Ok para abrir uma janela para este arquivo.
-ConfigView.section.style.showProgramIcon=Mostrar o \u00edcone do programa no nome da coluna
-ConfigView.section.style.showProgramIcon.tooltip=A visualiza\u00e7\u00e3o pode precisar de re-abrir para as mudan\u00e7as acontecerem
-swt.alert.cant.update=biblioteca SWT carregada de "%3" n\u00e3o p\u00f4de ser automaticamente atualizada da vers\u00e3o %1 para a %2 (deve ser carregada de "%4"). Por favor veja <A HREF="http://azureuswiki.com/index.php/SWT_Cant_Auto_Update">no wiki</A> para detalhes.
-authenticator.savepassword=Lembrar da minha senha
-ConfigView.section.security.clearpasswords=Resetar as senhas lembradas
-ConfigView.section.security.clearpasswords.button=Resetar
-TorrentInfoView.torrent.encoding=Codifica\u00e7\u00e3o do torrent
-TorrentInfoView.columns=Colunas da visualiza\u00e7\u00e3o 'Meus Torrents'
-progress.window.title=Opera\u00e7\u00e3o em Progresso
-progress.window.msg.filemove=Por favor espere enquanto a movimenta\u00e7\u00e3o/renomeamento do arquivo se completa
-ConfigView.label.popup.timestamp=Adicionar estampas de tempo aos alertas popup
-ConfigView.label.popup.autohide=Automaticamente esconder alertas popup que n\u00e3o s\u00e3o sobre erros ap\u00f3s x segundos (definir em 0 para desativar o auto-esconder)
-ConfigView.label.please.visit.here=Por favor visite aqui para detalhes
-ConfigView.section.ipfilter.enable.descriptionCache=Armazenar as descri\u00e7\u00f5es de IP em arquivo de rascunho
-ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Quando desatida, as descri\u00e7\u00f5es n\u00e3o ser\u00e3o lembradas
-OpenTorrentWindow.filesInfo=%1 de %2 ser\u00e3o baixados.
-OpenTorrentWindow.diskUsage=%1 de %2
-ConfigView.label.openmytorrents=Abrir 'Meus Torrents' ao iniciar
-ConfigView.label.open_transfer_bar_on_start=Abrir a Barra de Transfer\u00eancia ao iniciar
-ConfigView.section.style.DNDalwaysInIncomplete=Sempre mostrar torrents com arquivos para 'N\u00e3o Baixar' na se\u00e7\u00e3o Incompletos de Meus Torrents
-OpenTorrentWindow.mb.noGlobalDestDir.title=Diret\u00f3rio Destino
-OpenTorrentWindow.mb.noGlobalDestDir.text=O diret\u00f3rio destino '%1' \u00e9 inv\u00e1lido.
-OpenTorrentWindow.mb.noDestDir.title=Diret\u00f3rio Destino n\u00e3o achado
-OpenTorrentWindow.mb.noDestDir.text=O diret\u00f3rio destino '%1' para o torrent '%2' n\u00e3o existe ou \u00e9 inv\u00e1lido.
-OpenTorrentWindow.mb.notValid.title=Abrir Torrent
-OpenTorrentWindow.mb.notValid.text=N\u00e3o p\u00f4de abrir o torrent '%1'.  Se voc\u00ea est\u00e1 abrindo no modo ficar de seed, por favor tenha certeza de que os arquivos de dados do torrent existem.
-OpenTorrentWindow.mb.notTorrent.title=Abrir Torrent
-OpenTorrentWindow.mb.notTorrent.text=N\u00e3o p\u00f4de abrir '%1'.  N\u00e3o aparenta ser um arquivo .torrent.\n\nAlguns dos dados recebidos:\n%2
-ConfigView.label.pause.downloads.on.exit=Pausar downloads ao sair
-ConfigView.label.resume.downloads.on.start=Resumir downloads pausados ao iniciar ap\u00f3s a inicializa\u00e7\u00e3o completar
-UIDebugGenerator.message.cancel.title=Gerar Info de Debug Info Cancelado
-UIDebugGenerator.message.cancel.text=Voc\u00ea n\u00e3o inseriu uma descri\u00e7\u00e3o do bug que voc\u00ea est\u00e1 tentando reportar.  O seu bug pode ser \u00f3bvio pra voc\u00ea, mas sem uma descri\u00e7\u00e3o, n\u00f3s s\u00f3 estar\u00edamos tentando advinhar o seu problema.\n\nA Gera\u00e7\u00e3o de Informa\u00e7\u00e3o sobre o Debug foi cancelada.
-ConfigView.section.connection.group.http.info=Suporte para seeding HTTP.
-ConfigView.section.connection.http.enable=Ativar
-ConfigView.section.connection.http.port=N\u00famero da porta de entrada
-ConfigView.section.connection.http.portoverride=N\u00e3o Levar em Conta a Porta HTTP do Tracker [0: nenhuma]
-window.update.noupdates.title=Procurar pelos Resultados das Atualiza\u00e7\u00f5es
-window.update.noupdates.text=N\u00e3o h\u00e1 novas atualiza\u00e7\u00f5es dispon\u00edveis para voc\u00ea.\n\nParab\u00e9ns!
-ConfigView.label.bindip.details=Exemplo: 192.168.1.5;eth0;eth1[2] prender\u00e1 o IP especificado a todos os IPs da 1\u00aa interface e ao 3\u00ba IP da 2\u00aa interface.\nO 1\u00ba IP ser\u00e1 usado para todos os servi\u00e7os, todos os outros s\u00e3o usados s\u00f3 para o balan\u00e7o da carga.\nAs seguintes interfaces est\u00e3o dispon\u00edveis:\n%1
-ConfigView.label.mindownloads=M\u00edn. de downloads simult\u00e2neos
-UI.cannot_submit_blank_text=Voc\u00ea deve inserir um valor.
-crypto.alert.as.warning=Rede '%1' \u00e9 conhecida por imp\u00f4r traffic shaping para reduzir a performance de download. A encripta\u00e7\u00e3o do transporte foi automaticamente ligada - isto pode ser desligado/modificado via par\u00e2metros de configura\u00e7\u00e3o. 
-ConfigView.section.interface.alerts=Alertas
-ConfigView.label.popupdownloadadded=Mostrar um alerta quando um download \u00e9 adicionado
-popup.download.added="%1" foi adicionado a sua lista de downloads.
-MessageBoxWindow.nomoreprompting=N\u00e3o me alertar de novo
-TorrentOptionsView.param.max.seeds=N\u00famero m\u00e1ximo de conex\u00f5es de seed [0: limite de conex\u00f5es]
-TorrentOptionsView.param.alternative.value.enable=Alternar o valor quando ficando de seed
-ConfigView.section.proxy.check.on.start=Verificar o status do proxy ao iniciar
-TransferStatsView.legend.pingaverage=M\u00e9dia
-TransferStatsView.legend.ping1=Alvo 1
-TransferStatsView.legend.ping2=Alvo 2
-TransferStatsView.legend.ping3=Alvo 3
-ConfigView.section.interface.enabletray._mac=Ativar o \u00cdcone da Barra de Status [requer reiniciar]
-ConfigView.label.closetotray._mac=Fechar minimiza para o \u00cdcone da Barra de Status
-ConfigView.label.minimizetotray._mac=Minimizar minimiza para o \u00cdcone da Barra de Status
-OpenTorrentWindow.mb.existingFiles.title=O(s) Arquivo(s) j\u00e1 existe(m)!
-OpenTorrentWindow.mb.existingFiles.text=Alguns dos arquivos j\u00e1 existem na(s) pasta(s) destino que voc\u00ea especificou:\n\n%1\nSe voc\u00ea continuar, o Vuze verificar\u00e1 o(s) arquivo(s) acima pelos dados corretos e sobrescrever\u00e1 se necess\u00e1rio.
-splash.unloadingTorrents=Descarregando Torrents
-splash.unloadingTorrent=Descarregando Torrent
-ConfigView.section.file.defaultdir.autorename=Auto renomear os dados do torrent se os arquivos no caminho parecem diferentes
-ConfigView.section.file.defaultdir.autorename.tooltip=Isto impede um torrent de sobrescrever os arquivos de outro torrent quando os nomes dos arquivos s\u00e3o os mesmos
-alert.raised.at.close=(Mensagem do fechamento anterior do Vuze)
-Plugin.trackerpeerauth.name=Autoriza\u00e7\u00e3o do Peer do Tracker
-Plugin.trackerpeerauth.info=Este plugin trabalha com os trackers para verificar que os peers s\u00e3o membros v\u00e1lidos da multid\u00e3o
-Peers.column.maxupspeed=Velocidade M\u00e1x. de Upload
-Peers.column.maxdownspeed=Velocidade M\u00e1x. de Download
-MyTorrents.items.DownSpeedLimit.disabled=Nenhum download
-upnp.selectedaddresses=Endere\u00e7os (';' separados, '-' prefixo=negar, '+' =permitir) [em branco: qualquer um]
-upnp.alert.multipledevice.warning=M\u00faltiplos dispositivos UPnP foram detectados - verifique se todos requerem mapeamento de porta (veja o log e a configura\u00e7\u00e3o do UPnP)
-UpdateMonitor.messagebox.restart.title=Atualiza\u00e7\u00e3o do Software
-UpdateMonitor.messagebox.restart.text=O Vuze completou o download de uma atualiza\u00e7\u00e3o importante e agora deve ser reiniciado para que a atualiza\u00e7\u00e3o possa ser instalada.
-PiecesView.BlockView.Have=Tem
-PiecesView.BlockView.NoHave=N\u00e3o Tem
-PiecesView.BlockView.Header=%1 coluna(s), %2 fileira(s), %3 peda\u00e7os
-ConfigView.section.update.autodownload=Auto-baixar atualiza\u00e7\u00f5es e alertar quando a instala\u00e7\u00e3o estiver pronta
-Peers.column.peer_id=ID do Peer
-Peers.column.peer_id.info=A ID do Peer em formul\u00e1rio leg\u00edvel
-Peers.column.peer_byte_id=ID do Peer
-Peers.column.peer_byte_id.info=ID do Peer em formul\u00e1rio em bytes
-Peers.column.handshake_reserved=Bytes Reservados para o Handshake
-Peers.column.handshake_reserved.info=Indica quais bits reservados foram definidos no handshake BT
-Peers.column.client_identification=Identifica\u00e7\u00e3o do Cliente
-Peers.column.client_identification.info=Indica os nomes naturais dos clientes recebidos pelo Vuze - \u00fatil para debugging
-dht.warn.user=Avisar sobre problemas de mapeamento de NAT/portas em potencial
-ConfigView.label.openbar.incomplete=Barras de download: auto-abrir downloads
-ConfigView.label.openbar.complete=auto-abrir seeds
-ConfigView.label.transferbar.remember_location=Lembrar do \u00faltimo local da barra de transfer\u00eancia
-ConfigView.section.transfer.autospeed.forcemin=Velocidade de upload em %1 for\u00e7ada quando baselining a conex\u00e3o
-MainWindow.menu.tools.speedtest=Teste de Velocidade...
-speedtest.wizard.title=Teste de Velocidade
-speedtest.wizard.run=Executar um teste de velocidade
-speedtest.wizard.test.mode.updown=upload e download
-SpeedTestWizard.test.panel.currinfo=Teste de banda BitTorrent.
-SpeedTestWizard.test.panel.label=Teste de velocidade do Vuze:
-SpeedTestWizard.test.panel.already.running=O teste j\u00e1 est\u00e1 rodando!
-SpeedTestWizard.test.panel.not.accepted=Pedido de teste n\u00e3o aceito: 
-SpeedTestWizard.test.panel.abort=Abortar
-SpeedTestWizard.test.panel.abort.countdown=abortar teste em:
-SpeedTestWizard.test.panel.test.countdown=o teste termina em:
-SpeedTestWizard.test.panel.testfailed=O teste falhou
-SpeedTestWizard.test.panel.aborted=Teste abortado manualmente.
-SpeedTestWizard.test.panel.enc.label=Pressionar o teste com encripta\u00e7\u00e3o:
-SpeedTestWizard.test.panel.standard=padr\u00e3o
-SpeedTestWizard.test.panel.encrypted=encriptado
-SpeedTestWizard.set.upload.button.apply=Aplicar
-SpeedTestWizard.set.upload.result=\u00daltimo Resultado do Teste
-SpeedTestWizard.set.upload.bytes.per.sec=kBytes/seg
-SpeedTestWizard.set.upload.bits.per.sec=bits/seg
-SpeedTestWizard.finish.panel.title=O Teste de Velocidade Terminou!
-SpeedTestWizard.finish.panel.click.close=Voc\u00ea fechou o assitente do teste de velocidade. Clique em fechar para sair.
-SpeedTestWizard.finish.panel.max.upload=Upload m\u00e1x:
-SpeedTestWizard.finish.panel.max.seeding.upload=M\u00e1x. de upload enquanto ficando de seed :
-SpeedTestWizard.finish.panel.max.download=Download m\u00e1x:
-SpeedTestWizard.finish.panel.enabled=ativado
-SpeedTestWizard.finish.panel.disabled=desativado
-SpeedTestWizard.abort.message.scheduled.in=teste agendado em ... %1 segundos"
-SpeedTestWizard.abort.message.unsupported.type=Tipo de teste n\u00e3o suportado!!!!
-SpeedTestWizard.abort.message.manual.abort=Manualmente abortado
-SpeedTestWizard.abort.message.scheduling.failed=O agendamento do teste falhou
-SpeedTestWizard.abort.message.download.added=Download %1 adicionado durante o teste
-SpeedTestWizard.abort.message.entered.error=Teste de download entrou em estado de erro '%1'
-SpeedTestWizard.abort.message.entered.queued=Teste baixado entrou em estado requerido/parado
-SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread foi interrompido antes que o teste completasse
-SpeedTestWizard.abort.message.execution.failed=A execu\u00e7\u00e3o do teste falhou
-SpeedTestWizard.abort.message.failed.peers=Falhou em conectar a quaisquer peers
-SpeedTestWizard.abort.message.insufficient.slots=N\u00e3o p\u00f4de fazer upload a quaisquer dos peers - slots de upload insuficientes?
-SpeedTestWizard.abort.message.not.unchoked=N\u00e3o p\u00f4de baixar de quaisquer dos peers como nunca foi desobstru\u00eddo por eles
-SpeedTestWizard.stage.message.requesting=requesitando teste...
-SpeedTestWizard.stage.message.preparing=preparando teste...
-SpeedTestWizard.stage.message.starting=iniciando o teste...
-SpeedTestWizard.stage.message.connect.stats=Estat\u00edsticas da conex\u00e3o: peers=%1, down_ok=%2, up_ok=%3
-window.uiswitcher.title=Escolhedor de IU do Vuze
-window.uiswitcher.text=Por favor selecione uma interface de usu\u00e1rio abaixo que melhor se ajusta as suas necessidades.
-window.uiswitcher.NewUI.text=* Recomendado para todos os usu\u00e1rios.\n\n* Interface f\u00e1cil, intuitiva.\n* Rica em recursos e configura\u00e7\u00f5es.
-window.uiswitcher.ClassicUI.title=Interface Cl\u00e1ssica
-window.uiswitcher.ClassicUI.text=* Mant\u00e9m a funcionalidade de cliente s\u00e9rie 2.x\n\n* Visualiza\u00e7\u00e3o por abas cl\u00e1ssico\n* Legado vista, reduzido conjunto de recursos.
-iconBar.switch.tooltip=Escolher a Interface de Usu\u00e1rio do Vuze
-VivaldiView.notAvailable=Visualiza\u00e7\u00e3o Vivaldi n\u00e3o dispon\u00edvel
-restart.error=Reiniciar falhou:\n%1\nVeja <A HREF="{restart.error.url}">problemas ao reiniciar</a>.
-restart.error.oom=Mem\u00f3ria Esgotada
-restart.error.fnf='%1' n\u00e3o encontrado em '%2'
-restart.error.pnf=Path '%1' n\u00e3o encontrado
-restart.error.bad=Arquivo de formato ruim para '%1'
-restart.error.denied=O acesso foi negado quando tentando executar '%1'.  Tenha certeza de que voc\u00ea tem os direitos para rodar este programa.
-TableColumn.header.date_completed=Completado Em
-TableColumn.menu.date_added.reset=Data do Reset
-ConfigView.section.ipfilter.discardbanning=Bloquear peers cuja propor\u00e7\u00e3o de dados descartados ruins/bons exceder [0: desativado]
-ConfigView.section.ipfilter.discardminkb=M\u00ednimo de %1 descartados antes de aplicar a propor\u00e7\u00e3o
-ConfigView.interface.start.advanced=Iniciar na Visualiza\u00e7\u00e3o Avan\u00e7ada (AZ 2.x)
-MyTorrents.column.ColumnQuality=Qualidade
-MyTorrents.column.ColumnSpeed=Velocidade
-MyTorrents.column.ColumnProgressETA.2ndLine=TEC: %1
-MyTorrents.column.ColumnProgressETA.StreamReady=Streaming Pronto
-MyTorrents.column.ColumnProgressETA.PlayableIn=Toc\u00e1vel em %1
-TableColumn.header.Quality=Qualidade
-TableColumn.header.Speed=Velocidade
-TableColumn.header.RateIt=Taxa
-TableColumn.header.Rating=Classifica\u00e7\u00e3o
-TableColumn.header.SpeedGraphic=Velocidade
-TableColumn.header.AzProduct=De
-TableColumn.header.MediaThumb=M\u00eddia
-TableColumn.header.ProgressETA=Progresso
-TableColumn.header.name.ext=Tipo de Arquivo: %1
-v3.MainWindow.tab.home=Painel
-v3.MainWindow.tab.browse=No Vuze
-v3.MainWindow.tab.library=Biblioteca
-v3.MainWindow.tab.publish=Publicar
-v3.MainWindow.tab.advanced=Avan\u00e7ado
-v3.MainWindow.menu.home=&Painel
-v3.MainWindow.menu.browse=&No Vuze
-v3.MainWindow.menu.library=&Biblioteca
-v3.MainWindow.menu.publish=&Publicar
-v3.MainWindow.menu.advanced=&Avan\u00e7ado
-v3.MainWindow.menu.view.searchbar=Barra de Busca
-v3.MainWindow.currentDL=Atualmente Baixando
-v3.MainWindow.button.stop=Parar
-v3.MainWindow.button.start=Iniciar
-v3.MainWindow.button.pause=Pausar
-v3.MainWindow.button.resume=Resumir
-v3.MainWindow.button.delete=Apagar
-v3.MainWindow.button.comment=Comentar
-v3.MainWindow.button.viewdetails=Ver Detalhes
-v3.MainWindow.button.play=Tocar
-v3.MainWindow.button.cancel=Cancelar
-v3.MainWindow.button.preview=Pr\u00e9-visualiza\u00e7\u00e3o
-v3.MainWindow.view.wait=Inicializando a visualiza\u00e7\u00e3o, por favor espere.
-v3.MainWindow.xofx=%1 de %2
-v3.MainWindow.Loading=Carregando.. Por favor espere
-v3.filter-bar=T\u00edtulo do Filtro:
-v3.MainWindow.search.defaultText=Procurar no Vuze
-v3.mb.delPublished.title=Parar de Ficar de Seed com este Conte\u00fado
-v3.mb.delPublished.text=AVISO: Esta a\u00e7\u00e3o N\u00c3O remover\u00e1 seu conte\u00fado publicado '%1' de <A HREF="%2">%3</A> .\n\nClique em "Apagar" apenas se voc\u00ea quer que o seu conte\u00fado permane\u00e7a publicado e baix\u00e1vel, mas quer liberar a sua banda. Tenha certeza de que o processo de upload foi completado antes de faz\u00ea-lo (<A HREF="%4">how</A>?).\n\nClique em "Cancelar" se voc\u00ea quer remover completamente seu conte\u00fado publicado de %3, e usar o bot\u [...]
-v3.mb.delPublished.delete=&Apagar
-v3.mb.delPublished.cancel=&Cancelar
-v3.mb.PlayFileNotFound.title=Arquivo N\u00e3o Encontrado
-v3.mb.PlayFileNotFound.text=Os arquivos para '%1' est\u00e3o ou apagados ou desaparecidos.
-v3.mb.PlayFileNotFound.button.remove=Remover do Vuze
-v3.mb.PlayFileNotFound.button.redownload=Baixar Dados de Novo
-v3.mb.PlayFileNotFound.button.find=Achar Manualmente..
-v3.topbar.menu.show.plugin=\u00c1rea dos Plugins
-v3.topbar.menu.show.search=Busca
-v3.topbar.menu.show.frog=O Sapo Azul
-splash.initializeCore=Iniiciando o Core
-splash.initializeUIElements=Inicializando os Elementos da Interface do Usu\u00e1rio
-ConfigView.section.transfer.autospeedbeta=Auto-Velocidade-Beta
-ConfigView.section.ipfilter.peerblocking.group=Bloqueio de Peers
-ConfigView.section.ipfilter.autoload.group=Auto Carregar
-ConfigView.section.ipfilter.autoload.file=Arquivo de filtro de IP para auto-carregar
-ConfigView.section.ipfilter.autoload.info=Suporta DAT (eMule), P2P (PeerGuardian, splist), e P2B v1,2,3 formatos do (PeerGuardian 2).  O arquivo pode ser local ou URL, zip'd, gzip'd ou texto simples. As URLs automaticamente ser\u00e3o baixadas de novo ap\u00f3s 7 dias, enquanto que os arquivos recarregar\u00e3o dentro de um minuto a serem substitu\u00eddos/tocados.
-ConfigView.section.ipfilter.autoload.loadnow=Carregar Agora
-splash.loadIpFilters=Carregando os Filtros de IP..
-SpeedTestWizard.set.upload.title=Definir Limites de Upload e Download
-SpeedTestWizard.set.download.label=Limite da Velocidade de Download:
-SpeedTestWizard.set.upload.label=Limite da Velocidade de Upload:
-SpeedTestWizard.name.conf.level.absolute=Absoluto
-SpeedTestWizard.name.conf.level.high=Alta
-SpeedTestWizard.name.conf.level.med=M\u00e9dia
-SpeedTestWizard.name.conf.level.low=Baixa
-SpeedTestWizard.name.conf.level.none=Nenhum
-ConfigView.section.transfer.select=Auto-Velocidade
-ConfigView.section.transfer.select.v2=Auto-Velocidade (beta)
-mb.azmustclose.title=Erro de Inicializa\u00e7\u00e3o
-mb.azmustclose.text=O Vuze deve fechar devido a um problema ao (re)iniciar o Vuze, isso provavelmente fez o programa ser executado como um usu\u00e1rio Administrador.\n\nAp\u00f3s o Vuze fechar, por favor re-abra-o manualmente.
-network.ipv6.prefer.addresses=Preferir os endere\u00e7os IPv6 quando ambos IPv6 e IPv4 est\u00e3o dispon\u00edveis
-network.bindError=Falhou em prender o socket do servidor como nenhum dos endere\u00e7os compat\u00edveis est\u00e3o dispon\u00edveis, por favor verifique suas configura\u00e7\u00f5es de prender-ao-IP.
-network.enforce.ipbinding=Refor\u00e7ar as amarras ao IP mesmo quando as interfaces n\u00e3o est\u00e3o dispon\u00edveis, impede quaisquer conex\u00f5es se nenhuma das interfaces especificadas est\u00e3o dispon\u00edveis
-DHTView.title.full_v6=Base de Dados Distribu\u00edda IPv6
-ConfigView.pluginlist.loadSelected=Carregar os Selecionados
-SpeedView.stats.asn=Rede:
-SpeedView.stats.estupcap=Limite de Upload:
-SpeedView.stats.estdowncap=Limite de Download:
-SpeedView.stats.unknown=Desconhecido
-SpeedView.stats.estimate=Estimativa
-SpeedView.stats.measured=Medido
-SpeedView.stats.measuredmin=M\u00edn. medido
-SpeedView.stats.manual=Consertado
-ConfigView.section.transfer.autospeed.networks=Detalhes da Rede
-ConfigView.section.transfer.autospeed.resetnetwork=Resetar detalhes da rede
-ConfigView.section.transfer.autospeed.network.info=Os limites acima s\u00e3o normalmente calculados automaticamente durante o download ou s\u00e3o o resultado de um teste de velocidade. Se voc\u00ea quer especific\u00e1-los manualmente use a op\u00e7\u00e3o abaixo.\nTodos os limites al\u00e9m dos 'consertados' ser\u00e3o subsequencialmente ajustados se necess\u00e1rio. \nInsira o valor e ent\u00e3o selecione seu tipo. Note que as velocidades est\u00e3o em %1.
-dialog.uiswitcher.restart.title=Trocador de Interface do Usu\u00e1rio: Requerido Reiniciar o Vuze
-dialog.uiswitcher.restart.text=O Vuze precisa reiniciar para trocar para o modo da nova Interface do Usu\u00e1rio.
-TrayWindow.menu.close=Fechar a Cesta de Download
-# Used for peers which we can't determine.
-PeerSocket.unknown=Desconhecido
-PeerSocket.fake_client=FALSO
-PeerSocket.bad_peer_id=ID do peer ruim
-PeerSocket.mismatch_id=n\u00e3o combinam
-PeerSocket.unknown_az_style=Desconhecido %1/%2
-PeerSocket.unknown_shadow_style=Desconhecido %1/%2
-OpenTorrentWindow.mb.askCreateDir.title=O Diret\u00f3rio Destino n\u00e3o existe
-OpenTorrentWindow.mb.askCreateDir.text=O diret\u00f3rio destino '%1' n\u00e3o existe.\n\nCriar agora?
-SpeedView.stats.estimatechoke=Estimativa (desobstru\u00e7\u00e3o)
-ConfigTransferAutoSpeed.upload.capacity.usage=Uso da Capacidade de Upload
-ConfigTransferAutoSpeed.mode=Modo:
-ConfigTransferAutoSpeed.capacity.used=% da Capacidade Usada
-ConfigTransferAutoSpeed.while.downloading=Baixando:
-ConfigTransferAutoSpeed.set.dht.ping=Configura\u00e7\u00e3o do Ping DHT:
-ConfigTransferAutoSpeed.set.point=definir ponto (ms)
-ConfigTransferAutoSpeed.set.tolerance=toler\u00e2ncia (ms)
-ConfigTransferAutoSpeed.ping.time.good=Bom:
-ConfigTransferAutoSpeed.ping.time.bad=Ruim:
-ConfigTransferAutoSpeed.adjustment.interval=Intervalo do ajuste:
-ConfigTransferAutoSpeed.skip.after.adjust=Pular ap\u00f3s o ajuste:
-GeneralView.label.distributedCopies=C\u00f3pias Distribu\u00eddas:
-PiecesView.DistributionView.title=Distribui\u00e7\u00e3o dos Peda\u00e7os
-PiecesView.DistributionView.NoAvl=Peda\u00e7os Indispon\u00edveis
-PiecesView.DistributionView.SeedAvl=Contribui\u00e7\u00e3o Avl do Seed
-PiecesView.DistributionView.PeerAvl=Contribui\u00e7\u00e3o Avl do Peer
-PiecesView.DistributionView.RarestAvl=Peda\u00e7os Mais Raros: %1 (Avl:%2)
-PiecesView.DistributionView.weHave=Peda\u00e7os que voc\u00ea tem
-PiecesView.DistributionView.theyHave=Peda\u00e7os que o peer tem
-PiecesView.DistributionView.weDownload=Peda\u00e7os que voc\u00ea est\u00e1 baixando
-PeersView.gain=Ganho
-PeersView.gain.info=Quantidade de dados baixados - enviados
-unix.script.new.title=Novo Script de Inicializa\u00e7\u00e3o do Vuze dispon\u00edvel
-unix.script.new.text=Um novo script de inicializa\u00e7\u00e3o do Vuze est\u00e1 dispon\u00edvel, e foi salvo em '%1'.\n\n\u00c9 altamente recomendado que voc\u00ea saia do Vuze e troque para este script ('%2').\n\nSe voc\u00ea modificou seu script de inicializa\u00e7\u00e3o do Vuze pesadamente, por favor veja <A HREF="{unix.script.new.manual.url}">AzureusWiki: Unix Script</A>.\n\nSe voc\u00ea instalou o Vuze de uma distro (yum, apt-get, etc), \u00e9 recomendado que voc\u00ea reinstale o [...]
-unix.script.new.button.quit=Sair Agora
-unix.script.new.button.continue=Eu o farei depois
-unix.script.new.button.asknomore=N\u00e3o me diga de novo
-unix.script.new.auto.title=Novo Script de Inicializa\u00e7\u00e3o do Vuze
-unix.script.new.auto.text=Um Novo Script de Inicializa\u00e7\u00e3o do Vuze est\u00e1 dispon\u00edvel.\n\n\u00c9 altamente recomendado que voc\u00ea reinicie o Vuze agora.
-Content.alert.notuploaded.button.abort=&N\u00e3o Sair
-ConfigView.label.checkOnSeeding=Realizar re-verifica\u00e7\u00e3o de baixo recurso de peda\u00e7os quando ficando de seed
-ConfigView.label.ui_switcher=Exibir o Escolhedor de Interface Gr\u00e1fica do Vuze
-ConfigView.label.ui_switcher_button=Mostrar
-SpeedTestWizard.test.panel.explain=Mede sua velocidade no protocolo do Vuze. Selecione o tipo de teste de velocidade e o modo de encripta\u00e7\u00e3o. Visite a p\u00e1gina do wiki do Vuze para detalhes sobre este teste. O teste parar\u00e1 automaticamente se ele levar mais do que 2 minutos. Testes t\u00edpicos terminam em menos de 1 minuto.
-SpeedTestWizard.set.upload.hint=Definir os limites de upload e download usados pelo algor\u00edtmo de AutoVelocidade do Vuze.
-SpeedTestWizard.set.upload.panel.explain=Os limites definidos aqui s\u00e3o usados pelo algor\u00edtmo de AutoVelocidade do Vuze. Defina os limites de transfer\u00eancia e os limites de confian\u00e7a.\n\nNote que as velocidades da linha s\u00e3o frequentemente quotadas em "bits por segundo" - contudo o valor abaixo \u00e9 mostrado em "kilobytes por segundo".
-SpeedTestWizard.set.limit.conf.level=Confian\u00e7a
-SpeedTestWizard.finish.panel.auto.speed=AutoVelocidade \u00e9 :
-SpeedTestWizard.finish.panel.auto.speed.seeding=AutoVelocidade enquanto ficando de seed \u00e9 : 
-ConfigTransferAutoSpeed.add.comment.to.log.group=Adicionar coment\u00e1rio ao log de debug
-ConfigTransferAutoSpeed.add.comment.to.log=Coment\u00e1rio:
-ConfigTransferAutoSpeed.algorithm.selector=Seletor de Auto-Velocidade
-ConfigTransferAutoSpeed.algorithm=Algor\u00edtmo:
-ConfigTransferAutoSpeed.auto.speed.classic=Auto-Velocidade(cl\u00e1ssica)
-ConfigTransferAutoSpeed.auto.speed.beta=Auto-Velocidade(beta)
-ConfigTransferAutoSpeed.data.update.frequency=Frequ\u00eancia da Atualiza\u00e7\u00e3o
-Alert.failed.update=A instala\u00e7\u00e3o de pelo menos um componente falhou. Veja <A HREF="{Alert.failed.update.url}">AzureusWiki: A Atualiza\u00e7\u00e3o Falhou</A>
-OpenTorrentWindow.mb.existingFiles.partialList=(Lista Parcial.  Mais arquivos j\u00e1 existem)
-TableColumn.header.bad_avail_time.info=\u00daltima vez que uma c\u00f3pia completa do download estava dispon\u00edvel
-TableColumn.header.bad_avail_time=C\u00f3pia Completa Vista
-MyTorrentsView.menu.exporthttpseeds=Export URLs de seed HTTP para a \u00c1rea de Transfer\u00eancia
-SWT.alert.erroringuithread=Um erro n\u00e3o manejado ocorreu na GUI, mais erros podem ser reportados.
-ConfigView.label.minannounce=Tempo m\u00ednimo entre an\u00fancios de tracker em segundos
-ConfigView.label.maxnumwant=Limitar o n\u00famero de peers que o tracker pode retornar
-ConfigView.label.announceport=N\u00e3o levar em conta a porta TCP anunciada para os an\u00fancios do tracker, pex e dht\n[deixar vazio: sem levar em conta, 0: sem conex\u00f5es de entrada]
-ConfigView.label.noportannounce=N\u00e3o anunciar a porta de escuta para o tracker (isto n\u00e3o afeta o pex, dht)
-ConfigView.label.maxseedspertorrent=M\u00e1x. de seeds por torrent padr\u00e3o [0: ilimitados] 
-wizard.webseed=Adicionar Seeds HTTP ao torrent
-wizard.webseed.title=Seeds HTTP
-wizard.webseed.configuration=Configur\u00e3\u00e7\u00e3o de Seed HTTP
-wizard.webseed.adding=Adicionar Seeds HTTP
-GeneralView.label.private=Torrent Privado:
-GeneralView.yes=sim
-GeneralView.no=n\u00e3o
-ConfigView.label.userequestlimiting=Usar pedido de throttling em vez de leituras atrasadas para limitar a velocidade de download [sem efeito quando a velocidade de download \u00e9 ilimitada]
-ConfigView.label.userequestlimiting.tooltip=Limitar Pedidos n\u00e3o \u00e9 t\u00e3o leve como as leituras atrasadas, mas permite a prioriza\u00e7\u00e3o do download baseado no posi\u00e7\u00e3o da fila do download e poderia melhorar a performance da rede
-ConfigView.label.userequestlimitingpriorities=Focar a velocidade do download no come\u00e7o da fila de download quando o limite da velocidade de download foi alcan\u00e7ado
-ConfigView.section.logging.timestamp=Formato da estampa de tempo para arquivos log
-Peers.column.timetocomplete=Tempo Restante
-Peers.column.timetocomplete.info=Tempo restante at\u00e9 o peer estar completo
-ConfigView.section.interface.display.suppress.file.download.dialog=Suprimir o di\u00e1logo popup do Download do Arquivo
-ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Mostrar todo o progresso do download do arquivo na barra de status em vez de um di\u00e1logo popup
-FileDownload.canceled=Um download de arquivo torrent foi cancelado com sucesso por uma a\u00e7\u00e3o do usu\u00e1rio: %1
-Progress.reporting.status.canceled=Cancelado
-Progress.reporting.status.finished=Terminou
-Progress.reporting.status.retrying=Tentando de Novo...
-Progress.reporting.action.label.retry.tooltip=Tentar de novo a opera\u00e7\u00e3o
-Progress.reporting.action.label.remove.tooltip=Remover este Relat\u00f3rio de Progresso do hist\u00f3rico
-Progress.reporting.action.label.cancel.tooltip=Cancelar a opera\u00e7\u00e3o
-Progress.reporting.action.label.detail=Detalhes
-Progress.reporting.default.error=Falhou
-Progress.reporting.no.reports.to.display=N\u00e3o h\u00e1 Relat\u00f3rios de Progresso para exibir desta vez
-Progress.reporting.no.history.to.display=N\u00e3o h\u00e1 mensagens detalhadas a exibir
-Progress.reporting.detail.history.limit=O limite de mensagens detalhadas (%1) para este ProgressReporter foi excedido; mensagens subsequentes ser\u00e3o adicionadas ao hist\u00f3rico
-Progress.reporting.statusbar.button.tooltip=Mostrar a Janela de Relat\u00f3rio do Progresso
-webui.bindip=Prender IP - normalmente n\u00e3o requerido (*)
-v3.MainWindow.text.log.in=Assinar pra entrar
-v3.MainWindow.text.log.out=Assinar pra sair
-v3.MainWindow.text.get.started=Se Inicie
-v3.MainWindow.text.my.account=Minha Conta
-v3.MainWindow.text.my.profile=Perfil
-OpenTorrentWindow.simple.open=Local do Torrent (Arquivo, URL, Hash)
-Progress.reporting.window.remove.auto=Automaticalmente remover itens inativos
-Progress.reporting.window.remove.auto.tooltip=Automaticalmente remover todos os processos completados, falhos ou cancelados da visualiza\u00e7\u00e3o
-Progress.reporting.window.remove.now=Remover itens inativos
-Progress.reporting.window.remove.now.tooltip=Remover todos os processos completados, falhos ou cancelados da visualiza\u00e7\u00e3o
-dhttracker.tracklimitedwhenonline=Contudo, realize rastreamento de baixo recurso quando online para cruzamento da popula\u00e7\u00e3o na multid\u00e3o
-TorrentOptionsView.multi.title.short=Op\u00e7\u00f5es do Torrent
-TorrentOptionsView.multi.title.full=Op\u00e7\u00f5es do Torrent
-MyTorrentsView.menu.open_parent_folder=Abrir a Pasta Contendo
-ConfigView.section.style.use_show_parent_folder=Usar "%1" em vez de "%2" nos menus do torrent
-ConfigView.section.style.use_show_parent_folder.tooltip=Ativar esta op\u00e7\u00e3o permitir\u00e1 a voc\u00ea abrir a pasta de conten\u00e7\u00e3o no aplicativo gerenciador de arquivos correto.\nContudo, pode significar que o local para salvar o download n\u00e3o \u00e9 selecionado automaticamente.
-PeerManager.status.ps_disabled=A fonte peer do Tracker est\u00e1 desativada
-ConfigView.section.stats.exportfiles=Exportar os detalhes do arquivo
-updater.cant.write.to.app.title=N\u00e3o P\u00f4de Escrever na Pasta do Aplicativo
-updater.cant.write.to.app.details=A pasta "%1" n\u00e3o pode ser escrita.\n\nIsto impedir\u00e1 que atualiza\u00e7\u00f5es futuras do software sejam aplicadas.\n\nPor favor <a href="http://www.azureuswiki.com/index.php/Failed_Update">veja o wiki para detalhes</a>.
-plugin.install.class_version_error=Este plugin requer uma vers\u00e3o mais nova do Java para rodar.
-v3.MainWindow.tab.events=Atividade
-button.columnsetup.tooltip=Configura\u00e7\u00e3o da Coluna
-v3.activity.remove.title=Remover a Entrada da Atividade
-v3.activity.remove.text=Voc\u00ea tem certeza de que voc\u00ea quer remover o evento da atividade '%1'?
-v3.MainWindow.menu.file.closewindow=Fechar
-Menu.show.torrent.menu=Mostrar o menu Torrents
-Menu.show.torrent.menu.tooltip=Mostra o menu Torrents na barra do menu do aplicativo no topo
-Views.plugins.aznetstatus.title=Status da Rede
-plugin.aznetstatus.pingtarget=Ping/trace a rota do alvo
-ConfigView.section.style.usePathFinder=Usar 'Descobridor de Caminhos' em vez do 'Descobridor'
-menu.sortByColumn=Organizar Por %1 
-MyTorrentsView.menu.manual.per_peer=Manual (por peer)
-MyTorrentsView.menu.manual.shared_peers=Manual (pelos peers)
-v3.button.removeActivityEntry=Remover a Entrada da Atividade
-v3.splash.initSkin=Inicializando a Skin da UI
-v3.splash.hookPluginUI=Enganchando na UI do Plugin
-OpenTorrentWindow.mb.notTorrent.cannot.display=Incapaz de exibir os dados apropriadamente
-MainWindow.menu.window.zoom.maximize=Maximizar
-MainWindow.menu.window.zoom.restore=Restaurar
-security.crypto.title=Acesso a Chave de Encripta\u00e7\u00e3o
-security.crypto.encrypt=Por favor insira uma senha para proteger sua chave de encripta\u00e7\u00e3o gerada recentemente. Por favor n\u00e3o esque\u00e7a esta senha, n\u00e3o h\u00e1 meio de recuper\u00e1-loa se voc\u00ea esquecer!
-security.crypto.decrypt=Por favor insira sua senha para destrancar sua chave de encripta\u00e7\u00e3o.
-security.crypto.reason=Motivo para a opera\u00e7\u00e3o
-security.crypto.password=Senha
-security.crypto.password2=Re-inserir a senha
-security.crypto.persist_for=Per\u00edodo de persist\u00eancia da senha
-security.crypto.persist_for.dont_save=N\u00e3o salvar
-security.crypto.persist_for.session=Esta sess\u00e3o
-security.crypto.persist_for.day=1 dia
-security.crypto.persist_for.week=1 semana
-security.crypto.persist_for.30days=30 dias
-security.crypto.persist_for.forever=Pra sempre
-security.crypto.password.mismatch.title=Erro com a Senha
-security.crypto.password.mismatch=Os valores inseridos da senha n\u00e3o combinam, por favor re-insira-os.
-ConfigView.section.security.group.crypto=Chaves P\u00fablicas/Privadas
-ConfigView.section.security.resetkey=Resetar as chaves
-ConfigView.section.security.resetkey.warning.title=Aviso sobre a Perda de Dados
-ConfigView.section.security.resetkey.warning=Voc\u00ea tem certeza que voc\u00ea quer resetar suas chaves de encripta\u00e7\u00e3o? Se voc\u00ea o fizer toda a informa\u00e7\u00e3o encriptada usando elas ser\u00e1 PERMANENTEMENTE PERDIDA. Tamb\u00e9m quaisquer outros peers em possess\u00e3o da sua chave p\u00fablica n\u00e3o mais ser\u00e3o capazes de comunicar com voc\u00ea sem eles obterem sua nova chave. Ent\u00e3o, a menos que voc\u00ea realmente saiba o que voc\u00ea est\u00e1 fazen [...]
-ConfigView.section.security.unlockkey=Destrancar as chaves explicitamente
-ConfigView.section.security.unlockkey.button=Destrancar
-ConfigView.section.security.publickey=Chave p\u00fablica
-ConfigView.section.security.publickey.undef=N\u00e3o definida ainda
-ConfigView.section.security.resetkey.error.title=A Opera\u00e7\u00e3o Falhou
-ConfigView.section.security.resetkey.error=Falhou em resetar as chaves
-ConfigView.section.security.unlockkey.error=Falhou em destrancar a chave - senha incorreta
-ConfigView.copy.to.clipboard.tooltip=Copiar para a \u00e1rea de transfer\u00eancia
-Views.plugins.azbuddy.title=Amigos
-Browser.popup.error.no.access=Um ocorreu enquanto tentava acessar um recurso remoto.\nPor favor tente de novo mais tarde.\n
-ConfigView.label.queue.stoponcebandwidthmet=N\u00e3o iniciar mais quaisquer torrents quando o limite da velocidade de upload/download for alcan\u00e7ado
-ConfigView.section.style.forceMozilla=For\u00e7ar o Vuze a usar o Mozilla para os widgets do Navegador [xulrunner ou firefox 3 requeridos; requer reiniciar]
-ConfigView.section.style.xulRunnerPath=Especificar o caminho do XulRunner / Firefox manualmente [requerido para o FF3; requer reiniciar]
-azbuddy.name=Amigos
-azbuddy.enabled=Ativado
-azbuddy.disabled=O plugin est\u00e1 desativado, veja a config do plugin para mudar.
-azbuddy.nickname=Seu Apelido
-azbuddy.msglog.title=Informa\u00e7\u00e3o sobre o Amigo
-azbuddy.addtorrent.title=Aceitar o Download?
-azbuddy.addtorrent.msg=O amigo '%1' enviou para voc\u00ea o '%2'.\nVoc\u00ea quer adicionar este download?
-azbuddy.contextmenu=Enviar para um Amigo
-azbuddy.ui.mykey=Minha chave:
-azbuddy.ui.add=Adicionar
-azbuddy.ui.new_buddy=Nova chave do amigo:
-azbuddy.ui.table.name=Nome
-azbuddy.ui.table.last_msg=\u00daltima Mensagem
-azbuddy.ui.menu.remove=Remover
-azbuddy.ui.menu.copypk=Copiar a Chave P\u00fablica
-azbuddy.ui.menu.send=Enviar Mensagem
-azbuddy.ui.menu.send_msg=Insira o texto a enviar para seu(s) amigo(s)
-azbuddy.ui.menu.ygm=Enviar o YGM
-azbuddy.ui.menu.enc=Encriptar a \u00c1rea de Transferencia
-azbuddy.ui.menu.dec=Decriptar a \u00c1rea de Transfer\u00eancia
-azbuddy.ui.menu.sign=Sinalizar a \u00c1rea de Transfer\u00eancia
-azbuddy.ui.menu.verify=Verificar a \u00c1rea de Transfer\u00eancia
-azbuddy.ui.table.lastseen=Visto pela \u00daltima Vez
-Button.retry=&Tentar de Novo
-Button.ignore=&Ignorar
-DHTView.general.skew=\u00c2ngulo:
-azbuddy.ui.table.msg_in=Msg Entra
-azbuddy.ui.table.msg_out=Msg Sai
-v3.MainWindow.menu.view.footer=Barra dos Amigos
-azbuddy.downspeed=M\u00e1x da velocidade de download em KB/s do amigo [0: ilimitada]
-security.crypto.badpw=A senha suprima estava incorreta
-ConfigView.section.security.backupkeys=Fazer backup das chave em um arquivo
-ConfigView.section.security.restorekeys=Restaurar as chaves de um arquivo
-ConfigView.section.security.restorekeys.button=Restaurar
-ConfigView.section.security.op.error.title=A Opera\u00e7\u00e3o Falhou
-ConfigView.section.security.op.error=Falhou em completar a opera\u00e7\u00e3o:\n    %1
-ConfigView.section.security.restart.title=Requer Reiniciar
-ConfigView.section.security.restart.msg=O Vuze reiniciar\u00e1 agora para completar a opera\u00e7\u00e3o.
-ConfigView.section.security.system.managed=Prote\u00e7\u00e3o da chave gerenciada pelo sistema
-azbuddy.ui.table.msg_queued=Na Fila
-azbuddy.ui.menu.chat=Bate-papo
-azbuddy.chat.title=Chat do Vuze
-azbuddy.chat.says=%1 diz:
-Button.bar.show=Mostrar
-Button.bar.hide=Esconder
-Button.bar.share=Compartilhar
-Button.bar.add=Adicionar Amigos
-Button.bar.edit=Editar
-Button.bar.edit.cancel=Edi\u00e7\u00e3o Feita
-v3.MainWindow.menu.view.pluginbar=Barra dos Plugins
-MainWindow.dialog.select.vuze.file=Selecionar o Arquivo do Vuze
-MainWindow.menu.file.open.vuze=Arquivo do Vuze...
-metasearch.addtemplate.title=Instalar o Modelo de Busca?
-metasearch.addtemplate.desc=Voc\u00ea tem certeza que voc\u00ea quer instalar um modelo de busca chamdo '%1'?
-v3.share.private.title=Compartilhando o Torrent
-v3.share.private.text=O torrent selecionado est\u00e1 marcado como Torrent Privado.\n\nVoc\u00ea n\u00e3o pode compartilhar torrents privados.
-metasearch.addtemplate.dup.title=Modelo Duplicado
-metasearch.addtemplate.dup.desc=O modelo de busca %1 j\u00e1 est\u00e1 instalado
-metasearch.export.select.template.file=Salvar o Modelo
-metasearch.import.select.template.file=Abrir o Modelo
-azbuddy.tracker.enabled=Ativar a 'Acelera\u00e7\u00e3o do Amigo' para priorizar o download com seus amigos
-azbuddy.protocolspeed=Eleva\u00e7\u00e3o m\u00e1xima do protocolo em KB/s do amigo
-v3.MainWindow.button.run=Executar o Arquivo Baixado
-v3.activity.header.vuze.news=Not\u00edcias do Vuze
-message.taking.too.long=Aparenta que isto est\u00e1 tomando mais tempo do que o esperado\nPressione 'ESC' se voc\u00ea deseja cancelar esta opera\u00e7\u00e3o
-message.status.success=Sucesso
-azbuddy.tracker.bbb.status.title=Acelera\u00e7\u00e3o do Amigo
-azbuddy.tracker.bbb.status.title.tooltip=Clique duplo para detalhes
-azbuddy.tracker.bbb.status.idle=Sem acelera\u00e7\u00e3o
-azbuddy.tracker.bbb.status.nli=Login Requerido
-azbuddy.tracker.bbb.status.in=Eu Estou Sendo Acelerado
-azbuddy.tracker.bbb.status.out=Atualmente Acelerando os Amigos
-v3.MainWindow.search.go.tooltip=Executar a Busca
-v3.MainWindow.search.last.tooltip=Retornar para os resultados da busca
-metasearch.addtemplate.done.title=Modelo Adicionado
-metasearch.addtemplate.done.desc=Modelo '%1' adicionado com sucesso.\nEle ser\u00e1 usado quando voc\u00ea fizer a pr\u00f3xima busca!
-ConfigView.section.security.nopw=Nenhuma senha foi fornecida
-ConfigView.section.security.nopw_v=Nenhuma senha dispon\u00edvel, por favor logue no Vuze
-fileplugininstall.install.title=Instalar o Plugin?
-fileplugininstall.install.desc=Voc\u00ea tem certeza que voc\u00ea quer instalar o plugin '%1', vers\u00e3o %2?
-fileplugininstall.duplicate.title=Plugin Duplicado
-fileplugininstall.duplicate.desc=O Plugin '%1', vers\u00e3o %2 j\u00e1 est\u00e1 instalado
-azbuddy.online_status=Status Online
-azbuddy.os_away=Distante
-azbuddy.os_not_avail=N\u00e3o Dispon\u00edvel
-azbuddy.os_busy=Ocupado
-azbuddy.ui.menu.disconnect=Desconectar
-azbuddy.enable_chat_notif=Ativar as notifica\u00e7\u00f5es do chat
-progress.window.msg.progress=Por favor espere enquanto a opera\u00e7\u00e3o completa
-ConfigView.section.connection.advanced.read_select=Ler o tempo pra encerrar selecionado (milis, padr\u00e3o %1)
-ConfigView.section.connection.advanced.read_select_min=Ler a espera m\u00ednima selecionada (milis, padr\u00e3o %1)
-ConfigView.section.connection.advanced.write_select=Gravar o tempo pra encerrar selecionado (milis, padr\u00e3o %1)
-ConfigView.section.connection.advanced.write_select_min=Gravar a espera m\u00ednima selecionada (milis, padr\u00e3o %1)
-DetailedListView.title=Lista Detalhada
-ConfigView.section.connection.network.max.outstanding.connect.attempts=M\u00e1x de conex\u00f5es de longo curso destacadas
-plugins.init.force_enabled=O Vuze detectou que o plugin "%1" foi desativado - ele foi reativado para permitir que o Vuze trabalhe apropriadamente.
-ConfigView.section.connection.prefer.udp=Preferir conex\u00f5es UDP
-subscript.add.title=Instalar a Subscri\u00e7\u00e3o?
-subscript.add.desc=Voc\u00ea tem certeza que voc\u00ea quer instalar a subscri\u00e7\u00e3o '%1'?
-subscript.add.dup.title=Duplicar a Subscri\u00e7\u00e3o
-subscript.add.dup.desc=A subscri\u00e7\u00e3o '%1' j\u00e1 est\u00e1 instalada.
-subscript.add.upgrade.title=Atualizar a Subscri\u00e7\u00e3o?
-subscript.add.upgrade.desc=Voc\u00ea tem certeza que voc\u00ea quer atualizar a subscri\u00e7\u00e3o '%1'?
-subscript.add.upgradeto.desc=A vers\u00e3o %1 da subscri\u00e7\u00e3o '%2' est\u00e1 dispon\u00edvel.\nVoc\u00ea quer atualizar?
-azsubs.contextmenu.addassoc=Adicionar a associa\u00e7\u00e3o de subscri\u00e7\u00e3o
-azsubs.contextmenu.lookupassoc=Procurar as associa\u00e7\u00f5es das subscri\u00e7\u00f5es
-iconBar.start=Iniciar
-iconBar.stop=Parar
-iconBar.remove=Apagar
-iconBar.up=Envio
-iconBar.down=Baixado
-iconBar.run=Executar
-iconBar.editcolumns=Configura\u00e7\u00e3o da Coluna
-iconBar.top=Mover pro topo
-iconBar.bottom=Mover pro fundo
-iconBar.queue=Iniciar
-iconBar.open=Adicionar Torrent
-iconBar.share=Compartilhar
-iconBar.share.tooltip=Compartilhar Conte\u00fado
-iconBar.details=Detalhes
-iconBar.comment=Coment\u00e1rio
-iconBar.play=Tocar
-iconBar.queue.tooltip=Enfileirar
-v3.MainWindow.menu.view.sidebar=Barra Lateral
-v3.MainWindow.menu.view.actionbar=Barra da A\u00e7\u00e3o
-v3.MainWindow.menu.view.toolbars=Barras de Ferramentas
-ump.install=Atualiza\u00e7\u00e3o R\u00e1pida em Progresso:\nInstalando um pequeno add-on de playback requerido para este v\u00eddeo.
-subscriptions.listwindow.title=Descobridor de Subscri\u00e7\u00f5es
-subscriptions.listwindow.autochecktext=O Vuze pode achar subscri\u00e7\u00f5es relacionadas ao conte\u00fado na sua biblioteca. Voc\u00ea quer ativar esta fun\u00e7\u00e3o?
-subscriptions.listwindow.loadingtext=Procurando subscri\u00e7\u00f5es relacionadas com %1
-subscriptions.listwindow.failed=Nenhuma subscri\u00e7\u00e3o Achada
-subscriptions.listwindow.popularity=Popularidade
-subscriptions.listwindow.popularity.unknown=Desconhecido
-subscriptions.listwindow.name=Nome
-subscriptions.listwindow.subscribe=Subscrever
-TableColumn.header.azsubs.ui.column.subs=Subscrever
-subscriptions.listwindow.popularity.reading=Lendo...
-PluginDeprecation.log.start=Esta janela cont\u00e9m informa\u00e7\u00e3o sobre plugins usando funcionalidades que ser\u00e3o removidas em futuras vers\u00f5es do Vuze.\nVoc\u00ea n\u00e3o precisa desinstalar os plugins, voc\u00ea deve apenas atualizar o plugin para a \u00faltima vers\u00e3o.\nSe voc\u00ea est\u00e1 rodando a \u00faltima vers\u00e3o, ent\u00e3o por favor copie o conte\u00fado desta janela e poste-o no f\u00f3rum localizado aqui:\n\t%1\n\n
-PluginDeprecation.log.details=---------\nIDENTIFICADOR: %1\nCONTE\u00daDO: %2\n\n*** COME\u00c7AR A RASTREAR ***\n%3*** FINALIZAR O RASTREAMENTO ***\n\n
-PluginDeprecation.view=Debug do Plugin
-PluginDeprecation.alert=Um plugin tentou usar uma funcionalidade a qual ser\u00e1 removida no futuro - por favor abra a visualiza\u00e7\u00e3o do Log do Debug do Plugin para mais informa\u00e7\u00e3o.
-TableColumn.header.Thumbnail=\u00cdcone
-TableColumn.header.Thumbnail.info=A imagem do thumbnail para o conte\u00fado do Vuze; para todos os outros conte\u00fados o sistema operacional est\u00e1 fornecendo estes \u00edcones.
-v3.MainWindow.menu.getting_started=&Sendo Iniciado
-MainWindow.menu.community=&Comunidade
-MainWindow.menu.community.wiki=Wiki da &Comunidade
-MainWindow.menu.community.forums=F\u00f3runs da Co&munidade
-MainWindow.menu.community.blog=Blog do &Vuze
-MainWindow.menu.help.support=&Ajuda e Suporte
-externalLogin.title=Login Requerido
-externalLogin.explanation=O modelo "%1" requer que voc\u00ea logue. Uma vez logado esta janela automaticamente fechar\u00e1. Se ela n\u00e3o fechar por favor clique em "feito".
-externalLogin.explanation.capture=Voc\u00ea precisa logar para criar este modelo. Uma vez que voc\u00ea est\u00e1, por favor clique em "Feito".
-Button.done=Feito
-GeneralView.torrent_created_on_and_by=%1 por %2
-Button.continue=Continuar
-Button.preview=Pr\u00e9-visualizar
-Subscription.menu.forcecheck=Atualizar Agora
-Subscription.menu.clearall=Marcar Todos Os Resultados Como Lidos
-Subscription.menu.remove=Apagar
-sidebar.Library=Minha Biblioteca
-sidebar.LibraryDL=Baixando
-sidebar.LibraryCD=Completados
-authenticator.location=Local
-authenticator.details=Detalhes
-v3.MainWindow.menu.showActionBarText=Mostrar o Texto
-subscript.import.fail.title=Falhou em Importar
-subscript.import.fail.desc=Detalhes: %1
-Subscription.menu.export=Exportar
-subscript.export.select.template.file=Salvar a Subscri\u00e7\u00e3o
-Button.remove=Remover
-Button.send=Enviar
-Button.back=Voltar
-sidebar.LibraryUnopened=N\u00e3o Observado
-TableColumn.header.unopened=Novo
-Unopened.bigView.header=Novo
-Subscription.menu.deleteall=Apagar Todos os Resultados
-Subscription.menu.reset=Resetar Ao Estado Inicial
-ConfigView.section.Subscriptions=Subscri\u00e7\u00f5es
-subscriptions.config.maxresults=N\u00famero m\u00e1ximo de resultados retidos por subscri\u00e7\u00e3o [0: ilimitados]
-v3.activity.button.readall=Marcar Todos os Lidos
-TableColumn.header.activityNew=Novo
-TableColumn.header.activityType=Tipo
-TableColumn.header.activityText=Mensagem
-TableColumn.header.activityDate=Data Adicionada
-TableColumn.header.activityActions=A\u00e7\u00f5es
-Subscription.menu.resetauth=Resetar os Detalhes da Autentica\u00e7\u00e3o
-Search.menu.engines=Modelos
-Wizard.Subscription.title=Subscrever
-Wizard.Subscription.optin.title=Ativar Subscri\u00e7\u00f5es
-Wizard.Subscription.subscribe.title=Subscri\u00e7\u00f5es Dispon\u00edveis
-Wizard.Subscription.create.title=Criar Nova Subscri\u00e7\u00e3o
-Button.search=Procurar
-Button.save=Salvar
-Button.add=Adicionar
-Button.add.tooltip=Adic. um torrent \u00e0 sua biblioteca
-Button.createNewSubscription=Criar Nova Subscri\u00e7\u00e3o
-Button.availableSubscriptions=Subscri\u00e7\u00f5es Dispon\u00edveis
-Wizard.Subscription.optin.description=Com as Subscri\u00e7\u00f5es ativadas, o Vuze mostrar\u00e1 a voc\u00ea subscri\u00e7\u00f5es relacionadas ao conte\u00fado na sua Biblioteca e deixar\u00e1 voc\u00ea saber quando seu conte\u00fado subscrito est\u00e1 dispon\u00edvel para download.\n\nVoc\u00ea gostaria de ativar as Subscri\u00e7\u00f5es?
-Wizard.Subscription.create.search=Busca
-Wizard.Subscription.search.subtitle1=Digite uma busca para come\u00e7ar a criar sua subscri\u00e7\u00e3o :
-Wizard.Subscription.search.subtitle2=O que eu posso procurar?
-Wizard.Subscription.search.subtitle2.sub1=Filmes em HD, Shows da TV, Filmes, Trailers na Rede Vuze
-Wizard.Subscription.search.subtitle2.sub2=Torrents da Web
-Wizard.Subscription.search.subtitle3=Uma vez que a sua subscri\u00e7\u00e3o \u00e9 completada, voc\u00ea receber\u00e1 atualiza\u00e7\u00f5es ao vivo na sua barra lateral sempre que novos resultados est\u00e3o dispon\u00edveis para sua busca.
-Wizard.Subscription.rss.subtitle1=Digite ou cole a URL abaixo:
-Wizard.Subscription.rss.subtitle2=Muitos editores fornecem feeds RSS do conte\u00fado deles, Localize a URL no website do editor, copie e cole a URL no campo acima, ent\u00e3o clique em Salvar.
-Wizard.Subscription.rss.subtitle3=Uma vez salvo, voc\u00ea receber\u00e1 atualiza\u00e7\u00f5es ao vivo na sua barra lateral sempre que novos resultados est\u00e3o dispon\u00edveis via seu feed RSS.
-Wizard.Subscription.subscribe.library=Conte\u00fado na sua Biblioteca
-Wizard.Subscription.subscribe.subscriptions=Subscri\u00e7\u00f5es Relacionadas
-Wizard.Subscription.subscribe.library.empty=Sem subscri\u00e7\u00f5es dispon\u00edveis?\n \nProcure pelo bot\u00e3o para subscrever laranja brilhante na Rede HD do Vuze.\n \n<A HREF="http://wiki.vuze.com/w/FAQ_Subscriptions">Leia mais</A>
-message.confirm.delete.title=Confirmar a Exclus\u00e3o
-message.confirm.delete.text=Voc\u00ea tem certeza que voc\u00ea quer apagar o '%1'?
-Subscription.menu.properties=Propriedades
-props.window.title=Propriedades para o '%1'
-subs.prop.is_auto=Auto-baixar os novos resultados
-subs.prop.last_scan=\u00daltima atualiza\u00e7\u00e3o bem sucedida
-subs.prop.last_result=\u00daltimo novo resultado achado
-subs.prop.last_error=\u00daltimo erro
-subs.prop.num_read=N\u00famero dos resultados de leitura
-subs.prop.num_unread=N\u00famero de resultados n\u00e3o lidos
-subs.prop.template=Modelo
-subs.prop.auth=Autentica\u00e7\u00e3o requerida
-externalLogin.auth_method_proxy=Usar m\u00e9todo de captura de cookies extendido. Se isto falhar em funcionar, desative a op\u00e7\u00e3o e tente de novo
-externalLogin.wait=Carregando a p\u00e1gina, por favor espere...
-TableColumn.menu.date_added.time=Mostrar/Esconder o Tempo
-sidebar.VuzeHDNetwork=Rede HD do Vuze
-subs.prop.next_scan=Pr\u00f3ximo scan em
-subs.prop.assoc=Associa\u00e7\u00f5es
-subs.prop.version=Vers\u00e3o
-subscriptions.column.new=Novo
-subscriptions.column.new.info=Indica se h\u00e1 um ou mais resultados novos
-subscriptions.column.name=Subscri\u00e7\u00e3o
-subscriptions.column.nb-results=Total de Resultados
-subscriptions.column.nb-new-results=Novos Resultados
-subscriptions.column.last-checked=Verificado Pela \u00daltima Vez
-subscriptions.view.title=Subscri\u00e7\u00f5es
-subs.prop.is_public=P\u00fablico
-subs.prop.high_version=Maior vers\u00e3o encontrada
-Subscription.menu.upgrade=Ativar A Atualiza\u00e7\u00e3o Para A Vers\u00e3o Maior
-metasearch.template.version.bad=O modelo da busca '%1' n\u00e3o pode ser instalado at\u00e9 que voc\u00ea atualize o Vuze
-metasearch.addtemplate.failed.title=A Instala\u00e7\u00e3o Falhou
-metasearch.addtemplate.failed.desc=Falhou em instalar o modelo da busca: %1
-subscription.version.bad=A subscri\u00e7\u00e3o '%1' n\u00e3o pode ser instalado at\u00e9 que voc\u00ea atualize o Vuze
-statusbar.feedback=Enviar Feedback   
-statusbar.feedback.tooltip=Clique aqui para enviar feedback
-sidebar.Activity=Notifica\u00e7\u00f5es
-v3.activity.button.watchall=Marcar Todos os Observados
-subscriptions.view.help.1=Adicionar Subscri\u00e7\u00f5es onde quer que voc\u00ea veja
-subscriptions.view.help.2=Obtenha atualiza\u00e7\u00f5es ao vivo gr\u00e1tis sempre que novo conte\u00fado est\u00e1 dispon\u00edvel para baixar. <A HREF="http://wiki.vuze.com/w/FAQ_Subscriptions">Leia mais</A>.
-sidebar.sash.tooltip=F7 para rapidamente esconder/mostrar a barra lateral
-sidebar.expand.tooltip=Expandir a Barra Lateral
-sidebar.dropdown.tooltip=Mostrar a barra lateral no formato do menu
-subscript.all.subscribed=Voc\u00ea est\u00e1 subscrito a este conte\u00fado
-subscript.some.subscribed=Voc\u00ea est\u00e1 subscrito a algumas das subscri\u00e7\u00f5es para este conte\u00fado.\nClique para ver as outras dispon\u00edveis
-subscript.none.subscribed=Clique para ver as subscri\u00e7\u00f5es dispon\u00edveis para este conte\u00fado
-v3.iconBar.up.tooltip=Mover pra Cima\nSegure o bot\u00e3o do mouse para mover pro topo
-v3.iconBar.down.tooltip=Mover pra Baixo\nSegure o bot\u00e3o do mouse para mover para o fundo
-TableColumn.header.azsubs.ui.column.subs_link=Associa\u00e7\u00e3o
-TableColumn.header.azsubs.ui.column.subs_link.info=Associados com as subscri\u00e7\u00f5es
-Button.deleteContent.fromLibrary=Remover da Biblioteca
-Button.deleteContent.fromComputer=Apagar do Computador
-v3.deleteContent.message=\nVoc\u00ea gostaria de apagar o '%1' do seu computador ou apenas remov\u00ea-lo da sua Biblioteca do Vuze?
-v3.MainWindow.menu.view.toolbartext=Texto da Barra de Ferramentas
-v3.MainWindow.menu.view.asSimpleList=Lista Simples
-v3.MainWindow.menu.view.asAdvancedList=Lista Avan\u00e7ada
-v3.MainWindow.menu.view.statusbar=Barra de Status
-Subscription.menu.dirtyall=Marcar Todos Os Resultados Como N\u00e3o Lidos
-configureWizard.file.message3=O Vuze baixar\u00e1 os arquivos em uma pasta espec\u00edfica, voc\u00ea pode escolher esta pasta aqui:
-v3.deleteContent.applyToAll=Aplicar a a\u00e7\u00e3o a todas as %1 entradas selecionadas
-ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrents que n\u00e3o fazem upload de nada
-v3.MainWindow.menu.contentnetworks=Redes &HD
-v3.MainWindow.menu.contentnetworks.about=Sobre as Redes HD
-Peers.column.as.info=Detalhes do AS do PEER (Sistema Aut\u00f4nomo)
-ConfigView.label.autoopen.downloadbars=Auto-abrir as Barras de Download quando
-ConfigView.label.autoopen=Auto-Abrir
-ConfigView.label.autoopen.detailstab=Auto-abrir a Aba de Detalhes quando
-ConfigView.label.systray=Tray do Sistema
-ConfigView.label.systray._mac=\u00cdcone da Barra de Status
-ConfigView.section.interface.legacy=Legado
-v3.MainWindow.menu.contentnetworks.manage=&Gerenciar as Redes HD
-azbuddy.ui.table.rem_cat=Gatos dentro
-azbuddy.ui.menu.cat=Categorias
-azbuddy.ui.menu.cat.share=Ativar as subscri\u00e7\u00f5es com amigo(s)
-azbuddy.ui.menu.cat.set=Inserir categorias
-azbuddy.ui.menu.cat.set_msg=Lista das categorias separadas por v\u00edrgula, ou 'Todas'
-azbuddy.ui.menu.cat_subs=Subscrever
-subs.prop.update_period=Per\u00eddo de atualiza\u00e7\u00f5es
-azbuddy.enable_cat_pub=Categorias p\u00fablicas nas quais todos os seus amigos podem subscrever (separadas por ',' ) 
-azbuddy.ui.table.read_cat=Leitura do gato
-TableColumn.header.#=Ordem
-TableColumn.header.#.info=N\u00famero da Posi\u00e7\u00e3o/Ordenamento
-TableColumn.header.category.info=Nome da categoria a qual o torrent pertence
-TableColumn.header.DateCompleted.info=Data em que o download do torrent foi completado
-TableColumn.header.AzProduct.info=Rede de Conte\u00fado da qual o torrent se originou
-TableColumn.header.health.info=Qu\u00e3o saud\u00e1vel sua conex\u00e3o com a multid\u00e3o do torrent \u00e9
-TableColumn.header.maxuploads.info=# m\u00e1ximo de peers aos quais faz upload simult\u00e2neamente
-TableColumn.header.name.info=Nome do torrent
-TableColumn.header.unopened.info=Bandeira para indicar se o torrent foi reproduzido (aberto)
-TableColumn.header.savepath.info=A pasta ou arquivo destino para os dados do torrent
-TableColumn.header.SeedingRank.info=Valor do ranking de qu\u00e3o terrivelmente o torrent precisa de seeding. Valor mais alto quer dizer maior necessidade.
-TableColumn.header.shareRatio.info=Quanto voc\u00ea fez de upload (compartilhou) em compara\u00e7\u00e3o a quanto voc\u00ea baixou.
-TableColumn.header.size.info=Tamanho do conte\u00fado do torrent no disco
-TableColumn.header.azsubs.ui.column.subs.info=Bot\u00e3o que permite a voc\u00ea subscrever ao feed contendo os torrents relacionados
-TableColumn.header.upspeed.info=Velocidade de upload atual
-TableColumn.header.downspeed.info=Velocidade de download atual
-TableColumn.header.up.info=Quantia de dados atuais enviada para outros usu\u00e1rios
-TableColumn.header.down.info=Quantia de dados atuais recebida dos outros usu\u00e1rios
-TableColumn.header.ProgressETA.info=Combina as colunas de Status, Completamento, TEC e Velocidade de Download em uma coluna multi-alinhada.
-TableColumn.header.eta.info=Tempo estimado antes que seja feito o download do torrent 
-Pieces.column.#.info=N\u00famero de Peda\u00e7os
-Peers.column.%.info=Porcentagem do torrent que o peer baixou at\u00e9 agora
-TableColumn.header.download.info=Quantia de dados recebida do peer
-TableColumn.header.upload.info=Quantia de dados que n\u00f3s enviamos para o epeer
-TableColumn.header.downloadspeed.info=Taxa da qual n\u00f3s estamos recebendo do peer
-TableColumn.header.uploadspeed.info=Taxa na qual n\u00f3s estamos enviando dados para o peer
-TableColumn.header.lan.info=Bandeira indicando se o peer est\u00e1 na sua LAN
-TableColumn.header.downloadspeedoverall.info=Taxa de download estimada do peer
-Peers.column.pieces.info=Barra gr\u00e1fica representando quais peda\u00e7os o peer baixou
-TableColumn.header.TableColumnNameInfo=Nome e Descri\u00e7\u00e3o da Coluna
-TableColumn.header.TableColumnSample=Amostra
-TableColumn.header.TableColumnInfo=Descri\u00e7\u00e3o da Coluna
-TableColumn.header.TableColumnChosenColumn=Escolher a Coluna
-subs.prop.is_auto_ok=Auto-download permitido
-label.learnmore=Aprender Mais
-ColumnSetup.title=Configura\u00e7\u00e3o das Colunas para '%1'
-ColumnSetup.explain=Explorar as colunas dispon\u00edveis a esquerda e adicion\u00e1-las a lista de colunas vis\u00edveis a direita. Expandir ou retrair a lista de colunas dispon\u00edveis usando a se\u00e7\u00e3o dos Filtros no parte de baixo a esquerda. Arrastar e Soltar e os atalhos do teclado tamb\u00e9m s\u00e3o suportados. 
-ColumnSetup.chosencolumns=Colunas Escolhidas
-ColumnSetup.proficiency=Profici\u00eancia:
-ColumnSetup.categories=Categorias:
-ColumnSetup.filters=Filtros
-ColumnSetup.availcolumns=Dispon\u00edveis %1 colunas
-ColumnSetup.availcolumns.filteredby=Dispon\u00edveis %1 colunas filtradas por %2
-devices.view.title=Dispositivos
-device.mediaserver.view.title=Servidores de M\u00eddia
-device.router.view.title=Roteadores
-device.model.desc=Descri\u00e7\u00e3o do Modelo
-device.model.name=Nome do Modelo
-device.model.num=N\u00famero do modelo
-device.manu.desc=Fabricante
-device.router.is_mapping=Mapeamento autom\u00e1tico de portas
-device.router.req_map=Mapeamentos obrigat\u00f3rios
-device.router.configure=Configurar UPnP
-device.mediaserver.configure=Configurar Meu Servidor de M\u00eddia
-device.hide=Ocultar Dispositivo
-device.show=Mostrar dispositivos ocultos
-device.search=Buscar por Dispositivos
-device.router.con_type=Conex\u00e3o: %1
-device.browse=Navegar
-device.upnp.desc_url=Descri\u00e7\u00e3o do Dispositivo
-device.upnp.present_url=Administra\u00e7\u00e3o de Dispositivos
-ConfigView.label.maxStalledSeeding=M\u00e1ximo 'stalled' [0:ilimitado]
-device.search.auto=Automaticamente procurar dispositivos
-devices.sidebar.simple=Visualiza\u00e7\u00e3o Simples
-devices.xcode.working_dir=\u00c1rea Transcode
-devices.xcode.prof_def=Perfil transcode Padr\u00e3o
-devices.xcode.profs=Perfis transcode Dispon\u00edveis
-device.lastseen=Visto pela \u00faltima vez
-devices.contextmenu.xcode=Transcondifica Para Dispositivo
-devices.device=Dispositivo
-devices.profile=Perfil
-General.percent=Porcentagem
-devices.installed=Instalado
-devices.comp.missing=Suporte do Vuze n\u00e3o instalado
-devices.state=Estado
-MainWindow.menu.help.donate=&Fa\u00e7a uma Doa\u00e7\u00e3o !!!
-DonationWindow.noload.title=Doa\u00e7\u00e3o
-DonationWindow.noload.text=A janela de doa\u00e7\u00e3o n\u00e3o conseguiu carregar. Por favor, tente novamente mais tarde.
-devices.xcode.only.show=Mostrar apenas arquivos Transcoded no dispositivo
-device.quit.transcoding.title=Transcodificar em andamento
-device.quit.transcoding.text='%1' est\u00e1 convertendo atualmente para '%2' e est\u00e1 %3% completo.\nISe voc\u00ea sair agora, ir\u00e1 ser necess\u00e1rio reiniciar do come\u00e7o na pr\u00f3xima vez.
-download.removerules.unauthorised.data=\tRemover Dados
-device.xcode.always=Sempre
-device.xcode.whenreq=Quando requerido
-device.xcode.never=Nunca
-devices.copy.pending=C\u00f3pia de arquivo pendente
-devices.sidebar.hide.rend.generic=Ocultar dispositivos gen\u00e9ricos
-v3.devicesview.infobar.text2=Para transcodificar conte\u00fado para um dispositivo, basta arrastar o conte\u00fado de sua biblioteca para os dispositivos na barra lateral. Para ver transcodifica conclu\u00eddas, clique no dispositivo individual na direita.
-iconBar.transcode=Dispositivo
-iconBar.transcode.tooltip=Fazer m\u00eddia dispon\u00edvel para um dispositivo
-device.retry.copy=Repetir C\u00f3pia
-devices.copy.fail=Falha na c\u00f3pia para o dispositivo
-devices.on.demand=Sobre a demanda
-devices.ready=Pronto
-TableColumn.header.trancode_qpos.info=Posi\u00e7\u00e3o na fila Transcode
-TableColumn.header.profile=Dispositivo
-TableColumn.header.profile.info=Perfil Usado para Transcodificar
-TableColumn.header.copied=Copiado
-TableColumn.header.device=Dispositivo
-TableColumn.header.device.info=Dispositivo Alvo
-TableColumn.header.trancode_completion=Progresso da Convers\u00e3o
-# This is the beginning of the word "View".  It's right aligned under the icon bar item
-v3.iconBar.view.big.tooltip=Ver como Lista Simples
-# This is the end of the word "View".  It's left aligned under the icon bar item
-v3.iconBar.view.small.tooltip=Ver como lista avan\u00e7ada
-general.dont.ask.again=N\u00e3o perguntar de novo
-v3.menu.device.exploreTranscodes=Mostrar arquivos
-v3.menu.device.exploreTranscodes._windows=Mostrar arquivos no Explorer
-v3.menu.device.exploreTranscodes._mac=Mostrar arquivos no Finder
-v3.menu.device.defaultprofile=Perfil padr\u00e3o
-devices.button.installitunes=Instale Integra\u00e7\u00e3o com iTunes
-device.itunes.install=Voc\u00ea precisa do iTunes instalado
-device.itunes.start=Voc\u00ea precisa come\u00e7ar a iTunes ou ativar in\u00edcio autom\u00e1tico
-device.itunes.install_problem=Parece haver um problema com a integra\u00e7\u00e3o com o iTunes
-devices.downloading=Baixando
-TableColumn.header.duration=Dura\u00e7\u00e3o
-TableColumn.header.resolution=Resolu\u00e7\u00e3o
-devices.xcode.autoStart=Iniciar automaticamente quando necess\u00e1rio
-option.askeverytime=Perguntar sempre
-option.rememberthis=Lembre-se esta defini\u00e7\u00e3o
-devices.associate=Associado com
-devices.associate.already=J\u00e1 associado
-devices.always.cache=Cache de arquivos  n\u00e3o-transcodificado 
-devices.turnon.prepageload=Para ativar esse recurso, instala\u00e7\u00e3o de componentes extras \u00e9 requerida.
-devices.turnon.itunes=Inclu\u00eddo suporte para iTunes (requerido para dispositivos da Apple)
-devices.turnon.qos=Compartilhar estatisticas an\u00f4nimas com Vuze
-devices.turnon.title=Ativar Suporte \u00e0 Dispositivo
-devices.choose.device.title=Selecione um dispositivo de reprodu\u00e7\u00e3o do video:
-devices.choose.profile.info.text=Ap\u00f3s a sele\u00e7\u00e3o, Vuze vai detectar ou n\u00e3o o formato de v\u00eddeo ser\u00e1 reproduzido no dispositivo selecionado e criar uma c\u00f3pia compat\u00edvel com o dispositivo, se necess\u00e1rio.\n\nPasse o mouse sobre o dispositivo selecionado para ver mais detalhes.
-devices.choose.profile.info.title.selected=%1 detalhes:
-devices.view.heading=Convertendo m\u00eddia para reprodu\u00e7\u00e3o em dispositivo
-device.view.heading=M\u00eddia para %1
-devices.choose.device.info.title=Dica Dispositivo
-devices.choose.device.info.text=Da pr\u00f3xima vez, basta arrastar e soltar arquivos para o dispositivo de sua escolha na barra lateral.
-label.clickone=Clique em um
-Button.turnon=Ligar
-ConfigView.label.dm.dblclick=D\u00ea um duplo clique em Exibir torrents:
-ConfigView.option.dm.dblclick.play=Executar Conte\u00fado
-ConfigView.option.dm.dblclick.details=Abrir Visualiza\u00e7\u00e3o de Detalhes do Torrent
-ConfigView.option.dm.dblclick.show=Mostrar Arquivo
-ConfigView.option.dm.dblclick.show._mac=Mostrar Arquivo(s) no Finder
-ConfigView.option.dm.dblclick.show._windows=Mostrar Arquivo(s) no Explorer
-xcode.deletedata.title=Excluir conte\u00fado transcodificado
-xcode.deletedata.message=Tem certeza de que quer apagar definitivamente a c\u00f3pia de '%1' transcodificado para '%2'%3?
-xcode.deletedata.message.2=\n(uma c\u00f3pia ainda pode existir no '%1')
-v3.deviceview.infobar.line1=Arrastar e soltar os v\u00eddeos da sua biblioteca para o dispositivo de sua escolha.
-v3.deviceview.infobar.line2=Jogue seus v\u00eddeos em qualquer de suas telas - iPad, iPhone, iPod, TV
-v3.deviceview.infobar.line1.generic=Arrastar e soltar os v\u00eddeos de sua biblioteca para %1 em sua barra lateral.
-v3.deviceview.infobar.line2.itunes=V\u00eddeos aparecer\u00e1 na pasta de filmes do iTunes quando eles est\u00e3o prontos para jogar.
-v3.deviceview.infobar.line2.xbox=Transmitir v\u00eddeos, indo para o seu Xbox 360 e selecionando Meu XBox -> Biblioteca de V\u00eddeo -> Vuze.
-v3.deviceview.infobar.line2.ps3=Transmitir v\u00eddeos, indo para o seu PS3 e selecionando V\u00eddeos -> Vuze.
-devices.copy_url=Copiar URL da Stream para \u00c1rea de Transfer\u00eancia
-devices.converting=Convertendo
-Button.reload=Recarregar
-devices.auto.start=Auto-iniciar
-Subscription.menu.setcookies=Definir cookies
-general.enter.cookies=Digitar Cookies
-device.config.xcode.workdir=Padr\u00e3o diret\u00f3rio de trabalho para arquivos transcodificados
-MyTorrentsView.menu.clear_alloc_data=Limpar Estado de Aloca\u00e7\u00e3o
-DiskManager.error.nospace=Espa\u00e7o em disco insuficiente
-DiskManager.error.nospace_fat32={DiskManager.error.nospace} - checar {wiki.fat32}
-ConfigView.section.file.rename.incomplete=Adicionar sufixo para arquivos incompletos
-subscriptions.config.autostartdls=Iniciar automaticamente downloads quando adicionado (ao contr\u00e1rio de coloc\u00e1-los em um estado parado)
-subscriptions.config.autostart.min=S\u00f3 come\u00e7am  se >= MB [0: ilimitado]
-subscriptions.config.autostart.max=S\u00f3 come\u00e7am se <= MB [0: ilimitado]
-dlg.corewait.title=Inicializando N\u00facleo
-dlg.corewait.text=Um Momento Por Favor...\n\nSeu pedido ir\u00e1 ser processado depois do Vuze tiver completado a inicializa\u00e7\u00e3o
-library.core.wait=Um momento, por favor...\nO cliente Vuze est\u00e1 inicializando
-ConfigView.label.StartUIBeforeCore=Iniciar UI antes de iniciar o n\u00facleo
-general.add.friends=Adicione alguns amigos!
-general.all.friends=Todos os Amigos
-friend.mod.subs=Bot\u00e3o direito do mouse para alterar assinaturas
-TableColumn.header.class=Classe
-device.rss.group=RSS Fedd local
-devices.xcode.rsspub=Publicar feed RSS
-device.rss.enable=Criar um feed RSS para o arquivo convertido - isto faz o conte\u00fado dispon\u00edvel para leitores de feed RSS
-device.rss.port=Porta feed RSS
-device.rss.view=Clique para exibir RSS feed
-device.rss.localonly=Restringir o acesso a este computador s\u00f3
-devices.xcode.autoCopy=Copiar automaticamente para a pasta
-devices.xcode.setcopyto=Definir Copiar para pasta ...
-devices.xcode.setcopyto.title=Escolha copiar para localiza\u00e7\u00e3o
-devices.copy.folder.auto=Automaticamente copiar os arquivos para a pasta
-devices.copy.folder.dest=Copiar para pasta
-TableColumn.menu.maxuploads=# Uploads no M\u00e1x.
-devices.xcode.mancopy=Copiar Manualmente Arquivos
-devices.xcode.show.cat=Separar por Categoria
-devices.cat.show=Exibir Categorias
-devices.tivo.machine=Nome da m\u00e1quina TiVo
-devices.info.copypending=%1 Arquivo(s) Aguardando Para Serem Copiados
-device.error.xcodefail=Convers\u00e3o Falhou
-device.error.copyfail=Um Ou Mais Arquivos Falharam Ao Copiar Para Pasta
-device.error.copytonotset="Copiar para pasta" n\u00e3o informado
-device.error.copyfail2=Um Ou Mais Arquivos Falharam Ao Copiar Para Dispositivo
-v3.deviceview.infobar.line2.tivo=Transmitir v\u00eddeos, indo para o seu TiVo e selecionando Vuze na Lista de Reprodu\u00e7\u00e3o.
-v3.deviceview.infobar.line2.psp=V\u00eddeos ser\u00e3o copiados para o PSP quando ele est\u00e1 conectado.
-devices.info.copypending2=%1 Arquivo(s) Aguardando Para Ser Copiados, Conecte Seus Dispositivos
-subscriptions.column.nb-subscribers=Assinantes
-device.od.enable=Habilitar download offline dos dispositivos
-device.odauto.enable=Gerenciar automaticamente os downloads
-device.odpt.enable=Incluir torrents privados
-devices.contextmenu.od=Baixando Offline
-devices.contextmenu.od.auto=<Autom\u00e1tico>
-devices.contextmenu.od.enable=Habilitado
-devices.contextmenu.od.enabled=Desabilitado
-devices.od.view.heading=Downloads agendados para download off-line
-DevicesOD.column.od_completion=Progresso da Tranfer\u00eancia
-devices.od.idle=Ocioso
-device.od.turnon.title=Ligar suporte para downloader offline
-device.is.disabled=Dispositivo est\u00e1 desabilitado
-device.configure=Configurar...
-device.od.error.notfound=Dispositivo parece estar offline
-device.od.error.opfailstatus=Dispositivo falhou ao processar o comando %1: status %2
-device.od.error.opfailexcep=O dispositivo falhou ao processar comando %1: exce\u00e7\u00e3o %2
-device.od.error.nospace=Sem espa\u00e7o no dispositivo ou nenhum drive externo conectado
-device.od.space=Espa\u00e7o dispon\u00edvel
-ConfigView.section.style.forceSIValues=Os valores da for\u00e7a a ser mostrado como IEC valoriza independentemente da unidade de exibi\u00e7\u00e3o para fins de legados (por exemplo, 1MB = 1MiB = 1048576B)
-ConfigView.label.enableSystrayToolTip=Exibir estatus de download na barra
-devices.activation=Ativando Dispositivo
-button.nothanks=N\u00e3o, obrigado
-devices.od.turnon.text1=N\u00f3s percebemos que voc\u00ea conectou-se a um %1.
-devices.od.turnon.text2=Voc\u00ea gostaria que %1 continuasse a baixar os arquivos enquanto o computador estiver offline?
-devices.od.turnon.text3=Por favor, conecte o Disco R\u00edgido no %1 para usar esse recurso.
-devices.od.turnon.learn=Aprender mais >
-devices.router=roteador
-webui.pairingenable=Permitir o emparelhamento para este plugin (op\u00e7\u00f5es de teste ser\u00e1 ativado depois que os detalhes de emparelhamento atuais s\u00e3o sucesso publicado)
-webui.group.access=Controle de Acesso
-ConfigView.section.Pairing=Emparelhamento
-pairing.accesscode=C\u00f3digo de Acesso
-pairing.ac.getnew=Alocar um novo c\u00f3digo de acesso
-pairing.ac.getnew.create=Criar
-pairing.ipv4=Endere\u00e7o IPv4 p\u00fablico
-pairing.ipv6=Endere\u00e7o IPv6 p\u00fablico
-pairing.local.ipv4=Endere\u00e7o IPv4 local
-pairing.local.ipv6=Endere\u00e7o IPv6 local
-pairing.host=Endere\u00e7o de host (nome DNS)
-pairing.group.explicit=Atributos expl\u00edcitos
-pairing.explicit.enable=Habilitado
-pairing.explicit.info=Atributos IP Normalmente expl\u00edcitas n\u00e3o precisa ser especificado como estes podem ser derivadas automaticamente.\nO atributo 'host' pode ser usado, por exemplo, se voc\u00ea tiver uma conta DynDNS e software cliente apropriado para manter seu IP din\u00e2mico registrado corretamente.
-pairing.op.fail=Falha na opera\u00e7\u00e3o de emparelhamento
-pairing.alloc.fail=Falha ao alocar um novo c\u00f3digo de acesso\n%1
-pairing.enable=Ativar o emparelhamento do Vuze e aplica\u00e7\u00f5es/interfaces remotas
-pairing.status.registered=Atualizado com sucesso (%1)
-pairing.status.pending=Atualiza\u00e7\u00e3o ir\u00e1 ser realizada em %1
-pairing.status.initialising=Inicializando
-pairing.status.disabled=Desabilitado
-pairing.view.registered=Clique para exibir os detalhes do registro atual
-webui.pairing.info.n=O emparelhamento est\u00e1 desativado, ver a conex\u00e3o-> op\u00e7\u00f5es de emparelhamento para obter informa\u00e7\u00f5es sobre este recurso
-webui.pairing.info.y=O emparelhamento \u00e9 ativado, ver a conex\u00e3o-> op\u00e7\u00f5es de emparelhamento para mais detalhes.
-webui.enable=Habilitar
-ConfigView.section.rss=RSS Local etc.
-subscriptions.rss.enable=Criar Feeds RSS de assinaturas
-device.tivo.enable=Habilitar suporte TiVo
-Button.removeAll=Remover Todos
-label.rename=Renomear %1
-pairing.server.warning.title=Mensagem do Servidor de emparelhamento
-wizard.webseedseditor.edit.title=Editor de Seeds  HTTP
-wizard.webseedseditor.edit.newseed=Novo Seed
-MyTorrentsView.menu.editWebSeeds=Editar Seeds HTTP
-ClientStats.title.full=Estatus do Cliente
-ClientStats.column.count=Contador
-network.ipv6.enable.support=Ativar o suporte IPv6 (Java7 exigido no Windows)
-ConfigView.section.plugins.magnetplugin=Gerenciador de Magnet URI
-MagnetPlugin.use.lookup.service=Use o servi\u00e7o de pesquisa Vuze secund\u00e1rio se pesquisa magnet se via DHT falhar
-MagnetPlugin.report.secondarylookup=Tentando servi\u00e7o de pesquisa secund\u00e1ria
-MagnetPlugin.report.secondarylookup.ok=Pesquisa secund\u00e1ria bem-sucedida
-MagnetPlugin.report.secondarylookup.fail=Pesquisa secund\u00e1ria falhou: n\u00e3o encontrou fontes
-TrackerView.title.short=Fontes
-TrackerView.title.full=Fontes
-Trackers.column.type=Tipo
-Trackers.column.name=Detalhes
-Trackers.column.seeds.info=Seeds na multid\u00e3o
-Trackers.column.leechers.info=Leechers na multid\u00e3o
-Trackers.column.peers.info=Peers retornado pelo tracker
-Trackers.column.interval=Intervalo
-Trackers.column.interval.info=Re-consulta intervalo em segundos: intervalo (intervalo min)
-Trackers.column.updatein=Pr\u00f3ximo
-Trackers.column.updatein.info=Tempo para pr\u00f3xima atualiza\u00e7\u00e3o
-tps.status.available=Dispon\u00edvel
-tps.status.unavailable=Indispon\u00edvel
-tps.lan.details=%1 clientes locais descobertos
-tps.pex.details=Conectado \u00e0 %1 peers (pendente: pex=%2, outros=%3)
-tps.tracker.cache1=Peer cache: usado=%1
-dht.status.disabled=Desabilitado, distributed database n\u00e3o est\u00e1 dispon\u00edvel
-tps.type.incoming=Entrada
-tps.incoming.details=Atual: TCP=%1, UDP=%2; Total ever=%3
-ConfigView.label.autoadjust=Automaticamente ajustar essas configura\u00e7\u00f5es com base na velocidade de conex\u00e3o
-ConfigView.label.start=Iniciar
-ConfigView.label.stop=Desligar
-ConfigView.label.start.onlogin=Iniciar o Vuze no login
-ConfigView.label.stop.seedcomp=Quando completar o seending
-ConfigView.label.stop.downcomp=Quando o download est\u00e1 completo
-ConfigView.label.stop.Nothing=N\u00e3o fazer nada
-ConfigView.label.stop.QuitVuze=Desligar Vuze
-ConfigView.label.stop.Sleep=Computador em espera
-ConfigView.label.stop.Hibernate=Hibernar Computador
-ConfigView.label.stop.Shutdown=Desligar o computador
-core.shutdown.alert=Ac\u00e7\u00e3o '%1' desencadeada como %2
-core.shutdown.dl=downloads completados
-core.shutdown.se=seeding completados
-pairing.last.error=\u00daltimo erro
-MainWindow.menu.pairing=Emparelhamento remoto
-ConfigView.label.pauseresume=Auto-pausar/resumir
-update.now.title=Atualiza\u00e7\u00e3o Requirida
-update.now.desc=Vuze precisa para aplicar as atualiza\u00e7\u00f5es para concluir a migra\u00e7\u00e3o.\n\nDepois de fechar esta caixa de di\u00e1logo pode ser solicitado pelo Windows para completar o processo de atualiza\u00e7\u00e3o.\n\nUm rein\u00edcio do Vuze n\u00e3o ser\u00e1 necess\u00e1rio.
-ConfigView.label.jvm=Op\u00e7\u00f5es do Java
-platform.jvmopt.sunonly=Somente Sun JVMs s\u00e3o suportadas (vers\u00e3o atual=%1)
-platform.jvmopt.configerror=N\u00e3o \u00e9 poss\u00edvel gerenciar as op\u00e7\u00f5es de JVM devido a um erro de configura\u00e7\u00e3o
-platform.jvmopt.nolinkfile=N\u00e3o \u00e9 poss\u00edvel gerenciar as op\u00e7\u00f5es de JVM como a migra\u00e7\u00e3o n\u00e3o \u00e9 completa
-platform.jvmopt.nolink=N\u00e3o pode gerenciar os op\u00e7\u00f5es de de JVM como proibida por de configura\u00e7\u00e3o existente
-platform.jvmopt.accesserror=Falha ao acessar op\u00e7\u00f5es do JVM no arquivo: %1
-pairing.status.noservices=Nenhum servi\u00e7o remoto habilitado
-webui.pairingtest=\tClique para testar o emparelhamento
-webui.connectiontest=\tClique para testar a conex\u00e3o
-jvm.info=Um rein\u00edcio do Vuze \u00e9 necess\u00e1rio se op\u00e7\u00f5es s\u00e3o alterados. AVISO *** - alterar as op\u00e7\u00f5es da JVM incorretamente pode causar Vuze a falhar para iniciar ou executar mal ***\n
-jvm.show.file=As op\u00e7\u00f5es locais do arquivo JVM \u00e9 '%1' - Somente edite diretamente para prop\u00f3sitos de recupera\u00e7\u00e3o
-jvm.reset=Restaurar op\u00e7\u00f5es JVM para o padr\u00e3o de instala\u00e7\u00e3o
-jvm.error=Houve um erro ao acessar as op\u00e7\u00f5es de JVM: %1
-jvm.max.mem=Tamanho da mem\u00f3ria Heap M\u00e1ximo [branco=padr\u00e3o,min=%1]
-jvm.min.mem=Tamanho da mem\u00f3ria Heap M\u00ednimo [branco=padr\u00e3o,min=%1]
-ConfigView.section.invalid.value.title=Valor Inv\u00e1lido
-ConfigView.section.invalid.value=Valor inv\u00e1lido '%1' digitado para '%2': %3
-Button.dismiss=Rejeito
-webui.pairing.autoauth=Habilitar prote\u00e7\u00e3o de senha padr\u00e3o: username = vuze, password = code> acesso <pairing
-ConfigView.label.stop.autoreset=Autom\u00e1ticamente restaurar a\u00e7\u00f5es para '%1' uma vez engatilhadas
-remote.pairing.title=Emparelhamento remoto
-remote.pairing.subtitle=Vuze remoto lhe d\u00e1 o poder de controlar Vuze a partir de qualquer computador, navegador m\u00f3vel ou dispositivo Android.
-remote.pairing.instruction=Simplesmente digite o c\u00f3digo abaixo nos espa\u00e7os providos por qualquer aplicativo remoto.
-remote.pairing.tip.title=Dica: Duas maneiras f\u00e1ceis de usar Vuze Remoto:
-remote.pairing.accesscode=C\u00f3digo de acesso:
-remote.pairing.test.running=Testando conectividade remota ...
-remote.pairing.test.success=Vuze \u00e9 acess\u00edvel remotamente.
-remote.pairing.test.unavailable=Oops, n\u00e3o foi poss\u00edvel determinar sua conex\u00e3o remota. <A HREF="retry">Try again</A>
-remote.pairing.test.fail=Vuze n\u00e3o est\u00e1 acess\u00edvel fora de sua rede local.  <A HREF="/pairing_error_faq.start">Learn more</A>
-update.fail.app.changed.title=Falha na Atualiza\u00e7\u00e3o
-update.fail.app.changed=Vuze precisa ser atualizado, mas o processo n\u00e3o pode ser executado automaticamente como o nome do aplicativo foi alterado para '%1'.\n\nPor favor, v\u00e1 para http://www.vuze.com/ e baixar o instalador mais recente.
-webui.port.override=Porta auxiliar: necess\u00e1rio apenas se difere da porta p\u00fablica interna devido a configura\u00e7\u00e3o NAT
-MainWindow.status.warning.tooltip=Clique aqui para mais detalhes
-search.dialog.text=Digite o texto para procurar novos torrents:
-core.not.available=Vuze ainda est\u00e1 iniciando, por favor tente novamente quando estiver completadostill initialising, please try again when it has completed
-dlg.auth.title=Ativa\u00e7\u00e3o
-dlg.auth.enter.subtitle.try.1=Quase L\u00e1.
-dlg.auth.enter.line.try.1=Digite seu c\u00f3digo de ativa\u00e7\u00e0o abaixo para completar sua atualiza\u00e7\u00e3o para o Vuze Plus
-dlg.auth.enter.line.try.2=Desculpe, n\u00f3s n\u00e3o podemos validar seu c\u00f3digo de ativa\u00e7\u00e3o. Por favor cheque o n\u00famero e tente digitar novamente.
-dlg.auth.enter.prompt=Vuze Plus c\u00f3digo de ativa\u00e7\u00e3o:
-Button.validate=Validar
-Button.getstarted=Come\u00e7ar
-Button.goLibrary=Ir para {library.name}
-dlg.auth.success.subtitle=Parab\u00e9ns!
-dlg.auth.success.line1=Obrigado por fazer o upgrade para Vuze Plus.
-dlg.auth.success.line2=Voc\u00ea agora \u00e9 capaz de gravar DVDs ilimitadas jog\u00e1veis, digitalizar seus arquivos em busca de v\u00edrus e transmitir v\u00eddeos que voc\u00ea est\u00e1 baixando - todos, sem an\u00fancios!
-dlg.auth.trial.success.line1=Vuze est\u00e1 pronto para criar DVDs.
-dlg.auth.trial.success.subtitle=Gravador de DVD est\u00e1 Pronto
-dlg.auth.trial.success.info=Arraste os arquivos de v\u00eddeo a partir de sua biblioteca em "Criar novo DVD." Se voc\u00ea j\u00e1 tinha adicionado um v\u00eddeo antes de instalar os componentes, por favor, adicione-o novamente.
-dlg.auth.revoked=C\u00f3digo de Ativa\u00e7\u00e3o Revogado
-dlg.auth.revoked.line1=Seu c\u00f3digo de ativa\u00e7\u00e3o do Vuze Plus foi revogado. Por favor clique abaixo para obter mais informa\u00e7\u00f5es.
-dlg.auth.revoked.link=<A HREF="info">informa\u00e7\u00e3o sob c\u00f3digos de ativa\u00e7\u00e3o Revogado</A>
-dlg.auth.denied=C\u00f3digo de Ativa\u00e7\u00e3o Negado
-dlg.auth.denied.line1=Seu C\u00f3digo de Ativa\u00e7\u00e3o do Vuze Plus foi negado. Por favor clique abaixo para obter mais informa\u00e7\u00f5es
-dlg.auth.cancelled=C\u00f3digo de Ativa\u00e7\u00e3o Cancelado
-dlg.auth.cancelled.line1=Sua Ativa\u00e7\u00e3o do Vuze Plus foi cancelado.
-dlg.auth.cancelled.line2=Se voc\u00ea sentir que isto \u00e9 um erro, por favor, contacte o suporte indicado em seu email recebido
-dlg.auth.enter.subtitle.try.2=Falha na Valida\u00e7\u00e3o
-dlg.auth.enter.link.try.2=<A HREF="link">Clique Aqui</A>se voc\u00ea n\u00e3o tiver comprado sua c\u00f3pia do Vuze Plus ainda.
-dlg.auth.enter.link.try.1=Voc\u00ea n\u00e3o tem c\u00f3digo de ativa\u00e7\u00e3o? <A HREF="atualizar">Atualizar agora</A>.
-dlg.auth.enter.expiry=O c\u00f3digo de ativa\u00e7\u00e3o expira em %1.
-dlg.auth.enter.revoked=C\u00f3digo de ativa\u00e7\u00e3o atual foi revogado.
-dlg.auth.enter.cancelled=C\u00f3digo de ativa\u00e7\u00e3o atual foi cancelado.
-dlg.auth.enter.denied=C\u00f3digo de ativa\u00e7\u00e3o atual foi negado.
-dlg.auth.validating.subtitle=Validando
-dlg.try.trial.title=Testar Grava\u00e7\u00e3o de DVD
-dlg.try.trial.text=Vuze precisa instalar o plugin necess\u00e1rio para gravar DVDs jog\u00e1veis \u200b\u200bde seus v\u00eddeos. Clique em Ativar para continuar.
-dlg.auth.tos=Eu li e aceito as <A HREF="tos">Condi\u00e7\u00f5es do Servi\u00e7o.</A>
-dlg.auth.install.subtitle.plus=Instalando Vuze Plus...
-dlg.auth.install.subtitle.trial=Instalando Gravador de DVD
-dlg.auth.install.progress=Instalando %1 componentes...
-dlg.auth.install.pct=%1% conclu\u00eddo
-mdi.entry.dvdburn=Gravar DVD
-mdi.entry.dvdburn.new=Cria Novo DVD
-menu.register=Ativa\u00e7\u00e3o do Vuze Plus
-dlg.auth.trial.title=Testar Gravador de DVD
-dlg.player.install.subtitle=Instala\u00e7\u00e3o
-dlg.player.install.description=Instalando componente adicional para reprodu\u00e7\u00e3o...
-devices.xcode.remove.vetoed=Transcodifica\u00e7\u00e3o de '%1' em progresso, o download n\u00e3o pode ser removido at\u00e9 a transcodifica\u00e7\u00e3o ser completada ou cancelada na p\u00e1gina de ""Dispositivos
-Button.agree=Eu concordo
-dlg.auth.install.failed.title=Falha na Ativa\u00e7\u00e3o
-dlg.auth.install.failed.text=C\u00f3digo de ativa\u00e7\u00e3o '%1' falhou em virtude de um erro no servidor.\n\nPor Favor tente  novamente a ativa\u00e7\u00e3o (erro reportado foi '%2')
-device.status.online=O dispositivo est\u00e1 on-line
-device.itunes.status.running=O iTunes est\u00e1 sendo executado
-device.itunes.status.notrunning=O iTunes n\u00e3o est\u00e1 sendo executado
-device.itunes.status.notinstalled=O iTunes n\u00e3o est\u00e1 instalado
-OpenTorrentWindow.mb.notTorrent.retry=Pesquisa Magnet
-ConfigView.section.ipfilter.clear.on.reload=Limpar flitros quando recarregar. Duranteo o processo recarga, os IPs n\u00e3o ser\u00e3o bloqueados. Se desmarcado, recente desbloqueios n\u00e3o ter\u00e3o efeito at\u00e9 reiniciar.
-view.waiting.core=Visualizar estar\u00e3o dispon\u00edveis uma vez N\u00facleo Vuze \u00e9 carregado ..
-devices.profile.direct=Direto
-cat.autoxcode=Dispositivo Autom\u00e1tico
-ConfigView.section.tables=Tabelas
-ConfigView.section.style.useTree=Exibir Arquivos em {library.name} exibi\u00e7\u00f5es (Requires Restart)
-ConfigView.section.mode.resetdefaults=Redefinir configura\u00e7\u00e3o para valores padr\u00e3o (reiniciar recomendado)
-resetconfig.warn.title=Confirme A\u00e7\u00e3o
-resetconfig.warn=Isto ir\u00e1 resultar em que todas as modifica\u00e7\u00f5es feitas na configura\u00e7\u00e3o Vuze sendo perdida.\nProsseguir com a redefini\u00e7\u00e3o de configura\u00e7\u00e3o?
-ConfigView.label.xfer.bias_up=Aumentar velocidades de download pela polariza\u00e7\u00e3o de upload capacidade de downloads incompletos
-ConfigView.label.xfer.bias_slack=KB/s m\u00ednimo reservado para downloads completos
-ConfigView.label.xfer.bias_no_limit=Tentar aplicar comportamento quando n\u00e3o houver limite de upload global eficaz
-SpeedView.stats.upload=Dados de Upload Enfilerados:
-SpeedView.stats.con=Detalhes da conex\u00e3o:
-SpeedView.stats.con_details=total=%1, unchoked=%2, enfilerado=%3, bloqueado=%4
-SpeedView.stats.upbias=Vi\u00e9s do Upload:
-dlg.install.mlab.subtitle=Instalando
-dlg.install.mlab.description=Por favor, aguarde enquanto o componente do teste de velocdiade \u00e9 instalado
-dial.up=Discar
-auto.mode=Autom\u00e1tico (recomendado)
-configureWizard.transfer2.hint=Configurando seu limite de upload alto demais ou baixo demais ir\u00e1 afetar a performace do download!
-configureWizard.transfer2.message=Bittorretn \u00e9 baseado em um protocolo tit-for-tat - em geral quanto mais r\u00e1pido \u00e9 o upload, mais veloz \u00e9 seu download - ent\u00e3o para baixar r\u00e1pido, e rapidamente obter uma boa taxa de compartilhamento, voc\u00ea precisa de uma boa velocidade de upload.\n\nDe qualquer forma, se seu upload for r\u00e1pido demais para sua conex\u00e3o, voc\u00ea pode sobrecarregar ela, resultando numa lentid\u00e3o greal e impactar outros aplicati [...]
-configureWizard.transfer2.group=Modo
-configureWizard.transfer2.test.info=Selecione para executar um teste de velocidade abrangente
-configureWizard.transfer2.test=Executar teste
-configureWizard.transfer2.mselect=Selecione o limite de velocidade da sua conex\u00e3o de UPLOAD 
-configureWizard.transfer2.mselect.info=A entrada xxx/<valor> denota a velocidade da conex\u00e3o de upload de <valor> bits-por-segundo.\nPor exemplo, se voc\u00ea tem uma conex\u00e3o ADSL com 768 Kbps de downstream e 384 Kbps para upstream, selecione 'xxx/384 kbit/sec'.\nVoc\u00ea deve indicar o valor mais pr\u00f3ximo poss\u00edvel, se sua velocidade exata n\u00e3o for exibida.
-configureWizard.transfer2.rate.unchanged=Configura\u00e7\u00f5es atuais ser\u00e3o usadas
-configureWizard.transfer2.rate.changed=Limite da Conex\u00e3o=%1\nAplicada o limite ser\u00e1 de %2 (m\u00e1x. de torrents ativos=%3, m\u00e1x. baixando=%4)
-speedtest.wizard.select.title=Selecione o tipo de teste de velocidade
-speedtest.wizard.select.group=Tipo de teste
-speedtest.wizard.select.general=O teste de velocidade geral (recomendado)
-speedtest.wizard.select.bt=Teste de velocidade espec\u00edfico para Bittorrent
-FileItem.storage.reorder=Reordenar
-ConfigView.label.piecereorder=Acrescentar dados a arquivos como baixados e reordenar pe\u00e7as como os avan\u00e7os download.
-ConfigView.label.piecereorderminmb=Apenas reordenar arquivos maiores que esse (em MB)
-configureWizard.transfer2.current=<Configura\u00e7\u00e3o Atual>
-ConfigView.section.style.extendedErase=Desenhe linhas de grade e preencher \u00e1reas em branco
-iconBar.stream=Executar Agora
-FilesView.menu.setpriority.numeric=Num\u00e9rico...
-FilesView.dialog.priority.title=Digite prioridade num\u00e9rica
-FilesView.dialog.priority.text=0=Normal, 1=Alta, 2=Alt\u00edssima...
-beta.wizard.intro.title=Sele\u00e7\u00e3o Inscri\u00e7\u00e3o
-beta.wizard.link=Clique aqui para acessar a p\u00e1gina da Web vers\u00e3o beta
-beta.wizard.off=Estou feliz com vers\u00f5es de lan\u00e7amento, n\u00e3o, obrigado!
-beta.wizard.on=Atualizar-me com as mais recentes vers\u00f5es beta est\u00e1veis \u200b\u200bpor favor.
-beta.wizard.version=Voc\u00ea est\u00e1 usando a seguinte vers\u00e3o %1
-beta.wizard.disable.title=Necess\u00e1rio reinstalar
-beta.wizard.disable.text=Obrigado por testar as vers\u00f5es beta!\n\nFa\u00e7a o download e instale a vers\u00e3o mais recente a deixar o programa beta
-beta.wizard.forum=Use os f\u00f3runs do Vuze a dar feedback e relat\u00f3rio de erros
-dlg.install.vuzexcode.subtitle=Instalando o componente de An\u00e1lise de M\u00eddia
-dlg.install.vuzexcode.description=Por favor, aguarde enquanto o componente Analisador de M\u00eddia \u00e9 instalado
-TableColumn.header.filecount=Arquivos
-TableColumn.header.torrentspeed=Velocidade
-FileProgress.deleted=Apagado
-priority.high=Prioridade alta
-priority.normal=Prioridade normal
-label.wrap.text=Quebrar texto
-ScrapeInfoView.title=Tracker Prim\u00e1rio
-Column.seedspeers.started=%1 de %2
-#connected to more seeds/peers than tracker reports
-library.all.header.p=%1 items: %2 ativo
-library.incomplete.header.p=%1 items baixando, %2 aguardando para baixar
-library.unopened.header.p=%1 itens
-library.all.header=%1 item: %2 ativo
-library.incomplete.header=%1 item baixando, %2 aguardando para baixar
-ConfigView.section.style.status.show_rategraphs=Mostrar gr\u00e1ficos hist\u00f3ria taxa embaixo do texto download/upload
-device.error.mountrequired="%1" Necess\u00e1rio a montagem no seu dispositivo
-v3.deviceview.infobar.line2.android=Ativar USB montagem no telefone para transferir adequadamente os v\u00eddeos.
-MyTorrents.column.ColumnProgressETA.compon=Completado em %1
-Sidebar.beta.title=Programa Beta
-MainWindow.menu.beta.on=Junte-se Programa Beta ...
-MainWindow.menu.beta.off=Deixe Programa Beta ...
-Button.sendNow=Enviar Agora
-Button.sendManual=Envio Manual (criar .zip)
-deletecontent.also.deletetorrent=Apagar .torrent  tamb\u00e9m
-ConfigView.section.file.deletion.section=Exclus\u00e3o de arquivo
-ConfigView.section.file.delete.torrent=Por padr\u00e3o, apagar .torrent quando apagar conte\u00fado
-ConfigView.section.file.delete.confirm=Confirmar a exclus\u00e3o de conte\u00fado via Barra de Ferramentas e tecla delete
-MainWindow.menu.view.beta=Programa Beta
-ConfigView.section.server.enableudpprobe=Habilitar an\u00e1lise de tracker UDP para trackers HTTP
-memmon.low.warning=A mem\u00f3ria \u00e9 fraca, voc\u00ea tem %1 remanescente de %2.\nO desempenho ir\u00e1 se degradar e, finalmente, Vuze vai parar de trabalhar\nVeja <a href="http://wiki.vuze.com/w/Java_VM_memory_usage">the Wiki</a> para obter detalhes sobre como aumentar a mem\u00f3ria dispon\u00edvel.
-jvm.max.mem.current=Heap m\u00e1ximo atual \u00e9 %1
-jvm.max.direct.mem=Tamanho da mem\u00f3eira direta M\u00e1xima [branco=padr\u00e3o,min=%1]
-jvm.max.direct.mem.info=Nota: esta op\u00e7\u00e3o de mem\u00f3ria "Direta", \u00e9 o mais comum para a necessidade de atualizar a  mem\u00f3ria "Heap" acima.
-jvm.options.summary=S\u00famario das atuais op\u00e7\u00f5es explicitas:
-memmon.heap.auto.increase.warning=Mem\u00f3ria Heap foi aumentado para %1. Isso ter\u00e1 efeito quando Vuze \u00e9 reiniciado.
-device.showGeneric=Mostrar dispositivos gen\u00e9ricos
-mdi.entry.games=Jogos
-Peers.column.Protocol=Protocolo
-devices.copying=Copiando para dispositivo
-devices.cancel_xcode=Cancelar Convers\u00e3o
-sidebar.header.transfers=Arquivos
-sidebar.header.discovery=Descobrir Cont\u00e9udo
-sidebar.header.devices=Reprodu\u00e7\u00e3o dispositivo
-sidebar.header.subscriptions=Assinaturas
-mdi.entry.about.devices=Em progresso
-mdi.entry.about.plugins=Sobre Plugins
-mdi.entry.about.dvdburn=Iniciar
-ConfigView.section.file.tb.delete=Ao excluir via tecla Delete ou barra de ferramentas:
-ConfigView.tb.delete.ask=Perguntar
-ConfigView.tb.delete.content=Apagar sem perguntar
-ConfigView.tb.delete.torrent=Somente remover da Biblioteca
-search.export.all=Exportar Todos os modelos de pesquisa ...
-subscriptions.search.enable=Permitir a pesquisa de resultados da assinatura (\u00e9 necess\u00e1rio reiniciar)
-devices.cancel_xcode_del=Cancelar Convers\u00e3o/Remover
-subscriptions.add.tooltip=Adicionar Assinatura
-subscriptions.overview=Resumo assinaturas
-configureWizard.nat.title=Porta do NAT / Servidor 
-configureWizard.nat.message=Para obter o melhor desempenho com Vuze, \u00e9 altamente recomendado ter total acesso \u00e0 internet. Est\u00e1 ferramenta deixa voc\u00ea testar e/ou mudar as portas usadas para aceitar conex\u00f5es de entrada.\n\n NOTA: A porta TCP 6880 \u00e9 usada internamente, ent\u00e3o n\u00e3o pode ser utilizada.
-configureWizard.nat.server.udp_listen_port=Escutar porta de entrada UDP
-v3.menu.device.defaultprofile.never=Nunca Transcode
-subscriptions.info.avail=Voc\u00ea n\u00e3o adicionou nenhum inscri\u00e7\u00f5es ainda. %1 est\u00e3o dispon\u00edveis para sua biblioteca.
-subscriptions.dl_subs.enable=Baixe assinaturas de outros clientes, quando necess\u00e1rio
-# Will be used for {library.name} in classic view
-library.name._classic=Meus Torrents
-# Will be used for {library.name} in VuzeUI view
-library.name._vuze=Biblioteca
-ConfigView.section.style.units=Unidades Exibidas
-ConfigView.section.style.CatInSidebar=Exibir Categorias na Barra Lateral
-library.category.header=Categoria '%1'
-device.import.title=Importar Dispositivo?
-device.import.desc=Voc\u00ea tem certeza que deseja importar dispositivo '%1'?
-device.import.dup.title=Dispositivo Duplicado
-device.import.dup.desc=Dispositivo '%1' j\u00e1 est\u00e1 presente.
-stream.analysing.media=Analisando M\u00eddia
-device.export.select.template.file=Exportar Dispositivo
-dlg.stream.plus.subtext=Cansado de esperar seus downloads para completar? Assista mais cedo com Executar Agora, um recurso Vuze Plus que lhe permite assistir a um v\u00eddeo ao mesmo tempo que continua a baixar.
-dlg.stream.plus.text=Atualizar para o Vuze Plus e reproduza seus v\u00eddeos que est\u00e3o baixando.
-dlg.stream.plus.renew.text=Renove sua assinatura Vuze Plus para continuar a reproduzir os seus v\u00eddeos que baixou.
-dlg.stream.plus.renew.title=Vuze Plus Renova\u00e7\u00e3o
-dlg.stream.plus.renew.subtitle=Renova\u00e7\u00e3o do Vuze Plus
-Button.renew=Renovar
-stream.analysing.media.preview=Analisando M\u00eddia (Modo de Visualiza\u00e7\u00e3o)
-devices.restrict_access=Acesso Restrito...
-devices.restrict_access.prompt=Restringir o acesso ao '%1'
-devices.restrict_access.msg=V\u00edrgula separa IPs da lista para permitir [ou negar se tiver o prefixo -]
-TableColumn.TorrentStream.tooltip.disabled=Executar Agora n\u00e3o suporta arquivos desse tipo
-TableColumn.TorrentStream.tooltip.expand=Expandir linha para ver Executar Agora para arquivos individuais
-table.columns.reset=Redefinir Colunas
-plus.notificaiton.ExpiringEntry.s=Sua assinatura Vuze Plus ir\u00e1 expirar em %1 dia: <A %2>Renove Agora</A>
-plus.notificaiton.ExpiringEntry.p=Sua assinatura Vuze Plus ir\u00e1 expirar em %1 dias: <A %2>Renove Agora</A>
-plus.notificaiton.ExpiredEntry.s=Sua assinatura do Vuze Plus expirou: <A %2>Renove Agora</A>
-plus.notificaiton.OfflineExpiredEntry=Voc\u00ea ficou desconectado por muitos dias. Vuze Plus foi desativado.
-rss.internal.test.url=Clique para ver a p\u00e1gina inicial local
-cat.rss.gen=Criar feed local RSS
-dht.backup.only=DHT como backup somente
-TableColumn.header.ipfilter=Filtro de IP habilitado
-MyTorrentsView.menu.ipf_enable=Ativar filtro de IP
-devices.sidebar.mainheader.tooltip=%1 deispositivos est\u00e3o ocultos como generico ou sem tags.\nUse clique direito do mouse  para revelar as op\u00e7\u00f5es
-device.mediaserver.remove_all=Remover Todos Servidores de M\u00eddia
-device.mediaserver.remove_all.title=Confirmar Remo\u00e7\u00e3o
-device.mediaserver.remove_all.desc=Voc\u00ea tem certeza que deseja remover todas os servidores de m\u00eddias?
-device.renderer.remove_all=Remova todos os Renderers
-device.renderer.remove_all.desc=Voc\u00ea tem certeza que deseja remover todos os Renderers e seus transcodes?
-MyTorrentsView.menu.create_personal_share=Criar Compartilhamento Pessoal
-device.tag=Tag do Dispositivo
-device.onlyShowTagged=Exibir somente Dispositivos com Tags
-devices.sidebar.show.only.tagged=Exibir somente dispositivos com tags
-filter.header.matches1=(Resultados da busca: %1)
-filter.header.matches2=(Resultados da buscas: %1, %2 ativo)
-ipfilter.disabled=Filtros de IP desativado
-ipfilter.options=Op\u00e7\u00f5es de Filtro de IP ...
-TableColumn.header.eta_next=Pr\u00f3ximo ETA
-torrentdownload.error.dl_fail=Falha no download '%1' para '%2': %3
-MainWindow.menu.speed_limits=Limite de Velocidade
-MainWindow.menu.speed_limits.profile=Digite o nome do perfil
-MainWindow.menu.speed_limits.profiles=Perfis
-MainWindow.menu.speed_limits.load=Aplicar...
-MainWindow.menu.speed_limits.view=Visualizar...
-MainWindow.menu.speed_limits.delete=Apagar
-MainWindow.menu.speed_limits.view_current=Visualizar Atual...
-MainWindow.menu.speed_limits.save_current=Salvar atual como ...
-MainWindow.menu.speed_limits.reset=Limpar Limites de Atual
-MainWindow.menu.speed_limits.info.title=Detalhes do Limites de velocidade
-MainWindow.menu.speed_limits.info.prof=Defini\u00e7\u00f5es para o perfil '%1'
-MainWindow.menu.speed_limits.info.curr=Configura\u00e7\u00f5es atuais
-MainWindow.menu.speed_limits.schedule=Agendar...
-MainWindow.menu.speed_limits.schedule.title=Agendar Limites de velocidade
-MainWindow.menu.speed_limits.schedule.msg=As regras atuais que controlam a aplica\u00e7\u00e3o autom\u00e1tica da velocidade limite de perfis
-MainWindow.menu.speed_limits.schedule.err=Os seguintes erros foram relatados, por favor, re-editar para corrigir!
-torrent.decode.info.order.bad=Alerta no Torrent: Torrent '%1' est\u00e1 com formatado incorretamente e pode gerar um hash incorreto.\n\nVeja <a href="http://wiki.vuze.com/w/Torrent_Info_Order_Bad">o Vuze Wiki</a> para mais detalhes e possiveis solu\u00e7\u00f5es.
-MainWindow.menu.advanced_tools=Avan\u00e7ado
-torrent.fix.corrupt=Corrigir Torrent Corrompido ...
-torrent.fix.corrupt.browse=Abrir Torrent
-torrent.fix.corrupt.result.title=Resultado da opera\u00e7\u00e3o
-torrent.fix.corrupt.result.nothing=O torrent parece ser v\u00e1lido!
-torrent.fix.corrupt.result.fixed=Hash de novo torrent de %1 calculado.\nPressione OK para salvar o torrent.
-MyTorrentsView.menu.sl_add_to_prof=Adicionar/Atualizar o Perfil
-MyTorrentsView.menu.sl_remove_from_prof=Remover do perfil
-MagnetPlugin.use.md.download=Habilitar o download de transfer\u00eancia baseada em metadados
-MagnetPlugin.use.md.download.delay=\tatraso [segs]
-MagnetPlugin.report.md.starts=Download de Metadata criado
-MagnetPlugin.report.md.progress=Progresso do download da Metadata: %1
-MagnetPlugin.report.md.done=Download metadados conclu\u00edda
-MagnetPlugin.use.md.download.name=Download de metadados para %1
-OpenTorrentWindow.addFiles.magnet=Adic. &Magnet
-MainWindow.menu.file.open.uri=URL, Magnet ou Hash...
-Button.open=Abrir
-plugin.init.load.failed=Erro ao carregar plugin '%1' de %2
-plugin.init.load.failed.classmissing=Desisntale o plugin via 'Ferramentas->Plugins->Assistente de Desisntala\u00e7\u00e3o' e ent\u00e3o reistanle elel
-v3.MainWindow.search.tooltip=Digite os termos da sua pesquisa, link magn\u00e9tico, URL hash ou torrent e tecle enter!
-device.playnow.group=Executar Agora
-device.playnow.min_buffer=Tamanho do buffer enquanto o rebuffering ocorre [sec]
-ConfigView.section.backuprestore=Backup & Restaurar
-ConfigView.section.br.overview=Configure seus backups requeridos para o Vuze. Isso ir\u00e1 permitir a recupera\u00e7\u00e3o de suas configura\u00e7\u00f5es no caso de um erro s\u00e9rio, tal como um erro no disco.\n\nIf poss\u00edvel backup para um disco separado do que voc\u00ea normalmente usa o Vuze!\n\nObserve que as opera\u00e7\u00f5es aqui somente se aplicam as configura\u00e7\u00f5es do Vuze, voc\u00ea precisa administrar o backup dos seus downloads voc\u00ea mesmo.\n\n 
-br.backup.manual.info=Configura\u00e7\u00e3o manual do backup
-br.backup.folder.title=Selecione pasta de backup
-br.backup.folder.info=Escolha a pasta que o backup ser\u00e1 gravado
-br.restore=Restaurar
-br.restore.info=Restaurar a configura\u00e7\u00e3o de um backup
-br.restore.warning.title=Aviso de Perda de configura\u00e7\u00e3o!
-br.restore.warning.info=Restaurando sua configura\u00e7\u00e3o ir\u00e1 substituir completamente o seu j\u00e1 existente.\nConsidere fazer o backup de ante-m\u00e3o!
-br.backup.progress=Backup/Restaurar Resultados
-br.restore.folder.title=Selecione Restaurar pasta
-br.restore.folder.info=Selecione a pasta que cont\u00e9m um backup anterior
-br.backup.auto.enable=Ativar backups autom\u00e1ticos
-br.backup.auto.dir.select=Por favor, escolha o diret\u00f3rio de backup padr\u00e3o
-br.backup.auto.everydays=Freq\u00fc\u00eancia de backup [dias]
-br.backup.auto.retain=N\u00famero de backups para manter
-br.backup.auto.now=Testar  auto-backup agora
-br.test=Teste
-TorrentOptionsView.param.upload.priority=Carregar prioridade [0=padr\u00e3o;1=priorizado]
-cat.upload.priority=Prioridade de Upload
-cat.options=Op\u00e7\u00f5es/Info dos Torrents Atuais...
-br.backup.last.time=\u00daltimo backup ocorreu em
-br.backup.last.error=\u00daltimo Erro no backup:
-br.backup.setup.info=Por favor, considere a cria\u00e7\u00e3o de backup de configura\u00e7\u00e3o autom\u00e1tica.\nVeja Ferramentas-> Op\u00e7\u00f5es-> Backup & Restaurar
-MainWindow.about.internet.contributors=Contribuidores
-FilePriority.invalid.title=Prioridade inv\u00e1lida
-FilePriority.invalid.text=Valor inv\u00e1lido digitao,  inteiro requerido: %1
-MyTorrentsView.menu.trackername.editprefs=Editar exibi\u00e7\u00e3o de Trackers preferidos...
-trackername.prefs.title=Digite exibi\u00e7\u00e3o preferido para Torrent com Multi-Rastreador
-trackername.prefs.message=V\u00edrgula lista separada de nomes de host rastreador\nPor exemplo: a.b.com; c.d.net
-device.wiki=Dicas na Wiki...
-MagnetPlugin.report.ddb_disabled=DDB est\u00e1 desativado
-ConfigView.section.style.enableHeaderHeight=Altura cabe\u00e7alho personalizado
-ConfigView.section.style.customDateFormat=Formato de data personalizado
-br.backup.notify=Notifique quando o backup estiver completo
-sidebar.LibraryCD.tooltip=Tem %1 completo torrent(s), %2 dos quais est\u00e1/est\u00e3o semeando
-sidebar.LibraryDL.tooltip=Tem %1 torrent incompleto(s), %2 dos quais est\u00e1/est\u00e3o baixando
-ConfigView.section.style.launch=Auxiliar de In\u00edcio
-ConfigView.label.lh.info=Por padr\u00e3o o lan\u00e7amento de um arquivo usa o aplicativo registrado para o tipo de arquivo.\nSubstituir esse comportamento, definindo aplica\u00e7\u00f5es expl\u00edcitas para extens\u00f5es de arquivo dadas [lista separada por v\u00edrgula].
-ConfigView.label.lh.ext=Extens\u00f5es
-ConfigView.label.lh.prog=Aplicativo
-pairing.config.icon.show=Exibir \u00edcone do Vuze Remote na barra de status
-pairing.ui.icon.show=Mostrar \u00cdcone
-pairing.ui.icon.tip=Status da Conex\u00e3o do Vuze Remoto
-ManagerItem.moving=Movendo
-wizard.newtorrent.byo=Construa seu pr\u00f3prio
-wizard.newtorrent.byo.info=Soltar uma sele\u00e7\u00e3o de arquivos e/ou diret\u00f3rios para a \u00e1rea abaixo para construir um torrent. D\u00ea um duplo clique ou F2 para editar nomes.
-wizard.newtorrent.byo.help=Construa seu pr\u00f3prio torrent de uma sele\u00e7\u00e3o de arquivos e diret\u00f3rios
-wizard.newtorrent.byo.editname.title=Editar Nome do Item
-wizard.newtorrent.byo.editname.text=Digite o nome do item que aparece no torrent
-wizard.newtorrent.byo.addcontainer.title=Adic. Container
-wizard.newtorrent.byo.addcontainer.text=Digite o nome do cont\u00eainer como aparece no torrent
-label.torrent.structure=Estrutura do Torrent
-label.original.file=Arquivo Original
-button.add.container=Adic. Container
-TableColumn.header.torrentrelpath=Caminho do Torrent
-TableColumn.header.torrentrelpath.info=Localiza\u00e7\u00e3o relativa do arquivo no torrent
-TableColumn.header.torrentfileindex=\u00cdndice de arquivo
-TableColumn.header.torrentfileindex.info=\u00cdndice do arquivo no torrent
-ConfigView.section.tracker.client.enabletcp=Habilitar tracker HTTP/HTTPS protocolo do cliente
-label.udp_probe=Examinar UDP
-MyTorrentsView.menu.eta.abs=Exibir TEC em tempo absoluto
-ConfigView.label.sleep=Dormir
-ConfigView.label.sleep.info=Impedir o computador de dormir/suspender enquanto...
-ConfigView.label.sleep.download=Baixando
-ConfigView.label.sleep.fpseed='Primeira Prioridade' seeding est\u00e1 ativo
-TableColumn.header.fileext=Tipo de Arquivo
-TableColumn.header.fileext.info=Tipo de arquivo/extens\u00e3o de arquivo prim\u00e1rio do download
-TableColumn.header.crc32.info=CRC-32 checksum para o arquivo (deve ser totalmente transferido; clique para calcular)
-FilesView.crc32.calculate=Calcule o CRC-32 Checksum (s)
-TableColumn.header.md5.info=Hash MD5 para o arquivo (deve ser totalmente transferido; clique para calcular)
-FilesView.md5.calculate=Calcular hash MD5(s)
-FilesView.click=Clicar...
-FilesView.click.info=Clique para calcular, use o bot\u00e3o direito do mouse no menu para v\u00e1rios c\u00e1lculos
-ConfigView.section.connection.port.rand.enable=Escutar portas rand\u00f4micamente ao iniciar
-ConfigView.section.connection.port.rand.range=Alcance das portas [min-max]
-ConfigView.section.connection.port.rand.together=Mesma porta para TCP e UDP
-ConfigView.label.start.inlrm=Iniciar no modo econ\u00f4mico (UI desativada, limitando a rede e o uso de mem\u00f3ria etc)
-wizard.multitracker.edit.text=Editar como Texto
-wizard.multitracker.edit.text.title=Entrar com Detalhes do Tracker
-wizard.multitracker.edit.text.msg=Digite um trackerr por linha. Separar diferentes grupos (camadas) com uma linha em branco.
-MainWindow.menu.quick_view=Exibi\u00e7\u00e3o R\u00e1pida
-quick.view.no.files=Nenhum Arquivo Aplic\u00e1vel
-ConfigView.label.quickviewexts=Extens\u00f5es de Arquivos para Exibi\u00e7\u00e3o-R\u00e1pida
-ConfigView.label.quickviewmaxkb=Tamanho m\u00e1ximo do arquivo [KB]
-MainWindow.menu.quick_view.msg=Conte\u00fado do arquivo '%1' dentro de Download '%2'
-quick.view.scheduled.title=Agendar Exibi\u00e7\u00e3o R\u00e1pida
-quick.view.scheduled.text=O arquivo selecionado foi priorizado e ser\u00e1 auto-aberto para visualiza\u00e7\u00e3o quando completo.
-label.dont.show.again=N\u00e3o mostrar esta mensagem novamente
-label.plugin.options=Op\u00e7\u00f5es de Plugins...
-TableColumn.header.torrent_created=Criado Torrent em
-TableColumn.header.torrent_created.info=Data em que o torrent foi criado, quando dispon\u00edvel
-pairing.ui.icon.tip.no.recent=Sem conex\u00f5es recentes
-label.access.denied=Acesso negado
-label.date.format=Formato da Data
-label.table.default=Tabela Padr\u00e3o
-device.config.xcode.disable_sleep=Impedir o computador de hibernar enquanto transcodifica
-label.aggregate.info=Informa\u00e7\u00e3o Agregada
-label.options.and.info=Op\u00e7\u00f5es/Info...
-ConfigView.section.tracker.client.exclude_lan=Excluir transfer\u00eancias em LAN das est\u00e1tisticas
-ConfigView.pluginlist.uninstallSelected=Desinstalar Selecionado
-devices.sidebar.onxcodecomplete=Quando Transcode Terminar
-core.shutdown.xcode=transcodifica\u00e7\u00e3o conclu\u00edda
-torrent.view.info=Exibir Info do Torrent...
-torrent.view.info.title=Informa\u00e7\u00e3o do Torrent
-network.check.ipbinding=Checar enderen\u00e7o/interfaces de IP ao iniciar
-ConfigView.section.proxy.testsocks=Testar SOCKS
-ConfigView.section.proxy.testsocks.title=Testando conex\u00e3o SOCKS
-MyTorrentsView.menu.torrent.dl=Link de Download do Torrent
-custom.settings.import.title=Importe defini\u00e7\u00f5es de configura\u00e7\u00e3o?
-custom.settings.import=Voc\u00ea est\u00e1 certo que deseja  importar configura\u00e7\u00f5es para '%1'?
-custom.settings.import.res.title=Importa\u00e7\u00e3o da configura\u00e7\u00e3o completa
-custom.settings.import.res=Importado %1 configura\u00e7\u00f5es.%2
-ConfigView.section.dns.info=Esta se\u00e7\u00e3o especifica servidores DNS alternativos e define em que podem ser utilizados.\n\nPor exemplo, o Google executa um servidor DNS no endere\u00e7o 8.8.8.8 (e 8.8.4.4 para backup)\n\nIsso pode ser \u00fatil quando o provedor de DNS existente n\u00e3o est\u00e1 resolvendo nomes corretamente.\n
-ConfigView.section.dns.alts=Servirdores DNS alternativos [separados por ';']
-ConfigView.section.dns.allow_socks=Usar quando a busca por servidor proxy SOCKS falhar
-ConfigView.section.proxy.dns.info=Veja a Conex\u00e3o-> configura\u00e7\u00e3o de DNS para especificar os servidores DNS adicionais para a resolu\u00e7\u00e3o de proxy.
-label.inactive=Inativo
-label.in=Em
-label.out=Sa\u00edda
-label.more=Mais
-label.fails=Falhas
-label.ago=atr\u00e1s
-label.con_prob=Problemas na Conex\u00e3o
-proxy.info.title=Info do Proxy
-ConfigView.section.proxy.show_icon=Mostrar \u00edcone SOCKS na \u00e1rea de status quando ativado
-proxy.socks.bad.incoming=Conex\u00f5es de entrada n\u00e3o-proxy detectado!
-wizard.newtorrent.showtorrent=Procure o arquivo torrent gerado
-ConfigView.section.proxy.show_icon.flag.incoming=Exibir n\u00e3o-locais, n\u00e3o-SOCKS conex\u00f5es de entrada como estado de erro
-label.connections=Conex\u00f5es
-label.routing=Roteamento
-label.route=Rota
-label.outgoing=Saindo
-network.admin.maybe.vpn.title=VPN Ativo?
-network.admin.maybe.vpn.msg=Parece que voc\u00ea pode ter uma rede privada virtual (VPN) ativo no\n\n\t%1\n\nIf este \u00e9 o caso, voc\u00ea pode aumentar a privacidade explicitamente vincula\u00e7\u00e3o a esse - Escolha Sim para faz\u00ea-lo.\n\nIf n\u00e3o, ou voc\u00ea n\u00e3o tem certeza, selecione NO.\n\nVeja <a href="http://wiki.vuze.com/w/Proxies_And_VPNs#VPN_Configuration">the wiki</a> para mais informa\u00e7\u00f5es.
-settings.updated.title=Configura\u00e7\u00f5es Atualizadas
-settings.updated.msg=Suas configura\u00e7\u00f5es do Vuze foram atualizadas.
-network.ipbinding.icon.show=Mostrar \u00edcone de status na barra de status quando as liga\u00e7\u00f5es ativas
-label.no.connections=Sem conex\u00f5es
-label.missing=Desaparecido
-network.admin.binding.state=Liga\u00e7\u00f5es: %1, for\u00e7adas=%2
-ConfigView.section.server.enablednsrecords=Permitir o uso de rastreador registros DNS usados \u200b\u200bpara melhorar DDOS acidentais
-network.ipv4.prefer.stack=Preferir IPv4 stack - usar seperadamente IPv4 e IPv6 stacks ao inv\u00e9s da implementa\u00e7\u00e3o dual-stack
-ConfigView.section.file.subfolder.dnd=Mover arquivos n\u00e3o selecionados para download para subpasta
-ConfigView.label.showuptime=Exibir Tempo de Upload
-label.uptime_coarse=Tempo de Up%1%2
-devices.copy.device.auto=Automaticamente copiar arquivos para dispositivo
-devices.xcode.autoCopy.device=Copiar automaticamente para o Dispositivo
-devices.info.copypending3=%1 FArquivo(s) Aguardando Para Serem Copiados - Hablitar Auto-C\u00f3pia Ou Selecioine C\u00f3pia Manual
-label.num_selected=%1 selecionado
-MainWindow.menu.transfers.pausetransfersfor=Pausar Por...
-dialog.pause.for.period.title=Digitar Per\u00edodo de Tempo
-dialog.pause.for.period.text=Pausar download e automaticamente resumi-los em [minutos]
-dialog.pause.for.period.text2=Auto-resumir ativo: %1 restante...
-security.cert.auto.install=Instalar automaticamente certificados SSL desconhecidos sem avisar
-Trackers.column.last_update=\u00daltima Atualiza\u00e7\u00e3o
-pairing.group.srp=Op\u00e7\u00f5es de emparelhamento seguro
-pairing.srp.info=Algumas aplica\u00e7\u00f5es remotas apoiar tanto maior conectividade e seguran\u00e7a, utilizando o protocolo senha remoto seguro "e, opcionalmente, as conex\u00f5es de proxy para aumentar a conectividade.\n\nConsulte a documenta\u00e7\u00e3o do aplicativo de controle remoto para ver se voc\u00ea pode se beneficiar com isso.
-pairing.srp.enable=Ativar emparelhamento seguro
-pairing.srp.setpw=Atualizar sua senha de  emparelhamento
-pairing.srp.setpw.doit=Mudar
-pairing.srp.pw.req=Senha necess\u00e1ria - nada vai funcionar sem isso!
-pairing.srp.registering=Registrando...
-security.crypto.pw.title=Digite a Senha
-label.more.info.here=Clique aqui para mais informa\u00e7\u00f5es
-label.num_queued=%1 na fila
-label.lang.upper.case=Use letras mai\u00fasculas (ajuda a alinhar a experi\u00eancia do usu\u00e1rio para aqueles que t\u00eam "capslock" sempre ativado)
-device.config.ms.maxlines=M\u00e1ximo de entradas a serem exibidas quando navegador no servidor de m\u00eddia
-openTorrentWindow.mb.alreadyExists.merge=Voc\u00ea deseja adicionar trackers adicionais de um novo download \u00e0 um j\u00e1 existente?
-ConfigView.section.connection.group.webseed=Seeds Web/HTTP
-ConfigView.section.connection.webseed.act.on.avail=Somente ativar seeds da Web/HTTP para baixar quando a disponibilidade for baixa
-stats.longterm.group=Longo-Termo
-stats.long.weekstart=Contagem da semana come\u00e7a em:
-stats.long.monthstart=Contagem do m\u00eas come\u00e7a em:
-MainWindow.menu.speed_limits.wiki=Ajuda Wiki...
-ConfigView.label.info.in.window.title=Exibir taxas atuais e etc. na barra de t\u00edtulos
-ConfigView.label.hap=Marcar download completo
-ConfigView.label.hap.tooltip=Ocultar um peda\u00e7o completo
-ConfigView.label.hapds=Desconectar dos seeds para disfar\u00e7ar, mas complete downloads
-Button.swarmit=Insira na Multid\u00e3o!
-Button.swarmit.tooltip=Buscar arquivos com mesmo tamanho usando Swarm Discoveries
-show.config.changes=Exibir Mudan\u00e7as das Configura\u00e7\u00f5es...
-config.changes.title=Mudan\u00e7as nas Configura\u00e7\u00f5es
-DHTOpsView.title.full=Gr\u00e1fico DDB
-DHTOpsView.notAvailable=Gr\u00e1fico  DDB n\u00e3o dispon\u00edvel
-DHTOpsView.idle=Inativo - aguardando por atividade...
-ConfigView.section.style.TagInSidebar=Exibir Tags na Barra lateral
-label.add.tag=Adicionar Tag...
-label.show.tag=Exibir Tag
-TagAddWindow.message=Digitar uma nova tag
-TagAddWindow.title=Adicionar Nova Tag
-TagRenameWindow.message=Digitar um novo nome para a Tag
-TagRenameWindow.title=Renomear Tag
-tag.type.ds=Estado do Download
-tag.type.ds.qford=Na Fila para Download
-tag.type.ds.qfors=Na Fila para Semear
-label.show.all=Exibir Tudo
-tag.type.ipset=Mudar IP
-label.complete=Completo
-label.incomplete=Incompleto
-ConfigView.label.dl.add.req.attention=Real\u00e7ar a se\u00e7\u00e3o de downloading quando um download for adicionado
-ColumnProgressETA.showETA=Exibir TEC
-ColumnProgressETA.showSpeed=Exibir Velocidade
-ConfigView.label.queue.retainforce=Transi\u00e7\u00e3o 'for\u00e7ar Inicio' download para 'for\u00e7ar semear' quando completo
-TableColumn.header.CountryCode=CP
-TableColumn.header.CountryCode.info=O c\u00f3digo do pa\u00eds (ISO 3166) onde o par est\u00e1 localizado
-TableColumn.header.Country=Pa\u00eds
-TableColumn.header.Country.info=O pa\u00eds onde o par est\u00e1 localizado
-TableColumn.header.CountryFlag=Bandeira
-TableColumn.header.CountryFlag.info=Bandeira do pa\u00eds do par
-TableColumn.header.CountryFlagSmall=Bandeira
-TableColumn.header.CountryFlagSmall.info=Pequena bandeira do pa\u00eds do par
-tag.type.man.featcon=Conte\u00fado em Destaque
-label.content=Conte\u00fado
-tag.share=Compartilhar suas Tags com a Comunidade
-cat.share=Compartilhar Categoriza\u00e7\u00e3o com a Comunidade
-tag.sharing.enable.title=Compartilhar com a Comunidade
-tag.sharing.enable.text=Voc\u00ea deseja compartilhar suas tags/categorias de forma an\u00f4nima com a comunidade?\n\nIsso ir\u00e1 ajudar os outros a organizar melhor seus downloads.\n\nClique direito domouse sobre tags/categorias na barra lateral para fazer configura\u00e7\u00f5es individuais se requerida.
-ConfigView.section.style.ShowTabsInTorrentView=Exibir sub-abas nas exibi\u00e7\u00f5es da Biblioteca (Requer Reiniciar)
-label.close.tab=Fechar Aba
-TorrentDetailsView.filter=Procurar por arquivos...
-PeersView.menu.showdownload=Exibir Download &Detalhes
-window.update.noupdates.beta.text=N\u00e3o h\u00e1 atualiza\u00e7\u00f5es dispon\u00edveis para voc\u00ea.\n\nVoc\u00ea est\u00e1 usando a \u00faltima vers\u00e3o beta disponibilizada (%1)\n\nVisite <a href="http://dev.vuze.com/">Beta Program site</a> para mais informa\u00e7\u00f5es sobre as vers\u00f5es est\u00e1veis e n\u00e3o estav\u00e9is do programa.
-tag.show.stats=Exibir Est\u00e1tisticas das Tags...
-TagStatsView.title.full=Atividade das Tag
-tag.stats.none.defined=Nenhuma tag com avalia\u00e7\u00e3o selecionado/definido!
-label.click.to.showhide=Clique para mostrar/esconder
-label.click.to.change=Clique para mudar
-iconBar.play.tooltip=Reproduzir conte\u00fado selecionado
-iconBar.startstop.tooltip=Iniciar ou Parar Itens selecionados
-label.click.to.restore=Clique para Restaurar
-label.dblclick.to.min=Clique duplo para Minimizar
-label.no.download.selected=Nenhum download selecionado
-ConfigView.section.style.showRankIcon=Exibir \u00cdcone de Ordem
-label.color=Cores
-TableColumn.header.tag.name=Nome da Tag
-TableColumn.header.tag.count=# Itens
-tags.view.heading=S\u00famario das Tags
-label.toggle.new.marker=Ver Novo Marcador
-label.no.tag=Sem Tag
-label.move.on.comp=Mover Quando Completo
-label.set=Alterar...
-label.browser=Navegador
-label.various=V\u00e1rios
-sidebar.show=Exibir barra lateral
-sidebar.top.level.gap=Espa\u00e7o entre as linhas de cabe\u00e7alhos ({ConfigView.section.security.restart.title})
-device.config.autohide.old.devices=Auto-ocultar dispositivos que n\u00e3o foram vistos recetemente [dias, 0: desabilitado]
-ColumnRenameWindow.title=Renomear Coluna
-ColumnRenameWindow.message=Digite um novo nome para a coluna, deixe em branco para restaurar
-Button.set=Alterar
-ConfigView.section.transfer.setmark=Alterar/Limpar marcas: o total das est\u00e1tisticaas de transfer\u00eancias ir\u00e3o ser exibidas deste ponto em diante
-SpeedView.stats.total.since=Total (desde %1)
-TableColumn.header.peakup=Up Alcan\u00e7ado
-TableColumn.header.peakup.info=Up M\u00e1x. Alcan\u00e7ado
-TableColumn.header.peakdown=Down Alcan\u00e7ado
-TableColumn.header.peakdown.info=Vel. M\u00e1x. Alcan\u00e7ado
-smooth.config=(v\u00e1 em config para configurar a dura\u00e7\u00e3o da janela)
-TableColumn.header.smoothup=Up Suavizado
-TableColumn.header.smoothup.info=Velocidade de Up Suavizado {smooth.config}
-TableColumn.header.smoothdown=Down Suavizado
-TableColumn.header.smoothdown.info=Velocidade de Download Suavizado {smooth.config}
-TableColumn.header.smootheta=TEC Suavizado
-TableColumn.header.smootheta.info=Velocidade TEC Suavizado {smooth.config}
-stats.general.smooth_secs=Tamanho m\u00e9dio da janela suavizada [secs]
-DownloadActivityView.legend.up_smooth=Envio (Suave)
-DownloadActivityView.legend.down_smooth=Baixando (Suave)
-menu.min.share.ratio=Taxa de Compartilhamento M\u00ednimo (%1)...
-min.sr.window.message=Digite o ratio m\u00ednimo de compartilhamento [0:desabilitado]
-min.sr.window.title=Taxa M\u00ednima de Compartilhamento
-sidebar.show.options=Exibir as Op\u00e7\u00f5es como uma barra lateral do qu\u00ea uma janela separada
-TorrentOptionsView.param.reset.stats=Resetar est\u00e1tisticas de transfer\u00eancia de torrent para zero
-ConfigView.label.moveifsamedrive=Mas somente fa\u00e7a isso quando a fonte e o destino s\u00e3o sistema de arquivos diferentes
-OpenTorrentWindow.pastearea=Digite a URL, magnet link, ou hash:
-OpenTorrentWindow.checkbox.showAdvanced=Uma vez que o torrent \u00e9 carregado, deixe-me definir op\u00e7\u00f5es avan\u00e7adas, como a sele\u00e7\u00e3o de arquivo e o local para salvar.
-OpenTorrentFile.column.download=Baixar?
-OpenTorrentOptions.title=Op\u00e7oes de Abertura de Torrent
-OpenTorrentOptions.header.torrentinfo=Informa\u00e7\u00f5es do Torrent
-OpenTorrentOptions.header.filesInfo.all=%1 Arquivos: %3
-OpenTorrentOptions.header.filesInfo.some=%1 de %2 Arquivos: %3
-OpenTorrentOptions.header.saveto=Salvar com Destino: %1
-OpenTorrentOptions.header.startoptions=Op\u00e7\u00f5es de Iniciar: %1
-OpenTorrentOptions.header.peeroptions=Tracker, Op\u00e7\u00f5es de Conex\u00e3o & Peer
-ConfigView.section.file.showopentorrentoptions=Quando abrindo um torrent, exiba di\u00e1logo de op\u00e7\u00f5es:
-OpenTorrentOptions.show.label=Quando abrindo um torrent, exiba esta janela:
-OpenTorrentOptions.show.always=todas as vezes
-OpenTorrentOptions.show.never=Nunca novamente
-OpenTorrentOptions.show.many=Somente quando houver mais de 1 arquivo
-Button.rename=Renomear
-Button.retarget=Realocar
-label.download.file=Arquivo Baixado
-menu.selectfilesinfolder=Selecionar todos os arquivos em %1
-label.current=Atual
-label.limit=Limite
-label.showhide.tag=Mostrar / Ocultar Tag(s)
-label.dismiss.all=Dispensar Todos
-ConfigView.label.show.win.on.add=Mostrar a janela principal quando um download \u00e9 adicionado por outro aplicativo
-label.current_ip=Endere\u00e7o de IP Atual:
-label.properties=Propriedades
-UpdateProperty.title=Propriedade da Atualiza\u00e7\u00e3o
-UpdateProperty.list.message=Digite novo valor para %1. Use ',' para separar m\u00faltiplas entradas; deixe em branco para limpar
-label.untagged=Sem Tags
-ConfigView.label.stop.RunScript=Executar Script
-ConfigView.label.stop.RunScriptAndClose=Executar Script + Desligar o Vuze
-label.script.to.run=Script \u00e0 executar
-TableColumn.header.tag_colors=Cores das Tags
-label.init.save.loc=Salvar Inicialmente no Local
-label.initial_tags=Tags Iniciais
-OpenTorrentFile.column.download.info=Baixar arquivo do interior do torrent\nUsar barra de espa\u00e7o para alternar para o modo de m\u00faltipla sele\u00e7\u00e3o
-OpenTorrentFile.column.size.info=Tamanho do Arquivo
-OpenTorrentWindow.mb.invaliddefsave.title=Local Inv\u00e1lido para Salvar
-OpenTorrentWindow.mb.invaliddefsave.text=O local para salvar '%1' \u00e9 inv\u00e1lido.\n\nQuando voc\u00ea fechar este dialogo, ir\u00e1 ser perguntado para mudar isso.\n\nO local padr\u00e3o para salvar pode ser configurado via Ferramentas->Op\u00e7\u00f5es->Arquivos.
-OpenTorrentWindow.set.savepath=Mudar o Nome da Pasta de N\u00edvel Superior
-FilesView.menu.setpriority.numeric.auto=N\u00famerico - Auto Decrescente
-Button.mark=Marcar
-Button.unmark=Desmarcar
-TableColumn.header.sessionup=Envios na Sess\u00e3o
-TableColumn.header.sessionup.info=Byts enviados nesta sess\u00e3o
-TableColumn.header.sessiondown=Baixados na Sess\u00e3o
-TableColumn.header.sessiondown.info=Bytes baixados nesta sess\u00e3o
-ConfigView.section.file.showopentorrentoptions.sep=Usar dial\u00f3go separado por torrent
-label.n.will.be.downloaded=%1 ir\u00e1 ser baixado
-label.edit.trackers=Editar Trackers
-wizard.multitracker.template.title=Editor de Modelos de Tracker
-label.replace=Substituir
-label.merge=Juntar
-apply.selected.template=Aplicar Modelo Selecionado
-dialog.add.peers.title=Adicionar Peer(s)
-dialog.add.peers.msg=Digite o endere\u00e7o de cada peer na forma de <host>:<port> - use v\u00edrgula para separar v\u00e1rias entradas
-OpenTorrentWindow.fileList.changeDestination.all=Mudar Destino de %1 Arquivos Para Mesma Pasta
-menu.max.share.ratio=Taxa de Compartilhamento Alvo (%1)...
-max.sr.window.message=Digite uma Taxa de Compartilhamento Alvo [0:desabilitado]
-max.sr.window.title=Taxa de Compartilhamento Alvo
-ConfigView.section.mode.beginner.text1=Tudo que voc\u00ea precusa para baixar torrents - grande para novos usu\u00e1rios aprenderem sobre o cliente e os torrents
-ConfigView.section.mode.intermediate.text1=Mais recursos para controle, optimiza\u00e7\u00e3o e visualizando downloads
-ConfigView.section.mode.advanced.text1=Acesso completo para todas as op\u00e7\u00f5es e recursos
-label.tracker.templates=Modelos de Tracker
-label.reapply=Reaplicar
-ConfigView.section.security.resetcerts=Restaurar armazenagem de certificados (ir\u00e1 reiniciar o Vuze)
-ConfigView.section.security.resetcerts.warning.title=Alerta de Perda de Dados
-ConfigView.section.security.resetcerts.warning.msg=Voc\u00ea est\u00e1 certo que deseja restaurar a armazenagem de certificados? Se voc\u00ea tiver criado um auto-assinado certificado ou manualmente importado qualquer certificado, esses ser\u00e3o perdidos!
-ConfigView.section.security.resetcerts.error.msg=Falha ao redefinir o armazenamento de certificados por uma raz\u00e3o desconhecida, consulte os f\u00f3runs de ajuda
-TableColumn.header.sr_prog=Progresso da Taxa de Compartilhamento
-TableColumn.header.sr_prog.info=Mostra a data em que a rela\u00e7\u00e3o de uma parte de Download atingido certos valores
-TableColumn.menu.sr_prog.interval=Configurar Intervalo do Progresso...
-sr_prog.window.title=Intervalo do Progresso
-sr_prog.window.message=Digite share intervalo rela\u00e7\u00e3o grava\u00e7\u00e3o andamento (por exemplo, 1.0 = cada c\u00f3pia completa)
-ConfigView.label.downloading.info=Automaticamente ajusta a posi\u00e7\u00e3o da fila de downloads para que trabalhe da melhor forma para que voc\u00ea tenha uma melhor m\u00e9dia geral de download baseado na ativade de sua rede
-ConfigView.label.downloading.autoReposition=Reposi\u00e7\u00e3o na fila de downloads para otimizar o download
-ConfigView.label.downloading.testTime=Per\u00edodo de avalia\u00e7\u00e3o da velocidade de download [seg]
-ConfigView.label.downloading.reTest=Reavaliar de downloads a cada [min; 0=nunca]
-TableColumn.header.DownloadingRank=Rank de Downloading
-show.tooltip.label=Exibir Dicas
-label.alertnum=Alertas: %1
-tray.options=Op\u00e7\u00f5es de bandeja
-label.more.dot=Mais...
-ConfigView.label.enableSystrayToolTipNextETA=Exibir pr\u00f3ximo download a completar
-menu.change.url=Mudar URL...
-change.url.msg.title=Mudar URL para '%1'
-change.url.msg.desc=Isso ir\u00e1 criar uma nova assinatura e renomear a que existe
-TableColumn.header.readrate=Taxa de Leitura
-TableColumn.header.readrate.info=Taxa de Leitura do Arquivo
-TableColumn.header.writerate=Taxa de Escrita
-TableColumn.header.writerate.info=Taxa de Escrita do Arquivo
-TableColumn.header.file_eta.info=Tempo estimado at\u00e9 o arquivo esteja baixado completamente
-label.force.piece=For\u00e7ar Peda\u00e7o
-label.rerequest.blocks=Pedir novamente blocos
-tag.show.overview=Exibir Sum\u00e1rio das Tag
-config.internal.browser=Navegador Interno
-config.internal.browser.info1=O navegador interno \u00e9 usado para exibir o conte\u00fado da web embutido no cliente, por exemplo, a p\u00e1gina da rede Vuze HD
-config.internal.browser.info2=Por padr\u00e3o o Internet Explorer \u00e9 usado no Windows, o Safari no Mac. * Limitado vers\u00f5es * do Firefox pode ser usado no lugar - veja as seguintes op\u00e7\u00f5es
-config.external.browser=Navegador Externo
-config.external.browser.info1=O navegador externo \u00e9 usado para exibir conte\u00fado da web fora do cliente, por exemplo nos casos dos detalhes dos resultado das buscas
-config.external.browser.info2=Navegador padr\u00e3o do seu computador \u00e9 usado normalmente. Voc\u00ea pode alterar isso para usar um navegador espec\u00edfico, ou que a fornecida por um plugin (por exemplo, o plug-in do navegador Tor)
-config.external.browser.switch.info=Voc\u00ea pode mudar de navegador interno para externo para alguns recursos, embora algumas funcionalidades podem ser perdidas
-external.browser.system=Padr\u00e3o do Computador
-config.external.browser.select=Navegador Selecionado
-config.external.browser.prog=Execut\u00e1vel do Navegador
-config.external.browser.test=Testar configura\u00e7\u00e3o do navegador externo
-external.browser.failed=Navegador Externo Falhou
-xmwebui.required=Voc\u00ea precisa instalar o "Vuze Web Remote" plugin para que isto trabalhar\n\nVeja Ferramentas>Plugins>Assistente de Instala\u00e7\u00e3o...
-config.external.browser.switch.feature=Recurso
-config.external.browser.switch.external=Externo
-config.external.browser.switch.implic=Implica\u00e7\u00f5es
-config.external.browser.switch.search=Resultados da pesquisa
-config.external.browser.switch.search.inf=Requer "Vuze Remote Web 'plug-in; Nenhum resultado web; nenhum modelo de recursos de edi\u00e7\u00e3o; Sem cria\u00e7\u00e3o de assinatura a partir dos resultados
-config.external.browser.switch.subs.inf=Requer "Vuze Web Remote" plugin; Resultados n\u00e3o pode ser "alterados" enquanto baixam;Sem configura\u00e7\u00e3o de refer\u00eancia sob os links de download
-label.bar.trans=Barra de transpar\u00eancia [0=opaco;100=transparente]
-subs.ext.view.info=Voc\u00ea configurou o Vuze para usa um navegdor externo para exibir os resultados das assinaturas
-subs.ext.view.launch.info=Pressione este bot\u00e3o para abrir o navegador
-delete.partial.files=Quando remover um download da biblioteca, apagar qualquer arquivo parcial selecionado como 'n\u00e3o baixar" ou 'apagar'
-# The remaining keys were not in MessagesBundle.properties
-ConfigView.label.popup.suppress_alerts=Suprimir alertas
-ConfigView.label.popup.use_message_boxes=Usar caixa de mensagem em vez da caixa de alerta popup padr\u00e3o.
-Content.alert.notuploaded.multi.text=%1 do seu conte\u00fado publicado n\u00e3o est\u00e1 completamente de seed. Se voc\u00ea %2 agora, as pessoas n\u00e3o ser\u00e3o capazes de baixar completamente o seu trabalho publicado.\n\nVoc\u00ea tem certeza de que voc\u00ea quer faz\u00ea-lo %2?\n\nConte\u00fado n\u00e3o completamente de seed:\n%3
-Content.alert.notuploaded.quit=sair do Vuze
-Content.alert.notuploaded.button.stop=&Parar
-ConfigView.label.popup.show.button=Mostrar
-MainWindow.menu.help.faq=&Perguntas Feitas Frequentemente
-Content.alert.notuploaded.multi.title=Uploads N\u00e3o Completados
-Content.alert.notuploaded.text=O Upload de '%1' n\u00e3o est\u00e1 completado. Se voc\u00ea %2 agora, as pessoas n\u00e3o ser\u00e3o capazes de baixar completamente o seu trabalho publicado.\n\nVoc\u00ea tem certeza de que voc\u00ea quer faz\u00ea-lo %2?
-MyTorrentsView.menu.removeand=Remo&ver e 
-window.uiswitcher.bottom.text=Sua sele\u00e7\u00e3o pode ser mudada facilmente de novo selecionando o bot\u00e3o do Escolhedor de IU do Vuze
-Content.alert.notuploaded.title=Upload N\u00e3o Completado
-webui.restart.info=Altera\u00e7\u00f5es nos par\u00e2metros marcados com um (*) requerem reiniciar para terem efeito
-Content.alert.notuploaded.button.continue=&Continuar Ficando de Seed
-Content.alert.notuploaded.stop=parar
-ConfigView.label.popup.show=Mostrar todos os alertas popup registrados at\u00e9 agora (se h\u00e1 algum)
+v3.MainWindow.menu.contentnetworks=Redes &HD
+window.uiswitcher.text=Por favor selecione uma interface de usu\u00E1rio abaixo que melhor se ajusta as suas necessidades.
+plugin.sharing.download.remove.veto=Este download \u00E9 o resultado de um recurso sendo compartilhado.\nPara remover o download remova o compartilhamento associado\: go to Tools->My Classic-Shares.
+VivaldiView.notAvailable=Visualiza\u00E7\u00E3o Vivaldi n\u00E3o dispon\u00EDvel
+ConfigView.section.file.showopentorrentoptions.sep=Usar dial\u00F3go separado por torrent
+sidebar.header.devices=Reprodu\u00E7\u00E3o dispositivo
+mdi.entry.tagdiscovery={tag.discovery.view.heading}
+speedtest.wizard.run=Executar um teste de velocidade
+importTorrentWizard.title=Importar um torrent XML
+v3.deviceview.infobar.line2.itunes=V\u00EDdeos aparecer\u00E1 na pasta de filmes do iTunes quando eles est\u00E3o prontos para jogar.
+splash.loadingImages=Carregando Imagens
+CacheView.writes.toFile=Para o Arquivo
+unix.script.new.text=Um novo script de inicializa\u00E7\u00E3o do Vuze est\u00E1 dispon\u00EDvel, e foi salvo em '%1'.\n\n\u00C9 altamente recomendado que voc\u00EA saia do Vuze e troque para este script ('%2').\n\nSe voc\u00EA modificou seu script de inicializa\u00E7\u00E3o do Vuze pesadamente, por favor veja <A HREF\="{unix.script.new.manual.url}">AzureusWiki\: Unix Script</A>.\n\nSe voc\u00EA instalou o Vuze de uma distro (yum, apt-get, etc), \u00E9 recomendado que voc\u00EA reinstale [...]
+ConfigView.section.style.showRankIcon=Exibir \u00CDcone de Ordem
+columnChooser.title=Escolher as colunas a exibir
+ConfigView.section.tracker.maxgettime=Tempo m\u00E1x. para processamento GET (segundos) [0\:ilimitado]
+Button.moveDown=Mover &pra Baixo
+ConfigView.label.hapds=Desconectar dos seeds para disfar\u00E7ar, mas complete downloads
+tag.stats.none.defined=Nenhuma tag com avalia\u00E7\u00E3o selecionado/definido\!
+label.download.file=Arquivo Baixado
+splash.unloadingTorrent=Descarregando Torrent
+ManagerItem.forced=For\u00E7ado
+device.search=Buscar por Dispositivos
+iconBar.play=Tocar
+ConfigView.label.seeding.rankType.seed.options=S\u00F3 Op\u00E7\u00F5es de Contagem dos Seeds
+IPChecker.external.service.discoveryvip.name=Discoveryvip 
+azbuddy.msglog.title=Informa\u00E7\u00E3o sobre o Amigo
+MyTorrentsView.menu.rename=Renomear
+stats.long.monthstart=Contagem do m\u00EAs come\u00E7a em\:
+wizard.tracker.dht=Decentralizado (s\u00F3 clientes Vuze)
+subscript.import.fail.desc=Detalhes\: %1
+pairing.ui.icon.tip.no.recent=Sem conex\u00F5es recentes
+platform.win32.baddll.FPServiceProvider=FoxyProxy Video Utility
+ConfigView.label.prioritizefirstpiece=Priorizar o primeiro e o \u00FAltimo peda\u00E7o do(s) arquivo(s)
+Wizard.Subscription.search.subtitle3=Uma vez que a sua subscri\u00E7\u00E3o \u00E9 completada, voc\u00EA receber\u00E1 atualiza\u00E7\u00F5es ao vivo na sua barra lateral sempre que novos resultados est\u00E3o dispon\u00EDveis para sua busca.
+Wizard.Subscription.search.subtitle2=O que eu posso procurar?
+Wizard.Subscription.search.subtitle1=Digite uma busca para come\u00E7ar a criar sua subscri\u00E7\u00E3o \:
+Peers.column.peer_id.info=A ID do Peer em formul\u00E1rio leg\u00EDvel
+ConfigView.section.connection.peersource.Plugin=Adicionadas por um plugin
+settings.updated.title=Configura\u00E7\u00F5es Atualizadas
+Button.ignore=&Ignorar
+ConfigTransferAutoSpeed.set.dht.ping=Configura\u00E7\u00E3o do Ping DHT\:
+ConfigView.section.connection.advanced.mtu.tooltip=Tamanho m\u00E1ximo de um pacote que pode ser transferido em um frame na rede.\nO Vuze usa MTU-40 (MSS) para otimiza\u00E7\u00F5es de packet-payload de upload.\nValores recomendados\:\n  576 - Conex\u00F5es Dial-up\n1492 - Conex\u00F5es de banda larga PPPoE\n1500 - conex\u00F5es de banda larga a Cabo,Ethernet e DSL 
+subscriptions.listwindow.subscribe=Subscrever
+ConfigView.title.full._mac=Prefer\u00EAncias
+remote.pairing.test.fail=Vuze n\u00E3o est\u00E1 acess\u00EDvel fora de sua rede local.  <A HREF\="/pairing_error_faq.start">Learn more</A>
+ipCheckerWizard.chooseService=Por favor escolha um servi\u00E7o de verifica\u00E7\u00E3o IP dos servi\u00E7os listados
+ConfigView.label.downloading.autoReposition=Reposicionar na fila de downloads para otimizar o download
+iconBar.top=Mover pro topo
+configureWizard.welcome.title=Bem-vindo ao Assistente de Configura\u00E7\u00E3o do Vuze
+ManagerItem.ready=Esperando por outro(s) torrent(s) para requisitar
+PeersView.BlockView.NoAvail.Have=Voc\u00EA tem; O peer n\u00E3o
+label.information={wizard.information}
+wizard.tracker.external=Usar um rastreador externo
+MagnetPlugin.report.found=encontrado(s) %1
+MagnetPlugin.report.md.done=Metadados baixado com sucesso
+Plugin.trackerpeerauth.info=Este plugin trabalha com os trackers para verificar que os peers s\u00E3o membros v\u00E1lidos da multid\u00E3o
+FilesView.click.info=Clique para calcular, use o bot\u00E3o direito do mouse no menu para v\u00E1rios c\u00E1lculos
+MyTorrentsView.menu.editWebSeeds=Editar Seeds HTTP
+Button.yes=Sim
+MyTorrents.items.UpSpeedLimit.disabled=Sem upload
+ConfigView.section.style.confirmationOnExit=Mostrar janela de confirma\u00E7\u00E3o ao sair
+label.num_selected=%1 selecionado
+PeersView.gain.info=Quantidade baixado - os dados enviados
+MagnetURLHandler.report.percent=completado\: %1%
+MyTorrentsView.dialog.NumberError.title=N\u00FAmero Inv\u00E1lido ou N\u00E3o Reconhecido
+ConfigView.section.connection.webseed.act.on.avail=Somente ativar seeds da Web/HTTP para baixar quando a disponibilidade for baixa
+SpeedTestWizard.test.panel.abort.countdown=abortar teste em\:
+remote.pairing.tip.title=Dica\: Duas maneiras f\u00E1ceis de usar Vuze Remoto\:
+Peers.column.as=AS/ASN
+PeersView.state.handshake=Esperando pelo handshake
+TableColumn.header.mergeddata=Fus\u00E3o da Multid\u00E3o
+upnp.mapping.dataport=Porta de Entrada dos Dados do Peer
+crypto.alert.as.warning=Rede '%1' \u00E9 conhecida por imp\u00F4r traffic shaping para reduzir a performance de download. A encripta\u00E7\u00E3o do transporte foi automaticamente ligada - isto pode ser desligado/modificado via par\u00E2metros de configura\u00E7\u00E3o. 
+network.admin.maybe.vpn.title=VPN Ativo?
+ConfigView.section.security.restart.msg=O Vuze reiniciar\u00E1 agora para completar a opera\u00E7\u00E3o.
+DevicesOD.column.od_status={MyTrackerView.status}
+library.incomplete.header=%1 item baixando, %2 aguardando para baixar
+TableColumn.menu.date_added.time=Mostrar/Esconder o Tempo
+ConfigView.section.proxy.testsocks=Testar SOCKS
+MainWindow.menu.file.export=&Exportar Torrent XML...
+splash.loadingTorrents=Carregando Torrents
+Button.removeAll=Remover Todos
+devices.copying=Copiando para dispositivo
+tags.view.infobar.text2=Visualizar e atribuir tags atribu\u00EDdas por outros usu\u00E1rios exibidas com o Descobrir Tags , localizado no menu de exibi\u00E7\u00E3o.
+sidebar.expand.tooltip=Expandir a Barra Lateral
+tags.view.infobar.text1=Descobrir Tags
+ConfigView.label.stop.RunScriptAndClose=Executar Script + Desligar o Vuze
+v3.MainWindow.view.wait=Inicializando a visualiza\u00E7\u00E3o, por favor espere.
+openUrl.title=Abrir Local
+Torrent.create.progress.piececount=Contagem dos peda\u00E7os\: 
+ConfigView.section.startstop={ConfigView.label.start} & {ConfigView.label.stop}
+OpenTorrentFile.column.download=Baixar?
+authenticator.location=Local
+upnp.alertothermappings=Relatar portas possu\u00EDdas por outros computadores
+ConfigView.section.ipfilter.peerblocking.group=Bloqueio de Peers
+TableColumn.header.tag.upload_priority={cat.upload.priority}
+SystemTray.menu.startalltransfers=Iniciar Todas as Transfer\u00EAncias
+health.explain.error=H\u00E1 um erro com este torrent.  Veja a coluna Status, ou a dica no \u00EDcone para o erro.
+IPChecker.external.service.discoveryvip.url=http\://ip.discoveryvip.com/ 
+ConfigView.section.Devices={devices.view.title}
+SpeedView.stats.estimatechoke=Estimativa (desobstru\u00E7\u00E3o)
+MainWindow.dht.status.unreachable=DHT Atr\u00E1s de Firewall
+json.file.browse=Abrir arquivo JSON
+Views.plugins.UPnP.title.tooltip=Universal Plug and Play
+dlg.stream.plus.subtext=Cansado de esperar seus downloads para completar? Assista mais cedo com Executar Agora, um recurso Vuze Plus que lhe permite assistir a um v\u00EDdeo ao mesmo tempo que continua a baixar.
+MainWindow.menu.view.mytorrents=&Meus Torrents
+Wizard.Subscription.subscribe.library=Conte\u00FAdo na sua Biblioteca
+splash.initializeCore=Iniiciando o Core
+ConfigView.section.transfer.autospeed=Auto-Velocidade (cl\u00E1ssica)
+iconBar.transcode=Dispositivo
+ConfigView.section.file.truncate.too.large=Cortar os arquivos existentes que s\u00E3o muito grandes
+GeneralView.label.size=Tamanho \: 
+ConfigView.copy.to.clipboard.tooltip=Copiar para a \u00E1rea de transfer\u00EAncia
+azbuddy.ui.table.name=Nome
+ConfigView.section.security.resetcerts.warning.title=Alerta de Perda de Dados
+SpeedView.stats.maxPing=Ping M\u00E1x\:
+TableColumn.header.writerate.info=Taxa de Escrita do Arquivo
+MainWindow.menu.file.folder.keybinding=Meta+Shift+O
+Subscription.menu.forcecheck=Atualizar Agora
+ConfigView.text.minutes=minutos
+MainWindow.menu.view.mytracker=Meu &Rastreador
+wizard.choosefile=Escolha o arquivo
+Button.preview=Pr\u00E9-visualizar
+menu.min.share.ratio=Taxa de Compartilhamento M\u00EDnimo (%1)...
+MyTorrents.column.ColumnQuality=Qualidade
+SpeedTestWizard.finish.panel.enabled=ativado
+DHTTransport.report.request_all=requisitando a transfer\u00EAncia inteira de %1
+ConfigView.label.seeding.preferLargerSwarms=Quando os torrents tem o mesmo rank, preferir as multid\u00F5es maiores
+fileDownloadWindow.state_initializing=Inicializando
+ConfigView.label.ircwiki=Por favor leia http\://azureuswiki.com/index.php/Rules_para o_IRC
+azbuddy.dchat.shared.tooltip=Compartilhado significa que o mesmo apelido \u00E9 usado em todos os canais por padr\u00E3o\nCanais p\u00FAblicos e an\u00F4nimos t\u00EAm configura\u00E7\u00F5es padr\u00E3o separados.
+LoggerView.loggingDisabled=Logging n\u00E3o est\u00E1 ativado.
+FilesView.%=% 
+subs.ext.view.launch.info=Pressione este bot\u00E3o para abrir o navegador
+MainWindow.dialog.share.sharedircontents.recursive=Recursivo
+Button.deleteContent.fromComputer=Apagar do Computador
+MainWindow.menu.help.checkupdate=&Procurar por Atualiza\u00E7\u00F5es...
+Trackers.column.name=Detalhes
+health.explain.yellow=significa que o rastreador est\u00E1 OK, voc\u00EA est\u00E1 conectado a peers, mas voc\u00EA n\u00E3o tem nenhuma conex\u00E3o remota.\nVoc\u00EA pode ter um problema de NAT se seus torrents ficam no estado amarelo o tempo todo
+dht.portdefault=Usar a porta padr\u00E3o
+Button.send=Enviar
+FilesView.mode=Modo
+PeerManager.status.finished=Terminado
+MyTorrentsView.dialog.setSpeed.title=Definir %1 velocidade
+MyTorrentsView.header=Torrents Incompletos
+MagnetPlugin.report.dead=%1 est\u00E1 morto
+azbuddy.ui.menu.ping=Ping
+devices.od.turnon.text3=Por favor, conecte o Disco R\u00EDgido no %1 para usar esse recurso.
+devices.od.turnon.text2=Voc\u00EA gostaria que %1 continuasse a baixar os arquivos enquanto o computador estiver offline?
+pairing.srp.enable=Ativar emparelhamento seguro
+devices.od.turnon.text1=N\u00F3s percebemos que voc\u00EA conectou-se a um %1.
+ConfigView.section.tracker.processinglimits=Limites de processamento
+IPChecker.external.service.no-ip.url=http\://www.no-ip.com/
+ConfigView.section.transfer.autospeed.forcemin=Velocidade de upload em %1 for\u00E7ada quando baselining a conex\u00E3o
+popup.previous=< (%1)
+LocaleUtil.column.encoding=Codifica\u00E7\u00E3o
+MainWindow.menu.transfers.startalltransfers=C&ome\u00E7ar Todos
+upnp.alert.mappingfailed=UPnP\: Falha no mapeamento '%1'
+FileView.BlockView.Active=Ativo
+authenticator.user=Nome de Usu\u00E1rio
+label.torrent.structure=Estrutura do Torrent
+Button.markSelected=Marcar os Selecionados
+sidebar.show.options=Exibir as Op\u00E7\u00F5es como uma barra lateral do qu\u00EA uma janela separada
+subscript.add.upgrade.title=Atualizar a Subscri\u00E7\u00E3o?
+window.uiswitcher.title=Escolhedor de IU do Vuze
+MyTorrentsView.menu.category.delete=&Apagar Categoria
+ConfigView.section.plugins=Plugins 
+v3.MainWindow.menu.file.closewindow.keybinding=Meta+W
+DownloadManager.error.filenotfound=Arquivo N\u00E3o Encontrado 
+TableColumn.header.copied=Copiado
+menu.json.to.bencode=Converter JSON Para BEncoded...
+ConfigView.section.security.resetkey.warning.title=Aviso sobre a Perda de Dados
+devices.contextmenu.xcode=Transcondifica Para Dispositivo
+label.table.default=Tabela Padr\u00E3o
+wizard.notimplemented=Ainda n\u00E3o implementado
+ConfigView.label.seeding.autoStart0Peers=Auto-Iniciar todos os torrents completados com 0 peers
+OpenTorrentOptions.header.saveto=Salvar com Destino\: %1
+Torrent.create.progress.ignoringfile=Ignorando arquivo
+label.keep.alive=Manter Vivo
+config.external.browser.switch.subs={ConfigView.section.Subscriptions}
+TableColumn.header.torrentfileindex=\u00CDndice de arquivo
+devices.installed=Instalado
+br.backup.auto.enable=Ativar backups autom\u00E1ticos
+TrackerAvail.column.name={Trackers.column.name}
+device.router.req_map=Mapeamentos obrigat\u00F3rios
+ConfigView.section.tracker.ip=Endere\u00E7o IP externo do rastreador
+azbuddy.enable_chat_notif=Ativar as notifica\u00E7\u00F5es do chat
+label.container.display=<container>
+TableColumn.header.swarm_average_completion.info=A porcentagem da conclus\u00E3o m\u00E9dia dos peers na multid\u00E3o
+dialog.uiswitcher.restart.title=Trocador de Interface do Usu\u00E1rio\: Requerido Reiniciar o Vuze
+ConfigView.label.transferbar.remember_location=Lembrar do \u00FAltimo local da barra de transfer\u00EAncia
+ConfigView.label.show.win.on.add=Mostrar a janela principal quando um download \u00E9 adicionado por outro aplicativo
+wizard.multitracker.group=Grupo de Rastreador
+dlg.auth.enter.line.try.2=Desculpe, n\u00F3s n\u00E3o podemos validar seu c\u00F3digo de ativa\u00E7\u00E3o. Por favor cheque o n\u00FAmero e tente digitar novamente.
+dlg.auth.enter.line.try.1=Digite seu c\u00F3digo de ativa\u00E7\u00E0o abaixo para completar sua atualiza\u00E7\u00E3o para o Vuze Plus
+SpeedView.stats.upload_details=%1
+device.status.online=O dispositivo est\u00E1 on-line
+TableColumn.header.DateTorrentLastActive.info=Data que o torrent esteve ativo pela \u00FAltima vez. N\u00E3o atualizar at\u00E9 o torrent estiver na fila ou parado.
+FileItem.write=escrita
+label.limit=Limite
+PiecesView.DistributionView.RarestAvl=Peda\u00E7os Mais Raros\: %1 (Avl\:%2)
+PeersView.BlockView.Transfer=Transferindo
+LoggerView.filter.uncheckAll=Desmarcar Todas as Categorias
+MyTorrentsView.menu.manual.per_torrent=Manual (por torrent)
+MainWindow.menu.file.open.torrentforseeding=Arquivo Torrent... (Para Ficar de Seed)
+dialog.associations.title=Verifica\u00E7\u00E3o de Associa\u00E7\u00E3o
+ConfigView.label.jvm=Op\u00E7\u00F5es do Java
+ConfigView.label.playdownloadspeech=Falar quando um download est\u00E1 terminado
+dlg.auth.install.subtitle.trial=Instalando Gravador de DVD
+configureWizard.transfer.title=Configura\u00E7\u00F5es de Transfer\u00EAncia e Conex\u00E3o
+upnp.ignorebaddevices=Ignorar dispositivos que falham em responder corretamente
+label.rerequest.blocks=Pedir novamente blocos
+ConfigView.section.ipfilter.remove=Remover
+OpenTorrentOptions.header.startoptions=Op\u00E7\u00F5es de Iniciar\: %1
+Formats.units.Tibit=Tibit
+window.networkselection.description=Torrent\:
+configureWizard.transfer.connection=Linha
+PeersView.Messaging.info=Suporta o envio de mensagens avana\u00E7ado API.
+general.all.friends=Todos os Amigos
+IrcClient.joining=Entrando
+subscriptions.dl_subs.enable=Baixe assinaturas de outros clientes, quando necess\u00E1rio
+ConfigView.section.connection.encryption.encrypt.info=Se a encripta\u00E7\u00E3o est\u00E1 ativada voc\u00EA n\u00E3o ser\u00E1 capaz de conectar a clientes incompat\u00EDveis a menos que voc\u00EA configure as op\u00E7\u00F5es de retorno
+ConfigView.section.logging.log2type=Erro
+TableColumn.header.sessionup.info=Byts enviados nesta sess\u00E3o
+label.tags=Tags
+azneti2phelper.install=Instalar Plugin I2P
+SpeedTestWizard.finish.panel.auto.speed.seeding=AutoVelocidade enquanto ficando de seed \u00E9 \: 
+ConfigView.label.seeding.numPeersAsFullCopy.tooltip=Fingindo que h\u00E1 1 c\u00F3pia completa por X peers, voc\u00EA reduz o rank dos torrents com alta contagem de peers.\n\u00C9 prov\u00E1vel que os torrents com contagem alta de peers tamb\u00E9m possuam alto tr\u00E1fego.\nIsto n\u00E3o muda quaisquer das exibi\u00E7\u00F5es '\# de seeds'.
+ConfigView.section.dns.info=Esta se\u00E7\u00E3o especifica servidores DNS alternativos e define em que podem ser utilizados.\n\nPor exemplo, o Google executa um servidor DNS no endere\u00E7o 8.8.8.8 (e 8.8.4.4 para backup)\n\nIsso pode ser \u00FAtil quando o provedor de DNS existente n\u00E3o est\u00E1 resolvendo nomes corretamente.\n
+TableColumn.header.DateCompleted={TableColumn.header.date_completed}
+dht.backup.only=DHT como backup somente
+ConfigView.section.proxy.check.on.start=Verificar o status do proxy ao iniciar
+TableColumn.header.date_completed=Completado Em
+UIDebugGenerator.messageask.text=Por favor insira uma descri\u00E7\u00E3o do bug que voc\u00EA est\u00E1 reportando
+config.browser.internal.disable=Desabilitar todos os usos do navegador interno.
+Button.deleteContent.fromLibrary=Remover da Biblioteca
+ConfigView.section.connection.peersource.Tracker=De um rastreador
+library.launch.web.in.browser.anon=Navegue anonimamente
+iconBar.queue=Iniciar
+CacheView.reads.avgsize=Tamanho M\u00E9dio
+ConfigView.section.file.perf.cache.enable.read=Realizar leituras adiantadas para reduzir as leituras do disco enquanto faz upload
+SpeedTestWizard.set.upload.panel.explain=Os limites definidos aqui s\u00E3o usados pelo algor\u00EDtmo de AutoVelocidade do Vuze. Defina os limites de transfer\u00EAncia e os limites de confian\u00E7a.\n\nNote que as velocidades da linha s\u00E3o frequentemente quotadas em "bits por segundo" - contudo o valor abaixo \u00E9 mostrado em "kilobytes por segundo".
+wizard.maketorrent.piececount=Contagem de Peda\u00E7os
+change.url.msg.desc=Isso ir\u00E1 criar uma nova assinatura e renomear a que existe
+CacheView.reads.title=Leituras E/S
+ConfigView.section.style.inactiveUpdate=Atualizar a janela principal a cada atualiza\u00E7\u00E3o(\u00F5es) da N GUI quando n\u00E3o \u00E9 a janela ativa
+v3.iconBar.up={iconBar.up}
+v3.mb.PlayFileNotFound.text=Os arquivos para '%1' est\u00E3o ou apagados ou desaparecidos.
+plus.notificaiton.OfflineExpiredEntry=Voc\u00EA ficou desconectado por muitos dias. Vuze Plus foi desativado.
+tags.view.heading=S\u00FAmario das Tags
+ConfigView.label.queue.stoponcebandwidthmet=N\u00E3o iniciar mais quaisquer torrents quando o limite da velocidade de upload/download for alcan\u00E7ado
+ConfigView.button.save=Salvar
+Security.keystore.corrupt=Keystore '%1' falhou ao carregar, por favor apague-a e recrie/re-importe os certificados
+azbuddy.dchat.pc.pinned.only=Somente aceitar bate-papos de participantes pinados
+UpdateWindow.status.restartNeeded=Reiniciar ser\u00E1 necess\u00E1rio\!
+importTorrentWizard.process.inputfilebad.message=Uma falha ocorreu ao acessar o arquivo de entrada de dados\:
+ConfigView.section.security.op.error.title=A Opera\u00E7\u00E3o Falhou
+subscript.add.desc=Voc\u00EA tem certeza que voc\u00EA quer instalar a subscri\u00E7\u00E3o '%1'?
+ConfigView.section.tracker.maxgettime.info=Usado para an\u00FAncio e limpezas
+tps.type.plugin=Plugin
+azbuddy.tracker.bbb.status.in=Eu Estou Sendo Acelerado
+devices.copy.folder.dest=Copiar para pasta
+ConfigView.text.hours=horas
+label.monitor.clipboard=Monitorar \u00C1rea de Transfer\u00EAncia Por Links de Torrents
+#
+# Tooltips
+#
+GeneralView.label.status.pieces_available.tooltip=Exibe o n\u00FAmero de c\u00F3pias dispon\u00EDveis de cada peda\u00E7o.\nSe o n\u00FAmero a direita for menor que 1, voc\u00EA n\u00E3o est\u00E1 vendo uma c\u00F3pia completa do arquivo (e pode ter problemas para completar o download).
+GeneralView.label.in_swarm=na multid\u00E3o
+MyTrackerView.scrapes=Scrapes
+MainWindow.menu.file.open.torrentfortracking=Arquivo Torrent... (Apenas Tracking)
+label.close.tab=Fechar Aba
+window.updateswt.title=Sua vers\u00E3o da SWT \u00E9 muito antiga\!
+ConfigView.label.autoupdate=Abrir o di\u00E1logo de atualiza\u00E7\u00E3o quando uma vers\u00E3o mais nova estiver dispon\u00EDvel
+update.now.title=Atualiza\u00E7\u00E3o Requirida
+subscript.add.dup.desc=A subscri\u00E7\u00E3o '%1' j\u00E1 est\u00E1 instalada.
+upnp.ignorebaddevices.reset=Resetar a lista de dispositivos ignorados
+ManagerItem.downloading=Baixando
+DiskManager.error.nospace_fat32={DiskManager.error.nospace} - checar {wiki.fat32}
+Button.retry=&Tentar de Novo
+PeersView.state.info=Estado da conex\u00E3o com o peer
+device.rss.enable=Criar um feed RSS para o arquivo convertido - isto faz o conte\u00FAdo dispon\u00EDvel para leitores de feed RSS
+ConfigView.section.ipfilter.allow=PERMITIR estes intervalos (o padr\u00E3o \u00E9 NEGAR)
+progress.window.msg.filemove=Por favor espere enquanto a movimenta\u00E7\u00E3o/renomeamento do arquivo se completa
+OpenTorrentWindow.mb.alreadyExists.default.name=M\u00EDdia
+mdi.entry.about.devices=Em progresso
+update.fail.app.changed.title=Falha na Atualiza\u00E7\u00E3o
+pairing.alloc.fail=Falha ao alocar um novo c\u00F3digo de acesso\n%1
+ConfigView.section.tracker.portbackup=Fazer backup das portas (separadas por ';')
+MinimizedWindow.all_transfers=Transfer\u00EAncias do Vuze
+ConfigView.section.tracker.natchecktimeout=Verifica o esgotamento do tempo (segs)
+iconBar.share=Compartilhar
+TableColumn.header.sessiondown.info=Bytes baixados nesta sess\u00E3o
+devices.turnon.itunes=Inclu\u00EDdo suporte para iTunes (requerido para dispositivos da Apple)
+PeersView.menu.showdownload=Exibir Download &Detalhes
+SpeedTestWizard.abort.message.entered.queued=Teste baixado entrou em estado requerido/parado
+Button.renew=Renovar
+ConfigView.text.any=qualquer
+FilesView.sha1.calculate=Calcular SHA1 hash(s)
+OpenTorrentFile.column.name.info={OpenTorrentWindow.fileTable.fileName}
+PeersView.outgoingreqcount.info=Contagem dos pedidos de sa\u00EDda feitos pelo peer
+ConfigView.section.style.ShowTagButtons=Exibir Bot\u00F5es de Tag na Biblioteca
+subscriptions.view.help.2=Obtenha atualiza\u00E7\u00F5es ao vivo gr\u00E1tis sempre que novo conte\u00FAdo est\u00E1 dispon\u00EDvel para baixar. <A HREF\="http\://wiki.vuze.com/w/FAQ_Subscriptions">Leia mais</A>.
+subscriptions.view.help.1=Adicionar Subscri\u00E7\u00F5es onde quer que voc\u00EA veja
+ConfigView.section.proxy.disable.plugin.proxies=Desabilitar plugins proxis (exemplo\: Tor/I2P plugins) quando o servidor SOCKS est\u00E1 configurado
+azbuddy.dchat.open.in.vuze=Abrir no Vuze
+MyTorrentsView.menu.setSpeed.in=entrada
+TorrentOptionsView.multi.title.short=Op\u00E7\u00F5es do Torrent
+br.backup.auto.now=Testar  auto-backup agora
+OpenTorrentWindow.checkbox.showAdvanced=Uma vez que o torrent \u00E9 carregado, deixe-me definir op\u00E7\u00F5es avan\u00E7adas, como a sele\u00E7\u00E3o de arquivo e o local para salvar.
+ConfigView.section.proxy.username.info=Se o servidor proxy exige autentica\u00E7\u00E3o mesmo quando nenhuma est\u00E1 definida, use a string "<nenhuma>" como nome de usu\u00E1rio
+settings.updated.msg=Suas configura\u00E7\u00F5es do Vuze foram atualizadas.
+GeneralView.label.numberofpieces=\# de Peda\u00E7os \: 
+ConfigView.label.enableSystrayToolTipNextETA=Exibir pr\u00F3ximo download a completar
+splash.plugin=Carregando o Plugin\:  
+Progress.reporting.window.remove.auto.tooltip=Automaticalmente remover todos os processos completados, falhos ou cancelados da visualiza\u00E7\u00E3o
+ConfigView.label.set_ui_transfer_speeds.description.upload=Definir as velocidades de upload (em KB/s)
+wizard.webseedseditor.edit.newseed=Novo Seed
+wizard.newtorrent.showtorrent=Procure o arquivo torrent gerado
+installPluginsWizard.details.loading=Carregando detalhes, aguarde por favor...
+v3.MainWindow.button.cancel=Cancelar
+ConfigView.section.logging.netinfo=Gerar info sobre a rede
+importTorrentWizard.process.unknownfail.title=Erro Inesperado
+TableColumn.header.status=Status
+MainWindow.menu.community.chat=Comunidade &Bate-papo
+label.pop.out=Sair
+TableColumn.header.upspeed.info=Velocidade de upload atual
+Button.bar.edit.cancel=Edi\u00E7\u00E3o Feita
+PeersView.C1.info=Ou o peer est\u00E1 impedindo voc\u00EA de baixar
+menu.change.url=Mudar URL...
+Network.alert.acceptfail=Muitas falhas sucessivas ocorridas na porta %1, %2 - processamento abandonado. Por favor, cheque as configura\u00E7\u00F5es do firewall para esta porta para garantir que est\u00E1 habilitada para receber conex\u00F5es.
+TableColumn.header.activityDate=Data Adicionada
+TableColumn.header.priority.info=Determina quanta banda de upload \u00E9 dada ao torrent
+GeneralView.label.tracker=Status do Rastreador \: 
+ConfigView.section.connection.peersource.DHT=Rastreamento descentralizado
+ConfigView.section.interface.wavlocation=Localiza\u00E7\u00E3o do arquivo .wav
+ConfigView.section.style.disableAlertSliding=Desativar anima\u00E7\u00E3o de sliding/em alto estilo para mensagens de alerta
+device.od.error.nospace=Sem espa\u00E7o no dispositivo ou nenhum drive externo conectado
+PeersView.uniquepiece=Peda\u00E7o (modo Super-Seed)
+security.certcreate.orgunit=Unidade Organizacional
+metasearch.addtemplate.desc=Voc\u00EA tem certeza que voc\u00EA quer instalar um modelo de busca chamdo '%1'?
+ConfigView.section.transfer.autospeed.maxupload=Velocidade m\u00E1xima de upload em %1 [0\: ilimitada]
+Formats.units.persec=/s
+# Will be used for {library.name} in VuzeUI view
+library.name._vuze=Biblioteca
+ConfigView.pluginlist.coreplugins=Os seguintes plugins embutidos est\u00E3o carregados\:
+ConfigView.section.transfer.autospeed.maxdec=Diminui\u00E7\u00E3o m\u00E1xima em %1 por ciclo
+configureWizard.nat.server.tcp_listen_port=Porta de Escuta da Entrada TCP
+configureWizard.nat.tooManyPorts=Muitas portas para testar (m\u00E1x. 9)
+MyTorrentsView.menu.upSpeedLimit=Limite de Velocidade de Upload
+GeneralView.title.full=Geral 
+UIDebugGenerator.message.cancel.text=Voc\u00EA n\u00E3o inseriu uma descri\u00E7\u00E3o do bug que voc\u00EA est\u00E1 tentando reportar.  O seu bug pode ser \u00F3bvio pra voc\u00EA, mas sem uma descri\u00E7\u00E3o, n\u00F3s s\u00F3 estar\u00EDamos tentando advinhar o seu problema.\n\nA Gera\u00E7\u00E3o de Informa\u00E7\u00E3o sobre o Debug foi cancelada.
+ConfigView.text.all=todos
+MainWindow.menu.tools.nattest=&Teste do NAT / Firewall
+ConfigView.section.transfer.autospeed.chokeping.tooltip=Os tempos do Ping em excesso deste valor ser\u00E1 considerado como um indicador de satura\u00E7\u00E3o de rede
+v3.MainWindow.tab.browse=No Vuze
+auto.mode=Autom\u00E1tico (recomendado)
+v3.activity.button.watchall=Marcar Todos os Observados
+ConfigView.label.minPeersToBoostNoSeeds=Rank da Prioridade para Ficar de Seed menor para torrents sem seeds e com menos de
+ConfigView.section.style.defaultSortOrder.flip=Oposto da ordem anterior
+azbuddy.dchat.rchans=Canais Relacionados
+TorrentOptionsView.param.alternative.value.enable=Alternar o valor quando ficando de seed
+Trackers.column.last_update=\u00DAltima Atualiza\u00E7\u00E3o
+IPChecker.external.httpinvalidresponse=Resposta HTTP inv\u00E1lida
+columnChooser.apply=Aplicar
+ConfigView.section.file.perf.cache.trace=Rastrear opera\u00E7\u00F5es de cache para fins de diagn\u00F3stico
+MagnetPlugin.report.alive=%1 est\u00E1 vivo
+TableColumn.header.maxdownspeed=M\u00E1x de Velocidade de Down
+ConfigView.section.tracker.torrentsperpage=Quantos torrents por p\u00E1gina?  [0\: ilimitados]
+platform.win32.baddll.AxShlex=Alcohol 120%
+ConfigView.section.ipfilter.bannedinfo=IPs que enviaram dados ruins - banidos se os limites excederam
+OpenTorrentWindow.set.savepath=Mudar o Nome da Pasta de N\u00EDvel Superior
+Formats.units.Kibit=Kibit
+LoggerView.filter=Filtro
+OpenTorrentOptions.header.tags={label.initial_tags}\: %1
+FilesView.rename.failed.text=A opera\u00E7\u00E3o falhou, provavelmente devido a sele\u00E7\u00E3o de alvo inv\u00E1lida
+azbuddy.tracker.bbb.status.out=Atualmente Acelerando os Amigos
+ConfigView.label.sleep.fpseed='Primeira Prioridade' seeding est\u00E1 ativo
+subscriptions.listwindow.autochecktext=O Vuze pode achar subscri\u00E7\u00F5es relacionadas ao conte\u00FAdo na sua biblioteca. Voc\u00EA quer ativar esta fun\u00E7\u00E3o?
+discarded=descartado
+ConfigTransferAutoSpeed.ping.time.good=Bom\:
+installPluginsWizard.list.name=Nome
+ConfigView.section.backuprestore=Backup & Restaurar
+DownloadActivityView.legend.up_smooth=Envio (Suave)
+devices.contextmenu.od.enable=Habilitado
+pairing.status.registered=Atualizado com sucesso (%1)
+DHTView.activity.details=Detalhes
+platform.win32.baddll.WSOCKHK=Net nanny
+ConfigView.label.minSeedingTime.tooltip=Os Ranks de Seeding podem flutuar frequentemente em um curto per\u00EDodo de tempo, as vezes fazendo o torrent iniciar automaticamente, apenas para ser parado & e posto no fila imediatamente ap\u00F3s isso.\nIsto alivia o problema for\u00E7ando o torrent a ficar de seed por um per\u00EDodo dado de tempo.  Voc\u00EA ainda pode par\u00E1-lo manualmente se voc\u00EA quiser.
+PeerSocket.fake_client=FALSO
+TrackerChangerWindow.title=Adicionar Rastreador(es)
+wizard.savingfile=Salvando Arquivo...
+platform.jvmopt.configerror=N\u00E3o \u00E9 poss\u00EDvel gerenciar as op\u00E7\u00F5es de JVM devido a um erro de configura\u00E7\u00E3o
+OpenTorrentFile.column.size.info=Tamanho do Arquivo
+ConfigView.section.security.resetkey.error.title=A Opera\u00E7\u00E3o Falhou
+ConfigView.section.queue.seeding.autoStarting=In\u00EDcio Autom\u00E1tico
+ConfigView.section.security.restorekeys=Restaurar as chaves de um arquivo
+MainWindow.menu.file.open.torrent.keybinding=Meta+O
+MainWindow.status.unofficialversion=Beta do Vuze
+wizard.operationfailed=A opera\u00E7\u00E3o falhou
+IPChecker.external.timeout=Ocorreu um esgotamento do tempo
+ipfilter.disabled=Filtros de IP desativado
+TableColumn.header.seeds.info=\# seeds conectados para (\# seeds no total)
+speedtest.wizard.select.general=O teste de velocidade geral (recomendado)
+wizard.comment=Coment\u00E1rio
+unix.script.new.auto.text=Um Novo Script de Inicializa\u00E7\u00E3o do Vuze est\u00E1 dispon\u00EDvel.\n\n\u00C9 altamente recomendado que voc\u00EA reinicie o Vuze agora.
+installPluginsWizard.file.invalidfile=O arquivo n\u00E3o \u00E9 um plugin v\u00E1lido do Vuze.
+MyTorrentsView.menu.setSpeed.down.disable=Desabilitar Download
+wizard.multitracker.edit.newgroup=Novo Grupo
+v3.MainWindow.menu.view.footer=Barra dos Amigos
+TableColumn.header.remaining.info=Quantia restante para baixar
+platform.win32.baddll.gapsp=Neoteris
+Pieces.column.Requested=Requesitado
+iconBar.bottom=Mover pro fundo
+SpeedTestWizard.abort.message.scheduling.failed=O agendamento do teste falhou
+TableColumn.header.file_eta={TableColumn.header.eta}
+PeersView.source.info=A fonte deste peer
+GeneralView.label.totalspeed.tooltip=Velocidade total (e m\u00E9dia) de todos os clientes aos quais voc\u00EA est\u00E1 conectado.
+FilesView.menu.setpriority.high=&Alta
+tag.type.man.featcon=Conte\u00FAdo em Destaque
+ConfigView.section.dns.alts=Servirdores DNS alternativos [separados por ';']
+ConfigView.section.style.dropdiraction.sharefoldercontents=Compartilhar Conte\u00FAdo
+azbuddy.tracker.bbb.status.title.tooltip=Clique duplo para detalhes
+library.launch.web.in.browser.dir.list=Sempre Mostrar Lista de Arquivos
+speedtest.wizard.select.title=Selecione o tipo de teste de velocidade
+PeersView.uploadspeed=Velocidade de Upload
+SpeedTestWizard.test.panel.already.running=O teste j\u00E1 est\u00E1 rodando\!
+table.columns.reset=Redefinir Colunas
+MySeedersView.header=Torrents Completos
+device.renderer.view.title=Renderizadores
+upnp.mapping.tcpssltrackerport=Porta do Rastreador TCP SSL
+IrcClient.hasleft=saiu
+TableColumn.header.downspeed=Velocidade de Down
+wizard.newtorrent.byo=Construa seu pr\u00F3prio
+MainWindow.menu.community.forums=F\u00F3runs da Co&munidade
+GeneralView.label.user_comment=Coment\u00E1rio do Usu\u00E1rio \: 
+MainWindow.IPs.tooltip=\u00DAltima atualiza\u00E7\u00E3o da lista de filtros\: %1\nTotal de Filtros IP na lista - N\u00BA de IPs bloqueados/banidos/ruins nesta sess\u00E3o.\nClique duas vezes para detalhes.
+OpenTorrentWindow.mb.notTorrent.cannot.display=Incapaz de exibir os dados apropriadamente
+General.percent=Porcentagem
+beta.wizard.disable.text=Obrigado por testar as vers\u00F5es beta\!\n\nFa\u00E7a o download e instale a vers\u00E3o mais recente a deixar o programa beta
+Button.turnon=Ligar
+TableColumn.header.torrentrelpath=Caminho do Torrent
+swt.alert.cant.update=biblioteca SWT carregada de "%3" n\u00E3o p\u00F4de ser automaticamente atualizada da vers\u00E3o %1 para a %2 (deve ser carregada de "%4"). Por favor veja <A HREF\="http\://azureuswiki.com/index.php/SWT_Cant_Auto_Update">no wiki</A> para detalhes.
+ConfigView.section.interface.checkassoc=Verificar associa\u00E7\u00F5es ao iniciar
+webui.port=Porta (*)
+subscript.some.subscribed=Voc\u00EA est\u00E1 subscrito a algumas das subscri\u00E7\u00F5es para este conte\u00FAdo.\nClique para ver as outras dispon\u00EDveis
+show.tooltip.label=Exibir Dicas
+br.backup.auto.everydays=Freq\u00FC\u00EAncia de backup [dias]
+label.tag.selection=Tags Selecionadas
+ConfigView.section.security.choosetoolssavedir=Selecione a pasta contendo o arquivo 'tools.jar'
+v3.MainWindow.menu.view.toolbars=Barras de Ferramentas
+subscript.export.select.template.file=Salvar a Subscri\u00E7\u00E3o
+window.update.noupdates.beta.title={window.update.noupdates.title}
+TableColumn.header.priority=Prioridade
+devices.copy.folder.auto=Automaticamente copiar os arquivos para a pasta
+TableColumn.header.tag.visible={label.visible}
+MyTorrentsView.\#.info={TableColumn.header.\#.info}
+platform.win32.baddll.radhslib=Naomi Filtro de internet ( Radiante )
+Scrape.status.error.nohash=Hash inexistente na resposta.
+MagnetURLHandler.report.torrent_size=tamanho do torrent\: %1
+Wizard.Subscription.create.title=Criar Nova Subscri\u00E7\u00E3o
+jvm.max.direct.mem.info=Nota\: esta op\u00E7\u00E3o de mem\u00F3ria "Direta", \u00E9 o mais comum para a necessidade de atualizar a  mem\u00F3ria "Heap" acima.
+azbuddy.chat.says=%1 diz\:
+menu.max.share.ratio=Taxa de Compartilhamento Alvo (%1)...
+device.xcode.group={device.xcode}
+OpenTorrentWindow.torrent.remove=Remover torrent da lista
+ActivityView.legend.swarmaverage=M\u00E9dia da multid\u00E3o
+TableColumn.header.seed_to_peer_ratio=Propor\u00E7\u00E3oSeed2Peer
+MainWindow.menu.window=&Janela
+device.router.con_type=Conex\u00E3o\: %1
+SpeedView.stats.estupcap=Limite de Upload\:
+importTorrentWizard.torrentfile.title=Sele\u00E7\u00E3o da Entrada de Dados do Torrent
+ConfigView.label.savedirectory=Diret\u00F3rio para Salvar
+label.open.all=Abrir Todos
+TableColumn.header.timesincedownload.info=O tempo decorrido desde que os dados foram baixados para o torrent
+DownloadActivityView.title.full={TableColumn.header.Speed}
+pairing.ac.getnew=Alocar um novo c\u00F3digo de acesso
+Button.apply=Aplicar
+ConfigView.section.style.launch=Auxiliar de In\u00EDcio
+TableColumn.header.done.info=Porcentagem feita da tarefa atual
+GeneralView.label.shareRatio=Propor\u00E7\u00E3o de Compartilhamento\: 
+SpeedTestWizard.set.upload.bits.per.sec=bits/seg
+FilesView.menu.rename_only=Renomeamento R\u00E1pido
+MainWindow.menu.view.ipFilter=&Filtros de IP
+v3.mb.delPublished.cancel=&Cancelar
+label.click.to.showhide=Clique para mostrar/esconder
+label.alertnum=Alertas\: %1
+devices.xcode.rsspub=Publicar feed RSS
+upnp.mapping.tcptrackerport=Porta do Rastreador TCP
+remote.pairing.test.success=Vuze \u00E9 acess\u00EDvel remotamente.
+sidebar.header.subscriptions=Assinaturas
+dlg.auth.revoked.link=<A HREF\="info">informa\u00E7\u00E3o sob c\u00F3digos de ativa\u00E7\u00E3o Revogado</A>
+TableColumn.header.readrate=Taxa de Leitura
+ConfigView.section.file.defaultdir.section=Op\u00E7\u00F5es Padr\u00E3o do Diret\u00F3rio
+Peers.column.peer_byte_id.info=ID do Peer em formul\u00E1rio em bytes
+label.color=Cores
+ConfigView.label.seeding.firstPriority.info=Torrents com Primeira Prioridade sempre estar\u00E3o no topo da fila.\nQuaisquer torrents combinando com o Crit\u00E9rio de Primeira Prioridade n\u00E3o ser\u00E3o automaticamente parados e enfileirados.\nUm torrent combinando com o crit\u00E9rio de Primeira Prioridade tomar\u00E1 um slot de download simult\u00E2neo se ele precisar.
+ConfigView.label.movetorrent=Mover .torrent
+ConfigView.section.tracker.enablecompact=Ativar o protocolo de an\u00FAncio compacto
+ConfigView.label.maxStalledSeeding=M\u00E1ximo 'stalled' [0\:ilimitado]
+azbuddy.ui.menu.send=Enviar Mensagem
+jvm.min.mem=Tamanho da mem\u00F3ria Heap M\u00EDnimo [branco\=padr\u00E3o,min\=%1]
+ConfigView.notAvailableForMode=Esta se\u00E7\u00E3o \u00E9 destinada para o modo %1 ou mais alto.  N\u00E3o est\u00E1 dispon\u00EDvel no modo %2.
+devices.choose.profile.info.text=Ap\u00F3s a sele\u00E7\u00E3o, Vuze vai detectar ou n\u00E3o o formato de v\u00EDdeo ser\u00E1 reproduzido no dispositivo selecionado e criar uma c\u00F3pia compat\u00EDvel com o dispositivo, se necess\u00E1rio.\n\nPasse o mouse sobre o dispositivo selecionado para ver mais detalhes.
+ConfigView.label.userequestlimitingpriorities=Focar a velocidade do download no come\u00E7o da fila de download quando o limite da velocidade de download foi alcan\u00E7ado
+UpdateWindow.columns.install=Instalar
+network.admin.maybe.vpn.msg=Parece que voc\u00EA pode ter uma rede privada virtual (VPN) ativo no\\n\\n\\t%1\\n\\nIf este \u00E9 o caso, voc\u00EA pode aumentar a privacidade explicitamente vincula\u00E7\u00E3o a esse - Escolha Sim para faz\u00EA-lo.\n\nIf n\u00E3o, ou voc\u00EA n\u00E3o tem certeza, selecione NO.\n\nVeja <a href\="http\://wiki.vuze.com/w/Proxies_And_VPNs\#VPN_Configuration">the wiki</a> para mais informa\u00E7\u00F5es.
+MainWindow.upgrade.newerversion=Existe uma vers\u00E3o mais nova do Vuze dispon\u00EDvel para download 
+ConfigView.label.experimental.osx.kernel.panic.fix=Corre\u00E7\u00E3o experimental para os p\u00E2nicos do kernel em sistemas dual-cpu OSX [requer reiniciar]
+azbuddy.disabled=O plugin est\u00E1 desativado, veja a config do plugin para mudar.
+unix.script.new.auto.title=Novo Script de Inicializa\u00E7\u00E3o do Vuze
+ConfigView.section.connection.advanced.SO_RCVBUF.tooltip=Define o valor do socket padr\u00E3o SO_RCVBUF (em bytes), i.e. tamanho e escala da janela de recebimento TCP.\nO Vuze deixa isto n\u00E3o definido por padr\u00E3o, significando que os padr\u00F5es para o SO b\u00E1sico s\u00E3o usados.\nNOTA\: O linux dobra o valor dado.
+ConfigView.section.style.useSIUnits=Usar Unidades IEC (KB -> KiB etc.)
+azbuddy.ui.menu.cat=Tags/Categorias
+device.config.xcode.maxbps=N\u00EDve Max KB/seg de transcode [0\: ilimitado]
+MainWindow.menu.file.closetab=Fechar &Aba
+ConfigView.label.stop=Desligar
+wizard.invalidfile=Arquivo Inv\u00E1lido\!
+wizard.invaliddirectory=Diret\u00F3rio Inv\u00E1lido\!
+installPluginsWizard.mode.file=Por arquivo
+config.external.browser.switch.subs.inf=Requer "Vuze Web Remote" plugin; Resultados n\u00E3o pode ser "alterados" enquanto baixam;Sem configura\u00E7\u00E3o de refer\u00EAncia sob os links de download
+ConfigView.label.savetorrentbackup=Salvar Backup
+TagSettings.viewInSideBar=Exibir na Barra Lateral
+quick.view.no.files=Nenhum Arquivo Aplic\u00E1vel
+UpdateProperty.list.message=Digite novo valor para %1. Use ',' para separar m\u00FAltiplas entradas; deixe em branco para limpar
+ConfigView.section.security.toolsdir=Diret\u00F3rio contendo o arquivo 'tools.jar'
+ConfigView.section.file.tb.delete=Ao excluir via tecla Delete ou barra de ferramentas\:
+DHTTransport.report.send_complete=enviar completados
+MainWindow.about.internet.bugreports=Relatar Bugs
+azbuddy.downspeed=M\u00E1x da velocidade de download em KB/s do amigo [0\: ilimitada]
+TableColumn.header.timesinceupload.info=O tempo decorrido desde que os dados foram enviados para o torrent
+ConfigView.label.systray._mac=\u00CDcone da Barra de Status
+v3.deviceview.infobar.line1.generic=Arrastar e soltar os v\u00EDdeos de sua biblioteca para %1 em sua barra lateral.
+ConfigView.section.proxy.enable_socks=Eu tenho um Proxy SOCKS
+azbuddy.ui.table.lastseen=Visto pela \u00DAltima Vez
+MyTorrentsView.menu.rescanfile=Periodicamente Re-verifcar os Peda\u00E7os Incompletos
+ConfigView.section.mode=Modo
+label.anon=An\u00F4nimo
+xcode.deletedata.title=Excluir conte\u00FAdo transcodificado
+ConfigView.label.irclogin=Apelido
+TableColumn.header.device.info=Dispositivo Alvo
+ConfigView.section.ipfilter.save=Salvar
+wizard.multitracker.delete=Apagar
+iconBar.editcolumns=Configura\u00E7\u00E3o da Coluna
+PiecesView.DistributionView.NoAvl=Peda\u00E7os Indispon\u00EDveis
+sidebar.show=Exibir barra lateral
+TableColumn.header.upload.info=Quantia de dados que n\u00F3s enviamos para o epeer
+ConfigView.section.sharing.privatetorrent=Torrent privado - s\u00F3 aceitar peers do rastreador
+installPluginsWizard.list.loading=Por favor, espere enquanto a lista de plugins \u00E9 carregada.
+Button.bar.add=Adicionar Amigos
+exportTorrentWizard.torrentfile.browse=Navegar
+MyTrackerView.tracker=Rastreador
+devices.associate=Associado com
+ConfigView.section.security.backupkeys.button=Backup
+ConfigView.option.dm.dblclick.details=Abrir Visualiza\u00E7\u00E3o de Detalhes do Torrent
+dlg.auth.trial.success.subtitle=Gravador de DVD est\u00E1 Pronto
+ConfigView.label.show.tag.but=Exibir Bot\u00F5es das Tags
+Button.abort=Abortar
+SpeedView.stats.manual=Consertado
+MyTrackerView.completed=Completo
+ConfigView.section.interface.cleardecisions=Limpar os di\u00E1logos de decis\u00E3o lembrados
+iconBar.pstream={iconBar.stream}
+externalLogin.wait=Carregando a p\u00E1gina, por favor espere...
+ConfigView.section.Subscriptions=Subscri\u00E7\u00F5es
+TableColumn.header.eta_next=Pr\u00F3ximo ETA
+pairing.srp.pw.req=Senha necess\u00E1ria - nada vai funcionar sem isso\!
+SpeedView.stats.unknown=Desconhecido
+azbuddy.dchat.import.data=Dados de backup exportados anteriormente
+remote.pairing.functions=<A HREF\="clip">Copiar c\u00F3digo para \u00E1rea de transfer\u00EAncia</A>   |   <A HREF\="new">Obter novo c\u00F3digo</A>
+LocaleUtil.label.chooseencoding=Por favor selecione a codifica\u00E7\u00E3o mais apropriada
+wizard.information=Informa\u00E7\u00E3o
+ConfigView.section.tracker.seedretention.info=Nota\: As estat\u00EDsticas de upload ser\u00E3o perdidas para seeds n\u00E3o retidos
+CacheView.speeds.writes=Escritas
+window.updateswt.status=Status
+config.external.browser.non.pub=Sempre usar o %1 para conte\u00FAdo n\u00E3o-p\u00FAblico
+TorrentOptionsView.param.reset.to.default=Definir as op\u00E7\u00F5es de volta aos seus valores padr\u00E3o
+TableColumn.header.DownloadingRank=Rank de Downloading
+device.renderer.remove_all=Remova todos os Renderers
+torrentdownload.error.dl_fail=Falha no download '%1' para '%2'\: %3
+DHTView.transport.packets=Pacotes
+SpeedView.stats.maxUp=Velocidade M\u00E1x de Upload\:
+tps.tracker.cache=Cache de peer
+label.set=Alterar...
+splash.initializePlugins=Inicializando os Plugins 
+ConfigView.section.interface.cleardecisionsbutton=Limpar
+FilesView.dialog.priority.title=Digite prioridade num\u00E9rica
+label.no.tag=Sem Tag
+PeersView.upload=Upload
+TableColumn.header.torrent_created.info=Data em que o torrent foi criado, quando dispon\u00EDvel
+wizard.multitracker.configuration=Configura\u00E7\u00E3o do Multi-Rastreador
+StartStopRules.shareRatioMet=Propor\u00E7\u00E3o de Compartilhamento OK
+TableColumn.header.azsubs.ui.column.subs=Subscrever
+ConfigView.label.seeding.autoStart0Peers.tooltip=Marque se voc\u00EA quer que o rastreador sempre liste os seeds para torrents com 0 Peers.
+security.certcreate.intro=Este di\u00E1logo permite a voc\u00EA criar um certificado auto-assinado
+device.itunes.install_problem=Parece haver um problema com a integra\u00E7\u00E3o com o iTunes
+FilesView.md5.calculate=Calcular hash MD5(s)
+min.sr.window.message=Digite o ratio m\u00EDnimo de compartilhamento [0\:desabilitado]
+set.share.ratio.win.title=Configurar Taxa de Compartilhamento
+ConfigView.label.backupconfigfiles=Fazer backup dos arquivos de configura\u00E7\u00E3o para prop\u00F3sitos de recupera\u00E7\u00E3o
+iconBar.stop=Parar
+StartStopRules.SPratioMet=Propor\u00E7\u00E3o de S\:P OK
+ConfigView.label.checkOnSeeding=Realizar re-verifica\u00E7\u00E3o de baixo recurso de peda\u00E7os quando ficando de seed
+DiskManager.alert.movefilerecoveryfails=Erro ao recuperar ap\u00F3s uma falha de movimenta\u00E7\u00E3o\nRestaura\u00E7\u00E3o do arquivo %1 falhou, %2
+device.ms.group={device.mediaserver.view.title}
+ConfigView.label.seeding.rankType.seed=Apenas Contagem de Seeds
+Unopened.bigView.header=Novo
+ConfigView.section.sharing.rescanperiod=Per\u00EDodo de re-escaneamento (segs)
+PeerManager.status.checking=Verificando
+device.xcode=Converter
+wizard.progresstitle=Criando Arquivo Torrent
+wizard.tracker.howToLocal=\tV\u00E1 em 'Ferramentas->Op\u00E7\u00F5es->Rastreador' para ativ\u00E1-lo
+TrayWindow.menu.startalldownloads=Iniciar Todos os Downloads
+ConfigView.section.tracker.client.scrapesingleonly=Desativar agrega\u00E7\u00E3o de scrape por rastreador (pode ajudar com os rastreadores que reportam os erros de 'URL muito longa' (414) ) 
+TableColumn.header.availability.info=\# de c\u00F3pias completas sendo vistas
+ConfigView.option.dm.dblclick.launch.qv={MainWindow.menu.quick_view} / {iconBar.run}
+upnp.enable=Ativar UPnP
+wizard.createtorrent.extrahashes=Adicionar hashes para as outras redes (ex\: Gnutella2, eDonkey2000)
+stats.snapshot.group=Instant\u00E2neo
+v3.iconBar.down={iconBar.down}
+label.dont.show.again=N\u00E3o mostrar esta mensagem novamente
+azbuddy.ui.table.read_cat=Tag/Cat leitura
+ConfigView.section.connection.network.max.outstanding.connect.attempts=M\u00E1x de conex\u00F5es de longo curso destacadas
+security.certcreate.createok=Certificado criado com sucesso
+webui.mode.info=O modo pode ser\n\t"full"\t\= todas as opera\u00E7\u00F5es dispon\u00EDveis (padr\u00E3o)\n\t"view"\t\= ver apenas (mas pode atualizar a freq\u00FC\u00EAncia de atualiza\u00E7\u00E3o)
+wizard.multitracker.edit=Editar...
+azneti2phelper.install.description=Por favor, aguarde enquanto o Plugin I2P \u00E9 instalado
+PeersView.T.L.tooltip=Voc\u00EA estabeleceu a conex\u00E3o
+azmsgsync.install.subtitle=Instalando Plugin de Mensagens Sync
+webui.access.info=O acesso pode ser\n\t"local"\t\= significando que apenas a m\u00E1quina local pode conectar-se\n\t"all"\t\= acesso irrestrito (default)\n\tIP\t\= e.x. 192.168.0.2\t\t\tapenas um IP\n\tIP1-IP2\t\= e.x. 192.168.0.1-192.168.0.255\tfaixa de IP inclusiva
+MainWindow.menu.view.console.keybinding=Meta+4
+DownloadManager.error.filewithouttorrentinfo=Nenhuma informa\u00E7\u00E3o de Torrent encontrada no arquivo
+TableColumn.header.TableColumnSample=Amostra
+AlertMessageBox.warning=Alerta
+MyTrackerView.peers=Peers
+azbuddy.beta.msgsync.missing=Voc\u00EA precisa instalar o plugin 'Mensagem Sync'
+SpeedView.stats.measuredmin=M\u00EDn. medido
+label.restored=Restaurado(s)
+Plugin.localtracker.info=O descobridor de peers na LAN permite m\u00FAltiplas c\u00F3pias do Vuze atr\u00E1s de um firewall e em uma rede comum para baixar com efici\u00EAncia torrents ativando a conex\u00E3o direta entre eles
+azbuddy.dchat.decentralized.enabled={azbuddy.dchat.decentralized} Habilitado
+MainWindow.menu.file.open.torrentnodefault.keybinding.mac=Meta+Opt+O
+ConfigView.section.transfer.lan.tooltip=Configura\u00E7\u00F5es espec\u00EDficias-pra-LAN
+UpdateMonitor.messagebox.accept.unverified.title=Aceitar Instala\u00E7\u00E3o N\u00E3o-Verificada
+Formats.units.KiB=KiB
+security.certtruster.prompt=Voc\u00EA quer confiar nela?
+GeneralView.label.distributedCopies=C\u00F3pias Distribu\u00EDdas\:
+label.socks=SOCKS
+ConfigView.section.torrent.decoding=Decodificar as Defini\u00E7\u00F5es de Caracteres
+MainWindow.menu.file.open=&Abrir
+MainWindow.menu.speed_limits.schedule.err=Os seguintes erros foram relatados, por favor, re-editar para corrigir\!
+v3.MainWindow.menu.getting_started=&Sendo Iniciado
+dlg.auth.success.line2=Voc\u00EA agora \u00E9 capaz de gravar DVDs ilimitadas jog\u00E1veis, digitalizar seus arquivos em busca de v\u00EDrus e transmitir v\u00EDdeos que voc\u00EA est\u00E1 baixando - todos, sem an\u00FAncios\!
+ConfigView.section.interface.resetassocbutton=Redefinir
+dlg.auth.success.line1=Obrigado por fazer o upgrade para Vuze Plus.
+TableColumn.header.peakup.info=Up M\u00E1x. Alcan\u00E7ado
+DHTView.title.fullcvs=CVS da Base de Dados Distribu\u00EDda
+webui.rootdir=Diret\u00F3rio Raiz (*)
+wizard.multitracker.noannounce=A URL de an\u00FAncio n\u00E3o est\u00E1 presente em sua lista de rastreadores
+Button.add.tooltip=Adic. um torrent \u00E0 sua biblioteca
+ConfigView.label.start.inlrm=Iniciar no modo econ\u00F4mico (UI desativada, limitando a rede e o uso de mem\u00F3ria etc)
+PeersView.statup=Estat\u00EDsticas do Upload
+ConfigView.section.queue.seeding=Ficar de Seed
+ConsoleView.title.short=Console 
+subs.prop.num_read=N\u00FAmero dos resultados de leitura
+ConfigView.label.save_list.max_entries=Salvar tamanho do hist\u00F3rico de localiza\u00E7\u00E3o
+ManagerItem.finishing=Terminando
+network.admin.bind.enforce.fail='Impor liga\u00E7\u00F5es IP' est\u00E1 selecionado , mas n\u00E3o liga\u00E7\u00F5es foram especificados\n\nVeja Ferramentas->Op\u00E7\u00F5es->Conex\u00E3o->Configura\u00E7\u00F5es Avan\u00E7adas de Rede
+v3.MainWindow.menu.view.sidebar.keybinding=F7
+TableColumn.header.filesdone=Arquivos Feitos
+uninstallPluginsWizard.title=Desinstalar Plugins
+MainWindow.menu.help.whatsnew=O que h\u00E1 de novo?
+DHTView.operations.data=Dados
+wizard.newtorrent.byo.addcontainer.title=Adic. Container
+StartStopRules.numSeedsMet=\# Seeds OK
+config.internal.browser.proxy.select=Proxy do Navegador
+TableColumn.header.torrent_created=Criado Torrent em
+openTorrentWindow.mb.alreadyExists.merge=Voc\u00EA deseja adicionar trackers adicionais de um novo download \u00E0 um j\u00E1 existente?
+dlg.stream.plus.title={Button.upgrade}
+ConfigView.section.tracker.createcert=Criar certificado auto-assinado
+UIDebugGenerator.complete.text=Por favor envie o arquivo '%1' para az-bugreports at azureus-inc.com\n\nClique em Ok para abrir uma janela para este arquivo.
+bencode.file.browse=Abrir arquivo BEencoded
+subscriptions.overview=Resumo assinaturas
+ConfigView.dialog.choosedefaultsavepath=Por favor, escolha o diret\u00F3rio padr\u00E3o para salvar
+v3.MainWindow.menu.showActionBarText=Mostrar o Texto
+azbuddy.dchat.ftux.footer=Qualquer uso do Vuze\u00AE ou Vuze+\u2122 que viole direitos autoriais de qualquer pessoa ou entidade n\u00E3o \u00E9 permitido.
+TableColumn.header.chat.user.count.info=N\u00FAmero estimado de usu\u00E1rios online (excluindo voc\u00EA)
+FilesView.hide.dnd=Ocultar arquivos n\u00E3o selecionado para download
+subscriptions.listwindow.popularity.unknown=Desconhecido
+MyTorrentsView.menu.edit_comment.enter.message=Inserir um coment\u00E1rio para este download.
+ConfigView.label.autoopen.downloadbars=Auto-abrir as Barras de Download quando
+pairing.ui.icon.show=Mostrar \u00CDcone
+MainWindow.menu.closealldownloadbars=Fechar Todas as &Barras de Download
+network.bindError=Falhou em prender o socket do servidor como nenhum dos endere\u00E7os compat\u00EDveis est\u00E3o dispon\u00EDveis, por favor verifique suas configura\u00E7\u00F5es de prender-ao-IP.
+Plugin.localtracker.networks.info=Considere as seguintes redes serem locais [';' redes separadas, ex\: 145.227.*.*]
+network.check.ipbinding=Checar enderen\u00E7o/interfaces de IP ao iniciar
+label.various=V\u00E1rios
+TableColumn.header.ProgressETA.info=Combina as colunas de Status, Completamento, TEC e Velocidade de Download em uma coluna multi-alinhada.
+configureWizard.transfer.maxDownloads=M\u00E1ximo de Downloads 
+wizard.browse=Navegar... 
+GeneralView.title.short=Geral 
+FileItem.storage.linear=Linear
+configureWizard.nat.ok=OK\! 
+TrackerAvail.column.seeds.info={Trackers.column.seeds.info}
+Button.back=Voltar
+dhttracker.tracklimitedwhenonline=Contudo, realize rastreamento de baixo recurso quando online para cruzamento da popula\u00E7\u00E3o na multid\u00E3o
+ConfigView.section.security.publickey=Chave p\u00FAblica
+MainWindow.menu.transfers.resumetransfers=&Resumir
+ConfigView.label.playdownloadfinished=Tocar um som quando um download est\u00E1 terminado
+FileItem.read=leitura
+TableColumn.header.commenticon.info=Exibe o \u00EDcone se o download tem um coment\u00E1rio definido-pelo-usu\u00E1rio
+splash.loadingTorrent=Carregando Torrent
+GenericText.column=coluna
+OpenTorrentWindow.tlf.remove=Remover pasta de n\u00EDvel superior
+ConfigView.section.ipfilter.enable=Ativar
+MyTorrentsView.menu.setCategory.add=&Adicionar Categoria...
+popup.closing.in=Auto-fechando a janela em %1 segundos
+MagnetPlugin.private_torrent=<torrent privado>
+pairing.status.disabled=Desabilitado
+torrent.fix.corrupt.result.nothing=O torrent parece ser v\u00E1lido\!
+TableColumn.header.AzProduct.info=Rede de Conte\u00FAdo da qual o torrent se originou
+plugins.basicview.status=Status\:
+label.test.internet=Testar sua conex\u00E3o com a internet
+azbuddy.ui.table.msg_queued=Na Fila
+mdi.entry.dvdburn=Gravar DVD
+configureWizard.nat.sharePort=Usar uma \u00FAnica porta de entrada compartilhada para todos os torrents
+FilesView.pieces=Peda\u00E7os
+ManagerItem.paused=Pausado
+MainWindow.menu.view.irc=&IRC
+PiecesView.\#=\# 
+DonationWindow.noload.text=A janela de doa\u00E7\u00E3o n\u00E3o conseguiu carregar. Por favor, tente novamente mais tarde.
+MainWindow.sr.status.tooltip.ok=Taxa de Compartilhamento %1 OK
+Torrent.create.progress.cancelled=Opera\u00E7\u00E3o cancelada
+ConfigView.label.subdir_is_in_default=Quando considerando se os downloads existem em um diret\u00F3rio padr\u00E3o, tamb\u00E9m considerar os sub-diret\u00F3rios
+window.uiswitcher.ClassicUI.title=Interface Cl\u00E1ssica
+ConfigView.section.style.showProgramIcon=Mostrar o \u00EDcone do programa no nome da coluna
+MainWindow.menu.file.open.vuze=Arquivo do Vuze...
+ConfigView.section.queue.downloading={ManagerItem.downloading}
+TableColumn.header.tags={label.tags}
+MagnetPlugin.use.md.download.delay=\tatraso [segs]
+ConfigView.label.stopAfterMinutes=Uma vez trocado para ficar de seed, parar ap\u00F3s uma dura\u00E7\u00E3o de tempo
+dht.execute=Executar
+PiecesView.size=Tamanho
+# Will be used for {library.name} in classic view
+library.name._classic=Meus Torrents
+MainWindow.dialog.exitconfirmation.title=Sair do Vuze?
+device.wiki=Dicas na Wiki...
+v3.MainWindow.menu.view.searchbar=Barra de Busca
+Trackers.column.type=Tipo
+OpenTorrentFile.column.name={TableColumn.header.name}
+core.not.available=Vuze ainda est\u00E1 iniciando, por favor tente novamente quando estiver completadostill initialising, please try again when it has completed
+GeneralView.label.trackerscrapeupdate=Limpar Rastreador
+ConfigView.section.pluginslist=Lista\t 
+PeersGraphicView.title.full=Multid\u00E3o
+MyTrackerView.badnat=NAT Ruim
+iconBar.host.tooltip=Hospedeiro
+Column.seedspeers.started.noscrape=%1
+v3.MainWindow.menu.library=&Biblioteca
+Peers.column.Protocol=Protocolo
+CacheView.speeds.title=Taxa de Dados
+TagSettingsView.title=Configura\u00E7\u00F5es
+window.uiswitcher.NewUI.text=* Recomendado para todos os usu\u00E1rios.\n\n* Interface f\u00E1cil, intuitiva.\n* Rica em recursos e configura\u00E7\u00F5es.
+StartStopRules.FP0Peers=FP / 0 Peers
+SubscriptionWizard.column.SubWizRank={subscriptions.column.SubWizRank}
+Plugin.localtracker.networks=Redes locais
+PeerManager.status.error=Erro
+installPluginsWizard.file.file=Arquivo \:
+PeersView.S.info=Desprezado\: Um peer pode ser "desprezado" manualmente ou automaticamente (por n\u00E3o entregar os dados a uma taxa alta o bastante)
+Scrape.status.scraping.queued=Scraping na fila...
+ConfigView.section.style.extendedErase=Desenhe linhas de grade e preencher \u00E1reas em branco
+progress.window.msg.progress=Por favor espere enquanto a opera\u00E7\u00E3o completa
+MainWindow.menu.advanced_tools=Avan\u00E7ado
+wizard.newtorrent.byo.addcontainer.text=Digite o nome do cont\u00EAiner como aparece no torrent
+quick.view.scheduled.text=O arquivo selecionado foi priorizado e ser\u00E1 auto-aberto para visualiza\u00E7\u00E3o quando completo.
+DHTView.general.reachable=Alcan\u00E7\u00E1vel\:
+MyTorrentsView.menu.setSpeed.unlimit=Sem limite
+IPChecker.external.addressextracted=Endere\u00E7o IP extra\u00EDdo
+ConfigView.label.seeding.ignoreShareRatio=Ignorar torrents que tenham uma propor\u00E7\u00E3o de compartilhamento de
+TorrentOptionsView.param.reset.stats=Resetar est\u00E1tisticas de transfer\u00EAncia de torrent para zero
+azbuddy.dchat.status.noplugin=Erro\: Plugin Mensagem Sync n\u00E3o instalado
+Peers.column.DLedFromOthers=De Outros
+TableColumn.header.archive.date=Data do Arquivo
+tag.type.ds.comp={label.complete}
+ConfigView.section.interface.cleartrackersbutton=Limpar
+ConfigView.section.tracker.announcescrapepercentage=Intervalo do scrape com % da idade do an\u00FAncio\nex\: 200 \= 2\:1. 0 \= deixar o peer decidir
+ConfigView.tb.delete.content=Apagar sem perguntar
+MySharesView.menu.remove=Remover
+DHTView.operations.title=Detalhes da Opera\u00E7\u00E3o
+ConfigView.section.ipfilter=Filtros de IP
+DHTView.activity.status.true=Requisitado
+azbuddy.nickname=Seu Apelido
+ConfigView.section.tracker.udpversion=Vers\u00E3o do Protocolo UDP (1 ou 2)
+ConfigView.section.file.friendly.hashchecking=Verifica\u00E7\u00E3o de hash amig\u00E1vel
+ConfigView.section.style.doNotUseGB=N\u00E3o usar a unidade GB
+installPluginsWizard.list.loaded=Por favor, escolha os plugins que voc\u00EA quer instalar.
+Security.jar.tools_not_found=Assinatura JAR falhou - 'tools.jar' n\u00E3o encontrado em %1. Veja Ferramentas->Op\u00E7\u00F5es->Seguran\u00E7a para detalhes.
+upnp.alert.mappingok=UPnP\: Mapeamento '%1' estabelecido
+TableColumn.header.file_eta.info=Tempo estimado at\u00E9 o arquivo esteja baixado completamente
+configureWizard.nat.ko=Erro do NAT
+Button.goLibrary=Ir para {library.name}
+ManagerItem.high=alta
+TrackerAvail.column.type={Trackers.column.type}
+menu.bencode.to.json=Converter BEncoded Para JSON...
+ConfigView.section.tracker.client.exclude_lan=Excluir transfer\u00EAncias em LAN das est\u00E1tisticas
+stats.longterm.group=Longo-Termo
+upnp.alert.mappinggrabbed=UPnP\: Mapeamento '%1' estabelecido - obtido de '%2'
+tag.constraints.info=Veja em <A HREF\="https\://wiki.vuze.com/w/Tags\#Constraints">Restri\u00E7\u00F5es Tag</A> p\u00E1gina da wiki
+download.removerules.unauthorised.info=Torrents n\u00E3o-autorizados s\u00E3o aqueles nos quais a resposta ao an\u00FAncio cont\u00E9m "n\u00E3o-autorizado" ou "desautorizado" na "falha na resposta"
+MainWindow.menu.transfers.resumetransfers.keybinding=Meta+R
+ConfigView.text.ignoreRule=Ignorar Regra
+ConfigView.section.sharing.torrentcomment=Coment\u00E1rio para torrents gerados
+ConfigView.label.checkonstart=Procurar pela \u00FAltima vers\u00E3o quando o Vuze iniciar
+MyTorrentsView.menu.explore._mac=Mostrar no Descobridor
+#connected to more seeds/peers than tracker reports
+library.all.header.p=%1 items\: %2 ativo
+ConfigView.section.tracker.passwordenabletorrent.info=Requer cliente BitTorrent adequado (ex\: Vuze)
+br.restore.info=Restaurar a configura\u00E7\u00E3o de um backup
+MyTorrentsView.menu.downSpeedLimit=Limite de Velocidade de Download
+ConfigView.label.maxdownloads=M\u00E1ximo de downloads simult\u00E2neos [0\: ilimitados]\n - N\u00E3o pode ser maior do que o n\u00FAmero m\u00E1x. de torrents ativos
+UpdateMonitor.messagebox.restart.title=Atualiza\u00E7\u00E3o do Software
+MyTorrentsView.menu.moreColHidden=(%1 Escondidos...)
+dlg.auth.cancelled=C\u00F3digo de Ativa\u00E7\u00E3o Cancelado
+MyTrackerView.status.stopped=Parado
+wizard.close.confirmation=Confirma\u00E7\u00E3o
+azbuddy.dchat.copy.rss.url=URL RSS
+FilesView.menu.setpriority.numeric=Num\u00E9rico...
+ConfigView.section.transfer.autospeed.tooltip=Configura\u00E7\u00F5es espec\u00EDficas da Auto-velocidade
+subscriptions.listwindow.loadingtext=Procurando subscri\u00E7\u00F5es relacionadas com %1
+tag.type.ds.seed={ManagerItem.seeding}
+ArchivedFilesView.size={FilesView.size}
+UI.cannot_submit_blank_text=Voc\u00EA deve inserir um valor.
+updater.cant.write.to.app.title=N\u00E3o P\u00F4de Escrever na Pasta do Aplicativo
+OpenTorrentWindow.addFiles.Folder=Adicionar &Pasta
+TagGroupWindow.title=Configurar Tag do Grupo
+webui.bindip=Prender IP - normalmente n\u00E3o requerido (*)
+max.sr.window.title=Taxa de Compartilhamento Alvo
+PeerFilesView.title.short={FilesView.title.short}
+azbuddy.dchat.auto.mute=Mudo para Novos Usu\u00E1rios
+PeersView.I2.info=O peer est\u00E1 interessado no que voc\u00EA tem?
+pairing.local.ipv6=Endere\u00E7o IPv6 local
+archive.info.title=Downloads Arquivados
+pairing.local.ipv4=Endere\u00E7o IPv4 local
+MainWindow.upgrade.tooltip.progressbar=O progresso do download \u00E9 mostrado aqui
+MyTorrentsView.dialog.setNumber.download=download
+ConfigView.label.startminimized=Iniciar minimizado 
+TableColumn.header.upspeed=Velocidade de Up
+iconBar.new.tooltip=Criar um torrent
+cat.options=Op\u00E7\u00F5es/Info dos Torrents Atuais...
+ActivityView.legend.trimmed=Arrumado (pontuado)
+SpeedTestWizard.set.upload.label=Limite da Velocidade de Upload\:
+v3.MainWindow.text.my.profile=Perfil
+ConfigView.label.seeding.rankType.peerSeed.options=Op\u00E7\u00F5es da Propor\u00E7\u00E3o dos Peers\:Seeds
+TableColumn.header.date_added.info=Data que o torrent foi adicionado
+pairing.status.noservices=Nenhum servi\u00E7o remoto habilitado
+UpdateWindow.columns.currentversion={label.current}
+ConfigView.section.ipfilter.enablebanning=Bloquear peers que consistentemente mandam dados ruins
+PiecesView.BlockView.Have=Tem
+ConfigView.label.maxactivetorrents=M\u00E1ximo de torrents ativos [0\: ilimitados]\n - Novos torrents n\u00E3o come\u00E7ar\u00E3o se voc\u00EA estiver baixando/ou ficando mais de seed
+MyTorrentsView.menu.edit_comment=Editar Coment\u00E1rio
+TableColumn.header.TorrentStream={iconBar.stream}
+PiecesView.availability=Disponibilidade
+MySharesView.type.file=Arquivo
+TableColumn.header.status.info=O que o torrent est\u00E1 fazendo
+v3.topbar.menu.show.search=Busca
+pairing.group.explicit=Atributos expl\u00EDcitos
+TableColumn.header.secondsdownloading.info=Quantia de tempo que voc\u00EA esteve baixando.
+MainWindow.upgrade.step2=Passo 2\: Fechar esta vers\u00E3o e reiniciar a nova vers\u00E3o do Vuze
+label.original.file=Arquivo Original
+MainWindow.upgrade.step1=Passo 1\: Baixar a nova vers\u00E3o 
+ConfigView.section.tracker.natcheckenable=Verifica a conectividade da 'porta de entrada de dados' e reporta as falhas para os peers
+GeneralView.label.maxuploadspeed=Limite de Up
+ConfigView.label.maxdownloadspeed=Velocidade m\u00E1xima global de download em KB/s [0\: ilimitada]
+rss.internal.test.url=Clique para ver a p\u00E1gina inicial local
+window.networkselection.title=Sele\u00E7\u00E3o de Rede
+label.set.share.ratio={set.share.ratio.win.title}...
+PeersView.BlockView.Avail.Have=Ambos tem
+device.error.copytonowrite='Copiar Para Pasta' "%1" N\u00E3o \u00E9 permitida escrita
+ConfigureWizard.language.choose=Escolha um idioma da lista abaixo\:
+SpeedTestWizard.finish.panel.click.close=Voc\u00EA fechou o assitente do teste de velocidade. Clique em fechar para sair.
+MainWindow.menu.quick_view=Exibi\u00E7\u00E3o R\u00E1pida
+MagnetPlugin.contextmenu.exporturi=Copiar a URI do Magnet para a \u00C1rea de Transfer\u00EAncia
+devices.choose.device.title=Selecione um dispositivo de reprodu\u00E7\u00E3o do video\:
+MainWindow.menu.file.open.torrentnodefault=Arquivo Torrent... (Sem Save Padr\u00E3o)
+MyTrackerView.seeds=Seeds
+ColumnSetup.filters=Filtros
+MainWindow.nat.status.ok=NAT OK
+Security.keystore.empty=O keystore est\u00E1 vazio. Por favor, crie um certificado auto-assinado (veja Ferramentas->Op\u00E7\u00F5es->Seguran\u00E7a) ou importe um certificado existente para '%1'
+CategoryAddWindow.message=Insira um novo nome de categoria
+GeneralView.label.private=Torrent Privado\:
+ConfigView.unlimited=Ilimitado
+ConfigView.section.connection.advanced.SO_SNDBUF.tooltip=Define o valor do socket padr\u00E3o SO_SNDBUF (em bytes), i.e. o tamanho da janela de envio TCP.\nO Vuze deixa isto n\u00E3o definido por padr\u00E3o, siginificando que os padr\u00F5es para o SO b\u00E1sico s\u00E3o usados.\nNOTA\: O linux dobra o valor dado.
+iconBar.stop.tooltip=Interromper
+dht.reseed=Ficar de seed de novo
+restart.error.fnf='%1' n\u00E3o encontrado em '%2'
+v3.MainWindow.button.preview=Pr\u00E9-visualiza\u00E7\u00E3o
+AutoMigration.useralert=Arquivos da configura\u00E7\u00E3o do usu\u00E1rio do Vuze/resultados da auto-migra\u00E7\u00E3o dos diret\u00F3rios\:\n\n%1\nQuaisquer falhas devem ser migradas manualmente.\nN\u00C3O SE ESQUE\u00C7A DE ATUALIZAR OS CAMINHOS PARA SALVAR NA SUA CONFIGURA\u00C7\u00C3O SE ELES FORAM MIGRADOS\!
+statusbar.feedback=Enviar Feedback   
+v3.menu.device.exploreTranscodes._mac=Mostrar arquivos no Finder
+label.shared=Compartilhado
+LoggerView.includeOnly=S\u00F3 exibir linhas combinando esta express\u00E3o regular\:
+plus.notificaiton.ExpiringEntry.s=Sua assinatura Vuze Plus ir\u00E1 expirar em %1 dia\: <A %2>Renove Agora</A>
+device.router.configure=Configurar UPnP
+plus.notificaiton.ExpiringEntry.p=Sua assinatura Vuze Plus ir\u00E1 expirar em %1 dias\: <A %2>Renove Agora</A>
+ConfigView.label.popupfilefinished=Mostrar um alerta quando um arquivo estiver conclu\u00EDdo
+ConfigView.section.tracker.server=Servidor
+v3.activity.header.vuze.news=Not\u00EDcias do Vuze
+metasearch.addtemplate.title=Instalar o Modelo de Busca?
+plugin.aznetstatus.logfull=Registro Completo
+dht.ipfilter.log=Registrar as viola\u00E7\u00F5es do Filtro de IP
+stream.analysing.media.preview=Analisando M\u00EDdia (Modo de Visualiza\u00E7\u00E3o)
+Scrape.status.nextScrapeAt=Pr\u00F3xima scrape em %1
+Scrape.status.error=Erro de Scrape\:
+SystemTray.tooltip.seeding=%1 ficando de seed, 
+TableColumn.TorrentStream.tooltip.disabled=Executar Agora n\u00E3o suporta arquivos desse tipo
+webui.passwordenable=Ativar senha
+updater.progress.window.info=Pressione 'Abortar' para terminar todas tarefas pendentes
+TableColumn.header.tag.discovery.addedon=Encontrado em
+pairing.enable=Ativar o emparelhamento do Vuze e aplica\u00E7\u00F5es/interfaces remotas
+fileDownloadWindow.title=Vuze \u2013 Baixador de Torrents
+MainWindow.upgrade.explanation=Este assistente baixar\u00E1 a nova vers\u00E3o na sua pasta do Vuze e reiniciar\u00E1 o Vuze
+br.restore.folder.info=Selecione a pasta que cont\u00E9m um backup anterior
+update.fail.app.changed=Vuze precisa ser atualizado, mas o processo n\u00E3o pode ser executado automaticamente como o nome do aplicativo foi alterado para '%1'.\n\nPor favor, v\u00E1 para http\://www.vuze.com/ e baixar o instalador mais recente.
+jvm.max.direct.mem=Tamanho da mem\u00F3ria direta M\u00E1xima [branco\=padr\u00E3o,min\=%1]
+Scrape.status.error.invalid=Reposta inv\u00E1lida.
+wizard.close=Fechar
+device.config.ms.maxlines=M\u00E1ximo de entradas a serem exibidas quando navegador no servidor de m\u00EDdia
+azbuddy.dchat.not.installed=Suporte para bate-papo an\u00F4nimo n\u00E3o est\u00E1 instalado
+ConfigView.label.ui_switcher_button=Mostrar
+ConfigView.label.lh.prog=Aplicativo
+FilesView.title.short=Arquivos
+jvm.options.summary=S\u00FAmario das atuais op\u00E7\u00F5es explicitas\:
+restart.error.denied=O acesso foi negado quando tentando executar '%1'.  Tenha certeza de que voc\u00EA tem os direitos para rodar este programa.
+iconBar.open=Adicionar Torrent
+ConfigView.label.minPeersToBoostNoSeeds.tooltip=Quaisquer torrents sem seeds e tendo menos peers do que voc\u00EA especificar\nir\u00E3o para o final da fila.
+devices.od.view.heading=Downloads agendados para download off-line
+ConfigView.section.transfer.autospeed.network.info=Os limites acima s\u00E3o normalmente calculados automaticamente durante o download ou s\u00E3o o resultado de um teste de velocidade. Se voc\u00EA quer especific\u00E1-los manualmente use a op\u00E7\u00E3o abaixo.\nTodos os limites al\u00E9m dos 'consertados' ser\u00E3o subsequencialmente ajustados se necess\u00E1rio. \nInsira o valor e ent\u00E3o selecione seu tipo. Note que as velocidades est\u00E3o em %1.
+sharing.progress.cancel=Cancelar
+label.indirect.connect=Conex\u00E3o Indireta
+MagnetURLHandler.report.no_sources=nenhuma(s) fonte(s) achada(s) para o torrent
+Button.done=Feito
+dht.reseed.port=Porta
+MyTorrentsView.menu.movetorrent=Mover Arquivo Torrent...
+v3.MainWindow.menu.contentnetworks.about=Sobre as Redes HD
+AdvRenameWindow.title=Renomear Download
+wizard.maketorrents.superseed=Usar super-seeding
+MainWindow.menu.view.stats.keybinding=Meta+5
+SystemTray.tooltip.downloading=%1 baixando, 
+importTorrentWizard.process.importfail.title=Falha na Importa\u00E7\u00E3o do Torrent 
+device.config.autohide.old.devices=Auto-ocultar dispositivos que n\u00E3o foram vistos recetemente [dias, 0\: desabilitado]
+custom.settings.import.res.title=Importa\u00E7\u00E3o da configura\u00E7\u00E3o completa
+ConfigView.label.userequestlimiting.tooltip=Limitar Pedidos n\u00E3o \u00E9 t\u00E3o leve como as leituras atrasadas, mas permite a prioriza\u00E7\u00E3o do download baseado no posi\u00E7\u00E3o da fila do download e poderia melhorar a performance da rede
+CacheView.writes.toCache=Para o Cache
+SpeedTestWizard.abort.message.download.added=Download %1 adicionado durante o teste
+OpenTorrentFile.column.download.info=Baixar arquivo do interior do torrent\nUsar barra de espa\u00E7o para alternar para o modo de m\u00FAltipla sele\u00E7\u00E3o
+TableColumn.header.chat.status={TableColumn.header.status}
+DownloadActivityView.legend.down_smooth=Baixando (Suave)
+proxy.info.title=Info do Proxy
+MyTorrentsView.menu.recheck=For\u00E7ar Re-chec&agem
+UpdateProperty.title=Propriedade da Atualiza\u00E7\u00E3o
+TableColumn.header.swarm_average_speed.info=A velocidade m\u00E9dia dos peers na multid\u00E3o
+PeerSocket.unknown_shadow_style=Desconhecido %1 %2
+Button.createNewSubscription=Criar Nova Subscri\u00E7\u00E3o
+MagnetPlugin.use.lookup.service=Use o servi\u00E7o de pesquisa Vuze secund\u00E1rio se pesquisa magnet se via DHT falhar
+mb.azmustclose.title=Erro de Inicializa\u00E7\u00E3o
+ConfigView.label.maxseedspertorrent=M\u00E1x. de seeds por torrent padr\u00E3o [0\: ilimitados] 
+MyTorrentsView.menu.thisColumn.remove=Remover Coluna
+download.removerules.name=Regras de Remo\u00E7\u00E3o
+label.rss=RSS
+PeerManager.status.offline=Erro de Conex\u00E3o 
+br.backup.progress=Backup/Restaurar Resultados
+v3.MainWindow.search.tooltip=Digite os termos da sua pesquisa, link magn\u00E9tico, URL hash ou torrent e tecle enter\!
+azbuddy.dchat.ui.max.lines=M\u00E1ximo de mensagens por janela de bate-papo
+menu.min.share.ratio2=Configurar Ratio M\u00EDnimo...
+TagStatsView.title.full=Atividade das Tag
+config.changes.title=Mudan\u00E7as nas Configura\u00E7\u00F5es
+TableColumn.header.savepath=Caminho para Salvar
+GeneralView.label.uploadspeed=Velocidade de Upload \:
+MyTorrentsView.menu.networks=Redes
+ConfigView.label.watchtorrentfolderinterval=Intervalo
+Button.install={swt.install.window.ok}
+ConfigView.section.connection.group.http.info=Suporte para seeding HTTP.
+ConfigView.label.opendialog=Abrir automaticamente o Assistente de Atualiza\u00E7\u00E3o quando uma atualiza\u00E7\u00E3o estiver dispon\u00EDvel
+device.lastseen=Visto pela \u00FAltima vez
+TableColumn.header.networks=Redes
+azbuddy.ui.add=Adicionar
+GeneralView.label.hashfails=Falhas no Hash \:
+azbuddy.dchat.share.fail.msg=Falha ao compartilhar %1\:\\n\\n%2
+ConfigView.pluginlist.shared=compartilhado
+ConfigView.section.security.restorekeys.button=Restaurar
+TableColumn.header.activityNew=Novo
+ColumnSetup.proficiency=Profici\u00EAncia\:
+FilesView.skip.confirm.delete.text=Cortar o arquivo '%1' para salvar espa\u00E7o?
+ConfigView.section.style.separateProtDataStats=Mostrar dados separados e estat\u00EDsticas do protocolo como '(protocolo) de dados'
+configureWizard.welcome.usermodes=Esta configura\u00E7\u00E3o de profici\u00EAncia do usu\u00E1rio determinar\u00E1 o n\u00EDvel das op\u00E7\u00F5es exibidas em Ferramentas > Op\u00E7\u00F5es. \u00C9 do seu melhor interesse defin\u00ED-la apropriadamente.
+plugin.install.class_version_error=Este plugin requer uma vers\u00E3o mais nova do Java para rodar.
+configureWizard.welcome.message=Este assistente ajudar\u00E1 voc\u00EA a configurar o Vuze para o uso mais comum. Voc\u00EA pode modificar a configura\u00E7\u00E3o em profundidade usando o menu Ferramentas->Op\u00E7\u00F5es. 
+window.update.noupdates.beta.text=N\u00E3o h\u00E1 atualiza\u00E7\u00F5es dispon\u00EDveis para voc\u00EA.\n\nVoc\u00EA est\u00E1 usando a \u00FAltima vers\u00E3o beta disponibilizada (%1)\n\nVisite <a href\="http\://dev.vuze.com/">Beta Program site</a> para mais informa\u00E7\u00F5es sobre as vers\u00F5es est\u00E1veis e n\u00E3o estav\u00E9is do programa.
+security.crypto.persist_for.week=1 semana
+MainWindow.nat.status.probok=NAT OK?
+azbuddy.dchat.open.i2p.magnet=Abrir Magnet s\u00F3 de I2P No Vuze
+ConfigView.section.connection.advanced.read_select_min=Ler a espera m\u00EDnima selecionada (milis, padr\u00E3o %1)
+SpeedTestWizard.abort.message.entered.error=Teste de download entrou em estado de erro '%1'
+TableColumn.header.mergeddata.info=Quantidade de dados incorporada a este download via fus\u00E3o da multid\u00E3o
+devices.state=Estado
+speedtest.wizard.test.mode.up=upload
+Formats.units.alot=Muito \!\!\!
+CacheView.reads.amount=Quantidade
+ConfigView.section.style.ShowTagButtons.CompOnly=Somente exibir na se\u00E7\u00E3o Completo da Biblioteca
+ConfigTransferAutoSpeed.add.comment.to.log.group=Adicionar coment\u00E1rio ao log de debug
+OpenTorrentTorrent.column.\#=\#
+TableColumn.header.peers.info=\# peers conectados a (\# peers no total)
+Button.next=Pr\u00F3ximo
+azbuddy.dchat.custom=Canais personalizados
+ColumnProgressETA.showSpeed=Exibir Velocidade
+Torrent.create.progress.piecelength=Comprimento do peda\u00E7o\: 
+dialog.uiswitcher.restart.text=O Vuze precisa reiniciar para trocar para o modo da nova Interface do Usu\u00E1rio.
+label.favorites=Favoritos
+v3.iconBar.down.tooltip=Mover pra Baixo\nSegure o bot\u00E3o do mouse para mover para o fundo
+devices.xcode.autoCopy.device=Copiar automaticamente para o Dispositivo
+beta.wizard.forum=Use os f\u00F3runs do Vuze a dar feedback e relat\u00F3rio de erros
+label.replace=Substituir
+MainWindow.menu.help=&Ajuda
+TableColumn.header.tag.downrate={TableColumn.header.downspeed}
+ConfigView.section.stats.xslfiledetails=Isto ser\u00E1 inclu\u00EDdo no cabe\u00E7alho do arquivo de estat\u00EDsticas via tag <?xml-stylesheet>
+window.updateswt.status.downloading=Baixando a \u00DAltima Vers\u00E3o da SWT
+remote.pairing.subtitle=Vuze remoto lhe d\u00E1 o poder de controlar Vuze a partir de qualquer computador, navegador m\u00F3vel ou dispositivo Android.
+ConfigView.label.importdirectory=Diret\u00F3rio de Importa\u00E7\u00E3o
+DownloadManager.error.fileempty=Arquivo torrent est\u00E1 vazio
+MainWindow.menu.community.blog=Blog do &Vuze
+devices.xcode.setcopyto.title=Escolha copiar para localiza\u00E7\u00E3o
+TableColumn.header.md5.info=Hash MD5 para o arquivo (deve ser totalmente transferido; clique para calcular)
+TableColumn.header.name=Nome
+library.launch.web.in.browser=Substituir isto para downloads que cont\u00E9m um site e abrir no navegador
+ConfigView.label.showpopuponclose=Mostrar janela de confirma\u00E7\u00E3o quando parar de ficar de seed com uma propor\u00E7\u00E3o de compartilhamento menor que 1
+PeerManager.status.ps_disabled=A fonte peer do rastreador est\u00E1 desativada
+MainWindow.menu.view.stats=&Estat\u00EDsticas
+wizard.multitracker.edit.text.msg=Digite um trackerr por linha. Separar diferentes grupos (camadas) com uma linha em branco.
+ConfigView.higher.mode.available=Mais op\u00E7\u00F5es est\u00E3o dispon\u00EDveis em modos de usu\u00E1rios mais altos
+PeersView.download.info=O total baixado por voc\u00EA do peer
+seedmore.title=O Torrent n\u00E3o est\u00E1 com seeds o bastante
+ConfigTransferAutoSpeed.algorithm.selector=Seletor de Auto-Velocidade
+MyTorrentsView.menu.thisColumn.sort=&Ordenar
+window.uiswitcher.NewUI.title=Vuze
+ConfigView.section.mode.beginner.text1=Tudo que voc\u00EA precusa para baixar torrents - grande para novos usu\u00E1rios aprenderem sobre o cliente e os torrents
+Menu.show.torrent.menu=Mostrar o menu Torrents
+xfs.allocation.xfs_io.not.found=A aloca\u00E7\u00E3o do arquivo XFS falhou porque /usr/sbin/xfs_io n\u00E3o p\u00F4de ser executado. Tenha certeza de que est\u00E1 apropriadamente instalado no seu sistema. O erro original foi \: "%1".
+SpeedTestWizard.stage.message.starting=iniciando o teste...
+MyTorrentsView.dialog.setFilter.text=A se\u00E7\u00E3o %1 ser\u00E1 filtrada pelo texto que voc\u00EA especificar abaixo.  Usar o | s\u00EDmbolo (cano) para filtrar m\u00FAltiplas frases. 
+subscriptions.listwindow.name=Nome
+SystemTray.menu.pausetransfers=Pausar Transfer\u00EAncias
+openUrl.url=URL\: 
+sr_prog.window.title=Intervalo do Progresso
+wizard.newtorrent.byo.info=Soltar uma sele\u00E7\u00E3o de arquivos e/ou diret\u00F3rios para a \u00E1rea abaixo para construir um torrent. D\u00EA um duplo clique ou F2 para editar nomes.
+label.rename=Renomear %1
+MainWindow.menu.view.configuration=&Op\u00E7\u00F5es...
+Button.bar.edit=Editar
+label.public.short=P
+MainWindow.dht.status.failed=O DHT Falhou
+ConfigView.label.defaultsavepath=Salvar no diret\u00F3rio de dados padr\u00E3o
+OpenTorrentWindow.mb.notValid.title=Abrir Torrent
+label.script.to.run=Script \u00E0 executar
+DiskManager.alert.movefilefails=Erro ao mover arquivos completos\nA movimenta\u00E7\u00E3o do arquivo %1 falhou, %2
+label.public={subs.prop.is_public}
+ConfigView.label.dm.dblclick=D\u00EA um duplo clique em Exibir torrents\:
+Utils.link.visit=Por favor visite
+device.od.space=Espa\u00E7o dispon\u00EDvel
+FilesView.crc32.calculate=Calcule o CRC-32 Checksum (s)
+ConfigView.label.stop.QuitVuze=Desligar Vuze
+label.untagged=Sem Tags
+installPluginsWizard.list.version=Vers\u00E3o
+ConfigView.section.tracker.username=Nome de usu\u00E1rio
+ConfigView.section.ipfilter.autoload.info=Suporta DAT (eMule), P2P (PeerGuardian, splist), e P2B v1,2,3 formatos do (PeerGuardian 2).  O arquivo pode ser local ou URL, zip'd, gzip'd ou texto simples. As URLs automaticamente ser\u00E3o baixadas de novo ap\u00F3s 7 dias, enquanto que os arquivos recarregar\u00E3o dentro de um minuto a serem substitu\u00EDdos/tocados.
+sidebar.header.discovery=Descobrir Cont\u00E9udo
+importTorrentWizard.torrentfile.message=Insira o arquivo torrent para o qual importar
+MainWindow.menu.speed_limits.view=Visualizar...
+ConfigView.section.mode.intermediate.wiki.host=Hospedar Arquivos
+MainWindow.upgrade.error.downloading.hint=Erro\:\tIncapaz de baixar a nova vers\u00E3o, por favor atualize manualmente
+MyTorrentsView.filter.tooltip=Use o s\u00EDmbolo '|' para filtrar v\u00E1rias frases \nCtrl+X para alternar entre RegEx e modos de pesquisa normais \nNo RegEx prefixo modo com '\!' para 'n\u00E3o'. \nPrefixo com \n\t'c\:. 'para pesquisar coment\u00E1rios \n\t't\:' para o host rastreador \n\t'f\:" para pesquisar nomes de arquivos
+ConfigView.section.language=Idioma
+ConfigView.label.userSuperSeeding=Usar Super Seeding
+TableColumn.header.smoothup.info=Velocidade de Up Suavizado {smooth.config}
+PeersView.connected_time=Tempo Conectado
+fileDownloadWindow.retry=Tentar Novamente
+TagAddWindow.public.info=Compartilhamento de tag ir\u00E1 ajudar outros usu\u00E1rios a organizar os seus downloads.
+openUrl.referrer=URL da p\u00E1gina de refer\u00EAncia\:
+DHTView.general.title=Geral
+PiecesView.legend.incache=Dados est\u00E3o no Cache
+SpeedView.stats.estdowncap=Limite de Download\:
+TableColumn.header.comment=Coment\u00E1rio
+PeersView.source=Fonte
+archivedlsview.view.heading=Downloads Arquivados
+GeneralView.label.maxuploadspeed.tooltip=Velocidade M\u00E1x. de Upload [0 \: ilimitada]
+security.crypto.persist_for.forever=Pra sempre
+ConfigView.label.hap.tooltip=Ocultar um peda\u00E7o completo
+ConfigView.section.connection.group.networks=Redes
+MainWindow.menu.file.exit.keybinding=Alt+F4
+devices.comp.missing=Suporte do Vuze n\u00E3o instalado
+SpeedTestWizard.test.panel.abort=Abortar
+ManagerItem.queued=Na Fila
+ConfigView.section.file.nativedelete._mac=Usar a Lixeira quando apagar os arquivos
+subscript.all.subscribed=Voc\u00EA est\u00E1 subscrito a este conte\u00FAdo
+DHTView.transport.title=Detalhes do Transporte
+tag.type.ds.init={fileDownloadWindow.state_initializing}
+TableColumn.header.completed.info=\# dos peers que terminaram de baixar o torrent como reportado pelo rastreador
+subscriptions.view.title=Subscri\u00E7\u00F5es
+CacheView.speeds.reads=Leituras
+subscription.request.add.title={subscriptions.add.tooltip}
+ConfigView.label.queue.debuglog.info=Adiciona informa\u00E7\u00F5es de debug da fila ao arquivo de console/log.\nEmbora cifradas, as informa\u00E7\u00F5es de debug dizem a voc\u00EA o estado dos torrents e porque eles est\u00E3o/n\u00E3o est\u00E3o iniciando/requerindo.
+PiecesView.legend.written=Escritos
+PiecesView.BlockView.Header=%1 coluna(s), %2 fileira(s), %3 peda\u00E7os
+PiecesView.writers=Bloquear Contribuidores
+label.comments=Coment\u00E1rios
+ConfigView.section.transfer.autospeed.maxinc=Aumento m\u00E1ximo em %1 por ciclo
+TableColumn.header.tag.color={label.color}
+ConfigView.label.minannounce=Tempo m\u00EDnimo entre an\u00FAncios de rastreador em segundos
+azbuddy.dchat.cannel.import=Restaurar Canal
+authenticator.details=Detalhes
+ConfigView.section.connection.group.peersources.info=Selecione as fontes padr\u00E3o permitidas para a conex\u00E3o com o peer
+configureWizard.file.browse=Procurar
+OpenTorrentOptions.header.peeroptions=Rastreador, Peer & Op\u00E7\u00F5es de Conex\u00E3o
+MyTorrentsView.menu.moveEnd=&Fundo
+ConfigView.pluginlist.unloadSelected=Descarregar o Selecionado
+device.error.mountrequired="%1" Necess\u00E1rio a montagem no seu dispositivo
+dht.reseed.label=Normalmente ficar de seed de novo da Base de Dados Distribu\u00EDda n\u00E3o \u00E9 necess\u00E1rio. Contudo, se o n\u00FAmero de contatos \u00E9 baixo, isto pode ser usado para a re-integra\u00E7\u00E3o.\nDeixe em branco para bootstrap off peers conectados ou insira o IP e porta para explicitamente bootstrap de um peer conhecido.
+MainWindow.menu.file.import.keybinding.mac=Meta+Shift+I
+tag.show.overview=Exibir Sum\u00E1rio das Tag
+wizard.next=Pr\u00F3ximo >
+MainWindow.status.tooOld=\u00E9 antiga, por favor atualize-a.
+TableColumn.header.SpeedGraphic=Velocidade
+ConfigView.section.interface.clearsavepaths=Limpar os caminhos para salvar recordados
+TableColumn.header.filecount=Arquivos
+SpeedView.stats.now=Agora
+ConfigView.section.file.bgdefaultdir.ask=Padr\u00E3o de Melhor Palpite
+ConfigView.section.mode.advanced.text=Acesso as configura\u00E7\u00F5es de rede.\nUse este modo se voc\u00EA sabe o que MTU ou I/O n\u00E3o-bloqueadores s\u00E3o...
+MyTrackerView.name=Nome
+props.window.title=Propriedades para o '%1'
+AlertMessageBox.information=Informa\u00E7\u00E3o
+pairing.nets.enable=Permitir o registro de endere\u00E7os de rede de servi\u00E7os n\u00E3o p\u00FAblicos
+device.is.disabled=Dispositivo est\u00E1 desabilitado
+TableColumn.header.crc32.info=CRC-32 checksum para o arquivo (deve ser totalmente transferido; clique para calcular)
+ConfigView.section.connection.advanced.IPDiffServ.tooltip=Define a parte do DiffServ do campo do tipo-de-servi\u00E7o (TOS) no cabe\u00E7alho do IP para os pacotes de sa\u00EDda.\nValores hexadecimais podem ser especificados prefixando eles com '0x', ex\: 0x10.\nO Vuze deixa isto n\u00E3o definido por padr\u00E3o, significando que os padr\u00F5es para o SO b\u00E1sico s\u00E3o usados.\nNOTA\: As implementa\u00E7\u00E3o da rede b\u00E1sica pode ignorar este valor, ent\u00E3o esta op\u00E7 [...]
+v3.MainWindow.menu.view.pluginbar=Barra dos Plugins
+ConfigView.label.noportannounce=N\u00E3o anunciar a porta de escuta para o rastreador (isto n\u00E3o afeta o pex, dht)
+OpenTorrentWindow.mb.invaliddefsave.title=Local Inv\u00E1lido para Salvar
+azbuddy.protocolspeed=Acelera\u00E7\u00E3o m\u00E1xima do protocolo em KB/s do amigo
+view.waiting.core=Visualizar estar\u00E3o dispon\u00EDveis uma vez N\u00FAcleo Vuze \u00E9 carregado ..
+ConfigView.section.transfer.autospeed.resetnetwork=Resetar detalhes da rede
+ConfigView.label.lazybitfield=Usar lazy bitfield (ajuda a ficar de seed nas redes empregando o bloqueamento baseado no bitfield)
+ConfigView.section.file.perf.cache.enable.write=Armazenar os dados de download no cache para reduzir as escritas em disco e tamb\u00E9m diminuir as leituras do disco requeridas para a checagem dos peda\u00E7os
+OpenTorrentWindow.mb.askCreateDir.text=O diret\u00F3rio destino '%1' n\u00E3o existe.\n\nCriar agora?
+MagnetPlugin.report.error=erro %1
+ConfigView.label.ui_switcher=Exibir o Escolhedor de Interface Gr\u00E1fica do Vuze
+MainWindow.nat.status.bad=Atr\u00E1s de Firewall
+Scrape.status.scraping=Scraping..
+SpeedTestWizard.stage.message.connect.stats=Estat\u00EDsticas da conex\u00E3o\: peers\=%1, down_ok\=%2, up_ok\=%3
+azbuddy.ui.menu.cat.set_msg=V\u00EDrgula separa as listas das tags, categorias ou "Todos"
+MagnetPlugin.report.ddb_disabled=DDB est\u00E1 desativado
+SpeedTestWizard.abort.message.execution.failed=A execu\u00E7\u00E3o do teste falhou
+TableColumn.header.DateFileCompleted.info=Mais recente data de conclus\u00E3o arquivo em torrent
+Wizard.Subscription.title=Subscrever
+Tracker.tooltip.MultiSupport=Este rastreador suporta m\u00FAltiplos hash scrapes por pedido.
+unix.script.new.title=Novo Script de Inicializa\u00E7\u00E3o do Vuze dispon\u00EDvel
+upnp.mapping.dhtudp=Base de Dados Distribu\u00EDda
+azbuddy.os_away=Ausente
+ConfigView.section.file.rename.incomplete=Adicionar sufixo para arquivos incompletos
+MainWindow.menu.community=&Comunidade
+TableColumn.header.Thumbnail=\u00CDcone
+TableColumn.header.azsubs.ui.column.subs_link.info=Associados com as subscri\u00E7\u00F5es
+ConfigView.section.interface.display.suppress.file.download.dialog.tooltip=Mostrar todo o progresso do download do arquivo na barra de status em vez de um di\u00E1logo popup
+dlg.auth.install.progress=Instalando %1 componentes...
+wizard.multitracker.template.title=Editor de Modelos de Rastreador
+menu.max.share.ratio2=Configurar Ratio Desejado...
+ConfigTransferAutoSpeed.auto.speed.neural=Neural (Gudy Alpha)
+TableColumn.header.trackername.info=Nome do rastreador baseado na URL de an\u00FAncio
+jvm.info=Um rein\u00EDcio do Vuze \u00E9 necess\u00E1rio se op\u00E7\u00F5es s\u00E3o alterados. AVISO *** - alterar as op\u00E7\u00F5es da JVM incorretamente pode causar Vuze a falhar para iniciar ou executar mal ***\n
+SpeedTestWizard.abort.message.unsupported.type=Tipo de teste n\u00E3o suportado\!\!\!\!
+tag.type.ds.down={ManagerItem.downloading}
+plugins.basicview.config=Config.
+SpeedView.stats.asn=Rede\:
+StartStopRules.ratioMet=Peers\:Seed OK
+ConfigView.section.tracker.pollintervalmin=M\u00EDnimo
+PeersView.title.full=Peers
+wizard.multitracker.edit.name=Nome
+ConfigView.section.plugins.dhttracker=Rastreador Distribu\u00EDdo
+TableColumn.header.networks.info=Redes permitidas para a comunica\u00E7\u00E3o de dados peer-peer
+TableColumn.header.trackernextaccess=Pr\u00F3ximo Acesso do Rastreador
+subscriptions.column.nb-results=Total de Resultados
+TableColumn.header.CountryCode.info=O c\u00F3digo do pa\u00EDs (ISO 3166) onde o par est\u00E1 localizado
+installPluginsWizard.installMode.shared=Instalar o(s) plugin(s) para todos os usu\u00E1rios
+wizard.previous=< Voltar 
+subs.prop.template=Modelo
+Button.unmark=Desmarcar
+ConfigView.label.maxuploadspeedseeding=Alternar a taxa apenas quando ficando de seed
+update.instance.install=Checando a Instala\u00E7\u00E3o
+OpenTorrentWindow.mb.existingFiles.title=O(s) Arquivo(s) j\u00E1 existe(m)\!
+natpmp.enable=Ativar (note que deve tamb\u00E9m estar ativado na configura\u00E7\u00E3o do aeroporto para funcionar)
+set.share.ratio.win.msg=Configurar a taxa de compartilhamente  para ajustar o total de download/upload quando necess\u00E1rio
+ConfigView.section.file.defaultdir.bestguess=Usar o melhor palpite quando escolher o diret\u00F3rio padr\u00E3o para salvar
+cat.autoxcode=Dispositivo Autom\u00E1tico
+MyTorrentsView.menu.advancedmenu=Avan\u00E7ado
+stats.long.weekstart=Contagem da semana come\u00E7a em\:
+menu.pop.out=Pop Out...
+label.content=Conte\u00FAdo
+v3.MainWindow.tab.events=Atividade
+CacheView.speeds.fromFile=Do/Para o Arquivo
+v3.iconBar.up.tooltip=Mover pra Cima\nSegure o bot\u00E3o do mouse para mover pro topo
+ConfigView.section.tracker.publishenabledetails=Publicar todos os detalhes do torrent
+openUrl.url.info=Suporta http, https, magnet e strings de infohash raw hex 
+FileProgress.deleted=Apagado
+TrackerView.title.short=Fontes
+ConfigView.section.tracker.sslport=Ativar rastreador na porta HTTPS
+ConfigView.section.transfer.autospeed.maxupload.tooltip=A velocidade de upload n\u00E3o ser\u00E1 aumentada automaticamente acima deste limite
+ColumnProgressETA.showETA=Exibir TEC
+label.aggregate.info=Informa\u00E7\u00E3o Agregada
+ConfigView.section.stats.savefreq=Freq\u00FC\u00EAncia de salvamento
+devices.info.copypending3=%1 Arquivo(s) Aguardando Para Serem Copiados - Hablitar Auto-C\u00F3pia Ou Selecione C\u00F3pia Manual
+tag.type.ds.pau={ManagerItem.paused}
+devices.info.copypending2=%1 Arquivo(s) Aguardando Para Ser Copiados, Conecte Seus Dispositivos
+wizard.title=Criar um torrent 
+Plugin.pluginupdate.enablecheck=Ativar a verifica\u00E7\u00E3o por atualiza\u00E7\u00F5es dos plugins
+installPluginsWizard.installMode.info.title=Info
+dht.execute.info=Pressione para executar o comando
+ConfigView.section.proxy.no.local.dns=Evitar pesquisas de DNS locais
+PiecesView.DistributionView.weDownload=Peda\u00E7os que voc\u00EA est\u00E1 baixando
+ConfigView.label.seeding.firstPriority.seedingMinutes=Tempo decorrido desde que mudou de baixando para seeding
+ConfigView.label.stop.downcomp=Quando o download est\u00E1 completo
+OpenTorrentWindow.addPosition.last=\u00DAltimo
+PiecesView.legend.downloaded=Baixados, escrita pendente
+ConfigView.label.maxuploadsseeding=Alternar para o padr\u00E3o quando ficando de seed
+label.accept=Aceitar
+ConfigView.section.tracker.tcpnonblocking=Usar I/O n\u00E3o-bloqueador para processamento do rastreador TCP. Selecionar esta op\u00E7\u00E3o requer que o rastreador seja executado numa porta alternativa. Experimental\!
+azbuddy.ui.table.rem_cat=Tags/Cats em
+ConfigView.section.file.torrent.ignorefiles=Arquivos a ignorar quando criar torrents\nex\: .DS_Store;Thumbs.db
+sidebar.header.vuze=Vuze
+tps.lan.details=%1 clientes locais descobertos
+wizard.announceUrl=URL de An\u00FAncio \:
+device.quit.transcoding.text='%1' est\u00E1 convertendo atualmente para '%2' e est\u00E1 %3% completo.\nISe voc\u00EA sair agora, ir\u00E1 ser necess\u00E1rio reiniciar do come\u00E7o na pr\u00F3xima vez.
+rss.internal.enable.low.noise=Habilitar downloads de baixo-ru\u00EDdo (downloads internos etc.)
+platform.win32.baddll.winsflt=Puresight Internet Filtro de conte\u00FAdo
+TagRenameWindow.message=Digitar um novo nome para a Tag
+TableColumn.header.torrentname={authenticator.torrent}
+Button.reset=Resetar
+ConfigView.upload.abbreviated=U\:
+metasearch.addtemplate.dup.desc=O modelo de busca %1 j\u00E1 est\u00E1 instalado
+MagnetPlugin.report.md.starts=Criado download de metadados
+CacheView.title.full=Cache
+label.visible=Vis\u00EDvel
+ConfigView.label.serverport.tooltip=A porta deve estar dentro de 1-65535, e nunca a 6880 como essa est\u00E1 reservada para o uso interno do Vuze.
+azbuddy.tracker.bbb.status.nli=Login Requerido
+device.error.copytonotset="Copiar para pasta" n\u00E3o informado
+devices.restrict_access=Acesso Restrito...
+configureWizard.nat.testing=Testando porta
+device.import.dup.desc=Dispositivo '%1' j\u00E1 est\u00E1 presente.
+SpeedTestWizard.test.panel.testfailed=O teste falhou
+ConfigView.section.server.enablednsrecords=Permitir o uso de rastreador registros DNS usados \u200B\u200Bpara melhorar DDOS acidentais
+webui.user=Nome de usu\u00E1rio
+device.itunes.status.notrunning=O iTunes n\u00E3o est\u00E1 sendo executado
+sidebar.LibraryDL=Baixando
+PeersView.BlockView.title=Mapa dos Peda\u00E7os
+MyTorrentsView.menu.host.error.title=Falha na Hospedagem do Torrent 
+TableColumn.header.tag.moveoncomp={label.move.on.comp}
+iconBar.run=Executar
+IPChecker.external.service.dyndns.description=Dynamic DNS Network Services, LLC 
+TrackerAvail.column.peers.info={Trackers.column.peers.info}
+UpdateWindow.status.failed=Falha
+ConfigTransferAutoSpeed.skip.after.adjust=Pular ap\u00F3s o ajuste\:
+label.unpin=Despinar
+MyTorrentsView.menu.setCategory=Designar Categoria
+dlg.auth.enter.denied=C\u00F3digo de ativa\u00E7\u00E3o atual foi negado.
+ConfigView.section.ipfilter.autoload.loadnow=Carregar Agora
+br.backup=Backup
+ConfigView.pluginlist.column.unloadable=Descarreg\u00E1vel
+PeersView.ip=IP
+ConfigView.section.security.resetcerts.error.title={ Configview.section.security.resetkey.error.title }
+ConfigView.label.set_ui_transfer_speeds=N\u00E3o levar em conta as velocidades de transfer\u00EAncia selecion\u00E1veis
+ManagerItem.superseeding=Super-Seeding
+MainWindow.menu.file.create.keybinding=Meta+N
+azbuddy.ui.menu.chat=Bate-papo
+Scrape.status.cached=Scrape do cache
+UpdateWindow.header=Os seguintes componentes precisam de uma atualiza\u00E7\u00E3o \:
+MyTorrentsView.menu.rename.displayed_and_save_path=Renomear Nome Exibido e Salvar Caminho
+ConfigView.label.bStartNoMoreSeedsWhenUpLimitMetPercent=A aproxima\u00E7\u00E3o acima \u00E9 uma porcentagem (desmarque para absoluto)
+sidebar.LibraryCD=Completados
+TagAddWindow.title=Adicionar Nova Tag
+ConfigView.pluginlist.loadSelected=Carregar os Selecionados
+AdvRenameWindow.rename.torrent=Renomear Torrent
+subscript.add.dup.title=Duplicar a Subscri\u00E7\u00E3o
+ConfigTransferAutoSpeed.ping.time.bad=Ruim\:
+IrcClient.connecting=Conectando a 
+dlg.stream.plus.renew.subtext={dlg.stream.plus.subtext}
+ConfigView.label.overrideip.tooltip=Informar o rastreador de diferentes endere\u00E7o(s) de IP do que aquele de onde os pacotes de sa\u00EDda vem. Deixe em branco para n\u00E3o usar a op\u00E7\u00E3o.
+tps.type.dht=DHT
+ConfigView.section.tracker.sendpeerids=Enviar as identidades dos peers aos que baixam
+FileItem.storage.compact=Compacta
+tag.property.tracker_templates={label.tracker.templates}
+security.crypto.password2=Re-inserir a senha
+TableColumn.header.comment.info=Coment\u00E1rio definido-pelo-usu\u00E1rio para o download
+ConfigView.boolean.ircsendinfo=Permite enviar as suas configura\u00E7\u00F5es (an\u00F4nimo) para\n os operadores do canal para ajud\u00E1-los a ajudar voc\u00EA
+MainWindow.menu.file=&Arquivo
+FilesView.rename.confirm.delete.text=Confirmar exclus\u00E3o do arquivo original '%1'
+SpeedView.stats.autospeed=Velocidade de Upload Autom\u00E1tica
+MainWindow.menu.speed_limits.schedule.title=Agendar Limites de velocidade
+ConfigView.section.style.library={library.name}
+devices.cancel_xcode=Cancelar Convers\u00E3o
+ColumnSetup.availcolumns.filteredby=Dispon\u00EDveis %1 colunas filtradas por %2
+IrcClient.nowknown=\u00E9 agora conhecido como 
+ConfigView.section.logging.enable=Ativar registro para o arquivo
+device.od.group={device.offlinedownloader.view.title}
+PiecesView.title.short=Peda\u00E7os
+ClientStats.column.name={TableColumn.header.name}
+ConfigView.section.interface.alerts=Alertas
+TableColumn.header.totalspeed=Velocidade Total
+faq.legal.url=http\://wiki.vuze.com/w/FAQ_Legal
+MainWindow.menu.file.share.file=&Arquivo...
+device.playnow.min_buffer=Tamanho do buffer enquanto o rebuffering ocorre [sec]
+MyTorrentsView.menu.edit_comment.enter.title=Editar Coment\u00E1rio
+iconBar.share.tooltip=Compartilhar Conte\u00FAdo
+UpdateWindow.restart=Reiniciar
+pairing.srp.info=Algumas aplica\u00E7\u00F5es remotas apoiar tanto maior conectividade e seguran\u00E7a, utilizando o protocolo senha remoto seguro "e, opcionalmente, as conex\u00F5es de proxy para aumentar a conectividade.\n\nConsulte a documenta\u00E7\u00E3o do aplicativo de controle remoto para ver se voc\u00EA pode se beneficiar com isso.
+OpenTorrentWindow.addPosition.first=Primeiro
+MainWindow.dialog.share.sharedir=Selecionar Pasta para Compartilhar
+security.certtruster.no=N\u00E3o
+ConfigView.section.tracker.pollintervalmax=M\u00E1ximo
+delete.partial.files=Quando remover um download da biblioteca, apagar qualquer arquivo parcial selecionado como 'n\u00E3o baixar" ou 'apagar'
+PeersView.statup.info=Um valor estimado da velocidade de upload do peer
+MainWindow.menu.beta.on=Junte-se Programa Beta ...
+SpeedTestWizard.name.conf.level.med=M\u00E9dia
+MagnetPlugin.report.secondarylookup=Tentando servi\u00E7o de pesquisa secund\u00E1ria
+upnp.refresh.button=Atualizar
+LoggerView.clear=&Limpar
+ConfigView.section.stats.exportfiles=Exportar os detalhes do arquivo
+label.inbound=Entrando
+window.uiswitcher.ClassicUI.text=* Mant\u00E9m a funcionalidade de cliente s\u00E9rie 2.x\n\n* Visualiza\u00E7\u00E3o por abas cl\u00E1ssico\n* Legado vista, reduzido conjunto de recursos.
+tps.type.incoming=Entrada
+ConfigView.section.UPnP=UPnP
+PiecesView.legend.requested=Requeridos
+ConfigView.section.tracker.sslport.info=Veja o FAQ para mais informa\u00E7\u00F5es
+ConfigView.section.tracker.client.readtimeout=A leitura expira em (secs)
+TagDiscoveriesView.menu.tagit=Atribuir Tag
+ConfigView.section.file.showopentorrentoptions=Quando abrindo um torrent, exiba di\u00E1logo de op\u00E7\u00F5es\:
+ConfigView.section.file.perf.cache.notsmallerthan=N\u00E3o colocar no cache arquivos menores que isto (em %1)
+TrackerAvail.column.leechers={Trackers.column.leechers}
+torrent.fix.corrupt.result.title=Resultado da opera\u00E7\u00E3o
+FilesView.remaining=Peda\u00E7os Restantes
+devices.on.demand=Sobre a demanda
+ConfigView.section.ipfilter.list.title=Lista de IPs Bloqueados
+v3.MainWindow.tab.minilibrary=De downloads
+mdi.entry.about.plugins=Sobre Plugins
+upnp.alert.multipledevice.warning=M\u00FAltiplos dispositivos UPnP foram detectados - verifique se todos requerem mapeamento de porta (veja o log e a configura\u00E7\u00E3o do UPnP)
+archive.failed.text=Um ou mais downloads n\u00E3o estavam em um estado arquiv\u00E1vel.\n\nVeja <a href\="http\://wiki.vuze.com/w/Archiving_Downloads">o Wiki</a> para mais informa\u00E7\u00F5es.
+jvm.error=Houve um erro ao acessar as op\u00E7\u00F5es de JVM\: %1
+TableColumn.header.fileext=Tipo de Arquivo
+xcode.deletedata.message=Tem certeza de que quer apagar definitivamente a c\u00F3pia de '%1' transcodificado para '%2'%3?
+ConfigView.label.max_peers_per_torrent=M\u00E1ximo de conex\u00F5es padr\u00E3o por torrent [0\: ilimitadas]
+pairing.srp.setpw=Atualizar sua senha de  emparelhamento
+ConfigView.section.tracker.web=Web 
+MyTrackerView.bytesout=Bytes Enviados
+PeersView.pieces=Peda\u00E7os
+plugin.sharing.torrent.remove.veto=Este registro de rastreador \u00E9 o resultado de um recurso que est\u00E1 sendo compartilhado.\nPara remover o download remova o compartilhamento associado\: v\u00E1 em Ferramentas->Meus compartilhamentos.
+azbuddy.dchat.create.join.key=Criar/entrar no canal personalizado\: chave
+mdi.entry.plus.full=Vuze Plus
+CacheView.general.title=Info sobre o Cache
+beta.wizard.intro.title=Sele\u00E7\u00E3o Inscri\u00E7\u00E3o
+#
+# 2.0.7.x
+#
+Categories.all=Todas
+security.certcreate.country=C\u00F3digo do pa\u00EDs com duas letras
+MainWindow.menu.window.zoom=&Zoom
+ConfigView.download.abbreviated=D\:
+MainWindow.menu.plugins.uninstallPlugins=Assistente de Desinstala\u00E7\u00E3o...
+subscriptions.column.SubWizName={FilesView.name}
+ConfigView.section.ipfilter.totalIPs=%1 IPs bloqueados no total, que s\u00E3o %2 da internet.
+TableColumn.header.Speed=Velocidade
+ConfigView.section.tracker.client=Cliente
+label.nat.proxies=NAT/Proxies
+ConfigView.section.file.perf.cache.flushpieces=Escrever peda\u00E7os completos no disco imediatamente. Isto suaviza o acesso ao disco mas pode resultar em mais opera\u00E7\u00F5es de escrita.
+MagnetPlugin.report.md.progress=Progresso do download da Metadados\: %1
+UIDebugGenerator.complete.title=Gera\u00E7\u00E3o de Debug Completa
+network.ipv4.prefer.stack=Preferir IPv4 stack - usar seperadamente IPv4 e IPv6 stacks ao inv\u00E9s da implementa\u00E7\u00E3o dual-stack
+ConfigView.label.set_ui_transfer_speeds.description=Voc\u00EA pode escolher definir manualmente as velocidades de download e upload dispon\u00EDveis na barra de status no tray do sistema.\nOs valores devem estar separados por v\u00EDrgula.
+ConfigView.label.maxdownloads.short=M\u00E1ximo de downloads simult\u00E2neos [0\: ilimitado]
+SpeedTestWizard.test.panel.aborted=Teste abortado manualmente.
+ConfigView.label.stop.Shutdown=Desligar o computador
+azmsgsync.install=Instalar Plugin de Mensagens Sync
+FilesView.menu.setpriority=&Definir Prioridade 
+MyTorrentsView.dialog.setPosition.text=Insira a posi\u00E7\u00E3o para definir os torrents selecionados\:
+device.import.dup.title=Dispositivo Duplicado
+Formats.units.kbit=kbit
+metasearch.addtemplate.done.desc=Modelo '%1' adicionado com sucesso.\nEle ser\u00E1 usado quando voc\u00EA fizer a pr\u00F3xima busca\!
+ConfigView.section.color=Esquema de Cores
+devices.choose.profile.info.title.selected=%1 detalhes\:
+SpeedTestWizard.test.panel.encrypted=encriptado
+Peers.column.client_identification=Identifica\u00E7\u00E3o do Cliente
+MainWindow.menu.view.clientstats={ClientStats.title.full}
+label.checking.comments=Verificar a disponibilidade de coment\u00E1rios e avalia\u00E7\u00F5es de usu\u00E1rios
+PiecesView.speed.info=Peers mais lento s\u00E3o impedidos de interferir muito com os peda\u00E7os mais r\u00E1pidos 
+FilesView.name=Nome
+MyTorrentsView.menu.checkfilesexist=Arquivos de Verifica\u00E7\u00E3o Existem
+ConfigView.pluginlist.column.name=Nome
+v3.MainWindow.button.run=Executar o Arquivo Baixado
+configureWizard.transfer.message=Por favor escolha uma conex\u00E3o abaixo. Esteja ciente que n\u00E3o permitir uma velocidade de upload boa resultar\u00E1 em baixas velocidades de download. Como a velocidade de upload s\u00F3 conta POR torrent que voc\u00EA est\u00E1 baixando, tentar baixar muitos torrents ao mesmo tempo tamb\u00E9m resultar\u00E1 em baixas velocidades. N\u00F3s recomendadmos usar 5 KB/s por torrent como um m\u00EDnimo ESTRITO. Quanto mais r\u00E1pido o seu upload, mais [...]
+beta.wizard.link.url=http\://dev.vuze.com
+devices.od.turnon.learn=Aprender mais >
+MainWindow.menu.help.debug=Gerar Info de Debug (Crash Log)
+LocaleUtil.section.chooseencoding=Escolher codifica\u00E7\u00E3o para o nome do arquivo
+ConfigView.section.transfer.autospeed.reset=Resetar valores avan\u00E7ados
+MainWindow.menu.speed_limits.reset=Limpar Limites de Atual
+v3.mb.delPublished.text=AVISO\: Esta a\u00E7\u00E3o N\u00C3O remover\u00E1 seu conte\u00FAdo publicado '%1' de <A HREF\="%2">%3</A> .\n\nClique em "Apagar" apenas se voc\u00EA quer que o seu conte\u00FAdo permane\u00E7a publicado e baix\u00E1vel, mas quer liberar a sua banda. Tenha certeza de que o processo de upload foi completado antes de faz\u00EA-lo (<A HREF\="%4">how</A>?).\n\nClique em "Cancelar" se voc\u00EA quer remover completamente seu conte\u00FAdo publicado de %3, e usar o bo [...]
+Button.continue=Continuar
+ConfigView.label.ircchannel=Canal
+Torrent.create.progress.hashing=Hasheando arquivos
+ConfigView.section.mode.beginner.text=Tudo que voc\u00EA precisa para baixar torrents.\nUse este modo se tudo que voc\u00EA quer \u00E9 gerenciar seus torrents.
+externalLogin.explanation=O modelo "%1" requer que voc\u00EA logue. Uma vez logado esta janela automaticamente fechar\u00E1. Se ela n\u00E3o fechar por favor clique em "feito".
+Menu.show.torrent.menu.tooltip=Mostra o menu Torrents na barra do menu do aplicativo no topo
+PeerManager.status.finishedin=Terminado em 
+security.certtruster.issuedto=Emitido Para\:
+Torrent.create.progress.parsingfiles=Analizando arquivos
+Progress.reporting.window.remove.auto=Automaticalmente remover itens inativos
+SpeedView.stats.upload=Dados de Upload Enfilerados\:
+stats.display.group={ConfigView.section.display}
+ConfigView.section.style.osx_small_fonts=Usar fontes pequenas [requer reiniciar]
+UpdateWindow.status.done=Pronto
+platform.win32.baddll.netdog=Armor2net Firewall pessoal
+custom.settings.import=Voc\u00EA est\u00E1 certo que deseja  importar configura\u00E7\u00F5es para '%1'?
+ConfigView.section.connection.pairing.srp.url=http\://wiki.vuze.com/w/secure_remote_password
+devices.sidebar.oxc.nothing={ConfigView.label.stop.Nothing}
+GeneralView.menu.selectTracker=Selecionar
+devices.associate.already=J\u00E1 associado
+DHTTransport.report.complete=completo
+# > 2402
+popup.download.finished="%1" terminou de baixar.
+device.upnp.desc_url=Descri\u00E7\u00E3o do Dispositivo
+security.certcreate.alias=Apelido
+FilesView.menu.rename=Renomear ou Mover Arquivo(s)
+v3.iconBar.view.small=ew
+Tracker.announce.ignorePeerSeed=Ignorar Contagem de Peers/Seeds. %1
+ConfigView.section.tracker.publicenable.info=Isto permite que outros criem torrents que usem o seu tracker\nsem que voc\u00EA os hospede/publique
+MyTrackerView.category=Categoria
+ConfigView.label.moveonlyusingdefaultsave=apenas se estiver no diret\u00F3rio de dados padr\u00E3o
+label.merge=Juntar
+MainWindow.menu.file.closewindow.keybinding=Meta+Shift+W
+Progress.reporting.window.remove.now=Remover itens inativos
+SpeedTestWizard.finish.panel.auto.speed=AutoVelocidade \u00E9 \:
+pairing.srp.registering=Registrando...
+subs.prop.high_version=Maior vers\u00E3o encontrada
+ConfigView.section.tracker.logenable=Registrar as estat\u00EDsticas per\u00EDodicas em 'tracker.log'
+beta.wizard.title=A configura\u00E7\u00E3o da vers\u00E3o Beta
+menu.open.torrent={torrent.fix.corrupt.browse}...
+dlg.install.azemp.subtitle={dlg.player.install.subtitle}
+OpenTorrentWindow.mb.noGlobalDestDir.text=O diret\u00F3rio destino '%1' \u00E9 inv\u00E1lido.
+ConfigView.label.zeronewfiles.tooltip=Minimiza a fragmenta\u00E7\u00E3o
+MainWindow.dialog.choose.file=Escolha o arquivo torrent
+TableColumn.header.name.ext=Tipo de Arquivo\: %1
+window.updateswt.status.downloading.updater=Baixando o M\u00F3dulo de Atualiza\u00E7\u00E3o
+azmsgsync.install.description=Por favor, aguarde enquanto o plugin Sync Mensagem \u00E9 instalado
+MyTorrentsView.menu.editTrackerMerge=Editar URLs dos Rastreadores  Juntos
+DevicesOD.column.od_name={TableColumn.header.name}
+v3.mb.PlayFileNotFound.title=Arquivo N\u00E3o Encontrado
+ConfigView.section.language.info=Quando ativada, uma verifica\u00E7\u00E3o de atualiza\u00E7\u00E3o ocorrer\u00E1 toda vez que o Vuze iniciar.
+ConfigView.section.stats.xslfile=Nome do arquivo XSL
+core.shutdown.xcode=transcodifica\u00E7\u00E3o conclu\u00EDda
+TableColumn.header.smootheta=TEC Suavizado
+VivaldiView.title.full_v6=Vivaldi IPv6
+label.date.format=Formato da Data
+ConfigTransferAutoSpeed.auto.speed.beta=Auto-Velocidade(beta)
+TableColumn.header.health.info=Qu\u00E3o saud\u00E1vel sua conex\u00E3o com a multid\u00E3o do torrent \u00E9
+ConfigView.text.ignore=Ignorar
+configureWizard.transfer.maxUpSpeed=Velocidade M\u00E1xima de Upload (KB/s)
+label.anon.chat=Bate-papo An\u00F4nimo
+IrcView.clientsconnected=usu\u00E1rios
+azneti2phelper.install.reason.decentralised=O torrent que voc\u00EA est\u00E1 adicionando \u00E9 puramente descentralizado. \u00C9 poss\u00EDvel que esse torrent s\u00F3 fucione na rede I2P.
+dialog.associations.askagain=Verificar ao iniciar
+tag.property.untagged={label.untagged}
+ConfigView.section.security.resetcerts.error.msg=Falha ao redefinir o armazenamento de certificados por uma raz\u00E3o desconhecida, consulte os f\u00F3runs de ajuda
+GeneralView.label.peers=Peers\:
+ConfigView.section.connection.networks.Tor=A rede do Onion Router (Tor)
+ConfigView.label.playfilespeech=Falar quando um arquivo est\u00E1 terminado
+library.tag.header=Tag '%1'
+jvm.max.mem=Tamanho da mem\u00F3ria Heap M\u00E1ximo [branco\=padr\u00E3o,min\=%1]
+ConfigView.section.ipfilter.autoload.group=Auto Carregar
+ConfigView.section.tracker.passwordenableweb=Ativar senha na rede do tracker
+Button.ok=OK
+ConfigView.pluginlist.column.type.perUser=Por Usu\u00E1rio
+MyTorrentsView.menu.setUpSpeed=Definir Velocidade de Upload
+OpenTorrentWindow.dataLocation=Local para salvar os dados\:
+MyTorrentsView.menu.trackername.editprefs=Editar exibi\u00E7\u00E3o de Rastreadores preferidos...
+PiecesView.typeItem.1=R\u00E1pido
+AlertMessageBox.error=Erro
+PiecesView.typeItem.0=Lento
+v3.deleteContent.or.archive=Alternativamente, cancele esta opera\u00E7\u00E3o e arquivo seus downloads para f\u00E1cil recupera\u00E7\u00E3o depois \= veja 'Downloads Arquivados' no menu Visualizar
+ConfigView.section.connection.port.rand.range=Alcance das portas [min-max]
+window.update.noupdates.title=Procurar pelos Resultados das Atualiza\u00E7\u00F5es
+ConfigView.section.style.useFancyTabs=Usar Abas Extravagantes
+ConfigView.label.seeding.autoReposition=Automaticamente reposicionar torrents baseado no Rank do Seeding
+beta.wizard.on=Atualizar-me com as mais recentes vers\u00F5es beta est\u00E1veis \u200B\u200Bpor favor.
+Peers.column.timetocomplete=Tempo Restante
+ConfigView.section.proxy.testsocks.title=Testando conex\u00E3o SOCKS
+ConfigView.section.downloadManagement=Gerenciamento de Download 
+config.external.browser.info2=Navegador padr\u00E3o do seu computador \u00E9 usado normalmente. Voc\u00EA pode alterar isso para usar um navegador espec\u00EDfico, ou que a fornecida por um plugin (por exemplo, o plug-in do navegador Tor)
+config.external.browser.info1=O navegador externo \u00E9 usado para exibir conte\u00FAdo da web fora do cliente, por exemplo nos casos dos detalhes dos resultado das buscas
+tag.type.man.vhdn={sidebar.VuzeHDNetwork}
+MainWindow.menu.file.open.uri.keybinding=Meta+U
+ActivityView.legend.achieved=Taxa obtida
+dialog.add.peers.title=Adicionar Peer(s)
+devices.choose.device.info.title=Dica Dispositivo
+installPluginsWizard.list.title=Lista dos Plugins Instal\u00E1veis
+TorrentInfoView.title.full={GeneralView.section.info}
+TableColumn.header.health=Sa\u00FAde
+ConfigView.label.sleep.download=Baixando
+Button.no=N\u00E3o
+Scrape.status.ok=Scrape Ok
+azbuddy.dchat.public.beta=Bate-Papo p\u00FAblico beta
+pairing.status.info=Status
+DownloadActivityView.legend.down={iconBar.down}
+fileplugininstall.install.desc=Voc\u00EA tem certeza que voc\u00EA quer instalar o plugin '%1', vers\u00E3o %2?
+MainWindow.menu.speed_limits.view_current=Visualizar Atual...
+azbuddy.dchat.rchans.managed=Gerenciar Novo Canal
+IrcClient.noNick=Nenhum Apelido Especificado. Por favor v\u00E1 para Visualiza\u00E7\u00E3o 'Op\u00E7\u00F5es'
+Peers.column.client_identification.info=Indica os nomes naturais dos clientes recebidos pelo Vuze - \u00FAtil para debugging
+MainWindow.menu.transfers.pausetransfers.keybinding=Meta+P
+Categories.uncategorized=Sem categoria
+MySharesView.title.full=Meus Compartilhamentos
+DiskManager.alert.movefileexists=Erro ao mover arquivos completos\nO arquivo %1 j\u00E1 existe no diret\u00F3rio de destino MoveTo
+MyTorrentsView.menu.start=&Iniciar
+dht.enabled=Ativar a base de dados distribu\u00EDda
+v3.mb.PlayFileNotFound.button.remove=Remover do Vuze
+window.updateswt.status.done=Reiniciando
+TableColumn.header.transcode_name={ Tablecolumn.header.name }
+MainWindow.updateavail=Clique aqui para atualiza\u00E7\u00F5es
+TableColumn.header.secondsdownloading=Baixando Para
+Button.bar.share=Compartilhar
+ConfigView.section.transfer.speeds.wiki=Boas configura\u00E7\u00F5es de velocidade
+Views.plugins.UPnP.title=UPnP
+ConfigView.section.ipfilter.discardminkb=M\u00EDnimo de %1 descartados antes de aplicar a propor\u00E7\u00E3o
+MainWindow.menu.view.open_global_transfer_bar=Barra de Transfer\u00EAncias
+devices.copy.fail=Falha na c\u00F3pia para o dispositivo
+IrcClient.channel=Canal 
+SpeedTestWizard.abort.message.insufficient.slots=N\u00E3o p\u00F4de fazer upload a quaisquer dos peers - slots de upload insuficientes?
+FilesView.rename.choose.path.dir=Escolher diret\u00F3rio novo ou existente
+Main.parameter.usage=Uso \: java org.gudy.azureus2.cl.Main [par\u00E2metros] "arquivo.torrent" "caminho para salvar"
+ConfigView.section.mode.intermediate=Intermedi\u00E1rio
+FilesView.header={FilesView.title.full}
+label.chat.type=Tipo de Bate-papo
+ConfigView.section.file.decoder.prompt=Sempre alertar quando houver uma escolha de codifica\u00E7\u00E3o dispon\u00EDvel
+label.edit.trackers=Editar Rastreadores
+torrent.comments.title=Coment\u00E1rios/Avalia\u00E7\u00F5es de '%1'
+v3.MainWindow.menu.view.asSimpleList=Lista Simples
+ManagerItem.waiting=Esperando
+config.external.browser.select=Navegador Selecionado
+ConfigView.text.peers=Peers
+wizard.maketorrent.auto=Autom\u00E1tico
+ConfigView.section.tracker.publicenable=Ativar torrents externos
+v3.mb.PlayFileNotFound.button.find=Achar Manualmente..
+MyTrackerView.left=Restante
+azbuddy.dchat.copy.channel.pk=Chave P\u00FAblica
+GeneralView.section.transfer=Transfer\u00EAncias
+PluginDeprecation.alert=Um plugin tentou usar uma funcionalidade a qual ser\u00E1 removida no futuro - por favor abra a visualiza\u00E7\u00E3o do Log do Debug do Plugin para mais informa\u00E7\u00E3o.
+GeneralView.label.trackerurl.tooltip=Clique para copiar a URL de an\u00FAncio para a \u00E1rea de transfer\u00EAncia
+UIDebugGenerator.messageask.title=Gerador de Debug
+Views.plugins.azbuddy.title=Amigos
+ConfigView.section.global=Geral
+ConfigView.section.style.useUnitsRateBits=Usar bits em vez de bytes para os valores das taxas baseadas em bytes (KiB/s->Kibit/s etc.)
+ConfigView.label.StartUIBeforeCore=Iniciar UI antes de iniciar o n\u00FAcleo
+device.rss.group=RSS Fedd local
+MainWindow.menu.speed_limits.wiki=Ajuda Wiki...
+ConfigView.label.please.visit.here=Por favor visite aqui para detalhes
+MainWindow.menu.file.exit=Sai&r
+device.import.desc=Voc\u00EA tem certeza que deseja importar dispositivo '%1'?
+GeneralView.no=N\u00E3o
+Tracker.tooltip.NoMultiSupport=Este rastreador n\u00E3o suporta m\u00FAltiplos hash scrapes por pedido.
+MainWindow.dialog.choose.folder=Escolha o diret\u00F3rio contendo os arquivos torrent
+azbuddy.os_online=Online
+MainWindow.menu.file.configure=Assistente de &Configura\u00E7\u00E3o...
+MainWindow.about.internet.contributors=Contribuidores
+azbuddy.dchat.rchans.rand=Subcanal Aleat\u00F3rio
+ConfigView.label.set_ui_transfer_speeds.description.download=Definir as velocidades de download (em KB/s)
+ConfigView.label.resume.downloads.on.start=Resumir downloads pausados ao iniciar ap\u00F3s a inicializa\u00E7\u00E3o completar
+ConfigView.section.connection.http.port=N\u00FAmero da porta de entrada
+ConfigView.section.stats.exportpeers=Exportar os detalhes dos peers
+ConfigView.section.file.subfolder.dnd=Mover arquivos n\u00E3o selecionados para download para subpasta
+FilesView.firstpiece=Primeiro peda\u00E7o \# 
+pairing.explicit.info=Atributos IP Normalmente expl\u00EDcitas n\u00E3o precisa ser especificado como estes podem ser derivadas automaticamente.\nO atributo 'host' pode ser usado, por exemplo, se voc\u00EA tiver uma conta DynDNS e software cliente apropriado para manter seu IP din\u00E2mico registrado corretamente.
+azbuddy.dchat.copy.i2p.magnet=Copiar Magnet s\u00F3 de I2P Para \u00C1rea de Transfer\u00EAncia
+Views.plugins.Plugin.Update.title=Atualiza\u00E7\u00E3o do Plugin
+ConfigView.section.logging.showLogsFor=Mostrar os logs das %1 para as seguintes categorias\:
+ConfigView.section.connection.http.portoverride=N\u00E3o Levar em Conta a Porta HTTP do Rastreador [0\: nenhuma]
+azbuddy.dchat.anon.share.endpoint.info=Infelizmente utilizando destinos separados atualmente n\u00E3o s\u00E3o confi\u00E1vel
+TableColumn.header.chat.fave={label.fave}
+SystemTray.menu.show=&Mostrar o Vuze
+TransferStatsView.legend.pingaverage=M\u00E9dia
+subscriptions.listwindow.failed=Nenhuma subscri\u00E7\u00E3o Achada
+iconBar.publish.tooltip=Publicar
+torrent.view.info.title=Informa\u00E7\u00E3o do Torrent
+device.xcode.whenreq=Quando requerido
+TableColumn.TorrentStream.tooltip.expand=Expandir linha para ver Executar Agora para arquivos individuais
+tag.search=Buscar na Comunidade...
+aznettorbrowser.install=Instalar Plugin do Navegador Tor
+UpdateWindow.columns.name=Nome
+dlg.auth.enter.subtitle.try.2=Falha na Valida\u00E7\u00E3o
+dlg.auth.enter.subtitle.try.1=Quase L\u00E1.
+azbuddy.ui.menu.disconnect=Desconectar
+option.askeverytime=Perguntar sempre
+ConfigView.section.language.UpdateNow=Atualizar Agora\!
+ConfigView.section.file.config.currentdir=Diret\u00F3rio da configura\u00E7\u00E3o atual\:
+TrayWindow.menu.show=&Mostrar o Vuze
+Pieces.column.Requested.info=Mostra se mais pedidos podem ser feitos no peda\u00E7o ou n\u00E3o (*)
+ConfigView.label.seeding.ignoreRatioPeers=Ignorar torrents que tenham pelo menos 1 seed para cada
+PeersView.menu.blockupload=Bloquear Upload
+dlg.auth.install.failed.text=C\u00F3digo de ativa\u00E7\u00E3o '%1' falhou em virtude de um erro no servidor.\n\nPor Favor tente  novamente a ativa\u00E7\u00E3o (erro reportado foi '%2')
+Trackers.column.interval.info=Re-consulta intervalo em segundos\: intervalo (intervalo min)
+MagnetPlugin.report.searching=buscando...
+dht.reseed.info=Ficar de seed da base de dados de novo
+TableColumn.header.tag.public={ConfigView.pluginlist.column.type.shared}
+config.internal.browser.info3=Um proxy pode ser usado em raz\u00E3o do conte\u00FAdo ser alcan\u00E7ado indiretamente, quando instalado (Ex\: Provido pelo plugin Tor Helper)
+config.internal.browser.info2=Por padr\u00E3o o Internet Explorer \u00E9 usado no Windows, o Safari no Mac. * Limitado vers\u00F5es * do Firefox pode ser usado no lugar - veja as seguintes op\u00E7\u00F5es
+Subscription.menu.clearall=Marcar Todos Os Resultados Como Lidos
+subscript.add.upgradeto.desc=A vers\u00E3o %1 da subscri\u00E7\u00E3o '%2' est\u00E1 dispon\u00EDvel.\nVoc\u00EA quer atualizar?
+Wizard.Subscription.subscribe.title=Subscri\u00E7\u00F5es Dispon\u00EDveis
+config.internal.browser.info1=O navegador interno \u00E9 usado para exibir o conte\u00FAdo da web embutido no cliente, por exemplo, a p\u00E1gina da rede Vuze HD
+ConfigView.section.interface.display.suppress.file.download.dialog=Suprimir o di\u00E1logo popup do Download do Arquivo
+PeersView.piece.info=\u00DAltimo peda\u00E7o \# requesitado deste peer
+DownloadActivityView.legend.up={iconBar.up}
+ConfigView.section.tracker.forceport=For\u00E7ar torrents externos hospedados para a porta padr\u00E3o
+v3.topbar.menu.show.frog=O Sapo Azul
+torrent.comment.azrating.install=Plugin de Avalia\u00E7\u00E3o n\u00E3o est\u00E1 instalado - veja Ferramentas->Plugins->Assistente de Instala\u00E7\u00E3o
+ConfigView.label.announceport=N\u00E3o levar em conta a porta TCP anunciada para os an\u00FAncios do rastreador, pex e dht\n[deixar vazio\: sem levar em conta, 0\: sem conex\u00F5es de entrada]
+ConfigView.section.stats=Estat\u00EDsticas
+Column.seedspeers.started=%1 de %2
+subscriptions.enter.freq=Introduzir a frequ\u00EAncia de atualiza\u00E7\u00E3o em minutos
+ConfigView.section.invalid.value.title=Valor Inv\u00E1lido
+DHTView.transport.in=Entrou \:
+ConfigView.label.seeding.rankType.seed.tooltip=Menos Seeds \= Maior Rank
+azbuddy.enabled=Ativado
+dhttracker.alt_group=Rastreamento Alternativo
+ConfigView.section.connection.networks.I2P=Rede I2P
+plugin.init.load.failed=Erro ao carregar plugin '%1' de %2
+message.confirm.delete.title=Confirmar a Exclus\u00E3o
+dht.reseed.group=Ficar de seed de novo
+ConfigView.label.quickviewexts=Extens\u00F5es de Arquivos para Exibi\u00E7\u00E3o-R\u00E1pida
+sidebar.Library=Minha Biblioteca
+ConfigView.label.switchpriority=Auto-trocar para prioridade baixa quando estiver ficando de seed
+PeersView.menu.kickandban=Chutar e Banir
+subs.prop.last_scan=\u00DAltima atualiza\u00E7\u00E3o bem sucedida
+IPChecker.external.service.no-ip.description=Provedor de servi\u00E7o DNS din\u00E2mico e est\u00E1tico\n(nenhum servi\u00E7o de 'verificar o endre\u00E7o' dispon\u00EDvel gratuitamente)
+devices.ready=Pronto
+device.od.error.opfailexcep=O dispositivo falhou ao processar comando %1\: exce\u00E7\u00E3o %2
+TableColumn.header.OnlyCDing4=S\u00F3FazendoSeed4
+IPChecker.external.service.dyndns.url=http\://www.dyndns.org/ 
+label.learnmore=Aprender Mais
+dlg.install.vuzexcode.subtitle=Instalando o componente de An\u00E1lise de M\u00EDdia
+TableColumn.header.TableColumnChosenColumn=Escolher a Coluna
+Subscription.menu.setcookies=Definir cookies
+iconBar.run.tooltip=Abrir
+ConfigView.label.stop.RunScript=Executar Script
+vote.vuze.url=http\://vote.vuze.com/
+ConfigView.section.tracker.maxposttimemultiplier.info=Usado para formar submiss\u00F5es e uploads
+azbuddy.tracker.bbb.status.title=Acelera\u00E7\u00E3o de Amigo
+Button.swarmit=Insira na Multid\u00E3o\!
+GeneralView.label.status.file=Status do Arquivo
+GeneralView.label.creationdate=Criado Em \:
+ipCheckerWizard.service.description=Descri\u00E7\u00E3o \:
+subscription.version.bad=A subscri\u00E7\u00E3o '%1' n\u00E3o pode ser instalado at\u00E9 que voc\u00EA atualize o Vuze
+ConfigView.section.tracker.enablekey=Ativar a entrega da chave ao tracker para seguran\u00E7a melhorada
+platform.jvmopt.nolinkfile=N\u00E3o \u00E9 poss\u00EDvel gerenciar as op\u00E7\u00F5es de JVM como a migra\u00E7\u00E3o n\u00E3o \u00E9 completa
+ColumnRenameWindow.message=Digite um novo nome para a coluna, deixe em branco para restaurar
+upnp.grabports=Mapear portas mesmo se possu\u00EDdas por outro computador
+ConfigView.section.security.clearpasswords.button=Resetar
+ConfigView.label.seeding.ignore.header.evenFirstPriority=Ignorar o torrent mesmo se\nas regras de Primeira Prioridade se apliquem
+Button.revert=Reverter
+uninstallPluginsWizard.list.title=Lista dos Plugins Instalados
+UpdateConstraint.message=Digite as restri\u00E7\u00F5es a serem aplicadas para a tag - veja o Wiki para mais detalhes.
+azbuddy.online_status=Status Online
+ConfigView.section.logging.log1type=Aviso
+OpenTorrentOptions.header.filesInfo.all=%1 Arquivos\: %3
+ConfigView.section.start=Iniciar
+MyTrackerView.title.full=Meu Rastreador
+devices.copy.device.auto=Automaticamente copiar arquivos para dispositivo
+PeersView.discarded=Descartado
+metasearch.import.select.template.file=Abrir o Modelo
+download.removerules.unauthorised.data=\tRemover Dados
+device.onlyShowTagged=Exibir somente Dispositivos com Tags
+MainWindow.sr.status.tooltip.poor=Taxa de Compartilhamento %1 pobre\: < 0.9
+wizard.webseed.title=Seeds HTTP
+ConfigView.label.queue.debuglog=Registrar a informa\u00E7\u00E3o de debug
+ConfigView.section.ipfilter.add=Adicionar
+chat.view.enter.key.msg=Digite a chave do canal para seu bate-papo
+Button.swarmit.tooltip=Buscar arquivos com mesmo tamanho usando Swarm Discoveries
+ConfigView.label.playfilefinished=Tocar um som quando um arquivo est\u00E1 terminado
+MySharesView.type.dircontents=Conte\u00FAdo do Diret\u00F3rio
+ArchivedFilesView.title.full={FilesView.title.full}
+importTorrentWizard.importfile.invalidPath=Arquivo de importa\u00E7\u00E3o inv\u00E1lido 
+TableColumn.header.trackername=Nome do Rastreador
+azbuddy.dchat.status.notavail=Nenhum status dispon\u00EDvel ainda
+br.backup.setup.info=Por favor, considere a cria\u00E7\u00E3o de backup de configura\u00E7\u00E3o autom\u00E1tica.\nVeja Ferramentas-> Op\u00E7\u00F5es-> Backup & Restaurar
+device.itunes.start=Voc\u00EA precisa come\u00E7ar a iTunes ou ativar in\u00EDcio autom\u00E1tico
+ConfigView.section.style.DNDalwaysInIncomplete=Sempre mostrar torrents com arquivos para 'N\u00E3o Baixar' na se\u00E7\u00E3o Incompletos de Meus Torrents
+IPChecker.external.httploadfail=Falha ao carregar a p\u00E1gina
+ConfigView.section.rss=RSS Local etc.
+FileView.BlockView.title=Peda\u00E7os do Arquivo
+MainWindow.menu.view.detailedlist=&Lista Detalhada
+FilesView.rename.failed.title=Renomear/Refazer o Alvo falhou
+PeersView.menu.close=&Fechar 
+ConfigView.section.proxy.group.peer=Comunica\u00E7\u00F5es do Peer
+Files.column.fileext=Tipo
+Subscription.menu.dirtyall=Marcar Todos Os Resultados Como N\u00E3o Lidos
+label.quick.config=Configura\u00E7\u00E3o R\u00E1pida
+dlg.auth.cancelled.line2=Se voc\u00EA sentir que isto \u00E9 um erro, por favor, contacte o suporte indicado em seu email recebido
+label.dblclick.to.min=Clique duplo para Minimizar
+ConfigView.option.dm.dblclick.launch={iconBar.run}
+network.admin.dns.spi.fail=Falha ao instalar o Gerenciador de DNS\n\nIsso vai impactar fun\u00E7\u00F5es como for\u00E7ado preven\u00E7\u00E3o resolu\u00E7\u00E3o dns com SOCKS\n\nErro\: %1
+dlg.auth.cancelled.line1=Sua Ativa\u00E7\u00E3o do Vuze Plus foi cancelado.
+azmsgsync.install.fail.msg=Instala\u00E7\u00E3o do Plugin de Mensagens Sync falhou\: %1
+PeersView.state.established=Completamente estabelecida
+Progress.reporting.action.label.remove.tooltip=Remover este Relat\u00F3rio de Progresso do hist\u00F3rico
+ConfigView.section.style.CatInSidebar=Exibir Categorias na Barra Lateral
+ConfigView.section.style.showdownloadbasket=Mostrar Cesta de Downloads (Arrastar e Soltar .torrents)
+configureWizard.transfer2.rate.changed=Limite da Conex\u00E3o\=%1\nAplicada o limite ser\u00E1 de %2 (m\u00E1x. de torrents ativos\=%3, m\u00E1x. baixando\=%4)
+azbuddy.ui.menu.cat_subs=Assinar
+v3.menu.device.defaultprofile.never=Nunca Transcode
+columnChooser.move=Arraste as linhas para re-orden\u00E1-las
+ConsoleView.title.full=Console 
+azbuddy.beta.enabled=Beta Habilitado
+Plugin.extseed.name=Seeds Externos
+subscriptions.column.auto-download=Download Autom\u00E1tico
+ConfigView.section.file.save.peers.pertorrent=por torrent
+ConfigTransferAutoSpeed.capacity.used=% da Capacidade Usada
+ConfigView.label.seeding.rankType=Colocar os torrents completados para auto-iniciar baseado em\:
+ConfigView.section.mode.intermediate.text=Acesso as fun\u00E7\u00F5es do rastreador.\nUse este modo se voc\u00EA quer criar seu pr\u00F3prio rastreador e hospedar/publicar seus arquivos.
+PiecesView.DistributionView.PeerAvl=Contribui\u00E7\u00E3o Avl do Peer
+configureWizard.transfer2.hint=Configurando seu limite de upload alto demais ou baixo demais ir\u00E1 afetar a performace do download\!
+subs.prop.next_scan=Pr\u00F3ximo scan em
+SpeedView.stats.uploaded=Enviado (Protocolo)
+ConfigView.section.queue.main=Principal
+config.external.browser.test=Testar configura\u00E7\u00E3o do navegador externo
+ConfigView.label.copyanddeleteratherthanmove=Copia e ent\u00E3o apaga os dados originais en vez de mov\u00EA-los em uma opera\u00E7\u00E3o - pode ajudar a evitar a perda de dados em alguns sistemas de arquivos
+OpenTorrentWindow.message=Experimental
+ConfigView.section.logging.level=N\u00EDvel do Log
+ConfigView.section.file.config.section=Configura\u00E7\u00F5es da Configura\u00E7\u00E3o
+ConfigView.section.transfer.lan=LAN
+SpeedTestWizard.test.panel.standard=padr\u00E3o
+ConfigView.section.ipfilter.discardbanning=Bloquear peers cuja propor\u00E7\u00E3o de dados descartados ruins/bons exceder [0\: desativado]
+ConfigView.section.style.colorOverride.altRow=Linhas Alternadas
+SpeedTestWizard.set.upload.hint=Definir os limites de upload e download usados pelo algor\u00EDtmo de AutoVelocidade do Vuze.
+PeerFilesView.title.full={FilesView.title.full}
+DHTTransport.report.resending=re-enviando dados
+Torrent.create.progress.totalfilesize=Tamanho total do arquivo\: 
+GeneralView.label.seeds=Seeds\:
+SpeedTestWizard.test.panel.explain=Mede sua velocidade no protocolo do Vuze. Selecione o tipo de teste de velocidade e o modo de encripta\u00E7\u00E3o. Visite a p\u00E1gina do wiki do Vuze para detalhes sobre este teste. O teste parar\u00E1 automaticamente se ele levar mais do que 2 minutos. Testes t\u00EDpicos terminam em menos de 1 minuto.
+TableColumn.header.md5=MD5
+PeerSocket.mismatch_id=n\u00E3o combinam
+MagnetPlugin.report.secondarylookup.fail=Pesquisa secund\u00E1ria falhou\: n\u00E3o encontrou fontes
+iconBar.startstop.tooltip=Iniciar ou Parar Itens selecionados
+ConfigView.section.tracker.nonblocking=Op\u00E7\u00F5es n\u00E3o-bloqueadoras
+devices.xcode.show.cat=Separar por Categoria
+Button.reload=Recarregar
+wizard.multitracker.edit.deletetracker=Apagar
+MainWindow.status.unknown=desconhecido
+TableColumn.header.tag.rssfeed={label.rss}
+devices.copy_url=Copiar URL da Stream para \u00C1rea de Transfer\u00EAncia
+sharing.progress.hide=Esconder
+ConfigView.section.stats.minutes=min 
+devices.router=roteador
+MainWindow.menu.file.import.keybinding=Meta+I
+Formats.units.Mibit=Mibit
+GeneralView.label.hash.tooltip=Clique para copiar o hash para a \u00E1rea de transfer\u00EAncia
+br.backup.notify=Notifique quando o backup estiver completo
+Content.alert.notuploaded.button.abort=&N\u00E3o Sair
+MyTorrents.column.ColumnProgressETA.StreamReady=Streaming Pronto
+OpenTorrentWindow.mb.noDestDir.text=O diret\u00F3rio destino '%1' para o torrent '%2' n\u00E3o existe ou \u00E9 inv\u00E1lido.
+show.config.changes=Exibir Mudan\u00E7as das Configura\u00E7\u00F5es...
+label.toggle.new.marker=Ver Novo Marcador
+Wizard.Subscription.create.search=Busca
+MainWindow.nat.status.tooltip.unknown=Status para alcan\u00E7ar Firewall/NAT desconhecido (TCP)
+security.cert.auto.install=Instalar automaticamente certificados SSL desconhecidos sem avisar
+ConfigView.section.file.friendly.hashchecking.tooltip=Um levemente mais lento, mais muito menos stressante no cpu/sistema, modo de checagem de hash por peda\u00E7o.
+ConfigView.section.logging.filter=Filtrar quando registrando no arquivo
+MainWindow.menu.view.irc.moved=O Irc est\u00E1 agora dispon\u00EDvel como um plugin, veja http\://azureus.sourceforge.net/plugin_list.php. Quando instalado, use o menu visualizar->plugins->menu IRC para acess\u00E1-lo
+SpeedView.stats.uptime=Tempo de Upload
+ConfigView.section.connection.encryption.encrypt.fallback_incoming=Permitir conex\u00F5es de entrada n\u00E3o encriptadas
+TableColumn.header.trancode_qpos=\#
+Progress.reporting.statusbar.button.tooltip=Mostrar a Janela de Relat\u00F3rio do Progresso
+dlg.try.trial.text=Vuze precisa instalar o plugin necess\u00E1rio para gravar DVDs jog\u00E1veis \u200B\u200Bde seus v\u00EDdeos. Clique em Ativar para continuar.
+ConfigView.section.logging.logdir=Diret\u00F3rio do arquivo de log
+MainWindow.menu.quick_view.msg=Conte\u00FAdo do arquivo '%1' dentro de Download '%2'
+PeersView.client=Cliente
+TableColumn.header.secondsseeding.info=Quantia total de tempo que voc\u00EA esteve fazendo see.
+SpeedTestWizard.name.conf.level.low=Baixa
+remote.pairing.learnmore=<A HREF\="/pairing_learnmore.start">Pareamento FAQs</A>
+label.listen=Ouvir
+ConfigView.label.ignoreCase=Ignorar Mai\u00FAsculas/Min\u00FAsculas
+device.error.copytomissing='Copiar para Pasta' "%1" N\u00E3o encontrado
+devices.xcode.profs=Perfis transcode Dispon\u00EDveis
+config.dialog.shortcut.text=Digite caractere para combina\u00E7\u00E3o com 'control+' para esta se\u00E7\u00E3o, deixe em branco para remover
+ConfigView.label.transfer.ignorepeerports=Ignorar peers com estas portas de dados (';' separadas, ex\: 0;25;100-200)
+exportTorrentWizard.process.torrentfail.title=Falha na Leitura do Torrent 
+MagnetPlugin.report.tunnel=abrindo para %1
+ConfigView.section.ipfilter.enable.descriptionCache=Armazenar as descri\u00E7\u00F5es de IP em arquivo de rascunho
+MainWindow.menu.help.donate=&Fa\u00E7a uma Doa\u00E7\u00E3o \!\!\!
+device.xcode.always=Sempre
+unix.script.new.button.asknomore=N\u00E3o me diga de novo
+MyTorrentsView.menu.setSpeed.disabled=Desativado
+browser.internal.auto.disabled=O navegador interno foi automaticamente desabilitado para impedir o crash do Vuze.\\n\\nVoc\u00EA pode reabilitar via Ferramentas->Op\u00E7\u00F5es->Interface->Exibir\: Navegador Interno\\n\\nPara mais informa\u00E7\u00F5es, veja <A HREF\="http\://wiki.vuze.com/w/Vuze_disappears\#SWT_Browser_Issues">O Wiki</A>
+Button.moveUp=Mover &pra Cima
+MainWindow.menu.file.open.url.keybinding=Meta+L
+DownloadManager.error.sha1=Erro\: Algor\u00EDtmo n\u00E3o encontrado (SHA1)
+ConfigView.pluginlist.column.directory=Diret\u00F3rio
+security.certtruster.issuedby=Emitido Por\:
+ConfigView.section.seeding=Ficar de seed
+ConfigView.tb.delete.torrent=Somente remover da Biblioteca
+ConfigView.section.sharing.protocol=Protocolo para recursos compartilhados
+ConfigView.section.logging.statsinfo=Gerar info das estat\u00EDsticas
+ConfigView.section.transfer.autospeedbeta=Auto-Velocidade-Beta
+wizard.finish=Terminar
+ConfigView.section.connection.udp.enable=Ativar UDP
+subs.prop.is_auto_ok=Auto-download permitido
+network.ipv6.enable.support=Ativar o suporte IPv6 (Java7 exigido no Windows)
+DHTView.general.rendezvous=Encontro\:
+label.searching=Procurando...
+upnp.alert.differenthost=UPnP\: O Mapeamento '%1' foi reservado por '%2' - por favor selecione uma porta\tdiferente
+ConfigTransferAutoSpeed.while.downloading=Baixando\:
+tag.discovery.view.heading=Descobrir Tags
+DHTOpsView.title.full=Gr\u00E1fico DDB
+ClientStats.column.sent={DHTView.transport.sent}
+swt.updater.downloader.downloading=Baixando o SWT de
+TableColumn.header.MediaThumb=M\u00EDdia
+platform.win32.baddll.info=O Vuze detectou a presen\u00E7a de '%1'. Isto \u00E9 parte de '%2' e \u00E9 sabido que causa problemas severos tais como crash no aplicativo e alto uso da CPU.  Se voc\u00EA encontrar estes ent\u00E3o por favor desinstale o software ou configure-o para n\u00E3o afetar o Vuze.
+IrcClient.error=Erro
+MyTorrentsView.menu.reposition.manual=Reposicionar...
+priority.high=Prioridade alta
+tag.share=Compartilhar suas Tags com a Comunidade
+MyTorrents.items.DownSpeedLimit.disabled=Nenhum download
+ConfigView.label.version.info.link=Visite aqui para detalhes sobre quais dados s\u00E3o enviados para o servidor de verifica\u00E7\u00E3o da vers\u00E3o
+br.backup.folder.info=Escolha a pasta que o backup ser\u00E1 gravado
+devices.profile.direct=Direto
+ConfigView.label.start=Iniciar
+IrcClient.joined=entrou
+ConfigView.section.file.torrent.autoskipfiles=Extens\u00F5es de arquivos que n\u00E3o devem ser baixados ao adicionar um torrent [separado por ;]
+label.properties=Propriedades
+device.renderer.remove_all.desc=Voc\u00EA tem certeza que deseja remover todos os Renderers e seus transcodes?
+azbuddy.dchat.info=Bate-papo Descentralizada permite que voc\u00EA converse com outros usu\u00E1rios Vuze diretamente , e, opcionalmente, de forma an\u00F4nima.
+#Used by the webui plugin
+MyTorrentsView.menu.removeand.deletedata=Apagar &Dados
+label.chat=Bate-papo
+ConfigView.section.transfer.autospeed.downadjratio=Taxa da velocidade de Download\:Upload (ex\: 2.0-> o limite da velocidade de download \u00E9 o dobro do limite de upload)
+label.lang.upper.case=Use letras mai\u00FAsculas (ajuda a alinhar a experi\u00EAncia do usu\u00E1rio para aqueles que t\u00EAm "capslock" sempre ativado)
+subscriptions.config.maxresults=N\u00FAmero m\u00E1ximo de resultados retidos por subscri\u00E7\u00E3o [0\: ilimitados]
+label.access.denied=Acesso negado
+wizard.multitracker.edit.title=Editor Multi-Rastreador
+Scrape.status.networkdisabled=Rede n\u00E3o ativada
+wizard.choosetorrent=Por favor escolha o arquivo torrent a criar
+ConfigView.label.info.in.window.title=Exibir taxas atuais e etc. na barra de t\u00EDtulos
+health.explain.green=significa que tudo vai bem.
+MainWindow.menu.speed_limits.info.prof=Defini\u00E7\u00F5es para o perfil '%1'
+Peers.column.UpDownRatio=Up\:Down
+ConfigView.section.tracker.checkip=Auto-descobrir endere\u00E7o IP externo...
+Formats.units.Gibit=Gibit
+ConfigView.pluginlist.uninstallSelected=Desinstalar Selecionado
+dlg.auth.validating.subtitle=Validando
+FilesView.name.fastRename=Renomeamento R\u00E1pido
+security.crypto.reason=Motivo para a opera\u00E7\u00E3o
+GeneralView.label.totalsize=Tamanho Total \:
+ConfigView.section.language.UpdateURL=URL da Atualiza\u00E7\u00E3o
+OpenTorrentWindow.mb.notTorrent.title=Abrir Torrent
+GeneralView.label.totalspeed=Velocidade Total \:
+ConfigView.label.overrideip=N\u00E3o levar em conta o(s) IP(s) de an\u00FAncio do rastreador - semi-v\u00EDrgula os separa se h\u00E1 mais de um para diferentes redes
+seedmore.shareratio=Sua propor\u00E7\u00E3o de compartilhamento neste torrent \u00E9 de
+browser.internal.disabled.info=O navegador interno est\u00E1 desabilitado.\\n\\nIsto ocorreu porque voc\u00EA explicitamente desabilitou via\\n\\n\\tFerrametas->Op\u00E7\u00F5es->Interface->Exibir\: Navegador Interno\\n\\nou foi automaticamente desabilitado em face dos crashs que parecem ocorrer em virtude do componente.\\n\\nO link atual est\u00E1 sendoe xibido abaixo (a p\u00E1gina pode n\u00E3o ser exibida corretamente em face das dep\u00EAndencias do cliente)
+ConfigView.section.connection.encryption.encrypt.fallback_outgoing=Permitir conex\u00F5es de sa\u00EDda n\u00E3o encriptadas se a tentativa de encriptar a conex\u00E3o falhar
+GeneralView.torrent_created_on_and_by=%1 por %2
+MyTorrentsView.menu.manual.shared_torrents=Manual (pelos torrents)
+ConfigView.section.style.useCustomTabs=Usar abas que fecham (precisa reiniciar)
+device.mediaserver.configure=Configurar Meu Servidor de M\u00EDdia
+filter.header.matches2=(Resultados da buscas\: %1, %2 ativo)
+webui.upnpenable=Ativar UPnP para esta porta (*)
+filter.header.matches1=(Resultados da busca\: %1)
+ConfigView.section.mode.intermediate.text1=Mais recursos para controle, optimiza\u00E7\u00E3o e visualizando downloads
+ConfigView.label.open_transfer_bar_on_start=Abrir a Barra de Transfer\u00EAncia ao iniciar
+label.no.download.selected=Nenhum download selecionado
+MainWindow.menu.speed_limits.schedule=Agendar...
+friend.mod.subs=Bot\u00E3o direito do mouse para alterar assinaturas
+MainWindow.menu.window.zoom.maximize=Maximizar
+ConfigView.section.file.save.peers.enable=Salvar as conex\u00F5es com o peer para reconex\u00F5es r\u00E1pidas
+v3.MainWindow.menu.view.pluginbar.keybinding=F8
+DHTView.transport.received=Recebidos
+TableColumn.header.peakdown.info=Vel. M\u00E1x. Alcan\u00E7ado
+azbuddy.tracker.enabled=Ativar a 'Acelera\u00E7\u00E3o do Amigo' para priorizar o download com seus amigos
+OpenTorrentWindow.startMode.queued=Na Fila
+ConfigView.section.mode.beginner.wiki.definitions=Vocabul\u00E1rio BitTorrent
+Wizard.Subscription.optin.description=Com as Subscri\u00E7\u00F5es ativadas, o Vuze mostrar\u00E1 a voc\u00EA subscri\u00E7\u00F5es relacionadas ao conte\u00FAdo na sua Biblioteca e deixar\u00E1 voc\u00EA saber quando seu conte\u00FAdo subscrito est\u00E1 dispon\u00EDvel para download.\n\nVoc\u00EA gostaria de ativar as Subscri\u00E7\u00F5es?
+ConfigView.section.tracker.enablecategories=Separar os torrents por categoria
+IPChecker.external.ipnotfound=Endere\u00E7o IP n\u00E3o encontrado
+tps.type.pex=PEX
+remote.pairing.test.running=Testando conectividade remota ...
+search.export.all=Exportar Todos os modelos de pesquisa ...
+OpenTorrentWindow.simple.open=Local do Torrent (Arquivo, URL, Hash)
+ClientStats.column.discarded={ Peersview.discarded }
+GeneralView.label.updatein.stopped=Parado
+OpenTorrentWindow.mb.askCreateDir.title=O Diret\u00F3rio Destino n\u00E3o existe
+PeersView.downloadspeed=Velocidade de Download
+security.certtruster.yes=Sim
+ConfigView.label.opendetails=Auto-abrir a aba de detalhes
+beta.wizard.version=Voc\u00EA est\u00E1 usando a seguinte vers\u00E3o %1
+ipCheckerWizard.title=Assistente do Verificador de IP 
+LoggerView.excludeAll=N\u00E3o exibir linhas combinando esta express\u00E3o regular\:
+config.browser.internal.disable.info=Isso ir\u00E1 ter impacto em todas as exibi\u00E7\u00F5es que a usem, apesar de alguns podem ser comutado para usar um navegador externo - veja acima
+dlg.auth.revoked.line1=Seu c\u00F3digo de ativa\u00E7\u00E3o do Vuze Plus foi revogado. Por favor clique abaixo para obter mais informa\u00E7\u00F5es.
+tag.type.ds.incomp={label.incomplete}
+TableColumn.header.tracker=Status do Rastreador
+ConfigView.section.file.perf.cache.size.explain=O cache \u00E9 usado para reduzir as leituras do/escritas ao disco. A menos que voc\u00EA esteja usando a op\u00E7\u00E3o java '-XX\:MaxDirectMemorySize' para explicitamente definir a mem\u00F3ria dispon\u00EDvel para ser o cache e a rede IO usar, voc\u00EA deve manter esse valor a pelo menos %1 abaixo do tamanho m\u00E1ximo do seu VM. O tamanho atual m\u00E1ximo do VM \u00E9 %2. Para instru\u00E7\u00F5es sobre como mudar isto, veja MemoryU [...]
+ConfigView.section.proxy.peer.same=Usar as mesmas configura\u00E7\u00F5es de proxy para o rastreador e para as comunica\u00E7\u00F5es com os peers
+download.removerules.unauthorised=Remover torrents n\u00E3o-autorizados automaticamente
+device.rss.view=Clique para exibir RSS feed
+wizard.addingmt=Adicionando informa\u00E7\u00E3o Multi-Rastreador
+TableColumn.header.trancode_qpos.info=Posi\u00E7\u00E3o na fila Transcode
+Progress.reporting.action.label.detail=Detalhes
+importTorrentWizard.importfile.title=Sele\u00E7\u00E3o do Arquivo para Importa\u00E7\u00E3o
+SpeedView.stats.total=Total
+PiecesView.numberofblocks=\# de Blocos 
+MainWindow.menu.view.plugins=&Plugins 
+health.explain.share=significa que o torrent ou est\u00E1 hospedado ou publicado
+torrent.fix.corrupt.result.fixed=Hash de novo torrent de %1 calculado.\nPressione OK para salvar o torrent.
+azneti2phelper.install.text=Instalar o Plugin I2P para ter suporte ao acesso a rede an\u00F4nima I2P?\\n\\n<a href\="http\://wiki.vuze.com/w/I2PHelper_HowTo">Clique para mais informa\u00E7\u00F5es</a>\\n\\nNote que a instala\u00E7\u00E3o pode levar v\u00E1rios minutos para que a\\nrede fique dispon\u00EDvel - seja paciente\!
+Files.column.storagetype=Tipo de Armazenagem
+MainWindow.menu.speed_limits.profiles=Perfis
+ConfigView.section.security.unlockkey.button=Destrancar
+LoggerView.autoscroll=Auto-rolar
+installPluginsWizard.installMode.info.text=Voc\u00EA n\u00E3o precisa de plugins para o Vuze funcionar apropriadamente, eles trazem op\u00E7\u00F5es complementares para divers\u00E3o, automa\u00E7\u00E3o ou controle remoto.\nEnt\u00E3o por favor leia cada descri\u00E7\u00E3o do plugin cuidadosamente antes de decidir instal\u00E1-lo.\nA maioria dos plugins s\u00E3o seguros para testar, apenas n\u00E3o sobrecarregue a sua configura\u00E7\u00E3o com plugins que voc\u00EA n\u00E3o usar\u00E1.
+dht.port=Porta UDP para a base de dados
+plugins.basicview.log=Registro\:
+ConfigView.section.file.max_open_files.explain=Abrir muitos arquivos pode causar problemas no sistema operacional devido aos recursos limitados dos gerenciadores de arquivos. Isto limita o n\u00FAmero de arquivos abertos coincidentes.
+security.certcreate.ok=Criar
+webui.password=Senha
+memmon.low.warning=A mem\u00F3ria \u00E9 fraca, voc\u00EA tem %1 remanescente de %2.\nO desempenho ir\u00E1 se degradar e, finalmente, Vuze vai parar de trabalhar\nVeja <a href\="http\://wiki.vuze.com/w/Java_VM_memory_usage">the Wiki</a> para obter detalhes sobre como aumentar a mem\u00F3ria dispon\u00EDvel.
+installPluginsWizard.installMode.user=Instalar o(s) plugin(s) somente para voc\u00EA
+azbuddy.dchat.log.messages=Registrar Mensagens Em Arquivo
+azbuddy.dchat.link.url=http\://wiki.vuze.com/w/decentralized_chat
+TableColumn.header.readrate.info=Taxa de Leitura do Arquivo
+MySharesView.name=Nome
+ConfigView.label.passwordconfirm=Senha (confirmar)
+PiecesView.priority=Prioridade
+OpenTorrentWindow.xOfTotal=(%1 de %2)
+br.test=Teste
+window.updateswt.cancel=Cancelar
+ConfigView.label.disconnetseed.tooltip=Quando estiver ficando de seed com um torrent, desconectar quaisquer clientes que tamb\u00E9m est\u00E3o ficando de seed.\nEles n\u00E3o precisam estar falando com voc\u00EA.
+configureWizard.file.invalidPath=Diret\u00F3rio inv\u00E1lido
+ConfigView.section.tracker.password=Senha
+v3.deleteContent.applyToAll=Aplicar a a\u00E7\u00E3o a todas as %1 entradas selecionadas
+MagnetPlugin.report.secondarylookup.ok=Pesquisa secund\u00E1ria bem-sucedida
+alert.copy.on.comp.fail=Download %1\nErro ao copiar arquivos completos para '%2'\: %3
+GeneralView.label.maxuploads.tooltip=N\u00FAmero m\u00E1ximo de peers que ser\u00E3o desobstru\u00EDdos a qualquer tempo dado.
+Scrape.status.error.badURL=A URL de an\u00FAncio n\u00E3o obedece \u00E0s especifica\u00E7\u00F5es de scrape.
+exportTorrentWizard.process.outputfileexists.message=O arquivo de sa\u00EDda de dados existe - sobrescrever? 
+cat.share=Compartilhar Categoriza\u00E7\u00E3o com a Comunidade
+ConfigView.section.transfer.lan.downloadrate=Velocidade m\u00E1xima de download na LAN em KB/s [0\: ilimitada]
+Button.remove=Remover
+MyTorrents.bigView.header={sidebar.LibraryDL}
+ConfigView.section.connection.advanced.IPDiffServ=Valor do DiffServ do pacote de sa\u00EDda (campo do TOS)
+SpeedView.stats.now.tooltip=Total (Protocolo)
+ConfigView.label.pause.downloads.on.exit=Pausar downloads ao sair
+device.export.select.template.file=Exportar Dispositivo
+ConfigView.section.security.resetkey.warning=Voc\u00EA tem certeza que voc\u00EA quer resetar suas chaves de encripta\u00E7\u00E3o? Se voc\u00EA o fizer toda a informa\u00E7\u00E3o encriptada usando elas ser\u00E1 PERMANENTEMENTE PERDIDA. Tamb\u00E9m quaisquer outros peers em possess\u00E3o da sua chave p\u00FAblica n\u00E3o mais ser\u00E3o capazes de comunicar com voc\u00EA sem eles obterem sua nova chave. Ent\u00E3o, a menos que voc\u00EA realmente saiba o que voc\u00EA est\u00E1 fazen [...]
+ConfigView.section.connection.nondata.udp.same=Usar a mesma porta UDP para a Base de Dados Distribu\u00EDda e o Rastreador UDP
+label.ctrl.space.for.suggestion=Pressione Ctrl + <espa\u00E7o> para sugest\u00F5es
+iconBar.up=Envio
+ConfigView.label.seeding.fakeFullCopySeedStart.tooltip=Freq\u00FCentemente, torrents com poucas contagens de seeds e muitas contagens de peers querem dizer que provavelmente n\u00E3o s\u00E3o uma c\u00F3pia completa entre os peers.\nPortanto, voc\u00EA pode n\u00E3o querer que as regras de seeding finjam que h\u00E1 uma c\u00F3pia completa (e assim incorretamente reduzindo o seu rank)
+ConfigView.section.file.writemblimit.explain=Quando a velocidade de escrita no disco \u00E9 menor do que a velocidade de download este par\u00E2metro limita quantos dados ser\u00E3o requeridos antes que as velocidades de download sejam reduzidas.
+iconBar.transcode.tooltip=Fazer m\u00EDdia dispon\u00EDvel para um dispositivo
+SpeedTestWizard.set.download.label=Limite da Velocidade de Download\:
+#
+#2.0.7.0
+#
+security.certtruster.title=Alerta do Certificado de Seguran\u00E7a
+ConfigView.label.downloading.reTest=Reavaliar de downloads a cada [min; 0\=nunca]
+general.dont.ask.again=N\u00E3o perguntar de novo
+ConfigView.section.style.dataStatsOnly=Mostrar apenas os dados das estat\u00EDsticas (esconder as estat\u00EDsticas do protocolo)
+SpeedView.title.full=Atividade
+PeersView.download=Down
+TableColumn.header.chat.user.count=Contador de Usu\u00E1rios
+tps.status.unavailable=Indispon\u00EDvel
+subscriptions.column.category={TableColumn.header.category}
+resetconfig.warn.title=Confirme A\u00E7\u00E3o
+ConfigView.pluginlist.column.type.shared=Compartilhado
+Button.upgrade=Atualiza\u00E7\u00E3o
+TorrentOptionsView.param.max.uploads.when.busy=Velocidade m\u00E1xima de upload em KB/s quando o limite global de upload alcan\u00E7ar [0\: desativado]
+authenticator.password=Senha
+v3.deviceview.infobar.line2=Jogue seus v\u00EDdeos em qualquer de suas telas - iPad, iPhone, iPod, TV
+v3.deviceview.infobar.line1=Arrastar e soltar os v\u00EDdeos da sua biblioteca para o dispositivo de sua escolha.
+LocaleUtil.label.hint.doubleclick=Dica\: um duplo clique em uma linha escolhe a codifica\u00E7\u00E3o e fecha a janela 
+fileDownloadWindow.state_downloading=Baixando
+v3.MainWindow.tab.advanced=Avan\u00E7ado
+openUrl.referrer.info=Requerido apenas para sites da web que os pe\u00E7am
+Wizard.Subscription.subscribe.subscriptions=Subscri\u00E7\u00F5es Relacionadas
+ConfigView.option.dm.dblclick.show._windows=Mostrar Arquivo(s) no Explorer
+MyTorrentsView.menu.manual.per_peer=Manual (por peer)
+ConfigView.section.style.colorOverrides=N\u00E3o Levar em Conta as Cores
+device.itunes.install=Voc\u00EA precisa do iTunes instalado
+ConfigView.pluginlist.column.type=Tipo
+ConfigView.section.files=Arquivos
+AdvRenameWindow.message=Digite um novo nome para este download.
+popup.file.finished="%1" terminou de baixar.
+UpdateWindow.columns.version=Vers\u00E3o
+ManagerItem.moving=Movendo
+dhttracker.enable_alt={ConfigView.section.stats.enable}
+wizard.filesaved=Arquivo Salvo.
+exportTorrentWizard.exportfile.title=Exportar Sele\u00E7\u00E3o de Arquivos
+TableColumn.header.seed_to_peer_ratio.info=Total da propor\u00E7a\u00F5 de seeds para peers na multid\u00E3o 
+ManagerItem.stopping=Parando
+ConfigView.section.proxy.peer.informtracker=Informar a limita\u00E7\u00E3o ao rastreador
+MainWindow.menu.transfers.pausetransfersfor.keybinding=Shift + Meta + p
+ConfigView.label.tcplistenport=Porta de escuta da entrada TCP
+TableColumn.header.unopened=Novo
+wizard.newtorrent.byo.help=Construa seu pr\u00F3prio torrent de uma sele\u00E7\u00E3o de arquivos e diret\u00F3rios
+dlg.player.install.subtitle=Instala\u00E7\u00E3o
+SpeedView.stats.autospeed.disabled=Esta op\u00E7\u00E3o ou est\u00E1 desativada (voc\u00EA precisa do DHT) ou n\u00E3o est\u00E1 em uso (velocidade manual de upload selecionada)
+metasearch.addtemplate.failed.title=A Instala\u00E7\u00E3o Falhou
+wizard.multitracker.edit.edit=Editar
+ConfigView.label.hap=Marcar download completo
+DHTView.general.unknown=Desconhecido\:
+ConfigView.label.ignoreSeeds=Ignorar torrents com pelo menos
+PeersView.I2=I (Interessante para o peer)
+label.not.spam=N\u00E3o \u00E9 Spammer
+PeersView.I1=I (Interessado pelo peer)
+azbuddy.ui.table.msg_out=Msg Sai
+TagAddWindow.subtitle=Voc\u00EA pode gerenciar todas as suas tags e categorias por meio de Visualizar->{tags.view.heading}, e descobrir novas tags por meio de Visualizar->{tag.discovery.view.heading}.\n
+label.connections=Conex\u00F5es
+torrent.fix.corrupt=Corrigir Torrent Corrompido ...
+PasswordWindow.title=O Vuze est\u00E1 trancado
+MainWindow.menu.file.create=&Novo Torrent...
+TrackerAvail.column.peers={Trackers.column.peers}
+ConfigView.section.proxy.host=Servidor
+plugins.basicview.clear=Limpar
+ConfigView.label.passwordmatchnone=N\u00E3o
+ConfigView.section.connection.networks.prompt=Alertar para a sele\u00E7\u00E3o quando um download com um rastreador an\u00F4nimo \u00E9 adicionado
+plugin.download.remove.veto.notstopped=O download n\u00E3o pode ser removido se n\u00E3o for parado
+br.backup.auto.retain=N\u00FAmero de backups para manter
+authenticator.torrent=Torrent
+MainWindow.menu.transfers=T&ransfer\u00EAncias
+torrent.comments.info=Coment\u00E1rios e avalia\u00E7\u00F5es recuperadas de outros usu\u00E1rios que baixaram este torrent.\nIsso pode levar algum tempo, especialmente se voc\u00EA acabou de iniciar o Vuze.\n\nRedes Ativas [%1] - mude isso via "Op\u00E7\u00F5es de Conex\u00E3o" nas configura\u00E7\u00F5es.
+OpenTorrentWindow.mb.notTorrent.retry=Pesquisa Magnet
+DHTView.general.replacements=Substitui\u00E7\u00F5es\:
+exportTorrentWizard.torrentfile.title=Sele\u00E7\u00E3o da Entrada de Dados do Torrent
+window.networkselection.info=O torrent listado abaixo tem rastreador(es) que suportam as seguintes redes.\nSelecione aqueles a ativar para a comunica\u00E7\u00E3o com o rastreador e peer.\nSe \u00E9 um rastreador an\u00F4nimo que suporta clientes p\u00FAblicos ative ambas as redes an\u00F4nima e p\u00FAblica.\nAtivar a rede p\u00FAblica tem a consequ\u00EAncia \u00F3bvia de remover a anonimidade\!
+OpenTorrentWindow.torrentTable.saveLocation=Salvar o Local
+dlg.stream.plus.subtitle={Button.upgrade}
+Alert.failed.update.url=http\://wiki.vuze.com/w/failed_update
+ConfigView.section.style.enableXPStyle=Ativar estilo XP (precisa reiniciar)
+MainWindow.dialog.choose.savepath=Escolha o caminho para salvar
+dlg.auth.tos=Eu li e aceito as <A HREF\="tos">Condi\u00E7\u00F5es do Servi\u00E7o.</A>
+label.fails=Falhas
+wizard.torrentFile=Arquivo Torrent
+webui.connectiontest=\tClique para testar a conex\u00E3o
+ConfigView.section.style.colorOverride.error=Erro
+TableColumn.header.chat.msg.count=Contador de Mensagens
+speedtest.wizard.select.bt=Teste de velocidade espec\u00EDfico para Bittorrent
+aznettorbrowser.install.description=Por favor, aguarde enquanto o Plugin para o navegador Tor \u00E9 instalado
+label.move.on.comp=Mover Quando Completo
+ConfigView.section.style.usePathFinder=Usar 'Descobridor de Caminhos' em vez do 'Descobridor'
+ConfigView.tb.delete.ask=Perguntar
+v3.MainWindow.button.start=Iniciar
+FilesView.rename.filename.title=Renomea arquivo
+Button.agree=Eu concordo
+ConfigView.label.defaultstarttorrentsstopped=Por padr\u00E3o adicionar novos torrents no estado parado
+MyTorrentsView.dialog.setFilter.title=Modificar Filtro
+security.certtruster.resource=Recurso\:
+ConfigView.section.connection.encryption=Encripta\u00E7\u00E3o do Transporte
+TableColumn.header.pieces=Peda\u00E7os
+Views.plugins.Distributed.DB.title=Base de Dados Distribu\u00EDda
+upnp.wiki_link=P\u00E1gina do wiki do Vuze sobre o UPnP
+ConfigView.label.queue.minQueueingShareRatio=N\u00E3o requerer ou parar um torrent at\u00E9 que a sua propor\u00E7\u00E3o de compartilhamento atinja
+ConfigView.section.server.enableudpprobe=Habilitar an\u00E1lise de rastreador UDP para rastreadores HTTP
+TableColumn.header.OnlyCDing4.info=Quantia de tempo que o torrent esteve fazendo seed. Exclui o tempo que o torrent estava baixando (e fazendo seed).
+label.incomplete=Incompleto
+torrent.avail.title=Fontes para '%1'
+DHTView.db.title=Base de Dados
+UpdateWindow.status.downloading=Baixando
+ConfigView.section.logging.loggerenable=Ativar logging
+azbuddy.ui.table.con=Con
+Peers.column.Encryption=Encripta\u00E7\u00E3o
+sidebar.header.plugins=Plugins e Extras
+ConfigView.section.br.overview=Configure seus backups requeridos para o Vuze. Isso ir\u00E1 permitir a recupera\u00E7\u00E3o de suas configura\u00E7\u00F5es no caso de um erro s\u00E9rio, tal como um erro no disco.\n\nIf poss\u00EDvel backup para um disco separado do que voc\u00EA normalmente usa o Vuze\!\n\nObserve que as opera\u00E7\u00F5es aqui somente se aplicam as configura\u00E7\u00F5es do Vuze, voc\u00EA precisa administrar o backup dos seus downloads voc\u00EA mesmo.\n\n 
+device.showGeneric=Mostrar dispositivos gen\u00E9ricos
+subscriptions.column.nb-subscribers=Assinantes
+ConfigView.section.style.use_show_parent_folder.tooltip=Ativar esta op\u00E7\u00E3o permitir\u00E1 a voc\u00EA abrir a pasta de conten\u00E7\u00E3o no aplicativo gerenciador de arquivos correto.\nContudo, pode significar que o local para salvar o download n\u00E3o \u00E9 selecionado automaticamente.
+PiecesView.DistributionView.title=Distribui\u00E7\u00E3o dos Peda\u00E7os
+MainWindow.menu.view.mytorrents.keybinding=Meta+1
+window.update.noupdates.text=N\u00E3o h\u00E1 novas atualiza\u00E7\u00F5es dispon\u00EDveis para voc\u00EA.\n\nParab\u00E9ns\!
+chat.view.enter.key.title=Digite a Chave do Canal
+ConfigView.pluginlist.noplugins=Nenhum plugin foi encontrado.
+Views.plugins.aznetstatus.title=Status da Rede
+GeneralView.label.status.pieces_available=Status dos Peda\u00E7os
+ConfigView.section.file.defaultdir.auto=Automaticamente baixar para o diret\u00F3rio padr\u00E3o (Sem Alertar)
+dlg.auth.enter.cancelled=C\u00F3digo de ativa\u00E7\u00E3o atual foi cancelado.
+ConfigView.section.mode.intermediate.wiki.publish=Publicar Arquivos
+SpeedTestWizard.abort.message.failed.peers=Falhou em conectar a quaisquer peers
+ConfigView.section.interface.password={ConfigView.section.tracker.password}
+TableColumn.header.down=Baixado
+tag.type.ipset=Mudar IP
+ConfigView.section.queue.seeding.firstPriority=Primeira Prioridade
+SpeedView.stats.title=Estat\u00EDsticas
+ConfigView.section.transfer.autospeed.minupload.tooltip=A velocidade de upload n\u00E3o ser\u00E1 normalmente diminu\u00EDda abaixo deste limite
+ConfigView.section.ipfilter.list.banned=foi banido
+max.sr.window.message=Digite uma Taxa de Compartilhamento Alvo [0\:desabilitado]
+ConfigView.section.proxy.username=Nome de Usu\u00E1rio
+IPChecker.external.service.dyndns.name=DynDNS 
+azbuddy.dchat.save.messages=Salvar Mensagens Entre Rein\u00EDcios
+ConfigView.section.connection.advanced.info.link=Por favor visite aqui para detalhes
+dht.advanced.label=S\u00F3 corrigir estes valores se voc\u00EA realmente sabe o que voc\u00EA est\u00E1 fazendo
+UpdateWindow.close=Fechar
+wizard.file=Arquivo \:
+SpeedTestWizard.test.panel.label=Teste de velocidade do Vuze\:
+UpdateMonitor.messagebox.restart.text=O Vuze completou o download de uma atualiza\u00E7\u00E3o importante e agora deve ser reiniciado para que a atualiza\u00E7\u00E3o possa ser instalada.
+DHTView.db.direct=Direto
+ConfigView.section.file.readmblimit=M\u00E1ximo de pedidos de leitura requeridos (em %1)
+webui.enable=Habilitar
+beta.wizard.disable.title=Necess\u00E1rio reinstalar
+wizard.multitracker.edit.text=Editar como Texto
+FancyMenu.Header.Organize=Organizar
+trackername.prefs.title=Digite exibi\u00E7\u00E3o preferido para Torrent com Multi-Rastreador
+TableColumn.header.tag.discovery.torrent=Torrent Sugerido Para
+label.reapply=Reaplicar
+Security.jar.signfail=Assinatura JAR falhou - %1
+TagAddWindow.message=Digitar uma nova tag
+v3.activity.remove.text=Voc\u00EA tem certeza de que voc\u00EA quer remover o evento da atividade '%1'?
+label.see.x.for.help=Veja %1 para ajuda
+azbuddy.ui.table.online=Online
+TableColumn.header.sessionup=Envios na Sess\u00E3o
+label.public.chat=Bate-papo P\u00FAblico
+upnp.portchange.alert=As seguintes portas foram mudadas para evitar problemas com dispositivos UPnP\: %1 [porta antiga\=%2] %3 [porta antiga\=%4]
+ConfigView.section.transfer=Transfer\u00EAncias
+ConfigView.label.incrementalfile=Ativar cria\u00E7\u00E3o incremental de arquivo [Requerido para FAT32 no Linux]
+menu.delete.options={iconBar.remove}...
+azbuddy.dchat.status.destroyed=Destru\u00EDdo
+swt.install.window.ok=Instalar
+fileDownloadWindow.downloading=Baixando de \:
+TableColumn.header.AvgAvail.info=Soma da disponibilidade dos peda\u00E7os divididos por \# peda\u00E7os, divididos por \# conex\u00F5es
+wizard.hint.directory=Dica\:\tVoc\u00EA pode escolher um \u00FAnico diret\u00F3rio com Arrastar e Soltar
+PeersView.state.pending=Pendente
+device.view.heading=M\u00EDdia para %1
+PeersView.incomingreqcount.info=Contagem dos pedidos de entrada feitos pelo peer
+v3.MainWindow.menu.advanced=&Avan\u00E7ado
+ConfigView.label.minimizetotray=Minimizar minimiza para o Tray do Sistema
+TableColumn.header.ipfilter=Filtro de IP habilitado
+device.tag=Tag do Dispositivo
+TableColumn.header.path={FilesView.path}
+device.upnp.present_url=Administra\u00E7\u00E3o de Dispositivos
+azbuddy.dchat.ftux.welcome=Bem-vindo ao Bate-papo
+PeersView.C2=O (Obstruindo o peer)
+wizard.maketorrent.piecesize=Tamanho do Peda\u00E7os
+PeersView.C1=O (Obstru\u00EDdo pelo peer)
+ConfigView.section.security.resetcerts.warning.msg=Voc\u00EA est\u00E1 certo que deseja restaurar a armazenagem de certificados? Se voc\u00EA tiver criado um auto-assinado certificado ou manualmente importado qualquer certificado, esses ser\u00E3o perdidos\!
+popup.error.hide=Esconder
+authenticator.savepassword=Lembrar da minha senha
+TableColumn.header.profile.info=Perfil Usado para Transcodificar
+ConfigView.label.stop.Hibernate=Hibernar Computador
+v3.MainWindow.button.pause=Pausar
+ConfigView.label.closetotray._mac=Fechar minimiza para o \u00CDcone da Barra de Status
+SpeedView.stats.idlePing=Ping Inativo\:
+ConfigView.label.showsplash=Mostrar a tela de abertura
+subscriptions.info.avail=Voc\u00EA n\u00E3o adicionou nenhum inscri\u00E7\u00F5es ainda. %1 est\u00E3o dispon\u00EDveis para sua biblioteca.
+webui.protocol=Protocolo (*)
+label.initial_tags=Tags Iniciais
+config.external.browser.switch.implic=Implica\u00E7\u00F5es
+DHTTransport.report.timeout_some=tempo esgotado, %1 pacotes recebidos de %2 mas incompletos
+ConfigView.section.tracker=Rastreador
+exportTorrentWizard.process.exportfail.title=Falha na Exporta\u00E7\u00E3o do Torrent 
+ConfigView.interface.start.advanced=Iniciar na Visualiza\u00E7\u00E3o Avan\u00E7ada (AZ 2.x)
+ConfigView.section.style.TagInSidebar=Exibir Tags na Barra lateral
+ConfigView.section.style.status=\u00C1rea do Status\:
+GeneralView.label.timeelapsed=Tempo Decorrido \: 
+ConfigView.label.passwordmatchyes=Sim
+installPluginsWizard.installMode.title=Por favor, escolha o tipo de instala\u00E7\u00E3o
+ConfigView.section.connection.group.peersources=Fontes Peer
+TableColumn.header.tag.properties={label.properties}
+ConfigView.section.interface.wavlocation.info=Selecione o arquivo .wav ou deixe em branco para o som padr\u00E3o
+DHTView.db.keys=Teclas
+ConfigView.section.file.max_open_files.tooltip=\u00DAtil se voc\u00EA baixa torrents com centenas/milhares de arquivos neles, e se voc\u00EA est\u00E1 atingindo o limite de gerenciamento de arquivos do SO.
+devices.sidebar.mainheader.tooltip=%1 deispositivos est\u00E3o ocultos como generico ou sem tags.\nUse clique direito do mouse  para revelar as op\u00E7\u00F5es
+ConfigView.label.startNumSeeds=\nCome\u00E7ar a ficar de seed se houver menos de\n - N\u00E3o leva em conta todas as outras regras
+ConfigView.section.file.decoder.showall=Considerar todas as codifica\u00E7\u00F5es poss\u00EDveis
+CacheView.writes.hits=Salvos
+TableColumn.header.sha1.info=Hash SHA1 para o arquivo (deve ser totalmente baixado, clique para calcular)
+installPluginsWizard.file.no_such_file=Nenhum arquivo existe com o nome dado.
+installPluginsWizard.finish.explanation=Os plugins selecionados ser\u00E3o instalados usando o Assistente de Atualiza\u00E7\u00E3o.\n\nPor favor seja paciente, isto pode demorar um pouco para aparecer.\n\nPara um relat\u00F3rio do progresso, clique duas vezes a esquerda da barra de status.
+label.current.equals={label.current} %1
+MyTorrentsSubView.title.full=Torrents
+configureWizard.nat.test=Teste
+PeersView.uniquepiece.none=Nenhum
+TableColumn.header.uploadspeed.info=Taxa na qual n\u00F3s estamos enviando dados para o peer
+dlg.auth.install.pct=%1% conclu\u00EDdo
+TableColumn.header.name.info=Nome do torrent
+DHTView.title.full=Base de Dados Distribu\u00EDda
+unix.script.new.button.continue=Eu o farei depois
+ConfigView.section.connection.advanced.read_select=Ler o tempo pra encerrar selecionado (milis, padr\u00E3o %1)
+azneti2phelper.install.subtitle=Instalando Plugin I2P
+devices.restrict_access.prompt=Restringir o acesso ao '%1'
+StartStopRules.firstPriority=1a Prioridade 
+ConfigView.label.stop.Nothing=N\u00E3o fazer nada
+tps.incoming.details=Atual\: TCP\=%1, UDP\=%2; Total\=%3
+MyTorrentsView.menu.movedata.dialog=Escolher novo local
+Peers.column.handshake_reserved=Bytes Reservados para o Handshake
+TableColumn.header.shareRatio.info=Quanto voc\u00EA fez de upload (compartilhou) em compara\u00E7\u00E3o a quanto voc\u00EA baixou.
+dht.override.ip=N\u00E3o levar em conta o endere\u00E7o IP externo
+MyTorrentsView.menu.open_parent_folder=Abrir a Pasta Contendo
+MyTrackerView.downloaded=Baixados
+TransferStatsView.title.full=Transfer\u00EAncias
+azbuddy.dchat.copy.channel.key=Chave do Canal
+wizard.tracker=Rastreador\: 
+ConfigView.section.tracker.passwordwebhttpsonly=S\u00F3 permitir o acesso via HTTPS
+ConfigView.section.style.colorOverride.warning=Aviso
+v3.MainWindow.text.get.started=Se Inicie
+azbuddy.name=Amigos
+TableColumn.header.tracker.info=Status do rastreador
+config.external.browser.switch.search.inf=Requer "Vuze Remote Web 'plug-in; Nenhum resultado web; nenhum modelo de recursos de edi\u00E7\u00E3o; Sem cria\u00E7\u00E3o de assinatura a partir dos resultados
+GeneralView.section.availability=Disponibilidade
+Progress.reporting.detail.history.limit=O limite de mensagens detalhadas (%1) para este ProgressReporter foi excedido; mensagens subsequentes ser\u00E3o adicionadas ao hist\u00F3rico
+Subscription.menu.deleteall=Apagar Todos os Resultados
+Trackers.column.leechers=Leechers
+device.configure=Configurar...
+MainWindow.status.warning.tooltip=Clique aqui para mais detalhes
+MyTorrentsView.menu.browse={azbuddy.dchat.open.in.browser}
+azbuddy.ui.menu.sign=Sinalizar a \u00C1rea de Transfer\u00EAncia
+archive.failed.title=Arquivamento do Download Falhou
+azbuddy.dchat.rchans.ro=Novo Canal S\u00F3 para Leitura
+AllPeersView.title.full=Todos os Peers
+platform.win32.baddll.nvLsp=DA NVIDIA NTUNE / Forceware
+torrent.decode.info.order.bad=Alerta no Torrent\: Torrent '%1' est\u00E1 com formatado incorretamente e pode gerar um hash incorreto.\n\nVeja <a href\="http\://wiki.vuze.com/w/Torrent_Info_Order_Bad">o Vuze Wiki</a> para mais detalhes e possiveis solu\u00E7\u00F5es.
+DHTOpsView.idle=Inativo - aguardando por atividade...
+ConfigView.label.passwordmatch=Senha ativada \:
+ConfigView.label.ircserver=Servidor
+LocaleUtil.title=Escolher Codifica\u00E7\u00E3o
+Plugin.localtracker.wellknownlocals=Automaticamente incluir loopback/link/redes locais de site (192.168 etc)
+ConfigView.label.minimizetotray._mac=Minimizar minimiza para o \u00CDcone da Barra de Status
+ConfigView.section.sharing=Compartilhamento
+config.external.browser.switch.search=Resultados da pesquisa
+ConfigView.dialog.choosemovepath=Por favor, escolha o diret\u00F3rio para o qual mover
+MainWindow.menu.transfers.stopalltransfers=P&arar Todos
+GeneralView.label.averagespeed=m\u00E9dia
+pairing.group.optional=Atributos opcionais
+PiecesView.speed=Velocidade
+Trackers.column.interval=Intervalo
+label.pinned.only=Pinados Somente
+ConfigView.label.movepartialdownloads=Mover mesmo se alguns arquivos est\u00E3o marcados para "N\u00E3o Baixar"
+ConfigView.section.stats.seconds=s
+AllPeers.column.\#=\#
+devices.profile=Perfil
+Peers.column.pieces.info=Barra gr\u00E1fica representando quais peda\u00E7os o peer baixou
+Trackers.column.leechers.info=Leechers na multid\u00E3o
+azbuddy.dchat.noti.sound=Tocar um som quando receber uma mensagem
+subscript.add.upgrade.desc=Voc\u00EA tem certeza que voc\u00EA quer atualizar a subscri\u00E7\u00E3o '%1'?
+MainWindow.menu.speed_limits.info.title=Detalhes do Limites de velocidade
+ConfigTransferAutoSpeed.auto.speed.classic=Auto-Velocidade(cl\u00E1ssica)
+MainWindow.dht.status.unreachabletooltip=Aparenta haver um problema com o mapeamento da porta UDP da Base de Dados Distribu\u00EDda (NAT/firewall)
+TableColumn.header.size.info=Tamanho do conte\u00FAdo do torrent no disco
+configureWizard.transfer.hint=Dica \: Usar um pouco menos do que a velocidade da sua linha \u00E9 a melhor configura\u00E7\u00E3o.
+ConfigView.section.tracker.server.group.networks=Redes
+subscriptions.config.autostartdls=Iniciar automaticamente downloads quando adicionado (ao contr\u00E1rio de coloc\u00E1-los em um estado parado)
+LoggerView.filter.checkAll=Marcar Todas as Categorias
+v3.MainWindow.search.go.tooltip=Executar a Busca
+ConfigView.label.popup.autohide=Automaticamente esconder alertas popup que n\u00E3o s\u00E3o sobre erros ap\u00F3s x segundos (definir em 0 para desativar o auto-esconder)
+pairing.srp.state=Status \:%1
+ConfigView.section.file.deletion.section=Exclus\u00E3o de arquivo
+DownloadManager.error.ioerror=Erro de Entrada/Sa\u00EDda de Dados
+dialog.pause.for.period.text=Pausar download e automaticamente resumi-los em [minutos]
+TrackerAvail.column.seeds={Trackers.column.seeds}
+TableColumn.header.CountryFlag=Bandeira
+wizard.close.message=Voc\u00EA quer que este assistente seja executado na pr\u00F3xima vez que o Vuze for iniciado?
+devices.od.xfering={PeersView.BlockView.Transfer}
+ConfigView.section.style.ShowCatButtons=Exibir Bot\u00F5es de Categorias na Biblioteca
+popup.more.waiting=%1 mais mensagem(ns)..
+ConfigView.section.tracker.pollintervalincby=Aumentar em
+ConfigView.section.file.delete.confirm=Confirmar a exclus\u00E3o de conte\u00FAdo via Barra de Ferramentas e tecla delete
+MainWindow.status.latestversionunchecked=Verifica\u00E7\u00E3o de vers\u00E3o desativada
+ClientStats.column.count=Contador
+TableColumn.header.done=Feito
+v3.MainWindow.button.play=Tocar
+mdi.entry.about.dvdburn=Iniciar
+device.browse=Navegar
+ConfigView.section.file.delete.torrent=Por padr\u00E3o, apagar .torrent quando apagar conte\u00FAdo
+wizard.maketorrents.force=For\u00E7ar inicio do torrent
+ConfigView.section.tracker.main=Principal
+Formats.units.B=B
+MyTorrentsView.menu.setpriority.low=&Baixa
+ConfigView.section.style.status.show_ddb=Status do DDB
+wizard.singlefile=Arquivo \u00FAnico
+ConfigView.label.minSpeedForActiveSeeding=N\u00E3o contar torrent completo como usando um slot se a velocidade for inferior a
+SpeedTestWizard.name.conf.level.absolute=Absoluto
+MainWindow.about.title=Sobre
+LoggerView.realtime=Atualizar em tempo real
+Formats.units.kB=kb
+menu.add.peers={dialog.add.peers.title}...
+ConfigView.section.security.clearpasswords=Resetar as senhas lembradas
+device.rss.port=Porta feed RSS
+remote.pairing.accesscode=C\u00F3digo de acesso\:
+devices.converting=Convertendo
+device.error.copyfail2=Um Ou Mais Arquivos Falharam Ao Copiar Para Dispositivo
+authenticator.title=Autentica\u00E7\u00E3o Requerida
+Formats.units.bit=bit
+label.add.tag=Adicionar Tag...
+tag.type.ds.qfors=Na Fila para Semear
+plugins.init.force_enabled=O Vuze detectou que o plugin "%1" foi desativado - ele foi reativado para permitir que o Vuze trabalhe apropriadamente.
+ActivityView.legend.overhead=Taxa elevada
+TableColumn.header.trackernextaccess.info=Quando o pr\u00F3ximo acesso do rastreador ocorrer\u00E1
+ColumnSetup.explain=Explorar as colunas dispon\u00EDveis a esquerda e adicion\u00E1-las a lista de colunas vis\u00EDveis a direita. Expandir ou retrair a lista de colunas dispon\u00EDveis usando a se\u00E7\u00E3o dos Filtros no parte de baixo a esquerda. Arrastar e Soltar e os atalhos do teclado tamb\u00E9m s\u00E3o suportados. 
+platform.win32.baddll.imon=nod32
+MainWindow.upgrade.section.manual=Atualiza\u00E7\u00E3o Manual
+MyTorrentsView.menu.editTableColumns=&Configura\u00E7\u00E3o das Colunas
+window.updateswt.status.finding=Procurando a \u00FAltima vers\u00E3o da SWT
+MagnetPlugin.current.port=Porta usada para URI
+PeersView.state.connecting=Conectando
+v3.filter-bar=T\u00EDtulo do Filtro\:
+tag.type.ds.qford=Na Fila para Download
+MainWindow.menu.file.share.dir=P&asta...
+ConfigView.section.invalid.value=Valor inv\u00E1lido '%1' digitado para '%2'\: %3
+br.backup.manual.info=Configura\u00E7\u00E3o manual do backup
+MyTorrentsView.menu.manual=&Manual...
+TorrentOptionsView.title.full=Op\u00E7\u00F5es
+azbuddy.dchat.anon.beta=Bate-papo an\u00F4nimo beta (I2P)
+SpeedTestWizard.stage.message.preparing=preparando teste...
+FilesView.numberofpieces=\# de peda\u00E7os
+upnp.alertsuccess=Relatar mapeamentos bem-sucedidos
+fileplugininstall.duplicate.desc=O Plugin '%1', vers\u00E3o %2 j\u00E1 est\u00E1 instalado
+DHTView.activity.status.false=Rodando
+pairing.group.srp=Op\u00E7\u00F5es de emparelhamento seguro
+plugin.init.load.failed.classmissing=Desisntale o plugin via 'Ferramentas->Plugins->Assistente de Desisntala\u00E7\u00E3o' e ent\u00E3o reistanle elel
+ConfigView.section.security.resetcerts=Restaurar armazenagem de certificados (ir\u00E1 reiniciar o Vuze)
+platform.win32.baddll.nl_lsp=Netlimiter
+ConfigView.label.directory=Diret\u00F3rio
+MyTorrentsView.menu.queue=&Fila
+MainWindow.about.internet.wiki=FAQ e Wiki do Vuze
+platform.jvmopt.accesserror=Falha ao acessar op\u00E7\u00F5es do JVM no arquivo\: %1
+MainWindow.dialog.choose.savepath_forallfiles=Escolha o caminho para salvar TODOS os arquivos
+VivaldiView.title.full=Vivaldi
+devices.sidebar.show.only.tagged=Exibir somente dispositivos com tags
+ConfigView.section.proxy.show_icon.flag.incoming=Exibir n\u00E3o-locais, n\u00E3o-SOCKS conex\u00F5es de entrada como estado de erro
+ConfigView.label.movecompleted=Mover arquivos completados (ap\u00F3s o download)
+PiecesView.reservedby=Reservado
+dialog.pause.for.period.text2=Auto-resumir ativo\: %1 restante...
+splash.unloadingTorrents=Descarregando Torrents
+OpenTorrentWindow.tlf.rename=Renomear Torrent com mudan\u00E7a na pasta de n\u00EDvel superior
+Peers.column.DLedFromOthers.info=Quantidade de dados recebidos de outros enquanto conectados a voc\u00EA
+azbuddy.dchat.copy.magnet=Copiar Magnet Para \u00C1rea de Transfer\u00EAncia
+devices.always.cache=Cache de arquivos  n\u00E3o-transcodificado 
+ConfigView.section.security.nopw_v=Nenhuma senha dispon\u00EDvel, por favor logue no Vuze
+configureWizard.nat.unable=Incapaz de testar\: Porta inv\u00E1lida dada, ou o teste do servi\u00E7o falhou.\nOutro aplicativo j\u00E1 pode estar usando esta porta.
+ConfigView.section.ipfilter.autoload.file=Arquivo de filtro de IP para auto-carregar
+ConfigView.label.popupdownloadadded=Mostrar um alerta quando um download \u00E9 adicionado
+label.private.chat=Bate-papo Privado
+azbuddy.ui.table.msg_in=Msg Entra
+DonationWindow.noload.title=Doa\u00E7\u00E3o
+MyTorrentsView.menu.export=&Torrent XML...
+TableColumn.header.ProgressETA=Progresso
+TableColumn.header.sizewithdnd.info=Tamanho dos dados do torrent, se voc\u00EA baixasse todos os arquivos
+platform.jvmopt.sunonly=Somente Sun JVMs s\u00E3o suportadas (vers\u00E3o atual\=%1)
+window.updateswt.ok=OK
+Subscription.menu.properties=Propriedades
+v3.MainWindow.menu.browse=&No Vuze
+security.certcreate.org=Organiza\u00E7\u00E3o
+ConfigView.section.transfer.select=Auto-Velocidade
+Views.plugins.Distributed.Tracker.title=Rastreador Distribu\u00EDdo
+ClientStats.column.received={DHTView.transport.received}
+beta.wizard.info=Se inscrevendo para o uso das vers\u00F5es beta do Vuze, voc\u00EA ter\u00E1 acesso a recursos que est\u00E3o por vir para ele.\n\nIsso lhe d\u00E1 a chance de experimentar esses recursos e nos ajudar a melhorar a sua implementa\u00E7\u00E3o - seu retorno \u00E9 de grande ajuda para n\u00F3s\!\n\nPor ser uma vers\u00E3o beta, pode ser inst\u00E1vel, de qualquer forma, selecionando essa op\u00E7\u00E3o dar\u00E1 a voc\u00EA o acesso a vers\u00F5es relativamente est\u00E1v [...]
+security.crypto.password=Senha
+popup.download.added="%1" foi adicionado a sua lista de downloads.
+iconBar.remove.tooltip=Remover
+TableColumn.header.tag.name=Nome da Tag
+Peers.column.UpRatio=Propor\u00E7\u00E3o de Upload
+dlg.stream.plus.text=Atualizar para o Vuze Plus e reproduza seus v\u00EDdeos que est\u00E3o baixando.
+LocaleUtil.label.checkbox.rememberdecision=Lembrar a decis\u00E3o para os nomes de arquivos restantes
+DHTView.operations.received=Recebidos
+download.removerules.removed.ok=Remo\u00E7\u00E3o autom\u00E1tica do torrent '%1' bem-sucedida. Isto foi causado pelas regras de remo\u00E7\u00E3o de torrents
+ConfigTransferAutoSpeed.data.update.frequency=Frequ\u00EAncia da Atualiza\u00E7\u00E3o
+TableColumn.header.tag.initsaveloc={label.init.save.loc}
+TableColumn.header.torrentpath=Local do Torrent
+MyTorrents.column.ColumnProgressETA.PlayableIn=Toc\u00E1vel em %1
+iconBar.showDownloadBar.tooltip=Mostrar a Barra de Downloads
+dht.execute.command=Comando de diagn\u00F3stico
+TableColumn.header.pieces.info=Barra gr\u00E1fica representando quais peda\u00E7os voc\u00EA baixou
+Progress.reporting.default.error=Falhou
+SpeedTestWizard.abort.message.manual.abort=Manualmente abortado
+DHTView.activity.target=Alvo
+v3.deviceview.infobar.line2.psp=V\u00EDdeos ser\u00E3o copiados para o PSP quando ele est\u00E1 conectado.
+platform.win32.baddll.nvappfilter=nvidia Firewall
+ConfigView.label.maxuploadspeed=Velocidade m\u00E1xima global de upload em KB/s [0\: ilimitada]
+ConfigView.label.passwordmatchno=N\u00E3o / As senhas n\u00E3o combinam
+IrcClient.defaultChannel=\#Usu\u00E1rios-do-Azureus
+devices.cat.show=Exibir Categorias
+MyLibrary.bigView.header={sidebar.Library}
+configureWizard.finish.title=Completado
+ConfigTransferAutoSpeed.adjustment.interval=Intervalo do ajuste\:
+ConfigView.label.peers=peers
+jvm.show.file=As op\u00E7\u00F5es locais do arquivo JVM \u00E9 '%1' - Somente edite diretamente para prop\u00F3sitos de recupera\u00E7\u00E3o
+MyTorrentsView.menu.setSpeed.unlimited=Ilimitado
+TableColumn.header.downspeed.info=Velocidade de download atual
+security.certcreate.strength=For\u00E7a
+ConfigView.text.neverStop=Nunca Parar
+ConfigView.label.startwatchedtorrentsstopped=Iniciar parado
+UpdateWindow.title=Atualizador do Vuze
+MyTorrentsView.\#=\# 
+TableColumn.header.RateIt=Taxa
+label.show.selected.rates=Exibir Propor\u00E7\u00E3o dos Itens Selecionados
+label.tracker.selection=Sele\u00E7\u00E3o de Rastreador
+ConfigView.label.seeding.rankType.peer.tooltip=mais peers e menos seeds \= higher rank\nEste ranking minimiza o n\u00FAmero de torrents que precisam ser mantidos ativos para maximizar o upload
+subs.prop.enabled={azbuddy.enabled}
+Main.parameter.maxUploads=N\u00BA m\u00E1ximo de uploads simult\u00E2neos
+ConfigView.label.downloading.info=Automaticamente ajusta a posi\u00E7\u00E3o da fila de downloads para que trabalhe da melhor forma para que voc\u00EA tenha uma melhor m\u00E9dia geral de download baseado na ativade de sua rede
+ConfigView.label.bStartNoMoreSeedsWhenUpLimitMetSlack=Carregar limite aproxima\u00E7\u00E3o (percentagem ou redu\u00E7\u00E3o absoluta em KB/s)
+general.enter.cookies=Digitar Cookies
+TableColumn.header.maxuploads=M\u00E1x de \# Uploads
+wizard.invalidurl=Esta URL n\u00E3o \u00E9 v\u00E1lida
+ConfigView.section.tracker.client.scrapestoppedenable=Scrape torrents que n\u00E3o est\u00E3o rodando
+SpeedView.stats.con_details=total\=%1, desobstru\u00EDdo\=%2, enfilerado\=%3, bloqueado\=%4
+speedtest.wizard.select.group=Tipo de teste
+PeersView.T.R.tooltip=O peer estabeleceu a conex\u00E3o
+config.external.browser=Navegador Externo
+v3.deviceview.infobar.line2.ps3=Transmitir v\u00EDdeos, indo para o seu PS3 e selecionando V\u00EDdeos -> Vuze.
+ConfigView.section.transfer.lan.uploadrate=Velocidade m\u00E1xima de upload na LAN em KB/s [0\: ilimitada]
+TableColumn.header.Country=Pa\u00EDs
+upnp.selectedaddresses=Endere\u00E7os (';' separados, '-' prefixo\=negar, '+' \=permitir) [em branco\: qualquer um]
+wizard.newtorrent.byo.editname.text=Digite o nome do item que aparece no torrent
+fileDownloadWindow.saveTorrentIn=Salvar Arquivo Torrent Em 
+label.announce=An\u00FAncio
+devices.choose.profile.title={devices.choose.device.title}
+StartStopRules.waiting=Aguardando
+ConfigView.label.seeding.rankType.peerSeed.tooltip=Maior Propor\u00E7\u00E3o \= Maior Rank
+cat.upload.priority=Prioridade de Upload
+ConfigView.section.transfer.autospeed.enableauto=Ativar quando baixando e ficando de seed
+PeersView.menu.kickandban.reason=Peer banido manualmente
+FancyMenu.Header.Social=Social
+label.uptime_coarse=Tempo de Up%1%2
+ConfigView.section.transfer.lan.downloadrate.tooltip=Conex\u00F5es com os peers dentro da mesma LAN interna tem um limite de taxa de download separado.
+ConfigView.label.userequestlimiting=Usar pedido de throttling em vez de leituras atrasadas para limitar a velocidade de download [sem efeito quando a velocidade de download \u00E9 ilimitada]
+MyTorrentsView.dialog.NumberError.text=O n\u00FAmero que voc\u00EA inseriu \u00E9 inv\u00E1lido ou n\u00E3o reconhecido.
+security.crypto.encrypt=Por favor insira uma senha para proteger sua chave de encripta\u00E7\u00E3o gerada recentemente. Por favor n\u00E3o esque\u00E7a esta senha, n\u00E3o h\u00E1 meio de recuper\u00E1-loa se voc\u00EA esquecer\!
+button.nothanks=N\u00E3o, obrigado
+Peers.column.handshake_reserved.info=Indica quais bits reservados foram definidos no handshake BT
+webui.pairingtest=\tClique para testar o emparelhamento
+exportTorrentWizard.torrentfile.path=Caminho
+ConfigView.label.queue.retainforce=Transi\u00E7\u00E3o 'for\u00E7ar Inicio' download para 'for\u00E7ar semear' quando completo
+UpdateWindow.restartLater=Reiniciar Mais Tarde
+devices.turnon.prepageload=Para ativar esse recurso, instala\u00E7\u00E3o de componentes extras \u00E9 requerida.
+min.sr.window.title=Taxa M\u00EDnima de Compartilhamento
+azbuddy.dchat.anon.share.endpoint=Compartilha torrent an\u00F4nimo e destino do bate-papo
+ConfigView.section.file.max_open_files=M\u00E1ximo de arquivos abertos para leitura/escrita\n[0\: ilimitados]
+device.manu.desc=Fabricante
+SubscriptionWizard.column.SubWizName={FilesView.name}
+TableColumn.header.eta=TEC
+devices.choose.device.info.text=Da pr\u00F3xima vez, basta arrastar e soltar arquivos para o dispositivo de sua escolha na barra lateral.
+ConfigView.section.tracker.announcecacheminpeers=Anunciar cache e ativar in\u00EDcio do peer 
+ConfigView.label.openconfig=Abrir as op\u00E7\u00F5es na inicializa\u00E7\u00E3o
+OpenTorrentOptions.header.torrentinfo=Informa\u00E7\u00F5es do Torrent
+ConfigView.section.style.defaultSortOrder.asc=Ascendente
+GeneralView.section.downloaded=Baixados
+wizard.multitracker.title=Multi- Rastreador
+swt.uninstall.window.header=Os seguintes componentes foram selecionados para a remo\u00E7\u00E3o \:
+FileItem.donotdownload=N\u00E3o baixar
+ipCheckerWizard.explanations=Voc\u00EA pode usar este assistente para descobrir qual \u00E9 o seu endere\u00E7o IP externo. Se o seu endere\u00E7o IP \u00E9 din\u00E2mico, n\u00F3s recomendamos que voc\u00EA abra uma conta com um Servi\u00E7o de DNS Din\u00E3mico. Alguns destes servi\u00E7os est\u00E3o listados abaixo, use o link fornecido para criar uma conta (quando suportado). Ent\u00E3o preencha o campo do endere\u00E7o IP com o nome do seu servidor din\u00E2mico (ex\: nomedomeuhost. [...]
+FilesView.menu.setpriority.skipped=&N\u00E3o baixar
+MainWindow.menu.speed_limits=Limite de Velocidade
+IrcClient.hasjoined=entrou
+ConfigView.section.queue=Filas
+TagAddWindow.public.checkbox=Compartilhar tag an\u00F4nimamente com a comunidade
+PeersView.discarded.info=Dados que voc\u00EA de alguma forma recebeu embora voc\u00EA n\u00E3o precisasse deles, ent\u00E3o voc\u00EA se livrou deles.
+group.auto=Autom\u00E1tico
+ConfigView.section.connection.group.networks.info=Selecione as redes padr\u00E3o permitidas para a transmiss\u00E3o de dados peer-peer
+label.con_prob=Problemas na Conex\u00E3o
+MyTrackerView.status.started=Rodando
+device.config.xcode.disable_sleep=Impedir o computador de hibernar enquanto transcodifica
+ConfigView.label.minSpeedForActiveDL.tooltip=Um slot de download \u00E9 sempre usado para os 30 segundos iniciais\nap\u00F3s o torrent incompleto iniciar.
+azbuddy.dchat.nick.shared=Apelido\: compartilhado
+TableColumn.header.eta.info=Tempo estimado antes que seja feito o download do torrent 
+MainWindow.menu.torrent=T&orrent
+MainWindow.menu.transfers.pausetransfersfor=Pausar Por...
+exportTorrentWizard.finish.message=Exporta\u00E7\u00E3o conclu\u00EDda com sucesso 
+label.show.all=Exibir Tudo
+TableColumn.header.torrentrelpath.info=Localiza\u00E7\u00E3o relativa do arquivo no torrent
+TableColumn.header.tag.uplimit={TableColumn.header.maxupspeed}
+authenticator.realm=Dom\u00EDnio
+MySharesView.type=Tipo
+dlg.stream.plus.renew.subtitle=Renova\u00E7\u00E3o do Vuze Plus
+PeerSocket.unknown_az_style=Desconhecido %1 %2
+ConfigView.section.connection.advanced.write_select=Gravar o tempo pra encerrar selecionado (milis, padr\u00E3o %1)
+splash.initializeGui=Inicializando a Janela Principal
+upnp.ignorebaddevices.info=Dispositivos atualmente ignorados\: %1
+ConfigView.label.showuptime=Exibir Tempo de Upload
+ConfigView.label.seeding.ignore0Peers=Ignorar torrents com 0 peers
+devices.cancel_xcode_del=Cancelar Convers\u00E3o/Remover
+manual.mode=Manual
+label.pin=Pinar
+ipCheckerWizard.service.url=Link\: 
+ConfigView.section.proxy.show_icon=Mostrar \u00EDcone SOCKS na \u00E1rea de status quando ativado
+azbuddy.ui.table.loc_cat=Tags/Cats para
+splash.of=de
+OpenTorrentOptions.show.always=todas as vezes
+plugins.basicview.progress=Progresso\:
+resetconfig.warn=Isto ir\u00E1 resultar em que todas as modifica\u00E7\u00F5es feitas na configura\u00E7\u00E3o Vuze sendo perdida.\nProsseguir com a redefini\u00E7\u00E3o de configura\u00E7\u00E3o?
+ConfigView.section.connection.encryption.encrypt.fallback_info=Ativando-a a op\u00E7\u00E3o de retorno permitir\u00E1 conex\u00F5es com clientes incompat\u00EDveis MAS resultar\u00E1 em conex\u00F5es n\u00E3o encriptadas
+dlg.auth.install.subtitle.plus=Instalando Vuze Plus...
+OpenTorrentOptions.show.many=Somente quando houver mais de 1 arquivo
+ConfigView.pluginlist.column.version=Vers\u00E3o
+MyTorrentsView.menu.exportmenu=Exportar\t\t\t\t\t\t\t\t\t\t\t\t\t 
+ConfigView.section.connection.encryption.encrypt.info.link=Por favor visite aqui para detalhes
+MyTorrentsView.menu.moveUp=&Para Cima
+MyTorrents.column.ColumnProgressETA.2ndLine=TEC\: %1
+label.spam=Spammer
+v3.MainWindow.button.delete=Apagar
+MainWindow.status.updowndetails.tooltip=Detalhes da velocidade de Download/Upload\nClique com o bot\u00E3o direito para mudar, clique 2 vezes para abrir as estat\u00EDsticas
+Column.seedspeers.started.over=%1
+exportTorrentWizard.torrentfile.invalidPath=Arquivo torrent inv\u00E1lido
+MyTorrentsView.menu.rename.save_path=Renomearo Caminho para Salvar
+Subscription.menu.upgrade=Ativar A Atualiza\u00E7\u00E3o Para A Vers\u00E3o Maior
+installPluginsWizard.file.title=Por favor procure o plugin que voc\u00EA quer instalar
+ConfigView.section.security.publickey.undef=N\u00E3o definida ainda
+MyTorrentsView.menu.tracker=Rastreador/Torrent
+MainWindow.statusText.checking=Procurando por Atualiza\u00E7\u00F5es
+view.one.download.only=Selecione um download para ser mostrado nesta exibi\u00E7\u00E3o
+upnp.refresh.label=Atualizar os mapeamentos
+swt.install.window.header=Os seguintes componentes foram selecionados para a instala\u00E7\u00E3o \:
+ManagerItem.stopped=Parado
+platform.win32.baddll.InjHook12=Torrent Ratio Keeper
+Button.dismiss=Rejeito
+UpdateWindow.ok=Atualizar
+ConfigView.pluginlist.info=Os seguintes plugins foram identificados.  Alguns plugins podem n\u00E3o ter abas de configura\u00E7\u00E3o.
+security.crypto.title=Acesso a Chave de Encripta\u00E7\u00E3o
+MainWindow.about.internet.homepage=Home page do Vuze
+network.enforce.ipbinding=Refor\u00E7ar as amarras ao IP mesmo quando as interfaces n\u00E3o est\u00E3o dispon\u00EDveis, impede quaisquer conex\u00F5es se nenhuma das interfaces especificadas est\u00E3o dispon\u00EDveis
+dlg.corewait.text=Um Momento Por Favor...\n\nSeu pedido ir\u00E1 ser processado depois do Vuze tiver completado a inicializa\u00E7\u00E3o
+StartStopRules.menu.viewDebug=Ver Informa\u00E7\u00F5es de Debug
+label.num.torrents=%1 {ConfigView.section.torrents}
+ConfigView.section.transfer.autospeed.enableautoseeding=Ativar apenas quando ficando de seed
+FilesView.path=Caminho
+br.restore.warning.title=Aviso de Perda de configura\u00E7\u00E3o\!
+subscriptions.search.enable=Permitir a pesquisa de resultados da assinatura (\u00E9 necess\u00E1rio reiniciar)
+chat.view.create.chat=Criar Bate-papo
+ConfigView.label.prioritizefirstpiece.tooltip=Tenta baixar o come\u00E7o e o fim de um arquivo primeiro.\nPara o suporte de pr\u00E9-visualiza\u00E7\u00E3o.
+update.now.desc=Vuze precisa para aplicar as atualiza\u00E7\u00F5es para concluir a migra\u00E7\u00E3o.\n\nDepois de fechar esta caixa de di\u00E1logo pode ser solicitado pelo Windows para completar o processo de atualiza\u00E7\u00E3o.\n\nUm rein\u00EDcio do Vuze n\u00E3o ser\u00E1 necess\u00E1rio.
+iconBar.openURL.tooltip=Abrir uma URL
+ConfigView.label.xfer.bias_no_limit=Tentar aplicar comportamento quando n\u00E3o houver limite de upload global eficaz
+ConfigView.label.startRatioPeers=Come\u00E7ar a ficar de seed quando houver menos de 1 seed para
+CacheView.general.inUse=Em Uso
+#file can be a URL or a path in the jar
+MainWindow.menu.help.releasenotes=Notas do Lan\u00E7amento
+Main.parameter.maxSpeed=Velocidade m\u00E1xima de upload em bytes/seg
+TableColumn.header.CountryCode=CP
+option.rememberthis=Lembre-se esta defini\u00E7\u00E3o
+ConfigView.title.short=Op\u00E7\u00F5es
+FileItem.storage.reorder=Reordenar
+TableColumn.header.completion=Conclus\u00E3o
+subscriptions.config.ratelimits=Taxa limite\: lista de <host>\=<minutos no m\u00EDnimo>pares, separado por v\u00EDrgula
+v3.menu.device.exploreTranscodes=Mostrar arquivos
+TableColumn.header.commenticon=\u00CDcone do Coment\u00E1rio
+label.help=Ajuda
+pairing.view.registered=Clique para exibir os detalhes do registro atual
+ConfigView.dialog.choosewatchtorrentfolderpath=Por favor, escolha o diret\u00F3rio de importa\u00E7\u00E3o dos .torrents
+ConfigView.label.seeding.preferLargerSwarms.tooltip=Se voc\u00EA est\u00E1 ficando de seed principalmente com torrents com peers que est\u00E3o "travados", preferir multid\u00F5es maiores faz sentido\nQuando voc\u00EA est\u00E1 ficando de seed principalmente com torrents com alta disponibilidade, preferir multid\u00F5es menores faz sentido.
+ConfigView.section.interface.cleartrackers=Limpar os rastreadores lembrados
+label.bar.trans=Barra de transpar\u00EAncia [0\=opaco;100\=transparente]
+device.playnow.buffer=Tamanho do buffer antes da reprodu\u00E7\u00E3o come\u00E7ar [seg]
+MainWindow.menu.help.plugins=Plugins
+proxy.socks.bad.incoming=Conex\u00F5es de entrada n\u00E3o-proxy detectado\!
+v3.activity.remove.title=Remover a Entrada da Atividade
+TrackerAvail.column.status={Trackers.column.status}
+menu.selectfilesinfolder=Selecionar todos os arquivos em %1
+sidebar.LibraryDL.tooltip=Tem %1 torrent incompleto(s), %2 dos quais est\u00E1/est\u00E3o baixando
+devices.activation=Ativando Dispositivo
+OpenTorrentFile.column.size={TableColumn.header.size}
+MyTrackerView.status=Status
+sidebar.top.level.gap=Espa\u00E7o entre as linhas de cabe\u00E7alhos ({ConfigView.section.security.restart.title})
+ConfigView.section.transfer.lan.enable=Ativar os limites de velocidade separados para as conex\u00F5es LAN 
+TableColumn.header.filesdone.info=Arquivos feitos/Total dos arquivos *ou* arquivos n\u00E3o-ignorados feitos (Arquivos feitos)/Total de arquivos n\u00E3o-ignorados (Total de arquivos)
+ConfigView.section.connection.advanced.SO_RCVBUF=Tamanho do Socket SO_RCVBUF [0\: usar o padr\u00E3o do SO]
+ConfigView.section.connection.advanced=Configura\u00E7\u00F5es de Rede Avan\u00E7adas
+TableColumn.header.tag.discovery.name=Sugest\u00E3o de Tag
+MainWindow.upgrade.section.automatic=Atualiza\u00E7\u00E3o Autom\u00E1tica 
+TrackerView.title.full=Fontes
+azbuddy.dchat.open.in.browser=Abrir no Navegador
+FileItem.delete=Apagar
+ConfigView.section.connection.pairing.url=http\://wiki.vuze.com/w/ug_options \# Emparelhamento
+ConfigView.label.bindip=Prender ao endere\u00E7o IP local
+MyTorrentsView.menu.exporttorrent=Torrent...
+core.shutdown.se=seeding completados
+Button.sendNow=Enviar Agora
+subs.prop.auth=Autentica\u00E7\u00E3o requerida
+wizard.hint.file=Dica\:\tVoc\u00EA pode escolher um \u00FAnico arquivo com Arrastar e Soltar
+upnp.mapping.udptrackerport=Porta do Rastreador UDP
+label.click.to.change=Clique para mudar
+window.updateswt.text=Sua vers\u00E3o do SWT \u00E9 muito antiga\!\nA SWT \u00E9 a biblioteca gr\u00E1fica usada pelo Vuze, e a vers\u00E3o que voc\u00EA tem \u00E9 muito antiga para rodar a \u00FAltima vers\u00E3o do Vuze. Clique no bot\u00E3o OK para atualizar sua SWT.
+wizard.tracker.ssl=Usar SSL
+security.certcreate.cancel=Cancelar
+ConfigView.section.tracker.publishenable=Publicar detalhes do torrent para "<tracker_url>"
+MyTorrents.column.ColumnSpeed=Velocidade
+deletecontent.also.deletetorrent=Apagar .torrent  tamb\u00E9m
+externalLogin.title=Login Requerido
+ConfigView.section.tracker.client.showwarnings=Mostrar mensagens de aviso reportadas pelos rastreadores
+label.DNS=DNS
+TorrentOptionsView.param.upload.priority=Carregar prioridade [0\=padr\u00E3o;1\=priorizado]
+dlg.auth.enter.link.try.2=<A HREF\="link">Clique Aqui</A>se voc\u00EA n\u00E3o tiver comprado sua c\u00F3pia do Vuze Plus ainda.
+dlg.auth.enter.link.try.1=Voc\u00EA n\u00E3o tem c\u00F3digo de ativa\u00E7\u00E3o? <A HREF\="atualizar">Atualizar agora</A>.
+chats.view.heading=Vis\u00E3o geral do bate-papo
+config.dialog.shortcut.title=Configurar Atalho no Teclado
+Button.clear=Limpar
+Peers.column.UpDownRatio.info=A Propor\u00E7\u00E3o "Enviado \: Baixado" do Peer
+ConfigView.label.seeding.firstPriority.FP=Primeira Prioridade
+subs.prop.update_period=Per\u00EDdo de atualiza\u00E7\u00F5es
+tray.options=Op\u00E7\u00F5es de bandeja
+GeneralView.label.swarm_average_completion=Conclus\u00E3o em M\u00E9dia\:
+TableColumn.header.azsubs.ui.column.subs_link=Associa\u00E7\u00E3o
+ConfigView.label.bStartNoMoreSeedsWhenUpLimitMet=N\u00E3o inicie nenhum torrent mais para semeamento quando o limite de upload global se encontrar
+ConfigView.section.ipfilter.edit=Editar
+device.od.error.opfailstatus=Dispositivo falhou ao processar o comando %1\: status %2
+OpenTorrentWindow.fileTable.fileName=Nome do Arquivo
+azbuddy.dchat.open.magnet=Abrir Magnet No Vuze
+ConfigView.section.language.enableUpdate=Ativar Atualiza\u00E7\u00E3o via Web
+dht.info=Este plugin suporta rastreamento descentralizado, entre outras coisas, - desativando-o reduzir\u00E1 a sua habilidade de baixar
+library.unopened.header.p=%1 itens
+DevicesOD.column.od_remaining={TableColumn.header.remaining}
+label.num_queued=%1 na fila
+FileView.BlockView.Outstanding=Pendente
+ConfigView.section.file.delete.include_files_outside_save_dir=Quando apagar dados, permitir que arquivos ligados fora do diret\u00F3rio do torrent tamb\u00E9m sejam removidos
+ConfigView.button.browse=&Procurar...
+device.error.copyfail=Um Ou Mais Arquivos Falharam Ao Copiar Para Pasta
+PeersView.piece=Peda\u00E7o
+download.removerules.unauthorised.seedingonly=\tApenas se ficar de seed
+dlg.auth.revoked=C\u00F3digo de Ativa\u00E7\u00E3o Revogado
+br.restore.warning.info=Restaurando sua configura\u00E7\u00E3o ir\u00E1 substituir completamente o seu j\u00E1 existente.\nConsidere fazer o backup de ante-m\u00E3o\!
+security.crypto.decrypt=Por favor insira sua senha para destrancar sua chave de encripta\u00E7\u00E3o.
+custom.settings.import.res=Importado %1 configura\u00E7\u00F5es.%2
+label.missing=Desaparecido
+ConfigView.section.server=Conex\u00E3o
+TrackerChangerWindow.newtracker=Digite nova url do tracker(es) - separado por v\u00EDrgula, se mais de um
+config.external.browser.switch.info=Voc\u00EA pode mudar de navegador interno para externo para alguns recursos, embora algumas funcionalidades podem ser perdidas
+tag.type.ds=Estado do Download
+TableColumn.header.transcode_status={TableColumn.header.status}
+security.crypto.persist_for.dont_save=N\u00E3o salvar
+general.add.friends=Adicione alguns amigos\!
+FilePriority.invalid.title=Prioridade inv\u00E1lida
+tag.type.ds.act={FileView.BlockView.Active}
+ConfigView.label.seeding.firstPriority.ignoreIdleHours=Torrents que n\u00E3o fazem upload de nada
+ConfigView.section.mode.advanced.wiki.main=P\u00E1gina Principal do Wiki
+remote.pairing.tip.text=Vuze Remote Toolbar\: Ir para <A HREF\="http\://remote.vuze.com/download/">remote.vuze.com/download</A>\nVuze Remote Mobile\: Ir para <A HREF\="http\://remote.vuze.com/">remote.vuze.com</A> in your mobile browser.
+devices.contextmenu.od=Baixando Offline
+tps.status.available=Dispon\u00EDvel
+MainWindow.menu.view.allpeers=Todos os Peers
+dht.advanced.group=Configura\u00E7\u00F5es avan\u00E7adas
+configureWizard.nat.message=Para obter o melhor desempenho com Vuze, \u00E9 altamente recomendado ter total acesso \u00E0 internet. Est\u00E1 ferramenta deixa voc\u00EA testar e/ou mudar as portas usadas para aceitar conex\u00F5es de entrada.\n\n NOTA\: A porta TCP 6880 \u00E9 usada internamente, ent\u00E3o n\u00E3o pode ser utilizada.
+PasswordWindow.passwordprotected=O Vuze est\u00E1 protegido por senha.\nPara mostrar a janela do Vuze, por favor insira a sua senha aqui \:
+GeneralView.label.downloaded=Baixados \: 
+TableColumn.header.AzProduct=De
+ConfigView.complete.abbreviated=C\:
+ConfigView.section.sharing.rescanenable=Ativar re-escaneamento peri\u00F3dico dos compartilhados por mudan\u00E7as
+azbuddy.dchat.public.nick=Apelido p\u00FAblico compartilhado
+iconBar.details=Detalhes
+ConfigView.label.seeds=sementes
+Button.save=Salvar
+DHTView.transport.sent=Enviados
+azneti2phelper.install.reason.i2ptracker=O torrent que voc\u00EA est\u00E1 adicionando tem um rastreador I2P.
+SpeedView.uploadSpeed.title=Velocidade de Upload
+TableColumn.header.torrentpath.info=Local do Torrent no disco
+fileDownloadWindow.state_error=Erro\: 
+importTorrentWizard.process.outputfileexists.message=O arquivo de sa\u00EDda de dados existe - sobrescrever? 
+devices.sidebar.hide.rend.generic=Ocultar dispositivos gen\u00E9ricos
+v3.MainWindow.search.defaultText=Procurar no Vuze
+MyTorrentsView.menu.remove=&Remover
+v3.mb.delPublished.delete=&Apagar
+wizard.newtorrent.byo.editname.title=Editar Nome do Item
+dlg.player.install.description=Instalando componente adicional para reprodu\u00E7\u00E3o...
+library.all.header=%1 item\: %2 ativo
+ConfigView.section.connection.group.webseed=Seeds Web/HTTP
+speedtest.wizard.test.mode.updown=upload e download
+ConfigView.section.file.writemblimit=M\u00E1ximo de pedidos de escrita requeridos (em %1)
+ConfigView.section.security.resetkey=Resetar as chaves
+devices.turnon.qos=Compartilhar estatisticas an\u00F4nimas com Vuze
+stream.analysing.media=Analisando M\u00EDdia
+Button.finish=Terminar
+iconBar.down=Baixado
+v3.share.private.text=O torrent selecionado est\u00E1 marcado como Torrent Privado.\n\nVoc\u00EA n\u00E3o pode compartilhar torrents privados.
+TableColumn.header.chat.name=Nome do bate-papo
+ConfigView.section.ipfilter.description=Descri\u00E7\u00E3o
+v3.mb.PlayFileNotFound.button.redownload=Baixar Dados de Novo
+ConfigView.section.file.perf.cache.size=Tamanho do cache em %1
+label.route=Rota
+torrent.comment.azmsgsync.install=Plugin Mensagens Sync n\u00E3o est\u00E1 instalado ou o bate-papo est\u00E1 desabilitado - veja Ferramentas->Plugins->Amigos
+azbuddy.dchat.ro=Canal s\u00F3 para leitura
+devices.xcode.remove.vetoed=Transcodifica\u00E7\u00E3o de '%1' em progresso, o download n\u00E3o pode ser removido at\u00E9 a transcodifica\u00E7\u00E3o ser completada ou cancelada na p\u00E1gina de ""Dispositivos
+dhttracker.alt_port=Porta [0 \: random]
+TableColumn.menu.date_added.reset=Data do Reset
+ConfigView.section.file.perf.explain=Aviso - Mudan\u00E7as inadequadas destes par\u00E2metros podem afetar adversamente o desempenho do download. Requer reiniciar.\nSe voc\u00EA tem problemas com "falta de mem\u00F3ria" considere limitar as conex\u00F5es por torrent (Veja as configura\u00E7\u00F5es das Transfer\u00EAncias)
+label.showhide.tag=Mostrar / Ocultar Tag(s)
+MainWindow.menu.window.minimize.keybinding=Meta+M
+configureWizard.finish.message=O Vuze est\u00E1 agora configurado, divirta-se\!
+importTorrentWizard.torrentfile.invalidPath=Arquivo torrent inv\u00E1lido 
+PeersView.C2.info=Se voc\u00EA est\u00E1 impedindo o peer de baixar
+ConfigView.section.tracker.scrapecacheperiod=Cache do scrape (ms)
+security.crypto.persist_for.day=1 dia
+v3.share.private.title=Compartilhando o Torrent
+MainWindow.menu.view.tagsoverview={tags.view.heading}
+mdi.entry.games=Jogos
+device.itunes.status.running=O iTunes est\u00E1 sendo executado
+importTorrentWizard.finish.message=Importa\u00E7\u00E3o conclu\u00EDda com sucesso
+ConfigView.section.stats.defaultsavepath=Diret\u00F3rio para salvar as estat\u00EDsticas
+externalLogin.explanation.capture=Voc\u00EA precisa logar para criar este modelo. Uma vez que voc\u00EA est\u00E1, por favor clique em "Feito".
+ConfigView.section.dns.allow_socks=Usar quando a busca por servidor proxy SOCKS falhar
+FilesView.done=Conclu\u00EDdo
+security.certcreate.state=Estado ou Prov\u00EDncia
+platform.win32.baddll.vlsp=Venturi Firewall
+ConfigView.section.logging.choosedefaultsavepath=Por favor, escolha o diret\u00F3rio para salvar
+PluginDeprecation.log.start=Esta janela cont\u00E9m informa\u00E7\u00E3o sobre plugins usando funcionalidades que ser\u00E3o removidas em futuras vers\u00F5es do Vuze.\nVoc\u00EA n\u00E3o precisa desinstalar os plugins, voc\u00EA deve apenas atualizar o plugin para a \u00FAltima vers\u00E3o.\nSe voc\u00EA est\u00E1 rodando a \u00FAltima vers\u00E3o, ent\u00E3o por favor copie o conte\u00FAdo desta janela e poste-o no f\u00F3rum localizado aqui\:\n\t%1\n\n
+TableColumn.header.peakdown=Down Alcan\u00E7ado
+Column.seedspeers.notstarted=%2
+Plugin.localtracker.autoadd=Peers expl\u00EDcitos
+TableColumn.header.Quality=Qualidade
+ConfigView.label.seeding.rankType.seed.fallback=Reverter para a Propor\u00E7\u00E3o de Peers\:Seeds ap\u00F3s\n(0 \: Nunca Reverter)
+ConfigView.label.use_old_speed_menus=Usar menus de velocidade do estilo antigo [requer reiniciar]
+devices.contextmenu.od.enabled=Desabilitado
+TableColumn.header.totalspeed.info=Velocidade Total de todos os peers aos quais voc\u00EA est\u00E1 conectado
+OpenTorrentFile.column.\#=\#
+label.anon.short=A
+message.confirm.delete.text=Voc\u00EA tem certeza que voc\u00EA quer apagar o '%1'?
+ConfigView.section.connection.encryption.require_encrypted_transport.tooltip=For\u00E7ar o uso de conex\u00F5es encriptadas com outros peers.
+azbuddy.dchat.status.nohandler=Erro\: Nenhum manipulador de mensagem dispon\u00EDvel
+chats.view.infobar.text2=Esta vis\u00E3o, mostra informa\u00E7\u00E3o sobre v\u00E1rios bate-papos que voc\u00EA est\u00E1 monitorando/participando. Visite a Wiki para mais informa\u00E7\u00F5es em <a href\="{azbuddy.dchat.link.url}">clicando aqui...</a>
+chats.view.infobar.text1=Vis\u00E3o geral do bate-papo
+Progress.reporting.status.canceled=Cancelado
+dlg.install.vuzexcode.description=Por favor, aguarde enquanto o componente Analisador de M\u00EDdia \u00E9 instalado
+iconBar.play.tooltip=Reproduzir conte\u00FAdo selecionado
+Wizard.Subscription.rss.subtitle3=Uma vez salvo, voc\u00EA receber\u00E1 atualiza\u00E7\u00F5es ao vivo na sua barra lateral sempre que novos resultados est\u00E3o dispon\u00EDveis via seu feed RSS.
+SpeedTestWizard.set.limit.conf.level=Confian\u00E7a
+Wizard.Subscription.rss.subtitle2=Muitos editores fornecem feeds RSS do conte\u00FAdo deles, Localize a URL no website do editor, copie e cole a URL no campo acima, ent\u00E3o clique em Salvar.
+fileplugininstall.install.title=Instalar o Plugin?
+Wizard.Subscription.rss.subtitle1=Digite ou cole a URL abaixo\:
+ManagerItem.error=Erro
+azbuddy.ui.menu.verify=Verificar a \u00C1rea de Transfer\u00EAncia
+ConfigView.section.connection.port.rand.together=Mesma porta para TCP e UDP
+v3.splash.initSkin=Inicializando a Skin da UI
+OpenTorrentOptions.header.filesInfo.some=%1 de %2 Arquivos\: %3
+ConfigView.section.style.colorOverrides.reset=Redefinir Cor
+restart.error.pnf=Path '%1' n\u00E3o encontrado
+TableColumn.header.bad_avail_time=C\u00F3pia Completa Vista
+ConfigView.section.security.group.crypto=Chaves P\u00FAblicas/Privadas
+PeersView.I1.info=Voc\u00EA est\u00E1 interessado no que o outro peer tem?
+ConfigView.section.files.move=Conclus\u00E3o da Movimenta\u00E7\u00E3o
+FileView.BlockView.Skipped=Pulado
+ConfigView.section.style.alwaysRefreshMyTorrents.tooltip=Esta op\u00E7\u00E3o atualizar\u00E1 a guia Meus Torrents mesmo se n\u00E3o exibida (\u00FAtil para alguns plugins mirc)
+TableColumn.header.SeedingRank.info=Valor do ranking de qu\u00E3o terrivelmente o torrent precisa de seeding. Valor mais alto quer dizer maior necessidade.
+MyTorrentsView.menu.setpriority=Definir &Prioridade
+device.model.desc=Descri\u00E7\u00E3o do Modelo
+ConfigView.label.openstatsonstart=Abrir as estat\u00EDsticas ao iniciar
+ConfigView.section.proxy.enable_proxy=Ativar Proxying de comunica\u00E7\u00F5es com o rastreador [requer reiniciar]
+ConfigView.section.ipfilter.blockbanning=Banir um bloco de 256 endere\u00E7os quando pelo menos muitos no bloco forem banidos
+azbuddy.os_busy=Ocupado
+MainWindow.menu.file.restart=Reiniciar o Vuze
+TorrentOptionsView.title.short=Op\u00E7\u00F5es
+ConfigView.section.style.forceSIValues=Os valores da for\u00E7a a ser mostrado como IEC valoriza independentemente da unidade de exibi\u00E7\u00E3o para fins de legados (por exemplo, 1MB \= 1MiB \= 1048576B)
+OpenTorrentWindow.startMode=Adicionar Modo
+Button.selectAll=Selecionar Todos
+ManagerItem.checking=Verificando
+ConfigView.group.scrape=Scrape
+v3.deleteContent.message=\nVoc\u00EA gostaria de apagar o '%1' do seu computador ou apenas remov\u00EA-lo da sua Biblioteca do Vuze?
+TableColumn.header.AvgAvail=M\u00E9dia de Disp/peda\u00E7os
+popup.next=>
+wizard.mode=Rastreador / Modo 
+ConfigView.section.transfer.lan.uploadrate.tooltip=Conex\u00F5es com os peers dentro da mesma LAN interna tem um limite de taxa de upload separado.
+azbuddy.ui.menu.ygm=Enviar o YGM
+ConfigView.label.seeding.firstPriority=A primeira prioridade vai para os torrents com
+SystemTray.menu.stopalltransfers=Parar &Todas as Transfer\u00EAncias
+OpenTorrentOptions.show.never=Nunca novamente
+ConfigView.section.style.graphicsUpdate=Atualizar as barras gr\u00E1ficas a cada N atualiza\u00E7\u00F5e(s) da GUI
+ConfigView.pluginlist.whereToPutOr=Para plugins compartilhados usar\:
+SpeedTestWizard.test.panel.not.accepted=Pedido de teste n\u00E3o aceito\: 
+ConfigView.section.security=Seguran\u00E7a
+label.copy.to.clipboard=Copiar Para \u00C1rea de Transfer\u00EAncia
+ConfigView.label.autoopen=Auto-Abrir
+ConfigView.label.seeding.addForSeedingDLCopyCount=Considerar para 'adicionar para ficar de seed' downloads que baixaram este n\u00FAmero de c\u00F3pias
+CategoryAddWindow.title=Adicionar Nova Categoria
+FileProgress.stopped={ManagerItem.stopped}
+ConfigView.section.transfer.autospeed.chokeping=Tempo para silenciar o ping [milisegundos]
+wizard.multitracker.edit.text.title=Entrar com Detalhes do Rastreador
+FilePriority.invalid.text=Valor inv\u00E1lido digitao,  inteiro requerido\: %1
+installPluginsWizard.mode.title=Por favor, escolha um m\u00E9todo de instala\u00E7\u00E3o
+FilesView.rename.confirm.delete.title=Confirmar Exclus\u00E3o
+MyTrackerView.webui.contextmenu.copyurl=Copia a URL do torrent para a \u00C1rea de Transfer\u00EAncia
+ConfigView.section.logging.timestamp=Formato da estampa de tempo para arquivos log
+TableColumn.header.up=Enviado
+configureWizard.transfer2.group=Modo
+ConfigView.label.seeding.ignore.header.rule=Regra
+PeersView.T=T
+TableColumn.header.TableColumnNameInfo=Nome e Descri\u00E7\u00E3o da Coluna
+PeersView.S=D
+UpdateConstraint.title=Atualizar Restri\u00E7\u00F5es
+OpenTorrentWindow.startMode.stopped=Parado
+v3.deviceview.infobar.line2.xbox=Transmitir v\u00EDdeos, indo para o seu Xbox 360 e selecionando Meu XBox -> Biblioteca de V\u00EDdeo -> Vuze.
+ConfigView.label.seeding.ignore.header.value=Valor
+Formats.units.TB=TB
+beta.wizard.off=Estou feliz com vers\u00F5es de lan\u00E7amento, n\u00E3o, obrigado\!
+SpeedTestWizard.finish.panel.title=O Teste de Velocidade Terminou\!
+MyTorrentsView.menu.rename.displayed.enter.message=Inserir um novo nome para exibir para este download.\nSe nenhum texto \u00E9 inserido, o nome original ser\u00E1 usado.
+DHTView.db.values=Valores
+ConfigView.section.stats.savefile=Nome do arquivo de estat\u00EDsticas
+MyTorrentsView.menu.showdownloadbar=Mostrar a Barra de &Download 
+br.backup.folder.title=Selecione pasta de backup
+PiecesView.blocks=Blocos
+apply.selected.template=Aplicar Modelo Selecionado
+IrcClient.disconnected=Desconectado de
+PeersView.optunchoke=Desobstru\u00E7\u00E3o Otimista
+azbuddy.dchat.general.chats=Bate-Papos Gerais
+Scrape.status.initializing=Aguardando para Scrape
+ManagerItem.low=baixa
+TableColumn.header.tag.public.info={tag.share}
+label.beta=Beta
+ConfigView.section.style.dropdiraction=A\u00E7\u00E3o ao Arrastar e Soltar para diret\u00F3rios
+GeneralView.label.hash=Hash \:
+pairing.ac.getnew.create=Criar
+ConfigView.section.file.defaultdir.lastused=Atualizar o diret\u00F3rio padr\u00E3o para o local onde salvou pela \u00FAltima vez
+MyTorrentsView.menu.eta.abs=Exibir TEC em tempo absoluto
+PeersView.%=% 
+ConfigView.label.udplistenport=Porta de escuta UDP
+Progress.reporting.action.label.cancel.tooltip=Cancelar a opera\u00E7\u00E3o
+jvm.max.mem.current=Heap m\u00E1ximo atual \u00E9 %1
+ConfigView.label.seeding.rankType.timedRotation=Rota\u00E7\u00E3o Temporarizada
+fileplugininstall.duplicate.title=Plugin Duplicado
+ConfigView.section.connection.encryption.use_crypto_port=Usar a extens\u00E3o do rastreador 'cryptoport' para impedir tentativas de conex\u00E3o de entrada simples. Alguns rastreadores n\u00E3o aceitam isto e falham com erros tais como "Porta Inv\u00E1lida" ou "Argumento Ilegal"
+v3.MainWindow.menu.games={mdi.entry.games}
+ConfigView.section.display=Exibir
+ConfigView.section.style.status.show_sr=Taxa de Compartilhamento
+label.checking.sources=Checando a disponibilidade de fontes para o download
+FilesView.rename.filename.text=Escolher um novo nome para o arquivo
+exportTorrentWizard.exportfile.browse=Navegar
+unix.script.new.button.quit=Sair Agora
+TableColumn.header.sessiondown=Baixados na Sess\u00E3o
+label.proxy=Proxy
+exportTorrentWizard.exportfile.invalidPath=Arquivo de exporta\u00E7\u00E3o inv\u00E1lido 
+MainWindow.menu.view.plugins.logViews=Visualiza\u00E7\u00F5es do Log
+v3.MainWindow.tab.publish=Publicar
+label.show.tag=Exibir Tag
+LocaleUtil.column.text=Texto Desconhecido
+v3.MainWindow.button.stop=Parar
+wizard.webseed.adding=Adicionar Seeds HTTP
+dht.warn.user=Avisar sobre problemas de mapeamento de NAT/portas em potencial
+v3.MainWindow.menu.view.asAdvancedList=Lista Avan\u00E7ada
+ConfigView.section.style.ShowFancyMenu=Exibir Menu Especial (Requer Re\u00EDnicio)
+ConfigView.section.tracker.client.scrapeinfo=Desativar o scraping impedir\u00E1 que muitas das regras das filas dos torrents de funcionarem como elas confiam na informa\u00E7\u00E3o da multid\u00E3o obtida pelos rastreadores de scraping.
+ConfigView.section.logging.generatediagnostics.info=Gerar informa\u00E7\u00E3o de diagn\u00F3stico e copiar para a \u00E1rea de transfer\u00EAncia e arquivo log, se configurado
+device.router.view.title=Roteadores
+ConfigView.label.sleep=Dormir
+TableColumn.header.unopened.info=Bandeira para indicar se o torrent foi reproduzido (aberto)
+ConfigView.section.tracker.passwordenabletorrent=Ativar senha nos torrents
+Pieces.column.\#.info=N\u00FAmero de Peda\u00E7os
+menu.sortByColumn=Organizar Por %1 
+ConfigView.section.tracker.createbutton=Criar
+devices.button.installitunes=Instale Integra\u00E7\u00E3o com iTunes
+device.autohide.alert=%1 dispositivo(s) foram ocultos como eles n\u00E3o est\u00E3o online por %2 dias.\nVeha Ferramentas->Op\u00E7\u00F5es->Dispositivos para configurar seu comportamento.\nClique Direito em 'Reproduzir Dispostivo' na barra lateral para exibir dispositivos ocultos.
+ConfigView.section.style=Interface 
+TableColumn.header.size=Tamanho
+unix.script.new.manual.url=http\://wiki.vuze.com/w/unix_startup_script
+dlg.corewait.title=Inicializando N\u00FAcleo
+ConfigView.section.transfer.select.v2=Auto-Velocidade (beta)
+ConfigView.section.tracker.pollinterval=Intervalo de apura\u00E7\u00E3o dos clientes no rastreador (segs)
+ConfigView.section.tables=Tabelas
+br.backup.auto.dir.select=Por favor, escolha o diret\u00F3rio de backup padr\u00E3o
+CacheView.reads.hits=Acertos
+natpmp.info=NAT-PMP \u00E9 a alternativa da Apple para o UPnP e \u00E9 suportada por recentes esta\u00E7\u00F5es de aeroportos\n\nNote que o UPnP tem que estar ativado para ativar o NAT-PMP ja que o dispositivo NAT-PMP \u00E9 tratado como um tipo de dispositivo UPnP especial
+webui.i2p_dest=Endere\u00E7o i2p
+MyTrackerView.date_added=Adicionado
+UIDebugGenerator.message.cancel.title=Gerar Info de Debug Info Cancelado
+Wizard.Subscription.subscribe.library.empty=Sem subscri\u00E7\u00F5es dispon\u00EDveis?\n \nProcure pelo bot\u00E3o para subscrever laranja brilhante na Rede HD do Vuze.\n \n<A HREF\="http\://wiki.vuze.com/w/FAQ_Subscriptions">Leia mais</A>
+MyTorrentsView.menu.setSpeed.disable=Desativar Upload
+wizard.webseed=Adicionar Seeds HTTP ao torrent
+ConfigView.label.priorityExtensions=Auto-priorizar os arquivos com - ex\: .txt;.nfo;.jpg
+iconBar.openNoDefault.tooltip=Abrir um arquivo .torrent (sem save padr\u00E3o)
+ConfigView.section.connection.advanced.url=http\://azureuswiki.com/index.php/AdvancedNetworkSettings
+IrcClient.copyright=Usando o PircBot Java IRC API - http\://www.jibble.org/pircbot.php
+OpenTorrentWindow.mb.badSize.title=Arquivo Incompat\u00EDvel
+custom.settings.import.title=Importe defini\u00E7\u00F5es de configura\u00E7\u00E3o?
+dlg.auth.enter.expiry=O c\u00F3digo de ativa\u00E7\u00E3o expira em %1.
+MyTorrentsView.menu.host.error.message=O seguinte erro ocorreu durante a hospedagem do torrent 
+azbuddy.ui.menu.remove=Remover
+DHTView.db.divfreq=Freq. Div.
+ConfigView.section.proxy.dns.info=Veja a Conex\u00E3o-> configura\u00E7\u00E3o de DNS para especificar os servidores DNS adicionais para a resolu\u00E7\u00E3o de proxy.
+Peers.column.timetocomplete.info=Tempo restante at\u00E9 o peer estar completo
+MainWindow.nat.status.unknown=NAT
+ConfigView.label.seeding.rankType.timedRotation.tooltip=Todos os torrents completados na fila ir\u00E3o para o modo seeding.\nA dura\u00E7\u00E3o do tempo de seeding \u00E9 definida em 'Tempo M\u00EDnimo de Seeding'
+OpenTorrentWindow.addFiles.URL=Adicionar &URL
+azbuddy.addtorrent.msg=O amigo '%1' enviou para voc\u00EA o '%2'.\nVoc\u00EA quer adicionar este download?
+MyTorrentsView.menu.thisColumn.toClipboard=Copiar o Texto para a \u00C1rea de Transfer\u00EAncia
+v3.activity.header.downloads=Downloads
+TorrentDetailsView.filter=Procurar por arquivos...
+ConfigView.section.ipfilter.editFilter=Editar Filtro
+v3.splash.hookPluginUI=Enganchando na UI do Plugin
+MyTorrentsView.menu.movemenu=Mover Arquivos
+mb.azmustclose.text=O Vuze deve fechar devido a um problema ao (re)iniciar o Vuze, isso provavelmente fez o programa ser executado como um usu\u00E1rio Administrador.\n\nAp\u00F3s o Vuze fechar, por favor re-abra-o manualmente.
+ConfigView.section.security.unlockkey=Destrancar as chaves explicitamente
+v3.MainWindow.tab.home=Painel
+PeersView.connected_time.info=Tempo total que est\u00E1 conectado com o peer
+MyTrackerView.bytesin=Bytes Recebidos
+ConfigView.section.file.perf=Op\u00E7\u00F5es de Performance
+security.crypto.persist_for.30days=30 dias
+MainWindow.dialog.select.vuze.file=Selecionar o Arquivo do Vuze
+installPluginsWizard.list.description=Descri\u00E7\u00E3o do plugin
+label.right.click.for.options=Clique com bot\u00E3o direito do mouse para op\u00E7\u00F5es
+label.out=Sa\u00EDda
+ConfigView.section.transfer.autospeed.latencyfactor=Fator usado para ligar as mudan\u00E7as de lat\u00EAncia as mudan\u00E7as de velocidade (n\u00BAs maiores diminuem a sensitividade)
+br.restore.folder.title=Selecione Restaurar pasta
+ConfigView.section.mode.beginner=Iniciante
+Progress.reporting.window.remove.now.tooltip=Remover todos os processos completados, falhos ou cancelados da visualiza\u00E7\u00E3o
+platform.jvmopt.nolink=N\u00E3o pode gerenciar os op\u00E7\u00F5es de de JVM como proibida por de configura\u00E7\u00E3o existente
+ConfigView.section.plugins.dht=Base de Dados Distribu\u00EDda
+ConfigView.section.connection.encryption.min_encryption_level=N\u00EDvel m\u00EDnimo da encripta\u00E7\u00E3o
+ConfigView.section.transfer.autospeed.minupload=Velocidade m\u00EDnima de upload em %1
+ConfigView.label.seeding.firstPriority.ignoreSPRatio=Torrents com uma propor\u00E7\u00E3o de Seeds para Peers de
+tag.discovery.view.options=Op\u00E7\u00F5es
+label.click.to.restore=Clique para Restaurar
+core.shutdown.dl=downloads completados
+ConfigView.section.tracker.scrapeandcache=Scrape e cache
+ConfigView.section.proxy.port=Porta
+ConfigView.label.seeding.firstPriority.ignore0Peer=Torrents com 0 Peers
+Button.cancel=&Cancelar
+TableColumn.header.sr_prog=Progresso da Taxa de Compartilhamento
+label.init.save.loc=Salvar Inicialmente no Local
+Peers.column.maxupspeed=Velocidade M\u00E1x. de Upload
+CacheView.reads.\#=\#
+MainWindow.menu.window.alltofront=Trazer Todos para a &Frente
+MainWindow.menu.tools.speedtest=Teste de Velocidade...
+azbuddy.dchat.node.status=%1%2Nodes\=%3, Pedidos\=%4
+subs.ext.view.info=Voc\u00EA configurou o Vuze para usa um navegdor externo para exibir os resultados das assinaturas
+azbuddy.ui.menu.cat.set=Digite as tags/categorias
+OpenTorrentWindow.addFiles.Clipboard=Adicionar da \u00C1rea de Transfer\u00EAncia
+ConfigView.label.seeding.rankType.peer=Contagem de Peers Pesados
+ConfigView.group.irctitle=Configura\u00E7\u00F5es do IRC 
+plugin.sharing.remove.veto=Este compartilhamento \u00E9 um sub-compartilhamento de um 'conte\u00FAdo de diret\u00F3rio' e n\u00E3o pode ser explicitamente apagado.\n Apague o compartilhamento raiz
+download.removerules.updatetorrents=Remover os torrents de atualiza\u00E7\u00E3o conforme a multid\u00E3o requerir
+Torrent.create.progress.totalfilecount=Contagem total de arquivos\:
+plugin.aznetstatus.pingtarget=Ping/trace a rota do alvo
+TableColumn.header.tag.type={MySharesView.type}
+Trackers.column.peers=Peers
+LoggerView.pause=Pausar Logging
+ConfigView.label.usefastresume=Usar modo de Resumo R\u00E1pido
+MainWindow.menu.window.minimize=&Minimizar
+speedtest.wizard.test.mode.down=download
+devices.xcode.only.show=Mostrar apenas arquivos Transcoded no dispositivo
+ConfigView.label.savetorrents=Salvar arquivos .torrent
+ConfigView.pluginlist.column.isOperational=Operacional?
+external.browser.failed=Navegador Externo Falhou
+TableColumn.header.tag_colors=Cores das Tags
+GeneralView.yes=sim
+Wizard.Subscription.optin.title=Ativar Subscri\u00E7\u00F5es
+Formats.units.MB=MB
+ConfigView.section.style.status.show_rategraphs=Mostrar gr\u00E1ficos hist\u00F3ria taxa embaixo do texto download/upload
+configureWizard.file.title=Torrents / Arquivos
+health.explain.grey=Significa que o seu torrent n\u00E3o est\u00E1 funcionando (baixando ou enviando)
+library.incomplete.header.p=%1 items baixando, %2 aguardando para baixar
+PeersView.client.info=Tipo de cliente BT que o peer est\u00E1 usando
+label.copy.url.to.clip=Copiar URL Para \u00C1rea de Transfer\u00EAncia
+DownloadManager.error.unabletostartserver=Incapaz de iniciar o servidor - verifique a configura\u00E7\u00E3o da porta de entrada / e permiss\u00F5es no firewall para que o aplicativo aja como servidor
+ConfigView.label.seeding.firstPriority.DLMinutes=Um tempo decorrido desde o come\u00E7o do download
+exportTorrentWizard.process.inputfilebad.message=Uma falha ocorreu ao acessar o arquivo de entrada de dados\:
+Button.bar.show=Mostrar
+GeneralView.label.maxuploads=Slots de Upload \:
+DHTView.activity.title=Atividade
+importTorrentWizard.importfile.browse=Navegar
+ConfigView.label.popupdownloadfinished=Mostrar um alerta quando um download estiver conclu\u00EDdo
+ConfigView.section.style.status.show_ipf=Status do IPFilter
+TrayWindow.menu.close=Fechar a Cesta de Download
+devices.sidebar.oxc.pm.4={ConfigView.label.stop.Sleep}
+devices.sidebar.oxc.pm.2={ConfigView.label.stop.Hibernate}
+devices.sidebar.oxc.pm.1={ConfigView.label.stop.Shutdown}
+ConfigView.label.quickviewmaxkb=Tamanho m\u00E1ximo do arquivo [KB]
+MainWindow.dht.status.initializing=DHT Inicializando
+security.crypto.pw.title=Digite a Senha
+importTorrentWizard.process.torrentfail.title=Falha na Escrita do Torrent
+ConfigView.section.style.units=Unidades Exibidas
+ConfigView.section.style.dropdiraction.sharefoldercontentsrecursive=Compartilhar Conte\u00FAdos (Recursivo)
+TableColumn.header.TableColumnInfo=Descri\u00E7\u00E3o da Coluna
+message.status.success=Sucesso
+ConfigView.pluginlist.whereToPut=Colocar quaisquer plugins espec\u00EDficos-para-o-usu\u00E1rio em seu pr\u00F3prio diret\u00F3rio\:
+TrackerClient.announce.warningmessage=Rastreador '%1' retornou o aviso '%2'
+ConfigView.section.proxy.password=Senha
+MainWindow.menu.window.zoom.restore=Restaurar
+ConfigView.section.file.save.peers.max=M\u00E1ximo de peers a salvar [0\: ilimitados]
+ConfigView.section.file.defaultdir.autorename=Auto renomear os dados do torrent se os arquivos no caminho parecem diferentes
+PiecesView.DistributionView.weHave=Peda\u00E7os que voc\u00EA tem
+PeersView.downloadspeedoverall=Velocidade Global de Download
+device.mediaserver.remove_all.title=Confirmar Remo\u00E7\u00E3o
+Formats.units.KB=KB
+device.show=Mostrar dispositivos ocultos
+OpenTorrentWindow.filesInfo=%1 de %2 ser\u00E3o baixados.
+#There is a plugin to help with internationalizing these bundles at http://plugins.vuze.com/plugin_list.php
+MainWindow.menu.file.open.torrent=Arquivo Torrent...
+uninstallPluginsWizard.finish.title=Desinstala\u00E7\u00E3o em Progresso
+ConfigView.section.style.forceMozilla=For\u00E7ar o Vuze a usar o Mozilla para os widgets do Navegador [xulrunner ou firefox 3 requeridos; requer reiniciar]
+sidebar.header.transfers=Arquivos
+TagGroupWindow.message=Digite o nome do grupo
+ConfigView.label.deletetorrents=Apagar o .torrent original depois de adicionar o download
+update.instance.update=Checando por Atualiza\u00E7\u00F5es
+ConfigView.label.seeding.fakeFullCopySeedStart=mas apenas para os torrents com pelo menos
+label.plugin.options=Op\u00E7\u00F5es de Plugins...
+FileItem.normal=Normal 
+UpdateMonitor.messagebox.verification.failed.title=Verifica\u00E7\u00E3o da Instala\u00E7\u00E3o Falhou
+MyTorrentsView.menu.move=&Mover 
+FilesView.priority=Prioridade
+label.classic=Cl\u00E1ssico
+upnp.mapping.dataportudp=Porta do cliente tracker UDP
+DownloadActivityView.legend.peeraverage={PeersGraphicView.title.full}
+SpeedTestWizard.set.upload.result=\u00DAltimo Resultado do Teste
+ConfigView.section.style.showProgramIcon.tooltip=A visualiza\u00E7\u00E3o pode precisar de re-abrir para as mudan\u00E7as acontecerem
+IrcClient.topicforchannel=T\u00F3pico do canal
+ConfigView.section.logging.maxsize=Tamanho m\u00E1ximo do arquivo de log
+devices.view.title=Dispositivos
+ConfigView.label.seeding.firstPriority.ignore.info=Esteja ciente que usar estas regras pode resultar em parar um torrent\nt\u00E3o r\u00E1pido quanto o download terminar.
+authenticator.tracker=Rastreador
+azbuddy.ui.mykey=Minha chave\:
+wizard.maketorrents.init.tags=Tags iniciais (Separadas por ",")
+OpenTorrentWindow.fileList=Arquivos nos torrents\:
+iconBar.queue.tooltip=Enfileirar
+ConfigView.dialog.choosedefaulttorrentpath=Por favor, escolha o diret\u00F3rio padr\u00E3o dos torrents
+installPluginsWizard.file.browse=Navegar...
+label.complete=Completo
+subs.prop.last_error=\u00DAltimo erro
+tag.type.ds.inact={label.inactive}
+v3.MainWindow.tab.library=Biblioteca
+health.explain.red=significa que voc\u00EA n\u00E3o est\u00E1 conectado a nenhum peer enquanto baixa
+MainWindow.status.latestversion=Mais Recentes
+configureWizard.nat.server.udp_listen_port=Escutar porta de entrada UDP
+installPluginsWizard.title=Instalar Plugins
+webui.port.override=Porta auxiliar\: necess\u00E1rio apenas se difere da porta p\u00FAblica interna devido a configura\u00E7\u00E3o NAT
+security.certcreate.title=Criar um Certificado Auto-Assinado
+TrackerAvail.column.leechers.info={Trackers.column.leechers.info}
+DetailedListView.title=Lista Detalhada
+OpenTorrentWindow.fileTable.destinationName=Nome do Destino
+FilesView.menu.setpriority.numeric.auto=N\u00FAmerico - Auto Decrescente
+ConfigView.label.strictfilelocking=Refor\u00E7ar a tranca do acesso de escrita exclusivo do arquivo pelos torrents
+TransferStatsView.legend.ping3=Alvo 3
+TransferStatsView.legend.ping2=Alvo 2
+TransferStatsView.legend.ping1=Alvo 1
+PeersView.port.info=Porta sendo usada
+ConfigView.section.connection.network.max.simultaneous.connect.attempts=M\u00E1x. de tentativas de conex\u00F5es de sa\u00EDda simult\u00E2neas
+DHTView.general.nodes=N\u00F3s\:
+ConfigView.label.openconsole=Abrir o console na inicializa\u00E7\u00E3o
+MainWindow.menu.file.create.fromfile=De um &Arquivo
+VivaldiView.title.fullcvs=Vivaldi CVS
+TableColumn.header.SeedingRank=Rank do Seeding
+ConfigView.section.file.perf.cache.enable=Ativar cache de disco
+ConfigView.section.connection.encryption.encrypt.group=Encripta\u00E7\u00E3o/Ofusca\u00E7\u00E3o do Transporte
+SpeedTestWizard.test.panel.enc.label=Pressionar o teste com encripta\u00E7\u00E3o\:
+MyTorrentsView.menu.create_personal_share=Criar Compartilhamento Pessoal
+Button.sendManual=Envio Manual (criar .zip)
+azbuddy.dchat.share.fail.title=Falha no Compartilhamento
+dlg.auth.title=Ativa\u00E7\u00E3o
+MainWindow.status.latestversion.clickupdate=Clique para atualizar
+TableColumn.header.availability=Disponibilidade
+IPChecker.external.service.discoveryvip.description=Discoveryvip \u2013 Apenas verifica\u00E7\u00E3o de Endere\u00E7o IP
+MainWindow.upgrade.section.info=Nova Vers\u00E3o Dispon\u00EDvel 
+PeersView.incomingreqcount=Reqs de Entrada
+upnp.alertdeviceproblems=Relatar problemas com o dispositivo UPnP
+v3.MainWindow.button.comment=Comentar
+configureWizard.transfer2.mselect=Selecione o limite de velocidade da sua conex\u00E3o de UPLOAD 
+IrcClient.haskicked=foi chutado
+MainWindow.menu.file.share.dircontents=Conte\u00FAdo &da Pasta...
+ConfigView.label.pauseresume=Auto-pausar/resumir
+swt.uninstall.window.title=Removedor de Plugins do Vuze
+UpdateMonitor.messagebox.accept.unverified.text='%1' n\u00E3o p\u00F4de ser verificado como um plugin oficial do Vuze.\nSe \u00E9 tal plugin voc\u00EA N\u00C3O deve continuar.\nProsseguir com a instala\u00E7\u00E3o?
+MainWindow.status.update.tooltip=Duplo clique para informa\u00E7\u00E3o sobre o progresso
+MainWindow.menu.closealldetails=Fechar &Todos os Detalhes
+Progress.reporting.action.label.retry.tooltip=Tentar de novo a opera\u00E7\u00E3o
+Subscription.menu.reset=Resetar Ao Estado Inicial
+MyTorrentsView.mytorrents=Meus Torrents 
+br.restore=Restaurar
+pairing.status.pending=Atualiza\u00E7\u00E3o ir\u00E1 ser realizada em %1
+ConfigView.option.dm.dblclick.play=Executar Conte\u00FAdo
+devices.sidebar.oxc.closevuze={ConfigView.label.stop.QuitVuze}
+ConfigView.section.ipfilter.end=IP Final
+CacheView.reads.fromCache=Do Cache
+dlg.auth.trial.title=Testar Gravador de DVD
+PeersView.T.info=L (local)\: voc\u00EA estabeleceu a conex\u00E3o, R (remota)\: o peer estabeleceu a conex\u00E3o.
+tag.sharing.enable.text=Voc\u00EA deseja compartilhar suas tags/categorias de forma an\u00F4nima com a comunidade?\n\nIsso ir\u00E1 ajudar os outros a organizar melhor seus downloads.\n\nClique direito domouse sobre tags/categorias na barra lateral para fazer configura\u00E7\u00F5es individuais se requerida.
+MyTrackerView.status.published=Publicado
+Formats.units.GB=GB
+PeersView.BlockView.NextRequest=Pr\u00F3ximo Pedido
+v3.MainWindow.Loading=Carregando.. Por favor espere
+azbuddy.ui.menu.send_msg=Insira o texto a enviar para seu(s) amigo(s)
+ConfigView.section.file.merge.same.size=Tentar mesclar arquivos incompletos que tenham o mesmo tamanho
+v3.MainWindow.menu.view.toolbartext=Texto da Barra de Ferramentas
+ConfigView.pluginlist.broken=Quebrado
+GeneralView.label.filename=Nome\:
+DownloadManager.error.filetoobig=Arquivo Torrent \u00E9 muito grande
+TableColumn.header.maxuploads.info=\# m\u00E1ximo de peers aos quais faz upload simult\u00E2neamente
+azbuddy.dchat.user.status=Online\: %1, Postado\: %2
+webui.mode=Modo (*)
+iconBar.open.tooltip=Abrir Torrent(s)
+security.crypto.persist_for=Per\u00EDodo de persist\u00EAncia da senha
+MainWindow.menu.view.myshares=Meus Compartilhamentos
+dlg.install.mlab.subtitle=Instalando
+devices.info.copypending=%1 Arquivo(s) Aguardando Para Serem Copiados
+device.search.auto=Automaticamente procurar dispositivos
+ipCheckerWizard.progresstitle=Verificando IP 
+TableColumn.header.peersources.info=Fontes peer permitidas para o estabelecimento das conex\u00F5es com peers
+ConfigView.option.dm.dblclick.show=Mostrar Arquivo
+splash.openViews=Abrindo as Visualiza\u00E7\u00F5es
+MainWindow.dialog.exitconfirmation.text=Voc\u00EA quer realmente sair do Vuze?
+azbuddy.dchat.rchans.pub=Canal P\u00FAblico
+exportTorrentWizard.finish.title=Conclu\u00EDdo
+iconBar.down.tooltip=Mover para baixo
+DHTTransport.report.received_bit=recebeu %1 para %2 de %3
+library.core.wait=Um momento, por favor...\nO cliente Vuze est\u00E1 inicializando
+label.options.and.info=Op\u00E7\u00F5es/Info...
+ConfigView.section.file.defaultdir.autorename.tooltip=Isto impede um torrent de sobrescrever os arquivos de outro torrent quando os nomes dos arquivos s\u00E3o os mesmos
+ConfigView.label.periodiccheck=Procurar pela \u00FAltima vers\u00E3o periodicamente
+Progress.reporting.status.finished=Terminou
+plus.notificaiton.ExpiredEntry.s=Sua assinatura do Vuze Plus expirou\: <A %2>Renove Agora</A>
+TableColumn.header.maxupspeed=M\u00E1x de Velocidadde de Up
+MainWindow.menu.language.refresh=&Atualizar
+MessageBoxWindow.rememberdecision=Lembrar minha decis\u00E3o
+plus.notificaiton.ExpiredEntry.p={plus.notificaiton.ExpiredEntry.s}
+configureWizard.nat.title=Porta do NAT / Servidor 
+label.current_ip=Endere\u00E7o de IP Atual\:
+ConfigView.section.logging.log0type=Informa\u00E7\u00E3o
+upnp.refresh_mappings_on_bad_nat=Automaticamente atualizar os mapeamentos quando o status do NAT \u00E9 "firewalled"
+splash.plugin.UIinit=Inicializando a GUI do Plugin\:  %1
+DHTView.general.skew=\u00C2ngulo\:
+DHTView.general.users=Usu\u00E1rios\:
+SpeedTestWizard.test.panel.test.countdown=o teste termina em\:
+#Used by the webui plugin
+MyTorrentsView.menu.removeand.deletetorrent=Apagar &Arquivo Torrent 
+ConfigView.label.watchtorrentfolder=Importar novos .torrents automaticamente
+torrent.view.info=Exibir Info do Torrent...
+ConfigView.section.tracker.server.group.networks.info=Selecione as redes para as quais o tracker aceitar\u00E1 peers
+IrcView.actionnotsupported=Esta a\u00E7\u00E3o n\u00E3o \u00E9 suportada 
+ConfigView.section.tracker.announcecacheperiod=Anunciar o cache (ms)
+DHTView.operations.findNode=Achar Node
+iconBar.up.tooltip=Mover para cima
+MyTorrentsView.menu.archive=Arquivado(s)
+label.bt.connect=Conex\u00E3o BT
+ConfigView.section.proxy.group.tracker=Comunica\u00E7\u00F5es do Rastreador
+MainWindow.menu.vote=Sugerir um Recurso
+DHTView.operations.ping=Ping
+ConfigView.label.queue.newseedsmovetop=Mover torrents completados recentemente para a frente da lista de seeding
+ConfigView.label.disconnetseed=Desconectar seeds quando estiver ficando de seed
+MainWindow.menu.transfers.resumetransfers.keybinding.mac=Meta+Shift+.
+ConfigView.section.connection.group.http=HTTP
+device.retry.copy=Repetir C\u00F3pia
+ConfigView.label.enableSystrayToolTip=Exibir estatus de download na barra
+ConfigView.section.tracker.maxthreads=M\u00E1x. de pedidos coincidentes
+MainWindow.menu.file.create.fromdir=De um &Diret\u00F3rio
+ConfigView.section.security.system.managed=Prote\u00E7\u00E3o da chave gerenciada pelo sistema
+Button.mark=Marcar
+MyTorrentsView.menu.sl_remove_from_prof=Remover do perfil
+ConfigView.section.connection.advanced.SO_SNDBUF=Tamanho do Socket SO_SNDBUF [0\: usar o padr\u00E3o do SO]
+torrent.fix.corrupt.browse=Abrir Torrent
+memmon.heap.auto.increase.warning=Mem\u00F3ria Heap foi aumentado para %1. Isso ter\u00E1 efeito quando Vuze \u00E9 reiniciado.
+azbuddy.ui.menu.cat.share=Habilitar Assinaturas para Amigo(s)
+Formats.units.TiB=TiB
+ConfigView.label.seeding.rankType.peerSeed=Propor\u00E7\u00E3o de Peers\:Seed
+label.more.dot=Mais...
+PeersView.outgoingreqcount=Reqs de Sa\u00EDda
+DHTView.db.indirect=Indireto
+platform.win32.baddll.MxAVLsp=vcom Fix-it utilities
+DownloadManager.error.unsupportedencoding=Codifica\u00E7\u00E3o N\u00E3o Suportada
+exportTorrentWizard.exportfile.message=Insira o arquivo XML para exportar para
+MyTorrentsView.menu.clear_alloc_data=Limpar Estado de Aloca\u00E7\u00E3o
+ConfigView.section.file.decoder.nodecoder=Nenhum
+TorrentOptionsView.multi.title.full=Op\u00E7\u00F5es do Torrent
+device.router.is_mapping=Mapeamento autom\u00E1tico de portas
+MyTorrentsView.filter=Filtro\:
+configureWizard.transfer2.message=Bittorrent \u00E9 baseado em um protocolo "dar e receber"- em geral quanto mais r\u00E1pido \u00E9 o upload, mais veloz \u00E9 seu download - ent\u00E3o para baixar r\u00E1pido, e rapidamente obter uma boa taxa de compartilhamento, voc\u00EA precisa de uma boa velocidade de upload.\n\nDe qualquer forma, se seu upload for r\u00E1pido demais para sua conex\u00E3o, voc\u00EA pode sobrecarregar ela, resultando numa lentid\u00E3o greal e impactar outros aplic [...]
+ConfigView.section.tracker.client.connecttimeout=A conex\u00E3o expira em (segs)
+GeneralView.label.maxdownloadspeed.tooltip=Velocidade M\u00E1xima de Download [0\: ilimitada]
+azbuddy.ui.menu.enc=Encriptar a \u00C1rea de Transferencia
+ConfigView.label.piecereorder=Acrescentar dados a arquivos como baixados e reordenar pe\u00E7as como os avan\u00E7os download.
+dial.up=Discar
+device.itunes.status.notinstalled=O iTunes n\u00E3o est\u00E1 instalado
+MainWindow.menu.transfers.pausetransfers=&Pausar
+MainWindow.dialog.share.sharefile=Selecionar Arquivo para Compartilhar
+stats.general.smooth_secs=Tamanho m\u00E9dio da janela suavizada [secs]
+upnp.ignorebaddevices.reset.action=Resetar
+DHTView.general.contacts=Contatos\:
+ConfigView.section.security.nopw=Nenhuma senha foi fornecida
+MainWindow.menu.file.share.dircontentsrecursive=Conte\u00FAdos da Pasta... (&Recursivo)
+OpenTorrentWindow.mb.existingFiles.text=Alguns dos arquivos j\u00E1 existem na(s) pasta(s) destino que voc\u00EA especificou\:\n\n%1\nSe voc\u00EA continuar, o Vuze verificar\u00E1 o(s) arquivo(s) acima pelos dados corretos e sobrescrever\u00E1 se necess\u00E1rio.
+tagtype.discovered=Descobrir Tag
+TableColumn.header.min_sr={min.sr.window.title}
+GeneralView.label.downloadspeed=Velocidade de Download \: 
+v3.MainWindow.menu.view.sidebar=Barra Lateral
+AlertMessageBox.unread=Voc\u00EA n\u00E3o leu as mensagens de alerta - clique aqui para exib\u00ED-las.
+Trackers.column.seeds=Seeds
+MainWindow.menu.speed_limits.profile=Digite o nome do perfil
+ConfigView.section.sharing.permitdht=Permitir tracking descentralizado quando o rastreador est\u00E1 indispon\u00EDvel
+MySeeders.bigView.header={sidebar.LibraryCD}
+beta.wizard.link=Clique aqui para acessar a p\u00E1gina da Web vers\u00E3o beta
+MainWindow.menu.view=&Visualizar
+ConfigView.section.ipfilter.list.inrange=estava no intervalo
+ConfigView.section.style.addurlsilently=Abrir URLs passadas silenciosamente
+PeersView.host=Nome do Servidor
+TorrentInfoView.columns=Colunas da visualiza\u00E7\u00E3o 'Meus Torrents'
+ColumnSetup.categories=Categorias\:
+MyTrackerView.uploaded=Enviados
+network.ipv6.prefer.addresses=Preferir os endere\u00E7os IPv6 quando ambos IPv6 e IPv4 est\u00E3o dispon\u00EDveis
+metasearch.addtemplate.done.title=Modelo Adicionado
+importTorrentWizard.finish.title=Conclu\u00EDdo
+uninstallPluginsWizard.list.loaded=Por favor, escolha os plugins que voc\u00EA quer desinstalar.
+subscriptions.add.tooltip=Adicionar Assinatura
+devices.sidebar.onxcodecomplete=Quando Transcode Terminar
+label.in=Em
+ConfigView.label.autoSeedingIgnoreInfo=Torrents ignorados v\u00E3o para o final da fila de seeds. Eles n\u00E3o s\u00E3o automaticamente iniciados.\nIgnorar regras n\u00E3o se aplica a torrents que entrem no crit\u00E9rio da Primeira Prioridade.\nA menos que declarado de outro modo, use um valor de 0 para desativar uma regra.
+TableColumn.header.\#.info=N\u00FAmero da Posi\u00E7\u00E3o/Ordenamento
+search.dialog.text=Digite o texto para procurar novos torrents\:
+ConfigView.section.tracker.port=Ativar rastreador na porta HTTP
+azbuddy.dchat.ui.max.kb=M\u00E1ximo de caracteres por janela de bate-papo [KB]
+UpdateWindow.status.restartMaybeNeeded=Pode ser necess\u00E1rio reiniciar
+ArchivedFilesView.name={FilesView.name}
+ConfigView.group.override=N\u00E3o Levar as Op\u00E7\u00F5es em Conta
+TableColumn.header.activityType=Tipo
+fileDownloadWindow.status=Status\:
+TableColumn.header.activityActions=A\u00E7\u00F5es
+azbuddy.dchat.copy.channel.export=Backup do Canal
+ConfigView.label.xfer.bias_slack=KB/s m\u00EDnimo reservado para downloads completos
+MinimizedWindow.name=Nome\: 
+Trackers.column.updatein.info=Tempo para pr\u00F3xima atualiza\u00E7\u00E3o
+aznettorbrowser.install.text=Instalar Plugin do Navegador Tor para suportar navega\u00E7\u00E3o de conte\u00FAdo .onion e .i2p?
+PeerColumn.activationCount=Peers tentando se conectar\: %1
+ConfigView.section.interface.legacy=Legado
+TableColumn.header.Rating=Classifica\u00E7\u00E3o
+ConfigView.section.sharing.usessl=Usar SSL para recursos compartilhados (requer a configura\u00E7\u00E3o do Rastreador)
+IrcView.title.short=IRC
+ConfigView.label.startwatchedtorrentsstopped.tooltip=Adiciona novos .torrents no estado PARADO
+GeneralView.label.swarm_average_completion.tooltip=A porcentagem da conclus\u00E3o dos peers em m\u00E9dia na multid\u00E3o
+FileItem.low={SpeedTestWizard.name.conf.level.low}
+device.odpt.enable=Incluir torrents privados
+SWT.alert.erroringuithread=Um erro n\u00E3o manejado ocorreu na GUI, mais erros podem ser reportados.
+ConfigView.section.style.useTree=Exibir Arquivos em {library.name} exibi\u00E7\u00F5es (Requires Restart)
+TableColumn.header.trancode_completion=Progresso da Convers\u00E3o
+metasearch.addtemplate.failed.desc=Falhou em instalar o modelo da busca\: %1
+message.taking.too.long=Aparenta que isto est\u00E1 tomando mais tempo do que o esperado\nPressione 'ESC' se voc\u00EA deseja cancelar esta opera\u00E7\u00E3o
+Button.open=Abrir
+mdi.entry.chatsoverview={chats.view.heading}
+ConfigView.section.tracker.client.enabletcp=Habilitar protocolo HTTP/HTTPS para o rastreador  do cliente
+v3.MainWindow.search.last.tooltip=Retornar para os resultados da busca
+exportTorrentWizard.process.inputfilebad.title=Arquivo Torrent Inv\u00E1lido
+ConfigView.label.closetotray=Fechar minimiza para o Tray do Sistema
+tag.sharing.enable.title=Compartilhar com a Comunidade
+ConfigView.label.zeronewfiles=Alocar e zerar novos arquivos na cria\u00E7\u00E3o 
+ConfigView.filter=procurar op\u00E7\u00F5es aqui
+Scrape.status.disabled=Scrape Desativado
+ConfigView.section.connection.peersource.Incoming=Conex\u00F5es de entrada
+MainWindow.dialog.share.sharedircontents=Selecionar Conte\u00FAdos da Pasta para Compartilhar
+menu.delete.options.keybinding=DEL
+label.more=Mais
+TagRenameWindow.title=Renomear Tag
+devices.od=downloader desligado
+MainWindow.menu.view.configuration.keybinding=Meta+,
+ConfigView.section.transfer.autospeed.reset.button=Resetar
+DHTView.transport.bytes=Bytes
+pairing.explicit.enable=Habilitado
+subscriptions.config.auto=Download autom\u00E1tico
+ConfigView.label.systray=Tray do Sistema
+DHTView.general.dying=Morrendo\:
+Pieces.column.\#=\#
+upnp.releasemappings=Liberar os mapeamentos ao fechar
+sidebar.header.dvd={mdi.entry.dvdburn}
+DHTTransport.report.timeout=tempo esgotado, sem respostas de %1
+wizard.hint.mode=Dica\:\tVoc\u00EA pode Arrastar e Soltar um \u00FAnico arquivo ou diret\u00F3rio neste assistente\n\tpara escolher um arquivo ou diret\u00F3rio
+v3.MainWindow.currentDL=Atualmente Baixando
+ConfigView.section.file.decoder.label=Codifica\u00E7\u00E3o padr\u00E3o do torrent quando requerido pela sele\u00E7\u00E3o
+v3.MainWindow.button.stream=Stream
+ConfigView.section.tracker.publishenablepeerdetails=Publica os detalhes do peer
+OpenTorrentWindow.fileList.changeDestination.all=Mudar Destino de %1 Arquivos Para Mesma Pasta
+SpeedView.stats.total.since=Total (desde %1)
+ConfigTransferAutoSpeed.set.point=definir ponto (ms)
+subscriptions.listwindow.popularity=Popularidade
+label.more.info.here=Clique aqui para mais informa\u00E7\u00F5es
+TableColumn.header.completed=Completados
+TableColumn.header.maxdownspeed.info=M\u00E1x de Velocidade de Download por torrent
+deletedata.title=Aten\u00E7\u00E3o 
+iconBar.start.tooltip=Iniciar
+azmsgsync.install.text=O Plugin 'Mensagens Sync' \u00E9 requerido para o bate-papo descentralizado [desabilitado se j\u00E1 instalado]
+FilesView.size=Tamanho
+GeneralView.label.trackerurl=URL do rastreador \: 
+ConfigView.section.torrents=Torrents
+MySharesView.type.dir=Diret\u00F3rio
+DHTView.activity.type.4=Put Externo
+ConfigView.section.tracker.host.addurls=Garante que as URLs do rastreador est\u00E3o presentes nos torrents hospedados
+DHTView.activity.type.3=Put Interno
+DHTView.activity.type.2=Get Externo
+DHTView.activity.type.1=Get Interno
+importTorrentWizard.torrentfile.path=Caminho
+SpeedView.stats.upbias=Vi\u00E9s do Upload\:
+exportTorrentWizard.title=Exportar um torrent XML
+devices.copy.pending=C\u00F3pia de arquivo pendente
+ConfigView.label.openbar.complete=auto-abrir seeds
+dht.reseed.ip=Endere\u00E7o IP
+dlg.stream.plus.renew.text=Renove sua assinatura Vuze Plus para continuar a reproduzir os seus v\u00EDdeos que baixou.
+subs.prop.version=Vers\u00E3o
+label.trackers=Rastreadores
+ConfigView.label.prioritizemostcompletedfiles=Priorizar mais os arquivos de alta prioridade de acordo com a % completada e o tamanho do arquivo
+azbuddy.contextmenu=Enviar para um Amigo
+webui.homepage=Home Page (*)
+Plugin.trackerpeerauth.name=Autoriza\u00E7\u00E3o do Peer do Rastreador
+MainWindow.upgrade.assistant=Assistente de Atualiza\u00E7\u00E3o
+updater.progress.window.title=Tarefas de Instala\u00E7\u00E3o Atuais
+devices.sidebar.simple=Visualiza\u00E7\u00E3o Simples
+ConfigView.section.NATPMP=NAT-PMP
+subscriptions.column.nb-new-results=Novos Resultados
+MyTorrentsView.menu.rename.displayed=Renomear o Nome Exibido
+ConfigView.label.serverport=Porta de escuta TCP / UDP de entrada
+ConfigView.section.tracker.client.scrapeenable=Ativar scraping
+Formats.units.GiB=Gib
+importTorrentWizard.process.outputfileexists.title=O Arquivo Existe
+GeneralView.label.connected=conectado(s)
+tps.pex.details=Conectado \u00E0 %1 peers (pendente\: pex\=%2, outros\=%3)
+configureWizard.transfer.maxActiveTorrents=M\u00E1ximo de Ativos 
+remote.pairing.title=Emparelhamento remoto
+OpenTorrentWindow.mb.noDestDir.title=Diret\u00F3rio Destino n\u00E3o achado
+configureWizard.file.path=Caminho
+PeersView.menu.kick=Chutar
+MagnetPlugin.report.waiting_ddb=esperando pela inicializa\u00E7\u00E3o do DDB...
+MyTrackerView.bytesoutave=M\u00E9dia de Sa\u00EDda
+ConfigView.label.stop.seedcomp=Quando completar o seending
+azbuddy.dchat.rchans.anon=Canal An\u00F4nimo
+webui.pairing.info.y=O emparelhamento \u00E9 ativado, ver a conex\u00E3o-> op\u00E7\u00F5es de emparelhamento para mais detalhes.
+security.crypto.password.mismatch.title=Erro com a Senha
+wiki.fat32=http\://wiki.vuze.com/w/fat32_file_size_limit
+ConfigView.label.seeding.rankType.none=Nenhum
+webui.pairing.info.n=O emparelhamento est\u00E1 desativado, ver a conex\u00E3o-> op\u00E7\u00F5es de emparelhamento para obter informa\u00E7\u00F5es sobre este recurso
+Button.validate=Validar
+device.xcode.never=Nunca
+quick.view.scheduled.title=Agendar Exibi\u00E7\u00E3o R\u00E1pida
+MainWindow.menu.file.export.keybinding.mac=Meta+Shift+E
+sr_prog.window.message=Digite share intervalo rela\u00E7\u00E3o grava\u00E7\u00E3o andamento (por exemplo, 1.0 \= cada c\u00F3pia completa)
+TableColumn.header.completion.info=Representa\u00E7\u00E3o gr\u00E1fica dos % baixados
+Button.add=Adicionar
+subscript.import.fail.title=Falhou em Importar
+StartStopRules.0Peers=0 Peers
+MainWindow.menu.pairing=Emparelhamento remoto
+wizard.webseedseditor.edit.title=Editor de Seeds  HTTP
+remote.pairing.instruction2={remote.pairing.instruction} Alternativamente, escaneie o c\u00F3digo QR no seu dispositivo m\u00F3vel e passe sobre a necessidade de acessar o c\u00F3digo.
+xmwebui.required=Voc\u00EA precisa instalar o "Vuze Web Remote" plugin para que isto trabalhar\n\nVeja Ferramentas>Plugins>Assistente de Instala\u00E7\u00E3o...
+IrcView.noticefrom=Notifica\u00E7\u00E3o \: 
+# This is the end of the word "View".  It's left aligned under the icon bar item
+v3.iconBar.view.small.tooltip=Ver como lista avan\u00E7ada
+OpenTorrentWindow.mb.noGlobalDestDir.title=Diret\u00F3rio Destino
+SpeedTestWizard.abort.message.scheduled.in=teste agendado em ... %1 segundos"
+MyTorrentsView.menu.showdetails=Mostrar &Detalhes
+window.updateswt.ignore=Ignorar
+devices.xcode.autoCopy=Copiar automaticamente para a pasta
+PeersView.BlockView.Avail.NoHave=Peer tem; Voc\u00EA n\u00E3o
+pairing.ipv6=Endere\u00E7o IPv6 p\u00FAblico
+pairing.ipv4=Endere\u00E7o IPv4 p\u00FAblico
+Search.menu.engines=Modelos
+mdi.entry.archiveddownloadsview={archivedlsview.view.heading}
+ConfigView.section.security.backupkeys=Fazer backup das chave em um arquivo
+azbuddy.ui.new_buddy=Nova chave do amigo\:
+#
+# 2.0.4.4
+#
+ConfigView.section.style.guiUpdate=Atualizar a GUI a cada
+DHTOpsView.notAvailable=Gr\u00E1fico  DDB n\u00E3o dispon\u00EDvel
+MainWindow.menu.file.export.keybinding=Meta+E
+PiecesView.DistributionView.theyHave=Peda\u00E7os que o peer tem
+DHTView.title.full_v6=Base de Dados Distribu\u00EDda IPv6
+subscriptions.listwindow.popularity.reading=Lendo...
+ConfigView.label.start.onlogin=Iniciar o Vuze no login
+configureWizard.transfer.connection.7=adsl/cabo xxx/1024 kbps
+configureWizard.transfer.connection.6=adsl/cabo xxx/768 kbps
+UpdateWindow.cancel=Cancelar
+configureWizard.transfer.connection.5=adsl/cabo xxx/512 kbps
+progress.window.title=Opera\u00E7\u00E3o em Progresso
+configureWizard.transfer.connection.4=adsl/cabo xxx/384 kbps 
+TableColumn.header.resolution=Resolu\u00E7\u00E3o
+configureWizard.transfer.connection.3=adsl/cabo xxx/256 kbps 
+configureWizard.transfer.connection.2=adsl/cabo xxx/128 kbps 
+configureWizard.transfer.connection.1=modem
+ConfigView.section.security.unlockkey.error=Falhou em destrancar a chave - senha incorreta
+ConfigView.option.dm.dblclick.show._mac=Mostrar Arquivo(s) no Finder
+configureWizard.transfer.connection.0=Personalizado
+ConfigView.eta.abbreviated=E\:
+ConfigView.section.DNS={label.DNS}
+tag.type.ds.stop={ManagerItem.stopped}
+device.odauto.enable=Gerenciar automaticamente os downloads
+ConfigView.label.allowSendVersion=Permitir ao Vuze o envio an\u00F4nimo do n\u00FAmero da vers\u00E3o e ID aleat\u00F3ria enquanto procura por nova vers\u00E3o
+OpenTorrentFile.column.priority={FilesView.priority}
+tag.property.constraint=Restri\u00E7\u00E3o
+dlg.stream.plus.renew.title=Vuze Plus Renova\u00E7\u00E3o
+MainWindow.menu.view.beta=Programa Beta
+iconBar.bottom.tooltip=Mover para baixo
+wizard.choosedirectory=Escolha uma diret\u00F3rio
+MainWindow.menu.file.folder=&Pasta...
+TableColumn.header.Country.info=O pa\u00EDs onde o par est\u00E1 localizado
+wizard.multitracker.new=Novo...
+devices.restrict_access.msg=V\u00EDrgula separa IPs da lista para permitir [ou negar se tiver o prefixo -]
+MyTorrentsView.clearFilter.tooltip=Limpar o Filtro
+ConfigView.label.switchpriority.tooltip=Baixa prioridade reduz a largura de banda de upload fornecida ao torrent.
+Button.retarget=Realocar
+dialog.associations.prompt=O Vuze n\u00E3o \u00E9 o aplicativo padr\u00E3o para arquivos BitTorrent.\nVoc\u00EA gostaria de associar os arquivos .torrent com o Vuze?
+restart.error.oom=Mem\u00F3ria Esgotada
+columnChooser.columndescription=Descri\u00E7\u00E3o
+TableColumn.header.tag.copyoncomp={label.copy.on.comp}
+v3.topbar.menu.show.logo=Logotipo
+configureWizard.title=Assistente de Configura\u00E7\u00E3o
+ConfigView.section.tracker.sendjavaversionandos=Enviar a vers\u00E3o do Java e o nome do SO
+PeersView.BlockView.NoAvail.NoHave=Ningu\u00E9m tem
+ConfigView.section.connection.advanced.write_select_min=Gravar a espera m\u00EDnima selecionada (milis, padr\u00E3o %1)
+ConfigView.text.neverStart=Nunca Iniciar 
+TableColumn.header.remaining=Restando
+TableColumn.header.swarm_average_completion=Conclus\u00E3o da M\u00E9dia dos Peers
+config.external.browser.prog=Execut\u00E1vel do Navegador
+pairing.host=Endere\u00E7o de host (nome DNS)
+swt.uninstall.window.ok=Remover
+MyTorrentsView.menu.ipf_enable=Ativar filtro de IP
+GeneralView.label.completed=Completado \: 
+MyTorrentsView.menu.explore._windows=Mostrar no Explorer
+sidebar.sash.tooltip=F7 para rapidamente esconder/mostrar a barra lateral
+azbuddy.ui.table.last_msg=\u00DAltima Mensagem
+OpenTorrentWindow.changeDestination=Mudar o Destino
+popup.error.hideall=Esconder Todos
+GeneralView.label.maxdownloadspeed=Limite de Down
+br.backup.last.time=\u00DAltimo backup ocorreu em
+dialog.add.peers.msg=Digite o endere\u00E7o de cada peer na forma de <host>\:<port> - use v\u00EDrgula para separar v\u00E1rias entradas
+pairing.op.fail=Falha na opera\u00E7\u00E3o de emparelhamento
+DHTView.db.local=Local
+MainWindow.about.section.system=Sistema
+SystemTray.menu.exit=S&air
+MyTorrentsView.menu.exporthttpseeds=Export URLs de seed HTTP para a \u00C1rea de Transfer\u00EAncia
+PeersView.state=Estado
+smooth.config=(v\u00E1 em config para configurar a dura\u00E7\u00E3o da janela)
+ConfigView.section.mode.advanced=Avan\u00E7ado
+health.explain.blue=quando ficando de seed, significa que voc\u00EA ainda n\u00E3o est\u00E1 conectado a qualquer peer\nquando baixando, significa que voc\u00EA est\u00E1 conectado a alguns peers mas o rastreador est\u00E1 inativo
+ConfigView.section.tracker.maxposttimemultiplier=Multiplicador de tempo para processamento POST [0\:ilimitado]
+wizard.singlefile.help=Criar um torrent de um arquivo \u00FAnico 
+webui.access=Accesso (*)
+devices.xcode.tagshare=Compartilhar Transcodes Com Tag
+TableColumn.header.bad_avail_time.info=\u00DAltima vez que uma c\u00F3pia completa do download estava dispon\u00EDvel
+library.category.header=Categoria '%1'
+v3.menu.device.defaultprofile=Perfil padr\u00E3o
+ConfigView.section.style.addurlsilently.tooltip=Automaticamente baixar URLs dos .torrent passadas/soltas sem abrir a caixa de di\u00E1logo.
+SharedPortServer.alert.selectorfailed=Falhou em estabelecer um ouvidor para os dados de entrada.\nVerifique se as configura\u00E7\u00F5es de firewall est\u00E3o permitindo que o java(w).exe ajam como um 'servidor'
+ipCheckerWizard.checkFailed=Falhou, raz\u00E3o \:
+TorrentOptionsView.param.max.peers=N\u00FAmero m\u00E1ximo de conex\u00F5es [0\: ilimitadas]
+TrayWindow.menu.exit=S&air
+PiecesView.BlockView.NoHave=N\u00E3o Tem
+wizard.maketorrents.autoopen=Abrir o torrent para ficar de seed quando completo
+MainWindow.nat.status.tooltip.ok=OK para Alcan\u00E7ar (TCP)
+ConfigView.section.logging.udptransport=Ativar tra\u00E7o de transporte verboso UDP
+label.no.suggestions=Sem sugest\u00F5es
+device.model.name=Nome do Modelo
+exportTorrentWizard.process.unknownfail.title=Erro Inesperado 
+SpeedTestWizard.set.upload.button.apply=Aplicar
+TableColumn.header.DateTorrentLastActive=\u00DAltima Atividade
+# This is the beginning of the word "View".  It's right aligned under the icon bar item
+v3.iconBar.view.big.tooltip=Ver como Lista Simples
+label.anon.i2p=An\u00F4nimo (I2P)
+ConfigView.label.maxnumwant=Limitar o n\u00FAmero de peers que o rastreador pode retornar
+OpenTorrentWindow.startMode.seeding=Ficando de Seed
+TableColumn.header.crc32=CRC -32
+label.outbound=De sa\u00EDda
+ConfigView.auto=Autom\u00E1tico
+PeerSocket.bad_peer_id=ID de peer ruim
+ConfigView.label.lh.ext=Extens\u00F5es
+TorrentInfoView.torrent.encoding=Codifica\u00E7\u00E3o do torrent
+ConfigView.section.transfer.autospeed.enabledownadj=Ativar ajuste da velocidade de download
+subs.prop.last_result=\u00DAltimo novo resultado achado
+AlertMessageBox.comment=Coment\u00E1rio
+webui.tor_dest=Endere\u00E7o Tor
+GeneralView.label.trackerurlopen.tooltip=Clicar para abrir a p\u00E1gina principal do tracker
+DHTTransport.report.sending=enviando dados
+ConfigView.section.file.decoder.prompt.tooltip=Sempre mostrar uma janela quando houver uma escolha de codifica\u00E7\u00E3o estiver dispon\u00EDvel
+azbuddy.dchat.anon.nick=Apelido an\u00F4nimo compartilhado
+dialog.pause.for.period.title=Digitar Per\u00EDodo de Tempo
+MyTorrentsView.menu.health=Sobre a Qualidade
+SpeedTestWizard.test.panel.currinfo=Teste de banda BitTorrent.
+ConfigView.section.connection.encryption.min_encryption_level.tooltip=Simples - s\u00F3 handshake\nRC4 - corrente completa\nMaior encripta\u00E7\u00E3o requer mais CPU.
+ConfigView.label.watchtorrentfolderinterval.tooltip=Pausa at\u00E9 que a pasta seja verificada novamente
+label.protocol={Peers.column.Protocol}
+device.mediaserver.remove_all.desc=Voc\u00EA tem certeza que deseja remover todas os servidores de m\u00EDdias?
+FilesView.menu.open=&Abrir
+MainWindow.menu.file.closewindow=Fechar &Janela
+Subscription.menu.resetauth=Resetar os Detalhes da Autentica\u00E7\u00E3o
+installPluginsWizard.list.nullversion=N\u00BA da Vers\u00E3o
+OpenTorrentOptions.title=Abrir Op\u00E7\u00F5es de Torrent
+v3.MainWindow.menu.contentnetworks.manage=&Gerenciar as Redes HD
+DHTView.operations.sent=Enviados
+CacheView.speeds.fromCache=Do/Para o Cache
+SpeedView.stats.measured=Medido
+label.mute=Mudo
+ColumnRenameWindow.title=Renomear Coluna
+configureWizard.transfer2.test=Executar teste
+device.playnow.group=Executar Agora
+Trackers.column.updatein=Pr\u00F3ximo
+ipCheckerWizard.checkComplete=IP Completado\: 
+PiecesView.DistributionView.SeedAvl=Contribui\u00E7\u00E3o Avl do Seed
+change.url.msg.title=Mudar URL para '%1'
+UpdateWindow.columns.size=Tamanho
+ConfigView.label.openmytorrents=Abrir 'Meus Torrents' ao iniciar
+network.ipbinding.icon.show=Mostrar \u00EDcone de status na barra de status quando as liga\u00E7\u00F5es ativas
+MainWindow.dht.status.users=%1 Usu\u00E1rios
+FilesView.rename.choose.path=Escolher arquivo novo ou existente
+TableColumn.header.alerts={ConfigView.section.interface.alerts}
+device.import.title=Importar Dispositivo?
+ConfigView.section.irc=IRC 
+azmsgsync.install.ok.msg=Plugin de Mensagens Sync foi instalado com sucesso
+tag.type.man=Manual
+MainWindow.sr.status.tooltip.bad=Taxa de Compartilhamento %1 ruim\: < 0.5
+Formats.units.Mbit=Mbit
+subscription.request.add.message=%1 \u00E9 um alimentador RSS\n\nAdicionar uma nova assinatura?
+ConfigView.section.style.dropdiraction.opentorrents=Abrir Torrents
+xcode.deletedata.message.2=\n(uma c\u00F3pia ainda pode existir no '%1')
+ConfigView.section.file.readmblimit.explain=Este par\u00E2metro limita quanta mem\u00F3ria ser\u00E1 usada para armazenar leituras que ainda est\u00E3o pendentes no processamento.
+MainWindow.status.checking=verificando
+IrcView.help=Os comandos v\u00E1lidos s\u00E3o \:\n . /help \: exibe esta mensagem\n . /nick | /name \: muda o seu nome\n . /me a\u00E7\u00E3o \: envia uma a\u00E7\u00E3o\n . /msg mensagem sobre o apelido \: envia uma mensagem privada para <nick>\n . /r mensagem \: responde a \u00FAltima mensagem privada\n . /join \#canalB (n\u00E3o clique aqui,\u00E9 uma exemplo) \: muda o canal atual\tpara o canalB
+TableColumn.header.tag.downlimit={TableColumn.header.maxdownspeed}
+ClientStats.column.percent=%
+DHTView.general.leaves=Leaves\:
+ColumnSetup.availcolumns=Dispon\u00EDveis %1 colunas
+subscript.add.title=Instalar a Subscri\u00E7\u00E3o?
+MainWindow.menu.plugins.installPlugins=Assistente de Instala\u00E7\u00E3o...
+MyTorrentsView.menu.setSpeed.multi=%1 em %2 vagas de %3
+ConfigView.section.connection.prefer.udp=Preferir conex\u00F5es UDP
+ConfigView.label.seeding.numPeersAsFullCopy=Fingir que h\u00E1 1 c\u00F3pia completa para cada\n(0 \: N\u00E3o Fingir)
+ConfigView.section.ipfilter.clear.on.reload=Limpar flitros quando recarregar. Duranteo o processo recarga, os IPs n\u00E3o ser\u00E3o bloqueados. Se desmarcado, recente desbloqueios n\u00E3o ter\u00E3o efeito at\u00E9 reiniciar.
+columnChooser.columnname=Nome da Coluna
+OpenTorrentWindow.mb.openError.title=Erro ao Abrir
+subs.prop.assoc=Associa\u00E7\u00F5es
+# Not used, but could be renamed in all translation files to label.experimental :)
+OpenTorrentWindow.addFiles=&Adicionar Arquivos
+dlg.auth.trial.success.info=Arraste os arquivos de v\u00EDdeo a partir de sua biblioteca em "Criar novo DVD." Se voc\u00EA j\u00E1 tinha adicionado um v\u00EDdeo antes de instalar os componentes, por favor, adicione-o novamente.
+device.mediaserver.view.title=Servidores de M\u00EDdia
+label.no.messages=Sem Mensagem
+ConfigView.label.maxuploads=M\u00E1ximo de slots de upload padr\u00E3o por torrent
+statusbar.feedback.tooltip=Clique aqui para enviar feedback
+GeneralView.label.remaining=Tempo Restante \: 
+GeneralView.section.info=Informa\u00E7\u00F5es
+swt.updater.urlsgetter.platform=SWT para a plataforma \:
+popup.error.details=Detalhes
+Peers.column.lan=LAN
+OpenTorrentWindow.mb.openError.text='%1' n\u00E3o p\u00F4de ser aberto\:\\r\\n%2
+webui.pairing.autoauth=Habilitar prote\u00E7\u00E3o de senha padr\u00E3o\: username \= vuze, password \= code> acesso <pairing
+MainWindow.upgrade.hint2=Dica\:\tSe voc\u00EA deseja fechar o Vuze mais tarde, pressione Cancelar e\n\trenomeie Azureus2-new.jar para Azureus2.jar ap\u00F3s fechar
+#
+# > 2.0.8.0
+#
+OpenTorrentWindow.title=Abrir Torrent(s)
+MainWindow.upgrade.hint1=Dica\:\tPressionando Terminar faz tudo automaticamente
+TableColumn.header.peers=Peers
+PiecesView.completed=Completos
+Peers.column.network=Rede
+Button.search=Procurar
+splash.plugin.init=Inicializando o Plugin\: 
+platform.win32.baddll.sarah=fritz\! camada de aplica\u00E7\u00E3o firewall
+MainWindow.menu.speed_limits.load=Aplicar...
+device.model.num=N\u00FAmero do modelo
+Peers.column.UpRatio.info=A propor\u00E7\u00E3o "Enviado por voc\u00EA \: Enviado por outros" do Peer
+ConfigView.section.style.customDateFormat=Formato de data personalizado
+ConfigView.label.mindownloads=M\u00EDn. de downloads simult\u00E2neos
+mdi.entry.plus.free=Vuze Plus
+Browser.popup.error.no.access=Um ocorreu enquanto tentava acessar um recurso remoto.\nPor favor tente de novo mais tarde.\n
+ConfigView.label.lh.info=Por padr\u00E3o o lan\u00E7amento de um arquivo usa o aplicativo registrado para o tipo de arquivo.\nSubstituir esse comportamento, definindo aplica\u00E7\u00F5es expl\u00EDcitas para extens\u00F5es de arquivo dadas [lista separada por v\u00EDrgula].
+ConfigView.label.openbar.incomplete=Barras de download\: auto-abrir downloads
+label.exec.on.assign=Executar Em Atribuir
+ConfigView.label.max_peers_total=M\u00E1ximo de conex\u00F5es globais [0\: ilimitadas]
+plugin.installer.recommended.plugin=Plugin recomendado - por favor reveja e instale se requerido
+dlg.try.trial.title=Testar Grava\u00E7\u00E3o de DVD
+metasearch.export.select.template.file=Salvar o Modelo
+MyTorrentsView.menu.changeDirectory=Mudar o Diret\u00F3rio de Dados
+ConfigView.section.style.defaultSortOrder.desc=Descendente
+ConfigView.section.tracker.enableudp=Ativar o protocolo do tracker UDP
+ConfigView.section.plugins.magnetplugin=Gerenciador de Magnet URI
+FancyMenu.Header.Other=Outros
+Trackers.column.seeds.info=Seeds na multid\u00E3o
+wizard.maketorrents.autohost=Hospedar o torrent no rastreador embutido
+iconBar.editcolumns.tooltip=Configura\u00E7\u00E3o da Coluna
+ConfigView.section.style.reOrderDelay.never=Nunca
+Formats.units.MiB=Mib
+ConfigTransferAutoSpeed.upload.capacity.usage=Uso da Capacidade de Upload
+v3.MainWindow.text.my.account=Minha Conta
+sidebar.dropdown.tooltip=Mostrar a barra lateral no formato do menu
+PeersView.timetosend=Tempo para re-enviar o Peda\u00E7o (Modo Super-Seed)
+MainWindow.menu.transfers.pausetransfers.keybinding.mac=Meta+.
+ConfigView.text.neverIgnore=Nunca Ignorar
+TableColumn.header.maxupspeed.info=M\u00E1x de Velocidade de Upload por torrent
+IrcClient.connected=Conectado a 
+MyTrackerView.passive=Passivo
+SpeedTestWizard.finish.panel.max.download=Download m\u00E1x\:
+restart.error.url=http\://wiki.vuze.com/w/restarting_issues
+wizard.multitracker=Adicionar informa\u00E7\u00E3o Multi-Rastreador ao torrent
+importTorrentWizard.importfile.path=Caminho
+PeersView.gain=Ganho
+MyTorrentsView.menu.filter=Lista de Filtros...
+GeneralView.label.savein=Salvar em \:
+device.tivo.enable=Habilitar suporte TiVo
+TableColumn.header.activityText=Mensagem
+archivedls.view.infobar.text2=Mantenha seus downloads completos e parados na m\u00E3o arquivandos eles - use o clique direito do mouse e use o menu arquivar, restaure eles com simples clique na biblioteca.\nDownloads arquivados usam poucos recursos dentro do Vuze.. Para mais informa\u00E7\u00E3o <a href\="http\://wiki.vuze.com/w/Archiving_Downloads">clique aqui para visitar o Wiki..</a>
+archivedls.view.infobar.text1=Downloads Arquivados
+pairing.config.icon.show=Exibir \u00EDcone do Vuze Remote na barra de status
+DownloadManager.error.datamissing=Dados Ausentes
+v3.MainWindow.text.log.out=Assinar pra sair
+CacheView.general.size=Total
+menu.copy.hash.to.clipboard=Copiar Hash para \u00C1rea de Transfer\u00EAncia
+TableColumn.header.duration=Dura\u00E7\u00E3o
+ConfigView.label.sleep.info=Impedir o computador de dormir/suspender enquanto...
+ump.install=Atualiza\u00E7\u00E3o R\u00E1pida em Progresso\:\nInstalando um pequeno add-on de playback requerido para este v\u00EDdeo.
+Button.rename=Renomear
+ActivityView.legend.limit=Taxa limite
+ConfigView.section.file.decoder.showlax=Mostrar menos codifica\u00E7\u00F5es
+device.offlinedownloader.view.title=Downloaders Off-line
+ConfigView.title.full=Op\u00E7\u00F5es
+TableColumn.header.DateCompleted.info=Data em que o download do torrent foi completado
+ConfigView.section.style.ShowTabsInTorrentView=Exibir sub-abas nas exibi\u00E7\u00F5es da Biblioteca (Requer Reiniciar)
+ConfigView.section.general=Geral
+ConfigView.pluginlist.scan=Escanear por novos Plugins
+ConfigView.option.dm.dblclick.open.browser={MyTorrentsView.menu.browse}
+mdi.entry.dvdburn.new=Cria Novo DVD
+ConfigView.label.popup.timestamp=Adicionar estampas de tempo aos alertas popup
+ConfigView.label.openbar=Auto-abrir a barra de download
+OpenTorrentWindow.startMode.forceStarted=For\u00E7ar In\u00EDcio
+azbuddy.dchat.fave.chats=Bate-papos Favoritos
+PeersView.Messaging=Enviando Mensagens
+ConfigView.label.downloading.testTime=Per\u00EDodo de avalia\u00E7\u00E3o da velocidade de download [seg]
+ConfigView.pluginlist.column.loadAtStartup=Carregar ao at Iniciar
+wizard.tracker.local=Usar o Rastreador Embutido do Vuze
+splash.firstMessageNoI18N=(\: Vuze \:)
+TableColumn.header.sr_prog.info=Mostra a data em que a rela\u00E7\u00E3o de uma parte de Download atingido certos valores
+# used for more than just "delete data"
+deletedata.noprompt=N\u00E3o me alertar de novo
+Stats.title.full=Estat\u00EDsticas
+MyTorrentsView.dialog.setPosition.title=Definir Posi\u00E7\u00E3o
+Button.unmarkSelected=Desmarcar os Selecionados
+ConfigView.label.show.cat.but=Exibir Bot\u00F5es de Categorias
+ConfigView.label.checkOncompletion=Verificar novamente os peda\u00E7os quando o download for conclu\u00EDdo
+Peers.column.as.info=Detalhes do AS do PEER (Sistema Aut\u00F4nomo)
+ColumnSetup.chosencolumns=Colunas Escolhidas
+PiecesView.priority.info=a prioridade da conclus\u00E3o deste peda\u00E7o, mas n\u00E3o preste muita aten\u00E7\u00E3o a ele
+SpeedTestWizard.set.upload.title=Definir Limites de Upload e Download
+GeneralView.label.trackerurlupdate=Atualizar o Rastreador
+ConfigView.section.connection.encryption.require_encrypted_transport=Requer transporte encriptado
+DHTTransport.report.rerequest_bit=re-requisitando %1 para %2 de %3
+Progress.reporting.no.history.to.display=N\u00E3o h\u00E1 mensagens detalhadas a exibir
+OpenTorrentOptions.show.label=Quando abrindo um torrent, exiba esta janela\:
+ConfigView.section.plugins.irc=IRC
+dlg.auth.denied.link=<A HREF\="info">Informa\u00E7\u00F5es sobre Negativa de Ativa\u00E7\u00E3o dos c\u00F3digos</A>
+Generic.words.scan=Escanear
+azbuddy.tracker.bbb.status.idle=Sem acelera\u00E7\u00E3o
+security.certcreate.createfail=Cria\u00E7\u00E3o do certificado falhou
+ConfigView.section.style.use_show_parent_folder=Usar "%1" em vez de "%2" nos menus do torrent
+tag.azbuddy.dchat.shares=Compartilhar no Bate-papo
+SpeedTestWizard.finish.panel.disabled=desativado
+TableColumn.header.tag.count=\# Itens
+configureWizard.file.fastResume=Ativar resumo r\u00E1pido 
+ConfigView.section.security.op.error=Falhou em completar a opera\u00E7\u00E3o\:\n    %1
+remote.pairing.instruction=Simplesmente digite o c\u00F3digo abaixo nos espa\u00E7os providos por qualquer aplicativo remoto.
+TableColumn.header.savepath.info=A pasta ou arquivo destino para os dados do torrent
+swt.updater.urlsgetter.downloading=Obtendo uma lista de mirrors de
+devices.auto.start=Auto-iniciar
+FilesView.menu.setpriority.normal=&Normal 
+configureWizard.transfer2.mselect.info=A entrada xxx/<valor> denota a velocidade da conex\u00E3o de upload de <valor> bits-por-segundo.\nPor exemplo, se voc\u00EA tem uma conex\u00E3o ADSL com 768 Kbps de downstream e 384 Kbps para upstream, selecione 'xxx/384 kbit/sec'.\nVoc\u00EA deve indicar o valor mais pr\u00F3ximo poss\u00EDvel, se sua velocidade exata n\u00E3o for exibida.
+ConfigView.section.plugins.xml_http_if=Interface XML/HTTP
+iconBar.stream=Executar Agora
+v3.iconBar.view.big=Vi
+sidebar.LibraryUnopened=N\u00E3o Observado
+MyTorrentsView.menu.stop=Par&ar
+MyTorrentsView.menu.explore=Mostrar Arquivo
+MainWindow.menu.help.about=Sobre o Vuze
+label.none.assigned=Nada atribu\u00EDdo
+MainWindow.nat.status.tooltip.bad=Problema para alcan\u00E7ar Firewall/NAT (TCP). V\u00E1 at\u00E9 o Wiki por ajuda
+archive.info.text=Os downloads selecionados ir\u00E3o ser arquivados e disponibilzados sob o nome de "Downloads Arquivados" no menu "Visualizar".\n\nVeja <a href\="http\://wiki.vuze.com/w/Archiving_Downloads">o Wiki</a> para mais informa\u00E7\u00F5es.
+TableColumn.header.category.info=Nome da categoria a qual o torrent pertence
+DownloadManager.error.operationcancancelled=Opera\u00E7\u00E3o cancelada
+label.dismiss.all=Dispensar Todos
+ConfigView.label.seeding.firstPriority.shareRatio=Uma propor\u00E7\u00E3o de compartilhamento inferior a
+device.mediaserver.remove_all=Remover Todos Servidores de M\u00EDdia
+IPChecker.external.loadingwebpage=Carregando p\u00E1gina da web
+TableColumn.header.tag.group=Grupo
+subscriptions.config.autostart.min=S\u00F3 come\u00E7am  se >\= MB [0\: ilimitado]
+azsubs.contextmenu.lookupassoc=Procurar as associa\u00E7\u00F5es das subscri\u00E7\u00F5es
+v3.MainWindow.button.resume=Resumir
+TorrentOptionsView.param.max.seeds=N\u00FAmero m\u00E1ximo de conex\u00F5es de seed [0\: limite de conex\u00F5es]
+platform.win32.baddll.iFW_Xfilter=iolo Personal firewall
+TableColumn.header.\#=Ordem
+dhttracker.tracknormalwhenoffline=S\u00F3 rastrear torrents normais quando o tracker deles est\u00E1 indispon\u00EDvel
+MainWindow.menu.file.open.url=&Local...
+Peers.column.peer_byte_id=ID do Peer
+MainWindow.menu.file.open.uri=URL, Magnet ou Hash...
+torrent.comment.rat2=Coment\u00E1rio(s)\: %1
+torrent.comment.rat1=Classifica\u00E7\u00E3o m\u00E9dia\: %1 (pontua\u00E7\u00F5es\: %2)
+MainWindow.upgrade.explanation.manual=Voc\u00EA pode atualizar manualmente fechando o Vuze, baixando a nova vers\u00E3o e reiniciando o Vuze
+MainWindow.about.internet.forumdiscussion=F\u00F3runs
+pairing.ui.icon.tip=Status da Conex\u00E3o do Vuze Remoto
+ConfigView.label.seeding.ignore=Ignorar Regras
+ConfigView.section.mode.advanced.text1=Acesso completo para todas as op\u00E7\u00F5es e recursos
+subscript.none.subscribed=Clique para ver as subscri\u00E7\u00F5es dispon\u00EDveis para este conte\u00FAdo
+TableColumn.header.smoothup=Up Suavizado
+FilesView.dialog.priority.text=0\=Normal, 1\=Alta, 2\=Alt\u00EDssima...
+alert.raised.at.close=(Mensagem do fechamento anterior do Vuze)
+SystemTray.menu.closealldownloadbars=Fechar &Todas as Barras de Download
+SpeedTestWizard.finish.panel.max.seeding.upload=M\u00E1x. de upload enquanto ficando de seed \:
+ConfigView.section.ipfilter.persistblocking=Salvar detalhes dos IPs bloqueados durante os rein\u00EDcios
+PiecesView.type=Tipo
+ConfigView.section.plugins.TrackerWeb=Rastreador de Web
+TableColumn.header.CountryFlag.info=Bandeira do pa\u00EDs do par
+SpeedTestWizard.abort.message.interrupted=TorrentSpeedTestMonitorThread foi interrompido antes que o teste completasse
+ConfigView.boolean.irclog=Ativar registro da atividade no canal (em IRC_log.htm)
+ConfigView.section.style.reOrderDelay=Reordenar tabelas a cada N atualiza\u00E7\u00F5e(s) da GUI [0\: nunca]
+MySharesView.type.dircontentsrecursive=Conte\u00FAdo do diret\u00F3rio (recursivo)
+GeneralView.label.status=Status \:
+ConfigView.section.style.alwaysShowTorrentFiles=Sempre mostrar os arquivos Torrent em Detalhes/Arquivos
+GeneralView.label.uploaded=Enviados \:
+ConfigView.section.update.autodownload=Auto-baixar atualiza\u00E7\u00F5es e alertar quando a instala\u00E7\u00E3o estiver pronta
+trackername.prefs.message=V\u00EDrgula lista separada de nomes de host rastreador\nPor exemplo\: a.b.com; c.d.net
+ConfigView.label.removeOnStop=Remover o torrent da lista ap\u00F3s automaticamente parar
+OpenTorrentWindow.diskUsage=%1 de %2
+device.rss.localonly=Restringir o acesso a este computador s\u00F3
+ConfigView.section.file.nativedelete._windows=Mover os arquivos apagados para o Recycle Bin
+MyTorrentsView.menu.changeTracker=&Adicionar a URL do Rastreador 
+MainWindow.menu.view.myshares.keybinding=Meta+3
+ConfigView.section.connection.port.rand.enable=Escutar portas rand\u00F4micamente ao iniciar
+MagnetPlugin.report.downloading=baixando de %1
+MyTorrentsView.dialog.setNumber.upload=upload
+configureWizard.transfer.maxUploadsPerTorrent=M\u00E1ximo de Uploads por Torrent 
+FilesView.fullpath=Mostrar Caminho Completo
+Formats.units.Tbit=Tbit
+MainWindow.menu.view.mytracker.keybinding=Meta+2
+ConfigView.section.transfer.setmark=Alterar/Limpar marcas\: o total das est\u00E1tisticaas de transfer\u00EAncias ir\u00E3o ser exibidas deste ponto em diante
+MagnetPlugin.use.md.download.name=Download de metadados para %1
+externalLogin.auth_method_proxy=Usar m\u00E9todo de captura de cookies extendido. Se isto falhar em funcionar, desative a op\u00E7\u00E3o e tente de novo
+IrcView.errormsg=Sintaxe Errada em /msg \: /msg usu\u00E1rio texto
+ConfigView.label.dl.add.req.attention=Real\u00E7ar a se\u00E7\u00E3o de downloading quando um download for adicionado
+ConfigView.label.autoopen.detailstab=Auto-abrir a Aba de Detalhes quando
+apply.to.current=Aplicar para Atual
+ConfigView.section.plugins.update=Atualiza\u00E7\u00E3o dos Plugins
+OpenTorrentWindow.mb.invaliddefsave.text=O local para salvar '%1' \u00E9 inv\u00E1lido.\n\nQuando voc\u00EA fechar este dialogo, ir\u00E1 ser perguntado para mudar isso.\n\nO local padr\u00E3o para salvar pode ser configurado via Ferramentas->Op\u00E7\u00F5es->Arquivos.
+label.vuze.services=Servi\u00E7os do Vuze
+dht.logging=Ativar o rastreamento da atividade
+tag.property.trackers={label.trackers}
+MyTorrentsView.menu.setDownSpeed=Definir Velocidade de Download
+subs.prop.num_unread=N\u00FAmero de resultados n\u00E3o lidos
+ConfigView.section.style.dropdiraction.sharefolder=Compartilhar Diret\u00F3rio
+ConfigView.section.tracker.separatepeerids.info=Aumenta a anonimidade se estiver baixando/enviando anonimamente\nenquanto estiver usando um conex\u00E3o com o rastreador n\u00E3o-an\u00F4nima 
+devices.xcode.prof_def=Perfil transcode Padr\u00E3o
+ConfigView.label.piecereorderminmb=Apenas reordenar arquivos maiores que esse (em MB)
+mdi.entry.tagsoverview={tags.view.heading}
+Wizard.Subscription.search.subtitle2.sub2=Torrents da Web
+iconBar.start=Iniciar
+Wizard.Subscription.search.subtitle2.sub1=Filmes em HD, Shows da TV, Filmes, Trailers na Rede Vuze
+iconBar.comment=Coment\u00E1rio
+azbuddy.chat.title=Chat do Vuze
+MainWindow.menu.tools.netstat={Views.plugins.aznetstatus.title}...
+TableColumn.header.DateFileCompleted=Arquivos completos
+GeneralView.label.updatein=Atualizar em \:
+TorrentOptionsView.param.max.uploads=N\u00FAmero m\u00E1ximo de slots de upload [m\u00EDnimo\: 2]
+TableColumn.header.device=Dispositivo
+ConfigView.section.style.doNotUseGB.tooltip=Se marcado, o Vuze continuar\u00E1 a usar MB mesmo para tamanhos maiores do que 1024MB
+proxy.socks.ui.icon.tip=Status de SOCKS \: %1\nClique duplo para status\nClique direito para op\u00E7\u00F5es
+TableColumn.header.writerate=Taxa de Escrita
+dlg.auth.trial.success.line1=Vuze est\u00E1 pronto para criar DVDs.
+TableColumn.header.chat.msg.out=Aguardando Mensagem
+jvm.reset=Restaurar op\u00E7\u00F5es JVM para o padr\u00E3o de instala\u00E7\u00E3o
+splash.initializeUIElements=Inicializando os Elementos da Interface do Usu\u00E1rio
+azbuddy.addtorrent.title=Confirmar Download?
+MyShares.column.category=Categoria
+label.fave=Favorito
+DHTView.transport.out=Saiu \:
+subs.prop.is_auto=Auto-baixar os novos resultados
+PeersView.menu.snubbed=&Desprezado
+ConfigView.section.style.defaultSortOrder=Ordem de Organiza\u00E7\u00E3o Padr\u00E3o
+ConfigView.section.proxy.enable_socks.peer=Ativar o proxying das comunica\u00E7\u00F5es com os peers (apenas para conex\u00F5es de sa\u00EDda) [requer reiniciar]
+Progress.reporting.no.reports.to.display=N\u00E3o h\u00E1 Relat\u00F3rios de Progresso para exibir desta vez
+ConfigView.label.xfs.allocation=Alocar novos arquivos usando um m\u00E9todo espec\u00EDfico para o sistema de arquivos XFS
+TableColumn.header.download.info=Quantia de dados recebida do peer
+label.browser=Navegador
+cat.rss.gen=Criar feed local RSS
+config.internal.browser=Navegador Interno
+SpeedView.stats.currentPing=Ping Atual\:
+DownloadManager.error.badsize=Tamanho incorreto
+TableColumn.menu.maxuploads=\# Uploads no M\u00E1x.
+TableColumn.header.date_added=Data adicionada
+TableColumn.header.class=Classe
+ConfigView.section.connection.advanced.socket.group=Op\u00E7\u00F5es do Socket
+ConfigView.section.logging=Registro
+speedtest.wizard.title=Teste de Velocidade
+ConfigView.section.proxy=Op\u00E7\u00F5es do Proxy
+TableColumn.header.tag.uprate={TableColumn.header.upspeed}
+MainWindow.menu.community.wiki=Wiki da &Comunidade
+ActivityView.legend.peeraverage=M\u00E9dia
+subscriptions.rss.enable=Criar Feeds RSS de assinaturas
+MyTrackerView.badnat.info=Seeds/Peers que falharam a uma checagem do NAT, se ativados
+ConfigView.label.bindip.details=Exemplo\: 192.168.1.5;eth0;eth1[2] prender\u00E1 o IP especificado a todos os IPs da 1\u00AA interface e ao 3\u00BA IP da 2\u00AA interface.\nO 1\u00BA IP ser\u00E1 usado para todos os servi\u00E7os, todos os outros s\u00E3o usados s\u00F3 para o balan\u00E7o da carga.\nAs seguintes interfaces est\u00E3o dispon\u00EDveis\:\n%1
+ConfigView.section.ipfilter.list.notinrange=n\u00E3o estava em qualquer intervalo
+TableColumn.header.seeds=Seeds
+button.columnsetup.tooltip=Configura\u00E7\u00E3o da Coluna
+security.crypto.persist_for.session=Esta sess\u00E3o
+wizard.webseed.configuration=Configur\u00E3\u00E7\u00E3o de Seed HTTP
+OpenTorrentWindow.mb.notTorrent.text=N\u00E3o p\u00F4de abrir '%1'.  N\u00E3o aparenta ser um arquivo .torrent.\n\nAlguns dos dados recebidos\:\n%2
+azbuddy.dchat.decentralized=Bate-papo Descentralizado
+GeneralView.label.comment=Coment\u00E1rio sobre o Torrent \: 
+ConfigView.label.save_list.clear=Remover hist\u00F3rico
+label.wrap.text=Quebrar texto
+remote.pairing.test.unavailable=Oops, n\u00E3o foi poss\u00EDvel determinar sua conex\u00E3o remota. <A HREF\="retry">Try again</A>
+iconBar.switch.tooltip=Escolher a Interface de Usu\u00E1rio do Vuze
+TableColumn.header.seeds.fullcopycalc=%2 c\u00F3pias completas assumidas para %1 peers
+v3.topbar.menu.show.plugin=\u00C1rea dos Plugins
+v3.menu.device.exploreTranscodes._windows=Mostrar arquivos no Explorer
+devices.contextmenu.od.auto=<Autom\u00E1tico>
+security.certtruster.intro=O certificado de seguran\u00E7a foi emitido por uma empresa na qual voc\u00EA n\u00E3o confia
+ConfigView.section.style.xulRunnerPath=Especificar o caminho do XulRunner / Firefox manualmente [requerido para o FF3; requer reiniciar]
+MyTrackerView.announces=An\u00FAncios
+metasearch.template.version.bad=O modelo da busca '%1' n\u00E3o pode ser instalado at\u00E9 que voc\u00EA atualize o Vuze
+azbuddy.dchat.copy.channel.url=URL do Canal
+ConfigView.label.minSeedingTime=Tempo m\u00EDnimo para ficar de seed em segundos
+OpenTorrentWindow.torrent.options=As seguintes configura\u00E7\u00F5es se aplicar\u00E3o aos torrents selecionados abaixo\:
+PeersView.upload.info=Seu upload total para o peer.
+MyTrackerView.bytesinave=M\u00E9dia de Entrada
+TableColumn.header.CountryFlagSmall.info=Pequena bandeira do pa\u00EDs do par
+ConfigView.label.stop.Sleep=Computador em espera
+Subscription.menu.export=Exportar
+restart.error=Reiniciar falhou\:\n%1\nVeja <A HREF\="{restart.error.url}">problemas ao reiniciar</a>.
+DHTTransport.report.send_timeout=tempo de enviar esgotado
+label.test.types=Tipos de Teste
+play.select.content=Selecionar Conte\u00FAdo para Reproduzir
+menu.plus=Vuze Plus
+# %1 = "in kbps" or ""; %2 = "upload" or "download"
+MyTorrentsView.dialog.setNumber.text=Insira um n\u00FAmero %1 para mudar %2 para\:
+Plugin.localtracker.autoadd.info=Automaticamente adicionar estes peers locais [';' endere\u00E7os separados, ex\: 1.2.3.4]
+Trackers.column.status=Status
+PeersView.uploadspeed.info=A sua velocidade de upload para o peer
+TableColumn.header.down.info=Quantia de dados atuais recebida dos outros usu\u00E1rios
+MainWindow.dht.status.tooltip=Quando a Base de Dados Distribu\u00EDda est\u00E1 rodando isto mostra o n\u00BA estimado de usu\u00E1rios atualmente online
+azinstancehandler.alert.portclash=Conflito de portas detectado na LAN\: %1 j\u00E1 em uso por outro usu\u00E1rio do Vuze, selecione nova(s) porta(s) aleat\u00F3ria(s) para a escuta TCP  / UDP de entrada [entre %2 e %3]. 
+MainWindow.menu.speed_limits.schedule.msg=As regras atuais que controlam a aplica\u00E7\u00E3o autom\u00E1tica da velocidade limite de perfis
+OpenTorrentWindow.mb.alreadyExists.text=<A HREF\="%1">%3</A> j\u00E1 foi adicionado como '%2'
+PeerManager.status.ok=OK
+ConfigView.section.mode.title=Profici\u00EAncia do Usu\u00E1rio
+label.n.will.be.downloaded=%1 ir\u00E1 ser baixado
+external.browser.manual=Manual
+metasearch.addtemplate.dup.title=Modelo Duplicado
+ConfigView.section.interface.enabletray=Ativar o Tray do sistema [requer reiniciar]
+PeersView.BlockView.AvailCount=Contagem da Disponibilidade
+iconBar.openFolder.tooltip=Abrir uma Pasta
+Plugin.localtracker.name=Descobridor de Peers em LAN
+restart.error.bad=Arquivo de formato ruim para '%1'
+CacheView.writes.title=Escritas E/S
+TableColumn.header.peakup=Up Alcan\u00E7ado
+v3.MainWindow.menu.publish=&Publicar
+MainWindow.menu.view.show=Mostrar
+configureWizard.transfer2.test.info=Selecione para executar um teste de velocidade abrangente
+subscriptions.config.autostart.max=S\u00F3 come\u00E7am se <\= MB [0\: ilimitado]
+library.unopened.header=%1 item
+ConfigView.section.security.restart.title=Requer Reiniciar
+MyTorrentsView.menu.group=Grupo...
+label.set.shortcut=Configurar Atalho
+beta.wizard.forum.url=http\://www.vuze.com/forum_beta.start
+ConfigView.section.connection.tcp.enable=Ativar TCP
+label.reset.piece=Restaurar Peda\u00E7o
+ArchivedFilesView.title.short={FilesView.title.short}
+subscriptions.listwindow.title=Descobridor de Subscri\u00E7\u00F5es
+splash.initializeGM=Inicializando o Gerenciador Global de Torrents
+Peers.column.%=%
+MainWindow.menu.tools=&Ferramentas
+Peers.column.\#=\#
+ConfigView.section.connection.http.enable=Ativar
+diagnostics.log_found=O Vuze n\u00E3o fechou apropriadamente. Verifique por quaisquer <A HREF\="%1">arquivos log de diagn\u00F3stico</A>. Tamb\u00E9m leia o artigo do wiki <A HREF\="http\://www.azureuswiki.com/index.php/Vuze_disappears"> Vuze Disappears</A> para mais informa\u00E7\u00E3o. 
+plugins.basicview.activity=Atividade\:
+ArchivedDownloadsView.header={archivedlsview.view.heading}
+dlg.auth.denied.line1=Seu C\u00F3digo de Ativa\u00E7\u00E3o do Vuze Plus foi negado. Por favor clique abaixo para obter mais informa\u00E7\u00F5es
+natpmp.routeraddress=Endere\u00E7o da esta\u00E7\u00E3o [em branco\: auto]
+Button.availableSubscriptions=Subscri\u00E7\u00F5es Dispon\u00EDveis
+MyTorrentsView.menu.moveDown=&Para Baixo
+UpdateWindow.quit=Sair
+PeersView.host.info=O nome do servidor do peer, quando dispon\u00EDvel (pode afetar a performance)
+wizard.directory.help=Criar um torrent de um diret\u00F3rio
+Peers.column.maxdownspeed=Velocidade M\u00E1x. de Download
+DHTView.general.uptime=Tempo de Upload\:
+MainWindow.menu.help.support=&Ajuda e Suporte
+MyTorrentsView.menu.moveTop=&Topo
+ConfigView.label.xfs.allocation.tooltip=Por favor tenha certeza /usr/sbin/xfs_io est\u00E1 apropriadamente instalado no seu sistema. Na maioria das distribui\u00E7\u00F5es Linux, est\u00E1 inclu\u00EDdo no pacote "xfsprogs".
+MyTorrentsView.menu.manual.shared_peers=Manual (pelos peers)
+TorrentOptionsView.param.reset.button=Resetar
+wizard.multitracker.edit.newtracker=Novo Rastreador
+PiecesView.title.full=Peda\u00E7os
+menu.register=Ativa\u00E7\u00E3o do Vuze Plus
+upnp.mapping.trackerclientudp=Porta do Cliente Tracker UDP
+ConfigView.section.connection.networks.Public=Rede de IP p\u00FAblica (n\u00E3o an\u00F4nima)
+MyTorrentsView.menu.editTracker=&Editar URL(s) do Rastreador
+IrcView.privatefrom=De
+ConfigView.section.mode.resetdefaults=Redefinir configura\u00E7\u00E3o para valores padr\u00E3o (reiniciar recomendado)
+TableColumn.header.peersources=Fontes Peer
+DHTView.general.live=Ao vivo\:
+ConfigView.label.moveifsamedrive=Mas somente fa\u00E7a isso quando a fonte e o destino s\u00E3o sistema de arquivos diferentes
+configureWizard.file.message3=O Vuze baixar\u00E1 os arquivos em uma pasta espec\u00EDfica, voc\u00EA pode escolher esta pasta aqui\:
+subs.prop.is_public=P\u00FAblico
+configureWizard.file.message2=O Vuze \u00E9 capaz de resumir seus arquivos instant\u00E2neamente, adicionando alguns dados de resumo aos seus torrents. Usando esta fun\u00E7\u00E3o, voc\u00EA ser\u00E1 tamb\u00E9m resumir\u00E1 peda\u00E7os parcialmente baixados.
+configureWizard.file.message1=O Vuze salvar\u00E1 os torrents abertos em uma pasta espec\u00EDfica, voc\u00EA pode escolher esta pasta aqui\:
+ConfigView.label.autoadjust=Automaticamente ajustar essas configura\u00E7\u00F5es com base na velocidade de conex\u00E3o
+webui.pairingenable=Permitir o emparelhamento para este plugin (op\u00E7\u00F5es de teste ser\u00E1 ativado depois que os detalhes de emparelhamento atuais s\u00E3o sucesso publicado)
+devices.tivo.machine=Nome da m\u00E1quina TiVo
+ConfigView.section.ipfilter.start=IP Inicial
+wizard.directory=Diret\u00F3rio
+globalmanager.download.remove.veto=A\u00E7\u00E3o de Remo\u00E7\u00E3o Vetada
+ConfigView.section.file.defaultdir.ask=Diret\u00F3rio padr\u00E3o\: 
+upnp.alert.lostdevice=UPnP\: Conex\u00E3o com o servi\u00E7o '%1' no dispositivo UPnP '%2' perdida
+MyTorrentsView.menu.sl_add_to_prof=Adicionar/Atualizar o Perfil
+devices.view.heading=Convertendo m\u00EDdia para reprodu\u00E7\u00E3o em dispositivo
+azbuddy.ui.table.ss=SS
+SystemTray.menu.open_global_transfer_bar=Mostrar a Barra de Transfer\u00EAncias
+devices.downloading=Baixando
+ConfigView.section.stats.graph_update_dividers=Exibir linha vertical a cada 60 segundos
+Formats.units.Gbit=Gbit
+TableColumn.header.timesincedownload=Inativo pra Baixo
+ConfigView.section.queue.seeding.ignore=Ignorar Regras
+azsubs.contextmenu.addassoc=Adicionar a associa\u00E7\u00E3o de subscri\u00E7\u00E3o
+ConfigView.section.connection.advanced.mtu=Unidade de Transmiss\u00E3o M\u00E1xima da Linha (MTU)
+Peers.column.Encryption.info=N\u00EDvel da encripta\u00E7\u00E3o em uso
+ConfigView.section.connection.advanced.bind_port=Prender a porta local [0\: desativado]
+tps.tracker.cache1=Peer cache\: usado\=%1
+aznettorbrowser.install.subtitle=Instalando Plugin do Navegador Tor
+MainWindow.dialog.restartconfirmation.title=Reiniciar o Vuze?
+ConfigView.section.ipfilter.enable.descriptionCache.tooltip=Quando desatida, as descri\u00E7\u00F5es n\u00E3o ser\u00E3o lembradas
+sidebar.Activity=Notifica\u00E7\u00F5es
+upnp.selectedinterfaces=Interfaces selecionadas (';' separadas, ex\: eth0;eth1) [em branco\: todas]
+ConfigView.label.moveonlyusingdefaultsave.tooltip=Mover apenas se os dados baixados estiverem no diret\u00F3rio de dados padr\u00E3o
+tag.show.stats=Exibir Est\u00E1tisticas das Tags...
+MagnetURLHandler.report.error=erro %1
+ConfigTransferAutoSpeed.mode=Modo\:
+v3.devicesview.infobar.text2=Para transcodificar conte\u00FAdo para um dispositivo, basta arrastar o conte\u00FAdo de sua biblioteca para os dispositivos na barra lateral. Para ver transcodifica conclu\u00EDdas, clique no dispositivo individual na direita.
+tag.type.ds.err={ManagerItem.error}
+azbuddy.os_not_avail=N\u00E3o Dispon\u00EDvel
+MyTorrentsView.menu.torrent.dl=Link de Download do Torrent
+TableColumn.header.downloadspeedoverall.info=Taxa de download estimada do peer
+OpenTorrentWindow.mb.existingFiles.partialList=(Lista Parcial.  Mais arquivos j\u00E1 existem)
+wizard.maketorrent.filesize=Tamanho do(s) Arquivo(s)
+DHTView.operations.store=Armazenar
+subscriptions.column.SubWizRank=Rank
+TrayWindow.menu.stopalldownloads=Parar &Todos os Downloads
+FilesView.menu.retarget=Mover Arquivos
+iconBar.top.tooltip=Mover para o topo
+SpeedTestWizard.stage.message.requesting=requesitando teste...
+MainWindow.dht.status.disabled=DHT Desativado
+MainWindow.menu.transfers.pausetransfersfor.keybinding.mac=Opt+Ctrl+Shift+.
+device.od.enable=Habilitar download offline dos dispositivos
+Button.getstarted=Come\u00E7ar
+SpeedView.stats.estimate=Estimativa
+MainWindow.menu.speed_limits.save_current=Salvar atual como ...
+ConfigView.section.interface.clearsavepathsbutton=Limpar
+OpenTorrentWindow.fileList.changeDestination=Mudar o Destino
+MyTorrentsView.menu.movedata=Mover Arquivos de Dados...
+Progress.reporting.status.retrying=Tentando de Novo...
+label.current=Atual
+ConfigView.section.style.showiconbar=Mostrar a Barra de Ferramentas
+pairing.accesscode=C\u00F3digo de Acesso
+v3.deviceview.infobar.line2.tivo=Transmitir v\u00EDdeos, indo para o seu TiVo e selecionando Vuze na Lista de Reprodu\u00E7\u00E3o.
+MessageBoxWindow.nomoreprompting=N\u00E3o me alertar de novo
+devices.xcode.mancopy=Copiar Manualmente Arquivos
+SpeedTestWizard.name.conf.level.none=Nenhum
+MainWindow.menu.file.import=&Importar Torrent XML...
+Tracker.alert.listenfail=Falhou em estabelecer a escuta na porta %1.\nVerifique se outros aplicativos j\u00E1 n\u00E3o est\u00E3o usando esta porta.\nVerifique tamb\u00E9m se h\u00E1 outra c\u00F3pia do Vuze rodando.
+v3.MainWindow.menu.file.closewindow=Fechar
+ConfigView.label.minSpeedForActiveDL=N\u00E3o contar o torrent como usando um slot de download se a velocidade for inferior a
+MagnetPlugin.use.md.download=Habilitar o download de transfer\u00EAncia baseada em metadados
+importTorrentWizard.torrentfile.browse=Navegar
+label.force.piece=For\u00E7ar Peda\u00E7o
+Peers.column.%.info=Porcentagem do torrent que o peer baixou at\u00E9 agora
+upnp.info=Universal Plug and Play (UPnP) permite o mapeamento autom\u00E1tico de portas nos roteadores com UPnP ativado.
+TableColumn.header.chat.msg.count.info=Contagem de mensagens de outros usu\u00E1rios (tirando as suas)
+ConfigView.section.file.hashchecking.smallestfirst=Re-verificar os downloads menores primeiro
+TableColumn.header.profile=Dispositivo
+label.popups=Popups
+config.external.browser.switch.feature=Recurso
+label.clickone=Clique em um
+PeersView.title.short=Peers
+ConfigView.label.seeding.rankType.tooltip=Torrents mais altos no ranking s\u00E3o iniciados automaticamente.\nQuando outro torrent obt\u00EAm um rank maior, o de menor rank para e volta pra fila.\n\nApenas torrents em um estado Na Fila est\u00E3o dispon\u00EDveis para in\u00EDcio autom\u00E1tico.\nTorrents parados nunca s\u00E3o iniciados automaticamente.
+OpenTorrentWindow.torrentLocation=Arquivos Torrent\:
+network.admin.binding.state=Liga\u00E7\u00F5es\: %1, for\u00E7adas\=%2
+ConfigView.section.tracker.maxpeersreturned=M\u00E1ximo de peers retornados [0\: ilimitados]
+label.none={PeersView.uniquepiece.none}
+v3.MainWindow.xofx=%1 de %2
+MyTorrentsView.menu.setpriority.high=&Alta
+ConfigView.label.seeding.autoReposition.tooltip=Se ativado, a ordem dos torrents (a coluna '\#') ser\u00E1 alterada para combinar com aquela do Rank do Seeding\nIsto \u00E9 \u00FAtil se voc\u00EA n\u00E3o gosta de ver os n\u00FAmeros do Rank de Seeding, mas ainda quer saber a ordem na qual os torrents completados ser\u00E3o iniciados.
+MyTorrentsView.menu.open=&Abrir Arquivo
+label.routing=Roteamento
+GeneralView.label.updatein.querying=Requisitando...
+ConfigTransferAutoSpeed.algorithm=Algor\u00EDtmo\:
+CacheView.reads.fromFile=Do Arquivo
+installPluginsWizard.finish.title=Instala\u00E7\u00E3o em Progresso
+ManagerItem.initializing=Inicializando
+DHTView.activity.status=Status
+ConfigView.section.logging.generatediagnostics=Gerar
+MainWindow.menu.language=&Idioma
+IPChecker.external.service.no-ip.name=No-IP
+update.instance.uninstall=Checando a Desinstala\u00E7\u00E3o
+MainWindow.menu.view.iconbar=Barra de Ferramentas
+devices.xcode.autoStart=Iniciar automaticamente quando necess\u00E1rio
+ConfigView.section.transfer.autospeed.networks=Detalhes da Rede
+v3.MainWindow.menu.view.actionbar=Barra da A\u00E7\u00E3o
+MainWindow.menu.file.share=&Compartilhar
+device.wiki.itunes=http\://wiki.vuze.com/w/devices_itunes_tips
+DHTView.db.divsize=Tamanho Div
+dht.advanced=Ativar configura\u00E7\u00F5es avan\u00E7adas
+label.inactive=Inativo
+MagnetPlugin.decentral_backup_disabled=<backup descentralizado desativado>
+v3.MainWindow.menu.home=&Painel
+MainWindow.nat.status.tooltip.probok=Para alcan\u00E7ar foi OK, contudo sem conex\u00F5es de entrada TCP recentes
+device.config.xcode.workdir=Padr\u00E3o diret\u00F3rio de trabalho para arquivos transcodificados
+ConfigView.label.queue.maxactivetorrentswhenseeding=M\u00E1x. s\u00F3 quando ficando de seed [0\:ilimitados]
+DHTView.activity.type=Tipo
+button.add.container=Adic. Container
+ConfigView.section.ipfilter.blockedinfo=IPs que foram bloqueados pelos filtros de IP
+ConfigView.section.Pairing=Emparelhamento
+TableColumn.header.azsubs.ui.column.subs.info=Bot\u00E3o que permite a voc\u00EA subscrever ao feed contendo os torrents relacionados
+security.crypto.badpw=A senha suprima estava incorreta
+MyTorrentsView.menu.thisColumn.autoTooltip=Sempre exibir dicas
+Button.bar.hide=Esconder
+alert.copy.on.comp.done=Download %1\nArquivos copiados com sucesso para '%2'
+window.welcome.title=Bem-Vindo ao Vuze %1
+pairing.status.initialising=Inicializando
+config.external.browser.switch.external=Externo
+ConfigView.section.ipfilter.list.baddata=enviou dados ruins\: ocorr\u00EAncias \= 
+window.updateswt.failed=A atualiza\u00E7\u00E3o falhou, pressione OK de novo para reiniciar.
+#Used by the webui plugin
+MyTorrentsView.menu.removeand.deleteboth=Apagar &Ambos
+dlg.install.mlab.description=Por favor, aguarde enquanto o componente do teste de velocdiade \u00E9 instalado
+importTorrentWizard.importfile.message=Selecione o arquivo XML para importar 
+label.ago=atr\u00E1s
+v3.MainWindow.menu.view.statusbar=Barra de Status
+MyTorrentsView.menu.renameColumn={ColumnRenameWindow.title}...
+dlg.auth.enter.revoked=C\u00F3digo de ativa\u00E7\u00E3o atual foi revogado.
+FileView.BlockView.Done=Conclu\u00EDdo
+iconBar.remove=Apagar
+device.quit.transcoding.title=Transcodificar em andamento
+dht.status.disabled=Desabilitado, distributed database n\u00E3o est\u00E1 dispon\u00EDvel
+DHTView.operations.failed=Falhou
+Views.plugins.IRC.title=IRC - Suporte T\u00E9cnico Online
+TableColumn.header.Thumbnail.info=A imagem do thumbnail para o conte\u00FAdo do Vuze; para todos os outros conte\u00FAdos o sistema operacional est\u00E1 fornecendo estes \u00EDcones.
+UpdateMonitor.messagebox.verification.failed.text=Verifica\u00E7\u00E3o da '%1' falhou\: %2
+DownloadActivityView.title.short={TableColumn.header.Speed}
+subscriptions.column.name=Subscri\u00E7\u00E3o
+subscriptions.column.new.info=Indica se h\u00E1 um ou mais resultados novos
+azbuddy.ui.menu.dec=Decriptar a \u00C1rea de Transfer\u00EAncia
+Peers.column.peer_id=ID do Peer
+MyTorrentsView.menu.restore.and=Restaurar e...
+ManagerItem.allocating=Alocando
+core.shutdown.alert=Ac\u00E7\u00E3o '%1' desencadeada como %2
+TableColumn.header.max_sr={max.sr.window.title}
+Sidebar.beta.title=Programa Beta
+seedmore.uploadmore=Ter uma propor\u00E7\u00E3o de compartilhamento inferior a 100% n\u00E3o \u00E9 uma boa coisa para a rede BitTorrent.\nVoc\u00EA deveria deixar este torrente ficar de seed um pouco mais.\nVoc\u00EA tem certeza que voc\u00EA quer prosseguir?
+MyTorrentsView.dialog.setNumber.inKbps=em %1
+device.hide=Ocultar Dispositivo
+priority.normal=Prioridade normal
+MyTorrents.items.UpSpeedLimit.unlimited=Ilimitado
+MainWindow.about.section.internet=Internet 
+TableColumn.header.smootheta.info=Velocidade TEC Suavizado {smooth.config}
+Plugin.localtracker.enable=Ativar o descobridor de peers na LAN
+ConfigView.section.tracker.separatepeerids=Usar diferentes identidades de peer para o rastreador e para a comunica\u00E7\u00E3o de dados
+ipCheckerWizard.service=Servi\u00E7o
+OpenTorrentWindow.mb.notValid.text=N\u00E3o p\u00F4de abrir o torrent '%1'.  Se voc\u00EA est\u00E1 abrindo no modo ficar de seed, por favor tenha certeza de que os arquivos de dados do torrent existem.
+ConfigView.section.interface.resetassoc=Redefinir associa\u00E7\u00F5es de arquivos do explorer (.torrent)
+SpeedView.stats.session.tooltip=Total (Protocolo)
+security.certcreate.city=Cidade ou Localidade
+swt.install.window.title=Instalador de Plugins do Vuze
+ConfigView.section.server.enableudp=Ativar o protocolo do cliente rastreador UDP.
+ConfigView.section.stats.choosedefaultsavepath=Por favor escolha o diret\u00F3rio para salvar as estat\u00EDsticas
+SpeedView.downloadSpeed.title=Velocidade de Download
+ConfigView.label.defaultstarttorrentsstoppedandpause=Quando um torrent \u00E9 adicionado no estado "parado" automaticamente pause-o
+TableColumn.header.smoothdown.info=Velocidade de Download Suavizado {smooth.config}
+SpeedTestWizard.finish.panel.max.upload=Upload m\u00E1x\:
+ConfigView.label.allowsameip.tooltip=S\u00F3 marque se voc\u00EA PRECISA.\nEsta \u00E9 uma prote\u00E7\u00E3o contra leechers (quando desativado).
+device.error.xcodefail=Convers\u00E3o Falhou
+TableColumn.header.timesinceupload=Inativo pra Cima
+ConfigView.label.seeding.rankType.none.tooltip=Ordem baseada na coluna \#
+device.od.error.notfound=Dispositivo parece estar offline
+ConfigView.section.transfer.autospeed.info=A auto-velocidade ajusta automaticamente o limite da velocidade de upload para evitar sobrecarregar a conex\u00E3o de rede.\n\nEstes limites s\u00F3 ser\u00E3o aplicados quando a velocidade autom\u00E1tica de upload estiver ativada e tamb\u00E9m requer que a base de dados distribu\u00EDda esteja ativada.\n
+sidebar.LibraryCD.tooltip=Tem %1 completo torrent(s), %2 dos quais est\u00E1/est\u00E3o semeando
+dlg.auth.success.subtitle=Parab\u00E9ns\!
+exportTorrentWizard.exportfile.path=Caminho
+pairing.srp.setpw.doit=Mudar
+MyTorrentsView.menu.clear_resume_data=Limpar Dados de Resumo
+ipfilter.options=Op\u00E7\u00F5es de Filtro de IP ...
+security.crypto.password.mismatch=Os valores inseridos da senha n\u00E3o combinam, por favor re-insira-os.
+label.contraints=Restri\u00E7\u00F5es...
+ConfigView.label.maxuploadswhenbusymin=Velocidade m\u00E1xima de upload por torrent quando o timer est\u00E1 ocupado [seg]
+MainWindow.menu.beta.off=Deixe Programa Beta ...
+ConfigView.section.style.alwaysRefreshMyTorrents=Sempre atualizar Meus Torrents
+FancyMenu.Header.Control=Controle
+TableColumn.header.lan.info=Bandeira indicando se o peer est\u00E1 na sua LAN
+PeersView.port=Porta
+Button.set=Alterar
+webui.group.access=Controle de Acesso
+dlg.auth.install.failed.title=Falha na Ativa\u00E7\u00E3o
+ConfigView.label.password=Proteger o Vuze usando uma senha\n- Ser\u00E1 perguntado(a) quando des-iconificar e quando iniciado.
+configureWizard.transfer2.current=<Configura\u00E7\u00E3o Atual>
+wizard.multitracker.edit.deletegroup=Apagar
+Button.close=Fechar
+ConfigView.section.connection.advanced.bind_port.tooltip=Conex\u00F5es de socket de sa\u00EDda ser\u00E3o localmente presas a porta dada.\nAtivar isto pode ajudar com a instabilidade do roteador NAT.
+ConfigView.section.connection.network.max.simultaneous.connect.attempts.tooltip=N\u00FAmero m\u00E1ximo de novos estabelecimentos de conex\u00F5es de sa\u00EDda que o Vuze deve tentar a qualquer tempo dado.\nNOTA\: O Service Pack 2 do Windows XP (SP2) imp\u00F5e um limite para o sistema de apenas 10 tentativas para conectar simult\u00E2neas.\nO valor padr\u00E3o \u00E9 8.
+ConfigView.section.stats.enable=Ativar 
+TableColumn.menu.sr_prog.interval=Configurar Intervalo do Progresso...
+FilesView.title.full=Arquivos
+TableColumn.header.tag.xcode=Auto Transcode
+sidebar.VuzeHDNetwork=Rede HD do Vuze
+ConfigTransferAutoSpeed.add.comment.to.log=Coment\u00E1rio\:
+br.backup.last.error=\u00DAltimo Erro no backup\:
+ConfigView.section.proxy.socks.version=Vers\u00E3o do SOCKS
+uninstallPluginsWizard.finish.explanation=Os plugins selecionados ser\u00E3o desinstalados usando o Assistente de Atualiza\u00E7\u00E3o.
+MainWindow.menu.view.console=C&onsole 
+IrcView.privateto=Para
+Wizard.Subscription.create.rss=RSS
+SpeedView.stats.session=Esta Sess\u00E3o
+TableColumn.header.sha1=SHA1
+ScrapeInfoView.title=Rastreador Prim\u00E1rio
+security.certcreate.firstlastname=Primeiro e \u00FAltimo nome
+ConfigView.section.style.colorOverride.progressBar=Barra de Progresso
+MyTorrentsView.menu.host=&Servidor...
+SpeedView.stats.downloaded=Baixado (Protocolo)
+SpeedTestWizard.abort.message.not.unchoked=N\u00E3o p\u00F4de baixar de quaisquer dos peers como nunca foi desobstru\u00EDdo por eles
+Subscription.menu.remove=Apagar
+ConfigView.label.maxdownloads.tooltip=Voc\u00EA sempre ser\u00E1 capaz de baixar ativamente o n\u00FAmero que voc\u00EA p\u00F4r aqui, com uma exce\u00E7\u00E3o.\nUma combina\u00E7\u00E3o de Primeira Prioridade do torrent completado pode tomar o controle de um slot de download ativo se absolutamente necess\u00E1rio.
+ConfigView.section.tracker.extensions=Extens\u00F5es
+label.check.avail={GeneralView.section.availability}
+DiskManager.error.nospace=Espa\u00E7o em disco insuficiente
+OpenTorrentWindow.torrentTable.name=Nome
+ConfigView.label.seeding.firstPriority.following=os/dos seguintes\:
+ConfigView.section.security.toolsinfo=Arquivos JAR assinados s\u00E3o usados para ajudar alguns plugins, por exemplo o Swing Web Interface (quando configurado para faz\u00EA-lo).\nPara assinar arquivos JAR \u00E9 necess\u00E1rio ter accesso ao arquivo 'tools.jar' que vem com a instala\u00E7\u00E3o do Sun JDK (n\u00E3o do JRE).\nSe voc\u00EA s\u00F3 tiver instalado o JRE ent\u00E3o por favor instale o JDK.\nNormalmente o Vuze pode achar o arquivo para voc\u00EA. Entretanto, se isto falhar [...]
+ConfigView.label.watchtorrentfolder.tooltip=Procurar por novos .torrents regularmente
+TableColumn.header.sizewithdnd=Tamanho do Torrent
+ConfigView.section.file.resume.recheck.all=Quando der pau-reiniciar verificar o arquivo inteiro por peda\u00E7os completados (De outro modo apenas peda\u00E7os ativos do \u00FAltimo salvamento s\u00E3o verificados)
+ConfigView.section.connection.peersource.PeerExchange=Supridas por outro peer
+v3.MainWindow.button.viewdetails=Ver Detalhes
+ConfigView.label.xfer.bias_up=Aumentar velocidades de download pela polariza\u00E7\u00E3o de upload capacidade de downloads incompletos
+general.na.short=N/A
+label.copy.on.comp=Copiar Quando Completo
+ColumnSetup.title=Configura\u00E7\u00E3o das Colunas para '%1'
+ConfigView.section.stats.hours=h
+ConfigTransferAutoSpeed.log.button=Log
+TableColumn.header.torrentfileindex.info=\u00CDndice do arquivo no torrent
+ConfigView.label.seeding.firstPriority.ignore=Ignorar as regras de Primeira Prioridade acima para\:
+MyTorrentsView.menu.publish=Pub&licar...
+dlg.auth.enter.prompt=Vuze Plus c\u00F3digo de ativa\u00E7\u00E3o\:
+DHTView.operations.findValue=Achar Valor
+v3.MainWindow.button.download=Download
+window.welcome.file=/changelog.txt
+MainWindow.menu.file.closetab.keybinding=Meta+W
+platform.win32.baddll.SBLSP=Speedbit Acelerador de v\u00EDdeo
+updater.cant.write.to.app.details=A pasta "%1" n\u00E3o pode ser escrita.\n\nIsto impedir\u00E1 que atualiza\u00E7\u00F5es futuras do software sejam aplicadas.\n\nPor favor <a href\="http\://www.azureuswiki.com/index.php/Failed_Update">veja o wiki para detalhes</a>.
+ClientStats.title.full=Estatus do Cliente
+Trackers.column.peers.info=Peers retornado pelo tracker
+splash.loadIpFilters=Carregando os Filtros de IP..
+MyTorrentsView.menu.peersource=Fontes Peer
+dht.diagnostics.group=Diagn\u00F3sticos
+OpenTorrentFileView.header={ConfigView.section.files}
+ManagerItem.seeding=Ficando de seed
+ConfigView.label.autoopen.dl={ManagerItem.downloading}
+pairing.last.error=\u00DAltimo erro
+SpeedView.stats.ratio=Propor\u00E7\u00E3o
+FilesView.click=Clicar...
+ConfigView.section.connection.serverport.wiki=Escolhas de boas portas
+MagnetPlugin.decentral_disabled=<rastreamento descentralizado desativado>
+SystemTray.menu.resumetransfers=Resumir Transfer\u00EAncias
+devices.od.idle=Ocioso
+IPChecker.external.analysingresponse=Analisando resposta
+upnp.ignorebaddevices.alert=O dispositivo UPnP no local %1 est\u00E1 sendo ignorado devido a repetidas falhas. Veja a configura\u00E7\u00E3o do plugin UPnP para op\u00E7\u00F5es com respeit a esta a\u00E7\u00E3o.
+DHTView.operations.ok=Ok
+OpenTorrentWindow.fileTable.size=Tamanho
+exportTorrentWizard.process.outputfileexists.title=O Arquivo Existe
+azbuddy.ui.table.last_ygm=YGM
+devices.xcode.setcopyto=Definir Copiar para pasta ...
+ConfigView.label.stop.autoreset=Automaticamente restaurar a\u00E7\u00F5es para '%1' uma vez engatilhadas
+v3.activity.button.readall=Marcar Todos os Lidos
+TableColumn.header.category=Categoria
+ConfigView.section.plugins.webui=Interface Swing Web
+webui.rootres=Recurso Raiz (*)
+ConfigView.section.transfer.autospeed.enabledebug=Informa\u00E7\u00E3o de debug no Log
+ConfigView.label.autoopen.cd={ManagerItem.seeding}
+TableColumn.header.smoothdown=Down Suavizado
+SpeedView.stats.con=Detalhes da conex\u00E3o\:
+wizard.multitracker.edit.save=Salvar
+ConfigView.label.moveremoved=Mover arquivos completados (quando sendo removidos)
+Alert.failed.update=A instala\u00E7\u00E3o de pelo menos um componente falhou. Veja <A HREF\="{Alert.failed.update.url}">AzureusWiki\: A Atualiza\u00E7\u00E3o Falhou</A>  [%1]
+ConfigTransferAutoSpeed.set.tolerance=toler\u00E2ncia (ms)
+devices.device=Dispositivo
+azbuddy.dchat.nick=Apelido
+ConfigView.label.allowsameip=Permitir m\u00FAltiplas conex\u00F5es do mesmo IP
+dlg.auth.denied=C\u00F3digo de Ativa\u00E7\u00E3o Negado
+azbuddy.os_offline=Offline
+subscriptions.column.last-checked=Verificado Pela \u00DAltima Vez
+TableColumn.header.shareRatio=Propor\u00E7\u00E3o do Compartilhamento
+installPluginsWizard.mode.list=Pela lista do sourceforge.net
+MyTorrentsView.menu.rename.displayed.enter.title=Renomear o Nome Exibido 
+external.browser.system=Padr\u00E3o do Computador
+ConfigView.section.style.status.show_nat=Status do NAT
+ConfigView.section.tracker.seedretention=M\u00E1ximo de seeds retidos por torrent [0\: ilimitados]
+ConfigView.label.ratio=propor\u00E7\u00E3o
+OpenTorrentWindow.mb.badSize.text='%1' n\u00E3o \u00E9 '%2' e n\u00E3o pode ser usado para ficar de seed
+OpenTorrentWindow.addPosition=Posi\u00E7\u00E3o na Fila
+ConfigView.section.tracker.nonblockingconcmax=M\u00E1x. de conex\u00F5es coincidentes [0\: ilimitadas]
+TableColumn.header.up.info=Quantia de dados atuais enviada para outros usu\u00E1rios
+azbuddy.ui.menu.copypk=Copiar a Chave P\u00FAblica
+ConfigView.section.tracker.pollintervalincper=A cada 'n' clientes
+label.tracker.templates=Modelos de Rastreador
+SpeedTestWizard.set.upload.bytes.per.sec=kBytes/seg
+ConfigView.label.saveresumeinterval=Atualizar os dados de resumo a cada
+ConfigView.section.interface.enabletray._mac=Ativar o \u00CDcone da Barra de Status [requer reiniciar]
+TableColumn.header.downloadspeed.info=Taxa da qual n\u00F3s estamos recebendo do peer
+OpenTorrentWindow.pastearea=Digite a URL, magnet link, ou hash\:
+label.udp_probe=Examinar UDP
+MainWindow.upgrade.downloadingfrom=Baixando de \: 
+exportTorrentWizard.torrentfile.message=Selecione o arquivo torrent para exportar
+ConfigView.section.dns.url=http\://wiki.vuze.com/w/ug_options \# DNS
+pairing.server.warning.title=Mensagem do Servidor de emparelhamento
+TableColumn.header.swarm_average_speed=Velocidade M\u00E9dia da Multid\u00E3o
+PeersView.ip.info=IP do peer
+DevicesOD.column.od_completion=Progresso da Tranfer\u00EAncia
+OpenTorrentWindow.mb.alreadyExists.title=O torrent j\u00E1 existe
+MyTorrentsView.menu.restore={br.restore}
+MyTorrents.column.ColumnProgressETA.compon=Completado em %1
+azbuddy.enable_cat_pub=Tags/Categorias P\u00FAblicas para TODOS seus amigos possam assinar para (Separado por ",") 
+MainWindow.menu.speed_limits.wiki.url=http\://wiki.vuze.com/w/speed_limit_scheduler
+importTorrentWizard.process.inputfilebad.title=Arquivo de Importa\u00E7\u00E3o Inv\u00E1lido
+TableColumn.header.torrentspeed=Velocidade
+MainWindow.dialog.restartconfirmation.text=Voc\u00EA realmente quer reiniciar o Vuze?
+PluginDeprecation.view=Debug do Plugin
+v3.button.removeActivityEntry=Remover a Entrada da Atividade
+FancyMenu.Header.Content=Conte\u00FAdo
+DHTTransport.report.rerequest_all=re-requisitando transfer\u00EAncia inteira de %1
+platform.win32.baddll.niphk=Normando Anti- V\u00EDrus
+label.no.connections=Sem conex\u00F5es
+MyTorrentsView.menu.forceStart=&For\u00E7ar In\u00EDcio
+MainWindow.menu.speed_limits.info.curr=Configura\u00E7\u00F5es atuais
+devices.turnon.title=Ativar Suporte \u00E0 Dispositivo
+TableColumn.header.secondsseeding=Fazendo Seed Por
+MainWindow.about.internet.sourceforge=P\u00E1gina do Projeto no Sourceforge
+v3.mb.delPublished.title=Parar de Ficar de Seed com este Conte\u00FAdo
+configureWizard.transfer2.rate.unchanged=Configura\u00E7\u00F5es atuais ser\u00E3o usadas
+ConfigView.pluginlist.column.type.builtIn=Embutido
+sharing.progress.title=Progresso do Compartilhamento
+SpeedTestWizard.name.conf.level.high=Alta
+label.outgoing=Sa\u00EDda
+PluginDeprecation.log.details=---------\nIDENTIFICADOR\: %1\nCONTE\u00DADO\: %2\n\n*** COME\u00C7AR A RASTREAR ***\n%3*** FINALIZAR O RASTREAMENTO ***\n\n
+TableColumn.header.fileext.info=Tipo de arquivo/extens\u00E3o de arquivo prim\u00E1rio do download
+platform.win32.baddll.mclsp=Mcafee privacy service
+TableColumn.header.CountryFlagSmall=Bandeira
+v3.deviceview.infobar.line2.android=Ativar USB montagem no telefone para transferir adequadamente os v\u00EDdeos.
+ConfigView.section.security.resetkey.error=Falhou em resetar as chaves
+device.od.turnon.title=Ligar suporte para downloader offline
+MainWindow.menu.speed_limits.delete=Apagar
+ConfigView.section.style.enableHeaderHeight=Altura cabe\u00E7alho personalizado
+OpenTorrentWindow.addFiles.magnet=Adic. &Magnet
+FileItem.high=alta
+devices.xcode.working_dir=\u00C1rea Transcode
+GeneralView.label.status.pieces=Status dos Peda\u00E7os
+FileDownload.canceled=Um download de arquivo torrent foi cancelado com sucesso por uma a\u00E7\u00E3o do usu\u00E1rio\: %1
+dlg.install.azemp.description={dlg.player.install.description}
+azbuddy.dchat.pc.enable=Habilitar bate-papo privado
+v3.MainWindow.text.log.in=Assinar pra entrar
+upnp.trace_to_log=Informa\u00E7\u00E3o de debug completa da sa\u00EDda de dados no log
+label.tag=Etiqueta
+# Used for peers which we can't determine.
+PeerSocket.unknown=Desconhecido
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pt_PT.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pt_PT.properties
index 667b94e..f563df0 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pt_PT.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_pt_PT.properties
@@ -1178,6 +1178,8 @@ MyTorrentsView.menu.setSpeed.disable=Desactivar o Upload
 MyTorrentsView.menu.setSpeed.disabled=Desactivado
 MyTorrentsView.menu.setSpeed.in=em
 MyTorrentsView.menu.setSpeed.slots=slots de
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=M\u00e1x Up
 GeneralView.label.maxuploadspeed.tooltip=velocidade max de upload [0 : ilimitado]
 MyTorrents.items.UpSpeedLimit.disabled=Sem upload
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ro_RO.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ro_RO.properties
index ed5edf9..f1094ee 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ro_RO.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ro_RO.properties
@@ -1229,6 +1229,8 @@ MyTorrentsView.menu.setSpeed.disable=Dezactiveaz\u0103 \u00cenc\u0103rcarea
 MyTorrentsView.menu.setSpeed.disabled=Dezactivat\u0103
 MyTorrentsView.menu.setSpeed.in=\u00een
 MyTorrentsView.menu.setSpeed.slots=sloturi pentru
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Viteza Maxim\u0103 de \u00cenc\u0103rcare
 GeneralView.label.maxuploadspeed.tooltip=viteza maxim\u0103 de \u00eenc\u0103rcare [0: nelimitat\u0103]
 MyTorrents.items.UpSpeedLimit.disabled=Nici o \u00eenc\u0103rcare
@@ -2606,13 +2608,7 @@ ConfigView.label.systray=Tray sistem
 ConfigView.label.systray._mac=Icoana din Bara de Stare
 ConfigView.section.interface.legacy=\u00cenvechit
 v3.MainWindow.menu.contentnetworks.manage=Ad&ministreaz\u0103 Re\u021belele HD
-azbuddy.ui.menu.cat=Categorii
-azbuddy.ui.menu.cat.share=Activeaz\u0103 abonamentele pentru prieteni
-azbuddy.ui.menu.cat.set=Scrie categoriile
-azbuddy.ui.menu.cat.set_msg=List\u0103 de categorii separate prin virgul\u0103, sau 'Tot'
-azbuddy.ui.menu.cat_subs=Aboneaz\u0103
 subs.prop.update_period=Perioada de actualizare
-azbuddy.enable_cat_pub=Categorii publice la care se pot abona TO\u021aI prietenii t\u0103i (separate prin ',' )
 TableColumn.header.#=Nr.
 TableColumn.header.#.info=Num\u0103rul de Pozi\u021bie/Ordonare
 TableColumn.header.category.info=Numele categoriei c\u0103reia \u00eei apar\u021bine torentul
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ru_RU.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ru_RU.properties
index 36be36d..74d4216 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ru_RU.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_ru_RU.properties
@@ -1253,6 +1253,8 @@ MyTorrentsView.menu.setSpeed.disable=\u0417\u0430\u043f\u0440\u0435\u0442\u0438\
 MyTorrentsView.menu.setSpeed.disabled=\u0412\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043e
 MyTorrentsView.menu.setSpeed.in=\u0432
 MyTorrentsView.menu.setSpeed.slots=\u0441\u043b\u043e\u0442\u0430\u0445 \u043f\u043e
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438
 GeneralView.label.maxuploadspeed.tooltip=- \u0435\u0434.\u0438\u0437\u043c.; \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0434\u0430\u0447\u0438 [0 : \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e]
 MyTorrents.items.UpSpeedLimit.disabled=\u041d\u0435\u0442 \u0440\u0430\u0437\u0434\u0430\u0447\u0438
@@ -2670,16 +2672,7 @@ ConfigView.label.systray=\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439
 ConfigView.label.systray._mac=\u0418\u043a\u043e\u043d\u043a\u0430 \u041f\u0430\u043d\u0435\u043b\u0438 \u0421\u0442\u0430\u0442\u0443\u0441\u0430
 ConfigView.section.interface.legacy=\u041f\u0440\u0435\u0436\u043d\u0438\u0439 \u0441\u0442\u0438\u043b\u044c
 v3.MainWindow.menu.contentnetworks.manage=&\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0421\u0435\u0442\u044f\u043c\u0438 HD
-azbuddy.ui.table.loc_cat=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0432\u043e \u0432\u043d\u0435
-azbuddy.ui.table.rem_cat=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435
-azbuddy.ui.menu.cat=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438
-azbuddy.ui.menu.cat.share=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u0441 \u0434\u0440\u0443\u0437\u044c\u044f\u043c\u0438
-azbuddy.ui.menu.cat.set=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438
-azbuddy.ui.menu.cat.set_msg=\u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u044f\u0442\u044b\u043c\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439, \u0438\u043b\u0438 'All' (\u0432\u0441\u0435)
-azbuddy.ui.menu.cat_subs=\u041f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f
 subs.prop.update_period=\u041f\u0435\u0440\u0438\u043e\u0434 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f
-azbuddy.enable_cat_pub=\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0412\u0421\u0415 \u0412\u0430\u0448\u0438 \u0434\u0440\u0443\u0437\u044c\u044f \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f (\u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f ',')
-azbuddy.ui.table.read_cat=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f \u0447\u0442\u0435\u043d\u0438\u044f
 TableColumn.header.#=\u2116
 TableColumn.header.#.info=\u041d\u043e\u043c\u0435\u0440 \u041f\u043e\u0437\u0438\u0446\u0438\u0438/\u041f\u043e\u0440\u044f\u0434\u043a\u0430
 TableColumn.header.category.info=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u0442\u043e\u0440\u0440\u0435\u043d\u0442
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sk_SK.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sk_SK.properties
index e29b5de..efdc8cb 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sk_SK.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sk_SK.properties
@@ -1174,6 +1174,8 @@ MyTorrentsView.menu.setSpeed.disable=Vypn\u00fa\u0165 upload
 MyTorrentsView.menu.setSpeed.disabled=Vypnut\u00fd
 MyTorrentsView.menu.setSpeed.in=v
 MyTorrentsView.menu.setSpeed.slots=slotoch
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Max. up
 GeneralView.label.maxuploadspeed.tooltip=max. r\u00fdchlos\u0165 uploadu [0 : neobmedzen\u00e1]
 MyTorrents.items.UpSpeedLimit.disabled=\u017diadna
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sr.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sr.properties
index 2ab5836..b35ec85 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sr.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sr.properties
@@ -1237,6 +1237,8 @@ MyTorrentsView.menu.setSpeed.disable=\u0417\u0430\u0431\u0440\u0430\u043d\u0438
 MyTorrentsView.menu.setSpeed.disabled=\u0418\u0441\u043a\u0459\u0443\u0447\u0435\u043d\u043e
 MyTorrentsView.menu.setSpeed.in=\u0443
 MyTorrentsView.menu.setSpeed.slots=\u043f\u0440\u043e\u0440\u0435\u0437\u0430 \u043e\u0434
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=\u0411\u0440\u0437. \u0441\u043b\u0430\u045a\u0430
 GeneralView.label.maxuploadspeed.tooltip=\u041d\u0430\u0458\u0432\u0435\u045b\u0430 \u0431\u0440\u0437\u0438\u043d\u0430 \u0441\u043b\u0430\u045a\u0430 [0: \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e]
 MyTorrents.items.UpSpeedLimit.disabled=\u041d\u0435\u043c\u0430 \u0441\u043b\u0430\u045a\u0430
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sr_Latin.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sr_Latin.properties
index b6c63da..7ad4172 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sr_Latin.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sr_Latin.properties
@@ -1277,6 +1277,8 @@ MyTorrentsView.menu.setSpeed.disable=Zabrani slanje
 MyTorrentsView.menu.setSpeed.disabled=Isklju\u010deno
 MyTorrentsView.menu.setSpeed.in=u
 MyTorrentsView.menu.setSpeed.slots=proreza od
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Brz. slanja
 GeneralView.label.maxuploadspeed.tooltip=Najve\u0107a brzina slanja [0: neograni\u010deno]
 MyTorrents.items.UpSpeedLimit.disabled=Nema slanja
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sv_SE.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sv_SE.properties
index bcc66fa..428e6c0 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sv_SE.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_sv_SE.properties
@@ -1232,6 +1232,8 @@ MyTorrentsView.menu.setSpeed.disable=Inaktivera uppladdning
 MyTorrentsView.menu.setSpeed.disabled=Inaktiverad
 MyTorrentsView.menu.setSpeed.in=i
 MyTorrentsView.menu.setSpeed.slots=platser av
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Max Upp
 GeneralView.label.maxuploadspeed.tooltip=max uppladdningshastighet [0 : Obegr\u00e4nsad]
 MyTorrents.items.UpSpeedLimit.disabled=Ingen uppladdning
@@ -2509,9 +2511,6 @@ ConfigView.label.autoopen.detailstab=\u00d6ppna fliken Detaljer n\u00e4r
 ConfigView.label.systray=Meddelandef\u00e4ltet
 ConfigView.label.systray._mac=Ikon f\u00f6r Statusf\u00e4ltet
 v3.MainWindow.menu.contentnetworks.manage=Hantera HD N\u00e4tverk
-azbuddy.ui.menu.cat=Kategorier
-azbuddy.ui.menu.cat.set_msg=Kommaseparerad lista av kategorier eller 'Alla'
-azbuddy.ui.menu.cat_subs=Prenumerera
 TableColumn.header.TableColumnChosenColumn=Vald Kolumn
 ColumnSetup.chosencolumns=Valda Kolumner
 ColumnSetup.categories=Kategorier:
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_th_TH.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_th_TH.properties
index 8d473bd..8668eea 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_th_TH.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_th_TH.properties
@@ -1149,6 +1149,8 @@ MyTorrentsView.menu.setSpeed.disable=\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01 Upload
 MyTorrentsView.menu.setSpeed.disabled=\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01
 MyTorrentsView.menu.setSpeed.in=\u0e43\u0e19
 MyTorrentsView.menu.setSpeed.slots=slots \u0e02\u0e2d\u0e07
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=Up \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14
 GeneralView.label.maxuploadspeed.tooltip=\u0e04\u0e27\u0e32\u0e21\u0e40\u0e23\u0e47\u0e27 Upload \u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 [0 : \u0e44\u0e21\u0e48\u0e08\u0e33\u0e01\u0e31\u0e14]
 MyTorrents.items.UpSpeedLimit.disabled=\u0e44\u0e21\u0e48 upload
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_uk_UA.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_uk_UA.properties
index 30c2829..8eb15a3 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_uk_UA.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_uk_UA.properties
@@ -1251,6 +1251,8 @@ MyTorrentsView.menu.setSpeed.disable=\u0417\u0430\u0431\u043e\u0440\u043e\u043d\
 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
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 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 \u0440\u043e\u0437\u0434\u0430\u0447\u0456
@@ -2671,16 +2673,7 @@ ConfigView.label.systray=\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u0438\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
 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 ',') 
-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
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_zh_CN.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_zh_CN.properties
index bc88ebd..af69ab6 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_zh_CN.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_zh_CN.properties
@@ -1242,6 +1242,8 @@ MyTorrentsView.menu.setSpeed.disable=\u7981\u6b62\u4e0a\u4f20
 MyTorrentsView.menu.setSpeed.disabled=\u7981\u6b62
 MyTorrentsView.menu.setSpeed.in=\u5206
 MyTorrentsView.menu.setSpeed.slots=\u4efd\uff0c\u6bcf\u4efd
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=\u6700\u5927\u4e0a\u4f20\u901f\u5ea6
 GeneralView.label.maxuploadspeed.tooltip=\u6700\u5927\u4e0a\u4f20\u901f\u5ea6\uff3b0\uff1a\u65e0\u9650\u5236\uff3d
 MyTorrents.items.UpSpeedLimit.disabled=\u65e0\u4e0a\u4f20
@@ -2623,11 +2625,6 @@ ConfigView.label.autoopen.detailstab=\u81ea\u52a8\u6253\u5f00\u8be6\u60c5\u6807\
 ConfigView.label.systray=\u7cfb\u7edf\u6258\u76d8
 ConfigView.label.systray._mac=\u72b6\u6001\u680f\u56fe\u6807
 v3.MainWindow.menu.contentnetworks.manage=\u7ba1\u7406\u9ad8\u6e05\u7f51\u7edc\uff08&M\uff09
-azbuddy.ui.menu.cat=\u5206\u7c7b
-azbuddy.ui.menu.cat.share=\u542f\u7528\u6765\u81ea\u597d\u53cb\u7684\u8ba2\u9605
-azbuddy.ui.menu.cat.set=\u8f93\u5165\u5206\u7c7b
-azbuddy.ui.menu.cat.set_msg=\u7528\u9017\u53f7\u5206\u9694\u7684\u5206\u7c7b\u5217\u8868\uff0c\u6216\u8005 'All'
-azbuddy.ui.menu.cat_subs=\u8ba2\u9605
 TableColumn.header.#.info=\u4f4d\u7f6e/\u6b21\u5e8f\u53f7
 TableColumn.header.category.info=torrent \u6240\u5c5e\u7684\u5206\u7c7b\u540d
 TableColumn.header.DateCompleted.info=torrent \u4e0b\u8f7d\u5b8c\u6210\u7684\u65e5\u671f
diff --git a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_zh_TW.properties b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_zh_TW.properties
index 269486a..4460dcb 100644
--- a/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_zh_TW.properties
+++ b/azureus2/src/org/gudy/azureus2/internat/MessagesBundle_zh_TW.properties
@@ -1225,6 +1225,8 @@ MyTorrentsView.menu.setSpeed.disable=\u7981\u6b62\u4e0a\u50b3
 MyTorrentsView.menu.setSpeed.disabled=\u5df2\u7981\u6b62
 MyTorrentsView.menu.setSpeed.in=\u9032
 MyTorrentsView.menu.setSpeed.slots=\u500b\u6578
+# %1 = total speed; %2 = # of slots; %3 = speed per slot
+MyTorrentsView.menu.setSpeed.multi=%1 {MyTorrentsView.menu.setSpeed.in} %2 {MyTorrentsView.menu.setSpeed.slots} %3
 GeneralView.label.maxuploadspeed=\u6700\u5927\u4e0a\u50b3
 GeneralView.label.maxuploadspeed.tooltip=\u6700\u5927\u4e0a\u50b3\u901f\u5ea6 [0\uff1a\u7121\u9650\u5236]                                  
 MyTorrents.items.UpSpeedLimit.disabled=\u7981\u6b62\u4e0a\u50b3
diff --git a/azureus2/src/org/gudy/azureus2/platform/JavaBitMode.java b/azureus2/src/org/gudy/azureus2/platform/JavaBitMode.java
index 0f8ab75..f7b27b3 100644
--- a/azureus2/src/org/gudy/azureus2/platform/JavaBitMode.java
+++ b/azureus2/src/org/gudy/azureus2/platform/JavaBitMode.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.platform;
 
 import org.gudy.azureus2.core3.util.Constants;
diff --git a/azureus2/src/org/gudy/azureus2/platform/PlatformManager.java b/azureus2/src/org/gudy/azureus2/platform/PlatformManager.java
index 98fc301..c3e5624 100644
--- a/azureus2/src/org/gudy/azureus2/platform/PlatformManager.java
+++ b/azureus2/src/org/gudy/azureus2/platform/PlatformManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/PlatformManagerCapabilities.java b/azureus2/src/org/gudy/azureus2/platform/PlatformManagerCapabilities.java
index f6af547..89d8097 100644
--- a/azureus2/src/org/gudy/azureus2/platform/PlatformManagerCapabilities.java
+++ b/azureus2/src/org/gudy/azureus2/platform/PlatformManagerCapabilities.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Mar-2004
  * Created by James Yeh
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.platform;
diff --git a/azureus2/src/org/gudy/azureus2/platform/PlatformManagerFactory.java b/azureus2/src/org/gudy/azureus2/platform/PlatformManagerFactory.java
index da7ff02..5ad4699 100644
--- a/azureus2/src/org/gudy/azureus2/platform/PlatformManagerFactory.java
+++ b/azureus2/src/org/gudy/azureus2/platform/PlatformManagerFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/PlatformManagerListener.java b/azureus2/src/org/gudy/azureus2/platform/PlatformManagerListener.java
index f1c8cb1..dedd53f 100644
--- a/azureus2/src/org/gudy/azureus2/platform/PlatformManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/platform/PlatformManagerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/PlatformManagerPingCallback.java b/azureus2/src/org/gudy/azureus2/platform/PlatformManagerPingCallback.java
index 77181ab..2ee4218 100644
--- a/azureus2/src/org/gudy/azureus2/platform/PlatformManagerPingCallback.java
+++ b/azureus2/src/org/gudy/azureus2/platform/PlatformManagerPingCallback.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/PlatformManagerPluginDelegate.java b/azureus2/src/org/gudy/azureus2/platform/PlatformManagerPluginDelegate.java
index c8357dd..120eed2 100644
--- a/azureus2/src/org/gudy/azureus2/platform/PlatformManagerPluginDelegate.java
+++ b/azureus2/src/org/gudy/azureus2/platform/PlatformManagerPluginDelegate.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.platform;
diff --git a/azureus2/src/org/gudy/azureus2/platform/dummy/PlatformManagerImpl.java b/azureus2/src/org/gudy/azureus2/platform/dummy/PlatformManagerImpl.java
index fd258c5..1fdbb9c 100644
--- a/azureus2/src/org/gudy/azureus2/platform/dummy/PlatformManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/platform/dummy/PlatformManagerImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.platform.dummy;
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/macosx/NativeInvocationBridge.java b/azureus2/src/org/gudy/azureus2/platform/macosx/NativeInvocationBridge.java
index c090cbf..8e0d8a6 100644
--- a/azureus2/src/org/gudy/azureus2/platform/macosx/NativeInvocationBridge.java
+++ b/azureus2/src/org/gudy/azureus2/platform/macosx/NativeInvocationBridge.java
@@ -3,7 +3,7 @@ package org.gudy.azureus2.platform.macosx;
 /*
  * Created on 26-Mar-2005
  * Created by James Yeh
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -17,9 +17,6 @@ package org.gudy.azureus2.platform.macosx;
  * 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.
- *
  */
 
 import org.gudy.azureus2.core3.util.Debug;
diff --git a/azureus2/src/org/gudy/azureus2/platform/macosx/PListEditor.java b/azureus2/src/org/gudy/azureus2/platform/macosx/PListEditor.java
index fff5747..e5fe44d 100644
--- a/azureus2/src/org/gudy/azureus2/platform/macosx/PListEditor.java
+++ b/azureus2/src/org/gudy/azureus2/platform/macosx/PListEditor.java
@@ -1,327 +1,326 @@
-/*
- * Created on Apr 1, 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.platform.macosx;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-
-import org.gudy.azureus2.core3.util.ByteFormatter;
-import org.gudy.azureus2.core3.util.FileUtil;
-
-public class 
-PListEditor 
-{	
-	private String plistFile;
-	
-	private boolean	found_bom;
-	
-	public 
-	PListEditor(
-		String plistFile )
-	
-		throws IOException
-	{
-		this.plistFile = plistFile;
-		
-		File	file  = new File( plistFile );
-		
-		if ( !file.exists()){
-			
-			throw( new IOException( "plist file '" + file + "' doesn't exist" ));
-		}
-		
-		if ( !file.canWrite()){
-			
-			throw( new IOException( "plist file '" + file + "' is read only" ));
-		}
-	}
-	
-	public void 
-	setFileTypeExtensions(
-		String[] extensions )
-	
-		throws IOException
-	{
-		StringBuffer value = new StringBuffer();
-		StringBuffer find = new StringBuffer();
-		find.append("(?s).*?<key>CFBundleDocumentTypes</key>\\s*<array>.*?<key>CFBundleTypeExtensions</key>\\s*<array>");
-		for(int i = 0 ; i < extensions.length ; i++) {
-			value.append("\n\t\t\t\t<string>");
-			value.append(extensions[i]);
-			value.append("</string>");
-			
-			find.append(".*?");
-			find.append(extensions[i]);
-		}
-		value.append("\n\t\t\t");
-		
-		find.append(".*?</array>.*");
-		String match = "(?s)(<key>CFBundleDocumentTypes</key>\\s*<array>.*?<key>CFBundleTypeExtensions</key>\\s*<array>)(.*?)(</array>)";
-		
-		setValue(find.toString(), match, value.toString());
-	}
-	
-	public void 
-	setSimpleStringValue(
-		String key,
-		String value)
-	
-		throws IOException
-	{
-		String find = "(?s).*?<key>" + key + "</key>\\s*" + "<string>" + value + "</string>.*";
-		String match = "(?s)(<key>" + key + "</key>\\s*" + "<string>)(.*?)(</string>)";
-		setValue(find, match, value);
-	}
-	
-	public void
-	setArrayValues(
-		String key,
-		String valueType,
-		String[] values) 
-	
-		throws IOException
-	{
-		StringBuffer value = new StringBuffer();
-		StringBuffer find = new StringBuffer();
-		find.append("(?s).*?<key>" + key + "</key>\\s*" + "<array>");
-		for(int i = 0 ; i < values.length ; i++) {
-			find.append("\\s*<" + valueType + ">" + values[i] + "</" + valueType + ">");
-			value.append("\n\t\t\t\t<" + valueType + ">");
-			value.append(values[i]);
-			value.append("</" + valueType + ">");
-		}
-		find.append("\\s*</array>.*");
-		value.append("\n\t\t\t");
-		
-		String match = "(?s)(<key>" + key + "</key>\\s*<array>)(.*?)(</array>)";
-		
-		setValue(find.toString(),match,value.toString());
-	}
-	
-	private boolean 
-	isValuePresent(
-		String	fileContent,
-		String 	match )
-	
-		throws IOException
-	{		
-		//System.out.println("Searching for:\n" + match);
-		return fileContent.matches(match);
-	}
-	
-
-	/**
-	 * 
-	 * @param find the regex expression to find if the value is already present
-	 * @param match the regex expression that will match for the replace, it needs to capture 3 groups, the 2nd one being replaced by value
-	 * @param value the value that replaces the 2nd match group
-	 */
-	private void 
-	setValue(
-		String find,
-		String match,
-		String value)
-	
-		throws IOException
-	{
-		String fileContent = getFileContent();
-		
-		if( !isValuePresent(fileContent,find)) {
-			//System.out.println("Changing " +plistFile);
-			fileContent = fileContent.replaceFirst(match, "$1"+value + "$3");
-			setFileContent(fileContent);
-			touchFile();
-		}
-	}
-	
-	private String 
-	getFileContent()
-		throws IOException
-	{
-		InputStreamReader reader = null;
-
-		try{
-			byte[]	file_bytes = FileUtil.readFileAsByteArray( new File( plistFile ));
-			
-				// handle UTF-8 encoded BOM EFBBBF
-						
-			if ( 	file_bytes.length > 3 &&
-					file_bytes[0] == (byte)0xEF &&
-					file_bytes[1] == (byte)0xBB &&
-					file_bytes[2] == (byte)0xBF ){
-				
-				found_bom = true;
-				
-				reader = new InputStreamReader( new ByteArrayInputStream( file_bytes, 3, file_bytes.length - 3 ));
-				
-			}else{
-				
-				found_bom = false;
-				
-				reader = new InputStreamReader( new ByteArrayInputStream( file_bytes ));
-
-			}
-					
-			//max 32KB
-			
-			int length = 32 * 1024;
-			
-			char[] buffer = new char[length];
-			
-			int offset = 0;
-			
-			int len = 0;
-			
-			while((len = reader.read(buffer,offset,length-offset)) > 0) {
-				offset += len;
-			}
-			
-			String result =  new String(buffer,0,offset);
-			
-			return result;
-			
-		} finally {
-			if(reader != null) {
-				reader.close();
-			}
-		}
-		
-		
-		//return FileUtil.readFileAsString(new File(plistFile), 64*1024, "UTF-8" );
-	}
-	
-	private void 
-	setFileContent(
-		String fileContent )
-	
-		throws IOException
-	{
-		File	file		= new File( plistFile );
-		
-		File	backup_file = new File( plistFile + ".bak" );
-		
-		if ( file.exists()){
-			
-			if ( !FileUtil.copyFile( file, backup_file )){
-				
-				throw( new IOException( "Failed to backup plist file prior to modification" ));
-			}
-		}
-		
-		boolean	ok = false;
-		
-		try{
-			
-			ByteArrayOutputStream	baos = new ByteArrayOutputStream( fileContent.length() + 256 );
-			
-			if ( found_bom ){
-				
-					// preserve UTF-8 BOM if it was found
-				
-				baos.write( new byte[]{ (byte)0xEF, (byte)0xBB, (byte)0xBF });
-			}
-			
-			OutputStreamWriter osw = new OutputStreamWriter( baos );
-			
-			osw.write( fileContent );
-			
-			osw.close();
-			
-			FileOutputStream out = null;
-						
-			try{
-				
-				out = new FileOutputStream( plistFile );
-
-		    	out.write(  baos.toByteArray() );
-	
-			}finally{
-				
-				if( out != null ){
-					
-					out.close();
-					
-					ok = true;
-				}
-			}
-		}finally{
-			if ( ok ){
-				
-				backup_file.delete();
-				
-			}else{
-				
-				if ( backup_file.exists()){
-					
-					File	bork_file = new File( plistFile + ".bad" );
-
-					file.renameTo( bork_file );
-					
-					file.delete();
-					
-					backup_file.renameTo( file );
-				}
-			}
-		}
-	}
-	
-	public void 
-	touchFile()
-	{
-		File	file  = new File( plistFile );
-		for(int i = 0 ; i <= 2 ; i++) {
-			if(file != null) {
-				String command[] = new String[] { "touch", file.getAbsolutePath() };
-				
-				try{
-					Runtime.getRuntime().exec(command);
-					
-				} catch(Exception e) {
-					
-					e.printStackTrace();
-				}
-			
-				file = file.getParentFile();
-			}
-		}
-	}
-	
-	public static void main(String args[]) {
-		try{
-			PListEditor editor = new PListEditor("/Applications/Vuze.app/Contents/Info.plist");
-			editor.setFileTypeExtensions(new String[] {"torrent","tor","vuze","vuz"});
-			editor.setSimpleStringValue("CFBundleName", "Vuze");
-			editor.setSimpleStringValue("CFBundleTypeName", "Vuze Download");
-			editor.setSimpleStringValue("CFBundleGetInfoString","Vuze");
-			editor.setArrayValues("CFBundleURLSchemes", "string", new String[] {"magnet","dht"});
-		}catch( Throwable e ){
-			
-			e.printStackTrace();
-		}
-	}
-
-}
+/*
+ * Created on Apr 1, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.platform.macosx;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+
+import org.gudy.azureus2.core3.util.ByteFormatter;
+import org.gudy.azureus2.core3.util.FileUtil;
+
+public class 
+PListEditor 
+{	
+	private String plistFile;
+	
+	private boolean	found_bom;
+	
+	public 
+	PListEditor(
+		String plistFile )
+	
+		throws IOException
+	{
+		this.plistFile = plistFile;
+		
+		File	file  = new File( plistFile );
+		
+		if ( !file.exists()){
+			
+			throw( new IOException( "plist file '" + file + "' doesn't exist" ));
+		}
+		
+		if ( !file.canWrite()){
+			
+			throw( new IOException( "plist file '" + file + "' is read only" ));
+		}
+	}
+	
+	public void 
+	setFileTypeExtensions(
+		String[] extensions )
+	
+		throws IOException
+	{
+		StringBuffer value = new StringBuffer();
+		StringBuffer find = new StringBuffer();
+		find.append("(?s).*?<key>CFBundleDocumentTypes</key>\\s*<array>.*?<key>CFBundleTypeExtensions</key>\\s*<array>");
+		for(int i = 0 ; i < extensions.length ; i++) {
+			value.append("\n\t\t\t\t<string>");
+			value.append(extensions[i]);
+			value.append("</string>");
+			
+			find.append(".*?");
+			find.append(extensions[i]);
+		}
+		value.append("\n\t\t\t");
+		
+		find.append(".*?</array>.*");
+		String match = "(?s)(<key>CFBundleDocumentTypes</key>\\s*<array>.*?<key>CFBundleTypeExtensions</key>\\s*<array>)(.*?)(</array>)";
+		
+		setValue(find.toString(), match, value.toString());
+	}
+	
+	public void 
+	setSimpleStringValue(
+		String key,
+		String value)
+	
+		throws IOException
+	{
+		String find = "(?s).*?<key>" + key + "</key>\\s*" + "<string>" + value + "</string>.*";
+		String match = "(?s)(<key>" + key + "</key>\\s*" + "<string>)(.*?)(</string>)";
+		setValue(find, match, value);
+	}
+	
+	public void
+	setArrayValues(
+		String key,
+		String valueType,
+		String[] values) 
+	
+		throws IOException
+	{
+		StringBuffer value = new StringBuffer();
+		StringBuffer find = new StringBuffer();
+		find.append("(?s).*?<key>" + key + "</key>\\s*" + "<array>");
+		for(int i = 0 ; i < values.length ; i++) {
+			find.append("\\s*<" + valueType + ">" + values[i] + "</" + valueType + ">");
+			value.append("\n\t\t\t\t<" + valueType + ">");
+			value.append(values[i]);
+			value.append("</" + valueType + ">");
+		}
+		find.append("\\s*</array>.*");
+		value.append("\n\t\t\t");
+		
+		String match = "(?s)(<key>" + key + "</key>\\s*<array>)(.*?)(</array>)";
+		
+		setValue(find.toString(),match,value.toString());
+	}
+	
+	private boolean 
+	isValuePresent(
+		String	fileContent,
+		String 	match )
+	
+		throws IOException
+	{		
+		//System.out.println("Searching for:\n" + match);
+		return fileContent.matches(match);
+	}
+	
+
+	/**
+	 * 
+	 * @param find the regex expression to find if the value is already present
+	 * @param match the regex expression that will match for the replace, it needs to capture 3 groups, the 2nd one being replaced by value
+	 * @param value the value that replaces the 2nd match group
+	 */
+	private void 
+	setValue(
+		String find,
+		String match,
+		String value)
+	
+		throws IOException
+	{
+		String fileContent = getFileContent();
+		
+		if( !isValuePresent(fileContent,find)) {
+			//System.out.println("Changing " +plistFile);
+			fileContent = fileContent.replaceFirst(match, "$1"+value + "$3");
+			setFileContent(fileContent);
+			touchFile();
+		}
+	}
+	
+	private String 
+	getFileContent()
+		throws IOException
+	{
+		InputStreamReader reader = null;
+
+		try{
+			byte[]	file_bytes = FileUtil.readFileAsByteArray( new File( plistFile ));
+			
+				// handle UTF-8 encoded BOM EFBBBF
+						
+			if ( 	file_bytes.length > 3 &&
+					file_bytes[0] == (byte)0xEF &&
+					file_bytes[1] == (byte)0xBB &&
+					file_bytes[2] == (byte)0xBF ){
+				
+				found_bom = true;
+				
+				reader = new InputStreamReader( new ByteArrayInputStream( file_bytes, 3, file_bytes.length - 3 ));
+				
+			}else{
+				
+				found_bom = false;
+				
+				reader = new InputStreamReader( new ByteArrayInputStream( file_bytes ));
+
+			}
+					
+			//max 32KB
+			
+			int length = 32 * 1024;
+			
+			char[] buffer = new char[length];
+			
+			int offset = 0;
+			
+			int len = 0;
+			
+			while((len = reader.read(buffer,offset,length-offset)) > 0) {
+				offset += len;
+			}
+			
+			String result =  new String(buffer,0,offset);
+			
+			return result;
+			
+		} finally {
+			if(reader != null) {
+				reader.close();
+			}
+		}
+		
+		
+		//return FileUtil.readFileAsString(new File(plistFile), 64*1024, "UTF-8" );
+	}
+	
+	private void 
+	setFileContent(
+		String fileContent )
+	
+		throws IOException
+	{
+		File	file		= new File( plistFile );
+		
+		File	backup_file = new File( plistFile + ".bak" );
+		
+		if ( file.exists()){
+			
+			if ( !FileUtil.copyFile( file, backup_file )){
+				
+				throw( new IOException( "Failed to backup plist file prior to modification" ));
+			}
+		}
+		
+		boolean	ok = false;
+		
+		try{
+			
+			ByteArrayOutputStream	baos = new ByteArrayOutputStream( fileContent.length() + 256 );
+			
+			if ( found_bom ){
+				
+					// preserve UTF-8 BOM if it was found
+				
+				baos.write( new byte[]{ (byte)0xEF, (byte)0xBB, (byte)0xBF });
+			}
+			
+			OutputStreamWriter osw = new OutputStreamWriter( baos );
+			
+			osw.write( fileContent );
+			
+			osw.close();
+			
+			FileOutputStream out = null;
+						
+			try{
+				
+				out = new FileOutputStream( plistFile );
+
+		    	out.write(  baos.toByteArray() );
+	
+			}finally{
+				
+				if( out != null ){
+					
+					out.close();
+					
+					ok = true;
+				}
+			}
+		}finally{
+			if ( ok ){
+				
+				backup_file.delete();
+				
+			}else{
+				
+				if ( backup_file.exists()){
+					
+					File	bork_file = new File( plistFile + ".bad" );
+
+					file.renameTo( bork_file );
+					
+					file.delete();
+					
+					backup_file.renameTo( file );
+				}
+			}
+		}
+	}
+	
+	public void 
+	touchFile()
+	{
+		File	file  = new File( plistFile );
+		for(int i = 0 ; i <= 2 ; i++) {
+			if(file != null) {
+				String command[] = new String[] { "touch", file.getAbsolutePath() };
+				
+				try{
+					Runtime.getRuntime().exec(command);
+					
+				} catch(Exception e) {
+					
+					e.printStackTrace();
+				}
+			
+				file = file.getParentFile();
+			}
+		}
+	}
+	
+	public static void main(String args[]) {
+		try{
+			PListEditor editor = new PListEditor("/Applications/Vuze.app/Contents/Info.plist");
+			editor.setFileTypeExtensions(new String[] {"torrent","tor","vuze","vuz"});
+			editor.setSimpleStringValue("CFBundleName", "Vuze");
+			editor.setSimpleStringValue("CFBundleTypeName", "Vuze Download");
+			editor.setSimpleStringValue("CFBundleGetInfoString","Vuze");
+			editor.setArrayValues("CFBundleURLSchemes", "string", new String[] {"magnet","dht"});
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+		}
+	}
+
+}
diff --git a/azureus2/src/org/gudy/azureus2/platform/macosx/PlatformManagerImpl.java b/azureus2/src/org/gudy/azureus2/platform/macosx/PlatformManagerImpl.java
index 8ed3d37..a460e20 100644
--- a/azureus2/src/org/gudy/azureus2/platform/macosx/PlatformManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/platform/macosx/PlatformManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Mar-2004
  * Created by James Yeh
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -1556,13 +1553,16 @@ public class PlatformManagerImpl implements PlatformManager, AEDiagnosticsEviden
      */
     protected static String performOSAScript(CharSequence[] cmds) throws IOException
     {
+    	/*
         long start = System.currentTimeMillis();
+       
         Debug.outNoStack("Executing OSAScript: ");
         for (int i = 0; i < cmds.length; i++)
         {
             Debug.outNoStack("\t" + cmds[i]);
         }
-
+		*/
+        
         String[] cmdargs = new String[2 * cmds.length + 1];
         cmdargs[0] = "osascript";
         for (int i = 0; i < cmds.length; i++)
@@ -1575,15 +1575,16 @@ public class PlatformManagerImpl implements PlatformManager, AEDiagnosticsEviden
         BufferedReader reader = new BufferedReader(new InputStreamReader(osaProcess.getInputStream()));
         String line = reader.readLine();
         reader.close();
-        Debug.outNoStack("OSAScript Output: " + line);
+        
+        //Debug.outNoStack("OSAScript Output: " + line);
 
         reader = new BufferedReader(new InputStreamReader(osaProcess.getErrorStream()));
         String errorMsg = reader.readLine();
         reader.close();
 
-        Debug.outNoStack("OSAScript Error (if any): " + errorMsg);
+        //Debug.outNoStack("OSAScript Error (if any): " + errorMsg);
 
-        Debug.outNoStack(MessageFormat.format("OSAScript execution ended ({0}ms)", new Object[]{String.valueOf(System.currentTimeMillis() - start)}));
+        //Debug.outNoStack(MessageFormat.format("OSAScript execution ended ({0}ms)", new Object[]{String.valueOf(System.currentTimeMillis() - start)}));
 
         try {
         	osaProcess.destroy();
@@ -1607,22 +1608,24 @@ public class PlatformManagerImpl implements PlatformManager, AEDiagnosticsEviden
      */
     protected static String performOSAScript(File script) throws IOException
     {
+    	/*
         long start = System.currentTimeMillis();
         Debug.outNoStack("Executing OSAScript from file: " + script.getPath());
-
+		*/
+    	
         Process osaProcess = performRuntimeExec(new String[]{"osascript", script.getPath()});
         BufferedReader reader = new BufferedReader(new InputStreamReader(osaProcess.getInputStream()));
         String line = reader.readLine();
         reader.close();
-        Debug.outNoStack("OSAScript Output: " + line);
+        //Debug.outNoStack("OSAScript Output: " + line);
 
         reader = new BufferedReader(new InputStreamReader(osaProcess.getErrorStream()));
         String errorMsg = reader.readLine();
         reader.close();
 
-        Debug.outNoStack("OSAScript Error (if any): " + errorMsg);
+        //Debug.outNoStack("OSAScript Error (if any): " + errorMsg);
 
-        Debug.outNoStack(MessageFormat.format("OSAScript execution ended ({0}ms)", new Object[]{String.valueOf(System.currentTimeMillis() - start)}));
+        //Debug.outNoStack(MessageFormat.format("OSAScript execution ended ({0}ms)", new Object[]{String.valueOf(System.currentTimeMillis() - start)}));
 
         try {
         	osaProcess.destroy();
@@ -1656,13 +1659,15 @@ public class PlatformManagerImpl implements PlatformManager, AEDiagnosticsEviden
      */
     protected static boolean compileOSAScript(CharSequence[] cmds, File destination)
     {
+    	/*
         long start = System.currentTimeMillis();
         Debug.outNoStack("Compiling OSAScript: " + destination.getPath());
         for (int i = 0; i < cmds.length; i++)
         {
             Debug.outNoStack("\t" + cmds[i]);
         }
-
+		*/
+    	
         String[] cmdargs = new String[2 * cmds.length + 3];
         cmdargs[0] = "osacompile";
         for (int i = 0; i < cmds.length; i++)
@@ -1690,9 +1695,9 @@ public class PlatformManagerImpl implements PlatformManager, AEDiagnosticsEviden
             return false;
         }
 
-        Debug.outNoStack("OSACompile Error (if any): " + errorMsg);
+        //Debug.outNoStack("OSACompile Error (if any): " + errorMsg);
 
-        Debug.outNoStack(MessageFormat.format("OSACompile execution ended ({0}ms)", new Object[]{String.valueOf(System.currentTimeMillis() - start)}));
+        //Debug.outNoStack(MessageFormat.format("OSACompile execution ended ({0}ms)", new Object[]{String.valueOf(System.currentTimeMillis() - start)}));
 
         return (errorMsg == null);
     }
diff --git a/azureus2/src/org/gudy/azureus2/platform/macosx/PlatformManagerUpdateChecker.java b/azureus2/src/org/gudy/azureus2/platform/macosx/PlatformManagerUpdateChecker.java
index 340c290..2decb24 100644
--- a/azureus2/src/org/gudy/azureus2/platform/macosx/PlatformManagerUpdateChecker.java
+++ b/azureus2/src/org/gudy/azureus2/platform/macosx/PlatformManagerUpdateChecker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -223,6 +220,7 @@ PlatformManagerUpdateChecker
 					checker.addUpdate(
 						UPDATE_NAME,
 						update_d,
+						current_version,
 						target_version,
 						alternate_rdl,
 						Update.RESTART_REQUIRED_YES );
diff --git a/azureus2/src/org/gudy/azureus2/platform/macosx/access/cocoa/CocoaJavaBridge.java b/azureus2/src/org/gudy/azureus2/platform/macosx/access/cocoa/CocoaJavaBridge.java
index 4b5b0a3..12a883d 100644
--- a/azureus2/src/org/gudy/azureus2/platform/macosx/access/cocoa/CocoaJavaBridge.java
+++ b/azureus2/src/org/gudy/azureus2/platform/macosx/access/cocoa/CocoaJavaBridge.java
@@ -3,7 +3,7 @@ package org.gudy.azureus2.platform.macosx.access.cocoa;
 /*
  * Created on 27-Mar-2005
  * Created by James Yeh
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -17,9 +17,6 @@ package org.gudy.azureus2.platform.macosx.access.cocoa;
  * 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.
- *
  */
 
 import org.gudy.azureus2.core3.logging.*;
diff --git a/azureus2/src/org/gudy/azureus2/platform/macosx/access/jnilib/OSXAccess.java b/azureus2/src/org/gudy/azureus2/platform/macosx/access/jnilib/OSXAccess.java
index 4446a81..0ddde4a 100644
--- a/azureus2/src/org/gudy/azureus2/platform/macosx/access/jnilib/OSXAccess.java
+++ b/azureus2/src/org/gudy/azureus2/platform/macosx/access/jnilib/OSXAccess.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 21, 2006 3:19:03 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.platform.macosx.access.jnilib;
 
@@ -55,7 +52,7 @@ public class OSXAccess
 	private static boolean loadLibrary(String lib) {
 		try {
 			SystemLoadLibrary(lib);
-			System.out.println(lib + " v" + getVersion() + " Load complete!");
+			//System.out.println(lib + " v" + getVersion() + " Load complete!");
 			bLoaded = true;
 			initialize();
 		} catch (Throwable e1) {
diff --git a/azureus2/src/org/gudy/azureus2/platform/macosx/access/jnilib/OSXDriveDetectListener.java b/azureus2/src/org/gudy/azureus2/platform/macosx/access/jnilib/OSXDriveDetectListener.java
index 4677e41..d1b811d 100644
--- a/azureus2/src/org/gudy/azureus2/platform/macosx/access/jnilib/OSXDriveDetectListener.java
+++ b/azureus2/src/org/gudy/azureus2/platform/macosx/access/jnilib/OSXDriveDetectListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.platform.macosx.access.jnilib;
 
 import java.io.File;
diff --git a/azureus2/src/org/gudy/azureus2/platform/unix/PlatformManagerImpl.java b/azureus2/src/org/gudy/azureus2/platform/unix/PlatformManagerImpl.java
index e2b6331..acfbd62 100644
--- a/azureus2/src/org/gudy/azureus2/platform/unix/PlatformManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/platform/unix/PlatformManagerImpl.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.platform.unix;
diff --git a/azureus2/src/org/gudy/azureus2/platform/unix/PlatformManagerUnixPlugin.java b/azureus2/src/org/gudy/azureus2/platform/unix/PlatformManagerUnixPlugin.java
index dd89ef4..4cd92aa 100644
--- a/azureus2/src/org/gudy/azureus2/platform/unix/PlatformManagerUnixPlugin.java
+++ b/azureus2/src/org/gudy/azureus2/platform/unix/PlatformManagerUnixPlugin.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.platform.unix;
diff --git a/azureus2/src/org/gudy/azureus2/platform/unix/ScriptAfterShutdown.java b/azureus2/src/org/gudy/azureus2/platform/unix/ScriptAfterShutdown.java
index baed061..1612d1a 100644
--- a/azureus2/src/org/gudy/azureus2/platform/unix/ScriptAfterShutdown.java
+++ b/azureus2/src/org/gudy/azureus2/platform/unix/ScriptAfterShutdown.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.platform.unix;
 
 import java.io.*;
diff --git a/azureus2/src/org/gudy/azureus2/platform/unix/ScriptBeforeStartup.java b/azureus2/src/org/gudy/azureus2/platform/unix/ScriptBeforeStartup.java
index 0ddf84c..ae3c1ec 100644
--- a/azureus2/src/org/gudy/azureus2/platform/unix/ScriptBeforeStartup.java
+++ b/azureus2/src/org/gudy/azureus2/platform/unix/ScriptBeforeStartup.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.platform.unix;
 
 import java.io.*;
diff --git a/azureus2/src/org/gudy/azureus2/platform/unix/startupScript b/azureus2/src/org/gudy/azureus2/platform/unix/startupScript
index de8117f..748fbb4 100644
--- a/azureus2/src/org/gudy/azureus2/platform/unix/startupScript
+++ b/azureus2/src/org/gudy/azureus2/platform/unix/startupScript
@@ -4,30 +4,30 @@
 SCRIPT_NOT_CHANGED=0	# change this to 1 if you don't want your script overwritten!
 JAVA_PROGRAM_DIR=""	# use full path to java bin dir, ex. "/usr/java/j2sdk1.4.2/bin/"
 #PROGRAM_DIR="/home/username/apps/azureus"	# use full path to Azureus bin dir
-JAVA_ARGS="-Xmx128m"
+JAVA_ARGS="-Xmx256m"
 
 #export MOZILLA_FIVE_HOME="/path/to/gre"	# Full path to GRE/Mozilla. When commenting out this line, also comment out the next line
 #if [ "$LD_LIBRARY_PATH x" = " x" ]; then export LD_LIBRARY_PATH=$MOZILLA_FIVE_HOME; else export LD_LIBRARY_PATH=$MOZILLA_FIVE_HOME:$LD_LIBRARY_PATH; fi
 #######################################
 
-
+export SWT_GTK3=0   # things don't work well with the preliminary GTK3 SWT support
 
 ######## YOU PROBABLY DO NOT WANT TO TOUCH ANYTHING BELOW! ########
 
-SCRIPT_VERSION=3
+SCRIPT_VERSION=4
 START_CLASS="org.gudy.azureus2.ui.swt.Main"
 
 MSG_LOADING="Loading Azureus:"
 MSG_STARTING="Starting Azureus..."
 MSG2="Java exec found in "
 MSG3="OOPS, your java version is too old "
-MSG4="You need to upgrade to JRE 1.4.x or newer from http://java.sun.com"
+MSG4="You need to upgrade to JRE 1.5.x or newer from http://java.sun.com"
 MSG5="Suitable java version found "
 MSG6="Configuring environment..."
 MSG7="OOPS, you don't seem to have a valid JRE "
 MSG8="OOPS, unable to locate java exec in "
 MSG9=" hierarchy"
-MSG10="Java exec not found in PATH, starting auto-search..."
+MSG_JAVASEARCH="Java exec not found in PATH, starting auto-search..."
 MSG11="Java exec found in PATH. Verifying..."
 MSG_AZEXIT="Exit from Azureus complete"
 MSG_TERMINATED="Azureus TERMINATED."
@@ -39,6 +39,7 @@ SKIP_GCJ=1
 
 look_for_java()
 {
+  # check if java is in path.  If it is, we do not need to search
 	if command -v java &>/dev/null; then
 		if check_version ; then
 			echo $MSG11
@@ -46,7 +47,7 @@ look_for_java()
 		fi
 	fi
 
-	echo $MSG10
+	echo $MSG_JAVASEARCH
 
 
 	JAVA_CHECK_DIRS="/usr/java/latest /usr/java /usr/lib/jvm/latest /usr/lib/jvm"
@@ -60,8 +61,6 @@ look_for_java()
 				echo $MSG2 $JAVA_PROGRAM_DIR
 				if check_version ; then
 					return 0
-				else
-					return 1
 				fi
 			fi
 		done
@@ -93,22 +92,19 @@ check_version()
 
 	JAVA_HEADER=`"${JAVA_PROGRAM_DIR}java" -version 2>&1 | head -n 1`
 	JAVA_IMPL=`echo ${JAVA_HEADER} | cut -f1 -d' '`
-	if [ "$JAVA_IMPL" = "java" ] ; then
-		VERSION=`echo ${JAVA_HEADER} | sed "s/java version \"\(.*\)\"/\1/"`
-		if echo $VERSION | grep "^1.[0-3]" ; then
+  if [ "$JAVA_IMPL" = "#" ] ; then
+    echo $MSG_JAVABORK
+    ${JAVA_PROGRAM_DIR}java -version 2>&1
+    exit 1
+	else
+		VERSION=`echo ${JAVA_HEADER} | sed "s/^.* version \"\(.*\)\"/\1/"`
+		if echo $VERSION | grep "^1.[0-4]" ; then
 			echo $MSG3 "[${JAVA_PROGRAM_DIR}java = ${VERSION}]" ; echo $MSG4
 			return 1
 		else
-			echo $MSG5 "[${JAVA_PROGRAM_DIR}java = ${VERSION}]" ; echo $MSG6
+			echo $MSG5 "[${JAVA_PROGRAM_DIR}java = ${JAVA_IMPL} ${VERSION}]" ; echo $MSG6
 			return 0
 		fi
-	elif [ "$JAVA_IMPL" = "#" ] ; then
-		echo $MSG_JAVABORK
-		${JAVA_PROGRAM_DIR}java -version 2>&1
-		exit 1
-	else	
-		echo $MSG7 "[${JAVA_PROGRAM_DIR}java = ${JAVA_IMPL}]" ; echo $MSG4
-		return 1
 	fi
 }
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/win32/PlatformManagerImpl.java b/azureus2/src/org/gudy/azureus2/platform/win32/PlatformManagerImpl.java
index 32447ff..dd0c462 100644
--- a/azureus2/src/org/gudy/azureus2/platform/win32/PlatformManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/platform/win32/PlatformManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -1610,7 +1607,7 @@ PlatformManagerImpl
 					try{
 						registerAdditionalFileType( 
 							"Magnet", 
-							"Magnet URI", 
+							"URL:Magnet Protocol", 
 							".magnet", 
 							"application/x-magnet",
 							true );
@@ -1624,16 +1621,23 @@ PlatformManagerImpl
 			
 				// we always write this hierarchy in case magnet.exe installed in the future
 			
-			createKey( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet" );
-			createKey( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers" );
-			createKey( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers\\Azureus" );
-	
-			access.writeStringValue( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers\\Azureus", "DefaultIcon", "\"" + az_exe_string + "," + getIconIndex() + "\"" );
-			access.writeStringValue( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers\\Azureus", "Description", "Download with Vuze (formerly Azureus)" );
-			access.writeStringValue( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers\\Azureus", "ShellExecute", "\"" + az_exe_string + "\" %URL" );
+			for ( int type: new int[]{ AEWin32Access.HKEY_LOCAL_MACHINE, AEWin32Access.HKEY_CURRENT_USER } ){
+				
+				try{
+					createKey( type, "Software\\Magnet" );
+					createKey( type, "Software\\Magnet\\Handlers" );
+					createKey( type, "Software\\Magnet\\Handlers\\Azureus" );
+			
+					access.writeStringValue( type, "Software\\Magnet\\Handlers\\Azureus", "DefaultIcon", "\"" + az_exe_string + "\"," + getIconIndex());
+					access.writeStringValue( type, "Software\\Magnet\\Handlers\\Azureus", "Description", "Download with Vuze" );
+					access.writeStringValue( type, "Software\\Magnet\\Handlers\\Azureus", "ShellExecute", "\"" + az_exe_string + "\" \"%URL\"" );
+					
+					access.writeWordValue( type, "Software\\Magnet\\Handlers\\Azureus\\Type", "urn:btih", 0 );
+					
+				}catch( Throwable e ){
+				}
+			}
 			
-			access.writeWordValue( AEWin32Access.HKEY_LOCAL_MACHINE, "Software\\magnet\\Handlers\\Azureus\\Type", "urn:btih", 0 );
-
 		}catch( Throwable e ){		
 		}
 	}
@@ -1772,7 +1776,7 @@ PlatformManagerImpl
 			writeStringToHKCRandHKCU(
 					name + "\\DefaultIcon",
 					"",
-					az_exe_string + "," + getIconIndex());
+					"\"" + az_exe_string + "\"," + getIconIndex());
 			
 			writeStringToHKCRandHKCU(
 					name + "\\shell\\open\\command",
diff --git a/azureus2/src/org/gudy/azureus2/platform/win32/PlatformManagerUpdateChecker.java b/azureus2/src/org/gudy/azureus2/platform/win32/PlatformManagerUpdateChecker.java
index 177b72d..e7b0737 100644
--- a/azureus2/src/org/gudy/azureus2/platform/win32/PlatformManagerUpdateChecker.java
+++ b/azureus2/src/org/gudy/azureus2/platform/win32/PlatformManagerUpdateChecker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -223,6 +220,7 @@ PlatformManagerUpdateChecker
 					checker.addUpdate(
 						UPDATE_NAME,
 						update_d,
+						current_version,
 						target_version,
 						alternate_rdl,
 						Update.RESTART_REQUIRED_YES );
diff --git a/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32Access.java b/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32Access.java
index 275ad7c..f7f6753 100644
--- a/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32Access.java
+++ b/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32Access.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 16, 2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32AccessException.java b/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32AccessException.java
index 9bd6b51..1c75438 100644
--- a/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32AccessException.java
+++ b/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32AccessException.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 16, 2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32AccessListener.java b/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32AccessListener.java
index 3b8797e..1b6ca87 100644
--- a/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32AccessListener.java
+++ b/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32AccessListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32Manager.java b/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32Manager.java
index 8326c3b..afa57ff 100644
--- a/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32Manager.java
+++ b/azureus2/src/org/gudy/azureus2/platform/win32/access/AEWin32Manager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 16, 2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessCallback.java b/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessCallback.java
index 48cb345..278f345 100644
--- a/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessCallback.java
+++ b/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessCallback.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessExceptionImpl.java b/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessExceptionImpl.java
index 070340c..58fcb8f 100644
--- a/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessExceptionImpl.java
+++ b/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessExceptionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 16, 2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessImpl.java b/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessImpl.java
index 44309ee..2fea678 100644
--- a/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessImpl.java
+++ b/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 16, 2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessInterface.java b/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessInterface.java
index b3df613..f7a31e4 100644
--- a/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessInterface.java
+++ b/azureus2/src/org/gudy/azureus2/platform/win32/access/impl/AEWin32AccessInterface.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 16, 2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/LaunchablePlugin.java b/azureus2/src/org/gudy/azureus2/plugins/LaunchablePlugin.java
index b9e37ad..d06c8b6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/LaunchablePlugin.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/LaunchablePlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/Plugin.java b/azureus2/src/org/gudy/azureus2/plugins/Plugin.java
index 76d9a48..4fc3c26 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/Plugin.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/Plugin.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginAdapter.java b/azureus2/src/org/gudy/azureus2/plugins/PluginAdapter.java
index 2b55587..4395c1f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginAdapter.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginConfig.java b/azureus2/src/org/gudy/azureus2/plugins/PluginConfig.java
index a4e6d3e..a7527aa 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginConfig.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginConfig.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginConfigListener.java b/azureus2/src/org/gudy/azureus2/plugins/PluginConfigListener.java
index 637c414..438de52 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginConfigListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginConfigListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-May-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginEvent.java b/azureus2/src/org/gudy/azureus2/plugins/PluginEvent.java
index c1b36eb..1ab9730 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginEvent.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginEventListener.java b/azureus2/src/org/gudy/azureus2/plugins/PluginEventListener.java
index 6e1da5f..5ef9cdf 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginEventListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginEventListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginException.java b/azureus2/src/org/gudy/azureus2/plugins/PluginException.java
index c6c82ec..44370a3 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginInterface.java b/azureus2/src/org/gudy/azureus2/plugins/PluginInterface.java
index 43b07b2..849c8e9 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginInterface.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginInterface.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginLauncher.java b/azureus2/src/org/gudy/azureus2/plugins/PluginLauncher.java
index 275a9e0..26cbdfa 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginLauncher.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginLauncher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginListener.java b/azureus2/src/org/gudy/azureus2/plugins/PluginListener.java
index 2fac5bf..24763d0 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginManager.java b/azureus2/src/org/gudy/azureus2/plugins/PluginManager.java
index 30bf675..df12379 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -164,7 +165,16 @@ PluginManager
 		Plugin		plugin,
 		String		id )
 	{
-		PluginManagerImpl.registerPlugin( plugin, id );
+		PluginManagerImpl.registerPlugin( plugin, id, plugin.getClass().getName() );
+	}
+	
+	public static void
+	registerPlugin(
+		Plugin		plugin,
+		String		id,
+		String		config_key )
+	{
+		PluginManagerImpl.registerPlugin( plugin, id, config_key );
 	}
 	
 	/**
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginManagerArgumentHandler.java b/azureus2/src/org/gudy/azureus2/plugins/PluginManagerArgumentHandler.java
index 0b1c027..f7bc8d9 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginManagerArgumentHandler.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginManagerArgumentHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/PluginManagerDefaults.java b/azureus2/src/org/gudy/azureus2/plugins/PluginManagerDefaults.java
index 846851a..6d06ef2 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/PluginManagerDefaults.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/PluginManagerDefaults.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/UnloadablePlugin.java b/azureus2/src/org/gudy/azureus2/plugins/UnloadablePlugin.java
index 51feb14..3d5953c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/UnloadablePlugin.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/UnloadablePlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDException.java b/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDException.java
index 803137c..0331563 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDGenerator.java b/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDGenerator.java
index 28bc82a..de745ec 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDGenerator.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDGenerator.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -35,6 +32,7 @@ public interface
 ClientIDGenerator 
 {
 	public static final String PR_URL			= "URL";			// in/out, the target URL
+	public static final String PR_PROXY			= "Proxy";			// if we're using a Proxy
 	public static final String PR_RAW_REQUEST	= "Raw-Request";	// in, Boolean
 	public static final String PR_USER_AGENT	= "User-Agent";		// out
 	
diff --git a/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDManager.java b/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDManager.java
index f1afef0..bcf87ca 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/clientid/ClientIDManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/config/ConfigParameter.java b/azureus2/src/org/gudy/azureus2/plugins/config/ConfigParameter.java
index d98a954..5d8fc0a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/config/ConfigParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/config/ConfigParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/config/ConfigParameterListener.java b/azureus2/src/org/gudy/azureus2/plugins/config/ConfigParameterListener.java
index ce014da..3b7f978 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/config/ConfigParameterListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/config/ConfigParameterListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/config/PluginConfigSource.java b/azureus2/src/org/gudy/azureus2/plugins/config/PluginConfigSource.java
index 58142a6..17aa8f3 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/config/PluginConfigSource.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/config/PluginConfigSource.java
@@ -1,7 +1,7 @@
 /*
  * Created on 6 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabase.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabase.java
index 839878f..f4f7fc8 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabase.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabase.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,13 @@
  * 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.plugins.ddb;
 
 import java.net.InetSocketAddress;
+import java.util.Map;
 
 /**
  * @author parg
@@ -53,6 +51,9 @@ DistributedDatabase
 	public boolean
 	isExtendedUseAllowed();
 	
+	public String
+	getNetwork();
+	
 	public DistributedDatabaseContact
 	getLocalContact();
 	
@@ -97,6 +98,12 @@ DistributedDatabase
 	
 		throws DistributedDatabaseException;
 	
+	public DistributedDatabaseContact
+	importContact(
+		Map<String,Object>				map )
+	
+		throws DistributedDatabaseException;
+	
 	public void
 	write(
 		DistributedDatabaseListener		listener,
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseContact.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseContact.java
index 1a88ab3..3b5c64b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseContact.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseContact.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,13 @@
  * 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.plugins.ddb;
 
 import java.net.InetSocketAddress;
+import java.util.Map;
 
 /**
  * @author parg
@@ -58,6 +56,9 @@ DistributedDatabaseContact
 	public boolean
 	isOrHasBeenLocal();
 	
+	public Map<String,Object>
+	exportToMap();
+	
 		/**
 		 * Tries to open a NAT tunnel to the contact. Should only be used if direct contact fails
 		 * @return
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseEvent.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseEvent.java
index abe4938..967d03e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseException.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseException.java
index 42f34a4..38e5fa5 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseKey.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseKey.java
index f27eb6e..1fd9ad4 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseKey.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseKey.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseKeyStats.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseKeyStats.java
index cfceb98..bb33622 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseKeyStats.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseKeyStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23 May 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseListener.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseListener.java
index ce5210e..5be1a12 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseProgressListener.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseProgressListener.java
index 22ba347..bdabbac 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseProgressListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseProgressListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 06-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseTransferHandler.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseTransferHandler.java
index fa34e52..a7e2e60 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseTransferHandler.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseTransferHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -38,7 +35,7 @@ DistributedDatabaseTransferHandler
 	
 		throws DistributedDatabaseException;
 	
-	public void
+	public DistributedDatabaseValue
 	write(
 		DistributedDatabaseContact			contact,
 		DistributedDatabaseTransferType		type,
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseTransferType.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseTransferType.java
index 3ecc4a3..267ac2a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseTransferType.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseTransferType.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseValue.java b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseValue.java
index b77c0b5..2ef898e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseValue.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ddb/DistributedDatabaseValue.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/dht/mainline/MainlineDHTManager.java b/azureus2/src/org/gudy/azureus2/plugins/dht/mainline/MainlineDHTManager.java
index d8b3099..6b5ee7a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/dht/mainline/MainlineDHTManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/dht/mainline/MainlineDHTManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14 Jan 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.dht.mainline;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/dht/mainline/MainlineDHTProvider.java b/azureus2/src/org/gudy/azureus2/plugins/dht/mainline/MainlineDHTProvider.java
index e7ec2c7..1b68a56 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/dht/mainline/MainlineDHTProvider.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/dht/mainline/MainlineDHTProvider.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14 Jan 2008
  * Created by Allan Crooks
- * Copyright (C) 2008 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.dht.mainline;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManager.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManager.java
index bd01d45..cb32690 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerChannel.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerChannel.java
index dcf7983..f9cb7cf 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerChannel.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerChannel.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerEvent.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerEvent.java
index bf30fbe..6bd70a3 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerException.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerException.java
index 6e3760d..e634afd 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerFileInfo.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerFileInfo.java
index 51971d0..96b7d4a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerFileInfo.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerFileInfo.java
@@ -1,11 +1,12 @@
 /*
  * Created : 2004/May/26
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,9 +16,6 @@
  * 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.plugins.disk;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerListener.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerListener.java
index 79f7718..278fb2c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerRandomReadRequest.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerRandomReadRequest.java
index e5542cb..edc1516 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerRandomReadRequest.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerRandomReadRequest.java
@@ -2,20 +2,19 @@
  * Created on Oct 10, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerReadRequest.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerReadRequest.java
index b5a32cb..290cf1c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerReadRequest.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerReadRequest.java
@@ -1,35 +1,34 @@
-/*
- * Created on Feb 5, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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.disk;
-
-public interface 
-DiskManagerReadRequest 
-{
-	public int
-	getPieceNumber();
-	
-	public int
-	getOffset();
-	
-	public int
-	getLength();
-}
+/*
+ * Created on Feb 5, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.disk;
+
+public interface 
+DiskManagerReadRequest 
+{
+	public int
+	getPieceNumber();
+	
+	public int
+	getOffset();
+	
+	public int
+	getLength();
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerReadRequestListener.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerReadRequestListener.java
index c7fa7a5..6753058 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerReadRequestListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerReadRequestListener.java
@@ -1,38 +1,37 @@
-/*
- * Created on Feb 5, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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.disk;
-
-import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
-
-public interface 
-DiskManagerReadRequestListener 
-{
-	public void
-	complete(
-		DiskManagerReadRequest		request,
-		PooledByteBuffer			buffer );
-	
-	public void
-	failed(
-		DiskManagerReadRequest		request,
-		DiskManagerException		error );
-}
+/*
+ * Created on Feb 5, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.disk;
+
+import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
+
+public interface 
+DiskManagerReadRequestListener 
+{
+	public void
+	complete(
+		DiskManagerReadRequest		request,
+		PooledByteBuffer			buffer );
+	
+	public void
+	failed(
+		DiskManagerReadRequest		request,
+		DiskManagerException		error );
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerRequest.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerRequest.java
index 6e7cb24..9706f0c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerRequest.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerWriteRequest.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerWriteRequest.java
index 328d26a..a7eb1b8 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerWriteRequest.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerWriteRequest.java
@@ -1,35 +1,34 @@
-/*
- * Created on Feb 5, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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.disk;
-
-public interface 
-DiskManagerWriteRequest 
-{
-	public int
-	getPieceNumber();
-	
-	public int
-	getOffset();
-	
-	public int
-	getLength();
-}
+/*
+ * Created on Feb 5, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.disk;
+
+public interface 
+DiskManagerWriteRequest 
+{
+	public int
+	getPieceNumber();
+	
+	public int
+	getOffset();
+	
+	public int
+	getLength();
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerWriteRequestListener.java b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerWriteRequestListener.java
index f0b5e80..f98b2d3 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerWriteRequestListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/disk/DiskManagerWriteRequestListener.java
@@ -1,35 +1,34 @@
-/*
- * Created on Feb 5, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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.disk;
-
-public interface 
-DiskManagerWriteRequestListener 
-{
-	public void
-	complete(
-		DiskManagerWriteRequest		request );
-	
-	public void
-	failed(
-		DiskManagerWriteRequest		request,
-		DiskManagerException		error );
-}
+/*
+ * Created on Feb 5, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.disk;
+
+public interface 
+DiskManagerWriteRequestListener 
+{
+	public void
+	complete(
+		DiskManagerWriteRequest		request );
+	
+	public void
+	failed(
+		DiskManagerWriteRequest		request,
+		DiskManagerException		error );
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/Download.java b/azureus2/src/org/gudy/azureus2/plugins/download/Download.java
index 155c06d..53e018b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/Download.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/Download.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -22,6 +23,7 @@
 package org.gudy.azureus2.plugins.download;
 
 import java.io.File;
+import java.util.List;
 import java.util.Map;
 
 import org.gudy.azureus2.plugins.download.savelocation.DefaultSaveLocationManager;
@@ -29,6 +31,7 @@ import org.gudy.azureus2.plugins.download.savelocation.SaveLocationChange;
 import org.gudy.azureus2.plugins.download.savelocation.SaveLocationManager;
 import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabase;
 import org.gudy.azureus2.plugins.disk.DiskManager;
 import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.plugins.network.RateLimiter;
@@ -178,6 +181,8 @@ Download extends DownloadEventNotifier, DownloadStub
     
     public static final long FLAG_METADATA_DOWNLOAD = 0x00000200;
 
+    public static final long FLAG_LIGHT_WEIGHT		= 0x00000400;
+
     
 	/** get state from above ST_ set
    * @return ST_ constant
@@ -1118,4 +1123,18 @@ Download extends DownloadEventNotifier, DownloadStub
   stubbify()
 	
 		throws DownloadException, DownloadRemovalVetoException;
+  
+  /**
+   * @since 5.4.0.1
+   * @return
+   */
+  public List<DistributedDatabase>
+  getDistributedDatabases();
+
+	/**
+	 * Returns the "Primary" file in the download.  Usually the largest one
+	 * 
+	 * @since 5.0.0.1
+	 */
+	public DiskManagerFileInfo getPrimaryFile();
 }
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadActivationEvent.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadActivationEvent.java
index 3a91918..72daa04 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadActivationEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadActivationEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadActivationListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadActivationListener.java
index c322376..51eaa48 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadActivationListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadActivationListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAnnounceResult.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAnnounceResult.java
index e47c376..b75c972 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAnnounceResult.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAnnounceResult.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAnnounceResultPeer.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAnnounceResultPeer.java
index fe8e434..8bc54b6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAnnounceResultPeer.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAnnounceResultPeer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAttributeListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAttributeListener.java
index 6da1bd4..7b50aa8 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAttributeListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadAttributeListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 8 Nov 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.download;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadCompletionListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadCompletionListener.java
index a366e9d..e1d7110 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadCompletionListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadCompletionListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 2 Jun 2008
  * Created by Allan Crooks
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadEventNotifier.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadEventNotifier.java
index 7ab4436..1cf3d36 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadEventNotifier.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadEventNotifier.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Feb 2007.
  * Created by Allan Crooks.
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,8 +12,7 @@
  * 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.
+ * MA 02111-1307, USA. 
  */
 package org.gudy.azureus2.plugins.download;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadException.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadException.java
index 54599ed..1b90a5d 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadListener.java
index 67b7a0f..fc7e6b7 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManager.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManager.java
index d82e483..88675c6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -409,6 +410,9 @@ DownloadManager
 	public DownloadStub[]
 	getDownloadStubs();
 	
+	public int
+	getDownloadStubCount();
+	
 	public void addDownloadStubListener( DownloadStubListener l, boolean inform_of_current );
 	
 	public void removeDownloadStubListener( DownloadStubListener l );
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManagerListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManagerListener.java
index 451f346..e25a58a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManagerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManagerStats.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManagerStats.java
index 9f900b1..5a6e568 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManagerStats.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadManagerStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -88,4 +85,10 @@ DownloadManagerStats
 	  
 	public long 
 	getProtocolBytesSent();
+	
+	public long
+	getSmoothedReceiveRate();
+	
+	public long
+	getSmoothedSendRate();
 }
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPeerListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPeerListener.java
index b342895..63414d1 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPeerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPeerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPropertyEvent.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPropertyEvent.java
index 55f02f3..d438722 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPropertyEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPropertyEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPropertyListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPropertyListener.java
index 8e418e7..0c0713f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPropertyListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadPropertyListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadRemovalVetoException.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadRemovalVetoException.java
index 94dfe20..b2daac1 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadRemovalVetoException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadRemovalVetoException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadScrapeResult.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadScrapeResult.java
index 9b05a62..23ce7a2 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadScrapeResult.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadScrapeResult.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStats.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStats.java
index 0583ea0..b04cb6c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStats.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -94,18 +95,19 @@ DownloadStats
 	public int
 	getCompleted();
 	
-  /** Retrieve the level of download completion.
-   * 
+  /** Retrieve the level of download completion, *including* DND files. If
+   * the user has one or more DND file, return value will never reach 1000.
+   * <P>
    * To understand the bLive parameter, you must know a bit about the
-   * Torrent activation process:
-   * 1) Torrent goes into ST_WAITING
-   * 2) Torrent moves to ST_PREPARING
-   * 3) Torrent moves to ST_DOWNLOADING or ST_SEEDING
-   *
+   * Torrent activation process:<br>
+   * 1) Torrent goes into ST_WAITING<br>
+   * 2) Torrent moves to ST_PREPARING<br>
+   * 3) Torrent moves to ST_DOWNLOADING or ST_SEEDING<br>
+   * <P>
    * While in ST_PREPARING, Completion Level is rebuilt (either via Fast Resume
    * or via piece checking). Quite often, the download completion level before
    * ST_PREPARING and after ST_PREPARING are identical.
-   *
+   * <P>
    * Before going into ST_PREPARING, we store the download completion level.
    * If you wish to retrieve this value instead of the live "building" one,
    * pass false for the parameter.
@@ -159,14 +161,17 @@ DownloadStats
 		boolean	include_protocol );
 	
 	/**
-	 * Gives number of bytes remaining.  Excludes DND files only if disk manager exists
+	 * Gives number of bytes remaining.  *Includes* DND files
 	 * 
 	 * @since 2.5.0.2
 	 */
 	
 	public long
 	getRemaining();
-	
+
+	public long
+	getRemainingExcludingDND();
+
 	/**
 	 * Gives the number of bytes uploaded
 	 * @return
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStub.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStub.java
index fe03859..c765315 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStub.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStub.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -83,4 +82,25 @@ DownloadStub
 		public long
 		getLength();
 	}
+	
+	public interface
+	DownloadStubEx
+	
+		extends DownloadStub
+	{
+		public long
+		getCreationDate();
+		
+		public String[]
+		getManualTags();
+		
+			// could migrate to DownloadStub one day
+		
+		public void
+		remove(
+			boolean		delete_torrent,
+			boolean		delete_data )
+		
+			throws DownloadException, DownloadRemovalVetoException;
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStubEvent.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStubEvent.java
index 9b12db8..487008a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStubEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStubEvent.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStubListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStubListener.java
index 7a46d5c..66dbc20 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStubListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadStubListener.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTrackerListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTrackerListener.java
index a14c4c6..d0651b2 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTrackerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTrackerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTypeComplete.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTypeComplete.java
index fd86343..bfc6f77 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTypeComplete.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTypeComplete.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 19, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTypeIncomplete.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTypeIncomplete.java
index 3754d6c..23ce8e6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTypeIncomplete.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadTypeIncomplete.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 19, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadWillBeAddedListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadWillBeAddedListener.java
index 37bd932..4407d05 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadWillBeAddedListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadWillBeAddedListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadWillBeRemovedListener.java b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadWillBeRemovedListener.java
index e64dc3d..dc9b082 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/DownloadWillBeRemovedListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/DownloadWillBeRemovedListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/DefaultSaveLocationManager.java b/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/DefaultSaveLocationManager.java
index ccf6b17..654dee2 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/DefaultSaveLocationManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/DefaultSaveLocationManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.download.savelocation;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/SaveLocationChange.java b/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/SaveLocationChange.java
index f47d2a8..2941562 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/SaveLocationChange.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/SaveLocationChange.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.download.savelocation;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/SaveLocationManager.java b/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/SaveLocationManager.java
index 7b5d5d8..f78362a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/SaveLocationManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/download/savelocation/SaveLocationManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.download.savelocation;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/installer/FilePluginInstaller.java b/azureus2/src/org/gudy/azureus2/plugins/installer/FilePluginInstaller.java
index a245b19..7a73d94 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/installer/FilePluginInstaller.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/installer/FilePluginInstaller.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/installer/InstallablePlugin.java b/azureus2/src/org/gudy/azureus2/plugins/installer/InstallablePlugin.java
index 8eb5d46..ea8a733 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/installer/InstallablePlugin.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/installer/InstallablePlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstallationListener.java b/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstallationListener.java
index d653892..0ff6203 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstallationListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstallationListener.java
@@ -1,38 +1,37 @@
-/*
- * Created on Mar 6, 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.installer;
-
-import org.gudy.azureus2.plugins.PluginException;
-
-public interface 
-PluginInstallationListener 
-{
-	public void
-	completed();
-	
-	public void
-	cancelled();
-	
-	public void
-	failed(
-		PluginException	e );
-}
+/*
+ * Created on Mar 6, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.installer;
+
+import org.gudy.azureus2.plugins.PluginException;
+
+public interface 
+PluginInstallationListener 
+{
+	public void
+	completed();
+	
+	public void
+	cancelled();
+	
+	public void
+	failed(
+		PluginException	e );
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstaller.java b/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstaller.java
index 58c45ae..2fcd687 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstaller.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstaller.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstallerListener.java b/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstallerListener.java
index 58d475e..d7b9587 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstallerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/installer/PluginInstallerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/installer/StandardPlugin.java b/azureus2/src/org/gudy/azureus2/plugins/installer/StandardPlugin.java
index 0d65f53..dcf9472 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/installer/StandardPlugin.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/installer/StandardPlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ipc/IPCException.java b/azureus2/src/org/gudy/azureus2/plugins/ipc/IPCException.java
index 462360f..eb6eae7 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ipc/IPCException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ipc/IPCException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-May-2006
  * Created by Damokles
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ipc/IPCInterface.java b/azureus2/src/org/gudy/azureus2/plugins/ipc/IPCInterface.java
index 6db691f..749aa3e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ipc/IPCInterface.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ipc/IPCInterface.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-May-2006
  * Created by Damokles
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPBanned.java b/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPBanned.java
index 8d726f9..b693f76 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPBanned.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPBanned.java
@@ -2,13 +2,14 @@
  * File    : IPBanned.java
  * Created : 08-Jan-2007
  * By      : jstockall
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, All Rights Reserved.
  * 
  * 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.
+ * 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
@@ -18,9 +19,6 @@
  * 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 org.gudy.azureus2.plugins.ipfilter;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPBlocked.java b/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPBlocked.java
index c49f294..d5c7df5 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPBlocked.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPBlocked.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPFilter.java b/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPFilter.java
index 5de8bec..ac40cc5 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPFilter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPFilter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPFilterException.java b/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPFilterException.java
index 8202ed8..91983f1 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPFilterException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPFilterException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPRange.java b/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPRange.java
index b79c1ec..b64d7d8 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPRange.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ipfilter/IPRange.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/logging/FileLoggerAdapter.java b/azureus2/src/org/gudy/azureus2/plugins/logging/FileLoggerAdapter.java
index ffa7d50..896657d 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/logging/FileLoggerAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/logging/FileLoggerAdapter.java
@@ -1,6 +1,6 @@
 /*
  * Created on Mar 3, 2006 11:39:23 AM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.plugins.logging;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/logging/LogAlert.java b/azureus2/src/org/gudy/azureus2/plugins/logging/LogAlert.java
index 586a02f..784c9ae 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/logging/LogAlert.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/logging/LogAlert.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Aug 2008
  * Created by Allan Crooks
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/logging/LogAlertListener.java b/azureus2/src/org/gudy/azureus2/plugins/logging/LogAlertListener.java
index 5f1d79d..97759c0 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/logging/LogAlertListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/logging/LogAlertListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Aug 2008
  * Created by Allan Crooks
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/logging/Logger.java b/azureus2/src/org/gudy/azureus2/plugins/logging/Logger.java
index 132f2fa..98b70c9 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/logging/Logger.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/logging/Logger.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerAlertListener.java b/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerAlertListener.java
index c7c4d47..ecc2bbe 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerAlertListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerAlertListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerChannel.java b/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerChannel.java
index ae55bf1..2063357 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerChannel.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerChannel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerChannelListener.java b/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerChannelListener.java
index a680739..5b58fa3 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerChannelListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/logging/LoggerChannelListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/Message.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/Message.java
index 5fde4c4..93ccb76 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/Message.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/Message.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageException.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageException.java
index f7d02d2..fa4ee04 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageException.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 8, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageManager.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageManager.java
index 73a51d1..ad53b17 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 24, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageManagerListener.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageManagerListener.java
index 3b7b9b4..f9f69d6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageManagerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 26, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageStreamDecoder.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageStreamDecoder.java
index 8416f8e..4589390 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageStreamDecoder.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageStreamDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 11, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageStreamEncoder.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageStreamEncoder.java
index a4fdbef..99a73bc 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageStreamEncoder.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/MessageStreamEncoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageCancel.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageCancel.java
index 477d6a4..0aff1f3 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageCancel.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageCancel.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 28, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageManager.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageManager.java
index fe7fd17..5eef08f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 28, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessagePiece.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessagePiece.java
index 854ab4c..b285013 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessagePiece.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessagePiece.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 28, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageRequest.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageRequest.java
index dae49b4..63fe9b9 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageRequest.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/bittorrent/BTMessageRequest.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 28, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageConnection.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageConnection.java
index 6a50226..5cbcc0d 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageConnection.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageConnectionListener.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageConnectionListener.java
index 94f0625..953ff67 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageConnectionListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageConnectionListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageEndpoint.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageEndpoint.java
index 65abe73..9729bc0 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageEndpoint.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageEndpoint.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageHandler.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageHandler.java
index fcbca2b..e09f1cd 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageHandler.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageRegistration.java b/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageRegistration.java
index e109525..3d7af6e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageRegistration.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/messaging/generic/GenericMessageRegistration.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/Connection.java b/azureus2/src/org/gudy/azureus2/plugins/network/Connection.java
index c39bc40..54c38cd 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/Connection.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/Connection.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionListener.java b/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionListener.java
index bae9f13..dfc3c2b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionManager.java b/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionManager.java
index 8f233b0..76a755f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionStub.java b/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionStub.java
index 87f17e9..cfc508b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionStub.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/ConnectionStub.java
@@ -2,20 +2,19 @@
  * Created on May 25, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/IncomingMessageQueue.java b/azureus2/src/org/gudy/azureus2/plugins/network/IncomingMessageQueue.java
index 8f144cc..0584874 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/IncomingMessageQueue.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/IncomingMessageQueue.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/IncomingMessageQueueListener.java b/azureus2/src/org/gudy/azureus2/plugins/network/IncomingMessageQueueListener.java
index d60bf8f..4b5e828 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/IncomingMessageQueueListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/IncomingMessageQueueListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 11, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/OutgoingMessageQueue.java b/azureus2/src/org/gudy/azureus2/plugins/network/OutgoingMessageQueue.java
index eebb1d7..ede9b64 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/OutgoingMessageQueue.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/OutgoingMessageQueue.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/OutgoingMessageQueueListener.java b/azureus2/src/org/gudy/azureus2/plugins/network/OutgoingMessageQueueListener.java
index ebe4628..7ea601f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/OutgoingMessageQueueListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/OutgoingMessageQueueListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/RateLimiter.java b/azureus2/src/org/gudy/azureus2/plugins/network/RateLimiter.java
index 3e8a848..3351619 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/RateLimiter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/RateLimiter.java
@@ -1,44 +1,43 @@
-/*
- * Created on Apr 16, 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.network;
-
-public interface 
-RateLimiter 
-{
-	public String
-	getName();
-	
-	/**
-	 * Get rate limit. 0 -> unlimited, -1 -> disabled
-	 * @return
-	 */
-	
-	public int 
-	getRateLimitBytesPerSecond();
-	
-	public void
-	setRateLimitBytesPerSecond(
-		int		bytes_per_second );
-	
-	public long
-	getRateLimitTotalByteCount();
-}
+/*
+ * Created on Apr 16, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.network;
+
+public interface 
+RateLimiter 
+{
+	public String
+	getName();
+	
+	/**
+	 * Get rate limit. 0 -> unlimited, -1 -> disabled
+	 * @return
+	 */
+	
+	public int 
+	getRateLimitBytesPerSecond();
+	
+	public void
+	setRateLimitBytesPerSecond(
+		int		bytes_per_second );
+	
+	public long
+	getRateLimitTotalByteCount();
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/RawMessage.java b/azureus2/src/org/gudy/azureus2/plugins/network/RawMessage.java
index 1b27918..52f31f3 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/RawMessage.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/RawMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/Transport.java b/azureus2/src/org/gudy/azureus2/plugins/network/Transport.java
index 4689027..edd4a21 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/Transport.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/Transport.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 11, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/TransportCipher.java b/azureus2/src/org/gudy/azureus2/plugins/network/TransportCipher.java
index bba15cf..5c3139a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/TransportCipher.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/TransportCipher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.network;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/network/TransportException.java b/azureus2/src/org/gudy/azureus2/plugins/network/TransportException.java
index 3ac277f..b2e69d0 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/network/TransportException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/network/TransportException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.network;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/Peer.java b/azureus2/src/org/gudy/azureus2/plugins/peers/Peer.java
index c7346cd..daf0de8 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/Peer.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/Peer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerDescriptor.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerDescriptor.java
index 4875ac0..f653303 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerDescriptor.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerDescriptor.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Oct 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerEvent.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerEvent.java
index 5fb8d5f..d382d61 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Feb-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerListener.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerListener.java
index 036a1ce..982ea1e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerListener2.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerListener2.java
index b6668a2..f261c28 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerListener2.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerListener2.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Feb-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManager.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManager.java
index ff2d9cc..772b4c8 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -54,21 +55,21 @@ PeerManager
 	
 	public void 
 	addPeer( 
-		String ip_address, 
-		int port );
+		String 		ip_address, 
+		int 		port );
 	
 	public void 
 	addPeer( 
-		String 	ip_address, 
-		int 	tcp_port, 
-		boolean use_crypto );
+		String 		ip_address, 
+		int 		tcp_port, 
+		boolean 	use_crypto );
   
 	public void 
 	addPeer( 
-		String 	ip_address, 
-		int 	tcp_port, 
-		int		udp_port,
-		boolean use_crypto );
+		String 		ip_address, 
+		int 		tcp_port, 
+		int			udp_port,
+		boolean 	use_crypto );
   
 	public void 
 	addPeer( 
@@ -78,6 +79,14 @@ PeerManager
 		boolean 			use_crypto,
 		Map<Object,Object>	user_data );
 	
+	public void 
+	peerDiscovered( 
+		String				peer_source,
+		String 				ip_address, 
+		int 				tcp_port, 
+		int					udp_port,
+		boolean 			use_crypto );
+	
 	public void
 	removePeer(
 		Peer		peer );
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerEvent.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerEvent.java
index 2d2e916..27faa58 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerEvent.java
@@ -1,57 +1,56 @@
-/*
- * Created on Dec 22, 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.peers;
-
-public interface 
-PeerManagerEvent 
-{
-	/** Peer Added: Use getPeer */
-	public static final int ET_PEER_ADDED			= 1;		// getPeer
-	/** Peer Removed: Use getPeer */
-	public static final int ET_PEER_REMOVED			= 2;		// getPeer
-	/** Peer Discovered: getPeerDescriptor for discovery information; getPeer() returns peer that discovered it. */
-	public static final int ET_PEER_DISCOVERED		= 3;		// getPeerDescriptor; opt getPeer if discovered from a Peer
-	/** Peer Sent Bad Data: {@link #getPeer()}; {@link #getData()} to retrieve {@link Integer} piece number */
-	public static final int ET_PEER_SENT_BAD_DATA	= 4;		// getPeer; getData -> Integer piece number
-
-	/** Piece Activated: Use {@link #getPeer()}; {@link #getData()} returns Piece Object */
-	public static final int ET_PIECE_ACTIVATED			= 5;		// opt getPeer; getData -> Piece object
-	/** Piece Deactivated: Use {@link #getPeer()}; {@link #getData()} returns Piece Object */
-	public static final int ET_PIECE_DEACTIVATED		= 6;		// getData -> Piece object
-	/** Piece Completion Changed: Use {@link #getPeer()}; {@link #getData()} returns Piece Object */
-	public static final int ET_PIECE_COMPLETION_CHANGED	= 7;		// getData -> Piece object
-	
-	public PeerManager
-	getPeerManager();
-	
-	public int
-	getType();
-	
-	public Peer
-	getPeer();
-	
-	public PeerDescriptor
-	getPeerDescriptor();
-	
-	public Object
-	getData();
-}
+/*
+ * Created on Dec 22, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.peers;
+
+public interface 
+PeerManagerEvent 
+{
+	/** Peer Added: Use getPeer */
+	public static final int ET_PEER_ADDED			= 1;		// getPeer
+	/** Peer Removed: Use getPeer */
+	public static final int ET_PEER_REMOVED			= 2;		// getPeer
+	/** Peer Discovered: getPeerDescriptor for discovery information; getPeer() returns peer that discovered it. */
+	public static final int ET_PEER_DISCOVERED		= 3;		// getPeerDescriptor; opt getPeer if discovered from a Peer
+	/** Peer Sent Bad Data: {@link #getPeer()}; {@link #getData()} to retrieve {@link Integer} piece number */
+	public static final int ET_PEER_SENT_BAD_DATA	= 4;		// getPeer; getData -> Integer piece number
+
+	/** Piece Activated: Use {@link #getPeer()}; {@link #getData()} returns Piece Object */
+	public static final int ET_PIECE_ACTIVATED			= 5;		// opt getPeer; getData -> Piece object
+	/** Piece Deactivated: Use {@link #getPeer()}; {@link #getData()} returns Piece Object */
+	public static final int ET_PIECE_DEACTIVATED		= 6;		// getData -> Piece object
+	/** Piece Completion Changed: Use {@link #getPeer()}; {@link #getData()} returns Piece Object */
+	public static final int ET_PIECE_COMPLETION_CHANGED	= 7;		// getData -> Piece object
+	
+	public PeerManager
+	getPeerManager();
+	
+	public int
+	getType();
+	
+	public Peer
+	getPeer();
+	
+	public PeerDescriptor
+	getPeerDescriptor();
+	
+	public Object
+	getData();
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerListener.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerListener.java
index 5c83ea0..7bb7d9d 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerListener2.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerListener2.java
index 52cd8d1..9ede605 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerListener2.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerListener2.java
@@ -1,30 +1,29 @@
-/*
- * Created on Dec 22, 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.peers;
-
-public interface 
-PeerManagerListener2 
-{
-	public void
-	eventOccurred(
-		PeerManagerEvent	event );
-}
+/*
+ * Created on Dec 22, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.peers;
+
+public interface 
+PeerManagerListener2 
+{
+	public void
+	eventOccurred(
+		PeerManagerEvent	event );
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerStats.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerStats.java
index 2dd9de0..5bf8791 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerStats.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerManagerStats.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerReadRequest.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerReadRequest.java
index bb61d32..7b93c7b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerReadRequest.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerReadRequest.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerStats.java b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerStats.java
index 6821203..ee14f8f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/PeerStats.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/PeerStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/peers/Piece.java b/azureus2/src/org/gudy/azureus2/plugins/peers/Piece.java
index 4e365a9..319e3df 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/peers/Piece.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/peers/Piece.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15 May 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/platform/PlatformManager.java b/azureus2/src/org/gudy/azureus2/plugins/platform/PlatformManager.java
index c549090..c4d6a1f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/platform/PlatformManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/platform/PlatformManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/platform/PlatformManagerException.java b/azureus2/src/org/gudy/azureus2/plugins/platform/PlatformManagerException.java
index 16f2f1e..cf66fa7 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/platform/PlatformManagerException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/platform/PlatformManagerException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareException.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareException.java
index 5e469ae..2efe2c4 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareItem.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareItem.java
index 9ab524c..98ec52d 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareItem.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareItem.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareManager.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareManager.java
index c40a2ba..e7adf20 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -33,6 +34,9 @@ public interface
 ShareManager 
 {
 	public static final String	PR_PERSONAL		= "personal";		// "true"/"false"
+	public static final String	PR_NETWORKS		= "networks";		// String of nets, comma separated
+	public static final String	PR_TAGS			= "tags";			// String of long tag IDs, comma separated
+	public static final String	PR_USER_DATA	= "user_data";		// something distinct the 'creator' can recognise
 	
 	public void
 	initialise()
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareManagerListener.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareManagerListener.java
index 0c1fb77..fd771a6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareManagerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResource.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResource.java
index d946434..462b34f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResource.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResource.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -21,6 +22,8 @@
 
 package org.gudy.azureus2.plugins.sharing;
 
+import java.util.Map;
+
 import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
 
 /**
@@ -73,6 +76,9 @@ ShareResource
 	public TorrentAttribute[]
 	getAttributes();
 	
+	public Map<String,String>
+	getProperties();
+	
 	public boolean
 	canBeDeleted()
 	
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDeletionVetoException.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDeletionVetoException.java
index 32715a5..0fc998a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDeletionVetoException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDeletionVetoException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDir.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDir.java
index 5191afa..9887291 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDir.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDir.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDirContents.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDirContents.java
index bd8671f..0249074 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDirContents.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceDirContents.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceEvent.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceEvent.java
index 86bdd2a..2da679b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceFile.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceFile.java
index 763a665..a21e9ea 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceFile.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceFile.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceListener.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceListener.java
index 11d98c7..fd08a53 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceWillBeDeletedListener.java b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceWillBeDeletedListener.java
index 57b5c7e..c587c3c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceWillBeDeletedListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/sharing/ShareResourceWillBeDeletedListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/Torrent.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/Torrent.java
index a947305..35607f5 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/Torrent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/Torrent.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAnnounceURLList.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAnnounceURLList.java
index 62f5ee7..cc92b1a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAnnounceURLList.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAnnounceURLList.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAnnounceURLListSet.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAnnounceURLListSet.java
index 1c95ab8..0a8ce59 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAnnounceURLListSet.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAnnounceURLListSet.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttribute.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttribute.java
index d9375e7..980f90b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttribute.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttribute.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttributeEvent.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttributeEvent.java
index ceead61..0a4040a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttributeEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttributeEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttributeListener.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttributeListener.java
index ffaa50c..3f64d6c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttributeListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentAttributeListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentCreator.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentCreator.java
index f950821..b61022f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentCreator.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentCreator.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentCreatorListener.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentCreatorListener.java
index cb46fdb..1c69b71 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentCreatorListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentCreatorListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentDownloader.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentDownloader.java
index f3c902e..c2cf117 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentDownloader.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentDownloader.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentEncodingException.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentEncodingException.java
index 781869e..9b852eb 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentEncodingException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentEncodingException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentException.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentException.java
index 81d055b..9ff2c6d 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentFile.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentFile.java
index 51c3863..bea2f0b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentFile.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentFile.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManager.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManager.java
index 006baa8..13a2888 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManagerEvent.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManagerEvent.java
index 1eea010..230168b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManagerEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManagerEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManagerListener.java b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManagerListener.java
index bf35a0a..9edd728 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/torrent/TorrentManagerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/Tracker.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/Tracker.java
index df91188..aaf82c3 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/Tracker.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/Tracker.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -27,6 +28,7 @@ package org.gudy.azureus2.plugins.tracker;
  */
 
 import java.net.InetAddress;
+import java.util.Map;
 
 import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.plugins.tracker.web.TrackerWebContext;
@@ -38,6 +40,11 @@ Tracker
 	public static final int	PR_HTTP			= 1;
 	public static final int	PR_HTTPS		= 2;
 	
+		// properties for passing as, well, properties
+	
+	public static final String	PR_NON_BLOCKING		= "nonblocking";		// Boolean
+	
+	
 	public TrackerTorrent
 	host(
 		Torrent		torrent,
@@ -109,6 +116,16 @@ Tracker
     
     	throws TrackerException;
     
+    public TrackerWebContext
+    createWebContext(
+    	String					name,
+    	int						port,
+		int						protocol,
+		InetAddress				bind_ip,
+		Map<String,Object>		properties )
+    
+    	throws TrackerException;
+    
     public void
     addListener(
    		TrackerListener		listener );
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerException.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerException.java
index d206d6f..0e5e7b1 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerListener.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerListener.java
index 90f6bee..5d90b19 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeer.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeer.java
index e58e473..f89147b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeer.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeerEvent.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeerEvent.java
index 6be4981..532afb4 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeerEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeerEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeerListener.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeerListener.java
index 1374ea3..6ea9f7b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerPeerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrent.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrent.java
index 5699337..cf37a61 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrent.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentListener.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentListener.java
index 7b9aa92..6d0ddd2 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentRemovalVetoException.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentRemovalVetoException.java
index a7bc7da..c419605 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentRemovalVetoException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentRemovalVetoException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentRequest.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentRequest.java
index 37a7f7c..8c55df1 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentRequest.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentRequest.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentWillBeRemovedListener.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentWillBeRemovedListener.java
index 6983d3c..cac0e2b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentWillBeRemovedListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/TrackerTorrentWillBeRemovedListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerAuthenticationAdapter.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerAuthenticationAdapter.java
index 7e882b3..0508749 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerAuthenticationAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerAuthenticationAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerAuthenticationListener.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerAuthenticationListener.java
index d1f00b9..27403fc 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerAuthenticationListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerAuthenticationListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebContext.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebContext.java
index 6d450b5..e3a2868 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebContext.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebContext.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageGenerator.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageGenerator.java
index 9c19d4a..9a3298c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageGenerator.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageGenerator.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageRequest.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageRequest.java
index 1a44b0c..a243af8 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageRequest.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageRequest.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageResponse.java b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageResponse.java
index 2838082..c4dd717 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageResponse.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/tracker/web/TrackerWebPageResponse.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -119,4 +120,7 @@ TrackerWebPageResponse
 	getRawOutputStream()
 	
 		throws IOException;
+	
+	public boolean
+	isActive();
 }
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/Graphic.java b/azureus2/src/org/gudy/azureus2/plugins/ui/Graphic.java
index 92687fd..76b93a1 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/Graphic.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/Graphic.java
@@ -2,11 +2,12 @@
  * Created on 2004/May/23
  * Created by TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.plugins.ui;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/GraphicURI.java b/azureus2/src/org/gudy/azureus2/plugins/ui/GraphicURI.java
new file mode 100644
index 0000000..ea44841
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/GraphicURI.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.ui;
+
+import java.net.URI;
+
+/**
+ * @author TuxPaper
+ * @created Feb 10, 2015
+ *
+ */
+public class GraphicURI
+implements Graphic
+{
+	private URI uri;
+
+	public GraphicURI(URI uri) {
+		this.uri = uri;
+	}
+	
+	public URI getURI() {
+		return uri;
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIDataSourceListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIDataSourceListener.java
index 49854ef..65f1cda 100755
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIDataSourceListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIDataSourceListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.ui;
 
 public interface UIDataSourceListener
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIException.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIException.java
index bc77ae4..7a22571 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputReceiver.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputReceiver.java
index 150fc89..383b795 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputReceiver.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputReceiver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Nov-2006
  * Created by Allan Crooks
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.ui;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputReceiverListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputReceiverListener.java
index 96a6c6a..017a194 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputReceiverListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputReceiverListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.ui;
 
 public interface UIInputReceiverListener
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputValidator.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputValidator.java
index b38707e..4d52efd 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputValidator.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIInputValidator.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Nov-2006
  * Created by Allan Crooks
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.ui;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIInstance.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIInstance.java
index c84f24f..e17622f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIInstance.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIInstance.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIInstanceFactory.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIInstanceFactory.java
index d736e5b..53d14ad 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIInstanceFactory.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIInstanceFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIManager.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIManager.java
index 766d7a3..deeb3ca 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -25,6 +22,7 @@ package org.gudy.azureus2.plugins.ui;
 import java.io.File;
 import java.net.URL;
 
+import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.plugins.logging.LoggerChannel;
 import org.gudy.azureus2.plugins.ui.model.*;
@@ -33,6 +31,8 @@ import org.gudy.azureus2.plugins.ui.tables.TableManager;
 
 /**
  * Management tools for the user interface.
+ * <P>
+ * To get an UIManager, see {@link PluginInterface#getUIManager()}
  * 
  * @author parg
  */
@@ -349,6 +349,7 @@ UIManager
 
  	public void addDataSourceListener(UIDataSourceListener l, boolean triggerNow);
  	public void removeDataSourceListener(UIDataSourceListener l);
+ 	public Object getDataSource();
  	
  	public void setEverythingHidden( boolean hidden );
 }
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerEvent.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerEvent.java
index 140a2a9..00147ee 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerEventListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerEventListener.java
index 855aa4e..128c15f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerEventListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerEventListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerListener.java
index 07ba41d..7099d12 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerListener2.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerListener2.java
index 758e998..d750444 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerListener2.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIManagerListener2.java
@@ -12,9 +12,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIMessage.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIMessage.java
index b7b3759..28c80a1 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIMessage.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Apr 2008
  * Created by Allan Crooks
- * Copyright (C) 2008 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.ui;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIPluginView.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIPluginView.java
index c741f28..debd1bf 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIPluginView.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIPluginView.java
@@ -3,11 +3,12 @@
  * Created : Oct 12, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.plugins.ui;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/UIPluginViewToolBarListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/UIPluginViewToolBarListener.java
index ccf88e8..2ca373d 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/UIPluginViewToolBarListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/UIPluginViewToolBarListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.ui;
 
 import java.util.Map;
@@ -9,6 +27,7 @@ import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarEnablerBase;
  * 
  * @author Vuze
  *
+ * @see UIPluginView#setToolBarListener(UIPluginViewToolBarListener)
  */
 public interface UIPluginViewToolBarListener
 	extends UIToolBarActivationListener, UIToolBarEnablerBase
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIComponent.java b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIComponent.java
index feba711..da8fc75 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIComponent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIComponent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -33,6 +30,8 @@ UIComponent
 	public static final String PT_ENABLED		= "enabled";		// Boolean
 	public static final String PT_VALUE			= "value";			// Depends on component type
 	public static final String PT_VISIBLE		= "visible";		// Boolean
+	public static final String PT_WIDTH_HINT	= "whint";			// Integer
+	public static final String PT_HEIGHT_HINT	= "hhint";			// Integer
 	
 	public void
 	setEnabled(
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIProgressBar.java b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIProgressBar.java
index 48dbc41..323c974 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIProgressBar.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIProgressBar.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIPropertyChangeEvent.java b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIPropertyChangeEvent.java
index 4b5fee7..aa7f74c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIPropertyChangeEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIPropertyChangeEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIPropertyChangeListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIPropertyChangeListener.java
index 45287b3..54108dc 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIPropertyChangeListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UIPropertyChangeListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UITextArea.java b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UITextArea.java
index 5f8696f..e05c1e4 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UITextArea.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UITextArea.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UITextField.java b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UITextField.java
index b3c71e3..9da0e1e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/components/UITextField.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/components/UITextField.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ActionParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ActionParameter.java
index 93d8b2c..0fbe00f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ActionParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ActionParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/BooleanParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/BooleanParameter.java
index c49d35b..781b69b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/BooleanParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/BooleanParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ColorParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ColorParameter.java
index a38f6d3..f7dc86b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ColorParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ColorParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23 Oct 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.ui.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ConfigSection.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ConfigSection.java
index c026d07..9fa6f61 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ConfigSection.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ConfigSection.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/DirectoryParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/DirectoryParameter.java
index 963d694..a3ca4fb 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/DirectoryParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/DirectoryParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/EnablerParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/EnablerParameter.java
index defd11f..79a4843 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/EnablerParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/EnablerParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/FileParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/FileParameter.java
index 3ef281d..9fd6ec7 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/FileParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/FileParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Nov-2006
  * Created by Allan Crooks
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/InfoParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/InfoParameter.java
index 4b52fd7..8e22c04 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/InfoParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/InfoParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/IntParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/IntParameter.java
index 36ed1d9..c1daddf 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/IntParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/IntParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/LabelParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/LabelParameter.java
index b8e532d..53f649c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/LabelParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/LabelParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/Parameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/Parameter.java
index 5ae765a..ddae13e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/Parameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/Parameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterGroup.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterGroup.java
index acb4443..e61c5d9 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterGroup.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterGroup.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -29,6 +26,9 @@ package org.gudy.azureus2.plugins.ui.config;
 
 public interface 
 ParameterGroup 
+	extends Parameter
 {
-
+	public void
+	setNumberOfColumns(
+		int		num );
 }
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterListener.java
index 2c9095a..0c9c752 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterTabFolder.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterTabFolder.java
new file mode 100644
index 0000000..94e9706
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/ParameterTabFolder.java
@@ -0,0 +1,36 @@
+/*
+ * Created on Mar 26, 2015
+ * Created by Paul Gardner
+ * 
+ * Copyright 2015 Azureus Software, 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 org.gudy.azureus2.plugins.ui.config;
+
+public interface 
+ParameterTabFolder
+	extends Parameter
+{
+	public void
+	addTab(
+		ParameterGroup		group );
+	
+	public void
+	removeTab(
+		ParameterGroup		group );
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/PasswordParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/PasswordParameter.java
index d70c437..ba68294 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/PasswordParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/PasswordParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/PluginConfigUIFactory.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/PluginConfigUIFactory.java
index cd6b228..e14f985 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/PluginConfigUIFactory.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/PluginConfigUIFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/StringListParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/StringListParameter.java
index b51230f..37133d3 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/StringListParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/StringListParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/StringParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/StringParameter.java
index f2e47b4..7d79b24 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/StringParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/StringParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/UIParameter.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/UIParameter.java
index 1416da5..4a469dc 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/UIParameter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/UIParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.ui.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/config/UIParameterContext.java b/azureus2/src/org/gudy/azureus2/plugins/ui/config/UIParameterContext.java
index 9d12859..8df4818 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/config/UIParameterContext.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/config/UIParameterContext.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.ui.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuBuilder.java b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuBuilder.java
new file mode 100644
index 0000000..b24070f
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuBuilder.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.ui.menus;
+
+/**
+ * @author TuxPaper
+ * @created Jan 19, 2015
+ *
+ */
+public interface MenuBuilder
+{
+	public void buildSubmenu(MenuItem parent, Object target);
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuContext.java b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuContext.java
index 1f4897e..da56d34 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuContext.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuContext.java
@@ -1,7 +1,7 @@
 /*
  * Created on 4 Jun 2008
  * Created by Allan Crooks
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItem.java b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItem.java
index e411462..e9e35f6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItem.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -143,6 +140,14 @@ public interface MenuItem
 	public void	addFillListener(MenuItemFillListener listener);
 	
 	public void	removeFillListener(MenuItemFillListener	listener);
+
+	/**
+	 * For {@link #STYLE_MENU}, builder is called when user wants to see the
+	 * submenu items.  Setting a builder will force clear all submenu items.
+	 * 
+	 * @since 5.5.0.1
+	 */
+	public void setSubmenuBuilder(MenuBuilder builder);
 	
    	/**
    	 * Adds a selection listener for this menu item.
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItemFillListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItemFillListener.java
index 46c78cd..ab7ea5e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItemFillListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItemFillListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,25 +14,22 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
 package org.gudy.azureus2.plugins.ui.menus;
 
-public interface 
-MenuItemFillListener 
+import org.gudy.azureus2.plugins.download.Download;
+
+public interface MenuItemFillListener
 {
-		/**
-		 * This is fired before a menu is shown  
-		 * @param data For table context menu items this will be TableRow[]
-		 * of selected rows
-		 */
-	
-	public void
-	menuWillBeShown(
-		MenuItem	menu,
-		Object		data );
+	/**
+	 * This is fired before a menu is shown  
+	 * 
+	 * @param data 
+	 * For table context menu items this will be TableRow[] of selected rows <BR>
+	 * For {@link MenuManager#MENU_DOWNLOAD_CONTEXT} this will be an array of {@link Download} <BR>
+	 */
+
+	public void menuWillBeShown(MenuItem menu, Object data);
 }
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItemListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItemListener.java
index 9a7e624..177572a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItemListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuItemListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,14 +14,13 @@
  * 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.plugins.ui.menus;
 
+import org.gudy.azureus2.plugins.download.Download;
+
 /** A listener that is triggered when the user selects a menu item
  *
  * @author parg (Original ContextMenuItemListener)
@@ -44,6 +43,9 @@ MenuItemListener
    * @param target What this menu item applies to.  For the default
    *               implementation, target is null.  Implementing classes
    *               may provide an object related to the menu selection.
+   *               <P>
+	 * For table context menu items this will be TableRow[] of selected rows <BR>
+	 * For {@link MenuManager#MENU_DOWNLOAD_CONTEXT} this will be an array of {@link Download} <BR>
    */
 	public void
 	selected(
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuManager.java b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuManager.java
index 90e9f8e..b68eef0 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/menus/MenuManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25 January 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,16 +14,19 @@
  * 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.plugins.ui.menus;
 
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.UIManager;
+
 /**
  * Helper class to allow plugins to register their own menus. If you want to
  * add menus to be available in tables, you should use the <tt>TableManager</tt>
  * class. 
+ * <P>
+ * To get an instance of MenuManager, use {@link UIManager#getMenuManager()}
  *
  * @author amc1
  * @see org.gudy.azureus2.plugins.local.ui.tables.TableManager TableManager
@@ -70,15 +73,37 @@ public interface MenuManager {
 	public static final String MENU_TORRENT_MENU = "torrentmenu";
 	
 	/**
-	 * All menus which are Download specific, such as download bars, the Torrent
-	 * menu, torrent tables etc.
+	 * All menus which are {@link Download} specific, such as download bars, the
+	 * Torrent menu, torrent tables etc.
+	 * <P>
+	 * data or target parameter in listener triggers will be an array of 
+	 * {@link Download}
 	 * 
 	 * @since 3.0.2
 	 */
 	public static final String MENU_DOWNLOAD_CONTEXT = "download_context";
-	
+
+	/**
+	 * All menus which are {@link DiskManagerFileInfo} specific, such as the
+	 * Files tab in Torrent Details view, or the file row within the library view
+	 * <P>
+	 * data or target parameter in listener triggers will be an array of 
+	 * {@link DiskManagerFileInfo}
+	 * 
+	 * @since 5.6
+	 */
+	public static final String MENU_FILE_CONTEXT = "file_context";
+
+
+	/**
+	 * @since 5.6
+	 */
+	public static final String MENU_TAG_CONTEXT = "tag_content";
+
 	/**
 	 * Creates a menu item for the appropriate menu.
+	 * <P>
+	 * On plugin unload, use {@link MenuItem#remove()} or {@link MenuItem#removeAllChildItems()} 
 	 * 
 	 * @param menuID The <tt>MENU_</tt> identifier as defined above. 
 	 * @param resource_key ID of the menu, which is also used to retrieve the
@@ -91,6 +116,12 @@ public interface MenuManager {
      * Creates a menu item in a particular context. {@link MenuContext}
      * instances can be retrieved from some plugin objects that support 
      * menu items to be added to it.
+     * <P>
+     * Example: When adding menus to {@link UISWTStatusEntry}, call
+     * {@link UISWTStatusEntry#getMenuContext()} to get the MenuContext, and
+     * then pass it into this function.
+	 * <P>
+	 * On plugin unload, use {@link MenuItem#remove()} or {@link MenuItem#removeAllChildItems()} 
      * 
      * @param context The menu context object which represents the place to
      *                add a menu item.
@@ -103,6 +134,8 @@ public interface MenuManager {
     
     /**
      * Creates a menu item as a sub-item of the given menu item.
+	 * <P>
+	 * On plugin unload, use {@link MenuItem#remove()} or {@link MenuItem#removeAllChildItems()} 
      * 
      * @param parent The MenuItem to add this new item to. The parent MenuItem
      *               must have its style attribute to be set to "menu".
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/model/BasicPluginConfigModel.java b/azureus2/src/org/gudy/azureus2/plugins/ui/model/BasicPluginConfigModel.java
index 6adb145..1f64473 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/model/BasicPluginConfigModel.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/model/BasicPluginConfigModel.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,16 +14,13 @@
  * 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.plugins.ui.model;
 
+import org.gudy.azureus2.plugins.ui.components.UITextArea;
 import org.gudy.azureus2.plugins.ui.config.*;
-import org.gudy.azureus2.plugins.ui.config.FileParameter;
 
 /**
  * This object represents a configuration section.
@@ -288,6 +285,10 @@ BasicPluginConfigModel
 	 */
 	public UIParameter addUIParameter2(UIParameterContext context, String name);
 	
+	public UITextArea
+	addTextArea(
+		String	resource_name );
+	
 	/**
 	 * 
 	 * @param resource_name
@@ -301,6 +302,15 @@ BasicPluginConfigModel
 		Parameter[]	parameters );
 
 	/**
+	 * @since 5601
+	 * @param resource_name
+	 * @return
+	 */
+	
+	public ParameterTabFolder
+	createTabFolder();
+	
+	/**
 	 * 
 	 * @return
 	 * @since 2.3.0.5
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/model/BasicPluginViewModel.java b/azureus2/src/org/gudy/azureus2/plugins/ui/model/BasicPluginViewModel.java
index 13601e5..7a2c0c4 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/model/BasicPluginViewModel.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/model/BasicPluginViewModel.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/model/PluginConfigModel.java b/azureus2/src/org/gudy/azureus2/plugins/ui/model/PluginConfigModel.java
index 82b5ce0..5f5e561 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/model/PluginConfigModel.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/model/PluginConfigModel.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/model/PluginViewModel.java b/azureus2/src/org/gudy/azureus2/plugins/ui/model/PluginViewModel.java
index 588898a..4473a1f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/model/PluginViewModel.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/model/PluginViewModel.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCell.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCell.java
index a722b22..7d7d478 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCell.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCell.java
@@ -8,7 +8,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellAddedListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellAddedListener.java
index 76913c7..e4f9c5e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellAddedListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellAddedListener.java
@@ -5,7 +5,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellClipboardListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellClipboardListener.java
index 967e69d..6550bfa 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellClipboardListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellClipboardListener.java
@@ -5,7 +5,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellDisposeListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellDisposeListener.java
index 8e7f390..fcf251a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellDisposeListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellDisposeListener.java
@@ -5,7 +5,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellInplaceEditorListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellInplaceEditorListener.java
index 2bbf367..e228e8b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellInplaceEditorListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellInplaceEditorListener.java
@@ -3,7 +3,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellLightRefreshListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellLightRefreshListener.java
index 24c8c96..e5e6483 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellLightRefreshListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellLightRefreshListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.plugins.ui.tables;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseEvent.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseEvent.java
index 2fbe961..018ee45 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseEvent.java
@@ -3,7 +3,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseListener.java
index 456c2b9..993ef1b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseListener.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.plugins.ui.tables;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseMoveListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseMoveListener.java
index 826cb80..1205d6e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseMoveListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellMouseMoveListener.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.plugins.ui.tables;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellRefreshListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellRefreshListener.java
index b4543d7..a1d2580 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellRefreshListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellRefreshListener.java
@@ -5,7 +5,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellRefresher.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellRefresher.java
index cb670c7..51f5e4c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellRefresher.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellRefresher.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.ui.tables;
 
 import java.util.HashMap;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellToolTipListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellToolTipListener.java
index b5e72ae..2c51331 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellToolTipListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellToolTipListener.java
@@ -5,7 +5,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellVisibilityListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellVisibilityListener.java
index e2333f7..7cfdf00 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellVisibilityListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableCellVisibilityListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.plugins.ui.tables;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumn.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumn.java
index 89ddbec..892fe64 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumn.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumn.java
@@ -3,7 +3,8 @@
  *
  * 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.
+ * 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
@@ -419,6 +420,9 @@ public interface TableColumn {
    */
   public Object getUserData(String key);
   
+
+  public String getUserDataString(String key);
+
   /**
    * Sets the visibility of the column
    * 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnCreationListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnCreationListener.java
index 7381421..595f0da 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnCreationListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnCreationListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 19, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnExtraInfoListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnExtraInfoListener.java
index 4a7f3bf..1763cfa 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnExtraInfoListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnExtraInfoListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 10, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnInfo.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnInfo.java
index 98b0366..76d217c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnInfo.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableColumnInfo.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 10, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableContextMenuItem.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableContextMenuItem.java
index b60c270..8a6fff6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableContextMenuItem.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableContextMenuItem.java
@@ -4,7 +4,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableManager.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableManager.java
index 30152dd..75c4794 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableManager.java
@@ -17,6 +17,7 @@ package org.gudy.azureus2.plugins.ui.tables;
 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.menus.MenuManager;
 
 /** Allows plugins to manage Azureus UI tables.
  *
@@ -62,6 +63,7 @@ public interface TableManager
   public static final String TABLE_ALL_PEERS             = "AllPeers";
 
   /** Creates a column for a UI table.
+   * <p>
    * In order for this object to be displayed in an Azureus UI table, the
    * returned object must be added via the {@link #addColumn(TableColumn)}
    * <p>
@@ -75,7 +77,7 @@ public interface TableManager
    * plus ".column." plus the logical name of your column. 
    * <p>
    * For example, if you are creating a column named "quality" in the table 
-   * TABLE_TORRENT_FILES, youwould have to add the following to your language 
+   * TABLE_TORRENT_FILES, you would have to add the following to your language 
    * file:<br>
    *    <code>Files.column.quality=<i>Column Title</i></code><br>
    * and if you wish to have a short description of the column (visible when
@@ -83,6 +85,10 @@ public interface TableManager
    * plus ".info".  For the example above:<br>
    *    <code>Files.column.quality.info=<i>One line description</i></code>
    *
+   * <p>
+   * <br>
+   * If you wish to add a menu item to tables that show torrents, use 
+   * {@link MenuManager#addMenuItem(String, String)}
    *
    * @param tableID Which table the column will be visible in. See {@link TableManager}.
    * @param cellID The logical name of the column.
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRow.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRow.java
index 5276957..fdf4777 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRow.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRow.java
@@ -6,7 +6,8 @@
  *
  * 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.
+ * 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
@@ -51,6 +52,9 @@ public interface TableRow {
    */
   String getTableID();
 
+  public int
+  getIndex();
+  
   /**
    * Change the row's foreground color.
   *
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowMouseEvent.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowMouseEvent.java
index 354ebdf..0540b54 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowMouseEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowMouseEvent.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.plugins.ui.tables;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowMouseListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowMouseListener.java
index 7705634..6cddcaa 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowMouseListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowMouseListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.plugins.ui.tables;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowRefreshListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowRefreshListener.java
index 31120d7..1acd89d 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowRefreshListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/tables/TableRowRefreshListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Oct 6, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarActivationListener.java b/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarActivationListener.java
index 08f8be5..2b92266 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarActivationListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarActivationListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.ui.toolbar;
 
 import com.aelitis.azureus.ui.common.ToolBarItem;
@@ -5,8 +23,12 @@ import com.aelitis.azureus.ui.common.ToolBarItem;
 public interface UIToolBarActivationListener
 {
 	public final static long ACTIVATIONTYPE_NORMAL = 0x0;
+
 	public final static long ACTIVATIONTYPE_HELD = 0x1;
+
 	public final static long ACTIVATIONTYPE_RIGHTCLICK = 0x2;
 
-  public boolean toolBarItemActivated(ToolBarItem item, long activationType, Object datasource);
+	/** XXX Should have been UIToolBarItem */
+	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
+			Object datasource);
 }
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarEnablerBase.java b/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarEnablerBase.java
index 41b65a6..a8edfb6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarEnablerBase.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarEnablerBase.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.ui.toolbar;
 
 /**
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarItem.java b/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarItem.java
index d32cbb8..8cc88ea 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarItem.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarItem.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.ui.toolbar;
 
 public interface UIToolBarItem
@@ -57,4 +75,32 @@ public interface UIToolBarItem
 
 	public void setDefaultActivationListener(
 			UIToolBarActivationListener defaultActivation);
+	
+	/**
+	 * @return Group that item belongs to
+	 *
+	 * @since 5.0.0.1
+	 */
+	public String getGroupID();
+
+	/**
+	 * @param groupID
+	 *
+	 * @since 5.0.0.1
+	 */
+	public void setGroupID(String groupID);
+
+	/**
+	 * @param string
+	 *
+	 * @since 5.0.0.1
+	 */
+	public void setToolTip(String text);
+
+	/**
+	 * @return
+	 *
+	 * @since 5.0.0.1
+	 */
+	String getToolTip();
 }
diff --git a/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarManager.java b/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarManager.java
index c0203a1..9c7b9a8 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/ui/toolbar/UIToolBarManager.java
@@ -1,8 +1,27 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.ui.toolbar;
 
 public interface UIToolBarManager
 {
 	public final static String GROUP_BIG = "big";
+
 	public final static String GROUP_MAIN = "main";
 
 	/**
@@ -14,7 +33,7 @@ public interface UIToolBarManager
 	 * @return newly created toolbar
 	 */
 	public UIToolBarItem createToolBarItem(String id);
-	
+
 	/**
 	 * Adds a {@link UIToolBarItem} to the UI.  Make sure you at least set the
 	 * icon before adding
@@ -24,6 +43,10 @@ public interface UIToolBarManager
 	public void addToolBarItem(UIToolBarItem item);
 
 	public UIToolBarItem getToolBarItem(String id);
+
 	public UIToolBarItem[] getAllToolBarItems();
+
 	public void removeToolBarItem(String id);
+	
+	
 }
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdatableComponent.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdatableComponent.java
index c191106..61d26d9 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdatableComponent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdatableComponent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/Update.java b/azureus2/src/org/gudy/azureus2/plugins/update/Update.java
index 4ebc3b9..0772f36 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/Update.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/Update.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -70,6 +67,9 @@ Update
 	getDesciptionURL();
 
 	public String
+	getOldVersion();
+	
+	public String
 	getNewVersion();
 	
 	public ResourceDownloader[]
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckInstance.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckInstance.java
index dbc6faa..2abe6df 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckInstance.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckInstance.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckInstanceListener.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckInstanceListener.java
index 01e7905..89dffbe 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckInstanceListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckInstanceListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateChecker.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateChecker.java
index f10f7cf..5fd495c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateChecker.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateChecker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -48,6 +45,7 @@ UpdateChecker
 	addUpdate(
 		String				name,
 		String[]			description,
+		String				old_version,
 		String				new_version,
 		ResourceDownloader	downloader,
 		int					restart_required );
@@ -60,6 +58,7 @@ UpdateChecker
 	addUpdate(
 		String					name,
 		String[]				description,
+		String					old_version,
 		String					new_version,
 		ResourceDownloader[]	downloaders,
 		int						restart_required );
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckerListener.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckerListener.java
index c5ed8a2..3796961 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateCheckerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateException.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateException.java
index b411932..89bad28 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateInstaller.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateInstaller.java
index dc89222..39dfd78 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateInstaller.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateInstaller.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateInstallerListener.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateInstallerListener.java
index 0f5a9ad..517d9e3 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateInstallerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateInstallerListener.java
@@ -1,37 +1,36 @@
-/*
- * Created on Jan 8, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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.update;
-
-public interface 
-UpdateInstallerListener 
-{
-	public void
-	reportProgress(
-		String		str );
-	
-	public void
-	complete();
-	
-	public void
-	failed(
-		UpdateException	exception );
-}
+/*
+ * Created on Jan 8, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.update;
+
+public interface 
+UpdateInstallerListener 
+{
+	public void
+	reportProgress(
+		String		str );
+	
+	public void
+	complete();
+	
+	public void
+	failed(
+		UpdateException	exception );
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateListener.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateListener.java
index 02c8bf4..a11f51e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManager.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManager.java
index a8fd910..1d688b9 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerDecisionListener.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerDecisionListener.java
index 2b52884..5191f11 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerDecisionListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerDecisionListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Aug-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerListener.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerListener.java
index 498bb3e..cee8c72 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerVerificationListener.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerVerificationListener.java
index 58851f2..14d34be 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerVerificationListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateManagerVerificationListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11 May 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateProgressListener.java b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateProgressListener.java
index a0038f3..276f8cc 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/update/UpdateProgressListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/update/UpdateProgressListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 01-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedDispatcher.java b/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedDispatcher.java
index d787de2..356c6c2 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedDispatcher.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedDispatcher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedList.java b/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedList.java
index de1889c..73c0a27 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedList.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedList.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedListAcceptor.java b/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedListAcceptor.java
index 4cb0a7a..34abae9 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedListAcceptor.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/AggregatedListAcceptor.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/ByteArrayWrapper.java b/azureus2/src/org/gudy/azureus2/plugins/utils/ByteArrayWrapper.java
index a7e5a67..b1741d4 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/ByteArrayWrapper.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/ByteArrayWrapper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/DelayedTask.java b/azureus2/src/org/gudy/azureus2/plugins/utils/DelayedTask.java
index 21fbf80..412c562 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/DelayedTask.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/DelayedTask.java
@@ -1,39 +1,38 @@
-/*
- * Created on Apr 24, 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;
-
-public interface 
-DelayedTask 
-{
-		/**
-		 * Queue the task for execution. The task MUST have been set prior to this. If successful
-		 * this will result in the runnable target being invoked when all prior delayed tasks
-		 * have completed
-		 */
-	
-	public void
-	queue();
-
-	public void 
-	queueFirst();
-	
-}
+/*
+ * Created on Apr 24, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils;
+
+public interface 
+DelayedTask 
+{
+		/**
+		 * Queue the task for execution. The task MUST have been set prior to this. If successful
+		 * this will result in the runnable target being invoked when all prior delayed tasks
+		 * have completed
+		 */
+	
+	public void
+	queue();
+
+	public void 
+	queueFirst();
+	
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/FeatureManager.java b/azureus2/src/org/gudy/azureus2/plugins/utils/FeatureManager.java
index db9b026..d26a287 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/FeatureManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/FeatureManager.java
@@ -1,234 +1,233 @@
-/*
- * Created on Feb 4, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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;
-
-import org.gudy.azureus2.plugins.PluginException;
-
-
-public interface 
-FeatureManager 
-{
-	public Licence[]
-	getLicences();
-	
-	public Licence[]
-	createLicences(
-		String[]				feature_ids )
-	
-		throws PluginException;
-	
-	public Licence
-	addLicence(
-		String		licence_key )
-	
-		throws PluginException;
-	
-	public FeatureDetails[]
-	getFeatureDetails(
-		String					feature_id );
-	
-		// feature present and not expired
-	
-	public boolean
-	isFeatureInstalled(
-		String					feature_id );
-	
-	public void
-	refreshLicences();
-	
-	public void
-	registerFeatureEnabler(
-		FeatureEnabler	enabler );
-	
-	public void
-	unregisterFeatureEnabler(
-		FeatureEnabler	enabler );
-	
-	public void
-	addListener(
-		FeatureManagerListener		listener );
-	
-	public void
-	removeListener(
-		FeatureManagerListener		listener );
-
-	
-	public interface
-	Licence
-	{
-		public final int LS_PENDING_AUTHENTICATION	= 1;
-		public final int LS_AUTHENTICATED			= 2;
-		public final int LS_INVALID_KEY				= 3;
-		public final int LS_CANCELLED				= 4;
-		public final int LS_REVOKED					= 5;
-		public final int LS_ACTIVATION_DENIED		= 6;
-		
-		public int
-		getState();
-		
-		public String
-		getKey();
-		
-		public String
-		getShortID();
-		
-		public FeatureDetails[]
-		getFeatures();
-		
-		public boolean
-		isFullyInstalled();
-		
-		public void
-		retryInstallation();
-		
-		public void
-		addInstallationListener(
-			LicenceInstallationListener	listener );
-		
-		public void
-		removeInstallationListener(
-			LicenceInstallationListener	listener );
-		
-		public void
-		remove();
-		
-		public interface
-		LicenceInstallationListener
-		{
-			public void
-			start(
-				String		licence_key );
-			
-			public void
-			reportActivity(
-				String		licence_key,
-				String		install,
-				String		activity );
-			
-			public void
-			reportProgress(
-				String		licence_key,
-				String		install,
-				int			percent );
-			
-			public void
-			complete(
-				String		licence_key );
-			
-			public void
-			failed(
-				String				licence_key,
-				PluginException		error );
-		}
-	}
-	
-	public interface
-	FeatureEnabler
-	{
-		public Licence[]
-       	getLicences();
-		
-		public Licence[]
-		createLicences(
-			String[]				feature_ids )
-		
-			throws PluginException;
-		
-       	public Licence
-       	addLicence(
-       		String		licence_key );
-       	
-       	public void
-       	refreshLicences();
-       	
-    	public void
-    	addListener(
-    		FeatureManagerListener		listener );
-    	
-    	public void
-    	removeListener(
-    		FeatureManagerListener		listener );
-	}
-	
-	public interface
-	FeatureDetails
-	{
-		public String	PR_PUBLIC_KEY				= "PublicKey";				// String
-		public String	PR_VALID_UNTIL				= "ValidUntil";				// Long
-		public String	PR_OFFLINE_VALID_UNTIL		= "OfflineValidUntil";		// Long
-		public String	PR_IS_INSTALL_TIME			= "IsInstallTime";			// Long (0=false)
-		public String	PR_IS_TRIAL					= "IsTrial";				// Long (0=false)
-		public String	PR_TRIAL_USES_LIMIT			= "TrialUsesLimit";			// Long
-		public String	PR_TRIAL_USES_FAIL_COUNT	= "TrialUsesFailCount";		// Long
-		public String	PR_TRIAL_USES_REMAINING		= "TrialUsesRemaining";		// Long
-		public String	PR_REQUIRED_PLUGINS			= "Plugins";				// String: comma separated plugin ids
-		public String	PR_FINGERPRINT				= "Fingerprint";			// String
-		public String	PR_RENEWAL_KEY				= "RenewalKey";				// String
-		
-		public Licence
-		getLicence();
-		
-		public String
-		getID();
-		
-			/**
-			 * Returns true if offline expired or overall expired. 
-			 * NOT to be used by verified plugins, they must do the check explicitly using the
-			 * signed properties
-			 * @return
-			 */
-		
-		public boolean
-		hasExpired();
-		
-		public byte[]
-		getEncodedProperties();
-		
-		public byte[]
-		getSignature();
-		
-		public Object
-		getProperty(
-			String		propery_name );
-		
-		public void
-		setProperty(
-			String		property_name,
-			Object		property_value );
-	}
-	
-	public interface
-	FeatureManagerListener
-	{
-		public void
-		licenceAdded(
-			Licence	licence );
-		
-		public void
-		licenceChanged(
-			Licence	licence );
-		
-		public void
-		licenceRemoved(
-			Licence	licence );
-	}
-}
+/*
+ * Created on Feb 4, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils;
+
+import org.gudy.azureus2.plugins.PluginException;
+
+
+public interface 
+FeatureManager 
+{
+	public Licence[]
+	getLicences();
+	
+	public Licence[]
+	createLicences(
+		String[]				feature_ids )
+	
+		throws PluginException;
+	
+	public Licence
+	addLicence(
+		String		licence_key )
+	
+		throws PluginException;
+	
+	public FeatureDetails[]
+	getFeatureDetails(
+		String					feature_id );
+	
+		// feature present and not expired
+	
+	public boolean
+	isFeatureInstalled(
+		String					feature_id );
+	
+	public void
+	refreshLicences();
+	
+	public void
+	registerFeatureEnabler(
+		FeatureEnabler	enabler );
+	
+	public void
+	unregisterFeatureEnabler(
+		FeatureEnabler	enabler );
+	
+	public void
+	addListener(
+		FeatureManagerListener		listener );
+	
+	public void
+	removeListener(
+		FeatureManagerListener		listener );
+
+	
+	public interface
+	Licence
+	{
+		public final int LS_PENDING_AUTHENTICATION	= 1;
+		public final int LS_AUTHENTICATED			= 2;
+		public final int LS_INVALID_KEY				= 3;
+		public final int LS_CANCELLED				= 4;
+		public final int LS_REVOKED					= 5;
+		public final int LS_ACTIVATION_DENIED		= 6;
+		
+		public int
+		getState();
+		
+		public String
+		getKey();
+		
+		public String
+		getShortID();
+		
+		public FeatureDetails[]
+		getFeatures();
+		
+		public boolean
+		isFullyInstalled();
+		
+		public void
+		retryInstallation();
+		
+		public void
+		addInstallationListener(
+			LicenceInstallationListener	listener );
+		
+		public void
+		removeInstallationListener(
+			LicenceInstallationListener	listener );
+		
+		public void
+		remove();
+		
+		public interface
+		LicenceInstallationListener
+		{
+			public void
+			start(
+				String		licence_key );
+			
+			public void
+			reportActivity(
+				String		licence_key,
+				String		install,
+				String		activity );
+			
+			public void
+			reportProgress(
+				String		licence_key,
+				String		install,
+				int			percent );
+			
+			public void
+			complete(
+				String		licence_key );
+			
+			public void
+			failed(
+				String				licence_key,
+				PluginException		error );
+		}
+	}
+	
+	public interface
+	FeatureEnabler
+	{
+		public Licence[]
+       	getLicences();
+		
+		public Licence[]
+		createLicences(
+			String[]				feature_ids )
+		
+			throws PluginException;
+		
+       	public Licence
+       	addLicence(
+       		String		licence_key );
+       	
+       	public void
+       	refreshLicences();
+       	
+    	public void
+    	addListener(
+    		FeatureManagerListener		listener );
+    	
+    	public void
+    	removeListener(
+    		FeatureManagerListener		listener );
+	}
+	
+	public interface
+	FeatureDetails
+	{
+		public String	PR_PUBLIC_KEY				= "PublicKey";				// String
+		public String	PR_VALID_UNTIL				= "ValidUntil";				// Long
+		public String	PR_OFFLINE_VALID_UNTIL		= "OfflineValidUntil";		// Long
+		public String	PR_IS_INSTALL_TIME			= "IsInstallTime";			// Long (0=false)
+		public String	PR_IS_TRIAL					= "IsTrial";				// Long (0=false)
+		public String	PR_TRIAL_USES_LIMIT			= "TrialUsesLimit";			// Long
+		public String	PR_TRIAL_USES_FAIL_COUNT	= "TrialUsesFailCount";		// Long
+		public String	PR_TRIAL_USES_REMAINING		= "TrialUsesRemaining";		// Long
+		public String	PR_REQUIRED_PLUGINS			= "Plugins";				// String: comma separated plugin ids
+		public String	PR_FINGERPRINT				= "Fingerprint";			// String
+		public String	PR_RENEWAL_KEY				= "RenewalKey";				// String
+		
+		public Licence
+		getLicence();
+		
+		public String
+		getID();
+		
+			/**
+			 * Returns true if offline expired or overall expired. 
+			 * NOT to be used by verified plugins, they must do the check explicitly using the
+			 * signed properties
+			 * @return
+			 */
+		
+		public boolean
+		hasExpired();
+		
+		public byte[]
+		getEncodedProperties();
+		
+		public byte[]
+		getSignature();
+		
+		public Object
+		getProperty(
+			String		propery_name );
+		
+		public void
+		setProperty(
+			String		property_name,
+			Object		property_value );
+	}
+	
+	public interface
+	FeatureManagerListener
+	{
+		public void
+		licenceAdded(
+			Licence	licence );
+		
+		public void
+		licenceChanged(
+			Licence	licence );
+		
+		public void
+		licenceRemoved(
+			Licence	licence );
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/Formatters.java b/azureus2/src/org/gudy/azureus2/plugins/utils/Formatters.java
index c7eb2b6..f49cae9 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/Formatters.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/Formatters.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleDecoder.java b/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleDecoder.java
index 1ae3287..07535fb 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleDecoder.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleDecoder.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleListener.java b/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleListener.java
index fd1020e..14831a7 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleUtilities.java b/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleUtilities.java
index 9ad38eb..ca1cfcb 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleUtilities.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/LocaleUtilities.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/LocationProvider.java b/azureus2/src/org/gudy/azureus2/plugins/utils/LocationProvider.java
index a4d2fd4..2d28fc1 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/LocationProvider.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/LocationProvider.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/LocationProviderListener.java b/azureus2/src/org/gudy/azureus2/plugins/utils/LocationProviderListener.java
index 0538257..75752a4 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/LocationProviderListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/LocationProviderListener.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/Monitor.java b/azureus2/src/org/gudy/azureus2/plugins/utils/Monitor.java
index 7d89122..161395b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/Monitor.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/Monitor.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 20, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/PooledByteBuffer.java b/azureus2/src/org/gudy/azureus2/plugins/utils/PooledByteBuffer.java
index 693f1ed..ac41335 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/PooledByteBuffer.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/PooledByteBuffer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/PowerManagementListener.java b/azureus2/src/org/gudy/azureus2/plugins/utils/PowerManagementListener.java
index 9e57e9d..e45602f 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/PowerManagementListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/PowerManagementListener.java
@@ -2,20 +2,19 @@
  * Created on Oct 10, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/Semaphore.java b/azureus2/src/org/gudy/azureus2/plugins/utils/Semaphore.java
index 3b75025..f050ecf 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/Semaphore.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/Semaphore.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/ShortCuts.java b/azureus2/src/org/gudy/azureus2/plugins/utils/ShortCuts.java
index 6713da0..6f08bde 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/ShortCuts.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/ShortCuts.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/StaticUtilities.java b/azureus2/src/org/gudy/azureus2/plugins/utils/StaticUtilities.java
index 69c3064..62d35c1 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/StaticUtilities.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/StaticUtilities.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 15, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,13 @@
  * 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.plugins.utils;
 
 import java.io.InputStream;
+import java.net.URL;
 
 import org.gudy.azureus2.core3.util.AESemaphore;
 import org.gudy.azureus2.core3.util.Debug;
@@ -74,11 +72,12 @@ public class StaticUtilities {
   
   public static RSSFeed
   getRSSFeed(
+	URL				source_url,
 	InputStream		is )
   
   	throws SimpleXMLParserDocumentException
   {
-	  return( PluginInitializer.getDefaultInterface().getUtilities().getRSSFeed( is ));
+	  return( PluginInitializer.getDefaultInterface().getUtilities().getRSSFeed( source_url, is ));
   }
   	/**
   	 * See UIInstance.promptUser
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimer.java b/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimer.java
index 9db1ff3..878f7b7 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimer.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimerEvent.java b/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimerEvent.java
index 1be57f6..14a5821 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimerEvent.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimerEvent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimerEventPerformer.java b/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimerEventPerformer.java
index 76b81ba..495ca6a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimerEventPerformer.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/UTTimerEventPerformer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/Utilities.java b/azureus2/src/org/gudy/azureus2/plugins/utils/Utilities.java
index a94ccbf..86afec2 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/Utilities.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/Utilities.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -36,6 +37,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.gudy.azureus2.plugins.PluginException;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabase;
 import org.gudy.azureus2.plugins.utils.resourcedownloader.*;
 import org.gudy.azureus2.plugins.utils.resourceuploader.ResourceUploaderFactory;
 import org.gudy.azureus2.plugins.utils.search.SearchException;
@@ -206,8 +208,22 @@ Utilities
 	public SimpleXMLParserDocumentFactory
 	getSimpleXMLParserDocumentFactory();
 	
+	/**
+	 * @deprecated
+	 * @param is
+	 * @return
+	 * @throws SimpleXMLParserDocumentException
+	 */
+	
+	public RSSFeed
+	getRSSFeed(
+		InputStream		is )
+	
+		throws SimpleXMLParserDocumentException;
+	
 	public RSSFeed
 	getRSSFeed(
+		URL				source_url,
 		InputStream		is )
 	
 		throws SimpleXMLParserDocumentException;
@@ -218,11 +234,26 @@ Utilities
 	
 		throws ResourceDownloaderException, SimpleXMLParserDocumentException;
 	
+	/**
+	 * @deprecated
+	 * @param feed_location
+	 * @return
+	 * @throws ResourceDownloaderException
+	 * @throws SimpleXMLParserDocumentException
+	 */
+	
 	public RSSFeed
 	getRSSFeed(
 		ResourceDownloader	feed_location )
 	
 		throws ResourceDownloaderException, SimpleXMLParserDocumentException;
+
+	public RSSFeed
+	getRSSFeed(
+		URL					source_url,
+		ResourceDownloader	feed_location )
+	
+		throws ResourceDownloaderException, SimpleXMLParserDocumentException;
 	
 		/**
 		 * Returns a public IP address of the machine or null if it can't be determined
@@ -277,6 +308,10 @@ Utilities
 		long					idle_dispatch_time,
 		long					max_queue_size );
  	
+	/**
+	 * 
+ 	 * @return Map read from config file, or empty HashMap if error
+	 */
  	public Map
  	readResilientBEncodedFile(
  		File	parent_dir,
@@ -414,6 +449,9 @@ Utilities
 	unregisterJSONRPCClient(
 		JSONClient		client );
 
+	public List<DistributedDatabase>
+	getDistributedDatabases(
+		String[]		networks );	 
 	
 	public interface
 	JSONServer
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloader.java b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloader.java
index e8d27d5..5b0572a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloader.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloader.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderAdapter.java b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderAdapter.java
index e08c79a..69559a8 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderCancelledException.java b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderCancelledException.java
index 0e3b94a..9eb5361 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderCancelledException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderCancelledException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21 Apr 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins.utils.resourcedownloader;
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderDelayedFactory.java b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderDelayedFactory.java
index b024569..bb871b8 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderDelayedFactory.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderDelayedFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderException.java b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderException.java
index 9b1e1ed..cf4aff6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -32,6 +29,20 @@ ResourceDownloaderException
 {
 	public
 	ResourceDownloaderException(
+		String				str )
+	{
+		super( str);
+	}
+	
+	public
+	ResourceDownloaderException(
+		Throwable				cause )
+	{
+		super( cause);
+	}
+	
+	public
+	ResourceDownloaderException(
 		ResourceDownloader	rd,
 		String				str )
 	{
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderFactory.java b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderFactory.java
index 5ebe6c1..c310b41 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderFactory.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderListener.java b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderListener.java
index f55585b..882f90c 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/resourcedownloader/ResourceDownloaderListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploader.java b/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploader.java
index 4ff5e0b..97baeac 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploader.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploader.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Oct-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploaderException.java b/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploaderException.java
index 1b7f91b..823cd28 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploaderException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploaderException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploaderFactory.java b/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploaderFactory.java
index 28966de..3c02221 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploaderFactory.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/resourceuploader/ResourceUploaderFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Oct-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/search/Search.java b/azureus2/src/org/gudy/azureus2/plugins/utils/search/Search.java
index ffd7d62..c619e49 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/search/Search.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/search/Search.java
@@ -1,32 +1,31 @@
-/*
- * Created on Jun 30, 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.search;
-
-public interface 
-Search 
-{
-	public SearchProviderResults[]
-	getResults();
-	
-	public boolean
-	isComplete();
-}
+/*
+ * Created on Jun 30, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.search;
+
+public interface 
+Search 
+{
+	public SearchProviderResults[]
+	getResults();
+	
+	public boolean
+	isComplete();
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchException.java b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchException.java
index 64a579c..4159d36 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchException.java
@@ -1,42 +1,41 @@
-/*
- * 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.search;
-
-public class 
-SearchException 
-	extends Exception
-{
-	public
-	SearchException(
-		String		str )
-	{
-		super( str );
-	}
-	
-	public
-	SearchException(
-		String		str,
-		Throwable 	e )
-	{
-		super( str, e );
-	}
-}
+/*
+ * Created on Jun 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.search;
+
+public class 
+SearchException 
+	extends Exception
+{
+	public
+	SearchException(
+		String		str )
+	{
+		super( str );
+	}
+	
+	public
+	SearchException(
+		String		str,
+		Throwable 	e )
+	{
+		super( str, e );
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchInitiator.java b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchInitiator.java
index 17aa504..49e6155 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchInitiator.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchInitiator.java
@@ -1,57 +1,56 @@
-/*
- * Created on Jun 30, 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.search;
-
-import java.util.Map;
-
-public interface 
-SearchInitiator 
-{
-	public static final String PR_SEARCH_TERM	= "search_term";	// search expression
-	public static final String PR_MATURE		= "mature";			// "true" or "false"
-	
-	public SearchProvider[]
-	getProviders();
-	
-	public Search
-	createSearch(
-		SearchProvider[]	providers,
-		Map<String,String>	properties,
-		SearchListener		listener )
-	
-		throws SearchException;
-	
-		/**
-		 * Convenience method for remote invocation
-		 * @param provider_ids
-		 * @param properties
-		 * @return
-		 * @throws SearchException
-		 */
-	
-	public Search
-	createSearch(
-		String				provider_ids,	// comma separated list
-		String				properties )	// name=value, comma separated
-	
-		throws SearchException;
-}
+/*
+ * Created on Jun 30, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.search;
+
+import java.util.Map;
+
+public interface 
+SearchInitiator 
+{
+	public static final String PR_SEARCH_TERM	= "search_term";	// search expression
+	public static final String PR_MATURE		= "mature";			// "true" or "false"
+	
+	public SearchProvider[]
+	getProviders();
+	
+	public Search
+	createSearch(
+		SearchProvider[]	providers,
+		Map<String,String>	properties,
+		SearchListener		listener )
+	
+		throws SearchException;
+	
+		/**
+		 * Convenience method for remote invocation
+		 * @param provider_ids
+		 * @param properties
+		 * @return
+		 * @throws SearchException
+		 */
+	
+	public Search
+	createSearch(
+		String				provider_ids,	// comma separated list
+		String				properties )	// name=value, comma separated
+	
+		throws SearchException;
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchInstance.java b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchInstance.java
index 192d62f..bbaf643 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchInstance.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchInstance.java
@@ -1,29 +1,28 @@
-/*
- * 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.search;
-
-public interface 
-SearchInstance 
-{
-	public void
-	cancel();
-}
+/*
+ * Created on Jun 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.search;
+
+public interface 
+SearchInstance 
+{
+	public void
+	cancel();
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchListener.java b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchListener.java
index a2b9c45..0c1d9db 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchListener.java
@@ -1,33 +1,32 @@
-/*
- * Created on Jun 30, 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.search;
-
-public interface 
-SearchListener 
-{
-	public void
-	receivedResults(
-		SearchProviderResults[]		results );
-	
-	public void
-	completed();
-}
+/*
+ * Created on Jun 30, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.search;
+
+public interface 
+SearchListener 
+{
+	public void
+	receivedResults(
+		SearchProviderResults[]		results );
+	
+	public void
+	completed();
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchObserver.java b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchObserver.java
index cd7801c..e8d3e27 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchObserver.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchObserver.java
@@ -1,43 +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.search;
-
-public interface 
-SearchObserver 
-{
-	public static final int PR_MAX_RESULTS_WANTED	= 1;	// Long
-	
-	public void
-	resultReceived(
-		SearchInstance		search,
-		SearchResult		result );
-	
-	public void
-	complete();
-	
-	public void
-	cancelled();
-	
-	public Object
-	getProperty(
-		int		property );
-}
+/*
+ * Created on Jun 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.search;
+
+public interface 
+SearchObserver 
+{
+	public static final int PR_MAX_RESULTS_WANTED	= 1;	// Long
+	
+	public void
+	resultReceived(
+		SearchInstance		search,
+		SearchResult		result );
+	
+	public void
+	complete();
+	
+	public void
+	cancelled();
+	
+	public Object
+	getProperty(
+		int		property );
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchProvider.java b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchProvider.java
index 161e211..8cd6349 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchProvider.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchProvider.java
@@ -1,59 +1,59 @@
-/*
- * 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.search;
-
-import java.util.Map;
-
-public interface 
-SearchProvider 
-{
-		// properties
-	
-	public static final int PR_ID							= 0;	// getProperty only; Long
-	public static final int PR_NAME							= 1;	// mandatory; String
-	public static final int PR_ICON_URL						= 2;	// optional; String
-	public static final int PR_DOWNLOAD_LINK_LOCATOR		= 3;	// optional; String
-	public static final int PR_REFERER						= 4;	// optional; String
-	public static final int PR_SUPPORTS_RESULT_FIELDS		= 5;	// optional; int[]
-	public static final int PR_USE_ACCURACY_FOR_RANK		= 6;	// optional; Boolean
-	
-		// search parameters
-	
-	public static final String	SP_SEARCH_TERM			 	= "s";	// String
-	public static final String	SP_MATURE				 	= "m";	// Boolean
-	
-	public SearchInstance
-	search(
-		Map<String,Object>	search_parameters,
-		SearchObserver		observer )
-	
-		throws SearchException;
-	
-	public Object
-	getProperty(
-		int			property );
-	
-	public void
-	setProperty(
-		int			property,
-		Object		value );
-}
+/*
+ * Created on Jun 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.search;
+
+import java.util.Map;
+
+public interface 
+SearchProvider 
+{
+		// properties
+	
+	public static final int PR_ID							= 0;	// getProperty only; Long
+	public static final int PR_NAME							= 1;	// mandatory; String
+	public static final int PR_ICON_URL						= 2;	// optional; String
+	public static final int PR_DOWNLOAD_LINK_LOCATOR		= 3;	// optional; String
+	public static final int PR_REFERER						= 4;	// optional; String
+	public static final int PR_SUPPORTS_RESULT_FIELDS		= 5;	// optional; int[]
+	public static final int PR_USE_ACCURACY_FOR_RANK		= 6;	// optional; Boolean
+	
+		// search parameters
+	
+	public static final String	SP_SEARCH_TERM			 	= "s";	// String
+	public static final String	SP_MATURE				 	= "m";	// Boolean
+	public static final String	SP_NETWORKS				 	= "n";	// String[]
+	
+	public SearchInstance
+	search(
+		Map<String,Object>	search_parameters,
+		SearchObserver		observer )
+	
+		throws SearchException;
+	
+	public Object
+	getProperty(
+		int			property );
+	
+	public void
+	setProperty(
+		int			property,
+		Object		value );
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchProviderResults.java b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchProviderResults.java
index 497185e..e9772c6 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchProviderResults.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchProviderResults.java
@@ -1,38 +1,37 @@
-/*
- * Created on Jun 30, 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.search;
-
-public interface 
-SearchProviderResults 
-{
-	public SearchProvider
-	getProvider();
-	
-	public SearchResult[]
-	getResults();
-	
-	public boolean
-	isComplete();
-	
-	public SearchException
-	getError();
-}
+/*
+ * Created on Jun 30, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.search;
+
+public interface 
+SearchProviderResults 
+{
+	public SearchProvider
+	getProvider();
+	
+	public SearchResult[]
+	getResults();
+	
+	public boolean
+	isComplete();
+	
+	public SearchException
+	getError();
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchResult.java b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchResult.java
index c866ebe..113cbf2 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchResult.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/search/SearchResult.java
@@ -1,58 +1,57 @@
-/*
- * 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.search;
-
-public interface 
-SearchResult 
-{
-	public static final int	PR_NAME					= 1;	// String
-	public static final int	PR_PUB_DATE				= 2;	// Date
-	public static final int	PR_SIZE					= 3;	// Long
-	public static final int	PR_LEECHER_COUNT		= 4;	// Long	(-1 unknown)
-	public static final int	PR_SEED_COUNT			= 5;	// Long	(-1 unknown)
-	public static final int	PR_SUPER_SEED_COUNT		= 6;	// Long	(-1 unknown)
-	public static final int	PR_CATEGORY				= 7;	// String
-	public static final int	PR_COMMENTS				= 8;	// Long	(-1 unknown)
-	public static final int	PR_VOTES				= 9;	// Long	(-1 unknown)
-	public static final int	PR_CONTENT_TYPE			= 10;	// String  ("video","audio","game")
-	public static final int	PR_DETAILS_LINK			= 11;	// URL as String
-	public static final int	PR_DOWNLOAD_LINK		= 12;	// URL as String
-	public static final int	PR_PLAY_LINK			= 13;	// URL as String
-	public static final int	PR_PRIVATE				= 14;	// Boolean
-	public static final int	PR_DRM_KEY				= 15;	// String
-	public static final int	PR_DOWNLOAD_BUTTON_LINK = 16;	// URL as String
-	public static final int	PR_RANK					= 17;	// Long value, 0->100 (-1 unknown)
-	public static final int	PR_ACCURACY				= 18;	// Long value, 0->100 (-1 unknown)
-	public static final int	PR_VOTES_DOWN			= 19;	// Long	(-1 unknown)
-	public static final int	PR_UID					= 20;	// String
-	public static final int	PR_HASH					= 21;	// byte[] torrent hash
-	
-
-	
-		// if you add more properties make sure you amend the mapping in PluginEngine appropriately
-		// AND the reverse mapping in MetaSearchManagerImpl
-		// AND generic XML attributes in xml-http plugin
-	
-	public Object
-	getProperty(
-		int		property_name );
-}
+/*
+ * Created on Jun 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.search;
+
+public interface 
+SearchResult 
+{
+	public static final int	PR_NAME					= 1;	// String
+	public static final int	PR_PUB_DATE				= 2;	// Date
+	public static final int	PR_SIZE					= 3;	// Long
+	public static final int	PR_LEECHER_COUNT		= 4;	// Long	(-1 unknown)
+	public static final int	PR_SEED_COUNT			= 5;	// Long	(-1 unknown)
+	public static final int	PR_SUPER_SEED_COUNT		= 6;	// Long	(-1 unknown)
+	public static final int	PR_CATEGORY				= 7;	// String
+	public static final int	PR_COMMENTS				= 8;	// Long	(-1 unknown)
+	public static final int	PR_VOTES				= 9;	// Long	(-1 unknown)
+	public static final int	PR_CONTENT_TYPE			= 10;	// String  ("video","audio","game")
+	public static final int	PR_DETAILS_LINK			= 11;	// URL as String
+	public static final int	PR_DOWNLOAD_LINK		= 12;	// URL as String
+	public static final int	PR_PLAY_LINK			= 13;	// URL as String
+	public static final int	PR_PRIVATE				= 14;	// Boolean
+	public static final int	PR_DRM_KEY				= 15;	// String
+	public static final int	PR_DOWNLOAD_BUTTON_LINK = 16;	// URL as String
+	public static final int	PR_RANK					= 17;	// Long value, 0->100 (-1 unknown)
+	public static final int	PR_ACCURACY				= 18;	// Long value, 0->100 (-1 unknown)
+	public static final int	PR_VOTES_DOWN			= 19;	// Long	(-1 unknown)
+	public static final int	PR_UID					= 20;	// String
+	public static final int	PR_HASH					= 21;	// byte[] torrent hash
+	
+
+	
+		// if you add more properties make sure you amend the mapping in PluginEngine appropriately
+		// AND the reverse mapping in MetaSearchManagerImpl
+		// AND generic XML attributes in xml-http plugin
+	
+	public Object
+	getProperty(
+		int		property_name );
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/security/CertificateListener.java b/azureus2/src/org/gudy/azureus2/plugins/utils/security/CertificateListener.java
index 3a10733..79e2a92 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/security/CertificateListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/security/CertificateListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/security/PasswordListener.java b/azureus2/src/org/gudy/azureus2/plugins/utils/security/PasswordListener.java
index 2991faa..c17cf0b 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/security/PasswordListener.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/security/PasswordListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/security/SEPublicKey.java b/azureus2/src/org/gudy/azureus2/plugins/utils/security/SEPublicKey.java
index 9c0d684..dfa2d89 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/security/SEPublicKey.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/security/SEPublicKey.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/security/SEPublicKeyLocator.java b/azureus2/src/org/gudy/azureus2/plugins/utils/security/SEPublicKeyLocator.java
index 1a7b1b4..a7a6746 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/security/SEPublicKeyLocator.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/security/SEPublicKeyLocator.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/security/SESecurityManager.java b/azureus2/src/org/gudy/azureus2/plugins/utils/security/SESecurityManager.java
index 302eca5..0c20345 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/security/SESecurityManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/security/SESecurityManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/Subscription.java b/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/Subscription.java
index 9899b1d..f2b0b01 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/Subscription.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/Subscription.java
@@ -1,38 +1,37 @@
-/*
- * 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 boolean
-	isSearchTemplate();
-	
-	public SubscriptionResult[]
-	getResults();
-}
+/*
+ * Created on Oct 7, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.subscriptions;
+
+public interface 
+Subscription 
+{
+	public String
+	getID();
+	
+	public String
+	getName();
+	
+	public boolean
+	isSearchTemplate();
+	
+	public SubscriptionResult[]
+	getResults();
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionException.java b/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionException.java
index 69db3de..28e5eb1 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionException.java
@@ -1,42 +1,41 @@
-/*
- * 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 );
-	}
-}
+/*
+ * Created on Jun 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 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/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionManager.java b/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionManager.java
index f83802f..30ba269 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionManager.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionManager.java
@@ -1,29 +1,34 @@
-/*
- * 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();
-}
+/*
+ * Created on Oct 7, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.plugins.utils.subscriptions;
+
+import java.net.URL;
+
+public interface 
+SubscriptionManager 
+{
+	public Subscription[] 
+	getSubscriptions();
+	
+	public void
+	requestSubscription(
+		URL			url );
+}
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionResult.java b/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionResult.java
index e15c84e..8eacc1a 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionResult.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/subscriptions/SubscriptionResult.java
@@ -1,40 +1,39 @@
-/*
- * 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 );
-	
-}
+/*
+ * Created on Oct 7, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 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/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSChannel.java b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSChannel.java
index 48bd61b..dee8743 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSChannel.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSChannel.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSFeed.java b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSFeed.java
index 49a40e4..5cf01a0 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSFeed.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSFeed.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSItem.java b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSItem.java
index 5925a68..dc7749e 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSItem.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/rss/RSSItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocument.java b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocument.java
index 9963596..6584b95 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocument.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocument.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 24, 2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
  
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentAttribute.java b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentAttribute.java
index 5774c2e..0f4bebb 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentAttribute.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentAttribute.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 24, 2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
  
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentException.java b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentException.java
index e221386..7ead682 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentException.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentException.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 24, 2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
  
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentFactory.java b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentFactory.java
index 55a52b6..bb22101 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentFactory.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -24,6 +21,7 @@ package org.gudy.azureus2.plugins.utils.xml.simpleparser;
 
 import java.io.File;
 import java.io.InputStream;
+import java.net.URL;
 
 /**
  * @author parg
@@ -38,10 +36,23 @@ SimpleXMLParserDocumentFactory
 		File		file )
 		
 		throws SimpleXMLParserDocumentException;
+
+	/**
+	 * @deprecated
+	 * @param is
+	 * @return
+	 * @throws SimpleXMLParserDocumentException
+	 */
 	
+	public SimpleXMLParserDocument
+	create(
+		InputStream		is )
+		
+		throws SimpleXMLParserDocumentException;
 	
 	public SimpleXMLParserDocument
 	create(
+		URL				source_url,
 		InputStream		is )
 		
 		throws SimpleXMLParserDocumentException;
diff --git a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentNode.java b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentNode.java
index 986b02f..1d6b612 100644
--- a/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentNode.java
+++ b/azureus2/src/org/gudy/azureus2/plugins/utils/xml/simpleparser/SimpleXMLParserDocumentNode.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 24, 2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
  
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/PluginUtils.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/PluginUtils.java
index 98c53e1..7d3e604 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/PluginUtils.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/PluginUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/FailedPlugin.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/FailedPlugin.java
index b44a7ae..b7618eb 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/FailedPlugin.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/FailedPlugin.java
@@ -3,11 +3,12 @@
  * Created : Dec 2, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.pluginsimpl.local;
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginConfigImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginConfigImpl.java
index 0ad02cb..c49dee0 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginConfigImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginConfigImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginCoreUtils.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginCoreUtils.java
index 1c93d8b..d524fd0 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginCoreUtils.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginCoreUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 17, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -378,6 +375,16 @@ PluginCoreUtils
 		Object datasource,
 		boolean toCore)
 	{
+		if (datasource instanceof Object[]) {
+			Object[] array = (Object[]) datasource;
+			Object[] newArray = new Object[array.length];
+			for (int i = 0; i < array.length; i++) {
+				Object o = array[i];
+				newArray[i] = convert(o, toCore);
+			}
+			return newArray;
+		}
+
 		try {
 			if (toCore) {
 				if (datasource instanceof org.gudy.azureus2.core3.download.DownloadManager) {
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginInitializer.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginInitializer.java
index f512508..8dc927b 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginInitializer.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginInitializer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -308,19 +309,20 @@ PluginInitializer
   protected static void
   queueRegistration(
   	Plugin		plugin,
-	String		id )
+	String		id,
+	String		config_key )
   {
   	try{
   		class_mon.enter();
   		
 	   	if ( singleton == null ){
 	  		
-	  		registration_queue.add( new Object[]{ plugin, id });
+	  		registration_queue.add( new Object[]{ plugin, id, config_key });
 	 
 	  	}else{
 	  		
 	  		try{
-	  			singleton.initializePluginFromInstance( plugin, id, plugin.getClass().getName());
+	  			singleton.initializePluginFromInstance( plugin, id, config_key );
 	  			
 			}catch( Throwable e ){
 	  				
@@ -523,8 +525,8 @@ PluginInitializer
 	  }
   }
   
-  protected boolean
-  isInitialisationThread()
+  public static boolean
+  isInitThread()
   {
 	  synchronized( initThreads ){
 
@@ -532,6 +534,12 @@ PluginInitializer
 	  }
   }
   
+  protected boolean
+  isInitialisationThread()
+  {
+	  return( isInitThread());
+  }
+  
   	public List 
 	loadPlugins(
 		AzureusCore		core,
@@ -1379,7 +1387,7 @@ PluginInitializer
 	  try{
 		  addInitThread();
 		  
-		  final LinkedList initQueue = new LinkedList();
+		  final LinkedList<Runnable> initQueue = new LinkedList<Runnable>();
 		  
 			for (int i = 0; i < loaded_pi_list.size(); i++) {
 				final int idx = i;
@@ -1517,8 +1525,7 @@ PluginInitializer
 			
 								Plugin plugin = (Plugin) x[0];
 			
-								singleton.initializePluginFromInstance(plugin, (String) x[1], plugin
-										.getClass().getName());
+								singleton.initializePluginFromInstance(plugin, (String) x[1], (String)x[2]);
 							}
 						} catch (PluginException e) {
 						}
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginInterfaceImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginInterfaceImpl.java
index 0076e6b..8b15732 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginInterfaceImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginInterfaceImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginManagerDefaultsImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginManagerDefaultsImpl.java
index b2b31e4..de34aaa 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginManagerDefaultsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginManagerDefaultsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginManagerImpl.java
index 87ca3f2..1ef9d9d 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/PluginManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -249,9 +250,10 @@ PluginManagerImpl
 	public static void
 	registerPlugin(
 		Plugin		plugin,
-		String		id )
+		String		id,
+		String		config_key )
 	{
-		PluginInitializer.queueRegistration( plugin, id );
+		PluginInitializer.queueRegistration( plugin, id, config_key );
 	}
 
 	public PluginInterface getPluginInterfaceByID(String id) {
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/clientid/ClientIDManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/clientid/ClientIDManagerImpl.java
index 78e19d0..f018a77 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/clientid/ClientIDManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/clientid/ClientIDManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,15 @@
  * 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.pluginsimpl.local.clientid;
 
+import java.io.EOFException;
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.*;
 import java.util.*;
 
@@ -297,12 +297,40 @@ ClientIDManagerImpl
 	
 		throws ClientIDException
 	{
-		if ( use_filter ){
+		boolean	filter_it = use_filter;
+		
+		if ( filter_it ){
+			
+			URL		url 	= (URL)properties.get( ClientIDGenerator.PR_URL );
+			
+			String host = url.getHost();
+			
+			if ( host.equals( "127.0.0.1" ) || AENetworkClassifier.categoriseAddress( host ) != AENetworkClassifier.AT_PUBLIC ){
+				
+				filter_it = false;
+				
+			}else{
+				
+				Proxy	proxy 	= (Proxy)properties.get( ClientIDGenerator.PR_PROXY );
+
+				if ( proxy != null && proxy.type() == Proxy.Type.SOCKS ){
+					
+					InetSocketAddress address = (InetSocketAddress)proxy.address();
+					
+					if ( address.getAddress().isLoopbackAddress()){
+						
+						filter_it = false;
+					}
+				}
+			}
+		}
+		
+		if ( filter_it ){
 		
 				// to support SSL here we would need to substitute the https url with an https one
 				// and then drive the SSL in the filter appropriately
 			
-			URL	url = (URL)properties.get( ClientIDGenerator.PR_URL );
+			URL		url 	= (URL)properties.get( ClientIDGenerator.PR_URL );
 			
 			boolean	is_ssl = url.getProtocol().toLowerCase().equals( "https" );
 			
@@ -406,7 +434,7 @@ ClientIDManagerImpl
 					}
 				}
 				
-				List	lines = new ArrayList();
+				List<String>	lines = new ArrayList<String>();
 				
 				int	pos = 0;
 				
@@ -536,38 +564,148 @@ ClientIDManagerImpl
 					target = new Socket();					
 				}
 				
-				InetSocketAddress targetSockAddress = new InetSocketAddress(  InetAddress.getByName(target_host) , target_port  );
-			    InetAddress bindIP = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress(targetSockAddress.getAddress() instanceof Inet6Address ? NetworkAdmin.IP_PROTOCOL_VERSION_REQUIRE_V6 : NetworkAdmin.IP_PROTOCOL_VERSION_REQUIRE_V4);
-			    
-		        if ( bindIP != null ){
-		        	
-		        	target.bind( new InetSocketAddress( bindIP, 0 ) );
-		        }
-
-		        // System.out.println( "filtering " + target_host + ":" + target_port );
-		        
-		        target.connect( targetSockAddress);
-		        
-				target.getOutputStream().write( header_out.getBytes(Constants.BYTE_ENCODING ));
-				
-				target.getOutputStream().flush();
-				
-				InputStream	target_is = target.getInputStream(); 
+				try{
+					InetSocketAddress targetSockAddress = new InetSocketAddress(  InetAddress.getByName(target_host) , target_port  );
 					
-				while( true ){
+				    InetAddress bindIP = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress(targetSockAddress.getAddress() instanceof Inet6Address ? NetworkAdmin.IP_PROTOCOL_VERSION_REQUIRE_V6 : NetworkAdmin.IP_PROTOCOL_VERSION_REQUIRE_V4);
+				    
+			        if ( bindIP != null ){
+			        	
+			        	target.bind( new InetSocketAddress( bindIP, 0 ) );
+			        }
+	
+			        // System.out.println( "filtering " + target_host + ":" + target_port );
+			        
+			        target.connect( targetSockAddress);
+			        
+					target.getOutputStream().write( header_out.getBytes(Constants.BYTE_ENCODING ));
 					
-					int	len = target_is.read( buffer );
+					target.getOutputStream().flush();
 					
-					if ( len == -1 ){
+					InputStream	target_is = target.getInputStream(); 
 						
-						break;
+						// meh, need to support 301/302 redirects here
+					
+					String reply_header = "";
+					
+					byte[] temp = new byte[1];
+					
+					while( true ){
+						
+						int	len = target_is.read( temp );
+						
+						if ( len != 1 ){
+							
+							throw( new ClientIDException( "EOF while reading reply header" ));
+						}
+						
+						reply_header += new String(temp,"ISO-8859-1" );
+						
+						if ( temp[0] == '\n' && reply_header.endsWith( "\r\n\r\n" )){
+							
+							break;
+						}
 					}
 					
-					socket.getOutputStream().write( buffer, 0,len );
+					String[] reply_lines = reply_header.trim().split( "\r\n" );
 					
-					written += len;
-				}	
-				
+					String line1 = reply_lines[0];
+					
+					line1 = line1.substring( line1.indexOf( ' ' ) + 1).trim();
+					
+					if ( line1.startsWith( "301" ) || line1.startsWith( "302" )){
+						
+						for ( int i=1;i<reply_lines.length;i++){
+							
+							String line = reply_lines[i];
+							
+							if ( line.toLowerCase( Locale.US ).startsWith( "location:" )){
+								
+								String redirect_url = line.substring( 9  ).trim();
+									
+								String lc_redirect_url = redirect_url.toLowerCase( Locale.US );
+								
+								if ( lc_redirect_url.startsWith( "http:" ) || lc_redirect_url.startsWith( "https:" )){
+									
+									// absolute, nothing to do
+									
+								}else{
+									
+										// relative
+									
+									String prefix = "http" + (is_ssl?"s":"") + "://" + target_host + ":" + target_port;
+									
+									if ( redirect_url.startsWith( "/" )){
+										
+										redirect_url = prefix + redirect_url;
+										
+									}else{
+										
+										String get_line = lines.get(0);
+										
+										get_line = get_line.substring( get_line.indexOf( ' ' ) + 1 ).trim();
+										
+										get_line = get_line.substring( 0, get_line.indexOf( ' ' )).trim();
+										
+										int	x_pos = get_line.indexOf( '?' );
+										
+										if ( x_pos != -1 ){
+											
+											get_line = get_line.substring( 0, x_pos );
+										}
+										
+										x_pos = get_line.lastIndexOf( '/' );
+										
+										if ( x_pos == -1 ){
+											
+											redirect_url = prefix + "/" + redirect_url;
+											
+										}else{
+											
+											redirect_url = prefix + get_line.substring( 0, x_pos + 1 ) + redirect_url;
+										}
+									}
+								}
+								
+								Properties	http_properties = new Properties();
+						 		
+						 		http_properties.put( ClientIDGenerator.PR_URL, new URL( redirect_url ));
+						 	
+						 		generateHTTPProperties( http_properties );
+						 			
+						 		URL updated = (URL)http_properties.get( ClientIDGenerator.PR_URL );
+						 		
+						 		reply_lines[i] = "Location: " + updated.toExternalForm();
+							}
+						}
+					}
+					
+					OutputStream os = socket.getOutputStream();
+					
+					for ( String str: reply_lines ){
+						
+						os.write((str + "\r\n" ).getBytes( "ISO-8859-1" ));
+					}
+					
+					os.write( "\r\n" .getBytes( "ISO-8859-1" ));
+					
+					while( true ){
+						
+						int	len = target_is.read( buffer );
+						
+						if ( len == -1 ){
+							
+							break;
+						}
+						
+						os.write( buffer, 0,len );
+						
+						written += len;
+					}	
+				}finally{
+					
+					target.close();
+				}
 			}catch( ClientIDException e ){
 						
 				report_error = e.getMessage();
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/config/ConfigParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/config/ConfigParameterImpl.java
index ebe4632..7a88685 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/config/ConfigParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/config/ConfigParameterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Aug-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/config/PluginConfigSourceImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/config/PluginConfigSourceImpl.java
index ef7d8a2..d3b5b09 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/config/PluginConfigSourceImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/config/PluginConfigSourceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 8 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl.local.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseContactImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseContactImpl.java
index 8546af1..ab83b18 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseContactImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseContactImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,13 @@
  * 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.pluginsimpl.local.ddb;
 
 import java.net.InetSocketAddress;
+import java.util.Map;
 
 import org.gudy.azureus2.plugins.ddb.DistributedDatabase;
 import org.gudy.azureus2.plugins.ddb.DistributedDatabaseContact;
@@ -177,6 +175,12 @@ DDBaseContactImpl
 		return( contact.isOrHasBeenLocal());
 	}
 
+	public Map<String, Object> 
+	exportToMap() 
+	{
+		return( contact.exportToMap());
+	}
+	
 	public boolean
 	openTunnel()
 	{
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseHelpers.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseHelpers.java
index a670766..d5ae665 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseHelpers.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseHelpers.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseImpl.java
index 306cb2d..b5e3caf 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -25,20 +22,24 @@ package org.gudy.azureus2.pluginsimpl.local.ddb;
 import java.net.InetSocketAddress;
 import java.util.*;
 
-
 import org.gudy.azureus2.core3.util.AEMonitor;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.HashWrapper;
 import org.gudy.azureus2.core3.util.SHA1Simple;
 import org.gudy.azureus2.core3.util.SystemTime;
 import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.ddb.*;
-
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
 
 import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.dht.DHT;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
 import com.aelitis.azureus.core.util.CopyOnWriteList;
 import com.aelitis.azureus.plugins.dht.DHTPlugin;
+import com.aelitis.azureus.plugins.dht.DHTPluginInterface;
 import com.aelitis.azureus.plugins.dht.DHTPluginContact;
 import com.aelitis.azureus.plugins.dht.DHTPluginKeyStats;
 import com.aelitis.azureus.plugins.dht.DHTPluginListener;
@@ -60,10 +61,8 @@ DDBaseImpl
 	
 	protected static AEMonitor		class_mon	= new AEMonitor( "DDBaseImpl:class");
 
-	protected static Map			transfer_map = new HashMap();
-	
-	private static DDBaseTTTorrent	torrent_transfer;
-	
+	private Map<HashWrapper,DistributedDatabaseTransferHandler>			transfer_map = new HashMap<HashWrapper,DistributedDatabaseTransferHandler>();
+		
 	public static DDBaseImpl
 	getSingleton(
 		AzureusCore	azureus_core )
@@ -83,11 +82,122 @@ DDBaseImpl
 		return( singleton );
 	}
 	
+	private static Map<DHTPluginInterface,DistributedDatabase> dht_pi_map = new HashMap<DHTPluginInterface, DistributedDatabase>();
+	
+	public static List<DistributedDatabase>
+	getDDBs(
+		Download		download )
+	{
+		List<DistributedDatabase>	result = new ArrayList<DistributedDatabase>();
+		
+		String[] networks = PluginCoreUtils.unwrap( download ).getDownloadState().getNetworks();
+					
+		for ( String net: networks ){
+			
+			if ( net == AENetworkClassifier.AT_PUBLIC ){
+				
+				DistributedDatabase ddb = getSingleton( AzureusCoreFactory.getSingleton());
+				
+				if ( ddb.isAvailable()){
+					
+					result.add( ddb );
+				}
+				
+			}else{
+				
+				Map<String,Object>	options = new HashMap<String, Object>();
+				
+				options.put( AEProxyFactory.DP_DOWNLOAD, download );
+				
+				DHTPluginInterface dpi = AEProxyFactory.getPluginDHTProxy( "ddb", net, options );
+				
+				if ( dpi != null ){
+					
+					DistributedDatabase ddb;
+					
+					synchronized( dht_pi_map ){
+						
+						ddb = dht_pi_map.get( dpi );
+						
+						if ( ddb == null ){
+							
+							ddb = new DDBaseImpl( net, dpi );
+							
+							dht_pi_map.put( dpi, ddb );
+						}
+					}
+					
+					if ( ddb.isAvailable()){
+					
+						result.add( ddb );
+					}
+				}
+			}
+		}
+		
+		return( result );
+	}
+	
+	public static List<DistributedDatabase>
+	getDDBs(
+		String[]		networks )
+	{
+		List<DistributedDatabase>	result = new ArrayList<DistributedDatabase>();
+							
+		for ( String net: networks ){
+			
+			if ( net == AENetworkClassifier.AT_PUBLIC ){
+				
+				DistributedDatabase ddb = getSingleton( AzureusCoreFactory.getSingleton());
+				
+				if ( ddb.isAvailable()){
+					
+					result.add( ddb );
+				}
+				
+			}else{
+				
+				Map<String,Object>	options = new HashMap<String, Object>();
+				
+				options.put( AEProxyFactory.DP_NETWORKS, networks );
+				
+				DHTPluginInterface dpi = AEProxyFactory.getPluginDHTProxy( "ddb", net, options );
+				
+				if ( dpi != null ){
+					
+					DistributedDatabase ddb;
+					
+					synchronized( dht_pi_map ){
+						
+						ddb = dht_pi_map.get( dpi );
+						
+						if ( ddb == null ){
+							
+							ddb = new DDBaseImpl( net, dpi );
+							
+							dht_pi_map.put( dpi, ddb );
+						}
+					}
+					
+					if ( ddb.isAvailable()){
+					
+						result.add( ddb );
+					}
+				}
+			}
+		}
+		
+		return( result );
+	}
+	
+	final private AzureusCore				azureus_core;
+	final private DDBaseTTTorrent			torrent_transfer;
+	final private String					network;
 	
-	private AzureusCore		azureus_core;
-	private DHTPlugin		dht_use_accessor;
+	private DHTPluginInterface				dht_use_accessor;
 		
-	private CopyOnWriteList	listeners = new CopyOnWriteList();
+
+	private CopyOnWriteList<DistributedDatabaseListener>	listeners = new CopyOnWriteList<DistributedDatabaseListener>();
 	
 	protected
 	DDBaseImpl(
@@ -97,16 +207,42 @@ DDBaseImpl
 		
 		torrent_transfer =  new DDBaseTTTorrent( this );
 		
+		network	= AENetworkClassifier.AT_PUBLIC;
+		
 		grabDHT();
 	}
 	
+	protected
+	DDBaseImpl(
+		String					_net,
+		DHTPluginInterface		_dht )
+	{
+		network				= _net;
+		dht_use_accessor	= _dht;
+		
+		azureus_core		= null;
+		torrent_transfer 	=  new DDBaseTTTorrent( this );
+	}
+	
+	public String
+	getNetwork()
+	{
+		return( network );
+	}
+	
+	public DHTPluginInterface
+	getDHTPlugin()
+	{
+		return( dht_use_accessor );
+	}
+	
 	public DDBaseTTTorrent
 	getTTTorrent()
 	{
 		return( torrent_transfer );
 	}
 	
-	protected DHTPlugin
+	protected DHTPluginInterface
 	grabDHT()
 	{
 		if ( dht_use_accessor != null ){
@@ -117,15 +253,15 @@ DDBaseImpl
 		try{
 			class_mon.enter();
 			
-			if( dht_use_accessor == null ){
+			if ( dht_use_accessor == null ){
 						
-			PluginInterface dht_pi = 
+				PluginInterface dht_pi = 
 					azureus_core.getPluginManager().getPluginInterfaceByClass(
 								DHTPlugin.class );
 						
 				if ( dht_pi != null ){
 					
-					dht_use_accessor = (DHTPlugin)dht_pi.getPlugin();
+					dht_use_accessor = (DHTPluginInterface)dht_pi.getPlugin();
 					
 					if ( dht_use_accessor.isEnabled()){
 						
@@ -136,13 +272,19 @@ DDBaseImpl
 								localAddressChanged(
 									DHTPluginContact	local_contact )
 								{
-									List l = listeners.getList();
+									List<DistributedDatabaseListener> list = listeners.getList();
 									
 									dbEvent ev = new dbEvent( DistributedDatabaseEvent.ET_LOCAL_CONTACT_CHANGED );
 									
-									for (int i=0;i<l.size();i++){
+									for ( DistributedDatabaseListener l: list){
 										
-										((DistributedDatabaseListener)l.get(i)).event( ev );
+										try{
+											l.event( ev );
+											
+										}catch( Throwable e ){
+											
+											Debug.out( e );
+										}
 									}
 								}
 							});
@@ -168,7 +310,7 @@ DDBaseImpl
 	public boolean
 	isAvailable()
 	{
-		DHTPlugin	dht = grabDHT();
+		DHTPluginInterface	dht = grabDHT();
 		
 		if ( dht == null ){
 			
@@ -181,7 +323,7 @@ DDBaseImpl
 	public boolean
 	isExtendedUseAllowed()
 	{
-		DHTPlugin	dht = grabDHT();
+		DHTPluginInterface	dht = grabDHT();
 		
 		if ( dht == null ){
 			
@@ -194,7 +336,7 @@ DDBaseImpl
 	public DistributedDatabaseContact
 	getLocalContact()
 	{
-		DHTPlugin	dht = grabDHT();
+		DHTPluginInterface	dht = grabDHT();
 		
 		if ( dht == null ){
 			
@@ -215,7 +357,7 @@ DDBaseImpl
 		}
 	}
 	
-	protected DHTPlugin
+	protected DHTPluginInterface
 	getDHT()
 	
 		throws DistributedDatabaseException
@@ -229,7 +371,7 @@ DDBaseImpl
 	log(
 		String	str )
 	{
-		DHTPlugin	dht = grabDHT();
+		DHTPluginInterface	dht = grabDHT();
 		
 		if ( dht != null ){
 			
@@ -334,6 +476,24 @@ DDBaseImpl
 		return( new DDBaseContactImpl( this, contact ));
 	}
 	
+	public DistributedDatabaseContact
+	importContact(
+		Map<String,Object>			map )
+	
+		throws DistributedDatabaseException
+	{
+		throwIfNotAvailable();
+	
+		DHTPluginContact	contact = getDHT().importContact( map );
+		
+		if ( contact == null ){
+			
+			throw( new DistributedDatabaseException( "import of '" + map + "' failed" ));
+		}
+		
+		return( new DDBaseContactImpl( this, contact));
+	}
+	
 	public void
 	write(
 		DistributedDatabaseListener		listener,
@@ -382,7 +542,7 @@ DDBaseImpl
 					((DDBaseKeyImpl)key).getBytes(),
 					key.getDescription(),
 					((DDBaseValueImpl)values[0]).getBytes(),
-					(byte)( DHTPlugin.FLAG_SINGLE_VALUE | extra_flags ),
+					(byte)( DHTPluginInterface.FLAG_SINGLE_VALUE | extra_flags ),
 					new listenerMapper( listener, DistributedDatabaseEvent.ET_VALUE_WRITTEN, key, 0, false, false ));
 		}else{
 			
@@ -412,7 +572,7 @@ DDBaseImpl
 			
 				// format is: <continuation> <len><len><data>
 			
-			byte[]	payload			= new byte[DHTPlugin.MAX_VALUE_SIZE];
+			byte[]	payload			= new byte[DHTPluginInterface.MAX_VALUE_SIZE];
 			int		payload_length	= 1;
 					
 			int	pos = 0;
@@ -450,7 +610,7 @@ DDBaseImpl
 							f_current_key,
 							key.getDescription(),
 							copy,
-							(byte)( DHTPlugin.FLAG_MULTI_VALUE | extra_flags ),
+							(byte)( DHTPluginInterface.FLAG_MULTI_VALUE | extra_flags ),
 							new listenerMapper( listener, DistributedDatabaseEvent.ET_VALUE_WRITTEN, key, 0, false, false ));
 					
 					payload_length	= 1;
@@ -473,7 +633,7 @@ DDBaseImpl
 						f_current_key,
 						key.getDescription(),
 						copy,
-						(byte)( DHTPlugin.FLAG_MULTI_VALUE | extra_flags ),
+						(byte)( DHTPluginInterface.FLAG_MULTI_VALUE | extra_flags ),
 						new listenerMapper( listener, DistributedDatabaseEvent.ET_VALUE_WRITTEN, key, 0, false, false ));
 			}
 		}
@@ -530,7 +690,7 @@ DDBaseImpl
 		getDHT().get(	
 			((DDBaseKeyImpl)key).getBytes(), 
 			key.getDescription(),
-			DHTPlugin.FLAG_STATS,
+			DHTPluginInterface.FLAG_STATS,
 			256, 
 			timeout, 
 			false,
@@ -662,7 +822,7 @@ DDBaseImpl
 					}
 				}
 				
-				public void
+				public byte[]
 				handleWrite(
 					DHTPluginContact	originator,
 					byte[]				xfer_key,
@@ -671,18 +831,28 @@ DDBaseImpl
 					try{
 						DDBaseContactImpl	contact = new DDBaseContactImpl( DDBaseImpl.this, originator );
 						
-						handler.write( 
-							contact,
-							type,
-							new DDBaseKeyImpl( xfer_key ),
-							new DDBaseValueImpl( contact, value, SystemTime.getCurrentTime(), -1));
+						DDBaseValueImpl	res = (DDBaseValueImpl)
+							handler.write( 
+								contact,
+								type,
+								new DDBaseKeyImpl( xfer_key ),
+								new DDBaseValueImpl( contact, value, SystemTime.getCurrentTime(), -1));
+						
+						if ( res == null ){
+							
+							return( null );
+						}
+						
+						return( res.getBytes());
 						
 					}catch( Throwable e ){
 						
 						Debug.printStackTrace(e);
+						
+						return( null );
 					}
 				}
-			});
+			}, null );
 	}
 	
 	public DistributedDatabaseTransferType
@@ -841,7 +1011,7 @@ DDBaseImpl
 		{
 			if ( type == DistributedDatabaseEvent.ET_KEY_STATS_READ ){
 				
-				if (( _value.getFlags() & DHTPlugin.FLAG_STATS ) == 0 ){
+				if (( _value.getFlags() & DHTPluginInterface.FLAG_STATS ) == 0 ){
 					
 						// skip, old impl
 					
@@ -890,7 +1060,7 @@ DDBaseImpl
 			}else{
 				byte[]	value = _value.getValue();
 				
-				if ( _value.getFlags() == DHTPlugin.FLAG_MULTI_VALUE ){
+				if ( _value.getFlags() == DHTPluginInterface.FLAG_MULTI_VALUE ){
 	
 					int	pos = 1;
 					
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseKeyImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseKeyImpl.java
index b3ad853..53b9da9 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseKeyImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseKeyImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseTTTorrent.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseTTTorrent.java
index 773d291..bc27837 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseTTTorrent.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseTTTorrent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Mar-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -362,7 +359,7 @@ DDBaseTTTorrent
 	
 		// server side write
 	
-	public void
+	public DistributedDatabaseValue
 	write(
 		DistributedDatabaseContact			contact,
 		DistributedDatabaseTransferType		type,
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseValueImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseValueImpl.java
index d3e2784..90b5ed1 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseValueImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ddb/DDBaseValueImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 18-Feb-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/deprecate/PluginDeprecation.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/deprecate/PluginDeprecation.java
index 7673622..9332166 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/deprecate/PluginDeprecation.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/deprecate/PluginDeprecation.java
@@ -1,7 +1,7 @@
 /*
  * Created on 5 Aug 2008
  * Created by Allan Crooks
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/deprecate/PluginDeprecationException.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/deprecate/PluginDeprecationException.java
index 2490b7f..9e32ed6 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/deprecate/PluginDeprecationException.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/deprecate/PluginDeprecationException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 5 Aug 2008
  * Created by Allan Crooks
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/dht/mainline/MainlineDHTManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/dht/mainline/MainlineDHTManagerImpl.java
index 0021616..106572e 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/dht/mainline/MainlineDHTManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/dht/mainline/MainlineDHTManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16 Jan 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl.local.dht.mainline;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerChannelImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerChannelImpl.java
index a357d2d..72132e4 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerChannelImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerChannelImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Mar-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,14 +14,12 @@
  * 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.pluginsimpl.local.disk;
 
+import java.io.IOException;
 import java.util.*;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
@@ -266,7 +264,11 @@ DiskManagerChannelImpl
 	{
 		if ( core_file.getDownloaded() != core_file.getLength()){
 			
-			if ( core_file.isSkipped()){
+			boolean is_paused = download.isPaused();
+			
+			if ( core_file.isSkipped() && !is_paused ){
+				
+					// don't mess with skipped state if paused
 				
 				core_file.setSkipped( false );
 			}
@@ -275,21 +277,28 @@ DiskManagerChannelImpl
 			
 			if ( !force_start ){
 				
-				synchronized( download ){
-					
-					Map	dl_state = (Map)download.getDownload().getData( channel_key );
+					// don't auto-start a paused torrent - the fact that it isn't running will be picked
+					// up later when the requests blocks on data and the download is found to not
+					// be running
+				
+				if ( !is_paused ){
 					
-					if ( dl_state == null ){
+					synchronized( download ){
 						
-						dl_state = new HashMap();
+						Map	dl_state = (Map)download.getDownload().getData( channel_key );
 						
-						download.getDownload().setData( channel_key, dl_state );
+						if ( dl_state == null ){
+							
+							dl_state = new HashMap();
+							
+							download.getDownload().setData( channel_key, dl_state );
+						}
+						
+						dl_state.put( ""+channel_id, "" );
 					}
 					
-					dl_state.put( ""+channel_id, "" );
+					download.setForceStart( true );
 				}
-				
-				download.setForceStart( true );
 			}
 		}
 		
@@ -766,6 +775,15 @@ DiskManagerChannelImpl
 						
 						DirectByteBuffer buffer = core_file.read( pos, (int)len );
 	
+							// might not have read the amount requested if file has been truncated
+						
+						int read = buffer.position( DirectByteBuffer.SS_EXTERNAL );
+						
+						if ( read != len ){
+							
+							throw( new IOException( "EOF: insufficient bytes read (expected=" + len + ", actual=" + read + ")" ));
+						}
+						
 						inform( new event( new PooledByteBufferImpl( buffer ), pos, (int)len ));
 						
 						pos += len;
@@ -801,6 +819,10 @@ DiskManagerChannelImpl
 								if ( dm.isDestroyed()){
 									
 									throw( new Exception( "Download has been removed" ));
+																		
+								}else if ( core_file.isSkipped()){
+									
+									throw( new Exception( "File is 'do not download'" ));
 									
 								}else{
 									
@@ -816,7 +838,14 @@ DiskManagerChannelImpl
 											
 										}else if ( now - download_not_running_time > 15*1000 ){ 
 											
-											throw( new Exception( "Download has been stopped" ));
+											if ( dm.isPaused()){
+											
+												throw( new Exception( "Download has been paused" ));
+
+											}else{
+												
+												throw( new Exception( "Download has been stopped" ));
+											}
 										}
 									}else{
 										
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerFileInfoImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerFileInfoImpl.java
index c24f428..0d68a98 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerFileInfoImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerFileInfoImpl.java
@@ -1,11 +1,12 @@
 /*
  * Created : 2004/May/26
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,9 +16,6 @@
  * 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.pluginsimpl.local.disk;
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerImpl.java
index df50d6d..93fa34f 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerRandomReadController.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerRandomReadController.java
index da2ee7e..9014d30 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerRandomReadController.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/disk/DiskManagerRandomReadController.java
@@ -2,20 +2,19 @@
  * Created on Oct 10, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadAnnounceResultImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadAnnounceResultImpl.java
index 3c4ec14..df5f39c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadAnnounceResultImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadAnnounceResultImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadEventNotifierImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadEventNotifierImpl.java
index a9d37ee..207acd1 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadEventNotifierImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadEventNotifierImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Feb 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl.local.download;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadImpl.java
index 1fe25da..fd947d4 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -52,6 +53,7 @@ import org.gudy.azureus2.core3.util.BEncoder;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.SystemTime;
 import org.gudy.azureus2.core3.util.TorrentUtils;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabase;
 import org.gudy.azureus2.plugins.disk.DiskManager;
 import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.plugins.download.*;
@@ -60,6 +62,7 @@ import org.gudy.azureus2.plugins.network.RateLimiter;
 import org.gudy.azureus2.plugins.peers.PeerManager;
 import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
+import org.gudy.azureus2.pluginsimpl.local.ddb.DDBaseImpl;
 import org.gudy.azureus2.pluginsimpl.local.deprecate.PluginDeprecation;
 import org.gudy.azureus2.pluginsimpl.local.disk.DiskManagerFileInfoImpl;
 import org.gudy.azureus2.pluginsimpl.local.peers.PeerManagerImpl;
@@ -1412,10 +1415,18 @@ DownloadImpl
 		
 			// hack alert - could use classloader to find plugin I guess
 		
-		if ( name.equals( "DHTTrackerPlugin" )){
+		pos = name.indexOf( "DHTTrackerPlugin" );
+		
+		if ( pos == 0 ){
+			
+				// built in
 			
 			name = null;
 			
+		}else if ( pos > 0 ){
+			
+			name = name.substring( 0, pos );
+					
 		}else if ( name.equals( "DHTAnnounceResult")){
 			
 			name = "mlDHT";
@@ -1831,7 +1842,8 @@ DownloadImpl
 		
 		if ( delegate == null ){
 			
-			Debug.out( "Listener not found for removal" );
+			// sometimes we end up with double removal so don't bother spewing about this
+			// Debug.out( "Listener not found for removal" );
 			
 		}else{
 			
@@ -1984,6 +1996,16 @@ DownloadImpl
 		return new DiskManagerFileInfoImpl(this, info[index]);
 	}
 	
+	public DiskManagerFileInfo
+	getPrimaryFile() {
+		org.gudy.azureus2.core3.disk.DiskManagerFileInfo primaryFile = download_manager.getDownloadState().getPrimaryFile();
+		
+		if (primaryFile == null) {
+			return null;
+		}
+		return new DiskManagerFileInfoImpl(this, primaryFile);
+	}
+	
 	public DiskManagerFileInfo[]
 	getDiskManagerFileInfo()
 	{
@@ -2042,7 +2064,7 @@ DownloadImpl
 		RateLimiter		limiter,
 		boolean			is_upload )
 	{
-		download_manager.addRateLimiter( UtilitiesImpl.wrapLimiter( limiter ), is_upload );
+		download_manager.addRateLimiter( UtilitiesImpl.wrapLimiter( limiter, false ), is_upload );
 	}
 		
 	public void
@@ -2050,7 +2072,7 @@ DownloadImpl
 		RateLimiter		limiter,
 		boolean			is_upload )
 	{
-		download_manager.removeRateLimiter( UtilitiesImpl.wrapLimiter( limiter ), is_upload );
+		download_manager.removeRateLimiter( UtilitiesImpl.wrapLimiter( limiter, false ), is_upload );
 	}
   	
   public int getSeedingRank() {
@@ -2284,6 +2306,12 @@ DownloadImpl
 		 return( this );
 	 }
 
+	 public List<DistributedDatabase>
+	 getDistributedDatabases()
+	 {
+		 return( DDBaseImpl.getDDBs( this ));
+	 }
+	 
 	 public byte[]
 	 getTorrentHash()
 	 {
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerImpl.java
index 1646d6b..8361e81 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -42,8 +43,10 @@ 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.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.*;
 import org.gudy.azureus2.plugins.download.*;
 import org.gudy.azureus2.plugins.download.savelocation.DefaultSaveLocationManager;
@@ -56,6 +59,10 @@ import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl;
 import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl;
 
 import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManager;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
 import com.aelitis.azureus.core.util.CopyOnWriteList;
 
 
@@ -86,10 +93,11 @@ DownloadManagerImpl
 		}
 	}
 	
-	//private AzureusCore				azureus_core;
-	private GlobalManager			global_manager;
-	private DownloadManagerStats	stats;
-	private DownloadEventNotifierImpl global_dl_notifier;
+
+	private final GlobalManager					global_manager;
+	private final DownloadManagerStats			stats;
+	private final DownloadEventNotifierImpl 	global_dl_notifier;
+	private final TagManager					tag_manager;
 	
 	private List<DownloadManagerListener>					listeners		= new ArrayList<DownloadManagerListener>();
 	private CopyOnWriteList<DownloadWillBeAddedListener>	dwba_listeners	= new CopyOnWriteList<DownloadWillBeAddedListener>();
@@ -103,12 +111,15 @@ DownloadManagerImpl
 	DownloadManagerImpl(
 		AzureusCore	_azureus_core )
 	{
-		//azureus_core	= _azureus_core;
+	
 		global_manager	= _azureus_core.getGlobalManager();
 		
 		stats = new DownloadManagerStatsImpl( global_manager );
+		
 		global_dl_notifier = new DownloadEventNotifierImpl(this);
 		
+		tag_manager = TagManagerFactory.getTagManager();
+		
 		readStubConfig();
 		
 		global_manager.addListener(
@@ -1162,7 +1173,7 @@ DownloadManagerImpl
 		
 		DownloadManager	core_dm = PluginCoreUtils.unwrap( download );
 		
-		Map gm_data = global_manager.exportDownloadStateToMap( core_dm );
+		Map<String,Object> gm_data = global_manager.exportDownloadStateToMap( core_dm );
 		
 			// meh, gm assumes this map is always serialised + deserialised and doesn't expect
 			// String values
@@ -1175,7 +1186,52 @@ DownloadManagerImpl
 			Debug.out( e );
 		}
 				
-		DownloadStubImpl stub = new DownloadStubImpl( this,	download, gm_data );
+		
+		String[]	manual_tags = null;
+		
+		if ( tag_manager.isEnabled()){
+						
+			List<Tag> tag_list = tag_manager.getTagType( TagType.TT_DOWNLOAD_MANUAL ).getTagsForTaggable( core_dm );
+			
+			if ( tag_list != null && tag_list.size() > 0 ){
+
+					// hack to remove the restored tag name here as auto-added during restore
+				
+				String restored_tag_name = MessageText.getString( "label.restored" );
+
+				tag_list = new ArrayList<Tag>( tag_list );
+				
+				Iterator<Tag> it = tag_list.iterator();
+				
+				while( it.hasNext()){
+					
+					Tag t = it.next();
+					
+					if ( t.isTagAuto()){
+						
+						it.remove();
+						
+					}else if ( t.getTagName( true ).equals( restored_tag_name )){
+						
+						it.remove();
+					}
+				}
+				
+				if ( tag_list.size() > 0 ){
+					
+					manual_tags = new String[tag_list.size()];
+					
+					for ( int i=0;i<manual_tags.length;i++){
+						
+						manual_tags[i] = tag_list.get(i).getTagName( true );
+					}
+					
+					Arrays.sort( manual_tags );
+				}
+			}
+		}
+
+		DownloadStubImpl stub = new DownloadStubImpl( this,	download, manual_tags, gm_data );
 		
 		try{		
 			informAdded( stub, true );
@@ -1268,6 +1324,34 @@ DownloadManagerImpl
 					writeStubConfig();
 				}
 				
+				String[] manual_tags = stub.getManualTags();
+				
+				if ( manual_tags != null && tag_manager.isEnabled()){
+					
+					TagType tt = tag_manager.getTagType( TagType.TT_DOWNLOAD_MANUAL );
+					
+					for ( String name: manual_tags ){
+						
+						Tag tag = tt.getTag( name, true );
+						
+						if ( tag == null ){
+							
+							try{
+								tag = tt.createTag( name, true );
+								
+							}catch( Throwable e ){
+								
+								Debug.out(e);
+							}
+						}
+						
+						if ( tag != null ){
+							
+							tag.addTaggable( core_dm );
+						}
+					}
+				}
+				
 				removed = true;
 				
 				informRemoved( stub, false );
@@ -1322,6 +1406,26 @@ DownloadManagerImpl
 		}
 	}
 	
+	protected TOTorrent
+	getTorrent(
+		DownloadStubImpl		stub )
+	{
+		File torrent_file = new File( ARCHIVE_DIR, ByteFormatter.encodeString( stub.getTorrentHash()) + ".dat" );
+		
+		if ( torrent_file.exists()){
+			
+			try{
+				return( TOTorrentFactory.deserialiseFromBEncodedFile( torrent_file ));
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+		
+		return( null );
+	}
+	
 	protected void
 	updated(
 		DownloadStubImpl		stub )
@@ -1343,37 +1447,68 @@ DownloadManagerImpl
 		}
 	}
 	
+	public int 
+	getDownloadStubCount() 
+	{
+		synchronized( download_stubs ){
+			
+			return( download_stubs.size());
+		}
+	}
+	
+	private Set<DownloadStub>	informing_of_add = new HashSet<DownloadStub>();
+	
 	private void
 	informAdded(
 		DownloadStub			stub,
 		final boolean			preparing )
 	{
-		final List<DownloadStub>	list = new ArrayList<DownloadStub>();
-		
-		list.add( stub );
+		synchronized( informing_of_add ){
+			
+			if ( informing_of_add.contains( stub )){
+				
+				Debug.out( "Already informing of addition, ignoring" );
+				
+				return;
+			}
+			
+			informing_of_add.add( stub );
+		}
 		
-		for ( DownloadStubListener l: download_stub_listeners ){
+		try{
+			final List<DownloadStub>	list = new ArrayList<DownloadStub>();
 			
-			try{
-				l.downloadStubEventOccurred(
-						new DownloadStubEvent()
-						{
-							public int
-							getEventType()
-							{
-								return( preparing?DownloadStubEvent.DSE_STUB_WILL_BE_ADDED:DownloadStubEvent.DSE_STUB_ADDED );
-							}
-							
-							public List<DownloadStub>
-							getDownloadStubs()
-							{
-								return( list );
-							}
-						});
+			list.add( stub );
+			
+			for ( DownloadStubListener l: download_stub_listeners ){
 				
-			}catch( Throwable e ){
+				try{
+					l.downloadStubEventOccurred(
+							new DownloadStubEvent()
+							{
+								public int
+								getEventType()
+								{
+									return( preparing?DownloadStubEvent.DSE_STUB_WILL_BE_ADDED:DownloadStubEvent.DSE_STUB_ADDED );
+								}
+								
+								public List<DownloadStub>
+								getDownloadStubs()
+								{
+									return( list );
+								}
+							});
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+		}finally{
+			
+			synchronized( informing_of_add ){
 				
-				Debug.out( e );
+				informing_of_add.remove( stub );
 			}
 		}
 	}
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerStatsImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerStatsImpl.java
index 5092ccb..e7d4c5c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadManagerStatsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -121,4 +118,16 @@ DownloadManagerStatsImpl
 	{
 		return( global_manager_stats.getTotalProtocolBytesSent());
 	}
+	
+	public long
+	getSmoothedReceiveRate()
+	{
+		return( global_manager_stats.getSmoothedReceiveRate());
+	}
+	
+	public long
+	getSmoothedSendRate()
+	{
+		return( global_manager_stats.getSmoothedSendRate());
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadScrapeResultImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadScrapeResultImpl.java
index 0d99e63..0cb978e 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadScrapeResultImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadScrapeResultImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadStatsImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadStatsImpl.java
index 9da0f44..51a588d 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadStatsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -137,6 +138,10 @@ DownloadStatsImpl
 		return( dm_stats.getRemaining());
 	}
 	
+	public long getRemainingExcludingDND() {
+		return dm_stats.getRemainingExcludingDND();
+	}
+	
 	public long
 	getUploaded()
 	{
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadStubImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadStubImpl.java
index 0d128b1..45aba23 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadStubImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/download/DownloadStubImpl.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -27,10 +26,15 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.gudy.azureus2.core3.torrent.TOTorrent;
 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.TorrentUtils;
 import org.gudy.azureus2.plugins.download.Download;
 import org.gudy.azureus2.plugins.download.DownloadException;
-import org.gudy.azureus2.plugins.download.DownloadStub;
+import org.gudy.azureus2.plugins.download.DownloadRemovalVetoException;
+import org.gudy.azureus2.plugins.download.DownloadStub.DownloadStubEx;
 import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
 
@@ -38,14 +42,17 @@ import com.aelitis.azureus.util.MapUtils;
 
 public class 
 DownloadStubImpl
-	implements DownloadStub
+	implements DownloadStubEx
 {
 	private final DownloadManagerImpl		manager;
 	private final String					name;
 	private final byte[]					hash;
 	private final long						size;
+	private final long						date_created;
 	private final String					save_path;
 	private final DownloadStubFileImpl[]	files;
+	private final String[]					manual_tags;
+	
 	private final Map<String,Object>		gm_map;
 	
 	private DownloadImpl			temp_download;
@@ -55,11 +62,14 @@ DownloadStubImpl
 	DownloadStubImpl(
 		DownloadManagerImpl		_manager,
 		DownloadImpl			_download,
-		Map<String,Object>						_gm_map )
+		String[]				_manual_tags,
+		Map<String,Object>		_gm_map )
 	{
 		manager			= _manager;
 		temp_download	= _download;
 		
+		date_created = SystemTime.getCurrentTime();
+				
 		name	= temp_download.getName();
 		
 		Torrent	torrent = temp_download.getTorrent();
@@ -76,8 +86,10 @@ DownloadStubImpl
 		
 		for ( int i=0;i<files.length;i++){
 			
-			files[i] = new DownloadStubFileImpl( _files[i] );
+			files[i] = new DownloadStubFileImpl( this, _files[i] );
 		}
+		
+		manual_tags = _manual_tags;
 	}
 	
 	protected
@@ -87,15 +99,12 @@ DownloadStubImpl
 	{
 		manager		= _manager;
 		
-		hash = (byte[])_map.get( "hash" );
-		
-		name	= MapUtils.getMapString( _map, "name", null );
-		
-		size 	= MapUtils.getMapLong( _map, "s", 0 );
-		
-		save_path	= MapUtils.getMapString( _map, "l", null );
-
-		gm_map 	= (Map<String,Object>)_map.get( "gm" );
+		date_created	= MapUtils.getMapLong( _map, "dt", 0 );
+		hash 			= (byte[])_map.get( "hash" );
+		name			= MapUtils.getMapString( _map, "name", null );
+		size 			= MapUtils.getMapLong( _map, "s", 0 );
+		save_path		= MapUtils.getMapString( _map, "l", null );
+		gm_map 			= (Map<String,Object>)_map.get( "gm" );
 		
 		List<Map<String,Object>>	file_list = (List<Map<String,Object>>)_map.get( "files" );
 		
@@ -109,10 +118,26 @@ DownloadStubImpl
 			
 			for ( int i=0;i<files.length;i++){
 				
-				files[i] = new DownloadStubFileImpl((Map)file_list.get(i));
+				files[i] = new DownloadStubFileImpl( this, (Map)file_list.get(i));
 			}
 		}
 		
+		List<Object>	tag_list = (List<Object>)_map.get( "t" );
+		
+		if ( tag_list != null ){
+			
+			manual_tags = new String[tag_list.size()];
+			
+			for (int i=0;i<manual_tags.length;i++){
+				
+				manual_tags[i] = MapUtils.getString( tag_list.get(i));
+			}
+					
+		}else{
+			
+			manual_tags = null;
+		}
+		
 		attributes = (Map<String,Object>)_map.get( "attr" );
 	}
 	
@@ -121,6 +146,7 @@ DownloadStubImpl
 	{
 		Map<String,Object>	map = new HashMap<String,Object>();
 		
+		map.put( "dt", date_created );
 		map.put( "hash", hash );
 		map.put( "s", size );
 		
@@ -138,6 +164,21 @@ DownloadStubImpl
 			file_list.add( file.exportToMap());
 		}
 		
+		if ( manual_tags != null ){
+		
+			List<String>	tag_list = new ArrayList<String>( manual_tags.length );
+			
+			for ( String s: manual_tags ){
+				if ( s != null ){
+					tag_list.add( s );
+				}
+			}
+			
+			if ( tag_list.size() > 0 ){
+				map.put( "t", tag_list );
+			}
+		}
+		
 		if ( attributes != null ){
 		
 			map.put( "attr", attributes );
@@ -189,6 +230,12 @@ DownloadStubImpl
 		return( size );
 	}
 	
+	public long 
+	getCreationDate() 
+	{
+		return( date_created );
+	}
+	
 	public String
 	getSavePath()
 	{
@@ -201,6 +248,12 @@ DownloadStubImpl
 		return( files );
 	}
 	
+	public String[]
+	getManualTags()
+	{
+		return( manual_tags );
+	}
+	
 	public long 
 	getLongAttribute(
 		TorrentAttribute 	attribute )
@@ -251,26 +304,190 @@ DownloadStubImpl
 		manager.remove( this );
 	}
 	
+	public void 
+	remove(
+		boolean delete_torrent, 
+		boolean delete_data )
+			
+		throws DownloadException, DownloadRemovalVetoException 
+	{
+		if ( delete_data ){
+			
+			TOTorrent torrent = manager.getTorrent( this );
+			
+			if ( torrent != null ){
+				
+				File save_location = new File(getSavePath());
+				
+				if ( torrent.isSimpleTorrent()){
+					
+					if ( save_location.isFile()){
+						
+						FileUtil.deleteWithRecycle( save_location, false );
+					}
+				}else{
+					
+						// stub files are fully resolved (i.e. links followed). Anything outside the
+						// save location root doesn't get touched and we want to avoid individual file deletes
+						// if we can delete a parent directory instead
+					
+					if ( save_location.isDirectory()){
+						
+						DownloadStubFile[] files = getStubFiles();
+						
+						String	save_path = save_location.getAbsolutePath();
+						
+						if ( !save_path.endsWith( File.separator )){
+							
+							save_path += File.separator;
+						}
+						
+						int	found = 0;
+						
+						for ( DownloadStubFile file: files ){
+							
+							File f = file.getFile();
+							
+							String path = f.getAbsolutePath();
+							
+							if ( path.startsWith( save_path )){
+								
+								if ( f.exists()){
+								
+									found++;
+								}
+							}
+						}
+						
+						int actual = countFiles( save_location );
+													
+						if ( actual == found ){
+							
+							FileUtil.deleteWithRecycle( save_location, false );
+							
+						}else{
+							
+							for ( DownloadStubFile file: files ){
+								
+								File f = file.getFile();
+								
+								String path = f.getAbsolutePath();
+								
+								if ( path.startsWith( save_path )){
+									
+									FileUtil.deleteWithRecycle( f, false );
+								}
+							}
+							
+							TorrentUtils.recursiveEmptyDirDelete( save_location, false );
+						}
+					}
+				}
+			}
+		}
+	
+		if ( delete_torrent ){
+			
+			byte[]	bytes = (byte[])gm_map.get( "torrent" );
+			
+			if ( bytes != null ){
+				
+				try{
+					String torrent_file = new String( bytes, "UTF-8" );
+					
+					File file = new File( torrent_file );
+					
+					TorrentUtils.delete( file, false );
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+		}
+		
+		manager.remove( this );
+	}
+	
+	private int
+	countFiles(
+		File		dir )
+	{
+		int	result = 0;
+		
+		File[] files = dir.listFiles();
+		
+		if ( files != null ){
+			
+			for ( File f: files ){
+				
+				if ( f.isFile()){
+					
+					result++;
+					
+				}else{
+					
+					result += countFiles( f );
+				}
+			}
+		}
+		
+		return( result );
+	}
+	
 	protected static class
 	DownloadStubFileImpl
 		implements DownloadStubFile
 	{
-		private final File		file;
-		private final long		length;
+		private final DownloadStubImpl		stub;
+		private final Object				file;
+		private final long					length;
 		
 		protected
 		DownloadStubFileImpl(
+			DownloadStubImpl	_stub,
 			DownloadStubFile	stub_file )
 		{
-			file	= stub_file.getFile();
+			stub	= _stub;
 			length	= stub_file.getLength();
+			
+			File f	= stub_file.getFile();
+			
+			String path = f.getAbsolutePath();
+			
+			String save_loc = stub.getSavePath();
+			
+			int	save_loc_len = save_loc.length();
+			
+			if ( 	path.startsWith( save_loc ) && 
+					path.length() > save_loc_len &&
+					path.charAt( save_loc_len ) == File.separatorChar ){
+				
+				file = path.substring( save_loc_len + 1 );
+				
+			}else{
+				
+				file = f;
+			}
 		}
 		
 		protected
 		DownloadStubFileImpl(
-			Map		map )
+			DownloadStubImpl	_stub,
+			Map					map )
 		{
-			file 	= new File( MapUtils.getMapString(map, "file", null ));
+			stub	= _stub;
+			
+			String abs_file = MapUtils.getMapString(map, "file", null );
+			
+			if ( abs_file != null ){
+				
+				file 	= new File( abs_file );
+				
+			}else{
+				
+				file =  MapUtils.getMapString(map, "rel", null );
+			}
 			
 			length 	= (Long)map.get( "len" );
 		}
@@ -280,7 +497,15 @@ DownloadStubImpl
 		{
 			Map	map = new HashMap();
 
-			map.put( "file", file.getAbsolutePath());
+			if ( file instanceof File ){
+				
+				map.put( "file", ((File)file).getAbsolutePath());
+				
+			}else{
+				
+				map.put( "rel",(String)file );
+			}
+			
 			map.put( "len", length );
 			
 			return( map );
@@ -289,7 +514,14 @@ DownloadStubImpl
 		public File
 		getFile()
 		{
-			return( file );
+			if ( file instanceof File ){
+			
+				return((File)file );
+				
+			}else{
+				
+				return( new File( stub.getSavePath(), (String)file ));
+			}
 		}
 		
 		public long
@@ -298,4 +530,213 @@ DownloadStubImpl
 			return( length );
 		}
 	}
+	
+	
+	/*
+	private static Object	file_name_manager_lock = new Object();
+	
+	private static long		nodes 	= 0;
+	private static long		chars 	= 0;
+	private static long		raw 	= 0;
+	
+	private static class
+	FileNameManager
+	{
+		private FileNode	root = new FileNode( null, null );
+		
+		public FileNode
+		addFile(
+			File		f )
+		{
+			raw += f.getAbsolutePath().length();
+			
+			synchronized( file_name_manager_lock ){
+				
+				f = f.getAbsoluteFile();
+				
+				List<String>	comps = new ArrayList<String>( 32 );
+				
+				while(true ){
+					
+					File parent = f.getParentFile();
+					
+					if ( parent == null ){
+						
+						comps.add( f.getAbsolutePath());
+						
+						break;
+						
+					}else{
+						
+						comps.add( f.getName());
+					
+						f = parent;
+					}
+				}
+				
+				int	comp_num = comps.size();
+				
+				if ( comp_num == 1 ){
+					
+					return( new FileNode( comps.get(0), null ));
+					
+				}else{
+					
+					FileNode node = root;
+					
+					for ( int i=comp_num-1;i>0;i--){
+						
+						String bit = comps.get(i);
+						
+						node = node.getChild( bit );
+					}
+					
+					return( new FileNode( comps.get(0), node ));
+				}
+			}
+		}
+	}
+	
+	private static final class
+	FileNode
+	{
+		private final String			name;
+		private final FileNode			parent;
+		
+		private LightHashMap<String,FileNode>	kids;
+		
+		private
+		FileNode(
+			String		_name,
+			FileNode	_parent )
+		{
+			name		= _name;
+			parent		= _parent;
+			
+			nodes++;
+			if ( name != null ){
+				chars += name.length();
+			}
+		}
+		
+		public String
+		getName()
+		{
+			return( name );
+		}
+		
+		public FileNode
+		getParent()
+		{
+			return( parent );
+		}
+		
+		private FileNode
+		getChild(
+			String		name )
+		{
+			FileNode node;
+			
+			if ( kids == null ){
+				
+				kids = new LightHashMap<String, DownloadStubImpl.FileNode>();
+				
+				node = null;
+				
+			}else{
+				
+				node = kids.get( name );
+			}
+			
+			if ( node == null ){
+								
+				node = new FileNode( name, this );
+				
+				kids.put( name, node );
+			}
+			
+			return( node );
+		}
+		
+		public File
+		getFile()
+		{
+			if ( parent == null ){
+			
+				return( new File( name ));
+				
+			}else{
+				
+				List<FileNode> nodes = new ArrayList<FileNode>( 32 );
+	
+				FileNode current = this;
+
+				synchronized( file_name_manager_lock ){
+												
+					while( current.getName() != null ){
+						
+						nodes.add(current);
+						
+						current = current.getParent();
+					}
+				}
+				
+				StringBuffer path = new StringBuffer( 1024 );
+
+				int	num_nodes = nodes.size();
+				
+				for ( int i=num_nodes-1;i>=0;i--){
+					
+					if ( path.length() > 0 ){
+						
+						path.append( File.separator );
+					}
+					
+					path.append( nodes.get(i).getName());
+				}
+				
+				return( new File( path.toString()));
+			}
+		}
+	}
+	
+	private static void
+	addFiles(
+		FileNameManager		manager,
+		File				file )
+	{
+		if ( file.isFile()){
+			
+			FileNode node = manager.addFile( file );
+			
+			System.out.println( node.getFile() + ": nodes=" + nodes + ",chars=" + chars + ",raw=" + raw );
+			
+		}else{
+			
+			File[] files = file.listFiles();
+			
+			for ( File f: files ){
+				
+				addFiles( manager, f );
+			}
+		}
+	}
+	
+	public static void
+	main(
+		String[]		args )
+	{
+		try{
+			FileNameManager manager = new FileNameManager();
+			
+			File root = new File( "C:\\temp" );
+			
+			addFiles( manager, root );
+			
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+		}
+	}
+	*/
 }
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/FilePluginInstallerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/FilePluginInstallerImpl.java
index b53ef16..73808fb 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/FilePluginInstallerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/FilePluginInstallerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -389,6 +386,7 @@ FilePluginInstallerImpl
 								checker,
 								getName(),
 								new String[]{"Installation from file: " + file.toString()},
+								"",	// old version
 								version,
 								rd,
 								is_jar,
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/InstallablePluginImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/InstallablePluginImpl.java
index 3455788..95926f6 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/InstallablePluginImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/InstallablePluginImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 01-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/PluginInstallerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/PluginInstallerImpl.java
index fcf4364..29a8345 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/PluginInstallerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/PluginInstallerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -414,12 +411,60 @@ PluginInstallerImpl
   		}
   	}
 	
+	private File
+	extractFromVuzeFile(
+		File				file )
+		
+		throws PluginException
+	{
+		VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile(file);
+	
+		VuzeFileComponent[] comps = vf.getComponents();
+		
+		for (int j=0;j<comps.length;j++){
+			
+			VuzeFileComponent comp = comps[j];
+			
+			if ( comp.getType() == VuzeFileComponent.COMP_TYPE_PLUGIN ){
+				
+				try{
+					Map	content = comp.getContent();
+					
+					String	id 		= new String((byte[])content.get( "id" ), "UTF-8" );
+					String	version = new String((byte[])content.get( "version" ), "UTF-8" );
+					String	suffix	= ((Long)content.get( "is_jar" )).longValue()==1?"jar":"zip";
+					
+					byte[]	plugin_file = (byte[])content.get( "file" );
+					
+					File temp_dir = AETemporaryFileHandler.createTempDir();
+					
+					File temp_file = new File( temp_dir, id + "_" + version + "." + suffix );
+					
+					FileUtil.copyFile( new ByteArrayInputStream( plugin_file ), temp_file );
+					
+					return( temp_file );
+					
+				}catch( Throwable e ){
+					
+					throw( new PluginException( "Not a valid Vuze file", e ));
+				}
+			}
+		}
+	
+		return( file );
+	}
+	
 	public FilePluginInstaller
 	installFromFile(
 		File				file )
 	
 		throws PluginException
 	{			
+		if ( file.getName().toLowerCase( Locale.US ).endsWith( ".vuze" )){
+			
+			file = extractFromVuzeFile( file );
+		}
+		
 		return( new FilePluginInstallerImpl(this,file));
 	}
 	
@@ -870,6 +915,7 @@ PluginInstallerImpl
 									update_name,
 									new String[]{ "Uninstall: " + plugin_dir},
 									pi.getPluginVersion(),
+									pi.getPluginVersion(),
 									rd,
 									unloadable?Update.RESTART_REQUIRED_NO:Update.RESTART_REQUIRED_YES );
 								
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/StandardPluginImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/StandardPluginImpl.java
index cd28294..ebab754 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/StandardPluginImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/installer/StandardPluginImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipc/IPCInterfaceImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipc/IPCInterfaceImpl.java
index 153bf8a..321c5f0 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipc/IPCInterfaceImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipc/IPCInterfaceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-May-2006
  * Created by Damokles
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPBannedImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPBannedImpl.java
index abefd7d..52116dc 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPBannedImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPBannedImpl.java
@@ -2,13 +2,14 @@
  * File    : IPBanned.java
  * Created : 08-Jan-2007
  * By      : jstockall
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, All Rights Reserved.
  * 
  * 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.
+ * 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
@@ -18,9 +19,6 @@
  * 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 org.gudy.azureus2.pluginsimpl.local.ipfilter;
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPBlockedImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPBlockedImpl.java
index d11f93c..a6e1f88 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPBlockedImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPBlockedImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPFilterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPFilterImpl.java
index e408188..a59c718 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPFilterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPFilterImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPRangeImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPRangeImpl.java
index 4392168..a66c34c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPRangeImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ipfilter/IPRangeImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/launch/PluginLauncherImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/launch/PluginLauncherImpl.java
index 07daa0e..abe1a92 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/launch/PluginLauncherImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/launch/PluginLauncherImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/launch/PluginSingleInstanceHandler.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/launch/PluginSingleInstanceHandler.java
index cc3c133..2eb6a75 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/launch/PluginSingleInstanceHandler.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/launch/PluginSingleInstanceHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/logging/LoggerChannelImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/logging/LoggerChannelImpl.java
index fbe4673..8eb2a1c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/logging/LoggerChannelImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/logging/LoggerChannelImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/logging/LoggerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/logging/LoggerImpl.java
index c3c4ce9..8087b46 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/logging/LoggerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/logging/LoggerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessage.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessage.java
index d0faf1e..db4de11 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessage.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionAdapter.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionAdapter.java
index d576553..c0c530c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 9 Aug 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionDirect.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionDirect.java
index 04cac90..6aaf80e 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionDirect.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionDirect.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -25,7 +22,6 @@ package org.gudy.azureus2.pluginsimpl.local.messaging;
 import java.nio.ByteBuffer;
 import java.util.*;
 
-
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.DirectByteBuffer;
 import org.gudy.azureus2.plugins.messaging.MessageException;
@@ -164,7 +160,7 @@ GenericMessageConnectionDirect
 	addInboundRateLimiter(
 		RateLimiter		_limiter )
 	{
-		LimitedRateGroup limiter = UtilitiesImpl.wrapLimiter( _limiter );
+		LimitedRateGroup limiter = UtilitiesImpl.wrapLimiter( _limiter, false );
 
 		synchronized( this ){
 			
@@ -188,7 +184,7 @@ GenericMessageConnectionDirect
 	removeInboundRateLimiter(
 		RateLimiter		_limiter )
 	{
-		LimitedRateGroup limiter = UtilitiesImpl.wrapLimiter( _limiter );
+		LimitedRateGroup limiter = UtilitiesImpl.wrapLimiter( _limiter, false );
 
 		synchronized( this ){
 			
@@ -210,7 +206,7 @@ GenericMessageConnectionDirect
 	addOutboundRateLimiter(
 		RateLimiter		_limiter )
 	{
-		LimitedRateGroup limiter = UtilitiesImpl.wrapLimiter( _limiter );
+		LimitedRateGroup limiter = UtilitiesImpl.wrapLimiter( _limiter, false );
 
 		synchronized( this ){
 			
@@ -234,7 +230,7 @@ GenericMessageConnectionDirect
 	removeOutboundRateLimiter(
 		RateLimiter		_limiter )
 	{
-		LimitedRateGroup limiter = UtilitiesImpl.wrapLimiter( _limiter );
+		LimitedRateGroup limiter = UtilitiesImpl.wrapLimiter( _limiter, false );
 		
 		synchronized( this ){
 			
@@ -299,6 +295,13 @@ GenericMessageConnectionDirect
 						connection.close( error==null?null:Debug.getNestedExceptionMessage(error));
 					}
 					
+					public Object 
+					getConnectionProperty( 
+						String property_name )
+					{
+						return( null );
+					}
+					 
 					public String 
 					getDescription() 
 					{
@@ -429,6 +432,13 @@ GenericMessageConnectionDirect
 						connection.close(error==null?null:Debug.getNestedExceptionMessage(error));
 					}
 					
+					public Object 
+					getConnectionProperty( 
+						String property_name )
+					{
+						return( null );
+					}
+					
 					public String 
 					getDescription() 
 					{
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionImpl.java
index da540a9..d22e75b 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 9 Aug 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionIndirect.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionIndirect.java
index 5475970..aa9ee6e 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionIndirect.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageConnectionIndirect.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10 Aug 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageDecoder.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageDecoder.java
index cc51441..7588e6d 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageDecoder.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageDecoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageEncoder.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageEncoder.java
index 38c4433..9aad3f9 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageEncoder.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageEncoder.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageEndpointImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageEndpointImpl.java
index a824971..f2690a9 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageEndpointImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/GenericMessageEndpointImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageAdapter.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageAdapter.java
index 2244c8d..d3ef575 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 10, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageManagerImpl.java
index bc77857..1b2c23b 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 24, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageStreamDecoderAdapter.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageStreamDecoderAdapter.java
index 6bd9655..6f7535d 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageStreamDecoderAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageStreamDecoderAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 21, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageStreamEncoderAdapter.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageStreamEncoderAdapter.java
index 127aaa4..a347119 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageStreamEncoderAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/messaging/MessageStreamEncoderAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 21, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/ConnectionImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/ConnectionImpl.java
index ca021d0..bc5cd72 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/ConnectionImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/ConnectionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -60,6 +57,8 @@ public class ConnectionImpl implements Connection {
       public void connectFailure( Throwable failure_msg ) {  listener.connectFailure( failure_msg );  }
       public void exceptionThrown( Throwable error ) {  listener.exceptionThrown( error );  }
       
+      public Object getConnectionProperty( String property_name){ return( null );}
+      
       public String
       getDescription()
       {
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/ConnectionManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/ConnectionManagerImpl.java
index bfc2923..e96e032 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/ConnectionManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/ConnectionManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/IncomingMessageQueueImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/IncomingMessageQueueImpl.java
index bb70e48..2d87091 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/IncomingMessageQueueImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/IncomingMessageQueueImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/OutgoingMessageQueueImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/OutgoingMessageQueueImpl.java
index 9f5002a..bb35692 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/OutgoingMessageQueueImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/OutgoingMessageQueueImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 9, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/RawMessageAdapter.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/RawMessageAdapter.java
index f28ead9..f2016ba 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/RawMessageAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/RawMessageAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 11, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/TransportImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/TransportImpl.java
index c92dbe7..7c9b7dd 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/TransportImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/network/TransportImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 11, 2005
  * Created by Alon Rohter
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignDelegate.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignDelegate.java
index d154cde..2b4f5c7 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignDelegate.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignDelegate.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -30,8 +31,10 @@ package org.gudy.azureus2.pluginsimpl.local.peers;
 
 import java.net.InetAddress;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.gudy.azureus2.core3.disk.DiskManager;
 import org.gudy.azureus2.core3.disk.DiskManagerReadRequest;
@@ -86,6 +89,12 @@ PeerForeignDelegate
 
 	protected AEMonitor	this_mon	= new AEMonitor( "PeerForeignDelegate" );
 
+	private Set<Object>	download_disabled_set;
+	
+	private boolean	is_download_disabled;
+	
+	private volatile boolean	closed;
+	
 	protected
 	PeerForeignDelegate(
 		PeerManagerImpl		_manager,
@@ -96,7 +105,7 @@ PeerForeignDelegate
 		
 		PEPeerManager pm = manager.getDelegate();
 		
-		network_connection = new PeerForeignNetworkConnection( foreign );
+		network_connection = new PeerForeignNetworkConnection( this, foreign );
 				
 		network_connection.addRateLimiter( pm.getUploadLimitedRateGroup(), true );
 		network_connection.addRateLimiter( pm.getDownloadLimitedRateGroup(), false );
@@ -109,7 +118,7 @@ PeerForeignDelegate
 					  RateLimiter		limiter,
 					  boolean			is_upload )
 				  {
-					  network_connection.addRateLimiter( UtilitiesImpl.wrapLimiter( limiter ), is_upload );
+					  network_connection.addRateLimiter( UtilitiesImpl.wrapLimiter( limiter, false ), is_upload );
 				  }
 
 				  public void
@@ -117,7 +126,7 @@ PeerForeignDelegate
 					  RateLimiter		limiter,
 					  boolean			is_upload )
 				  {
-					  network_connection.removeRateLimiter( UtilitiesImpl.wrapLimiter( limiter ), is_upload );
+					  network_connection.removeRateLimiter( UtilitiesImpl.wrapLimiter( limiter, false ), is_upload );
 				  }
 				  
 				  public RateLimiter[]
@@ -193,6 +202,11 @@ PeerForeignDelegate
     
     public boolean isDownloadPossible()
     {
+    	if ( is_download_disabled ){
+    		
+    		return( false );
+    	}
+    	
     	return foreign.isDownloadPossible();
     }
     
@@ -246,6 +260,8 @@ PeerForeignDelegate
 	closeConnection( 
 		String reason ) 
 	{
+		closed = true;
+		
 		try{
 			foreign.close( reason, false, false );
 			
@@ -255,12 +271,24 @@ PeerForeignDelegate
 		}
 	}
 		
+	public boolean
+	isClosed()
+	{
+		return( closed );
+		
+	}
 	public List
 	getExpiredRequests()
 	{
 		return( foreign.getExpiredRequests());
 	}
   		
+	public long
+	getLastMessageSentTime()
+	{
+		return( 0 );
+	}
+	
 	public int
 	getMaxNbRequests()
 	{
@@ -521,6 +549,11 @@ PeerForeignDelegate
 	public boolean 
 	isChokingMe()
 	{
+		if ( is_download_disabled ){
+			
+			return( true );
+		}
+		
 		return( foreign.isChoked());
 	}
 
@@ -540,6 +573,11 @@ PeerForeignDelegate
 	public boolean 
 	isInteresting()
 	{
+		if ( is_download_disabled ){
+			
+			return( false );
+		}
+		
 		return( foreign.isInteresting());
 	}
 
@@ -1076,6 +1114,89 @@ PeerForeignDelegate
 	}
 	
 	public void
+	setUploadDisabled(
+		Object		key,
+		boolean		disabled )
+	{
+		// nothing to do here as we only support download here
+	}
+	
+	public void
+	setDownloadDisabled(
+		Object		key,
+		boolean		disabled )
+	{
+		synchronized( this ){
+			
+			if ( download_disabled_set == null ){
+				
+				if ( disabled ){
+					
+					download_disabled_set = new HashSet<Object>();
+					
+					download_disabled_set.add( key );
+					
+				}else{
+					
+					Debug.out( "derp" );
+				}
+			}else{
+				
+				if ( disabled ){
+					
+					if ( !download_disabled_set.add( key )){
+						
+						Debug.out( "derp" );
+					}
+					
+				}else{
+					
+					if ( !download_disabled_set.remove( key )){
+						
+						Debug.out( "derp" );
+					}
+					
+					if ( download_disabled_set.size() == 0 ){
+						
+						download_disabled_set = null;
+					}
+				}
+			}
+					
+			is_download_disabled = download_disabled_set != null;
+			
+			if ( is_download_disabled ){
+				
+				List<Object>	list = foreign.getRequests();
+				
+				if ( list != null ){
+					
+					for ( Object obj: list ){
+						
+						if ( obj instanceof PeerReadRequest ){
+							
+							foreign.cancelRequest((PeerReadRequest)obj);
+						}
+					}
+				}
+			}
+			//System.out.println( "setDownloadDisabled " + getIp() + " -> " + (download_disabled_set==null?0:download_disabled_set.size()));
+		}		
+	}
+	
+	public boolean
+	isUploadDisabled()
+	{
+		return( true );
+	}
+	
+	public boolean
+	isDownloadDisabled()
+	{
+		return( is_download_disabled );
+	}
+	
+	public void
 	setHaveAggregationEnabled(
 		boolean		enabled )
 	{
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignNetworkConnection.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignNetworkConnection.java
index 0b593cf..0624f7c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignNetworkConnection.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerForeignNetworkConnection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -46,7 +43,8 @@ public class
 PeerForeignNetworkConnection
 	extends NetworkConnectionHelper
 {
-	private Peer				peer;
+	final private PeerForeignDelegate		delegate;
+	final private Peer						peer;
 	
 	private OutgoingMessageQueue	outgoing_message_queue = new omq();
 	private IncomingMessageQueue	incoming_message_queue = new imq();
@@ -55,9 +53,11 @@ PeerForeignNetworkConnection
 			
 	protected
 	PeerForeignNetworkConnection(
-		Peer		_peer )
+		PeerForeignDelegate		_delegate,
+		Peer					_peer )
 	{
-		peer	= _peer;
+		delegate	= _delegate;
+		peer		= _peer;
 	}
 	
 	public ConnectionEndpoint
@@ -201,7 +201,7 @@ PeerForeignNetworkConnection
 		receiveFromTransport( 
 			int max_bytes ) throws IOException
 		{
-			return( peer.readBytes( max_bytes ));
+			return( peer.readBytes( delegate.isDownloadDisabled()?0:max_bytes ));
 		}
 		 
 		public void 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerImpl.java
index 499936a..7aa9f76 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -54,7 +55,11 @@ PeerImpl
   	
 	private HashMap<Object,PEPeerListener> peer_listeners;
   	
-
+	private UtilitiesImpl.PluginLimitedRateGroupListener	up_rg_listener;
+	private UtilitiesImpl.PluginLimitedRateGroupListener	down_rg_listener;
+					
+	private volatile boolean closed;
+	
 		/**
 		 * don't use me, use PeerManagerImpl.getPeerForPEPeer
 		 * @param _delegate
@@ -347,12 +352,95 @@ PeerImpl
 		throw( new RuntimeException( "not supported"));
 	}
 
+	private void
+	createRGListeners()
+	{
+		up_rg_listener = 
+				new UtilitiesImpl.PluginLimitedRateGroupListener()
+				{
+					public void
+					disabledChanged(
+						PluginLimitedRateGroup		group,
+						boolean						is_disabled )
+					{
+						if ( closed ){
+							
+							group.removeListener( this );					
+						}
+							
+						delegate.setUploadDisabled( group, is_disabled );
+					}
+					
+					public void
+					sync(
+						PluginLimitedRateGroup		group,
+						boolean						is_disabled )
+					{
+						if ( closed ){
+							
+							group.removeListener( this );					
+						}
+					}
+				};
+
+		down_rg_listener = 
+				new UtilitiesImpl.PluginLimitedRateGroupListener()
+				{
+					public void
+					disabledChanged(
+						PluginLimitedRateGroup		group,
+						boolean						is_disabled )
+					{
+						if ( closed ){
+							
+							group.removeListener( this );
+						}	
+					
+						delegate.setDownloadDisabled( group, is_disabled );
+					}
+					
+					public void
+					sync(
+						PluginLimitedRateGroup		group,
+						boolean						is_disabled )
+					{
+						if ( closed ){
+							
+							group.removeListener( this );					
+						}
+					}
+				};	
+	}
 	public void
 	addRateLimiter(
 	  RateLimiter		limiter,
 	  boolean			is_upload )
 	{
-		delegate.addRateLimiter( UtilitiesImpl.wrapLimiter( limiter ), is_upload );
+		synchronized( this ){
+
+			if ( closed ){
+				
+				return;
+			}
+			
+			PluginLimitedRateGroup wrapped_limiter = UtilitiesImpl.wrapLimiter( limiter, true );
+	
+			if ( up_rg_listener == null ){
+				
+				createRGListeners();
+			}
+			
+			if ( is_upload ){
+				
+				wrapped_limiter.addListener( up_rg_listener );
+				
+			}else{
+				
+				wrapped_limiter.addListener( down_rg_listener );
+			}
+			
+			delegate.addRateLimiter( wrapped_limiter, is_upload );
+		}
 	}
 
 	public void
@@ -360,7 +448,24 @@ PeerImpl
 	  RateLimiter		limiter,
 	  boolean			is_upload )
 	{
-		delegate.removeRateLimiter( UtilitiesImpl.wrapLimiter( limiter ), is_upload );
+		synchronized( this ){
+
+			PluginLimitedRateGroup wrapped_limiter = UtilitiesImpl.wrapLimiter( limiter, true );
+	
+			if ( up_rg_listener != null ){
+							
+				if ( is_upload ){
+					
+					wrapped_limiter.removeListener( up_rg_listener );
+					
+				}else{
+					
+					wrapped_limiter.removeListener( down_rg_listener );
+				}
+			}
+			
+			delegate.removeRateLimiter(wrapped_limiter, is_upload );
+		}
 	}
 	
 	public RateLimiter[]
@@ -419,6 +524,40 @@ PeerImpl
 	protected void
 	closed()
 	{
+		synchronized( this ){
+
+			closed	= true;
+			
+			if ( up_rg_listener != null ){
+				
+					// tidy up
+				
+				LimitedRateGroup[] limiters = delegate.getRateLimiters( true );
+						
+				for ( LimitedRateGroup l: limiters ){
+					
+					if ( l instanceof PluginLimitedRateGroup  ){
+		
+						((PluginLimitedRateGroup)l).removeListener( up_rg_listener );
+					}
+					
+					delegate.removeRateLimiter( l,  true );
+				}
+				
+				limiters = delegate.getRateLimiters( false );
+				
+				for ( LimitedRateGroup l: limiters ){
+					
+					if ( l instanceof PluginLimitedRateGroup  ){
+		
+						((PluginLimitedRateGroup)l).removeListener( down_rg_listener );
+					}
+					
+					delegate.removeRateLimiter( l,  false );
+				}
+			}
+		}
+		
 		if ( delegate instanceof PeerForeignDelegate ){
 			
 			((PeerForeignDelegate)delegate).stop();
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerManagerImpl.java
index 4fe81b2..43d5dd3 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -105,16 +106,8 @@ PeerManagerImpl
 		pe_pieces	= _manager.getPieces();
 		
 		manager.addListener(
-			new PEPeerManagerListener()
+			new PEPeerManagerListenerAdapter()
 			{
-				 public void
-				 peerAdded(
-					PEPeerManager	manager, 
-					PEPeer 			peer )
-				 {
-					 
-				 }
-				 
 				 public void 
 				 peerRemoved( 
 					PEPeerManager 	manager, 
@@ -127,35 +120,6 @@ PeerManagerImpl
 						 dele.closed();
 					 }
 				 }
-				 
-				 public void 
-				 peerDiscovered(
-					PEPeerManager manager,
-					PeerItem peer, 
-					PEPeer finder) 
-				 {
-				 }
-				 
-				 public void 
-				 peerSentBadData(
-					PEPeerManager manager, PEPeer peer,	int pieceNumber) 
-				 {
-				 }
-				 
-				 public void 
-				 pieceAdded( 
-					 PEPeerManager 	manager, 
-					 PEPiece 		piece, 
-					 PEPeer 		for_peer )
-				 {
-				 }
-
-				 public void 
-				 pieceRemoved( 
-					 PEPeerManager 	manager, 
-					 PEPiece 		piece )
-				 {
-				 }
 					
 				 public void
 				 destroyed()
@@ -356,6 +320,22 @@ PeerManagerImpl
 		}
 	}
 		
+	public void 
+	peerDiscovered( 
+		String		peer_source,
+		String 		ip_address, 
+		int 		tcp_port, 
+		int			udp_port,
+		boolean 	use_crypto )
+	{
+		checkIfPrivate();
+		
+		if ( manager.isPeerSourceEnabled( peer_source )){
+
+			manager.peerDiscovered( peer_source, ip_address, tcp_port, udp_port, use_crypto );
+		}
+	}
+	
 	protected boolean
 	pluginPeerSourceEnabled()
 	{
@@ -481,6 +461,13 @@ PeerManagerImpl
 			
 			PEPeer	local = (PEPeer)foreign_map.get( _foreign );
 			
+			if ( local != null && local.isClosed()){
+				
+				foreign_map.remove( _foreign );
+				
+				local = null;
+			}
+			
 			if( local == null ){
 				
 				if ( destroyed ){
@@ -566,7 +553,7 @@ PeerManagerImpl
 
 			final Map	peer_map = new HashMap();
 
-			PEPeerManagerListener core_listener = new PEPeerManagerListener() {
+			PEPeerManagerListener core_listener = new PEPeerManagerListenerAdapter() {
 				public void peerAdded( PEPeerManager manager, PEPeer peer ) {
 					PeerImpl pi = getPeerForPEPeer( peer );
 					peer_map.put( peer, pi );
@@ -585,39 +572,6 @@ PeerManagerImpl
 						l.peerRemoved( PeerManagerImpl.this, pi );
 					}
 				}
-				
-				public void 
-				peerDiscovered(
-					PEPeerManager manager,
-					PeerItem peer, 
-					PEPeer finder) 
-				{
-				}
-				
-				public void 
-				pieceAdded( 
-					PEPeerManager 	manager, 
-					PEPiece 		piece, 
-					PEPeer 			for_peer )
-				{
-				}
-				  
-				public void 
-				pieceRemoved( 
-					PEPeerManager 	manager, 
-					PEPiece 		piece )
-				{
-				}
-				
-				public void 
-				peerSentBadData(PEPeerManager manager, PEPeer peer,	int pieceNumber) 
-				{
-				}
-				
-				public void
-				destroyed()
-				{
-				}
 			};
 
 			listener_map1.put( l, core_listener );
@@ -921,6 +875,13 @@ PeerManagerImpl
 			
 		}
 		
+		public void 
+		pieceCorrupted(
+			PEPeerManager 	manager, 
+			int 			piece_number) 
+		{
+		}
+		
 			// disk manager methods
 		
 		public void
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerManagerStatsImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerManagerStatsImpl.java
index ff452df..8e02808 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerManagerStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerManagerStatsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerStatsImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerStatsImpl.java
index 6df2864..207c0c5 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerStatsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/peers/PeerStatsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareConfigImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareConfigImpl.java
index c4b44fc..51f0b32 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareConfigImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareConfigImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareItemImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareItemImpl.java
index 360cd74..83b37b9 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareItemImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareItemImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareManagerImpl.java
index 0da912b..f8c2a11 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -543,14 +544,15 @@ ShareManagerImpl
 	
 		throws ShareException, ShareResourceDeletionVetoException
 	{
-		return( addFile( null, file, getBooleanProperty( properties, PR_PERSONAL )));
+		return( addFile( null, file, getBooleanProperty( properties, PR_PERSONAL ), properties ));
 	}
 	
 	protected ShareResourceFile
 	addFile(
 		ShareResourceDirContentsImpl	parent,
 		File							file,
-		boolean							personal )
+		boolean							personal,
+		Map<String,String>				properties )
 
 		throws ShareException, ShareResourceDeletionVetoException
 	{
@@ -559,7 +561,7 @@ ShareManagerImpl
 					+ file.toString() + "'"));
 
 		try{
-			return( (ShareResourceFile)addFileOrDir( parent, file, ShareResource.ST_FILE, personal ));
+			return( (ShareResourceFile)addFileOrDir( parent, file, ShareResource.ST_FILE, personal, properties ));
 			
 		}catch( ShareException e ){
 			
@@ -594,14 +596,15 @@ ShareManagerImpl
 	
 		throws ShareException, ShareResourceDeletionVetoException
 	{
-		return( addDir( null, dir, getBooleanProperty( properties, PR_PERSONAL )));
+		return( addDir( null, dir, getBooleanProperty( properties, PR_PERSONAL ), properties ));
 	}
 	
 	public ShareResourceDir
 	addDir(
 		ShareResourceDirContentsImpl	parent,
 		File							dir,
-		boolean							personal )
+		boolean							personal,
+		Map<String,String>				properties )
 	
 		throws ShareException, ShareResourceDeletionVetoException
 	{
@@ -612,7 +615,7 @@ ShareManagerImpl
 		try{
 			this_mon.enter();
 			
-			return( (ShareResourceDir)addFileOrDir( parent, dir, ShareResource.ST_DIR, personal ));
+			return( (ShareResourceDir)addFileOrDir( parent, dir, ShareResource.ST_DIR, personal, properties ));
 			
 		}catch( ShareException e ){
 			
@@ -640,7 +643,8 @@ ShareManagerImpl
 		ShareResourceDirContentsImpl	parent,
 		File							file,
 		int								type,
-		boolean							personal )
+		boolean							personal,
+		Map<String,String>				properties )
 	
 		throws ShareException, ShareResourceDeletionVetoException
 	{
@@ -664,13 +668,13 @@ ShareManagerImpl
 		
 				reportCurrentTask( "Adding file '" + name + "'");
 				
-				new_resource = new ShareResourceFileImpl( this, parent, file, personal );
+				new_resource = new ShareResourceFileImpl( this, parent, file, personal, properties );
 				
 			}else{
 				
 				reportCurrentTask( "Adding dir '" + name + "'");
 				
-				new_resource = new ShareResourceDirImpl( this, parent, file, personal );
+				new_resource = new ShareResourceDirImpl( this, parent, file, personal, properties );
 			}
 			
 			shares.put(name, new_resource );
@@ -743,7 +747,7 @@ ShareManagerImpl
 				old_resource.delete( true );
 			}
 
-			ShareResourceDirContentsImpl new_resource = new ShareResourceDirContentsImpl( this, dir, recursive, getBooleanProperty( properties, PR_PERSONAL ), true );
+			ShareResourceDirContentsImpl new_resource = new ShareResourceDirContentsImpl( this, dir, recursive, getBooleanProperty( properties, PR_PERSONAL ), properties, true );
 						
 			shares.put( name, new_resource );
 			
@@ -932,6 +936,7 @@ ShareManagerImpl
 			reportCurrentTask( e.toString());
 		}
 	}
+	
 	public void
 	addListener(
 		ShareManagerListener		l )
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirContentsImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirContentsImpl.java
index 2e62fab..99c4db6 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirContentsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirContentsImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -39,9 +40,10 @@ ShareResourceDirContentsImpl
 	extends		ShareResourceImpl
 	implements 	ShareResourceDirContents
 {
-	private final File			root;
-	private final boolean		recursive;
-	private final byte[]		personal_key;
+	private final File					root;
+	private final boolean				recursive;
+	private final Map<String,String>	properties;
+	private final byte[]				personal_key;
 	
 	protected ShareResource[]		children	= new ShareResource[0];
 	
@@ -51,6 +53,7 @@ ShareResourceDirContentsImpl
 		File				_dir,
 		boolean				_recursive,
 		boolean				_personal,
+		Map<String,String>	_properties,
 		boolean				_async_check )
 
 		throws ShareException
@@ -59,7 +62,8 @@ ShareResourceDirContentsImpl
 		
 		root 		= _dir;
 		recursive	= _recursive;
-		
+		properties	= _properties;
+				
 		if ( !root.exists()){
 			
 			throw( new ShareException( "Dir '" + root.getName() + "' not found"));
@@ -129,6 +133,8 @@ ShareResourceDirContentsImpl
 		
 		personal_key = (byte[])_map.get( "per_key" );
 		
+		properties = BDecoder.decodeStrings((Map)_map.get( "props" ));
+
 			// deserialised resource, checkConsistency will be called later to trigger sub-share adding
 	}
 	
@@ -220,7 +226,7 @@ ShareResourceDirContentsImpl
 								
 								if ( res == null ){
 								
-									res = manager.addDir( this, file, personal_key != null );
+									res = manager.addDir( this, file, personal_key != null, properties );
 								}
 								
 								kids.add( res );
@@ -237,7 +243,7 @@ ShareResourceDirContentsImpl
 							
 							if ( res == null ){
 								
-								res = manager.addFile( this, file, personal_key != null );
+								res = manager.addFile( this, file, personal_key != null, properties );
 							}
 							
 							kids.add( res );
@@ -310,6 +316,11 @@ ShareResourceDirContentsImpl
 			
 			map.put( "per_key", personal_key );
 		}
+		
+		if ( properties != null ){
+			
+			map.put( "props", properties );
+		}
 	}
 	
 	protected static ShareResourceImpl
@@ -358,6 +369,12 @@ ShareResourceDirContentsImpl
 		return( children );
 	}
 	
+	public Map<String, String> 
+	getProperties() 
+	{
+		return( properties );
+	}
+	
 	protected class
 	shareNode
 		implements ShareResourceDirContents
@@ -503,6 +520,12 @@ ShareResourceDirContentsImpl
 			return( node_children );
 		}
 		
+		public Map<String, String> 
+		getProperties() 
+		{
+			return( null );
+		}
+		
 		public void
 		addChangeListener(
 			ShareResourceListener	l )
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirImpl.java
index 1830369..a4c4bd1 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceDirImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -58,11 +59,12 @@ ShareResourceDirImpl
 		ShareManagerImpl				_manager,
 		ShareResourceDirContentsImpl	_parent,
 		File							_file,
-		boolean							_personal )
+		boolean							_personal,
+		Map<String,String>				_properties )
 	
 		throws ShareException
 	{
-		super( _manager, _parent, ST_DIR, _file, _personal );
+		super( _manager, _parent, ST_DIR, _file, _personal, _properties );
 	}
 	
 	protected
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileImpl.java
index a80972c..405f5f1 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -58,11 +59,12 @@ ShareResourceFileImpl
 		ShareManagerImpl				_manager,
 		ShareResourceDirContentsImpl	_parent,
 		File							_file,
-		boolean							_personal )
+		boolean							_personal,
+		Map<String,String>				_properties )
 	
 		throws ShareException
 	{
-		super( _manager, _parent, ST_FILE, _file, _personal );
+		super( _manager, _parent, ST_FILE, _file, _personal,_properties );
 	}
 	
 	protected
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileOrDirImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileOrDirImpl.java
index ac2f491..2d98195 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileOrDirImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceFileOrDirImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -33,7 +34,6 @@ import java.util.*;
 import org.gudy.azureus2.plugins.sharing.*;
 import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
 import org.gudy.azureus2.pluginsimpl.local.torrent.*;
-
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.download.DownloadManagerState;
 import org.gudy.azureus2.core3.download.DownloadManagerStateFactory;
@@ -45,8 +45,9 @@ public abstract class
 ShareResourceFileOrDirImpl
 	extends		ShareResourceImpl
 {
-	private final File				file;
-	private	final byte[]			personal_key;
+	private final File					file;
+	private	final byte[]				personal_key;
+	private final Map<String,String>	properties;
 	
 	private ShareItemImpl		item;
 	
@@ -72,12 +73,15 @@ ShareResourceFileOrDirImpl
 		ShareResourceDirContentsImpl	_parent,
 		int								_type,
 		File							_file,
-		boolean							_personal )
+		boolean							_personal,
+		Map<String,String>				_properties )
 	
 		throws ShareException
 	{
 		super( _manager, _type );
 		
+		properties	= _properties;
+		
 		if ( getType() == ST_FILE ){
 			
 			if ( !_file.exists()){
@@ -137,6 +141,8 @@ ShareResourceFileOrDirImpl
 		
 		personal_key = (byte[])_map.get( "per_key" );
 
+		properties = BDecoder.decodeStrings((Map)_map.get( "props" ));
+		
 		item = ShareItemImpl.deserialiseItem( this, _map );
 	}
 	
@@ -271,12 +277,13 @@ ShareResourceFileOrDirImpl
 				
 				TorrentUtils.setDecentralised( to_torrent );
 			}
-						
+			
 			DownloadManagerState	download_manager_state = 
 				DownloadManagerStateFactory.getDownloadState( to_torrent ); 
 
 			TorrentUtils.setResumeDataCompletelyValid( download_manager_state );
 
+			
 			download_manager_state.save();
 			
 			if ( item == null ){
@@ -324,7 +331,7 @@ ShareResourceFileOrDirImpl
 				}
 			}else{
 				
-				manager.addFileOrDir( null, file, getType(), personal_key != null );
+				manager.addFileOrDir( null, file, getType(), personal_key != null, properties );
 			}
 		}catch( Throwable e ){
 							
@@ -378,6 +385,11 @@ ShareResourceFileOrDirImpl
 			map.put( "per_key", personal_key );
 		}
 		
+		if ( properties != null ){
+			
+			map.put( "props", properties );
+		}
+		
 		item.serialiseItem( map );
 	}
 	
@@ -404,4 +416,10 @@ ShareResourceFileOrDirImpl
 	{
 		return( item );
 	}
+	
+	public Map<String, String> 
+	getProperties() 
+	{
+		return( properties );
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceImpl.java
index cd47089..30d29c0 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/sharing/ShareResourceImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/BaseTorrentAttributeImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/BaseTorrentAttributeImpl.java
index c50223f..603e0a1 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/BaseTorrentAttributeImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/BaseTorrentAttributeImpl.java
@@ -1,7 +1,7 @@
 /**
  * Created on 19-Jul-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.pluginsimpl.local.torrent;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAnnounceURLListImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAnnounceURLListImpl.java
index e81a4a3..e6019a9 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAnnounceURLListImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAnnounceURLListImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAnnounceURLListSetImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAnnounceURLListSetImpl.java
index c26fccb..8bb71d6 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAnnounceURLListSetImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAnnounceURLListSetImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeCategoryImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeCategoryImpl.java
index e0c1ef8..21e1ce8 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeCategoryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeCategoryImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeDisplayNameImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeDisplayNameImpl.java
index 9a7f4fe..b953d32 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeDisplayNameImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeDisplayNameImpl.java
@@ -1,7 +1,7 @@
 /**
  * Created on 19-Jul-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.pluginsimpl.local.torrent;
 public class TorrentAttributeDisplayNameImpl extends BaseTorrentAttributeImpl {
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeNetworksImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeNetworksImpl.java
index 4afa777..3999eb0 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeNetworksImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeNetworksImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributePeerSourcesImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributePeerSourcesImpl.java
index faaa07b..d00d7f4 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributePeerSourcesImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributePeerSourcesImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributePluginImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributePluginImpl.java
index 869b52e..e419e8a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributePluginImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributePluginImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeRelativeSavePathImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeRelativeSavePathImpl.java
index dce52de..0d22ae7 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeRelativeSavePathImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeRelativeSavePathImpl.java
@@ -1,7 +1,7 @@
 /**
  * Created on 04-Nov-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.pluginsimpl.local.torrent;
 public class TorrentAttributeRelativeSavePathImpl extends BaseTorrentAttributeImpl {
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeSharePropertiesImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeSharePropertiesImpl.java
index 91bcd1a..a143a2a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeSharePropertiesImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeSharePropertiesImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeTrackerClientExtImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeTrackerClientExtImpl.java
index 21d60df..20d373a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeTrackerClientExtImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeTrackerClientExtImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeUserCommentImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeUserCommentImpl.java
index 5768154..44a7c40 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeUserCommentImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentAttributeUserCommentImpl.java
@@ -1,7 +1,7 @@
 /**
  * Created on 26-Oct-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.pluginsimpl.local.torrent;
 public class TorrentAttributeUserCommentImpl extends BaseTorrentAttributeImpl {
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentDownloaderImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentDownloaderImpl.java
index 7c91b7b..7205a5d 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentDownloaderImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentDownloaderImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentFileImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentFileImpl.java
index de94bc2..2519458 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentFileImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentFileImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentImpl.java
index 3b7420c..4b1eb2c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentManagerImpl.java
index 4c2b94a..df966c3 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/torrent/TorrentManagerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerImpl.java
index 28bb1a6..379192d 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -200,7 +201,7 @@ TrackerImpl
 	
 		throws TrackerException
 	{
-		return( new TrackerWebContextImpl( this, null, port, protocol, null ));
+		return( new TrackerWebContextImpl( this, null, port, protocol, null, null ));
 	}
 	
 	public TrackerWebContext
@@ -211,7 +212,7 @@ TrackerImpl
 	
 		throws TrackerException
 	{
-		return( new TrackerWebContextImpl( this, name, port, protocol, null ));
+		return( new TrackerWebContextImpl( this, name, port, protocol, null, null ));
 	}
 	
 	public TrackerWebContext
@@ -223,7 +224,20 @@ TrackerImpl
     
     	throws TrackerException
     {
-		return( new TrackerWebContextImpl( this, name, port, protocol, bind_ip ));
+		return( new TrackerWebContextImpl( this, name, port, protocol, bind_ip, null ));
+    }
+	
+	public TrackerWebContext
+    createWebContext(
+    	String					name,
+    	int						port,
+		int						protocol,
+		InetAddress				bind_ip,
+		Map<String,Object>		properties )
+    
+    	throws TrackerException
+    {
+		return( new TrackerWebContextImpl( this, name, port, protocol, bind_ip, properties ));
     }
 	
 	public void
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerPeerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerPeerImpl.java
index 6151ba1..72af2ab 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerPeerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerPeerImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerTorrentImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerTorrentImpl.java
index 08ee943..2785da0 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerTorrentImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerTorrentImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerTorrentRequestImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerTorrentRequestImpl.java
index 0353148..dd0d3e7 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerTorrentRequestImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerTorrentRequestImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWCHelper.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWCHelper.java
index 51feeae..2e41567 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWCHelper.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWCHelper.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.pluginsimpl.local.tracker;
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebContextImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebContextImpl.java
index 3483f11..d84a414 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebContextImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebContextImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -47,11 +48,12 @@ TrackerWebContextImpl
 	
 	public 
 	TrackerWebContextImpl(
-		TrackerImpl	_tracker,
-		String		name,
-		int			port,
-		int			protocol,
-		InetAddress	bind_ip )
+		TrackerImpl				_tracker,
+		String					name,
+		int						port,
+		int						protocol,
+		InetAddress				bind_ip,
+		Map<String,Object>		properties )
 	
 		throws TrackerException
 	{
@@ -61,11 +63,11 @@ TrackerWebContextImpl
 			
 			if ( protocol == Tracker.PR_HTTP ){
 				
-				server = TRTrackerServerFactory.create( name, TRTrackerServerFactory.PR_TCP, port, bind_ip, false, false );
+				server = TRTrackerServerFactory.create( name, TRTrackerServerFactory.PR_TCP, port, bind_ip, false, false, properties );
 				
 			}else{
 				
-				server = TRTrackerServerFactory.createSSL( name, TRTrackerServerFactory.PR_TCP, port, bind_ip, false, false );
+				server = TRTrackerServerFactory.createSSL( name, TRTrackerServerFactory.PR_TCP, port, bind_ip, false, false, properties );
 			}
 			
 			server.addListener2( this );
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageRequestImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageRequestImpl.java
index 83df2f1..aae926f 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageRequestImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageRequestImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -120,6 +121,12 @@ TrackerWebPageRequestImpl
 		return( request.getOutputStream());
 	}
 	
+	protected boolean
+	isActive()
+	{
+		return( request.isActive());
+	}
+	
 	protected AsyncController
 	getAsyncController()
 	{
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageResponseImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageResponseImpl.java
index d21ca64..6a35d13 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageResponseImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/tracker/TrackerWebPageResponseImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -244,6 +245,12 @@ TrackerWebPageResponseImpl
 		return( request.getOutputStream());
 	}
 	
+	public boolean 
+	isActive()
+	{
+		return( request.isActive());
+	}
+	
 	protected void
 	complete()
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIInputReceiver.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIInputReceiver.java
index c74b202..33e5d78 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIInputReceiver.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIInputReceiver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Nov-2006
  * Created by Allan Crooks
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl.local.ui;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIMessage.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIMessage.java
index aa0f3e7..999842b 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIMessage.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/AbstractUIMessage.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Apr 2008
  * Created by Allan Crooks
- * Copyright (C) 2008 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl.local.ui;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/UIManagerEventAdapter.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/UIManagerEventAdapter.java
index d5227e2..2852db6 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/UIManagerEventAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/UIManagerEventAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/UIManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/UIManagerImpl.java
index 30fad67..501acb1 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/UIManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/UIManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -222,7 +219,7 @@ UIManagerImpl
   		SelectedContentManager.addCurrentlySelectedContentListener(new SelectedContentListener() {
   			public void currentlySelectedContentChanged(
   					ISelectedContent[] currentContent, String viewID) {
-  				triggerDataSourceListeners(SelectedContentManager.convertSelectedContentToObject(currentContent));
+  				triggerDataSourceListeners(SelectedContentManager.convertSelectedContentToObject(null));
   			}
   		});
 
@@ -808,8 +805,7 @@ UIManagerImpl
 		}
 		if (triggerNow) {
 			try {
-				ISelectedContent[] contents = SelectedContentManager.getCurrentlySelectedContent();
-				l.dataSourceChanged(SelectedContentManager.convertSelectedContentToObject(contents));
+				l.dataSourceChanged(SelectedContentManager.convertSelectedContentToObject(null));
 			} catch (Throwable t) {
 				Debug.out(t);
 			}
@@ -828,6 +824,11 @@ UIManagerImpl
 		}
 	}
 	
+	// @see org.gudy.azureus2.plugins.ui.UIManager#getDataSource()
+	public Object getDataSource() {
+		return SelectedContentManager.convertSelectedContentToObject(null);
+	}
+	
 	private static void triggerDataSourceListeners(Object ds) {
 		UIDataSourceListener[] listeners;
 		class_mon.enter();
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UIComponentImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UIComponentImpl.java
index a5c2647..573bf34 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UIComponentImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UIComponentImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -31,12 +28,15 @@ import java.util.*;
 
 import org.gudy.azureus2.plugins.ui.components.*;
 
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
 public class 
 UIComponentImpl
 	implements UIComponent
 {
 	protected Properties	properties 	= new Properties();
-	protected List			listeners	= new ArrayList();
+	
+	protected CopyOnWriteList<UIPropertyChangeListener>			listeners	= new CopyOnWriteList<UIPropertyChangeListener>();
 	
 	
 	protected
@@ -80,7 +80,7 @@ UIComponentImpl
 		final Object	old_value = properties.get( property_type );
 		
 		properties.put( property_type, property_value );
-		
+				
 		UIPropertyChangeEvent	ev = new
 			UIPropertyChangeEvent()
 			{
@@ -109,9 +109,9 @@ UIComponentImpl
 				}
 			};
 			
-		for (int i=0;i<listeners.size();i++){
+		for ( UIPropertyChangeListener listener: listeners ){
 			
-			((UIPropertyChangeListener)listeners.get(i)).propertyChanged( ev );
+			listener.propertyChanged( ev );
 		}
 	}
 	
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UIProgressBarImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UIProgressBarImpl.java
index a742083..841aeea 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UIProgressBarImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UIProgressBarImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextAreaImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextAreaImpl.java
index 6355fc8..7c15fa9 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextAreaImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextAreaImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextFieldImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextFieldImpl.java
index 010f125..5dcc5b2 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextFieldImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/components/UITextFieldImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ActionParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ActionParameterImpl.java
index 3d08141..f7e6bac 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ActionParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ActionParameterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/BooleanParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/BooleanParameterImpl.java
index 126cf27..1a61758 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/BooleanParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/BooleanParameterImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ColorParameter.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ColorParameter.java
index 67a4196..0d91157 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ColorParameter.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ColorParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ColorParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ColorParameterImpl.java
index 9a35559..874531f 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ColorParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ColorParameterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23 Oct 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl.local.ui.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ConfigSectionHolder.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ConfigSectionHolder.java
index d703994..0c54bb8 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ConfigSectionHolder.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ConfigSectionHolder.java
@@ -2,20 +2,19 @@
  * Created on Oct 19, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ConfigSectionRepository.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ConfigSectionRepository.java
index 271f6ea..44d2e8b 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ConfigSectionRepository.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ConfigSectionRepository.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/DirectoryParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/DirectoryParameterImpl.java
index b1f8739..17be23a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/DirectoryParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/DirectoryParameterImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/FileParameter.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/FileParameter.java
index 1e522a1..e8fcd26 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/FileParameter.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/FileParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/InfoParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/InfoParameterImpl.java
index e35f598..4fea0a0 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/InfoParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/InfoParameterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/IntParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/IntParameterImpl.java
index db8cec3..1e8c210 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/IntParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/IntParameterImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/IntsParameter.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/IntsParameter.java
index 6f25142..67637cb 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/IntsParameter.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/IntsParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/LabelParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/LabelParameterImpl.java
index c9f207a..8bb4c25 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/LabelParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/LabelParameterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterGroupImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterGroupImpl.java
index 9faf79f..0aa7759 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterGroupImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterGroupImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,14 +14,12 @@
  * 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.pluginsimpl.local.ui.config;
 
+import org.gudy.azureus2.plugins.ui.config.Parameter;
 import org.gudy.azureus2.plugins.ui.config.ParameterGroup;
 
 /**
@@ -31,15 +29,54 @@ import org.gudy.azureus2.plugins.ui.config.ParameterGroup;
 
 public class 
 ParameterGroupImpl
+	extends ParameterImpl
 	implements ParameterGroup
 {
-	private String	resource;
+	private String				resource;
+	private ParameterImpl[]		parameters;
+	
+	private int		num_columns = 1;
+	
+	private ParameterTabFolderImpl		tab_folder;
 	
 	public
 	ParameterGroupImpl(
-		String	_resource )
+		String			_resource,
+		Parameter[]		_parameters )
 	{
+		super( null, "", "" );
+		
 		resource = _resource;
+		
+		if ( _parameters != null ){
+			
+			parameters = new ParameterImpl[_parameters.length];
+			
+			for (int i=0;i<_parameters.length;i++){
+				
+				ParameterImpl parameter = (ParameterImpl)_parameters[i];
+				
+				parameters[i] = parameter;
+				
+				if ( parameter != null ){
+				
+					parameter.setGroup( this );
+				}
+			}
+		}
+	}
+	
+	public void
+	setTabFolder(
+		ParameterTabFolderImpl		tf )
+	{
+		tab_folder	= tf;
+	}
+
+	public ParameterTabFolderImpl
+	getTabFolder()
+	{
+		return( tab_folder );
 	}
 	
 	public String
@@ -47,4 +84,23 @@ ParameterGroupImpl
 	{
 		return( resource );
 	}
+	
+	public void
+	setNumberOfColumns(
+		int		num )
+	{
+		num_columns		= num;
+	}
+	
+	public int
+	getNumberColumns()
+	{
+		return( num_columns );
+	}
+	
+	public ParameterImpl[]
+	getParameters()
+	{
+		return( parameters );
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterImpl.java
index 55e6d23..0564101 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterImplListener.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterImplListener.java
index 73f8782..7486b2c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterImplListener.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterImplListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterRepository.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterRepository.java
index 5341931..5584d98 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterRepository.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterRepository.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterTabFolderImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterTabFolderImpl.java
new file mode 100644
index 0000000..45b7dd5
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/ParameterTabFolderImpl.java
@@ -0,0 +1,61 @@
+/*
+ * Created on Mar 26, 2015
+ * Created by Paul Gardner
+ * 
+ * Copyright 2015 Azureus Software, 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 org.gudy.azureus2.pluginsimpl.local.ui.config;
+
+import java.util.*;
+
+import org.gudy.azureus2.plugins.ui.config.ParameterGroup;
+import org.gudy.azureus2.plugins.ui.config.ParameterTabFolder;
+
+public class 
+ParameterTabFolderImpl 
+	extends ParameterImpl
+	implements ParameterTabFolder
+	
+{
+	private List<ParameterGroupImpl>	groups = new ArrayList<ParameterGroupImpl>();
+	
+	public
+	ParameterTabFolderImpl()
+	{
+		super( null, "", "" );
+	}
+	
+	public void
+	addTab(
+		ParameterGroup		_group )
+	{
+		ParameterGroupImpl	group = (ParameterGroupImpl)_group;
+		
+		groups.add( group );
+		
+		group.setTabFolder( this );
+	}
+	
+	public void
+	removeTab(
+		ParameterGroup		group )
+	{
+		
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/PasswordParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/PasswordParameterImpl.java
index a63c540..9f14926 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/PasswordParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/PasswordParameterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/PluginConfigUIFactoryImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/PluginConfigUIFactoryImpl.java
index 9445f44..71299c4 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/PluginConfigUIFactoryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/PluginConfigUIFactoryImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/StringListParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/StringListParameterImpl.java
index 211f5a0..8dacedf 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/StringListParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/StringListParameterImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/StringParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/StringParameterImpl.java
index c289262..090d27c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/StringParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/StringParameterImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/UIParameterImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/UIParameterImpl.java
index 40ce39e..6d36f03 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/UIParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/UIParameterImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl.local.ui.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/UITextAreaImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/UITextAreaImpl.java
new file mode 100644
index 0000000..d12d6ba
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/config/UITextAreaImpl.java
@@ -0,0 +1,136 @@
+/*
+ * Created on Sep 17, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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 org.gudy.azureus2.pluginsimpl.local.ui.config;
+
+import org.gudy.azureus2.plugins.config.ConfigParameterListener;
+import org.gudy.azureus2.plugins.ui.components.UIPropertyChangeListener;
+import org.gudy.azureus2.plugins.ui.components.UITextArea;
+import org.gudy.azureus2.plugins.ui.config.EnablerParameter;
+import org.gudy.azureus2.plugins.ui.config.Parameter;
+import org.gudy.azureus2.plugins.ui.config.ParameterListener;
+import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl;
+
+
+public class
+UITextAreaImpl 
+	extends 	ParameterImpl
+	implements 	UITextArea
+{
+	private org.gudy.azureus2.pluginsimpl.local.ui.components.UITextAreaImpl	text_area;
+	
+	public
+	UITextAreaImpl(
+		PluginConfigImpl		config,
+		String					resource_name )
+	{ 
+		super( config, resource_name, resource_name );
+		
+		text_area = new org.gudy.azureus2.pluginsimpl.local.ui.components.UITextAreaImpl();
+	}
+
+	public void
+	setText(
+		String		text )
+	{
+		text_area.setText( text );
+	}
+	
+	public void
+	appendText(
+		String		text )
+	{
+		text_area.appendText(text);
+	}
+	
+	public String
+	getText()
+	{
+		return( text_area.getText());
+	}
+	
+	public void
+	setMaximumSize(
+		int	max_size )
+	{
+		text_area.setMaximumSize(max_size);
+	}
+	
+	public void
+	setEnabled(
+		boolean		enabled )
+	{
+		super.setEnabled( enabled );
+		
+		text_area.setEnabled(enabled);
+	}
+	
+	public boolean
+	getEnabled()
+	{
+		return( super.isEnabled());
+	}
+	
+	public void
+	setVisible(
+		boolean		visible )
+	{
+		super.setEnabled( visible );
+		
+		text_area.setEnabled(visible );
+	}
+	
+	public boolean
+	getVisible()
+	{
+		return( super.isVisible());
+	}
+	
+	public void
+	setProperty(
+		String	property_type,
+		Object	property_value )
+	{
+		text_area.setProperty(property_type, property_value);
+	}
+	
+	public Object
+	getProperty(
+		String		property_type )
+	{
+		return( text_area.getProperty(property_type));
+	}
+	
+	public void
+	addPropertyChangeListener(
+		UIPropertyChangeListener	l )
+	{
+		text_area.addPropertyChangeListener(l);
+	}
+	
+	public void
+	removePropertyChangeListener(
+		UIPropertyChangeListener	l )
+	{	
+		text_area.removePropertyChangeListener(l);
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuContextImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuContextImpl.java
index 870711d..555a242 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuContextImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuContextImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 4 Jun 2008
  * Created by Allan Crooks
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuItemImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuItemImpl.java
index 9c28ed1..5554ef4 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuItemImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuItemImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 6 Feb 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl.local.ui.menus;
 
@@ -31,10 +28,7 @@ import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.ui.Graphic;
 import org.gudy.azureus2.plugins.ui.UIManager;
 import org.gudy.azureus2.plugins.ui.UIManagerEvent;
-import org.gudy.azureus2.plugins.ui.menus.MenuItem;
-import org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener;
-import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
-
+import org.gudy.azureus2.plugins.ui.menus.*;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
 import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl;
 
@@ -72,6 +66,8 @@ public class MenuItemImpl implements MenuItem {
 	
 	private MenuContextImpl menu_context = null;
 
+	private MenuBuilder builder;
+
 	public MenuItemImpl(PluginInterface _pi, String menuID, String key) {
 		pi = _pi;
 		if (pi == null) {
@@ -133,11 +129,11 @@ public class MenuItemImpl implements MenuItem {
 		return (graphic);
 	}
 
-	public void invokeMenuWillBeShownListeners(Object o) {
+	public void invokeMenuWillBeShownListeners(Object target) {
 		for (Iterator iter = fill_listeners.iterator(); iter.hasNext();) {
 			try {
 				MenuItemFillListener l = (MenuItemFillListener) iter.next();
-				l.menuWillBeShown(this, o);
+				l.menuWillBeShown(this, target);
 			} catch (Throwable e) {
 				Debug.printStackTrace(e);
 			}
@@ -230,11 +226,12 @@ public class MenuItemImpl implements MenuItem {
 		this.display_text = text;
 	}
 
-	protected void invokeListenersOnList(CopyOnWriteList listeners_to_notify, Object o) {
+	protected void invokeListenersOnList(CopyOnWriteList listeners_to_notify,
+			Object target) {
 		for (Iterator iter = listeners_to_notify.iterator(); iter.hasNext();) {
 			try {
 				MenuItemListener l = (MenuItemListener) iter.next();
-				l.selected(this, o);
+				l.selected(this, target);
 			} catch (Throwable e) {
 				Debug.printStackTrace(e);
 			}
@@ -292,4 +289,12 @@ public class MenuItemImpl implements MenuItem {
 		this.menu_context = context;
 	}
 
+	// @see org.gudy.azureus2.plugins.ui.menus.MenuItem#setSubmenuBuilder(org.gudy.azureus2.plugins.ui.menus.MenuBuilder)
+	public void setSubmenuBuilder(MenuBuilder builder) {
+		this.builder = builder;
+	}
+
+	public MenuBuilder getSubmenuBuilder() {
+		return builder;
+	}
 }
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuManagerImpl.java
index f9f4da4..8a0544a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/menus/MenuManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25 January 2007
  * Created by Allan Crooks
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl.local.ui.menus;
 import org.gudy.azureus2.plugins.PluginInterface;
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginConfigModelImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginConfigModelImpl.java
index 5d803be..5ee4b62 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginConfigModelImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginConfigModelImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -29,21 +26,18 @@ package org.gudy.azureus2.pluginsimpl.local.ui.model;
 
 import java.util.*;
 
-
-
 import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.plugins.ui.components.UITextArea;
 import org.gudy.azureus2.plugins.ui.config.ActionParameter;
 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.ParameterGroup;
-
+import org.gudy.azureus2.plugins.ui.config.ParameterTabFolder;
 import org.gudy.azureus2.pluginsimpl.local.PluginConfigImpl;
 import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl;
 import org.gudy.azureus2.pluginsimpl.local.ui.config.*;
-
 import org.gudy.azureus2.plugins.*;
-
 import org.gudy.azureus2.plugins.ui.model.*;
 
 public class 
@@ -313,26 +307,33 @@ BasicPluginConfigModelImpl
 		return( res );			
 	}
 	
+	public UITextArea
+	addTextArea(
+		String		resource_name )
+	{
+		UITextAreaImpl res = new UITextAreaImpl( configobj, resource_name );
+		
+		parameters.add( res );
+		
+		return( res );		
+	}
+	
 	public ParameterGroup
 	createGroup(
 		String											_resource_name,
 		org.gudy.azureus2.plugins.ui.config.Parameter[]	_parameters )
 	{
-		ParameterGroupImpl	pg = new ParameterGroupImpl( _resource_name );
-		
-		for (int i=0;i<_parameters.length;i++){
-			
-			ParameterImpl parameter = (ParameterImpl)_parameters[i];
-			
-			if ( parameter != null ){
-			
-				parameter.setGroup( pg );
-			}
-		}
+		ParameterGroupImpl	pg = new ParameterGroupImpl( _resource_name, _parameters );
 		
 		return( pg );
 	}
 	
+	public ParameterTabFolder 
+	createTabFolder() 
+	{
+		return( new ParameterTabFolderImpl());
+	}
+	
 	public void
 	destroy()
 	{
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginViewModelImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginViewModelImpl.java
index 9cef1ae..3e61e65 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginViewModelImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/model/BasicPluginViewModelImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/tables/TableContextMenuItemImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/tables/TableContextMenuItemImpl.java
index 0ce6390..1fa9595 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/tables/TableContextMenuItemImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/tables/TableContextMenuItemImpl.java
@@ -4,7 +4,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/tables/TableManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/tables/TableManagerImpl.java
index 88cd0c5..3863ca1 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/tables/TableManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/ui/tables/TableManagerImpl.java
@@ -12,9 +12,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdatableComponentImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdatableComponentImpl.java
index 4f2e3b1..bc17d5b 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdatableComponentImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdatableComponentImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateCheckInstanceImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateCheckInstanceImpl.java
index 708b9ea..95a39a8 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateCheckInstanceImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateCheckInstanceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -472,6 +469,7 @@ UpdateCheckInstanceImpl
 		UpdatableComponentImpl	comp,
 		String					update_name,
 		String[]				desc,
+		String					old_version,
 		String					new_version,
 		ResourceDownloader[]	downloaders,
 		int						restart_required )
@@ -480,7 +478,7 @@ UpdateCheckInstanceImpl
 			this_mon.enter();
 		
 			UpdateImpl	update = 
-				new UpdateImpl( this, comp, update_name, desc, new_version, 
+				new UpdateImpl( this, comp, update_name, desc, old_version, new_version, 
 								downloaders, comp.isMandatory(), restart_required );
 			
 			updates.add( update );
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateCheckerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateCheckerImpl.java
index 3d6cc29..836cdde 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateCheckerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateCheckerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -75,12 +72,13 @@ UpdateCheckerImpl
 	addUpdate(
 		String				name,
 		String[]			description,
+		String				old_version,
 		String				new_version,
 		ResourceDownloader	downloader,
 		int					restart_required )
 	{
 		return(	addUpdate(
-					name, description, new_version,
+					name, description, old_version, new_version,
 					new ResourceDownloader[]{ downloader },
 					restart_required ));
 	}
@@ -89,6 +87,7 @@ UpdateCheckerImpl
 	addUpdate(
 		String					name,
 		String[]				description,
+		String					old_version,
 		String					new_version,
 		ResourceDownloader[]	downloaders,
 		int						restart_required )
@@ -96,7 +95,7 @@ UpdateCheckerImpl
 		reportProgress( "Adding update: " + name );
 		
 		return( check_instance.addUpdate( 
-					component, name, description, new_version,
+					component, name, description, old_version, new_version,
 					downloaders, restart_required ));
 	}
 	
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateImpl.java
index 3383c7e..fa5191c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -46,6 +43,7 @@ UpdateImpl
 	private String					name;
 	private String[]				description;
 	private String					relative_url_base	= "";
+	private String					old_version;
 	private String					new_version;
 	private ResourceDownloader[]	downloaders;
 	private boolean					mandatory;
@@ -65,6 +63,7 @@ UpdateImpl
 		UpdatableComponentImpl	_component,
 		String					_name,
 		String[]				_desc,
+		String					_old_version,
 		String					_new_version,
 		ResourceDownloader[]	_downloaders,
 		boolean					_mandatory,
@@ -74,6 +73,7 @@ UpdateImpl
 		component			= _component;
 		name				= _name;
 		description			= _desc;
+		old_version			= _old_version;
 		new_version			= _new_version;
 		downloaders			= _downloaders;
 		mandatory			= _mandatory;
@@ -151,6 +151,12 @@ UpdateImpl
 	}
 	
 	public String
+	getOldVersion()
+	{
+		return( old_version );
+	}
+	
+	public String
 	getNewVersion()
 	{
 		return( new_version );
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateInstallerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateInstallerImpl.java
index 931e916..3af034a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateInstallerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateInstallerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateManagerImpl.java
index 1c74e2c..2ac2ab7 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/update/UpdateManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/FormattersImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/FormattersImpl.java
index 8840253..7403e81 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/FormattersImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/FormattersImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/LocaleDecoderImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/LocaleDecoderImpl.java
index add8d81..8337579 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/LocaleDecoderImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/LocaleDecoderImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/LocaleUtilitiesImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/LocaleUtilitiesImpl.java
index ceeb2f8..25356a9 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/LocaleUtilitiesImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/LocaleUtilitiesImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/MonitorImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/MonitorImpl.java
index a201ab6..87cec0f 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/MonitorImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/MonitorImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 20, 2005
  * Created by Alon Rohter
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/PooledByteBufferImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/PooledByteBufferImpl.java
index de6bb2a..d62e816 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/PooledByteBufferImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/PooledByteBufferImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jul-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/SemaphoreImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/SemaphoreImpl.java
index ccf3fbc..28d1d2b 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/SemaphoreImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/SemaphoreImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/ShortCutsImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/ShortCutsImpl.java
index 46471c2..50d1e4d 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/ShortCutsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/ShortCutsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/UTTimerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/UTTimerImpl.java
index 215ad08..ac95c55 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/UTTimerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/UTTimerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/UtilitiesImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/UtilitiesImpl.java
index 30b5ad5..394bf81 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/UtilitiesImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/UtilitiesImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -31,6 +32,7 @@ import java.io.InputStream;
 import java.io.File;
 import java.lang.reflect.Method;
 import java.net.InetAddress;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.ByteBuffer;
 import java.util.*;
@@ -39,6 +41,7 @@ import org.gudy.azureus2.platform.PlatformManager;
 import org.gudy.azureus2.platform.PlatformManagerCapabilities;
 import org.gudy.azureus2.platform.PlatformManagerFactory;
 import org.gudy.azureus2.plugins.*;
+import org.gudy.azureus2.plugins.ddb.DistributedDatabase;
 import org.gudy.azureus2.plugins.download.Download;
 import org.gudy.azureus2.plugins.network.RateLimiter;
 import org.gudy.azureus2.plugins.torrent.Torrent;
@@ -57,6 +60,7 @@ 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;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.ddb.DDBaseImpl;
 import org.gudy.azureus2.pluginsimpl.local.network.ConnectionManagerImpl;
 import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.*;
 import org.gudy.azureus2.pluginsimpl.local.utils.resourceuploader.ResourceUploaderFactoryImpl;
@@ -72,10 +76,9 @@ 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.AEMonitor;
-import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 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.BEncoder;
 import org.gudy.azureus2.core3.util.Constants;
 import org.gudy.azureus2.core3.util.Debug;
@@ -90,10 +93,11 @@ import org.gudy.azureus2.core3.util.SystemTime;
 import org.gudy.azureus2.core3.util.Timer;
 import org.gudy.azureus2.core3.util.TimerEvent;
 import org.gudy.azureus2.core3.util.TimerEventPerformer;
-import org.json.simple.JSONObject;
 
 import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.networkmanager.LimitedRateGroup;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
 import com.aelitis.azureus.core.util.CopyOnWriteList;
 import com.aelitis.azureus.core.versioncheck.VersionCheckClient;
 
@@ -199,12 +203,10 @@ UtilitiesImpl
 	private static CopyOnWriteList<LocationProviderListener>	lp_listeners 		= new CopyOnWriteList<LocationProviderListener>();
 	private static CopyOnWriteList<LocationProvider>			location_providers 	= new CopyOnWriteList<LocationProvider>();
 	
-	
-	
-	
 	public static PluginLimitedRateGroup
 	wrapLimiter(
-		final RateLimiter	limiter )
+		RateLimiter						limiter,
+		boolean							disable_disable )
 	{
 		synchronized( limiter_map ){
 		
@@ -212,9 +214,15 @@ UtilitiesImpl
 			
 			if ( l == null ){
 				
-				l = new PluginLimitedRateGroup( limiter );
+				l = new PluginLimitedRateGroup( limiter, disable_disable );
 				
 				limiter_map.put( limiter, l );
+			}else{
+				
+				if ( l.isDisableDisable() != disable_disable ){
+					
+					Debug.out( "Inconsistent setting for disable_disable" );
+				}
 			}
 			
 			return( l );
@@ -536,12 +544,22 @@ UtilitiesImpl
 	
 	public RSSFeed
 	getRSSFeed(
-		InputStream	is )
+		InputStream		is )
+	
+		throws SimpleXMLParserDocumentException
+	{
+		return( getRSSFeed( null, is ));
+	}
+	
+	public RSSFeed
+	getRSSFeed(
+		URL				source_url,
+		InputStream		is )
 	
 		throws SimpleXMLParserDocumentException
 	{
 		try{
-			return( new RSSFeedImpl( this, is ));
+			return( new RSSFeedImpl( this, source_url, is ));
 			
 		}finally{
 			
@@ -559,7 +577,83 @@ UtilitiesImpl
 	
 		throws ResourceDownloaderException, SimpleXMLParserDocumentException
 	{
-		return( getRSSFeed( getResourceDownloaderFactory().create( feed_location )));
+		String	feed_str	= feed_location.toExternalForm();
+	
+		String	lc_feed_str = feed_str.toLowerCase( Locale.US );
+	
+		ResourceDownloader	rd;
+		
+		PluginProxy plugin_proxy	= null;
+		
+		try{
+			if ( lc_feed_str.startsWith( "tor:" )){
+			
+				String target_resource = feed_str.substring( 4 );
+	
+				try{
+					feed_location = new URL( target_resource );
+					
+				}catch( MalformedURLException e ){
+					
+					throw( new ResourceDownloaderException( e ));
+				}
+				
+				Map<String,Object>	options = new HashMap<String,Object>();
+			
+				options.put( AEProxyFactory.PO_PEER_NETWORKS, new String[]{ AENetworkClassifier.AT_TOR });
+			
+				plugin_proxy = 
+					AEProxyFactory.getPluginProxy( 
+						"RSS Feed download of '" + target_resource + "'",
+						feed_location,
+						options,
+						true );
+	
+				if ( plugin_proxy == null ){
+					
+					throw( new ResourceDownloaderException( "No Tor plugin proxy available for '" + feed_str + "'" ));
+				}
+		
+			
+				rd = getResourceDownloaderFactory().create( plugin_proxy.getURL(), plugin_proxy.getProxy());		
+	
+				rd.setProperty( "URL_HOST", plugin_proxy.getURLHostRewrite() + (feed_location.getPort()==-1?"":(":" + feed_location.getPort())));
+	
+			}else{
+				
+				if ( AENetworkClassifier.categoriseAddress( feed_location.getHost()) != AENetworkClassifier.AT_PUBLIC ){
+					
+					plugin_proxy = 
+							AEProxyFactory.getPluginProxy( 
+								"RSS Feed download of '" + feed_location + "'",
+								feed_location,
+								true );
+			
+					if ( plugin_proxy == null ){
+							
+						throw( new ResourceDownloaderException( "No Plugin proxy available for '" + feed_str + "'" ));
+					}
+				
+					
+					rd = getResourceDownloaderFactory().create( plugin_proxy.getURL(), plugin_proxy.getProxy());		
+			
+					rd.setProperty( "URL_HOST", plugin_proxy.getURLHostRewrite() + (feed_location.getPort()==-1?"":(":" + feed_location.getPort())));
+
+				}else{
+				
+					rd = getResourceDownloaderFactory().create( feed_location );
+				}
+			}
+			
+			return( getRSSFeed( feed_location, rd));
+			
+		}finally{
+			
+			if ( plugin_proxy != null ){
+				
+				plugin_proxy.setOK( true );
+			}
+		}
 	}
 	
 	public RSSFeed
@@ -568,7 +662,18 @@ UtilitiesImpl
 	
 		throws ResourceDownloaderException, SimpleXMLParserDocumentException
 	{
-		return( new RSSFeedImpl( this, feed_location ));
+		return( getRSSFeed( null, feed_location ));
+	}
+
+	
+	public RSSFeed
+	getRSSFeed(
+		URL					source_url,
+		ResourceDownloader	feed_location )
+	
+		throws ResourceDownloaderException, SimpleXMLParserDocumentException
+	{
+		return( new RSSFeedImpl( this, source_url, feed_location ));
 	}
 	
 	public InetAddress
@@ -1648,6 +1753,13 @@ UtilitiesImpl
 			return( 
 				new SubscriptionManager()
 				{
+					public void
+					requestSubscription(
+						URL		url )
+					{
+						sm.requestSubscription( url );
+					}
+					
 					public Subscription[] 
 					getSubscriptions() 
 					{
@@ -1820,9 +1932,20 @@ UtilitiesImpl
 		lp_listeners.remove( listener );
 	}
 	
+	public List<DistributedDatabase>
+	getDistributedDatabases(
+			String[]		networks )
+	{
+		return( DDBaseImpl.getDDBs( networks ));
+	}
+	   
 	public interface
 	PluginSubscriptionManager
 	{
+		public void
+		requestSubscription(
+			URL		url );
+		
 		public PluginSubscription[]
 		getSubscriptions(
 			boolean	subscribed_only );
@@ -1884,6 +2007,26 @@ UtilitiesImpl
 			throws S;
 	}
 	
+	public interface
+	PluginLimitedRateGroupListener
+	{
+		public void
+		disabledChanged(
+			PluginLimitedRateGroup		group,
+			boolean						is_disabled );
+		
+			/**
+			 * Periodically called to allow sanity checks - shouldn't really be required
+			 * @param group
+			 * @param is_disabled
+			 */
+		
+		public void
+		sync(
+			PluginLimitedRateGroup		group,
+			boolean						is_disabled );
+	}
+	
 	public static class
 	PluginLimitedRateGroup
 		implements LimitedRateGroup
@@ -1892,28 +2035,199 @@ UtilitiesImpl
 		
 		private ConnectionManagerImpl.PluginRateLimiter plimiter;
 		
+		private CopyOnWriteList<PluginLimitedRateGroupListener>	listeners;
+	
+		/*
+		 * For peer connections throttling up/down speed to zero to try and block upload/download has the
+		 * unwanted effect of blocking protocol message flow and stalls the connection. the 'disable_disable'
+		 * flag causes the rate limiter to inform listeners (peer connections) when flow shoudl be disabled 
+		 * at the protocol (as opposed to byte) level and at the same time leaves the byte flow unlimited
+		 * to ensure the connection doesn't stall
+		 */
+		
+		private final boolean	disable_disable;
+		
+		private boolean	current_disabled = false;
+		
+		private long	last_sync;
+		
 		private
 		PluginLimitedRateGroup(
-			RateLimiter		_limiter )
+			RateLimiter		_limiter,
+			boolean			_disable_disable )
 		{
 			limiter	= _limiter;
 			
+			disable_disable	= _disable_disable;
+			
 			if ( limiter instanceof ConnectionManagerImpl.PluginRateLimiter ){
 				
 				plimiter = (ConnectionManagerImpl.PluginRateLimiter)limiter;
 			}
 		}
 		
+		public boolean
+		isDisableDisable()
+		{
+			return( disable_disable );
+		}
+		
+		public void
+		addListener(
+			PluginLimitedRateGroupListener		listener )
+		{
+			if ( disable_disable ){
+				
+					// in case things have changed but not been triggered yet...
+				
+				getRateLimitBytesPerSecond();
+				
+				synchronized( this ){
+					
+					if ( listeners == null ){
+						
+						listeners = new CopyOnWriteList<UtilitiesImpl.PluginLimitedRateGroupListener>();
+					}
+					
+					listeners.add( listener );
+					
+					if ( current_disabled ){
+						
+						try{
+							listener.disabledChanged( this, true );
+							
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}
+				}
+			}
+		}
+		
+		public void
+		removeListener(
+			PluginLimitedRateGroupListener		listener )
+		{
+			if ( disable_disable ){
+				
+				synchronized( this ){
+					
+					if ( listeners != null ){
+						
+						if ( listeners.remove( listener )){
+					
+							if ( current_disabled ){
+								
+								try{
+									listener.disabledChanged( this, false );
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		
 		public String 
 		getName()
 		{
-			return( limiter.getName());
+			String name = limiter.getName();
+			
+			if ( Constants.IS_CVS_VERSION ){
+				
+				if ( disable_disable ){
+					
+					String str = "";
+					
+					if ( current_disabled ){
+						
+						str += "Disabled";
+					}
+					
+					synchronized( this ){
+						
+						if ( listeners != null ){
+							
+							str += (str.length()==0?"":"/") + listeners.size();
+						}
+					}
+					
+					if ( str.length() > 0 ){
+						
+						name += " (" + str + ")";
+					}
+				}
+			}
+			
+			return( name );
 		}
 		  
 		public int 
 		getRateLimitBytesPerSecond()
 		{
-			 return( limiter.getRateLimitBytesPerSecond());
+			int	value = limiter.getRateLimitBytesPerSecond();
+		
+			if ( disable_disable ){
+			
+				boolean is_disabled = value == -1;
+				
+				if ( is_disabled != current_disabled ){
+					
+					synchronized( this ){
+						
+						current_disabled = is_disabled;
+						
+						if ( listeners != null ){
+							
+							for ( PluginLimitedRateGroupListener l: listeners ){
+								
+								try{
+									l.disabledChanged( this, is_disabled );
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+							}
+						}
+					}
+				}else{
+					long now = SystemTime.getMonotonousTime();
+					
+					if ( now - last_sync > 60*1000 ){
+						
+						last_sync = now;
+						
+						synchronized( this ){
+														
+							if ( listeners != null ){
+								
+								for ( PluginLimitedRateGroupListener l: listeners ){
+									
+									try{
+										l.sync( this, current_disabled );
+										
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}
+								}
+							}
+						}
+					}
+				}
+				 
+				return( is_disabled?0:value );
+				
+			}else{
+			 
+				return( value );
+			}
 		}
 		
 		public void
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderAlternateImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderAlternateImpl.java
index 9154a53..960c232 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderAlternateImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderAlternateImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderBaseImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderBaseImpl.java
index 7c027dd..5e2823c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderBaseImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderBaseImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderDelayedImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderDelayedImpl.java
index 3091fc8..178b84a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderDelayedImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderDelayedImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderErrorImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderErrorImpl.java
index 2758450..ce3060a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderErrorImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderErrorImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFactoryImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFactoryImpl.java
index b4a95b8..4d334a0 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFactoryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFactoryImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFileImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFileImpl.java
index 76dee82..5c9adc9 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFileImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderFileImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderMetaRefreshImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderMetaRefreshImpl.java
index 520603a..22e4c0a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderMetaRefreshImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderMetaRefreshImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderRetryImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderRetryImpl.java
index e14ad19..69cd457 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderRetryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderRetryImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderTimeoutImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderTimeoutImpl.java
index 5e6dcf1..98ca499 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderTimeoutImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderTimeoutImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderTorrentImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderTorrentImpl.java
index 9d9825c..b948c15 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderTorrentImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderTorrentImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderURLImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderURLImpl.java
index 324db88..a61ab67 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderURLImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourcedownloader/ResourceDownloaderURLImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -36,7 +37,10 @@ import java.net.*;
 import javax.net.ssl.*;
 
 import java.net.PasswordAuthentication;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -52,6 +56,7 @@ import org.gudy.azureus2.core3.util.AddressUtils;
 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;
 import org.gudy.azureus2.core3.util.TorrentUtils;
 import org.gudy.azureus2.core3.util.UrlUtils;
 import org.gudy.azureus2.core3.util.protocol.magnet.MagnetConnection2;
@@ -236,7 +241,12 @@ ResourceDownloaderURLImpl
 		try{
 			String	protocol = original_url.getProtocol().toLowerCase();
 			
-			if ( protocol.equals( "magnet" ) || protocol.equals( "dht" ) || protocol.equals( "vuze" ) || protocol.equals( "ftp" )){
+			if ( 	protocol.equals( "magnet" ) || 
+					protocol.equals( "maggot" ) || 
+					protocol.equals( "dht" ) || 
+					protocol.equals( "vuze" ) || 
+					protocol.equals( "azplug" ) || 
+					protocol.equals( "ftp" )){
 				
 				return( -1 );
 				
@@ -260,7 +270,7 @@ ResourceDownloaderURLImpl
 				
 				if ( auto_plugin_proxy ){
 					
-					plugin_proxy = AEProxyFactory.getPluginProxy( "loading plugin details", url );
+					plugin_proxy = AEProxyFactory.getPluginProxy( "downloading resource", url );
 	
 					if ( plugin_proxy == null ){
 						
@@ -319,6 +329,8 @@ ResourceDownloaderURLImpl
 				  	
 							}
 				  
+							con.setInstanceFollowRedirects( plugin_proxy == null );
+							
 							if ( plugin_proxy != null ){
 							
 								con.setRequestProperty( "HOST", plugin_proxy.getURLHostRewrite() + (initial_url.getPort()==-1?"":(":" + initial_url.getPort())));
@@ -330,15 +342,40 @@ ResourceDownloaderURLImpl
 				  
 							setRequestProperties( con, false );
 							
-							con.connect();
+							try{
+								con.connect();
 				
+							}catch( AEProxyFactory.UnknownHostException e ){
+								
+								throw( new UnknownHostException( e.getMessage()));
+							}
+							
 							int response = con.getResponseCode();
 							
 							setProperty( "URL_HTTP_Response", new Long( response ));
 
 							if ((response != HttpURLConnection.HTTP_ACCEPTED) && (response != HttpURLConnection.HTTP_OK)) {
 								
-								throw( new ResourceDownloaderException( this, "Error on connect for '" + trimForDisplay( url ) + "': " + Integer.toString(response) + " " + con.getResponseMessage()));    
+								if ( 	response == HttpURLConnection.HTTP_MOVED_TEMP ||
+										response == HttpURLConnection.HTTP_MOVED_PERM ){
+									
+										// auto redirect doesn't work from http to https or vice-versa
+									
+									return( -1 );	// cheap option for the moment
+								}
+								
+								URL	dest = url;
+								
+								if ( plugin_proxy != null ){
+									
+									try{
+										dest = new URL( plugin_proxy.getTarget());
+										
+									}catch( Throwable e ){
+									}
+								}
+								
+								throw( new ResourceDownloaderException( this, "Error on connect for '" + trimForDisplay( dest ) + "': " + Integer.toString(response) + " " + con.getResponseMessage()));    
 							}
 															
 							getRequestProperties( con );
@@ -604,7 +641,7 @@ redirect_label:
 						
 						if ( auto_plugin_proxy ){
 							
-							plugin_proxy = AEProxyFactory.getPluginProxy( "loading plugin details", current_url );
+							plugin_proxy = AEProxyFactory.getPluginProxy( "downloading resource", current_url );
 			
 							if ( plugin_proxy == null ){
 								
@@ -628,6 +665,8 @@ redirect_label:
 								try{
 									URLConnection	con;
 									
+									PluginProxy current_plugin_proxy = plugin_proxy==null?AEProxyFactory.getPluginProxy( force_proxy ):plugin_proxy;
+
 									if ( current_url.getProtocol().equalsIgnoreCase("https")){
 								      	
 											// see ConfigurationChecker for SSL client defaults
@@ -648,6 +687,84 @@ redirect_label:
 													}
 												});
 						  	
+										if ( current_plugin_proxy != null ){
+											
+												// unfortunately the use of an intermediate host name causes
+												// SSL to completely fail (the hostname verifier above isn't enough to
+												// stop borkage) so what can we do? 
+											
+												// actually, not sure why, but when I hacked in this delegator things magically
+												// started working :(
+											
+											TrustManagerFactory tmf = SESecurityManager.getTrustManagerFactory();
+											
+											final List<X509TrustManager>	default_tms = new ArrayList<X509TrustManager>();
+											
+											if ( tmf != null ){
+												
+												for ( TrustManager tm: tmf.getTrustManagers()){
+																						
+													if ( tm instanceof X509TrustManager ){
+														
+														default_tms.add((X509TrustManager)tm);
+													}
+												}
+											}
+											
+											TrustManager[] tms_delegate = 
+												new TrustManager[]
+												{
+													new X509TrustManager() {
+														public X509Certificate[] 
+														getAcceptedIssuers() 
+														{
+															List<X509Certificate> result = new ArrayList<X509Certificate>();
+															
+															for ( X509TrustManager tm: default_tms ){
+																
+																result.addAll( Arrays.asList(tm.getAcceptedIssuers()));
+															}
+															
+															return( result.toArray(new X509Certificate[result.size()]));
+														}
+														
+														public void 
+														checkClientTrusted(
+															java.security.cert.X509Certificate[] 	chain, 
+															String 									authType) 
+															
+															throws CertificateException
+														{
+															for ( X509TrustManager tm: default_tms ){
+																
+																tm.checkClientTrusted( chain, authType );
+															}
+														}
+														
+														public void 
+														checkServerTrusted(
+															java.security.cert.X509Certificate[] 	chain, 
+															String 									authType) 
+															
+															throws CertificateException
+														{
+															for ( X509TrustManager tm: default_tms ){
+																
+																tm.checkServerTrusted(chain, authType);
+															}
+														}
+													}
+												};
+										
+											SSLContext sc = SSLContext.getInstance("SSL");
+											
+											sc.init( null, tms_delegate, RandomUtils.SECURE_RANDOM );
+											
+											SSLSocketFactory factory = sc.getSocketFactory();
+											
+											ssl_con.setSSLSocketFactory(factory);
+										}
+										
 										con = ssl_con;
 						  	
 									}else{
@@ -656,7 +773,6 @@ redirect_label:
 						  	
 									}
 									
-									PluginProxy current_plugin_proxy = plugin_proxy==null?AEProxyFactory.getPluginProxy( force_proxy ):plugin_proxy;
 									
 									if ( con instanceof HttpURLConnection ){
 										
@@ -746,8 +862,14 @@ redirect_label:
 									
 									boolean	trust_content_length = getBooleanProperty( "URL_Trust_Content_Length" );
 									
-									con.connect();
-						
+									try{
+										con.connect();
+										
+									}catch( AEProxyFactory.UnknownHostException e ){
+										
+										throw( new UnknownHostException( e.getMessage()));
+									}
+									
 									int response = con instanceof HttpURLConnection?((HttpURLConnection)con).getResponseCode():HttpURLConnection.HTTP_OK;
 												
 									ok = true;
@@ -890,7 +1012,18 @@ redirect_label:
 										
 										getRequestProperties( con );
 										
-										throw( new ResourceDownloaderException( this, "Error on connect for '" + trimForDisplay( current_url ) + "': " + Integer.toString(response) + " " + http_con.getResponseMessage() + (error_str==null?"":( ": error=" + error_str ))));    
+										URL	dest = current_url;
+										
+										if ( current_plugin_proxy != null ){
+											
+											try{
+												dest = new URL( current_plugin_proxy.getTarget());
+												
+											}catch( Throwable e ){
+											}
+										}
+										
+										throw( new ResourceDownloaderException( this, "Error on connect for '" + trimForDisplay( dest ) + "': " + Integer.toString(response) + " " + http_con.getResponseMessage() + (error_str==null?"":( ": error=" + error_str ))));    
 									}
 									
 									getRequestProperties( con );
@@ -1244,7 +1377,23 @@ redirect_label:
 					
 				}else{
 					
-					con.setRequestProperty(key,(String)value);
+					String nice_key = "";
+					
+					boolean	upper = true;
+					
+					for ( char c: key.toCharArray()){
+					
+						if ( upper ){
+							c = Character.toUpperCase(c);
+							upper = false;
+						}else if ( c == '-' ){
+							upper = true;
+						}
+						
+						nice_key += c;
+					}
+					
+					con.setRequestProperty(nice_key,(String)value);
 				}
 			}
 		}
@@ -1353,6 +1502,19 @@ redirect_label:
 	trimForDisplay(
 		URL		url )
 	{
+		if ( force_proxy != null ){
+			
+			PluginProxy pp = AEProxyFactory.getPluginProxy( force_proxy );
+			
+			if ( pp != null ){
+				
+				try{
+					url = new URL( pp.getTarget());
+					
+				}catch( Throwable e ){
+				}
+			}
+		}
 		String str = url.toString();
 		
 		int pos = str.indexOf( '?' );
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourceuploader/ResourceUploaderFactoryImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourceuploader/ResourceUploaderFactoryImpl.java
index efdd611..968eab0 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourceuploader/ResourceUploaderFactoryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourceuploader/ResourceUploaderFactoryImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 03-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourceuploader/ResourceUploaderURLImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourceuploader/ResourceUploaderURLImpl.java
index 6d6eab4..de0cba7 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourceuploader/ResourceUploaderURLImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/resourceuploader/ResourceUploaderURLImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Oct-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SEPublicKeyImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SEPublicKeyImpl.java
index 5e8ef6e..564d24a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SEPublicKeyImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SEPublicKeyImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SESTSConnectionImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SESTSConnectionImpl.java
index 46fd4a7..3d4e7a2 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SESTSConnectionImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SESTSConnectionImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20 Jun 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -32,12 +29,12 @@ import javax.crypto.Cipher;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 
-
 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.AESemaphore;
 import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.AddressUtils;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.DirectByteBuffer;
 import org.gudy.azureus2.core3.util.SimpleTimer;
@@ -247,7 +244,7 @@ SESTSConnectionImpl
 	{
 		synchronized( SESTSConnectionImpl.class ){
 							
-			int	hit_count = generate_bloom.add( originator.getAddress().getAddress());
+			int	hit_count = generate_bloom.add( AddressUtils.getAddressBytes( originator ));
 			
 			long	now = SystemTime.getCurrentTime();
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SESecurityManagerImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SESecurityManagerImpl.java
index 9b4f2ce..5159c37 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SESecurityManagerImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/security/SESecurityManagerImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSChannelImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSChannelImpl.java
index 1edfef8..61ea55a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSChannelImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSChannelImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSFeedImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSFeedImpl.java
index 90d2464..16e100b 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSFeedImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSFeedImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,13 @@
  * 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.pluginsimpl.local.utils.xml.rss;
 
 import java.io.InputStream;
+import java.net.URL;
 import java.util.*;
 
 import org.gudy.azureus2.core3.util.Debug;
@@ -51,22 +49,24 @@ RSSFeedImpl
 	public
 	RSSFeedImpl(
 		Utilities			utilities,
+		URL					source_url,
 		ResourceDownloader	downloader )
 	
 		throws ResourceDownloaderException, SimpleXMLParserDocumentException
 	{
-		this( utilities, downloader.download());
+		this( utilities, source_url, downloader.download());
 	}
 	
 	public
 	RSSFeedImpl(
 		Utilities			utilities,
+		URL					source_url,
 		InputStream			is  )
 	
 		throws SimpleXMLParserDocumentException
 	{
 		try{
-			SimpleXMLParserDocument	doc = utilities.getSimpleXMLParserDocumentFactory().create( is );
+			SimpleXMLParserDocument	doc = utilities.getSimpleXMLParserDocumentFactory().create( source_url, is );
 		
 			String	doc_name = doc.getName();
 			
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSItemImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSItemImpl.java
index 917760b..fe1fee7 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSItemImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSItemImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -82,6 +79,8 @@ RSSItemImpl
 		if ( link_node != null ){
 
 			try{
+				String value = "";
+
 				if ( is_atom ){
 					
 					SimpleXMLParserDocumentAttribute attr = link_node.getAttribute( "href" );
@@ -91,26 +90,24 @@ RSSItemImpl
 						return( null );
 					}
 					
-					String	value = attr.getValue().trim();
+					value = attr.getValue().trim();
 					
-					if ( value.length() == 0 ){
-						
-						return( null );
-					}
-					
-					return( new URL( value ));
-
 				}else{
 				
-					String	value = link_node.getValue().trim();
+					value = link_node.getValue().trim();
+				}
 					
-					if ( value.length() == 0 ){
-						
-						return( null );
-					}
+				if ( value.length() == 0 ){
 					
-					return( new URL( value ));
+					return( null );
 				}
+				
+				if (value.startsWith("//")) {
+					value = "http:" + value;
+				}
+				
+				return( new URL( value ));
+
 			}catch( Throwable e ){
 			
 				Debug.printStackTrace(e);
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSUtils.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSUtils.java
index 5676549..be93f4b 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSUtils.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/rss/RSSUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,20 +14,23 @@
  * 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.pluginsimpl.local.utils.xml.rss;
 
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Locale;
 
 import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
 
 /**
  * @author parg
@@ -41,6 +44,13 @@ RSSUtils
 	parseRSSDate(
 		String	date_str )
 	{
+		date_str = date_str.trim();
+		
+		if ( date_str.length() == 0 ){
+			
+			return( null );
+		}
+		
 		try{
 			// see rfc822 [EEE,] dd MMM yyyy HH:mm::ss z
 			// assume 4 digit year
@@ -99,6 +109,13 @@ RSSUtils
 	parseAtomDate(
 		String	date_str )
 	{
+		date_str = date_str.trim();
+		
+		if ( date_str.length() == 0 ){
+			
+			return( null );
+		}
+		
 			// full-time from http://tools.ietf.org/html/rfc3339 with T and Z
 		
 		final String[]	formats = {
@@ -135,6 +152,38 @@ RSSUtils
 		return( null );
 	}
 	
+	public static boolean
+	isRSSFeed(
+		File		file )
+	{
+		try{
+			String str = FileUtil.readFileAsString( file, 512 ).toLowerCase();
+			
+			str = str.trim().toLowerCase( Locale.US );
+			
+			if ( str.startsWith( "<?xml" )){
+				
+				if ( str.contains( "<feed" ) || str.contains( "<rss" )){
+					
+					InputStream is = new BufferedInputStream( new FileInputStream( file ));
+					
+					try{
+						new RSSFeedImpl( new UtilitiesImpl( null, null ), null, is );
+						
+						return( true );
+						
+					}finally{
+						
+						is.close();
+					}
+				}
+			}
+		}catch( Throwable e ){
+		}
+		
+		return( false );
+	}
+	
 	public static void
 	main(
 		String[]	args )
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentAttributeImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentAttributeImpl.java
index 951a0f3..cd97576 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentAttributeImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentAttributeImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentFactoryImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentFactoryImpl.java
index c4b279b..2cbcef6 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentFactoryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentFactoryImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 24-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -29,6 +26,7 @@ package org.gudy.azureus2.pluginsimpl.local.utils.xml.simpleparser;
 
 import java.io.File;
 import java.io.InputStream;
+import java.net.URL;
 
 import org.gudy.azureus2.plugins.utils.xml.simpleparser.*;
 
@@ -51,7 +49,17 @@ SimpleXMLParserDocumentFactoryImpl
 		
 		throws SimpleXMLParserDocumentException
 	{
-		return( new SimpleXMLParserDocumentImpl( is ));
+		return( new SimpleXMLParserDocumentImpl( null, is ));
+	}
+	
+	public SimpleXMLParserDocument
+	create(
+		URL				source_url,
+		InputStream		is )
+		
+		throws SimpleXMLParserDocumentException
+	{
+		return( new SimpleXMLParserDocumentImpl( source_url, is ));
 	}
 	
 	public SimpleXMLParserDocument
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentImpl.java
index 7764cd2..a67a8a2 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -24,13 +25,18 @@ package org.gudy.azureus2.pluginsimpl.local.utils.xml.simpleparser;
 import javax.xml.parsers.*;
 
 import org.xml.sax.*;
+import org.apache.commons.lang.Entities;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument;
 import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentAttribute;
 import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException;
 import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentNode;
 import org.w3c.dom.*;
 
+import com.aelitis.azureus.core.util.UncloseableInputStream;
+
 import java.io.*;
 import java.net.InetAddress;
 import java.net.URL;
@@ -44,8 +50,10 @@ SimpleXMLParserDocumentImpl
 {
 	private static DocumentBuilderFactory 		dbf_singleton;
 
-	protected Document							document;
-	protected SimpleXMLParserDocumentNodeImpl	root_node;
+	private URL			source_url;
+	
+	private Document						document;
+	private SimpleXMLParserDocumentNodeImpl	root_node;
 	
 	
 	public
@@ -78,13 +86,30 @@ SimpleXMLParserDocumentImpl
 		}
 	}
 
+	/**
+	 * @deprecated
+	 * @param _input_stream
+	 * @throws SimpleXMLParserDocumentException
+	 */
 	public
 	SimpleXMLParserDocumentImpl(
-		InputStream		input_stream )
+		InputStream		_input_stream )
+		
+		throws SimpleXMLParserDocumentException
+	{
+		this( null, _input_stream );
+	}
+	
+	public
+	SimpleXMLParserDocumentImpl(
+		URL				_source_url,
+		InputStream		_input_stream )
 		
 		throws SimpleXMLParserDocumentException
 	{
-		create( input_stream );
+		source_url		= _source_url;
+		
+		create( _input_stream );
 	}
 	
 	protected static synchronized DocumentBuilderFactory
@@ -125,8 +150,64 @@ SimpleXMLParserDocumentImpl
 		return( dbf_singleton );
 	}
 	
-	protected void
+	private void
 	create(
+		InputStream		_input_stream )
+		
+		throws SimpleXMLParserDocumentException
+	{
+			// make sure we can mark the stream to permit later recovery if needed
+		
+		if ( !_input_stream.markSupported()){
+			
+			_input_stream = new BufferedInputStream( _input_stream );
+		}
+		
+		_input_stream.mark( 100*1024 );
+		
+			// prevent the parser from screwing with our stream by closing it
+		
+		UncloseableInputStream	uc_is = new UncloseableInputStream( _input_stream );
+		
+		try{
+			createSupport( uc_is );
+			
+		}catch( SimpleXMLParserDocumentException e ){
+			
+			String msg = Debug.getNestedExceptionMessage( e );
+			
+			if (	( msg.contains( "entity" ) && msg.contains( "was referenced" )) ||
+					msg.contains( "entity reference" )){
+				
+				try{
+						// nasty hack to try and handle HTML entities that some annoying feeds include :(
+					
+					_input_stream.reset();
+					
+					createSupport( new EntityFudger( _input_stream ));
+					
+					return;
+					
+				}catch( Throwable f ){
+				}
+			}
+			
+			//Debug.out( e );
+			
+			throw( e );
+			
+		}finally{
+			
+			try{
+				_input_stream.close();
+				
+			}catch( Throwable e ){
+			}
+		}
+	}
+	
+	private void
+	createSupport(
 		InputStream		input_stream )
 		
 		throws SimpleXMLParserDocumentException
@@ -161,25 +242,96 @@ SimpleXMLParserDocumentImpl
 						try{
 							URL url  = new URL( systemId );
 							
+							if ( source_url != null ){
+								
+								String net = AENetworkClassifier.categoriseAddress( source_url.getHost());
+								
+								if ( net != AENetworkClassifier.AT_PUBLIC ){
+									
+									if ( AENetworkClassifier.categoriseAddress( url.getHost()) != net ){
+				
+										return new InputSource(	new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes()));
+									}
+								}
+							}
+									
 							String host = url.getHost();
 							
 							InetAddress.getByName( host );
 							
 								// try connecting too as connection-refused will also bork XML parsing
 							
+							InputStream is = null;
+							
 							try{
 								URLConnection con = url.openConnection();
 								
 								con.setConnectTimeout( 15*1000 );
 								con.setReadTimeout( 15*1000 );
 								
-								InputStream is = con.getInputStream();
+								is = con.getInputStream();
+									
+								byte[]	buffer = new byte[32];
+								
+								int	pos = 0;
+								
+								while( pos < buffer.length ){
+									
+									int len = is.read( buffer, pos, buffer.length - pos );
+									
+									if ( len <= 0 ){
 										
-								is.close();
+										break;
+									}
+									
+									pos += len;
+								}
+																
+								String str = new String( buffer, "UTF-8" ).trim().toLowerCase( Locale.US );
 								
+								if ( !str.contains( "<?xml" )){
+									
+										// not straightforward to check for naked DTDs, could be lots of <!-- commentry preamble which of course can occur
+										// in HTML too
+									
+									buffer = new byte[32000];
+									
+									pos = 0;
+									
+									while( pos < buffer.length ){
+										
+										int len = is.read( buffer, pos, buffer.length - pos );
+										
+										if ( len <= 0 ){
+											
+											break;
+										}
+										
+										pos += len;
+									}
+									
+									str += new String( buffer, "UTF-8" ).trim().toLowerCase( Locale.US );
+									
+									if ( str.contains( "<html") && str.contains( "<head" )){
+									
+										throw( new Exception( "Bad DTD" ));
+									}
+								}
 							}catch( Throwable e ){
 								
 								return new InputSource(	new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes()));
+								
+							}finally{
+								
+								if ( is != null ){
+									
+									try{
+										is.close();
+										
+									}catch( Throwable e){
+										
+									}
+								}
 							}
 							return( null );
 							
@@ -222,9 +374,7 @@ SimpleXMLParserDocumentImpl
 			}
 						
 		}catch( Throwable e ){
-			
-			e.printStackTrace();
-			
+						
 			throw( new SimpleXMLParserDocumentException( e ));
 		}
 	}
@@ -385,4 +535,252 @@ SimpleXMLParserDocumentImpl
             throw new SAXException(message,spe);
         }
     }
+    
+    private static class
+    EntityFudger
+    	extends InputStream
+    {
+    	private InputStream		is;
+    	    
+    	char[]	buffer		= new char[16];
+    	int		buffer_pos	= 0;
+    	
+    	char[] 	insertion		= new char[16];
+    	int		insertion_pos	= 0;
+    	int		insertion_len	= 0;
+    	
+    	public
+    	EntityFudger(
+    		InputStream		_is )
+    	{
+    		is		= _is;
+    	}
+    	
+    	@Override
+    	public int 
+    	read() 
+    		throws IOException 
+    	{
+    		if ( insertion_len > 0 ){
+    			
+    			int	result = insertion[ insertion_pos++ ]&0xff;
+    		
+    			if ( insertion_pos == insertion_len ){
+    				
+     				insertion_pos	= 0;
+     				insertion_len	= 0;
+    			}
+    			
+    			return( result );
+    		}
+    		
+    		while( true ){
+    			
+	     		int	b = is.read();
+	     		
+	     		if ( b < 0 ){
+	     			
+	     				// end of file
+	     			
+	     			if ( buffer_pos == 0 ){
+	     			
+	     				return( b );
+	     				
+	     			}else if ( buffer_pos == 1 ){
+	     				
+	     				buffer_pos = 0;
+	     				
+	     				return( buffer[0]&0xff );
+	     				
+	     			}else{
+	     				
+	     				System.arraycopy( buffer, 1, insertion, 0, buffer_pos - 1 );
+	     				
+	     				insertion_len 	= buffer_pos - 1;
+	     				insertion_pos	= 0;
+	     				
+	     				buffer_pos = 0;
+	     				
+	     				return( buffer[0]&0xff );
+	     			}
+	     		}
+	     		
+	     			// normal byte
+	     		
+	     		if ( buffer_pos == 0 ){
+	     			
+	     			if ( b == '&' ){
+	     				
+	     				buffer[ buffer_pos++ ] = (char)b;
+	     				
+	     			}else{
+	     				
+	     				return( b );
+	     			}
+	     			
+	     		}else{
+	     			
+	     			if ( buffer_pos == buffer.length-1 ){
+	     				
+	     					// buffer's full, give up
+	     				
+	     				buffer[ buffer_pos++ ] = (char)b;
+	     				
+	     				System.arraycopy( buffer, 0, insertion, 0, buffer_pos );
+	     				
+	     				buffer_pos		= 0;
+	     				insertion_pos	= 0;
+	     				insertion_len	= buffer_pos;
+	     				
+	     				return( insertion[insertion_pos++] );
+	     				
+	     			}else{
+	     				
+		     			if ( b == ';' ){
+		     				
+		     					// got some kind of reference mebe
+		     				
+		     				buffer[ buffer_pos++ ] = (char)b;
+		     				
+		     				String	ref = new String( buffer, 1, buffer_pos-2 ).toLowerCase( Locale.US );
+		     				
+		     				String	replacement;
+		     				
+		     				if ( 	ref.equals( "amp") 		|| 
+		     						ref.equals( "lt" ) 		|| 
+		     						ref.equals( "gt" ) 		|| 
+		     						ref.equals( "quot" )	|| 
+		     						ref.equals( "apos" ) 	||
+		     						ref.startsWith( "#" )){
+		     					
+		     					replacement = new String( buffer, 0, buffer_pos );
+		     					
+		     				}else{
+		     							     							     					
+			     				int num = Entities.HTML40.entityValue( ref );
+			     					
+		     					if ( num != -1 ){
+		     					
+		     						replacement = "&#" + num + ";";
+		     						
+		     					}else{
+		     						
+		     						replacement = new String( buffer, 0, buffer_pos );
+		     					}
+		     				}
+		     				
+		     				char[] chars = replacement.toCharArray();
+		     				
+		     				System.arraycopy( chars, 0, insertion, 0, chars.length );
+		     				
+		     				buffer_pos		= 0;
+		     				insertion_pos	= 0;
+		     				insertion_len	= chars.length;
+		     				
+		     				return( insertion[insertion_pos++] );
+		     				
+		     			}else{
+		     				
+	     					buffer[ buffer_pos++ ] = (char)b;
+
+		     				char c = (char)b;
+		     				
+		     				if ( !Character.isLetterOrDigit( c )){
+		     						     					
+		     						// handle naked &
+		     					
+		     					if ( buffer_pos == 2 && buffer[0] == '&'){
+		     						
+		     						char[] chars = "&".toCharArray();
+		     						
+		     						System.arraycopy( chars, 0, insertion, 0, chars.length );
+		     						
+		     						buffer_pos		= 0;
+		     						insertion_pos	= 0;
+		     						insertion_len	= chars.length;
+		     						
+		     							// don't forget the char we just read
+		     						
+		     						insertion[insertion_len++] = (char)b;
+		     						
+		     						return( insertion[insertion_pos++] );
+		     						
+		     					}else{
+		     						
+		     							// not a valid entity reference
+		     						
+		    	     				System.arraycopy( buffer, 0, insertion, 0, buffer_pos );
+		    	     				
+		    	     				buffer_pos		= 0;
+		    	     				insertion_pos	= 0;
+		    	     				insertion_len	= buffer_pos;
+		    	     				
+		    	     				return( insertion[insertion_pos++] );
+		     					}
+		     				}
+		     			}
+	     			}
+	     		}
+    		}
+    	}
+
+    	public void 
+    	close() 
+    			
+    		throws IOException
+    	{
+    		is.close();
+    	}
+
+    	public long 
+    	skip(
+    		long n )
+    		
+    		throws IOException
+    	{
+    			// meh, vague attempt here
+    		
+    		if ( insertion_len > 0 ){
+    			
+    				// buffer is currently empty, shove remaining into buffer to unify processing
+    			
+    			int	rem = insertion_len - insertion_pos;
+    			
+    			System.arraycopy( insertion, insertion_pos, buffer, 0, rem );
+    			
+    			insertion_pos 	= 0;
+    			insertion_len	= 0;
+    			
+    			buffer_pos = rem;
+    		}
+    		    		
+    		if ( n <= buffer_pos ){
+    			
+    				// skip is <= buffer contents
+    			
+    			int	rem = buffer_pos - (int)n;
+    			
+      			System.arraycopy( buffer, (int)n, insertion, 0, rem );
+
+      			insertion_pos	= 0;
+      			insertion_len 	= rem;
+      			
+      			return( n );
+    		}
+    		
+    		int	to_skip = buffer_pos;
+    		
+    		buffer_pos	= 0;
+    		
+    		return( is.skip( n - to_skip ) + to_skip );
+    	}
+
+    	public int 
+    	available()
+    	
+    		throws IOException
+    	{
+     		return( buffer_pos + is.available());
+    	}
+    }
 }
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentNodeImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentNodeImpl.java
index 3889cc8..c9d4e4d 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentNodeImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/local/utils/xml/simpleparser/SimpleXMLParserDocumentNodeImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPException.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPException.java
index c5f24c8..5fdca12 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPException.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPException.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPFactory.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPFactory.java
index 86cb36f..599f940 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPFactory.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPFactory.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPObject.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPObject.java
index a0adf09..0c88f9c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPObject.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPObject.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPPluginConfig.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPPluginConfig.java
index e3afa87..7648809 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPPluginConfig.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPPluginConfig.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPPluginInterface.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPPluginInterface.java
index cc52796..9c3ce31 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPPluginInterface.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPPluginInterface.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPReply.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPReply.java
index 23b7395..3883251 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPReply.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPReply.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequest.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequest.java
index 29f4867..bb42a5c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequest.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequest.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestAccessController.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestAccessController.java
index 102b56c..fb5747f 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestAccessController.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestAccessController.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestDispatcher.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestDispatcher.java
index fbf4390..8afaf9c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestDispatcher.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestDispatcher.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestHandler.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestHandler.java
index ac95536..442a861 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestHandler.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/RPRequestHandler.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/disk/RPDiskManagerFileInfo.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/disk/RPDiskManagerFileInfo.java
index 24b9ab4..fe3c5cf 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/disk/RPDiskManagerFileInfo.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/disk/RPDiskManagerFileInfo.java
@@ -1,7 +1,7 @@
 /*
  * Created on 09-May-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownload.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownload.java
index b88b186..a4a4900 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownload.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownload.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -27,8 +28,10 @@ package org.gudy.azureus2.pluginsimpl.remote.download;
  */
 
 import java.io.File;
+import java.util.List;
 import java.util.Map;
 
+import org.gudy.azureus2.plugins.ddb.DistributedDatabase;
 import org.gudy.azureus2.plugins.disk.DiskManager;
 import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.plugins.download.*;
@@ -1096,6 +1099,13 @@ RPDownload
 		throw( new DownloadException( "Not Supported" ));
 	}
 	
+	public List<DistributedDatabase>
+	getDistributedDatabases()
+	{
+		notSupported();
+		return( null );
+	}
+	
 	public byte[]
 	getTorrentHash()
 	{
@@ -1118,5 +1128,10 @@ RPDownload
 		notSupported();
 		
 		return( null );
+	}
+
+	// @see org.gudy.azureus2.plugins.download.Download#getPrimaryFile()
+	public DiskManagerFileInfo getPrimaryFile() {
+		return getDiskManagerFileInfo(0);
 	}    	
 }
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadAnnounceResult.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadAnnounceResult.java
index 50bdb47..23fa075 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadAnnounceResult.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadAnnounceResult.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadManager.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadManager.java
index 545615b..e035391 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadManager.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -499,6 +500,14 @@ RPDownloadManager
 		return( null );
 	}
 	
+	public int 
+	getDownloadStubCount() 
+	{
+		notSupported();
+		
+		return 0;
+	}
+	
 	public void addDownloadStubListener( DownloadStubListener l, boolean inform_of_current ){
 		notSupported();
 	}
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadScrapeResult.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadScrapeResult.java
index b42d305..2a47c46 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadScrapeResult.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadScrapeResult.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadStats.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadStats.java
index 56c742d..d09cce7 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadStats.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/download/RPDownloadStats.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -355,4 +356,11 @@ RPDownloadStats
 	{
 		return bytesUnavailable;
 	}
+
+	// @see org.gudy.azureus2.plugins.download.DownloadStats#getRemainingExcludingDND()
+	public long getRemainingExcludingDND() {
+		notSupported();
+		
+		return( 0 );
+	}
 }
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/ipfilter/RPIPFilter.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/ipfilter/RPIPFilter.java
index 3a41c20..f1c3f1d 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/ipfilter/RPIPFilter.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/ipfilter/RPIPFilter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/ipfilter/RPIPRange.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/ipfilter/RPIPRange.java
index aa0ab56..e2e0899 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/ipfilter/RPIPRange.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/ipfilter/RPIPRange.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPInternalProcessException.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPInternalProcessException.java
index 0be16eb..f0d0666 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPInternalProcessException.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPInternalProcessException.java
@@ -1,7 +1,7 @@
 /**
  * Created on 10-Jan-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.pluginsimpl.remote.rpexceptions;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPMethodAccessDeniedException.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPMethodAccessDeniedException.java
index 54f1934..dd591d7 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPMethodAccessDeniedException.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPMethodAccessDeniedException.java
@@ -1,7 +1,7 @@
 /**
  * Created on 10-Jan-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.pluginsimpl.remote.rpexceptions;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPNoObjectIDException.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPNoObjectIDException.java
index 3a40ff8..1c90281 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPNoObjectIDException.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPNoObjectIDException.java
@@ -1,7 +1,7 @@
 /**
  * Created on 10-Jan-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.pluginsimpl.remote.rpexceptions;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPObjectNoLongerExistsException.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPObjectNoLongerExistsException.java
index 4466e25..a137f4a 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPObjectNoLongerExistsException.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPObjectNoLongerExistsException.java
@@ -1,7 +1,7 @@
 /**
  * Created on 10-Jan-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.pluginsimpl.remote.rpexceptions;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPThrowableAsReplyException.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPThrowableAsReplyException.java
index f08178f..da61e6f 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPThrowableAsReplyException.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/rpexceptions/RPThrowableAsReplyException.java
@@ -1,7 +1,7 @@
 /**
  * Created on 10-Jan-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.pluginsimpl.remote.rpexceptions;
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrent.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrent.java
index 1aee2ca..31bc013 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrent.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrent.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrentDownloader.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrentDownloader.java
index 54fdfae..a4c1a37 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrentDownloader.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrentDownloader.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrentManager.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrentManager.java
index 7c15ee4..fa7ce65 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrentManager.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/torrent/RPTorrentManager.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/tracker/RPTracker.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/tracker/RPTracker.java
index 17647ea..afb7f7c 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/tracker/RPTracker.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/tracker/RPTracker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -30,12 +27,12 @@ package org.gudy.azureus2.pluginsimpl.remote.tracker;
 
 import java.net.InetAddress;
 import java.net.URL;
+import java.util.Map;
 
 import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.pluginsimpl.remote.torrent.RPTorrent;
 import org.gudy.azureus2.plugins.tracker.*;
 import org.gudy.azureus2.plugins.tracker.web.*;
-
 import org.gudy.azureus2.pluginsimpl.remote.*;
 
 
@@ -239,6 +236,21 @@ RPTracker
 		return( null );
 	}
     
+    public TrackerWebContext
+    createWebContext(
+    	String					name,
+    	int						port,
+		int						protocol,
+		InetAddress				bind_ip,
+		Map<String,Object>		properties )
+    
+    	throws TrackerException
+	{	
+    	notSupported();
+		
+		return( null );
+	}
+    
     public void
     addListener(
    		TrackerListener		listener )
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/tracker/RPTrackerTorrent.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/tracker/RPTrackerTorrent.java
index 218aa99..a72d93f 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/tracker/RPTrackerTorrent.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/tracker/RPTrackerTorrent.java
@@ -1,7 +1,7 @@
 /*
  * Created on 21-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/utils/RPShortCuts.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/utils/RPShortCuts.java
index b938dec..7c0e913 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/utils/RPShortCuts.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/remote/utils/RPShortCuts.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/PluginUpdatePlugin.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/PluginUpdatePlugin.java
index 65f28da..dcbd3ad 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/PluginUpdatePlugin.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/PluginUpdatePlugin.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -864,6 +861,7 @@ PluginUpdatePlugin
 								checker,
 								plugin_id + "/" + plugin_names,
 								update_d,
+								az_plugin_version,
 								sf_plugin_version,
 								alternate_rdl,
 								sf_plugin_download.toLowerCase().endsWith(".jar"),
@@ -906,7 +904,8 @@ PluginUpdatePlugin
 		final UpdateChecker				checker,
 		final String					update_name,
 		final String[]					update_details,
-		final String					version,
+		final String					old_version,
+		final String					new_version,
 		final ResourceDownloader		resource_downloader,
 		final boolean					is_jar,
 		final int						restart_type,
@@ -915,7 +914,8 @@ PluginUpdatePlugin
 		final Update update = checker.addUpdate(
 				update_name,
 				update_details,
-				version,
+				old_version,
+				new_version,
 				resource_downloader,
 				restart_type );
 
@@ -962,7 +962,8 @@ PluginUpdatePlugin
 								pi_for_update,
 								restart_type == Update.RESTART_REQUIRED_NO,
 								is_jar,
-								version, 
+								old_version,
+								new_version, 
 								data,
 								verify );
 						
@@ -998,14 +999,15 @@ PluginUpdatePlugin
 		PluginInterface		plugin,		// note this will be first one if > 1 defined
 		boolean				unloadable,
 		boolean				is_jar,		// false -> zip 
-		String				version,
+		String				old_version,
+		String				new_version,
 		InputStream			data,
 		boolean				verify )
 	{
 		log.log( LoggerChannel.LT_INFORMATION,
-				 "Installing plugin '" + update.getName() + "', version " + version );
+				 "Installing plugin '" + update.getName() + "', version " + new_version );
 
-		String	target_version = version.endsWith("_CVS")?version.substring(0,version.length()-4):version;
+		String	target_version = new_version.endsWith("_CVS")?new_version.substring(0,new_version.length()-4):new_version;
 
 		UpdateInstaller	installer	= null;
 		
@@ -1027,7 +1029,7 @@ PluginUpdatePlugin
 				
 				log.log( LoggerChannel.LT_INFORMATION, "    This is a built-in plugin, updating core" );
 
-				CorePatchChecker.patchAzureus2( update.getCheckInstance(), data, plugin.getPluginID() + "_" + version, log );
+				CorePatchChecker.patchAzureus2( update.getCheckInstance(), data, plugin.getPluginID() + "_" + new_version, log );
 				
 					// always need to restart for this
 				
@@ -1569,24 +1571,28 @@ PluginUpdatePlugin
 									try{
 										FileInputStream fis = new FileInputStream( origin );
 										
-										old_props.load( fis );
-										
 										try{
+											old_props.load( fis );
+										
+										}catch( Throwable e ){
+											
+										}finally{
+											
 											fis.close();
 											
-										}catch( Throwable e ){
 										}
 										
 										fis = new FileInputStream( final_target );
 										
-										new_props.load( fis );
-								
 										try{
-											fis.close();
-											
+											new_props.load( fis );
+								
 										}catch( Throwable e ){
+											
+										}finally{
+											
+											fis.close();											
 										}
-										
 									}catch( Throwable e ){
 										
 										Debug.printStackTrace( e );
@@ -1894,7 +1900,7 @@ PluginUpdatePlugin
 			
 			if ( update_txt_found || b_disable == null || !b_disable ){
 				
-				String msg =   "Version " + version + " of plugin '" + update.getName() + "' " +
+				String msg =   "Version " + new_version + " of plugin '" + update.getName() + "' " +
 								"installed successfully";
 	
 				if ( update_txt_found ){
@@ -1920,7 +1926,7 @@ PluginUpdatePlugin
 			
 		}catch( Throwable e ){
 					
-			String msg =   "Version " + version + " of plugin '" + 	update.getName() + "' " +
+			String msg =   "Version " + new_version + " of plugin '" + 	update.getName() + "' " +
 							"failed to install - " + (e.getMessage());
 		
 			log.logAlertRepeatable( LoggerChannel.LT_ERROR, msg );
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetails.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetails.java
index 48e9510..00cbaa1 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetails.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetails.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsException.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsException.java
index 3eefd0c..8c71d47 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsException.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsException.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoader.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoader.java
index 253cd84..fe7840d 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoader.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoader.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoaderFactory.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoaderFactory.java
index 16a0554..3ecab82 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoaderFactory.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoaderFactory.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoaderListener.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoaderListener.java
index b3231ad..fe997d7 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoaderListener.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/SFPluginDetailsLoaderListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsImpl.java
index 1224047..1be5936 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsLoaderImpl.java b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsLoaderImpl.java
index 775b559..91ecade 100644
--- a/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsLoaderImpl.java
+++ b/azureus2/src/org/gudy/azureus2/pluginsimpl/update/sf/impl2/SFPluginDetailsLoaderImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/common/IUserInterface.java b/azureus2/src/org/gudy/azureus2/ui/common/IUserInterface.java
index 3319438..d98367e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/common/IUserInterface.java
+++ b/azureus2/src/org/gudy/azureus2/ui/common/IUserInterface.java
@@ -3,7 +3,7 @@
  *
  * Created on 9. Oktober 2003, 00:07
  *
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -16,9 +16,6 @@
  * 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.common;
diff --git a/azureus2/src/org/gudy/azureus2/ui/common/UIImageRepository.java b/azureus2/src/org/gudy/azureus2/ui/common/UIImageRepository.java
index 1e24c01..5ece080 100644
--- a/azureus2/src/org/gudy/azureus2/ui/common/UIImageRepository.java
+++ b/azureus2/src/org/gudy/azureus2/ui/common/UIImageRepository.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/common/UITemplate.java b/azureus2/src/org/gudy/azureus2/ui/common/UITemplate.java
index 10b2e2c..c1b3f94 100644
--- a/azureus2/src/org/gudy/azureus2/ui/common/UITemplate.java
+++ b/azureus2/src/org/gudy/azureus2/ui/common/UITemplate.java
@@ -2,7 +2,7 @@
  * UITemplate.java
  *
  * Created on 26. Oktober 2003, 22:40
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.common;
diff --git a/azureus2/src/org/gudy/azureus2/ui/common/UserInterfaceFactory.java b/azureus2/src/org/gudy/azureus2/ui/common/UserInterfaceFactory.java
index b6d4220..1b8847b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/common/UserInterfaceFactory.java
+++ b/azureus2/src/org/gudy/azureus2/ui/common/UserInterfaceFactory.java
@@ -2,7 +2,7 @@
  * UserInterfaceFactory.java
  *
  * Created on 9. Oktober 2003, 00:33
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.common;
diff --git a/azureus2/src/org/gudy/azureus2/ui/common/util/MenuItemManager.java b/azureus2/src/org/gudy/azureus2/ui/common/util/MenuItemManager.java
index f76cd05..abc1ed0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/common/util/MenuItemManager.java
+++ b/azureus2/src/org/gudy/azureus2/ui/common/util/MenuItemManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 6 Feb 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,20 +14,17 @@
  * 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.common.util;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.*;
 
 import org.gudy.azureus2.core3.util.AEMonitor;
 import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.ui.menus.MenuContext;
 import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
+import org.gudy.azureus2.pluginsimpl.local.ui.menus.MenuContextImpl;
 
 /**
  * Similar to TableContextMenuManager - this keeps references to created menu
@@ -102,6 +99,10 @@ public class MenuItemManager {
 		if (menu_item_map != null) {menu_item_map.remove(item.getResourceKey());}
 	}
 
+	/**
+	 * See {@link MenuManager} for MENU_ Constants.<BR>
+	 * For {@link MenuContext}, use the hack {@link MenuContextImpl#context}
+	 */
 	public MenuItem[] getAllAsArray(String sMenuID) {
 		if (sMenuID != null) {
 			triggerMenuItemQuery(sMenuID);
@@ -120,6 +121,10 @@ public class MenuItemManager {
 		return l.toArray(new MenuItem[l.size()]);
 	}
 	
+	/**
+	 * See {@link MenuManager} for MENU_ Constants.<BR>
+	 * For {@link MenuContext}, use the hack {@link MenuContextImpl#context}
+	 */
 	public MenuItem[] getAllAsArray(String[] menu_ids) {
 		ArrayList<MenuItem> l  = new ArrayList<MenuItem>();
 		for (int i=0; i<menu_ids.length; i++) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/common/util/MenuItemManagerListener.java b/azureus2/src/org/gudy/azureus2/ui/common/util/MenuItemManagerListener.java
index 47e70d4..8b28616 100644
--- a/azureus2/src/org/gudy/azureus2/ui/common/util/MenuItemManagerListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/common/util/MenuItemManagerListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Nov 15, 2010
  *
- * Copyright 2010 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/archive.png b/azureus2/src/org/gudy/azureus2/ui/icons/archive.png
new file mode 100644
index 0000000..a23514b
Binary files /dev/null and b/azureus2/src/org/gudy/azureus2/ui/icons/archive.png differ
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/downarrow.png b/azureus2/src/org/gudy/azureus2/ui/icons/downarrow.png
new file mode 100644
index 0000000..a6618b3
Binary files /dev/null and b/azureus2/src/org/gudy/azureus2/ui/icons/downarrow.png differ
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/icons.properties b/azureus2/src/org/gudy/azureus2/ui/icons/icons.properties
index 4b0f441..ad2d223 100644
--- a/azureus2/src/org/gudy/azureus2/ui/icons/icons.properties
+++ b/azureus2/src/org/gudy/azureus2/ui/icons/icons.properties
@@ -80,6 +80,11 @@ 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
 
+net_I2P_s=org/gudy/azureus2/ui/icons/net_I2P_s.png
+net_I2P_b=org/gudy/azureus2/ui/icons/net_I2P_b.png
+net_Tor_s=org/gudy/azureus2/ui/icons/net_Tor_s.png
+net_Tor_b=org/gudy/azureus2/ui/icons/net_Tor_b.png
+
 transparent=org/gudy/azureus2/ui/icons/transparent16x16.png
 
 dl_bar_end=org/gudy/azureus2/ui/icons/dl_bar_end.png
@@ -104,6 +109,7 @@ alignright=org/gudy/azureus2/ui/icons/alignright.png
 tick_mark=com/aelitis/azureus/ui/images/success.png
 cross_mark=com/aelitis/azureus/ui/images/failure.png
 check_yes=com/aelitis/azureus/ui/images/check-yes.png
+check_ro_yes=com/aelitis/azureus/ui/images/check-ro-yes.png
 check_no=com/aelitis/azureus/ui/images/check-no.png
 
 pair_sb_idle=org/gudy/azureus2/ui/icons/statusbar/pa_idle.png
@@ -115,6 +121,14 @@ st_net_green=org/gudy/azureus2/ui/icons/statusbar/st_net_green.png
 st_net_yellow=org/gudy/azureus2/ui/icons/statusbar/st_net_yellow.png
 st_net_red=org/gudy/azureus2/ui/icons/statusbar/st_net_red.png
 
+dchat_gray=org/gudy/azureus2/ui/icons/statusbar/dchat_gray.png
+dchat_gray_text=org/gudy/azureus2/ui/icons/statusbar/dchat_gray_text.png
+dchat_green=org/gudy/azureus2/ui/icons/statusbar/dchat_green.png
+
+archive=org/gudy/azureus2/ui/icons/archive.png
+popout_window=org/gudy/azureus2/ui/icons/popout_win.png
+menu_down=org/gudy/azureus2/ui/icons/downarrow.png
+
 #		if ( Utils.isAZ2UI()){ 
 #			addPath("org/gudy/azureus2/ui/icons/recheck.gif", "progress_retry");
 #			addPath("org/gudy/azureus2/ui/icons/stop.gif",    "progress_cancel");
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/net_I2P_b.png b/azureus2/src/org/gudy/azureus2/ui/icons/net_I2P_b.png
new file mode 100644
index 0000000..7edc00c
Binary files /dev/null and b/azureus2/src/org/gudy/azureus2/ui/icons/net_I2P_b.png differ
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/net_I2P_s.png b/azureus2/src/org/gudy/azureus2/ui/icons/net_I2P_s.png
new file mode 100644
index 0000000..369b22a
Binary files /dev/null and b/azureus2/src/org/gudy/azureus2/ui/icons/net_I2P_s.png differ
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/net_Tor_b.png b/azureus2/src/org/gudy/azureus2/ui/icons/net_Tor_b.png
new file mode 100644
index 0000000..63f21df
Binary files /dev/null and b/azureus2/src/org/gudy/azureus2/ui/icons/net_Tor_b.png differ
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/net_Tor_s.png b/azureus2/src/org/gudy/azureus2/ui/icons/net_Tor_s.png
new file mode 100644
index 0000000..3eca3ee
Binary files /dev/null and b/azureus2/src/org/gudy/azureus2/ui/icons/net_Tor_s.png differ
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/popout_win.png b/azureus2/src/org/gudy/azureus2/ui/icons/popout_win.png
new file mode 100644
index 0000000..2ebf935
Binary files /dev/null and b/azureus2/src/org/gudy/azureus2/ui/icons/popout_win.png differ
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/statusbar/dchat_gray.png b/azureus2/src/org/gudy/azureus2/ui/icons/statusbar/dchat_gray.png
new file mode 100644
index 0000000..ab29daf
Binary files /dev/null and b/azureus2/src/org/gudy/azureus2/ui/icons/statusbar/dchat_gray.png differ
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/statusbar/dchat_gray_text.png b/azureus2/src/org/gudy/azureus2/ui/icons/statusbar/dchat_gray_text.png
new file mode 100644
index 0000000..d827bc3
Binary files /dev/null and b/azureus2/src/org/gudy/azureus2/ui/icons/statusbar/dchat_gray_text.png differ
diff --git a/azureus2/src/org/gudy/azureus2/ui/icons/statusbar/dchat_green.png b/azureus2/src/org/gudy/azureus2/ui/icons/statusbar/dchat_green.png
new file mode 100644
index 0000000..1352673
Binary files /dev/null and b/azureus2/src/org/gudy/azureus2/ui/icons/statusbar/dchat_green.png differ
diff --git a/azureus2/src/org/gudy/azureus2/ui/none/Main.java b/azureus2/src/org/gudy/azureus2/ui/none/Main.java
index fed22e5..02ca0fe 100644
--- a/azureus2/src/org/gudy/azureus2/ui/none/Main.java
+++ b/azureus2/src/org/gudy/azureus2/ui/none/Main.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle.properties b/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle.properties
index c552154..ad350ca 100644
--- a/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle.properties
+++ b/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle.properties
@@ -77,3 +77,35 @@ Scrape.status.scraping.queued=Scraping queued...
 Scrape.status.disabled=Scrape Disabled
 Scrape.status.networkdisabled=Network not enabled
 Scrape.status.cached=Cached scrape
+
+# download state tags
+
+tag.type.ds=Download State
+tag.type.ds.init=Initializing
+tag.type.ds.down=Downloading
+tag.type.ds.seed=Seeding
+tag.type.ds.qford=Queued for Download
+tag.type.ds.qfors=Queued for Seeding
+tag.type.ds.stop=Stopped
+tag.type.ds.err=Error
+tag.type.ds.act=Active
+tag.type.ds.pau=Paused
+tag.type.ds.inact=Inactive
+tag.type.ds.comp=Complete
+tag.type.ds.incomp=Incomplete
+
+# predefined manual tags
+
+tag.type.man.vhdn=Vuze HD Network
+tag.type.man.featcon=Featured Content
+
+# auto category tags
+
+Categories.all=All
+Categories.uncategorized=Uncategorized
+
+# download manager errors
+
+DownloadManager.error.datamissing=Data Missing
+DownloadManager.error.badsize=Incorrect Size
+DownloadManager.error.filenotfound=File Not Found
diff --git a/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle_eu.properties b/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle_eu.properties
new file mode 100644
index 0000000..8d96df1
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle_eu.properties
@@ -0,0 +1,83 @@
+Formats.units.alot=Pilo bat\!\!\!
+tps.type.pex=PEX
+MagnetURLHandler.report.no_sources=ez da iturbururik aurkitu torrentarentzat
+tps.incoming.details=Oraingoa\: TCP \=%1, UDP \=%2; Guztira inoiz\=%3
+Categories.all=Guztiak
+DownloadManager.error.badsize=Neurri Okerra
+tag.type.ds.inact=Jardungabe
+Scrape.status.error=Zuritze Akatsa\:
+tps.status.unavailable=Ez dago eskuragarri
+Scrape.status.error.nohash=Hasha ez dago erantzunean.
+tps.lan.details=%1 tokiko bezero aurkituta
+Formats.units.TiB=TiB
+Formats.units.Tibit=Tibit
+MagnetPlugin.report.downloading=%1-tik jeisten
+tag.type.ds.pau=Pausatuta
+Scrape.status.nextScrapeAt=Hurrengo zuritzea %1
+MagnetPlugin.report.searching=bilatzen...
+MagnetPlugin.decentral_backup_disabled=<deszentralizatutako babeskopia ezgaituta>
+Scrape.status.scraping=Zuritzen...
+tag.type.ds=Jeisketa Egoera
+tag.type.ds.down=Jeisten
+tag.type.ds.act=Jardunean
+tps.tracker.cache=Hartzaile katxea
+tag.type.ds.incomp=Osatugabe
+Scrape.status.scraping.queued=Zuritzea lerrokatuta
+DHTView.activity.status.false=Ekinean
+DownloadManager.error.datamissing=Datuak Ez daude
+tps.tracker.cache1=Hartzaile katxea\: erabilita\=%1
+Formats.units.MiB=MiB
+MagnetPlugin.use.md.download.name=Metadatutak %1-tik jeitsita
+tag.type.man.vhdn=Vuze HD Sarea
+Scrape.status.disabled=Zuritzea Ezgaituta
+MagnetPlugin.report.waiting_ddb=DDB abiatzearen zain...
+DownloadManager.error.filenotfound=Agiria Ez da Aurkitu
+Formats.units.KiB=KiB
+Formats.units.bit=bit
+Formats.units.Mibit=Mibit
+Formats.units.B=B
+MagnetPlugin.report.tunnel=tuneltuta %1-ra
+tag.type.ds.qfors=Emaritzarako Lerrokatuta
+MagnetURLHandler.report.torrent_size=torrentaren neurria\: %1
+Formats.units.TB=TB
+tps.pex.details=%1 hartzailera elkartuta (egiteke\: pex\=%2, besteak\=%3)
+Scrape.status.ok=Zuritzea Ongi
+MagnetPlugin.private_torrent=<torrent pribatua>
+Formats.units.persec=/s
+tps.type.plugin=Plugina
+Formats.units.GiB=GiB
+tag.type.ds.qford=Jeisteko Lerrokatuta
+MagnetURLHandler.report.error=akatsa %1
+Scrape.status.error.invalid=Erantzun baliogabea.
+Formats.units.kbit=kbit
+Scrape.status.cached=Katxeatutako zuritzea
+Formats.units.GB=GB
+MagnetPlugin.report.alive=%1 bizirik dago
+Formats.units.Gibit=Gibit
+TrackerClient.announce.warningmessage='%1'-ko aztarnariak '%2' kontuz oharra itzuli du
+Scrape.status.initializing=Zuritzearen zain...
+Formats.units.MB=MB
+tps.status.available=Eskuragarri
+Formats.units.Gbit=Gbit
+MagnetPlugin.report.found=aurkituta %1
+Categories.uncategorized=Kategoriagabea
+tag.type.ds.init=Abiatzen
+Scrape.status.error.badURL=Iragarritako URL-ak ez ditu zuritze zehaztapenak jarraitzen.
+Formats.units.kB=kB
+tag.type.ds.err=Akatsa
+MagnetPlugin.report.error=%1 akatsa
+Formats.units.Mbit=Mbit
+tag.type.man.featcon=Ezaugarri Nagusiak
+dht.status.disabled=Ezgaituta, banatutako datubasea ez dago eskuragarri
+tag.type.ds.stop=Geldituta
+MagnetPlugin.report.dead=%1 hilda dago
+Formats.units.Kibit=Kibit
+MagnetPlugin.decentral_disabled=<deszentralizatutako aztarnaketa ezgaituta>
+Scrape.status.networkdisabled=Sarea ez dago gaituta
+tag.type.ds.comp=Osoa
+Formats.units.KB=KB
+tps.type.dht=DHT
+MagnetURLHandler.report.percent=osatuta\: %1%
+tag.type.ds.seed=Emaritzen
+Formats.units.Tbit=Tbit
+tps.type.incoming=Barrurakoa
diff --git a/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle_fr_FR.properties b/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle_fr_FR.properties
new file mode 100644
index 0000000..9e2208f
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle_fr_FR.properties
@@ -0,0 +1,80 @@
+Formats.units.alot=Beaucoup \!
+tps.type.pex=PEX
+MagnetURLHandler.report.no_sources=aucune source trouv\u00E9s pour ce torrent
+tps.incoming.details=Courant \: TCP\=%1 , UDP\=%2; Total jamais\=%3
+Categories.all=Tous
+tag.type.ds.inact=Inactif
+Scrape.status.error=Erreur de scraping \:
+tps.status.unavailable=Indisponible
+Scrape.status.error.nohash=Hash manquant dans la r\u00E9ponse .
+tps.lan.details=%1 clients locaux d\u00E9couverts
+Formats.units.TiB=Tio
+Formats.units.Tibit=Tibit
+MagnetPlugin.report.downloading=t\u00E9l\u00E9charger depuis %1
+tag.type.ds.pau=Pause
+Scrape.status.nextScrapeAt=Prochain scrape \u00E0 %1
+MagnetPlugin.report.searching=recherche...
+MagnetPlugin.decentral_backup_disabled=<sauvegarde decentralis\u00E9e d\u00E9sactiv\u00E9e>
+Scrape.status.scraping=Scraping...
+tag.type.ds=\u00C9tat du t\u00E9l\u00E9chargement
+tag.type.ds.down=T\u00E9l\u00E9chargement
+tag.type.ds.act=Actif
+tps.tracker.cache=Cache de pair
+tag.type.ds.incomp=Incomplet
+Scrape.status.scraping.queued=Scraping en attente...
+DHTView.activity.status.false=En marche
+tps.tracker.cache1=Cache de pair\: utilis\u00E9\=%1
+Formats.units.MiB=Mio
+MagnetPlugin.use.md.download.name=Metadata pour %1
+tag.type.man.vhdn=R\u00E9seau HD de Vuze\u2122
+Scrape.status.disabled=Scrape d\u00E9sactiv\u00E9
+MagnetPlugin.report.waiting_ddb=attendre l'initialisation de la base de donn\u00E9es distribu\u00E9es...
+Formats.units.KiB=Kio
+Formats.units.bit=bit
+Formats.units.Mibit=Mibit
+Formats.units.B=o
+MagnetPlugin.report.tunnel=tunneling \u00E0 %1
+tag.type.ds.qfors=En attente pour le seeding
+MagnetURLHandler.report.torrent_size=taille de torrent \: %1
+Formats.units.TB=To
+tps.pex.details=Connect\u00E9 \u00E0 %1 pairs (en attente\: pex\=%2 , autre\=%3)
+Scrape.status.ok=Scrape OK
+Formats.units.persec=/s
+MagnetPlugin.private_torrent=<torrent priv\u00E9>
+tps.type.plugin=Plugin
+Formats.units.GiB=Gio
+tag.type.ds.qford=En attente pour le t\u00E9l\u00E9chargement
+MagnetURLHandler.report.error=erreur %1
+Scrape.status.error.invalid=R\u00E9ponse Valide.
+Formats.units.kbit=kbit
+Scrape.status.cached=Scrape en cache
+Formats.units.GB=Go
+MagnetPlugin.report.alive=%1 est en vie
+Formats.units.Gibit=Gibit
+TrackerClient.announce.warningmessage=Tracker pour ' %1' a donn\u00E9 un avertissement '%2'
+Scrape.status.initializing=Attente du scraping...
+Formats.units.MB=Mo
+tps.status.available=Disponible
+Formats.units.Gbit=Gbit
+MagnetPlugin.report.found=trouv\u00E9 %1
+Categories.uncategorized=Sans cat\u00E9gorie
+tag.type.ds.init=Initialisation
+Scrape.status.error.badURL=L'URL d'annonce ne suit pas les sp\u00E9cifications scrape.
+Formats.units.kB=ko
+tag.type.ds.err=Erreur
+MagnetPlugin.report.error=erreur %1
+Formats.units.Mbit=Mbit
+tag.type.man.featcon=Contenu s\u00E9lectionn\u00E9e
+dht.status.disabled=D\u00E9sactiv\u00E9e , base de donn\u00E9es distribu\u00E9e non disponible
+tag.type.ds.stop=Arr\u00EAt\u00E9
+MagnetPlugin.report.dead=%1 est mort
+Formats.units.Kibit=Kibit
+MagnetPlugin.decentral_disabled=<decentralised disabled> suivi
+Scrape.status.networkdisabled=R\u00E9seau non activ\u00E9
+tag.type.ds.comp=Termin\u00E9
+Formats.units.KB=Ko
+tps.type.dht=DHT
+MagnetURLHandler.report.percent=termin\u00E9e \: %1%
+Formats.units.Tbit=Tbit
+tag.type.ds.seed=Seeding
+tps.type.incoming=Entrant
diff --git a/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle_pt_BR.properties b/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle_pt_BR.properties
new file mode 100644
index 0000000..e3ae18a
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/none/internat/MessagesBundle_pt_BR.properties
@@ -0,0 +1,83 @@
+Formats.units.alot=Um bocado\!\!\!
+tps.type.pex=PEX
+MagnetURLHandler.report.no_sources=nenhuma fonte encontrada para o torrent
+tps.incoming.details=Atual\: TCP\=%1, UDP\=%2; Total de sempre\=%3
+Categories.all=Tudo
+DownloadManager.error.badsize=Tamanho incorreto
+tag.type.ds.inact=Inativo
+Scrape.status.error=Erro de Scrape\:
+tps.status.unavailable=Indispon\u00EDvel
+Scrape.status.error.nohash=Hash ausente para resposta.
+tps.lan.details=%1 clientes locais descobertos
+Formats.units.TiB=TiB
+Formats.units.Tibit=Tibit
+MagnetPlugin.report.downloading=baixando de %1
+tag.type.ds.pau=Pausado
+Scrape.status.nextScrapeAt=Pr\u00F3ximo scrape em %1
+MagnetPlugin.report.searching=Procurando ...
+MagnetPlugin.decentral_backup_disabled=<descentralizado backup desativado>
+Scrape.status.scraping=Scraping ...
+tag.type.ds=Estado do Download
+tag.type.ds.down=Baixando
+tag.type.ds.act=Ativo
+tps.tracker.cache=Cache de Peers
+tag.type.ds.incomp=Incompleto
+Scrape.status.scraping.queued=Scraping na fila...
+DHTView.activity.status.false=Executando
+DownloadManager.error.datamissing=Dados Perdidos
+tps.tracker.cache1=Cache de Peers usado \=%1
+Formats.units.MiB=MiB
+MagnetPlugin.use.md.download.name=Baixar metadados para %1
+tag.type.man.vhdn=Rede HD Vuze
+Scrape.status.disabled=Scrape Desativado
+MagnetPlugin.report.waiting_ddb=espera para inicializa\u00E7\u00E3o DDB ...
+DownloadManager.error.filenotfound=Arquivo N\u00E3o Encontrado
+Formats.units.KiB=KiB
+Formats.units.bit=bit
+Formats.units.Mibit=Mibit
+Formats.units.B=b
+MagnetPlugin.report.tunnel=tunelamento para %1
+tag.type.ds.qfors=Na Fila para Semear
+MagnetURLHandler.report.torrent_size=Tamanho do Torrent\: %1
+Formats.units.TB=TB
+tps.pex.details=Conectados \u00E0 %1 peers (pendentes\: pex\=%2, outros\=%3)
+Scrape.status.ok=Scrape OK
+Formats.units.persec=/s
+MagnetPlugin.private_torrent=<torrent privado>
+tps.type.plugin=Plug-in
+Formats.units.GiB=GiB
+tag.type.ds.qford=Na fila para download
+MagnetURLHandler.report.error=erro %1
+Scrape.status.error.invalid=Resposta Inv\u00E1lida.
+Formats.units.kbit=kbit
+Scrape.status.cached=Scrape em cache
+Formats.units.GB=GB
+MagnetPlugin.report.alive=%1 est\u00E1 vivo
+Formats.units.Gibit=Gibit
+TrackerClient.announce.warningmessage=Rastreador para '%1' retornando alerta '%2'
+Scrape.status.initializing=Esperando o scrape...
+Formats.units.MB=MB
+tps.status.available=Dispon\u00EDvel
+Formats.units.Gbit=Gbit
+MagnetPlugin.report.found=encontrado %1
+Categories.uncategorized=Sem categoria
+tag.type.ds.init=Inicializando
+Scrape.status.error.badURL=A URL do an\u00FAncioL n\u00E3o segue as especifica\u00E7\u00F5es de scrape .
+Formats.units.kB=kB
+tag.type.ds.err=Erro
+MagnetPlugin.report.error=erro %1
+Formats.units.Mbit=Mbit
+tag.type.man.featcon=Conte\u00FAdo em destaque
+dht.status.disabled=Desativada, banco de dados distribu\u00EDdo n\u00E3o dispon\u00EDvel
+tag.type.ds.stop=Parado
+MagnetPlugin.report.dead=%1 est\u00E1 morto
+Formats.units.Kibit=Kibit
+MagnetPlugin.decentral_disabled=<descentralizado rastreamento desativado>
+Scrape.status.networkdisabled=Rede n\u00E3o habilitada
+tag.type.ds.comp=Completo
+tps.type.dht=DHT
+Formats.units.KB=KB
+MagnetURLHandler.report.percent=conclu\u00EDdo \: %1%
+Formats.units.Tbit=Tbit
+tag.type.ds.seed=Semeando
+tps.type.incoming=Entrada
diff --git a/azureus2/src/org/gudy/azureus2/ui/swing/UISwingImageRepository.java b/azureus2/src/org/gudy/azureus2/ui/swing/UISwingImageRepository.java
index 0852fba..f0d7d2f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swing/UISwingImageRepository.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swing/UISwingImageRepository.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/AZProgressBar.java b/azureus2/src/org/gudy/azureus2/ui/swt/AZProgressBar.java
index bfe85be..32248d7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/AZProgressBar.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/AZProgressBar.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/Alerts.java b/azureus2/src/org/gudy/azureus2/ui/swt/Alerts.java
index cc2ee2c..71969b5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/Alerts.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/Alerts.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 1, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/BlockedIpsWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/BlockedIpsWindow.java
index edf2c0e..4320967 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/BlockedIpsWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/BlockedIpsWindow.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/BrowserWrapper.java b/azureus2/src/org/gudy/azureus2/ui/swt/BrowserWrapper.java
new file mode 100644
index 0000000..0c5234b
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/BrowserWrapper.java
@@ -0,0 +1,242 @@
+/*
+ * Created on Oct 2, 2012
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt;
+
+import org.eclipse.swt.browser.CloseWindowListener;
+import org.eclipse.swt.browser.LocationListener;
+import org.eclipse.swt.browser.OpenWindowListener;
+import org.eclipse.swt.browser.ProgressListener;
+import org.eclipse.swt.browser.StatusTextListener;
+import org.eclipse.swt.browser.TitleListener;
+import org.eclipse.swt.browser.WindowEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.util.AEDiagnostics;
+import org.gudy.azureus2.core3.util.Debug;
+
+
+public abstract class 
+BrowserWrapper 
+{
+	public static BrowserWrapper
+	createBrowser(
+		Composite		composite,
+		int				style )
+	{
+			// dump checking is async and might decide to disable the real browser to give it a chance to
+			// complete in case there's a race
+		
+		AEDiagnostics.waitForDumpChecks( 10*1000 );
+		
+		boolean use_fake = COConfigurationManager.getBooleanParameter( "browser.internal.disable" );
+		
+		if ( use_fake ){
+			
+			return( new BrowserWrapperFake( composite, style ));
+			
+		}else{
+		
+			return( new BrowserWrapperSWT( composite, style ));
+		}
+	}
+	
+	protected
+	BrowserWrapper()
+	{
+	}
+	
+	public abstract boolean
+	isFake();
+	
+	public abstract Composite
+	getControl();
+	
+	public abstract void
+	setBrowser(
+		WindowEvent		event );
+	
+	public abstract  void
+	setVisible(
+		boolean		visible );
+	
+	public abstract boolean
+	isVisible();
+	
+	public abstract  boolean
+	isDisposed();
+	
+	public abstract void
+	dispose();
+	
+	public abstract  boolean
+	execute(
+		String		str );
+	
+	public abstract boolean
+	isBackEnabled();
+	
+	public abstract String
+	getUrl();
+	
+	public abstract void
+	setUrl(
+		String		url );
+	
+	public abstract void
+	setText(
+		String		text );
+	
+	public abstract void
+	setData(
+		String		key,
+		Object		value );
+	
+	public abstract Object
+	getData(
+		String	key );
+	
+	public abstract void
+	back();
+	
+	public abstract void
+	refresh();
+	
+	public abstract void
+	update();
+	
+	public abstract Shell
+	getShell();
+	
+	public abstract Display
+	getDisplay();
+	
+	public abstract Composite
+	getParent();
+	
+	public abstract Object
+	getLayoutData();
+	
+	public abstract void
+	setLayoutData(
+		Object	data );
+	
+	public abstract void
+	setFocus();
+	
+	public abstract void
+	addListener(
+		int			type,
+		Listener	l );
+	
+	public abstract void
+	addLocationListener(
+		LocationListener		l );
+	
+	public abstract void
+	removeLocationListener(
+		LocationListener		l );
+	
+	public abstract void
+	addTitleListener(
+		TitleListener		l );
+	
+	public abstract void
+	addProgressListener(
+		ProgressListener		l );
+	
+	public abstract void
+	removeProgressListener(
+		ProgressListener		l );
+	
+	public abstract void
+	addOpenWindowListener(
+		OpenWindowListener		l );
+	
+	public abstract void
+	addCloseWindowListener(
+		CloseWindowListener		l );
+	
+	public abstract void
+	addDisposeListener(
+		DisposeListener		l );
+	
+	public abstract void
+	removeDisposeListener(
+		DisposeListener		l );
+	
+	public abstract void
+	addStatusTextListener(
+		StatusTextListener		l );
+	
+	public abstract void
+	removeStatusTextListener(
+		StatusTextListener		l );
+	
+	public abstract BrowserFunction
+	addBrowserFunction(
+		String				name,
+		BrowserFunction		bf );
+	
+	public static abstract class
+	BrowserFunction
+	{
+		private BrowserFunction		delegate;
+		
+		protected void
+		bind(
+			BrowserFunction		_delegate )
+		{
+			delegate = _delegate;
+		}
+		
+		public abstract Object 
+		function(
+			Object[] arguments );
+
+		public boolean
+		isDisposed()
+		{
+			if ( delegate != null ){
+				
+				return( delegate.isDisposed());
+			}
+			
+			Debug.out( "wrong" );
+			
+			return( false );
+		}
+		
+		public void
+		dispose()
+		{
+			if ( delegate != null ){
+				
+				delegate.dispose();
+			}
+			
+			Debug.out( "wrong" );
+		}
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/BrowserWrapperFake.java b/azureus2/src/org/gudy/azureus2/ui/swt/BrowserWrapperFake.java
new file mode 100644
index 0000000..2392ee8
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/BrowserWrapperFake.java
@@ -0,0 +1,499 @@
+/*
+ * Created on Apr 1, 2015
+ * Created by Paul Gardner
+ * 
+ * Copyright 2015 Azureus Software, 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 org.gudy.azureus2.ui.swt;
+
+import java.util.*;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.CloseWindowListener;
+import org.eclipse.swt.browser.LocationEvent;
+import org.eclipse.swt.browser.LocationListener;
+import org.eclipse.swt.browser.OpenWindowListener;
+import org.eclipse.swt.browser.ProgressEvent;
+import org.eclipse.swt.browser.ProgressListener;
+import org.eclipse.swt.browser.StatusTextListener;
+import org.eclipse.swt.browser.TitleEvent;
+import org.eclipse.swt.browser.TitleListener;
+import org.eclipse.swt.browser.WindowEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+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.mainwindow.ClipboardCopy;
+import org.gudy.azureus2.ui.swt.mainwindow.Colors;
+
+
+public class 
+BrowserWrapperFake
+	extends BrowserWrapper
+{
+	private Composite		parent;
+	
+	private Composite		browser;
+	private Label			link_label;
+	private Label			description_label;
+	
+	private String 			url;
+	private String			description;
+	
+	private List<LocationListener>		location_listeners 	= new ArrayList<LocationListener>();
+	private List<ProgressListener>		progress_listeners 	= new ArrayList<ProgressListener>();
+	private List<TitleListener>			title_listeners 	= new ArrayList<TitleListener>();
+	
+	protected
+	BrowserWrapperFake(
+		Composite		_parent,
+		int				style )
+	{
+		parent	= _parent;
+		
+		browser = new Composite( parent, SWT.NULL );
+		browser.setBackground( Colors.white );
+		
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		browser.setLayout(layout);
+		
+		Label label = new Label(browser, SWT.WRAP);
+		Messages.setLanguageText(label, "browser.internal.disabled.info");
+		label.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ));
+		label.setBackground( Colors.white );
+
+		Composite details = new Composite( browser, SWT.BORDER );
+		layout = new GridLayout();
+		layout.numColumns = 2;
+		details.setLayout(layout);
+		details.setLayoutData( new GridData( GridData.FILL_BOTH ));
+		details.setBackground( Colors.white );
+		
+			// url
+		
+		label = new Label(details, SWT.NULL );
+		label.setText( "URL" );
+		label.setLayoutData( new GridData());
+		label.setBackground( Colors.white );
+		
+		
+		link_label = new Label(details, SWT.NULL);
+		link_label.setText( MessageText.getString( "ConfigView.label.please.visit.here" ));
+		
+		link_label.setCursor(link_label.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
+		link_label.setForeground(Colors.blue);
+		link_label.setBackground( Colors.white );
+		
+		link_label.addMouseListener(new MouseAdapter() {
+			public void mouseDoubleClick(MouseEvent e) {
+				Utils.launch( url );
+			}
+			public void mouseUp(MouseEvent e) {
+				
+				if ( e.button == 1 && e.stateMask != SWT.CONTROL){
+				
+					Utils.launch( url );
+				}
+			}
+		});
+		
+		GridData grid_data = new GridData(GridData.FILL_HORIZONTAL);
+		grid_data.horizontalIndent = 10;
+		link_label.setLayoutData(grid_data);
+		
+		ClipboardCopy.addCopyToClipMenu( 
+			link_label,
+			new ClipboardCopy.copyToClipProvider() {
+				
+				public String getText() {
+					return( url );
+				}
+			});
+		
+			// desc
+		
+		label = new Label(details, SWT.NULL );
+		Messages.setLanguageText(label, "columnChooser.columndescription" );
+		label.setLayoutData( new GridData());
+		label.setBackground( Colors.white );
+
+		description_label = new Label(details, SWT.NULL );
+		description_label.setText( "" );
+		grid_data = new GridData(GridData.FILL_HORIZONTAL);
+		grid_data.horizontalIndent = 10;
+		description_label.setLayoutData( grid_data );
+		description_label.setBackground( Colors.white );
+	}
+	
+	public boolean
+	isFake()
+	{
+		return( true );
+	}
+	
+	public Composite
+	getControl()
+	{
+		return( browser );
+	}
+	
+	public void
+	setBrowser(
+		WindowEvent		event )
+	{
+	}
+	
+	public void
+	setVisible(
+		boolean		visible )
+	{
+		browser.setVisible( visible );
+	}
+	
+	public boolean
+	isVisible()
+	{
+		return( browser.isVisible());
+	}
+	
+	public boolean
+	isDisposed()
+	{
+		return( browser.isDisposed());
+	}
+	
+	public void
+	dispose()
+	{
+		browser.dispose();
+	}
+	
+	public boolean
+	execute(
+		String		str )
+	{
+		return( false );
+	}
+	
+	public boolean
+	isBackEnabled()
+	{
+		return( false );
+	}
+	
+	public String
+	getUrl()
+	{
+		return( url );
+	}
+	
+	public void
+	setUrl(
+		final String		_url )
+	{
+		url		= _url;
+		
+		Utils.execSWTThread(
+			new Runnable()
+			{				
+				public void 
+				run() 
+				{
+					String url_str = _url;
+					
+					int	pos = url_str.indexOf( '?' );
+					
+					if ( pos != -1 ){
+						
+						url_str = url_str.substring( 0, pos );
+					}
+					
+					link_label.setText( url_str );
+
+					browser.layout();
+					
+					for ( LocationListener l: location_listeners ){
+						
+						try{
+							LocationEvent event = new LocationEvent( browser );
+							
+							event.top 		= true;
+							event.location 	= _url;
+							
+							l.changed( event );
+							
+						}catch( Throwable e){
+							
+							Debug.out( e );
+						}
+					}
+					
+					for ( ProgressListener l: progress_listeners ){
+						
+						try{
+							ProgressEvent event = new ProgressEvent( browser );
+							
+							l.completed( event );
+							
+						}catch( Throwable e){
+							
+							Debug.out( e );
+						}
+					}
+					
+					for ( TitleListener l: title_listeners ){
+						
+						try{
+							TitleEvent event = new TitleEvent( browser );
+							
+							event.title = "Browser Disabled";
+							
+							l.changed( event );
+							
+						}catch( Throwable e){
+							
+							Debug.out( e );
+						}
+					}
+				}
+			});
+	}
+	
+	public void
+	setText(
+		String		text )
+	{
+		description	= text;
+				
+		Utils.execSWTThread(
+			new Runnable()
+			{				
+				public void 
+				run() 
+				{					
+					description_label.setText( description );
+
+					browser.layout();
+				}
+			});
+	}
+	
+	public void
+	setData(
+		String		key,
+		Object		value )
+	{
+		browser.setData(key, value);
+	}
+
+	public Object
+	getData(
+		String	key )
+	{
+		return( browser.getData( key ));
+	}
+	
+	public void
+	back()
+	{
+	}
+	
+	public void
+	refresh()
+	{
+	}
+	
+	public void
+	update()
+	{
+		browser.update();
+	}
+	
+	public Shell
+	getShell()
+	{
+		return( browser.getShell());
+	}
+	
+	public Display
+	getDisplay()
+	{
+		return( browser.getDisplay());
+	}
+	
+	public Composite
+	getParent()
+	{
+		return( browser.getParent());
+	}
+	
+	public Object
+	getLayoutData()
+	{
+		return( browser.getLayoutData());
+	}
+	
+	public void
+	setLayoutData(
+		Object	data )
+	{
+		browser.setLayoutData( data );
+	}
+	
+	public void
+	setFocus()
+	{
+		browser.setFocus();
+	}
+	
+	public void
+	addListener(
+		int			type,
+		Listener	l )
+	{
+		browser.addListener( type, l );
+	}
+	
+	public void
+	addLocationListener(
+		LocationListener		l )
+	{
+		location_listeners.add( l );
+	}
+	
+	public void
+	removeLocationListener(
+		LocationListener		l )
+	{
+		location_listeners.remove( l );
+	}
+	
+	public void
+	addTitleListener(
+		TitleListener		l )
+	{
+		title_listeners.add( l );
+	}
+	
+	public void
+	addProgressListener(
+		ProgressListener		l )
+	{
+		progress_listeners.add( l );
+	}
+	
+	public void
+	removeProgressListener(
+		ProgressListener		l )
+	{
+		progress_listeners.remove( l );
+	}
+	
+	public void
+	addOpenWindowListener(
+		OpenWindowListener		l )
+	{
+	}
+	
+	public void
+	addCloseWindowListener(
+		CloseWindowListener		l )
+	{
+	}
+	
+	public void
+	addDisposeListener(
+		DisposeListener		l )
+	{
+		browser.addDisposeListener( l );
+	}
+	
+	public void
+	removeDisposeListener(
+		DisposeListener		l )
+	{
+		browser.removeDisposeListener( l );
+	}
+	
+	public void
+	addStatusTextListener(
+		StatusTextListener		l )
+	{
+	}
+	
+	public void
+	removeStatusTextListener(
+		StatusTextListener		l )
+	{
+	}
+	
+	public BrowserFunction
+	addBrowserFunction(
+		String						name,
+		final BrowserFunction		bf )
+	{	
+		return( new BrowserFunctionFake( bf ));
+	}
+	
+	public static class
+	BrowserFunctionFake
+		extends BrowserFunction
+	{
+		private final BrowserFunction	bf;
+		
+		private boolean	disposed;
+		
+		private 
+		BrowserFunctionFake(
+			BrowserFunction	_bf )
+		{
+			bf		= _bf;
+			
+			bf.bind( this );
+		}
+		
+		public Object 
+		function(
+			Object[] arguments )
+		{
+			return( bf.function( arguments ));
+		}
+
+		public boolean
+		isDisposed()
+		{
+			return( disposed );
+		}
+		
+		public void
+		dispose()
+		{
+			disposed	= true;
+		}
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/BrowserWrapperSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/BrowserWrapperSWT.java
new file mode 100644
index 0000000..318cbdc
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/BrowserWrapperSWT.java
@@ -0,0 +1,345 @@
+/*
+ * Created on Apr 1, 2015
+ * Created by Paul Gardner
+ * 
+ * Copyright 2015 Azureus Software, 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 org.gudy.azureus2.ui.swt;
+
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.browser.CloseWindowListener;
+import org.eclipse.swt.browser.LocationListener;
+import org.eclipse.swt.browser.OpenWindowListener;
+import org.eclipse.swt.browser.ProgressListener;
+import org.eclipse.swt.browser.StatusTextListener;
+import org.eclipse.swt.browser.TitleListener;
+import org.eclipse.swt.browser.WindowEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+
+public class 
+BrowserWrapperSWT
+	extends BrowserWrapper
+{
+	private Browser		browser;
+	
+	protected
+	BrowserWrapperSWT(
+		Composite		composite,
+		int				style )
+	{
+		browser = new Browser( composite, style );
+	}
+	
+	public boolean
+	isFake()
+	{
+		return( false );
+	}
+	public Composite
+	getControl()
+	{
+		return( browser );
+	}
+	
+	public void
+	setBrowser(
+		WindowEvent		event )
+	{
+		event.browser = browser;
+	}
+	
+	public void
+	setVisible(
+		boolean		visible )
+	{
+		browser.setVisible( visible );
+	}
+	
+	public boolean
+	isVisible()
+	{
+		return( browser.isVisible());
+	}
+	
+	public boolean
+	isDisposed()
+	{
+		return( browser.isDisposed());
+	}
+	
+	public void
+	dispose()
+	{
+		browser.dispose();
+	}
+	
+	public boolean
+	execute(
+		String		str )
+	{
+		//System.out.println( "execute: " + str );
+		
+		return( browser.execute( str ));
+	}
+	
+	public boolean
+	isBackEnabled()
+	{
+		return( browser.isBackEnabled());
+	}
+	
+	public String
+	getUrl()
+	{
+		return( browser.getUrl());
+	}
+	
+	public void
+	setUrl(
+		String		url )
+	{
+		browser.setUrl( url );
+	}
+	
+	public void
+	setText(
+		String		text )
+	{
+		browser.setText( text );
+	}
+	
+	public void
+	setData(
+		String		key,
+		Object		value )
+	{
+		browser.setData(key, value);
+	}
+
+	public Object
+	getData(
+		String	key )
+	{
+		return( browser.getData( key ));
+	}
+	
+	public void
+	back()
+	{
+		browser.back();
+	}
+	
+	public void
+	refresh()
+	{
+		browser.refresh();
+	}
+	
+	public void
+	update()
+	{
+		browser.update();
+	}
+	
+	public Shell
+	getShell()
+	{
+		return( browser.getShell());
+	}
+	
+	public Display
+	getDisplay()
+	{
+		return( browser.getDisplay());
+	}
+	
+	public Composite
+	getParent()
+	{
+		return( browser.getParent());
+	}
+	
+	public Object
+	getLayoutData()
+	{
+		return( browser.getLayoutData());
+	}
+	
+	public void
+	setLayoutData(
+		Object	data )
+	{
+		browser.setLayoutData( data );
+	}
+	
+	public void
+	setFocus()
+	{
+		browser.setFocus();
+	}
+	
+	public void
+	addListener(
+		int			type,
+		Listener	l )
+	{
+		browser.addListener( type, l );
+	}
+	
+	public void
+	addLocationListener(
+		LocationListener		l )
+	{
+		browser.addLocationListener( l );
+	}
+	
+	public void
+	removeLocationListener(
+		LocationListener		l )
+	{
+		browser.removeLocationListener( l );
+	}
+	
+	public void
+	addTitleListener(
+		TitleListener		l )
+	{
+		browser.addTitleListener( l );
+	}
+	
+	public void
+	addProgressListener(
+		ProgressListener		l )
+	{
+		browser.addProgressListener( l );
+	}
+	
+	public void
+	removeProgressListener(
+		ProgressListener		l )
+	{
+		browser.removeProgressListener( l );
+	}
+	
+	public void
+	addOpenWindowListener(
+		OpenWindowListener		l )
+	{
+		browser.addOpenWindowListener( l );
+	}
+	
+	public void
+	addCloseWindowListener(
+		CloseWindowListener		l )
+	{
+		browser.addCloseWindowListener( l );
+	}
+	
+	public void
+	addDisposeListener(
+		DisposeListener		l )
+	{
+		browser.addDisposeListener( l );
+	}
+	
+	public void
+	removeDisposeListener(
+		DisposeListener		l )
+	{
+		browser.removeDisposeListener( l );
+	}
+	
+	public void
+	addStatusTextListener(
+		StatusTextListener		l )
+	{
+		browser.addStatusTextListener( l );
+	}
+	
+	public void
+	removeStatusTextListener(
+		StatusTextListener		l )
+	{
+		browser.removeStatusTextListener( l );
+	}
+	
+	public BrowserFunction
+	addBrowserFunction(
+		String						name,
+		final BrowserFunction		bf )
+	{
+		org.eclipse.swt.browser.BrowserFunction swt_bf =
+			new org.eclipse.swt.browser.BrowserFunction(
+				browser,
+				name )
+			{
+				@Override
+				public Object 
+				function(
+					Object[] arguments )
+				{
+					return( bf.function(arguments));
+				}
+			};
+		
+		return( new BrowserFunctionSWT( bf, swt_bf ));
+	}
+	
+	public static class
+	BrowserFunctionSWT
+		extends BrowserFunction
+	{
+		private final BrowserFunction							bf;
+		private final org.eclipse.swt.browser.BrowserFunction	swt_bf;
+		
+		private 
+		BrowserFunctionSWT(
+			BrowserFunction							_bf,
+			org.eclipse.swt.browser.BrowserFunction	_swt_bf )
+		{
+			bf		= _bf;
+			swt_bf 	= _swt_bf;
+			
+			bf.bind( this );
+		}
+		
+		public Object 
+		function(
+			Object[] arguments )
+		{
+			return( bf.function( arguments ));
+		}
+
+		public boolean
+		isDisposed()
+		{
+			return( swt_bf.isDisposed());
+		}
+		
+		public void
+		dispose()
+		{
+			swt_bf.dispose();
+		}
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/CategoryAdderWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/CategoryAdderWindow.java
index c6c3bf2..4ece7ee 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/CategoryAdderWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/CategoryAdderWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on 2 feb. 2004
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/DelayedListenerMultiCombiner.java b/azureus2/src/org/gudy/azureus2/ui/swt/DelayedListenerMultiCombiner.java
index 79dedaf..50d811c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/DelayedListenerMultiCombiner.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/DelayedListenerMultiCombiner.java
@@ -1,10 +1,12 @@
 /**
  * Created on Dec 30, 2010
  *
- * Copyright 2010 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/FileDownloadWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/FileDownloadWindow.java
index 9cfac63..7efd21f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/FileDownloadWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/FileDownloadWindow.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -22,7 +23,6 @@
 package org.gudy.azureus2.ui.swt;
 
 import java.io.File;
-import java.net.URLDecoder;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -40,6 +40,7 @@ import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloader;
 import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderCallBackInterface;
 import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderFactory;
 import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.UrlUtils;
 import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
 import org.gudy.azureus2.ui.swt.progress.*;
 
@@ -116,12 +117,8 @@ public class FileDownloadWindow
 		this.listener = listener;
 		this.request_properties = request_properties;
 
-		try {
-			decoded_url = URLDecoder.decode(original_url, "UTF8");
-		} catch (Throwable e) {
-			decoded_url = original_url;
-
-		}
+		decoded_url = UrlUtils.decodeIfNeeded( original_url );
+		
 		Utils.execSWTThread(new AERunnable() {
 			public void runSupport() {
 				init();
@@ -139,12 +136,8 @@ public class FileDownloadWindow
 		this.force_dialog = force_dialog;
 		this.request_properties = request_properties;
 
-		try {
-			decoded_url = URLDecoder.decode(original_url, "UTF8");
-		} catch (Throwable e) {
-			decoded_url = original_url;
-
-		}
+		decoded_url = UrlUtils.decodeIfNeeded( original_url );
+		
 		Utils.execSWTThread(new AERunnable() {
 			public void runSupport() {
 				init();
@@ -293,8 +286,13 @@ public class FileDownloadWindow
 					return;
 				}
 
-				pReporter.setErrorMessage(MessageText.getString("fileDownloadWindow.state_error")
-						+ downloader.getError());
+				if ( torrentOptions != null && torrentOptions.getHideErrors()){
+					pReporter.setCancelCloses( true );
+					pReporter.cancel();
+				}else{
+					pReporter.setErrorMessage(MessageText.getString("fileDownloadWindow.state_error")
+							+ downloader.getError());
+				}
 				return;
 			case TorrentDownloader.STATE_FINISHED:
 				if (localLastState == state) {
@@ -334,9 +332,20 @@ public class FileDownloadWindow
 			shortURL = url;
 			// truncate any url parameters for display. This has the benefit of hiding additional uninteresting
 			// parameters added to urls to control the download process (e.g. "&pause_on_error" for magnet downloads")
-			int amp_pos = shortURL.indexOf('&');
-			if (amp_pos != -1) {
-				shortURL = shortURL.substring(0, amp_pos + 1) + "...";
+			int trunc_pos = shortURL.indexOf('&');
+			if ( trunc_pos == -1 ){
+				// if this is a magnet link with no added params then we want to retain the xt=... part otherwise
+				// we just end up with 'magnet:...' which looks silly
+				
+				trunc_pos = shortURL.indexOf('?');
+				
+				if ( trunc_pos > 0 && shortURL.charAt(trunc_pos-1) == ':' ){
+					
+					trunc_pos = -1;
+				}
+			}
+			if (trunc_pos != -1) {
+				shortURL = shortURL.substring(0, trunc_pos + 1) + "...";
 			}
 			shortURL = shortURL.replaceAll("&", "&&");
 		}
@@ -360,10 +369,15 @@ public class FileDownloadWindow
 				"dn"
 			};
 			for (String toMatch : titles) {
-				Matcher matcher = Pattern.compile("[?&]" + toMatch + "=(.*)&?",
+				Matcher matcher = Pattern.compile("[?&]" + toMatch + "=([^&]*)",
 						Pattern.CASE_INSENSITIVE).matcher(url);
-				if (matcher.find()) {
-					return matcher.group(1);
+				if (matcher.find()){
+					
+					String file_name = matcher.group(1);
+					
+					file_name = UrlUtils.decode( file_name );
+					
+					return( file_name );
 				}
 			}
 			
@@ -380,7 +394,7 @@ public class FileDownloadWindow
 			
 			String lc_url = url.toLowerCase(MessageText.LOCALE_ENGLISH);
 
-			if ( lc_url.startsWith( "magnet:") || lc_url.startsWith( "dht:" ) || lc_url.startsWith( "bc:" ) || lc_url.startsWith( "bctp:" )){
+			if ( lc_url.startsWith( "magnet:") || lc_url.startsWith( "maggot:") || lc_url.startsWith( "dht:" ) || lc_url.startsWith( "bc:" ) || lc_url.startsWith( "bctp:" )){
 				
 				return( url );
 			}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/ImageRepository.java b/azureus2/src/org/gudy/azureus2/ui/swt/ImageRepository.java
index 5eb56cf..cd8a3a9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/ImageRepository.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/ImageRepository.java
@@ -1,6 +1,6 @@
 /*
  * Created on 29 juin 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
@@ -39,11 +36,12 @@ import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.program.Program;
 import org.eclipse.swt.widgets.*;
-
 import org.gudy.azureus2.core3.peer.PEPeer;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 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.HostNameToIPResolver;
 import org.gudy.azureus2.core3.util.SystemTime;
 import org.gudy.azureus2.plugins.peers.Peer;
 import org.gudy.azureus2.plugins.utils.LocationProvider;
@@ -449,6 +447,8 @@ public class ImageRepository
 		return( getCountryFlag( PluginCoreUtils.unwrap( peer ), small ));
 	}
 	
+	private static Map<String,Image>	net_images = new HashMap<String, Image>();
+	
 	public static Image
 	getCountryFlag(
 		PEPeer		peer,
@@ -470,40 +470,77 @@ public class ImageRepository
 			if ( fp != null ){	
 				
 				try{
-	
-					InetAddress peer_address = InetAddress.getByName( peer.getIp());
+					String ip = peer.getIp();
 					
-					String cc_key = fp.getISO3166CodeForIP( peer_address ) + (small?".s":".l");
-					
-					flag = flag_cache.get( cc_key );
+					if ( HostNameToIPResolver.isDNSName( ip )){
+						
+						InetAddress peer_address = InetAddress.getByName( ip );
 					
-					if ( flag != null ){
+						String cc_key = fp.getISO3166CodeForIP( peer_address ) + (small?".s":".l");
+						
+						flag = flag_cache.get( cc_key );
+						
+						if ( flag != null ){
+						
+							peer.setUserData( peer_key, flag );
+							
+						}else{
 					
-						peer.setUserData( peer_key, flag );
+							InputStream is = fp.getCountryFlagForIP( peer_address, small?0:1 );
+								
+							if ( is != null ){
+								
+								try{
+									flag = new Image( Display.getDefault(), is);
+	
+									//System.out.println( "Created flag image for " + cc_key );
+									
+								}finally{
+									
+									is.close();
+								}
+							}else{
+								
+								flag = flag_none;
+							}
 						
+							flag_cache.put( cc_key, flag );
+						
+							peer.setUserData( peer_key, flag );
+						}
 					}else{
-				
-						InputStream is = fp.getCountryFlagForIP( peer_address, small?0:1 );
+
+						String cat =  AENetworkClassifier.categoriseAddress( ip );
+						
+						if ( cat != AENetworkClassifier.AT_PUBLIC ){
 							
-						if ( is != null ){
+							final String key = "net_" + cat + (small?"_s":"_b" );
 							
-							try{
-								flag = new Image( Display.getDefault(), is);
-
-								//System.out.println( "Created flag image for " + cc_key );
+							Image i = net_images.get( key );
+														
+							if ( i == null ){
 								
-							}finally{
+								Utils.execSWTThread(
+									new Runnable() 
+									{									
+										public void 
+										run() 
+										{
+											Image i = ImageLoader.getInstance().getImage( key );
+											
+											net_images.put( key, i );
+										}
+									},
+									false );
 								
-								is.close();
+								i = net_images.get( key );
 							}
-						}else{
 							
-							flag = flag_none;
+							if ( ImageLoader.isRealImage( i )){
+								
+								return( i );
+							}
 						}
-						
-						flag_cache.put( cc_key, flag );
-						
-						peer.setUserData( peer_key, flag );
 					}
 					
 				}catch( Throwable e ){
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/ImageViewerWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/ImageViewerWindow.java
index 8198bef..44f14ce 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/ImageViewerWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/ImageViewerWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on 2 feb. 2004
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/KeyBindings.java b/azureus2/src/org/gudy/azureus2/ui/swt/KeyBindings.java
index bf5677f..a674af7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/KeyBindings.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/KeyBindings.java
@@ -3,11 +3,12 @@
  * Created : 2005 Jan 7
  * By      : James Yeh
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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;
@@ -347,6 +345,39 @@ public final class KeyBindings
         }
     }
 
+    public static KeyBindingInfo getKeyBindingInfo( String localizationKey)
+    {
+        localizationKey += ".keybinding";
+        final String platformSpecificKey = localizationKey + getPlatformKeySuffix();
+
+        // first, check for platform-specific, localization-specific binding
+        if(MessageText.keyExists(platformSpecificKey))
+        {
+            return( parseKeyBinding(MessageText.getString(platformSpecificKey)));
+        }
+        else if(MessageText.keyExists(localizationKey)) // platform-independent, localization-specific binding
+        {
+        	return( parseKeyBinding(MessageText.getString(localizationKey)));
+        }
+        else if(!MessageText.isCurrentLocale(MessageText.LOCALE_DEFAULT))
+        {
+            // default locale
+
+            // platform-specific first
+            if(MessageText.keyExistsForDefaultLocale(platformSpecificKey))
+            {
+            	return( parseKeyBinding(MessageText.getDefaultLocaleString(platformSpecificKey)));
+            }
+            else if(MessageText.keyExistsForDefaultLocale(localizationKey))
+            {
+                 // default locale, platform-independent
+            	return(  parseKeyBinding(MessageText.getDefaultLocaleString(localizationKey)));
+            }
+        }
+        
+        return( null );
+    }
+    
     /**
      * Helper method to set a keyboard accelerator for a MenuItem. If kbInfo is SWT.NONE, no accelerator will be set.
      * @param menu SWT MenuItem
@@ -393,17 +424,17 @@ public final class KeyBindings
      * level API like JFace or native rendering).
      * </p>
      */
-    private static class KeyBindingInfo
+    public static class KeyBindingInfo
     {
         /**
          * The display name of the accelerator
          */
-        private final String name;
+        public final String name;
 
         /**
          * The SWT keyboard accelerator value
          */
-        private final int accelerator;
+        public final int accelerator;
 
         /**
          * Constructs a new KeyBindingInfo object with the given accelerator name and accelerator value
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/ListenerDMTask.java b/azureus2/src/org/gudy/azureus2/ui/swt/ListenerDMTask.java
new file mode 100644
index 0000000..145d0c5
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/ListenerDMTask.java
@@ -0,0 +1,92 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.swt;
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.Debug;
+
+/**
+ * SWT {@link Listener} that walks through a list of {@link DownloadManager}
+ * objects, executing {@link #run(DownloadManager)} for each.
+ */
+abstract class ListenerDMTask
+	implements Listener
+{
+	private DownloadManager[] dms;
+
+	private boolean ascending;
+
+	private boolean async;
+
+	public ListenerDMTask(DownloadManager[] dms) {
+		this(dms, true);
+	}
+
+	public ListenerDMTask(DownloadManager[] dms, boolean ascending) {
+		this.dms = dms;
+		this.ascending = ascending;
+	}
+
+	public ListenerDMTask(DownloadManager[] dms, boolean ascending, boolean async) {
+		this.dms = dms;
+		this.ascending = ascending;
+		this.async = async;
+	}
+
+	// One of the following methods should be overridden.
+	public void run(DownloadManager dm) {
+	}
+
+	public void run(DownloadManager[] dm) {
+	}
+
+	public void handleEvent(Event event) {
+		if (async) {
+
+			new AEThread2("DMTask:async", true) {
+				public void run() {
+					go();
+				}
+			}.start();
+		} else {
+
+			go();
+		}
+	}
+
+	public void go() {
+		try {
+			DownloadManager dm = null;
+			for (int i = 0; i < dms.length; i++) {
+				dm = dms[ascending ? i : (dms.length - 1) - i];
+				if (dm == null) {
+					continue;
+				}
+				this.run(dm);
+			}
+			this.run(dms);
+		} catch (Exception e) {
+			Debug.printStackTrace(e);
+		}
+	}
+}
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/ListenerGetOffSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/ListenerGetOffSWT.java
new file mode 100644
index 0000000..e07ef3c
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/ListenerGetOffSWT.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.swt;
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+import org.gudy.azureus2.core3.util.AERunnable;
+
+/**
+ * 
+ * SWT {@link Listener} that invokes event handling off of the SWT Thread
+ * 
+ * @author TuxPaper
+ * @created Jan 20, 2015
+ *
+ */
+public abstract class ListenerGetOffSWT
+	implements Listener
+{
+	// @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
+	public void handleEvent(final Event event) {
+		Utils.getOffOfSWTThread(new AERunnable() {
+			public void runSupport() {
+				handleEventOffSWT(event);
+			}
+		});
+	}
+
+	abstract void handleEventOffSWT(Event event);
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/LocaleUtilSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/LocaleUtilSWT.java
index 211ff60..d3862ba 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/LocaleUtilSWT.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/LocaleUtilSWT.java
@@ -2,7 +2,7 @@
  * LocaleUtilSWT.java
  *
  * Created on 29. August 2003, 17:32
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/Main.java b/azureus2/src/org/gudy/azureus2/ui/swt/Main.java
index 4194a53..45e90b0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/Main.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/Main.java
@@ -1,6 +1,6 @@
 /*
  * Created on 8 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
@@ -160,7 +157,12 @@ Main
     		closedown	= true;
     		
     		break;
+    		
+    	}else if ( arg.equalsIgnoreCase( "--open" )){
+    	
+    		continue;
     	}
+    	
 	        // Sometimes Windows use filename in 8.3 form and cannot
 	        // match .torrent extension. To solve this, canonical path
 	        // is used to get back the long form
@@ -204,6 +206,7 @@ Main
         if( 	filename.toUpperCase().startsWith( "HTTP:" ) || 
         		filename.toUpperCase().startsWith( "HTTPS:" ) || 
         		filename.toUpperCase().startsWith( "MAGNET:" ) ||
+        		filename.toUpperCase().startsWith( "MAGGOT:" ) ||
            		filename.toUpperCase().startsWith( "BC:" ) ||
            		filename.toUpperCase().startsWith( "BCTP:" ) ||
         		filename.toUpperCase().startsWith( "DHT:" ) ) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/MenuBuildUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/MenuBuildUtils.java
index 8211ac9..ee4df3e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/MenuBuildUtils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/MenuBuildUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-Jan-2007
  * Created by Allan Crooks
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
@@ -26,22 +23,31 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.events.MenuEvent;
 import org.eclipse.swt.events.MenuListener;
 import org.eclipse.swt.widgets.Menu;
+import org.gudy.azureus2.plugins.download.Download;
 import org.gudy.azureus2.plugins.ui.Graphic;
+import org.gudy.azureus2.plugins.ui.GraphicURI;
 import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
 import org.gudy.azureus2.pluginsimpl.local.ui.menus.MenuItemImpl;
 import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl;
 import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
 import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.*;
+
+import com.aelitis.azureus.plugins.I2PHelpers;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginUtils;
 
 
 /**
@@ -152,6 +158,8 @@ public class MenuBuildUtils {
 		 * displayed in a menu.
 		 */
 		public void notifyFillListeners(MenuItem menu_item);
+		
+		public void buildSubmenu(MenuItem parent);
 	}
 
 	/**
@@ -184,6 +192,18 @@ public class MenuBuildUtils {
 			((MenuItemImpl) menu_item).invokeMenuWillBeShownListeners(objects);
 		}
 
+		// @see org.gudy.azureus2.ui.swt.MenuBuildUtils.PluginMenuController#buildSubmenu(org.gudy.azureus2.plugins.ui.menus.MenuItem)
+		public void buildSubmenu(MenuItem parent) {
+			org.gudy.azureus2.plugins.ui.menus.MenuBuilder submenuBuilder = ((MenuItemImpl) parent).getSubmenuBuilder();
+			if (submenuBuilder != null) {
+				try {
+					parent.removeAllChildItems();
+					submenuBuilder.buildSubmenu(parent, objects);
+				} catch (Throwable t) {
+					Debug.out(t);
+				}
+			}
+		}
 	}
 
 	/**
@@ -203,7 +223,6 @@ public class MenuBuildUtils {
 	 * MenuItemManager or TableContextMenuManager, where plugins will usually
 	 * register menu items they have created.
 	 * 
-	 * @param composite Some composite to get a shell from.
 	 * @param items The list of plugin MenuItem to add
 	 * @param parent The SWT Menu to add to.
 	 * @param prev_was_separator Indicates if the previous item in the menu is
@@ -215,9 +234,9 @@ public class MenuBuildUtils {
 	 * @param controller The callback object used by this method when creating the
 	 *            SWT menus (used for invoking fill and selection listeners).
 	 */
-	public static void addPluginMenuItems(Composite composite,
-			MenuItem[] items, Menu parent,	boolean prev_was_separator,
-			boolean enable_items, PluginMenuController controller) {
+	public static void addPluginMenuItems(MenuItem[] items, Menu parent,
+			boolean prev_was_separator,
+			final boolean enable_items, final PluginMenuController controller) {
 		
 		for (int i = 0; i < items.length; i++) {
 			final MenuItemImpl az_menuitem = (MenuItemImpl) items[i];
@@ -291,10 +310,16 @@ public class MenuBuildUtils {
 			});
 			
 			if (is_container) {
-				Menu this_menu = new Menu(composite.getShell(), SWT.DROP_DOWN);
+				Menu this_menu = new Menu(parent);
 				menuItem.setMenu(this_menu);
-				addPluginMenuItems(composite, az_menuitem.getItems(), this_menu, false,
-						enable_items, controller);
+
+				addMaintenanceListenerForMenu(this_menu, new MenuBuilder() {
+					public void buildMenu(Menu root_menu, MenuEvent menuEvent) {
+						controller.buildSubmenu(az_menuitem);
+						addPluginMenuItems(az_menuitem.getItems(), root_menu, false,
+								enable_items, controller);
+					}
+				});
 			}
 			
 			String custom_title = az_menuitem.getText();
@@ -303,10 +328,12 @@ public class MenuBuildUtils {
 			Graphic g = az_menuitem.getGraphic();
 			if (g instanceof UISWTGraphic) {
 				Utils.setMenuItemImage(menuItem, ((UISWTGraphic) g).getImage());
+			} else if (g instanceof GraphicURI) {
+				Utils.setMenuItemImage(menuItem, ((GraphicURI) g).getURI().toString());
 			}
 
 			menuItem.setEnabled(enable_items && az_menuitem.isEnabled());
-
+			
 		}
 	}
 	
@@ -428,4 +455,266 @@ public class MenuBuildUtils {
 			
 		return( result );
 	}
+	
+	private static AtomicBoolean	pub_chat_pending 	= new AtomicBoolean();
+	private static AtomicBoolean	anon_chat_pending 	= new AtomicBoolean();
+
+	public static void
+	addChatMenu(
+		Menu			menu,
+		String			menu_resource_key,
+		final String	chat_key )
+	{
+		if ( BuddyPluginUtils.isBetaChatAvailable()){
+						
+			final Menu chat_menu = new Menu(menu.getShell(), SWT.DROP_DOWN);
+			
+			final org.eclipse.swt.widgets.MenuItem chat_item = new org.eclipse.swt.widgets.MenuItem(menu, SWT.CASCADE);
+			
+			Messages.setLanguageText( chat_item, menu_resource_key );
+			
+			chat_item.setMenu(chat_menu);
+
+			org.eclipse.swt.widgets.MenuItem chat_pub = new org.eclipse.swt.widgets.MenuItem(chat_menu, SWT.PUSH);
+			
+			Messages.setLanguageText(chat_pub, "label.public");
+			
+			chat_pub.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event){
+					
+					pub_chat_pending.set( true );
+					
+					BuddyPluginUtils.createBetaChat(
+						AENetworkClassifier.AT_PUBLIC, 
+						chat_key,
+						new Runnable()
+						{
+							public void
+							run()
+							{
+								pub_chat_pending.set( false );
+							}
+						});
+				}});
+			
+			if ( pub_chat_pending.get()){
+				
+				chat_pub.setEnabled( false );
+				chat_pub.setText( chat_pub.getText() + " (" + MessageText.getString( "PeersView.state.pending" ) + ")" );
+			}
+			
+			if ( BuddyPluginUtils.isBetaChatAnonAvailable()){
+				
+				org.eclipse.swt.widgets.MenuItem chat_priv = new org.eclipse.swt.widgets.MenuItem(chat_menu, SWT.PUSH);
+				
+				Messages.setLanguageText(chat_priv, "label.anon");
+				
+				chat_priv.addListener(SWT.Selection, new Listener() {
+					public void handleEvent(Event event){
+						
+						anon_chat_pending.set( true );
+						
+						BuddyPluginUtils.createBetaChat( 
+							AENetworkClassifier.AT_I2P, 
+							chat_key,
+							new Runnable()
+							{
+								public void
+								run()
+								{
+									anon_chat_pending.set( false );
+								}
+							});
+					}});
+				
+				if ( anon_chat_pending.get()){
+					
+					chat_priv.setEnabled( false );
+					chat_priv.setText( chat_priv.getText() + " (" + MessageText.getString( "PeersView.state.pending" ) + ")" );
+
+				}
+			}else{
+				
+				org.eclipse.swt.widgets.MenuItem chat_priv = new org.eclipse.swt.widgets.MenuItem(chat_menu, SWT.PUSH);
+				
+				chat_priv.setText( MessageText.getString("label.anon") + "..." );
+				
+				chat_priv.addListener(SWT.Selection, new Listener() {
+					public void handleEvent(Event event){
+						
+						I2PHelpers.installI2PHelper( null, null, null );
+					}});
+				
+				if ( I2PHelpers.isInstallingI2PHelper()){
+					
+					chat_priv.setEnabled( false );
+					chat_priv.setText( chat_priv.getText() + " (" + MessageText.getString( "PeersView.state.pending" ) + ")" );
+
+				}
+			}
+		}
+	}
+	
+	public interface
+	ChatKeyResolver
+	{
+		public String
+		getChatKey(
+			Object		object );
+	}
+	
+	public static MenuItem
+	addChatMenu(
+		final MenuManager		menu_manager,
+		final MenuItem			chat_item,
+		final ChatKeyResolver	chat_key_resolver )
+	{
+		chat_item.setStyle( MenuItem.STYLE_MENU );
+			
+		chat_item.addFillListener(
+			new MenuItemFillListener() 
+			{
+				
+				public void 
+				menuWillBeShown(
+					MenuItem 	menu, 
+					Object 		data) 
+				{
+					menu.removeAllChildItems();
+					
+					{
+						MenuItem chat_pub = menu_manager.addMenuItem(chat_item,  "label.public");
+						
+						chat_pub.addMultiListener(
+								new MenuItemListener() {
+									
+									public void 
+									selected(
+										MenuItem 	menu, 
+										Object 		target) 
+									{
+										Object[]	rows = (Object[])target;
+										
+										if ( rows.length > 0 ){
+											
+											final AtomicInteger count = new AtomicInteger( rows.length );
+											
+											pub_chat_pending.set( true );
+	
+											for ( Object obj: rows ){
+												
+												String chat_key = chat_key_resolver.getChatKey( obj );
+												
+												if ( chat_key != null ){
+													
+													BuddyPluginUtils.createBetaChat(
+														AENetworkClassifier.AT_PUBLIC, 
+														chat_key,
+														new Runnable()
+														{
+															public void
+															run()
+															{
+																if ( count.decrementAndGet() == 0 ){
+																
+																	pub_chat_pending.set( false );
+																}
+															}
+														});
+												}
+											}
+										}
+									}
+								});
+						
+						if ( pub_chat_pending.get()){
+							
+							chat_pub.setEnabled( false );
+							chat_pub.setText( chat_pub.getText() + " (" + MessageText.getString( "PeersView.state.pending" ) + ")" );
+						}
+					}
+					
+					if ( BuddyPluginUtils.isBetaChatAnonAvailable()){
+						
+						MenuItem chat_priv = menu_manager.addMenuItem(chat_item,  "label.anon");
+						
+						chat_priv.addMultiListener(
+							new MenuItemListener()
+							{	
+								public void 
+								selected(
+									MenuItem menu, 
+									Object target) 
+								{
+									Object[]	rows = (Object[])target;
+									
+									if ( rows.length > 0 ){
+										
+										final AtomicInteger count = new AtomicInteger( rows.length );
+										
+										anon_chat_pending.set( true );
+
+										for ( Object obj: rows ){
+											
+											String chat_key = chat_key_resolver.getChatKey( obj );
+											
+											if ( chat_key != null ){
+																					
+												BuddyPluginUtils.createBetaChat(
+													AENetworkClassifier.AT_I2P, 
+													chat_key,
+													new Runnable()
+													{
+														public void
+														run()
+														{
+															if ( count.decrementAndGet() == 0 ){
+															
+																anon_chat_pending.set( false );
+															}
+														}
+													});	
+											}
+										}
+									}
+								}
+							});
+						
+						if ( anon_chat_pending.get()){
+							
+							chat_priv.setEnabled( false );
+							chat_priv.setText( chat_priv.getText() + " (" + MessageText.getString( "PeersView.state.pending" ) + ")" );
+						}
+					
+					}else{
+						
+						MenuItem chat_priv = menu_manager.addMenuItem(chat_item,  "label.anon");
+						
+						chat_priv.setText( MessageText.getString("label.anon") + "..." );
+											
+						chat_priv.addMultiListener(
+							new MenuItemListener()
+							{	
+								public void 
+								selected(
+									MenuItem menu, 
+									Object target) 
+								{
+								
+									I2PHelpers.installI2PHelper( null, null, null );
+								}
+							});
+						
+						if ( I2PHelpers.isInstallingI2PHelper()){
+							
+							chat_priv.setEnabled( false );
+							chat_priv.setText( chat_priv.getText() + " (" + MessageText.getString( "PeersView.state.pending" ) + ")" );
+						}
+					}
+				}
+			});
+	
+		
+		return( chat_item );
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/Messages.java b/azureus2/src/org/gudy/azureus2/ui/swt/Messages.java
index c0bd1a0..601666b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/Messages.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/Messages.java
@@ -1,6 +1,6 @@
 /*
  * Created on 21.07.2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
@@ -30,7 +27,6 @@ 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.DoubleBufferedLabel;
-import org.gudy.azureus2.ui.swt.views.table.TableColumnOrTreeColumn;
 
 import java.util.regex.Pattern;
 
@@ -277,8 +273,6 @@ public class Messages {
             ((ToolItem) widget).setText(message);
         else if(widget instanceof Text) 
           ((Text) widget).setText(message);
-        else if(widget instanceof TableColumnOrTreeColumn) 
-          ((TableColumnOrTreeColumn) widget).setText(message);
         else if(widget instanceof TreeColumn) 
           ((TreeColumn) widget).setText(message);
         else if(widget instanceof DoubleBufferedLabel) 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/OpenTorrentWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/OpenTorrentWindow.java
index fa72327..70ce3da 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/OpenTorrentWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/OpenTorrentWindow.java
@@ -3,11 +3,12 @@
  *
  * Created on February 23, 2004, 4:09 PM
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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;
@@ -820,61 +818,70 @@ public class OpenTorrentWindow
 		}
 
 		String sDefaultPath = COConfigurationManager.getStringParameter(PARAM_DEFSAVEPATH);
+		
 		if (!sDestDir.equals(sDefaultPath)) {
-			// Move sDestDir to top of list
-
-			// First, check to see if sDestDir is already in the list
-			File fDestDir = new File(sDestDir);
-			int iDirPos = -1;
-			for (int i = 0; i < dirList.size(); i++) {
-				String sDirName = dirList.get(i);
-				File dir = new File(sDirName);
-				if (dir.equals(fDestDir)) {
-					iDirPos = i;
-					break;
-				}
-			}
 
-			// If already in list, remove it
-			if (iDirPos > 0 && iDirPos < dirList.size())
-				dirList.remove(iDirPos);
+			int	 limit = COConfigurationManager.getIntParameter( "saveTo_list.max_entries" );
 
-			// and add it to the top
-			dirList.add(0, sDestDir);
-
-			// Limit
-			if (dirList.size() > 15)
-				dirList.remove(dirList.size() - 1);
-
-			// Temporary list cleanup
-			try {
-				for (int j = 0; j < dirList.size(); j++) {
-					File dirJ = new File(dirList.get(j));
-					for (int i = 0; i < dirList.size(); i++) {
-						try {
-							if (i == j)
-								continue;
-
-							File dirI = new File(dirList.get(i));
+			if ( limit >= 0 ){
+				
+				// Move sDestDir to top of list
+
+				// First, check to see if sDestDir is already in the list
+				File fDestDir = new File(sDestDir);
+				int iDirPos = -1;
+				for (int i = 0; i < dirList.size(); i++) {
+					String sDirName = dirList.get(i);
+					File dir = new File(sDirName);
+					if (dir.equals(fDestDir)) {
+						iDirPos = i;
+						break;
+					}
+				}
 
-							if (dirI.equals(dirJ)) {
-								dirList.remove(i);
-								// dirList shifted up, fix indexes
-								if (j > i)
-									j--;
-								i--;
+				// If already in list, remove it
+				if (iDirPos > 0 && iDirPos < dirList.size())
+					dirList.remove(iDirPos);
+	
+				// and add it to the top
+				dirList.add(0, sDestDir);
+	
+				
+				// Limit
+				if (limit > 0 && dirList.size() > limit){
+					dirList.remove(dirList.size() - 1);
+				}
+				
+				// Temporary list cleanup
+				try {
+					for (int j = 0; j < dirList.size(); j++) {
+						File dirJ = new File(dirList.get(j));
+						for (int i = 0; i < dirList.size(); i++) {
+							try {
+								if (i == j)
+									continue;
+	
+								File dirI = new File(dirList.get(i));
+	
+								if (dirI.equals(dirJ)) {
+									dirList.remove(i);
+									// dirList shifted up, fix indexes
+									if (j > i)
+										j--;
+									i--;
+								}
+							} catch (Exception e) {
+								// Ignore
 							}
-						} catch (Exception e) {
-							// Ignore
 						}
 					}
+				} catch (Exception e) {
+					// Ignore
 				}
-			} catch (Exception e) {
-				// Ignore
-			}
 
-			COConfigurationManager.setParameter("saveTo_list", dirList);
-			COConfigurationManager.save();
+				COConfigurationManager.setParameter("saveTo_list", dirList);
+				COConfigurationManager.save();
+			}
 		}
 
 		if (COConfigurationManager.getBooleanParameter("DefaultDir.AutoUpdate")){
@@ -2214,7 +2221,7 @@ public class OpenTorrentWindow
 		}
 		
 		// Do a quick check to see if it's a torrent
-		if (!TorrentUtil.isFileTorrent(torrentFile, torrentFile.getName())) {
+		if (!TorrentUtil.isFileTorrent(torrentFile, torrentFile.getName(), true )) {
 			if (bDeleteFileOnCancel) {
 				torrentFile.delete();
 			}
@@ -2626,7 +2633,7 @@ public class OpenTorrentWindow
 			File file = inf.getFile();
 			// we already know it isn't a torrent.. we are just using the call
 			// to popup the message
-			TorrentUtil.isFileTorrent(file, inf.getURL());
+			TorrentUtil.isFileTorrent(file, inf.getURL(), true );
 			if (file.exists()) {
 				file.delete();
 			}
@@ -2883,6 +2890,17 @@ public class OpenTorrentWindow
 			} catch (Exception e) {
 				e.printStackTrace();
 			}
+			
+			if ( sSmartDir == null || sSmartDir.trim().length() == 0 ){
+			
+				String def = COConfigurationManager.getStringParameter( "DefaultDir.BestGuess.Default" );
+				
+				if ( def != null ){
+					
+					sSmartDir = def.trim();
+				}
+			}
+			
 			return sSmartDir;
 		}
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/OpenUrlWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/OpenUrlWindow.java
index 7907a3b..5260311 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/OpenUrlWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/OpenUrlWindow.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/PasswordWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/PasswordWindow.java
index 7de53a3..dc6ea1c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/PasswordWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/PasswordWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on 7 sept. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/PropertiesWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/PropertiesWindow.java
index 84e7b91..757219b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/PropertiesWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/PropertiesWindow.java
@@ -1,7 +1,7 @@
 /*
  * Created on 02-Oct-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/SimpleTextEntryWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/SimpleTextEntryWindow.java
index 0457f10..48adcb0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/SimpleTextEntryWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/SimpleTextEntryWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on 16 July 2006
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
@@ -151,7 +148,18 @@ public class SimpleTextEntryWindow extends AbstractUISWTInputReceiver {
 	    	if (text_entry_text != null) {
 		    	text_entry_text.setText(this.preentered_text);
 		    	if (this.select_preentered_text) {
-		    		text_entry_text.selectAll();
+		    		
+		    		int[] range = this.select_preentered_text_range;
+		    		
+		    		if ( range == null || range.length != 2 ){
+		    			text_entry_text.selectAll();
+		    		}else{
+		    			try{
+		    				text_entry_text.setSelection( range[0], range[1] );
+		    			}catch( Throwable e ){
+		    				text_entry_text.selectAll();
+		    			}
+		    		}
 		    	}
 	    	}
 	    	else if (text_entry_combo != null ){
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/StartServer.java b/azureus2/src/org/gudy/azureus2/ui/swt/StartServer.java
index 57c2590..46e29bf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/StartServer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/StartServer.java
@@ -1,6 +1,6 @@
 /*
  * Created on 8 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
@@ -351,6 +348,7 @@ StartServer
 	  return( 	file_name_lower.startsWith( "http:" ) || 
 			  	file_name_lower.startsWith( "https:" ) || 
 			  	file_name_lower.startsWith( "magnet:" ) ||
+				file_name_lower.startsWith( "maggot:" ) ||
 			  	file_name_lower.startsWith( "bc:" ) ||
 			  	file_name_lower.startsWith( "bctp:" ) ||
 	  			file_name_lower.startsWith( "dht:" ));
@@ -422,7 +420,9 @@ StartServer
   public void stopIt() {
     bContinue = false;
     try {
-      socket.close();
+      if ( socket != null ){
+    	  socket.close();
+      }
     }
     catch (Throwable e) {/*ignore */}
   }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/StartSocket.java b/azureus2/src/org/gudy/azureus2/ui/swt/StartSocket.java
index 501735e..a47c6c5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/StartSocket.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/StartSocket.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 30, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/TextViewerWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/TextViewerWindow.java
index 4a92127..8ccd0c6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/TextViewerWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/TextViewerWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on 2 feb. 2004
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
@@ -110,7 +107,7 @@ public class TextViewerWindow {
 
     txtInfo = new Text(shell, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
     gridData = new GridData(  GridData.FILL_BOTH );
-    gridData.widthHint = 500;
+    gridData.widthHint = 600;
     gridData.heightHint = 400;
     gridData.horizontalSpan = 2;
     txtInfo.setLayoutData(gridData);
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/TorrentMenuFancy.java b/azureus2/src/org/gudy/azureus2/ui/swt/TorrentMenuFancy.java
new file mode 100644
index 0000000..191021c
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/TorrentMenuFancy.java
@@ -0,0 +1,2244 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.swt;
+
+import java.io.File;
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+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;
+import org.gudy.azureus2.core3.ipfilter.IpFilterManagerFactory;
+import org.gudy.azureus2.core3.peer.PEPeerManager;
+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.download.Download;
+import org.gudy.azureus2.plugins.sharing.ShareManager;
+import org.gudy.azureus2.plugins.ui.Graphic;
+import org.gudy.azureus2.plugins.ui.GraphicURI;
+import org.gudy.azureus2.plugins.ui.menus.MenuBuilder;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
+import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.pluginsimpl.local.ui.menus.MenuItemImpl;
+import org.gudy.azureus2.ui.common.util.MenuItemManager;
+import org.gudy.azureus2.ui.swt.exporttorrent.wizard.ExportTorrentWizard;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
+import org.gudy.azureus2.ui.swt.mainwindow.IMenuConstants;
+import org.gudy.azureus2.ui.swt.mainwindow.MenuFactory;
+import org.gudy.azureus2.ui.swt.mainwindow.SelectableSpeedMenu;
+import org.gudy.azureus2.ui.swt.minibar.DownloadBar;
+import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
+import org.gudy.azureus2.ui.swt.sharing.ShareUtils;
+import org.gudy.azureus2.ui.swt.shells.AdvRenameWindow;
+import org.gudy.azureus2.ui.swt.views.table.TableSelectedRowsListener;
+import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
+import org.gudy.azureus2.ui.swt.views.table.utils.TableContextMenuManager;
+import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
+import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.speedmanager.SpeedLimitHandler;
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.common.table.TableCellCore;
+import com.aelitis.azureus.ui.common.table.TableColumnCore;
+import com.aelitis.azureus.ui.common.table.TableRowCore;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
+import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+
+/**
+ * @author TuxPaper
+ * @created Jan 20, 2015
+ *
+ */
+public class TorrentMenuFancy
+{
+	private static final String HEADER_CONTROL = "Control";
+
+	private static final String HEADER_SOCIAL = "Social";
+
+	private static final String HEADER_ORGANIZE = "Organize";
+
+	private static final String HEADER_MENU = "Other";
+
+	private static final String HEADER_MSG_PREFIX = "FancyMenu.Header.";
+
+	private static final String HEADER_CONTENT = "Content";
+
+	private static class HeaderInfo
+	{
+		private Runnable runnable;
+
+		private Composite composite;
+
+		private String id;
+
+		public HeaderInfo(String id, Runnable runnable, Composite composite) {
+			this.id = id;
+			this.runnable = runnable;
+			this.composite = composite;
+		}
+	}
+
+	private static class FancyRowInfo
+	{
+		private Listener listener;
+
+		private Label lblText;
+
+		private Label lblRight;
+
+		private Label lblIcon;
+
+		private Label lblCheck;
+
+		private Composite cRow;
+
+		private boolean keepMenu;
+
+		private boolean isSelected;
+
+		private boolean hasSubMenu;
+
+		public void setEnabled(boolean enabled) {
+			cRow.setEnabled(enabled);
+		}
+
+		public Label getRightLabel() {
+			if (lblRight == null) {
+				lblRight = new Label(cRow, SWT.NONE);
+				GridData gd = new GridData();
+				gd.horizontalIndent = 10;
+				lblRight.setLayoutData(gd);
+				lblRight.setEnabled(false);
+			}
+			return lblRight;
+		}
+
+		public Listener getListener() {
+			return listener;
+		}
+
+		public void setListener(Listener listener) {
+			this.listener = listener;
+		}
+
+		public Label getText() {
+			return lblText;
+		}
+
+		public void setText(Label lblText) {
+			this.lblText = lblText;
+		}
+
+		public void setRightLabel(Label lblRight) {
+			this.lblRight = lblRight;
+		}
+
+		public void setRightLabelText(String s) {
+			getRightLabel().setText(s);
+		}
+
+		public Label getIconLabel() {
+			return lblIcon;
+		}
+
+		public void setIconLabel(Label lblIcon) {
+			this.lblIcon = lblIcon;
+		}
+
+		public Composite getRow() {
+			return cRow;
+		}
+
+		public void setRow(Composite cRow) {
+			this.cRow = cRow;
+		}
+
+		public boolean keepMenu() {
+			return keepMenu;
+		}
+
+		public void setKeepMenu(boolean keepMenu) {
+			this.keepMenu = keepMenu;
+		}
+
+		public void setSelection(boolean isSelected) {
+			this.isSelected = isSelected;
+			ImageLoader.getInstance().setLabelImage(lblCheck,
+					isSelected ? "check_yes" : "check_no");
+		}
+
+		public boolean isSelected() {
+			return isSelected;
+		}
+
+		public void setCheckLabel(Label lblCheck) {
+			this.lblCheck = lblCheck;
+		}
+
+		public boolean hasSubMenu() {
+			return hasSubMenu;
+		}
+
+		public void setHasSubMenu(boolean hasSubMenu) {
+			this.hasSubMenu = hasSubMenu;
+		}
+	}
+
+	private static class FancyMenuRowInfo
+		extends FancyRowInfo
+	{
+		private Menu menu;
+
+		public Menu getMenu() {
+			return menu;
+		}
+
+		public void setMenu(Menu menu) {
+			this.menu = menu;
+		}
+	}
+
+	private interface FancyMenuRowInfoListener
+	{
+		public void buildMenu(Menu menu);
+	}
+
+	protected static final boolean DEBUG_MENU = false;
+
+	private static final int SHELL_MARGIN = 1;
+
+	private List<FancyRowInfo> listRowInfos = new ArrayList<FancyRowInfo>();
+
+	private List<HeaderInfo> listHeaders = new ArrayList<HeaderInfo>();
+
+	private Composite topArea;
+
+	private Composite detailArea;
+
+	private Listener headerListener;
+
+	private TableViewSWT<?> tv;
+
+	private boolean isSeedingView;
+
+	private Shell parentShell;
+
+	private DownloadManager[] dms;
+
+	private String tableID;
+
+	private boolean hasSelection;
+
+	private Map<String, String[]> mapMovedPluginMenus = new HashMap<String, String[]>();
+
+	private Map<String, Integer> mapMovedPluginMenuUserMode = new HashMap<String, Integer>();
+
+	private java.util.List<String> listMovedPluginIDs = new ArrayList<String>();
+
+	private Shell shell;
+
+	private Listener listenerForTrigger;
+
+	private Listener listenerRow;
+
+	private PaintListener listenerRowPaint;
+
+	private TableColumnCore column;
+
+	private HeaderInfo activatedHeader;
+
+	private Menu currentMenu;
+
+	private FancyRowInfo currentRowInfo;
+
+	private Point originalShellLocation;
+
+	private boolean subMenuVisible;
+
+	private PaintListener paintListenerArrow;
+
+	public TorrentMenuFancy(final TableViewSWT<?> tv,
+			final boolean isSeedingView, Shell parentShell,
+			final DownloadManager[] dms, final String tableID) {
+		this.tv = tv;
+		this.isSeedingView = isSeedingView;
+		this.parentShell = parentShell;
+		this.dms = dms;
+		this.tableID = tableID;
+		hasSelection = dms.length > 0;
+
+		String[] ids_control = {
+			"azpeerinjector.contextmenu.inject",
+			"tablemenu.main.item",
+			"StartStopRules.menu.viewDebug",
+			"MyTorrentsView.menu.rename.displayed"
+		};
+		mapMovedPluginMenuUserMode.put("tablemenu.main.item", 2);
+		mapMovedPluginMenuUserMode.put("azpeerinjector.contextmenu.inject", 2);
+
+		mapMovedPluginMenus.put(HEADER_CONTROL, ids_control);
+		listMovedPluginIDs.addAll(Arrays.asList(ids_control));
+
+		String[] ids_social = {
+			"azsubs.contextmenu.lookupassoc",
+			"rcm.contextmenu.lookupassoc",
+			"rcm.contextmenu.lookupsize",
+			"MagnetPlugin.contextmenu.exporturi",
+			"azbuddy.contextmenu",
+			"RatingPlugin.contextmenu.manageRating",
+			"label.chat",
+		};
+		mapMovedPluginMenus.put(HEADER_SOCIAL, ids_social);
+		listMovedPluginIDs.addAll(Arrays.asList(ids_social));
+
+		String[] ids_content = {
+			"upnpmediaserver.contextmenu",
+			"devices.contextmenu.xcode",
+			"antivirus.ui.contextmenu.scan",
+			"vuzexcode.transcode",
+			"burn.menu.addtodvd"
+		};
+		mapMovedPluginMenus.put(HEADER_CONTENT, ids_content);
+		listMovedPluginIDs.addAll(Arrays.asList(ids_content));
+
+		listenerForTrigger = new Listener() {
+			public void handleEvent(Event event) {
+				FancyRowInfo rowInfo = findRowInfo(event.widget);
+				if (rowInfo != null) {
+					if (!rowInfo.keepMenu()) {
+						shell.dispose();
+					}
+
+					if (rowInfo.getListener() != null) {
+						rowInfo.getListener().handleEvent(event);
+					}
+				} else {
+					shell.dispose();
+				}
+			}
+		};
+
+		paintListenerArrow = new PaintListener() {
+			public void paintControl(PaintEvent e) {
+				Control c = (Control) e.widget;
+				Point size = c.getSize();
+				int arrowSize = 8;
+				int xStart = size.x - arrowSize;
+				int yStart = size.y - (size.y + arrowSize) / 2;
+				e.gc.setBackground(e.display.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND));
+				e.gc.setAntialias(SWT.ON);
+				e.gc.fillPolygon(new int[] {
+					xStart,
+					yStart,
+					xStart + arrowSize,
+					yStart + 4,
+					xStart,
+					yStart + 8,
+				});
+			}
+		};
+
+		listenerRow = new Listener() {
+			public void handleEvent(Event event) {
+				Composite parent = detailArea;
+				Rectangle bounds = parent.getBounds();
+				if (event.type == SWT.MouseExit) {
+					currentRowInfo = null;
+					parent.redraw(0, 0, bounds.width, bounds.height, true);
+				} else if (event.type == SWT.MouseEnter) {
+					FancyRowInfo rowInfo = findRowInfo(event.widget);
+					currentRowInfo = rowInfo;
+					parent.redraw(0, 0, bounds.width, bounds.height, true);
+				}
+			}
+		};
+
+		listenerRowPaint = new PaintListener() {
+			public void paintControl(PaintEvent e) {
+				FancyRowInfo rowInfo = findRowInfo(e.widget);
+				if (rowInfo == null) {
+					return;
+				}
+
+				boolean isSelected = currentRowInfo == rowInfo;
+
+				if (!isSelected) {
+					for (Control control : ((Composite) e.widget).getChildren()) {
+						control.setBackground(null);
+						control.setForeground(null);
+					}
+					//System.out.println("bounds=" + bounds + "/" + cursorLocation + "/" + cursorLocationRel + "; clip=" + e.gc.getClipping());
+					return;
+				}
+				Rectangle bounds = ((Control) e.widget).getBounds();
+
+				Color bg = e.display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+				int arc = bounds.height / 3;
+				e.gc.setBackground(bg);
+				e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW));
+				e.gc.setAntialias(SWT.ON);
+				//System.out.println("clip=" + e.gc.getClipping());
+				e.gc.fillRoundRectangle(0, 0, bounds.width - 1, bounds.height - 1, arc,
+						arc);
+				e.gc.setAlpha(100);
+				e.gc.drawRoundRectangle(0, 0, bounds.width - 1, bounds.height - 1, arc,
+						arc);
+
+				Color fg = e.display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+				for (Control control : ((Composite) e.widget).getChildren()) {
+					control.setBackground(bg);
+					control.setForeground(fg);
+				}
+
+			}
+		};
+
+		Collections.sort(listMovedPluginIDs);
+	}
+
+	public void showMenu(TableColumnCore acolumn, final Menu fallbackMenu ) {
+		this.column = acolumn;
+		Display d = parentShell.getDisplay();
+
+		// We don't get mouse down notifications on trim or borders..
+		shell = new Shell(parentShell, SWT.NO_TRIM | SWT.DOUBLE_BUFFERED) {
+			protected void checkSubclass() {
+			}
+
+			public void dispose() {
+				if (DEBUG_MENU) {
+					System.out.println("Dispose via " + Debug.getCompressedStackTrace());
+				}
+				super.dispose();
+			};
+		};
+
+		//FormLayout shellLayout = new FormLayout();
+		RowLayout shellLayout = new RowLayout(SWT.VERTICAL);
+		shellLayout.fill = true;
+		shellLayout.marginBottom = shellLayout.marginLeft = shellLayout.marginRight = shellLayout.marginTop = 0;
+		shellLayout.marginWidth = shellLayout.marginHeight = SHELL_MARGIN;
+
+		shell.setLayout(shellLayout);
+		shell.setBackgroundMode(SWT.INHERIT_FORCE);
+
+		topArea = new Composite(shell, SWT.DOUBLE_BUFFERED);
+		detailArea = new Composite(shell, SWT.DOUBLE_BUFFERED);
+
+		topArea.setBackground(d.getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+		topArea.setForeground(d.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
+
+		FormData fd = Utils.getFilledFormData();
+		fd.bottom = null;
+		RowLayout topLayout = new RowLayout(SWT.HORIZONTAL);
+		topLayout.spacing = 0;
+		topLayout.pack = true;
+		topLayout.marginBottom = topLayout.marginTop = topLayout.marginLeft = topLayout.marginRight = 0;
+		topArea.setLayout(topLayout);
+
+		//detailArea.setBackground(ColorCache.getRandomColor());
+		fd = Utils.getFilledFormData();
+		fd.top = new FormAttachment(topArea, 0, SWT.BOTTOM);
+		FormLayout layoutDetailsArea = new FormLayout();
+		layoutDetailsArea.marginWidth = 2;
+		layoutDetailsArea.marginBottom = 2;
+		detailArea.setLayout(layoutDetailsArea);
+
+		headerListener = new Listener() {
+			// @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
+			public void handleEvent(Event e) {
+				Control control = (Control) e.widget;
+				if (e.type == SWT.Paint) {
+					Rectangle bounds = control.getBounds();
+					int y = bounds.height - 2;
+					e.gc.drawLine(0, y, bounds.width, y);
+				} else if (e.type == SWT.MouseEnter || e.type == SWT.Touch) {
+					Object data = e.widget.getData("ID");
+
+					if (data instanceof HeaderInfo) {
+						HeaderInfo header = (HeaderInfo) data;
+						if (DEBUG_MENU) {
+							System.out.println("enter : " + data);
+						}
+
+						activateHeader(header);
+					}
+				}
+			}
+		};
+
+		HeaderInfo firstHeader = addHeader(HEADER_CONTROL, HEADER_MSG_PREFIX
+				+ HEADER_CONTROL, new AERunnable() {
+			public void runSupport() {
+				buildTorrentCustomMenu_Control(detailArea, dms);
+			}
+		});
+		addHeader(HEADER_CONTENT, HEADER_MSG_PREFIX + HEADER_CONTENT,
+				new AERunnable() {
+					public void runSupport() {
+						buildTorrentCustomMenu_Content(detailArea, dms);
+					}
+				});
+		addHeader(HEADER_ORGANIZE, HEADER_MSG_PREFIX + HEADER_ORGANIZE,
+				new AERunnable() {
+					public void runSupport() {
+						buildTorrentCustomMenu_Organize(detailArea, dms);
+					}
+				});
+		addHeader(HEADER_SOCIAL, HEADER_MSG_PREFIX + HEADER_SOCIAL,
+				new AERunnable() {
+					public void runSupport() {
+						buildTorrentCustomMenu_Social(detailArea);
+					}
+				});
+
+		// Add table specific items
+		final List<org.gudy.azureus2.plugins.ui.menus.MenuItem> listOtherItems = new ArrayList<org.gudy.azureus2.plugins.ui.menus.MenuItem>();
+
+		TableContextMenuItem[] items = TableContextMenuManager.getInstance().getAllAsArray(
+				tableID);
+
+		for (TableContextMenuItem item : items) {
+			if (Collections.binarySearch(listMovedPluginIDs, item.getResourceKey()) >= 0) {
+				continue;
+			}
+			listOtherItems.add(item);
+		}
+
+		// Add Download Context specific menu items
+		org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items = MenuItemManager.getInstance().getAllAsArray(
+				MenuManager.MENU_DOWNLOAD_CONTEXT);
+		for (org.gudy.azureus2.plugins.ui.menus.MenuItem item : menu_items) {
+			if (Collections.binarySearch(listMovedPluginIDs, item.getResourceKey()) >= 0) {
+				continue;
+			}
+			listOtherItems.add(item);
+		}
+
+		// Add Plugin Context menus..
+		if (column != null) {
+			TableContextMenuItem[] columnItems = column.getContextMenuItems(TableColumnCore.MENU_STYLE_COLUMN_DATA);
+			for (TableContextMenuItem item : columnItems) {
+				if (Collections.binarySearch(listMovedPluginIDs, item.getResourceKey()) >= 0) {
+					continue;
+				}
+				listOtherItems.add(item);
+			}
+		}
+
+		if (listOtherItems.size() > 0) {
+			addHeader(HEADER_MENU, HEADER_MSG_PREFIX + HEADER_MENU, new AERunnable() {
+				public void runSupport() {
+					buildTorrentCustomMenu_Other(detailArea, listOtherItems);
+				}
+			});
+		}
+
+		originalShellLocation = d.getCursorLocation();
+		originalShellLocation.x -= 5;
+		originalShellLocation.y -= 16;
+
+		shell.setLocation(originalShellLocation);
+
+		shell.addPaintListener(new PaintListener() {
+
+			public void paintControl(PaintEvent e) {
+				e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_WIDGET_BORDER));
+				Rectangle clientArea = shell.getClientArea();
+				e.gc.drawRectangle(0, 0, clientArea.width - 1, clientArea.height - 1);
+			}
+		});
+
+		shell.addKeyListener(new KeyListener() {
+
+			public void keyReleased(KeyEvent e) {
+			}
+
+			public void keyPressed(KeyEvent e) {
+				if (e.keyCode == SWT.ARROW_DOWN) {
+					if (currentRowInfo == null) {
+						currentRowInfo = listRowInfos.get(0);
+					} else {
+						boolean next = false;
+						for (FancyRowInfo rowInfo : listRowInfos) {
+							if (next) {
+								currentRowInfo = rowInfo;
+								next = false;
+								break;
+							}
+							if (rowInfo == currentRowInfo) {
+								next = true;
+							}
+						}
+						if (next) {
+							currentRowInfo = listRowInfos.get(0);
+						}
+					}
+					Rectangle bounds = detailArea.getBounds();
+					detailArea.redraw(0, 0, bounds.width, bounds.height, true);
+				} else if (e.keyCode == SWT.ARROW_UP) {
+					if (currentRowInfo == null) {
+						currentRowInfo = listRowInfos.get(listRowInfos.size() - 1);
+					} else {
+						FancyRowInfo previous = listRowInfos.get(listRowInfos.size() - 1);
+						for (FancyRowInfo rowInfo : listRowInfos) {
+							if (rowInfo == currentRowInfo) {
+								currentRowInfo = previous;
+								break;
+							}
+							previous = rowInfo;
+						}
+					}
+					Rectangle bounds = detailArea.getBounds();
+					detailArea.redraw(0, 0, bounds.width, bounds.height, true);
+				} else if (e.keyCode == SWT.ARROW_LEFT) {
+					HeaderInfo previous = listHeaders.get(listHeaders.size() - 1);
+					for (HeaderInfo header : listHeaders) {
+						if (header == activatedHeader) {
+							activateHeader(previous);
+							break;
+						}
+						previous = header;
+					}
+				} else if (e.keyCode == SWT.ARROW_RIGHT) {
+					if (currentRowInfo != null && currentRowInfo.hasSubMenu()) {
+						Event event = new Event();
+						event.display = e.display;
+						event.widget = currentRowInfo.cRow;
+						listenerForTrigger.handleEvent(event);
+					} else {
+						boolean next = false;
+						for (HeaderInfo header : listHeaders) {
+							if (next) {
+								activateHeader(header);
+								next = false;
+								break;
+							}
+							if (header == activatedHeader) {
+								next = true;
+							}
+						}
+						if (next) {
+							activateHeader(listHeaders.get(0));
+						}
+					}
+				}
+			}
+		});
+
+		if ( fallbackMenu != null ){
+			
+			firstHeader.composite.addMenuDetectListener(
+					new MenuDetectListener() {
+						
+						public void menuDetected(MenuDetectEvent e) {
+							shell.dispose();
+							fallbackMenu.setVisible( true );
+						}
+					});
+		}
+		
+		shell.addTraverseListener(new TraverseListener() {
+			public void keyTraversed(TraverseEvent e) {
+				if (e.detail == SWT.TRAVERSE_ESCAPE) {
+					if (DEBUG_MENU) {
+						System.out.println("Dispose via ESCAPE");
+					}
+					shell.dispose();
+				} else if (e.detail == SWT.TRAVERSE_RETURN) {
+					if (currentRowInfo != null) {
+						Event event = new Event();
+						event.display = e.display;
+						event.widget = currentRowInfo.cRow;
+						listenerForTrigger.handleEvent(event);
+					}
+				}
+			}
+		});
+
+		shell.addShellListener(new ShellListener() {
+			public void shellIconified(ShellEvent e) {
+			}
+
+			public void shellDeiconified(ShellEvent e) {
+			}
+
+			public void shellDeactivated(ShellEvent e) {
+				// Must do later, so clicks go to wherever
+				Utils.execSWTThreadLater(0, new AERunnable() {
+					public void runSupport() {
+						if (subMenuVisible) {
+							return;
+						}
+						if (shell.isDisposed()) {
+							return;
+						}
+						Shell[] shells = shell.getShells();
+						if (shells != null && shells.length > 0) {
+							for (Shell aShell : shells) {
+								if (!aShell.isDisposed()) {
+									return;
+								}
+							}
+						}
+						shell.dispose();
+					}
+				});
+			}
+
+			public void shellClosed(ShellEvent e) {
+			}
+
+			public void shellActivated(ShellEvent e) {
+			}
+		});
+
+		activateHeader(firstHeader);
+
+		shell.open();
+	}
+
+	protected void activateHeader(HeaderInfo header) {
+		if (header == null || activatedHeader == header) {
+			return;
+		}
+
+		if (currentMenu != null && !currentMenu.isDisposed()) {
+			currentMenu.setVisible(false);
+		}
+		Display d = header.composite.getDisplay();
+		header.composite.setBackground(d.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
+		header.composite.setForeground(d.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND));
+
+		Utils.disposeSWTObjects(detailArea.getChildren());
+		listRowInfos.clear();
+		currentRowInfo = null;
+
+		if (header.runnable != null) {
+			header.runnable.run();
+		}
+
+		String[] ids = mapMovedPluginMenus.get(header.id);
+		if (ids != null) {
+			addTableItemsWithID(detailArea, tableID, ids);
+			addMenuItemsWithID(detailArea, MenuManager.MENU_DOWNLOAD_CONTEXT, ids);
+			if (column != null) {
+				TableContextMenuItem[] columnItems = column.getContextMenuItems(TableColumnCore.MENU_STYLE_COLUMN_DATA);
+				addItemsArray(detailArea, columnItems, ids);
+			}
+		}
+
+		Control lastControl = null;
+		for (Control child : detailArea.getChildren()) {
+			FormData fd = new FormData();
+			if (lastControl == null) {
+				fd.top = new FormAttachment(0);
+			} else {
+				fd.top = new FormAttachment(lastControl);
+			}
+			fd.left = new FormAttachment(0, 0);
+			fd.right = new FormAttachment(100, 0);
+			child.setLayoutData(fd);
+			lastControl = child;
+		}
+
+		shell.setLocation(shell.getLocation().x, originalShellLocation.y);
+		detailArea.moveBelow(null);
+		shell.pack(true);
+		detailArea.layout(true, true);
+
+		Point shellSize = shell.getSize();
+		Point ptBottomRight = shell.toDisplay(shellSize);
+		Rectangle monitorArea = shell.getMonitor().getClientArea();
+		if (ptBottomRight.x > monitorArea.x + monitorArea.width) {
+			shell.setLocation(monitorArea.x + monitorArea.width - shellSize.x,
+					shell.getLocation().y);
+		}
+
+		if (ptBottomRight.y > monitorArea.y + monitorArea.height) {
+			// Bottom-Up
+			if (shell.getChildren()[0] != detailArea) {
+				shell.setLocation(shell.getLocation().x, originalShellLocation.y
+						- detailArea.getSize().y - 3);
+				detailArea.moveAbove(null);
+				lastControl = null;
+				Control[] children = detailArea.getChildren();
+				for (int i = 0; i < children.length; i++) {
+					Control child = children[children.length - i - 1];
+					FormData fd = new FormData();
+					if (lastControl == null) {
+						fd.top = new FormAttachment(0);
+					} else {
+						fd.top = new FormAttachment(lastControl);
+					}
+					fd.left = new FormAttachment(0, 0);
+					fd.right = new FormAttachment(100, 0);
+					child.setLayoutData(fd);
+					lastControl = child;
+				}
+				shell.layout(true, true);
+			}
+		}
+
+		if (activatedHeader != null) {
+			activatedHeader.composite.setBackground(d.getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+			activatedHeader.composite.setForeground(d.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
+		}
+
+		activatedHeader = header;
+	}
+
+	public void buildTorrentCustomMenu_Control(final Composite cParent,
+			final DownloadManager[] dms) {
+		final int userMode = COConfigurationManager.getIntParameter("User Mode");
+
+		boolean start = false;
+		boolean stop = false;
+		boolean recheck = false;
+		boolean barsOpened = true;
+		boolean bChangeDir = hasSelection;
+
+		for (int i = 0; i < dms.length; i++) {
+			DownloadManager dm = dms[i];
+
+			if (barsOpened && !DownloadBar.getManager().isOpen(dm)) {
+				barsOpened = false;
+			}
+			stop = stop || ManagerUtils.isStopable(dm);
+
+			start = start || ManagerUtils.isStartable(dm);
+
+			recheck = recheck || dm.canForceRecheck();
+
+			boolean stopped = ManagerUtils.isStopped(dm);
+
+			int state = dm.getState();
+			bChangeDir &= (state == DownloadManager.STATE_ERROR
+					|| state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_QUEUED);
+			;
+			/**
+			 * Only perform a test on disk if:
+			 *    1) We are currently set to allow the "Change Data Directory" option, and
+			 *    2) We've only got one item selected - otherwise, we may potentially end up checking massive
+			 *       amounts of files across multiple torrents before we generate a menu.
+			 */
+			if (bChangeDir && dms.length == 1) {
+				bChangeDir = dm.isDataAlreadyAllocated();
+				if (bChangeDir && state == DownloadManager.STATE_ERROR) {
+					// filesExist is way too slow!
+					bChangeDir = !dm.filesExist(true);
+				} else {
+					DiskManagerFileInfo[] files = dm.getDiskManagerFileInfoSet().getFiles();
+					bChangeDir = false;
+					for (DiskManagerFileInfo info : files) {
+						if (info.isSkipped()) {
+							continue;
+						}
+						bChangeDir = !info.getFile(true).exists();
+						break;
+					}
+				}
+			}
+		}
+		Composite cQuickCommands = new Composite(cParent, SWT.NONE);
+		//cQuickCommands.setBackground(ColorCache.getRandomColor());
+		RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL);
+		rowLayout.justify = true;
+		rowLayout.marginLeft = 0;
+		rowLayout.marginRight = 0;
+		cQuickCommands.setLayout(rowLayout);
+		GridData gd = new GridData();
+		gd.grabExcessHorizontalSpace = true;
+		gd.horizontalAlignment = SWT.FILL;
+		cQuickCommands.setLayoutData(gd);
+
+		// Queue
+		createActionButton(dms, cQuickCommands, "MyTorrentsView.menu.queue",
+				"start", start, new ListenerGetOffSWT() {
+					void handleEventOffSWT(Event event) {
+						TorrentUtil.queueDataSources(dms, true);
+					}
+				});
+
+		// Force Start
+		if (userMode > 0) {
+			boolean forceStart = false;
+			boolean forceStartEnabled = false;
+
+			for (int i = 0; i < dms.length; i++) {
+				DownloadManager dm = dms[i];
+
+				forceStartEnabled = forceStartEnabled
+						|| ManagerUtils.isForceStartable(dm);
+
+				forceStart = forceStart || dm.isForceStart();
+			}
+
+			final boolean newForceStart = !forceStart;
+
+			createActionButton(dms, cQuickCommands, "MyTorrentsView.menu.forceStart",
+					"forcestart", forceStartEnabled, forceStart ? SWT.BORDER : SWT.PUSH,
+					new ListenerDMTask(dms) {
+						public void run(DownloadManager dm) {
+							if (ManagerUtils.isForceStartable(dm)) {
+								dm.setForceStart(newForceStart);
+							}
+						}
+					});
+		}
+
+		// Pause
+		if (userMode > 0) {
+			createActionButton(dms, cQuickCommands, "v3.MainWindow.button.pause",
+					"pause", stop, new ListenerGetOffSWT() {
+						public void handleEventOffSWT(Event event) {
+							TorrentUtil.pauseDataSources(dms);
+						}
+					});
+		}
+
+		// Stop
+		createActionButton(dms, cQuickCommands, "MyTorrentsView.menu.stop", "stop",
+				stop, new ListenerGetOffSWT() {
+					public void handleEventOffSWT(Event event) {
+						TorrentUtil.stopDataSources(dms);
+					}
+				});
+
+		// Force Recheck
+		createActionButton(dms, cQuickCommands, "MyTorrentsView.menu.recheck",
+				"recheck", recheck, new ListenerDMTask(dms) {
+					public void run(DownloadManager dm) {
+						if (dm.canForceRecheck()) {
+							dm.forceRecheck();
+						}
+					}
+				});
+
+		// Delete
+		createActionButton(dms, cQuickCommands, "menu.delete.options", "delete",
+				hasSelection, new Listener() {
+					public void handleEvent(Event event) {
+						TorrentUtil.removeDownloads(dms, null, true);
+					}
+				});
+
+		///////////////////////////////////////////////////////////////////////////
+
+		if (bChangeDir) {
+			createRow(cParent, "MyTorrentsView.menu.changeDirectory", null,
+					new Listener() {
+						public void handleEvent(Event e) {
+							TorrentUtil.changeDirSelectedTorrents(dms, parentShell);
+						}
+					});
+		}
+
+		// Open Details
+		if (hasSelection) {
+			createRow(cParent, "MyTorrentsView.menu.showdetails", "details",
+					new ListenerDMTask(dms) {
+						public void run(DownloadManager dm) {
+							UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+							if (uiFunctions != null) {
+								uiFunctions.getMDI().showEntryByID(
+										MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS, dm);
+							}
+						}
+					});
+		}
+
+		// Open Bar
+		if (hasSelection) {
+			FancyRowInfo row = createRow(cParent,
+					"MyTorrentsView.menu.showdownloadbar", "downloadBar",
+					new ListenerDMTask(dms) {
+						public void run(DownloadManager dm) {
+							if (DownloadBar.getManager().isOpen(dm)) {
+								DownloadBar.close(dm);
+							} else {
+								DownloadBar.open(dm, parentShell);
+							}
+						} // run
+					});
+			row.setSelection(barsOpened);
+		}
+
+		//////////////////////////////////////
+
+		if (hasSelection) {
+			FancyRowInfo rowSpeedDL = createRow(cParent,
+					"MyTorrentsView.menu.downSpeedLimit", "image.torrentspeed.down",
+					false, new Listener() {
+						public void handleEvent(Event e) {
+							Event event = new Event();
+							event.type = SWT.MouseUp;
+							event.widget = e.widget;
+							event.stateMask = e.stateMask;
+							event.button = e.button;
+							e.display.post(event);
+
+							AzureusCore core = AzureusCoreFactory.getSingleton();
+							SelectableSpeedMenu.invokeSlider((Control) event.widget, core,
+									dms, false, shell);
+							if (e.display.getActiveShell() != shell) {
+								if (!shell.isDisposed()) {
+									shell.dispose();
+								}
+								return;
+							}
+							FancyRowInfo rowInfo = findRowInfo(event.widget);
+							if (rowInfo != null) {
+								updateRowSpeed(rowInfo, false);
+							}
+
+						}
+					});
+			rowSpeedDL.keepMenu = true;
+
+			updateRowSpeed(rowSpeedDL, false);
+		}
+
+		if (hasSelection) {
+			FancyRowInfo rowSpeedUL = createRow(cParent,
+					"MyTorrentsView.menu.upSpeedLimit", "image.torrentspeed.up", false,
+					new Listener() {
+						public void handleEvent(Event e) {
+							Event event = new Event();
+							event.type = SWT.MouseUp;
+							event.widget = e.widget;
+							event.stateMask = e.stateMask;
+							event.button = e.button;
+							e.display.post(event);
+
+							AzureusCore core = AzureusCoreFactory.getSingleton();
+							SelectableSpeedMenu.invokeSlider((Control) e.widget, core, dms,
+									true, shell);
+							if (e.display.getActiveShell() != shell) {
+								if (!shell.isDisposed()) {
+									shell.dispose();
+								}
+								return;
+							}
+							FancyRowInfo rowInfo = findRowInfo(event.widget);
+							if (rowInfo != null) {
+								updateRowSpeed(rowInfo, true);
+							}
+						}
+					});
+			rowSpeedUL.keepMenu = true;
+
+			updateRowSpeed(rowSpeedUL, true);
+		}
+
+		//////////////////////////////////////
+
+		if (hasSelection && userMode > 0) {
+			createMenuRow(cParent, "MyTorrentsView.menu.tracker", null,
+					new FancyMenuRowInfoListener() {
+						public void buildMenu(Menu menu) {
+							boolean changeUrl = hasSelection;
+							boolean manualUpdate = true;
+							boolean allStopped = true;
+
+							int userMode = COConfigurationManager.getIntParameter("User Mode");
+							final boolean use_open_containing_folder = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled");
+
+							for (DownloadManager dm : dms) {
+								boolean stopped = ManagerUtils.isStopped(dm);
+
+								allStopped &= stopped;
+
+								if (userMode < 2) {
+									TRTrackerAnnouncer trackerClient = dm.getTrackerClient();
+
+									if (trackerClient != null) {
+										boolean update_state = ((SystemTime.getCurrentTime() / 1000
+												- trackerClient.getLastUpdateTime() >= TRTrackerAnnouncer.REFRESH_MINIMUM_SECS));
+										manualUpdate = manualUpdate & update_state;
+									}
+								}
+
+							}
+
+							TorrentUtil.addTrackerTorrentMenu(menu, dms, changeUrl,
+									manualUpdate, allStopped, use_open_containing_folder);
+						}
+
+					});
+		}
+
+		if (hasSelection) {
+			AzureusCore azureus_core = AzureusCoreFactory.getSingleton();
+
+			SpeedLimitHandler slh = SpeedLimitHandler.getSingleton(azureus_core);
+
+			if (slh.hasAnyProfiles()) {
+				
+				createMenuRow(cParent, IMenuConstants.MENU_ID_SPEED_LIMITS, null,
+						new FancyMenuRowInfoListener() {
+							public void buildMenu(Menu menu) {
+								TorrentUtil.addSpeedLimitsMenu(dms, menu);
+							}
+						});
+			}
+		}
+
+		if (userMode > 0 && hasSelection) {
+
+			boolean can_pause = false;
+
+			for (int i = 0; i < dms.length; i++) {
+				DownloadManager dm = dms[i];
+				if (ManagerUtils.isPauseable(dm)) {
+					can_pause = true;
+					break;
+				}
+			}
+
+			if ( can_pause ){
+				
+				createRow(detailArea, "MainWindow.menu.transfers.pausetransfersfor",
+					null, new Listener() {
+						public void handleEvent(Event event) {
+							TorrentUtil.pauseDownloadsFor(dms);
+						}
+					});
+			}
+		}
+
+		// === advanced > options ===
+		// ===========================
+
+		if (userMode > 0 && dms.length > 1) {
+			createRow(cParent, "label.options.and.info", null,
+					new ListenerDMTask(dms) {
+						public void run(DownloadManager[] dms) {
+							UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+							if (uiFunctions != null) {
+								uiFunctions.getMDI().showEntryByID(
+										MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_OPTIONS,
+										dms);
+							}
+						}
+					});
+		}
+
+		// === advanced > peer sources ===
+		// ===============================
+
+		if (userMode > 0) {
+			createMenuRow(cParent, "MyTorrentsView.menu.peersource", null,
+					new FancyMenuRowInfoListener() {
+						public void buildMenu(Menu menu) {
+							TorrentUtil.addPeerSourceSubMenu(dms, menu);
+						}
+					});
+		}
+
+		// IP Filter Enable
+		if (userMode > 0
+				&& IpFilterManagerFactory.getSingleton().getIPFilter().isEnabled()) {
+
+			boolean allEnabled = true;
+			boolean allDisabled = true;
+
+			for (int j = 0; j < dms.length; j++) {
+				DownloadManager dm = dms[j];
+
+				boolean filterDisabled = dm.getDownloadState().getFlag(
+						DownloadManagerState.FLAG_DISABLE_IP_FILTER);
+
+				if (filterDisabled) {
+					allEnabled = false;
+				} else {
+					allDisabled = false;
+				}
+			}
+
+			boolean bChecked;
+
+			if (allEnabled) {
+				bChecked = true;
+			} else if (allDisabled) {
+				bChecked = false;
+			} else {
+				bChecked = false;
+			}
+
+			final boolean newDisable = bChecked;
+
+			FancyRowInfo row = createRow(cParent, "MyTorrentsView.menu.ipf_enable",
+					null, new ListenerDMTask(dms) {
+						public void run(DownloadManager dm) {
+							dm.getDownloadState().setFlag(
+									DownloadManagerState.FLAG_DISABLE_IP_FILTER, newDisable);
+						}
+					});
+
+			row.setSelection(bChecked);
+		}
+
+		// === advanced > networks ===
+		// ===========================
+
+		if (userMode > 1) {
+			createMenuRow(cParent, "MyTorrentsView.menu.networks", null,
+					new FancyMenuRowInfoListener() {
+						public void buildMenu(Menu menu) {
+							TorrentUtil.addNetworksSubMenu(dms, menu);
+						}
+					});
+		}
+
+		// Advanced menu with stuff I don't know where to put
+		if (userMode > 0) {
+			createMenuRow(cParent, "MyTorrentsView.menu.advancedmenu", null,
+					new FancyMenuRowInfoListener() {
+						public void buildMenu(Menu menu) {
+
+							boolean allStopped = true;
+							boolean allScanSelected = true;
+							boolean allScanNotSelected = true;
+							boolean fileMove = true;
+
+							for (DownloadManager dm : dms) {
+								boolean stopped = ManagerUtils.isStopped(dm);
+
+								allStopped &= stopped;
+
+								fileMove = fileMove && dm.canMoveDataFiles();
+
+								boolean scan = dm.getDownloadState().getFlag(
+										DownloadManagerState.FLAG_SCAN_INCOMPLETE_PIECES);
+
+								// include DND files in incomplete stat, since a recheck may
+								// find those files have been completed
+								boolean incomplete = !dm.isDownloadComplete(true);
+
+								allScanSelected = incomplete && allScanSelected && scan;
+								allScanNotSelected = incomplete && allScanNotSelected && !scan;
+							}
+
+							boolean fileRescan = allScanSelected || allScanNotSelected;
+
+							final MenuItem itemFileMoveTorrent = new MenuItem(menu, SWT.PUSH);
+							Messages.setLanguageText(itemFileMoveTorrent,
+									"MyTorrentsView.menu.movetorrent");
+							itemFileMoveTorrent.addListener(SWT.Selection,
+									new ListenerDMTask(dms) {
+										public void run(DownloadManager[] dms) {
+											TorrentUtil.moveTorrentFile(parentShell, dms);
+										}
+									});
+							itemFileMoveTorrent.setEnabled(fileMove);
+
+							final MenuItem itemFileRescan = new MenuItem(menu, SWT.CHECK);
+							Messages.setLanguageText(itemFileRescan,
+									"MyTorrentsView.menu.rescanfile");
+							itemFileRescan.addListener(SWT.Selection,
+									new ListenerDMTask(dms) {
+										public void run(DownloadManager dm) {
+											dm.getDownloadState().setFlag(
+													DownloadManagerState.FLAG_SCAN_INCOMPLETE_PIECES,
+													itemFileRescan.getSelection());
+										}
+									});
+							itemFileRescan.setSelection(allScanSelected);
+							itemFileRescan.setEnabled(fileRescan);
+
+							// clear allocation
+
+							MenuItem itemFileClearAlloc = new MenuItem(menu, SWT.PUSH);
+							Messages.setLanguageText(itemFileClearAlloc,
+									"MyTorrentsView.menu.clear_alloc_data");
+							itemFileClearAlloc.addListener(SWT.Selection, new ListenerDMTask(
+									dms) {
+								public void run(DownloadManager dm) {
+									dm.setDataAlreadyAllocated(false);
+								}
+							});
+
+							itemFileClearAlloc.setEnabled(allStopped);
+
+							// clear resume
+
+							MenuItem itemFileClearResume = new MenuItem(menu, SWT.PUSH);
+							Messages.setLanguageText(itemFileClearResume,
+									"MyTorrentsView.menu.clear_resume_data");
+							itemFileClearResume.addListener(SWT.Selection,
+									new ListenerDMTask(dms) {
+										public void run(DownloadManager dm) {
+											dm.getDownloadState().clearResumeData();
+										}
+									});
+							itemFileClearResume.setEnabled(allStopped);
+
+							if (userMode > 1 && isSeedingView) {
+
+								boolean canSetSuperSeed = false;
+								boolean superSeedAllYes = true;
+								boolean superSeedAllNo = true;
+								for (DownloadManager dm : dms) {
+									PEPeerManager pm = dm.getPeerManager();
+
+									if (pm != null) {
+
+										if (pm.canToggleSuperSeedMode()) {
+
+											canSetSuperSeed = true;
+										}
+
+										if (pm.isSuperSeedMode()) {
+
+											superSeedAllYes = false;
+
+										} else {
+
+											superSeedAllNo = false;
+										}
+									} else {
+										superSeedAllYes = false;
+										superSeedAllNo = false;
+									}
+								}
+
+								final MenuItem itemSuperSeed = new MenuItem(menu, SWT.CHECK);
+
+								Messages.setLanguageText(itemSuperSeed,
+										"ManagerItem.superseeding");
+
+								boolean enabled = canSetSuperSeed
+										&& (superSeedAllNo || superSeedAllYes);
+
+								itemSuperSeed.setEnabled(enabled);
+
+								final boolean selected = superSeedAllNo;
+
+								if (enabled) {
+
+									itemSuperSeed.setSelection(selected);
+
+									itemSuperSeed.addListener(SWT.Selection, new ListenerDMTask(
+											dms) {
+										public void run(DownloadManager dm) {
+											PEPeerManager pm = dm.getPeerManager();
+
+											if (pm != null) {
+
+												if (pm.isSuperSeedMode() == selected
+														&& pm.canToggleSuperSeedMode()) {
+
+													pm.setSuperSeedMode(!selected);
+												}
+											}
+										}
+									});
+								}
+							}
+
+						}
+					});
+		}
+	}
+
+	private void updateRowSpeed(FancyRowInfo row, boolean isUpload) {
+		int dlRate = isUpload
+				? dms[0].getStats().getUploadRateLimitBytesPerSecond()
+				: dms[0].getStats().getDownloadRateLimitBytesPerSecond();
+		for (DownloadManager dm : dms) {
+			int dlRate2 = isUpload ? dm.getStats().getUploadRateLimitBytesPerSecond()
+					: dm.getStats().getDownloadRateLimitBytesPerSecond();
+			if (dlRate != dlRate2) {
+				dlRate = -2;
+				break;
+			}
+		}
+		if (dlRate != -2) {
+			String currentSpeed;
+			if (dlRate == 0) {
+				currentSpeed = MessageText.getString("MyTorrentsView.menu.setSpeed.unlimited");
+			} else if (dlRate < 0) {
+				currentSpeed = MessageText.getString("MyTorrentsView.menu.setSpeed.disabled");
+			} else {
+				currentSpeed = DisplayFormatters.formatByteCountToKiBEtcPerSec(dlRate);
+			}
+			row.setRightLabelText(currentSpeed);
+			row.cRow.layout();
+		}
+	}
+
+	private FancyMenuRowInfo createMenuRow(Composite cParent, String keyTitle,
+			String keyImage, final FancyMenuRowInfoListener listener) {
+
+		Listener showSWTMenuListener = new Listener() {
+			int lastX = 0;
+
+			int lastY = 0;
+
+			public void handleEvent(final Event event) {
+				if (event.type == SWT.MouseHover && lastX == event.x
+						&& lastY == event.y) {
+					return;
+				}
+				lastX = event.x;
+				lastY = event.y;
+
+				FancyMenuRowInfo rowInfo;
+
+				FancyRowInfo findRowInfo = findRowInfo(event.widget);
+				if (!(findRowInfo instanceof FancyMenuRowInfo)) {
+					return;
+				}
+
+				rowInfo = (FancyMenuRowInfo) findRowInfo;
+				currentMenu = rowInfo.getMenu();
+				if (currentMenu != null && !currentMenu.isDisposed()) {
+					return;
+				}
+
+				currentMenu = new Menu(parentShell, SWT.POP_UP);
+				rowInfo.setMenu(currentMenu);
+
+				currentMenu.addMenuListener(new MenuListener() {
+
+					public void menuShown(MenuEvent arg0) {
+						subMenuVisible = true;
+					}
+
+					public void menuHidden(final MenuEvent arg0) {
+						subMenuVisible = false;
+						currentMenu = null;
+						Utils.execSWTThreadLater(0, new Runnable() {
+
+							public void run() {
+								arg0.widget.dispose();
+							}
+						});
+					}
+				});
+				listener.buildMenu(currentMenu);
+
+				Composite rowComposite = rowInfo.getRow();
+
+				if (rowComposite != null) {
+					Point size = rowComposite.getSize();
+					Point menuLocation = rowComposite.toDisplay(size.x - 3, -3);
+					currentMenu.setLocation(menuLocation);
+				}
+				if (currentMenu.getItemCount() > 0) {
+					currentMenu.setVisible(true);
+
+					addMenuItemListener(currentMenu, listenerForTrigger);
+
+					final FancyMenuRowInfo currentRow = rowInfo;
+					final Point currentMousePos = event.display.getCursorLocation();
+					// Once the menu is visible, we don't get mouse events (even with addFilter)
+					Utils.execSWTThreadLater(300, new Runnable() {
+						public void run() {
+							Point cursorLocation = event.display.getCursorLocation();
+							if (currentMousePos.equals(cursorLocation)) {
+								Utils.execSWTThreadLater(300, this);
+								return;
+							}
+
+							Control control = Utils.getCursorControl();
+
+							if (control != null) {
+								Object data = control.getData("ID");
+								if (data instanceof HeaderInfo) {
+									HeaderInfo header = (HeaderInfo) data;
+									activateHeader(header);
+								}
+							}
+
+							Menu submenu = currentRow.getMenu();
+							if (submenu == null || submenu.isDisposed()
+									|| !submenu.isVisible()) {
+								return;
+							}
+							FancyRowInfo rowInfo = findRowInfo(control);
+							if (rowInfo != null && rowInfo != currentRow) {
+								submenu.setVisible(false);
+								return;
+							}
+							Utils.execSWTThreadLater(300, this);
+						}
+					});
+				} else {
+					currentMenu.dispose();
+					currentMenu = null;
+				}
+			}
+		};
+
+		FancyMenuRowInfo row = new FancyMenuRowInfo();
+		createRow(cParent, keyTitle, keyImage, true, showSWTMenuListener, row);
+		row.setHasSubMenu(true);
+
+		Composite cRow = row.getRow();
+		Utils.addListenerAndChildren(cRow, SWT.MouseHover, showSWTMenuListener);
+
+		row.setKeepMenu(true);
+		//row.getRightLabel().setText("\u25B6");
+		Label rightLabel = row.getRightLabel();
+		GridData gd = new GridData(12, SWT.DEFAULT);
+		rightLabel.setLayoutData(gd);
+		row.getRightLabel().addPaintListener(paintListenerArrow);
+
+		return row;
+	}
+
+	protected void addMenuItemListener(Menu menu, Listener l) {
+		for (MenuItem item : menu.getItems()) {
+			if (item.getStyle() == SWT.CASCADE) {
+				addMenuItemListener(item.getMenu(), l);
+			} else {
+				item.addListener(SWT.Selection, l);
+			}
+		}
+	}
+
+	private FancyRowInfo createRow(Composite cParent, String keyTitle,
+			final String keyImage, final Listener triggerListener) {
+		return createRow(cParent, keyTitle, keyImage, true, triggerListener,
+				new FancyRowInfo());
+	}
+
+	private FancyRowInfo createRow(Composite cParent, String keyTitle,
+			String keyImage, boolean triggerOnUp, Listener triggerListener) {
+		return createRow(cParent, keyTitle, keyImage, triggerOnUp, triggerListener,
+				new FancyRowInfo());
+	}
+
+	private FancyRowInfo createRow(Composite cParent, String keyTitle,
+			String keyImage, boolean triggerOnUp, Listener triggerListener,
+			FancyRowInfo rowInfo) {
+
+		Composite cRow = new Composite(cParent, SWT.NONE);
+		//cRow.setBackground(ColorCache.getRandomColor());
+
+		cRow.setData("ID", rowInfo);
+		GridLayout gridLayout = new GridLayout(4, false);
+		gridLayout.marginWidth = 1;
+		gridLayout.marginHeight = 3;
+		gridLayout.marginRight = 4;
+		gridLayout.horizontalSpacing = 0;
+		gridLayout.verticalSpacing = 0;
+		cRow.setLayout(gridLayout);
+
+		GridData gridData;
+
+		Label lblIcon = new Label(cRow, SWT.CENTER | SWT.NONE);
+		gridData = new GridData();
+		gridData.widthHint = 20;
+		lblIcon.setLayoutData(gridData);
+		if (keyImage != null) {
+			ImageLoader.getInstance().setLabelImage(lblIcon, keyImage);
+		}
+
+		Label item = new Label(cRow, SWT.NONE);
+		gridData = new GridData();
+		gridData.grabExcessHorizontalSpace = true;
+		gridData.horizontalIndent = 2;
+		item.setLayoutData(gridData);
+		Messages.setLanguageText(item, keyTitle);
+
+		Label lblCheck = new Label(cRow, SWT.CENTER);
+		gridData = new GridData();
+		gridData.widthHint = 13;
+		lblCheck.setLayoutData(gridData);
+
+		if (triggerListener != null) {
+			Utils.addListenerAndChildren(cRow, triggerOnUp ? SWT.MouseUp
+					: SWT.MouseDown, listenerForTrigger);
+		}
+
+		Utils.addListenerAndChildren(cRow, SWT.MouseEnter, listenerRow);
+		Utils.addListenerAndChildren(cRow, SWT.MouseExit, listenerRow);
+
+		cRow.addPaintListener(listenerRowPaint);
+
+		rowInfo.setListener(triggerListener);
+		rowInfo.setRow(cRow);
+		rowInfo.setIconLabel(lblIcon);
+		rowInfo.setText(item);
+		rowInfo.setRightLabel(null);
+		rowInfo.setCheckLabel(lblCheck);
+
+		listRowInfos.add(rowInfo);
+		return rowInfo;
+	}
+
+	private FancyRowInfo findRowInfo(Widget widget) {
+		Object findData = findData(widget, "ID");
+		if (findData instanceof FancyRowInfo) {
+			return (FancyRowInfo) findData;
+
+		}
+		return null;
+	}
+
+	protected Object findData(Widget widget, String id) {
+		if (widget == null || widget.isDisposed()) {
+			return null;
+		}
+		Object o = widget.getData(id);
+		if (o != null) {
+			return o;
+		}
+		if (widget instanceof Control) {
+			Control control = ((Control) widget).getParent();
+			while (control != null) {
+				o = control.getData(id);
+				if (o != null) {
+					return o;
+				}
+				control = control.getParent();
+			}
+		}
+		return null;
+	}
+
+	private Control createActionButton(final DownloadManager[] dms,
+			Composite cParent, String keyToolTip, String keyImage, boolean enable,
+			Listener listener) {
+		return createActionButton(dms, cParent, keyToolTip, keyImage, enable,
+				SWT.BORDER, listener);
+	}
+
+	private Control createActionButton(final DownloadManager[] dms,
+			Composite cParent, String keyToolTip, final String keyImage,
+			boolean enable, int style, final Listener listener) {
+		final Canvas item = new Canvas(cParent, SWT.NO_BACKGROUND
+				| SWT.DOUBLE_BUFFERED);
+
+		Listener l = new Listener() {
+			private boolean inWidget;
+
+			public void handleEvent(Event e) {
+				Control c = (Control) e.widget;
+				if (e.type == SWT.Paint) {
+					Point size = c.getSize();
+					if (inWidget) {
+						e.gc.setBackground(e.display.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
+					} else {
+						e.gc.setBackground(e.display.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
+					}
+					e.gc.setAdvanced(true);
+					e.gc.setAntialias(SWT.ON);
+					e.gc.fillRoundRectangle(0, 0, size.x - 1, size.y - 1, 6, 6);
+					e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW));
+					e.gc.drawRoundRectangle(0, 0, size.x - 1, size.y - 1, 6, 6);
+					e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
+					e.gc.drawRoundRectangle(1, 1, size.x - 3, size.y - 3, 6, 6);
+
+					Image image = ImageLoader.getInstance().getImage(
+							c.isEnabled() ? keyImage : keyImage + "-disabled");
+					Rectangle bounds = image.getBounds();
+					int x = size.x / 2 - bounds.width / 2;
+					int y = size.y / 2 - bounds.height / 2;
+
+					e.gc.drawImage(image, x, y);
+				} else if (e.type == SWT.MouseEnter) {
+					inWidget = true;
+					c.redraw();
+				} else if (e.type == SWT.MouseExit) {
+					inWidget = false;
+					c.redraw();
+				}
+			}
+		};
+
+		item.addListener(SWT.MouseEnter, l);
+		item.addListener(SWT.MouseExit, l);
+		item.addListener(SWT.Paint, l);
+
+		Messages.setLanguageTooltip(item, keyToolTip);
+		item.addListener(SWT.MouseUp, new Listener() {
+			public void handleEvent(Event event) {
+				listener.handleEvent(event);
+				shell.dispose();
+			}
+		});
+		item.setEnabled(enable);
+
+		RowData rowData = new RowData(30, 21);
+		item.setLayoutData(rowData);
+
+		return item;
+	}
+
+	public void buildTorrentCustomMenu_Organize(final Composite detailArea,
+			final DownloadManager[] dms) {
+
+		if (!hasSelection) {
+			return;
+		}
+		
+			// assign tags
+			
+		createMenuRow(detailArea, "label.tags", "image.sidebar.tag-overview",
+				new FancyMenuRowInfoListener() {
+					public void buildMenu(Menu menu) {
+						TagUIUtils.addLibraryViewTagsSubMenu(dms, menu, detailArea);
+					}
+				});
+
+			// assign cats
+		
+		createMenuRow(detailArea, "MyTorrentsView.menu.setCategory",
+				"image.sidebar.library", new FancyMenuRowInfoListener() {
+					public void buildMenu(Menu menu) {
+						TorrentUtil.addCategorySubMenu(dms, menu, detailArea);
+					}
+				});
+
+			// Archive
+		
+		final List<Download>	ar_dms = new ArrayList<Download>();
+		
+		for ( DownloadManager dm: dms ){
+			
+			Download stub = PluginCoreUtils.wrap(dm);
+			
+			if ( !stub.canStubbify()){
+				
+				continue;
+			}
+			
+			ar_dms.add( stub );
+		}
+		
+		if ( ar_dms.size() > 0 ){
+			
+			createRow(
+				detailArea, 
+				"MyTorrentsView.menu.archive", "image.sidebar.archive",
+				new Listener() 
+				{
+					public void handleEvent(Event event) {
+							
+						ManagerUtils.moveToArchive( ar_dms, null );
+					}
+				});
+		}
+		
+
+			// Advanced - > Rename
+		
+		createRow(detailArea, "MyTorrentsView.menu.rename", null, new Listener() {
+			public void handleEvent(Event event) {
+				for (DownloadManager dm : dms) {
+					AdvRenameWindow window = new AdvRenameWindow();
+					window.open(dm);
+				}
+			}
+		});
+
+			// Reposition
+		
+		createRow(detailArea, "MyTorrentsView.menu.reposition.manual", null,
+				new Listener() {
+					public void handleEvent(Event event) {
+						TorrentUtil.repositionManual(tv, dms, parentShell, isSeedingView);
+					}
+				});
+
+			// Filter
+		
+		if (tv.getSWTFilter() != null) {
+			createRow(detailArea, "MyTorrentsView.menu.filter", null, new Listener() {
+				public void handleEvent(Event event) {
+					tv.openFilterDialog();
+				}
+			});
+		}
+
+	}
+
+	public void buildTorrentCustomMenu_Social(Composite detailArea) {
+
+		boolean isTrackerOn = TRTrackerUtils.isTrackerEnabled();
+		int userMode = COConfigurationManager.getIntParameter("User Mode");
+
+		if (hasSelection) {
+			createMenuRow(detailArea, "ConfigView.section.interface.alerts", null,
+					new FancyMenuRowInfoListener() {
+						public void buildMenu(Menu menu) {
+							MenuFactory.addAlertsMenu(menu, false, dms);
+						}
+					});
+		}
+
+		if (userMode > 0 && isTrackerOn && hasSelection) {
+			// Host
+			createRow(detailArea, "MyTorrentsView.menu.host", "host", new Listener() {
+				public void handleEvent(Event event) {
+					TorrentUtil.hostTorrents(dms);
+				}
+			});
+
+			// Publish
+			createRow(detailArea, "MyTorrentsView.menu.publish", "publish",
+					new Listener() {
+						public void handleEvent(Event event) {
+							TorrentUtil.publishTorrents(dms);
+						}
+					});
+		}
+
+		if (userMode > 0) {
+			// Advanced > Export > Export XML
+			if (dms.length == 1) {
+				String title = MessageText.getString("MyTorrentsView.menu.exportmenu")
+						+ ": " + MessageText.getString("MyTorrentsView.menu.export");
+				FancyRowInfo row = createRow(detailArea, null, null,
+						new ListenerDMTask(dms) {
+							public void run(DownloadManager dm) {
+								if (dm != null) {
+									new ExportTorrentWizard(parentShell.getDisplay(), dm);
+								}
+							}
+						});
+				row.getText().setText(title);
+			}
+
+			// Advanced > Export > Export Torrent
+			String title = MessageText.getString("MyTorrentsView.menu.exportmenu")
+					+ ": " + MessageText.getString("MyTorrentsView.menu.exporttorrent");
+			FancyRowInfo row = createRow(detailArea, null, null, new ListenerDMTask(
+					dms) {
+				public void run(DownloadManager[] dms) {
+					TorrentUtil.exportTorrent(dms, parentShell);
+				}
+			});
+			row.getText().setText(title);
+
+			// Advanced > Export > WebSeed URL
+			createRow(detailArea, "MyTorrentsView.menu.exporthttpseeds", null,
+					new ListenerDMTask(dms) {
+						public void run(DownloadManager[] dms) {
+							TorrentUtil.exportHTTPSeeds(dms);
+						}
+					});
+		}
+
+		// personal share
+		if (isSeedingView) {
+			createRow(detailArea, "MyTorrentsView.menu.create_personal_share", null,
+					new ListenerDMTask(dms, false) {
+						public void run(DownloadManager dm) {
+							File file = dm.getSaveLocation();
+
+							Map<String, String> properties = new HashMap<String, String>();
+
+							properties.put(ShareManager.PR_PERSONAL, "true");
+
+							if (file.isFile()) {
+
+								ShareUtils.shareFile(file.getAbsolutePath(), properties);
+
+							} else if (file.isDirectory()) {
+
+								ShareUtils.shareDir(file.getAbsolutePath(), properties);
+							}
+						}
+					});
+		}
+
+	}
+
+	public void addTableItemsWithID(Composite detailArea, String menuID,
+			String[] ids) {
+
+		TableContextMenuItem[] items = TableContextMenuManager.getInstance().getAllAsArray(
+				menuID);
+		if (DEBUG_MENU) {
+			System.out.println("AddItemsWithID " + menuID + ": " + items.length);
+		}
+
+		addItemsArray(detailArea, items, ids);
+
+	}
+
+	public void addMenuItemsWithID(Composite detailArea, String menuID,
+			String[] ids) {
+
+		org.gudy.azureus2.plugins.ui.menus.MenuItem[] items = MenuItemManager.getInstance().getAllAsArray(
+				menuID);
+		if (DEBUG_MENU) {
+			System.out.println("AddItemsWithID " + menuID + ": " + items.length);
+		}
+
+		addItemsArray(detailArea, items, ids);
+
+	}
+
+	public void addItemsArray(final Composite detailArea,
+			org.gudy.azureus2.plugins.ui.menus.MenuItem[] items, String[] onlyIDs) {
+		int userMode = COConfigurationManager.getIntParameter("User Mode");
+
+		for (int i = 0; i < onlyIDs.length; i++) {
+			String id = onlyIDs[i];
+			if (DEBUG_MENU) {
+				System.out.println(" addItemsArray " + id);
+			}
+			Integer requiredUserMode = mapMovedPluginMenuUserMode.get(id);
+			if (requiredUserMode != null && userMode < requiredUserMode) {
+				if (DEBUG_MENU) {
+					System.out.println(" skipped, usermode is " + userMode
+							+ " but requires " + requiredUserMode);
+				}
+				continue;
+			}
+
+			for (final org.gudy.azureus2.plugins.ui.menus.MenuItem item : items) {
+				String key = item.getResourceKey();
+				if (!id.equals(key)) {
+					continue;
+				}
+
+				addPluginItem(detailArea, item);
+				if (DEBUG_MENU) {
+					System.out.println(" found, added");
+				}
+				break;
+			}
+		}
+	}
+
+	public void buildTorrentCustomMenu_Other(final Composite detailArea,
+			List<org.gudy.azureus2.plugins.ui.menus.MenuItem> items) {
+
+		for (org.gudy.azureus2.plugins.ui.menus.MenuItem item : items) {
+
+			if (DEBUG_MENU) {
+				System.out.println(item.getText() + ": " + item.getResourceKey());
+			}
+
+			// TableContextMenuItems get rows as datasource.. the rest get DownloadManagers
+			addPluginItem(detailArea, item);
+		}
+
+	}
+
+	private Object[] getTarget(org.gudy.azureus2.plugins.ui.menus.MenuItem item) {
+		if (MenuManager.MENU_TABLE.equals(item.getMenuID())) {
+			return tv.getSelectedRows();
+		}
+		Object[] dataSources = tv.getSelectedDataSources(false);
+		Download[] downloads = new Download[dataSources.length];
+		System.arraycopy(dataSources, 0, downloads, 0, dataSources.length);
+		return downloads;
+	}
+
+	private void addPluginItem(Composite detailArea,
+			final org.gudy.azureus2.plugins.ui.menus.MenuItem item) {
+
+		// menuWillBeShown listeners might change the visibility, so run before check
+		MenuItemImpl menuImpl = ((MenuItemImpl) item);
+		menuImpl.invokeMenuWillBeShownListeners(getTarget(item));
+
+		if (!item.isVisible()) {
+			if (DEBUG_MENU) {
+				System.out.println("Menu Not Visible: " + item.getText() + ": "
+						+ item.getMenuID());
+			}
+			return;
+		}
+
+		Graphic graphic = item.getGraphic();
+		FancyRowInfo row;
+
+		if (DEBUG_MENU) {
+			System.out.println("Menu " + item.getText() + ": " + item.getMenuID());
+		}
+
+		if (item.getStyle() == org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_MENU) {
+
+			row = createMenuRow(detailArea, item.getResourceKey(), null,
+					new FancyMenuRowInfoListener() {
+						public void buildMenu(Menu menu) {
+							if (dms.length != 0) {
+								MenuBuilder submenuBuilder = ((MenuItemImpl) item).getSubmenuBuilder();
+								if (submenuBuilder != null) {
+									try {
+										item.removeAllChildItems();
+										submenuBuilder.buildSubmenu(item, getTarget(item));
+									} catch (Throwable t) {
+										Debug.out(t);
+									}
+								}
+
+								MenuBuildUtils.addPluginMenuItems(item.getItems(), menu, false,
+										true, new MenuBuildUtils.PluginMenuController() {
+
+											public Listener makeSelectionListener(
+													final org.gudy.azureus2.plugins.ui.menus.MenuItem plugin_menu_item) {
+												return new TableSelectedRowsListener(tv, false) {
+													public boolean run(TableRowCore[] rows) {
+														if (rows.length != 0) {
+															((MenuItemImpl) plugin_menu_item).invokeListenersMulti(getTarget(item));
+														}
+														return true;
+													}
+												};
+											}
+
+											public void notifyFillListeners(
+													org.gudy.azureus2.plugins.ui.menus.MenuItem menu_item) {
+												((MenuItemImpl) menu_item).invokeMenuWillBeShownListeners(getTarget(item));
+											}
+
+											// @see org.gudy.azureus2.ui.swt.MenuBuildUtils.PluginMenuController#buildSubmenu(org.gudy.azureus2.plugins.ui.menus.MenuItem)
+											public void buildSubmenu(
+													org.gudy.azureus2.plugins.ui.menus.MenuItem parent) {
+												org.gudy.azureus2.plugins.ui.menus.MenuBuilder submenuBuilder = ((MenuItemImpl) parent).getSubmenuBuilder();
+												if (submenuBuilder != null) {
+													try {
+														parent.removeAllChildItems();
+														submenuBuilder.buildSubmenu(parent, getTarget(item));
+													} catch (Throwable t) {
+														Debug.out(t);
+													}
+												}
+											}
+										});
+							}
+						}
+
+					});
+		} else {
+			row = createRow(detailArea, item.getResourceKey(), null,
+					new TableSelectedRowsListener(tv, false) {
+
+						public boolean run(TableRowCore[] rows) {
+							if (rows.length != 0) {
+								((MenuItemImpl) item).invokeListenersMulti(getTarget(item));
+							}
+							return true;
+						}
+
+					});
+		}
+
+		row.setEnabled(item.isEnabled());
+		if (graphic instanceof UISWTGraphic) {
+			row.getIconLabel().setImage(((UISWTGraphic) graphic).getImage());
+		} else if (graphic instanceof GraphicURI) {
+			ImageLoader.getInstance().setLabelImage(row.getIconLabel(),
+					((GraphicURI) graphic).getURI().toString());
+		}
+	}
+
+	protected void buildTorrentCustomMenu_Content(Composite detailArea,
+			final DownloadManager[] dms) {
+
+		// Run Data File
+		if (hasSelection) {
+			createRow(detailArea, "MyTorrentsView.menu.open", "run",
+					new ListenerDMTask(dms) {
+						public void run(DownloadManager[] dms) {
+							TorrentUtil.runDataSources(dms);
+						}
+					});
+		}
+
+		// Explore (or open containing folder)
+		if (hasSelection) {
+			final boolean use_open_containing_folder = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled");
+			createRow(detailArea, "MyTorrentsView.menu."
+					+ (use_open_containing_folder ? "open_parent_folder" : "explore"),
+					null, new ListenerDMTask(dms, false) {
+						public void run(DownloadManager dm) {
+							ManagerUtils.open(dm, use_open_containing_folder);
+						}
+					});
+		}
+
+		// Open In Browser
+		
+		if (hasSelection) {
+			createMenuRow(
+				detailArea, 
+				"MyTorrentsView.menu.browse",
+				null, 
+				new FancyMenuRowInfoListener() 
+				{
+					public void 
+					buildMenu(
+						Menu menuBrowse ) 
+					{
+						final MenuItem itemBrowsePublic = new MenuItem(menuBrowse, SWT.PUSH);
+						itemBrowsePublic.setText( MessageText.getString( "label.public" ) + "..." );
+						itemBrowsePublic.addListener(
+							SWT.Selection, 
+							new ListenerDMTask(dms, false) {
+								public void run(DownloadManager dm) {
+									ManagerUtils.browse( dm, false, true );
+								}
+							});
+						
+						final MenuItem itemBrowseAnon = new MenuItem(menuBrowse, SWT.PUSH);
+						itemBrowseAnon.setText( MessageText.getString( "label.anon" ) + "..." );
+						itemBrowseAnon.addListener(
+							SWT.Selection, 
+							new ListenerDMTask(dms, false) {
+								public void run(DownloadManager dm) {
+									ManagerUtils.browse( dm, true, true );
+								}
+							});
+						
+						new MenuItem(menuBrowse, SWT.SEPARATOR);
+						
+						final MenuItem itemBrowseURL = new MenuItem(menuBrowse, SWT.PUSH);
+						Messages.setLanguageText(itemBrowseURL, "label.copy.url.to.clip" );
+						itemBrowseURL.addListener(SWT.Selection, new Listener() {
+							public void handleEvent(Event event){
+								Utils.getOffOfSWTThread(
+									new AERunnable() {
+										@Override
+										public void runSupport() {
+											String url = ManagerUtils.browse(dms[0], true, false );
+											if ( url != null ){
+												ClipboardCopy.copyToClipBoard( url );
+											}
+										}
+									});
+							}});
+						
+						itemBrowseURL.setEnabled( dms.length == 1 );
+						
+						new MenuItem(menuBrowse, SWT.SEPARATOR);
+
+						final MenuItem itemBrowseDir = new MenuItem(menuBrowse, SWT.CHECK);
+						Messages.setLanguageText(itemBrowseDir, "library.launch.web.in.browser.dir.list");
+						itemBrowseDir.setSelection(COConfigurationManager.getBooleanParameter( "Library.LaunchWebsiteInBrowserDirList"));
+						itemBrowseDir.addListener(SWT.Selection, new Listener() {
+							public void handleEvent(Event event) {
+								COConfigurationManager.setParameter( "Library.LaunchWebsiteInBrowserDirList", itemBrowseDir.getSelection());
+							}
+						});
+					}
+				});
+		}
+		
+		// Move Data Files
+		boolean fileMove = true;
+		for (int i = 0; i < dms.length; i++) {
+			DownloadManager dm = dms[i];
+			if (!dm.canMoveDataFiles()) {
+				fileMove = false;
+				break;
+			}
+		}
+		if (fileMove) {
+			createRow(detailArea, "MyTorrentsView.menu.movedata", null,
+					new ListenerDMTask(dms) {
+						public void run(DownloadManager[] dms) {
+							TorrentUtil.moveDataFiles(parentShell, dms);
+						}
+					});
+		}
+
+		createRow(detailArea, "MyTorrentsView.menu.checkfilesexist", null,
+				new ListenerDMTask(dms) {
+					public void run(DownloadManager dm) {
+						dm.filesExist(true);
+					}
+				});
+
+		createRow(detailArea, "MyTorrentsView.menu.thisColumn.toClipboard", null,
+				new Listener() {
+					public void handleEvent(Event event) {
+						String sToClipboard = "";
+						if (column == null) {
+							return;
+						}
+						String columnName = column.getName();
+						if (columnName == null) {
+							return;
+						}
+						TableRowCore[] rows = tv.getSelectedRows();
+						for (TableRowCore row : rows) {
+							if (row != rows[0]) {
+								sToClipboard += "\n";
+							}
+							TableCellCore cell = row.getTableCellCore(columnName);
+							if (cell != null) {
+								sToClipboard += cell.getClipboardText();
+							}
+						}
+						if (sToClipboard.length() == 0) {
+							return;
+						}
+						new Clipboard(Display.getDefault()).setContents(new Object[] {
+							sToClipboard
+						}, new Transfer[] {
+							TextTransfer.getInstance()
+						});
+					}
+				});
+	}
+
+	private HeaderInfo addHeader(String id, String title, AERunnable runnable) {
+		Composite composite = new Composite(topArea, SWT.NONE);
+
+		HeaderInfo headerInfo = new HeaderInfo(id, runnable, composite);
+
+		composite.setBackgroundMode(SWT.INHERIT_FORCE);
+		FillLayout fillLayout = new FillLayout();
+		fillLayout.marginWidth = 6;
+		fillLayout.marginHeight = 2;
+		composite.setLayout(fillLayout);
+		Display d = composite.getDisplay();
+		composite.setBackground(d.getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+		composite.setForeground(d.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
+
+		Label control = new Label(composite, SWT.NONE);
+		Messages.setLanguageText(control, title);
+		control.setData("ID", headerInfo);
+
+		control.addListener(SWT.MouseEnter, headerListener);
+		control.addListener(SWT.Touch, headerListener);
+		control.addListener(SWT.MouseExit, headerListener);
+		control.addListener(SWT.Paint, headerListener);
+
+		listHeaders.add(headerInfo);
+		return headerInfo;
+	}
+
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/TorrentUtil.java b/azureus2/src/org/gudy/azureus2/ui/swt/TorrentUtil.java
index 14e101b..3216dea 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/TorrentUtil.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/TorrentUtil.java
@@ -1,7 +1,7 @@
 /*
  * Created on 9 Jul 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
@@ -37,6 +34,7 @@ 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.disk.DiskManagerFileInfoSet;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerState;
 import org.gudy.azureus2.core3.global.GlobalManager;
@@ -54,16 +52,16 @@ import org.gudy.azureus2.core3.tracker.util.TRTrackerUtils;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadStub.DownloadStubEx;
 import org.gudy.azureus2.plugins.sharing.ShareManager;
-import org.gudy.azureus2.plugins.ui.*;
+import org.gudy.azureus2.plugins.ui.UIInputReceiver;
+import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
+import org.gudy.azureus2.plugins.ui.UIPluginView;
 import org.gudy.azureus2.plugins.ui.tables.TableColumn;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
 import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
 import org.gudy.azureus2.ui.swt.exporttorrent.wizard.ExportTorrentWizard;
-import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
-import org.gudy.azureus2.ui.swt.mainwindow.IMenuConstants;
-import org.gudy.azureus2.ui.swt.mainwindow.MenuFactory;
-import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
+import org.gudy.azureus2.ui.swt.mainwindow.*;
 import org.gudy.azureus2.ui.swt.maketorrent.*;
 import org.gudy.azureus2.ui.swt.minibar.DownloadBar;
 import org.gudy.azureus2.ui.swt.sharing.ShareUtils;
@@ -85,18 +83,19 @@ import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.UserPrompterResultListener;
 import com.aelitis.azureus.ui.common.table.TableColumnCore;
 import com.aelitis.azureus.ui.common.table.TableView;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.selectedcontent.*;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
 import com.aelitis.azureus.ui.swt.mdi.MdiEntrySWT;
 import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
 
-
 /**
  * @author Allan Crooks
  *
  */
-public class TorrentUtil {
+public class TorrentUtil
+{
 
 	// selected_dl_types -> 0 (determine that automatically), +1 (downloading), +2 (seeding), +3 (mixed - not used by anything yet) 
 	public static void fillTorrentMenu(final Menu menu,
@@ -105,7 +104,7 @@ public class TorrentUtil {
 			int selected_dl_types, final TableView tv) {
 
 		// TODO: Build submenus on the fly
-		
+
 		final boolean isSeedingView;
 		switch (selected_dl_types) {
 			case 1:
@@ -166,8 +165,7 @@ public class TorrentUtil {
 					int maxul = dm.getStats().getUploadRateLimitBytesPerSecond();
 					if (maxul == 0) {
 						upSpeedUnlimited = true;
-					}
-					else {
+					} else {
 						if (maxul > upSpeedSetMax) {
 							upSpeedSetMax = maxul;
 						}
@@ -181,8 +179,7 @@ public class TorrentUtil {
 					int maxdl = dm.getStats().getDownloadRateLimitBytesPerSecond();
 					if (maxdl == 0) {
 						downSpeedUnlimited = true;
-					}
-					else {
+					} else {
 						if (maxdl > downSpeedSetMax) {
 							downSpeedSetMax = maxdl;
 						}
@@ -193,8 +190,7 @@ public class TorrentUtil {
 					}
 					totalDownSpeed += maxdl;
 
-				}
-				catch (Exception ex) {
+				} catch (Exception ex) {
 					Debug.printStackTrace(ex);
 				}
 
@@ -207,7 +203,8 @@ public class TorrentUtil {
 
 				recheck = recheck || dm.canForceRecheck();
 
-				forceStartEnabled = forceStartEnabled || ManagerUtils.isForceStartable(dm);
+				forceStartEnabled = forceStartEnabled
+						|| ManagerUtils.isForceStartable(dm);
 
 				forceStart = forceStart || dm.isForceStart();
 
@@ -221,13 +218,16 @@ public class TorrentUtil {
 					TRTrackerAnnouncer trackerClient = dm.getTrackerClient();
 
 					if (trackerClient != null) {
-						boolean update_state = ((SystemTime.getCurrentTime() / 1000 - trackerClient.getLastUpdateTime() >= TRTrackerAnnouncer.REFRESH_MINIMUM_SECS));
+						boolean update_state = ((SystemTime.getCurrentTime() / 1000
+								- trackerClient.getLastUpdateTime() >= TRTrackerAnnouncer.REFRESH_MINIMUM_SECS));
 						manualUpdate = manualUpdate & update_state;
 					}
 
 				}
 				int state = dm.getState();
-				bChangeDir &= (state == DownloadManager.STATE_ERROR || state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_QUEUED);;
+				bChangeDir &= (state == DownloadManager.STATE_ERROR
+						|| state == DownloadManager.STATE_STOPPED || state == DownloadManager.STATE_QUEUED);
+				;
 				/**
 				 * Only perform a test on disk if:
 				 *    1) We are currently set to allow the "Change Data Directory" option, and
@@ -238,13 +238,14 @@ public class TorrentUtil {
 					bChangeDir = dm.isDataAlreadyAllocated();
 					if (bChangeDir && state == DownloadManager.STATE_ERROR) {
 						// filesExist is way too slow!
-						bChangeDir = !dm.filesExist( true );
+						bChangeDir = !dm.filesExist(true);
 					} else {
 						bChangeDir = false;
 					}
 				}
 
-				boolean scan = dm.getDownloadState().getFlag(DownloadManagerState.FLAG_SCAN_INCOMPLETE_PIECES);
+				boolean scan = dm.getDownloadState().getFlag(
+						DownloadManagerState.FLAG_SCAN_INCOMPLETE_PIECES);
 
 				// include DND files in incomplete stat, since a recheck may
 				// find those files have been completed
@@ -266,13 +267,11 @@ public class TorrentUtil {
 
 						superSeedAllYes = false;
 
-					}
-					else {
+					} else {
 
 						superSeedAllNo = false;
 					}
-				}
-				else {
+				} else {
 					superSeedAllYes = false;
 					superSeedAllNo = false;
 				}
@@ -280,8 +279,7 @@ public class TorrentUtil {
 
 			fileRescan = allScanSelected || allScanNotSelected;
 
-		}
-		else { // empty right-click
+		} else { // empty right-click
 			barsOpened = false;
 			forceStart = false;
 			forceStartEnabled = false;
@@ -301,7 +299,8 @@ public class TorrentUtil {
 
 		if (bChangeDir) {
 			MenuItem menuItemChangeDir = new MenuItem(menu, SWT.PUSH);
-			Messages.setLanguageText(menuItemChangeDir, "MyTorrentsView.menu.changeDirectory");
+			Messages.setLanguageText(menuItemChangeDir,
+					"MyTorrentsView.menu.changeDirectory");
 			menuItemChangeDir.addListener(SWT.Selection, new Listener() {
 				public void handleEvent(Event e) {
 					changeDirSelectedTorrents(dms, composite.getShell());
@@ -315,11 +314,12 @@ public class TorrentUtil {
 			Messages.setLanguageText(itemDetails, "MyTorrentsView.menu.showdetails");
 			menu.setDefaultItem(itemDetails);
 			Utils.setMenuItemImage(itemDetails, "details");
-			itemDetails.addListener(SWT.Selection, new DMTask(dms) {
+			itemDetails.addListener(SWT.Selection, new ListenerDMTask(dms) {
 				public void run(DownloadManager dm) {
 					UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 					if (uiFunctions != null) {
-						uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, dm);
+						uiFunctions.getMDI().showEntryByID(
+								MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS, dm);
 					}
 				}
 			});
@@ -330,12 +330,11 @@ public class TorrentUtil {
 		final MenuItem itemBar = new MenuItem(menu, SWT.CHECK);
 		Messages.setLanguageText(itemBar, "MyTorrentsView.menu.showdownloadbar");
 		Utils.setMenuItemImage(itemBar, "downloadBar");
-		itemBar.addListener(SWT.Selection, new DMTask(dms) {
+		itemBar.addListener(SWT.Selection, new ListenerDMTask(dms) {
 			public void run(DownloadManager dm) {
 				if (DownloadBar.getManager().isOpen(dm)) {
 					DownloadBar.close(dm);
-				}
-				else {
+				} else {
 					DownloadBar.open(dm, menu.getShell());
 				}
 			} // run
@@ -350,7 +349,7 @@ public class TorrentUtil {
 		final MenuItem itemOpen = new MenuItem(menu, SWT.PUSH);
 		Messages.setLanguageText(itemOpen, "MyTorrentsView.menu.open");
 		Utils.setMenuItemImage(itemOpen, "run");
-		itemOpen.addListener(SWT.Selection, new DMTask(dms) {
+		itemOpen.addListener(SWT.Selection, new ListenerDMTask(dms) {
 			public void run(DownloadManager[] dms) {
 				runDataSources(dms);
 			}
@@ -360,14 +359,71 @@ public class TorrentUtil {
 		// Explore (or open containing folder)
 		final boolean use_open_containing_folder = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled");
 		final MenuItem itemExplore = new MenuItem(menu, SWT.PUSH);
-		Messages.setLanguageText(itemExplore, "MyTorrentsView.menu." + (use_open_containing_folder ? "open_parent_folder" : "explore"));
-		itemExplore.addListener(SWT.Selection, new DMTask(dms, false) {
+		Messages.setLanguageText(itemExplore, "MyTorrentsView.menu."
+				+ (use_open_containing_folder ? "open_parent_folder" : "explore"));
+		itemExplore.addListener(SWT.Selection, new ListenerDMTask(dms, false) {
 			public void run(DownloadManager dm) {
 				ManagerUtils.open(dm, use_open_containing_folder);
 			}
 		});
 		itemExplore.setEnabled(hasSelection);
-
+		
+		// Open in browser
+		
+		final Menu menuBrowse = new Menu(menu.getShell(),SWT.DROP_DOWN);
+		final MenuItem itemBrowse = new MenuItem(menu, SWT.CASCADE);
+		Messages.setLanguageText(itemBrowse, "MyTorrentsView.menu.browse");
+		itemBrowse.setMenu(menuBrowse);
+				
+		final MenuItem itemBrowsePublic = new MenuItem(menuBrowse, SWT.PUSH);
+		itemBrowsePublic.setText( MessageText.getString( "label.public" ) + "..." );
+		itemBrowsePublic.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(DownloadManager dm) {
+				ManagerUtils.browse(dm,false,true);
+			}
+		});
+		
+		final MenuItem itemBrowseAnon = new MenuItem(menuBrowse, SWT.PUSH);
+		itemBrowseAnon.setText( MessageText.getString( "label.anon" ) + "..." );
+		itemBrowseAnon.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(DownloadManager dm) {
+				ManagerUtils.browse(dm,true,true);
+			}
+		});
+		
+		new MenuItem(menuBrowse, SWT.SEPARATOR);
+		
+		final MenuItem itemBrowseURL = new MenuItem(menuBrowse, SWT.PUSH);
+		Messages.setLanguageText(itemBrowseURL, "label.copy.url.to.clip" );
+		itemBrowseURL.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event){
+				Utils.getOffOfSWTThread(
+					new AERunnable() {
+						@Override
+						public void runSupport() {
+							String url = ManagerUtils.browse(dms[0], true, false );
+							if ( url != null ){
+								ClipboardCopy.copyToClipBoard( url );
+							}
+						}
+					});
+			}});
+		
+		itemBrowseURL.setEnabled( dms.length == 1 );
+		
+		new MenuItem(menuBrowse, SWT.SEPARATOR);
+		
+		final MenuItem itemBrowseDir = new MenuItem(menuBrowse, SWT.CHECK);
+		Messages.setLanguageText(itemBrowseDir, "library.launch.web.in.browser.dir.list");
+		itemBrowseDir.setSelection(COConfigurationManager.getBooleanParameter( "Library.LaunchWebsiteInBrowserDirList"));
+		itemBrowseDir.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				COConfigurationManager.setParameter( "Library.LaunchWebsiteInBrowserDirList", itemBrowseDir.getSelection());
+			}
+		});
+		
+		itemBrowse.setEnabled(hasSelection);
+		
 		// === advanced menu ===
 
 		final MenuItem itemAdvanced = new MenuItem(menu, SWT.CASCADE);
@@ -379,14 +435,18 @@ public class TorrentUtil {
 
 		// advanced > Download Speed Menu //
 
-		long maxDownload = COConfigurationManager.getIntParameter("Max Download Speed KBs", 0) * 1024L;
-		long maxUpload = COConfigurationManager.getIntParameter("Max Upload Speed KBs", 0) * 1024L;
+		long maxDownload = COConfigurationManager.getIntParameter(
+				"Max Download Speed KBs", 0) * 1024L;
+		long maxUpload = COConfigurationManager.getIntParameter(
+				"Max Upload Speed KBs", 0) * 1024L;
 
-		ViewUtils.addSpeedMenu(menu.getShell(), menuAdvanced, true, true, true, hasSelection, downSpeedDisabled, downSpeedUnlimited,
-				totalDownSpeed, downSpeedSetMax, maxDownload, upSpeedDisabled, upSpeedUnlimited, totalUpSpeed,
-				upSpeedSetMax, maxUpload, dms.length, new ViewUtils.SpeedAdapter() {
+		ViewUtils.addSpeedMenu(menu.getShell(), menuAdvanced, true, true, true,
+				hasSelection, downSpeedDisabled, downSpeedUnlimited, totalDownSpeed,
+				downSpeedSetMax, maxDownload, upSpeedDisabled, upSpeedUnlimited,
+				totalUpSpeed, upSpeedSetMax, maxUpload, dms.length, null,
+				new ViewUtils.SpeedAdapter() {
 					public void setDownSpeed(final int speed) {
-						DMTask task = new DMTask(dms) {
+						ListenerDMTask task = new ListenerDMTask(dms) {
 							public void run(DownloadManager dm) {
 								dm.getStats().setDownloadRateLimitBytesPerSecond(speed);
 							}
@@ -395,7 +455,7 @@ public class TorrentUtil {
 					}
 
 					public void setUpSpeed(final int speed) {
-						DMTask task = new DMTask(dms) {
+						ListenerDMTask task = new ListenerDMTask(dms) {
 							public void run(DownloadManager dm) {
 								dm.getStats().setUploadRateLimitBytesPerSecond(speed);
 							}
@@ -405,693 +465,198 @@ public class TorrentUtil {
 				});
 
 		// advanced > Speed Limits
-		
-		final Menu speedLimitsMenu = new Menu(menuAdvanced.getShell(), SWT.DROP_DOWN);
+
+		final Menu speedLimitsMenu = new Menu(menuAdvanced.getShell(),
+				SWT.DROP_DOWN);
 		final MenuItem speedLimitsMenuItem = new MenuItem(menuAdvanced, SWT.CASCADE);
-		Messages.setLanguageText(speedLimitsMenuItem,IMenuConstants.MENU_ID_SPEED_LIMITS);
+		Messages.setLanguageText(speedLimitsMenuItem,
+				IMenuConstants.MENU_ID_SPEED_LIMITS);
 		speedLimitsMenuItem.setMenu(speedLimitsMenu);
-		
-		MenuBuildUtils.addMaintenanceListenerForMenu(speedLimitsMenu,
-			new MenuBuildUtils.MenuBuilder() {
-				public void 
-				buildMenu(
-					Menu 		menu, 
-					MenuEvent 	menuEvent) 
-				{
-					final SpeedLimitHandler slh = SpeedLimitHandler.getSingleton( azureus_core );
-
-					boolean	all_have_limit = true;
-					
-					Set<String>	common_profiles = new HashSet<String>();
-					
-					final List<byte[]>	dm_hashes = new ArrayList<byte[]>();
-					
-					for (int i = 0; i < dms.length; i++) {
-						DownloadManager dm = (DownloadManager) dms[i];
 
-						int maxul = dm.getStats().getUploadRateLimitBytesPerSecond();
-						int maxdl = dm.getStats().getDownloadRateLimitBytesPerSecond();
-						
-						if ( maxul == 0 && maxdl == 0 ){
-							
-							all_have_limit = false;
-						}
-						
-						TOTorrent t = dm.getTorrent();
-						
-						if ( t == null ){
-							
-							common_profiles.clear();
-							
-						}else{
-							
-							try{
-								byte[] hash = t.getHash();
-							
-								dm_hashes.add( hash );
-								
-								List<String>	profs = slh.getProfilesForDownload( hash );
-								
-								if ( i == 0 ){
-									
-									common_profiles.addAll( profs );
-									
-								}else{
-									
-									common_profiles.retainAll( profs );
-								}
-							}catch( TOTorrentException e ){
-								
-								Debug.out( e );
-								
-								common_profiles.clear();
-							}
-						}
+		MenuBuildUtils.addMaintenanceListenerForMenu(speedLimitsMenu,
+				new MenuBuildUtils.MenuBuilder() {
+					public void buildMenu(Menu menu, MenuEvent menuEvent) {
+						addSpeedLimitsMenu(dms, speedLimitsMenu);
 					}
-						
-					java.util.List<String>	profiles = slh.getProfileNames();
+				});
 
-						// add to profile
-					
-					final Menu add_to_prof_menu = new Menu(speedLimitsMenu.getShell(), SWT.DROP_DOWN);
-					MenuItem add_to_prof_item = new MenuItem( menu, SWT.CASCADE);
-					add_to_prof_item.setMenu(add_to_prof_menu);
-			
-												
-					Messages.setLanguageText(add_to_prof_item, "MyTorrentsView.menu.sl_add_to_prof" );
-			
-					if ( !all_have_limit ){
-						
-						add_to_prof_item.setEnabled( false );
-						
-					}else{
-						
-						for ( final String p: profiles ){
-
-							MenuItem addItem = new MenuItem(add_to_prof_menu, SWT.PUSH);
-							addItem.setText( p );
-
-							addItem.addListener(
-								SWT.Selection,
-								new Listener()
-								{
-									public void 
-									handleEvent(
-										Event arg0 )
-									{
-										slh.addDownloadsToProfile( p, dm_hashes );
-										
-										MenuFactory.showText(
-												"MainWindow.menu.speed_limits.info.title",
-												MessageText.getString( "MainWindow.menu.speed_limits.info.prof", new String[]{ p }),
-												slh.getProfile( p ) );
-									}
-								});
-						}
-					}
-					
-						// remove from profile
-					
-					final Menu remove_from_prof_menu = new Menu(speedLimitsMenu.getShell(), SWT.DROP_DOWN);
-					MenuItem remove_from_prof_item = new MenuItem( menu, SWT.CASCADE);
-					remove_from_prof_item.setMenu(remove_from_prof_menu);
-			
-												
-					Messages.setLanguageText(remove_from_prof_item, "MyTorrentsView.menu.sl_remove_from_prof" );
-			
-					if ( common_profiles.isEmpty()){
-						
-						remove_from_prof_item.setEnabled( false );
-						
-					}else{
-						
-						for ( final String p: common_profiles ){
-
-							MenuItem addItem = new MenuItem(remove_from_prof_menu, SWT.PUSH);
-							addItem.setText( p );
-
-							addItem.addListener(
-								SWT.Selection,
-								new Listener()
-								{
-									public void 
-									handleEvent(
-										Event arg0 )
-									{
-										slh.removeDownloadsFromProfile( p, dm_hashes );
-										
-										MenuFactory.showText(
-												"MainWindow.menu.speed_limits.info.title",
-												MessageText.getString( "MainWindow.menu.speed_limits.info.prof", new String[]{ p }),
-												slh.getProfile( p ) );
-									}
-								});
-						}
-					}
-				}
-		});
-		
-		
-		
 		// advanced > Tracker Menu //
 		final Menu menuTracker = new Menu(menu.getShell(), SWT.DROP_DOWN);
 		final MenuItem itemTracker = new MenuItem(menuAdvanced, SWT.CASCADE);
 		Messages.setLanguageText(itemTracker, "MyTorrentsView.menu.tracker");
 		itemTracker.setMenu(menuTracker);
+		itemExplore.setEnabled(hasSelection);
+		addTrackerTorrentMenu(menuTracker, dms, changeUrl, manualUpdate,
+				allStopped, use_open_containing_folder);
 
-		final MenuItem itemChangeTracker = new MenuItem(menuTracker, SWT.PUSH);
-		Messages.setLanguageText(itemChangeTracker, "MyTorrentsView.menu.changeTracker"); //$NON-NLS-1$
-		Utils.setMenuItemImage(itemChangeTracker, "add_tracker");
-		itemChangeTracker.addListener(SWT.Selection, new DMTask(dms) {
-			public void run(DownloadManager[] dms) {
-				if ( dms.length > 0 ){
-					new TrackerChangerWindow(dms);
-				}
-			}
-		});
-		itemChangeTracker.setEnabled(changeUrl);
+		// advanced > files
 
-		final MenuItem itemEditTracker = new MenuItem(menuTracker, SWT.PUSH);
-		Messages.setLanguageText(itemEditTracker, "MyTorrentsView.menu.editTracker");
-		Utils.setMenuItemImage(itemEditTracker, "edit_trackers");
-		itemEditTracker.addListener(SWT.Selection, new DMTask(dms) {
-			public void 
-			run(
-				final DownloadManager[] dms ) 
-			{
-				Map<String,List<DownloadManager>>	same_map = new HashMap<String, List<DownloadManager>>();
-				
-				for ( DownloadManager dm: dms ){
-					
-					TOTorrent torrent = dm.getTorrent();
-					
-					if ( torrent == null ){
-						
-						continue;
-					}
-					
-					List<List<String>> group = TorrentUtils.announceGroupsToList(torrent);
-					
-					String str = "";
-					
-					for ( List<String> l: group ){
-						str += "[[";
-						
-						for ( String s:l ){
-							str += s + ", ";
-						}
-					}
-					
-					List<DownloadManager> dl = same_map.get( str );
-					
-					if ( dl == null ){
-						
-						dl = new ArrayList<DownloadManager>();
-						
-						same_map.put( str, dl );
-					}
-					
-					dl.add(dm );
-				}
-				
-				for ( final List<DownloadManager> set: same_map.values()){
-										
-					TOTorrent torrent = set.get(0).getTorrent();
+		final MenuItem itemFiles = new MenuItem(menuAdvanced, SWT.CASCADE);
+		Messages.setLanguageText(itemFiles, "ConfigView.section.files");
 
-					List<List<String>> group = TorrentUtils.announceGroupsToList(torrent);
+		final Menu menuFiles = new Menu(composite.getShell(), SWT.DROP_DOWN);
+		itemFiles.setMenu(menuFiles);
 
-					new MultiTrackerEditor(
-						null,
-						null, 
-						group, 
-						new TrackerEditorListener() 
-						{
-							public void 
-							trackersChanged(
-								String 				str, 
-								String 				str2, 
-								List<List<String>> 	group ) 
-							{
-								for ( DownloadManager dm: set ){
-									
-									TOTorrent torrent = dm.getTorrent();
-									
-									TorrentUtils.listToAnnounceGroups(group, torrent);
-		
-									try{
-										TorrentUtils.writeToFile(torrent);
-										
-									}catch (Throwable e){
-										
-										Debug.printStackTrace(e);
-									}
-		
-									if ( dm.getTrackerClient() != null){
-										
-										dm.getTrackerClient().resetTrackerUrl(true);
-									}
-								}
-							}
-						}, true, true );
-				}
-			} 
+		final MenuItem itemFileMoveData = new MenuItem(menuFiles, SWT.PUSH);
+		Messages.setLanguageText(itemFileMoveData, "MyTorrentsView.menu.movedata");
+		itemFileMoveData.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(DownloadManager[] dms) {
+				moveDataFiles(composite.getShell(), dms);
+			}
 		});
-		
-		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 = getURLList( torrent, "url-list" );
-				List webseeds = getURLList( torrent, "httpseeds" );
-				
-				Map ws = new HashMap();
-								
-				ws.put( "getright", getright );								
-				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 );
+		itemFileMoveData.setEnabled(fileMove);
 
+		final MenuItem itemFileMoveTorrent = new MenuItem(menuFiles, SWT.PUSH);
+		Messages.setLanguageText(itemFileMoveTorrent,
+				"MyTorrentsView.menu.movetorrent");
+		itemFileMoveTorrent.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(DownloadManager[] dms) {
+				moveTorrentFile(composite.getShell(), dms);
 			}
-			
-			protected List
-			getURLList(
-				TOTorrent	torrent,
-				String		key )
-			{
-				Object obj = torrent.getAdditionalProperty( key );
-				
-				if ( obj instanceof byte[] ){
-					
-	                List l = new ArrayList();
-	                
-			        l.add(obj);
-			        
-			        return( l );
-			        
-				}else if ( obj instanceof List ){
-					
-					return((List)obj);
-					
-				}else{
-					
-					return( new ArrayList());
-				}
+		});
+		itemFileMoveTorrent.setEnabled(fileMove);
+
+		final MenuItem itemCheckFilesExist = new MenuItem(menuFiles, SWT.PUSH);
+		Messages.setLanguageText(itemCheckFilesExist,
+				"MyTorrentsView.menu.checkfilesexist");
+		itemCheckFilesExist.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(DownloadManager dm) {
+				dm.filesExist(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"));
-		itemManualUpdate.addListener(SWT.Selection, new DMTask(dms) {
+		final MenuItem itemFileRescan = new MenuItem(menuFiles, SWT.CHECK);
+		Messages.setLanguageText(itemFileRescan, "MyTorrentsView.menu.rescanfile");
+		itemFileRescan.addListener(SWT.Selection, new ListenerDMTask(dms) {
 			public void run(DownloadManager dm) {
-				dm.requestTrackerAnnounce(false);
+				dm.getDownloadState().setFlag(
+						DownloadManagerState.FLAG_SCAN_INCOMPLETE_PIECES,
+						itemFileRescan.getSelection());
 			}
 		});
-		itemManualUpdate.setEnabled(manualUpdate);
+		itemFileRescan.setSelection(allScanSelected);
+		itemFileRescan.setEnabled(fileRescan);
 
-		boolean scrape_enabled = COConfigurationManager.getBooleanParameter("Tracker Client Scrape Enable");
+		// clear allocation
 
-		boolean scrape_stopped = COConfigurationManager.getBooleanParameter("Tracker Client Scrape Stopped Enable");
+		MenuItem itemFileClearAlloc = new MenuItem(menuFiles, SWT.PUSH);
+		Messages.setLanguageText(itemFileClearAlloc,
+				"MyTorrentsView.menu.clear_alloc_data");
+		itemFileClearAlloc.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(DownloadManager dm) {
+				dm.setDataAlreadyAllocated(false);
+			}
+		});
 
-		boolean manualScrape = (!scrape_enabled) || ((!scrape_stopped) && allStopped);
+		itemFileClearAlloc.setEnabled(allStopped);
 
-		final MenuItem itemManualScrape = new MenuItem(menuTracker, SWT.PUSH);
-		Messages.setLanguageText(itemManualScrape, "GeneralView.label.trackerscrapeupdate");
-		//itemManualUpdate.setImage(ImageRepository.getImage("edit_trackers"));
-		itemManualScrape.addListener(SWT.Selection, new DMTask(dms, true, true ) {
+		// clear resume
+
+		MenuItem itemFileClearResume = new MenuItem(menuFiles, SWT.PUSH);
+		Messages.setLanguageText(itemFileClearResume,
+				"MyTorrentsView.menu.clear_resume_data");
+		itemFileClearResume.addListener(SWT.Selection, new ListenerDMTask(dms) {
 			public void run(DownloadManager dm) {
-				dm.requestTrackerScrape(true);
+				dm.getDownloadState().clearResumeData();
 			}
 		});
-		itemManualScrape.setEnabled(manualScrape);
+		itemFileClearResume.setEnabled(allStopped);
 
-			// download link
+			// Advanced -> archive
 		
-		final MenuItem itemTorrentDL = new MenuItem(menuTracker, SWT.PUSH);
-		Messages.setLanguageText(itemTorrentDL, "MyTorrentsView.menu.torrent.dl" );
-		itemTorrentDL.addListener(SWT.Selection, new DMTask(dms, false) {
+		final List<Download>	ar_dms = new ArrayList<Download>();
+		
+		for ( DownloadManager dm: dms ){
+			
+			Download stub = PluginCoreUtils.wrap(dm);
+			
+			if ( !stub.canStubbify()){
+				
+				continue;
+			}
+			
+			ar_dms.add( stub );
+		}
+		
+		MenuItem itemArchive = new MenuItem(menuAdvanced, SWT.PUSH);
+		Messages.setLanguageText(itemArchive, "MyTorrentsView.menu.archive");
+		Utils.setMenuItemImage(itemArchive, "archive");
+		itemArchive.addListener(SWT.Selection, new ListenerDMTask(dms) {
 			public void run(DownloadManager dm) {
+				ManagerUtils.moveToArchive( ar_dms, null );
+			}
+		});
+		
+		itemArchive.setEnabled(ar_dms.size() > 0);
+		
+		
+		// Advanced - > Rename
+		final MenuItem itemRename = new MenuItem(menuAdvanced, SWT.DROP_DOWN);
+		Messages.setLanguageText(itemRename, "MyTorrentsView.menu.rename");
+		itemRename.setEnabled(hasSelection);
+		itemRename.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				for (DownloadManager dm : dms) {
+					AdvRenameWindow window = new AdvRenameWindow();
+					window.open(dm);
+				}
+			}
+		});
 
-				String	content;
-				
-				TOTorrent torrent = dm.getTorrent();
-				
-				String	link = null;
-				
-				if ( torrent == null ){
-					
-					content = "Torrent not available";
-					
-				}else{
-					
-					link = TorrentUtils.getObtainedFrom( torrent );
-					
-					if ( link != null ){
-						
-						try{
-							new URL( link );
-							
-						}catch( Throwable e ){
-							
-							link = null;
-						}
-					}
-					
-					if ( link != null ){
-						
-						if ( link.toLowerCase().startsWith( "magnet:" )){
-							
-							link = UrlUtils.getMagnetURI(dm.getDisplayName(), PluginCoreUtils.wrap( torrent ));
-							
-							content = "Torrent's magnet link:\r\n\r\n\t" + link;
-							
-						}else{
-						
-							content = "Torrent was obtained from\r\n\r\n\t" + link;
-						}
-					}else{
-						
-						if ( TorrentUtils.isReallyPrivate( torrent )){
-							
-							content = "Origin of torrent unknown and it is private so a magnet URI can't be used - sorry!";
-							
-						}else{
-							
-							link = UrlUtils.getMagnetURI(dm.getDisplayName(), PluginCoreUtils.wrap( torrent ));
-							
-							content = "Origin unavailable but magnet URI may work:\r\n\r\n\t" + link;
-						}
-					}
-				}
-				
-				if ( link != null ){
-					
-					ClipboardCopy.copyToClipBoard( link );
-					
-					content += "\r\n\r\nLink copied to clipboard";
-				}
-				
-				final TextViewerWindow viewer = new TextViewerWindow(
-						MessageText.getString( "MyTorrentsView.menu.torrent.dl" ) + ": " + dm.getDisplayName(),
-						null,
-						content, false  );
-			}
-		});
-		itemTorrentDL.setEnabled(dms.length==1);
-		
-			// explore torrent file
-		
-		final MenuItem itemTorrentExplore = new MenuItem(menuTracker, SWT.PUSH);
-		Messages.setLanguageText(itemTorrentExplore, "MyTorrentsView.menu." + (use_open_containing_folder ? "open_parent_folder" : "explore"));
-		itemTorrentExplore.addListener(SWT.Selection, new DMTask(dms, false) {
-			public void run(DownloadManager dm) {
-				ManagerUtils.open(new File(dm.getTorrentFileName()), use_open_containing_folder);
-			}
-		});
-		itemExplore.setEnabled(hasSelection);
-		
-		// advanced > files
-
-		final MenuItem itemFiles = new MenuItem(menuAdvanced, SWT.CASCADE);
-		Messages.setLanguageText(itemFiles, "ConfigView.section.files");
-
-		final Menu menuFiles = new Menu(composite.getShell(), SWT.DROP_DOWN);
-		itemFiles.setMenu(menuFiles);
-
-		final MenuItem itemFileMoveData = new MenuItem(menuFiles, SWT.PUSH);
-		Messages.setLanguageText(itemFileMoveData, "MyTorrentsView.menu.movedata");
-		itemFileMoveData.addListener(SWT.Selection, new DMTask(dms) {
-			public void run(DownloadManager[] dms) {
-				if (dms != null && dms.length > 0) {
+		// === advanced > quick view
 
-					DirectoryDialog dd = new DirectoryDialog(composite.getShell());
+		final Menu quickViewMenu = new Menu(menuAdvanced.getShell(), SWT.DROP_DOWN);
+		final MenuItem quickViewMenuItem = new MenuItem(menuAdvanced, SWT.CASCADE);
+		Messages.setLanguageText(quickViewMenuItem,
+				IMenuConstants.MENU_ID_QUICK_VIEW);
+		quickViewMenuItem.setMenu(quickViewMenu);
 
-					dd.setFilterPath(TorrentOpener.getFilterPathData());
+		MenuBuildUtils.addMaintenanceListenerForMenu(quickViewMenu,
+				new MenuBuildUtils.MenuBuilder() {
+					public void buildMenu(Menu menu, MenuEvent menuEvent) {
+						DownloadManager dm = dms[0];
 
-					dd.setText(MessageText.getString("MyTorrentsView.menu.movedata.dialog"));
+						DiskManagerFileInfo[] files = dm.getDiskManagerFileInfoSet().getFiles();
 
-					String path = dd.open();
+						int added = 0;
 
-					if (path != null) {
+						for (final DiskManagerFileInfo file : files) {
 
-						TorrentOpener.setFilterPathData(path);
+							if (Utils.isQuickViewSupported(file)) {
 
-						File target = new File(path);
+								final MenuItem addItem = new MenuItem(menu, SWT.CHECK);
 
-						for (int i = 0; i < dms.length; i++) {
+								addItem.setSelection(Utils.isQuickViewActive(file));
 
-							try {
-								dms[i].moveDataFilesLive( target);
+								addItem.setText(file.getTorrentFile().getRelativePath());
 
-							}
-							catch (Throwable e) {
+								addItem.addListener(SWT.Selection, new Listener() {
+									public void handleEvent(Event arg) {
+										Utils.setQuickViewActive(file, addItem.getSelection());
+									}
+								});
 
-								Logger.log(new LogAlert(dms[i], LogAlert.REPEATABLE,
-										"Download data move operation failed", e));
+								added++;
 							}
 						}
-					}
-				}
-			}
-		});
-		itemFileMoveData.setEnabled(fileMove);
-
-		final MenuItem itemFileMoveTorrent = new MenuItem(menuFiles, SWT.PUSH);
-		Messages.setLanguageText(itemFileMoveTorrent, "MyTorrentsView.menu.movetorrent");
-		itemFileMoveTorrent.addListener(SWT.Selection, new DMTask(dms) {
-			public void run(DownloadManager[] dms) {
-				if (dms != null && dms.length > 0) {
-
-					DirectoryDialog dd = new DirectoryDialog(composite.getShell());
-					String filter_path = TorrentOpener.getFilterPathTorrent();
-					
-					// If we don't have a decent path, default to the path of the first
-					// torrent.
-					if (filter_path == null || filter_path.trim().length() == 0) {
-						filter_path = new File(dms[0].getTorrentFileName()).getParent();
-					}
-					
-					dd.setFilterPath(filter_path);
-
-					dd.setText(MessageText.getString("MyTorrentsView.menu.movedata.dialog"));
-
-					String path = dd.open();
-
-					if (path != null) {
 
-						File target = new File(path);
+						if (added == 0) {
 
-						TorrentOpener.setFilterPathTorrent(target.toString());
+							final MenuItem addItem = new MenuItem(menu, SWT.PUSH);
 
-						for (int i = 0; i < dms.length; i++) {
+							addItem.setText(MessageText.getString("quick.view.no.files"));
 
-							try {
-								dms[i].moveTorrentFile(target);
-
-							}
-							catch (Throwable e) {
-
-								Logger.log(new LogAlert(dms[i], LogAlert.REPEATABLE,
-										"Download torrent move operation failed", e));
-							}
+							addItem.setEnabled(false);
 						}
 					}
-				}
-			}
-		});
-		itemFileMoveTorrent.setEnabled(fileMove);
-		
-		final MenuItem itemCheckFilesExist = new MenuItem(menuFiles, SWT.PUSH);
-		Messages.setLanguageText(itemCheckFilesExist, "MyTorrentsView.menu.checkfilesexist");
-		itemCheckFilesExist.addListener(SWT.Selection, new DMTask(dms) {
-			public void run(DownloadManager dm) {
-				dm.filesExist( true );
-			}
-		});
-
-		final MenuItem itemFileRescan = new MenuItem(menuFiles, SWT.CHECK);
-		Messages.setLanguageText(itemFileRescan, "MyTorrentsView.menu.rescanfile");
-		itemFileRescan.addListener(SWT.Selection, new DMTask(dms) {
-			public void run(DownloadManager dm) {
-				dm.getDownloadState().setFlag(DownloadManagerState.FLAG_SCAN_INCOMPLETE_PIECES,
-						itemFileRescan.getSelection());
-			}
-		});
-		itemFileRescan.setSelection(allScanSelected);
-		itemFileRescan.setEnabled(fileRescan);
-
-			// clear allocation
-		
-		MenuItem itemFileClearAlloc = new MenuItem(menuFiles, SWT.PUSH);
-		Messages.setLanguageText(itemFileClearAlloc, "MyTorrentsView.menu.clear_alloc_data");
-		itemFileClearAlloc.addListener(SWT.Selection, new DMTask(dms) {
-			public void run(DownloadManager dm) {
-				dm.setDataAlreadyAllocated( false );
-			}
-		});
-		
-		itemFileClearAlloc.setEnabled(allStopped);
-		
-			// clear resume
-		
-		MenuItem itemFileClearResume = new MenuItem(menuFiles, SWT.PUSH);
-		Messages.setLanguageText(itemFileClearResume, "MyTorrentsView.menu.clear_resume_data");
-		itemFileClearResume.addListener(SWT.Selection, new DMTask(dms) {
-			public void run(DownloadManager dm) {
-				dm.getDownloadState().clearResumeData();
-			}
-		});
-		itemFileClearResume.setEnabled(allStopped);
+				});
 
-		// Advanced - > Rename
-		final MenuItem itemRename = new MenuItem(menuAdvanced, SWT.DROP_DOWN);
-		Messages.setLanguageText(itemRename, "MyTorrentsView.menu.rename");
-		itemRename.setEnabled(hasSelection);
-		itemRename.addListener(SWT.Selection, new Listener() {
-			public void handleEvent(Event event) {
-				for (DownloadManager dm : dms) {
-					AdvRenameWindow window = new AdvRenameWindow();
-					window.open(dm);
-				}
-			}
-		});
+		quickViewMenuItem.setEnabled(dms.length == 1);
 
-		// === advanced > quick view
-				
-		final Menu quickViewMenu = new Menu(menuAdvanced.getShell(), SWT.DROP_DOWN);
-		final MenuItem quickViewMenuItem = new MenuItem(menuAdvanced, SWT.CASCADE);
-		Messages.setLanguageText(quickViewMenuItem,IMenuConstants.MENU_ID_QUICK_VIEW);
-		quickViewMenuItem.setMenu(quickViewMenu);
-		
-		MenuBuildUtils.addMaintenanceListenerForMenu(quickViewMenu,
-			new MenuBuildUtils.MenuBuilder() {
-				public void 
-				buildMenu(
-					Menu 		menu, 
-					MenuEvent 	menuEvent) 
-				{
-					DownloadManager dm = dms[0];
-					
-					DiskManagerFileInfo[]	files = dm.getDiskManagerFileInfoSet().getFiles();
-					
-					int	added = 0;
-					
-					for ( final DiskManagerFileInfo file: files ){
-						
-						if ( Utils.isQuickViewSupported( file )){
-								
-							final MenuItem addItem = new MenuItem(menu, SWT.CHECK );
-							
-							addItem.setSelection( Utils.isQuickViewActive( file ));
-							
-							addItem.setText( file.getTorrentFile().getRelativePath());
-
-							addItem.addListener(
-								SWT.Selection,
-								new Listener()
-								{
-									public void 
-									handleEvent(
-										Event arg ) 
-									{
-										Utils.setQuickViewActive( file, addItem.getSelection());
-									}
-								});
-							
-							added++;
-						}
-					}
-					
-					if ( added == 0 ){
-						
-						final MenuItem addItem = new MenuItem(menu, SWT.PUSH );
-												
-						addItem.setText( MessageText.getString( "quick.view.no.files"));
+		// Alerts 
 
-						addItem.setEnabled( false );
-					}
-				}
-		});
-		
-		quickViewMenuItem.setEnabled( dms.length == 1 );
-		
-			// Alerts 
-		
-		MenuFactory.addAlertsMenu( menuAdvanced, dms );
+		MenuFactory.addAlertsMenu(menuAdvanced, true, dms);
 
-	
 		// === advanced > export ===
 		// =========================
 
@@ -1107,172 +672,48 @@ public class TorrentUtil {
 			// Advanced > Export > Export XML
 			final MenuItem itemExportXML = new MenuItem(menuExport, SWT.PUSH);
 			Messages.setLanguageText(itemExportXML, "MyTorrentsView.menu.export");
-			itemExportXML.addListener(SWT.Selection, new DMTask(dms) {
+			itemExportXML.addListener(SWT.Selection, new ListenerDMTask(dms) {
 				public void run(DownloadManager[] dms) {
 					DownloadManager dm = dms[0]; // First only.
-					if (dm != null) new ExportTorrentWizard(itemExportXML.getDisplay(), dm);
+					if (dm != null)
+						new ExportTorrentWizard(itemExportXML.getDisplay(), dm);
 				}
 			});
 
 			// Advanced > Export > Export Torrent
 			final MenuItem itemExportTorrent = new MenuItem(menuExport, SWT.PUSH);
-			Messages.setLanguageText(itemExportTorrent, "MyTorrentsView.menu.exporttorrent");
-			itemExportTorrent.addListener(SWT.Selection, new DMTask(dms) {
+			Messages.setLanguageText(itemExportTorrent,
+					"MyTorrentsView.menu.exporttorrent");
+			itemExportTorrent.addListener(SWT.Selection, new ListenerDMTask(dms) {
 				public void run(DownloadManager[] dms) {
-					// FileDialog for single download
-					// DirectoryDialog for multiple.
-					File[] destinations = new File[dms.length];
-					if (dms.length == 1) {
-						FileDialog fd = new FileDialog(composite.getShell(), SWT.SAVE);
-						fd.setFileName(dms[0].getTorrentFileName());
-						String path = fd.open();
-						if (path == null) {return;}
-						destinations[0] = new File(path);
-					}
-					else {
-						DirectoryDialog dd = new DirectoryDialog(composite.getShell(), SWT.SAVE);
-						String path = dd.open();
-						if (path == null) {return;}
-						for (int i=0; i<dms.length; i++) {
-							destinations[i] = new File(path, new File(dms[i].getTorrentFileName()).getName());
-						}
-					}
-					
-					int i=0;
-					try {
-						for (; i<dms.length; i++) {
-							File target = destinations[i];
-							if (target.exists()) {
-								MessageBox mb = new MessageBox(composite.getShell(), SWT.ICON_QUESTION | SWT.YES | SWT.NO);
-								mb.setText(MessageText.getString("exportTorrentWizard.process.outputfileexists.title"));
-								mb.setMessage(MessageText.getString("exportTorrentWizard.process.outputfileexists.message") + "\n" + destinations[i].getName());
-
-								int result = mb.open();
-								if (result == SWT.NO) {return;}
-
-								if (!target.delete()) {
-									throw (new Exception("Failed to delete file"));
-								}
-							} // end deal with clashing torrent
-
-							// first copy the torrent - DON'T use "writeTorrent" as this amends the
-							// "filename" field in the torrent
-							TorrentUtils.copyToFile(dms[i].getDownloadState().getTorrent(), target);
-
-							// now remove the non-standard entries
-							TOTorrent dest = TOTorrentFactory.deserialiseFromBEncodedFile(target);
-							dest.removeAdditionalProperties();
-							dest.serialiseToBEncodedFile(target);
-						} // end for
-					} // end try
-					catch (Throwable e) {
-						Logger.log(new LogAlert(dms[i], LogAlert.UNREPEATABLE, "Torrent export failed", e));
-					}
+					exportTorrent(dms, composite.getShell());
 				} // end run()
 			}); // end DMTask
-			
+
 			// Advanced > Export > WebSeed URL
 			final MenuItem itemWebSeed = new MenuItem(menuExport, SWT.PUSH);
-			Messages.setLanguageText(itemWebSeed, "MyTorrentsView.menu.exporthttpseeds");
-			itemWebSeed.addListener(SWT.Selection, new DMTask(dms) {
+			Messages.setLanguageText(itemWebSeed,
+					"MyTorrentsView.menu.exporthttpseeds");
+			itemWebSeed.addListener(SWT.Selection, new ListenerDMTask(dms) {
 				public void run(DownloadManager[] dms) {
-					final String	NL = "\r\n";
-					String	data = "";
-					
-					boolean http_enable = COConfigurationManager.getBooleanParameter( "HTTP.Data.Listen.Port.Enable" );
-					
-					String	port;
-					
-					if ( http_enable ){
-						
-						int	p = COConfigurationManager.getIntParameter( "HTTP.Data.Listen.Port" );
-						int o = COConfigurationManager.getIntParameter( "HTTP.Data.Listen.Port.Override" );
-					    
-						if ( o == 0 ){
-							
-							port = String.valueOf( p );
-							
-						}else{
-							
-							port = String.valueOf( o );
-						}
-					}else{
-
-						data = "You need to enable the HTTP port or modify the URL(s) appropriately" + NL + NL;
-						
-						port = "<port>";
-					}
-				    
-					String	ip = COConfigurationManager.getStringParameter( "Tracker IP", "" );
-					
-					if ( ip.length() == 0 ){
-						
-						data += "You might need to modify the host address in the URL(s)" + NL + NL;
-						
-						try{
-						
-							InetAddress ia = NetworkAdmin.getSingleton().getDefaultPublicAddress();
-						
-							if ( ia != null ){
-								
-								ip = IPToHostNameResolver.syncResolve( ia.getHostAddress(), 10000 );
-							}
-						}catch( Throwable e ){
-							
-						}
-						
-						if ( ip.length() == 0 ){
-							
-							ip = "<host>";
-						}
-					}
-					
-					String	base = "http://" + UrlUtils.convertIPV6Host(ip) + ":" + port + "/";
-					
-					for (int i=0;i<dms.length;i++){
-						
-						DownloadManager dm = dms[i];
-						
-						if ( dm == null ){
-							continue;
-						}
-						
-						TOTorrent torrent = dm.getTorrent();
-						
-						if ( torrent == null ){
-							
-							continue;
-						}
-						
-						data += base + "webseed" + NL;
-						
-						try{
-							data += base + "files/" + URLEncoder.encode( new String( torrent.getHash(), "ISO-8859-1"), "ISO-8859-1" ) + "/" + NL + NL;
-							
-						}catch( Throwable e ){
-							
-						}
-					}
-					
-					if ( data.length() > 0){
-						ClipboardCopy.copyToClipBoard( data );
-					}
+					exportHTTPSeeds(dms);
 				}
 			});
 		} // export menu
 
-		
 		// === advanced > options ===
 		// ===========================
 
 		if (userMode > 0) {
 			final MenuItem itemExportXML = new MenuItem(menuAdvanced, SWT.PUSH);
 			Messages.setLanguageText(itemExportXML, "label.options.and.info");
-			itemExportXML.addListener(SWT.Selection, new DMTask(dms) {
+			itemExportXML.addListener(SWT.Selection, new ListenerDMTask(dms) {
 				public void run(DownloadManager[] dms) {
 					UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
-					
-					uiFunctions.openView(UIFunctions.VIEW_DM_MULTI_OPTIONS, dms);
+					if (uiFunctions != null) {
+						uiFunctions.getMDI().showEntryByID(
+								MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_OPTIONS, dms);
+					}
 				}
 			});
 		}
@@ -1285,91 +726,59 @@ public class TorrentUtil {
 
 			final Menu menuPeerSource = new Menu(composite.getShell(), SWT.DROP_DOWN);
 			itemPeerSource.setMenu(menuPeerSource);
-
-			for (int i = 0; i < PEPeerSource.PS_SOURCES.length; i++) {
-
-				final String p = PEPeerSource.PS_SOURCES[i];
-				String msg_text = "ConfigView.section.connection.peersource." + p;
-				final MenuItem itemPS = new MenuItem(menuPeerSource, SWT.CHECK);
-				itemPS.setData("peerSource", p);
-				Messages.setLanguageText(itemPS, msg_text); //$NON-NLS-1$
-				itemPS.addListener(SWT.Selection, new DMTask(dms) {
-					public void run(DownloadManager dm) {
-						dm.getDownloadState().setPeerSourceEnabled(p, itemPS.getSelection());
-					}
-				});
-				itemPS.setSelection(true);
-
-				boolean bChecked = hasSelection;
-				boolean bEnabled = !hasSelection;
-				if (bChecked) {
-					bEnabled = true;
-
-					// turn on check if just one dm is not enabled
-					for (int j = 0; j < dms.length; j++) {
-						DownloadManager dm = (DownloadManager) dms[j];
-
-						if (!dm.getDownloadState().isPeerSourceEnabled(p)) {
-							bChecked = false;
-						}
-						if (!dm.getDownloadState().isPeerSourcePermitted(p)) {
-							bEnabled = false;
-						}
-					}
-				}
-
-				itemPS.setSelection(bChecked);
-				itemPS.setEnabled(bEnabled);
-			}
+			
+			addPeerSourceSubMenu(dms, menuPeerSource);
 		}
 
 		// IP Filter Enable
 		if (userMode > 0) {
-			
+
 			final MenuItem ipf_enable = new MenuItem(menuAdvanced, SWT.CHECK);
 			Messages.setLanguageText(ipf_enable, "MyTorrentsView.menu.ipf_enable");
-			
 
-			ipf_enable.addListener(SWT.Selection, new DMTask(dms) {
+			ipf_enable.addListener(SWT.Selection, new ListenerDMTask(dms) {
 				public void run(DownloadManager dm) {
-					dm.getDownloadState().setFlag( DownloadManagerState.FLAG_DISABLE_IP_FILTER, !ipf_enable.getSelection());
+					dm.getDownloadState().setFlag(
+							DownloadManagerState.FLAG_DISABLE_IP_FILTER,
+							!ipf_enable.getSelection());
 				}
 			});
 
 			boolean bEnabled = IpFilterManagerFactory.getSingleton().getIPFilter().isEnabled();
-			
-			if ( bEnabled ){
-				boolean allChecked 		= true;
-				boolean allUnchecked	= true;
-		
+
+			if (bEnabled) {
+				boolean allChecked = true;
+				boolean allUnchecked = true;
+
 				for (int j = 0; j < dms.length; j++) {
 					DownloadManager dm = (DownloadManager) dms[j];
-	
-					boolean b = dm.getDownloadState().getFlag( DownloadManagerState.FLAG_DISABLE_IP_FILTER );
-						
-					if ( b ){
-						allUnchecked 	= false;
-					}else{
-						allChecked 		= false;
+
+					boolean b = dm.getDownloadState().getFlag(
+							DownloadManagerState.FLAG_DISABLE_IP_FILTER);
+
+					if (b) {
+						allUnchecked = false;
+					} else {
+						allChecked = false;
 					}
 				}
-	
-				boolean	bChecked;
-				
-				if ( allUnchecked ){
+
+				boolean bChecked;
+
+				if (allUnchecked) {
 					bChecked = true;
-				}else if ( allChecked ){
+				} else if (allChecked) {
 					bChecked = false;
-				}else{
+				} else {
 					bChecked = false;
 				}
-				
+
 				ipf_enable.setSelection(bChecked);
 			}
-			
-			ipf_enable.setEnabled(bEnabled);	
+
+			ipf_enable.setEnabled(bEnabled);
 		}
-		
+
 		// === advanced > networks ===
 		// ===========================
 
@@ -1379,34 +788,9 @@ public class TorrentUtil {
 
 			final Menu menuNetworks = new Menu(composite.getShell(), SWT.DROP_DOWN);
 			itemNetworks.setMenu(menuNetworks);
-
-			for (int i = 0; i < AENetworkClassifier.AT_NETWORKS.length; i++) {
-				final String nn = AENetworkClassifier.AT_NETWORKS[i];
-				String msg_text = "ConfigView.section.connection.networks." + nn;
-				final MenuItem itemNetwork = new MenuItem(menuNetworks, SWT.CHECK);
-				itemNetwork.setData("network", nn);
-				Messages.setLanguageText(itemNetwork, msg_text); //$NON-NLS-1$
-				itemNetwork.addListener(SWT.Selection, new DMTask(dms) {
-					public void run(DownloadManager dm) {
-						dm.getDownloadState().setNetworkEnabled(nn, itemNetwork.getSelection());
-					}
-				});
-				boolean bChecked = hasSelection;
-				if (bChecked) {
-					// turn on check if just one dm is not enabled
-					for (int j = 0; j < dms.length; j++) {
-						DownloadManager dm = (DownloadManager) dms[j];
-
-						if (!dm.getDownloadState().isNetworkEnabled(nn)) {
-							bChecked = false;
-							break;
-						}
-					}
-				}
-
-				itemNetwork.setSelection(bChecked);
-			}
-		}
+			
+			addNetworksSubMenu(dms, menuNetworks);
+		}
 
 		// superseed
 		if (userMode > 1 && isSeedingView) {
@@ -1425,13 +809,14 @@ public class TorrentUtil {
 
 				itemSuperSeed.setSelection(selected);
 
-				itemSuperSeed.addListener(SWT.Selection, new DMTask(dms) {
+				itemSuperSeed.addListener(SWT.Selection, new ListenerDMTask(dms) {
 					public void run(DownloadManager dm) {
 						PEPeerManager pm = dm.getPeerManager();
 
 						if (pm != null) {
 
-							if (pm.isSuperSeedMode() == selected && pm.canToggleSuperSeedMode()) {
+							if (pm.isSuperSeedMode() == selected
+									&& pm.canToggleSuperSeedMode()) {
 
 								pm.setSuperSeedMode(!selected);
 							}
@@ -1441,49 +826,44 @@ public class TorrentUtil {
 			}
 		}
 
-		 final MenuItem itemPositionManual = new MenuItem(menuAdvanced, SWT.PUSH);
+		// Advanced > Pause For..
+		if (userMode > 0) {
+
+			boolean can_pause = false;
+
+			for (int i = 0; i < dms.length; i++) {
+
+				DownloadManager dm = dms[i];
+
+				if (ManagerUtils.isPauseable(dm)) {
+
+					can_pause = true;
+
+					break;
+				}
+			}
+
+			final MenuItem itemPauseFor = new MenuItem(menuAdvanced, SWT.PUSH);
+
+			itemPauseFor.setEnabled(can_pause);
+
+			Messages.setLanguageText(itemPauseFor,
+					"MainWindow.menu.transfers.pausetransfersfor");
+
+			itemPauseFor.addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					pauseDownloadsFor(dms);
+				}
+			});
+		}
+
+		// Advanced > Reposition
+		final MenuItem itemPositionManual = new MenuItem(menuAdvanced, SWT.PUSH);
 		Messages.setLanguageText(itemPositionManual,
 				"MyTorrentsView.menu.reposition.manual");
 		itemPositionManual.addSelectionListener(new SelectionAdapter() {
 			public void widgetSelected(SelectionEvent e) {
-				SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
-						"MyTorrentsView.dialog.setPosition.title",
-						"MyTorrentsView.dialog.setPosition.text");
-				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);
-					}
-				});
+				repositionManual(tv, dms, composite.getShell(), isSeedingView);
 			}
 		});
 
@@ -1495,7 +875,7 @@ public class TorrentUtil {
 			Utils.setMenuItemImage(itemHost, "host");
 			itemHost.addListener(SWT.Selection, new Listener() {
 				public void handleEvent(Event event) {
-					hostTorrents(dms, azureus_core, composite);
+					hostTorrents(dms);
 				}
 			});
 
@@ -1505,7 +885,7 @@ public class TorrentUtil {
 			Utils.setMenuItemImage(itemPublish, "publish");
 			itemPublish.addListener(SWT.Selection, new Listener() {
 				public void handleEvent(Event event) {
-					publishTorrents(dms, azureus_core, composite);
+					publishTorrents(dms);
 				}
 			});
 
@@ -1515,214 +895,1158 @@ public class TorrentUtil {
 		/*  Do we really need the Move submenu?  There's shortcut keys and toolbar
 		 *  buttons..
 
-		 new MenuItem(menu, SWT.SEPARATOR);
+		 new MenuItem(menu, SWT.SEPARATOR);
+
+		 final MenuItem itemMove = new MenuItem(menu, SWT.CASCADE);
+		 Messages.setLanguageText(itemMove, "MyTorrentsView.menu.move");
+		 Utils.setMenuItemImage(itemMove, "move");
+		 itemMove.setEnabled(hasSelection);
+
+		 final Menu menuMove = new Menu(composite.getShell(), SWT.DROP_DOWN);
+		 itemMove.setMenu(menuMove);
+
+		 final MenuItem itemMoveTop = new MenuItem(menuMove, SWT.PUSH);
+		 Messages.setLanguageText(itemMoveTop, "MyTorrentsView.menu.moveTop");
+		 Utils.setMenuItemImage(itemMoveTop, "top");
+		 itemMoveTop.addListener(SWT.Selection, new Listener() {
+		 public void handleEvent(Event event) {
+		 moveSelectedTorrentsTop();
+		 }
+		 });
+		 itemMoveTop.setEnabled(moveUp);
+
+		 final MenuItem itemMoveUp = new MenuItem(menuMove, SWT.PUSH);
+		 Messages.setLanguageText(itemMoveUp, "MyTorrentsView.menu.moveUp");
+		 Utils.setMenuItemImage(itemMoveUp, "up");
+		 itemMoveUp.addListener(SWT.Selection, new Listener() {
+		 public void handleEvent(Event event) {
+		 moveSelectedTorrentsUp();
+		 }
+		 });
+
+		 final MenuItem itemMoveDown = new MenuItem(menuMove, SWT.PUSH);
+		 Messages.setLanguageText(itemMoveDown, "MyTorrentsView.menu.moveDown");
+		 Utils.setMenuItemImage(itemMoveDown, "down");
+		 itemMoveDown.addListener(SWT.Selection, new Listener() {
+		 public void handleEvent(Event event) {
+		 moveSelectedTorrentsDown();
+		 }
+		 });
+
+		 final MenuItem itemMoveEnd = new MenuItem(menuMove, SWT.PUSH);
+		 Messages.setLanguageText(itemMoveEnd, "MyTorrentsView.menu.moveEnd");
+		 Utils.setMenuItemImage(itemMoveEnd, "bottom");
+		 itemMoveEnd.addListener(SWT.Selection, new Listener() {
+		 public void handleEvent(Event event) {
+		 moveSelectedTorrentsEnd();
+		 }
+		 });
+		 itemMoveEnd.setEnabled(moveDown);
+		 */
+		/*  //TODO ensure that all limits combined don't go under the min 5kbs ?
+		 //Disable at the end of the list, thus the first item of the array is instanciated last.
+		 itemsSpeed[0] = new MenuItem(menuSpeed,SWT.PUSH);
+		 Messages.setLanguageText(itemsSpeed[0],"MyTorrentsView.menu.setSpeed.disable");
+		 itemsSpeed[0].setData("maxul", new Integer(-1));    
+		 itemsSpeed[0].addListener(SWT.Selection,itemsSpeedListener);
+		 */
+
+		// Category
+
+		Menu menuCategory = new Menu(composite.getShell(), SWT.DROP_DOWN);
+		final MenuItem itemCategory = new MenuItem(menu, SWT.CASCADE);
+		Messages.setLanguageText(itemCategory, "MyTorrentsView.menu.setCategory"); //$NON-NLS-1$
+		//itemCategory.setImage(ImageRepository.getImage("speed"));
+		itemCategory.setMenu(menuCategory);
+		itemCategory.setEnabled(hasSelection);
+
+		addCategorySubMenu(dms, menuCategory, composite);
+
+		// Tags
+
+		Menu menuTags = new Menu(composite.getShell(), SWT.DROP_DOWN);
+		final MenuItem itemTags = new MenuItem(menu, SWT.CASCADE);
+		Messages.setLanguageText(itemTags, "label.tags");
+		itemTags.setMenu(menuTags);
+		itemTags.setEnabled(hasSelection);
+
+		TagUIUtils.addLibraryViewTagsSubMenu(dms, menuTags, composite);
+
+		// personal share
+
+		if (isSeedingView) {
+			final MenuItem itemPersonalShare = new MenuItem(menu, SWT.PUSH);
+			Messages.setLanguageText(itemPersonalShare,
+					"MyTorrentsView.menu.create_personal_share");
+			itemPersonalShare.addListener(SWT.Selection, new ListenerDMTask(dms, false) {
+				public void run(DownloadManager dm) {
+					File file = dm.getSaveLocation();
+
+					Map<String, String> properties = new HashMap<String, String>();
+
+					properties.put(ShareManager.PR_PERSONAL, "true");
+
+					if (file.isFile()) {
+
+						ShareUtils.shareFile(file.getAbsolutePath(), properties);
+
+					} else if (file.isDirectory()) {
+
+						ShareUtils.shareDir(file.getAbsolutePath(), properties);
+					}
+				}
+			});
+
+			// XXX: Takes a very long time with many files..
+			/*
+			boolean	can_share_pers = dms.length > 0;
+			
+			for ( DownloadManager dm: dms ){
+				
+				if ( !( dm.isDownloadComplete( true ) && dm.filesExist( true ))){
+				
+					can_share_pers = false;
+					break;
+				}
+			}
+			
+			itemPersonalShare.setEnabled( can_share_pers );
+			*/
+		}
+
+		// ---
+		new MenuItem(menu, SWT.SEPARATOR);
+
+		// Queue
+		final MenuItem itemQueue = new MenuItem(menu, SWT.PUSH);
+		Messages.setLanguageText(itemQueue, "MyTorrentsView.menu.queue"); //$NON-NLS-1$
+		Utils.setMenuItemImage(itemQueue, "start");
+		itemQueue.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				Utils.getOffOfSWTThread(new AERunnable() {
+					public void runSupport() {
+						queueDataSources(dms, true);
+					}
+				});
+			}
+		});
+		itemQueue.setEnabled(start);
+
+		// Force Start
+		if (userMode > 0) {
+			final MenuItem itemForceStart = new MenuItem(menu, SWT.CHECK);
+			Messages.setLanguageText(itemForceStart, "MyTorrentsView.menu.forceStart");
+			Utils.setMenuItemImage(itemForceStart, "forcestart");
+			itemForceStart.addListener(SWT.Selection, new ListenerDMTask(dms) {
+				public void run(DownloadManager dm) {
+					if (ManagerUtils.isForceStartable(dm)) {
+						dm.setForceStart(itemForceStart.getSelection());
+					}
+				}
+			});
+			itemForceStart.setSelection(forceStart);
+			itemForceStart.setEnabled(forceStartEnabled);
+		}
+
+		// Pause
+		if (userMode > 0) {
+			final MenuItem itemPause = new MenuItem(menu, SWT.PUSH);
+			Messages.setLanguageText(itemPause, "v3.MainWindow.button.pause");
+			Utils.setMenuItemImage(itemPause, "pause");
+			itemPause.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					Utils.getOffOfSWTThread(new AERunnable() {
+						public void runSupport() {
+							pauseDataSources(dms);
+						}
+					});
+				}
+			});
+			itemPause.setEnabled(stop);
+		}
+
+		// Stop
+		final MenuItem itemStop = new MenuItem(menu, SWT.PUSH);
+		Messages.setLanguageText(itemStop, "MyTorrentsView.menu.stop");
+		Utils.setMenuItemImage(itemStop, "stop");
+		itemStop.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				Utils.getOffOfSWTThread(new AERunnable() {
+					public void runSupport() {
+						stopDataSources(dms);
+					}
+				});
+			}
+		});
+		itemStop.setEnabled(stop);
+
+		// Force Recheck
+		final MenuItem itemRecheck = new MenuItem(menu, SWT.PUSH);
+		Messages.setLanguageText(itemRecheck, "MyTorrentsView.menu.recheck");
+		Utils.setMenuItemImage(itemRecheck, "recheck");
+		itemRecheck.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(DownloadManager dm) {
+				if (dm.canForceRecheck()) {
+					dm.forceRecheck();
+				}
+			}
+		});
+		itemRecheck.setEnabled(recheck);
+
+		// Delete
+		final MenuItem itemRemove = new MenuItem(menu, SWT.PUSH);
+		Messages.setLanguageText(itemRemove, "menu.delete.options");
+		Utils.setMenuItemImage(itemRemove, "delete");
+		itemRemove.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				removeDownloads(dms, null, true);
+			}
+		});
+		itemRemove.setEnabled(hasSelection);
+
+	}
+
+	protected static void addNetworksSubMenu(DownloadManager[] dms,
+			Menu menuNetworks) {
+		for (int i = 0; i < AENetworkClassifier.AT_NETWORKS.length; i++) {
+			final String nn = AENetworkClassifier.AT_NETWORKS[i];
+			String msg_text = "ConfigView.section.connection.networks." + nn;
+			final MenuItem itemNetwork = new MenuItem(menuNetworks, SWT.CHECK);
+			itemNetwork.setData("network", nn);
+			Messages.setLanguageText(itemNetwork, msg_text); //$NON-NLS-1$
+			itemNetwork.addListener(SWT.Selection, new ListenerDMTask(dms) {
+				public void run(DownloadManager dm) {
+					dm.getDownloadState().setNetworkEnabled(nn,
+							itemNetwork.getSelection());
+				}
+			});
+			boolean bChecked = dms.length > 0;
+			if (bChecked) {
+				// turn on check if just one dm is not enabled
+				for (int j = 0; j < dms.length; j++) {
+					DownloadManager dm = dms[j];
+
+					if (!dm.getDownloadState().isNetworkEnabled(nn)) {
+						bChecked = false;
+						break;
+					}
+				}
+			}
+
+			itemNetwork.setSelection(bChecked);
+		}
+	}
+
+	protected static void addPeerSourceSubMenu(DownloadManager[] dms,
+			Menu menuPeerSource) {
+		boolean hasSelection = dms.length > 0;
+		for (int i = 0; i < PEPeerSource.PS_SOURCES.length; i++) {
+
+			final String p = PEPeerSource.PS_SOURCES[i];
+			String msg_text = "ConfigView.section.connection.peersource." + p;
+			final MenuItem itemPS = new MenuItem(menuPeerSource, SWT.CHECK);
+			itemPS.setData("peerSource", p);
+			Messages.setLanguageText(itemPS, msg_text); //$NON-NLS-1$
+			itemPS.addListener(SWT.Selection, new ListenerDMTask(dms) {
+				public void run(DownloadManager dm) {
+					dm.getDownloadState().setPeerSourceEnabled(p, itemPS.getSelection());
+				}
+			});
+			itemPS.setSelection(true);
+
+			boolean bChecked = hasSelection;
+			boolean bEnabled = !hasSelection;
+			if (bChecked) {
+				bEnabled = true;
+
+				// turn on check if just one dm is not enabled
+				for (int j = 0; j < dms.length; j++) {
+					DownloadManager dm = (DownloadManager) dms[j];
+
+					if (!dm.getDownloadState().isPeerSourceEnabled(p)) {
+						bChecked = false;
+					}
+					if (!dm.getDownloadState().isPeerSourcePermitted(p)) {
+						bEnabled = false;
+					}
+				}
+			}
+
+			itemPS.setSelection(bChecked);
+			itemPS.setEnabled(bEnabled);
+		}
+	}
+
+	protected static void exportHTTPSeeds(DownloadManager[] dms) {
+		final String NL = "\r\n";
+		String data = "";
+
+		boolean http_enable = COConfigurationManager.getBooleanParameter("HTTP.Data.Listen.Port.Enable");
+
+		String port;
+
+		if (http_enable) {
+
+			int p = COConfigurationManager.getIntParameter("HTTP.Data.Listen.Port");
+			int o = COConfigurationManager.getIntParameter("HTTP.Data.Listen.Port.Override");
+
+			if (o == 0) {
+
+				port = String.valueOf(p);
+
+			} else {
+
+				port = String.valueOf(o);
+			}
+		} else {
+
+			data = "You need to enable the HTTP port or modify the URL(s) appropriately"
+					+ NL + NL;
+
+			port = "<port>";
+		}
+
+		String ip = COConfigurationManager.getStringParameter("Tracker IP",
+				"");
+
+		if (ip.length() == 0) {
+
+			data += "You might need to modify the host address in the URL(s)"
+					+ NL + NL;
+
+			try {
+
+				InetAddress ia = NetworkAdmin.getSingleton().getDefaultPublicAddress();
+
+				if (ia != null) {
+
+					ip = IPToHostNameResolver.syncResolve(ia.getHostAddress(),
+							10000);
+				}
+			} catch (Throwable e) {
+
+			}
+
+			if (ip.length() == 0) {
+
+				ip = "<host>";
+			}
+		}
+
+		String base = "http://" + UrlUtils.convertIPV6Host(ip) + ":" + port
+				+ "/";
+
+		for (int i = 0; i < dms.length; i++) {
+
+			DownloadManager dm = dms[i];
+
+			if (dm == null) {
+				continue;
+			}
+
+			TOTorrent torrent = dm.getTorrent();
+
+			if (torrent == null) {
+
+				continue;
+			}
+
+			data += base + "webseed" + NL;
+
+			try {
+				data += base
+						+ "files/"
+						+ URLEncoder.encode(new String(torrent.getHash(),
+								"ISO-8859-1"), "ISO-8859-1") + "/" + NL + NL;
+
+			} catch (Throwable e) {
+
+			}
+		}
+
+		if (data.length() > 0) {
+			ClipboardCopy.copyToClipBoard(data);
+		}
+	}
+
+	protected static void exportTorrent(DownloadManager[] dms, Shell parentShell) {
+		// FileDialog for single download
+		// DirectoryDialog for multiple.
+		File[] destinations = new File[dms.length];
+		if (dms.length == 1) {
+			FileDialog fd = new FileDialog(parentShell, SWT.SAVE);
+			fd.setFileName(dms[0].getTorrentFileName());
+			String path = fd.open();
+			if (path == null) {
+				return;
+			}
+			destinations[0] = new File(path);
+		} else {
+			DirectoryDialog dd = new DirectoryDialog(parentShell, SWT.SAVE);
+			String path = dd.open();
+			if (path == null) {
+				return;
+			}
+			for (int i = 0; i < dms.length; i++) {
+				destinations[i] = new File(path,
+						new File(dms[i].getTorrentFileName()).getName());
+			}
+		}
+
+		int i = 0;
+		try {
+			for (; i < dms.length; i++) {
+				File target = destinations[i];
+				if (target.exists()) {
+					MessageBox mb = new MessageBox(parentShell, SWT.ICON_QUESTION
+							| SWT.YES | SWT.NO);
+					mb.setText(MessageText.getString("exportTorrentWizard.process.outputfileexists.title"));
+					mb.setMessage(MessageText.getString("exportTorrentWizard.process.outputfileexists.message")
+							+ "\n" + destinations[i].getName());
+
+					int result = mb.open();
+					if (result == SWT.NO) {
+						return;
+					}
+
+					if (!target.delete()) {
+						throw (new Exception("Failed to delete file"));
+					}
+				} // end deal with clashing torrent
+
+				// first copy the torrent - DON'T use "writeTorrent" as this amends the
+				// "filename" field in the torrent
+				TorrentUtils.copyToFile(dms[i].getDownloadState().getTorrent(), target);
+
+				// now remove the non-standard entries
+				TOTorrent dest = TOTorrentFactory.deserialiseFromBEncodedFile(target);
+				dest.removeAdditionalProperties();
+				dest.serialiseToBEncodedFile(target);
+			} // end for
+		} // end try
+		catch (Throwable e) {
+			Logger.log(new LogAlert(dms[i], LogAlert.UNREPEATABLE,
+					"Torrent export failed", e));
+		}
+	}
+
+	protected static void pauseDownloadsFor(DownloadManager[] dms) {
+
+		final List<DownloadManager> dms_to_pause = new ArrayList<DownloadManager>();
+
+		for (int i = 0; i < dms.length; i++) {
+
+			DownloadManager dm = dms[i];
+
+			if (ManagerUtils.isPauseable(dm)) {
+
+				dms_to_pause.add(dm);
+			}
+		}
+
+		if (dms_to_pause.size() == 0) {
+
+			return;
+		}
+
+		String text = MessageText.getString("dialog.pause.for.period.text");
+
+		SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+				"dialog.pause.for.period.title", "!" + text + "!");
+
+		int def = COConfigurationManager.getIntParameter(
+				"pause.for.period.default", 10);
+
+		entryWindow.setPreenteredText(String.valueOf(def), false);
+
+		entryWindow.prompt(new UIInputReceiverListener() {
+			public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
+				if (!entryWindow.hasSubmittedInput()) {
+
+					return;
+				}
+
+				String sReturn = entryWindow.getSubmittedInput();
+
+				if (sReturn == null) {
+
+					return;
+				}
+
+				int mins = -1;
+
+				try {
+
+					mins = Integer.valueOf(sReturn).intValue();
+
+				} catch (NumberFormatException er) {
+					// Ignore
+				}
+
+				if (mins <= 0) {
+
+					MessageBox mb = new MessageBox(Utils.findAnyShell(), SWT.ICON_ERROR
+							| SWT.OK);
+
+					mb.setText(MessageText.getString("MyTorrentsView.dialog.NumberError.title"));
+					mb.setMessage(MessageText.getString("MyTorrentsView.dialog.NumberError.text"));
+
+					mb.open();
+
+					return;
+				}
+
+				COConfigurationManager.setParameter("pause.for.period.default",
+						mins);
+
+				ManagerUtils.asyncPauseForPeriod(dms_to_pause, mins * 60);
+			}
+		});
+	}
+
+	protected static void addSpeedLimitsMenu(DownloadManager[] dms, Menu menu) {
+
+		AzureusCore azureus_core = AzureusCoreFactory.getSingleton();
+
+		final SpeedLimitHandler slh = SpeedLimitHandler.getSingleton(azureus_core);
+
+		boolean all_have_limit = true;
+
+		Set<String> common_profiles = new HashSet<String>();
+
+		final List<byte[]> dm_hashes = new ArrayList<byte[]>();
+
+		for (int i = 0; i < dms.length; i++) {
+			DownloadManager dm = dms[i];
+
+			int maxul = dm.getStats().getUploadRateLimitBytesPerSecond();
+			int maxdl = dm.getStats().getDownloadRateLimitBytesPerSecond();
+
+			if (maxul == 0 && maxdl == 0) {
+
+				all_have_limit = false;
+			}
+
+			TOTorrent t = dm.getTorrent();
+
+			if (t == null) {
+
+				common_profiles.clear();
+
+			} else {
+
+				try {
+					byte[] hash = t.getHash();
+
+					dm_hashes.add(hash);
+
+					List<String> profs = slh.getProfilesForDownload(hash);
+
+					if (i == 0) {
+
+						common_profiles.addAll(profs);
+
+					} else {
+
+						common_profiles.retainAll(profs);
+					}
+				} catch (TOTorrentException e) {
+
+					Debug.out(e);
+
+					common_profiles.clear();
+				}
+			}
+		}
+
+		java.util.List<String> profiles = slh.getProfileNames();
+
+		// add to profile
+
+		final Menu add_to_prof_menu = new Menu(menu.getShell(),
+				SWT.DROP_DOWN);
+		MenuItem add_to_prof_item = new MenuItem(menu, SWT.CASCADE);
+		add_to_prof_item.setMenu(add_to_prof_menu);
+
+		Messages.setLanguageText(add_to_prof_item,
+				"MyTorrentsView.menu.sl_add_to_prof");
+
+		if (!all_have_limit) {
+
+			add_to_prof_item.setEnabled(false);
+
+		} else {
+
+			for (final String p : profiles) {
+
+				MenuItem addItem = new MenuItem(add_to_prof_menu, SWT.PUSH);
+				addItem.setText(p);
+
+				addItem.addListener(SWT.Selection, new Listener() {
+					public void handleEvent(Event arg0) {
+						slh.addDownloadsToProfile(p, dm_hashes);
+
+						MenuFactory.showText("MainWindow.menu.speed_limits.info.title",
+								MessageText.getString("MainWindow.menu.speed_limits.info.prof",
+										new String[] {
+											p
+										}), slh.getProfile(p));
+					}
+				});
+			}
+		}
+
+		// remove from profile
+
+		final Menu remove_from_prof_menu = new Menu(menu.getShell(),
+				SWT.DROP_DOWN);
+		MenuItem remove_from_prof_item = new MenuItem(menu, SWT.CASCADE);
+		remove_from_prof_item.setMenu(remove_from_prof_menu);
+
+		Messages.setLanguageText(remove_from_prof_item,
+				"MyTorrentsView.menu.sl_remove_from_prof");
+
+		if (common_profiles.isEmpty()) {
+
+			remove_from_prof_item.setEnabled(false);
+
+		} else {
+
+			for (final String p : common_profiles) {
+
+				MenuItem addItem = new MenuItem(remove_from_prof_menu, SWT.PUSH);
+				addItem.setText(p);
+
+				addItem.addListener(SWT.Selection, new Listener() {
+					public void handleEvent(Event arg0) {
+						slh.removeDownloadsFromProfile(p, dm_hashes);
+
+						MenuFactory.showText("MainWindow.menu.speed_limits.info.title",
+								MessageText.getString("MainWindow.menu.speed_limits.info.prof",
+										new String[] {
+											p
+										}), slh.getProfile(p));
+					}
+				});
+			}
+		}
+	}
+
+	protected static void addTrackerTorrentMenu(Menu menuTracker,
+			DownloadManager[] dms, boolean changeUrl, boolean manualUpdate,
+			boolean allStopped, final boolean use_open_containing_folder) {
+		boolean hasSelection = dms.length > 0;
+
+		final MenuItem itemChangeTracker = new MenuItem(menuTracker, SWT.PUSH);
+		Messages.setLanguageText(itemChangeTracker,
+				"MyTorrentsView.menu.changeTracker");
+		Utils.setMenuItemImage(itemChangeTracker, "add_tracker");
+		itemChangeTracker.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(DownloadManager[] dms) {
+				if (dms.length > 0) {
+					new TrackerChangerWindow(dms);
+				}
+			}
+		});
+		itemChangeTracker.setEnabled(changeUrl);
+
+			// edit tracker URLs 
+		
+		final MenuItem itemEditTracker = new MenuItem(menuTracker, SWT.PUSH);
+		Messages.setLanguageText(itemEditTracker, "MyTorrentsView.menu.editTracker");
+		Utils.setMenuItemImage(itemEditTracker, "edit_trackers");
+		itemEditTracker.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(final DownloadManager[] dms) {
+				Map<String, List<DownloadManager>> same_map = new HashMap<String, List<DownloadManager>>();
+
+				for (DownloadManager dm : dms) {
+
+					TOTorrent torrent = dm.getTorrent();
+
+					if (torrent == null) {
+
+						continue;
+					}
+
+					List<List<String>> group = TorrentUtils.announceGroupsToList(torrent);
+
+					String str = "";
+
+					for (List<String> l : group) {
+						str += "[[";
+
+						for (String s : l) {
+							str += s + ", ";
+						}
+					}
+
+					List<DownloadManager> dl = same_map.get(str);
+
+					if (dl == null) {
+
+						dl = new ArrayList<DownloadManager>();
+
+						same_map.put(str, dl);
+					}
+
+					dl.add(dm);
+				}
+
+				for (final List<DownloadManager> set : same_map.values()) {
+
+					TOTorrent torrent = set.get(0).getTorrent();
+
+					List<List<String>> group = TorrentUtils.announceGroupsToList(torrent);
+
+					new MultiTrackerEditor(null, null, group,
+							new TrackerEditorListener() {
+								public void trackersChanged(String str, String str2,
+										List<List<String>> group) {
+									for (DownloadManager dm : set) {
+
+										TOTorrent torrent = dm.getTorrent();
+
+										TorrentUtils.listToAnnounceGroups(group, torrent);
+
+										try {
+											TorrentUtils.writeToFile(torrent);
+
+										} catch (Throwable e) {
+
+											Debug.printStackTrace(e);
+										}
+
+										if (dm.getTrackerClient() != null) {
+
+											dm.getTrackerClient().resetTrackerUrl(true);
+										}
+									}
+								}
+							}, true, true);
+				}
+			}
+		});
+
+		itemEditTracker.setEnabled(hasSelection);
+
+			// edit tracker URLs together
+			
+		final MenuItem itemEditTrackerMerged = new MenuItem(menuTracker, SWT.PUSH);
+		Messages.setLanguageText(itemEditTrackerMerged, "MyTorrentsView.menu.editTrackerMerge");
+		
+		itemEditTrackerMerged.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(final DownloadManager[] dms) {
+	
+				final List<List<String>>	merged_trackers = new ArrayList<List<String>>();
+				
+				Set<String>	added = new HashSet<String>();
+				
+				for (DownloadManager dm : dms) {
+	
+					TOTorrent torrent = dm.getTorrent();
+	
+					if (torrent == null) {
+	
+						continue;
+					}
+	
+					List<List<String>> group = TorrentUtils.announceGroupsToList(torrent);
+	
+					for ( List<String> set: group ){
+						
+						List<String>	rem = new ArrayList<String>();
+						
+						for ( String url_str: set ){
+							
+							try{
+								URL url = new URL( url_str );
+							
+								if ( TorrentUtils.isDecentralised( url )){
+									
+									continue;
+								}
+								
+								if ( !added.contains( url_str )){
+									
+									added.add( url_str );
+									
+									rem.add( url_str );
+								}
+							}catch( Throwable e ){
+								
+							}
+						}
+						
+						if ( rem.size() > 0 ){
+							
+							merged_trackers.add( rem );
+						}
+					}
+				}
+		
+				new MultiTrackerEditor(null, null, merged_trackers,
+					new TrackerEditorListener() {
+						public void trackersChanged(String str, String str2,
+								List<List<String>> group) {
+							for (DownloadManager dm : dms) {
+
+								TOTorrent torrent = dm.getTorrent();
+
+								TorrentUtils.listToAnnounceGroups(group, torrent);
+
+								try {
+									TorrentUtils.writeToFile(torrent);
+
+								} catch (Throwable e) {
+
+									Debug.printStackTrace(e);
+								}
+
+								if (dm.getTrackerClient() != null) {
+
+									dm.getTrackerClient().resetTrackerUrl(true);
+								}
+							}
+						}
+					}, true, true );
+			}
+		});
+	
+		itemEditTrackerMerged.setEnabled(dms.length > 1);
+		
+		// edit webseeds
+
+		final MenuItem itemEditWebSeeds = new MenuItem(menuTracker, SWT.PUSH);
+		Messages.setLanguageText(itemEditWebSeeds,
+				"MyTorrentsView.menu.editWebSeeds");
+		itemEditWebSeeds.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(final DownloadManager[] dms) {
+				final TOTorrent torrent = dms[0].getTorrent();
+
+				if (torrent == null) {
+
+					return;
+				}
+
+				List getright = getURLList(torrent, "url-list");
+				List webseeds = getURLList(torrent, "httpseeds");
+
+				Map ws = new HashMap();
+
+				ws.put("getright", getright);
+				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);
+
+			}
+
+			protected List getURLList(TOTorrent torrent, String key) {
+				Object obj = torrent.getAdditionalProperty(key);
+
+				if (obj instanceof byte[]) {
+
+					List l = new ArrayList();
+
+					l.add(obj);
+
+					return (l);
+
+				} else if (obj instanceof List) {
+
+					return ((List) obj);
+
+				} else {
+
+					return (new ArrayList());
+				}
+			}
+		});
+
+		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"));
+		itemManualUpdate.addListener(SWT.Selection, new ListenerDMTask(dms) {
+			public void run(DownloadManager dm) {
+				dm.requestTrackerAnnounce(false);
+			}
+		});
+		itemManualUpdate.setEnabled(manualUpdate);
+
+		boolean scrape_enabled = COConfigurationManager.getBooleanParameter("Tracker Client Scrape Enable");
+
+		boolean scrape_stopped = COConfigurationManager.getBooleanParameter("Tracker Client Scrape Stopped Enable");
+
+		boolean manualScrape = (!scrape_enabled)
+				|| ((!scrape_stopped) && allStopped);
+
+		final MenuItem itemManualScrape = new MenuItem(menuTracker, SWT.PUSH);
+		Messages.setLanguageText(itemManualScrape,
+				"GeneralView.label.trackerscrapeupdate");
+		//itemManualUpdate.setImage(ImageRepository.getImage("edit_trackers"));
+		itemManualScrape.addListener(SWT.Selection, new ListenerDMTask(dms, true, true) {
+			public void run(DownloadManager dm) {
+				dm.requestTrackerScrape(true);
+			}
+		});
+		itemManualScrape.setEnabled(manualScrape);
+
+		// download link
+
+		final MenuItem itemTorrentDL = new MenuItem(menuTracker, SWT.PUSH);
+		Messages.setLanguageText(itemTorrentDL, "MyTorrentsView.menu.torrent.dl");
+		itemTorrentDL.addListener(SWT.Selection, new ListenerDMTask(dms, false) {
+			public void run(DownloadManager dm) {
+
+				String content;
+
+				TOTorrent torrent = dm.getTorrent();
+
+				String link = null;
+
+				if (torrent == null) {
+
+					content = "Torrent not available";
+
+				} else {
+
+					link = TorrentUtils.getObtainedFrom(torrent);
+
+					if (link != null) {
+
+						try {
+							new URL(link);
+
+						} catch (Throwable e) {
+
+							link = null;
+						}
+					}
+
+					if (link != null) {
+
+						if (link.toLowerCase().startsWith("magnet:")) {
+
+							link = UrlUtils.getMagnetURI(dm);
+
+							content = "Torrent's magnet link:\r\n\r\n\t" + link;
+
+						} else {
+
+							content = "Torrent was obtained from\r\n\r\n\t" + link;
+						}
+					} else {
+
+						if (TorrentUtils.isReallyPrivate(torrent)) {
+
+							content = "Origin of torrent unknown and it is private so a magnet URI can't be used - sorry!";
+
+						} else {
+
+							link = UrlUtils.getMagnetURI(dm);
+
+							content = "Origin unavailable but magnet URI may work:\r\n\r\n\t"
+									+ link;
+						}
+					}
+				}
+
+				if (link != null) {
+
+					ClipboardCopy.copyToClipBoard(link);
+
+					content += "\r\n\r\nLink copied to clipboard";
+				}
+
+				final TextViewerWindow viewer = new TextViewerWindow(
+						MessageText.getString("MyTorrentsView.menu.torrent.dl") + ": "
+								+ dm.getDisplayName(), null, content, false);
+			}
+		});
+		itemTorrentDL.setEnabled(dms.length == 1);
+
+		// explore torrent file
+
+		final MenuItem itemTorrentExplore = new MenuItem(menuTracker, SWT.PUSH);
+		Messages.setLanguageText(itemTorrentExplore, "MyTorrentsView.menu."
+				+ (use_open_containing_folder ? "open_parent_folder" : "explore"));
+		itemTorrentExplore.addListener(SWT.Selection, new ListenerDMTask(dms, false) {
+			public void run(DownloadManager dm) {
+				ManagerUtils.open(new File(dm.getTorrentFileName()),
+						use_open_containing_folder);
+			}
+		});
+	}
+
+	protected static void moveTorrentFile(Shell shell, DownloadManager[] dms) {
+		if (dms != null && dms.length > 0) {
+
+			DirectoryDialog dd = new DirectoryDialog(shell);
+			String filter_path = TorrentOpener.getFilterPathTorrent();
+
+			// If we don't have a decent path, default to the path of the first
+			// torrent.
+			if (filter_path == null || filter_path.trim().length() == 0) {
+				filter_path = new File(dms[0].getTorrentFileName()).getParent();
+			}
+
+			dd.setFilterPath(filter_path);
+
+			dd.setText(MessageText.getString("MyTorrentsView.menu.movedata.dialog"));
+
+			String path = dd.open();
+
+			if (path != null) {
+
+				File target = new File(path);
+
+				TorrentOpener.setFilterPathTorrent(target.toString());
+
+				for (int i = 0; i < dms.length; i++) {
+
+					try {
+						dms[i].moveTorrentFile(target);
+
+					} catch (Throwable e) {
+
+						Logger.log(new LogAlert(dms[i], LogAlert.REPEATABLE,
+								"Download torrent move operation failed", e));
+					}
+				}
+			}
+		}
+	}
+
+	protected static void moveDataFiles(Shell shell, DownloadManager[] dms) {
+		if (dms != null && dms.length > 0) {
 
-		 final MenuItem itemMove = new MenuItem(menu, SWT.CASCADE);
-		 Messages.setLanguageText(itemMove, "MyTorrentsView.menu.move");
-		 Utils.setMenuItemImage(itemMove, "move");
-		 itemMove.setEnabled(hasSelection);
+			DirectoryDialog dd = new DirectoryDialog(shell);
 
-		 final Menu menuMove = new Menu(composite.getShell(), SWT.DROP_DOWN);
-		 itemMove.setMenu(menuMove);
+			dd.setFilterPath(TorrentOpener.getFilterPathData());
 
-		 final MenuItem itemMoveTop = new MenuItem(menuMove, SWT.PUSH);
-		 Messages.setLanguageText(itemMoveTop, "MyTorrentsView.menu.moveTop");
-		 Utils.setMenuItemImage(itemMoveTop, "top");
-		 itemMoveTop.addListener(SWT.Selection, new Listener() {
-		 public void handleEvent(Event event) {
-		 moveSelectedTorrentsTop();
-		 }
-		 });
-		 itemMoveTop.setEnabled(moveUp);
+			dd.setText(MessageText.getString("MyTorrentsView.menu.movedata.dialog"));
 
-		 final MenuItem itemMoveUp = new MenuItem(menuMove, SWT.PUSH);
-		 Messages.setLanguageText(itemMoveUp, "MyTorrentsView.menu.moveUp");
-		 Utils.setMenuItemImage(itemMoveUp, "up");
-		 itemMoveUp.addListener(SWT.Selection, new Listener() {
-		 public void handleEvent(Event event) {
-		 moveSelectedTorrentsUp();
-		 }
-		 });
+			String path = dd.open();
 
-		 final MenuItem itemMoveDown = new MenuItem(menuMove, SWT.PUSH);
-		 Messages.setLanguageText(itemMoveDown, "MyTorrentsView.menu.moveDown");
-		 Utils.setMenuItemImage(itemMoveDown, "down");
-		 itemMoveDown.addListener(SWT.Selection, new Listener() {
-		 public void handleEvent(Event event) {
-		 moveSelectedTorrentsDown();
-		 }
-		 });
+			if (path != null) {
 
-		 final MenuItem itemMoveEnd = new MenuItem(menuMove, SWT.PUSH);
-		 Messages.setLanguageText(itemMoveEnd, "MyTorrentsView.menu.moveEnd");
-		 Utils.setMenuItemImage(itemMoveEnd, "bottom");
-		 itemMoveEnd.addListener(SWT.Selection, new Listener() {
-		 public void handleEvent(Event event) {
-		 moveSelectedTorrentsEnd();
-		 }
-		 });
-		 itemMoveEnd.setEnabled(moveDown);
-		 */
-		/*  //TODO ensure that all limits combined don't go under the min 5kbs ?
-		 //Disable at the end of the list, thus the first item of the array is instanciated last.
-		 itemsSpeed[0] = new MenuItem(menuSpeed,SWT.PUSH);
-		 Messages.setLanguageText(itemsSpeed[0],"MyTorrentsView.menu.setSpeed.disable");
-		 itemsSpeed[0].setData("maxul", new Integer(-1));    
-		 itemsSpeed[0].addListener(SWT.Selection,itemsSpeedListener);
-		 */
+				TorrentOpener.setFilterPathData(path);
 
-			// Category
-		
-		Menu menuCategory = new Menu(composite.getShell(), SWT.DROP_DOWN);
-		final MenuItem itemCategory = new MenuItem(menu, SWT.CASCADE);
-		Messages.setLanguageText(itemCategory, "MyTorrentsView.menu.setCategory"); //$NON-NLS-1$
-		//itemCategory.setImage(ImageRepository.getImage("speed"));
-		itemCategory.setMenu(menuCategory);
-		itemCategory.setEnabled(hasSelection);
+				File target = new File(path);
 
-		addCategorySubMenu(dms, menuCategory, composite);
-		
-			// Tags
-			
-		Menu menuTags = new Menu(composite.getShell(), SWT.DROP_DOWN);
-		final MenuItem itemTags = new MenuItem(menu, SWT.CASCADE);
-		Messages.setLanguageText(itemTags, "label.tags");
-		itemTags.setMenu(menuTags);
-		itemTags.setEnabled(hasSelection);
+				for (int i = 0; i < dms.length; i++) {
 
-		TagUIUtils.addLibraryViewTagsSubMenu(dms, menuTags, composite);
-		
-			// personal share
-		
-		if ( isSeedingView ){
-			final MenuItem itemPersonalShare = new MenuItem(menu, SWT.PUSH);
-			Messages.setLanguageText(itemPersonalShare, "MyTorrentsView.menu.create_personal_share");
-			itemPersonalShare.addListener(SWT.Selection, new DMTask(dms, false) {
-				public void run(DownloadManager dm) {
-					File file = dm.getSaveLocation();
-					
-					Map<String,String>	properties = new HashMap<String, String>();
-					
-					properties.put( ShareManager.PR_PERSONAL, "true" );
-					
-					if ( file.isFile()){
-					
-						ShareUtils.shareFile( file.getAbsolutePath(), properties );
-						
-					}else if ( file.isDirectory()){
-						
-						ShareUtils.shareDir( file.getAbsolutePath(), properties );
+					try {
+						dms[i].moveDataFilesLive(target);
+
+					} catch (Throwable e) {
+
+						Logger.log(new LogAlert(dms[i], LogAlert.REPEATABLE,
+								"Download data move operation failed", e));
 					}
 				}
-			});
-			
-			boolean	can_share_pers = dms.length > 0;
-			
-			for ( DownloadManager dm: dms ){
-				
-				if ( !( dm.isDownloadComplete( true ) && dm.filesExist( true ))){
-				
-					can_share_pers = false;
-				}
 			}
-			
-			itemPersonalShare.setEnabled( can_share_pers );
 		}
-		
-		
-		// ---
-		new MenuItem(menu, SWT.SEPARATOR);
+	}
 
-		// Queue
-		final MenuItem itemQueue = new MenuItem(menu, SWT.PUSH);
-		Messages.setLanguageText(itemQueue, "MyTorrentsView.menu.queue"); //$NON-NLS-1$
-		Utils.setMenuItemImage(itemQueue, "start");
-		itemQueue.addListener(SWT.Selection, new Listener() {
-			public void handleEvent(Event event) {
-				Utils.getOffOfSWTThread(new AERunnable() {
-					public void runSupport() {
-						queueDataSources(dms, true);
-					}
-				});
-			}
-		});
-		itemQueue.setEnabled(start);
+	public static void repositionManual(final TableView tv,
+			final DownloadManager[] dms, final Shell shell,
+			final boolean isSeedingView) {
+		SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+				"MyTorrentsView.dialog.setPosition.title",
+				"MyTorrentsView.dialog.setPosition.text");
+		entryWindow.prompt(new UIInputReceiverListener() {
+			public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
+				if (!entryWindow.hasSubmittedInput()) {
+					return;
+				}
+				String sReturn = entryWindow.getSubmittedInput();
 
-		// Force Start
-		if (userMode > 0) {
-			final MenuItem itemForceStart = new MenuItem(menu, SWT.CHECK);
-			Messages.setLanguageText(itemForceStart, "MyTorrentsView.menu.forceStart");
-			Utils.setMenuItemImage(itemForceStart, "forcestart");
-			itemForceStart.addListener(SWT.Selection, new DMTask(dms) {
-				public void run(DownloadManager dm) {
-					if (ManagerUtils.isForceStartable(dm)) {
-						dm.setForceStart(itemForceStart.getSelection());
-					}
+				if (sReturn == null)
+					return;
+
+				int newPosition = -1;
+				try {
+					newPosition = Integer.valueOf(sReturn).intValue();
+				} catch (NumberFormatException er) {
+					// Ignore
 				}
-			});
-			itemForceStart.setSelection(forceStart);
-			itemForceStart.setEnabled(forceStartEnabled);
-		}
 
-		// Pause
-		if (userMode > 0) {
-			final MenuItem itemPause = new MenuItem(menu, SWT.PUSH);
-			Messages.setLanguageText(itemPause, "v3.MainWindow.button.pause"); 
-			Utils.setMenuItemImage(itemPause, "pause");
-			itemPause.addListener(SWT.Selection, new Listener() {
-				public void handleEvent(Event event) {
-					Utils.getOffOfSWTThread(new AERunnable() {
-						public void runSupport() {
-							pauseDataSources(dms);
-						}
-					});
+				AzureusCore azureus_core = AzureusCoreFactory.getSingleton();
+				if (azureus_core == null) {
+					return;
 				}
-			}); 
-			itemPause.setEnabled(stop);
-		}
-		
-		// Stop
-		final MenuItem itemStop = new MenuItem(menu, SWT.PUSH);
-		Messages.setLanguageText(itemStop, "MyTorrentsView.menu.stop"); 
-		Utils.setMenuItemImage(itemStop, "stop");
-		itemStop.addListener(SWT.Selection, new Listener() {
-			public void handleEvent(Event event) {
-				Utils.getOffOfSWTThread(new AERunnable() {
-					public void runSupport() {
-						stopDataSources(dms);
-					}
-				});
-			}
-		}); 
-		itemStop.setEnabled(stop);
+				int size = azureus_core.getGlobalManager().downloadManagerCount(
+						isSeedingView);
+				if (newPosition > size)
+					newPosition = size;
 
-		// Force Recheck
-		final MenuItem itemRecheck = new MenuItem(menu, SWT.PUSH);
-		Messages.setLanguageText(itemRecheck, "MyTorrentsView.menu.recheck");
-		Utils.setMenuItemImage(itemRecheck, "recheck");
-		itemRecheck.addListener(SWT.Selection, new DMTask(dms) {
-			public void run(DownloadManager dm) {
-				if (dm.canForceRecheck()) {
-					dm.forceRecheck();
+				if (newPosition <= 0) {
+					MessageBox mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+					mb.setText(MessageText.getString("MyTorrentsView.dialog.NumberError.title"));
+					mb.setMessage(MessageText.getString("MyTorrentsView.dialog.NumberError.text"));
+
+					mb.open();
+					return;
 				}
-			}
-		});
-		itemRecheck.setEnabled(recheck);
 
-		// Delete
-		final MenuItem itemRemove = new MenuItem(menu, SWT.PUSH);
-		Messages.setLanguageText(itemRemove, "menu.delete.options");
-		Utils.setMenuItemImage(itemRemove, "delete");
-		itemRemove.addListener(SWT.Selection, new Listener() {
-			public void handleEvent(Event event) {
-				removeDownloads(dms, null, true);
+				moveSelectedTorrentsTo(tv, dms, newPosition);
 			}
 		});
-		itemRemove.setEnabled(hasSelection);
-
 	}
 
-	private static void addCategorySubMenu(final DownloadManager[] dms, Menu menuCategory, final Composite composite) {
+	protected static void addCategorySubMenu(final DownloadManager[] dms,
+			Menu menuCategory, final Composite composite) {
 		MenuItem[] items = menuCategory.getItems();
 		int i;
 		for (i = 0; i < items.length; i++) {
@@ -1731,12 +2055,12 @@ public class TorrentUtil {
 
 		Category[] categories = CategoryManager.getCategories();
 		Arrays.sort(categories);
-		
+
 		// Ensure that there is at least one user category available.
 		boolean allow_category_selection = categories.length > 0;
 		if (allow_category_selection) {
 			boolean user_category_found = false;
-			for (i=0; i<categories.length; i++) {
+			for (i = 0; i < categories.length; i++) {
 				if (categories[i].getType() == Category.TYPE_USER) {
 					user_category_found = true;
 					break;
@@ -1751,7 +2075,7 @@ public class TorrentUtil {
 			if (catUncat != null) {
 				final MenuItem itemCategory = new MenuItem(menuCategory, SWT.PUSH);
 				Messages.setLanguageText(itemCategory, catUncat.getName());
-				itemCategory.addListener(SWT.Selection, new DMTask(dms) {
+				itemCategory.addListener(SWT.Selection, new ListenerDMTask(dms) {
 					public void run(DownloadManager dm) {
 						dm.getDownloadState().setCategory(catUncat);
 					}
@@ -1765,7 +2089,7 @@ public class TorrentUtil {
 				if (category.getType() == Category.TYPE_USER) {
 					final MenuItem itemCategory = new MenuItem(menuCategory, SWT.PUSH);
 					itemCategory.setText(category.getName());
-					itemCategory.addListener(SWT.Selection, new DMTask(dms) {
+					itemCategory.addListener(SWT.Selection, new ListenerDMTask(dms) {
 						public void run(DownloadManager dm) {
 							dm.getDownloadState().setCategory(category);
 						}
@@ -1777,53 +2101,56 @@ public class TorrentUtil {
 		}
 
 		final MenuItem itemAddCategory = new MenuItem(menuCategory, SWT.PUSH);
-		Messages.setLanguageText(itemAddCategory, "MyTorrentsView.menu.setCategory.add");
+		Messages.setLanguageText(itemAddCategory,
+				"MyTorrentsView.menu.setCategory.add");
 
-		itemAddCategory.addListener(SWT.Selection, new DMTask(dms) {
+		itemAddCategory.addListener(SWT.Selection, new ListenerDMTask(dms) {
 			public void run(DownloadManager[] dms) {
-				CategoryAdderWindow adderWindow = new CategoryAdderWindow(composite.getDisplay());
+				CategoryAdderWindow adderWindow = new CategoryAdderWindow(
+						composite.getDisplay());
 				Category newCategory = adderWindow.getNewCategory();
-				if (newCategory != null) assignToCategory(dms, newCategory);
+				if (newCategory != null)
+					assignToCategory(dms, newCategory);
 			}
 		});
 
 	}
 
-
-	
-  private static void moveSelectedTorrentsTo(TableView tv,
+	private static void moveSelectedTorrentsTo(TableView tv,
 			DownloadManager[] dms, int iNewPos) {
-    if (dms == null || dms.length == 0) {
-      return;
-    }
-    
-    TableColumnCore sortColumn = tv == null ? null : tv.getSortColumn();
-    boolean isSortAscending = sortColumn == null ? true
+		if (dms == null || dms.length == 0) {
+			return;
+		}
+
+		TableColumnCore sortColumn = tv == null ? null : tv.getSortColumn();
+		boolean isSortAscending = sortColumn == null ? true
 				: sortColumn.isSortAscending();
 
-    for (int i = 0; i < dms.length; i++) {
-      DownloadManager dm = dms[i];
-      int iOldPos = dm.getPosition();
-      
-      dm.getGlobalManager().moveTo(dm, iNewPos);
-      if (isSortAscending) {
-        if (iOldPos > iNewPos)
-          iNewPos++;
-      } else {
-        if (iOldPos < iNewPos)
-          iNewPos--;
-      }
-    }
-
-    if (tv != null) {
-      boolean bForceSort = sortColumn.getName().equals("#");
-      tv.columnInvalidate("#");
-      tv.refreshTable(bForceSort);
-    }
-  }
-
-	private static void changeDirSelectedTorrents(DownloadManager[] dms, Shell shell) {
-		if (dms.length <= 0) return;
+		for (int i = 0; i < dms.length; i++) {
+			DownloadManager dm = dms[i];
+			int iOldPos = dm.getPosition();
+
+			dm.getGlobalManager().moveTo(dm, iNewPos);
+			if (isSortAscending) {
+				if (iOldPos > iNewPos)
+					iNewPos++;
+			} else {
+				if (iOldPos < iNewPos)
+					iNewPos--;
+			}
+		}
+
+		if (tv != null) {
+			boolean bForceSort = sortColumn.getName().equals("#");
+			tv.columnInvalidate("#");
+			tv.refreshTable(bForceSort);
+		}
+	}
+
+	protected static void changeDirSelectedTorrents(DownloadManager[] dms,
+			Shell shell) {
+		if (dms.length <= 0)
+			return;
 
 		String sDefPath = COConfigurationManager.getStringParameter("Default save path");
 
@@ -1843,18 +2170,18 @@ public class TorrentUtil {
 			File fSavePath = new File(sSavePath);
 			for (int i = 0; i < dms.length; i++) {
 				DownloadManager dm = dms[i];
-				
+
 				int state = dm.getState();
-				if (state == DownloadManager.STATE_STOPPED) {
+				if (state != DownloadManager.STATE_ERROR) {
 					if (!dm.filesExist(true)) {
 						state = DownloadManager.STATE_ERROR;
 					}
 				}
 
 				if (state == DownloadManager.STATE_ERROR) {
-					
+
 					dm.setTorrentSaveDir(sSavePath);
-					
+
 					boolean found = dm.filesExist(true);
 					if (!found && dm.getTorrent() != null
 							&& !dm.getTorrent().isSimpleTorrent()) {
@@ -1868,7 +2195,6 @@ public class TorrentUtil {
 						}
 					}
 
-
 					if (found) {
 						dm.stopIt(DownloadManager.STATE_STOPPED, false, false);
 
@@ -1895,34 +2221,39 @@ public class TorrentUtil {
 		}
 	}
 
-	public static void hostTorrents(final Object[] download_managers, final AzureusCore azureus_core,
-			final Composite composite) {
-		DMTask task = new DMTask(toDMS(download_managers)) {
+	public static void hostTorrents(final Object[] download_managers) {
+		ListenerDMTask task = new ListenerDMTask(toDMS(download_managers), true,
+				true) {
 			public void run(DownloadManager dm) {
-				ManagerUtils.host(azureus_core, dm, composite);
+				ManagerUtils.host(AzureusCoreFactory.getSingleton(), dm);
 			}
 		};
 		task.go();
 		UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 		if (uiFunctions != null) {
-			uiFunctions.openView(UIFunctions.VIEW_MYTRACKER, null);
+			uiFunctions.getMDI().showEntryByID(
+					MultipleDocumentInterface.SIDEBAR_SECTION_MY_TRACKER);
 		}
 	}
 
-	public static void publishTorrents(final Object[] download_managers, final AzureusCore azureus_core,
-			final Composite composite) {
-		DMTask task = new DMTask(toDMS(download_managers)) {
+	public static void publishTorrents(final Object[] download_managers) {
+		ListenerDMTask task = new ListenerDMTask(toDMS(download_managers), true,
+				true) {
 			public void run(DownloadManager dm) {
-				ManagerUtils.publish(azureus_core, dm, composite);
+				ManagerUtils.publish(AzureusCoreFactory.getSingleton(), dm);
 			}
 		};
 		task.go();
 		UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 		if (uiFunctions != null) {
-			uiFunctions.openView(UIFunctions.VIEW_MYTRACKER, null);
+			uiFunctions.getMDI().showEntryByID(
+					MultipleDocumentInterface.SIDEBAR_SECTION_MY_TRACKER);
 		}
 	}
 
+	/**
+	 * @param datasources DownloadManager, DiskManagerFileInfo, SelectedContent
+	 */
 	public static void removeDataSources(final Object[] datasources) {
 		DownloadManager[] dms = toDMS(datasources);
 		removeDownloads(dms, null);
@@ -1931,6 +2262,10 @@ public class TorrentUtil {
 			FilesViewMenuUtil.changePriority(FilesViewMenuUtil.PRIORITY_DELETE,
 					fileInfos);
 		}
+		DownloadStubEx[] stubs = toDownloadStubs(  datasources );
+		if ( stubs.length > 0 ){
+			removeDownloadStubs(stubs,null,false);
+		}
 	}
 
 	public static boolean shouldStopGroup(Object[] datasources) {
@@ -1947,7 +2282,7 @@ public class TorrentUtil {
 				return true;
 			}
 		}
-		
+
 		for (DiskManagerFileInfo fileInfo : dmfi) {
 			if (!fileInfo.isSkipped()) {
 				return true;
@@ -1988,7 +2323,7 @@ public class TorrentUtil {
 			ManagerUtils.pause(dm, null);
 		}
 	}
-	
+
 	public static void queueDataSources(Object[] datasources,
 			boolean startStoppedParents) {
 		DownloadManager[] dms = toDMS(datasources);
@@ -2011,7 +2346,7 @@ public class TorrentUtil {
 	}
 
 	public static void resumeTorrents(Object[] download_managers) {
-		DMTask task = new DMTask(toDMS(download_managers)) {
+		ListenerDMTask task = new ListenerDMTask(toDMS(download_managers)) {
 			public void run(DownloadManager dm) {
 				ManagerUtils.start(dm);
 			}
@@ -2020,21 +2355,24 @@ public class TorrentUtil {
 	}
 
 	// Category Stuff
-	public static void assignToCategory(Object[] download_managers, final Category category) {
-		DMTask task = new DMTask(toDMS(download_managers)) {
+	public static void assignToCategory(Object[] download_managers,
+			final Category category) {
+		ListenerDMTask task = new ListenerDMTask(toDMS(download_managers)) {
 			public void run(DownloadManager dm) {
 				dm.getDownloadState().setCategory(category);
 			}
 		};
 		task.go();
 	}
-	
+
 	public static void promptUserForComment(final DownloadManager[] dms) {
-		if (dms.length == 0) {return;}
+		if (dms.length == 0) {
+			return;
+		}
 		DownloadManager dm = dms[0];
-		
+
 		// Create dialog box.
-		String suggested = dm.getDownloadState().getUserComment(); 
+		String suggested = dm.getDownloadState().getUserComment();
 		String msg_key_prefix = "MyTorrentsView.menu.edit_comment.enter.";
 		SimpleTextEntryWindow text_entry = new SimpleTextEntryWindow();
 		text_entry.setTitle(msg_key_prefix + "title");
@@ -2046,7 +2384,7 @@ public class TorrentUtil {
 				if (text_entry.hasSubmittedInput()) {
 					String value = text_entry.getSubmittedInput();
 					final String value_to_set = (value.length() == 0) ? null : value;
-					DMTask task = new DMTask(dms) {
+					ListenerDMTask task = new ListenerDMTask(dms) {
 						public void run(DownloadManager dm) {
 							dm.getDownloadState().setUserComment(value_to_set);
 						}
@@ -2055,9 +2393,8 @@ public class TorrentUtil {
 				}
 			}
 		});
-		
-	}
 
+	}
 
 	private static DownloadManager[] toDMS(Object[] objects) {
 		int count = 0;
@@ -2078,6 +2415,16 @@ public class TorrentUtil {
 		return resultTrim;
 	}
 
+	private static DownloadStubEx[] toDownloadStubs(Object[] objects){
+		List<DownloadStubEx>	result = new ArrayList<DownloadStubEx>( objects.length );
+		for ( Object o: objects ){
+			if ( o instanceof DownloadStubEx ){
+				result.add((DownloadStubEx)o);
+			}
+		}
+		return( result.toArray( new DownloadStubEx[result.size()]));
+	}
+	
 	private static DiskManagerFileInfo[] toDMFI(Object[] objects) {
 		int count = 0;
 		DiskManagerFileInfo[] result = new DiskManagerFileInfo[objects.length];
@@ -2093,78 +2440,15 @@ public class TorrentUtil {
 					if (dm != null) {
 						DiskManagerFileInfo[] infos = dm.getDiskManagerFileInfo();
 						if (fileIndex < infos.length) {
-							result[count++] = infos[fileIndex];
-						}
-					}
-				}
-			}
-		}
-		DiskManagerFileInfo[] resultTrim = new DiskManagerFileInfo[count];
-		System.arraycopy(result, 0, resultTrim, 0, count);
-		return resultTrim;
-	}
-
-	private abstract static class DMTask implements Listener {
-		private DownloadManager[] dms;
-
-		private boolean ascending;
-		private boolean	async;
-
-		public DMTask(DownloadManager[] dms) {
-			this(dms, true);
-		}
-
-		public DMTask(DownloadManager[] dms, boolean ascending) {
-			this.dms = dms;
-			this.ascending = ascending;
-		}
-
-		public DMTask(DownloadManager[] dms, boolean ascending, boolean async ) {
-			this.dms = dms;
-			this.ascending = ascending;
-			this.async = async;
-		}
-
-		// One of the following methods should be overridden.
-		public void run(DownloadManager dm) {
-		}
-
-		public void run(DownloadManager[] dm) {
-		}
-
-		public void handleEvent(Event event) {
-			if ( async ){
-				
-				new AEThread2( "DMTask:async", true )
-				{
-					public void
-					run()
-					{
-			go();
-		}
-				}.start();
-			}else{
-				
-				go();
-			}
-		}
-
-		public void go() {
-			try {
-				DownloadManager dm = null;
-				for (int i = 0; i < dms.length; i++) {
-					dm = dms[ascending ? i : (dms.length - 1) - i];
-					if (dm == null) {
-						continue;
+							result[count++] = infos[fileIndex];
+						}
 					}
-					this.run(dm);
 				}
-				this.run(dms);
-			}
-			catch (Exception e) {
-				Debug.printStackTrace(e);
 			}
 		}
+		DiskManagerFileInfo[] resultTrim = new DiskManagerFileInfo[count];
+		System.arraycopy(result, 0, resultTrim, 0, count);
+		return resultTrim;
 	}
 
 	/**
@@ -2176,11 +2460,18 @@ public class TorrentUtil {
 	 *
 	 * @since 3.0.2.3
 	 */
-	public static boolean isFileTorrent(File torrentFile, 
-			String torrentName) {
+	public static boolean isFileTorrent(File torrentFile, String torrentName, boolean warnOnError ) {
 		String sFirstChunk = null;
 		try {
 			sFirstChunk = FileUtil.readFileAsString(torrentFile, 16384).toLowerCase();
+			
+			try{
+				if (!sFirstChunk.startsWith("d")) {
+					sFirstChunk = FileUtil.readGZippedFileAsString(torrentFile, 16384).toLowerCase();
+				}
+			}catch( Throwable e ){
+				
+			}
 		} catch (IOException e) {
 			Debug.out("warning", e);
 		}
@@ -2189,251 +2480,285 @@ public class TorrentUtil {
 		}
 
 		if (!sFirstChunk.startsWith("d")) {
-			boolean isHTML = sFirstChunk.indexOf("<html") >= 0;
 			
-			String retry_url = UrlUtils.parseTextForMagnets( torrentName );
+			boolean isHTML = sFirstChunk.indexOf("<html") >= 0;
+
+			String retry_url = UrlUtils.parseTextForMagnets(torrentName);
 			if (retry_url == null) {
-				retry_url = UrlUtils.parseTextForMagnets(sFirstChunk); 	
+				retry_url = UrlUtils.parseTextForMagnets(sFirstChunk);
 			}
-			
+
 			if (retry_url != null) {
-				TorrentOpener.openTorrent( retry_url );
+				TorrentOpener.openTorrent(retry_url);
 				return false;
 			}
-			
-			String[] buttons;
-			
-			buttons = new String[]{ MessageText.getString("Button.ok") };
-			
-			MessageBoxShell boxShell = new MessageBoxShell(
-					MessageText.getString("OpenTorrentWindow.mb.notTorrent.title"),
-					MessageText.getString("OpenTorrentWindow.mb.notTorrent.text",
-							new String[] {
-							torrentName,
-							isHTML ? "" : MessageText.getString("OpenTorrentWindow.mb.notTorrent.cannot.display")
-					}),
-					buttons
-					, 0 );
-			
-			if (isHTML) {
-				boxShell.setHtml(sFirstChunk);
-			}
-			boxShell.open(null);
 
+			if ( warnOnError ){
+				String[] buttons;
+	
+				buttons = new String[] {
+					MessageText.getString("Button.ok")
+				};
+	
+				MessageBoxShell boxShell = new MessageBoxShell(
+						MessageText.getString("OpenTorrentWindow.mb.notTorrent.title"),
+						MessageText.getString(
+								"OpenTorrentWindow.mb.notTorrent.text",
+								new String[] {
+									torrentName,
+									isHTML
+											? ""
+											: MessageText.getString("OpenTorrentWindow.mb.notTorrent.cannot.display")
+								}), buttons, 0);
+	
+				if (isHTML) {
+					boxShell.setHtml(sFirstChunk);
+				}
+				
+				boxShell.open(null);
+			}
+			
 			return false;
 		}
 
 		return true;
 	}
 
+	// XXX Don't think *View's need this call anymore.  ToolBarView does it fo them
 	public static Map<String, Long> calculateToolbarStates(
-				ISelectedContent[] currentContent, String viewID) {
-			//System.out.println("updateCoreItems(" + currentContent.length + ", " + viewID + " via " + Debug.getCompressedStackTrace());
-			/*
-			String[] TBKEYS = new String[] {
-				"download",
-				"play",
-				"stream",
-				"run",
-				"top",
-				"up",
-				"down",
-				"bottom",
-				"start",
-				"stop",
-				"remove"
-			};
-			*/
-		
-			Map<String, Long> mapNewToolbarStates = new HashMap<String, Long>();
-			
-			String[] itemsNeedingSelection = {};
-	
-			String[] itemsNeedingRealDMSelection = {
-				"remove",
-				"top",
-				"bottom",
-				"transcode",
-				"startstop",
-			};
-	
-			String[] itemsRequiring1DMwithHash = {
-				"details",
-				"comment",
-				"up",
-				"down",
-			};
-	
-			String[] itemsRequiring1DMSelection = {};
-	
-			int numSelection = currentContent.length;
-			boolean hasSelection = numSelection > 0;
-			boolean has1Selection = numSelection == 1;
-	
-			for (int i = 0; i < itemsNeedingSelection.length; i++) {
-				String itemID = itemsNeedingSelection[i];
+			ISelectedContent[] currentContent, String viewID_unused) {
+		//System.out.println("calculateToolbarStates(" + currentContent.length + ", " + viewID_unused + " via " + Debug.getCompressedStackTrace());
+		/*
+		String[] TBKEYS = new String[] {
+			"download",
+			"play",
+			"stream",
+			"run",
+			"top",
+			"up",
+			"down",
+			"bottom",
+			"start",
+			"stop",
+			"remove"
+		};
+		*/
+
+		Map<String, Long> mapNewToolbarStates = new HashMap<String, Long>();
+
+		String[] itemsNeedingSelection = {};
+
+		String[] itemsNeedingRealDMSelection = {
+			"remove",
+			"top",
+			"bottom",
+			"transcode",
+			"startstop",
+		};
+
+		String[] itemsRequiring1DMwithHash = {
+			"details",
+			"comment",
+			"up",
+			"down",
+		};
+
+		String[] itemsRequiring1DMSelection = {};
+
+		int numSelection = currentContent.length;
+		boolean hasSelection = numSelection > 0;
+		boolean has1Selection = numSelection == 1;
+
+		for (int i = 0; i < itemsNeedingSelection.length; i++) {
+			String itemID = itemsNeedingSelection[i];
 			mapNewToolbarStates.put(itemID, hasSelection
 					? UIToolBarItem.STATE_ENABLED : 0);
+		}
+
+		TableView tv = SelectedContentManager.getCurrentlySelectedTableView();
+
+		boolean hasRealDM = tv != null; // not sure why we assume that the existance of any table view
+		// implies we have a real DM... Anyway, if false go ahead and test
+
+		if (!hasRealDM && numSelection > 0) {
+			hasRealDM = true;
+			for (int i = 0; i < currentContent.length; i++) {
+				ISelectedContent content = currentContent[i];
+				DownloadManager dm = content.getDownloadManager();
+				if (dm == null) {
+					hasRealDM = false;
+					break;
+				}
 			}
-	
-			TableView tv = SelectedContentManager.getCurrentlySelectedTableView();
-			
-			boolean hasRealDM = tv != null;	// not sure why we assume that the existance of any table view
-											// implies we have a real DM... Anyway, if false go ahead and test
-			
-			if ( !hasRealDM && numSelection > 0 ){
-				hasRealDM = true;
-				for (int i = 0; i < currentContent.length; i++) {
-					ISelectedContent content = currentContent[i];
-					DownloadManager dm = content.getDownloadManager();
-					if ( dm == null ){
-						hasRealDM = false;
-						break;
+		}
+		if (!hasRealDM) {
+			MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
+			if (mdi != null) {
+				MdiEntrySWT entry = mdi.getCurrentEntrySWT();
+				if (entry != null) {
+					if (entry.getDatasource() instanceof DownloadManager) {
+						hasRealDM = true;
+					} else if ((entry instanceof UIPluginView)
+							&& (((UIPluginView) entry).getDataSource() instanceof DownloadManager)) {
+						hasRealDM = true;
 					}
 				}
 			}
-			if (!hasRealDM) {
-				MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
-				if (mdi != null) {
-					MdiEntrySWT entry = mdi.getCurrentEntrySWT();
-					if (entry != null) {
-						if (entry.getDatasource() instanceof DownloadManager) {
-							hasRealDM = true;
-						} else if ((entry.getView() instanceof UIPluginView)
-								&& (((UIPluginView) entry.getView()).getDataSource() instanceof DownloadManager)) {
-							hasRealDM = true;
-						}
+		}
+
+		boolean canStart = false;
+		boolean canStop = false;
+		boolean canRemoveFileInfo = false;
+		boolean canRunFileInfo = false;
+		boolean hasDM = false;
+
+		if (currentContent.length > 0 && hasRealDM) {
+			
+				// well, in fact, we can have hasRealDM set to true here (because tv isn't null) and actually not have a real dm.
+				// fancy that - protect against null DownloadManagers...
+			
+			boolean canMoveUp = false;
+			boolean canMoveDown = false;
+			boolean canDownload = false;
+			GlobalManager gm = null;
+			for (int i = 0; i < currentContent.length; i++) {
+				ISelectedContent content = currentContent[i];
+				DownloadManager dm = content.getDownloadManager();
+				if ( dm == null ){
+					if (!canDownload && content.getDownloadInfo() != null) {
+						canDownload = true;
 					}
+					continue;
 				}
-			}
-	
-			boolean canStart = false;
-			boolean canStop = false;
-			boolean canRemoveFileInfo = false;
-			boolean canRunFileInfo = false;
-			boolean hasDM = false;
-	
-			if (currentContent.length > 0 && hasRealDM) {
-				boolean	canMoveUp	= true;
-				boolean	canMoveDown	= true;
-				GlobalManager gm = currentContent[0].getDownloadManager().getGlobalManager();
-				for (int i = 0; i < currentContent.length; i++) {
-					ISelectedContent content = currentContent[i];
-					DownloadManager dm = content.getDownloadManager();
-					if ( !gm.isMoveableUp( dm )){
-						canMoveUp = false;
+				if ( gm == null ){
+					gm = dm.getGlobalManager();
+				}
+				
+				int fileIndex = content.getFileIndex();
+				if (fileIndex == -1) {
+					if (!canMoveUp && gm.isMoveableUp(dm)) {
+						canMoveUp = true;
 					}
-					if ( !gm.isMoveableDown( dm )){
-						canMoveDown = false;
+					if (!canMoveDown && gm.isMoveableDown(dm)) {
+						canMoveDown = true;
 					}
-					int fileIndex = content.getFileIndex();
-					if (fileIndex == -1) {
-						hasDM = true;
-	  				if (!canStart && ManagerUtils.isStartable(dm)) {
-	  					canStart = true;
-	  				}
-	  				if (!canStop && ManagerUtils.isStopable(dm)) {
-	  					canStop = true;
-	  				}
-					} else {
-						DiskManagerFileInfo[] fileInfos = dm.getDiskManagerFileInfo();
-						if (fileIndex < fileInfos.length) {
-							DiskManagerFileInfo fileInfo = fileInfos[fileIndex];
-			    		if (!canStart && (fileInfo.isSkipped())) {
-			    			canStart = true;
-			    		}
-			    		
-			    		if (!canStop && !fileInfo.isSkipped()) {
-			    			canStop = true;
-			    		}
-			    		
-							if (!canRemoveFileInfo && !fileInfo.isSkipped()) {
-								int storageType = fileInfo.getStorageType();
-								if (storageType == DiskManagerFileInfo.ST_LINEAR
-										|| storageType == DiskManagerFileInfo.ST_COMPACT) {
-									canRemoveFileInfo = true;
-								}
-			    		}
-							
-							if (!canRunFileInfo
-									&& fileInfo.getAccessMode() == DiskManagerFileInfo.READ
-									&& fileInfo.getDownloaded() == fileInfo.getLength()
-									&& fileInfo.getFile(true).exists()) {
-								canRunFileInfo = true;
+
+					hasDM = true;
+					if (!canStart && ManagerUtils.isStartable(dm)) {
+						canStart = true;
+					}
+					if (!canStop && ManagerUtils.isStopable(dm)) {
+						canStop = true;
+					}
+				} else {
+					DiskManagerFileInfoSet fileInfos = dm.getDiskManagerFileInfoSet();
+					if (fileIndex < fileInfos.nbFiles()) {
+						DiskManagerFileInfo fileInfo = fileInfos.getFiles()[fileIndex];
+						if (!canStart && (fileInfo.isSkipped())) {
+							canStart = true;
+						}
+
+						if (!canStop && !fileInfo.isSkipped()) {
+							canStop = true;
+						}
+
+						if (!canRemoveFileInfo && !fileInfo.isSkipped()) {
+							int storageType = fileInfo.getStorageType();
+							if (storageType == DiskManagerFileInfo.ST_LINEAR
+									|| storageType == DiskManagerFileInfo.ST_COMPACT) {
+								canRemoveFileInfo = true;
 							}
 						}
+
+						if (!canRunFileInfo
+								&& fileInfo.getAccessMode() == DiskManagerFileInfo.READ
+								&& fileInfo.getDownloaded() == fileInfo.getLength()
+								&& fileInfo.getFile(true).exists()) {
+							canRunFileInfo = true;
+						}
 					}
 				}
-				boolean canRemove = hasDM || canRemoveFileInfo;
-				
-				mapNewToolbarStates.put("remove", canRemove
-						? UIToolBarItem.STATE_ENABLED : 0);
-				
-					// actually we roll the dm indexes when > 1 selected and we get
-					// to the top/bottom, so only enforce this for single selection :)
-				
-				if ( currentContent.length == 1 ){
-					mapNewToolbarStates.put("up", canMoveUp ? UIToolBarItem.STATE_ENABLED : 0);
-					mapNewToolbarStates.put("down", canMoveDown ? UIToolBarItem.STATE_ENABLED : 0);
-				}
 			}
 	
-	    boolean canRun = has1Selection && ((hasDM && !canRunFileInfo) || (!hasDM && canRunFileInfo));
-			if (canRun) {
-				ISelectedContent content = currentContent[0];
-				DownloadManager dm = content.getDownloadManager();
-	
-				if (dm == null) {
+			boolean canRemove = hasDM || canRemoveFileInfo;
+
+			mapNewToolbarStates.put("remove", canRemove ? UIToolBarItem.STATE_ENABLED
+					: 0);
+			
+			mapNewToolbarStates.put("download", canDownload ? UIToolBarItem.STATE_ENABLED
+					: 0);
+
+			// actually we roll the dm indexes when > 1 selected and we get
+			// to the top/bottom, so only enforce this for single selection :)
+
+			if (currentContent.length == 1) {
+				mapNewToolbarStates.put("up", canMoveUp ? UIToolBarItem.STATE_ENABLED
+						: 0);
+				mapNewToolbarStates.put("down", canMoveDown
+						? UIToolBarItem.STATE_ENABLED : 0);
+			}
+		}
+
+		boolean canRun = has1Selection
+				&& ((hasDM && !canRunFileInfo) || (!hasDM && canRunFileInfo));
+		if (canRun) {
+			ISelectedContent content = currentContent[0];
+			DownloadManager dm = content.getDownloadManager();
+
+			if (dm == null) {
+				canRun = false;
+			} else {
+				TOTorrent torrent = dm.getTorrent();
+
+				if (torrent == null) {
+
 					canRun = false;
-				} else {
-					TOTorrent torrent = dm.getTorrent();
-	
-					if (torrent == null) {
-	
-						canRun = false;
-	
-					} else if (!dm.getAssumedComplete() && torrent.isSimpleTorrent()) {
-	
-						canRun = false;
-	/*
-					} else if (PlatformTorrentUtils.useEMP(torrent)
-							&& PlatformTorrentUtils.embeddedPlayerAvail()
-							&& PlayUtils.canProgressiveOrIsComplete(torrent)) {
-						// play button enabled and not UMP.. don't need launch
-	
-						canRun = false;
-	
-					}
-					*/
-					}
+
+				} else if (!dm.getAssumedComplete() && torrent.isSimpleTorrent()) {
+
+					canRun = false;
+					/*
+									} else if (PlatformTorrentUtils.useEMP(torrent)
+											&& PlatformTorrentUtils.embeddedPlayerAvail()
+											&& PlayUtils.canProgressiveOrIsComplete(torrent)) {
+										// play button enabled and not UMP.. don't need launch
+					
+										canRun = false;
+					
+									}
+									*/
 				}
 			}
-			mapNewToolbarStates.put("run", canRun ? UIToolBarItem.STATE_ENABLED : 0);
-	
-			mapNewToolbarStates.put("start", canStart ? UIToolBarItem.STATE_ENABLED : 0);
-			mapNewToolbarStates.put("stop", canStop ? UIToolBarItem.STATE_ENABLED : 0);
-	
-			for (int i = 0; i < itemsNeedingRealDMSelection.length; i++) {
-				String itemID = itemsNeedingRealDMSelection[i];
-				if (!mapNewToolbarStates.containsKey(itemID)) {
-	  			mapNewToolbarStates.put(itemID, hasSelection && hasDM
-	  					&& hasRealDM ? UIToolBarItem.STATE_ENABLED : 0);
-				}
+		}
+		mapNewToolbarStates.put("run", canRun ? UIToolBarItem.STATE_ENABLED : 0);
+
+		mapNewToolbarStates.put("start", canStart ? UIToolBarItem.STATE_ENABLED : 0);
+		mapNewToolbarStates.put("stop", canStop ? UIToolBarItem.STATE_ENABLED : 0);
+		mapNewToolbarStates.put("startstop",
+				canStart || canStop ? UIToolBarItem.STATE_ENABLED : 0);
+
+		for (int i = 0; i < itemsNeedingRealDMSelection.length; i++) {
+			String itemID = itemsNeedingRealDMSelection[i];
+			if (!mapNewToolbarStates.containsKey(itemID)) {
+				mapNewToolbarStates.put(itemID, hasSelection && hasDM && hasRealDM
+						? UIToolBarItem.STATE_ENABLED : 0);
 			}
-			for (int i = 0; i < itemsRequiring1DMSelection.length; i++) {
-				String itemID = itemsRequiring1DMSelection[i];
-				if (!mapNewToolbarStates.containsKey(itemID)) {
-					mapNewToolbarStates.put(itemID, has1Selection && hasDM ? UIToolBarItem.STATE_ENABLED : 0);
-				}
+		}
+		for (int i = 0; i < itemsRequiring1DMSelection.length; i++) {
+			String itemID = itemsRequiring1DMSelection[i];
+			if (!mapNewToolbarStates.containsKey(itemID)) {
+				mapNewToolbarStates.put(itemID, has1Selection && hasDM
+						? UIToolBarItem.STATE_ENABLED : 0);
 			}
-	
-			for (int i = 0; i < itemsRequiring1DMwithHash.length; i++) {
-				String itemID = itemsRequiring1DMwithHash[i];
-				if (!mapNewToolbarStates.containsKey(itemID)) {
-					mapNewToolbarStates.put(itemID, hasDM ? UIToolBarItem.STATE_ENABLED : 0);
-				}
+		}
+
+		for (int i = 0; i < itemsRequiring1DMwithHash.length; i++) {
+			String itemID = itemsRequiring1DMwithHash[i];
+			if (!mapNewToolbarStates.containsKey(itemID)) {
+				mapNewToolbarStates.put(itemID, hasDM ? UIToolBarItem.STATE_ENABLED : 0);
 			}
-	
+		}
+
 		mapNewToolbarStates.put(
 				"download",
 				has1Selection
@@ -2449,11 +2774,12 @@ public class TorrentUtil {
 				mapNewToolbarStates.put("down", 0L);
 			}
 		}
-			
+
 		return mapNewToolbarStates;
 	}
 
-	public static void removeDownloads(DownloadManager[] dms, AERunnable deleteFailed) {
+	public static void removeDownloads(DownloadManager[] dms,
+			AERunnable deleteFailed) {
 		removeDownloads(dms, deleteFailed, false);
 	}
 
@@ -2471,6 +2797,18 @@ public class TorrentUtil {
 		// 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)
+		
+		boolean can_archive = false;
+		
+		for (int i = 0; i < dms.length; i++) {
+			DownloadManager dm = dms[i];
+			if (dm == null) {
+				continue;
+			}
+			if ( PluginCoreUtils.wrap( dm ).canStubbify()){
+				can_archive = true;
+			}
+		}
 		for (int i = 0; i < dms.length; i++) {
 			DownloadManager dm = dms[i];
 			if (dm == null) {
@@ -2489,8 +2827,12 @@ public class TorrentUtil {
 							dm.getDisplayName()
 						});
 
-				String[] buttons;
+				if ( can_archive ){
+					text += "\n\n" + MessageText.getString("v3.deleteContent.or.archive" );
+				}
 				
+				String[] buttons;
+
 				int defaultButtonPos;
 				buttons = new String[] {
 					MessageText.getString("Button.cancel"),
@@ -2578,4 +2920,130 @@ public class TorrentUtil {
 			}
 		}
 	}
+	
+	
+	public static void 
+	removeDownloadStubs(
+		final DownloadStubEx[] 	dms,
+		final AERunnable 		deleteFailed, 
+		final boolean 			forcePrompt) 
+	{
+		if ( dms == null ){
+			
+			return;
+		}
+
+		for ( int i = 0; i < dms.length; i++ ){
+			
+			DownloadStubEx dm = dms[i];
+
+			boolean deleteTorrent = COConfigurationManager.getBooleanParameter("def.deletetorrent");
+
+			int confirm = COConfigurationManager.getIntParameter("tb.confirm.delete.content");
+			boolean doPrompt = confirm == 0 | forcePrompt;
+
+			if (doPrompt) {
+				String title = MessageText.getString("deletedata.title");
+				String text = MessageText.getString("v3.deleteContent.message",
+						new String[] {
+							dm.getName()
+						});
+
+				String[] buttons;
+
+				int defaultButtonPos;
+				buttons = new String[] {
+					MessageText.getString("Button.cancel"),
+					MessageText.getString("Button.deleteContent.fromComputer"),
+					MessageText.getString("Button.deleteContent.fromLibrary"),
+				};
+				/*
+				int[] buttonVals = new int[] {
+					SWT.CANCEL,
+					1,
+					2
+				};
+				*/
+				defaultButtonPos = 2;
+
+				final MessageBoxShell mb = new MessageBoxShell(title, text, buttons,
+						defaultButtonPos);
+				int numLeft = (dms.length - i);
+				if (numLeft > 1) {
+					mb.setRemember("na", false, MessageText.getString(
+							"v3.deleteContent.applyToAll", new String[] {
+								"" + numLeft
+							}));
+					// never store remember state
+					mb.setRememberOnlyIfButton(-3);
+				}
+				mb.setRelatedObject(dm);
+				mb.setLeftImage("image.trash");
+				mb.addCheckBox("deletecontent.also.deletetorrent", 2, deleteTorrent);
+
+				final int index = i;
+
+				mb.open(new UserPrompterResultListener() {
+
+					public void prompterClosed(int result) {
+						ImageLoader.getInstance().releaseImage("image.trash");
+
+						removeDownloadStubsPrompterClosed(dms, index, deleteFailed, result,
+								mb.isRemembered(), mb.getCheckBoxEnabled());
+					}
+				});
+				return;
+			} else {
+				boolean deleteData = confirm == 1;
+				removeDownloadStubsPrompterClosed(dms, i, deleteFailed, deleteData ? 1 : 2,
+						true, deleteTorrent);
+			}
+		}
+	}
+	
+	private static void removeDownloadStubsPrompterClosed(DownloadStubEx[] dms,
+			int index, AERunnable deleteFailed, int result, boolean doAll,
+			boolean deleteTorrent) {
+		if (result == -1) {
+			// user pressed ESC (as opposed to clicked Cancel), cancel whole
+			// list
+			return;
+		}
+		if (doAll) {
+			if (result == 1 || result == 2) {
+
+				for (int i = index; i < dms.length; i++) {
+					DownloadStubEx dm = dms[i];
+					boolean deleteData = result == 2 ? false
+							: !false; // dm.getDownloadState().getFlag(Download.FLAG_DO_NOT_DELETE_DATA_ON_REMOVE);
+					//ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED,	deleteTorrent, deleteData, deleteFailed);
+					try{
+						dm.remove(deleteTorrent, deleteData);
+					}catch( Throwable e ){
+						if ( deleteFailed != null ){
+							deleteFailed.runSupport();
+						}
+					}
+				}
+			} //else cancel
+		} else { // not remembered
+			if (result == 1 || result == 2) {
+				DownloadStubEx dm = dms[index];
+				boolean deleteData = result == 2 ? false
+						: !false; // dm.getDownloadState().getFlag(Download.FLAG_DO_NOT_DELETE_DATA_ON_REMOVE);
+				//ManagerUtils.asyncStopDelete(dm, DownloadManager.STATE_STOPPED,	deleteTorrent, deleteData, null);
+				try{
+					dm.remove(deleteTorrent, deleteData);
+					
+				}catch( Throwable e ){
+					// no delete failed logic here apparently...
+				}
+			}
+			// remove the one we just did and go through loop again
+			dms[index] = null;
+			if (index != dms.length - 1) {
+				removeDownloadStubs(dms, deleteFailed, true);
+			}
+		}
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/TrackerChangerWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/TrackerChangerWindow.java
index 1fdf6fd..d16c6aa 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/TrackerChangerWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/TrackerChangerWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on 9 sept. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/TrayWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/TrayWindow.java
index 17c8322..caa0aa2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/TrayWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/TrayWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on 8 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
@@ -254,7 +251,7 @@ public class TrayWindow
 		DownloadManagerStats	stats = manager.getStats();
 		
         String name = manager.getDisplayName();
-        String completed = DisplayFormatters.formatPercentFromThousands(stats.getCompleted());
+        String completed = DisplayFormatters.formatPercentFromThousands(stats.getPercentDoneExcludingDND());
         toolTip.append(separator);
         toolTip.append(name);
         toolTip.append(" -- C: ");
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java
index 76f27be..11183cf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/UIConfigDefaultsSWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt;
@@ -52,6 +49,7 @@ public class UIConfigDefaultsSWT
 		def.addParameter("IconBar.enabled", true);
 
 		def.addParameter("DefaultDir.BestGuess", true);
+		def.addParameter("DefaultDir.BestGuess.Default", "");
 		def.addParameter("DefaultDir.AutoUpdate", true);
 		def.addParameter("DefaultDir.AutoSave.AutoRename", true);
 		def.addParameter("GUI_SWT_bFancyTab", true);
@@ -139,16 +137,27 @@ public class UIConfigDefaultsSWT
 
 			def.addParameter("list.dm.dblclick", "1");
 			def.addParameter(MultipleDocumentInterface.SIDEBAR_SECTION_LIBRARY + ".viewmode", 1);
-  		def.addParameter(MultipleDocumentInterface.SIDEBAR_SECTION_LIBRARY_DL + "DL.viewmode", 1);
-  		def.addParameter(MultipleDocumentInterface.SIDEBAR_SECTION_LIBRARY_CD + ".viewmode", 1);
+			def.addParameter(MultipleDocumentInterface.SIDEBAR_SECTION_LIBRARY_DL + "DL.viewmode", 1);
+			def.addParameter(MultipleDocumentInterface.SIDEBAR_SECTION_LIBRARY_CD + ".viewmode", 1);
 		}
 		
 		
 		def.addParameter( "browser.external.id", "system" );
 		def.addParameter( "browser.external.search", false );
+		def.addParameter( "browser.internal.disable", false );
 		def.addParameter( "browser.internal.proxy.id", "none" );
 		
-		COConfigurationManager.setParameter( "Bar Transparency", 0 );
-
+		def.addParameter( "Bar Transparency", 0 );
+		
+		def.addParameter( "Low Resource Silent Update Restart Enabled", true );
+		
+		def.addParameter( "Library.ShowCatButtons", true );
+		def.addParameter( "Library.ShowTagButtons", false );
+		def.addParameter( "Library.ShowTagButtons.CompOnly", false );
+		def.addParameter( "open.torrent.window.rename.on.tlf.change", true );
+		
+		def.addParameter( "Library.LaunchWebsiteInBrowser", true );
+		def.addParameter( "Library.LaunchWebsiteInBrowserAnon", false );
+		def.addParameter( "Library.LaunchWebsiteInBrowserDirList", false );
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java
index fe52d27..a17d367 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/UIExitUtilsSWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/UISwitcherListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/UISwitcherListener.java
index 0aa1a8c..7873d50 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/UISwitcherListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/UISwitcherListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/UISwitcherUtil.java b/azureus2/src/org/gudy/azureus2/ui/swt/UISwitcherUtil.java
index d46f252..29d7263 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/UISwitcherUtil.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/UISwitcherUtil.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/URLTransfer.java b/azureus2/src/org/gudy/azureus2/ui/swt/URLTransfer.java
index 90ea5f0..1921082 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/URLTransfer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/URLTransfer.java
@@ -1,6 +1,6 @@
 /*
  * Created on 01.12.2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/UserAlerts.java b/azureus2/src/org/gudy/azureus2/ui/swt/UserAlerts.java
index 4a39b0f..800c0d7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/UserAlerts.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/UserAlerts.java
@@ -1,6 +1,6 @@
 /*
  * Created on 28.11.2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,17 +14,17 @@
  * 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 java.applet.Applet;
+import java.applet.AudioClip;
+import java.io.File;
+import java.net.URL;
+import java.util.Map;
+
 import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.disk.DiskManager;
-import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.core3.disk.DiskManagerListener;
-import org.gudy.azureus2.core3.disk.DiskManagerPiece;
+import org.gudy.azureus2.core3.disk.*;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerDiskListener;
 import org.gudy.azureus2.core3.download.DownloadManagerState;
@@ -32,24 +32,18 @@ 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.internat.MessageText;
-import org.gudy.azureus2.core3.logging.*;
+import org.gudy.azureus2.core3.logging.LogAlert;
+import org.gudy.azureus2.core3.logging.Logger;
 import org.gudy.azureus2.core3.util.*;
 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.minibar.DownloadBar;
 
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-
-import org.gudy.azureus2.plugins.platform.PlatformManagerException;
-
-import java.applet.Applet;
-import java.applet.AudioClip;
-import java.io.File;
-import java.net.URL;
-import java.util.Map;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 
 /**
  * Contains methods to alert the user of certain events.
@@ -95,8 +89,9 @@ UserAlerts
 
 							if ((!complete && COConfigurationManager.getBooleanParameter("Open Details"))
 									|| (complete && COConfigurationManager.getBooleanParameter("Open Seeding Details"))) {
-								UIFunctionsManagerSWT.getUIFunctionsSWT().openView(
-										UIFunctions.VIEW_DM_DETAILS, manager);
+								UIFunctionsManager.getUIFunctions().getMDI().loadEntryByID(
+										MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS,
+										false, false, manager);
 							}
 
 							if (((!complete) && COConfigurationManager.getBooleanParameter("Open Bar Incomplete"))
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/Utils.java b/azureus2/src/org/gudy/azureus2/ui/swt/Utils.java
index bda195c..5ff1e65 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/Utils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/Utils.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -21,17 +22,17 @@
 
 package org.gudy.azureus2.ui.swt;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
 import java.net.URL;
+import java.net.URLConnection;
 import java.util.*;
 import java.util.List;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.SWTException;
-import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.custom.SashForm;
 import org.eclipse.swt.dnd.*;
 import org.eclipse.swt.events.DisposeEvent;
 import org.eclipse.swt.events.DisposeListener;
@@ -46,11 +47,15 @@ import org.gudy.azureus2.core3.config.ParameterListener;
 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.core3.download.DownloadManager;
 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.platform.PlatformManager;
 import org.gudy.azureus2.platform.PlatformManagerCapabilities;
 import org.gudy.azureus2.platform.PlatformManagerFactory;
 import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.PluginManager;
 import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
 import org.gudy.azureus2.plugins.disk.DiskManagerListener;
 import org.gudy.azureus2.plugins.platform.PlatformManagerException;
@@ -60,12 +65,14 @@ 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.*;
-import org.gudy.azureus2.ui.swt.views.table.impl.TableOrTreeUtils;
 
 import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.util.GeneralUtils;
 import com.aelitis.azureus.core.util.LaunchManager;
+import com.aelitis.azureus.plugins.I2PHelpers;
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.UIFunctionsUserPrompter;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
@@ -485,10 +492,6 @@ public class Utils
 	}
 
 	public static void alternateRowBackground(TableItem item) {
-		alternateRowBackground(TableOrTreeUtils.getEventItem(item));
-	}
-
-	public static void alternateRowBackground(TableItemOrTreeItem item) {
 		if (Utils.TABLE_GRIDLINE_IS_ALTERNATING_COLOR) {
 			if (!item.getParent().getLinesVisible())
 				item.getParent().setLinesVisible(true);
@@ -524,8 +527,7 @@ public class Utils
 		if (iTopIndex < 0 || (iTopIndex == 0 && table.getItemCount() == 0)) {
 			return;
 		}
-		TableOrTreeSWT tt = TableOrTreeUtils.getTableOrTreeSWT(table);
-		int iBottomIndex = getTableBottomIndex(tt, iTopIndex);
+		int iBottomIndex = getTableBottomIndex(table, iTopIndex);
 
 		Color[] colors = {
 			table.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND),
@@ -533,7 +535,7 @@ public class Utils
 		};
 		int iFixedIndex = iTopIndex;
 		for (int i = iTopIndex; i <= iBottomIndex; i++) {
-			TableItemOrTreeItem row = tt.getItem(i);
+			TableItem row = table.getItem(i);
 			// Rows can be disposed!
 			if (!row.isDisposed()) {
 				Color newColor = colors[iFixedIndex % colors.length];
@@ -555,7 +557,21 @@ public class Utils
 	 * @param repoKey ImageRepository image key
 	 * @see <a href="http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGMenus/chapter_7_section_3.html#//apple_ref/doc/uid/TP30000356/TPXREF116">Apple HIG</a>
 	 */
-	public static void setMenuItemImage(final MenuItem item, final String repoKey) {
+  	public static void setMenuItemImage(final MenuItem item, final String repoKey) {
+  		if (Constants.isOSX || repoKey == null) {
+  			return;
+  		}
+  		ImageLoader imageLoader = ImageLoader.getInstance();
+  		item.setImage(imageLoader.getImage(repoKey));
+  		item.addDisposeListener(new DisposeListener() {
+  			public void widgetDisposed(DisposeEvent e) {
+  				ImageLoader imageLoader = ImageLoader.getInstance();
+  				imageLoader.releaseImage(repoKey);
+  			}
+  		});
+  	}
+
+	public static void setMenuItemImage(CLabel item, final String repoKey) {
 		if (Constants.isOSX || repoKey == null) {
 			return;
 		}
@@ -884,8 +900,10 @@ public class Utils
 
 	/**
 	 * Bottom Index may be negative. Returns bottom index even if invisible.
+	 * <p>
+	 * Used by rssfeed
 	 */
-	public static int getTableBottomIndex(TableOrTreeSWT table, int iTopIndex) {
+	public static int getTableBottomIndex(Table table, int iTopIndex) {
 
 		// Shortcut: if lastBottomIndex is present, assume it's accurate
 		Object lastBottomIndex = table.getData("lastBottomIndex");
@@ -903,79 +921,14 @@ public class Utils
 		}
 
 		Rectangle clientArea = table.getClientArea();
-		TableItemOrTreeItem bottomItem = table.getItem(new Point(xPos,
+		TableItem bottomItem = table.getItem(new Point(xPos,
 				clientArea.y + clientArea.height - 2));
 		if (bottomItem != null) {
-			while (bottomItem.getParentItem() != null) {
-				bottomItem = bottomItem.getParentItem();
-			}
 			return table.indexOf(bottomItem);
 		}
 		return table.getItemCount() - 1;
 	}
 	
-	public static List<TableItemOrTreeItem> getVisibleTableItems(TableOrTreeSWT table) {
-
-		if (table.getColumnCount() < 2) {
-			return Collections.emptyList();
-		}
-
-		int xPos = table.getColumn(0).getWidth() + table.getColumn(1).getWidth() - 1;
-
-		Rectangle clientArea = table.getClientArea();
-		TableItemOrTreeItem bottomItem = table.getItem(new Point(xPos,
-				clientArea.y + clientArea.height - 1));
-		if (bottomItem == null) {
-			if (clientArea.height + clientArea.y <= 0) {
-				return Collections.emptyList();
-			}
-		}
-
-		TableItemOrTreeItem curItem = table.getTopItem();
-		if (curItem == null) {
-			if (table.getItemCount() > 0) {
-				// BUG in GTK: topitem of tree will be null after setItemCount
-				curItem = table.getItem(0);
-			} else {
-				return Collections.emptyList();
-			}
-		}
-		List<TableItemOrTreeItem> items = new ArrayList<TableItemOrTreeItem>();
-		int i = table.indexOf(curItem);
-		int count = table.getItemCount();
-		while (true) {
-			if (curItem == bottomItem) {
-				items.add(curItem);
-				break;
-			} else if (curItem == null) {
-				break;
-			}
-			items.add(curItem);
-			if (curItem.getExpanded() && curItem.getItemCount() > 0) {
-				if (!addItemsToList(items, curItem.getItems(), bottomItem)) {
-					break;
-				}
-			}
-			i++;
-			if (i >= count) {
-				break;
-			}
-			curItem = table.getItem(i);
-		}
-		return items;
-	}
-
-	private static boolean addItemsToList(List<TableItemOrTreeItem> list, TableItemOrTreeItem[] items,
-			TableItemOrTreeItem stopOnItem) {
-		
-		for (TableItemOrTreeItem item : items) {
-			list.add(item);
-			if (item == stopOnItem) {
-				return false;
-			}
-		}
-		return true;
-	}
 
 	public static void launch( final DiskManagerFileInfo fileInfo ){
 		LaunchManager	launch_manager = LaunchManager.getManager();
@@ -1021,71 +974,126 @@ public class Utils
 		launch( sFile, false );
 	}
 	
-	private static Set<String>		pending_ext_urls 	= new HashSet<String>();
-	private static AsyncDispatcher	ext_url_dispatcher 	= new AsyncDispatcher( "Ext Urls" );
+	private static Set<String>		pending_ext_urls 		= new HashSet<String>();
+	private static AsyncDispatcher	ext_url_dispatcher 		= new AsyncDispatcher( "Ext Urls" );
+	
+	private static boolean			i2p_install_active_for_url		= false;
+	private static boolean			browser_install_active_for_url	= false;
+	
+	public static void 
+	launch(
+		String 		sFileOriginal,
+		boolean		sync )
+	{
+		launch( sFileOriginal, sync, false );
+	}
+	
+	public static void 
+	launch(
+		String 		sFileOriginal,
+		boolean		sync,
+		boolean		force_url )
+	{
+		launch( sFileOriginal, sync, force_url, false );
+	}
 	
 	public static void 
 	launch(
-		String 	sFile,
-		boolean	sync )
+		String 		sFileOriginal,
+		boolean		sync,
+		boolean		force_url,
+		boolean		force_anon )
 	{
-		if (sFile == null || sFile.trim().length() == 0) {
+		String sFileModified = sFileOriginal;
+		
+		if (sFileModified == null || sFileModified.trim().length() == 0) {
 			return;
 		}
 		
-		if (!Constants.isWindows && new File(sFile).isDirectory()) {
-			PlatformManager mgr = PlatformManagerFactory.getPlatformManager();
-			if (mgr.hasCapability(PlatformManagerCapabilities.ShowFileInBrowser)) {
-				try {
-					PlatformManagerFactory.getPlatformManager().showFile(sFile);
-					return;
-				} catch (PlatformManagerException e) {
+		if ( !force_url ){
+			if (!Constants.isWindows && new File(sFileModified).isDirectory()) {
+				PlatformManager mgr = PlatformManagerFactory.getPlatformManager();
+				if (mgr.hasCapability(PlatformManagerCapabilities.ShowFileInBrowser)) {
+					try {
+						PlatformManagerFactory.getPlatformManager().showFile(sFileModified);
+						return;
+					} catch (PlatformManagerException e) {
+					}
 				}
 			}
-		}
-
-		sFile = sFile.replaceAll( "&vzemb=1", "" );
-
-		String exe = getExplicitLauncher( sFile );
-		
-		if ( exe != null ){
+	
+			sFileModified = sFileModified.replaceAll( "&vzemb=1", "" );
+	
+			String exe = getExplicitLauncher( sFileModified );
 			
-			File	file = new File( sFile );
-										
-			try{
-				System.out.println( "Launching " + sFile + " with " + exe );
+			if ( exe != null ){
 				
-				if ( Constants.isWindows ){
-					
-						// need to use createProcess as we want to force the process to decouple correctly (otherwise Vuze won't close until the child closes)
-					
-					try{
-						PlatformManagerFactory.getPlatformManager().createProcess( exe + " \"" + sFile + "\"", false );
+				File	file = new File( sFileModified );
+											
+				try{
+					System.out.println( "Launching " + sFileModified + " with " + exe );
 					
-						return;
+					if ( Constants.isWindows ){
 						
-					}catch( Throwable e ){
+							// need to use createProcess as we want to force the process to decouple correctly (otherwise Vuze won't close until the child closes)
+						
+						try{
+							PlatformManagerFactory.getPlatformManager().createProcess( exe + " \"" + sFileModified + "\"", false );
+						
+							return;
+							
+						}catch( Throwable e ){
+						}
 					}
+					
+					ProcessBuilder pb = GeneralUtils.createProcessBuilder( file.getParentFile(), new String[]{ exe, file.getName()}, null );
+					
+					pb.start();
+					
+					return;
+					
+				}catch( Throwable e ){
+					
+					Debug.out( "Launch failed", e );
 				}
-				
-				ProcessBuilder pb = GeneralUtils.createProcessBuilder( file.getParentFile(), new String[]{ exe, file.getName()}, null );
-				
-				pb.start();
-				
-				return;
-				
-			}catch( Throwable e ){
-				
-				Debug.out( "Launch failed", e );
 			}
 		}
-			
-		String lc_sFile = sFile.toLowerCase( Locale.US );
+		
+		String lc_sFile = sFileModified.toLowerCase( Locale.US );
 		
 		if ( lc_sFile.startsWith( "http:" ) || lc_sFile.startsWith( "https:" )){
+
+			String 		net_type;
+			String 		eb_choice;
+			boolean		use_plugins;
 			
-			String eb_choice = COConfigurationManager.getStringParameter( "browser.external.id", "system" );
+			if ( force_anon ){
+				
+				net_type 		= AENetworkClassifier.AT_TOR;
+				eb_choice 		= "plugin";
+				use_plugins		= true;
+				
+			}else{
+				
+				net_type = AENetworkClassifier.AT_PUBLIC;
+						
+				try{
+					net_type = AENetworkClassifier.categoriseAddress( new URL( sFileModified ).getHost());
+					
+				}catch( Throwable e ){
+					
+				}
+			
+				eb_choice = COConfigurationManager.getStringParameter( "browser.external.id", "system" );
+
+				use_plugins = COConfigurationManager.getBooleanParameter( "browser.external.non.pub", true );
 
+				if ( net_type != AENetworkClassifier.AT_PUBLIC && use_plugins ){
+					
+					eb_choice = "plugin";	// hack to force to that code leg
+				}
+			}
+			
 			if ( eb_choice.equals( "system" )){
 				
 			}else if ( eb_choice.equals( "manual" )){
@@ -1097,7 +1105,7 @@ public class Utils
 				if ( bf.exists()){
 					
 					try{
-						Process proc = Runtime.getRuntime().exec( new String[]{ bf.getAbsolutePath(), sFile });
+						Process proc = Runtime.getRuntime().exec( new String[]{ bf.getAbsolutePath(), sFileModified });
 						
 					}catch( Throwable e ){
 						
@@ -1105,118 +1113,418 @@ public class Utils
 					}
 				}else{
 					
-					Debug.out( "Can't launch '" + sFile + "' as manual browser '" + bf + " ' doesn't exist" );
+					Debug.out( "Can't launch '" + sFileModified + "' as manual browser '" + bf + " ' doesn't exist" );
 				}
 				
 				return;
 				
 			}else{
 				
-				java.util.List<PluginInterface> pis = 
-						AzureusCoreFactory.getSingleton().getPluginManager().getPluginsWithMethod(
-							"launchURL", 
-							new Class[]{ URL.class, boolean.class, Runnable.class });
+				handlePluginLaunch( eb_choice, net_type, use_plugins, sFileOriginal, sFileModified, sync, force_url, force_anon );
+				
+				return;
+			}
+		}else if ( lc_sFile.startsWith( "chat:" )){
+							
+			String plug_uri = "azplug:?id=azbuddy&arg=" + UrlUtils.encode( sFileModified );
+			
+			try{
+				URLConnection connection = new URL( plug_uri ).openConnection();
+				
+				connection.connect();
+				
+				String res = FileUtil.readInputStreamAsString( connection.getInputStream(), 2048 );
+								
+				return;
+				
+			}catch( Throwable e ){	
+			}
+		}
+		
+		boolean launched = Program.launch(sFileModified);
+		
+		if (!launched && Constants.isUnix) {
+			
+			sFileModified = sFileModified.replaceAll( " ", "\\ " );
+			
+			if (!Program.launch("xdg-open " + sFileModified)) {
+				
+				if ( !Program.launch("htmlview " + sFileModified)){
+					
+					Debug.out( "Failed to launch '" + sFileModified + "'" );
+				}
+			}
+		}
+	}
+
+	private static void
+	handlePluginLaunch(
+		String				eb_choice,
+		String				net_type,
+		boolean				use_plugins,
+		final String		sFileOriginal,
+		final String		sFileModified,
+		final boolean		sync,
+		final boolean		force_url,
+		final boolean		force_anon )
+	{
+		PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager();
+		
+		if ( net_type == AENetworkClassifier.AT_I2P ){
+			
+			if ( pm.getPluginInterfaceByID( "azneti2phelper" ) == null ){
 				
-				boolean found = false;
+				boolean	try_it;
 				
-				for ( final PluginInterface pi: pis ){
+				synchronized( pending_ext_urls ){
+
+					try_it = !i2p_install_active_for_url;
 					
-					String id = "plugin:" + pi.getPluginID();
+					i2p_install_active_for_url = true;
+				}
+				
+				if ( try_it ){
 					
-					if ( id.equals( eb_choice )){
-						
-						found = true;
+					ext_url_dispatcher.dispatch(
+						new AERunnable()
+						{	
+							public void 
+							runSupport() 
+							{
+								boolean installing = false;
+								
+								try{
+									final boolean[]	install_outcome = { false };
+									
+									installing = 
+											I2PHelpers.installI2PHelper( 
+											"azneti2phelper.install",
+											install_outcome,
+											new Runnable()
+											{
+												public void
+												run()
+												{
+													try{
+														if ( install_outcome[0] ){
+										
+															Utils.launch( sFileOriginal, sync, force_url, force_anon );
+														}
+													}finally{
+														
+														synchronized( pending_ext_urls ){
+															
+															i2p_install_active_for_url = false;
+														}
+													}
+												}
+											});
+	
+								}finally{
+									
+									if ( !installing ){
+										
+										synchronized( pending_ext_urls ){
+											
+											i2p_install_active_for_url = false;
+										}
+									
+									}
+								}
+							}
+						});
+				}else{
+					
+					Debug.out( "I2P installation already active" );
+				}
+				
+				return;
+			}
+		}
+		
+		java.util.List<PluginInterface> pis = 
+				pm.getPluginsWithMethod(
+					"launchURL", 
+					new Class[]{ URL.class, boolean.class, Runnable.class });
+		
+		boolean found = false;
+		
+		for ( final PluginInterface pi: pis ){
+			
+			String id = "plugin:" + pi.getPluginID();
+			
+			if ( eb_choice.equals( "plugin" ) || id.equals( eb_choice )){
+				
+				found = true;
+								
+				synchronized( pending_ext_urls ){
+					
+					if ( pending_ext_urls.contains( sFileModified )){
 						
-						final String f_sFile = sFile;
+						Debug.outNoStack( "Already queued browser request for '" + sFileModified + "' - ignoring" );
 						
-						synchronized( pending_ext_urls ){
-							
-							if ( pending_ext_urls.contains( f_sFile )){
+						return;
+					}
+					
+					pending_ext_urls.add( sFileModified );
+				}
+				
+				AERunnable launch = 
+					new AERunnable()
+					{
+						public void 
+						runSupport() 
+						{
+							try{
+								final AESemaphore sem = new AESemaphore( "wait" );
+
+								pi.getIPC().invoke( 
+									"launchURL", 
+									new Object[]{ 
+										new URL( sFileModified ), 
+										false, 
+										new Runnable()
+										{
+											public void
+											run()
+											{
+												sem.release();
+											}
+										}});
+								
+								if ( !sem.reserve( 30*1000 )){
+									
+									// can happen when user is prompted to accept the launch or not and is
+									// slow in replying
+									// Debug.out( "Timeout waiting for external url launch" );
+								}
+								
+							}catch( Throwable e ){
 								
-								Debug.outNoStack( "Already queued browser request for '" + f_sFile + "' - ignoring" );
+								Debug.out( e );
 								
-								return;
+							}finally{
+																		
+								synchronized( pending_ext_urls ){
+									
+									pending_ext_urls.remove( sFileModified );
+								}
 							}
-							
-							pending_ext_urls.add( f_sFile );
 						}
+					};
+												
+				if ( sync ){
+						
+					launch.runSupport();
 						
-						AERunnable launch = 
-							new AERunnable()
+				}else{
+						
+					ext_url_dispatcher.dispatch( launch );
+				}
+			}
+		}
+		
+		if ( !found ){
+			
+			if ( net_type != AENetworkClassifier.AT_PUBLIC && use_plugins ){
+				
+				boolean	try_it;
+				
+				synchronized( pending_ext_urls ){
+
+					try_it = !browser_install_active_for_url;
+					
+					browser_install_active_for_url = true;
+				}
+				
+				if ( try_it ){
+					
+					ext_url_dispatcher.dispatch(
+						new AERunnable()
+						{	
+							public void 
+							runSupport() 
 							{
-								public void 
-								runSupport() 
-								{
-									try{
-										final AESemaphore sem = new AESemaphore( "wait" );
-	
-										pi.getIPC().invoke( 
-											"launchURL", 
-											new Object[]{ 
-												new URL( f_sFile ), 
-												false, 
-												new Runnable()
+								boolean installing = false;
+								
+								try{
+									final boolean[]	install_outcome = { false };
+									
+									installing = 
+										installTorBrowser( 
+											"aznettorbrowser.install",
+											install_outcome,
+											new Runnable()
+											{
+												public void
+												run()
 												{
-													public void
-													run()
-													{
-														sem.release();
+													try{
+														if ( install_outcome[0] ){
+																
+															Utils.launch( sFileOriginal, sync, force_url, force_anon );
+														}
+													}finally{
+														
+														synchronized( pending_ext_urls ){
+															
+															browser_install_active_for_url = false;
+														}
 													}
-												}});
-										
-										if ( !sem.reserve( 30*1000 )){
-											
-											Debug.out( "Timeout waiting for external url launch" );
-										}
-										
-									}catch( Throwable e ){
-										
-										Debug.out( e );
+												}
+											});
+									
+								}catch( Throwable e ){
+								
+									Debug.out( e );
+									
+								}finally{
+									
+									if ( !installing ){
 										
-									}finally{
-																				
 										synchronized( pending_ext_urls ){
 											
-											pending_ext_urls.remove( f_sFile );
+											browser_install_active_for_url = false;
 										}
 									}
 								}
-							};
-														
-						if ( sync ){
-								
-							launch.runSupport();
-								
-						}else{
-								
-							ext_url_dispatcher.dispatch( launch );
-						}
-					}
-				}
-				
-				if ( !found ){
+							}
+						});
+				}else{
 					
-					Debug.out( "Failed to find external URL launcher plugin with id '" + eb_choice + "'" );
+					Debug.out( "Browser installation already active" );
 				}
 				
 				return;
 			}
 		}
 		
-		boolean launched = Program.launch(sFile);
-		if (!launched && Constants.isUnix) {
+		if ( !eb_choice.equals( "plugin" )){
+				
+			Debug.out( "Failed to find external URL launcher plugin with id '" + eb_choice + "'" );
+		}
+		
+		return;
+	}
+	
+
+	
+	private static boolean tb_installing = false;
+	
+	public static boolean
+	isInstallingTorBrowser()
+	{
+		synchronized( pending_ext_urls ){
+			
+			return( tb_installing );
+		}
+	}
+	
+	private static boolean
+	installTorBrowser(
+		String				remember_id,
+		final boolean[]		install_outcome,
+		final Runnable		callback )
+	{
+		synchronized( pending_ext_urls ){
+			
+			if ( tb_installing ){
+				
+				Debug.out( "Tor Browser already installing" );
+				
+				return( false );
+			}
+			
+			tb_installing = true;
+		}
+		
+		boolean	installing = false;
+		
+		try{
+			UIFunctions uif = UIFunctionsManager.getUIFunctions();
+			
+			if ( uif == null ){
+				
+				Debug.out( "UIFunctions unavailable - can't install plugin" );
+				
+				return( false );
+			}
+			
+			String title = MessageText.getString("aznettorbrowser.install");
+			
+			String text = MessageText.getString("aznettorbrowser.install.text" );
+			
+			UIFunctionsUserPrompter prompter = uif.getUserPrompter(title, text, new String[] {
+				MessageText.getString("Button.yes"),
+				MessageText.getString("Button.no")
+			}, 0);
+			
+			if ( remember_id != null ){
+				
+				prompter.setRemember( 
+					remember_id, 
+					false,
+					MessageText.getString("MessageBoxWindow.nomoreprompting"));
+			}
 			
-			sFile = sFile.replaceAll( " ", "\\ " );
+			prompter.setAutoCloseInMS(0);
 			
-			if (!Program.launch("xdg-open " + sFile)) {
-				if ( !Program.launch("htmlview " + sFile)){
+			prompter.open(null);
+			
+			boolean	install = prompter.waitUntilClosed() == 0;
+			
+			if ( install ){
+								
+				uif.installPlugin(
+					"aznettorbrowser",
+					"aznettorbrowser.install",
+					new UIFunctions.actionListener()
+					{
+						public void
+						actionComplete(
+							Object		result )
+						{
+							try{
+								if ( callback != null ){
+									
+									if ( result instanceof Boolean ){
+										
+										install_outcome[0] = (Boolean)result;
+									}
+									
+									callback.run();
+								}
+							}finally{
+																	
+								synchronized( pending_ext_urls ){
+										
+									tb_installing = false;
+								}
+							}
+						}
+					});
+				
+				installing = true;
+				
+			}else{
+				
+				Debug.out( "Tor Browser install declined (either user reply or auto-remembered)" );
+			}
+			
+			return( install );
+			
+		}finally{
+			
+			if ( !installing ){
+			
+				synchronized( pending_ext_urls ){
 					
-					Debug.out( "Failed to launch '" + sFile + "'" );
+					tb_installing = false;
 				}
 			}
 		}
 	}
-
+	
 	private static String
 	getExplicitLauncher(
 		String	file )
@@ -1589,7 +1897,19 @@ public class Utils
 	 * @param control Control that had it's sized changed and needs more room
 	 */
 	public static void relayout(Control control) {
+		long startOn = DEBUG_SWTEXEC ? System.currentTimeMillis() : 0;
 		relayout(control, false);
+		if (DEBUG_SWTEXEC) {
+			long diff = System.currentTimeMillis() - startOn;
+			if (diff > 100) {
+				String s = "Long relayout of " + diff + "ms "
+						+ Debug.getCompressedStackTrace();
+				if (diag_logger != null) {
+					diag_logger.log(s);
+				}
+				System.out.println(s);
+			}
+		}
 	}
 
 	/**
@@ -1602,6 +1922,16 @@ public class Utils
 		if (control == null || control.isDisposed() || !control.isVisible()) {
 			return;
 		}
+		
+		if (control instanceof ScrolledComposite) {
+			ScrolledComposite sc = (ScrolledComposite) control;
+			Control content = sc.getContent();
+			if (content != null && !content.isDisposed()) {
+				Rectangle r = sc.getClientArea();
+				sc.setMinSize(content.computeSize(r.width, SWT.DEFAULT ));
+			}
+		}
+
 
 		Composite parent = control.getParent();
 		Point targetSize = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
@@ -1627,19 +1957,31 @@ public class Utils
 			parent.layout();
 			return;
 		}
+		//System.out.println("size=" + size + ";target=" + targetSize);
 
+		Control previous = control;
 		while (parent != null) {
-			parent.layout(true, true);
-			parent = parent.getParent();
+			parent.layout(new Control[] { previous }, SWT.ALL | SWT.DEFER);
+			if (parent instanceof ScrolledComposite) {
+				ScrolledComposite sc = (ScrolledComposite) parent;
+				Control content = sc.getContent();
+				if (content != null && !content.isDisposed()) {
+  				Rectangle r = sc.getClientArea();
+  				sc.setMinSize(content.computeSize(r.width, SWT.DEFAULT ));
+				}
+			}
 
 			Point newSize = control.getSize();
 
-			//System.out.println("new=" + newSize + ";target=" + targetSize);
+			//System.out.println("new=" + newSize + ";target=" + targetSize + ";" + control.isVisible());
 
 			if ((fixedHeight > -1 || (newSize.y >= targetSize.y))
 					&& (fixedWidth > -1 || (newSize.x >= targetSize.x))) {
 				break;
 			}
+
+			previous = parent;
+			parent = parent.getParent();
 		}
 
 		if (parent != null) {
@@ -1665,7 +2007,7 @@ public class Utils
 	 * @deprecated Use {@link #execSWTThread(AERunnableWithCallback)} to avoid
 	 *             thread locking issues
 	 */
-	public static boolean execSWTThreadWithBool(String ID, AERunnableBoolean code) {
+	public static Boolean execSWTThreadWithBool(String ID, AERunnableBoolean code) {
 		return execSWTThreadWithBool(ID, code, 0);
 	}
 
@@ -1687,16 +2029,19 @@ public class Utils
 	 * @param ID id for debug
 	 * @param code code to run
 	 * @param millis ms to timeout in
-	 * @return
+	 * 
+	 * @return returns NULL if code never run
 	 */
-	public static boolean execSWTThreadWithBool(String ID,
+	public static Boolean execSWTThreadWithBool(String ID,
 			AERunnableBoolean code, long millis) {
 		if (code == null) {
-			return false;
+			Logger.log(new LogEvent(LogIDs.CORE, "code null"));
+			
+			return null;
 		}
 
-		boolean[] returnValueObject = {
-			false
+		Boolean[] returnValueObject = {
+			null
 		};
 
 		Display display = getDisplay();
@@ -1712,7 +2057,7 @@ public class Utils
 			if (!execSWTThread(code)) {
 				// code never got run
 				// XXX: throw instead?
-				return false;
+				return null;
 			}
 		} catch (Throwable e) {
 			if (sem != null) {
@@ -2387,17 +2732,61 @@ public class Utils
 		tp.run(runnable);
 	}
 	
-	public static Browser createSafeBrowser(Composite parent, int style) {
+	public static BrowserWrapper 
+	createSafeBrowser(
+		Composite parent, int style) 
+	{
 		try {
-  		Browser browser = new Browser(parent, Utils.getInitialBrowserStyle(style));
+		final BrowserWrapper browser = BrowserWrapper.createBrowser(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());
+  			public void widgetDisposed(DisposeEvent e)
+  			{
+  					/*
+  					 * Intent here seems to be to run all pending events through the queue to ensure
+  					 * that the 'setUrl' and 'setVisible' actions are complete before disposal in an
+  					 * attempt to ensure memory released. This is old code and the new 4508 SWT introduced
+  					 * in Dec 2014 causes the 'readAndDispatch' loop to bever exit.
+  					 * So added code to queue an async event and hope that by the time this runs
+  					 * any housekeeping is complete
+  					 * Meh, tested and the injected code doesn't run until, say, you move the window containing
+  					 * the browser. So added timeout
+  					 */
+  				
+  				browser.setUrl("about:blank");
+  				
+  				browser.setVisible(false);
+  				
+  				final boolean[]	done = {false};
+  				
+  				final long start = SystemTime.getMonotonousTime();
+  				
+  				execSWTThreadLater(
+  					250,
+  					new Runnable()
+  					{
+  						public void 
+  						run() 
+  						{
+  							synchronized( done ){
+  								
+  								done[0] = true;
+  							}
+  						}
+  					});
+  				
+  				while(!e.display.isDisposed() && e.display.readAndDispatch()){
+  					
+  					synchronized( done ){
+  						
+  						if ( done[0] || SystemTime.getMonotonousTime() - start > 500 ){
+  						
+  							break;
+  						}
+  					}
+  				}
   			}
   		});
-  		return browser;
+  		return browser ;
 		} catch (Throwable e) {
 		}
 		return null;
@@ -2979,4 +3368,184 @@ public class Utils
 			}
 		}
 	}
+	
+	public static Sash
+	createSash(
+		Composite	form,
+		int			SASH_WIDTH )
+	{
+	    final Sash sash = new Sash(form, SWT.HORIZONTAL);
+	    Image image = new Image(sash.getDisplay(), 9, SASH_WIDTH);
+	    ImageData imageData = image.getImageData();
+	    int[] row = new int[imageData.width];
+	    for (int i = 0; i < row.length; i++) {
+	    	if (imageData.depth == 16) {
+	    		row[i] = (i % 3) != 0 ? 0x7BDEF7BD : 0xDEF7BDEB;
+	    	} else { 
+	    		row[i] = (i % 3) != 0 ? 0xE0E0E0 : 0x808080;
+	    		if (imageData.depth == 32) {
+	    			row[i] = (row[i] & 255) + (row[i] << 8);
+	    		}
+	    	}
+			}
+	    for (int y = 1; y < imageData.height - 1; y++) {
+	    	imageData.setPixels(0, y, row.length, row, 0);
+	    }
+	    Arrays.fill(row, imageData.depth == 16 ? 0x7BDEF7BD : 0xE0E0E0E0);
+	  	imageData.setPixels(0, 0, row.length, row, 0);
+	  	imageData.setPixels(0, imageData.height - 1, row.length, row, 0);
+	    image.dispose();
+	    image = new Image(sash.getDisplay(), imageData);
+	    sash.setBackgroundImage(image);
+	    sash.addDisposeListener(new DisposeListener() {
+				public void widgetDisposed(DisposeEvent e) {
+					sash.getBackgroundImage().dispose();
+				}
+			});
+	    
+	    return( sash );
+	}
+	
+	/**
+	 * Sometimes, Display.getCursorControl doesn't go deep enough..
+	 */
+	public static Control getCursorControl() {
+		Display d = Utils.getDisplay();
+		Point cursorLocation = d.getCursorLocation();
+		Control cursorControl = d.getCursorControl();
+		
+		if (cursorControl instanceof Composite) {
+			return getCursorControl((Composite) cursorControl, cursorLocation);
+		}
+		
+		return cursorControl;
+	}
+
+	public static Control getCursorControl(Composite parent, Point cursorLocation) {
+		for (Control con : parent.getChildren()) {
+			Rectangle bounds = con.getBounds();
+			Point displayLoc = con.toDisplay(0, 0);
+			bounds.x = displayLoc.x;
+			bounds.y = displayLoc.y;
+			boolean found = bounds.contains(cursorLocation);
+			if (found) {
+				if (con instanceof Composite) {
+					return getCursorControl((Composite) con, cursorLocation);
+				}
+				return con;
+			}
+		}
+		return parent;
+	}
+
+	public static void relayoutUp(Composite c) {
+		while (c != null && !c.isDisposed()) {
+			Composite newParent = c.getParent();
+			if (newParent == null) {
+				break;
+			}
+			newParent.layout(new Control[] { c });
+			c = newParent;
+		}
+	}
+
+	public static void updateScrolledComposite(ScrolledComposite sc) {
+		Control content = sc.getContent();
+		if (content != null && !content.isDisposed()) {
+			Rectangle r = sc.getClientArea();
+			sc.setMinSize(content.computeSize(r.width, SWT.DEFAULT ));
+		}
+	}
+	
+	public static void
+	maintainSashPanelWidth(
+		final SashForm		sash,
+		final Composite		comp,
+		final int[]			default_weights,
+		final String		config_key )
+	{
+		final boolean is_lhs = comp == sash.getChildren()[0];
+		
+		String str = COConfigurationManager.getStringParameter( config_key, default_weights[0]+","+default_weights[1] );
+		
+		try{
+			String[] bits = str.split( "," );
+			
+			sash.setWeights( new int[]{ Integer.parseInt( bits[0] ), Integer.parseInt( bits[1] )});
+				
+		}catch( Throwable e ){
+			
+			sash.setWeights( default_weights );
+		}
+		
+		Listener sash_listener= 
+	    	new Listener()
+	    	{
+	    		private int	comp_weight;
+	    		private int	comp_width;
+	    		
+		    	public void 
+				handleEvent(
+					Event ev ) 
+				{
+		    		if ( ev.widget == comp ){
+		    			
+		    			int[] weights = sash.getWeights();
+		    			
+		    			int current_weight = weights[is_lhs?0:1];
+		    			
+		    			if ( comp_weight != current_weight ){
+		    				
+		    				COConfigurationManager.setParameter( config_key, weights[0]+","+weights[1] );
+		    				
+		    					// sash has moved
+		    				
+		    				comp_weight = current_weight;
+		    				
+		    					// keep track of the width
+		    				
+		    				comp_width = comp.getBounds().width;
+		    			}
+		    		}else{
+		    			
+		    				// resize
+		    			
+		    			if ( comp_width > 0 ){
+		    						    				
+				            int width = sash.getClientArea().width;
+				            	
+				            if ( width < 20 ){
+				            	
+				            	width = 20;
+				            }
+				            
+				            double ratio = (double)comp_width/width;
+	
+				            comp_weight = (int)(ratio*1000 );
+	
+				            if ( comp_weight < 20 ){
+				            	
+				            	comp_weight = 20;
+				            	
+				            }else if ( comp_weight > 980 ){
+				            	
+				            	comp_weight = 980;
+				            }
+				            
+				            if ( is_lhs ){
+				            	
+				            	sash.setWeights( new int[]{ comp_weight, 1000 - comp_weight });
+				            	
+				            }else{
+				            	
+				            	sash.setWeights( new int[]{ 1000 - comp_weight, comp_weight });
+				            }
+		    			}
+		    		}
+			    }
+		    };
+	    
+		comp.addListener(SWT.Resize, sash_listener );
+	    sash.addListener(SWT.Resize, sash_listener );
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/associations/AssociationChecker.java b/azureus2/src/org/gudy/azureus2/ui/swt/associations/AssociationChecker.java
index 6c6f00b..5b9236b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/associations/AssociationChecker.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/associations/AssociationChecker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 23-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/auth/AuthenticatorWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/auth/AuthenticatorWindow.java
index 97fc9bd..74196f8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/auth/AuthenticatorWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/auth/AuthenticatorWindow.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -409,7 +410,7 @@ AuthenticatorWindow
 				return;
 			}
 			
-			final String ignore_key = "IgnoreAuth:" + realm + ":" + target + ":" + details;
+			final String ignore_key = "IgnoreAuth:" + realm + ":" + target + ":" + details.hashCode();
 			
 			if ( RememberedDecisionsManager.getRememberedDecision( ignore_key ) == 1 ){
 				
@@ -420,6 +421,22 @@ AuthenticatorWindow
 				return;
 			}
 			
+			String old_ignore_key = "IgnoreAuth:" + realm + ":" + target + ":" + details;
+			
+			int old_decision = RememberedDecisionsManager.getRememberedDecision( old_ignore_key );
+			if ( old_decision >= 0 ) {
+
+				RememberedDecisionsManager.setRemembered(old_ignore_key, -1);
+			}
+
+			if ( old_decision == 1 ){
+				
+				Debug.out( "Authentication for " + realm + "/" + target + "/" + details + " ignored as told not to ask again" );
+				
+				sem.releaseForever();
+				
+				return;
+			}
 				
 	 		shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
 	 	
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/auth/CertificateCreatorWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/auth/CertificateCreatorWindow.java
index 92955f2..84fc523 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/auth/CertificateCreatorWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/auth/CertificateCreatorWindow.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/auth/CertificateTrustWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/auth/CertificateTrustWindow.java
index 8cb9996..bd37bae 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/auth/CertificateTrustWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/auth/CertificateTrustWindow.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/auth/CryptoWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/auth/CryptoWindow.java
index 9a4c1c5..9db6143 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/auth/CryptoWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/auth/CryptoWindow.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -33,12 +34,11 @@ import org.eclipse.swt.events.MouseAdapter;
 import org.eclipse.swt.events.MouseEvent;
 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.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
-
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.util.*;
 
@@ -363,6 +363,7 @@ CryptoWindow
 						Utils.launch((String) ((Label) arg0.widget).getData());
 					}
 				});
+				ClipboardCopy.addCopyToClipMenu( linkLabel );
 		 	}
 		 	
 				// line
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/beta/BetaWizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/beta/BetaWizard.java
index db28778..54af4eb 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/beta/BetaWizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/beta/BetaWizard.java
@@ -2,20 +2,19 @@
  * Created on May 24, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/beta/BetaWizardStart.java b/azureus2/src/org/gudy/azureus2/ui/swt/beta/BetaWizardStart.java
index f948622..723eff7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/beta/BetaWizardStart.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/beta/BetaWizardStart.java
@@ -2,20 +2,19 @@
  * Created on May 24, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem.java
deleted file mode 100644
index 211bd28..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Created: 2004/May/26
- * 
- * 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 Alle Lenotre, La Grille Royale,
- * 78600 Le Mesnil le Roi, France.
- */
-
-package org.gudy.azureus2.ui.swt.components;
-
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Image;
-
-public abstract interface BufferedGraphicTableItem
-{
-	public abstract int getMarginWidth();
-
-	public abstract int getMarginHeight();
-
-	public abstract void setMargin(int width, int height);
-
-	/** Orientation of cell.  SWT.LEFT, SWT.RIGHT, SWT.CENTER, or SWT.FILL.
-	 * When SWT.FILL, update() will be called when the size of the cell has 
-	 * changed.
-	 */
-	public abstract void setOrientation(int orientation);
-
-	public abstract int getOrientation();
-
-	public abstract Point getSize();
-
-	public abstract boolean setGraphic(Image img);
-
-	public abstract Image getGraphic();
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem1.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem1.java
deleted file mode 100644
index 2353a41..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedGraphicTableItem1.java
+++ /dev/null
@@ -1,193 +0,0 @@
- /*
- * File    : BufferedGraphicTableItem1.java
- * Created : 24 nov. 2003
- *
- * 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.swt.components;
-
-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.graphics.Point;
-import org.eclipse.swt.widgets.Display;
-import org.gudy.azureus2.ui.swt.components.BufferedTableRow;
-
-/** Draws an image at a column in a row of a table using direct paints to the 
- *  table.
- * In comparison to BufferedGraphicTable2,
- * Pros:
- *  - Cleaner
- *  - More proper
- *
- * 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)
- *  - other bugs
- *
- * @see BufferedGraphicTable2
- * @author TuxPaper
- *
- */
-public abstract class BufferedGraphicTableItem1 extends BufferedTableItemImpl
-		implements BufferedGraphicTableItem
-{
-  private int marginHeight = 1;
-  private int marginWidth = 1;
-  private int orientation = SWT.CENTER;
-
-	//The Buffered image
-  private Image image;
-  
-  
-  public BufferedGraphicTableItem1(BufferedTableRow row,int position) {
-    super(row, position);
-  }
-
-  /** Retrieve the graphic related to this table item.
-   * @return the Image that is draw in the cell, or null if there is none.
-   */
-  public Image getGraphic() {
-    return image;
-  }
-  
-  /* Sets image to be drawn.
-   * @param img Image to be stored & drawn
-   * @return true - image was changed.<br>  
-   *         false = image was the same (doesn't mean image bits were the same)
-   */
-  public boolean setGraphic(Image img) {
-    boolean bImageSet = (image != img);
-    boolean bDoRedraw = (img == null);
-
-    if (bImageSet) {
-      // redraw if size changed to wipe area
-      if (!bDoRedraw && 
-          image != null && !image.isDisposed() && !img.isDisposed() &&
-          !image.getBounds().equals(img.getBounds()))
-        bDoRedraw = true;
-      image = img;
-    }
-    //doPaint(bDoRedraw);
-
-    return bImageSet;
-  }
-
-  public boolean needsPainting() {
-  	return true;
-  }
-
-  public void dispose() {
-    super.dispose();
-    image = null;
-  }
-  
-  /** Calculate the bounds of the receiver should be drawing in
-    * @return what size/position the canvas should be
-    */
-  public Rectangle getBoundsForCanvas() {
-    Rectangle bounds = super.getBounds();
-    if(bounds == null)
-      return null;
-    bounds.y += marginHeight;
-    bounds.height -= (marginHeight * 2);
-    bounds.x += marginWidth;
-    bounds.width -= (marginWidth * 2);
-    return bounds;
-  }
-  
-  // @see {getBounds}
-  public Rectangle getBounds() {
-  	return getBoundsForCanvas();
-  }
-  
-  public Rectangle getBoundsRaw() {
-    return super.getBounds();
-  }
-
-  public Point getSize() {
-    Rectangle bounds = super.getBounds();
-    if(bounds == null)
-      return new Point(0, 0);
-    return new Point(bounds.width - (marginWidth * 2), 
-                     bounds.height - (marginHeight * 2));
-  }
-  
-  public void invalidate() {
-  }
-  
-	public int getMarginHeight() {
-		return marginHeight;
-	}
-
-	public int getMarginWidth() {
-		return marginWidth;
-	}
-
-  public void setMargin(int width, int height) {
-  	if (width >= 0) {
-  		marginWidth = width;
-  	}
-  	
-  	if (height >= 0) {
-  		marginHeight = height;
-  	}
-  }
-
-	public int getOrientation() {
-		return orientation;
-	}
-  
-  public void setOrientation(int orientation) {
-  	this.orientation = orientation;
-  }
-  
-  public Image getBackgroundImage() {
-  	Image imageRowBG = row.getBackgroundImage();
-  	if (imageRowBG != null) {
-  		Rectangle bounds = super.getBounds();
-  		
-  		int wInside = bounds.width - (marginWidth * 2);
-  		int hInside = bounds.height - (marginHeight * 2);
-  		Image imageCellBG = new Image(Display.getDefault(), wInside, hInside);
-  		GC gc = new GC(imageCellBG);
-  		gc.drawImage(imageRowBG, bounds.x + marginWidth, 0 + marginHeight,
-					wInside, hInside, 0, 0, wInside, hInside);
-  		gc.dispose();
-  		
-  		return imageCellBG;
-  	}
-  	
-		Rectangle bounds = super.getBounds();
-		
-		if (bounds.isEmpty()) {
-			return null;
-		}
-		
-		Image image = new Image(Display.getDefault(), bounds.width
-				- (marginWidth * 2), bounds.height - (marginHeight * 2));
-		
-		GC gc = new GC(image);
-		gc.setForeground(getBackground());
-		gc.setBackground(getBackground());
-		gc.fillRectangle(0, 0, bounds.width, bounds.height);
-		gc.dispose();
-		
-		return image;
-	}
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedLabel.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedLabel.java
index 4a97d1f..a78550a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedLabel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedLabel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -195,6 +196,8 @@ BufferedLabel
 		    	  }
 		      }
 		    });	
+		    
+		    ClipboardCopy.addCopyToClipMenu( label );
 		}
 	}
 	
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTableItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTableItem.java
deleted file mode 100644
index 941f9f6..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTableItem.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Created on Jun 12, 2006 11:34:42 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 org.gudy.azureus2.ui.swt.components;
-
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Rectangle;
-
-/**
- * @author TuxPaper
- * @created Jun 12, 2006
- *
- */
-public interface BufferedTableItem
-{
-
-	public abstract String getText();
-
-	public abstract boolean setText(String text);
-
-	public abstract Image getIcon();
-
-	public abstract void setIcon(Image img);
-
-	public abstract void setRowForeground(Color color);
-
-	public abstract boolean setForeground(Color color);
-
-	public abstract boolean setForeground(int red, int green, int blue);
-
-	public abstract Color getBackground();
-
-	public abstract Rectangle getBounds();
-
-	public abstract Rectangle getBoundsRaw();
-
-	public abstract void refresh();
-
-	public abstract void dispose();
-
-	/**
-	 * Is the cell currently shown on the screen?
-	 * 
-	 * @return
-	 */
-	public abstract boolean isShown();
-
-	public abstract boolean needsPainting();
-
-	/** Column location (not position) changed.  Usually due to a resize of
-	 * a column in a position prior to this one.
-	 */
-	public abstract void locationChanged();
-
-	public abstract int getPosition();
-
-	/**
-	 * 
-	 */
-	public abstract Image getBackgroundImage();
-
-	/**
-	 * @return
-	 */
-	public abstract Color getForeground();
-
-	/**
-	 * 
-	 */
-	public abstract void invalidate();
-
-	/**
-	 * Set to redraw at the next OS paint
-	 */
-	public abstract void redraw();
-	
-	/**
-	 * # of lines item can handle
-	 * @return
-	 *
-	 * @since 3.0.1.1
-	 */
-	public abstract int getMaxLines();
-
-	/**
-	 * @param cursorID
-	 *
-	 * @since 3.0.4.3
-	 */
-	public abstract void setCursor(int cursorID);
-
-	/**
-	 * 
-	 *
-	 * @since 3.0.5.3
-	 */
-	public abstract boolean isMouseOver();
-
-	/**
-	 * @return
-	 *
-	 * @since 4.5.1.1
-	 */
-	boolean isInPaintItem();
-
-	/**
-	 * @return
-	 *
-	 * @since 4.6.0.5
-	 */
-	public int getHeight();
-}
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTableItemImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTableItemImpl.java
deleted file mode 100644
index f72c50f..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTableItemImpl.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * File    : BufferedTableItem.java
- * Created : 24 nov. 2003
- * By      : Olivier
- *
- * 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.swt.components;
-
-import org.eclipse.swt.graphics.*;
-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;
-import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;
-
-import com.aelitis.azureus.ui.swt.utils.ColorCache2;
-import com.aelitis.azureus.ui.swt.utils.ColorCache2.*;
-
-/**
- * @author Olivier
- *
- */
-public abstract class BufferedTableItemImpl implements BufferedTableItem
-{
-	protected BufferedTableRow row;
-
-	private int position;
-
-	private CachedColor ourFGColor_cache = null;
-	
-	private String text = "";
-	
-	private Image icon = null;
-
-	private AERunnable runnableDirtyCell;
-
-	private boolean isDirty;
-
-	public BufferedTableItemImpl(BufferedTableRow row, int position) {
-		this.row = row;
-		this.position = position;
-	}
-
-	public String getText() {
-		return text;
-	}
-
-	public boolean setText(String text) {
-		if (this.text.equals(text)) {
-			return false;
-		}
-		this.text = (text == null) ? "" : text;
-		
-		redraw();
-		
-		return true;
-	}
-
-  // @see org.gudy.azureus2.ui.swt.components.BufferedTableItem#redraw()
-  public void redraw() {
-		//System.out.println("redraw via " + Debug.getCompressedStackTrace(5));
-
-  	synchronized (this) {
-			if (isDirty) {
-				return;
-			}
-		}
-  	
-  	if (!row.isVisibleNoSWT()) {
-  		return;
-  	}
-
-		// Might be a good optimization.. haven't tried it
-  	//if (isInPaintItem()) {
-		//		&& row.getTable().getData("fullPaint") == Boolean.TRUE) {
-  	//	return;
-  	//}
-  	
-		if (runnableDirtyCell == null) {
-			synchronized (this) {
-				if (runnableDirtyCell == null) {
-					runnableDirtyCell = new AERunnable() {
-						public void runSupport() {
-							synchronized (BufferedTableItemImpl.this) {
-								isDirty = false;
-							}
-							if (isInPaintItem()
-									&& row.getTable().getData("fullPaint") == Boolean.TRUE) {
-								return;
-							}
-							// row.isVisible is time consuming.  getBounds intersecting 
-							// clientArea will probably be empty when not visible
-							//if (!row.isVisible()) {
-							//	return;
-							//}
-							Rectangle bounds = getBoundsRaw();
-							if (bounds != null) {
-								TableOrTreeSWT table = row.getTable();
-								Rectangle dirty = table.getClientArea().intersection(bounds);
-								//System.out.println("old = " + this.text + ";new=" + text + ";dirty=" + bounds);
-
-								if (!dirty.isEmpty()) {
-									quickRedrawCell(table, dirty, bounds);
-								}
-							}
-						}
-					};
-				}
-			}
-		}
-		
-		synchronized (this) {
-			isDirty = true;
-		}
-		Utils.execSWTThread(runnableDirtyCell);
-	}
-
-	protected void quickRedrawCell(TableOrTreeSWT table, Rectangle dirty,
-			Rectangle cellBounds) {
-		table.redraw(dirty.x, dirty.y, dirty.width, dirty.height, false);
-	}
-
-	public void setIcon(Image img) {
-		if (position != -1) {
-			row.setImage(position, img);
-			icon = img;
-		}
-	}
-
-	public Image getIcon() {
-		if (position != -1) {
-			Image image = row.getImage(position);
-			return (image != null) ? image : icon;
-		}
-
-		return null;
-	}
-
-	public void setRowForeground(Color color) {
-		row.setForeground(color);
-	}
-
-	public boolean setForeground(Color color) {
-		if (position == -1)
-			return false;
-
-		boolean ok = row.setForeground(position, color);
-		if (ok && ourFGColor_cache != null) {
-			if (!ourFGColor_cache.isDisposed()) {ourFGColor_cache.dispose();}
-			ourFGColor_cache = null;
-		}
-		return ok;
-	}
-	
-	public Color getForeground() {
-		if (position == -1)
-			return null;
-
-		return row.getForeground(position);
-	}
-
-	public boolean setForeground(final int red, final int green, final int blue) {
-		if (position == -1) {
-			return false;
-		}
-
-		Color oldColor = row.getForeground(position);
-		if (oldColor != null) {
-
-  		RGB newRGB = new RGB(red, green, blue);
-  
-  		if (oldColor.getRGB().equals(newRGB)) {
-  			return false;
-  		}
-		}
-
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				swt_setForeground(red, green, blue);
-			}
-		});
-		return true;
-	}
-
-	private boolean swt_setForeground(final int red, final int green, final int blue) {
-		if (red == -1 && green == -1 && blue == -1) {
-			return setForeground(null);
-		}
-
-		Color oldColor = row.getForeground(position);
-
-		RGB newRGB = new RGB(red, green, blue);
-
-		if (oldColor != null && oldColor.getRGB().equals(newRGB)) {
-			return false;
-		}
-
-		CachedColor newColor = ColorCache2.getColor( row.getTable().getDisplay(), newRGB );
-		boolean ok = row.setForeground(position, newColor.getColor());
-		if (ok) {
-			if (ourFGColor_cache != null && !ourFGColor_cache.isDisposed())
-				ourFGColor_cache.dispose();
-			ourFGColor_cache = newColor;
-		} else {
-			if (!newColor.isDisposed())
-				newColor.dispose();
-		}
-
-		return ok;
-	}
-
-	public Color getBackground() {
-		return row.getBackground();
-	}
-
-	public Rectangle getBounds() {
-		if (position == -1) {
-			return null;
-		}
-		if (isInPaintItem()) {
-			InPaintInfo data = (InPaintInfo) row.getTable().getData("inPaintInfo");
-			return new Rectangle(data.curCellBounds.x, data.curCellBounds.y,
-					data.curCellBounds.width, data.curCellBounds.height);
-		}
-		return row.getBounds(position);
-	}
-	
-  public Rectangle getBoundsRaw() {
-    return getBounds();
-  }
-
-
-	public TableOrTreeSWT getTable() {
-		return row.getTable();
-	}
-
-	public void dispose() {
-		if (ourFGColor_cache != null && !ourFGColor_cache.isDisposed())
-			ourFGColor_cache.dispose();
-	}
-
-	public boolean isShown() {
-		return true;
-// XXX Bounds check is almost always slower than any changes we
-//     are going to do to the column
-//		if (position < 0) {
-//			return false;
-//		}
-//		
-//		Rectangle bounds = row.getBounds(position);
-//		if (bounds == null) {
-//			return false;
-//		}
-//
-//		return row.getTable().getClientArea().intersects(bounds);
-	}
-
-	public boolean needsPainting() {
-		return false;
-	}
-
-	public void locationChanged() {
-	}
-
-	public int getPosition() {
-		return position;
-	}
-
-	public Image getBackgroundImage() {
-		TableOrTreeSWT table = row.getTable();
-		
-		Rectangle bounds = getBounds();
-		
-		if (bounds.isEmpty()) {
-			return null;
-		}
-		
-		Image image = new Image(table.getDisplay(), bounds.width, bounds.height);
-		
-		GC gc = new GC(image);
-		gc.setForeground(getBackground());
-		gc.setBackground(getBackground());
-		gc.fillRectangle(0, 0, bounds.width, bounds.height);
-		//gc.copyArea(image, bounds.x, bounds.y);
-		gc.dispose();
-		
-		return image;
-	}
-
-  // @see org.gudy.azureus2.ui.swt.components.BufferedTableItem#getMaxLines()
-  public int getMaxLines() {
-  	return 1;
-  }
-  
-  // @see org.gudy.azureus2.ui.swt.components.BufferedTableItem#setCursor(int)
-  public void setCursor(final int cursorID) {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				if (row == null) {
-					return;
-				}
-				TableOrTreeSWT table = row.getTable();
-				if (table == null || table.isDisposed()) {
-					return;
-				}
-				table.setCursor(table.getDisplay().getSystemCursor(cursorID));
-			}
-		});
-  }
-  
-  // @see org.gudy.azureus2.ui.swt.components.BufferedTableItem#isMouseOver()
-  public boolean isMouseOver() {
-		TableOrTreeSWT table = row.getTable();
-		if (table == null || table.isDisposed()) {
-			return false;
-		}
-		Point pt = table.getDisplay().getCursorLocation();
-		pt = table.toControl(pt);
-
-		Rectangle bounds = getBounds();
-		return bounds == null ? false : bounds.contains(pt);
-  }
-  
-	public boolean isInPaintItem() {
-		if (row.inPaintItem()) {
-			InPaintInfo data = (InPaintInfo) row.getTable().getData("inPaintInfo");
-			return data.curCellIndex == position;
-		}
-		return false;
-	}
-	
-	// @see org.gudy.azureus2.ui.swt.components.BufferedTableItem#getHeight()
-	public int getHeight() {
-		return row.getHeight();
-	}
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTableRow.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTableRow.java
deleted file mode 100644
index de16ba2..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTableRow.java
+++ /dev/null
@@ -1,834 +0,0 @@
-/*
- * File    : BufferedTableItem.java
- * Created : 24-Nov-2003
- * 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.swt.components;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-
-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.views.table.TableItemOrTreeItem;
-import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;
-
-import com.aelitis.azureus.ui.swt.utils.ColorCache2;
-import com.aelitis.azureus.ui.swt.utils.ColorCache2.*;
-
-/**
- * A buffered Table Row.
- *<p> 
- * We buffer certain properties of TableRow to save CPU cycles.  For example,
- * foreground_colors is cached because TableItem.getForegroundColor is expensive
- * when there is no color set, and setForegroundColor is always expensive.
- *<p> 
- * Text is not buffered as SWT does a good job of buffering it already.
- *<p>
- * 
- * @note For Virtual tables, we can not set any visual properties until
- *        SWT.SetData has been called.  getData("SD") is set after SetData
- *        call, and the row is invalidated.  Thus, there is no need to set
- *        any visual properties until the row #isVisible()
- * 
- * @author parg<br>
- * @author TuxPaper (SWT.Virtual Stuff)
- */
-public class 
-BufferedTableRow
-{
-	private static final int VALUE_SIZE_INC	= 8;
-
-	// for checkWidget(int)
-	public final static int REQUIRE_TABLEITEM = 0;
-	public final static int REQUIRE_TABLEITEM_INITIALIZED = 1;
-	public final static int REQUIRE_VISIBILITY = 2;
-	
-	protected TableOrTreeSWT table;
-	protected TableItemOrTreeItem	item;
-	
-	protected Image[]	image_values	= new Image[0];
-	protected Color[]	foreground_colors	= new Color[0];
-	
-	protected CachedColor		foreground_cache;
-	protected CachedColor     	ourForeground_cache;
-	
-	private Point ptIconSize = null;
-
-	private Image imageBG;
-
-	private int numSubItems;
-
-	private boolean expanded;
-
-	private boolean isVirtual;
-	
-	
-	/**
-	 * Default constructor
-	 * 
-	 * @param _table
-	 */
-	public BufferedTableRow(TableOrTreeSWT _table)
-	{
-		table = _table;
-		item = null;
-	}
-	
-	/**
-	 * Disposes of underlying SWT TableItem. If no TableItem has been
-	 * assigned to the row yet, an unused TableItem will be disposed of, if
-	 * available.
-	 * <p>
-	 * Disposing of fonts, colors and other resources are the responsibilty of 
-	 * the caller.
-	 */
-	public void
-	dispose()
-	{
-		if (table != null && !table.isDisposed() && Utils.isThisThreadSWT()) {
-			if (!checkWidget(REQUIRE_TABLEITEM)) {
-				// No assigned spot yet, or not our spot:
-				// find a row with no TableRow data
-
-				TableItemOrTreeItem[] items = table.getItems();
-				for (int i = items.length - 1; i >= 0; i--) {
-					TableItemOrTreeItem item = items[i];
-					if (!item.isDisposed()) {
-						Object itemRow = item.getData("TableRow");
-						if (itemRow == null || itemRow == this) {
-							this.item = item;
-							break;
-						}
-					}
-				}
-			}
-
-			boolean itemNeedsDisposal = item != null && !item.isDisposed(); 
-			
-			if (ourForeground_cache != null && !ourForeground_cache.isDisposed()) {
-				// Even though we are going to dispose soon, set foreground to null
-				// in case for some reason the OS gets a paint event in between
-				// the color disposal and the item disposal
-				if (itemNeedsDisposal) {
-					item.setForeground(null);
-				}
-				this.ourForeground_cache.dispose();
-			}
-
-			if (itemNeedsDisposal) {
-				item.dispose();
-			} else if (table.getItemCount() > 0) {
-				System.err.println("No table row was found to dispose");
-			}
-		} else {
-			if (!Utils.isThisThreadSWT()) {
-				System.err.println("Calling BufferedTableRow.dispose on non-SWT thread!");
-				System.err.println(Debug.getStackTrace(false, false));
-			}
-		}
-		item = null;
-	}
-	
-	/**
-	 * Sets the receiver's image at a column.
-	 *
-	 * @param index the column index
-	 * @param new_image the new image
-	 */
-	public void
-	setImage(
-   		int 	index,
-		Image	new_image )
-	{
-		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
-			return;
-
-		if ( index >= image_values.length ){
-			
-			int	new_size = Math.max( index+1, image_values.length+VALUE_SIZE_INC );
-			
-			Image[]	new_images = new Image[new_size];
-			
-			System.arraycopy( image_values, 0, new_images, 0, image_values.length );
-			
-			image_values = new_images;
-		}
-		
-		Image	image = image_values[index];
-		
-		if ( new_image == image ){
-			
-			return;
-		}
-		
-		image_values[index] = new_image;
-		
-		item.setImage( index, new_image );	
-	}
-	
-	public Image getImage(int index) {
-		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
-			return null;
-		
-		return item.getImage(index);
-	}
-
-	/**
-	 * Checks if the widget is valid
-	 * 
-	 * @param checkFlags REQUIRE_* flags (OR'd)
-	 * 
-	 * @return True: Ok; False: Not ok
-	 */
-	public boolean checkWidget(int checkFlags) {
-		boolean bWidgetOk = item != null && !item.isDisposed()
-				&& item.getData("TableRow") == this;
-
-		final boolean bCheckVisibility = (checkFlags & REQUIRE_VISIBILITY) > 0;
-		final boolean bCheckInitialized = (checkFlags & REQUIRE_TABLEITEM_INITIALIZED) > 0;
-
-		if (bWidgetOk && bCheckInitialized) {
-			bWidgetOk = !isVirtual
-					|| item.getData("SD") != null;
-		}
-
-		if (bWidgetOk && bCheckVisibility) {
-			if (_isVisible()) {
-				// Caller assumes that a visible item can be modified, so 
-				// make sure we initialize it.
-				if (!bCheckInitialized && isVirtual
-						&& item.getData("SD") == null) {
-					// This is catch is temporary for SWT 3212, because there are cases where
-					// it says it isn't disposed, when it really almost is
-					try {
-						item.setData("SD", "1");
-					} catch (NullPointerException badSWT) {
-					}
-
-		    	setIconSize(ptIconSize);
-					invalidate();
-				}
-			} else {
-				bWidgetOk = false;
-			}
-		}
-
-		return bWidgetOk;
-	}
-	
-	private boolean _isVisible() {
-		// Least time consuming checks first
-
-		if (inPaintItem()) {
-			return true;
-		}
-
-		if (!table.isVisible()) {
-			return false;
-		}
-		
-		//if (table.getData("inPaintItem") != null) {
-		//	System.out.println(table.indexOf((Widget) table.getData("inPaintItem")) + ";" + table.indexOf(item));
-		//	System.out.println(Debug.getCompressedStackTrace());
-		//}
-		
-		Rectangle bounds = getBounds(0);
-		if (bounds == null) {
-			return false;
-		}
-		return table.getClientArea().contains(bounds.x, bounds.y);
-
-		/*
-		int index = table.indexOf(item);
-		if (index == -1)
-			return false;
-		
-		int iTopIndex = table.getTopIndex();
-		if (index < iTopIndex)
-			return false;
-
-		int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex);
-		if (index > iBottomIndex)
-			return false;
-
-  	//System.out.println("i-" + index + ";top=" + iTopIndex + ";b=" + iBottomIndex);
-		
-		return true;
-		*/
-	}
-	
-	
-	public Color
-	getForeground()
-	{
-		if (foreground_cache != null) {
-			return foreground_cache.getColor();
-		}
-		
-		if (!Utils.isSWTThread()) {
-			return null;
-		}
-
-		if (foreground_cache == null && isSelected()) {
-			return table.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
-		}
-
-		if (!checkWidget(REQUIRE_TABLEITEM)) {
-			return null;
-		}
-
-		return( item.getForeground());
-	}
-	
-	public boolean
-	setForeground(
-		Color	c )
-	{
-		if (foreground_cache == null && c == null) {return false;}
-		
-		if (foreground_cache != null ){
-			
-			Color existing = foreground_cache.getColor();
-			
-			if ( existing != null && existing.equals(c)){
-		
-				return false;
-			}
-		}
-		
-		foreground_cache = ColorCache2.getColor( c );
-		if (this.ourForeground_cache != null) {
-			if (!this.ourForeground_cache.isDisposed()) {
-				this.ourForeground_cache.dispose();
-			}
-			this.ourForeground_cache = null;
-		}
-		
-		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
-			return false;
-
-		item.setForeground(c);
-		return true;
-	}
-
-	public void setForeground(final int red, final int green, final int blue) {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				swt_setForeground(red, green, blue);
-			}
-		});
-	}
-
-	
-	public void swt_setForeground(int red, int green, int blue) {
-		if (red == -1 && green == -1 && blue == -1) {
-			this.setForeground(null);
-			return;
-		}
-		
-		RGB newRGB = new RGB(red, green, blue);
-		if (this.foreground_cache != null ){
-			
-			Color c = this.foreground_cache.getColor();
-			
-			if ( c != null && c.getRGB().equals(newRGB)){
-		
-				return;
-			}
-		}
-		
-		// Hopefully it is OK to just assume it is safe to dispose of the colour,
-		// since we're expecting it to match this.foreground.
-		CachedColor newColor = ColorCache2.getColor(getTable().getDisplay(), newRGB);
-		if (checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) {
-			item.setForeground(newColor.getColor());
-		}
-		if (ourForeground_cache != null && !ourForeground_cache.isDisposed()) {
-			ourForeground_cache.dispose();
-		}
-		this.foreground_cache = newColor;
-		this.ourForeground_cache = newColor;
-	}
-	
-	public boolean
-	setForeground(
-	  final int index,
-		final Color	new_color )
-	{
-				
-		synchronized (this) {
-			
-  		if ( index >= foreground_colors.length ){
-  			
-  			int	new_size = Math.max( index+1, foreground_colors.length+VALUE_SIZE_INC );
-  			
-  			Color[]	new_colors = new Color[new_size];
-  			
-  			System.arraycopy( foreground_colors, 0, new_colors, 0, foreground_colors.length );
-  			
-  			foreground_colors = new_colors;
-  		}
-  
-  		Color value = foreground_colors[index];
-  		
-  		if ( new_color == value ){
-  			
-  			return false;
-  		}
-  		
-  		if (	new_color != null && 
-  				value != null &&
-  				new_color.equals( value )){
-  					
-  			return false;
-  		}
-  		
-  		foreground_colors[index] = new_color;
-		}
-
-		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) {
-			return true;
-		}
-
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				if ( !item.isDisposed()){
-					item.setForeground(index, new_color);
-				}
-			}
-		});
-    
-    return true;
-	}
-
-	public Color getForeground(int index)
-	{
-		synchronized (this) {
-  		if (index >= foreground_colors.length) {
-  		  return getForeground();
-  		}
-  
-  		if (foreground_colors[index] == null) {
-  			if (isSelected()) {
-  				if (!Utils.isSWTThread()) {
-  					return null;
-  				}
-  
-    			Color systemColor = table.getDisplay().getSystemColor(
-    					table.isFocusControl() ? SWT.COLOR_LIST_SELECTION_TEXT
-    							: SWT.COLOR_WIDGET_FOREGROUND);
-    			return systemColor;
-  			}
-  			return getForeground();
-  		}
-  
-  		return foreground_colors[index];
-		}
-	}
-	
-	protected String
-	getText(
-		int		index )
-	{
-		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
-			return "";
-
-		// SWT >= 3041(Win),3014(GTK),3002(Carbon) and returns "" if range check
-		// fails
-		return item.getText(index);
-	}
-
-  /**
-   * @param index
-   * @param new_value
-   * @return true if the item has been updated
-   */
-	public boolean
-	setText(
-		int			index,
-		String		new_value )
-	{
-		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
-			return false;
-		
-		if (index < 0 || index >= table.getColumnCount())
-			return false;
-		
-		if (new_value == null)
-			new_value = "";
-
-		if (item.getText(index).equals(new_value))
-			return false;
-
-		item.setText( index, new_value );
-    
-    return true;
-	}
-	
-  public Rectangle getBounds(int index) {
-		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
-			return null;
-
-		Rectangle r = item.getBounds(index);
-		if (r == null || r.width == 0 || r.height == 0)
-			return null;
-
-		return r; 
-	}
-
-  protected TableOrTreeSWT getTable() {
-  	return table;
-  }
-  
-  public Color getBackground() {
-		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
-      return null;
-		
-		if (isSelected()) {
-			// XXX This isn't the right color on Cocoa when in focus
-			return table.getDisplay().getSystemColor(
-					table.isFocusControl() ? SWT.COLOR_LIST_SELECTION
-							: SWT.COLOR_WIDGET_BACKGROUND);
-		}
-    return item.getBackground();
-  }
-
-  /**
-   * The Index is this item's the position in list.
-   *
-   * @return Item's Position
-   */
-  public int getIndex() {
-		if (!checkWidget(REQUIRE_TABLEITEM))
-  		return -1;
-
-    return table.indexOf(item);
-  }
-  
-  public boolean isSelected() {
-		if (!checkWidget(REQUIRE_TABLEITEM))
-  		return false;
-
-    return table.isSelected(item);
-  }
-
-  public void setSelected(final boolean bSelected) {
-  	Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				swt_setSelected(bSelected);
-			}
-		});
-  }
-  
-  private void swt_setSelected(boolean bSelected) {
-		if (!checkWidget(REQUIRE_TABLEITEM))
-  		return;
-
-    if (bSelected)
-      table.select(item);
-    else
-      table.deselect(item);
-  }
-
-  public boolean setTableItem(int newIndex, boolean isVisible) {
-  	TableItemOrTreeItem newRow;
-
-  	try {
-//  		if (item != null && !item.isDisposed() && table.indexOf(item) == newIndex) {
-//  			return false;
-//  		}
-  		
-  		//System.out.println((item == null ? null : "" + table.indexOf(item)) + ":" + newIndex + ":" + isVisible + ":" + table.getData("maxItemShown"));
-  		newRow = table.getItem(newIndex);
-  	} catch (IllegalArgumentException er) {
-  		if (item == null || item.isDisposed()) {
-  			return false;
-  		}
-  		item = null;
-  		return true;
-  	} catch (Throwable e) {
-  		System.out.println("setTableItem(" + newIndex + ", " + isVisible + ")");
-  		e.printStackTrace();
-  		return false;
-  	}
-  	
-  	return setTableItem(newRow, isVisible);
-  }
-
-  public boolean setTableItem(TableItemOrTreeItem newRow, boolean isVisible) {
-  	if (item == null) {
-  		isVirtual = (table.getStyle() & SWT.VIRTUAL) != 0;
-  		if (ptIconSize == null) {
-  			ptIconSize = new Point(1, table.getItemHeight());
-  		}
-  	}
-  	if (newRow.isDisposed()) {
-  		Debug.out("newRow disposed from " + Debug.getCompressedStackTrace());
-  		return false;
-  	}
-
-  	if (newRow.equals(item)) {
-  		if (newRow.getData("TableRow") == this) {
-  			return false;
-  		}
-  	}
-
-  	//if (!newRow.getParent().equalsTableOrTree(table))
-  	//	return false;
-
-// The following is commented out after moving visible logic to TableRowImpl
-//  	if (!isVisible) {
-//  		// Q&D, clear out.. we'll fill it correctly when it's visible
-//  		if (newRow.getData("TableRow") != null) {
-//    		newRow.setData("TableRow", null);
-//    		table.deselect(newRow);
-//    		return true;
-//  		}
-//  		//System.out.println("quickclear " + table.indexOf(newRow));
-//  		return false;
-//  	}
-		//System.out.println("slowset " + table.indexOf(newRow));
-
-  	boolean lastItemExisted = item != null && !item.isDisposed();
-  	// can't base newRowHadItem on "TableRow" as we clear it in "unlinking" stage
-  	//boolean newRowHadItem = newRow.getData("TableRow") != null;
-
-  	if (newRow.getData("SD") != null) {
-  	} else {
-  		newRow.setData("SD", "1");
-  		setIconSize(ptIconSize);
-  	}
-
-		newRow.setForeground(foreground_cache==null?null:foreground_cache.getColor());
-
-		int numColumns = table.getColumnCount();
-		for (int i = 0; i < numColumns; i++) {
-			try {
-				//newRow.setImage(i, null);
-				newRow.setForeground(i, i < foreground_colors.length
-						? foreground_colors[i] : null);
-			} catch (NoSuchMethodError e) {
-				/* Ignore for Pre 3.0 SWT.. */
-			}
-		}
-
-  	try {
-  		newRow.setData("TableRow", this);
-  	} catch (Exception e) {
-  		e.printStackTrace();
-  		System.out.println("Disposed? " + newRow.isDisposed());
-  		if (!newRow.isDisposed()) {
-  			System.out.println("TR? " + newRow.getData("TableRow"));
-  			System.out.println("SD? " + newRow.getData("SD"));
-  		}
-  	}
-
-	  image_values	= new Image[0];
-	  //foreground_colors	= new Color[0];
-    //foreground = null;
-
-    // unlink old item from tablerow
-    if (lastItemExisted && item.getData("TableRow") == this && !newRow.equals(item)) {
-    	item.setData("TableRow", null);
-    	table.deselect(item);
-    	/*
-  		int numColumns = table.getColumnCount();
-  		for (int i = 0; i < numColumns; i++) {
-        try {
-        	//item.setImage(i, null);
-        	item.setForeground(i, null);
-        } catch (NoSuchMethodError e) {
-        }
-  		}
-  		*/
-    }
-
-    item = newRow;
-
-  	setSubItemCount(numSubItems);
-		item.setExpanded(expanded);
-		// Need to execute (de)select later, because if we are in a paint event
-		// that paint event may be reporting a row selected before the selection
-		// event fired (Cocoa 3650 fires paint before select yet the row is marked
-		// selected)
-		Utils.execSWTThreadLater(0, new AERunnable() {
-			public void runSupport() {
-				if (table.isDisposed() || item == null) {
-					return;
-				}
-				if (item.isDisposed()
-						|| item.getData("TableRow") != BufferedTableRow.this) {
-					return;
-				}
-				// select/deselect takes less time than a table.isSelected (tree)
-				if (isSelected()) {
-					table.select(item);
-				} else {
-					table.deselect(item);
-				}
-			}
-		});
-		if (isVisible && !inPaintItem()) {
-		//if (newRowHadItem && isVisible && !inPaintItem()) {
-			//invalidate();
-			// skip the visibility check and SWT thread wrapping of invalidate
-			Rectangle r = item.getBounds(0);
-			table.redraw(0, r.y, table.getClientArea().width, r.height, true);
-		}
-
-    return true;
-  }
-
-  public boolean setHeight(int iHeight) {
-  	return setIconSize(new Point(1, iHeight));
-  }
-  
-  public int getHeight() {
-  	return ptIconSize == null ? 0 : ptIconSize.y;
-  }
-  
-  public boolean setIconSize(Point pt) {
-    ptIconSize = pt;
-
-    if (pt == null || item == null )
-      return false;
-    
-		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
-			return false;
-		
-    Image oldImage = item.getImage(0);
-    if (oldImage != null) {
-    	Rectangle r = oldImage.getBounds();
-    	if (r.width == pt.x && r.height == pt.y)
-    		return false;
-    }
-		
-    // set row height by setting image
-    Image image = new Image(item.getDisplay(), pt.x, pt.y);
-    item.setImage(0, image);
-    item.setImage(0, null);
-    image.dispose();
-    
-    return true;
-  }
-
-  /**
-	 * Whether the row is currently visible to the user
-	 * 
-	 * @return visibility
-	 */
-  public boolean isVisible() {
-  	return checkWidget(REQUIRE_VISIBILITY);
-  }
-	
-  /**
-   * Overridable function that is called when row needs invalidation.
-   *
-   */
-  public void invalidate() {
-  	Utils.execSWTThread(new AERunnable() {
-		
-			public void runSupport() {
-		  	if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED | REQUIRE_VISIBILITY))
-		  		return;
-
-				Rectangle r = item.getBounds(0);
-
-				table.redraw(0, r.y, table.getClientArea().width, r.height, true);
-			}
-		});
-  }
-  
-  public void setBackgroundImage(Image image) {
-  	if (imageBG != null && !imageBG.isDisposed()) {
-  		imageBG.dispose();
-  	}
-  	imageBG = image;
-  }
-  
-  public Image getBackgroundImage() {
-  	return imageBG;
-  }
-
-	public void setSubItemCount(int i) {
-		numSubItems = i;
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				if (item != null && !item.isDisposed()) {
-					item.setItemCount(numSubItems == 0 ? 0 : 1);
-				}
-			}
-		});
-	}
-	
-	public int getSubItemCount() {
-		return numSubItems;
-	}
-	
-	public TableItemOrTreeItem[] getSubItems() {
-		return table.getItems();
-	}
-
-	public void setExpanded(boolean b) {
-		expanded = b;
-		if (item != null && !item.isDisposed()) {
-	    if (item.getItemCount() != numSubItems) {
-	    	item.setItemCount(numSubItems);
-				Rectangle r = item.getBounds(0);
-				if (r != null) {
-					table.redraw(0, r.y, table.getClientArea().width, r.height, true);
-				}
-	    }
-	    TableItemOrTreeItem[] items = item.getItems();
-	    for (TableItemOrTreeItem subItem : items) {
-				subItem.setData("TableRow", null);
-			}
-	    item.setExpanded(b);
-		}
-	}
-	
-	public boolean isExpanded() {
-		return expanded;
-	}
-
-	/**
-	 * @return
-	 *
-	 * @since 4.4.0.5
-	 */
-	public boolean inPaintItem() {
-		if (item != null && !item.isDisposed()) {
-			InPaintInfo info = (InPaintInfo) table.getData("inPaintInfo");
-			if (info != null && item.getItem().equals(info.item)) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	public boolean isVisibleNoSWT() {
-		return true;  // assume the worst
-	}
-	
-	public TableItemOrTreeItem getItem() {
-		return item;
-	}
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedToolItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedToolItem.java
index 939430a..4f014c5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedToolItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedToolItem.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTruncatedLabel.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTruncatedLabel.java
index 8e7ed94..db8c743 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTruncatedLabel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedTruncatedLabel.java
@@ -1,7 +1,7 @@
 /*
  * Created on 04-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedWidget.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedWidget.java
index 7cc81ec..ca06b0e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedWidget.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/BufferedWidget.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/CompositeMinSize.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/CompositeMinSize.java
index f4a5968..e6e349a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/CompositeMinSize.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/CompositeMinSize.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.components;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/DoubleBufferedLabel.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/DoubleBufferedLabel.java
index e8efae8..8738205 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/DoubleBufferedLabel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/DoubleBufferedLabel.java
@@ -2,20 +2,19 @@
  * Created on Jan 9, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -28,7 +27,6 @@ import org.eclipse.swt.graphics.GC;
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.graphics.Rectangle;
 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.gudy.azureus2.core3.util.Debug;
@@ -121,11 +119,15 @@ DoubleBufferedLabel
 		boolean changed, 
 		boolean realWidth ) 
 	{
+		/* Can't do this as things are often layed out when invisible and 
+		 * don't get redone on visibility change :(
+		 
 		if (!isVisible()){
 			
 			return (new Point(0, 0));
 		}
-
+		*/
+		
 		if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT) {
 			return new Point(wHint, hHint);
 		}
@@ -133,8 +135,6 @@ DoubleBufferedLabel
 
 		Point lastSize = new Point(0, 0);
 
-
-
 		GC gc = new GC(this);
 		
 		GCStringPrinter sp = new GCStringPrinter(gc, getText(), new Rectangle(0,
@@ -181,4 +181,4 @@ DoubleBufferedLabel
 
 		redraw();
 	}
-}
\ No newline at end of file
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/InPaintInfo.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/InPaintInfo.java
deleted file mode 100644
index d3d4e43..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/InPaintInfo.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Created on Feb 4, 2011
- *
- * Copyright 2010 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.components;
-
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Item;
-
-/**
- * @author TuxPaper
- * @created Feb 4, 2011
- *
- */
-public class InPaintInfo
-{
-	public Item item;
-	public int curCellIndex;
-	public Rectangle curCellBounds;
-
-	public InPaintInfo(Item item, int curCellIndex, Rectangle curCellBounds) {
-		this.item = item;
-		this.curCellIndex = curCellIndex;
-		this.curCellBounds = curCellBounds;
-	}
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/Legend.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/Legend.java
index 7723d6b..8f015b9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/Legend.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/Legend.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/LinkArea.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/LinkArea.java
index 80357d7..ac0c075 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/LinkArea.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/LinkArea.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jul 2, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/LinkLabel.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/LinkLabel.java
index c48bebd..d9a5b2f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/LinkLabel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/LinkLabel.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Nov-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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 40,000 euros
- * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  *
  */
 
@@ -28,9 +25,9 @@ import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Label;
-
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 
 public class 
@@ -89,7 +86,8 @@ LinkLabel
 	      public void mouseUp(MouseEvent arg0) {
 	      	Utils.launch((String) ((Label) arg0.widget).getData());
 	      }
-	    });		
+	    });	
+	    ClipboardCopy.addCopyToClipMenu( label );
 	}
 	
 	public static void updateLinkedLabel(Label label, String hyperlink) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/StringListChooser.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/StringListChooser.java
index 8c2b9d4..a5f87e8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/StringListChooser.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/StringListChooser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.components;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/BackGroundGraphic.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/BackGroundGraphic.java
index 48aca58..9f264ba 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/BackGroundGraphic.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/BackGroundGraphic.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Graphic.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Graphic.java
index f5d04da..b3792d7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Graphic.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Graphic.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/MultiPlotGraphic.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/MultiPlotGraphic.java
index efd267a..c777283 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/MultiPlotGraphic.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/MultiPlotGraphic.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/PieUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/PieUtils.java
index 7ba37fc..d82178a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/PieUtils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/PieUtils.java
@@ -2,11 +2,12 @@
  * Created on 19 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.components.graphics;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/PingGraphic.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/PingGraphic.java
index daa7cc0..4d97729 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/PingGraphic.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/PingGraphic.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Plot3D.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Plot3D.java
index 17bcc0c..6368614 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Plot3D.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Plot3D.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jun 26, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Scale.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Scale.java
index 389b708..8699529 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Scale.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/Scale.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ScaledGraphic.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ScaledGraphic.java
index 32fbca1..996eadf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ScaledGraphic.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ScaledGraphic.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/SpeedGraphic.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/SpeedGraphic.java
index 3a11506..2b2417e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/SpeedGraphic.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/SpeedGraphic.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ValueFormater.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ValueFormater.java
index 84d7ad5..3bf4d20 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ValueFormater.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ValueFormater.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ValueSource.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ValueSource.java
index 65d1774..ced1615 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ValueSource.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/graphics/ValueSource.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/shell/ShellFactory.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/shell/ShellFactory.java
index bba36a6..1dd10d2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/shell/ShellFactory.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/shell/ShellFactory.java
@@ -3,7 +3,7 @@ package org.gudy.azureus2.ui.swt.components.shell;
 /*
  * Created on 17-Mar-2005
  * Created by James Yeh
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -17,9 +17,6 @@ package org.gudy.azureus2.ui.swt.components.shell;
  * 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.
- *
  */
 
 import org.eclipse.swt.SWT;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/components/shell/ShellManager.java b/azureus2/src/org/gudy/azureus2/ui/swt/components/shell/ShellManager.java
index 2ba4fb5..f0acd07 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/components/shell/ShellManager.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/components/shell/ShellManager.java
@@ -16,7 +16,7 @@ import java.util.*;
 /*
  * Created on 17-Mar-2005
  * Created by James Yeh
- * Copyright (C) 2004-2005 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -30,9 +30,6 @@ import java.util.*;
  * 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.
- *
  */
 
 /**
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/BooleanParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/BooleanParameter.java
index f06e6c0..4d17f14 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/BooleanParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/BooleanParameter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 9 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/ButtonParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/ButtonParameter.java
index e5a4a75..d3727f5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/ButtonParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/ButtonParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -65,6 +62,12 @@ ButtonParameter
     button.setLayoutData(layoutData);
   }
 
+  public Button
+  getButton()
+  {
+	  return( button );
+  }
+  
   public Control getControl() 
   {
 	 return button;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/ChangeSelectionActionPerformer.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/ChangeSelectionActionPerformer.java
index 7fe7993..f5f3878 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/ChangeSelectionActionPerformer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/ChangeSelectionActionPerformer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/ColorParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/ColorParameter.java
index bdca4a5..5b33f1d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/ColorParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/ColorParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -60,16 +61,24 @@ public class ColorParameter extends Parameter implements ParameterListener {
   	super(name);
     sParamName = name;
     colorChooser = new Button(composite,SWT.PUSH);
-    r = COConfigurationManager.getIntParameter(name+".red",_r);
-    g = COConfigurationManager.getIntParameter(name+".green",_g);
-    b = COConfigurationManager.getIntParameter(name+".blue",_b);
+    if (name == null) {
+    	r = _r;
+    	g = _g;
+    	b = _b;
+    } else {
+      r = COConfigurationManager.getIntParameter(name+".red",_r);
+      g = COConfigurationManager.getIntParameter(name+".green",_g);
+      b = COConfigurationManager.getIntParameter(name+".blue",_b);
+      COConfigurationManager.addParameterListener(sParamName, this);
+    }
     updateButtonColor(composite.getDisplay(), r, g, b);
 
-    COConfigurationManager.addParameterListener(sParamName, this);
     
     colorChooser.addListener(SWT.Dispose, new Listener() {
       public void handleEvent(Event e) {
-        COConfigurationManager.removeParameterListener(sParamName, ColorParameter.this);
+      	if (sParamName != null) {
+      		COConfigurationManager.removeParameterListener(sParamName, ColorParameter.this);
+      	}
         if(img != null && ! img.isDisposed()) {
           img.dispose();          
         }
@@ -83,9 +92,17 @@ public class ColorParameter extends Parameter implements ParameterListener {
         RGB newColor = cd.open();
         if (newColor == null)
           return;
-        newColorChosen();
-        COConfigurationManager.setRGBParameter(name, newColor.red, newColor.green, newColor.blue);
-        newColorSet();
+        newColorChosen(newColor);
+        if (name != null) {
+        	COConfigurationManager.setRGBParameter(name, newColor.red, newColor.green, newColor.blue);
+        } else {
+        	r = newColor.red;
+        	g = newColor.green;
+        	b = newColor.blue;
+        	
+          updateButtonColor(colorChooser.getDisplay(), r, g, b);
+        }
+        newColorSet(newColor);
       }
     });
     
@@ -119,15 +136,27 @@ public class ColorParameter extends Parameter implements ParameterListener {
     updateButtonColor(colorChooser.getDisplay(), r, g, b);
   }
   
-  public void newColorChosen() {
+  public void newColorChosen(RGB newColor) {
     // subclasses can write their own code
   }
   
-  public void newColorSet() {
+  public void newColorSet(RGB newColor) {
 	  // subclasses can write their own code
   }
 
   public void setValue(Object value) {
   	// not needed, we already trap external changes
   }
+  
+  public void setColor(int _r, int _g, int _b) {
+		r = _r;
+		g = _g;
+		b = _b;
+
+		if (sParamName == null) {
+    	updateButtonColor(colorChooser.getDisplay(), r, g, b);
+		} else {
+			COConfigurationManager.setRGBParameter(sParamName, r, g, b);
+		}
+  }
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/ConfigParameterAdapter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/ConfigParameterAdapter.java
index 6312ff4..dc85267 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/ConfigParameterAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/ConfigParameterAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -27,6 +24,10 @@ import org.gudy.azureus2.core3.config.ParameterListener;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.ui.swt.config.generic.GenericParameterAdapter;
 
+/**
+ * A {@link GenericParameterAdapter} that stores/retrieves settings from
+ * {@link COConfigurationManager}
+ */
 public class ConfigParameterAdapter extends GenericParameterAdapter
 {
 	private static final int CHANGINGCOUNT_BREAKER = 5;
@@ -136,7 +137,9 @@ public class ConfigParameterAdapter extends GenericParameterAdapter
 
 		changingCount++;
 		try {
-			if (getBooleanValue(key) == value) {
+			if (getBooleanValue(key) == value
+					&& (COConfigurationManager.doesParameterNonDefaultExist(key)
+							|| COConfigurationManager.doesParameterDefaultExist(key))) {
 				changedExternally = true;
 				return;
 			}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/DirectoryParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/DirectoryParameter.java
index c98c339..8131b4c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/DirectoryParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/DirectoryParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 08-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/DualChangeSelectionActionPerformer.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/DualChangeSelectionActionPerformer.java
index 83716f4..ea9ace9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/DualChangeSelectionActionPerformer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/DualChangeSelectionActionPerformer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/ExclusiveSelectionActionPerformer.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/ExclusiveSelectionActionPerformer.java
index 3f1ac1e..b98f487 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/ExclusiveSelectionActionPerformer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/ExclusiveSelectionActionPerformer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/FileParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/FileParameter.java
index f3b2c7f..09ac7a6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/FileParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/FileParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-Nov-2006
  * Created by Allan Crooks
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/FloatParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/FloatParameter.java
index 34a1109..a996585 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/FloatParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/FloatParameter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 10 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/GenericActionPerformer.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/GenericActionPerformer.java
index 2d5acc1..6ee1805 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/GenericActionPerformer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/GenericActionPerformer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/IAdditionalActionPerformer.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/IAdditionalActionPerformer.java
index 360cce0..e186bde 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/IAdditionalActionPerformer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/IAdditionalActionPerformer.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/IParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/IParameter.java
index a01b6c9..cc65187 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/IParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/IParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/InfoParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/InfoParameter.java
index 02ba180..03b6eca 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/InfoParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/InfoParameter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 9 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/IntListParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/IntListParameter.java
index b5e6d1c..7198b8b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/IntListParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/IntListParameter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 10 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/IntParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/IntParameter.java
index d3ce700..4f86e3e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/IntParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/IntParameter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 10 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config;
 
@@ -26,6 +23,8 @@ import org.eclipse.swt.widgets.Control;
 import org.gudy.azureus2.ui.swt.config.generic.GenericIntParameter;
 
 /**
+ * Creates a config {@link Parameter} linked to a {@link GenericIntParameter}
+ * 
  * @author Olivier
  * 
  */
@@ -59,6 +58,7 @@ IntParameter
 				minValue, maxValue);
   }
   
+  // @see org.gudy.azureus2.ui.swt.config.Parameter#isInitialised()
   public boolean
   isInitialised()
   {
@@ -97,10 +97,12 @@ IntParameter
   	return( delegate.getValue());
   }
   
+  // @see org.gudy.azureus2.ui.swt.config.IParameter#setLayoutData(java.lang.Object)
   public void setLayoutData(Object layoutData) {
    delegate.setLayoutData( layoutData );
   }
   
+  // @see org.gudy.azureus2.ui.swt.config.IParameter#getControl()
   public Control
   getControl()
   {
@@ -115,12 +117,14 @@ IntParameter
 		delegate.setGenerateIntermediateEvents(generateIntermediateEvents);
 	}
 
+  // @see org.gudy.azureus2.ui.swt.config.Parameter#setValue(java.lang.Object)
   public void setValue(Object value) {
   	if (value instanceof Number) {
   		setValue(((Number)value).intValue());
   	}
   }
   
+  // @see org.gudy.azureus2.ui.swt.config.Parameter#getValueObject()
   public Object getValueObject() {
   	return new Integer(getValue());
   }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/IpFilterEditor.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/IpFilterEditor.java
index 857bdc1..4a68c93 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/IpFilterEditor.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/IpFilterEditor.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/LinkParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/LinkParameter.java
index 6454212..b329cfc 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/LinkParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/LinkParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/Parameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/Parameter.java
index c328d1a..116cc03 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/Parameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/Parameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -44,7 +41,9 @@ Parameter
 	private static AEMonitor	class_mon	= new AEMonitor( "Parameter:class" );
 
 	public Parameter(String sConfigID) {
-		config_adapter = new ConfigParameterAdapter( this, sConfigID );
+		if (sConfigID != null) {
+			config_adapter = new ConfigParameterAdapter( this, sConfigID );
+		}
 	}
 	
 	public boolean
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/ParameterChangeAdapter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/ParameterChangeAdapter.java
index 28d4616..c61cf37 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/ParameterChangeAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/ParameterChangeAdapter.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.config;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/ParameterChangeListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/ParameterChangeListener.java
index 674a64e..8b10bf8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/ParameterChangeListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/ParameterChangeListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on 22-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/PasswordParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/PasswordParameter.java
index 616ec2f..6615cc8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/PasswordParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/PasswordParameter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 8 september 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/RadioParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/RadioParameter.java
index 8976ddc..1848773 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/RadioParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/RadioParameter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 2004/02/15
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/StringAreaParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/StringAreaParameter.java
index bac5403..27ad785 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/StringAreaParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/StringAreaParameter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 9 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/StringListParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/StringListParameter.java
index c927701..0398b91 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/StringListParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/StringListParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/StringParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/StringParameter.java
index 1b12f6d..037726b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/StringParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/StringParameter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 9 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/TextAreaParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/TextAreaParameter.java
new file mode 100644
index 0000000..cb4c298
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/TextAreaParameter.java
@@ -0,0 +1,190 @@
+/*
+ * Created on 9 juil. 2003
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.config;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.*;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.plugins.ui.components.UIComponent;
+import org.gudy.azureus2.plugins.ui.components.UIPropertyChangeEvent;
+import org.gudy.azureus2.plugins.ui.components.UIPropertyChangeListener;
+import org.gudy.azureus2.pluginsimpl.local.ui.config.UITextAreaImpl;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
+
+
+public class 
+TextAreaParameter 
+	extends 	Parameter
+	implements	UIPropertyChangeListener
+{
+	private UITextAreaImpl	ui_text_area;
+	
+	private StyledText	text_area;
+  
+	public 
+	TextAreaParameter(
+		Composite 			composite,
+		UITextAreaImpl 		_ui_text_area) 
+	{
+		super( "" );
+  	
+		ui_text_area = _ui_text_area;
+  	
+		text_area = new StyledText(composite,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+		
+		ClipboardCopy.addCopyToClipMenu(
+				text_area,
+				new ClipboardCopy.copyToClipProvider()
+				{
+					public String 
+					getText() 
+					{
+						return( text_area.getText().trim());
+					}
+				});
+	
+		text_area.setText(ui_text_area.getText());
+
+		ui_text_area.addPropertyChangeListener(this);		
+	}
+	
+	public void 
+	setLayoutData(
+		Object layoutData ) 
+	{
+		if ( layoutData instanceof GridData ){
+
+			GridData gd = (GridData)layoutData;
+
+			Integer hhint = (Integer)ui_text_area.getProperty( UIComponent.PT_HEIGHT_HINT );
+
+			if ( hhint != null ){
+
+				gd.heightHint = hhint;
+			}
+		}
+
+		text_area.setLayoutData(layoutData);
+	}
+
+
+	public Control 
+	getControl() 
+	{
+		return( text_area );
+	}
+
+	public void 
+	setValue(
+		Object value) 
+	{
+	}
+	
+	public void 
+	propertyChanged(
+		final UIPropertyChangeEvent ev ) 
+	{
+		if ( text_area.isDisposed() || !ui_text_area.isVisible()){
+			
+			ui_text_area.removePropertyChangeListener( this );
+			
+			return;
+		}
+		
+		text_area.getDisplay().asyncExec(
+			new AERunnable()
+			{
+				public void 
+				runSupport() 
+				{
+					if ( text_area.isDisposed() || !ui_text_area.isVisible()){
+						
+						ui_text_area.removePropertyChangeListener( TextAreaParameter.this );
+						
+						return;
+					}
+
+					String old_value = (String)ev.getOldPropertyValue();
+					String new_value = (String) ev.getNewPropertyValue();
+
+					ScrollBar bar = text_area.getVerticalBar();
+
+					boolean max = bar.getSelection() == bar.getMaximum() - bar.getThumb();
+
+					int lineOffset = text_area.getLineCount() - text_area.getTopIndex();
+
+					if ( new_value.startsWith( old_value )){
+
+						String toAppend = new_value.substring(old_value.length());
+
+						if ( toAppend.length() == 0 ){
+
+							return;
+						}
+
+						StringBuffer builder = new StringBuffer(toAppend.length());
+
+						String[] lines = toAppend.split("\n");
+
+
+						for( int i=0;i<lines.length;i++){
+
+							String line = lines[i];
+
+							builder.append("\n");
+							builder.append(line);
+						}
+
+						text_area.append(builder.toString());
+
+					}else{
+
+						StringBuffer builder = new StringBuffer(new_value.length());
+
+						String[] lines = new_value.split("\n");
+
+						for( int i=0;i<lines.length;i++){
+
+							String line = lines[i];
+
+							if (line != lines[0] ){
+
+								builder.append("\n");
+							}
+
+							builder.append(line);
+						}
+
+						text_area.setText(builder.toString());
+					}
+
+					if ( max ){
+
+						bar.setSelection(bar.getMaximum()-bar.getThumb());
+
+						text_area.setTopIndex(text_area.getLineCount()-lineOffset);
+
+						text_area.redraw();
+					}
+
+				}
+			});
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/UISWTParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/UISWTParameter.java
index 8cb30d5..aaa5124 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/UISWTParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/UISWTParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,15 +14,14 @@
  * 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.config;
 
 import org.eclipse.swt.widgets.Control;
 
 /**
+ * For plugins to add a generic SWT widget to the config page
+ * 
  * @author Allan Crooks
  *
  */
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericBooleanParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericBooleanParameter.java
index 481c765..3134f15 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericBooleanParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericBooleanParameter.java
@@ -1,6 +1,6 @@
 /*
  * Created on 9 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.config.generic;
 
@@ -171,6 +168,17 @@ public class GenericBooleanParameter
 			});
 		}
 	}
+	
+	public void refresh() {
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				boolean selected = isSelected();
+				if (checkBox.getSelection() != selected) {
+					checkBox.setSelection(selected);
+				}
+			}
+		});
+	}
 
 	private void debug(String string) {
 		System.out.println("[GenericBooleanParameter:" + name + "] " + string);
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericFloatParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericFloatParameter.java
new file mode 100644
index 0000000..37f046d
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericFloatParameter.java
@@ -0,0 +1,153 @@
+/*
+ * Created on 10 juil. 2003
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.config.generic;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.ui.swt.Utils;
+
+public class GenericFloatParameter {
+
+  Text inputField;
+  float fMinValue = 0;
+  float fMaxValue = -1;
+  boolean allowZero = false;
+	private GenericParameterAdapter adapter;
+	private String name;
+
+  public GenericFloatParameter(GenericParameterAdapter adapter,Composite composite, final String name) {
+    adapter.getFloatValue( name );
+    initialize(adapter,composite,name);
+  }
+
+  public GenericFloatParameter(GenericParameterAdapter adapter,Composite composite, final String name, 
+                        float minValue, float maxValue, boolean allowZero,
+                        int digitsAfterDecimal) {
+    adapter.getFloatValue( name );
+    initialize(adapter,composite,name);
+    fMinValue = minValue;
+    fMaxValue = maxValue;
+    this.allowZero = allowZero;
+  }
+  
+    
+  public void initialize(final GenericParameterAdapter adapter,Composite composite, final String name) {
+ 
+    this.adapter = adapter;
+		this.name = name;
+		inputField = new Text(composite, SWT.BORDER | SWT.RIGHT);
+    float value = adapter.getFloatValue( name );
+    inputField.setText(String.valueOf(value));
+    inputField.addListener(SWT.Verify, new Listener() {
+      public void handleEvent(Event e) {
+        String text = e.text;
+        char[] chars = new char[text.length()];
+        text.getChars(0, chars.length, chars, 0);
+        for (int i = 0; i < chars.length; i++) {
+          if ( !((chars[i] >= '0' && chars[i] <= '9') || chars[i] == '.') ) {
+            e.doit = false;
+            return;
+          }
+        }
+      }
+    });
+
+    inputField.addListener(SWT.Modify, new Listener() {
+      public void handleEvent(Event event) {
+        try {
+          float val = Float.parseFloat(inputField.getText());
+          if (val < fMinValue) {
+            if (!(allowZero && val == 0)) {
+            	val = fMinValue;
+            }
+          }
+          if (val > fMaxValue) {
+            if (fMaxValue > -1) {
+              val = fMaxValue;
+            }
+          }
+          // don't inform of intermediate values as stupid to do so
+          // adapter.setFloatValue(name, val);
+        }
+        catch (Exception e) {}
+      }
+    });
+
+    inputField.addListener(SWT.FocusOut, new Listener() {
+      public void handleEvent(Event event) {
+        try {
+          float val = Float.parseFloat(inputField.getText());
+          if (val < fMinValue) {
+            if (!(allowZero && val == 0)) {
+              inputField.setText(String.valueOf(fMinValue));
+              val	= fMinValue;
+            }
+          }
+          if (val > fMaxValue) {
+            if (fMaxValue > -1) {
+            	inputField.setText(String.valueOf(fMaxValue));
+            	val = fMaxValue;
+            }
+          }
+          adapter.setFloatValue(name, val);
+        }
+        catch (Exception e) {}
+      }
+    });
+  }
+  
+  public void
+  setValue(
+	final float	value )
+  {
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				if ( !inputField.isDisposed()){
+					 inputField.setText(String.valueOf(value));
+				}
+			}
+		});
+  }
+
+  public void
+  refresh()
+  {
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				if ( !inputField.isDisposed()){
+					 inputField.setText(String.valueOf(adapter.getFloatValue(name)));
+				}
+			}
+		});
+  }
+  
+  public void setLayoutData(Object layoutData) {
+    inputField.setLayoutData(layoutData);
+  }
+  
+  public Control
+  getControl()
+  {
+  	return( inputField );
+  }
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericIntParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericIntParameter.java
index 27bd05f..c9828ad 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericIntParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericIntParameter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -28,15 +25,18 @@ import org.eclipse.swt.widgets.*;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.ui.swt.Utils;
 
+/**
+ * SWT widgets representing an Int Parameter, backed by a {@link GenericParameterAdapter}
+ */
 public class GenericIntParameter
 {
 	private static boolean DEBUG = false;
 
 	private GenericParameterAdapter adapter;
 
-	private int iMinValue = 0;
+	private int iMinValue = Integer.MIN_VALUE;
 
-	private int iMaxValue = -1;
+	private int iMaxValue = Integer.MAX_VALUE;
 
 	private int iDefaultValue;
 
@@ -72,6 +72,14 @@ public class GenericIntParameter
 	public GenericIntParameter(GenericParameterAdapter adapter,
 			Composite composite, String name, int minValue, int maxValue) {
 		iDefaultValue = adapter.getIntValue(name);
+		
+		if ( maxValue < minValue ){
+			Debug.out( "max < min, not good" );
+				// common mistake to use -1 to indicate no-limit
+
+			maxValue = Integer.MAX_VALUE;
+		}
+		
 		iMinValue = minValue;
 		iMaxValue = maxValue;
 		initialize(adapter, composite, name);
@@ -181,7 +189,7 @@ public class GenericIntParameter
 
 	public void setMinimumValue(final int value) {
 		iMinValue = value;
-		if (iMinValue > 0 && getValue() < iMinValue) {
+		if (iMinValue != Integer.MIN_VALUE && getValue() < iMinValue) {
 			setValue(iMinValue);
 		}
 		Utils.execSWTThread(new AERunnable() {
@@ -191,14 +199,14 @@ public class GenericIntParameter
 		});
 	}
 
-	public void setMaximumValue(int value) {
+	public void setMaximumValue(final int value) {
 		iMaxValue = value;
-		if (iMaxValue != -1 && getValue() > iMaxValue) {
+		if (iMaxValue != Integer.MAX_VALUE && getValue() > iMaxValue) {
 			setValue(iMaxValue);
 		}
 		Utils.execSWTThread(new AERunnable() {
 			public void runSupport() {
-				spinner.setMaximum(iMaxValue == -1 ? Integer.MAX_VALUE : iMaxValue);
+				spinner.setMaximum(value);
 			}
 		});
 	}
@@ -209,9 +217,9 @@ public class GenericIntParameter
 
 	public void setValue(int value) {
 		int newValue;
-		if (iMaxValue != -1 && value > iMaxValue) {
+		if (iMaxValue != Integer.MAX_VALUE && value > iMaxValue) {
 			newValue = iMaxValue;
-		} else if (iMinValue > 0 && value < iMinValue) {
+		} else if (iMinValue != Integer.MIN_VALUE && value < iMinValue) {
 			newValue = iMinValue;
 		} else {
 			newValue = value;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericParameterAdapter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericParameterAdapter.java
index 4542229..f16eb86 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericParameterAdapter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/generic/GenericParameterAdapter.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -78,6 +75,21 @@ GenericParameterAdapter
 		throw( new RuntimeException( "Not implemented" ));
 	}
 	
+	public float
+	getFloatValue(
+		String		key )
+	{
+		throw( new RuntimeException( "Not implemented" ));
+	}
+	
+	public void
+	setFloatValue(
+		String		key,
+		float		value )
+	{
+		throw( new RuntimeException( "Not implemented" ));
+	}
+	
 	
 	public void
 	informChanged(
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginBooleanParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginBooleanParameter.java
index 6e799c3..339bc2d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginBooleanParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginBooleanParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginColorParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginColorParameter.java
index c91360d..e7089f8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginColorParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginColorParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginDirectoryParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginDirectoryParameter.java
index 31ac8a5..400e7fb 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginDirectoryParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginDirectoryParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginFileParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginFileParameter.java
index 1daeab2..85cb34c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginFileParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginFileParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginIntParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginIntParameter.java
index b92c2ef..0fd251b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginIntParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginIntParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginIntsParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginIntsParameter.java
index 8f9c4b4..8c895ad 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginIntsParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginIntsParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginParameter.java
index 0509e91..e269888 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginParameterImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginParameterImpl.java
index 0983c50..1ba7c0f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginParameterImpl.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginParameterImpl.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginStringParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginStringParameter.java
index 25dc3f3..8e804e8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginStringParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginStringParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginStringsParameter.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginStringsParameter.java
index 236b344..7ab73c6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginStringsParameter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/plugins/PluginStringsParameter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/ConfigureWizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/ConfigureWizard.java
index 232f261..651e074 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/ConfigureWizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/ConfigureWizard.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/FilePanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/FilePanel.java
index 201e5c0..ed17e52 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/FilePanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/FilePanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/FinishPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/FinishPanel.java
index db454f0..8c4bb01 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/FinishPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/FinishPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/LanguagePanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/LanguagePanel.java
index efaa704..a44eadc 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/LanguagePanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/LanguagePanel.java
@@ -1,6 +1,6 @@
 /*
  * Created on Feb 28, 2006 8:54:43 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.config.wizard;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/NatPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/NatPanel.java
index 573ef73..1bf0092 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/NatPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/NatPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/TransferPanel2.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/TransferPanel2.java
index 0b89c6e..3415a02 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/TransferPanel2.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/TransferPanel2.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/WelcomePanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/WelcomePanel.java
index b458b09..c68db65 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/WelcomePanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/config/wizard/WelcomePanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -28,11 +29,11 @@ import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.layout.RowLayout;
 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.Utils;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.wizard.AbstractWizardPanel;
 import org.gudy.azureus2.ui.swt.wizard.IWizardPanel;
@@ -167,6 +168,7 @@ public class WelcomePanel extends AbstractWizardPanel {
 	      	Utils.launch((String) ((Label) arg0.widget).getData());
 	      }
 	    });
+	    ClipboardCopy.addCopyToClipMenu( linkLabel );
 	    
 	    final Label linkLabel1 = new Label(gWiki, SWT.NULL);
 	    linkLabel1.setText( (userMode == 1)?MessageText.getString(messTexts[3]):"");
@@ -184,6 +186,7 @@ public class WelcomePanel extends AbstractWizardPanel {
 	      	Utils.launch((String) ((Label) arg0.widget).getData());
 	      }
 	    });
+	    ClipboardCopy.addCopyToClipMenu( linkLabel1 );
 
     
     Listener radioGroup = new Listener () {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateCellText.java b/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateCellText.java
index 99b20f6..c89a143 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateCellText.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateCellText.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 28, 2006 8:20:02 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.debug;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateImage.java b/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateImage.java
index 944eee5..dd040a0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateImage.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateImage.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 28, 2006 5:03:50 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.debug;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateShell.java b/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateShell.java
index c82e3d6..b4c51c2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateShell.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateShell.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 28, 2006 4:51:20 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.debug;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateTab.java b/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateTab.java
index a07fb3c..665bd04 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateTab.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/debug/ObfusticateTab.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 28, 2006 10:45:31 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.debug;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/debug/UIDebugGenerator.java b/azureus2/src/org/gudy/azureus2/ui/swt/debug/UIDebugGenerator.java
index b71a017..97bd58e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/debug/UIDebugGenerator.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/debug/UIDebugGenerator.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 28, 2006 4:31:42 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.debug;
 
@@ -28,7 +25,6 @@ import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.layout.*;
 import org.eclipse.swt.widgets.*;
-
 import org.bouncycastle.util.encoders.Base64;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.logging.LogEvent;
@@ -363,6 +359,21 @@ public class UIDebugGenerator
 			});
 			addFilesToZip(out, files);
 
+			// recent crashes from temp dir
+			
+			try{
+				File temp_file = File.createTempFile( "AZU", "tmp" );
+				
+				files = temp_file.getParentFile().listFiles(new FileFilter() {
+					public boolean accept(File pathname) {
+						return (pathname.getName().startsWith("hs_err") && pathname.lastModified() > ago);
+					}
+				});
+				addFilesToZip(out, files);
+				temp_file.delete();
+			}catch( Throwable e ){	
+			}
+			
 			// recent errors from OSX java log dir
 			File javaLogPath = new File(System.getProperty("user.home"), "Library"
 					+ File.separator + "Logs" + File.separator + "Java");
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/donations/DonationWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/donations/DonationWindow.java
index d585a9d..5cfd8c8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/donations/DonationWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/donations/DonationWindow.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 9, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -18,8 +20,6 @@
 
 package org.gudy.azureus2.ui.swt.donations;
  
-import java.util.Locale;
-
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.browser.*;
 import org.eclipse.swt.events.*;
@@ -27,7 +27,6 @@ import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.widgets.Display;
 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.stats.transfer.OverallStats;
@@ -36,6 +35,7 @@ import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.plugins.utils.FeatureManager;
 import org.gudy.azureus2.plugins.utils.FeatureManager.FeatureDetails;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
 import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
@@ -61,9 +61,9 @@ public class DonationWindow
 
 	private static Shell shell = null;
 
-	private static Browser browser;
+	private static BrowserWrapper browser;
 
-	private static BrowserFunction browserFunction;
+	private static BrowserWrapper.BrowserFunction browserFunction;
 
 	public static void checkForDonationPopup() {
 		if (shell != null) {
@@ -166,8 +166,8 @@ public class DonationWindow
 			return;
 		}
 		final Shell parentShell = Utils.findAnyShell();
-		shell = ShellFactory.createShell(parentShell, SWT.BORDER
-				| SWT.APPLICATION_MODAL | SWT.TITLE);
+		shell = ShellFactory.createShell(parentShell,
+				SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
 		shell.setLayout(new FillLayout());
 		if (parentShell != null) {
 			parentShell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
@@ -176,7 +176,7 @@ public class DonationWindow
 		shell.addTraverseListener(new TraverseListener() {
 			public void keyTraversed(TraverseEvent e) {
 				if (e.detail == SWT.TRAVERSE_ESCAPE) {
-					shell.dispose();
+					e.widget.dispose();
 					e.doit = false;
 				}
 			}
@@ -209,77 +209,80 @@ public class DonationWindow
 			}
 		});
 		
-		browserFunction = new BrowserFunction(browser, "sendDonationEvent") {
-			public Object function(Object[] arguments) {
-
-				if (shell == null || shell.isDisposed()) {
-					return null;
-				}
-				
-				if (arguments == null) {
-					Debug.out("Invalid sendDonationEvent null ");
-					return null;
-				}
-				if (arguments.length < 1) {
-					Debug.out("Invalid sendDonationEvent length " + arguments.length + " not 1");
-					return null;
-				}
-				if (!(arguments[0] instanceof String)) {
-					Debug.out("Invalid sendDonationEvent "
-							+ (arguments[0] == null ? "NULL"
-									: arguments.getClass().getSimpleName()) + " not String");
-					return null;
-				}
-
-				String text = (String) arguments[0];
-				if (text.contains("page-loaded")) {
-					pageLoadedOk = true;
-					COConfigurationManager.setParameter("donations.count",
-							COConfigurationManager.getLongParameter("donations.count", 1) + 1);
-					Utils.centreWindow(shell);
-					if (parentShell != null) {
-						parentShell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
+		browserFunction = browser.addBrowserFunction(
+			"sendDonationEvent",
+			new BrowserWrapper.BrowserFunction()
+			{
+				public Object function(Object[] arguments) {
+	
+					if (shell == null || shell.isDisposed()) {
+						return null;
 					}
-					shell.open();
-				} else if (text.contains("reset-ask-time")) {
-					int time = reAskEveryHours;
-					String[] strings = text.split(" ");
-					if (strings.length > 1) {
-						try {
-							time = Integer.parseInt(strings[1]);
-						} catch (Throwable t) {
-						}
+					
+					if (arguments == null) {
+						Debug.out("Invalid sendDonationEvent null ");
+						return null;
+					}
+					if (arguments.length < 1) {
+						Debug.out("Invalid sendDonationEvent length " + arguments.length + " not 1");
+						return null;
 					}
-					resetAskTime(time);
-				} else if (text.contains("never-ask-again")) {
-					neverAskAgain();
-				} else if (text.contains("close")) {
-					Utils.execSWTThreadLater(0, new AERunnable() {	
-						public void runSupport() {
-							if (shell != null && !shell.isDisposed()) {
-								shell.dispose();
+					if (!(arguments[0] instanceof String)) {
+						Debug.out("Invalid sendDonationEvent "
+								+ (arguments[0] == null ? "NULL"
+										: arguments.getClass().getSimpleName()) + " not String");
+						return null;
+					}
+	
+					String text = (String) arguments[0];
+					if (text.contains("page-loaded")) {
+						pageLoadedOk = true;
+						COConfigurationManager.setParameter("donations.count",
+								COConfigurationManager.getLongParameter("donations.count", 1) + 1);
+						Utils.centreWindow(shell);
+						if (parentShell != null) {
+							parentShell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
+						}
+						shell.open();
+					} else if (text.contains("reset-ask-time")) {
+						int time = reAskEveryHours;
+						String[] strings = text.split(" ");
+						if (strings.length > 1) {
+							try {
+								time = Integer.parseInt(strings[1]);
+							} catch (Throwable t) {
 							}
 						}
-					});
-				} else if (text.startsWith("open-url")) {
-					String url = text.substring(9);
-					Utils.launch(url);
-				} else if (text.startsWith("set-size")) {
-					String[] strings = text.split(" ");
-					if (strings.length > 2) {
-						try {
-							int w = Integer.parseInt(strings[1]);
-							int h = Integer.parseInt(strings[2]);
-
-							Rectangle computeTrim = shell.computeTrim(0, 0, w, h);
-							shell.setSize(computeTrim.width, computeTrim.height);
-						} catch (Exception e) {
+						resetAskTime(time);
+					} else if (text.contains("never-ask-again")) {
+						neverAskAgain();
+					} else if (text.contains("close")) {
+						Utils.execSWTThreadLater(0, new AERunnable() {	
+							public void runSupport() {
+								if (shell != null && !shell.isDisposed()) {
+									shell.dispose();
+								}
+							}
+						});
+					} else if (text.startsWith("open-url")) {
+						String url = text.substring(9);
+						Utils.launch(url);
+					} else if (text.startsWith("set-size")) {
+						String[] strings = text.split(" ");
+						if (strings.length > 2) {
+							try {
+								int w = Integer.parseInt(strings[1]);
+								int h = Integer.parseInt(strings[2]);
+	
+								Rectangle computeTrim = shell.computeTrim(0, 0, w, h);
+								shell.setSize(computeTrim.width, computeTrim.height);
+							} catch (Exception e) {
+							}
 						}
 					}
+					return null;
 				}
-				return null;
-			}
-		};
+			});
 
 		browser.addStatusTextListener(new StatusTextListener() {
 			String last = null;
@@ -316,29 +319,49 @@ public class DonationWindow
 				+ "&uphours=" + upHours + "&azid=" + azid + "&sourceref="
 				+ UrlUtils.encode(sourceRef);
 
-		SimpleTimer.addEvent("donation.pageload", SystemTime.getOffsetTime(6000),
-				new TimerEventPerformer() {
-					public void perform(TimerEvent event) {
-						if (!pageLoadedOk) {
-							Utils.execSWTThread(new AERunnable() {
-								public void runSupport() {
-									Debug.out("Page Didn't Load:" + url);
-									shell.dispose();
-									if (showNoLoad) {
-										new MessageBoxShell(SWT.OK,
-  											MessageText.getString("DonationWindow.noload.title"),
-  											MessageText.getString("DonationWindow.noload.text",
-														new String[] {
-															url
-														})).open(null);
+		if ( !browser.isFake()){
+			
+			SimpleTimer.addEvent("donation.pageload", SystemTime.getOffsetTime(6000),
+					new TimerEventPerformer() {
+						public void perform(TimerEvent event) {
+							if (!pageLoadedOk) {
+								Utils.execSWTThread(new AERunnable() {
+									public void runSupport() {
+										Debug.out("Page Didn't Load:" + url);
+										shell.dispose();
+										if (showNoLoad) {
+											new MessageBoxShell(SWT.OK,
+	  											MessageText.getString("DonationWindow.noload.title"),
+	  											MessageText.getString("DonationWindow.noload.text",
+															new String[] {
+																url
+															})).open(null);
+										}
 									}
-								}
-							});
+								});
+							}
 						}
-					}
-				});
-
+					});
+		}
+		
 		browser.setUrl(url);
+		
+		if ( browser.isFake()){
+			
+			browser.setUrl( "http://www.vuze.com/donation/donate.php" );
+				
+			browser.setText( "Please follow the link to donate via an external browser" );
+			
+			shell.setSize( 400, 500 );
+			
+			Utils.centreWindow(shell);
+			
+			if (parentShell != null) {
+				parentShell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
+			}
+			
+			shell.open();
+		}
 	}
 
 	/**
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizard.java
index 25c36bb..57ba8fe 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizard.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardFinishPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardFinishPanel.java
index 6c917fb..7ca35c7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardFinishPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardFinishPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardInputPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardInputPanel.java
index 9dcf0f4..7168195 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardInputPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardInputPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardOutputPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardOutputPanel.java
index fc6830e..5480871 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardOutputPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/exporttorrent/wizard/ExportTorrentWizardOutputPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/help/AboutWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/help/AboutWindow.java
index 920e012..1de7ff8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/help/AboutWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/help/AboutWindow.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -27,7 +28,6 @@ import org.eclipse.swt.graphics.*;
 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.core3.util.*;
@@ -69,8 +69,7 @@ public class AboutWindow {
     
     paintColorTo = 0;
 
-    final Shell window = ShellFactory.createMainShell((Constants.isOSX)
-				? SWT.DIALOG_TRIM : (SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL));
+    final Shell window = ShellFactory.createMainShell(SWT.DIALOG_TRIM);
     Utils.setShellIcon(window);
     final Display display = window.getDisplay();
 
@@ -120,16 +119,21 @@ public class AboutWindow {
     labelImage.setLayoutData(gridData);
     labelImage.addPaintListener(new PaintListener() {
 			public void paintControl(PaintEvent e) {
-				Rectangle boundsColor = imgSrc.getBounds();
-				int ofs = (labelImage.getSize().x - boundsColor.width) / 2;
-				if (paintColorTo > 0) {
-					e.gc.drawImage(imgSrc, 0, 0, paintColorTo, boundsColor.height, ofs, 10, 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 + ofs, 10, imgBounds.width - paintColorTo - 1, imgBounds.height);
+				try{
+					Rectangle boundsColor = imgSrc.getBounds();
+					int ofs = (labelImage.getSize().x - boundsColor.width) / 2;
+					if (paintColorTo > 0) {
+						e.gc.drawImage(imgSrc, 0, 0, paintColorTo, boundsColor.height, ofs, 10, 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 + ofs, 10, imgBounds.width - paintColorTo - 1, imgBounds.height);
+					}
+				}catch( Throwable f ){
+					// seen some 'argument not valid errors spewed here, couldn't track down
+					// the cause though :( parg.
 				}
 			}
 		});
@@ -149,12 +153,21 @@ public class AboutWindow {
     gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL);
     gridData.verticalSpan = 1;
     gSys.setLayoutData(gridData);
+    
+    String swt = "";
+    if (Utils.isGTK) {
+    	try {
+    		swt = "/" + System.getProperty("org.eclipse.swt.internal.gtk.version");
+			} catch (Throwable e1) {
+				// TODO Auto-generated catch block
+			}
+    }
 
     Text txtSysInfo = new Text(gSys, SWT.READ_ONLY | SWT.MULTI | SWT.WRAP);
     txtSysInfo.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
     txtSysInfo.setText("Java " + System.getProperty("java.version") + "\n "
 				+ System.getProperty("java.vendor") + "\n"
-				+ "SWT v" + SWT.getVersion() + ", " + SWT.getPlatform() + "\n"
+				+ "SWT v" + SWT.getVersion() + ", " + SWT.getPlatform() + swt + "\n"
 				+ System.getProperty("os.name") + " v"
 				+ System.getProperty("os.version") + ", "
 				+ System.getProperty("os.arch") + "\n"
@@ -167,20 +180,22 @@ public class AboutWindow {
 		final String[][] link = {
 			{
 				"homepage",
-				"sourceforge",
 				"bugreports",
 				"forumdiscussion",
 				"wiki",
+				"!Vuze Wiki Hidden Service (I2P)",
+				"!Vuze Wiki Hidden Service (Tor)",
 				"contributors",
 				"!EULA",
 				"!Privacy Policy"
 			},
 			{
 				"http://www.vuze.com",
-				"http://sourceforge.net/projects/azureus",
 				"http://forum.vuze.com/forum.jspa?forumID=124",
 				"http://forum.vuze.com",
 				Constants.AZUREUS_WIKI,
+				"http://que23xpe7o3lzq6auv6stb4bha7ddavrlgqdv2cuhgd36fgfmp6q.b32.i2p/",
+				"http://dr5aamfveql2b34p.onion/",
 				Constants.AZUREUS_WIKI + "Contributors",
 				"http://www.vuze.com/corp/terms.php",
 				"http://www.vuze.com/corp/privacy.php"
@@ -204,10 +219,11 @@ public class AboutWindow {
         public void mouseDoubleClick(MouseEvent arg0) {
         	Utils.launch((String) ((CLabel) arg0.widget).getData());
         }
-        public void mouseDown(MouseEvent arg0) {
+        public void mouseUp(MouseEvent arg0) {
         	Utils.launch((String) ((CLabel) arg0.widget).getData());
         }
       });
+      ClipboardCopy.addCopyToClipMenu( linkLabel );
     }
     
     Label labelOwner = new Label(window, SWT.WRAP | SWT.CENTER);
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/help/HealthHelpWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/help/HealthHelpWindow.java
index 59e3158..1f1d542 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/help/HealthHelpWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/help/HealthHelpWindow.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizard.java
index f9dea39..bebadc1 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizard.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardFinishPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardFinishPanel.java
index eb6a82b..9ad4993 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardFinishPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardFinishPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardInputPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardInputPanel.java
index 5488f34..d9dda74 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardInputPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardInputPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardOutputPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardOutputPanel.java
index 5521c32..89cdaa7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardOutputPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/importtorrent/wizard/ImportTorrentWizardOutputPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/ChooseServicePanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/ChooseServicePanel.java
index e7eaf71..d0035b4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/ChooseServicePanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/ChooseServicePanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/IpCheckerWizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/IpCheckerWizard.java
index 8604139..69aa846 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/IpCheckerWizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/IpCheckerWizard.java
@@ -5,7 +5,8 @@
  * 
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/IpSetterCallBack.java b/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/IpSetterCallBack.java
index 6a09b35..d67ea0b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/IpSetterCallBack.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/IpSetterCallBack.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/ProgressPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/ProgressPanel.java
index edfd059..5df0064 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/ProgressPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/ipchecker/ProgressPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/ClipboardCopy.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/ClipboardCopy.java
index 0d8b954..14fe349 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/ClipboardCopy.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/ClipboardCopy.java
@@ -2,11 +2,12 @@
  * Created on 3 mai 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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 Alle Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  */
 package org.gudy.azureus2.ui.swt.mainwindow;
 
@@ -36,6 +34,7 @@ import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.MenuItem;
 import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.ui.swt.Utils;
 
 
 /**
@@ -46,11 +45,28 @@ public class ClipboardCopy {
   
   public static void
   copyToClipBoard(
-    String    data )
+    final String    data )
   {
-	  new Clipboard(SWTThread.getInstance().getDisplay()).setContents(
-			  new Object[] {data.replaceAll("\\x00", " " )  }, 
-			  new Transfer[] {TextTransfer.getInstance()});
+	  Runnable do_it = 
+		new Runnable()
+	  	{
+		  public void
+		  run()
+		  {
+			  new Clipboard(SWTThread.getInstance().getDisplay()).setContents(
+					  new Object[] {data.replaceAll("\\x00", " " )  }, 
+					  new Transfer[] {TextTransfer.getInstance()});
+		  }
+	  	};
+	  	
+	  if ( Utils.isSWTThread()){
+		  
+		  do_it.run();
+		  
+	  }else{
+		  
+		  Utils.execSWTThread( do_it );
+	  }
   }
   
   public static void
@@ -86,7 +102,18 @@ public class ClipboardCopy {
 
 				  MenuItem   item = new MenuItem( menu,SWT.NONE );
 
-				  item.setText( MessageText.getString( "ConfigView.copy.to.clipboard.tooltip"));
+				  String	msg_text_id;
+				  
+				  if ( provider instanceof copyToClipProvider2 ){
+					  
+					  msg_text_id = ((copyToClipProvider2)provider).getMenuResource();
+					  
+				  }else{
+					  
+					  msg_text_id = "label.copy.to.clipboard";
+				  }
+				  
+				  item.setText( MessageText.getString( msg_text_id ));
 
 				  item.addSelectionListener(
 						  new SelectionAdapter()
@@ -120,10 +147,34 @@ public class ClipboardCopy {
 		  });
   }
   
+  public static void
+  addCopyToClipMenu(
+	final Control				control )
+  {
+	  addCopyToClipMenu(
+		control,
+		new copyToClipProvider()
+		{
+			  public String
+			  getText()
+			  {
+				  return((String)control.getData());
+			  }
+		});
+  }
+  
   public interface
   copyToClipProvider
   {
 	  public String
 	  getText();
   }
+  
+  public interface
+  copyToClipProvider2
+  	extends copyToClipProvider
+  {
+	  public String
+	  getMenuResource();
+  }
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/Colors.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/Colors.java
index bbe0d81..b5fdc45 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/Colors.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/Colors.java
@@ -1,11 +1,12 @@
 /*
  * Created on 2 mai 2004 Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,9 +16,6 @@
  * 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 Alle Lenotre, La Grille Royale,
- * 78600 Le Mesnil le Roi, France.
  */
 package org.gudy.azureus2.ui.swt.mainwindow;
 import java.util.ArrayList;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/DebugMenuHelper.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/DebugMenuHelper.java
index a921bdd..6f9d8cd 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/DebugMenuHelper.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/DebugMenuHelper.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.mainwindow;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/HSLColor.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/HSLColor.java
index 9db5cf1..33ce095 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/HSLColor.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/HSLColor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.mainwindow;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainMenu.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainMenu.java
index 21e9832..a43c48f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainMenu.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainMenu.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.mainwindow;
 
 import org.eclipse.swt.widgets.Menu;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainStatusBar.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainStatusBar.java
index 599f39f..7135546 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainStatusBar.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainStatusBar.java
@@ -2,20 +2,19 @@
  * Created on Sep 13, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainWindow.java
index 1060e7e..817d6de 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMainWindow.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.mainwindow;
 
 import org.eclipse.swt.graphics.Rectangle;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMenuConstants.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMenuConstants.java
index bb91909..8801230 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMenuConstants.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/IMenuConstants.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.mainwindow;
 
 
@@ -145,6 +163,8 @@ public interface IMenuConstants
 	public static final String MENU_ID_STATS = "MainWindow.menu.view.stats";
 
 	public static final String MENU_ID_NAT_TEST = "MainWindow.menu.tools.nattest";
+	
+	public static final String MENU_ID_NET_STATUS = "MainWindow.menu.tools.netstat";
 
 	public static final String MENU_ID_SPEED_TEST = "MainWindow.menu.tools.speedtest";
 
@@ -180,6 +200,8 @@ public interface IMenuConstants
 	
 	public static final String MENU_ID_BETA_PROG = "MainWindow.menu.beta";
 
+	public static final String MENU_ID_VOTE = "MainWindow.menu.vote";
+
 	public static final String MENU_ID_PLUGINS_INSTALL = "MainWindow.menu.plugins.installPlugins";
 
 	public static final String MENU_ID_PLUGINS_UNINSTALL = "MainWindow.menu.plugins.uninstallPlugins";
@@ -194,6 +216,8 @@ public interface IMenuConstants
 
 	public static final String MENU_ID_COMMUNITY_FORUMS = "MainWindow.menu.community.forums";
 	
+	public static final String MENU_ID_COMMUNITY_CHAT = "MainWindow.menu.community.chat";
+	
 	public static final String MENU_ID_COMMUNITY_WIKI = "MainWindow.menu.community.wiki";
 
 	public static final String MENU_ID_HELP_SUPPORT = "MainWindow.menu.help.support";
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/ListenerNeedingCoreRunning.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/ListenerNeedingCoreRunning.java
index e1b5989..a3d13ae 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/ListenerNeedingCoreRunning.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/ListenerNeedingCoreRunning.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.mainwindow;
 
 import org.eclipse.swt.widgets.Event;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MainMenu.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MainMenu.java
index 3fa3ca7..5238c3f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MainMenu.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MainMenu.java
@@ -2,11 +2,12 @@
  * Created on 4 mai 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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 Alle Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  */
 package org.gudy.azureus2.ui.swt.mainwindow;
 
@@ -237,7 +235,7 @@ public class MainMenu
 			MenuFactory.addPairingMenuItem(viewMenu);
 			//MenuFactory.addDetailedListMenuItem(viewMenu);
 			//MenuFactory.addDeviceManagerMenuItem(viewMenu);
-			//MenuFactory.addSubscriptionMenuItem(viewMenu);
+			MenuFactory.addSubscriptionMenuItem(viewMenu);
 
 			if (PluginsMenuHelper.getInstance().buildViewMenu(viewMenu, viewMenu.getShell()) && Constants.isOSX) {
 				MenuFactory.addSeparatorMenuItem(viewMenu);
@@ -332,6 +330,7 @@ public class MainMenu
 		if (false == SystemProperties.isJavaWebStartInstance()) {
 			MenuFactory.addCheckUpdateMenuItem(helpMenu);
 			MenuFactory.addBetaMenuItem(helpMenu);
+			MenuFactory.addVoteMenuItem(helpMenu);
 		}
 		MenuFactory.addDonationMenuItem(helpMenu);
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MainStatusBar.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MainStatusBar.java
index 627d587..157d879 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MainStatusBar.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MainStatusBar.java
@@ -1,6 +1,6 @@
 /*
  * Created on Mar 20, 2006 6:40:14 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,14 +13,13 @@
  * 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.mainwindow;
 
 import java.text.NumberFormat;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.CLabel;
@@ -28,7 +27,6 @@ import org.eclipse.swt.events.*;
 import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.layout.*;
 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.TransferSpeedValidator;
@@ -62,7 +60,8 @@ import com.aelitis.azureus.plugins.dht.DHTPlugin;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.UIStatusTextClickListener;
-import com.aelitis.azureus.ui.common.updater.UIUpdatable;
+import com.aelitis.azureus.ui.common.updater.UIUpdatableAlways;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
 
@@ -70,7 +69,7 @@ import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
  * Moved from MainWindow and GUIUpdater
  */
 public class MainStatusBar
-	implements IMainStatusBar, UIUpdatable
+	implements IMainStatusBar, UIUpdatableAlways
 {
 	/**
 	 * Warning status icon identifier
@@ -165,13 +164,6 @@ public class MainStatusBar
 	 */
 	private CLabelPadding progressViewerImageLabel;
 
-	private String lastProgressImageID = null;
-
-	private boolean updateProgressBarDisplayQueued = false;
-
-	protected IProgressReport latestReport = null;
-
-	protected AEMonitor latestReport_mon = new AEMonitor("latestReport");
 
 	private String lastSRimageID = null;
 
@@ -476,7 +468,8 @@ public class MainStatusBar
 
 								if (uif != null) {
 
-									uif.openView(UIFunctions.VIEW_CONFIG, "ipfilter");
+									uif.getMDI().showEntryByID(
+											MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG, "ipfilter");
 								}
 							}
 						});
@@ -547,7 +540,8 @@ public class MainStatusBar
 
 		Listener lNAT = new ListenerNeedingCoreRunning() {
 			public void handleEvent(AzureusCore core, Event e) {
-				uiFunctions.openView(UIFunctions.VIEW_CONFIG,
+				uiFunctions.getMDI().loadEntryByID(
+						MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG, true, false,
 						ConfigSection.SECTION_CONNECTION);
 
 				if (PluginInitializer.getDefaultInterface().getConnectionManager().getNATStatus() != ConnectionManager.NAT_OK) {
@@ -592,7 +586,7 @@ public class MainStatusBar
 
 					CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
 						public void azureusCoreRunning(AzureusCore core) {
-							SelectableSpeedMenu.invokeSlider(core, true);
+							SelectableSpeedMenu.invokeSlider(statusUp, core, true);
 						}
 					});
 				}
@@ -629,7 +623,7 @@ public class MainStatusBar
 
 					CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
 						public void azureusCoreRunning(AzureusCore core) {
-							SelectableSpeedMenu.invokeSlider(core, false);
+							SelectableSpeedMenu.invokeSlider(statusDown, core, false);
 						}
 					});
 				}
@@ -735,7 +729,6 @@ public class MainStatusBar
 		/////////
 		
 		PRManager.addListener(new ProgressListener());
-		setProgressImage();
 		
 		uiFunctions.getUIUpdater().addUpdater(this);
 		
@@ -1123,12 +1116,42 @@ public class MainStatusBar
 	}
 
 	// @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI()
-	public void updateUI() {
+	
+	boolean was_hidden = false;
+	
+	public void updateUI(){
+		updateUI(true);
+	}
+	
+	public void updateUI( boolean is_visible ) {
 		if (statusBar.isDisposed()) {
 			uiFunctions.getUIUpdater().removeUpdater(this);
 			return;
 		}
 
+			// see if this fixes occasional issue with status bar vanishing when bringing back from taskbar/tray
+		
+		boolean is_hidden = (!is_visible) || statusBar.getDisplay().getFocusControl() == null;
+		
+		if ( is_hidden ){
+			
+			was_hidden = true;
+			
+		}else{
+			
+			if ( was_hidden ){
+				
+				statusBar.layout( true, true );
+				
+				was_hidden = false;
+			}
+		}
+		
+		if ( !is_visible ){
+			
+			return;
+		}
+		
 		// Plugins.
 		Control[] plugin_elements = this.plugin_label_composite.getChildren();
 		for (int i = 0; i < plugin_elements.length; i++) {
@@ -1547,8 +1570,11 @@ public class MainStatusBar
 
 		private static final int KEEPWIDTHFOR_MS = 30 * 1000;
 		
-		String text = "";
-
+		String 	text = "";
+		String	tooltip_text;
+		
+		private boolean	hovering;
+		
 		private Image image;
 
 		private Image bgImage;
@@ -1568,8 +1594,49 @@ public class MainStatusBar
 			setForeground(parent.getForeground());
 			
 			addPaintListener(this);
+			
+			addMouseTrackListener(
+				new MouseTrackAdapter()
+				{
+					@Override
+					public void mouseEnter(MouseEvent e) {
+						CLabelPadding.super.setToolTipText( tooltip_text );
+						hovering = true;
+					}
+					
+					@Override
+					public void mouseExit(MouseEvent e) {
+						hovering = false;
+					}
+				});
 		}
 
+		public void
+		setToolTipText(
+			String str )
+		{	
+			if ( str == tooltip_text ){
+				return;
+			}
+			if ( str != null && tooltip_text != null && str.equals( tooltip_text )){
+				return;
+			}
+			
+			tooltip_text = str;
+			
+			if ( hovering ){
+				
+				super.setToolTipText( str );
+			}
+		}
+		
+		@Override
+		public String 
+		getToolTipText() 
+		{
+			return( tooltip_text );
+		}
+		
 		public void paintControl(PaintEvent e) {
 			Point size = getSize();
 			e.gc.setAdvanced(true);
@@ -1825,128 +1892,183 @@ public class MainStatusBar
 		}
 	}
 
+
+	public Rectangle getBounds() {
+		if (null != statusBar) {
+			return statusBar.getBounds();
+		}
+		return null;
+	}
+
+	// @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName()
+	public String getUpdateUIName() {
+		return ID;
+	}
+	
 	/**
 	 * Updates the display of the ProgressBar and/or the status text
 	 * @param pReport the <code>ProgressReport</code> containing the information
 	 * to display; can be <code>null</code> in which case the status text and progress bar will be reset to default states
 	 */
-	private void updateProgressBarDisplay(IProgressReport pReport) {
-		latestReport_mon.enter();
-		try {
-			latestReport = pReport;
-		} finally {
-			latestReport_mon.exit();
-		}
-		if (null == progressBar || progressBar.isDisposed()
-				|| updateProgressBarDisplayQueued) {
-			return;
-		}
-		updateProgressBarDisplayQueued = true;
+	
+	
+	
+	
 
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				latestReport_mon.enter();
-				try {
-					updateProgressBarDisplayQueued = false;
 
-					if ((null == progressBar || true == progressBar.isDisposed())) {
-						return;
-					}
+	/**
+	 * A listener that listens to any changes notified from the <code>ProgressReportingManager</code> and
+	 * accordingly update the progress bar and/or the status text area.
+	 * @author knguyen
+	 *
+	 */
+	private class ProgressListener
+		implements IProgressReportingListener
+	{
+		private String lastProgressImageID = null;
 
-					if (null != latestReport) {
-						/*
-						 * Pass the values through to the progressbar
-						 */
-						progressBar.setMinimum(latestReport.getMinimum());
-						progressBar.setMaximum(latestReport.getMaximum());
-						progressBar.setIndeterminate(latestReport.isIndeterminate());
-						progressBar.setPercentage(latestReport.getPercentage());
-						showProgressBar(true);
+		private Set<IProgressReporter>	pending_updates = new HashSet<IProgressReporter>();
 
-						/*
-						 * Update status text
-						 */
-						if (true == isAZ3) {
-							statusText.setText(latestReport.getName());
-						} else {
-							setStatusText(latestReport.getName());
-						}
+		private 
+		ProgressListener()
+		{
+			Utils.execSWTThread(
+				new Runnable()
+				{
+					public void
+					run()
+					{
+						swt_setProgressImage();
 					}
+				});
+		}
+		
+		private void 
+		swt_updateProgressBarDisplay(
+			IProgressReport pReport) 
+		{
+			if (null == progressBar || progressBar.isDisposed()){
+				
+				return;
+			}
 
-					else {
-						/*
-						 * Since the pReport is null then reset progress display appropriately
-						 */
-						showProgressBar(false);
 
-						if (true == isAZ3) {
-							statusText.setText("");
-						} else {
-							setStatusText(null);
-						}
-					}
-				} finally {
-					latestReport_mon.exit();
-				}
+			if (null != pReport) {
+				/*
+				 * Pass the values through to the progressbar
+				 */
+				progressBar.setMinimum(pReport.getMinimum());
+				progressBar.setMaximum(pReport.getMaximum());
+				progressBar.setIndeterminate(pReport.isIndeterminate());
+				progressBar.setPercentage(pReport.getPercentage());
+				showProgressBar(true);
 
+				/*
+				 * Update status text
+				 */
+				if (true == isAZ3) {
+					statusText.setText(pReport.getName());
+				} else {
+					setStatusText(pReport.getName());
+				}
 			}
 
-		}, true);
+			else {
+				/*
+				 * Since the pReport is null then reset progress display appropriately
+				 */
+				showProgressBar(false);
 
-	}
+				if (true == isAZ3) {
+					statusText.setText("");
+				} else {
+					setStatusText(null);
+				}
+			}
+		}
 
-	private void setProgressImage() {
-		String imageID;
+		private void swt_setProgressImage() {
+			
+			if (progressViewerImageLabel.isDisposed()) {
+				return;
+			}
+			
+			String imageID;
 
-		if (PRManager.getReporterCount(ProgressReportingManager.COUNT_ERROR) > 0) {
-			imageID = "progress_error";
-		} else if (PRManager.getReporterCount(ProgressReportingManager.COUNT_ALL) > 0) {
-			imageID = "progress_info";
-		} else {
-			imageID = "progress_viewer";
+			if (PRManager.getReporterCount(ProgressReportingManager.COUNT_ERROR) > 0) {
+				imageID = "progress_error";
+			} else if (PRManager.getReporterCount(ProgressReportingManager.COUNT_ALL) > 0) {
+				imageID = "progress_info";
+			} else {
+				imageID = "progress_viewer";
+			}
+			
+			if (!imageID.equals(lastProgressImageID)) {
+
+				ImageLoader imageLoader = ImageLoader.getInstance();
+				progressViewerImageLabel.setImage(imageLoader.getImage(imageID));
+				if (lastProgressImageID != null) {
+					imageLoader.releaseImage(lastProgressImageID);
+				}
+				lastProgressImageID  = imageID;
+			}
 		}
 		
-		if (!imageID.equals(lastProgressImageID)) {
-			final String fImageID = imageID;
-			Utils.execSWTThread(new AERunnable() {
-				public void runSupport() {
-					if (progressViewerImageLabel.isDisposed()) {
-						return;
-					}
-					ImageLoader imageLoader = ImageLoader.getInstance();
-					progressViewerImageLabel.setImage(imageLoader.getImage(fImageID));
-					if (lastProgressImageID != null) {
-						imageLoader.releaseImage(lastProgressImageID);
+		public int 
+		reporting(
+			final int 					eventType, 
+			final IProgressReporter 	reporter) 
+		{
+			if ( eventType == MANAGER_EVENT_UPDATED ){
+				
+					// reduce pointless refreshes due to multple update events
+				
+				synchronized( pending_updates ){
+			
+					if ( pending_updates.contains( reporter )){
+						
+						return( RETVAL_OK );
 					}
-					lastProgressImageID  = fImageID;
+					
+					pending_updates.add( reporter );
 				}
-			});
+			}
+			
+			Utils.execSWTThread(
+				new Runnable()
+				{
+					public void
+					run()
+					{
+						swt_reporting( eventType, reporter );
+					}});
+			
+			return RETVAL_OK;
 		}
-	}
-
-	/**
-	 * A listener that listens to any changes notified from the <code>ProgressReportingManager</code> and
-	 * accordingly update the progress bar and/or the status text area.
-	 * @author knguyen
-	 *
-	 */
-	private class ProgressListener
-		implements IProgressReportingListener
-	{
-
-		public int reporting(int eventType, IProgressReporter reporter) {
-
+		
+		private int 
+		swt_reporting(
+			int 				eventType, 
+			IProgressReporter 	reporter) 
+		{
+			synchronized( pending_updates ){
+				
+					// always remove so that the removal event also cleans up
+			
+				pending_updates.remove( reporter );
+			}
+						
 			/*
 			 * Show the appropriate image based on the content of the reporting manager
 			 */
-			setProgressImage();
+			swt_setProgressImage();
 
 			if (null == reporter) {
 				return RETVAL_OK;
 			}
 
 			if (MANAGER_EVENT_REMOVED == eventType) {
-				updateFromPrevious();
+				swt_updateFromPrevious();
 			} else if (MANAGER_EVENT_ADDED == eventType
 					|| MANAGER_EVENT_UPDATED == eventType) {
 				/*
@@ -1974,14 +2096,10 @@ public class MainStatusBar
 					 * The new window is opened only if there is not one already showing the same reporter
 					 */
 					if (false == ProgressReporterWindow.isOpened(final_reporter)) {
-						Utils.execSWTThread(new AERunnable() {
-							public void runSupport() {
-								if ( !ProgressReporterWindow.isOpened(final_reporter)){
+						if ( !ProgressReporterWindow.isOpened(final_reporter)){
 									ProgressReporterWindow.open(final_reporter,
 											ProgressReporterWindow.NONE);
-								}
-							}
-						}, true);
+						}
 					}
 				}
 
@@ -1989,19 +2107,19 @@ public class MainStatusBar
 				 * If this reporter is not active then get the previous reporter that is still active and display info from that
 				 */
 				if (false == pReport.isActive()) {
-					updateFromPrevious();
+					swt_updateFromPrevious();
 				} else {
-					update(pReport);
+					swt_update(pReport);
 				}
 			}
 
 			return RETVAL_OK;
 		}
 
-		private void update(final IProgressReport pReport) {
+		private void swt_update(final IProgressReport pReport) {
 
 			if (null == pReport) {
-				updateProgressBarDisplay(null);
+				swt_updateProgressBarDisplay(null);
 				return;
 			}
 
@@ -2010,19 +2128,17 @@ public class MainStatusBar
 			 * and display the text from the current reporter
 			 */
 			if (true == PRManager.hasMultipleActive()) {
-				Utils.execSWTThread(new AERunnable() {
-					public void runSupport() {
-						setStatusText(pReport.getName());
-						progressBar.setIndeterminate(true);
-						showProgressBar(true);
-					}
-				}, true);
+				
+				setStatusText(pReport.getName());
+				progressBar.setIndeterminate(true);
+				showProgressBar(true);
+			
 			} else {
-				updateProgressBarDisplay(pReport);
+				swt_updateProgressBarDisplay(pReport);
 			}
 		}
 
-		private void updateFromPrevious() {
+		private void swt_updateFromPrevious() {
 			/*
 			 * Get the previous reporter that is still active
 			 */
@@ -2032,22 +2148,10 @@ public class MainStatusBar
 			 * If null then we reset the status text and the progress bar
 			 */
 			if (null != previousReporter) {
-				update(previousReporter.getProgressReport());
+				swt_update(previousReporter.getProgressReport());
 			} else {
-				update(null);
+				swt_update(null);
 			}
 		}
 	}
-
-	public Rectangle getBounds() {
-		if (null != statusBar) {
-			return statusBar.getBounds();
-		}
-		return null;
-	}
-
-	// @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName()
-	public String getUpdateUIName() {
-		return ID;
-	}
 }
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MenuFactory.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MenuFactory.java
index a3001a2..b68fabd 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MenuFactory.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/MenuFactory.java
@@ -1,6 +1,26 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.mainwindow;
 
+import java.io.BufferedInputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.net.URL;
@@ -14,7 +34,6 @@ import java.util.Map;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.*;
 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;
@@ -186,10 +205,8 @@ public class MenuFactory
 		if (menu_items.length > 0) {
 			addSeparatorMenuItem(menu);
 
-			MenuBuildUtils.addPluginMenuItems(menu.getShell(),
-					menu_items, menu, true, true,
-					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(
-							plugin_dls));
+			MenuBuildUtils.addPluginMenuItems(menu_items, menu, true, true,
+					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(plugin_dls));
 		}
 
 		menu_items = null;
@@ -226,10 +243,8 @@ public class MenuFactory
 				dls_as_rows[i] = wrapAsRow(plugin_dls[i], table_to_use);
 			}
 
-			MenuBuildUtils.addPluginMenuItems(menu.getShell(),
-					menu_items, menu, true, true,
-					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(
-							dls_as_rows));
+			MenuBuildUtils.addPluginMenuItems(menu_items, menu, true, true,
+					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(dls_as_rows));
 		}
 
 	}
@@ -664,7 +679,8 @@ public class MenuFactory
 			public void handleEvent(Event e) {
 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 				if (uiFunctions != null) {
-					uiFunctions.openView(UIFunctions.VIEW_MYTORRENTS, null);
+					uiFunctions.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_LIBRARY);
 				}
 			}
 		});
@@ -675,7 +691,8 @@ public class MenuFactory
 			public void handleEvent(Event e) {
 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 				if (uiFunctions != null) {
-					uiFunctions.openView(UIFunctions.VIEW_ALLPEERS, null);
+					uiFunctions.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_ALLPEERS);
 				}
 			}
 		});
@@ -686,7 +703,8 @@ public class MenuFactory
 			public void handleEvent(Event e) {
 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 				if (uiFunctions != null) {
-					uiFunctions.openView(UIFunctions.VIEW_PEERS_STATS, null);
+					uiFunctions.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_CLIENT_STATS);
 				}
 			}
 		});
@@ -705,7 +723,7 @@ public class MenuFactory
 		return addMenuItem(menu, MENU_ID_SUBSCRIPTIONS, new Listener() {
 			public void handleEvent(Event e) {
 				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-				mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_HEADER_SUBSCRIPTIONS);
+				mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_SUBSCRIPTIONS);
 			}
 		});
 	}
@@ -713,10 +731,8 @@ public class MenuFactory
 	public static MenuItem addMyTrackerMenuItem(Menu menu) {
 		return addMenuItem(menu, MENU_ID_MY_TRACKERS, new Listener() {
 			public void handleEvent(Event e) {
-				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
-				if (uiFunctions != null) {
-					uiFunctions.openView(UIFunctions.VIEW_MYTRACKER, null);
-				}
+				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+				mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_MY_TRACKER);
 			}
 		});
 	}
@@ -726,7 +742,8 @@ public class MenuFactory
 			public void handleEvent(Event e) {
 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 				if (uiFunctions != null) {
-					uiFunctions.openView(UIFunctions.VIEW_MYSHARES, null);
+					uiFunctions.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_MY_SHARES);
 				}
 			}
 		});
@@ -1132,6 +1149,56 @@ public class MenuFactory
 								}
 							});
 						
+						MenuItem bencodeToJSON = new MenuItem(menu, SWT.PUSH);
+						
+						Messages.setLanguageText(bencodeToJSON, "menu.bencode.to.json" );
+																
+						bencodeToJSON.addListener(
+							SWT.Selection,
+							new Listener()
+							{
+								public void 
+								handleEvent(
+									Event arg )
+								{
+									Utils.execSWTThreadLater(
+											1,
+											new Runnable()
+											{
+												public void
+												run()
+												{
+													BencodeToJSON();
+												}
+											});
+								}
+							});
+						
+						MenuItem JSONToBencode = new MenuItem(menu, SWT.PUSH);
+						
+						Messages.setLanguageText(JSONToBencode, "menu.json.to.bencode" );
+																
+						JSONToBencode.addListener(
+							SWT.Selection,
+							new Listener()
+							{
+								public void 
+								handleEvent(
+									Event arg )
+								{
+									Utils.execSWTThreadLater(
+											1,
+											new Runnable()
+											{
+												public void
+												run()
+												{
+													JSONToBencode();
+												}
+											});
+								}
+							});
+						
 						MenuItem showChanges = new MenuItem(menu, SWT.PUSH);
 						
 						Messages.setLanguageText(showChanges, "show.config.changes" );
@@ -1163,6 +1230,171 @@ public class MenuFactory
 	}
 	
 	private static void
+	BencodeToJSON()
+	{
+		final Shell shell = Utils.findAnyShell();
+		
+		FileDialog dialog = new FileDialog( shell.getShell(), SWT.SYSTEM_MODAL | SWT.OPEN );
+			
+		dialog.setFilterExtensions(new String[] { "*.config", "*.torrent", "*.tor", Constants.FILE_WILDCARD });
+		
+		dialog.setFilterNames(new String[] { "*.config", "*.torrent", "*.tor", Constants.FILE_WILDCARD });
+		
+		dialog.setFilterPath( TorrentOpener.getFilterPathTorrent());
+								
+		dialog.setText(MessageText.getString( "bencode.file.browse" ));
+		
+		String str = dialog.open();
+												
+		if ( str != null ){
+			
+			try{
+				BufferedInputStream bis = new BufferedInputStream( new FileInputStream( str ));
+				
+				try{
+					Map map = BDecoder.decode( bis );
+					
+					if ( map == null ){
+						
+						throw( new Exception( "BDecode failed" ));
+					}
+					
+					final String json = BEncoder.encodeToJSON( map );
+					
+	 				Utils.execSWTThreadLater(
+						1,
+						new Runnable()
+						{
+							public void
+							run()
+							{
+				 				FileDialog dialog2 = new FileDialog( shell, SWT.SYSTEM_MODAL | SWT.SAVE );
+																					
+								dialog2.setFilterPath( TorrentOpener.getFilterPathTorrent());
+														
+								dialog2.setFilterExtensions(new String[]{ "*.json" });
+								
+								String str2 = dialog2.open();
+																		
+								if ( str2 != null ){
+									
+									if ( !( str2.toLowerCase( Locale.US ).endsWith( ".json" ))){
+										
+										str2 += ".json";
+									}
+									
+									try{
+										if ( !FileUtil.writeStringAsFile( new File( str2 ), json )){
+											
+											throw( new Exception( "Failed to write output file" ));
+										}
+									}catch( Throwable e ){
+										
+										MessageBoxShell mb = new MessageBoxShell( SWT.ERROR, MessageText.getString( "ConfigView.section.security.resetkey.error.title"), Debug.getNestedExceptionMessage( e )); 
+				 						
+							 			mb.setParent( shell );
+							 				
+							 			mb.open( null );
+									}
+								}
+							}
+						});
+				}finally{
+					
+					bis.close();
+				}
+			}catch( Throwable e ){
+				
+				MessageBoxShell mb = new MessageBoxShell( SWT.ERROR, MessageText.getString( "ConfigView.section.security.resetkey.error.title"), Debug.getNestedExceptionMessage( e )); 
+	 						
+	 			mb.setParent( shell );
+	 				
+	 			mb.open( null );
+			}
+		}
+	}
+	
+	private static void
+	JSONToBencode()
+	{
+		final Shell shell = Utils.findAnyShell();
+		
+		FileDialog dialog = new FileDialog( shell.getShell(), SWT.SYSTEM_MODAL | SWT.OPEN );
+			
+		dialog.setFilterExtensions(new String[] { "*.json", Constants.FILE_WILDCARD });
+		
+		dialog.setFilterNames(new String[] { "*.json", Constants.FILE_WILDCARD });
+		
+		dialog.setFilterPath( TorrentOpener.getFilterPathTorrent());
+								
+		dialog.setText(MessageText.getString( "json.file.browse" ));
+		
+		String str = dialog.open();
+												
+		if ( str != null ){
+			
+			try{
+				String json = FileUtil.readFileAsString( new File( str ), -1, "UTF-8" );
+
+				if ( json == null ){
+					
+					throw( new Exception( "JSON decode failed" ));
+				}
+				
+				final Map map = BDecoder.decodeFromJSON( json );
+				
+ 				Utils.execSWTThreadLater(
+					1,
+					new Runnable()
+					{
+						public void
+						run()
+						{
+			 				FileDialog dialog2 = new FileDialog( shell, SWT.SYSTEM_MODAL | SWT.SAVE );
+																				
+							dialog2.setFilterPath( TorrentOpener.getFilterPathTorrent());
+													
+							dialog2.setFilterExtensions(new String[]{ "*.config", "*.torrent", "*.tor", Constants.FILE_WILDCARD });
+							
+							String str2 = dialog2.open();
+																	
+							if ( str2 != null ){
+								
+								if ( !str2.contains( "." )){
+									
+									str2 += ".config";
+								}
+								
+								try{
+									byte[] bytes = BEncoder.encode( map );
+									
+									FileUtil.writeBytesAsFile( str2, bytes );
+										
+								}catch( Throwable e ){
+									
+									MessageBoxShell mb = new MessageBoxShell( SWT.ERROR, MessageText.getString( "ConfigView.section.security.resetkey.error.title"), Debug.getNestedExceptionMessage( e )); 
+			 						
+						 			mb.setParent( shell );
+						 				
+						 			mb.open( null );
+								}
+							}
+						}
+					});
+			
+			}catch( Throwable e ){
+				
+				MessageBoxShell mb = new MessageBoxShell( SWT.ERROR, MessageText.getString( "ConfigView.section.security.resetkey.error.title"), Debug.getNestedExceptionMessage( e )); 
+	 						
+	 			mb.setParent( shell );
+	 				
+	 			mb.open( null );
+			}
+		}
+	}
+	
+	
+	private static void
 	handleTorrentView()
 	{
 		final Shell shell = Utils.findAnyShell();
@@ -1617,7 +1849,8 @@ public class MenuFactory
 			public void handleEvent(Event e) {
 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 				if (uiFunctions != null) {
-					uiFunctions.openView(UIFunctions.VIEW_CONSOLE, null);
+					uiFunctions.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_LOGGER);
 				}
 			}
 		});
@@ -1643,6 +1876,28 @@ public class MenuFactory
 		});
 	}
 
+	public static MenuItem addNetStatusMenuItem(Menu menu) {
+		return addMenuItem(menu, MENU_ID_NET_STATUS, new Listener() {
+			public void handleEvent(Event e) {
+				UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
+				if (uiFunctions != null) {
+
+					PluginsMenuHelper.IViewInfo[] views = PluginsMenuHelper.getInstance().getPluginViewsInfo();
+					
+					for ( PluginsMenuHelper.IViewInfo view: views ){
+						
+						String viewID = view.viewID;
+						
+						if ( viewID != null && viewID.equals( "aznetstatus" )){
+							
+							view.openView( uiFunctions );
+						}
+					}
+				}
+			}
+		});
+	}
+	
 	public static MenuItem addSpeedTestMenuItem(Menu menu) {
 		return addMenuItem(menu, MENU_ID_SPEED_TEST, new Listener() {
 			public void handleEvent(Event e) {
@@ -1668,7 +1923,8 @@ public class MenuFactory
 			public void handleEvent(Event e) {
 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 				if (uiFunctions != null) {
-					uiFunctions.openView(UIFunctions.VIEW_CONFIG, null);
+					uiFunctions.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG);
 				}
 			}
 		});
@@ -1898,7 +2154,15 @@ public class MenuFactory
 			}
 		});
 	}
-
+	
+	public static MenuItem addVoteMenuItem(Menu menu) {
+		return addMenuItem(menu, MENU_ID_VOTE, new Listener() {
+			public void handleEvent(Event e) {
+				Utils.launch(MessageText.getString("vote.vuze.url"));
+			}
+		});
+	}
+	
 	public static MenuItem addReleaseNotesMenuItem(final Menu menu) {
 		return addMenuItem(menu, MENU_ID_RELEASE_NOTES, new Listener() {
 			public void handleEvent(Event e) {
@@ -2049,26 +2313,33 @@ public class MenuFactory
 	public static void
 	addAlertsMenu(
 		Menu					menu,
+		boolean	createSubmenu,
 		final DownloadManager[]	dms )
 	{
 		if ( dms.length == 0 ){
 			
 			return;
 		}
+
+		Menu alert_menu;
+
+		if (createSubmenu) {
+  		alert_menu = new Menu( menu.getShell(), SWT.DROP_DOWN );
+  		
+  		MenuItem alerts_item = new MenuItem( menu, SWT.CASCADE);
+  		
+  		Messages.setLanguageText( alerts_item, "ConfigView.section.interface.alerts" );
+  		
+  		alerts_item.setMenu(alert_menu);
+		} else {
+			alert_menu = menu;
+		}
 		
 		String[][] alert_keys =
 			{	{ "Play Download Finished", "playdownloadfinished" },
 				{ "Play Download Finished Announcement", "playdownloadspeech" },
 				{ "Popup Download Finished", "popupdownloadfinished" },
 			};
-				
-		Menu alert_menu = new Menu( menu.getShell(), SWT.DROP_DOWN );
-		
-		MenuItem alerts_item = new MenuItem( menu, SWT.CASCADE);
-		
-		Messages.setLanguageText( alerts_item, "ConfigView.section.interface.alerts" );
-		
-		alerts_item.setMenu(alert_menu);
 		
 		boolean[]	all_enabled = new boolean[ alert_keys.length ];
 		
@@ -2611,6 +2882,7 @@ public class MenuFactory
 			  }
 
 			  // Everything below is unsupported.
+			  public int getIndex() {notSupported(); return 0;}
 			  public void setForeground(int red, int green, int blue) {setForegroundDebug(); notSupported();}
 			  public void setForeground(int[] rgb) {setForegroundDebug(); notSupported();}
 			  public void setForegroundToErrorColor() {setForegroundDebug(); notSupported();}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/PluginsMenuHelper.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/PluginsMenuHelper.java
index a2664c2..429502b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/PluginsMenuHelper.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/PluginsMenuHelper.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.mainwindow;
 
 import java.util.*;
@@ -16,10 +34,8 @@ import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
 import org.gudy.azureus2.ui.swt.pluginsimpl.*;
 
-import com.aelitis.azureus.ui.mdi.MdiEntryCreationListener;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
 
 public class PluginsMenuHelper
 {
@@ -62,7 +78,7 @@ public class PluginsMenuHelper
 		org.gudy.azureus2.plugins.ui.menus.MenuItem[] plugin_items;
 		plugin_items = MenuItemManager.getInstance().getAllAsArray("mainmenu");
 		if (plugin_items.length > 0) {
-			MenuBuildUtils.addPluginMenuItems(parent, plugin_items, viewMenu, true,
+			MenuBuildUtils.addPluginMenuItems(plugin_items, viewMenu, true,
 					true, MenuBuildUtils.BASIC_MENU_ITEM_CONTROLLER);
 		}
 
@@ -101,7 +117,7 @@ public class PluginsMenuHelper
 		org.gudy.azureus2.plugins.ui.menus.MenuItem[] plugin_items;
 		plugin_items = MenuItemManager.getInstance().getAllAsArray("mainmenu");
 		if (plugin_items.length > 0) {
-			MenuBuildUtils.addPluginMenuItems(parent, plugin_items, pluginMenu, true,
+			MenuBuildUtils.addPluginMenuItems(plugin_items, pluginMenu, true,
 					true, MenuBuildUtils.BASIC_MENU_ITEM_CONTROLLER);
 			MenuFactory.addSeparatorMenuItem(pluginMenu);
 		}
@@ -198,40 +214,6 @@ public class PluginsMenuHelper
 		});
 	}
 
-	public void addPluginView(final UISWTViewCore view, final String name) {
-		IViewInfo view_info = new IViewInfo();
-		view_info.name = name;
-		view_info.view = view;
-		try {
-			plugin_helper_mon.enter();
-			plugin_view_info_map.put(name, view_info);
-		} finally {
-			plugin_helper_mon.exit();
-		}
-		triggerPluginAddedViewListeners(view_info);
-	}
-
-	public void removePluginView(final UISWTViewCore view, final String name) {
-		IViewInfo view_info = null;
-		try {
-			plugin_helper_mon.enter();
-			view_info = plugin_view_info_map.remove(name);
-		} finally {
-			plugin_helper_mon.exit();
-		}
-
-		if (view_info != null) {
-			Utils.execSWTThread(new AERunnable() {
-				public void runSupport() {
-					UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
-					if (uiFunctions != null) {
-						uiFunctions.closePluginView(view);
-					}
-				}
-			});
-		}
-	}
-
 	/**
 	 * Populates Azureus' menu bar
 	 * @param locales
@@ -271,8 +253,6 @@ public class PluginsMenuHelper
 
 	public static class IViewInfo
 	{
-		public UISWTViewCore view;
-
 		public String name;
 
 		public String viewID;
@@ -283,8 +263,6 @@ public class PluginsMenuHelper
 			if (event_listener != null) {
 				uiFunctions.openPluginView(UISWTInstance.VIEW_MAIN, viewID,
 						event_listener, null, true);
-			} else {
-				uiFunctions.openPluginView(view, name);
 			}
 		}
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SWTThread.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SWTThread.java
index 3d91589..a1cd1c0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SWTThread.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SWTThread.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.mainwindow;
@@ -384,7 +381,7 @@ public class SWTThread {
   
   public boolean isTerminated() {
   	//System.out.println("isTerm" + terminated + ";" + display.isDisposed() + Debug.getCompressedStackTrace(3));
-  	return terminated || display.isDisposed() || displayDispoed;
+  	return terminated || displayDispoed || display.isDisposed();
   }
 
 	public IUIIntializer getInitializer() {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SWTThreadAlreadyInstanciatedException.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SWTThreadAlreadyInstanciatedException.java
index e9ad1c3..9d2bdb8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SWTThreadAlreadyInstanciatedException.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SWTThreadAlreadyInstanciatedException.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 1, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.mainwindow;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SelectableSpeedMenu.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SelectableSpeedMenu.java
index 0db2212..3d123a2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SelectableSpeedMenu.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SelectableSpeedMenu.java
@@ -1,7 +1,7 @@
 /**
  * Created on 04-Jun-2006
  * Created by Allan Crooks
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.mainwindow;
 
@@ -28,6 +25,7 @@ import org.eclipse.swt.widgets.*;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator;
+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;
@@ -44,12 +42,9 @@ import com.aelitis.azureus.core.AzureusCore;
 public class SelectableSpeedMenu {
 
 	private final static int[] increases = {
-		1,
-		1,
-		3,
-		5, // totals 10
+		5,
 		10,
-		40, // totals 50
+		35, // totals 50
 		50, // 100
 		50,
 		50,
@@ -314,9 +309,10 @@ public class SelectableSpeedMenu {
 	}
 	   
 	/**
+	 * @param cClickedFrom 
 	 * @since 3.0.1.7
 	 */
-	public static void invokeSlider(AzureusCore core, boolean isUpSpeed) {
+	public static void invokeSlider(Control cClickedFrom, AzureusCore core, boolean isUpSpeed) {
 		final String prefix = MessageText.getString(isUpSpeed
 				? "GeneralView.label.maxuploadspeed"
 				: "GeneralView.label.maxdownloadspeed");
@@ -396,10 +392,7 @@ public class SelectableSpeedMenu {
 					lastValue * 1024, true), lastValue);
 		}
 
-		// SWT BUG: on windows/linux, if mouse is down on shell open, all mouse events
-		// will not reflect this
-		if (speedScale.open(auto ? -1 : maxBandwidth, Constants.isWindows
-				|| Constants.isLinux)) {
+		if (speedScale.open(cClickedFrom, auto ? -1 : maxBandwidth, true)) {
 			int value = speedScale.getValue();
 
 			if (!speedScale.wasMenuChosen() || lastValue == value) {
@@ -420,6 +413,126 @@ public class SelectableSpeedMenu {
 			}
 		}
 	}
-	
+
+	public static void invokeSlider(Control cClickedFrom, AzureusCore core, 
+			DownloadManager[] dms, boolean isUpSpeed, Shell parentShell) {
+		final String prefix = MessageText.getString(isUpSpeed
+				? "GeneralView.label.maxuploadspeed"
+				: "GeneralView.label.maxdownloadspeed");
+
+		GlobalManager gm = core.getGlobalManager();
+
+		int maxBandwidth = 0;
+		for (DownloadManager dm : dms) {
+			int bandwidth = (isUpSpeed
+					? dm.getStats().getUploadRateLimitBytesPerSecond()
+					: dm.getStats().getDownloadRateLimitBytesPerSecond()) / 1024;
+			if (bandwidth > maxBandwidth || bandwidth == 0) {
+				maxBandwidth = bandwidth;
+			}
+		}
+		boolean unlim = maxBandwidth == 0;
+		final int num_entries = dms.length;
+
+		SpeedScaleShell speedScale = new SpeedScaleShell() {
+			public String getStringValue(int value, String sValue) {
+				if (sValue != null) {
+					return prefix + ": " + sValue;
+				}
+				if (value == 0) {
+					return MessageText.getString("MyTorrentsView.menu.setSpeed.unlimited");
+				}
+				if (value == -1) {
+					return MessageText.getString("ConfigView.auto");
+				}
+				
+				String speed = DisplayFormatters.formatByteCountToKiBEtcPerSec(
+						value * 1024, true);
+				if (num_entries > 1) {
+					speed = MessageText.getString(
+							"MyTorrentsView.menu.setSpeed.multi",
+							new String[] {
+								DisplayFormatters.formatByteCountToKiBEtcPerSec(value * 1024
+										* num_entries),
+								String.valueOf(num_entries),
+								speed
+							});
+				}
+
+				return prefix + ": " + speed;
+			}
+		};
+		int max = unlim ? (isUpSpeed ? 100 : 800) : maxBandwidth * 5;
+		if (max < 50) {
+			max = 50;
+		}
+		speedScale.setMaxValue(max);
+		speedScale.setMaxTextValue(9999999);
+		speedScale.setParentShell(parentShell);
+
+		final String config_prefix = "config.ui.speed.partitions.manual."
+				+ (isUpSpeed ? "upload" : "download") + ".";
+		int lastValue = COConfigurationManager.getIntParameter(config_prefix
+				+ "last", -10);
+
+		Integer[] speed_limits;
+		if (COConfigurationManager.getBooleanParameter(config_prefix + "enabled",
+				false)) {
+			speed_limits = parseSpeedPartitionString(COConfigurationManager.getStringParameter(
+					config_prefix + "values", ""));
+		} else {
+			speed_limits = getGenericSpeedList(6, maxBandwidth);
+		}
+		if (speed_limits != null) {
+			for (int i = 0; i < speed_limits.length; i++) {
+				int value = speed_limits[i].intValue();
+				if (value > 0) {
+					int total = value * num_entries;
+					String speed = DisplayFormatters.formatByteCountToKiBEtcPerSec(
+							total * 1024, true);
+					if (num_entries > 1) {
+						speed = MessageText.getString("MyTorrentsView.menu.setSpeed.multi",
+								new String[] {
+									speed,
+									String.valueOf(num_entries),
+									DisplayFormatters.formatByteCountToKiBEtcPerSec(value * 1024)
+								});
+					}
+
+					speedScale.addOption(speed, value);
+					if (value == lastValue) {
+						lastValue = -10;
+					}
+				}
+			}
+		}
+		speedScale.addOption(
+				MessageText.getString("MyTorrentsView.menu.setSpeed.unlimited"), 0);
+
+		if (lastValue > 0) {
+			speedScale.addOption(DisplayFormatters.formatByteCountToKiBEtcPerSec(
+					lastValue * 1024, true), lastValue);
+		}
+
+		if (speedScale.open(cClickedFrom, maxBandwidth, true)) {
+			int value = speedScale.getValue();
+
+			if (!speedScale.wasMenuChosen() || lastValue == value) {
+				COConfigurationManager.setParameter(config_prefix + "last",
+						maxBandwidth);
+			}
+
+			if (value >= 0) {
+				for (DownloadManager dm : dms) {
+  				if (isUpSpeed) {
+  					dm.getStats().setUploadRateLimitBytesPerSecond(value * 1024);
+  				} else {
+  					dm.getStats().setDownloadRateLimitBytesPerSecond(value * 1024);
+  				}
+				}
+			}
+		}
+	}
+
 }
  
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SplashWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SplashWindow.java
index 3756174..84a1bbf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SplashWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SplashWindow.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.mainwindow;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SystemWarningWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SystemWarningWindow.java
index 33a8128..eb23be4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SystemWarningWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/SystemWarningWindow.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 4, 2010
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/TorrentOpener.java b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/TorrentOpener.java
index e168da7..624477e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/TorrentOpener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/mainwindow/TorrentOpener.java
@@ -2,11 +2,12 @@
  * Created on 3 mai 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,18 +17,18 @@
  * 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 Alle Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
  */
 package org.gudy.azureus2.ui.swt.mainwindow;
 
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.dnd.DND;
@@ -52,6 +53,12 @@ import org.gudy.azureus2.core3.torrent.impl.TorrentOpenFileOptions;
 import org.gudy.azureus2.core3.torrent.impl.TorrentOpenOptions;
 import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderCallBackInterface;
 import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.UIManagerEvent;
+import org.gudy.azureus2.plugins.utils.StaticUtilities;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionManager;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.utils.xml.rss.RSSUtils;
 import org.gudy.azureus2.ui.swt.*;
 import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
 
@@ -83,12 +90,15 @@ public class TorrentOpener {
 	 * @note PLUGINS USE THIS FUNCTION!
 	 */
 	public static void openTorrent(final String torrentFile) {
+		openTorrent( torrentFile, new HashMap<String, Object>());
+	}
+	
+	public static void openTorrent(final String torrentFile, final Map<String,Object> options ) {
 		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
 			public void azureusCoreRunning(AzureusCore core) {
     		UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
     		if (uif != null) {
-    			uif.openTorrentOpenOptions(null, null, new String[] { torrentFile },
-    					false, false);
+    			uif.openTorrentOpenOptions(null, null, new String[] { torrentFile }, options );
     		}
 			}
 		});
@@ -206,8 +216,6 @@ public class TorrentOpener {
 			}
 		}
 		
-		final boolean bOverrideToStopped = event.detail == DND.DROP_COPY;
-
 		if (event.data instanceof String[] || event.data instanceof String) {
 			final String[] sourceNames = (event.data instanceof String[])
 					? (String[]) event.data : new String[] { (String) event.data };
@@ -223,7 +231,7 @@ public class TorrentOpener {
 					UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
 					if (uif != null) {
 						uif.openTorrentOpenOptions(null, null, new String[] { sURL },
-								bOverrideToStopped, false);
+								false, false);
 					}
 				} else if (source.isFile()) {
 					
@@ -248,7 +256,7 @@ public class TorrentOpener {
 							UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
 							if (uif != null) {
 								uif.openTorrentOpenOptions(null, null, new String[] { filename },
-										bOverrideToStopped, false);
+										false, false);
 							}
 				
 						}
@@ -261,7 +269,7 @@ public class TorrentOpener {
 					UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
 					if (uif != null) {
 						uif.openTorrentOpenOptions(null, dir_name, null,
-								bOverrideToStopped, false);
+								false, false);
 					}
 				}
 			}
@@ -270,7 +278,7 @@ public class TorrentOpener {
 			if (uif != null) {
 				uif.openTorrentOpenOptions(null, null, new String[] {
 					((URLTransfer.URLType) event.data).linkURL
-				}, bOverrideToStopped, false);
+				}, false, false);
 			}
 		}
 	}
@@ -495,6 +503,33 @@ public class TorrentOpener {
 							}
 						}
 
+							// rename display name based on whether the user has manually renamed either the only file in 
+							// a single file torrent or the top-level-folder in a multi-file torrent
+						
+						if ( files.length == 1 ){
+							
+							TorrentOpenFileOptions file = files[0];
+							
+							if ( file.isManualRename()){
+								
+								String fileRename = file.getDestFileName();
+								
+								if ( fileRename != null && fileRename.length() > 0 ){
+								
+									dm.getDownloadState().setDisplayName( fileRename );
+								}
+							}
+						}else{
+							
+							String folderRename = torrentOptions.getManualRename();
+							
+							if ( 	folderRename != null && 
+									folderRename.length() > 0 && 
+									new File( torrentOptions.getParentDir()).getName().equals( folderRename )){
+								
+								dm.getDownloadState().setDisplayName( folderRename );
+							}
+						}
 						
 						
 						if (comp_num > 0) {
@@ -516,6 +551,18 @@ public class TorrentOpener {
 							file_info_set.setPriority( priorities );
 						}
 						
+						int	maxUp = torrentOptions.getMaxUploadSpeed();
+						
+						if ( maxUp > 0 ){
+							dm.getStats().setUploadRateLimitBytesPerSecond( maxUp*1024 );
+						}
+						
+						int	maxDown = torrentOptions.getMaxDownloadSpeed();
+						
+						if ( maxDown > 0 ){
+							dm.getStats().setDownloadRateLimitBytesPerSecond( maxDown*1024 );
+						}
+						
 						if (torrentOptions.disableIPFilter) {
 
 							dm.getDownloadState().setFlag(
@@ -529,6 +576,15 @@ public class TorrentOpener {
 							}
 						}
 
+						Map<String,Boolean> enabledNetworks = torrentOptions.getEnabledNetworks();
+
+						if ( enabledNetworks != null ){
+							for (String net : enabledNetworks.keySet()) {
+								boolean enable = enabledNetworks.get(net);
+								dm.getDownloadState().setNetworkEnabled(net, enable);
+							}
+						}
+						
 						List<Tag> initialTags = torrentOptions.getInitialTags();
 													
 						for ( Tag t: initialTags ){
@@ -684,8 +740,50 @@ public class TorrentOpener {
 			return false;
 		}
 
+		if ( RSSUtils.isRSSFeed( torrentFile )){
+				
+			boolean	done = false;
+			
+			try{
+				URL url = new URL( sOriginatingLocation );
+				
+				UIManager ui_manager = StaticUtilities.getUIManager( 10*1000 );
+				
+				if ( ui_manager != null ){
+				
+					String details = MessageText.getString(
+							"subscription.request.add.message",
+							new String[]{ sOriginatingLocation });
+					
+					long res = ui_manager.showMessageBox(
+							"subscription.request.add.title",
+							"!" + details + "!",
+							UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+					
+					if ( res == UIManagerEvent.MT_YES ){
+							
+						SubscriptionManager sm = PluginInitializer.getDefaultInterface().getUtilities().getSubscriptionManager();
+
+						sm.requestSubscription( url );
+						
+						done = true;
+					}
+				}				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+
+			
+			if ( done ){
+				if (bDeleteFileOnCancel) {
+					torrentFile.delete();
+				}
+				return false;
+			}
+		}
 		// Do a quick check to see if it's a torrent
-		if (!TorrentUtil.isFileTorrent(torrentFile, torrentFile.getName())) {
+		if (!TorrentUtil.isFileTorrent(torrentFile, torrentFile.getName(), !torrentOptions.getHideErrors())) {
 			if (bDeleteFileOnCancel) {
 				torrentFile.delete();
 			}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/BYOPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/BYOPanel.java
index 288a11e..df5a0f0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/BYOPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/BYOPanel.java
@@ -5,7 +5,8 @@
  * 
  * 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.
+ * 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
@@ -145,8 +146,16 @@ public class BYOPanel
 				fDialog.setText(MessageText.getString("MainWindow.dialog.choose.file"));
 				if (fDialog.open() != null) {
 					String[] fileNames = fDialog.getFileNames();
+					File last_file = null;
 					for (String fileName : fileNames) {
-						addFilename(new File(fDialog.getFilterPath(), fileName));
+						File f = new File(fDialog.getFilterPath(), fileName);
+						addFilename(f);
+						last_file = f;
+					}
+					
+					if ( last_file != null ){
+						
+						TorrentOpener.setFilterPathData( last_file.getAbsolutePath());
 					}
 				}
 			}
@@ -164,7 +173,12 @@ public class BYOPanel
 				fDialog.setMessage(MessageText.getString("MainWindow.dialog.choose.folder"));
 				String path = fDialog.open();
 				if (path != null) {
-					addFilename(new File(path));
+					File f = new File(path);
+					addFilename(f);
+					
+					if ( f.isDirectory()){
+						TorrentOpener.setFilterPathData( f.getAbsolutePath());
+					}
 				}
 			}
 			
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/DirectoryPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/DirectoryPanel.java
index 15ecce7..72e5c36 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/DirectoryPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/DirectoryPanel.java
@@ -5,7 +5,8 @@
  * 
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/ModePanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/ModePanel.java
index e122f26..f724adf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/ModePanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/ModePanel.java
@@ -5,7 +5,8 @@
  * 
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/MultiTrackerEditor.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/MultiTrackerEditor.java
index 70e2433..30df495 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/MultiTrackerEditor.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/MultiTrackerEditor.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -379,7 +380,7 @@ public class MultiTrackerEditor {
 			public void handleEvent(Event e) {
 				Map<String,List<List<String>>> multiTrackers = TrackersUtil.getInstance().getMultiTrackers();
 				String	selected = currentTemplate[0];
-				trackers = TorrentUtils.removeAnnounceURLs(trackers, multiTrackers.get( selected ));
+				trackers = TorrentUtils.removeAnnounceURLs(trackers, multiTrackers.get( selected ), false);
 				refresh();
 				computeSaveEnable();
 			}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/MultiTrackerPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/MultiTrackerPanel.java
index c3c7c28..4ea745c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/MultiTrackerPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/MultiTrackerPanel.java
@@ -5,7 +5,8 @@
  * 
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/NewTorrentWizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/NewTorrentWizard.java
index 18f7917..dc17b38 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/NewTorrentWizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/NewTorrentWizard.java
@@ -5,7 +5,8 @@
  * 
  * 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.
+ * 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
@@ -29,8 +30,6 @@ import org.eclipse.swt.widgets.*;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.torrent.TOTorrentCreator;
-import org.gudy.azureus2.core3.util.AETemporaryFileHandler;
-import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.TorrentUtils;
 import org.gudy.azureus2.ui.swt.URLTransfer;
 import org.gudy.azureus2.ui.swt.Utils;
@@ -99,8 +98,10 @@ NewTorrentWizard
   
   boolean autoOpen 			= false;
   boolean autoHost 			= false;
+  boolean forceStart		= false;
+  String  initialTags		= COConfigurationManager.getStringParameter( "CreateTorrent.default.initialTags", "" );
+  boolean superseed			= false;
   boolean permitDHT			= true;
-  boolean privateTorrent	= false;
   
   TOTorrentCreator creator = null;
 
@@ -169,6 +170,23 @@ NewTorrentWizard
  	COConfigurationManager.setParameter( "CreateTorrent.default.save", default_save_dir );
   }
   
+  protected String
+  getInitialTags(
+		 boolean	save )
+  {
+	  if ( save ){
+		  COConfigurationManager.setParameter( "CreateTorrent.default.initialTags", initialTags );
+	  }
+	  return( initialTags );
+  }
+  
+  protected void
+  setInitialTags(
+	String		tags )
+  {
+	  initialTags = tags;
+  }
+  
   void setComment(String s) {
     comment = s;
     
@@ -256,6 +274,19 @@ NewTorrentWizard
   }
   
   protected boolean
+  getPrivateTorrent()
+  {
+	  return( COConfigurationManager.getBooleanParameter( "CreateTorrent.default.privatetorrent", false ));
+  }
+  
+  protected void
+  setPrivateTorrent(
+	boolean	privateTorrent )
+  {	  
+	  COConfigurationManager.setParameter( "CreateTorrent.default.privatetorrent", privateTorrent );	 
+  }
+  
+  protected boolean
   getAddOtherHashes()
   {
   	return( addOtherHashes );
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/ProgressPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/ProgressPanel.java
index 87ee77d..357c59d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/ProgressPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/ProgressPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -33,13 +34,14 @@ import org.eclipse.swt.events.SelectionEvent;
 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.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerInitialisationAdapter;
 import org.gudy.azureus2.core3.internat.LocaleTorrentUtil;
 import org.gudy.azureus2.core3.internat.MessageText;
 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.torrent.*;
 import org.gudy.azureus2.core3.tracker.host.TRHostException;
 import org.gudy.azureus2.core3.util.*;
@@ -52,6 +54,10 @@ import org.gudy.azureus2.ui.swt.wizard.IWizardPanel;
 
 import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManager;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
 
 /**
  * @author Olivier
@@ -201,7 +207,7 @@ public class ProgressPanel extends AbstractWizardPanel<NewTorrentWizard> impleme
  
       TorrentUtils.setDHTBackupEnabled( torrent, wizard.permitDHT );
 	  
-      TorrentUtils.setPrivate( torrent, wizard.privateTorrent );
+      TorrentUtils.setPrivate( torrent, wizard.getPrivateTorrent());
       
       LocaleTorrentUtil.setDefaultTorrentEncoding( torrent );
       
@@ -298,7 +304,7 @@ public class ProgressPanel extends AbstractWizardPanel<NewTorrentWizard> impleme
 	  	CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD,
 						new AzureusCoreRunningListener() {
 							public void azureusCoreRunning(AzureusCore core) {
-								boolean default_start_stopped = COConfigurationManager.getBooleanParameter("Default Start Torrents Stopped");
+								boolean start_stopped = COConfigurationManager.getBooleanParameter("Default Start Torrents Stopped");
 
 								byte[] hash = null;
 								try {
@@ -306,16 +312,81 @@ public class ProgressPanel extends AbstractWizardPanel<NewTorrentWizard> impleme
 								} catch (TOTorrentException e1) {
 								}
 
-								DownloadManager dm = core.getGlobalManager().addDownloadManager(
+								if ( wizard.forceStart || wizard.superseed ){
+									
+										// superseeding can only be set for an active download...
+									
+									start_stopped = false;
+								}
+								
+								DownloadManagerInitialisationAdapter dmia;
+								
+								final String	initialTags = wizard.getInitialTags( true );
+								
+								if ( initialTags.length() > 0 ){
+									
+									dmia = 
+										new DownloadManagerInitialisationAdapter() 
+										{
+											public int 
+											getActions() 
+											{
+												return( ACT_ASSIGNS_TAGS );
+											}
+											
+											public void 
+											initialised(
+												DownloadManager 	dm, 
+												boolean 			for_seeding ) 
+											{
+												TagManager tm = TagManagerFactory.getTagManager();
+												
+												TagType tag_type = tm.getTagType( TagType.TT_DOWNLOAD_MANUAL );
+												
+												String[]	bits = initialTags.replace( ';', ',' ).split( "," );
+												
+												for ( String tag: bits ){
+													
+													tag = tag.trim();
+													
+													if ( tag.length() > 0 ){
+													
+														try{
+															Tag t = tag_type.getTag( tag,  true );
+														
+															if ( t == null ){
+																
+																t = tag_type.createTag( tag, true );
+															}
+															
+															t.addTaggable( dm );
+															
+														}catch( Throwable e ){
+															
+															Debug.out( e );
+														}
+													}
+												}
+											}
+										};
+								}else{
+									
+									dmia = null;
+								}
+								
+								
+								
+								
+								final DownloadManager dm = core.getGlobalManager().addDownloadManager(
 										torrent_file.toString(),
 										hash,
 										save_dir.toString(),
-										default_start_stopped ? DownloadManager.STATE_STOPPED
+										start_stopped ? DownloadManager.STATE_STOPPED
 												: DownloadManager.STATE_QUEUED, true, // persistent 
 										true, // for seeding
-										null); // no adapter required
+										dmia ); 
 
-								if (!default_start_stopped && dm != null) {
+								if (!start_stopped && dm != null) {
 									// We want this to move to seeding ASAP, so move it to the top
 									// of the download list, where it will do the quick check and
 									// move to the seeding list
@@ -337,6 +408,69 @@ public class ProgressPanel extends AbstractWizardPanel<NewTorrentWizard> impleme
 												"Host operation fails", e));
 									}
 								}
+								
+								if ( dm != null ){
+									
+									if ( wizard.forceStart ){
+										
+										dm.setForceStart( true );
+									}
+									
+									if ( wizard.superseed ){
+										
+										new AEThread2( "startwait" )
+										{
+											public void
+											run()
+											{
+												long	start = SystemTime.getMonotonousTime();
+												
+												while( true ){
+												
+													if ( dm.isDestroyed()){
+														
+														break;
+													}
+													
+													long elapsed = SystemTime.getMonotonousTime() - start;
+													
+													if ( elapsed > 60*1000 ){
+														
+														int state = dm.getState();
+														
+														if ( 	state == DownloadManager.STATE_ERROR || 
+																state ==DownloadManager.STATE_STOPPED ){
+															
+															break;
+														}
+													}
+													
+													if ( elapsed > 5*60*1000 ){
+														
+														break;
+													}
+													
+													PEPeerManager pm = dm.getPeerManager();
+													
+													if ( pm != null ){
+														
+														pm.setSuperSeedMode( true );
+														
+														break;
+													}
+													
+													try{
+														Thread.sleep(1000);
+														
+													}catch( Throwable e ){
+														
+														break;
+													}
+												}
+											}
+										}.start();
+									}
+								}
 
 							}
 						});
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/SavePathPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/SavePathPanel.java
index 7602280..e984024 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/SavePathPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/SavePathPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -291,23 +292,71 @@ public class SavePathPanel extends AbstractWizardPanel<NewTorrentWizard> {
     gridData.horizontalSpan = 3;
     bAutoOpen.setLayoutData(gridData);
     
+    final Button bforce = new Button(panel,SWT.CHECK);
+    Messages.setLanguageText(bforce,"wizard.maketorrents.force");
+    gridData = new GridData(GridData.FILL_HORIZONTAL);
+    gridData.horizontalSpan = 3;
+    bforce.setLayoutData(gridData);
+    
+    final Button bSuperSeed = new Button(panel,SWT.CHECK);
+    Messages.setLanguageText(bSuperSeed,"wizard.maketorrents.superseed");
+    gridData = new GridData(GridData.FILL_HORIZONTAL);
+    gridData.horizontalSpan = 3;
+    bSuperSeed.setLayoutData(gridData);
+
     final Button bAutoHost = new Button(panel,SWT.CHECK);
     Messages.setLanguageText(bAutoHost,"wizard.maketorrents.autohost");
     gridData = new GridData(GridData.FILL_HORIZONTAL);
     gridData.horizontalSpan = 3;
     bAutoHost.setLayoutData(gridData);
+
+    label = new Label(panel,SWT.NULL);
+    Messages.setLanguageText(label,"wizard.maketorrents.init.tags");
+    final Text tag_area = new Text(panel,SWT.BORDER);
+    gridData = new GridData(GridData.FILL_HORIZONTAL);
+    gridData.horizontalSpan = 2;
+    tag_area.setLayoutData(gridData);
+    
+    bforce.setEnabled( false );
+    tag_area.setEnabled( false );
+    bSuperSeed.setEnabled( false );
     bAutoHost.setEnabled( false );
     
-    bAutoOpen.addListener(SWT.Selection,new Listener() {
-        public void handleEvent(Event event) {
-          wizard.autoOpen = bAutoOpen.getSelection();
+    bAutoOpen.addListener(SWT.Selection,new Listener(){
+        public void handleEvent(Event event){
+          boolean autoOpen = wizard.autoOpen = bAutoOpen.getSelection();
           
-          bAutoHost.setEnabled( wizard.autoOpen && wizard.getTrackerType() != NewTorrentWizard.TT_EXTERNAL );
+          boolean enable = autoOpen && wizard.getTrackerType() != NewTorrentWizard.TT_EXTERNAL;
+          
+          bforce.setEnabled( autoOpen );
+          tag_area.setEnabled( autoOpen );
+          bSuperSeed.setEnabled( autoOpen );
+          bAutoHost.setEnabled( enable );
+        }
+      });
+    
+    bforce.addListener(SWT.Selection,new Listener(){
+        public void handleEvent(Event event) {
+          wizard.forceStart = bforce.getSelection();
         }
       });
     
-    bAutoHost.addListener(SWT.Selection,new Listener() {
-      public void handleEvent(Event event) {
+    tag_area.setText( wizard.getInitialTags(false));
+    tag_area.addModifyListener(new ModifyListener(){
+        public void modifyText( ModifyEvent arg0){
+        	wizard.setInitialTags( tag_area.getText().trim());
+        }
+    });
+    
+    
+    bSuperSeed.addListener(SWT.Selection,new Listener(){
+        public void handleEvent(Event event){
+          wizard.superseed = bSuperSeed.getSelection();
+        }
+      });
+    
+    bAutoHost.addListener(SWT.Selection,new Listener(){
+      public void handleEvent(Event event){
         wizard.autoHost = bAutoHost.getSelection();
       }
     });
@@ -332,17 +381,34 @@ public class SavePathPanel extends AbstractWizardPanel<NewTorrentWizard> {
         }
       });
       
-	
+    	// terrible code, who wrote this?
+    
+    if ( wizard.getTrackerType() == NewTorrentWizard.TT_DECENTRAL ){
+    	
+    	wizard.setPrivateTorrent( false );
+    }
+    
+    boolean privateTorrent = wizard.getPrivateTorrent();
+    
+	bAllowDHT.setEnabled( !privateTorrent );
+    if ( privateTorrent ){
+  	  
+  	  bAllowDHT.setSelection( false );
+  	  wizard.permitDHT = false;
+    }
+    
 	bPrivateTorrent.addListener(SWT.Selection,new Listener() {
         public void handleEvent(Event event) {
-          wizard.privateTorrent = bPrivateTorrent.getSelection();
+          boolean privateTorrent = bPrivateTorrent.getSelection();
+          
+          wizard.setPrivateTorrent(privateTorrent);
 		  
-          if ( wizard.privateTorrent ){
+          if ( privateTorrent ){
         	  
         	  bAllowDHT.setSelection( false );
         	  wizard.permitDHT = false;
           }
-		  bAllowDHT.setEnabled( !wizard.privateTorrent );
+		  bAllowDHT.setEnabled( !privateTorrent );
         }
       });
 
@@ -350,6 +416,8 @@ public class SavePathPanel extends AbstractWizardPanel<NewTorrentWizard> {
 
 		bAllowDHT.setEnabled( false );
 		bPrivateTorrent.setEnabled( false );
+    }else{
+    	bPrivateTorrent.setSelection( privateTorrent );
     }
   }
   
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/SingleFilePanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/SingleFilePanel.java
index 77a00df..daa8ff7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/SingleFilePanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/SingleFilePanel.java
@@ -5,7 +5,8 @@
  * 
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/TrackerEditorListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/TrackerEditorListener.java
index fe4d4a6..f7d2b3a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/TrackerEditorListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/TrackerEditorListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedPanel.java
index 5795dcc..9facd3f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedPanel.java
@@ -5,7 +5,8 @@
  * 
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditor.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditor.java
index e3779f9..629573c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditor.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditor.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -408,10 +409,8 @@ public class WebSeedsEditor {
   		URL url = new URL(str);
   		
   		String prot = url.getProtocol().toLowerCase();
-  		
-  			// don't support https in Az
-  		
-  		if ( prot.equals( "http" )){
+  		  		
+  		if ( prot.startsWith( "http" )){
   			
   			return( true );
   		}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditorListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditorListener.java
index 332fded..a2df582 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditorListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/maketorrent/WebSeedsEditorListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/minibar/AllTransfersBar.java b/azureus2/src/org/gudy/azureus2/ui/swt/minibar/AllTransfersBar.java
index 782b9f1..8f670c4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/minibar/AllTransfersBar.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/minibar/AllTransfersBar.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 May 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.minibar;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/minibar/DownloadBar.java b/azureus2/src/org/gudy/azureus2/ui/swt/minibar/DownloadBar.java
index d6d3bfc..6e8d762 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/minibar/DownloadBar.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/minibar/DownloadBar.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 May 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,16 +14,15 @@
  * 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.minibar;
 
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerStats;
 import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.plugins.download.Download;
 import org.gudy.azureus2.plugins.download.DownloadException;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
 import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
@@ -137,7 +136,7 @@ public class DownloadBar extends MiniBar {
 		DownloadManagerStats stats = download.getStats();
 
         download_name.setText(download.getDisplayName());
-        int percent = stats.getCompleted();
+        int percent = stats.getPercentDoneExcludingDND();
         
         this.updateSpeedLabel(down_speed, stats.getDataReceiveRate(), stats.getProtocolReceiveRate());
         this.updateSpeedLabel(up_speed, stats.getDataSendRate(), stats.getProtocolSendRate());
@@ -149,13 +148,13 @@ public class DownloadBar extends MiniBar {
         }
 	}
 	
-	public String[] getPluginMenuIdentifiers(Object context) {
+	public String[] getPluginMenuIdentifiers(Object[] context) {
 		if (context == null) {return null;}
-		return new String[] {"downloadbar", "download_context"};
+		return new String[] {"downloadbar", MenuManager.MENU_DOWNLOAD_CONTEXT};
 	}
 	
-	public Object getPluginMenuContextObject() {
-		try {return DownloadManagerImpl.getDownloadStatic(this.download);}
+	public Object[] getPluginMenuContextObjects() {
+		try {return( new Download[]{ DownloadManagerImpl.getDownloadStatic(this.download) });}
 		catch (DownloadException de) {return null;}
 	}
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/minibar/MiniBar.java b/azureus2/src/org/gudy/azureus2/ui/swt/minibar/MiniBar.java
index 5351ded..158ccca 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/minibar/MiniBar.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/minibar/MiniBar.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 May 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.minibar;
 
@@ -386,18 +383,14 @@ public abstract class MiniBar implements MenuBuildUtils.MenuBuilder {
 	
 	public void buildMenu(Menu menu) {
 		org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items;
-		Object plugin_context_obj = this.getPluginMenuContextObject();
-		Object[] plugin_context_obj_arg = null;
-		if (plugin_context_obj != null) {
-			plugin_context_obj_arg = new Object[]{plugin_context_obj};
-		}
-		String[] plugin_menu_ids = this.getPluginMenuIdentifiers(plugin_context_obj);
+		Object[] plugin_context_objs = this.getPluginMenuContextObjects();
+		String[] plugin_menu_ids = this.getPluginMenuIdentifiers(plugin_context_objs);
 		if (plugin_menu_ids != null) {
 			menu_items = MenuItemManager.getInstance().getAllAsArray(plugin_menu_ids);
 			if (menu_items.length > 0) {
-				MenuBuildUtils.addPluginMenuItems(splash, menu_items, menu, true, true,
+				MenuBuildUtils.addPluginMenuItems(menu_items, menu, true, true,
 						// This will retrieve the plugin download object for associated menus.
-						new MenuBuildUtils.MenuItemPluginMenuControllerImpl(plugin_context_obj_arg)
+						new MenuBuildUtils.MenuItemPluginMenuControllerImpl(plugin_context_objs)
 				);
 				new MenuItem(menu, SWT.SEPARATOR);
 			}
@@ -585,11 +578,11 @@ public abstract class MiniBar implements MenuBuildUtils.MenuBuilder {
 	protected abstract void beginConstruction();
 	protected abstract Object getContextObject();
 	
-	public String[] getPluginMenuIdentifiers(Object context) {
+	public String[] getPluginMenuIdentifiers(Object[] context) {
 		return null;
 	}
 	
-	public Object getPluginMenuContextObject() {
+	public Object[] getPluginMenuContextObjects() {
 		return null;
 	}
 	
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/minibar/MiniBarManager.java b/azureus2/src/org/gudy/azureus2/ui/swt/minibar/MiniBarManager.java
index 8559c78..c3149e1 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/minibar/MiniBarManager.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/minibar/MiniBarManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 May 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.minibar;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/nat/NatTestWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/nat/NatTestWindow.java
index dd08ca3..54e10f7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/nat/NatTestWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/nat/NatTestWindow.java
@@ -2,11 +2,12 @@
  * Created on 14 avr. 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.nat;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java b/azureus2/src/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java
index 520453e..f3d8b9e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/networks/SWTNetworkSelection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Jan-2005
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java b/azureus2/src/org/gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java
index 8e47a81..4e10ebd 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/osx/CarbonUIEnhancer.java
@@ -32,6 +32,7 @@ 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.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 
 public class CarbonUIEnhancer
@@ -805,7 +806,8 @@ public class CarbonUIEnhancer
 					case kHICommandPreferences: {
 						UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 						if (uiFunctions != null) {
-							uiFunctions.openView(UIFunctions.VIEW_CONFIG, null);
+							uiFunctions.getMDI().showEntryByID(
+									MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG);
 						}
 						return noErr;
 					}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/osx/CocoaUIEnhancer.java b/azureus2/src/org/gudy/azureus2/ui/swt/osx/CocoaUIEnhancer.java
index 4c00b1a..5af5eb4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/osx/CocoaUIEnhancer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/osx/CocoaUIEnhancer.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.osx;
 
 import java.lang.reflect.*;
@@ -9,7 +27,6 @@ import org.eclipse.swt.graphics.Device;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.internal.C;
 import org.eclipse.swt.widgets.*;
-
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.util.AERunnable;
 import org.gudy.azureus2.core3.util.Debug;
@@ -17,11 +34,15 @@ import org.gudy.azureus2.ui.swt.Messages;
 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.PluginsMenuHelper;
 import org.gudy.azureus2.ui.swt.nat.NatTestWindow;
 import org.gudy.azureus2.ui.swt.speedtest.SpeedTestWizard;
 
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
+import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
+import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 
 /**
  * You can exclude this file (or this whole path) for non OSX builds
@@ -538,7 +559,8 @@ public class CocoaUIEnhancer
 					public void widgetSelected(SelectionEvent e) {
 						UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 						if (uiFunctions != null) {
-							uiFunctions.openView(UIFunctions.VIEW_CONFIG, null);
+							uiFunctions.getMDI().showEntryByID(
+									MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG);
 						}
 					};
 				});
@@ -580,6 +602,28 @@ public class CocoaUIEnhancer
 					}
 				});
 
+				MenuItem netstatMenu = new MenuItem(systemMenu, SWT.CASCADE, prefIndex);
+				Messages.setLanguageText(netstatMenu, "MainWindow.menu.tools.netstat");
+				netstatMenu.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
+						if (uiFunctions != null) {
+
+							PluginsMenuHelper.IViewInfo[] views = PluginsMenuHelper.getInstance().getPluginViewsInfo();
+							
+							for ( PluginsMenuHelper.IViewInfo view: views ){
+								
+								String viewID = view.viewID;
+								
+								if ( viewID != null && viewID.equals( "aznetstatus" )){
+									
+									view.openView( uiFunctions );
+								}
+							}
+						}
+					}
+				});
+				
 				MenuItem speedMenu = new MenuItem(systemMenu, SWT.CASCADE, prefIndex);
 				Messages.setLanguageText(speedMenu, "MainWindow.menu.tools.speedtest");
 				speedMenu.addSelectionListener(new SelectionAdapter() {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/osx/OSXFileOpen.java b/azureus2/src/org/gudy/azureus2/ui/swt/osx/OSXFileOpen.java
index 2ac4b64..fd81e86 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/osx/OSXFileOpen.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/osx/OSXFileOpen.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.osx;
 
 import java.lang.reflect.Field;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/osx/Start.java b/azureus2/src/org/gudy/azureus2/ui/swt/osx/Start.java
index cbc6b92..72db296 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/osx/Start.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/osx/Start.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 30, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.osx;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/PluginUISWTSkinObject.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/PluginUISWTSkinObject.java
index eb5c9d6..7ff1885 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/PluginUISWTSkinObject.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/PluginUISWTSkinObject.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.plugins;
 
 /**
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTConfigSection.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTConfigSection.java
index fe2bc0b..345c933 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTConfigSection.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTConfigSection.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTGraphic.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTGraphic.java
index 7fb7599..5c7d7c2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTGraphic.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTGraphic.java
@@ -2,11 +2,12 @@
  * Created on 2004/May/23
  * Created by TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.plugins;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTInputReceiver.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTInputReceiver.java
index 4ec46dc..d3e9cc7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTInputReceiver.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTInputReceiver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 11-Nov-2006
  * Created by Allan Crooks
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTInstance.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTInstance.java
index 1460564..ece7878 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTInstance.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTInstance.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -90,6 +87,8 @@ public interface UISWTInstance extends UIInstanceBase {
 	
 	public static final String VIEW_CONFIG 		= "ConfigView";
 
+	public static final String VIEW_SIDEBAR_AREA = "SideBarArea";
+
 	
 	/** Retrieve the SWT Display object that Azureus uses (when in SWT mode).
 	 * If you have a thread that does some periodic/asynchronous stuff, Azureus 
@@ -135,7 +134,8 @@ public interface UISWTInstance extends UIInstanceBase {
 
 	/**
 	 * Add a view to an Azureus parent view.  For views added to the {@link #VIEW_MAIN}
-	 * window, this adds a menu option.<P>
+	 * window, this adds a menu option.
+	 * <P>
 	 * In comparison to {@link #addView(String, String, UISWTViewEventListener)},
 	 * this method saves memory by not creating the {@link UISWTViewEventListener}
 	 * until it is needed.  It also ensures that only one 
@@ -144,7 +144,7 @@ public interface UISWTInstance extends UIInstanceBase {
 	 * @param sParentID VIEW_* constant
 	 * @param sViewID of your view.  Used as part of the resource id.<br>
 	 *          "Views.plugins." + ID + ".title" = title of your view
-	 * @param l Class of the Listener to be created and triggered
+	 * @param cla Class of the Listener to be created and triggered
 	 *           
 	 * @note If you want the window to auto-open, use openMainView when you gain
 	 *        access to the UISWTInstance
@@ -239,6 +239,10 @@ public interface UISWTInstance extends UIInstanceBase {
 	 */
 	public UISWTView[] getOpenViews(String sParentID);
 
+	/**
+	 * 
+	 * @since 4.8.0.0
+	 */
 	public UISWTViewEventListenerWrapper[] 
 	getViewListeners(
 		String sParentID );
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTParameterContext.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTParameterContext.java
index 2886a4e..2f38a00 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTParameterContext.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTParameterContext.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25 May 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.plugins;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTStatusEntry.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTStatusEntry.java
index 94bb2f2..cb06a30 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTStatusEntry.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTStatusEntry.java
@@ -1,7 +1,7 @@
 /**
  * Created on 03-Feb-2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.plugins;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTStatusEntryListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTStatusEntryListener.java
index ec57441..45ccb37 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTStatusEntryListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTStatusEntryListener.java
@@ -1,7 +1,7 @@
 /**
  * Created on 03-Feb-2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.plugins;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTView.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTView.java
index 695afe1..166a551 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTView.java
@@ -3,11 +3,12 @@
  * Created : Oct 14, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.plugins;
@@ -93,6 +91,20 @@ public interface UISWTView extends UIPluginView {
 	public Object getDataSource();
 
 	/**
+	 * Get the original datasource that was set to the view
+	 * 
+	 * @since 5.5.0.0
+	 */
+	public Object getInitialDataSource();
+
+	/**
+	 * Get parent view, if one exists
+	 * 
+	 * @since 5.5.0.0
+	 */
+	public UISWTView getParentView();
+	
+	/**
 	 * Trigger an event for this view
 	 * 
 	 * @param eventType  Event to trigger {@link UISWTViewEvent}}
@@ -121,5 +133,22 @@ public interface UISWTView extends UIPluginView {
 	 * @since 4.5.1.1
 	 */
 	public PluginInterface getPluginInterface();
+
+
+	/**
+	 * To save memory/CPU, views are sometimes destroyed on {@link UISWTViewEvent#TYPE_FOCUSLOST}
+	 * <P>
+	 * This allows overriding of the default behaviour
+	 * 
+	 * @since 5.6.0.1
+	 */
+	public void setDestroyOnDeactivate(boolean b);
+
+	/**
+	 * Retrieve whether this view can be destroyed on  {@link UISWTViewEvent#TYPE_FOCUSLOST}
+	 * 
+	 * @since 5.6.0.1
+	 */
+	boolean isDestroyOnDeactivate();
 	
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTViewEvent.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTViewEvent.java
index d50e1a8..37ed7eb 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTViewEvent.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTViewEvent.java
@@ -3,11 +3,12 @@
  * Created : Oct 14, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.plugins;
@@ -33,6 +31,18 @@ package org.gudy.azureus2.ui.swt.plugins;
  * @author TuxPaper
  */
 public interface UISWTViewEvent {
+	public static final String[] DEBUG_TYPES = {
+		"Create",
+		"DS",
+		"Init",
+		"FocusG",
+		"FocusL",
+		"Refr",
+		"Lang",
+		"Destr",
+		"Close"
+	};
+	
 	/**
 	 * Triggered before view is initialize in order to allow any set up before
 	 * initialization
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTViewEventListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTViewEventListener.java
index d71e723..f640a01 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTViewEventListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/plugins/UISWTViewEventListener.java
@@ -3,11 +3,12 @@
  * Created : Oct 14, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.plugins;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/AbstractUISWTInputReceiver.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/AbstractUISWTInputReceiver.java
index d9aa3f3..6eab926 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/AbstractUISWTInputReceiver.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/AbstractUISWTInputReceiver.java
@@ -1,7 +1,7 @@
 /*
  * Created on 13-Nov-2006
  * Created by Allan Crooks
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl;
 
@@ -30,12 +27,19 @@ import org.gudy.azureus2.ui.swt.plugins.UISWTInputReceiver;
 public abstract class AbstractUISWTInputReceiver extends AbstractUIInputReceiver 
 	implements UISWTInputReceiver {
 
-	protected boolean select_preentered_text = true;
+	protected boolean 	select_preentered_text 			= true;
+	protected int[]		select_preentered_text_range 	= null;
+	
 	public void selectPreenteredText(boolean select) {
 		this.assertPrePrompt();
 		this.select_preentered_text = select;
 	}
 	
+	public void selectPreenteredTextRange(int[] range) {
+		this.assertPrePrompt();
+		this.select_preentered_text_range = range;
+	}
+	
 	protected int line_height = -1;
 	public void setLineHeight(int line_height) {
 		this.assertPrePrompt();
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginConfigImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginConfigImpl.java
index 6f70e89..f23efd3 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginConfigImpl.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginConfigImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 28-Apr-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -28,36 +25,35 @@ package org.gudy.azureus2.ui.swt.pluginsimpl;
  */
 
 import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
+import java.util.*;
 import java.util.List;
-import java.util.Map;
 
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.graphics.RGB;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.layout.RowLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Listener;
+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.AERunnable;
 import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.ui.config.ActionParameter;
-import org.gudy.azureus2.plugins.ui.config.ConfigSection;
-import org.gudy.azureus2.plugins.ui.config.EnablerParameter;
-import org.gudy.azureus2.plugins.ui.config.ParameterListener;
+import org.gudy.azureus2.plugins.ui.config.*;
 import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
 import org.gudy.azureus2.pluginsimpl.local.ui.config.*;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.config.*;
 import org.gudy.azureus2.ui.swt.components.LinkLabel;
+import org.gudy.azureus2.ui.swt.config.*;
+import org.gudy.azureus2.ui.swt.config.BooleanParameter;
+import org.gudy.azureus2.ui.swt.config.DirectoryParameter;
+import org.gudy.azureus2.ui.swt.config.InfoParameter;
+import org.gudy.azureus2.ui.swt.config.IntParameter;
+import org.gudy.azureus2.ui.swt.config.Parameter;
+import org.gudy.azureus2.ui.swt.config.PasswordParameter;
+import org.gudy.azureus2.ui.swt.config.StringListParameter;
+import org.gudy.azureus2.ui.swt.config.StringParameter;
 import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
 import org.gudy.azureus2.ui.swt.plugins.UISWTParameterContext;
@@ -160,15 +156,21 @@ BasicPluginConfigImpl
 		main_tab.setLayout(layout);
 		
 		final Map	comp_map	= new HashMap();
+				
+		Composite current_composite	= main_tab;
 		
-		ParameterGroupImpl	current_group	= null;
+		Map<ParameterGroupImpl,Composite>		group_map 		= new HashMap<ParameterGroupImpl, Composite>();
+		
+		Map<ParameterTabFolderImpl,CTabFolder>	tab_folder_map	= new HashMap<ParameterTabFolderImpl, CTabFolder>();
+		Map<ParameterGroupImpl,Composite>		tab_map			= new HashMap<ParameterGroupImpl, Composite>();
 		
-		Composite current_composite	= main_tab;
 		
 		BasicPluginConfigModel	model = model_ref.get();
 
 		org.gudy.azureus2.plugins.ui.config.Parameter[] parameters = model.getParameters();
 		
+		List<Button>	buttons = new ArrayList<Button>();
+		
 		for (int i=0;i<parameters.length;i++){
 			
 			final ParameterImpl	param = 	(ParameterImpl)parameters[i];
@@ -186,25 +188,168 @@ BasicPluginConfigImpl
 				
 			}else{
 			
-				if ( pg != current_group ){
+				ParameterTabFolderImpl	tab_folder = pg.getTabFolder();
+				
+				if ( tab_folder != null ){
+
+					ParameterGroupImpl tab_group = tab_folder.getGroup();
+			
+					CTabFolder	tf = tab_folder_map.get( tab_folder );
 					
-					current_group	= pg;
+					if ( tf == null ){
+											
+						Composite tab_parent = current_composite;
+												
+						if ( tab_group != null ){
+							
+							String tg_resource = tab_group.getResourceName();
+							
+							if ( tg_resource != null ){
+														
+								tab_parent = group_map.get( tab_group );
+								
+								if ( tab_parent == null ){
+									
+									tab_parent = new Group( current_composite, SWT.NULL);
+									
+									Messages.setLanguageText(tab_parent, tg_resource );
+																	
+									GridData gridData = new GridData(GridData.FILL_HORIZONTAL );
+									
+									gridData.horizontalSpan = 2;
+									
+									if ( tab_group.getMinimumRequiredUserMode() > userMode ){
+										
+										tab_parent.setVisible( false );
+										
+										gridData.widthHint = 0;
+										gridData.heightHint = 0;
+									}
+									
+									tab_parent.setLayoutData(gridData);
+
+									layout = new GridLayout();
+									
+									layout.numColumns = tab_group.getNumberColumns() * 2;
+									
+									tab_parent.setLayout(layout);
+									
+									group_map.put( tab_group, tab_parent );
+								}
+							}
+						}
+												
+						tf = new CTabFolder( tab_parent, SWT.LEFT );
+						
+						tf.setBorderVisible( tab_group == null );
+						
+						tf.setTabHeight(20);
+						
+						GridData grid_data = new GridData( GridData.FILL_HORIZONTAL );
+						
+						grid_data.horizontalSpan = 2;
+						
+						if ( tab_folder.getMinimumRequiredUserMode() > userMode ){
+							
+							tf.setVisible( false );
+							
+							grid_data.widthHint = 0;
+							grid_data.heightHint = 0;
+						}
+						
+						tf.setLayoutData(grid_data);
+						
+						tab_folder_map.put( tab_folder, tf );
+					}
 					
-					current_composite = new Group(main_tab, SWT.NULL);
+					Composite tab_composite = tab_map.get( pg );
+
+					if ( tab_composite == null ){
+												
+						CTabItem tab_item = new CTabItem(tf, SWT.NULL);
+						
+						String tab_name = pg.getResourceName();
+						
+						if ( tab_name != null ){
+							
+							Messages.setLanguageText( tab_item, tab_name );
+						}
+						
+						tab_composite = new Composite( tf, SWT.NULL );
+						tab_item.setControl( tab_composite );
+						
+						layout = new GridLayout();
+						layout.numColumns = 2;
+						
+						tab_composite.setLayout(layout);
+						
+						GridData grid_data = new GridData(GridData.FILL_BOTH);
+						
+						if ( pg.getMinimumRequiredUserMode() > userMode ){
+							
+							tab_composite.setVisible( false );
+							
+							grid_data.widthHint = 0;
+							grid_data.heightHint = 0;
+						}
+						
+						tab_composite.setLayoutData( grid_data );
+							
+						if ( tf.getItemCount() == 1 ){
+						
+							tf.setSelection( tab_item );
+						}
+						
+						tab_map.put( pg, tab_composite );
+					}
 					
-					Messages.setLanguageText(current_composite, current_group.getResourceName());
+					current_composite = tab_composite;
+				}
+									
+				Composite comp = group_map.get( pg );
 					
-					GridData gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL);
+				if ( comp == null ){
+				
+					boolean nested = pg.getGroup() != null || tab_folder != null;
+					
+					Composite group_parent = nested?current_composite:main_tab;
+					
+					String resource_name = pg.getResourceName();
 					
-					gridData.horizontalSpan = 2;
+					boolean use_composite = resource_name == null || tab_folder != null;
 					
-					current_composite.setLayoutData(gridData);
+					current_composite = use_composite?new Composite( group_parent, SWT.NULL ):new Group( group_parent, SWT.NULL);
+					
+					if ( !use_composite ){
+					
+						Messages.setLanguageText(current_composite, resource_name );
+					}
+					
+					GridData grid_data = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL);
+					
+					grid_data.horizontalSpan = 2;
+					
+					if ( pg.getMinimumRequiredUserMode() > userMode ){
+						
+						current_composite.setVisible( false );
+						
+						grid_data.widthHint = 0;
+						grid_data.heightHint = 0;
+					}
+					
+					current_composite.setLayoutData( grid_data );
 					
 					layout = new GridLayout();
 					
-					layout.numColumns = 2;
+					layout.numColumns = pg.getNumberColumns() * 2;
+					
+					current_composite.setLayout(layout);
 					
-					current_composite.setLayout(layout);			
+					group_map.put( pg, current_composite );
+				
+				}else{
+					
+					current_composite = comp;
 				}
 			}
 			
@@ -385,7 +530,7 @@ BasicPluginConfigImpl
 						area, key, color_param.getRedValue(),
 						color_param.getGreenValue(), color_param.getBlueValue()) {
 					
-					public void newColorSet() {
+					public void newColorSet(RGB newColor) {
 						color_param.reloadParamDataFromConfig(true);
 						if (reset_button_holder[0] == null) {return;}
 						reset_button_holder[0].getControl().setEnabled(true);
@@ -497,8 +642,11 @@ BasicPluginConfigImpl
 				
 				if ( _param.getStyle() == ActionParameter.STYLE_BUTTON ){
 				
-					swt_param = new ButtonParameter( current_composite, _param.getActionResource());
+					ButtonParameter bp = new ButtonParameter( current_composite, _param.getActionResource());
+					
+					swt_param = bp;
 				
+					buttons.add( bp.getButton());
 				}else{
 					
 					swt_param = new LinkParameter( current_composite, _param.getActionResource());					
@@ -543,6 +691,14 @@ BasicPluginConfigImpl
 				else {
 					swt_param = null;
 				}
+			} else if ( param instanceof UITextAreaImpl ){
+				
+				swt_param = new TextAreaParameter(current_composite, ((UITextAreaImpl)param));
+				
+				GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+				gridData.horizontalSpan	= 2;
+				gridData.heightHint = 100;
+				swt_param.setLayoutData( gridData );
 				
 			}else{
 				
@@ -551,7 +707,8 @@ BasicPluginConfigImpl
 				GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
 				gridData.horizontalSpan	= 2;
 				// for wrap to work
-		    gridData.widthHint = 300;
+		  
+				gridData.widthHint = 300;
 				
 				label.setLayoutData( gridData );
 				
@@ -589,6 +746,11 @@ BasicPluginConfigImpl
 			}
 		}
 		
+		if ( buttons.size() > 1 ){
+			
+			Utils.makeButtonsEqualWidth( buttons );
+		}
+		
 		// Only need one instance
 		ParameterImplListener parameterImplListener = new ParameterImplListener() {
 			
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginViewImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginViewImpl.java
index 80d747e..94c0b94 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginViewImpl.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/BasicPluginViewImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-Apr-2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -41,13 +38,14 @@ import org.gudy.azureus2.plugins.ui.components.UIPropertyChangeListener;
 import org.gudy.azureus2.plugins.ui.model.BasicPluginViewModel;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.components.BufferedLabel;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTView;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
 
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 
 
 /**
@@ -55,7 +53,7 @@ import com.aelitis.azureus.ui.UIFunctionsManager;
  */
 public class 
 BasicPluginViewImpl 
-	implements UISWTViewEventListener, UIPropertyChangeListener 
+	implements UISWTViewCoreEventListenerEx, UIPropertyChangeListener 
 {
   
   BasicPluginViewModel model;
@@ -81,6 +79,18 @@ BasicPluginViewImpl
     isCreated = false;
   }
   
+	public boolean
+	isCloneable()
+	{
+		return( true );
+	}
+	
+	public UISWTViewCoreEventListener
+	getClone()
+	{
+		return( new BasicPluginViewImpl( model ));
+	}
+	
   public BasicPluginViewModel
   getModel()
   {
@@ -221,9 +231,10 @@ BasicPluginViewImpl
     		public void widgetSelected(SelectionEvent e) {
        	 UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
       	 if (uiFunctions != null) {
-      		 uiFunctions.openView(UIFunctions.VIEW_CONFIG,
+						uiFunctions.getMDI().showEntryByID(
+								MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
 								model.getConfigSectionID());
-      	 }
+	      	 }
     		}
     	});
     	btnConfig.setLayoutData(new GridData());
@@ -249,6 +260,18 @@ BasicPluginViewImpl
     	gridData = new GridData(GridData.FILL_BOTH);
     	gridData.horizontalSpan = 2;
     	log.setLayoutData(gridData);
+    	
+		ClipboardCopy.addCopyToClipMenu(
+				log,
+				new ClipboardCopy.copyToClipProvider()
+				{
+					public String 
+					getText() 
+					{
+						return( log.getText().trim());
+					}
+				});
+		
     	//String	text = model.getLogArea().getText().trim();
     	//log.setText( text);
     	//log.setTopIndex(log.getLineCount());
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIMessageImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIMessageImpl.java
index 7a39a2f..768888b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIMessageImpl.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIMessageImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12 Apr 2008
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.pluginsimpl;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTGraphicImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTGraphicImpl.java
index eee7746..580d1c4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTGraphicImpl.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTGraphicImpl.java
@@ -2,11 +2,12 @@
  * Created on 2004/May/23
  * Created by TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.pluginsimpl;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTInstanceImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTInstanceImpl.java
index afed21e..92fddea 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTInstanceImpl.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTInstanceImpl.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-Sep-2005
  * Created by Paul Gardner
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -42,8 +39,6 @@ import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.util.AERunnable;
 import org.gudy.azureus2.core3.util.AETemporaryFileHandler;
 import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.PluginEvent;
-import org.gudy.azureus2.plugins.PluginEventListener;
 import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.download.Download;
 import org.gudy.azureus2.plugins.torrent.Torrent;
@@ -72,11 +67,11 @@ import org.gudy.azureus2.ui.swt.views.table.utils.TableContextMenuManager;
 import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
 
 import com.aelitis.azureus.ui.IUIIntializer;
-import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.common.table.TableColumnCore;
 import com.aelitis.azureus.ui.common.table.TableStructureEventDispatcher;
 import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl;
 import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 
@@ -86,6 +81,7 @@ UISWTInstanceImpl
 {
 	private Map<BasicPluginConfigModel,BasicPluginConfigImpl> 	config_view_map = new WeakHashMap<BasicPluginConfigModel,BasicPluginConfigImpl>();
 	
+	// Map<ParentId, Map<ViewId, Listener>>
 	private Map<String,Map<String,UISWTViewEventListenerHolder>> views = new HashMap<String,Map<String,UISWTViewEventListenerHolder>>();
 
 	private Map<PluginInterface,UIInstance>	plugin_map = new WeakHashMap<PluginInterface,UIInstance>();
@@ -94,6 +90,13 @@ UISWTInstanceImpl
 
 	private final UIFunctionsSWT 		uiFunctions;
 	
+	public static interface SWTViewListener {
+		public void setViewAdded(String parent, String id, UISWTViewEventListener l);
+		public void setViewRemoved(String parent, String id, UISWTViewEventListener l);
+	}
+	
+	private List<SWTViewListener> listSWTViewListeners = new ArrayList<SWTViewListener>(0);
+	
 	public UISWTInstanceImpl() {
 		// Since this is a UI **SWT** Instance Implementor, it's assumed
 		// that the UI Functions are of UIFunctionsSWT 
@@ -502,7 +505,8 @@ UISWTInstanceImpl
 				
 				event.setResult(Boolean.TRUE);
 	    	
-				uiFunctions.openView(UIFunctions.VIEW_CONFIG, data);
+				uiFunctions.getMDI().showEntryByID(
+						MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG, data);
 
 				break;
 			}
@@ -621,6 +625,19 @@ UISWTInstanceImpl
 				}
 			});
 		}
+		
+		SWTViewListener[] viewListeners = listSWTViewListeners.toArray(new SWTViewListener[0]);
+		for (SWTViewListener l : viewListeners) {
+			l.setViewAdded(sParentID, sViewID, holder);
+		}
+	}
+	
+	public void addSWTViewListener(SWTViewListener l) {
+		listSWTViewListeners.add(l);
+	}
+	
+	public void removeSWTViewListener(SWTViewListener l) {
+		listSWTViewListeners.remove(l);
 	}
 	
 	// TODO: Remove views from PeersView, etc
@@ -642,6 +659,14 @@ UISWTInstanceImpl
 				}
 			});
 		}
+
+		SWTViewListener[] viewListeners = listSWTViewListeners.toArray(new SWTViewListener[0]);
+		for (UISWTViewEventListener holder : subViews.values()) {
+  		for (SWTViewListener l : viewListeners) {
+  			l.setViewRemoved(sParentID, sViewID, holder);
+  		}
+		}
+
 		subViews.remove(sViewID);
 	}
 
@@ -781,10 +806,12 @@ UISWTInstanceImpl
 		return array;
 	}
 	
+	// @see org.gudy.azureus2.plugins.ui.UIInstance#getInputReceiver()
 	public UIInputReceiver getInputReceiver() {
 		return new SimpleTextEntryWindow();
 	}
 	
+	// @see org.gudy.azureus2.plugins.ui.UIInstance#createMessage()
 	public UIMessage createMessage() {
 		return new UIMessageImpl();
 	}
@@ -814,7 +841,9 @@ UISWTInstanceImpl
 	public void openConfig(final BasicPluginConfigModel model) {
 		Utils.execSWTThread(new Runnable() {
 			public void run() {
-	    	uiFunctions.openView(UIFunctions.VIEW_CONFIG, model.getSection());
+				uiFunctions.getMDI().loadEntryByID(
+						MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG, true, false,
+						model.getSection());
 			}
 		});
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTStatusEntryImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTStatusEntryImpl.java
index 0e8b419..187f8bf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTStatusEntryImpl.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTStatusEntryImpl.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.pluginsimpl;
 
 import java.util.Iterator;
@@ -116,7 +131,7 @@ public class UISWTStatusEntryImpl implements UISWTStatusEntry, MainStatusBar.CLa
 		}
 	}
 
-	private void update0(final CLabelPadding label) {
+	private void update0(CLabelPadding label) {
 		label.setText(text);
 		label.setToolTipText(tooltip);
 		label.setImage(image_enabled ? image : null);
@@ -133,7 +148,7 @@ public class UISWTStatusEntryImpl implements UISWTStatusEntry, MainStatusBar.CLa
 			    new MenuBuildUtils.MenuBuilder() {
 					public void buildMenu(Menu menu, MenuEvent menuEvent) {
 						MenuItem[] items = MenuItemManager.getInstance().getAllAsArray(menu_context.context);
-						MenuBuildUtils.addPluginMenuItems(label, items, menu, true, true, 
+						MenuBuildUtils.addPluginMenuItems(items, menu, true, true, 
 							MenuBuildUtils.BASIC_MENU_ITEM_CONTROLLER);
 					}
 				}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCore.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCore.java
index 24bf1b0..4ec3d78 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCore.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCore.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.pluginsimpl;
 
 import org.eclipse.swt.widgets.Composite;
@@ -14,6 +32,7 @@ import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
 public interface UISWTViewCore
 	extends UISWTView
 {
+	// XXX ControlType never seems to be set to this.. could remove?
 	public static final int CONTROLTYPE_SKINOBJECT = 0x100 + 1;
 
 	// >> From IView
@@ -53,9 +72,9 @@ public interface UISWTViewCore
   
   // << From IView
 
-	public void setSkinObject(PluginUISWTSkinObject so, Composite composite);
+	public void setPluginSkinObject(PluginUISWTSkinObject so);
 	
-	public PluginUISWTSkinObject getSkinObject();
+	public PluginUISWTSkinObject getPluginSkinObject();
 	
 	public void setUseCoreDataSource(boolean useCoreDataSource);
 
@@ -71,4 +90,6 @@ public interface UISWTViewCore
 	public Object
 	getUserData(
 		Object		key );
+
+	public void setParentView(UISWTView parentView);
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCoreEventListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCoreEventListener.java
index cd1174a..280f508 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCoreEventListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCoreEventListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Aug 14, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCoreEventListenerEx.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCoreEventListenerEx.java
new file mode 100644
index 0000000..b7b8f5c
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewCoreEventListenerEx.java
@@ -0,0 +1,34 @@
+/*
+ * Created on Mar 18, 2015
+ * Created by Paul Gardner
+ * 
+ * Copyright 2015 Azureus Software, 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 org.gudy.azureus2.ui.swt.pluginsimpl;
+
+public interface 
+UISWTViewCoreEventListenerEx
+	extends UISWTViewCoreEventListener
+{
+	public boolean
+	isCloneable();
+	
+	public UISWTViewCoreEventListener
+	getClone();
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventCancelledException.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventCancelledException.java
index 8d6687d..7764333 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventCancelledException.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventCancelledException.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 20, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventImpl.java
index fb77113..22d2ffc 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventImpl.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventImpl.java
@@ -3,11 +3,12 @@
  * Created : Oct 14, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.pluginsimpl;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventListenerHolder.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventListenerHolder.java
index e44613d..245b839 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventListenerHolder.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewEventListenerHolder.java
@@ -2,20 +2,19 @@
  * Created on Oct 19, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -145,7 +144,11 @@ UISWTViewEventListenerHolder
 						Debug.out(e);
 						return false;
 					}
-				} else if (mapSWTViewToEventListener != null) {
+				} else if (type == UISWTViewEvent.TYPE_DATASOURCE_CHANGED) {
+					datasource = event.getData();
+				}
+				
+				if (mapSWTViewToEventListener != null) {
 					if (type == UISWTViewEvent.TYPE_DESTROY) {
 						eventListener = mapSWTViewToEventListener.remove(event.getView());
 					} else {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewImpl.java
index b4130ff..a7fe94d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewImpl.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UISWTViewImpl.java
@@ -3,11 +3,12 @@
  * Created : Oct 14, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,136 +18,209 @@
  * 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.pluginsimpl;
 
 import java.awt.Frame;
 import java.awt.Panel;
-import java.util.HashMap;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.awt.SWT_AWT;
 import org.eclipse.swt.custom.CTabFolder;
 import org.eclipse.swt.custom.CTabItem;
 import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.*;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.FormLayout;
+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.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.AERunnable;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.LightHashMap;
 import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
 import org.gudy.azureus2.plugins.ui.UIRuntimeException;
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarEnablerBase;
 import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.debug.ObfusticateImage;
-import org.gudy.azureus2.ui.swt.plugins.*;
+import org.gudy.azureus2.ui.swt.plugins.PluginUISWTSkinObject;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
+import org.gudy.azureus2.ui.swt.views.IViewAlwaysInitialize;
 
-import com.aelitis.azureus.ui.common.ToolBarEnabler;
 import com.aelitis.azureus.ui.common.ToolBarItem;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 import com.aelitis.azureus.util.MapUtils;
 
 /**
- * This class creates an IView that triggers UISWTViewEventListener 
+ * This class creates an view that triggers {@link UISWTViewEventListener} 
  * appropriately
  * 
  * @author TuxPaper
  *
  */
 public class UISWTViewImpl
-	implements UISWTViewCore, AEDiagnosticsEvidenceGenerator
+	implements UISWTViewCore, UIPluginViewToolBarListener
 {
 	public static final String CFG_PREFIX = "Views.plugins.";
 
-	private PluginUISWTSkinObject skinObject;
+	private boolean delayInitializeToFirstActivate = true;
+
+	private static final boolean DEBUG_TRIGGERS = false;
+
+	// TODO: not protected
+	protected PluginUISWTSkinObject skinObject;
+
+	private Object initialDatasource;
+
+	// different from parentID?
+	private UISWTView parentView;
 
-	private Object dataSource = null;
+	/* Always Core */
+	protected Object datasource;
 
 	private boolean useCoreDataSource = false;
 
-	private final UISWTViewEventListener eventListener;
+	private UISWTViewEventListener eventListener;
 
-	private Composite composite;
+	// This is the same as TabbedEntry.swtItem.getControl and something in SideBarEntry
+	// TODO: not protected
+	protected Composite composite;
 
-	private final String sViewID;
+	protected final String id;
+
+	private String title;
+	
+	private String titleID;
 
 	private int iControlType = UISWTView.CONTROLTYPE_SWT;
 
-	private boolean bFirstGetCompositeCall = true;
+	private Boolean hasFocus = null;
 
-	//private final String sParentID;
+	private Map<Object, Object> user_data;
 
-	private String sTitle = null;
+	private boolean haveSentInitialize = false;
 
-	private String lastFullTitleKey = null;
+	private boolean created = false;
 
-	private String lastFullTitle = "";
+	private String parentViewID;
 
-	//private Boolean hasFocus = null;
+	private boolean destroyOnDeactivate;
 
-	private UIPluginViewToolBarListener toolbarListener;
+	private Composite masterComposite;
 
-	private volatile Map<Object,Object>	user_data;
-	
-	public UISWTViewImpl(String sParentID, String sViewID,
-			UISWTViewEventListener eventListener, Object initialDatasource)
-			throws Exception {
-		//this.sParentID = sParentID;
-		this.sViewID = sViewID;
-		this.eventListener = eventListener;
-		if (eventListener instanceof UISWTViewCoreEventListener) {
-			useCoreDataSource = true;
-		}
-
-		AEDiagnostics.addEvidenceGenerator(this);
+	private Set<UIPluginViewToolBarListener> setToolBarEnablers = new HashSet<UIPluginViewToolBarListener>(1);
 
-		if (initialDatasource != null) {
-			triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, initialDatasource);
+	public UISWTViewImpl(String id, String parentViewID, boolean destroyOnDeactivate) {
+		this.id = id;
+		this.parentViewID = parentViewID;
+		this.destroyOnDeactivate = destroyOnDeactivate;
+		this.titleID = CFG_PREFIX + this.id + ".title";
+		if (!MessageText.keyExists(titleID) && MessageText.keyExists(this.id)){
+			this.titleID = id;
 		}
+	}
 
-			// we could pass the parentid as the data for the create call but unfortunately
-			// there's a bunch of crap out there that assumes that data is the view object :(
-		if (!eventListener.eventOccurred(new UISWTViewEventImpl(sParentID, this,
-				UISWTViewEvent.TYPE_CREATE, this)))
+	public void setEventListener(UISWTViewEventListener _eventListener,
+			boolean doCreate)
+					throws UISWTViewEventCancelledException {
+		this.eventListener = _eventListener;
+	
+		if (eventListener == null) {
+			return;
+		}
+	
+		if (_eventListener instanceof UISWTViewEventListenerHolder) {
+			UISWTViewEventListenerHolder h = (UISWTViewEventListenerHolder) _eventListener;
+			UISWTViewEventListener delegatedEventListener = h.getDelegatedEventListener(
+					this);
+			if (delegatedEventListener != null) {
+				this.eventListener = delegatedEventListener;
+			}
+		}
+	
+		if (eventListener instanceof IViewAlwaysInitialize) {
+			delayInitializeToFirstActivate = false;
+		}
+	
+		if (eventListener instanceof UISWTViewCoreEventListener) {
+			setUseCoreDataSource(true);
+		}
+	
+		// >> from UISWTViewImpl
+		// we could pass the parentid as the data for the create call but unfortunately
+		// there's a bunch of crap out there that assumes that data is the view object :(
+		if (doCreate && !triggerBooleanEvent(UISWTViewEvent.TYPE_CREATE, this)) {
 			throw new UISWTViewEventCancelledException();
-
+		}
+		// <<
 	}
 
 	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore#getEventListener()
+	 * @see com.aelitis.azureus.ui.swt.mdi.MdiEntrySWT#getEventListener()
 	 */
 	public UISWTViewEventListener getEventListener() {
 		return eventListener;
 	}
 
-	// UISWTPluginView implementation
-	// ==============================
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.ui.swt.plugins.UISWTView#getInitialDataSource()
+	 */
+	public Object getInitialDataSource() {
+		return initialDatasource;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#setDatasource(java.lang.Object)
+	 */
+	public void setDatasource(Object datasource) {
+		if (initialDatasource == null) {
+			initialDatasource = datasource;
+		}
+		triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, datasource);
+	}
 
 	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.ui.swt.plugins.UISWTView#getDataSource()
 	 */
+	// XXX There's also a getDatasource().. lowercase S :(
+	// It doesn't use useCoreDataSource and should be either removed or renamed
+	// to getDataSourcePlugin
 	public Object getDataSource() {
-		return dataSource;
+		return PluginCoreUtils.convert(datasource, useCoreDataSource());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore#setParentView(org.gudy.azureus2.ui.swt.plugins.UISWTView)
+	 */
+	public void setParentView(UISWTView parentView) {
+		this.parentView = parentView;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.ui.swt.plugins.UISWTView#getParentView()
+	 */
+	public UISWTView getParentView() {
+		return parentView;
 	}
 
 	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.plugins.ui.UIPluginView#getViewID()
 	 */
+	// XXX Same as getID().. remove getID?
 	public String getViewID() {
-		return sViewID;
+		return id;
 	}
 
 	/* (non-Javadoc)
@@ -155,25 +229,25 @@ public class UISWTViewImpl
 	public void closeView() {
 		try {
 
-			UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
-			if (uiFunctions != null) {
-				uiFunctions.closePluginView(this);
-			}
-			
+			// In theory mdi.closeEntry will dispose of the swtItem (ctabitem or other)
+			// via #close(false).  Not sure what happens to composite though,
+			// so I don't know fi that TYPE_DESTROY actually gets called
+			// The CTabItem scan seems pointless now, though
+
 			Composite c = getComposite();
-			
-			if ( c != null && !c.isDisposed()){
-			
+
+			if (c != null && !c.isDisposed()) {
+
 				Composite parent = c.getParent();
-				
-				triggerEvent( UISWTViewEvent.TYPE_DESTROY, null );
-				
-				if ( parent instanceof CTabFolder ){
-					
-					for ( CTabItem item: ((CTabFolder)parent).getItems()){
-						
-						if ( item.getControl() == c ){
-							
+
+				triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
+
+				if (parent instanceof CTabFolder) {
+
+					for (CTabItem item : ((CTabFolder) parent).getItems()) {
+
+						if (item.getControl() == c) {
+
 							item.dispose();
 						}
 					}
@@ -182,6 +256,7 @@ public class UISWTViewImpl
 		} catch (Throwable e) {
 			Debug.out(e);
 		}
+
 	}
 
 	/* (non-Javadoc)
@@ -189,8 +264,9 @@ public class UISWTViewImpl
 	 */
 	public void setControlType(int iControlType) {
 		if (iControlType == CONTROLTYPE_AWT || iControlType == CONTROLTYPE_SWT
-				|| iControlType == CONTROLTYPE_SKINOBJECT)
+				|| iControlType == CONTROLTYPE_SKINOBJECT) {
 			this.iControlType = iControlType;
+		}
 	}
 
 	/* (non-Javadoc)
@@ -204,55 +280,197 @@ public class UISWTViewImpl
 	 * @see org.gudy.azureus2.ui.swt.plugins.UISWTView#triggerEvent(int, java.lang.Object)
 	 */
 	public void triggerEvent(int eventType, Object data) {
+		try {
+			triggerBooleanEvent(eventType, data);
+		} catch (Exception e) {
+			// TODO: Better error
+			Debug.out(e);
+		}
+	}
+	
+	private static String padRight(String s, int n) {
+    return String.format("%1$-" + n + "s", s);  
+	}
+
+	private boolean triggerBooleanEvent(int eventType, Object data) {
+		if (DEBUG_TRIGGERS) {
+			if (eventListener == null || eventType != UISWTViewEvent.TYPE_REFRESH) {
+				System.out.println(System.currentTimeMillis() + "." + padRight(id, 20)
+						+ "] " + "trigger "
+						+ padRight((eventType < UISWTViewEvent.DEBUG_TYPES.length
+								? UISWTViewEvent.DEBUG_TYPES[eventType] : "" + eventType), 6)
+						+ ", " + (eventListener == null ? "null" : "nonn") + ";data="
+						+ (data instanceof Object[] ? Arrays.toString((Object[]) data)
+								: data)
+						+ "/ds="
+						+ (datasource instanceof Object[]
+								? Arrays.toString((Object[]) datasource) : datasource)
+						+ ";" + title + ";" + Debug.getCompressedStackTrace());
+			}
+		}
+		if (eventListener == null
+				&& eventType != UISWTViewEvent.TYPE_DATASOURCE_CHANGED) {
+			return false;
+		}
+	
+		if (eventType == UISWTViewEvent.TYPE_INITIALIZE) {
+			if (haveSentInitialize) {
+				if (DEBUG_TRIGGERS) {
+					System.out.println("  -> already haveSentInitialize");
+				}
+				return false;
+			}
+			if (!created) {
+				// create will set DS changed
+				triggerBooleanEvent(UISWTViewEvent.TYPE_CREATE, this);
+			} else if (datasource != null) {
+				triggerBooleanEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, datasource);
+			}
+			haveSentInitialize = true;
+		}
+	
+		if (eventType == UISWTViewEvent.TYPE_CREATE) {
+			created = true;
+		}
+	
+		if (delayInitializeToFirstActivate
+				&& eventType == UISWTViewEvent.TYPE_FOCUSGAINED
+				&& !haveSentInitialize) {
+			swt_triggerInitialize();
+		}
 		// prevent double fire of focus gained/lost
-		/* erm, this code doesn't do anything atm as nothing is setting hasFocus, removing for the moment
 		if (eventType == UISWTViewEvent.TYPE_FOCUSGAINED && hasFocus != null
 				&& hasFocus) {
-			return;
+			if (DEBUG_TRIGGERS) {
+				System.out.println("  -> already hasFocus");
+			}
+			return true;
 		}
 		if (eventType == UISWTViewEvent.TYPE_FOCUSLOST && hasFocus != null
 				&& !hasFocus) {
-			return;
+			if (DEBUG_TRIGGERS) {
+				System.out.println("  -> already !hasFocus");
+			}
+			return true;
 		}
-		*/
+	
 		if (eventType == UISWTViewEvent.TYPE_DATASOURCE_CHANGED) {
-			Object newDataSource = PluginCoreUtils.convert(data, useCoreDataSource);
-			if (dataSource == newDataSource) {
-				return;
+			Object newDataSource = PluginCoreUtils.convert(data, true);
+			if (datasource == newDataSource) {
+				if (DEBUG_TRIGGERS) {
+					System.out.println("  -> same DS, skip");
+				}
+				return true;
+			}
+			if (newDataSource instanceof Object[] && datasource instanceof Object[]) {
+				if (Arrays.equals((Object[]) newDataSource, (Object[]) datasource)) {
+					if (DEBUG_TRIGGERS) {
+						System.out.println("  -> same DS[], skip");
+					}
+					return true;
+				}
 			}
-			data = dataSource = newDataSource;
+			datasource = newDataSource;
+			data = PluginCoreUtils.convert(datasource, useCoreDataSource);
+			if (initialDatasource == null) {
+				initialDatasource = datasource;
+			}
+			if (eventListener == null) {
+				return true;
+			}
+			// TODO: What about triggering skinObject's EVENT_DATASOURCE_CHANGED?
 		} else if (eventType == UISWTViewEvent.TYPE_LANGUAGEUPDATE) {
-			lastFullTitle = "";
+			//lastFullTitle = "";
+			System.out.println(eventListener.getClass().getSimpleName());
+			if (eventListener.getClass().getSimpleName().startsWith("SBC_My")) {
+				System.out.println("STOP");
+			}
 			Messages.updateLanguageForControl(getComposite());
 		} else if (eventType == UISWTViewEvent.TYPE_OBFUSCATE
 				&& (eventListener instanceof ObfusticateImage)) {
 			if (data instanceof Map) {
-				((ObfusticateImage) eventListener).obfusticatedImage((Image) MapUtils.getMapObject(
-						(Map) data, "image", null, Image.class));
+				((ObfusticateImage) eventListener).obfusticatedImage(
+						(Image) MapUtils.getMapObject((Map<?, ?>) data, "image", null,
+								Image.class));
+			}
+		} else if (eventType == UISWTViewEvent.TYPE_FOCUSGAINED) {
+			hasFocus = true;
+			if (!haveSentInitialize) {
+				swt_triggerInitialize();
+			}
+		} else if (eventType == UISWTViewEvent.TYPE_FOCUSLOST) {
+			hasFocus = false;
+			if (isDestroyOnDeactivate()) {
+				triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
+			}
+		} else if (eventType == UISWTViewEvent.TYPE_DESTROY) {
+			if (hasFocus != null && hasFocus) {
+				triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
+			}
+			// focus lost may have destroyed us already
+			if (!created && !haveSentInitialize && getComposite() == null) {
+				return true;
 			}
 		}
-
+	
+		boolean result = false;
 		try {
-			eventListener.eventOccurred(new UISWTViewEventImpl(null,this, eventType, data));
+			result = eventListener.eventOccurred(
+					new UISWTViewEventImpl(parentViewID, this, eventType, data));
 		} catch (Throwable t) {
-			Debug.out("ViewID=" + sViewID + "; EventID=" + eventType + "; data="
-					+ data, t);
+			Debug.out("ViewID=" + id + "; EventID="
+					+ UISWTViewEvent.DEBUG_TYPES[eventType] + "; data=" + data, t);
 			//throw (new UIRuntimeException("UISWTView.triggerEvent:: ViewID="
 			//		+ sViewID + "; EventID=" + eventType + "; data=" + data, t));
 		}
-		
+	
 		if (eventType == UISWTViewEvent.TYPE_DESTROY) {
-			Utils.disposeComposite(getComposite());
-		}	
+			if (masterComposite != null && !masterComposite.isDisposed()) {
+				Composite parent = masterComposite.getParent();
+				Utils.disposeComposite(masterComposite);
+				Utils.relayoutUp(parent);
+			}
+			masterComposite = null;
+			composite = null;
+			haveSentInitialize = false;
+			hasFocus = false;
+			created = false;
+			initialDatasource = datasource;
+			datasource = null;
+		} else if (eventType == UISWTViewEvent.TYPE_CREATE) {
+			if (eventListener instanceof UISWTViewEventListenerHolder) {
+				UISWTViewEventListenerHolder h = (UISWTViewEventListenerHolder) eventListener;
+				UISWTViewEventListener delegatedEventListener = h.getDelegatedEventListener(
+						this);
+				if (delegatedEventListener != null) {
+					try {
+						setEventListener(delegatedEventListener, false);
+					} catch (UISWTViewEventCancelledException e) {
+					}
+				}
+			}
+
+			if (DEBUG_TRIGGERS) {
+				System.out.println(" -> raw DS Change");
+			}
+			triggerEventRaw(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, PluginCoreUtils.convert(datasource, useCoreDataSource));
+		}
+	
+		return result;
 	}
 
 	protected boolean triggerEventRaw(int eventType, Object data) {
+		if (eventListener == null) {
+			System.err.println(
+					"null eventListener for " + UISWTViewEvent.DEBUG_TYPES[eventType] + " " + Debug.getCompressedStackTrace());
+			return eventType == UISWTViewEvent.TYPE_CLOSE ? true : false;
+		}
 		try {
-			return eventListener.eventOccurred(new UISWTViewEventImpl(null,this,
-					eventType, data));
+			return eventListener.eventOccurred(
+					new UISWTViewEventImpl(parentViewID, this, eventType, data));
 		} catch (Throwable t) {
-			throw (new UIRuntimeException("UISWTView.triggerEvent:: ViewID="
-					+ sViewID + "; EventID=" + eventType + "; data=" + data, t));
+			throw (new UIRuntimeException("UISWTView.triggerEvent:: ViewID=" + id
+					+ "; EventID=" + eventType + "; data=" + data, t));
 		}
 	}
 
@@ -260,11 +478,34 @@ public class UISWTViewImpl
 	 * @see org.gudy.azureus2.ui.swt.plugins.UISWTView#setTitle(java.lang.String)
 	 */
 	public void setTitle(String title) {
-		if ( title.contains( "." ) && MessageText.keyExists(title)){
-				// it if appears to be a resource key then resolve it here
-			title = MessageText.getString( title );
+		if (title == null) {
+			return;
+		}
+		if (title.startsWith("{") && title.endsWith("}") && title.length() > 2) {
+			setTitleID(title.substring(1, title.length() - 1));
+			return;
+		}
+		if (title.equals(this.title)) {
+			return;
+		}
+		if (title.contains(".") && MessageText.keyExists(title)) {
+			setTitleID(title);
+			return;
+		}
+	
+		this.title = title;
+		this.titleID = null;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#setTitleID(java.lang.String)
+	 */
+	public void setTitleID(String titleID) {
+		if (titleID != null
+				&& (MessageText.keyExists(titleID) || titleID.startsWith("!"))) {
+			this.titleID = titleID;
+			this.title = null;
 		}
-		sTitle = title;
 	}
 
 	/* (non-Javadoc)
@@ -274,84 +515,59 @@ public class UISWTViewImpl
 		if (eventListener instanceof UISWTViewEventListenerHolder) {
 			return (((UISWTViewEventListenerHolder) eventListener).getPluginInterface());
 		}
-
+	
 		return null;
 	}
 
-	
-	// Core Functions
-
-	
 	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore#getComposite()
 	 */
 	public Composite getComposite() {
-		if (bFirstGetCompositeCall) {
-			bFirstGetCompositeCall = false;
-		}
 		return composite;
 	}
 
-
 	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore#getTitleID()
 	 */
+	// XXX Might not be needed once StatsView, SBC_TDV, and TVSWT_TC are converted
 	public String getTitleID() {
-		if (sTitle == null) {
+		if (title == null) {
 			// still need this crappy check because some plugins still expect their
 			// view id to be their name
-			if (MessageText.keyExists(sViewID)) {
-				return sViewID;
+			if (MessageText.keyExists(id)) {
+				return id;
 			}
-			String id = CFG_PREFIX + sViewID + ".title";
+			String id = CFG_PREFIX + this.id + ".title";
 			if (MessageText.keyExists(id)) {
 				return id;
 			}
-			return "!" + sViewID + "!";
+			return "!" + id + "!";
 		}
-		return "!" + sTitle + "!";
+		return "!" + title + "!";
 	}
 
 	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore#getFullTitle()
 	 */
 	public String getFullTitle() {
-		//System.out.println("getFullTitle " + sTitle + ";" + getTitleID() + ";" + lastFullTitle + ";" + lastFullTitleKey);
-		if (sTitle != null) {
-			return sTitle;
+		if (titleID != null) {
+			return MessageText.getString(titleID);
 		}
-
-		String key = getTitleID();
-		if (key == null) {
-			return "";
-		}
-
-		if (lastFullTitle.length() > 0 && key.equals(lastFullTitleKey)) {
-			return lastFullTitle;
-		}
-
-		lastFullTitleKey = key;
-
-		if (MessageText.keyExists(key) || key.startsWith("!") && key.endsWith("!")) {
-			lastFullTitle = MessageText.getString(key);
-		} else {
-			lastFullTitle = key.replace('.', ' '); // support old plugins
-		}
-
-		return lastFullTitle;
+		return title;
 	}
 
 	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore#initialize(org.eclipse.swt.widgets.Composite)
 	 */
 	public void initialize(Composite parent) {
+		this.masterComposite = parent; 
 		if (iControlType == UISWTView.CONTROLTYPE_SWT) {
 			GridData gridData;
 			Layout parentLayout = parent.getLayout();
 			if (parentLayout instanceof FormLayout) {
 				composite = parent;
 			} else {
-				composite = new Composite(parent, SWT.NULL);
+				composite = new Composite(parent, SWT.NONE);
 				GridLayout layout = new GridLayout(1, false);
 				layout.marginHeight = 0;
 				layout.marginWidth = 0;
@@ -359,30 +575,56 @@ public class UISWTViewImpl
 				gridData = new GridData(GridData.FILL_BOTH);
 				composite.setLayoutData(gridData);
 			}
-
-			triggerEvent(UISWTViewEvent.TYPE_INITIALIZE, composite);
-
-			if (composite.getLayout() instanceof GridLayout) {
-				// Force children to have GridData layoutdata.
-				Control[] children = composite.getChildren();
-				for (int i = 0; i < children.length; i++) {
-					Control control = children[i];
-					Object layoutData = control.getLayoutData();
-					if (layoutData == null || !(layoutData instanceof GridData)) {
-						if (layoutData != null)
-							Logger.log(new LogEvent(LogIDs.PLUGIN, LogEvent.LT_WARNING,
-									"Plugin View '" + sViewID + "' tried to setLayoutData of "
-											+ control + " to a " + layoutData.getClass().getName()));
-
-						if (children.length == 1)
-							gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
-						else
-							gridData = new GridData();
-
-						control.setLayoutData(gridData);
+			
+			Listener showListener = new Listener() {
+				public void handleEvent(Event event) {
+					if (composite == null || composite.isDisposed()) {
+						return;
+					}
+					Composite parent = composite.getParent();
+					if (parent instanceof CTabFolder) {
+						CTabFolder tabFolder = (CTabFolder) parent;
+						Control selectedControl = tabFolder.getSelection().getControl();
+						if (selectedControl != composite) {
+							return;
+						}
+					} else if (parent instanceof TabFolder) {
+						TabFolder tabFolder = (TabFolder) parent;
+						TabItem[] selectedControl = tabFolder.getSelection();
+						if (selectedControl != null && selectedControl.length == 1
+								&& selectedControl[0].getControl() != composite) {
+							return;
+						}
 					}
+					// Delay trigger of FOCUSGAINED a bit, so that parent is visible
+					Utils.execSWTThreadLater(0, new AERunnable() {
+						@Override
+						public void runSupport() {
+							triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
+						}
+					});
 				}
+			};
+	
+			composite.addListener(SWT.Show, showListener);
+			if (parent != composite) {
+				parent.addListener(SWT.Show, showListener);
+			}
+			if (composite.isVisible()) {
+				boolean focusGained = true;
+				if (parent instanceof CTabFolder || (parent instanceof TabFolder)) {
+					// can't be gaining the focus yet.. we just created it and
+					// it hasn't been assigned to TabFolder yet
+					focusGained = false;
+				}
+				if (focusGained) {
+					triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
+				}
+			}
+			if (delayInitializeToFirstActivate) {
+				return;
 			}
+			swt_triggerInitialize();
 		} else if (iControlType == UISWTView.CONTROLTYPE_AWT) {
 			composite = new Composite(parent, SWT.EMBEDDED);
 			FillLayout layout = new FillLayout();
@@ -391,24 +633,63 @@ public class UISWTViewImpl
 			composite.setLayout(layout);
 			GridData gridData = new GridData(GridData.FILL_BOTH);
 			composite.setLayoutData(gridData);
-
+	
 			Frame f = SWT_AWT.new_Frame(composite);
-
+	
 			Panel pan = new Panel();
-
+	
 			f.add(pan);
-
+	
 			triggerEvent(UISWTViewEvent.TYPE_INITIALIZE, pan);
 		} else if (iControlType == UISWTViewCore.CONTROLTYPE_SKINOBJECT) {
-			triggerEvent(UISWTViewEvent.TYPE_INITIALIZE, getSkinObject());
+			triggerEvent(UISWTViewEvent.TYPE_INITIALIZE, getPluginSkinObject());
 		}
 	}
 
-	/**
-	 * @return
-	 */
-	public boolean requestClose() {
-		return triggerEventRaw(UISWTViewEvent.TYPE_CLOSE, null);
+	private void swt_triggerInitialize() {
+		if (haveSentInitialize) {
+			return;
+		}
+	
+		if (!created) {
+			triggerBooleanEvent(UISWTViewEvent.TYPE_CREATE, this);
+		}
+	
+		if ( composite != null ){
+			composite.setRedraw(false);
+			composite.setLayoutDeferred(true);
+			triggerEvent(UISWTViewEvent.TYPE_INITIALIZE, composite);
+		
+			if (composite.getLayout() instanceof GridLayout) {
+				// Force children to have GridData layoutdata.
+				Control[] children = composite.getChildren();
+				for (int i = 0; i < children.length; i++) {
+					Control control = children[i];
+					Object layoutData = control.getLayoutData();
+					if (layoutData == null || !(layoutData instanceof GridData)) {
+						if (layoutData != null) {
+							Logger.log(
+									new LogEvent(LogIDs.PLUGIN, LogEvent.LT_WARNING,
+											"Plugin View '" + id + "' tried to setLayoutData of "
+													+ control + " to a "
+													+ layoutData.getClass().getName()));
+						}
+		
+						GridData gridData;
+						if (children.length == 1) {
+							gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+						} else {
+							gridData = new GridData();
+						}
+		
+						control.setLayoutData(gridData);
+					}
+				}
+			}
+			composite.layout();
+			composite.setLayoutDeferred(false);
+			composite.setRedraw(true);
+		}
 	}
 
 	/* (non-Javadoc)
@@ -425,133 +706,159 @@ public class UISWTViewImpl
 		if (this.useCoreDataSource == useCoreDataSource) {
 			return;
 		}
-
+	
 		this.useCoreDataSource = useCoreDataSource;
-		triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, dataSource);
+		if (datasource != null) {
+			setDatasource(datasource);
+		}
 	}
 
 	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore#getSkinObject()
 	 */
-	public PluginUISWTSkinObject getSkinObject() {
+	public PluginUISWTSkinObject getPluginSkinObject() {
 		return skinObject;
 	}
 
 	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore#setSkinObject(org.gudy.azureus2.ui.swt.plugins.PluginUISWTSkinObject, org.eclipse.swt.widgets.Composite)
 	 */
-	public void setSkinObject(PluginUISWTSkinObject skinObject, Composite c) {
-		this.skinObject = skinObject;
-		this.composite = c;
+	// TODO: Combine this with the other setSkinObject..
+	public void setPluginSkinObject(PluginUISWTSkinObject so) {
+		this.skinObject = so;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator#generate(org.gudy.azureus2.core3.util.IndentWriter)
-	 */
-	public void generate(IndentWriter writer) {
-		if (eventListener instanceof AEDiagnosticsEvidenceGenerator) {
-			writer.println("View: " + sViewID + ": " + sTitle);
-
-			try {
-				writer.indent();
-
-				((AEDiagnosticsEvidenceGenerator) eventListener).generate(writer);
-			} catch (Exception e) {
-
-			} finally {
-
-				writer.exdent();
+	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
+			Object datasource) {
+		UIToolBarEnablerBase[] toolbarEnablers = getToolbarEnablers();
+		for (UIToolBarEnablerBase tbEnablerBase : toolbarEnablers) {
+			if (tbEnablerBase instanceof UIPluginViewToolBarListener) {
+				UIPluginViewToolBarListener tbEnabler = (UIPluginViewToolBarListener) tbEnablerBase;
+				if (tbEnabler.toolBarItemActivated(item, activationType, datasource)) {
+					return true;
+				}
 			}
-		} else {
-			writer.println("View (no generator): " + sViewID + ": " + sTitle);
 		}
-	}
-
-	public boolean toolBarItemActivated(ToolBarItem item, long activationType, Object datasource) {
-		if (toolbarListener != null) {
-			return toolbarListener.toolBarItemActivated(item, activationType, datasource);
-		}
-		if (eventListener instanceof UIPluginViewToolBarListener) {
-			return ((UIPluginViewToolBarListener) eventListener).toolBarItemActivated(item, activationType, datasource);
-		} else if (eventListener instanceof ToolBarEnabler) {
-			return ((ToolBarEnabler) eventListener).toolBarItemActivated(item.getID());
-		} 
 		return false;
 	}
 
 	public void refreshToolBarItems(Map<String, Long> list) {
-		if (eventListener instanceof UIPluginViewToolBarListener) {
-			((UIPluginViewToolBarListener) eventListener).refreshToolBarItems(list);
-		} else if (eventListener instanceof ToolBarEnabler) {
-			Map<String, Boolean> states = new HashMap<String, Boolean>();
-			for ( Map.Entry<String, Long> entry: list.entrySet()){
-				String id = entry.getKey();
-				states.put(id, (entry.getValue() & UIToolBarItem.STATE_ENABLED) > 0);
-			}
-			
-			((ToolBarEnabler) eventListener).refreshToolBar(states);
-
-			for ( Map.Entry<String, Boolean> entry: states.entrySet()){
-				String id = entry.getKey();
-				Boolean visible = entry.getValue();
-				list.put(id, visible ? UIToolBarItem.STATE_ENABLED : 0);
+		UIToolBarEnablerBase[] toolbarEnablers = getToolbarEnablers();
+		for (UIToolBarEnablerBase tbEnablerBase : toolbarEnablers) {
+			if (tbEnablerBase instanceof UIPluginViewToolBarListener) {
+				UIPluginViewToolBarListener tbEnabler = (UIPluginViewToolBarListener) tbEnablerBase;
+				tbEnabler.refreshToolBarItems(list);
 			}
 		}
 	}
 
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.UIPluginView#setToolBarListener(org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener)
+	 */
 	public void setToolBarListener(UIPluginViewToolBarListener l) {
-		toolbarListener = l;
+		addToolbarEnabler(l);
 	}
-	
+
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.UIPluginView#getToolBarListener()
+	 */
 	public UIPluginViewToolBarListener getToolBarListener() {
-		return toolbarListener;
+		return setToolBarEnablers.size() == 0 ? null : setToolBarEnablers.iterator().next();
+	}
+
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getToolbarEnablers()
+	 */
+	public UIToolBarEnablerBase[] getToolbarEnablers() {
+		// XXX What if eventListener is of UIPluginViewToolBarListener (as per UISWTViewImpl's check)
+		return setToolBarEnablers.toArray(new UIToolBarEnablerBase[0]);
 	}
 	
-	public void
-	setUserData(
-		Object		key,
-		Object		data )
-	{
-		synchronized( this ){
-			
-			if ( user_data == null ){
-				
-				if ( data == null ){
-					
-					return;
-				}
-				
-				user_data = new HashMap<Object, Object>();
+	public boolean hasToolbarEnableers() {
+		return setToolBarEnablers.size() > 0;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#addToolbarEnabler(org.gudy.azureus2.plugins.ui.toolbar.UIToolBarEnablerBase)
+	 */
+	public void addToolbarEnabler(UIToolBarEnablerBase enabler) {
+		if (setToolBarEnablers.contains(enabler)) {
+			return;
+		}
+		setToolBarEnablers.add((UIPluginViewToolBarListener) enabler);
+		setToolbarVisibility(setToolBarEnablers.size() > 0);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#removeToolbarEnabler(org.gudy.azureus2.plugins.ui.toolbar.UIToolBarEnablerBase)
+	 */
+	public void removeToolbarEnabler(UIToolBarEnablerBase enabler) {
+		setToolBarEnablers.remove(enabler);
+		setToolbarVisibility(setToolBarEnablers.size() > 0);
+	}
+
+	protected void setToolbarVisibility(boolean visible) {
+	}
+
+	public void setUserData(Object key, Object data) {
+		synchronized (this) {
+	
+			if (user_data == null) {
+	
+				user_data = new LightHashMap<Object, Object>();
 			}
-			
-			if ( data == null ){
-				
-				user_data.remove( key );
-				
-				if ( user_data.isEmpty()){
-					
+	
+			if (data == null) {
+	
+				user_data.remove(key);
+	
+				if (user_data.isEmpty()) {
+	
 					user_data = null;
 				}
-			}else{
-					
-				user_data.put( key, data );
+			} else {
+	
+				user_data.put(key, data);
 			}
 		}
 	}
+
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore#getUserData(java.lang.Object)
+	 */
+	public Object getUserData(Object key) {
+		synchronized (this) {
 	
-	public Object
-	getUserData(
-		Object		key )
-	{
-		Map<Object,Object> temp = user_data;
-		
-		if ( temp == null ){
-			
-			return( null );
-			
-		}else{
-			
-			return( temp.get( key ));
+			if (user_data == null) {
+	
+				return (null);
+			}
+	
+			return (user_data.get(key));
 		}
 	}
+
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.ui.swt.plugins.UISWTView#setDestroyOnDeactivate(boolean)
+	 */
+	public void setDestroyOnDeactivate(boolean b) {
+		destroyOnDeactivate = b;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.ui.swt.plugins.UISWTView#isDestroyOnDeactivate()
+	 */
+	public boolean isDestroyOnDeactivate() {
+		return destroyOnDeactivate;
+	}
+
+	public boolean isDelayInitializeToFirstActivate() {
+		return delayInitializeToFirstActivate;
+	}
+
+	public void setDelayInitializeToFirstActivate(
+			boolean delayInitializeToFirstActivate) {
+		this.delayInitializeToFirstActivate = delayInitializeToFirstActivate;
+	}
+
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIToolBarItemImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIToolBarItemImpl.java
new file mode 100644
index 0000000..d0a8c91
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIToolBarItemImpl.java
@@ -0,0 +1,181 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.swt.pluginsimpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener;
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager;
+
+import com.aelitis.azureus.ui.common.ToolBarItem;
+
+/**
+ * 
+ * A Toolbar item implementation, independent of UI (SWT)
+ * 
+ * @author TuxPaper
+ * @created Feb 19, 2015
+ *
+ */
+public class UIToolBarItemImpl
+	implements ToolBarItem
+{
+	private String id;
+
+	private String imageID = "image.toolbar.run";
+
+	private String textID;
+
+	private boolean alwaysAvailable = false;
+
+	private long state;
+
+	private UIToolBarActivationListener defaultActivation;
+
+	private String tooltipID;
+
+	private String groupID = UIToolBarManager.GROUP_MAIN;
+
+	private List<ToolBarItemListener> toolBarItemListeners = new ArrayList<ToolBarItemListener>();
+
+	private String toolTip;
+
+	public UIToolBarItemImpl(String id) {
+		this.id = id;
+	}
+
+	// @see com.aelitis.azureus.ui.common.ToolBarItem#addToolBarItemListener(com.aelitis.azureus.ui.common.ToolBarItem.ToolBarItemListener)
+	public void addToolBarItemListener(ToolBarItemListener l) {
+		if (!toolBarItemListeners.contains(l)) {
+			toolBarItemListeners.add(l);
+		}
+	}
+	
+	// @see com.aelitis.azureus.ui.common.ToolBarItem#removeToolBarItemListener(com.aelitis.azureus.ui.common.ToolBarItem.ToolBarItemListener)
+	public void removeToolBarItemListener(ToolBarItemListener l) {
+		toolBarItemListeners.remove(l);
+	}
+
+	private void triggerFieldChange() {
+		ToolBarItemListener[] array = toolBarItemListeners.toArray(new ToolBarItemListener[0]);
+		for (ToolBarItemListener l : array) {
+			l.uiFieldChanged(this);
+		}
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#getID()
+	public String getID() {
+		return id;
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#getTextID()
+	public String getTextID() {
+		return textID;
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#setTextID(java.lang.String)
+	public void setTextID(String id) {
+		textID = id;
+		triggerFieldChange();
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#getImageID()
+	public String getImageID() {
+		return imageID;
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#setImageID(java.lang.String)
+	public void setImageID(String id) {
+		imageID = id;
+		triggerFieldChange();
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#isAlwaysAvailable()
+	public boolean isAlwaysAvailable() {
+		return alwaysAvailable;
+	}
+
+	public void setAlwaysAvailable(boolean alwaysAvailable) {
+		this.alwaysAvailable = alwaysAvailable;
+		triggerFieldChange();
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#getState()
+	public long getState() {
+		return state;
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#setState(long)
+	public void setState(long state) {
+		this.state = state;
+		triggerFieldChange();
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#triggerToolBarItem(long, java.lang.Object)
+	public boolean triggerToolBarItem(long activationType, Object datasource) {
+		ToolBarItemListener[] array = toolBarItemListeners.toArray(new ToolBarItemListener[0]);
+		for (ToolBarItemListener l : array) {
+			if (l.triggerToolBarItem(this, activationType, datasource)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#setDefaultActivationListener(org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener)
+	public void setDefaultActivationListener(
+			UIToolBarActivationListener defaultActivation) {
+		this.defaultActivation = defaultActivation;
+	}
+
+	// @see com.aelitis.azureus.ui.common.ToolBarItem#getDefaultActivationListener()
+	public UIToolBarActivationListener getDefaultActivationListener() {
+		return defaultActivation;
+	}
+
+	// @see com.aelitis.azureus.ui.common.ToolBarItem#getTooltipID()
+	public String getTooltipID() {
+		return tooltipID;
+	}
+
+	public void setTooltipID(String tooltipID) {
+		this.tooltipID = tooltipID;
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#getGroupID()
+	public String getGroupID() {
+		return groupID;
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#setGroupID(java.lang.String)
+	public void setGroupID(String groupID) {
+		this.groupID = groupID;
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#setToolTip(java.lang.String)
+	public void setToolTip(String text) {
+		toolTip = text;
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem#getToolTip()
+	public String getToolTip() {
+		return toolTip;
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIToolBarManagerCore.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIToolBarManagerCore.java
index 153ad3a..4329dc0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIToolBarManagerCore.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIToolBarManagerCore.java
@@ -1,9 +1,43 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.pluginsimpl;
 
 
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UIToolBarManagerImpl.ToolBarManagerListener;
+
+import com.aelitis.azureus.ui.common.ToolBarItem;
 
 public interface UIToolBarManagerCore
 	extends UIToolBarManager
 {
+
+	ToolBarItem[] getAllSWTToolBarItems();
+
+	void addListener(ToolBarManagerListener l);
+
+	void removeListener(ToolBarManagerListener l);
+
+	void addToolBarItem(UIToolBarItem item, boolean trigger);
+
+	String[] getToolBarIDsByGroup(String groupID);
+	
+	String[] getGroupIDs();
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIToolBarManagerImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIToolBarManagerImpl.java
new file mode 100644
index 0000000..2d3e9c9
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsimpl/UIToolBarManagerImpl.java
@@ -0,0 +1,189 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.swt.pluginsimpl;
+
+import java.util.*;
+
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager;
+
+import com.aelitis.azureus.ui.common.ToolBarItem;
+import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
+import com.aelitis.azureus.ui.selectedcontent.SelectedContentListener;
+import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
+
+/**
+ * @author TuxPaper
+ * @created Feb 19, 2015
+ *
+ */
+public class UIToolBarManagerImpl
+	implements UIToolBarManagerCore
+{
+	private static UIToolBarManagerImpl instance;
+
+	private Map<String, UIToolBarItem> items = new LinkedHashMap<String, UIToolBarItem>();
+	
+	private Map<String, List<String>> mapGroupToItemIDs = new HashMap<String, List<String>>();
+
+	public List<ToolBarManagerListener> listListeners = new ArrayList<ToolBarManagerListener>();
+
+	public static UIToolBarManager getInstance() {
+		if (instance == null) {
+			instance = new UIToolBarManagerImpl();
+		}
+		return instance;
+	}
+
+	public static interface ToolBarManagerListener
+	{
+		public void toolbarItemRemoved(UIToolBarItem item);
+
+		public void toolbarItemAdded(UIToolBarItem item);
+	}
+
+	
+	public UIToolBarManagerImpl() {
+		SelectedContentManager.addCurrentlySelectedContentListener(new SelectedContentListener() {
+			public void currentlySelectedContentChanged(
+					ISelectedContent[] currentContent, String viewID) {
+				if (viewID == null) {
+  				ToolBarItem[] allSWTToolBarItems = getAllSWTToolBarItems();
+  				for (ToolBarItem item : allSWTToolBarItems) {
+  					item.setState(0);
+  				}
+				}
+			}
+		});
+	}
+	
+	public void addListener(ToolBarManagerListener l) {
+		synchronized (listListeners) {
+			listListeners.add(l);
+		}
+	}
+
+	public void removeListener(ToolBarManagerListener l) {
+		synchronized (listListeners) {
+			listListeners.remove(l);
+		}
+	}
+
+	public UIToolBarItem getToolBarItem(String itemID) {
+		return items.get(itemID);
+	}
+
+	public UIToolBarItem[] getAllToolBarItems() {
+		return items.values().toArray(new UIToolBarItem[0]);
+	}
+
+	public ToolBarItem[] getAllSWTToolBarItems() {
+		return items.values().toArray(new ToolBarItem[0]);
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager#createToolBarItem(java.lang.String)
+	public UIToolBarItem createToolBarItem(String id) {
+		UIToolBarItemImpl base = new UIToolBarItemImpl(id);
+		return base;
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager#addToolBarItem(org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem)
+	public void addToolBarItem(UIToolBarItem item) {
+		addToolBarItem(item, true);
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager#addToolBarItem(org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem)
+	public void addToolBarItem(UIToolBarItem item, boolean trigger) {
+		if (item == null) {
+			return;
+		}
+		if (items.containsKey(item.getID())) {
+			return;
+		}
+		
+		items.put(item.getID(), item);
+
+		String groupID = item.getGroupID();
+		synchronized (mapGroupToItemIDs) {
+			List<String> list = mapGroupToItemIDs.get(groupID);
+			if (list == null) {
+				list = new ArrayList<String>();
+				mapGroupToItemIDs.put(groupID, list);
+			}
+			list.add(item.getID());
+		}
+
+		if (trigger) {
+  		ToolBarManagerListener[] listeners = listListeners.toArray(new ToolBarManagerListener[0]);
+  		for (ToolBarManagerListener l : listeners) {
+  			l.toolbarItemAdded(item);
+  		}
+		}
+	}
+
+	public String[] getToolBarIDsByGroup(String groupID) {
+		synchronized (mapGroupToItemIDs) {
+			List<String> list = mapGroupToItemIDs.get(groupID);
+			if (list == null) {
+				return new String[0];
+			}
+			return list.toArray(new String[0]);
+		}
+	}
+
+	public UIToolBarItem[] getToolBarItemsByGroup(String groupID) {
+		synchronized (mapGroupToItemIDs) {
+			List<String> list = mapGroupToItemIDs.get(groupID);
+			if (list == null) {
+				return new UIToolBarItem[0];
+			}
+			UIToolBarItem[] items = new UIToolBarItem[list.size()];
+			int i = 0;
+			for (String id : list) {
+				items[i] = getToolBarItem(id);
+				i++;
+			}
+			return items;
+		}
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager#removeToolBarItem(java.lang.String)
+	public void removeToolBarItem(String id) {
+		UIToolBarItem toolBarItem = items.remove(id);
+		if (toolBarItem != null) {
+
+			synchronized (mapGroupToItemIDs) {
+				List<String> list = mapGroupToItemIDs.get(toolBarItem.getGroupID());
+				if (list != null) {
+					list.remove(toolBarItem.getID());
+				}
+			}
+
+			ToolBarManagerListener[] listeners = listListeners.toArray(new ToolBarManagerListener[0]);
+			for (ToolBarManagerListener l : listeners) {
+				l.toolbarItemRemoved(toolBarItem);
+			}
+		}
+	}
+	
+	// @see org.gudy.azureus2.ui.swt.pluginsimpl.UIToolBarManagerCore#getGroupIDs()
+	public String[] getGroupIDs() {
+		return mapGroupToItemIDs.keySet().toArray(new String[0]);
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWFilePanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWFilePanel.java
index 4df8a73..587bb49 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWFilePanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWFilePanel.java
@@ -2,11 +2,12 @@
  * Created on 30 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.pluginsinstaller;
 
@@ -92,7 +90,7 @@ public class IPWFilePanel extends AbstractWizardPanel<InstallPluginWizard> {
 	btnBrowse.addListener(SWT.Selection,new Listener() {
 	  public void handleEvent(Event event) {
 	    FileDialog fd = new FileDialog(wizard.getWizardWindow());
-	    fd.setFilterExtensions(new String[] {"*.zip;*.jar"});
+	    fd.setFilterExtensions(new String[] {"*.zip;*.jar;*.vuze"});
 	    fd.setFilterNames(new String[] {"Azureus Plugins"});
 	    String fileName = fd.open();
 	    if(fileName != null) txtFile.setText(fileName);	    
@@ -106,13 +104,11 @@ public class IPWFilePanel extends AbstractWizardPanel<InstallPluginWizard> {
 		String error_message = null;
 		try {
 			File f = new File(fileName);
-			if (f.isFile()
-					&& (f.getName().endsWith(".jar") || f.getName().endsWith(".zip"))) {
+			if (f.isFile() && (f.getName().endsWith(".jar") || f.getName().endsWith(".zip") || f.getName().endsWith(".vuze"))) {
 				wizard.setErrorMessage("");
 				wizard.setNextEnabled(true);
 				List<InstallablePlugin> list = new ArrayList<InstallablePlugin>();
-				InstallablePlugin plugin = core.getPluginManager().getPluginInstaller().installFromFile(
-						f);
+				InstallablePlugin plugin = core.getPluginManager().getPluginInstaller().installFromFile(f);
 				list.add(plugin);
 				wizard.plugins = list;
 				valid = true;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWFinishPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWFinishPanel.java
index 673f41f..144f59e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWFinishPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWFinishPanel.java
@@ -2,11 +2,12 @@
  * Created on 29 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.pluginsinstaller;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWInstallModePanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWInstallModePanel.java
index 37af4ab..e269aa4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWInstallModePanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWInstallModePanel.java
@@ -2,11 +2,12 @@
  * Created on 29 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.pluginsinstaller;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWListPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWListPanel.java
index 7266abe..22f713c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWListPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWListPanel.java
@@ -2,11 +2,12 @@
  * Created on 29 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.pluginsinstaller;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWModePanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWModePanel.java
index 2e0bf63..7f5da66 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWModePanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/IPWModePanel.java
@@ -2,11 +2,12 @@
  * Created on 29 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.pluginsinstaller;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/InstallPluginWizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/InstallPluginWizard.java
index 3f7d301..b79722d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/InstallPluginWizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsinstaller/InstallPluginWizard.java
@@ -2,11 +2,12 @@
  * Created on 29 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.pluginsinstaller;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UIPWFinishPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UIPWFinishPanel.java
index 8f605bf..b1325c5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UIPWFinishPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UIPWFinishPanel.java
@@ -2,11 +2,12 @@
  * Created on 29 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.pluginsuninstaller;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UIPWListPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UIPWListPanel.java
index 6d92044..26c9ec6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UIPWListPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UIPWListPanel.java
@@ -2,11 +2,12 @@
  * Created on 29 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.pluginsuninstaller;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UnInstallPluginWizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UnInstallPluginWizard.java
index 3767601..e04c7e0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UnInstallPluginWizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/pluginsuninstaller/UnInstallPluginWizard.java
@@ -2,11 +2,12 @@
  * Created on 29 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.pluginsuninstaller;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IMessage.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IMessage.java
index b33844c..df43651 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IMessage.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IMessage.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 public interface IMessage
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReport.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReport.java
index f9a3b76..d60cc37 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReport.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReport.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 import org.eclipse.swt.graphics.Image;
@@ -11,6 +29,9 @@ import org.eclipse.swt.graphics.Image;
 public interface IProgressReport
 {
 
+	public IProgressReporter
+	getReporter();
+	
 	/**
 	 * Returns the reporter type of the reporter that created this report
 	 * @return
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReportConstants.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReportConstants.java
index 18b1d66..23876df 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReportConstants.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReportConstants.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 /**
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReporter.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReporter.java
index a9de392..cf521e9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReporter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReporter.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 import org.eclipse.swt.graphics.Image;
@@ -127,6 +145,10 @@ public interface IProgressReporter
 	 */
 	public void setCancelAllowed(boolean cancelAllowed);
 
+	public void setCancelCloses(boolean cancelCloses);
+
+	public boolean getCancelCloses();
+	
 	/**
 	 * 
 	 * @param listener
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReporterListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReporterListener.java
index 5c61329..4986777 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReporterListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReporterListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReportingListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReportingListener.java
index 2a2fbe5..9a0d92e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReportingListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/IProgressReportingListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 /**
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReportMessage.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReportMessage.java
index e76d84f..365a7ff 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReportMessage.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReportMessage.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 /**
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporter.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporter.java
index fbe8988..b41b109 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporter.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 import java.util.ArrayList;
@@ -136,6 +154,8 @@ public class ProgressReporter
 	 */
 	private boolean isActive = true;
 
+	private boolean cancelCloses = false;
+	
 	/**
 	 * Construct a <code>ProgressReporter</code>; the returned instance is initialized with the proper ID
 	 */
@@ -584,6 +604,12 @@ public class ProgressReporter
 		return (true == isDisposed || true == isDone);
 	}
 
+	public boolean getCancelCloses() {
+		return( cancelCloses );
+	}
+	public void setCancelCloses(boolean b) {
+		cancelCloses = b;
+	}
 	/**
 	 * Create and add an <code>IMessage</code> to the message history
 	 * @param value
@@ -769,6 +795,9 @@ public class ProgressReporter
 		private ProgressReport() {
 		}
 
+		public IProgressReporter getReporter() {
+			return( ProgressReporter.this );
+		}
 		/* (non-Javadoc)
 		 * @see org.gudy.azureus2.ui.swt.progress.IProgressReport#getReporterType()
 		 */
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterPanel.java
index d7ee951..3a4538d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterPanel.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 import org.eclipse.swt.SWT;
@@ -445,13 +463,17 @@ public class ProgressReporterPanel
 			case REPORT_TYPE_CANCEL:
 				getDisplay().asyncExec(new Runnable() {
 					public void run() {
-						synchProgressBar(pReport);
-						updateStatusLabel(
-								MessageText.getString("Progress.reporting.status.canceled"),
-								false);
-						appendToDetail(pReport.getMessage(), false);
-						synchActionLabels(pReport);
-						resizeContent();
+						if ( pReport.getReporter().getCancelCloses()){
+							dispose();
+						}else{
+							synchProgressBar(pReport);
+							updateStatusLabel(
+									MessageText.getString("Progress.reporting.status.canceled"),
+									false);
+							appendToDetail(pReport.getMessage(), false);
+							synchActionLabels(pReport);
+							resizeContent();
+						}
 					}
 				});
 				break;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterStack.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterStack.java
index 98558a7..9495020 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterStack.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterStack.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 import java.util.*;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterWindow.java
index 230dc28..7576002 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReporterWindow.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 import java.util.ArrayList;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReportingManager.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReportingManager.java
index 6929bd1..7d14010 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReportingManager.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressReportingManager.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.progress;
 
 import java.util.*;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressWindow.java
index 1224c38..2534785 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/progress/ProgressWindow.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27 Jul 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/sharing/ShareUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/sharing/ShareUtils.java
index 9ffcd7a..8b46445 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/sharing/ShareUtils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/sharing/ShareUtils.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/sharing/progress/ProgressWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/sharing/progress/ProgressWindow.java
index 146fa03..e942563 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/sharing/progress/ProgressWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/sharing/progress/ProgressWindow.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/AbstractWizardPage.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/AbstractWizardPage.java
index 41ed579..479551b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/AbstractWizardPage.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/AbstractWizardPage.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.shells;
 
 import java.util.LinkedHashMap;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/AdvRenameWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/AdvRenameWindow.java
index a97bb0f..5d74120 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/AdvRenameWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/AdvRenameWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on Sep 3, 2009 3:12:13 PM
- * Copyright (C) 2009 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
@@ -23,11 +20,10 @@ 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.download.DownloadManagerState;
 import org.gudy.azureus2.core3.logging.LogAlert;
 import org.gudy.azureus2.core3.logging.Logger;
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
@@ -232,12 +228,42 @@ public class AdvRenameWindow
 		if (dm == null) {
 			return;
 		}
+		
+		boolean saveLocationIsFolder = dm.getSaveLocation().isDirectory();
+		
+		String newDisplayName 	= newName;
+		String newSavePath		= FileUtil.convertOSSpecificChars( newName, saveLocationIsFolder );
+		String newTorrentName	= FileUtil.convertOSSpecificChars( newName, false );
+
 		if ((renameDecisions & RENAME_DISPLAY) > 0) {
-			dm.getDownloadState().setDisplayName(newName);
+			dm.getDownloadState().setDisplayName(newDisplayName);
 		}
 		if ((renameDecisions & RENAME_SAVEPATH) > 0) {
 			try {
-				dm.renameDownload(newName);
+				
+				try{
+					if ( dm.getTorrent().isSimpleTorrent()){
+					
+				    	String dnd_sf = dm.getDownloadState().getAttribute( DownloadManagerState.AT_INCOMP_FILE_SUFFIX );
+				        
+				    	if ( dnd_sf != null ){
+				    		
+				    		dnd_sf = dnd_sf.trim();
+
+				    		String existing_name = dm.getSaveLocation().getName();
+				    		
+				    		if ( existing_name.endsWith( dnd_sf )){
+				    			
+				    			if ( !newSavePath.endsWith( dnd_sf )){
+				    				
+				    				newSavePath += dnd_sf;
+				    			}
+				    		}
+				    	}
+					}
+				}catch( Throwable e ){
+				}
+				dm.renameDownload(newSavePath);
 			} catch (Exception e) {
 				Logger.log(new LogAlert(dm, LogAlert.REPEATABLE,
 						"Download data rename operation failed", e));
@@ -245,7 +271,7 @@ public class AdvRenameWindow
 		}
 		if ((renameDecisions & RENAME_TORRENT) > 0) {
 			try {
-				dm.renameTorrentSafe(newName);
+				dm.renameTorrentSafe(newTorrentName);
   		} catch (Exception e) {
   			Logger.log(new LogAlert(dm, LogAlert.REPEATABLE,
   					"Torrent rename operation failed", e));
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/BrowserShell.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/BrowserShell.java
index f58252a..532c433 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/BrowserShell.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/BrowserShell.java
@@ -1,55 +1,54 @@
-/*
- * Created on Oct 13, 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.ui.swt.shells;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-
-public class 
-BrowserShell 
-{
-	public
-	BrowserShell(
-		String		title_resource,
-		String		url,
-		int			width,
-		int			height )
-	{
-		MessageBoxShell boxShell = 
-			new MessageBoxShell(
-				MessageText.getString( title_resource ),
-				"",
-				new String[] {
-					//MessageText.getString("Button.ok")
-				},
-				0 );
-
-		boxShell.setUrl( url );
-
-		boxShell.setBrowserFollowLinks( true );
-		
-		boxShell.setSquish( true );
-		
-		boxShell.setSize( width, height );
-		
-		boxShell.open(null);
-	}
-}
+/*
+ * Created on Oct 13, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.shells;
+
+import org.gudy.azureus2.core3.internat.MessageText;
+
+public class 
+BrowserShell 
+{
+	public
+	BrowserShell(
+		String		title_resource,
+		String		url,
+		int			width,
+		int			height )
+	{
+		MessageBoxShell boxShell = 
+			new MessageBoxShell(
+				MessageText.getString( title_resource ),
+				"",
+				new String[] {
+					//MessageText.getString("Button.ok")
+				},
+				0 );
+
+		boxShell.setUrl( url );
+
+		boxShell.setBrowserFollowLinks( true );
+		
+		boxShell.setSquish( true );
+		
+		boxShell.setSize( width, height );
+		
+		boxShell.open(null);
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java
index 58731ca..fd2c020 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/CoreWaiterSWT.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.shells;
 
 import org.eclipse.swt.widgets.Shell;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/DockPosition.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/DockPosition.java
index c8eadf5..f3acb2c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/DockPosition.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/DockPosition.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.shells;
 
 /**
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/GCStringPrinter.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/GCStringPrinter.java
index b7eaa8f..01af1f4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/GCStringPrinter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/GCStringPrinter.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/IWizardPage.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/IWizardPage.java
index 35563ba..2059762 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/IWizardPage.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/IWizardPage.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.shells;
 
 import org.eclipse.swt.widgets.Composite;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/MessageBoxShell.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/MessageBoxShell.java
index 15602e2..a85b25f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/MessageBoxShell.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/MessageBoxShell.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.shells;
 
 import java.util.*;
@@ -9,9 +27,9 @@ import org.eclipse.swt.events.*;
 import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.layout.*;
 import org.eclipse.swt.widgets.*;
-
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
@@ -399,6 +417,12 @@ public class MessageBoxShell
 			Label lblImage = new Label(textComposite, SWT.NONE);
 			lblImage.setImage(imgLeft);
 			lblImage.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
+		} else if (!squish) {
+			textComposite = new Composite(shell, SWT.NONE);
+			GridLayout gl = new GridLayout(2, false);
+			gl.marginWidth = 5;
+			textComposite.setLayout(gl);
+			textComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
 		}
 
 		Control linkControl;
@@ -415,7 +439,7 @@ public class MessageBoxShell
 		if ((html != null && html.length() > 0)
 				|| (url != null && url.length() > 0)) {
 			try {
-				final Browser browser = Utils.createSafeBrowser(shell, SWT.NONE);
+				final BrowserWrapper browser = Utils.createSafeBrowser(shell, SWT.NONE);
 				if (url != null && url.length() > 0) {
 					browser.setUrl(url);
 				} else {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/MessageSlideShell.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/MessageSlideShell.java
index 2a4d023..ba1c392 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/MessageSlideShell.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/MessageSlideShell.java
@@ -1,6 +1,6 @@
 /*
  * Created on Mar 7, 2006 10:42:32 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/MultipageWizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/MultipageWizard.java
index f48cae2..41afd75 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/MultipageWizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/MultipageWizard.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.shells;
 
 import java.util.ArrayList;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/Offset.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/Offset.java
index d486e20..15b630e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/Offset.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/Offset.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.shells;
 
 public class Offset
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/PopupShell.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/PopupShell.java
index 75db3e0..5b17f5d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/PopupShell.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/PopupShell.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellDocker.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellDocker.java
index 312bdf3..c170b6f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellDocker.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellDocker.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.shells;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellFader.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellFader.java
index 013f4f0..a9e7d3b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellFader.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellFader.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.shells;
 
 public class ShellFader
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellSlider.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellSlider.java
index 9a828b3..3a48330 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellSlider.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/ShellSlider.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.shells;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/SimpleBrowserWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/SimpleBrowserWindow.java
index c4e8f63..453a15b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/SimpleBrowserWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/SimpleBrowserWindow.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.shells;
@@ -26,7 +23,7 @@ import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Shell;
-
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
 
@@ -37,8 +34,8 @@ import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
  */
 public class SimpleBrowserWindow
 {
-	private Shell	 	shell;
-	private Browser 	browser;
+	private Shell	 		shell;
+	private BrowserWrapper 	browser;
 	
 	public SimpleBrowserWindow(Shell parent, String url, double wPct, double hPct,
 			boolean allowResize, boolean isModal) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/shells/SpeedScaleShell.java b/azureus2/src/org/gudy/azureus2/ui/swt/shells/SpeedScaleShell.java
index b1f2564..af78bde 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/shells/SpeedScaleShell.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/shells/SpeedScaleShell.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.shells;
@@ -51,18 +48,20 @@ public class SpeedScaleShell
 
 	private int HEIGHT = TEXT_HEIGHT + SCALER_HEIGHT;
 
-	private static final int WIDTH = 120;
+	private static final int MIN_WIDTH = 130;
 
 	private static final int PADDING_X0 = 10;
 
 	private static final int PADDING_X1 = 10;
 
-	private static final int WIDTH_NO_PADDING = WIDTH - PADDING_X0 - PADDING_X1;
-
 	private static final int TYPED_TEXT_ALPHA = 80;
 
 	private static final long CLOSE_DELAY = 600;
 
+	private int WIDTH;
+
+	private int WIDTH_NO_PADDING;
+
 	private int value;
 
 	private boolean cancelled;
@@ -78,6 +77,8 @@ public class SpeedScaleShell
 	private int bigPageIncrement;
 
 	private Shell shell;
+	
+	private Shell parentShell;
 
 	private LinkedHashMap mapOptions = new LinkedHashMap();
 
@@ -107,6 +108,7 @@ public class SpeedScaleShell
 
 	/**
 	 * Borks with 0 or -1 maxValue
+	 * @param cClickedFrom 
 	 * 
 	 * @param startValue
 	 * @param assumeInitiallyDown 
@@ -114,7 +116,8 @@ public class SpeedScaleShell
 	 *
 	 * @since 3.0.1.7
 	 */
-	public boolean open(final int startValue, boolean _assumeInitiallyDown) {
+	public boolean open(final Control cClickedFrom, final int startValue,
+			boolean _assumeInitiallyDown) {
 		value = startValue;
 		this.assumeInitiallyDown = _assumeInitiallyDown;
 		if (assumeInitiallyDown) {
@@ -122,12 +125,35 @@ public class SpeedScaleShell
 		}
 		cancelled = true;
 
-		shell = new Shell(Utils.findAnyShell(), SWT.DOUBLE_BUFFERED | SWT.ON_TOP);
+		shell = new Shell(parentShell == null ? Utils.findAnyShell() : parentShell,
+				SWT.DOUBLE_BUFFERED | SWT.ON_TOP);
 		shell.setLayout(new FillLayout());
 		final Display display = shell.getDisplay();
 
 		composite = new Composite(shell, SWT.DOUBLE_BUFFERED);
 
+		GC gc = new GC(composite);
+		gc.setAntialias(SWT.ON);
+		WIDTH = MIN_WIDTH;
+		Rectangle r = new Rectangle(0, 0, 9999, 20);
+		for (Iterator iter = mapOptions.keySet().iterator(); iter.hasNext();) {
+			Integer value = (Integer) iter.next();
+			String text = (String) mapOptions.get(value);
+			
+			String s = getStringValue(value, text);
+			GCStringPrinter stringPrinter = new GCStringPrinter(gc, s, r, 0, 0);
+			stringPrinter.calculateMetrics();
+			Point size = stringPrinter.getCalculatedSize();
+			size.x *= 1.10;
+			
+			if (WIDTH < size.x) {
+				WIDTH = size.x;
+			}
+		}
+		gc.dispose();
+		WIDTH_NO_PADDING = WIDTH - PADDING_X0 - PADDING_X1;
+		
+		
 		final Point firstMousePos = display.getCursorLocation();
 
 		composite.addTraverseListener(new TraverseListener() {
@@ -169,22 +195,26 @@ public class SpeedScaleShell
 			}
 		});
 
-		composite.addMouseMoveListener(new MouseMoveListener() {
+		final MouseMoveListener mouseMoveListener = new MouseMoveListener() {
 			public void mouseMove(MouseEvent e) {
+				Point ptOnDisplay = ((Control) e.widget).toDisplay(e.x, e.y);
+				Point ptOnComposite = composite.toControl(ptOnDisplay);
 				lastMoveHadMouseDown = false;
 				boolean hasButtonDown = (e.stateMask & SWT.BUTTON_MASK) > 0
 						|| assumeInitiallyDown;
 				if (hasButtonDown) {
-					if (e.y > HEIGHT - SCALER_HEIGHT) {
+					if (ptOnComposite.y > HEIGHT - SCALER_HEIGHT) {
 						lastMoveHadMouseDown = true;
-						setValue(getValueFromMousePos(e.x));
+						setValue(getValueFromMousePos(ptOnComposite.x));
 					}
 					composite.redraw();
 				} else {
 					composite.redraw();
 				}
 			}
-		});
+		};
+		
+		composite.addMouseMoveListener(mouseMoveListener);
 
 		composite.addMouseTrackListener(new MouseTrackListener() {
 			boolean mouseIsOut = false;
@@ -195,6 +225,9 @@ public class SpeedScaleShell
 			}
 
 			public void mouseExit(MouseEvent e) {
+				if (composite.equals(Utils.getCursorControl())) {
+					return;
+				}
 				mouseIsOut = true;
 				SimpleTimer.addEvent("close scaler",
 						SystemTime.getOffsetTime(CLOSE_DELAY), new TimerEventPerformer() {
@@ -220,11 +253,13 @@ public class SpeedScaleShell
 			}
 		});
 
-		composite.addMouseListener(new MouseListener() {
+		final MouseListener mouseListener = new MouseListener() {
 			boolean bMouseDown = false;
 
 			public void mouseUp(MouseEvent e) {
-				if (assumeInitiallyDown) {
+				Point ptOnDisplay = ((Control) e.widget).toDisplay(e.x, e.y);
+				Point ptOnComposite = composite.toControl(ptOnDisplay);
+				if (assumeInitiallyDown && e.widget == composite) {
 					//System.out.println("assumed down");
 					assumeInitiallyDown = false;
 				}
@@ -234,21 +269,20 @@ public class SpeedScaleShell
 						Point mousePos = display.getCursorLocation();
 						//System.out.println("first=" + firstMousePos + ";mouse= " + mousePos);
 						if (mousePos.equals(firstMousePos)) {
-							lastMoveHadMouseDown = false;
 							return;
 						}
 					}
 					bMouseDown = true;
 				}
 				if (bMouseDown) {
-					if (e.y > HEIGHT - SCALER_HEIGHT) {
-						setValue(getValueFromMousePos(e.x));
+					if (ptOnComposite.y > HEIGHT - SCALER_HEIGHT) {
+						setValue(getValueFromMousePos(ptOnComposite.x));
 						setCancelled(false);
 						if (lastMoveHadMouseDown) {
 							shell.dispose();
 						}
-					} else if (e.y > TEXT_HEIGHT) {
-						int idx = (e.y - TEXT_HEIGHT) / OPTION_HEIGHT;
+					} else if (ptOnComposite.y > TEXT_HEIGHT) {
+						int idx = (ptOnComposite.y - TEXT_HEIGHT) / OPTION_HEIGHT;
 						Iterator iterator = mapOptions.keySet().iterator();
 						int newValue;
 						do {
@@ -264,12 +298,14 @@ public class SpeedScaleShell
 			}
 
 			public void mouseDown(MouseEvent e) {
+				Point ptOnDisplay = ((Control) e.widget).toDisplay(e.x, e.y);
+				Point ptOnComposite = composite.toControl(ptOnDisplay);
 				if (e.count > 1) {
 					lastMoveHadMouseDown = true;
 					return;
 				}
 				Point mousePos = display.getCursorLocation();
-				if (e.y > HEIGHT - SCALER_HEIGHT) {
+				if (ptOnComposite.y > HEIGHT - SCALER_HEIGHT) {
 					bMouseDown = true;
 					setValue(getValueFromMousePos(e.x));
 				}
@@ -278,7 +314,18 @@ public class SpeedScaleShell
 			public void mouseDoubleClick(MouseEvent e) {
 			}
 
-		});
+		};
+		composite.addMouseListener(mouseListener);
+		if (cClickedFrom != null) {
+			cClickedFrom.addMouseListener(mouseListener);
+			cClickedFrom.addMouseMoveListener(mouseMoveListener);
+			composite.addDisposeListener(new DisposeListener() {
+				public void widgetDisposed(DisposeEvent arg0) {
+					cClickedFrom.removeMouseListener(mouseListener);
+					cClickedFrom.removeMouseMoveListener(mouseMoveListener);
+				}
+			});
+		}
 
 		composite.addPaintListener(new PaintListener() {
 			public void paintControl(PaintEvent e) {
@@ -340,6 +387,7 @@ public class SpeedScaleShell
 					Integer value = (Integer) iter.next();
 					String text = (String) mapOptions.get(value);
 
+					e.gc.setAntialias(SWT.ON);
 					Rectangle area = new Rectangle(0, y, WIDTH, OPTION_HEIGHT);
 					Color bg;
 					if (area.contains(mousePos)) {
@@ -392,9 +440,8 @@ public class SpeedScaleShell
 						e.gc.setAlpha(TYPED_TEXT_ALPHA);
 					} catch (Exception ex) {
 					}
-					e.gc.setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND));
-					e.gc.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
 					//e.gc.drawRectangle(rect);
+					e.gc.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
 
 					GCStringPrinter.printString(e.gc, sValue, new Rectangle(rect.x + 2,
 							rect.y + 2, WIDTH - 5, OPTION_HEIGHT), true, false, SWT.LEFT
@@ -421,6 +468,7 @@ public class SpeedScaleShell
 						gc.setForeground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
 					} else {
 						try {
+							gc.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
 							gc.setAlpha(TYPED_TEXT_ALPHA);
 						} catch (Exception e) {
 						}
@@ -627,4 +675,8 @@ public class SpeedScaleShell
 	public void setMenuChosen(boolean menuChosen) {
 		this.menuChosen = menuChosen;
 	}
+
+	public void setParentShell(Shell parentShell) {
+		this.parentShell = parentShell;
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestData.java b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestData.java
index 1ad3ee3..56844b6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestData.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestData.java
@@ -1,7 +1,7 @@
 /**
  * Created on May 10, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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 org.gudy.azureus2.ui.swt.speedtest;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestFinishPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestFinishPanel.java
index 50e31e1..cf88009 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestFinishPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestFinishPanel.java
@@ -21,7 +21,7 @@ import com.aelitis.azureus.core.AzureusCoreFactory;
 /**
  * Created on May 3, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -34,9 +34,6 @@ import com.aelitis.azureus.core.AzureusCoreFactory;
  * 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 SpeedTestFinishPanel extends AbstractWizardPanel
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestPanel.java
index d743588..d39ec99 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestPanel.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestSelector.java b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestSelector.java
index 6438e9c..4a2d5c6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestSelector.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestSelector.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.speedtest;
 
 
@@ -110,7 +128,7 @@ SpeedTestSelector
 
 			wizard.close();
 
-			runMLABTest(true, null);
+			runMLABTest( null);
 			
 			//new ConfigureWizard( false, ConfigureWizard.WIZARD_MODE_SPEED_TEST_AUTO );
 			
@@ -122,15 +140,14 @@ SpeedTestSelector
 		}
 	}
 
-	public static void runMLABTest(final boolean allowShaperProbeLogic,
-			final Runnable runWhenClosed) {
+	public static void runMLABTest(final Runnable runWhenClosed) {
 		CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
 			public void azureusCoreRunning(AzureusCore core) {
 				UIFunctionsManager.getUIFunctions().installPlugin("mlab",
 						"dlg.install.mlab", new UIFunctions.actionListener() {
 							public void actionComplete(Object result) {
 								if (result instanceof Boolean) {
-									_runMLABTest(allowShaperProbeLogic, runWhenClosed);
+									_runMLABTest(runWhenClosed);
 								} else {
 
 									try {
@@ -150,8 +167,7 @@ SpeedTestSelector
 		});
 	}
 	
-	private static void _runMLABTest(final boolean allowShaperProbeLogic,
-			final Runnable runWhenClosed) {
+	private static void _runMLABTest(final Runnable runWhenClosed) {
 		PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID(
 				"mlab");
 		
@@ -163,7 +179,7 @@ SpeedTestSelector
 		}else{
 			try {
 				HashMap<String, Object> map = new HashMap<String, Object>();
-				map.put("allowShaperProbeLogic", Boolean.valueOf(allowShaperProbeLogic));
+				
 				pi.getIPC().invoke("runTest", new Object[] {
 					map,
 					new IPCInterface() {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestSetLimitPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestSetLimitPanel.java
index be309ca..a3ffc07 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestSetLimitPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestSetLimitPanel.java
@@ -22,7 +22,7 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
 /**
  * Created on May 1, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -35,9 +35,6 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerLimitEstimate;
  * 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 SpeedTestSetLimitPanel extends AbstractWizardPanel {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestWizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestWizard.java
index 8d9742c..fc91f14 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestWizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/speedtest/SpeedTestWizard.java
@@ -1,7 +1,7 @@
 /*
  * Created on Apr 30, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/twistie/ITwistieConstants.java b/azureus2/src/org/gudy/azureus2/ui/swt/twistie/ITwistieConstants.java
index f84c3f6..2a0f696 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/twistie/ITwistieConstants.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/twistie/ITwistieConstants.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.twistie;
 
 public interface ITwistieConstants
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/twistie/ITwistieListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/twistie/ITwistieListener.java
index ed411b3..d29976a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/twistie/ITwistieListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/twistie/ITwistieListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.twistie;
 
 /**
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/twistie/TwistieLabel.java b/azureus2/src/org/gudy/azureus2/ui/swt/twistie/TwistieLabel.java
index 2d35337..f724b8c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/twistie/TwistieLabel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/twistie/TwistieLabel.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.twistie;
 
 import java.util.ArrayList;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/twistie/TwistieSection.java b/azureus2/src/org/gudy/azureus2/ui/swt/twistie/TwistieSection.java
index 85cd448..0caf729 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/twistie/TwistieSection.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/twistie/TwistieSection.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.twistie;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/update/FullUpdateWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/update/FullUpdateWindow.java
index 7714431..3583ef5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/update/FullUpdateWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/update/FullUpdateWindow.java
@@ -1,10 +1,12 @@
 /**
  * Created on June 29th, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -27,9 +29,9 @@ import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Shell;
-
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
 
@@ -40,9 +42,9 @@ public class FullUpdateWindow
 {
 	private static Shell current_shell = null;
 
-	private static Browser browser;
+	private static BrowserWrapper browser;
 
-	private static BrowserFunction browserFunction;
+	private static BrowserWrapper.BrowserFunction browserFunction;
 
 	public static void 
 	handleUpdate(
@@ -132,89 +134,117 @@ public class FullUpdateWindow
 				}
 			});
 	
-			browserFunction = new BrowserFunction(browser, "sendVuzeUpdateEvent") {
-				private String last = null;
-
-				public Object function(Object[] arguments) {
-
-					if (shell == null || shell.isDisposed()) {
-						return null;
-					}
-					
-					if (arguments == null) {
-						Debug.out("Invalid sendVuzeUpdateEvent null ");
-						return null;
-					}
-					if (arguments.length < 1) {
-						Debug.out("Invalid sendVuzeUpdateEvent length " + arguments.length + " not 1");
-						return null;
-					}
-					if (!(arguments[0] instanceof String)) {
-						Debug.out("Invalid sendVuzeUpdateEvent "
-								+ (arguments[0] == null ? "NULL"
-										: arguments.getClass().getSimpleName()) + " not String");
-						return null;
-					}
-
-					String text = ((String) arguments[0]).toLowerCase();
-					if (last  != null && last.equals(text)) {
-						return null;
-					}
-					last = text;
-					if ( text.contains("page-loaded")) {
-						
-						Utils.centreWindow(shell);
-						if (parentShell != null) {
-							parentShell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
+			browser.addOpenWindowListener(new OpenWindowListener() {
+				public void open(WindowEvent event) {
+					final BrowserWrapper subBrowser = Utils.createSafeBrowser(shell,
+							Utils.getInitialBrowserStyle(SWT.NONE));
+					subBrowser.addLocationListener(new LocationListener() {
+						public void changed(LocationEvent arg0) {
 						}
-						shell.open();
-						
-					} else if (text.startsWith("set-size")){
-						
-						String[] strings = text.split(" ");
-						
-						if (strings.length > 2){
-							try {
-								
-								int w = Integer.parseInt(strings[1]);
-								int h = Integer.parseInt(strings[2]);
-
-								Rectangle computeTrim = shell.computeTrim(0, 0, w, h);
-								shell.setSize(computeTrim.width, computeTrim.height);
-								
-							} catch (Exception e) {
+						public void changing(LocationEvent event) {
+							if (event.location == null || !event.location.startsWith("http")) {
+								return;
 							}
+							event.doit = false;
+							Utils.launch(event.location);
+							
+							Utils.execSWTThreadLater(1000, new AERunnable() {
+								public void runSupport() {
+									subBrowser.dispose();
+								}
+							});
+						}
+					});
+					subBrowser.setBrowser( event );
+				}
+			});
+
+			browserFunction = browser.addBrowserFunction(
+				"sendVuzeUpdateEvent",
+				new BrowserWrapper.BrowserFunction()
+				{
+					private String last = null;
+	
+					public Object function(Object[] arguments) {
+	
+						if (shell == null || shell.isDisposed()) {
+							return null;
 						}
-					}else if ( text.contains( "decline" ) || text.contains( "close" )){
 						
-						Utils.execSWTThreadLater(0, new AERunnable() {	
-							public void runSupport() {
-								shell.dispose();
+						if (arguments == null) {
+							Debug.out("Invalid sendVuzeUpdateEvent null ");
+							return null;
+						}
+						if (arguments.length < 1) {
+							Debug.out("Invalid sendVuzeUpdateEvent length " + arguments.length + " not 1");
+							return null;
+						}
+						if (!(arguments[0] instanceof String)) {
+							Debug.out("Invalid sendVuzeUpdateEvent "
+									+ (arguments[0] == null ? "NULL"
+											: arguments.getClass().getSimpleName()) + " not String");
+							return null;
+						}
+	
+						String text = ((String) arguments[0]).toLowerCase();
+						if (last  != null && last.equals(text)) {
+							return null;
+						}
+						last = text;
+						if ( text.contains("page-loaded")) {
+							
+							Utils.centreWindow(shell);
+							if (parentShell != null) {
+								parentShell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
 							}
-						});
-						
-					}else if ( text.contains("accept")){
-						
-						Utils.execSWTThreadLater(0, new AERunnable() {	
-							public void runSupport(){
-								
-								listener_informed[0] = true;
-								
-								try{
-									listener.actionComplete( true );
+							shell.open();
+							
+						} else if (text.startsWith("set-size")){
+							
+							String[] strings = text.split(" ");
+							
+							if (strings.length > 2){
+								try {
 									
-								}catch( Throwable e ){
+									int w = Integer.parseInt(strings[1]);
+									int h = Integer.parseInt(strings[2]);
+	
+									Rectangle computeTrim = shell.computeTrim(0, 0, w, h);
+									shell.setSize(computeTrim.width, computeTrim.height);
 									
-									Debug.out( e );
+								} catch (Exception e) {
 								}
-								
-								shell.dispose();
 							}
-						});
+						}else if ( text.contains( "decline" ) || text.contains( "close" )){
+							
+							Utils.execSWTThreadLater(0, new AERunnable() {	
+								public void runSupport() {
+									shell.dispose();
+								}
+							});
+							
+						}else if ( text.contains("accept")){
+							
+							Utils.execSWTThreadLater(0, new AERunnable() {	
+								public void runSupport(){
+									
+									listener_informed[0] = true;
+									
+									try{
+										listener.actionComplete( true );
+										
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}
+									
+									shell.dispose();
+								}
+							});
+						}
+						return null;
 					}
-					return null;
-				}
-			};
+				});
 
 			browser.addStatusTextListener(new StatusTextListener() {
 				public void changed(StatusTextEvent event) {
@@ -254,6 +284,19 @@ public class FullUpdateWindow
 			
 			browser.setUrl(final_url);
 			
+			if ( browser.isFake()){
+				
+				shell.setSize( 400, 500 );
+				
+				Utils.centreWindow(shell);
+				
+				browser.setUrl( "http://www.vuze.com/download" );
+				
+				browser.setText( "Update available, please go to www.vuze.com to update." );
+				
+				shell.open();
+			}
+			
 			ok = true;
 			
 		}finally{
@@ -276,7 +319,7 @@ public class FullUpdateWindow
 	{
 		try {
 			open( 
-				"http://127.0.0.1:8080/client/update.php?newversion=5.0.0.0", 
+					"http://192.168.1.6:8090/client/update.php?newversion=5.6.0.0", 
 				new UIFunctions.actionListener()
 				{
 					public void actionComplete(Object result) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/update/SilentInstallUI.java b/azureus2/src/org/gudy/azureus2/ui/swt/update/SilentInstallUI.java
index d0fcc8e..7814696 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/update/SilentInstallUI.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/update/SilentInstallUI.java
@@ -1,107 +1,106 @@
-/*
- * Created on Mar 6, 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.ui.swt.update;
-
-
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.update.Update;
-import org.gudy.azureus2.plugins.update.UpdateCheckInstance;
-import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
-
-
-public class 
-SilentInstallUI 
-{
-	private UpdateMonitor			monitor;
-	private	UpdateCheckInstance		instance;
-	
-	private  boolean				cancelled;
-	
-	protected
-	SilentInstallUI(
-		UpdateMonitor			_monitor,
-		UpdateCheckInstance		_instance )
-	{
-		monitor		= _monitor;
-		instance	= _instance;
-		
-		try{
-			monitor.addDecisionHandler(_instance );
-					
-			new AEThread2( "SilentInstallerUI", true )
-			{
-				public void
-				run()
-				{
-					try{
-						Update[] updates = instance.getUpdates();
-
-						for ( Update update: updates ){
-														
-							ResourceDownloader[] downloaders = update.getDownloaders();
-							
-							for ( ResourceDownloader downloader: downloaders ){
-								
-								synchronized( SilentInstallUI.this ){
-									
-									if ( cancelled ){
-										
-										return;
-									}									
-								}
-								
-								downloader.download();
-							}
-						}
-						
-						boolean	restart_required = false;
-						
-						for (int i=0;i<updates.length;i++){
-			
-							if ( updates[i].getRestartRequired() == Update.RESTART_REQUIRED_YES ){
-								
-								restart_required = true;
-							}
-						}
-						
-						if ( restart_required ){
-							
-							monitor.handleRestart();
-						}
-					}catch( Throwable e ){
-						
-						Debug.out( "Install failed", e );
-						
-						instance.cancel();
-					}
-				}
-			}.start();
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			instance.cancel();
-		}
-	}
-}
\ No newline at end of file
+/*
+ * Created on Mar 6, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.update;
+
+
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.update.Update;
+import org.gudy.azureus2.plugins.update.UpdateCheckInstance;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
+
+
+public class 
+SilentInstallUI 
+{
+	private UpdateMonitor			monitor;
+	private	UpdateCheckInstance		instance;
+	
+	private  boolean				cancelled;
+	
+	protected
+	SilentInstallUI(
+		UpdateMonitor			_monitor,
+		UpdateCheckInstance		_instance )
+	{
+		monitor		= _monitor;
+		instance	= _instance;
+		
+		try{
+			monitor.addDecisionHandler(_instance );
+					
+			new AEThread2( "SilentInstallerUI", true )
+			{
+				public void
+				run()
+				{
+					try{
+						Update[] updates = instance.getUpdates();
+
+						for ( Update update: updates ){
+														
+							ResourceDownloader[] downloaders = update.getDownloaders();
+							
+							for ( ResourceDownloader downloader: downloaders ){
+								
+								synchronized( SilentInstallUI.this ){
+									
+									if ( cancelled ){
+										
+										return;
+									}									
+								}
+								
+								downloader.download();
+							}
+						}
+						
+						boolean	restart_required = false;
+						
+						for (int i=0;i<updates.length;i++){
+			
+							if ( updates[i].getRestartRequired() == Update.RESTART_REQUIRED_YES ){
+								
+								restart_required = true;
+							}
+						}
+						
+						if ( restart_required ){
+							
+							monitor.handleRestart();
+						}
+					}catch( Throwable e ){
+						
+						Debug.out( "Install failed", e );
+						
+						instance.cancel();
+					}
+				}
+			}.start();
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			instance.cancel();
+		}
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/update/SimpleInstallUI.java b/azureus2/src/org/gudy/azureus2/ui/swt/update/SimpleInstallUI.java
index 873157b..fb19dd0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/update/SimpleInstallUI.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/update/SimpleInstallUI.java
@@ -1,291 +1,290 @@
-/*
- * Created on Mar 6, 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.ui.swt.update;
-
-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.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.ProgressBar;
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.update.Update;
-import org.gudy.azureus2.plugins.update.UpdateCheckInstance;
-import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
-import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter;
-import org.gudy.azureus2.ui.swt.Utils;
-
-
-public class 
-SimpleInstallUI 
-{
-	private UpdateMonitor			monitor;
-	private	UpdateCheckInstance		instance;
-	
-	private  boolean				cancelled;
-	private ResourceDownloader		current_downloader;
-	
-	protected
-	SimpleInstallUI(
-		UpdateMonitor			_monitor,
-		UpdateCheckInstance		_instance )
-	{
-		monitor		= _monitor;
-		instance	= _instance;
-		
-		try{
-			monitor.addDecisionHandler(_instance );
-					
-			Utils.execSWTThread(
-				new Runnable()
-				{
-					public void
-					run()
-					{
-						try{
-							build();
-							
-						}catch( Throwable e ){
-							
-							Debug.out( e );
-							
-							instance.cancel();
-						}
-					}
-				});
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			instance.cancel();
-		}
-	}
-	
-	protected void
-	build()
-	{
-		Composite parent = (Composite)instance.getProperty( UpdateCheckInstance.PT_UI_PARENT_SWT_COMPOSITE );
-		
-		if ( parent != null ){
-			
-			if (parent.isDisposed()) {
-				throw( new RuntimeException( "cancelled" ));
-			}
-			
-			build( parent );
-			
-		}else{
-			
-			throw( new RuntimeException( "borkeroo" ));
-		}
-	}
-	
-	protected void
-	build(
-		Composite		parent )
-	{
-		parent.setLayout(new FormLayout());
-				
-		Button cancel_button = new Button( parent, SWT.NULL );
-
-		cancel_button.setText( "Cancel" );
-		
-		cancel_button.addListener(
-				SWT.Selection, 
-				new Listener() 
-				{
-					public void 
-					handleEvent(
-						Event arg0 ) 
-					{
-						synchronized( SimpleInstallUI.this ){
-						
-							cancelled = true;
-
-							if ( current_downloader != null ){
-								
-								current_downloader.cancel();
-							}
-						}
-						
-						instance.cancel();
-					}
-				});
-			
-		FormData	data = new FormData();
-		data.right 	= new FormAttachment(100,0);
-		data.top	= new FormAttachment(0,0);
-		data.bottom	= new FormAttachment(100,0);
-
-		cancel_button.setLayoutData( data );
-			
-		final Label label = new Label(parent, SWT.NULL );
-		
-		label.setText( "blah blah " );
-		
-		data = new FormData();
-		data.left 	= new FormAttachment(0,0);
-		data.top	= new FormAttachment(cancel_button,0, SWT.CENTER);
-
-		label.setLayoutData( data );
-
-		final ProgressBar progress = new ProgressBar(parent, SWT.NULL );
-		
-		progress.setMinimum( 0 );
-		progress.setMaximum( 100 );
-		progress.setSelection( 0 );
-		
-		
-		data = new FormData();
-		data.left 	= new FormAttachment(label,4);
-		data.top	= new FormAttachment(cancel_button, 0, SWT.CENTER);
-		data.right	= new FormAttachment(cancel_button,-4);
-
-		progress.setLayoutData( data );
-		
-		parent.layout( true, true );
-		
-		new AEThread2( "SimpleInstallerUI", true )
-		{
-			public void
-			run()
-			{
-				try{
-					Update[] updates = instance.getUpdates();
-
-					for ( Update update: updates ){
-						
-						String	name = update.getName();
-						
-						int	pos = name.indexOf('/');
-						
-						if ( pos >= 0 ){
-							
-							name = name.substring( pos+1 );
-						}
-						
-						setLabel( name );
-
-						ResourceDownloader[] downloaders = update.getDownloaders();
-						
-						for ( ResourceDownloader downloader: downloaders ){
-							
-							synchronized( SimpleInstallUI.this ){
-								
-								if ( cancelled ){
-									
-									return;
-								}
-								
-								current_downloader = downloader;
-							}
-							
-							setProgress( 0 );
-							
-							downloader.addListener(
-								new ResourceDownloaderAdapter()
-								{
-									public void
-									reportPercentComplete(
-										ResourceDownloader	downloader,
-										int					percentage )
-									{
-										setProgress( percentage );
-									}
-									
-									public void
-									reportAmountComplete(
-										ResourceDownloader	downloader,
-										long				amount )
-									{
-										
-									}
-								});
-							
-							downloader.download();
-						}
-					}
-					
-					boolean	restart_required = false;
-					
-					for (int i=0;i<updates.length;i++){
-		
-						if ( updates[i].getRestartRequired() == Update.RESTART_REQUIRED_YES ){
-							
-							restart_required = true;
-						}
-					}
-					
-					if ( restart_required ){
-						
-						monitor.handleRestart();
-					}
-				}catch( Throwable e ){
-					
-					Debug.out( "Install failed", e );
-					
-					instance.cancel();
-				}
-			}
-			
-			protected void
-			setLabel(
-				final String		str )
-			{
-				Utils.execSWTThread(
-					new Runnable()
-					{
-						public void
-						run()
-						{
-							if (label != null && !label.isDisposed()) {
-								label.setText( str );
-								label.getParent().layout();
-							}
-						}
-					});
-			}
-			
-			protected void
-			setProgress(
-				final int		percent )
-			{
-				Utils.execSWTThread(
-					new Runnable()
-					{
-						public void
-						run()
-						{
-							if (progress != null && !progress.isDisposed()) {
-								progress.setSelection( percent );
-							}
-						}
-					});
-			}
-		}.start();
-	}
-}
+/*
+ * Created on Mar 6, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.update;
+
+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.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.ProgressBar;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.update.Update;
+import org.gudy.azureus2.plugins.update.UpdateCheckInstance;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderAdapter;
+import org.gudy.azureus2.ui.swt.Utils;
+
+
+public class 
+SimpleInstallUI 
+{
+	private UpdateMonitor			monitor;
+	private	UpdateCheckInstance		instance;
+	
+	private  boolean				cancelled;
+	private ResourceDownloader		current_downloader;
+	
+	protected
+	SimpleInstallUI(
+		UpdateMonitor			_monitor,
+		UpdateCheckInstance		_instance )
+	{
+		monitor		= _monitor;
+		instance	= _instance;
+		
+		try{
+			monitor.addDecisionHandler(_instance );
+					
+			Utils.execSWTThread(
+				new Runnable()
+				{
+					public void
+					run()
+					{
+						try{
+							build();
+							
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+							
+							instance.cancel();
+						}
+					}
+				});
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			instance.cancel();
+		}
+	}
+	
+	protected void
+	build()
+	{
+		Composite parent = (Composite)instance.getProperty( UpdateCheckInstance.PT_UI_PARENT_SWT_COMPOSITE );
+		
+		if ( parent != null ){
+			
+			if (parent.isDisposed()) {
+				throw( new RuntimeException( "cancelled" ));
+			}
+			
+			build( parent );
+			
+		}else{
+			
+			throw( new RuntimeException( "borkeroo" ));
+		}
+	}
+	
+	protected void
+	build(
+		Composite		parent )
+	{
+		parent.setLayout(new FormLayout());
+				
+		Button cancel_button = new Button( parent, SWT.NULL );
+
+		cancel_button.setText( "Cancel" );
+		
+		cancel_button.addListener(
+				SWT.Selection, 
+				new Listener() 
+				{
+					public void 
+					handleEvent(
+						Event arg0 ) 
+					{
+						synchronized( SimpleInstallUI.this ){
+						
+							cancelled = true;
+
+							if ( current_downloader != null ){
+								
+								current_downloader.cancel();
+							}
+						}
+						
+						instance.cancel();
+					}
+				});
+			
+		FormData	data = new FormData();
+		data.right 	= new FormAttachment(100,0);
+		data.top	= new FormAttachment(0,0);
+		data.bottom	= new FormAttachment(100,0);
+
+		cancel_button.setLayoutData( data );
+			
+		final Label label = new Label(parent, SWT.NULL );
+		
+		label.setText( "blah blah " );
+		
+		data = new FormData();
+		data.left 	= new FormAttachment(0,0);
+		data.top	= new FormAttachment(cancel_button,0, SWT.CENTER);
+
+		label.setLayoutData( data );
+
+		final ProgressBar progress = new ProgressBar(parent, SWT.NULL );
+		
+		progress.setMinimum( 0 );
+		progress.setMaximum( 100 );
+		progress.setSelection( 0 );
+		
+		
+		data = new FormData();
+		data.left 	= new FormAttachment(label,4);
+		data.top	= new FormAttachment(cancel_button, 0, SWT.CENTER);
+		data.right	= new FormAttachment(cancel_button,-4);
+
+		progress.setLayoutData( data );
+		
+		parent.layout( true, true );
+		
+		new AEThread2( "SimpleInstallerUI", true )
+		{
+			public void
+			run()
+			{
+				try{
+					Update[] updates = instance.getUpdates();
+
+					for ( Update update: updates ){
+						
+						String	name = update.getName();
+						
+						int	pos = name.indexOf('/');
+						
+						if ( pos >= 0 ){
+							
+							name = name.substring( pos+1 );
+						}
+						
+						setLabel( name );
+
+						ResourceDownloader[] downloaders = update.getDownloaders();
+						
+						for ( ResourceDownloader downloader: downloaders ){
+							
+							synchronized( SimpleInstallUI.this ){
+								
+								if ( cancelled ){
+									
+									return;
+								}
+								
+								current_downloader = downloader;
+							}
+							
+							setProgress( 0 );
+							
+							downloader.addListener(
+								new ResourceDownloaderAdapter()
+								{
+									public void
+									reportPercentComplete(
+										ResourceDownloader	downloader,
+										int					percentage )
+									{
+										setProgress( percentage );
+									}
+									
+									public void
+									reportAmountComplete(
+										ResourceDownloader	downloader,
+										long				amount )
+									{
+										
+									}
+								});
+							
+							downloader.download();
+						}
+					}
+					
+					boolean	restart_required = false;
+					
+					for (int i=0;i<updates.length;i++){
+		
+						if ( updates[i].getRestartRequired() == Update.RESTART_REQUIRED_YES ){
+							
+							restart_required = true;
+						}
+					}
+					
+					if ( restart_required ){
+						
+						monitor.handleRestart();
+					}
+				}catch( Throwable e ){
+					
+					Debug.out( "Install failed", e );
+					
+					instance.cancel();
+				}
+			}
+			
+			protected void
+			setLabel(
+				final String		str )
+			{
+				Utils.execSWTThread(
+					new Runnable()
+					{
+						public void
+						run()
+						{
+							if (label != null && !label.isDisposed()) {
+								label.setText( str );
+								label.getParent().layout();
+							}
+						}
+					});
+			}
+			
+			protected void
+			setProgress(
+				final int		percent )
+			{
+				Utils.execSWTThread(
+					new Runnable()
+					{
+						public void
+						run()
+						{
+							if (progress != null && !progress.isDisposed()) {
+								progress.setSelection( percent );
+							}
+						}
+					});
+			}
+		}.start();
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateAutoDownloader.java b/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateAutoDownloader.java
index 549f65f..9f09369 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateAutoDownloader.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateAutoDownloader.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.update;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateMonitor.java b/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateMonitor.java
index 9407165..cb31f57 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateMonitor.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateMonitor.java
@@ -2,11 +2,12 @@
  * Created on 7 mai 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.update;
 
@@ -26,7 +24,6 @@ import java.io.File;
 
 import org.eclipse.swt.SWT;
 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.logging.LogEvent;
@@ -658,7 +655,16 @@ public class UpdateMonitor
 		
 		if ( uiFunctions != null ){
 			
-			uiFunctions.performAction( 
+			int	visiblity_state = uiFunctions.getVisibilityState();
+			
+			if ( 	visiblity_state == UIFunctions.VS_TRAY_ONLY && 
+					COConfigurationManager.getBooleanParameter( "Low Resource Silent Update Restart Enabled" )){
+				
+				uiFunctions.dispose( true, false );
+				
+			}else{
+				
+				uiFunctions.performAction( 
 					UIFunctions.ACTION_UPDATE_RESTART_REQUEST,
 					Constants.isWindows7OrHigher,		// no timer for in 7 as they always get an elevation prompt so we don't want to shutdown and then leave\
 														// Vuze down pending user authorisation of the update
@@ -674,6 +680,10 @@ public class UpdateMonitor
 							}
 						}
 					});
+			}
+		}else{
+			
+			Debug.out( "Can't handle restart as no ui functions available" );
 		}
 	}
 		
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateProgressWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateProgressWindow.java
index 1903432..faa9f9d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateProgressWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateProgressWindow.java
@@ -1,7 +1,7 @@
 /*
  * Created on 01-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateWindow.java
index 38f6c5d..e81bb31 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/update/UpdateWindow.java
@@ -2,11 +2,12 @@
  * Created on 7 mai 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.update;
 
@@ -33,10 +31,10 @@ import org.eclipse.swt.events.DisposeEvent;
 import org.eclipse.swt.events.DisposeListener;
 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.*;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.LinkArea;
@@ -90,11 +88,12 @@ UpdateWindow
   private long totalDownloadSize;
   private List downloaders;
   private Iterator iterDownloaders;
-	private Browser browser;
+  private BrowserWrapper browser;
   
-  private static final int COL_NAME = 0;
-  private static final int COL_VERSION = 1;
-  private static final int COL_SIZE = 2;
+  private static final int COL_NAME 		= 0;
+  private static final int COL_OLD_VERSION 	= 1;
+  private static final int COL_NEW_VERSION 	= 2;
+  private static final int COL_SIZE 		= 3;
   
   
   public 
@@ -219,10 +218,10 @@ UpdateWindow
     SashForm sash = new SashForm(updateWindow,SWT.VERTICAL);
        
     table = new Table(sash,SWT.CHECK | SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
-    String[] names = {"name" , "version" , "size"};
-    int[] sizes = {350,100,100};
+    String[] names = {"name" , "currentversion", "version" , "size"};
+    int[] sizes = {350,100,100,100};
     for(int i = 0 ; i < names.length ; i++) {
-      TableColumn column = new TableColumn(table, i == 0 ? SWT.LEFT : SWT.RIGHT);
+      TableColumn column = new TableColumn(table, i==0?SWT.LEFT:SWT.RIGHT);
       Messages.setLanguageText(column,"UpdateWindow.columns." + names[i]);
       column.setWidth(sizes[i]);
     }
@@ -341,7 +340,7 @@ UpdateWindow
     
     sash.setWeights(new int[] { 25, 75 });
     
-    updateWindow.setSize(600,450);
+    updateWindow.setSize(700,450);
     //updateWindow.open();
   }
   
@@ -416,7 +415,23 @@ UpdateWindow
         final TableItem item = new TableItem(table,SWT.NULL);
         item.setData(update);
         item.setText(COL_NAME,update.getName()==null?"Unknown":update.getName());  
-        item.setText(COL_VERSION,update.getNewVersion()==null?"Unknown":update.getNewVersion());
+        
+        String old_version = update.getOldVersion();
+        if ( old_version == null ){
+        	old_version=MessageText.getString( "SpeedView.stats.unknown" );
+        }else if ( old_version.equals( "0" ) || old_version.equals( "0.0" )){
+        	old_version = "";
+        }
+        
+        item.setText(COL_OLD_VERSION, old_version );
+
+        String new_version = update.getNewVersion();
+        if ( new_version == null ){
+        	new_version=MessageText.getString( "SpeedView.stats.unknown" );
+        }
+        
+        item.setText(COL_NEW_VERSION, new_version );
+        
         ResourceDownloader[] rds = update.getDownloaders();
         long totalLength = 0;
         for(int i = 0 ; i < rds.length ; i++) {
@@ -426,7 +441,7 @@ UpdateWindow
           }
         }                
         
-        item.setText(COL_SIZE,DisplayFormatters.formatByteCountToBase10KBEtc(totalLength));                
+        item.setText(COL_SIZE,DisplayFormatters.formatByteCountToKiBEtc(totalLength));                
         
         item.setChecked(true);
         
@@ -587,6 +602,9 @@ UpdateWindow
         btnOk.setEnabled(true);
         btnOk.addListener(SWT.Selection,new Listener() {
           public void handleEvent(Event e) {
+        	btnOk.setEnabled( false );
+        	btnCancel.setEnabled( false );
+        	
             finishUpdate(true, false);
           }
         });
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/updater2/PreUpdateChecker.java b/azureus2/src/org/gudy/azureus2/ui/swt/updater2/PreUpdateChecker.java
index 931b757..35dda3d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/updater2/PreUpdateChecker.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/updater2/PreUpdateChecker.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.updater2;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/updater2/SWTUpdateChecker.java b/azureus2/src/org/gudy/azureus2/ui/swt/updater2/SWTUpdateChecker.java
index ff4640d..2ff1848 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/updater2/SWTUpdateChecker.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/updater2/SWTUpdateChecker.java
@@ -2,11 +2,12 @@
  * Created on 20 mai 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.updater2;
 
@@ -229,6 +227,7 @@ public class SWTUpdateChecker implements UpdatableComponent
 	      final Update update = 
 	    	  checker.addUpdate("SWT Library for " + versionGetter.getPlatform() + extra,
 		          new String[] {"SWT is the graphical library used by " + Constants.APP_NAME},
+		          "" + versionGetter.getCurrentVersion(),
 		          "" + versionGetter.getLatestVersion(),
 		          swtDownloader,
 		          Update.RESTART_REQUIRED_YES
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/updater2/SWTVersionGetter.java b/azureus2/src/org/gudy/azureus2/ui/swt/updater2/SWTVersionGetter.java
index de54e2d..534f2ef 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/updater2/SWTVersionGetter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/updater2/SWTVersionGetter.java
@@ -2,11 +2,12 @@
  * Created on 20 mai 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.updater2;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/ArchivedFilesView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/ArchivedFilesView.java
new file mode 100644
index 0000000..72fffb2
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/ArchivedFilesView.java
@@ -0,0 +1,274 @@
+/*
+ * Created on 2 juil. 2003
+ *
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views;
+
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+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.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
+import org.gudy.azureus2.plugins.download.DownloadStub;
+import org.gudy.azureus2.plugins.download.DownloadStub.DownloadStubFile;
+import org.gudy.azureus2.ui.swt.Messages;
+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.TableViewFactory;
+import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab;
+import org.gudy.azureus2.ui.swt.views.tableitems.archivedfiles.*;
+import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
+
+import com.aelitis.azureus.ui.common.table.*;
+import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
+
+
+
+
+public class ArchivedFilesView 
+	extends TableViewTab<DownloadStubFile>
+	implements 	TableLifeCycleListener, TableDataSourceChangedListener, 
+				TableViewSWTMenuFillListener
+{
+	private static final String TABLE_ID = "ArchivedFiles";
+	
+	private final static TableColumnCore[] basicItems = {
+		new NameItem(TABLE_ID),
+		new SizeItem(TABLE_ID),
+	};
+
+	static{
+		TableColumnManager tcManager = TableColumnManager.getInstance();
+
+		tcManager.setDefaultColumnNames( TABLE_ID, basicItems );
+	}
+	 
+	public static final String MSGID_PREFIX = "ArchivedFilesView";
+	
+	private TableViewSWT<DownloadStubFile> tv;
+
+	private DownloadStub	current_download;
+
+	public static boolean show_full_path;
+
+	static{
+		COConfigurationManager.addAndFireParameterListener(
+			"ArchivedFilesView.show.full.path",
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					String parameterName) 
+				{
+					show_full_path = COConfigurationManager.getBooleanParameter( "ArchivedFilesView.show.full.path" );
+				}
+			});
+	}
+	
+	public 
+	ArchivedFilesView() 
+	{
+		super(MSGID_PREFIX);
+	}
+
+	public TableViewSWT<DownloadStubFile>
+	initYourTableView() 
+	{
+		tv = TableViewFactory.createTableViewSWT(
+				DownloadStubFile.class,
+				TABLE_ID, 
+				getPropertiesPrefix(), 
+				basicItems,
+				basicItems[0].getName(), 
+				SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL );
+
+		tv.addLifeCycleListener(this);
+		tv.addMenuFillListener(this);
+		tv.addTableDataSourceChangedListener(this, true);
+		
+		tv.setEnableTabViews(false,true,null);
+		
+		return( tv );
+	}
+	
+	public void 
+	fillMenu(
+		String sColumnName, Menu menu) 
+	{
+		List<Object>	ds = tv.getSelectedDataSources();
+		
+		final List<DownloadStubFile> files = new ArrayList<DownloadStub.DownloadStubFile>();
+		
+		for ( Object o: ds ){
+			
+			files.add((DownloadStubFile)o);
+		}
+		
+		boolean	hasSelection = files.size() > 0;
+		
+			// Explore (or open containing folder)
+		
+		final boolean use_open_containing_folder = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled");
+		
+		final MenuItem itemExplore = new MenuItem(menu, SWT.PUSH);
+		
+		Messages.setLanguageText(itemExplore, "MyTorrentsView.menu."
+				+ (use_open_containing_folder ? "open_parent_folder" : "explore"));
+		
+		itemExplore.addListener(SWT.Selection, new Listener() {
+			public void 
+			handleEvent(
+				Event event) 
+			{
+				for ( DownloadStubFile file: files ){
+				
+					ManagerUtils.open( new File( file.getFile().getAbsolutePath()), use_open_containing_folder);
+				}
+			}
+		});
+		
+		itemExplore.setEnabled(hasSelection);
+		
+		new MenuItem( menu, SWT.SEPARATOR );
+	}
+	
+	public void 
+	addThisColumnSubMenu(
+		String columnName, 
+		Menu menuThisColumn) 
+	{
+	    if ( columnName.equals("name")){
+	    	
+	    	new MenuItem( menuThisColumn, SWT.SEPARATOR );
+	    	
+	    	final MenuItem path_item = new MenuItem( menuThisColumn, SWT.CHECK );
+
+	    	path_item.setSelection( show_full_path );
+
+	    	Messages.setLanguageText(path_item, "FilesView.fullpath");
+
+	    	path_item.addListener(SWT.Selection, new Listener() {
+	    		public void handleEvent(Event e) {
+	    			show_full_path = path_item.getSelection();
+	    			tv.columnInvalidate("name");
+	    			tv.refreshTable(false);
+	    			COConfigurationManager.setParameter( "ArchivedFilesView.show.full.path", show_full_path );
+	    		}
+	    	});	
+	    }
+	}
+	
+	public void 
+	tableDataSourceChanged(
+		Object ds ) 
+	{
+		if ( ds == current_download ){
+			
+			tv.setEnabled( ds != null );
+			
+			return;
+		}
+		
+		boolean	enabled = true;
+		
+		if ( ds instanceof DownloadStub ){
+			
+			current_download = (DownloadStub)ds;
+			
+		}else if ( ds instanceof Object[]) {
+			
+			Object[] objs = (Object[])ds;
+			
+			if ( objs.length != 1 ){
+				
+				enabled = false;
+				
+			}else{
+				
+				DownloadStub stub = (DownloadStub)objs[0];
+				
+				if ( stub == current_download ){
+					
+					return;
+				}
+				
+				current_download = stub;
+			}
+		}else{
+			
+			current_download = null;
+			
+			enabled = false;
+		}
+		
+	  	if ( !tv.isDisposed()){
+	  		
+			tv.removeAllTableRows();
+			
+			tv.setEnabled( enabled );
+			
+			if ( enabled ){
+				
+				if ( current_download != null ){
+		  		
+					addExistingDatasources();
+				}
+			}
+	    }
+	}
+	
+	public void 
+	tableViewInitialized() 
+	{
+		if ( current_download != null ){
+		
+			addExistingDatasources();
+			
+		}else{
+		
+			tv.setEnabled( false );
+		}
+    }
+
+	public void 
+	tableViewDestroyed() 
+	{
+	}
+
+	private void 
+	addExistingDatasources() 
+	{
+		if ( current_download == null || tv.isDisposed()){
+			
+			return;
+		}
+
+		DownloadStubFile[] files = current_download.getStubFiles();
+		
+		tv.addDataSources( files );
+		
+		tv.processDataSourceQueueSync();
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/ConfigShell.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/ConfigShell.java
index 848a540..60b0500 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/ConfigShell.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/ConfigShell.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.views;
 
 import org.eclipse.swt.SWT;
@@ -14,6 +30,7 @@ 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.components.shell.ShellFactory;
@@ -57,9 +74,18 @@ public class ConfigShell
 	 * @param width
 	 * @param height
 	 */
-	public void open(String section) {
+	public void open(final String section) {
+		Utils.execSWTThread(new AERunnable() {
+			
+			public void runSupport() {
+				swt_open(section);
+			}
+		});
+	}
+
+	public void swt_open(String section) {
 		if (null != shell && false == shell.isDisposed()) {
-			configView.selectSection(section);
+			configView.selectSection(section, true);
 			if (true == shell.getMinimized()) {
 				shell.setMinimized(false);
 			}
@@ -72,12 +98,14 @@ public class ConfigShell
 			Utils.setShellIcon(shell);
 			configView = new ConfigView();
 			try {
-				swtView = new UISWTViewImpl(null, "ConfigView", configView, section);
+				swtView = new UISWTViewImpl("ConfigView", null, false);
+				swtView.setDatasource(section);
+				swtView.setEventListener(configView, true);
 			} catch (Exception e1) {
 				Debug.out(e1);
 			}
 			swtView.initialize(shell);
-			configView.selectSection(section);
+			configView.selectSection(section,true);
 
 			/*
 			 * Set default size and centers the shell if it's configuration does not exist yet
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/ConfigView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/ConfigView.java
index e9a0836..639a5cf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/ConfigView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/ConfigView.java
@@ -1,6 +1,6 @@
 /*
  * Created on 2 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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;
 
@@ -31,7 +28,6 @@ import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.layout.*;
 import org.eclipse.swt.widgets.*;
 import org.eclipse.swt.widgets.List;
-
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.logging.LogEvent;
@@ -39,9 +35,12 @@ 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.plugins.ui.UIInputReceiver;
+import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
 import org.gudy.azureus2.plugins.ui.config.ConfigSection;
 import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionRepository;
 import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.plugins.*;
 import org.gudy.azureus2.ui.swt.views.configsections.*;
@@ -116,7 +115,7 @@ public class ConfigView implements UISWTViewEventListener {
 		});
   }
   	
-  private void _initialize(Composite composite) {
+  private void _initialize(final Composite composite) {
   	
     GridData gridData;
     /*
@@ -239,8 +238,10 @@ public class ConfigView implements UISWTViewEventListener {
       configLayout.marginWidth = 0;
       cRightSide.setLayout(configLayout);
   
-      // Header
+      	// Header
+      
       Composite cHeader = new Composite(cRightSide, SWT.BORDER);
+      
       configLayout = new GridLayout();
       configLayout.marginHeight = 3;
       configLayout.marginWidth = 0;
@@ -272,6 +273,57 @@ public class ConfigView implements UISWTViewEventListener {
       gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_END | GridData.GRAB_HORIZONTAL);
       usermodeHint.setLayoutData(gridData);
   
+	  Menu headerMenu = new Menu(cHeader.getShell(), SWT.POP_UP );
+			  
+	  final MenuItem menuShortCut = new MenuItem(headerMenu, SWT.PUSH);      
+	  Messages.setLanguageText( menuShortCut, "label.set.shortcut" );
+
+	  menuShortCut.addSelectionListener(new SelectionAdapter() {
+		  public void widgetSelected(SelectionEvent e) {
+			  
+			  final TreeItem tree_item = (TreeItem)lHeader.getData( "TreeItem" );
+			  
+			  if ( tree_item != null ){
+				  
+				  final String id = (String)tree_item.getData( "ID" );
+				  
+				  if ( id != null ){
+					  
+						SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+								"config.dialog.shortcut.title",
+								"config.dialog.shortcut.text");
+						entryWindow.setPreenteredText(COConfigurationManager.getStringParameter( "config.section.shortcut.key." + id, "" ), false);
+						entryWindow.setTextLimit(1);
+						entryWindow.prompt(new UIInputReceiverListener() {
+							public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
+								if (!entryWindow.hasSubmittedInput()) {
+									return;
+								}
+								String sReturn = entryWindow.getSubmittedInput();
+								if ( sReturn != null ){
+									
+									sReturn = sReturn.trim();
+								
+									if ( sReturn.length() > 1 ){
+										
+										sReturn = sReturn.substring(0,1);
+									}
+
+									COConfigurationManager.setParameter( "config.section.shortcut.key." + id, sReturn );
+					  
+									updateHeader( tree_item );
+								}
+							}
+						});
+				  }
+			  }
+		  }
+	  });
+	  
+	  cHeader.setMenu( headerMenu );
+	  lHeader.setMenu( headerMenu );
+	  usermodeHint.setMenu( headerMenu );
+	  
       // Config Section
       cConfigSection = new Composite(cRightSide, SWT.NULL);
       layoutConfigSection = new StackLayout();
@@ -279,8 +331,7 @@ public class ConfigView implements UISWTViewEventListener {
       gridData = new GridData(GridData.FILL_BOTH);
       gridData.horizontalIndent = 2;
       cConfigSection.setLayoutData(gridData);
-  
-  
+    	          
       form.setWeights(new int[] {20,80});
   
       tree.addSelectionListener(new SelectionAdapter() {
@@ -290,7 +341,7 @@ public class ConfigView implements UISWTViewEventListener {
           //OSX lets you select nothing in the tree for example when a child is selected
           //and you close its parent.
           if(tree.getSelection().length > 0)
-    	      showSection(tree.getSelection()[0]);
+    	      showSection(tree.getSelection()[0], false);
            }
       });
       // Double click = expand/contract branch
@@ -463,9 +514,63 @@ public class ConfigView implements UISWTViewEventListener {
       }
     }
     
- 
-
-
+    final Display d = composite.getDisplay();
+    
+    final Listener shortcut_listener = 
+    	new Listener()
+		{
+			public void 
+			handleEvent(
+				Event e) 
+			{
+				  if ((e.stateMask & ( SWT.MOD1 | SWT.CONTROL )) != 0 || e.keyCode == SWT.COMMAND ){
+	
+				  char key = e.character;
+	
+				  if (key <= 26 && key > 0){
+					  key += 'a' - 1;
+				  }
+	
+				  if ((e.stateMask & SWT.SHIFT )!= 0 ){
+					  key = Character.toUpperCase(key);
+				  }
+				  if ( !Character.isISOControl( key )){
+	
+					  for ( TreeItem ti: sections.keySet()){
+	
+						  String id = (String)ti.getData( "ID" );
+	
+						  if ( id != null ){
+	
+							  String shortcut = COConfigurationManager.getStringParameter( "config.section.shortcut.key." + id, "" );
+	
+							  if ( shortcut.equals( String.valueOf( key ))){
+	
+								  //findFocus( cConfig );
+	
+								  selectSection( id, true );
+	
+								  e.doit = false;
+	
+								  break;
+							  }
+						  }
+					  }
+				  }
+			  }   			
+			};
+		};
+		
+    d.addFilter( SWT.KeyDown, shortcut_listener );
+  	
+    cConfigSection.addDisposeListener(
+    	new DisposeListener() {
+			
+			public void widgetDisposed(DisposeEvent e) {
+				d.removeFilter( SWT.KeyDown, shortcut_listener);
+			}
+		});
+    
     if (composite instanceof Shell) {
     	initApplyCloseButton();
     } else {
@@ -473,7 +578,7 @@ public class ConfigView implements UISWTViewEventListener {
     }
     
     if (startSection != null) {
-    	if (selectSection(startSection)) {
+    	if (selectSection(startSection,false)) {
     		return;
     	}
     }
@@ -481,9 +586,32 @@ public class ConfigView implements UISWTViewEventListener {
     TreeItem[] items = { tree.getItems()[0] };
     tree.setSelection(items);
     // setSelection doesn't trigger a SelectionListener, so..
-    showSection(items[0]);
+    showSection(items[0], false );
   }
 
+ 
+  /*
+  private void
+  findFocus(
+		Control 	c )
+  {
+	
+	 if ( c.isFocusControl()){
+		 System.out.println( "Focus=" + c );
+	 }
+	  
+	  if ( c instanceof Composite ){
+	  
+		  Control[] kids = ((Composite)c).getChildren();
+	  
+		  for( Control k: kids ){
+		  
+			  findFocus( k );
+		  }
+	  }
+  }
+  */
+  
 	private void setupSC(ScrolledComposite sc) {
 		Composite c = (Composite) sc.getContent();
 		if (c != null) {
@@ -493,7 +621,7 @@ public class ConfigView implements UISWTViewEventListener {
 		}
 		sc.getVerticalBar().setPageIncrement(sc.getSize().y);
 	}
-	
+
 
   /**
 	 * @param text
@@ -551,7 +679,7 @@ public class ConfigView implements UISWTViewEventListener {
 									}
 									TreeItem[] selection = tree.getSelection();
 									if (selection != null && selection.length > 0) {
-										showSection(selection[0]);
+										showSection(selection[0],false);
 									}
 								}
 							}
@@ -637,7 +765,11 @@ public class ConfigView implements UISWTViewEventListener {
 		return false;
 	}
 
-	private void showSection(TreeItem section) {
+	private void 
+	showSection(
+		TreeItem 	section,
+		boolean		focus ) 
+	{
     ScrolledComposite item = (ScrolledComposite)section.getData("Panel");
 
     if (item != null) {
@@ -656,6 +788,10 @@ public class ConfigView implements UISWTViewEventListener {
       cConfigSection.layout();
       
       updateHeader(section);
+      
+      if ( focus ){
+    	  layoutConfigSection.topControl.traverse( SWT.TRAVERSE_TAB_NEXT);
+      }
     }
   }
 	
@@ -730,7 +866,7 @@ public class ConfigView implements UISWTViewEventListener {
         }
         
         Composite c = ((UISWTConfigSection)configSection).configSectionCreate(item);
-        
+                
         sectionsCreated.add(configSection);
         
         item.setContent(c);
@@ -742,6 +878,8 @@ public class ConfigView implements UISWTViewEventListener {
 		if (section == null)
 			return;
 		
+		lHeader.setData( "TreeItem", section );
+		
 		int userMode = COConfigurationManager.getIntParameter("User Mode");
 		int maxUsermode = 0;
 		try
@@ -756,19 +894,34 @@ public class ConfigView implements UISWTViewEventListener {
 			//Debug.printStackTrace(e);
 		}
 		
+		String id = (String)section.getData( "ID" );
+		
+		String shortcut = COConfigurationManager.getStringParameter( "config.section.shortcut.key." + id, null );
+		
+		String sc_text;
+		
+		if ( shortcut != null && shortcut.length() > 0 ){
+		
+			sc_text = "      (Ctrl+" + shortcut.charAt(0) + ")";
+		}else{
+			
+			sc_text = "";
+		}
+
 		if (userMode < maxUsermode)
 			Messages.setLanguageText(usermodeHint, "ConfigView.higher.mode.available");
 		else
 			usermodeHint.setText("");
 		
 		String sHeader = section.getText();
+				
 		section = section.getParentItem();
 		while (section != null)
 		{
 			sHeader = section.getText() + " : " + sHeader;
 			section = section.getParentItem();
 		}
-		lHeader.setText(" " + sHeader.replaceAll("&", "&&"));
+		lHeader.setText(" " + sHeader.replaceAll("&", "&&") + sc_text );
 		lHeader.getParent().layout(true, true);
 	}
 
@@ -996,12 +1149,12 @@ public class ConfigView implements UISWTViewEventListener {
     return MessageText.getString(MessageText.resolveLocalizationKey("ConfigView.title.full")); //$NON-NLS-1$
   }
 
-  public boolean selectSection(String id) {
+  public boolean selectSection(String id, boolean focus) {
 		TreeItem ti = findTreeItem(id);
 		if (ti == null)
 			return false;
 		tree.setSelection(new TreeItem[] { ti });
-		showSection(ti);
+		showSection(ti, focus);
 		return true;
 	}
 
@@ -1021,7 +1174,7 @@ public class ConfigView implements UISWTViewEventListener {
 				  
 			  tree.setSelection( new TreeItem[]{ item });
 			  
-			  showSection( item );
+			  showSection( item, true );
 			  
 			  break;
 		  }
@@ -1046,7 +1199,7 @@ public class ConfigView implements UISWTViewEventListener {
 	  	startSection = id;
 	  	Utils.execSWTThread(new AERunnable() {
 				public void runSupport() {
-					selectSection(startSection);
+					selectSection(startSection,false);
 				}
 			});
 		}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/DownloadActivityView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/DownloadActivityView.java
index 3a1081e..3fe3d03 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/DownloadActivityView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/DownloadActivityView.java
@@ -1,12 +1,13 @@
 /*
  * Created on 2 juil. 2003
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
- *
+ * 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
@@ -15,9 +16,6 @@
  * 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;
 
@@ -33,9 +31,11 @@ import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerStats;
 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.plugins.ui.UIPluginViewToolBarListener;
 import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.TorrentUtil;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.Legend;
 import org.gudy.azureus2.ui.swt.components.graphics.MultiPlotGraphic;
@@ -55,7 +55,9 @@ import com.aelitis.azureus.ui.selectedcontent.SelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
 
 
-
+/**
+ * aka "Speed" sub view
+ */
 public class 
 DownloadActivityView 
 	implements UISWTViewCoreEventListener, UIPluginViewToolBarListener
@@ -73,6 +75,8 @@ DownloadActivityView
 	private MultiPlotGraphic 		mpg;
 	
 	private DownloadManager 		manager;
+
+	private Composite parent;
 	
 	public 
 	DownloadActivityView()
@@ -87,10 +91,17 @@ DownloadActivityView
 	  
 	public void 
 	initialize(
-		Composite composite )
+		Composite parent )
 	{
-	    panel = new Composite(composite,SWT.NULL);
+	    this.parent = parent;
+			panel = new Composite(parent,SWT.NULL);
 	    panel.setLayout(new GridLayout(legend_at_bottom?1:2, false));
+	    fillPanel();
+	}
+	
+	public void fillPanel() {
+		Utils.disposeComposite(panel, false);
+
 	    GridData gridData;
 
 	    ValueFormater formatter =
@@ -271,6 +282,9 @@ DownloadActivityView
 	refresh(
 		boolean	force )
 	{
+		if (mpg == null) {
+			return;
+		}
 		mpg.refresh( force );
 	}
 	
@@ -311,32 +325,46 @@ DownloadActivityView
 			return;
 		}
 		  
-	  	DownloadManager old_manager = manager;
-		if (newDataSource == null){
-			manager = null;
-		}else if (newDataSource instanceof Object[]){
-			Object temp = ((Object[])newDataSource)[0];
-			if ( temp instanceof DownloadManager ){
-				manager = (DownloadManager)temp;
-			}else if ( temp instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)temp).getDownloadManager();
-			}else{
-				return;
+		DownloadManager newManager = null;
+		if (newDataSource instanceof Object[]) {
+			Object[] newDataSources = (Object[]) newDataSource;
+			if (newDataSources.length == 1) {
+				Object temp = ((Object[]) newDataSource)[0];
+				if (temp instanceof DownloadManager) {
+					newManager = (DownloadManager) temp;
+				} else if (temp instanceof DiskManagerFileInfo) {
+					newManager = ((DiskManagerFileInfo) temp).getDownloadManager();
+				}
 			}
-		}else{
-			if ( newDataSource instanceof DownloadManager ){
-				manager = (DownloadManager)newDataSource;
-			}else if ( newDataSource instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)newDataSource).getDownloadManager();
-			}else{
-				return;
+		} else {
+			if (newDataSource instanceof DownloadManager) {
+				newManager = (DownloadManager) newDataSource;
+			} else if (newDataSource instanceof DiskManagerFileInfo) {
+				newManager = ((DiskManagerFileInfo) newDataSource).getDownloadManager();
 			}
 		}
-		
-		if ( old_manager == manager ){
-			
+	
+		if (newManager == manager) {
 			return;
 		}
+
+		manager = newManager;
+		
+		Utils.execSWTThread(new AERunnable() {
+			@Override
+			public void runSupport() {
+				if (panel == null || panel.isDisposed()) {
+					return;
+				}
+				Utils.disposeComposite(panel, false);
+			  if (manager != null){
+			  	fillPanel();
+			  	parent.layout(true, true);
+			  } else {
+			  	ViewUtils.setViewRequiresOneDownload(panel);
+			  }
+			}
+		});
 		
 		if ( manager == null ){
 			
@@ -475,9 +503,14 @@ DownloadActivityView
 
 	    				id += ":" + manager.getSize();
 	    			}
-	    		}
 
-	    		SelectedContentManager.changeCurrentlySelectedContent(id, new SelectedContent[]{ new SelectedContent(manager)});
+	    			SelectedContentManager.changeCurrentlySelectedContent(id,
+								new SelectedContent[] {
+									new SelectedContent(manager)
+						});
+					} else {
+						SelectedContentManager.changeCurrentlySelectedContent(id, null);
+					}
 
 	    		refresh( true );
 	    					    
@@ -487,6 +520,8 @@ DownloadActivityView
 		    	
 		    	setFocused( false );
 		    	
+		    	SelectedContentManager.clearCurrentlySelectedContent();
+
 		    	break;
 		    }
 	    }
@@ -494,20 +529,21 @@ DownloadActivityView
 	    return( true );
 	}
 	
-	public boolean 
-	toolBarItemActivated(
-		ToolBarItem 	item, 
-		long 			activationType,
-		Object 			datasource) 
-	{
-		return( ViewUtils.toolBarItemActivated( manager, item, activationType, datasource ));
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener#toolBarItemActivated(com.aelitis.azureus.ui.common.ToolBarItem, long, java.lang.Object)
+	 */
+	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
+			Object datasource) {
+		return false; // default handler will handle it
 	}
 
-	public void 
-	refreshToolBarItems(
-		Map<String, Long> list) 
-	{	
-		ViewUtils.refreshToolBarItems(manager, list);
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener#refreshToolBarItems(java.util.Map)
+	 */
+	public void refreshToolBarItems(Map<String, Long> list) {
+		Map<String, Long> states = TorrentUtil.calculateToolbarStates(
+				SelectedContentManager.getCurrentlySelectedContent(), null);
+		list.putAll(states);
 	}
 	
 	private abstract class
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/FilesView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/FilesView.java
index 54e764c..7d65480 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/FilesView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/FilesView.java
@@ -1,11 +1,12 @@
 /*
  * Created on 17 juil. 2003
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,9 +16,6 @@
  * 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;
 
@@ -26,7 +24,6 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
 import java.util.regex.Pattern;
 
 import org.eclipse.swt.SWT;
@@ -34,16 +31,11 @@ import org.eclipse.swt.dnd.*;
 import org.eclipse.swt.events.KeyEvent;
 import org.eclipse.swt.events.KeyListener;
 import org.eclipse.swt.graphics.Point;
-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.*;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.config.ParameterListener;
 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.*;
 import org.gudy.azureus2.core3.logging.LogEvent;
 import org.gudy.azureus2.core3.logging.LogIDs;
 import org.gudy.azureus2.core3.logging.Logger;
@@ -51,9 +43,7 @@ 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.toolbar.UIToolBarItem;
 import org.gudy.azureus2.ui.swt.Messages;
-import org.gudy.azureus2.ui.swt.TorrentUtil;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
@@ -69,10 +59,8 @@ import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
 
 import com.aelitis.azureus.core.util.AZ3Functions;
 import com.aelitis.azureus.core.util.RegExUtil;
-import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.common.table.*;
 import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
-import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
@@ -87,7 +75,8 @@ import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 public class FilesView
 	extends TableViewTab<DiskManagerFileInfo>
 	implements TableDataSourceChangedListener, TableSelectionListener,
-	TableViewSWTMenuFillListener, TableRefreshListener, DownloadManagerStateAttributeListener,
+	TableViewSWTMenuFillListener, TableRefreshListener, 
+	DownloadManagerStateAttributeListener, DownloadManagerListener,
 	TableLifeCycleListener, TableViewFilterCheck<DiskManagerFileInfo>, KeyListener
 {
 	private static boolean registeredCoreSubViews = false;
@@ -112,6 +101,7 @@ public class FilesView
     new TorrentRelativePathItem(),
     new FileCRC32Item(),
     new FileMD5Item(),
+    new FileSHA1Item(),
     new FileAvailabilityItem(),
     new AlertsItem(  TableManager.TABLE_TORRENT_FILES ),
     new FileReadSpeedItem(),
@@ -132,6 +122,7 @@ public class FilesView
   private boolean	enable_tabs = true;
   
   public static boolean show_full_path;
+  public static boolean hide_dnd_files;
 
   static{
 	  COConfigurationManager.addAndFireParameterListener(
@@ -176,6 +167,11 @@ public class FilesView
 		if (allowTabViews) {
 	  		tv.setEnableTabViews(enable_tabs,true,null);
 		}
+		
+			// default filter to support meta-filter operations (e.g. hide dnd files)
+		
+		tv.enableFilterCheck( null, this );
+		
   		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
   		if (uiFunctions != null) {
   			UISWTInstance pluginUI = uiFunctions.getUISWTInstance();
@@ -201,48 +197,51 @@ public class FilesView
 
   
   // @see com.aelitis.azureus.ui.common.table.TableDataSourceChangedListener#tableDataSourceChanged(java.lang.Object)
-  public void tableDataSourceChanged(Object newDataSource) {
-	  	DownloadManager old_manager = manager;
-		if (newDataSource == null){
-			manager = null;
-		}else if (newDataSource instanceof Object[]){
-			Object[] ds = (Object[])newDataSource;
-			
-			if ( ds.length == 1 ){
-				Object temp = ds[0];
-				if ( temp instanceof DownloadManager ){
-					manager = (DownloadManager)temp;
-				}else if ( temp instanceof DiskManagerFileInfo){
-					manager = ((DiskManagerFileInfo)temp).getDownloadManager();
-				}else{
-					return;
+	public void tableDataSourceChanged(Object newDataSource) {
+		DownloadManager newManager = null;
+		if (newDataSource instanceof Object[]) {
+			Object[] newDataSources = (Object[]) newDataSource;
+			if (newDataSources.length == 1) {
+				Object temp = ((Object[]) newDataSource)[0];
+				if (temp instanceof DownloadManager) {
+					newManager = (DownloadManager) temp;
+				} else if (temp instanceof DiskManagerFileInfo) {
+					newManager = ((DiskManagerFileInfo) temp).getDownloadManager();
 				}
-			}else{
-				manager = null;
 			}
-		}else{
-			if ( newDataSource instanceof DownloadManager ){
-				manager = (DownloadManager)newDataSource;
-			}else if ( newDataSource instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)newDataSource).getDownloadManager();
-			}else{
-				return;
+		} else {
+			if (newDataSource instanceof DownloadManager) {
+				newManager = (DownloadManager) newDataSource;
+			} else if (newDataSource instanceof DiskManagerFileInfo) {
+				newManager = ((DiskManagerFileInfo) newDataSource).getDownloadManager();
 			}
 		}
-		
-		if ( old_manager == manager ){
+
+		if (newManager == manager) {
+			tv.setEnabled(manager != null);
 			return;
 		}
-		
-		if (old_manager != null) {
-			old_manager.getDownloadState().removeListener(this, DownloadManagerState.AT_FILE_LINKS2, DownloadManagerStateAttributeListener.WRITTEN);
+
+		if (manager != null) {
+			manager.getDownloadState().removeListener(this,
+					DownloadManagerState.AT_FILE_LINKS2,
+					DownloadManagerStateAttributeListener.WRITTEN);
+			manager.removeListener(this);
 		}
+
+		manager = newManager;
+
 		if (manager != null) {
-			manager.getDownloadState().addListener(this, DownloadManagerState.AT_FILE_LINKS2, DownloadManagerStateAttributeListener.WRITTEN);
+			manager.getDownloadState().addListener(this,
+					DownloadManagerState.AT_FILE_LINKS2,
+					DownloadManagerStateAttributeListener.WRITTEN);
+
+			manager.addListener(this);
 		}
 
-		if ( !tv.isDisposed()){
+		if (!tv.isDisposed()) {
 			tv.removeAllTableRows();
+			tv.setEnabled(manager != null);
 		}
 	}
 	
@@ -260,15 +259,59 @@ public class FilesView
 		updateSelectedContent();
 	}
 
+	public void
+	stateChanged(
+		DownloadManager manager,
+		int		state )
+	{
+	}
+
+	public void
+	downloadComplete(DownloadManager manager)
+	{
+	}
+
+	public void
+	completionChanged(DownloadManager manager, boolean bCompleted)
+	{
+	}
+
+	public void
+	positionChanged(DownloadManager download, int oldPosition, int newPosition)
+	{
+	}
+
+	public void
+	filePriorityChanged( DownloadManager download, DiskManagerFileInfo file )
+	{
+		if ( hide_dnd_files ){
+			
+			tv.refilter();
+		}
+	}
+  
 	public boolean 
 	filterCheck(
 		DiskManagerFileInfo ds, String filter, boolean regex )
 	{
+		if ( hide_dnd_files && ds.isSkipped()){
+			
+			return( false );
+		}
+		
 		if ( filter == null || filter.length() == 0 ){
 			
 			return( true );
 		}
 
+		if ( tv.getFilterControl() == null ){
+		
+				// view has no visible filter control so ignore any current filter as the
+				// user's going to get confused...
+			
+			return( true );
+		}
+		
 		try {
 			File file = ds.getFile(true);
 
@@ -322,6 +365,7 @@ public class FilesView
 		DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) tv.getFirstSelectedDataSource();
 		
 		if ( fileInfo == null ){
+			
 			return;
 		}
 		
@@ -333,31 +377,58 @@ public class FilesView
 			
 			ManagerUtils.open( fileInfo, openMode) ;
 			
-		}else if ( mode.equals( "3" )){
-			
-			if ( fileInfo.getAccessMode() == DiskManagerFileInfo.READ ){
-				
-				Utils.launch(fileInfo);
-			}	
 		}else{
 			
-			AZ3Functions.provider az3 = AZ3Functions.getProvider();
+			boolean webInBrowser = COConfigurationManager.getBooleanParameter( "Library.LaunchWebsiteInBrowser" );
 			
-			if ( az3 != null ){
-				
-				DownloadManager dm = fileInfo.getDownloadManager();
-				
-				if ( az3.canPlay(dm, fileInfo.getIndex()) || (stateMask & SWT.CONTROL) != 0 ){
-					
-					az3.play( dm, fileInfo.getIndex() );
+			if ( webInBrowser ){
+													
+				if ( ManagerUtils.browseWebsite( fileInfo )){
 					
 					return;
 				}
 			}
+				
+			if ( mode.equals( "3" ) || mode.equals( "4" )){
+	
 			
-			if ( fileInfo.getAccessMode() == DiskManagerFileInfo.READ ){
+				if ( fileInfo.getAccessMode() == DiskManagerFileInfo.READ ){
+					
+					if ( 	mode.equals( "4" ) &&
+							fileInfo.getDownloaded() == fileInfo.getLength() &&
+							Utils.isQuickViewSupported( fileInfo )){
+						
+						Utils.setQuickViewActive( fileInfo, true );
+						
+					}else{
+					
+						Utils.launch(fileInfo);
+					}
+				}	
+			}else if ( mode.equals( "5" )){
 				
-				Utils.launch(fileInfo);
+				ManagerUtils.browse( fileInfo );
+				
+			}else{
+				
+				AZ3Functions.provider az3 = AZ3Functions.getProvider();
+				
+				if ( az3 != null ){
+					
+					DownloadManager dm = fileInfo.getDownloadManager();
+					
+					if ( az3.canPlay(dm, fileInfo.getIndex()) || (stateMask & SWT.CONTROL) != 0 ){
+						
+						az3.play( dm, fileInfo.getIndex() );
+						
+						return;
+					}
+				}
+				
+				if ( fileInfo.getAccessMode() == DiskManagerFileInfo.READ ){
+					
+					Utils.launch(fileInfo);
+				}
 			}
 		}
 	}
@@ -480,6 +551,18 @@ public class FilesView
             COConfigurationManager.setParameter( "mtv.eta.show_absolute", MyTorrentsView.eta_absolute );
           }
         });
+    }else if (sColumnName.equals("priority")) {
+        final MenuItem item = new MenuItem(menuThisColumn, SWT.CHECK );
+        Messages.setLanguageText(item, "FilesView.hide.dnd");
+        item.setSelection( hide_dnd_files );
+                
+        item.addListener(SWT.Selection, new Listener() {
+          public void handleEvent(Event e) {
+        	  hide_dnd_files = item.getSelection();
+        	  COConfigurationManager.setParameter( "FilesView.hide.dnd", hide_dnd_files );
+        	  tv.refilter();
+          }
+        });
     }
   }
   
@@ -527,6 +610,8 @@ public class FilesView
 
   	if (manager != null) {
 		  manager.getDownloadState().removeListener(this, DownloadManagerState.AT_FILE_LINKS2, DownloadManagerStateAttributeListener.WRITTEN);
+		  
+		  manager.removeListener( this );
 	  }
   }
 
@@ -600,48 +685,6 @@ public class FilesView
 			Logger.log(new LogEvent(LogIDs.GUI, "failed to init drag-n-drop", t));
 		}
 	}
-	
-	public void refreshToolBarItems(Map<String, Long> list) {
-		super.refreshToolBarItems(list);
-		ISelectedContent[] content = SelectedContentManager.getCurrentlySelectedContent();
-		long hasEnabledSelect = content.length > 0
-				? UIToolBarItem.STATE_ENABLED : 0;
-		list.put("run", hasEnabledSelect);
-		list.put("start", hasEnabledSelect);
-		list.put("stop", hasEnabledSelect);
-		list.put("remove", hasEnabledSelect);
-		list.put("startstop", hasEnabledSelect);
-	}
-
-	public boolean toolBarItemActivated(ToolBarItem item, long activationType, Object datasource) {
-		String itemKey = item.getID();
-
-		Object[] selected = tv.getSelectedDataSources().toArray();
-		
-		if ( selected.length > 0 ){
-	    if(itemKey.equals("run")){
-	      TorrentUtil.runDataSources(selected);
-	      return true;
-	    }
-	    if(itemKey.equals("start")){
-	      TorrentUtil.queueDataSources(selected, false);
-	      UIFunctionsManagerSWT.getUIFunctionsSWT().refreshIconBar();
-	      return true;
-	    }
-	    if(itemKey.equals("stop")){
-	      TorrentUtil.stopDataSources(selected);
-	      UIFunctionsManagerSWT.getUIFunctionsSWT().refreshIconBar();
-	      return true;
-	    }
-	    if(itemKey.equals("remove")){
-	      TorrentUtil.removeDataSources(selected);
-	      UIFunctionsManagerSWT.getUIFunctionsSWT().refreshIconBar();
-	      return true;
-	    }
-		}
-		
-    return super.toolBarItemActivated(item, activationType, datasource);
-	}
 
 	public boolean eventOccurred(UISWTViewEvent event) {
 		if (event.getType() == UISWTViewEvent.TYPE_CREATE){
@@ -652,11 +695,11 @@ public class FilesView
 	    		  enable_tabs = parent != null && parent.equals( UISWTInstance.VIEW_TORRENT_DETAILS );
 	    	  }
 	    }
-		
 		boolean b = super.eventOccurred(event);
 		if (event.getType() == UISWTViewEvent.TYPE_FOCUSGAINED) {
 	    updateSelectedContent();
 		} else if (event.getType() == UISWTViewEvent.TYPE_FOCUSLOST) {
+			SelectedContentManager.clearCurrentlySelectedContent();
 		}
 		return b;
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/FilesViewMenuUtil.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/FilesViewMenuUtil.java
index 4dd3360..02eb14f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/FilesViewMenuUtil.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/FilesViewMenuUtil.java
@@ -1,10 +1,12 @@
 /**
  * Created on May 12, 2010
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -27,6 +29,7 @@ import org.eclipse.swt.widgets.*;
 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;
 import org.gudy.azureus2.core3.util.AERunnable;
 import org.gudy.azureus2.core3.util.Debug;
@@ -34,9 +37,11 @@ import org.gudy.azureus2.core3.util.FileUtil;
 import org.gudy.azureus2.plugins.sharing.ShareManager;
 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.Utils;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.ui.common.util.MenuItemManager;
+import org.gudy.azureus2.ui.swt.*;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.MenuFactory;
 import org.gudy.azureus2.ui.swt.sharing.ShareUtils;
 import org.gudy.azureus2.ui.swt.shells.AdvRenameWindow;
@@ -63,7 +68,7 @@ public class FilesViewMenuUtil
 	public static final Object PRIORITY_SKIPPED 		= new Object();
 	public static final Object PRIORITY_DELETE 			= new Object();
 
-	public static void fillMenu(final TableView tv,
+	public static void fillMenu(final TableView<?> tv,
 			final Menu menu, final DownloadManager manager,
 			final Object[] data_sources) {
 		Shell shell = menu.getShell();
@@ -96,6 +101,64 @@ public class FilesViewMenuUtil
 		});
 		itemExplore.setEnabled(hasSelection);
 
+			// open in browser
+		
+		final Menu menuBrowse = new Menu(menu.getShell(),SWT.DROP_DOWN);
+		final MenuItem itemBrowse = new MenuItem(menu, SWT.CASCADE);
+		Messages.setLanguageText(itemBrowse, "MyTorrentsView.menu.browse");
+		itemBrowse.setMenu(menuBrowse);
+
+		
+		final MenuItem itemBrowsePublic = new MenuItem(menuBrowse, SWT.PUSH);
+		itemBrowsePublic.setText( MessageText.getString( "label.public" ) + "..." );
+		itemBrowsePublic.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				for (int i = data_sources.length - 1; i >= 0; i--) {
+					DiskManagerFileInfo info = (DiskManagerFileInfo) data_sources[i];
+					if (info != null) {
+						ManagerUtils.browse(info, false, true );
+					}
+				}
+			}
+		});
+		
+		final MenuItem itemBrowseAnon = new MenuItem(menuBrowse, SWT.PUSH);
+		itemBrowseAnon.setText( MessageText.getString( "label.anon" ) + "..." );
+		itemBrowseAnon.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				for (int i = data_sources.length - 1; i >= 0; i--) {
+					DiskManagerFileInfo info = (DiskManagerFileInfo) data_sources[i];
+					if (info != null) {
+						ManagerUtils.browse(info, true, true );
+					}
+				}
+			}
+		});
+		
+		new MenuItem(menuBrowse, SWT.SEPARATOR);
+		
+		final MenuItem itemBrowseURL = new MenuItem(menuBrowse, SWT.PUSH);
+		Messages.setLanguageText(itemBrowseURL, "label.copy.url.to.clip" );
+		itemBrowseURL.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event){
+				Utils.getOffOfSWTThread(
+					new AERunnable() {
+						@Override
+						public void runSupport() {
+							String url = ManagerUtils.browse(dmi_array[0], true, false );
+							if ( url != null ){
+								ClipboardCopy.copyToClipBoard( url );
+							}
+						}
+					});
+			}});
+		
+		itemBrowseURL.setEnabled( data_sources.length==1 );
+		
+		menuBrowse.setEnabled(hasSelection);
+		
+			// rename/retarget
+		
 		MenuItem itemRenameOrRetarget = null, itemRename = null, itemRetarget = null;
 
 		itemRenameOrRetarget = new MenuItem(menu, SWT.PUSH);
@@ -337,6 +400,19 @@ public class FilesViewMenuUtil
 		itemLow.addListener(SWT.Selection, priorityListener);
 		itemSkipped.addListener(SWT.Selection, priorityListener);
 		itemDelete.addListener(SWT.Selection, priorityListener);
+		
+		org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items = MenuItemManager.getInstance().getAllAsArray(
+				MenuManager.MENU_FILE_CONTEXT);
+		if (menu_items.length > 0) {
+			// plugins take org.gudy.azureus2.plugins.disk.DiskManagerFileInfo
+			org.gudy.azureus2.plugins.disk.DiskManagerFileInfo[] fileInfos = new org.gudy.azureus2.plugins.disk.DiskManagerFileInfo[data_sources.length];
+			for (int i = 0; i < data_sources.length; i++) {
+				fileInfos[i] = (org.gudy.azureus2.plugins.disk.DiskManagerFileInfo) PluginCoreUtils.convert(
+						data_sources[i], false);
+			}
+			MenuBuildUtils.addPluginMenuItems(menu_items, menu, false, true,
+					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(fileInfos));
+		}
 	}
 
 	public static void rename(final TableView tv, final DownloadManager not_used,
@@ -395,27 +471,72 @@ public class FilesViewMenuUtil
 					paused = manager.pause();
 				}
 
+				boolean	dont_delete_existing = false;
+				
 				if (f_target.exists()) {
 
-					// Nothing to do.
-					if (f_target.equals(existing_file))
+						// Nothing to do.
+					
+					if ( f_target.equals(existing_file)){
+						
 						continue;
 
-					// A rewrite will occur, so we need to ask the user's permission.
-					else if (existing_file.exists() && !askCanOverwrite(existing_file))
-						continue;
+					}else if ( retarget_it ){
+						
+						// we're doing a re-target so we just need to update the file info to refer to the new existing file
+						
+						dont_delete_existing = true;
+						
+					}else if ( existing_file.exists() && !askCanOverwrite(existing_file)){
+
+						// A rewrite will occur, so we need to ask the user's permission.
 
+						continue;
+					}
+					
 					// If we reach here, then it means we are doing a real move, but there is
 					// no existing file.
 				}
 
 				final File ff_target = f_target;
-				final TableRowCore row = tv == null ? null : tv.getRow(datasources[i]);
+				
+				TableRowCore row = tv == null ? null : tv.getRow(datasources[i]);
+				
+				if ( row == null ){
+					
+					if ( tv != null ){
+						
+						row = tv.getRow( fileInfo.getDownloadManager());
+						
+						if ( row != null ){
+							
+							TableRowCore[] subrows = row.getSubRowsWithNull();
+									
+							if ( subrows != null ){
+								
+								for ( TableRowCore sr: subrows ){
+									
+									if ( sr.getDataSource(true) == fileInfo ){
+										
+										row = sr;
+										
+										break;
+									}
+								}
+							}
+						}
+					}
+				}
+				
+				final TableRowCore f_row = row;
+				
+				final boolean f_dont_delete_existing = dont_delete_existing;
+				
 				Utils.getOffOfSWTThread(new AERunnable() {
 					public void runSupport() {
-						moveFile(fileInfo.getDownloadManager(), fileInfo, ff_target);
-						if (row != null) {
-							row.invalidate(true);
+						moveFile(fileInfo.getDownloadManager(), fileInfo, ff_target, f_dont_delete_existing );
+						if (f_row != null) {
+							f_row.invalidate(true);
 						}
 					}
 				});
@@ -614,7 +735,31 @@ public class FilesViewMenuUtil
 	private static String askForRenameFilename(DiskManagerFileInfo fileInfo) {
 		SimpleTextEntryWindow dialog = new SimpleTextEntryWindow(
 				"FilesView.rename.filename.title", "FilesView.rename.filename.text");
-		dialog.setPreenteredText(fileInfo.getFile(true).getName(), false); // false -> it's not "suggested", it's a previous value
+		String file_name = fileInfo.getFile(true).getName();
+		dialog.setPreenteredText(file_name, false); // false -> it's not "suggested", it's a previous value
+		
+		int pos = file_name.lastIndexOf( '.' );
+		
+		if ( pos > 0 ){
+			
+			String suffix = fileInfo.getDownloadManager().getDownloadState().getAttribute( DownloadManagerState.AT_INCOMP_FILE_SUFFIX );
+			
+			if ( suffix != null && file_name.substring( pos ).equals( suffix )){
+				
+				pos--;
+				
+				while( pos > 0 && file_name.charAt( pos ) != '.' ){
+					
+					pos--;
+				}
+			}
+			
+			if ( pos > 0 ){
+			
+				dialog.selectPreenteredTextRange( new int[]{ 0, pos });
+			}
+		}
+		
 		dialog.allowEmptyInput(false);
 		dialog.prompt();
 		if (!dialog.hasSubmittedInput()) {
@@ -624,8 +769,7 @@ public class FilesViewMenuUtil
 	}
 
 	private static String askForRetargetedFilename(DiskManagerFileInfo fileInfo) {
-		FileDialog fDialog = new FileDialog(Utils.findAnyShell(), SWT.SYSTEM_MODAL
-				| SWT.SAVE);
+		FileDialog fDialog = new FileDialog(Utils.findAnyShell(), SWT.SYSTEM_MODAL ); // parg - removed SAVE option as this prevents the selection of existing read-only media when re-targetting	| SWT.SAVE);
 		File existing_file = fileInfo.getFile(true);
 		fDialog.setFilterPath(existing_file.getParent());
 		fDialog.setFileName(existing_file.getName());
@@ -658,13 +802,24 @@ public class FilesViewMenuUtil
 	}
 
 	// same code is used in tableitems.files.NameItem
-	private static void moveFile(final DownloadManager manager,
-			final DiskManagerFileInfo fileInfo, final File target) {
+	private static void 
+	moveFile(
+		final DownloadManager 			manager,
+		final DiskManagerFileInfo 		fileInfo, 
+		final File 						target,
+		boolean							dont_delete_existing ) 
+	{
 
 		// this behaviour should be put further down in the core but I'd rather not
 		// do so close to release :(
 
 		manager.setUserData("is_changing_links", true);
+		
+		if ( dont_delete_existing ){
+				// I don't link this one bit, but there's a lot of things I don't like and this isn't the worst
+			manager.setUserData("set_link_dont_delete_existing", true);
+		}
+		
 		try {
 			final boolean[] result = {
 				false
@@ -675,6 +830,8 @@ public class FilesViewMenuUtil
 					result[0] = fileInfo.setLink(target);
 
 					manager.setUserData("is_changing_links", false);
+					manager.setUserData("set_link_dont_delete_existing", null);
+					
 					if (!result[0]) {
 						new MessageBoxShell(SWT.ICON_ERROR | SWT.OK,
 								MessageText.getString("FilesView.rename.failed.title"),
@@ -684,6 +841,7 @@ public class FilesViewMenuUtil
 			});
 		} catch (Exception e) {
 			manager.setUserData("is_changing_links", false);
+			manager.setUserData("set_link_dont_delete_existing", null);
 		}
 	}
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/GeneralView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/GeneralView.java
index d77c593..e9fcf36 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/GeneralView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/GeneralView.java
@@ -1,6 +1,6 @@
 /*
  * Created on 2 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,14 +14,13 @@
  * 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;
 
 import java.text.DecimalFormat;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.ScrolledComposite;
@@ -35,7 +34,6 @@ import org.eclipse.swt.graphics.Rectangle;
 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.config.ParameterListener;
 import org.gudy.azureus2.core3.disk.DiskManager;
@@ -66,6 +64,8 @@ import com.aelitis.azureus.util.MapUtils;
 
 /**
  * View of General information on the torrent
+ * <p>
+ * See also {SBC_TorrentDetailsView}
  * 
  * @author Olivier
  * 
@@ -135,32 +135,31 @@ public class GeneralView
   }
 
 	public void dataSourceChanged(Object newDataSource) {
-	  	DownloadManager old_manager = manager;
-		if (newDataSource == null){
-			manager = null;
-		}else if (newDataSource instanceof Object[]){
-			Object temp = ((Object[])newDataSource)[0];
-			if ( temp instanceof DownloadManager ){
-				manager = (DownloadManager)temp;
-			}else if ( temp instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)temp).getDownloadManager();
-			}else{
-				return;
+		DownloadManager newManager = null;
+		if (newDataSource instanceof Object[]) {
+			Object[] newDataSources = (Object[]) newDataSource;
+			if (newDataSources.length == 1) {
+				Object temp = ((Object[]) newDataSource)[0];
+				if (temp instanceof DownloadManager) {
+					newManager = (DownloadManager) temp;
+				} else if (temp instanceof DiskManagerFileInfo) {
+					newManager = ((DiskManagerFileInfo) temp).getDownloadManager();
+				}
 			}
-		}else{
-			if ( newDataSource instanceof DownloadManager ){
-				manager = (DownloadManager)newDataSource;
-			}else if ( newDataSource instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)newDataSource).getDownloadManager();
-			}else{
-				return;
+		} else {
+			if (newDataSource instanceof DownloadManager) {
+				newManager = (DownloadManager) newDataSource;
+			} else if (newDataSource instanceof DiskManagerFileInfo) {
+				newManager = ((DiskManagerFileInfo) newDataSource).getDownloadManager();
 			}
 		}
-		
-		if ( old_manager == manager ){
+	
+		if (newManager == manager) {
 			return;
 		}
 
+		manager = newManager;
+
 		Utils.execSWTThread(new AERunnable() {
 			public void runSupport() {
 				swt_refreshInfo();
@@ -200,11 +199,11 @@ public class GeneralView
     scrolled_comp.setContent(genComposite);
 	scrolled_comp.addControlListener(new ControlAdapter() {
 		public void controlResized(ControlEvent e) {
-			Rectangle r = scrolled_comp.getClientArea();
-			scrolled_comp.setMinSize(genComposite.computeSize(r.width, SWT.DEFAULT ));
+			Utils.updateScrolledComposite(scrolled_comp);
 		}
 	});
 	
+	
     Utils.execSWTThreadLater(0, new AERunnable() {
 			public void runSupport() {
 				swt_refreshInfo();
@@ -215,18 +214,8 @@ public class GeneralView
   }
   
   private void swt_refreshInfo() {
-  	if (manager == null || parent == null){
-  		if ( genComposite != null && !genComposite.isDisposed()){
-  			
-  		  	Utils.disposeComposite(genComposite, false);
-
-  			Label lab = new Label( genComposite, SWT.NULL );
-  			GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
-  			lab.setLayoutData(gridData);
-  			Messages.setLanguageText(lab, "label.no.download.selected" );
-  			
-  			genComposite.layout();
-  		}
+  	if (manager == null || parent == null || parent.isDisposed()){
+  		ViewUtils.setViewRequiresOneDownload(genComposite);
   		return;
   	}
   	
@@ -543,8 +532,7 @@ public class GeneralView
 
     genComposite.layout();
     
-	Rectangle r = scrolled_comp.getClientArea();
-	scrolled_comp.setMinSize(genComposite.computeSize(r.width, SWT.DEFAULT ));
+    Utils.updateScrolledComposite(scrolled_comp);
     //Utils.changeBackgroundComposite(genComposite,MainWindow.getWindow().getBackground());
   }
 
@@ -1072,6 +1060,7 @@ public class GeneralView
 				if (do_relayout)
 				{
 					gInfo.layout();
+					Utils.updateScrolledComposite(scrolled_comp);
 				}
 			}
 		});
@@ -1088,20 +1077,51 @@ public class GeneralView
 	  } else if (c instanceof Link) {
 						String sNewComment;
 		  sNewComment = new_comment.replaceAll(
-								"([^=\">][\\s]+|^)(http://[\\S]+)", "$1<A HREF=\"$2\">$2</A>");
+								"([^=\">][\\s]+|^)((?:https?://|chat:)[\\S]+)", "$1<A HREF=\"$2\">$2</A>");
 						// need quotes around url
 		  sNewComment = sNewComment.replaceAll("(href=)(htt[^\\s>]+)", "$1\"$2\"");
 
+		  	// probably want to URL decode the link text if it is a URL
+		  
+		  try{
+			  Pattern p = Pattern.compile("(?i)(<A HREF=[^>]*>)([^<]*</A>)");
+	
+			  Matcher m = p.matcher( sNewComment );
+	
+			  boolean result = m.find();
+	
+			  if ( result ){
+	
+				  StringBuffer sb = new StringBuffer();
+	
+				  while( result ){
+	
+					  m.appendReplacement(sb, m.group(1));
+					  
+					  String str = m.group(2);
+	
+					  sb.append( UrlUtils.decode( str ));
+	
+					  result = m.find(); 
+				  }
+	
+				  m.appendTail(sb);
+	
+				  sNewComment = sb.toString();
+				  
+			  }}catch( Throwable e ){
+			  }
+		  
 						// Examples:
 						// http://cowbow.com/fsdjl&sdfkj=34.sk9391 moo
 						// <A HREF=http://cowbow.com/fsdjl&sdfkj=34.sk9391>moo</a>
 						// <A HREF="http://cowbow.com/fsdjl&sdfkj=34.sk9391">moo</a>
 						// <A HREF="http://cowbow.com/fsdjl&sdfkj=34.sk9391">http://moo.com</a>
 		  ((Link)c).setText(sNewComment);
-			  	        	}
-	  return true;
-			  	    
-			          }
+	  }
+	  
+	  return true;			  	    
+  }
 
   public void parameterChanged(String parameterName) {
     graphicsUpdate = COConfigurationManager.getIntParameter("Graphics Update");
@@ -1146,14 +1166,21 @@ public class GeneralView
       		if (manager.getTorrent() != null) {
   					id += "." + manager.getInternalName();
       		} else {
-      			id += ":" + manager.getSize();
-      		}
-      	}
+						id += ":" + manager.getSize();
+					}
+					SelectedContentManager.changeCurrentlySelectedContent(id,
+							new SelectedContent[] {
+								new SelectedContent(manager)
+					});
+				} else {
+					SelectedContentManager.changeCurrentlySelectedContent(id, null);
+				}
   
-      	SelectedContentManager.changeCurrentlySelectedContent(id, new SelectedContent[] {
-      		new SelectedContent(manager)
-      	});
       	break;
+
+      case UISWTViewEvent.TYPE_FOCUSLOST:
+    		SelectedContentManager.clearCurrentlySelectedContent();
+    		break;
         
       case UISWTViewEvent.TYPE_REFRESH:
         refresh();
@@ -1172,12 +1199,20 @@ public class GeneralView
     return true;
   }
 
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener#toolBarItemActivated(com.aelitis.azureus.ui.common.ToolBarItem, long, java.lang.Object)
+	 */
 	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
 			Object datasource) {
-		return( ViewUtils.toolBarItemActivated(manager, item, activationType, datasource));
+		return false; // default handler will handle it
 	}
 
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener#refreshToolBarItems(java.util.Map)
+	 */
 	public void refreshToolBarItems(Map<String, Long> list) {
-		ViewUtils.refreshToolBarItems(manager, list);
+		Map<String, Long> states = TorrentUtil.calculateToolbarStates(
+				SelectedContentManager.getCurrentlySelectedContent(), null);
+		list.putAll(states);
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/IViewAlwaysInitialize.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/IViewAlwaysInitialize.java
index d7c1e2c..b0e91a6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/IViewAlwaysInitialize.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/IViewAlwaysInitialize.java
@@ -1,10 +1,12 @@
 /**
  * Created on Mar 30, 2010
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/LoggerView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/LoggerView.java
index 72fedf0..d8b4ed5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/LoggerView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/LoggerView.java
@@ -1,9 +1,10 @@
 /**
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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;
 
@@ -39,7 +37,6 @@ import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.layout.RowLayout;
 import org.eclipse.swt.widgets.*;
-
 import org.gudy.azureus2.core3.config.ParameterListener;
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.logging.*;
@@ -51,6 +48,7 @@ import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTView;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListenerEx;
 
 /**
  * @author TuxPaper
@@ -58,8 +56,10 @@ import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
  * @since 2.3.0.5
  */
 public class LoggerView
-	implements ILogEventListener, ParameterListener, UISWTViewCoreEventListener
+	implements ILogEventListener, ParameterListener, UISWTViewCoreEventListenerEx
 {
+	public static final String VIEW_ID = "LoggerView";
+	
 	//private final static LogIDs LOGID = LogIDs.GUI;
 
 	private static final int COLOR_INFO = 0;
@@ -136,6 +136,33 @@ public class LoggerView
 		setEnabled(true);
 	}
 
+	private
+	LoggerView(
+		LoggerView		other )
+	{
+		buffer.addAll( other.buffer );
+		
+		for (int i = 0; i < ignoredComponents.length; i++) {
+			ignoredComponents[i] = new ArrayList();
+		}
+		
+		stopOnNull	= other.stopOnNull;
+		
+		setEnabled( other.bEnabled );
+	}
+	
+	public boolean
+	isCloneable()
+	{
+		return( true );
+	}
+	
+	public UISWTViewCoreEventListener
+	getClone()
+	{
+		return( new LoggerView( this ));
+	}
+	
 	private void initialize(Composite composite) {
 		display = composite.getDisplay();
 
@@ -169,6 +196,18 @@ public class LoggerView
 				consoleText.setTabs(areaWidth / 6 / charWidth);
 			}
 		});
+		
+		consoleText.addListener(SWT.KeyDown, new Listener() {
+			public void handleEvent(Event event) {
+				int key = event.character;
+				if (key <= 26 && key > 0) {
+					key += 'a' - 1;
+				}
+				if ((event.stateMask & SWT.MOD1) > 0  && key == 'a') {
+					((StyledText) event.widget).selectAll();
+				}
+			}
+		});
 
 		ScrollBar sb = consoleText.getVerticalBar();
 		sb.addSelectionListener(new SelectionAdapter() {
@@ -723,6 +762,7 @@ public class LoggerView
 	public boolean eventOccurred(UISWTViewEvent event) {
     switch (event.getType()) {
       case UISWTViewEvent.TYPE_CREATE:
+      	event.getView().setDestroyOnDeactivate(false);
       	swtView = (UISWTView)event.getData();
       	swtView.setTitle(getFullTitle());
         break;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/MySharesView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/MySharesView.java
index f0912cc..6d5390d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/MySharesView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/MySharesView.java
@@ -3,11 +3,12 @@
  * Created : 18-Jan-2004
  * By      : parg
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.
  */
 
 
@@ -47,6 +45,7 @@ import org.gudy.azureus2.plugins.torrent.Torrent;
 import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
 import org.gudy.azureus2.plugins.tracker.Tracker;
 import org.gudy.azureus2.plugins.tracker.TrackerTorrent;
+import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
 import org.gudy.azureus2.plugins.ui.tables.TableManager;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
@@ -85,7 +84,8 @@ public class MySharesView
 extends TableViewTab<ShareResource>
 implements ShareManagerListener,
 		TableLifeCycleListener, TableViewSWTMenuFillListener,
-		TableRefreshListener, TableSelectionListener, ViewTitleInfo2
+		TableRefreshListener, TableSelectionListener, ViewTitleInfo2,
+		UIPluginViewToolBarListener
 {
   private static final TableColumnCore[] basicItems = {
     new NameItem(),
@@ -157,7 +157,8 @@ implements ShareManagerListener,
 
 					UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 					if (uiFunctions != null) {
-						uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, dm);
+						uiFunctions.getMDI().showEntryByID(
+								MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS, dm);
 					}
 
 					break;
@@ -406,7 +407,6 @@ implements ShareManagerListener,
 	  }
 
 	public void refreshToolBarItems(Map<String, Long> list) {
-	  	super.refreshToolBarItems(list);
 
 	  	boolean start = false, stop = false, remove = false;
     
@@ -477,7 +477,7 @@ implements ShareManagerListener,
     	startSelectedShares();
     	return true;
     }
-		return super.toolBarItemActivated(item, activationType, datasource);
+		return false;
   }
   
   private List
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsSubView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsSubView.java
new file mode 100644
index 0000000..f270c8d
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsSubView.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views;
+
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+
+/**
+ * @author TuxPaper
+ * @created Mar 6, 2015
+ *
+ */
+public class MyTorrentsSubView
+	extends MyTorrentsView
+{
+
+	public MyTorrentsSubView() {
+		super("MyTorrentsSubView", false);
+		neverShowCatOrTagButtons = true;
+		isEmptyListOnNullDS = true;
+		AzureusCore _azureus_core = AzureusCoreFactory.getSingleton();
+		init(_azureus_core, "MyTorrentsSubView", Download.class,
+				TableColumnCreator.createCompleteDM("MyTorrentsSubView"));
+	}
+
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsSuperView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsSuperView.java
index 7ac8c2e..4241c25 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsSuperView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsSuperView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,26 +12,24 @@
  * 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;
 
-import java.util.Arrays;
 import java.util.Map;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.*;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
 import org.eclipse.swt.layout.*;
 import org.eclipse.swt.widgets.*;
-
 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 org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.IndentWriter;
 import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
 import org.gudy.azureus2.plugins.ui.tables.TableManager;
 import org.gudy.azureus2.ui.swt.DelayedListenerMultiCombiner;
@@ -51,14 +49,12 @@ import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.AzureusCoreRunningListener;
 import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.common.table.TableColumnCore;
-import com.aelitis.azureus.ui.common.table.TableRowCore;
-import com.aelitis.azureus.ui.common.table.TableSelectionAdapter;
-import com.aelitis.azureus.ui.common.table.TableSelectionListener;
 import com.aelitis.azureus.ui.common.table.TableView;
 import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
 import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentListener;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
+import com.aelitis.azureus.ui.swt.mdi.MdiEntrySWT;
 import com.aelitis.azureus.util.MapUtils;
 
 /**
@@ -148,30 +144,7 @@ public class MyTorrentsSuperView
   	layout.marginWidth = 0;
   	child1.setLayout(layout);
 
-    final Sash sash = new Sash(form, SWT.HORIZONTAL);
-    Image image = new Image(sash.getDisplay(), 9, SASH_WIDTH);
-    ImageData imageData = image.getImageData();
-    int[] row = new int[imageData.width];
-    for (int i = 0; i < row.length; i++) {
-   		row[i] = (i % 3) != 0 ? 0xE0E0E0 : 0x808080;
-    	if (imageData.depth == 32) {
-    		row[i] = (row[i] & 255) + (row[i] << 8);
-    	}
-		}
-    for (int y = 1; y < imageData.height - 1; y++) {
-    	imageData.setPixels(0, y, row.length, row, 0);
-    }
-    Arrays.fill(row, 0xE0E0E0E0);
-  	imageData.setPixels(0, 0, row.length, row, 0);
-  	imageData.setPixels(0, imageData.height - 1, row.length, row, 0);
-    image.dispose();
-    image = new Image(sash.getDisplay(), imageData);
-    sash.setBackgroundImage(image);
-    sash.addDisposeListener(new DisposeListener() {
-			public void widgetDisposed(DisposeEvent e) {
-				sash.getBackgroundImage().dispose();
-			}
-		});
+  	final Sash sash = Utils.createSash( form, SASH_WIDTH );
 
     child2 = new Composite(form,SWT.NULL);
     layout = new GridLayout();
@@ -287,7 +260,21 @@ public class MyTorrentsSuperView
     seedingview = createTorrentView(core,
 				TableManager.TABLE_MYTORRENTS_COMPLETE, true, getCompleteColumns(),
 				child2);
+    
+    
+    torrentview.getComposite().addListener(SWT.FocusIn, new Listener() {
+			public void handleEvent(Event event) {
+				seedingview.getTableView().getTabsCommon().setTvOverride(torrentview.getTableView());
+			}
+		});
+
+    seedingview.getComposite().addListener(SWT.FocusIn, new Listener() {
+			public void handleEvent(Event event) {
+				seedingview.getTableView().getTabsCommon().setTvOverride(null);
+			}
+		});
 
+    
     	// delegate selections from the incomplete view to the sub-tabs owned by the seeding view
     
     SelectedContentManager.addCurrentlySelectedContentListener(
@@ -315,7 +302,7 @@ public class MyTorrentsSuperView
     				
     					if ( tabs != null ){
     				
-    						tabs.triggerTabViewsDataSourceChanged( (TableViewSWT<?>)selected_tv );
+    						tabs.triggerTabViewsDataSourceChanged(selected_tv);
     					}
 	    			}
     			}
@@ -360,12 +347,37 @@ public class MyTorrentsSuperView
 
     return lastSelectedView;
   }
+  
+	private UIPluginViewToolBarListener getActiveToolbarListener() {
+		MyTorrentsView[] viewsToCheck = {
+			getCurrentView(),
+			torrentview,
+			seedingview
+		};
+		for (int i = 0; i < viewsToCheck.length; i++) {
+			MyTorrentsView view = viewsToCheck[i];
+			if (view != null) {
+				MdiEntrySWT activeSubView = view.getTableView().getTabsCommon().getActiveSubView();
+				if (activeSubView != null) {
+					UIPluginViewToolBarListener toolBarListener = activeSubView.getToolBarListener();
+					if (toolBarListener != null) {
+						return toolBarListener;
+					}
+				}
+				if (i == 0 && view.isTableFocus()) {
+					return view;
+				}
+			}
+		}
+
+		return null;
+	}
 
   /* (non-Javadoc)
    * @see com.aelitis.azureus.ui.common.ToolBarEnabler2#refreshToolBarItems(java.util.Map)
    */
   public void refreshToolBarItems(Map<String, Long> list) {
-    MyTorrentsView currentView = getCurrentView();
+  	UIPluginViewToolBarListener currentView = getActiveToolbarListener();
     if (currentView != null) {
       currentView.refreshToolBarItems(list);
     }
@@ -375,12 +387,18 @@ public class MyTorrentsSuperView
    * @see com.aelitis.azureus.ui.common.ToolBarActivation#toolBarItemActivated(com.aelitis.azureus.ui.common.ToolBarItem, long)
    */
   public boolean toolBarItemActivated(ToolBarItem item, long activationType, Object datasource) {
-    MyTorrentsView currentView = getCurrentView();
+  	UIPluginViewToolBarListener currentView = getActiveToolbarListener();
     if (currentView != null) {
       if (currentView.toolBarItemActivated(item, activationType, datasource)) {
       	return true;
       }
     }
+    MyTorrentsView currentView2 = getCurrentView();
+    if (currentView2 != currentView && currentView2 != null) {
+      if (currentView2.toolBarItemActivated(item, activationType, datasource)) {
+      	return true;
+      }
+    }
     return false;
   }
   
@@ -515,7 +533,10 @@ public class MyTorrentsSuperView
 				isSeedingView, columns, txtFilter, cCats, isSeedingView );
 		
 		try {
-			UISWTViewImpl swtView = new UISWTViewImpl(UISWTInstance.VIEW_MAIN, tableID, view, ds);
+			UISWTViewImpl swtView = new UISWTViewImpl(tableID, UISWTInstance.VIEW_MAIN, false);
+			swtView.setDatasource(ds);
+			swtView.setEventListener(view, true);
+			swtView.setDelayInitializeToFirstActivate(false);
 			
 			swtView.initialize(c);
 		} catch (Exception e) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsView.java
index b0379c6..296d768 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTorrentsView.java
@@ -1,11 +1,12 @@
 /*
  * Created on 30 juin 2003
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,15 +16,11 @@
  * 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;
 
 import java.io.File;
-import java.io.UnsupportedEncodingException;
 import java.net.URL;
 import java.util.*;
 import java.util.List;
@@ -33,9 +30,13 @@ import org.eclipse.swt.SWT;
 import org.eclipse.swt.dnd.*;
 import org.eclipse.swt.events.*;
 import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.layout.*;
+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.gudy.azureus2.core3.category.*;
+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.config.ParameterListener;
 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
@@ -43,7 +44,11 @@ import org.gudy.azureus2.core3.disk.DiskManagerFileInfoSet;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerListener;
 import org.gudy.azureus2.core3.download.DownloadManagerState;
-import org.gudy.azureus2.core3.global.*;
+import org.gudy.azureus2.core3.download.DownloadManagerStats;
+import org.gudy.azureus2.core3.global.GlobalManager;
+import org.gudy.azureus2.core3.global.GlobalManagerEvent;
+import org.gudy.azureus2.core3.global.GlobalManagerEventListener;
+import org.gudy.azureus2.core3.global.GlobalManagerListener;
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.logging.LogEvent;
 import org.gudy.azureus2.core3.logging.LogIDs;
@@ -54,6 +59,7 @@ import org.gudy.azureus2.core3.torrent.TOTorrentException;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.PluginManager;
+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.UIPluginViewToolBarListener;
@@ -80,22 +86,24 @@ import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab;
 import org.gudy.azureus2.ui.swt.views.table.painted.TableRowPainted;
 import org.gudy.azureus2.ui.swt.views.utils.CategoryUIUtils;
 import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
+import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
 
 import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.tag.Tag;
-import com.aelitis.azureus.core.tag.TagListener;
-import com.aelitis.azureus.core.tag.Taggable;
+import com.aelitis.azureus.core.tag.*;
 import com.aelitis.azureus.core.util.RegExUtil;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.common.table.*;
+import com.aelitis.azureus.ui.common.table.impl.TableViewImpl;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
+import com.aelitis.azureus.ui.swt.mdi.MdiEntrySWT;
 
 /** Displays a list of torrents in a table view.
  *
@@ -111,8 +119,7 @@ public class MyTorrentsView
        implements GlobalManagerListener,
                   ParameterListener,
                   DownloadManagerListener,
-                  CategoryManagerListener,
-                  CategoryListener,
+                  TagTypeListener,
                   TagListener,
                   KeyListener,
                   TableLifeCycleListener, 
@@ -123,7 +130,8 @@ public class MyTorrentsView
                   TableViewFilterCheck.TableViewFilterCheckEx<DownloadManager>,
                   TableRowRefreshListener,
                   TableCountChangeListener,
-                  TableExpansionChangeListener
+                  TableExpansionChangeListener,
+                  UIPluginViewToolBarListener
 {
 	private static final LogIDs LOGID = LogIDs.GUI;
 	
@@ -220,19 +228,19 @@ public class MyTorrentsView
 		}
   	};
   	
-  protected boolean isSeedingView;
   private boolean	supportsTabs;
   private Composite cTablePanel;
   private Font fontButton = null;
-  protected Composite cCategories;
+  protected Composite cCategoriesAndTags;
   private DragSource dragSource = null;
   private DropTarget dropTarget = null;
   protected Text txtFilter = null;
+  private Menu	tableHeaderMenu = null;
   private TimerEventPeriodic	txtFilterUpdateEvent;
 
   
-  private Category 	currentCategory;
-  private Tag		currentTag;
+  private Tag[]		currentTags;
+  private List<Tag>	allTags;
   
   // table item index, where the drag has started
   private int drag_drop_line_start = -1;
@@ -246,15 +254,34 @@ public class MyTorrentsView
 
 	private Composite filterParent;
 
-	private boolean neverShowCatButtons;
+	protected boolean neverShowCatOrTagButtons;
 	
 	private boolean rebuildListOnFocusGain = false;
 
+	private Menu oldMenu;
+
+	private boolean isCompletedOnly;
+
+	private Class<?> forDataSourceType;
+
+	private SelectionListener buttonSelectionListener;
+
+	private Listener buttonHoverListener;
+
+	private DropTargetListener buttonDropTargetListener;
+
+	protected boolean isEmptyListOnNullDS;
+
 	public MyTorrentsView( boolean supportsTabs ) {
 		super("MyTorrentsView");
 		this.supportsTabs = supportsTabs;
 	}
-	
+
+	public MyTorrentsView(String propertiesPrefix, boolean supportsTabs) {
+		super(propertiesPrefix);
+		this.supportsTabs = supportsTabs;
+	}
+
   /**
    * Initialize
    * 
@@ -270,14 +297,14 @@ public class MyTorrentsView
   		boolean 			isSeedingView,
   		TableColumnCore[]	basicItems,
   		Text 				txtFilter, 
-  		Composite 			cCats,
+  		Composite 			cCatsAndTags,
   		boolean				supportsTabs ) 
   {
 		super("MyTorrentsView");
 		this.txtFilter = txtFilter;
-		this.cCategories = cCats;
+		this.cCategoriesAndTags = cCatsAndTags;
 		this.supportsTabs = supportsTabs;
-		init(_azureus_core, tableID, isSeedingView, isSeedingView
+		init(_azureus_core, tableID, isSeedingView
 				? DownloadTypeComplete.class : DownloadTypeIncomplete.class, basicItems);
   }
   
@@ -286,10 +313,56 @@ public class MyTorrentsView
   	return tv;
   }
   
-  public void init(AzureusCore _azureus_core, String tableID,
-			boolean isSeedingView, Class<?> forDataSourceType, TableColumnCore[] basicItems) {
+  // @see org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab#tableViewTabInitComplete()
+  public void tableViewTabInitComplete() {
+  	if (COConfigurationManager.getBooleanParameter("Library.showFancyMenu", true)) {
+    	Composite tableComposite = tv.getComposite();
+    	oldMenu = tableComposite.getMenu();
+    	Menu menu = new Menu(tableComposite);
+    	tableComposite.setMenu(menu);
+    	menu.addMenuListener(new MenuListener() {
+  			
+  			public void menuShown(MenuEvent e) {
+  				if (!showMyOwnMenu(e)) {
+  					oldMenu.setVisible(true);
+  				}
+  			}
+  			
+  			public void menuHidden(MenuEvent e) {
+  			}
+  		});
+  	}
+  	super.tableViewTabInitComplete();
+  }
+  
+	protected boolean showMyOwnMenu(MenuEvent e) {
+		Display d = e.widget.getDisplay();
+		if (d == null)
+			return false;
+		
+		Object[] dataSources = tv.getSelectedDataSources(true);
+		final DownloadManager[] dms = getSelectedDownloads();
 
-  	this.isSeedingView 	= isSeedingView;
+		boolean hasSelection = (dms.length > 0);
+
+		if (!hasSelection) {
+			return false;
+		}
+		Point pt = e.display.getCursorLocation();
+		pt = tv.getTableComposite().toControl(pt.x, pt.y);
+		TableColumnCore column = tv.getTableColumnByOffset(pt.x);
+
+		boolean isSeedingView = Download.class.equals(forDataSourceType) || DownloadTypeComplete.class.equals(forDataSourceType);
+		new TorrentMenuFancy(tv, isSeedingView, getComposite().getShell(), dms,
+				tv.getTableID()).showMenu(column, oldMenu);
+		return true;
+	}
+
+	public void init(AzureusCore _azureus_core, String tableID,
+			Class<?> forDataSourceType, TableColumnCore[] basicItems) {
+
+		this.forDataSourceType = forDataSourceType;
+		this.isCompletedOnly = forDataSourceType.equals(DownloadTypeComplete.class);
   	
     tv = createTableView(forDataSourceType, tableID, basicItems);
     tv.setRowDefaultHeight(17);
@@ -305,8 +378,10 @@ public class MyTorrentsView
     this.globalManager 	= azureus_core.getGlobalManager();
     
 
-    if (currentCategory == null) {
-    	currentCategory = CategoryManager.getCategory(Category.TYPE_ALL);
+    if (currentTags == null) {
+			currentTags = new Tag[] {
+				CategoryManager.getCategory(Category.TYPE_ALL)
+			};
     }
     tv.addLifeCycleListener(this);
     tv.setMainPanelCreator(this);
@@ -321,12 +396,32 @@ public class MyTorrentsView
     
     tv.addTableDataSourceChangedListener(new TableDataSourceChangedListener() {
 			public void tableDataSourceChanged(Object newDataSource) {
-				if (newDataSource instanceof Category) {
-					neverShowCatButtons = true;
-					activateCategory((Category) newDataSource);
-				}else if ( newDataSource instanceof Tag ){
-					neverShowCatButtons = true;
-					activateTag((Tag) newDataSource);
+				if (newDataSource instanceof Tag[]) {
+					neverShowCatOrTagButtons = true;
+					setCurrentTags((Tag[]) newDataSource);
+					return;
+				}
+
+				if (newDataSource instanceof Object[]) {
+					Object[] datasources = ((Object[]) newDataSource);
+					Object firstDS = datasources.length > 0 ? datasources[0] : null;
+					if (firstDS instanceof Tag) {
+						Tag[] tags = new Tag[datasources.length];
+						System.arraycopy(datasources, 0, tags, 0, datasources.length);
+						setCurrentTags(tags);
+						return;
+					}
+				}
+				
+				if ( newDataSource instanceof Tag ){
+					neverShowCatOrTagButtons = true;
+					setCurrentTags(new Tag[] {
+						(Tag) newDataSource
+					});
+				}
+				
+				if (newDataSource == null && isEmptyListOnNullDS) {
+					setCurrentTags(new Tag[] { });
 				}
 			}
 		}, true);
@@ -337,35 +432,9 @@ public class MyTorrentsView
 				// dirty hack because window's filter box is within a bubble of it's own
 				filterParent = filterParent.getParent();
 			}
-			Menu menuFilterHeader = new Menu(filterParent);
-			
-				// show uptime
-			
-			final MenuItem menuItemShowUptime = new MenuItem(menuFilterHeader, SWT.CHECK);
-			Messages.setLanguageText( menuItemShowUptime, "ConfigView.label.showuptime" );
-
-			menuItemShowUptime.addSelectionListener(new SelectionListener() {
-				public void widgetSelected(SelectionEvent e) {
-					COConfigurationManager.setParameter(
-							"MyTorrentsView.showuptime", menuItemShowUptime.getSelection());
-				}
-
-				public void widgetDefaultSelected(SelectionEvent e) {
-				}
-			});
-			
-				// hooks
-			
-			menuFilterHeader.addMenuListener(new MenuListener() {
-				public void menuShown(MenuEvent e) {
-					menuItemShowUptime.setSelection(COConfigurationManager.getBooleanParameter( "MyTorrentsView.showuptime" ));
-				}
-
-				public void menuHidden(MenuEvent e) {
-				}
-			});
 			
-			filterParent.setMenu(menuFilterHeader);
+			Menu menuFilterHeader = getHeaderMenu(txtFilter);
+			filterParent.setMenu( menuFilterHeader );
 			Control[] children = filterParent.getChildren();
 			for (Control control : children) {
 				if (control != txtFilter) {
@@ -373,12 +442,6 @@ public class MyTorrentsView
 				}
 			}
 		}
-
-		//tv.setEnableTabViews(true);
-		//IView views[] = { new GeneralView(), new PeersView(),
-		//	new PeersGraphicView(), new PiecesView(), new FilesView(),
-		//	new LoggerView() };
-    //tv.setCoreTabViews(views);
 	}
 
   // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized()
@@ -398,20 +461,17 @@ public class MyTorrentsView
 			public void runSupport() {
 		    COConfigurationManager.addAndFireParameterListeners(new String[] {
 					"DND Always In Incomplete",
-					"User Mode"
+					"User Mode",
+					"Library.ShowCatButtons", "Library.ShowTagButtons", "Library.ShowTagButtons.CompOnly",
 				}, MyTorrentsView.this);
 
-		    	// can get an activate prior to this running so need to guard against adding the category listener twice
-		    
-		    if (currentCategory != null && !currentCategory.hasCategoryListener( MyTorrentsView.this)) {
-		    	currentCategory.addCategoryListener(MyTorrentsView.this);
-		    }
 		    
-		    if ( currentTag != null ){
-		    	currentTag.removeTagListener(MyTorrentsView.this);	// avoid double addition if already present
-		    	currentTag.addTagListener(MyTorrentsView.this,false);
+		    if ( currentTags != null ){
+		    	for (Tag tag : currentTags) {
+		    		tag.addTagListener(MyTorrentsView.this, false);
+					}
 		    }
-		    CategoryManager.addCategoryManagerListener(MyTorrentsView.this);
+		    TagManagerFactory.getTagManager().getTagType( TagType.TT_DOWNLOAD_MANUAL ).addTagTypeListener(MyTorrentsView.this,false);
 		    globalManager.addListener(MyTorrentsView.this, false);
 		    globalManager.addEventListener( gm_event_listener );
 		    DownloadManager[] dms = globalManager.getDownloadManagers().toArray(new DownloadManager[0]);
@@ -430,6 +490,86 @@ public class MyTorrentsView
     cTablePanel.layout();
   }
 
+  private Menu
+  getHeaderMenu(
+		Control		control )
+  {
+	  if ( tableHeaderMenu != null ){
+		  
+		  return( tableHeaderMenu );
+	  }
+	  
+	  tableHeaderMenu = new Menu(control.getShell(), SWT.POP_UP );
+		
+	  // show uptime
+	  
+	  final MenuItem menuItemShowUptime = new MenuItem(tableHeaderMenu, SWT.CHECK);
+	  Messages.setLanguageText( menuItemShowUptime, "ConfigView.label.showuptime" );
+
+	  menuItemShowUptime.addSelectionListener(new SelectionAdapter() {
+		  public void widgetSelected(SelectionEvent e) {
+			  COConfigurationManager.setParameter(
+					  "MyTorrentsView.showuptime", menuItemShowUptime.getSelection());
+		  }
+	  });
+
+	  // selected download rates
+	  
+	  final MenuItem menuItemShowRates = new MenuItem(tableHeaderMenu, SWT.CHECK);
+	  Messages.setLanguageText( menuItemShowRates, "label.show.selected.rates" );
+
+	  menuItemShowRates.addSelectionListener(new SelectionAdapter() {
+		  public void widgetSelected(SelectionEvent e) {
+			  COConfigurationManager.setParameter(
+					  "MyTorrentsView.showrates", menuItemShowRates.getSelection());
+		  }
+	  });
+	  // show category buttons
+
+	  final MenuItem menuItemShowCatBut = new MenuItem(tableHeaderMenu, SWT.CHECK);
+	  Messages.setLanguageText( menuItemShowCatBut, "ConfigView.label.show.cat.but" );
+
+	  menuItemShowCatBut.addSelectionListener(new SelectionAdapter() {
+		  public void widgetSelected(SelectionEvent e) {
+			  COConfigurationManager.setParameter(
+					  "Library.ShowCatButtons", menuItemShowCatBut.getSelection());
+		  }
+	  });
+
+
+	  // show tag buttons
+
+	  final MenuItem menuItemShowTagBut = new MenuItem(tableHeaderMenu, SWT.CHECK);
+	  Messages.setLanguageText( menuItemShowTagBut, "ConfigView.label.show.tag.but" );
+
+	  menuItemShowTagBut.addSelectionListener(new SelectionAdapter() {
+		  public void widgetSelected(SelectionEvent e) {
+			  COConfigurationManager.setParameter(
+					  "Library.ShowTagButtons", menuItemShowTagBut.getSelection());
+		  }
+	  });
+
+
+	  // hooks
+
+	  tableHeaderMenu.addMenuListener(new MenuListener() {
+		  public void menuShown(MenuEvent e) {
+			  menuItemShowUptime.setSelection(COConfigurationManager.getBooleanParameter( "MyTorrentsView.showuptime" ));
+			  menuItemShowRates.setSelection(COConfigurationManager.getBooleanParameter( "MyTorrentsView.showrates" ));
+			  menuItemShowCatBut.setSelection(COConfigurationManager.getBooleanParameter( "Library.ShowCatButtons" ));
+			  menuItemShowTagBut.setSelection(COConfigurationManager.getBooleanParameter( "Library.ShowTagButtons" ));
+
+			  menuItemShowCatBut.setEnabled( !neverShowCatOrTagButtons );
+			  menuItemShowTagBut.setEnabled( !neverShowCatOrTagButtons );
+		  }
+
+		  public void menuHidden(MenuEvent e) {
+		  }
+	  });
+
+	  return( tableHeaderMenu );
+  }
+  
   // @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewDestroyed()
   public void tableViewDestroyed() {
     tv.removeKeyListener(this);
@@ -440,11 +580,14 @@ public class MyTorrentsView
 					Utils.disposeSWTObjects(new Object[] {
 						dragSource,
 						dropTarget,
-						fontButton
+						fontButton,
+						tableHeaderMenu
 					});
-					dragSource = null;
-					dropTarget = null;
-					fontButton = null;
+					dragSource 		= null;
+					dropTarget 		= null;
+					fontButton		= null;
+					tableHeaderMenu = null;
+					
 				} catch (Exception e) {
 					Debug.out(e);
 				}
@@ -455,17 +598,20 @@ public class MyTorrentsView
 			DownloadManager dm = (DownloadManager) dms[i];
 			dm.removeListener(this);
 		}
-    if (currentCategory != null) {
-    	currentCategory.removeCategoryListener(this);
-    }
-    CategoryManager.removeCategoryManagerListener(this);
-    if ( currentTag != null ){
-    	currentTag.removeTagListener(this);
-    }
+
+		if (currentTags != null) {
+			for (Tag tag : currentTags) {
+				tag.removeTagListener(this);
+			}
+		}
+    TagManagerFactory.getTagManager().getTagType( TagType.TT_DOWNLOAD_MANUAL ).removeTagTypeListener(MyTorrentsView.this);
+
     globalManager.removeListener(this);
     globalManager.removeEventListener( gm_event_listener );
     COConfigurationManager.removeParameterListener("DND Always In Incomplete", this);
-    COConfigurationManager.removeParameterListener("User Mode", this);
+    COConfigurationManager.removeParameterListener("Library.ShowCatButtons", this);
+    COConfigurationManager.removeParameterListener("Library.ShowTagButtons", this);
+    COConfigurationManager.removeParameterListener("Library.ShowTagButtons.CompOnly", this);
   }
   
   
@@ -525,56 +671,130 @@ public class MyTorrentsView
   }
   
   private void swt_createTabs() {
-    Category[] categories = CategoryManager.getCategories();
-    Arrays.sort(categories);
-    boolean showCat = false;
-    if (!neverShowCatButtons) {
-      for(int i = 0; i < categories.length; i++) {
-          if(categories[i].getType() == Category.TYPE_USER) {
-              showCat = true;
-              break;
-          }
-      }
+	
+    boolean catButtonsDisabled = neverShowCatOrTagButtons;
+    if ( !catButtonsDisabled){
+    	catButtonsDisabled = !COConfigurationManager.getBooleanParameter( "Library.ShowCatButtons" );
+    }
+    
+    List<Tag> tags_to_show = new ArrayList<Tag>();
+
+    boolean tagButtonsDisabled = neverShowCatOrTagButtons;
+    if ( !tagButtonsDisabled){
+    	tagButtonsDisabled = !COConfigurationManager.getBooleanParameter( "Library.ShowTagButtons" );
+    	
+    	if ( !tagButtonsDisabled ){
+    		if ( !isCompletedOnly ){
+    			tagButtonsDisabled = COConfigurationManager.getBooleanParameter( "Library.ShowTagButtons.CompOnly" );
+    		}
+    	}
     }
+    
+    if ( !tagButtonsDisabled ){
+			ArrayList<Tag> tagsManual = new ArrayList<Tag>(
+					TagManagerFactory.getTagManager().getTagType(
+							TagType.TT_DOWNLOAD_MANUAL).getTags());
+			for (Tag tag : tagsManual) {
+				if (tag.isVisible()) {
+					tags_to_show.add(tag);
+				}
+			}
+    }
+    
+    if (!catButtonsDisabled) {
+			ArrayList<Tag> tagsCat = new ArrayList<Tag>(
+					TagManagerFactory.getTagManager().getTagType(
+							TagType.TT_DOWNLOAD_CATEGORY).getTags());
+			for (Tag tag : tagsCat) {
+				if (tag.isVisible()) {
+					tags_to_show.add(tag);
+				}
+			}
 
+    }
+    
+    tags_to_show = TagUIUtils.sortTags( tags_to_show );
+    
    	buildHeaderArea();
-  	if (cCategories != null && !cCategories.isDisposed()) {
-      Control[] controls = cCategories.getChildren();
-      for (int i = 0; i < controls.length; i++) {
-        controls[i].dispose();
-      }
+  	if (cCategoriesAndTags != null && !cCategoriesAndTags.isDisposed()) {
+  		Utils.disposeComposite(cCategoriesAndTags, false);
   	}
-    
-    if (showCat) {
-    	buildCat(categories);
+      	
+    if (tags_to_show.size() > 0 ) {
+    	buildCatAndTag(tags_to_show);
     } else if (cTableParentPanel != null && !cTableParentPanel.isDisposed()) {
   		cTableParentPanel.layout();
   	}
   }
   
 	private void buildHeaderArea() {
-		if (cCategories == null) {
-			cCategories = new CompositeMinSize(cTableParentPanel, SWT.NONE);
-			((CompositeMinSize) cCategories).setMinSize(new Point(SWT.DEFAULT, 24));
-			GridData gridData = new GridData(SWT.RIGHT, SWT.TOP, true, false);
-			cCategories.setLayoutData(gridData);
-			cCategories.moveAbove(null);
-		}else if ( cCategories.isDisposed()){
+		if (cCategoriesAndTags == null) {
+			cCategoriesAndTags = new CompositeMinSize(cTableParentPanel, SWT.NONE);
+			((CompositeMinSize) cCategoriesAndTags).setMinSize(new Point(SWT.DEFAULT, 24));
+			GridData gridData = new GridData(SWT.RIGHT, SWT.CENTER, true, false);
+			cCategoriesAndTags.setLayoutData(gridData);
+			cCategoriesAndTags.moveAbove(null);
+			
+			if ( filterParent != null ){
+					// inherit the background of the search filter - best that can be done to make things look ok
+				Color background = filterParent.getBackground();
+				if ( background != null ){
+					cCategoriesAndTags.setBackground( background );
+					cTableParentPanel.setBackground( background );
+				}
+			}
+			
+			cCategoriesAndTags.setBackgroundMode(SWT.INHERIT_FORCE);
+		}else if ( cCategoriesAndTags.isDisposed()){
 			return;
 		}
 		
-		if (!(cCategories.getLayout() instanceof RowLayout)) {
-      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);
+		RowLayout rowLayout;
+		
+		if (cCategoriesAndTags.getLayout() instanceof RowLayout){
+		  rowLayout = (RowLayout)cCategoriesAndTags.getLayout();
+		}else{
+	      rowLayout = new RowLayout();
+	      cCategoriesAndTags.setLayout(rowLayout);
 		}
-
-    tv.enableFilterCheck(txtFilter, this);
+	    rowLayout.marginTop = 0;
+	    rowLayout.marginBottom = 0;
+	    rowLayout.marginLeft = 3;
+	    rowLayout.marginRight = 3;
+	    rowLayout.spacing = 0;
+	    rowLayout.wrap = true;
+	     
+		
+	    Menu menu = getHeaderMenu(cTableParentPanel);
+	    cTableParentPanel.setMenu( menu );
+	    
+	    if ( Constants.isOSX ){
+	    	
+	    		/* bug on OSX whereby the table is allowing menu-detect events to fire both on the table itself and the composite it
+	    		 * sits on - this results in the header-area menu appearing after a menu appears for the table itself
+	    		 * Doesn't happen on 10.6.8 but observed to happen on 10.9.4
+	    		 */
+	    	
+		    cTableParentPanel.addListener( 
+					SWT.MenuDetect,
+					new Listener() {
+						
+						public void 
+						handleEvent(
+							Event event ) 
+						{
+							Display display = cTableParentPanel.getDisplay();
+							
+							Point pp_rel = display.map( null, cTableParentPanel, event.x, event.y );
+														
+							Control hit = Utils.findChild(cTableParentPanel, pp_rel.x, pp_rel.y );
+							
+							event.doit = hit == cTableParentPanel;
+						}
+					});
+	    }
+	    
+	    tv.enableFilterCheck(txtFilter, this);
 	}
 
   /**
@@ -583,75 +803,80 @@ public class MyTorrentsView
 	 * @param categories 
    * @since 3.1.1.1
 	 */
-	private void buildCat(Category[] categories) {
+	private void buildCatAndTag(List<Tag> tags) {
+		
+		if (tags.size() == 0) {
+			return;
+		}
+		
 		int iFontPixelsHeight = 10;
-		int iFontPointHeight = (iFontPixelsHeight * 72)
-				/ cCategories.getDisplay().getDPI().y;
-		for (int i = 0; i < categories.length; i++) {
-			final Category category = categories[i];
-
-			final Button catButton = new Button(cCategories, SWT.TOGGLE);
-			catButton.addKeyListener(this);
-			if (i == 0 && fontButton == null) {
-				Font f = catButton.getFont();
-				FontData fd = f.getFontData()[0];
-				fd.setHeight(iFontPointHeight);
-				fontButton = new Font(cCategories.getDisplay(), fd);
-			}
-			catButton.setText("|");
-			catButton.setFont(fontButton);
-			catButton.pack(true);
-			if (catButton.computeSize(100, SWT.DEFAULT).y > 0) {
-				RowData rd = new RowData();
-				rd.height = catButton.computeSize(100, SWT.DEFAULT).y - 2
-						+ catButton.getBorderWidth() * 2;
-				catButton.setLayoutData(rd);
-			}
-
-			final String name = category.getName();
-			if (category.getType() == Category.TYPE_USER)
-				catButton.setText(name);
-			else
-				Messages.setLanguageText(catButton, name);
-
-			catButton.setData("Category", category);
-			if (category == currentCategory) {
-				catButton.setSelection(true);
-			}
+		int iFontPointHeight = (iFontPixelsHeight * 72)	/ cCategoriesAndTags.getDisplay().getDPI().y;
 
-			catButton.addSelectionListener(new SelectionAdapter() {
+		Label spacer = null;
+		
+		int	max_rd_height = 0;
+		
+		allTags = tags;
+		
+		if (buttonSelectionListener == null) {
+			buttonSelectionListener = new SelectionAdapter() {
 				public void widgetSelected(SelectionEvent e) {
+					boolean add = (e.stateMask == SWT.MOD1);
+
 					Button curButton = (Button) e.widget;
 					boolean isEnabled = curButton.getSelection();
-					Control[] controls = cCategories.getChildren();
+
+					Tag tag = (Tag) curButton.getData("Tag");
+
 					if (!isEnabled) {
-						for (int i = 0; i < controls.length; i++) {
-							if (controls[i] instanceof Button) {
-								curButton = (Button) controls[i];
-								break;
+						removeTagFromCurrent(tag);
+					} else {
+						if (add) {
+							Category catAll = CategoryManager.getCategory(Category.TYPE_ALL);
+							
+							if (tag.equals(catAll)) {
+								setCurrentTags(new Tag[] { catAll });
+							} else {
+  							Tag[] newTags = new Tag[currentTags.length + 1];
+  							System.arraycopy(currentTags, 0, newTags, 0, currentTags.length);
+  							newTags[currentTags.length] = tag;
+  							
+  							newTags = (Tag[]) removeFromArray(newTags, catAll);
+  							setCurrentTags(newTags);
 							}
+						} else {
+							setCurrentTags(new Tag[] {
+								(Tag) curButton.getData("Tag")
+							});
 						}
 					}
 
+					Control[] controls = curButton.getParent().getChildren();
 					for (int i = 0; i < controls.length; i++) {
 						if (!(controls[i] instanceof Button)) {
 							continue;
 						}
 						Button b = (Button) controls[i];
-						if (b != curButton && b.getSelection())
-							b.setSelection(false);
-						else if (b == curButton && !b.getSelection())
-							b.setSelection(true);
+						Tag btag = (Tag) b.getData("Tag");
+						b.setSelection(isCurrent(btag));
 					}
-					activateCategory((Category) curButton.getData("Category"));
 				}
-			});
+			};
 
-			catButton.addListener(SWT.MouseHover, new Listener() {
+			buttonHoverListener = new Listener() {
 				public void handleEvent(Event event) {
 					Button curButton = (Button) event.widget;
-					Category curCategory = (Category) curButton.getData("Category");
-					List<DownloadManager> dms = curCategory.getDownloadManagers(globalManager.getDownloadManagers());
+					Tag tag = (Tag) curButton.getData("Tag");
+
+					if (!(tag instanceof Category)) {
+						curButton.setToolTipText(TagUIUtils.getTagTooltip(tag, true));
+						return;
+					}
+
+					Category category = (Category) tag;
+
+					List<DownloadManager> dms = category.getDownloadManagers(
+							globalManager.getDownloadManagers());
 
 					long ttlActive = 0;
 					long ttlSize = 0;
@@ -660,17 +885,19 @@ public class MyTorrentsView
 					int count = 0;
 					for (DownloadManager dm : dms) {
 
-						if (!isInCategory(dm, currentCategory))
+						if (!category.hasTaggable(dm)) {
 							continue;
+						}
 
 						count++;
 						if (dm.getState() == DownloadManager.STATE_DOWNLOADING
-								|| dm.getState() == DownloadManager.STATE_SEEDING){
+								|| dm.getState() == DownloadManager.STATE_SEEDING) {
 							ttlActive++;
 						}
-						ttlSize += dm.getSize();
-						ttlRSpeed += dm.getStats().getDataReceiveRate();
-						ttlSSpeed += dm.getStats().getDataSendRate();
+						DownloadManagerStats stats = dm.getStats();
+						ttlSize += stats.getSizeExcludingDND();
+						ttlRSpeed += stats.getDataReceiveRate();
+						ttlSSpeed += stats.getDataSendRate();
 					}
 
 					String up_details = "";
@@ -678,66 +905,73 @@ public class MyTorrentsView
 
 					if (category.getType() != Category.TYPE_ALL) {
 
-						String up_str = MessageText.getString("GeneralView.label.maxuploadspeed");
-						String down_str = MessageText.getString("GeneralView.label.maxdownloadspeed");
-						String unlimited_str = MessageText.getString("MyTorrentsView.menu.setSpeed.unlimited");
+						String up_str = MessageText.getString(
+								"GeneralView.label.maxuploadspeed");
+						String down_str = MessageText.getString(
+								"GeneralView.label.maxdownloadspeed");
+						String unlimited_str = MessageText.getString(
+								"MyTorrentsView.menu.setSpeed.unlimited");
 
 						int up_speed = category.getUploadSpeed();
 						int down_speed = category.getDownloadSpeed();
 
-						up_details = up_str
-								+ ": "
-								+ (up_speed == 0 ? unlimited_str
-										: DisplayFormatters.formatByteCountToKiBEtc(up_speed));
-						down_details = down_str
-								+ ": "
-								+ (down_speed == 0 ? unlimited_str
-										: DisplayFormatters.formatByteCountToKiBEtc(down_speed));
+						up_details = up_str + ": " + (up_speed == 0 ? unlimited_str
+								: DisplayFormatters.formatByteCountToKiBEtc(up_speed));
+						down_details = down_str + ": " + (down_speed == 0 ? unlimited_str
+								: DisplayFormatters.formatByteCountToKiBEtc(down_speed));
 					}
 
 					if (count == 0) {
-						curButton.setToolTipText(down_details + "\n" + up_details
-								+ "\nTotal: 0");
+						curButton.setToolTipText(
+								down_details + "\n" + up_details + "\nTotal: 0");
 						return;
 					}
 
 					curButton.setToolTipText((up_details.length() == 0 ? ""
-							: (down_details + "\n" + up_details + "\n"))
-							+ "Total: "
-							+ count
-							+ "\n"
-							+ "Downloading/Seeding: "
-							+ ttlActive
-							+ "\n"
-							+ "\n"
+							: (down_details + "\n" + up_details + "\n")) + "Total: " + count
+							+ "\n" + "Downloading/Seeding: " + ttlActive + "\n" + "\n"
 							+ "Total Speed: "
 							+ DisplayFormatters.formatByteCountToKiBEtcPerSec(ttlRSpeed)
 							+ " / "
 							+ DisplayFormatters.formatByteCountToKiBEtcPerSec(ttlSSpeed)
-							+ "\n"
-							+ "Average Speed: "
-							+ DisplayFormatters.formatByteCountToKiBEtcPerSec(ttlRSpeed
-									/ (ttlActive==0?1:ttlActive))
+							+ "\n" + "Average Speed: "
+							+ DisplayFormatters.formatByteCountToKiBEtcPerSec(
+									ttlRSpeed / (ttlActive == 0 ? 1 : ttlActive))
 							+ " / "
-							+ DisplayFormatters.formatByteCountToKiBEtcPerSec(ttlSSpeed
-									/ (ttlActive==0?1:ttlActive))
-							+ "\n"
-							+ "Size: "
+							+ DisplayFormatters.formatByteCountToKiBEtcPerSec(
+									ttlSSpeed / (ttlActive == 0 ? 1 : ttlActive))
+							+ "\n" + "Size: "
 							+ DisplayFormatters.formatByteCountToKiBEtc(ttlSize));
-				}
-			});
 
-			final DropTarget tabDropTarget = new DropTarget(catButton,
-					DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK);
-			Transfer[] types = new Transfer[] {
-				TextTransfer.getInstance()
+				}
 			};
-			tabDropTarget.setTransfer(types);
-			tabDropTarget.addDropListener(new DropTargetAdapter() {
+
+			buttonDropTargetListener = new DropTargetAdapter() {
 				public void dragOver(DropTargetEvent e) {
-					//System.out.println("dragging over: " + drag_drop_line_start);
+
 					if (drag_drop_line_start >= 0) {
-						e.detail = DND.DROP_MOVE;
+						boolean doAdd = false;
+
+						Control curButton = ((DropTarget) e.widget).getControl();
+						Tag tag = (Tag) curButton.getData("Tag");
+						Object[] ds = tv.getSelectedDataSources().toArray();
+						if (tag != null) {
+  						for (Object obj : ds) {
+  
+  							if (obj instanceof DownloadManager) {
+  
+  								DownloadManager dm = (DownloadManager) obj;
+  
+  								if (!tag.hasTaggable(dm)) {
+  									doAdd = true;
+  									break;
+  								}
+  							}
+  						}
+						}
+
+						e.detail = doAdd ? DND.DROP_COPY : DND.DROP_MOVE;
+
 					} else {
 						e.detail = DND.DROP_NONE;
 					}
@@ -745,18 +979,111 @@ public class MyTorrentsView
 
 				public void drop(DropTargetEvent e) {
 					e.detail = DND.DROP_NONE;
-					//System.out.println("DragDrop on Button:" + drag_drop_line_start);
+
 					if (drag_drop_line_start >= 0) {
 						drag_drop_line_start = -1;
 						drag_drop_rows = null;
 
-						TorrentUtil.assignToCategory(tv.getSelectedDataSources().toArray(),
-								(Category) catButton.getData("Category"));
+						Object[] ds = tv.getSelectedDataSources().toArray();
+
+						Control curButton = ((DropTarget) e.widget).getControl();
+
+						Tag tag = (Tag) curButton.getData("Tag");
+
+						if (tag instanceof Category) {
+							TorrentUtil.assignToCategory(ds, (Category) tag);
+							return;
+						}
+
+						boolean doAdd = false;
+						for (Object obj : ds) {
+
+							if (obj instanceof DownloadManager) {
+
+								DownloadManager dm = (DownloadManager) obj;
+
+								if (!tag.hasTaggable(dm)) {
+									doAdd = true;
+									break;
+								}
+							}
+						}
+
+						for (Object obj : ds) {
+
+							if (obj instanceof DownloadManager) {
+
+								DownloadManager dm = (DownloadManager) obj;
+								
+								if (doAdd) {
+									tag.addTaggable(dm);
+								} else {
+									tag.removeTaggable(dm);
+								}
+							}
+						}
 					}
 				}
-			});
+			};
+		}
+
+		for ( final Tag tag: tags ){
+			boolean isCat = (tag instanceof Category);
+			
+			final Button button = new Button(cCategoriesAndTags, SWT.TOGGLE);
+			
+			if (isCat) {
+  			if (spacer == null) {
+  				spacer = new Label(cCategoriesAndTags, SWT.NONE);
+  				RowData rd = new RowData();
+  				rd.width = 8;
+  				spacer.setLayoutData(rd);
+  				spacer.moveAbove(null);
+  			}
+  			button.moveAbove(spacer);
+			}
+
+			button.addKeyListener(this);
+			if ( fontButton == null) {
+				Font f = button.getFont();
+				FontData fd = f.getFontData()[0];
+				fd.setHeight(iFontPointHeight);
+				fontButton = new Font(cCategoriesAndTags.getDisplay(), fd);
+			}
+			button.setText("|");
+			button.setFont(fontButton);
+			button.pack(true);
+			if (button.computeSize(100, SWT.DEFAULT).y > 0) {
+				RowData rd = new RowData();
+				int rd_height = button.computeSize(100, SWT.DEFAULT).y - 2 + button.getBorderWidth() * 2;
+				rd.height = rd_height;
+				max_rd_height = Math.max( max_rd_height, rd_height );
+				button.setLayoutData(rd);
+			}
+
+			String tag_name = tag.getTagName( true );
+			
+			button.setText(tag_name);
+			
+			button.setData("Tag", tag);
+			if (isCurrent(tag)) {
+				button.setSelection(true);
+			}
+
+			button.addSelectionListener(buttonSelectionListener);
+
+
+			button.addListener(SWT.MouseHover, buttonHoverListener);
+
+			final DropTarget tabDropTarget = new DropTarget(button,
+					DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK);
+			Transfer[] types = new Transfer[] {
+				TextTransfer.getInstance()
+			};
+			tabDropTarget.setTransfer(types);
+			tabDropTarget.addDropListener(buttonDropTargetListener);
 
-			catButton.addDisposeListener(new DisposeListener() {
+			button.addDisposeListener(new DisposeListener() {
 				public void widgetDisposed(DisposeEvent e) {
 					if (!tabDropTarget.isDisposed()) {
 						tabDropTarget.dispose();
@@ -764,37 +1091,53 @@ public class MyTorrentsView
 				}
 			});
 
-			final Menu menu = new Menu(catButton.getShell(), SWT.POP_UP);
+			Menu menu = new Menu( button );
+			
+			button.setMenu( menu );
 
-			catButton.setMenu(menu);
+			if (isCat) {
+				CategoryUIUtils.setupCategoryMenu(menu, (Category) tag);
+			} else {
+				TagUIUtils.createSideBarMenuItems(menu, tag);
+			}
+		}
 
-			CategoryUIUtils.setupCategoryMenu(menu, category);
+		if ( max_rd_height > 0 ){
+			RowLayout layout = (RowLayout)cCategoriesAndTags.getLayout();
+			int top_margin = ( 24 - max_rd_height + 1 )/2;
+			if (top_margin > 0 ){
+				layout.marginTop = top_margin;
+			}
 		}
 		
-		cCategories.getParent().layout(true, true);
+		cCategoriesAndTags.getParent().layout(true, true);
 	}
 	
 	public boolean isOurDownloadManager(DownloadManager dm) {
-		if (!isInCategory(dm, currentCategory)) {
+		if (!isInTags(dm, currentTags)) {
 			return false;
 		}
 
-		if ( !isInTag( dm, currentTag )){
-			return( false );
+		if (Download.class.equals(forDataSourceType)) {
+			return true;
 		}
-		boolean bCompleted =  dm.isDownloadComplete(bDNDalwaysIncomplete);
-		boolean bOurs = (bCompleted && isSeedingView)
-				|| (!bCompleted && !isSeedingView);
-		
-//		System.out.println("ourDM? " + sTableID + "; " + dm.getDisplayName()
-//				+ "; Complete=" + bCompleted + ";Ours=" + bOurs + ";bc"
-//				+ dm.getStats().getDownloadCompleted(false) + ";"
-//				+ dm.getStats().getDownloadCompleted(true));
+
+		boolean bCompleted = dm.isDownloadComplete(bDNDalwaysIncomplete);
+		boolean bOurs = (bCompleted && isCompletedOnly)
+				|| (!bCompleted && !isCompletedOnly);
+
+		//System.out.println("ourDM? " + tv.getTableID() + "; " + dm.getDisplayName()
+		//		+ "; Complete=" + bCompleted + ";Ours=" + bOurs + ";bc"
+		//		+ dm.getStats().getDownloadCompleted(false) + ";"
+		//		+ dm.getStats().getDownloadCompleted(true));
 
 		return bOurs;
 	}
 
 	public boolean filterCheck(DownloadManager dm, String sLastSearch, boolean bRegexSearch) {
+		if ( dm == null ){
+			return( false );
+		}
 		boolean bOurs;
 		if (sLastSearch.length() > 0) {
 			try {
@@ -986,7 +1329,7 @@ public class MyTorrentsView
 							}
 						}
 						
-						((ViewUtils.ViewTitleExtraInfo)x).setEnabled( tv.getComposite(), isSeedingView, enabled );
+						((ViewUtils.ViewTitleExtraInfo)x).setEnabled( tv.getComposite(), enabled );
 					}
 				}
 			}
@@ -1027,7 +1370,7 @@ public class MyTorrentsView
 					}
 				}
 				
-				((ViewUtils.ViewTitleExtraInfo)x).update( tv.getComposite(), isSeedingView, rows.length, active );
+				((ViewUtils.ViewTitleExtraInfo)x).update( tv.getComposite(), rows.length, active );
 			}
 		}
 	}
@@ -1147,7 +1490,9 @@ public class MyTorrentsView
 				continue;
 			}
 			if (uiFunctions != null) {
-				uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, dm_sources[i]);
+				uiFunctions.getMDI().showEntryByID(
+						MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS,
+						dm_sources[i]);
 			}
 		}  	
   }
@@ -1248,6 +1593,7 @@ public class MyTorrentsView
 		boolean hasSelection = (dms.length > 0);
 
 		if (hasSelection) {
+			boolean isSeedingView = Download.class.equals(forDataSourceType) || DownloadTypeComplete.class.equals(forDataSourceType);
 			TorrentUtil.fillTorrentMenu(menu, dms, azureus_core, cTablePanel, true,
 					(isSeedingView) ? 2 : 1, tv);
 
@@ -1480,6 +1826,7 @@ public class MyTorrentsView
 
 	// @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
 	public void keyPressed(KeyEvent e) {
+		viewActive = true;
 		int key = e.character;
 		if (key <= 26 && key > 0)
 			key += 'a' - 1;
@@ -1666,9 +2013,10 @@ public class MyTorrentsView
 			});
 		}
 
-		int count = globalManager.downloadManagerCount(isSeedingView); 
 		for (int i = 0; i < dms.length; i++) {
 			DownloadManager dm = dms[i];
+			boolean complete = dm.isDownloadComplete(false);
+			int count = globalManager.downloadManagerCount(complete); 
 			int pos = dm.getPosition() + by;
 			if (pos < i + 1)
 				pos = i + 1;
@@ -1718,13 +2066,20 @@ public class MyTorrentsView
    * @see org.gudy.azureus2.core3.config.ParameterListener#parameterChanged(java.lang.String)
    */
   public void parameterChanged(String parameterName) {
-		if (parameterName == null
-				|| parameterName.equals("DND Always In Incomplete")) {
+		if (parameterName == null || parameterName.equals("DND Always In Incomplete")) {
 			bDNDalwaysIncomplete = COConfigurationManager.getBooleanParameter("DND Always In Incomplete");
 		}
+		
+		if (parameterName != null && 
+				( 	parameterName.equals("Library.ShowCatButtons") || 
+					parameterName.equals("Library.ShowTagButtons" ) ||
+					parameterName.equals("Library.ShowTagButtons.CompOnly" ))){
+			
+			createTabs();
+		}
 	}
 
-	private UISWTViewCore getActiveView() {
+	private MdiEntrySWT getActiveView() {
 		TableViewSWT_TabsCommon tabsCommon = tv.getTabsCommon();
 		if (tabsCommon != null) {
 			return tabsCommon.getActiveSubView();
@@ -1732,38 +2087,31 @@ public class MyTorrentsView
 		return null;
 	}
 
-  public void refreshToolBarItems(Map<String, Long> list) {
-	super.refreshToolBarItems(list);
-  		ISelectedContent[] datasource = SelectedContentManager.getCurrentlySelectedContent();
-		boolean hasMultiple = datasource.length > 1;
-		
-		// Most subviews can only handle one datasource.  I'm lazy, so instead of 
-		// fixing each view up, disable toolbar handling for them when we have
-		// multiple selection
-		if (!hasMultiple) {
+	public void refreshToolBarItems(Map<String, Long> list) {
+		ISelectedContent[] datasource = SelectedContentManager.getCurrentlySelectedContent();
+
+		if (!isTableFocus()) {
   		UISWTViewCore active_view = getActiveView();
   		if (active_view != null) {
   			UIPluginViewToolBarListener l = active_view.getToolBarListener();
   			if (l != null) {
-  				l.refreshToolBarItems(list);
-  				// don't return here, we want to merge in any potential operations
-  				// from the selected content calculation below
+  				Map<String, Long> activeViewList = new HashMap<String, Long>();
+  				l.refreshToolBarItems(activeViewList);
+  				if (activeViewList.size() > 0) {
+  					list.putAll(activeViewList);
+  					return;
+  				}
   			}
   		}
 		}
-  	
-		Map<String, Long> states = TorrentUtil.calculateToolbarStates(datasource, tv.getTableID());
-		list.putAll(states);
   }  
 
   public boolean toolBarItemActivated(ToolBarItem item, long activationType, Object datasource) {
-	  
-		boolean hasMultiple = datasource instanceof Object[] && ((Object[])datasource).length > 1;
-		
-		// Most subviews can only handle one datasource.  I'm lazy, so instead of 
-		// fixing each view up, disable toolbar handling for them when we have
-		// multiple selection
-		if (!hasMultiple) {
+	  boolean isTableSelected = false;
+	  if (tv instanceof TableViewImpl) {
+	  	isTableSelected = ((TableViewImpl) tv).isTableSelected();
+	  }
+	  if (!isTableSelected) {
   		UISWTViewCore active_view = getActiveView();
   		if (active_view != null) {
   			UIPluginViewToolBarListener l = active_view.getToolBarListener();
@@ -1771,7 +2119,8 @@ public class MyTorrentsView
   				return true;
   			}
   		}
-		}
+  		return false;
+	  }
 
 		String itemKey = item.getID();
   	if (activationType == UIToolBarActivationListener.ACTIVATIONTYPE_HELD) {
@@ -1825,7 +2174,7 @@ public class MyTorrentsView
       TorrentUtil.removeDataSources(tv.getSelectedDataSources().toArray());
       return true;
     }
-    return super.toolBarItemActivated(item, activationType, datasource);
+    return false;
   }
   
 
@@ -1875,39 +2224,12 @@ public class MyTorrentsView
 	}
 
   // DownloadManagerListener
-	public void completionChanged(final DownloadManager manager,
-			boolean bCompleted) {
+	public void completionChanged(DownloadManager manager, boolean bCompleted) {
 		// manager has moved lists
 
 		if (isOurDownloadManager(manager)) {
-
-			// only make the download visible if it satisfies the category selection
-
-			if (currentCategory == null
-					|| currentCategory.getType() == Category.TYPE_ALL) {
-
-				tv.addDataSource(manager);
-
-			} else {
-
-				int catType = currentCategory.getType();
-
-				Category manager_category = manager.getDownloadState().getCategory();
-
-				if (manager_category == null) {
-
-					if (catType == Category.TYPE_UNCATEGORIZED) {
-
-						tv.addDataSource(manager);
-					}
-				} else {
-
-					if (currentCategory.getName().equals(manager_category.getName()))
-
-						tv.addDataSource(manager);
-				}
-			}
-		} else if ((isSeedingView && !bCompleted) || (!isSeedingView && bCompleted)) {
+			tv.addDataSource(manager);
+		} else {
 
 			tv.removeDataSource(manager);
 		}
@@ -1918,111 +2240,169 @@ public class MyTorrentsView
   }
 
 
-  /**
-   * Rebuild the table based on the category activated
-   * 
-   * @param category
-   */
-  private void activateCategory(Category category) {
-		if (category != currentCategory) {
-			if (currentCategory != null)
-				currentCategory.removeCategoryListener(this);
-			if (category != null)
-				category.addCategoryListener(this);
-
-			currentCategory = category;
-		}
-		
-		tv.processDataSourceQueue();
-		Object[] managers = globalManager.getDownloadManagers().toArray();
-		List<DownloadManager> listRemoves = new ArrayList<DownloadManager>();
-		List<DownloadManager> listAdds = new ArrayList<DownloadManager>();
+	public void
+	tagTypeChanged(
+		TagType		tag_type )
+	{	
+	}
+	
+	public void
+	tagAdded(
+		Tag			tag )
+	{
+		createTabs();
+	}
+	
+	private Set<Tag> pending_tag_changes = new HashSet<Tag>();
+	
+	public void
+	tagChanged(
+		Tag			tag )
+	{	
+			// we can get a lot of hits here, limit tab rebuilds somewhat
 		
-		for (int i = 0; i < managers.length; i++) {
-			DownloadManager dm = (DownloadManager) managers[i];
+		synchronized( pending_tag_changes ){
+			
+			pending_tag_changes.add( tag );
+		}
 		
-			boolean bHave = tv.isUnfilteredDataSourceAdded(dm);
-			if (!isOurDownloadManager(dm)) {
-				if (bHave) {
-					listRemoves.add(dm);
-				}
-			} else {
-				if (!bHave) {
-					listAdds.add(dm);
+		Utils.execSWTThread(new AERunnable() {
+			@Override
+			public void runSupport() {
+			
+				if ( allTags != null ){
+						
+					boolean create_tabs = false;
+					
+					synchronized( pending_tag_changes ){
+						
+						for ( Tag t: pending_tag_changes ){
+							
+							boolean should_be_visible	= t.isVisible();
+							boolean is_visible			= allTags.contains( t );
+							
+							if ( should_be_visible != is_visible ){
+								
+								create_tabs = true;
+								
+								break;
+							}
+						}
+						
+						pending_tag_changes.clear();
+					}
+					
+					if ( create_tabs ){
+						
+						createTabs();
+					}
 				}
 			}
-		}
-		tv.removeDataSources(listRemoves.toArray(new DownloadManager[0]));
-		tv.addDataSources(listAdds.toArray(new DownloadManager[0]));
-		
-  	tv.processDataSourceQueue();
-		//tv.refreshTable(false);
+		});
 	}
-  
-  public boolean isInCurrentCategory(DownloadManager manager) {
-  	return isInCategory(manager, currentCategory);
-  }
-
-  private boolean isInCategory(DownloadManager manager, Category category) {
-  	if (category == null) {
-  		return true;
-  	}
-		int type = category.getType();
-		if (type == Category.TYPE_ALL) {
-			return true;
+	
+	public void
+	tagRemoved(
+		Tag			tag )
+	{
+		if (currentTags == null) {
+			return;
 		}
 
-  	Category dmCategory = manager.getDownloadState().getCategory();
-  	if (dmCategory == null) {
-  		return type == Category.TYPE_UNCATEGORIZED;
-  	}
-  	
-  	return category.equals(dmCategory);
-  }
-
-
-  // CategoryManagerListener Functions
-	public void categoryAdded(Category category) {
+		removeTagFromCurrent(tag);
 		createTabs();
 	}
+	
+  
+	private void removeTagFromCurrent(Tag tag) {
+		boolean found = false;
+		for (int i = 0; i < currentTags.length; i++) {
+			Tag curTag = currentTags[i];
+			if (curTag.equals(tag)) {
+				Tag[] tags;
+				if (currentTags.length == 1) {
+					tags = new Tag[] {
+						CategoryManager.getCategory(Category.TYPE_ALL)
+					};
+				} else {
+  				tags = new Tag[currentTags.length - 1];
+  				if (i > 0) {
+  					System.arraycopy(currentTags, 0, tags, 0, i);
+  				}
+  				if (tags.length - i > 0) {
+  					System.arraycopy(currentTags, i + 1, tags, 0, tags.length - i);
+  				}
+				}
 
-	public void categoryRemoved(Category category) {
-		if (currentCategory == category) {
-			activateCategory(CategoryManager.getCategory(Category.TYPE_ALL));
-		} else {
+				setCurrentTags(tags);
+				found = true;
+				break;
+			}
+		}
+		
+		if (!found) {
 			// always activate as deletion of this one might have
 			// affected the current view 
-			activateCategory(currentCategory);
+			setCurrentTags(currentTags);
 		}
+	}
+	
+	private Object[] removeFromArray(Object[] array, Object o) {
+		for (int i = 0; i < array.length; i++) {
+			Object cur = array[i];
+			if (cur.equals(o)) {
+				Tag[] newArray = new Tag[array.length - 1];
+				if (i > 0) {
+					System.arraycopy(array, 0, newArray, 0, i);
+				}
+				if (newArray.length - i > 0) {
+					System.arraycopy(array, i + 1, newArray, 0, newArray.length - i);
+				}
 
-		createTabs();
+				return newArray;
+			}
+		}
+		
+		return array;
 	}
-  
-  public void categoryChanged(Category category) {	
-  }
 
-  
-  		// tags 
-  
-  	private void 
-  	activateTag(
-  		Tag tag) 
-  	{
-  		if ( tag != currentTag ){
-  			
-  			if ( currentTag != null ){
-  			
-  				currentTag.removeTagListener(this);
-  			}
-  			
-  			if ( tag != null ){
-  				
-  				tag.addTagListener(this,false);
-  			}
-  			
-  			currentTag = tag;
-  		}
+			// tags 
+
+	private void setCurrentTags(Tag[] tags) {
+		if (currentTags != null) {
+			for (Tag tag : currentTags) {
+				tag.removeTagListener(this);
+			}
+		}
 
+		currentTags = tags;
+		if (currentTags != null) {
+			Set<Tag> to_remove = null;
+			for (Tag tag : currentTags) {
+				if ( tag.getTaggableTypes() != Taggable.TT_DOWNLOAD ){
+						// hmm, not a download related tag (e.g. peer-set), remove from the set. We can get this in the
+						// TagsOverview 'torrents' sub-view when peer-sets are selected in the main tag table
+					if (  to_remove == null ){
+						to_remove = new HashSet<Tag>();
+					}
+					to_remove.add( tag );
+				}else{
+					tag.addTagListener(this, false);
+				}
+			}
+			if ( to_remove != null ){
+				Tag[] updated_tags = new Tag[currentTags.length-to_remove.size()];
+				
+				int	pos = 0;
+				for (Tag tag : currentTags) {
+					if ( !to_remove.contains( tag )){
+						updated_tags[pos++] = tag;
+					}
+				}
+				currentTags = updated_tags;
+			}
+		}
+  	
   		tv.processDataSourceQueue();
   		Object[] managers = globalManager.getDownloadManagers().toArray();
   		List<DownloadManager> listRemoves = new ArrayList<DownloadManager>();
@@ -2050,22 +2430,27 @@ public class MyTorrentsView
   	}
   
   	private boolean 
-  	isInTag(
+  	isInTags(
   		DownloadManager		manager, 
-  		Tag 				tag ) 
+  		Tag[] 				tags ) 
   	{
-  		if ( tag == null ){
+  		if ( tags == null ){
   			return true;
   		}
   		
-  		return( tag.hasTaggable( manager ));
+  		for (Tag tag : tags) {
+				if (tag.hasTaggable(manager)) {
+					return true;
+				}
+			}
+  		return false;
   	}
   	
   	public boolean 
   	isInCurrentTag(
   		DownloadManager 	manager ) 
   	{
-  		return( isInTag(manager, currentTag ));
+  		return( isInTags(manager, currentTags ));
   	}
 
 	public void
@@ -2085,39 +2470,25 @@ public class MyTorrentsView
 	taggableSync(
 		Tag 		tag ) 
 	{
-		if ( tag.getTagName( true ).equals( "rrr" )){
-			System.out.println( "a" );
-		}
-		Set<DownloadManager>	dms_in_tag = new HashSet<DownloadManager>();
+		// request to fully resync this tag
 		
-		for ( Taggable t: tag.getTagged()){
-			
-			DownloadManager	manager = (DownloadManager)t;
+		List<DownloadManager> dataSources = tv.getDataSources();
+		
+		for ( DownloadManager dm : dataSources ){
 			
-			if ( isOurDownloadManager( manager )){
+			if ( !isOurDownloadManager(dm)){
 				
-				dms_in_tag.add( manager );
+				tv.removeDataSource(dm);
 			}
 		}
-		
-		if ( tv.getRowCount() != dms_in_tag.size()){
-						
-			Set<DownloadManager> dms_in_table = new HashSet<DownloadManager>(tv.getDataSources());
+
+		for ( Taggable t: tag.getTagged()){
 			
-			for ( DownloadManager dm: dms_in_table ){
-				
-				if ( !dms_in_tag.contains( dm )){
-										
-					tv.removeDataSource( dm );
-				}
-			}
+			DownloadManager	manager = (DownloadManager)t;
 			
-			for ( DownloadManager dm: dms_in_tag ){
+			if ( isOurDownloadManager( manager ) && !tv.dataSourceExists(manager)){
 				
-				if ( !dms_in_table.contains( dm )){
-										
-					tv.addDataSource( dm );
-				}
+				tv.addDataSource(manager);
 			}
 		}
 	}
@@ -2206,10 +2577,12 @@ public class MyTorrentsView
 			PiecesView.MSGID_PREFIX,
 			DownloadActivityView.MSGID_PREFIX,
 			PieceInfoView.MSGID_PREFIX,
-			FilesView.MSGID_PREFIX
+			FilesView.MSGID_PREFIX,
+			TaggingView.MSGID_PREFIX
 		));
 				
-		// discoveries sub-tab hack
+		// sub-tab hacks
+		restrictTo.add( "azbuddy.ui.menu.chat" );
 		PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager();
 		PluginInterface pi = pm.getPluginInterfaceByID("aercm", true);
 
@@ -2251,6 +2624,13 @@ public class MyTorrentsView
 					TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG,	// downloading view
 					TableManager.TABLE_MYTORRENTS_COMPLETE,			// bottom part of split views (hack of course)
 			};
+			
+			boolean hasTags = false;
+			try {
+				// gotta be a simpler way?
+				hasTags = TagManagerFactory.getTagManager().getTagType(TagType.TT_DOWNLOAD_MANUAL).getTags().size() > 0;
+			} catch (Throwable t) {
+			}
 
 			for ( String id: views_with_tabs ){
 
@@ -2264,6 +2644,9 @@ public class MyTorrentsView
 				pluginUI.addView( id, FilesView.MSGID_PREFIX,	FilesView.class, null);
 				pluginUI.addView( id, TorrentInfoView.MSGID_PREFIX, TorrentInfoView.class, null);
 				pluginUI.addView( id, TorrentOptionsView.MSGID_PREFIX, TorrentOptionsView.class, null);
+				if (hasTags) {
+					pluginUI.addView( id, TaggingView.MSGID_PREFIX, TaggingView.class, null);
+				}
 	
 				if (Logger.isEnabled()) {
 					pluginUI.addView( id, LoggerView.MSGID_PREFIX, LoggerView.class, null);
@@ -2339,8 +2722,8 @@ public class MyTorrentsView
 		if (event.getType() == UISWTViewEvent.TYPE_FOCUSGAINED) {
 			if (rebuildListOnFocusGain) {
   			List<?> dms = globalManager.getDownloadManagers();
-  			List<DownloadManager> listAdds = new ArrayList();
-  			List<DownloadManager> listRemoves = new ArrayList();
+  			List<DownloadManager> listAdds = new ArrayList<DownloadManager>();
+  			List<DownloadManager> listRemoves = new ArrayList<DownloadManager>();
   			for (Iterator<?> iter = dms.iterator(); iter.hasNext();) {
   				DownloadManager dm = (DownloadManager) iter.next();
   
@@ -2401,4 +2784,19 @@ public class MyTorrentsView
 			dm.getDownloadState().setBooleanAttribute( DownloadManagerState.AT_FILES_EXPANDED, false );
 		}
 	}
+	
+	protected Class<?> getForDataSourceType() {
+		return forDataSourceType;
+	}
+	
+	private boolean isCurrent(Tag tag) {
+		if (currentTags != null) {
+  		for (Tag curTag : currentTags) {
+  			if (tag.equals(curTag)) {
+  				return true;
+  			}
+  		}
+		}
+		return false;
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTrackerView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTrackerView.java
index 8d1905f..a70ebbf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTrackerView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/MyTrackerView.java
@@ -3,11 +3,12 @@
  * Created : 30-Oct-2003
  * By      : parg
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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;
@@ -49,6 +47,7 @@ import org.gudy.azureus2.core3.tracker.host.TRHostTorrentRemovalVetoException;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
 import org.gudy.azureus2.plugins.tracker.TrackerTorrent;
+import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
 import org.gudy.azureus2.plugins.ui.tables.TableManager;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
 import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentManagerImpl;
@@ -72,6 +71,7 @@ import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.common.table.*;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 
 
 /**
@@ -84,7 +84,8 @@ import com.aelitis.azureus.ui.common.table.*;
 public class MyTrackerView
 	extends TableViewTab<TRHostTorrent>
 	implements TRHostListener, CategoryManagerListener, TableLifeCycleListener,
-	TableSelectionListener, TableViewSWTMenuFillListener, TableRefreshListener
+	TableSelectionListener, TableViewSWTMenuFillListener, TableRefreshListener,
+	UIPluginViewToolBarListener
 {
   private static TableColumnCore[] basicItems = null;
 
@@ -164,7 +165,8 @@ public class MyTrackerView
 				if (dm != null) {
 					UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 					if (uiFunctions != null) {
-						uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, dm);
+						uiFunctions.getMDI().showEntryByID(
+								MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS, dm);
 					}
 				}
 			}
@@ -349,8 +351,6 @@ public class MyTrackerView
 	}	 
 
 	public void refreshToolBarItems(Map<String, Long> list) {
-		super.refreshToolBarItems(list);
-
 		boolean start = false, stop = false, remove = false;
     Object[] hostTorrents = tv.getSelectedDataSources().toArray();
     if (hostTorrents.length > 0) {
@@ -404,7 +404,7 @@ public class MyTrackerView
       return true;
     }
 
-		return super.toolBarItemActivated(item, activationType, datasource);
+		return false;
 	}
   
   private void stopSelectedTorrents() {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersGeneralView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersGeneralView.java
index 3115721..8f0734f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersGeneralView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersGeneralView.java
@@ -1,11 +1,12 @@
 /*
  * Created on 2 juil. 2003
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,9 +16,6 @@
  * 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;
 
@@ -28,11 +26,12 @@ import java.util.Set;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.Shell;
-
 import org.gudy.azureus2.core3.peer.PEPeer;
 import org.gudy.azureus2.plugins.peers.Peer;
 import org.gudy.azureus2.plugins.ui.tables.TableManager;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListenerEx;
 import org.gudy.azureus2.ui.swt.views.peer.PeerInfoView;
 import org.gudy.azureus2.ui.swt.views.peer.RemotePieceDistributionView;
 import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
@@ -53,7 +52,7 @@ import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 public class 
 PeersGeneralView
 	extends TableViewTab<PEPeer>
-	implements TagListener, TableLifeCycleListener, TableViewSWTMenuFillListener
+	implements TagListener, TableLifeCycleListener, TableViewSWTMenuFillListener, UISWTViewCoreEventListenerEx
 {	
 	private TableViewSWT<PEPeer> tv;
 	
@@ -70,6 +69,18 @@ PeersGeneralView
 		tag = _tag;
 	}	
 
+	public boolean
+	isCloneable()
+	{
+		return( true );
+	}
+	
+	public UISWTViewCoreEventListener
+	getClone()
+	{
+		return( new PeersGeneralView( tag ));
+	}
+	
 	public String 
 	getFullTitle() 
 	{
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersGraphicView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersGraphicView.java
index 1d72c7b..2a3c962 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersGraphicView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersGraphicView.java
@@ -2,11 +2,12 @@
  * Created on 19 nov. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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;
 
@@ -54,11 +52,11 @@ import org.gudy.azureus2.core3.peer.PEPeerStats;
 import org.gudy.azureus2.core3.peer.impl.PEPeerTransport;
 import org.gudy.azureus2.core3.peer.util.PeerUtils;
 import org.gudy.azureus2.core3.util.AEMonitor;
+import org.gudy.azureus2.core3.util.AERunnable;
 import org.gudy.azureus2.core3.util.Base32;
 import org.gudy.azureus2.core3.util.DisplayFormatters;
 import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
-import org.gudy.azureus2.ui.swt.ImageRepository;
-import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.*;
 import org.gudy.azureus2.ui.swt.components.graphics.PieUtils;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTView;
@@ -210,37 +208,35 @@ public class PeersGraphicView
 			  my_flag = ImageRepository.getCountryFlag( ia, false );
 		  }
 	  }
-	  
-	  DownloadManager old_manager = manager;
-	  if (newDataSource == null){
-		  manager = null;
-	  }else if (newDataSource instanceof Object[]){
-		  Object temp = ((Object[])newDataSource)[0];
-		  if ( temp instanceof DownloadManager ){
-			  manager = (DownloadManager)temp;
-		  }else if ( temp instanceof DiskManagerFileInfo){
-			  manager = ((DiskManagerFileInfo)temp).getDownloadManager();
-		  }else{
-			  return;
-		  }
-	  }else{
-		  if ( newDataSource instanceof DownloadManager ){
-			  manager = (DownloadManager)newDataSource;
-		  }else if ( newDataSource instanceof DiskManagerFileInfo){
-			  manager = ((DiskManagerFileInfo)newDataSource).getDownloadManager();
-		  }else{
-			  return;
-		  }
-	  }
 
-	  if ( old_manager == manager ){
-		  return;
-	  }
-	  
-	  if (old_manager != null){
-		  old_manager.removePeerListener(this);
-	  }
-	  
+		DownloadManager newManager = null;
+		if (newDataSource instanceof Object[]) {
+			Object[] newDataSources = (Object[]) newDataSource;
+			if (newDataSources.length == 1) {
+				Object temp = ((Object[]) newDataSource)[0];
+				if (temp instanceof DownloadManager) {
+					newManager = (DownloadManager) temp;
+				} else if (temp instanceof DiskManagerFileInfo) {
+					newManager = ((DiskManagerFileInfo) temp).getDownloadManager();
+				}
+			}
+		} else {
+			if (newDataSource instanceof DownloadManager) {
+				newManager = (DownloadManager) newDataSource;
+			} else if (newDataSource instanceof DiskManagerFileInfo) {
+				newManager = ((DiskManagerFileInfo) newDataSource).getDownloadManager();
+			}
+		}
+	
+		if (newManager == manager) {
+			return;
+		}
+
+		if (manager != null) {
+			manager.removePeerListener(this);
+		}
+		
+		manager = newManager;
 
 	  try {
 		  peers_mon.enter();
@@ -252,6 +248,16 @@ public class PeersGraphicView
 	  if (manager != null){
 		  manager.addPeerListener(this);
 	  }
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+			  if (manager != null){
+			  	Utils.disposeComposite(panel, false);
+			  } else {
+			  	ViewUtils.setViewRequiresOneDownload(panel);
+			  }
+			}
+		});
+
   }
 
   private void delete() {
@@ -730,15 +736,18 @@ public class PeersGraphicView
 	      		} else {
 	      			id += ":" + manager.getSize();
 	      		}
-	      	}
+						SelectedContentManager.changeCurrentlySelectedContent(id,
+								new SelectedContent[] {
+									new SelectedContent(manager)
+						});
+					} else {
+						SelectedContentManager.changeCurrentlySelectedContent(id, null);
+					}
 	  
-	      	SelectedContentManager.changeCurrentlySelectedContent(id, new SelectedContent[] {
-	      		new SelectedContent(manager)
-	      	});
-	      	
 	      break;
       case UISWTViewEvent.TYPE_FOCUSLOST:
     	  setFocused( false );
+    	  SelectedContentManager.clearCurrentlySelectedContent();
     	  break;
       case UISWTViewEvent.TYPE_REFRESH:
         refresh();
@@ -748,12 +757,20 @@ public class PeersGraphicView
     return true;
   }
 	
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener#toolBarItemActivated(com.aelitis.azureus.ui.common.ToolBarItem, long, java.lang.Object)
+	 */
 	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
 			Object datasource) {
-		return( ViewUtils.toolBarItemActivated(manager, item, activationType, datasource));
+		return false; // default handler will handle it
 	}
 
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener#refreshToolBarItems(java.util.Map)
+	 */
 	public void refreshToolBarItems(Map<String, Long> list) {
-		ViewUtils.refreshToolBarItems(manager, list);
+		Map<String, Long> states = TorrentUtil.calculateToolbarStates(
+				SelectedContentManager.getCurrentlySelectedContent(), null);
+		list.putAll(states);
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersSuperView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersSuperView.java
index 68c620f..173462d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersSuperView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersSuperView.java
@@ -1,11 +1,12 @@
 /*
  * Created on 2 juil. 2003
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,9 +16,6 @@
  * 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;
 
@@ -28,7 +26,6 @@ import java.util.Iterator;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.Shell;
-
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerPeerListener;
 import org.gudy.azureus2.core3.global.GlobalManager;
@@ -38,6 +35,8 @@ import org.gudy.azureus2.core3.peer.PEPeerManager;
 import org.gudy.azureus2.plugins.peers.Peer;
 import org.gudy.azureus2.plugins.ui.tables.TableManager;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListenerEx;
 import org.gudy.azureus2.ui.swt.views.peer.PeerInfoView;
 import org.gudy.azureus2.ui.swt.views.peer.RemotePieceDistributionView;
 import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
@@ -69,8 +68,10 @@ import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 public class PeersSuperView
 	extends TableViewTab<PEPeer>
 	implements GlobalManagerListener, DownloadManagerPeerListener,
-	TableLifeCycleListener, TableViewSWTMenuFillListener
-{	
+	TableLifeCycleListener, TableViewSWTMenuFillListener, UISWTViewCoreEventListenerEx
+{
+	public static final String VIEW_ID = "AllPeersView";
+	
 	private TableViewSWT<PEPeer> tv;
 	private Shell shell;
 	private boolean active_listener = true;
@@ -83,8 +84,21 @@ public class PeersSuperView
    *
    */
   public PeersSuperView() {
-  	super("AllPeersView");
+  	super( VIEW_ID );
 	}	
+  
+	public boolean
+	isCloneable()
+	{
+		return( true );
+	}
+	
+	public UISWTViewCoreEventListener
+	getClone()
+	{
+		return( new PeersSuperView());
+	}
+	
 
   // @see org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab#initYourTableView()
   public TableViewSWT<PEPeer> initYourTableView() {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersView.java
index 8ccbbf8..d2a3d69 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/PeersView.java
@@ -1,11 +1,12 @@
 /*
  * Created on 2 juil. 2003
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,12 +16,10 @@
  * 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;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import org.eclipse.swt.SWT;
@@ -44,10 +43,9 @@ import org.gudy.azureus2.core3.util.TorrentUtils;
 import org.gudy.azureus2.plugins.peers.Peer;
 import org.gudy.azureus2.plugins.ui.UIInputReceiver;
 import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
+import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
 import org.gudy.azureus2.plugins.ui.tables.TableManager;
-import org.gudy.azureus2.ui.swt.Messages;
-import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
-import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.*;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewEventImpl;
@@ -69,6 +67,7 @@ import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.common.table.*;
 import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
@@ -136,6 +135,8 @@ public class PeersView
 			new HandshakeReservedBytesItem(table_id),
 			new ClientIdentificationItem(table_id),	
 			new ASItem(table_id),
+			new IndexItem(table_id),
+			new ColumnPeerNetwork(table_id),
 		};
 	}
 	
@@ -229,43 +230,47 @@ public class PeersView
 			focus_pending_ds = newDataSource;
 			return;
 		}
-	  	DownloadManager old_manager = manager;
-		if (newDataSource == null){
-			manager = null;
-		}else if (newDataSource instanceof Object[]){
-			Object temp = ((Object[])newDataSource)[0];
-			if ( temp instanceof DownloadManager ){
-				manager = (DownloadManager)temp;
-			}else if ( temp instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)temp).getDownloadManager();
-			}else{
-				return;
+		
+		DownloadManager newManager = null;
+		if (newDataSource instanceof Object[]) {
+			Object[] newDataSources = (Object[]) newDataSource;
+			if (newDataSources.length == 1) {
+				Object temp = ((Object[]) newDataSource)[0];
+				if (temp instanceof DownloadManager) {
+					newManager = (DownloadManager) temp;
+				} else if (temp instanceof DiskManagerFileInfo) {
+					newManager = ((DiskManagerFileInfo) temp).getDownloadManager();
+				}
 			}
-		}else{
-			if ( newDataSource instanceof DownloadManager ){
-				manager = (DownloadManager)newDataSource;
-			}else if ( newDataSource instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)newDataSource).getDownloadManager();
-			}else{
-				return;
+		} else {
+			if (newDataSource instanceof DownloadManager) {
+				newManager = (DownloadManager) newDataSource;
+			} else if (newDataSource instanceof DiskManagerFileInfo) {
+				newManager = ((DiskManagerFileInfo) newDataSource).getDownloadManager();
 			}
 		}
-		
-		if ( old_manager == manager ){
+	
+		if (newManager == manager) {
+			tv.setEnabled(manager != null);
 			return;
 		}
 
-		if (old_manager != null){
-			old_manager.removePeerListener(this);
+		if (manager != null) {
+			manager.removePeerListener(this);
 		}
 		
-		if ( !tv.isDisposed()){
-			tv.removeAllTableRows();
-		
-			if (manager != null ){
-				manager.addPeerListener(this, false);
-				addExistingDatasources();
-			}
+		manager = newManager;
+
+		if (tv.isDisposed()) {
+			return;
+		}
+
+		tv.removeAllTableRows();
+		tv.setEnabled(manager != null);
+	
+		if (manager != null ){
+			manager.addPeerListener(this, false);
+			addExistingDatasources();
 		}
 	}
 
@@ -412,27 +417,33 @@ public class PeersView
 				
 				Utils.setMenuItemImage(itemDetails, "details");
 				
-				itemDetails.addListener(
-					SWT.Selection,
-					new Listener()
-					{
-						public void 
-						handleEvent(
-							Event event) 
-						{
-							UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
-							if (uiFunctions != null) {
-								for ( DownloadManager dm: download_managers ){
-									uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, dm);
-								}
+				itemDetails.addListener(SWT.Selection, new Listener() {
+					public void handleEvent(Event event) {
+						UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+						if (uiFunctions != null) {
+							for (DownloadManager dm : download_managers) {
+								uiFunctions.getMDI().showEntryByID(
+										MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS,
+										dm);
 							}
 						}
-					});
-				
+					}
+				});
+
 				new MenuItem(menu, SWT.SEPARATOR);
 			}
 		}
 
+		final MenuItem kick_item = new MenuItem(menu, SWT.PUSH);
+
+		Messages.setLanguageText(kick_item, "PeersView.menu.kick");
+		kick_item.addListener(SWT.Selection, new TableSelectedRowsListener(tv) {
+			public void run(TableRowCore row) {
+				PEPeer peer = (PEPeer) row.getDataSource(true);
+				peer.getManager().removePeer(peer,"Peer kicked" );
+			}
+		});
+		
 		final MenuItem ban_item = new MenuItem(menu, SWT.PUSH);
 
 		Messages.setLanguageText(ban_item, "PeersView.menu.kickandban");
@@ -442,7 +453,7 @@ public class PeersView
 				String msg = MessageText.getString("PeersView.menu.kickandban.reason");
 				IpFilterManagerFactory.getSingleton().getIPFilter().ban(peer.getIp(),
 						msg, true );
-				peer.getManager().removePeer(peer);
+				peer.getManager().removePeer(peer, "Peer kicked and banned");
 			}
 		});
 
@@ -457,6 +468,10 @@ public class PeersView
 
 		// advanced > Download Speed Menu //
 
+		Map<String,Object> menu_properties = new HashMap<String,Object>();
+		menu_properties.put( ViewUtils.SM_PROP_PERMIT_UPLOAD_DISABLE, true );	
+		menu_properties.put( ViewUtils.SM_PROP_PERMIT_DOWNLOAD_DISABLE, true );
+	
 		ViewUtils.addSpeedMenu(
 			shell,
 			menuAdvanced, true, true,
@@ -473,6 +488,7 @@ public class PeersView
 			upSpeedSetMax,
 			maxUp,
 			peers.length,
+			menu_properties,
 			new ViewUtils.SpeedAdapter()
 			{
 				public void 
@@ -597,6 +613,9 @@ public class PeersView
 								  			}catch( Throwable e ){
 								  			
 								  			}
+								  		}else{
+								  			
+							  				pm.addPeer( bit, 6881, 0, NetworkManager.getCryptoRequired( NetworkManager.CRYPTO_OVERRIDE_NONE ), null );
 								  		}
 								  	}
 								}
@@ -755,31 +774,21 @@ public class PeersView
 	      		} else {
 	      			id += ":" + manager.getSize();
 	      		}
-	      	}
+						SelectedContentManager.changeCurrentlySelectedContent(id,
+								new SelectedContent[] {
+									new SelectedContent(manager)
+						});
+					} else {
+						SelectedContentManager.changeCurrentlySelectedContent(id, null);
+					}
 	  
-	      	SelectedContentManager.changeCurrentlySelectedContent(id, new SelectedContent[] {
-	      		new SelectedContent(manager)
-	      	});
-
 		    break;
 	      case UISWTViewEvent.TYPE_FOCUSLOST:
 	    	  setFocused( false );
+	    		SelectedContentManager.clearCurrentlySelectedContent();
 	    	  break;	    
 	    }
 	    
 	    return( super.eventOccurred(event));
-	}
-	
-	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
-			Object datasource) {
-		if ( ViewUtils.toolBarItemActivated(manager, item, activationType, datasource)){
-			return( true );
-		}
-		return( super.toolBarItemActivated(item, activationType, datasource));
-	}
-
-	public void refreshToolBarItems(Map<String, Long> list) {
-		ViewUtils.refreshToolBarItems(manager, list);
-		super.refreshToolBarItems(list);
-	}
+	}	
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/PieceDistributionView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/PieceDistributionView.java
index 357372d..b9b194d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/PieceDistributionView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/PieceDistributionView.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/PiecesView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/PiecesView.java
index 51ced2a..3d50540 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/PiecesView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/PiecesView.java
@@ -1,11 +1,12 @@
 /*
  * Created on 2 juil. 2003
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,14 +16,10 @@
  * 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;
 
 import java.util.List;
-import java.util.Map;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionAdapter;
@@ -42,18 +39,17 @@ import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.components.Legend;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewEventImpl;
 import org.gudy.azureus2.ui.swt.views.piece.MyPieceDistributionView;
 import org.gudy.azureus2.ui.swt.views.piece.PieceInfoView;
 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.TableViewFactory;
+import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWT_TabsCommon;
 import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab;
 import org.gudy.azureus2.ui.swt.views.tableitems.pieces.*;
 
 import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker;
-import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.common.table.TableColumnCore;
 import com.aelitis.azureus.ui.common.table.TableDataSourceChangedListener;
 import com.aelitis.azureus.ui.common.table.TableLifeCycleListener;
@@ -78,8 +74,7 @@ public class PiecesView
 	DownloadManagerPieceListener,
 	TableDataSourceChangedListener,
 	TableLifeCycleListener,
-	TableViewSWTMenuFillListener,
-	UISWTViewCoreEventListener
+	TableViewSWTMenuFillListener
 {
 	private static boolean registeredCoreSubViews = false;
 
@@ -252,10 +247,7 @@ public class PiecesView
     				}
     			}
     		});
-		
-		new MenuItem( menu, SWT.SEPARATOR );
-		
-		/*
+				
 		final MenuItem reset_piece = new MenuItem( menu, SWT.PUSH );
 		
 		Messages.setLanguageText( reset_piece, "label.reset.piece" );
@@ -275,7 +267,8 @@ public class PiecesView
     				}
     			}
     		});
-    	*/
+		
+		new MenuItem( menu, SWT.SEPARATOR );
 	}
 	
 	public void 
@@ -314,60 +307,65 @@ public class PiecesView
 			focus_pending_ds = newDataSource;
 			return;
 		}
-	  	DownloadManager old_manager = manager;
-		if (newDataSource == null){
-			manager = null;
-		}else if (newDataSource instanceof Object[]){
-			Object temp = ((Object[])newDataSource)[0];
-			if ( temp instanceof DownloadManager ){
-				manager = (DownloadManager)temp;
-			}else if ( temp instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)temp).getDownloadManager();
-			}else{
-				return;
+
+		DownloadManager newManager = null;
+		if (newDataSource instanceof Object[]) {
+			Object[] newDataSources = (Object[]) newDataSource;
+			if (newDataSources.length == 1) {
+				Object temp = ((Object[]) newDataSource)[0];
+				if (temp instanceof DownloadManager) {
+					newManager = (DownloadManager) temp;
+				} else if (temp instanceof DiskManagerFileInfo) {
+					newManager = ((DiskManagerFileInfo) temp).getDownloadManager();
+				}
 			}
-		}else{
-			if ( newDataSource instanceof DownloadManager ){
-				manager = (DownloadManager)newDataSource;
-			}else if ( newDataSource instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)newDataSource).getDownloadManager();
-			}else{
-				return;
+		} else {
+			if (newDataSource instanceof DownloadManager) {
+				newManager = (DownloadManager) newDataSource;
+			} else if (newDataSource instanceof DiskManagerFileInfo) {
+				newManager = ((DiskManagerFileInfo) newDataSource).getDownloadManager();
 			}
 		}
-		
-		if ( old_manager == manager ){
+	
+		if (newManager == manager) {
+			tv.setEnabled(manager != null);
 			return;
 		}
+
+		if (manager != null) {
+			manager.removePeerListener(this);
+			manager.removePieceListener(this);
+		}
 		
-		if (old_manager != null){
-			old_manager.removePeerListener(this);
-			old_manager.removePieceListener(this);
+		manager = newManager;
+		
+		if (tv.isDisposed()){
+			return;
 		}
 
-		if ( !tv.isDisposed()){
-			tv.removeAllTableRows();
-			if (manager != null) {
-				manager.addPeerListener(this, false);
-				manager.addPieceListener(this, false);
-				addExistingDatasources();
-			}
+		tv.removeAllTableRows();
+		tv.setEnabled(manager != null);
+
+		if (manager != null) {
+			manager.addPeerListener(this, false);
+			manager.addPieceListener(this, false);
+			addExistingDatasources();
 		}
 	}
 
 	// @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewInitialized()
 	public void tableViewInitialized() {
 		if (legendComposite != null && tv != null) {
-			Composite composite = ((TableViewSWT<PEPiece>) tv).getTableComposite();
+			Composite composite = tv.getTableComposite();
 
 			legendComposite = Legend.createLegendComposite(composite,
 					BlocksItem.colors, new String[] {
-					"PiecesView.legend.requested",
-					"PiecesView.legend.written",        			
-					"PiecesView.legend.downloaded",
+						"PiecesView.legend.requested",
+						"PiecesView.legend.written",
+						"PiecesView.legend.downloaded",
 						"PiecesView.legend.incache"
 					});
-	}
+		}
 
 		if (manager != null) {
 			manager.removePeerListener(this);
@@ -375,8 +373,9 @@ public class PiecesView
 			manager.addPeerListener(this, false);
 			manager.addPieceListener(this, false);
 			addExistingDatasources();
-    }
-    }
+
+		}
+	}
 
 	// @see com.aelitis.azureus.ui.common.table.TableLifeCycleListener#tableViewDestroyed()
 	public void tableViewDestroyed() {
@@ -417,11 +416,24 @@ public class PiecesView
 		}
 
 		PEPiece[] dataSources = manager.getCurrentPieces();
-		if (dataSources == null || dataSources.length == 0)
-			return;
+		if (dataSources != null && dataSources.length >= 0) {
+  		tv.addDataSources(dataSources);
+    	tv.processDataSourceQueue();
+		}
+
+		// For this view the tab datasource isn't driven by table row selection so we
+		// need to update it with the primary data source
+		
+		// TODO: TrackerView and PiecesView now have this similar code -- this
+		//       would be better handled in TableViewTab (or TableViewSWT?)
+	
+		TableViewSWT_TabsCommon tabs = tv.getTabsCommon();
+		
+		if ( tabs != null ){
+			
+			tabs.triggerTabViewsDataSourceChanged(tv);
+		}
 
-		tv.addDataSources(dataSources);
-  	tv.processDataSourceQueue();
 	}
 
 	/**
@@ -454,31 +466,22 @@ public class PiecesView
 	      		} else {
 	      			id += ":" + manager.getSize();
 	      		}
-	      	}
+						SelectedContentManager.changeCurrentlySelectedContent(id,
+								new SelectedContent[] {
+									new SelectedContent(manager)
+						});
+					} else {
+						SelectedContentManager.changeCurrentlySelectedContent(id, null);
+					}
 	  
-	      	SelectedContentManager.changeCurrentlySelectedContent(id, new SelectedContent[] {
-	      		new SelectedContent(manager)
-	      	});
-		 
 		    break;
 	      case UISWTViewEvent.TYPE_FOCUSLOST:
 	    	  setFocused( false );
+	    		SelectedContentManager.clearCurrentlySelectedContent();
 	    	  break;	
 	    }
 	    
 	    return( super.eventOccurred(event));
 	}
 	
-	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
-			Object datasource) {
-		if ( ViewUtils.toolBarItemActivated(manager, item, activationType, datasource)){
-			return( true );
-		}
-		return( super.toolBarItemActivated(item, activationType, datasource));
-	}
-
-	public void refreshToolBarItems(Map<String, Long> list) {
-		ViewUtils.refreshToolBarItems(manager, list);
-		super.refreshToolBarItems(list);
-	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/ScrapeInfoView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/ScrapeInfoView.java
index 50b6ecf..57121e5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/ScrapeInfoView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/ScrapeInfoView.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.views;
 
 import java.net.URL;
@@ -11,6 +27,7 @@ import org.eclipse.swt.events.*;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.*;
+
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.torrent.TOTorrent;
@@ -30,6 +47,13 @@ import org.gudy.azureus2.ui.swt.plugins.UISWTView;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
 
+/**
+ * aka "Primary Tracker" view in "Sources" View
+ * <p>
+ * This view is placed within the {@link TrackerView} even though it relies on
+ * a {@link DownloadManager} datasource instead of TrackerPeerSource
+ * 
+ */
 public class ScrapeInfoView
 	implements UISWTViewCoreEventListener
 {
@@ -396,7 +420,7 @@ public class ScrapeInfoView
 				if ( cScrapeInfoView != null ){
 					Utils.disposeComposite(cScrapeInfoView, false);
 				}
-				if ( cParent != null ){
+				if ( cParent != null && !cParent.isDisposed() ){
 					
 					initialize( cParent );
 				}
@@ -426,6 +450,9 @@ public class ScrapeInfoView
 
       case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
       	Object ds = event.getData();
+      	if (ds instanceof Object[] && ((Object[]) ds).length > 0) {
+      		ds = ((Object[]) ds)[0];
+      	}
       	if (ds instanceof DownloadManager) {
 					DownloadManager dm = (DownloadManager) ds;
 					setDownlaodManager(dm);
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/TagSettingsView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/TagSettingsView.java
new file mode 100644
index 0000000..a0b59c3
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/TagSettingsView.java
@@ -0,0 +1,796 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views;
+
+import java.io.File;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+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.AERunnable;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.config.*;
+import org.gudy.azureus2.ui.swt.config.generic.*;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
+
+import com.aelitis.azureus.core.tag.*;
+import com.aelitis.azureus.core.tag.TagFeatureProperties.TagProperty;
+import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+import com.aelitis.azureus.ui.swt.utils.FontUtils;
+
+/**
+ * @author TuxPaper
+ * @created Mar 11, 2015
+ *
+ */
+public class TagSettingsView
+	implements UISWTViewCoreEventListener, TagTypeListener
+{
+
+	private UISWTView swtView;
+
+	private Composite cMainComposite;
+
+	private ScrolledComposite sc;
+
+	private Tag tag;
+
+	public static class Params
+	{
+		private Control cName;
+
+		private ColorParameter tagColor;
+
+		private GenericIntParameter maxDownloadSpeed;
+
+		private GenericIntParameter maxUploadSpeed;
+
+		private GenericBooleanParameter viewInSideBar;
+
+		private GenericBooleanParameter isPublic;
+
+		public GenericBooleanParameter uploadPriority;
+
+		public GenericFloatParameter min_sr;
+
+		public GenericFloatParameter max_sr;
+
+		public folderOption initalSaveFolder;
+
+		public folderOption moveOnCompleteFolder;
+
+		public folderOption copyOnCompleteFolder;
+
+		public Text constraints;
+	}
+
+	private Params params = null;
+
+	public TagSettingsView() {
+	}
+
+	// @see org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener#eventOccurred(org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent)
+	public boolean eventOccurred(UISWTViewEvent event) {
+		switch (event.getType()) {
+			case UISWTViewEvent.TYPE_CREATE:
+				swtView = (UISWTView) event.getData();
+				swtView.setTitle(getFullTitle());
+				break;
+
+			case UISWTViewEvent.TYPE_DESTROY:
+				delete();
+				break;
+
+			case UISWTViewEvent.TYPE_INITIALIZE:
+				initialize((Composite) event.getData());
+				break;
+
+			case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
+				Messages.updateLanguageForControl(cMainComposite);
+				swtView.setTitle(getFullTitle());
+				break;
+
+			case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
+				Object ds = event.getData();
+				dataSourceChanged(ds);
+				break;
+
+			case UISWTViewEvent.TYPE_FOCUSGAINED:
+				break;
+
+			case UISWTViewEvent.TYPE_REFRESH:
+				refresh();
+				break;
+		}
+
+		return true;
+	}
+
+	private void delete() {
+		dataSourceChanged(null);
+		params = null;
+	}
+
+	private void refresh() {
+	}
+
+	private void dataSourceChanged(Object ds) {
+
+		if (tag != null) {
+			TagType tagType = tag.getTagType();
+			tagType.removeTagTypeListener(this);
+		}
+
+		if (ds instanceof Tag) {
+			tag = (Tag) ds;
+		} else if (ds instanceof Object[]) {
+			Object[] objects = (Object[]) ds;
+			if (objects.length == 1 && objects[0] instanceof Tag) {
+				tag = (Tag) objects[0];
+			} else {
+				tag = null;
+			}
+		} else {
+			tag = null;
+		}
+
+		if (tag != null) {
+			TagType tagType = tag.getTagType();
+			tagType.addTagTypeListener(this, true);
+		}
+		initialize(null);
+
+	}
+
+	private void initialize(Composite parent) {
+		if (cMainComposite == null || cMainComposite.isDisposed()) {
+			if (parent == null || parent.isDisposed()) {
+				return;
+			}
+			sc = new ScrolledComposite(parent, SWT.V_SCROLL);
+			sc.setExpandHorizontal(true);
+			sc.setExpandVertical(true);
+			sc.getVerticalBar().setIncrement(16);
+			Layout parentLayout = parent.getLayout();
+			if (parentLayout instanceof GridLayout) {
+				GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
+				sc.setLayoutData(gd);
+			} else if (parentLayout instanceof FormLayout) {
+				sc.setLayoutData(Utils.getFilledFormData());
+			}
+
+			cMainComposite = new Composite(sc, SWT.NONE);
+
+			sc.setContent(cMainComposite);
+		} else {
+			Utils.disposeComposite(cMainComposite, false);
+		}
+
+		if (tag == null) {
+			params = null;
+			cMainComposite.setLayout(new FillLayout());
+			Label label = new Label(cMainComposite, SWT.NONE);
+			label.setText("Select one tag to see the tag's settings");
+		} else {
+			params = new Params();
+
+			GridData gd;
+			GridLayout gridLayout;
+			gridLayout = new GridLayout(1, false);
+			gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
+			gridLayout.marginHeight = gridLayout.marginWidth = 0;
+			cMainComposite.setLayout(gridLayout);
+
+			Composite cSection1 = new Composite(cMainComposite, SWT.NONE);
+			gridLayout = new GridLayout(4, false);
+			gridLayout.marginHeight = 0;
+			cSection1.setLayout(gridLayout);
+			gd = new GridData(SWT.FILL, SWT.FILL, true, false);
+			cSection1.setLayoutData(gd);
+
+			Composite cSection2 = new Composite(cMainComposite, SWT.NONE);
+			gridLayout = new GridLayout(4, false);
+			cSection2.setLayout(gridLayout);
+			gd = new GridData(SWT.FILL, SWT.FILL, true, false);
+			cSection2.setLayoutData(gd);
+
+			Label label;
+
+			// Field: Tag Type
+			label = new Label(cSection1, SWT.NONE);
+			label.setText(tag.getTagType().getTagTypeName(true));
+			FontUtils.setFontHeight(label, 12, SWT.BOLD);
+			gd = new GridData();
+			gd.horizontalSpan = 4;
+			label.setLayoutData(gd);
+
+			// Field: Name
+			label = new Label(cSection1, SWT.NONE);
+			Messages.setLanguageText(label, "MinimizedWindow.name");
+			gd = new GridData(SWT.BEGINNING, SWT.CENTER, false, false);
+			label.setLayoutData(gd);
+
+			if (!tag.getTagType().isTagTypeAuto()) {
+				Text txtName = new Text(cSection1, SWT.BORDER);
+				params.cName = txtName;
+				gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
+				txtName.setLayoutData(gd);
+
+				txtName.addModifyListener(new ModifyListener() {
+					public void modifyText(ModifyEvent e) {
+						try {
+							String newName = ((Text) e.widget).getText();
+							if (!tag.getTagName(true).equals(newName)) {
+								tag.setTagName(newName);
+							}
+						} catch (TagException e1) {
+							Debug.out(e1);
+						}
+					}
+				});
+			} else {
+				label = new Label(cSection1, SWT.NONE);
+				gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
+				label.setLayoutData(gd);
+				params.cName = label;
+			}
+
+			// Field: Color
+			label = new Label(cSection1, SWT.NONE);
+			Messages.setLanguageText(label, "label.color");
+			int[] color = tag.getColor();
+			params.tagColor = new ColorParameter(cSection1, null, color[0], color[1],
+					color[2]) {
+				// @see org.gudy.azureus2.ui.swt.config.ColorParameter#newColorChosen(org.eclipse.swt.graphics.RGB)
+				public void newColorChosen(RGB newColor) {
+					tag.setColor(new int[] {
+						newColor.red,
+						newColor.green,
+						newColor.blue
+					});
+				}
+			};
+
+			// Field: Visible
+
+			params.viewInSideBar = new GenericBooleanParameter(
+					new GenericParameterAdapter() {
+						public boolean getBooleanValue(String key) {
+							return tag.isVisible();
+						}
+
+						public boolean getBooleanValue(String key, boolean def) {
+							return tag.isVisible();
+						}
+
+						public void setBooleanValue(String key, boolean value) {
+							tag.setVisible(value);
+						}
+					}, cSection2, null, "TagSettings.viewInSideBar");
+			gd = new GridData();
+			gd.horizontalSpan = 4;
+			params.viewInSideBar.setLayoutData(gd);
+
+			// Field: Public
+			if (tag.canBePublic()) {
+				params.isPublic = new GenericBooleanParameter(
+						new GenericParameterAdapter() {
+							public boolean getBooleanValue(String key) {
+								return tag.isPublic();
+							}
+
+							public boolean getBooleanValue(String key, boolean def) {
+								return tag.isPublic();
+							}
+
+							public void setBooleanValue(String key, boolean value) {
+								tag.setPublic(value);
+							}
+						}, cSection2, null, "TagAddWindow.public.checkbox");
+				gd = new GridData();
+				gd.horizontalSpan = 4;
+				params.isPublic.setLayoutData(gd);
+			}
+
+			////////////////////
+
+			Group gTransfer = new Group(cMainComposite, SWT.NONE);
+			gTransfer.setText("Transfer Settings");
+			gridLayout = new GridLayout(4, false);
+			gTransfer.setLayout(gridLayout);
+
+			gd = new GridData(SWT.NONE, SWT.NONE, false, false, 4, 1);
+			gTransfer.setLayoutData(gd);
+
+			if (tag instanceof TagFeatureRateLimit) {
+				final TagFeatureRateLimit rl = (TagFeatureRateLimit) tag;
+				String k_unit = DisplayFormatters.getRateUnitBase10(
+						DisplayFormatters.UNIT_KB).trim();
+
+				if (rl.supportsTagDownloadLimit()) {
+					// Field: Download Limit
+					if (rl.supportsTagDownloadLimit()) {
+
+						gd = new GridData();
+						label = new Label(gTransfer, SWT.NULL);
+						label.setLayoutData(gd);
+						label.setText(k_unit + " " + MessageText.getString(
+								"GeneralView.label.maxdownloadspeed.tooltip"));
+
+						gd = new GridData();
+						//gd.horizontalSpan = 3;
+						params.maxDownloadSpeed = new GenericIntParameter(
+								new GenericParameterAdapter() {
+									public int getIntValue(String key) {
+										int limit = rl.getTagDownloadLimit();
+										return limit < 0 ? limit : limit / 1024;
+									}
+
+									public int getIntValue(String key, int def) {
+										return getIntValue(key);
+									}
+
+									public void setIntValue(String key, int value) {
+										if (value == -1) {
+											rl.setTagDownloadLimit(-1);
+										} else {
+											rl.setTagDownloadLimit(value * 1024);
+										}
+									}
+
+									public boolean resetIntDefault(String key) {
+										return false;
+									}
+								}, gTransfer, null, -1, Integer.MAX_VALUE);
+						params.maxDownloadSpeed.setLayoutData(gd);
+					}
+				}
+
+				// Upload Limit
+				if (rl.supportsTagUploadLimit()) {
+					gd = new GridData();
+					label = new Label(gTransfer, SWT.NULL);
+					label.setLayoutData(gd);
+					label.setText(k_unit + " " + MessageText.getString(
+							"GeneralView.label.maxuploadspeed.tooltip"));
+
+					gd = new GridData();
+					//gd.horizontalSpan = 3;
+					params.maxUploadSpeed = new GenericIntParameter(
+							new GenericParameterAdapter() {
+								public int getIntValue(String key) {
+									int limit = rl.getTagUploadLimit();
+									return limit < 0 ? limit : limit / 1024;
+								}
+
+								public int getIntValue(String key, int def) {
+									return getIntValue(key);
+								}
+
+								public void setIntValue(String key, int value) {
+									if (value == -1) {
+										rl.setTagUploadLimit(value);
+									} else {
+										rl.setTagUploadLimit(value * 1024);
+									}
+								}
+
+								public boolean resetIntDefault(String key) {
+									return false;
+								}
+							}, gTransfer, null, -1, Integer.MAX_VALUE);
+					params.maxUploadSpeed.setLayoutData(gd);
+				}
+
+				// Field: Upload Priority
+				if (rl.getTagUploadPriority() >= 0) {
+					params.uploadPriority = new GenericBooleanParameter(
+							new GenericParameterAdapter() {
+								public boolean getBooleanValue(String key) {
+									return rl.getTagUploadPriority() > 0;
+								}
+
+								public boolean getBooleanValue(String key, boolean def) {
+									return getBooleanValue(key);
+								}
+
+								public void setBooleanValue(String key, boolean value) {
+									rl.setTagUploadPriority(value ? 1 : 0);
+								}
+							}, gTransfer, null, "cat.upload.priority");
+					gd = new GridData();
+					gd.horizontalSpan = 4;
+					params.uploadPriority.setLayoutData(gd);
+				}
+
+				// Field: Min Share
+				if (rl.getTagMinShareRatio() >= 0) {
+					label = new Label(gTransfer, SWT.NONE);
+					Messages.setLanguageText(label, "TableColumn.header.min_sr");
+					gd = new GridData(SWT.BEGINNING, SWT.CENTER, false, false);
+					label.setLayoutData(gd);
+
+					params.min_sr = new GenericFloatParameter(
+							new GenericParameterAdapter() {
+								public float getFloatValue(String key) {
+									return rl.getTagMinShareRatio() / 1000f;
+								}
+
+								public void setFloatValue(String key, float value) {
+									rl.setTagMinShareRatio((int) (value * 1000));
+								}
+							}, gTransfer, null, 0, Float.MAX_VALUE, true, 3);
+					gd = new GridData();
+					//gd.horizontalSpan = 3;
+					gd.widthHint = 50;
+					params.min_sr.setLayoutData(gd);
+				}
+
+				// Field: Max Share
+				if (rl.getTagMaxShareRatio() >= 0) {
+					label = new Label(gTransfer, SWT.NONE);
+					Messages.setLanguageText(label, "TableColumn.header.max_sr");
+					gd = new GridData(SWT.BEGINNING, SWT.CENTER, false, false);
+					label.setLayoutData(gd);
+
+					params.max_sr = new GenericFloatParameter(
+							new GenericParameterAdapter() {
+								public float getFloatValue(String key) {
+									return rl.getTagMaxShareRatio() / 1000f;
+								}
+
+								public void setFloatValue(String key, float value) {
+									rl.setTagMaxShareRatio((int) (value * 1000));
+								}
+							}, gTransfer, null, 0, Float.MAX_VALUE, true, 3);
+					gd = new GridData();
+					//gd.horizontalSpan = 3;
+					gd.widthHint = 50;
+					params.max_sr.setLayoutData(gd);
+				}
+			}
+
+			/////////////////////////////////
+
+			if (tag instanceof TagFeatureFileLocation) {
+				final TagFeatureFileLocation fl = (TagFeatureFileLocation) tag;
+
+				if (fl.supportsTagCopyOnComplete() || fl.supportsTagInitialSaveFolder()
+						|| fl.supportsTagMoveOnComplete()) {
+
+					Group gFiles = new Group(cMainComposite, SWT.NONE);
+					gFiles.setText("File Settings");
+					gridLayout = new GridLayout(4, false);
+					gFiles.setLayout(gridLayout);
+
+					gd = new GridData(SWT.FILL, SWT.NONE, true, false, 4, 1);
+					gFiles.setLayoutData(gd);
+
+					if (fl.supportsTagInitialSaveFolder()) {
+						params.initalSaveFolder = new folderOption(gFiles,
+								"label.init.save.loc") {
+							public void setFolder(File folder) {
+								fl.setTagInitialSaveFolder(folder);
+							}
+
+							public File getFolder() {
+								return fl.getTagInitialSaveFolder();
+							}
+						};
+					}
+
+					if (fl.supportsTagMoveOnComplete()) {
+						params.moveOnCompleteFolder = new folderOption(gFiles,
+								"label.move.on.comp") {
+							public void setFolder(File folder) {
+								fl.setTagMoveOnCompleteFolder(folder);
+							}
+
+							public File getFolder() {
+								return fl.getTagMoveOnCompleteFolder();
+							}
+						};
+					}
+
+					if (fl.supportsTagCopyOnComplete()) {
+						params.copyOnCompleteFolder = new folderOption(gFiles,
+								"label.copy.on.comp") {
+							public void setFolder(File folder) {
+								fl.setTagCopyOnCompleteFolder(folder);
+							}
+
+							public File getFolder() {
+								return fl.getTagCopyOnCompleteFolder();
+							}
+						};
+					}
+				}
+			}
+
+			///////////////////////////////
+
+			if (tag.getTagType().hasTagTypeFeature(TagFeature.TF_PROPERTIES)
+					&& (tag instanceof TagFeatureProperties)) {
+				TagFeatureProperties tfp = (TagFeatureProperties) tag;
+
+				final TagProperty propConstraint = tfp.getProperty(
+						TagFeatureProperties.PR_CONSTRAINT);
+				if (propConstraint != null) {
+					Group gConstraint = new Group(cMainComposite, SWT.NONE);
+					Messages.setLanguageText(gConstraint, "tag.property.constraint");
+					gridLayout = new GridLayout(3, false);
+					gConstraint.setLayout(gridLayout);
+
+					gd = new GridData(SWT.FILL, SWT.NONE, true, false, 4, 1);
+					gConstraint.setLayoutData(gd);
+
+					params.constraints = new Text(gConstraint,
+							SWT.WRAP | SWT.BORDER | SWT.MULTI);
+					gd = new GridData(SWT.FILL, SWT.NONE, true, false, 3, 1);
+					gd.heightHint = 40;
+					params.constraints.setLayoutData(gd);
+					params.constraints.addKeyListener(new KeyListener() {
+						public void keyReleased(KeyEvent e) {
+						}
+
+						public void keyPressed(KeyEvent e) {
+							params.constraints.setData("skipset", 1);
+						}
+					});
+
+					Button btnSave = new Button(gConstraint, SWT.PUSH);
+					btnSave.addListener(SWT.Selection, new Listener() {
+						public void handleEvent(Event event) {
+							propConstraint.setStringList(new String[] {
+								params.constraints.getText()
+							});
+						}
+					});
+					Messages.setLanguageText(btnSave, "Button.save");
+
+					Button btnReset = new Button(gConstraint, SWT.PUSH);
+					btnReset.addListener(SWT.Selection, new Listener() {
+						public void handleEvent(Event event) {
+							params.constraints.setData("skipset", null);
+							swt_updateFields();
+						}
+					});
+					Messages.setLanguageText(btnReset, "Button.reset");
+
+					Link lblAboutConstraint = new Link(gConstraint, SWT.WRAP);
+					lblAboutConstraint.setLayoutData(
+							Utils.getWrappableLabelGridData(1, GridData.GRAB_HORIZONTAL));
+					lblAboutConstraint.setText(
+							MessageText.getString("tag.constraints.info"));
+					lblAboutConstraint.addListener(SWT.Selection, new Listener() {
+						public void handleEvent(Event event) {
+							if (event.text != null && (event.text.startsWith("http://")
+									|| event.text.startsWith("https://"))) {
+								Utils.launch(event.text);
+							}
+						}
+					});
+
+				}
+			}
+
+			swt_updateFields();
+		}
+
+		cMainComposite.layout();
+		sc.setMinSize(cMainComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+	}
+
+	private static abstract class folderOption
+	{
+		private Button btnClear;
+
+		private Label lblValue;
+
+		public folderOption(final Composite parent, String labelTextID) {
+			ImageLoader imageLoader = ImageLoader.getInstance();
+			Image imgOpenFolder = imageLoader.getImage("openFolderButton");
+
+			GridData gd = new GridData();
+			Label label = new Label(parent, SWT.NONE);
+			label.setLayoutData(gd);
+			Messages.setLanguageText(label, labelTextID);
+
+			Button browse = new Button(parent, SWT.PUSH);
+			browse.setImage(imgOpenFolder);
+			imgOpenFolder.setBackground(browse.getBackground());
+			browse.setToolTipText(MessageText.getString("ConfigView.button.browse"));
+
+			browse.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					DirectoryDialog dialog = new DirectoryDialog(parent.getShell(),
+							SWT.APPLICATION_MODAL);
+					String filterPath;
+					File tagInitialSaveFolder = getFolder();
+					filterPath = tagInitialSaveFolder != null
+							? tagInitialSaveFolder.toString()
+							: COConfigurationManager.getStringParameter("Default save path");
+					dialog.setFilterPath(filterPath);
+					dialog.setMessage(MessageText.getString("label.init.save.loc"));
+					dialog.setText(MessageText.getString("label.init.save.loc"));
+					final String path = dialog.open();
+					if (path != null) {
+						Utils.getOffOfSWTThread(new AERunnable() {
+							public void runSupport() {
+								setFolder(new File(path));
+							}
+						});
+					}
+				}
+			});
+
+			lblValue = new Label(parent, SWT.WRAP);
+			gd = Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL);
+			gd.verticalAlignment = SWT.CENTER;
+			lblValue.setLayoutData(gd);
+
+			btnClear = new Button(parent, SWT.PUSH);
+			Messages.setLanguageText(btnClear, "Button.clear");
+			btnClear.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					setFolder(null);
+				}
+			});
+		}
+
+		public void update() {
+			File folder = getFolder();
+			if (folder == null) {
+				Messages.setLanguageText(lblValue, "label.none.assigned");
+			} else {
+				lblValue.setText(folder.toString());
+			}
+			btnClear.setVisible(folder != null);
+		}
+
+		public abstract File getFolder();
+
+		public abstract void setFolder(File folder);
+	}
+
+	private String getFullTitle() {
+		return MessageText.getString("TagSettingsView.title");
+	}
+
+	private void swt_updateFields() {
+		if (tag == null || params == null) {
+			initialize(null);
+			return;
+		}
+
+		if (params.cName != null && !params.cName.isDisposed()) {
+			String name = tag.getTagName(true);
+			if (params.cName instanceof Text) {
+				Text txt = (Text) params.cName;
+				if (!txt.getText().equals(name)) {
+					txt.setText(name);
+				}
+			} else if (params.cName instanceof Label) {
+				Label lbl = (Label) params.cName;
+				lbl.setText(name);
+			}
+		}
+
+		if (params.tagColor != null) {
+			int[] color = tag.getColor();
+			params.tagColor.setColor(color[0], color[1], color[2]);
+		}
+
+		if (params.viewInSideBar != null) {
+			params.viewInSideBar.refresh();
+		}
+
+		if (params.isPublic != null) {
+			params.isPublic.refresh();
+		}
+
+		if (params.maxDownloadSpeed != null) {
+			params.maxDownloadSpeed.resetToDefault();
+		}
+		if (params.maxUploadSpeed != null) {
+			params.maxUploadSpeed.resetToDefault();
+		}
+
+		if (params.uploadPriority != null) {
+			params.uploadPriority.refresh();
+		}
+		if (params.min_sr != null) {
+			params.min_sr.refresh();
+		}
+		if (params.max_sr != null) {
+			params.max_sr.refresh();
+		}
+
+		if (params.initalSaveFolder != null) {
+			params.initalSaveFolder.update();
+		}
+		if (params.moveOnCompleteFolder != null) {
+			params.moveOnCompleteFolder.update();
+		}
+		if (params.copyOnCompleteFolder != null) {
+			params.copyOnCompleteFolder.update();
+		}
+		if (params.constraints != null
+				&& params.constraints.getData("skipset") == null) {
+			String text = "";
+			if (tag.getTagType().hasTagTypeFeature(TagFeature.TF_PROPERTIES)
+					&& (tag instanceof TagFeatureProperties)) {
+				TagFeatureProperties tfp = (TagFeatureProperties) tag;
+
+				TagProperty propConstraint = tfp.getProperty(
+						TagFeatureProperties.PR_CONSTRAINT);
+				if (propConstraint != null) {
+					String[] stringList = propConstraint.getStringList();
+					// constraint only has one entry
+					if (stringList.length == 1 && stringList.length > 0) {
+						text = stringList[0];
+					}
+				}
+			}
+			params.constraints.setText(text);
+		}
+	}
+
+	// @see com.aelitis.azureus.core.tag.TagTypeListener#tagTypeChanged(com.aelitis.azureus.core.tag.TagType)
+	public void tagTypeChanged(TagType tag_type) {
+		// TODO Auto-generated method stub
+
+	}
+
+	// @see com.aelitis.azureus.core.tag.TagTypeListener#tagAdded(com.aelitis.azureus.core.tag.Tag)
+	public void tagAdded(Tag tag) {
+		// TODO Auto-generated method stub
+
+	}
+
+	// @see com.aelitis.azureus.core.tag.TagTypeListener#tagChanged(com.aelitis.azureus.core.tag.Tag)
+	public void tagChanged(final Tag changedTag) {
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				if (changedTag.equals(tag)) {
+					swt_updateFields();
+				}
+			}
+		});
+	}
+
+	// @see com.aelitis.azureus.core.tag.TagTypeListener#tagRemoved(com.aelitis.azureus.core.tag.Tag)
+	public void tagRemoved(Tag tag) {
+		// TODO Auto-generated method stub
+
+	}
+
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/TaggingView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/TaggingView.java
new file mode 100644
index 0000000..7149d02
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/TaggingView.java
@@ -0,0 +1,485 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.*;
+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.Constants;
+import org.gudy.azureus2.ui.swt.MenuBuildUtils;
+import org.gudy.azureus2.ui.swt.MenuBuildUtils.MenuBuilder;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
+import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
+
+import com.aelitis.azureus.core.tag.*;
+import com.aelitis.azureus.ui.UIFunctions.TagReturner;
+import com.aelitis.azureus.ui.swt.utils.ColorCache;
+
+/**
+ * View showing tags set on selected taggable item(s).  Sometimes easier than
+ * drag and dropping to buttons/sidebar
+ * 
+ * @author TuxPaper
+ * @created Mar 23, 2015
+ *
+ */
+public class TaggingView
+	implements UISWTViewCoreEventListener, TagTypeListener
+{
+	public static final String MSGID_PREFIX = "TaggingView";
+
+	private UISWTView swtView;
+
+	private Composite cMainComposite;
+
+	private ScrolledComposite sc;
+
+	private List<Taggable> taggables;
+
+	private List<Button> buttons;
+
+	private Composite parent;
+
+	public TaggingView() {
+	}
+
+	// @see org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener#eventOccurred(org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent)
+	public boolean eventOccurred(UISWTViewEvent event) {
+		switch (event.getType()) {
+			case UISWTViewEvent.TYPE_CREATE:
+				swtView = (UISWTView) event.getData();
+				swtView.setTitle(getFullTitle());
+				break;
+
+			case UISWTViewEvent.TYPE_DESTROY:
+				delete();
+				break;
+
+			case UISWTViewEvent.TYPE_INITIALIZE:
+				parent = (Composite) event.getData();
+				break;
+
+			case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
+				Messages.updateLanguageForControl(cMainComposite);
+				swtView.setTitle(getFullTitle());
+				break;
+
+			case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
+				Object ds = event.getData();
+				dataSourceChanged(ds);
+				break;
+
+			case UISWTViewEvent.TYPE_FOCUSGAINED:
+				initialize();
+				if (taggables == null) {
+					dataSourceChanged(swtView.getDataSource());
+				}
+				break;
+				
+			case UISWTViewEvent.TYPE_FOCUSLOST:
+				delete();
+				break;
+
+			case UISWTViewEvent.TYPE_REFRESH:
+				refresh();
+				break;
+		}
+
+		return true;
+	}
+
+	private void delete() {
+		Utils.disposeComposite(sc);
+		dataSourceChanged(null);
+	}
+
+	private void refresh() {
+	}
+
+	private void dataSourceChanged(Object ds) {
+		boolean wasNull = taggables == null;
+
+		if (ds instanceof Taggable) {
+			taggables = new ArrayList<Taggable>();
+			taggables.add((Taggable) ds);
+		} else if (ds instanceof Taggable[]) {
+			taggables = new ArrayList<Taggable>();
+			taggables.addAll(Arrays.asList((Taggable[]) ds));
+		} else if (ds instanceof Object[]) {
+			taggables = new ArrayList<Taggable>();
+			Object[] objects = (Object[]) ds;
+			for (Object o : objects) {
+				if (o instanceof Taggable) {
+					Taggable taggable = (Taggable) o;
+					taggables.add(taggable);
+				}
+			}
+			if (taggables.size() == 0) {
+				taggables = null;
+			}
+		} else {
+			taggables = null;
+		}
+
+		boolean isNull = taggables == null;
+		if (isNull != wasNull) {
+			TagManager tm = TagManagerFactory.getTagManager();
+			TagType tagType;
+			/*
+			tagType = tm.getTagType(TagType.TT_DOWNLOAD_CATEGORY);
+			if (isNull) {
+				tagType.removeTagTypeListener(this);
+			} else {
+				tagType.addTagTypeListener(this, false);
+			}
+			*/
+			tagType = tm.getTagType(TagType.TT_DOWNLOAD_MANUAL);
+			if (isNull) {
+				tagType.removeTagTypeListener(this);
+			} else {
+				tagType.addTagTypeListener(this, false);
+			}
+		}
+
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				swt_updateFields();
+			}
+		});
+	}
+
+	private void initialize() {
+		if (cMainComposite == null || cMainComposite.isDisposed()) {
+			if (parent == null || parent.isDisposed()) {
+				return;
+			}
+			sc = new ScrolledComposite(parent, SWT.V_SCROLL);
+			sc.setExpandHorizontal(true);
+			sc.setExpandVertical(true);
+			sc.getVerticalBar().setIncrement(16);
+			Layout parentLayout = parent.getLayout();
+			if (parentLayout instanceof GridLayout) {
+				GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
+				sc.setLayoutData(gd);
+			} else if (parentLayout instanceof FormLayout) {
+				sc.setLayoutData(Utils.getFilledFormData());
+			}
+
+			cMainComposite = new Composite(sc, SWT.NONE);
+
+			sc.setContent(cMainComposite);
+		} else {
+			Utils.disposeComposite(cMainComposite, false);
+		}
+		
+		cMainComposite.setLayout(new GridLayout(1, false));
+
+		TagManager tm = TagManagerFactory.getTagManager();
+		int[] tagTypesWanted = {
+			TagType.TT_DOWNLOAD_MANUAL,
+		//TagType.TT_DOWNLOAD_CATEGORY
+		};
+
+		SelectionListener selectionListener = new SelectionListener() {
+
+			public void widgetSelected(SelectionEvent e) {
+				Button button = (Button) e.widget;
+				Tag tag = (Tag) button.getData("Tag");
+				if (button.getGrayed()) {
+					button.setGrayed(false);
+					button.setSelection(!button.getSelection());
+					button.getParent().redraw();
+				}
+				boolean doTag = button.getSelection();
+				for (Taggable taggable : taggables) {
+					if (doTag) {
+						tag.addTaggable(taggable);
+					} else {
+						tag.removeTaggable(taggable);
+					}
+				}
+				button.getParent().redraw();
+				button.getParent().update();
+			}
+
+			public void widgetDefaultSelected(SelectionEvent e) {
+			}
+		};
+
+		Listener menuDetectListener = new Listener() {
+			public void handleEvent(Event event) {
+
+				final Button button = (Button) event.widget;
+				Menu menu = new Menu(button);
+				button.setMenu(menu);
+				
+				MenuBuildUtils.addMaintenanceListenerForMenu(menu, new MenuBuilder() {
+					public void buildMenu(final Menu menu, MenuEvent menuEvent) {
+						Tag tag = (Tag) button.getData("Tag");
+						TagUIUtils.createSideBarMenuItems(menu, tag);
+					}
+				});
+			}
+		};
+		
+		PaintListener paintListener = new PaintListener() {
+			
+			public void paintControl(PaintEvent e) {
+				Button button;
+				Composite c = null;
+				if (e.widget instanceof Composite) {
+					c = (Composite) e.widget;
+					button = (Button) c.getChildren()[0];
+				} else {
+					button = (Button) e.widget;
+				}
+				Tag tag = (Tag) button.getData("Tag");
+				if (tag == null) {
+					return;
+				}
+
+				
+				
+				//ImageLoader.getInstance().getImage(? "check_yes" : "check_no");
+
+				if (c != null) {
+					boolean checked = button.getSelection();
+  				Point size = c.getSize();
+  				Point sizeButton = button.getSize();
+  				e.gc.setAntialias(SWT.ON);
+  				e.gc.setForeground(ColorCache.getColor(e.display, tag.getColor()));
+  				int lineWidth = button.getSelection() ? 2 : 1;
+  				e.gc.setLineWidth(lineWidth);
+
+  				int curve = 20;
+  				int width = sizeButton.x + lineWidth + 1;
+  				width += Constants.isOSX ? 5 : curve / 2;
+  				if (checked) {
+    				e.gc.setAlpha(0x20);
+    				e.gc.setBackground(ColorCache.getColor(e.display, tag.getColor()));
+    				e.gc.fillRoundRectangle(-curve, lineWidth - 1, width + curve, size.y - lineWidth, curve, curve);
+    				e.gc.setAlpha(0xff);
+  				}
+  				if (!checked) {
+    				e.gc.setAlpha(0x80);
+  				}
+  				e.gc.drawRoundRectangle(-curve, lineWidth - 1, width + curve, size.y - lineWidth, curve, curve);
+  				e.gc.drawLine(lineWidth - 1, lineWidth, lineWidth - 1, size.y - lineWidth);
+				} else {
+  				if (!Constants.isOSX && button.getSelection()) {
+    				Point size = button.getSize();
+    				e.gc.setBackground(ColorCache.getColor(e.display, tag.getColor()));
+    				e.gc.setAlpha(20);
+    				e.gc.fillRectangle(0, 0, size.x, size.y);
+  				}
+				}
+			}
+		};
+
+		buttons = new ArrayList<Button>();
+		for (int tagType : tagTypesWanted) {
+			Composite c = new Composite(cMainComposite, SWT.DOUBLE_BUFFERED);
+			c.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+			RowLayout rowLayout = new RowLayout();
+			rowLayout.pack = false;
+			rowLayout.spacing = 5;
+			c.setLayout(rowLayout);
+			
+			TagType tt = tm.getTagType(tagType);
+			List<Tag> tags = tt.getTags();
+			tags = TagUIUtils.sortTags(tags);
+			for (Tag tag : tags) {
+				Composite p = new Composite(c, SWT.DOUBLE_BUFFERED);
+				GridLayout layout = new GridLayout(1, false);
+				layout.marginHeight = 3;
+				if (Constants.isWindows) {
+					layout.marginWidth = 6;
+					layout.marginLeft = 2;
+					layout.marginTop = 1;
+				} else {
+					layout.marginWidth = 0;
+					layout.marginLeft = 3;
+					layout.marginRight = 10;
+				}
+				p.setLayout(layout);
+				p.addPaintListener(paintListener);
+				
+				Button button = new Button(p, SWT.CHECK);
+				buttons.add(button);
+				if ( tag.isTagAuto()){
+					button.setEnabled( false );
+				}else{
+					button.addSelectionListener(selectionListener);
+				}
+				button.setData("Tag", tag);
+
+				button.addListener(SWT.MenuDetect, menuDetectListener);
+				button.addPaintListener(paintListener);
+			}
+		}
+		
+		Button buttonAdd = new Button(cMainComposite, SWT.PUSH);
+		buttonAdd.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, false, false));
+		Messages.setLanguageText(buttonAdd, "label.add.tag");
+		buttonAdd.addSelectionListener(new SelectionListener() {
+			public void widgetSelected(SelectionEvent e) {
+				TagUIUtils.createManualTag(new TagReturner() {
+					public void returnedTags(Tag[] tags) {
+						for (Tag tag : tags) {
+							for (Taggable taggable : taggables) {
+								tag.addTaggable(taggable);
+							}
+						}
+					}
+				});
+			}
+			
+			public void widgetDefaultSelected(SelectionEvent e) {
+			}
+		});
+		
+		sc.addControlListener(new ControlAdapter() {
+			public void controlResized(ControlEvent e) {
+				Rectangle r = sc.getClientArea();
+				Point size = cMainComposite.computeSize(r.width, SWT.DEFAULT);
+				sc.setMinSize(size);
+			}
+		});
+
+		swt_updateFields();
+
+		Rectangle r = sc.getClientArea();
+		Point size = cMainComposite.computeSize(r.width, SWT.DEFAULT);
+		sc.setMinSize(size);
+	}
+
+	private String getFullTitle() {
+		return MessageText.getString("label.tags");
+	}
+
+	private void swt_updateFields() {
+
+		if (cMainComposite == null || cMainComposite.isDisposed()) {
+			return;
+		}
+		
+
+		List<Control> layoutChanges = new ArrayList<Control>();
+		for (Button button : buttons) {
+			boolean hasTag = false;
+			boolean hasNoTag = false;
+
+			Tag tag = (Tag) button.getData("Tag");
+			if (tag == null) {
+				continue;
+			}
+			String name = tag.getTagName(true);
+			if (!button.getText().equals(name)) {
+				button.setText(name);
+				layoutChanges.add(button);
+			}
+
+			if (taggables == null) {
+				button.setSelection(false);
+				button.setEnabled(false);
+				button.getParent().redraw();
+				continue;
+			}
+			if ( !tag.isTagAuto()){
+				button.setEnabled(true);
+			}
+			
+			for (Taggable taggable : taggables) {
+				boolean curHasTag = tag.hasTaggable(taggable);
+				if (!hasTag && curHasTag) {
+					hasTag = true;
+					if (hasNoTag) {
+						break;
+					}
+				} else if (!hasNoTag && !curHasTag) {
+					hasNoTag = true;
+					if (hasTag) {
+						break;
+					}
+				}
+			}
+			if (hasTag && hasNoTag) {
+				button.setGrayed(true);
+				button.setSelection(true);
+			} else {
+				button.setGrayed(false);
+				button.setSelection(hasTag);
+			}
+			button.getParent().redraw();
+		}
+
+		if (layoutChanges.size() > 0) {
+			cMainComposite.layout(layoutChanges.toArray(new Control[0]));
+			parent.layout();
+		}
+	}
+
+	// @see com.aelitis.azureus.core.tag.TagTypeListener#tagTypeChanged(com.aelitis.azureus.core.tag.TagType)
+	public void tagTypeChanged(TagType tag_type) {
+		// TODO Auto-generated method stub
+	}
+
+	// @see com.aelitis.azureus.core.tag.TagTypeListener#tagAdded(com.aelitis.azureus.core.tag.Tag)
+	public void tagAdded(Tag tag) {
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				initialize();
+			}
+		});
+	}
+
+	// @see com.aelitis.azureus.core.tag.TagTypeListener#tagChanged(com.aelitis.azureus.core.tag.Tag)
+	public void tagChanged(final Tag changedTag) {
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				swt_updateFields();
+			}
+		});
+	}
+
+	// @see com.aelitis.azureus.core.tag.TagTypeListener#tagRemoved(com.aelitis.azureus.core.tag.Tag)
+	public void tagRemoved(Tag tag) {
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				initialize();
+			}
+		});
+	}
+
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/TorrentInfoView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/TorrentInfoView.java
index 80eb18c..49b8db6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/TorrentInfoView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/TorrentInfoView.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -49,6 +46,7 @@ import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete;
 import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
 import org.gudy.azureus2.plugins.ui.tables.TableManager;
 import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.TorrentUtil;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.BufferedLabel;
 import org.gudy.azureus2.ui.swt.plugins.UISWTView;
@@ -464,12 +462,18 @@ public class TorrentInfoView
 	      		} else {
 	      			id += ":" + download_manager.getSize();
 	      		}
-	      	}
-	  
-	      	SelectedContentManager.changeCurrentlySelectedContent(id, new SelectedContent[] {
-	      		new SelectedContent(download_manager)
-	      	});
+						SelectedContentManager.changeCurrentlySelectedContent(id,
+								new SelectedContent[] {
+									new SelectedContent(download_manager)
+						});
+					} else {
+						SelectedContentManager.changeCurrentlySelectedContent(id, null);
+					}
       	break;
+
+      case UISWTViewEvent.TYPE_FOCUSLOST:
+    		SelectedContentManager.clearCurrentlySelectedContent();
+    		break;
         
       case UISWTViewEvent.TYPE_REFRESH:
         refresh();
@@ -479,12 +483,20 @@ public class TorrentInfoView
     return true;
   }
 	
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener#toolBarItemActivated(com.aelitis.azureus.ui.common.ToolBarItem, long, java.lang.Object)
+	 */
 	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
 			Object datasource) {
-		return( ViewUtils.toolBarItemActivated(download_manager, item, activationType, datasource));
+		return false; // default handler will handle it
 	}
 
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener#refreshToolBarItems(java.util.Map)
+	 */
 	public void refreshToolBarItems(Map<String, Long> list) {
-		ViewUtils.refreshToolBarItems(download_manager, list);
+		Map<String, Long> states = TorrentUtil.calculateToolbarStates(
+				SelectedContentManager.getCurrentlySelectedContent(), null);
+		list.putAll(states);
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/TorrentOptionsView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/TorrentOptionsView.java
index 330c0db..e917859 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/TorrentOptionsView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/TorrentOptionsView.java
@@ -1,7 +1,7 @@
 /*
  * Created on 16-Jan-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -32,7 +29,6 @@ import org.eclipse.swt.layout.FormLayout;
 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.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerState;
@@ -48,6 +44,7 @@ import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.BufferedLabel;
 import org.gudy.azureus2.ui.swt.config.ChangeSelectionActionPerformer;
 import org.gudy.azureus2.ui.swt.config.generic.GenericBooleanParameter;
+import org.gudy.azureus2.ui.swt.config.generic.GenericFloatParameter;
 import org.gudy.azureus2.ui.swt.config.generic.GenericIntParameter;
 import org.gudy.azureus2.ui.swt.config.generic.GenericParameterAdapter;
 import org.gudy.azureus2.ui.swt.plugins.UISWTView;
@@ -389,7 +386,43 @@ TorrentOptionsView
 						DownloadManagerState.PARAM_UPLOAD_PRIORITY, 0, 1 );
 						
 			ds_parameters.put( DownloadManagerState.PARAM_UPLOAD_PRIORITY, upload_priority_enabled );
-			upload_priority_enabled.setLayoutData( gridData );		
+			upload_priority_enabled.setLayoutData( gridData );
+			
+				// min sr
+			
+			label = new Label(gTorrentOptions, SWT.NULL);
+			gridData = new GridData();
+			label.setLayoutData( gridData );
+			Messages.setLanguageText(label, "TableColumn.header.min_sr" );
+			
+			gridData = new GridData();
+			gridData.widthHint=50;
+			GenericFloatParameter	min_sr = 
+				new GenericFloatParameter( 
+						ds_param_adapter, 
+						gTorrentOptions, 
+						DownloadManagerState.PARAM_MIN_SHARE_RATIO, 0, Float.MAX_VALUE, true, 3 );
+						
+			ds_parameters.put( DownloadManagerState.PARAM_MIN_SHARE_RATIO, min_sr );
+			min_sr.setLayoutData( gridData );	
+			
+				// max sr
+			
+			label = new Label(gTorrentOptions, SWT.NULL);
+			gridData = new GridData();
+			label.setLayoutData( gridData );
+			Messages.setLanguageText(label, "TableColumn.header.max_sr" );
+			
+			gridData = new GridData();
+			gridData.widthHint=50;
+			GenericFloatParameter	max_sr = 
+				new GenericFloatParameter( 
+						ds_param_adapter, 
+						gTorrentOptions, 
+						DownloadManagerState.PARAM_MAX_SHARE_RATIO, 0, Float.MAX_VALUE, true, 3 );
+						
+			ds_parameters.put( DownloadManagerState.PARAM_MAX_SHARE_RATIO, max_sr );
+			max_sr.setLayoutData( gridData );		
 		}
 		
 			// reset
@@ -539,11 +572,11 @@ TorrentOptionsView
 
 			DownloadManager	dm = managers[i];
 
-			total_size += dm.getSize();
-
 			DownloadManagerStats stats = dm.getStats();
 
-			total_remaining += stats.getRemaining();
+			total_size += stats.getSizeExcludingDND();
+
+			total_remaining += stats.getRemainingExcludingDND();
 			
 			long	good_received 	= stats.getTotalGoodDataBytesReceived();
 			long	received 		= stats.getTotalDataBytesReceived();
@@ -659,6 +692,10 @@ TorrentOptionsView
 						GenericBooleanParameter	bool_param = (GenericBooleanParameter)param;
 						boolean	value = state.getBooleanParameter( key );
 						bool_param.setSelected( value );
+					} else if (param instanceof GenericFloatParameter) {
+						GenericFloatParameter	float_param = (GenericFloatParameter)param;
+						float	value = state.getIntParameter( key )/1000f;
+						float_param.setValue( value );
 					} else {		
 						Debug.out( "Unknown parameter type: " + param.getClass());
 					}
@@ -869,6 +906,43 @@ TorrentOptionsView
 				}
 			}
 		}
+		
+		public float
+		getFloatValue(
+			String		key )
+		{
+			int	result = 0;
+			
+			for (int i=0;i<managers.length;i++){
+				int	val = managers[i].getDownloadState().getIntParameter( key );
+				
+				if ( i==0 ){
+					result = val;
+				}else if ( result != val ){
+					return( 0 );
+				}
+			}
+			
+			return( result/1000.0f );
+		}
+		
+		public void
+		setFloatValue(
+			String		key,
+			float		_value )
+		{
+			int	value = (int)(_value*1000);
+			
+			for (int i=0;i<managers.length;i++){
+
+				DownloadManager	manager = managers[i];
+				
+				if ( value != manager.getDownloadState().getIntParameter( key )){
+				
+					manager.getDownloadState().setIntParameter( key, value );
+				}
+			}
+		}
 	}
 	
 	private void dataSourceChanged(Object newDataSource) {
@@ -886,6 +960,17 @@ TorrentOptionsView
 		} else if (newDataSource instanceof DownloadManager[]) {
 			multi_view = true;
 			managers = (DownloadManager[]) newDataSource;
+		}else if ( newDataSource instanceof Object[]){
+			Object[] objs = (Object[])newDataSource;
+			if ( objs.length > 0 ){
+				if ( objs[0] instanceof DownloadManager ){
+					managers = new DownloadManager[objs.length];
+					for ( int i=0;i<objs.length;i++){
+						managers[i] = (DownloadManager)objs[i];
+					}
+					multi_view = true;
+				}
+			}
 		}
 		if (parent != null) {
 			Utils.execSWTThread(new AERunnable() {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/TrackerAvailView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/TrackerAvailView.java
new file mode 100644
index 0000000..1f3581c
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/TrackerAvailView.java
@@ -0,0 +1,189 @@
+/*
+ * Created on 2 juil. 2003
+ *
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views;
+
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Menu;
+import org.gudy.azureus2.core3.download.DownloadManagerAvailability;
+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.TableViewFactory;
+import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab;
+import org.gudy.azureus2.ui.swt.views.tableitems.tracker.*;
+
+import com.aelitis.azureus.core.tracker.TrackerPeerSource;
+import com.aelitis.azureus.ui.common.table.*;
+
+
+
+
+public class TrackerAvailView 
+	extends TableViewTab<TrackerPeerSource>
+	implements 	TableLifeCycleListener, TableDataSourceChangedListener, 
+				TableViewSWTMenuFillListener
+{
+	private static final String TABLE_ID = "TrackerAvail";
+	
+	private final static TableColumnCore[] basicItems = {
+		new TypeItem(TABLE_ID),
+		new NameItem(TABLE_ID),
+		new StatusItem(TABLE_ID),
+		new SeedsItem(TABLE_ID),
+		new LeechersItem(TABLE_ID),
+		new PeersItem(TABLE_ID),
+		new CompletedItem(TABLE_ID),
+	};
+
+	public static final String MSGID_PREFIX = "TrackerView";
+
+	private DownloadManagerAvailability 	availability;
+	
+	private TableViewSWT<TrackerPeerSource> tv;
+
+	/**
+	 * Initialize
+	 *
+	 */
+	public TrackerAvailView() {
+		super(MSGID_PREFIX);
+	}
+
+	public TableViewSWT<TrackerPeerSource>
+	initYourTableView() 
+	{
+		tv = TableViewFactory.createTableViewSWT(
+				TrackerPeerSource.class,
+				TABLE_ID, 
+				getPropertiesPrefix(), 
+				basicItems,
+				basicItems[0].getName(), 
+				SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL );
+
+		tv.addLifeCycleListener(this);
+		tv.addMenuFillListener(this);
+		tv.addTableDataSourceChangedListener(this, true);
+		
+		tv.setEnableTabViews(false,true,null);
+
+		return tv;
+	}
+
+	public boolean
+	isUpdating()
+	{
+		List<TrackerPeerSource> peer_sources = tv.getDataSources();
+		
+		for ( TrackerPeerSource p: peer_sources ){
+			
+			int status = p.getStatus();
+			
+			if ( 	status == TrackerPeerSource.ST_INITIALISING ||
+					status == TrackerPeerSource.ST_QUEUED ||
+					status == TrackerPeerSource.ST_UPDATING ){
+				
+				return( true );
+			}
+		}
+		
+		return( false );
+	}
+	
+	public void 
+	fillMenu(
+		String sColumnName, Menu menu) 
+	{
+	}
+	
+	public void 
+	addThisColumnSubMenu(
+		String columnName, 
+		Menu menuThisColumn) 
+	{
+	}
+	
+
+	
+	public void 
+	tableDataSourceChanged(
+		Object newDataSource ) 
+	{
+	  	DownloadManagerAvailability old_avail = availability;
+		if (newDataSource == null){
+			availability = null;
+		}else if (newDataSource instanceof Object[]){
+			Object temp = ((Object[])newDataSource)[0];
+			if ( temp instanceof DownloadManagerAvailability ){
+				availability = (DownloadManagerAvailability)temp;
+			}else{
+				return;
+			}
+		}else{
+			if ( newDataSource instanceof DownloadManagerAvailability ){
+				availability = (DownloadManagerAvailability)newDataSource;
+			}else{
+				return;
+			}
+		}
+		if ( old_avail == availability ){
+			return;
+		}
+	  	
+	  	if ( !tv.isDisposed()){
+	  		
+			tv.removeAllTableRows();
+	  	
+			if ( availability != null ){
+	  		
+				addExistingDatasources();
+			}
+	    }
+	}
+	
+	public void 
+	tableViewInitialized() 
+	{
+		if ( availability != null ){
+			
+			addExistingDatasources();
+		}
+    }
+
+	public void 
+	tableViewDestroyed() 
+	{
+	}
+
+	private void 
+	addExistingDatasources() 
+	{
+		if ( availability == null || tv.isDisposed()){
+			
+			return;
+		}
+
+		List<TrackerPeerSource> tps = availability.getTrackerPeerSources();
+		
+		tv.addDataSources( tps.toArray( (new TrackerPeerSource[tps.size()])));
+		
+		tv.processDataSourceQueueSync();
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/TrackerView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/TrackerView.java
index 06ad9bc..3d317d3 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/TrackerView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/TrackerView.java
@@ -1,11 +1,12 @@
 /*
  * Created on 2 juil. 2003
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,19 +16,14 @@
  * 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;
 
 import java.util.List;
-import java.util.Map;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.MenuItem;
-
 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerTPSListener;
@@ -48,19 +44,24 @@ import org.gudy.azureus2.ui.swt.views.table.TableSelectedRowsListener;
 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.TableViewFactory;
+import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWT_TabsCommon;
 import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab;
 import org.gudy.azureus2.ui.swt.views.tableitems.tracker.*;
 
 import com.aelitis.azureus.core.tracker.TrackerPeerSource;
-import com.aelitis.azureus.ui.common.ToolBarItem;
-import com.aelitis.azureus.ui.common.table.*;
+import com.aelitis.azureus.ui.common.table.TableColumnCore;
+import com.aelitis.azureus.ui.common.table.TableDataSourceChangedListener;
+import com.aelitis.azureus.ui.common.table.TableLifeCycleListener;
+import com.aelitis.azureus.ui.common.table.TableRowCore;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 
 
-
+/**
+ * aka "Sources" view
+ */
 public class TrackerView 
 	extends TableViewTab<TrackerPeerSource>
 	implements 	TableLifeCycleListener, TableDataSourceChangedListener, 
@@ -69,15 +70,15 @@ public class TrackerView
 	private static boolean registeredCoreSubViews = false;
 
 	private final static TableColumnCore[] basicItems = {
-		new TypeItem(),
-		new NameItem(),
-		new StatusItem(),
-		new PeersItem(),
-		new SeedsItem(),
-		new LeechersItem(),
-		new CompletedItem(),
-		new UpdateInItem(),
-		new IntervalItem(),
+		new TypeItem(TableManager.TABLE_TORRENT_TRACKERS),
+		new NameItem(TableManager.TABLE_TORRENT_TRACKERS),
+		new StatusItem(TableManager.TABLE_TORRENT_TRACKERS),
+		new PeersItem(TableManager.TABLE_TORRENT_TRACKERS),
+		new SeedsItem(TableManager.TABLE_TORRENT_TRACKERS),
+		new LeechersItem(TableManager.TABLE_TORRENT_TRACKERS),
+		new CompletedItem(TableManager.TABLE_TORRENT_TRACKERS),
+		new UpdateInItem(TableManager.TABLE_TORRENT_TRACKERS),
+		new IntervalItem(TableManager.TABLE_TORRENT_TRACKERS),
 		new LastUpdateItem(TableManager.TABLE_TORRENT_TRACKERS),
 	};
 
@@ -332,48 +333,48 @@ public class TrackerView
 	public void 
 	tableDataSourceChanged(
 		Object newDataSource ) 
-	{
-	  	DownloadManager old_manager = manager;
-		if (newDataSource == null){
-			manager = null;
-		}else if (newDataSource instanceof Object[]){
-			Object temp = ((Object[])newDataSource)[0];
-			if ( temp instanceof DownloadManager ){
-				manager = (DownloadManager)temp;
-			}else if ( temp instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)temp).getDownloadManager();
-			}else{
-				return;
+ {
+		DownloadManager newManager = null;
+		if (newDataSource instanceof Object[]) {
+			Object[] newDataSources = (Object[]) newDataSource;
+			if (newDataSources.length == 1) {
+				Object temp = ((Object[]) newDataSource)[0];
+				if (temp instanceof DownloadManager) {
+					newManager = (DownloadManager) temp;
+				} else if (temp instanceof DiskManagerFileInfo) {
+					newManager = ((DiskManagerFileInfo) temp).getDownloadManager();
+				}
 			}
-		}else{
-			if ( newDataSource instanceof DownloadManager ){
-				manager = (DownloadManager)newDataSource;
-			}else if ( newDataSource instanceof DiskManagerFileInfo){
-				manager = ((DiskManagerFileInfo)newDataSource).getDownloadManager();
-			}else{
-				return;
+		} else {
+			if (newDataSource instanceof DownloadManager) {
+				newManager = (DownloadManager) newDataSource;
+			} else if (newDataSource instanceof DiskManagerFileInfo) {
+				newManager = ((DiskManagerFileInfo) newDataSource).getDownloadManager();
 			}
 		}
-		if ( old_manager == manager ){
+	
+		if (newManager == manager) {
+			tv.setEnabled(manager != null);
 			return;
 		}
-		
-	  	if ( old_manager != null ){
-	  		
-	  		old_manager.removeTPSListener( this );
+
+		if (manager != null) {
+			manager.removeTPSListener(this);
 		}
 		
-	  	if ( !tv.isDisposed()){
-	  		
-			tv.removeAllTableRows();
-	  	
-			if ( manager != null ){
-	    	
-				manager.addTPSListener( this );
-	  		
-				addExistingDatasources();
-			}
-	    }
+		manager = newManager;
+
+		if (tv.isDisposed()) {
+			return;
+		}
+
+		tv.removeAllTableRows();
+		tv.setEnabled(manager != null);
+
+		if (manager != null) {
+			manager.addTPSListener(this);
+			addExistingDatasources();
+		}
 	}
 	
 	public void 
@@ -384,6 +385,16 @@ public class TrackerView
 			manager.addTPSListener( this );
 			
 			addExistingDatasources();
+			
+				// For this view the tab datasource isn't driven by table row selection so we
+				// need to update it with the primary data source
+			
+	 		TableViewSWT_TabsCommon tabs = tv.getTabsCommon();
+	  		
+	  		if ( tabs != null ){
+	  			
+	  			tabs.triggerTabViewsDataSourceChanged( tv );
+	  		}
 		}
     }
 
@@ -431,27 +442,22 @@ public class TrackerView
 	      		} else {
 	      			id += ":" + manager.getSize();
 	      		}
-	      	}
+						SelectedContentManager.changeCurrentlySelectedContent(id,
+								new SelectedContent[] {
+									new SelectedContent(manager)
+						});
+					} else {
+						SelectedContentManager.changeCurrentlySelectedContent(id, null);
+					}
 	  
-	      	SelectedContentManager.changeCurrentlySelectedContent(id, new SelectedContent[] {
-	      		new SelectedContent(manager)
-	      	});
 	      	break;
+	      	
+	      case UISWTViewEvent.TYPE_FOCUSLOST:
+	    		SelectedContentManager.clearCurrentlySelectedContent();
+	    		break;
 	    }
 	    
 	    return( super.eventOccurred(event));
 	}
 	
-	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
-			Object datasource) {
-		if ( ViewUtils.toolBarItemActivated(manager, item, activationType, datasource)){
-			return( true );
-		}
-		return( super.toolBarItemActivated(item, activationType, datasource));
-	}
-
-	public void refreshToolBarItems(Map<String, Long> list) {
-		ViewUtils.refreshToolBarItems(manager, list);
-		super.refreshToolBarItems(list);
-	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/ViewUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/ViewUtils.java
index a20b1d6..b6bee84 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/ViewUtils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/ViewUtils.java
@@ -3,11 +3,12 @@
  * Created : 24-Oct-2003
  * By      : parg
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,25 +18,25 @@
  * 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;
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.Map;
 
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
 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.internat.MessageText;
 import org.gudy.azureus2.core3.util.Constants;
 import org.gudy.azureus2.core3.util.Debug;
@@ -45,16 +46,11 @@ import org.gudy.azureus2.plugins.ui.UIInputReceiver;
 import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
 import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
 import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
-import org.gudy.azureus2.ui.swt.TorrentUtil;
 import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
 
-import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.common.table.impl.CoreTableColumn;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 
 /**
  * @author parg
@@ -242,6 +238,17 @@ ViewUtils
 	{
 		return( new CustomDateFormat( column ));
 	}
+	
+	public static final String SM_PROP_PERMIT_UPLOAD_DISABLE	= "enable_upload_disable";
+	public static final String SM_PROP_PERMIT_DOWNLOAD_DISABLE	= "enable_download_disable";
+	
+	private static final Map<String,Object>	SM_DEFAULTS = new HashMap<String, Object>();
+	
+	static{
+		SM_DEFAULTS.put( SM_PROP_PERMIT_UPLOAD_DISABLE, false );
+		SM_DEFAULTS.put( SM_PROP_PERMIT_DOWNLOAD_DISABLE, false );
+	}
+	
 	public static void
 	addSpeedMenu(
 		final Shell 		shell,
@@ -261,240 +268,308 @@ ViewUtils
 		long				upSpeedSetMax,
 		long				maxUpload,
 		final int			num_entries,
+		Map<String,Object>	_properties,
 		final SpeedAdapter	adapter )
-	{
-		String menu_key = "MyTorrentsView.menu.manual";
-		if (num_entries > 1) {menu_key += (isTorrentContext?".per_torrent":".per_peer" );}
-
-		if ( doDownMenu ){
+ {
+		if (doDownMenu) {
 			// advanced > Download Speed Menu //
 			final MenuItem itemDownSpeed = new MenuItem(menuAdvanced, SWT.CASCADE);
-			Messages.setLanguageText(itemDownSpeed, "MyTorrentsView.menu.setDownSpeed"); //$NON-NLS-1$
+			Messages.setLanguageText(itemDownSpeed,
+					"MyTorrentsView.menu.setDownSpeed"); //$NON-NLS-1$
 			Utils.setMenuItemImage(itemDownSpeed, "speed");
-	
-			final Menu menuDownSpeed = new Menu(shell, SWT.DROP_DOWN);
+
+			Menu menuDownSpeed = new Menu(shell, SWT.DROP_DOWN);
 			itemDownSpeed.setMenu(menuDownSpeed);
+
+			addSpeedMenuDown(shell, menuDownSpeed, isTorrentContext, hasSelection,
+					downSpeedDisabled, downSpeedUnlimited, totalDownSpeed,
+					downSpeedSetMax, maxDownload, num_entries, _properties, adapter);
+		}
+
+		if (doUpMenu) {
+			// advanced >Upload Speed Menu //
+			final MenuItem itemUpSpeed = new MenuItem(menuAdvanced, SWT.CASCADE);
+			Messages.setLanguageText(itemUpSpeed, "MyTorrentsView.menu.setUpSpeed"); //$NON-NLS-1$
+			Utils.setMenuItemImage(itemUpSpeed, "speed");
+
+			Menu menuUpSpeed = new Menu(shell, SWT.DROP_DOWN);
+			itemUpSpeed.setMenu(menuUpSpeed);
+			addSpeedMenuUp(shell, menuUpSpeed, isTorrentContext, hasSelection,
+					upSpeedDisabled, upSpeedUnlimited, totalUpSpeed, upSpeedSetMax,
+					maxUpload, num_entries, _properties, adapter);
+		}
+	}
+
+	public static void
+	addSpeedMenuUp(
+		final Shell 		shell,
+		Menu				menuSpeed,
+		boolean				isTorrentContext,
+		boolean				hasSelection,
+		boolean				upSpeedDisabled,
+		boolean				upSpeedUnlimited,
+		long				totalUpSpeed,
+		long				upSpeedSetMax,
+		long				maxUpload,
+		final int			num_entries,
+		Map<String,Object>	_properties,
+		final SpeedAdapter	adapter )
+	{
+		Map<String,Object>	properties = new HashMap<String, Object>( SM_DEFAULTS );
+		if ( _properties != null ){
+			properties.putAll( _properties );
+		}
+		
+		String menu_key = "MyTorrentsView.menu.manual";
+		if (num_entries > 1) {menu_key += (isTorrentContext?".per_torrent":".per_peer" );}
+
+		if ( menuSpeed != null ){
 	
-			final MenuItem itemCurrentDownSpeed = new MenuItem(menuDownSpeed, SWT.PUSH);
-			itemCurrentDownSpeed.setEnabled(false);
-			StringBuffer speedText = new StringBuffer();
+			final MenuItem itemCurrentUpSpeed = new MenuItem(menuSpeed, SWT.PUSH);
+			itemCurrentUpSpeed.setEnabled(false);
 			String separator = "";
-			//itemDownSpeed.                   
-			if (downSpeedDisabled) {
+			StringBuffer speedText = new StringBuffer();
+			//itemUpSpeed.                   
+			if (upSpeedDisabled) {
 				speedText.append(MessageText
 						.getString("MyTorrentsView.menu.setSpeed.disabled"));
 				separator = " / ";
 			}
-			if (downSpeedUnlimited) {
+			if (upSpeedUnlimited) {
 				speedText.append(separator);
 				speedText.append(MessageText
 						.getString("MyTorrentsView.menu.setSpeed.unlimited"));
 				separator = " / ";
 			}
-			if (totalDownSpeed > 0) {
+			if (totalUpSpeed > 0) {
 				speedText.append(separator);
 				speedText.append(DisplayFormatters
-						.formatByteCountToKiBEtcPerSec(totalDownSpeed));
+						.formatByteCountToKiBEtcPerSec(totalUpSpeed));
 			}
-			itemCurrentDownSpeed.setText(speedText.toString());
-	
-			new MenuItem(menuDownSpeed, SWT.SEPARATOR);
+			itemCurrentUpSpeed.setText(speedText.toString());
 	
-			final MenuItem itemsDownSpeed[] = new MenuItem[12];
-			Listener itemsDownSpeedListener = new Listener() {
+			// ---
+			new MenuItem(menuSpeed, SWT.SEPARATOR);
+				
+			Listener itemsUpSpeedListener = new Listener() {
 				public void handleEvent(Event e) {
 					if (e.widget != null && e.widget instanceof MenuItem) {
 						MenuItem item = (MenuItem) e.widget;
-						int speed = item.getData("maxdl") == null ? 0 : ((Integer) item
-								.getData("maxdl")).intValue();
-						adapter.setDownSpeed(speed);
+						int speed = item.getData("maxul") == null ? 0 : ((Integer) item
+								.getData("maxul")).intValue();
+						adapter.setUpSpeed(speed);
 					}
 				}
 			};
 	
-			itemsDownSpeed[1] = new MenuItem(menuDownSpeed, SWT.PUSH);
-			Messages.setLanguageText(itemsDownSpeed[1],
-					"MyTorrentsView.menu.setSpeed.unlimit");
-			itemsDownSpeed[1].setData("maxdl", new Integer(0));
-			itemsDownSpeed[1].addListener(SWT.Selection, itemsDownSpeedListener);
-	
+			if ( num_entries > 1 || !upSpeedUnlimited ){
+				MenuItem mi = new MenuItem(menuSpeed, SWT.PUSH);
+				Messages.setLanguageText(mi,
+						"MyTorrentsView.menu.setSpeed.unlimit");
+				mi.setData("maxul", new Integer(0));
+				mi.addListener(SWT.Selection, itemsUpSpeedListener);
+			}
+			
+			boolean allowDisable = (Boolean)properties.get( SM_PROP_PERMIT_UPLOAD_DISABLE );
+
+			if ( allowDisable && !upSpeedDisabled ){
+				MenuItem mi = new MenuItem(menuSpeed, SWT.PUSH);
+				Messages.setLanguageText(mi,
+						"MyTorrentsView.menu.setSpeed.disable");
+				mi.setData("maxul", new Integer(-1));
+				mi.addListener(SWT.Selection, itemsUpSpeedListener);
+			}
+			
 			if (hasSelection) {
-	
-				//using 200KiB/s as the default limit when no limit set.
-				if (maxDownload == 0){		
-					if ( downSpeedSetMax == 0 ){
-						maxDownload = 200 * 1024;
+				//using 75KiB/s as the default limit when no limit set.
+				if (maxUpload == 0){
+					maxUpload = 75 * 1024;
+				}else{
+					if ( upSpeedSetMax <= 0 ){
+						maxUpload = 200 * 1024;
 					}else{
-						maxDownload	= 4 * ( downSpeedSetMax/1024 ) * 1024;
+						maxUpload = 4 * ( upSpeedSetMax/1024 ) * 1024;
 					}
 				}
+				for (int i = 0; i < 10; i++) {
+					MenuItem mi = new MenuItem(menuSpeed, SWT.PUSH);
+					mi.addListener(SWT.Selection, itemsUpSpeedListener);
 	
-				for (int i = 2; i < 12; i++) {
-					itemsDownSpeed[i] = new MenuItem(menuDownSpeed, SWT.PUSH);
-					itemsDownSpeed[i].addListener(SWT.Selection, itemsDownSpeedListener);
-		
-					// dms.length has to be > 0 when hasSelection
-					int limit = (int)(maxDownload / (10 * num_entries) * (12 - i));
-					StringBuffer speed = new StringBuffer();
-					speed.append(DisplayFormatters.formatByteCountToKiBEtcPerSec(limit
-							* num_entries));
+					int limit = (int)( maxUpload / (10 * num_entries) * (10 - i));
+					String speed = DisplayFormatters.formatByteCountToKiBEtcPerSec(limit
+							* num_entries);
 					if (num_entries > 1) {
-						speed.append(" ");
-						speed.append(MessageText
-								.getString("MyTorrentsView.menu.setSpeed.in"));
-						speed.append(" ");
-						speed.append(num_entries);
-						speed.append(" ");
-						speed.append(MessageText
-								.getString("MyTorrentsView.menu.setSpeed.slots"));
-						speed.append(" ");
-						speed
-								.append(DisplayFormatters.formatByteCountToKiBEtcPerSec(limit));
+						speed = MessageText.getString("MyTorrentsView.menu.setSpeed.multi",
+								new String[] {
+									speed,
+									String.valueOf(num_entries),
+									DisplayFormatters.formatByteCountToKiBEtcPerSec(limit)
+								});
 					}
-					itemsDownSpeed[i].setText(speed.toString());
-					itemsDownSpeed[i].setData("maxdl", new Integer(limit));
+
+					mi.setText(speed);
+					mi.setData("maxul", new Integer(limit));
 				}
 			}
 	
-			// ---
-			new MenuItem(menuDownSpeed, SWT.SEPARATOR);
-				
-			final MenuItem itemDownSpeedManualSingle = new MenuItem(menuDownSpeed, SWT.PUSH);
-			Messages.setLanguageText(itemDownSpeedManualSingle, menu_key);
-			itemDownSpeedManualSingle.addSelectionListener(new SelectionAdapter() {
+			new MenuItem(menuSpeed, SWT.SEPARATOR);
+	
+			final MenuItem itemUpSpeedManualSingle = new MenuItem(menuSpeed, SWT.PUSH);
+			Messages.setLanguageText(itemUpSpeedManualSingle, menu_key);
+			itemUpSpeedManualSingle.addSelectionListener(new SelectionAdapter() {
 				public void widgetSelected(SelectionEvent e) {
-					int speed_value = getManualSpeedValue(shell, true);
-					if (speed_value > 0) {adapter.setDownSpeed(speed_value);}
+					int speed_value = getManualSpeedValue(shell, false);
+					if (speed_value > 0) {adapter.setUpSpeed(speed_value);}
 				}
 			});
 			
 			if (num_entries > 1) {
-				final MenuItem itemDownSpeedManualShared = new MenuItem(menuDownSpeed, SWT.PUSH);
-				Messages.setLanguageText(itemDownSpeedManualShared, isTorrentContext?"MyTorrentsView.menu.manual.shared_torrents":"MyTorrentsView.menu.manual.shared_peers");
-				itemDownSpeedManualShared.addSelectionListener(new SelectionAdapter() {
+				final MenuItem itemUpSpeedManualShared = new MenuItem(menuSpeed, SWT.PUSH);
+				Messages.setLanguageText(itemUpSpeedManualShared, isTorrentContext?"MyTorrentsView.menu.manual.shared_torrents":"MyTorrentsView.menu.manual.shared_peers" );
+				itemUpSpeedManualShared.addSelectionListener(new SelectionAdapter() {
 					public void widgetSelected(SelectionEvent e) {
-						int speed_value = getManualSharedSpeedValue(shell, true, num_entries);
-						if (speed_value > 0) {adapter.setDownSpeed(speed_value);}
+						int speed_value = getManualSharedSpeedValue(shell, false, num_entries);
+						if (speed_value > 0) {adapter.setUpSpeed(speed_value);}
 					}
 				});
 			}
 		}
+	}
+
+	public static void
+	addSpeedMenuDown(
+		final Shell 		shell,
+		Menu				menuSpeed,
+		boolean				isTorrentContext,
+		boolean				hasSelection,
+		boolean				downSpeedDisabled,
+		boolean				downSpeedUnlimited,
+		long				totalDownSpeed,
+		long				downSpeedSetMax,
+		long				maxDownload,
+		final int			num_entries,
+		Map<String,Object>	_properties,
+		final SpeedAdapter	adapter )
+	{
+		Map<String,Object>	properties = new HashMap<String, Object>( SM_DEFAULTS );
+		if ( _properties != null ){
+			properties.putAll( _properties );
+		}
 		
-		if ( doUpMenu ){
-			// advanced >Upload Speed Menu //
-			final MenuItem itemUpSpeed = new MenuItem(menuAdvanced, SWT.CASCADE);
-			Messages.setLanguageText(itemUpSpeed, "MyTorrentsView.menu.setUpSpeed"); //$NON-NLS-1$
-			Utils.setMenuItemImage(itemUpSpeed, "speed");
-	
-			final Menu menuUpSpeed = new Menu(shell, SWT.DROP_DOWN);
-			itemUpSpeed.setMenu(menuUpSpeed);
-	
-			final MenuItem itemCurrentUpSpeed = new MenuItem(menuUpSpeed, SWT.PUSH);
-			itemCurrentUpSpeed.setEnabled(false);
-			String separator = "";
+		String menu_key = "MyTorrentsView.menu.manual";
+		if (num_entries > 1) {menu_key += (isTorrentContext?".per_torrent":".per_peer" );}
+
+		if ( menuSpeed != null ){
+			final MenuItem itemCurrentDownSpeed = new MenuItem(menuSpeed, SWT.PUSH);
+			itemCurrentDownSpeed.setEnabled(false);
 			StringBuffer speedText = new StringBuffer();
-			//itemUpSpeed.                   
-			if (upSpeedDisabled) {
+			String separator = "";
+			//itemDownSpeed.                   
+			if (downSpeedDisabled) {
 				speedText.append(MessageText
 						.getString("MyTorrentsView.menu.setSpeed.disabled"));
 				separator = " / ";
 			}
-			if (upSpeedUnlimited) {
+			if (downSpeedUnlimited) {
 				speedText.append(separator);
 				speedText.append(MessageText
 						.getString("MyTorrentsView.menu.setSpeed.unlimited"));
 				separator = " / ";
 			}
-			if (totalUpSpeed > 0) {
+			if (totalDownSpeed > 0) {
 				speedText.append(separator);
 				speedText.append(DisplayFormatters
-						.formatByteCountToKiBEtcPerSec(totalUpSpeed));
+						.formatByteCountToKiBEtcPerSec(totalDownSpeed));
 			}
-			itemCurrentUpSpeed.setText(speedText.toString());
+			itemCurrentDownSpeed.setText(speedText.toString());
 	
-			// ---
-			new MenuItem(menuUpSpeed, SWT.SEPARATOR);
+			new MenuItem(menuSpeed, SWT.SEPARATOR);
 	
-			final MenuItem itemsUpSpeed[] = new MenuItem[12];
-			Listener itemsUpSpeedListener = new Listener() {
+			Listener itemsDownSpeedListener = new Listener() {
 				public void handleEvent(Event e) {
 					if (e.widget != null && e.widget instanceof MenuItem) {
 						MenuItem item = (MenuItem) e.widget;
-						int speed = item.getData("maxul") == null ? 0 : ((Integer) item
-								.getData("maxul")).intValue();
-						adapter.setUpSpeed(speed);
+						int speed = item.getData("maxdl") == null ? 0 : ((Integer) item
+								.getData("maxdl")).intValue();
+						adapter.setDownSpeed(speed);
 					}
 				}
 			};
 	
-			itemsUpSpeed[1] = new MenuItem(menuUpSpeed, SWT.PUSH);
-			Messages.setLanguageText(itemsUpSpeed[1],
-					"MyTorrentsView.menu.setSpeed.unlimit");
-			itemsUpSpeed[1].setData("maxul", new Integer(0));
-			itemsUpSpeed[1].addListener(SWT.Selection, itemsUpSpeedListener);
-	
+			if ( num_entries > 1 || !downSpeedUnlimited ){
+				MenuItem mi = new MenuItem(menuSpeed, SWT.PUSH);
+				Messages.setLanguageText(mi,
+						"MyTorrentsView.menu.setSpeed.unlimit");
+				mi.setData("maxdl", new Integer(0));
+				mi.addListener(SWT.Selection, itemsDownSpeedListener);
+			}
+			
+			boolean allowDisable = (Boolean)properties.get( SM_PROP_PERMIT_DOWNLOAD_DISABLE );
+
+			if ( allowDisable && !downSpeedDisabled ){
+				MenuItem mi = new MenuItem(menuSpeed, SWT.PUSH);
+				Messages.setLanguageText(mi,
+						"MyTorrentsView.menu.setSpeed.down.disable");
+				mi.setData("maxdl", new Integer(-1));
+				mi.addListener(SWT.Selection, itemsDownSpeedListener);
+			}
+			
 			if (hasSelection) {
-				//using 75KiB/s as the default limit when no limit set.
-				if (maxUpload == 0){
-					maxUpload = 75 * 1024;
-				}else{
-					if ( upSpeedSetMax == 0 ){
-						maxUpload = 200 * 1024;
+	
+				//using 200KiB/s as the default limit when no limit set.
+				if (maxDownload == 0){		
+					if ( downSpeedSetMax <= 0 ){
+						maxDownload = 200 * 1024;
 					}else{
-						maxUpload = 4 * ( upSpeedSetMax/1024 ) * 1024;
+						maxDownload	= 4 * ( downSpeedSetMax/1024 ) * 1024;
 					}
 				}
-				for (int i = 2; i < 12; i++) {
-					itemsUpSpeed[i] = new MenuItem(menuUpSpeed, SWT.PUSH);
-					itemsUpSpeed[i].addListener(SWT.Selection, itemsUpSpeedListener);
 	
-					int limit = (int)( maxUpload / (10 * num_entries) * (12 - i));
-					StringBuffer speed = new StringBuffer();
-					speed.append(DisplayFormatters.formatByteCountToKiBEtcPerSec(limit
-							* num_entries));
+				for (int i = 0; i < 10; i++) {
+					MenuItem mi = new MenuItem(menuSpeed, SWT.PUSH);
+					mi.addListener(SWT.Selection, itemsDownSpeedListener);
+		
+					// dms.length has to be > 0 when hasSelection
+					int limit = (int)(maxDownload / (10 * num_entries) * (10 - i));
+					String speed = DisplayFormatters.formatByteCountToKiBEtcPerSec(limit
+							* num_entries);
 					if (num_entries > 1) {
-						speed.append(" ");
-						speed.append(MessageText
-								.getString("MyTorrentsView.menu.setSpeed.in"));
-						speed.append(" ");
-						speed.append(num_entries);
-						speed.append(" ");
-						speed.append(MessageText
-								.getString("MyTorrentsView.menu.setSpeed.slots"));
-						speed.append(" ");
-						speed
-								.append(DisplayFormatters.formatByteCountToKiBEtcPerSec(limit));
+						speed = MessageText.getString("MyTorrentsView.menu.setSpeed.multi", new String[] {
+							speed,
+							String.valueOf(num_entries),
+							DisplayFormatters.formatByteCountToKiBEtcPerSec(limit)
+						});
 					}
-	
-					itemsUpSpeed[i].setText(speed.toString());
-					itemsUpSpeed[i].setData("maxul", new Integer(limit));
+					mi.setText(speed);
+					mi.setData("maxdl", new Integer(limit));
 				}
 			}
 	
-			new MenuItem(menuUpSpeed, SWT.SEPARATOR);
-	
-			final MenuItem itemUpSpeedManualSingle = new MenuItem(menuUpSpeed, SWT.PUSH);
-			Messages.setLanguageText(itemUpSpeedManualSingle, menu_key);
-			itemUpSpeedManualSingle.addSelectionListener(new SelectionAdapter() {
+			// ---
+			new MenuItem(menuSpeed, SWT.SEPARATOR);
+				
+			final MenuItem itemDownSpeedManualSingle = new MenuItem(menuSpeed, SWT.PUSH);
+			Messages.setLanguageText(itemDownSpeedManualSingle, menu_key);
+			itemDownSpeedManualSingle.addSelectionListener(new SelectionAdapter() {
 				public void widgetSelected(SelectionEvent e) {
-					int speed_value = getManualSpeedValue(shell, false);
-					if (speed_value > 0) {adapter.setUpSpeed(speed_value);}
+					int speed_value = getManualSpeedValue(shell, true);
+					if (speed_value > 0) {adapter.setDownSpeed(speed_value);}
 				}
 			});
 			
 			if (num_entries > 1) {
-				final MenuItem itemUpSpeedManualShared = new MenuItem(menuUpSpeed, SWT.PUSH);
-				Messages.setLanguageText(itemUpSpeedManualShared, isTorrentContext?"MyTorrentsView.menu.manual.shared_torrents":"MyTorrentsView.menu.manual.shared_peers" );
-				itemUpSpeedManualShared.addSelectionListener(new SelectionAdapter() {
+				final MenuItem itemDownSpeedManualShared = new MenuItem(menuSpeed, SWT.PUSH);
+				Messages.setLanguageText(itemDownSpeedManualShared, isTorrentContext?"MyTorrentsView.menu.manual.shared_torrents":"MyTorrentsView.menu.manual.shared_peers");
+				itemDownSpeedManualShared.addSelectionListener(new SelectionAdapter() {
 					public void widgetSelected(SelectionEvent e) {
-						int speed_value = getManualSharedSpeedValue(shell, false, num_entries);
-						if (speed_value > 0) {adapter.setUpSpeed(speed_value);}
+						int speed_value = getManualSharedSpeedValue(shell, true, num_entries);
+						if (speed_value > 0) {adapter.setDownSpeed(speed_value);}
 					}
 				});
 			}
 		}
 	}
-	
+
 	public static int getManualSpeedValue(Shell shell, boolean for_download) {
 		String kbps_str = MessageText.getString("MyTorrentsView.dialog.setNumber.inKbps",
 				new String[]{ DisplayFormatters.getRateUnit(DisplayFormatters.UNIT_KB ) });
@@ -551,44 +626,29 @@ ViewUtils
 		return result;
 	}
 	
-	public static boolean toolBarItemActivated( DownloadManager manager, ToolBarItem item, long activationType,
-			Object datasource) {
-		String itemKey = item.getID();
-
-		if (itemKey.equals("run")) {
-			ManagerUtils.run(manager);
-			return true;
-		}
-		
-		if (itemKey.equals("start")) {
-			ManagerUtils.queue(manager, null);
-			UIFunctionsManagerSWT.getUIFunctionsSWT().refreshIconBar();
-			return true;
+	public static void setViewRequiresOneDownload(Composite genComposite) {
+		if (genComposite == null || genComposite.isDisposed()) {
+			return;
 		}
-		
-		if (itemKey.equals("stop")) {
-			ManagerUtils.stop(manager, null);
-			UIFunctionsManagerSWT.getUIFunctionsSWT().refreshIconBar();
-			return true;
-		}
-		
-		if (itemKey.equals("remove")) {
-			TorrentUtil.removeDownloads(new DownloadManager[] {
-				manager
-			}, null);
-			return true;
+		Utils.disposeComposite(genComposite, false);
+
+		Label lab = new Label(genComposite, SWT.NULL);
+		GridData gridData = new GridData(SWT.CENTER, SWT.CENTER, true, true);
+		gridData.verticalIndent = 10;
+		lab.setLayoutData(gridData);
+		Messages.setLanguageText(lab, "view.one.download.only");
+
+		genComposite.layout(true);
+
+		Composite parent = genComposite.getParent();
+		if (parent instanceof ScrolledComposite) {
+			ScrolledComposite scrolled_comp = (ScrolledComposite) parent;
+			
+			Rectangle r = scrolled_comp.getClientArea();
+			scrolled_comp.setMinSize(genComposite.computeSize(r.width, SWT.DEFAULT ));
 		}
-		
-		return false;
-	}
 
-	public static void refreshToolBarItems( DownloadManager manager, Map<String, Long> list) {
-		list.put("run", UIToolBarItem.STATE_ENABLED);
-		list.put("start", ManagerUtils.isStartable(manager) ? UIToolBarItem.STATE_ENABLED : 0);
-		list.put("startstop", UIToolBarItem.STATE_ENABLED);
-		list.put("stop", ManagerUtils.isStopable(manager) ? UIToolBarItem.STATE_ENABLED : 0);
-		list.put("remove", UIToolBarItem.STATE_ENABLED);
-	}	
+	}
 	
 	public interface
 	SpeedAdapter
@@ -608,14 +668,12 @@ ViewUtils
 		public void
 		update(
 			Composite	composite,
-			boolean		seeding_view,
 			int			count,
 			int			active );
 			
 		public void
 		setEnabled(
 			Composite	composite,
-			boolean		seeding_view,
 			boolean		enabled );
 			
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsDataSource.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsDataSource.java
index b232bd7..ce36fe8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsDataSource.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsDataSource.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.clientstats;
 
 import java.util.HashMap;
@@ -22,10 +40,13 @@ public class ClientStatsDataSource
 	public long bytesDiscarded;
 
 	public long bytesSent;
+	
+	public Map<String, Map<String, Object>> perNetworkStats;
 
 	public ClientStatsOverall overall;
 
 	public ClientStatsDataSource() {
+		perNetworkStats =	new HashMap<String, Map<String, Object>>();
 	}
 
 	public ClientStatsDataSource(Map loadMap) {
@@ -34,6 +55,8 @@ public class ClientStatsDataSource
 		bytesReceived = MapUtils.getMapLong(loadMap, "bytesReceived", 0);
 		bytesDiscarded = MapUtils.getMapLong(loadMap, "bytesDiscarded", 0);
 		bytesSent = MapUtils.getMapLong(loadMap, "bytesSent", 0);
+		perNetworkStats = MapUtils.getMapMap(loadMap, "perNetworkStats",
+				new HashMap<String, Map<String, Object>>());
 	}
 
 	public Object toBencodeObject() {
@@ -43,6 +66,7 @@ public class ClientStatsDataSource
 		map.put("bytesReceived", Long.valueOf(bytesReceived));
 		map.put("bytesDiscarded", Long.valueOf(bytesDiscarded));
 		map.put("bytesSent", Long.valueOf(bytesSent));
+		map.put("perNetworkStats", perNetworkStats);
 		return map;
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsOverall.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsOverall.java
index 182ab68..272f269 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsOverall.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsOverall.java
@@ -1,10 +1,12 @@
 /**
  * Created on Oct 24, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsView.java
index 80478c1..21d2e8c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ClientStatsView.java
@@ -1,7 +1,24 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.clientstats;
 
 import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.List;
@@ -9,7 +26,6 @@ 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.download.DownloadManagerState;
@@ -17,9 +33,8 @@ 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.DisplayFormatters;
-import org.gudy.azureus2.core3.util.FileUtil;
-import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.core3.peer.impl.PEPeerTransport;
+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;
@@ -34,6 +49,7 @@ import org.gudy.azureus2.ui.swt.views.table.impl.TableViewTab;
 import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.peermanager.peerdb.PeerItem;
 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;
@@ -84,6 +100,8 @@ public class ClientStatsView
 
 	private int lastAddMonth;
 
+	private static boolean registered = false;
+
 	public ClientStatsView() {
 		super("ClientStats");
 
@@ -92,6 +110,7 @@ public class ClientStatsView
 		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
 			public void azureusCoreRunning(AzureusCore core) {
 				initColumns(core);
+				register(core);
 			}
 		});
 	}
@@ -166,12 +185,12 @@ public class ClientStatsView
 				sb.append(": ");
 
 				ClientStatsDataSource[] stats;
-				
-				synchronized( mapData ){
-					
+
+				synchronized (mapData) {
+
 					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) {
@@ -207,7 +226,7 @@ public class ClientStatsView
 						return v1 > v2 ? -1 : 1;
 					}
 				});
-				/*
+
 				int top = 5;
 				first = true;
 				sb.append("\nBest Seeders (");
@@ -311,7 +330,7 @@ public class ClientStatsView
 						break;
 					}
 				}
-				*/
+
 				ClipboardCopy.copyToClipBoard(sb.toString());
 			}
 		});
@@ -321,10 +340,9 @@ public class ClientStatsView
 	}
 
 	public TableViewSWT<ClientStatsDataSource> initYourTableView() {
-		tv = TableViewFactory.createTableViewSWT(
-				ClientStatsDataSource.class, TABLEID, getPropertiesPrefix(),
-				new TableColumnCore[0], ColumnCS_Count.COLUMN_ID, SWT.MULTI
-						| SWT.FULL_SELECTION | SWT.VIRTUAL);
+		tv = TableViewFactory.createTableViewSWT(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);
@@ -363,7 +381,6 @@ public class ClientStatsView
 						new ColumnCS_Count(column);
 					}
 				});
-		/*
 		tableManager.registerColumn(ClientStatsDataSource.class,
 				ColumnCS_Discarded.COLUMN_ID, new TableColumnCreationListener() {
 					public void tableColumnCreated(TableColumn column) {
@@ -388,40 +405,59 @@ public class ClientStatsView
 						new ColumnCS_Sent(column);
 					}
 				});
-		*/
 		tableManager.registerColumn(ClientStatsDataSource.class,
 				ColumnCS_Pct.COLUMN_ID, new TableColumnCreationListener() {
 					public void tableColumnCreated(TableColumn column) {
 						new ColumnCS_Pct(column);
 					}
 				});
-		
+
+		for (final String network : AENetworkClassifier.AT_NETWORKS) {
+			tableManager.registerColumn(ClientStatsDataSource.class, network + "."
+					+ ColumnCS_Sent.COLUMN_ID, new TableColumnCreationListener() {
+				public void tableColumnCreated(TableColumn column) {
+					column.setUserData("network", network);
+					new ColumnCS_Sent(column);
+				}
+			});
+			tableManager.registerColumn(ClientStatsDataSource.class, network + "."
+					+ ColumnCS_Discarded.COLUMN_ID, new TableColumnCreationListener() {
+				public void tableColumnCreated(TableColumn column) {
+					column.setUserData("network", network);
+					new ColumnCS_Discarded(column);
+				}
+			});
+			tableManager.registerColumn(ClientStatsDataSource.class, network + "."
+					+ ColumnCS_Received.COLUMN_ID, new TableColumnCreationListener() {
+				public void tableColumnCreated(TableColumn column) {
+					column.setUserData("network", network);
+					new ColumnCS_Received(column);
+				}
+			});
+			tableManager.registerColumn(ClientStatsDataSource.class, network + "."
+					+ ColumnCS_Count.COLUMN_ID, new TableColumnCreationListener() {
+				public void tableColumnCreated(TableColumn column) {
+					column.setUserData("network", network);
+					new ColumnCS_Count(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() {
 		synchronized (mapData) {
 			Map map = FileUtil.readResilientConfigFile(CONFIG_FILE);
@@ -499,12 +535,6 @@ public class ClientStatsView
 				tv.addDataSources(mapData.values().toArray(new ClientStatsDataSource[0]));
 			}
 		}
-		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
-
-			public void azureusCoreRunning(AzureusCore core) {
-				register(core);
-			}
-		});
 	}
 
 	protected void register(AzureusCore core) {
@@ -513,11 +543,24 @@ public class ClientStatsView
 		synchronized (mapData) {
 			startedListeningOn = SystemTime.getCurrentTime();
 		}
+		registered = true;
 	}
 
+	// @see org.gudy.azureus2.core3.global.GlobalManagerListener#destroyInitiated()
 	public void destroyInitiated() {
+		if (core == null) {
+			return;
+		}
+		core.getGlobalManager().removeListener(this);
+		List downloadManagers = core.getGlobalManager().getDownloadManagers();
+		for (Object object : downloadManagers) {
+			((DownloadManager) object).removePeerListener(this);
+		}
+		registered = false;
+		save(CONFIG_FILE);
 	}
 
+	// @see org.gudy.azureus2.core3.global.GlobalManagerListener#destroyed()
 	public void destroyed() {
 	}
 
@@ -566,18 +609,25 @@ public class ClientStatsView
 		// This captures more duplicates than peer id because most clients
 		// randomize their peer id on restart.  IP address, however, changes
 		// less often.
+		byte[] address = null;
 		byte[] peerId = peer.getId();
 		InetAddress ip = peer.getAlternativeIPv6();
 		if (ip == null) {
 			try {
-				ip = InetAddress.getByName(peer.getIp());
-			} catch (UnknownHostException e) {
+				ip = AddressUtils.getByName(peer.getIp());
+				address = ip.getAddress();
+			} catch (Throwable e) {
+				String ipString = peer.getIp();
+				if (ipString != null) {
+					address = ByteFormatter.intToByteArray(ipString.hashCode());
+				}
 			}
+		} else {
+			address = ip.getAddress();
 		}
-		if (ip == null) {
+		if (address == 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);
@@ -603,43 +653,120 @@ public class ClientStatsView
 							BloomFilterFactory.createAddOnly(BLOOMFILTER_PEERID_SIZE), 2);
 					overall = new ClientStatsOverall();
 					mapData.clear();
-					tv.removeAllTableRows();
+					if (tv != null) {
+						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);
+			ClientStatsDataSource stat;
+			stat = mapData.get(id);
 			boolean needNew = stat == null;
 			if (needNew) {
 				stat = new ClientStatsDataSource();
 				stat.overall = overall;
+				stat.client = id;
 				mapData.put(id, stat);
 			}
 
-			overall.count++;
+			boolean inBloomFilter = bloomFilter.contains(bloomId) || bloomFilterPeerId.contains(peerId);
+
+			if (!inBloomFilter) {
+				bloomFilter.add(bloomId);
+				bloomFilterPeerId.add(peerId);
+				
+				lastAdd = now;
+				synchronized (overall) {
+					
+					overall.count++;
+				}
+				stat.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();
+
+			long existingBytesReceived = peer.getStats().getTotalDataBytesReceived();
+			long existingBytesSent = peer.getStats().getTotalDataBytesSent();
+			long existingBytesDiscarded = peer.getStats().getTotalBytesDiscarded();
+
+			if (existingBytesReceived > 0) {
+				stat.bytesReceived -= existingBytesReceived;
+				if (stat.bytesReceived < 0) {
+					stat.bytesReceived = 0;
+				}
+			}
+			if (existingBytesSent > 0) {
+				stat.bytesSent -= existingBytesSent;
+				if (stat.bytesSent < 0) {
+					stat.bytesSent = 0;
+				}
+			}
+			if (existingBytesDiscarded > 0) {
+				stat.bytesDiscarded -= existingBytesDiscarded;
+				if (stat.bytesDiscarded < 0) {
+					stat.bytesDiscarded = 0;
+				}
+			}
+
+			if (peer instanceof PEPeerTransport) {
+				PeerItem identity = ((PEPeerTransport) peer).getPeerItemIdentity();
+				if (identity != null) {
+					String network = identity.getNetwork();
+					if (network != null) {
+						Map<String, Object> map = stat.perNetworkStats.get(network);
+						if (map == null) {
+							map = new HashMap<String, Object>();
+							stat.perNetworkStats.put(network, map);
+						}
+						if (!inBloomFilter) {
+  						long count = MapUtils.getMapLong(map, "count", 0);
+  						map.put("count", count + 1);
+						}
+
+						if (existingBytesReceived > 0) {
+							long bytesReceived = MapUtils.getMapLong(map, "bytesReceived",
+									0);
+							bytesReceived -= existingBytesReceived;
+							if (bytesReceived < 0) {
+								bytesReceived = 0;
+							}
+							map.put("bytesReceived", bytesReceived);
+						}
+						if (existingBytesSent > 0) {
+							long bytesSent = MapUtils.getMapLong(map, "bytesSent", 0);
+							bytesSent -= existingBytesSent;
+							if (bytesSent < 0) {
+								bytesSent = 0;
+							}
+							map.put("bytesSent", bytesSent);
+						}
+						if (existingBytesDiscarded > 0) {
+							long bytesDiscarded = MapUtils.getMapLong(map,
+									"bytesDiscarded", 0);
+							bytesDiscarded -= existingBytesDiscarded;
+							if (bytesDiscarded < 0) {
+								bytesDiscarded = 0;
+							}
+							map.put("bytesDiscarded", bytesDiscarded);
+						}
+
+					}
 				}
 			}
+
+			if (tv != null) {
+  			if (needNew) {
+  				tv.addDataSource(stat);
+  			} else {
+  				TableRowCore row = tv.getRow(stat);
+  				if (row != null) {
+  					row.invalidate();
+  				}
+  			}
+			}
 		}
 	}
 
@@ -655,22 +782,58 @@ public class ClientStatsView
 	public void peerRemoved(PEPeer peer) {
 		synchronized (mapData) {
 			ClientStatsDataSource stat = mapData.get(getID(peer));
+			if (peer.getStats().getTotalDataBytesSent() > 0)
 			if (stat != null) {
 				stat.current--;
+
+				String network = null;
+				if (peer instanceof PEPeerTransport) {
+					PeerItem identity = ((PEPeerTransport) peer).getPeerItemIdentity();
+					if (identity != null) {
+						network = identity.getNetwork();
+					}
+				}
+				
+
 				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();
+				if (network != null) {
+					Map<String, Object> map = stat.perNetworkStats.get(network);
+					if (map == null) {
+						map = new HashMap<String, Object>();
+						stat.perNetworkStats.put(network, map);
+					}
+					long bytesReceived = MapUtils.getMapLong(map, "bytesReceived", 0);
+					map.put("bytesReceived", bytesReceived
+							+ peer.getStats().getTotalDataBytesReceived());
+					long bytesSent = MapUtils.getMapLong(map, "bytesSent", 0);
+					map.put("bytesSent", bytesSent
+							+ peer.getStats().getTotalDataBytesSent());
+					long bytesDiscarded = MapUtils.getMapLong(map, "bytesDiscarded", 0);
+					map.put("bytesDiscarded", bytesDiscarded
+							+ peer.getStats().getTotalBytesDiscarded());
+				}
+
+				if (tv != null) {
+  				TableRowCore row = tv.getRow(stat);
+  				if (row != null) {
+  					row.invalidate();
+  				}
 				}
 			}
 		}
 	}
 
 	private String getID(PEPeer peer) {
-		String s = peer.getClient();
+		String s = peer.getClientNameFromPeerID();
+		if (s == null) {
+			s = peer.getClient();
+			if (s.startsWith("HTTP Seed")) {
+				return "HTTP Seed";
+			}
+		}
 		return s.replaceAll(" v?[0-9._]+", "");
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Count.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Count.java
index 3a1f94f..8a43cdb 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Count.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Count.java
@@ -1,7 +1,30 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.clientstats;
 
+import java.util.Map;
+
+import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.plugins.ui.tables.*;
 
+import com.aelitis.azureus.util.MapUtils;
+
 public class ColumnCS_Count
 	implements TableCellRefreshListener
 {
@@ -12,6 +35,13 @@ public class ColumnCS_Count
 		column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 50);
 		column.addListeners(this);
 		column.setType(TableColumn.TYPE_TEXT_ONLY);
+		
+		Object network = column.getUserDataString("network");
+		if (network != null) {
+			column.setVisible(false);
+			column.setNameOverride(network + " "
+					+ MessageText.getString("ClientStats.column." + COLUMN_ID));
+		}
 	}
 
 	public void refresh(TableCell cell) {
@@ -20,6 +50,18 @@ public class ColumnCS_Count
 			return;
 		}
 		long val = ds.count;
+		TableColumn column = cell.getTableColumn();
+		if (column != null) {
+			Object network = column.getUserDataString("network");
+			if (network != null) {
+				Map<String, Object> map = ds.perNetworkStats.get(network);
+				if (map != null) {
+					val = MapUtils.getMapLong(map, "count", 0);
+				} else {
+					val = 0;
+				}
+			}
+		}
 		if (cell.setSortValue(val) || !cell.isValid()) {
 			cell.setText(Long.toString(val));
 		}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Discarded.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Discarded.java
index 232704f..c6ea36a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Discarded.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Discarded.java
@@ -1,10 +1,33 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.clientstats;
 
+import java.util.Map;
+
+import org.gudy.azureus2.core3.internat.MessageText;
 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.util.MapUtils;
+
 public class ColumnCS_Discarded
 	implements TableCellRefreshListener
 {
@@ -15,6 +38,12 @@ public class ColumnCS_Discarded
 		column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80);
 		column.addListeners(this);
 		column.setType(TableColumn.TYPE_TEXT_ONLY);
+		String network = column.getUserDataString("network");
+		if (network != null) {
+			column.setVisible(false);
+			column.setNameOverride(network + " "
+					+ MessageText.getString("ClientStats.column." + COLUMN_ID));
+		}
 	}
 
 	public void refresh(TableCell cell) {
@@ -23,6 +52,18 @@ public class ColumnCS_Discarded
 			return;
 		}
 		long val = ds.bytesDiscarded;
+		TableColumn column = cell.getTableColumn();
+		if (column != null) {
+			String network = column.getUserDataString("network");
+			if (network != null) {
+				Map<String, Object> map = ds.perNetworkStats.get(network);
+				if (map != null) {
+					val = MapUtils.getMapLong(map, "bytesDiscarded", 0);
+				} else {
+					val = 0;
+				}
+			}
+		}
 		if (cell.setSortValue(val) || !cell.isValid()) {
 			cell.setText(DisplayFormatters.formatByteCountToKiBEtc(val));
 		}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Name.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Name.java
index 6dce82d..d057c10 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Name.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Name.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.clientstats;
 
 import org.gudy.azureus2.plugins.ui.tables.TableCell;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Pct.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Pct.java
index 25fa92d..b530773 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Pct.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Pct.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.clientstats;
 
 import org.gudy.azureus2.core3.util.DisplayFormatters;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Received.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Received.java
index e205461..899510c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Received.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Received.java
@@ -1,10 +1,33 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.clientstats;
 
+import java.util.Map;
+
+import org.gudy.azureus2.core3.internat.MessageText;
 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.util.MapUtils;
+
 public class ColumnCS_Received
 	implements TableCellRefreshListener
 {
@@ -15,6 +38,12 @@ public class ColumnCS_Received
 		column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80);
 		column.addListeners(this);
 		column.setType(TableColumn.TYPE_TEXT_ONLY);
+		String network = column.getUserDataString("network");
+		if (network != null) {
+			column.setVisible(false);
+			column.setNameOverride(network + " "
+					+ MessageText.getString("ClientStats.column." + COLUMN_ID));
+		}
 	}
 
 	public void refresh(TableCell cell) {
@@ -23,6 +52,18 @@ public class ColumnCS_Received
 			return;
 		}
 		long val = ds.bytesReceived;
+		TableColumn column = cell.getTableColumn();
+		if (column != null) {
+			String network = column.getUserDataString("network");
+			if (network != null) {
+				Map<String, Object> map = ds.perNetworkStats.get(network);
+				if (map != null) {
+					val = MapUtils.getMapLong(map, "bytesReceived", 0);
+				} else {
+					val = 0;
+				}
+			}
+		}
 		if (cell.setSortValue(val) || !cell.isValid()) {
 			cell.setText(DisplayFormatters.formatByteCountToKiBEtc(val));
 		}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_ReceivedPer.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_ReceivedPer.java
index 1b18967..371eeb3 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_ReceivedPer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_ReceivedPer.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.clientstats;
 
 import org.gudy.azureus2.core3.util.DisplayFormatters;
@@ -19,7 +37,7 @@ public class ColumnCS_ReceivedPer
 
 	public void refresh(TableCell cell) {
 		ClientStatsDataSource ds = (ClientStatsDataSource) cell.getDataSource();
-		if (ds == null) {
+		if (ds == null || ds.count == 0) {
 			return;
 		}
 		long val = ds.bytesReceived / ds.count;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Sent.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Sent.java
index b605370..5ac0832 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Sent.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/clientstats/ColumnCS_Sent.java
@@ -1,10 +1,33 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.clientstats;
 
+import java.util.Map;
+
+import org.gudy.azureus2.core3.internat.MessageText;
 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.util.MapUtils;
+
 public class ColumnCS_Sent
 	implements TableCellRefreshListener
 {
@@ -15,6 +38,12 @@ public class ColumnCS_Sent
 		column.initialize(TableColumn.ALIGN_TRAIL, TableColumn.POSITION_LAST, 80);
 		column.addListeners(this);
 		column.setType(TableColumn.TYPE_TEXT_ONLY);
+		String network = column.getUserDataString("network");
+		if (network != null) {
+			column.setVisible(false);
+			column.setNameOverride(network + " "
+					+ MessageText.getString("ClientStats.column." + COLUMN_ID));
+		}
 	}
 
 	public void refresh(TableCell cell) {
@@ -23,6 +52,19 @@ public class ColumnCS_Sent
 			return;
 		}
 		long val = ds.bytesSent;
+
+		TableColumn column = cell.getTableColumn();
+		if (column != null) {
+			String network = column.getUserDataString("network");
+			if (network != null) {
+				Map<String, Object> map = ds.perNetworkStats.get(network);
+				if (map != null) {
+					val = MapUtils.getMapLong(map, "bytesSent", 0);
+				} else {
+					val = 0;
+				}
+			}
+		}
 		if (cell.setSortValue(val) || !cell.isValid()) {
 			cell.setText(DisplayFormatters.formatByteCountToKiBEtc(val));
 		}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_ChosenColumn.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_ChosenColumn.java
index 1d9cb62..8dabb03 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_ChosenColumn.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_ChosenColumn.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 3, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -57,6 +59,7 @@ public class ColumnTC_ChosenColumn
 		String s = MessageText.getString(key, column.getName());
 		//s = column.getPosition() + "] " + s;
 		cell.setText(s);
-		cell.setToolTip("");
+		String info = MessageText.getString(key + ".info", "");
+		cell.setToolTip(info);
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_Info.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_Info.java
index cc41c36..6725496 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_Info.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_Info.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 3, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_NameInfo.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_NameInfo.java
index 6d4e80c..1256ea8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_NameInfo.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_NameInfo.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 3, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_Sample.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_Sample.java
index 263b017..fc06910 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_Sample.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/ColumnTC_Sample.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 3, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/TableColumnSetupWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/TableColumnSetupWindow.java
index 74b084b..873ac7e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/TableColumnSetupWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/columnsetup/TableColumnSetupWindow.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 3, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -28,7 +30,6 @@ import org.eclipse.swt.graphics.GC;
 import org.eclipse.swt.graphics.Rectangle;
 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.AERunnable;
@@ -49,6 +50,7 @@ import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdatable;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
 import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT;
+import com.aelitis.azureus.ui.swt.utils.FontUtils;
 
 /**
  * @author TuxPaper
@@ -919,15 +921,25 @@ public class TableColumnSetupWindow
 	 * @since 4.0.0.5
 	 */
 	protected void apply() {
+		TableColumnManager tcm = TableColumnManager.getInstance();
+		if (doReset) {
+			TableColumnCore[] allTableColumns = tcm.getAllTableColumnCoreAsArray(
+					forDataSourceType, forTableID);
+			if (allTableColumns != null) {
+				for (TableColumnCore column : allTableColumns) {
+					if (column != null) {
+						column.reset();
+					}
+				}
+			}
+		}
+
 		for (TableColumnCore tc : mapNewVisibility.keySet()) {
 			boolean visible = mapNewVisibility.get(tc).booleanValue();
 			tc.setVisible(visible);
-			if (doReset) {
-				tc.reset();
-			}
 		}
-		TableColumnManager.getInstance().saveTableColumns(forDataSourceType,
-				forTableID);
+
+		tcm.saveTableColumns(forDataSourceType, forTableID);
 		listener.tableStructureChanged(true, forDataSourceType);
 	}
 
@@ -1099,7 +1111,9 @@ public class TableColumnSetupWindow
 						| SWT.SINGLE);
 		tvAvail.setParentDataSource(this);
 		tvAvail.setMenuEnabled(false);
-		tvAvail.setRowDefaultHeight(65);
+		
+		int fontHeightInPX = FontUtils.getFontHeightInPX(shell.getFont());
+		tvAvail.setRowDefaultHeight(fontHeightInPX * 5);
 
 		tvAvail.addLifeCycleListener(new TableLifeCycleListener() {
 			private DragSource dragSource;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionBackupRestore.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionBackupRestore.java
index 3c272d5..0c87d20 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionBackupRestore.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionBackupRestore.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
@@ -46,6 +44,7 @@ import org.gudy.azureus2.ui.swt.config.BooleanParameter;
 import org.gudy.azureus2.ui.swt.config.ChangeSelectionActionPerformer;
 import org.gudy.azureus2.ui.swt.config.IntParameter;
 import org.gudy.azureus2.ui.swt.config.StringParameter;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
 import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
@@ -115,7 +114,7 @@ public class ConfigSectionBackupRestore implements UISWTConfigSection {
 		linkLabel.setData("http://wiki.vuze.com/w/Backup_And_Restore");
 		linkLabel.setCursor(linkLabel.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
 		linkLabel.setForeground(Colors.blue);
-    gridData = Utils.getWrappableLabelGridData(1, 0);
+		gridData = Utils.getWrappableLabelGridData(1, 0);
 		linkLabel.setLayoutData(gridData);
 		linkLabel.addMouseListener(new MouseAdapter() {
 			public void mouseDoubleClick(MouseEvent arg0) {
@@ -126,6 +125,7 @@ public class ConfigSectionBackupRestore implements UISWTConfigSection {
 				Utils.launch((String) ((Label) arg0.widget).getData());
 			}
 		});
+		ClipboardCopy.addCopyToClipMenu( linkLabel );
 		
 	    final BackupManager	backup_manager = BackupManagerFactory.getManager( AzureusCoreFactory.getSingleton());
 	    
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java
index fdc00d9..243eb92 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnection.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
@@ -39,6 +37,7 @@ import org.gudy.azureus2.core3.util.Constants;
 import org.gudy.azureus2.plugins.ui.config.ConfigSection;
 import org.gudy.azureus2.ui.swt.components.LinkLabel;
 import org.gudy.azureus2.ui.swt.config.*;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
 import org.gudy.azureus2.ui.swt.Messages;
@@ -316,6 +315,7 @@ public class ConfigSectionConnection implements UISWTConfigSection {
 					Utils.launch((String) ((Label) arg0.widget).getData());
 				}
 			});
+			ClipboardCopy.addCopyToClipMenu( linkLabel );
 		}
 
 		if (userMode > 0) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java
index 4a335c1..bdb7047 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionAdvanced.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionDNS.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionDNS.java
index 0e0854b..0201a7a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionDNS.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionDNS.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionEncryption.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionEncryption.java
index 3d1a057..9ec4bf8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionEncryption.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionEncryption.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionProxy.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionProxy.java
index e7e1e26..a8a5a88 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionProxy.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionConnectionProxy.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.configsections;
@@ -115,7 +113,7 @@ public class ConfigSectionConnectionProxy implements UISWTConfigSection {
 		
 		Group gProxyTracker = new Group(cSection, SWT.NULL);
 		Messages.setLanguageText(gProxyTracker, CFG_PREFIX + "group.tracker");
-		gridData = new GridData();
+		gridData = new GridData(GridData.FILL_HORIZONTAL);
 		gridData.horizontalSpan = 2;
 		gProxyTracker.setLayoutData(gridData);
 		layout = new GridLayout();
@@ -162,6 +160,12 @@ public class ConfigSectionConnectionProxy implements UISWTConfigSection {
 		gridData.widthHint = 105;
 		pPass.setLayoutData(gridData);
 
+		final BooleanParameter trackerDNSKill = new BooleanParameter(gProxyTracker,
+				"Proxy.SOCKS.Tracker.DNS.Disable", CFG_PREFIX + "no.local.dns");
+		gridData = new GridData();
+		gridData.horizontalSpan = 2;
+		trackerDNSKill.setLayoutData(gridData);
+		
 		final NetworkAdminSocksProxy[]	test_proxy = { null };
 		
 		final Button test_socks = new Button(gProxyTracker, SWT.PUSH);
@@ -257,7 +261,7 @@ public class ConfigSectionConnectionProxy implements UISWTConfigSection {
 			}
 		});
 		
-		Parameter[] socks_params = { enableProxy, enableSocks, pHost, pPort, pUser, pPass };
+		Parameter[] socks_params = { enableProxy, enableSocks, pHost, pPort, pUser, pPass, trackerDNSKill };
 		
 		ParameterChangeAdapter socks_adapter = 
 			new ParameterChangeAdapter()
@@ -280,6 +284,12 @@ public class ConfigSectionConnectionProxy implements UISWTConfigSection {
 								pHost.getValue().trim().length() > 0 &&
 								pPort.getValue().trim().length() > 0;
 							
+							boolean 	socks_enabled = 
+										enableProxy.isSelected() && 
+										enableSocks.isSelected();
+							
+							trackerDNSKill.setEnabled( socks_enabled )
+							;
 							if ( enabled ){
 								
 								try{
@@ -339,7 +349,7 @@ public class ConfigSectionConnectionProxy implements UISWTConfigSection {
 		
 		Group gProxyPeer = new Group(cSection, SWT.NULL);
 		Messages.setLanguageText(gProxyPeer, CFG_PREFIX + "group.peer");
-		gridData = new GridData();
+		gridData = new GridData(GridData.FILL_HORIZONTAL);
 		gridData.horizontalSpan = 2;
 		gProxyPeer.setLayoutData(gridData);
 		layout = new GridLayout();
@@ -410,7 +420,7 @@ public class ConfigSectionConnectionProxy implements UISWTConfigSection {
 
 		final Control[] proxy_controls = new Control[] { enableSocks.getControl(),
 				lHost, pHost.getControl(), lPort, pPort.getControl(), lUser,
-				pUser.getControl(), lPass, pPass.getControl(), };
+				pUser.getControl(), lPass, pPass.getControl() };
 
 		IAdditionalActionPerformer proxy_enabler = new GenericActionPerformer(
 				new Control[] {}) {
@@ -461,6 +471,15 @@ public class ConfigSectionConnectionProxy implements UISWTConfigSection {
 		gridData.widthHint = 200;  // needed for wrap
 		label.setLayoutData(gridData);
 		
+			// disable plugin proxies
+			
+		final BooleanParameter disablepps = new BooleanParameter(cSection,
+				"Proxy.SOCKS.disable.plugin.proxies", CFG_PREFIX + "disable.plugin.proxies");
+		gridData = new GridData();
+		gridData.horizontalSpan = 2;
+		disablepps.setLayoutData(gridData);
+
+	
 			// check on start
 		
 		final BooleanParameter checkOnStart = new BooleanParameter(cSection,
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFile.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFile.java
index 62908ec..3ba2d10 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFile.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFile.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
@@ -32,9 +30,11 @@ import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.layout.RowLayout;
 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.StringList;
 import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults;
+import org.gudy.azureus2.core3.config.impl.StringListImpl;
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.torrent.TOTorrent;
 import org.gudy.azureus2.core3.util.Constants;
@@ -93,7 +93,7 @@ public class ConfigSectionFile
 		int userMode = COConfigurationManager.getIntParameter("User Mode");
 
 		// Default Dir Section
-		Group gDefaultDir = new Group(gFile, SWT.NONE);
+		final Group gDefaultDir = new Group(gFile, SWT.NONE);
 		Messages.setLanguageText(gDefaultDir,
 				"ConfigView.section.file.defaultdir.section");
 		layout = new GridLayout();
@@ -182,32 +182,121 @@ public class ConfigSectionFile
 			gridData = new GridData(GridData.FILL_HORIZONTAL);
 			gridData.horizontalSpan = 3;
 			autoSaveAutoRename.setLayoutData(gridData);
-			IAdditionalActionPerformer aapDefaultDirStuff3 = new ChangeSelectionActionPerformer(
-					autoSaveAutoRename.getControls(), false);
+			//IAdditionalActionPerformer aapDefaultDirStuff3 = new ChangeSelectionActionPerformer(
+			//		autoSaveAutoRename.getControls(), false);
 
 			// def dir: best guess
 			sCurConfigID = "DefaultDir.BestGuess";
 			allConfigIDs.add(sCurConfigID);
-			BooleanParameter bestGuess = new BooleanParameter(gDefaultDir,
+			final BooleanParameter bestGuess = new BooleanParameter(gDefaultDir,
 					sCurConfigID, "ConfigView.section.file.defaultdir.bestguess");
 			gridData = new GridData(GridData.FILL_HORIZONTAL);
 			gridData.horizontalSpan = 3;
 			bestGuess.setLayoutData(gridData);
 
-			IAdditionalActionPerformer aapDefaultDirStuff = new ChangeSelectionActionPerformer(
-					bestGuess.getControls(), true);
+				// best guess default dir
+			sCurConfigID = "DefaultDir.BestGuess.Default";
+			allConfigIDs.add(sCurConfigID);
+			final Label lblBestGuessDefaultDir = new Label(gDefaultDir, SWT.NONE);
+			Messages.setLanguageText(lblBestGuessDefaultDir,
+					"ConfigView.section.file.bgdefaultdir.ask");
+			gridData = new GridData();
+			gridData.horizontalIndent=25;
+			lblBestGuessDefaultDir.setLayoutData(gridData);
 
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			final StringParameter bestGuessPathParameter = new StringParameter(gDefaultDir,
+					sCurConfigID);
+			bestGuessPathParameter.setLayoutData(gridData);
+
+			final Button bestGuessBrowse = new Button(gDefaultDir, SWT.PUSH);
+			bestGuessBrowse.setImage(imgOpenFolder);
+			bestGuessBrowse.setToolTipText(MessageText.getString("ConfigView.button.browse"));
+
+			bestGuessBrowse.addListener(SWT.Selection, new Listener() {
+				/* (non-Javadoc)
+				 * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
+				 */
+				public void handleEvent(Event event) {
+					DirectoryDialog dialog = new DirectoryDialog(parent.getShell(),
+							SWT.APPLICATION_MODAL);
+					dialog.setFilterPath(pathParameter.getValue());
+					dialog.setMessage(MessageText.getString("ConfigView.dialog.choosedefaultsavepath"));
+					dialog.setText(MessageText.getString("ConfigView.section.file.defaultdir.ask"));
+					String path = dialog.open();
+					if (path != null) {
+						bestGuessPathParameter.setValue(path);
+					}
+				}
+			});
+						
+			COConfigurationManager.addAndFireParameterListener(
+					"Default save path",
+					new ParameterListener() {
+						
+						public void parameterChanged(String parameterName) {
+						
+							if ( gDefaultDir.isDisposed()){
+								
+								COConfigurationManager.removeParameterListener(parameterName, this );
+								
+							}else{
+								
+								String dsp = COConfigurationManager.getStringParameter( parameterName );
+								
+								boolean enable = dsp == null || dsp.trim().length() == 0;
+								
+								bestGuess.setEnabled( enable );
+								lblBestGuessDefaultDir.setEnabled( enable );
+								bestGuessPathParameter.setEnabled( enable );
+								bestGuessBrowse.setEnabled( enable );
+							}
+						}
+					});
+			
+			final Composite cHistory = new Composite(gDefaultDir, SWT.NONE);
+		
+			layout = new GridLayout();
+			layout.numColumns = 6;
+			//layout.marginHeight = 2;
+			cHistory.setLayout(layout);
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			gridData.horizontalSpan = 3;
+			cHistory.setLayoutData(gridData);
+			
 			// def dir: auto update
 			sCurConfigID = "DefaultDir.AutoUpdate";
 			allConfigIDs.add(sCurConfigID);
-			BooleanParameter autoUpdateSaveDir = new BooleanParameter(gDefaultDir,
+			BooleanParameter autoUpdateSaveDir = new BooleanParameter(cHistory,
 					sCurConfigID, "ConfigView.section.file.defaultdir.lastused");
+			
+			Label padLabel = new Label( cHistory, SWT.NULL );
 			gridData = new GridData(GridData.FILL_HORIZONTAL);
-			gridData.horizontalSpan = 3;
-			autoUpdateSaveDir.setLayoutData(gridData);
+			padLabel.setLayoutData(gridData);
+			
+			sCurConfigID = "saveTo_list.max_entries";
+			allConfigIDs.add(sCurConfigID);
+			Label historyMax = new Label(cHistory, SWT.NULL);
+			Messages.setLanguageText(historyMax,"ConfigView.label.save_list.max_entries");
+
+			IntParameter paramhistoryMax = new IntParameter(cHistory,	sCurConfigID);
+			
+			Label historyReset = new Label(cHistory, SWT.NULL);
+			Messages.setLanguageText(historyReset,"ConfigView.label.save_list.clear");
 
-			IAdditionalActionPerformer aapDefaultDirStuff2 = new ChangeSelectionActionPerformer(
-					autoUpdateSaveDir.getControls(), true);
+			final Button clear_history_button = new Button(cHistory, SWT.PUSH);
+			Messages.setLanguageText(clear_history_button, "Button.clear" );
+			
+			clear_history_button.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					COConfigurationManager.setParameter("saveTo_list", new StringListImpl());
+					clear_history_button.setEnabled( false );
+				}
+			});
+			
+			StringList dirList = COConfigurationManager.getStringListParameter("saveTo_list");
+			
+			clear_history_button.setEnabled( dirList.size() > 0 );
 		}
 
 		new Label(gFile, SWT.NONE);
@@ -309,6 +398,8 @@ public class ConfigSectionFile
 					btnZeroNew));
 		}
 
+			// truncate too large
+		
 		sCurConfigID = "File.truncate.if.too.large";
 		allConfigIDs.add(sCurConfigID);
 		if (userMode > 0) {
@@ -320,6 +411,21 @@ public class ConfigSectionFile
 			truncateLarge.setLayoutData(gridData);
 		}
 
+			// merge files of same size
+		
+		sCurConfigID = "Merge Same Size Files";
+		allConfigIDs.add(sCurConfigID);
+		if (userMode > 0) {
+			// truncate too large
+			BooleanParameter mergeSameSize = new BooleanParameter(gFile,
+					sCurConfigID, "ConfigView.section.file.merge.same.size");
+			gridData = new GridData();
+			gridData.horizontalSpan = 2;
+			mergeSameSize.setLayoutData(gridData);
+		}
+		
+			// recheck on complete
+		
 		sCurConfigID = "Check Pieces on Completion";
 		allConfigIDs.add(sCurConfigID);
 		if (userMode > 0) {
@@ -519,7 +625,7 @@ public class ConfigSectionFile
 
 		sCurConfigID = "quick.view.maxkb";
 		allConfigIDs.add(sCurConfigID);
-		IntParameter qvmax = new IntParameter(cQuickView, sCurConfigID, 1, 2048 );
+		IntParameter qvmax = new IntParameter(cQuickView, sCurConfigID, 1, 9999 );
 		
 		
 		// rename incomplete
@@ -571,6 +677,14 @@ public class ConfigSectionFile
 					subfolder_name.getControls(), false);
 			enable_subfolder.setAdditionalActionPerformer(subfolderAP);
 			
+				// torrent add auto-skip file types
+			
+			Label lSkipFiles = new Label(gFile, SWT.NULL);
+			Messages.setLanguageText(lSkipFiles,
+					"ConfigView.section.file.torrent.autoskipfiles");
+
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			new StringParameter(gFile, "File.Torrent.AutoSkipExtensions").setLayoutData(gridData);
 			
 				// torrent create/delete ignore files 
 			
@@ -584,6 +698,8 @@ public class ConfigSectionFile
 
 		}
 
+			// File Deletetion Group
+		
 		Group gDeletion = new Group(gFile, SWT.NONE);
 		Messages.setLanguageText(gDeletion,
 				"ConfigView.section.file.deletion.section");
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileMove.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileMove.java
index c29a83c..55255a6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileMove.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileMove.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFilePerformance.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFilePerformance.java
index cddb3c8..0177ad9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFilePerformance.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFilePerformance.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrents.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrents.java
index b187a97..80a1f6e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrents.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrents.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
@@ -83,8 +81,8 @@ public class ConfigSectionFileTorrents implements UISWTConfigSection {
     
     int userMode = COConfigurationManager.getIntParameter("User Mode");
     
+    	// Save .Torrent files to..
     
-    // Save .Torrent files to..
     BooleanParameter saveTorrents = new BooleanParameter(cTorrent, "Save Torrent Files",
                                                          "ConfigView.label.savetorrents");
 
@@ -137,6 +135,14 @@ public class ConfigSectionFileTorrents implements UISWTConfigSection {
     IAdditionalActionPerformer grayPathAndButton1 = new ChangeSelectionActionPerformer(controls);
     saveTorrents.setAdditionalActionPerformer(grayPathAndButton1);
 
+   		// Delete .Torrent files
+    
+    BooleanParameter deleteTorrents = new BooleanParameter(cTorrent, "Delete Original Torrent Files",
+                                                         "ConfigView.label.deletetorrents");
+
+    
+    	// add stopped
+    
     gridData = new GridData();
     gridData.horizontalSpan = 2;
     BooleanParameter add_stopped = new BooleanParameter(
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrentsDecoding.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrentsDecoding.java
index c14e7fa..a2bf525 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrentsDecoding.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionFileTorrentsDecoding.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionIPFilter.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionIPFilter.java
index ba46ede..fb4cb54 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionIPFilter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionIPFilter.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterface.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterface.java
index d4a8e79..fdd45c7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterface.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterface.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceAlerts.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceAlerts.java
index 9941372..85442d7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceAlerts.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceAlerts.java
@@ -3,11 +3,12 @@
  * Created : Dec 4, 2006
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceColor.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceColor.java
index ea163ab..df244c8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceColor.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceColor.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,18 +18,17 @@
  * 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.configsections;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
 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.plugins.ui.config.ConfigSection;
 import org.gudy.azureus2.ui.swt.Messages;
@@ -112,7 +112,7 @@ public class ConfigSectionInterfaceColor implements UISWTConfigSection {
 			ColorParameter colorParm = new ColorParameter(cColorOverride, sConfigID,
 					colorsToOverride[i].getRed(), colorsToOverride[i].getGreen(),
 					colorsToOverride[i].getBlue()) {
-				public void newColorChosen() {
+				public void newColorChosen(RGB newColor) {
 					COConfigurationManager.setParameter(sParamName + ".override", true);
 					for (int i = 0; i < sColorsToOverride.length; i++) {
 						if (sParamName.equals("Colors." + sColorsToOverride[i])) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceDisplay.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceDisplay.java
index 7b4edf0..80749a2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceDisplay.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceDisplay.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
@@ -265,7 +263,8 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 		
 			// external browser
 			
-		if( userMode > 0 ) {
+		if( userMode > 0 ){
+			
 			Group gExternalBrowser = new Group(cSection, SWT.NULL);
 			layout = new GridLayout();
 			layout.numColumns = 1;
@@ -273,11 +272,12 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 			gExternalBrowser.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 			
 			gExternalBrowser.setText( MessageText.getString( "config.external.browser" ));
-			
-			label = new Label(gExternalBrowser, SWT.NULL);
+			label = new Label(gExternalBrowser, SWT.WRAP);
 			Messages.setLanguageText(label, "config.external.browser.info1");
-			label = new Label(gExternalBrowser, SWT.NULL);
+			label.setLayoutData(Utils.getWrappableLabelGridData(1, 0));
+			label = new Label(gExternalBrowser, SWT.WRAP);
 			Messages.setLanguageText(label, "config.external.browser.info2");
+			label.setLayoutData(Utils.getWrappableLabelGridData(1, 0));
 			
 				// browser selection
 
@@ -293,12 +293,18 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 						"launchURL", 
 						new Class[]{ URL.class, boolean.class, Runnable.class });
 			
+			String pi_names = "";
+			
 			for ( PluginInterface pi: pis ){
 				
-				browser_choices.add( 
-						new String[]{ "plugin:" + pi.getPluginID(),  pi.getPluginName() });
+				String pi_name = pi.getPluginName();
+				
+				pi_names += ( pi_names.length()==0?"":"/") + pi_name;
 				
+				browser_choices.add( 
+						new String[]{ "plugin:" + pi.getPluginID(),  pi_name });			
 			}
+			
 			final Composite cEBArea = new Composite(gExternalBrowser, SWT.WRAP);
 			gridData = new GridData( GridData.FILL_HORIZONTAL);
 			cEBArea.setLayoutData(gridData);
@@ -307,7 +313,7 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 			layout.marginHeight = 0;
 			cEBArea.setLayout(layout);
 			
-			label = new Label(cEBArea, SWT.NULL);
+			label = new Label(cEBArea, SWT.WRAP);
 			Messages.setLanguageText(label, "config.external.browser.select");
 
 			final Composite cEB = new Group(cEBArea, SWT.WRAP);
@@ -351,7 +357,7 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 			
 			buttons.get(existing_index).setSelection( true );
 			
-			Messages.setLanguageText(new Label(cEBArea,SWT.NONE), "config.external.browser.prog" );
+			Messages.setLanguageText(new Label(cEBArea,SWT.WRAP), "config.external.browser.prog" );
 			
 			Composite manualArea = new Composite(cEBArea,SWT.NULL);
 			layout = new GridLayout(2,false);
@@ -399,21 +405,42 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 				b.addListener( SWT.Selection, radioListener );
 			}
 			
+				// always use plugin for non-pub
+			
+			if ( pis.size() > 0 ){
+				
+				Composite nonPubArea = new Composite(gExternalBrowser,SWT.NULL);
+				layout = new GridLayout(2,false);
+				layout.marginHeight = 0;
+				nonPubArea.setLayout(layout);
+				nonPubArea.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+	
+				String temp = MessageText.getString( "config.external.browser.non.pub", new String[]{ pi_names });
+				
+				BooleanParameter non_pub = new BooleanParameter( nonPubArea, "browser.external.non.pub", true, "!" + temp + "!" );
+			}
+			
 				// test launch
 			
 			Composite testArea = new Composite(gExternalBrowser,SWT.NULL);
-			layout = new GridLayout(3,false);
+			layout = new GridLayout(4,false);
 			layout.marginHeight = 0;
 			testArea.setLayout(layout);
 			testArea.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
-			label = new Label(testArea, SWT.NULL);
+			label = new Label(testArea, SWT.WRAP);
 			Messages.setLanguageText(label, "config.external.browser.test");
 
 		    final Button test_button = new Button(testArea, SWT.PUSH);
 		    
 		    Messages.setLanguageText(test_button, "configureWizard.nat.test");
 
+		    final Text test_url = new Text( testArea, SWT.BORDER );
+		    
+		    test_url.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		    test_url.setText( "http://www.vuze.com/" );
+		    
 		    test_button.addListener(SWT.Selection, 
 		    		new Listener() 
 					{
@@ -422,13 +449,15 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 				        {
 				        	test_button.setEnabled( false );
 				        	
+				        	final String url_str = test_url.getText().trim();
+				        	
 				        	new AEThread2( "async" )
 				        	{
 				        		public void
 				        		run()
 				        		{
 				        			try{
-				        				Utils.launch( "http://www.vuze.com/", true );
+				        				Utils.launch( url_str, true );
 				        				
 				        			}finally{
 				        				
@@ -455,7 +484,7 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 
 				// switch internal->external
 			
-			label = new Label(gExternalBrowser, SWT.NULL);
+			label = new Label(gExternalBrowser, SWT.WRAP);
 			Messages.setLanguageText(label, "config.external.browser.switch.info");
 
 			Group switchArea = new Group(gExternalBrowser,SWT.NULL);
@@ -467,11 +496,11 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 
 				// header
 			
-			label = new Label(switchArea, SWT.NULL);
+			label = new Label(switchArea, SWT.WRAP);
 			Messages.setLanguageText(label, "config.external.browser.switch.feature");
-			label = new Label(switchArea, SWT.NULL);
+			label = new Label(switchArea, SWT.WRAP);
 			Messages.setLanguageText(label, "config.external.browser.switch.external");
-			label = new Label(switchArea, SWT.NULL);
+			label = new Label(switchArea, SWT.WRAP);
 			gridData = new GridData(GridData.FILL_HORIZONTAL);
 			gridData.horizontalIndent = 10;
 			label.setLayoutData(gridData);
@@ -479,7 +508,7 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 
 				// search 
 			
-			label = new Label(switchArea, SWT.NULL);
+			label = new Label(switchArea, SWT.WRAP);
 			gridData = new GridData();
 			gridData.verticalIndent = 10;
 			label.setLayoutData(gridData);
@@ -491,8 +520,8 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 			gridData.horizontalAlignment = SWT.CENTER;
 			switchSearch.setLayoutData(gridData);
 			
-			label = new Label(switchArea, SWT.NULL);
-			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			label = new Label(switchArea, SWT.WRAP);
+			gridData = Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL);
 			gridData.verticalIndent = 10;
 			gridData.horizontalIndent = 10;
 			label.setLayoutData(gridData);
@@ -500,7 +529,7 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 
 				// subscriptions
 			
-			label = new Label(switchArea, SWT.NULL);
+			label = new Label(switchArea, SWT.WRAP);
 			gridData = new GridData();
 			label.setLayoutData(gridData);
 			Messages.setLanguageText(label, "config.external.browser.switch.subs");
@@ -510,8 +539,8 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 			gridData.horizontalAlignment = SWT.CENTER;
 			switchSubs.setLayoutData(gridData);
 			
-			label = new Label(switchArea, SWT.NULL);
-			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			label = new Label(switchArea, SWT.WRAP);
+			gridData = Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL);
 			gridData.horizontalIndent = 10;
 			label.setLayoutData(gridData);
 			Messages.setLanguageText(label, "config.external.browser.switch.subs.inf");
@@ -519,7 +548,7 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 		
 			// internal browser
 		
-		if( userMode > 1 ) {
+		if( userMode > 1) {
 			Group gInternalBrowser = new Group(cSection, SWT.NULL);
 			layout = new GridLayout();
 			layout.numColumns = 1;
@@ -528,10 +557,22 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 			
 			gInternalBrowser.setText( MessageText.getString( "config.internal.browser" ));
 			
-			label = new Label(gInternalBrowser, SWT.NULL);
+			label = new Label(gInternalBrowser, SWT.WRAP);
+			gridData = Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL);
+			label.setLayoutData(gridData);
 			Messages.setLanguageText(label, "config.internal.browser.info1");
 
-			label = new Label(gInternalBrowser, SWT.NULL);
+			
+			final BooleanParameter intbrow_disable = new BooleanParameter(gInternalBrowser, "browser.internal.disable", "config.browser.internal.disable");
+			label = new Label(gInternalBrowser, SWT.WRAP);
+			gridData = Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL);
+			gridData.horizontalIndent = 15;
+			label.setLayoutData(gridData);
+			Messages.setLanguageText(label, "config.browser.internal.disable.info");
+		
+			label = new Label(gInternalBrowser, SWT.WRAP);
+			gridData = Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL);
+			label.setLayoutData(gridData);
 			Messages.setLanguageText(label, "config.internal.browser.info3");
 			
 			java.util.List<PluginInterface> pis = AEProxyFactory.getPluginHTTPProxyProviders( true ); 
@@ -556,7 +597,9 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 			layout.marginHeight = 0;
 			cIPArea.setLayout(layout);
 			
-			label = new Label(cIPArea, SWT.NULL);
+			label = new Label(cIPArea, SWT.WRAP);
+			gridData = Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL);
+			label.setLayoutData(gridData);
 			Messages.setLanguageText(label, "config.internal.browser.proxy.select");
 
 			final Composite cIP = new Group(cIPArea, SWT.WRAP);
@@ -636,7 +679,9 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 			
 				// force firefox
 			
-			label = new Label(gInternalBrowser, SWT.NULL);
+			label = new Label(gInternalBrowser, SWT.WRAP);
+			gridData = Utils.getWrappableLabelGridData(1, GridData.FILL_HORIZONTAL);
+			label.setLayoutData(gridData);
 			Messages.setLanguageText(label, "config.internal.browser.info2");
 
 			
@@ -644,9 +689,23 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 			Composite pArea = new Composite(gInternalBrowser,SWT.NULL);
 			pArea.setLayout(new GridLayout(3,false));
 			pArea.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-			Messages.setLanguageText(new Label(pArea,SWT.NONE), MSG_PREFIX+"xulRunnerPath");
+			Messages.setLanguageText(new Label(pArea,SWT.WRAP), MSG_PREFIX+"xulRunnerPath");
 			final Parameter xulDir = new DirectoryParameter(pArea, "swt.xulRunner.path","");
 			fMoz.setAdditionalActionPerformer(new ChangeSelectionActionPerformer(xulDir.getControls(), false));
+			
+			intbrow_disable.setAdditionalActionPerformer(
+					new ChangeSelectionActionPerformer(
+						xulDir.getControls(), true));
+			
+			intbrow_disable.setAdditionalActionPerformer(
+					new ChangeSelectionActionPerformer(
+						new Control[]{ fMoz.getControl() }, true));
+			
+			for ( Button b: buttons ){
+				intbrow_disable.setAdditionalActionPerformer(
+						new ChangeSelectionActionPerformer(
+							new Control[]{ b }, true));
+			}
 		}
 		
 			// refresh
@@ -668,13 +727,13 @@ public class ConfigSectionInterfaceDisplay implements UISWTConfigSection {
 		label = new Label(gRefresh, SWT.NULL);
 		Messages.setLanguageText(label, MSG_PREFIX + "inactiveUpdate");
 		gridData = new GridData();
-		IntParameter inactiveUpdate = new IntParameter(gRefresh, "Refresh When Inactive", 1,	-1);
+		IntParameter inactiveUpdate = new IntParameter(gRefresh, "Refresh When Inactive", 1, Integer.MAX_VALUE);
 		inactiveUpdate.setLayoutData(gridData);
 
 		label = new Label(gRefresh, SWT.NULL);
 		Messages.setLanguageText(label, MSG_PREFIX + "graphicsUpdate");
 		gridData = new GridData();
-		IntParameter graphicUpdate = new IntParameter(gRefresh, "Graphics Update", 1,	-1);
+		IntParameter graphicUpdate = new IntParameter(gRefresh, "Graphics Update", 1, Integer.MAX_VALUE);
 		graphicUpdate.setLayoutData(gridData);
 		
 		return cSection;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceLanguage.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceLanguage.java
index 5e814c0..5e04d2b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceLanguage.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceLanguage.java
@@ -1,7 +1,7 @@
 /*
  * Created on Oct 21, 2004
  * Created by Alon Rohter
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceLegacy.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceLegacy.java
index d39ec57..9e90519 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceLegacy.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceLegacy.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 6, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfacePassword.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfacePassword.java
index 744282b..c90055a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfacePassword.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfacePassword.java
@@ -3,11 +3,12 @@
  * Created : Dec 4, 2006
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceStart.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceStart.java
index bc5b76d..6b8a652 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceStart.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceStart.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceTables.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceTables.java
index 50e96e0..508a57a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceTables.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionInterfaceTables.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
@@ -34,7 +32,6 @@ import org.eclipse.swt.events.SelectionListener;
 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.config.ParameterListener;
 import org.gudy.azureus2.core3.internat.MessageText;
@@ -84,149 +81,214 @@ public class ConfigSectionInterfaceTables
 		Composite cSection = new Composite(parent, SWT.NULL);
 		cSection.setLayoutData(new GridData(GridData.FILL_BOTH));
 		layout = new GridLayout();
-		layout.numColumns = 2;
+		layout.numColumns = 1;
 		cSection.setLayout(layout);
 
-		label = new Label(cSection, SWT.NULL);
-		Messages.setLanguageText(label, MSG_PREFIX + "defaultSortOrder");
-		int[] sortOrderValues = {
-			0,
-			1,
-			2
-		};
-		String[] sortOrderLabels = {
-			MessageText.getString(MSG_PREFIX + "defaultSortOrder.asc"),
-			MessageText.getString(MSG_PREFIX + "defaultSortOrder.desc"),
-			MessageText.getString(MSG_PREFIX + "defaultSortOrder.flip")
-		};
-		new IntListParameter(cSection, "config.style.table.defaultSortOrder",
-				sortOrderLabels, sortOrderValues);
-
-		if (userMode > 0) {
-			label = new Label(cSection, SWT.NULL);
-			Messages.setLanguageText(label, MSG_PREFIX + "guiUpdate");
-			int[] values = {
-				100,
-				250,
-				500,
-				1000,
-				2000,
-				5000,
-				10000,
-				15000
+		{
+			Group cGeneral = new Group(cSection, SWT.NULL);
+			Messages.setLanguageText(cGeneral, "ConfigView.section.global" );
+			layout = new GridLayout();
+			layout.numColumns = 2;
+			cGeneral.setLayout(layout);
+			cGeneral.setLayoutData(new GridData( GridData.FILL_HORIZONTAL ));
+		
+			label = new Label(cGeneral, SWT.NULL);
+			Messages.setLanguageText(label, MSG_PREFIX + "defaultSortOrder");
+			int[] sortOrderValues = {
+				0,
+				1,
+				2
 			};
-			String[] labels = {
-				"100 ms",
-				"250 ms",
-				"500 ms",
-				"1 s",
-				"2 s",
-				"5 s",
-				"10 s",
-				"15 s"
+			String[] sortOrderLabels = {
+				MessageText.getString(MSG_PREFIX + "defaultSortOrder.asc"),
+				MessageText.getString(MSG_PREFIX + "defaultSortOrder.desc"),
+				MessageText.getString(MSG_PREFIX + "defaultSortOrder.flip")
 			};
-			new IntListParameter(cSection, "GUI Refresh", 1000, labels, values);
-
-			label = new Label(cSection, SWT.NULL);
-			Messages.setLanguageText(label, MSG_PREFIX + "graphicsUpdate");
-			gridData = new GridData();
-			IntParameter graphicUpdate = new IntParameter(cSection, "Graphics Update",
-					1, -1);
-			graphicUpdate.setLayoutData(gridData);
-
-			label = new Label(cSection, SWT.NULL);
-			Messages.setLanguageText(label, MSG_PREFIX + "reOrderDelay");
-			gridData = new GridData();
-			IntParameter reorderDelay = new IntParameter(cSection, "ReOrder Delay");
-			reorderDelay.setLayoutData(gridData);
-
-			new BooleanParameter(cSection, "NameColumn.showProgramIcon", MSG_PREFIX
-					+ "showProgramIcon").setLayoutData(new GridData(SWT.FILL, SWT.LEFT, true, false, 2, 1));
-
-			////
-
-			new BooleanParameter(cSection, "Table.extendedErase", MSG_PREFIX
-					+ "extendedErase").setLayoutData(new GridData(SWT.FILL, SWT.LEFT,
-					true, false, 2, 1));
-
-			////
-			
-			boolean hhEnabled = COConfigurationManager.getIntParameter("Table.headerHeight") > 0;
-
-			Button chkHeaderHeight = new Button(cSection, SWT.CHECK);
-			Messages.setLanguageText(chkHeaderHeight, MSG_PREFIX + "enableHeaderHeight");
-			chkHeaderHeight.setSelection(hhEnabled);
-			
-			final IntParameter paramHH = new IntParameter(cSection, "Table.headerHeight", 0, 100);
-			paramHH.setEnabled(hhEnabled);
-			
-			chkHeaderHeight.addSelectionListener(new SelectionListener() {
-				public void widgetSelected(SelectionEvent e) {
-					if (((Button) e.widget).getSelection()) {
-						COConfigurationManager.setParameter("Table.headerHeight", 16);
-						paramHH.setEnabled(true);
-					} else {
-						COConfigurationManager.setParameter("Table.headerHeight", 0);
-						paramHH.setEnabled(false);
-					}
-				}
+			new IntListParameter(cGeneral, "config.style.table.defaultSortOrder",
+					sortOrderLabels, sortOrderValues);
+	
+			if (userMode > 0) {
+				label = new Label(cGeneral, SWT.NULL);
+				Messages.setLanguageText(label, MSG_PREFIX + "guiUpdate");
+				int[] values = {
+					100,
+					250,
+					500,
+					1000,
+					2000,
+					5000,
+					10000,
+					15000
+				};
+				String[] labels = {
+					"100 ms",
+					"250 ms",
+					"500 ms",
+					"1 s",
+					"2 s",
+					"5 s",
+					"10 s",
+					"15 s"
+				};
+				new IntListParameter(cGeneral, "GUI Refresh", 1000, labels, values);
+	
+				label = new Label(cGeneral, SWT.NULL);
+				Messages.setLanguageText(label, MSG_PREFIX + "graphicsUpdate");
+				gridData = new GridData();
+				IntParameter graphicUpdate = new IntParameter(cGeneral, "Graphics Update",
+						1, Integer.MAX_VALUE );
+				graphicUpdate.setLayoutData(gridData);
+	
+				label = new Label(cGeneral, SWT.NULL);
+				Messages.setLanguageText(label, MSG_PREFIX + "reOrderDelay");
+				gridData = new GridData();
+				IntParameter reorderDelay = new IntParameter(cGeneral, "ReOrder Delay");
+				reorderDelay.setLayoutData(gridData);
+	
+				new BooleanParameter(cGeneral, "NameColumn.showProgramIcon", MSG_PREFIX
+						+ "showProgramIcon").setLayoutData(new GridData(SWT.FILL, SWT.LEFT, true, false, 2, 1));
+	
+				////
+	
+				new BooleanParameter(cGeneral, "Table.extendedErase", MSG_PREFIX
+						+ "extendedErase").setLayoutData(new GridData(SWT.FILL, SWT.LEFT,
+						true, false, 2, 1));
+	
+				////
 				
-				public void widgetDefaultSelected(SelectionEvent e) {
-				}
-			});
-			
-			/////
-
-			boolean cdEnabled = COConfigurationManager.getStringParameter("Table.column.dateformat", "").length() > 0;
-
-			Button chkCustomDate = new Button(cSection, SWT.CHECK);
-			Messages.setLanguageText(chkCustomDate, MSG_PREFIX + "customDateFormat");
-			chkCustomDate.setSelection(cdEnabled);
-			
-			final StringParameter paramCustomDate = new StringParameter(cSection, "Table.column.dateformat", "");
-			paramCustomDate.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-			paramCustomDate.setEnabled(cdEnabled);
-			paramCustomDate.addChangeListener(new ParameterChangeAdapter() {
+				boolean hhEnabled = COConfigurationManager.getIntParameter("Table.headerHeight") > 0;
+	
+				Button chkHeaderHeight = new Button(cGeneral, SWT.CHECK);
+				Messages.setLanguageText(chkHeaderHeight, MSG_PREFIX + "enableHeaderHeight");
+				chkHeaderHeight.setSelection(hhEnabled);
+				
+				final IntParameter paramHH = new IntParameter(cGeneral, "Table.headerHeight", 0, 100);
+				paramHH.setEnabled(hhEnabled);
 				
-				public void parameterChanged(Parameter p, boolean caused_internally) {
-					String s = (String) p.getValueObject();
-					boolean ok = false;
-					try {
-						SimpleDateFormat temp = new SimpleDateFormat(s);
-						temp.format(new Date());
-						ok = true;
-					} catch (Exception e) {
-						// probably illegalargumentexception
+				chkHeaderHeight.addSelectionListener(new SelectionListener() {
+					public void widgetSelected(SelectionEvent e) {
+						if (((Button) e.widget).getSelection()) {
+							COConfigurationManager.setParameter("Table.headerHeight", 16);
+							paramHH.setEnabled(true);
+						} else {
+							COConfigurationManager.setParameter("Table.headerHeight", 0);
+							paramHH.setEnabled(false);
+						}
 					}
-					p.getControl().setBackground(ok ? null : Colors.colorErrorBG);
-				}
+					
+					public void widgetDefaultSelected(SelectionEvent e) {
+					}
+				});
 				
-			});
-			
-			chkCustomDate.addSelectionListener(new SelectionListener() {
-				public void widgetSelected(SelectionEvent e) {
-					if (((Button) e.widget).getSelection()) {
-						COConfigurationManager.setParameter("Table.column.dateformat", "yyyy/MM/dd");
-						paramCustomDate.setEnabled(true);
-					} else {
-						COConfigurationManager.setParameter("Table.column.dateformat", "");
-						paramCustomDate.setEnabled(false);
+				/////
+	
+				boolean cdEnabled = COConfigurationManager.getStringParameter("Table.column.dateformat", "").length() > 0;
+	
+				Button chkCustomDate = new Button(cGeneral, SWT.CHECK);
+				Messages.setLanguageText(chkCustomDate, MSG_PREFIX + "customDateFormat");
+				chkCustomDate.setSelection(cdEnabled);
+				
+				final StringParameter paramCustomDate = new StringParameter(cGeneral, "Table.column.dateformat", "");
+				paramCustomDate.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+				paramCustomDate.setEnabled(cdEnabled);
+				paramCustomDate.addChangeListener(new ParameterChangeAdapter() {
+					
+					public void parameterChanged(Parameter p, boolean caused_internally) {
+						String s = (String) p.getValueObject();
+						boolean ok = false;
+						try {
+							SimpleDateFormat temp = new SimpleDateFormat(s);
+							temp.format(new Date());
+							ok = true;
+						} catch (Exception e) {
+							// probably illegalargumentexception
+						}
+						p.getControl().setBackground(ok ? null : Colors.colorErrorBG);
 					}
-				}
+					
+				});
 				
-				public void widgetDefaultSelected(SelectionEvent e) {
-				}
-			});
+				chkCustomDate.addSelectionListener(new SelectionListener() {
+					public void widgetSelected(SelectionEvent e) {
+						if (((Button) e.widget).getSelection()) {
+							COConfigurationManager.setParameter("Table.column.dateformat", "yyyy/MM/dd");
+							paramCustomDate.setEnabled(true);
+						} else {
+							COConfigurationManager.setParameter("Table.column.dateformat", "");
+							paramCustomDate.setEnabled(false);
+						}
+					}
+					
+					public void widgetDefaultSelected(SelectionEvent e) {
+					}
+				});
+			}
 		}
-
+		
 		{
 			Group cLibrary = new Group(cSection, SWT.NULL);
 			Messages.setLanguageText(cLibrary, MSG_PREFIX + "library");
 			layout = new GridLayout();
 			layout.numColumns = 2;
 			cLibrary.setLayout(layout);
-			cLibrary.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 2, 1));
+			cLibrary.setLayoutData(new GridData( GridData.FILL_HORIZONTAL ));
+						
+				// User tree
+			
+			new BooleanParameter(cLibrary, "Table.useTree", MSG_PREFIX
+					+ "useTree").setLayoutData(new GridData(SWT.FILL,
+							SWT.LEFT, true, false, 2, 1));
 
+			if (userMode > 1) {
+				new BooleanParameter(cLibrary, "DND Always In Incomplete", MSG_PREFIX
+						+ "DNDalwaysInIncomplete").setLayoutData(new GridData(SWT.FILL,
+								SWT.LEFT, true, false, 2, 1));
+			}
+
+			if (isAZ3) {
+				new BooleanParameter(cLibrary, "Library.CatInSideBar", MSG_PREFIX
+						+ "CatInSidebar").setLayoutData(new GridData(SWT.FILL,
+								SWT.LEFT, true, false, 2, 1));
+			}
+			
+			new BooleanParameter(cLibrary, "Library.ShowCatButtons", MSG_PREFIX
+					+ "ShowCatButtons").setLayoutData(new GridData(SWT.FILL,
+							SWT.LEFT, true, false, 2, 1));
+
+			if (isAZ3) {
+
+				new BooleanParameter(cLibrary, "Library.TagInSideBar", MSG_PREFIX
+						+ "TagInSidebar").setLayoutData(new GridData(SWT.FILL,
+								SWT.LEFT, true, false, 2, 1));
+			}
+			
+			BooleanParameter show_tag = new BooleanParameter(cLibrary, "Library.ShowTagButtons", MSG_PREFIX
+					+ "ShowTagButtons");
+			
+			show_tag.setLayoutData(new GridData(SWT.FILL, SWT.LEFT, true, false, 2, 1));
+
+			BooleanParameter show_tag_comp_only =new BooleanParameter(cLibrary, "Library.ShowTagButtons.CompOnly", MSG_PREFIX
+					+ "ShowTagButtons.CompOnly");
+			
+			gridData = new GridData(SWT.FILL,SWT.LEFT, true, false, 2, 1);
+			gridData.horizontalIndent = 25;
+			show_tag_comp_only.setLayoutData( gridData );
+			
+			show_tag.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( show_tag_comp_only ));
+			
+			if (isAZ3) {
+
+				new BooleanParameter(cLibrary, "Library.ShowTabsInTorrentView", MSG_PREFIX
+						+ "ShowTabsInTorrentView").setLayoutData(new GridData(SWT.FILL,
+								SWT.LEFT, true, false, 2, 1));
+			}
+			
+			new BooleanParameter(cLibrary, "Library.showFancyMenu", true, MSG_PREFIX
+					+ "ShowFancyMenu").setLayoutData(new GridData(SWT.FILL, SWT.LEFT,
+					true, false, 2, 1));
+
+
+		
 			// double-click
 
 			label = new Label(cLibrary, SWT.NULL);
@@ -237,6 +299,8 @@ public class ConfigSectionInterfaceTables
 				"ConfigView.option.dm.dblclick.details",
 				"ConfigView.option.dm.dblclick.show",
 				"ConfigView.option.dm.dblclick.launch",
+				"ConfigView.option.dm.dblclick.launch.qv",
+				"ConfigView.option.dm.dblclick.open.browser",
 			};
 
 			String dblclickLabels[] = new String[dblclickOptions.length];
@@ -247,18 +311,38 @@ public class ConfigSectionInterfaceTables
 				dblclickLabels[i] = MessageText.getString(dblclickOptions[i]);
 				dblclickValues[i] = "" + i;
 			}
-			new StringListParameter(cLibrary, "list.dm.dblclick", dblclickLabels,
-					dblclickValues);
+			new StringListParameter(cLibrary, "list.dm.dblclick", dblclickLabels, dblclickValues);
+			
+				// always open websites in browser
+			
+			Composite cLaunchWeb = new Composite(cLibrary, SWT.NULL);
+			layout = new GridLayout();
+			layout.numColumns = 4;
+			cLaunchWeb.setLayout(layout);
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			gridData.horizontalSpan = 2;
+			gridData.horizontalIndent = 25;
+			cLaunchWeb.setLayoutData(gridData);
+			
+			BooleanParameter web_in_browser =
+					new BooleanParameter(cLaunchWeb, "Library.LaunchWebsiteInBrowser", "library.launch.web.in.browser");
 
-				// Launch helpers
+			BooleanParameter web_in_browser_anon =
+					new BooleanParameter(cLaunchWeb, "Library.LaunchWebsiteInBrowserAnon", "library.launch.web.in.browser.anon");
+
+			web_in_browser.setAdditionalActionPerformer( new ChangeSelectionActionPerformer( web_in_browser_anon ));
 			
+				// Launch helpers
+				
 			Group cLaunch = new Group(cLibrary, SWT.NULL);
 			Messages.setLanguageText(cLaunch, MSG_PREFIX + "launch");
 			layout = new GridLayout();
 			layout.numColumns = 5;
 			cLaunch.setLayout(layout);
-			cLaunch.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
-
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			gridData.horizontalSpan = 2;
+			cLaunch.setLayoutData(gridData);
+	
 		    Label	info_label = new Label( cLaunch, SWT.WRAP );
 		    Messages.setLanguageText( info_label, "ConfigView.label.lh.info" );
 		    gridData = Utils.getWrappableLabelGridData(5, GridData.HORIZONTAL_ALIGN_FILL );
@@ -268,7 +352,7 @@ public class ConfigSectionInterfaceTables
 				
 				label = new Label(cLaunch, SWT.NULL);
 				Messages.setLanguageText(label, "ConfigView.label.lh.ext");
-
+	
 				StringParameter exts = new StringParameter(cLaunch, "Table.lh" + i + ".exts", "");
 				gridData = new GridData();
 				gridData.widthHint = 200;
@@ -276,9 +360,9 @@ public class ConfigSectionInterfaceTables
 				
 				label = new Label(cLaunch, SWT.NULL);
 				Messages.setLanguageText(label, "ConfigView.label.lh.prog");
-
+	
 				final FileParameter prog = new FileParameter(cLaunch, "Table.lh" + i + ".prog", "", new String[0]);
-
+	
 				gridData = new GridData();
 				gridData.widthHint = 400;
 				prog.getControls()[0].setLayoutData( gridData );
@@ -352,33 +436,6 @@ public class ConfigSectionInterfaceTables
 							});
 				}
 			}
-			
-			
-				// User tree
-			
-			new BooleanParameter(cLibrary, "Table.useTree", MSG_PREFIX
-					+ "useTree").setLayoutData(new GridData(SWT.FILL,
-							SWT.LEFT, true, false, 2, 1));
-
-			if (userMode > 1) {
-				new BooleanParameter(cLibrary, "DND Always In Incomplete", MSG_PREFIX
-						+ "DNDalwaysInIncomplete").setLayoutData(new GridData(SWT.FILL,
-								SWT.LEFT, true, false, 2, 1));
-			}
-
-			if (isAZ3) {
-				new BooleanParameter(cLibrary, "Library.CatInSideBar", MSG_PREFIX
-						+ "CatInSidebar").setLayoutData(new GridData(SWT.FILL,
-								SWT.LEFT, true, false, 2, 1));
-				
-				new BooleanParameter(cLibrary, "Library.TagInSideBar", MSG_PREFIX
-						+ "TagInSidebar").setLayoutData(new GridData(SWT.FILL,
-								SWT.LEFT, true, false, 2, 1));
-			
-				new BooleanParameter(cLibrary, "Library.ShowTabsInTorrentView", MSG_PREFIX
-						+ "ShowTabsInTorrentView").setLayoutData(new GridData(SWT.FILL,
-								SWT.LEFT, true, false, 2, 1));
-			}
 		}
 
 		return cSection;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionLogging.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionLogging.java
index 7533639..8ca1730 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionLogging.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionLogging.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionMode.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionMode.java
index 881b016..07b8201 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionMode.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionMode.java
@@ -4,11 +4,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -18,9 +19,6 @@
  * 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.configsections;
@@ -38,8 +36,8 @@ import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Group;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Listener;
-
 import org.gudy.azureus2.plugins.ui.config.ConfigSection;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
 import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
@@ -163,7 +161,7 @@ public class ConfigSectionMode implements UISWTConfigSection {
     gridData = new GridData(GridData.FILL_HORIZONTAL);
     gridData.horizontalSpan = 4;
     linkLabel.setLayoutData(gridData);
-   
+    ClipboardCopy.addCopyToClipMenu( linkLabel );
     
     final Runnable setModeText = 
     	new Runnable()
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionPlugins.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionPlugins.java
index 2db29da..54a1006 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionPlugins.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionPlugins.java
@@ -1,11 +1,12 @@
 /*
  * File    : ConfigSectionPlguins.java
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -15,9 +16,6 @@
  * 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.configsections;
@@ -87,7 +85,7 @@ public class ConfigSectionPlugins implements UISWTConfigSection, ParameterListen
 	private final static String[] COLUMN_HEADERS = { "loadAtStartup", "type",
 			"name", "version", "directory", "unloadable" };
 
-	private final static int[] COLUMN_SIZES = { 110, 50, 150, 75, 100, 50 };
+	private final static int[] COLUMN_SIZES = { 180, 70, 250, 100, 100, 50 };
 
 	private final static int[] COLUMN_ALIGNS = { SWT.CENTER, SWT.LEFT, SWT.LEFT,
 			SWT.RIGHT, SWT.LEFT, SWT.CENTER};
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSecurity.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSecurity.java
index 1b4fff6..48da2c7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSecurity.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSecurity.java
@@ -1,7 +1,7 @@
 /*
  * Created on 12-Jun-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -44,6 +41,7 @@ import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.auth.CertificateCreatorWindow;
 import org.gudy.azureus2.ui.swt.config.*;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
 import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
@@ -310,7 +308,7 @@ ConfigSectionSecurity
 					Utils.launch((String) ((Label) arg0.widget).getData());
 				}
 			});
-			
+			ClipboardCopy.addCopyToClipMenu( linkLabel );
 			
 				// publick key display
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSharing.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSharing.java
index 9896253..f1aeae7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSharing.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionSharing.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionStartShutdown.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionStartShutdown.java
index d7d1f17..9f30549 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionStartShutdown.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionStartShutdown.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
@@ -27,7 +25,6 @@ package org.gudy.azureus2.ui.swt.views.configsections;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.*;
@@ -48,8 +45,6 @@ import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
 import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
 import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
 
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
@@ -214,109 +209,11 @@ public class ConfigSectionStartShutdown implements UISWTConfigSection {
 
 				// done downloading
 			
-			gridData = new GridData();
-			label = new Label(gStop, SWT.NULL);
-		    Messages.setLanguageText(label, "ConfigView.label.stop.downcomp");
-		    label.setLayoutData( gridData );
-			
-		    int	shutdown_types = platform.getShutdownTypes();
-		    
-			List<String>	l_action_values = new ArrayList<String>();
-			List<String>	l_action_descs 	= new ArrayList<String>();
-
-			l_action_values.add( "Nothing" ); 
-			l_action_values.add( "QuitVuze" );
-			
-			if (( shutdown_types & PlatformManager.SD_SLEEP ) != 0 ){
-				
-				l_action_values.add( "Sleep" );
-			}
-			if (( shutdown_types & PlatformManager.SD_HIBERNATE ) != 0 ){
-				
-				l_action_values.add( "Hibernate" );
-			}
-			if (( shutdown_types & PlatformManager.SD_SHUTDOWN ) != 0 ){
-				
-				l_action_values.add( "Shutdown" );
-			}
-			
-			l_action_values.add( "RunScript" );
-			l_action_values.add( "RunScriptAndClose" );
-
-			String[] action_values = l_action_values.toArray( new String[ l_action_values.size()]);
-					
-			for ( String s: action_values ){
-				
-				l_action_descs.add( MessageText.getString( "ConfigView.label.stop." + s ));
-			}
-			
-			String[] action_descs = l_action_descs.toArray( new String[ l_action_descs.size()]);
-
-			final StringListParameter dc = new StringListParameter(gStop, "On Downloading Complete Do", "Nothing", action_descs, action_values );
-
-			final Label dc_label = new Label(gStop, SWT.NONE);
-			Messages.setLanguageText(dc_label, "label.script.to.run");
-			dc_label.setLayoutData(new GridData());
-
-			gridData = new GridData(GridData.FILL_HORIZONTAL);
-			final FileParameter dc_script = new FileParameter(gStop, "On Downloading Complete Script", "", new String[0]);
-			dc_script.setLayoutData(gridData);
-	
-			boolean	is_script = dc.getValue().startsWith( "RunScript" );
-			
-			dc_label.setEnabled( is_script );
-			dc_script.setEnabled( is_script );
-			
-			dc.addChangeListener(
-				new ParameterChangeAdapter()
-				{
-					public void
-					parameterChanged(
-						Parameter	p,
-						boolean		caused_internally )
-					{
-						boolean	is_script = dc.getValue().startsWith( "RunScript" );
-						
-						dc_label.setEnabled( is_script );
-						dc_script.setEnabled( is_script );
-					}
-				});
+			addDoneDownloadingOption( gStop, true );
 				
 				// done seeding
 			
-			gridData = new GridData();
-		    label = new Label(gStop, SWT.NULL);
-		    Messages.setLanguageText(label, "ConfigView.label.stop.seedcomp");
-		    label.setLayoutData( gridData );
-					    
-		    final StringListParameter sc = new StringListParameter(gStop, "On Seeding Complete Do", "Nothing", action_descs, action_values );
-			
-			final Label sc_label = new Label(gStop, SWT.NONE);
-			Messages.setLanguageText(sc_label, "label.script.to.run");
-			sc_label.setLayoutData(new GridData());
-			gridData = new GridData(GridData.FILL_HORIZONTAL);
-			final FileParameter sc_script = new FileParameter(gStop, "On Seeding Complete Script", "", new String[0]);
-			sc_script.setLayoutData(gridData);
-	
-			is_script = sc.getValue().startsWith( "RunScript" );
-			
-			sc_label.setEnabled( is_script );
-			sc_script.setEnabled( is_script );
-			
-			sc.addChangeListener(
-				new ParameterChangeAdapter()
-				{
-					public void
-					parameterChanged(
-						Parameter	p,
-						boolean		caused_internally )
-					{
-						boolean	is_script = sc.getValue().startsWith( "RunScript" );
-						
-						sc_label.setEnabled( is_script );
-						sc_script.setEnabled( is_script );
-					}
-				});
+			addDoneSeedingOption( gStop, true );
 			
 		    	// reset on trigger
 		    
@@ -867,4 +764,135 @@ public class ConfigSectionStartShutdown implements UISWTConfigSection {
 		return( value );
 	}
 
+	private static String[][]
+	getActionDetails()
+	{	
+		final PlatformManager platform = PlatformManagerFactory.getPlatformManager();
+
+	    int	shutdown_types = platform.getShutdownTypes();
+	    
+		List<String>	l_action_values = new ArrayList<String>();
+		List<String>	l_action_descs 	= new ArrayList<String>();
+
+		l_action_values.add( "Nothing" ); 
+		l_action_values.add( "QuitVuze" );
+		
+		if (( shutdown_types & PlatformManager.SD_SLEEP ) != 0 ){
+			
+			l_action_values.add( "Sleep" );
+		}
+		if (( shutdown_types & PlatformManager.SD_HIBERNATE ) != 0 ){
+			
+			l_action_values.add( "Hibernate" );
+		}
+		if (( shutdown_types & PlatformManager.SD_SHUTDOWN ) != 0 ){
+			
+			l_action_values.add( "Shutdown" );
+		}
+		
+		l_action_values.add( "RunScript" );
+		l_action_values.add( "RunScriptAndClose" );
+
+		String[] action_values = l_action_values.toArray( new String[ l_action_values.size()]);
+				
+		for ( String s: action_values ){
+			
+			l_action_descs.add( MessageText.getString( "ConfigView.label.stop." + s ));
+		}
+		
+		String[] action_descs = l_action_descs.toArray( new String[ l_action_descs.size()]);
+		
+		return( new String[][]{ action_descs, action_values });
+	}
+	
+	public static void
+	addDoneDownloadingOption(
+		Composite		comp,
+		boolean			include_script_setting )
+	{
+		GridData gridData = new GridData();
+		Label label = new Label(comp, SWT.NULL);
+	    Messages.setLanguageText(label, "ConfigView.label.stop.downcomp");
+	    label.setLayoutData( gridData );
+		
+	    String[][]	action_details = getActionDetails();
+
+		final StringListParameter dc = new StringListParameter(comp, "On Downloading Complete Do", "Nothing", action_details[0], action_details[1] );
+
+		if ( include_script_setting ){
+			
+			final Label dc_label = new Label(comp, SWT.NONE);
+			Messages.setLanguageText(dc_label, "label.script.to.run");
+			dc_label.setLayoutData(new GridData());
+	
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			final FileParameter dc_script = new FileParameter(comp, "On Downloading Complete Script", "", new String[0]);
+			dc_script.setLayoutData(gridData);
+	
+			boolean	is_script = dc.getValue().startsWith( "RunScript" );
+			
+			dc_label.setEnabled( is_script );
+			dc_script.setEnabled( is_script );
+			
+			dc.addChangeListener(
+				new ParameterChangeAdapter()
+				{
+					public void
+					parameterChanged(
+						Parameter	p,
+						boolean		caused_internally )
+					{
+						boolean	is_script = dc.getValue().startsWith( "RunScript" );
+						
+						dc_label.setEnabled( is_script );
+						dc_script.setEnabled( is_script );
+					}
+				});	
+		}
+	}
+	
+	private static void
+	addDoneSeedingOption(
+		Composite		comp,
+		boolean			include_script_setting )
+	{
+		GridData gridData = new GridData();
+		Label label = new Label(comp, SWT.NULL);
+	    Messages.setLanguageText(label, "ConfigView.label.stop.seedcomp");
+	    label.setLayoutData( gridData );
+			
+	    String[][]	action_details = getActionDetails();
+
+	    final StringListParameter sc = new StringListParameter(comp, "On Seeding Complete Do", "Nothing", action_details[0], action_details[1] );
+		
+	    if ( include_script_setting ){
+	    	
+			final Label sc_label = new Label(comp, SWT.NONE);
+			Messages.setLanguageText(sc_label, "label.script.to.run");
+			sc_label.setLayoutData(new GridData());
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			final FileParameter sc_script = new FileParameter(comp, "On Seeding Complete Script", "", new String[0]);
+			sc_script.setLayoutData(gridData);
+		
+			boolean is_script = sc.getValue().startsWith( "RunScript" );
+			
+			sc_label.setEnabled( is_script );
+			sc_script.setEnabled( is_script );
+			
+			sc.addChangeListener(
+				new ParameterChangeAdapter()
+				{
+					public void
+					parameterChanged(
+						Parameter	p,
+						boolean		caused_internally )
+					{
+						boolean	is_script = sc.getValue().startsWith( "RunScript" );
+						
+						sc_label.setEnabled( is_script );
+						sc_script.setEnabled( is_script );
+					}
+				});
+	    }
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionStats.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionStats.java
index 4190cb2..137db36 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionStats.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionStats.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
@@ -42,11 +40,11 @@ import org.eclipse.swt.widgets.Listener;
 import org.eclipse.swt.widgets.DirectoryDialog;
 import org.eclipse.swt.events.MouseAdapter;
 import org.eclipse.swt.events.MouseEvent;
-
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.plugins.ui.config.ConfigSection;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.config.*;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
 import org.gudy.azureus2.ui.swt.Messages;
@@ -211,6 +209,7 @@ public class ConfigSectionStats implements UISWTConfigSection {
     final String linkFAQ = "http://plugins.vuze.com/faq.php#20";
     lxslDetails.setCursor(lxslDetails.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
     lxslDetails.setForeground(Colors.blue);
+    lxslDetails.setData( linkFAQ );
     lxslDetails.addMouseListener(new MouseAdapter() {
       public void mouseDoubleClick(MouseEvent arg0) {
       	Utils.launch(linkFAQ);
@@ -219,6 +218,7 @@ public class ConfigSectionStats implements UISWTConfigSection {
       	Utils.launch(linkFAQ);
       }
     });
+    ClipboardCopy.addCopyToClipMenu( lxslDetails );
     controls[7] = lxslDetails;
     
     // row
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTracker.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTracker.java
index 5778695..eaa0407 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTracker.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTracker.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java
index 5b96e3e..ee47a02 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerClient.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerServer.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerServer.java
index b3787d2..c1be649 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerServer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTrackerServer.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
@@ -30,7 +28,6 @@ import org.eclipse.swt.events.MouseEvent;
 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.core3.util.AENetworkClassifier;
@@ -42,6 +39,7 @@ import org.gudy.azureus2.ui.swt.auth.CertificateCreatorWindow;
 import org.gudy.azureus2.ui.swt.config.*;
 import org.gudy.azureus2.ui.swt.ipchecker.IpCheckerWizard;
 import org.gudy.azureus2.ui.swt.ipchecker.IpSetterCallBack;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
 
@@ -235,6 +233,7 @@ ConfigSectionTrackerServer
     Messages.setLanguageText(ssl_faq_label, CFG_PREFIX + "tracker.sslport.info");
     final String linkFAQ = "http://plugins.vuze.com/faq.php#19";
     ssl_faq_label.setCursor(ssl_faq_label.getDisplay().getSystemCursor(SWT.CURSOR_HAND));
+    ssl_faq_label.setData(linkFAQ);
     ssl_faq_label.setForeground(Colors.blue);
     ssl_faq_label.addMouseListener(new MouseAdapter() {
        public void mouseDoubleClick(MouseEvent arg0) {
@@ -244,6 +243,7 @@ ConfigSectionTrackerServer
       	 Utils.launch(linkFAQ);
        }
     });
+    ClipboardCopy.addCopyToClipMenu( ssl_faq_label );
     
     Control[] ssl_controls = { 	
     		tracker_port_ssl.getControl(),
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransfer.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransfer.java
index 578a41b..74e27d5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransfer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransfer.java
@@ -3,11 +3,12 @@
  * Created : 11 mar. 2004
  * By      : TuxPaper
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.configsections;
@@ -103,7 +101,7 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
 
 		gridData = new GridData();
 		final IntParameter paramMaxUploadSpeed = new IntParameter(cSection,
-				"Max Upload Speed KBs", 0, -1);
+				"Max Upload Speed KBs", 0, Integer.MAX_VALUE );
 		paramMaxUploadSpeed.setLayoutData(gridData);
 
 		//  max upload speed when seeding
@@ -135,7 +133,7 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
 
 		gridData = new GridData();
 		final IntParameter paramMaxUploadSpeedSeeding = new IntParameter(
-				cMaxUploadSpeedOptionsArea, "Max Upload Speed Seeding KBs", 0, -1);
+				cMaxUploadSpeedOptionsArea, "Max Upload Speed Seeding KBs", 0, Integer.MAX_VALUE );
 		paramMaxUploadSpeedSeeding.setLayoutData(gridData);
 		enable_seeding_rate
 				.setAdditionalActionPerformer(new ChangeSelectionActionPerformer(
@@ -176,7 +174,7 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
 			Messages.setLanguageText(label, "ConfigView.label.maxuploadswhenbusymin" );
 
 			gridData = new GridData();
-			new IntParameter(cSection, "max.uploads.when.busy.inc.min.secs", 0, -1).setLayoutData(gridData);
+			new IntParameter(cSection, "max.uploads.when.busy.inc.min.secs", 0, Integer.MAX_VALUE ).setLayoutData(gridData);
 		}
 		
 		// max download speed
@@ -187,7 +185,7 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
 		
 		gridData = new GridData();
 		final IntParameter paramMaxDownSpeed = new IntParameter(cSection,
-				"Max Download Speed KBs", 0, -1);
+				"Max Download Speed KBs", 0, Integer.MAX_VALUE );
 		paramMaxDownSpeed.setLayoutData(gridData);
 				
 			// max upload/download limit dependencies
@@ -338,7 +336,7 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
 			Messages.setLanguageText(label, "ConfigView.label.xfer.bias_slack");
 
 			IntParameter bias_slack = new IntParameter(
-					bias_slack_area, "Bias Upload Slack KBs", 1, -1);
+					bias_slack_area, "Bias Upload Slack KBs", 1, Integer.MAX_VALUE );
 			
 			
 			final Composite bias_unlimited_area = new Composite(cSection, SWT.NULL);
@@ -404,7 +402,7 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
 
 			gridData = new GridData();
 			IntParameter paramMaxUploads = new IntParameter(auto_group, "Max Uploads",
-					2, -1);
+					2, Integer.MAX_VALUE );
 			paramMaxUploads.setLayoutData(gridData);
 
 				// max uploads when seeding
@@ -433,7 +431,7 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
 
 			gridData = new GridData();
 			final IntParameter paramMaxUploadsSeeding = new IntParameter(
-					cMaxUploadsOptionsArea, "Max Uploads Seeding", 2, -1);
+					cMaxUploadsOptionsArea, "Max Uploads Seeding", 2, Integer.MAX_VALUE );
 			paramMaxUploadsSeeding.setLayoutData(gridData);
 
 			
@@ -479,7 +477,7 @@ public class ConfigSectionTransfer implements UISWTConfigSection {
 
 			gridData = new GridData();
 			final IntParameter paramMaxPeersSeeding = new IntParameter(
-					cMaxPeersOptionsArea, "Max.Peer.Connections.Per.Torrent.When.Seeding", 0, -1);
+					cMaxPeersOptionsArea, "Max.Peer.Connections.Per.Torrent.When.Seeding", 0, Integer.MAX_VALUE );
 			paramMaxPeersSeeding.setLayoutData(gridData);	
 			
 			/////
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeed.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeed.java
index 87d6177..efb281a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeed.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeed.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeedBeta.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeedBeta.java
index e11bbeb..379150c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeedBeta.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeedBeta.java
@@ -21,7 +21,7 @@ import com.aelitis.azureus.core.speedmanager.impl.v2.SpeedManagerAlgorithmProvid
 /**
  * Created on May 15, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -34,9 +34,6 @@ import com.aelitis.azureus.core.speedmanager.impl.v2.SpeedManagerAlgorithmProvid
  * 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 ConfigSectionTransferAutoSpeedBeta
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeedSelect.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeedSelect.java
index e220610..5d64b37 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeedSelect.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferAutoSpeedSelect.java
@@ -5,6 +5,7 @@ import org.gudy.azureus2.ui.swt.views.stats.TransferStatsView;
 import org.gudy.azureus2.ui.swt.config.*;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.plugins.ui.config.ConfigSection;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
@@ -35,7 +36,7 @@ import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerImpl;
 /**
  * Created on Jun 13, 2007
  * Created by Alan Snyder
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, Inc, 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
@@ -48,9 +49,6 @@ import com.aelitis.azureus.core.speedmanager.impl.SpeedManagerImpl;
  * 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 ConfigSectionTransferAutoSpeedSelect
@@ -587,7 +585,7 @@ public class ConfigSectionTransferAutoSpeedSelect
 	      	Utils.launch((String) ((Label) arg0.widget).getData());
 	      }
 	    });
-
+	    ClipboardCopy.addCopyToClipMenu( linkLabel );
 
         return cSection;
     }//configSectionCreate
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferLAN.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferLAN.java
index dd97407..d70a0e8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferLAN.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/configsections/ConfigSectionTransferLAN.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.configsections;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/file/FileInfoView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/file/FileInfoView.java
index 1110464..c4615cc 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/file/FileInfoView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/file/FileInfoView.java
@@ -3,11 +3,12 @@
  * Created : Oct 2, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.file;
@@ -115,12 +113,16 @@ public class FileInfoView
 	}
 
 	private void dataSourceChanged(Object newDataSource) {
-		if (newDataSource == null)
-			file = null;
-		else if (newDataSource instanceof Object[])
-			file = (DiskManagerFileInfo) ((Object[]) newDataSource)[0];
-		else if (newDataSource instanceof DiskManagerFileInfo)
+		if (newDataSource instanceof Object[]
+				&& ((Object[]) newDataSource).length > 0) {
+			newDataSource = ((Object[]) newDataSource)[0];
+		}
+		
+		if (newDataSource instanceof DiskManagerFileInfo) {
 			file = (DiskManagerFileInfo) newDataSource;
+		} else {
+			file = null;
+		}
 
 		Utils.execSWTThread(new AERunnable() {
 			public void runSupport() {
@@ -280,8 +282,8 @@ public class FileInfoView
 							
 						final int piece_number = pn;
 						
-						DiskManagerPiece	dm_piece = dm_pieces[piece_number];
-						PEPiece				pe_piece = pe_pieces[piece_number];
+						final DiskManagerPiece	dm_piece = dm_pieces[piece_number];
+						final PEPiece			pe_piece = pe_pieces[piece_number];
 						
 						final MenuItem force_piece = new MenuItem( menu, SWT.CHECK );
 						
@@ -306,6 +308,30 @@ public class FileInfoView
 					    			}
 					    		});
 						}
+						
+						final MenuItem reset_piece = new MenuItem( menu, SWT.PUSH );
+						
+						Messages.setLanguageText( reset_piece, "label.reset.piece" );
+							
+						boolean	can_reset = dm_piece.isDone() || dm_piece.getNbWritten() > 0;
+						
+						reset_piece.setEnabled( can_reset );
+													
+						reset_piece.addSelectionListener(
+					    	new SelectionAdapter()
+				    		{
+				    			public void 
+				    			widgetSelected(
+				    				SelectionEvent e) 
+				    			{
+				    				dm_piece.reset();
+				    				
+				    				if ( pe_piece != null ){
+				    					
+				    					pe_piece.reset();
+				    				}
+				    			}
+				    		});
 					}					
 				}
 			});
@@ -361,7 +387,7 @@ public class FileInfoView
 	}
 
 	private void fillFileInfoSection() {
-		if (topLabel == null) {
+		if (topLabel == null || topLabel.isDisposed()) {
 			return;
 		}
 		topLabel.setText( "" );
@@ -485,6 +511,9 @@ public class FileInfoView
 	}
 	
 	protected void refreshInfoCanvas() {
+		if (fileInfoCanvas == null || fileInfoCanvas.isDisposed()) {
+			return;
+		}
 		refreshInfoCanvasQueued = false;
 		Rectangle bounds = fileInfoCanvas.getClientArea();
 		if (bounds.width <= 0 || bounds.height <= 0)
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/PeerFilesView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/PeerFilesView.java
index 7fed05e..1acf2c5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/PeerFilesView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/PeerFilesView.java
@@ -300,8 +300,12 @@ public class PeerFilesView
 			
 			int percent = ( done * 1000 ) / (last_piece - first_piece + 1 );
 			
-			cell.setText(percent < 0 ? ""
-					: DisplayFormatters.formatPercentFromThousands((int) percent));
+			if ( !cell.setSortValue(percent) && cell.isValid()){
+
+				return;
+			}
+			
+			cell.setText(percent < 0 ? "" : DisplayFormatters.formatPercentFromThousands((int) percent));
 				
 		}
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/PeerInfoView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/PeerInfoView.java
index 0ab8449..00212dc 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/PeerInfoView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/PeerInfoView.java
@@ -3,11 +3,12 @@
  * Created : Oct 2, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.peer;
@@ -181,7 +179,8 @@ public class PeerInfoView
 	}
 
 	private void dataSourceChanged(Object newDataSource) {
-		if (newDataSource instanceof Object[]) {
+		if (newDataSource instanceof Object[]
+				&& ((Object[]) newDataSource).length > 0) {
 			newDataSource = ((Object[]) newDataSource)[0];
 		}
 		
@@ -336,6 +335,9 @@ public class PeerInfoView
 	}
 
 	private void swt_fillPeerInfoSection() {
+		if (peerInfoComposite == null || peerInfoComposite.isDisposed()) {
+			return;
+		}
 		if (imageLabel.getImage() != null) {
 			Image image = imageLabel.getImage();
 			imageLabel.setImage(null);
@@ -429,7 +431,8 @@ public class PeerInfoView
 	private void refreshInfoCanvas() {
 		refreshInfoCanvasQueued = false;
 
-		if (peerInfoComposite == null || !peerInfoComposite.isVisible()) {
+		if (peerInfoComposite == null || peerInfoComposite.isDisposed()
+				|| !peerInfoComposite.isVisible()) {
 			return;
 		}
 
@@ -633,7 +636,8 @@ public class PeerInfoView
 	}
 
 	private void delete() {
-		if (!imageLabel.isDisposed() && imageLabel.getImage() != null) {
+		if (imageLabel != null && !imageLabel.isDisposed()
+				&& imageLabel.getImage() != null) {
 			Image image = imageLabel.getImage();
 			imageLabel.setImage(null);
 			image.dispose();
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/RemotePieceDistributionView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/RemotePieceDistributionView.java
index 2c82b7c..4d006bf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/RemotePieceDistributionView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/peer/RemotePieceDistributionView.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.peer;
 
@@ -40,15 +37,17 @@ public class RemotePieceDistributionView extends PieceDistributionView {
 	 * @see org.gudy.azureus2.ui.swt.views.PieceDistributionView#dataSourceChanged(java.lang.Object)
 	 */
 	public void dataSourceChanged(Object newDataSource) {
-		if (newDataSource instanceof Object[]) {
+		if (newDataSource instanceof Object[]
+				&& ((Object[]) newDataSource).length > 0) {
 			newDataSource = ((Object[]) newDataSource)[0];
 		}
-		if (newDataSource == null) {
-			peer = null;
-			pem = null;
-		} else if (newDataSource instanceof PEPeer) {
+
+		if (newDataSource instanceof PEPeer) {
 			peer = (PEPeer) newDataSource;
 			pem = peer.getManager();
+		} else {
+			peer = null;
+			pem = null;
 		}
 
 		Utils.execSWTThread(new AERunnable() {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/piece/MyPieceDistributionView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/piece/MyPieceDistributionView.java
index 0117af6..5782b7b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/piece/MyPieceDistributionView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/piece/MyPieceDistributionView.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.piece;
@@ -41,15 +38,16 @@ public class MyPieceDistributionView
 	}
 	
 	public void dataSourceChanged(Object newDataSource) {
-		if (newDataSource instanceof DownloadManager) {
-			pem = ((DownloadManager) newDataSource).getPeerManager();
-		} else if (newDataSource instanceof Object[]) {
+		if (newDataSource instanceof Object[]
+				&& ((Object[]) newDataSource).length > 0) {
 			newDataSource = ((Object[]) newDataSource)[0];
-			if (newDataSource instanceof PEPiece) {
-				PEPiece piece = (PEPiece) newDataSource;
-				pem = piece.getManager();
-			}
+		}
 
+		if (newDataSource instanceof DownloadManager) {
+			pem = ((DownloadManager) newDataSource).getPeerManager();
+		} else if (newDataSource instanceof PEPiece) {
+			PEPiece piece = (PEPiece) newDataSource;
+			pem = piece.getManager();
 		} else {
 			pem = null;
 		}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/piece/PieceInfoView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/piece/PieceInfoView.java
index 7db5786..29d58d4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/piece/PieceInfoView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/piece/PieceInfoView.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.piece;
@@ -60,12 +57,19 @@ import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTView;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
+import org.gudy.azureus2.ui.swt.views.PiecesView;
 
-import com.aelitis.azureus.core.peermanager.PeerManager;
 import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker;
 import com.aelitis.azureus.util.MapUtils;
 
 /**
+ * Piece Map View.
+ * <p>
+ * This view is placed within the {@link PiecesView} even though it relies on
+ * a {@link DownloadManager} datasource instead of a {@link PEPiece}
+ * <p>
+ * Also placed in Library views
+ * 
  * @author TuxPaper
  * @created Feb 26, 2007
  *
@@ -169,7 +173,7 @@ public class PieceInfoView
 					}
 					fillPieceInfoSection();
 				}
-			} else 	if (objects.length > 0 && (objects[0] instanceof DownloadManager)) {
+			} else 	if (objects.length == 1 && (objects[0] instanceof DownloadManager)) {
 				oldBlockInfo = null;
 				synchronized( this ){
 					if (dlm != null) {
@@ -179,6 +183,20 @@ public class PieceInfoView
 					dlm.addPieceListener(this, false);
 				}
 				fillPieceInfoSection();
+			} else {
+				synchronized( this ){
+	  			if (dlm != null) {
+	  				dlm.removePieceListener(this);
+	  			}
+	  			dlm = null;
+				}
+			}
+		} else {
+			synchronized( this ){
+  			if (dlm != null) {
+  				dlm.removePieceListener(this);
+  			}
+  			dlm = null;
 			}
 		}
 	}
@@ -396,10 +414,12 @@ public class PieceInfoView
 						final PiecePicker picker = peer_manager.getPiecePicker();
 						
 						DiskManagerPiece[] 	dm_pieces = disk_manager.getPieces();
-							
+						PEPiece[]			pe_pieces = peer_manager.getPieces();
+
 						final int piece_number = pn;
 						
-						DiskManagerPiece	dm_piece = dm_pieces[piece_number];
+						final DiskManagerPiece	dm_piece = dm_pieces[piece_number];
+						final PEPiece			pm_piece = pe_pieces[piece_number];
 						
 						final MenuItem force_piece = new MenuItem( menu, SWT.CHECK );
 						
@@ -424,6 +444,30 @@ public class PieceInfoView
 					    			}
 					    		});
 						}
+						
+						final MenuItem reset_piece = new MenuItem( menu, SWT.PUSH );
+						
+						Messages.setLanguageText( reset_piece, "label.reset.piece" );
+							
+						boolean	can_reset = dm_piece.isDone() || dm_piece.getNbWritten() > 0;
+						
+						reset_piece.setEnabled( can_reset );
+													
+						reset_piece.addSelectionListener(
+					    	new SelectionAdapter()
+				    		{
+				    			public void 
+				    			widgetSelected(
+				    				SelectionEvent e) 
+				    			{
+				    				dm_piece.reset();
+				    				
+				    				if ( pm_piece != null ){
+				    					
+				    					pm_piece.reset();
+				    				}
+				    			}
+				    		});
 					}					
 				}
 			});
@@ -558,7 +602,8 @@ public class PieceInfoView
 			alreadyFilling = false;
 		}
 		
-		if (!pieceInfoCanvas.isVisible()) {
+		if (pieceInfoCanvas == null || pieceInfoCanvas.isDisposed()
+				|| !pieceInfoCanvas.isVisible()) {
 			return;
 		}
 		pieceInfoCanvas.layout(true);
@@ -573,7 +618,7 @@ public class PieceInfoView
 			GC gc = new GC(pieceInfoCanvas);
 			gc.fillRectangle(bounds);
 			gc.dispose();
-			topLabelLHS = "";
+			topLabelLHS = MessageText.getString("view.one.download.only");
 			updateTopLabel();
 			
 			return;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/ActivityView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/ActivityView.java
index cee4e7c..6b9ecca 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/ActivityView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/ActivityView.java
@@ -3,11 +3,12 @@
  * Created : 15 d�c. 2003}
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.stats;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/CacheView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/CacheView.java
index 9367217..16e58de 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/CacheView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/CacheView.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 13, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.stats;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTOpsPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTOpsPanel.java
index 83152b7..69322f4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTOpsPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTOpsPanel.java
@@ -2,11 +2,12 @@
  * Created on 22 juin 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.stats;
 
@@ -44,7 +42,6 @@ import org.gudy.azureus2.core3.util.TimerEventPerformer;
 import org.gudy.azureus2.core3.util.TimerEventPeriodic;
 import org.gudy.azureus2.ui.swt.Utils;
 
-import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.dht.DHT;
 import com.aelitis.azureus.core.dht.control.DHTControlActivity;
 import com.aelitis.azureus.core.dht.control.DHTControlListener;
@@ -316,6 +313,13 @@ DHTOpsPanel
 	{
 		//System.out.println( activity.getString() + "/" + type + "/" + activity.getCurrentState().getString());
 		
+		if ( activity.isQueued()){
+			
+				// ignore these until they become active
+			
+			return;
+		}
+		
 		synchronized( activity_map ){
 			
 			ActivityDetail details = activity_map.get( activity );
@@ -387,6 +391,11 @@ DHTOpsPanel
 		
 		Rectangle size = canvas.getBounds();
 
+		if ( size.width <= 0 || size.height <= 0 ){
+			
+			return;
+		}
+		
 		scale.width = size.width;
 		scale.height = size.height;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTOpsView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTOpsView.java
index abb5cf5..c533cae 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTOpsView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTOpsView.java
@@ -2,11 +2,12 @@
  * Created on 22 juin 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,13 +17,9 @@
  * 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.stats;
 
-import java.util.List;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.FillLayout;
@@ -53,18 +50,23 @@ public class DHTOpsView
 	Composite panel;
 	DHTOpsPanel drawPanel;
 	private final boolean autoAlpha;
+	private final boolean autoDHT;
+	
 	private int dht_type;
 	private AzureusCore core;
 	private UISWTView swtView;
 
+	public DHTOpsView() {
+		this(false);
+	}
 
 	public DHTOpsView(boolean autoAlpha) {
-		this.autoAlpha = autoAlpha;
-
+		this( autoAlpha, true );
 	}
 
-	public DHTOpsView() {
-		this(false);
+	public DHTOpsView(boolean autoAlpha, boolean autoDHT ) {
+		this.autoAlpha = autoAlpha;
+		this.autoDHT	= autoDHT;
 	}
 
 	private void init(AzureusCore core) {
@@ -110,15 +112,24 @@ public class DHTOpsView
 		}
 	}
 
-	private void initialize(Composite composite) {
-		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
-
-			public void azureusCoreRunning(AzureusCore core) {
-				DHTOpsView.this.core = core;
-				init(core);
-			}
-		});
-
+	public void
+	setDHT(
+		DHT		_dht )
+	{
+		dht	= _dht;
+	}
+	
+	public void initialize(Composite composite) {
+		if ( autoDHT ){
+			AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+	
+				public void azureusCoreRunning(AzureusCore core) {
+					DHTOpsView.this.core = core;
+					init(core);
+				}
+			});
+		}
+		
 		panel = new Composite(composite,SWT.NULL);
 		panel.setLayout(new FillLayout());    
 		drawPanel = new DHTOpsPanel(panel);    
@@ -150,7 +161,7 @@ public class DHTOpsView
 		return( MSGID_PREFIX + ".title.full" );
 	}
 
-	private 
+	public 
 	void delete() 
 	{	
 		if (drawPanel != null) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTView.java
index 63c0b2b..ec0e0e7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/DHTView.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 13, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.stats;
@@ -63,8 +60,10 @@ public class DHTView
   public static final int DHT_TYPE_MAIN 	= DHT.NW_MAIN;
   public static final int DHT_TYPE_CVS  	= DHT.NW_CVS;
   public static final int DHT_TYPE_MAIN_V6 	= DHT.NW_MAIN_V6;
-	public static final String MSGID_PREFIX = "DHTView";
+  public static final String MSGID_PREFIX = "DHTView";
 
+  private boolean auto_dht;
+  
   DHT dht;
   
   Composite panel;
@@ -102,7 +101,12 @@ public class DHTView
 	protected AzureusCore core;
   
 
-  public DHTView( ) {
+  public DHTView()
+  {
+	  this( true );
+  }
+  public DHTView( boolean _auto_dht ) {
+	auto_dht = _auto_dht;
     inGraph = SpeedGraphic.getInstance();
     outGraph = SpeedGraphic.getInstance();
   }
@@ -142,15 +146,40 @@ public class DHTView
     }
   }
   
-  private void initialize(Composite composite) {
-  	AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
-
-			public void azureusCoreRunning(AzureusCore core) {
-				DHTView.this.core = core;
-				init(core);
-			}
-		});
+  public void
+  setDHT(
+	DHT		_dht )
+  {
+	  if ( dht == null ){
 
+		  dht	= _dht;
+		  
+		  controlListener = new DHTControlListener() {
+		        public void activityChanged(DHTControlActivity activity,int type) {
+		          activityChanged = true;
+		        }                
+		      };
+		  dht.getControl().addListener(controlListener);
+		  
+	  }else if ( dht == _dht ){
+		  
+	  }else{
+		  
+		  Debug.out( "Not Supported ");
+	  }
+  }
+  
+  public void initialize(Composite composite) {
+	if ( auto_dht ){
+	  	AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+	
+				public void azureusCoreRunning(AzureusCore core) {
+					DHTView.this.core = core;
+					init(core);
+				}
+			});
+	}
+	
   	panel = new Composite(composite,SWT.NULL);
     GridLayout layout = new GridLayout();
     layout.numColumns = 2;
@@ -541,7 +570,7 @@ public class DHTView
   }
   
 
-  private void delete() {
+  public void delete() {
     Utils.disposeComposite(panel);
     if (dht != null) {
       dht.getControl().removeListener(controlListener);
@@ -568,7 +597,11 @@ public class DHTView
     return panel;
   }
   
-  private void refresh() {    
+  private void refresh() {
+	  // need to do these here otherwise they sit in an unpainted state
+	inGraph.refresh(false);
+	outGraph.refresh(false);
+	
   	if (dht == null) {
   		if (core != null) {
   			// keep trying until dht is avail
@@ -576,10 +609,7 @@ public class DHTView
   		}
 			return;
   	}
-    
-    inGraph.refresh(false);
-    outGraph.refresh(false);
-    
+        
     refreshGeneral();
     refreshDB();
     refreshTransportDetails();
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/StatsView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/StatsView.java
index a6f583e..ab0ed63 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/StatsView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/StatsView.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 13, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,37 +14,34 @@
  * 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.stats;
 
-import java.util.ArrayList;
-import java.util.Map;
-
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.CTabFolder;
-import org.eclipse.swt.custom.CTabItem;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.widgets.*;
-
+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.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.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.plugins.*;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance.UISWTViewEventListenerWrapper;
-import org.gudy.azureus2.ui.swt.pluginsimpl.*;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListenerEx;
 import org.gudy.azureus2.ui.swt.views.IViewAlwaysInitialize;
 
 import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
+import com.aelitis.azureus.ui.mdi.MdiEntry;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
+import com.aelitis.azureus.ui.swt.mdi.MdiEntrySWT;
+import com.aelitis.azureus.ui.swt.mdi.TabbedMdiInterface;
 
 /**
  * aka "Statistics View" that contains {@link ActivityView}, 
@@ -52,22 +49,18 @@ import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
  * {@link VivaldiView}
  */
 public class StatsView
-	implements IViewAlwaysInitialize, UISWTViewCoreEventListener
+	implements IViewAlwaysInitialize, UISWTViewCoreEventListenerEx
 {
 	public static String VIEW_ID = UISWTInstance.VIEW_STATISTICS;
 	
 	public static final int EVENT_PERIODIC_UPDATE = 0x100;
 
-	private CTabFolder folder;
-
-	private ArrayList<UISWTViewCore> tabViews = new ArrayList<UISWTViewCore>();
+	private TabbedMdiInterface tabbedMDI;
 
 	private UpdateThread updateThread;
 
 	private Object dataSource;
 
-	private UISWTViewCore activeView;
-
 	private UISWTView swtView;
 
 	private Composite parent;
@@ -88,9 +81,10 @@ public class StatsView
 
 			while (bContinue) {
 
-				for (UISWTViewCore iview : tabViews) {
+				MdiEntry[] entries = tabbedMDI.getEntries();
+				for (MdiEntry entry : entries) {
 					try {
-						iview.triggerEvent(EVENT_PERIODIC_UPDATE, null);
+						((MdiEntrySWT) entry).triggerEvent(EVENT_PERIODIC_UPDATE, null);
 					} catch (Exception e) {
 						Debug.printStackTrace(e);
 					}
@@ -111,24 +105,42 @@ public class StatsView
 		}
 	}
 
+	public
+	StatsView()
+	{
+	}
+	
+	public boolean
+	isCloneable()
+	{
+		return( true );
+	}
+	
+	public UISWTViewCoreEventListener
+	getClone()
+	{
+		return( new StatsView());
+	}
+	
 	private void initialize(Composite composite) {
 		parent = composite;
-		folder = new CTabFolder(composite, SWT.LEFT);
-		folder.setBorderVisible(true);
-
-		Label lblClose = new Label(folder, SWT.WRAP);
-		lblClose.setText("x");
-		lblClose.addListener(SWT.MouseUp, new Listener() {
-			public void handleEvent(Event event) {
-				delete();
-			}
-		});
-		folder.setTopRight(lblClose);
-		folder.setTabHeight(20);
 
     // Call plugin listeners
 		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
 		if (uiFunctions != null) {
+			tabbedMDI = uiFunctions.createTabbedMDI(composite, VIEW_ID);
+			
+			CTabFolder folder = tabbedMDI.getTabFolder();
+			Label lblClose = new Label(folder, SWT.WRAP);
+			lblClose.setText("x");
+			lblClose.addListener(SWT.MouseUp, new Listener() {
+				public void handleEvent(Event event) {
+					delete();
+				}
+			});
+			folder.setTopRight(lblClose);
+
+			
 			UISWTInstance pluginUI = uiFunctions.getUISWTInstance();
 
 			if (pluginUI != null && !registeredCoreSubViews) {
@@ -182,46 +194,19 @@ public class StatsView
 					String name = l.getViewID();
 				
 					try {
-						UISWTViewImpl view = new UISWTViewImpl(
-								UISWTInstance.VIEW_STATISTICS, name, l, null);
-						addSection(view, name);
+						MdiEntrySWT entry = (MdiEntrySWT) tabbedMDI.createEntryFromEventListener(
+								UISWTInstance.VIEW_STATISTICS, l, name, false, null, null);
+						entry.setDestroyOnDeactivate(false);
+						if ((dataSource == null && i == 0) || name.equals(dataSource)) {
+							tabbedMDI.showEntry(entry);
+						}
 					} catch (Exception e) {
 						// skip
 					}
 				}
 			}
 		}
-
-		// Initialize view when user selects it
-		folder.addSelectionListener(new SelectionAdapter() {
-			public void widgetSelected(SelectionEvent e) {
-				CTabItem item = (CTabItem) e.item;
-				selectView(item);
-			}
-		});
-
-		Utils.execSWTThreadLater(0, new AERunnable() {
-			public void runSupport() {
-				if (folder == null || folder.isDisposed() || folder.getItemCount() == 0) {
-					return;
-				}
-				if ( dataSource != null ){
-					for ( CTabItem item: folder.getItems()){
-						
-						String ds = (String)item.getData( "ds" );
-						
-						if ( dataSource.equals( ds )){
-							
-							selectView( item );
-							
-							return;
-						}
-					}
-				}
-				selectView(folder.getItem(0));
-			}
-		});
-
+		
 		updateThread = new UpdateThread();
 		updateThread.setDaemon(true);
 		updateThread.start();
@@ -229,142 +214,17 @@ public class StatsView
 		dataSourceChanged(dataSource);
 	}
 
-	private void selectView(CTabItem item) {
-		if (item == null) {
-			return;
-		}
-		if (folder.getSelection() != item) {
-			folder.setSelection(item);
-		}
-		folder.getShell().setCursor(
-				folder.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
-		try {
-			// Send one last refresh to previous tab, just in case it
-			// wants to do something when view goes invisible
-			refresh();
-
-			Object ds = item.getData("ds");
-						
-			if (ds == null) {
-				ds = dataSource;
-			}else{
-				dataSource = ds;
-			}
-
-			UISWTViewCore view = (UISWTViewCore) item.getData("IView");
-			if (view == null) {
-				Class<?> cla = (Class<?>)item.getData("claEventListener");
-				UISWTViewEventListener l = (UISWTViewEventListener) cla.newInstance();
-				view = new UISWTViewImpl(UISWTInstance.VIEW_MAIN, cla.getSimpleName(),
-						l, ds);
-				item.setData("IView", view);
-			}
-			activeView = view;
-
-			if (item.getControl() == null) {
-				view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, ds);
-				view.initialize(folder);
-				item.setControl(view.getComposite());
-			}
-
-			item.getControl().setFocus();
-
-			UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
-			if (uiFunctions != null) {
-				uiFunctions.getMDI().getEntry( StatsView.VIEW_ID ).setDatasource( dataSource );
-				
-				uiFunctions.refreshIconBar(); // For edit columns view
-			}
-
-			refresh();
-		} catch (Exception e) {
-			Debug.out(e);
-		} finally {
-			folder.getShell().setCursor(null);
-		}
-	}
-
-	// Copied from ManagerView
-	private UISWTViewCore getActiveView() {
-		return activeView;
-	}
-
 	// Copied from ManagerView
 	private void refresh() {
-		if (folder == null || folder.isDisposed())
+		if (tabbedMDI == null || tabbedMDI.isDisposed())
 			return;
 
-		try {
-			UISWTViewCore view = getActiveView();
-			if (view != null) {
-				view.triggerEvent(UISWTViewEvent.TYPE_REFRESH, null);
-			}
-
-			CTabItem[] items = folder.getItems();
-
-			for (int i = 0; i < items.length; i++) {
-				CTabItem item = items[i];
-				view = (UISWTViewCore) item.getData("IView");
-				try {
-					if (item.isDisposed() || view == null) {
-						continue;
-					}
-					String lastTitle = item.getText();
-					String newTitle = view.getFullTitle();
-					if (lastTitle == null || !lastTitle.equals(newTitle)) {
-						item.setText(escapeAccelerators(newTitle));
-					}
-					String lastToolTip = item.getToolTipText();
-					String newToolTip = view.getFullTitle();
-					if (lastToolTip == null || !lastToolTip.equals(newToolTip)) {
-						item.setToolTipText(newToolTip);
-					}
-				} catch (Exception e) {
-					Debug.printStackTrace(e);
-				}
-			}
-
-		} catch (Exception e) {
-			Debug.printStackTrace(e);
+		MdiEntrySWT entry = tabbedMDI.getCurrentEntrySWT();
+		if (entry != null) {
+			entry.updateUI();
 		}
 	}
 
-	private void focusGained()
-	{
-		if (folder == null || folder.isDisposed())
-			return;
-
-		try {			
-			CTabItem[] items = folder.getItems();
-
-			for (int i = 0; i < items.length; i++) {
-				CTabItem item = items[i];
-				UISWTViewCore view = (UISWTViewCore) item.getData("IView");
-				try {
-					if (item.isDisposed() || view == null) {
-						continue;
-					}
-					view.triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
-				} catch (Throwable e) {
-					Debug.printStackTrace(e);
-				}
-			}
-
-		} catch ( Throwable e) {
-			Debug.printStackTrace(e);
-		}
-	}
-	
-	// Copied from ManagerView
-	private static String escapeAccelerators(String str) {
-		if (str == null) {
-
-			return (str);
-		}
-
-		return (str.replaceAll("&", "&&"));
-	}
-
 	private String getFullTitle() {
 		return MessageText.getString("Stats.title.full");
 	}
@@ -374,93 +234,22 @@ public class StatsView
 			updateThread.stopIt();
 		}
 
-		if (folder != null && !folder.isDisposed()) {
-
-			folder.setSelection(0);
-		}
-
-		//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 (Utils.isCarbon) {
-			if (folder != null && !folder.isDisposed()) {
-				CTabItem[] items = folder.getItems();
-				for (int i = 0; i < items.length; i++) {
-					if (!items[i].isDisposed())
-						items[i].dispose();
-				}
-			}
-		}
-
-		for (int i = 0; i < tabViews.size(); i++) {
-			UISWTViewCore view = tabViews.get(i);
-			if (view != null) {
-    		view.triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
-			}
-		}
-		tabViews.clear();
-
 		Utils.disposeSWTObjects(new Object[] {
-			folder,
 			parent
 		});
 	}
 
 	private void dataSourceChanged(Object newDataSource) {
-		if ( dataSource == newDataSource ){
-			return;
-		}
-		if ( dataSource != null && newDataSource != null && dataSource.equals( newDataSource )){
-			return;
-		}
-		
 		dataSource = newDataSource;
-		if (folder == null) {
+		
+		
+		if (tabbedMDI == null) {
 			return;
 		}
-		if (newDataSource instanceof String) {
-			
-			for ( CTabItem item: folder.getItems()){
-				
-				String ds = (String)item.getData( "ds" );
-				
-				if ( newDataSource.equals( ds )){
-			
-					selectView(item);
-				}
-			}
-		}
-	}
-
-	/*
-	private int addSection(String titleIdPrefix, Class<?> claEventListener) {
-		return addSection(titleIdPrefix, claEventListener, null);
-	}
 
-	private int addSection(String titleIdPrefix, Class<?> claEventListener, Object ds) {
-		CTabItem item = new CTabItem(folder, SWT.NULL);
-		Messages.setLanguageText(item, titleIdPrefix + ".title.full");
-		item.setData("claEventListener", claEventListener);
-		if (ds != null) {
-			item.setData("ds", ds);
-		}
-		return folder.indexOf(item);
-	}
-	*/
-	
-	private void addSection(UISWTViewCore view, Object dataSource) {
-		if (view == null)
-			return;
-
-		view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, dataSource);
-
-		CTabItem item = new CTabItem(folder, SWT.NULL);
-		Messages.setLanguageText(item, view.getTitleID());
-		item.setData("IView", view);
-		if (dataSource != null) {
-			item.setData("ds", dataSource);
+		if (newDataSource instanceof String) {
+			tabbedMDI.showEntryByID((String) newDataSource);
 		}
-		tabViews.add(view);
 	}
 
 	/* (non-Javadoc)
@@ -471,6 +260,7 @@ public class StatsView
 			case UISWTViewEvent.TYPE_CREATE:
 				swtView = (UISWTView) event.getData();
 				swtView.setTitle(getFullTitle());
+				swtView.setDestroyOnDeactivate(false);
 				break;
 
 			case UISWTViewEvent.TYPE_DESTROY:
@@ -483,7 +273,6 @@ public class StatsView
 
 			case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
 				swtView.setTitle(getFullTitle());
-				Messages.updateLanguageForControl(folder);
 				break;
 
 			case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
@@ -491,7 +280,6 @@ public class StatsView
 				break;
 
 			case UISWTViewEvent.TYPE_FOCUSGAINED:
-				focusGained();
 				break;
 
 			case UISWTViewEvent.TYPE_REFRESH:
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/TagStatsView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/TagStatsView.java
index 19bf36f..955054d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/TagStatsView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/TagStatsView.java
@@ -1,624 +1,623 @@
-/*
- * Created on May 1, 2013
- * Created by Paul Gardner
- * 
- * Copyright 2013 Azureus Software, 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.stats;
-
-import java.util.*;
-
-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.graphics.Color;
-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.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Listener;
-
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.gudy.azureus2.ui.swt.Messages;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.components.Legend;
-import org.gudy.azureus2.ui.swt.components.graphics.MultiPlotGraphic;
-import org.gudy.azureus2.ui.swt.components.graphics.ValueFormater;
-import org.gudy.azureus2.ui.swt.components.graphics.ValueSource;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-import org.gudy.azureus2.ui.swt.plugins.UISWTView;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
-import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
-
-import com.aelitis.azureus.core.tag.*;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-
-
-public class TagStatsView 
-	extends TagTypeAdapter
-	implements UISWTViewCoreEventListener, TagManagerListener
-{	
-	public static final String MSGID_PREFIX = "TagStatsView";
-  
-	private Composite 			panel;
-	private Group	 			legend_panel;
-	private ScrolledComposite	legend_panel_sc;
-  
-	private Composite			speed_panel;
-	
-	private UISWTView swtView;  
-  
-	private MultiPlotGraphic 		mpg;
-	
-	
-	public 
-	TagStatsView() 
-	{
-	}
-  
- 
-	public void 
-	periodicUpdate() 
-	{
-
-	}
-  
-	private void 
-	initialize(
-		Composite composite) 
-	{
-	    panel = new Composite(composite,SWT.NULL);	    
-	    panel.setLayout(new GridLayout(2, false));
-	    
-	    legend_panel_sc = new ScrolledComposite(panel, SWT.V_SCROLL );
-	    legend_panel_sc.setExpandHorizontal(true);
-	    legend_panel_sc.setExpandVertical(true);
-		GridLayout layout = new GridLayout();
-		layout.horizontalSpacing = 0;
-		layout.verticalSpacing = 0;
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		legend_panel_sc.setLayout(layout);
-		GridData gridData = new GridData(GridData.FILL_VERTICAL );
-		legend_panel_sc.setLayoutData(gridData);
-		
-		legend_panel = new Group( legend_panel_sc, SWT.NULL );
-		legend_panel.setText( MessageText.getString( "label.tags" ));
-		
-		legend_panel.setLayout(new GridLayout());
-
-		legend_panel_sc.setContent(legend_panel);
-		legend_panel_sc.addControlListener(new ControlAdapter() {
-			public void controlResized(ControlEvent e) {
-				legend_panel_sc.setMinSize(legend_panel.computeSize(SWT.DEFAULT, SWT.DEFAULT ));
-			}
-		});
-	    
-		speed_panel = new Composite( panel, SWT.NULL );
-		speed_panel.setLayout(new GridLayout());
-		gridData = new GridData(GridData.FILL_BOTH );
-		speed_panel.setLayoutData(gridData);
-		
-	    build();
-    
-	    TagManager tm = TagManagerFactory.getTagManager();
-	    
-	    tm.addTagManagerListener( this, false );
-	    
-	    for ( TagType tt: tm.getTagTypes()){
-	    	
-	    	tt.addTagTypeListener( this, false );
-	    }
-	    
-		panel.addListener( 
-			SWT.Activate,
-			new Listener()
-			{
-				public void 
-				handleEvent(
-					Event event )
-				{
-					refresh(true);
-				}
-			});
-	}
-  
-	private void
-	build()
-	{
-		if ( legend_panel == null || legend_panel.isDisposed()){
-			
-			return;
-		}
-		
-		for ( Control c: legend_panel.getChildren()){
-			
-			c.dispose();
-		}
-		
-		List<String>	configs 		= new ArrayList<String>();
-		List<String>	texts			= new ArrayList<String>();	
-		List<Color>		colors			= new ArrayList<Color>();
-		
-		TagManager tm = TagManagerFactory.getTagManager();
-		
-		List<TagType> tag_types = tm.getTagTypes();
-		
-		tag_types	= TagUIUtils.sortTagTypes( tag_types );
-		
-		List<TagFeatureRateLimit>	visible_tags = new ArrayList<TagFeatureRateLimit>();
-				
-		for ( TagType tag_type: tag_types ){
-						
-			if ( tag_type.hasTagTypeFeature( TagFeature.TF_RATE_LIMIT )){
-				
-				List<Tag> tags = tag_type.getTags();
-				
-				tags = TagUIUtils.sortTags( tags );
-				
-				for ( Tag tag: tags ){
-					
-					if ( !tag.isVisible()){
-						
-						continue;
-					}
-					
-					TagFeatureRateLimit rl = (TagFeatureRateLimit)tag;
-
-					if ( !rl.supportsTagRates()){
-						
-						continue;
-					}
-					
-					String	config_key = "TagStatsView.cc." + tag_type.getTagType() + "." + tag.getTagID();
-					
-					configs.add( config_key );
-					
-					texts.add( tag.getTagName( true ));
-					
-					Color tt_colour;
-					
-					int[]	rgb = tag.getColor();
-					
-					if ( rgb == null ){
-					
-						tt_colour = Colors.blues[ Colors.BLUES_DARKEST];
-             
-					}else{
-						
-						tt_colour = ColorCache.getColor( legend_panel.getDisplay(), rgb );
-					}
-					
-					colors.add( tt_colour );
-					
-					visible_tags.add( rl );
-				}
-			}
-		}
-		
-		
-		final Color[]		color_array = colors.toArray( new Color[ colors.size()]);
-		final String[]		text_array = texts.toArray( new String[ texts.size()]);
-
-	    final List<ValueSourceImpl>	sources = new ArrayList<ValueSourceImpl>();
-	    	    
-		List<int[]>	history_records 	= new ArrayList<int[]>();
-		int			history_record_max	= 0;
-		
-	    for ( int i=0;i<visible_tags.size();i++ ){
-	    	
-	    	final TagFeatureRateLimit tag = visible_tags.get(i);
-
-			tag.setRecentHistoryRetention( true );
-			
-			int[][] history = tag.getRecentHistory();
-			
-			history_record_max = Math.max( history[0].length, history_record_max );
-			
-			history_records.add( history[0] );
-			history_records.add( history[1] );
-	    	
-	    	sources.add( new ValueSourceImpl( tag, text_array[i], i, color_array, true ));
-	    	sources.add( new ValueSourceImpl( tag, text_array[i], i, color_array, false ));
-	    };
-		
-	    ValueFormater formatter =
-	    	new ValueFormater() 
-	    	{
-	        	public String 
-	        	format(
-	        		int value) 
-	        	{
-	        		return DisplayFormatters.formatByteCountToKiBEtcPerSec( value );
-	        	}
-	    	};
-	      
-
-		
-		if ( mpg != null ){
-			
-			mpg.dispose();
-		}
-
-		final MultiPlotGraphic f_mpg = mpg = MultiPlotGraphic.getInstance( sources.toArray( new ValueSource[ sources.size()]), formatter );
-
-		int[][] history = new int[history_records.size()][];
-		
-		for ( int i=0;i<history.length;i++){
-			int[] 	hist 		= history_records.get(i);
-			int		hist_len 	= hist.length;
-			
-			if ( hist_len == history_record_max ){
-				history[i] = hist;
-			}else{
-				int[] temp = new int[history_record_max];
-				System.arraycopy( hist, 0, temp, history_record_max-hist_len, hist_len );
-				history[i] = temp;
-			}
-		}
-		
-		mpg.reset( history );
-		
-	    GridData gridData;
-	    		
-		if ( color_array.length > 0 ){
-		
-			gridData = new GridData( GridData.FILL_VERTICAL );
-			gridData.verticalAlignment = SWT.CENTER;
-
-			Legend.createLegendComposite(
-				legend_panel, 
-				color_array, 
-				configs.toArray( new String[ configs.size()]), 
-				text_array,
-				gridData, 
-				false,
-				new Legend.LegendListener()
-				{
-					private int	hover_index = -1;
-					
-					public void 
-					hoverChange(
-						boolean 	entry, 
-						int 		index ) 
-					{
-						if ( hover_index != -1 ){
-							
-							for ( int i=hover_index*2;i<hover_index*2+2;i++){
-								
-								sources.get(i).setHover( false );
-							}
-						}
-						
-						if ( entry ){
-							
-							hover_index = index;
-							
-							for ( int i=hover_index*2;i<hover_index*2+2;i++){
-								
-								sources.get(i).setHover( true );
-							}
-						}
-											
-						f_mpg.refresh( true );
-					}
-					
-					public void
-					visibilityChange(
-						boolean	visible,
-						int		index )
-					{
-						for ( int i=index*2;i<index*2+2;i++){
-							
-							sources.get(i).setVisible( visible );
-						}
-						
-						f_mpg.refresh( true );
-					}
-				});
-		}else{
-
-			gridData = new GridData( GridData.FILL_HORIZONTAL );
-			gridData.verticalAlignment = SWT.TOP;
-
-			Label lab = new Label( legend_panel, SWT.NULL );
-			lab.setText( MessageText.getString( "tag.stats.none.defined" ));
-			
-			lab.setLayoutData( gridData );
-		}
-		
-		legend_panel_sc.setMinSize(legend_panel.computeSize(SWT.DEFAULT, SWT.DEFAULT ));
-		
-			// speed
-		
-		for ( Control c: speed_panel.getChildren()){
-			
-			c.dispose();
-		}
-				
-	    Canvas speed_canvas = new Canvas( speed_panel,SWT.NO_BACKGROUND);
-	    gridData = new GridData(GridData.FILL_BOTH);
-	    speed_canvas.setLayoutData(gridData);
-
-
-		mpg.initialize( speed_canvas, true );
-		
-	    panel.layout( true, true );
-	    
-	}
-	
-	private void
-	rebuild()
-	{
-		Utils.execSWTThread(
-			new Runnable()
-			{
-				public void
-				run()
-				{
-					build();
-				}
-			});
-	}
-	
-	private void
-	rebuild(
-		TagType		tag_type,
-		boolean		added )
-	{
-		if ( panel == null || panel.isDisposed()){
-			
-			tag_type.getTagManager().removeTagManagerListener( this );
-		
-			return;
-		}
-		
-		if ( added ){
-			
-			tag_type.addTagTypeListener( this, false );
-		}
-		
-		rebuild();
-	}
-	
-	public void
-	tagTypeAdded(
-		TagManager		manager,
-		TagType			tag_type )
-	{
-		rebuild( tag_type, true );
-	}
-	
-	public void
-	tagTypeRemoved(
-		TagManager		manager,
-		TagType			tag_type )
-	{		
-		rebuild( tag_type, false );
-	}
-	
-	private void
-	rebuild(
-		Tag			tag )
-	{
-		if ( panel == null || panel.isDisposed()){
-			
-			TagType tt = tag.getTagType();
-			
-			tt.removeTagTypeListener( this );
-			
-			tt.getTagManager().removeTagManagerListener( this );
-			
-			return;
-		}
-		
-		rebuild();
-	}
-	
-	public void
-	tagAdded(
-		Tag			tag )
-	{
-		rebuild( tag );
-	}
-	
-	public void
-	tagRemoved(
-		Tag			tag )
-	{
-		rebuild( tag );
-	}
-	
-	private void 
-	delete() 
-	{    
-	    Utils.disposeComposite( panel );
-	    
-	    TagManager tm = TagManagerFactory.getTagManager();
-	    
-	    tm.removeTagManagerListener( this );
-	    
-	    for ( TagType tt: tm.getTagTypes()){
-	    	
-	    	tt.removeTagTypeListener( this );
-	    }
-	    
-	    if ( mpg != null ){
-	    	
-	    	mpg.dispose();
-	    }
-	}
-
-
-  
-	private void 
-	refresh(
-		boolean force) 
-	{
-		if ( mpg != null ){
-		
-			mpg.refresh( force );
-		}
-	}  
-  
-	public boolean 
-	eventOccurred(
-		UISWTViewEvent event) 
-	{
-		switch (event.getType()) {
-			case UISWTViewEvent.TYPE_CREATE:
-				swtView = event.getView();
-				swtView.setTitle(MessageText.getString(MSGID_PREFIX + ".title.full"));
-				break;
-	
-			case UISWTViewEvent.TYPE_DESTROY:
-				delete();
-				break;
-	
-			case UISWTViewEvent.TYPE_INITIALIZE:
-				initialize((Composite)event.getData());
-				break;
-	
-			case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
-				Messages.updateLanguageForControl( panel );
-				break;
-	
-			case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
-				break;
-	
-			case UISWTViewEvent.TYPE_FOCUSGAINED:
-				refresh(true);
-				break;
-	
-			case UISWTViewEvent.TYPE_REFRESH:
-				refresh(false);
-				break;
-	
-			case StatsView.EVENT_PERIODIC_UPDATE:
-				periodicUpdate();
-				break;
-		}
-
-		return true;
-	}
-	
-	private static class
-	ValueSourceImpl
-		implements ValueSource
-	{	
-		TagFeatureRateLimit		tag;
-		String					name;
-		int						index;
-		Color[]					colours;
-		boolean					is_up;
-		
-		private boolean			is_hover;
-		private boolean			is_invisible;
-		
-		private
-		ValueSourceImpl(
-			TagFeatureRateLimit		_tag,
-			String					_name,
-			int						_index,
-			Color[]					_colours,
-			boolean					_is_up )
-		{
-			tag		= _tag;
-			name	= _name;
-			index	= _index;
-			colours	= _colours;
-			is_up	= _is_up;
-		}
-			
-		public String
-		getName()
-		{
-			return( name );
-		}
-		
-		public Color 
-		getLineColor() 
-		{
-			return( colours[index] );
-		}
-		
-		public boolean
-		isTrimmable()
-		{
-			return( false );
-		}
-		
-		private void
-		setHover(
-			boolean	h )
-		{
-			is_hover = h;
-		}
-		
-		public int 
-		getAlpha() 
-		{
-			return( 255 );
-		}
-		
-		private void
-		setVisible(
-			boolean	visible )
-		{
-			is_invisible = !visible;
-		}
-		
-		public int 
-		getStyle() 
-		{
-			if ( is_invisible ){
-				
-				return( STYLE_INVISIBLE );
-			}
-			
-			int	style = is_up?STYLE_UP:STYLE_DOWN;
-			
-			if ( is_hover ){
-				
-				style |= STYLE_BOLD;
-			}
-			
-			return( style );
-		}
-		
-		public int
-		getValue()
-		{
-			int rate = is_up?tag.getTagCurrentUploadRate():tag.getTagCurrentDownloadRate();
-			
-			if ( rate < 0 ){
-				
-				rate = 0;
-			}
-			
-			return( rate );
-		}
-	}
-}
+/*
+ * Created on May 1, 2013
+ * Created by Paul Gardner
+ * 
+ * Copyright 2013 Azureus Software, 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 org.gudy.azureus2.ui.swt.views.stats;
+
+import java.util.*;
+
+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.graphics.Color;
+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.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+
+
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.components.Legend;
+import org.gudy.azureus2.ui.swt.components.graphics.MultiPlotGraphic;
+import org.gudy.azureus2.ui.swt.components.graphics.ValueFormater;
+import org.gudy.azureus2.ui.swt.components.graphics.ValueSource;
+import org.gudy.azureus2.ui.swt.mainwindow.Colors;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
+import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
+
+import com.aelitis.azureus.core.tag.*;
+import com.aelitis.azureus.ui.swt.utils.ColorCache;
+
+
+public class TagStatsView 
+	extends TagTypeAdapter
+	implements UISWTViewCoreEventListener, TagManagerListener
+{	
+	public static final String MSGID_PREFIX = "TagStatsView";
+  
+	private Composite 			panel;
+	private Group	 			legend_panel;
+	private ScrolledComposite	legend_panel_sc;
+  
+	private Composite			speed_panel;
+	
+	private UISWTView swtView;  
+  
+	private MultiPlotGraphic 		mpg;
+	
+	
+	public 
+	TagStatsView() 
+	{
+	}
+  
+ 
+	public void 
+	periodicUpdate() 
+	{
+
+	}
+  
+	private void 
+	initialize(
+		Composite composite) 
+	{
+	    panel = new Composite(composite,SWT.NULL);	    
+	    panel.setLayout(new GridLayout(2, false));
+	    
+	    legend_panel_sc = new ScrolledComposite(panel, SWT.V_SCROLL );
+	    legend_panel_sc.setExpandHorizontal(true);
+	    legend_panel_sc.setExpandVertical(true);
+		GridLayout layout = new GridLayout();
+		layout.horizontalSpacing = 0;
+		layout.verticalSpacing = 0;
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		legend_panel_sc.setLayout(layout);
+		GridData gridData = new GridData(GridData.FILL_VERTICAL );
+		legend_panel_sc.setLayoutData(gridData);
+		
+		legend_panel = new Group( legend_panel_sc, SWT.NULL );
+		legend_panel.setText( MessageText.getString( "label.tags" ));
+		
+		legend_panel.setLayout(new GridLayout());
+
+		legend_panel_sc.setContent(legend_panel);
+		legend_panel_sc.addControlListener(new ControlAdapter() {
+			public void controlResized(ControlEvent e) {
+				legend_panel_sc.setMinSize(legend_panel.computeSize(SWT.DEFAULT, SWT.DEFAULT ));
+			}
+		});
+	    
+		speed_panel = new Composite( panel, SWT.NULL );
+		speed_panel.setLayout(new GridLayout());
+		gridData = new GridData(GridData.FILL_BOTH );
+		speed_panel.setLayoutData(gridData);
+		
+	    build();
+    
+	    TagManager tm = TagManagerFactory.getTagManager();
+	    
+	    tm.addTagManagerListener( this, false );
+	    
+	    for ( TagType tt: tm.getTagTypes()){
+	    	
+	    	tt.addTagTypeListener( this, false );
+	    }
+	    
+		panel.addListener( 
+			SWT.Activate,
+			new Listener()
+			{
+				public void 
+				handleEvent(
+					Event event )
+				{
+					refresh(true);
+				}
+			});
+	}
+  
+	private void
+	build()
+	{
+		if ( legend_panel == null || legend_panel.isDisposed()){
+			
+			return;
+		}
+		
+		for ( Control c: legend_panel.getChildren()){
+			
+			c.dispose();
+		}
+		
+		List<String>	configs 		= new ArrayList<String>();
+		List<String>	texts			= new ArrayList<String>();	
+		List<Color>		colors			= new ArrayList<Color>();
+		
+		TagManager tm = TagManagerFactory.getTagManager();
+		
+		List<TagType> tag_types = tm.getTagTypes();
+		
+		tag_types	= TagUIUtils.sortTagTypes( tag_types );
+		
+		List<TagFeatureRateLimit>	visible_tags = new ArrayList<TagFeatureRateLimit>();
+				
+		for ( TagType tag_type: tag_types ){
+						
+			if ( tag_type.hasTagTypeFeature( TagFeature.TF_RATE_LIMIT )){
+				
+				List<Tag> tags = tag_type.getTags();
+				
+				tags = TagUIUtils.sortTags( tags );
+				
+				for ( Tag tag: tags ){
+					
+					if ( !tag.isVisible()){
+						
+						continue;
+					}
+					
+					TagFeatureRateLimit rl = (TagFeatureRateLimit)tag;
+
+					if ( !rl.supportsTagRates()){
+						
+						continue;
+					}
+					
+					String	config_key = "TagStatsView.cc." + tag_type.getTagType() + "." + tag.getTagID();
+					
+					configs.add( config_key );
+					
+					texts.add( tag.getTagName( true ));
+					
+					Color tt_colour;
+					
+					int[]	rgb = tag.getColor();
+					
+					if ( rgb == null ){
+					
+						tt_colour = Colors.blues[ Colors.BLUES_DARKEST];
+             
+					}else{
+						
+						tt_colour = ColorCache.getColor( legend_panel.getDisplay(), rgb );
+					}
+					
+					colors.add( tt_colour );
+					
+					visible_tags.add( rl );
+				}
+			}
+		}
+		
+		
+		final Color[]		color_array = colors.toArray( new Color[ colors.size()]);
+		final String[]		text_array = texts.toArray( new String[ texts.size()]);
+
+	    final List<ValueSourceImpl>	sources = new ArrayList<ValueSourceImpl>();
+	    	    
+		List<int[]>	history_records 	= new ArrayList<int[]>();
+		int			history_record_max	= 0;
+		
+	    for ( int i=0;i<visible_tags.size();i++ ){
+	    	
+	    	final TagFeatureRateLimit tag = visible_tags.get(i);
+
+			tag.setRecentHistoryRetention( true );
+			
+			int[][] history = tag.getRecentHistory();
+			
+			history_record_max = Math.max( history[0].length, history_record_max );
+			
+			history_records.add( history[0] );
+			history_records.add( history[1] );
+	    	
+	    	sources.add( new ValueSourceImpl( tag, text_array[i], i, color_array, true ));
+	    	sources.add( new ValueSourceImpl( tag, text_array[i], i, color_array, false ));
+	    };
+		
+	    ValueFormater formatter =
+	    	new ValueFormater() 
+	    	{
+	        	public String 
+	        	format(
+	        		int value) 
+	        	{
+	        		return DisplayFormatters.formatByteCountToKiBEtcPerSec( value );
+	        	}
+	    	};
+	      
+
+		
+		if ( mpg != null ){
+			
+			mpg.dispose();
+		}
+
+		final MultiPlotGraphic f_mpg = mpg = MultiPlotGraphic.getInstance( sources.toArray( new ValueSource[ sources.size()]), formatter );
+
+		int[][] history = new int[history_records.size()][];
+		
+		for ( int i=0;i<history.length;i++){
+			int[] 	hist 		= history_records.get(i);
+			int		hist_len 	= hist.length;
+			
+			if ( hist_len == history_record_max ){
+				history[i] = hist;
+			}else{
+				int[] temp = new int[history_record_max];
+				System.arraycopy( hist, 0, temp, history_record_max-hist_len, hist_len );
+				history[i] = temp;
+			}
+		}
+		
+		mpg.reset( history );
+		
+	    GridData gridData;
+	    		
+		if ( color_array.length > 0 ){
+		
+			gridData = new GridData( GridData.FILL_VERTICAL );
+			gridData.verticalAlignment = SWT.CENTER;
+
+			Legend.createLegendComposite(
+				legend_panel, 
+				color_array, 
+				configs.toArray( new String[ configs.size()]), 
+				text_array,
+				gridData, 
+				false,
+				new Legend.LegendListener()
+				{
+					private int	hover_index = -1;
+					
+					public void 
+					hoverChange(
+						boolean 	entry, 
+						int 		index ) 
+					{
+						if ( hover_index != -1 ){
+							
+							for ( int i=hover_index*2;i<hover_index*2+2;i++){
+								
+								sources.get(i).setHover( false );
+							}
+						}
+						
+						if ( entry ){
+							
+							hover_index = index;
+							
+							for ( int i=hover_index*2;i<hover_index*2+2;i++){
+								
+								sources.get(i).setHover( true );
+							}
+						}
+											
+						f_mpg.refresh( true );
+					}
+					
+					public void
+					visibilityChange(
+						boolean	visible,
+						int		index )
+					{
+						for ( int i=index*2;i<index*2+2;i++){
+							
+							sources.get(i).setVisible( visible );
+						}
+						
+						f_mpg.refresh( true );
+					}
+				});
+		}else{
+
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			gridData.verticalAlignment = SWT.TOP;
+
+			Label lab = new Label( legend_panel, SWT.NULL );
+			lab.setText( MessageText.getString( "tag.stats.none.defined" ));
+			
+			lab.setLayoutData( gridData );
+		}
+		
+		legend_panel_sc.setMinSize(legend_panel.computeSize(SWT.DEFAULT, SWT.DEFAULT ));
+		
+			// speed
+		
+		for ( Control c: speed_panel.getChildren()){
+			
+			c.dispose();
+		}
+				
+	    Canvas speed_canvas = new Canvas( speed_panel,SWT.NO_BACKGROUND);
+	    gridData = new GridData(GridData.FILL_BOTH);
+	    speed_canvas.setLayoutData(gridData);
+
+
+		mpg.initialize( speed_canvas, true );
+		
+	    panel.layout( true, true );
+	    
+	}
+	
+	private void
+	rebuild()
+	{
+		Utils.execSWTThread(
+			new Runnable()
+			{
+				public void
+				run()
+				{
+					build();
+				}
+			});
+	}
+	
+	private void
+	rebuild(
+		TagType		tag_type,
+		boolean		added )
+	{
+		if ( panel == null || panel.isDisposed()){
+			
+			tag_type.getTagManager().removeTagManagerListener( this );
+		
+			return;
+		}
+		
+		if ( added ){
+			
+			tag_type.addTagTypeListener( this, false );
+		}
+		
+		rebuild();
+	}
+	
+	public void
+	tagTypeAdded(
+		TagManager		manager,
+		TagType			tag_type )
+	{
+		rebuild( tag_type, true );
+	}
+	
+	public void
+	tagTypeRemoved(
+		TagManager		manager,
+		TagType			tag_type )
+	{		
+		rebuild( tag_type, false );
+	}
+	
+	private void
+	rebuild(
+		Tag			tag )
+	{
+		if ( panel == null || panel.isDisposed()){
+			
+			TagType tt = tag.getTagType();
+			
+			tt.removeTagTypeListener( this );
+			
+			tt.getTagManager().removeTagManagerListener( this );
+			
+			return;
+		}
+		
+		rebuild();
+	}
+	
+	public void
+	tagAdded(
+		Tag			tag )
+	{
+		rebuild( tag );
+	}
+	
+	public void
+	tagRemoved(
+		Tag			tag )
+	{
+		rebuild( tag );
+	}
+	
+	private void 
+	delete() 
+	{    
+	    Utils.disposeComposite( panel );
+	    
+	    TagManager tm = TagManagerFactory.getTagManager();
+	    
+	    tm.removeTagManagerListener( this );
+	    
+	    for ( TagType tt: tm.getTagTypes()){
+	    	
+	    	tt.removeTagTypeListener( this );
+	    }
+	    
+	    if ( mpg != null ){
+	    	
+	    	mpg.dispose();
+	    }
+	}
+
+
+  
+	private void 
+	refresh(
+		boolean force) 
+	{
+		if ( mpg != null ){
+		
+			mpg.refresh( force );
+		}
+	}  
+  
+	public boolean 
+	eventOccurred(
+		UISWTViewEvent event) 
+	{
+		switch (event.getType()) {
+			case UISWTViewEvent.TYPE_CREATE:
+				swtView = event.getView();
+				swtView.setTitle(MessageText.getString(MSGID_PREFIX + ".title.full"));
+				break;
+	
+			case UISWTViewEvent.TYPE_DESTROY:
+				delete();
+				break;
+	
+			case UISWTViewEvent.TYPE_INITIALIZE:
+				initialize((Composite)event.getData());
+				break;
+	
+			case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
+				Messages.updateLanguageForControl( panel );
+				break;
+	
+			case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
+				break;
+	
+			case UISWTViewEvent.TYPE_FOCUSGAINED:
+				refresh(true);
+				break;
+	
+			case UISWTViewEvent.TYPE_REFRESH:
+				refresh(false);
+				break;
+	
+			case StatsView.EVENT_PERIODIC_UPDATE:
+				periodicUpdate();
+				break;
+		}
+
+		return true;
+	}
+	
+	private static class
+	ValueSourceImpl
+		implements ValueSource
+	{	
+		TagFeatureRateLimit		tag;
+		String					name;
+		int						index;
+		Color[]					colours;
+		boolean					is_up;
+		
+		private boolean			is_hover;
+		private boolean			is_invisible;
+		
+		private
+		ValueSourceImpl(
+			TagFeatureRateLimit		_tag,
+			String					_name,
+			int						_index,
+			Color[]					_colours,
+			boolean					_is_up )
+		{
+			tag		= _tag;
+			name	= _name;
+			index	= _index;
+			colours	= _colours;
+			is_up	= _is_up;
+		}
+			
+		public String
+		getName()
+		{
+			return( name );
+		}
+		
+		public Color 
+		getLineColor() 
+		{
+			return( colours[index] );
+		}
+		
+		public boolean
+		isTrimmable()
+		{
+			return( false );
+		}
+		
+		private void
+		setHover(
+			boolean	h )
+		{
+			is_hover = h;
+		}
+		
+		public int 
+		getAlpha() 
+		{
+			return( 255 );
+		}
+		
+		private void
+		setVisible(
+			boolean	visible )
+		{
+			is_invisible = !visible;
+		}
+		
+		public int 
+		getStyle() 
+		{
+			if ( is_invisible ){
+				
+				return( STYLE_INVISIBLE );
+			}
+			
+			int	style = is_up?STYLE_UP:STYLE_DOWN;
+			
+			if ( is_hover ){
+				
+				style |= STYLE_BOLD;
+			}
+			
+			return( style );
+		}
+		
+		public int
+		getValue()
+		{
+			int rate = is_up?tag.getTagCurrentUploadRate():tag.getTagCurrentDownloadRate();
+			
+			if ( rate < 0 ){
+				
+				rate = 0;
+			}
+			
+			return( rate );
+		}
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/TransferStatsView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/TransferStatsView.java
index fffe96f..c0dbacb 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/TransferStatsView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/TransferStatsView.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 13, 2004
  * Created by Olivier Chalouhi
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.stats;
@@ -106,6 +103,7 @@ import com.aelitis.azureus.core.speedmanager.SpeedManagerPingSource;
 import com.aelitis.azureus.core.speedmanager.SpeedManagerPingZone;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.net.udp.uc.PRUDPPacketHandler;
 import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory;
 
@@ -120,7 +118,6 @@ public class TransferStatsView
 	private static final int MAX_DISPLAYED_PING_MILLIS		= 1199;	// prevents us hitting 1200 and resulting in graph expanding to 1400
 	private static final int MAX_DISPLAYED_PING_MILLIS_DISP	= 1200;	// tidy display
 	
-	private AzureusCore			azureus_core;
 	private GlobalManager		global_manager;
 	private GlobalManagerStats 	stats;
 	private SpeedManager 		speedManager;
@@ -174,7 +171,6 @@ public class TransferStatsView
   public TransferStatsView() {
   	AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
 			public void azureusCoreRunning(AzureusCore core) {
-				azureus_core	= core;
 				global_manager = core.getGlobalManager();
 				stats = global_manager.getStats();
 				speedManager = core.getSpeedManager();
@@ -339,7 +335,8 @@ public class TransferStatsView
 
     				if (uif != null) {
 
-    					uif.openView(UIFunctions.VIEW_CONFIG, "Stats");
+							uif.getMDI().showEntryByID(
+									MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG, "Stats");
     				}
     			}
     		});
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/VivaldiPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/VivaldiPanel.java
index 3db0ad7..54b56b1 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/VivaldiPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/VivaldiPanel.java
@@ -2,11 +2,12 @@
  * Created on 22 juin 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.stats;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/VivaldiView.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/VivaldiView.java
index 36644bc..e7289c5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/VivaldiView.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/stats/VivaldiView.java
@@ -2,11 +2,12 @@
  * Created on 22 juin 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.stats;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/CoreTableColumnSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/CoreTableColumnSWT.java
index 3ab440f..b0228c9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/CoreTableColumnSWT.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/CoreTableColumnSWT.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableCellSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableCellSWT.java
index 03b6740..79d7fec 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableCellSWT.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableCellSWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,24 +13,15 @@
  * 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 org.gudy.azureus2.ui.swt.views.table;
 
 import org.eclipse.swt.graphics.*;
 
-import org.gudy.azureus2.ui.swt.components.BufferedTableItem;
-
 /**
  * SWT specific functions for Table Cells
  * 
- * SWT cells are split into two logical sections: a BufferedTableItem that
- * handles the actual drawing, and this class' implementor, which handles
- * listeners, checking to see if things are right, buffering, etc.  
- * 
  * @author TuxPaper
  * @created Jan 22, 2007
  *
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableCellSWTPaintListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableCellSWTPaintListener.java
index 54ebc8f..32685ae 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableCellSWTPaintListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableCellSWTPaintListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 19, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableColumnOrTreeColumn.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableColumnOrTreeColumn.java
deleted file mode 100644
index e740955..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableColumnOrTreeColumn.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * Created on May 3, 2010
- *
- * 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;
-
-import org.eclipse.swt.events.ControlListener;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.*;
-
-/**
- * @author TuxPaper
- * @created May 3, 2010
- *
- */
-public interface TableColumnOrTreeColumn
-{
-
-	public Image getImage();
-
-	public String getText();
-
-	public void addControlListener(ControlListener listener);
-
-	public void addListener(int eventType, Listener listener);
-
-	public void addSelectionListener(SelectionListener listener);
-
-	public void addDisposeListener(DisposeListener listener);
-
-	public boolean getMoveable();
-
-	public TableOrTreeSWT getParent();
-
-	public boolean getResizable();
-
-	public String getToolTipText();
-
-	public int getWidth();
-
-	public void dispose();
-
-	public boolean equals(Object obj);
-
-	public int getAlignment();
-
-	public Object getData();
-
-	public Object getData(String key);
-
-	public Display getDisplay();
-
-	public Listener[] getListeners(int eventType);
-
-	public int getStyle();
-
-	public int hashCode();
-
-	public void pack();
-
-	public void removeControlListener(ControlListener listener);
-
-	public void removeSelectionListener(SelectionListener listener);
-
-	public void setAlignment(int alignment);
-
-	public void setImage(Image image);
-
-	public void setMoveable(boolean moveable);
-
-	public void setResizable(boolean resizable);
-
-	public void setText(String string);
-
-	public void setToolTipText(String string);
-
-	public boolean isDisposed();
-
-	public boolean isListening(int eventType);
-
-	public void setWidth(int width);
-
-	public void notifyListeners(int eventType, Event event);
-
-	public void removeListener(int eventType, Listener listener);
-
-	public void removeDisposeListener(DisposeListener listener);
-
-	public void setData(Object data);
-
-	public void setData(String key, Object value);
-
-	public String toString();
-
-	public Item getColumn();
-
-}
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableItemOrTreeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableItemOrTreeItem.java
deleted file mode 100644
index 1bd7925..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableItemOrTreeItem.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * Created on May 3, 2010
- *
- * 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;
-
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-
-/**
- * @author TuxPaper
- * @created May 3, 2010
- *
- */
-public interface TableItemOrTreeItem
-{
-
-	public void addListener(int eventType, Listener listener);
-
-	public void addDisposeListener(DisposeListener listener);
-
-	public void clear(int index, boolean all);
-
-	public void clearAll(boolean all);
-
-	public void dispose();
-
-	public boolean equals(Object obj);
-
-	public Color getBackground();
-
-	public Color getBackground(int index);
-
-	public Rectangle getBounds();
-
-	public Rectangle getBounds(int index);
-
-	public Object getData();
-
-	public Object getData(String key);
-
-	public Display getDisplay();
-
-	public boolean getChecked();
-
-	public Listener[] getListeners(int eventType);
-
-	public boolean getExpanded();
-
-	public int getStyle();
-
-	public Font getFont();
-
-	public Font getFont(int index);
-
-	public Color getForeground();
-
-	public Color getForeground(int index);
-
-	public boolean getGrayed();
-
-	public void notifyListeners(int eventType, Event event);
-
-	public TableItemOrTreeItem getItem(int index);
-
-	public int getItemCount();
-
-	public TableItemOrTreeItem[] getItems();
-
-	public Image getImage();
-
-	public Image getImage(int index);
-
-	public Rectangle getImageBounds(int index);
-
-	public void removeListener(int eventType, Listener listener);
-
-	public TableOrTreeSWT getParent();
-
-	public TableItemOrTreeItem getParentItem();
-
-	public String getText();
-
-	public String getText(int index);
-
-	public void removeDisposeListener(DisposeListener listener);
-
-	public Rectangle getTextBounds(int index);
-
-	public int hashCode();
-
-	public boolean isDisposed();
-
-	public boolean isListening(int eventType);
-
-	public int indexOf(TableItemOrTreeItem item);
-
-	public void removeAll();
-
-	public void setBackground(Color color);
-
-	public void setBackground(int index, Color color);
-
-	public void setData(Object data);
-
-	public void setData(String key, Object value);
-
-	public void setChecked(boolean checked);
-
-	public void setExpanded(boolean expanded);
-
-	public void setFont(Font font);
-
-	public String toString();
-
-	public void setFont(int index, Font font);
-
-	public void setForeground(Color color);
-
-	public void setForeground(int index, Color color);
-
-	public void setGrayed(boolean grayed);
-
-	public void setImage(Image[] images);
-
-	public void setImage(int index, Image image);
-
-	public void setImage(Image image);
-
-	public void setItemCount(int count);
-
-	public void setText(String[] strings);
-
-	public void setText(int index, String string);
-
-	public void setText(String string);
-
-	///////////////
-	
-	public Item getItem();
-}
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableOrTreeSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableOrTreeSWT.java
deleted file mode 100644
index f452e89..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableOrTreeSWT.java
+++ /dev/null
@@ -1,394 +0,0 @@
-/**
- * Created on May 3, 2010
- *
- * 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;
-
-import org.eclipse.swt.accessibility.Accessible;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-
-/**
- * Provides caller with access to a tree or table without needing to know
- * which it's operating on
- * 
- * @author TuxPaper
- * @created May 3, 2010
- */
-public interface TableOrTreeSWT
-{
-
-	public Rectangle computeTrim(int x, int y, int width, int height);
-
-	public void addControlListener(ControlListener listener);
-
-	public void changed(Control[] changed);
-
-	public void addDragDetectListener(DragDetectListener listener);
-
-	public Rectangle getClientArea();
-
-	public void addListener(int eventType, Listener listener);
-
-	public void addFocusListener(FocusListener listener);
-
-	public ScrollBar getHorizontalBar();
-
-	public void addDisposeListener(DisposeListener listener);
-
-	public ScrollBar getVerticalBar();
-
-	public void addHelpListener(HelpListener listener);
-
-	public void addKeyListener(KeyListener listener);
-
-	public void addMenuDetectListener(MenuDetectListener listener);
-
-	public void addMouseListener(MouseListener listener);
-
-	public void addSelectionListener(SelectionListener listener);
-
-	public void addMouseTrackListener(MouseTrackListener listener);
-
-	public void addMouseMoveListener(MouseMoveListener listener);
-
-	public void addMouseWheelListener(MouseWheelListener listener);
-
-	public int getBackgroundMode();
-
-	public void addPaintListener(PaintListener listener);
-
-	public Control[] getChildren();
-
-	public void addTraverseListener(TraverseListener listener);
-
-	public void dispose();
-
-	public Layout getLayout();
-
-	public Control[] getTabList();
-
-	public boolean getLayoutDeferred();
-
-	public Point computeSize(int wHint, int hHint);
-
-	public boolean isLayoutDeferred();
-
-	public Object getData();
-
-	public void layout();
-
-	public Object getData(String key);
-
-	public void layout(boolean changed);
-
-	public Display getDisplay();
-
-	public Listener[] getListeners(int eventType);
-
-	public void layout(boolean changed, boolean all);
-
-	public int getStyle();
-
-	public boolean dragDetect(Event event);
-
-	public boolean isListening(int eventType);
-
-	public boolean dragDetect(MouseEvent event);
-
-	public void notifyListeners(int eventType, Event event);
-
-	public void removeListener(int eventType, Listener listener);
-
-	public void removeDisposeListener(DisposeListener listener);
-
-	public void setBackgroundMode(int mode);
-
-	public boolean setFocus();
-
-	public void setLayout(Layout layout);
-
-	public int getBorderWidth();
-
-	public void setLayoutDeferred(boolean defer);
-
-	public Rectangle getBounds();
-
-	public void setTabList(Control[] tabList);
-
-	public void setData(Object data);
-
-	public Cursor getCursor();
-
-	public void setData(String key, Object value);
-
-	public boolean getDragDetect();
-
-	public boolean getEnabled();
-
-	public Font getFont();
-
-	public Color getForeground();
-
-	public Object getLayoutData();
-
-	public Point getLocation();
-
-	public Menu getMenu();
-
-	public Monitor getMonitor();
-
-	public Composite getParent();
-
-	public Region getRegion();
-
-	public Shell getShell();
-
-	public Point getSize();
-
-	public String getToolTipText();
-
-	public boolean getVisible();
-
-	public String toString();
-
-	public boolean isEnabled();
-
-	public boolean isFocusControl();
-
-	public boolean isReparentable();
-
-	public boolean isVisible();
-
-	public void moveAbove(Control control);
-
-	public void moveBelow(Control control);
-
-	public void pack();
-
-	public void pack(boolean changed);
-
-	public void clear(int index, boolean all);
-
-	public boolean print(GC gc);
-
-	public void clearAll(boolean all);
-
-	public Point computeSize(int wHint, int hHint, boolean changed);
-
-	public void redraw();
-
-	public void redraw(int x, int y, int width, int height, boolean all);
-
-	public void removeControlListener(ControlListener listener);
-
-	public void removeDragDetectListener(DragDetectListener listener);
-
-	public void removeFocusListener(FocusListener listener);
-
-	public void removeHelpListener(HelpListener listener);
-
-	public void removeKeyListener(KeyListener listener);
-
-	public void removeMenuDetectListener(MenuDetectListener listener);
-
-	public void removeMouseTrackListener(MouseTrackListener listener);
-
-	public void removeMouseListener(MouseListener listener);
-
-	public void removeMouseMoveListener(MouseMoveListener listener);
-
-	public void removeMouseWheelListener(MouseWheelListener listener);
-
-	public void removePaintListener(PaintListener listener);
-
-	public void removeTraverseListener(TraverseListener listener);
-
-	public void deselect(TableItemOrTreeItem item);
-
-	public void setBackground(Color color);
-
-	public void deselectAll();
-
-	public boolean equals(Object obj);
-
-	public boolean forceFocus();
-
-	public Accessible getAccessible();
-
-	public Color getBackground();
-
-	public Image getBackgroundImage();
-
-	public void setBackgroundImage(Image image);
-
-	public void setBounds(int x, int y, int width, int height);
-
-	public void setBounds(Rectangle rect);
-
-	public void setCapture(boolean capture);
-
-	public void setCursor(Cursor cursor);
-
-	public void setDragDetect(boolean dragDetect);
-
-	public void setEnabled(boolean enabled);
-
-	public void setForeground(Color color);
-
-	public void setLayoutData(Object layoutData);
-
-	public void setLocation(int x, int y);
-
-	public void setLocation(Point location);
-
-	public void setMenu(Menu menu);
-
-	public int getGridLineWidth();
-
-	public int getHeaderHeight();
-
-	public boolean getHeaderVisible();
-
-	public void setRegion(Region region);
-
-	public void setSize(int width, int height);
-
-	public TableColumnOrTreeColumn getColumn(int index);
-
-	public void setSize(Point size);
-
-	public int getColumnCount();
-
-	public void setToolTipText(String string);
-
-	public int[] getColumnOrder();
-
-	public void setVisible(boolean visible);
-
-	public TableColumnOrTreeColumn[] getColumns();
-
-	public TableItemOrTreeItem getItem(int index);
-
-	public Point toControl(int x, int y);
-
-	public Point toControl(Point point);
-
-	public TableItemOrTreeItem getItem(Point point);
-
-	public Point toDisplay(int x, int y);
-
-	public Point toDisplay(Point point);
-
-	public int getItemCount();
-
-	public int getItemHeight();
-
-	public TableItemOrTreeItem[] getItems();
-
-	public boolean getLinesVisible();
-
-	public TableItemOrTreeItem getParentItem();
-
-	public TableItemOrTreeItem[] getSelection();
-
-	public int getSelectionCount();
-
-	public TableColumnOrTreeColumn getSortColumn();
-
-	public int getSortDirection();
-
-	public TableItemOrTreeItem getTopItem();
-
-	public int hashCode();
-
-	public boolean isDisposed();
-
-	public void update();
-
-	public int indexOf(TableColumnOrTreeColumn column);
-
-	public int indexOf(TableItemOrTreeItem item);
-
-	public boolean setParent(Composite parent);
-
-	public void removeAll();
-
-	public void removeSelectionListener(SelectionListener listener);
-
-	public void removeTreeListener(TreeListener listener);
-
-	public void setInsertMark(TableItemOrTreeItem item, boolean before);
-
-	public void setItemCount(int count);
-
-	public void setLinesVisible(boolean show);
-
-	public void select(TableItemOrTreeItem item);
-
-	public void selectAll();
-
-	public void setColumnOrder(int[] order);
-
-	public void setFont(Font font);
-
-	public void setHeaderVisible(boolean show);
-
-	public void setRedraw(boolean redraw);
-
-	public void setSelection(TableItemOrTreeItem item);
-
-	public void setSelection(TableItemOrTreeItem[] items);
-
-	public void setSortColumn(TableColumnOrTreeColumn column);
-
-	public void setSortDirection(int direction);
-
-	public void setTopItem(TableItemOrTreeItem item);
-
-	public void showColumn(TableColumnOrTreeColumn column);
-
-	public void showItem(TableItemOrTreeItem item);
-
-	public void showSelection();
-
-	////////////
-	
-	public Composite getComposite();
-
-	public int getTopIndex();
-
-	public int getSelectionIndex();
-
-	public int[] getSelectionIndices();
-
-	public void setSelection(int[] newSelectedRowIndices);
-
-	public void select(int[] newSelectedRowIndices);
-
-	public boolean isSelected(TableItemOrTreeItem item);
-
-	boolean equalsTableOrTree(TableOrTreeSWT tt);
-	
-	public TableItemOrTreeItem createNewItem(int style);
-
-	public TableColumnOrTreeColumn createNewColumn(int style);
-
-	public int indexOf(Widget item);
-}
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableRowSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableRowSWT.java
index e2d1ac2..cbd8bc6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableRowSWT.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableRowSWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.table;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableRowSWTPaintListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableRowSWTPaintListener.java
index 30eb0a0..24acd1f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableRowSWTPaintListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableRowSWTPaintListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on May 6, 2010
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableSelectedRowsListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableSelectedRowsListener.java
index 9e43a2f..8a66686 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableSelectedRowsListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableSelectedRowsListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table;
 
 import org.eclipse.swt.widgets.Event;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewFilterCheck.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewFilterCheck.java
index 71e432e..832924e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewFilterCheck.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewFilterCheck.java
@@ -1,10 +1,12 @@
 /**
  * Created on Oct 4, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWT.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWT.java
index 3195708..1e17ad5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWT.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWT.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.table;
@@ -27,7 +24,11 @@ import org.eclipse.swt.events.KeyListener;
 import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Text;
-import org.gudy.azureus2.plugins.ui.tables.*;
+
+import org.gudy.azureus2.plugins.ui.tables.TableRowMouseEvent;
+import org.gudy.azureus2.plugins.ui.tables.TableRowMouseListener;
+import org.gudy.azureus2.plugins.ui.tables.TableRowRefreshListener;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
 import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWT_TabsCommon;
 
 import com.aelitis.azureus.ui.common.table.*;
@@ -64,6 +65,8 @@ public interface TableViewSWT<DATASOURCETYPE>
 
 	void initialize(Composite composite);
 
+	void initialize(UISWTView parent, Composite composite);
+
 	/**
 	 * @param image
 	 * @return
@@ -131,6 +134,8 @@ public interface TableViewSWT<DATASOURCETYPE>
 	 */
 	void enableFilterCheck(Text txtFilter, com.aelitis.azureus.ui.common.table.TableViewFilterCheck<DATASOURCETYPE> filterCheck);
 
+	Text getFilterControl();
+	
 	/**
 	 * @since 4.7.0.1
 	 */
@@ -184,8 +189,6 @@ public interface TableViewSWT<DATASOURCETYPE>
 	 */
 	void addRowMouseListener(TableRowMouseListener listener);
 
-	TableOrTreeSWT getTableOrTreeSWT();
-
 	/**
 	 * @since 4.5.0.5
 	 */
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTFilter.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTFilter.java
index 739edf1..6175e12 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTFilter.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTFilter.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table;
 
 import org.eclipse.swt.events.ModifyListener;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTMenuFillListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTMenuFillListener.java
index 803cf5c..9e21a13 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTMenuFillListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTMenuFillListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.table;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTPanelCreator.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTPanelCreator.java
index 13d1561..4969877 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTPanelCreator.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/TableViewSWTPanelCreator.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table;
 
 import org.eclipse.swt.widgets.Composite;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/FakeTableCell.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/FakeTableCell.java
index ffbf57f..cdc78b9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/FakeTableCell.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/FakeTableCell.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.table.impl;
@@ -40,7 +37,6 @@ import org.gudy.azureus2.core3.peer.PEPiece;
 import org.gudy.azureus2.core3.tracker.host.TRHostTorrent;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.components.BufferedTableItem;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
@@ -688,6 +684,10 @@ public class FakeTableCell
 				public void removeMouseListener(TableRowMouseListener listener) {
 				}
 
+				public int getIndex() {
+					return 1;
+				}
+				
 				public boolean isValid() {
 					return FakeTableCell.this.isValid();
 				}
@@ -1433,12 +1433,6 @@ public class FakeTableCell
 				cellArea.x, cellArea.y, cellArea.width, cellArea.height);
 	}
 
-	// @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getBufferedTableItem()
-	public BufferedTableItem getBufferedTableItem() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
 	// @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getForegroundSWT()
 	public Color getForegroundSWT() {
 		return composite.getForeground();
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableCellImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableCellImpl.java
deleted file mode 100644
index 1589ed8..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableCellImpl.java
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * File    : TableCellImpl.java
- * Created : 24 nov. 2003
- * By      : Olivier
- * Originally PluginItem.java, and changed to be more generic.
- *
- * 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.table.impl;
-
-import java.util.Comparator;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.Item;
-
-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.AERunnable;
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.ui.Graphic;
-import org.gudy.azureus2.plugins.ui.tables.TableColumn;
-import org.gudy.azureus2.plugins.ui.tables.TableRow;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.components.*;
-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.utils.TableColumnSWTUtils;
-
-import com.aelitis.azureus.ui.common.table.TableColumnCore;
-import com.aelitis.azureus.ui.common.table.TableRowCore;
-
-
-/** TableCellImpl represents one cell in the table.  
- * Table access is provided by BufferedTableItem.  
- * TableCellImpl is stored in and accessed by TableRowCore.
- * Drawing control gets passed to listeners.
- *
- * For plugins, this object is the implementation to TableCell.
- *
- * This object is needed to split core code from plugin code.
- */
-public class TableCellImpl 
-	extends TableCellSWTBase
-{
-	private static final LogIDs LOGID = LogIDs.GUI;
-	
-	private static final boolean canUseQuickDraw = Constants.isWindows;
-	
-	
-  private BufferedTableItem bufferedTableItem;
-	
-  // Getting the cell's bounds can be slow.  QUICK_WIDTH uses TableColumn's width
-	private static final boolean QUICK_WIDTH = true;
-
-  public TableCellImpl(TableRowCore _tableRow, TableColumnCore _tableColumn,
-      int position, BufferedTableItem item) {
-  	super(_tableRow, _tableColumn);
-
-  	if (item != null) {
-    	bufferedTableItem = item;
-    } else {
-    	createBufferedTableItem(position);
-    }
-
-    //bDebug = (position == 1) && tableColumn.getTableID().equalsIgnoreCase("Peers");
-    constructionCompleter();
-  }
-
-  protected void
-  constructionCompleter()
-  {
-	  constructionComplete();
-	  
-      tableColumn.invokeCellAddedListeners(TableCellImpl.this);
-  }
-  
-  /**
-   * Initialize
-   *  
-   * @param _tableRow
-   * @param _tableColumn
-   * @param position
-   */
-  public TableCellImpl(TableRowSWT _tableRow, TableColumnCore _tableColumn,
-                       int position) {
-  	this(_tableRow, _tableColumn, position, null);
-  }
-  
-  private void createBufferedTableItem(int position) {
-    BufferedTableRow bufRow = (BufferedTableRow)tableRow;
-    if (tableColumn.getType() == TableColumnCore.TYPE_GRAPHIC) {
-      bufferedTableItem = new BufferedGraphicTableItem1(bufRow, position) {
-        public void refresh() {
-          TableCellImpl.this.refresh();
-        }
-        public void invalidate() {
-        	clearFlag(FLAG_VALID);
-        	this.redraw();
-        	// or this redraw? TableCellImpl.this.redraw();
-        }
-        protected void quickRedrawCell(TableOrTreeSWT table, Rectangle dirty, Rectangle cellBounds) {
-        	TableItemOrTreeItem item = row.getItem();
-					boolean ourQuickRedraw = canUseQuickDraw && tableRow != null
-							&& !tableRow.isMouseOver() && !tableRow.isSelected();
-					if (ourQuickRedraw) {
-      			TableCellImpl.this.quickRedrawCell2(table, item, dirty, cellBounds);
-      		} else {
-      			super.quickRedrawCell(table, dirty, cellBounds);
-      		}
-        }
-      };
-    	setOrientationViaColumn();
-    } else {
-			bufferedTableItem = new BufferedTableItemImpl(bufRow, position) {
-				public void refresh() {
-					TableCellImpl.this.refresh();
-				}
-
-				public void invalidate() {
-					clearFlag(FLAG_VALID);
-				}
-
-				protected void quickRedrawCell(TableOrTreeSWT table, Rectangle dirty,
-						Rectangle cellBounds) {
-					TableItemOrTreeItem item = row.getItem();
-					boolean ourQuickRedraw = canUseQuickDraw && tableRow != null
-							&& !tableRow.isMouseOver() && !tableRow.isSelected();
-					if (ourQuickRedraw) {
-						TableCellImpl.this.quickRedrawCell2(table, item, dirty, cellBounds);
-					} else {
-						super.quickRedrawCell(table, dirty, cellBounds);
-					}
-				}
-			};
-    }
-  }
-
-	protected void quickRedrawCell2(TableOrTreeSWT table,
-			TableItemOrTreeItem tableItemOrTreeItem, Rectangle dirty,
-			Rectangle cellBounds) {
-		if (bufferedTableItem.isInPaintItem()) {
-			return;
-		}
-		Rectangle bounds = new Rectangle(0, 0, cellBounds.width, cellBounds.height);
-		Point pt = new Point(cellBounds.x, cellBounds.y);
-		Image img = new Image(table.getDisplay(), bounds);
-
-		int colPos = bufferedTableItem.getPosition();
-
-		Item item = tableItemOrTreeItem.getItem();
-		table.setData("inPaintInfo", new InPaintInfo(item, colPos, bounds));
-		table.setData("fullPaint", Boolean.TRUE);
-
-		GC gc = new GC(img);
-		try {
-			TableViewSWTImpl<?> tv = (TableViewSWTImpl<?>) tableRow.getView();
-			TableViewSWT_EraseItem.eraseItem(null, gc, tableItemOrTreeItem, colPos,
-					false, bounds, tv, true);
-			//gc.setBackground(ColorCache.getRandomColor());
-			//gc.fillRectangle(bounds);
-
-			Color fg = getForegroundSWT();
-			if (fg != null) {
-				gc.setForeground(fg);
-			}
-			gc.setBackground(getBackgroundSWT());
-
-			TableViewSWT_PaintItem.paintItem(gc, (TableRowSWT) tableRow, colPos,
-					tableRow.getIndex(), bounds, tv, true);
-		} finally {
-			gc.dispose();
-		}
-
-		gc = new GC(table.getComposite());
-		try {
-			//System.out.println("draw " + bounds);
-			gc.drawImage(img, pt.x, pt.y);
-		} finally {
-			img.dispose();
-			gc.dispose();
-		}
-
-		table.setData("inPaintInfo", null);
-		table.setData("fullPaint", Boolean.FALSE);
-	}
-
-	protected void quickRedrawCell(TableOrTreeSWT table,
-			TableItemOrTreeItem tableItemOrTreeItem, Rectangle dirty,
-			Rectangle cellBounds) {
-		if (bufferedTableItem.isInPaintItem()) {
-			return;
-		}
-		
-		int colPos = bufferedTableItem.getPosition();
-
-		Item item = tableItemOrTreeItem.getItem();
-		table.setData("inPaintInfo", new InPaintInfo(item, colPos, cellBounds));
-		table.setData("fullPaint", Boolean.TRUE);
-
-		GC gc = new GC(table.getComposite());
-		try {
-			TableViewSWTImpl<?> tv = (TableViewSWTImpl<?>) tableRow.getView();
-			TableViewSWT_EraseItem.eraseItem(null, gc, tableItemOrTreeItem,
-					bufferedTableItem.getPosition(), true, cellBounds, tv, true);
-
-			Color fg = getForegroundSWT();
-			if (fg != null) {
-				gc.setForeground(fg);
-			}
-			gc.setBackground(getBackgroundSWT());
-			
-			TableViewSWT_PaintItem.paintItem(gc, (TableRowSWT) tableRow,
-					bufferedTableItem.getPosition(), tableRow.getIndex(), cellBounds, tv, true);
-		} finally {
-			gc.dispose();
-		}
-
-		table.setData("inPaintInfo", null);
-		table.setData("fullPaint", Boolean.FALSE);
-	}
-
-	protected void pluginError(Throwable e) {
-    String sTitleLanguageKey = (tableColumn==null?"?":tableColumn.getTitleLanguageKey());
-
-    String sPosition = (bufferedTableItem == null) 
-      ? "null" 
-      : "" + bufferedTableItem.getPosition() + 
-        " (" + MessageText.getString(sTitleLanguageKey) + ")";
-    Logger.log(new LogEvent(LOGID, "Table Cell Plugin for Column #" + sPosition
-				+ " generated an exception ", e));
-  }
-
-	protected void pluginError(String s) {
-    String sTitleLanguageKey = (tableColumn==null?"?":tableColumn.getTitleLanguageKey());
-
-		String sPosition = "r"
-				+ tableRow.getIndex()
-				+ (bufferedTableItem == null ? "null" : "c"
-						+ bufferedTableItem.getPosition() + " ("
-						+ MessageText.getString(sTitleLanguageKey) + ")");
-		Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR,
-				"Table Cell Plugin for Column #" + sPosition + ":" + s + "\n  "
-						+ Debug.getStackTrace(true, true)));
-  }
-  
-  /* Public API */
-  ////////////////
-  
-  public Object getDataSource() {
-		// if we've been disposed then row/col are null
-	  
-	TableRowCore	row = tableRow;
-	TableColumnCore	col	= tableColumn;
-	
-	if ( row == null || col == null){
-		return( null );
-	}
-	
-    return row.getDataSource(col.getUseCoreDataSource());
-  }
-  
-  public TableColumn getTableColumn() {
-    return tableColumn;
-  }
-
-  public TableRow getTableRow() {
-    return tableRow;
-  }
-
-  public String getTableID() {
-    return tableRow.getTableID();
-  }
-  
-  public Color getForegroundSWT() {
-		if (isDisposed()) {
-			return null;
-		}
-
-    return bufferedTableItem.getForeground();
-  }
-  
-  public Color getBackgroundSWT() {
-		if (isDisposed()) {
-			return null;
-		}
-
-		return bufferedTableItem.getBackground();
-	}
-
-  
-  public boolean setForeground(Color color) {
-		if (isDisposed()) {
-			return false;
-		}
-
-  	// Don't need to set when not visible
-  	if (isInvisibleAndCanRefresh())
-  		return false;
-
-    boolean set = bufferedTableItem.setForeground(color);
-    if (set) {
-    	setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH);
-    }
-    return set;
-  }
-
-  @Override
-  public boolean uiSetText(String text) {
-  	return bufferedTableItem.setText(text);
-  }
-  
-  @Override
-  public boolean setGraphic(Graphic img) {
-  	boolean changed = super.setGraphic(img);
-  	if (changed && img != null) {
-    	Image imgSWT = ((UISWTGraphic)img).getImage();
-    	((BufferedGraphicTableItem)bufferedTableItem).setGraphic(imgSWT);
-  	}
-  	return changed;
-  }
-
-  public String getText() {
-  	if (hasFlag(FLAG_SORTVALUEISTEXT) && sortValue instanceof String)
-  		return (String)sortValue;
-  	if (bufferedTableItem == null) {
-  		return null;
-  	}
-    return bufferedTableItem.getText();
-  }
-
-  public boolean isShown() {
-  	if (bufferedTableItem == null || tableRow == null ) {
-  		return false;
-  	}
-
-    return bufferedTableItem.isShown()
-				&& tableRow.getView().isColumnVisible(tableColumn);
-  }
-  
-  public Comparable<?> getSortValue() {
-  	Comparable<?> v = super.getSortValue();
-  	if (v == null) {
-      if (bufferedTableItem != null)
-        return bufferedTableItem.getText();
-      return "";
-  	}
-    return v;
-  }
-  
-	// @see org.gudy.azureus2.plugins.ui.tables.TableCell#getMaxLines()
-	public int getMaxLines() {
-		if (bufferedTableItem == null) {
-			// use 1 in case some plugin borks on div by zero
-			return 1;
-		}
-		return bufferedTableItem.getMaxLines();
-	}
-  
-  /* Start TYPE_GRAPHIC Functions */
-
-	public Point getSize() {
-    if (!(bufferedTableItem instanceof BufferedGraphicTableItem))
-      return null;
-    return ((BufferedGraphicTableItem)bufferedTableItem).getSize();
-  }
-
-	public int getWidthRaw() {
-		return tableColumn.getWidth() - 2;
-	}
-	
-  public int getWidth() {
-  	if (isDisposed()) {
-  		return -1;
-  	}
-  	if (QUICK_WIDTH) {
-  		return tableColumn.getWidth() - 2 - (getMarginWidth() * 2);
-  	} else {
-    	Point pt = null;
-    	
-      if (bufferedTableItem instanceof BufferedGraphicTableItem) {
-      	pt = ((BufferedGraphicTableItem)bufferedTableItem).getSize();
-      } else {
-      	Rectangle bounds = bufferedTableItem.getBounds();
-      	if (bounds != null) {
-      		pt = new Point(bounds.width, bounds.height);
-      	}
-      }
-      if (pt == null)
-        return -1;
-      return pt.x;
-  	}
-  }
-
-  public int getHeight() {
-  	return bufferedTableItem.getHeight();
-  }
-
-  /* (non-Javadoc)
-   * @see org.gudy.azureus2.plugins.ui.tables.TableCell#setFillCell(boolean)
-   */
-  public void setFillCell(boolean bFillCell) {
-  	super.setFillCell(bFillCell);
-		if (isDisposed()) {
-			return;
-		}
-
-    if (!(bufferedTableItem instanceof BufferedGraphicTableItem))
-      return;
-    
-    if (bFillCell)
-    	((BufferedGraphicTableItem)bufferedTableItem).setOrientation(SWT.FILL);
-    else
-    	setOrientationViaColumn();
-    setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH);
-  }
-
-	public void setMarginHeight(int height) {
-		if (isDisposed()) {
-			return;
-		}
-
-    if (!(bufferedTableItem instanceof BufferedGraphicTableItem))
-      return;
-    ((BufferedGraphicTableItem)bufferedTableItem).setMargin(-1, height);
-    setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH);
-  }
-
-  public void setMarginWidth(int width) {
-		if (isDisposed()) {
-			return;
-		}
-
-    if (!(bufferedTableItem instanceof BufferedGraphicTableItem))
-      return;
-    ((BufferedGraphicTableItem)bufferedTableItem).setMargin(width, -1);
-    setFlag(FLAG_VISUALLY_CHANGED_SINCE_REFRESH);
-  }
-
-	public int getMarginHeight() {
-    if (!(bufferedTableItem instanceof BufferedGraphicTableItem))
-      return 0;
-    return ((BufferedGraphicTableItem)bufferedTableItem).getMarginHeight();
-  }
-
-  public int getMarginWidth() {
-    if (!(bufferedTableItem instanceof BufferedGraphicTableItem))
-      return 0;
-    return ((BufferedGraphicTableItem)bufferedTableItem).getMarginWidth();
-  }
-
-  /* End TYPE_GRAPHIC Functions */
-
-
-	/* Start of Core-Only function */
-  //////////////////////////////////
-	
-	public void redraw() {
-		if (!tableRow.isVisible()) {
-			return;
-		}
-		if (bufferedTableItem != null) {
-			bufferedTableItem.redraw();
-		}
-	}
-	
-  public void invalidate(final boolean bMustRefresh) {
-  	super.invalidate(bMustRefresh);
-  	if (bMustRefresh) {
-  		if (bufferedTableItem != null) {
-  			bufferedTableItem.invalidate();
-  		}
-  	}
-  }
-  
-
-  public void dispose() {
-  	super.dispose();
-
-    if (bufferedTableItem != null) {
-			//bufferedTableItem.setForeground(null);
-			bufferedTableItem.dispose();
-		}
-    
-    bufferedTableItem = null;
-  }
-  
-  public boolean needsPainting() {
-		if (isDisposed()) {
-			return false;
-		}
-
-  	if (cellSWTPaintListeners != null || tableColumn.hasCellOtherListeners("SWTPaint")) {
-  		return true;
-  	}
-  	if (bufferedTableItem == null) {
-  		return false;
-  	}
-    return bufferedTableItem.needsPainting();
-  }
-  
-  public void locationChanged() {
-  	if (bufferedTableItem != null) {
-  		bufferedTableItem.locationChanged();
-  	}
-  }
-
-	/* (non-Javadoc)
-	 * @see java.lang.Object#toString()
-	 */
-	public String toString() {
-		return "TableCell {"
-				+ (tableColumn == null ? "disposed" : tableColumn.getName())
-				+ ","
-				+ (tableRow == null ? "" : "r" + tableRow.getIndex())
-				+ (bufferedTableItem == null ? "c?" : "c"
-						+ bufferedTableItem.getPosition()) + "," + getText() + ","
-				+ getSortValue() + "}";
-	}
-
-	/* Comparable Implementation */
-  
-  public static final Comparator TEXT_COMPARATOR = new TextComparator();
-  private static class TextComparator implements Comparator {
-		public int compare(Object arg0, Object arg1) {
-			return arg0.toString().compareToIgnoreCase(arg1.toString());
-		}
-  }
-  
-
-	public Rectangle getBounds() {
-		if (isDisposed()) {
-			return new Rectangle(0, 0, 0, 0);
-		}
-		Rectangle bounds = bufferedTableItem.getBounds();
-		if (bounds == null) {
-			return new Rectangle(0, 0, 0, 0);
-		}
-    return bounds;
-	}
-
-	private void setOrientationViaColumn() {
-		if (!(bufferedTableItem instanceof BufferedGraphicTableItem))
-			return;
-		
-		int align = tableColumn.getAlignment();
-		BufferedGraphicTableItem ti = (BufferedGraphicTableItem) bufferedTableItem;
-		ti.setOrientation(TableColumnSWTUtils.convertColumnAlignmentToSWT(align));
-	}
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.plugins.ui.tables.TableCell#getBackgroundGraphic()
-	 */
-	public Graphic getBackgroundGraphic() {
-		if (bufferedTableItem == null) {
-			return null;
-		}
-  	return new UISWTGraphicImpl(bufferedTableItem.getBackgroundImage());
-	}
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableCellSWT#getBackgroundImage()
-	 */
-	public Image getBackgroundImage() {
-		if (bufferedTableItem == null) {
-			return null;
-		}
-  	return bufferedTableItem.getBackgroundImage();
-	}
-	
-	public BufferedTableItem getBufferedTableItem() {
-		return bufferedTableItem;
-	}
-
-	/* (non-Javadoc)
-	 * @see com.aelitis.azureus.ui.common.table.TableCellCore#setCursorID(int)
-	 */
-	public boolean setCursorID(int cursorID) {
-		if (!super.setCursorID(cursorID)) {
-			return false;
-		}
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				if (isMouseOver()) {
-					bufferedTableItem.setCursor(getCursorID());
-				}
-			}
-		});
-		return true;
-	}
-	
-	public boolean isMouseOver() {
-		if (bufferedTableItem == null) {
-			return false;
-		}
-		if (!tableRow.isVisible()) {
-			return false;
-		}
-		return bufferedTableItem.isMouseOver();
-	}
-	
-	public Rectangle getBoundsOnDisplay() {
-		Rectangle bounds = getBounds();
-		Point pt = ((TableViewSWT<?>) tableRow.getView()).getTableOrTreeSWT().toDisplay(bounds.x, bounds.y);
-		bounds.x = pt.x;
-		bounds.y = pt.y;
-		return bounds;
-	}
-	
-	@Override
-	public boolean refresh(boolean bDoGraphics, boolean bRowVisible,
-			boolean bCellVisible) {
-		return super.refresh(bDoGraphics, bRowVisible, bCellVisible);
-	}
-
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableCellSWTBase.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableCellSWTBase.java
index a39e64d..3bc0769 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableCellSWTBase.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableCellSWTBase.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table.impl;
 
 import java.text.Collator;
@@ -522,8 +540,10 @@ public abstract class TableCellSWTBase
 
 	public void invokeVisibilityListeners(int visibility,
 			boolean invokeColumnListeners) {
-		if (invokeColumnListeners && tableColumn != null) {
-			tableColumn.invokeCellVisibilityListeners(this, visibility);
+		TableColumnCore tc = tableColumn;
+		
+		if (invokeColumnListeners && tc != null) {
+			tc.invokeCellVisibilityListeners(this, visibility);
 		}
 
 		if (cellVisibilityListeners == null)
@@ -550,8 +570,10 @@ public abstract class TableCellSWTBase
 		}
 		setFlag(FLAG_DISPOSED);
 
-		if (tableColumn != null) {
-			tableColumn.invokeCellDisposeListeners(this);
+		TableColumnCore tc = tableColumn;
+		
+		if (tc != null) {
+			tc.invokeCellDisposeListeners(this);
 		}
 
 		if (disposeListeners != null) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableColumnDelegate.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableColumnDelegate.java
deleted file mode 100644
index db29858..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableColumnDelegate.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/**
- * Created on May 5, 2010
- *
- * 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.impl;
-
-import org.eclipse.swt.events.ControlListener;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.ui.swt.views.table.TableColumnOrTreeColumn;
-import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;
-
-/**
- * @author TuxPaper
- * @created May 5, 2010
- *
- */
-public class TableColumnDelegate
-	implements TableColumnOrTreeColumn
-{
-	TableColumn column;
-
-	public TableColumnDelegate(TableColumn column) {
-		this.column = column;
-	}
-
-	public TableColumnDelegate(Table table, int style) {
-		column = new TableColumn(table, style);
-	}
-
-	public Image getImage() {
-		return column.getImage();
-	}
-
-	public String getText() {
-		return column.getText();
-	}
-
-	public void addControlListener(ControlListener listener) {
-		column.addControlListener(listener);
-	}
-
-	public void addListener(int eventType, Listener listener) {
-		column.addListener(eventType, listener);
-	}
-
-	public void addSelectionListener(SelectionListener listener) {
-		column.addSelectionListener(listener);
-	}
-
-	public void addDisposeListener(DisposeListener listener) {
-		column.addDisposeListener(listener);
-	}
-
-	public TableOrTreeSWT getParent() {
-		return TableOrTreeUtils.getTableOrTreeSWT(column.getParent());
-	}
-
-	public boolean getMoveable() {
-		return column.getMoveable();
-	}
-
-	public boolean getResizable() {
-		return column.getResizable();
-	}
-
-	public String getToolTipText() {
-		return column.getToolTipText();
-	}
-
-	public int getWidth() {
-		return column.getWidth();
-	}
-
-	public void dispose() {
-		column.dispose();
-	}
-
-	public boolean equals(Object obj) {
-		return column.equals(obj);
-	}
-
-	public int getAlignment() {
-		return column.getAlignment();
-	}
-
-	public Object getData() {
-		return column.getData();
-	}
-
-	public Object getData(String key) {
-		return column.getData(key);
-	}
-
-	public Display getDisplay() {
-		return column.getDisplay();
-	}
-
-	public Listener[] getListeners(int eventType) {
-		return column.getListeners(eventType);
-	}
-
-	public int getStyle() {
-		return column.getStyle();
-	}
-
-	public int hashCode() {
-		return column.hashCode();
-	}
-
-	public void pack() {
-		column.pack();
-	}
-
-	public void removeControlListener(ControlListener listener) {
-		column.removeControlListener(listener);
-	}
-
-	public void removeSelectionListener(SelectionListener listener) {
-		column.removeSelectionListener(listener);
-	}
-
-	public void setAlignment(int alignment) {
-		column.setAlignment(alignment);
-	}
-
-	public void setImage(Image image) {
-		column.setImage(image);
-	}
-
-	public void setMoveable(boolean moveable) {
-		column.setMoveable(moveable);
-	}
-
-	public boolean isDisposed() {
-		return column.isDisposed();
-	}
-
-	public void setResizable(boolean resizable) {
-		column.setResizable(resizable);
-	}
-
-	public boolean isListening(int eventType) {
-		return column.isListening(eventType);
-	}
-
-	public void notifyListeners(int eventType, Event event) {
-		column.notifyListeners(eventType, event);
-	}
-
-	public void setText(String string) {
-		column.setText(string);
-	}
-
-	public void setToolTipText(String string) {
-		column.setToolTipText(string);
-	}
-
-	public void removeListener(int eventType, Listener listener) {
-		column.removeListener(eventType, listener);
-	}
-
-	public void setWidth(int width) {
-		column.setWidth(width);
-	}
-
-	public void removeDisposeListener(DisposeListener listener) {
-		column.removeDisposeListener(listener);
-	}
-
-	public void setData(Object data) {
-		column.setData(data);
-	}
-
-	public void setData(String key, Object value) {
-		column.setData(key, value);
-	}
-
-	public String toString() {
-		return column.toString();
-	}
-
-	/////////
-	
-	public Item getColumn() {
-		return column;
-	}
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableDelegate.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableDelegate.java
deleted file mode 100644
index 2861d24..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableDelegate.java
+++ /dev/null
@@ -1,921 +0,0 @@
-/**
- * Created on May 5, 2010
- *
- * 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.impl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.eclipse.swt.accessibility.Accessible;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.ui.swt.views.table.TableColumnOrTreeColumn;
-import org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem;
-import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;
-
-/**
- * Delegates a SWT {@link Table} into a {@link TableOrTreeSWT} allowing easy
- * switching from Table and Tree.
- * <p>
- * Uses own map for setData and getData for faster lookups and no SWT thread
- * checking
- * 
- * @author TuxPaper
- * @created May 5, 2010
- *
- */
-public class TableDelegate
-	implements TableOrTreeSWT
-{
-	Table table;
-	
-	Map<String, Object> data = new HashMap<String, Object>(5);
-
-	private TableDelegate() {
-	}
-
-	protected TableDelegate(Table table) {
-		this.table = table;
-	}
-
-	protected TableDelegate(Composite parent, int style) {
-		table = new Table(parent, style);
-	}
-
-	public Rectangle computeTrim(int x, int y, int width, int height) {
-		return table.computeTrim(x, y, width, height);
-	}
-
-	public void addControlListener(ControlListener listener) {
-		table.addControlListener(listener);
-	}
-
-	public void changed(Control[] changed) {
-		table.changed(changed);
-	}
-
-	public void addDragDetectListener(DragDetectListener listener) {
-		table.addDragDetectListener(listener);
-	}
-
-	public Rectangle getClientArea() {
-		return table.getClientArea();
-	}
-
-	public void addListener(int eventType, Listener listener) {
-		table.addListener(eventType, listener);
-	}
-
-	public void addFocusListener(FocusListener listener) {
-		table.addFocusListener(listener);
-	}
-
-	public ScrollBar getHorizontalBar() {
-		return table.getHorizontalBar();
-	}
-
-	public void addDisposeListener(DisposeListener listener) {
-		table.addDisposeListener(listener);
-	}
-
-	public ScrollBar getVerticalBar() {
-		return table.getVerticalBar();
-	}
-
-	public void addHelpListener(HelpListener listener) {
-		table.addHelpListener(listener);
-	}
-
-	public void addKeyListener(KeyListener listener) {
-		table.addKeyListener(listener);
-	}
-
-	public void addMenuDetectListener(MenuDetectListener listener) {
-		table.addMenuDetectListener(listener);
-	}
-
-	public void addMouseListener(MouseListener listener) {
-		table.addMouseListener(listener);
-	}
-
-	public void addMouseTrackListener(MouseTrackListener listener) {
-		table.addMouseTrackListener(listener);
-	}
-
-	public void addMouseMoveListener(MouseMoveListener listener) {
-		table.addMouseMoveListener(listener);
-	}
-
-	public void addMouseWheelListener(MouseWheelListener listener) {
-		table.addMouseWheelListener(listener);
-	}
-
-	public int getBackgroundMode() {
-		return table.getBackgroundMode();
-	}
-
-	public void addPaintListener(PaintListener listener) {
-		table.addPaintListener(listener);
-	}
-
-	public void addSelectionListener(SelectionListener listener) {
-		table.addSelectionListener(listener);
-	}
-
-	public Control[] getChildren() {
-		return table.getChildren();
-	}
-
-	public void addTraverseListener(TraverseListener listener) {
-		table.addTraverseListener(listener);
-	}
-
-	public void dispose() {
-		table.dispose();
-	}
-
-	public Layout getLayout() {
-		return table.getLayout();
-	}
-
-	public Control[] getTabList() {
-		return table.getTabList();
-	}
-
-	public boolean getLayoutDeferred() {
-		return table.getLayoutDeferred();
-	}
-
-	public Point computeSize(int wHint, int hHint) {
-		return table.computeSize(wHint, hHint);
-	}
-
-	public boolean isLayoutDeferred() {
-		return table.isLayoutDeferred();
-	}
-
-	public Object getData() {
-		return getData(null);
-	}
-
-	public void layout() {
-		table.layout();
-	}
-
-	public Object getData(String key) {
-		synchronized (data) {
-			return data.get(key);
-		}
-	}
-
-	public void layout(boolean changed) {
-		table.layout(changed);
-	}
-
-	public Display getDisplay() {
-		return table.getDisplay();
-	}
-
-	public Listener[] getListeners(int eventType) {
-		return table.getListeners(eventType);
-	}
-
-	public void layout(boolean changed, boolean all) {
-		table.layout(changed, all);
-	}
-
-	public int getStyle() {
-		return table.getStyle();
-	}
-
-	public boolean dragDetect(Event event) {
-		return table.dragDetect(event);
-	}
-
-	public boolean isDisposed() {
-		return table.isDisposed();
-	}
-
-	public boolean isListening(int eventType) {
-		return table.isListening(eventType);
-	}
-
-	public boolean dragDetect(MouseEvent event) {
-		return table.dragDetect(event);
-	}
-
-	public void notifyListeners(int eventType, Event event) {
-		table.notifyListeners(eventType, event);
-	}
-
-	public void removeListener(int eventType, Listener listener) {
-		table.removeListener(eventType, listener);
-	}
-
-	public void removeDisposeListener(DisposeListener listener) {
-		table.removeDisposeListener(listener);
-	}
-
-	public void setBackgroundMode(int mode) {
-		table.setBackgroundMode(mode);
-	}
-
-	public boolean setFocus() {
-		return table.setFocus();
-	}
-
-	public Image getBackgroundImage() {
-		return table.getBackgroundImage();
-	}
-
-	public void setLayout(Layout layout) {
-		table.setLayout(layout);
-	}
-
-	public int getBorderWidth() {
-		return table.getBorderWidth();
-	}
-
-	public void setLayoutDeferred(boolean defer) {
-		table.setLayoutDeferred(defer);
-	}
-
-	public Rectangle getBounds() {
-		return table.getBounds();
-	}
-
-	public void setTabList(Control[] tabList) {
-		table.setTabList(tabList);
-	}
-
-	public void setData(Object data) {
-		setData(null, data);
-	}
-
-	public Cursor getCursor() {
-		return table.getCursor();
-	}
-
-	public void setData(String key, Object value) {
-		synchronized (data) {
-			data.put(key, value);
-		}
-	}
-
-	public boolean getDragDetect() {
-		return table.getDragDetect();
-	}
-
-	public boolean getEnabled() {
-		return table.getEnabled();
-	}
-
-	public Font getFont() {
-		return table.getFont();
-	}
-
-	public Color getForeground() {
-		return table.getForeground();
-	}
-
-	public Object getLayoutData() {
-		return table.getLayoutData();
-	}
-
-	public Point getLocation() {
-		return table.getLocation();
-	}
-
-	public Menu getMenu() {
-		return table.getMenu();
-	}
-
-	public Monitor getMonitor() {
-		return table.getMonitor();
-	}
-
-	public void clear(int index) {
-		table.clear(index);
-	}
-
-	public Composite getParent() {
-		return table.getParent();
-	}
-
-	public Region getRegion() {
-		return table.getRegion();
-	}
-
-	public void clear(int start, int end) {
-		table.clear(start, end);
-	}
-
-	public Shell getShell() {
-		return table.getShell();
-	}
-
-	public Point getSize() {
-		return table.getSize();
-	}
-
-	public String getToolTipText() {
-		return table.getToolTipText();
-	}
-
-	public boolean getVisible() {
-		return table.getVisible();
-	}
-
-	public String toString() {
-		return table.toString();
-	}
-
-	public void clear(int[] indices) {
-		table.clear(indices);
-	}
-
-	public void clearAll() {
-		table.clearAll();
-	}
-
-	public boolean isEnabled() {
-		return table.isEnabled();
-	}
-
-	public Point computeSize(int wHint, int hHint, boolean changed) {
-		return table.computeSize(wHint, hHint, changed);
-	}
-
-	public boolean isFocusControl() {
-		return table.isFocusControl();
-	}
-
-	public boolean isReparentable() {
-		return table.isReparentable();
-	}
-
-	public boolean isVisible() {
-		return table.isVisible();
-	}
-
-	public void moveAbove(Control control) {
-		table.moveAbove(control);
-	}
-
-	public void moveBelow(Control control) {
-		table.moveBelow(control);
-	}
-
-	public void pack() {
-		table.pack();
-	}
-
-	public void pack(boolean changed) {
-		table.pack(changed);
-	}
-
-	public boolean print(GC gc) {
-		return table.print(gc);
-	}
-
-	public void deselect(int[] indices) {
-		table.deselect(indices);
-	}
-
-	public void deselect(int index) {
-		table.deselect(index);
-	}
-
-	public void redraw() {
-		table.redraw();
-	}
-
-	public void deselect(int start, int end) {
-		table.deselect(start, end);
-	}
-
-	public void redraw(int x, int y, int width, int height, boolean all) {
-		table.redraw(x, y, width, height, all);
-	}
-
-	public void deselectAll() {
-		table.deselectAll();
-	}
-
-	public boolean equals(Object obj) {
-		return table.equals(obj);
-	}
-
-	public boolean forceFocus() {
-		return table.forceFocus();
-	}
-
-	public Accessible getAccessible() {
-		return table.getAccessible();
-	}
-
-	public Color getBackground() {
-		return table.getBackground();
-	}
-
-	public void removeControlListener(ControlListener listener) {
-		table.removeControlListener(listener);
-	}
-
-	public void removeDragDetectListener(DragDetectListener listener) {
-		table.removeDragDetectListener(listener);
-	}
-
-	public void removeFocusListener(FocusListener listener) {
-		table.removeFocusListener(listener);
-	}
-
-	public void removeHelpListener(HelpListener listener) {
-		table.removeHelpListener(listener);
-	}
-
-	public void removeKeyListener(KeyListener listener) {
-		table.removeKeyListener(listener);
-	}
-
-	public void removeMenuDetectListener(MenuDetectListener listener) {
-		table.removeMenuDetectListener(listener);
-	}
-
-	public void removeMouseTrackListener(MouseTrackListener listener) {
-		table.removeMouseTrackListener(listener);
-	}
-
-	public void removeMouseListener(MouseListener listener) {
-		table.removeMouseListener(listener);
-	}
-
-	public void removeMouseMoveListener(MouseMoveListener listener) {
-		table.removeMouseMoveListener(listener);
-	}
-
-	public void removeMouseWheelListener(MouseWheelListener listener) {
-		table.removeMouseWheelListener(listener);
-	}
-
-	public void removePaintListener(PaintListener listener) {
-		table.removePaintListener(listener);
-	}
-
-	public void removeTraverseListener(TraverseListener listener) {
-		table.removeTraverseListener(listener);
-	}
-
-	public TableColumnOrTreeColumn getColumn(int index) {
-		return wrapOrNull(table.getColumn(index));
-	}
-
-	public int getColumnCount() {
-		return table.getColumnCount();
-	}
-
-	public void setBackground(Color color) {
-		table.setBackground(color);
-	}
-
-	public int[] getColumnOrder() {
-		return table.getColumnOrder();
-	}
-
-	public void setBackgroundImage(Image image) {
-		table.setBackgroundImage(image);
-	}
-
-	public TableColumnOrTreeColumn[] getColumns() {
-		return wrapOrNull(table.getColumns());
-	}
-
-	public void setBounds(int x, int y, int width, int height) {
-		table.setBounds(x, y, width, height);
-	}
-
-	public int getGridLineWidth() {
-		return table.getGridLineWidth();
-	}
-
-	public int getHeaderHeight() {
-		return table.getHeaderHeight();
-	}
-
-	public boolean getHeaderVisible() {
-		return table.getHeaderVisible();
-	}
-
-	public TableItemOrTreeItem getItem(int index) {
-		return wrapOrNull(table.getItem(index));
-	}
-
-	public void setBounds(Rectangle rect) {
-		table.setBounds(rect);
-	}
-
-	public TableItemOrTreeItem getItem(Point point) {
-		return wrapOrNull(table.getItem(point));
-	}
-
-	public void setCapture(boolean capture) {
-		table.setCapture(capture);
-	}
-
-	public void setCursor(Cursor cursor) {
-		table.setCursor(cursor);
-	}
-
-	public void setDragDetect(boolean dragDetect) {
-		table.setDragDetect(dragDetect);
-	}
-
-	public void setEnabled(boolean enabled) {
-		table.setEnabled(enabled);
-	}
-
-	public int getItemCount() {
-		return table.getItemCount();
-	}
-
-	public int getItemHeight() {
-		return table.getItemHeight();
-	}
-
-	public TableItemOrTreeItem[] getItems() {
-		return wrapOrNull(table.getItems());
-	}
-
-	public boolean getLinesVisible() {
-		return table.getLinesVisible();
-	}
-
-	public void setForeground(Color color) {
-		table.setForeground(color);
-	}
-
-	public TableItemOrTreeItem[] getSelection() {
-		return wrapOrNull(table.getSelection());
-	}
-
-	public void setLayoutData(Object layoutData) {
-		table.setLayoutData(layoutData);
-	}
-
-	public int getSelectionCount() {
-		return table.getSelectionCount();
-	}
-
-	public void setLocation(int x, int y) {
-		table.setLocation(x, y);
-	}
-
-	public int getSelectionIndex() {
-		return table.getSelectionIndex();
-	}
-
-	public void setLocation(Point location) {
-		table.setLocation(location);
-	}
-
-	public int[] getSelectionIndices() {
-		return table.getSelectionIndices();
-	}
-
-	public void setMenu(Menu menu) {
-		table.setMenu(menu);
-	}
-
-	public TableColumnOrTreeColumn getSortColumn() {
-		return wrapOrNull(table.getSortColumn());
-	}
-
-	public int getSortDirection() {
-		return table.getSortDirection();
-	}
-
-	public int getTopIndex() {
-		int topIndex = table.getTopIndex();
-		if (topIndex == 0 && table.getItemCount() == 0) {
-			return -1;
-		}
-		return topIndex;
-	}
-
-	public int hashCode() {
-		return table.hashCode();
-	}
-
-	public void setRegion(Region region) {
-		table.setRegion(region);
-	}
-
-	public void setSize(int width, int height) {
-		table.setSize(width, height);
-	}
-
-	public void setSize(Point size) {
-		table.setSize(size);
-	}
-
-	public int indexOf(TableColumnOrTreeColumn column) {
-		if (column == null) {
-			return -1;
-		}
-		return table.indexOf((TableColumn) column.getColumn());
-	}
-
-	public void setToolTipText(String string) {
-		table.setToolTipText(string);
-	}
-
-	public int indexOf(TableItemOrTreeItem item) {
-		if (item == null) {
-			return -1;
-		}
-		return table.indexOf((TableItem) item.getItem());
-	}
-
-	public void setVisible(boolean visible) {
-		table.setVisible(visible);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#isSelected(org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem)
-	public boolean isSelected(TableItemOrTreeItem item) {
-		return table.isSelected(indexOf(item));
-	}
-
-	public Point toControl(int x, int y) {
-		return table.toControl(x, y);
-	}
-
-	public Point toControl(Point point) {
-		return table.toControl(point);
-	}
-
-	public Point toDisplay(int x, int y) {
-		return table.toDisplay(x, y);
-	}
-
-	public Point toDisplay(Point point) {
-		return table.toDisplay(point);
-	}
-
-	public void remove(int[] indices) {
-		table.remove(indices);
-	}
-
-	public void remove(int index) {
-		table.remove(index);
-	}
-
-	public void remove(int start, int end) {
-		table.remove(start, end);
-	}
-
-	public void removeAll() {
-		table.removeAll();
-	}
-
-	public void removeSelectionListener(SelectionListener listener) {
-		table.removeSelectionListener(listener);
-	}
-
-	public void select(int[] indices) {
-		table.select(indices);
-	}
-
-	public void select(int index) {
-		table.select(index);
-	}
-
-	public void select(int start, int end) {
-		table.select(start, end);
-	}
-
-	public void selectAll() {
-		table.selectAll();
-	}
-
-	public void update() {
-		table.update();
-	}
-
-	public boolean setParent(Composite parent) {
-		return table.setParent(parent);
-	}
-
-	public void setColumnOrder(int[] order) {
-		table.setColumnOrder(order);
-	}
-
-	public void setFont(Font font) {
-		table.setFont(font);
-	}
-
-	public void setHeaderVisible(boolean show) {
-		table.setHeaderVisible(show);
-	}
-
-	public void setItemCount(int count) {
-		table.setItemCount(count);
-	}
-
-	public void setLinesVisible(boolean show) {
-		table.setLinesVisible(show);
-	}
-
-	public void setRedraw(boolean redraw) {
-		table.setRedraw(redraw);
-	}
-
-	public void setSelection(int[] indices) {
-		table.setSelection(indices);
-	}
-
-	public void setSelection(TableItemOrTreeItem item) {
-		table.setSelection(item == null ? null : (TableItem) item.getItem());
-	}
-
-	public void setSelection(TableItem[] items) {
-		table.setSelection(items);
-	}
-
-	public void setSelection(int index) {
-		table.setSelection(index);
-	}
-
-	public void setSelection(int start, int end) {
-		table.setSelection(start, end);
-	}
-
-	public void setSortColumn(TableColumnOrTreeColumn column) {
-		table.setSortColumn(column == null ? null
-				: (TableColumn) column.getColumn());
-	}
-
-	public void setSortDirection(int direction) {
-		table.setSortDirection(direction);
-	}
-
-	public void setTopIndex(int index) {
-		table.setTopIndex(index);
-	}
-
-	public void showColumn(TableColumnOrTreeColumn column) {
-		table.showColumn(column == null ? null : (TableColumn) column.getColumn());
-	}
-
-	public void showItem(TableItemOrTreeItem item) {
-		table.showItem(item == null ? null : (TableItem) item.getItem());
-	}
-
-	public void showSelection() {
-		table.showSelection();
-	}
-
-	///////
-
-	private TableItemOrTreeItem wrapOrNull(TableItem item) {
-		if (item == null) {
-			return null;
-		}
-		return TableOrTreeUtils.getEventItem(item);
-	}
-
-	private TableItemOrTreeItem[] wrapOrNull(TableItem[] items) {
-		if (items == null) {
-			return null;
-		}
-		TableItemOrTreeItem[] returnItems = new TableItemOrTreeItem[items.length];
-		for (int i = 0; i < returnItems.length; i++) {
-			returnItems[i] = TableOrTreeUtils.getEventItem(items[i]);
-		}
-		return returnItems;
-	}
-
-	private TableColumnOrTreeColumn wrapOrNull(TableColumn item) {
-		if (item == null) {
-			return null;
-		}
-		return new TableColumnDelegate(item);
-	}
-
-	private TableColumnOrTreeColumn[] wrapOrNull(TableColumn[] items) {
-		if (items == null) {
-			return null;
-		}
-		TableColumnOrTreeColumn[] returnItems = new TableColumnOrTreeColumn[items.length];
-		for (int i = 0; i < returnItems.length; i++) {
-			returnItems[i] = new TableColumnDelegate(items[i]);
-		}
-		return returnItems;
-	}
-
-	private TableItem[] toTableItemArray(TableItemOrTreeItem[] items) {
-		if (items == null) {
-			return null;
-		}
-		TableItem[] returnItems = new TableItem[items.length];
-		for (int i = 0; i < returnItems.length; i++) {
-			returnItems[i] = (TableItem) items[i].getItem();
-		}
-		return returnItems;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#clear(int, boolean)
-	public void clear(int index, boolean allChildren) {
-		table.clear(index);
-	}
-
-	public void clearAll(boolean allChildren) {
-		table.clearAll();
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#deselect(org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem)
-	public void deselect(TableItemOrTreeItem item) {
-		table.deselect(table.indexOf((TableItem) item.getItem()));
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#getParentItem()
-	public TableItemOrTreeItem getParentItem() {
-		return null;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#getTopItem()
-	public TableItemOrTreeItem getTopItem() {
-		int i = table.getTopIndex();
-		return i < 0 || (i == 0 && table.getItemCount() == 0) ? null : getItem(i);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#removeTreeListener(org.eclipse.swt.events.TreeListener)
-	public void removeTreeListener(TreeListener listener) {
-		// TODO Auto-generated method stub
-
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#setInsertMark(org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem, boolean)
-	public void setInsertMark(TableItemOrTreeItem item, boolean before) {
-		// TODO Auto-generated method stub
-
-	}
-
-	public void select(TableItemOrTreeItem item) {
-		table.select(table.indexOf((TableItem) item.getItem()));
-	}
-
-	public void setSelection(TableItemOrTreeItem[] items) {
-		int[] indexes = new int[items.length];
-		for (int i = 0; i < indexes.length; i++) {
-			indexes[i] = table.indexOf((TableItem) items[i].getItem());
-		}
-		table.select(indexes);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#setTopItem(org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem)
-	public void setTopItem(TableItemOrTreeItem item) {
-		// TODO Auto-generated method stub
-
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#getComposite()
-	public Composite getComposite() {
-		return table;
-	}
-
-	public boolean equalsTableOrTree(TableOrTreeSWT tt) {
-		return table.equals(tt.getComposite());
-	}
-
-	public TableItemOrTreeItem createNewItem(int style) {
-		return TableOrTreeUtils.createNewItem(this, style);
-	}
-
-	public TableColumnOrTreeColumn createNewColumn(int style) {
-		return new TableColumnDelegate(table, style);
-	}
-
-  public int indexOf(Widget item) {
-  	if (item instanceof TableItem) {
-  		return table.indexOf((TableItem) item);
-  	}
-  	return -1;
-  }
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableItemDelegate.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableItemDelegate.java
deleted file mode 100644
index e5f1e50..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableItemDelegate.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/**
- * Created on May 5, 2010
- *
- * 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.impl;
-
-import java.util.Map;
-
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.util.LightHashMap;
-import org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem;
-import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;
-
-/**
- * @author TuxPaper
- * @created May 5, 2010
- *
- */
-public class TableItemDelegate
-	implements TableItemOrTreeItem
-{
-	TableItem item;
-
-	Map data = new LightHashMap(2);
-
-	protected TableItemDelegate(TableItem item2) {
-		item = item2;
-		if (item == null) {
-			System.out.println("NULL");
-		}
-	}
-
-	protected TableItemDelegate(TableDelegate tableDelegate, int style) {
-		item = new TableItem(tableDelegate.table, style);
-		if (item == null) {
-			System.out.println("NULL");
-		}
-	}
-
-	public void addListener(int eventType, Listener listener) {
-		item.addListener(eventType, listener);
-	}
-
-	public void addDisposeListener(DisposeListener listener) {
-		item.addDisposeListener(listener);
-	}
-
-	public void dispose() {
-		item.dispose();
-	}
-
-	public boolean equals(Object obj) {
-		if (obj instanceof TableItemOrTreeItem) {
-			return item.equals(((TableItemOrTreeItem) obj).getItem());
-		}
-		return item.equals(obj);
-	}
-
-	public Color getBackground() {
-		return item.getBackground();
-	}
-
-	public Color getBackground(int index) {
-		return item.getBackground(index);
-	}
-
-	public Rectangle getBounds() {
-		return item.getBounds();
-	}
-
-	public Rectangle getBounds(int index) {
-		return item.getBounds(index);
-	}
-
-	public boolean getChecked() {
-		return item.getChecked();
-	}
-
-	public Font getFont() {
-		return item.getFont();
-	}
-
-	public Font getFont(int index) {
-		return item.getFont(index);
-	}
-
-	public Color getForeground() {
-		return item.getForeground();
-	}
-
-	public Color getForeground(int index) {
-		return item.getForeground(index);
-	}
-
-	public Object getData() {
-		return getData(null);
-	}
-	
-	public Object getData(String key) {
-		synchronized (data) {
-			return data.get(key);
-		}
-	}
-
-	public boolean getGrayed() {
-		return item.getGrayed();
-	}
-
-	public Image getImage() {
-		return item.getImage();
-	}
-
-	public Image getImage(int index) {
-		return item.getImage(index);
-	}
-
-	public Display getDisplay() {
-		return item.getDisplay();
-	}
-
-	public Rectangle getImageBounds(int index) {
-		return item.getImageBounds(index);
-	}
-
-	public Listener[] getListeners(int eventType) {
-		return item.getListeners(eventType);
-	}
-
-	public int getImageIndent() {
-		return item.getImageIndent();
-	}
-
-	public TableOrTreeSWT getParent() {
-		return TableOrTreeUtils.getTableOrTreeSWT(item.getParent());
-	}
-
-	public int getStyle() {
-		return item.getStyle();
-	}
-
-	public String getText() {
-		return item.getText();
-	}
-
-	public String getText(int index) {
-		return item.getText(index);
-	}
-
-	public Rectangle getTextBounds(int index) {
-		return item.getTextBounds(index);
-	}
-
-	public int hashCode() {
-		return item.hashCode();
-	}
-
-	public boolean isDisposed() {
-		return item.isDisposed();
-	}
-
-	public boolean isListening(int eventType) {
-		return item.isListening(eventType);
-	}
-
-	public void notifyListeners(int eventType, Event event) {
-		item.notifyListeners(eventType, event);
-	}
-
-	public void setBackground(Color color) {
-		item.setBackground(color);
-	}
-
-	public void setBackground(int index, Color color) {
-		item.setBackground(index, color);
-	}
-
-	public void setChecked(boolean checked) {
-		item.setChecked(checked);
-	}
-
-	public void setFont(Font font) {
-		item.setFont(font);
-	}
-
-	public void removeListener(int eventType, Listener listener) {
-		item.removeListener(eventType, listener);
-	}
-
-	public void setFont(int index, Font font) {
-		item.setFont(index, font);
-	}
-
-	public void removeDisposeListener(DisposeListener listener) {
-		item.removeDisposeListener(listener);
-	}
-
-	public void setForeground(Color color) {
-		item.setForeground(color);
-	}
-
-	public void setForeground(int index, Color color) {
-		item.setForeground(index, color);
-	}
-
-	public void setGrayed(boolean grayed) {
-		item.setGrayed(grayed);
-	}
-
-	public void setImage(Image[] images) {
-		item.setImage(images);
-	}
-
-	public void setImage(int index, Image image) {
-		item.setImage(index, image);
-	}
-
-	public void setImage(Image image) {
-		item.setImage(image);
-	}
-
-	public void setImageIndent(int indent) {
-		item.setImageIndent(indent);
-	}
-
-	public void setText(String[] strings) {
-		item.setText(strings);
-	}
-	
-	public void setData(Object data) {
-		setData(null, data);
-	}
-	
-	public void setData(String key, Object value) {
-		synchronized (data) {
-			data.put(key, value);
-		}
-	}
-
-	public void setText(int index, String string) {
-		item.setText(index, string);
-	}
-
-	public void setText(String string) {
-		item.setText(string);
-	}
-
-	public String toString() {
-		return item.toString();
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem#clear(int, boolean)
-	public void clear(int index, boolean all) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem#clearAll(boolean)
-	public void clearAll(boolean all) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem#getExpanded()
-	public boolean getExpanded() {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem#getItem(int)
-	public TableItemOrTreeItem getItem(int index) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	public int getItemCount() {
-		return 0;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem#getItems()
-	public TableItemOrTreeItem[] getItems() {
-		return new TableItemOrTreeItem[0];
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem#getParentItem()
-	public TableItemOrTreeItem getParentItem() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem#indexOf(org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem)
-	public int indexOf(TableItemOrTreeItem item) {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem#removeAll()
-	public void removeAll() {
-		// TODO Auto-generated method stub
-		
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem#setExpanded(boolean)
-	public void setExpanded(boolean expanded) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem#setItemCount(int)
-	public void setItemCount(int count) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	public Item getItem() {
-		return item;
-	}
-	
-	public boolean equals(TableItemOrTreeItem ti) {
-		return item.equals(ti.getItem());
-	}
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableOrTreeUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableOrTreeUtils.java
deleted file mode 100644
index f8560a2..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableOrTreeUtils.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/**
- * Created on May 3, 2010
- *
- * 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.impl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.eclipse.swt.custom.ControlEditor;
-import org.eclipse.swt.custom.TableEditor;
-import org.eclipse.swt.custom.TreeEditor;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.ui.swt.views.table.TableColumnOrTreeColumn;
-import org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem;
-import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;
-
-/**
- * @author TuxPaper
- * @created May 3, 2010
- *
- */
-public class TableOrTreeUtils
-{
-	private static Map<Object, Object> mapDelegates = new HashMap<Object, Object>();
-
-	public static TableItemOrTreeItem getEventItem(Widget item) {
-		synchronized (mapDelegates) {
-			Object object = mapDelegates.get(item);
-			if (object instanceof TableItemOrTreeItem) {
-				return (TableItemOrTreeItem) object;
-			}
-		}
-
-		TableItemOrTreeItem delegate = null;
-		synchronized (mapDelegates) {
-			if (item instanceof TreeItem) {
-				delegate = new TreeItemDelegate((TreeItem) item);
-				mapDelegates.put(item, delegate);
-			} else if (item instanceof TableItem) {
-				delegate = new TableItemDelegate((TableItem) item);
-				mapDelegates.put(item, delegate);
-			}
-		}
-
-		if (delegate != null) {
-			delegate.addDisposeListener(new DisposeListener() {
-				public void widgetDisposed(DisposeEvent e) {
-					synchronized (mapDelegates) {
-						mapDelegates.remove(e.widget);
-					}
-				}
-			});
-		}
-		return delegate;
-	}
-
-	public static TableOrTreeSWT getTableOrTreeSWT(Widget widget) {
-		synchronized (mapDelegates) {
-			Object object = mapDelegates.get(widget);
-			if (object instanceof TableOrTreeSWT) {
-				return (TableOrTreeSWT) object;
-			}
-		}
-
-		TableOrTreeSWT delegate = null;
-		synchronized (mapDelegates) {
-			if (widget instanceof Tree) {
-				delegate = new TreeDelegate((Tree) widget);
-				mapDelegates.put(widget, delegate);
-			} else if (widget instanceof Table) {
-				delegate = new TableDelegate((Table) widget);
-				mapDelegates.put(widget, delegate);
-			}
-		}
-
-		if (delegate != null) {
-			delegate.addDisposeListener(new DisposeListener() {
-				public void widgetDisposed(DisposeEvent e) {
-					synchronized (mapDelegates) {
-						mapDelegates.remove(e.widget);
-					}
-				}
-			});
-		}
-		return delegate;
-	}
-
-	public static TableItemOrTreeItem createNewItem(TableOrTreeSWT parent,
-			int style) {
-		TableItemOrTreeItem delegate = null;
-		synchronized (mapDelegates) {
-			if (parent instanceof TreeDelegate) {
-				delegate = new TreeItemDelegate(parent, style);
-				mapDelegates.put(((TreeItemDelegate) delegate).item, delegate);
-			} else if (parent instanceof TableDelegate) {
-				delegate = new TableItemDelegate((TableDelegate) parent, style);
-				mapDelegates.put(((TableItemDelegate)delegate).item, delegate);
-			}
-		}
-
-		if (delegate != null) {
-			delegate.addDisposeListener(new DisposeListener() {
-				public void widgetDisposed(DisposeEvent e) {
-					synchronized (mapDelegates) {
-						mapDelegates.remove(e.widget);
-					}
-				}
-			});
-		}
-		return delegate;
-	}
-
-	public static TableColumnOrTreeColumn getTableColumnEventItem(Widget item) {
-		if (item instanceof TreeColumn) {
-			return new TreeColumnDelegate((TreeColumn) item);
-		}
-		if (item instanceof TableColumn) {
-			return new TableColumnDelegate((TableColumn) item);
-		}
-		return null;
-	}
-
-	public static TableOrTreeSWT createGrid(Composite parent, int style,
-			boolean tree) {
-		TableOrTreeSWT delegate = null;
-		synchronized (mapDelegates) {
-			if (tree) {
-				try {
-					delegate = new TreeDelegate(parent, style);
-					mapDelegates.put(((TreeDelegate) delegate).getComposite(), delegate);
-				} catch (Exception e) {
-					Debug.out(e);
-				}
-			} else {
-				delegate = new TableDelegate(parent, style);
-				mapDelegates.put(((TableDelegate)delegate).getComposite(), delegate);
-			}
-		}
-
-		if (delegate != null) {
-			delegate.addDisposeListener(new DisposeListener() {
-				public void widgetDisposed(DisposeEvent e) {
-					synchronized (mapDelegates) {
-						mapDelegates.remove(e.widget);
-					}
-				}
-			});
-		}
-		return delegate;
-	}
-
-	public static ControlEditor createTableOrTreeEditor(TableOrTreeSWT tableOrTree) {
-		return (tableOrTree instanceof TreeDelegate) ? new TreeEditor(
-				(Tree) tableOrTree.getComposite()) : new TableEditor(
-				(Table) tableOrTree.getComposite());
-	}
-
-	/**
-	 * @since 4.4.0.5
-	 */
-	public static void setEditorItem(ControlEditor editor, Control input,
-			int column, TableItemOrTreeItem item) {
-		if (item instanceof TreeItemDelegate) {
-			((TreeEditor) editor).setEditor(input, (TreeItem) item.getItem(), column);
-		} else {
-			((TableEditor) editor).setEditor(input, (TableItem) item.getItem(),
-					column);
-		}
-	}
-
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableRowImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableRowImpl.java
deleted file mode 100644
index 86fe223..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableRowImpl.java
+++ /dev/null
@@ -1,908 +0,0 @@
-/*
- * File    : TableRowImpl.java
- * Originally TorrentRow.java, and changed to be more generic by TuxPaper
- *
- * 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.table.impl;
-
-import java.util.*;
-
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.Rectangle;
-
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.ui.tables.*;
-import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.components.BufferedTableRow;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-import org.gudy.azureus2.ui.swt.views.table.*;
-
-import com.aelitis.azureus.ui.common.table.*;
-import com.aelitis.azureus.ui.common.table.impl.TableViewImpl;
-
-/** Represents an entire row in a table.  Stores each cell belonging to the
- * row and handles refreshing them.
- *
- * @see TableCellImpl
- * 
- * @author TuxPaper
- *            2005/Oct/07: Moved TableItem.SetData("TableRow", ..) to 
- *                         BufferedTableRow
- *            2005/Oct/07: Removed all calls to BufferedTableRoe.getItem()
- */
-public class TableRowImpl<COREDATASOURCE>
-	extends BufferedTableRow
-	implements TableRowSWT
-{
-	/** 
-	 * List of cells in this row.  
-	 * They are not stored in display order.
-	 * Not written to after initializer
-	 */
-	private Map<String, TableCellCore> mTableCells;
-
-	private Object coreDataSource;
-
-	private Object pluginDataSource;
-
-	private boolean bDisposed;
-
-	private boolean bSetNotUpToDateLastRefresh = false;
-
-	private TableView<COREDATASOURCE> tableView;
-
-	private static AEMonitor this_mon = new AEMonitor("TableRowImpl");
-
-	private ArrayList<TableRowMouseListener> mouseListeners;
-
-	private boolean wasShown = false;
-
-	private Map<String, Object> dataList;
-
-	private int lastIndex = -1;
-
-	private int fontStyle;
-
-	private int alpha = 255;
-
-	private TableRowCore parentRow;
-
-	private TableRowImpl<Object>[] subRows;
-
-	private AEMonitor mon_SubRows = new AEMonitor("subRows");
-
-	private TableColumnCore[] columnsSorted;
-
-	private boolean bSkipFirstColumn;
-
-	// XXX add rowVisuallyupdated bool like in ListRow
-
-	public TableRowImpl(TableRowCore parentRow, TableView<COREDATASOURCE> tv,
-			TableOrTreeSWT table, TableColumnCore[] columnsSorted, String sTableID,
-			Object dataSource, int index, boolean bSkipFirstColumn) {
-		super(table);
-		this.parentRow = parentRow;
-		this.tableView = tv;
-		coreDataSource = dataSource;
-		bDisposed = false;
-		lastIndex = index;
-
-		mTableCells = new LightHashMap<String, TableCellCore>(columnsSorted.length,
-				1);
-
-		// create all the cells for the column
-		for (int i = 0; i < columnsSorted.length; i++) {
-			if (columnsSorted[i] == null) {
-				continue;
-			}
-
-			if (!columnsSorted[i].handlesDataSourceType(getDataSource(false).getClass())) {
-				mTableCells.put(columnsSorted[i].getName(), null);
-				continue;
-			}
-
-			//System.out.println(dataSource + ": " + tableColumns[i].getName() + ": " + tableColumns[i].getPosition());
-			TableCellImpl cell = new TableCellImpl(TableRowImpl.this,
-					columnsSorted[i], bSkipFirstColumn ? i + 1 : i);
-			mTableCells.put(columnsSorted[i].getName(), cell);
-			//if (i == 10) cell.bDebug = true;
-		}
-	}
-
-	/**
-	 * Default constructor
-	 * 
-	 * @param table
-	 * @param sTableID
-	 * @param columnsSorted
-	 * @param dataSource
-	 * @param bSkipFirstColumn
-	 */
-	public TableRowImpl(TableView<COREDATASOURCE> tv, TableOrTreeSWT table,
-			TableColumnCore[] columnsSorted, Object dataSource,
-			boolean bSkipFirstColumn) {
-		super(table);
-		this.tableView = tv;
-		this.columnsSorted = columnsSorted;
-		coreDataSource = dataSource;
-		this.bSkipFirstColumn = bSkipFirstColumn;
-		bDisposed = false;
-
-		mTableCells = new LightHashMap<String, TableCellCore>(columnsSorted.length,
-				1);
-
-		// create all the cells for the column
-		for (int i = 0; i < columnsSorted.length; i++) {
-			if (columnsSorted[i] == null) {
-				continue;
-			}
-			//System.out.println(dataSource + ": " + tableColumns[i].getName() + ": " + tableColumns[i].getPosition());
-			TableCellImpl cell = new TableCellImpl(TableRowImpl.this,
-					columnsSorted[i], bSkipFirstColumn ? i + 1 : i);
-			mTableCells.put(columnsSorted[i].getName(), cell);
-			//if (i == 10) cell.bDebug = true;
-		}
-	}
-
-	public boolean isValid() {
-		if (bDisposed || mTableCells == null) {
-			return true;
-		}
-
-		boolean valid = true;
-		for (TableCell cell : mTableCells.values()) {
-			if (cell != null && cell.isValid()) {
-				return false;
-			}
-		}
-
-		return valid;
-	}
-
-	/** TableRow Implementation which returns the 
-	 * associated plugin object for the row.  Core Column Object who wish to get 
-	 * core data source must re-class TableRow as TableRowCore and use
-	 * getDataSource(boolean)
-	 *
-	 * @see TableRowCore.getDataSource()
-	 */
-	public Object getDataSource() {
-		return getDataSource(false);
-	}
-
-	public String getTableID() {
-		return tableView.getTableID();
-	}
-
-	public TableCell getTableCell(String field) {
-		if (bDisposed || mTableCells == null) {
-			return null;
-		}
-
-		return mTableCells.get(field);
-	}
-
-	public void addMouseListener(TableRowMouseListener listener) {
-		try {
-			this_mon.enter();
-
-			if (mouseListeners == null) {
-				mouseListeners = new ArrayList<TableRowMouseListener>(1);
-			}
-
-			mouseListeners.add(listener);
-
-		} finally {
-			this_mon.exit();
-		}
-	}
-
-	public void removeMouseListener(TableRowMouseListener listener) {
-		try {
-			this_mon.enter();
-
-			if (mouseListeners == null) {
-				return;
-			}
-
-			mouseListeners.remove(listener);
-
-		} finally {
-			this_mon.exit();
-		}
-	}
-
-	public void invokeMouseListeners(TableRowMouseEvent event) {
-		ArrayList<TableRowMouseListener> listeners = mouseListeners;
-		if (listeners == null) {
-			return;
-		}
-
-		for (int i = 0; i < listeners.size(); i++) {
-			try {
-				TableRowMouseListener l = listeners.get(i);
-
-				l.rowMouseTrigger(event);
-
-			} catch (Throwable e) {
-				Debug.printStackTrace(e);
-			}
-		}
-	}
-
-	/* Start Core-Only functions */
-	///////////////////////////////
-
-	public void delete() {
-		this_mon.enter();
-
-		try {
-			if (bDisposed) {
-				return;
-			}
-
-			if (TableViewImpl.DEBUGADDREMOVE) {
-				System.out.println((table.isDisposed() ? "" : table.getData("Name"))
-						+ " row delete; index=" + getIndex());
-			}
-
-			for (TableCellCore cell : mTableCells.values()) {
-				try {
-					if (cell != null) {
-						cell.dispose();
-					}
-				} catch (Exception e) {
-					Debug.out(e);
-				}
-			}
-
-			//setForeground((Color) null);
-
-			bDisposed = true;
-		} finally {
-			this_mon.exit();
-		}
-	}
-
-	public List<TableCellCore> refresh(boolean bDoGraphics) {
-		if (bDisposed) {
-			return Collections.EMPTY_LIST;
-		}
-
-		boolean bVisible = isVisible();
-
-		return refresh(bDoGraphics, bVisible);
-	}
-
-	public List<TableCellCore> refresh(boolean bDoGraphics, boolean bVisible) {
-		// If this were called from a plugin, we'd have to refresh the sorted column
-		// even if we weren't visible
-		List<TableCellCore> list = Collections.EMPTY_LIST;
-
-		if (bDisposed) {
-			return list;
-		}
-
-		if (!bVisible) {
-			if (!bSetNotUpToDateLastRefresh) {
-				setUpToDate(false);
-				bSetNotUpToDateLastRefresh = true;
-			}
-			return list;
-		}
-
-		bSetNotUpToDateLastRefresh = false;
-
-		//System.out.println(SystemTime.getCurrentTime() + "refresh " + getIndex() + ";vis=" + bVisible);
-
-		((TableViewSWTImpl<COREDATASOURCE>) tableView).invokeRefreshListeners(this);
-
-		for (TableCellCore cell : mTableCells.values()) {
-			if (cell == null || cell.isDisposed()) {
-				continue;
-			}
-			TableColumn column = cell.getTableColumn();
-			//System.out.println(column);
-			if (column != tableView.getSortColumn()
-					&& !tableView.isColumnVisible(column)) {
-				//System.out.println("skip " + column);
-				continue;
-			}
-			boolean changed = cell.refresh(bDoGraphics, bVisible);
-			if (changed) {
-				if (list == Collections.EMPTY_LIST) {
-					list = new ArrayList<TableCellCore>(mTableCells.size());
-				}
-				list.add(cell);
-			}
-
-		}
-
-		//System.out.println();
-		return list;
-	}
-
-	public void locationChanged(int iStartColumn) {
-		if (bDisposed || !isVisible()) {
-			return;
-		}
-
-		for (TableCellCore cell : mTableCells.values()) {
-			if (cell != null && cell.getTableColumn().getPosition() > iStartColumn) {
-				cell.locationChanged();
-			}
-		}
-	}
-
-	public TableCellCore getTableCellCore(String name) {
-		if (bDisposed || mTableCells == null) {
-			return null;
-		}
-
-		return mTableCells.get(name);
-	}
-
-	/**
-	 * @param name
-	 * @return
-	 */
-	public TableCellSWT getTableCellSWT(String name) {
-		if (bDisposed || mTableCells == null) {
-			return null;
-		}
-
-		TableCellCore cell = mTableCells.get(name);
-		if (cell instanceof TableCellSWT) {
-			return (TableCellSWT) cell;
-		}
-		return null;
-	}
-
-	public Object getDataSource(boolean bCoreObject) {
-		if (bDisposed) {
-			return null;
-		}
-
-		if (bCoreObject) {
-			return coreDataSource;
-		}
-
-		if (pluginDataSource != null) {
-			return pluginDataSource;
-		}
-
-		pluginDataSource = PluginCoreUtils.convert(coreDataSource, bCoreObject);
-
-		return pluginDataSource;
-	}
-
-	public boolean isRowDisposed() {
-		return bDisposed;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#getIndex()
-	 */
-	public int getIndex() {
-		if (bDisposed) {
-			return -1;
-		}
-
-		if (lastIndex >= 0) {
-			if (parentRow != null) {
-				return lastIndex;
-			}
-			TableRowCore row = ((TableViewSWTImpl<COREDATASOURCE>) tableView).getRowQuick(lastIndex);
-			if (row == this) {
-				return lastIndex;
-			}
-		}
-
-		// don't set directly to lastIndex, so setTableItem will eventually do
-		// its job
-		return tableView.indexOf(this);
-
-		//return super.getIndex();
-	}
-
-	public int getRealIndex() {
-		return super.getIndex();
-	}
-
-	public boolean setTableItem(int newIndex, boolean isVisible) {
-		if (bDisposed) {
-			System.out.println("XXX setTI: bDisposed from "
-					+ Debug.getCompressedStackTrace());
-			return false;
-		}
-
-		int maxItemShown = tableView.getMaxItemShown();
-		if (newIndex > maxItemShown) {
-				//System.out.println((item == null ? null : "" + table.indexOf(item)) + ":" + newIndex + ":" + isVisible + ":" + tableView.getMaxItemShown());
-				tableView.setMaxItemShown(newIndex);
-			if (!isVisible) {
-				return false;
-			}
-		}
-
-		boolean changedIndex = lastIndex != newIndex || item == null;
-
-		//if (getRealIndex() != newIndex) {
-		//	((TableViewSWTImpl)tableView).debug("sTI " + newIndex + "; via " + Debug.getCompressedStackTrace(4));
-		//}
-		boolean changedSWTRow = !changedIndex ? false : super.setTableItem(newIndex, isVisible);
-		//if (changedSWTRow) {
-		//	System.out.println((item == null ? null : "" + table.indexOf(item)) + ":" + newIndex + ":" + isVisible + ":" + tableView.getMaxItemShown());
-		//}
-		if (changedIndex) {
-			//System.out.println("row " + newIndex + " from " + lastIndex + ";" + tableView.isRowVisible(this) + ";" + changedSWTRow);
-			lastIndex = newIndex;
-		}
-		//boolean rowVisible = tableView.isRowVisible(this);
-		setShown(isVisible, changedSWTRow);
-		if (changedSWTRow && isVisible) {
-			redraw();
-			//invalidate();
-			//refresh(true, true);
-			setUpToDate(false);
-		}
-		return changedSWTRow;
-	}
-
-	public boolean setTableItem(int newIndex) {
-		if (!Utils.isThisThreadSWT()) {
-			return false;
-		}
-		return setTableItem(newIndex, true);
-	}
-
-	private static final boolean DEBUG_SET_FOREGROUND = System.getProperty("debug.setforeground") != null;
-
-	private Object[] subDataSources;
-
-	private static void setForegroundDebug(String method_sig, Color c) {
-		if (DEBUG_SET_FOREGROUND && c != null) {
-			Debug.out("BufferedTableRow " + method_sig + " -> " + c);
-		}
-	}
-
-	private static void setForegroundDebug(String method_sig, int r, int g, int b) {
-		if (DEBUG_SET_FOREGROUND && (!(r == 0 && g == 0 && b == 0))) {
-			Debug.out("BufferedTableRow " + method_sig + " -> " + r + "," + g + ","
-					+ b);
-		}
-	}
-
-	// @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#setForeground(int, int, int)
-	public void setForeground(int r, int g, int b) {
-		setForegroundDebug("setForeground(r, g, b)", r, g, b);
-		// Don't need to set when not visible
-		if (!isVisible()) {
-			return;
-		}
-
-		super.setForeground(r, g, b);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#setForeground(org.eclipse.swt.graphics.Color)
-	public boolean setForeground(final Color c) {
-		setForegroundDebug("setForeground(Color)", c);
-		// Don't need to set when not visible
-		if (!isVisible()) {
-			return true;
-		}
-
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				TableRowImpl.this.setForegroundInSWTThread(c);
-			}
-		});
-		return true;
-	}
-
-	private void setForegroundInSWTThread(Color c) {
-		setForegroundDebug("setForegroundInSWTThread(Color)", c);
-		if (!isVisible()) {
-			return;
-		}
-
-		super.setForeground(c);
-	}
-
-	// @see org.gudy.azureus2.plugins.ui.tables.TableRow#setForeground(int[])
-	public void setForeground(int[] rgb) {
-		if (rgb == null || rgb.length < 3) {
-			setForeground((Color) null);
-			return;
-		}
-		setForeground(rgb[0], rgb[1], rgb[2]);
-	}
-
-	public void setForegroundToErrorColor() {
-		this.setForeground(Colors.colorError);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#invalidate()
-	 */
-	
-	public void invalidate() {
-		invalidate(false);
-	}
-	public void invalidate(boolean mustRefresh) {
-		super.invalidate();
-
-		if (bDisposed) {
-			return;
-		}
-
-		for (TableCellCore cell : mTableCells.values()) {
-			if (cell != null) {
-				cell.invalidate(mustRefresh);
-			}
-		}
-	}
-
-	public void setUpToDate(boolean upToDate) {
-		if (bDisposed) {
-			return;
-		}
-
-		for (TableCellCore cell : mTableCells.values()) {
-			if (cell != null) {
-				cell.setUpToDate(upToDate);
-			}
-		}
-	}
-
-	public void redraw() {
-		redraw(false);
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableRowCore#redraw()
-	public void redraw(boolean doChildren) {
-		// this will call paintItem which may call refresh
-		Rectangle bounds = getBounds();
-		table.redraw(bounds.x, bounds.y, bounds.width, bounds.height, false);
-	}
-
-	public String toString() {
-		String result = "TableRowImpl@" + Integer.toHexString(hashCode()) + "/#"
-				+ lastIndex;
-		return result;
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableRowCore#getView()
-	public TableView<COREDATASOURCE> getView() {
-		return tableView;
-	}
-
-	public boolean isShown() {
-		return wasShown;
-	}
-	
-	/**
-	 * @param b
-	 *
-	 * @since 3.0.4.3
-	 */
-	public boolean setShown(boolean b, boolean force) {
-		if (bDisposed) {
-			return false;
-		}
-
-		if (b == wasShown && !force) {
-			return false;
-		}
-		wasShown = b;
-
-		for (TableCellCore cell : mTableCells.values()) {
-			if (cell != null) {
-				cell.invokeVisibilityListeners(b
-						? TableCellVisibilityListener.VISIBILITY_SHOWN
-						: TableCellVisibilityListener.VISIBILITY_HIDDEN, true);
-			}
-		}
-		return true;
-
-		/* Don't need to refresh; paintItem will trigger a refresh on
-		 * !cell.isUpToDate()
-		 *
-		if (b) {
-			refresh(b, true);
-		}
-		/**/
-	}
-
-	public boolean isMouseOver() {
-		return tableView.getTableRowWithCursor() == this;
-	}
-
-	public void setData(String id, Object data) {
-		synchronized (this) {
-			if (dataList == null) {
-				dataList = new HashMap<String, Object>(1);
-			}
-			if (data == null) {
-				dataList.remove(id);
-			} else {
-				dataList.put(id, data);
-			}
-		}
-	}
-
-	public Object getData(String id) {
-		synchronized (this) {
-			return dataList == null ? null : dataList.get(id);
-		}
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableRowSWT#getBounds()
-	public Rectangle getBounds() {
-		Rectangle bounds = getBounds(1);
-		if (bounds == null) {
-			return new Rectangle(0, 0, 0, 0);
-		}
-		Rectangle tableBounds = table.getClientArea();
-		bounds.x = tableBounds.x;
-		bounds.width = tableBounds.width;
-		return bounds;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableRowSWT#setFontStyle(int)
-	public boolean setFontStyle(int style) {
-		if (fontStyle == style) {
-			return false;
-		}
-
-		fontStyle = style;
-		invalidate();
-
-		return true;
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableRowCore#setAlpha(int)
-	public boolean setAlpha(int alpha) {
-		if (this.alpha == alpha) {
-			return false;
-		}
-
-		this.alpha = alpha;
-		invalidate();
-
-		return true;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableRowSWT#getAlpha()
-	public int getAlpha() {
-		return alpha;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableRowSWT#getFontStyle()
-	public int getFontStyle() {
-		return fontStyle;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#isVisible()
-	public boolean isVisible() {
-		return tableView.isRowVisible(this);
-		//return Utils.execSWTThreadWithBool("isVisible", new AERunnableBoolean() {
-		//	public boolean runSupport() {
-		//		return TableRowImpl.super.isVisible();
-		//	}
-		//}, 1000);
-	}
-
-	public boolean isVisibleNoSWT() {
-		return tableView.isRowVisible(this);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#setSelected(boolean)
-	public void setSelected(boolean selected) {
-		if (tableView instanceof TableViewSWT) {
-			((TableViewSWT<COREDATASOURCE>) tableView).setRowSelected(this, selected, true);
-		}
-	}
-
-	public void setWidgetSelected(boolean selected) {
-		super.setSelected(selected);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#isSelected()
-	public boolean isSelected() {
-		return tableView.isSelected(this);
-		/*
-		return Utils.execSWTThreadWithBool("isSelected", new AERunnableBoolean() {
-			public boolean runSupport() {
-				return TableRowImpl.super.isSelected();
-			}
-		}, 1000);
-		*/
-	}
-
-	// @see org.gudy.azureus2.ui.swt.components.BufferedTableRow#setSubItemCount(int)
-	@SuppressWarnings("rawtypes")
-	public void setSubItemCount(final int count) {
-		super.setSubItemCount(count);
-		if (count == getSubItemCount()) {
-			if (count == 0 || (subRows != null && subRows[0] == null)) {
-				return;
-			}
-		}
-		mon_SubRows.enter();
-		try {
-			subRows = new TableRowImpl[count];
-			for (int i = 0; i < count; i++) {
-				//subRows[i] = new TableRowImpl(this, tableView, table, columnsSorted,
-				//		getTableID(), null, i, bSkipFirstColumn);
-				subRows[i] = null;
-			}
-		} finally {
-			mon_SubRows.exit();
-		}
-	}
-
-	@SuppressWarnings("rawtypes")
-	public void setSubItems(Object[] datasources) {
-		this.subDataSources = datasources;
-		super.setSubItemCount(datasources.length);
-
-		mon_SubRows.enter();
-		try {
-			subRows = new TableRowImpl[datasources.length];
-			for (int i = 0; i < datasources.length; i++) {
-				//subRows[i] = new TableRowImpl(this, tableView, table, columnsSorted,
-				//		getTableID(), datasources[i], i, bSkipFirstColumn);
-				subRows[i] = null;
-			}
-		} finally {
-			mon_SubRows.exit();
-		}
-	}
-
-	public TableRowCore linkSubItem(int indexOf) {
-		mon_SubRows.enter();
-		try {
-			if (indexOf >= subRows.length) {
-				return null;
-			}
-			TableRowImpl<Object> subRow = subRows[indexOf];
-			if (subRow == null) {
-				subRows[indexOf] = subRow = new TableRowImpl(this, tableView, table,
-						columnsSorted, getTableID(), subDataSources[indexOf], indexOf,
-						bSkipFirstColumn);
-			}
-			TableItemOrTreeItem subItem = item.getItem(indexOf);
-			subRow.setTableItem(subItem, true);
-			return subRow;
-		} finally {
-			mon_SubRows.exit();
-		}
-	}
-
-	public TableRowCore[] getSubRowsWithNull() {
-		mon_SubRows.enter();
-		try {
-			TableRowCore[] copyOf = new TableRowCore[subRows.length];
-			System.arraycopy(subRows, 0, copyOf, 0, subRows.length);
-			return copyOf;
-		} finally {
-			mon_SubRows.exit();
-		}
-	}
-	
-	public TableRowCore getSubRow(int pos) {
-		mon_SubRows.enter();
-		try {
-			int i = -1;
-			for (TableRowCore row : subRows) {
-				if (row != null) {
-					i++;
-					if (i == pos) {
-						return row;
-					}
-				}
-			}
-			return null;
-		} finally {
-			mon_SubRows.exit();
-		}
-	}
-
-	public void removeSubRow(final Object datasource) {
-		Utils.execSWTThreadLater(0, new AERunnable() {
-			public void runSupport() {
-				swt_removeSubRow(datasource);
-			}
-		});
-	}
-
-	public void swt_removeSubRow(Object datasource) {
-		if (datasource instanceof TableRowImpl) {
-			removeSubRow(((TableRowImpl) datasource).getDataSource());
-		}
-
-		mon_SubRows.enter();
-		try {
-			if (subDataSources == null || subDataSources.length == 0
-					|| subDataSources.length != subRows.length) {
-				return;
-			}
-
-			for (int i = 0; i < subDataSources.length; i++) {
-				Object ds = subDataSources[i];
-				if (ds == datasource) { // use .equals instead?
-					TableRowImpl rowToDel = subRows[i];
-					TableRowImpl[] newSubRows = new TableRowImpl[subRows.length - 1];
-					System.arraycopy(subRows, 0, newSubRows, 0, i);
-					System.arraycopy(subRows, i + 1, newSubRows, i, subRows.length - i
-							- 1);
-					subRows = newSubRows;
-
-					Object[] newDatasources = new Object[subRows.length];
-					System.arraycopy(subDataSources, 0, newDatasources, 0, i);
-					System.arraycopy(subDataSources, i + 1, newDatasources, i,
-							subDataSources.length - i - 1);
-					subDataSources = newDatasources;
-
-					rowToDel.dispose();
-					rowToDel.delete();
-
-					super.setSubItemCount(subRows.length);
-
-					break;
-				}
-			}
-		} finally {
-			mon_SubRows.exit();
-		}
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableRowCore#isInPaintItem()
-	public boolean isInPaintItem() {
-		return super.inPaintItem();
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableRowCore#getParentRowCore()
-	public TableRowCore getParentRowCore() {
-		return parentRow;
-	}
-
-	public TableItemOrTreeItem getItem() {
-		return super.item;
-	}
-
-	public int getFullHeight() {
-		// TODO: should include subitems
-		return getBounds(1).height;
-	}
-
-	public void setSortColumn(String columnID) {
-		// ignored
-	}
-
-	public TableCellCore getSortColumnCell(String hint) {
-		if (bDisposed || mTableCells == null) {
-			return null;
-		}
-		return mTableCells.get(hint);
-	}
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableRowSWTBase.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableRowSWTBase.java
index ab6bafd..9bc9f53 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableRowSWTBase.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableRowSWTBase.java
@@ -1,10 +1,28 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table.impl;
 
 import java.util.*;
 
 import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.widgets.Display;
-
+import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.util.AERunnable;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.plugins.ui.tables.*;
@@ -26,6 +44,9 @@ public abstract class TableRowSWTBase
 {
 	public static boolean DEBUG_ROW_PAINT = false;
 
+	private static final boolean expand_enabled = COConfigurationManager.getBooleanParameter("Table.useTree");
+
+	
 	protected Object lock;
 
 	private final TableViewSWT tv;
@@ -458,6 +479,12 @@ public abstract class TableRowSWTBase
 	public boolean isMouseOver() {
 		return tv.getTableRowWithCursor() == this;
 	}
+	
+	public boolean
+	canExpand()
+	{
+		return( expand_enabled );
+	}
 
 	/* (non-Javadoc)
 	 * @see com.aelitis.azureus.ui.common.table.TableRowCore#isExpanded()
@@ -470,11 +497,14 @@ public abstract class TableRowSWTBase
 	 * @see com.aelitis.azureus.ui.common.table.TableRowCore#setExpanded(boolean)
 	 */
 	public void setExpanded(boolean b) {
-		if ( expanded != b ){
-		
-			expanded = b;
+		if ( canExpand() ){
+
+			if ( expanded != b ){
 			
-			tv.invokeExpansionChangeListeners( this, b );
+				expanded = b;
+				
+				tv.invokeExpansionChangeListeners( this, b );
+			}
 		}
 	}
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableTooltips.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableTooltips.java
index c73cef9..50d7f0c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableTooltips.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableTooltips.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.table.impl;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewFactory.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewFactory.java
index d3fd734..c573768 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewFactory.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewFactory.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table.impl;
 
 import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
@@ -7,19 +25,12 @@ import com.aelitis.azureus.ui.common.table.TableColumnCore;
 
 public class TableViewFactory
 {
-	public static<V> TableViewSWT<V> createTableViewSWT(Class<?> pluginDataSourceType, String _sTableID,
-			String _sPropertiesPrefix, TableColumnCore[] _basicItems,
-			String _sDefaultSortOn, int _iTableStyle) {
-		//return new TableViewSWTImpl<V>(pluginDataSourceType, _sTableID, _sPropertiesPrefix, _basicItems, _sDefaultSortOn, _iTableStyle);
-		return (TableViewSWT<V>) new TableViewPainted(pluginDataSourceType, _sTableID, _sPropertiesPrefix, _basicItems, _sDefaultSortOn, _iTableStyle);
-	}
-
-	public static<V> TableViewSWT<V> createTableViewSWT(boolean newCode, Class<?> pluginDataSourceType, String _sTableID,
+	public static <V> TableViewSWT<V> createTableViewSWT(
+			Class<?> pluginDataSourceType, String _sTableID,
 			String _sPropertiesPrefix, TableColumnCore[] _basicItems,
 			String _sDefaultSortOn, int _iTableStyle) {
-		if (newCode) {
-			return (TableViewSWT<V>) new TableViewPainted(pluginDataSourceType, _sTableID, _sPropertiesPrefix, _basicItems, _sDefaultSortOn, _iTableStyle);
-		}
-		return new TableViewSWTImpl<V>(pluginDataSourceType, _sTableID, _sPropertiesPrefix, _basicItems, _sDefaultSortOn, _iTableStyle);
+		return (TableViewSWT<V>) new TableViewPainted(pluginDataSourceType,
+				_sTableID, _sPropertiesPrefix, _basicItems, _sDefaultSortOn,
+				_iTableStyle);
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWTImpl.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWTImpl.java
deleted file mode 100644
index 9343786..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWTImpl.java
+++ /dev/null
@@ -1,2972 +0,0 @@
-/*
- *
- * 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.table.impl;
-
-import java.lang.reflect.Method;
-import java.util.*;
-import java.util.List;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.*;
-import org.eclipse.swt.dnd.*;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.layout.*;
-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.internat.MessageText.MessageTextListener;
-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.plugins.ui.tables.TableCellInplaceEditorListener;
-import org.gudy.azureus2.plugins.ui.tables.TableRowMouseEvent;
-import org.gudy.azureus2.plugins.ui.tables.TableRowMouseListener;
-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;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
-import org.gudy.azureus2.ui.swt.pluginsimpl.*;
-import org.gudy.azureus2.ui.swt.views.table.*;
-import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnSWTUtils;
-
-import com.aelitis.azureus.ui.common.table.*;
-import com.aelitis.azureus.ui.common.table.TableViewFilterCheck;
-import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
-import com.aelitis.azureus.ui.common.table.impl.TableViewImpl;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-
-/** 
- * An IView with a sortable table.  Handles composite/menu/table creation
- * and management.
- *
- * @deprecated This implementation requires much massaging of the native table/tree widget
- * 
- * @author Olivier (Original PeersView/MyTorrentsView/etc code)
- * @author TuxPaper
- *         2004/Apr/20: Remove need for tableItemToObject
- *         2005/Oct/07: Virtual Table
- *         2005/Nov/16: Moved TableSorter into TableView
- *         
- * @note From TableSorter.java:<br>
- *   <li>2004/Apr/20: Remove need for tableItemToObject (store object in tableItem.setData)
- *   <li>2004/May/11: Use Comparable instead of SortableItem
- *   <li>2004/May/14: moved from org.gudy.azureus2.ui.swt.utils
- *   <li>2005/Oct/10: v2307 : Sort SWT.VIRTUAL Tables, Column Indicator
- *   
- * @future TableView should be split into two.  One for non SWT functions, and
- *          the other extending the first, with extra SWT stuff. 
- *
- * @future dataSourcesToRemove should be removed after a certain amount of time
- *          has passed.  Currently, dataSourcesToRemove is processed every
- *          refresh IF the table is visible, or it is processed when we collect
- *          20 items to remove.
- *          
- * @note 4005: We set a text cell's measured width to the columns prefered width
- *             instead of setting it to the actual space needed for the text.
- *             We should really store the last measured width in TableCell and
- *             use that.
- */
-public class TableViewSWTImpl<DATASOURCETYPE>
-	extends TableViewImpl<DATASOURCETYPE>
-	implements ParameterListener, TableViewSWT<DATASOURCETYPE>,
-	ObfusticateImage, MessageTextListener
-{
-	protected final static boolean DRAW_VERTICAL_LINES = Constants.isWindows;
-
-	protected static final boolean DRAW_FULL_ROW = Constants.isWindows;
-
-	private final static LogIDs LOGID = LogIDs.GUI;
-
-	protected static final boolean DEBUG_CELL_CHANGES = false;
-
-	private static final boolean DEBUG_ROWCHANGE = false;
-
-	private static final boolean OBEY_COLUMN_MINWIDTH = false;
-
-	/** Column name to sort on if user hasn't chosen one yet 
-	 */
-	protected String sDefaultSortOn;
-
-	/** 1st column gap problem (Eclipse Bug 43910).  Set to true when table is 
-	 * using TableItem.setImage 
-	 */
-	protected boolean bSkipFirstColumn = true;
-
-	private Point ptIconSize = null;
-
-	/** Composite for IView implementation */
-	private Composite mainComposite;
-
-	/** Composite that stores the table (sometimes the same as mainComposite) */
-	private Composite tableComposite;
-
-	/** Table for SortableTable implementation */
-	private TableOrTreeSWT table;
-
-	private ControlEditor editor;
-
-	/** SWT style options for the creation of the Table */
-	protected int iTableStyle;
-
-	/** Context Menu */
-	private Menu menu;
-
-	/** For updating GUI.  
-	 * Some UI objects get updating every X cycles (user configurable) 
-	 */
-	protected int loopFactor;
-
-	/** How often graphic cells get updated
-	 */
-	protected int graphicsUpdate = configMan.getIntParameter("Graphics Update");
-
-	protected int reOrderDelay = configMan.getIntParameter("ReOrder Delay");
-
-	/**
-	 * Cache of selected table items to bypass insufficient drawing on Mac OS X
-	 */
-	//private ArrayList oldSelectedItems;
-
-	private ColumnMoveListener columnMoveListener = new ColumnMoveListener();
-
-	/** TabViews */
-	private boolean bEnableTabViews = false;
-
-	private boolean tabViewsExpandedByDefault = true;
-	
-	private TableRowSWT[] visibleRows;
-
-	private boolean[] columnsVisible;
-
-	private TableViewSWTPanelCreator mainPanelCreator;
-
-	private boolean columnPaddingAdjusted = false;
-
-	private boolean columnVisibilitiesChanged = true;
-
-	/**
-	 * Up to date table client area.  So far, the best places to refresh
-	 * this variable are in the PaintItem event and the scrollbar's events.
-	 * Typically table.getClientArea() is time consuming 
-	 */
-	protected Rectangle clientArea;
-
-	private boolean isVisible;
-
-	// private Rectangle firstClientArea;
-
-	private int lastHorizontalPos;
-	
-
-	private boolean useTree;
-
-	protected int headerHeight;
-
-	private Shell shell;
-
-	private TableViewSWT_Common tvSWTCommon;
-
-	private TableViewSWT_TabsCommon tvTabsCommon;
-
-
-	/**
-	 * Main Initializer
-	 * @param _sTableID Which table to handle (see 
-	 *                   {@link org.gudy.azureus2.plugins.ui.tables.TableManager}).
-	 *                   Config settings are stored with the prefix of  
-	 *                   "Table.<i>TableID</i>"
-	 * @param _sPropertiesPrefix Prefix for retrieving text from the properties
-	 *                            file (MessageText).  Typically 
-	 *                            <i>TableID</i> + "View"
-	 * @param _basicItems Column Definitions
-	 * @param _sDefaultSortOn Column name to sort on if user hasn't chosen one yet
-	 * @param _iTableStyle SWT style constants used when creating the table
-	 */
-	public TableViewSWTImpl(Class<?> pluginDataSourceType, String _sTableID,
-			String _sPropertiesPrefix, TableColumnCore[] _basicItems,
-			String _sDefaultSortOn, int _iTableStyle) {
-		super(pluginDataSourceType, _sTableID, _sPropertiesPrefix, _basicItems);
-		setProvideIndexesOnRemove(true);
-		boolean wantTree = (_iTableStyle & SWT.CASCADE) != 0;
-		_iTableStyle &= ~SWT.CASCADE;
-		if (wantTree) {
-			useTree = COConfigurationManager.getBooleanParameter("Table.useTree")
-					&& !Utils.isCarbon;
-		}
-		sDefaultSortOn = _sDefaultSortOn;
-		iTableStyle = _iTableStyle | SWT.V_SCROLL | SWT.DOUBLE_BUFFERED;
-
-		tvSWTCommon = new TableViewSWT_Common(this) {
-			@Override
-			public void mouseDown(TableRowSWT row, TableCellCore cell, int button,
-					int stateMask) {
-				if (row != null && !row.isRowDisposed()) {
-					tv.setRowSelected(row, true, true);
-				}
-			}
-			
-			public void widgetSelected(SelectionEvent event) {
-				updateSelectedRows(table.getSelection(), true);
-			}
-			
-			@Override
-			public void keyReleased(KeyEvent e) {
-				swt_calculateClientArea();
-				visibleRowsChanged();
-
-				super.keyReleased(e);
-			}
-		};
-	}
-
-	/**
-	 * Main Initializer. Table Style will be SWT.SINGLE | SWT.FULL_SELECTION
-	 *
-	 * @param _sTableID Which table to handle (see 
-	 *                   {@link org.gudy.azureus2.plugins.ui.tables.TableManager}
-	 *                   ).  Config settings are stored with the prefix of 
-	 *                   "Table.<i>TableID</i>"
-	 * @param _sPropertiesPrefix Prefix for retrieving text from the properties
-	 *                            file (MessageText).  
-	 *                            Typically <i>TableID</i> + "View"
-	 * @param _sDefaultSortOn Column name to sort on if user hasn't chosen one
-	 *                         yet
-	 */
-	public TableViewSWTImpl(Class<?> pluginDataSourceType, String _sTableID,
-			String _sPropertiesPrefix, String _sDefaultSortOn) {
-
-		this(pluginDataSourceType, _sTableID, _sPropertiesPrefix,
-				new TableColumnCore[0], _sDefaultSortOn, SWT.SINGLE
-						| SWT.FULL_SELECTION | SWT.VIRTUAL);
-	}
-
-	// AbstractIView::initialize
-	public void initialize(Composite composite) {
-		composite.setRedraw(false);
-
-		tvTabsCommon = new TableViewSWT_TabsCommon(this);
-
-		shell = composite.getShell();
-		mainComposite = tvTabsCommon.createSashForm(composite);
-		tableComposite = tvTabsCommon.tableComposite;
-		table = createTable(tableComposite);
-		menu = createMenu(table);
-		clientArea = table.getClientArea();
-		editor = TableOrTreeUtils.createTableOrTreeEditor(table);
-		editor.minimumWidth = 80;
-		editor.grabHorizontal = true;
-		initializeTable(table);
-
-		triggerLifeCycleListener(TableLifeCycleListener.EVENT_INITIALIZED);
-
-		configMan.addParameterListener("Graphics Update", this);
-		configMan.addParameterListener("ReOrder Delay", this);
-		Colors.getInstance().addColorsChangedListener(this);
-
-		// So all TableView objects of the same TableID have the same columns,
-		// and column widths, etc
-		TableStructureEventDispatcher.getInstance(tableID).addListener(this);
-		composite.setRedraw(true);
-	}
-
-
-	/** Creates a composite within the specified composite and sets its layout
-	 * to a default FillLayout().
-	 *
-	 * @param composite to create your Composite under
-	 * @return The newly created composite
-	 */
-	public Composite createMainPanel(Composite composite) {
-		TableViewSWTPanelCreator mainPanelCreator = getMainPanelCreator();
-		if (mainPanelCreator != null) {
-			return mainPanelCreator.createTableViewPanel(composite);
-		}
-		Composite panel = new Composite(composite, SWT.NO_FOCUS);
-		composite.getLayout();
-		GridLayout layout = new GridLayout();
-		layout.marginHeight = 0;
-		layout.marginWidth = 0;
-		panel.setLayout(layout);
-
-		Object parentLayout = composite.getLayout();
-		if (parentLayout == null || (parentLayout instanceof GridLayout)) {
-			panel.setLayoutData(new GridData(GridData.FILL_BOTH));
-		}
-
-		return panel;
-	}
-
-	/** Creates the Table.
-	 *
-	 * @return The created Table.
-	 */
-	public TableOrTreeSWT createTable(Composite panel) {
-		table = TableOrTreeUtils.createGrid(panel, iTableStyle, useTree);
-		table.setLayoutData(new GridData(GridData.FILL_BOTH));
-
-		return table;
-	}
-
-	/** Sets up the sorter, columns, and context menu.
-	 *
-	 * @param table Table to be initialized
-	 */
-	public void initializeTable(final TableOrTreeSWT table) {
-		iTableStyle = table.getStyle();
-		if ((iTableStyle & SWT.VIRTUAL) == 0) {
-			throw new Error("Virtual Table Required");
-		}
-
-		table.setLinesVisible(Utils.TABLE_GRIDLINE_IS_ALTERNATING_COLOR);
-		table.setMenu(menu);
-		table.setData("Name", tableID);
-		table.setData("ObfusticateImage", this);
-		
-		// On Windows, TreeItems POSTPAINT event spendsabout 7% of it's time in getFont()
-		// calling the OS API.  If we set the font, it skips the API call.
-		// This could be optimized further by setting the font on each table item,
-		// however, it's unknown what performace hit we'd get on row creation.
-		table.setFont(table.getFont());
-
-		// Setup table
-		// -----------
-
-		table.addPaintListener(new PaintListener() {
-			public void paintControl(PaintEvent event) {
-				swt_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.PaintItem, new TableViewSWT_PaintItem(this, table));
-
-		if (Constants.isWindows) {
-			TableViewSWT_EraseItem eraseItemListener = new TableViewSWT_EraseItem(this, table);
-			table.addListener(SWT.EraseItem, eraseItemListener);
-			table.addListener(SWT.Paint, eraseItemListener);
-		}
-
-		ScrollBar horizontalBar = table.getHorizontalBar();
-		if (horizontalBar != null) {
-			horizontalBar.addSelectionListener(new SelectionListener() {
-				public void widgetDefaultSelected(SelectionEvent e) {
-					Utils.execSWTThreadLater(0, new AERunnable() {
-						public void runSupport() {
-							swt_calculateClientArea();
-						}
-					});
-					//updateColumnVisibilities();
-				}
-
-				public void widgetSelected(SelectionEvent e) {
-					Utils.execSWTThreadLater(0, new AERunnable() {
-						public void runSupport() {
-							swt_calculateClientArea();
-						}
-					});
-					//updateColumnVisibilities();
-				}
-			});
-		}
-
-		table.addListener(SWT.MeasureItem, new Listener() {
-			public void handleEvent(Event event) {
-				int iColumnNo = event.index;
-
-				if (bSkipFirstColumn) {
-					iColumnNo--;
-				}
-
-				TableColumnCore[] columnsOrdered = getVisibleColumns();
-				if (iColumnNo >= 0 && iColumnNo < columnsOrdered.length) {
-					TableColumnCore tc = columnsOrdered[iColumnNo];
-					int preferredWidth = tc.getPreferredWidth();
-					event.width = preferredWidth;
-				}
-
-				int defaultHeight = getRowDefaultHeight();
-				if (event.height < defaultHeight) {
-					event.height = defaultHeight;
-				}
-			}
-		});
-
-		// Deselect rows if user clicks on a blank spot (a spot with no row)
-		table.addMouseListener(tvSWTCommon);
-		table.addMouseMoveListener(tvSWTCommon);
-		table.addSelectionListener(tvSWTCommon);
-		
-		// we are sent a SWT.Settings event when the language changes and
-		// when System fonts/colors change.  In both cases, invalidate
-		table.addListener(SWT.Settings, new Listener() {
-			public void handleEvent(Event e) {
-				tableInvalidate();
-			}
-		});
-		
-		if (useTree) {
-  		Listener listenerExpandCollapse = new Listener() {
-  			public void handleEvent(Event event) {
-  				TableItemOrTreeItem item = TableOrTreeUtils.getEventItem(event.item);
-  				if (item == null) {
-  					return;
-  				}
-  				TableRowCore row = getRow(item);
-  				if (row == null || row.isRowDisposed()) {
-  					return;
-  				}
-  				row.setExpanded(event.type == SWT.Expand ? true : false);
-  				Utils.execSWTThreadLater(0, new AERunnable() {
-						public void runSupport() {
-							visibleRowsChanged();
-						}
-					});
-  			}
-  		};
-  		table.addListener(SWT.Expand, listenerExpandCollapse);
-  		table.addListener(SWT.Collapse, listenerExpandCollapse);
-		}
-
-		new TableTooltips(this, table.getComposite());
-
-		table.addKeyListener(tvSWTCommon);
-		
-		table.addDisposeListener(new DisposeListener(){
-			public void widgetDisposed(DisposeEvent e) {
-				TableViewSWTFilter<?> filter = getSWTFilter();
-				if (filter != null && filter.widget != null && !filter.widget.isDisposed()) {
-					filter.widget.removeKeyListener(tvSWTCommon);
-					filter.widget.removeModifyListener(filter.widgetModifyListener);
-				}
-				Utils.disposeSWTObjects(new Object[] { sliderArea } );
-			}
-		});
-/*
-		if (Utils.isCocoa) {
-			table.addListener(SWT.MouseVerticalWheel, new Listener() {
-				public void handleEvent(Event event) {
-					calculateClientArea();
-					visibleRowsChanged();
-				}
-			});
-		}
-*/		
-		ScrollBar bar = table.getVerticalBar();
-		if (bar != null) {
-			bar.addSelectionListener(new SelectionAdapter() {
-				public void widgetSelected(SelectionEvent e) {
-					Utils.execSWTThreadLater(0, new AERunnable() {
-						public void runSupport() {
-							// need to calc later as getClientArea isn't up to date yet
-							// on Win
-							swt_calculateClientArea();
-							visibleRowsChanged();
-						}
-					});
-					// Bug: Scroll is slow when table is not focus
-					if (!table.isFocusControl()) {
-						table.setFocus();
-					}
-				}
-			});
-		}
-
-		table.setHeaderVisible(getHeaderVisible());
-		headerHeight = table.getHeaderHeight();
-
-		clientArea = table.getClientArea();
-		//firstClientArea = table.getClientArea();
-		table.addListener(SWT.Resize, new Listener() {
-			public void handleEvent(Event event) {
-				swt_calculateClientArea();
-			}
-		});
-
-		swt_initializeTableColumns(table);
-
-		MessageText.addListener(this);
-	}
-	
-	public void localeChanged(Locale old_locale, Locale new_locale) {
-		Utils.execSWTThreadLater(0, new AERunnable() {
-			public void runSupport() {
-				if (tvTabsCommon != null) {
-					tvTabsCommon.localeChanged();
-				}
-				tableInvalidate();
-				refreshTable(true);
-
-				TableColumnOrTreeColumn[] tableColumnsSWT = table.getColumns();
-				for (int i = 0; i < tableColumnsSWT.length; i++) {
-					TableColumnCore column = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore");
-					if (column != null) {
-						Messages.setLanguageText(tableColumnsSWT[i].getColumn(),
-								column.getTitleLanguageKey());
-					}
-				}
-
-			}
-		});
-	}
-
-	
-	// @see com.aelitis.azureus.ui.common.table.TableView#setHeaderVisible(boolean)
-	public void setHeaderVisible(boolean visible) {
-		super.setHeaderVisible(visible);
-
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				if (table != null && !table.isDisposed()) {
-					table.setHeaderVisible(getHeaderVisible());
-					headerHeight = table.getHeaderHeight();
-				}
-			}
-		});
-	}
-
-	protected void swt_calculateClientArea() {
-		Rectangle oldClientArea = clientArea;
-		clientArea = table.getClientArea();
-		ScrollBar horizontalBar = table.getHorizontalBar();
-		boolean clientAreaCausedVisibilityChanged = false;
-		if (horizontalBar != null) {
-			int pos = horizontalBar.getSelection();
-			if (pos != lastHorizontalPos) {
-				lastHorizontalPos = pos;
-				clientAreaCausedVisibilityChanged = true;
-			}
-		}
-		if (oldClientArea != null
-				&& (oldClientArea.x != clientArea.x || oldClientArea.width != clientArea.width)) {
-			clientAreaCausedVisibilityChanged = true;
-		}
-		if (oldClientArea != null
-				&& (oldClientArea.y != clientArea.y || oldClientArea.height != clientArea.height)) {
-			visibleRowsChanged();
-		}
-		if (oldClientArea != null
-				&& (oldClientArea.height < table.getHeaderHeight())) {
-			clientAreaCausedVisibilityChanged = true;
-		}
-		if (clientAreaCausedVisibilityChanged) {
-			columnVisibilitiesChanged = true;
-			Utils.execSWTThreadLater(50, new AERunnable() {
-				public void runSupport() {
-					if (columnVisibilitiesChanged) {
-						refreshTable(false);
-					}
-				}
-			});
-		}
-	}
-
-	public void triggerTabViewsDataSourceChanged(boolean sendParent) {
-		if (tvTabsCommon != null) {
-			tvTabsCommon.triggerTabViewsDataSourceChanged(sendParent);
-		}
-	}
-
-	private interface SourceReplaceListener
-	{
-		void sourcesChanged();
-
-		void cleanup(Text toClean);
-	}
-
-	private SourceReplaceListener cellEditNotifier;
-
-	private Control sliderArea;
-
-	private boolean isDragging;
-
-	private int maxItemShown = -1;
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#editCell(int, int)
-	 */
-	public void editCell(final TableColumnCore column, final int row) {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				swt_editCell(column, row);
-			}
-		});
-	}
-
-	private void swt_editCell(final TableColumnCore column, final int row) {
-		Text oldInput = (Text) editor.getEditor();
-		if (row < 0 || row >= table.getItemCount()) {
-			cellEditNotifier = null;
-			if (oldInput != null && !oldInput.isDisposed()) {
-				editor.getEditor().dispose();
-			}
-			return;
-		}
-
-		final TableItemOrTreeItem item = table.getItem(row);
-
-		String cellName = column.getName();
-		final TableRowSWT rowSWT = (TableRowSWT) getRow(row);
-		final TableCellSWT cell = rowSWT.getTableCellSWT(cellName);
-
-		// reuse widget if possible, this way we'll keep the focus all the time on jumping through the rows
-		final Text newInput = oldInput == null || oldInput.isDisposed() ? new Text(
-				table.getComposite(), Constants.isOSX ? SWT.NONE : SWT.BORDER) : oldInput;
-		final DATASOURCETYPE datasource = (DATASOURCETYPE) cell.getDataSource();
-		if (cellEditNotifier != null) {
-			cellEditNotifier.cleanup(newInput);
-		}
-
-		table.showItem(item);
-		showColumn(column);
-		
-		TableColumnOrTreeColumn swtColumn = getSWTColumn(column);
-		final int swtColumnNo = table.indexOf(swtColumn);
-
-		newInput.setText(cell.getText());
-
-		newInput.setSelection(0);
-		newInput.selectAll();
-		newInput.setFocus();
-
-		class QuickEditListener
-			implements ModifyListener, SelectionListener, KeyListener,
-			TraverseListener, SourceReplaceListener, ControlListener
-		{
-			boolean resizing = true;
-
-			public QuickEditListener(Text toAttach) {
-				toAttach.addModifyListener(this);
-				toAttach.addSelectionListener(this);
-				toAttach.addKeyListener(this);
-				toAttach.addTraverseListener(this);
-				toAttach.addControlListener(this);
-
-				cellEditNotifier = this;
-			}
-
-			public void modifyText(ModifyEvent e) {
-				if (item.isDisposed()) {
-					sourcesChanged();
-					return;
-				}
-				TableColumnCore columnCore = (TableColumnCore) cell.getTableColumn();
-				TableCellInplaceEditorListener inplaceEditorListener = columnCore.getInplaceEditorListener();
-				if (inplaceEditorListener != null
-						&& inplaceEditorListener.inplaceValueSet(cell, newInput.getText(),
-								false)) {
-					newInput.setBackground(null);
-				} else {
-					newInput.setBackground(Colors.colorErrorBG);
-				}
-			}
-
-			public void widgetDefaultSelected(SelectionEvent e) {
-				if (item.isDisposed()) {
-					sourcesChanged();
-					newInput.traverse(SWT.TRAVERSE_RETURN);
-					return;
-				}
-				TableColumnCore columnCore = (TableColumnCore) cell.getTableColumn();
-				TableCellInplaceEditorListener inplaceEditorListener = columnCore.getInplaceEditorListener();
-				if (inplaceEditorListener != null) {
-						inplaceEditorListener.inplaceValueSet(cell, newInput.getText(), true);
-				}
-				rowSWT.invalidate();
-				editCell(column, row + 1);
-			}
-
-			public void widgetSelected(SelectionEvent e) {
-			}
-
-			public void keyPressed(KeyEvent e) {
-				if (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.ARROW_UP) {
-					e.doit = false;
-					editCell(column, row + (e.keyCode == SWT.ARROW_DOWN ? 1 : -1));
-				}
-			}
-
-			public void keyReleased(KeyEvent e) {
-			}
-
-			public void keyTraversed(TraverseEvent e) {
-				if (e.detail == SWT.TRAVERSE_ESCAPE) {
-					e.doit = false;
-					editCell(column, -1);
-				}
-			}
-
-			public void sourcesChanged() {
-				if (getRow(datasource) == rowSWT || getRow(datasource) == null
-						|| newInput.isDisposed()) {
-					return;
-				}
-				String newVal = newInput.getText();
-				Point sel = newInput.getSelection();
-				editCell(column, getRow(datasource).getIndex());
-				if (newInput.isDisposed()) {
-					return;
-				}
-				newInput.setText(newVal);
-				newInput.setSelection(sel);
-			}
-
-			public void cleanup(Text oldText) {
-				if (!oldText.isDisposed()) {
-					oldText.removeModifyListener(this);
-					oldText.removeSelectionListener(this);
-					oldText.removeKeyListener(this);
-					oldText.removeTraverseListener(this);
-					oldText.removeControlListener(this);
-				}
-			}
-
-			public void controlMoved(ControlEvent e) {
-				table.showItem(item);
-				if (resizing) {
-					return;
-				}
-				resizing = true;
-
-				Point sel = newInput.getSelection();
-
-				TableOrTreeUtils.setEditorItem(editor, newInput, swtColumnNo, item);
-
-				editor.minimumWidth = newInput.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
-
-				Rectangle leftAlignedBounds = item.getBounds(swtColumnNo);
-				leftAlignedBounds.width = editor.minimumWidth = newInput.computeSize(
-						SWT.DEFAULT, SWT.DEFAULT).x;
-				if (leftAlignedBounds.intersection(clientArea).equals(leftAlignedBounds)) {
-					editor.horizontalAlignment = SWT.LEFT;
-				} else {
-					editor.horizontalAlignment = SWT.RIGHT;
-				}
-
-				editor.layout();
-
-				newInput.setSelection(0);
-				newInput.setSelection(sel);
-
-				resizing = false;
-			}
-
-			public void controlResized(ControlEvent e) {
-			}
-		}
-
-		QuickEditListener l = new QuickEditListener(newInput);
-
-		l.modifyText(null);
-
-		TableOrTreeUtils.setEditorItem(editor, newInput, swtColumnNo, item);
-		table.deselectAll();
-		table.select(table.getItem(row));
-		setSelectedRows(new TableRowCore[] { getRow(row) }, true);
-
-		l.resizing = false;
-
-		l.controlMoved(null);
-	}
-
-	private TableColumnOrTreeColumn getSWTColumn(TableColumnCore tc) {
-		int[] columnOrder = table.getColumnOrder();
-		int i = tc.getPosition() - (bSkipFirstColumn ? 1 : 0);
-		if (i < 0 || i >= columnOrder.length) {
-			return null;
-		}
-		return table.getColumn(columnOrder[i]);
-	}
-
-	private void showColumn(TableColumnCore tc) {
-		TableColumnOrTreeColumn swtColumn = getSWTColumn(tc);
-		if (swtColumn != null) {
-			table.showColumn(swtColumn);
-		}
-	}
-
-	private void swt_updateColumnVisibilities(boolean doInvalidate) {
-		TableColumnOrTreeColumn[] columns = table.getColumns();
-		if (table.getItemCount() < 1 || columns.length == 0 || !table.isVisible()) {
-			return;
-		}
-		columnVisibilitiesChanged = false;
-		TableItemOrTreeItem topRow = table.getTopItem();
-		if (topRow == null) {
-			return;
-		}
-		for (int i = 0; i < columns.length; i++) {
-			final TableColumnCore tc = (TableColumnCore) columns[i].getData("TableColumnCore");
-			if (tc == null) {
-				continue;
-			}
-
-			int position = tc.getPosition();
-			if (position < 0 || position >= columnsVisible.length) {
-				continue;
-			}
-
-			Rectangle size = topRow.getBounds(i);
-			//System.out.println(tableID + ": column " + i + ":" + tc.getName() + ": size="  + size + "; ca=" + clientArea + "; pos=" + position);
-			size.intersect(clientArea);
-			boolean nowVisible = !size.isEmpty();
-			//System.out.println("  visible; was=" + columnsVisible[position] + "; now=" + nowVisible + ";doValidae=" + doInvalidate);
-			if (columnsVisible[position] != nowVisible) {
-				columnsVisible[position] = nowVisible;
-				if (nowVisible && doInvalidate) {
-					swt_runForVisibleRows(new TableGroupRowRunner() {
-						public void run(TableRowCore row) {
-							TableCellCore cell = row.getTableCellCore(tc.getName());
-							if (cell != null) {
-  							cell.invalidate();
-  							cell.redraw();
-							}
-						}
-					});
-				}
-			}
-		}
-	}
-
-	public boolean isColumnVisible(
-			org.gudy.azureus2.plugins.ui.tables.TableColumn column) {
-		int position = column.getPosition();
-		if (position < 0 || position >= columnsVisible.length) {
-			return false;
-		}
-		return columnsVisible[position];
-
-	}
-
-	protected void swt_initializeTableColumns(final TableOrTreeSWT table) {
-		TableColumnOrTreeColumn[] oldColumns = table.getColumns();
-
-		for (int i = 0; i < oldColumns.length; i++) {
-			oldColumns[i].removeListener(SWT.Move, columnMoveListener);
-		}
-
-		for (int i = oldColumns.length - 1; i >= 0; i--) {
-			oldColumns[i].dispose();
-		}
-
-		columnPaddingAdjusted = false;
-
-		// Pre 3.0RC1 SWT on OSX doesn't call this!! :(
-		ControlListener resizeListener = new ControlAdapter() {
-			// Bug: getClientArea() eventually calls back to controlResized,
-			//      creating a loop until a stack overflow
-			private boolean bInFunction = false;
-
-			public void controlResized(ControlEvent e) {
-				TableColumnOrTreeColumn column = TableOrTreeUtils.getTableColumnEventItem(e.widget);
-				if (column == null || column.isDisposed() || bInFunction) {
-					return;
-				}
-
-				try {
-					bInFunction = true;
-
-					TableColumnCore tc = (TableColumnCore) column.getData("TableColumnCore");
-					if (tc != null) {
-						Long lPadding = (Long) column.getData("widthOffset");
-						int padding = (lPadding == null) ? 0 : lPadding.intValue();
-						int newWidth = column.getWidth();
-						if (OBEY_COLUMN_MINWIDTH) {
-  						int minWidth = tc.getMinWidth();
-  						if (minWidth > 0 && newWidth - padding < minWidth) {
-  							newWidth = minWidth + padding;
-  							column.setWidth(minWidth);
-  						}
-						}
-						tc.setWidth(newWidth - padding);
-					}
-
-					int columnNumber = table.indexOf(column);
-					locationChanged(columnNumber);
-				} finally {
-					bInFunction = false;
-				}
-			}
-		};
-
-		// Add 1 to position because we make a non resizable 0-sized 1st column
-		// to fix the 1st column gap problem (Eclipse Bug 43910)
-
-		// SWT does not set 0 column width as expected in OS X; see bug 43910
-		// this will be removed when a SWT-provided solution is available to satisfy all platforms with identation issue
-		//bSkipFirstColumn = bSkipFirstColumn && !Constants.isOSX;
-
-		if (bSkipFirstColumn) {
-			TableColumnOrTreeColumn tc = table.createNewColumn(SWT.NULL);
-			//tc.setWidth(useTree ? 25 : 0);
-			tc.setWidth(0);
-			tc.setResizable(false);
-			tc.setMoveable(false);
-		}
-
-		TableColumnCore[] tableColumns = getAllColumns();
-		TableColumnCore[] tmpColumnsOrdered = new TableColumnCore[tableColumns.length];
-		//Create all columns
-		int columnOrderPos = 0;
-		Arrays.sort(tableColumns,
-				TableColumnManager.getTableColumnOrderComparator());
-		for (int i = 0; i < tableColumns.length; i++) {
-			int position = tableColumns[i].getPosition();
-			if (position != -1 && tableColumns[i].isVisible()) {
-				table.createNewColumn(SWT.NULL);
-				//System.out.println(i + "] " + tableColumns[i].getName() + ";" + position);
-				tmpColumnsOrdered[columnOrderPos++] = tableColumns[i];
-			}
-		}
-		int numSWTColumns = table.getColumnCount();
-		int iNewLength = numSWTColumns - (bSkipFirstColumn ? 1 : 0);
-		TableColumnCore[] columnsOrdered = new TableColumnCore[iNewLength];
-		System.arraycopy(tmpColumnsOrdered, 0, columnsOrdered, 0, iNewLength);
-		setColumnsOrdered(columnsOrdered);
-		columnsVisible = new boolean[tableColumns.length];
-
-		ColumnSelectionListener columnSelectionListener = new ColumnSelectionListener();
-
-		//Assign length and titles
-		//We can only do it after ALL columns are created, as position (order)
-		//may not be in the natural order (if the user re-order the columns).
-		int swtColumnPos = (bSkipFirstColumn ? 1 : 0);
-		for (int i = 0; i < tableColumns.length; i++) {
-			TableColumnCore columnCore = tableColumns[i];
-			int position = columnCore.getPosition();
-			if (position == -1 || !columnCore.isVisible()) {
-				continue;
-			}
-
-			columnsVisible[i] = false;
-
-			String sName = columnCore.getName();
-			// +1 for Eclipse Bug 43910 (see above)
-			// user has reported a problem here with index-out-of-bounds - not sure why
-			// but putting in a preventative check so that hopefully the view still opens
-			// so they can fix it
-
-			if (swtColumnPos >= numSWTColumns) {
-				Debug.out("Incorrect table column setup, skipping column '" + sName
-						+ "', position=" + swtColumnPos + ";numCols=" + numSWTColumns);
-				continue;
-			}
-
-			TableColumnOrTreeColumn column = table.getColumn(swtColumnPos);
-			try {
-				column.setMoveable(true);
-			} catch (NoSuchMethodError e) {
-				// Ignore < SWT 3.1
-			}
-			column.setAlignment(TableColumnSWTUtils.convertColumnAlignmentToSWT(columnCore.getAlignment()));
-			String iconReference = columnCore.getIconReference();
-			if (iconReference != null) {
-				Image image = ImageLoader.getInstance().getImage(iconReference);
-				column.setImage(image);
-			} else {
-				Messages.setLanguageText(column.getColumn(), columnCore.getTitleLanguageKey());
-			}
-			if (!Constants.isUnix && !Utils.isCarbon) {
-				column.setWidth(columnCore.getWidth());
-			} else {
-				column.setData("widthOffset", new Long(1));
-				column.setWidth(columnCore.getWidth() + 1);
-			}
-			if (columnCore.getMinWidth() == columnCore.getMaxWidth()
-					&& columnCore.getMinWidth() > 0) {
-				column.setResizable(false);
-			}
-			column.setData("TableColumnCore", columnCore);
-			column.setData("configName", "Table." + tableID + "." + sName);
-			column.setData("Name", sName);
-
-			column.addControlListener(resizeListener);
-			// At the time of writing this SWT (3.0RC1) on OSX doesn't call the 
-			// selection listener for tables
-			column.addListener(SWT.Selection, columnSelectionListener);
-			
-
-			swtColumnPos++;
-		}
-
-		// Initialize the sorter after the columns have been added
-		TableColumnManager tcManager = TableColumnManager.getInstance();
-
-		String sSortColumn = tcManager.getDefaultSortColumnName(tableID);
-		if (sSortColumn == null || sSortColumn.length() == 0) {
-			sSortColumn = sDefaultSortOn;
-		}
-
-		TableColumnCore tc = tcManager.getTableColumnCore(tableID, sSortColumn);
-		if (tc == null && tableColumns.length > 0) {
-			tc = tableColumns[0];
-		}
-		setSortColumn(tc, false);
-		fixAlignment(tc, true);
-		swt_changeColumnIndicator();
-
-		// Add move listener at the very end, so we don't get a bazillion useless 
-		// move triggers
-		TableColumnOrTreeColumn[] columns = table.getColumns();
-		for (int i = 0; i < columns.length; i++) {
-			TableColumnOrTreeColumn column = columns[i];
-			column.addListener(SWT.Move, columnMoveListener);
-		}
-
-		columnVisibilitiesChanged = true;
-	}
-
-	public void fixAlignment(TableColumnCore tc, boolean sorted) {
-		if (Constants.isOSX) {
-			if (table.isDisposed() || tc == null) {
-				return;
-			}
-			int[] columnOrder = table.getColumnOrder();
-			int i = tc.getPosition() - (bSkipFirstColumn ? 1 : 0);
-			if (i < 0 || i >= columnOrder.length) {
-				return;
-			}
-			TableColumnOrTreeColumn swtColumn = table.getColumn(columnOrder[i]);
-			if (swtColumn != null) {
-				if (swtColumn.getAlignment() == SWT.RIGHT && sorted) {
-					swtColumn.setText("   " + swtColumn.getText() + "   ");
-				} else {
-					swtColumn.setText(swtColumn.getText().trim());
-				}
-			}
-		}
-	}
-
-	/** Creates the Context Menu.
-	 * @param table 
-	 *
-	 * @return a new Menu object
-	 */
-	private Menu createMenu(final TableOrTreeSWT table) {
-		if (!isMenuEnabled()) {
-			return null;
-		}
-		
-		final Menu menu = new Menu(shell, SWT.POP_UP);
-		table.addListener(SWT.MenuDetect, new Listener() {
-			public void handleEvent(Event event) {
-				Point pt = event.display.map(null, table.getComposite(), new Point(event.x, event.y));
-				boolean noRow = table.getItem(pt) == null;
-
-				Rectangle clientArea = table.getClientArea();
-				boolean inHeader = clientArea.y <= pt.y && pt.y < (clientArea.y + headerHeight);
-				if (!noRow) {
-					noRow = inHeader;
-				}
-				
-				menu.setData("inBlankArea", (!inHeader && noRow));
-
-				menu.setData("isHeader", new Boolean(noRow));
-
-				menu.setData("column",getTableColumnByOffset(event.x)); 
-			}
-		});
-		MenuBuildUtils.addMaintenanceListenerForMenu(menu,
-				new MenuBuildUtils.MenuBuilder() {
-					public void buildMenu(Menu menu, MenuEvent menuEvent) {
-						Object oIsHeader = menu.getData("isHeader");
-						boolean isHeader = (oIsHeader instanceof Boolean)
-								? ((Boolean) oIsHeader).booleanValue() : false;
-						Object oInBlankArea = menu.getData("inBlankArea");
-						boolean inBlankArea = (oInBlankArea instanceof Boolean)
-								? ((Boolean) oInBlankArea).booleanValue() : false;
-
-						TableColumnCore column = (TableColumnCore) menu.getData("column");
-
-						if (isHeader) {
-							tvSWTCommon.fillColumnMenu(menu, column, inBlankArea);
-						} else {
-							tvSWTCommon.fillMenu(menu, column);
-						}
-
-					}
-				});
-
-		return menu;
-	}
-
-
-	/** IView.getComposite()
-	 * @return the composite for this TableView
-	 */
-	public Composite getComposite() {
-		return mainComposite;
-	}
-
-	public Composite getTableComposite() {
-		return tableComposite;
-	}
-	
-	public TableOrTreeSWT getTableOrTreeSWT() {
-		return table;
-	}
-
-	// see common.TableView
-	public void refreshTable(final boolean bForceSort) {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				swt_refreshTable(bForceSort);
-
-				if (tvTabsCommon != null) {
-					tvTabsCommon.swt_refresh();
-				}
-			}
-		});
-
-		super.refreshTable(bForceSort);
-	}
-
-	private void swt_refreshTable(boolean bForceSort) {
-		// don't refresh while there's no table
-		if (table == null) {
-			return;
-		}
-
-		// call to trigger invalidation if visibility changes
-		isVisible();
-
-		// XXX Try/Finally used to be there for monitor.enter/exit, however
-		//     this doesn't stop re-entry from the same thread while already in
-		//     process.. need a bAlreadyRefreshing variable instead
-		try {
-			if (getComposite() == null || getComposite().isDisposed()) {
-				return;
-			}
-
-			if (columnVisibilitiesChanged == true) {
-				swt_updateColumnVisibilities(true);
-			}
-
-			final boolean bDoGraphics = (loopFactor % graphicsUpdate) == 0;
-			final boolean bWillSort = bForceSort || (reOrderDelay != 0)
-					&& ((loopFactor % reOrderDelay) == 0);
-			//System.out.println("Refresh.. WillSort? " + bWillSort);
-
-			if (bWillSort) {
-				TableColumnCore sortColumn = getSortColumn();
-				if (bForceSort && sortColumn != null) {
-					resetLastSortedOn();
-					sortColumn.setLastSortValueChange(SystemTime.getCurrentTime());
-				}
-				_sortColumn(true, false, false);
-			}
-
-			long lTimeStart = SystemTime.getMonotonousTime();
-
-			Utils.getOffOfSWTThread(new AERunnable() {
-				public void runSupport() {
-					//Refresh all visible items in table...
-					runForAllRows(new TableGroupRowVisibilityRunner() {
-						public void run(TableRowCore row, boolean bVisible) {
-							row.refresh(bDoGraphics, bVisible);
-						}
-					});
-				}
-			});
-
-			if (TableViewImpl.DEBUGADDREMOVE) {
-				long lTimeDiff = (SystemTime.getMonotonousTime() - lTimeStart);
-				if (lTimeDiff > 500) {
-					debug(lTimeDiff + "ms to refresh rows");
-				}
-			}
-
-			loopFactor++;
-		} finally {
-		}
-	}
-
-	private void swt_refreshVisibleRows() {
-		if (getComposite() == null || getComposite().isDisposed()) {
-			return;
-		}
-
-		swt_runForVisibleRows(new TableGroupRowRunner() {
-			public void run(TableRowCore row) {
-				row.refresh(false, true);
-			}
-		});
-	}
-
-	private void locationChanged(final int iStartColumn) {
-		if (getComposite() == null || getComposite().isDisposed()) {
-			return;
-		}
-
-		columnVisibilitiesChanged = true;
-
-		runForAllRows(new TableGroupRowRunner() {
-			public void run(TableRowCore row) {
-				row.locationChanged(iStartColumn);
-			}
-		});
-	}
-
-	/*
-	private void doPaint(final GC gc, final Rectangle dirtyArea) {
-		if (getComposite() == null || getComposite().isDisposed()) {
-			return;
-		}
-
-		swt_runForVisibleRows(new TableGroupRowRunner() {
-			public void run(TableRowCore row) {
-				if (!(row instanceof TableRowSWT)) {
-					return;
-				}
-				TableRowSWT rowSWT = (TableRowSWT) row;
-				Rectangle bounds = rowSWT.getBounds();
-				if (bounds.intersects(dirtyArea)) {
-
-					if (Constants.isWindowsVistaOrHigher) {
-						Image imgBG = new Image(gc.getDevice(), bounds.width, bounds.height);
-						gc.copyArea(imgBG, bounds.x, bounds.y);
-						rowSWT.setBackgroundImage(imgBG);
-					}
-
-					//System.out.println("paint " + row);
-					Color oldBG = (Color) row.getData("bgColor");
-					Color newBG = rowSWT.getBackground();
-					if (oldBG == null || !oldBG.equals(newBG)) {
-						//System.out.println("redraw " + row + "; " + oldBG + ";" + newBG);
-						row.invalidate();
-						row.redraw();
-						row.setData("bgColor", newBG);
-					} else {
-						rowSWT.doPaint(gc, true);
-					}
-				}
-			}
-		});
-	}
-	*/
-
-	/** IView.delete: This method is called when the view is destroyed.
-	 * Each color instanciated, images and such things should be disposed.
-	 * The caller is the GUI thread.
-	 */
-	public void delete() {
-		triggerLifeCycleListener(TableLifeCycleListener.EVENT_DESTROYED);
-
-		if (tvTabsCommon != null) {
-			tvTabsCommon.delete();
-			tvTabsCommon = null;
-		}
-
-		TableStructureEventDispatcher.getInstance(tableID).removeListener(this);
-		TableColumnManager tcManager = TableColumnManager.getInstance();
-		if (tcManager != null) {
-			tcManager.saveTableColumns(getDataSourceType(), tableID);
-		}
-
-		if (table != null && !table.isDisposed()) {
-			table.dispose();
-		}
-		removeAllTableRows();
-		configMan.removeParameterListener("ReOrder Delay", this);
-		configMan.removeParameterListener("Graphics Update", this);
-		Colors.getInstance().removeColorsChangedListener(this);
-
-		super.delete();
-
-		//oldSelectedItems =  null;
-		Composite comp = getComposite();
-		if (comp != null && !comp.isDisposed()) {
-			comp.dispose();
-		}
-		
-		MessageText.removeListener(this);
-	}
-
-	// see common.TableView
-
-
-	private void addDataSourcesToSWT(final Object dataSources[], boolean async) {
-		try {
-			if (isDisposed()) {
-				return;
-			}
-			if (DEBUGADDREMOVE) {
-				debug("--" + " Add " + dataSources.length + " rows to SWT "
-						+ (async ? " async " : " NOW"));
-			}
-
-			
-			if (async) {
-				Utils.execSWTThreadLater(0, new AERunnable() {
-					public void runSupport() {
-						_addDataSourcesToSWT(dataSources);
-					}
-				});
-			} else {
-				Utils.execSWTThread(new AERunnable() {
-					public void runSupport() {
-						_addDataSourcesToSWT(dataSources);
-					}
-				}, false);
-			}
-
-			for (int i = 0; i < dataSources.length; i++) {
-				Object dataSource = dataSources[i];
-				if (dataSource == null) {
-					continue;
-				}
-				TableRowCore row = getRow((DATASOURCETYPE) dataSource);
-				TableColumnCore sortColumn = getSortColumn();
-  			if (row != null && sortColumn != null) {
-  				TableCellCore cell = row.getSortColumnCell(sortColumn.getName());
-  				if (cell != null) {
-  					try {
-  						cell.invalidate();
-  						cell.refresh(true);
-  					} catch (Exception e) {
-  						Logger.log(new LogEvent(LOGID,
-  								"Minor error adding a row to table " + tableID, e));
-  					}
-  				}
-  			}
-			}
-
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-	private void _addDataSourcesToSWT(final Object dataSources[]) {
-		if (table == null || table.isDisposed()) {
-			return;
-		}
-
-		mainComposite.getParent().setCursor(
-				table.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
-
-		TableRowCore[] selectedRows = getSelectedRows();
-			
-		boolean bWas0Rows = table.getItemCount() == 0;
-		try {
-
-			if (DEBUGADDREMOVE) {
-				debug("--" + " Add " + dataSources.length + " rows to SWT. size(false) == " + size(false));
-			}
-
-			// purposefully not included in time check 
-			int size = size(false);
-			// Bug in Windows (7).  If you add 10 rows by setItemCount,
-			// Windows will do some crappy shifting down of the non-row area
-			table.setItemCount(size);
-
-			if (size == 1) {
-				columnVisibilitiesChanged = true;
-			}
-
-		} catch (Exception e) {
-			Logger.log(new LogEvent(LOGID, "Error while adding row to Table "
-					+ tableID, e));
-		}
-
-		if (!columnPaddingAdjusted && table.getItemCount() > 0 && bWas0Rows) {
-			TableColumnOrTreeColumn[] tableColumnsSWT = table.getColumns();
-			TableItemOrTreeItem item = table.getItem(0);
-			// on *nix, the last column expands to fill remaining space.. let's just not touch it
-			int len = Constants.isUnix ? tableColumnsSWT.length - 1
-					: tableColumnsSWT.length;
-			for (int i = 0; i < len; i++) {
-				TableColumnCore tc = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore");
-				if (tc != null) {
-					boolean foundOne = false;
-
-					Rectangle bounds = item.getBounds(i);
-					int tcWidth = tc.getWidth();
-					if (tcWidth != 0 && bounds.width != 0) {
-						Object oOldOfs = tableColumnsSWT[i].getData("widthOffset");
-						int oldOfs = (oOldOfs instanceof Number) ? ((Number)oOldOfs).intValue() : 0;
-						int ofs = tc.getWidth() - bounds.width + oldOfs;
-						if (ofs > 0 && ofs != oldOfs) {
-							foundOne = true;
-							tableColumnsSWT[i].setResizable(true);
-							tableColumnsSWT[i].setData("widthOffset", new Long(ofs + oldOfs));
-						}
-					}
-					if (foundOne) {
-						tc.triggerColumnSizeChange(0);
-					}
-				}
-			}
-			columnPaddingAdjusted = true;
-		} 
-		if (bWas0Rows) {
-			swt_updateColumnVisibilities(false);
-		}
-
-		setSelectedRows(selectedRows);
-		if (DEBUGADDREMOVE) {
-			debug("<< " + size(false));
-		}
-
-		boolean bReplacedVisible = false;
-		for (Object ds : dataSources) {
-			TableRowCore row = getRow((DATASOURCETYPE) ds);
-			if (row != null) {
-				int i = indexOf(row);
-				int iTopIndex = uiGetTopIndex();
-				int iBottomIndex = uiGetBottomIndex(iTopIndex);
-				if (i >= iTopIndex && i <= iBottomIndex) {
-					bReplacedVisible = true;
-					break;
-				}
-			}
-		}
-		if (bReplacedVisible) {
-			visibleRowsChanged();
-		}
-		
-		mainComposite.getParent().setCursor(null);
-	}
-	
-	@Override
-	public void reallyAddDataSources(Object[] dataSources) {
-		super.reallyAddDataSources(dataSources);
-
-		addDataSourcesToSWT(dataSources, true);
-	}
-
-	@Override
-	public void uiRemoveRows(TableRowCore[] rows, final Integer[] rowIndexes) {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				if (table == null || table.isDisposed()) {
-					return;
-				}
-
-				//TableRowCore[] oldSelectedRows = getSelectedRows();
-				
-				mainComposite.getParent().setCursor(
-						table.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
-
-				try {
-					int iTopIndex = uiGetTopIndex();
-					int iBottomIndex = uiGetBottomIndex(iTopIndex);
-					if (DEBUGADDREMOVE) {
-						debug("--- Remove: vis rows " + iTopIndex + " to " + iBottomIndex);
-					}
-					
-					boolean needRefresh = false;
-					for (Integer i : rowIndexes) {
-						if (i >= iTopIndex && i <= iBottomIndex) {
-							needRefresh = true;
-							break;
-						}
-					}
-
-					table.setItemCount(getRowCount());
-					fillRowGaps(false);
-					
-					if (needRefresh || iBottomIndex == table.getItemCount() - 1) {
-						table.redraw();
-					}
-				} finally {
-					mainComposite.getParent().setCursor(null);
-					
-				}
-			}
-		});
-		
-	}
-	
-	// from common.TableView
-	public void removeAllTableRows() {
-
-		long lTimeStart = System.currentTimeMillis();
-
-		final TableRowCore[] rows = getRows();
-
-
-		super.removeAllTableRows();
-
-
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				if (DEBUGADDREMOVE) {
-					debug("removeAll (SWT)");
-				}
-
-				if (table != null && !table.isDisposed()) {
-					table.removeAll();
-				}
-
-				// Image Disposal handled by each cell
-
-				for (int i = 0; i < rows.length; i++) {
-					rows[i].delete();
-				}
-			}
-		});
-
-		if (DEBUGADDREMOVE) {
-			long lTimeDiff = (System.currentTimeMillis() - lTimeStart);
-			if (lTimeDiff > 10) {
-				debug("RemovaAll took " + lTimeDiff + "ms");
-			}
-		}
-	}
-
-	/* ParameterListener Implementation */
-
-	public void parameterChanged(String parameterName) {
-		if (parameterName == null || parameterName.equals("Graphics Update")) {
-			graphicsUpdate = configMan.getIntParameter("Graphics Update");
-		}
-		if (parameterName == null || parameterName.equals("ReOrder Delay")) {
-			reOrderDelay = configMan.getIntParameter("ReOrder Delay");
-		}
-		if (parameterName == null || parameterName.startsWith("Color")) {
-			tableInvalidate();
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see com.aelitis.azureus.ui.common.table.impl.TableViewImpl#tableStructureChanged(boolean, java.lang.Class)
-	 */
-	public void tableStructureChanged(final boolean columnAddedOrRemoved,
-			Class forPluginDataSourceType) {
-		if (forPluginDataSourceType == null
-				|| forPluginDataSourceType.equals(getDataSourceType())) {
-			super.tableStructureChanged(columnAddedOrRemoved, forPluginDataSourceType);
-			Utils.execSWTThread(new AERunnable() {
-				public void runSupport() {
-					if (table.isDisposed()) {
-						return;
-					}
-  				_tableStructureChanged(columnAddedOrRemoved);
-  			}
-  		});
-		}
-	}
-	
-	private void _tableStructureChanged(boolean columnAddedOrRemoved) {
-
-		swt_initializeTableColumns(table);
-		refreshTable(false);
-
-		triggerLifeCycleListener(TableLifeCycleListener.EVENT_INITIALIZED);
-	}
-
-	// ITableStructureModificationListener
-	public void columnOrderChanged(final int[] positions) {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				try {
-					if (table.isDisposed()) {
-						return;
-					}
-					table.setColumnOrder(positions);
-					swt_updateColumnVisibilities(true);
-				} catch (NoSuchMethodError e) {
-					// Pre SWT 3.1
-					// This shouldn't really happen, since this function only gets triggered
-					// from SWT >= 3.1
-					tableStructureChanged(false, null);
-				}
-			}
-		});
-	}
-
-	/** 
-	 * The Columns width changed
-	 */
-	// ITableStructureModificationListener
-	public void columnSizeChanged(final TableColumnCore tableColumn, int diff) {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				swt_columnSizeChanged(tableColumn);
-			}
-		});
-	}
-
-	public void swt_columnSizeChanged(TableColumnCore tableColumn) {
-		int newWidth = tableColumn.getWidth();
-		if (table == null || table.isDisposed()) {
-			return;
-		}
-
-		TableColumnOrTreeColumn column = null;
-		TableColumnOrTreeColumn[] tableColumnsSWT = table.getColumns();
-		for (int i = 0; i < tableColumnsSWT.length; i++) {
-			if (tableColumnsSWT[i].getData("TableColumnCore") == tableColumn) {
-				column = tableColumnsSWT[i];
-				break;
-			}
-		}
-		if (column == null) {
-			return;
-		}
-		Long lOfs = (Long) column.getData("widthOffset");
-		if (lOfs != null) {
-			newWidth += lOfs.intValue();
-		}
-		swt_refreshVisibleRows();
-		if (column.isDisposed() || (column.getWidth() == newWidth)) {
-			return;
-		}
-
-		if (Constants.isUnix) {
-			final int fNewWidth = newWidth;
-			final TableColumnOrTreeColumn fTableColumn = column;
-			column.getDisplay().asyncExec(new AERunnable() {
-				public void runSupport() {
-					if (!fTableColumn.isDisposed()) {
-						fTableColumn.setWidth(fNewWidth);
-					}
-				}
-			});
-		} else {
-			column.setWidth(newWidth);
-		}
-	}
-
-	public void columnRefresh(TableColumnCore tableColumn) {
-		final String sColumnName = tableColumn.getName();
-		runForAllRows(new TableGroupRowVisibilityRunner() {
-			public void run(TableRowCore row, boolean bVisible) {
-				TableCellCore cell = row.getTableCellCore(sColumnName);
-				if (cell != null) {
-					cell.refresh(true, bVisible);
-				}
-			}
-		});
-	}
-
-
-	/** Warning: this method may require SWT Thread! 
-	 * 
-	 * TODO: Make sure callers are okay with that
-	 */
-	protected TableRowCore getRow(TableItemOrTreeItem item) {
-		if (item == null) {
-			return null;
-		}
-		try {
-			Object o = item.getData("TableRow");
-			if ((o instanceof TableRowCore) && !((TableRowCore) o).isRowDisposed()) {
-				return (TableRowCore) o;
-			}
-
-			if (item.getParentItem() != null) {
-				TableRowCore row = getRow(item.getParentItem());
-				return row.linkSubItem(item.getParentItem().indexOf(item));
-			}
-			
-			int iPos = table.indexOf(item);
-			//System.out.println(iPos + " has no table row.. associating. " + Debug.getCompressedStackTrace(4));
-			Object sortedRows_sync = getRowsSync();
-			synchronized (sortedRows_sync) {
-				if (iPos >= 0 && iPos < getRowCount()) {
-					TableRowSWT row = (TableRowSWT) getRow(iPos);
-					//System.out.print(".. associating to " + row);
-					if (row != null && !row.isRowDisposed()) {
-						row.setTableItem(iPos);
-						//System.out.println(", now " + row);
-						return row;
-					}
-					return null;
-				}
-			}
-		} catch (Exception e) {
-			Debug.out(e);
-		}
-		return null;
-	}
-
-
-	public TableRowSWT[] swt_getVisibleRows() {
-		if (!isVisible()) {
-			return new TableRowSWT[0];
-		}
-		
-		synchronized (this) {
-  		if (visibleRows == null) {
-  			visibleRowsChanged();
-  		}
-  		
-  		return visibleRows;
-		}
-	}
-
-	/** For each visible row source, run the code provided by the specified 
-	 * parameter.
-	 *
-	 * @param runner Code to run for each selected row/datasource
-	 */
-	public void swt_runForVisibleRows(TableGroupRowRunner runner) {
-		TableRowSWT[] rows = swt_getVisibleRows();
-		if (runner.run(rows)) {
-			return;
-		}
-
-		for (int i = 0; i < rows.length; i++) {
-			runner.run(rows[i]);
-		}
-	}
-
-
-	/**
-	 * Runs a specified task for a list of table items that the table contains
-	 * @param items A list of TableItems that are part of the table view
-	 * @param runner A task
-	 */
-	public void runForTableItems(List<TableItemOrTreeItem> items, TableGroupRowRunner runner) {
-		if (table == null || table.isDisposed()) {
-			return;
-		}
-
-		final Iterator<TableItemOrTreeItem> iter = items.iterator();
-		List<TableRowCore> rows_to_use = new ArrayList<TableRowCore>(items.size());
-		while (iter.hasNext()) {
-			TableItemOrTreeItem tableItem = iter.next();
-			if (tableItem.isDisposed()) {
-				continue;
-			}
-
-			TableRowSWT row = (TableRowSWT) getRow(tableItem);
-			if (row != null && !row.isRowDisposed()) {
-				rows_to_use.add(row);
-			}
-		}
-		if (rows_to_use.size() > 0) {
-			TableRowCore[] rows = rows_to_use.toArray(new TableRowCore[rows_to_use.size()]);
-			boolean ran = runner.run(rows);
-			if (!ran) {
-				for (int i = 0; i < rows.length; i++) {
-					TableRowCore row = rows[i];
-					runner.run(row);
-				}
-			}
-		}
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableView#clipboardSelected()
-	public void clipboardSelected() {
-		String sToClipboard = "";
-		for (int j = 0; j < table.getColumnCount(); j++) {
-			if (j != 0) {
-				sToClipboard += "\t";
-			}
-			sToClipboard += table.getColumn(j).getText();
-		}
-
-		TableRowCore[] rows = getSelectedRows();
-		for (TableRowCore row : rows) {
-			sToClipboard += "\n";
-			TableColumnCore[] visibleColumns = getVisibleColumns();
-			for (int j = 0; j < visibleColumns.length; j++) {
-				TableColumnCore column = visibleColumns[j];
-				if (column.isVisible()) {
-  				if (j != 0) {
-  					sToClipboard += "\t";
-  				}
-  				TableCellCore cell = row.getTableCellCore(column.getName());
-  				if (cell != null) {
-  					sToClipboard += cell.getClipboardText();
-  				}
-				}
-			}
-		}
-		new Clipboard(getComposite().getDisplay()).setContents(new Object[] {
-			sToClipboard
-		}, new Transfer[] {
-			TextTransfer.getInstance()
-		});
-	}
-
-	/** Handle sorting of a column based on clicking the Table Header */
-	private class ColumnSelectionListener
-		implements Listener
-	{
-		/** Process a Table Header click
-		 * @param event event information
-		 */
-		public void handleEvent(final Event event) {
-			int maskNoButton = (event.stateMask & ~SWT.BUTTON_MASK);
-			if (maskNoButton != 0) {
-				return;
-			}
-			TableColumnOrTreeColumn column = TableOrTreeUtils.getTableColumnEventItem(event.widget);
-			if (column == null) {
-				return;
-			}
-			TableColumnCore tableColumnCore = (TableColumnCore) column.getData("TableColumnCore");
-			if (tableColumnCore != null) {
-				setSortColumn(tableColumnCore, true);
-				columnVisibilitiesChanged = true;
-				refreshTable(true);
-			}
-		}
-	}
-
-	/**
-	 * Handle movement of a column based on user dragging the Column Header.
-	 * SWT >= 3.1
-	 */
-	private class ColumnMoveListener
-		implements Listener
-	{
-		public void handleEvent(Event event) {
-			TableColumnOrTreeColumn column = TableOrTreeUtils.getTableColumnEventItem(event.widget);
-			if (column == null) {
-				return;
-			}
-
-			TableColumnCore tableColumnCore = (TableColumnCore) column.getData("TableColumnCore");
-			if (tableColumnCore == null) {
-				return;
-			}
-
-			TableOrTreeSWT table = column.getParent();
-
-			// Get the 'added position' of column
-			// It would have been easier if event (.start, .end) contained the old
-			// and new position..
-			TableColumnOrTreeColumn[] tableColumns = table.getColumns();
-			int iAddedPosition;
-			for (iAddedPosition = 0; iAddedPosition < tableColumns.length; iAddedPosition++) {
-				if (column.getColumn() == tableColumns[iAddedPosition].getColumn()) {
-					break;
-				}
-			}
-			if (iAddedPosition >= tableColumns.length) {
-				return;
-			}
-
-			// Find out position in the order list
-			int iColumnOrder[];
-			try {
-				iColumnOrder = table.getColumnOrder();
-			} catch (NoSuchMethodError e) {
-				// Ignore < SWT 3.1
-				return;
-			}
-			for (int i = 0; i < iColumnOrder.length; i++) {
-				if (iColumnOrder[i] == iAddedPosition) {
-					int iNewPosition = i - (bSkipFirstColumn ? 1 : 0);
-					if (tableColumnCore.getPosition() != iNewPosition) {
-						if (iNewPosition == -1) {
-							iColumnOrder[0] = 0;
-							iColumnOrder[1] = iAddedPosition;
-							table.setColumnOrder(iColumnOrder);
-							iNewPosition = 0;
-						}
-						//System.out.println("Moving " + tableColumnCore.getName() + " to Position " + i);
-						tableColumnCore.setPositionNoShift(iNewPosition);
-						tableColumnCore.saveSettings(null);
-						TableStructureEventDispatcher.getInstance(tableID).columnOrderChanged(
-								iColumnOrder);
-					}
-					break;
-				}
-			}
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see com.aelitis.azureus.ui.common.table.TableView#getRow(int, int)
-	 */
-	public TableRowCore getRow(int x, int y) {
-		int iColumn = getColumnNo(x);
-		if (iColumn < 0) {
-			return null;
-		}
-
-		TableItemOrTreeItem item = table.getItem(new Point(2, y));
-		if (item == null) {
-			return null;
-		}
-		return getRow(item);
-	}
-
-	public TableCellCore getTableCell(int x, int y) {
-		int iColumn = getColumnNo(x);
-		if (iColumn < 0) {
-			return null;
-		}
-
-		TableItemOrTreeItem item = table.getItem(new Point(2, y));
-		if (item == null) {
-			item = table.getItem(new Point(x, y));
-		}
-
-		if (item == null) {
-			return null;
-		}
-		TableRowSWT row = (TableRowSWT) getRow(item);
-
-		if (row == null || row.isRowDisposed()) {
-			return null;
-		}
-
-		TableColumnOrTreeColumn tcColumn = table.getColumn(iColumn);
-		String sCellName = (String) tcColumn.getData("Name");
-		if (sCellName == null) {
-			return null;
-		}
-
-		return row.getTableCellCore(sCellName);
-	}
-
-	public TableRowSWT getTableRow(int x, int y, boolean anyX) {
-		TableItemOrTreeItem item = table.getItem(new Point(anyX ? 2 : x, y));
-		if (item == null) {
-			return null;
-		}
-		return (TableRowSWT) getRow(item);
-	}
-
-	private int getColumnNo(int iMouseX) {
-		int iColumn = -1;
-		int itemCount = table.getItemCount();
-		if (table.getItemCount() > 0) {
-			//Using  table.getTopIndex() instead of 0, cause
-			//the first row has no bounds when it's not visible under OS X.
-			int topIndex = table.getTopIndex();
-			if (topIndex >= itemCount || topIndex < 0) {
-				topIndex = itemCount - 1;
-			}
-			TableItemOrTreeItem ti = table.getItem(topIndex);
-			if (ti.isDisposed()) {
-				return -1;
-			}
-			for (int i = bSkipFirstColumn ? 1 : 0; i < table.getColumnCount(); i++) {
-				// M8 Fixes SWT GTK Bug 51777:
-				//  "TableItem.getBounds(int) returns the wrong values when table scrolled"
-				Rectangle cellBounds = ti.getBounds(i);
-				//System.out.println("i="+i+";Mouse.x="+iMouseX+";cellbounds="+cellBounds);
-				if (iMouseX >= cellBounds.x
-						&& iMouseX < cellBounds.x + cellBounds.width
-						&& cellBounds.width > 0) {
-					iColumn = i;
-					break;
-				}
-			}
-		}
-		return iColumn;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableColumnByOffset(int)
-	 */
-	public TableColumnCore getTableColumnByOffset(int x) {
-		int iColumn = getColumnNo(x);
-		if (iColumn < 0) {
-			return null;
-		}
-
-		TableColumnOrTreeColumn column = table.getColumn(iColumn);
-		return (TableColumnCore) column.getData("TableColumnCore");
-	}
-
-	// @see org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator#generate(org.gudy.azureus2.core3.util.IndentWriter)
-	public void generate(IndentWriter writer) {
-		super.generate(writer);
-
-		if (tvTabsCommon != null) {
-			tvTabsCommon.generate(writer);
-		}
-
-		writer.println("Columns:");
-		writer.indent();
-		try {
-			TableColumnOrTreeColumn[] tableColumnsSWT = table.getColumns();
-			for (int i = 0; i < tableColumnsSWT.length; i++) {
-				final TableColumnCore tc = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore");
-				if (tc != null) {
-					writer.println(tc.getName() + ";w=" + tc.getWidth() + ";w-offset="
-							+ tableColumnsSWT[i].getData("widthOffset"));
-				}
-			}
-		} catch (Throwable t) {
-		} finally {
-			writer.exdent();
-		}
-	}
-
-	public boolean getSkipFirstColumn() {
-		return bSkipFirstColumn;
-	}
-
-	// see common.TableView
-	public void setRowDefaultHeight(int iHeight) {
-		if (ptIconSize == null) {
-			ptIconSize = new Point(1, iHeight);
-		} else {
-			ptIconSize.y = iHeight;
-		}
-		if (!Constants.isOSX) {
-			bSkipFirstColumn = true;
-		}
-	}
-
-	public int getRowDefaultHeight() {
-		if (ptIconSize == null) {
-			return 0;
-		}
-		return ptIconSize.y;
-	}
-
-	// from common.TableView
-	public void setRowDefaultIconSize(Point size) {
-		ptIconSize = size;
-		if (!Constants.isOSX) {
-			bSkipFirstColumn = true;
-		}
-	}
-
-
-	/* (non-Javadoc)
-	 * @see com.aelitis.azureus.ui.common.table.impl.TableViewImpl#selectRow(com.aelitis.azureus.ui.common.table.TableRowCore, boolean)
-	 */
-	public void setRowSelected(final TableRowCore row, boolean selected, boolean trigger) {
-		super.setRowSelected(row, selected, trigger);
-		
-		if (row instanceof TableRowSWT) {
-			((TableRowSWT) row).setWidgetSelected(selected);
-		}
-	}
-
-	protected void updateSelectedRows(TableItemOrTreeItem[] newSelectionArray, boolean trigger) {
-		List<TableRowCore> newSelectionList = new ArrayList<TableRowCore>(1);
-
-		//System.out.print("Selected Items: ");
-		for (TableItemOrTreeItem item : newSelectionArray) {
-			//System.out.print(table.indexOf(item));
-			TableRowCore row = getRow(item);
-			if (row != null && !row.isRowDisposed()) {
-				newSelectionList.add(row);
-			}// else { System.out.print("( NO ROW)"); }
-			//System.out.print(", ");
-		}
-		//System.out.println();
-		setSelectedRows(newSelectionList.toArray(new TableRowCore[0]), trigger);
-	}
-
-	@Override
-	public void uiSelectionChanged(final TableRowCore[] newlySelectedRows,
-			final TableRowCore[] deselectedRows) {
-		Utils.execSWTThread(new AERunnable() {
-			
-			@Override
-			public void runSupport() {
-				if (table.isDisposed()) {
-					return;
-				}
-				
-				for (TableRowCore row : deselectedRows) {
-					if (row instanceof TableRowImpl) {
-						TableRowImpl rowImpl = (TableRowImpl) row;
-						TableItemOrTreeItem item = rowImpl.getItem();
-						if (item != null && !item.isDisposed()) {
-							table.deselect(item);
-						}
-					}
-				}
-
-				for (TableRowCore row : newlySelectedRows) {
-					if (row instanceof TableRowImpl) {
-						TableRowImpl rowImpl = (TableRowImpl) row;
-						TableItemOrTreeItem item = rowImpl.getItem();
-						if (item != null && !item.isDisposed()) {
-							table.select(item);
-						}
-					}
-				}
-
-			}
-		});
-	}
-
-
-	@Override
-	protected boolean setSortColumn(TableColumnCore newSortColumn,
-			boolean allowOrderChange) {
-		final TableColumnCore oldSortColumn = getSortColumn();
-		
-		boolean columnChanged = super.setSortColumn(newSortColumn, allowOrderChange);
-		if (columnChanged) {
-			Utils.execSWTThread(new AERunnable() {
-				public void runSupport() {
-					TableColumnCore sortColumn = getSortColumn();
-					fixAlignment(oldSortColumn, false);
-					fixAlignment(sortColumn, true);
-				}
-			});
-		}
-		return columnChanged;
-	}
-
-	@Override
-	protected void uiChangeColumnIndicator() {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				swt_changeColumnIndicator();
-			}
-		});
-	}
-
-	private void swt_changeColumnIndicator() {
-		if (table == null || table.isDisposed()) {
-			return;
-		}
-
-		try {
-			TableColumnCore sortColumn = getSortColumn();
-			// can't use TableColumnCore.getPosition, because user may have moved
-			// columns around, messing up the SWT column indexes.  
-			// We can either use search columnsOrdered, or search table.getColumns()
-			TableColumnOrTreeColumn[] tcs = table.getColumns();
-			for (int i = 0; i < tcs.length; i++) {
-				String sName = (String) tcs[i].getData("Name");
-				if (sName != null && sortColumn != null
-						&& sName.equals(sortColumn.getName())) {
-					table.setSortDirection(sortColumn.isSortAscending() ? SWT.UP
-							: SWT.DOWN);
-					table.setSortColumn(tcs[i]);
-					return;
-				}
-			}
-
-			table.setSortColumn(null);
-		} catch (NoSuchMethodError e) {
-			// sWT < 3.2 doesn't have column indicaters
-		}
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableView#isRowVisible(com.aelitis.azureus.ui.common.table.TableRowCore)
-	public boolean isRowVisible(TableRowCore row) {
-		if (row.isInPaintItem()) {
-			return true;
-		}
-		if (visibleRows == null) {
-			return false;
-		}
-		for (TableRowCore visibleRow : visibleRows) {
-			if (row == visibleRow) {
-				if (Utils.isThisThreadSWT() && !isVisible()) {
-					return false;
-				}
-				return true;
-			}
-		}
-		return false;
-	}
-
-	@Override
-	public void visibleRowsChanged() {
-		//debug("VRC " + Debug.getCompressedStackTrace());
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				swt_visibleRowsChanged();
-			}
-
-		});
-	}
-
-	private void swt_visibleRowsChanged() {
-		final List<TableRowSWT> newlyVisibleRows = new ArrayList<TableRowSWT>();
-		final List<TableRowSWT> nowInVisibleRows;
-		synchronized (this) {
-  		List<TableItemOrTreeItem> visibleTableItems;
-  		if (isVisible()) {
-  			visibleTableItems = Utils.getVisibleTableItems(table);
-  		} else {
-  			visibleTableItems = Collections.emptyList();
-  		}
-			nowInVisibleRows = new ArrayList<TableRowSWT>(0);
-  		if (visibleRows != null) {
-  			nowInVisibleRows.addAll(Arrays.asList(visibleRows));
-  		}
-  		TableRowSWT[] rows = new TableRowSWT[visibleTableItems.size()];
-  		int pos = 0;
-  		for (TableItemOrTreeItem item : visibleTableItems) {
-  			TableRowCore row = getRow(item);
-  			if (row instanceof TableRowSWT) {
-  				rows[pos++] = (TableRowSWT) row;
-  				boolean removed = nowInVisibleRows.remove(row);
-  				if (!removed) {
-  					newlyVisibleRows.add((TableRowSWT) row);
-  				}
-  			}
-  		}
-  
-  		if (pos < rows.length) {
-  			// Some were null, shrink array
-  			TableRowSWT[] temp = new TableRowSWT[pos];
-  			System.arraycopy(rows, 0, temp, 0, pos);
-  			visibleRows = temp;
-  		} else {
-  			visibleRows = rows;
-  		}
-		}
-		
-		if (DEBUG_ROWCHANGE) {
-			System.out.println("visRowsChanged; shown=" + visibleRows.length + "; +"
-					+ newlyVisibleRows.size() + "/-" + nowInVisibleRows.size() + " via "
-					+ Debug.getCompressedStackTrace(8));
-		}
-		Utils.getOffOfSWTThread(new AERunnable() {
-			
-			public void runSupport() {
-				boolean bTableUpdate = false;
-
-				for (TableRowSWT row : newlyVisibleRows) {
-					row.refresh(true, true);
-					row.setShown(true, false);
-					if (Constants.isOSX) {
-						bTableUpdate = true;
-					}
-				}
-
-				for (TableRowSWT row : nowInVisibleRows) {
-					row.setShown(false, false);
-				}
-
-				if (bTableUpdate) {
-					Utils.execSWTThread(new AERunnable() {
-						public void runSupport() {
-							table.update();
-						}
-					});
-				}
-
-			}
-		});
-
-	}
-
-	public Image obfusticatedImage(final Image image) {
-		if (table.getItemCount() == 0 || !isVisible()) {
-			return image;
-		}
-
-		TableColumnOrTreeColumn[] tableColumnsSWT = table.getColumns();
-		for (int i = 0; i < tableColumnsSWT.length; i++) {
-			final TableColumnCore tc = (TableColumnCore) tableColumnsSWT[i].getData("TableColumnCore");
-
-			if (tc != null && tc.isObfusticated()) {
-				int iTopIndex = table.getTopIndex();
-				int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex);
-
-				int size = iBottomIndex - iTopIndex + 1;
-				if (size <= 0 || iTopIndex < 0) {
-					continue;
-				}
-
-				for (int j = iTopIndex; j <= iBottomIndex; j++) {
-					TableItemOrTreeItem rowSWT = table.getItem(j);
-					TableRowSWT row = (TableRowSWT) table.getItem(j).getData("TableRow");
-					if (row != null && !row.isRowDisposed()) {
-						TableCellSWT cell = row.getTableCellSWT(tc.getName());
-
-						String text = cell.getObfusticatedText();
-
-						if (text != null) {
-							final Rectangle columnBounds = rowSWT.getBounds(i);
-							if (columnBounds.y + columnBounds.height > clientArea.y
-									+ clientArea.height) {
-								columnBounds.height -= (columnBounds.y + columnBounds.height)
-										- (clientArea.y + clientArea.height);
-							}
-							if (columnBounds.x + columnBounds.width > clientArea.x
-									+ clientArea.width) {
-								columnBounds.width -= (columnBounds.x + columnBounds.width)
-										- (clientArea.x + clientArea.width);
-							}
-							
-							Point location = Utils.getLocationRelativeToShell(table.getComposite());
-							
-							columnBounds.x += location.x;
-							columnBounds.y += location.y;
-
-							UIDebugGenerator.obfusticateArea(image, columnBounds, text);
-						}
-					}
-				}
-
-				//UIDebugGenerator.offusticateArea(image, columnBounds);
-			}
-		}
-
-		UISWTViewCore view = tvTabsCommon == null ? null : tvTabsCommon.getActiveSubView();
-		if (view instanceof ObfusticateImage) {
-			try {
-				((ObfusticateImage) view).obfusticatedImage(image);
-			} catch (Exception e) {
-				Debug.out("Obfuscating " + view, e);
-			}
-		}
-		return image;
-	}
-
-	// from common.TableView
-	public void setEnableTabViews(boolean enableTabViews,boolean expandByDefault, String[] restrictedToIDs) {
-		bEnableTabViews = enableTabViews;
-		tabViewsExpandedByDefault = expandByDefault;
-	}
-	
-	public boolean isTabViewsEnabled() {
-		return bEnableTabViews;
-	}
-	public String[] getTabViewsRestrictedTo() {
-		return( null );
-	}
-	public boolean 
-	getTabViewsExpandedByDefault()
-	{
-		return( tabViewsExpandedByDefault );
-	}
-	
-	public void addMenuFillListener(TableViewSWTMenuFillListener l) {
-		tvSWTCommon.addMenuFillListener(l);
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableView#isDisposed()
-	public boolean isDisposed() {
-		return mainComposite == null || mainComposite.isDisposed() || table == null
-				|| table.isDisposed();
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableView#setFocus()
-	public void setFocus() {
-		if (table != null && !table.isDisposed()) {
-			table.setFocus();
-		}
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.TableViewSWT#addKeyListener(org.eclipse.swt.events.KeyListener)
-	public void addKeyListener(KeyListener listener) {
-		if (tvSWTCommon == null || isDisposed()) {
-			return;
-		}
-		tvSWTCommon.addKeyListener(listener);
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableView#removeKeyListener(org.eclipse.swt.events.KeyListener)
-	public void removeKeyListener(KeyListener listener) {
-		if (tvSWTCommon == null || isDisposed()) {
-			return;
-		}
-		tvSWTCommon.removeKeyListener(listener);
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getKeyListeners()
-	 */
-	public KeyListener[] getKeyListeners() {
-		if (tvSWTCommon == null || isDisposed()) {
-			return new KeyListener[0];
-		}
-		return tvSWTCommon.getKeyListeners();
-	}
-
-	// @see com.aelitis.azureus.ui.common.table.TableView#selectAll()
-	public void selectAll() {
-		if (table != null && !table.isDisposed()) {
-			// Used to ensure all rows have index, but I don't see a reason why.
-			// Uses a lot of CPU, so kill it :)
-			//ensureAllRowsHaveIndex();
-			table.selectAll();
-			super.selectAll();
-		}
-	}
-
-	/**
-	 * 
-	 *
-	 * @since 3.0.0.7
-	 *
-	private void ensureAllRowsHaveIndex() {
-		for (int i = 0; i < sortedRows.size(); i++) {
-			TableRowSWT row = sortedRows.get(i);
-			row.setTableItem(i);
-		}
-	}
-	*/
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#isDragging()
-	 */
-	public boolean isDragging() {
-		return isDragging;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#createDragSource(int)
-	public DragSource createDragSource(int style) {
-		final DragSource dragSource = new DragSource(table.getComposite(), style);
-		dragSource.addDragListener(new DragSourceAdapter() {
-			public void dragStart(DragSourceEvent event) {
-				table.setCursor(null);
-				isDragging = true;
-			}
-			
-			public void dragFinished(DragSourceEvent event) {
-				isDragging = false;
-			}
-		});
-		table.addDisposeListener(new DisposeListener() {
-			// @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
-			public void widgetDisposed(DisposeEvent e) {
-				if (!dragSource.isDisposed()) {
-					dragSource.dispose();
-				}
-			}
-		});
-		return dragSource;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#createDropTarget(int)
-	public DropTarget createDropTarget(int style) {
-		final DropTarget dropTarget = new DropTarget(table.getComposite(), style);
-		table.addDisposeListener(new DisposeListener() {
-			// @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
-			public void widgetDisposed(DisposeEvent e) {
-				if (!dropTarget.isDisposed()) {
-					dropTarget.dispose();
-				}
-			}
-		});
-		return dropTarget;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#indexOf(org.eclipse.swt.widgets.Widget)
-	public TableRowCore getRow(DropTargetEvent event) {
-		TableItemOrTreeItem ti = TableOrTreeUtils.getEventItem(event.item);
-		if (ti != null) {
-			return (TableRowCore) ti.getData("TableRow");
-		}
-		return null;
-	}
-
-	/**
-	 * @return
-	 */
-	protected TableViewSWTPanelCreator getMainPanelCreator() {
-		return mainPanelCreator;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.TableViewSWT#setMainPanelCreator(org.gudy.azureus2.ui.swt.views.TableViewMainPanelCreator)
-	public void setMainPanelCreator(TableViewSWTPanelCreator mainPanelCreator) {
-		this.mainPanelCreator = mainPanelCreator;
-	}
-
-	public TableCellCore getTableCellWithCursor() {
-		Point pt = table.getDisplay().getCursorLocation();
-		pt = table.toControl(pt);
-		return getTableCell(pt.x, pt.y);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableRowWithCursor()
-	public TableRowCore getTableRowWithCursor() {
-		Point pt = table.getDisplay().getCursorLocation();
-		pt = table.toControl(pt);
-		return getTableRow(pt.x, pt.y, true);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableCellMouseOffset()
-	public Point getTableCellMouseOffset(TableCellSWT tableCell) {
-		if (tableCell == null) {
-			return null;
-		}
-		Point pt = table.getDisplay().getCursorLocation();
-		pt = table.toControl(pt);
-
-		Rectangle bounds = tableCell.getBounds();
-		int x = pt.x - bounds.x;
-		if (x < 0 || x > bounds.width) {
-			return null;
-		}
-		int y = pt.y - bounds.y;
-		if (y < 0 || y > bounds.height) {
-			return null;
-		}
-		return new Point(x, y);
-	}
-
-
-	/** Note: Callers need to be on SWT Thread */
-	public boolean isVisible() {
-		if (!Utils.isThisThreadSWT()) {
-			return isVisible;
-		}
-		boolean wasVisible = isVisible;
-		isVisible = table != null && !table.isDisposed() && table.isVisible() && !shell.getMinimized();
-		if (isVisible != wasVisible) {
-			visibleRowsChanged();
-			UISWTViewCore view = tvTabsCommon == null ? null : tvTabsCommon.getActiveSubView();
-			if (isVisible) {
-				loopFactor = 0;
-
-				if (view != null) {
-					view.triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
-				}
-			} else {
-				if (view != null) {
-					view.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
-				}
-			}
-		}
-		return isVisible;
-	}
-
-	public void showRow(final TableRowCore row) {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				if (isDisposed()) {
-    			return;
-    		}
-				int index = row.getIndex();
-				if (index >= 0 && index < table.getItemCount()) {
-					table.showItem(table.getItem(index));
-				}
-			}
-		});
-	}
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#openFilterDialog()
-	 */
-	public 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);
-	}
-
-	public void setFilterText(String s) {
-		if (tvSWTCommon != null) {
-			tvSWTCommon.setFilterText(s);
-		}
-	}
-	
-	public TableViewSWTFilter<?> getSWTFilter() {
-		return (TableViewSWTFilter<?>) filter;
-	}
-
-	public boolean
-	isFiltered(
-		DATASOURCETYPE	ds )
-	{
-		if ( filter == null ){
-			return( true );
-		}
-		
-		return( filter.checker.filterCheck( ds, filter.text, filter.regex ));
-	}
-	
-	// @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#enableFilterCheck(org.eclipse.swt.widgets.Text, org.gudy.azureus2.ui.swt.views.table.TableViewFilterCheck)
-	public void enableFilterCheck(Text txtFilter,
-			TableViewFilterCheck<DATASOURCETYPE> filterCheck) {
-		TableViewSWTFilter<?> filter = getSWTFilter();
-		if (filter != null) {
-			if (filter.widget != null && !filter.widget.isDisposed()) {
-				filter.widget.removeKeyListener(tvSWTCommon);
-				filter.widget.removeModifyListener(filter.widgetModifyListener);
-			}
-		} else{
-			this.filter = filter = new TableViewSWTFilter<DATASOURCETYPE>();
-		}
-		filter.widget = txtFilter;
-		if (txtFilter != null) {
-			txtFilter.setMessage("Filter");
-  		txtFilter.addKeyListener(tvSWTCommon);
-  
-  		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 void disableFilterCheck()
-	{
-		TableViewSWTFilter<?> filter = getSWTFilter();
-		if ( filter == null ){
-			return;
-		}
-		
-		if (filter.widget != null && !filter.widget.isDisposed()) {
-			filter.widget.removeKeyListener(tvSWTCommon);
-			filter.widget.removeModifyListener(filter.widgetModifyListener);
-		}
-		filter = null;
-	}
-	
-	public boolean enableSizeSlider(Composite composite, final int min, final int max) {
-		try {
-			if (sliderArea != null && !sliderArea.isDisposed()) {
-				sliderArea.dispose();
-			}
-			Class<?> claTable = Class.forName("org.eclipse.swt.widgets."
-					+ (useTree ? "Tree" : "Table"));
-			final Method method = claTable.getDeclaredMethod("setItemHeight", new Class<?>[] {
-				int.class
-			});
-			method.setAccessible(true);
-
-			composite.setLayout(new FormLayout());
-			sliderArea = new Label(composite, SWT.NONE);
-			((Label)sliderArea).setImage(ImageLoader.getInstance().getImage("zoom"));
-			sliderArea.addListener(SWT.MouseUp, new Listener() {
-				public void handleEvent(Event event) {
-					final Shell shell = new Shell(sliderArea.getShell(), SWT.BORDER);
-					Listener l = new Listener() {
-						public void handleEvent(Event event) {
-							if (event.type == SWT.MouseExit) {
-								Control curControl = event.display.getCursorControl();
-								Point curPos = event.display.getCursorLocation();
-								Point curPosRelShell = shell.toControl(curPos);
-								Rectangle bounds = shell.getBounds();
-								bounds.x = bounds.y = 0;
-								if (!bounds.contains(curPosRelShell)) {
-									shell.dispose();
-									return;
-								}
-								if (curControl != null
-										&& (curControl == shell || curControl.getParent() == shell)) {
-									return;
-								}
-							}
-							shell.dispose();
-						}
-					};
-					shell.setBackgroundMode(SWT.INHERIT_FORCE);
-					shell.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
-					shell.addListener(SWT.MouseExit, l);
-					shell.addListener(SWT.Deactivate, l);
-					FillLayout fillLayout = new FillLayout();
-					fillLayout.marginHeight = 4;
-					shell.setLayout(fillLayout);
-					final Scale slider = new Scale(shell, SWT.VERTICAL);
-					slider.addListener(SWT.MouseExit, l);
-					slider.addListener(SWT.Deactivate, l);
-					slider.setMinimum(min);
-					slider.setMaximum(max);
-					slider.setSelection(getRowDefaultHeight());
-					try {
-						method.invoke(table.getComposite(), new Object[] { slider.getSelection() } );
-					} catch (Throwable e1) {
-					}
-					slider.addSelectionListener(new SelectionListener() {
-						public void widgetSelected(SelectionEvent e) {
-							setRowDefaultHeight(slider.getSelection());
-							try {
-								method.invoke(table.getComposite(), new Object[] { slider.getSelection() } );
-							} catch (Throwable e1) {
-								e1.printStackTrace();
-							}
-							tableInvalidate();
-						}
-						
-						public void widgetDefaultSelected(SelectionEvent e) {
-						}
-					});
-					Point pt = sliderArea.toDisplay(event.x - 2, event.y - 5);
-					int width = Constants.isOSX ? 20 : 50;
-					shell.setBounds(pt.x - (width / 2), pt.y, width, 120);
-					shell.open();
-				}
-			});
-			
-			sliderArea.setLayoutData(Utils.getFilledFormData());
-			composite.layout();
-		} catch (Throwable t) {
-			return false;
-		}
-		return true;
-	}
-	
-	public void disableSizeSlider() {
-		Utils.disposeSWTObjects(new Object[] { sliderArea });
-	}
-	
-	public void setEnabled(final boolean enable) {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				if (!isDisposed()) {
-					table.setEnabled(enable);
-					/*
-					if (enable) {
-						Image oldImage = table.getBackgroundImage();
-						table.setBackgroundImage(null);
-						Utils.disposeSWTObjects(new Object[] { oldImage } );
-					} else {
-						final Image image = new Image(table.getDisplay(), 50, 50);
-						
-						GC gc = new GC(image);
-						gc.setBackground(ColorCache.getColor(gc.getDevice(), 0xee, 0xee, 0xee));
-						gc.fillRectangle(0, 0, 50, 50);
-						gc.dispose();
-						table.addDisposeListener(new DisposeListener() {
-							public void widgetDisposed(DisposeEvent e) {
-								Utils.disposeSWTObjects(new Object[] { image } );
-							}
-						});
-						
-						table.setBackgroundImage(image);
-					}
-					*/
-				}
-			}
-		});
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#addRowMouseListener(org.gudy.azureus2.plugins.ui.tables.TableRowMouseListener)
-	 */
-	public void addRowMouseListener(TableRowMouseListener listener) {
-		if (tvSWTCommon != null) {
-			tvSWTCommon.addRowMouseListener(listener);
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#removeRowMouseListener(org.gudy.azureus2.plugins.ui.tables.TableRowMouseListener)
-	 */
-	public void removeRowMouseListener(TableRowMouseListener listener) {
-		if (tvSWTCommon != null) {
-			tvSWTCommon.removeRowMouseListener(listener);
-		}
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#invokeRowMouseListener(org.gudy.azureus2.plugins.ui.tables.TableRowMouseEvent)
-	 */
-	public void invokeRowMouseListener(TableRowMouseEvent event) {
-		if (tvSWTCommon != null) {
-			tvSWTCommon.invokeRowMouseListener(event);
-		}
-	}
-
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#addRowPaintListener(org.gudy.azureus2.ui.swt.views.table.TableRowSWTPaintListener)
-	 */
-	public void addRowPaintListener(TableRowSWTPaintListener listener) {
-		if (tvSWTCommon != null) {
-			tvSWTCommon.addRowPaintListener(listener);
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#removeRowPaintListener(org.gudy.azureus2.ui.swt.views.table.TableRowSWTPaintListener)
-	 */
-	public void removeRowPaintListener(TableRowSWTPaintListener listener) {
-		if (tvSWTCommon != null) {
-			tvSWTCommon.removeRowPaintListener(listener);
-		}
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#invokePaintListeners(org.eclipse.swt.graphics.GC, com.aelitis.azureus.ui.common.table.TableRowCore, com.aelitis.azureus.ui.common.table.TableColumnCore, org.eclipse.swt.graphics.Rectangle)
-	 */
-	public void invokePaintListeners(GC gc, TableRowCore row,
-			TableColumnCore column, Rectangle cellArea) {
-		if (tvSWTCommon != null) {
-			tvSWTCommon.invokePaintListeners(gc, row, column, cellArea);
-		}
-	}
-
-	public boolean canHaveSubItems() {
-		return useTree;
-	}
-		
-	public void setParentDataSource(Object newDataSource) {
-		super.setParentDataSource(newDataSource);
-
-		triggerTabViewsDataSourceChanged(true);
-	}
-	
-	public void packColumns() {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				if (table != null && !table.isDisposed()) {
-					table.pack(true);
-				}
-			}
-		});
-	}
-	
-	public int getMaxItemShown() {
-		return maxItemShown;
-	}
-	
-	public void setMaxItemShown(int i) {
-		maxItemShown  = i;
-	}
-	
-	public int indexOf(TableRowCore row) {
-		if (!Utils.isThisThreadSWT()) {
-			return super.indexOf(row);
-		}
-		int i = ((TableRowImpl) row).getRealIndex();
-		if (i == -1) {
-			i = super.indexOf(row);
-			if (i >= 0) {
-				row.setTableItem(i);
-			}
-		}
-		return i;
-	}
-
-
-	@Override
-	public TableRowCore createNewRow(Object ds) {
-		TableRowImpl row = new TableRowImpl(this, table, getVisibleColumns(), ds,
-				bSkipFirstColumn);
-		return row;
-	}
-
-	private int uiGetTopIndex() {
-		return ((Number) Utils.execSWTThreadWithObject("uiGetTopIndex", new AERunnableObject() {
-			public Object runSupport() {
-				 return table.getTopIndex();
-			}
-		}, 500)).intValue();
-	}
-	
-	@Override
-	public int uiGuessMaxVisibleRows() {
-		return 0;
-	}
-	
-	private int uiGetBottomIndex(final int iTopIndex) {
-		return ((Number) Utils.execSWTThreadWithObject("uiGetBottomIndex", new AERunnableObject() {
-			public Object runSupport() {
-				return Utils.getTableBottomIndex(table, iTopIndex);
-			}
-		}, 500)).intValue();
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getRowSWT(java.lang.Object)
-	public TableRowSWT getRowSWT(DATASOURCETYPE dataSource) {
-		return (TableRowSWT) getRow(dataSource);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#enableFilterCheck(org.eclipse.swt.widgets.Text, com.aelitis.azureus.ui.common.table.TableViewFilterCheck)
-	 */
-	public void enableFilterCheck(
-			Text txtFilter,
-			org.gudy.azureus2.ui.swt.views.table.TableViewFilterCheck<DATASOURCETYPE> filterCheck) {
-	}
-
-	@Override
-	public void getOffUIThread(AERunnable runnable) {
-		Utils.getOffOfSWTThread(runnable);
-	}
-	
-	@Override
-	protected void _sortColumn(final boolean bForceDataRefresh, final boolean bFillGapsOnly,
-			final boolean bFollowSelected) {
-		if (Utils.isThisThreadSWT()) {
-			super._sortColumn(bForceDataRefresh, bFillGapsOnly, bFollowSelected);
-			return;
-		}
-		Utils.execSWTThread(new AERunnable() {
-			
-			@Override
-			public void runSupport() {
-				_sortColumn(bForceDataRefresh, bFillGapsOnly, bFollowSelected);
-			}
-		});
-	}
-	
-	public boolean isSingleSelection() {
-		return (iTableStyle & SWT.MULTI) > 0;
-	}
-	
-	public void expandColumns() {
-		TableColumnOrTreeColumn[] 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);
-			}
-		}
-	}
-	
-	public void showColumnEditor() {
-		if (tvSWTCommon != null) {
-			tvSWTCommon.showColumnEditor();
-		}
-	}
-	
-	public TableViewSWT_TabsCommon getTabsCommon() {
-		return( tvTabsCommon );
-	}
-}
\ No newline at end of file
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_Common.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_Common.java
index e1b5d3b..5c8051f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_Common.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_Common.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table.impl;
 
 import java.util.ArrayList;
@@ -12,10 +30,11 @@ import org.eclipse.swt.dnd.Transfer;
 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.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
 import org.gudy.azureus2.plugins.ui.tables.*;
-import org.gudy.azureus2.pluginsimpl.local.ui.tables.TableContextMenuItemImpl;
+import org.gudy.azureus2.pluginsimpl.local.ui.menus.MenuItemImpl;
 import org.gudy.azureus2.ui.common.util.MenuItemManager;
 import org.gudy.azureus2.ui.swt.MenuBuildUtils;
 import org.gudy.azureus2.ui.swt.Messages;
@@ -158,11 +177,6 @@ public class TableViewSWT_Common
 		tv.editCell(null, -1); // clear out current cell editor
 
 		if (cell != null && tc != null) {
-			if (e.button == 2 && e.stateMask == SWT.CONTROL) {
-				((TableCellImpl) cell).bDebug = !((TableCellImpl) cell).bDebug;
-				System.out.println("Set debug for " + cell + " to "
-						+ ((TableCellImpl) cell).bDebug);
-			}
 			TableCellMouseEvent event = createMouseEvent(cell, e,
 					TableCellMouseEvent.EVENT_MOUSEDOWN, false);
 			if (event != null) {
@@ -806,21 +820,18 @@ public class TableViewSWT_Common
 		
 		String tableID = tv.getTableID();
 		String sMenuID = hasLevel1 ? tableID : TableManager.TABLE_TORRENT_FILES;
-		
-		// Add Plugin Context menus..
-		boolean enable_items = selectedRows.length > 0;
-
-		TableContextMenuItem[] items = TableContextMenuManager.getInstance().getAllAsArray(
-				sMenuID);
 
 		// We'll add download-context specific menu items - if the table is download specific.
 		// We need a better way to determine this...
+		boolean isDownloadContext;
 		org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items = null;
-		if ("MySeeders".equals(tableID) || "MyTorrents".equals(tableID)) {
+		if (Download.class.isAssignableFrom( tv.getDataSourceType()) && !hasLevel2) {
 			menu_items = MenuItemManager.getInstance().getAllAsArray(
-					"download_context");
+					MenuManager.MENU_DOWNLOAD_CONTEXT);
+			isDownloadContext = true;
 		} else {
 			menu_items = MenuItemManager.getInstance().getAllAsArray((String) null);
+			isDownloadContext = false;
 		}
 		
 		if (columnName == null) {
@@ -871,26 +882,40 @@ public class TableViewSWT_Common
  		});
 		}
 		
+		
+		// Add Plugin Context menus..
+		boolean enable_items = selectedRows.length > 0;
+
+		TableContextMenuItem[] items = TableContextMenuManager.getInstance().getAllAsArray(
+				sMenuID);
+
 		if (items.length > 0 || menu_items.length > 0) {
 			new org.eclipse.swt.widgets.MenuItem(menu, SWT.SEPARATOR);
 
 			// Add download context menu items.
 			if (menu_items != null) {
 				// getSelectedDataSources(false) returns us plugin items.
-				MenuBuildUtils.addPluginMenuItems(tv.getComposite(), menu_items, menu,
-						true, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl(
-								tv.getSelectedDataSources(false)));
+				Object[] target;
+				if (isDownloadContext) {
+					Object[] dataSources = tv.getSelectedDataSources(false);
+					target = new Download[dataSources.length];
+					System.arraycopy(dataSources, 0, target, 0, target.length);
+				} else {
+					target = selectedRows;
+				}
+				MenuBuildUtils.addPluginMenuItems(menu_items, menu, true, true,
+						new MenuBuildUtils.MenuItemPluginMenuControllerImpl(target));
 			}
 
 			if (items.length > 0) {
-				MenuBuildUtils.addPluginMenuItems(tv.getComposite(), items, menu, true,
-						enable_items, new MenuBuildUtils.PluginMenuController() {
+				MenuBuildUtils.addPluginMenuItems(items, menu, true, enable_items,
+						new MenuBuildUtils.PluginMenuController() {
 							public Listener makeSelectionListener(
 									final org.gudy.azureus2.plugins.ui.menus.MenuItem plugin_menu_item) {
 								return new TableSelectedRowsListener(tv, false) {
 									public boolean run(TableRowCore[] rows) {
 										if (rows.length != 0) {
-											((TableContextMenuItemImpl) plugin_menu_item).invokeListenersMulti(rows);
+											((MenuItemImpl) plugin_menu_item).invokeListenersMulti(rows);
 										}
 										return true;
 									}
@@ -899,35 +924,53 @@ public class TableViewSWT_Common
 
 							public void notifyFillListeners(
 									org.gudy.azureus2.plugins.ui.menus.MenuItem menu_item) {
-								((TableContextMenuItemImpl) menu_item).invokeMenuWillBeShownListeners(tv.getSelectedRows());
+								((MenuItemImpl)menu_item).invokeMenuWillBeShownListeners(tv.getSelectedRows());
+							}
+							
+							// @see org.gudy.azureus2.ui.swt.MenuBuildUtils.PluginMenuController#buildSubmenu(org.gudy.azureus2.plugins.ui.menus.MenuItem)
+							public void buildSubmenu(
+									org.gudy.azureus2.plugins.ui.menus.MenuItem parent) {
+								org.gudy.azureus2.plugins.ui.menus.MenuBuilder submenuBuilder = ((MenuItemImpl) parent).getSubmenuBuilder();
+								if (submenuBuilder != null) {
+									try {
+										parent.removeAllChildItems();
+										submenuBuilder.buildSubmenu(parent, tv.getSelectedRows());
+									} catch (Throwable t) {
+										Debug.out(t);
+									}
+								}
 							}
 						});
 			}
 		}
 		
 		if (hasLevel1) {
-		// Add Plugin Context menus..
-		if (column != null) {
- 		TableContextMenuItem[] columnItems = column.getContextMenuItems(TableColumnCore.MENU_STYLE_COLUMN_DATA);
- 		if (columnItems.length > 0) {
- 			new MenuItem(menu, SWT.SEPARATOR);
- 
- 			MenuBuildUtils.addPluginMenuItems(tv.getComposite(), columnItems, menu,
- 					true, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl(
- 							tv.getSelectedDataSources(true)));
- 
- 		}
-		}
+			// Add Plugin Context menus..
+			if (column != null) {
+				TableContextMenuItem[] columnItems = column.getContextMenuItems(TableColumnCore.MENU_STYLE_COLUMN_DATA);
+				if (columnItems.length > 0) {
+					new MenuItem(menu, SWT.SEPARATOR);
+
+					MenuBuildUtils.addPluginMenuItems(
+							columnItems,
+							menu,
+							true,
+							true,
+							new MenuBuildUtils.MenuItemPluginMenuControllerImpl(
+									tv.getSelectedDataSources(true)));
 
-		if (tv.getSWTFilter() != 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) {
- 				tv.openFilterDialog();
- 			}
- 		});
-		}
+				}
+			}
+
+			if (tv.getSWTFilter() != 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) {
+						tv.openFilterDialog();
+					}
+				});
+			}
 		}
 	}
 
@@ -950,6 +993,8 @@ public class TableViewSWT_Common
 	public void fillColumnMenu(final Menu menu, final TableColumnCore column,
 			boolean isBlankArea) {
 		String tableID = tv.getTableID();
+		int	hiddenColumnCount = 0;
+		
 		if (!isBlankArea) {
 			TableColumnManager tcm = TableColumnManager.getInstance();
 			TableColumnCore[] allTableColumns = tcm.getAllTableColumnCoreAsArray(
@@ -964,6 +1009,7 @@ public class TableViewSWT_Common
 					TableColumnInfo columnInfo = tcm.getColumnInfo(
 							tv.getDataSourceType(), tableID, tc.getName());
 					if (columnInfo.getProficiency() != TableColumnInfo.PROFICIENCY_BEGINNER) {
+						hiddenColumnCount++;
 						continue;
 					}
 				}
@@ -987,6 +1033,19 @@ public class TableViewSWT_Common
 			}
 		}
 
+		if ( hiddenColumnCount > 0 ){
+			
+			MenuItem itemMoreHidden = new MenuItem(menu, SWT.PUSH);
+			Messages.setLanguageText(itemMoreHidden,
+					"MyTorrentsView.menu.moreColHidden", new String[]{ String.valueOf( hiddenColumnCount )});
+	
+			itemMoreHidden.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event e) {
+					showColumnEditor();
+				}
+			});
+		}
+		
 		if (menu.getItemCount() > 0) {
 			new MenuItem(menu, SWT.SEPARATOR);
 		}
@@ -1032,24 +1091,7 @@ public class TableViewSWT_Common
 			public void handleEvent(Event e) {
 				String tableID = tv.getTableID();
 				TableColumnManager tcm = TableColumnManager.getInstance();
-				String[] defaultColumnNames = tcm.getDefaultColumnNames(tableID);
-				if (defaultColumnNames != null) {
-					TableColumnCore[] tableColumns = tv.getVisibleColumns();
-					for (TableColumnCore column : tableColumns) {
-						column.setVisible(false);
-					}
-					int i = 0;
-					for (String name : defaultColumnNames) {
-						TableColumnCore column = tcm.getTableColumnCore(tableID, name);
-						if (column != null) {
-							column.reset();
-							column.setVisible(true);
-							column.setPositionNoShift(i++);
-						}
-					}
-					tcm.saveTableColumns(tv.getDataSourceType(), tableID);
-					TableStructureEventDispatcher.getInstance(tableID).tableStructureChanged(true, tv.getDataSourceType());
-				}
+				tcm.resetColumns(tv.getDataSourceType(), tableID);
 			}
 		});
 
@@ -1097,8 +1139,8 @@ public class TableViewSWT_Common
 		if (items.length > 0) {
 			new MenuItem(menu, SWT.SEPARATOR);
 
-			MenuBuildUtils.addPluginMenuItems(tv.getComposite(), items, menu,
-					true, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl(
+			MenuBuildUtils.addPluginMenuItems(items, menu, true, true, 
+					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(
 							tv.getSelectedDataSources(true)));
 
 		}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_EraseItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_EraseItem.java
deleted file mode 100644
index c4bd73d..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_EraseItem.java
+++ /dev/null
@@ -1,243 +0,0 @@
-package org.gudy.azureus2.ui.swt.views.table.impl;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.config.ParameterListener;
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-import org.gudy.azureus2.ui.swt.mainwindow.HSLColor;
-import org.gudy.azureus2.ui.swt.views.table.TableColumnOrTreeColumn;
-import org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem;
-import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;
-
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-
-public class TableViewSWT_EraseItem
-	implements Listener
-{
-	final static public Color[] alternatingColors = new Color[] {
-		null,
-		Colors.colorAltRow
-	};
-
-	static{
-		Colors.getInstance().addColorsChangedListener(
-			new ParameterListener() {
-				
-				public void parameterChanged(String parameterName) {
-					alternatingColors[1] = Colors.colorAltRow;
-				}
-			});
-	}
-	
-	private final TableOrTreeSWT table;
-	
-	private TableViewSWTImpl<?> tv;
-	
-	private boolean drawExtended;
-	
-	private boolean first = true;
-
-	private static Color colorLine;
-	
-	public TableViewSWT_EraseItem(TableViewSWTImpl<?> _tv, TableOrTreeSWT table) {
-		this.table = table;
-		this.tv = _tv;
-		COConfigurationManager.addAndFireParameterListener("Table.extendedErase",
-				new ParameterListener() {
-					public void parameterChanged(String parameterName) {
-						Utils.execSWTThread(new AERunnable() {
-							public void runSupport() {
-								drawExtended = COConfigurationManager.getBooleanParameter("Table.extendedErase");
-								if (!first) {
-									Rectangle bounds = tv.getTableOrTreeSWT().getBounds();
-									tv.getTableOrTreeSWT().redraw(bounds.x, bounds.y, bounds.width, bounds.height, true);
-								}
-								first = false;
-							}
-						});
-					}
-				});
-
-		if (colorLine == null) {
-  		colorLine = tv.getComposite().getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
-  		HSLColor hslColor = new HSLColor();
-  		hslColor.initHSLbyRGB(colorLine.getRed(), colorLine.getGreen(),
-  				colorLine.getBlue());
-  
-  		int lum = hslColor.getLuminence();
-  		if (lum > 127)
-  			lum -= 25;
-  		else
-  			lum += 40;
-  		hslColor.setLuminence(lum);
-  		
-  		colorLine = new Color(tv.getComposite().getDisplay(), hslColor.getRed(), hslColor.getGreen(), hslColor.getBlue());
-		}
-
-		/* Background image badly slows down tree drawing
-		int itemHeight = table.getItemHeight() + 1;
-		int height = 1920;
-		Image image = new Image(table.getComposite().getDisplay(), 10, height);
-		GC gc = new GC(image);
-		int y = table.getHeaderHeight();
-		while (y < height) {
-			gc.setBackground(table.getBackground());
-			gc.fillRectangle(0, y, 10, itemHeight);
-			gc.setBackground(alternatingColors[1]);
-			gc.fillRectangle(0, y + itemHeight, 10, itemHeight);
-			y += itemHeight * 2;
-		}
-		gc.dispose();
-		table.setBackgroundImage(image);
-		*/
-	}
-	
-	public void handleEvent(Event event) {
-		if (event.type == SWT.EraseItem) {
-			TableItemOrTreeItem item = TableOrTreeUtils.getEventItem(event.item);
-			eraseItem(event, event.gc, item, event.index, drawExtended, item.getBounds(event.index), tv, false);
-		} else if (drawExtended) {
-			paint(event);
-		}
-	}
-
-	private void paint(Event event) {
-		//System.out.println("paint " + event.getBounds() + ";" + table.getColumnCount());
-		int numItems = table.getItemCount();
-		int rowHeight = table.getItemHeight();
-		int height = rowHeight * numItems;
-		int rowAreaHeight = tv.clientArea.height + tv.clientArea.y;
-
-		int blankHeight = rowAreaHeight - height;
-		if (blankHeight > 0) {
-			int startY;
-			if (numItems > 0) {
-				TableItemOrTreeItem lastItem = table.getItem(numItems - 1);
-					// dunno how, but I have a stacktrace with an NPE caused by lastItem being null (even though numItems > 0 ...)
-				if ( lastItem != null ){
-					Rectangle lastItemBounds;
-					if (lastItem.getExpanded()) {
-	  				TableItemOrTreeItem[] subItems = lastItem.getItems();
-	  				lastItemBounds = subItems == null || subItems.length == 0
-	  						? lastItem.getBounds() : subItems[subItems.length - 1].getBounds();
-					} else {
-						lastItemBounds = lastItem.getBounds();
-					}
-					startY = lastItemBounds.y + lastItemBounds.height;
-				}else{
-					startY = 0;
-				}
-			} else {
-				startY = 0;
-			}
-			//if (event.width == tv.clientArea.width && event.height < blankHeight) {
-			//	System.out.println("MOO");
-			//	table.redraw(tv.clientArea.x, startY, tv.clientArea.width, blankHeight, false);
-			//	return;
-			//}
-			//System.out.println("numItems=" + numItems + ";" + startY);
-			GC gc = event.gc;
-			gc.setClipping((Rectangle) null);
-			for (int i = 0; i < blankHeight / rowHeight; i++) {
-				int curY = (startY + (i * rowHeight));
-				int pos = (i + numItems) % 2;
-				//System.out.println(i + "==" + pos + " for " + (startY + (i * rowHeight)));
-				Color color = i <= -1 ? ColorCache.getRandomColor() : alternatingColors[pos];
-				if (color == null) {
-					//color = event.display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
-					continue;
-				}
-				gc.setBackground(color);
-				gc.fillRectangle(tv.clientArea.x, startY + (i * rowHeight),
-						tv.clientArea.width, rowHeight);
-			}
-
-			// Vertical lines between columns
-			if (TableViewSWTImpl.DRAW_VERTICAL_LINES) {
-				TableColumnOrTreeColumn[] columns = table.getColumns();
-				int pos = 0;
-				//gc.setForeground(ColorCache.getColor(event.display, 245, 245, 245));
-
-				gc.setForeground(Colors.black);
-				gc.setAdvanced(true);
-				gc.setAlpha(10);
-				for (TableColumnOrTreeColumn tc : columns) {
-					gc.drawLine(pos - 1, startY, pos - 1, startY + blankHeight);
-					pos += tc.getWidth();
-				}
-				gc.drawLine(pos - 1, startY, pos - 1, startY + blankHeight);
-			}
-		}
-	}
-
-	public static void eraseItem(Event event, GC gc, TableItemOrTreeItem item,
-			int columnNo, boolean drawExtended, Rectangle bounds, TableViewSWTImpl<?> tv, boolean alwaysDrawBG) {
-
-		TableOrTreeSWT table = tv.getTableOrTreeSWT();
-
-		if (event == null || (event.detail & (SWT.HOT | SWT.SELECTED | SWT.FOCUSED)) == 0) {
-
-			int pos;
-			TableItemOrTreeItem parentItem = item.getParentItem();
-			if (parentItem != null) {
-				pos = parentItem.indexOf(item) + ((table.indexOf(parentItem) + 1) % 2);
-			} else {
-				pos = table.indexOf(item);
-			}
-			Color color = alternatingColors[pos % 2];
-			if (color != null) {
-				gc.setBackground(color);
-				if (parentItem != null) {
-					gc.setAlpha(128);
-				}
-			}
-			Rectangle drawBounds = bounds;
-			if (TableViewSWTImpl.DRAW_FULL_ROW && drawExtended
-					&& columnNo == table.getColumnCount() - 1) {
-				tv.swt_calculateClientArea();
-				drawBounds = new Rectangle(bounds.x, bounds.y, tv.clientArea.x
-						+ tv.clientArea.width - bounds.x, bounds.height);
-				gc.setClipping(drawBounds);
-				//System.out.println(bounds.width);
-			}
-			if (alwaysDrawBG || color != null) {
-				if (color == null) {
-					gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
-				}
-				gc.fillRectangle(drawBounds);
-				if (event != null) {
-					event.detail &= ~SWT.BACKGROUND;
-				}
-			}
-		}
-		
-		if (event != null && (event.detail & SWT.SELECTED) > 0 && !table.isFocusControl()) {
-			gc.setBackground(Colors.blues[3]);
-			gc.fillRectangle(bounds);
-			if (event != null) {
-				event.detail &= ~SWT.BACKGROUND;
-			}
-		}
-
-		// Vertical lines between columns
-		if (TableViewSWTImpl.DRAW_VERTICAL_LINES && drawExtended && colorLine != null) {
-			if (item != null
-					&& (bounds.width == item.getParent().getColumn(columnNo).getWidth())
-					&& bounds.width > 0) {
-				Color fg = gc.getForeground();
-				gc.setForeground(colorLine);
-				// needed because windows shifts the area over, dragging our old line
-				// around.  Clear clipping so we can erase it
-				gc.setClipping((Rectangle) null);
-				gc.drawLine(bounds.x + bounds.width - 1, bounds.y - 1, bounds.x
-						+ bounds.width - 1, bounds.y + bounds.height);
-				gc.setForeground(fg);
-			}
-		}
-	}
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_PaintItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_PaintItem.java
deleted file mode 100644
index dfec56e..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_PaintItem.java
+++ /dev/null
@@ -1,469 +0,0 @@
-package org.gudy.azureus2.ui.swt.views.table.impl;
-
-import java.util.Random;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-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.tables.TableColumn;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.components.BufferedGraphicTableItem;
-import org.gudy.azureus2.ui.swt.components.BufferedTableItem;
-import org.gudy.azureus2.ui.swt.components.InPaintInfo;
-import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
-import org.gudy.azureus2.ui.swt.views.table.*;
-import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnSWTUtils;
-
-import com.aelitis.azureus.ui.common.table.TableColumnCore;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
-import com.aelitis.azureus.ui.swt.utils.FontUtils;
-
-public class TableViewSWT_PaintItem
-	implements Listener
-{
-	Widget lastItem;
-
-	int lastRowIndex = -1;
-
-	private final TableOrTreeSWT table;
-
-	private TableViewSWTImpl<?> tv;
-
-	private boolean bSkipFirstColumn;
-
-	public TableViewSWT_PaintItem(TableViewSWTImpl<?> tv, TableOrTreeSWT table) {
-		this.table = table;
-		this.tv = tv;
-	}
-
-	private int[] getColumnRange(TableItemOrTreeItem ti, int iMouseX, int width) {
-		int[] columnRange = {
-			-1,
-			-1
-		};
-		int numColumns = table.getColumnCount();
-		if (numColumns <= 0) {
-			return columnRange;
-		}
-		for (int i = bSkipFirstColumn ? 1 : 0; i < numColumns; i++) {
-			Rectangle cellBounds = ti.getBounds(i);
-			if (iMouseX >= cellBounds.x && iMouseX < cellBounds.x + cellBounds.width
-					&& cellBounds.width > 0) {
-				columnRange[0] = i;
-				break;
-			}
-		}
-
-		if (columnRange[0] == -1) {
-			return columnRange;
-		}
-
-		if (columnRange[0] + 1 == numColumns) {
-			columnRange[1] = columnRange[0];
-		} else {
-
-			int end = iMouseX + width;
-			for (int i = columnRange[0] + 1; i < numColumns; i++) {
-				Rectangle cellBounds = ti.getBounds(i);
-				//System.out.println(cellBounds + ";" + end);
-				if (cellBounds.x > end && cellBounds.width > 0) {
-					columnRange[1] = i - 1;
-					break;
-				}
-			}
-			if (columnRange[1] == -1) {
-				columnRange[1] = numColumns - 1;
-			}
-		}
-
-		return columnRange;
-	}
-
-	public void handleEvent(Event event) {
-
-		if (event.gc.getClipping().isEmpty()) {
-			return;
-		}
-
-		if (!table.isEnabled()) {
-			// added disable affect
-			event.gc.setAlpha(100);
-		}
-
-		if (event.type == SWT.Paint) {
-			int numPainted = 0;
-			//Color fg = event.gc.getForeground();
-			//Color bg = event.gc.getBackground();
-			Region r = new Region();
-			event.gc.getClipping(r);
-			//System.out.println(r.contains(event.x, event.y));
-			//event.gc.setForeground(ColorCache.getRandomColor());
-			//event.gc.drawRectangle(event.x, event.y, event.width - 1, event.height - 1);
-			//event.gc.setForeground(fg);
-			// paint only gets bounds, gotta fill event.item and event.index
-			TableItemOrTreeItem item = table.getItem(new Point(5, event.y));
-			if (item == null) {
-				return;
-			}
-			event.item = item.getItem();
-			int[] columnRange = getColumnRange(item, event.x, event.width);
-			if (columnRange[0] == -1) {
-				return;
-			}
-
-			//int height = tv.getRowDefaultHeight();
-			//System.out.println("Dirty: " + event.getBounds() + "; +" + height + "; " + event.gc.getClipping());
-			for (int i = columnRange[0]; i <= columnRange[1]; i++) {
-				event.index = i;
-
-
-				for (int y = event.y; y < (event.y + event.height); y += item.getBounds().height) {
-					item = table.getItem(new Point(5, y));
-					if (item == null) {
-						break;
-					}
-					Rectangle bounds = item.getBounds(i);
-					if (!r.intersects(bounds)) {
-						//event.gc.setForeground(ColorCache.getRandomColor());
-						//event.gc.
-						continue;
-					}
-					event.item = item.getItem();
-					//System.out.println(table.indexOf(event.item) + ": " + i);
-
-					
-					table.setData("inPaintInfo", new InPaintInfo(item.getItem(), event.index, bounds));
-
-					if (event.item != lastItem) {
-						table.setData("lastIndex", null);
-						lastRowIndex = table.indexOf(event.item);
-						table.setData("lastIndex", lastRowIndex);
-					}
-
-					boolean doErase = true;
-					if (Constants.isWindows7OrHigher) {
-						Point location = table.toControl(event.display.getCursorLocation());
-						if (location.y >= bounds.y && location.y < bounds.y + bounds.height) {
-							doErase = false;
-						}
-					}
-
-					Font f = event.gc.getFont();
-					if (doErase) {
-						//TableItemOrTreeItem item = TableOrTreeUtils.getEventItem(event.item);
-						TableViewSWT_EraseItem.eraseItem(event, event.gc, item, event.index, true, bounds, tv, true);
-					}
-					//TableItemOrTreeItem item = TableOrTreeUtils.getEventItem(event.item);
-					paintItem(event.gc, (TableRowSWT) tv.getRow(item), event.index, lastRowIndex, bounds, tv, false);
-					event.gc.setFont(f);
-					event.gc.setClipping(r);
-					
-					numPainted++;
-
-					lastItem = event.item;
-				}
-
-			}
-			
-			//System.out.println("# Painted:" + numPainted);
-
-		} else {
-			TableItemOrTreeItem item = TableOrTreeUtils.getEventItem(event.item);
-			Rectangle bounds = item.getBounds(event.index);
-
-			table.setData("inPaintInfo", new InPaintInfo((Item) event.item, event.index, bounds));
-
-			if (event.item != lastItem) {
-				table.setData("lastIndex", null);
-				lastRowIndex = table.indexOf(event.item);
-				table.setData("lastIndex", lastRowIndex);
-			}
-
-			//visibleRowsChanged();
-			paintItem(event.gc, (TableRowSWT) tv.getRow(item), event.index, lastRowIndex, bounds, tv, false);
-
-			lastItem = event.item;
-		}
-
-		table.setData("inPaintInfo", null);
-		table.setData("lastIndex", null);
-	}
-
-	/**
-	 * @param event
-	 * @param rowIndex 
-	 */
-	public static void paintItem(GC gc, TableRowSWT row, int columnIndex,
-			int rowIndex, Rectangle _cellBounds, TableViewSWT<?> tv, boolean skipClipCalc) {
-		//if (columnIndex == 1 && rowIndex == 0) {
-		//	System.out.println("paintItem " + gc.getClipping() +":" + rowIndex + ":" + columnIndex + ": " + Debug.getCompressedStackTrace());
-		//}
-		try {
-			//System.out.println(gc.getForeground().getRGB().toString());
-			//System.out.println("paintItem " + gc.getClipping());
-			if (TableViewSWTImpl.DEBUG_CELL_CHANGES) {
-				Random random = new Random(SystemTime.getCurrentTime() / 500);
-				gc.setBackground(ColorCache.getColor(gc.getDevice(),
-						210 + random.nextInt(45), 210 + random.nextInt(45),
-						210 + random.nextInt(45)));
-				gc.fillRectangle(gc.getClipping());
-			}
-
-			if (row == null || row.isRowDisposed()) {
-				return;
-			}
-			int iColumnNo = columnIndex;
-
-			//System.out.println(SystemTime.getCurrentTime() + "] paintItem " + rowIndex + ":" + iColumnNo);
-			if ((tv instanceof TableViewSWTImpl) && ((TableViewSWTImpl)tv).bSkipFirstColumn) {
-				if (iColumnNo == 0) {
-					return;
-				}
-				iColumnNo--;
-			}
-
-			TableColumnCore[] columnsOrdered = tv.getVisibleColumns();
-
-			if (iColumnNo >= columnsOrdered.length) {
-				System.out.println("Col #" + iColumnNo + " >= " + columnsOrdered.length
-						+ " count");
-				return;
-			}
-
-			if (!tv.isColumnVisible(columnsOrdered[iColumnNo])) {
-				System.out.println("col not visible " + iColumnNo);
-				return;
-			}
-
-			//if (rowIndex < tv.lastTopIndex || rowIndex > tv.lastBottomIndex) {
-			// this refreshes whole row (perhaps multiple), saving the many
-			// cell.refresh calls later because !cell.isUpToDate()
-			//tv.visibleRowsChanged();
-			//}
-
-			Rectangle cellBounds = new Rectangle(_cellBounds.x, _cellBounds.y, _cellBounds.width, _cellBounds.height); // item.getBounds(columnIndex);
-
-			//System.out.println("cb=" + cellBounds + ";b=" + event.getBounds() + ";clip=" + gc.getClipping());
-			Rectangle origClipping = gc.getClipping();
-
-			TableOrTreeSWT table = tv.getTableOrTreeSWT();
-			if (table != null) {
-  			if (origClipping.isEmpty()
-  					|| (origClipping.width >= cellBounds.width && origClipping.height >= cellBounds.height)) {
-  				table.setData("fullPaint", Boolean.TRUE);
-  			} else {
-  				table.setData("fullPaint", Boolean.FALSE);
-  				//System.out.println("not full paint: " + origClipping + ";cellbounds=" + cellBounds);
-  			}
-			}
-
-			if (!tv.isRowVisible(row)) {
-				tv.visibleRowsChanged();
-			}
-
-			tv.invokePaintListeners(gc, row, columnsOrdered[iColumnNo], cellBounds);
-
-			int rowAlpha = row.getAlpha();
-
-			int fontStyle = row.getFontStyle();
-			if (fontStyle == SWT.BOLD) {
-				gc.setFont(FontUtils.getAnyFontBold(gc));
-			}
-
-			//if (item.getImage(columnIndex) != null) {
-			//	cellBounds.x += 18;
-			//	cellBounds.width -= 18;
-			//}
-
-			if (cellBounds.width <= 0 || cellBounds.height <= 0) {
-				//System.out.println("no bounds");
-				return;
-			}
-
-			TableCellSWT cell = row.getTableCellSWT(columnsOrdered[iColumnNo].getName());
-
-			if (cell == null) {
-				return;
-			}
-
-			if (!cell.isUpToDate()) {
-				//System.out.println("R " + rowIndex + ":" + iColumnNo);
-				cell.refresh(true, true);
-				//return;
-			}
-
-			String text = cell.getText();
-
-			if (!skipClipCalc) {
-				Rectangle clipping = new Rectangle(cellBounds.x, cellBounds.y,
-  					cellBounds.width, cellBounds.height);
-  			// Cocoa calls paintitem while row is below tablearea, and painting there
-  			// is valid!
-  			if (!Utils.isCocoa && (tv instanceof TableViewSWTImpl)) {
-  				int iMinY = ((TableViewSWTImpl) tv).headerHeight + ((TableViewSWTImpl) tv).clientArea.y;
-  
-  				if (clipping.y < iMinY) {
-  					clipping.height -= iMinY - clipping.y;
-  					clipping.y = iMinY;
-  				}
-  				int iMaxY = ((TableViewSWTImpl) tv).clientArea.height + ((TableViewSWTImpl) tv).clientArea.y;
-  				if (clipping.y + clipping.height > iMaxY) {
-  					clipping.height = iMaxY - clipping.y + 1;
-  				}
-  			}
-  
-  			if (clipping.width <= 0 || clipping.height <= 0) {
-  				//System.out.println(row.getIndex() + " clipping="+clipping + ";" );
-  				return;
-  			}
-  
-  			if (!origClipping.contains(clipping.x, clipping.y)
-  					|| !origClipping.contains(clipping.x + clipping.width - 1, clipping.y
-  							+ clipping.height - 1)) {
-  				gc.setClipping(clipping);
-  			}
-			}
-
-			if (rowAlpha < 255) {
-				gc.setAlpha(rowAlpha);
-			}
-
-			if (cell.needsPainting()) {
-				Image graphicSWT = cell.getGraphicSWT();
-				if (graphicSWT != null && !graphicSWT.isDisposed()) {
-					int marginWidth = cell.getMarginWidth();
-					int marginHeight = cell.getMarginHeight();
-					Rectangle graphicBounds = new Rectangle(cellBounds.x + marginWidth,
-							cellBounds.y + marginHeight,
-							cellBounds.width - (marginWidth * 2), cellBounds.height
-									- (marginHeight * 2));
-					Rectangle imageBounds = graphicSWT.getBounds();
-					BufferedTableItem bufferedTableItem = null;
-					if (cell instanceof TableCellImpl) {
-						bufferedTableItem = ((TableCellImpl) cell).getBufferedTableItem();
-					}
-					if (bufferedTableItem instanceof BufferedGraphicTableItem) {
-						BufferedGraphicTableItem ti = (BufferedGraphicTableItem) bufferedTableItem;
-						int orientation = ti.getOrientation();
-						
-						if (orientation == SWT.FILL) {
-							if (!graphicBounds.isEmpty()) {
-								gc.setAdvanced(true);
-								//System.out.println(imageBounds + ";" + graphicBounds);
-  							gc.drawImage(graphicSWT, 0, 0, imageBounds.width,
-  									imageBounds.height, graphicBounds.x, graphicBounds.y,
-  									graphicBounds.width, graphicBounds.height);
-							}
-						} else {
-						
-  			  		if (imageBounds.width < graphicBounds.width) {
-    			    	if (orientation == SWT.CENTER) {
-    			    		graphicBounds.x += (graphicBounds.width - imageBounds.width) / 2;
-    			    	} else if (orientation == SWT.RIGHT) {
-    			    		graphicBounds.x = (graphicBounds.x + graphicBounds.width) - imageBounds.width;
-    			    	}
-  			  		}
-  			  		
-  			  		if (imageBounds.height < graphicBounds.height) {
-  			  			graphicBounds.y += (graphicBounds.height - imageBounds.height) / 2;
-  			  		}
-
-  			  		gc.drawImage(graphicSWT, graphicBounds.x, graphicBounds.y);
-						}
-
-					} else {
-			  		gc.drawImage(graphicSWT, graphicBounds.x, graphicBounds.y);
-					}
-				}
-				cell.doPaint(gc);
-			}
-			if (text.length() > 0) {
-				int ofsx = 0;
-				Image image = cell.getIcon();
-				Rectangle imageBounds = null;
-				if (image != null && !image.isDisposed()) {
-					imageBounds = image.getBounds();
-					int ofs = imageBounds.width;
-					ofsx += ofs;
-					cellBounds.x += ofs;
-					cellBounds.width -= ofs;
-				}
-				//System.out.println("PS " + rowIndex + ";" + cellBounds + ";" + cell.getText());
-				int style = TableColumnSWTUtils.convertColumnAlignmentToSWT(columnsOrdered[iColumnNo].getAlignment());
-				if (cellBounds.height > 20) {
-					style |= SWT.WRAP;
-				}
-				int textOpacity = cell.getTextAlpha();
-				if (textOpacity < 255) {
-					gc.setTextAntialias(SWT.ON);
-					gc.setAlpha(textOpacity);
-				} else if (textOpacity > 255) {
-					gc.setFont(FontUtils.getAnyFontBold(gc));
-					gc.setTextAntialias(SWT.ON);
-					gc.setAlpha(textOpacity & 255);
-				}
-				// put some padding on text
-				ofsx += 6;
-				cellBounds.x += 3;
-				cellBounds.width -= 6;
-				cellBounds.y += 2;
-				cellBounds.height -= 4;
-				if (!cellBounds.isEmpty()) {
-					GCStringPrinter sp = new GCStringPrinter(gc, text, cellBounds, true,
-							cellBounds.height > 20, style);
-					
-					boolean fit = sp.printString();
-					if (fit) {
-
-						cell.setDefaultToolTip(null);
-					} else {
-
-						cell.setDefaultToolTip(text);
-					}
-
-					Point size = sp.getCalculatedSize();
-					size.x += ofsx;
-
-					TableColumn tableColumn = cell.getTableColumn();
-					if (tableColumn != null && tableColumn.getPreferredWidth() < size.x) {
-						tableColumn.setPreferredWidth(size.x);
-					}
-
-					if (imageBounds != null) {
-						int drawToY = cellBounds.y + (cellBounds.height / 2)
-								- (imageBounds.height / 2);
-						
-						boolean hack_adv = Constants.isWindows8OrHigher && gc.getAdvanced();
-						
-						if ( hack_adv ){
-								// problem with icon transparency on win8
-							gc.setAdvanced( false );
-						}
-						if ((style & SWT.RIGHT) != 0) {
-							int drawToX = cellBounds.x + cellBounds.width - size.x;
-							gc.drawImage(image, drawToX, drawToY);
-						} else {
-							gc.drawImage(image, cellBounds.x - imageBounds.width - 3, drawToY);
-						}
-						
-						if ( hack_adv ){
-							gc.setAdvanced( true );
-						}
-					}
-				} else {
-					cell.setDefaultToolTip(null);
-				}
-			}
-			if (cell instanceof TableCellSWTBase) {
-				((TableCellSWTBase) cell).clearVisuallyChangedSinceRefresh();
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_TabsCommon.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_TabsCommon.java
index d562051..84f5d63 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_TabsCommon.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewSWT_TabsCommon.java
@@ -1,447 +1,232 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table.impl;
 
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.*;
-import org.eclipse.swt.events.*;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.*;
-import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Sash;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.config.ParameterListener;
 import org.gudy.azureus2.core3.config.impl.ConfigurationManager;
-import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.util.Constants;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.IndentWriter;
-import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
-import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance.UISWTViewEventListenerWrapper;
-import org.gudy.azureus2.ui.swt.pluginsimpl.*;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
 import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
 
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.common.table.TableView;
+import com.aelitis.azureus.ui.mdi.MdiEntry;
+import com.aelitis.azureus.ui.mdi.MdiEntryCreationListener2;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
+import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
+import com.aelitis.azureus.ui.selectedcontent.SelectedContentListener;
+import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
+import com.aelitis.azureus.ui.swt.mdi.MdiEntrySWT;
+import com.aelitis.azureus.ui.swt.mdi.TabbedMdiInterface;
+import com.aelitis.azureus.ui.swt.mdi.TabbedMdiMaximizeListener;
 
 /**
  * 
  * @author TuxPaper
  *
- * @TODO dynamically load tab contents, like SBC_TorrentDetailsView does
  */
-public class TableViewSWT_TabsCommon
+public class TableViewSWT_TabsCommon implements SelectedContentListener
 {
-	private static final Object	NULL_DS = new Object();
-	
+	UISWTView parentView;
 	TableViewSWT<?> tv;
 	
-		/** TabViews */
-	private ArrayList<UISWTViewCore> 					tabViews 		= new ArrayList<UISWTViewCore>(1);
-
-	private ArrayList<UISWTViewEventListenerWrapper>	removedViews 	= new ArrayList<UISWTViewEventListenerWrapper>();
-	
-	/** TabViews */
-	private CTabFolder 			tabFolder;
-	
 	/** Composite that stores the table (sometimes the same as mainComposite) */
 	public Composite tableComposite;
 
-	private boolean minimized;
-	private UISWTViewCore selectedView;
+	private TableView<?> tvOverride;
+	private Sash sash;
+	private TabbedMdiInterface tabbedMDI;
+	private Composite cTabsHolder;
+	private FormData fdHeightChanger;
+	private MenuItem menuItemShowTabs;
 
-	public TableViewSWT_TabsCommon(TableViewSWT<?> tv) {
+	public TableViewSWT_TabsCommon(UISWTView parentView, TableViewSWT<?> tv) {
+		this.parentView = parentView;
 		this.tv = tv;
 	}
 
-	public void triggerTabViewsDataSourceChanged(boolean sendParent) {
-		if (tabViews == null || tabViews.size() == 0) {
+	public void triggerTabViewsDataSourceChanged(TableView<?> tv) {
+		if (tabbedMDI == null || tabbedMDI.isDisposed()) {
 			return;
 		}
-		
-		if (sendParent) {
-			for (int i = 0; i < tabViews.size(); i++) {
-				UISWTViewCore view = tabViews.get(i);
-				if (view != null) {
-					dataSourceChanged( view, tv.getParentDataSource());
-				}
-			}
+		MdiEntry[] entries = tabbedMDI.getEntries();
+		if (entries == null || entries.length == 0) {
 			return;
 		}
 
-		// Set Data Object for all tabs.  
-
-		Object[] dataSourcesCore = tv.getSelectedDataSources(true);
-		Object[] dataSourcesPlugin = null;
-
-		for (int i = 0; i < tabViews.size(); i++) {
-			UISWTViewCore view = tabViews.get(i);
-			if (view != null) {
-				if (view.useCoreDataSource()) {
-					dataSourceChanged( view, dataSourcesCore.length == 0 ? tv.getParentDataSource()	: dataSourcesCore);
-				} else {
-					if (dataSourcesPlugin == null) {
-						dataSourcesPlugin = tv.getSelectedDataSources(false);
-					}
+		Object[] ds = tv.getSelectedDataSources(true);
 
-					dataSourceChanged( 
-						view,
-						dataSourcesPlugin.length == 0 ? PluginCoreUtils.convert( tv.getParentDataSource(), false) : dataSourcesPlugin);
-				}
+		for (MdiEntry entry : entries) {
+			if (entry instanceof MdiEntrySWT) {
+				triggerTabViewDataSourceChanged((MdiEntrySWT) entry, tv, ds);
 			}
 		}
 	}
 
-	public void triggerTabViewsDataSourceChanged(TableViewSWT<?> tv) {
-		if (tabViews == null || tabViews.size() == 0) {
+	public void setTvOverride(TableView<?> tvOverride) {
+		this.tvOverride = tvOverride;
+		selectedContent = SelectedContentManager.getCurrentlySelectedContent();
+	}
+
+	public void triggerTabViewDataSourceChanged(MdiEntrySWT view, TableView<?> tv,
+			Object[] dataSourcesCore) {
+		if (tvOverride != null) {
+			tv = tvOverride;
+		}
+		if (view == null) {
 			return;
 		}
 
-		// Set Data Object for all tabs.  
-
-		Object[] dataSourcesCore = tv.getSelectedDataSources(true);
-		Object[] dataSourcesPlugin = null;
-
-		for (int i = 0; i < tabViews.size(); i++) {
-			UISWTViewCore view = tabViews.get(i);
-			if (view != null) {
-				if (view.useCoreDataSource()) {
-					dataSourceChanged( 
-							view,
-							dataSourcesCore.length == 0 ? tv.getParentDataSource()
-									: dataSourcesCore);
-				} else {
-					if (dataSourcesPlugin == null) {
-						dataSourcesPlugin = tv.getSelectedDataSources(false);
-					}
+		// When there is not selected datasources in the TableView, send the
+		// parent's datasource
 
-					dataSourceChanged( 
-							view,
-							dataSourcesPlugin.length == 0 ? PluginCoreUtils.convert(
-									tv.getParentDataSource(), false) : dataSourcesPlugin);
-				}
-			}
+		if (dataSourcesCore == null) {
+			dataSourcesCore = tv.getSelectedDataSources(true);
 		}
-	}
-	
-	public void triggerTabViewDataSourceChanged(UISWTViewCore view) {
-		if (view != null) {
-			dataSourceChanged( view, tv.getParentDataSource());
-
-			if (view.useCoreDataSource()) {
-				Object[] dataSourcesCore = tv.getSelectedDataSources(true);
-				if (dataSourcesCore.length > 0) {
-					dataSourceChanged( 
-						view,
-						dataSourcesCore.length == 0 ? tv.getParentDataSource()
-									: dataSourcesCore);
-				}
-			} else {
-				Object[] dataSourcesPlugin = tv.getSelectedDataSources(false);
-				if (dataSourcesPlugin.length > 0) {
-					dataSourceChanged( 
-						view,
-						dataSourcesPlugin.length == 0 ? PluginCoreUtils.convert(
-									tv.getParentDataSource(), false) : dataSourcesPlugin);
-				}
-			}
+		if (tabbedMDI != null) {
+			tabbedMDI.setMaximizeVisible(dataSourcesCore != null && dataSourcesCore.length == 1);
 		}
-		
+		view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED,
+				dataSourcesCore.length == 0 ? tv.getParentDataSource()
+						: dataSourcesCore);
 	}
-
+	
 	public void delete() {
-		if (tabViews != null && tabViews.size() > 0) {
-			for (int i = 0; i < tabViews.size(); i++) {
-				UISWTViewCore view = tabViews.get(i);
-				if (view != null) {
-					view.triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
-				}
+		SelectedContentManager.removeCurrentlySelectedContentListener(this);
+		
+		if (menuItemShowTabs != null) {
+			menuItemShowTabs.remove();
+		}
+		/* disposal of composite should take care of tabbedMDI
+		if (tabbedMDI == null || tabbedMDI.isDisposed()) {
+			return;
+		}
+		MdiEntry[] entries = tabbedMDI.getEntries();
+		if (entries == null || entries.length == 0) {
+			return;
+		}
+		for (MdiEntry entry : entries) {
+			if (entry instanceof MdiEntrySWT) {
+				((MdiEntrySWT) entry).triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);				
 			}
 		}
+		*/
 	}
 
 	public void generate(IndentWriter writer) {
-		writer.println("# of SubViews: " + tabViews.size());
-		writer.indent();
-		try {
-			for (Iterator<UISWTViewCore> iter = tabViews.iterator(); iter.hasNext();) {
-				UISWTViewCore view = iter.next();
-				writer.println(view.getTitleID() + ": " + view.getFullTitle());
-			}
-		} finally {
-			writer.exdent();
-		}
+		writer.println("# of SubViews: "
+				+ (tabbedMDI == null ? "null" : tabbedMDI.getEntriesCount()));
 	}
 
 	public void localeChanged() {
-		if (tabViews != null && tabViews.size() > 0) {
-			for (int i = 0; i < tabViews.size(); i++) {
-				UISWTViewCore view = tabViews.get(i);
-				if (view != null) {
-					view.triggerEvent(UISWTViewEvent.TYPE_LANGUAGEUPDATE, null);
-				}
+		MdiEntry[] entries = tabbedMDI.getEntries();
+		if (entries == null || entries.length == 0) {
+			return;
+		}
+		for (MdiEntry entry : entries) {
+			if (entry instanceof MdiEntrySWT) {
+				((MdiEntrySWT) entry).triggerEvent(UISWTViewEvent.TYPE_LANGUAGEUPDATE, null);
 			}
 		}
 	}
 
-	public UISWTViewCore getActiveSubView() {
-		if (!tv.isTabViewsEnabled() || tabFolder == null || tabFolder.isDisposed()
-				|| minimized) {
+	public MdiEntrySWT getActiveSubView() {
+		if (!tv.isTabViewsEnabled() || tabbedMDI == null || tabbedMDI.isDisposed()
+				|| tabbedMDI.getMinimized()) {
 			return null;
 		}
 
-		return selectedView;
+		return tabbedMDI.getCurrentEntrySWT();
 	}
 
-	private void
-	dataSourceChanged(
-		final UISWTViewCore			view,
-		final Object				ds )
-	{
-		Utils.execSWTThread(
-			new Runnable()
-			{	
-				public void 
-				run() 
-				{
-					Composite comp = view.getComposite();
-					
-					if ( comp != null && comp.isVisible()){
-					
-						Object old_ds = view.getUserData( TableViewSWT_TabsCommon.class );
-						
-						if ( old_ds != null ){
-							
-							view.setUserData( TableViewSWT_TabsCommon.class, null );
-						}
-						
-						view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, ds);
-						
-					}else{
-						
-						view.setUserData( TableViewSWT_TabsCommon.class, ds==null?NULL_DS:ds );
-					}
-				}
-			});
-	}
-	
-	private void
-	checkPendingDataSourceChange(
-		UISWTViewCore		view )
-	{
-		Object ds = view.getUserData( TableViewSWT_TabsCommon.class );
-		
-		if ( ds != null ){
-			
-			if ( ds == NULL_DS ){
-				
-				ds = null;
-			}
-						
-			view.setUserData( TableViewSWT_TabsCommon.class, null );
-			
-			view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, ds);
-		}
-	}
+		// TabViews Functions
 	
-	public void 
-	refreshSelectedSubView()
-	{
-		UISWTViewCore view = getActiveSubView();
-		
-		if ( view != null && view.getComposite().isVisible()){
-			
-			checkPendingDataSourceChange( view );
-			
-			view.triggerEvent(UISWTViewEvent.TYPE_REFRESH, null);
+	private MdiEntry addTabView(UISWTViewEventListenerWrapper listener,
+			String afterID) {
+		UISWTViewCore view = null;
+		MdiEntrySWT entry = (MdiEntrySWT) tabbedMDI.createEntryFromEventListener(
+				tv.getTableID(), listener, listener.getViewID(), true, null, afterID);
+		if (entry instanceof UISWTViewCore) {
+			view = (UISWTViewCore) entry;
+
+		} else {
+			return entry;
 		}
-	}
 
-	private String
-	getViewTitleID(
-		String	view_id )
-	{
-		String history_key = "swt.ui.table.tab.view.namecache." + view_id;
+		try {
+			if (parentView != null) {
+				view.setParentView(parentView);
+			}
 
-		String id = COConfigurationManager.getStringParameter( history_key, "" );
+			triggerTabViewDataSourceChanged(entry, tv, null);
 
-		if ( id.length() == 0 ){
-			
-			String test = view_id + ".title.full";
-			
-			if ( MessageText.keyExists( test )){
-			
-				return( test );
-			}
-			
-			id = "!" + view_id + "!";
-		}
-		
-		return( id );
-	}
+		} catch (Throwable e) {
 
-		// TabViews Functions
-	
-	private void 
-	addTabView(
-		UISWTViewEventListenerWrapper 	listener,
-		boolean							start_of_day,
-		boolean							start_minimized )
-	{
-		if ( tabFolder == null){
-			
-			return;
+			Debug.out(e);
 		}
-				
-		String view_id = listener.getViewID();
-		
-		try{
-			UISWTViewImpl view = new UISWTViewImpl(tv.getTableID(), view_id, listener, null);
-			
-			triggerTabViewDataSourceChanged(view);
-	
-			int	insert_at = tabFolder.getItemCount();
-			
-			if ( !start_of_day && insert_at > 0 ){
-				
-				UIFunctionsSWT ui_func  = UIFunctionsManagerSWT.getUIFunctionsSWT();
-				
-				if ( ui_func != null ){
-					
-					UISWTInstance ui_swt = ui_func.getUISWTInstance();
-
-					if ( ui_swt != null ){
-						
-						ArrayList<UISWTViewEventListenerWrapper> listeners = new ArrayList<UISWTViewEventListenerWrapper>( Arrays.asList( ui_swt.getViewListeners(tv.getTableID())));
-					
-						int	l_index = listeners.indexOf( listener );
-						
-						CTabItem[] items = tabFolder.getItems();
-													
-						for ( int j=0;j<items.length;j++){
-									
-							UISWTViewImpl v = (UISWTViewImpl)items[j].getData( "IView" );
-									
-							if ( v != null ){
-										
-								int v_index = listeners.indexOf( v.getEventListener());
-							
-								if ( v_index > l_index ){
-									
-									insert_at = j;
-									
-									break;
-								}
-							}
-						}
-					}
-				}
-			}
-			
-			CTabItem item = new CTabItem( tabFolder, SWT.NULL, insert_at );
-			
-			boolean	is_minimized;
-			
-			if ( start_of_day ){
-				
-				is_minimized = start_minimized;
-				
-			}else{
-				
-				is_minimized = tabFolder.getMinimized();
-			}
-						
-			item.setToolTipText( MessageText.getString( is_minimized?"label.click.to.restore":"label.dblclick.to.min"));
-			
-			item.setData("IView", view);
-			
-			String title_id = view.getTitleID();
-			
-			String history_key = "swt.ui.table.tab.view.namecache." + view_id;
-			
-			String existing = COConfigurationManager.getStringParameter( history_key, "" );
-			
-			if ( !existing.equals( title_id )){
-				
-				COConfigurationManager.setParameter( history_key, title_id );
-			}
-			
-			Messages.setLanguageText(item, title_id );
-			
-			view.initialize(tabFolder);
-			
-			item.setControl(view.getComposite());
-			
-			tabViews.add(view);
-			
-			if ( !start_of_day ){
-				
-				removedViews.remove( listener );
-				
-				tabFolder.setSelection(item);
-				selectedView = (UISWTViewImpl)item.getData( "IView" );
-			}
 
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
+		return entry;
 	}
 	
-	private void
-	checkTabViews(
-		Map		closed )
+	private void removeTabView(String id)
 	{
-		for ( UISWTViewEventListenerWrapper l: new ArrayList<UISWTViewEventListenerWrapper>( removedViews )){
-			
-			String view_id = l.getViewID();
-			
-			if ( !closed.containsKey( view_id )){
-				
-				addTabView( l, false, false );
-			}
+		boolean exists = tabbedMDI.entryExists(id);
+		if (!exists) {
+			return;
 		}
+		MdiEntry entry = tabbedMDI.getEntry(id);
 		
-		for ( CTabItem item: tabFolder.getItems()){
-			
-			UISWTViewImpl view = (UISWTViewImpl)item.getData( "IView" );
-			
-			if ( view != null ){
-				
-				String view_id = view.getViewID();
-				
-				if ( closed.containsKey( view_id )){
-					
-					removeTabView( item );
-				}
-			}
-		}
-	}
-	
-	private void
-	removeTabView(
-		CTabItem		item )
-	{
-		UISWTViewImpl view = (UISWTViewImpl)item.getData( "IView" );
-		
-		if ( view != null ){
-						
-			removedViews.add((UISWTViewEventListenerWrapper)view.getEventListener());
-			
-			tabViews.remove( view );
-			
-			view.triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
-		
-			item.dispose();
-		}
+		// XXX 
+		//removedViews.add(((MdiEntrySWT) entry).getEventListener());
+		tabbedMDI.removeItem(entry);
 	}
 
 	public Composite createSashForm(final Composite composite) {
@@ -450,18 +235,18 @@ public class TableViewSWT_TabsCommon
 			return tableComposite;
 		}
 
+		SelectedContentManager.addCurrentlySelectedContentListener(this);
+
 		ConfigurationManager configMan = ConfigurationManager.getInstance();
 		
 		int iNumViews = 0;
 
 		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
-		UISWTViewEventListenerWrapper[] pluginViews = null;
 		if (uiFunctions != null) {
 			UISWTInstance pluginUI = uiFunctions.getUISWTInstance();
 
 			if (pluginUI != null) {
-				pluginViews = pluginUI.getViewListeners(tv.getTableID());
-				iNumViews += pluginViews.length;
+				iNumViews += pluginUI.getViewListeners(tv.getTableID()).length;
 			}
 		}
 
@@ -485,14 +270,35 @@ public class TableViewSWT_TabsCommon
 
 		// Create them in reverse order, so we can have the table auto-grow, and
 		// set the tabFolder's height manually
+		
+		
+		cTabsHolder = new Composite(form, SWT.NONE);
+		tabbedMDI = uiFunctions.createTabbedMDI(cTabsHolder, props_prefix);
+		tabbedMDI.setMaximizeVisible(true);
+		tabbedMDI.setMinimizeVisible(true);
+
+		tabbedMDI.setTabbedMdiMaximizeListener(new TabbedMdiMaximizeListener() {
+			public void maximizePressed() {
+				TableView tvToUse = tvOverride == null ? tv : tvOverride;
+				Object[] ds = tvToUse.getSelectedDataSources(true);
+				
+				if (ds.length == 1 && ds[0] instanceof DownloadManager) {
+
+					UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
 
-		final int TABHEIGHT = 22;
-		tabFolder = new CTabFolder(form, SWT.TOP | SWT.BORDER);
-		tabFolder.setMinimizeVisible(true);
-		tabFolder.setTabHeight(TABHEIGHT);
-		final int iFolderHeightAdj = tabFolder.computeSize(SWT.DEFAULT, 0).y;
+					if (uiFunctions != null) {
 
-		final Sash sash = new Sash(form, SWT.HORIZONTAL);
+						uiFunctions.getMDI().showEntryByID(
+								MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS,
+								ds);
+					}
+				}
+			}
+		});
+		
+		final int SASH_WIDTH = 5;
+		
+		sash = Utils.createSash( form, SASH_WIDTH );
 
 		tableComposite = tv.createMainPanel(form);
 		Composite cFixLayout = tableComposite;
@@ -522,6 +328,7 @@ public class TableViewSWT_TabsCommon
 			iSplitAt *= 100;
 		}
 
+		// pct is % bottom
 		double pct = iSplitAt / 10000.0;
 		if (pct < 0.03) {
 			pct = 0.03;
@@ -531,15 +338,16 @@ public class TableViewSWT_TabsCommon
 
 		// height will be set on first resize call
 		sash.setData("PCT", new Double(pct));
-		tabFolder.setLayoutData(formData);
-		final FormData tabFolderData = formData;
+		cTabsHolder.setLayout(new FormLayout());
+		fdHeightChanger = formData;
+		cTabsHolder.setLayoutData(formData);
 
 		// FormData for Sash
 		formData = new FormData();
 		formData.left = new FormAttachment(0, 0);
 		formData.right = new FormAttachment(100, 0);
-		formData.bottom = new FormAttachment(tabFolder);
-		formData.height = 5;
+		formData.bottom = new FormAttachment(cTabsHolder);
+		formData.height = SASH_WIDTH;
 		sash.setLayoutData(formData);
 
 		// FormData for table Composite
@@ -550,6 +358,8 @@ public class TableViewSWT_TabsCommon
 		formData.bottom = new FormAttachment(sash);
 		cFixLayout.setLayoutData(formData);
 
+
+		
 		// Listeners to size the folder
 		sash.addSelectionListener(new SelectionAdapter() {
 			public void widgetSelected(SelectionEvent e) {
@@ -559,282 +369,83 @@ public class TableViewSWT_TabsCommon
 					return;
 				}
 
-				if (tabFolder.getMinimized()) {
-					tabFolder.setMinimized(false);
-					refreshSelectedSubView();
-					ConfigurationManager configMan = ConfigurationManager.getInstance();
-					configMan.setParameter(props_prefix + ".subViews.minimized",
-							false);
-				}
-
 				Rectangle area = form.getClientArea();
-				tabFolderData.height = area.height - e.y - e.height - iFolderHeightAdj;
-				form.layout();
-
-				Double l = new Double((double) tabFolder.getBounds().height
-						/ form.getBounds().height);
-				sash.setData("PCT", l);
-				if (e.detail != SWT.DRAG) {
-					ConfigurationManager configMan = ConfigurationManager.getInstance();
-					configMan.setParameter(props_prefix + ".SplitAt",
-							(int) (l.doubleValue() * 10000));
-				}
-			}
-		});
-
-		final CTabFolder2Adapter folderListener = new CTabFolder2Adapter() {
-			public void minimize(CTabFolderEvent event) {
-				minimized = true;
 				
-				tabFolder.setMinimized(true);
-				tabFolderData.height = iFolderHeightAdj;
-				CTabItem[] items = tabFolder.getItems();
-				String tt = MessageText.getString( "label.click.to.restore" );
-				for (int i = 0; i < items.length; i++) {
-					CTabItem tabItem = items[i];
-					tabItem.setToolTipText( tt );
-					tabItem.getControl().setVisible(false);
-				}
-				form.layout();
-
-				UISWTViewCore view = getActiveSubView();
-				
-				fireFocusLost( view );	// fire even if null so we pick up current...
+				int height = area.height - e.y - e.height;
 				
-				ConfigurationManager configMan = ConfigurationManager.getInstance();
-				configMan.setParameter(props_prefix + ".subViews.minimized", true);
-			}
-
-			public void restore(CTabFolderEvent event) {
-				minimized = false;
-				tabFolder.setMinimized(false);
-				CTabItem selection = tabFolder.getSelection();
-				if (selection != null) {
-					selection.getControl().setVisible(true);
+				if ( !Constants.isWindows ){
+					height -= SASH_WIDTH;
 				}
 				
-				CTabItem[] items = tabFolder.getItems();
-				String tt = MessageText.getString( "label.dblclick.to.min"  );
+					// prevent sash from being dragged too far up. In the worst case it ends up 
+					// overlaying the split my-torrents sash and the user can't easily separate the two...
 				
-				for (int i = 0; i < items.length; i++) {
-					CTabItem tabItem = items[i];
-					tabItem.setToolTipText( tt );
+				if ( area.height - height < 100 ){
+					height = area.height - 100;
 				}
 				
-				form.notifyListeners(SWT.Resize, null);
-
-				UISWTViewCore view = getActiveSubView();
-				if (view != null) {
-					fireFocusGained( view );
+				if ( height < 0 ){
+					height = 0;
 				}
-				refreshSelectedSubView();
-
-				ConfigurationManager configMan = ConfigurationManager.getInstance();
-				configMan.setParameter(props_prefix + ".subViews.minimized", false);
 				
-				tabFolder.setToolTipText( "max" );
-			}
+				fdHeightChanger.height = height;
 
-		};
-		
-		tabFolder.addCTabFolder2Listener(folderListener);
-
-		tabFolder.addSelectionListener(new SelectionListener() {
-			public void widgetSelected(SelectionEvent e) {
-				selectedView = null;
-				// make sure its above
-				try {
-					((CTabItem) e.item).getControl().setVisible(true);
-					((CTabItem) e.item).getControl().moveAbove(null);
-
-					selectedView = (UISWTViewImpl)e.item.getData( "IView" );
-					// Call getActiveSubView and don't use selectedView. Function
-					// may return null even if there's a selectedView
-					UISWTViewCore view = getActiveSubView();
-					if (view != null) {
-						fireFocusGained( view );
-					}
-					
-				} catch (Exception t) {
+				Double l = new Double((double) height / area.height);
+				sash.setData("PCT", l);
+				if (e.detail != SWT.DRAG) {
+					ConfigurationManager configMan = ConfigurationManager.getInstance();
+					configMan.setParameter(props_prefix + ".SplitAt",
+							(int) (l.doubleValue() * 10000));
 				}
-			}
-
-			public void widgetDefaultSelected(SelectionEvent e) {
+				form.layout();
+				// sometimes sash cheese is left
+				cTabsHolder.redraw();
 			}
 		});
+		
+		buildFolder(form, props_prefix);
 
-		tabFolder.addMouseListener(new MouseAdapter() {
-			public void mouseDown(MouseEvent e) {
-				if (tabFolder.getMinimized()) {
-					folderListener.restore(null);
-					// If the user clicked down on the restore button, and we restore
-					// before the CTabFolder does, CTabFolder will minimize us again
-					// There's no way that I know of to determine if the mouse is 
-					// on that button!
-
-					// one of these will tell tabFolder to cancel
-					e.button = 0;
-					tabFolder.notifyListeners(SWT.MouseExit, null);
-				}
-			}
-			public void mouseDoubleClick(MouseEvent e) {
-				if (!tabFolder.getMinimized()) {
-					folderListener.minimize( null );
-				}
-			}
-		});
+		return form;
+	}
 
-		final Menu menu = new Menu( tabFolder );
+	private void buildFolder(final Composite form, final String props_prefix) {
+		PluginInterface pi = PluginInitializer.getDefaultInterface();
+		UIManager uim = pi.getUIManager();
+		MenuManager menuManager = uim.getMenuManager();
 		
-		tabFolder.addListener(SWT.MenuDetect, new Listener() {
-			public void handleEvent(Event event) {
-				
-				for ( MenuItem item: menu.getItems()){
-					
-					item.dispose();
-				}
-												
-				final CTabItem item = tabFolder.getItem( tabFolder.toControl( event.x, event.y ));
-				
-				boolean	need_sep = false;
-				
-				if ( item != null ){
-					
-					tabFolder.setSelection(item);
-					selectedView = (UISWTViewImpl)item.getData( "IView" );
-						
-					if ( selectedView != null ){
-						
-						final String view_id = selectedView.getViewID();
-						
-						MenuItem mi = new MenuItem( menu, SWT.PUSH );
-						
-						mi.setText( MessageText.getString( "label.close.tab" ));
-						
-						mi.addListener(
-							SWT.Selection,
-							new Listener()
-							{
-								public void 
-								handleEvent(
-									Event event ) 
-								{
-									String key = props_prefix + ".closedtabs";
-									
-									Map closedtabs = COConfigurationManager.getMapParameter(key, new HashMap());
-									
-									if ( !closedtabs.containsKey( view_id )){
-										
-										closedtabs.put( view_id, "" );
-										
-										COConfigurationManager.setParameter( key, closedtabs );
-									}
-								}
-							});
-						
-						need_sep = true;
-					}
-				}else{
-					
-					for ( final UISWTViewEventListenerWrapper l: removedViews ){
-						
-						need_sep = true;
-						
-						final String view_id = l.getViewID();
-						
-						MenuItem mi = new MenuItem( menu, SWT.PUSH );
-						
-						mi.setText( MessageText.getString( getViewTitleID( view_id )));
-						
-						mi.addListener(
-							SWT.Selection,
-							new Listener()
-							{
-								public void 
-								handleEvent(
-									Event event ) 
-								{
-									String key = props_prefix + ".closedtabs";
-									
-									Map closedtabs = COConfigurationManager.getMapParameter(key, new HashMap());
-									
-									if ( closedtabs.containsKey( view_id )){
-									
-										closedtabs.remove( view_id );
-									
-										COConfigurationManager.setParameter( key, closedtabs );
-									}
-								}
-							});
-					}
-				}
-				
-				if ( need_sep ){
-				
-					new MenuItem( menu, SWT.SEPARATOR );
-				}
-				
-				final MenuItem mi = new MenuItem( menu, SWT.CHECK );
-				
-				mi.setSelection( COConfigurationManager.getBooleanParameter( "Library.ShowTabsInTorrentView"));
-				
-				mi.setText( MessageText.getString( "ConfigView.section.style.ShowTabsInTorrentView" ));
-				
-				mi.addListener(
-					SWT.Selection,
-					new Listener()
-					{
-						public void 
-						handleEvent(
-							Event event ) 
-						{
-							COConfigurationManager.setParameter( "Library.ShowTabsInTorrentView", mi.getSelection());
-						}
-					});
-				
-				menu.setVisible(true);
-
+		
+		menuItemShowTabs = menuManager.addMenuItem(props_prefix + "._end_",
+				"ConfigView.section.style.ShowTabsInTorrentView");
+		menuItemShowTabs.setStyle(MenuItem.STYLE_CHECK);
+		menuItemShowTabs.addFillListener(new MenuItemFillListener() {
+			public void menuWillBeShown(MenuItem menu, Object data) {
+				menu.setData(COConfigurationManager.getBooleanParameter(
+						"Library.ShowTabsInTorrentView"));
+			}
+		});
+		menuItemShowTabs.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				COConfigurationManager.setParameter("Library.ShowTabsInTorrentView",
+						(Boolean) menu.getData());
 			}
 		});
 		
-		form.addListener(SWT.Resize, new Listener() {
+		cTabsHolder.addListener(SWT.Resize, new Listener() {
 			public void handleEvent(Event e) {
-				if (tabFolder.getMinimized()) {
+				if (tabbedMDI.getMinimized()) {
+					fdHeightChanger.height = tabbedMDI.getFolderHeight();
+					cTabsHolder.getParent().layout();
 					return;
 				}
 
 				Double l = (Double) sash.getData("PCT");
 				if (l != null) {
-					tabFolderData.height = (int) (form.getBounds().height * l.doubleValue())
-							- iFolderHeightAdj;
-					form.layout();
+					fdHeightChanger.height = (int) (form.getBounds().height * l.doubleValue());
+					cTabsHolder.getParent().layout();
 				}
 			}
 		});
 
-		String key = props_prefix + ".closedtabs";
-		
-		Map closed_tabs = COConfigurationManager.getMapParameter(key, new HashMap());
-
-		COConfigurationManager.addParameterListener(
-			key,
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					String	name )
-				{
-					if ( tabFolder.isDisposed()){
-						
-						COConfigurationManager.removeParameterListener( name, this );
-						
-					}else{
-						
-						checkTabViews( COConfigurationManager.getMapParameter(name, new HashMap()));
-					}
-				}
-			});
-		
 		String[] restricted_to = tv.getTabViewsRestrictedTo();
 		
 		Set<String> rt_set = new HashSet<String>();
@@ -844,95 +455,78 @@ public class TableViewSWT_TabsCommon
 			rt_set.addAll( Arrays.asList( restricted_to ));
 		}
 		
-		boolean folder_minimized = 
-			configMan.getBooleanParameter( props_prefix + ".subViews.minimized", !tv.getTabViewsExpandedByDefault());
-		
 		// Call plugin listeners
 		
-		if (pluginViews != null) {
-			for (UISWTViewEventListenerWrapper l : pluginViews) {
-				if (l != null) {
-					try {
-						String view_id = l.getViewID();
-						
-						if ( restricted_to == null || rt_set.contains( view_id )){
-						
-							if ( closed_tabs.containsKey( view_id )){
-								
-								removedViews.add( l );
-								
-							}else{
-								
-								addTabView( l, true, folder_minimized );
+		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
+		if (uiFunctions != null) {
+
+			UISWTInstance pluginUI = uiFunctions.getUISWTInstance();
+
+			if (pluginUI != null) {
+
+				UISWTViewEventListenerWrapper[] pluginViews = pluginUI.getViewListeners(
+						tv.getTableID());
+				if (pluginViews != null) {
+					for (final UISWTViewEventListenerWrapper l : pluginViews) {
+						if (l == null) {
+							continue;
+						}
+						try {
+							String view_id = l.getViewID();
+							
+							if (restricted_to != null && !rt_set.contains(view_id)) {
+								continue;
 							}
+							
+							tabbedMDI.registerEntry(view_id, new MdiEntryCreationListener2() {
+								public MdiEntry createMDiEntry(MultipleDocumentInterface mdi, String id,
+										Object datasource, Map<?, ?> params) {
+									return addTabView(l, null);
+								}
+							});
+							
+							tabbedMDI.loadEntryByID(view_id, false);
+
+						} catch (Exception e) {
+							// skip, plugin probably specifically asked to not be added
 						}
-					} catch (Exception e) {
-						// skip, plugin probably specifically asked to not be added
 					}
 				}
 			}
 		}
 
-		if ( folder_minimized ){
-			
-			tabFolder.setMinimized(true);
-			
-			tabFolderData.height = iFolderHeightAdj;
-			
-		}else{
-			
-			tabFolder.setMinimized(false);
-		}
-
-		if (tabFolder.getItemCount() > 0) {
-			CTabItem item = tabFolder.getItem(0);
-			tabFolder.setSelection(item);
-			selectedView = (UISWTViewImpl)item.getData( "IView" );
+		if (!tabbedMDI.getMinimized()) {
+			MdiEntry[] entries = tabbedMDI.getEntries();
+			if (entries.length > 0) {
+				tabbedMDI.showEntry(entries[0]);
+			}
 		}
-
-		return form;
 	}
 
-	private UISWTViewCore	focused_view = null;
+	private ISelectedContent[] selectedContent;
 	
-	private void
-	fireFocusGained(
-		UISWTViewCore		view )
-	{
-		if ( focused_view != null ){
-			
-			focused_view.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
-		}
-		
-		focused_view = view;
-		
-		checkPendingDataSourceChange( view );
-		
-		view.triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
-	}
-	
-	private void
-	fireFocusLost(
-		UISWTViewCore		view )
-	{
-		if ( focused_view != null && focused_view != view ){
+	public void swt_refresh() {
+		if (tv.isTabViewsEnabled() && tabbedMDI != null && !tabbedMDI.isDisposed()
+				&& !tabbedMDI.getMinimized()){
 			
-			focused_view.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
-		}
-		
-		focused_view = null;
-		
-		if ( view != null ){
-		
-			view.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
+			MdiEntry entry = tabbedMDI.getCurrentEntry();
+			if (entry != null) {
+				entry.updateUI();
+			}
 		}
 	}
-	
-	public void swt_refresh() {
-		if (tv.isTabViewsEnabled() && tabFolder != null && !tabFolder.isDisposed()
-				&& !tabFolder.getMinimized()){
-			
-			refreshSelectedSubView();
+
+	// @see com.aelitis.azureus.ui.selectedcontent.SelectedContentListener#currentlySelectedContentChanged(com.aelitis.azureus.ui.selectedcontent.ISelectedContent[], java.lang.String)
+	public void currentlySelectedContentChanged(ISelectedContent[] currentContent,
+			String viewID) {
+		TableView tvToUse = tvOverride == null ? tv : tvOverride;
+		if (viewID != null && viewID.equals(tvToUse.getTableID())) {
+			selectedContent = currentContent;
+		}
+		if (currentContent.length == 0 && tv.isVisible() && selectedContent != null
+				&& selectedContent.length != 0) {
+			SelectedContentManager.changeCurrentlySelectedContent(
+					tvToUse.getTableID(), selectedContent, tvToUse);
 		}
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewTab.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewTab.java
index 66605dd..152c678 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewTab.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TableViewTab.java
@@ -1,32 +1,53 @@
-package org.gudy.azureus2.ui.swt.views.table.impl;
+/*
+ * Copyright (C) Azureus Software, 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 ( 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
+ */
 
-import java.util.Map;
+package org.gudy.azureus2.ui.swt.views.table.impl;
 
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Menu;
-
+import org.eclipse.swt.widgets.Text;
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator;
 import org.gudy.azureus2.core3.util.IndentWriter;
-import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.plugins.UISWTView;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
 import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
 
-import com.aelitis.azureus.ui.common.ToolBarItem;
+import com.aelitis.azureus.ui.common.table.TableView;
+import com.aelitis.azureus.ui.common.table.TableViewFilterCheck.TableViewFilterCheckEx;
+import com.aelitis.azureus.ui.mdi.MdiEntry;
 
+/**
+ * An {@link UISWTView} that contains a {@link TableView}.  Usually is
+ * an view in a  {@link MdiEntry}, or a TableView's subview.
+ */
 public abstract class TableViewTab<DATASOURCETYPE>
-	implements UISWTViewCoreEventListener, UIPluginViewToolBarListener,
-	AEDiagnosticsEvidenceGenerator
+	implements UISWTViewCoreEventListener, AEDiagnosticsEvidenceGenerator
 {
 	private TableViewSWT<DATASOURCETYPE> tv;
 	private Object parentDataSource;
 	private final String propertiesPrefix;
 	private Composite composite;
 	private UISWTView swtView;
+	private Text filterTextControl;
+	private TableViewFilterCheckEx<DATASOURCETYPE> filterCheck;
 
 	
 	public TableViewTab(String propertiesPrefix) {
@@ -43,13 +64,17 @@ public abstract class TableViewTab<DATASOURCETYPE>
 			tv.setParentDataSource(parentDataSource);
 		}
 		Composite parent = initComposite(composite);
-		tv.initialize(parent);
+		tv.initialize(swtView, parent);
 		if (parent != composite) {
 			this.composite = composite;
 		} else {
 			this.composite = tv.getComposite();
 		}
 		
+		if (filterCheck != null) {
+			tv.enableFilterCheck(filterTextControl, filterCheck);
+		}
+		
 		tableViewTabInitComplete();
 	}
 	
@@ -79,6 +104,7 @@ public abstract class TableViewTab<DATASOURCETYPE>
 		if (tv != null) {
 			tv.delete();
 		}
+		tv = null;
 	}
 
 	public String getFullTitle() {
@@ -98,27 +124,6 @@ public abstract class TableViewTab<DATASOURCETYPE>
 		return composite;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener#toolBarItemActivated(com.aelitis.azureus.ui.common.ToolBarItem, long, java.lang.Object)
-	 */
-	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
-			Object datasource) {
-		if (item.getID().equals("editcolumns")) {
-			if (tv instanceof TableViewSWTImpl) {
-				((TableViewSWT<?>)tv).showColumnEditor();
-				return true;
-			}
-		}
-		return false;
-	}
-	
-	/* (non-Javadoc)
-	 * @see com.aelitis.azureus.ui.common.ToolBarEnabler2#refreshToolBarItems(java.util.Map)
-	 */
-	public void refreshToolBarItems(Map<String, Long> list) {
-		list.put("editcolumns", UIToolBarItem.STATE_ENABLED);
-	}
-	
 	public String getPropertiesPrefix() {
 		return propertiesPrefix;
 	}
@@ -130,14 +135,14 @@ public abstract class TableViewTab<DATASOURCETYPE>
 	public void viewActivated() {
 		// cheap hack.. calling isVisible freshens table's visible status (and
 		// updates subviews)
-		if (tv instanceof TableViewSWTImpl) {
-			((TableViewSWTImpl<?>)tv).isVisible();
+		if (tv instanceof TableViewSWT) {
+			((TableViewSWT<?>)tv).isVisible();
 		}
 	}
 	
 	private void viewDeactivated() {
-		if (tv instanceof TableViewSWTImpl) {
-			((TableViewSWTImpl<?>)tv).isVisible();
+		if (tv instanceof TableViewSWT) {
+			((TableViewSWT<?>)tv).isVisible();
 		}
 	}
 
@@ -145,7 +150,6 @@ public abstract class TableViewTab<DATASOURCETYPE>
 		switch (event.getType()) {
 			case UISWTViewEvent.TYPE_CREATE:
 				swtView = (UISWTView) event.getData();
-				swtView.setToolBarListener(this);
 				swtView.setTitle(getFullTitle());
 				break;
 
@@ -189,4 +193,14 @@ public abstract class TableViewTab<DATASOURCETYPE>
 	public UISWTView getSWTView() {
 		return swtView;
 	}
+
+	public void enableFilterCheck(Text textControl,
+			TableViewFilterCheckEx<DATASOURCETYPE> filter_check_handler) {
+		if (tv != null) {
+			tv.enableFilterCheck(textControl, filter_check_handler);
+		} else {
+			filterTextControl = textControl;
+			filterCheck = filter_check_handler;
+		}
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TreeColumnDelegate.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TreeColumnDelegate.java
deleted file mode 100644
index 188ecf4..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TreeColumnDelegate.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/**
- * Created on May 3, 2010
- *
- * 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.impl;
-
-import org.eclipse.swt.events.ControlListener;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.ui.swt.views.table.TableColumnOrTreeColumn;
-import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;
-
-/**
- * @author TuxPaper
- * @created May 3, 2010
- *
- */
-public class TreeColumnDelegate implements TableColumnOrTreeColumn
-{
-	TreeColumn treeColumn;
-
-	public TreeColumnDelegate(TreeColumn item) {
-		treeColumn = item;
-	}
-
-	public TreeColumnDelegate(TableOrTreeSWT parent, int style) {
-		treeColumn = new TreeColumn((Tree) parent.getComposite(), style);
-	}
-
-	public Image getImage() {
-		return treeColumn.getImage();
-	}
-
-	public String getText() {
-		return treeColumn.getText();
-	}
-
-	public void addControlListener(ControlListener listener) {
-		treeColumn.addControlListener(listener);
-	}
-
-	public void addListener(int eventType, Listener listener) {
-		treeColumn.addListener(eventType, listener);
-	}
-
-	public void addSelectionListener(SelectionListener listener) {
-		treeColumn.addSelectionListener(listener);
-	}
-
-	public void addDisposeListener(DisposeListener listener) {
-		treeColumn.addDisposeListener(listener);
-	}
-
-	public boolean getMoveable() {
-		return treeColumn.getMoveable();
-	}
-
-	public TableOrTreeSWT getParent() {
-		return TableOrTreeUtils.getTableOrTreeSWT(treeColumn.getParent());
-	}
-
-	public boolean getResizable() {
-		return treeColumn.getResizable();
-	}
-
-	public String getToolTipText() {
-		return treeColumn.getToolTipText();
-	}
-
-	public int getWidth() {
-		return treeColumn.getWidth();
-	}
-
-	public void dispose() {
-		treeColumn.dispose();
-	}
-
-	public boolean equals(Object obj) {
-		return treeColumn.equals(obj);
-	}
-
-	public int getAlignment() {
-		return treeColumn.getAlignment();
-	}
-
-	public Object getData() {
-		return treeColumn.getData();
-	}
-
-	public Object getData(String key) {
-		return treeColumn.getData(key);
-	}
-
-	public Display getDisplay() {
-		return treeColumn.getDisplay();
-	}
-
-	public Listener[] getListeners(int eventType) {
-		return treeColumn.getListeners(eventType);
-	}
-
-	public int getStyle() {
-		return treeColumn.getStyle();
-	}
-
-	public int hashCode() {
-		return treeColumn.hashCode();
-	}
-
-	public void pack() {
-		treeColumn.pack();
-	}
-
-	public void removeControlListener(ControlListener listener) {
-		treeColumn.removeControlListener(listener);
-	}
-
-	public void removeSelectionListener(SelectionListener listener) {
-		treeColumn.removeSelectionListener(listener);
-	}
-
-	public void setAlignment(int alignment) {
-		treeColumn.setAlignment(alignment);
-	}
-
-	public void setImage(Image image) {
-		treeColumn.setImage(image);
-	}
-
-	public void setMoveable(boolean moveable) {
-		treeColumn.setMoveable(moveable);
-	}
-
-	public void setResizable(boolean resizable) {
-		treeColumn.setResizable(resizable);
-	}
-
-	public void setText(String string) {
-		treeColumn.setText(string);
-	}
-
-	public void setToolTipText(String string) {
-		treeColumn.setToolTipText(string);
-	}
-
-	public boolean isDisposed() {
-		return treeColumn.isDisposed();
-	}
-
-	public boolean isListening(int eventType) {
-		return treeColumn.isListening(eventType);
-	}
-
-	public void setWidth(int width) {
-		treeColumn.setWidth(width);
-	}
-
-	public void notifyListeners(int eventType, Event event) {
-		treeColumn.notifyListeners(eventType, event);
-	}
-
-	public void removeListener(int eventType, Listener listener) {
-		treeColumn.removeListener(eventType, listener);
-	}
-
-	public void removeDisposeListener(DisposeListener listener) {
-		treeColumn.removeDisposeListener(listener);
-	}
-
-	public void setData(Object data) {
-		treeColumn.setData(data);
-	}
-
-	public void setData(String key, Object value) {
-		treeColumn.setData(key, value);
-	}
-
-	public String toString() {
-		return treeColumn.toString();
-	}
-
-	/////////////////
-	
-	public Item getColumn() {
-		return treeColumn;
-	}
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TreeDelegate.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TreeDelegate.java
deleted file mode 100644
index d3a79b1..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TreeDelegate.java
+++ /dev/null
@@ -1,916 +0,0 @@
-/**
- * Created on May 3, 2010
- *
- * 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.impl;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.eclipse.swt.accessibility.Accessible;
-import org.eclipse.swt.events.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.ui.swt.components.InPaintInfo;
-import org.gudy.azureus2.ui.swt.views.table.TableColumnOrTreeColumn;
-import org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem;
-import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;
-
-/**
- * Delegates a SWT {@link Tree} into a {@link TableOrTreeSWT} allowing easy
- * switching from Table and Tree.
- * <p>
- * Uses own map for setData and getData for faster lookups and no SWT thread
- * checking
- * 
- * @author TuxPaper
- * @created May 3, 2010
- *
- */
-public class TreeDelegate implements TableOrTreeSWT
-{
-	static Constructor<?> constTree;
-	Tree tree;
-
-	Map<String, Object> data = new HashMap<String, Object>(5);
-	private int style;
-	
-	static {
-		try {
-			Class<?> claTree;
-			if (Constants.isWindows) {
-				claTree = Class.forName("org.eclipse.swt.widgets.Tree2");
-			} else {
-				claTree = Tree.class;
-			}
-			constTree = claTree.getConstructor(new Class[] {
-				Composite.class,
-				int.class
-			});
-		} catch (Throwable t) {
-		}
-	}
-
-	protected TreeDelegate(Composite parent, int style)
-			throws Exception {
-		this(constTree == null ? new Tree(parent,
-				style) : (Tree) constTree.newInstance(new Object[] { parent, style }));
-		this.style = style;
-	}
-
-	protected TreeDelegate(Tree t) {
-		tree = t;
-		this.style = t.getStyle();
-	}
-
-	public Composite getComposite() {
-		return tree;
-	}
-
-	public Rectangle computeTrim(int x, int y, int width, int height) {
-		return tree.computeTrim(x, y, width, height);
-	}
-
-	public void addControlListener(ControlListener listener) {
-		tree.addControlListener(listener);
-	}
-
-	public void changed(Control[] changed) {
-		tree.changed(changed);
-	}
-
-	public void addDragDetectListener(DragDetectListener listener) {
-		tree.addDragDetectListener(listener);
-	}
-
-	public Rectangle getClientArea() {
-		return tree.getClientArea();
-	}
-
-	public void addListener(int eventType, Listener listener) {
-		tree.addListener(eventType, listener);
-	}
-
-	public void addFocusListener(FocusListener listener) {
-		tree.addFocusListener(listener);
-	}
-
-	public ScrollBar getHorizontalBar() {
-		return tree.getHorizontalBar();
-	}
-
-	public void addDisposeListener(DisposeListener listener) {
-		tree.addDisposeListener(listener);
-	}
-
-	public ScrollBar getVerticalBar() {
-		return tree.getVerticalBar();
-	}
-
-	public void addHelpListener(HelpListener listener) {
-		tree.addHelpListener(listener);
-	}
-
-	public void addKeyListener(KeyListener listener) {
-		tree.addKeyListener(listener);
-	}
-
-	public void addMenuDetectListener(MenuDetectListener listener) {
-		tree.addMenuDetectListener(listener);
-	}
-
-	public void addMouseListener(MouseListener listener) {
-		tree.addMouseListener(listener);
-	}
-
-	public void addSelectionListener(SelectionListener listener) {
-		tree.addSelectionListener(listener);
-	}
-
-	public void addMouseTrackListener(MouseTrackListener listener) {
-		tree.addMouseTrackListener(listener);
-	}
-
-	public void addMouseMoveListener(MouseMoveListener listener) {
-		tree.addMouseMoveListener(listener);
-	}
-
-	public void addTreeListener(TreeListener listener) {
-		tree.addTreeListener(listener);
-	}
-
-	public void addMouseWheelListener(MouseWheelListener listener) {
-		tree.addMouseWheelListener(listener);
-	}
-
-	public int getBackgroundMode() {
-		return tree.getBackgroundMode();
-	}
-
-	public void addPaintListener(PaintListener listener) {
-		tree.addPaintListener(listener);
-	}
-
-	public Control[] getChildren() {
-		return tree.getChildren();
-	}
-
-	public void addTraverseListener(TraverseListener listener) {
-		tree.addTraverseListener(listener);
-	}
-
-	public void dispose() {
-		tree.dispose();
-	}
-
-	public Layout getLayout() {
-		return tree.getLayout();
-	}
-
-	public Control[] getTabList() {
-		return tree.getTabList();
-	}
-
-	public boolean getLayoutDeferred() {
-		return tree.getLayoutDeferred();
-	}
-
-	public Point computeSize(int wHint, int hHint) {
-		return tree.computeSize(wHint, hHint);
-	}
-
-	public boolean isLayoutDeferred() {
-		return tree.isLayoutDeferred();
-	}
-
-	public void layout() {
-		tree.layout();
-	}
-
-	public Object getData() {
-		return getData(null);
-	}
-	
-	public Object getData(String key) {
-		synchronized (data) {
-			return data.get(key);
-		}
-	}
-
-	public void layout(boolean changed) {
-		tree.layout(changed);
-	}
-
-	public Display getDisplay() {
-		return tree.getDisplay();
-	}
-
-	public Listener[] getListeners(int eventType) {
-		return tree.getListeners(eventType);
-	}
-
-	public void layout(boolean changed, boolean all) {
-		tree.layout(changed, all);
-	}
-
-	public int getStyle() {
-		return style;
-	}
-
-	public boolean dragDetect(Event event) {
-		return tree.dragDetect(event);
-	}
-
-	public boolean isListening(int eventType) {
-		return tree.isListening(eventType);
-	}
-
-	public boolean dragDetect(MouseEvent event) {
-		return tree.dragDetect(event);
-	}
-
-	public void notifyListeners(int eventType, Event event) {
-		tree.notifyListeners(eventType, event);
-	}
-
-	public void removeListener(int eventType, Listener listener) {
-		tree.removeListener(eventType, listener);
-	}
-
-	public void removeDisposeListener(DisposeListener listener) {
-		tree.removeDisposeListener(listener);
-	}
-
-	public void setBackgroundMode(int mode) {
-		tree.setBackgroundMode(mode);
-	}
-
-	public boolean setFocus() {
-		return tree.setFocus();
-	}
-
-	public void setLayout(Layout layout) {
-		tree.setLayout(layout);
-	}
-
-	public int getBorderWidth() {
-		return tree.getBorderWidth();
-	}
-
-	public void setLayoutDeferred(boolean defer) {
-		tree.setLayoutDeferred(defer);
-	}
-
-	public Rectangle getBounds() {
-		return tree.getBounds();
-	}
-
-	public void setTabList(Control[] tabList) {
-		tree.setTabList(tabList);
-	}
-
-	public Cursor getCursor() {
-		return tree.getCursor();
-	}
-
-	public void setData(Object data) {
-		setData(null, data);
-	}
-	
-	public void setData(String key, Object value) {
-		synchronized (data) {
-			data.put(key, value);
-		}
-	}
-
-	public boolean getDragDetect() {
-		return tree.getDragDetect();
-	}
-
-	public boolean getEnabled() {
-		return tree.getEnabled();
-	}
-
-	public Font getFont() {
-		return tree.getFont();
-	}
-
-	public Color getForeground() {
-		return tree.getForeground();
-	}
-
-	public Object getLayoutData() {
-		return tree.getLayoutData();
-	}
-
-	public Point getLocation() {
-		return tree.getLocation();
-	}
-
-	public Menu getMenu() {
-		return tree.getMenu();
-	}
-
-	public Monitor getMonitor() {
-		return tree.getMonitor();
-	}
-
-	public Composite getParent() {
-		return tree.getParent();
-	}
-
-	public Region getRegion() {
-		return tree.getRegion();
-	}
-
-	public Shell getShell() {
-		return tree.getShell();
-	}
-
-	public Point getSize() {
-		return tree.getSize();
-	}
-
-	public String getToolTipText() {
-		return tree.getToolTipText();
-	}
-
-	public boolean getVisible() {
-		return tree.getVisible();
-	}
-
-	public String toString() {
-		return tree.toString();
-	}
-
-	public boolean isEnabled() {
-		return tree.isEnabled();
-	}
-
-	public boolean isFocusControl() {
-		return tree.isFocusControl();
-	}
-
-	public boolean isReparentable() {
-		return tree.isReparentable();
-	}
-
-	public boolean isVisible() {
-		return tree.isVisible();
-	}
-
-	public void moveAbove(Control control) {
-		tree.moveAbove(control);
-	}
-
-	public void moveBelow(Control control) {
-		tree.moveBelow(control);
-	}
-
-	public void pack() {
-		tree.pack();
-	}
-
-	public void pack(boolean changed) {
-		tree.pack(changed);
-	}
-
-	public void clear(int index, boolean all) {
-		tree.clear(index, all);
-	}
-
-	public boolean print(GC gc) {
-		return tree.print(gc);
-	}
-
-	public void clearAll(boolean all) {
-		tree.clearAll(all);
-	}
-
-	public Point computeSize(int wHint, int hHint, boolean changed) {
-		return tree.computeSize(wHint, hHint, changed);
-	}
-
-	public void redraw() {
-		tree.redraw();
-	}
-
-	public void redraw(int x, int y, int width, int height, boolean all) {
-		tree.redraw(x, y, width, height, all);
-	}
-
-	public void removeControlListener(ControlListener listener) {
-		tree.removeControlListener(listener);
-	}
-
-	public void removeDragDetectListener(DragDetectListener listener) {
-		tree.removeDragDetectListener(listener);
-	}
-
-	public void removeFocusListener(FocusListener listener) {
-		tree.removeFocusListener(listener);
-	}
-
-	public void removeHelpListener(HelpListener listener) {
-		tree.removeHelpListener(listener);
-	}
-
-	public void removeKeyListener(KeyListener listener) {
-		tree.removeKeyListener(listener);
-	}
-
-	public void removeMenuDetectListener(MenuDetectListener listener) {
-		tree.removeMenuDetectListener(listener);
-	}
-
-	public void removeMouseTrackListener(MouseTrackListener listener) {
-		tree.removeMouseTrackListener(listener);
-	}
-
-	public void removeMouseListener(MouseListener listener) {
-		tree.removeMouseListener(listener);
-	}
-
-	public void removeMouseMoveListener(MouseMoveListener listener) {
-		tree.removeMouseMoveListener(listener);
-	}
-
-	public void removeMouseWheelListener(MouseWheelListener listener) {
-		tree.removeMouseWheelListener(listener);
-	}
-
-	public void removePaintListener(PaintListener listener) {
-		tree.removePaintListener(listener);
-	}
-
-	public void removeTraverseListener(TraverseListener listener) {
-		tree.removeTraverseListener(listener);
-	}
-
-	public void deselect(TableItemOrTreeItem item) {
-		//System.out.println("DESEL " + Debug.getCompressedStackTrace());
-		tree.deselect((TreeItem) item.getItem());
-	}
-
-	public void setBackground(Color color) {
-		tree.setBackground(color);
-	}
-
-	public void deselectAll() {
-		tree.deselectAll();
-	}
-
-	public boolean equals(Object obj) {
-		return tree.equals(obj);
-	}
-
-	public boolean forceFocus() {
-		return tree.forceFocus();
-	}
-
-	public Accessible getAccessible() {
-		return tree.getAccessible();
-	}
-
-	public Color getBackground() {
-		return tree.getBackground();
-	}
-
-	public Image getBackgroundImage() {
-		return tree.getBackgroundImage();
-	}
-
-	public void setBackgroundImage(Image image) {
-		tree.setBackgroundImage(image);
-	}
-
-	public void setBounds(int x, int y, int width, int height) {
-		tree.setBounds(x, y, width, height);
-	}
-
-	public void setBounds(Rectangle rect) {
-		tree.setBounds(rect);
-	}
-
-	public void setCapture(boolean capture) {
-		tree.setCapture(capture);
-	}
-
-	public void setCursor(Cursor cursor) {
-		tree.setCursor(cursor);
-	}
-
-	public void setDragDetect(boolean dragDetect) {
-		tree.setDragDetect(dragDetect);
-	}
-
-	public void setEnabled(boolean enabled) {
-		tree.setEnabled(enabled);
-	}
-
-	public void setForeground(Color color) {
-		tree.setForeground(color);
-	}
-
-	public void setLayoutData(Object layoutData) {
-		tree.setLayoutData(layoutData);
-	}
-
-	public void setLocation(int x, int y) {
-		tree.setLocation(x, y);
-	}
-
-	public void setLocation(Point location) {
-		tree.setLocation(location);
-	}
-
-	public void setMenu(Menu menu) {
-		tree.setMenu(menu);
-	}
-
-	public int getGridLineWidth() {
-		return tree.getGridLineWidth();
-	}
-
-	public int getHeaderHeight() {
-		return tree.getHeaderHeight();
-	}
-
-	public boolean getHeaderVisible() {
-		return tree.getHeaderVisible();
-	}
-
-	public void setRegion(Region region) {
-		tree.setRegion(region);
-	}
-
-	public void setSize(int width, int height) {
-		tree.setSize(width, height);
-	}
-
-	public TableColumnOrTreeColumn getColumn(int index) {
-		return wrapOrNull(tree.getColumn(index));
-	}
-
-	public void setSize(Point size) {
-		tree.setSize(size);
-	}
-
-	public int getColumnCount() {
-		return tree.getColumnCount();
-	}
-
-	public void setToolTipText(String string) {
-		tree.setToolTipText(string);
-	}
-
-	public int[] getColumnOrder() {
-		return tree.getColumnOrder();
-	}
-
-	public void setVisible(boolean visible) {
-		tree.setVisible(visible);
-	}
-
-	public TableColumnOrTreeColumn[] getColumns() {
-		return wrapOrNull(tree.getColumns());
-	}
-
-	public TableItemOrTreeItem getItem(int index) {
-		if (index < 0) {
-			return null;
-		}
-		return wrapOrNull(tree.getItem(index));
-	}
-
-	public Point toControl(int x, int y) {
-		return tree.toControl(x, y);
-	}
-
-	public Point toControl(Point point) {
-		return tree.toControl(point);
-	}
-
-	public TableItemOrTreeItem getItem(Point point) {
-		return wrapOrNull(tree.getItem(point));
-	}
-
-	public Point toDisplay(int x, int y) {
-		return tree.toDisplay(x, y);
-	}
-
-	public Point toDisplay(Point point) {
-		return tree.toDisplay(point);
-	}
-
-	public int getItemCount() {
-		return tree.getItemCount();
-	}
-
-	public int getItemHeight() {
-		return tree.getItemHeight();
-	}
-
-	public TableItemOrTreeItem[] getItems() {
-		return wrapOrNull(tree.getItems());
-	}
-
-	public boolean getLinesVisible() {
-		return tree.getLinesVisible();
-	}
-
-	public TableItemOrTreeItem getParentItem() {
-		return wrapOrNull(tree.getParentItem());
-	}
-
-	public TableItemOrTreeItem[] getSelection() {
-		return wrapOrNull(tree.getSelection());
-	}
-
-	public int getSelectionCount() {
-		return tree.getSelectionCount();
-	}
-
-	public TableColumnOrTreeColumn getSortColumn() {
-		return wrapOrNull(tree.getSortColumn());
-	}
-
-	public int getSortDirection() {
-		return tree.getSortDirection();
-	}
-
-	public TableItemOrTreeItem getTopItem() {
-		return wrapOrNull(tree.getTopItem());
-	}
-
-	public int hashCode() {
-		return tree.hashCode();
-	}
-
-	public boolean isDisposed() {
-		return tree.isDisposed();
-	}
-
-	public void update() {
-		tree.update();
-	}
-
-	public int indexOf(TableColumnOrTreeColumn column) {
-		return tree.indexOf((TreeColumn) column.getColumn());
-	}
-
-	public int indexOf(TableItemOrTreeItem item) {
-		TreeItem ti = (TreeItem) item.getItem();
-		if (ti.isDisposed()) {
-			return -1;
-		}
-
-		InPaintInfo info = (InPaintInfo) tree.getData("inPaintInfo");
-		if (info != null && ti.equals(info.item)) {
-			Object data = tree.getData("lastIndex");
-			if (data instanceof Number) {
-				int idx = ((Number)data).intValue();
-				//System.out.println("yay " + idx);
-				return idx;
-			}
-		}
-
-		return tree.indexOf(ti);
-	}
-
-	public boolean setParent(Composite parent) {
-		return tree.setParent(parent);
-	}
-
-	public void removeAll() {
-		tree.removeAll();
-	}
-
-	public void removeSelectionListener(SelectionListener listener) {
-		tree.removeSelectionListener(listener);
-	}
-
-	public void removeTreeListener(TreeListener listener) {
-		tree.removeTreeListener(listener);
-	}
-
-	public void setInsertMark(TableItemOrTreeItem item, boolean before) {
-		tree.setInsertMark((TreeItem) item.getItem(), before);
-	}
-
-	public void setItemCount(int count) {
-		tree.setItemCount(count);
-	}
-
-	public void setLinesVisible(boolean show) {
-		tree.setLinesVisible(show);
-	}
-
-	public void select(TableItemOrTreeItem item) {
-		tree.select((TreeItem) item.getItem());
-	}
-
-	public void selectAll() {
-		tree.selectAll();
-	}
-
-	public void setColumnOrder(int[] order) {
-		tree.setColumnOrder(order);
-	}
-
-	public void setFont(Font font) {
-		tree.setFont(font);
-	}
-
-	public void setHeaderVisible(boolean show) {
-		tree.setHeaderVisible(show);
-	}
-
-	public void setRedraw(boolean redraw) {
-		tree.setRedraw(redraw);
-	}
-
-	public void setSelection(TableItemOrTreeItem item) {
-		tree.setSelection((TreeItem) item.getItem());
-	}
-
-	public void setSelection(TableItemOrTreeItem[] items) {
-		tree.setSelection(toTreeItemArray(items));
-	}
-
-	public void setSortColumn(TableColumnOrTreeColumn column) {
-		tree.setSortColumn(column == null ? null : (TreeColumn) column.getColumn());
-	}
-
-	public void setSortDirection(int direction) {
-		tree.setSortDirection(direction);
-	}
-
-	public void setTopItem(TableItemOrTreeItem item) {
-		tree.setTopItem((TreeItem) item.getItem());
-	}
-
-	public void showColumn(TableColumnOrTreeColumn column) {
-		tree.showColumn((TreeColumn) column.getColumn());
-	}
-
-	public void showItem(TableItemOrTreeItem item) {
-		tree.showItem((TreeItem) item.getItem());
-	}
-
-	public void showSelection() {
-		tree.showSelection();
-	}
-
-	///////
-	
-	private TableItemOrTreeItem wrapOrNull(TreeItem item) {
-		if (item == null) {
-			return null;
-		}
-		return TableOrTreeUtils.getEventItem(item);
-	}
-
-	private TableItemOrTreeItem[] wrapOrNull(TreeItem[] items) {
-		if (items == null) {
-			return null;
-		}
-		TableItemOrTreeItem[] returnItems = new TableItemOrTreeItem[items.length];
-		for (int i = 0; i < returnItems.length; i++) {
-			returnItems[i] = TableOrTreeUtils.getEventItem(items[i]);
-		}
-		return returnItems;
-	}
-	
-	private TableColumnOrTreeColumn wrapOrNull(TreeColumn item) {
-		if (item == null) {
-			return null;
-		}
-		return new TreeColumnDelegate(item);
-	}
-
-	private TableColumnOrTreeColumn[] wrapOrNull(TreeColumn[] items) {
-		if (items == null) {
-			return null;
-		}
-		TableColumnOrTreeColumn[] returnItems = new TableColumnOrTreeColumn[items.length];
-		for (int i = 0; i < returnItems.length; i++) {
-			returnItems[i] = new TreeColumnDelegate(items[i]);
-		}
-		return returnItems;
-	}
-	
-	private TreeItem[] toTreeItemArray(TableItemOrTreeItem[] items) {
-		if (items == null) {
-			return null;
-		}
-		TreeItem[] returnItems = new TreeItem[items.length];
-		for (int i = 0; i < returnItems.length; i++) {
-			returnItems[i] = (TreeItem) items[i].getItem();
-		}
-		return returnItems;
-	}
-	
-	public int getTopIndex() {
-		
-		TreeItem topItem = tree.getTopItem();
-		if (topItem == null) {
-			return -1;
-		}
-		return tree.indexOf(topItem);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#getSelectionIndex()
-	public int getSelectionIndex() {
-		TreeItem[] selection = tree.getSelection();
-		if (selection == null || selection.length == 0) {
-			return -1;
-		}
-		return tree.indexOf(selection[0]);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#getSelectionIndices()
-	public int[] getSelectionIndices() {
-		TreeItem[] selection = tree.getSelection();
-		if (selection == null || selection.length == 0) {
-			return new int[0];
-		}
-		
-		int[] vals = new int[selection.length];
-		for (int i = 0; i < vals.length; i++) {
-			vals[i] = tree.indexOf(selection[i]);
-		}
-		return vals;
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#setSelection(int[])
-	public void setSelection(int[] newSelectedRowIndices) {
-		TreeItem[] items = new TreeItem[newSelectedRowIndices.length];
-		int itemCount = tree.getItemCount();
-		for (int i = 0; i < items.length; i++) {
-			if (newSelectedRowIndices[i] >= 0 && newSelectedRowIndices[i] < itemCount) {
-				items[i] = tree.getItem(newSelectedRowIndices[i]);
-			}
-		}
-		tree.setSelection(items);
-	}
-
-	// @see org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT#select(int[])
-	public void select(int[] newSelectedRowIndices) {
-		for (int i : newSelectedRowIndices) {
-			if (i >= 0) {
-				tree.select(tree.getItem(i));
-			}
-		}
-	}
-
-	public boolean isSelected(TableItemOrTreeItem item) {
-		TreeItem[] selection = tree.getSelection();
-		for (TreeItem treeItem : selection) {
-			if (treeItem == item.getItem()) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	public boolean equalsTableOrTree(TableOrTreeSWT tt) {
-		return tree.equals(tt.getComposite());
-	}
-
-	public TableItemOrTreeItem createNewItem(int style) {
-		return TableOrTreeUtils.createNewItem(this, style);
-	}
-
-  public TableColumnOrTreeColumn createNewColumn(int style) {
-  	return  new TreeColumnDelegate(this, style);
-  }
-  
-  public int indexOf(Widget item) {
-  	if (item instanceof TreeItem) {
-  		return tree.indexOf((TreeItem) item);
-  	}
-  	return -1;
-  }
-}
-
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TreeItemDelegate.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TreeItemDelegate.java
deleted file mode 100644
index 8a23e13..0000000
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/impl/TreeItemDelegate.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/**
- * Created on May 3, 2010
- *
- * 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.impl;
-
-import java.util.Map;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.widgets.*;
-
-import org.gudy.azureus2.core3.util.LightHashMap;
-import org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem;
-import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;
-
-/**
- * @author TuxPaper
- * @created May 3, 2010
- *
- */
-public class TreeItemDelegate implements TableItemOrTreeItem
-{
-	TreeItem item;
-
-	Map data = new LightHashMap(2);
-
-	int index = -1;
-
-	protected TreeItemDelegate(TreeItem treeItem) {
-		this.item = treeItem;
-	}
-
-	protected TreeItemDelegate(TableOrTreeSWT tree, int style) {
-		item = new TreeItem((Tree) tree.getComposite(), style);
-	}
-
-	public void addListener(int eventType, Listener listener) {
-		item.addListener(eventType, listener);
-	}
-
-	public void addDisposeListener(DisposeListener listener) {
-		item.addDisposeListener(listener);
-	}
-
-	public void clear(int index, boolean all) {
-		item.clear(index, all);
-	}
-
-	public void clearAll(boolean all) {
-		item.clearAll(all);
-	}
-
-	public void dispose() {
-		item.dispose();
-	}
-
-	public boolean equals(Object obj) {
-		if (obj instanceof TableItemOrTreeItem) {
-			return item.equals(((TableItemOrTreeItem) obj).getItem());
-		}
-		return item.equals(obj);
-	}
-
-	public Color getBackground() {
-		return item.getBackground();
-	}
-
-	public Color getBackground(int index) {
-		return item.getBackground(index);
-	}
-
-	public Rectangle getBounds() {
-		return item.getBounds();
-	}
-
-	public Rectangle getBounds(int index) {
-		return item.getBounds(index);
-	}
-
-	public Object getData() {
-		return getData(null);
-	}
-	
-	public Object getData(String key) {
-		synchronized (data) {
-			return data.get(key);
-		}
-	}
-
-	public Display getDisplay() {
-		return item.getDisplay();
-	}
-
-	public boolean getChecked() {
-		return item.getChecked();
-	}
-
-	public Listener[] getListeners(int eventType) {
-		return item.getListeners(eventType);
-	}
-
-	public boolean getExpanded() {
-		return item.getExpanded();
-	}
-
-	public int getStyle() {
-		return item.getStyle();
-	}
-
-	public Font getFont() {
-		return item.getFont();
-	}
-
-	public Font getFont(int index) {
-		return item.getFont(index);
-	}
-
-	public Color getForeground() {
-		return item.getForeground();
-	}
-
-	public Color getForeground(int index) {
-		return item.getForeground(index);
-	}
-
-	public boolean getGrayed() {
-		return item.getGrayed();
-	}
-
-	public void notifyListeners(int eventType, Event event) {
-		item.notifyListeners(eventType, event);
-	}
-
-	public TableItemOrTreeItem getItem(int index) {
-		TreeItem treeItem = item.getItem(index);
-		return TableOrTreeUtils.getEventItem(treeItem);
-	}
-
-	public int getItemCount() {
-		return item.getItemCount();
-	}
-
-	public TableItemOrTreeItem[] getItems() {
-		TreeItem[] items = item.getItems();
-		TableItemOrTreeItem[] returnItems = new TableItemOrTreeItem[items.length];
-		for (int i = 0; i < returnItems.length; i++) {
-			returnItems[i] = TableOrTreeUtils.getEventItem(items[i]);
-		}
-		return returnItems;
-	}
-
-	public Image getImage() {
-		return item.getImage();
-	}
-
-	public Image getImage(int index) {
-		return item.getImage(index);
-	}
-
-	public Rectangle getImageBounds(int index) {
-		return item.getImageBounds(index);
-	}
-
-	public void removeListener(int eventType, Listener listener) {
-		item.removeListener(eventType, listener);
-	}
-
-	public TableOrTreeSWT getParent() {
-		return TableOrTreeUtils.getTableOrTreeSWT(item.getParent());
-	}
-
-	public TableItemOrTreeItem getParentItem() {
-		TreeItem treeItem = item.getParentItem();
-		return TableOrTreeUtils.getEventItem(treeItem);
-	}
-
-	public String getText() {
-		return item.getText();
-	}
-
-	public String getText(int index) {
-		return item.getText(index);
-	}
-
-	public void removeDisposeListener(DisposeListener listener) {
-		item.removeDisposeListener(listener);
-	}
-
-	public Rectangle getTextBounds(int index) {
-		return item.getTextBounds(index);
-	}
-
-	public int hashCode() {
-		return item.hashCode();
-	}
-
-	public boolean isDisposed() {
-		return item.isDisposed();
-	}
-
-	public boolean isListening(int eventType) {
-		return item.isListening(eventType);
-	}
-
-	public int indexOf(TableItemOrTreeItem item2) {
-		return item.indexOf((TreeItem) item2.getItem());
-	}
-
-	public void removeAll() {
-		item.removeAll();
-	}
-
-	public void setBackground(Color color) {
-		item.setBackground(color);
-	}
-
-	public void setBackground(int index, Color color) {
-		item.setBackground(index, color);
-	}
-
-	public void setData(Object data) {
-		setData(null, data);
-	}
-	
-	public void setData(String key, Object value) {
-		synchronized (data) {
-			data.put(key, value);
-		}
-	}
-
-	public void setChecked(boolean checked) {
-		item.setChecked(checked);
-	}
-
-	private Boolean settingExpandTo = null;
-	public void setExpanded(boolean expanded) {
-		boolean wasExpanded = item.getExpanded();
-		item.setExpanded(expanded);
-		if (expanded != wasExpanded && (settingExpandTo == null || settingExpandTo != expanded)) {
-			try {
-				settingExpandTo = expanded;
-  			Event event = new Event();
-  			event.widget = item.getParent();
-  			event.item = item;
-  			event.type = expanded ? SWT.Expand : SWT.Collapse;
-  			item.getParent().notifyListeners(event.type, event);
-			} finally {
-				settingExpandTo = null;
-			}
-		}
-	}
-
-	public void setFont(Font font) {
-		item.setFont(font);
-	}
-
-	public String toString() {
-		return item.toString();
-	}
-
-	public void setFont(int index, Font font) {
-		item.setFont(index, font);
-	}
-
-	public void setForeground(Color color) {
-		item.setForeground(color);
-	}
-
-	public void setForeground(int index, Color color) {
-		item.setForeground(index, color);
-	}
-
-	public void setGrayed(boolean grayed) {
-		item.setGrayed(grayed);
-	}
-
-	public void setImage(Image[] images) {
-		item.setImage(images);
-	}
-
-	public void setImage(int index, Image image) {
-		item.setImage(index, image);
-	}
-
-	public void setImage(Image image) {
-		item.setImage(image);
-	}
-
-	public void setItemCount(int count) {
-		item.setItemCount(count);
-	}
-
-	public void setText(String[] strings) {
-		item.setText(strings);
-	}
-
-	public void setText(int index, String string) {
-		item.setText(index, string);
-	}
-
-	public void setText(String string) {
-		item.setText(string);
-	}
-
-	//////
-	
-	public Item getItem() {
-		return item;
-	}
-
-	protected int getStoredIndex() {
-		return index;
-	}
-	
-	protected void setStoredIndex(int i) {
-		index = i;
-	}
-}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableCellPainted.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableCellPainted.java
index 3692919..560bd44 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableCellPainted.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableCellPainted.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table.painted;
 
 import org.eclipse.swt.graphics.*;
@@ -156,6 +174,9 @@ public class TableCellPainted
 	 */
 	public int getHeight() {
 		if (bounds == null) {
+			if (tableRow == null) {
+				return 20; // probably disposed
+			}
 			return tableRow.getView().getRowDefaultHeight();
 		}
 		return bounds.height - (getMarginHeight() * 2);
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableRowPainted.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableRowPainted.java
index c703096..992b66f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableRowPainted.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableRowPainted.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table.painted;
 
 import java.util.LinkedHashMap;
@@ -155,7 +173,7 @@ public class TableRowPainted
 	 * @param pos
 	 */
 	public void swt_paintGC(GC gc, Rectangle drawBounds, int rowStartX,
-			int rowStartY, int pos) {
+			int rowStartY, int pos, boolean isTableSelected, boolean isTableEnabled) {
 		if (isRowDisposed() || gc == null || gc.isDisposed() || drawBounds == null) {
 			return;
 		}
@@ -170,43 +188,57 @@ public class TableRowPainted
 		}
 
 		boolean isSelected = isSelected();
-		boolean isSelectedNotFocused = isSelected && !getViewPainted().isTableSelected();
+		boolean isSelectedNotFocused = isSelected && !isTableSelected;
 		
 		Color origBG = gc.getBackground();
 		Color origFG = gc.getForeground();
-		
-		Color altColor = alternatingColors[pos >= 0 ? pos % 2 : 0];
-		if (altColor == null) {
-			altColor = gc.getDevice().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
-		}
-		if (isSelected) {
-			Color color;
-			color = gc.getDevice().getSystemColor(SWT.COLOR_LIST_SELECTION);
-			gc.setBackground(color);
-		} else {
-			gc.setBackground(altColor);
-		}
 
-		Color bg = getBackground();
-		if (bg == null) {
-			bg = gc.getBackground();
-		} else {
-			gc.setBackground(bg);
-		}
 		Color fg = getForeground();
 		Color shadowColor = null;
-		if (isSelected) {
-			shadowColor = fg;
-			fg = gc.getDevice().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
-			gc.setForeground(fg);
+
+		Color altColor;
+		Color bg;
+		if (isTableEnabled) {
+  		altColor = alternatingColors[pos >= 0 ? pos % 2 : 0];
+  		if (altColor == null) {
+  			altColor = gc.getDevice().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+  		}
+  		if (isSelected) {
+  			Color color;
+  			color = gc.getDevice().getSystemColor(SWT.COLOR_LIST_SELECTION);
+  			gc.setBackground(color);
+  		} else {
+  			gc.setBackground(altColor);
+  		}
+  
+  		bg = getBackground();
+  		if (bg == null) {
+  			bg = gc.getBackground();
+  		} else {
+  			gc.setBackground(bg);
+  		}
+
+  		if (isSelected) {
+  			shadowColor = fg;
+  			fg = gc.getDevice().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
+  		} else {
+  			if (fg == null) {
+  				fg = gc.getDevice().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+  			}
+  		}
 		} else {
-	  		if (fg == null) {
-				fg = gc.getDevice().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
-				gc.setForeground(fg);
-	  		} else {
-	  			gc.setForeground(fg);
-	  		}
+			Device device = gc.getDevice();
+			altColor = device.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
+			if (isSelected) {
+				bg = device.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
+			} else {
+				bg = altColor;
+			}
+			gc.setBackground(bg);
+
+			fg = device.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
 		}
+		gc.setForeground(fg);
 
 		int rowAlpha = getAlpha();
 		Font font = gc.getFont();
@@ -316,7 +348,7 @@ public class TableRowPainted
 		if (isFocused()) {
 			gc.setAlpha(40);
 			gc.setForeground(origFG);
-			gc.setLineStyle(SWT.LINE_DOT);
+			gc.setLineDash(new int[] { 1, 2 });
 			gc.drawRectangle(0, rowStartY,
 					getViewPainted().getClientArea().width - 1, getHeight() - 1);
 			gc.setLineStyle(SWT.LINE_SOLID);
@@ -809,42 +841,44 @@ public class TableRowPainted
 
 	@Override
 	public void setExpanded(boolean b) {
-		int oldHeight = getFullHeight();
-		super.setExpanded(b);
-		synchronized (subRows_sync) {
-			TableRowPainted[] newSubRows = null;
-			if (b && (subRows == null || subRows.length != numSubItems)
-					&& subDataSources != null && subDataSources.length == numSubItems) {
-				if (DEBUG_SUBS) {
-					debug("building subrows " + numSubItems);
+		if ( canExpand() ){
+			int oldHeight = getFullHeight();
+			super.setExpanded(b);
+			synchronized (subRows_sync) {
+				TableRowPainted[] newSubRows = null;
+				if (b && (subRows == null || subRows.length != numSubItems)
+						&& subDataSources != null && subDataSources.length == numSubItems) {
+					if (DEBUG_SUBS) {
+						debug("building subrows " + numSubItems);
+					}
+	
+					deleteExistingSubRows();
+					newSubRows = new TableRowPainted[numSubItems];
+					TableViewPainted tv = getViewPainted();
+					int h = 0;
+					for (int i = 0; i < newSubRows.length; i++) {
+						newSubRows[i] = new TableRowPainted(this, tv, subDataSources[i],
+								false);
+						newSubRows[i].setTableItem(i, false);
+						h += newSubRows[i].getHeight();
+					}
+	
+					subRowsHeight = h;
+	
+					subRows = newSubRows;
 				}
-
-				deleteExistingSubRows();
-				newSubRows = new TableRowPainted[numSubItems];
-				TableViewPainted tv = getViewPainted();
-				int h = 0;
-				for (int i = 0; i < newSubRows.length; i++) {
-					newSubRows[i] = new TableRowPainted(this, tv, subDataSources[i],
-							false);
-					newSubRows[i].setTableItem(i, false);
-					h += newSubRows[i].getHeight();
+	
+				getViewPainted().rowHeightChanged(this, oldHeight, getFullHeight());
+	
+				if (newSubRows != null) {
+					getViewPainted().triggerListenerRowAdded(newSubRows);
 				}
-
-				subRowsHeight = h;
-
-				subRows = newSubRows;
+	
 			}
-
-			getViewPainted().rowHeightChanged(this, oldHeight, getFullHeight());
-
-			if (newSubRows != null) {
-				getViewPainted().triggerListenerRowAdded(newSubRows);
+			if (isVisible()) {
+				getViewPainted().visibleRowsChanged();
+				getViewPainted().redrawTable();
 			}
-
-		}
-		if (isVisible()) {
-			getViewPainted().visibleRowsChanged();
-			getViewPainted().redrawTable();
 		}
 	}
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableViewPainted.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableViewPainted.java
index 9eda8ab..d86f7e6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableViewPainted.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/painted/TableViewPainted.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.table.painted;
 
 import java.util.*;
@@ -23,6 +41,7 @@ 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.mainwindow.HSLColor;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
 import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
@@ -38,6 +57,7 @@ import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentListener;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+import com.aelitis.azureus.ui.swt.mdi.MdiEntrySWT;
 import com.aelitis.azureus.ui.swt.utils.FontUtils;
 
 /**
@@ -266,8 +286,9 @@ public class TableViewPainted
 							if (select) {
 								rowToSelect.setSelected(select);
 							} else {
-								focusedRow.setSelected(false);
+								TableRowPainted rowToUnSelect = focusedRow;
 								setFocusedRow(rowToSelect);
+								rowToUnSelect.setSelected(false);
 							}
 							updateTable = true;
 						}
@@ -305,7 +326,9 @@ public class TableViewPainted
 						row = getRow(0);
 					}
 					if ((event.stateMask & SWT.SHIFT) != 0) {
-						selectRowsTo(row);
+						if ( row != null ){
+							selectRowsTo(row);
+						}
 					} else if (event.stateMask == 0) {
   					setSelectedRows(new TableRowCore[] {
   						row
@@ -346,8 +369,9 @@ public class TableViewPainted
   							if (select) {
   								rowToSelect.setSelected(select);
   							} else {
-  								focusedRow.setSelected(false);
+  								TableRowPainted rowToUnSelect = focusedRow;
   								setFocusedRow(rowToSelect);
+  								rowToUnSelect.setSelected(false);
   							}
   						} else {
   							setSelectedRows(new TableRowCore[] {
@@ -769,6 +793,8 @@ public class TableViewPainted
 			public void runSupport() {
 				if (!isDisposed()) {
 					cTable.setEnabled(enable);
+					cHeaderArea.setEnabled(enable);
+					cHeaderArea.redraw();
 				}
 			}
 		});
@@ -1003,7 +1029,10 @@ public class TableViewPainted
 	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#initialize(org.eclipse.swt.widgets.Composite)
 	 */
 	public void initialize(Composite parent) {
-		tvTabsCommon = new TableViewSWT_TabsCommon(this);
+		initialize( null, parent );
+	}
+	public void initialize(UISWTView parentView, Composite parent) {
+		tvTabsCommon = new TableViewSWT_TabsCommon(parentView,this);
 
 		shell = parent.getShell();
 		mainComposite = tvTabsCommon.createSashForm(parent);
@@ -1208,6 +1237,7 @@ public class TableViewPainted
 		// and column widths, etc
 		TableStructureEventDispatcher.getInstance(tableID).addListener(this);
 
+		MessageText.addListener(this);
 	}
 
 	protected void swt_vBarChanged() {
@@ -1479,6 +1509,8 @@ public class TableViewPainted
 		int pos = -1;
 		Set<TableRowPainted> visibleRows = this.visibleRows;
 		
+		boolean isTableSelected = isTableSelected();
+		boolean isTableEnabled = cTable.isEnabled();
 		for (TableRowPainted row : visibleRows) {
 			TableRowPainted paintedRow = row;
 			if (pos == -1) {
@@ -1498,7 +1530,8 @@ public class TableViewPainted
 					drawBounds.height += diffY2; 
 					gc.setClipping(drawBounds);
 				}
-				paintedRow.swt_paintGC(gc, drawBounds, rowStartX, rowStartY, pos);
+				paintedRow.swt_paintGC(gc, drawBounds, rowStartX, rowStartY, pos,
+						isTableSelected, isTableEnabled);
 			}
 			oldRow = row;
 		}
@@ -1515,7 +1548,7 @@ public class TableViewPainted
 		}
 		if (h > 0) {
 			int rowHeight = getRowDefaultHeight();
-			if (extendedErase) {
+			if (extendedErase && cTable.isEnabled()) {
 				while (yDirty < end) {
 					pos++;
 					Color color = TableRowPainted.alternatingColors[pos % 2];
@@ -1530,8 +1563,8 @@ public class TableViewPainted
 					yDirty += rowHeight;
 				}
 			} else {
-				gc.setBackground(gc.getDevice().getSystemColor(
-						SWT.COLOR_LIST_BACKGROUND));
+				gc.setBackground(gc.getDevice().getSystemColor(cTable.isEnabled() ?
+						SWT.COLOR_LIST_BACKGROUND : SWT.COLOR_WIDGET_BACKGROUND));
 				gc.fillRectangle(drawBounds.x, yDirty, drawBounds.width, h);
 			}
 		}
@@ -1573,11 +1606,19 @@ public class TableViewPainted
 	private void paintHeader(PaintEvent e) {
 
 		Rectangle ca = cHeaderArea.getClientArea();
-		Color c1 = e.display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
-		Color c2 = e.display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
-		Color line = c2;
-		Color fg = e.display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+		Color c1, c2, fg;
 
+		if (cTable.isEnabled()) {
+  		c1 = e.display.getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+  		c2 = e.display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
+  		fg = e.display.getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+		} else {
+			c1 = e.display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
+			c2 = e.display.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
+			fg = e.display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+		}
+
+		Color line = c2;
 		
 		Pattern patternUp = new Pattern(e.display, 0, 0, 0, ca.height, c1, c2);
 		Pattern patternDown = new Pattern(e.display, 0, -ca.height , 0, 0, c2, c1);
@@ -1884,6 +1925,14 @@ public class TableViewPainted
 		refilter();
 	}
 	
+	public Text 
+	getFilterControl()
+	{
+		TableViewSWTFilter<?> filter = getSWTFilter();
+		
+		return( filter==null?null:filter.widget );
+	}
+	
 	public void disableFilterCheck() {
 		TableViewSWTFilter<?> filter = getSWTFilter();
 		if ( filter == null ){
@@ -1977,13 +2026,6 @@ public class TableViewPainted
 	}
 
 	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#getTableOrTreeSWT()
-	 */
-	public TableOrTreeSWT getTableOrTreeSWT() {
-		return null;
-	}
-
-	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#packColumns()
 	 */
 	public void packColumns() {
@@ -2453,6 +2495,9 @@ public class TableViewPainted
 		return clientArea;
 	}
 
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.ui.swt.views.table.TableViewSWT#isVisible()
+	 */
 	public boolean isVisible() {
 		if (!Utils.isThisThreadSWT()) {
 			return isVisible;
@@ -2462,13 +2507,13 @@ public class TableViewPainted
 				&& !shell.getMinimized();
 		if (isVisible != wasVisible) {
 			visibleRowsChanged();
-			UISWTViewCore view = tvTabsCommon == null ? null
+			MdiEntrySWT view = tvTabsCommon == null ? null
 					: tvTabsCommon.getActiveSubView();
 			if (isVisible) {
 				loopFactor = 0;
 
 				if (view != null) {
-					view.triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
+					view.getMDI().showEntry(view);
 				}
 			} else {
 				if (view != null) {
@@ -2671,9 +2716,9 @@ public class TableViewPainted
 	}
 
 	@Override
-	public void triggerTabViewsDataSourceChanged(boolean sendParent) {
+	public void triggerTabViewsDataSourceChanged() {
 		if (tvTabsCommon != null) {
-			tvTabsCommon.triggerTabViewsDataSourceChanged(sendParent);
+			tvTabsCommon.triggerTabViewsDataSourceChanged(this);
 		}
 	}
 	
@@ -2717,6 +2762,10 @@ public class TableViewPainted
 			cTable
 		});
 		cTable = null;
+		
+		if (filter != null) {
+			disableFilterCheck();
+		}
 
 		removeAllTableRows();
 		configMan.removeParameterListener("ReOrder Delay", this);
@@ -2752,7 +2801,14 @@ public class TableViewPainted
 					menu.setData("isHeader", true);
 
 				} else {
-					boolean noRow = getTableRowWithCursor() == null;
+					TableRowCore row = getTableRowWithCursor();
+					boolean noRow = row == null;
+
+					// If shell is not active, right clicking on a row will
+					// result in a MenuDetect, but not a MouseDown or MouseUp
+					if (!isSelected(row)) {
+						setSelectedRows(new TableRowCore[] { row });
+					}
 
 					menu.setData("inBlankArea", noRow);
 					menu.setData("isHeader", false);
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnCreator.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnCreator.java
index 8e77d94..880f678 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnCreator.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnCreator.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.table.utils;
@@ -175,6 +172,7 @@ public class TableColumnCreator
 		c.put(RankItem.COLUMN_ID, new cInfo(RankItem.class, RankItem.DATASOURCE_TYPE));
 		c.put(NameItem.COLUMN_ID, new cInfo(NameItem.class, NameItem.DATASOURCE_TYPE));
 		c.put(SizeItem.COLUMN_ID, new cInfo(SizeItem.class, SizeItem.DATASOURCE_TYPE));
+		c.put(ColumnSizeWithDND.COLUMN_ID, new cInfo(ColumnSizeWithDND.class, ColumnSizeWithDND.DATASOURCE_TYPE));
 		c.put(DoneItem.COLUMN_ID, new cInfo(DoneItem.class, DoneItem.DATASOURCE_TYPE));
 		c.put(StatusItem.COLUMN_ID, new cInfo(StatusItem.class, StatusItem.DATASOURCE_TYPE));
 		c.put(ETAItem.COLUMN_ID, new cInfo(ETAItem.class, ETAItem.DATASOURCE_TYPE));
@@ -224,7 +222,9 @@ public class TableColumnCreator
 		c.put(ColumnTorrentSpeed.COLUMN_ID, new cInfo(ColumnTorrentSpeed.class, ColumnTorrentSpeed.DATASOURCE_TYPE));
 
 		c.put(DateCompletedItem.COLUMN_ID, new cInfo(DateCompletedItem.class, DateCompletedItem.DATASOURCE_TYPE));
+		c.put(DateFileCompletedItem.COLUMN_ID, new cInfo(DateFileCompletedItem.class, DateFileCompletedItem.DATASOURCE_TYPE));
 		c.put(DateAddedItem.COLUMN_ID, new cInfo(DateAddedItem.class, DateAddedItem.DATASOURCE_TYPE));
+		c.put(DateLastActiveItem.COLUMN_ID, new cInfo(DateLastActiveItem.class, DateLastActiveItem.DATASOURCE_TYPE));
 		c.put(IPFilterItem.COLUMN_ID, new cInfo(IPFilterItem.class, IPFilterItem.DATASOURCE_TYPE));
 		c.put(AlertsItem.COLUMN_ID, new cInfo(AlertsItem.class, AlertsItem.DATASOURCE_TYPE));
 		c.put(TorrentCreateDateItem.COLUMN_ID, new cInfo(TorrentCreateDateItem.class, TorrentCreateDateItem.DATASOURCE_TYPE));
@@ -243,6 +243,7 @@ public class TableColumnCreator
 
 		c.put(SessionUpItem.COLUMN_ID, new cInfo(SessionUpItem.class, SessionUpItem.DATASOURCE_TYPE));
 		c.put(SessionDownItem.COLUMN_ID, new cInfo(SessionDownItem.class, SessionDownItem.DATASOURCE_TYPE));
+		c.put(MergedDataItem.COLUMN_ID, new cInfo(MergedDataItem.class, MergedDataItem.DATASOURCE_TYPE));
 
 		// Core columns are implementors of TableColumn to save one class creation
 		// Otherwise, we'd have to create a generic TableColumnImpl class, pass it 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnSWTUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnSWTUtils.java
index 0167492..8715772 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnSWTUtils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableColumnSWTUtils.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.table.utils;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableContextMenuManager.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableContextMenuManager.java
index 1d67bf2..4d55ac5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableContextMenuManager.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/table/utils/TableContextMenuManager.java
@@ -2,11 +2,12 @@
  * File    : TableContextMenuManager.java
  * Created : 2004/May/16
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.table.utils;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/ColumnDateSizer.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/ColumnDateSizer.java
index 949091b..c9a5f65 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/ColumnDateSizer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/ColumnDateSizer.java
@@ -1,10 +1,12 @@
 /**
  * Created on Oct 5, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -73,8 +75,8 @@ public abstract class ColumnDateSizer
 	 * @param name
 	 * @param tableID
 	 */
-	public ColumnDateSizer(Class forDataSrouceType, String columnID, int width, String tableID) {
-		super(forDataSrouceType, columnID, ALIGN_TRAIL, width, tableID);
+	public ColumnDateSizer(Class forDataSourceType, String columnID, int width, String tableID) {
+		super(forDataSourceType, columnID, ALIGN_TRAIL, width, tableID);
 
 		final TableContextMenuItem menuShowTime = addContextMenuItem(
 				"TableColumn.menu.date_added.time", MENU_STYLE_HEADER);
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/archivedfiles/NameItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/archivedfiles/NameItem.java
new file mode 100644
index 0000000..1d63276
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/archivedfiles/NameItem.java
@@ -0,0 +1,103 @@
+/**
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.views.tableitems.archivedfiles;
+
+import java.io.File;
+
+import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText;
+import org.gudy.azureus2.ui.swt.views.ArchivedFilesView;
+import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.download.DownloadStub.DownloadStubFile;
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+
+
+public class 
+NameItem 
+	extends CoreTableColumnSWT 
+	implements TableCellLightRefreshListener, ObfusticateCellText
+{
+	public 
+	NameItem(
+		String tableID )
+	{
+		super(	"name", ALIGN_LEAD, POSITION_LAST, 400, tableID );
+		
+		setType(TableColumn.TYPE_TEXT);
+	}
+
+	public void 
+	fillTableColumnInfo(
+		TableColumnInfo info )
+	{
+		info.addCategories(new String[] {
+			CAT_CONTENT,
+		});
+		
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+	
+	public void 
+	refresh(
+		TableCell 	cell, 
+		boolean 	sortOnlyRefresh)
+	{
+		DownloadStubFile fileInfo = (DownloadStubFile) cell.getDataSource();
+		
+		String name;
+		
+		if ( fileInfo == null ){
+			
+			name = "";
+			
+		}else{
+			
+			File f = fileInfo.getFile();
+			
+			if ( ArchivedFilesView.show_full_path ){
+				
+				name = f.getAbsolutePath();
+			}else{
+				
+				name = f.getName();
+			}
+		}
+		
+		cell.setText(name);
+	}
+
+	public void 
+	refresh(
+		TableCell cell )
+	{
+		refresh(cell, false);
+	}
+
+	public String 
+	getObfusticatedText(
+		TableCell cell) 
+	{
+		DownloadStubFile fileInfo = (DownloadStubFile) cell.getDataSource();
+		
+		String name = (fileInfo == null) ? "" : Debug.secretFileName(fileInfo.getFile().getName());
+		
+		return( name );
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/archivedfiles/SizeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/archivedfiles/SizeItem.java
new file mode 100644
index 0000000..81aa693
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/archivedfiles/SizeItem.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.views.tableitems.archivedfiles;
+
+
+import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.plugins.download.DownloadStub.DownloadStubFile;
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+
+
+public class 
+SizeItem 
+	extends CoreTableColumnSWT 
+	implements TableCellLightRefreshListener
+{
+	public 
+	SizeItem(
+		String tableID )
+	{
+		super( "size", ALIGN_TRAIL, POSITION_LAST, 70, tableID );
+		
+		 setMinWidthAuto(true);
+	}
+
+	public void 
+	fillTableColumnInfo(
+		TableColumnInfo info )
+	{
+		info.addCategories(new String[] {
+			CAT_BYTES,
+		});
+		
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+	
+	public void 
+	refresh(
+		TableCell 	cell, 
+		boolean 	sortOnlyRefresh)
+	{
+		DownloadStubFile fileInfo = (DownloadStubFile) cell.getDataSource();
+		
+		long size;
+		
+		if ( fileInfo == null ){
+			
+			size = 0;
+			
+		}else{
+			
+			size = fileInfo.getLength();
+		}
+		
+		if( !cell.setSortValue( size ) && cell.isValid()){
+			
+			return;
+		}
+
+		if ( size < 0 ){
+			
+				// skipped
+			
+			cell.setText( "(" + DisplayFormatters.formatByteCountToKiBEtc(-size) + ")");
+			
+		}else{
+			
+			cell.setText(DisplayFormatters.formatByteCountToKiBEtc(size));
+		}
+	}
+
+	public void 
+	refresh(
+		TableCell cell )
+	{
+		refresh(cell, false);
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/DoneItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/DoneItem.java
index 9016904..39a4cb9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/DoneItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/DoneItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileAvailabilityItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileAvailabilityItem.java
index b30d689..c78425c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileAvailabilityItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileAvailabilityItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileCRC32Item.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileCRC32Item.java
index 287199a..16ed3ee 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileCRC32Item.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileCRC32Item.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileETAItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileETAItem.java
index 7d2a694..6d79878 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileETAItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileETAItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileExtensionItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileExtensionItem.java
index 19b9a82..8d02b89 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileExtensionItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileExtensionItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileHashItemBase.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileHashItemBase.java
index c779698..ec79d26 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileHashItemBase.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileHashItemBase.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.files;
@@ -60,6 +58,7 @@ FileHashItemBase
 {	
 	protected static final String	HT_CRC32	= "crc32";
 	protected static final String	HT_MD5		= "md5";
+	protected static final String	HT_SHA1		= "sha1";
 	
 	final String				hash_type;
 	final TableContextMenuItem 	menuItem;
@@ -91,7 +90,10 @@ FileHashItemBase
 					Object[]	files = (Object[])target;
 					
 					for ( Object _file: files ){
-						
+
+						if (_file instanceof TableRow) {
+							_file = ((TableRow)_file).getDataSource();
+						}
 						DiskManagerFileInfo file = (DiskManagerFileInfo)_file;
 						
 						updateHash( hash_type, file );
@@ -258,16 +260,21 @@ FileHashItemBase
 						File f = file.getFile( true );
 						
 						CRC32 			crc32 	= null;
-						MessageDigest	md5		= null;
+						MessageDigest	md		= null;
 						
 						if ( hash_type == HT_CRC32 ){
 							
 							crc32 = new CRC32();
 							
+						}else if ( hash_type == HT_MD5 ){
+							
+							md = MessageDigest.getInstance( "md5" );
+						
 						}else{
 							
-							md5 = MessageDigest.getInstance( "md5" );
-						}
+							md = MessageDigest.getInstance( "SHA1" );
+
+						}	
 						
 						FileInputStream fis = new FileInputStream( f );
 						
@@ -296,9 +303,9 @@ FileHashItemBase
 									crc32.update( buffer, 0, len );
 								}
 								
-								if ( md5 != null ){
+								if ( md != null ){
 									
-									md5.update( buffer, 0, len );
+									md.update( buffer, 0, len );
 								}
 								
 								done += len;
@@ -316,7 +323,7 @@ FileHashItemBase
 								
 							}else{
 								
-								hash = md5.digest();
+								hash = md.digest();
 							}
 							
 							Map other_hashes = dm.getDownloadState().getMapAttribute( DownloadManagerState.AT_FILE_OTHER_HASHES );
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileIndexItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileIndexItem.java
index 8d9aeac..3c0d033 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileIndexItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileIndexItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileMD5Item.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileMD5Item.java
index 399f366..1399e3d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileMD5Item.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileMD5Item.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileReadSpeedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileReadSpeedItem.java
index 04f4263..06ebf2e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileReadSpeedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileReadSpeedItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileSHA1Item.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileSHA1Item.java
new file mode 100644
index 0000000..17227ea
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileSHA1Item.java
@@ -0,0 +1,34 @@
+/*
+ * File    : NameItem.java
+ * Created : 24 nov. 2003
+ * By      : Olivier
+ *
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.tableitems.files;
+
+public class 
+FileSHA1Item
+	extends FileHashItemBase 
+{	
+	public 
+	FileSHA1Item() 
+	{	
+		super( HT_SHA1, 220 );
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileWriteSpeedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileWriteSpeedItem.java
index b7631bd..d8a702e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileWriteSpeedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FileWriteSpeedItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FirstPieceItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FirstPieceItem.java
index 3ecfff4..63e7bdb 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FirstPieceItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/FirstPieceItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/ModeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/ModeItem.java
index cc2074d..545ff7e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/ModeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/ModeItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/NameItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/NameItem.java
index 1c4786d..1ac1d9a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/NameItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/NameItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.files;
@@ -76,7 +74,7 @@ public class NameItem extends CoreTableColumnSWT implements
 				TableManager.TABLE_TORRENT_FILES);
 		setInplaceEditorListener(this);
 		setType(TableColumn.TYPE_TEXT);
-		menuItem = addContextMenuItem("FilesView.name.fastRename");
+		menuItem = addContextMenuItem("FilesView.name.fastRename", MENU_STYLE_HEADER);
 		
 		menuItem.setStyle(MenuItem.STYLE_CHECK);
 		//menuItem.setText(MessageText.getString("FilesView.name.fastRename")); TODO make this work
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PathItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PathItem.java
index 5f7beaf..f1493fd 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PathItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PathItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PercentItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PercentItem.java
index 33a4087..36aa3f7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PercentItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PercentItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PieceCountItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PieceCountItem.java
index e1fe790..dce1a4a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PieceCountItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PieceCountItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PriorityItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PriorityItem.java
index dee76e3..6a56bc8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PriorityItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/PriorityItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/ProgressGraphItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/ProgressGraphItem.java
index f962ca1..9dd0a27 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/ProgressGraphItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/ProgressGraphItem.java
@@ -1,7 +1,7 @@
 /*
  * File : CompletionItem.java Created : 24 nov. 2003 By : Olivier
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.tableitems.files;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/RemainingPiecesItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/RemainingPiecesItem.java
index 858779e..b2a845a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/RemainingPiecesItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/RemainingPiecesItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/SizeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/SizeItem.java
index 3f07bf6..45c75b9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/SizeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/SizeItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/StorageTypeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/StorageTypeItem.java
index 9f5a3bf..2a1fce9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/StorageTypeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/StorageTypeItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/TorrentRelativePathItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/TorrentRelativePathItem.java
index ae4b30d..2e2346a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/TorrentRelativePathItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/files/TorrentRelativePathItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.files;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/CategoryItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/CategoryItem.java
index 34cd205..58d7f4b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/CategoryItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/CategoryItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/NameItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/NameItem.java
index 09524c2..ff0d58a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/NameItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/NameItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.myshares;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/TypeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/TypeItem.java
index 820225e..d92fa18 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/TypeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/myshares/TypeItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.myshares;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AbstractTrackerCell.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AbstractTrackerCell.java
index 93a6939..ee4ff91 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AbstractTrackerCell.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AbstractTrackerCell.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,9 +12,6 @@
  * 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.tableitems.mytorrents;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AlertsItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AlertsItem.java
index b52bc25..314b57e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AlertsItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AlertsItem.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AvailabilityItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AvailabilityItem.java
index 2d456ba..b650390 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AvailabilityItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AvailabilityItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AvgAvailItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AvgAvailItem.java
index df80ec1..0871df1 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AvgAvailItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/AvgAvailItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/BadAvailTimeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/BadAvailTimeItem.java
index b281f30..f8bf0ad 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/BadAvailTimeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/BadAvailTimeItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-May-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CategoryItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CategoryItem.java
index 6f9ae43..73a2f7d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CategoryItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CategoryItem.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnFileCount.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnFileCount.java
index ec4f9d9..369197e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnFileCount.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnFileCount.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jan 17, 2010 2:19:53 AM
- * Copyright (C) 2010 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.tableitems.mytorrents;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnSizeWithDND.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnSizeWithDND.java
new file mode 100644
index 0000000..e7a4066
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnSizeWithDND.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.tableitems.mytorrents;
+
+import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+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;
+import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
+
+
+public class ColumnSizeWithDND
+       extends CoreTableColumnSWT 
+       implements TableCellRefreshListener
+{
+	public static final Class DATASOURCE_TYPE = Download.class;
+
+  public static final String COLUMN_ID = "sizewithdnd";
+
+	/** Default Constructor */
+  public ColumnSizeWithDND(String sTableID) {
+    super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID);
+    setRefreshInterval(INTERVAL_LIVE);
+    setMinWidthAuto(true);
+
+    setPosition(POSITION_LAST);
+  }
+
+  public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			CAT_SHARING,
+			CAT_BYTES
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_ADVANCED);
+	}
+
+  public void refresh(TableCell cell) {
+  	long value = 0;
+		Object ds = cell.getDataSource();
+		if (ds instanceof DownloadManager) {
+			DownloadManager dm = (DownloadManager) ds;
+			value = dm.getSize();
+		} else if (ds instanceof DiskManagerFileInfo) {
+			DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) ds;
+			value = fileInfo.getLength();
+		}
+
+    if (!cell.setSortValue(value) && cell.isValid())
+      return;
+
+    cell.setText(DisplayFormatters.formatByteCountToKiBEtc(value));
+  }
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnTorrentSpeed.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnTorrentSpeed.java
index f1c6a4b..e98c522 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnTorrentSpeed.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ColumnTorrentSpeed.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.tableitems.mytorrents;
 
 import org.eclipse.swt.graphics.Image;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentIconItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentIconItem.java
index 3f4816f..da28edc 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentIconItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentIconItem.java
@@ -3,11 +3,12 @@
  * Created : 14 Nov 2006
  * By      : Allan Crooks
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentItem.java
index 0671028..4e63fea 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CommentItem.java
@@ -3,11 +3,12 @@
  * Created : 26 Oct 2006
  * By      : Allan Crooks
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CompletedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CompletedItem.java
index 573304c..8524e12 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CompletedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CompletedItem.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -11,9 +11,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.tableitems.mytorrents;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CompletionItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CompletionItem.java
index eff9089..22a2fdc 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CompletionItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/CompletionItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
@@ -29,7 +27,7 @@ import java.util.Map;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.*;
-
+import org.gudy.azureus2.core3.disk.DiskManager;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.util.DisplayFormatters;
 import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
@@ -220,6 +218,7 @@ public class CompletionItem
 		if (dm == null) {
 			return 0;
 		}
-		return dm.getStats().getDownloadCompleted(true);
+
+		return dm.getStats().getPercentDoneExcludingDND();
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateAddedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateAddedItem.java
index 27e52ca..00496d8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateAddedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateAddedItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-May-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateCompletedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateCompletedItem.java
index 5a53f33..bd47112 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateCompletedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateCompletedItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-May-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateFileCompletedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateFileCompletedItem.java
new file mode 100644
index 0000000..c59df84
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateFileCompletedItem.java
@@ -0,0 +1,78 @@
+/*
+ * Created on 05-May-2006
+ * Created by Paul Gardner
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.views.tableitems.mytorrents;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator;
+import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
+
+public class DateFileCompletedItem
+	extends ColumnDateSizer
+{
+	public static final Class DATASOURCE_TYPE = Download.class;
+
+	public static final String COLUMN_ID = "DateFileCompleted";
+
+	public DateFileCompletedItem(String sTableID) {
+		super(DATASOURCE_TYPE, COLUMN_ID, TableColumnCreator.DATE_COLUMN_WIDTH, sTableID);
+		setRefreshInterval(INTERVAL_LIVE);
+		setMultiline(false);
+	}
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			CAT_TIME,
+			CAT_CONTENT,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE);
+	}
+
+	/**
+	 * @param tableID
+	 * @param b
+	 */
+	public DateFileCompletedItem(String tableID, boolean v) {
+		this(tableID);
+		setVisible(v);
+	}
+
+	public void refresh(TableCell cell, long timestamp) {
+		DownloadManager dm = (DownloadManager) cell.getDataSource();
+		long value = 0;
+		if (dm == null) {
+			return;
+		}
+		
+		value = dm.getDownloadState().getLongParameter(	DownloadManagerState.PARAM_DOWNLOAD_FILE_COMPLETED_TIME );
+
+		if ( value <= 0 ){
+			
+				// migration for old downloads, remove sometime (currently 5301)
+			
+			value = dm.getDownloadState().getLongParameter(	DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME);
+		}
+
+		super.refresh(cell, value);
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateLastActiveItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateLastActiveItem.java
new file mode 100644
index 0000000..60b106e
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DateLastActiveItem.java
@@ -0,0 +1,63 @@
+/*
+ * Created on 05-May-2006
+ * Created by Paul Gardner
+ * Copyright (C) Azureus Software, 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 org.gudy.azureus2.ui.swt.views.tableitems.mytorrents;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
+import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator;
+import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer;
+
+public class DateLastActiveItem
+	extends ColumnDateSizer
+{
+	public static final Class DATASOURCE_TYPE = Download.class;
+
+	public static final String COLUMN_ID = "DateTorrentLastActive";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] { CAT_TIME, CAT_CONTENT });
+		info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE);
+	}
+
+	public DateLastActiveItem(String sTableID) {
+		super(DATASOURCE_TYPE, COLUMN_ID, TableColumnCreator.DATE_COLUMN_WIDTH, sTableID);
+		
+		setMultiline(false);
+	}
+
+	public void refresh(TableCell cell, long timestamp) {
+		DownloadManager dm = (DownloadManager) cell.getDataSource();
+		if (dm == null) {
+			timestamp = 0;
+		} else {
+			timestamp = dm.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_LAST_ACTIVE_TIME);
+			if (timestamp == 0) {
+				timestamp = dm.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME);
+			}
+			if (timestamp == 0) {
+				timestamp = dm.getDownloadState().getLongParameter(DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME);
+			}
+		}
+		super.refresh(cell, timestamp);
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DoneItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DoneItem.java
index 742b0de..e2ab5b5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DoneItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DoneItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,15 +18,13 @@
  * 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.tableitems.mytorrents;
 
 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerStats;
 import org.gudy.azureus2.core3.util.DisplayFormatters;
 
 import org.gudy.azureus2.plugins.download.Download;
@@ -68,8 +67,10 @@ public class DoneItem
   	int value;
   	Object ds = cell.getDataSource();
   	if (ds instanceof DownloadManager) {
-  			// show amount completed of non-dnd files as makes more sense 
-  		value = ((DownloadManager) ds).getStats().getDownloadCompleted(false);
+  			// show amount completed of non-dnd files as makes more sense
+  		DownloadManager dm = (DownloadManager) ds;
+  		DownloadManagerStats stats = dm.getStats();
+  		value = stats.getPercentDoneExcludingDND();
   	} else if (ds instanceof DiskManagerFileInfo) {
   		DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) ds;
 			long length = fileInfo.getLength();
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownItem.java
index bc60c86..8b188f9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownSpeedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownSpeedItem.java
index 2ea520b..12ac5c9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownSpeedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownSpeedItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownSpeedLimitItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownSpeedLimitItem.java
index b5b01d9..a418264 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownSpeedLimitItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/DownSpeedLimitItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ETAItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ETAItem.java
index 5e6b53f..7030de1 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ETAItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ETAItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/FileExtensionItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/FileExtensionItem.java
index 1ed4433..6095df0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/FileExtensionItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/FileExtensionItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/FilesDoneItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/FilesDoneItem.java
index 762ea99..a1e39ef 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/FilesDoneItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/FilesDoneItem.java
@@ -3,11 +3,12 @@
  * Created : 01 febv. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/HealthItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/HealthItem.java
index 572fbb6..b8c0c9f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/HealthItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/HealthItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/IPFilterItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/IPFilterItem.java
index d8d1a74..744cbb7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/IPFilterItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/IPFilterItem.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
@@ -47,18 +45,13 @@ public class IPFilterItem
        extends CoreTableColumnSWT 
        implements TableCellRefreshListener
 {
-	private static final IpFilter ipfilter = IpFilterManagerFactory.getSingleton().getIPFilter();
+	private static IpFilter ipfilter = null;
 	
 	public static final Class DATASOURCE_TYPE = Download.class;
 
-	private static final UISWTGraphic tick_icon;
+	private static UISWTGraphic tick_icon;
 
-	private static final UISWTGraphic cross_icon;
-	
-	static {
-		tick_icon = new UISWTGraphicImpl(ImageLoader.getInstance().getImage("tick_mark"));
-		cross_icon = new UISWTGraphicImpl(ImageLoader.getInstance().getImage("cross_mark"));
-	}
+	private static UISWTGraphic cross_icon;
 	
   public static final String COLUMN_ID = "ipfilter";
 
@@ -82,8 +75,16 @@ public class IPFilterItem
     
     UISWTGraphic	icon 	= null;
     int				sort	= 0;
+
+    if (ipfilter == null) {
+    	ipfilter = IpFilterManagerFactory.getSingleton().getIPFilter();
+    }
     
     if( ipfilter.isEnabled()){
+    	if (tick_icon == null) {
+    		tick_icon = new UISWTGraphicImpl(ImageLoader.getInstance().getImage("tick_mark"));
+    		cross_icon = new UISWTGraphicImpl(ImageLoader.getInstance().getImage("cross_mark"));
+    	}
 	    DownloadManager dm = (DownloadManager)cell.getDataSource();
 	    if (dm != null) {
 	       boolean excluded = dm.getDownloadState().getFlag( DownloadManagerState.FLAG_DISABLE_IP_FILTER );
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MaxSRItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MaxSRItem.java
index ae5c8be..c883d1c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MaxSRItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MaxSRItem.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,21 +18,25 @@
  * 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.tableitems.mytorrents;
 
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
 import org.gudy.azureus2.plugins.ui.tables.TableCell;
 import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
 import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
+import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
+import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 
+import com.aelitis.azureus.ui.common.table.TableRowCore;
+
 /** Display Category torrent belongs to.
  *
  * @author TuxPaper
@@ -53,6 +58,96 @@ public class MaxSRItem
 	public MaxSRItem(String sTableID) {
 		super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID);
 		setRefreshInterval(INTERVAL_LIVE);
+		
+	    TableContextMenuItem menuItem = addContextMenuItem("menu.max.share.ratio2");
+	    menuItem.addMultiListener(new MenuItemListener() {
+				public void selected(MenuItem menu, Object target) {
+					if (target == null) {
+						return;
+					}
+					
+					Object[] o = (Object[]) target;
+					
+					int existing = -1;
+					
+					for (Object object : o) {
+						if (object instanceof TableRowCore) {
+							TableRowCore rowCore = (TableRowCore) object;
+							object = rowCore.getDataSource(true);
+						}
+						if (object instanceof DownloadManager) {
+							int x = ((DownloadManager)object).getDownloadState().getIntParameter( DownloadManagerState.PARAM_MAX_SHARE_RATIO );
+							
+							if ( existing == -1 ){
+								existing = x;
+							}else if ( existing != x ){
+								existing = -1;
+								break;
+							}
+						}
+					}
+					
+					String existing_text;
+					
+					if ( existing == -1 ){
+						existing_text = "";
+					}else{
+						existing_text = String.valueOf( existing/1000.0f);
+					}
+					
+					SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+							"max.sr.window.title", "max.sr.window.message");
+											
+					entryWindow.setPreenteredText( existing_text, false );
+					entryWindow.selectPreenteredText( true );
+					
+					entryWindow.prompt();
+					
+					if ( entryWindow.hasSubmittedInput()){
+						
+						try{
+							String text = entryWindow.getSubmittedInput().trim();
+							
+							int	sr = 0;
+							
+							if ( text.length() > 0 ){
+							
+								try{
+									float f = Float.parseFloat( text );
+								
+									sr = (int)(f * 1000 );
+								
+									if ( sr < 0 ){
+										
+										sr = 0;
+										
+									}else if ( sr == 0 && f > 0 ){
+										
+										sr = 1;
+									}
+								
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+								
+								for (Object object : o) {
+									if (object instanceof TableRowCore) {
+										TableRowCore rowCore = (TableRowCore) object;
+										object = rowCore.getDataSource(true);
+									}
+									if (object instanceof DownloadManager) {
+										((DownloadManager)object).getDownloadState().setIntParameter( DownloadManagerState.PARAM_MAX_SHARE_RATIO, sr );
+									}
+								}								
+							}			
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}
+				}
+	    });
 	}
 
 	public void refresh(TableCell cell) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MaxUploadsItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MaxUploadsItem.java
index e0a2647..43dd450 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MaxUploadsItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MaxUploadsItem.java
@@ -3,11 +3,12 @@
  * Created : 01 febv. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
@@ -27,7 +25,6 @@ package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
-
 import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.download.Download;
 import org.gudy.azureus2.plugins.ui.UIManager;
@@ -35,6 +32,8 @@ import org.gudy.azureus2.plugins.ui.menus.*;
 import org.gudy.azureus2.plugins.ui.tables.*;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
 
+import com.aelitis.azureus.ui.common.table.TableRowCore;
+
 public class MaxUploadsItem
        extends CoreTableColumnSWT 
        implements TableCellRefreshListener
@@ -71,6 +70,10 @@ public class MaxUploadsItem
 							if (target instanceof Object[]) {
 								Object[] targets = (Object[]) target;
 								for (Object object : targets) {
+									if (object instanceof TableRowCore) {
+										TableRowCore rowCore = (TableRowCore) object;
+										object = rowCore.getDataSource(true);
+									}
 									DownloadManager dm = (DownloadManager) object;
 									int value = ((Long) item.getData()).intValue();
 									dm.setMaxUploads(value);
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MergedDataItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MergedDataItem.java
new file mode 100644
index 0000000..db36774
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MergedDataItem.java
@@ -0,0 +1,71 @@
+/*
+ * Created by Paul Gardner
+ * 
+ * Copyright 2015 Azureus Software, 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 org.gudy.azureus2.ui.swt.views.tableitems.mytorrents;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+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;
+import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
+
+/**
+ *
+ * @author TuxPaper
+ * @since 2.0.8.5
+ */
+public class MergedDataItem
+       extends CoreTableColumnSWT 
+       implements TableCellRefreshListener
+{
+	public static final Class DATASOURCE_TYPE = Download.class;
+
+	public static final String COLUMN_ID = "mergeddata";
+
+	public MergedDataItem(String sTableID)
+	{
+		super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID);
+		
+		setRefreshInterval(INTERVAL_LIVE);
+		
+		setMinWidthAuto(true);
+	}
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+				CAT_BYTES
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE);
+	}
+
+	public void refresh(TableCell cell) {
+		DownloadManager dm = (DownloadManager)cell.getDataSource();
+
+		long value = (dm == null) ? 0 : dm.getDownloadState().getLongAttribute( DownloadManagerState.AT_MERGED_DATA );
+
+		if (!cell.setSortValue(value) && cell.isValid())
+			return;
+
+		cell.setText(value==0?"":DisplayFormatters.formatByteCountToKiBEtc( value ));
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MinSRItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MinSRItem.java
index 2f5cd28..75d0a09 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MinSRItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/MinSRItem.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,21 +18,25 @@
  * 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.tableitems.mytorrents;
 
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
 import org.gudy.azureus2.plugins.ui.tables.TableCell;
 import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
 import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
+import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
+import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 
+import com.aelitis.azureus.ui.common.table.TableRowCore;
+
 /** Display Category torrent belongs to.
  *
  * @author TuxPaper
@@ -53,6 +58,94 @@ public class MinSRItem
 	public MinSRItem(String sTableID) {
 		super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_TRAIL, 70, sTableID);
 		setRefreshInterval(INTERVAL_LIVE);
+		
+	    TableContextMenuItem menuItem = addContextMenuItem("menu.min.share.ratio2");
+	    menuItem.addMultiListener(new MenuItemListener() {
+				public void selected(MenuItem menu, Object target) {
+					if (target == null) {
+						return;
+					}
+					
+					Object[] o = (Object[]) target;
+					
+					int existing = -1;
+					
+					for (Object object : o) {
+						if (object instanceof TableRowCore) {
+							object = ((TableRowCore) object).getDataSource(true);
+						}
+						if (object instanceof DownloadManager) {
+							int x = ((DownloadManager)object).getDownloadState().getIntParameter( DownloadManagerState.PARAM_MIN_SHARE_RATIO );
+							
+							if ( existing == -1 ){
+								existing = x;
+							}else if ( existing != x ){
+								existing = -1;
+								break;
+							}
+						}
+					}
+					
+					String existing_text;
+					
+					if ( existing == -1 ){
+						existing_text = "";
+					}else{
+						existing_text = String.valueOf( existing/1000.0f);
+					}
+					
+					SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+							"min.sr.window.title", "min.sr.window.message");
+											
+					entryWindow.setPreenteredText( existing_text, false );
+					entryWindow.selectPreenteredText( true );
+					
+					entryWindow.prompt();
+					
+					if ( entryWindow.hasSubmittedInput()){
+						
+						try{
+							String text = entryWindow.getSubmittedInput().trim();
+							
+							int	sr = 0;
+							
+							if ( text.length() > 0 ){
+							
+								try{
+									float f = Float.parseFloat( text );
+								
+									sr = (int)(f * 1000 );
+								
+									if ( sr < 0 ){
+										
+										sr = 0;
+										
+									}else if ( sr == 0 && f > 0 ){
+										
+										sr = 1;
+									}
+								
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+								
+								for (Object object : o) {
+									if (object instanceof TableRowCore) {
+										object = ((TableRowCore) object).getDataSource(true);
+									}
+									if (object instanceof DownloadManager) {
+										((DownloadManager)object).getDownloadState().setIntParameter( DownloadManagerState.PARAM_MIN_SHARE_RATIO, sr );
+									}
+								}								
+							}			
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}
+				}
+	    });
 	}
 
 	public void refresh(TableCell cell) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NameItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NameItem.java
index 947a399..f46fedd 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NameItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NameItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
@@ -43,6 +41,8 @@ import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
 
+import com.aelitis.azureus.ui.common.table.TableRowCore;
+
 /** Torrent name cell for My Torrents.
  *
  * @author Olivier
@@ -81,6 +81,9 @@ public class NameItem extends CoreTableColumnSWT implements
 				}
 				Object[] o = (Object[]) target;
 				for (Object object : o) {
+					if (object instanceof TableRowCore) {
+						object = ((TableRowCore) object).getDataSource(true);
+					}
 					if (object instanceof DownloadManager) {
 						final DownloadManager dm = (DownloadManager) object;
 						String msg_key_prefix = "MyTorrentsView.menu.rename.displayed.enter.";
@@ -88,6 +91,7 @@ public class NameItem extends CoreTableColumnSWT implements
 						SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
 								msg_key_prefix + "title", msg_key_prefix + "message");
 						entryWindow.setPreenteredText(dm.getDisplayName(), false);
+						entryWindow.maintainWhitespace( true );	// apparently users want to be able to prefix with spaces
 						entryWindow.prompt(new UIInputReceiverListener() {
 							public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
 								if (!entryWindow.hasSubmittedInput()) {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NetworksItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NetworksItem.java
index 9feaef8..a34fbbf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NetworksItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/NetworksItem.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/OnlyCDing4Item.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/OnlyCDing4Item.java
index 4e499b7..0fa7036 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/OnlyCDing4Item.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/OnlyCDing4Item.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeakDownItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeakDownItem.java
index 0dfad8f..92ad1dc 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeakDownItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeakDownItem.java
@@ -1,22 +1,21 @@
-/*
+ /*
  * File    : PeakItem.java
  * Created : 01/07/2013
  * By      : Parg
  *
-* Copyright 2013 Azureus Software, 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.
+ * Copyright 2013 Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
  
 package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeakUpItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeakUpItem.java
index 0b2570f..693c595 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeakUpItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeakUpItem.java
@@ -3,20 +3,19 @@
  * Created : 01/07/2013
  * By      : Parg
  *
-* Copyright 2013 Azureus Software, 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.
+ * Copyright 2013 Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
  
 package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeerSourcesItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeerSourcesItem.java
index f19f9ff..fd77774 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeerSourcesItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeerSourcesItem.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeersItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeersItem.java
index 1201b42..93f2d71 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeersItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PeersItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PiecesItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PiecesItem.java
index e812e4e..3d8df68 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PiecesItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/PiecesItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/RankItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/RankItem.java
index c4fd823..9ac4589 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/RankItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/RankItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/RemainingItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/RemainingItem.java
index b77453d..9248be9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/RemainingItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/RemainingItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
@@ -84,7 +82,7 @@ public class RemainingItem
   	if (ds instanceof DownloadManager) {
       DownloadManager manager = (DownloadManager)cell.getDataSource();
       if (manager != null) {
-      	return( manager.getStats().getRemaining());
+      	return( manager.getStats().getRemainingExcludingDND());
       }
   	} else if (ds instanceof DiskManagerFileInfo) {
   		DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) ds;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SavePathItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SavePathItem.java
index 99370c3..65084a3 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SavePathItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SavePathItem.java
@@ -3,11 +3,12 @@
  * Created : 01 febv. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SecondsDownloadingItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SecondsDownloadingItem.java
index fe0b5c4..3ad2045 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SecondsDownloadingItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SecondsDownloadingItem.java
@@ -3,11 +3,12 @@
  * Created : 01 febv. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SecondsSeedingItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SecondsSeedingItem.java
index 1fc19ba..c42ef8e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SecondsSeedingItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SecondsSeedingItem.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SeedToPeerRatioItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SeedToPeerRatioItem.java
index 02718f8..4c024d7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SeedToPeerRatioItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SeedToPeerRatioItem.java
@@ -2,11 +2,12 @@
  * Created : 11 nov. 2004
  * By      : Alon Rohter
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SeedsItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SeedsItem.java
index f808fbd..f49c638 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SeedsItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SeedsItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SessionDownItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SessionDownItem.java
index be0124a..9375532 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SessionDownItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SessionDownItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SessionUpItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SessionUpItem.java
index b9934ae..f7f6c42 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SessionUpItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SessionUpItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ShareRatioItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ShareRatioItem.java
index 722cf16..466351e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ShareRatioItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ShareRatioItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
@@ -30,14 +28,20 @@ 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.Constants;
+import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
-
+import org.gudy.azureus2.ui.swt.views.tableitems.files.NameItem;
 import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
 import org.gudy.azureus2.plugins.ui.tables.*;
 
+import com.aelitis.azureus.ui.common.table.TableRowCore;
+
 /**
  *
  * @author Olivier
@@ -69,6 +73,47 @@ public class ShareRatioItem
 
     iMinShareRatio = COConfigurationManager.getIntParameter(CONFIG_ID);
     COConfigurationManager.addParameterListener(CONFIG_ID, this);
+    
+    TableContextMenuItem menuItem = addContextMenuItem("label.set.share.ratio");
+	
+	menuItem.setStyle(MenuItem.STYLE_PUSH);
+	
+	menuItem.addMultiListener(new MenuItemListener() {
+		public void selected(MenuItem menu, Object target) {
+			final Object[] dms = (Object[])target;
+			
+			SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+					"set.share.ratio.win.title", "set.share.ratio.win.msg");
+			
+			entryWindow.setPreenteredText( "1.000", false );
+			entryWindow.selectPreenteredText( true );
+			
+			entryWindow.prompt();
+			
+			if ( entryWindow.hasSubmittedInput()){
+				
+				try{
+					String str = entryWindow.getSubmittedInput().trim();
+					
+					int share_ratio = (int)( Float.parseFloat( str ) * 1000 );
+					
+					for ( Object object: dms ){
+						if (object instanceof TableRowCore) {
+							object = ((TableRowCore) object).getDataSource(true);
+						}
+						
+					    DownloadManager dm = (DownloadManager)object;
+					    
+					    dm.getStats().setShareRatio( share_ratio );
+					}
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+		}
+	});
   }
 
   protected void finalize() throws Throwable {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ShareRatioProgressItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ShareRatioProgressItem.java
index 0ac8511..49ce722 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ShareRatioProgressItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/ShareRatioProgressItem.java
@@ -1,132 +1,131 @@
-/*
- * Created on Dec 2, 2013
- * Created by Paul Gardner
- * 
- * Copyright 2013 Azureus Software, 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.tableitems.mytorrents;
-
-
-import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
-import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator;
-import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer;
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.download.DownloadManagerState;
-import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.ui.menus.MenuItem;
-import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
-import org.gudy.azureus2.plugins.ui.tables.*;
-
-
-
-public class 
-ShareRatioProgressItem
-	extends ColumnDateSizer
-{
-	public static final Class DATASOURCE_TYPE = Download.class;
-
-	public static final String COLUMN_ID = "sr_prog";
-
-	public void fillTableColumnInfo(TableColumnInfo info) {
-		info.addCategories(new String[] { CAT_TIME, CAT_SHARING, CAT_SWARM });
-		info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE);
-	}
-
-	public ShareRatioProgressItem(String sTableID) {
-		super(DATASOURCE_TYPE, COLUMN_ID, TableColumnCreator.DATE_COLUMN_WIDTH, sTableID);
-		setRefreshInterval(INTERVAL_LIVE);
-		setMultiline(false);
-		
-		final TableContextMenuItem menuSetInterval = addContextMenuItem(
-				"TableColumn.menu.sr_prog.interval", MENU_STYLE_HEADER);
-		menuSetInterval.setStyle(TableContextMenuItem.STYLE_PUSH);
-		menuSetInterval.addListener(new MenuItemListener() {
-			public void
-			selected(
-				MenuItem			menu,
-				Object 				target )
-			{
-				SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
-						"sr_prog.window.title", "sr_prog.window.message");
-							
-				int existing_sr = COConfigurationManager.getIntParameter( "Share Ratio Progress Interval" );
-				
-				String	sr_str 	= DisplayFormatters.formatDecimal((double) existing_sr / 1000, 3);
-				
-				entryWindow.setPreenteredText( sr_str, false );
-				entryWindow.selectPreenteredText( true );
-				entryWindow.setWidthHint( 400 );
-				
-				entryWindow.prompt();
-				
-				if ( entryWindow.hasSubmittedInput()){
-					
-					try{
-						String text = entryWindow.getSubmittedInput().trim();
-						
-						if ( text.length() > 0 ){
-						
-							float f = Float.parseFloat( text );
-							
-							int sr = (int)(f * 1000 );
-							
-							COConfigurationManager.setParameter( "Share Ratio Progress Interval", sr );
-						}
-					}catch( Throwable e ){
-						
-					}
-					
-				}
-			}
-		});
-	}
-
-	
-	public ShareRatioProgressItem(String tableID, boolean v) {
-		this(tableID);
-		setVisible(v);
-	}
-
-	public void refresh(TableCell cell, long timestamp) {
-		DownloadManager dm = (DownloadManager) cell.getDataSource();
-		
-		long data = (dm == null) ? 0 : dm.getDownloadState().getLongAttribute( DownloadManagerState.AT_SHARE_RATIO_PROGRESS );
-		
-		if ( data == 0 ){
-		
-			super.refresh( cell, data ) ;
-		
-		}else{
-			
-			long		sr 		= (int)data;
-			
-			String		sr_str 	= DisplayFormatters.formatDecimal((double) sr / 1000, 3);
-			
-			timestamp = (data>>>32)*1000;
-
-				// feed a bit of share ratio into sort order for fun
-			
-			timestamp += (sr&255);
-			
-			String prefix = sr_str + ": ";
-					
-			super.refresh( cell, timestamp, prefix );
-		}
-	}
-}
\ No newline at end of file
+/*
+ * Created on Dec 2, 2013
+ * Created by Paul Gardner
+ * 
+ * Copyright 2013 Azureus Software, 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 org.gudy.azureus2.ui.swt.views.tableitems.mytorrents;
+
+
+import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
+import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator;
+import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+
+
+public class 
+ShareRatioProgressItem
+	extends ColumnDateSizer
+{
+	public static final Class DATASOURCE_TYPE = Download.class;
+
+	public static final String COLUMN_ID = "sr_prog";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] { CAT_TIME, CAT_SHARING, CAT_SWARM });
+		info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE);
+	}
+
+	public ShareRatioProgressItem(String sTableID) {
+		super(DATASOURCE_TYPE, COLUMN_ID, TableColumnCreator.DATE_COLUMN_WIDTH, sTableID);
+		setRefreshInterval(INTERVAL_LIVE);
+		setMultiline(false);
+		
+		final TableContextMenuItem menuSetInterval = addContextMenuItem(
+				"TableColumn.menu.sr_prog.interval", MENU_STYLE_HEADER);
+		menuSetInterval.setStyle(TableContextMenuItem.STYLE_PUSH);
+		menuSetInterval.addListener(new MenuItemListener() {
+			public void
+			selected(
+				MenuItem			menu,
+				Object 				target )
+			{
+				SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+						"sr_prog.window.title", "sr_prog.window.message");
+							
+				int existing_sr = COConfigurationManager.getIntParameter( "Share Ratio Progress Interval" );
+				
+				String	sr_str 	= DisplayFormatters.formatDecimal((double) existing_sr / 1000, 3);
+				
+				entryWindow.setPreenteredText( sr_str, false );
+				entryWindow.selectPreenteredText( true );
+				entryWindow.setWidthHint( 400 );
+				
+				entryWindow.prompt();
+				
+				if ( entryWindow.hasSubmittedInput()){
+					
+					try{
+						String text = entryWindow.getSubmittedInput().trim();
+						
+						if ( text.length() > 0 ){
+						
+							float f = Float.parseFloat( text );
+							
+							int sr = (int)(f * 1000 );
+							
+							COConfigurationManager.setParameter( "Share Ratio Progress Interval", sr );
+						}
+					}catch( Throwable e ){
+						
+					}
+					
+				}
+			}
+		});
+	}
+
+	
+	public ShareRatioProgressItem(String tableID, boolean v) {
+		this(tableID);
+		setVisible(v);
+	}
+
+	public void refresh(TableCell cell, long timestamp) {
+		DownloadManager dm = (DownloadManager) cell.getDataSource();
+		
+		long data = (dm == null) ? 0 : dm.getDownloadState().getLongAttribute( DownloadManagerState.AT_SHARE_RATIO_PROGRESS );
+		
+		if ( data == 0 ){
+		
+			super.refresh( cell, data ) ;
+		
+		}else{
+			
+			long		sr 		= (int)data;
+			
+			String		sr_str 	= DisplayFormatters.formatDecimal((double) sr / 1000, 3);
+			
+			timestamp = (data>>>32)*1000;
+
+				// feed a bit of share ratio into sort order for fun
+			
+			timestamp += (sr&255);
+			
+			String prefix = sr_str + ": ";
+					
+			super.refresh( cell, timestamp, prefix );
+		}
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SizeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SizeItem.java
index 2fa339c..8935b67 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SizeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SizeItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,25 +18,24 @@
  * 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.tableitems.mytorrents;
 
+import java.text.NumberFormat;
+
 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.mainwindow.HSLColor;
-import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
-
 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.TableCellToolTipListener;
 import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
+import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
 
 /** Size of Torrent cell
  *
@@ -44,7 +44,7 @@ import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
  */
 public class SizeItem
 	extends CoreTableColumnSWT
-	implements TableCellRefreshListener
+	implements TableCellRefreshListener, TableCellToolTipListener
 {
 	public static final Class DATASOURCE_TYPE = Download.class;
 
@@ -70,12 +70,13 @@ public class SizeItem
 	}
 
 	public void refresh(TableCell cell) {
-		Object ds = cell.getDataSource();
 		sizeitemsort value;
+		Object ds = cell.getDataSource();
 		if (ds instanceof DownloadManager) {
 			DownloadManager dm = (DownloadManager) ds;
-			
-			value = new sizeitemsort(dm.getSize(), dm.getStats().getRemaining());
+
+			value = new sizeitemsort(dm.getStats().getSizeExcludingDND(),
+					dm.getStats().getRemainingExcludingDND());
 		} else if (ds instanceof DiskManagerFileInfo) {
 			DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) ds;
 			value = new sizeitemsort(fileInfo.getLength(), fileInfo.getLength()
@@ -96,16 +97,18 @@ public class SizeItem
 		if (DO_MULTILINE && cell.getMaxLines() > 1 && value.remaining > 0) {
 			s += "\n"
 					+ DisplayFormatters.formatByteCountToKiBEtc(value.remaining, false,
-							false, 0) + " to go";
+							false, 0) + " "
+					+ MessageText.getString("TableColumn.header.remaining");
 		}
 		cell.setText(s);
+
 		if (Utils.getUserMode() > 0 && (cell instanceof TableCellSWT)) {
 			if (value.size >= 0x40000000l) {
-				((TableCellSWT)cell).setTextAlpha(200 | 0x100);
+				((TableCellSWT) cell).setTextAlpha(200 | 0x100);
 			} else if (value.size < 0x100000) {
-				((TableCellSWT)cell).setTextAlpha(180);
+				((TableCellSWT) cell).setTextAlpha(180);
 			} else {
-				((TableCellSWT)cell).setTextAlpha(255);
+				((TableCellSWT) cell).setTextAlpha(255);
 			}
 		}
 	}
@@ -135,4 +138,37 @@ public class SizeItem
 			return size > otherObj.size ? 1 : -1;
 		}
 	}
+
+	public void cellHover(TableCell cell) {
+		Comparable sortValue = cell.getSortValue();
+		if (!(sortValue instanceof sizeitemsort)) {
+			return;
+		}
+		sizeitemsort value = (sizeitemsort) sortValue;
+		String tooltip = NumberFormat.getInstance().format(value.size) + " "
+				+ MessageText.getString("DHTView.transport.bytes");
+		if (value.remaining > 0) {
+			tooltip += "\n"
+					+ DisplayFormatters.formatByteCountToKiBEtc(value.remaining, false,
+							false) + " "
+					+ MessageText.getString("TableColumn.header.remaining");
+		}
+		Object ds = cell.getDataSource();
+		if (ds instanceof DownloadManager) {
+			DownloadManager dm = (DownloadManager) ds;
+			long fullSize = dm.getSize();
+			if (fullSize > value.size) {
+				tooltip += "\n"
+						+ DisplayFormatters.formatByteCountToKiBEtc(fullSize - value.size,
+								false, false) + " "
+						+ MessageText.getString("FileView.BlockView.Skipped");
+			}
+		}
+
+		cell.setToolTip(tooltip);
+	}
+
+	public void cellHoverComplete(TableCell cell) {
+		cell.setToolTip(null);
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedDownItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedDownItem.java
index 81f88b7..1af5679 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedDownItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedDownItem.java
@@ -3,20 +3,19 @@
  * Created : 01/07/2013
  * By      : Parg
  *
-* Copyright 2013 Azureus Software, 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.
+ * Copyright 2013 Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
  
 package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedETAItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedETAItem.java
index a997ca8..1e3a5c4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedETAItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedETAItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedUpItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedUpItem.java
index 261958b..9864f55 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedUpItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SmoothedUpItem.java
@@ -3,20 +3,19 @@
  * Created : 01/07/2013
  * By      : Parg
  *
-* Copyright 2013 Azureus Software, 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.
+ * Copyright 2013 Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
  
 package org.gudy.azureus2.ui.swt.views.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/StatusItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/StatusItem.java
index 173f070..7704bb6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/StatusItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/StatusItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SwarmAverageCompletion.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SwarmAverageCompletion.java
index 9785266..b97268e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SwarmAverageCompletion.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SwarmAverageCompletion.java
@@ -2,11 +2,12 @@
  * Created : 11 nov. 2004
  * By      : Alon Rohter
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SwarmAverageSpeed.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SwarmAverageSpeed.java
index ec3b56f..e74bf86 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SwarmAverageSpeed.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/SwarmAverageSpeed.java
@@ -2,11 +2,12 @@
  * Created : 11 nov. 2004
  * By      : Alon Rohter
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TagColorsItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TagColorsItem.java
index 3fdc231..920701a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TagColorsItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TagColorsItem.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TagsItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TagsItem.java
index 7e4a31e..1e0fe13 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TagsItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TagsItem.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TimeSinceDownloadItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TimeSinceDownloadItem.java
index 9151879..883e227 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TimeSinceDownloadItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TimeSinceDownloadItem.java
@@ -3,11 +3,12 @@
  * Created : 01 febv. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TimeSinceUploadItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TimeSinceUploadItem.java
index d81f38a..ddd0a20 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TimeSinceUploadItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TimeSinceUploadItem.java
@@ -3,11 +3,12 @@
  * Created : 01 febv. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TorrentCreateDateItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TorrentCreateDateItem.java
index 31effe5..96435f8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TorrentCreateDateItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TorrentCreateDateItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-May-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TorrentPathItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TorrentPathItem.java
index 1d7f05b..aea9465 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TorrentPathItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TorrentPathItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 19-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TotalSpeedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TotalSpeedItem.java
index d0c8016..1b4d38a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TotalSpeedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TotalSpeedItem.java
@@ -3,11 +3,12 @@
  * Created : 1 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerCellUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerCellUtils.java
index b06a1fc..176ff39 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerCellUtils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerCellUtils.java
@@ -3,11 +3,12 @@
  * Created : Nov 24, 2005
  * By      : TuxPaper
  *
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
@@ -55,7 +53,7 @@ public class TrackerCellUtils
 			}
 		}
 		TRTrackerScraperResponse response = dm.getTrackerScrapeResponse();
-		if (response instanceof TRTrackerBTScraperResponseImpl) {
+		if (response instanceof TRTrackerBTScraperResponseImpl && response.getStatus() == TRTrackerScraperResponse.ST_ONLINE) {
 			boolean bMultiHashScrapes = ((TRTrackerBTScraperResponseImpl) response).getTrackerStatus().getSupportsMultipeHashScrapes();
 			Color color = (bMultiHashScrapes) ? null : Colors.grey;
 			cell.setForeground(Utils.colorToIntArray(color));
@@ -75,7 +73,7 @@ public class TrackerCellUtils
 		}
 		String sToolTip = null;
 		TRTrackerScraperResponse response = dm.getTrackerScrapeResponse();
-		if (response instanceof TRTrackerBTScraperResponseImpl) {
+		if (response instanceof TRTrackerBTScraperResponseImpl && response.getStatus() == TRTrackerScraperResponse.ST_ONLINE ) {
 			String sPrefix = ((TRTrackerBTScraperResponseImpl) response).getTrackerStatus().getSupportsMultipeHashScrapes()
 					? "" : "No";
 			sToolTip = MessageText.getString("Tracker.tooltip." + sPrefix
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerNameItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerNameItem.java
index ec2061a..1c3f7a0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerNameItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerNameItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerNextAccessItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerNextAccessItem.java
index 180cbbd..6fa9d2a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerNextAccessItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerNextAccessItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerStatusItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerStatusItem.java
index 3d9a6dd..3e975ce 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerStatusItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/TrackerStatusItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpItem.java
index a5e558c..a81e65f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpSpeedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpSpeedItem.java
index 233e2ef..084ad34 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpSpeedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpSpeedItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.mytorrents;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpSpeedLimitItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpSpeedLimitItem.java
index 890d893..e80905a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpSpeedLimitItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytorrents/UpSpeedLimitItem.java
@@ -2,11 +2,12 @@
  * Created on 8 oct. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.tableitems.mytorrents;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AnnounceCountItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AnnounceCountItem.java
index 81b9aa9..f6391d5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AnnounceCountItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AnnounceCountItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AverageBytesInItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AverageBytesInItem.java
index 0a8412c..181b914 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AverageBytesInItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AverageBytesInItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AverageBytesOutItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AverageBytesOutItem.java
index 6cd518a..e4d9612 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AverageBytesOutItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/AverageBytesOutItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/BadNATCountItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/BadNATCountItem.java
index 60a5342..aee7199 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/BadNATCountItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/BadNATCountItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 30-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/CategoryItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/CategoryItem.java
index 0252b4f..a8db173 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/CategoryItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/CategoryItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 10-Dec-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/CompletedCountItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/CompletedCountItem.java
index 22e2773..114e07f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/CompletedCountItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/CompletedCountItem.java
@@ -1,10 +1,11 @@
 
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -14,9 +15,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/DateAddedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/DateAddedItem.java
index fe14f01..6d7b4c7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/DateAddedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/DateAddedItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/DownloadedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/DownloadedItem.java
index 7d7e394..efbcec8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/DownloadedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/DownloadedItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/LeftItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/LeftItem.java
index 38a54e6..6d927d8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/LeftItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/LeftItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/NameItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/NameItem.java
index 50cdc7e..6215db7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/NameItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/NameItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/PassiveItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/PassiveItem.java
index 9419ff0..e3663a0 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/PassiveItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/PassiveItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/PeerCountItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/PeerCountItem.java
index 8bfc0b0..f7e6610 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/PeerCountItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/PeerCountItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/ScrapeCountItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/ScrapeCountItem.java
index 4b8a0bb..95d393e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/ScrapeCountItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/ScrapeCountItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/SeedCountItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/SeedCountItem.java
index 6d46a13..d10e960 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/SeedCountItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/SeedCountItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/StatusItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/StatusItem.java
index 90bf0c5..c03c651 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/StatusItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/StatusItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TotalBytesInItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TotalBytesInItem.java
index 8cc29fa..6bcfdf1 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TotalBytesInItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TotalBytesInItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TotalBytesOutItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TotalBytesOutItem.java
index 5b2aab0..48b1dda 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TotalBytesOutItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TotalBytesOutItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TrackerItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TrackerItem.java
index 426722e..589baeb 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TrackerItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/TrackerItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/UploadedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/UploadedItem.java
index 64f1334..7ad68e5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/UploadedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/mytracker/UploadedItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.mytracker;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ASItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ASItem.java
index b9b7ff8..109971c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ASItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ASItem.java
@@ -3,11 +3,12 @@
  * Created : 24 dec 2008
  * By      : Parg
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
@@ -27,6 +25,7 @@ package org.gudy.azureus2.ui.swt.views.tableitems.peers;
 import java.net.InetAddress;
 
 import org.gudy.azureus2.core3.peer.PEPeer;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
 
 import com.aelitis.azureus.core.networkmanager.admin.*;
 
@@ -70,27 +69,32 @@ public class ASItem
     		
     		peer.setUserData( ASItem.class, text );
     	
-    		try{
-	    		NetworkAdmin.getSingleton().lookupASN( 
-	    			InetAddress.getByName( peer.getIp()),
-	    			new NetworkAdminASNListener()
-	    			{
-	    				public void
-	    				success(
-	    					NetworkAdminASN		asn )
-	    				{
-	    					peer.setUserData( ASItem.class, asn.getAS() + " - " + asn.getASName());
-	    				}
-	    				
-	    				public void
-	    				failed(
-	    					NetworkAdminException	error )
-	    				{
-	    				}
-	    			});
-	    	
-	    	}catch( Throwable e ){
-	    	}
+    		String peer_ip = peer.getIp();
+    		
+    		if ( AENetworkClassifier.categoriseAddress( peer_ip ) == AENetworkClassifier.AT_PUBLIC ){
+    			
+	    		try{
+		    		NetworkAdmin.getSingleton().lookupASN( 
+		    			InetAddress.getByName( peer_ip ),
+		    			new NetworkAdminASNListener()
+		    			{
+		    				public void
+		    				success(
+		    					NetworkAdminASN		asn )
+		    				{
+		    					peer.setUserData( ASItem.class, asn.getAS() + " - " + asn.getASName());
+		    				}
+		    				
+		    				public void
+		    				failed(
+		    					NetworkAdminException	error )
+		    				{
+		    				}
+		    			});
+		    	
+		    	}catch( Throwable e ){
+		    	}
+    		}
     	}
     }
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ChokedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ChokedItem.java
index 7d032ce..1bf4ef5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ChokedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ChokedItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ChokingItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ChokingItem.java
index 54d8789..a905817 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ChokingItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ChokingItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ClientIdentificationItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ClientIdentificationItem.java
index 5bba308..d546026 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ClientIdentificationItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ClientIdentificationItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 5 Sep 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.tableitems.peers;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ClientItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ClientItem.java
index 10eaa95..b72bbff 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ClientItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ClientItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ColumnPeerNetwork.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ColumnPeerNetwork.java
new file mode 100644
index 0000000..d409d9c
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ColumnPeerNetwork.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.tableitems.peers;
+
+import org.gudy.azureus2.core3.peer.impl.PEPeerTransport;
+import org.gudy.azureus2.plugins.ui.tables.TableCell;
+import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
+import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
+
+import com.aelitis.azureus.core.peermanager.peerdb.PeerItem;
+
+
+public class ColumnPeerNetwork
+       extends CoreTableColumnSWT 
+       implements TableCellRefreshListener
+{
+  /** Default Constructor */
+  public ColumnPeerNetwork(String table_id) {
+    super("network", POSITION_INVISIBLE, 65, table_id);
+    setRefreshInterval(INTERVAL_INVALID_ONLY);
+  }
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			CAT_PROTOCOL,
+			CAT_CONNECTION,
+		});
+	}
+
+  public void refresh(TableCell cell) {
+  	Object ds = cell.getDataSource();
+  	String text = "";
+  	Comparable val = null;
+  	if (ds instanceof PEPeerTransport) {
+			PEPeerTransport peer = (PEPeerTransport) ds;
+			
+			PeerItem identity = peer.getPeerItemIdentity();
+			
+			if (identity != null) {
+				val = text = identity.getNetwork();
+			}
+    }
+    
+    if( !cell.setSortValue( val ) && cell.isValid() ) {
+      return;
+    }
+    
+    cell.setText( text );
+  }
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ConnectedTimeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ConnectedTimeItem.java
index 1e57120..3289e20 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ConnectedTimeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ConnectedTimeItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DLedFromOthersItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DLedFromOthersItem.java
index df788a4..094c5d3 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DLedFromOthersItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DLedFromOthersItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DiscardedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DiscardedItem.java
index 830cdab..b123c1f 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DiscardedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DiscardedItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownItem.java
index 59fc22d..9a69be2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownSpeedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownSpeedItem.java
index 1df177a..5418fe9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownSpeedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownSpeedItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownSpeedLimitItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownSpeedLimitItem.java
index d4bebd6..470f0a4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownSpeedLimitItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownSpeedLimitItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 17-Nov-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownloadNameItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownloadNameItem.java
index 02d48ae..c5752a2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownloadNameItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/DownloadNameItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14 Sep 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.tableitems.peers;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/EncryptionItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/EncryptionItem.java
index 8c85117..ed671d3 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/EncryptionItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/EncryptionItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/GainItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/GainItem.java
index 0c6ad5e..4f23fff 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/GainItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/GainItem.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.views.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/HandshakeReservedBytesItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/HandshakeReservedBytesItem.java
index 8a5e2b9..a5d2914 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/HandshakeReservedBytesItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/HandshakeReservedBytesItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 29 Aug 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.tableitems.peers;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/HostNameItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/HostNameItem.java
index d061862..3bf27eb 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/HostNameItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/HostNameItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 27-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IncomingRequestCountItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IncomingRequestCountItem.java
index 3efb89d..1741f1c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IncomingRequestCountItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IncomingRequestCountItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IndexItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IndexItem.java
new file mode 100644
index 0000000..59af18b
--- /dev/null
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IndexItem.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.tableitems.peers;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
+
+
+public class IndexItem
+       extends CoreTableColumnSWT 
+       implements TableCellRefreshListener
+{
+
+
+	public static final String COLUMN_ID = "#";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+				CAT_SETTINGS,
+		});
+	}
+
+	public IndexItem(String table_id) {
+		super(COLUMN_ID, ALIGN_TRAIL, POSITION_INVISIBLE, 20, table_id);
+		setRefreshInterval(INTERVAL_LIVE);
+	}
+
+	public void refresh(TableCell cell) {
+
+		TableRow row = cell.getTableRow();
+
+		if ( row != null ){
+			int	index = row.getIndex();
+	
+			if (!cell.setSortValue(index) && cell.isValid())
+				return;
+	
+			cell.setText("" + (index+1));
+		}
+	}
+}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/InterestedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/InterestedItem.java
index 6d0e949..f972126 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/InterestedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/InterestedItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/InterestingItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/InterestingItem.java
index 4f537bc..418e7f2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/InterestingItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/InterestingItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IpItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IpItem.java
index 9f9f7e4..7c67a39 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IpItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/IpItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/LANItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/LANItem.java
index 9f962c9..466e34c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/LANItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/LANItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/MessagingItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/MessagingItem.java
index 75351d6..4dc6534 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/MessagingItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/MessagingItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/OptimisticUnchokeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/OptimisticUnchokeItem.java
index e472dbf..651b4af 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/OptimisticUnchokeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/OptimisticUnchokeItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/OutgoingRequestCountItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/OutgoingRequestCountItem.java
index 773873a..e04078c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/OutgoingRequestCountItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/OutgoingRequestCountItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerByteIDItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerByteIDItem.java
index aa3e02f..172810a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerByteIDItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerByteIDItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 2 Mar 2007
  * Created by Allan Crooks
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -12,8 +12,7 @@
  * 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.
+ * MA 02111-1307, USA.
  */
 package org.gudy.azureus2.ui.swt.views.tableitems.peers;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerIDItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerIDItem.java
index 05a2f95..5194745 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerIDItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerIDItem.java
@@ -1,6 +1,8 @@
 /*
- * Created on 2 Mar 2007 Created by Allan Crooks Copyright (C) 2007 Aelitis, All
- * Rights Reserved. This program is free software; you can redistribute it
+ * Created on 2 Mar 2007 Created by Allan Crooks
+ * Copyright (C) 2007 Azureus Software, 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
@@ -9,8 +11,7 @@
  * 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.
+ * MA 02111-1307, USA.
  */
 package org.gudy.azureus2.ui.swt.views.tableitems.peers;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerSourceItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerSourceItem.java
index 19e5edc..a2796ac 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerSourceItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PeerSourceItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PercentItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PercentItem.java
index 3861bc9..a53f75d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PercentItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PercentItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PieceItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PieceItem.java
index 97bd120..9b108ba 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PieceItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PieceItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PiecesItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PiecesItem.java
index a0eb428..f8285df 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PiecesItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PiecesItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PortItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PortItem.java
index 1368de8..f2434d1 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PortItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/PortItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ProtocolItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ProtocolItem.java
index 52e6d58..54c58cb 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ProtocolItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/ProtocolItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/SnubbedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/SnubbedItem.java
index 488a575..984ea6b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/SnubbedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/SnubbedItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/StatUpItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/StatUpItem.java
index 35e57b7..2df6e97 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/StatUpItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/StatUpItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/StateItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/StateItem.java
index fe6d99c..ed08650 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/StateItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/StateItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TimeToSendPieceItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TimeToSendPieceItem.java
index d466dee..dc6c1d1 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TimeToSendPieceItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TimeToSendPieceItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TimeUntilCompleteItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TimeUntilCompleteItem.java
index 0bc2a83..ec024b9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TimeUntilCompleteItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TimeUntilCompleteItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TotalDownSpeedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TotalDownSpeedItem.java
index 472e2e6..4c19d63 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TotalDownSpeedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TotalDownSpeedItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TypeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TypeItem.java
index 7ac595e..a6ab1e1 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TypeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/TypeItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UniquePieceItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UniquePieceItem.java
index fae25c3..c4f1ac7 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UniquePieceItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UniquePieceItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpDownRatioItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpDownRatioItem.java
index ec71e21..311a1a1 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpDownRatioItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpDownRatioItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpItem.java
index 5394932..c2d7521 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpRatioItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpRatioItem.java
index 3621945..e04337b 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpRatioItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpRatioItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpSpeedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpSpeedItem.java
index a4729ab..b04280e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpSpeedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpSpeedItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.peers;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpSpeedLimitItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpSpeedLimitItem.java
index e212563..3a5ab20 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpSpeedLimitItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/peers/UpSpeedLimitItem.java
@@ -2,11 +2,12 @@
  * Created on 8 oct. 2004
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.tableitems.peers;
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/AvailabilityItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/AvailabilityItem.java
index b6c2d95..9dda3c4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/AvailabilityItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/AvailabilityItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/BlockCountItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/BlockCountItem.java
index e3c756a..f7e89a5 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/BlockCountItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/BlockCountItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/BlocksItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/BlocksItem.java
index b950f5b..361bd37 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/BlocksItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/BlocksItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/CompletedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/CompletedItem.java
index db81385..b9991a9 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/CompletedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/CompletedItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/PieceNumberItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/PieceNumberItem.java
index 5c1d7a5..06e7ccd 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/PieceNumberItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/PieceNumberItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/PriorityItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/PriorityItem.java
index d15d12a..632675a 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/PriorityItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/PriorityItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/RequestedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/RequestedItem.java
index ebfb208..0fb69c6 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/RequestedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/RequestedItem.java
@@ -1,7 +1,7 @@
 /*
  * Created by Joseph Bridgewater
  * Created on Feb 05, 2006
- * Copyright (C) 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/ReservedByItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/ReservedByItem.java
index 517653e..d746dc3 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/ReservedByItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/ReservedByItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/SizeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/SizeItem.java
index ad03ab0..c2e074e 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/SizeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/SizeItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/SpeedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/SpeedItem.java
index 398bf78..f46cc65 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/SpeedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/SpeedItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/TypeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/TypeItem.java
index 539e0a3..45e55c4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/TypeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/TypeItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/WritersItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/WritersItem.java
index e16d6ce..25d2e82 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/WritersItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/pieces/WritersItem.java
@@ -1,9 +1,10 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -13,9 +14,6 @@
  * 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.tableitems.pieces;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/CompletedItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/CompletedItem.java
index 4c86206..ecb56fa 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/CompletedItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/CompletedItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.tracker;
@@ -27,7 +25,6 @@ package org.gudy.azureus2.ui.swt.views.tableitems.tracker;
 import org.gudy.azureus2.plugins.ui.tables.*;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 
-
 import com.aelitis.azureus.core.tracker.TrackerPeerSource;
 
 
@@ -38,9 +35,9 @@ CompletedItem
     implements TableCellRefreshListener
 {
 	public 
-	CompletedItem()
+	CompletedItem(String tableID)
 	{
-		super( "completed", ALIGN_CENTER, POSITION_LAST, 75, TableManager.TABLE_TORRENT_TRACKERS );
+		super( "completed", ALIGN_CENTER, POSITION_LAST, 75, tableID );
     
 		setRefreshInterval( INTERVAL_GRAPHIC );
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/IntervalItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/IntervalItem.java
index 16dd270..8ef6898 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/IntervalItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/IntervalItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.tracker;
@@ -28,7 +26,6 @@ import org.gudy.azureus2.core3.util.TimeFormatter;
 import org.gudy.azureus2.plugins.ui.tables.*;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 
-
 import com.aelitis.azureus.core.tracker.TrackerPeerSource;
 
 
@@ -38,9 +35,9 @@ IntervalItem
     implements TableCellRefreshListener
 {
 	public 
-	IntervalItem()
+	IntervalItem(String tableID)
 	{
-		super( "interval", ALIGN_CENTER, POSITION_LAST, 75, TableManager.TABLE_TORRENT_TRACKERS );
+		super( "interval", ALIGN_CENTER, POSITION_LAST, 75, tableID );
     
 		setRefreshInterval( INTERVAL_GRAPHIC );
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/LastUpdateItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/LastUpdateItem.java
index 8ca4436..8aac334 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/LastUpdateItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/LastUpdateItem.java
@@ -1,7 +1,7 @@
 /*
  * Created on 05-May-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/LeechersItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/LeechersItem.java
index 45357f9..053244c 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/LeechersItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/LeechersItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.tracker;
@@ -27,7 +25,6 @@ package org.gudy.azureus2.ui.swt.views.tableitems.tracker;
 import org.gudy.azureus2.plugins.ui.tables.*;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 
-
 import com.aelitis.azureus.core.tracker.TrackerPeerSource;
 
 
@@ -38,9 +35,9 @@ LeechersItem
     implements TableCellRefreshListener
 {
 	public 
-	LeechersItem()
+	LeechersItem(String tableID)
 	{
-		super( "leechers", ALIGN_CENTER, POSITION_LAST, 75, TableManager.TABLE_TORRENT_TRACKERS );
+		super( "leechers", ALIGN_CENTER, POSITION_LAST, 75, tableID );
     
 		setRefreshInterval( INTERVAL_GRAPHIC );
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/NameItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/NameItem.java
index abfaa33..85d6228 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/NameItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/NameItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.tracker;
@@ -37,9 +35,9 @@ NameItem
     implements TableCellRefreshListener
 {
 	public 
-	NameItem()
+	NameItem( String tableID)
 	{
-		super( "name", ALIGN_LEAD, POSITION_LAST, 300, TableManager.TABLE_TORRENT_TRACKERS );
+		super( "name", ALIGN_LEAD, POSITION_LAST, 300, tableID );
     
 		setRefreshInterval( INTERVAL_GRAPHIC );
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/PeersItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/PeersItem.java
index c7d632c..0206525 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/PeersItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/PeersItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.tracker;
@@ -27,7 +25,6 @@ package org.gudy.azureus2.ui.swt.views.tableitems.tracker;
 import org.gudy.azureus2.plugins.ui.tables.*;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 
-
 import com.aelitis.azureus.core.tracker.TrackerPeerSource;
 
 
@@ -37,9 +34,9 @@ PeersItem
     implements TableCellRefreshListener
 {
 	public 
-	PeersItem()
+	PeersItem(String tableID)
 	{
-		super( "peers", ALIGN_CENTER, POSITION_LAST, 75, TableManager.TABLE_TORRENT_TRACKERS );
+		super( "peers", ALIGN_CENTER, POSITION_LAST, 75, tableID );
     
 		setRefreshInterval( INTERVAL_GRAPHIC );
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/SeedsItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/SeedsItem.java
index 44e0295..1afccf2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/SeedsItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/SeedsItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.tracker;
@@ -27,7 +25,6 @@ package org.gudy.azureus2.ui.swt.views.tableitems.tracker;
 import org.gudy.azureus2.plugins.ui.tables.*;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 
-
 import com.aelitis.azureus.core.tracker.TrackerPeerSource;
 
 
@@ -37,9 +34,9 @@ SeedsItem
     implements TableCellRefreshListener
 {
 	public 
-	SeedsItem()
+	SeedsItem(String tableID)
 	{
-		super( "seeds", ALIGN_CENTER, POSITION_LAST, 75, TableManager.TABLE_TORRENT_TRACKERS );
+		super( "seeds", ALIGN_CENTER, POSITION_LAST, 75, tableID );
     
 		setRefreshInterval( INTERVAL_GRAPHIC );
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/StatusItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/StatusItem.java
index e46d24a..dd2a47d 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/StatusItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/StatusItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.tracker;
@@ -57,9 +55,9 @@ StatusItem
 
 	
 	public 
-	StatusItem()
+	StatusItem( String tableID )
 	{
-		super( "status", ALIGN_LEAD, POSITION_LAST, 75, TableManager.TABLE_TORRENT_TRACKERS );
+		super( "status", ALIGN_LEAD, POSITION_LAST, 75, tableID );
     
 		setRefreshInterval( INTERVAL_GRAPHIC );
 		
@@ -121,7 +119,7 @@ StatusItem
 					str += extra.substring( pos );
 				}
 			}
-		}else if ( status == TrackerPeerSource.ST_ERROR ){
+		}else if ( status == TrackerPeerSource.ST_ERROR || status == TrackerPeerSource.ST_STOPPED || status == TrackerPeerSource.ST_QUEUED ){
 			
 			if ( extra != null ){
 				
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/TypeItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/TypeItem.java
index 3725acc..0cbc0eb 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/TypeItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/TypeItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.tracker;
@@ -31,7 +29,6 @@ import org.gudy.azureus2.core3.internat.MessageText.MessageTextListener;
 import org.gudy.azureus2.plugins.ui.tables.*;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 
-
 import com.aelitis.azureus.core.tracker.TrackerPeerSource;
 
 
@@ -55,9 +52,9 @@ TypeItem
 
 	
 	public 
-	TypeItem()
+	TypeItem(String tableID)
 	{
-		super( "type", ALIGN_LEAD, POSITION_LAST, 75, TableManager.TABLE_TORRENT_TRACKERS );
+		super( "type", ALIGN_LEAD, POSITION_LAST, 75, tableID );
     
 		setRefreshInterval(INTERVAL_INVALID_ONLY);
 		
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/UpdateInItem.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/UpdateInItem.java
index 19486ef..40a9df2 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/UpdateInItem.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/tableitems/tracker/UpdateInItem.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tableitems.tracker;
@@ -28,7 +26,6 @@ import org.gudy.azureus2.core3.util.TimeFormatter;
 import org.gudy.azureus2.plugins.ui.tables.*;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 
-
 import com.aelitis.azureus.core.tracker.TrackerPeerSource;
 
 public class 
@@ -37,9 +34,9 @@ UpdateInItem
     implements TableCellRefreshListener
 {
 	public 
-	UpdateInItem()
+	UpdateInItem(String tableID)
 	{
-		super( "updatein", ALIGN_CENTER, POSITION_LAST, 75, TableManager.TABLE_TORRENT_TRACKERS );
+		super( "updatein", ALIGN_CENTER, POSITION_LAST, 75, tableID );
     
 		setRefreshInterval( INTERVAL_LIVE );
 	}
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/CategoryUIUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/CategoryUIUtils.java
index e71f032..bf8dfc8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/CategoryUIUtils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/CategoryUIUtils.java
@@ -1,10 +1,12 @@
 /**
  * Created on Nov 15, 2010
  *
- * Copyright 2010 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -47,6 +49,7 @@ import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
 import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 
 /**
  * @author TuxPaper
@@ -127,7 +130,8 @@ public class CategoryUIUtils
 
 			ViewUtils.addSpeedMenu(menu.getShell(), menu, true, true, true, true, false,
 					down_speed == 0, down_speed, down_speed, maxDownload, false,
-					up_speed == 0, up_speed, up_speed, maxUpload, 1, new SpeedAdapter() {
+					up_speed == 0, up_speed, up_speed, maxUpload, 1, null,
+					new SpeedAdapter() {
 						public void setDownSpeed(int val) {
 							category.setDownloadSpeed(val);
 						}
@@ -217,7 +221,7 @@ public class CategoryUIUtils
 
 			final BuddyPlugin buddy_plugin = (BuddyPlugin) bpi.getPlugin();
 
-			if (buddy_plugin.isEnabled()) {
+			if ( buddy_plugin.isClassicEnabled()){
 
 				final Menu share_menu = new Menu(menu.getShell(), SWT.DROP_DOWN);
 				final MenuItem share_item = new MenuItem(menu, SWT.CASCADE);
@@ -246,7 +250,7 @@ public class CategoryUIUtils
 						cname = category.getName();
 					}
 
-					final boolean is_public = buddy_plugin.isPublicCategory(cname);
+					final boolean is_public = buddy_plugin.isPublicTagOrCategory(cname);
 
 					final MenuItem itemPubCat = new MenuItem(share_menu, SWT.CHECK);
 
@@ -258,11 +262,11 @@ public class CategoryUIUtils
 						public void handleEvent(Event event) {
 							if (is_public) {
 
-								buddy_plugin.removePublicCategory(cname);
+								buddy_plugin.removePublicTagOrCategory(cname);
 
 							} else {
 
-								buddy_plugin.addPublicCategory(cname);
+								buddy_plugin.addPublicTagOrCategory(cname);
 							}
 						}
 					});
@@ -276,7 +280,7 @@ public class CategoryUIUtils
 							continue;
 						}
 
-						final boolean auth = buddy.isLocalRSSCategoryAuthorised(cname);
+						final boolean auth = buddy.isLocalRSSTagOrCategoryAuthorised(cname);
 
 						final MenuItem itemShare = new MenuItem(share_menu, SWT.CHECK);
 
@@ -293,11 +297,11 @@ public class CategoryUIUtils
 							public void handleEvent(Event event) {
 								if (auth) {
 
-									buddy.removeLocalAuthorisedRSSCategory(cname);
+									buddy.removeLocalAuthorisedRSSTagOrCategory(cname);
 
 								} else {
 
-									buddy.addLocalAuthorisedRSSCategory(cname);
+									buddy.addLocalAuthorisedRSSTagOrCategory(cname);
 								}
 							}
 						});
@@ -402,8 +406,10 @@ public class CategoryUIUtils
 		itemOptions.addListener(SWT.Selection, new Listener() {
 			public void handleEvent(Event event) {
 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
-
-				uiFunctions.openView(UIFunctions.VIEW_DM_MULTI_OPTIONS, dms);
+				if (uiFunctions != null) {
+					uiFunctions.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_OPTIONS, dms);
+				}
 			}
 		});
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/CoordinateTransform.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/CoordinateTransform.java
index aa3462e..ff74012 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/CoordinateTransform.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/CoordinateTransform.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.swt.views.utils;
 
 import org.eclipse.swt.graphics.Rectangle;
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/LocProvUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/LocProvUtils.java
index 59f6d9d..2fd62d8 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/LocProvUtils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/LocProvUtils.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/ManagerUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/ManagerUtils.java
index 539397e..c7fc183 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/ManagerUtils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/ManagerUtils.java
@@ -3,11 +3,12 @@
  * Created : 7 d�c. 2003}
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,14 +18,14 @@
  * 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 java.io.File;
-import java.util.Arrays;
+
+import java.io.*;
+import java.net.InetAddress;
+import java.net.URL;
+import java.util.*;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
@@ -32,43 +33,56 @@ import org.eclipse.swt.widgets.MessageBox;
 import org.eclipse.swt.widgets.Shell;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.core3.disk.DiskManagerFileInfoSet;
 import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.download.DownloadManagerState;
+import org.gudy.azureus2.core3.download.DownloadManagerListener;
+import org.gudy.azureus2.core3.download.impl.DownloadManagerAdapter;
 import org.gudy.azureus2.core3.global.GlobalManagerDownloadRemovalVetoException;
 import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.logging.LogAlert;
-import org.gudy.azureus2.core3.logging.Logger;
 import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
+import org.gudy.azureus2.core3.torrent.TOTorrentFile;
 import org.gudy.azureus2.core3.tracker.host.TRHostException;
-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.core3.util.*;
+import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
 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.PluginManager;
+import org.gudy.azureus2.plugins.UnloadablePlugin;
+import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
+import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
+import org.gudy.azureus2.plugins.disk.DiskManagerListener;
+import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
 import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadStub;
 import org.gudy.azureus2.plugins.platform.PlatformManagerException;
-import org.gudy.azureus2.plugins.sharing.ShareManager;
-import org.gudy.azureus2.plugins.sharing.ShareResource;
-import org.gudy.azureus2.plugins.sharing.ShareResourceDir;
-import org.gudy.azureus2.plugins.sharing.ShareResourceFile;
+import org.gudy.azureus2.plugins.sharing.*;
 import org.gudy.azureus2.plugins.tracker.Tracker;
 import org.gudy.azureus2.plugins.tracker.TrackerTorrent;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;
+import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
 import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
-import org.gudy.azureus2.ui.swt.Alerts;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl;
 import org.gudy.azureus2.ui.swt.TorrentUtil;
 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 org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
+import org.gudy.azureus2.ui.webplugin.WebPlugin;
 
 import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManager;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
 import com.aelitis.azureus.core.util.AZ3Functions;
+import com.aelitis.azureus.core.util.HTTPUtils;
 import com.aelitis.azureus.core.util.LaunchManager;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
@@ -202,58 +216,1041 @@ public class ManagerUtils {
 								{
 									File this_file = file.getFile(true);
 									
-									File parent_file = (open_containing_folder_mode) ? this_file.getParentFile() : null;
+									File parent_file = (open_containing_folder_mode) ? this_file.getParentFile() : null;
+									
+									open((parent_file == null) ? this_file : parent_file);		
+								}
+							});
+					}
+					
+					public void
+					actionDenied(
+						Throwable			reason )
+					{
+						Debug.out( "Launch request denied", reason );
+					}
+				});
+		}
+	}
+	
+	
+	public static void open(File f, boolean open_containing_folder_mode) {
+		if (open_containing_folder_mode) {
+			Utils.launch(f.getParent());
+		}
+		else {
+			open(f);
+		}
+	}
+	
+	public static void open(File f) {
+		while (f != null && !f.exists())
+			f = f.getParentFile();
+
+		if (f == null)
+			return;
+
+		PlatformManager mgr = PlatformManagerFactory.getPlatformManager();
+
+		if (mgr.hasCapability(PlatformManagerCapabilities.ShowFileInBrowser)) {
+			try {
+				PlatformManagerFactory.getPlatformManager().showFile(f.toString());
+				return;
+			} catch (PlatformManagerException e) {
+				Debug.printStackTrace(e);
+			}
+		}
+
+		if (f.isDirectory()) {
+			Utils.launch(f.toString()); // default launcher
+		} else {
+			Utils.launch(f.getParent().toString());
+		}
+	}
+  
+	private static boolean
+	getBrowseAnon(
+		DownloadManager		dm )
+	{
+		boolean	anon = COConfigurationManager.getBooleanParameter( "Library.LaunchWebsiteInBrowserAnon" );
+		
+		if ( !anon ){
+		
+			boolean	found_pub = false;
+			
+			String[] nets = dm.getDownloadState().getNetworks();
+			
+			for ( String net: nets ){
+				
+				if ( net == AENetworkClassifier.AT_PUBLIC ){
+					
+					found_pub = true;
+					
+					break;
+				}
+			}
+			
+			if ( nets.length > 0 && !found_pub ){
+				
+				anon = true;
+			}
+		}
+		
+		return( anon );
+	}
+	
+	private static DiskManagerFileInfo
+	getBrowseHomePage(
+		DownloadManager		dm )
+	{
+		try{
+			DiskManagerFileInfo[] files = dm.getDiskManagerFileInfoSet().getFiles();
+										
+			for ( DiskManagerFileInfo file: files ){
+				
+				if ( file.getTorrentFile().getPathComponents().length == 1 ){
+					
+					String name = file.getTorrentFile().getRelativePath().toLowerCase( Locale.US );
+					
+					if ( name.equals( "index.html" ) || name.equals( "index.htm" )){
+						
+						return( file );
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+		
+		return( null );	
+	}
+	
+	public static boolean
+	browseWebsite(
+		DiskManagerFileInfo		file )
+	{
+		try{
+			String name = file.getTorrentFile().getRelativePath().toLowerCase( Locale.US );
+			
+			if ( name.equals( "index.html" ) || name.equals( "index.htm" )){
+				
+				ManagerUtils.browse( file );
+				
+				return( true );
+			}
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+		
+		return( false );
+	}
+	
+	public static boolean
+	browseWebsite(
+		DownloadManager		dm )
+	{
+		DiskManagerFileInfo file = getBrowseHomePage( dm );
+		
+		if ( file != null ){
+						
+			ManagerUtils.browse( file );
+			
+			return( true );
+		}
+	
+		return( false );
+	}
+	
+	public static String 
+	browse(
+		DiskManagerFileInfo 	file )
+	{
+		boolean anon = getBrowseAnon( file.getDownloadManager());
+		
+		return( browse( file, anon, true ));
+	}
+	
+	public static String 
+	browse(
+		DiskManagerFileInfo 	file,
+		boolean					anon,
+		boolean					launch )
+	{
+		return( browse( file.getDownloadManager(), file, anon, launch ));
+	}
+	
+	public static String 
+	browse(
+		DownloadManager 	dm )
+	{
+		boolean anon = getBrowseAnon( dm );
+		
+		return( browse( dm, null, anon, true ));
+	}
+	
+	public static String 
+	browse(
+		DownloadManager 	dm,
+		boolean				anon,
+		boolean				launch )
+	{
+		return( browse( dm, null, anon, launch ));
+	}
+	
+	private static Map<DownloadManager,WebPlugin>	browse_plugins = new IdentityHashMap<DownloadManager, WebPlugin>();
+	
+	public static String 
+	browse(
+		final DownloadManager 			dm,
+		DiskManagerFileInfo				_file,
+		final boolean					anon,
+		final boolean					launch )
+	{
+		Properties	props = new Properties();
+		
+		File	save_location = dm.getSaveLocation();
+		
+		final String	root_dir;
+		
+		if ( save_location.isFile()){
+			
+			root_dir = save_location.getParentFile().getAbsolutePath();
+			
+		}else{
+		
+			root_dir = save_location.getAbsolutePath();
+		}
+		
+		final String	url_suffix;
+		
+		boolean	always_browse = COConfigurationManager.getBooleanParameter( "Library.LaunchWebsiteInBrowserDirList" );
+		
+		if ( !always_browse ){
+			
+			if ( _file == null ){
+				
+				_file = getBrowseHomePage( dm );
+			}
+		}
+		
+		final DiskManagerFileInfo file = _file;
+		
+		if ( file == null ){
+				
+				// asked to launch a download (note that the double-click on a download that has an index.html file will by default result in
+				// us getting here with the file set, not null)
+			
+			url_suffix = "";
+				
+		}else{
+				
+			String relative_path = file.getTorrentFile().getRelativePath();
+								
+			String[] bits = relative_path.replace( File.separatorChar, '/' ).split( "/" );
+				
+			String _url_suffix = "";
+				
+			int	bits_to_use = always_browse?bits.length-1:bits.length;
+			
+			for ( int i=0;i<bits_to_use;i++){
+				
+				String bit = bits[i];
+				
+				if ( bit.length() == 0 ){
+					
+					continue;
+				}
+				
+				_url_suffix += (_url_suffix==""?"":"/") + UrlUtils.encode( bit );
+			}
+			
+			url_suffix = _url_suffix;
+		}
+		
+		synchronized( browse_plugins ){
+			
+			WebPlugin	plugin = browse_plugins.get( dm );
+		
+			if ( plugin == null ){
+			
+				props.put( WebPlugin.PR_PORT, 0 );
+				props.put( WebPlugin.PR_BIND_IP, "127.0.0.1" );
+				props.put( WebPlugin.PR_HOME_PAGE, "" );
+				props.put( WebPlugin.PR_ROOT_DIR, root_dir );
+				props.put( WebPlugin.PR_ACCESS, "local" );
+				props.put( WebPlugin.PR_HIDE_RESOURCE_CONFIG, true );
+				
+				props.put( WebPlugin.PR_ENABLE_KEEP_ALIVE, true );
+				props.put( WebPlugin.PR_ENABLE_PAIRING, false );
+				props.put( WebPlugin.PR_ENABLE_UPNP, false );
+				props.put( WebPlugin.PR_ENABLE_I2P, false );
+				props.put( WebPlugin.PR_ENABLE_TOR, false );
+				
+				final String plugin_id 		= "webserver:" + dm.getInternalName();
+				final String plugin_name	= "Web Server for " + dm.getDisplayName();
+				
+				Properties messages = new Properties();
+				
+				messages.put( "plugins." + plugin_id, plugin_name );;
+		
+				PluginInitializer.getDefaultInterface().getUtilities().getLocaleUtilities().integrateLocalisedMessageBundle( messages );
+				
+				final AESemaphore 	waiter 		= new AESemaphore( "waiter" );
+				final String[]		url_holder	= { null };
+				
+				plugin = 
+					new UnloadableWebPlugin( props )
+					{
+						private Map<String,Object>	file_map = new HashMap<String,Object>();
+						
+						private String	host;
+						
+						@Override
+						public void 
+						initialize(
+							PluginInterface plugin_interface )
+								throws PluginException 
+						{
+							DiskManagerFileInfoSet file_set = dm.getDiskManagerFileInfoSet();
+							
+							DiskManagerFileInfo[] files = file_set.getFiles();
+							
+							Set<Object>	root_dir = new HashSet<Object>();
+							
+							file_map.put( "", root_dir );
+
+							for ( DiskManagerFileInfo dm_file: files ){
+												
+								TOTorrentFile file = dm_file.getTorrentFile();
+								
+								String	path = file.getRelativePath();
+								
+								file_map.put( path, dm_file );
+								
+								if ( path.startsWith( File.separator )){
+									
+									path = path.substring( 1 );
+								}
+								
+								Set<Object>	dir = root_dir;
+								
+								int	pos = 0;
+																
+								while( true ){
+									
+									int next_pos = path.indexOf( File.separatorChar, pos );
+									
+									if ( next_pos == -1 ){
+																				
+										dir.add( dm_file );
+										
+										break;
+										
+									}else{
+										
+										String bit = path.substring( pos, next_pos );
+										
+										dir.add( bit );
+										
+										String sub_path = path.substring( 0, next_pos );
+										
+										dir = (Set<Object>)file_map.get( sub_path );
+										
+										if ( dir == null ){
+											
+											dir = new HashSet<Object>();
+											
+											file_map.put( sub_path, dir );
+										}
+										
+										pos = next_pos + 1;
+									}
+								}
+							}
+							
+							Properties props = plugin_interface.getPluginProperties();
+							
+							props.put( "plugin.name", plugin_name );
+							
+							super.initialize( plugin_interface );
+							
+							InetAddress	bind_ip = getServerBindIP();
+														
+							if ( bind_ip.isAnyLocalAddress()){
+								
+								host = "127.0.0.1";
+								
+							}else{
+								
+								host = bind_ip.getHostAddress();
+							}
+							
+							int port = getServerPort();
+							
+							log( "Assigned port: " + port );
+							
+							String protocol = getProtocol();
+
+							String url = protocol + "://" + host + ":" + port + "/" + url_suffix;
+							
+							if ( launch ){
+							
+								Utils.launch( url, false, true, anon );
+								
+							}else{
+								
+								synchronized( url_holder ){
+									
+									url_holder[0] = url;
+								}
+								
+								waiter.release();
+							}
+						}
+						
+						@Override
+						public boolean
+						generate(
+							TrackerWebPageRequest		request,
+							TrackerWebPageResponse		response )
+						
+							throws IOException
+						{
+							try{
+								boolean res = super.generate(request, response);
+								
+								if ( !res ){
+									
+									response.setReplyStatus( 404 );
+								}
+							}catch( Throwable e ){
+								
+								response.setReplyStatus( 404 );
+							}
+							
+							return( true );
+						}
+						
+						@Override
+						protected boolean
+						useFile(
+							TrackerWebPageRequest				request,
+							final TrackerWebPageResponse		response,
+							String								root,
+							String								relative_url )
+							
+							throws IOException
+						{
+							URL absolute_url = request.getAbsoluteURL();
+							
+							String path = absolute_url.getPath();
+							
+							if ( path.equals( "/" )){
+								
+								if ( COConfigurationManager.getBooleanParameter( "Library.LaunchWebsiteInBrowserDirList" )){
+
+									relative_url = "/";
+								}
+							}
+							
+							String download_name = XUXmlWriter.escapeXML( dm.getDisplayName());
+							
+							String relative_file = relative_url.replace( '/', File.separatorChar );
+							
+							String	node_key = relative_file.substring( 1 );
+							
+							Object	file_node = file_map.get( node_key );
+							
+							boolean	file_node_is_parent = false;
+							
+							if ( file_node == null ){
+								
+								int pos = node_key.lastIndexOf( File.separator );
+								
+								if ( pos == -1 ){
+									
+									node_key = "";
+									
+								}else{
+									
+									node_key = node_key.substring( 0, pos );
+								}
+								
+								file_node = file_map.get( node_key );
+								
+								file_node_is_parent = true;
+							}
+									
+							if ( file_node == null){
+		
+								return( false );
+							}
+									
+							if ( file_node instanceof Set ){
+									
+								Set<Object>		kids = (Set<Object>)file_node;
+								
+								String request_url = request.getURL();
+								
+								if ( file_node_is_parent ){
+									
+									int	pos = request_url.lastIndexOf( "/" );
+									
+									if ( pos == -1 ){
+										
+										request_url = "";
+										
+									}else{
+										
+										request_url = request_url.substring( 0, pos );
+									}
+								}
+																
+								response.setContentType( "text/html" );
+								
+								OutputStream os = response.getOutputStream();
+																
+								String NL = "\r\n";
+								
+								String title = XUXmlWriter.escapeXML( UrlUtils.decode( request_url ));
+								
+								if ( title.length() == 0 ){
+									
+									title = "/";
+								}
+								
+								os.write((
+									"<html>" + NL +
+									" <head>" + NL +
+									" <meta charset=\"UTF-8\">" + NL + 
+									"  <title>" + download_name + ": Index of " + title + "</title>" + NL +
+									" </head>" + NL +
+									" <body>" + NL +
+									"  <p>" + download_name + "</p>" + NL + 
+									"  <h1>Index of " + title + "</h1>" + NL +
+									"  <pre><hr>" + NL ).getBytes( "UTF-8" ));
+								
+								String root_url = request_url;
+								
+								if ( !root_url.endsWith( "/" )){
+									
+									root_url += "/";
+								}
+								
+								if ( request_url.length() > 1 ){
+									
+									int	pos = request_url.lastIndexOf( '/' );
+									
+									if ( pos == 0 ){
+										
+										pos++;
+									}
+									
+									String parent = request_url.substring( 0, pos );
+									
+									os.write(( "<a href=\"" + parent + "\">..</a>" + NL).getBytes( "UTF-8" ));
+								}
+							
+								List<String[]>	filenames		= new ArrayList<String[]>( kids.size());
+								int				max_filename	= 0;
+								
+								int MAX_LEN = 120;
+								
+								for ( Object	entry: kids ){
+									
+									DiskManagerFileInfo		file;
+									String					file_name;
+									
+									if ( entry instanceof String ){
+										
+										file = null;
+										
+										file_name	= (String)entry;
+										
+									}else{
+										
+										file = (DiskManagerFileInfo)entry;
+										
+										if ( file.isSkipped()){
+											
+											continue;
+										}
+										
+										file_name 	= file.getTorrentFile().getRelativePath();
+										
+										int pos = file_name.lastIndexOf( File.separatorChar );
+										
+										if ( pos != -1 ){
+											
+											file_name = file_name.substring( pos+1 );
+										}
+									}
+																		
+									String url			= root_url + UrlUtils.encode( file_name );
+											
+									if ( file == null ){
+										
+										file_name += "/";
+									}
+									
+									int len = file_name.length();
+									
+									if ( len > MAX_LEN ){
+										
+										file_name = file_name.substring( 0, MAX_LEN-3 ) + "...";
+										
+										len = file_name.length();
+									}
+									
+									if ( len > max_filename ){
+										
+										max_filename = len;
+									}
+									
+									filenames.add( new String[]{ url, file_name, file==null?"":DisplayFormatters.formatByteCountToKiBEtc( file.getLength())});
+								}
+								
+								max_filename = ((max_filename + 15 )/8)*8;
+								
+								char[]	padding = new char[max_filename];
+								
+								Arrays.fill( padding, ' ' );
+								
+								Collections.sort(
+									filenames,
+									new Comparator<String[]>()
+									{
+										Comparator comp = new FormattersImpl().getAlphanumericComparator(true);
+										
+										public int 
+										compare(
+											String[] o1,
+											String[] o2) 
+										{
+											return( comp.compare(o1[0], o2[0] ));
+										}
+									});
+								
+								for ( String[] entry: filenames ){
+									
+									String file_name = entry[1];
+								
+									int	len = file_name.length();
+																		
+									StringBuffer line = new StringBuffer( max_filename + 64 );
+									
+									line.append( "<a href=\"" + entry[0] + "\">" + XUXmlWriter.escapeXML( file_name ) + "</a>" );
+									
+									line.append( padding, 0, max_filename - len );
+									
+									line.append(  entry[2] );
+									
+									line.append( NL );
+										
+									os.write( line.toString().getBytes( "UTF-8" ));
+								}
+								
+								os.write((
+								"  <hr></pre>" + NL +
+								"  <address>Vuze Web Server at " + host + " Port " + getServerPort() +"</address>" + NL +
+								" </body>" + NL +
+								"</html>" ).getBytes( "UTF-8" ));
+								
+								return( true );
+								
+							}else{
+							
+								DiskManagerFileInfo dm_file = (DiskManagerFileInfo)file_node;
+								
+								long	file_size = dm_file.getLength();
+								
+								File target_file = dm_file.getFile( true );
+								
+								boolean done = 	dm_file.getDownloaded() == file_size && 
+												target_file.length() == file_size;
+	
+									// for big files see if we can hand off all processing to the
+									// media server
+								
+								if ( file_size >= 512*1024 ){
+									
+									URL stream_url = getMediaServerContentURL( dm_file );
+
+									if ( stream_url != null ){
+										
+										OutputStream os = response.getRawOutputStream();
+										
+										os.write((
+											"HTTP/1.1 302 Found" + NL +
+											"Location: " + stream_url.toExternalForm() + NL +
+											NL ).getBytes( "UTF-8" ));
+										
+										return( true );
+									}
+								}
+								
+								String	file_type;
+								
+									// Use the original torrent file name when deducing file type to 
+									// avoid incomplete suffix issues etc
+								
+								String relative_path = dm_file.getTorrentFile().getRelativePath();
+								
+								int	pos = relative_path.lastIndexOf( "." );
+		
+								if ( pos == -1 ){
+		
+									file_type = "";
+									
+								}else{
+		
+									file_type = relative_path.substring(pos+1);
+								}
+								
+								if ( done ){
+									
+									if ( file_size < 512*1024 ){
+									
+
+										
+										FileInputStream	fis = null;
+				
+										try{
+											fis = new FileInputStream(target_file);
+				
+											response.useStream( file_type, fis );
+				
+											return( true );
+				
+										}finally{
+				
+											if ( fis != null ){
+				
+												fis.close();
+											}
+										}
+									}else{
+											
+										
+										OutputStream 	os 	= null;
+										InputStream 	is	= null;
+										
+										try{
+											os = response.getRawOutputStream();
+											
+											byte[] buffer = new byte[128*1024];
+											
+											is = new FileInputStream( target_file );
+											
+											while( true ){
+												
+												int len = is.read( buffer );
+												
+												if ( len <= 0 ){
+													
+													break;
+												}
+												
+												os.write( buffer, 0, len );
+											}
+										}catch( Throwable e ){
+											
+											//e.printStackTrace();
+											
+										}finally{
+											
+											try{
+												os.close();
+												
+											}catch( Throwable e ){
+											}
+											
+											try{
+												is.close();
+												
+											}catch( Throwable e ){
+											}
+											
+				
+										}
+								
+										return( true );
+									}
+							
+								}else{
+									
+									dm_file.setPriority(10);
 									
-									open((parent_file == null) ? this_file : parent_file);		
+									try{
+										final OutputStream os = response.getRawOutputStream();
+										
+										os.write((
+												"HTTP/1.1 200 OK" + NL +
+												"Content-Type:" + HTTPUtils.guessContentTypeFromFileType( file_type ) + NL +
+												"Content-Length: " + file_size + NL +
+												"Connection: close" + NL +
+												"X-Vuze-Hack: X" ).getBytes( "UTF-8" ));
+										
+										DiskManagerChannel chan = PluginCoreUtils.wrap( dm_file ).createChannel();
+										
+										final DiskManagerRequest req = chan.createRequest();
+										
+										final boolean[] header_complete = { false };
+										final long[]	last_write		= { 0 };
+										
+										req.setOffset( 0 );
+										req.setLength( file_size );
+																				
+										req.addListener(
+											new DiskManagerListener()
+											{
+												public void
+												eventOccurred(
+													DiskManagerEvent	event )
+												{
+													int	type = event.getType();
+													
+													if ( type ==  DiskManagerEvent.EVENT_TYPE_BLOCKED ){
+													
+														return;
+														
+													}else if ( type == DiskManagerEvent.EVENT_TYPE_FAILED ){
+														
+														throw( new RuntimeException( event.getFailure()));
+													}
+													
+													PooledByteBuffer buffer = event.getBuffer();
+													
+													if ( buffer == null ){
+														
+														throw( new RuntimeException( "eh?" ));
+													}
+
+													try{
+
+														boolean	do_header = false;
+														
+														synchronized( header_complete ){
+															
+															if ( !header_complete[0] ){
+																
+																do_header = true;
+																
+																header_complete[0] = true;
+															}
+															
+															last_write[0] = SystemTime.getMonotonousTime();
+														}
+														
+														if ( do_header ){
+															
+															os.write((NL+NL).getBytes( "UTF-8" ));
+														}
+																	
+														byte[] data = buffer.toByteArray();
+														
+														os.write( data );
+														
+													}catch( IOException e ){
+														
+														throw( new RuntimeException( "Failed to write to " + file, e ));
+														
+													}finally{
+														
+														buffer.returnToPool();
+													}
+												}
+											});
+									
+										final TimerEventPeriodic timer_event [] = {null};
+										
+										timer_event[0] =
+											SimpleTimer.addPeriodicEvent(
+												"KeepAlive",
+												10*1000,
+												new TimerEventPerformer() 
+												{
+													boolean	cancel_outstanding = false;
+													
+													public void 
+													perform(
+														TimerEvent event) 
+													{
+														if ( cancel_outstanding ){
+															
+															req.cancel();
+															
+														}else{
+															
+															synchronized( header_complete ){
+																
+																if ( header_complete[0] ){
+																	
+																	if ( SystemTime.getMonotonousTime() - last_write[0] >= 5*60*1000 ){
+																		
+																		req.cancel();
+																	}
+																}else{
+																	
+																	try{
+																		os.write( "X".getBytes( "UTF-8" ));
+																		
+																		os.flush();
+																		
+																	}catch( Throwable e ){
+																		
+																		req.cancel();
+																	}
+																}
+															}
+															
+															if ( !response.isActive()){
+																
+																cancel_outstanding = true;
+															}
+														}
+													}
+												});
+										
+										try{
+											req.run();
+										
+										}finally{
+											
+											timer_event[0].cancel();
+										}
+										
+										return( true );
+										
+									}catch( Throwable e ){
+										
+										return( false );
+									}
 								}
-							});
-					}
+							}
+						}
+						
+						public void 
+						unload() 
+							throws PluginException 
+						{
+							synchronized( browse_plugins ){
+								
+								 browse_plugins.remove( dm );
+							}
+							
+							super.unload();
+						}
+					};
+								
+				PluginManager.registerPlugin(
+					plugin,
+					plugin_id,
+					plugin_id );
+				
+				browse_plugins.put( dm, plugin );
+				
+				if ( launch ){
 					
-					public void
-					actionDenied(
-						Throwable			reason )
-					{
-						Debug.out( "Launch request denied", reason );
+					return( null );
+					
+				}else{
+					
+					waiter.reserve( 10*1000 );
+					
+					synchronized( url_holder ){
+						
+						return( url_holder[0] );
 					}
-				});
+				}
+			}else{
+				
+				String protocol = plugin.getProtocol();
+				
+				InetAddress	bind_ip = plugin.getServerBindIP();
+
+				String	host;
+				
+				if ( bind_ip.isAnyLocalAddress()){
+					
+					host = "127.0.0.1";
+					
+				}else{
+					
+					host = bind_ip.getHostAddress();
+				}
+				
+				String url = protocol + "://" + host+ ":" + plugin.getServerPort() + "/" + url_suffix;
+				
+				if ( launch ){
+				
+					Utils.launch( url, false, true, anon );
+					
+					return( null );
+					
+				}else{
+					
+					return( url );
+				}
+			}
 		}
 	}
+
+	public static URL 
+	getMediaServerContentURL(
+		DiskManagerFileInfo file ) 
+	{
+		PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager();
+		
+		PluginInterface pi = pm.getPluginInterfaceByID( "azupnpav", false );
 	
+		if ( pi == null ){
+			
+			return( null );
+		}
 	
-	public static void open(File f, boolean open_containing_folder_mode) {
-		if (open_containing_folder_mode) {
-			Utils.launch(f.getParent());
+		if ( !pi.getPluginState().isOperational()){
+			
+			return( null );
 		}
-		else {
-			open(f);
+	
+		try{						
+			Object	url = pi.getIPC().invoke( "getContentURL", new Object[]{ PluginCoreUtils.wrap( file )});
+			
+			if ( url instanceof String ){
+				
+				return( new URL( (String) url));
+			}
+		}catch ( Throwable e ){
+			
+			e.printStackTrace();
 		}
+	
+		return( null );
 	}
 	
-	public static void open(File f) {
-		while (f != null && !f.exists())
-			f = f.getParentFile();
-
-		if (f == null)
-			return;
-
-		PlatformManager mgr = PlatformManagerFactory.getPlatformManager();
-
-		if (mgr.hasCapability(PlatformManagerCapabilities.ShowFileInBrowser)) {
-			try {
-				PlatformManagerFactory.getPlatformManager().showFile(f.toString());
-				return;
-			} catch (PlatformManagerException e) {
-				Debug.printStackTrace(e);
-			}
+	private static class
+	UnloadableWebPlugin
+		extends WebPlugin
+		implements UnloadablePlugin
+	{
+		private
+		UnloadableWebPlugin(
+			Properties		props )
+		{
+			super( props );
 		}
-
-		if (f.isDirectory()) {
-			Utils.launch(f.toString()); // default launcher
-		} else {
-			Utils.launch(f.getParent().toString());
+		
+		public void 
+		unload() 
+			throws PluginException 
+		{
+			super.unloadPlugin();
 		}
 	}
-  
+	
   public static boolean isStartable(DownloadManager dm) {
     if(dm == null)
       return false;
@@ -275,6 +1272,18 @@ public class ManagerUtils {
     return true;
   }
   
+  public static boolean isPauseable(DownloadManager dm) {
+	    if(dm == null)
+	      return false;
+	    int state = dm.getState();
+	    if (	state == DownloadManager.STATE_STOPPED ||
+	    		state == DownloadManager.STATE_STOPPING	||
+	    		state == DownloadManager.STATE_ERROR ) {
+	      return false;
+	    }
+	    return true;
+	  }
+  
   public static boolean isStopped(DownloadManager dm) {
 	    if(dm == null)
 	      return false;
@@ -305,47 +1314,67 @@ public class ManagerUtils {
     return( true );
   }
   
+  /**
+   * Host a DownloadManager on our Tracker.
+   * <P>
+   * Doesn't require SWT Thread
+   */
   public static void 
   host(
   	AzureusCore		azureus_core,
-	DownloadManager dm,
-	Composite 		panel) 
-  {
-    if(dm == null)
-      return;
-    TOTorrent torrent = dm.getTorrent();
-    if (torrent != null) {
-      try {
-      	azureus_core.getTrackerHost().hostTorrent(torrent, true, false );
-      } catch (TRHostException e) {
-        MessageBox mb = new MessageBox(panel.getShell(), SWT.ICON_ERROR | SWT.OK);
-        mb.setText(MessageText.getString("MyTorrentsView.menu.host.error.title"));
-        mb.setMessage(MessageText.getString("MyTorrentsView.menu.host.error.message").concat("\n").concat(e.toString()));
-        mb.open();
-      }
-    }
-  }
+	DownloadManager dm)
+ {
+		if (dm == null) {
+			return;
+		}
+
+		TOTorrent torrent = dm.getTorrent();
+		if (torrent == null) {
+			return;
+		}
+
+		try {
+			azureus_core.getTrackerHost().hostTorrent(torrent, true, false);
+		} catch (TRHostException e) {
+			MessageBoxShell mb = new MessageBoxShell(
+					SWT.ICON_ERROR | SWT.OK,
+					MessageText.getString("MyTorrentsView.menu.host.error.title"),
+					MessageText.getString("MyTorrentsView.menu.host.error.message").concat(
+							"\n").concat(e.toString()));
+			mb.open(null);
+		}
+	}
   
+  /**
+   * Publish a DownloadManager on our Tracker.
+   * <P>
+   * Doesn't require SWT Thread
+   */
   public static void 
   publish(
   		AzureusCore		azureus_core,
-		DownloadManager dm,
-		Composite		 panel) 
-  {
-    if(dm == null)
-     return;
-    TOTorrent torrent = dm.getTorrent();
-    if (torrent != null) {
-      try {
-      	azureus_core.getTrackerHost().publishTorrent(torrent);
-      } catch (TRHostException e) {
-        MessageBox mb = new MessageBox(panel.getShell(), SWT.ICON_ERROR | SWT.OK);
-        mb.setText(MessageText.getString("MyTorrentsView.menu.host.error.title"));
-        mb.setMessage(MessageText.getString("MyTorrentsView.menu.host.error.message").concat("\n").concat(e.toString()));
-        mb.open();
-      }
-    }
-  }
+		DownloadManager dm)
+ {
+		if (dm == null) {
+			return;
+		}
+
+		TOTorrent torrent = dm.getTorrent();
+		if (torrent == null) {
+			return;
+		}
+
+		try {
+			azureus_core.getTrackerHost().publishTorrent(torrent);
+		} catch (TRHostException e) {
+			MessageBoxShell mb = new MessageBoxShell(
+					SWT.ICON_ERROR | SWT.OK,
+					MessageText.getString("MyTorrentsView.menu.host.error.title"),
+					MessageText.getString("MyTorrentsView.menu.host.error.message").concat(
+							"\n").concat(e.toString()));
+			mb.open(null);
+		}
+	}
   
   
   public static void 
@@ -644,4 +1673,250 @@ public class ManagerUtils {
 					}
 				});
 	}
+	
+	public static void 
+	asyncPauseForPeriod(
+		final List<DownloadManager>		dms,
+		final int 						seconds ) 
+	{
+		CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD,
+				new AzureusCoreRunningListener() {
+					public void azureusCoreRunning(AzureusCore core) 
+					{
+						
+						final List<DownloadManager>		paused = new ArrayList<DownloadManager>();
+						
+						final DownloadManagerListener listener = 
+							new DownloadManagerAdapter()
+							{
+								public void 
+								stateChanged(
+									DownloadManager 	manager, 
+									int 				state )
+								{
+									synchronized( paused ){
+									
+										if ( !paused.remove( manager )){
+											
+											return;
+										}
+									}
+									
+									manager.removeListener( this );
+								}
+							};
+						
+						for ( DownloadManager dm: dms ){
+							
+							if ( !isPauseable( dm )){
+								
+								continue;
+							}
+							
+							if ( dm.pause()){
+							
+								synchronized( paused ){
+									
+									paused.add( dm );
+								}
+								
+								dm.addListener( listener, false );
+							}
+						}
+						
+						if ( paused.size() > 0 ){
+							
+							SimpleTimer.addEvent(
+								"ManagerUtils.resumer",
+								SystemTime.getOffsetTime( seconds*1000),
+								new TimerEventPerformer()
+								{	
+									public void 
+									perform(
+										TimerEvent event ) 
+									{
+										List<DownloadManager>	to_resume = new ArrayList<DownloadManager>();
+										
+										synchronized( paused ){
+											
+											to_resume.addAll( paused );
+											
+											paused.clear();
+										}
+										
+										for ( DownloadManager dm: to_resume ){
+											
+											dm.removeListener( listener );
+											
+											try{
+												dm.resume();
+												
+											}catch( Throwable e ){
+												
+												Debug.out( e );
+											}
+										}
+									}
+								});
+						}
+					}
+				});
+	}
+	
+	public static class
+	ArchiveCallback
+	{
+		public void
+		success(
+			DownloadStub		source,
+			DownloadStub		target )
+		{
+		}
+		
+		public void
+		failed(
+			DownloadStub		original,
+			Throwable			error )
+		{
+		}
+		
+		public void
+		completed()
+		{
+		}
+	}
+	
+	
+	public static void
+	moveToArchive(
+		final List<Download>	downloads,
+		ArchiveCallback			_run_when_complete )
+	{
+		final ArchiveCallback run_when_complete=_run_when_complete==null?new ArchiveCallback():_run_when_complete;
+
+		Utils.getOffOfSWTThread(
+			new AERunnable() {
+				
+				@Override
+				public void 
+				runSupport() 
+				{
+					try{
+						String title 	= MessageText.getString( "archive.info.title" );
+						String text 	= MessageText.getString( "archive.info.text" );
+						
+						MessageBoxShell prompter = 
+							new MessageBoxShell(
+								title, text, 
+								new String[] { MessageText.getString("Button.ok") }, 0 );
+					
+						
+						String remember_id = "managerutils.archive.info";
+						
+						prompter.setRemember( 
+							remember_id, 
+							true,
+							MessageText.getString("MessageBoxWindow.nomoreprompting"));
+										
+						prompter.setAutoCloseInMS(0);
+						
+						prompter.open( null );
+						
+						prompter.waitUntilClosed();
+						
+						for ( Download dm: downloads ){
+							
+							try{
+								DownloadStub stub = dm.stubbify();
+								
+								run_when_complete.success( dm, stub );
+								
+							}catch( Throwable e ){
+								
+								run_when_complete.failed( dm, e );
+								
+								Debug.out( e );
+							}
+						}
+					}finally{
+					
+						run_when_complete.completed();
+					}
+				}
+			});
+	}
+	
+	public static void
+	restoreFromArchive(
+		final List<DownloadStub>		downloads,
+		final boolean					start,
+		ArchiveCallback					_run_when_complete )
+	{
+		final ArchiveCallback run_when_complete=_run_when_complete==null?new ArchiveCallback():_run_when_complete;
+		
+		Utils.getOffOfSWTThread(
+			new AERunnable() {
+				
+				@Override
+				public void 
+				runSupport() 
+				{
+					try{
+						Tag	tag = null;
+						
+						try{
+							TagManager	tm = TagManagerFactory.getTagManager();
+							
+							TagType tt = tm.getTagType( TagType.TT_DOWNLOAD_MANUAL );
+							
+							String tag_name = MessageText.getString( "label.restored" );
+							
+							tag = tt.getTag( tag_name, true );
+							
+							if ( tag == null ){	
+							
+								tag = tt.createTag( tag_name, true );
+							}
+						}catch( Throwable e ){
+									
+							Debug.out( e );
+						}
+						
+						for ( DownloadStub dm: downloads ){
+							
+							try{
+								Download dl = dm.destubbify();
+								
+								if ( dl != null ){
+																		
+									run_when_complete.success( dm, dl );
+									
+									if ( tag != null ){
+									
+										tag.addTaggable(PluginCoreUtils.unwrap( dl ));
+									}
+									
+									if ( start ){
+										
+										start( PluginCoreUtils.unwrap( dl ));
+									}
+								}else{
+									
+									run_when_complete.failed( dm, new Exception( "Unknown error" ));
+								}
+								
+							}catch( Throwable e ){
+								
+								run_when_complete.failed( dm, e );
+								
+								Debug.out( e );
+							}
+						}
+					}finally{
+													
+						run_when_complete.completed();
+					}
+				}
+			});
+	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/TagUIUtils.java b/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/TagUIUtils.java
index 411d1e6..48a6123 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/TagUIUtils.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/views/utils/TagUIUtils.java
@@ -1,10 +1,12 @@
 /**
  * Created on Nov 15, 2010
  *
- * Copyright 2010 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -19,34 +21,25 @@
 package org.gudy.azureus2.ui.swt.views.utils;
 
 import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
+import java.util.*;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.RGB;
 import org.eclipse.swt.widgets.*;
+
 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.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.gudy.azureus2.core3.util.TrackersUtil;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
 import org.gudy.azureus2.plugins.ui.menus.MenuManager;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
 import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl;
-import org.gudy.azureus2.ui.swt.MenuBuildUtils;
-import org.gudy.azureus2.ui.swt.Messages;
-import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow;
-import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.common.util.MenuItemManager;
+import org.gudy.azureus2.ui.swt.*;
+import org.gudy.azureus2.ui.swt.mainwindow.MenuFactory;
 import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
 import org.gudy.azureus2.ui.swt.maketorrent.MultiTrackerEditor;
 import org.gudy.azureus2.ui.swt.maketorrent.TrackerEditorListener;
@@ -58,26 +51,12 @@ import org.gudy.azureus2.ui.swt.views.stats.StatsView;
 import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.AzureusCoreRunningListener;
-import com.aelitis.azureus.core.tag.Tag;
-import com.aelitis.azureus.core.tag.TagDownload;
-import com.aelitis.azureus.core.tag.TagException;
-import com.aelitis.azureus.core.tag.TagFeature;
-import com.aelitis.azureus.core.tag.TagFeatureFileLocation;
-import com.aelitis.azureus.core.tag.TagFeatureProperties;
+import com.aelitis.azureus.core.tag.*;
 import com.aelitis.azureus.core.tag.TagFeatureProperties.TagProperty;
-import com.aelitis.azureus.core.tag.TagFeatureRSSFeed;
-import com.aelitis.azureus.core.tag.TagFeatureRateLimit;
-import com.aelitis.azureus.core.tag.TagFeatureRunState;
-import com.aelitis.azureus.core.tag.TagFeatureTranscode;
-import com.aelitis.azureus.core.tag.TagManager;
-import com.aelitis.azureus.core.tag.TagManagerFactory;
-import com.aelitis.azureus.core.tag.TagType;
-import com.aelitis.azureus.core.tag.Taggable;
 import com.aelitis.azureus.core.util.AZ3Functions;
-import com.aelitis.azureus.ui.UIFunctions;
-import com.aelitis.azureus.ui.UIFunctionsManager;
-import com.aelitis.azureus.ui.UIFunctionsUserPrompter;
-import com.aelitis.azureus.ui.UserPrompterResultListener;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy;
+import com.aelitis.azureus.ui.*;
 import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 
 /**
@@ -88,6 +67,13 @@ import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 public class TagUIUtils
 {
 	public static final int MAX_TOP_LEVEL_TAGS_IN_MENU	= 20;
+		
+	public static String
+	getChatKey(
+		Tag		tag )
+	{
+		return( "Tag: " + tag.getTagName( true ));
+	}
 	
 	public static void
 	setupSideBarMenus(
@@ -145,6 +131,8 @@ public class TagUIUtils
 						boolean	all_visible 	= true;
 						boolean all_invisible 	= true;
 
+						boolean	has_ut	= false;
+						
 						for ( Tag t: all_tags ){
 								
 							String name = t.getTagName( true );
@@ -157,6 +145,20 @@ public class TagUIUtils
 							}else{
 								all_visible = false;
 							}
+							
+							TagFeatureProperties props = (TagFeatureProperties)t;
+							
+							TagProperty prop = props.getProperty( TagFeatureProperties.PR_UNTAGGED );
+									
+							if ( prop != null ){
+								
+								Boolean b = prop.getBoolean();
+								
+								if ( b != null && b ){
+									
+									has_ut = true;
+								}
+							}
 						}
 						
 						org.gudy.azureus2.plugins.ui.menus.MenuItem showAllItem = menuManager.addMenuItem( menu, "label.show.all" );
@@ -270,6 +272,48 @@ public class TagUIUtils
 									});
 							}
 						}
+						
+						if ( !has_ut ){
+							
+							sepItem = menuManager.addMenuItem( menu, "sepu" );
+
+							sepItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_SEPARATOR );
+							
+							
+							org.gudy.azureus2.plugins.ui.menus.MenuItem m = menuManager.addMenuItem( menu, "label.untagged" );
+							
+							m.setStyle( org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_PUSH );
+																							
+							m.addListener(
+								new MenuItemListener() 
+								{
+									public void
+									selected(
+										org.gudy.azureus2.plugins.ui.menus.MenuItem			menu,
+										Object 												target )
+									{						
+										try{
+											String tag_name = MessageText.getString( "label.untagged" );
+											
+											Tag ut_tag = manual_tt.getTag( tag_name, true );
+											
+											if ( ut_tag == null ){
+												
+											
+												ut_tag = manual_tt.createTag( tag_name, true );
+											}
+											
+											TagFeatureProperties tp = (TagFeatureProperties)ut_tag;
+											
+											tp.getProperty( TagFeatureProperties.PR_UNTAGGED ).setBoolean( true );
+											
+										}catch( TagException e ){
+												
+											Debug.out( e );
+										}
+									}
+								});
+						}
 					}
 				});
 				
@@ -277,7 +321,7 @@ public class TagUIUtils
 				
 				menuItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
 					public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
-						createManualTag();
+						createManualTag(null);
 					}
 				});
 				
@@ -435,7 +479,7 @@ public class TagUIUtils
 				menuItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
 					public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
 						UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
-						uiFunctions.getMDI().loadEntryByID(StatsView.VIEW_ID, true, false, "TagStatsView");
+						uiFunctions.getMDI().showEntryByID(StatsView.VIEW_ID, "TagStatsView");
 
 					}
 				});
@@ -445,8 +489,7 @@ public class TagUIUtils
 				menuItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
 					public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
 						UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
-						uiFunctions.openView( UIFunctions.VIEW_TAGS_OVERVIEW, null);
-
+						uiFunctions.getMDI().showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_TAGS);
 					}
 				});
 			}
@@ -529,35 +572,14 @@ public class TagUIUtils
 		}
 	}
 	
-	public static Tag
-	createManualTag()
+	public static void
+	createManualTag(
+		UIFunctions.TagReturner tagReturner)
 	{
-		SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
-				"TagAddWindow.title", "TagAddWindow.message");
-		
-		entryWindow.prompt();
-		
-		if (entryWindow.hasSubmittedInput()) {
-			String tag_name = entryWindow.getSubmittedInput().trim();
-			TagType tt = TagManagerFactory.getTagManager().getTagType( TagType.TT_DOWNLOAD_MANUAL );
-			
-			Tag existing = tt.getTag( tag_name, true );
-			
-			if ( existing == null ){
-				
-				try{
-					checkTagSharing( false );
-					
-					return( tt.createTag( tag_name, true ));
-					
-				}catch( TagException e ){
-					
-					Debug.out( e );
-				}
-			}
+		UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+		if (uiFunctions != null) {
+			uiFunctions.showCreateTagDialog(tagReturner);
 		}
-		
-		return( null );
 	}
 	
 	public static void 
@@ -589,9 +611,24 @@ public class TagUIUtils
 				int down_speed 	= tf_rate_limit.getTagDownloadLimit();
 				int up_speed 	= tf_rate_limit.getTagUploadLimit();
 	
-				ViewUtils.addSpeedMenu(menu.getShell(), menu, has_up, has_down, true, true, false,
-						down_speed == 0, down_speed, down_speed, maxDownload, false,
-						up_speed == 0, up_speed, up_speed, maxUpload, 1, new SpeedAdapter() {
+				Map<String,Object> menu_properties = new HashMap<String,Object>();
+				
+				if ( tag_type.getTagType() == TagType.TT_PEER_IPSET || tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL ){
+				
+					if ( has_up ){
+						menu_properties.put( ViewUtils.SM_PROP_PERMIT_UPLOAD_DISABLE, true );
+					}
+					if ( has_down ){
+						menu_properties.put( ViewUtils.SM_PROP_PERMIT_DOWNLOAD_DISABLE, true );
+					}
+				}
+				
+				ViewUtils.addSpeedMenu(
+						menu.getShell(), menu, has_up, has_down, true, true, 
+						down_speed == -1, down_speed == 0, down_speed, down_speed, maxDownload, 
+						up_speed == -1,	up_speed == 0, up_speed, up_speed, maxUpload, 
+						1,	menu_properties,
+						new SpeedAdapter() {
 							public void setDownSpeed(int val) {
 								tf_rate_limit.setTagDownloadLimit(val);
 							}
@@ -816,116 +853,11 @@ public class TagUIUtils
 			}
 		}
 		
-		/*
-
-
-		// share with friends
-
-		PluginInterface bpi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByClass(
-				BuddyPlugin.class);
-
-		int cat_type = category.getType();
-
-		if (bpi != null && cat_type != Category.TYPE_UNCATEGORIZED) {
-
-			final BuddyPlugin buddy_plugin = (BuddyPlugin) bpi.getPlugin();
-
-			if (buddy_plugin.isEnabled()) {
-
-				final Menu share_menu = new Menu(menu.getShell(), SWT.DROP_DOWN);
-				final MenuItem share_item = new MenuItem(menu, SWT.CASCADE);
-				Messages.setLanguageText(share_item, "azbuddy.ui.menu.cat.share");
-				share_item.setMenu(share_menu);
-
-				List<BuddyPluginBuddy> buddies = buddy_plugin.getBuddies();
-
-				if (buddies.size() == 0) {
-
-					final MenuItem item = new MenuItem(share_menu, SWT.CHECK);
-
-					item.setText(MessageText.getString("general.add.friends"));
-
-					item.setEnabled(false);
-
-				} else {
-					final String cname;
-
-					if (cat_type == Category.TYPE_ALL) {
-
-						cname = "All";
-
-					} else {
-
-						cname = category.getName();
-					}
-
-					final boolean is_public = buddy_plugin.isPublicCategory(cname);
-
-					final MenuItem itemPubCat = new MenuItem(share_menu, SWT.CHECK);
-
-					Messages.setLanguageText(itemPubCat, "general.all.friends");
-
-					itemPubCat.setSelection(is_public);
-
-					itemPubCat.addListener(SWT.Selection, new Listener() {
-						public void handleEvent(Event event) {
-							if (is_public) {
-
-								buddy_plugin.removePublicCategory(cname);
-
-							} else {
-
-								buddy_plugin.addPublicCategory(cname);
-							}
-						}
-					});
-
-					new MenuItem(share_menu, SWT.SEPARATOR);
-
-					for (final BuddyPluginBuddy buddy : buddies) {
-
-						if (buddy.getNickName() == null) {
-
-							continue;
-						}
-
-						final boolean auth = buddy.isLocalRSSCategoryAuthorised(cname);
-
-						final MenuItem itemShare = new MenuItem(share_menu, SWT.CHECK);
-
-						itemShare.setText(buddy.getName());
-
-						itemShare.setSelection(auth || is_public);
-
-						if (is_public) {
-
-							itemShare.setEnabled(false);
-						}
-
-						itemShare.addListener(SWT.Selection, new Listener() {
-							public void handleEvent(Event event) {
-								if (auth) {
-
-									buddy.removeLocalAuthorisedRSSCategory(cname);
-
-								} else {
-
-									buddy.addLocalAuthorisedRSSCategory(cname);
-								}
-							}
-						});
-
-					}
-				}
-			}
-		}
-		*/
-		
 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_FILE_LOCATION )) {
 		
 			final TagFeatureFileLocation fl = (TagFeatureFileLocation)tag;
 			
-			if ( fl.supportsTagInitialSaveFolder() || fl.supportsTagMoveOnComplete()){
+			if ( fl.supportsTagInitialSaveFolder() || fl.supportsTagMoveOnComplete() || fl.supportsTagCopyOnComplete()){
 				
 				needs_separator_next = true;
 				
@@ -955,11 +887,22 @@ public class TagUIUtils
 						public void handleEvent(Event event) {
 							fl.setTagInitialSaveFolder( null );
 						}});
+	
+						// apply 
 					
-					new MenuItem( moc_menu, SWT.SEPARATOR);
+					final File existing = fl.getTagInitialSaveFolder();
+
+					MenuItem apply_item = new MenuItem( moc_menu, SWT.CASCADE);
+					
+					Messages.setLanguageText( apply_item, "apply.to.current" );
 	
-					File existing = fl.getTagInitialSaveFolder();
+					apply_item.addListener(SWT.Selection, new Listener() {
+						public void handleEvent(Event event) {
+							applyLocationToCurrent( tag, existing );
+						}});
 					
+					new MenuItem( moc_menu, SWT.SEPARATOR);
+						
 					if ( existing != null ){
 						
 						MenuItem current_item = new MenuItem( moc_menu, SWT.RADIO );
@@ -971,6 +914,7 @@ public class TagUIUtils
 						
 					}else{
 						
+						apply_item.setEnabled( false );
 						clear_item.setEnabled( false );
 					}
 					
@@ -1016,10 +960,22 @@ public class TagUIUtils
 							fl.setTagMoveOnCompleteFolder( null );
 						}});
 					
-					new MenuItem( moc_menu, SWT.SEPARATOR);
+
+						// apply 
+					
+					final File existing = fl.getTagMoveOnCompleteFolder();
 	
-					File existing = fl.getTagMoveOnCompleteFolder();
+					MenuItem apply_item = new MenuItem( moc_menu, SWT.CASCADE);
 					
+					Messages.setLanguageText( apply_item, "apply.to.current" );
+	
+					apply_item.addListener(SWT.Selection, new Listener() {
+						public void handleEvent(Event event) {
+							applyLocationToCurrent( tag, existing );
+						}});
+				
+					new MenuItem( moc_menu, SWT.SEPARATOR);
+						
 					if ( existing != null ){
 						
 						MenuItem current_item = new MenuItem( moc_menu, SWT.RADIO );
@@ -1031,6 +987,7 @@ public class TagUIUtils
 						
 					}else{
 						
+						apply_item.setEnabled( false );
 						clear_item.setEnabled( false );
 					}
 					
@@ -1056,6 +1013,101 @@ public class TagUIUtils
 							}
 						}});
 				}
+				
+				if ( fl.supportsTagCopyOnComplete()){
+					
+					final Menu moc_menu = new Menu( files_menu.getShell(), SWT.DROP_DOWN);
+					
+					MenuItem moc_item = new MenuItem( files_menu, SWT.CASCADE);
+					
+					Messages.setLanguageText( moc_item, "label.copy.on.comp" );
+					
+					moc_item.setMenu( moc_menu );
+	
+					MenuItem clear_item = new MenuItem( moc_menu, SWT.CASCADE);
+					
+					Messages.setLanguageText( clear_item, "Button.clear" );
+	
+					clear_item.addListener(SWT.Selection, new Listener() {
+						public void handleEvent(Event event) {
+							fl.setTagCopyOnCompleteFolder( null );
+						}});
+					
+					new MenuItem( moc_menu, SWT.SEPARATOR);
+	
+					File existing = fl.getTagCopyOnCompleteFolder();
+					
+					if ( existing != null ){
+						
+						MenuItem current_item = new MenuItem( moc_menu, SWT.RADIO );
+						current_item.setSelection( true );
+						
+						current_item.setText( existing.getAbsolutePath());
+						
+						new MenuItem( moc_menu, SWT.SEPARATOR);
+						
+					}else{
+						
+						clear_item.setEnabled( false );
+					}
+					
+					MenuItem set_item = new MenuItem( moc_menu, SWT.CASCADE);
+					
+					Messages.setLanguageText( set_item, "label.set" );
+	
+					set_item.addListener(SWT.Selection, new Listener() {
+						public void handleEvent(Event event){
+							DirectoryDialog dd = new DirectoryDialog(moc_menu.getShell());
+	
+							dd.setFilterPath( TorrentOpener.getFilterPathData());
+	
+							dd.setText(MessageText.getString("MyTorrentsView.menu.movedata.dialog"));
+	
+							String path = dd.open();
+	
+							if ( path != null ){
+								
+								TorrentOpener.setFilterPathData( path );
+								
+								fl.setTagCopyOnCompleteFolder( new File( path ));
+							}
+						}});
+				}
+			}
+		}
+		
+		if ( tag_type.hasTagTypeFeature( TagFeature.TF_EXEC_ON_ASSIGN )){
+			
+			final TagFeatureExecOnAssign	tf_eoa = (TagFeatureExecOnAssign)tag;
+			
+			int	supported_actions = tf_eoa.getSupportedActions();
+			
+			if ( supported_actions != TagFeatureExecOnAssign.ACTION_NONE ){
+				
+				final Menu eoa_menu = new Menu( menu.getShell(), SWT.DROP_DOWN);
+				
+				MenuItem eoa_item = new MenuItem( menu, SWT.CASCADE);
+				
+				Messages.setLanguageText( eoa_item, "label.exec.on.assign" );
+				
+				eoa_item.setMenu( eoa_menu );
+				
+				if ( tf_eoa.supportsAction( TagFeatureExecOnAssign.ACTION_DESTROY )){
+					
+					final MenuItem destroy_item = new MenuItem( eoa_menu, SWT.CHECK);
+				
+					Messages.setLanguageText( destroy_item, "FileItem.delete" );
+					
+					destroy_item.setSelection( tf_eoa.isActionEnabled( TagFeatureExecOnAssign.ACTION_DESTROY ));
+					
+					destroy_item.addListener( SWT.Selection, new Listener(){
+							public void 
+							handleEvent(Event event)
+							{
+								tf_eoa.setActionEnabled( TagFeatureExecOnAssign.ACTION_DESTROY, destroy_item.getSelection());
+							}
+						});
+				}
 			}
 		}
 		
@@ -1073,8 +1125,11 @@ public class TagUIUtils
 			itemOptions.addListener(SWT.Selection, new Listener() {
 				public void handleEvent(Event event) {
 					UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
-	
-					uiFunctions.openView(UIFunctions.VIEW_DM_MULTI_OPTIONS, dms.toArray( new DownloadManager[dms.size()]));
+					if (uiFunctions != null) {
+						uiFunctions.getMDI().showEntryByID(
+								MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_OPTIONS,
+								dms.toArray(new DownloadManager[dms.size()]));
+					}
 				}
 			});
 	
@@ -1110,7 +1165,59 @@ public class TagUIUtils
 							
 							String tp_name = tp.getName( false );
 							
-							if ( tp_name.equals( TagFeatureProperties.PR_TRACKER_TEMPLATES )){
+							if ( tp_name.equals( TagFeatureProperties.PR_CONSTRAINT )){
+								
+								MenuItem const_item = new MenuItem( props_menu, SWT.PUSH);
+								
+								Messages.setLanguageText( const_item, "label.contraints" );
+								
+								const_item.addListener(SWT.Selection, new Listener() {
+									public void 
+									handleEvent(Event event)
+									{
+										String[] val = tp.getStringList();
+										
+										String def_val;
+										
+										if ( val != null && val.length > 0 ){
+											
+											def_val = val[0];
+											
+										}else{
+											
+											def_val = "";
+										}
+										
+										String msg = MessageText.getString( "UpdateConstraint.message" );
+										
+										SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow( "UpdateConstraint.title", "!" + msg + "!" );
+										
+										entryWindow.setPreenteredText( def_val, false );
+										entryWindow.selectPreenteredText( true );
+										
+										entryWindow.prompt();
+										
+										if ( entryWindow.hasSubmittedInput()){
+											
+											try{
+												String text = entryWindow.getSubmittedInput().trim();
+												
+												if ( text.length() ==  0 ){
+													
+													tp.setStringList( null );
+													
+												}else{
+													
+													tp.setStringList( new String[]{ text });
+												}
+											}catch( Throwable e ){
+												
+												Debug.out( e );
+											}
+										}
+									}});
+								
+							}else if ( tp_name.equals( TagFeatureProperties.PR_TRACKER_TEMPLATES )){
 								
 								final TrackersUtil tut = TrackersUtil.getInstance();
 								
@@ -1476,6 +1583,119 @@ public class TagUIUtils
 				}});
 		}
 		
+		if ( tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL ){
+
+			needs_separator_next = true;
+			
+			MenuItem search = new MenuItem(menu, SWT.PUSH);
+			Messages.setLanguageText(search, "tag.search");
+			search.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event){
+					UIFunctionsManager.getUIFunctions().doSearch( "tag:" + tag.getTagName( true ));
+				}});
+		}
+		
+			// share with friends
+
+		PluginInterface bpi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByClass(
+				BuddyPlugin.class);
+
+		if ( tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL && bpi != null ){
+				
+			TagFeatureProperties props = (TagFeatureProperties)tag;
+							
+			TagProperty tp = props.getProperty( TagFeatureProperties.PR_UNTAGGED );
+			
+			Boolean is_ut = tp==null?null:tp.getBoolean();
+			
+			if ( is_ut == null || !is_ut ){
+	
+				final BuddyPlugin buddy_plugin = (BuddyPlugin) bpi.getPlugin();
+	
+				if (buddy_plugin.isClassicEnabled()) {
+	
+					final Menu share_menu = new Menu(menu.getShell(), SWT.DROP_DOWN);
+					final MenuItem share_item = new MenuItem(menu, SWT.CASCADE);
+					Messages.setLanguageText(share_item, "azbuddy.ui.menu.cat.share");
+					share_item.setText( share_item.getText() + "  " );	// nasty hack to fix nastyness on windows
+					share_item.setMenu(share_menu);
+	
+					List<BuddyPluginBuddy> buddies = buddy_plugin.getBuddies();
+	
+					if (buddies.size() == 0) {
+	
+						final MenuItem item = new MenuItem(share_menu, SWT.CHECK);
+	
+						item.setText(MessageText.getString("general.add.friends"));
+	
+						item.setEnabled(false);
+	
+					} else {
+						final String tag_name = tag.getTagName( true );
+	
+						final boolean is_public = buddy_plugin.isPublicTagOrCategory( tag_name );
+	
+						final MenuItem itemPubCat = new MenuItem(share_menu, SWT.CHECK);
+	
+						Messages.setLanguageText(itemPubCat, "general.all.friends");
+	
+						itemPubCat.setSelection(is_public);
+	
+						itemPubCat.addListener(SWT.Selection, new Listener() {
+							public void handleEvent(Event event) {
+								if (is_public) {
+	
+									buddy_plugin.removePublicTagOrCategory( tag_name );
+	
+								} else {
+	
+									buddy_plugin.addPublicTagOrCategory( tag_name );
+								}
+							}
+						});
+	
+						new MenuItem(share_menu, SWT.SEPARATOR);
+	
+						for (final BuddyPluginBuddy buddy : buddies) {
+	
+							if (buddy.getNickName() == null) {
+	
+								continue;
+							}
+	
+							final boolean auth = buddy.isLocalRSSTagOrCategoryAuthorised(tag_name);
+	
+							final MenuItem itemShare = new MenuItem(share_menu, SWT.CHECK);
+	
+							itemShare.setText(buddy.getName());
+	
+							itemShare.setSelection(auth || is_public);
+	
+							if (is_public) {
+	
+								itemShare.setEnabled(false);
+							}
+	
+							itemShare.addListener(SWT.Selection, new Listener() {
+								public void handleEvent(Event event) {
+									if (auth) {
+	
+										buddy.removeLocalAuthorisedRSSTagOrCategory(tag_name);
+	
+									} else {
+	
+										buddy.addLocalAuthorisedRSSTagOrCategory(tag_name);
+									}
+								}
+							});
+	
+						}
+					}
+				}
+			}
+		}
+		
+		
 			// rss feed
 		
 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_RSS_FEED )) {
@@ -1611,6 +1831,11 @@ public class TagUIUtils
 		
 		needs_separator_next = true;
 
+		if ( tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL ){
+					
+			MenuBuildUtils.addChatMenu( menu, "label.chat", getChatKey( tag ));
+		}
+		
 		MenuItem itemShowStats = new MenuItem(menu, SWT.PUSH);
 		
 		Messages.setLanguageText(itemShowStats, "tag.show.stats");
@@ -1882,7 +2107,7 @@ public class TagUIUtils
 			item_create.addListener(SWT.Selection, new Listener() {
 				public void handleEvent(Event event) {
 					
-					createManualTag();
+					createManualTag(null);
 				}
 			});
 			
@@ -1906,6 +2131,42 @@ public class TagUIUtils
 				}
 			});
 			
+			MenuItem itemGroup = new MenuItem(menu, SWT.PUSH);
+			
+			Messages.setLanguageText(itemGroup, "MyTorrentsView.menu.group");
+			itemGroup.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+							"TagGroupWindow.title", "TagGroupWindow.message");
+					
+					String group = tag.getGroup();
+					
+					if ( group == null ){
+						group = "";
+					}
+					entryWindow.setPreenteredText( group, false );
+					entryWindow.selectPreenteredText( true );
+					
+					entryWindow.prompt();
+					
+					if ( entryWindow.hasSubmittedInput()){
+						
+						try{
+							group = entryWindow.getSubmittedInput().trim();
+							
+							if ( group.length() == 0 ){
+								group = null;
+							}
+							tag.setGroup( group );
+							
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}
+				}
+			});
+			
 			MenuItem itemRename = new MenuItem(menu, SWT.PUSH);
 						
 			Messages.setLanguageText(itemRename, "MyTorrentsView.menu.rename");
@@ -1943,6 +2204,119 @@ public class TagUIUtils
 				}
 			});
 		}
+		
+
+		org.gudy.azureus2.plugins.ui.menus.MenuItem[] items = MenuItemManager.getInstance().getAllAsArray(
+				MenuManager.MENU_TAG_CONTEXT);
+		
+		if (items.length > 0) {
+			MenuFactory.addSeparatorMenuItem(menu);
+
+			// TODO: Don't send Tag.. send a yet-to-be-created plugin interface version of Tag
+			MenuBuildUtils.addPluginMenuItems(items, menu, true, true,
+					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Tag[] { tag }));
+		}
+	}
+	
+	public static void 
+	createSideBarMenuItems(
+		final Menu 			menu, 
+		final List<Tag>	 	_tags ) 
+	{
+		final List<Tag> tags = new ArrayList<Tag>( _tags );
+		
+		Iterator<Tag> it = tags.iterator();
+		
+		while( it.hasNext()){
+			
+			Tag tag = it.next();
+			
+			if ( tag.getTagType().getTagType() != TagType.TT_DOWNLOAD_MANUAL ){
+				
+				it.remove();
+			}
+		}
+		
+		if ( tags.size() == 0 ){
+			
+			return;
+		}
+		
+		MenuItem itemGroup = new MenuItem(menu, SWT.PUSH);
+		
+		Messages.setLanguageText(itemGroup, "MyTorrentsView.menu.group");
+		itemGroup.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
+						"TagGroupWindow.title", "TagGroupWindow.message");
+				
+				String group = "";
+				
+				entryWindow.setPreenteredText( group, false );
+				entryWindow.selectPreenteredText( true );
+				
+				entryWindow.prompt();
+				
+				if ( entryWindow.hasSubmittedInput()){
+					
+					try{
+						group = entryWindow.getSubmittedInput().trim();
+						
+						if ( group.length() == 0 ){
+							group = null;
+						}
+						
+						for ( Tag tag: tags ){
+						
+							tag.setGroup( group );
+						}
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+				}
+			}
+		});
+
+		org.gudy.azureus2.plugins.ui.menus.MenuItem[] items = MenuItemManager.getInstance().getAllAsArray(
+				MenuManager.MENU_TAG_CONTEXT);
+		
+		if (items.length > 0) {
+			MenuFactory.addSeparatorMenuItem(menu);
+
+			// TODO: Don't send Tag.. send a yet-to-be-created plugin interface version of Tag
+			MenuBuildUtils.addPluginMenuItems(items, menu, true, true,
+					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(tags.toArray(new Tag[0])));
+		}
+	}
+		
+	private static final AsyncDispatcher move_dispatcher = new AsyncDispatcher( "tag:applytocurrent" );
+	
+	private static void
+	applyLocationToCurrent(
+		final Tag			tag,
+		final File			location )
+	{
+		move_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void
+				runSupport()
+				{
+					Set<DownloadManager>	downloads = ((TagDownload)tag).getTaggedDownloads();
+					
+					for ( DownloadManager download: downloads ){
+						
+						try{
+							download.moveDataFilesLive( location );
+							
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}
+				}
+			});
 	}
 	
 	public static void 
@@ -1974,13 +2348,7 @@ public class TagUIUtils
 				
 				TagType tt = t.getTagType();
 				
-				if ( tt == manual_tt ){
-					
-					Integer i = manual_map.get( t );
-					
-					manual_map.put( t, i==null?1:i+1 );
-					
-				}else if ( tt.isTagTypeAuto()){
+				if ( tt.isTagTypeAuto() || t.isTagAuto()){
 					
 					List<Tag> x = auto_map.get( tt );
 					
@@ -1992,6 +2360,12 @@ public class TagUIUtils
 					}
 					
 					x.add( t );
+					
+				}else if ( tt == manual_tt ){
+					
+					Integer i = manual_map.get( t );
+					
+					manual_map.put( t, i==null?1:i+1 );
 				}
 			}
 		}
@@ -2196,17 +2570,20 @@ public class TagUIUtils
 		item_create.addListener(SWT.Selection, new Listener() {
 			public void handleEvent(Event event) {
 				
-				Tag new_tag = createManualTag();
-				
-				if ( new_tag != null ){
-					
-					for ( DownloadManager dm: dms ){
-						
-						new_tag.addTaggable( dm );
+				createManualTag(new UIFunctions.TagReturner() {
+					public void returnedTags(Tag[] tags) {
+						if ( tags != null ){
+							for (Tag new_tag : tags) {
+								for ( DownloadManager dm: dms ){
+									
+									new_tag.addTaggable( dm );
+								}
+								
+								COConfigurationManager.setParameter( "Library.TagInSideBar", true );
+							}
+						}
 					}
-					
-					COConfigurationManager.setParameter( "Library.TagInSideBar", true );
-				}
+				});
 			}
 		});
 	}
@@ -2240,30 +2617,59 @@ public class TagUIUtils
 	{
 		List<Tag>	tags = new ArrayList<Tag>( _tags );
 		
-		Collections.sort(
-			tags,
-			new Comparator<Tag>()
-			{
-				final Comparator<String> comp = new FormattersImpl().getAlphanumericComparator( true );
+		Collections.sort( tags, getTagComparator());
 
-				public int 
-				compare(
-					Tag o1, Tag o2) 
-				{
-					return( comp.compare( o1.getTagName(true), o2.getTagName(true)));
-				}
-			});
-		
 		return( tags );
 	}
 	
+	public static Comparator<Tag>
+	getTagComparator()
+	{
+		return( new Comparator<Tag>()
+		{
+			final Comparator<String> comp = new FormattersImpl().getAlphanumericComparator( true );
+
+			public int 
+			compare(
+				Tag o1, Tag o2) 
+			{
+				String	g1 = o1.getGroup();
+				String	g2 = o2.getGroup();
+				
+				if ( g1 != g2 ){
+					if ( g1 == null ){
+						return( 1 );
+					}else if ( g2 == null ){
+						return( -1 );
+					}else{
+						
+						int	res = comp.compare( g1,  g2 );
+						
+						if ( res != 0 ){
+							return( res );
+						}
+					}
+				}
+				return( comp.compare( o1.getTagName(true), o2.getTagName(true)));
+			}
+		});
+	}
+	
 	public static String
 	getTagTooltip(
 		Tag		tag )
 	{
+		return( getTagTooltip( tag, false ));
+	}
+	
+	public static String
+	getTagTooltip(
+		Tag			tag,
+		boolean		skip_name )
+	{
 		TagType tag_type = tag.getTagType();
 		
-		String 	str = tag_type.getTagTypeName( true ) + ": " + tag.getTagName( true );
+		String 	str = skip_name?"":(tag_type.getTagTypeName( true ) + ": " + tag.getTagName( true ));
 		
 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_RATE_LIMIT )){
 			
@@ -2343,6 +2749,20 @@ public class TagUIUtils
 					str += "\r\n    " + MessageText.getString("label.move.on.comp") + "=" + move_on_comp.getAbsolutePath();
 				}
 			}
+			if ( fl.supportsTagCopyOnComplete()){
+				
+				File copy_on_comp = fl.getTagCopyOnCompleteFolder();
+				
+				if ( copy_on_comp != null ){
+					
+					str += "\r\n    " + MessageText.getString("label.copy.on.comp") + "=" + copy_on_comp.getAbsolutePath();
+				}
+			}
+		}
+		
+		if ( str.startsWith( "\r\n" )){
+			
+			str = str.substring(2);
 		}
 		
 		return( str );
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/welcome/WelcomeWindow.java b/azureus2/src/org/gudy/azureus2/ui/swt/welcome/WelcomeWindow.java
index 8aa735c..cc68aea 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/welcome/WelcomeWindow.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/welcome/WelcomeWindow.java
@@ -2,11 +2,12 @@
  * Created on 15 avr. 2005
  * Created by Olivier Chalouhi
  * 
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -16,9 +17,6 @@
  * 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.welcome;
 
@@ -38,10 +36,10 @@ 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.*;
 import org.gudy.azureus2.pluginsimpl.local.utils.resourcedownloader.ResourceDownloaderFactoryImpl;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
 
@@ -150,7 +148,7 @@ public class WelcomeWindow {
   public void _setWhatsNew() {
 
 		if (sWhatsNew.indexOf("<html") >= 0 || sWhatsNew.indexOf("<HTML") >= 0) {
-			Browser browser = Utils.createSafeBrowser(cWhatsNew, SWT.NONE);
+			BrowserWrapper browser = Utils.createSafeBrowser(cWhatsNew, SWT.NONE);
 			if (browser != null) {	
 				browser.setText(sWhatsNew);
 			} else {
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/win32/Win32UIEnhancer.java b/azureus2/src/org/gudy/azureus2/ui/swt/win32/Win32UIEnhancer.java
index 63ef55f..d742103 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/win32/Win32UIEnhancer.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/win32/Win32UIEnhancer.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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 org.gudy.azureus2.ui.swt.win32;
@@ -24,23 +21,20 @@ import java.io.File;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Map;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Device;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.widgets.Shell;
-
 import org.gudy.azureus2.core3.util.AEThread2;
 import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.platform.win32.access.AEWin32Access;
 import org.gudy.azureus2.platform.win32.access.AEWin32Manager;
-import org.gudy.azureus2.platform.win32.access.impl.AEWin32AccessImpl;
 import org.gudy.azureus2.platform.win32.access.impl.AEWin32AccessInterface;
 
-import com.aelitis.azureus.core.drivedetector.*;
+import com.aelitis.azureus.core.drivedetector.DriveDetectedInfo;
+import com.aelitis.azureus.core.drivedetector.DriveDetector;
+import com.aelitis.azureus.core.drivedetector.DriveDetectorFactory;
 
 /**
  * @author TuxPaper
@@ -116,6 +110,12 @@ public class Win32UIEnhancer
 
 	private static int SHFILEINFO_sizeof;
 
+	private static long oldProc;
+
+	private static Method mGetWindowLongPtr;
+
+	private static Method mCallWindowProc;
+	
 	static {
 		try {
 			claOS = Class.forName("org.eclipse.swt.internal.win32.OS");
@@ -167,6 +167,23 @@ public class Win32UIEnhancer
 							int.class,
 							int.class
 						});
+				
+				mGetWindowLongPtr = claOS.getMethod("GetWindowLongPtr",
+						new Class[] {
+							int.class,
+							int.class
+						});
+				
+				// int /*long*/ CallWindowProc (int /*long*/ lpPrevWndFunc, int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
+
+				mCallWindowProc = claOS.getMethod("CallWindowProc",
+						new Class[] {
+							int.class,
+							int.class,
+							int.class,
+							int.class,
+							int.class
+						});
 
 				useLong = false;
 				
@@ -194,7 +211,21 @@ public class Win32UIEnhancer
 							int.class,
 							long.class
 						});
-
+				mGetWindowLongPtr = claOS.getMethod("GetWindowLongPtr",
+						new Class[] {
+							long.class,
+							int.class
+						});
+				
+				mCallWindowProc = claOS.getMethod("CallWindowProc",
+						new Class[] {
+							long.class,
+							long.class,
+							int.class,
+							long.class,
+							long.class
+						});
+				
 				useLong = true;
 				mOS_memmove_byte = claOS.getMethod("memmove", new Class[] {
 					byte[].class,
@@ -279,7 +310,13 @@ public class Win32UIEnhancer
 				4
 			});
 
+
 			Object oHandle = subshell.getClass().getField("handle").get(subshell);
+			oldProc = ((Number) mGetWindowLongPtr.invoke(null,  new Object[] {
+				oHandle,
+				OS_GWLP_WNDPROC
+			})).longValue();
+
 			if (useLong) {
 				Number n = (Number) mCallback_getAddress.invoke(messageCallback,
 						new Object[] {});
@@ -483,9 +520,16 @@ public class Win32UIEnhancer
 					}
 					break;
 			}
+
+			if (useLong) {
+				return (Long)mCallWindowProc.invoke(null, new Object[]{ oldProc, hwnd, (int) msg, wParam, lParam });
+			}else{
+				return (Integer)mCallWindowProc.invoke(null, new Object[]{ (int)oldProc, (int)hwnd, (int) msg, (int)wParam, (int)lParam });
+			}
 		} catch (Exception e) {
 			e.printStackTrace();
+			
+			return( 0 );
 		}
-		return 0;// OS.DefWindowProc (hwnd, (int)/*64*/msg, wParam, lParam);
 	}
 }
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/wizard/AbstractWizardPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/wizard/AbstractWizardPanel.java
index d84d7f5..fe25bb4 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/wizard/AbstractWizardPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/wizard/AbstractWizardPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/wizard/IWizardPanel.java b/azureus2/src/org/gudy/azureus2/ui/swt/wizard/IWizardPanel.java
index 51f52f9..5d61647 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/wizard/IWizardPanel.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/wizard/IWizardPanel.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/wizard/Wizard.java b/azureus2/src/org/gudy/azureus2/ui/swt/wizard/Wizard.java
index 95260a5..f521f12 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/wizard/Wizard.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/wizard/Wizard.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/swt/wizard/WizardListener.java b/azureus2/src/org/gudy/azureus2/ui/swt/wizard/WizardListener.java
index 11a1690..1e94103 100644
--- a/azureus2/src/org/gudy/azureus2/ui/swt/wizard/WizardListener.java
+++ b/azureus2/src/org/gudy/azureus2/ui/swt/wizard/WizardListener.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
diff --git a/azureus2/src/org/gudy/azureus2/ui/systray/SystemTraySWT.java b/azureus2/src/org/gudy/azureus2/ui/systray/SystemTraySWT.java
index ca79e24..f418daf 100644
--- a/azureus2/src/org/gudy/azureus2/ui/systray/SystemTraySWT.java
+++ b/azureus2/src/org/gudy/azureus2/ui/systray/SystemTraySWT.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -57,6 +58,7 @@ import com.aelitis.azureus.core.tag.TagType;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdatableAlways;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
@@ -244,7 +246,7 @@ public class SystemTraySWT
 		org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items;
 		menu_items = MenuItemManager.getInstance().getAllAsArray("systray");
 		if (menu_items.length > 0) {
-			MenuBuildUtils.addPluginMenuItems(uiFunctions.getMainShell(), menu_items, menu, true, true, MenuBuildUtils.BASIC_MENU_ITEM_CONTROLLER);
+			MenuBuildUtils.addPluginMenuItems(menu_items, menu, true, true, MenuBuildUtils.BASIC_MENU_ITEM_CONTROLLER);
 			new MenuItem(menu, SWT.SEPARATOR);
 		}
 		
@@ -361,8 +363,9 @@ public class SystemTraySWT
 				UIFunctions uif = UIFunctionsManager.getUIFunctions();
 
 				if (uif != null) {
-
-					uif.openView(UIFunctions.VIEW_CONFIG, ConfigSection.SECTION_INTERFACE );
+					uif.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+							ConfigSection.SECTION_INTERFACE);
 				}
 			}
 		});
@@ -387,6 +390,9 @@ public class SystemTraySWT
 	 * @param parent The system tray contextual menu
 	 */
 	private final void createUploadLimitMenu(final Menu parent) {
+		if ( gm == null ){
+			return;
+		}
 		final MenuItem uploadSpeedItem = new MenuItem(parent, SWT.CASCADE);
 		uploadSpeedItem.setText(MessageText.getString("GeneralView.label.maxuploadspeed"));
 
@@ -407,6 +413,9 @@ public class SystemTraySWT
 	 * @param parent The system tray contextual menu
 	 */
 	private final void createDownloadLimitMenu(final Menu parent) {
+		if ( gm == null ){
+			return;
+		}
 		final MenuItem downloadSpeedItem = new MenuItem(parent, SWT.CASCADE);
 		downloadSpeedItem.setText(MessageText.getString("GeneralView.label.maxdownloadspeed"));
 
@@ -446,8 +455,12 @@ public class SystemTraySWT
 		}
 	}
 
+	public void updateUI(){
+		updateUI(true);
+	}
+	
 	// @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI()
-	public void updateUI() {
+	public void updateUI(boolean is_visible) {
 		if (interval++ % 10 > 0) {
 			return;
 		}
diff --git a/azureus2/src/org/gudy/azureus2/ui/webplugin/WebPlugin.java b/azureus2/src/org/gudy/azureus2/ui/webplugin/WebPlugin.java
index 38ac69b..e9c4e40 100644
--- a/azureus2/src/org/gudy/azureus2/ui/webplugin/WebPlugin.java
+++ b/azureus2/src/org/gudy/azureus2/ui/webplugin/WebPlugin.java
@@ -7,7 +7,8 @@
  *
  * 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.
+ * 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
@@ -49,6 +50,7 @@ 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.core.proxy.AEProxyFactory;
 import com.aelitis.azureus.plugins.upnp.UPnPMapping;
 import com.aelitis.azureus.plugins.upnp.UPnPPlugin;
 import com.aelitis.azureus.util.JSONUtils;
@@ -62,6 +64,7 @@ WebPlugin
 	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_HOME_PAGE				= "Home Page";					// 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
@@ -71,6 +74,11 @@ WebPlugin
 	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	PR_NON_BLOCKING				= "NonBlocking";				// Boolean
+	public static final String	PR_ENABLE_PAIRING			= "EnablePairing";				// Boolean
+	public static final String	PR_ENABLE_I2P				= "EnableI2P";					// Boolean
+	public static final String	PR_ENABLE_TOR				= "EnableTor";					// Boolean
+	public static final String	PR_ENABLE_UPNP				= "EnableUPNP";					// Boolean
 	
 	public static final String	PROPERTIES_MIGRATED		= "Properties Migrated";
 	public static final String	CONFIG_MIGRATED			= "Config Migrated";
@@ -108,10 +116,10 @@ WebPlugin
 	public static final String 	CONFIG_PROTOCOL_DEFAULT			= "HTTP";
 
 	public static final String	CONFIG_UPNP_ENABLE				= "UPnP Enable";
-	public static final boolean	CONFIG_UPNP_ENABLE_DEFAULT		= true;
+	public 				boolean	CONFIG_UPNP_ENABLE_DEFAULT		= true;
 
-	public static final String 	CONFIG_HOME_PAGE				= "Home Page";
-	public static final String 	CONFIG_HOME_PAGE_DEFAULT		= "index.html";
+	public static final String 	CONFIG_HOME_PAGE				= PR_HOME_PAGE;
+	public  		 String 	CONFIG_HOME_PAGE_DEFAULT		= "index.html";
 	
 	public static final String 	CONFIG_ROOT_DIR					= PR_ROOT_DIR;
 	public        		String 	CONFIG_ROOT_DIR_DEFAULT			= "";
@@ -128,9 +136,11 @@ WebPlugin
 	
 	protected static final String	NL			= "\r\n";
 	
-	protected static final String[]		welcome_pages = {"index.html", "index.htm", "index.php", "index.tmpl" };
+	protected static final String[]		welcome_pages = { "index.html", "index.htm", "index.php", "index.tmpl" };
 	protected static File[]				welcome_files;
 	
+	private static final AsyncDispatcher	network_dispatcher = new AsyncDispatcher( "webplugin:netdispatch", 5000 );
+	
 	protected PluginInterface			plugin_interface;	// unfortunately this is accessed by webui - fix sometime
 	
 	private LoggerChannel			log;
@@ -138,6 +148,8 @@ WebPlugin
 	private BasicPluginViewModel 	view_model;
 	private BasicPluginConfigModel	config_model;
 	
+	private String					p_sid;
+	
 	private StringParameter			param_home;
 	private StringParameter			param_rootdir;
 	private StringParameter			param_rootres;
@@ -148,6 +160,9 @@ WebPlugin
 	
 	private StringParameter			param_access;
 	
+	private InfoParameter			param_i2p_dest;
+	private InfoParameter			param_tor_dest;
+	
 	private BooleanParameter		p_upnp_enable;
 	
 	private BooleanParameter		pw_enable;
@@ -255,6 +270,13 @@ WebPlugin
 			CONFIG_ROOT_RESOURCE_DEFAULT	= pr_root_resource;
 		}
 		
+		String	pr_home_page = (String)properties.get( PR_HOME_PAGE );
+		
+		if( pr_home_page != null ){
+			
+			CONFIG_HOME_PAGE_DEFAULT		= pr_home_page;
+		}
+		
 		String	pr_root_dir = (String)properties.get( PR_ROOT_DIR );
 		
 		if( pr_root_dir != null ){
@@ -269,6 +291,13 @@ WebPlugin
 			CONFIG_ACCESS_DEFAULT	= pr_access;
 		}
 		
+		Boolean	pr_enable_upnp = (Boolean)properties.get(PR_ENABLE_UPNP);
+		
+		if ( pr_enable_upnp != null ){
+		
+			CONFIG_UPNP_ENABLE_DEFAULT	= pr_enable_upnp.booleanValue();
+		}
+		
 		Boolean	pr_hide_resource_config = (Boolean)properties.get( PR_HIDE_RESOURCE_CONFIG );
 		
 		log = (LoggerChannel)properties.get( PR_LOG );
@@ -278,6 +307,15 @@ WebPlugin
 			log = plugin_interface.getLogger().getChannel("WebPlugin");
 		}
 		
+		Boolean prop_pairing_enable = (Boolean)properties.get( PR_ENABLE_PAIRING );
+		
+		if ( prop_pairing_enable == null || prop_pairing_enable ){
+		
+				// default is based on sid availability
+			
+			p_sid = (String)properties.get( PR_PAIRING_SID );
+		}
+		
 		UIManager	ui_manager = plugin_interface.getUIManager();
 		
 		view_model = (BasicPluginViewModel)properties.get( PR_VIEW_MODEL );
@@ -487,6 +525,12 @@ WebPlugin
 		param_bind.addListener( update_server_listener );
 		param_protocol.addListener( update_server_listener );		
 		
+		param_i2p_dest = config_model.addInfoParameter2( "webui.i2p_dest", "" );		
+		param_i2p_dest.setVisible( false );
+		
+		param_tor_dest = config_model.addInfoParameter2( "webui.tor_dest", "" );	
+		param_tor_dest.setVisible( false );
+
 		if ( param_enable != null ){
 			COConfigurationManager.registerExportedParameter( plugin_id + ".enable", param_enable.getConfigKeyName());
 		}
@@ -530,9 +574,7 @@ WebPlugin
 					}
 				});
 		
-		
-		final String p_sid = (String)properties.get( PR_PAIRING_SID );
-		
+				
 		final LabelParameter		pairing_info;
 		final BooleanParameter		pairing_enable;
 		final HyperlinkParameter	pairing_test;
@@ -614,7 +656,7 @@ WebPlugin
 		config_model.createGroup(
 			"ConfigView.section.server",
 			new Parameter[]{
-				param_port, param_bind, param_protocol, p_upnp_enable,
+				param_port, param_bind, param_protocol, param_i2p_dest, param_tor_dest, p_upnp_enable,
 			});
 		
 		param_home 		= config_model.addStringParameter2(	CONFIG_HOME_PAGE, "webui.homepage", CONFIG_HOME_PAGE_DEFAULT );
@@ -1008,7 +1050,7 @@ WebPlugin
 				
 			home_page = null;
 				
-		}else if (!home_page.startsWith("/" )){
+		}else if ( !home_page.startsWith("/" )){
 			
 			home_page = "/" + home_page;
 		}
@@ -1225,17 +1267,111 @@ WebPlugin
 			
 
 			int	protocol = protocol_str.equalsIgnoreCase( "HTTP")?Tracker.PR_HTTP:Tracker.PR_HTTPS;
-		
-			log.log( 	LoggerChannel.LT_INFORMATION, 
-						"Server initialisation: port = " + port +
-						(bind_ip == null?"":(", bind = " + bind_ip_str + ")")) +
-						", protocol = " + protocol_str + (root_dir.length()==0?"":(", root = " + root_dir )));
 
+			Map<String,Object>		tc_properties = new HashMap<String, Object>();
+
+			Boolean prop_non_blocking = (Boolean)properties.get( PR_NON_BLOCKING );
+
+			if ( prop_non_blocking != null && prop_non_blocking ){
+				
+				tc_properties.put( Tracker.PR_NON_BLOCKING, true );
+			}
+			
+			log.log( 	LoggerChannel.LT_INFORMATION, 
+						"Server initialisation: port=" + port +
+						(bind_ip == null?"":(", bind=" + bind_ip_str + ")")) +
+						", protocol=" + protocol_str + 
+						(root_dir.length()==0?"":(", root=" + root_dir )) + 
+						(properties.size()==0?"":(", props=" + properties )));
+			
 			tracker_context = 
 				plugin_interface.getTracker().createWebContext(
 						Constants.APP_NAME + " - " + plugin_interface.getPluginName(), 
-						port, protocol, bind_ip );
+						port, protocol, bind_ip, tc_properties );
 		
+			Boolean prop_enable_i2p = (Boolean)properties.get( PR_ENABLE_I2P );
+
+			if ( prop_enable_i2p == null || prop_enable_i2p ){
+				
+				network_dispatcher.dispatch(
+					new AERunnable() 
+					{	
+						public void
+						runSupport()
+						{
+							Map<String,Object>	options = new HashMap<String, Object>();
+							
+							options.put( AEProxyFactory.SP_PORT, port );
+							
+							Map<String,Object> reply = 
+									AEProxyFactory.getPluginServerProxy(
+										plugin_interface.getPluginName(),
+										AENetworkClassifier.AT_I2P,
+										plugin_interface.getPluginID(),
+										options );
+							
+							if ( reply != null ){
+							
+								param_i2p_dest.setVisible( true );
+							
+								String host = (String)reply.get( "host" );
+								
+								if ( !param_i2p_dest.getValue().equals( host )){
+								
+									param_i2p_dest.setValue( host );
+								
+									if ( p_sid != null ){
+									
+										updatePairing( p_sid );
+									}
+								}
+							}
+						}
+					});
+			}
+			
+			Boolean prop_enable_tor = (Boolean)properties.get( PR_ENABLE_TOR );
+
+			if ( prop_enable_tor == null || prop_enable_tor ){
+				
+				network_dispatcher.dispatch(
+					new AERunnable() 
+					{	
+						public void
+						runSupport()
+						{
+							Map<String,Object>	options = new HashMap<String, Object>();
+							
+							options.put( AEProxyFactory.SP_PORT, port );
+							
+							Map<String,Object> reply = 
+									AEProxyFactory.getPluginServerProxy(
+										plugin_interface.getPluginName(),
+										AENetworkClassifier.AT_TOR,
+										plugin_interface.getPluginID(),
+										options );
+							
+							if ( reply != null ){
+							
+								param_tor_dest.setVisible( true );
+							
+								String host = (String)reply.get( "host" );
+								
+								if ( !param_tor_dest.getValue().equals( host )){
+								
+									param_tor_dest.setValue( host );
+								
+									if ( p_sid != null ){
+									
+										updatePairing( p_sid );
+									}
+								}
+							}
+						}
+					});
+			}
+			
+			
 			Boolean	pr_enable_keep_alive = (Boolean)properties.get( PR_ENABLE_KEEP_ALIVE );
 
 			if ( pr_enable_keep_alive != null && pr_enable_keep_alive ){
@@ -1824,8 +1960,59 @@ WebPlugin
 		}
 		
 		cd.setAttribute( PairingConnectionData.ATTR_PROTOCOL, 	param_protocol.getValue());
+		
+		if ( param_i2p_dest.isVisible()){
+			
+			String host = param_i2p_dest.getValue();
+			
+			if ( host.length() > 0 ){
+				
+				cd.setAttribute( PairingConnectionData.ATTR_I2P, host );
+			}
+		}
+		
+		if ( param_tor_dest.isVisible()){
+			
+			String host = param_tor_dest.getValue();
+			
+			if ( host.length() > 0 ){
+				
+				cd.setAttribute( PairingConnectionData.ATTR_TOR, host );
+			}
+		}
 	}
 
+	public InetAddress
+	getServerBindIP()
+	{
+		if ( tracker_context == null ){
+			
+			return( new InetSocketAddress(0).getAddress());
+		}
+		
+		InetAddress address = tracker_context.getBindIP();
+		
+		if ( address == null ){
+			
+			return( new InetSocketAddress(0).getAddress());
+		}
+		
+		return( address );
+	}
+	
+	public int
+	getServerPort()
+	{
+		if ( tracker_context == null ){
+			
+			return( 0 );
+		}
+		
+		URL	url = tracker_context.getURLs()[0];
+		
+		return( url.getPort()==-1?url.getDefaultPort():url.getPort());
+	}
+	
 	public int
 	getPort()
 	{
@@ -2144,6 +2331,12 @@ WebPlugin
 					
 					throw( new IOException( "Not supported" ));
 				}
+				
+				public boolean 
+				isActive()
+				{
+					return( true );
+				}
 			};
 			
 		try{
@@ -2279,15 +2472,21 @@ WebPlugin
 			
 			try{
 				boolean valid_ip = true;
-				InetAddress ia = InetAddress.getByName( client );
+				
+				InetAddress client_ia = InetAddress.getByName( client );
 				
 				if ( ip_ranges == null ){
 					
-					if ( !ia.isLoopbackAddress()){
+					if ( !client_ia.isLoopbackAddress()){
 				
-						log.log( LoggerChannel.LT_ERROR, "Client '" + client + "' is not local, rejecting" );
+						InetAddress bind_ia = getServerBindIP();
 						
-						valid_ip = false;
+						if ( bind_ia.isAnyLocalAddress() || !bind_ia.equals( client_ia )){
+						
+							log.log( LoggerChannel.LT_ERROR, "Client '" + client + "' is not local, rejecting" );
+						
+							valid_ip = false;
+						}
 					}
 				}else{
 					
@@ -2295,7 +2494,7 @@ WebPlugin
 					
 					for ( IPRange range: ip_ranges ){
 						
-						if ( range.isInRange( ia.getHostAddress())){
+						if ( range.isInRange( client_ia.getHostAddress())){
 						
 							ok = true;
 						}
@@ -2303,7 +2502,7 @@ WebPlugin
 					
 					if ( !ok ){
 						
-						log.log( LoggerChannel.LT_ERROR, "Client '" + client + "' (" + ia.getHostAddress() + ") is not in range, rejecting" );
+						log.log( LoggerChannel.LT_ERROR, "Client '" + client + "' (" + client_ia.getHostAddress() + ") is not in range, rejecting" );
 						
 						valid_ip = false;
 					}
@@ -2492,7 +2691,7 @@ WebPlugin
 	
 			// first try file system for data
 		
-		if ( response.useFile( file_root, url )){
+		if ( useFile( request, response, file_root, UrlUtils.decode( url ))){
 			
 			return( true );
 		}
@@ -2547,6 +2746,28 @@ WebPlugin
 		return( false );
 	}
 	
+		/**
+		 * this method can be over-ridden to handle custom file delivery
+		 * @param request
+		 * @param response
+		 * @param root
+		 * @param relative_url
+		 * @return
+		 * @throws IOException
+		 */
+	
+	protected boolean
+	useFile(
+		TrackerWebPageRequest		request,
+		TrackerWebPageResponse		response,
+		String						root,
+		String						relative_url )
+		
+		throws IOException
+	{
+		return( response.useFile( file_root, relative_url ));
+	}
+	
 	private String
 	getArgumentFromURL(
 		URL			url,
diff --git a/azureus2/src/org/gudy/azureus2/ui/webplugin/WebPluginAccessController.java b/azureus2/src/org/gudy/azureus2/ui/webplugin/WebPluginAccessController.java
index 6bbce2c..7c257ab 100644
--- a/azureus2/src/org/gudy/azureus2/ui/webplugin/WebPluginAccessController.java
+++ b/azureus2/src/org/gudy/azureus2/ui/webplugin/WebPluginAccessController.java
@@ -1,7 +1,7 @@
 /*
  * Created on 15-Jul-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -15,9 +15,6 @@
  * 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.webplugin;
diff --git a/azureus2/src/org/gudy/azureus2/update/CorePatchChecker.java b/azureus2/src/org/gudy/azureus2/update/CorePatchChecker.java
index 4e0ddf2..fc74b67 100644
--- a/azureus2/src/org/gudy/azureus2/update/CorePatchChecker.java
+++ b/azureus2/src/org/gudy/azureus2/update/CorePatchChecker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -96,7 +93,7 @@ CorePatchChecker
 		
 			my_updates.put(
 				inst,
-				checker.addUpdate( "Core Patch Checker", new String[0], "",
+				checker.addUpdate( "Core Patch Checker", new String[0], "", "",
 								new ResourceDownloader[0],
 								Update.RESTART_REQUIRED_MAYBE ));
 		}finally{
diff --git a/azureus2/src/org/gudy/azureus2/update/CorePatchLevel.java b/azureus2/src/org/gudy/azureus2/update/CorePatchLevel.java
index d36556b..8ecdc2c 100644
--- a/azureus2/src/org/gudy/azureus2/update/CorePatchLevel.java
+++ b/azureus2/src/org/gudy/azureus2/update/CorePatchLevel.java
@@ -1,7 +1,7 @@
 /*
  * Created on 26-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/update/CoreUpdateChecker.java b/azureus2/src/org/gudy/azureus2/update/CoreUpdateChecker.java
index afe46d9..8e76913 100644
--- a/azureus2/src/org/gudy/azureus2/update/CoreUpdateChecker.java
+++ b/azureus2/src/org/gudy/azureus2/update/CoreUpdateChecker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 20-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -418,6 +415,7 @@ CoreUpdateChecker
 				checker.addUpdate(
 						"Core Azureus Version",
 						desc,
+						current_version,
 						latest_version,
 						top_downloader,
 						Update.RESTART_REQUIRED_YES );
diff --git a/azureus2/src/org/gudy/azureus2/update/UpdateJarPatcher.java b/azureus2/src/org/gudy/azureus2/update/UpdateJarPatcher.java
index c17fc2c..0669f00 100644
--- a/azureus2/src/org/gudy/azureus2/update/UpdateJarPatcher.java
+++ b/azureus2/src/org/gudy/azureus2/update/UpdateJarPatcher.java
@@ -1,7 +1,7 @@
 /*
  * Created on 25-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/update/UpdaterUpdateChecker.java b/azureus2/src/org/gudy/azureus2/update/UpdaterUpdateChecker.java
index 69672cf..5661ff4 100644
--- a/azureus2/src/org/gudy/azureus2/update/UpdaterUpdateChecker.java
+++ b/azureus2/src/org/gudy/azureus2/update/UpdaterUpdateChecker.java
@@ -1,7 +1,7 @@
 /*
  * Created on 07-May-2004
  * Created by Paul Gardner
- * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus2/src/org/gudy/azureus2/update/UpdaterUtils.java b/azureus2/src/org/gudy/azureus2/update/UpdaterUtils.java
index f0b5312..afff3cc 100644
--- a/azureus2/src/org/gudy/azureus2/update/UpdaterUtils.java
+++ b/azureus2/src/org/gudy/azureus2/update/UpdaterUtils.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 31, 2006 1:21:29 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.update;
 
diff --git a/azureus2/src/org/json/simple/AUTHORS.txt b/azureus2/src/org/json/simple/AUTHORS.txt
deleted file mode 100644
index f5ff495..0000000
--- a/azureus2/src/org/json/simple/AUTHORS.txt
+++ /dev/null
@@ -1 +0,0 @@
-Fang Yidong <fangyidong at yahoo.com.cn>
\ No newline at end of file
diff --git a/azureus2/src/org/json/simple/ItemList.java b/azureus2/src/org/json/simple/ItemList.java
deleted file mode 100644
index 29fd8b3..0000000
--- a/azureus2/src/org/json/simple/ItemList.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * $Id: ItemList.java,v 1.2 2009-03-15 22:12:18 parg Exp $
- * Created on 2006-3-24
- */
-package org.json.simple;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.StringTokenizer;
-
-/**
- * �����÷ָ���ֿ���һ��item.�ָ������һ����һ��item.ÿ��item���߲����ǿհ׷�.
- * ���磺
- * |a:b:c| => |a|,|b|,|c|
- * |:| => ||,||
- * |a:| => |a|,||
- * @author FangYidong<fangyidong at yahoo.com.cn>
- */
-public class ItemList {
-	private final static String sp=",";
-	List<String> items=new ArrayList<String>();
-	
-	
-	public ItemList(){}
-	
-	/**
-	 * 
-	 * @param s �ָ������һ���ַ�������
-	 */
-	public ItemList(String s){
-		this.split(s,sp,items);
-	}
-	/**
-	 * 
-	 * @param s �ָ������һ���ַ�������
-	 * @param sp �ָ��
-	 */
-	//public ItemList(String s,String sp){
-	//	this.sp=s;
-	//	this.split(s,sp,items);
-	//}
-	
-	/**
-	 * 
-	 * @param s
-	 * @param sp
-	 * @param isMultiToken sp�Ƿ�Ϊ��ָ��
-	 */
-	public ItemList(String s,String sp,boolean isMultiToken){
-		split(s,sp,items,isMultiToken);
-	}
-	
-	public List<String> getItems(){
-		return this.items;
-	}
-	
-	public String[] getArray(){
-		return (String[])this.items.toArray(new String[items.size()]);
-	}
-	
-	public void split(String s,String sp,List<String> append,boolean isMultiToken){
-		if(s==null || sp==null)
-			return;
-		if(isMultiToken){
-			StringTokenizer tokens=new StringTokenizer(s,sp);
-			while(tokens.hasMoreTokens()){
-				append.add(tokens.nextToken().trim());
-			}
-		}
-		else{
-			this.split(s,sp,append);
-		}
-	}
-	
-	public void split(String s,String sp,List<String> append){
-		if(s==null || sp==null)
-			return;
-		int pos=0;
-		int prevPos=0;
-		do{
-			prevPos=pos;
-			pos=s.indexOf(sp,pos);
-			if(pos==-1)
-				break;
-			append.add(s.substring(prevPos,pos).trim());
-			pos+=sp.length();
-		}while(pos!=-1);
-		append.add(s.substring(prevPos).trim());
-	}
-	
-	/**
-	 * ���÷ָ��.
-	 * @param sp �ָ��
-	 */
-	//public void setSP(String sp){
-	//	this.sp=sp;
-	//}
-	
-	/**
-	 * ���뵥��item.
-	 * @param i �����λ��(֮ǰ)
-	 * @param item
-	 */
-	public void add(int i,String item){
-		if(item==null)
-			return;
-		items.add(i,item.trim());
-	}
-	/**
-	 * ���뵥��item.
-	 * @param item
-	 */
-	public void add(String item){
-		if(item==null)
-			return;
-		items.add(item.trim());
-	}
-	
-	/**
-	 * ��һ��item.
-	 * @param list �����list
-	 */
-	public void addAll(ItemList list){
-		items.addAll(list.items);
-	}
-	
-	/**
-	 * ��һ��item.
-	 * @param s �ָ������һ���ַ�������
-	 */
-	public void addAll(String s){
-		this.split(s,sp,items);
-	}
-	
-	/**
-	 * ��һ��item.
-	 * @param s �ָ������һ���ַ�������
-	 * @param sp �ָ��
-	 */
-	public void addAll(String s,String sp){
-		this.split(s,sp,items);
-	}
-	
-	public void addAll(String s,String sp,boolean isMultiToken){
-		this.split(s,sp,items,isMultiToken);
-	}
-	
-	/**
-	 * ��õ�i��item. 0-based.
-	 * @param i
-	 * @return
-	 */
-	public String get(int i){
-		return (String)items.get(i);
-	}
-	
-	/**
-	 * ���item��.
-	 * @return
-	 */
-	public int size(){
-		return items.size();
-	}
-	/**
-	 * �÷ָ���ָ�ı�ʾ.
-	 */
-	public String toString(){
-		return toString(sp);
-	}
-	
-	/**
-	 * �÷ָ���ָ�ı�ʾ.
-	 * @param sp ����ø÷ָ���ָ�.
-	 * @return
-	 */
-	public String toString(String sp){
-		StringBuffer sb=new StringBuffer();
-		
-		for(int i=0;i<items.size();i++){
-			if(i==0)
-				sb.append(items.get(i));
-			else{
-				sb.append(sp);
-				sb.append(items.get(i));
-			}
-		}
-		return sb.toString();
-
-	}
-	
-	/**
-	 * �������item.
-	 */
-	public void clear(){
-		items.clear();
-	}
-	
-	/**
-	 * ��λ.������ݣ����ָ�����Ĭ��ֵ.
-	 */
-	public void reset(){
-		//sp=",";
-		items.clear();
-	}
-}
diff --git a/azureus2/src/org/json/simple/JSONArray.java b/azureus2/src/org/json/simple/JSONArray.java
deleted file mode 100644
index 172e8b0..0000000
--- a/azureus2/src/org/json/simple/JSONArray.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * $Id: JSONArray.java,v 1.1 2007-06-05 00:43:56 tuxpaper Exp $
- * Created on 2006-4-10
- */
-package org.json.simple;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-
-
-/**
- * @author FangYidong<fangyidong at yahoo.com.cn>
- */
-public class JSONArray extends ArrayList<Object> {
-	public JSONArray() {
-		super();
-	}
-
-	public JSONArray(Collection<Object> arg0) {
-		super(arg0);
-	}
-
-	public JSONArray(int initialCapacity) {
-		super(initialCapacity);
-	}
-
-	public String toString(){
-		ItemList list=new ItemList();
-		
-		Iterator<Object> iter=iterator();
-		
-		while(iter.hasNext()){
-			Object value=iter.next();				
-			if(value instanceof String){
-				list.add("\""+JSONObject.escape((String)value)+"\"");
-			}
-			else
-				list.add(String.valueOf(value));
-		}
-		return "["+list.toString()+"]";
-	}
-	
-	public void toString( StringBuilder sb ){
-		sb.append( "[" );
-
-		Iterator<Object> iter=iterator();
-		
-		boolean	first = true;
-		while(iter.hasNext()){
-			if ( first ){
-				first = false;
-			}else{
-				sb.append( "," );
-			}
-			Object value=iter.next();	
-			if(value instanceof String){
-				sb.append( "\"" );
-				JSONObject.escape(sb, (String)value);
-				sb.append( "\"");
-			}else if ( value instanceof JSONObject ){
-				((JSONObject)value).toString( sb );
-			}else if ( value instanceof JSONArray ){
-				((JSONArray)value).toString( sb ); 
-			}else{
-				sb.append(String.valueOf(value));
-			}
-		}
-		
-		sb.append( "]" );
-	}
-}
diff --git a/azureus2/src/org/json/simple/JSONObject.java b/azureus2/src/org/json/simple/JSONObject.java
deleted file mode 100644
index 08129bd..0000000
--- a/azureus2/src/org/json/simple/JSONObject.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * $Id: JSONObject.java,v 1.2 2008-08-07 01:18:54 parg Exp $
- * Created on 2006-4-10
- */
-package org.json.simple;
-
-import java.util.Iterator;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.LightHashMap;
-
-/**
- * @author FangYidong<fangyidong at yahoo.com.cn>
- */
-public class JSONObject extends LightHashMap<String,Object>{
-	
-	public JSONObject() {
-		super();
-	}
-
-	public JSONObject(int initialCapacity, float loadFactor) {
-		super(initialCapacity, loadFactor);
-	}
-
-	public JSONObject(int initialCapacity) {
-		super(initialCapacity);
-	}
-
-	public JSONObject(Map<String,Object> arg0) {
-		super(arg0);
-	}
-
-	public String toString(){
-		ItemList list=new ItemList();
-		Iterator<Map.Entry<String, Object>> iter=entrySet().iterator();
-		
-		while(iter.hasNext()){
-			Map.Entry<String, Object> entry=iter.next();
-			list.add(toString(entry.getKey().toString(),entry.getValue()));
-		}
-		return "{"+list.toString()+"}";
-	}
-	
-	public void toString( StringBuilder sb ){
-		
-		sb.append( "{" );
-
-		Iterator iter=entrySet().iterator();
-		
-		boolean first = true;
-		
-		while(iter.hasNext()){
-			if ( first ){
-				first = false;
-			}else{
-				sb.append( "," );
-			}
-			Map.Entry entry=(Map.Entry)iter.next();
-			toString(sb, entry.getKey().toString(),entry.getValue());
-		}
-		
-		sb.append( "}" );
-	}
-	
-	public static String toString(String key,Object value){
-		StringBuffer sb=new StringBuffer();
-		
-		sb.append("\"");
-		sb.append(escape(key));
-		sb.append("\":");
-		if(value==null){
-			sb.append("null");
-			return sb.toString();
-		}
-		
-		if(value instanceof String){
-			sb.append("\"");
-			sb.append(escape((String)value));
-			sb.append("\"");
-		}
-		else
-			sb.append(value);
-		return sb.toString();
-	}
-	
-	public static void toString(StringBuilder sb, String key,Object value){
-		sb.append("\"");
-		escape(sb,key);
-		sb.append("\":");
-		if(value==null){
-			sb.append("null");
-			return;
-		}
-		
-		if(value instanceof String){
-			sb.append("\"");
-			escape(sb,(String)value);
-			sb.append("\"");
-		}else if ( value instanceof JSONObject ){
-			((JSONObject)value).toString( sb );
-		}else if ( value instanceof JSONArray ){
-			((JSONArray)value).toString( sb );
-		}else{
-			sb.append(String.valueOf( value ));
-		}
-	}
-	
-	/**
-	 * " => \" , \ => \\
-	 * @param s
-	 * @return
-	 */
-	public static String escape(String s){
-		if(s==null)
-			return null;
-		StringBuffer sb=new StringBuffer();
-		for(int i=0;i<s.length();i++){
-			char ch=s.charAt(i);
-			switch(ch){
-			case '"':
-				sb.append("\\\"");
-				break;
-			case '\\':
-				sb.append("\\\\");
-				break;
-			case '\b':
-				sb.append("\\b");
-				break;
-			case '\f':
-				sb.append("\\f");
-				break;
-			case '\n':
-				sb.append("\\n");
-				break;
-			case '\r':
-				sb.append("\\r");
-				break;
-			case '\t':
-				sb.append("\\t");
-				break;
-			case '/':
-				sb.append("\\/");
-				break;
-			default:
-				if(ch>='\u0000' && ch<='\u001F'){
-					String ss=Integer.toHexString(ch);
-					sb.append("\\u");
-					for(int k=0;k<4-ss.length();k++){
-						sb.append('0');
-					}
-					sb.append(ss.toUpperCase());
-				}
-				else{
-					sb.append(ch);
-				}
-			}
-		}//for
-		return sb.toString();
-	}
-	
-	public static void escape(StringBuilder sb, String s){
-		if(s==null){
-			sb.append((String)null);
-		}else{
-			for(int i=0;i<s.length();i++){
-				char ch=s.charAt(i);
-				switch(ch){
-				case '"':
-					sb.append("\\\"");
-					break;
-				case '\\':
-					sb.append("\\\\");
-					break;
-				case '\b':
-					sb.append("\\b");
-					break;
-				case '\f':
-					sb.append("\\f");
-					break;
-				case '\n':
-					sb.append("\\n");
-					break;
-				case '\r':
-					sb.append("\\r");
-					break;
-				case '\t':
-					sb.append("\\t");
-					break;
-				case '/':
-					sb.append("\\/");
-					break;
-				default:
-					if(ch>='\u0000' && ch<='\u001F'){
-						String ss=Integer.toHexString(ch);
-						sb.append("\\u");
-						for(int k=0;k<4-ss.length();k++){
-							sb.append('0');
-						}
-						sb.append(ss.toUpperCase());
-					}
-					else{
-						sb.append(ch);
-					}
-				}
-			}//for
-		}
-	}
-}
diff --git a/azureus2/src/org/json/simple/JSONValue.java b/azureus2/src/org/json/simple/JSONValue.java
deleted file mode 100644
index 50e388a..0000000
--- a/azureus2/src/org/json/simple/JSONValue.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * $Id: JSONValue.java,v 1.1 2007-06-05 00:43:56 tuxpaper Exp $
- * Created on 2006-4-15
- */
-package org.json.simple;
-
-import java.io.Reader;
-import java.io.StringReader;
-
-import org.json.simple.parser.JSONParser;
-
-
-/**
- * @author FangYidong<fangyidong at yahoo.com.cn>
- */
-public class JSONValue {
-	/**
-	 * parse into java object from input source.
-	 * @param in
-	 * @return instance of : JSONObject,JSONArray,String,Boolean,Long,Double or null
-	 */
-	public static Object parse(Reader in){
-		try{
-			JSONParser parser=new JSONParser();
-			return parser.parse(in);
-		}
-		catch(Exception e){
-			return null;
-		}
-	}
-	
-	public static Object parse(String s){
-		StringReader in=new StringReader(s);
-		return parse(in);
-	}
-}
diff --git a/azureus2/src/org/json/simple/LICENSE.txt b/azureus2/src/org/json/simple/LICENSE.txt
deleted file mode 100644
index 5ab7695..0000000
--- a/azureus2/src/org/json/simple/LICENSE.txt
+++ /dev/null
@@ -1,504 +0,0 @@
-		  GNU LESSER GENERAL PUBLIC LICENSE
-		       Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL.  It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
-  When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-

-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard.  To achieve this, non-free programs must be
-allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-

-		  GNU LESSER GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-

-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-

-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-

-  6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Use a suitable shared library mechanism for linking with the
-    Library.  A suitable mechanism is one that (1) uses at run time a
-    copy of the library already present on the user's computer system,
-    rather than copying library functions into the executable, and (2)
-    will operate properly with a modified version of the library, if
-    the user installs one, as long as the modified version is
-    interface-compatible with the version that the work was made with.
-
-    c) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    d) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    e) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-

-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-

-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-

-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-			    NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-

-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library 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
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/azureus2/src/org/json/simple/README.txt b/azureus2/src/org/json/simple/README.txt
deleted file mode 100644
index 71e8475..0000000
--- a/azureus2/src/org/json/simple/README.txt
+++ /dev/null
@@ -1,144 +0,0 @@
-Simple Java toolkit for JSON (JSON.simple)
-==========================================
-
-1.Why the Simple Java toolkit (also named as JSON.simple) for JSON?
-  
-  When I use JSON as the data exchange format between the AJAX client and JSP 
-  for the first time, what worry me mostly is how to encode Java strings and 
-  numbers correctly in the server side so the AJAX client will receive a well
-  formed JSON data. When I looked into the 'JSON in Java' directory in JSON
-  website,I found that wrappers to JSONObject and JSONArray can be simpler, 
-  due to the simplicity of JSON itself. So I wrote the JSON.simple package.
-
-2.Is it simple,really?
-  
-  I think so. Take an example:
-
-  import org.json.simple.JSONObject;
-
-  JSONObject obj=new JSONObject();
-  obj.put("name","foo");
-  obj.put("num",new Integer(100));
-  obj.put("balance",new Double(1000.21));
-  obj.put("is_vip",new Boolean(true));
-  obj.put("nickname",null);
-  System.out.print(obj);
-
-  Result:
-  {"nickname":null,"num":100,"balance":1000.21,"is_vip":true,"name":"foo"}
-
-  The JSONObject.toString() will escape controls and specials correctly.
-
-3.How to use JSON.simple in JSP?
-
-  Take an example in JSP:
-  
-  <%@page contentType="text/html; charset=UTF-8"%>
-  <%@page import="org.json.simple.JSONObject"%>
-  <%
-	JSONObject obj=new JSONObject();
-  	obj.put("name","foo");
-  	obj.put("num",new Integer(100));
-  	obj.put("balance",new Double(1000.21));
-  	obj.put("is_vip",new Boolean(true));
-  	obj.put("nickname",null);
-	out.print(obj);
-	out.flush();
-  %>
-  
-  So the AJAX client will get the responseText.
-
-4.Some details about JSONObject?
-  
-  JSONObject inherits java.util.HashMap,so it don't have to worry about the 
-  mapping things between keys and values. Feel free to use the Map methods 
-  like get(), put(), and remove() and others. JSONObject.toString() will 
-  combine key value pairs to get the JSON data string. Values will be escaped
-  into JSON quote string format if it's an instance of java.lang.String. Other
-  type of instance like java.lang.Number,java.lang.Boolean,null,JSONObject and
-  JSONArray will NOT escape, just take their java.lang.String.valueOf() result.
-  null value will be the JSON 'null' in the result.
-
-  It's still correct if you put an instance of JSONObject or JSONArray into an 
-  instance of JSONObject or JSONArray. Take the example about:
-
-  JSONObject obj2=new JSONObject();
-  obj2.put("phone","123456");
-  obj2.put("zip","7890");
-  obj.put("contact",obj2);
-  System.out.print(obj);
-
-  Result:
-  {"nickname":null,"num":100,"contact":{"phone":"123456","zip":"7890"},"balance":1000.21,"is_vip":true,"name":"foo"}
-
-  The method JSONObject.escape() is used to escape Java string into JSON quote 
-  string. Controls and specials will be escaped correctly into \b,\f,\r,\n,\t,
-  \",\\,\/,\uhhhh.
-
-5.Some detail about JSONArray?
-  
-  org.json.simple.JSONArray inherits java.util.ArrayList. Feel free to use the
-  List methods like get(),add(),remove(),iterator() and so on. The rules of 
-  JSONArray.toString() is similar to JSONObject.toString(). Here's the example:
-
-  import org.json.simple.JSONArray;
-
-  JSONArray array=new JSONArray();
-  array.add("hello");
-  array.add(new Integer(123));
-  array.add(new Boolean(false));
-  array.add(null);
-  array.add(new Double(123.45));
-  array.add(obj2);//see above
-  System.out.print(array);
-
-  Result:
-  ["hello",123,false,null,123.45,{"phone":"123456","zip":"7890"}]
-
-6.What is JSONValue for?  
-
-  org.json.simple.JSONValue is use to parse JSON data into Java Object. 
-  In JSON, the topmost entity is JSON value, not the JSON object. But
-  it's not necessary to wrap JSON string,boolean,number and null again,
-  for the Java has already had the according classes: java.lang.String,
-  java.lang.Boolean,java.lang.Number and null. The mapping is:
-
-  JSON			Java
-  ------------------------------------------------
-  string      <=>  	java.lang.String 
-  number      <=>	java.lang.Number
-  true|false  <=>	java.lang.Boolean
-  null        <=>	null
-  array	      <=>	org.json.simple.JSONArray
-  object      <=>       org.json.simple.JSONObject
-  ------------------------------------------------
-
-  JSONValue has only one kind of method, JSONValue.parse(), which receives
-  a java.io.Reader or java.lang.String. Return type of JSONValue.parse() 
-  is according to the mapping above. If the input is incorrect in syntax or
-  there's exceptions during the parsing, I choose to return null, ignoring 
-  the exception: I have no idea if it's a serious implementaion, but I think
-  it's convenient to the user.
-  
-  Here's the example:
-  
-  String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]";
-  Object obj=JSONValue.parse(s);
-  JSONArray array=(JSONArray)obj;
-  System.out.println(array.get(1));
-  JSONObject obj2=(JSONObject)array.get(1);
-  System.out.println(obj2.get("1"));
-
-  Result:
-  {"1":{"2":{"3":{"4":[5,{"6":7}]}}}}
-  {"2":{"3":{"4":[5,{"6":7}]}}}
-
-7.About the author.
-
-  I'm a Java EE developer on Linux. 
-  I'm working on web systems and information retrieval systems.
-  I also develop 3D games and Flash games. 
-
-  You can contact me through: 
-  Fang Yidong<fangyidong at yahoo.com.cn>
-  Fang Yidong<fangyidng at gmail.com> 
diff --git a/azureus2/src/org/json/simple/Test.java b/azureus2/src/org/json/simple/Test.java
deleted file mode 100644
index 750b34b..0000000
--- a/azureus2/src/org/json/simple/Test.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * $Id: Test.java,v 1.1 2007-06-05 00:43:56 tuxpaper Exp $
- * Created on 2006-4-15
- */
-package org.json.simple;
-
-
-/**
- * @author FangYidong<fangyidong at yahoo.com.cn>
- */
-public class Test {
-
-	public static void main(String[] args) throws Exception{
-		JSONArray array1=new JSONArray();
-		array1.add("abc\u0010a/");
-		array1.add(new Integer(123));
-		array1.add(new Double(122.22));
-		array1.add(new Boolean(true));
-		System.out.println("======array1==========");
-		System.out.println(array1);
-		System.out.println();
-		
-		JSONObject obj1=new JSONObject();
-		obj1.put("name","fang");
-		obj1.put("age",new Integer(27));
-		obj1.put("is_developer",new Boolean(true));
-		obj1.put("weight",new Double(60.21));
-		obj1.put("array1",array1);
-		System.out.println();
-		
-		System.out.println("======obj1 with array1===========");
-		System.out.println(obj1);
-		System.out.println();
-		
-		obj1.remove("array1");
-		array1.add(obj1);
-		System.out.println("======array1 with obj1========");
-		System.out.println(array1);
-		System.out.println();
-		
-		System.out.println("======parse to java========");
-
-		String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]";
-		Object obj=JSONValue.parse(s);
-		JSONArray array=(JSONArray)obj;
-		System.out.println("======the 2nd element of array======");
-		System.out.println(array.get(1));
-		System.out.println();
-		
-		JSONObject obj2=(JSONObject)array.get(1);
-		System.out.println("======field \"1\"==========");
-		System.out.println(obj2.get("1"));	
-	}
-}
diff --git a/azureus2/src/org/json/simple/parser/JSONParser.java b/azureus2/src/org/json/simple/parser/JSONParser.java
deleted file mode 100644
index 90e0886..0000000
--- a/azureus2/src/org/json/simple/parser/JSONParser.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * $Id: JSONParser.java,v 1.2 2008-08-07 01:18:55 parg Exp $
- * Created on 2006-4-15
- */
-package org.json.simple.parser;
-
-import java.io.Reader;
-import java.util.Stack;
-
-import org.gudy.azureus2.core3.util.LightHashMap;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-
-
-/**
- * @author FangYidong<fangyidong at yahoo.com.cn>
- */
-public class JSONParser {
-	public static final int S_INIT=0;
-	public static final int S_IN_FINISHED_VALUE=1;//string,number,boolean,null,object,array
-	public static final int S_IN_OBJECT=2;
-	public static final int S_IN_ARRAY=3;
-	public static final int S_PASSED_PAIR_KEY=4;
-	public static final int S_IN_ERROR=-1;
-	
-	private int peekStatus(Stack statusStack){
-		if(statusStack.size()==0)
-			return -1;
-		Integer status=(Integer)statusStack.peek();
-		return status.intValue();
-	}
-	
-	public Object parse(Reader in) throws Exception{
-		Stack statusStack=new Stack();
-		Stack valueStack=new Stack();
-		Yylex lexer=new Yylex(in);
-		Yytoken token=null;
-		int status=S_INIT;
-		
-		try{
-			do{
-				token=lexer.yylex();
-				if(token==null)
-					token=new Yytoken(Yytoken.TYPE_EOF,null);
-				switch(status){
-				case S_INIT:
-					switch(token.type){
-					case Yytoken.TYPE_VALUE:
-						status=S_IN_FINISHED_VALUE;
-						statusStack.push(new Integer(status));
-						valueStack.push(token.value);
-						break;
-					case Yytoken.TYPE_LEFT_BRACE:
-						status=S_IN_OBJECT;
-						statusStack.push(new Integer(status));
-						valueStack.push(new JSONObject());
-						break;
-					case Yytoken.TYPE_LEFT_SQUARE:
-						status=S_IN_ARRAY;
-						statusStack.push(new Integer(status));
-						valueStack.push(new JSONArray());
-						break;
-					default:
-						status=S_IN_ERROR;
-					}//inner switch
-					break;
-					
-				case S_IN_FINISHED_VALUE:
-					if(token.type==Yytoken.TYPE_EOF)
-						return valueStack.pop();
-					else
-						return null;
-					
-				case S_IN_OBJECT:
-					switch(token.type){
-					case Yytoken.TYPE_COMMA:
-						break;
-					case Yytoken.TYPE_VALUE:
-						if(token.value instanceof String){
-							String key=(String)token.value;
-							valueStack.push(key);
-							status=S_PASSED_PAIR_KEY;
-							statusStack.push(new Integer(status));
-						}
-						else{
-							status=S_IN_ERROR;
-						}
-						break;
-					case Yytoken.TYPE_RIGHT_BRACE:
-						if(valueStack.size()>1){
-							statusStack.pop();
-							JSONObject map = (JSONObject)valueStack.pop();
-							map.compactify(-0.9f);
-							status=peekStatus(statusStack);
-						}
-						else{
-							status=S_IN_FINISHED_VALUE;
-						}
-						break;
-					default:
-						status=S_IN_ERROR;
-						break;
-					}//inner switch
-					break;
-					
-				case S_PASSED_PAIR_KEY:
-					switch(token.type){
-					case Yytoken.TYPE_COLON:
-						break;
-					case Yytoken.TYPE_VALUE:
-						statusStack.pop();
-						String key=(String)valueStack.pop();
-						JSONObject parent=(JSONObject)valueStack.peek();
-						parent.put(key,token.value);
-						status=peekStatus(statusStack);
-						break;
-					case Yytoken.TYPE_LEFT_SQUARE:
-						statusStack.pop();
-						key=(String)valueStack.pop();
-						parent=(JSONObject)valueStack.peek();
-						JSONArray newArray=new JSONArray();
-						parent.put(key,newArray);
-						status=S_IN_ARRAY;
-						statusStack.push(new Integer(status));
-						valueStack.push(newArray);
-						break;
-					case Yytoken.TYPE_LEFT_BRACE:
-						statusStack.pop();
-						key=(String)valueStack.pop();
-						parent=(JSONObject)valueStack.peek();
-						JSONObject newObject=new JSONObject();
-						parent.put(key,newObject);
-						status=S_IN_OBJECT;
-						statusStack.push(new Integer(status));
-						valueStack.push(newObject);
-						break;
-					default:
-						status=S_IN_ERROR;
-					}
-					break;
-					
-				case S_IN_ARRAY:
-					switch(token.type){
-					case Yytoken.TYPE_COMMA:
-						break;
-					case Yytoken.TYPE_VALUE:
-						JSONArray val=(JSONArray)valueStack.peek();
-						val.add(token.value);
-						break;
-					case Yytoken.TYPE_RIGHT_SQUARE:
-						if(valueStack.size()>1){
-							statusStack.pop();
-							valueStack.pop();
-							status=peekStatus(statusStack);
-						}
-						else{
-							status=S_IN_FINISHED_VALUE;
-						}
-						break;
-					case Yytoken.TYPE_LEFT_BRACE:
-						val=(JSONArray)valueStack.peek();
-						JSONObject newObject=new JSONObject();
-						val.add(newObject);
-						status=S_IN_OBJECT;
-						statusStack.push(new Integer(status));
-						valueStack.push(newObject);
-						break;
-					case Yytoken.TYPE_LEFT_SQUARE:
-						val=(JSONArray)valueStack.peek();
-						JSONArray newArray=new JSONArray();
-						val.add(newArray);
-						status=S_IN_ARRAY;
-						statusStack.push(new Integer(status));
-						valueStack.push(newArray);
-						break;
-					default:
-						status=S_IN_ERROR;
-					}//inner switch
-					break;
-				case S_IN_ERROR:
-					return null;
-				}//switch
-				if(status==S_IN_ERROR)
-					return null;
-			}while(token.type!=Yytoken.TYPE_EOF);
-		}
-		catch(Exception e){
-			throw e;
-		}
-		return null;
-	}
-}
diff --git a/azureus2/src/org/json/simple/parser/Yylex.java b/azureus2/src/org/json/simple/parser/Yylex.java
deleted file mode 100644
index cf79958..0000000
--- a/azureus2/src/org/json/simple/parser/Yylex.java
+++ /dev/null
@@ -1,428 +0,0 @@
-package org.json.simple.parser;
-
-
-class Yylex {
-	private final static int YY_BUFFER_SIZE = 512;
-	private final static int YY_F = -1;
-	private final static int YY_NO_STATE = -1;
-	private final static int YY_NOT_ACCEPT = 0;
-	//private final static int YY_START = 1;
-	private final static int YY_END = 2;
-	private final static int YY_NO_ANCHOR = 4;
-	private final static int YY_BOL = 65536;
-	private final static int YY_EOF = 65537;
-
-private StringBuffer sb=new StringBuffer();
-	private java.io.BufferedReader yy_reader;
-	private int yy_buffer_index;
-	private int yy_buffer_read;
-	private int yy_buffer_start;
-	private int yy_buffer_end;
-	private char yy_buffer[];
-	private boolean yy_at_bol;
-	private int yy_lexical_state;
-
-	Yylex (java.io.Reader reader) {
-		this ();
-		if (null == reader) {
-			throw (new Error("Error: Bad input stream initializer."));
-		}
-		yy_reader = new java.io.BufferedReader(reader);
-	}
-
-	Yylex (java.io.InputStream instream) {
-		this ();
-		if (null == instream) {
-			throw (new Error("Error: Bad input stream initializer."));
-		}
-		yy_reader = new java.io.BufferedReader(new java.io.InputStreamReader(instream));
-	}
-
-	private Yylex () {
-		yy_buffer = new char[YY_BUFFER_SIZE];
-		yy_buffer_read = 0;
-		yy_buffer_index = 0;
-		yy_buffer_start = 0;
-		yy_buffer_end = 0;
-		yy_at_bol = true;
-		yy_lexical_state = YYINITIAL;
-	}
-
-	//private boolean yy_eof_done = false;
-	private static final int YYINITIAL = 0;
-	private static final int STRING_BEGIN = 1;
-	private static final int yy_state_dtrans[] = {
-		0,
-		39
-	};
-	private void yybegin (int state) {
-		yy_lexical_state = state;
-	}
-	private int yy_advance ()
-		throws java.io.IOException {
-		int next_read;
-		int i;
-		int j;
-
-		if (yy_buffer_index < yy_buffer_read) {
-			return yy_buffer[yy_buffer_index++];
-		}
-
-		if (0 != yy_buffer_start) {
-			i = yy_buffer_start;
-			j = 0;
-			while (i < yy_buffer_read) {
-				yy_buffer[j] = yy_buffer[i];
-				++i;
-				++j;
-			}
-			yy_buffer_end = yy_buffer_end - yy_buffer_start;
-			yy_buffer_start = 0;
-			yy_buffer_read = j;
-			yy_buffer_index = j;
-			next_read = yy_reader.read(yy_buffer,
-					yy_buffer_read,
-					yy_buffer.length - yy_buffer_read);
-			if (-1 == next_read) {
-				return YY_EOF;
-			}
-			yy_buffer_read = yy_buffer_read + next_read;
-		}
-
-		while (yy_buffer_index >= yy_buffer_read) {
-			if (yy_buffer_index >= yy_buffer.length) {
-				yy_buffer = yy_double(yy_buffer);
-			}
-			next_read = yy_reader.read(yy_buffer,
-					yy_buffer_read,
-					yy_buffer.length - yy_buffer_read);
-			if (-1 == next_read) {
-				return YY_EOF;
-			}
-			yy_buffer_read = yy_buffer_read + next_read;
-		}
-		return yy_buffer[yy_buffer_index++];
-	}
-	private void yy_move_end () {
-		if (yy_buffer_end > yy_buffer_start &&
-		    '\n' == yy_buffer[yy_buffer_end-1])
-			yy_buffer_end--;
-		if (yy_buffer_end > yy_buffer_start &&
-		    '\r' == yy_buffer[yy_buffer_end-1])
-			yy_buffer_end--;
-	}
-	//private boolean yy_last_was_cr=false;
-	private void yy_mark_start () {
-		yy_buffer_start = yy_buffer_index;
-	}
-	private void yy_mark_end () {
-		yy_buffer_end = yy_buffer_index;
-	}
-	private void yy_to_mark () {
-		yy_buffer_index = yy_buffer_end;
-		yy_at_bol = (yy_buffer_end > yy_buffer_start) &&
-		            ('\r' == yy_buffer[yy_buffer_end-1] ||
-		             '\n' == yy_buffer[yy_buffer_end-1] ||
-		             2028/*LS*/ == yy_buffer[yy_buffer_end-1] ||
-		             2029/*PS*/ == yy_buffer[yy_buffer_end-1]);
-	}
-	private java.lang.String yytext () {
-		return (new java.lang.String(yy_buffer,
-			yy_buffer_start,
-			yy_buffer_end - yy_buffer_start));
-	}
-	//private int yylength () {
-	//	return yy_buffer_end - yy_buffer_start;
-	//}
-	private char[] yy_double (char buf[]) {
-		int i;
-		char newbuf[];
-		newbuf = new char[2*buf.length];
-		for (i = 0; i < buf.length; ++i) {
-			newbuf[i] = buf[i];
-		}
-		return newbuf;
-	}
-	private static final int YY_E_INTERNAL = 0;
-	//private final int YY_E_MATCH = 1;
-	private java.lang.String yy_error_string[] = {
-		"Error: Internal error.\n",
-		"Error: Unmatched input.\n"
-	};
-	private void yy_error (int code,boolean fatal) {
-		java.lang.System.out.print(yy_error_string[code]);
-		java.lang.System.out.flush();
-		if (fatal) {
-			throw new Error("Fatal Error.\n");
-		}
-	}
-	private static int[][] unpackFromString(int size1, int size2, String st) {
-		int colonIndex = -1;
-		String lengthString;
-		int sequenceLength = 0;
-		int sequenceInteger = 0;
-
-		int commaIndex;
-		String workString;
-
-		int res[][] = new int[size1][size2];
-		for (int i= 0; i < size1; i++) {
-			for (int j= 0; j < size2; j++) {
-				if (sequenceLength != 0) {
-					res[i][j] = sequenceInteger;
-					sequenceLength--;
-					continue;
-				}
-				commaIndex = st.indexOf(',');
-				workString = (commaIndex==-1) ? st :
-					st.substring(0, commaIndex);
-				st = st.substring(commaIndex+1);
-				colonIndex = workString.indexOf(':');
-				if (colonIndex == -1) {
-					res[i][j]=Integer.parseInt(workString);
-					continue;
-				}
-				lengthString =
-					workString.substring(colonIndex+1);
-				sequenceLength=Integer.parseInt(lengthString);
-				workString=workString.substring(0,colonIndex);
-				sequenceInteger=Integer.parseInt(workString);
-				res[i][j] = sequenceInteger;
-				sequenceLength--;
-			}
-		}
-		return res;
-	}
-	private static final int yy_acpt[] = {
-		/* 0 */ YY_NOT_ACCEPT,
-		/* 1 */ YY_NO_ANCHOR,
-		/* 2 */ YY_NO_ANCHOR,
-		/* 3 */ YY_NO_ANCHOR,
-		/* 4 */ YY_NO_ANCHOR,
-		/* 5 */ YY_NO_ANCHOR,
-		/* 6 */ YY_NO_ANCHOR,
-		/* 7 */ YY_NO_ANCHOR,
-		/* 8 */ YY_NO_ANCHOR,
-		/* 9 */ YY_NO_ANCHOR,
-		/* 10 */ YY_NO_ANCHOR,
-		/* 11 */ YY_NO_ANCHOR,
-		/* 12 */ YY_NO_ANCHOR,
-		/* 13 */ YY_NO_ANCHOR,
-		/* 14 */ YY_NO_ANCHOR,
-		/* 15 */ YY_NO_ANCHOR,
-		/* 16 */ YY_NO_ANCHOR,
-		/* 17 */ YY_NO_ANCHOR,
-		/* 18 */ YY_NO_ANCHOR,
-		/* 19 */ YY_NO_ANCHOR,
-		/* 20 */ YY_NO_ANCHOR,
-		/* 21 */ YY_NO_ANCHOR,
-		/* 22 */ YY_NO_ANCHOR,
-		/* 23 */ YY_NO_ANCHOR,
-		/* 24 */ YY_NO_ANCHOR,
-		/* 25 */ YY_NOT_ACCEPT,
-		/* 26 */ YY_NO_ANCHOR,
-		/* 27 */ YY_NO_ANCHOR,
-		/* 28 */ YY_NOT_ACCEPT,
-		/* 29 */ YY_NOT_ACCEPT,
-		/* 30 */ YY_NOT_ACCEPT,
-		/* 31 */ YY_NOT_ACCEPT,
-		/* 32 */ YY_NOT_ACCEPT,
-		/* 33 */ YY_NOT_ACCEPT,
-		/* 34 */ YY_NOT_ACCEPT,
-		/* 35 */ YY_NOT_ACCEPT,
-		/* 36 */ YY_NOT_ACCEPT,
-		/* 37 */ YY_NOT_ACCEPT,
-		/* 38 */ YY_NOT_ACCEPT,
-		/* 39 */ YY_NOT_ACCEPT,
-		/* 40 */ YY_NOT_ACCEPT,
-		/* 41 */ YY_NOT_ACCEPT,
-		/* 42 */ YY_NOT_ACCEPT,
-		/* 43 */ YY_NOT_ACCEPT,
-		/* 44 */ YY_NOT_ACCEPT
-	};
-	private static final int yy_cmap[] = unpackFromString(1,65538,
-"11:8,27:2,28,11,27,28,11:18,27,11,2,11:8,16,25,12,14,3,13:10,26,11:6,10:4,1" +
-"5,10,11:20,23,1,24,11:3,18,4,10:2,17,5,11:5,19,11,6,11:3,7,20,8,9,11:5,21,1" +
-"1,22,11:65410,0:2")[0];
-
-	private static final int yy_rmap[] = unpackFromString(1,45,
-"0,1:2,2,1:7,3,1:2,4,1:10,5,6,1,7,8,9,10,11,12,13,14,15,16,6,17,18,19,20,21," +
-"22")[0];
-
-	private static final int yy_nxt[][] = unpackFromString(23,29,
-"1,-1,2,-1:2,25,28,-1,29,-1:3,30,3,-1:7,4,5,6,7,8,9,10:2,-1:42,3,33,34,-1,34" +
-",-1:24,11,-1,34,-1,34,-1:12,16,17,18,19,20,21,22,23,40,-1:37,31,-1:23,26,-1" +
-":24,42,-1:26,32,-1:34,3,-1:34,35,-1:18,37,-1:32,11,-1:27,38,26,-1:2,38,-1:3" +
-"2,37,-1:27,12,-1:26,13,-1:11,1,14,15,27:25,-1:5,44:2,-1:4,44,-1:2,44,-1,44," +
-"-1,44:2,-1:14,24:2,-1:4,24,-1:2,24,-1,24,-1,24:2,-1:29,36,-1:13,41:2,-1:4,4" +
-"1,-1:2,41,-1,41,-1,41:2,-1:14,43:2,-1:4,43,-1:2,43,-1,43,-1,43:2,-1:10");
-
-	public Yytoken yylex ()
-		throws java.io.IOException {
-		int yy_lookahead;
-		int yy_anchor = YY_NO_ANCHOR;
-		int yy_state = yy_state_dtrans[yy_lexical_state];
-		int yy_next_state = YY_NO_STATE;
-		int yy_last_accept_state = YY_NO_STATE;
-		boolean yy_initial = true;
-		int yy_this_accept;
-
-		yy_mark_start();
-		yy_this_accept = yy_acpt[yy_state];
-		if (YY_NOT_ACCEPT != yy_this_accept) {
-			yy_last_accept_state = yy_state;
-			yy_mark_end();
-		}
-		while (true) {
-			if (yy_initial && yy_at_bol) yy_lookahead = YY_BOL;
-			else yy_lookahead = yy_advance();
-			yy_next_state = YY_F;
-			yy_next_state = yy_nxt[yy_rmap[yy_state]][yy_cmap[yy_lookahead]];
-			if (YY_EOF == yy_lookahead && true == yy_initial) {
-				return null;
-			}
-			if (YY_F != yy_next_state) {
-				yy_state = yy_next_state;
-				yy_initial = false;
-				yy_this_accept = yy_acpt[yy_state];
-				if (YY_NOT_ACCEPT != yy_this_accept) {
-					yy_last_accept_state = yy_state;
-					yy_mark_end();
-				}
-			}
-			else {
-				if (YY_NO_STATE == yy_last_accept_state) {
-					throw (new Error("Lexical Error: Unmatched Input."));
-				}
-				else {
-					yy_anchor = yy_acpt[yy_last_accept_state];
-					if (0 != (YY_END & yy_anchor)) {
-						yy_move_end();
-					}
-					yy_to_mark();
-					switch (yy_last_accept_state) {
-					case 1:
-						
-					case -2:
-						break;
-					case 2:
-						{ sb.delete(0,sb.length());yybegin(STRING_BEGIN);}
-					case -3:
-						break;
-					case 3:
-						{ Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);}
-					case -4:
-						break;
-					case 4:
-						{ return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null);}
-					case -5:
-						break;
-					case 5:
-						{ return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null);}
-					case -6:
-						break;
-					case 6:
-						{ return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null);}
-					case -7:
-						break;
-					case 7:
-						{ return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null);}
-					case -8:
-						break;
-					case 8:
-						{ return new Yytoken(Yytoken.TYPE_COMMA,null);}
-					case -9:
-						break;
-					case 9:
-						{ return new Yytoken(Yytoken.TYPE_COLON,null);}
-					case -10:
-						break;
-					case 10:
-						{}
-					case -11:
-						break;
-					case 11:
-						{ Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);}
-					case -12:
-						break;
-					case 12:
-						{ return new Yytoken(Yytoken.TYPE_VALUE,null);}
-					case -13:
-						break;
-					case 13:
-						{ Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);}
-					case -14:
-						break;
-					case 14:
-						{ sb.append(yytext());}
-					case -15:
-						break;
-					case 15:
-						{ yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE,sb.toString());}
-					case -16:
-						break;
-					case 16:
-						{sb.append('\\');}
-					case -17:
-						break;
-					case 17:
-						{sb.append('"');}
-					case -18:
-						break;
-					case 18:
-						{sb.append('/');}
-					case -19:
-						break;
-					case 19:
-						{sb.append('\b');}
-					case -20:
-						break;
-					case 20:
-						{sb.append('\f');}
-					case -21:
-						break;
-					case 21:
-						{sb.append('\n');}
-					case -22:
-						break;
-					case 22:
-						{sb.append('\r');}
-					case -23:
-						break;
-					case 23:
-						{sb.append('\t');}
-					case -24:
-						break;
-					case 24:
-						{	int ch=Integer.parseInt(yytext().substring(2),16);
-													sb.append((char)ch);
-												}
-					case -25:
-						break;
-					case 26:
-						{ Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);}
-					case -26:
-						break;
-					case 27:
-						{ sb.append(yytext());}
-					case -27:
-						break;
-					default:
-						yy_error(YY_E_INTERNAL,false);
-					case -1:
-					}
-					yy_initial = true;
-					yy_state = yy_state_dtrans[yy_lexical_state];
-					yy_next_state = YY_NO_STATE;
-					yy_last_accept_state = YY_NO_STATE;
-					yy_mark_start();
-					yy_this_accept = yy_acpt[yy_state];
-					if (YY_NOT_ACCEPT != yy_this_accept) {
-						yy_last_accept_state = yy_state;
-						yy_mark_end();
-					}
-				}
-			}
-		}
-	}
-}
diff --git a/azureus2/src/org/json/simple/parser/Yytoken.java b/azureus2/src/org/json/simple/parser/Yytoken.java
deleted file mode 100644
index 4c90001..0000000
--- a/azureus2/src/org/json/simple/parser/Yytoken.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * $Id: Yytoken.java,v 1.1 2007-06-05 00:43:56 tuxpaper Exp $
- * Created on 2006-4-15
- */
-package org.json.simple.parser;
-
-/**
- * @author FangYidong<fangyidong at yahoo.com.cn>
- */
-public class Yytoken {
-	public static final int TYPE_VALUE=0;//JSON primitive value: string,number,boolean,null
-	public static final int TYPE_LEFT_BRACE=1;
-	public static final int TYPE_RIGHT_BRACE=2;
-	public static final int TYPE_LEFT_SQUARE=3;
-	public static final int TYPE_RIGHT_SQUARE=4;
-	public static final int TYPE_COMMA=5;
-	public static final int TYPE_COLON=6;
-	public static final int TYPE_EOF=-1;//end of file
-	
-	public int type=0;
-	public Object value=null;
-	
-	public Yytoken(int type,Object value){
-		this.type=type;
-		this.value=value;
-	}
-	
-	public String toString(){
-		return String.valueOf(type+"=>|"+value+"|");
-	}
-}
diff --git a/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesConstants.java b/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesConstants.java
index 29b6e2c..3917bc4 100644
--- a/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesConstants.java
+++ b/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesConstants.java
@@ -1,10 +1,12 @@
 /**
  * Created on May 28, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesEntry.java b/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesEntry.java
index e0b913c..558f46a 100644
--- a/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesEntry.java
+++ b/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesEntry.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 28, 2008 
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -535,13 +537,13 @@ public class VuzeActivitiesEntry
 
 	}
 
-	public boolean isPlayable() {
+	public boolean isPlayable( boolean blocking) {
 		// our variable is an override
 		if (playable)  {
 			return true;
 		}
 		// use torrent so we don't recurse
-		return PlayUtils.canPlayDS(DataSourceUtils.getTorrent(this), -1);
+		return PlayUtils.canPlayDS(DataSourceUtils.getTorrent(this), -1, blocking);
 	}
 
 	public void setPlayable(boolean playable) {
diff --git a/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesListener.java b/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesListener.java
index 5e146a5..515a079 100644
--- a/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesListener.java
+++ b/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 28, 2008 
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesLoadedListener.java b/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesLoadedListener.java
index 63c0c7e..166604b 100644
--- a/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesLoadedListener.java
+++ b/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesLoadedListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 15, 2011
  *
- * Copyright 2010 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesManager.java b/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesManager.java
index e391a39..d6418e2 100644
--- a/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesManager.java
+++ b/azureus3/src/com/aelitis/azureus/activities/VuzeActivitiesManager.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 28, 2008 
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetwork.java b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetwork.java
index 664369d..82b8e77 100644
--- a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetwork.java
+++ b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetwork.java
@@ -1,281 +1,280 @@
-/*
- * Created on Nov 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 com.aelitis.azureus.core.cnetwork;
-
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-
-public interface 
-ContentNetwork 
-{
-	public static final long	CONTENT_NETWORK_UNKNOWN		= -1;
-	
-	public static final long	CONTENT_NETWORK_VUZE		= 1;
-	
-		/**
-		 * You should normally NOT refer explicitly to this constant without consideration
-		 * as we don't want network-specific code proliferating
-		 */
-	
-	public static final long	CONTENT_NETWORK_RFN			= 2;
-	
-	public static final long	CONTENT_NETWORK_VHDNL		= 3;
-
-
-	public static final int		SERVICE_SEARCH				= 1;	// String - query text
-	public static final int		SERVICE_XSEARCH				= 2;	// String - query text; Boolean - toSubscribe
-	public static final int		SERVICE_RPC					= 3;
-	public static final int		SERVICE_RELAY_RPC			= 4;
-	public static final int		SERVICE_AUTH_RPC			= 5;
-	public static final int		SERVICE_BIG_BROWSE			= 6;
-	public static final int		SERVICE_PUBLISH				= 7;
-	public static final int		SERVICE_WELCOME				= 8;
-	public static final int		SERVICE_PUBLISH_NEW			= 9;
-	public static final int		SERVICE_PUBLISH_ABOUT		= 10;
-	public static final int		SERVICE_CONTENT_DETAILS		= 11;	// String - hash; String (can be null) - client ref
-	public static final int		SERVICE_COMMENT				= 12;	// String - hash
-	public static final int		SERVICE_PROFILE				= 13;	// String - login_id; String - client ref
-	public static final int		SERVICE_TORRENT_DOWNLOAD	= 14;	// String - hash; String (can be null) - client ref
-	public static final int		SERVICE_SITE				= 15;
-	public static final int		SERVICE_SUPPORT				= 16;
-	public static final int		SERVICE_FAQ					= 17;
-	public static final int		SERVICE_FAQ_TOPIC			= 18;	// String - topic entry
-	public static final int		SERVICE_BLOG				= 19;
-	public static final int		SERVICE_FORUMS				= 20;
-	public static final int		SERVICE_WIKI				= 21;
-	public static final int		SERVICE_LOGIN				= 22;	// String - message (can be null)
-	public static final int		SERVICE_LOGOUT				= 23;
-	public static final int		SERVICE_REGISTER			= 24;
-	public static final int		SERVICE_MY_PROFILE			= 25;
-	public static final int		SERVICE_MY_ACCOUNT			= 26;
-	public static final int		SERVICE_SITE_RELATIVE		= 27;	// String - relative URL
-	public static final int		SERVICE_ADD_FRIEND			= 28;	// String - bg colour
-	public static final int		SERVICE_SUBSCRIPTION		= 29;	// String - subscription ID
-	public static final int		SERVICE_GET_ICON			= 30;	
-	public static final int		SERVICE_AUTHORIZE			= 31;	
-	public static final int		SERVICE_PREPLAYBACK  		= 32;
-	public static final int		SERVICE_POSTPLAYBACK  		= 33;
-	public static final int		SERVICE_SIDEBAR_CLOSE  		= 34;
-	public static final int		SERVICE_ABOUT				= 35;
-	public static final int		SERVICE_IDENTIFY			= 36;	
-	public static final int		SERVICE_EXT_SITE_RELATIVE		= 37;	// String - relative URL
-
-		// content network properties
-	
-	public static final int		PROPERTY_SITE_HOST			= 1;	// String
-	public static final int		PROPERTY_REMOVEABLE			= 2;	// Boolean
-	public static final int		PROPERTY_ORDER				= 3;	// String (Tux prefers to Integer)
-
-		// persistent (and local) properties
-	
-	public static final String	PP_AUTH_PAGE_SHOWN			= "auth_shown";			// Boolean, default false
-	public static final String	PP_IS_CUSTOMIZATION			= "is_cust";			// Boolean, default false
-	public static final String	PP_ACTIVE			        = "active";				// Boolean
-	public static final String	PP_SHOW_IN_MENU       		= "in_menu";			// Boolean
-	public static final String	PP_SOURCE_REF				= "source_ref"; 		// String
-
-	
-		/**
-		 * Returns one of the above CONTENT_NETWORK constants
-		 * @return
-		 */
-	
-	public long
-	getID();
-	
-	public String
-	getName();
-	
-	public Object
-	getProperty(
-		int			property );
-	
-	public boolean
-	isStartupNetwork();
-	
-	public void
-	setStartupNetwork(
-		boolean		is_startup );
-	
-		/**
-		 * Test if the network supports a particular service
-		 * @param service_type
-		 * @return
-		 */
-	
-	public boolean
-	isServiceSupported(
-		int			service_type );
-	
-		/**
-		 * Returns the base URL of the service. If not parameterised then this is sufficient to
-		 * invoke the service
-		 * @param service_type
-		 * @return
-		 */
-	
-	public String
-	getServiceURL(
-		int			service_type );
-	
-		/**
-		 * Generic parameterised service method
-		 * @param service_type
-		 * @param params
-		 * @return
-		 */
-	
-	public String
-	getServiceURL(
-		int			service_type,
-		Object[]	params );
-	
-		/**
-		 * search service helper method
-		 * @param query
-		 * @return
-		 */
-	
-	public String
-	getSearchService(
-		String		query );
-	
-	
-	public String
-	getXSearchService(
-		String		query,
-		boolean		to_subscribe );
-	
-	public String
-	getContentDetailsService(
-		String		hash,
-		String		client_ref );
-	
-	public String
-	getCommentService(
-		String		hash );
-	
-	public String
-	getProfileService(
-		String		login_id,
-		String		client_ref );
-	
-	public String
-	getTorrentDownloadService(
-		String		hash,
-		String		client_ref );
-	
-		/**
-		 * @param topic The topic number or a pre-defined topic constant found in <code>FAQTopics</code>
-		 */
-
-	public String
-	getFAQTopicService(
-		String		topic );
-	
-	public String
-	getLoginService(
-		String		message );
-	
-	public String
-	getSiteRelativeURL(
-		String		relative_url,
-		boolean		append_suffix );
-	
-	public String
-	getExternalSiteRelativeURL(
-		String		relative_url,
-		boolean		append_suffix );
-	
-	public String
-	getAddFriendURL(
-		String		bg_colour );
-	
-	public String
-	getSubscriptionURL(
-		String		subs_id );
-	
-		/**
-		 * I'd rather this function we embedded into the ContentNetwork service getting logic, but for
-		 * the moment expose it for simplicity
-		 * @param url_in			base URL onto which the suffix should be appended
-		 * @param for_post			whether this is for an HTTP 'POST' operation, in which case the parameter
-		 * 							separator is always an '&' (for 'GET' the first param uses a '?' sep)
-		 * @param include_azid		whether or not we should include the azid in the suffix
-		 * @return
-		 */
-	public String
-	appendURLSuffix(
-		String		url_in,
-		boolean		for_post,
-		boolean		include_azid );
-	
-		/**
-		 * export to vuze file
-		 * @return
-		 */
-	
-	public VuzeFile
-	getVuzeFile();
-	
-		/**
-		 * Sets a locally persistent property. Name should be from the PP_ names above so keep track
-		 * of what attributes exist
-		 * 
-		 * @param name	PP_ constant
-		 * @param value	must be bencodable!
-		 */
-	
-	public void
-	setPersistentProperty(
-		String		name,
-		Object		value );
-	
-	public Object
-	getPersistentProperty(
-		String		name );
-	
-	public void
-	addPersistentPropertyChangeListener(
-		ContentNetworkPropertyChangeListener	listener );
-	
-	public void
-	removePersistentPropertyChangeListener(
-		ContentNetworkPropertyChangeListener	listener );
-	
-		/**
-		 * Set a non-persistent property of the content network
-		 * @param key
-		 * @param value
-		 */
-	
-	public void
-	setTransientProperty(
-		Object		key,
-		Object		value );
-	
-	public Object
-	getTransientProperty(
-		Object		key );
-	
-	public void
-	remove();
-}
+/*
+ * Created on Nov 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.cnetwork;
+
+import com.aelitis.azureus.core.vuzefile.VuzeFile;
+
+public interface 
+ContentNetwork 
+{
+	public static final long	CONTENT_NETWORK_UNKNOWN		= -1;
+	
+	public static final long	CONTENT_NETWORK_VUZE		= 1;
+	
+		/**
+		 * You should normally NOT refer explicitly to this constant without consideration
+		 * as we don't want network-specific code proliferating
+		 */
+	
+	public static final long	CONTENT_NETWORK_RFN			= 2;
+	
+	public static final long	CONTENT_NETWORK_VHDNL		= 3;
+
+
+	public static final int		SERVICE_SEARCH				= 1;	// String - query text
+	public static final int		SERVICE_XSEARCH				= 2;	// String - query text; Boolean - toSubscribe
+	public static final int		SERVICE_RPC					= 3;
+	public static final int		SERVICE_RELAY_RPC			= 4;
+	public static final int		SERVICE_AUTH_RPC			= 5;
+	public static final int		SERVICE_BIG_BROWSE			= 6;
+	public static final int		SERVICE_PUBLISH				= 7;
+	public static final int		SERVICE_WELCOME				= 8;
+	public static final int		SERVICE_PUBLISH_NEW			= 9;
+	public static final int		SERVICE_PUBLISH_ABOUT		= 10;
+	public static final int		SERVICE_CONTENT_DETAILS		= 11;	// String - hash; String (can be null) - client ref
+	public static final int		SERVICE_COMMENT				= 12;	// String - hash
+	public static final int		SERVICE_PROFILE				= 13;	// String - login_id; String - client ref
+	public static final int		SERVICE_TORRENT_DOWNLOAD	= 14;	// String - hash; String (can be null) - client ref
+	public static final int		SERVICE_SITE				= 15;
+	public static final int		SERVICE_SUPPORT				= 16;
+	public static final int		SERVICE_FAQ					= 17;
+	public static final int		SERVICE_FAQ_TOPIC			= 18;	// String - topic entry
+	public static final int		SERVICE_BLOG				= 19;
+	public static final int		SERVICE_FORUMS				= 20;
+	public static final int		SERVICE_WIKI				= 21;
+	public static final int		SERVICE_LOGIN				= 22;	// String - message (can be null)
+	public static final int		SERVICE_LOGOUT				= 23;
+	public static final int		SERVICE_REGISTER			= 24;
+	public static final int		SERVICE_MY_PROFILE			= 25;
+	public static final int		SERVICE_MY_ACCOUNT			= 26;
+	public static final int		SERVICE_SITE_RELATIVE		= 27;	// String - relative URL
+	public static final int		SERVICE_ADD_FRIEND			= 28;	// String - bg colour
+	public static final int		SERVICE_SUBSCRIPTION		= 29;	// String - subscription ID
+	public static final int		SERVICE_GET_ICON			= 30;	
+	public static final int		SERVICE_AUTHORIZE			= 31;	
+	public static final int		SERVICE_PREPLAYBACK  		= 32;
+	public static final int		SERVICE_POSTPLAYBACK  		= 33;
+	public static final int		SERVICE_SIDEBAR_CLOSE  		= 34;
+	public static final int		SERVICE_ABOUT				= 35;
+	public static final int		SERVICE_IDENTIFY			= 36;	
+	public static final int		SERVICE_EXT_SITE_RELATIVE		= 37;	// String - relative URL
+
+		// content network properties
+	
+	public static final int		PROPERTY_SITE_HOST			= 1;	// String
+	public static final int		PROPERTY_REMOVEABLE			= 2;	// Boolean
+	public static final int		PROPERTY_ORDER				= 3;	// String (Tux prefers to Integer)
+
+		// persistent (and local) properties
+	
+	public static final String	PP_AUTH_PAGE_SHOWN			= "auth_shown";			// Boolean, default false
+	public static final String	PP_IS_CUSTOMIZATION			= "is_cust";			// Boolean, default false
+	public static final String	PP_ACTIVE			        = "active";				// Boolean
+	public static final String	PP_SHOW_IN_MENU       		= "in_menu";			// Boolean
+	public static final String	PP_SOURCE_REF				= "source_ref"; 		// String
+
+	
+		/**
+		 * Returns one of the above CONTENT_NETWORK constants
+		 * @return
+		 */
+	
+	public long
+	getID();
+	
+	public String
+	getName();
+	
+	public Object
+	getProperty(
+		int			property );
+	
+	public boolean
+	isStartupNetwork();
+	
+	public void
+	setStartupNetwork(
+		boolean		is_startup );
+	
+		/**
+		 * Test if the network supports a particular service
+		 * @param service_type
+		 * @return
+		 */
+	
+	public boolean
+	isServiceSupported(
+		int			service_type );
+	
+		/**
+		 * Returns the base URL of the service. If not parameterised then this is sufficient to
+		 * invoke the service
+		 * @param service_type
+		 * @return
+		 */
+	
+	public String
+	getServiceURL(
+		int			service_type );
+	
+		/**
+		 * Generic parameterised service method
+		 * @param service_type
+		 * @param params
+		 * @return
+		 */
+	
+	public String
+	getServiceURL(
+		int			service_type,
+		Object[]	params );
+	
+		/**
+		 * search service helper method
+		 * @param query
+		 * @return
+		 */
+	
+	public String
+	getSearchService(
+		String		query );
+	
+	
+	public String
+	getXSearchService(
+		String		query,
+		boolean		to_subscribe );
+	
+	public String
+	getContentDetailsService(
+		String		hash,
+		String		client_ref );
+	
+	public String
+	getCommentService(
+		String		hash );
+	
+	public String
+	getProfileService(
+		String		login_id,
+		String		client_ref );
+	
+	public String
+	getTorrentDownloadService(
+		String		hash,
+		String		client_ref );
+	
+		/**
+		 * @param topic The topic number or a pre-defined topic constant found in <code>FAQTopics</code>
+		 */
+
+	public String
+	getFAQTopicService(
+		String		topic );
+	
+	public String
+	getLoginService(
+		String		message );
+	
+	public String
+	getSiteRelativeURL(
+		String		relative_url,
+		boolean		append_suffix );
+	
+	public String
+	getExternalSiteRelativeURL(
+		String		relative_url,
+		boolean		append_suffix );
+	
+	public String
+	getAddFriendURL(
+		String		bg_colour );
+	
+	public String
+	getSubscriptionURL(
+		String		subs_id );
+	
+		/**
+		 * I'd rather this function we embedded into the ContentNetwork service getting logic, but for
+		 * the moment expose it for simplicity
+		 * @param url_in			base URL onto which the suffix should be appended
+		 * @param for_post			whether this is for an HTTP 'POST' operation, in which case the parameter
+		 * 							separator is always an '&' (for 'GET' the first param uses a '?' sep)
+		 * @param include_azid		whether or not we should include the azid in the suffix
+		 * @return
+		 */
+	public String
+	appendURLSuffix(
+		String		url_in,
+		boolean		for_post,
+		boolean		include_azid );
+	
+		/**
+		 * export to vuze file
+		 * @return
+		 */
+	
+	public VuzeFile
+	getVuzeFile();
+	
+		/**
+		 * Sets a locally persistent property. Name should be from the PP_ names above so keep track
+		 * of what attributes exist
+		 * 
+		 * @param name	PP_ constant
+		 * @param value	must be bencodable!
+		 */
+	
+	public void
+	setPersistentProperty(
+		String		name,
+		Object		value );
+	
+	public Object
+	getPersistentProperty(
+		String		name );
+	
+	public void
+	addPersistentPropertyChangeListener(
+		ContentNetworkPropertyChangeListener	listener );
+	
+	public void
+	removePersistentPropertyChangeListener(
+		ContentNetworkPropertyChangeListener	listener );
+	
+		/**
+		 * Set a non-persistent property of the content network
+		 * @param key
+		 * @param value
+		 */
+	
+	public void
+	setTransientProperty(
+		Object		key,
+		Object		value );
+	
+	public Object
+	getTransientProperty(
+		Object		key );
+	
+	public void
+	remove();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkException.java b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkException.java
index 1afdda0..2177108 100644
--- a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkException.java
+++ b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkException.java
@@ -1,42 +1,41 @@
-/*
- * Created on Nov 26, 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.core.cnetwork;
-
-public class 
-ContentNetworkException 
-	extends Exception
-{
-	public 
-	ContentNetworkException(
-		String			str )
-	{
-		super( str );
-	}
-
-	public 
-	ContentNetworkException(
-		String			str,
-		Throwable 		cause )
-	{
-		super( str, cause );
-	}
-}
+/*
+ * Created on Nov 26, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.cnetwork;
+
+public class 
+ContentNetworkException 
+	extends Exception
+{
+	public 
+	ContentNetworkException(
+		String			str )
+	{
+		super( str );
+	}
+
+	public 
+	ContentNetworkException(
+		String			str,
+		Throwable 		cause )
+	{
+		super( str, cause );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkListener.java b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkListener.java
index 07b6e3a..53bc993 100644
--- a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkListener.java
@@ -1,43 +1,42 @@
-/*
- * Created on Nov 21, 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.core.cnetwork;
-
-public interface 
-ContentNetworkListener 
-{
-	public void
-	networkAdded(
-		ContentNetwork	network );
-
-	public void
-	networkAddFailed(
-		long network_id,
-		Throwable error );
-
-	public void
-	networkChanged(
-		ContentNetwork	network );
-
-	public void
-	networkRemoved(
-		ContentNetwork	network );
-}
+/*
+ * Created on Nov 21, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.cnetwork;
+
+public interface 
+ContentNetworkListener 
+{
+	public void
+	networkAdded(
+		ContentNetwork	network );
+
+	public void
+	networkAddFailed(
+		long network_id,
+		Throwable error );
+
+	public void
+	networkChanged(
+		ContentNetwork	network );
+
+	public void
+	networkRemoved(
+		ContentNetwork	network );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkManager.java b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkManager.java
index e1175b6..e20ff9e 100644
--- a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkManager.java
@@ -1,64 +1,63 @@
-/*
- * Created on Nov 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 com.aelitis.azureus.core.cnetwork;
-
-public interface 
-ContentNetworkManager 
-{
-	public ContentNetwork[]
-	getContentNetworks();
-	
-	public ContentNetwork
-	getContentNetwork(
-		long			id );
-
-	public ContentNetwork
-	getStartupContentNetwork();
-
-		/**
-		 * Checks networks for those that have this URL as their site
-		 * @return matching network, null if none
-		 */
-	
-	public ContentNetwork
-	getContentNetworkForURL(
-		String		url );
-
-	/**
-	 * {@link ContentNetworkListener#networkAdded(ContentNetwork)} will be called
-	 * once the network is added
-	 */
-	public void
-	addContentNetwork(
-		long			id )
-	
-		throws ContentNetworkException;
-	
-	public void
-	addListener(
-		ContentNetworkListener		listener );
-	
-	public void
-	removeListener(
-		ContentNetworkListener		listener );
-
-}
+/*
+ * Created on Nov 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.cnetwork;
+
+public interface 
+ContentNetworkManager 
+{
+	public ContentNetwork[]
+	getContentNetworks();
+	
+	public ContentNetwork
+	getContentNetwork(
+		long			id );
+
+	public ContentNetwork
+	getStartupContentNetwork();
+
+		/**
+		 * Checks networks for those that have this URL as their site
+		 * @return matching network, null if none
+		 */
+	
+	public ContentNetwork
+	getContentNetworkForURL(
+		String		url );
+
+	/**
+	 * {@link ContentNetworkListener#networkAdded(ContentNetwork)} will be called
+	 * once the network is added
+	 */
+	public void
+	addContentNetwork(
+		long			id )
+	
+		throws ContentNetworkException;
+	
+	public void
+	addListener(
+		ContentNetworkListener		listener );
+	
+	public void
+	removeListener(
+		ContentNetworkListener		listener );
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkManagerFactory.java b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkManagerFactory.java
index acbd8b1..99ba2f9 100644
--- a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkManagerFactory.java
+++ b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkManagerFactory.java
@@ -1,40 +1,39 @@
-/*
- * Created on Nov 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 com.aelitis.azureus.core.cnetwork;
-
-import com.aelitis.azureus.core.cnetwork.impl.ContentNetworkManagerImpl;
-
-public class 
-ContentNetworkManagerFactory 
-{
-	public static void
-	preInitialise()
-	{
-		ContentNetworkManagerImpl.preInitialise();
-	}
-	
-	public static ContentNetworkManager
-	getSingleton()
-	{
-		return( ContentNetworkManagerImpl.getSingleton());
-	}
-}
+/*
+ * Created on Nov 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.cnetwork;
+
+import com.aelitis.azureus.core.cnetwork.impl.ContentNetworkManagerImpl;
+
+public class 
+ContentNetworkManagerFactory 
+{
+	public static void
+	preInitialise()
+	{
+		ContentNetworkManagerImpl.preInitialise();
+	}
+	
+	public static ContentNetworkManager
+	getSingleton()
+	{
+		return( ContentNetworkManagerImpl.getSingleton());
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkPropertyChangeListener.java b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkPropertyChangeListener.java
index 6e087fb..38f8979 100644
--- a/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkPropertyChangeListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/cnetwork/ContentNetworkPropertyChangeListener.java
@@ -1,30 +1,29 @@
-/*
- * Created on Dec 9, 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.core.cnetwork;
-
-public interface 
-ContentNetworkPropertyChangeListener 
-{
-	public void
-	propertyChanged(
-		String		name );
-}
+/*
+ * Created on Dec 9, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.cnetwork;
+
+public interface 
+ContentNetworkPropertyChangeListener 
+{
+	public void
+	propertyChanged(
+		String		name );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkImpl.java b/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkImpl.java
index 78237b9..e870b97 100644
--- a/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkImpl.java
@@ -1,482 +1,481 @@
-/*
- * Created on Nov 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 com.aelitis.azureus.core.cnetwork.impl;
-
-import java.io.IOException;
-import java.util.*;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.util.BEncoder;
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.cnetwork.*;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-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.util.ImportExportUtils;
-import com.aelitis.azureus.util.MapUtils;
-
-public abstract class 
-ContentNetworkImpl
-	implements ContentNetwork
-{
-	protected static final long	TYPE_VUZE_GENERIC		= 1;
-	
-	private static final String	PP_STARTUP_NETWORK		= "startup_network"; 	// Boolean
-
-	protected static ContentNetworkImpl
-	importFromBEncodedMapStatic(
-		ContentNetworkManagerImpl	manager,
-		Map							map )
-	
-		throws IOException
-	{
-		long type	= ImportExportUtils.importLong( map, "type" );
-		
-		if ( type == TYPE_VUZE_GENERIC ){
-			
-			return( new ContentNetworkVuzeGeneric( manager, map ));
-			
-		}else{
-		
-			throw( new IOException( "Unsupported network type: " + type ));
-		}
-	}
-	
-	private ContentNetworkManagerImpl	manager;
-	private long						type;
-	private long						version;
-	private long						id;
-	private String						name;
-	
-	private Map<String,Object>	pprop_defaults;
-	
-	private Map<Object,Object>	transient_properties = Collections.synchronizedMap( new HashMap<Object,Object>());
-	
-	private CopyOnWriteList		persistent_listeners = new CopyOnWriteList();
-	
-	protected
-	ContentNetworkImpl(
-		ContentNetworkManagerImpl	_manager,
-		long						_type,
-		long						_id,
-		long						_version,
-		String						_name,
-		Map<String,Object>			_pprop_defaults )
-	{
-		manager		= _manager;
-		type		= _type;
-		version		= _version;
-		id			= _id;
-		name		= _name;
-		
-		pprop_defaults	= _pprop_defaults;
-	}
-	
-	protected
-	ContentNetworkImpl(
-		ContentNetworkManagerImpl	_manager )
-	{
-		manager	= _manager;
-	}
-	
-	protected void
-	importFromBEncodedMap(
-		Map<String,Object>		map )
-	
-		throws IOException
-	{
-		type	= ImportExportUtils.importLong( map, "type" );
-		id		= ImportExportUtils.importLong( map, "id" );
-		version	= ImportExportUtils.importLong( map, "version" );
-		name 	= ImportExportUtils.importString( map, "name" );
-
-		pprop_defaults = (Map<String,Object>)map.get( "pprop_defaults" );
-	}
-	
-	protected void
-	exportToBEncodedMap(
-		Map<String,Object>			map )
-	
-		throws IOException
-	{
-		ImportExportUtils.exportLong( map, "type", type );
-		ImportExportUtils.exportLong( map, "id", id );
-		ImportExportUtils.exportLong( map, "version", version );
-		ImportExportUtils.exportString( map, "name", name );
-		
-		if ( pprop_defaults != null ){
-			
-			map.put( "pprop_defaults", pprop_defaults );
-		}
-	}
-	
-	protected void
-	updateFrom(
-		ContentNetworkImpl	other )
-	
-		throws IOException
-	{
-		Map<String,Object>	map = new HashMap<String,Object>();
-		
-		other.exportToBEncodedMap(map);
-		
-		importFromBEncodedMap( map );
-	}
-	
-	public long 
-	getID() 
-	{
-		return( id );
-	}
-	
-	protected long
-	getVersion()
-	{
-		return( version );
-	}
-	
-	public String
-	getName()
-	{
-		return( name );
-	}
-	
-	protected boolean
-	isSameAs(
-		ContentNetworkImpl		other )
-	{
-		try{
-			Map<String,Object>	map1 = new HashMap<String,Object>();
-			Map<String,Object>  map2 = new HashMap<String,Object>();
-			
-			exportToBEncodedMap( map1 );
-			
-			other.exportToBEncodedMap( map2 );
-			
-			return( BEncoder.mapsAreIdentical( map1, map2 ));
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			return( false );
-		}
-	}
-		
-	public String
-	getSearchService(
-		String		query )
-	{
-		return( getServiceURL( SERVICE_SEARCH, new Object[]{ query } ));
-	}
-	
-	public String
-	getXSearchService(
-		String		query,
-		boolean		to_subscribe )
-	{
-		return( getServiceURL( SERVICE_XSEARCH, new Object[]{ query, to_subscribe } ));
-	}
-	
-	public String 
-	getContentDetailsService(
-		String 		hash, 
-		String 		client_ref ) 
-	{
-		return( getServiceURL( SERVICE_CONTENT_DETAILS, new Object[]{ hash, client_ref }));
-	}
-	
-	public String 
-	getCommentService(
-		String hash )
-	{
-		return( getServiceURL( SERVICE_COMMENT, new Object[]{ hash }));
-	}
-	
-	public String 
-	getProfileService(
-		String 		login_id, 
-		String 		client_ref ) 
-	{
-		return( getServiceURL( SERVICE_PROFILE, new Object[]{ login_id, client_ref }));
-	}
-	
-	public String 
-	getTorrentDownloadService(
-		String 		hash, 
-		String 		client_ref ) 
-	{
-		return( getServiceURL( SERVICE_TORRENT_DOWNLOAD, new Object[]{ hash, client_ref }));
-	}
-	
-	public String 
-	getFAQTopicService(
-		String topic )
-	{
-		return( getServiceURL( SERVICE_FAQ_TOPIC, new Object[]{ topic }));
-	}
-	
-	public String 
-	getLoginService(
-		String 	message )
-	{
-		return( getServiceURL( SERVICE_LOGIN, new Object[]{ message }));
-	}
-	
-	public String 
-	getSiteRelativeURL(
-		String 		relative_url,
-		boolean		append_suffix )
-	{
-		return( getServiceURL( SERVICE_SITE_RELATIVE, new Object[]{ relative_url, append_suffix }));
-	}
-	
-	public String 
-	getExternalSiteRelativeURL(
-		String 		relative_url,
-		boolean		append_suffix )
-	{
-		return( getServiceURL( SERVICE_EXT_SITE_RELATIVE, new Object[]{ relative_url, append_suffix }));
-	}
-	
-	public String 
-	getAddFriendURL(
-		String 	colour )
-	{
-		return( getServiceURL( SERVICE_ADD_FRIEND, new Object[]{ colour }));
-	}
-	
-	public String 
-	getSubscriptionURL(
-		String 	subs_id )
-	{
-		return( getServiceURL( SERVICE_SUBSCRIPTION, new Object[]{ subs_id }));
-	}
-	
-	public VuzeFile
-	getVuzeFile()
-	{
-		VuzeFile	vf = VuzeFileHandler.getSingleton().create();
-		
-		Map	map = new HashMap();
-		
-		try{
-			exportToBEncodedMap( map );
-		
-			vf.addComponent( VuzeFileComponent.COMP_TYPE_CONTENT_NETWORK, map );
-			
-		}catch( Throwable e ){
-			
-			Debug.printStackTrace( e );
-		}
-		
-		return( vf );
-	}
-	
-	public boolean
-	isStartupNetwork()
-	{
-		if ( hasPersistentProperty( PP_STARTUP_NETWORK )){
-			
-			return((Boolean)getPersistentProperty( PP_STARTUP_NETWORK ));
-		}
-		
-		return((Boolean)getPersistentProperty( ContentNetwork.PP_IS_CUSTOMIZATION ));
-	}
-	
-	public void
-	setStartupNetwork(
-		boolean		b )
-	{
-		setPersistentProperty( PP_STARTUP_NETWORK, new Boolean(b));
-	}
-	
-	public void
-	setTransientProperty(
-		Object		key,
-		Object		value )
-	{
-		transient_properties.put( key, value );
-	}
-	
-	public Object
-	getTransientProperty(
-		Object		key )
-	{
-		return( transient_properties.get( key ));
-	}
-	
-	protected String
-	getPropertiesKey()
-	{
-		return( "cnetwork.net." + id + ".props" );
-	}
-	
-	public void
-	setPersistentProperty(
-		String		name,
-		Object		new_value )
-	{
-		synchronized( this ){
-			
-			String	key = getPropertiesKey();
-			
-			if ( new_value instanceof Boolean ){
-				
-				new_value = new Long(((Boolean)new_value)?1:0);
-			}
-			
-			Map props = new HashMap( COConfigurationManager.getMapParameter( key , new HashMap()));
-			
-			Object old_value = props.get( key );
-			
-			if ( BEncoder.objectsAreIdentical( old_value, new_value )){
-					
-				return;
-			}
-			
-			props.put( name, new_value );
-			
-			COConfigurationManager.setParameter( key, props );
-		}
-		
-		Iterator it = persistent_listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				
-				((ContentNetworkPropertyChangeListener)it.next()).propertyChanged(name);
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-	}
-	
-	public Object
-	getPersistentProperty(
-		String		name )
-	{
-		synchronized( this ){
-			
-			String	key = getPropertiesKey();
-			
-			Map props = COConfigurationManager.getMapParameter( key , new HashMap());
-	
-			if ( name == PP_SOURCE_REF ) {
-
-				return MapUtils.getMapString(props, name, MapUtils.getMapString(
-						pprop_defaults, name, null));
-			}
-
-			Object obj = props.get( name );
-			
-			if ( 	name == PP_AUTH_PAGE_SHOWN 	||
-					name == PP_IS_CUSTOMIZATION ||
-					name == PP_ACTIVE			||
-					name == PP_SHOW_IN_MENU		||
-					name == PP_STARTUP_NETWORK ){
-				
-				if ( obj == null && pprop_defaults != null ){
-					
-					obj = pprop_defaults.get( name );
-				}
-				
-				if ( obj == null ){
-					
-					return( false );
-					
-				}else{
-					
-					return(((Long)obj)==1);
-				}
-			}
-			
-			return( obj );
-		}
-	}
-	
-	protected boolean
-	hasPersistentProperty(
-		String		name )
-	{
-		synchronized( this ){
-			
-			String	key = getPropertiesKey();
-			
-			Map props = COConfigurationManager.getMapParameter( key , new HashMap());
-	
-			return( props.containsKey( name ));
-		}
-	}
-	
-	protected Map<String,Object>
-	getPersistentPropertyDefaults()
-	{
-		return( pprop_defaults );
-	}
-	
-	public void
-	addPersistentPropertyChangeListener(
-		ContentNetworkPropertyChangeListener	listener )
-	{
-		persistent_listeners.add( listener );
-	}
-	
-	public void
-	removePersistentPropertyChangeListener(
-		ContentNetworkPropertyChangeListener	listener )
-	{
-		persistent_listeners.remove( listener );
-	}
-	
-	protected void
-	destroy()
-	{
-		String	key = getPropertiesKey();
-
-		COConfigurationManager.setParameter( key, new HashMap());
-	}
-	
-	public void
-	remove()
-	{
-		manager.removeNetwork( this );
-	}
-	
-	protected void
-	debug(
-		String		str )
-	{
-		Debug.out( getString() + ": " + str );
-	}
-	
-	protected String
-	getString()
-	{
-		return( getID() + " - " + getName() + ": version=" + getVersion() + ", site=" + getProperty( PROPERTY_SITE_HOST ));
-	}
-}
+/*
+ * Created on Nov 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.cnetwork.impl;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.util.BEncoder;
+import org.gudy.azureus2.core3.util.Debug;
+
+import com.aelitis.azureus.core.cnetwork.*;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+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.util.ImportExportUtils;
+import com.aelitis.azureus.util.MapUtils;
+
+public abstract class 
+ContentNetworkImpl
+	implements ContentNetwork
+{
+	protected static final long	TYPE_VUZE_GENERIC		= 1;
+	
+	private static final String	PP_STARTUP_NETWORK		= "startup_network"; 	// Boolean
+
+	protected static ContentNetworkImpl
+	importFromBEncodedMapStatic(
+		ContentNetworkManagerImpl	manager,
+		Map							map )
+	
+		throws IOException
+	{
+		long type	= ImportExportUtils.importLong( map, "type" );
+		
+		if ( type == TYPE_VUZE_GENERIC ){
+			
+			return( new ContentNetworkVuzeGeneric( manager, map ));
+			
+		}else{
+		
+			throw( new IOException( "Unsupported network type: " + type ));
+		}
+	}
+	
+	private ContentNetworkManagerImpl	manager;
+	private long						type;
+	private long						version;
+	private long						id;
+	private String						name;
+	
+	private Map<String,Object>	pprop_defaults;
+	
+	private Map<Object,Object>	transient_properties = Collections.synchronizedMap( new HashMap<Object,Object>());
+	
+	private CopyOnWriteList		persistent_listeners = new CopyOnWriteList();
+	
+	protected
+	ContentNetworkImpl(
+		ContentNetworkManagerImpl	_manager,
+		long						_type,
+		long						_id,
+		long						_version,
+		String						_name,
+		Map<String,Object>			_pprop_defaults )
+	{
+		manager		= _manager;
+		type		= _type;
+		version		= _version;
+		id			= _id;
+		name		= _name;
+		
+		pprop_defaults	= _pprop_defaults;
+	}
+	
+	protected
+	ContentNetworkImpl(
+		ContentNetworkManagerImpl	_manager )
+	{
+		manager	= _manager;
+	}
+	
+	protected void
+	importFromBEncodedMap(
+		Map<String,Object>		map )
+	
+		throws IOException
+	{
+		type	= ImportExportUtils.importLong( map, "type" );
+		id		= ImportExportUtils.importLong( map, "id" );
+		version	= ImportExportUtils.importLong( map, "version" );
+		name 	= ImportExportUtils.importString( map, "name" );
+
+		pprop_defaults = (Map<String,Object>)map.get( "pprop_defaults" );
+	}
+	
+	protected void
+	exportToBEncodedMap(
+		Map<String,Object>			map )
+	
+		throws IOException
+	{
+		ImportExportUtils.exportLong( map, "type", type );
+		ImportExportUtils.exportLong( map, "id", id );
+		ImportExportUtils.exportLong( map, "version", version );
+		ImportExportUtils.exportString( map, "name", name );
+		
+		if ( pprop_defaults != null ){
+			
+			map.put( "pprop_defaults", pprop_defaults );
+		}
+	}
+	
+	protected void
+	updateFrom(
+		ContentNetworkImpl	other )
+	
+		throws IOException
+	{
+		Map<String,Object>	map = new HashMap<String,Object>();
+		
+		other.exportToBEncodedMap(map);
+		
+		importFromBEncodedMap( map );
+	}
+	
+	public long 
+	getID() 
+	{
+		return( id );
+	}
+	
+	protected long
+	getVersion()
+	{
+		return( version );
+	}
+	
+	public String
+	getName()
+	{
+		return( name );
+	}
+	
+	protected boolean
+	isSameAs(
+		ContentNetworkImpl		other )
+	{
+		try{
+			Map<String,Object>	map1 = new HashMap<String,Object>();
+			Map<String,Object>  map2 = new HashMap<String,Object>();
+			
+			exportToBEncodedMap( map1 );
+			
+			other.exportToBEncodedMap( map2 );
+			
+			return( BEncoder.mapsAreIdentical( map1, map2 ));
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( false );
+		}
+	}
+		
+	public String
+	getSearchService(
+		String		query )
+	{
+		return( getServiceURL( SERVICE_SEARCH, new Object[]{ query } ));
+	}
+	
+	public String
+	getXSearchService(
+		String		query,
+		boolean		to_subscribe )
+	{
+		return( getServiceURL( SERVICE_XSEARCH, new Object[]{ query, to_subscribe } ));
+	}
+	
+	public String 
+	getContentDetailsService(
+		String 		hash, 
+		String 		client_ref ) 
+	{
+		return( getServiceURL( SERVICE_CONTENT_DETAILS, new Object[]{ hash, client_ref }));
+	}
+	
+	public String 
+	getCommentService(
+		String hash )
+	{
+		return( getServiceURL( SERVICE_COMMENT, new Object[]{ hash }));
+	}
+	
+	public String 
+	getProfileService(
+		String 		login_id, 
+		String 		client_ref ) 
+	{
+		return( getServiceURL( SERVICE_PROFILE, new Object[]{ login_id, client_ref }));
+	}
+	
+	public String 
+	getTorrentDownloadService(
+		String 		hash, 
+		String 		client_ref ) 
+	{
+		return( getServiceURL( SERVICE_TORRENT_DOWNLOAD, new Object[]{ hash, client_ref }));
+	}
+	
+	public String 
+	getFAQTopicService(
+		String topic )
+	{
+		return( getServiceURL( SERVICE_FAQ_TOPIC, new Object[]{ topic }));
+	}
+	
+	public String 
+	getLoginService(
+		String 	message )
+	{
+		return( getServiceURL( SERVICE_LOGIN, new Object[]{ message }));
+	}
+	
+	public String 
+	getSiteRelativeURL(
+		String 		relative_url,
+		boolean		append_suffix )
+	{
+		return( getServiceURL( SERVICE_SITE_RELATIVE, new Object[]{ relative_url, append_suffix }));
+	}
+	
+	public String 
+	getExternalSiteRelativeURL(
+		String 		relative_url,
+		boolean		append_suffix )
+	{
+		return( getServiceURL( SERVICE_EXT_SITE_RELATIVE, new Object[]{ relative_url, append_suffix }));
+	}
+	
+	public String 
+	getAddFriendURL(
+		String 	colour )
+	{
+		return( getServiceURL( SERVICE_ADD_FRIEND, new Object[]{ colour }));
+	}
+	
+	public String 
+	getSubscriptionURL(
+		String 	subs_id )
+	{
+		return( getServiceURL( SERVICE_SUBSCRIPTION, new Object[]{ subs_id }));
+	}
+	
+	public VuzeFile
+	getVuzeFile()
+	{
+		VuzeFile	vf = VuzeFileHandler.getSingleton().create();
+		
+		Map	map = new HashMap();
+		
+		try{
+			exportToBEncodedMap( map );
+		
+			vf.addComponent( VuzeFileComponent.COMP_TYPE_CONTENT_NETWORK, map );
+			
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace( e );
+		}
+		
+		return( vf );
+	}
+	
+	public boolean
+	isStartupNetwork()
+	{
+		if ( hasPersistentProperty( PP_STARTUP_NETWORK )){
+			
+			return((Boolean)getPersistentProperty( PP_STARTUP_NETWORK ));
+		}
+		
+		return((Boolean)getPersistentProperty( ContentNetwork.PP_IS_CUSTOMIZATION ));
+	}
+	
+	public void
+	setStartupNetwork(
+		boolean		b )
+	{
+		setPersistentProperty( PP_STARTUP_NETWORK, new Boolean(b));
+	}
+	
+	public void
+	setTransientProperty(
+		Object		key,
+		Object		value )
+	{
+		transient_properties.put( key, value );
+	}
+	
+	public Object
+	getTransientProperty(
+		Object		key )
+	{
+		return( transient_properties.get( key ));
+	}
+	
+	protected String
+	getPropertiesKey()
+	{
+		return( "cnetwork.net." + id + ".props" );
+	}
+	
+	public void
+	setPersistentProperty(
+		String		name,
+		Object		new_value )
+	{
+		synchronized( this ){
+			
+			String	key = getPropertiesKey();
+			
+			if ( new_value instanceof Boolean ){
+				
+				new_value = new Long(((Boolean)new_value)?1:0);
+			}
+			
+			Map props = new HashMap( COConfigurationManager.getMapParameter( key , new HashMap()));
+			
+			Object old_value = props.get( key );
+			
+			if ( BEncoder.objectsAreIdentical( old_value, new_value )){
+					
+				return;
+			}
+			
+			props.put( name, new_value );
+			
+			COConfigurationManager.setParameter( key, props );
+		}
+		
+		Iterator it = persistent_listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				
+				((ContentNetworkPropertyChangeListener)it.next()).propertyChanged(name);
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+	}
+	
+	public Object
+	getPersistentProperty(
+		String		name )
+	{
+		synchronized( this ){
+			
+			String	key = getPropertiesKey();
+			
+			Map props = COConfigurationManager.getMapParameter( key , new HashMap());
+	
+			if ( name == PP_SOURCE_REF ) {
+
+				return MapUtils.getMapString(props, name, MapUtils.getMapString(
+						pprop_defaults, name, null));
+			}
+
+			Object obj = props.get( name );
+			
+			if ( 	name == PP_AUTH_PAGE_SHOWN 	||
+					name == PP_IS_CUSTOMIZATION ||
+					name == PP_ACTIVE			||
+					name == PP_SHOW_IN_MENU		||
+					name == PP_STARTUP_NETWORK ){
+				
+				if ( obj == null && pprop_defaults != null ){
+					
+					obj = pprop_defaults.get( name );
+				}
+				
+				if ( obj == null ){
+					
+					return( false );
+					
+				}else{
+					
+					return(((Long)obj)==1);
+				}
+			}
+			
+			return( obj );
+		}
+	}
+	
+	protected boolean
+	hasPersistentProperty(
+		String		name )
+	{
+		synchronized( this ){
+			
+			String	key = getPropertiesKey();
+			
+			Map props = COConfigurationManager.getMapParameter( key , new HashMap());
+	
+			return( props.containsKey( name ));
+		}
+	}
+	
+	protected Map<String,Object>
+	getPersistentPropertyDefaults()
+	{
+		return( pprop_defaults );
+	}
+	
+	public void
+	addPersistentPropertyChangeListener(
+		ContentNetworkPropertyChangeListener	listener )
+	{
+		persistent_listeners.add( listener );
+	}
+	
+	public void
+	removePersistentPropertyChangeListener(
+		ContentNetworkPropertyChangeListener	listener )
+	{
+		persistent_listeners.remove( listener );
+	}
+	
+	protected void
+	destroy()
+	{
+		String	key = getPropertiesKey();
+
+		COConfigurationManager.setParameter( key, new HashMap());
+	}
+	
+	public void
+	remove()
+	{
+		manager.removeNetwork( this );
+	}
+	
+	protected void
+	debug(
+		String		str )
+	{
+		Debug.out( getString() + ": " + str );
+	}
+	
+	protected String
+	getString()
+	{
+		return( getID() + " - " + getName() + ": version=" + getVersion() + ", site=" + getProperty( PROPERTY_SITE_HOST ));
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkManagerImpl.java b/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkManagerImpl.java
index c2f0051..3b6e52c 100644
--- a/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkManagerImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkManagerImpl.java
@@ -1,567 +1,566 @@
-/*
- * Created on Nov 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 com.aelitis.azureus.core.cnetwork.impl;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.*;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.util.AEDiagnostics;
-import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator;
-import org.gudy.azureus2.core3.util.AEDiagnosticsLogger;
-import org.gudy.azureus2.core3.util.AEThread2;
-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.IndentWriter;
-import org.gudy.azureus2.core3.util.SimpleTimer;
-import org.gudy.azureus2.core3.util.TimerEvent;
-import org.gudy.azureus2.core3.util.TimerEventPerformer;
-
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.cnetwork.ContentNetworkException;
-import com.aelitis.azureus.core.cnetwork.ContentNetworkListener;
-import com.aelitis.azureus.core.cnetwork.ContentNetworkManager;
-import com.aelitis.azureus.core.custom.Customization;
-import com.aelitis.azureus.core.custom.CustomizationManager;
-import com.aelitis.azureus.core.custom.CustomizationManagerFactory;
-
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-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;
-
-public class 
-ContentNetworkManagerImpl 
-	implements ContentNetworkManager, AEDiagnosticsEvidenceGenerator
-{
-	private static final boolean LOAD_ALL_NETWORKS	= true;
-	
-	private static final String CONFIG_FILE		= "cnetworks.config";
-	
-	private static ContentNetworkManagerImpl singleton = new ContentNetworkManagerImpl();
-		
-
-	public static void
-	preInitialise()
-	{
-		VuzeFileHandler.getSingleton().addProcessor(
-			new VuzeFileProcessor()
-			{
-				public void
-				process(
-					VuzeFile[]		files,
-					int				expected_types )
-				{
-					for (int i=0;i<files.length;i++){
-						
-						VuzeFile	vf = files[i];
-						
-						VuzeFileComponent[] comps = vf.getComponents();
-						
-						for (int j=0;j<comps.length;j++){
-							
-							VuzeFileComponent comp = comps[j];
-							
-							if ( comp.getType() == VuzeFileComponent.COMP_TYPE_CONTENT_NETWORK ){
-								
-								try{								
-									((ContentNetworkManagerImpl)getSingleton()).importNetwork( comp.getContent());
-								
-									comp.setProcessed();
-									
-								}catch( Throwable e ){
-									
-									log( "Failed to import from vuze file", e );
-							
-									Debug.out( e );
-								}
-							}
-						}
-					}
-				}
-			});		
-	}
-	
-	public static ContentNetworkManager
-	getSingleton()
-	{
-		return( singleton );
-	}
-	
-	private List<ContentNetworkImpl>	networks = new ArrayList<ContentNetworkImpl>();
-	
-	private CopyOnWriteList<ContentNetworkListener>	listeners = new CopyOnWriteList<ContentNetworkListener>();
-	
-	protected
-	ContentNetworkManagerImpl()
-	{
-		loadConfig();
-		
-		addNetwork( new ContentNetworkVuze( this ));
-		
-		AEDiagnostics.addEvidenceGenerator( this );
-		
-		CustomizationManager cust_man = CustomizationManagerFactory.getSingleton();
-		
-		Customization cust = cust_man.getActiveCustomization();
-		
-		if ( cust != null ){
-			
-			String cust_name 	= COConfigurationManager.getStringParameter( "cnetworks.custom.name", "" );
-			String cust_version = COConfigurationManager.getStringParameter( "cnetworks.custom.version", "0" );
-			
-			boolean	new_name 	= !cust_name.equals( cust.getName());
-			boolean	new_version = Constants.compareVersions( cust_version, cust.getVersion() ) < 0;
-			
-			if ( new_name || new_version ){
-				
-				try{
-					InputStream[] streams = cust.getResources( Customization.RT_CNETWORKS );
-					
-					for (int i=0;i<streams.length;i++){
-						
-						InputStream is = streams[i];
-						
-						try{
-							VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile(is);
-							
-							if ( vf != null ){
-								
-								VuzeFileComponent[] comps = vf.getComponents();
-								
-								for (int j=0;j<comps.length;j++){
-									
-									VuzeFileComponent comp = comps[j];
-									
-									int type = comp.getType();
-									
-									if ( type == VuzeFileComponent.COMP_TYPE_CONTENT_NETWORK ){
-										
-										try{
-												// change here as we always add all networks upfront so
-												// we always set the customisation flag regardless of
-												// whether existing or not
-											
-											ContentNetwork imported = importNetwork( comp.getContent());
-											
-											imported.setPersistentProperty( ContentNetwork.PP_IS_CUSTOMIZATION, true );
-											
-											comp.setProcessed();
-											
-										}catch( Throwable e ){
-											
-											log( "Failed to import customisation network", e );
-										}
-									}
-								}
-							}
-						}finally{
-							
-							try{
-								is.close();
-								
-							}catch( Throwable e ){
-							}
-						}
-					}
-				}finally{
-					
-					COConfigurationManager.setParameter( "cnetworks.custom.name", cust.getName());
-					COConfigurationManager.setParameter( "cnetworks.custom.version", cust.getVersion());
-				}
-			}
-		}
-		
-		
-		SimpleTimer.addPeriodicEvent(
-				"MetaSearchRefresh",
-				23*60*60*1000,
-				new TimerEventPerformer()
-				{
-					public void 
-					perform(
-						TimerEvent 	event ) 
-					{
-						checkForUpdates();
-					}
-				});
-		
-		if ( networks.size() > 1 || LOAD_ALL_NETWORKS ){
-			
-			new AEThread2( "CNetwork:init",	true )
-			{
-				public void
-				run()
-				{
-					checkForUpdates();
-				}
-			}.start();
-		}
-	}
-	
-	protected void
-	checkForUpdates()
-	{
-	}
-	
-	protected ContentNetworkImpl
-	importNetwork(
-		Map		content )
-	
-		throws IOException
-	{
-		ContentNetworkImpl network = ContentNetworkImpl.importFromBEncodedMapStatic( this, content );
-		
-		return( addNetwork( network ));
-	}
-	
-	// @see com.aelitis.azureus.core.cnetwork.ContentNetworkManager#addContentNetwork(long)
-	public void 
-	addContentNetwork(
-		final long 	id ) 
-	
-		throws ContentNetworkException
-	{
-	}
-	
-	public ContentNetwork
-	getContentNetworkForURL(
-		String		url )
-	{
-		try{
-			String	host = new URL( url ).getHost();
-			
-			for ( ContentNetwork cn: getContentNetworks()){
-				
-				String	site = (String)cn.getProperty( ContentNetwork.PROPERTY_SITE_HOST );
-				
-				if ( site != null && site.endsWith( host )){
-					
-					return( cn );
-				}
-			}
-		}catch( Throwable e ){
-			
-			Debug.printStackTrace(e);
-		}
-		
-		return( null );
-	}
-	
-	public ContentNetwork
-	getStartupContentNetwork()
-	{
-		ContentNetwork[] networks = getContentNetworks();
-		
-		for ( ContentNetwork network: networks ){
-			
-			if ( network.isStartupNetwork()){
-				
-				return( network );
-			}
-		}
-		
-		return( getContentNetwork( ContentNetwork.CONTENT_NETWORK_VUZE ));
-	}
-	
-	public ContentNetwork[] 
-	getContentNetworks() 
-	{
-		synchronized( this ){
-			
-			return((ContentNetwork[])networks.toArray( new ContentNetworkImpl[ networks.size()] ));
-		}
-	}
-	
-	public ContentNetworkImpl 
-	getContentNetwork(
-		long id ) 
-	{
-		synchronized( this ){
-			
-			for ( int i=0;i<networks.size();i++ ){
-					
-				ContentNetworkImpl network = networks.get(i);
-				
-				if ( network.getID() == id ){
-				
-					return( network );
-				}
-			}
-			
-			return( null );
-		}
-	}
-	
-	protected ContentNetworkImpl
-	addNetwork(
-		ContentNetworkImpl		network )
-	{
-		boolean	replace = false;
-		
-		synchronized( this ){
-		
-			Iterator<ContentNetworkImpl> it = networks.iterator();
-			
-			while( it.hasNext()){
-				
-				ContentNetworkImpl existing_network = it.next();
-				
-				if ( existing_network.getID() == network.getID()){
-					
-					if ( network.getVersion() > existing_network.getVersion()){
-						
-						try{
-							existing_network.updateFrom( network );
-						
-						}catch( Throwable e ){
-							
-							Debug.printStackTrace( e );
-						}
-						
-						network = existing_network;
-						
-						replace = true;
-						
-						break;
-						
-					}else{
-						
-						log( "Network " + existing_network.getString() + " already up to date" );
-						
-						return( existing_network );
-					}
-				}
-			}
-
-			if ( replace ){
-			
-				log( "Updated network: " + network.getString());
-				
-			}else{
-				
-				log( "Added network: " + network.getString());
-				
-				networks.add( network );
-			}
-			
-				// we never persist the vuze network
-			
-			if ( network.getID() != ContentNetwork.CONTENT_NETWORK_VUZE ){
-				
-				saveConfig();
-			}
-		}
-		
-		Iterator<ContentNetworkListener>	 it = (Iterator<ContentNetworkListener>)listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				if ( replace ){
-					
-					it.next().networkChanged( network );
-					
-				}else{
-					
-					it.next().networkAdded( network );
-				}
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}
-		
-		return( network );
-	}
-	
-	protected void
-	removeNetwork(
-		ContentNetworkImpl		network )
-	{
-		synchronized( this ){
-
-			if ( !networks.remove( network )){
-				
-				return;
-			}
-		
-			network.destroy();
-			
-			saveConfig();
-		}
-		
-		log( "Removed network: " + network.getString());
-		
-		Iterator<ContentNetworkListener>	 it = (Iterator<ContentNetworkListener>)listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				it.next().networkRemoved( network );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}
-	}
-	
-	protected void
-	loadConfig()
-	{
-		if ( FileUtil.resilientConfigFileExists( CONFIG_FILE )){
-			
-			Map	map = FileUtil.readResilientConfigFile( CONFIG_FILE );
-			
-			List list = (List)map.get( "networks" );
-			
-			if ( list != null ){
-				
-				for (int i=0;i<list.size();i++){
-					
-					Map	cnet_map = (Map)list.get(i);
-					
-					try{
-						
-						ContentNetworkImpl cn = ContentNetworkImpl.importFromBEncodedMapStatic( this, cnet_map );
-						
-						if ( cn.getID() != ContentNetwork.CONTENT_NETWORK_VUZE ){
-							
-							networks.add( cn );
-						}
-					}catch( Throwable e ){
-						
-						log( "Failed to load " + cnet_map, e );
-					}
-				}
-			}
-		}
-	}
-	
-	protected void
-	saveConfig()
-	{
-		Map	map = new HashMap();
-		
-		List list = new ArrayList();
-		
-		map.put( "networks", list );
-		
-		Iterator<ContentNetworkImpl> it = networks.iterator();
-		
-		while( it.hasNext()){
-			
-			ContentNetworkImpl network = it.next();
-
-			if ( network.getID() == ContentNetwork.CONTENT_NETWORK_VUZE ){
-				
-				continue;
-			}
-			
-			Map	cnet_map = new HashMap();
-			
-			try{
-				network.exportToBEncodedMap( cnet_map );
-			
-				list.add( cnet_map );
-				
-			}catch( Throwable e ){
-				
-				log( "Failed to save " + network.getName(), e );
-			}
-		}
-		
-		if ( list.size() == 0 ){
-			
-			FileUtil.deleteResilientConfigFile( CONFIG_FILE );
-			
-		}else{
-			
-			FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
-		}
-	}
-	
-	public void
-	addListener(
-		ContentNetworkListener		listener )
-	{
-		listeners.add( listener );
-	}
-	
-	public void
-	removeListener(
-		ContentNetworkListener		listener )
-	{
-		listeners.remove( listener );
-	}
-	
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		writer.println( "Content Networks" );
-			
-		try{
-			writer.indent();
-
-			synchronized( this ){
-				
-				Iterator<ContentNetworkImpl> it = networks.iterator();
-				
-				while( it.hasNext()){
-					
-					ContentNetworkImpl network = it.next();
-					
-					writer.println( network.getString());
-				}
-			}			
-		}finally{
-			
-			writer.exdent();
-		}
-	}
-	
-	public static void 
-	log(
-		String 		s,
-		Throwable 	e )
-	{
-		AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( "CNetworks" );
-
-		diag_logger.log( s );
-		diag_logger.log( e );
-	}
-	
-	public static void 
-	log(
-		String 	s )
-	{	
-		AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( "CNetworks" );
-
-		diag_logger.log( s );
-	}
-}
+/*
+ * Created on Nov 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.cnetwork.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.util.AEDiagnostics;
+import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator;
+import org.gudy.azureus2.core3.util.AEDiagnosticsLogger;
+import org.gudy.azureus2.core3.util.AEThread2;
+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.IndentWriter;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+import org.gudy.azureus2.core3.util.TimerEvent;
+import org.gudy.azureus2.core3.util.TimerEventPerformer;
+
+import com.aelitis.azureus.core.cnetwork.ContentNetwork;
+import com.aelitis.azureus.core.cnetwork.ContentNetworkException;
+import com.aelitis.azureus.core.cnetwork.ContentNetworkListener;
+import com.aelitis.azureus.core.cnetwork.ContentNetworkManager;
+import com.aelitis.azureus.core.custom.Customization;
+import com.aelitis.azureus.core.custom.CustomizationManager;
+import com.aelitis.azureus.core.custom.CustomizationManagerFactory;
+
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+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;
+
+public class 
+ContentNetworkManagerImpl 
+	implements ContentNetworkManager, AEDiagnosticsEvidenceGenerator
+{
+	private static final boolean LOAD_ALL_NETWORKS	= true;
+	
+	private static final String CONFIG_FILE		= "cnetworks.config";
+	
+	private static ContentNetworkManagerImpl singleton = new ContentNetworkManagerImpl();
+		
+
+	public static void
+	preInitialise()
+	{
+		VuzeFileHandler.getSingleton().addProcessor(
+			new VuzeFileProcessor()
+			{
+				public void
+				process(
+					VuzeFile[]		files,
+					int				expected_types )
+				{
+					for (int i=0;i<files.length;i++){
+						
+						VuzeFile	vf = files[i];
+						
+						VuzeFileComponent[] comps = vf.getComponents();
+						
+						for (int j=0;j<comps.length;j++){
+							
+							VuzeFileComponent comp = comps[j];
+							
+							if ( comp.getType() == VuzeFileComponent.COMP_TYPE_CONTENT_NETWORK ){
+								
+								try{								
+									((ContentNetworkManagerImpl)getSingleton()).importNetwork( comp.getContent());
+								
+									comp.setProcessed();
+									
+								}catch( Throwable e ){
+									
+									log( "Failed to import from vuze file", e );
+							
+									Debug.out( e );
+								}
+							}
+						}
+					}
+				}
+			});		
+	}
+	
+	public static ContentNetworkManager
+	getSingleton()
+	{
+		return( singleton );
+	}
+	
+	private List<ContentNetworkImpl>	networks = new ArrayList<ContentNetworkImpl>();
+	
+	private CopyOnWriteList<ContentNetworkListener>	listeners = new CopyOnWriteList<ContentNetworkListener>();
+	
+	protected
+	ContentNetworkManagerImpl()
+	{
+		loadConfig();
+		
+		addNetwork( new ContentNetworkVuze( this ));
+		
+		AEDiagnostics.addEvidenceGenerator( this );
+		
+		CustomizationManager cust_man = CustomizationManagerFactory.getSingleton();
+		
+		Customization cust = cust_man.getActiveCustomization();
+		
+		if ( cust != null ){
+			
+			String cust_name 	= COConfigurationManager.getStringParameter( "cnetworks.custom.name", "" );
+			String cust_version = COConfigurationManager.getStringParameter( "cnetworks.custom.version", "0" );
+			
+			boolean	new_name 	= !cust_name.equals( cust.getName());
+			boolean	new_version = Constants.compareVersions( cust_version, cust.getVersion() ) < 0;
+			
+			if ( new_name || new_version ){
+				
+				try{
+					InputStream[] streams = cust.getResources( Customization.RT_CNETWORKS );
+					
+					for (int i=0;i<streams.length;i++){
+						
+						InputStream is = streams[i];
+						
+						try{
+							VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile(is);
+							
+							if ( vf != null ){
+								
+								VuzeFileComponent[] comps = vf.getComponents();
+								
+								for (int j=0;j<comps.length;j++){
+									
+									VuzeFileComponent comp = comps[j];
+									
+									int type = comp.getType();
+									
+									if ( type == VuzeFileComponent.COMP_TYPE_CONTENT_NETWORK ){
+										
+										try{
+												// change here as we always add all networks upfront so
+												// we always set the customisation flag regardless of
+												// whether existing or not
+											
+											ContentNetwork imported = importNetwork( comp.getContent());
+											
+											imported.setPersistentProperty( ContentNetwork.PP_IS_CUSTOMIZATION, true );
+											
+											comp.setProcessed();
+											
+										}catch( Throwable e ){
+											
+											log( "Failed to import customisation network", e );
+										}
+									}
+								}
+							}
+						}finally{
+							
+							try{
+								is.close();
+								
+							}catch( Throwable e ){
+							}
+						}
+					}
+				}finally{
+					
+					COConfigurationManager.setParameter( "cnetworks.custom.name", cust.getName());
+					COConfigurationManager.setParameter( "cnetworks.custom.version", cust.getVersion());
+				}
+			}
+		}
+		
+		
+		SimpleTimer.addPeriodicEvent(
+				"MetaSearchRefresh",
+				23*60*60*1000,
+				new TimerEventPerformer()
+				{
+					public void 
+					perform(
+						TimerEvent 	event ) 
+					{
+						checkForUpdates();
+					}
+				});
+		
+		if ( networks.size() > 1 || LOAD_ALL_NETWORKS ){
+			
+			new AEThread2( "CNetwork:init",	true )
+			{
+				public void
+				run()
+				{
+					checkForUpdates();
+				}
+			}.start();
+		}
+	}
+	
+	protected void
+	checkForUpdates()
+	{
+	}
+	
+	protected ContentNetworkImpl
+	importNetwork(
+		Map		content )
+	
+		throws IOException
+	{
+		ContentNetworkImpl network = ContentNetworkImpl.importFromBEncodedMapStatic( this, content );
+		
+		return( addNetwork( network ));
+	}
+	
+	// @see com.aelitis.azureus.core.cnetwork.ContentNetworkManager#addContentNetwork(long)
+	public void 
+	addContentNetwork(
+		final long 	id ) 
+	
+		throws ContentNetworkException
+	{
+	}
+	
+	public ContentNetwork
+	getContentNetworkForURL(
+		String		url )
+	{
+		try{
+			String	host = new URL( url ).getHost();
+			
+			for ( ContentNetwork cn: getContentNetworks()){
+				
+				String	site = (String)cn.getProperty( ContentNetwork.PROPERTY_SITE_HOST );
+				
+				if ( site != null && site.endsWith( host )){
+					
+					return( cn );
+				}
+			}
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+		}
+		
+		return( null );
+	}
+	
+	public ContentNetwork
+	getStartupContentNetwork()
+	{
+		ContentNetwork[] networks = getContentNetworks();
+		
+		for ( ContentNetwork network: networks ){
+			
+			if ( network.isStartupNetwork()){
+				
+				return( network );
+			}
+		}
+		
+		return( getContentNetwork( ContentNetwork.CONTENT_NETWORK_VUZE ));
+	}
+	
+	public ContentNetwork[] 
+	getContentNetworks() 
+	{
+		synchronized( this ){
+			
+			return((ContentNetwork[])networks.toArray( new ContentNetworkImpl[ networks.size()] ));
+		}
+	}
+	
+	public ContentNetworkImpl 
+	getContentNetwork(
+		long id ) 
+	{
+		synchronized( this ){
+			
+			for ( int i=0;i<networks.size();i++ ){
+					
+				ContentNetworkImpl network = networks.get(i);
+				
+				if ( network.getID() == id ){
+				
+					return( network );
+				}
+			}
+			
+			return( null );
+		}
+	}
+	
+	protected ContentNetworkImpl
+	addNetwork(
+		ContentNetworkImpl		network )
+	{
+		boolean	replace = false;
+		
+		synchronized( this ){
+		
+			Iterator<ContentNetworkImpl> it = networks.iterator();
+			
+			while( it.hasNext()){
+				
+				ContentNetworkImpl existing_network = it.next();
+				
+				if ( existing_network.getID() == network.getID()){
+					
+					if ( network.getVersion() > existing_network.getVersion()){
+						
+						try{
+							existing_network.updateFrom( network );
+						
+						}catch( Throwable e ){
+							
+							Debug.printStackTrace( e );
+						}
+						
+						network = existing_network;
+						
+						replace = true;
+						
+						break;
+						
+					}else{
+						
+						log( "Network " + existing_network.getString() + " already up to date" );
+						
+						return( existing_network );
+					}
+				}
+			}
+
+			if ( replace ){
+			
+				log( "Updated network: " + network.getString());
+				
+			}else{
+				
+				log( "Added network: " + network.getString());
+				
+				networks.add( network );
+			}
+			
+				// we never persist the vuze network
+			
+			if ( network.getID() != ContentNetwork.CONTENT_NETWORK_VUZE ){
+				
+				saveConfig();
+			}
+		}
+		
+		Iterator<ContentNetworkListener>	 it = (Iterator<ContentNetworkListener>)listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				if ( replace ){
+					
+					it.next().networkChanged( network );
+					
+				}else{
+					
+					it.next().networkAdded( network );
+				}
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+		
+		return( network );
+	}
+	
+	protected void
+	removeNetwork(
+		ContentNetworkImpl		network )
+	{
+		synchronized( this ){
+
+			if ( !networks.remove( network )){
+				
+				return;
+			}
+		
+			network.destroy();
+			
+			saveConfig();
+		}
+		
+		log( "Removed network: " + network.getString());
+		
+		Iterator<ContentNetworkListener>	 it = (Iterator<ContentNetworkListener>)listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				it.next().networkRemoved( network );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+	}
+	
+	protected void
+	loadConfig()
+	{
+		if ( FileUtil.resilientConfigFileExists( CONFIG_FILE )){
+			
+			Map	map = FileUtil.readResilientConfigFile( CONFIG_FILE );
+			
+			List list = (List)map.get( "networks" );
+			
+			if ( list != null ){
+				
+				for (int i=0;i<list.size();i++){
+					
+					Map	cnet_map = (Map)list.get(i);
+					
+					try{
+						
+						ContentNetworkImpl cn = ContentNetworkImpl.importFromBEncodedMapStatic( this, cnet_map );
+						
+						if ( cn.getID() != ContentNetwork.CONTENT_NETWORK_VUZE ){
+							
+							networks.add( cn );
+						}
+					}catch( Throwable e ){
+						
+						log( "Failed to load " + cnet_map, e );
+					}
+				}
+			}
+		}
+	}
+	
+	protected void
+	saveConfig()
+	{
+		Map	map = new HashMap();
+		
+		List list = new ArrayList();
+		
+		map.put( "networks", list );
+		
+		Iterator<ContentNetworkImpl> it = networks.iterator();
+		
+		while( it.hasNext()){
+			
+			ContentNetworkImpl network = it.next();
+
+			if ( network.getID() == ContentNetwork.CONTENT_NETWORK_VUZE ){
+				
+				continue;
+			}
+			
+			Map	cnet_map = new HashMap();
+			
+			try{
+				network.exportToBEncodedMap( cnet_map );
+			
+				list.add( cnet_map );
+				
+			}catch( Throwable e ){
+				
+				log( "Failed to save " + network.getName(), e );
+			}
+		}
+		
+		if ( list.size() == 0 ){
+			
+			FileUtil.deleteResilientConfigFile( CONFIG_FILE );
+			
+		}else{
+			
+			FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
+		}
+	}
+	
+	public void
+	addListener(
+		ContentNetworkListener		listener )
+	{
+		listeners.add( listener );
+	}
+	
+	public void
+	removeListener(
+		ContentNetworkListener		listener )
+	{
+		listeners.remove( listener );
+	}
+	
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		writer.println( "Content Networks" );
+			
+		try{
+			writer.indent();
+
+			synchronized( this ){
+				
+				Iterator<ContentNetworkImpl> it = networks.iterator();
+				
+				while( it.hasNext()){
+					
+					ContentNetworkImpl network = it.next();
+					
+					writer.println( network.getString());
+				}
+			}			
+		}finally{
+			
+			writer.exdent();
+		}
+	}
+	
+	public static void 
+	log(
+		String 		s,
+		Throwable 	e )
+	{
+		AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( "CNetworks" );
+
+		diag_logger.log( s );
+		diag_logger.log( e );
+	}
+	
+	public static void 
+	log(
+		String 	s )
+	{	
+		AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( "CNetworks" );
+
+		diag_logger.log( s );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuze.java b/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuze.java
index 15db098..7239b97 100644
--- a/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuze.java
+++ b/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuze.java
@@ -1,104 +1,103 @@
-/*
- * Created on Nov 24, 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.core.cnetwork.impl;
-
-
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-// import com.aelitis.azureus.core.util.FeatureAvailability;
-
-public class 
-ContentNetworkVuze 
-	extends ContentNetworkVuzeGeneric
-{
-	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";
-
-	private static final String DEFAULT_RELAY_ADDRESS = "www.vuze.com"; //DO NOT TOUCH !!!!  use the -Drelay_address=ip override instead
-
-	private static final String DEFAULT_RELAY_PORT = "80";
-
-	private static final String DEFAULT_EXT_ADDRESS = "www.vuze.com"; //DO NOT TOUCH !!!!  
-
-	/*
-	static{
-		if ( FeatureAvailability.ENABLE_PLUS()){
-			
-			if ( System.getProperty( "platform_address", "" ).length() == 0 ){
-			
-				System.setProperty( "platform_address", "www2.vuze.com" );
-			}
-		}
-	}
-	*/
-	
-	private static final String URL_ADDRESS = System.getProperty( "platform_address", DEFAULT_ADDRESS );
-
-	private static final String URL_PORT 	= System.getProperty( "platform_port", DEFAULT_PORT );
-
-	private static final String URL_PREFIX = "http://" + URL_ADDRESS + ":" + URL_PORT + "/";
-
-	private static final String URL_EXT_PREFIX = "http://" 
-		+ System.getProperty( "platform_address_ext", DEFAULT_EXT_ADDRESS ) + ":"
-		+ System.getProperty( "platform_port_ext", DEFAULT_PORT ) + "/";
-
-	private static final String DEFAULT_AUTHORIZED_RPC = "https://" + URL_ADDRESS + ":443/rpc";
-
-	private static String URL_RELAY_RPC = System.getProperty("relay_url",
-			"http://" + System.getProperty("relay_address", DEFAULT_RELAY_ADDRESS)
-					+ ":" + System.getProperty("relay_port", DEFAULT_RELAY_PORT)
-					+ "/msgrelay/rpc");
-
-	private static final String URL_AUTHORIZED_RPC = System.getProperty(
-			"authorized_rpc", "1").equals("1") ? DEFAULT_AUTHORIZED_RPC : URL_PREFIX
-			+ "app";
-	
-	private static final String URL_FAQ = "http://wiki.vuze.com/";
-
-	private static final String URL_BLOG = "http://blog.vuze.com/";
-	
-	private static final String URL_FORUMS = "http://forum.vuze.com/";
-	
-	private static final String URL_WIKI = "http://wiki.vuze.com/";
-
-	protected
-	ContentNetworkVuze(
-		ContentNetworkManagerImpl	manager )
-	{
-		super( 	manager,
-				ContentNetwork.CONTENT_NETWORK_VUZE,
-				1,
-				"Vuze HD Network",
-				null,
-				null,
-				URL_ADDRESS,
-				URL_PREFIX,
-				null,			// no icon
-				URL_RELAY_RPC,
-				URL_AUTHORIZED_RPC,
-				URL_FAQ,
-				URL_BLOG,
-				URL_FORUMS,
-				URL_WIKI,
-				URL_EXT_PREFIX );
-	}
-}
+/*
+ * Created on Nov 24, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.cnetwork.impl;
+
+
+import com.aelitis.azureus.core.cnetwork.ContentNetwork;
+// import com.aelitis.azureus.core.util.FeatureAvailability;
+
+public class 
+ContentNetworkVuze 
+	extends ContentNetworkVuzeGeneric
+{
+	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";
+
+	private static final String DEFAULT_RELAY_ADDRESS = "www.vuze.com"; //DO NOT TOUCH !!!!  use the -Drelay_address=ip override instead
+
+	private static final String DEFAULT_RELAY_PORT = "80";
+
+	private static final String DEFAULT_EXT_ADDRESS = "www.vuze.com"; //DO NOT TOUCH !!!!  
+
+	/*
+	static{
+		if ( FeatureAvailability.ENABLE_PLUS()){
+			
+			if ( System.getProperty( "platform_address", "" ).length() == 0 ){
+			
+				System.setProperty( "platform_address", "www2.vuze.com" );
+			}
+		}
+	}
+	*/
+	
+	private static final String URL_ADDRESS = System.getProperty( "platform_address", DEFAULT_ADDRESS );
+
+	private static final String URL_PORT 	= System.getProperty( "platform_port", DEFAULT_PORT );
+
+	private static final String URL_PREFIX = "http://" + URL_ADDRESS + ":" + URL_PORT + "/";
+
+	private static final String URL_EXT_PREFIX = "http://" 
+		+ System.getProperty( "platform_address_ext", DEFAULT_EXT_ADDRESS ) + ":"
+		+ System.getProperty( "platform_port_ext", DEFAULT_PORT ) + "/";
+
+	private static final String DEFAULT_AUTHORIZED_RPC = "https://" + URL_ADDRESS + ":443/rpc";
+
+	private static String URL_RELAY_RPC = System.getProperty("relay_url",
+			"http://" + System.getProperty("relay_address", DEFAULT_RELAY_ADDRESS)
+					+ ":" + System.getProperty("relay_port", DEFAULT_RELAY_PORT)
+					+ "/msgrelay/rpc");
+
+	private static final String URL_AUTHORIZED_RPC = System.getProperty(
+			"authorized_rpc", "1").equals("1") ? DEFAULT_AUTHORIZED_RPC : URL_PREFIX
+			+ "app";
+	
+	private static final String URL_FAQ = "http://wiki.vuze.com/";
+
+	private static final String URL_BLOG = "http://blog.vuze.com/";
+	
+	private static final String URL_FORUMS = "http://forum.vuze.com/";
+	
+	private static final String URL_WIKI = "http://wiki.vuze.com/";
+
+	protected
+	ContentNetworkVuze(
+		ContentNetworkManagerImpl	manager )
+	{
+		super( 	manager,
+				ContentNetwork.CONTENT_NETWORK_VUZE,
+				1,
+				"Vuze HD Network",
+				null,
+				null,
+				URL_ADDRESS,
+				URL_PREFIX,
+				null,			// no icon
+				URL_RELAY_RPC,
+				URL_AUTHORIZED_RPC,
+				URL_FAQ,
+				URL_BLOG,
+				URL_FORUMS,
+				URL_WIKI,
+				URL_EXT_PREFIX );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuzeGeneric.java b/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuzeGeneric.java
index b6fba35..5708984 100644
--- a/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuzeGeneric.java
+++ b/azureus3/src/com/aelitis/azureus/core/cnetwork/impl/ContentNetworkVuzeGeneric.java
@@ -2,20 +2,19 @@
  * Created by Paul Gardner
  * Created on Nov 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.
+ * Copyright (C) Azureus Software, 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -70,7 +69,8 @@ ContentNetworkVuzeGeneric
 		});
 	}
 
-	private static final String RPC_ADDRESS = System.getProperty( "platform_rpc", "vrpc.vuze.com" );
+	private static final String RPC_ADDRESS = System.getProperty("platform_rpc",
+			"https://vrpc.vuze.com/vzrpc/rpc.php");
 
 	private Map<Integer, String>		service_map = new HashMap<Integer, String>();
 
@@ -213,7 +213,7 @@ ContentNetworkVuzeGeneric
 		
 		addService( SERVICE_SEARCH, 			URL_PREFIX + "search?q=" );
 		addService( SERVICE_XSEARCH, 			URL_PREFIX + "xsearch/index.php?q=" );
-		addService( SERVICE_RPC, 				"http://" + RPC_ADDRESS + "/vzrpc/rpc.php" );
+		addService( SERVICE_RPC, 				RPC_ADDRESS );
 		addService( SERVICE_BIG_BROWSE, 		URL_PREFIX + "browse.start?" );
 		addService( SERVICE_PUBLISH, 			URL_PREFIX + "publish.start?" );
 		addService( SERVICE_WELCOME, 			URL_PREFIX + "welcome.start?" );
diff --git a/azureus3/src/com/aelitis/azureus/core/content/AzureusPlatformContentDirectory.java b/azureus3/src/com/aelitis/azureus/core/content/AzureusPlatformContentDirectory.java
index ca444b8..b1442ef 100644
--- a/azureus3/src/com/aelitis/azureus/core/content/AzureusPlatformContentDirectory.java
+++ b/azureus3/src/com/aelitis/azureus/core/content/AzureusPlatformContentDirectory.java
@@ -1,7 +1,7 @@
 /*
  * Created on Dec 19, 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/core/content/ContentException.java b/azureus3/src/com/aelitis/azureus/core/content/ContentException.java
index e4d9fd6..a2b3daf 100644
--- a/azureus3/src/com/aelitis/azureus/core/content/ContentException.java
+++ b/azureus3/src/com/aelitis/azureus/core/content/ContentException.java
@@ -1,42 +1,41 @@
-/*
- * Created on Jul 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.core.content;
-
-public class 
-ContentException
-	extends Exception
-{
-	public
-	ContentException(
-		String	str )
-	{
-		super( str );
-	}
-	
-	public
-	ContentException(
-		String		str,
-		Throwable 	e )
-	{
-		super( str, e );
-	}
-}
+/*
+ * Created on Jul 8, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.content;
+
+public class 
+ContentException
+	extends Exception
+{
+	public
+	ContentException(
+		String	str )
+	{
+		super( str );
+	}
+	
+	public
+	ContentException(
+		String		str,
+		Throwable 	e )
+	{
+		super( str, e );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/content/RelatedAttributeLookupListener.java b/azureus3/src/com/aelitis/azureus/core/content/RelatedAttributeLookupListener.java
index 708d7ae..879fba1 100644
--- a/azureus3/src/com/aelitis/azureus/core/content/RelatedAttributeLookupListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/content/RelatedAttributeLookupListener.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -29,7 +28,8 @@ RelatedAttributeLookupListener
 	
 	public void
 	tagFound(
-		String		tag );
+		String		tag,
+		String		network );
 
 	public void
 	lookupComplete();
diff --git a/azureus3/src/com/aelitis/azureus/core/content/RelatedContent.java b/azureus3/src/com/aelitis/azureus/core/content/RelatedContent.java
index 419ec45..317b233 100644
--- a/azureus3/src/com/aelitis/azureus/core/content/RelatedContent.java
+++ b/azureus3/src/com/aelitis/azureus/core/content/RelatedContent.java
@@ -1,301 +1,325 @@
-/*
- * Created on Jul 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.content;
-
-import org.gudy.azureus2.core3.util.Base32;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.SystemTime;
-import org.gudy.azureus2.plugins.download.Download;
-
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-
-public abstract class 
-RelatedContent 
-{
-	public final static String[]	NO_TAGS = {};
-	
-	final private String 		title;
-	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;
-
-	private byte[]		tracker_keys;
-	private byte[]		ws_keys;
-	
-	private String[]	tags;
-	
-	private long changed_locally_on;
-	
-	public
-	RelatedContent(
-		byte[]		_related_to_hash,
-		String		_title,
-		byte[]		_hash,
-		String		_tracker,
-		byte[]		_tracker_keys,
-		byte[]		_ws_keys,
-		String[]	_tags,
-		long		_size,
-		int			_date,
-		int			_seeds_leechers,
-		byte		_cnet )
-	{
-		related_to_hash		= _related_to_hash;
-		title				= _title;
-		hash				= _hash;
-		tracker				= _tracker;
-		tracker_keys		= _tracker_keys;
-		ws_keys				= _ws_keys;
-		tags				= _tags;
-		size				= _size;
-		date				= _date;
-		seeds_leechers		= _seeds_leechers;
-		content_network		= _cnet;
-		setChangedLocallyOn(0);
-	}
-	
-	public
-	RelatedContent(
-		String		_title,
-		byte[]		_hash,
-		String		_tracker,
-		long		_size,
-		int			_date,
-		int			_seeds_leechers,
-		byte		_cnet )
-	{
-			// legacy constructor as referenced from plugin - remove oneday!
-		
-		this( _title, _hash, _tracker, null, null, null, _size, _date, _seeds_leechers, _cnet );
-	}
-	
-	public
-	RelatedContent(
-		String		_title,
-		byte[]		_hash,
-		String		_tracker,
-		byte[]		_tracker_keys,
-		byte[]		_ws_keys,
-		String[]	_tags,
-		long		_size,
-		int			_date,
-		int			_seeds_leechers,
-		byte		_cnet )
-	{
-		title				= _title;
-		hash				= _hash;
-		tracker				= _tracker;
-		tracker_keys		= _tracker_keys;
-		ws_keys				= _ws_keys;
-		tags				= _tags;
-		size				= _size;
-		date				= _date;
-		seeds_leechers		= _seeds_leechers;
-		content_network		= _cnet;
-		setChangedLocallyOn(0);
-	}
-	
-	protected void
-	setRelatedToHash(
-		byte[]		h )
-	{
-		related_to_hash = h;
-		// Intentionally not called, since setRelatedToHash gets called after
-		// constructing all the RelatedContent objects
-		// setChangedLocallyOn(0);
-	}
-	
-	public byte[]
-	getRelatedToHash()
-	{
-		return( related_to_hash );
-	}
-	
-	public abstract Download
-	getRelatedToDownload();
-	
-	public String
-	getTitle()
-	{
-		return( title );
-	}
-	
-	public abstract int
-	getRank();
-	
-	public byte[]
-	getHash()
-	{
-		return( hash );
-	}
-	
-	public abstract int
-	getLevel();
-	
-	public abstract boolean
-	isUnread();
-	
-	public abstract void
-	setUnread(
-		boolean	unread );
-	
-	public abstract int
-	getLastSeenSecs();
-	
-	public String
-	getTracker()
-	{
-		return( tracker );
-	}
-	
-	public byte[]
-	getTrackerKeys()
-	{
-		return( tracker_keys );
-	}
-	
-	public byte[]
-	getWebSeedKeys()
-	{
-		return( ws_keys );
-	}
-	
-	public String[]
-	getTags()
-	{
-		return( tags==null?NO_TAGS:tags );
-	}
-	
-	protected void
-	setTags(
-		String[]	_tags )
-	{
-		tags	= _tags;
-		setChangedLocallyOn(0);
-	}
-	
-	public long
-	getSize()
-	{
-		return( size );
-	}
-	
-	public long
-	getPublishDate()
-	{
-		return( date*60*60*1000L );
-	}
-	
-	protected int
-	getDateHours()
-	{
-		return( date );
-	}
-	
-	protected void
-	setDateHours(
-		int		_date )
-	{
-		date = _date;
-		setChangedLocallyOn(0);
-	}
-	
-	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;
-		setChangedLocallyOn(0);
-	}
-	
-	public long
-	getContentNetwork()
-	{
-		return((content_network&0xff)==0xff?ContentNetwork.CONTENT_NETWORK_UNKNOWN:(content_network&0xff));
-	}
-	
-	protected void
-	setContentNetwork(
-		long		cnet )
-	{
-		content_network = (byte)cnet;
-		setChangedLocallyOn(0);
-	}
-	
-	public long
-	getChangedLocallyOn()
-	{
-		return changed_locally_on;
-	}
-	
-	/**
-	 * 
-	 * @param _changed_locally_on  0 == current time
-	 */
-	public void
-	setChangedLocallyOn(long _changed_locally_on)
-	{
-		changed_locally_on = (_changed_locally_on == 0) ? SystemTime.getCurrentTime() : _changed_locally_on;
-	}
-	
-	public abstract void
-	delete();
-	
-	public String
-	getString()
-	{
-		return( "title=" + title + ", hash=" + (hash==null?"null":Base32.encode( hash )) + ", tracker=" + tracker +", date=" + date + ", sl=" + seeds_leechers + ", cnet=" + content_network );
-	}
-}
+/*
+ * Created on Jul 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.content;
+
+import org.gudy.azureus2.core3.util.Base32;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.plugins.download.Download;
+
+import com.aelitis.azureus.core.cnetwork.ContentNetwork;
+
+public abstract class 
+RelatedContent 
+{
+	public final static String[]	NO_TAGS = {};
+	
+	final private String 		title;
+	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;
+
+	private byte[]				tracker_keys;
+	private byte[]				ws_keys;
+	
+	private String[]			tags;
+	private byte				nets;
+	
+	private long changed_locally_on;
+	
+	public
+	RelatedContent(
+		byte[]		_related_to_hash,
+		String		_title,
+		byte[]		_hash,
+		String		_tracker,
+		byte[]		_tracker_keys,
+		byte[]		_ws_keys,
+		String[]	_tags,
+		byte		_nets,
+		long		_size,
+		int			_date,
+		int			_seeds_leechers,
+		byte		_cnet )
+	{
+		related_to_hash		= _related_to_hash;
+		title				= _title;
+		hash				= _hash;
+		tracker				= _tracker;
+		tracker_keys		= _tracker_keys;
+		ws_keys				= _ws_keys;
+		tags				= _tags;
+		nets				= _nets;
+		size				= _size;
+		date				= _date;
+		seeds_leechers		= _seeds_leechers;
+		content_network		= _cnet;
+		setChangedLocallyOn(0);
+	}
+	
+	public
+	RelatedContent(
+		String		_title,
+		byte[]		_hash,
+		String		_tracker,
+		long		_size,
+		int			_date,
+		int			_seeds_leechers,
+		byte		_cnet )
+	{
+			// legacy constructor as referenced from plugin - remove oneday!
+		
+		this( _title, _hash, _tracker, null, null, null, RelatedContentManager.NET_PUBLIC, _size, _date, _seeds_leechers, _cnet );
+	}
+	
+	public
+	RelatedContent(
+		String		_title,
+		byte[]		_hash,
+		String		_tracker,
+		byte[]		_tracker_keys,
+		byte[]		_ws_keys,
+		String[]	_tags,
+		byte		_nets,
+		long		_size,
+		int			_date,
+		int			_seeds_leechers,
+		byte		_cnet )
+	{
+		title				= _title;
+		hash				= _hash;
+		tracker				= _tracker;
+		tracker_keys		= _tracker_keys;
+		ws_keys				= _ws_keys;
+		tags				= _tags;
+		nets				= _nets;
+		size				= _size;
+		date				= _date;
+		seeds_leechers		= _seeds_leechers;
+		content_network		= _cnet;
+		setChangedLocallyOn(0);
+	}
+	
+	protected void
+	setRelatedToHash(
+		byte[]		h )
+	{
+		related_to_hash = h;
+		// Intentionally not called, since setRelatedToHash gets called after
+		// constructing all the RelatedContent objects
+		// setChangedLocallyOn(0);
+	}
+	
+	public byte[]
+	getRelatedToHash()
+	{
+		return( related_to_hash );
+	}
+	
+	public abstract Download
+	getRelatedToDownload();
+	
+	public String
+	getTitle()
+	{
+		return( title );
+	}
+	
+	public abstract int
+	getRank();
+	
+	public byte[]
+	getHash()
+	{
+		return( hash );
+	}
+	
+	public abstract int
+	getLevel();
+	
+	public abstract boolean
+	isUnread();
+	
+	public abstract void
+	setUnread(
+		boolean	unread );
+	
+	public abstract int
+	getLastSeenSecs();
+	
+	public String
+	getTracker()
+	{
+		return( tracker );
+	}
+	
+	public byte[]
+	getTrackerKeys()
+	{
+		return( tracker_keys );
+	}
+	
+	public byte[]
+	getWebSeedKeys()
+	{
+		return( ws_keys );
+	}
+	
+	public String[]
+	getTags()
+	{
+		return( tags==null?NO_TAGS:tags );
+	}
+	
+	protected void
+	setTags(
+		String[]	_tags )
+	{
+		tags	= _tags;
+		setChangedLocallyOn(0);
+	}
+	
+	public String[]
+	getNetworks()
+	{
+		return( RelatedContentManager.convertNetworks( nets ));
+	}
+	
+	protected byte
+	getNetworksInternal()
+	{
+		return( nets );
+	}
+	
+	protected void
+	setNetworksInternal(
+		byte		n )
+	{
+		nets = n;
+	}
+		
+	public long
+	getSize()
+	{
+		return( size );
+	}
+	
+	public long
+	getPublishDate()
+	{
+		return( date*60*60*1000L );
+	}
+	
+	protected int
+	getDateHours()
+	{
+		return( date );
+	}
+	
+	protected void
+	setDateHours(
+		int		_date )
+	{
+		date = _date;
+		setChangedLocallyOn(0);
+	}
+	
+	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;
+		setChangedLocallyOn(0);
+	}
+	
+	public long
+	getContentNetwork()
+	{
+		return((content_network&0xff)==0xff?ContentNetwork.CONTENT_NETWORK_UNKNOWN:(content_network&0xff));
+	}
+	
+	protected void
+	setContentNetwork(
+		long		cnet )
+	{
+		content_network = (byte)cnet;
+		setChangedLocallyOn(0);
+	}
+	
+	public long
+	getChangedLocallyOn()
+	{
+		return changed_locally_on;
+	}
+	
+	/**
+	 * 
+	 * @param _changed_locally_on  0 == current time
+	 */
+	public void
+	setChangedLocallyOn(long _changed_locally_on)
+	{
+		changed_locally_on = (_changed_locally_on == 0) ? SystemTime.getCurrentTime() : _changed_locally_on;
+	}
+	
+	public abstract void
+	delete();
+	
+	public String
+	getString()
+	{
+		return( "title=" + title + ", hash=" + (hash==null?"null":Base32.encode( hash )) + ", tracker=" + tracker +", date=" + date + ", sl=" + seeds_leechers + ", cnet=" + content_network + ", nets=" + nets );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/content/RelatedContentLookupListener.java b/azureus3/src/com/aelitis/azureus/core/content/RelatedContentLookupListener.java
index 0446904..73f2e94 100644
--- a/azureus3/src/com/aelitis/azureus/core/content/RelatedContentLookupListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/content/RelatedContentLookupListener.java
@@ -1,40 +1,39 @@
-/*
- * Created on Jul 15, 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.content;
-
-public interface 
-RelatedContentLookupListener 
-{
-	public void
-	lookupStart();
-	
-	public void
-	contentFound(
-		RelatedContent[]	content );
-	
-	public void
-	lookupComplete();
-	
-	public void
-	lookupFailed(
-		ContentException 	error );
-}
+/*
+ * Created on Jul 15, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.content;
+
+public interface 
+RelatedContentLookupListener 
+{
+	public void
+	lookupStart();
+	
+	public void
+	contentFound(
+		RelatedContent[]	content );
+	
+	public void
+	lookupComplete();
+	
+	public void
+	lookupFailed(
+		ContentException 	error );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/content/RelatedContentManager.java b/azureus3/src/com/aelitis/azureus/core/content/RelatedContentManager.java
index 41f8fc5..3896c95 100644
--- a/azureus3/src/com/aelitis/azureus/core/content/RelatedContentManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/content/RelatedContentManager.java
@@ -1,6569 +1,4962 @@
-/*
- * Created on Jul 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.core.content;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
-import java.lang.ref.WeakReference;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.URL;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.regex.Pattern;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-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.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLGroup;
-import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
-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;
-import org.gudy.azureus2.core3.util.SHA1Simple;
-import org.gudy.azureus2.core3.util.SimpleTimer;
-import org.gudy.azureus2.core3.util.StringInterner;
-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.TorrentUtils;
-import org.gudy.azureus2.core3.util.UrlUtils;
-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.disk.DiskManagerFileInfo;
-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.DHTTransport;
-import com.aelitis.azureus.core.dht.transport.DHTTransportContact;
-import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP;
-import com.aelitis.azureus.core.security.CryptoManagerFactory;
-import com.aelitis.azureus.core.tag.Tag;
-import com.aelitis.azureus.core.tag.TagManager;
-import com.aelitis.azureus.core.tag.TagManagerFactory;
-import com.aelitis.azureus.core.tag.TagType;
-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.RegExUtil;
-import com.aelitis.azureus.core.util.bloom.BloomFilter;
-import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
-import com.aelitis.azureus.plugins.dht.DHTPlugin;
-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;
-
-public class 
-RelatedContentManager
-	implements DistributedDatabaseTransferHandler
-{
-	public static final long FILE_ASSOC_MIN_SIZE	= 50*1024*1024;
-	
-	public static final int RCM_SEARCH_PROPERTY_CONTENT_NETWORK	= 50000;	// don't change these, used in plugin
-	public static final int RCM_SEARCH_PROPERTY_TRACKER_KEYS	= 50001;
-	public static final int RCM_SEARCH_PROPERTY_WEB_SEED_KEYS	= 50002;
-	public static final int RCM_SEARCH_PROPERTY_TAGS			= 50003;
-	
-	private static final boolean 	TRACE 			= false;
-	
-	private static final boolean	SEARCH_CVS_ONLY		= Constants.isCurrentVersionLT( "4.7.0.4" );
-	private static final boolean	TRACE_SEARCH		= false;
-	
-	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	MAX_REMOTE_SEARCH_CONTACTS	= 50;
-	private static final int	MAX_REMOTE_SEARCH_MILLIS		= 25*1000;
-	private static final int	REDUCED_REMOTE_SEARCH_MILLIS	= 10*1000;
-	
-	private static final int	TEMPORARY_SPACE_DELTA	= 50;
-	
-	private static final int	MAX_RANK	= 100;
-	
-	private static final String	CONFIG_FILE 				= "rcm.config";
-	private static final String	PERSIST_DEL_FILE 			= "rcmx.config";
-	
-	private static final String	CONFIG_TOTAL_UNREAD	= "rcm.numunread.cache";
-	
-	private static RelatedContentManager	singleton;
-	private static AzureusCore				core;
-	
-	public static synchronized void
-	preInitialise(
-		AzureusCore		_core )
-	{
-		core		= _core;
-	}
-	
-	public static synchronized RelatedContentManager
-	getSingleton()
-	
-		throws ContentException
-	{
-		if ( singleton == null ){
-			
-			singleton = new RelatedContentManager();
-		}
-		
-		return( singleton );
-	}
-	
-	
-	private PluginInterface 				plugin_interface;
-	private TorrentAttribute 				ta_networks;
-	private TorrentAttribute 				ta_category;
-	private DHTPlugin						dht_plugin;
-
-	private TagManager						tag_manager;
-	
-	private long	global_random_id = -1;
-	
-	private LinkedList<DownloadInfo>		download_infos1 	= new LinkedList<DownloadInfo>();
-	private LinkedList<DownloadInfo>		download_infos2 	= new LinkedList<DownloadInfo>();
-	
-	private ByteArrayHashMapEx<DownloadInfo>	download_info_map	= new ByteArrayHashMapEx<DownloadInfo>();
-	private Set<String>							download_priv_set	= new HashSet<String>();
-	
-	private final boolean	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>();
-	
-	private AESemaphore initialisation_complete_sem = new AESemaphore( "RCM:init" );
-
-	private static final int TIMER_PERIOD					= 30*1000;
-	private static final int CONFIG_SAVE_CHECK_PERIOD		= 60*1000;
-	private static final int CONFIG_SAVE_PERIOD				= 5*60*1000;
-	private static final int CONFIG_SAVE_CHECK_TICKS		= CONFIG_SAVE_CHECK_PERIOD/TIMER_PERIOD;
-	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 PUBLISH_SLEEPING_CHECK_PERIOD	= 5*60*1000;
-	private static final int PUBLISH_SLEEPING_CHECK_TICKS	= PUBLISH_SLEEPING_CHECK_PERIOD/TIMER_PERIOD;
-
-	private static final int SECONDARY_LOOKUP_PERIOD		= 15*60*1000;
-	private static final int SECONDARY_LOOKUP_TICKS			= SECONDARY_LOOKUP_PERIOD/TIMER_PERIOD;
-	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;
-	
-	private ContentCache				content_cache_ref;
-	private WeakReference<ContentCache>	content_cache;
-	
-	private boolean		content_dirty;
-	private long		last_config_access;		
-	private int			content_discard_ticks;
-	
-	private AtomicInteger	total_unread = new AtomicInteger( COConfigurationManager.getIntParameter( CONFIG_TOTAL_UNREAD, 0 ));
-	
-	private AsyncDispatcher	content_change_dispatcher 	= new AsyncDispatcher();
-	private AsyncDispatcher	harvest_dispatcher			= new AsyncDispatcher();
-	
-	private static final int SECONDARY_LOOKUP_CACHE_MAX = 10;
-	
-	private LinkedList<SecondaryLookup> secondary_lookups = new LinkedList<SecondaryLookup>();
-	
-	private boolean	secondary_lookup_in_progress;
-	private long	secondary_lookup_complete_time;
-	
-	private DistributedDatabase		ddb;
-	private RCMSearchXFer			transfer_type = new RCMSearchXFer();
-	
-	private static final int MAX_TRANSIENT_CACHE	= 256;
-	
-	private static Map<String,DownloadInfo> transient_info_cache =
-		new LinkedHashMap<String,DownloadInfo>(MAX_TRANSIENT_CACHE,0.75f,true)
-		{
-			protected boolean 
-			removeEldestEntry(
-		   		Map.Entry<String,DownloadInfo> eldest) 
-			{
-				return size() > MAX_TRANSIENT_CACHE;
-			}
-		};
-	
-	private static final int	HARVEST_MAX_BLOOMS				= 50;
-	private static final int	HARVEST_MAX_FAILS_HISTORY		= 128;
-	private static final int	HARVEST_BLOOM_UPDATE_MILLIS		= 15*60*1000;
-	private static final int	HARVEST_BLOOM_DISCARD_MILLIS	= 60*60*1000;
-	private static final int 	HARVEST_BLOOM_OP_RESET_MILLIS	= 5*60*1000;
-	private static final int 	HARVEST_BLOOM_OP_RESET_TICKS	= HARVEST_BLOOM_OP_RESET_MILLIS/TIMER_PERIOD;
-	private static final int 	HARVEST_BLOOM_SE_RESET_MILLIS	= 1*60*1000;
-	private static final int 	HARVEST_BLOOM_SE_RESET_TICKS	= HARVEST_BLOOM_SE_RESET_MILLIS/TIMER_PERIOD;
-
-	private ByteArrayHashMap<ForeignBloom>		harvested_blooms 	= new ByteArrayHashMap<ForeignBloom>();
-	private ByteArrayHashMap<String>			harvested_fails 	= new ByteArrayHashMap<String>();
-	
-	private volatile BloomFilter harvest_op_requester_bloom = BloomFilterFactory.createAddOnly( 2048 );
-	private volatile BloomFilter harvest_se_requester_bloom = BloomFilterFactory.createAddRemove4Bit( 512 );
-			
-			
-	private boolean	persist;
-	
-	{
-		COConfigurationManager.addAndFireParameterListener(
-			"rcm.persist",
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					String parameterName )
-				{
-					persist = COConfigurationManager.getBooleanParameter( "rcm.persist" ) || true;
-				}
-			});
-		
-			// remove one day
-		
-		COConfigurationManager.removeParameter( "rcm.dlinfo.history" );
-	}
-	
-	protected
-	RelatedContentManager()
-	
-		throws ContentException
-	{
-		COConfigurationManager.addAndFireParameterListeners(
-				new String[]{
-					"rcm.ui.enabled",
-					"rcm.max_search_level",
-					"rcm.max_results",
-				},
-				new ParameterListener()
-				{
-					public void 
-					parameterChanged(
-						String name )
-					{
-						max_search_level 	= COConfigurationManager.getIntParameter( "rcm.max_search_level", 3 );
-						max_results		 	= COConfigurationManager.getIntParameter( "rcm.max_results", 500 );
-					}
-				});
-		
-		if ( !FeatureAvailability.isRCMEnabled() || 
-			 !COConfigurationManager.getBooleanParameter( "rcm.overall.enabled", true )){
-			
-			enabled		= false;
-			
-			deleteRelatedContent();
-			
-			initialisation_complete_sem.releaseForever();
-
-			return;
-		}
-		
-		enabled = true;
-		
-		try{
-			if ( core == null ){
-				
-				throw( new ContentException( "getSingleton called before pre-initialisation" ));
-			}
-			
-			while( global_random_id == -1 ){
-				
-				global_random_id = COConfigurationManager.getLongParameter( "rcm.random.id", -1 );
-				
-				if ( global_random_id == -1 ){
-					
-					global_random_id = RandomUtils.nextLong();
-					
-					COConfigurationManager.setParameter( "rcm.random.id", global_random_id );
-				}
-			}
-				
-			plugin_interface = core.getPluginManager().getDefaultPluginInterface();
-			
-			ta_networks 	= plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_NETWORKS );
-			ta_category 	= plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_CATEGORY );
-
-			tag_manager	= TagManagerFactory.getTagManager();
-			
-			plugin_interface.getUtilities().createDelayedTask(new AERunnable() {
-				public void runSupport() {
-					SimpleTimer.addEvent(
-							"rcm.delay.init",
-							SystemTime.getOffsetTime( 15*1000 ),
-							new TimerEventPerformer()
-							{
-								public void 
-								perform(
-									TimerEvent event )
-								{
-									delayedInit();
-								}
-							});
-				}
-			}).queue();
-			
-		}catch( Throwable e ){
-			
-			initialisation_complete_sem.releaseForever();
-			
-			if ( e instanceof ContentException ){
-				
-				throw((ContentException)e);
-			}
-			
-			throw( new ContentException( "Initialisation failed", e ));
-		}
-	}
-	
-	private void delayedInit() {
-		
-		plugin_interface.addListener(
-			new PluginListener()
-			{
-				public void
-				initializationComplete()
-				{
-					if ( !persist ){
-						
-						deleteRelatedContent();
-					}
-					
-					try{
-						PluginInterface dht_pi = 
-							plugin_interface.getPluginManager().getPluginInterfaceByClass(
-										DHTPlugin.class );
-			
-						if ( dht_pi != null ){
-				
-							dht_plugin = (DHTPlugin)dht_pi.getPlugin();
-
-							if ( !dht_plugin.isEnabled()){
-								
-								return;
-							}
-							
-							DownloadManager dm = plugin_interface.getDownloadManager();
-							
-							Download[] downloads = dm.getDownloads();
-							
-							addDownloads( downloads, true );
-							
-							dm.addListener(
-								new DownloadManagerListener()
-								{
-									public void
-									downloadAdded(
-										Download	download )
-									{
-										addDownloads( new Download[]{ download }, false );
-									}
-									
-									public void
-									downloadRemoved(
-										Download	download )
-									{
-									}
-								},
-								false );
-							
-							SimpleTimer.addPeriodicEvent(
-								"RCM:publisher",
-								TIMER_PERIOD,
-								new TimerEventPerformer()
-								{
-									private int	tick_count;
-									
-									public void 
-									perform(
-										TimerEvent event ) 
-									{
-										tick_count++;
-
-										if ( tick_count == 1 ){
-											
-											try{
-												ddb = plugin_interface.getDistributedDatabase();
-											
-												ddb.addTransferHandler( transfer_type, RelatedContentManager.this );
-												
-											}catch( Throwable e ){
-												
-												// Debug.out( e );
-											}
-										}
-										
-										if ( enabled ){
-												
-											if ( tick_count >= INITIAL_PUBLISH_TICKS ){
-												
-												if ( tick_count % ( dht_plugin.isSleeping()?PUBLISH_SLEEPING_CHECK_TICKS: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_CHECK_TICKS == 0 ){
-													
-													saveRelatedContent( tick_count );
-												}
-											}
-												
-											harvestBlooms();
-											
-											if ( tick_count % HARVEST_BLOOM_SE_RESET_TICKS == 0 ){
-												
-												harvest_se_requester_bloom = harvest_se_requester_bloom.getReplica();
-											}
-											
-											if ( tick_count % HARVEST_BLOOM_OP_RESET_TICKS == 0 ){
-												
-												harvest_op_requester_bloom = harvest_op_requester_bloom.getReplica();
-											}									
-										}
-										
-										checkKeyBloom();
-										
-										testKeyBloom();
-									}
-								});
-						}										
-					}finally{
-							
-						initialisation_complete_sem.releaseForever();
-					}
-				}
-				
-				public void
-				closedownInitiated()
-				{
-					saveRelatedContent( 0 );
-				}
-				
-				public void
-				closedownComplete()
-				{
-				}
-			});
-	}
-	
-	public boolean
-	isEnabled()
-	{
-		return( enabled );
-	}
-		
-	public int
-	getMaxSearchLevel()
-	{
-		return( max_search_level );
-	}
-	
-	public void
-	setMaxSearchLevel(
-		int		_level )
-	{
-		COConfigurationManager.setParameter( "rcm.max_search_level", _level );
-	}
-	
-	public int
-	getMaxResults()
-	{
-		return( max_results );
-	}
-	
-	public void
-	setMaxResults(
-		int		_max )
-	{
-		COConfigurationManager.setParameter( "rcm.max_results", _max );
-		
-		enforceMaxResults( false );
-	}
-	
-	protected void
-	addDownloads(
-		Download[]		downloads,
-		boolean			initialising )
-	{
-		synchronized( this ){
-	
-			List<DownloadInfo>	new_info = new ArrayList<DownloadInfo>( downloads.length );
-			
-			for ( Download download: downloads ){
-				
-				try{
-					if ( !download.isPersistent()){
-						
-						continue;
-					}
-					
-					Torrent	torrent = download.getTorrent();
-	
-					if ( torrent == null ){
-						
-						continue;
-					}
-					
-					byte[]	hash = torrent.getHash();
-
-					if ( download_info_map.containsKey( hash )){
-						
-						continue;
-					}
-					
-					String[]	networks = download.getListAttribute( ta_networks );
-					
-					if ( networks == null ){
-						
-						continue;
-					}
-						
-					boolean	public_net = false;
-					
-					for (int i=0;i<networks.length;i++){
-						
-						if ( networks[i].equalsIgnoreCase( "Public" )){
-								
-							public_net	= true;
-							
-							break;
-						}
-					}
-					
-					TOTorrent to_torrent = PluginCoreUtils.unwrap( torrent );
-					
-					if ( public_net && !TorrentUtils.isReallyPrivate( to_torrent )){
-						
-						DownloadManagerState state = PluginCoreUtils.unwrap( download ).getDownloadState();
-
-						if ( state.getFlag(DownloadManagerState.FLAG_LOW_NOISE )){
-							
-							continue;
-						}
-						
-						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));
-						}
-
-						byte[][] keys = getKeys( download );
-						
-						DownloadInfo info = 
-							new DownloadInfo(
-								hash,
-								hash,
-								download.getName(),
-								(int)rand,
-								torrent.isPrivate()?StringInterner.intern(torrent.getAnnounceURL().getHost()):null,
-								keys[0],
-								keys[1],
-								getTags( download ),
-								0,
-								false,
-								torrent.getSize(),
-								(int)( to_torrent.getCreationDate()/(60*60)),
-								seeds_leechers,
-								(byte)PlatformTorrentUtils.getContentNetworkID( to_torrent ));
-						
-						new_info.add( info );
-						
-						if ( initialising || download_infos1.size() == 0 ){
-							
-							download_infos1.add( info );
-							
-						}else{
-							
-							download_infos1.add( RandomUtils.nextInt( download_infos1.size()), info );
-						}
-						
-						download_infos2.add( info );
-						
-						download_info_map.put( hash, info );
-						
-						if ( info.getTracker() != null ){
-							
-							download_priv_set.add( getPrivateInfoKey( info ));
-						}
-					}
-				}catch( Throwable e ){
-					
-					Debug.out( e );
-				}
-			}
-			
-			List<Map<String,Object>> history = (List<Map<String,Object>>)COConfigurationManager.getListParameter( "rcm.dlinfo.history.privx", new ArrayList<Map<String,Object>>());
-			
-			if ( initialising ){
-		
-				int padd = MAX_HISTORY - download_info_map.size();
-				
-				for ( int i=0;i<history.size() && padd > 0;i++ ){
-					
-					try{
-						DownloadInfo info = deserialiseDI((Map<String,Object>)history.get(i), null);
-						
-						if ( info != null && !download_info_map.containsKey( info.getHash())){
-							
-							download_info_map.put( info.getHash(), info );
-							
-							if ( info.getTracker() != null ){
-								
-								download_priv_set.add( getPrivateInfoKey( info ));
-							}
-							
-							download_infos1.add( info );
-							download_infos2.add( info );
-							
-							padd--;
-						}
-					}catch( Throwable e ){
-						
-					}
-				}
-				
-				Collections.shuffle( download_infos1 );
-				
-			}else{
-				
-				if ( new_info.size() > 0 ){
-					
-					final List<String>	base32_hashes = new ArrayList<String>();
-					
-					for ( DownloadInfo info: new_info ){
-						
-						byte[] hash = info.getHash();
-						
-						if ( hash != null ){
-							
-							base32_hashes.add( Base32.encode( hash ));
-						}
-						
-						Map<String,Object> map = serialiseDI( info, null );
-							
-						if ( map != null ){
-							
-							history.add( map );	
-						}
-					}
-					
-					while( history.size() > MAX_HISTORY ){
-						
-						history.remove(0);
-					}
-					
-					COConfigurationManager.setParameter( "rcm.dlinfo.history.privx", history );
-					
-					if ( base32_hashes.size() > 0 ){
-						
-						content_change_dispatcher.dispatch(
-							new AERunnable()
-							{
-								public void
-								runSupport()
-								{
-									List<RelatedContent>	to_remove = new ArrayList<RelatedContent>();
-									
-									synchronized( RelatedContentManager.this ){
-										
-										ContentCache content_cache = loadRelatedContent();
-										
-										for ( String h: base32_hashes ){
-										
-											DownloadInfo di = content_cache.related_content.get( h );
-											
-											if ( di != null ){
-												
-												to_remove.add( di );
-											}
-										}
-									}
-									
-									if ( to_remove.size() > 0 ){
-										
-										delete( to_remove.toArray( new RelatedContent[ to_remove.size()] ));
-									}
-								}
-							});
-					}
-				}
-			}
-		}
-	}
-	
-	protected void
-	republish()
-	{
-		synchronized( this ){
-
-			if( publishing_count > 0 ){
-				
-				return;
-			}
-			
-			if ( download_infos1.isEmpty()){
-				
-				List<DownloadInfo> list = download_info_map.values();
-				
-				download_infos1.addAll( list );
-				download_infos2.addAll( list );
-				
-				Collections.shuffle( download_infos1 );
-			}
-		}
-	}
-	
-	protected void
-	publish()
-	{
-		while( true ){
-			
-			DownloadInfo	info1 = null;
-			DownloadInfo	info2 = null;
-
-			synchronized( this ){
-	
-				if ( publishing_count >= MAX_CONCURRENT_PUBLISH ){
-					
-					return;
-				}
-				
-				if ( download_infos1.isEmpty() || download_info_map.size() == 1 ){
-					
-					return;
-				}
-							
-				info1 = download_infos1.removeFirst();
-				
-				Iterator<DownloadInfo> it = download_infos2.iterator();
-				
-				while( it.hasNext()){
-					
-					info2 = it.next();
-					
-					if ( info1 != info2 || download_infos2.size() == 1 ){
-						
-						it.remove();
-						
-						break;
-					}
-				}
-				
-				if ( info1 == info2 ){
-									
-					info2 = download_info_map.getRandomValueExcluding( info1 );
-					
-					if ( info2 == null || info1 == info2 ){
-						
-						// Debug.out( "Inconsistent!" );
-						
-						return;
-					}
-				}
-				
-				publishing_count++;
-			}
-			
-			try{
-				publish( info1, info2 );
-				
-			}catch( Throwable e ){
-				
-				synchronized( this ){
-
-					publishing_count--;
-				}
-				
-				Debug.out( e );
-			}
-		}
-	}
-	
-	protected void
-	publishNext()
-	{
-		synchronized( this ){
-
-			publishing_count--;
-			
-			if ( publishing_count < 0 ){
-				
-					// shouldn't happen but whatever
-				
-				publishing_count = 0;
-			}
-		}
-		
-		publish();
-	}
-	
-	protected void
-	publish(
-		final DownloadInfo	from_info,
-		final DownloadInfo	to_info )
-	
-		throws Exception
-	{			
-		final String from_hash	= ByteFormatter.encodeString( from_info.getHash());
-		final String to_hash	= ByteFormatter.encodeString( to_info.getHash());
-		
-		final byte[] key_bytes	= ( "az:rcm:assoc:" + from_hash ).getBytes( "UTF-8" );
-		
-		String title = to_info.getTitle(); 
-		
-		if ( title.length() > MAX_TITLE_LENGTH ){
-			
-			title = title.substring( 0, MAX_TITLE_LENGTH );
-		}
-		
-		Map<String,Object> map = new HashMap<String,Object>();
-		
-		map.put( "d", title );
-		map.put( "r", new Long( Math.abs( to_info.getRand()%1000 )));
-		
-		String	tracker = to_info.getTracker();
-		
-		if ( tracker == null ){
-			
-			map.put( "h", to_info.getHash());
-			
-		}else{
-			
-			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 ));
-					}		
-					
-					byte[][] keys = getKeys( d );
-					
-					if ( keys[0] != null ){
-						map.put( "k", keys[0] );
-					}
-					if ( keys[1] != null ){
-						map.put( "w", keys[1] );
-					}
-					
-					String[] _tags = getTags( d );
-					
-					if ( _tags != null ){
-						map.put( "g", encodeTags( _tags ));
-					}
-				}
-			}catch( Throwable e ){		
-			}
-		}
-				
-		final Set<String>	my_tags = new HashSet<String>();
-		
-		try{
-			Download d = from_info.getRelatedToDownload();
-		
-			if ( d != null ){
-				
-				String[] _tags = getTags( d );
-			
-				if ( _tags != null ){
-					
-					map.put( "b", from_info.getRand() % 100 );
-					
-					map.put( "m", encodeTags( _tags ));
-					
-					for ( String tag: _tags ){
-						
-						my_tags.add( tag );
-					}
-				}
-			}
-		}catch( Throwable e ){		
-		}
-		
-		long	size = to_info.getSize();
-		
-		if ( size != 0 ){
-			
-			map.put( "s", new Long( size ));
-		}
-		
-		final byte[] map_bytes = BEncoder.encode( map );
-		
-		//System.out.println( "rcmsize=" + map_bytes.length );
-		
-		final int max_hits = 30;
-		
-		dht_plugin.get(
-				key_bytes,
-				"Content rel test: " + from_hash.substring( 0, 16 ),
-				DHTPlugin.FLAG_SINGLE_VALUE,
-				max_hits,
-				30*1000,
-				false,
-				false,
-				new DHTPluginOperationListener()
-				{
-					private boolean diversified;
-					private int		hits;
-					
-					private Set<String>	entries = new HashSet<String>();
-					
-					public void
-					starts(
-						byte[]				key )
-					{
-					}
-					
-					public boolean
-					diversified()
-					{
-						diversified = true;
-						
-						return( false );
-					}
-					
-					public void
-					valueRead(
-						DHTPluginContact	originator,
-						DHTPluginValue		value )
-					{
-						try{
-							Map<String,Object> map = (Map<String,Object>)BDecoder.decode( value.getValue());							
-							
-							DownloadInfo info = decodeInfo( map, from_info.getHash(), 1, false, entries );
-
-							try{
-								String[] r_tags = decodeTags((byte[]) map.get( "m" ));
-								
- 								if ( r_tags != null ){
-																		
-									Long	b = (Long)map.get( "b" );
-									
-										// don't remove tags from the set that we actually published
-									
-									if ( b == null || from_info.getRand()%100 != b%100 ){
-										
-										for ( String tag: r_tags ){
-											
-											synchronized( my_tags ){
-												
-												my_tags.remove( tag );
-											}
-										}
-									}
-								}
-							}catch( Throwable e ){
-							}						
-							
-							if ( info != null ){
-							
-								analyseResponse( info, null );
-							}
-						}catch( Throwable e ){							
-						}
-						
-						hits++;
-					}
-					
-					public void
-					valueWritten(
-						DHTPluginContact	target,
-						DHTPluginValue		value )
-					{
-						
-					}
-					
-					public void
-					complete(
-						byte[]				key,
-						boolean				timeout_occurred )
-					{
-							// if we have something to say prioritise it somewhat
-						
-						int f_cutoff = my_tags.size()>0?20:10;
-
-						try{
-							boolean	do_it;
-							
-							// System.out.println( from_hash + ": hits=" + hits + ", div=" + diversified );
-							
-							if ( diversified || hits >= f_cutoff ){
-								
-								do_it = false;
-								
-							}else if ( hits <= f_cutoff / 2 ){
-								
-								do_it = true;
-															
-							}else{
-														
-								do_it = RandomUtils.nextInt( hits - (f_cutoff/2) + 1 ) == 0;
-							}
-								
-							if ( do_it ){
-								
-								try{
-									dht_plugin.put(
-											key_bytes,
-											"Content rel: " +  from_hash.substring( 0, 16 ) + " -> " + to_hash.substring( 0, 16 ),
-											map_bytes,
-											DHTPlugin.FLAG_ANON,
-											new DHTPluginOperationListener()
-											{
-												public boolean
-												diversified()
-												{
-													return( true );
-												}
-												
-												public void 
-												starts(
-													byte[] 				key ) 
-												{
-												}
-												
-												public void
-												valueRead(
-													DHTPluginContact	originator,
-													DHTPluginValue		value )
-												{
-												}
-												
-												public void
-												valueWritten(
-													DHTPluginContact	target,
-													DHTPluginValue		value )
-												{
-												}
-												
-												public void
-												complete(
-													byte[]				key,
-													boolean				timeout_occurred )
-												{
-													publishNext();
-												}
-											});
-								}catch( Throwable e ){
-									
-									Debug.printStackTrace(e);
-									
-									publishNext();
-								}
-							}else{
-								
-								publishNext();
-							}
-						}finally{
-							
-							checkAlternativePubs( to_info, map_bytes, f_cutoff );
-						}
-					}
-				});
-	}
-		
-	private void
-	checkAlternativePubs(
-		DownloadInfo	to_info,
-		final byte[]	map_bytes,
-		final int		f_cutoff )
-	{
-		Download dl = to_info.getRelatedToDownload();
-		
-		if ( dl != null ){
-			
-			DiskManagerFileInfo[] files = dl.getDiskManagerFileInfo();
-			
-			List<Long>	sizes = new ArrayList<Long>();
-			
-			for ( DiskManagerFileInfo file: files ){
-				
-				long	size = file.getLength();
-				
-				if ( size >= FILE_ASSOC_MIN_SIZE ){
-					
-					sizes.add( size );
-				}
-			}
-			
-			if ( sizes.size() > 0 ){
-
-				try{
-					final String to_hash	= ByteFormatter.encodeString( to_info.getHash());
-	
-					final long selected_size = sizes.get( new Random().nextInt( sizes.size()));
-	
-					final byte[] key_bytes	= ( "az:rcm:size:assoc:" + selected_size ).getBytes( "UTF-8" );
-					
-					int	max_hits = 30;
-					
-					dht_plugin.get(
-							key_bytes,
-							"Content size rel test: " + to_hash.substring( 0, 16 ),
-							DHTPlugin.FLAG_SINGLE_VALUE,
-							max_hits,
-							30*1000,
-							false,
-							false,
-							new DHTPluginOperationListener()
-							{
-								private boolean diversified;
-								private int		hits;
-								
-								private Set<String>	entries = new HashSet<String>();
-								
-								public void
-								starts(
-									byte[]				key )
-								{
-								}
-								
-								public boolean
-								diversified()
-								{
-									diversified = true;
-									
-									return( false );
-								}
-								
-								public void
-								valueRead(
-									DHTPluginContact	originator,
-									DHTPluginValue		value )
-								{		
-									hits++;
-								}
-								
-								public void
-								valueWritten(
-									DHTPluginContact	target,
-									DHTPluginValue		value )
-								{
-									
-								}
-								
-								public void
-								complete(
-									byte[]				key,
-									boolean				timeout_occurred )
-								{
-									boolean	do_it;
-									
-									// System.out.println( from_hash + ": hits=" + hits + ", div=" + diversified );
-									
-									if ( diversified || hits >= f_cutoff ){
-										
-										do_it = false;
-										
-									}else if ( hits <= f_cutoff / 2 ){
-										
-										do_it = true;
-																	
-									}else{
-																
-										do_it = RandomUtils.nextInt( hits - ( f_cutoff / 2 ) + 1 ) == 0;
-									}
-										
-									if ( do_it ){
-										
-										try{
-											dht_plugin.put(
-												key_bytes,
-												"Content size rel: " +  selected_size + " -> " + to_hash.substring( 0, 16 ),
-												map_bytes,
-												DHTPlugin.FLAG_ANON,
-												new DHTPluginOperationListener()
-												{
-													public boolean
-													diversified()
-													{
-														return( true );
-													}
-													
-													public void 
-													starts(
-														byte[] 				key ) 
-													{
-													}
-													
-													public void
-													valueRead(
-														DHTPluginContact	originator,
-														DHTPluginValue		value )
-													{
-													}
-													
-													public void
-													valueWritten(
-														DHTPluginContact	target,
-														DHTPluginValue		value )
-													{
-													}
-													
-													public void
-													complete(
-														byte[]				key,
-														boolean				timeout_occurred )
-													{
-													}
-												});
-										}catch( Throwable e ){
-											
-											Debug.printStackTrace(e);
-										}
-									}
-								}
-							});
-				}catch( Throwable e ){
-					
-					Debug.out( e);
-				}
-			}
-		}
-	}
-	
-	private DownloadInfo
-	decodeInfo(
-		Map				map,
-		byte[]			from_hash,	// will be null for those trawled from teh local DHT
-		int				level,
-		boolean			explicit,
-		Set<String>		unique_keys )
-	{
-		try{
-			String	title = new String((byte[])map.get( "d" ), "UTF-8" );
-			
-			String	tracker	= null;
-			
-			byte[]	hash 	= (byte[])map.get( "h" );
-			
-			if ( hash == null ){
-				
-				tracker = new String((byte[])map.get( "t" ), "UTF-8" );
-			}
-			
-			int	rand = ((Long)map.get( "r" )).intValue();
-			
-			String	key = title + " % " + rand;
-			
-			synchronized( unique_keys ){
-			
-				if ( unique_keys.contains( key )){
-					
-					return( null );
-				}
-				
-				unique_keys.add( key );
-			}
-			
-			Long	l_size = (Long)map.get( "s" );
-			
-			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" );
-			
-			// 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);
-			}
-				
-			byte[] tracker_keys = (byte[])map.get( "k" );
-			byte[] ws_keys 		= (byte[])map.get( "w" );
-			
-			if ( tracker_keys != null && tracker_keys.length % 4 != 0 ){
-				
-				tracker_keys = null;
-			}
-			
-			if ( ws_keys != null && ws_keys.length % 4 != 0 ){
-				
-				ws_keys = null;
-			}
-			
-			byte[]	_tags = (byte[])map.get( "g" );
-			
-			String[] tags = decodeTags( _tags );
-					
-			return(
-				new DownloadInfo( 
-						from_hash, hash, title, rand, tracker, tracker_keys, ws_keys, tags, level, explicit, size, 
-						published==null?0:published.intValue(),
-						seeds_leechers,
-						(byte)(cnet==null?ContentNetwork.CONTENT_NETWORK_UNKNOWN:cnet.byteValue()))); 
-			
-		}catch( Throwable e ){
-			
-			return( null );
-		}
-	}
-	
-	public void
-	lookupAttributes(
-		final byte[]							from_hash,
-		final RelatedAttributeLookupListener	listener )
-	
-		throws ContentException
-	{
-		if ( from_hash == null ){
-			
-			throw( new ContentException( "hash is null" ));
-		}
-
-		if ( 	!initialisation_complete_sem.isReleasedForever() ||
-				( dht_plugin != null && dht_plugin.isInitialising())){
-			
-			AsyncDispatcher dispatcher = new AsyncDispatcher();
-	
-			dispatcher.dispatch(
-				new AERunnable()
-				{
-					public void
-					runSupport()
-					{
-						try{
-							initialisation_complete_sem.reserve();
-							
-							lookupAttributesSupport( from_hash, listener );
-							
-						}catch( ContentException e ){
-							
-							Debug.out( e );
-						}
-					}
-				});
-		}else{
-			
-			lookupAttributesSupport( from_hash, listener );
-		}
-	}
-	
-	private void
-	lookupAttributesSupport(
-		final byte[]							from_hash,
-		final RelatedAttributeLookupListener	listener )
-	
-		throws ContentException
-	{
-		try{
-			if ( !enabled ){
-				
-				throw( new ContentException( "rcm is disabled" ));
-			}
-		
-			if ( dht_plugin == null ){
-				
-				throw( new ContentException( "DHT plugin unavailable" ));
-			}
-			
-			final String from_hash_str	= ByteFormatter.encodeString( from_hash );
-			
-			final byte[] key_bytes	= ( "az:rcm:assoc:" + from_hash_str ).getBytes( "UTF-8" );
-			
-			String op_str = "Content attr read: " + from_hash_str.substring( 0, 16 );
-			
-			dht_plugin.get(
-					key_bytes,
-					op_str,
-					DHTPlugin.FLAG_SINGLE_VALUE,
-					512,
-					30*1000,
-					false,
-					true,
-					new DHTPluginOperationListener()
-					{
-						private Set<String>	tags = new HashSet<String>();
-						
-						public void
-						starts(
-							byte[]				key )
-						{
-							if ( listener != null ){
-								
-								try{
-									listener.lookupStart();
-									
-								}catch( Throwable e ){
-									
-									Debug.out( e );
-								}
-							}
-						}
-						
-						public boolean
-						diversified()
-						{
-							return( true );
-						}
-						
-						public void
-						valueRead(
-							DHTPluginContact	originator,
-							DHTPluginValue		value )
-						{
-							try{
-								Map<String,Object> map = (Map<String,Object>)BDecoder.decode( value.getValue());
-								
-								String[] r_tags = decodeTags((byte[]) map.get( "m" ));
-								
-								if ( r_tags != null ){
-									
-									for ( String tag: r_tags ){
-										
-										synchronized( tags ){
-											
-											if ( tags.contains( tag )){
-												
-												continue;
-											}
-											
-											tags.add( tag );
-										}
-										
-										listener.tagFound( tag );
-									}
-								}
-								
-							}catch( Throwable e ){	
-							}
-						}
-						
-						public void
-						valueWritten(
-							DHTPluginContact	target,
-							DHTPluginValue		value )
-						{
-							
-						}
-						
-						public void
-						complete(
-							byte[]				key,
-							boolean				timeout_occurred )
-						{
-							if ( listener != null ){
-								
-								try{
-									listener.lookupComplete();
-									
-								}catch( Throwable e ){
-									
-									Debug.out( e );
-								}
-							}
-						}				
-					});
-		}catch( Throwable e ){
-		
-			ContentException	ce;
-			
-			if ( ( e instanceof ContentException )){
-				
-				ce = (ContentException)e;
-				
-			}else{
-				ce = new ContentException( "Lookup failed", e );
-			}
-			
-			if ( listener != null ){
-				
-				try{
-					listener.lookupFailed( ce );
-					
-				}catch( Throwable f ){
-					
-					Debug.out( f );
-				}
-			}
-			
-			throw( ce );
-		}
-	}
-	
-	public void
-	lookupContent(
-		final byte[]						hash,
-		final RelatedContentLookupListener	listener )
-	
-		throws ContentException
-	{			
-		if ( hash == null ){
-			
-			throw( new ContentException( "hash is null" ));
-		}
-
-		if ( 	!initialisation_complete_sem.isReleasedForever() ||
-				( dht_plugin != null && dht_plugin.isInitialising())){
-			
-			AsyncDispatcher dispatcher = new AsyncDispatcher();
-	
-			dispatcher.dispatch(
-				new AERunnable()
-				{
-					public void
-					runSupport()
-					{
-						try{
-							initialisation_complete_sem.reserve();
-							
-							lookupContentSupport( hash, 0, true, listener );
-							
-						}catch( ContentException e ){
-							
-							Debug.out( e );
-						}
-					}
-				});
-		}else{
-			
-			lookupContentSupport( hash, 0, true, listener );
-		}
-	}
-	
-	public void
-	lookupContent(
-		final long							file_size,
-		final RelatedContentLookupListener	listener )
-	
-		throws ContentException
-	{
-		if ( file_size < FILE_ASSOC_MIN_SIZE ){
-			
-			throw( new ContentException( "file size is invalid - min=" + FILE_ASSOC_MIN_SIZE ));
-		}
-
-		if ( 	!initialisation_complete_sem.isReleasedForever() ||
-				( dht_plugin != null && dht_plugin.isInitialising())){
-			
-			AsyncDispatcher dispatcher = new AsyncDispatcher();
-	
-			dispatcher.dispatch(
-				new AERunnable()
-				{
-					public void
-					runSupport()
-					{
-						try{
-							initialisation_complete_sem.reserve();
-							
-							lookupContentSupport( file_size, listener );
-							
-						}catch( ContentException e ){
-							
-							Debug.out( e );
-						}
-					}
-				});
-		}else{
-			
-			lookupContentSupport( file_size, listener );
-		}
-	}
-	
-	private void
-	lookupContentSupport(
-		final long							file_size,
-		final RelatedContentLookupListener	listener )
-	
-		throws ContentException
-	{
-		if ( !enabled ){
-			
-			throw( new ContentException( "rcm is disabled" ));
-		}
-	
-		if ( dht_plugin == null ){
-			
-			throw( new ContentException( "DHT plugin unavailable" ));
-		}
-
-		try{
-			final byte[] key_bytes	= ( "az:rcm:size:assoc:" + file_size ).getBytes( "UTF-8" );
-
-				// we need something to use
-			
-			final byte[] from_hash = new SHA1Simple().calculateHash( key_bytes );
-			
-			String op_str = "Content rel read: size=" + file_size;
-
-			lookupContentSupport0( from_hash, key_bytes, op_str, 0, true, listener );
-			
-		}catch( ContentException e ){
-			
-			throw( e );
-			
-		}catch( Throwable e ){
-			
-			throw( new ContentException( "lookup failed", e ));
-		}
-	}
-	
-	private void
-	lookupContentSupport(
-		final byte[]						from_hash,
-		final int							level,
-		final boolean						explicit,
-		final RelatedContentLookupListener	listener )
-	
-		throws ContentException
-	{
-		if ( !enabled ){
-		
-			throw( new ContentException( "rcm is disabled" ));
-		}
-		
-		if ( dht_plugin == null ){
-			
-			throw( new ContentException( "DHT plugin unavailable" ));
-		}
-
-		try{
-			
-			final String from_hash_str	= ByteFormatter.encodeString( from_hash );
-		
-			final byte[] key_bytes	= ( "az:rcm:assoc:" + from_hash_str ).getBytes( "UTF-8" );
-			
-			String op_str = "Content rel read: " + from_hash_str.substring( 0, 16 );
-
-			lookupContentSupport0( from_hash, key_bytes, op_str, level, explicit, listener );
-			
-		}catch( ContentException e ){
-			
-			throw( e );
-			
-		}catch( Throwable e ){
-			
-			throw( new ContentException( "lookup failed", e ));
-		}
-	}
-			
-	private void
-	lookupContentSupport0(
-		final byte[]						from_hash,
-		final byte[]						key_bytes,
-		final String						op_str,
-		final int							level,
-		final boolean						explicit,
-		final RelatedContentLookupListener	listener )
-	
-		throws ContentException
-	{
-		try{
-			final int max_hits = 30;
-			
-			dht_plugin.get(
-					key_bytes,
-					op_str,
-					DHTPlugin.FLAG_SINGLE_VALUE,
-					max_hits,
-					60*1000,
-					false,
-					true,
-					new DHTPluginOperationListener()
-					{
-						private Set<String>	entries = new HashSet<String>();
-						
-						private RelatedContentManagerListener manager_listener = 
-							new RelatedContentManagerListener()
-							{
-							private Set<RelatedContent>	content_list = new HashSet<RelatedContent>();
-							
-								public void
-								contentFound(
-									RelatedContent[]	content )
-								{
-									handle( content );
-								}
-	
-								public void
-								contentChanged(
-									RelatedContent[]	content )
-								{
-									handle( content );
-								}
-								
-								public void 
-								contentRemoved(
-									RelatedContent[] 	content ) 
-								{
-								}
-								
-								public void
-								contentChanged()
-								{									
-								}
-								
-								public void
-								contentReset()
-								{
-								}
-								
-								private void
-								handle(
-									RelatedContent[]	content )
-								{
-									List<RelatedContent>	new_content = new ArrayList<RelatedContent>( content.length );
-									
-									synchronized( content_list ){
-										
-										for ( RelatedContent rc: content ){
-										
-											if ( !content_list.contains( rc )){
-											
-												new_content.add( rc );
-											}
-										}
-										
-										if ( new_content.size() == 0 ){
-											
-											return;
-										}
-										
-										content_list.addAll( new_content );
-									}
-									
-									listener.contentFound( new_content.toArray( new RelatedContent[new_content.size()] ));
-								}
-							};
-						
-						public void
-						starts(
-							byte[]				key )
-						{
-							if ( listener != null ){
-								
-								try{
-									listener.lookupStart();
-									
-								}catch( Throwable e ){
-									
-									Debug.out( e );
-								}
-							}
-						}
-						
-						public boolean
-						diversified()
-						{
-							return( true );
-						}
-						
-						public void
-						valueRead(
-							DHTPluginContact	originator,
-							DHTPluginValue		value )
-						{
-							try{
-								Map<String,Object> map = (Map<String,Object>)BDecoder.decode( value.getValue());
-								
-								DownloadInfo info = decodeInfo( map, from_hash, level+1, explicit, entries );
-								
-								if ( info != null ){
-									
-									analyseResponse( info, listener==null?null:manager_listener );
-								}
-							}catch( Throwable e ){	
-							}
-						}
-						
-						public void
-						valueWritten(
-							DHTPluginContact	target,
-							DHTPluginValue		value )
-						{
-							
-						}
-						
-						public void
-						complete(
-							byte[]				key,
-							boolean				timeout_occurred )
-						{
-							if ( listener != null ){
-								
-								try{
-									listener.lookupComplete();
-									
-								}catch( Throwable e ){
-									
-									Debug.out( e );
-								}
-							}
-						}				
-					});
-		}catch( Throwable e ){
-		
-			ContentException	ce;
-			
-			if ( ( e instanceof ContentException )){
-				
-				ce = (ContentException)e;
-				
-			}else{
-				ce = new ContentException( "Lookup failed", e );
-			}
-			
-			if ( listener != null ){
-				
-				try{
-					listener.lookupFailed( ce );
-					
-				}catch( Throwable f ){
-					
-					Debug.out( f );
-				}
-			}
-			
-			throw( ce );
-		}
-	}
-	
-	protected void
-	popuplateSecondaryLookups(
-		ContentCache	content_cache )
-	{
-		Random rand = new Random();
-
-		secondary_lookups.clear();
-		
-			// stuff in a couple primarys
-		
-		List<DownloadInfo> primaries = download_info_map.values();
-		
-		int	primary_count = primaries.size();
-		
-		int	primaries_to_add;
-		
-		if ( primary_count < 2 ){
-			
-			primaries_to_add = 0;
-			
-		}else if ( primary_count < 5 ){
-			
-			if ( rand.nextInt(4) == 0 ){
-				
-				primaries_to_add = 1;
-				
-			}else{
-				
-				primaries_to_add = 0;
-			}
-		}else if ( primary_count < 10 ){
-			
-			primaries_to_add = 1;
-			
-		}else{
-			
-			primaries_to_add = 2;
-		}
-		
-		if ( primaries_to_add > 0 ){
-			
-			Set<DownloadInfo> added = new HashSet<DownloadInfo>();
-			
-			for (int i=0;i<primaries_to_add;i++){
-				
-				DownloadInfo info = primaries.get( rand.nextInt( primaries.size()));
-				
-				if ( !added.contains( info )){
-					
-					added.add( info );
-					
-					secondary_lookups.addLast(new SecondaryLookup(info.getHash(), info.getLevel()));
-				}
-			}
-		}
-		
-		Map<String,DownloadInfo>		related_content			= content_cache.related_content;
-
-		Iterator<DownloadInfo> it = related_content.values().iterator();
-		
-		List<DownloadInfo> secondary_cache_temp = new ArrayList<DownloadInfo>( related_content.size());
-
-		while( it.hasNext()){
-			
-			DownloadInfo di = it.next();
-			
-			if ( di.getHash() != null && di.getLevel() < max_search_level ){
-					
-				secondary_cache_temp.add( di );
-			}
-		}
-						
-		final int cache_size = Math.min( secondary_cache_temp.size(), SECONDARY_LOOKUP_CACHE_MAX - secondary_lookups.size());
-		
-		if ( cache_size > 0 ){
-						
-			for( int i=0;i<cache_size;i++){
-				
-				int index = rand.nextInt( secondary_cache_temp.size());
-				
-				DownloadInfo x = secondary_cache_temp.get( index );
-				
-				secondary_cache_temp.set( index, secondary_cache_temp.get(i));
-				
-				secondary_cache_temp.set( i, x );
-			}
-			
-			for ( int i=0;i<cache_size;i++){
-				
-				DownloadInfo x = secondary_cache_temp.get(i);
-				
-				secondary_lookups.addLast(new SecondaryLookup(x.getHash(), x.getLevel()));
-			}
-		}
-	}
-	
-	protected void
-	secondaryLookup()
-	{
-		SecondaryLookup sl;
-		
-		long	now = SystemTime.getMonotonousTime();
-		
-		synchronized( this ){
-			
-			if ( secondary_lookup_in_progress ){
-				
-				return;
-			}
-		
-			if ( now - secondary_lookup_complete_time < SECONDARY_LOOKUP_PERIOD ){
-				
-				return;
-			}
-			
-			if ( secondary_lookups.size() == 0 ){
-			
-				ContentCache cc = content_cache==null?null:content_cache.get();
-
-				if ( cc == null ){
-					
-						// this will populate the cache
-					
-					cc = loadRelatedContent();
-					
-				}else{
-					
-					popuplateSecondaryLookups( cc );
-				}
-			}
-
-			if ( secondary_lookups.size() == 0 ){
-				
-				return;
-			}
-						
-			sl = secondary_lookups.removeFirst();
-
-			secondary_lookup_in_progress = true;
-		}
-		
-		try{
-			lookupContentSupport( 
-				sl.getHash(),
-				sl.getLevel(),
-				false,
-				new RelatedContentLookupListener()
-				{
-					public void
-					lookupStart()
-					{	
-					}
-					
-					public void
-					contentFound(
-						RelatedContent[]	content )
-					{	
-					}
-					
-					public void
-					lookupComplete()
-					{
-						next();
-					}
-					
-					public void
-					lookupFailed(
-						ContentException 	error )
-					{
-						next();
-					}
-					
-					protected void
-					next()
-					{
-						final SecondaryLookup next_sl;
-						
-						synchronized( RelatedContentManager.this ){
-							
-							if ( secondary_lookups.size() == 0 ){
-								
-								secondary_lookup_in_progress = false;
-								
-								secondary_lookup_complete_time = SystemTime.getMonotonousTime();
-								
-								return;
-								
-							}else{
-								
-								next_sl = secondary_lookups.removeFirst();
-							}
-						}
-						
-						final RelatedContentLookupListener listener = this;
-						
-						SimpleTimer.addEvent(
-							"RCM:SLDelay",
-							SystemTime.getOffsetTime( 30*1000 ),
-							new TimerEventPerformer()
-							{
-								public void 
-								perform(
-									TimerEvent event ) 
-								{
-									try{					
-										lookupContentSupport( next_sl.getHash(), next_sl.getLevel(), false, listener );
-										
-									}catch( Throwable e ){
-										
-										Debug.out( e );
-										
-										synchronized( RelatedContentManager.this ){
-											
-											secondary_lookup_in_progress = false;
-											
-											secondary_lookup_complete_time = SystemTime.getMonotonousTime();
-										}
-									}
-								}
-							});
-					}
-				});
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			synchronized( this ){
-				
-				secondary_lookup_in_progress = false;
-				
-				secondary_lookup_complete_time = now;
-			}
-		}
-	}
-	
-	protected void
-	contentChanged(
-		final DownloadInfo		info )
-	{
-		setConfigDirty();
-		
-		content_change_dispatcher.dispatch(
-			new AERunnable()
-			{
-				public void
-				runSupport()
-				{
-					for ( RelatedContentManagerListener l: listeners ){
-						
-						try{
-							l.contentChanged( new RelatedContent[]{ info });
-							
-						}catch( Throwable e ){
-							
-							Debug.out( e );
-						}
-					}
-				}
-			});
-	}
-	
-	protected void
-	contentChanged(
-		boolean	is_dirty )
-	{
-		if ( is_dirty ){
-		
-			setConfigDirty();
-		}
-		
-		content_change_dispatcher.dispatch(
-			new AERunnable()
-			{
-				public void
-				runSupport()
-				{
-					for ( RelatedContentManagerListener l: listeners ){
-						
-						try{
-							l.contentChanged();
-							
-						}catch( Throwable e ){
-							
-							Debug.out( e );
-						}
-					}
-				}
-			});
-	}
-	
-	public void
-	delete(
-		RelatedContent[]	content )
-	{
-		synchronized( this ){
-			
-			ContentCache content_cache = loadRelatedContent();
-			
-			delete( content, content_cache, true );
-		}
-	}
-	
-	protected void
-	delete(
-		final RelatedContent[]	content,
-		ContentCache			content_cache,
-		boolean					persistent )
-	{
-		if ( persistent ){
-		
-			addPersistentlyDeleted( content );
-		}
-		
-		Map<String,DownloadInfo> related_content = content_cache.related_content;
-
-		Iterator<DownloadInfo> it = related_content.values().iterator();
-		
-		while( it.hasNext()){
-		
-			DownloadInfo di = it.next();
-			
-			for ( RelatedContent c: content ){
-				
-				if ( c == di ){
-					
-					it.remove();
-					
-					if ( di.isUnread()){
-						
-						decrementUnread();
-					}
-				}
-			}
-		}
-		
-		ByteArrayHashMapEx<ArrayList<DownloadInfo>> related_content_map = content_cache.related_content_map;
-		
-		List<byte[]> delete = new ArrayList<byte[]>();
-		
-		for ( byte[] key: related_content_map.keys()){
-			
-			ArrayList<DownloadInfo>	infos = related_content_map.get( key );
-			
-			for ( RelatedContent c: content ){
-
-				if ( infos.remove( c )){
-					
-					if ( infos.size() == 0 ){
-						
-						delete.add( key );
-						
-						break;
-					}
-				}
-			}
-		}
-		
-		for ( byte[] key: delete ){
-			
-			related_content_map.remove( key );
-		}
-		
-		setConfigDirty();
-		
-		content_change_dispatcher.dispatch(
-				new AERunnable()
-				{
-					public void
-					runSupport()
-					{
-						for ( RelatedContentManagerListener l: listeners ){
-							
-							try{
-								l.contentRemoved( content );
-
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-						}
-					}
-				});
-	}
-	
-	protected String
-	getPrivateInfoKey(
-		RelatedContent		info )
-	{
-		return( info.getTitle() + ":" + info.getTracker());
-	}
-	
-	protected void
-	analyseResponse(
-		DownloadInfo						to_info,
-		final RelatedContentManagerListener	listener )
-	{
-		try{			
-			synchronized( this ){
-				
-				byte[] target = to_info.getHash();
-				
-				String	key;
-				
-				if ( target != null ){
-					
-					if ( download_info_map.containsKey( target )){
-						
-							// target refers to downoad we already have
-						
-						return;
-					}
-					
-					key = Base32.encode( target );
-					
-				}else{
-					
-					key = getPrivateInfoKey( to_info );
-					
-					if ( download_priv_set.contains( key )){
-						
-							// target refers to downoad we already have
-						
-						return;
-					}
-				}
-				
-				if ( isPersistentlyDeleted( to_info )){
-					
-					return;
-				}
-				
-				ContentCache	content_cache = loadRelatedContent();
-				
-				DownloadInfo	target_info = null;
-				
-				boolean	changed_content = false;
-				boolean	new_content 	= false;
-				
-				
-				target_info = content_cache.related_content.get( key );
-				
-				if ( target_info == null ){
-								
-					if ( enoughSpaceFor( content_cache, to_info )){
-					
-						target_info = to_info;
-
-						content_cache.related_content.put( key, target_info );
-						
-						byte[] from_hash = to_info.getRelatedToHash();
-						
-						ArrayList<DownloadInfo> links = content_cache.related_content_map.get( from_hash );
-						
-						if ( links == null ){
-							
-							links = new ArrayList<DownloadInfo>(1);
-							
-							content_cache.related_content_map.put( from_hash, links );
-						}
-						
-						links.add( target_info );
-						
-						links.trimToSize();
-						
-						target_info.setPublic( content_cache );
-						
-						if ( secondary_lookups.size() < SECONDARY_LOOKUP_CACHE_MAX ){
-							
-							byte[]	hash 	= target_info.getHash();
-							int		level	= target_info.getLevel();
-							
-							if ( hash != null && level < max_search_level ){
-								
-								secondary_lookups.add( new SecondaryLookup( hash, level ));
-							}
-						}
-						
-						new_content = true;
-						
-					}else{
-						
-						transient_info_cache.put( key, to_info );
-					}
-				}else{
-					
-						// we already know about this, see if new info
-					
-					changed_content = target_info.addInfo( to_info );
-				}
-
-				if ( target_info != null ){
-					
-					final RelatedContent[]	f_target 	= new RelatedContent[]{ target_info };
-					final boolean			f_change	= changed_content;
-					
-					final boolean something_changed = changed_content || new_content;
-							
-					if ( something_changed ){
-					
-						setConfigDirty();
-					}
-					
-					content_change_dispatcher.dispatch(
-						new AERunnable()
-						{
-							public void
-							runSupport()
-							{
-								if ( something_changed ){
-									
-									for ( RelatedContentManagerListener l: listeners ){
-										
-										try{
-											if ( f_change ){
-												
-												l.contentChanged( f_target );
-												
-											}else{
-												
-												l.contentFound( f_target );
-											}
-										}catch( Throwable e ){
-											
-											Debug.out( e );
-										}
-									}
-								}
-								
-								if ( listener != null ){
-									
-									try{
-										if ( f_change ){
-											
-											listener.contentChanged( f_target );
-											
-										}else{
-											
-											listener.contentFound( f_target );
-										}
-									}catch( Throwable e ){
-										
-										Debug.out( e );
-									}
-								}
-							}
-						});
-				}
-			}
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-	}
-	
-	protected boolean
-	enoughSpaceFor(
-		ContentCache	content_cache,
-		DownloadInfo	fi )
-	{
-		Map<String,DownloadInfo> related_content = content_cache.related_content;
-		
-		if ( related_content.size() < max_results + temporary_space.get()){
-			
-			return( true );
-		}
-		
-		Iterator<Map.Entry<String,DownloadInfo>>	it = related_content.entrySet().iterator();
-				
-		int	max_level 		= fi.getLevel();
-		
-			// delete oldest at highest level >= level with minimum rank
-	
-		Map<Integer,DownloadInfo>	oldest_per_rank = new HashMap<Integer, DownloadInfo>();
-		
-		int	min_rank 	= Integer.MAX_VALUE;
-		int	max_rank	= -1;
-		
-		while( it.hasNext()){
-			
-			Map.Entry<String,DownloadInfo> entry = it.next();
-			
-			DownloadInfo info = entry.getValue();
-			
-			if ( info.isExplicit()){
-				
-				continue;
-			}
-			
-			int	info_level = info.getLevel();
-			
-			if ( info_level >= max_level ){
-				
-				if ( info_level > max_level ){
-					
-					max_level = info_level;
-					
-					min_rank 	= Integer.MAX_VALUE;
-					max_rank	= -1;
-					
-					oldest_per_rank.clear();
-				}
-				
-				int	rank = info.getRank();
-				
-				if ( rank < min_rank ){
-					
-					min_rank = rank;
-					
-				}else if ( rank > max_rank ){
-					
-					max_rank = rank;
-				}
-				
-				DownloadInfo oldest = oldest_per_rank.get( rank );
-				
-				if ( oldest == null ){
-					
-					oldest_per_rank.put( rank, info );
-					
-				}else{
-					
-					if ( info.getLastSeenSecs() < oldest.getLastSeenSecs()){
-						
-						oldest_per_rank.put( rank, info );
-					}
-				}
-			}
-		}
-		
-		DownloadInfo to_remove = oldest_per_rank.get( min_rank );
-		
-		if ( to_remove != null ){
-					
-			delete( new RelatedContent[]{ to_remove }, content_cache, false );
-			
-			return( true );
-		}
-		
-			// we don't want high-ranked entries to get stuck there and prevent newer stuff from getting in and rising up
-		
-		if ( max_level == 1 ){
-			
-			to_remove = oldest_per_rank.get( max_rank );
-			
-			if ( to_remove != null ){
-				
-				int	now_secs = (int)( SystemTime.getCurrentTime()/1000 );
-				
-					// give it a day at the top
-				
-				if ( now_secs - to_remove.getLastSeenSecs() >= 24*60*60 ){
-					
-					delete( new RelatedContent[]{ to_remove }, content_cache, false );
-					
-					return( true );
-				}
-			}
-		}
-		
-		return( false );
-	}
-	
-	public RelatedContent[]
-	getRelatedContent()
-	{
-		synchronized( this ){
-
-			ContentCache	content_cache = loadRelatedContent();
-			
-			return( content_cache.related_content.values().toArray( new DownloadInfo[ content_cache.related_content.size()]));
-		}
-	}
-	
-	private List<DownloadInfo>
-  	getRelatedContentAsList()
-  	{
-  		synchronized( this ){
-
-  			ContentCache	content_cache = loadRelatedContent();
-  			
-  			return( new ArrayList<DownloadInfo>( content_cache.related_content.values()));
-  		}
-  	}
-	
-	public void
-	reset()
-	{
-		reset( true );
-	}
-	
-	protected void
-	reset(
-		boolean	reset_perm_dels )
-	{
-		synchronized( this ){
-			
-			ContentCache cc = content_cache==null?null:content_cache.get();
-			
-			if ( cc == null ){
-				
-				FileUtil.deleteResilientConfigFile( CONFIG_FILE );
-				
-			}else{
-			
-				cc.related_content 		= new HashMap<String,DownloadInfo>();
-				cc.related_content_map 	= new ByteArrayHashMapEx<ArrayList<DownloadInfo>>();
-			}
-			
-			download_infos1.clear();
-			download_infos2.clear();
-			
-			List<DownloadInfo> list = download_info_map.values();
-			
-			download_infos1.addAll( list );
-			download_infos2.addAll( list );
-			
-			Collections.shuffle( download_infos1 );
-			
-			total_unread.set( 0 );
-			
-			if ( reset_perm_dels ){
-			
-				resetPersistentlyDeleted();
-			}
-			
-			setConfigDirty();
-		}
-		
-		content_change_dispatcher.dispatch(
-				new AERunnable()
-				{
-					public void
-					runSupport()
-					{
-						for ( RelatedContentManagerListener l: listeners ){
-							
-							l.contentReset();
-						}
-					}
-				});
-	}
-	
-	private String
-	fixupTerm(
-		String	term )
-	{
-		if ( term == null ){
-			
-			return( null );
-		}
-		
-		// if someone has a | in the expression then they probably mean "or" so to work with the following we remove any spaces
-		// either side of it
-	
-		if ( term.contains( "|" )){
-			
-			while( term.contains( " |" )){
-				
-				term = term.replaceAll( " \\|", "|" );
-			}
-			
-		while( term.contains( "| " )){
-				
-				term = term.replaceAll( "\\| ", "|" );
-			}
-		}
-		
-		return( term );
-	}
-	
-	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'
-		
-		String[]	 bits = Constants.PAT_SPLIT_SPACE.split(term.toLowerCase());
-
-		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{
-						if ( !RegExUtil.mightBeEvil( bit )){
-						
-							bit_patterns[i] = Pattern.compile( bit, Pattern.CASE_INSENSITIVE );
-						}
-					}catch( Throwable e ){
-					}
-				}else if ( bit.contains( "|" )){
-					
-					if ( !bit.contains( "tag:" )){
-						
-						try{
-							if ( !RegExUtil.mightBeEvil( bit )){
-							
-								bit_patterns[i] = Pattern.compile( bit, Pattern.CASE_INSENSITIVE );
-							}
-						}catch( Throwable e ){
-						}
-					}
-				}
-			}
-		}
-		
-		Map<String,RelatedContent>	result = new HashMap<String,RelatedContent>();
-		
-		Iterator<DownloadInfo>	it1 = getDHTInfos().iterator();
-		
-		Iterator<DownloadInfo>	it2;
-		
-		synchronized( this ){
-		
-			it2 = new ArrayList<DownloadInfo>( transient_info_cache.values()).iterator();
-		}
-
-		Iterator<DownloadInfo>	it3 = getRelatedContentAsList().iterator();
-
-		for ( Iterator _it: new Iterator[]{ it1, it2, it3 }){
-			
-			Iterator<DownloadInfo> it = (Iterator<DownloadInfo>)_it;	
-			
-			while( it.hasNext()){
-				
-				DownloadInfo c = it.next();
-				
-				String title 	= c.getTitle();
-				String lc_title = c.getTitle().toLowerCase();
-				
-				boolean	match 			= true;
-				boolean	at_least_one 	= false;
-				
-				if ( title.equalsIgnoreCase( term ) && term.trim().length() > 0 ){
-					
-						// pick up a direct match regardless of anything else
-					
-					at_least_one = true;
-					
-				}else{
-					
-					for (int i=0;i<bits.length;i++){
-						
-						String bit = bits[i];
-						
-						if ( bit.length() > 0 ){
-							
-							boolean	hit;
-							
-							if ( bit_patterns[i] == null ){
-							
-								String[]	sub_bits = bit.split("\\|");
-								
-								hit = false;
-								
-								for ( String sub_bit: sub_bits ){
-
-									if ( sub_bit.startsWith( "tag:" )){
-										
-										String[] tags = c.getTags();
-										
-										hit = false;
-										
-										if ( tags != null && tags.length > 0 ){
-											
-											String	target_tag = sub_bit.substring( 4 ).toLowerCase( Locale.US );
-											
-											target_tag = unescapeTag( target_tag );
-											
-											target_tag = truncateTag( target_tag );
-											
-											for ( String t: tags ){
-												
-												if ( t.startsWith( target_tag )){
-													
-													hit = true;
-													
-													break;
-												}
-											}
-										}
-									}else{
-									
-										hit = lc_title.contains( sub_bit );
-									}
-									
-									if ( hit ){
-										
-										break;
-									}
-								}
-							}else{
-							
-								hit = bit_patterns[i].matcher( lc_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 ){
-					
-					byte[]	hash = c.getHash();
-					
-					String key;
-					
-					if ( hash != null ){
-						
-						key = Base32.encode( hash );
-						
-					}else{
-			
-						key = getPrivateInfoKey( c );
-					}
-					
-					result.put( key, c );
-				}
-			}
-		}
-		
-		return( new ArrayList<RelatedContent>( result.values()));
-	}
-	
-	public SearchInstance
-	searchRCM(
-		Map<String,Object>		search_parameters,
-		SearchObserver			_observer )
-	
-		throws SearchException
-	{
-		initialisation_complete_sem.reserve();
-
-		if ( !enabled ){
-			
-			throw( new SearchException( "rcm is disabled" ));
-		}
-		
-		//dump();
-		
-		final MySearchObserver observer = new MySearchObserver( _observer );
-		
-		final String	term = fixupTerm( (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>	hashes = new HashSet<String>();
-					
-					try{				
-						List<RelatedContent>	matches = matchContent( term );
-							
-						for ( final RelatedContent c: matches ){
-							
-							final byte[] hash = c.getHash();
-							
-							if ( hash == null ){
-								
-								continue;
-							}
-							
-							hashes.add( Base32.encode( hash ));
-							
-							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_HASH ){
-											
-											return( hash );
-											
-										}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( UrlUtils.getMagnetURI( hash ));
-											}
-										}else if ( property_name == RCM_SEARCH_PROPERTY_CONTENT_NETWORK ){
-											
-											return( c.getContentNetwork());
-											
-										}else if ( property_name == RCM_SEARCH_PROPERTY_TRACKER_KEYS ){
-											
-											return( c.getTrackerKeys());
-											
-										}else if ( property_name == RCM_SEARCH_PROPERTY_WEB_SEED_KEYS ){
-											
-											return( c.getWebSeedKeys());
-											
-										}else if ( property_name == RCM_SEARCH_PROPERTY_TAGS ){
-
-											return( c.getTags());
-										}
-										
-										return( null );
-									}
-								};
-								
-							observer.resultReceived( si, result );
-						}
-					}finally{
-						
-						try{	
-							final List<DistributedDatabaseContact> 	initial_hinted_contacts = searchForeignBlooms( term );
-							final Set<DistributedDatabaseContact>	extra_hinted_contacts	= new HashSet<DistributedDatabaseContact>();
-							
-							Collections.shuffle( initial_hinted_contacts );
-							
-							// test injection of local 
-							// hinted_contacts.add( 0, ddb.getLocalContact());
-							
-							final LinkedList<DistributedDatabaseContact>	contacts_to_search = new LinkedList<DistributedDatabaseContact>();
-
-							final Map<InetSocketAddress,DistributedDatabaseContact> contact_map = new HashMap<InetSocketAddress, DistributedDatabaseContact>();
-														
-							for ( DistributedDatabaseContact c: initial_hinted_contacts ){
-								
-									// stick in map so non-hinted get removed below, but interleave later
-								
-								contact_map.put( c.getAddress(), c );
-							}
-							
-							DHT[]	dhts = dht_plugin.getDHTs();
-								
-							for ( DHT dht: dhts ){
-							
-								DHTTransport transport = dht.getTransport();
-								
-								if ( transport.isIPV6()){
-									
-									continue;
-								}
-								
-								int	network = transport.getNetwork();
-								
-								if ( SEARCH_CVS_ONLY && network != DHT.NW_CVS ){
-									
-									logSearch( "Search: ignoring main DHT" );
-
-									continue;
-								}
-								
-								DHTTransportContact[] contacts = dht.getTransport().getReachableContacts();
-								
-								Collections.shuffle( Arrays.asList( contacts ));
-																
-								for ( DHTTransportContact dc: contacts ){
-											
-									InetSocketAddress address = dc.getAddress();
-									
-									if ( !contact_map.containsKey( address )){
-										
-										try{
-											DistributedDatabaseContact c = 
-												ddb.importContact( 
-													address, 
-													DHTTransportUDP.PROTOCOL_VERSION_MIN, 
-													network==DHT.NW_CVS?DistributedDatabase.DHT_CVS:DistributedDatabase.DHT_MAIN );
-											
-											contact_map.put( address, c );
-											
-											contacts_to_search.add( c );
-											
-										}catch( Throwable e ){
-											
-										}
-									}
-								}
-							}
-							
-							if ( contact_map.size() < MAX_REMOTE_SEARCH_CONTACTS ){
-								
-									// back fill with less reliable contacts if required
-								
-								for ( DHT dht: dhts ){
-									
-									DHTTransport transport = dht.getTransport();
-									
-									if ( transport.isIPV6()){
-										
-										continue;
-									}
-									
-									int	network = transport.getNetwork();
-									
-									if ( SEARCH_CVS_ONLY && network != DHT.NW_CVS ){
-										
-										logSearch( "Search: ignoring main DHT" );
-
-										continue;
-									}
-									
-									DHTTransportContact[] contacts = dht.getTransport().getRecentContacts();
-	
-									for ( DHTTransportContact dc: contacts ){
-										
-										InetSocketAddress address = dc.getAddress();
-										
-										if ( !contact_map.containsKey( address )){
-											
-											try{
-												DistributedDatabaseContact c = ddb.importContact( address, DHTTransportUDP.PROTOCOL_VERSION_MIN, network==DHT.NW_CVS?DistributedDatabase.DHT_CVS:DistributedDatabase.DHT_MAIN );
-												
-												contact_map.put( address, c );
-												
-												contacts_to_search.add( c );
-																				
-												if ( contact_map.size() >= MAX_REMOTE_SEARCH_CONTACTS ){
-													
-													break;
-												}
-											}catch( Throwable e ){
-												
-											}
-										}
-									}
-									
-									if ( contact_map.size() >= MAX_REMOTE_SEARCH_CONTACTS ){
-										
-										break;
-									}
-								}
-							}
-							
-								// interleave hinted ones so we get some variety
-							
-							int	desired_pos = 0;
-							
-							for ( DistributedDatabaseContact dc: initial_hinted_contacts ){
-								
-								if ( desired_pos < contacts_to_search.size()){
-									
-									contacts_to_search.add( desired_pos, dc );
-								
-									desired_pos += 2;
-									
-								}else{
-									
-									contacts_to_search.addLast( dc );
-								}
-							}
-
-							
-							long	start		= SystemTime.getMonotonousTime();
-							long	max			= MAX_REMOTE_SEARCH_MILLIS;
-							
-							final AESemaphore	sem = new AESemaphore( "RCM:rems" );
-							
-							int	sent = 0;
-							
-							final int[]			done = {0};
-							
-							logSearch( "Search starts: contacts=" + contacts_to_search.size() + ", hinted=" + initial_hinted_contacts.size());
-							
-							while( true ){
-										
-									// hard limit of total results found and overall elapsed
-								
-								if ( 	observer.getResultCount() >= 200 || 
-										SystemTime.getMonotonousTime() - start >= max ){
-									
-									logSearch( "Hard limit exceeded" );
-									
-									return;
-								}
-
-								if ( sent >= MAX_REMOTE_SEARCH_CONTACTS ){
-									
-									logSearch( "Max contacts searched" );
-									
-									break;
-								}
-
-								final DistributedDatabaseContact contact_to_search;
-								
-								synchronized( contacts_to_search ){
-									
-									if ( contacts_to_search.isEmpty()){
-										
-										logSearch( "Contacts exhausted" );
-										
-										break;
-										
-									}else{
-										
-										contact_to_search = contacts_to_search.removeFirst();
-									}
-								}
-																
-								new AEThread2( "RCM:rems", true )
-								{
-									public void
-									run()
-									{
-										try{
-											logSearch( "Searching " + contact_to_search.getAddress());
-											
-											List<DistributedDatabaseContact> extra_contacts = sendRemoteSearch( si, hashes, contact_to_search, term, observer );
-													
-											if ( extra_contacts == null ){
-												
-												logSearch( "    " + contact_to_search.getAddress() + " failed" );
-												
-												foreignBloomFailed( contact_to_search );
-												
-											}else{
-												
-												String	type;
-												
-												if ( initial_hinted_contacts.contains( contact_to_search )){
-													type = "i";
-												}else if ( extra_hinted_contacts.contains( contact_to_search )){
-													type = "e";
-												}else{
-													type = "n";
-												}
-												logSearch( "    " + contact_to_search.getAddress() + " OK " + type + " - additional=" + extra_contacts.size());
-												
-													// insert results from more predictable nodes after the less predictable ones
-												
-												synchronized( contacts_to_search ){
-													
-													int	insert_point = 0;
-													
-													if ( type.equals( "i" )){
-														
-														for (int i=0;i<contacts_to_search.size();i++){
-															
-															if ( extra_hinted_contacts.contains(contacts_to_search.get(i))){
-																
-																insert_point = i+1;
-															}
-														}
-													}
-													
-													for ( DistributedDatabaseContact c: extra_contacts ){
-														
-														InetSocketAddress address = c.getAddress();
-						
-														if ( !contact_map.containsKey( address )){
-															
-															logSearch( "        additional target: " + address );
-															
-															extra_hinted_contacts.add( c );
-															
-															contact_map.put( address, c );
-															
-															contacts_to_search.add( insert_point, c );
-														}
-													}
-												}
-											}
-										}finally{
-											
-											synchronized( done ){
-											
-												done[0]++;
-											}
-											
-											sem.release();
-										}
-									}
-								}.start();
-								
-								sent++;
-								
-								synchronized( done ){
-									
-									if ( done[0] >= MAX_REMOTE_SEARCH_CONTACTS / 2 ){
-										
-										logSearch( "Switching to reduced time limit (1)" );
-										
-											// give another 5 secs for results to come in
-										
-										start		= SystemTime.getMonotonousTime();
-										max			= REDUCED_REMOTE_SEARCH_MILLIS;
-										
-										break;
-									}
-								}
-								
-								if ( sent > 10 ){
-									
-										// rate limit a bit after the first 10
-									
-									try{
-										Thread.sleep( 250 );
-										
-									}catch( Throwable e ){
-									}
-								}
-							}
-							
-							logSearch( "Request dispatch complete: sent=" + sent + ", done=" + done[0] );
-							
-							for ( int i=0;i<sent;i++ ){
-								
-								if ( done[0] > sent*9/10 ){
-									
-									logSearch( "9/10ths replied (" + done[0] + "/" + sent + "), done" );
-									
-									break;
-								}
-								
-								long	remaining = ( start + max ) - SystemTime.getMonotonousTime();
-								
-								if ( 	remaining > REDUCED_REMOTE_SEARCH_MILLIS &&
-										done[0] >= MAX_REMOTE_SEARCH_CONTACTS / 2 ){
-									
-									logSearch( "Switching to reduced time limit (2)" );
-									
-										// give another 5 secs for results to come in
-									
-									start		= SystemTime.getMonotonousTime();
-									max			= REDUCED_REMOTE_SEARCH_MILLIS;
-								}
-								
-								if ( remaining > 0 ){
-									
-									sem.reserve( 250 );
-									
-								}else{
-									
-									logSearch( "Time exhausted" );
-									
-									break;
-								}
-							}
-						}finally{
-								
-							logSearch( "Search complete" );
-							
-							observer.complete();
-						}
-					}
-				}
-			}.start();
-		}
-		
-		return( si );
-	}
-	
-	protected List<DistributedDatabaseContact>
-	sendRemoteSearch(
-		SearchInstance					si,
-		Set<String>						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( null );
-			}
-			
-			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" );
-				
-				final byte[] hash = (byte[])map.get( "h" );
-				
-				if ( hash == null ){
-					
-					continue;
-				}
-				
-				String	hash_str = Base32.encode( hash );
-					
-				if ( hashes.contains( hash_str )){
-					
-					continue;
-				}
-				
-				hashes.add( hash_str );
-
-				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_HASH ){
-									
-									return( hash );
-									
-								}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( UrlUtils.getMagnetURI( hash ));
-									}
-								}else if (  property_name == RCM_SEARCH_PROPERTY_CONTENT_NETWORK ){
-									
-									long cnet = ImportExportUtils.importLong( map, "c", ContentNetwork.CONTENT_NETWORK_UNKNOWN );
-
-									return( cnet );
-									
-								}else if ( property_name == RCM_SEARCH_PROPERTY_TRACKER_KEYS ){
-									
-									return( map.get( "k" ));
-									
-								}else if ( property_name == RCM_SEARCH_PROPERTY_WEB_SEED_KEYS ){
-									
-									return( map.get( "w" ));
-									
-								}else if ( property_name == RCM_SEARCH_PROPERTY_TAGS ){
-									
-									return( decodeTags((byte[])map.get( "g" )));
-								}
-
-							}catch( Throwable e ){
-							}
-							
-							return( null );
-						}
-					};
-					
-				observer.resultReceived( si, result );
-			}
-			
-			list = (List<Map<String,Object>>)reply.get( "c" );
-
-			List<DistributedDatabaseContact>	contacts = new ArrayList<DistributedDatabaseContact>();
-			
-			if ( list != null ){
-			
-				for ( Map<String,Object> m: list ){
-					
-					try{
-						String	host 	= ImportExportUtils.importString( m, "a" );
-						int		port	= ImportExportUtils.importInt( m, "p" );
-						
-						DistributedDatabaseContact ddb_contact = 
-							ddb.importContact( new InetSocketAddress( InetAddress.getByName(host), port ), DHTTransportUDP.PROTOCOL_VERSION_MIN, contact.getDHT());
-
-						contacts.add( ddb_contact );
-						
-					}catch( Throwable e ){
-					}
-					
-				}
-			}
-			
-			return( contacts );
-			
-		}catch( Throwable e ){
-			
-			return( null );
-		}
-	}
-	
-	protected BloomFilter
-	sendRemoteFetch(
-		DistributedDatabaseContact		contact )
-	{
-		try{
-			Map<String,Object>	request = new HashMap<String,Object>();
-			
-			request.put( "x", "f" );
-		
-			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,
-					5000 );
-			
-				// System.out.println( "search result=" + value );
-			
-			if ( value != null ){
-			
-				Map<String,Object> reply = (Map<String,Object>)BDecoder.decode((byte[])value.getValue( byte[].class ));
-			
-				Map<String,Object>	m = (Map<String,Object>)reply.get( "f" );
-				
-				if ( m != null ){
-					
-					return( BloomFilterFactory.deserialiseFromMap( m ));
-				}
-			}
-		}catch( Throwable e ){
-		}
-		
-		return( null );
-	}
-	
-	protected BloomFilter
-	sendRemoteUpdate(
-		ForeignBloom	f_bloom )
-	{
-		try{
-			Map<String,Object>	request = new HashMap<String,Object>();
-			
-			request.put( "x", "u" );
-			request.put( "s", new Long( f_bloom.getFilter().getEntryCount()));
-		
-			DistributedDatabaseKey key = ddb.createKey( BEncoder.encode( request ));
-			
-			DistributedDatabaseValue value = 
-				f_bloom.getContact().read( 
-					new DistributedDatabaseProgressListener()
-					{
-						public void
-						reportSize(
-							long	size )
-						{	
-						}
-						
-						public void
-						reportActivity(
-							String	str )
-						{	
-						}
-						
-						public void
-						reportCompleteness(
-							int		percent )
-						{
-						}
-					},
-					transfer_type,
-					key,
-					5000 );
-			
-				// System.out.println( "search result=" + value );
-			
-			if ( value != null ){
-			
-				Map<String,Object> reply = (Map<String,Object>)BDecoder.decode((byte[])value.getValue( byte[].class ));
-			
-				Map<String,Object>	m = (Map<String,Object>)reply.get( "f" );
-				
-				if ( m != null ){
-					
-					logSearch( "Bloom for " + f_bloom.getContact().getAddress() + " updated" );
-
-					return( BloomFilterFactory.deserialiseFromMap( m ));
-					
-				}else{
-					
-					if ( reply.containsKey( "s" )){
-						
-						logSearch( "Bloom for " + f_bloom.getContact().getAddress() + " same size" );
-						
-					}else{
-						
-						logSearch( "Bloom for " + f_bloom.getContact().getAddress() + " update not supported yet" );
-					}
-					
-					return( f_bloom.getFilter());
-				}
-			}
-		}catch( Throwable e ){
-		}
-		
-		logSearch( "Bloom for " + f_bloom.getContact().getAddress() + " update failed" );
-
-		return( null );
-	}
-	
-	protected Map<String,Object>
-	receiveRemoteRequest(
-		DistributedDatabaseContact		originator,
-		Map<String,Object>				request )
-	{
-		Map<String,Object>	response = new HashMap<String,Object>();
-		
-		try{	
-			boolean	originator_is_neighbour = false;
-			
-			DHT[] dhts = dht_plugin.getDHTs();
-			
-			byte[] originator_id = originator.getID();
-			
-			byte[] originator_bytes = originator.getAddress().getAddress().getAddress();
-
-			for ( DHT d: dhts ){
-				
-				List<DHTTransportContact> contacts = d.getControl().getClosestKContactsList( d.getRouter().getID(), true );
-				
-				for ( DHTTransportContact c: contacts ){
-					
-					if ( Arrays.equals( c.getID(), originator_id)){
-						
-						originator_is_neighbour = true;
-						
-						break;
-					}
-				}
-				
-				if ( originator_is_neighbour ){
-					
-					break;
-				}
-			}
-			
-			String	req_type = ImportExportUtils.importString( request, "x" );
-			
-			if ( req_type != null ){
-							
-				boolean dup = harvest_op_requester_bloom.contains( originator_bytes );
-					
-				logSearch( "Received remote request: " + BDecoder.decodeStrings( request ) + " from " + originator.getAddress() + "/" + originator.getDHT() + ", dup=" + dup + ", bs=" + harvest_op_requester_bloom.getEntryCount());
-				
-				if ( !dup ){
-					
-					harvest_op_requester_bloom.add( originator_bytes );
-					
-					if ( req_type.equals( "f" )){
-						
-						BloomFilter filter = getKeyBloom( !originator_is_neighbour );
-						
-						if ( filter != null ){
-							
-							response.put( "f", filter.serialiseToMap());
-						}
-					}else if ( req_type.equals( "u" )){
-						
-						BloomFilter filter = getKeyBloom( !originator_is_neighbour );
-						
-						if ( filter != null ){
-	
-							int	existing_size = ImportExportUtils.importInt( request, "s", 0 );
-						
-							if ( existing_size != filter.getEntryCount()){
-								
-								response.put( "f", filter.serialiseToMap());
-								
-							}else{
-								
-								response.put( "s", new Long( existing_size ));
-							}
-						}
-					}
-				}
-			}else{
-					// fallback to default handling
-
-				int hits = harvest_se_requester_bloom.count( originator_bytes );
-				
-				String	term = ImportExportUtils.importString( request, "t" );
-
-				term = fixupTerm( term );
-				
-				logSearch( "Received remote search: '" + term + "' from " + originator.getAddress() + ", hits=" + hits + ", bs=" + harvest_se_requester_bloom.getEntryCount());
-
-				if ( hits < 10 ){
-					
-					harvest_se_requester_bloom.add( originator_bytes );
-					
-					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>> l_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>();
-							
-							l_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 );
-							}
-							
-							byte[] tracker_keys = c.getTrackerKeys();
-							
-							if ( tracker_keys != null ){
-								map.put( "k", tracker_keys );
-							}
-							
-							byte[] ws_keys	= c.getWebSeedKeys();
-							
-							if ( ws_keys != null ){
-								map.put( "w", ws_keys );
-							}
-							
-							String[] tags = c.getTags();
-							
-							if ( tags != null ){
-								map.put( "g", encodeTags( tags ));
-							}
-							
-								// don't bother with tracker as no use to caller really
-						}
-						
-						response.put( "l", l_list );
-					
-						List<DistributedDatabaseContact> bloom_hits = searchForeignBlooms( term );
-						
-						if ( bloom_hits.size() > 0 ){
-							
-							List<Map>	c_list = new ArrayList<Map>();
-							
-							for ( DistributedDatabaseContact c: bloom_hits ){
-								
-								Map	m = new HashMap();
-								
-								c_list.add( m );
-								
-								InetSocketAddress address = c.getAddress();
-								
-								m.put( "a", address.getAddress().getHostAddress());
-								m.put( "p", new Long( address.getPort()));
-							}
-							
-							response.put( "c", c_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 = receiveRemoteRequest( contact, 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()
-	{
-		synchronized( this ){
-			
-			content_dirty	= true;
-		}
-	}
-	
-	protected ContentCache
-	loadRelatedContent()
-	{
-		boolean	fire_event = false;
-		
-		try{
-			synchronized( this ){
-	
-				last_config_access = SystemTime.getMonotonousTime();
-	
-				ContentCache cc = content_cache==null?null:content_cache.get();
-				
-				if ( cc == null ){
-				
-					if ( TRACE ){
-						System.out.println( "rcm: load new" );
-					}
-					
-					fire_event = true;
-					
-					cc = new ContentCache();
-		
-					content_cache = new WeakReference<ContentCache>( cc );
-					
-					try{
-						int	new_total_unread = 0;
-		
-						if ( FileUtil.resilientConfigFileExists( CONFIG_FILE )){
-											
-							Map map = FileUtil.readResilientConfigFile( CONFIG_FILE );
-							
-							Map<String,DownloadInfo>						related_content			= cc.related_content;
-							ByteArrayHashMapEx<ArrayList<DownloadInfo>>		related_content_map		= cc.related_content_map;
-		
-							Map<String,String>	rcm_map;
-							
-							byte[]	data = (byte[])map.get( "d" );
-							
-							if ( data != null ){
-										
-								try{
-									map = BDecoder.decode(new BufferedInputStream( new GZIPInputStream( new ByteArrayInputStream( CryptoManagerFactory.getSingleton().deobfuscate( data )))));
-									
-								}catch( Throwable e ){
-									
-										// can get here is config's been deleted
-									
-									map = new HashMap();
-								}
-							}
-							
-							rcm_map = (Map<String,String>)map.get( "rcm" );
-						
-							Object	rc_map_stuff 	= map.get( "rc" );
-							
-							if ( rc_map_stuff != null && rcm_map != null ){
-								
-								Map<Integer,DownloadInfo> id_map = new HashMap<Integer, DownloadInfo>();
-									
-								if ( rc_map_stuff instanceof Map ){
-									
-										// migration from when it was a Map with non-ascii key issues
-									
-									Map<String,Map<String,Object>>	rc_map 	= (Map<String,Map<String,Object>>)rc_map_stuff;
-
-									for ( Map.Entry<String,Map<String,Object>> entry: rc_map.entrySet()){
-										
-										try{
-										
-											String	key = entry.getKey();
-										
-											Map<String,Object>	info_map = entry.getValue();
-																		
-											DownloadInfo info = deserialiseDI( info_map, cc );
-											
-											if ( info.isUnread()){
-												
-												new_total_unread++;
-											}
-											
-											related_content.put( key, info );
-											
-											int	id = ((Long)info_map.get( "_i" )).intValue();
-				
-											id_map.put( id, info );
-											
-										}catch( Throwable e ){
-											
-											Debug.out( e );
-										}
-									}
-								}else{
-									
-									List<Map<String,Object>>	rc_map_list 	= (List<Map<String,Object>>)rc_map_stuff;
-
-									for ( Map<String,Object> info_map: rc_map_list ){
-										
-										try{
-										
-											String	key = new String((byte[])info_map.get( "_k" ), "UTF-8" );
-																												
-											DownloadInfo info = deserialiseDI( info_map, cc );
-											
-											if ( info.isUnread()){
-												
-												new_total_unread++;
-											}
-											
-											related_content.put( key, info );
-											
-											int	id = ((Long)info_map.get( "_i" )).intValue();
-				
-											id_map.put( id, info );
-											
-										}catch( Throwable e ){
-											
-											Debug.out( e );
-										}
-									}
-								}
-															
-								if ( rcm_map.size() != 0 && id_map.size() != 0 ){
-									
-									for ( String key: rcm_map.keySet()){
-										
-										try{
-											byte[]	hash = Base32.decode( key );
-											
-											int[]	ids = ImportExportUtils.importIntArray( rcm_map, key );
-											
-											if ( ids == null || ids.length == 0 ){
-												
-												// Debug.out( "Inconsistent - no ids" );
-												
-											}else{
-												
-												ArrayList<DownloadInfo>	di_list = new ArrayList<DownloadInfo>(ids.length);
-												
-												for ( int id: ids ){
-													
-													DownloadInfo di = id_map.get( id );
-													
-													if ( di == null ){
-														
-														// Debug.out( "Inconsistent: id " + id + " missing" );
-														
-													}else{
-														
-															// we don't currently remember all originators, just one that works 
-															
-														di.setRelatedToHash( hash );
-														
-														di_list.add( di );
-													}
-												}
-												
-												if ( di_list.size() > 0 ){
-													
-													related_content_map.put( hash, di_list );
-												}
-											}
-										}catch( Throwable e ){
-											
-											Debug.out( e );
-										}
-									}
-								}
-								
-								Iterator<DownloadInfo> it = related_content.values().iterator();
-								
-								while( it.hasNext()){
-									
-									DownloadInfo di = it.next();
-									
-									if ( di.getRelatedToHash() == null ){
-								
-										// Debug.out( "Inconsistent: info not referenced" );
-										
-										if ( di.isUnread()){
-											
-											new_total_unread--;
-										}
-										
-										it.remove();
-									}
-								}
-								
-								popuplateSecondaryLookups( cc );
-							}
-						}
-						
-						if ( total_unread.get() != new_total_unread ){
-														
-							// Debug.out( "total_unread - inconsistent (" + total_unread + "/" + new_total_unread + ")" );
-							
-							total_unread.set( new_total_unread );
-							
-							COConfigurationManager.setParameter( CONFIG_TOTAL_UNREAD, new_total_unread );
-						}
-					}catch( Throwable e ){
-						
-						Debug.out( e );
-					}
-					
-					enforceMaxResults( cc, false );
-				}
-				
-				content_cache_ref = cc;
-					
-				return( cc );
-			}
-		}finally{
-			
-			if ( fire_event ){
-				
-				contentChanged( false );
-			}
-		}
-	}
-	
-	protected void
-	saveRelatedContent(
-		int	tick_count )
-	{
-		synchronized( this ){
-				
-			COConfigurationManager.setParameter( CONFIG_TOTAL_UNREAD, total_unread.get());
-			
-			long	now = SystemTime.getMonotonousTime();;
-			
-			ContentCache cc = content_cache==null?null:content_cache.get();
-			
-			if ( !content_dirty ){
-					
-				if ( cc != null  ){
-					
-					if ( now - last_config_access > CONFIG_DISCARD_MILLIS ){
-					
-						if ( content_cache_ref != null ){
-							
-							content_discard_ticks = 0;
-						}
-						
-						if ( TRACE ){
-							System.out.println( "rcm: discard: tick count=" + content_discard_ticks++ );
-						}
-						
-						content_cache_ref	= null;
-					}
-				}else{
-					
-					if ( TRACE ){
-						System.out.println( "rcm: discarded" );
-					}
-				}
-				
-				return;
-			}
-			
-			if ( tick_count % CONFIG_SAVE_TICKS != 0 ){
-				
-				return;
-			}
-			
-			last_config_access = now;
-			
-			content_dirty	= false;
-			
-			if ( cc == null ){
-				
-				// Debug.out( "RCM: cache inconsistent" );
-				
-			}else{
-				
-				if ( persist ){
-					
-					if ( TRACE ){
-						System.out.println( "rcm: save" );
-					}
-					
-					Map<String,DownloadInfo>						related_content			= cc.related_content;
-					ByteArrayHashMapEx<ArrayList<DownloadInfo>>		related_content_map		= cc.related_content_map;
-	
-					if ( related_content.size() == 0 ){
-						
-						FileUtil.deleteResilientConfigFile( CONFIG_FILE );
-						
-					}else{
-						
-						Map<String,Object>	map = new HashMap<String, Object>();
-						
-						Set<Map.Entry<String,DownloadInfo>> rcs = related_content.entrySet();
-											
-						List<Map<String,Object>> rc_map_list = new ArrayList<Map<String, Object>>( rcs.size());
-						
-						map.put( "rc", rc_map_list );
-						
-						int		id = 0;
-						
-						Map<DownloadInfo,Integer>	info_map = new HashMap<DownloadInfo, Integer>();
-						
-						for ( Map.Entry<String,DownloadInfo> entry: rcs ){
-												
-							DownloadInfo	info = entry.getValue();
-													
-							Map<String,Object> di_map = serialiseDI( info, cc );
-							
-							if ( di_map != null ){
-								
-								info_map.put( info, id );
-	
-								di_map.put( "_i", new Long( id ));
-								di_map.put( "_k", entry.getKey());
-								
-								rc_map_list.add( di_map );
-		
-								id++;	
-							}
-						}
-						
-						Map<String,Object> rcm_map = new HashMap<String, Object>();
-						
-						map.put( "rcm", rcm_map );
-
-						for ( byte[] hash: related_content_map.keys()){
-							
-							List<DownloadInfo> dis = related_content_map.get( hash );
-							
-							int[] ids = new int[dis.size()];
-							
-							int	pos = 0;
-							
-							for ( DownloadInfo di: dis ){
-								
-								Integer	index = info_map.get( di );
-								
-								if ( index == null ){
-									
-									// Debug.out( "inconsistent: info missing for " + di );
-									
-									break;
-									
-								}else{
-									
-									ids[pos++] = index;
-								}
-							}
-							
-							if ( pos == ids.length ){
-							
-								ImportExportUtils.exportIntArray( rcm_map, Base32.encode( hash), ids );
-							}
-						}
-						
-						if ( true ){
-						
-							ByteArrayOutputStream baos = new ByteArrayOutputStream( 100*1024 );
-							
-							try{
-								GZIPOutputStream gos = new GZIPOutputStream( baos );
-								
-								gos.write( BEncoder.encode( map ));
-								
-								gos.close();
-								
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-							
-							map.clear();
-							
-							map.put( "d", CryptoManagerFactory.getSingleton().obfuscate( baos.toByteArray()));
-						}
-						
-						FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
-					}
-				}else{
-					
-					deleteRelatedContent();
-				}
-			
-				updateKeyBloom( cc );
-			}
-		}
-	}
-	
-	private void
-	deleteRelatedContent()
-	{
-		FileUtil.deleteResilientConfigFile( CONFIG_FILE );
-		FileUtil.deleteResilientConfigFile( PERSIST_DEL_FILE );
-	}
-	
-	public int
-	getNumUnread()
-	{
-		return( total_unread.get());
-	}
-	
-	public void
-	setAllRead()
-	{
-		boolean	changed = false;
-		
-		synchronized( this ){
-			
-			DownloadInfo[] content = (DownloadInfo[])getRelatedContent();
-			
-			for ( DownloadInfo c: content ){
-				
-				if ( c.isUnread()){
-				
-					changed = true;
-					
-					c.setUnreadInternal( false );
-				}
-			}
-			
-			total_unread.set( 0 );
-		}
-		
-		if ( changed ){
-		
-			contentChanged( true );
-		}
-	}
-	
-	public void
-	deleteAll()
-	{	
-		synchronized( this ){
-
-			ContentCache	content_cache = loadRelatedContent();
-			
-			addPersistentlyDeleted( content_cache.related_content.values().toArray( new DownloadInfo[ content_cache.related_content.size()]));
-		
-			reset( false );
-		}
-	}
-	
-	protected void
-	incrementUnread()
-	{
-		total_unread.incrementAndGet();
-	}
-	
-	protected void
-	decrementUnread()
-	{
-		synchronized( this ){
-			
-			int val = total_unread.decrementAndGet();
-			
-			if ( val < 0 ){
-				
-				// Debug.out( "inconsistent" );
-				
-				total_unread.set( 0 );
-			}
-		}
-	}
-	
-	protected Download
-	getDownload(
-		byte[]	hash )
-	{
-		try{
-			return( plugin_interface.getDownloadManager().getDownload( hash ));
-			
-		}catch( Throwable e ){
-			
-			return( null );
-		}
-	}
-	
-	private static final int KEY_BLOOM_LOAD_FACTOR			= 8;
-	private static final int KEY_BLOOM_MIN_BITS				= 1000;	
-	private static final int KEY_BLOOM_MAX_BITS				= 50000;	// 6k ish
-	private static final int KEY_BLOOM_MAX_ENTRIES			= KEY_BLOOM_MAX_BITS/KEY_BLOOM_LOAD_FACTOR;
-
-	private volatile BloomFilter	key_bloom_with_local;
-	private volatile BloomFilter	key_bloom_without_local;
-	private volatile long			last_key_bloom_update = -1;
-	
-	private Set<String>	ignore_words = new HashSet<String>();
-	
-	{
-		String ignore = "a, in, of, at, the, and, or, if, to, an, for, with";
-		
-		String[]	lame_entries = ignore.toLowerCase( Locale.US ).split(",");
-		
-		for ( String entry: lame_entries ){
-		
-			entry = entry.trim();
-			
-			if ( entry.length() > 0 ){
-				
-				ignore_words.add( entry );
-			}
-		}
-	}
-	
-	private static void
-	logSearch(
-		String		str )
-	{
-		if ( TRACE_SEARCH ){
-			System.out.println( str );
-		}
-	}
-	
-	private byte[][]
-	getKeys(
-		Download		download )
-	{
-		byte[]	tracker_keys	= null;
-		byte[]	ws_keys			= null;
-		
-		try{
-			Torrent torrent = download.getTorrent();
-		
-			if ( torrent != null ){
-				
-				TOTorrent to_torrent = PluginCoreUtils.unwrap( torrent );
-				
-				Set<String>	tracker_domains = new HashSet<String>();
-				
-				addURLToDomainKeySet( tracker_domains, to_torrent.getAnnounceURL());
-				
-				TOTorrentAnnounceURLGroup group = to_torrent.getAnnounceURLGroup();
-				
-				TOTorrentAnnounceURLSet[] sets = group.getAnnounceURLSets();
-				
-				for ( TOTorrentAnnounceURLSet set: sets ){
-					
-					URL[] urls = set.getAnnounceURLs();
-					
-					for ( URL u: urls ){
-						
-						addURLToDomainKeySet( tracker_domains, u );
-					}
-				}
-				
-				tracker_keys = domainsToArray( tracker_domains, 8 );
-				
-				Set<String>	ws_domains = new HashSet<String>();
-
-				List getright = BDecoder.decodeStrings( getURLList( to_torrent, "url-list" ));
-				List webseeds = BDecoder.decodeStrings( getURLList( to_torrent, "httpseeds" ));
-								
-				for ( List l: new List[]{ getright, webseeds }){
-					
-					for ( Object o: l ){
-					
-						if ( o instanceof String ){
-						
-							try{
-								addURLToDomainKeySet( ws_domains, new URL((String)o));
-								
-							}catch( Throwable e ){
-								
-							}
-						}
-					}
-				}
-				
-				ws_keys = domainsToArray( ws_domains, 3 );
-			}
-		}catch( Throwable e ){	
-		}
-		
-		return( new byte[][]{ tracker_keys, ws_keys });
-	}
-	
-	protected byte[]
-	domainsToArray(
-		Set<String>	domains,
-		int			max )
-	{
-		int	entries = Math.min( domains.size(), max );
-		
-		if ( entries > 0 ){
-			
-			byte[] keys = new byte[ entries*4 ];
-			
-			int	pos = 0;
-			
-			for ( String dom: domains ){
-				
-				int hash = dom.hashCode();
-				
-				byte[]	bytes = { (byte)(hash>>24), (byte)(hash>>16),(byte)(hash>>8),(byte)hash };
-				
-				System.arraycopy( bytes, 0, keys, pos, 4 );
-			
-				pos += 4;
-			}
-			
-			return( keys );
-		}
-		
-		return( null );
-	}
-	
-	protected List
-	getURLList(
-		TOTorrent	torrent,
-		String		key )
-	{
-		Object obj = torrent.getAdditionalProperty( key );
-		
-		if ( obj instanceof byte[] ){
-			
-            List l = new ArrayList();
-            
-	        l.add(obj);
-	        
-	        return( l );
-	        
-		}else if ( obj instanceof List ){
-			
-			return (List)BEncoder.clone(obj);
-			
-		}else{
-			
-			return( new ArrayList());
-		}
-	}
-	
-	private void
-	addURLToDomainKeySet(
-		Set<String>	set,
-		URL			u )
-	{
-		String prot = u.getProtocol();
-		
-		if ( prot != null ){
-			
-			if ( prot.equalsIgnoreCase( "http" ) || prot.equalsIgnoreCase( "udp" )){
-				
-				String host = u.getHost().toLowerCase( Locale.US );
-				
-				if ( host.contains( ":" )){
-				
-						// ipv6 raw
-					
-					return;
-				}
-				
-				String[] bits = host.split( "\\." );
-				
-				int	len = bits.length;
-				
-				if ( len >= 2 ){
-					
-					String	end = bits[len-1];
-					
-					char[] chars = end.toCharArray();
-					
-						// simple check for ipv4 raw
-					
-					boolean	all_digits = true;
-					
-					for ( char c: chars ){
-						
-						if ( !Character.isDigit( c )){
-							
-							all_digits = false;
-							
-							break;
-						}
-					}
-					
-					if ( !all_digits ){
-						
-						set.add( bits[len-2] + "." + end );
-					}
-				}
-			}
-		}
-	}
-		
-	private String[]
-	getTags(
-		Download	download )
-	{
-		if ( !tag_manager.isEnabled()){
-			
-			return( null );
-		}
-		
-		Set<String>	all_tags = new HashSet<String>();
-		
-		String	cat_name = ta_category==null?null:download.getAttribute( ta_category );
-		
-		if ( cat_name != null ){
-			
-			Tag cat_tag = tag_manager.getTagType( TagType.TT_DOWNLOAD_CATEGORY ).getTag( cat_name, true );
-			
-			if ( cat_tag != null && cat_tag.isPublic()){
-			
-				all_tags.add( cat_name.toLowerCase( Locale.US ));
-			}
-		}
-		
-		List<Tag> tags = tag_manager.getTagType( TagType.TT_DOWNLOAD_MANUAL ).getTagsForTaggable( PluginCoreUtils.unwrap( download ));
-		
-		for ( Tag t: tags ){
-			
-			if ( t.isPublic()){
-			
-				all_tags.add( t.getTagName( true ).toLowerCase( Locale.US ));
-			}
-		}
-		
-		if ( all_tags.size() == 0 ){
-		
-			return( null );
-			
-		}else if ( all_tags.size() == 1 ){
-			
-			return( new String[]{ all_tags.iterator().next()});
-			
-		}else{
-			
-			List<String> temp = new ArrayList<String>( all_tags );
-			
-			Collections.shuffle( temp );
-			
-			return( temp.toArray( new String[ temp.size()] ));
-		}
-	}
-	
-	private static final int MAX_TAGS 			= 3;
-	private static final int MAX_TAG_LENGTH		= 20;
-	
-	private byte[]
-	encodeTags(
-		String[]		tags )
-	{
-		if ( tags == null || tags.length == 0 ){
-			
-			return( null );
-		}
-		
-		byte[]	temp 	= new byte[MAX_TAGS*(MAX_TAG_LENGTH+1)];
-		int		pos		= 0;
-		
-		for ( int i=0;i<Math.min( MAX_TAGS, tags.length);i++){
-			
-			String tag = tags[i];
-			
-			tag = truncateTag( tag );
-			
-			try{
-				byte[] tag_bytes = tag.getBytes( "UTF-8" );
-					
-				int	tb_len = tag_bytes.length;
-											
-				temp[pos++] = (byte)tb_len;
-						
-				System.arraycopy( tag_bytes, 0, temp, pos, tb_len );
-						
-				pos += tb_len;
-				
-			}catch( Throwable e ){
-
-			}
-		}
-		
-		if ( pos == 0 ){
-			
-			return( null );
-			
-		}else{
-			
-			byte[] result = new byte[pos];
-			
-			System.arraycopy( temp, 0, result, 0, pos );
-			
-			return( result );
-		}
-	}
-	
-	private String
-	escapeTag(
-		String	tag )
-	{
-		if ( tag.contains( " " )){
-			
-			tag = tag.replaceAll( " ", "+" );
-		}
-		
-		return( tag );
-	}
-	
-	private String
-	unescapeTag(
-		String	tag )
-	{
-		if ( tag.contains( "+" )){
-			
-			tag = tag.replaceAll( "\\+", " " );
-		}
-		
-		return( tag );
-	}
-	
-	private String
-	truncateTag(
-		String	tag )
-	{
-		if ( tag.length() > MAX_TAG_LENGTH ){
-			
-			tag = tag.substring( 0, MAX_TAG_LENGTH );
-		}
-		
-		while( tag.length() > 0 ){
-			
-			try{
-				byte[] tag_bytes = tag.getBytes( "UTF-8" );
-								
-				if ( tag_bytes.length <= MAX_TAG_LENGTH ){
-					
-					break;
-					
-				}else{
-					
-					tag = tag.substring( 0, tag.length() - 1 );
-				}
-				
-			}catch( Throwable e ){
-				
-				break;
-			}
-		}
-		
-		return( tag );
-	}
-	
-	private String[]
-	decodeTags(
-		byte[]		bytes )
-	{
-		if ( bytes == null || bytes.length == 0 ){
-		
-			return( null );
-		}
-		
-		List<String>	tags = new ArrayList<String>( MAX_TAGS );
-		
-		int	pos = 0;
-		
-		while( pos < bytes.length ){
-			
-			int	tag_len = bytes[pos++]&0x000000ff;
-			
-			if ( tag_len > MAX_TAG_LENGTH ){
-				
-				break;
-			}
-			
-			try{
-				tags.add( new String( bytes, pos, tag_len, "UTF-8" ));
-				
-				pos += tag_len;
-				
-			}catch( Throwable e ){
-				
-				break;
-			}
-		}
-		
-		if ( tags.size() == 0 ){
-		
-			return( null );
-			
-		}else{
-				
-			return( tags.toArray( new String[ tags.size()] ));
-		}
-	}
-	
-	private List<DownloadInfo>
-	getDHTInfos()
-	{
-		List<DHTPluginValue> vals = dht_plugin.getValues();
-				
-		Set<String>	unique_keys = new HashSet<String>();
-		
-		List<DownloadInfo>	dht_infos = new ArrayList<DownloadInfo>();
-		
-		for ( DHTPluginValue val: vals ){
-			
-			if ( !val.isLocal()){
-				
-				byte[]	bytes = val.getValue();
-				
-				String test = new String( bytes );
-				
-				if ( test.startsWith( "d1:d" ) && test.endsWith( "ee" ) && test.contains( "1:h20:")){
-							
-					try{
-						Map map = BDecoder.decode( bytes );
-					
-						DownloadInfo info =	decodeInfo( map, null, 1, false, unique_keys );
-						
-						if ( info != null ){
-							
-							dht_infos.add( info );
-						}
-					}catch( Throwable e ){
-						
-					}
-				}
-			}
-		}
-		
-		return( dht_infos );
-	}
-	
-	private void
-	checkKeyBloom()
-	{
-		if ( last_key_bloom_update == -1 || SystemTime.getMonotonousTime() - last_key_bloom_update > 10*60*1000 ){
-			
-			synchronized( this ){
-				
-				updateKeyBloom( loadRelatedContent());
-			}
-		}
-	}
-	
-	private BloomFilter
-	getKeyBloom(
-		boolean		include_dht_local )
-	{
-		if ( key_bloom_with_local == null ){
-				
-			synchronized( this ){
-			
-				updateKeyBloom( loadRelatedContent());
-			}
-		}
-			
-		if ( include_dht_local ){
-			
-			return( key_bloom_with_local );
-			
-		}else{
-			
-			return( key_bloom_without_local );
-		}
-	}
-	
-	private List<String>
-	getDHTWords(
-		DownloadInfo	info )
-	{
-		String title = info.getTitle();
-		
-		title = title.toLowerCase( Locale.US );
-		
-		char[]	chars = title.toCharArray();
-		
-		for ( int i=0;i<chars.length;i++){
-			
-			if ( !Character.isLetterOrDigit( chars[i])){
-				
-				chars[i] = ' ';
-			}
-		}
-		
-		String[] words = new String( chars ).split( " " );
-		
-		List<String>	result = new ArrayList<String>( words.length );
-		
-		for ( String word: words ){
-			
-			if ( word.length() > 0 && !ignore_words.contains( word )){
-				
-				result.add( word );
-			}
-		}
-		
-		String[] tags = info.getTags();
-		
-		if ( tags != null ){
-			
-			for ( String tag: tags ){
-				
-				tag = escapeTag( tag );
-							
-					// support prefix matching
-				
-				for ( int i=1; i<=tag.length(); i++){
-				
-					result.add( "tag:" + tag.substring( 0, i ));
-				}
-			}
-		}
-		
-		return( result );
-	}
-	
-	private void
-	updateKeyBloom(
-		ContentCache		cc )
-	{
-		synchronized( this ){
-												
-			Set<String>	dht_only_words 		= new HashSet<String>();
-			Set<String>	non_dht_words 		= new HashSet<String>();
-			
-			List<DownloadInfo>		dht_infos		= getDHTInfos();
-			
-			Iterator<DownloadInfo>	it_dht 			= dht_infos.iterator();
-						
-			Iterator<DownloadInfo>	it_transient 	= transient_info_cache.values().iterator();
-			
-			Iterator<DownloadInfo>	it_rc 			= cc.related_content.values().iterator();			
-
-			for ( Iterator _it: new Iterator[]{ it_transient, it_rc, it_dht }){
-				
-				Iterator<DownloadInfo> it = (Iterator<DownloadInfo>)_it;
-				
-				while( it.hasNext()){
-				
-					DownloadInfo di = it.next();
-							
-					List<String>	words = getDHTWords( di );
-					
-					for ( String word: words ){
-															
-							// note that it_dht is processed last
-						
-						if ( it == it_dht ){
-							
-							if ( !non_dht_words.contains( word )){
-							
-								dht_only_words.add( word );
-							}
-						}else{
-															
-							non_dht_words.add( word );
-						}
-					}
-				}
-			}
-			
-			int	all_desired_bits = (dht_only_words.size() + non_dht_words.size()) * KEY_BLOOM_LOAD_FACTOR;
-			
-			all_desired_bits = Math.max( all_desired_bits, KEY_BLOOM_MIN_BITS );
-			all_desired_bits = Math.min( all_desired_bits, KEY_BLOOM_MAX_BITS );
-			
-			BloomFilter all_bloom = BloomFilterFactory.createAddOnly( all_desired_bits );
-
-			int	non_dht_desired_bits = non_dht_words.size() * KEY_BLOOM_LOAD_FACTOR;
-			
-			non_dht_desired_bits = Math.max( non_dht_desired_bits, KEY_BLOOM_MIN_BITS );
-			non_dht_desired_bits = Math.min( non_dht_desired_bits, KEY_BLOOM_MAX_BITS );
-			
-			BloomFilter non_dht_bloom = BloomFilterFactory.createAddOnly( non_dht_desired_bits );
-
-			List<String>	non_dht_words_rand = new ArrayList<String>( non_dht_words );
-			
-			Collections.shuffle( non_dht_words_rand );
-			
-			for ( String word: non_dht_words_rand ){
-				
-				try{
-					byte[]	bytes = word.getBytes( "UTF8" );
-					
-					all_bloom.add( bytes );
-					
-					if ( all_bloom.getEntryCount() >= KEY_BLOOM_MAX_ENTRIES ){
-						
-						break;
-					}
-					
-					if ( non_dht_bloom.getEntryCount() < KEY_BLOOM_MAX_ENTRIES ){
-					
-						non_dht_bloom.add( bytes );
-					}
-				}catch( Throwable e ){
-				}
-			}
-				
-			List<String>	dht_only_words_rand = new ArrayList<String>( dht_only_words );
-			
-			Collections.shuffle( dht_only_words_rand );
-
-			for ( String word: dht_only_words_rand ){
-				
-				try{
-					byte[]	bytes = word.getBytes( "UTF8" );
-					
-					all_bloom.add( bytes );
-					
-					if ( all_bloom.getEntryCount() >= KEY_BLOOM_MAX_ENTRIES ){
-						
-						break;
-					}
-				}catch( Throwable e ){
-				}
-			}
-			
-			logSearch( 
-				"blooms=" + 
-				all_bloom.getSize() + "/" + all_bloom.getEntryCount() +", " +
-				non_dht_bloom.getSize() + "/" + non_dht_bloom.getEntryCount()  +
-				": rcm=" + cc.related_content.size() + ", trans=" + transient_info_cache.size() + ", dht=" + dht_infos.size());
-			
-			key_bloom_with_local 	= all_bloom;
-			key_bloom_without_local = non_dht_bloom;
-			
-			last_key_bloom_update = SystemTime.getMonotonousTime();
-		}
-	}
-	
-	private void
-	testKeyBloom()
-	{
-		if ( true ){
-			return;
-		}
-		
-		System.out.println( "test key bloom" );
-		
-		try{
-			Map<String,int[]>	all_words 		= new HashMap<String,int[]>();
-	
-			synchronized( this ){
-				
-				ContentCache cache = loadRelatedContent();
-				
-				List<DownloadInfo>		dht_infos		= getDHTInfos();
-				
-				Iterator<DownloadInfo>	it_dht 			= dht_infos.iterator();
-							
-				Iterator<DownloadInfo>	it_transient 	= transient_info_cache.values().iterator();
-				
-				Iterator<DownloadInfo>	it_rc 			= cache.related_content.values().iterator();			
-	
-				updateKeyBloom( cache );
-				
-				int	 i=0;
-				
-				for ( Iterator _it: new Iterator[]{ it_transient, it_rc, it_dht }){
-					
-					Iterator<DownloadInfo> it = (Iterator<DownloadInfo>)_it;
-					
-					while( it.hasNext()){
-					
-						DownloadInfo di = it.next();
-								
-						List<String>	words = getDHTWords( di );
-						
-						for ( String word: words ){
-									
-							int[] x = all_words.get( word );
-							
-							if ( x == null ){
-								
-								x = new int[3];
-								
-								all_words.put( word, x );
-							}
-							
-							x[i] = 1;
-						}
-					}
-					
-					i++;
-				}
-			}
-			
-			BloomFilter bloom = getKeyBloom( true );
-	
-			int	total 	= 0;
-			int	clashes	= 0;
-			int misses	= 0;
-			
-			int match_fails = 0;
-			
-			Random random = new Random();
-			
-			for ( Map.Entry<String,int[]> entry: all_words.entrySet()){
-				
-				String 	word 	= entry.getKey();
-				int[]	source 	= entry.getValue();
-				
-				boolean	r1 = bloom.contains( word.getBytes("UTF-8") );
-				boolean r2 = bloom.contains( (word + random.nextLong()).getBytes("UTF-8"));
-				
-				System.out.println( word + " -> " + r1 + "/" +r2 );
-				
-				total++;
-				if ( r1 && r2 ){
-					clashes++;
-				}
-				if ( !r1 ){
-					
-					misses++;
-				}
-				
-				List<RelatedContent> hits = matchContent( word );
-				
-				if ( hits.size() == 0 ){
-					
-					hits = matchContent( word );
-					match_fails++;
-				}
-			}
-			
-			System.out.println( "total=" + total + ", clash=" + clashes + ", miss=" + misses + ", fails=" + match_fails + ", bloom=" + bloom.getString() );
-			
-		}catch( Throwable e ){
-			
-			e.printStackTrace();
-		}
-	}
-	
-	private void
-	harvestBlooms()
-	{
-		harvest_dispatcher.dispatch(
-			new AERunnable()
-			{
-				public void
-				runSupport()
-				{
-					if ( harvest_dispatcher.getQueueSize() > 0 ){
-						
-						return;
-					}
-					
-					ForeignBloom oldest = null;
-					
-					synchronized( harvested_blooms ){
-						
-						for ( ForeignBloom bloom: harvested_blooms.values()){
-							
-							if ( 	oldest == null ||
-									bloom.getLastUpdateTime() < oldest.getLastUpdateTime()){
-								
-								oldest	= bloom;
-							}
-						}
-					}
-					
-					long now = SystemTime.getMonotonousTime();
-					
-					if ( oldest != null ){
-						
-						if ( now - oldest.getLastUpdateTime() > HARVEST_BLOOM_UPDATE_MILLIS ){
-							
-							DistributedDatabaseContact ddb_contact = oldest.getContact();
-
-							if ( now - oldest.getCreateTime() > HARVEST_BLOOM_DISCARD_MILLIS ){
-							
-									// don't want to stick with a stable one for too long otherwise the stabler
-									// nodes will end up in lots of other nodes' harvest set and receive
-									// undue attention
-								
-								logSearch( "Harvest: discarding " + ddb_contact.getAddress());
-								
-								synchronized( harvested_blooms ){
-									
-									harvested_blooms.remove( ddb_contact.getID());
-								}
-							}else{
-
-								BloomFilter updated_filter = sendRemoteUpdate( oldest );
-								
-								if ( updated_filter == null ){
-																						
-									synchronized( harvested_blooms ){
-									
-										harvested_blooms.remove( ddb_contact.getID());
-									
-										harvested_fails.put( ddb_contact.getID(), "" );
-									}
-								}else{
-																	
-									oldest.updateFilter( updated_filter );
-								}
-							}
-						}
-					}
-					
-					if ( harvested_blooms.size() < HARVEST_MAX_BLOOMS ){
-					
-						try{
-							int	fail_count	= 0;
-							
-							DHT[] dhts = dht_plugin.getDHTs();
-							
-outer:
-							for ( DHT dht: dhts ){
-								
-								DHTTransport transport = dht.getTransport();
-								
-								if ( transport.isIPV6()){
-									
-									continue;
-								}
-								
-								int	network = dht.getTransport().getNetwork();
-								
-								if ( SEARCH_CVS_ONLY && network != DHT.NW_CVS ){
-									
-									logSearch( "Harvest: ignoring main DHT" );
-									
-									continue;
-								}
-													
-								DHTTransportContact[] contacts = dht.getTransport().getReachableContacts();
-								
-								for ( DHTTransportContact contact: contacts ){
-				
-									byte[]	contact_id = contact.getID();
-									
-									if ( dht.getRouter().isID( contact_id )){
-										
-										// logSearch( "not skipping local!!!!" );
-										
-										continue;
-									}
-									
-									DistributedDatabaseContact ddb_contact = 
-										ddb.importContact( contact.getAddress(), DHTTransportUDP.PROTOCOL_VERSION_MIN, network==DHT.NW_CVS?DistributedDatabase.DHT_CVS:DistributedDatabase.DHT_MAIN );
-									
-									synchronized( harvested_blooms ){
-																				
-										if ( harvested_fails.containsKey( contact_id )){
-											
-											continue;
-										}
-
-										if ( harvested_blooms.containsKey( contact_id )){
-											
-											continue;
-										}
-									}
-									
-									BloomFilter filter = sendRemoteFetch( ddb_contact );
-									
-									logSearch( "harvest: " + contact.getString() + " -> " +(filter==null?"null":filter.getString()));
-
-									if ( filter != null ){
-										
-										synchronized( harvested_blooms ){
-										
-											harvested_blooms.put( contact_id, new ForeignBloom( ddb_contact, filter ));
-										}
-										
-										break outer;
-										
-									}else{
-										
-										synchronized( harvested_blooms ){
-										
-											harvested_fails.put( contact_id, "" );
-										}
-										
-										fail_count++;
-										
-										if ( fail_count > 5 ){
-											
-											break outer;
-										}
-									}
-								}
-							}
-						}catch( Throwable e ){
-							
-							e.printStackTrace();
-						}
-					}
-					
-					synchronized( harvested_blooms ){
-					
-						if ( harvested_fails.size() > HARVEST_MAX_FAILS_HISTORY ){
-						
-							harvested_fails.clear();
-						}
-					}
-				}
-			});
-	}
-	
-	private void
-	foreignBloomFailed(
-		DistributedDatabaseContact		contact )
-	{
-		byte[]	contact_id = contact.getID();
-		
-		synchronized( harvested_blooms ){
-			
-			if ( harvested_blooms.remove( contact_id ) != null ){
-			
-				harvested_fails.put( contact_id, "" );
-			}
-		}
-	}
-	
-	private List<DistributedDatabaseContact>
-	searchForeignBlooms(
-		String		term )
-	{
-		List<DistributedDatabaseContact>	result = new ArrayList<DistributedDatabaseContact>();
-		
-		try{
-			String[]	 bits = Constants.PAT_SPLIT_SPACE.split(term.toLowerCase());
-	
-				// note that we don't need to unescape tags in this process as tags are escaped when
-				// inserted into the blooms and include the 'tag:' prefix
-			
-			int[]			bit_types 		= new int[bits.length];
-			byte[][]		bit_bytes	 	= new byte[bit_types.length][];
-			byte[][][]		extras			= new byte[bit_types.length][][];
-			
-			for (int i=0;i<bits.length;i++){
-				
-				String bit = bits[i].trim();
-				
-				if ( bit.length() > 0 ){
-					
-					char	c = bit.charAt(0);
-					
-					if ( c == '+' ){
-						
-						bit_types[i] = 1;
-						
-						bit = bit.substring(1);
-						
-					}else if ( c == '-' ){
-						
-						bit_types[i] = 2;
-						
-						bit = bit.substring(1);
-					}
-					
-					if ( bit.startsWith( "(" ) && bit.endsWith((")"))){
-						
-						bit_types[i] = 3;	// ignore
-						
-					}else if ( bit.contains( "|" )){
-											
-						String[]	parts = bit.split( "\\|" );
-						
-						List<String>	p = new ArrayList<String>();
-						
-						for ( String part: parts ){
-							
-							part = part.trim();
-							
-							if ( part.length() > 0 ){
-								
-								p.add( part );
-							}
-						}
-						
-						if ( p.size() == 0 ){
-							
-							bit_types[i] = 3;
-							
-						}else{
-							
-							bit_types[i] = 4;
-	
-							extras[i] = new byte[p.size()][];
-							
-							for ( int j=0;j<p.size();j++){
-								
-								extras[i][j] = p.get(j).getBytes( "UTF8" );
-							}
-						}
-					}
-					
-					bit_bytes[i] = bit.getBytes( "UTF8" );
-				}
-			}
-			
-			synchronized( harvested_blooms ){
-				
-				for ( ForeignBloom fb: harvested_blooms.values()){
-					
-					BloomFilter filter = fb.getFilter();
-					
-					boolean	failed 	= false;
-					int		matches	= 0;
-					
-					for (int i=0;i<bit_bytes.length;i++){
-						
-						byte[]	bit = bit_bytes[i];
-						
-						if ( bit == null || bit.length == 0 ){
-							
-							continue;
-						}
-						
-						int	type = bit_types[i];
-						
-						if ( type == 3 ){
-							
-							continue;
-						}
-						
-						if ( type == 0 || type == 1 ){
-							
-							if ( filter.contains( bit )){
-								
-								matches++;
-								
-							}else{
-								
-								failed	= true;
-								
-								break;
-							}
-						}else if ( type == 2 ){
-						
-							if ( !filter.contains( bit )){
-								
-								matches++;
-								
-							}else{
-								
-								failed	= true;
-								
-								break;
-							}
-						}else if ( type == 4 ){
-							
-							byte[][]	parts = extras[i];
-							
-							int	old_matches = matches;
-							
-							for ( byte[] p: parts ){
-								
-								if ( filter.contains( p )){
-								
-									matches++;
-									
-									break;
-								}
-							}
-							
-							if ( matches == old_matches ){
-								
-								failed = true;
-								
-								break;
-							}
-						}
-					}
-					
-					if ( matches > 0 && !failed ){
-						
-						result.add( fb.getContact());
-					}
-				}
-			}
-		}catch( UnsupportedEncodingException e ){
-			
-			Debug.out( e );
-		}
-		
-		return( result );
-	}
-	
-	private static final int PD_BLOOM_INITIAL_SIZE		= 1000;
-	private static final int PD_BLOOM_INCREMENT_SIZE	= 1000;
-	
-	
-	private BloomFilter	persist_del_bloom;
-	
-	protected byte[]
-	getPermDelKey(
-		RelatedContent	info )
-	{
-		byte[]	bytes = info.getHash();
-		
-		if ( bytes == null ){
-			
-			try{
-				bytes = new SHA1Simple().calculateHash( getPrivateInfoKey(info).getBytes( "ISO-8859-1" ));
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				return( null );
-			}
-		}
-		
-		byte[] key = new byte[8];
-		
-		System.arraycopy( bytes, 0, key, 0, 8 );
-		
-		return( key );
-	}
-	
-	protected List<byte[]>
-	loadPersistentlyDeleted()
-	{
-		List<byte[]> entries = null;
-		
-		if ( FileUtil.resilientConfigFileExists( PERSIST_DEL_FILE )){
-				
-			Map<String,Object> map = (Map<String,Object>)FileUtil.readResilientConfigFile( PERSIST_DEL_FILE );
-				
-			entries = (List<byte[]>)map.get( "entries" );
-		}
-	
-		if ( entries == null ){
-			
-			entries = new ArrayList<byte[]>(0);
-		}
-		
-		return( entries );
-	}
-	
-	protected void
-	addPersistentlyDeleted(
-		RelatedContent[]	content )
-	{		
-		if ( content.length == 0 ){
-			
-			return;
-		}
-	
-		List<byte[]> entries = loadPersistentlyDeleted();
-		
-		List<byte[]> new_keys = new ArrayList<byte[]>( content.length );
-		
-		for ( RelatedContent rc: content ){
-			
-			byte[] key = getPermDelKey( rc );
-			
-			new_keys.add( key );
-			
-			entries.add( key );
-		}
-		
-		Map<String,Object>	map = new HashMap<String, Object>();
-		
-		map.put( "entries", entries );
-		
-		FileUtil.writeResilientConfigFile( PERSIST_DEL_FILE, map );
-		
-		if ( persist_del_bloom != null ){
-			
-			if ( persist_del_bloom.getSize() / ( persist_del_bloom.getEntryCount() + content.length ) < 10 ){
-		
-				persist_del_bloom = BloomFilterFactory.createAddOnly( Math.max( PD_BLOOM_INITIAL_SIZE, persist_del_bloom.getSize() *10 + PD_BLOOM_INCREMENT_SIZE + content.length  ));
-				
-				for ( byte[] k: entries ){
-					
-					persist_del_bloom.add( k );
-				}
-			}else{
-				
-				for ( byte[] k: new_keys ){
-					
-					persist_del_bloom.add( k );
-				}
-			}
-		}
-	}
-	
-	protected boolean
-	isPersistentlyDeleted(
-		RelatedContent		content )
-	{
-		if ( persist_del_bloom == null ){
-			
-			List<byte[]> entries = loadPersistentlyDeleted();
-			
-			persist_del_bloom = BloomFilterFactory.createAddOnly( Math.max( PD_BLOOM_INITIAL_SIZE, entries.size()*10 + PD_BLOOM_INCREMENT_SIZE ));
-
-			for ( byte[] k: entries ){
-				
-				persist_del_bloom.add( k );
-			}
-		}
-		
-		byte[]	key = getPermDelKey( content );
-		
-		return( persist_del_bloom.contains( key ));
-	}
-
-	protected void
-	resetPersistentlyDeleted()
-	{
-		FileUtil.deleteResilientConfigFile( PERSIST_DEL_FILE );
-		
-		persist_del_bloom = BloomFilterFactory.createAddOnly( PD_BLOOM_INITIAL_SIZE );
-	}
-	
-	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 )
-	{
-		listeners.add( listener );
-	}
-	
-	public void
-	removeListener(
-		RelatedContentManagerListener		listener )
-	{
-		listeners.remove( listener );
-	}
-	
-	protected static class
-	ByteArrayHashMapEx<T>
-		extends ByteArrayHashMap<T>
-	{
-	    public T
-	    getRandomValueExcluding(
-	    	T	excluded )
-	    {
-	    	int	num = RandomUtils.nextInt( size );
-	    	
-	    	T result = null;
-	    	
-	        for (int j = 0; j < table.length; j++) {
-	        	
-		         Entry<T> e = table[j];
-		         
-		         while( e != null ){
-		        	 
-	              	T value = e.value;
-	               	
-	              	if ( value != excluded ){
-	              		
-	              		result = value;
-	              	}
-	              	
-	              	if ( num <= 0 && result != null ){
-	              		
-	              		return( result );
-	              	}
-	              	
-	              	num--;
-	              	
-	              	e = e.next;
-		        }
-		    }
-	    
-	        return( result );
-	    }
-	}
-	
-	private Map<String,Object>
-	serialiseDI(
-		DownloadInfo			info,
-		ContentCache			cc )
-	{
-		try{
-			Map<String,Object> info_map = new HashMap<String,Object>();
-			
-			info_map.put( "h", info.getHash());
-			
-			ImportExportUtils.exportString( info_map, "d", info.getTitle());
-			ImportExportUtils.exportInt( info_map, "r", info.getRand());
-			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());
-
-			byte[] tracker_keys = info.getTrackerKeys();
-			if ( tracker_keys != null ){
-				info_map.put( "k", tracker_keys );
-			}
-			
-			byte[] ws_keys = info.getWebSeedKeys();
-			if ( ws_keys != null ){
-				info_map.put( "w", ws_keys );
-			}
-			
-			String[] tags = info.getTags();
-			if ( tags != null ){
-				info_map.put( "g", encodeTags(tags));
-			}
-			if ( cc != null ){
-							
-				ImportExportUtils.exportBoolean( info_map, "u", info.isUnread());
-				ImportExportUtils.exportIntArray( info_map, "l", info.getRandList());
-				ImportExportUtils.exportInt( info_map, "s", info.getLastSeenSecs());
-				ImportExportUtils.exportInt( info_map, "e", info.getLevel());
-			}
-			
-			ImportExportUtils.exportLong(info_map, "cl", info.getChangedLocallyOn());
-			
-			return( info_map );
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			return( null );
-		}
-	}
-	
-	private DownloadInfo
-	deserialiseDI(
-		Map<String,Object>		info_map,
-		ContentCache			cc )
-	{
-		try{
-			byte[]	hash 	= (byte[])info_map.get("h");
-			String	title	= ImportExportUtils.importString( info_map, "d" );
-			int		rand	= ImportExportUtils.importInt( info_map, "r" );
-			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 );
-			byte[]	tracker_keys	= (byte[])info_map.get( "k");
-			byte[]	ws_keys			= (byte[])info_map.get( "w" );
-			long lastChangedLocally = ImportExportUtils.importLong( info_map, "cl" );
-			
-			if ( tracker_keys != null && tracker_keys.length % 4 != 0 ){
-				
-				tracker_keys = null;
-			}
-		
-			if ( ws_keys != null && ws_keys.length % 4 != 0 ){
-				
-				ws_keys = null;
-			}
-			
-			byte[]	_tags	= (byte[])info_map.get( "g" );
-
-			String[] tags = decodeTags( _tags );
-			
-			if ( cc == null ){
-			
-				 DownloadInfo info = new DownloadInfo( hash, hash, title, rand, tracker, tracker_keys, ws_keys, tags, 0, false, size, date, seeds_leechers, cnet );
-				 info.setChangedLocallyOn(lastChangedLocally);
-				 return info;
-				
-			}else{
-				
-				boolean unread = ImportExportUtils.importBoolean( info_map, "u" );
-				
-				int[] rand_list = ImportExportUtils.importIntArray( info_map, "l" );
-				
-				int	last_seen = ImportExportUtils.importInt( info_map, "s" );
-				
-				int	level = ImportExportUtils.importInt( info_map, "e" );
-				
-				DownloadInfo info = new DownloadInfo( hash, title, rand, tracker, tracker_keys, ws_keys, tags, unread, rand_list, last_seen, level, size, date, seeds_leechers, cnet, cc );
-        info.setChangedLocallyOn(lastChangedLocally);
-        return info;
-			}
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			return( null );
-		}
-	}
-	
-	private void
-	dump()
-	{
-		RelatedContent[] related_content = getRelatedContent();
-		
-		ByteArrayHashMap<List<String>>	tk_map = new ByteArrayHashMap<List<String>>();
-		ByteArrayHashMap<List<String>>	ws_map = new ByteArrayHashMap<List<String>>();
-		
-		for ( RelatedContent rc: related_content ){
-						
-			byte[] tracker_keys = rc.getTrackerKeys();
-			
-			if ( tracker_keys != null ){
-				
-				for (int i=0;i<tracker_keys.length;i+=4 ){
-					
-					byte[] tk = new byte[4];
-					
-					System.arraycopy( tracker_keys, i, tk, 0, 4 );
-					
-					List<String> titles = tk_map.get( tk );
-					
-					if ( titles == null ){
-						
-						titles = new ArrayList<String>();
-						
-						tk_map.put( tk, titles );
-					}
-					
-					titles.add( rc.getTitle());
-				}
-			}
-			byte[] ws_keys = rc.getWebSeedKeys();
-			
-			if ( ws_keys != null ){
-				
-				for (int i=0;i<ws_keys.length;i+=4 ){
-					
-					byte[] wk = new byte[4];
-					
-					System.arraycopy( ws_keys, i, wk, 0, 4 );
-					
-					List<String> titles = ws_map.get( wk );
-					
-					if ( titles == null ){
-						
-						titles = new ArrayList<String>();
-						
-						ws_map.put( wk, titles );
-					}
-					
-					titles.add( rc.getTitle());
-				}
-			}
-		}
-		
-		System.out.println( "-- Trackers --" );
-		
-		for ( byte[] key: tk_map.keys()){
-			
-			List<String>	titles = tk_map.get( key );
-			
-			System.out.println( ByteFormatter.encodeString( key ));
-			
-			for ( String title: titles ){
-				
-				System.out.println( "    " + title );
-			}
-		}
-		
-		System.out.println( "-- Web Seeds --" );
-		
-		for ( byte[] key: ws_map.keys()){
-			
-			List<String>	titles = ws_map.get( key );
-			
-			System.out.println( ByteFormatter.encodeString( key ));
-			
-			for ( String title: titles ){
-				
-				System.out.println( "    " + title );
-			}
-		}
-	}
-	
-	protected class
-	DownloadInfo
-		extends RelatedContent
-	{
-		final private int		rand;
-		
-		private boolean			unread	= true;
-		private int[]			rand_list;
-		private int				last_seen;
-		private int				level;
-		private boolean			explicit;
-		
-			// we *need* this reference here to manage garbage collection correctly
-		
-		private ContentCache	cc;
-		
-		protected
-		DownloadInfo(
-			byte[]		_related_to,
-			byte[]		_hash,
-			String		_title,
-			int			_rand,
-			String		_tracker,
-			byte[]		_tracker_keys,
-			byte[]		_ws_keys,
-			String[]	_tags,
-			int			_level,
-			boolean		_explicit,
-			long		_size,
-			int			_date,
-			int			_seeds_leechers,
-			byte		_cnet )
-		{
-			super( _related_to, _title, _hash, _tracker, _tracker_keys, _ws_keys, _tags, _size, _date, _seeds_leechers, _cnet );
-			
-			rand		= _rand;
-			level		= _level;
-			explicit	= _explicit;
-			
-			updateLastSeen();
-		}
-		
-		protected
-		DownloadInfo(
-			byte[]			_hash,
-			String			_title,
-			int				_rand,
-			String			_tracker,
-			byte[]			_tracker_keys,
-			byte[]			_ws_keys,
-			String[]		_tags,
-			boolean			_unread,
-			int[]			_rand_list,
-			int				_last_seen,
-			int				_level,
-			long			_size,
-			int				_date,
-			int				_seeds_leechers,
-			byte			_cnet,
-			ContentCache	_cc )
-		{
-			super( _title, _hash, _tracker, _tracker_keys, _ws_keys, _tags, _size, _date, _seeds_leechers, _cnet );
-			
-			rand		= _rand;
-			unread		= _unread;
-			rand_list	= _rand_list;
-			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
-		addInfo(
-			DownloadInfo		info )
-		{
-			boolean	result = false;
-			
-			synchronized( this ){
-		
-				updateLastSeen();
-				
-				int r = info.getRand();
-				
-				if ( rand_list == null ){
-					
-					rand_list = new int[]{ r };
-										
-					result	= true;
-					
-				}else{
-					
-					boolean	match = false;
-					
-					for (int i=0;i<rand_list.length;i++){
-						
-						if ( rand_list[i] == r ){
-							
-							match = true;
-							
-							break;
-						}
-					}
-					
-					if ( !match && rand_list.length < MAX_RANK ){
-						
-						int	len = rand_list.length;
-						
-						int[]	new_rand_list = new int[len+1];
-						
-						System.arraycopy( rand_list, 0, new_rand_list, 0, len );
-						
-						new_rand_list[len] = r;
-						
-						rand_list = new_rand_list;
-						
-						result = true;
-					}
-				}
-			}
-				
-			if ( info.getLevel() < level ){
-				
-				level = info.getLevel();
-				
-				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 && getDateHours() == 0 ){
-				
-				setDateHours( d );
-				
-				result = true;
-			}
-				
-			String[] other_tags = info.getTags();
-			
-			if ( other_tags != null && other_tags.length > 0 ){
-			
-				String[] existing_tags = getTags();
-				
-				if ( existing_tags == NO_TAGS ){
-					
-					setTags( other_tags );
-					
-					result = true;
-					
-				}else{
-					
-					boolean	same;
-					
-					if ( other_tags.length == existing_tags.length ){
-					
-						if ( existing_tags.length == 1 ){
-							
-							same = other_tags[0].equals( existing_tags[0] );
-							
-						}else{
-							
-							same = true;
-							
-							for ( int i=0;i<existing_tags.length;i++ ){
-								
-								String e_tag = existing_tags[i];
-								
-								boolean	found = false;
-								
-								for ( int j=0;j<other_tags.length;j++){
-									
-									if ( e_tag.equals( other_tags[j])){
-										
-										found = true;
-										
-										break;
-									}
-								}
-								
-								if ( !found ){
-									
-									same = false;
-									
-									break;
-								}
-							}
-						}
-					}else{
-					
-						same = false;
-					}
-					
-					if ( !same ){
-						
-						Set<String>	tags = new HashSet<String>();
-						
-						for ( String t: existing_tags ){
-							tags.add( t );
-						}
-						for ( String t: other_tags ){
-							tags.add( t );
-						}
-						
-						setTags( tags.toArray( new String[tags.size()]));
-						
-						result = true;
-					}
-				}
-			}
-
-			if (result) {
-				setChangedLocallyOn(0);
-			}
-			return( result );
-		}
-		
-		public int
-		getLevel()
-		{
-			return( level );
-		}
-		
-		protected boolean
-		isExplicit()
-		{
-			return( explicit );
-		}
-		
-		protected void
-		setExplicit(
-			boolean		b )
-		{
-			explicit	= b;
-		}
-		
-		protected void
-		updateLastSeen()
-		{
-				// persistence of this is piggy-backed on other saves to limit resource usage
-				// only therefore a vague measure
-
-			last_seen	= (int)( SystemTime.getCurrentTime()/1000 );
-		}
-		
-		public int
-		getRank()
-		{
-			return( rand_list==null?0:rand_list.length );
-		}
-		
-		public boolean
-		isUnread()
-		{
-			return( unread );
-		}
-		
-		protected void
-		setPublic(
-			ContentCache	_cc )
-		{
-			cc	= _cc;
-			
-			if ( unread ){
-				
-				incrementUnread();
-			}
-			
-			rand_list = new int[]{ rand };
-			setChangedLocallyOn(0);
-		}
-		
-		public int
-		getLastSeenSecs()
-		{
-			return( last_seen );
-		}
-		
-		protected void
-		setUnreadInternal(
-			boolean	_unread )
-		{
-			synchronized( this ){
-
-				unread = _unread;
-			}
-		}
-		
-		public void
-		setUnread(
-			boolean	_unread )
-		{
-			boolean	changed = false;
-			
-			synchronized( this ){
-				
-				if ( unread != _unread ){
-				
-					unread = _unread;
-					
-					changed = true;
-				}
-			}
-			
-			if ( changed ){
-			
-				if ( _unread ){
-					
-					incrementUnread();
-					
-				}else{
-					
-					decrementUnread();
-				}
-				
-				setChangedLocallyOn(0);
-				contentChanged( this );
-			}
-		}
-		
-		protected int
-		getRand()
-		{
-			return( rand );
-		}
-		
-		protected int[]
-		getRandList()
-		{
-			return( rand_list );
-		}
-		
-		public Download 
-		getRelatedToDownload() 
-		{
-			try{
-				return( getDownload( getRelatedToHash()));
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				return( null );
-			}
-		}
-		
-		public void 
-		delete() 
-		{
-			setChangedLocallyOn(0);
-			RelatedContentManager.this.delete( new RelatedContent[]{ this });
-		}
-		
-		public String
-		getString()
-		{
-			return( super.getString() + ", " + rand + ", rl=" + rand_list + ", last_seen=" + last_seen + ", level=" + level );
-		}
-	}
-	
-	private static class
-	ContentCache
-	{
-		private Map<String,DownloadInfo>						related_content			= new HashMap<String, DownloadInfo>();
-		private ByteArrayHashMapEx<ArrayList<DownloadInfo>>		related_content_map		= new ByteArrayHashMapEx<ArrayList<DownloadInfo>>();
-	}
-	
-	private static class
-	SecondaryLookup
-	{
-		final private byte[]	hash;
-		final private int		level;
-		
-		protected
-		SecondaryLookup(
-			byte[]		_hash,
-			int			_level )
-		{
-			hash	= _hash;
-			level	= _level;
-		}
-		
-		protected byte[]
-		getHash()
-		{
-			return( hash );
-		}
-		
-		protected int
-		getLevel()
-		{
-			return( level );
-		}
-	}
-	
-	protected class
-	RCMSearchXFer
-		implements DistributedDatabaseTransferType
-	{	
-	}
-	
-	private static class
-	MySearchObserver
-		implements SearchObserver
-	{
-		private SearchObserver		observer;
-		private AtomicInteger		num_results = new AtomicInteger();
-		
-		private
-		MySearchObserver(
-			SearchObserver		_observer )
-		{
-			observer = _observer;
-		}
-		
-		public void
-		resultReceived(
-			SearchInstance		search,
-			SearchResult		result )
-		{
-			observer.resultReceived( search, result );
-			
-			logSearch( "results=" + num_results.incrementAndGet());
-		}
-		
-		private int
-		getResultCount()
-		{
-			return( num_results.get());
-		}
-		
-		public void
-		complete()
-		{
-			observer.complete();
-		}
-		
-		public void
-		cancelled()
-		{
-			observer.cancelled();
-		}
-		
-		public Object
-		getProperty(
-			int		property )
-		{
-			return( observer.getProperty(property));
-		}
-	}
-	
-	private static class
-	ForeignBloom
-	{
-		private DistributedDatabaseContact	contact;
-		private BloomFilter					filter;
-		
-		private long						created;
-		private long						last_update;
-		
-		private
-		ForeignBloom(
-			DistributedDatabaseContact		_contact,
-			BloomFilter						_filter )
-		{
-			contact	= _contact;
-			filter	= _filter;
-			
-			created	 = SystemTime.getMonotonousTime();
-			
-			last_update	= created;
-		}
-		
-		public DistributedDatabaseContact
-		getContact()
-		{
-			return( contact );
-		}
-		
-		public BloomFilter
-		getFilter()
-		{
-			return( filter );
-		}
-		
-		public long
-		getCreateTime()
-		{
-			return( created );
-		}
-		
-		public long
-		getLastUpdateTime()
-		{
-			return( last_update );
-		}
-		
-		public void
-		updateFilter(
-			BloomFilter		f )
-		{
-			filter		= f;
-			last_update	= SystemTime.getMonotonousTime();
-		}
-	}
-}
+/*
+ * Created on Jul 8, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.content;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+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.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLGroup;
+import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+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.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.Debug;
+import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.core3.util.RandomUtils;
+import org.gudy.azureus2.core3.util.SHA1Simple;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+import org.gudy.azureus2.core3.util.StringInterner;
+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.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.DistributedDatabaseTransferType;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+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.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.pluginsimpl.local.ddb.DDBaseImpl;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.cnetwork.ContentNetwork;
+import com.aelitis.azureus.core.proxy.impl.AEPluginProxyHandler;
+import com.aelitis.azureus.core.security.CryptoManagerFactory;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManager;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
+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;
+import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
+import com.aelitis.azureus.plugins.dht.DHTPlugin;
+import com.aelitis.azureus.plugins.dht.DHTPluginContact;
+import com.aelitis.azureus.plugins.dht.DHTPluginInterface;
+import com.aelitis.azureus.plugins.dht.DHTPluginOperationListener;
+import com.aelitis.azureus.plugins.dht.DHTPluginValue;
+import com.aelitis.azureus.util.ImportExportUtils;
+
+public class 
+RelatedContentManager
+{
+	public static final long FILE_ASSOC_MIN_SIZE	= 50*1024*1024;
+	
+	public static final int RCM_SEARCH_PROPERTY_CONTENT_NETWORK	= 50000;	// don't change these, used in plugin
+	public static final int RCM_SEARCH_PROPERTY_TRACKER_KEYS	= 50001;
+	public static final int RCM_SEARCH_PROPERTY_WEB_SEED_KEYS	= 50002;
+	public static final int RCM_SEARCH_PROPERTY_TAGS			= 50003;
+	public static final int RCM_SEARCH_PROPERTY_NETWORKS		= 50004;
+	
+	private static final boolean 	TRACE 			= false;
+		
+	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	TEMPORARY_SPACE_DELTA	= 50;
+	
+	private static final int	MAX_RANK	= 100;
+	
+	private static final String	CONFIG_FILE 				= "rcm.config";
+	private static final String	PERSIST_DEL_FILE 			= "rcmx.config";
+	
+	private static final String	CONFIG_TOTAL_UNREAD	= "rcm.numunread.cache";
+	
+	private static RelatedContentManager	singleton;
+	private static AzureusCore				core;
+	
+	protected static final int TIMER_PERIOD					= 30*1000;
+	
+	private static final int CONFIG_SAVE_CHECK_PERIOD		= 60*1000;
+	private static final int CONFIG_SAVE_PERIOD				= 5*60*1000;
+	private static final int CONFIG_SAVE_CHECK_TICKS		= CONFIG_SAVE_CHECK_PERIOD/TIMER_PERIOD;
+	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 PUBLISH_SLEEPING_CHECK_PERIOD	= 5*60*1000;
+	private static final int PUBLISH_SLEEPING_CHECK_TICKS	= PUBLISH_SLEEPING_CHECK_PERIOD/TIMER_PERIOD;
+
+	private static final int SECONDARY_LOOKUP_PERIOD		= 15*60*1000;
+	private static final int SECONDARY_LOOKUP_TICKS			= SECONDARY_LOOKUP_PERIOD/TIMER_PERIOD;
+	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;
+	
+	protected static final byte		NET_NONE	= 0x00;
+	protected static final byte		NET_PUBLIC	= 0x01;
+	protected static final byte		NET_I2P		= 0x02;
+	protected static final byte		NET_TOR		= 0x04;
+	
+	private static final String[] NET_PUBLIC_ARRAY 			= { AENetworkClassifier.AT_PUBLIC };
+	private static final String[] NET_I2P_ARRAY 			= { AENetworkClassifier.AT_I2P };
+	private static final String[] NET_TOR_ARRAY 			= { AENetworkClassifier.AT_TOR };
+	private static final String[] NET_PUBLIC_AND_I2P_ARRAY 	= { AENetworkClassifier.AT_PUBLIC, AENetworkClassifier.AT_I2P };
+
+	public static synchronized void
+	preInitialise(
+		AzureusCore		_core )
+	{
+		core		= _core;
+	}
+	
+	public static synchronized RelatedContentManager
+	getSingleton()
+	
+		throws ContentException
+	{
+		if ( singleton == null ){
+			
+			singleton = new RelatedContentManager();
+		}
+		
+		return( singleton );
+	}
+	
+	protected final Object	rcm_lock	= new Object();
+
+	private PluginInterface 				plugin_interface;
+	private TorrentAttribute 				ta_networks;
+	private TorrentAttribute 				ta_category;
+	private DHTPluginInterface				public_dht_plugin;
+				
+	private volatile Map<Byte,DHTPluginInterface>		i2p_dht_plugin_map = new HashMap<Byte, DHTPluginInterface>();
+
+	private TagManager						tag_manager;
+	
+	private long	global_random_id = -1;
+	
+	private LinkedList<DownloadInfo>			pub_download_infos1 	= new LinkedList<DownloadInfo>();
+	private LinkedList<DownloadInfo>			pub_download_infos2 	= new LinkedList<DownloadInfo>();
+		
+	private LinkedList<DownloadInfo>			non_pub_download_infos1 	= new LinkedList<DownloadInfo>();
+	private LinkedList<DownloadInfo>			non_pub_download_infos2 	= new LinkedList<DownloadInfo>();
+	
+	private ByteArrayHashMapEx<DownloadInfo>	download_info_map	= new ByteArrayHashMapEx<DownloadInfo>();
+	private Set<String>							download_priv_set	= new HashSet<String>();
+
+	
+	private final boolean	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>();
+	
+	private AESemaphore initialisation_complete_sem = new AESemaphore( "RCM:init" );
+	
+	private ContentCache				content_cache_ref;
+	private WeakReference<ContentCache>	content_cache;
+	
+	private boolean		content_dirty;
+	private long		last_config_access;		
+	private int			content_discard_ticks;
+	
+	private AtomicInteger	total_unread = new AtomicInteger( COConfigurationManager.getIntParameter( CONFIG_TOTAL_UNREAD, 0 ));
+	
+	private AsyncDispatcher	content_change_dispatcher 	= new AsyncDispatcher();
+	
+	private static final int SECONDARY_LOOKUP_CACHE_MAX = 10;
+	
+	private LinkedList<SecondaryLookup> secondary_lookups = new LinkedList<SecondaryLookup>();
+	
+	private boolean	secondary_lookup_in_progress;
+	private long	secondary_lookup_complete_time;
+	
+	private RCMSearchXFer			transfer_type = new RCMSearchXFer();
+
+	private final 	CopyOnWriteList<RelatedContentSearcher>	searchers = new CopyOnWriteList<RelatedContentSearcher>();
+	
+	
+	private static final int MAX_TRANSIENT_CACHE	= 256;
+	
+	protected static Map<String,DownloadInfo> transient_info_cache =
+		new LinkedHashMap<String,DownloadInfo>(MAX_TRANSIENT_CACHE,0.75f,true)
+		{
+			protected boolean 
+			removeEldestEntry(
+		   		Map.Entry<String,DownloadInfo> eldest) 
+			{
+				return size() > MAX_TRANSIENT_CACHE;
+			}
+		};
+				
+			
+	private boolean	persist;
+	
+	{
+		COConfigurationManager.addAndFireParameterListener(
+			"rcm.persist",
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					String parameterName )
+				{
+					persist = COConfigurationManager.getBooleanParameter( "rcm.persist" ) || true;
+				}
+			});
+		
+			// remove one day
+		
+		COConfigurationManager.removeParameter( "rcm.dlinfo.history" );
+	}
+	
+	protected
+	RelatedContentManager()
+	
+		throws ContentException
+	{
+		COConfigurationManager.addAndFireParameterListeners(
+				new String[]{
+					"rcm.ui.enabled",
+					"rcm.max_search_level",
+					"rcm.max_results",
+				},
+				new ParameterListener()
+				{
+					public void 
+					parameterChanged(
+						String name )
+					{
+						max_search_level 	= COConfigurationManager.getIntParameter( "rcm.max_search_level", 3 );
+						max_results		 	= COConfigurationManager.getIntParameter( "rcm.max_results", 500 );
+					}
+				});
+		
+		if ( !FeatureAvailability.isRCMEnabled() || 
+			 !COConfigurationManager.getBooleanParameter( "rcm.overall.enabled", true )){
+			
+			enabled		= false;
+			
+			deleteRelatedContent();
+			
+			initialisation_complete_sem.releaseForever();
+
+			return;
+		}
+		
+		enabled = true;
+		
+		try{
+			if ( core == null ){
+				
+				throw( new ContentException( "getSingleton called before pre-initialisation" ));
+			}
+			
+			while( global_random_id == -1 ){
+				
+				global_random_id = COConfigurationManager.getLongParameter( "rcm.random.id", -1 );
+				
+				if ( global_random_id == -1 ){
+					
+					global_random_id = RandomUtils.nextLong();
+					
+					COConfigurationManager.setParameter( "rcm.random.id", global_random_id );
+				}
+			}
+				
+			plugin_interface = core.getPluginManager().getDefaultPluginInterface();
+			
+			ta_networks 	= plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_NETWORKS );
+			ta_category 	= plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_CATEGORY );
+
+			tag_manager	= TagManagerFactory.getTagManager();
+			
+			plugin_interface.getUtilities().createDelayedTask(new AERunnable() {
+				public void runSupport() {
+					SimpleTimer.addEvent(
+							"rcm.delay.init",
+							SystemTime.getOffsetTime( 15*1000 ),
+							new TimerEventPerformer()
+							{
+								public void 
+								perform(
+									TimerEvent event )
+								{
+									delayedInit();
+								}
+							});
+				}
+			}).queue();
+			
+		}catch( Throwable e ){
+			
+			initialisation_complete_sem.releaseForever();
+			
+			if ( e instanceof ContentException ){
+				
+				throw((ContentException)e);
+			}
+			
+			throw( new ContentException( "Initialisation failed", e ));
+		}
+	}
+	
+	protected PluginInterface
+	getPluginInterface()
+	{
+		return( plugin_interface );
+	}
+	
+	private void delayedInit() {
+		
+		plugin_interface.addListener(
+			new PluginListener()
+			{
+				public void
+				initializationComplete()
+				{
+					if ( !persist ){
+						
+						deleteRelatedContent();
+					}
+					
+					try{
+						PluginInterface dht_pi = 
+							plugin_interface.getPluginManager().getPluginInterfaceByClass(
+										DHTPlugin.class );
+			
+						if ( dht_pi != null ){
+				
+							DHTPlugin dp = (DHTPlugin)dht_pi.getPlugin();
+							
+							public_dht_plugin = dp;
+
+							RelatedContentSearcher public_searcher = new RelatedContentSearcher( RelatedContentManager.this, transfer_type, dp );
+							
+							searchers.add( public_searcher );
+							
+							DownloadManager dm = plugin_interface.getDownloadManager();
+							
+							Download[] downloads = dm.getDownloads();
+							
+							addDownloads( downloads, true );
+							
+							dm.addListener(
+								new DownloadManagerListener()
+								{
+									public void
+									downloadAdded(
+										Download	download )
+									{
+										addDownloads( new Download[]{ download }, false );
+									}
+									
+									public void
+									downloadRemoved(
+										Download	download )
+									{
+									}
+								},
+								false );
+							
+							SimpleTimer.addPeriodicEvent(
+								"RCM:publisher",
+								TIMER_PERIOD,
+								new TimerEventPerformer()
+								{
+									private int	tick_count;
+									
+									public void 
+									perform(
+										TimerEvent event ) 
+									{
+										tick_count++;
+										
+										if ( tick_count == 1 ){
+											
+											List<DistributedDatabase> ddbs = DDBaseImpl.getDDBs( new String[] {AENetworkClassifier.AT_I2P });
+											
+											for ( DistributedDatabase ddb: ddbs ){
+												
+												if ( ddb.getNetwork() == AENetworkClassifier.AT_I2P ){
+													
+													DHTPluginInterface i2p_dht = ((DDBaseImpl)ddb).getDHTPlugin();
+													
+													RelatedContentSearcher i2p_searcher = new RelatedContentSearcher( RelatedContentManager.this, transfer_type, i2p_dht );
+													
+													searchers.add( i2p_searcher );
+												}
+											}
+										}
+										
+										if ( enabled ){
+												
+											if ( tick_count >= INITIAL_PUBLISH_TICKS ){
+												
+												if ( tick_count % ( public_dht_plugin.isSleeping()?PUBLISH_SLEEPING_CHECK_TICKS: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_CHECK_TICKS == 0 ){
+													
+													saveRelatedContent( tick_count );
+												}
+											}							
+										}
+										
+										for ( RelatedContentSearcher searcher: searchers ){
+										
+											searcher.timerTick( enabled, tick_count );
+										}
+									}		
+								});
+						}										
+					}finally{
+							
+						initialisation_complete_sem.releaseForever();
+					}
+				}
+				
+				public void
+				closedownInitiated()
+				{
+					saveRelatedContent( 0 );
+				}
+				
+				public void
+				closedownComplete()
+				{
+				}
+			});
+	}
+	
+	public boolean
+	isEnabled()
+	{
+		return( enabled );
+	}
+		
+	public int
+	getMaxSearchLevel()
+	{
+		return( max_search_level );
+	}
+	
+	public void
+	setMaxSearchLevel(
+		int		_level )
+	{
+		COConfigurationManager.setParameter( "rcm.max_search_level", _level );
+	}
+	
+	public int
+	getMaxResults()
+	{
+		return( max_results );
+	}
+	
+	public void
+	setMaxResults(
+		int		_max )
+	{
+		COConfigurationManager.setParameter( "rcm.max_results", _max );
+		
+		enforceMaxResults( false );
+	}
+	
+	private DHTPluginInterface
+	selectDHT(
+		byte		networks )
+	{
+		DHTPluginInterface	result = null;
+		
+		if ((networks & NET_PUBLIC ) != 0 ){
+			
+			result = public_dht_plugin;
+			
+		}else if ((networks & NET_I2P ) != 0 ){
+			
+			synchronized( i2p_dht_plugin_map ){
+			
+				result = i2p_dht_plugin_map.get( networks );
+			
+				if ( result == null && !i2p_dht_plugin_map.containsKey( networks )){
+	
+					try{
+						
+						List<DistributedDatabase> ddbs = DDBaseImpl.getDDBs( convertNetworks( networks ));
+						
+						for ( DistributedDatabase ddb: ddbs ){
+							
+							if ( ddb.getNetwork() == AENetworkClassifier.AT_I2P ){
+								
+								result = ((DDBaseImpl)ddb).getDHTPlugin();
+							}
+						}
+					}finally{
+						
+						i2p_dht_plugin_map.put( networks, result );
+					}
+				}
+			}
+		}
+		
+		if ( result != null ){
+			
+			if ( !result.isEnabled()){
+				
+				result = null;
+			}
+		}
+		
+		return( result );
+	}
+	
+	protected void
+	addDownloads(
+		Download[]		downloads,
+		boolean			initialising )
+	{
+		synchronized( rcm_lock ){
+	
+			List<DownloadInfo>	new_info = new ArrayList<DownloadInfo>( downloads.length );
+			
+			for ( Download download: downloads ){
+				
+				try{
+					if ( !download.isPersistent()){
+						
+						continue;
+					}
+					
+					Torrent	torrent = download.getTorrent();
+	
+					if ( torrent == null ){
+						
+						continue;
+					}
+					
+					byte[]	hash = torrent.getHash();
+
+					if ( download_info_map.containsKey( hash )){
+						
+						continue;
+					}
+					
+					byte nets = getNetworks( download );
+
+					if ( nets == NET_NONE ){
+						
+						continue;
+					}
+					
+					TOTorrent to_torrent = PluginCoreUtils.unwrap( torrent );
+					
+					if ( !TorrentUtils.isReallyPrivate( to_torrent )){
+						
+						DownloadManagerState state = PluginCoreUtils.unwrap( download ).getDownloadState();
+
+						if ( state.getFlag(DownloadManagerState.FLAG_LOW_NOISE )){
+							
+							continue;
+						}
+						
+						LinkedList<DownloadInfo>			download_infos1;
+						LinkedList<DownloadInfo>			download_infos2;
+
+						if (( nets & NET_PUBLIC ) != 0 ){
+							
+							download_infos1 	= pub_download_infos1;
+							download_infos2 	= pub_download_infos2;
+							
+						}else{
+							
+							download_infos1		= non_pub_download_infos1;
+							download_infos2 	= non_pub_download_infos2;
+						}
+						
+						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));
+						}
+
+						byte[][] keys = getKeys( download );
+						
+						DownloadInfo info = 
+							new DownloadInfo(
+								hash,
+								hash,
+								download.getName(),
+								(int)rand,
+								torrent.isPrivate()?StringInterner.intern(torrent.getAnnounceURL().getHost()):null,
+								keys[0],
+								keys[1],
+								getTags( download ),
+								nets,
+								0,
+								false,
+								torrent.getSize(),
+								(int)( to_torrent.getCreationDate()/(60*60)),
+								seeds_leechers,
+								(byte)PlatformTorrentUtils.getContentNetworkID( to_torrent ));
+						
+						new_info.add( info );
+						
+						if ( initialising || download_infos1.size() == 0 ){
+							
+							download_infos1.add( info );
+							
+						}else{
+							
+							download_infos1.add( RandomUtils.nextInt( download_infos1.size()), info );
+						}
+						
+						download_infos2.add( info );
+						
+						download_info_map.put( hash, info );
+						
+						if ( info.getTracker() != null ){
+							
+							download_priv_set.add( getPrivateInfoKey( info ));
+						}
+					}
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+			
+			List<Map<String,Object>> history = (List<Map<String,Object>>)COConfigurationManager.getListParameter( "rcm.dlinfo.history.privx", new ArrayList<Map<String,Object>>());
+			
+			if ( initialising ){
+		
+				int padd = MAX_HISTORY - download_info_map.size();
+				
+				for ( int i=0;i<history.size() && padd > 0;i++ ){
+					
+					try{
+						DownloadInfo info = deserialiseDI((Map<String,Object>)history.get(i), null);
+						
+						if ( info != null && !download_info_map.containsKey( info.getHash())){
+							
+							download_info_map.put( info.getHash(), info );
+							
+							if ( info.getTracker() != null ){
+								
+								download_priv_set.add( getPrivateInfoKey( info ));
+							}
+							
+							if (( info.getNetworksInternal() & NET_PUBLIC ) != 0 ){
+							
+								pub_download_infos1.add( info );
+								pub_download_infos2.add( info );
+							
+							}else{
+								
+								non_pub_download_infos1.add( info );
+								non_pub_download_infos2.add( info );
+							}
+							
+							padd--;
+						}
+					}catch( Throwable e ){
+						
+					}
+				}
+				
+				Collections.shuffle( pub_download_infos1 );
+				Collections.shuffle( non_pub_download_infos1 );
+				
+			}else{
+				
+				if ( new_info.size() > 0 ){
+					
+					final List<String>	base32_hashes = new ArrayList<String>();
+					
+					for ( DownloadInfo info: new_info ){
+						
+						byte[] hash = info.getHash();
+						
+						if ( hash != null ){
+							
+							base32_hashes.add( Base32.encode( hash ));
+						}
+						
+						Map<String,Object> map = serialiseDI( info, null );
+							
+						if ( map != null ){
+							
+							history.add( map );	
+						}
+					}
+					
+					while( history.size() > MAX_HISTORY ){
+						
+						history.remove(0);
+					}
+					
+					COConfigurationManager.setParameter( "rcm.dlinfo.history.privx", history );
+					
+					if ( base32_hashes.size() > 0 ){
+						
+						content_change_dispatcher.dispatch(
+							new AERunnable()
+							{
+								public void
+								runSupport()
+								{
+									List<RelatedContent>	to_remove = new ArrayList<RelatedContent>();
+									
+									synchronized( rcm_lock ){
+										
+										ContentCache content_cache = loadRelatedContent();
+										
+										for ( String h: base32_hashes ){
+										
+											DownloadInfo di = content_cache.related_content.get( h );
+											
+											if ( di != null ){
+												
+												to_remove.add( di );
+											}
+										}
+									}
+									
+									if ( to_remove.size() > 0 ){
+										
+										delete( to_remove.toArray( new RelatedContent[ to_remove.size()] ));
+									}
+								}
+							});
+					}
+				}
+			}
+		}
+	}
+	
+	protected void
+	republish()
+	{
+		synchronized( rcm_lock ){
+
+			if ( publishing_count > 0 ){
+				
+				return;
+			}
+			
+			if ( pub_download_infos1.isEmpty()){
+				
+				List<DownloadInfo> list = download_info_map.values();
+				
+				for ( DownloadInfo info: list ){
+					
+					if (( info.getNetworksInternal() & NET_PUBLIC ) != 0 ){
+			
+						pub_download_infos1.add( info );
+						pub_download_infos2.add( info );
+					}
+				}
+				
+				Collections.shuffle( pub_download_infos1 );
+			}
+			
+			if ( non_pub_download_infos1.isEmpty()){
+				
+				List<DownloadInfo> list = download_info_map.values();
+				
+				for ( DownloadInfo info: list ){
+					
+					if (( info.getNetworksInternal() & NET_PUBLIC ) == 0 ){
+				
+						non_pub_download_infos1.add( info );
+						non_pub_download_infos2.add( info );
+					}
+				}
+				
+				Collections.shuffle( non_pub_download_infos1 );
+			}
+		}
+	}
+	
+	private boolean last_pub_was_pub;
+	
+	protected void
+	publish()
+	{
+		while( true ){
+			
+			DownloadInfo	info1 = null;
+			DownloadInfo	info2 = null;
+
+			synchronized( rcm_lock ){
+	
+				if ( publishing_count >= MAX_CONCURRENT_PUBLISH ){
+					
+						// too busy
+					
+					return;
+				}
+				
+				if ( download_info_map.size() == 1 ){
+					
+						// only one download, nothing to pair up with
+					
+					return;
+				}
+				
+				boolean	pub_ok = false;
+				
+				if ( 	pub_download_infos1.isEmpty() ||
+						( 	pub_download_infos1.size() == 1 && 
+							pub_download_infos1.getFirst() == pub_download_infos2.getFirst())){
+					
+					// either none or only one download remaining to be published and it has no partner
+					
+				}else{
+					
+					pub_ok = true;
+				}
+				
+				boolean	non_pub_ok = false;
+				
+				if ( 	non_pub_download_infos1.isEmpty() ||
+						( 	non_pub_download_infos1.size() == 1 && 
+							non_pub_download_infos1.getFirst() == non_pub_download_infos2.getFirst())){
+					
+					// either none or only one download remaining to be published and it has no partner
+					
+				}else{
+					
+					non_pub_ok = true;
+				}
+				
+				if ( !( pub_ok || non_pub_ok )){
+					
+					return;
+				}
+				
+				LinkedList<DownloadInfo> download_infos1;
+				LinkedList<DownloadInfo> download_infos2;
+				
+				if ( pub_ok && non_pub_ok ){
+				
+					if ( last_pub_was_pub ){
+						
+						pub_ok = false;
+					}
+					
+					last_pub_was_pub = !last_pub_was_pub;
+				}
+				
+				if ( pub_ok ){
+					
+					download_infos1 = pub_download_infos1;
+					download_infos2 = pub_download_infos2;
+					
+				}else{
+					
+					download_infos1 = non_pub_download_infos1;
+					download_infos2 = non_pub_download_infos2;
+				}
+				
+				if ( download_infos1.isEmpty() || download_info_map.size() == 1 ){
+					
+					return;
+				}
+							
+				info1 = download_infos1.removeFirst();
+				
+				Iterator<DownloadInfo> it = download_infos2.iterator();
+				
+				while( it.hasNext()){
+					
+					info2 = it.next();
+					
+					if ( info1 != info2 || download_infos2.size() == 1 ){
+						
+						it.remove();
+						
+						break;
+					}
+				}
+				
+				if ( info1 == info2 ){
+									
+					return;
+				}
+				
+				publishing_count++;
+			}
+			
+			try{
+				if ( !publish( info1, info2 )){
+				
+					synchronized( rcm_lock ){
+
+						publishing_count--;
+					}
+				}				
+			}catch( Throwable e ){
+				
+				synchronized( rcm_lock ){
+
+					publishing_count--;
+				}
+				
+				Debug.out( e );
+			}
+		}
+	}
+	
+	protected void
+	publishNext()
+	{
+		synchronized( rcm_lock ){
+
+			publishing_count--;
+			
+			if ( publishing_count < 0 ){
+				
+					// shouldn't happen but whatever
+				
+				publishing_count = 0;
+			}
+		}
+		
+		publish();
+	}
+	
+	protected boolean
+	publish(
+		final DownloadInfo	from_info,
+		final DownloadInfo	to_info )
+	
+		throws Exception
+	{		
+		final DHTPluginInterface dht_plugin = selectDHT( from_info.getNetworksInternal());
+
+		// System.out.println( "publish: " + from_info.getString() + " -> " + to_info.getString() + ": " + dht_plugin );
+		
+		if ( dht_plugin == null ){
+			
+			return( false );
+		}
+		
+		final String from_hash	= ByteFormatter.encodeString( from_info.getHash());
+		final String to_hash	= ByteFormatter.encodeString( to_info.getHash());
+		
+		final byte[] key_bytes	= ( "az:rcm:assoc:" + from_hash ).getBytes( "UTF-8" );
+		
+		String title = to_info.getTitle(); 
+		
+		if ( title.length() > MAX_TITLE_LENGTH ){
+			
+			title = title.substring( 0, MAX_TITLE_LENGTH );
+		}
+		
+		Map<String,Object> map = new HashMap<String,Object>();
+		
+		map.put( "d", title );
+		map.put( "r", new Long( Math.abs( to_info.getRand()%1000 )));
+		
+		String	tracker = to_info.getTracker();
+		
+		if ( tracker == null ){
+			
+			map.put( "h", to_info.getHash());
+			
+		}else{
+			
+			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 ));
+					}		
+					
+					byte[][] keys = getKeys( d );
+					
+					if ( keys[0] != null ){
+						map.put( "k", keys[0] );
+					}
+					if ( keys[1] != null ){
+						map.put( "w", keys[1] );
+					}
+					
+					String[] _tags = getTags( d );
+					
+					if ( _tags != null ){
+						map.put( "g", encodeTags( _tags ));
+					}
+					
+					byte nets = getNetworks( d );
+					
+					if ( nets != NET_PUBLIC ){
+						map.put( "o", new Long( nets&0xff ));
+					}
+				}
+			}catch( Throwable e ){		
+			}
+		}
+				
+		final Set<String>	my_tags = new HashSet<String>();
+		
+		try{
+			Download d = from_info.getRelatedToDownload();
+		
+			if ( d != null ){
+				
+				String[] _tags = getTags( d );
+			
+				if ( _tags != null ){
+					
+					map.put( "b", from_info.getRand() % 100 );
+					
+					map.put( "m", encodeTags( _tags ));
+					
+					for ( String tag: _tags ){
+						
+						my_tags.add( tag );
+					}
+				}
+			}
+		}catch( Throwable e ){		
+		}
+		
+		long	size = to_info.getSize();
+		
+		if ( size != 0 ){
+			
+			map.put( "s", new Long( size ));
+		}
+		
+		final byte[] map_bytes = BEncoder.encode( map );
+		
+		//System.out.println( "rcmsize=" + map_bytes.length );
+		
+		final int max_hits = 30;
+				
+		dht_plugin.get(
+				key_bytes,
+				"Content rel test: " + from_hash.substring( 0, 16 ),
+				DHTPlugin.FLAG_SINGLE_VALUE,
+				max_hits,
+				30*1000,
+				false,
+				false,
+				new DHTPluginOperationListener()
+				{
+					private boolean diversified;
+					private int		hits;
+					
+					private Set<String>	entries = new HashSet<String>();
+					
+					public void
+					starts(
+						byte[]				key )
+					{
+					}
+					
+					public boolean
+					diversified()
+					{
+						diversified = true;
+						
+						return( false );
+					}
+					
+					public void
+					valueRead(
+						DHTPluginContact	originator,
+						DHTPluginValue		value )
+					{
+						try{
+							Map<String,Object> map = (Map<String,Object>)BDecoder.decode( value.getValue());							
+							
+							DownloadInfo info = decodeInfo( map, from_info.getHash(), 1, false, entries );
+
+							try{
+								String[] r_tags = decodeTags((byte[]) map.get( "m" ));
+								
+ 								if ( r_tags != null ){
+																		
+									Long	b = (Long)map.get( "b" );
+									
+										// don't remove tags from the set that we actually published
+									
+									if ( b == null || from_info.getRand()%100 != b%100 ){
+										
+										for ( String tag: r_tags ){
+											
+											synchronized( my_tags ){
+												
+												my_tags.remove( tag );
+											}
+										}
+									}
+								}
+							}catch( Throwable e ){
+							}						
+							
+							if ( info != null ){
+							
+								analyseResponse( info, null );
+							}
+						}catch( Throwable e ){							
+						}
+						
+						hits++;
+					}
+					
+					public void
+					valueWritten(
+						DHTPluginContact	target,
+						DHTPluginValue		value )
+					{
+						
+					}
+					
+					public void
+					complete(
+						byte[]				key,
+						boolean				timeout_occurred )
+					{
+							// if we have something to say prioritise it somewhat
+						
+						int f_cutoff = my_tags.size()>0?20:10;
+
+						try{
+							boolean	do_it;
+							
+							// System.out.println( from_hash + ": hits=" + hits + ", div=" + diversified );
+							
+							if ( diversified || hits >= f_cutoff ){
+								
+								do_it = false;
+								
+							}else if ( hits <= f_cutoff / 2 ){
+								
+								do_it = true;
+															
+							}else{
+														
+								do_it = RandomUtils.nextInt( hits - (f_cutoff/2) + 1 ) == 0;
+							}
+								
+							if ( do_it ){
+								
+								try{
+									dht_plugin.put(
+											key_bytes,
+											"Content rel: " +  from_hash.substring( 0, 16 ) + " -> " + to_hash.substring( 0, 16 ),
+											map_bytes,
+											DHTPlugin.FLAG_ANON,
+											new DHTPluginOperationListener()
+											{
+												public boolean
+												diversified()
+												{
+													return( true );
+												}
+												
+												public void 
+												starts(
+													byte[] 				key ) 
+												{
+												}
+												
+												public void
+												valueRead(
+													DHTPluginContact	originator,
+													DHTPluginValue		value )
+												{
+												}
+												
+												public void
+												valueWritten(
+													DHTPluginContact	target,
+													DHTPluginValue		value )
+												{
+												}
+												
+												public void
+												complete(
+													byte[]				key,
+													boolean				timeout_occurred )
+												{
+													publishNext();
+												}
+											});
+								}catch( Throwable e ){
+									
+									Debug.printStackTrace(e);
+									
+									publishNext();
+								}
+							}else{
+								
+								publishNext();
+							}
+						}finally{
+							
+							checkAlternativePubs( to_info, map_bytes, f_cutoff );
+						}
+					}
+				});
+		
+		return( true );
+	}
+		
+	private void
+	checkAlternativePubs(
+		DownloadInfo	to_info,
+		final byte[]	map_bytes,
+		final int		f_cutoff )
+	{
+		Download dl = to_info.getRelatedToDownload();
+		
+		if ( dl != null ){
+			
+			DiskManagerFileInfo[] files = dl.getDiskManagerFileInfo();
+			
+			List<Long>	sizes = new ArrayList<Long>();
+			
+			for ( DiskManagerFileInfo file: files ){
+				
+				long	size = file.getLength();
+				
+				if ( size >= FILE_ASSOC_MIN_SIZE ){
+					
+					sizes.add( size );
+				}
+			}
+			
+			final DHTPluginInterface dht_plugin = selectDHT( to_info.getNetworksInternal());
+			
+			if ( dht_plugin != null && sizes.size() > 0 ){
+
+				try{
+					final String to_hash	= ByteFormatter.encodeString( to_info.getHash());
+	
+					final long selected_size = sizes.get( new Random().nextInt( sizes.size()));
+	
+					final byte[] key_bytes	= ( "az:rcm:size:assoc:" + selected_size ).getBytes( "UTF-8" );
+					
+					int	max_hits = 30;
+					
+					dht_plugin.get(
+							key_bytes,
+							"Content size rel test: " + to_hash.substring( 0, 16 ),
+							DHTPlugin.FLAG_SINGLE_VALUE,
+							max_hits,
+							30*1000,
+							false,
+							false,
+							new DHTPluginOperationListener()
+							{
+								private boolean diversified;
+								private int		hits;
+								
+								private Set<String>	entries = new HashSet<String>();
+								
+								public void
+								starts(
+									byte[]				key )
+								{
+								}
+								
+								public boolean
+								diversified()
+								{
+									diversified = true;
+									
+									return( false );
+								}
+								
+								public void
+								valueRead(
+									DHTPluginContact	originator,
+									DHTPluginValue		value )
+								{		
+									hits++;
+								}
+								
+								public void
+								valueWritten(
+									DHTPluginContact	target,
+									DHTPluginValue		value )
+								{
+									
+								}
+								
+								public void
+								complete(
+									byte[]				key,
+									boolean				timeout_occurred )
+								{
+									boolean	do_it;
+									
+									// System.out.println( from_hash + ": hits=" + hits + ", div=" + diversified );
+									
+									if ( diversified || hits >= f_cutoff ){
+										
+										do_it = false;
+										
+									}else if ( hits <= f_cutoff / 2 ){
+										
+										do_it = true;
+																	
+									}else{
+																
+										do_it = RandomUtils.nextInt( hits - ( f_cutoff / 2 ) + 1 ) == 0;
+									}
+										
+									if ( do_it ){
+										
+										try{
+											dht_plugin.put(
+												key_bytes,
+												"Content size rel: " +  selected_size + " -> " + to_hash.substring( 0, 16 ),
+												map_bytes,
+												DHTPlugin.FLAG_ANON,
+												new DHTPluginOperationListener()
+												{
+													public boolean
+													diversified()
+													{
+														return( true );
+													}
+													
+													public void 
+													starts(
+														byte[] 				key ) 
+													{
+													}
+													
+													public void
+													valueRead(
+														DHTPluginContact	originator,
+														DHTPluginValue		value )
+													{
+													}
+													
+													public void
+													valueWritten(
+														DHTPluginContact	target,
+														DHTPluginValue		value )
+													{
+													}
+													
+													public void
+													complete(
+														byte[]				key,
+														boolean				timeout_occurred )
+													{
+													}
+												});
+										}catch( Throwable e ){
+											
+											Debug.printStackTrace(e);
+										}
+									}
+								}
+							});
+				}catch( Throwable e ){
+					
+					Debug.out( e);
+				}
+			}
+		}
+	}
+	
+	protected DownloadInfo
+	decodeInfo(
+		Map				map,
+		byte[]			from_hash,	// will be null for those trawled from teh local DHT
+		int				level,
+		boolean			explicit,
+		Set<String>		unique_keys )
+	{
+		try{
+			String	title = new String((byte[])map.get( "d" ), "UTF-8" );
+			
+			String	tracker	= null;
+			
+			byte[]	hash 	= (byte[])map.get( "h" );
+			
+			if ( hash == null ){
+				
+				tracker = new String((byte[])map.get( "t" ), "UTF-8" );
+			}
+			
+			int	rand = ((Long)map.get( "r" )).intValue();
+			
+			String	key = title + " % " + rand;
+			
+			synchronized( unique_keys ){
+			
+				if ( unique_keys.contains( key )){
+					
+					return( null );
+				}
+				
+				unique_keys.add( key );
+			}
+			
+			Long	l_size = (Long)map.get( "s" );
+			
+			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" );
+			
+			// 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);
+			}
+				
+			byte[] tracker_keys = (byte[])map.get( "k" );
+			byte[] ws_keys 		= (byte[])map.get( "w" );
+			
+			if ( tracker_keys != null && tracker_keys.length % 4 != 0 ){
+				
+				tracker_keys = null;
+			}
+			
+			if ( ws_keys != null && ws_keys.length % 4 != 0 ){
+				
+				ws_keys = null;
+			}
+			
+			byte[]	_tags = (byte[])map.get( "g" );
+			
+			String[] tags = decodeTags( _tags );
+				
+			Long _nets = (Long)map.get( "o" );
+			
+			byte nets = _nets==null?NET_PUBLIC:_nets.byteValue();
+			
+			return(
+				new DownloadInfo( 
+						from_hash, hash, title, rand, tracker, tracker_keys, ws_keys, tags, nets, level, explicit, size, 
+						published==null?0:published.intValue(),
+						seeds_leechers,
+						(byte)(cnet==null?ContentNetwork.CONTENT_NETWORK_UNKNOWN:cnet.byteValue()))); 
+			
+		}catch( Throwable e ){
+			
+			return( null );
+		}
+	}
+	
+	public void
+	lookupAttributes(
+		final byte[]							from_hash,
+		final RelatedAttributeLookupListener	listener )
+	
+		throws ContentException
+	{
+		lookupAttributes( from_hash, new String[]{ AENetworkClassifier.AT_PUBLIC }, listener );
+	}
+	
+	public void
+	lookupAttributes(
+		final byte[]							from_hash,
+		final String[]							networks,
+		final RelatedAttributeLookupListener	listener )
+	
+		throws ContentException
+	{
+		if ( from_hash == null ){
+			
+			throw( new ContentException( "hash is null" ));
+		}
+
+		if ( 	!initialisation_complete_sem.isReleasedForever() ||
+				( public_dht_plugin != null && public_dht_plugin.isInitialising())){
+			
+			AsyncDispatcher dispatcher = new AsyncDispatcher();
+	
+			dispatcher.dispatch(
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						try{
+							initialisation_complete_sem.reserve();
+							
+							lookupAttributesSupport( from_hash, convertNetworks( networks ), listener );
+							
+						}catch( ContentException e ){
+							
+							Debug.out( e );
+						}
+					}
+				});
+		}else{
+			
+			lookupAttributesSupport( from_hash, convertNetworks( networks ), listener );
+		}
+	}
+	
+	private void
+	lookupAttributesSupport(
+		final byte[]							from_hash,
+		final byte								networks,
+		final RelatedAttributeLookupListener	listener )
+	
+		throws ContentException
+	{
+		try{
+			if ( !enabled ){
+				
+				throw( new ContentException( "rcm is disabled" ));
+			}
+			
+			final DHTPluginInterface dht_plugin = selectDHT( networks );
+
+			if ( dht_plugin == null ){
+				
+				throw( new Exception( "DHT Plugin unavailable for networks " + getString( convertNetworks( networks ))));
+			}
+			
+				// really should implement a getNetwork() in DHTPluginInterface...
+			
+			final String dht_plugin_network = dht_plugin == public_dht_plugin?AENetworkClassifier.AT_PUBLIC:AENetworkClassifier.AT_I2P;
+			
+			final String from_hash_str	= ByteFormatter.encodeString( from_hash );
+			
+			final byte[] key_bytes	= ( "az:rcm:assoc:" + from_hash_str ).getBytes( "UTF-8" );
+			
+			String op_str = "Content attr read: " + from_hash_str.substring( 0, 16 );
+			
+			dht_plugin.get(
+					key_bytes,
+					op_str,
+					DHTPlugin.FLAG_SINGLE_VALUE,
+					512,
+					30*1000,
+					false,
+					true,
+					new DHTPluginOperationListener()
+					{
+						private Set<String>	tags = new HashSet<String>();
+						
+						public void
+						starts(
+							byte[]				key )
+						{
+							if ( listener != null ){
+								
+								try{
+									listener.lookupStart();
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+								
+								ContentCache	content_cache = loadRelatedContent();
+
+								DownloadInfo info = content_cache.related_content.get( Base32.encode( from_hash ));
+								
+								if ( info != null ){
+																			
+									String[] l_tags = info.getTags();
+										
+									if ( l_tags != null ){
+											
+										for ( String tag: l_tags ){
+												
+											synchronized( tags ){
+													
+												if ( tags.contains( tag )){
+														
+													continue;
+												}
+													
+												tags.add( tag );
+											}
+											
+											try{
+												listener.tagFound( tag, dht_plugin_network );
+												
+											}catch( Throwable e ){
+												
+												Debug.out( e );
+											}
+										}
+									}
+								}
+							}
+						}
+						
+						public boolean
+						diversified()
+						{
+							return( true );
+						}
+						
+						public void
+						valueRead(
+							DHTPluginContact	originator,
+							DHTPluginValue		value )
+						{
+							try{
+								Map<String,Object> map = (Map<String,Object>)BDecoder.decode( value.getValue());
+								
+								String[] r_tags = decodeTags((byte[]) map.get( "m" ));
+								
+								if ( r_tags != null ){
+									
+									for ( String tag: r_tags ){
+										
+										synchronized( tags ){
+											
+											if ( tags.contains( tag )){
+												
+												continue;
+											}
+											
+											tags.add( tag );
+										}
+										
+										try{
+											listener.tagFound( tag, dht_plugin_network );
+											
+										}catch( Throwable e ){
+											
+											Debug.out( e );
+										}
+									}
+								}
+								
+							}catch( Throwable e ){	
+							}
+						}
+						
+						public void
+						valueWritten(
+							DHTPluginContact	target,
+							DHTPluginValue		value )
+						{
+							
+						}
+						
+						public void
+						complete(
+							byte[]				key,
+							boolean				timeout_occurred )
+						{
+							if ( listener != null ){
+								
+								try{
+									listener.lookupComplete();
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+							}
+						}				
+					});
+		}catch( Throwable e ){
+		
+			ContentException	ce;
+			
+			if ( ( e instanceof ContentException )){
+				
+				ce = (ContentException)e;
+				
+			}else{
+				ce = new ContentException( "Lookup failed", e );
+			}
+			
+			if ( listener != null ){
+				
+				try{
+					listener.lookupFailed( ce );
+					
+				}catch( Throwable f ){
+					
+					Debug.out( f );
+				}
+			}
+			
+			throw( ce );
+		}
+	}
+	
+	public void
+	lookupContent(
+		final byte[]						hash,
+		final RelatedContentLookupListener	listener )
+	
+		throws ContentException
+	{			
+		if ( hash == null ){
+			
+			throw( new ContentException( "hash is null" ));
+		}
+
+		byte	net = NET_PUBLIC;
+		
+		try{
+			Download download = plugin_interface.getDownloadManager().getDownload( hash );
+		
+			if ( download != null ){
+				
+				net = getNetworks( download );
+			}
+		}catch( Throwable e ){
+			
+		}
+		
+		final byte f_net = net;
+		
+		if ( 	!initialisation_complete_sem.isReleasedForever() ||
+				( public_dht_plugin != null && public_dht_plugin.isInitialising())){
+			
+			AsyncDispatcher dispatcher = new AsyncDispatcher();
+	
+			dispatcher.dispatch(
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						try{
+							initialisation_complete_sem.reserve();
+							
+							lookupContentSupport( hash, 0, f_net, true, listener );
+							
+						}catch( ContentException e ){
+							
+							Debug.out( e );
+						}
+					}
+				});
+		}else{
+			
+			lookupContentSupport( hash, 0, f_net, true, listener );
+		}
+	}
+	
+	public void
+	lookupContent(
+		final byte[]						hash,
+		final String[]						networks,
+		final RelatedContentLookupListener	listener )
+	
+		throws ContentException
+	{			
+		if ( hash == null ){
+			
+			throw( new ContentException( "hash is null" ));
+		}
+
+		final byte	net = convertNetworks( networks );
+		
+		if ( net == 0 ){
+			
+			throw( new ContentException( "No networks specified" ));
+		}
+		
+		if ( 	!initialisation_complete_sem.isReleasedForever() ||
+				( public_dht_plugin != null && public_dht_plugin.isInitialising())){
+			
+			AsyncDispatcher dispatcher = new AsyncDispatcher();
+	
+			dispatcher.dispatch(
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						try{
+							initialisation_complete_sem.reserve();
+							
+							lookupContentSupport( hash, 0, net, true, listener );
+							
+						}catch( ContentException e ){
+							
+							Debug.out( e );
+						}
+					}
+				});
+		}else{
+			
+			lookupContentSupport( hash, 0, net, true, listener );
+		}
+	}
+	
+	public void
+	lookupContent(
+		final long							file_size,
+		final RelatedContentLookupListener	listener )
+	
+		throws ContentException
+	{
+		if ( file_size < FILE_ASSOC_MIN_SIZE ){
+			
+			throw( new ContentException( "file size is invalid - min=" + FILE_ASSOC_MIN_SIZE ));
+		}
+
+		if ( 	!initialisation_complete_sem.isReleasedForever() ||
+				( public_dht_plugin != null && public_dht_plugin.isInitialising())){
+			
+			AsyncDispatcher dispatcher = new AsyncDispatcher();
+	
+			dispatcher.dispatch(
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						try{
+							initialisation_complete_sem.reserve();
+							
+							lookupContentSupport( file_size, NET_PUBLIC, listener );
+							
+						}catch( ContentException e ){
+							
+							Debug.out( e );
+						}
+					}
+				});
+		}else{
+			
+			lookupContentSupport( file_size, NET_PUBLIC, listener );
+		}
+	}
+	
+	public void
+	lookupContent(
+		final long							file_size,
+		final String[]						networks,
+		final RelatedContentLookupListener	listener )
+	
+		throws ContentException
+	{
+		if ( file_size < FILE_ASSOC_MIN_SIZE ){
+			
+			throw( new ContentException( "file size is invalid - min=" + FILE_ASSOC_MIN_SIZE ));
+		}
+
+		final byte	net = convertNetworks( networks );
+		
+		if ( net == 0 ){
+			
+			throw( new ContentException( "No networks specified" ));
+		}
+
+		if ( 	!initialisation_complete_sem.isReleasedForever() ||
+				( public_dht_plugin != null && public_dht_plugin.isInitialising())){
+			
+			AsyncDispatcher dispatcher = new AsyncDispatcher();
+	
+			dispatcher.dispatch(
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						try{
+							initialisation_complete_sem.reserve();
+							
+							lookupContentSupport( file_size, net, listener );
+							
+						}catch( ContentException e ){
+							
+							Debug.out( e );
+						}
+					}
+				});
+		}else{
+			
+			lookupContentSupport( file_size, net, listener );
+		}
+	}
+	
+	private void
+	lookupContentSupport(
+		final long							file_size,
+		final byte							networks,
+		final RelatedContentLookupListener	listener )
+	
+		throws ContentException
+	{
+		if ( !enabled ){
+			
+			throw( new ContentException( "rcm is disabled" ));
+		}
+	
+		try{
+			final byte[] key_bytes	= ( "az:rcm:size:assoc:" + file_size ).getBytes( "UTF-8" );
+
+				// we need something to use
+			
+			final byte[] from_hash = new SHA1Simple().calculateHash( key_bytes );
+			
+			String op_str = "Content rel read: size=" + file_size;
+
+			lookupContentSupport0( from_hash, key_bytes, op_str, 0, networks, true, listener );
+			
+		}catch( ContentException e ){
+			
+			throw( e );
+			
+		}catch( Throwable e ){
+			
+			throw( new ContentException( "lookup failed", e ));
+		}
+	}
+	
+	private void
+	lookupContentSupport(
+		final byte[]						from_hash,
+		final int							level,
+		final byte							networks,
+		final boolean						explicit,
+		final RelatedContentLookupListener	listener )
+	
+		throws ContentException
+	{
+		if ( !enabled ){
+		
+			throw( new ContentException( "rcm is disabled" ));
+		}
+		
+		try{
+			
+			final String from_hash_str	= ByteFormatter.encodeString( from_hash );
+		
+			final byte[] key_bytes	= ( "az:rcm:assoc:" + from_hash_str ).getBytes( "UTF-8" );
+			
+			String op_str = "Content rel read: " + from_hash_str.substring( 0, 16 );
+
+			lookupContentSupport0( from_hash, key_bytes, op_str, level, networks, explicit, listener );
+			
+		}catch( ContentException e ){
+			
+			throw( e );
+			
+		}catch( Throwable e ){
+			
+			throw( new ContentException( "lookup failed", e ));
+		}
+	}
+		
+	private String
+	getString(
+		String[]	args )
+	{
+		String str = "";
+		
+		for ( String s: args ){
+			
+			str += (str.length()==0?"":",") + s;
+		}
+		
+		return( str );
+	}
+	
+	private void
+	lookupContentSupport0(
+		final byte[]						from_hash,
+		final byte[]						key_bytes,
+		final String						op_str,
+		final int							level,
+		final byte							networks,
+		final boolean						explicit,
+		final RelatedContentLookupListener	listener )
+	
+		throws ContentException
+	{
+		try{
+			final int max_hits = 30;
+			
+			DHTPluginInterface dht_plugin = selectDHT( networks );
+
+			if ( dht_plugin == null ){
+				
+				throw( new Exception( "DHT Plugin unavailable for networks '" + getString( convertNetworks( networks )) + "'" ));
+			}
+			
+			dht_plugin.get(
+					key_bytes,
+					op_str,
+					DHTPlugin.FLAG_SINGLE_VALUE,
+					max_hits,
+					60*1000,
+					false,
+					true,
+					new DHTPluginOperationListener()
+					{
+						private Set<String>	entries = new HashSet<String>();
+						
+						private RelatedContentManagerListener manager_listener = 
+							new RelatedContentManagerListener()
+							{
+							private Set<RelatedContent>	content_list = new HashSet<RelatedContent>();
+							
+								public void
+								contentFound(
+									RelatedContent[]	content )
+								{
+									handle( content );
+								}
+	
+								public void
+								contentChanged(
+									RelatedContent[]	content )
+								{
+									handle( content );
+								}
+								
+								public void 
+								contentRemoved(
+									RelatedContent[] 	content ) 
+								{
+								}
+								
+								public void
+								contentChanged()
+								{									
+								}
+								
+								public void
+								contentReset()
+								{
+								}
+								
+								private void
+								handle(
+									RelatedContent[]	content )
+								{
+									List<RelatedContent>	new_content = new ArrayList<RelatedContent>( content.length );
+									
+									synchronized( content_list ){
+										
+										for ( RelatedContent rc: content ){
+										
+											if ( !content_list.contains( rc )){
+											
+												new_content.add( rc );
+											}
+										}
+										
+										if ( new_content.size() == 0 ){
+											
+											return;
+										}
+										
+										content_list.addAll( new_content );
+									}
+									
+									listener.contentFound( new_content.toArray( new RelatedContent[new_content.size()] ));
+								}
+							};
+						
+						public void
+						starts(
+							byte[]				key )
+						{
+							if ( listener != null ){
+								
+								try{
+									listener.lookupStart();
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+							}
+						}
+						
+						public boolean
+						diversified()
+						{
+							return( true );
+						}
+						
+						public void
+						valueRead(
+							DHTPluginContact	originator,
+							DHTPluginValue		value )
+						{
+							try{
+								Map<String,Object> map = (Map<String,Object>)BDecoder.decode( value.getValue());
+								
+								DownloadInfo info = decodeInfo( map, from_hash, level+1, explicit, entries );
+								
+								if ( info != null ){
+									
+									analyseResponse( info, listener==null?null:manager_listener );
+								}
+							}catch( Throwable e ){	
+							}
+						}
+						
+						public void
+						valueWritten(
+							DHTPluginContact	target,
+							DHTPluginValue		value )
+						{
+							
+						}
+						
+						public void
+						complete(
+							byte[]				key,
+							boolean				timeout_occurred )
+						{
+							if ( listener != null ){
+								
+								try{
+									listener.lookupComplete();
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+							}
+						}				
+					});
+		}catch( Throwable e ){
+		
+			ContentException	ce;
+			
+			if ( ( e instanceof ContentException )){
+				
+				ce = (ContentException)e;
+				
+			}else{
+				ce = new ContentException( "Lookup failed", e );
+			}
+			
+			if ( listener != null ){
+				
+				try{
+					listener.lookupFailed( ce );
+					
+				}catch( Throwable f ){
+					
+					Debug.out( f );
+				}
+			}
+			
+			throw( ce );
+		}
+	}
+	
+	protected void
+	popuplateSecondaryLookups(
+		ContentCache	content_cache )
+	{
+		Random rand = new Random();
+
+		secondary_lookups.clear();
+		
+			// stuff in a couple primarys
+		
+		List<DownloadInfo> primaries = download_info_map.values();
+		
+		int	primary_count = primaries.size();
+		
+		int	primaries_to_add;
+		
+		if ( primary_count < 2 ){
+			
+			primaries_to_add = 0;
+			
+		}else if ( primary_count < 5 ){
+			
+			if ( rand.nextInt(4) == 0 ){
+				
+				primaries_to_add = 1;
+				
+			}else{
+				
+				primaries_to_add = 0;
+			}
+		}else if ( primary_count < 10 ){
+			
+			primaries_to_add = 1;
+			
+		}else{
+			
+			primaries_to_add = 2;
+		}
+		
+		if ( primaries_to_add > 0 ){
+			
+			Set<DownloadInfo> added = new HashSet<DownloadInfo>();
+			
+			for (int i=0;i<primaries_to_add;i++){
+				
+				DownloadInfo info = primaries.get( rand.nextInt( primaries.size()));
+				
+				if ( !added.contains( info )){
+					
+					added.add( info );
+					
+					secondary_lookups.addLast(new SecondaryLookup(info.getHash(), info.getLevel(), info.getNetworksInternal()));
+				}
+			}
+		}
+		
+		Map<String,DownloadInfo>		related_content			= content_cache.related_content;
+
+		Iterator<DownloadInfo> it = related_content.values().iterator();
+		
+		List<DownloadInfo> secondary_cache_temp = new ArrayList<DownloadInfo>( related_content.size());
+
+		while( it.hasNext()){
+			
+			DownloadInfo di = it.next();
+			
+			if ( di.getHash() != null && di.getLevel() < max_search_level ){
+					
+				secondary_cache_temp.add( di );
+			}
+		}
+						
+		final int cache_size = Math.min( secondary_cache_temp.size(), SECONDARY_LOOKUP_CACHE_MAX - secondary_lookups.size());
+		
+		if ( cache_size > 0 ){
+						
+			for( int i=0;i<cache_size;i++){
+				
+				int index = rand.nextInt( secondary_cache_temp.size());
+				
+				DownloadInfo x = secondary_cache_temp.get( index );
+				
+				secondary_cache_temp.set( index, secondary_cache_temp.get(i));
+				
+				secondary_cache_temp.set( i, x );
+			}
+			
+			for ( int i=0;i<cache_size;i++){
+				
+				DownloadInfo x = secondary_cache_temp.get(i);
+				
+				secondary_lookups.addLast(new SecondaryLookup(x.getHash(), x.getLevel(), x.getNetworksInternal()));
+			}
+		}
+	}
+	
+	protected void
+	secondaryLookup()
+	{
+		SecondaryLookup sl;
+		
+		long	now = SystemTime.getMonotonousTime();
+		
+		synchronized( rcm_lock ){
+			
+			if ( secondary_lookup_in_progress ){
+				
+				return;
+			}
+		
+			if ( now - secondary_lookup_complete_time < SECONDARY_LOOKUP_PERIOD ){
+				
+				return;
+			}
+			
+			if ( secondary_lookups.size() == 0 ){
+			
+				ContentCache cc = content_cache==null?null:content_cache.get();
+
+				if ( cc == null ){
+					
+						// this will populate the cache
+					
+					cc = loadRelatedContent();
+					
+				}else{
+					
+					popuplateSecondaryLookups( cc );
+				}
+			}
+
+			if ( secondary_lookups.size() == 0 ){
+				
+				return;
+			}
+						
+			sl = secondary_lookups.removeFirst();
+
+			secondary_lookup_in_progress = true;
+		}
+		
+		try{
+			lookupContentSupport( 
+				sl.getHash(),
+				sl.getLevel(),
+				sl.getNetworks(),
+				false,
+				new RelatedContentLookupListener()
+				{
+					public void
+					lookupStart()
+					{	
+					}
+					
+					public void
+					contentFound(
+						RelatedContent[]	content )
+					{	
+					}
+					
+					public void
+					lookupComplete()
+					{
+						next();
+					}
+					
+					public void
+					lookupFailed(
+						ContentException 	error )
+					{
+						next();
+					}
+					
+					protected void
+					next()
+					{
+						final SecondaryLookup next_sl;
+						
+						synchronized( rcm_lock ){
+							
+							if ( secondary_lookups.size() == 0 ){
+								
+								secondary_lookup_in_progress = false;
+								
+								secondary_lookup_complete_time = SystemTime.getMonotonousTime();
+								
+								return;
+								
+							}else{
+								
+								next_sl = secondary_lookups.removeFirst();
+							}
+						}
+						
+						final RelatedContentLookupListener listener = this;
+						
+						SimpleTimer.addEvent(
+							"RCM:SLDelay",
+							SystemTime.getOffsetTime( 30*1000 ),
+							new TimerEventPerformer()
+							{
+								public void 
+								perform(
+									TimerEvent event ) 
+								{
+									try{					
+										lookupContentSupport( next_sl.getHash(), next_sl.getLevel(), next_sl.getNetworks(), false, listener );
+										
+									}catch( Throwable e ){
+										
+										//Debug.out( e );
+										
+										synchronized( rcm_lock ){
+											
+											secondary_lookup_in_progress = false;
+											
+											secondary_lookup_complete_time = SystemTime.getMonotonousTime();
+										}
+									}
+								}
+							});
+					}
+				});
+			
+		}catch( Throwable e ){
+			
+			//Debug.out( e );
+			
+			synchronized( rcm_lock ){
+				
+				secondary_lookup_in_progress = false;
+				
+				secondary_lookup_complete_time = now;
+			}
+		}
+	}
+	
+	protected void
+	contentChanged(
+		final DownloadInfo		info )
+	{
+		setConfigDirty();
+		
+		content_change_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void
+				runSupport()
+				{
+					for ( RelatedContentManagerListener l: listeners ){
+						
+						try{
+							l.contentChanged( new RelatedContent[]{ info });
+							
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}
+				}
+			});
+	}
+	
+	protected void
+	contentChanged(
+		boolean	is_dirty )
+	{
+		if ( is_dirty ){
+		
+			setConfigDirty();
+		}
+		
+		content_change_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void
+				runSupport()
+				{
+					for ( RelatedContentManagerListener l: listeners ){
+						
+						try{
+							l.contentChanged();
+							
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}
+				}
+			});
+	}
+	
+	public void
+	delete(
+		RelatedContent[]	content )
+	{
+		synchronized( rcm_lock ){
+			
+			ContentCache content_cache = loadRelatedContent();
+			
+			delete( content, content_cache, true );
+		}
+	}
+	
+	protected void
+	delete(
+		final RelatedContent[]	content,
+		ContentCache			content_cache,
+		boolean					persistent )
+	{
+		if ( persistent ){
+		
+			addPersistentlyDeleted( content );
+		}
+		
+		Map<String,DownloadInfo> related_content = content_cache.related_content;
+
+		Iterator<DownloadInfo> it = related_content.values().iterator();
+		
+		while( it.hasNext()){
+		
+			DownloadInfo di = it.next();
+			
+			for ( RelatedContent c: content ){
+				
+				if ( c == di ){
+					
+					it.remove();
+					
+					if ( di.isUnread()){
+						
+						decrementUnread();
+					}
+				}
+			}
+		}
+		
+		ByteArrayHashMapEx<ArrayList<DownloadInfo>> related_content_map = content_cache.related_content_map;
+		
+		List<byte[]> delete = new ArrayList<byte[]>();
+		
+		for ( byte[] key: related_content_map.keys()){
+			
+			ArrayList<DownloadInfo>	infos = related_content_map.get( key );
+			
+			for ( RelatedContent c: content ){
+
+				if ( infos.remove( c )){
+					
+					if ( infos.size() == 0 ){
+						
+						delete.add( key );
+						
+						break;
+					}
+				}
+			}
+		}
+		
+		for ( byte[] key: delete ){
+			
+			related_content_map.remove( key );
+		}
+		
+		setConfigDirty();
+		
+		content_change_dispatcher.dispatch(
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						for ( RelatedContentManagerListener l: listeners ){
+							
+							try{
+								l.contentRemoved( content );
+
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}
+					}
+				});
+	}
+	
+	protected String
+	getPrivateInfoKey(
+		RelatedContent		info )
+	{
+		return( info.getTitle() + ":" + info.getTracker());
+	}
+	
+	protected void
+	analyseResponse(
+		DownloadInfo						to_info,
+		final RelatedContentManagerListener	listener )
+	{
+		try{			
+			synchronized( rcm_lock ){
+				
+				byte[] target = to_info.getHash();
+				
+				String	key;
+				
+				if ( target != null ){
+					
+					if ( download_info_map.containsKey( target )){
+						
+							// target refers to downoad we already have
+						
+						return;
+					}
+					
+					key = Base32.encode( target );
+					
+				}else{
+					
+					key = getPrivateInfoKey( to_info );
+					
+					if ( download_priv_set.contains( key )){
+						
+							// target refers to downoad we already have
+						
+						return;
+					}
+				}
+				
+				if ( isPersistentlyDeleted( to_info )){
+					
+					return;
+				}
+				
+				ContentCache	content_cache = loadRelatedContent();
+				
+				DownloadInfo	target_info = null;
+				
+				boolean	changed_content = false;
+				boolean	new_content 	= false;
+				
+				
+				target_info = content_cache.related_content.get( key );
+				
+				if ( target_info == null ){
+								
+					if ( enoughSpaceFor( content_cache, to_info )){
+					
+						target_info = to_info;
+
+						content_cache.related_content.put( key, target_info );
+						
+						byte[] from_hash = to_info.getRelatedToHash();
+						
+						ArrayList<DownloadInfo> links = content_cache.related_content_map.get( from_hash );
+						
+						if ( links == null ){
+							
+							links = new ArrayList<DownloadInfo>(1);
+							
+							content_cache.related_content_map.put( from_hash, links );
+						}
+						
+						links.add( target_info );
+						
+						links.trimToSize();
+						
+						target_info.setPublic( content_cache );
+						
+						if ( secondary_lookups.size() < SECONDARY_LOOKUP_CACHE_MAX ){
+							
+							byte[]	hash 	= target_info.getHash();
+							int		level	= target_info.getLevel();
+							
+							if ( hash != null && level < max_search_level ){
+								
+								secondary_lookups.add( new SecondaryLookup( hash, level, target_info.getNetworksInternal()));
+							}
+						}
+						
+						new_content = true;
+						
+					}else{
+						
+						transient_info_cache.put( key, to_info );
+					}
+				}else{
+					
+						// we already know about this, see if new info
+					
+					changed_content = target_info.addInfo( to_info );
+				}
+
+				if ( target_info != null ){
+					
+					final RelatedContent[]	f_target 	= new RelatedContent[]{ target_info };
+					final boolean			f_change	= changed_content;
+					
+					final boolean something_changed = changed_content || new_content;
+							
+					if ( something_changed ){
+					
+						setConfigDirty();
+					}
+					
+					content_change_dispatcher.dispatch(
+						new AERunnable()
+						{
+							public void
+							runSupport()
+							{
+								if ( something_changed ){
+									
+									for ( RelatedContentManagerListener l: listeners ){
+										
+										try{
+											if ( f_change ){
+												
+												l.contentChanged( f_target );
+												
+											}else{
+												
+												l.contentFound( f_target );
+											}
+										}catch( Throwable e ){
+											
+											Debug.out( e );
+										}
+									}
+								}
+								
+								if ( listener != null ){
+									
+									try{
+										if ( f_change ){
+											
+											listener.contentChanged( f_target );
+											
+										}else{
+											
+											listener.contentFound( f_target );
+										}
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}
+								}
+							}
+						});
+				}
+			}
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+	}
+	
+	protected boolean
+	enoughSpaceFor(
+		ContentCache	content_cache,
+		DownloadInfo	fi )
+	{
+		Map<String,DownloadInfo> related_content = content_cache.related_content;
+		
+		if ( related_content.size() < max_results + temporary_space.get()){
+			
+			return( true );
+		}
+		
+		Iterator<Map.Entry<String,DownloadInfo>>	it = related_content.entrySet().iterator();
+				
+		int	max_level 		= fi.getLevel();
+		
+			// delete oldest at highest level >= level with minimum rank
+	
+		Map<Integer,DownloadInfo>	oldest_per_rank = new HashMap<Integer, DownloadInfo>();
+		
+		int	min_rank 	= Integer.MAX_VALUE;
+		int	max_rank	= -1;
+		
+		while( it.hasNext()){
+			
+			Map.Entry<String,DownloadInfo> entry = it.next();
+			
+			DownloadInfo info = entry.getValue();
+			
+			if ( info.isExplicit()){
+				
+				continue;
+			}
+			
+			int	info_level = info.getLevel();
+			
+			if ( info_level >= max_level ){
+				
+				if ( info_level > max_level ){
+					
+					max_level = info_level;
+					
+					min_rank 	= Integer.MAX_VALUE;
+					max_rank	= -1;
+					
+					oldest_per_rank.clear();
+				}
+				
+				int	rank = info.getRank();
+				
+				if ( rank < min_rank ){
+					
+					min_rank = rank;
+					
+				}else if ( rank > max_rank ){
+					
+					max_rank = rank;
+				}
+				
+				DownloadInfo oldest = oldest_per_rank.get( rank );
+				
+				if ( oldest == null ){
+					
+					oldest_per_rank.put( rank, info );
+					
+				}else{
+					
+					if ( info.getLastSeenSecs() < oldest.getLastSeenSecs()){
+						
+						oldest_per_rank.put( rank, info );
+					}
+				}
+			}
+		}
+		
+		DownloadInfo to_remove = oldest_per_rank.get( min_rank );
+		
+		if ( to_remove != null ){
+					
+			delete( new RelatedContent[]{ to_remove }, content_cache, false );
+			
+			return( true );
+		}
+		
+			// we don't want high-ranked entries to get stuck there and prevent newer stuff from getting in and rising up
+		
+		if ( max_level == 1 ){
+			
+			to_remove = oldest_per_rank.get( max_rank );
+			
+			if ( to_remove != null ){
+				
+				int	now_secs = (int)( SystemTime.getCurrentTime()/1000 );
+				
+					// give it a day at the top
+				
+				if ( now_secs - to_remove.getLastSeenSecs() >= 24*60*60 ){
+					
+					delete( new RelatedContent[]{ to_remove }, content_cache, false );
+					
+					return( true );
+				}
+			}
+		}
+		
+		return( false );
+	}
+	
+	public RelatedContent[]
+	getRelatedContent()
+	{
+		synchronized( rcm_lock ){
+
+			ContentCache	content_cache = loadRelatedContent();
+			
+			return( content_cache.related_content.values().toArray( new DownloadInfo[ content_cache.related_content.size()]));
+		}
+	}
+	
+	protected List<DownloadInfo>
+  	getRelatedContentAsList()
+  	{
+  		synchronized( rcm_lock ){
+
+  			ContentCache	content_cache = loadRelatedContent();
+  			
+  			return( new ArrayList<DownloadInfo>( content_cache.related_content.values()));
+  		}
+  	}
+	
+	public void
+	reset()
+	{
+		reset( true );
+	}
+	
+	protected void
+	reset(
+		boolean	reset_perm_dels )
+	{
+		synchronized( rcm_lock ){
+			
+			ContentCache cc = content_cache==null?null:content_cache.get();
+			
+			if ( cc == null ){
+				
+				FileUtil.deleteResilientConfigFile( CONFIG_FILE );
+				
+			}else{
+			
+				cc.related_content 		= new HashMap<String,DownloadInfo>();
+				cc.related_content_map 	= new ByteArrayHashMapEx<ArrayList<DownloadInfo>>();
+			}
+					
+			pub_download_infos1.clear();
+			pub_download_infos2.clear();
+			
+			non_pub_download_infos1.clear();
+			non_pub_download_infos2.clear();
+			
+			List<DownloadInfo>	list = download_info_map.values();
+			
+			for ( DownloadInfo info: list ){
+				
+				if (( info.getNetworksInternal() & NET_PUBLIC ) != 0 ){
+			
+					pub_download_infos1.add( info );
+					pub_download_infos2.add( info );
+					
+				}else{
+					
+					non_pub_download_infos1.add( info );
+					non_pub_download_infos2.add( info );
+				}
+			}
+			
+			Collections.shuffle( pub_download_infos1 );
+			Collections.shuffle( non_pub_download_infos1 );
+			
+			total_unread.set( 0 );
+			
+			if ( reset_perm_dels ){
+			
+				resetPersistentlyDeleted();
+			}
+			
+			setConfigDirty();
+		}
+		
+		content_change_dispatcher.dispatch(
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						for ( RelatedContentManagerListener l: listeners ){
+							
+							l.contentReset();
+						}
+					}
+				});
+	}
+		
+	public SearchInstance
+	searchRCM(
+		Map<String,Object>		search_parameters,
+		SearchObserver			observer )
+	
+		throws SearchException
+	{
+		initialisation_complete_sem.reserve();
+
+		if ( !enabled ){
+			
+			throw( new SearchException( "rcm is disabled" ));
+		}
+				
+		String[]	networks = (String[])search_parameters.get( SearchProvider.SP_NETWORKS );
+		
+		String	target_net = AENetworkClassifier.AT_PUBLIC;
+		
+		if ( networks != null ){
+			
+			for ( String net: networks ){
+				
+				if ( net == AENetworkClassifier.AT_PUBLIC ){
+					
+					target_net = AENetworkClassifier.AT_PUBLIC;
+					
+					break;
+					
+				}else if ( net == AENetworkClassifier.AT_I2P ){
+
+					target_net = AENetworkClassifier.AT_I2P;
+				}
+			}
+		}
+		
+		for ( RelatedContentSearcher searcher: searchers ){
+		
+			String net = searcher.getDHTPlugin().getNetwork();
+			
+			if ( net == target_net ){
+			
+				return( searcher.searchRCM( search_parameters, observer ));
+			}
+		}
+		
+		throw( new SearchException( "no searchers available" ));
+	}
+	
+
+	protected void
+	setConfigDirty()
+	{
+		synchronized( rcm_lock ){
+			
+			content_dirty	= true;
+		}
+	}
+	
+	protected ContentCache
+	loadRelatedContent()
+	{
+		boolean	fire_event = false;
+		
+		try{
+			synchronized( rcm_lock ){
+	
+				last_config_access = SystemTime.getMonotonousTime();
+	
+				ContentCache cc = content_cache==null?null:content_cache.get();
+				
+				if ( cc == null ){
+				
+					if ( TRACE ){
+						System.out.println( "rcm: load new" );
+					}
+					
+					fire_event = true;
+					
+					cc = new ContentCache();
+		
+					content_cache = new WeakReference<ContentCache>( cc );
+					
+					try{
+						int	new_total_unread = 0;
+		
+						if ( FileUtil.resilientConfigFileExists( CONFIG_FILE )){
+											
+							Map map = FileUtil.readResilientConfigFile( CONFIG_FILE );
+							
+							Map<String,DownloadInfo>						related_content			= cc.related_content;
+							ByteArrayHashMapEx<ArrayList<DownloadInfo>>		related_content_map		= cc.related_content_map;
+		
+							Map<String,String>	rcm_map;
+							
+							byte[]	data = (byte[])map.get( "d" );
+							
+							if ( data != null ){
+										
+								try{
+									map = BDecoder.decode(new BufferedInputStream( new GZIPInputStream( new ByteArrayInputStream( CryptoManagerFactory.getSingleton().deobfuscate( data )))));
+									
+								}catch( Throwable e ){
+									
+										// can get here is config's been deleted
+									
+									map = new HashMap();
+								}
+							}
+							
+							rcm_map = (Map<String,String>)map.get( "rcm" );
+						
+							Object	rc_map_stuff 	= map.get( "rc" );
+							
+							if ( rc_map_stuff != null && rcm_map != null ){
+								
+								Map<Integer,DownloadInfo> id_map = new HashMap<Integer, DownloadInfo>();
+									
+								if ( rc_map_stuff instanceof Map ){
+									
+										// migration from when it was a Map with non-ascii key issues
+									
+									Map<String,Map<String,Object>>	rc_map 	= (Map<String,Map<String,Object>>)rc_map_stuff;
+
+									for ( Map.Entry<String,Map<String,Object>> entry: rc_map.entrySet()){
+										
+										try{
+										
+											String	key = entry.getKey();
+										
+											Map<String,Object>	info_map = entry.getValue();
+																		
+											DownloadInfo info = deserialiseDI( info_map, cc );
+											
+											if ( info.isUnread()){
+												
+												new_total_unread++;
+											}
+											
+											related_content.put( key, info );
+											
+											int	id = ((Long)info_map.get( "_i" )).intValue();
+				
+											id_map.put( id, info );
+											
+										}catch( Throwable e ){
+											
+											Debug.out( e );
+										}
+									}
+								}else{
+									
+									List<Map<String,Object>>	rc_map_list 	= (List<Map<String,Object>>)rc_map_stuff;
+
+									for ( Map<String,Object> info_map: rc_map_list ){
+										
+										try{
+										
+											String	key = new String((byte[])info_map.get( "_k" ), "UTF-8" );
+																												
+											DownloadInfo info = deserialiseDI( info_map, cc );
+											
+											if ( info.isUnread()){
+												
+												new_total_unread++;
+											}
+											
+											related_content.put( key, info );
+											
+											int	id = ((Long)info_map.get( "_i" )).intValue();
+				
+											id_map.put( id, info );
+											
+										}catch( Throwable e ){
+											
+											Debug.out( e );
+										}
+									}
+								}
+															
+								if ( rcm_map.size() != 0 && id_map.size() != 0 ){
+									
+									for ( String key: rcm_map.keySet()){
+										
+										try{
+											byte[]	hash = Base32.decode( key );
+											
+											int[]	ids = ImportExportUtils.importIntArray( rcm_map, key );
+											
+											if ( ids == null || ids.length == 0 ){
+												
+												// Debug.out( "Inconsistent - no ids" );
+												
+											}else{
+												
+												ArrayList<DownloadInfo>	di_list = new ArrayList<DownloadInfo>(ids.length);
+												
+												for ( int id: ids ){
+													
+													DownloadInfo di = id_map.get( id );
+													
+													if ( di == null ){
+														
+														// Debug.out( "Inconsistent: id " + id + " missing" );
+														
+													}else{
+														
+															// we don't currently remember all originators, just one that works 
+															
+														di.setRelatedToHash( hash );
+														
+														di_list.add( di );
+													}
+												}
+												
+												if ( di_list.size() > 0 ){
+													
+													related_content_map.put( hash, di_list );
+												}
+											}
+										}catch( Throwable e ){
+											
+											Debug.out( e );
+										}
+									}
+								}
+								
+								Iterator<DownloadInfo> it = related_content.values().iterator();
+								
+								while( it.hasNext()){
+									
+									DownloadInfo di = it.next();
+									
+									if ( di.getRelatedToHash() == null ){
+								
+										// Debug.out( "Inconsistent: info not referenced" );
+										
+										if ( di.isUnread()){
+											
+											new_total_unread--;
+										}
+										
+										it.remove();
+									}
+								}
+								
+								popuplateSecondaryLookups( cc );
+							}
+						}
+						
+						if ( total_unread.get() != new_total_unread ){
+														
+							// Debug.out( "total_unread - inconsistent (" + total_unread + "/" + new_total_unread + ")" );
+							
+							total_unread.set( new_total_unread );
+							
+							COConfigurationManager.setParameter( CONFIG_TOTAL_UNREAD, new_total_unread );
+						}
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+					
+					enforceMaxResults( cc, false );
+				}
+				
+				content_cache_ref = cc;
+					
+				return( cc );
+			}
+		}finally{
+			
+			if ( fire_event ){
+				
+				contentChanged( false );
+			}
+		}
+	}
+	
+	protected void
+	saveRelatedContent(
+		int	tick_count )
+	{
+		synchronized( rcm_lock ){
+				
+			COConfigurationManager.setParameter( CONFIG_TOTAL_UNREAD, total_unread.get());
+			
+			long	now = SystemTime.getMonotonousTime();;
+			
+			ContentCache cc = content_cache==null?null:content_cache.get();
+			
+			if ( !content_dirty ){
+					
+				if ( cc != null  ){
+					
+					if ( now - last_config_access > CONFIG_DISCARD_MILLIS ){
+					
+						if ( content_cache_ref != null ){
+							
+							content_discard_ticks = 0;
+						}
+						
+						if ( TRACE ){
+							System.out.println( "rcm: discard: tick count=" + content_discard_ticks++ );
+						}
+						
+						content_cache_ref	= null;
+					}
+				}else{
+					
+					if ( TRACE ){
+						System.out.println( "rcm: discarded" );
+					}
+				}
+				
+				return;
+			}
+			
+			if ( tick_count % CONFIG_SAVE_TICKS != 0 ){
+				
+				return;
+			}
+			
+			last_config_access = now;
+			
+			content_dirty	= false;
+			
+			if ( cc == null ){
+				
+				// Debug.out( "RCM: cache inconsistent" );
+				
+			}else{
+				
+				if ( persist ){
+					
+					if ( TRACE ){
+						System.out.println( "rcm: save" );
+					}
+					
+					Map<String,DownloadInfo>						related_content			= cc.related_content;
+					ByteArrayHashMapEx<ArrayList<DownloadInfo>>		related_content_map		= cc.related_content_map;
+	
+					if ( related_content.size() == 0 ){
+						
+						FileUtil.deleteResilientConfigFile( CONFIG_FILE );
+						
+					}else{
+						
+						Map<String,Object>	map = new HashMap<String, Object>();
+						
+						Set<Map.Entry<String,DownloadInfo>> rcs = related_content.entrySet();
+											
+						List<Map<String,Object>> rc_map_list = new ArrayList<Map<String, Object>>( rcs.size());
+						
+						map.put( "rc", rc_map_list );
+						
+						int		id = 0;
+						
+						Map<DownloadInfo,Integer>	info_map = new HashMap<DownloadInfo, Integer>();
+						
+						for ( Map.Entry<String,DownloadInfo> entry: rcs ){
+												
+							DownloadInfo	info = entry.getValue();
+													
+							Map<String,Object> di_map = serialiseDI( info, cc );
+							
+							if ( di_map != null ){
+								
+								info_map.put( info, id );
+	
+								di_map.put( "_i", new Long( id ));
+								di_map.put( "_k", entry.getKey());
+								
+								rc_map_list.add( di_map );
+		
+								id++;	
+							}
+						}
+						
+						Map<String,Object> rcm_map = new HashMap<String, Object>();
+						
+						map.put( "rcm", rcm_map );
+
+						for ( byte[] hash: related_content_map.keys()){
+							
+							List<DownloadInfo> dis = related_content_map.get( hash );
+							
+							int[] ids = new int[dis.size()];
+							
+							int	pos = 0;
+							
+							for ( DownloadInfo di: dis ){
+								
+								Integer	index = info_map.get( di );
+								
+								if ( index == null ){
+									
+									// Debug.out( "inconsistent: info missing for " + di );
+									
+									break;
+									
+								}else{
+									
+									ids[pos++] = index;
+								}
+							}
+							
+							if ( pos == ids.length ){
+							
+								ImportExportUtils.exportIntArray( rcm_map, Base32.encode( hash), ids );
+							}
+						}
+						
+						if ( true ){
+						
+							ByteArrayOutputStream baos = new ByteArrayOutputStream( 100*1024 );
+							
+							try{
+								GZIPOutputStream gos = new GZIPOutputStream( baos );
+								
+								gos.write( BEncoder.encode( map ));
+								
+								gos.close();
+								
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+							
+							map.clear();
+							
+							map.put( "d", CryptoManagerFactory.getSingleton().obfuscate( baos.toByteArray()));
+						}
+						
+						FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
+					}
+				}else{
+					
+					deleteRelatedContent();
+				}
+			
+				for ( RelatedContentSearcher searcher: searchers ){
+				
+					searcher.updateKeyBloom( cc );
+				}
+			}
+		}
+	}
+	
+	private void
+	deleteRelatedContent()
+	{
+		FileUtil.deleteResilientConfigFile( CONFIG_FILE );
+		FileUtil.deleteResilientConfigFile( PERSIST_DEL_FILE );
+	}
+	
+	public int
+	getNumUnread()
+	{
+		return( total_unread.get());
+	}
+	
+	public void
+	setAllRead()
+	{
+		boolean	changed = false;
+		
+		synchronized( rcm_lock ){
+			
+			DownloadInfo[] content = (DownloadInfo[])getRelatedContent();
+			
+			for ( DownloadInfo c: content ){
+				
+				if ( c.isUnread()){
+				
+					changed = true;
+					
+					c.setUnreadInternal( false );
+				}
+			}
+			
+			total_unread.set( 0 );
+		}
+		
+		if ( changed ){
+		
+			contentChanged( true );
+		}
+	}
+	
+	public void
+	deleteAll()
+	{	
+		synchronized( rcm_lock ){
+
+			ContentCache	content_cache = loadRelatedContent();
+			
+			addPersistentlyDeleted( content_cache.related_content.values().toArray( new DownloadInfo[ content_cache.related_content.size()]));
+		
+			reset( false );
+		}
+	}
+	
+	protected void
+	incrementUnread()
+	{
+		total_unread.incrementAndGet();
+	}
+	
+	protected void
+	decrementUnread()
+	{
+		synchronized( rcm_lock ){
+			
+			int val = total_unread.decrementAndGet();
+			
+			if ( val < 0 ){
+				
+				// Debug.out( "inconsistent" );
+				
+				total_unread.set( 0 );
+			}
+		}
+	}
+	
+	protected Download
+	getDownload(
+		byte[]	hash )
+	{
+		try{
+			return( plugin_interface.getDownloadManager().getDownload( hash ));
+			
+		}catch( Throwable e ){
+			
+			return( null );
+		}
+	}
+	
+	private byte[][]
+	getKeys(
+		Download		download )
+	{
+		byte[]	tracker_keys	= null;
+		byte[]	ws_keys			= null;
+		
+		try{
+			Torrent torrent = download.getTorrent();
+		
+			if ( torrent != null ){
+				
+				TOTorrent to_torrent = PluginCoreUtils.unwrap( torrent );
+				
+				Set<String>	tracker_domains = new HashSet<String>();
+				
+				addURLToDomainKeySet( tracker_domains, to_torrent.getAnnounceURL());
+				
+				TOTorrentAnnounceURLGroup group = to_torrent.getAnnounceURLGroup();
+				
+				TOTorrentAnnounceURLSet[] sets = group.getAnnounceURLSets();
+				
+				for ( TOTorrentAnnounceURLSet set: sets ){
+					
+					URL[] urls = set.getAnnounceURLs();
+					
+					for ( URL u: urls ){
+						
+						addURLToDomainKeySet( tracker_domains, u );
+					}
+				}
+				
+				tracker_keys = domainsToArray( tracker_domains, 8 );
+				
+				Set<String>	ws_domains = new HashSet<String>();
+
+				List getright = BDecoder.decodeStrings( getURLList( to_torrent, "url-list" ));
+				List webseeds = BDecoder.decodeStrings( getURLList( to_torrent, "httpseeds" ));
+								
+				for ( List l: new List[]{ getright, webseeds }){
+					
+					for ( Object o: l ){
+					
+						if ( o instanceof String ){
+						
+							try{
+								addURLToDomainKeySet( ws_domains, new URL((String)o));
+								
+							}catch( Throwable e ){
+								
+							}
+						}
+					}
+				}
+				
+				ws_keys = domainsToArray( ws_domains, 3 );
+			}
+		}catch( Throwable e ){	
+		}
+		
+		return( new byte[][]{ tracker_keys, ws_keys });
+	}
+	
+	protected byte[]
+	domainsToArray(
+		Set<String>	domains,
+		int			max )
+	{
+		int	entries = Math.min( domains.size(), max );
+		
+		if ( entries > 0 ){
+			
+			byte[] keys = new byte[ entries*4 ];
+			
+			int	pos = 0;
+			
+			for ( String dom: domains ){
+				
+				int hash = dom.hashCode();
+				
+				byte[]	bytes = { (byte)(hash>>24), (byte)(hash>>16),(byte)(hash>>8),(byte)hash };
+				
+				System.arraycopy( bytes, 0, keys, pos, 4 );
+			
+				pos += 4;
+			}
+			
+			return( keys );
+		}
+		
+		return( null );
+	}
+	
+	protected List
+	getURLList(
+		TOTorrent	torrent,
+		String		key )
+	{
+		Object obj = torrent.getAdditionalProperty( key );
+		
+		if ( obj instanceof byte[] ){
+			
+            List l = new ArrayList();
+            
+	        l.add(obj);
+	        
+	        return( l );
+	        
+		}else if ( obj instanceof List ){
+			
+			return (List)BEncoder.clone(obj);
+			
+		}else{
+			
+			return( new ArrayList());
+		}
+	}
+	
+	private void
+	addURLToDomainKeySet(
+		Set<String>	set,
+		URL			u )
+	{
+		String prot = u.getProtocol();
+		
+		if ( prot != null ){
+			
+			if ( prot.equalsIgnoreCase( "http" ) || prot.equalsIgnoreCase( "udp" )){
+				
+				String host = u.getHost().toLowerCase( Locale.US );
+				
+				if ( host.contains( ":" )){
+				
+						// ipv6 raw
+					
+					return;
+				}
+				
+				String[] bits = host.split( "\\." );
+				
+				int	len = bits.length;
+				
+				if ( len >= 2 ){
+					
+					String	end = bits[len-1];
+					
+					char[] chars = end.toCharArray();
+					
+						// simple check for ipv4 raw
+					
+					boolean	all_digits = true;
+					
+					for ( char c: chars ){
+						
+						if ( !Character.isDigit( c )){
+							
+							all_digits = false;
+							
+							break;
+						}
+					}
+					
+					if ( !all_digits ){
+						
+						set.add( bits[len-2] + "." + end );
+					}
+				}
+			}
+		}
+	}
+		
+	private byte
+	getNetworks(
+		Download		download )
+	{
+		String[]	networks = download.getListAttribute( ta_networks );
+		
+		if ( networks == null ){
+				
+			return( NET_NONE );
+			
+		}else{
+		
+			return( convertNetworks( networks ));
+		}
+	}
+	
+	public static String[]
+	convertNetworks(
+		byte		net )
+	{
+		if ( net == NET_NONE ){
+			return( new String[0] );
+		}else if ( net == NET_PUBLIC ){
+			return( NET_PUBLIC_ARRAY );
+		}else if ( net == NET_I2P ){
+			return( NET_I2P_ARRAY );		
+		}else if ( net == NET_TOR ){
+			return( NET_TOR_ARRAY );
+		}else if ( net == (NET_PUBLIC | NET_I2P )){
+			return( NET_PUBLIC_AND_I2P_ARRAY );
+		}else{
+			List<String>	nets = new ArrayList<String>();
+			
+			if (( net & NET_PUBLIC ) != 0 ){
+				nets.add( AENetworkClassifier.AT_PUBLIC );
+			}
+			if (( net & NET_I2P ) != 0 ){
+				nets.add( AENetworkClassifier.AT_I2P );
+			}
+			if (( net & NET_TOR ) != 0 ){
+				nets.add( AENetworkClassifier.AT_TOR );
+			}
+			
+			return( nets.toArray( new String[ nets.size()]));
+		}
+	}
+	
+	public static byte
+	convertNetworks(
+		String[]		networks )
+	{
+		byte	nets = NET_NONE;
+
+		for ( int i=0;i<networks.length;i++ ){
+			
+			String n = networks[i];
+			
+			if (n.equalsIgnoreCase( AENetworkClassifier.AT_PUBLIC )){
+				
+				nets |= NET_PUBLIC;
+				
+			}else if ( n.equalsIgnoreCase( AENetworkClassifier.AT_I2P )){
+				
+				nets |= NET_I2P;
+				
+			}else if ( n.equalsIgnoreCase( AENetworkClassifier.AT_TOR )){
+				
+				nets |= NET_TOR;
+			}
+		}
+		
+		return( nets );
+	}
+	
+	private String[]
+	getTags(
+		Download	download )
+	{		
+		Set<String>	all_tags = new HashSet<String>();
+	
+		if ( tag_manager.isEnabled()){
+
+			String	cat_name = ta_category==null?null:download.getAttribute( ta_category );
+			
+			if ( cat_name != null ){
+				
+				Tag cat_tag = tag_manager.getTagType( TagType.TT_DOWNLOAD_CATEGORY ).getTag( cat_name, true );
+				
+				if ( cat_tag != null && cat_tag.isPublic()){
+				
+					all_tags.add( cat_name.toLowerCase( Locale.US ));
+				}
+			}
+			
+			List<Tag> tags = tag_manager.getTagType( TagType.TT_DOWNLOAD_MANUAL ).getTagsForTaggable( PluginCoreUtils.unwrap( download ));
+			
+			for ( Tag t: tags ){
+				
+				if ( t.isPublic()){
+				
+					all_tags.add( t.getTagName( true ).toLowerCase( Locale.US ));
+				}
+			}
+		}
+		
+		String[]	networks = download.getListAttribute( ta_networks );
+
+		for ( String network: networks ){
+			
+			if ( !network.equals( "Public" )){
+				
+				if ( AEPluginProxyHandler.hasPluginProxyForNetwork( network, true )){
+				
+					all_tags.add( "_" + network.toLowerCase( Locale.US ) + "_" );
+				}
+			}
+		}
+		
+		if ( all_tags.size() == 0 ){
+		
+			return( null );
+			
+		}else if ( all_tags.size() == 1 ){
+			
+			return( new String[]{ all_tags.iterator().next()});
+			
+		}else{
+			
+			List<String> temp = new ArrayList<String>( all_tags );
+			
+			Collections.shuffle( temp );
+			
+			return( temp.toArray( new String[ temp.size()] ));
+		}
+	}
+	
+	private static final int MAX_TAGS 			= 3;
+	private static final int MAX_TAG_LENGTH		= 20;
+	
+	protected byte[]
+	encodeTags(
+		String[]		tags )
+	{
+		if ( tags == null || tags.length == 0 ){
+			
+			return( null );
+		}
+		
+		byte[]	temp 	= new byte[MAX_TAGS*(MAX_TAG_LENGTH+1)];
+		int		pos		= 0;
+		
+		for ( int i=0;i<Math.min( MAX_TAGS, tags.length);i++){
+			
+			String tag = tags[i];
+			
+			tag = truncateTag( tag );
+			
+			try{
+				byte[] tag_bytes = tag.getBytes( "UTF-8" );
+					
+				int	tb_len = tag_bytes.length;
+											
+				temp[pos++] = (byte)tb_len;
+						
+				System.arraycopy( tag_bytes, 0, temp, pos, tb_len );
+						
+				pos += tb_len;
+				
+			}catch( Throwable e ){
+
+			}
+		}
+		
+		if ( pos == 0 ){
+			
+			return( null );
+			
+		}else{
+			
+			byte[] result = new byte[pos];
+			
+			System.arraycopy( temp, 0, result, 0, pos );
+			
+			return( result );
+		}
+	}
+	
+	protected String
+	truncateTag(
+		String	tag )
+	{
+		if ( tag.length() > MAX_TAG_LENGTH ){
+			
+			tag = tag.substring( 0, MAX_TAG_LENGTH );
+		}
+		
+		while( tag.length() > 0 ){
+			
+			try{
+				byte[] tag_bytes = tag.getBytes( "UTF-8" );
+								
+				if ( tag_bytes.length <= MAX_TAG_LENGTH ){
+					
+					break;
+					
+				}else{
+					
+					tag = tag.substring( 0, tag.length() - 1 );
+				}
+				
+			}catch( Throwable e ){
+				
+				break;
+			}
+		}
+		
+		return( tag );
+	}
+	
+	protected String[]
+	decodeTags(
+		byte[]		bytes )
+	{
+		if ( bytes == null || bytes.length == 0 ){
+		
+			return( null );
+		}
+		
+		List<String>	tags = new ArrayList<String>( MAX_TAGS );
+		
+		int	pos = 0;
+		
+		while( pos < bytes.length ){
+			
+			int	tag_len = bytes[pos++]&0x000000ff;
+			
+			if ( tag_len > MAX_TAG_LENGTH ){
+				
+				break;
+			}
+			
+			try{
+				tags.add( new String( bytes, pos, tag_len, "UTF-8" ));
+				
+				pos += tag_len;
+				
+			}catch( Throwable e ){
+				
+				break;
+			}
+		}
+		
+		if ( tags.size() == 0 ){
+		
+			return( null );
+			
+		}else{
+				
+			return( tags.toArray( new String[ tags.size()] ));
+		}
+	}
+	
+	private static final int PD_BLOOM_INITIAL_SIZE		= 1000;
+	private static final int PD_BLOOM_INCREMENT_SIZE	= 1000;
+	
+	
+	private BloomFilter	persist_del_bloom;
+	
+	protected byte[]
+	getPermDelKey(
+		RelatedContent	info )
+	{
+		byte[]	bytes = info.getHash();
+		
+		if ( bytes == null ){
+			
+			try{
+				bytes = new SHA1Simple().calculateHash( getPrivateInfoKey(info).getBytes( "ISO-8859-1" ));
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				return( null );
+			}
+		}
+		
+		byte[] key = new byte[8];
+		
+		System.arraycopy( bytes, 0, key, 0, 8 );
+		
+		return( key );
+	}
+	
+	protected List<byte[]>
+	loadPersistentlyDeleted()
+	{
+		List<byte[]> entries = null;
+		
+		if ( FileUtil.resilientConfigFileExists( PERSIST_DEL_FILE )){
+				
+			Map<String,Object> map = (Map<String,Object>)FileUtil.readResilientConfigFile( PERSIST_DEL_FILE );
+				
+			entries = (List<byte[]>)map.get( "entries" );
+		}
+	
+		if ( entries == null ){
+			
+			entries = new ArrayList<byte[]>(0);
+		}
+		
+		return( entries );
+	}
+	
+	protected void
+	addPersistentlyDeleted(
+		RelatedContent[]	content )
+	{		
+		if ( content.length == 0 ){
+			
+			return;
+		}
+	
+		List<byte[]> entries = loadPersistentlyDeleted();
+		
+		List<byte[]> new_keys = new ArrayList<byte[]>( content.length );
+		
+		for ( RelatedContent rc: content ){
+			
+			byte[] key = getPermDelKey( rc );
+			
+			new_keys.add( key );
+			
+			entries.add( key );
+		}
+		
+		Map<String,Object>	map = new HashMap<String, Object>();
+		
+		map.put( "entries", entries );
+		
+		FileUtil.writeResilientConfigFile( PERSIST_DEL_FILE, map );
+		
+		if ( persist_del_bloom != null ){
+			
+			if ( persist_del_bloom.getSize() / ( persist_del_bloom.getEntryCount() + content.length ) < 10 ){
+		
+				persist_del_bloom = BloomFilterFactory.createAddOnly( Math.max( PD_BLOOM_INITIAL_SIZE, persist_del_bloom.getSize() *10 + PD_BLOOM_INCREMENT_SIZE + content.length  ));
+				
+				for ( byte[] k: entries ){
+					
+					persist_del_bloom.add( k );
+				}
+			}else{
+				
+				for ( byte[] k: new_keys ){
+					
+					persist_del_bloom.add( k );
+				}
+			}
+		}
+	}
+	
+	protected boolean
+	isPersistentlyDeleted(
+		RelatedContent		content )
+	{
+		if ( persist_del_bloom == null ){
+			
+			List<byte[]> entries = loadPersistentlyDeleted();
+			
+			persist_del_bloom = BloomFilterFactory.createAddOnly( Math.max( PD_BLOOM_INITIAL_SIZE, entries.size()*10 + PD_BLOOM_INCREMENT_SIZE ));
+
+			for ( byte[] k: entries ){
+				
+				persist_del_bloom.add( k );
+			}
+		}
+		
+		byte[]	key = getPermDelKey( content );
+		
+		return( persist_del_bloom.contains( key ));
+	}
+
+	protected void
+	resetPersistentlyDeleted()
+	{
+		FileUtil.deleteResilientConfigFile( PERSIST_DEL_FILE );
+		
+		persist_del_bloom = BloomFilterFactory.createAddOnly( PD_BLOOM_INITIAL_SIZE );
+	}
+	
+	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( rcm_lock ){
+	
+			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 )
+	{
+		listeners.add( listener );
+	}
+	
+	public void
+	removeListener(
+		RelatedContentManagerListener		listener )
+	{
+		listeners.remove( listener );
+	}
+	
+	protected static class
+	ByteArrayHashMapEx<T>
+		extends ByteArrayHashMap<T>
+	{
+	    public T
+	    getRandomValueExcluding(
+	    	T	excluded )
+	    {
+	    	int	num = RandomUtils.nextInt( size );
+	    	
+	    	T result = null;
+	    	
+	        for (int j = 0; j < table.length; j++) {
+	        	
+		         Entry<T> e = table[j];
+		         
+		         while( e != null ){
+		        	 
+	              	T value = e.value;
+	               	
+	              	if ( value != excluded ){
+	              		
+	              		result = value;
+	              	}
+	              	
+	              	if ( num <= 0 && result != null ){
+	              		
+	              		return( result );
+	              	}
+	              	
+	              	num--;
+	              	
+	              	e = e.next;
+		        }
+		    }
+	    
+	        return( result );
+	    }
+	}
+	
+	private Map<String,Object>
+	serialiseDI(
+		DownloadInfo			info,
+		ContentCache			cc )
+	{
+		try{
+			Map<String,Object> info_map = new HashMap<String,Object>();
+			
+			info_map.put( "h", info.getHash());
+			
+			ImportExportUtils.exportString( info_map, "d", info.getTitle());
+			ImportExportUtils.exportInt( info_map, "r", info.getRand());
+			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());
+
+			byte[] tracker_keys = info.getTrackerKeys();
+			if ( tracker_keys != null ){
+				info_map.put( "k", tracker_keys );
+			}
+			
+			byte[] ws_keys = info.getWebSeedKeys();
+			if ( ws_keys != null ){
+				info_map.put( "w", ws_keys );
+			}
+			
+			String[] tags = info.getTags();
+			if ( tags != null ){
+				info_map.put( "g", encodeTags(tags));
+			}
+			
+			byte nets = info.getNetworksInternal();
+			if (nets != NET_PUBLIC ){
+				info_map.put( "o", new Long(nets&0x00ff ));
+			}
+			
+			if ( cc != null ){
+							
+				ImportExportUtils.exportBoolean( info_map, "u", info.isUnread());
+				ImportExportUtils.exportIntArray( info_map, "l", info.getRandList());
+				ImportExportUtils.exportInt( info_map, "s", info.getLastSeenSecs());
+				ImportExportUtils.exportInt( info_map, "e", info.getLevel());
+			}
+			
+			ImportExportUtils.exportLong(info_map, "cl", info.getChangedLocallyOn());
+			
+			return( info_map );
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( null );
+		}
+	}
+	
+	private DownloadInfo
+	deserialiseDI(
+		Map<String,Object>		info_map,
+		ContentCache			cc )
+	{
+		try{
+			byte[]	hash 	= (byte[])info_map.get("h");
+			String	title	= ImportExportUtils.importString( info_map, "d" );
+			int		rand	= ImportExportUtils.importInt( info_map, "r" );
+			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 );
+			byte[]	tracker_keys	= (byte[])info_map.get( "k");
+			byte[]	ws_keys			= (byte[])info_map.get( "w" );
+			long lastChangedLocally = ImportExportUtils.importLong( info_map, "cl" );
+			
+			if ( tracker_keys != null && tracker_keys.length % 4 != 0 ){
+				
+				tracker_keys = null;
+			}
+		
+			if ( ws_keys != null && ws_keys.length % 4 != 0 ){
+				
+				ws_keys = null;
+			}
+			
+			byte[]	_tags	= (byte[])info_map.get( "g" );
+
+			String[] tags = decodeTags( _tags );
+			
+			Long _nets = (Long)info_map.get( "o" );
+			
+			byte nets = _nets==null?NET_PUBLIC:_nets.byteValue();
+
+			if ( cc == null ){
+			
+				 DownloadInfo info = new DownloadInfo( hash, hash, title, rand, tracker, tracker_keys, ws_keys, tags, nets, 0, false, size, date, seeds_leechers, cnet );
+				 
+				 info.setChangedLocallyOn( lastChangedLocally );
+				 
+				 return( info );
+				
+			}else{
+				
+				boolean unread = ImportExportUtils.importBoolean( info_map, "u" );
+				
+				int[] rand_list = ImportExportUtils.importIntArray( info_map, "l" );
+				
+				int	last_seen = ImportExportUtils.importInt( info_map, "s" );
+				
+				int	level = ImportExportUtils.importInt( info_map, "e" );
+				
+				DownloadInfo info = new DownloadInfo( hash, title, rand, tracker, tracker_keys, ws_keys, tags, nets, unread, rand_list, last_seen, level, size, date, seeds_leechers, cnet, cc );
+				
+				info.setChangedLocallyOn( lastChangedLocally );
+        
+				return( info );
+			}
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( null );
+		}
+	}
+	
+	private void
+	dump()
+	{
+		RelatedContent[] related_content = getRelatedContent();
+		
+		ByteArrayHashMap<List<String>>	tk_map = new ByteArrayHashMap<List<String>>();
+		ByteArrayHashMap<List<String>>	ws_map = new ByteArrayHashMap<List<String>>();
+		
+		for ( RelatedContent rc: related_content ){
+						
+			byte[] tracker_keys = rc.getTrackerKeys();
+			
+			if ( tracker_keys != null ){
+				
+				for (int i=0;i<tracker_keys.length;i+=4 ){
+					
+					byte[] tk = new byte[4];
+					
+					System.arraycopy( tracker_keys, i, tk, 0, 4 );
+					
+					List<String> titles = tk_map.get( tk );
+					
+					if ( titles == null ){
+						
+						titles = new ArrayList<String>();
+						
+						tk_map.put( tk, titles );
+					}
+					
+					titles.add( rc.getTitle());
+				}
+			}
+			byte[] ws_keys = rc.getWebSeedKeys();
+			
+			if ( ws_keys != null ){
+				
+				for (int i=0;i<ws_keys.length;i+=4 ){
+					
+					byte[] wk = new byte[4];
+					
+					System.arraycopy( ws_keys, i, wk, 0, 4 );
+					
+					List<String> titles = ws_map.get( wk );
+					
+					if ( titles == null ){
+						
+						titles = new ArrayList<String>();
+						
+						ws_map.put( wk, titles );
+					}
+					
+					titles.add( rc.getTitle());
+				}
+			}
+		}
+		
+		System.out.println( "-- Trackers --" );
+		
+		for ( byte[] key: tk_map.keys()){
+			
+			List<String>	titles = tk_map.get( key );
+			
+			System.out.println( ByteFormatter.encodeString( key ));
+			
+			for ( String title: titles ){
+				
+				System.out.println( "    " + title );
+			}
+		}
+		
+		System.out.println( "-- Web Seeds --" );
+		
+		for ( byte[] key: ws_map.keys()){
+			
+			List<String>	titles = ws_map.get( key );
+			
+			System.out.println( ByteFormatter.encodeString( key ));
+			
+			for ( String title: titles ){
+				
+				System.out.println( "    " + title );
+			}
+		}
+	}
+	
+	protected class
+	DownloadInfo
+		extends RelatedContent
+	{
+		final private int		rand;
+		
+		private boolean			unread	= true;
+		private int[]			rand_list;
+		private int				last_seen;
+		private int				level;
+		private boolean			explicit;
+		
+			// we *need* this reference here to manage garbage collection correctly
+		
+		private ContentCache	cc;
+		
+		protected
+		DownloadInfo(
+			byte[]		_related_to,
+			byte[]		_hash,
+			String		_title,
+			int			_rand,
+			String		_tracker,
+			byte[]		_tracker_keys,
+			byte[]		_ws_keys,
+			String[]	_tags,
+			byte		_nets,
+			int			_level,
+			boolean		_explicit,
+			long		_size,
+			int			_date,
+			int			_seeds_leechers,
+			byte		_cnet )
+		{
+			super( _related_to, _title, _hash, _tracker, _tracker_keys, _ws_keys, _tags, _nets, _size, _date, _seeds_leechers, _cnet );
+			
+			rand		= _rand;
+			level		= _level;
+			explicit	= _explicit;
+			
+			updateLastSeen();
+		}
+		
+		protected
+		DownloadInfo(
+			byte[]			_hash,
+			String			_title,
+			int				_rand,
+			String			_tracker,
+			byte[]			_tracker_keys,
+			byte[]			_ws_keys,
+			String[]		_tags,
+			byte			_nets,
+			boolean			_unread,
+			int[]			_rand_list,
+			int				_last_seen,
+			int				_level,
+			long			_size,
+			int				_date,
+			int				_seeds_leechers,
+			byte			_cnet,
+			ContentCache	_cc )
+		{
+			super( _title, _hash, _tracker, _tracker_keys, _ws_keys, _tags, _nets, _size, _date, _seeds_leechers, _cnet );
+			
+			rand		= _rand;
+			unread		= _unread;
+			rand_list	= _rand_list;
+			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
+		addInfo(
+			DownloadInfo		info )
+		{
+			boolean	result = false;
+			
+			synchronized( this ){
+		
+				updateLastSeen();
+				
+				int r = info.getRand();
+				
+				if ( rand_list == null ){
+					
+					rand_list = new int[]{ r };
+										
+					result	= true;
+					
+				}else{
+					
+					boolean	match = false;
+					
+					for (int i=0;i<rand_list.length;i++){
+						
+						if ( rand_list[i] == r ){
+							
+							match = true;
+							
+							break;
+						}
+					}
+					
+					if ( !match && rand_list.length < MAX_RANK ){
+						
+						int	len = rand_list.length;
+						
+						int[]	new_rand_list = new int[len+1];
+						
+						System.arraycopy( rand_list, 0, new_rand_list, 0, len );
+						
+						new_rand_list[len] = r;
+						
+						rand_list = new_rand_list;
+						
+						result = true;
+					}
+				}
+			}
+				
+			if ( info.getLevel() < level ){
+				
+				level = info.getLevel();
+				
+				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 && getDateHours() == 0 ){
+				
+				setDateHours( d );
+				
+				result = true;
+			}
+				
+			String[] other_tags = info.getTags();
+			
+			if ( other_tags != null && other_tags.length > 0 ){
+			
+				String[] existing_tags = getTags();
+				
+				if ( existing_tags == NO_TAGS ){
+					
+					setTags( other_tags );
+					
+					result = true;
+					
+				}else{
+					
+					boolean	same;
+					
+					if ( other_tags.length == existing_tags.length ){
+					
+						if ( existing_tags.length == 1 ){
+							
+							same = other_tags[0].equals( existing_tags[0] );
+							
+						}else{
+							
+							same = true;
+							
+							for ( int i=0;i<existing_tags.length;i++ ){
+								
+								String e_tag = existing_tags[i];
+								
+								boolean	found = false;
+								
+								for ( int j=0;j<other_tags.length;j++){
+									
+									if ( e_tag.equals( other_tags[j])){
+										
+										found = true;
+										
+										break;
+									}
+								}
+								
+								if ( !found ){
+									
+									same = false;
+									
+									break;
+								}
+							}
+						}
+					}else{
+					
+						same = false;
+					}
+					
+					if ( !same ){
+						
+						Set<String>	tags = new HashSet<String>();
+						
+						for ( String t: existing_tags ){
+							tags.add( t );
+						}
+						for ( String t: other_tags ){
+							tags.add( t );
+						}
+						
+						setTags( tags.toArray( new String[tags.size()]));
+						
+						result = true;
+					}
+				}
+			}
+			
+			byte	other_nets 		= info.getNetworksInternal();
+			byte	existing_nets	= getNetworksInternal();
+			
+			if ( other_nets != existing_nets ){
+				
+				setNetworksInternal((byte)( other_nets | existing_nets ));
+				
+				result = true;
+			}
+			
+			if (result) {
+				setChangedLocallyOn(0);
+			}
+			return( result );
+		}
+		
+		public int
+		getLevel()
+		{
+			return( level );
+		}
+		
+		protected boolean
+		isExplicit()
+		{
+			return( explicit );
+		}
+		
+		protected void
+		setExplicit(
+			boolean		b )
+		{
+			explicit	= b;
+		}
+		
+		protected void
+		updateLastSeen()
+		{
+				// persistence of this is piggy-backed on other saves to limit resource usage
+				// only therefore a vague measure
+
+			last_seen	= (int)( SystemTime.getCurrentTime()/1000 );
+		}
+		
+		public int
+		getRank()
+		{
+			return( rand_list==null?0:rand_list.length );
+		}
+		
+		public boolean
+		isUnread()
+		{
+			return( unread );
+		}
+		
+		protected void
+		setPublic(
+			ContentCache	_cc )
+		{
+			cc	= _cc;
+			
+			if ( unread ){
+				
+				incrementUnread();
+			}
+			
+			rand_list = new int[]{ rand };
+			setChangedLocallyOn(0);
+		}
+		
+		public int
+		getLastSeenSecs()
+		{
+			return( last_seen );
+		}
+		
+		protected void
+		setUnreadInternal(
+			boolean	_unread )
+		{
+			synchronized( this ){
+
+				unread = _unread;
+			}
+		}
+		
+		public void
+		setUnread(
+			boolean	_unread )
+		{
+			boolean	changed = false;
+			
+			synchronized( this ){
+				
+				if ( unread != _unread ){
+				
+					unread = _unread;
+					
+					changed = true;
+				}
+			}
+			
+			if ( changed ){
+			
+				if ( _unread ){
+					
+					incrementUnread();
+					
+				}else{
+					
+					decrementUnread();
+				}
+				
+				setChangedLocallyOn(0);
+				contentChanged( this );
+			}
+		}
+		
+		protected int
+		getRand()
+		{
+			return( rand );
+		}
+		
+		protected int[]
+		getRandList()
+		{
+			return( rand_list );
+		}
+		
+		public Download 
+		getRelatedToDownload() 
+		{
+			try{
+				return( getDownload( getRelatedToHash()));
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				return( null );
+			}
+		}
+		
+		public void 
+		delete() 
+		{
+			setChangedLocallyOn(0);
+			RelatedContentManager.this.delete( new RelatedContent[]{ this });
+		}
+		
+		public String
+		getString()
+		{
+			return( super.getString() + ", " + rand + ", rl=" + rand_list + ", last_seen=" + last_seen + ", level=" + level );
+		}
+	}
+	
+	// can't move this class out of here as the key for the transfer type is based on its
+	// class name...
+	
+	protected class
+	RCMSearchXFer
+		implements DistributedDatabaseTransferType
+	{	
+	}
+	
+	protected static class
+	ContentCache
+	{
+		protected Map<String,DownloadInfo>						related_content			= new HashMap<String, DownloadInfo>();
+		protected ByteArrayHashMapEx<ArrayList<DownloadInfo>>	related_content_map		= new ByteArrayHashMapEx<ArrayList<DownloadInfo>>();
+	}
+	
+	private static class
+	SecondaryLookup
+	{
+		final private byte[]	hash;
+		final private int		level;
+		final private byte		nets;
+		
+		private
+		SecondaryLookup(
+			byte[]		_hash,
+			int			_level,
+			byte		_nets )
+		{
+			hash	= _hash;
+			level	= _level;
+			nets	= _nets;
+		}
+		
+		private byte[]
+		getHash()
+		{
+			return( hash );
+		}
+		
+		private int
+		getLevel()
+		{
+			return( level );
+		}
+		
+		private byte
+		getNetworks()
+		{
+			return( nets );
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/content/RelatedContentManagerListener.java b/azureus3/src/com/aelitis/azureus/core/content/RelatedContentManagerListener.java
index 6358f3c..0876c5d 100644
--- a/azureus3/src/com/aelitis/azureus/core/content/RelatedContentManagerListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/content/RelatedContentManagerListener.java
@@ -1,44 +1,43 @@
-/*
- * Created on Jul 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.content;
-
-public interface 
-RelatedContentManagerListener 
-{
-	public void
-	contentFound(
-		RelatedContent[]	content );
-
-	public void
-	contentChanged(
-		RelatedContent[]	content );
-	
-	public void
-	contentRemoved(
-		RelatedContent[]	content );
-	
-	public void
-	contentChanged();
-	
-	public void
-	contentReset();
-}
+/*
+ * Created on Jul 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.content;
+
+public interface 
+RelatedContentManagerListener 
+{
+	public void
+	contentFound(
+		RelatedContent[]	content );
+
+	public void
+	contentChanged(
+		RelatedContent[]	content );
+	
+	public void
+	contentRemoved(
+		RelatedContent[]	content );
+	
+	public void
+	contentChanged();
+	
+	public void
+	contentReset();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/content/RelatedContentSearcher.java b/azureus3/src/com/aelitis/azureus/core/content/RelatedContentSearcher.java
new file mode 100644
index 0000000..188d098
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/core/content/RelatedContentSearcher.java
@@ -0,0 +1,2360 @@
+/*
+ * Created on Sep 10, 2014
+ * Created by Paul Gardner
+ * 
+ * Copyright 2014 Azureus Software, 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.core.content;
+
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Pattern;
+
+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.AddressUtils;
+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.Constants;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.core3.util.UrlUtils;
+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.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.ddb.DDBaseImpl;
+
+import com.aelitis.azureus.core.cnetwork.ContentNetwork;
+import com.aelitis.azureus.core.content.RelatedContentManager.ContentCache;
+import com.aelitis.azureus.core.content.RelatedContentManager.DownloadInfo;
+import com.aelitis.azureus.core.dht.DHT;
+import com.aelitis.azureus.core.dht.transport.udp.DHTTransportUDP;
+import com.aelitis.azureus.core.util.RegExUtil;
+import com.aelitis.azureus.core.util.bloom.BloomFilter;
+import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
+import com.aelitis.azureus.plugins.dht.DHTPluginContact;
+import com.aelitis.azureus.plugins.dht.DHTPluginInterface;
+import com.aelitis.azureus.plugins.dht.DHTPluginInterface.DHTInterface;
+import com.aelitis.azureus.plugins.dht.DHTPluginValue;
+import com.aelitis.azureus.util.ImportExportUtils;
+
+public class 
+RelatedContentSearcher 
+	implements DistributedDatabaseTransferHandler
+{
+	private static final boolean	SEARCH_CVS_ONLY		= Constants.isCurrentVersionLT( "4.7.0.4" );
+	private static final boolean	TRACE_SEARCH		= false;
+
+	private static final int	MAX_REMOTE_SEARCH_RESULTS		= 30;
+	private static final int	MAX_REMOTE_SEARCH_CONTACTS		= 50;
+	private static final int	MAX_REMOTE_SEARCH_MILLIS		= 25*1000;
+	private static final int	REDUCED_REMOTE_SEARCH_MILLIS	= 10*1000;
+
+	private static final int	HARVEST_MAX_BLOOMS				= 50;
+	private static final int	HARVEST_MAX_FAILS_HISTORY		= 128;
+	private static final int	HARVEST_BLOOM_UPDATE_MILLIS		= 15*60*1000;
+	private static final int	HARVEST_BLOOM_DISCARD_MILLIS	= 60*60*1000;
+	private static final int 	HARVEST_BLOOM_OP_RESET_MILLIS	= 5*60*1000;
+	private static final int 	HARVEST_BLOOM_OP_RESET_TICKS	= HARVEST_BLOOM_OP_RESET_MILLIS/RelatedContentManager.TIMER_PERIOD;
+	private static final int 	HARVEST_BLOOM_SE_RESET_MILLIS	= 1*60*1000;
+	private static final int 	HARVEST_BLOOM_SE_RESET_TICKS	= HARVEST_BLOOM_SE_RESET_MILLIS/RelatedContentManager.TIMER_PERIOD;
+
+	private static final int KEY_BLOOM_LOAD_FACTOR			= 8;
+	private static final int KEY_BLOOM_MIN_BITS				= 1000;	
+	private static final int KEY_BLOOM_MAX_BITS				= 50000;	// 6k ish
+	private static final int KEY_BLOOM_MAX_ENTRIES			= KEY_BLOOM_MAX_BITS/KEY_BLOOM_LOAD_FACTOR;
+
+	private volatile BloomFilter	key_bloom_with_local;
+	private volatile BloomFilter	key_bloom_without_local;
+	private volatile long			last_key_bloom_update = -1;
+	
+	private Set<String>	ignore_words = new HashSet<String>();
+	
+	{
+		String ignore = "a, in, of, at, the, and, or, if, to, an, for, with";
+		
+		String[]	lame_entries = ignore.toLowerCase( Locale.US ).split(",");
+		
+		for ( String entry: lame_entries ){
+		
+			entry = entry.trim();
+			
+			if ( entry.length() > 0 ){
+				
+				ignore_words.add( entry );
+			}
+		}
+	}
+	
+	
+	
+	private ByteArrayHashMap<ForeignBloom>		harvested_blooms 	= new ByteArrayHashMap<ForeignBloom>();
+	private ByteArrayHashMap<String>			harvested_fails 	= new ByteArrayHashMap<String>();
+	
+	private volatile BloomFilter harvest_op_requester_bloom = BloomFilterFactory.createAddOnly( 2048 );
+	private volatile BloomFilter harvest_se_requester_bloom = BloomFilterFactory.createAddRemove4Bit( 512 );
+
+	private final AsyncDispatcher	harvest_dispatcher			= new AsyncDispatcher();
+
+	private final RelatedContentManager					manager;
+	private final DistributedDatabaseTransferType		transfer_type;
+	private final DHTPluginInterface					dht_plugin;
+	
+	private DistributedDatabase				ddb;
+
+	protected
+	RelatedContentSearcher(
+		RelatedContentManager				_manager,
+		DistributedDatabaseTransferType		_transfer_type,
+		DHTPluginInterface					_dht_plugin )
+	{
+		manager			= _manager;
+		transfer_type	= _transfer_type;
+		dht_plugin 		= _dht_plugin;
+	}
+	
+	protected DHTPluginInterface
+	getDHTPlugin()
+	{
+		return( dht_plugin );
+	}
+	
+	protected void
+	timerTick(
+		boolean		enabled,
+		int			tick_count )
+	{
+		if ( tick_count == 1 ){
+			
+			try{
+				List<DistributedDatabase> ddbs = DDBaseImpl.getDDBs( new String[]{ dht_plugin.getNetwork() });
+			
+				if ( ddbs.size() > 0 ){
+				
+					ddb = ddbs.get( 0 );
+					
+					ddb.addTransferHandler( transfer_type, this );
+				}
+			}catch( Throwable e ){
+				
+				// Debug.out( e );
+			}
+		}
+		
+		if ( enabled ){
+							
+			harvestBlooms();
+			
+			if ( tick_count % HARVEST_BLOOM_SE_RESET_TICKS == 0 ){
+				
+				harvest_se_requester_bloom = harvest_se_requester_bloom.getReplica();
+			}
+			
+			if ( tick_count % HARVEST_BLOOM_OP_RESET_TICKS == 0 ){
+				
+				harvest_op_requester_bloom = harvest_op_requester_bloom.getReplica();
+			}									
+		}
+		
+		checkKeyBloom();
+		
+		testKeyBloom();
+	}
+	
+	protected SearchInstance
+	searchRCM(
+		Map<String,Object>		search_parameters,
+		SearchObserver			_observer )
+	
+		throws SearchException
+	{				
+		final MySearchObserver observer = new MySearchObserver( _observer );
+		
+		final String	term = fixupTerm( (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>	hashes_sync_me = new HashSet<String>();
+					
+					try{				
+						List<RelatedContent>	matches = matchContent( term );
+							
+						for ( final RelatedContent c: matches ){
+							
+							final byte[] hash = c.getHash();
+							
+							if ( hash == null ){
+								
+								continue;
+							}
+							
+							hashes_sync_me.add( Base32.encode( hash ));
+							
+							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_HASH ){
+											
+											return( hash );
+											
+										}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( UrlUtils.getMagnetURI( hash, c.getTitle(), c.getNetworks()));
+											}
+										}else if ( property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_CONTENT_NETWORK ){
+											
+											return( c.getContentNetwork());
+											
+										}else if ( property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_TRACKER_KEYS ){
+											
+											return( c.getTrackerKeys());
+											
+										}else if ( property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_WEB_SEED_KEYS ){
+											
+											return( c.getWebSeedKeys());
+											
+										}else if ( property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_TAGS ){
+
+											return( c.getTags());
+											
+										}else if ( property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_NETWORKS ){
+
+											return( c.getNetworks());
+										}
+										
+										return( null );
+									}
+								};
+								
+							observer.resultReceived( si, result );
+						}
+					}finally{
+						
+						try{	
+							final List<DistributedDatabaseContact> 	initial_hinted_contacts = searchForeignBlooms( term );
+							final Set<DistributedDatabaseContact>	extra_hinted_contacts	= new HashSet<DistributedDatabaseContact>();
+							
+							Collections.shuffle( initial_hinted_contacts );
+							
+							// test injection of local 
+							// hinted_contacts.add( 0, ddb.getLocalContact());
+							
+							final LinkedList<DistributedDatabaseContact>	contacts_to_search = new LinkedList<DistributedDatabaseContact>();
+
+							final Map<InetSocketAddress,DistributedDatabaseContact> contact_map = new HashMap<InetSocketAddress, DistributedDatabaseContact>();
+														
+							for ( DistributedDatabaseContact c: initial_hinted_contacts ){
+								
+									// stick in map so non-hinted get removed below, but interleave later
+								
+								contact_map.put( c.getAddress(), c );
+							}
+							
+								// ddb might be null during init
+							
+							if ( ddb != null ){
+								
+								DHTInterface[]	dhts = dht_plugin.getDHTInterfaces();
+									
+								for ( DHTInterface dht: dhts ){
+													
+									if ( dht.isIPV6()){
+										
+										continue;
+									}
+									
+									int	network = dht.getNetwork();
+									
+									if ( SEARCH_CVS_ONLY && network != DHT.NW_CVS ){
+										
+										logSearch( "Search: ignoring main DHT" );
+	
+										continue;
+									}
+									
+									DHTPluginContact[] contacts = dht.getReachableContacts();
+									
+									Collections.shuffle( Arrays.asList( contacts ));
+																	
+									for ( DHTPluginContact dc: contacts ){
+												
+										InetSocketAddress address = dc.getAddress();
+										
+										if ( !contact_map.containsKey( address )){
+											
+											try{
+												DistributedDatabaseContact c = importContact( dc, network );
+												
+												contact_map.put( address, c );
+												
+												contacts_to_search.add( c );
+												
+											}catch( Throwable e ){
+												
+											}
+										}
+									}
+								}
+								
+								if ( contact_map.size() < MAX_REMOTE_SEARCH_CONTACTS ){
+									
+										// back fill with less reliable contacts if required
+									
+									for ( DHTInterface dht: dhts ){
+																				
+										if ( dht.isIPV6()){
+											
+											continue;
+										}
+										
+										int	network = dht.getNetwork();
+										
+										if ( SEARCH_CVS_ONLY && network != DHT.NW_CVS ){
+											
+											logSearch( "Search: ignoring main DHT" );
+	
+											continue;
+										}
+										
+										DHTPluginContact[] contacts = dht.getRecentContacts();
+		
+										for ( DHTPluginContact dc: contacts ){
+											
+											InetSocketAddress address = dc.getAddress();
+											
+											if ( !contact_map.containsKey( address )){
+												
+												try{
+													DistributedDatabaseContact c = importContact( dc, network );
+													
+													contact_map.put( address, c );
+													
+													contacts_to_search.add( c );
+																					
+													if ( contact_map.size() >= MAX_REMOTE_SEARCH_CONTACTS ){
+														
+														break;
+													}
+												}catch( Throwable e ){
+													
+												}
+											}
+										}
+										
+										if ( contact_map.size() >= MAX_REMOTE_SEARCH_CONTACTS ){
+											
+											break;
+										}
+									}
+								}
+							}
+							
+								// interleave hinted ones so we get some variety
+							
+							int	desired_pos = 0;
+							
+							for ( DistributedDatabaseContact dc: initial_hinted_contacts ){
+								
+								if ( desired_pos < contacts_to_search.size()){
+									
+									contacts_to_search.add( desired_pos, dc );
+								
+									desired_pos += 2;
+									
+								}else{
+									
+									contacts_to_search.addLast( dc );
+								}
+							}
+
+							
+							long	start		= SystemTime.getMonotonousTime();
+							long	max			= MAX_REMOTE_SEARCH_MILLIS;
+							
+							final AESemaphore	sem = new AESemaphore( "RCM:rems" );
+							
+							int	sent = 0;
+							
+							final int[]			done = {0};
+							
+							logSearch( "Search starts: contacts=" + contacts_to_search.size() + ", hinted=" + initial_hinted_contacts.size());
+							
+							while( true ){
+										
+									// hard limit of total results found and overall elapsed
+								
+								if ( 	observer.getResultCount() >= 200 || 
+										SystemTime.getMonotonousTime() - start >= max ){
+									
+									logSearch( "Hard limit exceeded" );
+									
+									return;
+								}
+
+								if ( sent >= MAX_REMOTE_SEARCH_CONTACTS ){
+									
+									logSearch( "Max contacts searched" );
+									
+									break;
+								}
+
+								final DistributedDatabaseContact contact_to_search;
+								
+								synchronized( contacts_to_search ){
+									
+									if ( contacts_to_search.isEmpty()){
+										
+										logSearch( "Contacts exhausted" );
+										
+										break;
+										
+									}else{
+										
+										contact_to_search = contacts_to_search.removeFirst();
+									}
+								}
+																
+								new AEThread2( "RCM:rems", true )
+								{
+									public void
+									run()
+									{
+										try{
+											logSearch( "Searching " + contact_to_search.getAddress());
+											
+											List<DistributedDatabaseContact> extra_contacts = sendRemoteSearch( si, hashes_sync_me, contact_to_search, term, observer );
+													
+											if ( extra_contacts == null ){
+												
+												logSearch( "    " + contact_to_search.getAddress() + " failed" );
+												
+												foreignBloomFailed( contact_to_search );
+												
+											}else{
+												
+												String	type;
+												
+												if ( initial_hinted_contacts.contains( contact_to_search )){
+													type = "i";
+												}else if ( extra_hinted_contacts.contains( contact_to_search )){
+													type = "e";
+												}else{
+													type = "n";
+												}
+												logSearch( "    " + contact_to_search.getAddress() + " OK " + type + " - additional=" + extra_contacts.size());
+												
+													// insert results from more predictable nodes after the less predictable ones
+												
+												synchronized( contacts_to_search ){
+													
+													int	insert_point = 0;
+													
+													if ( type.equals( "i" )){
+														
+														for (int i=0;i<contacts_to_search.size();i++){
+															
+															if ( extra_hinted_contacts.contains(contacts_to_search.get(i))){
+																
+																insert_point = i+1;
+															}
+														}
+													}
+													
+													for ( DistributedDatabaseContact c: extra_contacts ){
+														
+														InetSocketAddress address = c.getAddress();
+						
+														if ( !contact_map.containsKey( address )){
+															
+															logSearch( "        additional target: " + address );
+															
+															extra_hinted_contacts.add( c );
+															
+															contact_map.put( address, c );
+															
+															contacts_to_search.add( insert_point, c );
+														}
+													}
+												}
+											}
+										}finally{
+											
+											synchronized( done ){
+											
+												done[0]++;
+											}
+											
+											sem.release();
+										}
+									}
+								}.start();
+								
+								sent++;
+								
+								synchronized( done ){
+									
+									if ( done[0] >= MAX_REMOTE_SEARCH_CONTACTS / 2 ){
+										
+										logSearch( "Switching to reduced time limit (1)" );
+										
+											// give another 5 secs for results to come in
+										
+										start		= SystemTime.getMonotonousTime();
+										max			= REDUCED_REMOTE_SEARCH_MILLIS;
+										
+										break;
+									}
+								}
+								
+								if ( sent > 10 ){
+									
+										// rate limit a bit after the first 10
+									
+									try{
+										Thread.sleep( 250 );
+										
+									}catch( Throwable e ){
+									}
+								}
+							}
+							
+							logSearch( "Request dispatch complete: sent=" + sent + ", done=" + done[0] );
+							
+							for ( int i=0;i<sent;i++ ){
+								
+								if ( done[0] > sent*9/10 ){
+									
+									logSearch( "9/10ths replied (" + done[0] + "/" + sent + "), done" );
+									
+									break;
+								}
+								
+								long	remaining = ( start + max ) - SystemTime.getMonotonousTime();
+								
+								if ( 	remaining > REDUCED_REMOTE_SEARCH_MILLIS &&
+										done[0] >= MAX_REMOTE_SEARCH_CONTACTS / 2 ){
+									
+									logSearch( "Switching to reduced time limit (2)" );
+									
+										// give another 5 secs for results to come in
+									
+									start		= SystemTime.getMonotonousTime();
+									max			= REDUCED_REMOTE_SEARCH_MILLIS;
+								}
+								
+								if ( remaining > 0 ){
+									
+									sem.reserve( 250 );
+									
+								}else{
+									
+									logSearch( "Time exhausted" );
+									
+									break;
+								}
+							}
+						}finally{
+								
+							logSearch( "Search complete" );
+							
+							observer.complete();
+						}
+					}
+				}
+			}.start();
+		}
+		
+		return( si );
+	}
+	
+	private String
+	fixupTerm(
+		String	term )
+	{
+		if ( term == null ){
+			
+			return( null );
+		}
+		
+		// if someone has a | in the expression then they probably mean "or" so to work with the following we remove any spaces
+		// either side of it
+	
+		if ( term.contains( "|" )){
+			
+			while( term.contains( " |" )){
+				
+				term = term.replaceAll( " \\|", "|" );
+			}
+			
+		while( term.contains( "| " )){
+				
+				term = term.replaceAll( "\\| ", "|" );
+			}
+		}
+		
+		return( term );
+	}
+	
+	private String
+	escapeTag(
+		String	tag )
+	{
+		if ( tag.contains( " " )){
+			
+			tag = tag.replaceAll( " ", "+" );
+		}
+		
+		return( tag );
+	}
+	
+	private String
+	unescapeTag(
+		String	tag )
+	{
+		if ( tag.contains( "+" )){
+			
+			tag = tag.replaceAll( "\\+", " " );
+		}
+		
+		return( tag );
+	}
+	
+	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'
+		
+		String[]	 bits = Constants.PAT_SPLIT_SPACE.split(term.toLowerCase());
+
+		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{
+						if ( !RegExUtil.mightBeEvil( bit )){
+						
+							bit_patterns[i] = Pattern.compile( bit, Pattern.CASE_INSENSITIVE );
+						}
+					}catch( Throwable e ){
+					}
+				}else if ( bit.contains( "|" )){
+					
+					if ( !bit.contains( "tag:" )){
+						
+						try{
+							if ( !RegExUtil.mightBeEvil( bit )){
+							
+								bit_patterns[i] = Pattern.compile( bit, Pattern.CASE_INSENSITIVE );
+							}
+						}catch( Throwable e ){
+						}
+					}
+				}
+			}
+		}
+		
+		Map<String,RelatedContent>	result = new HashMap<String,RelatedContent>();
+		
+		Iterator<DownloadInfo>	it1 = getDHTInfos().iterator();
+		
+		Iterator<DownloadInfo>	it2;
+		
+		synchronized( manager.rcm_lock ){
+		
+			it2 = new ArrayList<DownloadInfo>( RelatedContentManager.transient_info_cache.values()).iterator();
+		}
+
+		Iterator<DownloadInfo>	it3 = manager.getRelatedContentAsList().iterator();
+
+		for ( Iterator _it: new Iterator[]{ it1, it2, it3 }){
+			
+			Iterator<DownloadInfo> it = (Iterator<DownloadInfo>)_it;	
+			
+			while( it.hasNext()){
+				
+				DownloadInfo c = it.next();
+				
+				String title 	= c.getTitle();
+				String lc_title = c.getTitle().toLowerCase();
+				
+				boolean	match 			= true;
+				boolean	at_least_one 	= false;
+				
+				if ( title.equalsIgnoreCase( term ) && term.trim().length() > 0 ){
+					
+						// pick up a direct match regardless of anything else
+					
+					at_least_one = true;
+					
+				}else{
+					
+					for (int i=0;i<bits.length;i++){
+						
+						String bit = bits[i];
+						
+						if ( bit.length() > 0 ){
+							
+							boolean	hit;
+							
+							if ( bit_patterns[i] == null ){
+							
+								String[]	sub_bits = bit.split("\\|");
+								
+								hit = false;
+								
+								for ( String sub_bit: sub_bits ){
+
+									if ( sub_bit.startsWith( "tag:" )){
+										
+										String[] tags = c.getTags();
+										
+										hit = false;
+										
+										if ( tags != null && tags.length > 0 ){
+											
+											String	target_tag = sub_bit.substring( 4 ).toLowerCase( Locale.US );
+											
+											target_tag = unescapeTag( target_tag );
+											
+											target_tag = manager.truncateTag( target_tag );
+											
+											for ( String t: tags ){
+												
+												if ( t.startsWith( target_tag )){
+													
+													hit = true;
+													
+													break;
+												}
+											}
+										}
+									}else{
+									
+										hit = lc_title.contains( sub_bit );
+									}
+									
+									if ( hit ){
+										
+										break;
+									}
+								}
+							}else{
+							
+								hit = bit_patterns[i].matcher( lc_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 ){
+					
+					byte[]	hash = c.getHash();
+					
+					String key;
+					
+					if ( hash != null ){
+						
+						key = Base32.encode( hash );
+						
+					}else{
+			
+						key = manager.getPrivateInfoKey( c );
+					}
+					
+					result.put( key, c );
+				}
+			}
+		}
+		
+		return( new ArrayList<RelatedContent>( result.values()));
+	}
+	
+	protected List<DistributedDatabaseContact>
+	sendRemoteSearch(
+		SearchInstance					si,
+		Set<String>						hashes_sync_me,
+		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,
+					contact.getAddress().isUnresolved()?20000:10000 );
+						
+			if ( value == null ){
+				
+				return( null );
+			}
+			
+			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" );
+			
+			if ( list != null ){
+				
+				for ( final Map<String,Object> map: list ){
+					
+					final String title = ImportExportUtils.importString( map, "n" );
+					
+					final byte[] hash = (byte[])map.get( "h" );
+					
+					if ( hash == null ){
+						
+						continue;
+					}
+					
+					String	hash_str = Base32.encode( hash );
+						
+					synchronized( hashes_sync_me ){
+						
+						if ( hashes_sync_me.contains( hash_str )){
+							
+							continue;
+						}
+						
+						hashes_sync_me.add( hash_str );
+					}
+	
+					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_HASH ){
+										
+										return( hash );
+										
+									}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( UrlUtils.getMagnetURI( hash, title, RelatedContentManager.convertNetworks((byte)ImportExportUtils.importLong( map, "o", RelatedContentManager.NET_PUBLIC ))));
+										}
+									}else if (  property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_CONTENT_NETWORK ){
+										
+										long cnet = ImportExportUtils.importLong( map, "c", ContentNetwork.CONTENT_NETWORK_UNKNOWN );
+	
+										return( cnet );
+										
+									}else if ( property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_TRACKER_KEYS ){
+										
+										return( map.get( "k" ));
+										
+									}else if ( property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_WEB_SEED_KEYS ){
+										
+										return( map.get( "w" ));
+										
+									}else if ( property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_TAGS ){
+										
+										return( manager.decodeTags((byte[])map.get( "g" )));
+										
+									}else if ( property_name == RelatedContentManager.RCM_SEARCH_PROPERTY_NETWORKS ){
+	
+										return( RelatedContentManager.convertNetworks((byte)ImportExportUtils.importLong( map, "o", RelatedContentManager.NET_PUBLIC )));
+									}
+	
+								}catch( Throwable e ){
+								}
+								
+								return( null );
+							}
+						};
+						
+					observer.resultReceived( si, result );
+				}
+			}
+			
+			list = (List<Map<String,Object>>)reply.get( "c" );
+
+			List<DistributedDatabaseContact>	contacts = new ArrayList<DistributedDatabaseContact>();
+			
+			if ( list != null ){
+			
+				for ( Map<String,Object> m: list ){
+					
+					try{
+						Map<String,Object> map = (Map<String,Object>)m.get( "m" );
+						
+						if ( map != null ){
+							
+							DistributedDatabaseContact ddb_contact = ddb.importContact( map );
+		
+							contacts.add( ddb_contact );
+							
+						}else{
+							
+							String	host 	= ImportExportUtils.importString( m, "a" );
+							
+							int		port	= ImportExportUtils.importInt( m, "p" );
+							
+							DistributedDatabaseContact ddb_contact = 
+								ddb.importContact( new InetSocketAddress( InetAddress.getByName(host), port ), DHTTransportUDP.PROTOCOL_VERSION_MIN, contact.getDHT());
+	
+							contacts.add( ddb_contact );
+						}
+						
+					}catch( Throwable e ){
+					}
+					
+				}
+			}
+			
+			return( contacts );
+			
+		}catch( Throwable e ){
+			
+			return( null );
+		}
+	}
+	
+	protected BloomFilter
+	sendRemoteFetch(
+		DistributedDatabaseContact		contact )
+	{
+		try{
+			Map<String,Object>	request = new HashMap<String,Object>();
+			
+			request.put( "x", "f" );
+		
+			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,
+					contact.getAddress().isUnresolved()?15000:5000 );
+			
+				// System.out.println( "search result=" + value );
+			
+			if ( value != null ){
+			
+				Map<String,Object> reply = (Map<String,Object>)BDecoder.decode((byte[])value.getValue( byte[].class ));
+			
+				Map<String,Object>	m = (Map<String,Object>)reply.get( "f" );
+				
+				if ( m != null ){
+					
+					return( BloomFilterFactory.deserialiseFromMap( m ));
+				}
+			}
+		}catch( Throwable e ){
+		}
+		
+		return( null );
+	}
+	
+	protected BloomFilter
+	sendRemoteUpdate(
+		ForeignBloom	f_bloom )
+	{
+		try{
+			Map<String,Object>	request = new HashMap<String,Object>();
+			
+			request.put( "x", "u" );
+			request.put( "s", new Long( f_bloom.getFilter().getEntryCount()));
+		
+			DistributedDatabaseKey key = ddb.createKey( BEncoder.encode( request ));
+			
+			DistributedDatabaseContact contact = f_bloom.getContact();
+			
+			DistributedDatabaseValue value = 
+				contact.read( 
+					new DistributedDatabaseProgressListener()
+					{
+						public void
+						reportSize(
+							long	size )
+						{	
+						}
+						
+						public void
+						reportActivity(
+							String	str )
+						{	
+						}
+						
+						public void
+						reportCompleteness(
+							int		percent )
+						{
+						}
+					},
+					transfer_type,
+					key,
+					contact.getAddress().isUnresolved()?15000:5000 );
+			
+				// System.out.println( "search result=" + value );
+			
+			if ( value != null ){
+			
+				Map<String,Object> reply = (Map<String,Object>)BDecoder.decode((byte[])value.getValue( byte[].class ));
+			
+				Map<String,Object>	m = (Map<String,Object>)reply.get( "f" );
+				
+				if ( m != null ){
+					
+					logSearch( "Bloom for " + f_bloom.getContact().getAddress() + " updated" );
+
+					return( BloomFilterFactory.deserialiseFromMap( m ));
+					
+				}else{
+					
+					if ( reply.containsKey( "s" )){
+						
+						logSearch( "Bloom for " + f_bloom.getContact().getAddress() + " same size" );
+						
+					}else{
+						
+						logSearch( "Bloom for " + f_bloom.getContact().getAddress() + " update not supported yet" );
+					}
+					
+					return( f_bloom.getFilter());
+				}
+			}
+		}catch( Throwable e ){
+		}
+		
+		logSearch( "Bloom for " + f_bloom.getContact().getAddress() + " update failed" );
+
+		return( null );
+	}
+	
+	protected Map<String,Object>
+	receiveRemoteRequest(
+		DistributedDatabaseContact		originator,
+		Map<String,Object>				request )
+	{
+		Map<String,Object>	response = new HashMap<String,Object>();
+		
+		try{	
+			boolean	originator_is_neighbour = false;
+			
+			DHTInterface[] dhts = dht_plugin.getDHTInterfaces();
+			
+			byte[] originator_id = originator.getID();
+			
+			byte[] originator_bytes = AddressUtils.getAddressBytes( originator.getAddress());
+
+			for ( DHTInterface d: dhts ){
+				
+				List<DHTPluginContact> contacts = d.getClosestContacts( d.getID(), true );
+				
+				for ( DHTPluginContact c: contacts ){
+					
+					if ( Arrays.equals( c.getID(), originator_id)){
+						
+						originator_is_neighbour = true;
+						
+						break;
+					}
+				}
+				
+				if ( originator_is_neighbour ){
+					
+					break;
+				}
+			}
+			
+			String	req_type = ImportExportUtils.importString( request, "x" );
+			
+			if ( req_type != null ){
+							
+				boolean dup = harvest_op_requester_bloom.contains( originator_bytes );
+					
+				logSearch( "Received remote request: " + BDecoder.decodeStrings( request ) + " from " + originator.getAddress() + "/" + originator.getDHT() + ", dup=" + dup + ", bs=" + harvest_op_requester_bloom.getEntryCount());
+				
+				if ( !dup ){
+					
+					harvest_op_requester_bloom.add( originator_bytes );
+					
+					if ( req_type.equals( "f" )){
+						
+						BloomFilter filter = getKeyBloom( !originator_is_neighbour );
+						
+						if ( filter != null ){
+							
+							response.put( "f", filter.serialiseToMap());
+						}
+					}else if ( req_type.equals( "u" )){
+						
+						BloomFilter filter = getKeyBloom( !originator_is_neighbour );
+						
+						if ( filter != null ){
+	
+							int	existing_size = ImportExportUtils.importInt( request, "s", 0 );
+						
+							if ( existing_size != filter.getEntryCount()){
+								
+								response.put( "f", filter.serialiseToMap());
+								
+							}else{
+								
+								response.put( "s", new Long( existing_size ));
+							}
+						}
+					}
+				}
+			}else{
+					// fallback to default handling
+
+				int hits = harvest_se_requester_bloom.count( originator_bytes );
+				
+				String	term = ImportExportUtils.importString( request, "t" );
+
+				term = fixupTerm( term );
+				
+				logSearch( "Received remote search: '" + term + "' from " + originator.getAddress() + ", hits=" + hits + ", bs=" + harvest_se_requester_bloom.getEntryCount());
+
+				if ( hits < 10 ){
+					
+					harvest_se_requester_bloom.add( originator_bytes );
+					
+					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>> l_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>();
+							
+							l_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 );
+							}
+							
+							byte[] tracker_keys = c.getTrackerKeys();
+							
+							if ( tracker_keys != null ){
+								map.put( "k", tracker_keys );
+							}
+							
+							byte[] ws_keys	= c.getWebSeedKeys();
+							
+							if ( ws_keys != null ){
+								map.put( "w", ws_keys );
+							}
+							
+							String[] tags = c.getTags();
+							
+							if ( tags != null ){
+								map.put( "g", manager.encodeTags( tags ));
+							}
+							
+							byte nets = c.getNetworksInternal();
+							
+							if ( 	nets != RelatedContentManager.NET_NONE &&  
+									nets != RelatedContentManager.NET_PUBLIC ){
+								
+								map.put( "o", new Long( nets&0x00ff));
+							}
+							
+								// don't bother with tracker as no use to caller really
+						}
+						
+						response.put( "l", l_list );
+					
+						List<DistributedDatabaseContact> bloom_hits = searchForeignBlooms( term );
+						
+						if ( bloom_hits.size() > 0 ){
+							
+							List<Map>	c_list = new ArrayList<Map>();
+							
+							for ( DistributedDatabaseContact c: bloom_hits ){
+								
+								Map	m = new HashMap();
+								
+								c_list.add( m );
+								
+								InetSocketAddress address = c.getAddress();
+								
+								if ( address.isUnresolved()){
+									
+									m.put( "m", c.exportToMap());
+									
+								}else{
+									m.put( "a", address.getAddress().getHostAddress());
+									
+									m.put( "p", new Long( address.getPort()));
+								}
+							}
+							
+							response.put( "c", c_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 = receiveRemoteRequest( contact, request );
+			
+			return( ddb.createValue( BEncoder.encode( result )));
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( null );
+		}
+	}
+	
+	public DistributedDatabaseValue
+	write(
+		DistributedDatabaseContact			contact,
+		DistributedDatabaseTransferType		type,
+		DistributedDatabaseKey				key,
+		DistributedDatabaseValue			value )
+	
+		throws DistributedDatabaseException
+	{
+		return( null );
+	}
+	
+	private void
+	checkKeyBloom()
+	{
+		if ( last_key_bloom_update == -1 || SystemTime.getMonotonousTime() - last_key_bloom_update > 10*60*1000 ){
+			
+			synchronized( manager.rcm_lock ){
+				
+				updateKeyBloom( manager.loadRelatedContent());
+			}
+		}
+	}
+	
+	private BloomFilter
+	getKeyBloom(
+		boolean		include_dht_local )
+	{
+		if ( key_bloom_with_local == null ){
+				
+			synchronized( manager.rcm_lock ){
+			
+				updateKeyBloom( manager.loadRelatedContent());
+			}
+		}
+			
+		if ( include_dht_local ){
+			
+			return( key_bloom_with_local );
+			
+		}else{
+			
+			return( key_bloom_without_local );
+		}
+	}
+	
+	private List<String>
+	getDHTWords(
+		DownloadInfo	info )
+	{
+		String title = info.getTitle();
+		
+		title = title.toLowerCase( Locale.US );
+		
+		char[]	chars = title.toCharArray();
+		
+		for ( int i=0;i<chars.length;i++){
+			
+			if ( !Character.isLetterOrDigit( chars[i])){
+				
+				chars[i] = ' ';
+			}
+		}
+		
+		String[] words = new String( chars ).split( " " );
+		
+		List<String>	result = new ArrayList<String>( words.length );
+		
+		for ( String word: words ){
+			
+			if ( word.length() > 0 && !ignore_words.contains( word )){
+				
+				result.add( word );
+			}
+		}
+		
+		String[] tags = info.getTags();
+		
+		if ( tags != null ){
+			
+			for ( String tag: tags ){
+				
+				tag = escapeTag( tag );
+							
+					// support prefix matching
+				
+				for ( int i=1; i<=tag.length(); i++){
+				
+					result.add( "tag:" + tag.substring( 0, i ));
+				}
+			}
+		}
+		
+		return( result );
+	}
+	
+	protected void
+	updateKeyBloom(
+		RelatedContentManager.ContentCache		cc )
+	{
+		synchronized( manager.rcm_lock ){
+												
+			Set<String>	dht_only_words 		= new HashSet<String>();
+			Set<String>	non_dht_words 		= new HashSet<String>();
+			
+			List<DownloadInfo>		dht_infos		= getDHTInfos();
+			
+			Iterator<DownloadInfo>	it_dht 			= dht_infos.iterator();
+						
+			Iterator<DownloadInfo>	it_transient 	= RelatedContentManager.transient_info_cache.values().iterator();
+			
+			Iterator<DownloadInfo>	it_rc 			= cc.related_content.values().iterator();			
+
+			for ( Iterator _it: new Iterator[]{ it_transient, it_rc, it_dht }){
+				
+				Iterator<DownloadInfo> it = (Iterator<DownloadInfo>)_it;
+				
+				while( it.hasNext()){
+				
+					DownloadInfo di = it.next();
+							
+					List<String>	words = getDHTWords( di );
+					
+					for ( String word: words ){
+															
+							// note that it_dht is processed last
+						
+						if ( it == it_dht ){
+							
+							if ( !non_dht_words.contains( word )){
+							
+								dht_only_words.add( word );
+							}
+						}else{
+															
+							non_dht_words.add( word );
+						}
+					}
+				}
+			}
+			
+			int	all_desired_bits = (dht_only_words.size() + non_dht_words.size()) * KEY_BLOOM_LOAD_FACTOR;
+			
+			all_desired_bits = Math.max( all_desired_bits, KEY_BLOOM_MIN_BITS );
+			all_desired_bits = Math.min( all_desired_bits, KEY_BLOOM_MAX_BITS );
+			
+			BloomFilter all_bloom = BloomFilterFactory.createAddOnly( all_desired_bits );
+
+			int	non_dht_desired_bits = non_dht_words.size() * KEY_BLOOM_LOAD_FACTOR;
+			
+			non_dht_desired_bits = Math.max( non_dht_desired_bits, KEY_BLOOM_MIN_BITS );
+			non_dht_desired_bits = Math.min( non_dht_desired_bits, KEY_BLOOM_MAX_BITS );
+			
+			BloomFilter non_dht_bloom = BloomFilterFactory.createAddOnly( non_dht_desired_bits );
+
+			List<String>	non_dht_words_rand = new ArrayList<String>( non_dht_words );
+			
+			Collections.shuffle( non_dht_words_rand );
+			
+			for ( String word: non_dht_words_rand ){
+				
+				try{
+					byte[]	bytes = word.getBytes( "UTF8" );
+					
+					all_bloom.add( bytes );
+					
+					if ( all_bloom.getEntryCount() >= KEY_BLOOM_MAX_ENTRIES ){
+						
+						break;
+					}
+					
+					if ( non_dht_bloom.getEntryCount() < KEY_BLOOM_MAX_ENTRIES ){
+					
+						non_dht_bloom.add( bytes );
+					}
+				}catch( Throwable e ){
+				}
+			}
+				
+			List<String>	dht_only_words_rand = new ArrayList<String>( dht_only_words );
+			
+			Collections.shuffle( dht_only_words_rand );
+
+			for ( String word: dht_only_words_rand ){
+				
+				try{
+					byte[]	bytes = word.getBytes( "UTF8" );
+					
+					all_bloom.add( bytes );
+					
+					if ( all_bloom.getEntryCount() >= KEY_BLOOM_MAX_ENTRIES ){
+						
+						break;
+					}
+				}catch( Throwable e ){
+				}
+			}
+			
+			logSearch( 
+				"blooms=" + 
+				all_bloom.getSize() + "/" + all_bloom.getEntryCount() +", " +
+				non_dht_bloom.getSize() + "/" + non_dht_bloom.getEntryCount()  +
+				": rcm=" + cc.related_content.size() + ", trans=" + RelatedContentManager.transient_info_cache.size() + ", dht=" + dht_infos.size());
+			
+			key_bloom_with_local 	= all_bloom;
+			key_bloom_without_local = non_dht_bloom;
+			
+			last_key_bloom_update = SystemTime.getMonotonousTime();
+		}
+	}
+	
+	private List<DownloadInfo>
+	getDHTInfos()
+	{
+		List<DHTPluginValue> vals = dht_plugin.getValues();
+				
+		Set<String>	unique_keys = new HashSet<String>();
+		
+		List<DownloadInfo>	dht_infos = new ArrayList<DownloadInfo>();
+		
+		for ( DHTPluginValue val: vals ){
+			
+			if ( !val.isLocal()){
+				
+				byte[]	bytes = val.getValue();
+				
+				String test = new String( bytes );
+				
+				if ( test.startsWith( "d1:d" ) && test.endsWith( "ee" ) && test.contains( "1:h20:")){
+							
+					try{
+						Map map = BDecoder.decode( bytes );
+					
+						DownloadInfo info =	manager.decodeInfo( map, null, 1, false, unique_keys );
+						
+						if ( info != null ){
+							
+							dht_infos.add( info );
+						}
+					}catch( Throwable e ){
+						
+					}
+				}
+			}
+		}
+		
+		return( dht_infos );
+	}
+	
+	private void
+	testKeyBloom()
+	{
+		if ( true ){
+			return;
+		}
+		
+		System.out.println( "test key bloom" );
+		
+		try{
+			Map<String,int[]>	all_words 		= new HashMap<String,int[]>();
+	
+			synchronized( manager.rcm_lock ){
+				
+				ContentCache cache = manager.loadRelatedContent();
+				
+				List<DownloadInfo>		dht_infos		= getDHTInfos();
+				
+				Iterator<DownloadInfo>	it_dht 			= dht_infos.iterator();
+							
+				Iterator<DownloadInfo>	it_transient 	= RelatedContentManager.transient_info_cache.values().iterator();
+				
+				Iterator<DownloadInfo>	it_rc 			= cache.related_content.values().iterator();			
+	
+				updateKeyBloom( cache );
+				
+				int	 i=0;
+				
+				for ( Iterator _it: new Iterator[]{ it_transient, it_rc, it_dht }){
+					
+					Iterator<DownloadInfo> it = (Iterator<DownloadInfo>)_it;
+					
+					while( it.hasNext()){
+					
+						DownloadInfo di = it.next();
+								
+						List<String>	words = getDHTWords( di );
+						
+						for ( String word: words ){
+									
+							int[] x = all_words.get( word );
+							
+							if ( x == null ){
+								
+								x = new int[3];
+								
+								all_words.put( word, x );
+							}
+							
+							x[i] = 1;
+						}
+					}
+					
+					i++;
+				}
+			}
+			
+			BloomFilter bloom = getKeyBloom( true );
+	
+			int	total 	= 0;
+			int	clashes	= 0;
+			int misses	= 0;
+			
+			int match_fails = 0;
+			
+			Random random = new Random();
+			
+			for ( Map.Entry<String,int[]> entry: all_words.entrySet()){
+				
+				String 	word 	= entry.getKey();
+				int[]	source 	= entry.getValue();
+				
+				boolean	r1 = bloom.contains( word.getBytes("UTF-8") );
+				boolean r2 = bloom.contains( (word + random.nextLong()).getBytes("UTF-8"));
+				
+				System.out.println( word + " -> " + r1 + "/" +r2 );
+				
+				total++;
+				if ( r1 && r2 ){
+					clashes++;
+				}
+				if ( !r1 ){
+					
+					misses++;
+				}
+				
+				List<RelatedContent> hits = matchContent( word );
+				
+				if ( hits.size() == 0 ){
+					
+					hits = matchContent( word );
+					match_fails++;
+				}
+			}
+			
+			System.out.println( "total=" + total + ", clash=" + clashes + ", miss=" + misses + ", fails=" + match_fails + ", bloom=" + bloom.getString() );
+			
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+		}
+	}
+	
+	private void
+	harvestBlooms()
+	{
+		harvest_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void
+				runSupport()
+				{
+					if ( harvest_dispatcher.getQueueSize() > 0 ){
+						
+						return;
+					}
+					
+					ForeignBloom oldest = null;
+					
+					synchronized( harvested_blooms ){
+						
+						for ( ForeignBloom bloom: harvested_blooms.values()){
+							
+							if ( 	oldest == null ||
+									bloom.getLastUpdateTime() < oldest.getLastUpdateTime()){
+								
+								oldest	= bloom;
+							}
+						}
+					}
+					
+					long now = SystemTime.getMonotonousTime();
+					
+					if ( oldest != null ){
+						
+						if ( now - oldest.getLastUpdateTime() > HARVEST_BLOOM_UPDATE_MILLIS ){
+							
+							DistributedDatabaseContact ddb_contact = oldest.getContact();
+
+							if ( 	now - oldest.getCreateTime() > HARVEST_BLOOM_DISCARD_MILLIS &&
+									harvested_blooms.size() >= HARVEST_MAX_BLOOMS / 2 ){
+							
+									// don't want to stick with a stable one for too long otherwise the stabler
+									// nodes will end up in lots of other nodes' harvest set and receive
+									// undue attention (unless we don't have that many nodes...)
+								
+								logSearch( "Harvest: discarding " + ddb_contact.getAddress());
+								
+								synchronized( harvested_blooms ){
+									
+									harvested_blooms.remove( ddb_contact.getID());
+								}
+							}else{
+
+								BloomFilter updated_filter = sendRemoteUpdate( oldest );
+								
+								if ( updated_filter == null ){
+																						
+									synchronized( harvested_blooms ){
+									
+										harvested_blooms.remove( ddb_contact.getID());
+									
+										harvested_fails.put( ddb_contact.getID(), "" );
+									}
+								}else{
+																	
+									oldest.updateFilter( updated_filter );
+								}
+							}
+						}
+					}
+					
+					if ( harvested_blooms.size() < HARVEST_MAX_BLOOMS ){
+					
+						try{
+							int	fail_count	= 0;
+							
+							DHTInterface[] dhts = dht_plugin.getDHTInterfaces();
+							
+outer:
+							for ( DHTInterface dht: dhts ){
+																
+								if ( dht.isIPV6()){
+									
+									continue;
+								}
+								
+								int	network = dht.getNetwork();
+								
+								if ( SEARCH_CVS_ONLY && network != DHT.NW_CVS ){
+									
+									logSearch( "Harvest: ignoring main DHT" );
+									
+									continue;
+								}
+													
+								DHTPluginContact[] contacts = dht.getReachableContacts();
+																
+								byte[] dht_id = dht.getID();
+								
+								for ( DHTPluginContact contact: contacts ){
+				
+									byte[]	contact_id = contact.getID();
+									
+									if ( Arrays.equals( dht_id, contact_id )){
+										
+										// logSearch( "not skipping local!!!!" );
+										
+										continue;
+									}
+									
+									DistributedDatabaseContact ddb_contact = importContact( contact, network );
+									
+									synchronized( harvested_blooms ){
+																				
+										if ( harvested_fails.containsKey( contact_id )){
+											
+											continue;
+										}
+
+										if ( harvested_blooms.containsKey( contact_id )){
+											
+											continue;
+										}
+									}
+									
+									BloomFilter filter = sendRemoteFetch( ddb_contact );
+									
+									logSearch( "harvest: " + contact.getString() + " -> " +(filter==null?"null":filter.getString()));
+
+									if ( filter != null ){
+										
+										synchronized( harvested_blooms ){
+										
+											harvested_blooms.put( contact_id, new ForeignBloom( ddb_contact, filter ));
+										}
+										
+										break outer;
+										
+									}else{
+										
+										synchronized( harvested_blooms ){
+										
+											harvested_fails.put( contact_id, "" );
+										}
+										
+										fail_count++;
+										
+										if ( fail_count > 5 ){
+											
+											break outer;
+										}
+									}
+								}
+							}
+						}catch( Throwable e ){
+							
+							e.printStackTrace();
+						}
+					}
+					
+					synchronized( harvested_blooms ){
+					
+						if ( harvested_fails.size() > HARVEST_MAX_FAILS_HISTORY ){
+						
+							harvested_fails.clear();
+						}
+					}
+				}
+			});
+	}
+	
+	private DistributedDatabaseContact
+	importContact(
+		DHTPluginContact		contact,
+		int						network )
+		
+		throws DistributedDatabaseException
+	{
+		InetSocketAddress address = contact.getAddress();
+		
+		if ( address.isUnresolved()){
+			
+			return( ddb.importContact( contact.exportToMap()));
+			
+		}else{
+		
+			return( ddb.importContact( address, DHTTransportUDP.PROTOCOL_VERSION_MIN, network==DHT.NW_CVS?DistributedDatabase.DHT_CVS:DistributedDatabase.DHT_MAIN ));
+		}
+	}
+	
+	private void
+	foreignBloomFailed(
+		DistributedDatabaseContact		contact )
+	{
+		byte[]	contact_id = contact.getID();
+		
+		synchronized( harvested_blooms ){
+			
+			if ( harvested_blooms.remove( contact_id ) != null ){
+			
+				harvested_fails.put( contact_id, "" );
+			}
+		}
+	}
+	
+	private List<DistributedDatabaseContact>
+	searchForeignBlooms(
+		String		term )
+	{
+		List<DistributedDatabaseContact>	result = new ArrayList<DistributedDatabaseContact>();
+		
+		try{
+			String[]	 bits = Constants.PAT_SPLIT_SPACE.split(term.toLowerCase());
+	
+				// note that we don't need to unescape tags in this process as tags are escaped when
+				// inserted into the blooms and include the 'tag:' prefix
+			
+			int[]			bit_types 		= new int[bits.length];
+			byte[][]		bit_bytes	 	= new byte[bit_types.length][];
+			byte[][][]		extras			= new byte[bit_types.length][][];
+			
+			for (int i=0;i<bits.length;i++){
+				
+				String bit = bits[i].trim();
+				
+				if ( bit.length() > 0 ){
+					
+					char	c = bit.charAt(0);
+					
+					if ( c == '+' ){
+						
+						bit_types[i] = 1;
+						
+						bit = bit.substring(1);
+						
+					}else if ( c == '-' ){
+						
+						bit_types[i] = 2;
+						
+						bit = bit.substring(1);
+					}
+					
+					if ( bit.startsWith( "(" ) && bit.endsWith((")"))){
+						
+						bit_types[i] = 3;	// ignore
+						
+					}else if ( bit.contains( "|" )){
+											
+						String[]	parts = bit.split( "\\|" );
+						
+						List<String>	p = new ArrayList<String>();
+						
+						for ( String part: parts ){
+							
+							part = part.trim();
+							
+							if ( part.length() > 0 ){
+								
+								p.add( part );
+							}
+						}
+						
+						if ( p.size() == 0 ){
+							
+							bit_types[i] = 3;
+							
+						}else{
+							
+							bit_types[i] = 4;
+	
+							extras[i] = new byte[p.size()][];
+							
+							for ( int j=0;j<p.size();j++){
+								
+								extras[i][j] = p.get(j).getBytes( "UTF8" );
+							}
+						}
+					}
+					
+					bit_bytes[i] = bit.getBytes( "UTF8" );
+				}
+			}
+			
+			synchronized( harvested_blooms ){
+				
+				for ( ForeignBloom fb: harvested_blooms.values()){
+					
+					BloomFilter filter = fb.getFilter();
+					
+					boolean	failed 	= false;
+					int		matches	= 0;
+					
+					for (int i=0;i<bit_bytes.length;i++){
+						
+						byte[]	bit = bit_bytes[i];
+						
+						if ( bit == null || bit.length == 0 ){
+							
+							continue;
+						}
+						
+						int	type = bit_types[i];
+						
+						if ( type == 3 ){
+							
+							continue;
+						}
+						
+						if ( type == 0 || type == 1 ){
+							
+							if ( filter.contains( bit )){
+								
+								matches++;
+								
+							}else{
+								
+								failed	= true;
+								
+								break;
+							}
+						}else if ( type == 2 ){
+						
+							if ( !filter.contains( bit )){
+								
+								matches++;
+								
+							}else{
+								
+								failed	= true;
+								
+								break;
+							}
+						}else if ( type == 4 ){
+							
+							byte[][]	parts = extras[i];
+							
+							int	old_matches = matches;
+							
+							for ( byte[] p: parts ){
+								
+								if ( filter.contains( p )){
+								
+									matches++;
+									
+									break;
+								}
+							}
+							
+							if ( matches == old_matches ){
+								
+								failed = true;
+								
+								break;
+							}
+						}
+					}
+					
+					if ( matches > 0 && !failed ){
+						
+						result.add( fb.getContact());
+					}
+				}
+			}
+		}catch( UnsupportedEncodingException e ){
+			
+			Debug.out( e );
+		}
+		
+		return( result );
+	}
+	
+	private static void
+	logSearch(
+		String		str )
+	{
+		if ( TRACE_SEARCH ){
+			System.out.println( str );
+		}
+	}
+	
+	private static class
+	MySearchObserver
+		implements SearchObserver
+	{
+		private SearchObserver		observer;
+		private AtomicInteger		num_results = new AtomicInteger();
+		
+		private
+		MySearchObserver(
+			SearchObserver		_observer )
+		{
+			observer = _observer;
+		}
+		
+		public void
+		resultReceived(
+			SearchInstance		search,
+			SearchResult		result )
+		{
+			observer.resultReceived( search, result );
+			
+			logSearch( "results=" + num_results.incrementAndGet());
+		}
+		
+		private int
+		getResultCount()
+		{
+			return( num_results.get());
+		}
+		
+		public void
+		complete()
+		{
+			observer.complete();
+		}
+		
+		public void
+		cancelled()
+		{
+			observer.cancelled();
+		}
+		
+		public Object
+		getProperty(
+			int		property )
+		{
+			return( observer.getProperty(property));
+		}
+	}
+	
+	private static class
+	ForeignBloom
+	{
+		private DistributedDatabaseContact	contact;
+		private BloomFilter					filter;
+		
+		private long						created;
+		private long						last_update;
+		
+		private
+		ForeignBloom(
+			DistributedDatabaseContact		_contact,
+			BloomFilter						_filter )
+		{
+			contact	= _contact;
+			filter	= _filter;
+			
+			created	 = SystemTime.getMonotonousTime();
+			
+			last_update	= created;
+		}
+		
+		public DistributedDatabaseContact
+		getContact()
+		{
+			return( contact );
+		}
+		
+		public BloomFilter
+		getFilter()
+		{
+			return( filter );
+		}
+		
+		public long
+		getCreateTime()
+		{
+			return( created );
+		}
+		
+		public long
+		getLastUpdateTime()
+		{
+			return( last_update );
+		}
+		
+		public void
+		updateFilter(
+			BloomFilter		f )
+		{
+			filter		= f;
+			last_update	= SystemTime.getMonotonousTime();
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoException.java b/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoException.java
index fe8bf7b..fee0318 100644
--- a/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoException.java
+++ b/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoException.java
@@ -1,35 +1,34 @@
-/*
- * Created on Apr 18, 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.core.crypto;
-
-public class 
-VuzeCryptoException 
-	extends Exception
-{
-	public
-	VuzeCryptoException(
-		String		str,
-		Throwable 	e )
-	{
-		super( str, e );
-	}
-}
+/*
+ * Created on Apr 18, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.crypto;
+
+public class 
+VuzeCryptoException 
+	extends Exception
+{
+	public
+	VuzeCryptoException(
+		String		str,
+		Throwable 	e )
+	{
+		super( str, e );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoListener.java b/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoListener.java
index 6cf6fd6..c62be6e 100644
--- a/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoListener.java
@@ -1,44 +1,43 @@
-/*
- * Created on Apr 18, 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.core.crypto;
-
-public interface 
-VuzeCryptoListener 
-{
-	public char[]
-	getSessionPassword(
-		String		reason )
-	
-		throws VuzeCryptoException;
-	
-	public void
-	sessionPasswordCorrect();
-	
-		/**
-		 * Indicates that the session password returned is incorrect. This is a bad state of 
-		 * affairs and the (probable) only solution is to generate a new public/private key
-		 * pair
-		 */
-	
-	public void
-	sessionPasswordIncorrect();
-}
+/*
+ * Created on Apr 18, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.crypto;
+
+public interface 
+VuzeCryptoListener 
+{
+	public char[]
+	getSessionPassword(
+		String		reason )
+	
+		throws VuzeCryptoException;
+	
+	public void
+	sessionPasswordCorrect();
+	
+		/**
+		 * Indicates that the session password returned is incorrect. This is a bad state of 
+		 * affairs and the (probable) only solution is to generate a new public/private key
+		 * pair
+		 */
+	
+	public void
+	sessionPasswordIncorrect();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoManager.java b/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoManager.java
index 599c737..6db1d12 100644
--- a/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/crypto/VuzeCryptoManager.java
@@ -1,328 +1,327 @@
-/*
- * Created on Apr 18, 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.core.crypto;
-
-
-import com.aelitis.azureus.core.security.*;
-
-
-public class 
-VuzeCryptoManager 
-{
-	private static VuzeCryptoManager	singleton;
-	
-	public static synchronized VuzeCryptoManager
-	getSingleton()
-	{
-		if ( singleton == null ){
-			
-			singleton = new VuzeCryptoManager();
-		}
-		
-		return( singleton );
-	}
-	
-	//private boolean			init_tried;
-	
-	private CryptoManager	crypt_man;
-	//private CopyOnWriteList	listeners = new CopyOnWriteList();
-	
-	//private volatile CryptoManagerPasswordHandler.passwordDetails	session_pw;
-	
-	protected
-	VuzeCryptoManager()
-	{
-		crypt_man = CryptoManagerFactory.getSingleton();
-		
-		/*
-		crypt_man.addPasswordHandler(
-			new CryptoManagerPasswordHandler()
-			{
-				private boolean	error_logged = !Constants.isCVSVersion();
-				
-				public int
-				getHandlerType()
-				{
-					return( HANDLER_TYPE_SYSTEM );
-				}
-				
-				public void 
-				passwordOK(
-					int 				handler_type,
-					passwordDetails 	details) 
-				{
-					Iterator it = listeners.iterator();
-					
-					while( it.hasNext()){
-
-						((VuzeCryptoListener)it.next()).sessionPasswordCorrect();
-					}
-				}
-				
-				public passwordDetails
-				getPassword(
-					int			handler_type,
-					int			action_type,
-					boolean		last_pw_incorrect,
-					String		reason )
-				{
-					if ( last_pw_incorrect ){
-						
-						Iterator it = listeners.iterator();
-						
-						while( it.hasNext()){
-
-							((VuzeCryptoListener)it.next()).sessionPasswordIncorrect();
-						}
-						
-						return( null );
-					}
-					
-					if ( session_pw != null ){
-						
-						return( session_pw );
-					}
-					
-					Iterator it = listeners.iterator();
-					
-					while( it.hasNext()){
-						
-						try{
-						
-							final char[] pw = ((VuzeCryptoListener)it.next()).getSessionPassword( reason );
-							
-							session_pw =
-								new passwordDetails()
-								{
-									public char[] 
-									getPassword() 
-									{
-										return( pw );
-									}
-									
-									public int 
-									getPersistForSeconds()
-									{
-										return( -1 );	// session 
-									}
-								};
-							
-							error_logged = false;
-								
-							return( session_pw );
-								
-						}catch (VuzeCryptoException ve) {
-
-							if ( !error_logged ){
-								
-								error_logged = true;
-								
-								Debug.out( "Listener failed " + ve.toString() + " on " + reason );
-								
-								if (ve.getCause() != null) {
-									Debug.out(ve.getCause());
-								}
-							}
-						}catch( Throwable e ){
-							
-							Debug.out( "Listener failed", e );
-						}
-					}
-					
-					if ( !error_logged ){
-						
-						error_logged = true;
-
-						Debug.out( "VuzeCryptoManager: no listeners returned session key" );
-					}
-					
-					return( null );
-				}
-			});
-		
-			// auto enable buddy plugin and system handler 
-		
-		boolean	init_done = COConfigurationManager.getBooleanParameter( "vuze.crypto.manager.initial.login.done", false );
-		
-		if ( !init_done ){
-		
-			AzureusCoreFactory.addCoreRunningListener(
-				new AzureusCoreRunningListener() {
-				
-  					public void 
-  					azureusCoreRunning(
-  							AzureusCore core) {
-  					{			
-  						initialise( core );
-  					}
-					}
-				});
-			
-		}
-		*/
-	}
-	
-	/*
-	protected void
-	initialise(
-		AzureusCore		core )
-	{
-		synchronized( this ){
-			
-			if ( init_tried ){
-				
-				return;
-			}
-			
-			init_tried = true;
-		}
-		
-		PluginInterface pi =  core.getPluginManager().getPluginInterfaceByID( "azbuddy" );
-		
-		if ( pi != null ){
-			
-			Plugin plugin = pi.getPlugin();
-			
-			if ( plugin instanceof BuddyPlugin ){
-				
-				BuddyPlugin buddy_plugin = (BuddyPlugin)plugin;
-				
-				if ( !buddy_plugin.isEnabled()){
-					
-					CryptoHandler handler = crypt_man.getECCHandler();
-					
-						// try and switch password handler if no keys yet defined
-					
-					if ( handler.peekPublicKey() == null ){
-						
-						try{
-							handler.setDefaultPasswordHandlerType(
-								CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM );
-						
-						}catch( Throwable e ){
-							
-							Debug.out( "CRYPTO: Failed to set default password handler type: " + Debug.getNestedExceptionMessage( e ));
-						}
-					}
-					
-					buddy_plugin.setEnabled( true );
-					
-					COConfigurationManager.setParameter( "vuze.crypto.manager.initial.login.done", true );
-					
-					COConfigurationManager.save();
-					
-					Debug.out( "CRYPTO: initialised buddy plugin and default handler type" );
-				}
-			}
-		}
-	}
-	*/
-		
-	public byte[]
-	getPlatformAZID()
-	{
-		return( crypt_man.getSecureID());
-	}
-
-	/*
-	public String
-	getPublicKey(
-		String		reason )
-	
-		throws VuzeCryptoException
-	{
-		try{
-			return( Base32.encode(crypt_man.getECCHandler().getPublicKey(reason)));
-			
-		}catch( Throwable e ){
-			
-			throw( new VuzeCryptoException( "Failed to access public key", e ));
-		}
-	}
-	
-	public boolean
-	hasPublicKey()
-	{
-		return crypt_man.getECCHandler().peekPublicKey() != null;
-	}
-		
-	public void
-	clearPassword()
-	{
-		session_pw	= null;
-	
-		crypt_man.clearPasswords( CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM );
-	}
-		 
-	public void
-	setPassword(
-		String		pw )
-	{
-		final char[]	pw_chars = pw.toCharArray();
-		
-		session_pw =
-			new CryptoManagerPasswordHandler.passwordDetails()
-			{
-				public char[] 
-				getPassword() 
-				{
-					return( pw_chars );
-				}
-				
-				public int 
-				getPersistForSeconds()
-				{
-					return( -1 );	// session 
-				}
-			};
-			
-		new AEThread2( "VuzeCryptoManager:testUnlock", true )
-		{
-			public void
-			run()
-			{
-				try{
-					crypt_man.getECCHandler().unlock();
-					
-				}catch( Throwable e ){
-					
-					Debug.out( "Password incorrect", e );
-				}
-			}
-		}.start();
-	}
-	
-	public void
-	addListener(
-		VuzeCryptoListener		listener )
-	{
-		listeners.add( listener );
-	}
-	
-	public void
-	removeListener(
-		VuzeCryptoListener		listener )
-	{
-		listeners.remove( listener );
-	}
-	*/
-}
+/*
+ * Created on Apr 18, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.crypto;
+
+
+import com.aelitis.azureus.core.security.*;
+
+
+public class 
+VuzeCryptoManager 
+{
+	private static VuzeCryptoManager	singleton;
+	
+	public static synchronized VuzeCryptoManager
+	getSingleton()
+	{
+		if ( singleton == null ){
+			
+			singleton = new VuzeCryptoManager();
+		}
+		
+		return( singleton );
+	}
+	
+	//private boolean			init_tried;
+	
+	private CryptoManager	crypt_man;
+	//private CopyOnWriteList	listeners = new CopyOnWriteList();
+	
+	//private volatile CryptoManagerPasswordHandler.passwordDetails	session_pw;
+	
+	protected
+	VuzeCryptoManager()
+	{
+		crypt_man = CryptoManagerFactory.getSingleton();
+		
+		/*
+		crypt_man.addPasswordHandler(
+			new CryptoManagerPasswordHandler()
+			{
+				private boolean	error_logged = !Constants.isCVSVersion();
+				
+				public int
+				getHandlerType()
+				{
+					return( HANDLER_TYPE_SYSTEM );
+				}
+				
+				public void 
+				passwordOK(
+					int 				handler_type,
+					passwordDetails 	details) 
+				{
+					Iterator it = listeners.iterator();
+					
+					while( it.hasNext()){
+
+						((VuzeCryptoListener)it.next()).sessionPasswordCorrect();
+					}
+				}
+				
+				public passwordDetails
+				getPassword(
+					int			handler_type,
+					int			action_type,
+					boolean		last_pw_incorrect,
+					String		reason )
+				{
+					if ( last_pw_incorrect ){
+						
+						Iterator it = listeners.iterator();
+						
+						while( it.hasNext()){
+
+							((VuzeCryptoListener)it.next()).sessionPasswordIncorrect();
+						}
+						
+						return( null );
+					}
+					
+					if ( session_pw != null ){
+						
+						return( session_pw );
+					}
+					
+					Iterator it = listeners.iterator();
+					
+					while( it.hasNext()){
+						
+						try{
+						
+							final char[] pw = ((VuzeCryptoListener)it.next()).getSessionPassword( reason );
+							
+							session_pw =
+								new passwordDetails()
+								{
+									public char[] 
+									getPassword() 
+									{
+										return( pw );
+									}
+									
+									public int 
+									getPersistForSeconds()
+									{
+										return( -1 );	// session 
+									}
+								};
+							
+							error_logged = false;
+								
+							return( session_pw );
+								
+						}catch (VuzeCryptoException ve) {
+
+							if ( !error_logged ){
+								
+								error_logged = true;
+								
+								Debug.out( "Listener failed " + ve.toString() + " on " + reason );
+								
+								if (ve.getCause() != null) {
+									Debug.out(ve.getCause());
+								}
+							}
+						}catch( Throwable e ){
+							
+							Debug.out( "Listener failed", e );
+						}
+					}
+					
+					if ( !error_logged ){
+						
+						error_logged = true;
+
+						Debug.out( "VuzeCryptoManager: no listeners returned session key" );
+					}
+					
+					return( null );
+				}
+			});
+		
+			// auto enable buddy plugin and system handler 
+		
+		boolean	init_done = COConfigurationManager.getBooleanParameter( "vuze.crypto.manager.initial.login.done", false );
+		
+		if ( !init_done ){
+		
+			AzureusCoreFactory.addCoreRunningListener(
+				new AzureusCoreRunningListener() {
+				
+  					public void 
+  					azureusCoreRunning(
+  							AzureusCore core) {
+  					{			
+  						initialise( core );
+  					}
+					}
+				});
+			
+		}
+		*/
+	}
+	
+	/*
+	protected void
+	initialise(
+		AzureusCore		core )
+	{
+		synchronized( this ){
+			
+			if ( init_tried ){
+				
+				return;
+			}
+			
+			init_tried = true;
+		}
+		
+		PluginInterface pi =  core.getPluginManager().getPluginInterfaceByID( "azbuddy" );
+		
+		if ( pi != null ){
+			
+			Plugin plugin = pi.getPlugin();
+			
+			if ( plugin instanceof BuddyPlugin ){
+				
+				BuddyPlugin buddy_plugin = (BuddyPlugin)plugin;
+				
+				if ( !buddy_plugin.isEnabled()){
+					
+					CryptoHandler handler = crypt_man.getECCHandler();
+					
+						// try and switch password handler if no keys yet defined
+					
+					if ( handler.peekPublicKey() == null ){
+						
+						try{
+							handler.setDefaultPasswordHandlerType(
+								CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM );
+						
+						}catch( Throwable e ){
+							
+							Debug.out( "CRYPTO: Failed to set default password handler type: " + Debug.getNestedExceptionMessage( e ));
+						}
+					}
+					
+					buddy_plugin.setEnabled( true );
+					
+					COConfigurationManager.setParameter( "vuze.crypto.manager.initial.login.done", true );
+					
+					COConfigurationManager.save();
+					
+					Debug.out( "CRYPTO: initialised buddy plugin and default handler type" );
+				}
+			}
+		}
+	}
+	*/
+		
+	public byte[]
+	getPlatformAZID()
+	{
+		return( crypt_man.getSecureID());
+	}
+
+	/*
+	public String
+	getPublicKey(
+		String		reason )
+	
+		throws VuzeCryptoException
+	{
+		try{
+			return( Base32.encode(crypt_man.getECCHandler().getPublicKey(reason)));
+			
+		}catch( Throwable e ){
+			
+			throw( new VuzeCryptoException( "Failed to access public key", e ));
+		}
+	}
+	
+	public boolean
+	hasPublicKey()
+	{
+		return crypt_man.getECCHandler().peekPublicKey() != null;
+	}
+		
+	public void
+	clearPassword()
+	{
+		session_pw	= null;
+	
+		crypt_man.clearPasswords( CryptoManagerPasswordHandler.HANDLER_TYPE_SYSTEM );
+	}
+		 
+	public void
+	setPassword(
+		String		pw )
+	{
+		final char[]	pw_chars = pw.toCharArray();
+		
+		session_pw =
+			new CryptoManagerPasswordHandler.passwordDetails()
+			{
+				public char[] 
+				getPassword() 
+				{
+					return( pw_chars );
+				}
+				
+				public int 
+				getPersistForSeconds()
+				{
+					return( -1 );	// session 
+				}
+			};
+			
+		new AEThread2( "VuzeCryptoManager:testUnlock", true )
+		{
+			public void
+			run()
+			{
+				try{
+					crypt_man.getECCHandler().unlock();
+					
+				}catch( Throwable e ){
+					
+					Debug.out( "Password incorrect", e );
+				}
+			}
+		}.start();
+	}
+	
+	public void
+	addListener(
+		VuzeCryptoListener		listener )
+	{
+		listeners.add( listener );
+	}
+	
+	public void
+	removeListener(
+		VuzeCryptoListener		listener )
+	{
+		listeners.remove( listener );
+	}
+	*/
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/Device.java b/azureus3/src/com/aelitis/azureus/core/devices/Device.java
index 8a4a021..53f65ce 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/Device.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/Device.java
@@ -1,194 +1,193 @@
-/*
- * 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;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.URL;
-
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-
-public interface 
-Device 
-{
-	public static final int DT_UNKNOWN				= 0;
-	public static final int DT_INTERNET_GATEWAY		= 1;
-	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();
-	
-	public String
-	getID();
-	
-	public String
-	getName();
-	
-	public void
-	setName(
-		String		name,
-		boolean isAutomaticName);
-	
-	public String
-	getClassification();
-		
-	public String
-	getShortDescription();
-	
-	public void
-	alive();
-	
-	public boolean
-	isAlive();
-	
-	public boolean
-	isLivenessDetectable();
-	
-	public boolean
-	isBusy();
-	
-	public boolean
-	isManual();
-	
-	public void
-	setHidden(
-		boolean		is_hidden );
-	
-	public boolean
-	isHidden();
-	
-	public void
-	setTagged(
-		boolean	is_tagged );
-	
-	public boolean 
-	isTagged();
-	
-	public boolean
-	isBrowsable();
-	
-	public browseLocation[]
-	getBrowseLocations();
-		
-	public InetAddress
-	getAddress();
-	
-	public void
-	setAddress(
-		InetAddress	address );
-	
-	public void
-	setTransientProperty(
-		Object		key,
-		Object		value );
-	
-	public Object
-	getTransientProperty(
-		Object		key );
-	
-		/**
-		 * Array of resource strings and their associated values
-		 * @return
-		 */
-	
-	public String[][]
-	getDisplayProperties();
-	
-	public void
-	requestAttention();
-	
-	public void
-	remove();
-	
-	public void
-	setCanRemove(
-		boolean	can );
-	
-	public boolean
-	canRemove();
-	
-	public String
-	getInfo();
-	
-	public String
-	getError();
-	
-	public String
-	getStatus();
-	
-	public void
-	addListener(
-		DeviceListener		listener );
-	
-	public void
-	removeListener(
-		DeviceListener		listener );
-	
-	public String
-	getString();
-	
-	interface
-	browseLocation
-	{
-		public String
-		getName();
-		
-		public URL
-		getURL();
-	}
-
-	public boolean 
-	isGenericUSB();
-	
-	public void
-	setGenericUSB(boolean b);
-	
-	public String
-	getImageID();
-	
-	public void
-	setImageID(String id);
-
-	public boolean
-	isNameAutomatic();
-	
-	public void
-	setExportable(
-		boolean		b );
-	
-	public boolean
-	isExportable();
-	
-	public URL
-	getWikiURL();
-	
-	public VuzeFile
-	getVuzeFile()
-	
-		throws IOException;
-
-	public TranscodeProfile[] 
-	getDirectTranscodeProfiles();
-}
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.URL;
+
+import com.aelitis.azureus.core.vuzefile.VuzeFile;
+
+public interface 
+Device 
+{
+	public static final int DT_UNKNOWN				= 0;
+	public static final int DT_INTERNET_GATEWAY		= 1;
+	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();
+	
+	public String
+	getID();
+	
+	public String
+	getName();
+	
+	public void
+	setName(
+		String		name,
+		boolean isAutomaticName);
+	
+	public String
+	getClassification();
+		
+	public String
+	getShortDescription();
+	
+	public void
+	alive();
+	
+	public boolean
+	isAlive();
+	
+	public boolean
+	isLivenessDetectable();
+	
+	public boolean
+	isBusy();
+	
+	public boolean
+	isManual();
+	
+	public void
+	setHidden(
+		boolean		is_hidden );
+	
+	public boolean
+	isHidden();
+	
+	public void
+	setTagged(
+		boolean	is_tagged );
+	
+	public boolean 
+	isTagged();
+	
+	public boolean
+	isBrowsable();
+	
+	public browseLocation[]
+	getBrowseLocations();
+		
+	public InetAddress
+	getAddress();
+	
+	public void
+	setAddress(
+		InetAddress	address );
+	
+	public void
+	setTransientProperty(
+		Object		key,
+		Object		value );
+	
+	public Object
+	getTransientProperty(
+		Object		key );
+	
+		/**
+		 * Array of resource strings and their associated values
+		 * @return
+		 */
+	
+	public String[][]
+	getDisplayProperties();
+	
+	public void
+	requestAttention();
+	
+	public void
+	remove();
+	
+	public void
+	setCanRemove(
+		boolean	can );
+	
+	public boolean
+	canRemove();
+	
+	public String
+	getInfo();
+	
+	public String
+	getError();
+	
+	public String
+	getStatus();
+	
+	public void
+	addListener(
+		DeviceListener		listener );
+	
+	public void
+	removeListener(
+		DeviceListener		listener );
+	
+	public String
+	getString();
+	
+	interface
+	browseLocation
+	{
+		public String
+		getName();
+		
+		public URL
+		getURL();
+	}
+
+	public boolean 
+	isGenericUSB();
+	
+	public void
+	setGenericUSB(boolean b);
+	
+	public String
+	getImageID();
+	
+	public void
+	setImageID(String id);
+
+	public boolean
+	isNameAutomatic();
+	
+	public void
+	setExportable(
+		boolean		b );
+	
+	public boolean
+	isExportable();
+	
+	public URL
+	getWikiURL();
+	
+	public VuzeFile
+	getVuzeFile()
+	
+		throws IOException;
+
+	public TranscodeProfile[] 
+	getDirectTranscodeProfiles();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceContentDirectory.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceContentDirectory.java
index 6d6fcf9..81dd108 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceContentDirectory.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceContentDirectory.java
@@ -1,37 +1,36 @@
-/*
- * 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;
-
-import java.net.URL;
-import java.util.List;
-
-public interface 
-DeviceContentDirectory
-	extends Device
-{
-	public List<URL>
-	getControlURLs();
-	
-	public void
-	setPreferredControlURL(
-		URL		url );
-}
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+import java.net.URL;
+import java.util.List;
+
+public interface 
+DeviceContentDirectory
+	extends Device
+{
+	public List<URL>
+	getControlURLs();
+	
+	public void
+	setPreferredControlURL(
+		URL		url );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceInternetGateway.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceInternetGateway.java
index 10b13cb..dd5496d 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceInternetGateway.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceInternetGateway.java
@@ -1,29 +1,28 @@
-/*
- * 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;
-
-public interface 
-DeviceInternetGateway
-	extends Device
-{
-
-}
+/*
+ * Created on Jan 28, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+DeviceInternetGateway
+	extends Device
+{
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceListener.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceListener.java
index cc031f1..69e74b3 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceListener.java
@@ -1,30 +1,29 @@
-/*
- * 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 );
-}
+/*
+ * Created on Sep 2, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+DeviceListener 
+{
+	public void
+	deviceChanged(
+		Device		device );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceManager.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceManager.java
index f9fd7f8..6f2433a 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceManager.java
@@ -1,165 +1,176 @@
-/*
- * 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;
-
-import java.io.File;
-import java.net.InetAddress;
-
-public interface 
-DeviceManager 
-{
-		// not the best place for these, but it'll do for the moment
-	
-	public static final String CONFIG_VIEW_HIDE_REND_GENERIC	= "device.sidebar.ui.rend.hidegeneric";
-	public static final String CONFIG_VIEW_SHOW_ONLY_TAGGED		= "device.sidebar.ui.rend.showonlytagged";
-	
-	public DeviceTemplate[]
-	getDeviceTemplates(
-		int		device_type );
-	
-	public DeviceManufacturer[]
-	getDeviceManufacturers(
-		int		device_type );
-	
-	public Device[]
-	getDevices();
-	
-	public Device
-	addVirtualDevice(
-		int					type,
-		String				uid,
-		String				classification,
-		String				name )
-	
-		throws DeviceManagerException;
-	
-	Device addInetDevice(
-		int					type, 
-		String					uid, 
-		String					classification,
-		String					name,
-		InetAddress					address )
-
-		throws DeviceManagerException;
-
-	public void
-	search(
-		int						max_millis,
-		DeviceSearchListener	listener );
-	
-	public boolean
-	getAutoSearch();
-	
-	public void
-	setAutoSearch(
-		boolean	auto );
-	
-	public int
-	getAutoHideOldDevicesDays();
-	
-	public void
-	setAutoHideOldDevicesDays(
-		int		days );
-	
-	public boolean
-	isRSSPublishEnabled();
-	
-	public void
-	setRSSPublishEnabled(
-		boolean		enabled );
-
-	public String
-	getRSSLink();
-	
-	public UnassociatedDevice[]
-	getUnassociatedDevices();
-	
-	public TranscodeManager
-	getTranscodeManager();
-	
-	public File
-	getDefaultWorkingDirectory();
-	
-	public void
-	setDefaultWorkingDirectory(
-		File		dir );
-	
-	public boolean
-	isBusy(
-		int	device_type );
-	
-	public DeviceOfflineDownloaderManager
-	getOfflineDownlaoderManager();
-	
-	public boolean
-	isTiVoEnabled();
-	
-	public void
-	setTiVoEnabled(
-		boolean	enabled );
-	
-	public boolean
-	getDisableSleep();
-	
-	public void
-	setDisableSleep(
-		boolean		b );
-	
-	public String
-	getLocalServiceName();
-	
-	public void
-	addDiscoveryListener(
-		DeviceManagerDiscoveryListener	listener );
-	
-	public void
-	removeDiscoveryListener(
-		DeviceManagerDiscoveryListener	listener );
-	
-	public void
-	addListener(
-		DeviceManagerListener		listener );
-	
-	public void
-	removeListener(
-		DeviceManagerListener		listener );
-	
-	public interface 
-	UnassociatedDevice
-	{
-		public InetAddress
-		getAddress();
-		
-		public String
-		getDescription();
-	}
-	
-	public interface
-	DeviceManufacturer
-	{
-		public String
-		getName();
-		
-		public DeviceTemplate[]
-		getDeviceTemplates();
-	}
-}
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+import java.io.File;
+import java.net.InetAddress;
+
+import com.aelitis.net.upnp.UPnPDevice;
+
+public interface 
+DeviceManager 
+{
+		// not the best place for these, but it'll do for the moment
+	
+	public static final String CONFIG_VIEW_HIDE_REND_GENERIC	= "device.sidebar.ui.rend.hidegeneric";
+	public static final String CONFIG_VIEW_SHOW_ONLY_TAGGED		= "device.sidebar.ui.rend.showonlytagged";
+	
+	public DeviceTemplate[]
+	getDeviceTemplates(
+		int		device_type );
+	
+	public DeviceManufacturer[]
+	getDeviceManufacturers(
+		int		device_type );
+	
+	public Device[]
+	getDevices();
+	
+	public Device
+	addVirtualDevice(
+		int					type,
+		String				uid,
+		String				classification,
+		String				name )
+	
+		throws DeviceManagerException;
+	
+	Device addInetDevice(
+		int					type, 
+		String					uid, 
+		String					classification,
+		String					name,
+		InetAddress					address )
+
+		throws DeviceManagerException;
+
+	public void
+	search(
+		int						max_millis,
+		DeviceSearchListener	listener );
+	
+	public boolean
+	getAutoSearch();
+	
+	public void
+	setAutoSearch(
+		boolean	auto );
+	
+	public int
+	getAutoHideOldDevicesDays();
+	
+	public void
+	setAutoHideOldDevicesDays(
+		int		days );
+	
+	public boolean
+	isRSSPublishEnabled();
+	
+	public void
+	setRSSPublishEnabled(
+		boolean		enabled );
+
+	public String
+	getRSSLink();
+	
+	public UnassociatedDevice[]
+	getUnassociatedDevices();
+	
+	public TranscodeManager
+	getTranscodeManager();
+	
+	public File
+	getDefaultWorkingDirectory();
+	
+	public void
+	setDefaultWorkingDirectory(
+		File		dir );
+	
+	public boolean
+	isBusy(
+		int	device_type );
+	
+	public DeviceOfflineDownloaderManager
+	getOfflineDownlaoderManager();
+	
+	public boolean
+	isTiVoEnabled();
+	
+	public void
+	setTiVoEnabled(
+		boolean	enabled );
+	
+	public boolean
+	getDisableSleep();
+	
+	public void
+	setDisableSleep(
+		boolean		b );
+	
+	public String
+	getLocalServiceName();
+	
+	public void
+	addDiscoveryListener(
+		DeviceManagerDiscoveryListener	listener );
+	
+	public void
+	removeDiscoveryListener(
+		DeviceManagerDiscoveryListener	listener );
+	
+	public void
+	addListener(
+		DeviceManagerListener		listener );
+	
+	public void
+	removeListener(
+		DeviceManagerListener		listener );
+	
+	public interface 
+	UnassociatedDevice
+	{
+		public InetAddress
+		getAddress();
+		
+		public String
+		getDescription();
+	}
+	
+	public interface
+	DeviceManufacturer
+	{
+		public String
+		getName();
+		
+		public DeviceTemplate[]
+		getDeviceTemplates();
+	}
+
+	/**
+	 * @param upnpDevice
+	 * @return
+	 *
+	 * @since 5.0.0.1
+	 */
+	Device
+	findDevice(
+			UPnPDevice upnpDevice);
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerDiscoveryListener.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerDiscoveryListener.java
index c6264a3..cf40f3a 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerDiscoveryListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerDiscoveryListener.java
@@ -2,20 +2,19 @@
  * Created on Oct 23, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerException.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerException.java
index 8951b55..45b6cb9 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerException.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerException.java
@@ -1,44 +1,43 @@
-/*
- * Created on Feb 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;
-
- at SuppressWarnings("serial")
-
-public class 
-DeviceManagerException
-	extends Exception
-{
-	public 
-	DeviceManagerException(
-		String		str )
-	{
-		super( str );
-	}
-	
-	public 
-	DeviceManagerException(
-		String		str,
-		Throwable 	e )
-	{
-		super( str, e );
-	}
-}
+/*
+ * Created on Feb 2, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+ at SuppressWarnings("serial")
+
+public class 
+DeviceManagerException
+	extends Exception
+{
+	public 
+	DeviceManagerException(
+		String		str )
+	{
+		super( str );
+	}
+	
+	public 
+	DeviceManagerException(
+		String		str,
+		Throwable 	e )
+	{
+		super( str, e );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerFactory.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerFactory.java
index 285681e..04eb61e 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerFactory.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerFactory.java
@@ -1,95 +1,108 @@
-/*
- * 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;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-
-public class 
-DeviceManagerFactory 
-{
-	final private static Class<DeviceManager> impl_class; 
-
-	static{
-		
-		String impl = System.getProperty( "az.factory.devicemanager.impl", "com.aelitis.azureus.core.devices.impl.DeviceManagerImpl" );
-		
-		Class<DeviceManager> temp = null;
-		
-		if ( impl.length() > 0 ){
-			
-			try{
-				temp = (Class<DeviceManager>)DeviceManagerFactory.class.getClassLoader().loadClass( impl );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( "Failed to load DeviceManagerFactory class: " + impl );
-			}
-		}
-		
-		impl_class = temp;
-	}
-
-	private static DeviceManager	singleton;
-	
-	public static void
-	preInitialise()
-	{		
-		if ( impl_class != null ){
-			
-			try{
-				impl_class.getMethod( "preInitialise" ).invoke( null, (Object[])null );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( "preInitialise failed", e );
-			}
-		}
-	}
-	
-	public static DeviceManager
-	getSingleton()
-	{
-		synchronized( DeviceManagerFactory.class ){
-			
-			if ( singleton != null ){
-				
-				return( singleton );
-			}
-		
-			if ( impl_class == null ){
-				
-				throw( new RuntimeException( "No Implementation" ));
-			}
-			
-			try{
-				singleton = (DeviceManager)impl_class.getMethod( "getSingleton" ).invoke( null, (Object[])null );
-			
-				return( singleton );
-				
-			}catch( Throwable e ){
-				
-				throw( new RuntimeException( "No Implementation", e ));
-			}
-		}
-	}
-}
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.util.Debug;
+
+
+public class 
+DeviceManagerFactory 
+{
+	final private static Class<DeviceManager> impl_class; 
+
+	static{
+		
+		String impl = System.getProperty( "az.factory.devicemanager.impl", "com.aelitis.azureus.core.devices.impl.DeviceManagerImpl" );
+		
+		Class<DeviceManager> temp = null;
+		
+		if ( impl.length() > 0 ){
+			
+			try{
+				temp = (Class<DeviceManager>)DeviceManagerFactory.class.getClassLoader().loadClass( impl );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( "Failed to load DeviceManagerFactory class: " + impl );
+			}
+		}
+		
+		impl_class = temp;
+	}
+
+	private static DeviceManager	singleton;
+	
+	public static void
+	preInitialise()
+	{		
+		if ( impl_class != null ){
+			
+			try{
+				impl_class.getMethod( "preInitialise" ).invoke( null, (Object[])null );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( "preInitialise failed", e );
+			}
+		}
+	}
+		
+	public static DeviceManager
+	getSingleton()
+	{
+		synchronized( DeviceManagerFactory.class ){
+			
+			if ( singleton != null ){
+				
+				return( singleton );
+			}
+		
+			if ( impl_class == null ){
+				
+				throw( new RuntimeException( "No Implementation" ));
+			}
+			
+			boolean isAZ3 = COConfigurationManager.getStringParameter("ui").equals("az3");
+			
+			if ( !isAZ3 ){
+				
+					// musn't instantiate the device manager for console UI as this has unwanted side effects
+					// such as enabling per-device content browse controls that end up hiding content but the
+					// user has no way of changing this!
+									
+				Debug.out( "DeviceManager is only fully functional with Vuze UI - some features unavailable" );
+				
+				return( null );
+			}
+			
+			try{
+				singleton = (DeviceManager)impl_class.getMethod( "getSingleton" ).invoke( null, (Object[])null );
+			
+				return( singleton );
+				
+			}catch( Throwable e ){
+				
+				throw( new RuntimeException( "No Implementation", e ));
+			}
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerListener.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerListener.java
index 0ff6a27..f68df49 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceManagerListener.java
@@ -1,45 +1,44 @@
-/*
- * 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 
-DeviceManagerListener 
-{
-	public void
-	deviceAdded(
-		Device		device );
-	
-	public void
-	deviceChanged(
-		Device		device );
-	
-	public void
-	deviceAttentionRequest(
-		Device		device );
-	
-	public void
-	deviceRemoved(
-		Device		device );
-
-	public void
-	deviceManagerLoaded();
-}
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+DeviceManagerListener 
+{
+	public void
+	deviceAdded(
+		Device		device );
+	
+	public void
+	deviceChanged(
+		Device		device );
+	
+	public void
+	deviceAttentionRequest(
+		Device		device );
+	
+	public void
+	deviceRemoved(
+		Device		device );
+
+	public void
+	deviceManagerLoaded();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceMediaRenderer.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceMediaRenderer.java
index 2dcc3d0..38e9bb8 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceMediaRenderer.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceMediaRenderer.java
@@ -1,153 +1,159 @@
-/*
- * 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;
-
-import java.io.File;
-import java.net.InetAddress;
-
-import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice;
-
-
-public interface 
-DeviceMediaRenderer
-	extends Device, TranscodeTarget
-{	
-	public static final int RS_PS3		= 1;
-	public static final int RS_XBOX		= 2;
-	public static final int RS_ITUNES	= 3;
-	public static final int RS_WII		= 4;
-	public static final int RS_BROWSER	= 5;
-	public static final int RS_OTHER	= 6;
-
-		/**
-		 * THIS WILL CHANGE!!!
-		 * @return	RS_<x>
-		 */
-
-	public int
-	getRendererSpecies();
-
-	public boolean
-	canFilterFilesView();
-	
-	public void
-	setFilterFilesView(
-		boolean	filter );
-	
-	public boolean
-	getFilterFilesView();
-	
-		// copy to device
-	
-	public boolean
-	canCopyToDevice();
-	
-	public boolean
-	getAutoCopyToDevice();
-		
-	public void
-	setAutoCopyToDevice(
-		boolean		auto );
-	
-	public int
-	getCopyToDevicePending();
-	
-	public boolean
-	canAutoStartDevice();
-	
-	public boolean
-	getAutoStartDevice();
-	
-	public void
-	setAutoStartDevice(
-		boolean		auto );
-	
-		// copy to folder
-	
-	public boolean
-	canCopyToFolder();
-	
-	public void
-	setCanCopyToFolder(
-		boolean		can );
-	
-	public File
-	getCopyToFolder();
-	
-	public void
-	setCopyToFolder(
-		File		file );
-	
-	public int
-	getCopyToFolderPending();
-	
-	public boolean
-	getAutoCopyToFolder();
-		
-	public void
-	setAutoCopyToFolder(
-		boolean		auto );
-	
-	public void
-	manualCopy()
-	
-		throws DeviceManagerException;
-	
-		// associate
-	
-	public boolean
-	canAssociate();
-	
-	public void
-	associate(
-		UnassociatedDevice	assoc );
-	
-	public boolean
-	canShowCategories();
-	
-	public void
-	setShowCategories(
-		boolean	b );
-	
-	public boolean
-	getShowCategories();
-	
-	public boolean
-	isRSSPublishEnabled();
-	
-	public void
-	setRSSPublishEnabled(
-		boolean		enabled );
-	
-	public InetAddress
-	getAddress();
-	
-	public boolean
-	canRestrictAccess();
-	
-	public String
-	getAccessRestriction();
-	
-	public void
-	setAccessRestriction(
-		String		str );
-}
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+import java.io.File;
+import java.net.InetAddress;
+
+import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice;
+
+
+public interface 
+DeviceMediaRenderer
+	extends Device, TranscodeTarget
+{	
+	public static final int RS_PS3		= 1;
+	public static final int RS_XBOX		= 2;
+	public static final int RS_ITUNES	= 3;
+	public static final int RS_WII		= 4;
+	public static final int RS_BROWSER	= 5;
+	public static final int RS_OTHER	= 6;
+
+		/**
+		 * THIS WILL CHANGE!!!
+		 * @return	RS_<x>
+		 */
+
+	public int
+	getRendererSpecies();
+
+	public boolean
+	canFilterFilesView();
+	
+	public void
+	setFilterFilesView(
+		boolean	filter );
+	
+	public boolean
+	getFilterFilesView();
+	
+		// copy to device
+	
+	public boolean
+	canCopyToDevice();
+	
+	public boolean
+	getAutoCopyToDevice();
+		
+	public void
+	setAutoCopyToDevice(
+		boolean		auto );
+	
+	public int
+	getCopyToDevicePending();
+	
+	public boolean
+	canAutoStartDevice();
+	
+	public boolean
+	getAutoStartDevice();
+	
+	public void
+	setAutoStartDevice(
+		boolean		auto );
+	
+		// copy to folder
+	
+	public boolean
+	canCopyToFolder();
+	
+	public void
+	setCanCopyToFolder(
+		boolean		can );
+	
+	public File
+	getCopyToFolder();
+	
+	public void
+	setCopyToFolder(
+		File		file );
+	
+	public int
+	getCopyToFolderPending();
+	
+	public boolean
+	getAutoCopyToFolder();
+		
+	public void
+	setAutoCopyToFolder(
+		boolean		auto );
+	
+	public void
+	manualCopy()
+	
+		throws DeviceManagerException;
+	
+		// associate
+	
+	public boolean
+	canAssociate();
+	
+	public void
+	associate(
+		UnassociatedDevice	assoc );
+	
+	public boolean
+	canShowCategories();
+	
+	public void
+	setShowCategories(
+		boolean	b );
+	
+	public boolean
+	getShowCategories();
+	
+	public boolean
+	isRSSPublishEnabled();
+	
+	public void
+	setRSSPublishEnabled(
+		boolean		enabled );
+	
+	public long
+	getAutoShareToTagID();
+	
+	public void
+	setAutoShareToTagID(
+		long		id );
+	
+	public InetAddress
+	getAddress();
+	
+	public boolean
+	canRestrictAccess();
+	
+	public String
+	getAccessRestriction();
+	
+	public void
+	setAccessRestriction(
+		String		str );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceMediaRendererTemplate.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceMediaRendererTemplate.java
index 8a87dd0..f514ae5 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceMediaRendererTemplate.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceMediaRendererTemplate.java
@@ -1,33 +1,32 @@
-/*
- * Created on Jul 10, 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 
-DeviceMediaRendererTemplate
-	extends DeviceTemplate
-{
-	public int
-	getRendererSpecies();
-	
-	public TranscodeProfile[]
-	getProfiles();
-}
+/*
+ * Created on Jul 10, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+DeviceMediaRendererTemplate
+	extends DeviceTemplate
+{
+	public int
+	getRendererSpecies();
+	
+	public TranscodeProfile[]
+	getProfiles();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownload.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownload.java
index f50b1d4..28b6804 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownload.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownload.java
@@ -1,40 +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;
-
-import org.gudy.azureus2.plugins.download.Download;
-
-public interface 
-DeviceOfflineDownload 
-{
-	public Download
-	getDownload();
-	
-	public boolean
-	isTransfering();
-	
-	public long
-	getCurrentTransferSize();
-	
-	public long
-	getRemaining();
-}
+/*
+ * Created on Sep 1, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.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/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloader.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloader.java
index ae64da0..1503cab 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloader.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloader.java
@@ -1,63 +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(
-		boolean		force )
-	
-		throws DeviceManagerException;
-	
-	public int
-	getTransferingCount();
-
-	public DeviceOfflineDownload[]
-	getDownloads();
-		
-	public void
-	addListener(
-		DeviceOfflineDownloaderListener		listener );
-	
-	public void
-	removeListener(
-		DeviceOfflineDownloaderListener		listener );
-}
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.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(
+		boolean		force )
+	
+		throws DeviceManagerException;
+	
+	public int
+	getTransferingCount();
+
+	public DeviceOfflineDownload[]
+	getDownloads();
+		
+	public void
+	addListener(
+		DeviceOfflineDownloaderListener		listener );
+	
+	public void
+	removeListener(
+		DeviceOfflineDownloaderListener		listener );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderListener.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderListener.java
index 7224221..8f92f59 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderListener.java
@@ -1,39 +1,38 @@
-/*
- * 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 );
-	
-}
+/*
+ * Created on Sep 1, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+DeviceOfflineDownloaderListener 
+{
+	public void
+	downloadAdded(
+		DeviceOfflineDownload	download );
+	
+	public void
+	downloadChanged(
+		DeviceOfflineDownload	download );
+	
+	public void
+	downloadRemoved(
+		DeviceOfflineDownload	download );
+	
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderManager.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderManager.java
index 8673aa7..cb634f8 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceOfflineDownloaderManager.java
@@ -1,61 +1,60 @@
-/*
- * 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 );
-}
+/*
+ * Created on Sep 1, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.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/azureus3/src/com/aelitis/azureus/core/devices/DeviceSearchListener.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceSearchListener.java
index 91b5402..d29077c 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceSearchListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceSearchListener.java
@@ -1,33 +1,32 @@
-/*
- * Created on Feb 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 
-DeviceSearchListener 
-{
-	public void
-	deviceFound(
-		Device 	device );
-	
-	public void
-	complete();
-}
+/*
+ * Created on Feb 2, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+DeviceSearchListener 
+{
+	public void
+	deviceFound(
+		Device 	device );
+	
+	public void
+	complete();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceTemplate.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceTemplate.java
index d3ccad9..67c68ee 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/DeviceTemplate.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceTemplate.java
@@ -1,65 +1,64 @@
-/*
- * Created on Jul 10, 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 
-DeviceTemplate 
-{
-	public int
-	getType();
-	
-	public String
-	getName();
-	
-	public String
-	getManufacturer();
-	
-	public String
-	getClassification();
-	
-	public String
-	getShortDescription();
-	
-	public boolean
-	isAuto();
-	
-		/**
-		 * auto devices can't be manually created
-		 * @param name
-		 * @return
-		 * @throws DeviceManagerException
-		 */
-	
-	public Device
-	createInstance(
-		String		name )
-	
-		throws DeviceManagerException;
-	
-	public Device
-	createInstance(
-		String		name,
-		String		uid,
-		boolean		manual )
-	
-		throws DeviceManagerException;
-}
+/*
+ * Created on Jul 10, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+DeviceTemplate 
+{
+	public int
+	getType();
+	
+	public String
+	getName();
+	
+	public String
+	getManufacturer();
+	
+	public String
+	getClassification();
+	
+	public String
+	getShortDescription();
+	
+	public boolean
+	isAuto();
+	
+		/**
+		 * auto devices can't be manually created
+		 * @param name
+		 * @return
+		 * @throws DeviceManagerException
+		 */
+	
+	public Device
+	createInstance(
+		String		name )
+	
+		throws DeviceManagerException;
+	
+	public Device
+	createInstance(
+		String		name,
+		String		uid,
+		boolean		manual )
+	
+		throws DeviceManagerException;
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/DeviceUPnP.java b/azureus3/src/com/aelitis/azureus/core/devices/DeviceUPnP.java
new file mode 100644
index 0000000..d98c6b9
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/core/devices/DeviceUPnP.java
@@ -0,0 +1,33 @@
+/*
+ * Created on Mar 6, 2015
+ * Created by Paul Gardner
+ * 
+ * Copyright 2015 Azureus Software, 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.core.devices;
+
+import com.aelitis.net.upnp.UPnPDevice;
+
+public interface 
+DeviceUPnP
+	extends Device
+{
+	public UPnPDevice
+	getUPnPDevice();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeActionVetoException.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeActionVetoException.java
index 3cec38c..2e51c0b 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeActionVetoException.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeActionVetoException.java
@@ -1,34 +1,33 @@
-/*
- * Created on Mar 16, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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 class 
-TranscodeActionVetoException
-	extends Exception
-{
-	public
-	TranscodeActionVetoException(
-		String		str )
-	{
-		super( str );
-	}
-}
+/*
+ * Created on Mar 16, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public class 
+TranscodeActionVetoException
+	extends Exception
+{
+	public
+	TranscodeActionVetoException(
+		String		str )
+	{
+		super( str );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeAnalysisListener.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeAnalysisListener.java
index cf342d1..6829faa 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeAnalysisListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeAnalysisListener.java
@@ -1,37 +1,36 @@
-/*
- * Created on Feb 15, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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 
-TranscodeAnalysisListener 
-{
-	public void
-	analysisComplete(
-		TranscodeJob					file,
-		TranscodeProviderAnalysis		analysis );
-	
-	public void
-	analysisFailed(
-		TranscodeJob		file,
-		TranscodeException	error );
-		
-}
+/*
+ * Created on Feb 15, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+TranscodeAnalysisListener 
+{
+	public void
+	analysisComplete(
+		TranscodeJob					file,
+		TranscodeProviderAnalysis		analysis );
+	
+	public void
+	analysisFailed(
+		TranscodeJob		file,
+		TranscodeException	error );
+		
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeException.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeException.java
index f80a88f..ba29e02 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeException.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeException.java
@@ -1,59 +1,58 @@
-/*
- * Created on Feb 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;
-
- at SuppressWarnings("serial")
-
-public class 
-TranscodeException
-	extends Exception
-{
-	private boolean	disable_retry = false;
-	
-	public 
-	TranscodeException(
-		String		str )
-	{
-		super( str );
-	}
-	
-	public 
-	TranscodeException(
-		String		str,
-		Throwable 	e )
-	{
-		super( str, e );
-	}
-	
-	public void
-	setDisableRetry(
-		boolean		b )
-	{
-		disable_retry = b;
-	}
-	
-	public boolean
-	isRetryDisabled()
-	{
-		return( disable_retry );
-	}
-}
+/*
+ * Created on Feb 2, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+ at SuppressWarnings("serial")
+
+public class 
+TranscodeException
+	extends Exception
+{
+	private boolean	disable_retry = false;
+	
+	public 
+	TranscodeException(
+		String		str )
+	{
+		super( str );
+	}
+	
+	public 
+	TranscodeException(
+		String		str,
+		Throwable 	e )
+	{
+		super( str, e );
+	}
+	
+	public void
+	setDisableRetry(
+		boolean		b )
+	{
+		disable_retry = b;
+	}
+	
+	public boolean
+	isRetryDisabled()
+	{
+		return( disable_retry );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeFile.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeFile.java
index ef4b2d3..c94e33a 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeFile.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeFile.java
@@ -1,145 +1,144 @@
-/*
- * Created on Feb 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.devices;
-
-import java.io.File;
-import java.net.URL;
-
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-
-public interface 
-TranscodeFile 
-{
-		// don't change these, they are serialised
-	
-	public static final String PT_COMPLETE		= "comp";
-	public static final String PT_COPIED		= "copied";
-	public static final String PT_COPY_FAILED	= "copy_fail";
-	public static final String PT_CATEGORY		= "cat";
-	public static final String PT_TAGS			= "tags";
-	
-	public String
-	getName();
-	
-	public DiskManagerFileInfo
-	getSourceFile()
-	
-		throws TranscodeException;
-	
-	public DiskManagerFileInfo 
-	getTargetFile() 
-	
-		throws TranscodeException;
-	
-	public String
-	getProfileName();
-	
-	public long
-	getCreationDateMillis();
-	
-	public boolean
-	isComplete();
-	
-	public boolean
-	getTranscodeRequired();
-	
-	public boolean
-	isCopiedToDevice();
-	
-	public long
-	getCopyToDeviceFails();
-	
-	public void
-	retryCopyToDevice();
-	
-	public boolean
-	isTemplate();
-	
-	public long
-	getDurationMillis();
-	
-	public long
-	getVideoWidth();
-	
-	public long
-	getVideoHeight();
-	
-	public long
-	getEstimatedTranscodeSize();
-	
-	public String[]
-	getCategories();
-	
-	public void
-	setCategories(
-		String[]	cats );
-	
-	public String[]
-	getTags(
-		boolean	localize );
-	
-	public void
-	setTags(
-		String[]	tags );
-	
-	public Device
-	getDevice();
-	
-	public File
-	getCacheFileIfExists();
-	
-		/**
-		 * Will return null unless there is a job in existance for this file
-		 * @return
-		 */
-	
-	public TranscodeJob
-	getJob();
-	
-	public URL
-	getStreamURL();
-	
-	public URL
-	getStreamURL(
-		String	host );
-	
-	public void
-	delete(
-		boolean	delete_cache_file )
-	
-		throws TranscodeException;
-	
-	public void
-	setTransientProperty(
-		Object		key,
-		Object		value );
-			
-	public Object
-	getTransientProperty(
-		Object		key );
-
-	public boolean 
-	isDeleted();
-
-	public boolean
-	isCopyingToDevice();
-}
+/*
+ * Created on Feb 13, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+import java.io.File;
+import java.net.URL;
+
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+
+public interface 
+TranscodeFile 
+{
+		// don't change these, they are serialised
+	
+	public static final String PT_COMPLETE		= "comp";
+	public static final String PT_COPIED		= "copied";
+	public static final String PT_COPY_FAILED	= "copy_fail";
+	public static final String PT_CATEGORY		= "cat";
+	public static final String PT_TAGS			= "tags";
+	
+	public String
+	getName();
+	
+	public DiskManagerFileInfo
+	getSourceFile()
+	
+		throws TranscodeException;
+	
+	public DiskManagerFileInfo 
+	getTargetFile() 
+	
+		throws TranscodeException;
+	
+	public String
+	getProfileName();
+	
+	public long
+	getCreationDateMillis();
+	
+	public boolean
+	isComplete();
+	
+	public boolean
+	getTranscodeRequired();
+	
+	public boolean
+	isCopiedToDevice();
+	
+	public long
+	getCopyToDeviceFails();
+	
+	public void
+	retryCopyToDevice();
+	
+	public boolean
+	isTemplate();
+	
+	public long
+	getDurationMillis();
+	
+	public long
+	getVideoWidth();
+	
+	public long
+	getVideoHeight();
+	
+	public long
+	getEstimatedTranscodeSize();
+	
+	public String[]
+	getCategories();
+	
+	public void
+	setCategories(
+		String[]	cats );
+	
+	public String[]
+	getTags(
+		boolean	localize );
+	
+	public void
+	setTags(
+		String[]	tags );
+	
+	public Device
+	getDevice();
+	
+	public File
+	getCacheFileIfExists();
+	
+		/**
+		 * Will return null unless there is a job in existance for this file
+		 * @return
+		 */
+	
+	public TranscodeJob
+	getJob();
+	
+	public URL
+	getStreamURL();
+	
+	public URL
+	getStreamURL(
+		String	host );
+	
+	public void
+	delete(
+		boolean	delete_cache_file )
+	
+		throws TranscodeException;
+	
+	public void
+	setTransientProperty(
+		Object		key,
+		Object		value );
+			
+	public Object
+	getTransientProperty(
+		Object		key );
+
+	public boolean 
+	isDeleted();
+
+	public boolean
+	isCopyingToDevice();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeJob.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeJob.java
index 3b11e5a..46cbb23 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeJob.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeJob.java
@@ -1,128 +1,127 @@
-/*
- * Created on Feb 4, 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.disk.DiskManagerFileInfo;
-
-public interface 
-TranscodeJob 
-{
-	public static final int	ST_QUEUED		= 0;
-	public static final int	ST_RUNNING		= 1;
-	public static final int	ST_PAUSED		= 2;
-	public static final int	ST_COMPLETE		= 3;
-	public static final int	ST_CANCELLED	= 4;
-	public static final int	ST_FAILED		= 5;
-	public static final int	ST_STOPPED		= 6;
-	public static final int	ST_REMOVED		= 7;
-
-	public String
-	getName();
-	
-	public TranscodeTarget
-	getTarget();
-	
-	public TranscodeProfile
-	getProfile();
-	
-	public DiskManagerFileInfo
-	getFile();
-	
-	public TranscodeFile
-	getTranscodeFile();
-	
-	public int
-	getTranscodeRequirement();
-	
-	public int
-	getIndex();
-	
-	public int
-	getState();
-	
-	public long
-	getDownloadETA();
-	
-	public int
-	getPercentComplete();
-	
-	public long
-	getETASecs();
-	
-	public String
-	getETA();
-	
-	public String
-	getError();
-	
-	public void
-	setEnableAutoRetry(
-		boolean		enabled );
-	
-	public boolean
-	getEnableAutoRetry();
-	
-	public void
-	setPreferDirectInput(
-		boolean		prefer );
-	
-	public boolean
-	getPreferDirectInput();
-	
-	public boolean
-	canPause();
-	
-	public void
-	pause();
-	
-	public void
-	resume();
-	
-	public void
-	queue();
-	
-	public void
-	stop();
-	
-	public void
-	remove()
-	
-		throws TranscodeActionVetoException;
-	
-	public void
-	removeForce();
-	
-	public void
-	moveUp();
-	
-	public void
-	moveDown();
-
-	public long
-	getProcessTime();
-	
-	public void
-	analyseNow(
-		TranscodeAnalysisListener	listener )
-	
-		throws TranscodeException;
-}
+/*
+ * Created on Feb 4, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+
+public interface 
+TranscodeJob 
+{
+	public static final int	ST_QUEUED		= 0;
+	public static final int	ST_RUNNING		= 1;
+	public static final int	ST_PAUSED		= 2;
+	public static final int	ST_COMPLETE		= 3;
+	public static final int	ST_CANCELLED	= 4;
+	public static final int	ST_FAILED		= 5;
+	public static final int	ST_STOPPED		= 6;
+	public static final int	ST_REMOVED		= 7;
+
+	public String
+	getName();
+	
+	public TranscodeTarget
+	getTarget();
+	
+	public TranscodeProfile
+	getProfile();
+	
+	public DiskManagerFileInfo
+	getFile();
+	
+	public TranscodeFile
+	getTranscodeFile();
+	
+	public int
+	getTranscodeRequirement();
+	
+	public int
+	getIndex();
+	
+	public int
+	getState();
+	
+	public long
+	getDownloadETA();
+	
+	public int
+	getPercentComplete();
+	
+	public long
+	getETASecs();
+	
+	public String
+	getETA();
+	
+	public String
+	getError();
+	
+	public void
+	setEnableAutoRetry(
+		boolean		enabled );
+	
+	public boolean
+	getEnableAutoRetry();
+	
+	public void
+	setPreferDirectInput(
+		boolean		prefer );
+	
+	public boolean
+	getPreferDirectInput();
+	
+	public boolean
+	canPause();
+	
+	public void
+	pause();
+	
+	public void
+	resume();
+	
+	public void
+	queue();
+	
+	public void
+	stop();
+	
+	public void
+	remove()
+	
+		throws TranscodeActionVetoException;
+	
+	public void
+	removeForce();
+	
+	public void
+	moveUp();
+	
+	public void
+	moveDown();
+
+	public long
+	getProcessTime();
+	
+	public void
+	analyseNow(
+		TranscodeAnalysisListener	listener )
+	
+		throws TranscodeException;
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeManager.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeManager.java
index 201bf51..b8c55fe 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeManager.java
@@ -1,41 +1,40 @@
-/*
- * Created on Feb 4, 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 
-TranscodeManager 
-{
-	public TranscodeProvider[]
-	getProviders();
-	
-	public TranscodeQueue
-	getQueue();
-	
-	public void
-	addListener(
-		TranscodeManagerListener		listener );
-	
-	public void
-	removeListener(
-		TranscodeManagerListener		listener );
-}
+/*
+ * Created on Feb 4, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+
+public interface 
+TranscodeManager 
+{
+	public TranscodeProvider[]
+	getProviders();
+	
+	public TranscodeQueue
+	getQueue();
+	
+	public void
+	addListener(
+		TranscodeManagerListener		listener );
+	
+	public void
+	removeListener(
+		TranscodeManagerListener		listener );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeManagerListener.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeManagerListener.java
index d4803ae..dd11429 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeManagerListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeManagerListener.java
@@ -1,38 +1,37 @@
-/*
- * Created on Feb 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.devices;
-
-public interface 
-TranscodeManagerListener 
-{
-	public void
-	providerAdded(
-		TranscodeProvider	provider );
-	
-	public void
-	providerUpdated(
-		TranscodeProvider	provider );
-	
-	public void
-	providerRemoved(
-		TranscodeProvider	provider );
-}
+/*
+ * Created on Feb 5, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+TranscodeManagerListener 
+{
+	public void
+	providerAdded(
+		TranscodeProvider	provider );
+	
+	public void
+	providerUpdated(
+		TranscodeProvider	provider );
+	
+	public void
+	providerRemoved(
+		TranscodeProvider	provider );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProfile.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProfile.java
index d2ae337..12b1fde 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProfile.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProfile.java
@@ -1,55 +1,54 @@
-/*
- * Created on Feb 4, 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 
-TranscodeProfile 
-{
-	public String
-	getUID();
-	
-	public String
-	getName();
-	
-	public String
-	getDescription();
-	
-	public boolean
-	isStreamable();
-	
-	public String
-	getIconURL();
-	
-	public int
-	getIconIndex();
-	
-	public String
-	getFileExtension();
-	
-	public String
-	getDeviceClassification();
-	
-	public TranscodeProvider
-	getProvider()
-	
-		throws TranscodeException;
-}
+/*
+ * Created on Feb 4, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+TranscodeProfile 
+{
+	public String
+	getUID();
+	
+	public String
+	getName();
+	
+	public String
+	getDescription();
+	
+	public boolean
+	isStreamable();
+	
+	public String
+	getIconURL();
+	
+	public int
+	getIconIndex();
+	
+	public String
+	getFileExtension();
+	
+	public String
+	getDeviceClassification();
+	
+	public TranscodeProvider
+	getProvider()
+	
+		throws TranscodeException;
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProvider.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProvider.java
index 6eef173..6cf5087 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProvider.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProvider.java
@@ -1,78 +1,77 @@
-/*
- * Created on Feb 4, 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 java.io.File;
-import java.net.URL;
-
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-
-public interface 
-TranscodeProvider 
-{
-	public static final int TP_VUZE	= 1;
-	
-	public int
-	getID();
-	
-	public String
-	getName();
-	
-	public TranscodeProfile[]
-	getProfiles();
-	
-	public TranscodeProfile[]
-	getProfiles(
-		String	classification_prefix );
-	
-	public TranscodeProfile
-	getProfile(
-		String		UID );
-	
-	public TranscodeProfile
-	addProfile(
-		File		file )
-	
-		throws TranscodeException;
-	
-	public TranscodeProviderAnalysis
-	analyse( 
-		TranscodeProviderAdapter	adapter,
-		DiskManagerFileInfo			input,
-		TranscodeProfile			profile )	
-	
-		throws TranscodeException;
-	
-	public TranscodeProviderJob
-	transcode( 
-		TranscodeProviderAdapter	adapter,
-		TranscodeProviderAnalysis	analysis,
-		boolean						force,
-		DiskManagerFileInfo			input,
-		TranscodeProfile			profile,
-		URL							output )
-	
-		throws TranscodeException;
-	
-	public File
-	getAssetDirectory();
-}
+/*
+ * Created on Feb 4, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+import java.io.File;
+import java.net.URL;
+
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+
+public interface 
+TranscodeProvider 
+{
+	public static final int TP_VUZE	= 1;
+	
+	public int
+	getID();
+	
+	public String
+	getName();
+	
+	public TranscodeProfile[]
+	getProfiles();
+	
+	public TranscodeProfile[]
+	getProfiles(
+		String	classification_prefix );
+	
+	public TranscodeProfile
+	getProfile(
+		String		UID );
+	
+	public TranscodeProfile
+	addProfile(
+		File		file )
+	
+		throws TranscodeException;
+	
+	public TranscodeProviderAnalysis
+	analyse( 
+		TranscodeProviderAdapter	adapter,
+		DiskManagerFileInfo			input,
+		TranscodeProfile			profile )	
+	
+		throws TranscodeException;
+	
+	public TranscodeProviderJob
+	transcode( 
+		TranscodeProviderAdapter	adapter,
+		TranscodeProviderAnalysis	analysis,
+		boolean						force,
+		DiskManagerFileInfo			input,
+		TranscodeProfile			profile,
+		URL							output )
+	
+		throws TranscodeException;
+	
+	public File
+	getAssetDirectory();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderAdapter.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderAdapter.java
index 6f81aa1..d69bc66 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderAdapter.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderAdapter.java
@@ -1,45 +1,44 @@
-/*
- * Created on Feb 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.devices;
-
-public interface 
-TranscodeProviderAdapter 
-{
-	public void
-	updateProgress(
-		int						percent,
-		int						eta_secs,
-		int						new_width,
-		int						new_height );
-	
-	public void
-	streamStats(
-		long					connect_rate,
-		long					write_speed );
-	
-	public void
-	failed(
-		TranscodeException		error );
-	
-	public void
-	complete();
-}
+/*
+ * Created on Feb 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+TranscodeProviderAdapter 
+{
+	public void
+	updateProgress(
+		int						percent,
+		int						eta_secs,
+		int						new_width,
+		int						new_height );
+	
+	public void
+	streamStats(
+		long					connect_rate,
+		long					write_speed );
+	
+	public void
+	failed(
+		TranscodeException		error );
+	
+	public void
+	complete();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderAnalysis.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderAnalysis.java
index c8599e9..16ee6e7 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderAnalysis.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderAnalysis.java
@@ -1,55 +1,54 @@
-/*
- * Created on Mar 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 
-TranscodeProviderAnalysis 
-{
-	public static final int PT_TRANSCODE_REQUIRED	= 1;	// Boolean
-	public static final int PT_DURATION_MILLIS		= 2;	// Long
-	public static final int PT_VIDEO_WIDTH			= 3;	// Long
-	public static final int PT_VIDEO_HEIGHT			= 4;	// Long
-	public static final int PT_SOURCE_SIZE			= 6;	// Long
-	public static final int PT_ESTIMATED_XCODE_SIZE	= 7;	// Long
-
-	public static final int PT_FORCE_TRANSCODE		= 5;	// Boolean (set)
-
-	
-	public void
-	cancel();
-	
-	public boolean
-	foundVideoStream();
-	
-	public boolean
-	getBooleanProperty(
-		int		property );
-	
-	public void
-	setBooleanProperty(
-		int			property,
-		boolean		value );
-	
-	public long
-	getLongProperty(
-		int		property );
-}
+/*
+ * Created on Mar 2, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+TranscodeProviderAnalysis 
+{
+	public static final int PT_TRANSCODE_REQUIRED	= 1;	// Boolean
+	public static final int PT_DURATION_MILLIS		= 2;	// Long
+	public static final int PT_VIDEO_WIDTH			= 3;	// Long
+	public static final int PT_VIDEO_HEIGHT			= 4;	// Long
+	public static final int PT_SOURCE_SIZE			= 6;	// Long
+	public static final int PT_ESTIMATED_XCODE_SIZE	= 7;	// Long
+
+	public static final int PT_FORCE_TRANSCODE		= 5;	// Boolean (set)
+
+	
+	public void
+	cancel();
+	
+	public boolean
+	foundVideoStream();
+	
+	public boolean
+	getBooleanProperty(
+		int		property );
+	
+	public void
+	setBooleanProperty(
+		int			property,
+		boolean		value );
+	
+	public long
+	getLongProperty(
+		int		property );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderJob.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderJob.java
index 5923a36..e647043 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderJob.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeProviderJob.java
@@ -1,39 +1,38 @@
-/*
- * Created on Feb 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.devices;
-
-public interface 
-TranscodeProviderJob 
-{
-	public void
-	pause();
-	
-	public void
-	resume();
-	
-	public void
-	cancel();
-	
-	public void
-	setMaxBytesPerSecond(
-		int		max );
-}
+/*
+ * Created on Feb 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+TranscodeProviderJob 
+{
+	public void
+	pause();
+	
+	public void
+	resume();
+	
+	public void
+	cancel();
+	
+	public void
+	setMaxBytesPerSecond(
+		int		max );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueue.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueue.java
index cbc69d9..7ebcfc4 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueue.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueue.java
@@ -1,91 +1,90 @@
-/*
- * Created on Feb 6, 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.disk.DiskManagerFileInfo;
-
-public interface 
-TranscodeQueue 
-{
-	public TranscodeJob
-	add(
-		TranscodeTarget			target,
-		TranscodeProfile		profile,
-		DiskManagerFileInfo		file,
-		boolean					add_stopped )
-	
-		throws TranscodeException;
-	
-	public TranscodeJob
-	add(
-		TranscodeTarget			target,
-		TranscodeProfile		profile,
-		DiskManagerFileInfo		file,
-		int						transcode_requirement,		// from target.TRANSCODE_<x>
-		boolean					add_stopped )
-	
-		throws TranscodeException;
-	
-	public TranscodeJob[]
-	getJobs();
-	
-	public void
-	pause();
-	
-	public boolean
-	isPaused();
-	
-	public void
-	resume();
-	
-	public int
-	getJobCount();
-	
-	public TranscodeJob
-	getCurrentJob();
-	
-	public boolean
-	isTranscoding();
-	
-	public long
-	getMaxBytesPerSecond();
-	
-	public void
-	setMaxBytesPerSecond(
-		long		max );
-	
-	public void
-	addListener(
-		TranscodeQueueListener		listener );
-	
-	public void
-	removeListener(
-		TranscodeQueueListener		listener );
-	
-	public void
-	addActionListener(
-		TranscodeQueueActionListener		listener );
-	
-	public void
-	removeActionListener(
-		TranscodeQueueActionListener		listener );
-}
+/*
+ * Created on Feb 6, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+
+public interface 
+TranscodeQueue 
+{
+	public TranscodeJob
+	add(
+		TranscodeTarget			target,
+		TranscodeProfile		profile,
+		DiskManagerFileInfo		file,
+		boolean					add_stopped )
+	
+		throws TranscodeException;
+	
+	public TranscodeJob
+	add(
+		TranscodeTarget			target,
+		TranscodeProfile		profile,
+		DiskManagerFileInfo		file,
+		int						transcode_requirement,		// from target.TRANSCODE_<x>
+		boolean					add_stopped )
+	
+		throws TranscodeException;
+	
+	public TranscodeJob[]
+	getJobs();
+	
+	public void
+	pause();
+	
+	public boolean
+	isPaused();
+	
+	public void
+	resume();
+	
+	public int
+	getJobCount();
+	
+	public TranscodeJob
+	getCurrentJob();
+	
+	public boolean
+	isTranscoding();
+	
+	public long
+	getMaxBytesPerSecond();
+	
+	public void
+	setMaxBytesPerSecond(
+		long		max );
+	
+	public void
+	addListener(
+		TranscodeQueueListener		listener );
+	
+	public void
+	removeListener(
+		TranscodeQueueListener		listener );
+	
+	public void
+	addActionListener(
+		TranscodeQueueActionListener		listener );
+	
+	public void
+	removeActionListener(
+		TranscodeQueueActionListener		listener );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueueActionListener.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueueActionListener.java
index ba6e6e9..92a19b5 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueueActionListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueueActionListener.java
@@ -1,35 +1,34 @@
-/*
- * Created on Mar 16, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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 
-TranscodeQueueActionListener 
-{
-	public static final int	ACT_REMOVE	= 1;
-	
-	public void
-	jobWillBeActioned(
-		TranscodeJob		job,
-		int					action )
-	
-		throws TranscodeActionVetoException;
-}
+/*
+ * Created on Mar 16, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+TranscodeQueueActionListener 
+{
+	public static final int	ACT_REMOVE	= 1;
+	
+	public void
+	jobWillBeActioned(
+		TranscodeJob		job,
+		int					action )
+	
+		throws TranscodeActionVetoException;
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueueListener.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueueListener.java
index 6f26349..5f46ffb 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueueListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeQueueListener.java
@@ -1,38 +1,37 @@
-/*
- * Created on Feb 6, 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 
-TranscodeQueueListener 
-{
-	public void
-	jobAdded(
-		TranscodeJob		job );
-	
-	public void
-	jobChanged(
-		TranscodeJob		job );
-	
-	public void
-	jobRemoved(
-		TranscodeJob		job );
-}
+/*
+ * Created on Feb 6, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+TranscodeQueueListener 
+{
+	public void
+	jobAdded(
+		TranscodeJob		job );
+	
+	public void
+	jobChanged(
+		TranscodeJob		job );
+	
+	public void
+	jobRemoved(
+		TranscodeJob		job );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeTarget.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeTarget.java
index 829d393..3729389 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeTarget.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeTarget.java
@@ -1,97 +1,96 @@
-/*
- * Created on Feb 4, 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 java.io.File;
-
-
-public interface 
-TranscodeTarget 
-{
-	public static final int TRANSCODE_UNKNOWN			= -1;
-	public static final int TRANSCODE_NEVER				= 1;
-	public static final int TRANSCODE_WHEN_REQUIRED		= 2;
-	public static final int TRANSCODE_ALWAYS			= 3;
-	
-	public String
-	getID();
-	
-	public Device
-	getDevice();
-	
-	public TranscodeFile[]
-	getFiles();
-	
-	public File
-	getWorkingDirectory();
-	
-	public void
-	setWorkingDirectory(
-		File		directory );
-	
-	public TranscodeProfile[]
-	getTranscodeProfiles();
-		
-	public TranscodeProfile
-	getDefaultTranscodeProfile()
-	
-		throws TranscodeException;
-	
-	public void
-	setDefaultTranscodeProfile(
-		TranscodeProfile		profile );
-	
-	public TranscodeProfile
-	getBlankProfile();
-	
-	public int
-	getTranscodeRequirement();
-	
-	public void
-	setTranscodeRequirement(
-		int		req );
-	
-	public boolean
-	getAlwaysCacheFiles();
-	
-	public void
-	setAlwaysCacheFiles(
-		boolean		always_cache );
-
-	public boolean
-	isTranscoding();
-	
-	public boolean
-	isNonSimple();
-	
-	public boolean
-	isAudioCompatible(
-		TranscodeFile		file );
-	
-	public void
-	addListener(
-		TranscodeTargetListener		listener );
-	
-	public void
-	removeListener(
-		TranscodeTargetListener		listener );
-}
+/*
+ * Created on Feb 4, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+import java.io.File;
+
+
+public interface 
+TranscodeTarget 
+{
+	public static final int TRANSCODE_UNKNOWN			= -1;
+	public static final int TRANSCODE_NEVER				= 1;
+	public static final int TRANSCODE_WHEN_REQUIRED		= 2;
+	public static final int TRANSCODE_ALWAYS			= 3;
+	
+	public String
+	getID();
+	
+	public Device
+	getDevice();
+	
+	public TranscodeFile[]
+	getFiles();
+	
+	public File
+	getWorkingDirectory();
+	
+	public void
+	setWorkingDirectory(
+		File		directory );
+	
+	public TranscodeProfile[]
+	getTranscodeProfiles();
+		
+	public TranscodeProfile
+	getDefaultTranscodeProfile()
+	
+		throws TranscodeException;
+	
+	public void
+	setDefaultTranscodeProfile(
+		TranscodeProfile		profile );
+	
+	public TranscodeProfile
+	getBlankProfile();
+	
+	public int
+	getTranscodeRequirement();
+	
+	public void
+	setTranscodeRequirement(
+		int		req );
+	
+	public boolean
+	getAlwaysCacheFiles();
+	
+	public void
+	setAlwaysCacheFiles(
+		boolean		always_cache );
+
+	public boolean
+	isTranscoding();
+	
+	public boolean
+	isNonSimple();
+	
+	public boolean
+	isAudioCompatible(
+		TranscodeFile		file );
+	
+	public void
+	addListener(
+		TranscodeTargetListener		listener );
+	
+	public void
+	removeListener(
+		TranscodeTargetListener		listener );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeTargetListener.java b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeTargetListener.java
index ba3eb60..6372272 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/TranscodeTargetListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/TranscodeTargetListener.java
@@ -1,42 +1,41 @@
-/*
- * Created on Feb 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.devices;
-
-public interface 
-TranscodeTargetListener 
-{
-	public static final int	CT_PROPERTY		= 1;		// data = String property
-	
-	public void
-	fileAdded(
-		TranscodeFile		file );
-	
-	public void
-	fileChanged(
-		TranscodeFile		file,
-		int					type,
-		Object				data );
-	
-	public void
-	fileRemoved(
-		TranscodeFile		file );
-}
+/*
+ * Created on Feb 13, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices;
+
+public interface 
+TranscodeTargetListener 
+{
+	public static final int	CT_PROPERTY		= 1;		// data = String property
+	
+	public void
+	fileAdded(
+		TranscodeFile		file );
+	
+	public void
+	fileChanged(
+		TranscodeFile		file,
+		int					type,
+		Object				data );
+	
+	public void
+	fileRemoved(
+		TranscodeFile		file );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceContentDirectoryImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceContentDirectoryImpl.java
index e3ef64e..441b3d9 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceContentDirectoryImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceContentDirectoryImpl.java
@@ -1,116 +1,115 @@
-/*
- * 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.URL;
-import java.util.List;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.devices.*;
-import com.aelitis.net.upnp.UPnPDevice;
-import com.aelitis.net.upnp.UPnPService;
-
-public class 
-DeviceContentDirectoryImpl
-	extends DeviceUPnPImpl
-	implements DeviceContentDirectory
-{
-	private UPnPService		upnp_service;
-	
-	protected
-	DeviceContentDirectoryImpl(
-		DeviceManagerImpl	_manager,
-		UPnPDevice			_device,
-		UPnPService			_service )
-	{
-		super( _manager, _device, Device.DT_CONTENT_DIRECTORY );
-		
-		upnp_service = _service;
-	}
-	
-	protected
-	DeviceContentDirectoryImpl(
-		DeviceManagerImpl	_manager,
-		Map					_map )
-	
-		throws IOException
-	{
-		super(_manager, _map );
-	}
-	
-	protected boolean
-	updateFrom(
-		DeviceImpl		_other,
-		boolean			_is_alive )
-	{
-		if ( !super.updateFrom( _other, _is_alive )){
-			
-			return( false );
-		}
-		
-		if ( !( _other instanceof DeviceContentDirectoryImpl )){
-			
-			Debug.out( "Inconsistent" );
-			
-			return( false );
-		}
-		
-		DeviceContentDirectoryImpl other = (DeviceContentDirectoryImpl)_other;
-				
-		if ( other.upnp_service != null ){
-			
-			upnp_service = other.upnp_service;
-		}
-		
-		return( true );
-	}
-	
-	public List<URL>
-	getControlURLs()
-	{
-		if ( upnp_service != null ){
-		
-			try{
-				return( upnp_service.getControlURLs());
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}
-		
-		return( null );
-	}
-	
-	public void 
-	setPreferredControlURL(
-		URL url) 
-	{
-		if ( upnp_service != null ){
-			
-			upnp_service.setPreferredControlURL( url );
-		}
-	}
-}
+/*
+ * Created on Jan 28, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import org.gudy.azureus2.core3.util.Debug;
+
+import com.aelitis.azureus.core.devices.*;
+import com.aelitis.net.upnp.UPnPDevice;
+import com.aelitis.net.upnp.UPnPService;
+
+public class 
+DeviceContentDirectoryImpl
+	extends DeviceUPnPImpl
+	implements DeviceContentDirectory
+{
+	private UPnPService		upnp_service;
+	
+	protected
+	DeviceContentDirectoryImpl(
+		DeviceManagerImpl	_manager,
+		UPnPDevice			_device,
+		UPnPService			_service )
+	{
+		super( _manager, _device, Device.DT_CONTENT_DIRECTORY );
+		
+		upnp_service = _service;
+	}
+	
+	protected
+	DeviceContentDirectoryImpl(
+		DeviceManagerImpl	_manager,
+		Map					_map )
+	
+		throws IOException
+	{
+		super(_manager, _map );
+	}
+	
+	protected boolean
+	updateFrom(
+		DeviceImpl		_other,
+		boolean			_is_alive )
+	{
+		if ( !super.updateFrom( _other, _is_alive )){
+			
+			return( false );
+		}
+		
+		if ( !( _other instanceof DeviceContentDirectoryImpl )){
+			
+			Debug.out( "Inconsistent" );
+			
+			return( false );
+		}
+		
+		DeviceContentDirectoryImpl other = (DeviceContentDirectoryImpl)_other;
+				
+		if ( other.upnp_service != null ){
+			
+			upnp_service = other.upnp_service;
+		}
+		
+		return( true );
+	}
+	
+	public List<URL>
+	getControlURLs()
+	{
+		if ( upnp_service != null ){
+		
+			try{
+				return( upnp_service.getControlURLs());
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+		
+		return( null );
+	}
+	
+	public void 
+	setPreferredControlURL(
+		URL url) 
+	{
+		if ( upnp_service != null ){
+			
+			upnp_service.setPreferredControlURL( url );
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceDriveManager.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceDriveManager.java
index db99aef..0567b7d 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceDriveManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceDriveManager.java
@@ -1,448 +1,447 @@
-/*
- * Created on Jul 31, 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.*;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.AERunnable;
-import org.gudy.azureus2.core3.util.AsyncDispatcher;
-
-import com.aelitis.azureus.core.devices.Device;
-import com.aelitis.azureus.core.devices.DeviceManagerListener;
-import com.aelitis.azureus.core.devices.DeviceMediaRenderer;
-import com.aelitis.azureus.core.devices.DeviceTemplate;
-import com.aelitis.azureus.core.drivedetector.DriveDetectedInfo;
-import com.aelitis.azureus.core.drivedetector.DriveDetectedListener;
-import com.aelitis.azureus.core.drivedetector.DriveDetectorFactory;
-import com.aelitis.azureus.util.MapUtils;
-
-public class 
-DeviceDriveManager 
-	implements DriveDetectedListener
-{
-	private DeviceManagerImpl		manager;
-	
-	private Map<String,DeviceMediaRendererManual>	device_map = new HashMap<String, DeviceMediaRendererManual>();
-	
-	private AsyncDispatcher	async_dispatcher = new AsyncDispatcher();
-	
-	private boolean	listener_added;
-	
-	protected
-	DeviceDriveManager(
-		DeviceManagerImpl		_manager )
-	{
-		manager = _manager;
-		
-		manager.addListener(
-			new DeviceManagerListener()
-			{
-				public void
-				deviceAdded(
-					Device		device )
-				{	
-				}
-				
-				public void
-				deviceChanged(
-					Device		device )
-				{
-				}
-				
-				public void
-				deviceAttentionRequest(
-					Device		device )
-				{
-				}
-				
-				public void
-				deviceRemoved(
-					Device		device )
-				{
-					synchronized( device_map ){
-						
-						Iterator<Map.Entry<String,DeviceMediaRendererManual>> it = device_map.entrySet().iterator();
-						
-						while( it.hasNext()){
-							
-							Map.Entry<String,DeviceMediaRendererManual> entry = it.next();
-							
-							if ( entry.getValue() == device ){
-								
-								it.remove();
-							}
-						}
-					}
-				}
-
-				public void
-				deviceManagerLoaded()
-				{
-				}
-			});
-		
-		if ( manager.getAutoSearch()){
-			
-			listener_added = true;
-			
-			DriveDetectorFactory.getDeviceDetector().addListener( this );
-		}
-	}
-	
-	protected void
-	search()
-	{
-		async_dispatcher.dispatch(
-			new AERunnable()
-			{
-				public void
-				runSupport()
-				{
-					if ( listener_added ){
-						
-						DriveDetectedInfo[] info = DriveDetectorFactory.getDeviceDetector().getDetectedDriveInfo();
-						
-						for ( DriveDetectedInfo i: info ){
-							
-							driveRemoved( i );
-							
-							driveDetected( i );
-						}
-						
-						return;
-					}
-					
-					try{
-							// this should synchronously first any discovered drives
-						
-						DriveDetectorFactory.getDeviceDetector().addListener( DeviceDriveManager.this );
-
-					}finally{
-						
-						DriveDetectorFactory.getDeviceDetector().removeListener( DeviceDriveManager.this );
-					}
-				}
-			});
-	}
-	
-	public void 
-	driveDetected(
-		final DriveDetectedInfo info )
- {
-		//System.out.println("DD " + info.getLocation() + " via " + Debug.getCompressedStackTrace());
-		async_dispatcher.dispatch(new AERunnable() {
-			public void runSupport() {
-				
-				Map<String, Object> infoMap = info.getInfoMap();
-
-				boolean isWritableUSB = MapUtils.getMapBoolean(infoMap, "isWritableUSB", false);
-				
-				File root = info.getLocation();
-
-				String sProdID = MapUtils.getMapString(infoMap, "ProductID",
-						MapUtils.getMapString(infoMap, "Product Name", "")).trim();
-				String sVendor = MapUtils.getMapString(infoMap, "VendorID",
-						MapUtils.getMapString(infoMap, "Vendor Name", "")).trim();
-
-				// Historically, we gave IDs to Motorola, Samsung, and HTC phones
-				// based on their vendor and product id only.  We need to maintain
-				// this ID in order to not create duplicates.
-				// Fortunately, both Motorola and Samsung include their model id in the 
-				// sProdID.  HTC doesn't, however, their PID doesn't identify unique
-				// models anyway, so including that wouldn't have helped anyway
-				if ((sVendor.equalsIgnoreCase("htc") && sProdID.equalsIgnoreCase("android phone"))
-						|| (sVendor.toLowerCase().contains("motorola") && sProdID.length() > 0)
-						|| sVendor.equalsIgnoreCase("samsung")) {
-					
-					if (isWritableUSB && sVendor.equalsIgnoreCase("samsung")) {
-						// Samsungs that start with Y are MP3 players
-						// Samsungs that don't have a dash aren't smart phones (none that we know of anyway..)
-						// Fake not writable so we remove the device instead of adding it
-						isWritableUSB = !sProdID.startsWith("Y")
-								&& sProdID.matches(".*[A-Z]-.*");
-					}
-
-					String name = sProdID.startsWith(sVendor) ? "" : sVendor;
-					if (sVendor.length() > 0) {
-						name += " ";
-					}
-					name += sProdID;
-
-					String id = "android.";
-					id += sProdID.replaceAll(" ", ".").toLowerCase();
-					if (sVendor.length() > 0) {
-						id += "." + sVendor.replaceAll(" ", ".").toLowerCase();
-					}
-					
-					if (isWritableUSB) {
-						addDevice(name, id, root, new File(root, "videos"), true);
-					} else {
-						//Fixup old bug where we were adding Samsung hard drives as devices
-						Device existingDevice = getDeviceMediaRendererByClassification(id);
-						if (existingDevice != null) {
-							existingDevice.remove();
-						}
-					}
-					return;
-				} else if (isWritableUSB && sVendor.toLowerCase().equals("rim")) {
-					String name = sVendor;
-  				if (name.length() > 0) {
-  					name += " ";
-  				}
-  				name += sProdID;
-					String id = "";
-					id += sProdID.replaceAll(" ", ".").toLowerCase();
-					if (sVendor.length() > 0) {
-						id += "." + sVendor.replaceAll(" ", ".").toLowerCase();
-					}
-					DeviceMediaRendererManual device = addDevice(name, id, root, new File(root, "videos"), false);
-					if (device != null) {
-						device.setImageID("bb");
-					}
-					return;
-				}
-				
-				if (!isWritableUSB) {
-					return;
-				}
-
-				if (root.exists()) {
-
-					File[] folders = root.listFiles();
-
-					if (folders != null) {
-
-						Set<String> names = new HashSet<String>();
-
-						for (File file : folders) {
-
-							names.add(file.getName().toLowerCase());
-						}
-
-						if (names.contains("psp") && names.contains("video")) {
-							addDevice("PSP", "sony.PSP", root, new File(root, "VIDEO"), false);
-							return;
-						}
-					}
-				}
-				
-				String pid = MapUtils.getMapString(infoMap, "PID", null);
-				String vid = MapUtils.getMapString(infoMap, "VID", null);
-				if (pid != null && vid != null) {
-					String name = sProdID.startsWith(sVendor) ? "" : sVendor;
-  				if (name.length() > 0) {
-  					name += " ";
-  				}
-  				name += sProdID;
-
-  				String id = "";
-					id += sProdID.replaceAll(" ", ".").toLowerCase();
-					id += "." + pid.toLowerCase();
-					if (sVendor.length() > 0) {
-						id += "." + sVendor.replaceAll(" ", ".").toLowerCase();
-					}
-					id += "." + vid.toLowerCase();
-					
-					// cheap hack to detect the PSP when it has no psp or video dir
-					if (id.equals("\"psp\".ms.02d2.sony.054c")
-							|| id.equals("\"psp\".ms.0381.sony.054c")) {
-						if (addDevice("PSP", "sony.PSP", root, new File(root, "VIDEO"), false) != null) {
-							return;
-						}
-					}
-					
-					addDevice(name, id, root, new File(root, "video"), true);
-				}
-			}
-		});
-	}
-	
-	protected DeviceMediaRenderer getDeviceMediaRendererByClassification(String target_classification) {
-		DeviceImpl[] devices = manager.getDevices();
-		
-		for ( DeviceImpl device: devices ){
-			
-			if ( device instanceof DeviceMediaRenderer ){
-			
-				DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
-				
-				String classification = renderer.getClassification();
-			
-				if ( classification.equalsIgnoreCase( target_classification )){
-																
-					return renderer;
-				}
-			}
-		}
-
-		return null;
-	}
-
-	protected DeviceMediaRendererManual addDevice(
-			String target_name, 
-			String target_classification,
-			File root,
-			File target_directory,
-			boolean generic)
-	{
-		
-		DeviceMediaRenderer existingDevice = getDeviceMediaRendererByClassification(target_classification);
-		if (existingDevice instanceof DeviceMediaRendererManual ) {
-			mapDevice( (DeviceMediaRendererManual) existingDevice, root, target_directory );
-			
-			existingDevice.setGenericUSB(generic);
-			return (DeviceMediaRendererManual) existingDevice;
-		}
-		
-		DeviceTemplate[] templates = manager.getDeviceTemplates( Device.DT_MEDIA_RENDERER );
-		
-		DeviceMediaRendererManual	renderer = null;
-		
-		for ( DeviceTemplate template: templates ){
-			
-			if ( template.getClassification().equalsIgnoreCase( target_classification )){
-				
-				try{
-					renderer = (DeviceMediaRendererManual)template.createInstance( target_name );
-
-					break;
-					
-				}catch( Throwable e ){
-					
-					log( "Failed to add device", e );
-				}
-			}
-		}
-		
-		if ( renderer == null ){
-			
-				// damn, the above doesn't work until devices is turned on...
-			
-			try{
-				renderer = (DeviceMediaRendererManual)manager.createDevice( Device.DT_MEDIA_RENDERER, null, target_classification, target_name, true );
-				
-			}catch( Throwable e ){
-				
-				log( "Failed to add device", e );
-			}
-		}
-		
-		if ( renderer != null ){
-			
-			try{
-				renderer.setAutoCopyToFolder( true );
-				// This will cause a change event
-				renderer.setGenericUSB(generic);
-				
-				mapDevice( renderer, root, target_directory );
-				
-				return renderer;
-				
-			}catch( Throwable e ){
-				
-				log( "Failed to add device", e );
-			}
-		}
-		return renderer;
-	}
-
-	public void 
-	driveRemoved(
-		final DriveDetectedInfo info )
-	{
-		async_dispatcher.dispatch(
-			new AERunnable()
-			{
-				public void
-				runSupport()
-				{
-					unMapDevice( info.getLocation());
-				}
-			});
-	}
-	
-	protected void
-	mapDevice(
-		DeviceMediaRendererManual		renderer,
-		File							root,
-		File							copy_to )
-	{
-		DeviceMediaRendererManual	existing;
-		
-		synchronized( device_map ){
-			
-			existing = device_map.put( root.getAbsolutePath(), renderer );
-		}
-		
-		if ( existing != null && existing != renderer ){
-			
-			log( "Unmapped " + existing.getName() + " from " + root );
-			
-			existing.setCopyToFolder( null );
-		}
-		
-		log( "Mapped " + renderer.getName() + " to " + root );
-
-		renderer.setCopyToFolder( copy_to );
-		
-		renderer.setLivenessDetectable( true );
-		
-		renderer.alive();
-	}
-	
-	protected void
-	unMapDevice(
-		File							root )
-	{
-		DeviceMediaRendererManual existing;
-		
-		synchronized( device_map ){
-			
-			existing = device_map.remove( root.getAbsolutePath());
-		}
-		
-		if ( existing != null ){
-			
-			log( "Unmapped " + existing.getName() + " from " + root );
-
-			existing.setCopyToFolder( null );
-			
-			existing.dead();
-		}
-	}
-	
-	protected void
-	log(
-		String str )
-	{
-		manager.log( "DriveMan: " + str );
-	}
-	
-	protected void
-	log(
-		String 		str,
-		Throwable 	e )
-	{
-		manager.log( "DriveMan: " + str, e );
-	}
-}
+/*
+ * Created on Jul 31, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.*;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
+
+import com.aelitis.azureus.core.devices.Device;
+import com.aelitis.azureus.core.devices.DeviceManagerListener;
+import com.aelitis.azureus.core.devices.DeviceMediaRenderer;
+import com.aelitis.azureus.core.devices.DeviceTemplate;
+import com.aelitis.azureus.core.drivedetector.DriveDetectedInfo;
+import com.aelitis.azureus.core.drivedetector.DriveDetectedListener;
+import com.aelitis.azureus.core.drivedetector.DriveDetectorFactory;
+import com.aelitis.azureus.util.MapUtils;
+
+public class 
+DeviceDriveManager 
+	implements DriveDetectedListener
+{
+	private DeviceManagerImpl		manager;
+	
+	private Map<String,DeviceMediaRendererManual>	device_map = new HashMap<String, DeviceMediaRendererManual>();
+	
+	private AsyncDispatcher	async_dispatcher = new AsyncDispatcher();
+	
+	private boolean	listener_added;
+	
+	protected
+	DeviceDriveManager(
+		DeviceManagerImpl		_manager )
+	{
+		manager = _manager;
+		
+		manager.addListener(
+			new DeviceManagerListener()
+			{
+				public void
+				deviceAdded(
+					Device		device )
+				{	
+				}
+				
+				public void
+				deviceChanged(
+					Device		device )
+				{
+				}
+				
+				public void
+				deviceAttentionRequest(
+					Device		device )
+				{
+				}
+				
+				public void
+				deviceRemoved(
+					Device		device )
+				{
+					synchronized( device_map ){
+						
+						Iterator<Map.Entry<String,DeviceMediaRendererManual>> it = device_map.entrySet().iterator();
+						
+						while( it.hasNext()){
+							
+							Map.Entry<String,DeviceMediaRendererManual> entry = it.next();
+							
+							if ( entry.getValue() == device ){
+								
+								it.remove();
+							}
+						}
+					}
+				}
+
+				public void
+				deviceManagerLoaded()
+				{
+				}
+			});
+		
+		if ( manager.getAutoSearch()){
+			
+			listener_added = true;
+			
+			DriveDetectorFactory.getDeviceDetector().addListener( this );
+		}
+	}
+	
+	protected void
+	search()
+	{
+		async_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void
+				runSupport()
+				{
+					if ( listener_added ){
+						
+						DriveDetectedInfo[] info = DriveDetectorFactory.getDeviceDetector().getDetectedDriveInfo();
+						
+						for ( DriveDetectedInfo i: info ){
+							
+							driveRemoved( i );
+							
+							driveDetected( i );
+						}
+						
+						return;
+					}
+					
+					try{
+							// this should synchronously first any discovered drives
+						
+						DriveDetectorFactory.getDeviceDetector().addListener( DeviceDriveManager.this );
+
+					}finally{
+						
+						DriveDetectorFactory.getDeviceDetector().removeListener( DeviceDriveManager.this );
+					}
+				}
+			});
+	}
+	
+	public void 
+	driveDetected(
+		final DriveDetectedInfo info )
+ {
+		//System.out.println("DD " + info.getLocation() + " via " + Debug.getCompressedStackTrace());
+		async_dispatcher.dispatch(new AERunnable() {
+			public void runSupport() {
+				
+				Map<String, Object> infoMap = info.getInfoMap();
+
+				boolean isWritableUSB = MapUtils.getMapBoolean(infoMap, "isWritableUSB", false);
+				
+				File root = info.getLocation();
+
+				String sProdID = MapUtils.getMapString(infoMap, "ProductID",
+						MapUtils.getMapString(infoMap, "Product Name", "")).trim();
+				String sVendor = MapUtils.getMapString(infoMap, "VendorID",
+						MapUtils.getMapString(infoMap, "Vendor Name", "")).trim();
+
+				// Historically, we gave IDs to Motorola, Samsung, and HTC phones
+				// based on their vendor and product id only.  We need to maintain
+				// this ID in order to not create duplicates.
+				// Fortunately, both Motorola and Samsung include their model id in the 
+				// sProdID.  HTC doesn't, however, their PID doesn't identify unique
+				// models anyway, so including that wouldn't have helped anyway
+				if ((sVendor.equalsIgnoreCase("htc") && sProdID.equalsIgnoreCase("android phone"))
+						|| (sVendor.toLowerCase().contains("motorola") && sProdID.length() > 0)
+						|| sVendor.equalsIgnoreCase("samsung")) {
+					
+					if (isWritableUSB && sVendor.equalsIgnoreCase("samsung")) {
+						// Samsungs that start with Y are MP3 players
+						// Samsungs that don't have a dash aren't smart phones (none that we know of anyway..)
+						// Fake not writable so we remove the device instead of adding it
+						isWritableUSB = !sProdID.startsWith("Y")
+								&& sProdID.matches(".*[A-Z]-.*");
+					}
+
+					String name = sProdID.startsWith(sVendor) ? "" : sVendor;
+					if (sVendor.length() > 0) {
+						name += " ";
+					}
+					name += sProdID;
+
+					String id = "android.";
+					id += sProdID.replaceAll(" ", ".").toLowerCase();
+					if (sVendor.length() > 0) {
+						id += "." + sVendor.replaceAll(" ", ".").toLowerCase();
+					}
+					
+					if (isWritableUSB) {
+						addDevice(name, id, root, new File(root, "videos"), true);
+					} else {
+						//Fixup old bug where we were adding Samsung hard drives as devices
+						Device existingDevice = getDeviceMediaRendererByClassification(id);
+						if (existingDevice != null) {
+							existingDevice.remove();
+						}
+					}
+					return;
+				} else if (isWritableUSB && sVendor.toLowerCase().equals("rim")) {
+					String name = sVendor;
+  				if (name.length() > 0) {
+  					name += " ";
+  				}
+  				name += sProdID;
+					String id = "";
+					id += sProdID.replaceAll(" ", ".").toLowerCase();
+					if (sVendor.length() > 0) {
+						id += "." + sVendor.replaceAll(" ", ".").toLowerCase();
+					}
+					DeviceMediaRendererManual device = addDevice(name, id, root, new File(root, "videos"), false);
+					if (device != null) {
+						device.setImageID("bb");
+					}
+					return;
+				}
+				
+				if (!isWritableUSB) {
+					return;
+				}
+
+				if (root.exists()) {
+
+					File[] folders = root.listFiles();
+
+					if (folders != null) {
+
+						Set<String> names = new HashSet<String>();
+
+						for (File file : folders) {
+
+							names.add(file.getName().toLowerCase());
+						}
+
+						if (names.contains("psp") && names.contains("video")) {
+							addDevice("PSP", "sony.PSP", root, new File(root, "VIDEO"), false);
+							return;
+						}
+					}
+				}
+				
+				String pid = MapUtils.getMapString(infoMap, "PID", null);
+				String vid = MapUtils.getMapString(infoMap, "VID", null);
+				if (pid != null && vid != null) {
+					String name = sProdID.startsWith(sVendor) ? "" : sVendor;
+  				if (name.length() > 0) {
+  					name += " ";
+  				}
+  				name += sProdID;
+
+  				String id = "";
+					id += sProdID.replaceAll(" ", ".").toLowerCase();
+					id += "." + pid.toLowerCase();
+					if (sVendor.length() > 0) {
+						id += "." + sVendor.replaceAll(" ", ".").toLowerCase();
+					}
+					id += "." + vid.toLowerCase();
+					
+					// cheap hack to detect the PSP when it has no psp or video dir
+					if (id.equals("\"psp\".ms.02d2.sony.054c")
+							|| id.equals("\"psp\".ms.0381.sony.054c")) {
+						if (addDevice("PSP", "sony.PSP", root, new File(root, "VIDEO"), false) != null) {
+							return;
+						}
+					}
+					
+					addDevice(name, id, root, new File(root, "video"), true);
+				}
+			}
+		});
+	}
+	
+	protected DeviceMediaRenderer getDeviceMediaRendererByClassification(String target_classification) {
+		DeviceImpl[] devices = manager.getDevices();
+		
+		for ( DeviceImpl device: devices ){
+			
+			if ( device instanceof DeviceMediaRenderer ){
+			
+				DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
+				
+				String classification = renderer.getClassification();
+			
+				if ( classification.equalsIgnoreCase( target_classification )){
+																
+					return renderer;
+				}
+			}
+		}
+
+		return null;
+	}
+
+	protected DeviceMediaRendererManual addDevice(
+			String target_name, 
+			String target_classification,
+			File root,
+			File target_directory,
+			boolean generic)
+	{
+		
+		DeviceMediaRenderer existingDevice = getDeviceMediaRendererByClassification(target_classification);
+		if (existingDevice instanceof DeviceMediaRendererManual ) {
+			mapDevice( (DeviceMediaRendererManual) existingDevice, root, target_directory );
+			
+			existingDevice.setGenericUSB(generic);
+			return (DeviceMediaRendererManual) existingDevice;
+		}
+		
+		DeviceTemplate[] templates = manager.getDeviceTemplates( Device.DT_MEDIA_RENDERER );
+		
+		DeviceMediaRendererManual	renderer = null;
+		
+		for ( DeviceTemplate template: templates ){
+			
+			if ( template.getClassification().equalsIgnoreCase( target_classification )){
+				
+				try{
+					renderer = (DeviceMediaRendererManual)template.createInstance( target_name );
+
+					break;
+					
+				}catch( Throwable e ){
+					
+					log( "Failed to add device", e );
+				}
+			}
+		}
+		
+		if ( renderer == null ){
+			
+				// damn, the above doesn't work until devices is turned on...
+			
+			try{
+				renderer = (DeviceMediaRendererManual)manager.createDevice( Device.DT_MEDIA_RENDERER, null, target_classification, target_name, true );
+				
+			}catch( Throwable e ){
+				
+				log( "Failed to add device", e );
+			}
+		}
+		
+		if ( renderer != null ){
+			
+			try{
+				renderer.setAutoCopyToFolder( true );
+				// This will cause a change event
+				renderer.setGenericUSB(generic);
+				
+				mapDevice( renderer, root, target_directory );
+				
+				return renderer;
+				
+			}catch( Throwable e ){
+				
+				log( "Failed to add device", e );
+			}
+		}
+		return renderer;
+	}
+
+	public void 
+	driveRemoved(
+		final DriveDetectedInfo info )
+	{
+		async_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void
+				runSupport()
+				{
+					unMapDevice( info.getLocation());
+				}
+			});
+	}
+	
+	protected void
+	mapDevice(
+		DeviceMediaRendererManual		renderer,
+		File							root,
+		File							copy_to )
+	{
+		DeviceMediaRendererManual	existing;
+		
+		synchronized( device_map ){
+			
+			existing = device_map.put( root.getAbsolutePath(), renderer );
+		}
+		
+		if ( existing != null && existing != renderer ){
+			
+			log( "Unmapped " + existing.getName() + " from " + root );
+			
+			existing.setCopyToFolder( null );
+		}
+		
+		log( "Mapped " + renderer.getName() + " to " + root );
+
+		renderer.setCopyToFolder( copy_to );
+		
+		renderer.setLivenessDetectable( true );
+		
+		renderer.alive();
+	}
+	
+	protected void
+	unMapDevice(
+		File							root )
+	{
+		DeviceMediaRendererManual existing;
+		
+		synchronized( device_map ){
+			
+			existing = device_map.remove( root.getAbsolutePath());
+		}
+		
+		if ( existing != null ){
+			
+			log( "Unmapped " + existing.getName() + " from " + root );
+
+			existing.setCopyToFolder( null );
+			
+			existing.dead();
+		}
+	}
+	
+	protected void
+	log(
+		String str )
+	{
+		manager.log( "DriveMan: " + str );
+	}
+	
+	protected void
+	log(
+		String 		str,
+		Throwable 	e )
+	{
+		manager.log( "DriveMan: " + str, e );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceImpl.java
index d0bd84d..6e3c527 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceImpl.java
@@ -2,20 +2,19 @@
  * 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -187,6 +186,7 @@ DeviceImpl
 	private static final String PP_REND_TRANS_REQ		= "tt_req";
 	private static final String PP_REND_TRANS_CACHE		= "tt_always_cache";
 	private static final String PP_REND_RSS_PUB			= "tt_rss_pub";
+	private static final String PP_REND_TAG_SHARE		= "tt_tag_share";
 	
 	protected static final String PP_REND_SHOW_CAT			= "tt_show_cat";
 	protected static final String PP_REND_CLASSIFICATION	= "tt_rend_class";
@@ -1421,6 +1421,19 @@ DeviceImpl
 		setPersistentBooleanProperty( PP_REND_RSS_PUB, enabled );
 	}
 	
+	public long
+	getAutoShareToTagID()
+	{
+		return( getPersistentLongProperty( PP_REND_TAG_SHARE, -1 ));
+	}
+	
+	public void
+	setAutoShareToTagID(
+		long		id )
+	{
+		setPersistentLongProperty( PP_REND_TAG_SHARE, id );
+	}
+	
 	public String[][] 
 	getDisplayProperties() 
 	{
@@ -1937,6 +1950,22 @@ DeviceImpl
 		setPersistentStringProperty(prop, value?"true":"false" );
 	}
 	
+	public long
+	getPersistentLongProperty(
+		String		prop,
+		long		def )
+	{
+		return( Long.parseLong( getPersistentStringProperty( prop, String.valueOf(def) )));
+	}
+	
+	public void
+	setPersistentLongProperty(
+		String		prop,
+		long		value )
+	{
+		setPersistentStringProperty(prop, String.valueOf( value ));
+	}
+	
 	public int
 	getPersistentIntProperty(
 		String		prop,
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceInternetGatewayImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceInternetGatewayImpl.java
index 599177f..bf5ed41 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceInternetGatewayImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceInternetGatewayImpl.java
@@ -1,318 +1,317 @@
-/*
- * 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.URL;
-import java.util.*;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.PluginInterface;
-
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreRunningListener;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.devices.*;
-import com.aelitis.azureus.plugins.upnp.UPnPMapping;
-import com.aelitis.azureus.plugins.upnp.UPnPPlugin;
-import com.aelitis.azureus.plugins.upnp.UPnPPluginService;
-import com.aelitis.net.upnp.UPnPDevice;
-import com.aelitis.net.upnp.services.UPnPWANConnection;
-
-public class 
-DeviceInternetGatewayImpl
-	extends DeviceUPnPImpl
-	implements DeviceInternetGateway
-{
-	private static final int CHECK_MAPPINGS_PERIOD 		= 30*1000;
-	private static final int CHECK_MAPPINGS_TICK_COUNT 	= CHECK_MAPPINGS_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
-	
-		
-	private static UPnPPlugin						upnp_plugin;
-	
-	static{
-		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
-
-			public void azureusCoreRunning(AzureusCore core) {
-
-				try {
-					PluginInterface pi_upnp = core.getPluginManager().getPluginInterfaceByClass(
-							UPnPPlugin.class);
-
-					if (pi_upnp != null) {
-
-						upnp_plugin = (UPnPPlugin) pi_upnp.getPlugin();
-					}
-				} catch (Throwable e) {
-				}
-			}
-		});
-	}
-			
-	private boolean		mapper_enabled;
-	
-	private UPnPPluginService[]	current_services;
-	private UPnPMapping[]		current_mappings;
-	
-	protected
-	DeviceInternetGatewayImpl(
-		DeviceManagerImpl			_manager,
-		UPnPDevice					_device,
-		List<UPnPWANConnection>		_connections )
-	{
-		super( _manager, _device, Device.DT_INTERNET_GATEWAY );
-		
-		updateStatus( 0 );
-	}
-	
-	protected
-	DeviceInternetGatewayImpl(
-		DeviceManagerImpl	_manager,
-		Map					_map )
-	
-		throws IOException
-	{
-		super(_manager, _map );
-	}
-	
-	protected boolean
-	updateFrom(
-		DeviceImpl		_other,
-		boolean			_is_alive )
-	{
-		if ( !super.updateFrom( _other, _is_alive )){
-			
-			return( false );
-		}
-		
-		if ( !( _other instanceof DeviceInternetGatewayImpl )){
-			
-			Debug.out( "Inconsistent" );
-			
-			return( false );
-		}
-		
-		DeviceInternetGatewayImpl other = (DeviceInternetGatewayImpl)_other;
-				
-		return( true );
-	}
-	
-	@Override
-	protected void
-	updateStatus(
-		int		tick_count )
-	{
-		super.updateStatus( tick_count );
-		
-		if ( tick_count % CHECK_MAPPINGS_TICK_COUNT != 0 ){
-			
-			return;
-		}
-		
-		mapper_enabled = upnp_plugin != null && upnp_plugin.isEnabled();
-			
-		UPnPDevice	device = getUPnPDevice();
-		
-		if ( mapper_enabled && device != null ){
-		
-			current_services = upnp_plugin.getServices( device );
-			
-			current_mappings = upnp_plugin.getMappings();
-		}
-	}
-	
-	protected URL
-	getPresentationURL(
-		UPnPDevice		device )
-	{
-		URL	url = super.getPresentationURL( device );
-		
-		if ( url == null ){
-			
-			try{
-					// no explicit one, try hitting location 
-				
-				URL loc = device.getRootDevice().getLocation();
-			
-				URL	test_loc = new URL( loc.getProtocol() +  "://" + loc.getHost() + "/" );
-				
-				test_loc.openConnection().connect();
-				
-				return( test_loc );
-				
-			}catch( Throwable e ){
-			}
-		}
-		
-		return( url );
-	}
-	
-	protected Set<mapping>
-	getRequiredMappings()
-	{
-		Set<mapping>	res = new TreeSet<mapping>();
-			
-		UPnPMapping[]		required_mappings 	= current_mappings;
-
-		if ( required_mappings != null ){
-			
-			for ( UPnPMapping mapping: required_mappings ){
-				
-				if ( mapping.isEnabled()){
-				
-					res.add( new mapping( mapping ));
-				}
-			}
-		}
-		
-		return( res );
-	}
-	
-	protected Set<mapping>
-	getActualMappings(
-		UPnPPluginService	service )
-	{
-		UPnPPluginService.serviceMapping[] actual_mappings = service.getMappings();
-		
-		Set<mapping> actual = new TreeSet<mapping>();
-		
-		for ( UPnPPluginService.serviceMapping act_mapping: actual_mappings ){
-		
-			mapping m = new mapping( act_mapping );
-			
-			actual.add( m );
-		}
-		
-		return( actual );
-	}
-	
-	protected void
-	getDisplayProperties(
-		List<String[]>	dp )
-	{
-		super.getDisplayProperties( dp );
-
-		addDP(dp, "device.router.is_mapping", mapper_enabled );
-		
-		UPnPPluginService[]	services = current_services;
-					
-		String	req_map_str = "";
-				
-		Set<mapping> required = getRequiredMappings();
-		
-		for ( mapping m: required ){
-			
-			req_map_str += (req_map_str.length()==0?"":",") + m.getString();
-		}
-			
-		addDP( dp, "device.router.req_map", req_map_str );
-		
-		if ( services != null ){
-			
-			for ( UPnPPluginService service: services ){
-								
-				Set<mapping> actual = getActualMappings( service );
-				
-				String	act_map_str = "";
-				
-				for ( mapping m: actual ){
-					
-					if ( required.contains(m)){
-					
-						act_map_str += (act_map_str.length()==0?"":",") + m.getString();
-					}
-				}
-				
-				String service_name = MessageText.getString( "device.router.con_type", new String[]{ service.getService().getConnectionType() });
-				
-				addDP( dp, "!    " + service_name + "!", act_map_str );
-			}
-		}
-	}
-	
-	protected static class
-	mapping
-		implements Comparable<mapping>
-	{
-		private boolean	is_tcp;
-		private int		port;
-		
-		protected
-		mapping(
-			UPnPMapping m )
-		{
-			is_tcp		= m.isTCP();
-			port		= m.getPort();
-		}
-		
-		protected
-		mapping(
-			UPnPPluginService.serviceMapping		m )
-		{
-			is_tcp		= m.isTCP();
-			port		= m.getPort();
-		}
-		
-		public int 
-		compareTo(
-			mapping o ) 
-		{
-			int res = port - o.port;
-			
-			if ( res == 0 ){
-				
-				res = (is_tcp?1:0) - (o.is_tcp?1:0);
-			}
-			
-			return( res );
-		}
-		
-		public boolean
-		equals(
-			Object	_other )
-		{
-			if ( _other instanceof mapping ){
-		
-				mapping other = (mapping)_other;
-				
-				return( is_tcp == other.is_tcp && port == other.port );
-				
-			}else{
-				
-				return( false );
-			}
-		}
-		
-		public int 
-		hashCode() 
-		{
-			return((port<<16) + (is_tcp?1:0));
-		}
-		
-		public String
-		getString()
-		{
-			return( (is_tcp?"TCP":"UDP") + " " + port );
-		}
-	}
-}
+/*
+ * Created on Jan 28, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.PluginInterface;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.devices.*;
+import com.aelitis.azureus.plugins.upnp.UPnPMapping;
+import com.aelitis.azureus.plugins.upnp.UPnPPlugin;
+import com.aelitis.azureus.plugins.upnp.UPnPPluginService;
+import com.aelitis.net.upnp.UPnPDevice;
+import com.aelitis.net.upnp.services.UPnPWANConnection;
+
+public class 
+DeviceInternetGatewayImpl
+	extends DeviceUPnPImpl
+	implements DeviceInternetGateway
+{
+	private static final int CHECK_MAPPINGS_PERIOD 		= 30*1000;
+	private static final int CHECK_MAPPINGS_TICK_COUNT 	= CHECK_MAPPINGS_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
+	
+		
+	private static UPnPPlugin						upnp_plugin;
+	
+	static{
+		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+
+			public void azureusCoreRunning(AzureusCore core) {
+
+				try {
+					PluginInterface pi_upnp = core.getPluginManager().getPluginInterfaceByClass(
+							UPnPPlugin.class);
+
+					if (pi_upnp != null) {
+
+						upnp_plugin = (UPnPPlugin) pi_upnp.getPlugin();
+					}
+				} catch (Throwable e) {
+				}
+			}
+		});
+	}
+			
+	private boolean		mapper_enabled;
+	
+	private UPnPPluginService[]	current_services;
+	private UPnPMapping[]		current_mappings;
+	
+	protected
+	DeviceInternetGatewayImpl(
+		DeviceManagerImpl			_manager,
+		UPnPDevice					_device,
+		List<UPnPWANConnection>		_connections )
+	{
+		super( _manager, _device, Device.DT_INTERNET_GATEWAY );
+		
+		updateStatus( 0 );
+	}
+	
+	protected
+	DeviceInternetGatewayImpl(
+		DeviceManagerImpl	_manager,
+		Map					_map )
+	
+		throws IOException
+	{
+		super(_manager, _map );
+	}
+	
+	protected boolean
+	updateFrom(
+		DeviceImpl		_other,
+		boolean			_is_alive )
+	{
+		if ( !super.updateFrom( _other, _is_alive )){
+			
+			return( false );
+		}
+		
+		if ( !( _other instanceof DeviceInternetGatewayImpl )){
+			
+			Debug.out( "Inconsistent" );
+			
+			return( false );
+		}
+		
+		DeviceInternetGatewayImpl other = (DeviceInternetGatewayImpl)_other;
+				
+		return( true );
+	}
+	
+	@Override
+	protected void
+	updateStatus(
+		int		tick_count )
+	{
+		super.updateStatus( tick_count );
+		
+		if ( tick_count % CHECK_MAPPINGS_TICK_COUNT != 0 ){
+			
+			return;
+		}
+		
+		mapper_enabled = upnp_plugin != null && upnp_plugin.isEnabled();
+			
+		UPnPDevice	device = getUPnPDevice();
+		
+		if ( mapper_enabled && device != null ){
+		
+			current_services = upnp_plugin.getServices( device );
+			
+			current_mappings = upnp_plugin.getMappings();
+		}
+	}
+	
+	protected URL
+	getPresentationURL(
+		UPnPDevice		device )
+	{
+		URL	url = super.getPresentationURL( device );
+		
+		if ( url == null ){
+			
+			try{
+					// no explicit one, try hitting location 
+				
+				URL loc = device.getRootDevice().getLocation();
+			
+				URL	test_loc = new URL( loc.getProtocol() +  "://" + loc.getHost() + "/" );
+				
+				test_loc.openConnection().connect();
+				
+				return( test_loc );
+				
+			}catch( Throwable e ){
+			}
+		}
+		
+		return( url );
+	}
+	
+	protected Set<mapping>
+	getRequiredMappings()
+	{
+		Set<mapping>	res = new TreeSet<mapping>();
+			
+		UPnPMapping[]		required_mappings 	= current_mappings;
+
+		if ( required_mappings != null ){
+			
+			for ( UPnPMapping mapping: required_mappings ){
+				
+				if ( mapping.isEnabled()){
+				
+					res.add( new mapping( mapping ));
+				}
+			}
+		}
+		
+		return( res );
+	}
+	
+	protected Set<mapping>
+	getActualMappings(
+		UPnPPluginService	service )
+	{
+		UPnPPluginService.serviceMapping[] actual_mappings = service.getMappings();
+		
+		Set<mapping> actual = new TreeSet<mapping>();
+		
+		for ( UPnPPluginService.serviceMapping act_mapping: actual_mappings ){
+		
+			mapping m = new mapping( act_mapping );
+			
+			actual.add( m );
+		}
+		
+		return( actual );
+	}
+	
+	protected void
+	getDisplayProperties(
+		List<String[]>	dp )
+	{
+		super.getDisplayProperties( dp );
+
+		addDP(dp, "device.router.is_mapping", mapper_enabled );
+		
+		UPnPPluginService[]	services = current_services;
+					
+		String	req_map_str = "";
+				
+		Set<mapping> required = getRequiredMappings();
+		
+		for ( mapping m: required ){
+			
+			req_map_str += (req_map_str.length()==0?"":",") + m.getString();
+		}
+			
+		addDP( dp, "device.router.req_map", req_map_str );
+		
+		if ( services != null ){
+			
+			for ( UPnPPluginService service: services ){
+								
+				Set<mapping> actual = getActualMappings( service );
+				
+				String	act_map_str = "";
+				
+				for ( mapping m: actual ){
+					
+					if ( required.contains(m)){
+					
+						act_map_str += (act_map_str.length()==0?"":",") + m.getString();
+					}
+				}
+				
+				String service_name = MessageText.getString( "device.router.con_type", new String[]{ service.getService().getConnectionType() });
+				
+				addDP( dp, "!    " + service_name + "!", act_map_str );
+			}
+		}
+	}
+	
+	protected static class
+	mapping
+		implements Comparable<mapping>
+	{
+		private boolean	is_tcp;
+		private int		port;
+		
+		protected
+		mapping(
+			UPnPMapping m )
+		{
+			is_tcp		= m.isTCP();
+			port		= m.getPort();
+		}
+		
+		protected
+		mapping(
+			UPnPPluginService.serviceMapping		m )
+		{
+			is_tcp		= m.isTCP();
+			port		= m.getPort();
+		}
+		
+		public int 
+		compareTo(
+			mapping o ) 
+		{
+			int res = port - o.port;
+			
+			if ( res == 0 ){
+				
+				res = (is_tcp?1:0) - (o.is_tcp?1:0);
+			}
+			
+			return( res );
+		}
+		
+		public boolean
+		equals(
+			Object	_other )
+		{
+			if ( _other instanceof mapping ){
+		
+				mapping other = (mapping)_other;
+				
+				return( is_tcp == other.is_tcp && port == other.port );
+				
+			}else{
+				
+				return( false );
+			}
+		}
+		
+		public int 
+		hashCode() 
+		{
+			return((port<<16) + (is_tcp?1:0));
+		}
+		
+		public String
+		getString()
+		{
+			return( (is_tcp?"TCP":"UDP") + " " + port );
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerImpl.java
index 4f93c2a..dc44d58 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerImpl.java
@@ -1,1963 +1,1976 @@
-/*
- * 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.impl;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.URL;
-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.logging.LogAlert;
-import org.gudy.azureus2.core3.logging.Logger;
-import org.gudy.azureus2.core3.util.AEDiagnostics;
-import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator;
-import org.gudy.azureus2.core3.util.AEDiagnosticsLogger;
-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.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.DelayedEvent;
-import org.gudy.azureus2.core3.util.FileUtil;
-import org.gudy.azureus2.core3.util.IndentWriter;
-import org.gudy.azureus2.core3.util.ListenerManager;
-import org.gudy.azureus2.core3.util.ListenerManagerDispatcher;
-import org.gudy.azureus2.core3.util.SimpleTimer;
-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.platform.PlatformManagerFactory;
-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.plugins.tracker.web.TrackerWebPageRequest;
-import org.gudy.azureus2.plugins.ui.UIManager;
-import org.gudy.azureus2.plugins.ui.UIManagerEvent;
-import org.gudy.azureus2.plugins.utils.PowerManagementListener;
-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.AzureusCoreRunningListener;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter;
-import com.aelitis.azureus.core.devices.*;
-import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-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.net.upnp.UPnPDevice;
-
-public class 
-DeviceManagerImpl 
-	implements DeviceManager, DeviceOfflineDownloaderManager, PowerManagementListener, 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 int	AUTO_HIDE_OLD_DAYS_DEFAULT	= 31;
-	private static final String	AUTO_HIDE_OLD_CONFIG_KEY	= "devices.config.auto_hide_old";
-
-	private static final String	RSS_ENABLE_CONFIG_KEY		= "devices.config.rss_enable";
-	
-	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 TRANSCODE_DIR_DEFAULT	= "transcodes";
-	
-	private static final String CONFIG_DEFAULT_WORK_DIR		= "devices.config.def_work_dir";
-	private static final String CONFIG_DISABLE_SLEEP		= "devices.config.disable_sleep";
-
-	
-	protected static final int	DEVICE_UPDATE_PERIOD			= 5*1000;
-	protected static final int	DEVICE_AUTO_HIDE_CHECK_PERIOD	= 2*60*1000;
-	protected static final int	DEVICE_AUTO_HIDE_CHECK_TICKS	= DEVICE_AUTO_HIDE_CHECK_PERIOD/DEVICE_UPDATE_PERIOD;
-	
-	private static boolean pre_initialised;
-	
-	private static DeviceManagerImpl		singleton;
-	
-	public static void
-	preInitialise()
-	{
-		synchronized( DeviceManagerImpl.class ){
-			
-			if ( pre_initialised ){
-				
-				return;
-			}
-			
-			pre_initialised = true;
-		}
-		
-		VuzeFileHandler.getSingleton().addProcessor(
-			new VuzeFileProcessor()
-			{
-				public void
-				process(
-					VuzeFile[]		files,
-					int				expected_types )
-				{
-					for (int i=0;i<files.length;i++){
-						
-						VuzeFile	vf = files[i];
-						
-						VuzeFileComponent[] comps = vf.getComponents();
-						
-						for (int j=0;j<comps.length;j++){
-							
-							VuzeFileComponent comp = comps[j];
-							
-							int	type = comp.getType();
-							
-							if ( type == VuzeFileComponent.COMP_TYPE_DEVICE ){
-								
-								try{
-									((DeviceManagerImpl)getSingleton()).importVuzeFile(
-											comp.getContent(),
-											( expected_types & 
-												( VuzeFileComponent.COMP_TYPE_DEVICE )) == 0 );
-									
-									comp.setProcessed();
-									
-								}catch( Throwable e ){
-									
-									Debug.printStackTrace(e);
-								}
-							}
-						}
-					}
-				}
-			});		
-	}
-	
-	public static DeviceManager
-	getSingleton()
-	{
-		synchronized( DeviceManagerImpl.class ){
-			
-			if ( singleton == null ){
-				
-				singleton = new DeviceManagerImpl();
-			}
-		}
-		
-		return( singleton );
-	}
-	
-	
-	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>();
-	
-	private DeviceTivoManager		tivo_manager;
-	private DeviceManagerUPnPImpl	upnp_manager;
-	private DeviceDriveManager		drive_manager;
-		
-	private Set<Device>				disable_events	= Collections.synchronizedSet( new HashSet<Device>());
-	
-		// have to go async on this as there are situations where we end up firing listeners
-		// while holding monitors and this can result in deadlock if sync
-	
-	private static final int LT_DEVICE_ADDED		= 1;
-	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 ListenerManager<DeviceManagerListener>	listeners = 
-		ListenerManager.createAsyncManager(
-				"DM:ld",
-				new ListenerManagerDispatcher<DeviceManagerListener>()
-				{
-					public void 
-					dispatch(
-						DeviceManagerListener 		listener, 
-						int 						type, 
-						Object 						value ) 
-					{
-						DeviceImpl	device = (DeviceImpl)value;
-						
-						switch( type ){
-						
-							case LT_DEVICE_ADDED:{
-								
-								listener.deviceAdded( device );
-								
-								break;
-							}
-							case LT_DEVICE_CHANGED:{
-								
-								if ( deviceAdded( device )){
-									
-									device.fireChanged();
-									
-									listener.deviceChanged( device );
-								}
-								
-								break;
-							}
-							case LT_DEVICE_ATTENTION:{
-								
-								if ( deviceAdded( device )){
-								
-									listener.deviceAttentionRequest( device );
-								}
-								
-								break;
-							}
-							case LT_DEVICE_REMOVED:{
-								
-								listener.deviceRemoved( device );
-								
-								break;
-							}
-							case LT_INITIALIZED:{
-								
-								listener.deviceManagerLoaded();
-								
-								break;
-							}
-						}
-					}
-					
-					protected boolean
-					deviceAdded(
-						Device		device )
-					{
-						synchronized( DeviceManagerImpl.this ){
-							
-							return( device_list.contains( device ));
-						}
-					}
-				});
-	
-	
-	private boolean	auto_search;
-	private int		auto_hide_old_days	= AUTO_HIDE_OLD_DAYS_DEFAULT;
-	
-	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;
-	private boolean	config_dirty;
-	
-	private int		explicit_search;
-	
-	private volatile TranscodeManagerImpl	transcode_manager;
-	
-	private CopyOnWriteList<DeviceManagerDiscoveryListener>	discovery_listeners = new CopyOnWriteList<DeviceManagerDiscoveryListener>();
-	
-	private int						getMimeType_fails;
-	
-	private Object					logger_lock = new Object();
-	private AEDiagnosticsLogger		logger;
-	
-	private AsyncDispatcher	async_dispatcher = new AsyncDispatcher( 10*1000 );
-
-	private AESemaphore			init_sem = new AESemaphore( "dm:init" );
-	
-	private volatile boolean initialized = false;
-	
-	private Object		lsn_lock			= new Object();
-	private String		local_service_name;
-	
-	protected
-	DeviceManagerImpl()
-	{
-		AEDiagnostics.addEvidenceGenerator( this );
-
-		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
-			public void azureusCoreRunning(AzureusCore core) {
-				initWithCore(core);
-			}
-		});
-	}
-	
-	private TranscodeManager
-	ensureInitialised(
-		boolean 	partial )
-	{
-		AzureusCore core =  AzureusCoreFactory.getSingleton();
-		
-		if ( core.isStarted()){
-		
-			initWithCore( core );
-			
-		}else if ( core.isInitThread()){
-			
-			Debug.out( "This is bad" );
-			
-			initWithCore( core );
-		}
-		
-		if ( partial ){
-			
-			long start = SystemTime.getMonotonousTime();
-			
-			while( !init_sem.reserve(250)){
-				
-				if ( transcode_manager != null ){
-					
-					break;
-				}
-				
-				if ( SystemTime.getMonotonousTime() - start >= 30*1000 ){
-					
-					Debug.out( "Timeout waiting for init" );
-					
-					AEDiagnostics.dumpThreads();
-					
-					break;
-				}
-			}
-		}else{
-			if ( !init_sem.reserve( 30*1000 )){
-				
-				Debug.out( "Timeout waiting for init" );
-				
-				AEDiagnostics.dumpThreads();
-			}
-		}
-		
-		return( transcode_manager );
-	}
-	
-	private void 
-	initWithCore(
-		final AzureusCore core ) 
-	{
-		synchronized( this ){
-			
-			if ( azureus_core != null ){
-				
-				return;
-			}
-		
-			azureus_core = core;
-		}
-		
-		try{
-			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(
-					new String[]{
-						AUTO_SEARCH_CONFIG_KEY,
-						AUTO_HIDE_OLD_CONFIG_KEY,
-					},
-					new ParameterListener()
-					{
-						public void 
-						parameterChanged(
-							String name ) 
-						{
-							auto_search 		= COConfigurationManager.getBooleanParameter( AUTO_SEARCH_CONFIG_KEY, true );
-							auto_hide_old_days	= COConfigurationManager.getIntParameter( AUTO_HIDE_OLD_CONFIG_KEY, AUTO_HIDE_OLD_DAYS_DEFAULT );
-						}
-					});
-			
-			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 );
-	
-			upnp_manager = new DeviceManagerUPnPImpl( this );
-	
-			loadConfig();
-					
-			new DeviceiTunesManager( this );
-					
-			drive_manager = new DeviceDriveManager( this );
-			
-			transcode_manager = new TranscodeManagerImpl( this );
-			
-			transcode_manager.initialise();
-			
-			core.addLifecycleListener(
-				new AzureusCoreLifecycleAdapter()
-				{
-					public void
-					stopping(
-						AzureusCore		core )
-					{					
-						synchronized( DeviceManagerImpl.this ){
-					
-							if ( config_dirty || config_unclean ){
-								
-								saveConfig();
-							}
-							
-							closing	= true;
-							
-							transcode_manager.close();
-							
-							DeviceImpl[] devices = getDevices();
-							
-							for ( DeviceImpl device: devices ){
-								
-								device.close();
-							}
-						}
-					}
-				});
-			
-			upnp_manager.initialise();
-			
-			SimpleTimer.addPeriodicEvent(
-					"DeviceManager:update",
-					DEVICE_UPDATE_PERIOD,
-					new TimerEventPerformer()
-					{
-						private int tick_count = 0;
-						
-						public void 
-						perform(
-							TimerEvent event ) 
-						{
-							List<DeviceImpl> copy;
-							
-							tick_count++;
-							
-							transcode_manager.updateStatus( tick_count );
-							
-							synchronized( DeviceManagerImpl.this ){
-	
-								if( device_list.size() == 0 ){
-									
-									return;
-								}
-								
-								copy = new ArrayList<DeviceImpl>( device_list );
-							}
-							
-							for ( DeviceImpl device: copy ){
-								
-								device.updateStatus( tick_count );
-							}
-							
-							if ( 	auto_hide_old_days > 0 && 
-									tick_count % DEVICE_AUTO_HIDE_CHECK_TICKS == 0 ){
-								
-								long	now = SystemTime.getCurrentTime();
-								
-								int	num_hidden = 0;
-								
-								for ( DeviceImpl device: copy ){
-																		
-									if ( 	device.isLivenessDetectable() &&
-											!device.isTagged()){
-										
-										int type = device.getType();
-										
-										if ( type == Device.DT_CONTENT_DIRECTORY ){
-											
-										}else if ( type == Device.DT_MEDIA_RENDERER ){
-											
-											DeviceMediaRenderer rend = (DeviceMediaRenderer)device;
-											
-											if ( rend.getRendererSpecies() != DeviceMediaRenderer.RS_OTHER ){
-												
-												continue;
-											}
-										}else{
-											
-											continue;
-										}
-										
-										long age = now - device.getLastSeen();
-										
-										if ( age > auto_hide_old_days*24*60*60*1000L ){
-											
-											if ( !device.isHidden()){
-												
-												log( "Auto-hiding '" +  device.getName() + "'" );
-													
-												device.setHidden( true );
-
-												device.setAutoHidden( true );
-											
-												num_hidden++;
-											}
-										}else{
-											
-											if ( device.isHidden() && device.isAutoHidden()){
-												
-												log( "Auto-showing '" +  device.getName() + "'" );
-												
-												device.setAutoHidden( false );
-												
-												device.setHidden( false );
-											}
-										}
-									}
-								}
-							
-								if ( num_hidden > 0 ){
-										
-									Logger.log(					
-										new LogAlert(
-											true,
-											LogAlert.AT_INFORMATION,
-											MessageText.getString(
-												"device.autohide.alert",
-												new String[]{
-													String.valueOf( num_hidden ),
-													String.valueOf( auto_hide_old_days )
-												})));
-								}
-							}
-						}
-					});
-			
-			initialized = true;
-			
-			listeners.dispatch( LT_INITIALIZED, null );
-			
-			core.addPowerManagementListener( this );
-			
-		}finally{
-			
-			init_sem.releaseForever();
-		}
-	}
-	
-	protected void
-	manageOD()
-	{
-		DeviceImpl[] devices = getDevices();
-		
-		for ( DeviceImpl device: devices ){
-			
-			if ( device.getType() == Device.DT_OFFLINE_DOWNLOADER ){
-				
-				((DeviceOfflineDownloaderImpl)device).checkConfig();
-			}
-		}
-	}
-	
-	protected void
-	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 
-	getUPnPManager()
-	{
-		return( upnp_manager );
-	}
-	
-	public String 
-	getLocalServiceName() 
-	{
-		synchronized( lsn_lock ){
-			
-			if ( local_service_name == null ){
-				
-					// try to use the media server's name
-				
-				try{
-					local_service_name = (String)getUPnPManager().getUPnPAVIPC().invoke( "getServiceName", new Object[]{});
-									
-				}catch( Throwable e ){
-				}
-				
-				if ( local_service_name == null ){
-					
-					local_service_name = Constants.APP_NAME;
-					
-					try{
-						String cn = PlatformManagerFactory.getPlatformManager().getComputerName();
-						
-						if ( cn != null && cn.length() > 0 ){
-						
-							local_service_name += " on " + cn;
-						}
-					}catch( Throwable e ){
-					}
-				}
-			}
-			
-			return( local_service_name );
-		}
-	}
-	
-	public boolean
-	isTiVoEnabled()
-	{
-		return( tivo_manager.isEnabled());
-	}
-	
-	public void
-	setTiVoEnabled(
-		boolean	enabled )
-	{
-		tivo_manager.setEnabled( enabled );
-	}
-	
-	public TranscodeProvider[]
-	getProviders()
-	{
-		TranscodeManager tm = ensureInitialised( true );
-		
-		if ( tm == null ){
-			
-			return( new TranscodeProvider[0] );
-		}
-		
-		return( tm.getProviders());
-	}
-	
-	public DeviceTemplate[] 
-	getDeviceTemplates(
-		int		device_type )
-	{
-		if ( transcode_manager == null || device_type != Device.DT_MEDIA_RENDERER ){
-			
-			return( new DeviceTemplate[0] );
-		}
-		
-		TranscodeProvider[] providers = transcode_manager.getProviders();
-		
-		List<DeviceTemplate> result = new ArrayList<DeviceTemplate>();
-		
-		for ( TranscodeProvider provider: providers ){
-			
-			TranscodeProfile[] profiles = provider.getProfiles();
-			
-			Map<String,DeviceMediaRendererTemplateImpl>	class_map = new HashMap<String, DeviceMediaRendererTemplateImpl>();
-			
-			for ( TranscodeProfile profile: profiles ){
-				
-				String	classification = profile.getDeviceClassification();
-				
-				if ( classification.startsWith( "apple." )){
-					
-					classification = "apple.";
-				}
-				
-				boolean	auto = 
-					classification.equals( "sony.PS3" ) ||
-					classification.equals( "microsoft.XBox" ) ||
-					classification.equals( "apple." ) ||
-					classification.equals( "nintendo.Wii" ) ||
-					classification.equals( "browser.generic" );
-				
-				DeviceMediaRendererTemplateImpl temp = class_map.get( classification );
-				
-				if ( temp == null ){
-					
-					temp = new DeviceMediaRendererTemplateImpl( this, classification, auto );
-					
-					class_map.put( classification, temp );
-					
-					result.add( temp );
-				}
-				
-				temp.addProfile( profile );
-			}
-		}
-		
-		return( result.toArray( new DeviceTemplate[ result.size() ]));
-	}
-	
-	public DeviceManufacturer[] 
-  	getDeviceManufacturers(
-  		int		device_type )
-	{
-		DeviceTemplate[] templates = getDeviceTemplates( device_type );
-		
-		Map<String,DeviceManufacturerImpl>	map = new HashMap<String, DeviceManufacturerImpl>();
-		
-		for ( DeviceTemplate template: templates ){
-			
-			if ( template.getType() != device_type ){
-				
-				continue;
-			}
-			
-			String	man_str = template.getManufacturer();
-			
-			DeviceManufacturerImpl man = map.get( man_str );
-			
-			if ( man == null ){
-				
-				man = new DeviceManufacturerImpl( man_str );
-				
-				map.put( man_str, man );
-			}
-			
-			man.addTemplate( template );
-		}
-		
-		return( map.values().toArray( new DeviceManufacturer[ map.size() ] ));
-	}
-	
-	public Device 
-	addVirtualDevice(
-		int 		type, 
-		String		uid,
-		String		classification,
-		String		name )
-	
-		throws DeviceManagerException
-	{
-		return( createDevice( type, uid, classification, name, true ));
-	}
-	
-	public Device 
-	addInetDevice(
-		int 		type, 
-		String		uid,
-		String		classification,
-		String		name,
-		InetAddress address)
-	
-		throws DeviceManagerException
-	{
-		Device device = createDevice( type, uid, classification, name, false );
-		device.setAddress(address);
-		return device;
-	}
-	
-	protected Device
-	createDevice(
-		int						device_type,
-		String					uid,
-		String					classification,
-		String					name,
-		boolean					manual )
-	
-		throws DeviceManagerException
-	{
-		if ( device_type == Device.DT_MEDIA_RENDERER ){
-			
-			DeviceImpl res;
-			
-			if ( manual ){
-				
-				res = new DeviceMediaRendererManual( this, uid, classification, true, name );
-				
-			}else{
-				
-				res = new DeviceMediaRendererImpl( this, uid, classification, true, name );
-			}
-			
-			res = addDevice( res );
-			
-			return( res );
-			
-		}else{
-			
-			throw( new DeviceManagerException( "Can't manually create this device type" ));
-		}
-	}
-	
-	public void
-	search(
-		final int					millis,
-		final DeviceSearchListener	listener )
-	{
-		new AEThread2( "DM:search", true )
-		{
-			public void
-			run()
-			{
-				synchronized( DeviceManagerImpl.this ){
-				
-					explicit_search++;
-				}
-				
-				tivo_manager.search();
-				
-				drive_manager.search();
-				
-				AESemaphore	sem = new AESemaphore( "DM:search" );
-				
-				DeviceManagerListener	dm_listener =
-					new DeviceManagerListener()
-					{
-						public void
-						deviceAdded(
-							Device		device )
-						{
-							listener.deviceFound( device );
-						}
-						
-						public void
-						deviceChanged(
-							Device		device )
-						{
-						}
-						
-						public void
-						deviceAttentionRequest(
-							Device		device )
-						{	
-						}
-						
-						public void
-						deviceRemoved(
-							Device		device )
-						{
-						}
-
-						public void 
-						deviceManagerLoaded() {
-						}
-					};
-					
-				try{
-					addListener( dm_listener );
-				
-					upnp_manager.search();
-					
-					sem.reserve( millis );
-					
-				}finally{
-					
-					synchronized( DeviceManagerImpl.this ){
-						
-						explicit_search--;
-					}
-					
-					removeListener( dm_listener );
-					
-					listener.complete();
-				}
-			}
-		}.start();
-	}
-	
-	protected DeviceImpl
-	getDevice(
-		String		id )
-	{
-		synchronized( this ){
-
-			return( device_map.get( id ));
-		}
-	}
-	
-	protected DeviceImpl
-	addDevice(
-		DeviceImpl		device )
-	{
-		return( addDevice( device, true ));
-	}
-	
-	protected DeviceImpl
-	addDevice(
-		DeviceImpl		device,
-		boolean			is_alive )
-	{
-			// for xbox (currently) we automagically replace a manual entry with an auto one as we may have
-			// added the manual one when receiving a previous browse before getting the UPnP renderer details
-			
-		DeviceImpl	existing = null;
-		
-		synchronized( this ){
-						
-			existing = device_map.get( device.getID());
-			
-			if ( existing != null ){
-				
-				existing.updateFrom( device, is_alive );
-												
-			}else{
-			
-				if ( device.getType() == Device.DT_MEDIA_RENDERER ){
-					
-					DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
-					
-					if ( renderer.getRendererSpecies() == DeviceMediaRenderer.RS_XBOX && !renderer.isManual()){
-						
-						for ( DeviceImpl d: device_list ){
-							
-							if ( d.getType() == Device.DT_MEDIA_RENDERER ){
-								
-								DeviceMediaRenderer r = (DeviceMediaRenderer)d;
-								
-								if ( r.getRendererSpecies() == DeviceMediaRenderer.RS_XBOX && r.isManual()){
-									
-									existing = d;
-
-									log( "Merging " + device.getString() + " -> " + existing.getString());
-										
-									String	secondary_id = device.getID();
-									
-									existing.setSecondaryID( secondary_id );
-									
-									existing.updateFrom( device, is_alive );
-								}
-							}
-						}
-					}
-				}
-			}
-			
-			if ( existing == null ){
-			
-				device_list.add( device );
-				
-				device_map.put( device.getID(), device );
-			}
-		}
-		
-		if ( existing != null ){
-			
-				// don't trigger config save here, if anything has changed it will have been handled
-				// by the updateFrom call above
-			
-			// if anything has changed then the updateFrom methods should have indicated this
-			// so there's no need to blindly fire a change event here
-			// deviceChanged( existing, false );
-			
-			applyUpdates( existing );
-			
-			return( existing );
-		}
-		
-		try{
-			disable_events.add( device );
-		
-			device.initialise();
-			
-			if ( is_alive ){
-			
-				device.alive();
-			}
-			
-			applyUpdates( device );
-			
-		}finally{
-			
-			disable_events.remove( device );
-		}
-		deviceAdded( device );
-		
-		configDirty();
-		
-		return( device );
-	}
-	
-	protected void
-	applyUpdates(
-		DeviceImpl		device )
-	{
-		if ( device.getType() == Device.DT_MEDIA_RENDERER ){
-			
-			DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
-			
-			if ( renderer instanceof DeviceUPnPImpl ){
-				
-				UPnPDevice upnp_device = ((DeviceUPnPImpl)renderer).getUPnPDevice();
-				
-				if ( upnp_device != null ){
-					
-					String lc_manufacturer 	= getOptionalLC( upnp_device.getManufacturer());
-					String lc_model			= getOptionalLC( upnp_device.getModelName());
-					String lc_fname			= getOptionalLC( upnp_device.getFriendlyName());
-					
-					if ( lc_manufacturer.startsWith( "samsung" )){
-						
-						device.setPersistentStringProperty( DeviceImpl.PP_REND_CLASSIFICATION, "samsung.generic" );
-						
-						TranscodeProfile[] profiles = device.getTranscodeProfiles();
-						
-						if ( profiles.length == 0 ){
-							
-							device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_NEVER );
-							
-						}else{
-							
-							device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_WHEN_REQUIRED );
-						}
-					}else if ( lc_manufacturer.startsWith( "western digital" )){
-							
-							device.setPersistentStringProperty( DeviceImpl.PP_REND_CLASSIFICATION, "western.digital.generic" );
-							
-							TranscodeProfile[] profiles = device.getTranscodeProfiles();
-							
-							if ( profiles.length == 0 ){
-								
-								device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_NEVER );
-								
-							}else{
-								
-								device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_WHEN_REQUIRED );
-							}
-					}else if ( lc_manufacturer.startsWith( "sony" ) && lc_fname.startsWith( "bravia" )){
-							
-						device.setPersistentStringProperty( DeviceImpl.PP_REND_CLASSIFICATION, "sony.bravia" );
-							
-					}else if ( lc_model.equals( "windows media player" )){
-						
-						String model_number = upnp_device.getModelNumber();
-						
-						if ( model_number != null ){
-							
-							try{
-								int num = Integer.parseInt( model_number );
-								
-								if ( num >= 12 ){
-									
-									device.setPersistentStringProperty( DeviceImpl.PP_REND_CLASSIFICATION, "ms_wmp.generic" );
-									
-									TranscodeProfile[] profiles = device.getTranscodeProfiles();
-									
-									if ( profiles.length == 0 ){
-										
-										device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_NEVER );
-										
-									}else{
-										
-										device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_WHEN_REQUIRED );
-									}
-								}
-							}catch( Throwable e ){
-								
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-	
-	private String
-	getOptionalLC(
-		String	str )
-	{
-		if ( str == null ){
-			
-			return( "" );
-		}
-		
-		return( str.toLowerCase().trim());
-	}
-	
-	protected void
-	removeDevice(
-		DeviceImpl		device )
-	{
-		synchronized( this ){
-			
-			DeviceImpl existing = device_map.remove( device.getID());
-			
-			if ( existing == null ){
-				
-				return;
-			}
-			
-			device_list.remove( device );
-			
-			String secondary_id = device.getSecondaryID();
-			
-			if ( secondary_id != null ){
-				
-				device_map.remove( secondary_id );
-			}
-		}
-		
-		device.destroy();
-		
-		deviceRemoved( device );
-		
-		configDirty();
-	}
-
-	public boolean
-	isBusy(
-		int	device_type )
-	{
-			// transcoding is rolled into renderers
-		
-		if ( device_type == Device.DT_UNKNOWN || device_type == Device.DT_MEDIA_RENDERER ){
-			
-			if ( getTranscodeManager().getQueue().isTranscoding()){
-				
-				return( true );
-			}
-		}
-		
-		DeviceImpl[] devices = getDevices();
-					
-		for ( DeviceImpl device: devices ){
-			
-			if ( device.isBusy()){
-				
-				if ( device_type == Device.DT_UNKNOWN || device_type == device.getType()){
-				
-					return( true );
-				}
-			}
-		}
-		
-		return( false );
-	}
-	
-	public DeviceImpl[]
-  	getDevices()
-	{
-		synchronized( this ){
-			
-			return( device_list.toArray( new DeviceImpl[ device_list.size()] ));
-		}
-	}
-  		
-	public boolean
-	getAutoSearch()
-	{
-		return( auto_search );
-	}
-	
-	public void
-	setAutoSearch(
-		boolean	auto )
-	{
-		COConfigurationManager.setParameter( AUTO_SEARCH_CONFIG_KEY, auto );
-	}
-	
-	public int
-	getAutoHideOldDevicesDays()
-	{
-		return( COConfigurationManager.getIntParameter( AUTO_HIDE_OLD_CONFIG_KEY, AUTO_HIDE_OLD_DAYS_DEFAULT ));
-	}
-	
-	public void
-	setAutoHideOldDevicesDays(
-		int		days )
-	{
-		COConfigurationManager.setParameter( AUTO_HIDE_OLD_CONFIG_KEY, days );
-	}
-	
-	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());
-	}
-	
-		// 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
-	getOfflineDownloadingIsAuto()
-	{
-		return( od_is_auto );
-	}
-	
-	public void
-	setOfflineDownloadingIsAuto(
-		boolean		auto )
-	{
-		COConfigurationManager.setParameter( OD_IS_AUTO_CONFIG_KEY, auto );
-	}
-
-	public boolean
-	getOfflineDownloadingIncludePrivate()
-	{
-		return( od_include_private );	
-	}
-	
-	public void
-	setOfflineDownloadingIncludePrivate(
-		boolean		include )
-	{
-		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
-	removeManualDownloads(
-		Download[]		downloads )
-	{
-		for ( Download d: downloads ){
-			
-			d.setBooleanAttribute( od_manual_ta, false );
-		}
-		
-		manageOD();
-	}
-	
-		// sdsd
-	
-	protected boolean
-	isExplicitSearch()
-	{
-		synchronized( this ){
-			
-			return( explicit_search > 0 );
-		}
-	}
-	
-	protected boolean
-	isClosing()
-	{
-		synchronized( this ){
-		
-			return( closing );
-		}
-	}
-	
-	protected void
-	loadConfig()
-	{
-		if ( !FileUtil.resilientConfigFileExists( CONFIG_FILE )){
-			
-			return;
-		}
-		
-		log( "Loading configuration" );
-				
-		synchronized( this ){
-			
-			Map map = FileUtil.readResilientConfigFile( CONFIG_FILE );
-			
-			List	l_devices = (List)map.get( "devices" );
-			
-			if ( l_devices != null ){
-				
-				for (int i=0;i<l_devices.size();i++){
-					
-					Map	m = (Map)l_devices.get(i);
-					
-					try{
-						DeviceImpl device = DeviceImpl.importFromBEncodedMapStatic(this,  m );
-						
-						device_list.add( device );
-						
-						device_map.put( device.getID(), device );
-						
-						String secondary_id = device.getSecondaryID();
-						
-						if ( secondary_id != null ){
-							
-							device_map.put( secondary_id, device );
-						}
-							
-						device.initialise();
-					
-						log( "    loaded " + device.getString());
-						
-					}catch( Throwable e ){
-						
-						log( "Failed to import subscription from " + m, e );
-					}
-				}
-			}
-		}
-	}
-	
-	protected void
-	configDirty(
-		DeviceImpl		device,
-		boolean			save_changes )
-	{
-		deviceChanged( device, save_changes );
-	}
-	
-	protected void
-	configDirty()
-	{
-		synchronized( this ){
-			
-			if ( config_dirty ){
-				
-				return;
-			}
-			
-			config_dirty = true;
-		
-			new DelayedEvent( 
-				"Subscriptions:save", 5000,
-				new AERunnable()
-				{
-					public void 
-					runSupport() 
-					{
-						synchronized( DeviceManagerImpl.this ){
-							
-							if ( !config_dirty ){
-
-								return;
-							}
-							
-							saveConfig();
-						}	
-					}
-				});
-		}
-	}
-	
-	protected void
-	saveConfig()
-	{
-		log( "Saving configuration" );
-		
-		synchronized( this ){
-			
-			if ( closing ){
-				
-					// to late to try writing
-				
-				return;
-			}
-			
-			config_dirty 	= false;
-			config_unclean	= false;
-			
-			if ( device_list.size() == 0 ){
-				
-				FileUtil.deleteResilientConfigFile( CONFIG_FILE );
-				
-			}else{
-				
-				Map map = new HashMap();
-				
-				List	l_devices = new ArrayList();
-				
-				map.put( "devices", l_devices );
-				
-				Iterator<DeviceImpl>	it = device_list.iterator();
-				
-				while( it.hasNext()){
-					
-					DeviceImpl device = it.next();
-						
-					try{
-						Map d = new HashMap();
-						
-						device.exportToBEncodedMap( d, false );
-						
-						l_devices.add( d );
-						
-					}catch( Throwable e ){
-						
-						log( "Failed to save device " + device.getString(), e );
-					}
-				}
-				
-				FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
-			}
-		}
-	}
-	
-	protected void
-	deviceAdded(
-		DeviceImpl		device )
-	{
-		configDirty();
-		
-		// I'd rather put this in a listener, but for now this will ensure
-		// it gets QOS'd even before any listeners are added
-		
-		try{
-			PlatformDevicesMessenger.qosFoundDevice(device);
-			
-		}catch( Throwable e ){
-			
-			Debug.out(e);
-		}
-		
-		listeners.dispatch( LT_DEVICE_ADDED, device );
-	}
-	
-	
-	protected void
-	deviceChanged(
-		DeviceImpl		device,
-		boolean			save_changes )
-	{
-		if ( save_changes ){
-			
-			configDirty();
-			
-		}else{
-			
-			synchronized( this ){
-
-				config_unclean = true;
-			}
-		}
-			
-		if ( !disable_events.contains( device )){
-		
-			//System.out.println(System.currentTimeMillis() + "] CHANGE -> " + device.getID() + "/" + device.getName() + " via " + Debug.getCompressedStackTrace());
-			
-			listeners.dispatch( LT_DEVICE_CHANGED, device );
-		}
-	}
-	
-	protected void
-	deviceRemoved(
-		DeviceImpl		device )
-	{
-		configDirty();
-		
-		listeners.dispatch( LT_DEVICE_REMOVED, device );
-	}
-	
-	protected void
-	requestAttention(
-		DeviceImpl		device )
-	{
-		listeners.dispatch( LT_DEVICE_ATTENTION, device );
-	}
-	
-	protected URL
-	getStreamURL(
-		TranscodeFileImpl		file,
-		String					host )
-	{
-		IPCInterface ipc = upnp_manager.getUPnPAVIPC();
-		
-		if ( ipc != null ){
-
-			try{
-				DiskManagerFileInfo f = file.getTargetFile();
-				
-				String str = (String)ipc.invoke( "getContentURL", new Object[]{ f });
-				
-				if ( str != null && str.length() > 0 ){
-					
-					if ( host != null ){
-						
-						str = str.replace( "127.0.0.1", host );
-					}
-					
-					return( new URL( str ));
-				}
-			}catch( Throwable e ){
-				
-			}
-		}
-		
-		return( null );
-	}
-	
-	protected String
-	getMimeType(
-		TranscodeFileImpl		file )
-	{
-		if ( getMimeType_fails > 5 ){
-			
-			return( null );
-		}
-		
-		IPCInterface ipc = upnp_manager.getUPnPAVIPC();
-		
-		if ( ipc != null ){
-
-			try{
-				DiskManagerFileInfo f = file.getTargetFile();
-				
-				String str = (String)ipc.invoke( "getMimeType", new Object[]{ f });
-				
-				if ( str != null && str.length() > 0 ){
-					
-					return( str );
-				}
-			}catch( Throwable e ){
-				
-				getMimeType_fails++;
-				
-				e.printStackTrace();
-			}
-		}
-		
-		return( null );
-	}
-	
-	public File
-	getDefaultWorkingDirectory()
-	{
-		return( getDefaultWorkingDirectory( false ));
-	}
-	
-	public File
-	getDefaultWorkingDirectory(
-		boolean		persist )
-	{
-		String def = COConfigurationManager.getStringParameter( CONFIG_DEFAULT_WORK_DIR, "" ).trim();
-		
-		if ( def.length() == 0 ){
-			
-			String	def_dir = COConfigurationManager.getStringParameter( "Default save path" );
-
-			def = def_dir + File.separator + TRANSCODE_DIR_DEFAULT;
-		}
-		
-		File f = new File( def );
-		
-		if ( !f.exists()){
-		
-				// migration from Azureus Downloads to Vuze Downloads
-			
-			if ( f.getName().equals( TRANSCODE_DIR_DEFAULT )){
-				
-				String	parent = f.getParentFile().getName();
-				
-				if ( parent.equals( "Azureus Downloads" ) || parent.equals( "Vuze Downloads" )){
-					
-					String	def_dir = COConfigurationManager.getStringParameter( "Default save path" );
-
-					f = new File( def_dir, TRANSCODE_DIR_DEFAULT );
-				}
-			}
-			if ( persist ){
-			
-				f.mkdirs();
-			}
-		}
-		
-		return( f );
-	}
-	
-	public void
-	setDefaultWorkingDirectory(
-		File		dir )
-	{
-		File existing = getDefaultWorkingDirectory( false );
-		
-		if ( !existing.getAbsolutePath().equals( dir.getAbsolutePath())){
-			
-				// default has changed, reset all device save locations so that they pick up the change
-				
-			DeviceImpl[] devices = getDevices();
-			
-			for ( DeviceImpl device: devices ){
-		
-				device.resetWorkingDirectory();
-			}
-		}
-		
-		COConfigurationManager.setParameter( CONFIG_DEFAULT_WORK_DIR, dir.getAbsolutePath());
-	}
-	
-	public boolean
-	getDisableSleep()
-	{
-		return( COConfigurationManager.getBooleanParameter( CONFIG_DISABLE_SLEEP, true ));
-	}
-	
-	public void
-	setDisableSleep(
-		boolean		b )
-	{
-		COConfigurationManager.setParameter( CONFIG_DISABLE_SLEEP, b );
-	}
-	
-	public TranscodeManagerImpl
-	getTranscodeManager()
-	{
-		if ( transcode_manager == null ){
-			
-			ensureInitialised( false );
-		}
-		
-		return( transcode_manager );
-	}
-	
-	public UnassociatedDevice[]
-	getUnassociatedDevices()
-	{
-		return( upnp_manager.getUnassociatedDevices());
-	}
-	
-	public String
-	getPowerName()
-	{
-		return( "Transcode" );
-	}
-	
-	public boolean
-	requestPowerStateChange(
-		int		new_state,
-		Object	data )
-	{
-		if ( getDisableSleep()){
-			
-			if ( getTranscodeManager().getQueue().isTranscoding()){
-				
-				return( false );
-			}
-		}
-		
-		return( true );
-	}
-
-	public void
-	informPowerStateChange(
-		int		new_state,
-		Object	data )
-	{
-		
-	}
-	
-  	public void
-  	addListener(
-  		DeviceManagerListener		listener )
-  	{
-  		listeners.addListener( listener );
-  		
-  		if (initialized) {
-
-  			listeners.dispatch( listener, LT_INITIALIZED, null );
-  		}
-  	}
-  	
-	protected boolean
-	browseReceived(
-		TrackerWebPageRequest		request,
-		Map<String,Object>			browser_args )
-	{
-		for ( DeviceManagerDiscoveryListener l: discovery_listeners ){
-			
-			try{
-				if ( l.browseReceived( request, browser_args )){
-									
-					return( true );
-				}
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}
-		
-		return( false );
-	}
-	
-	protected VuzeFile
-	exportVuzeFile(
-		DeviceImpl		device )
-	
-		throws IOException
-	{
-		VuzeFile	vf = VuzeFileHandler.getSingleton().create();
-		
-		Map	map = new HashMap();
-		
-		Map device_map = new HashMap();
-		
-		map.put( "device", device_map );
-		
-		device.exportToBEncodedMap( device_map, true );
-		
-		vf.addComponent( VuzeFileComponent.COMP_TYPE_DEVICE, map );
-		
-		return( vf );
-	}
-	
-	private void
-	importVuzeFile(
-		Map			map,
-		boolean		warn_user )
-	{
-		Map	m = (Map)map.get( "device" );
-					
-		try{
-			DeviceImpl device = DeviceImpl.importFromBEncodedMapStatic( this, m );
-			
-			DeviceImpl existing;
-			
-			synchronized( this ){
-				
-				existing = device_map.get( device.getID());
-			}
-			
-			if ( existing == null ){
-				
-				if ( warn_user ){
-					
-					UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-		
-					String details = MessageText.getString(
-							"device.import.desc",
-							new String[]{ device.getName()});
-					
-					long res = ui_manager.showMessageBox(
-							"device.import.title",
-							"!" + details + "!",
-							UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
-					
-					if ( res != UIManagerEvent.MT_YES ){	
-					
-						return;
-					}
-				}
-				
-				addDevice( device, false );
-				
-			}else{
-				
-				if ( warn_user ){
-					
-					UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-					
-					String details = MessageText.getString(
-							"device.import.dup.desc",
-							new String[]{ existing.getName()});
-					
-					ui_manager.showMessageBox(
-							"device.import.dup.title",
-							"!" + details + "!",
-							UIManagerEvent.MT_OK );
-				}
-				
-			}
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-	}
-	
-	public void
-	addDiscoveryListener(
-		DeviceManagerDiscoveryListener	listener )
-	{
-		discovery_listeners.add( listener );
-	}
-	
-	public void
-	removeDiscoveryListener(
-		DeviceManagerDiscoveryListener	listener )
-	{
-		discovery_listeners.remove( listener );
-	}
-  	
-  	public void
-  	removeListener(
-  		DeviceManagerListener		listener )
-  	{
-  		listeners.removeListener( listener );
-  	}
-  	
-	protected AEDiagnosticsLogger
-	getLogger()
-	{
-		synchronized( logger_lock ){
-			
-			if ( logger == null ){
-				
-				logger = AEDiagnostics.getLogger( LOGGER_NAME );
-			}
-			
-			return( logger );
-		}
-	}
-	
-	public void 
-	log(
-		String 		s,
-		Throwable 	e )
-	{
-		AEDiagnosticsLogger diag_logger = getLogger();
-		
-		diag_logger.log( s );
-		diag_logger.log( e );
-	}
-	
-	public void 
-	log(
-		String 	s )
-	{
-		AEDiagnosticsLogger diag_logger = getLogger();
-		
-		diag_logger.log( s );
-	}
- 	
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		writer.println( "Devices" );
-			
-		try{
-			writer.indent();
-			
-			DeviceImpl[] devices = getDevices();
-			
-			for ( DeviceImpl device: devices ){
-				
-				device.generate( writer );
-			}
-			
-			if ( transcode_manager != null ){
-			
-				transcode_manager.generate( writer );
-			}
-		}finally{
-			
-			writer.exdent();
-		}
-	}
-	
-	protected static class
-	DeviceManufacturerImpl
-		implements DeviceManufacturer
-	{
-		private String 	name;
-		
-		private List<DeviceTemplate>	templates = new ArrayList<DeviceTemplate>();
-		
-		protected
-		DeviceManufacturerImpl(
-			String		_name )
-		{
-			name	= _name;
-		}
-		
-		protected void
-		addTemplate(
-			DeviceTemplate	t )
-		{
-			templates.add( t );
-		}
-		
-		public String
-		getName()
-		{
-			return( name );
-		}
-		
-		public DeviceTemplate[]
-		getDeviceTemplates()
-		{
-			return( templates.toArray( new DeviceTemplate[ templates.size()] ));
-		}
-	}
-}
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.URL;
+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.logging.LogAlert;
+import org.gudy.azureus2.core3.logging.Logger;
+import org.gudy.azureus2.core3.util.AEDiagnostics;
+import org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator;
+import org.gudy.azureus2.core3.util.AEDiagnosticsLogger;
+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.Constants;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.DelayedEvent;
+import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.core3.util.IndentWriter;
+import org.gudy.azureus2.core3.util.ListenerManager;
+import org.gudy.azureus2.core3.util.ListenerManagerDispatcher;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+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.platform.PlatformManagerFactory;
+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.plugins.tracker.web.TrackerWebPageRequest;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.UIManagerEvent;
+import org.gudy.azureus2.plugins.utils.PowerManagementListener;
+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.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter;
+import com.aelitis.azureus.core.devices.*;
+import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+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.net.upnp.UPnPDevice;
+
+public class 
+DeviceManagerImpl 
+	implements DeviceManager, DeviceOfflineDownloaderManager, PowerManagementListener, 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 int	AUTO_HIDE_OLD_DAYS_DEFAULT	= 31;
+	private static final String	AUTO_HIDE_OLD_CONFIG_KEY	= "devices.config.auto_hide_old";
+
+	private static final String	RSS_ENABLE_CONFIG_KEY		= "devices.config.rss_enable";
+	
+	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 TRANSCODE_DIR_DEFAULT	= "transcodes";
+	
+	private static final String CONFIG_DEFAULT_WORK_DIR		= "devices.config.def_work_dir";
+	private static final String CONFIG_DISABLE_SLEEP		= "devices.config.disable_sleep";
+
+	
+	protected static final int	DEVICE_UPDATE_PERIOD			= 5*1000;
+	protected static final int	DEVICE_AUTO_HIDE_CHECK_PERIOD	= 2*60*1000;
+	protected static final int	DEVICE_AUTO_HIDE_CHECK_TICKS	= DEVICE_AUTO_HIDE_CHECK_PERIOD/DEVICE_UPDATE_PERIOD;
+	
+	private static boolean pre_initialised;
+	
+	private static DeviceManagerImpl		singleton;
+	
+	public static void
+	preInitialise()
+	{
+		synchronized( DeviceManagerImpl.class ){
+			
+			if ( pre_initialised ){
+				
+				return;
+			}
+			
+			pre_initialised = true;
+		}
+		
+		VuzeFileHandler.getSingleton().addProcessor(
+			new VuzeFileProcessor()
+			{
+				public void
+				process(
+					VuzeFile[]		files,
+					int				expected_types )
+				{
+					for (int i=0;i<files.length;i++){
+						
+						VuzeFile	vf = files[i];
+						
+						VuzeFileComponent[] comps = vf.getComponents();
+						
+						for (int j=0;j<comps.length;j++){
+							
+							VuzeFileComponent comp = comps[j];
+							
+							int	type = comp.getType();
+							
+							if ( type == VuzeFileComponent.COMP_TYPE_DEVICE ){
+								
+								try{
+									((DeviceManagerImpl)getSingleton()).importVuzeFile(
+											comp.getContent(),
+											( expected_types & 
+												( VuzeFileComponent.COMP_TYPE_DEVICE )) == 0 );
+									
+									comp.setProcessed();
+									
+								}catch( Throwable e ){
+									
+									Debug.printStackTrace(e);
+								}
+							}
+						}
+					}
+				}
+			});		
+	}
+	
+	public static DeviceManager
+	getSingleton()
+	{
+		synchronized( DeviceManagerImpl.class ){
+			
+			if ( singleton == null ){
+				
+				singleton = new DeviceManagerImpl();
+			}
+		}
+		
+		return( singleton );
+	}
+	
+	
+	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>();
+	
+	private DeviceTivoManager		tivo_manager;
+	private DeviceManagerUPnPImpl	upnp_manager;
+	private DeviceDriveManager		drive_manager;
+		
+	private Set<Device>				disable_events	= Collections.synchronizedSet( new HashSet<Device>());
+	
+		// have to go async on this as there are situations where we end up firing listeners
+		// while holding monitors and this can result in deadlock if sync
+	
+	private static final int LT_DEVICE_ADDED		= 1;
+	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 ListenerManager<DeviceManagerListener>	listeners = 
+		ListenerManager.createAsyncManager(
+				"DM:ld",
+				new ListenerManagerDispatcher<DeviceManagerListener>()
+				{
+					public void 
+					dispatch(
+						DeviceManagerListener 		listener, 
+						int 						type, 
+						Object 						value ) 
+					{
+						DeviceImpl	device = (DeviceImpl)value;
+						
+						switch( type ){
+						
+							case LT_DEVICE_ADDED:{
+								
+								listener.deviceAdded( device );
+								
+								break;
+							}
+							case LT_DEVICE_CHANGED:{
+								
+								if ( deviceAdded( device )){
+									
+									device.fireChanged();
+									
+									listener.deviceChanged( device );
+								}
+								
+								break;
+							}
+							case LT_DEVICE_ATTENTION:{
+								
+								if ( deviceAdded( device )){
+								
+									listener.deviceAttentionRequest( device );
+								}
+								
+								break;
+							}
+							case LT_DEVICE_REMOVED:{
+								
+								listener.deviceRemoved( device );
+								
+								break;
+							}
+							case LT_INITIALIZED:{
+								
+								listener.deviceManagerLoaded();
+								
+								break;
+							}
+						}
+					}
+					
+					protected boolean
+					deviceAdded(
+						Device		device )
+					{
+						synchronized( DeviceManagerImpl.this ){
+							
+							return( device_list.contains( device ));
+						}
+					}
+				});
+	
+	
+	private boolean	auto_search;
+	private int		auto_hide_old_days	= AUTO_HIDE_OLD_DAYS_DEFAULT;
+	
+	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;
+	private boolean	config_dirty;
+	
+	private int		explicit_search;
+	
+	private volatile TranscodeManagerImpl	transcode_manager;
+	
+	private CopyOnWriteList<DeviceManagerDiscoveryListener>	discovery_listeners = new CopyOnWriteList<DeviceManagerDiscoveryListener>();
+	
+	private int						getMimeType_fails;
+	
+	private Object					logger_lock = new Object();
+	private AEDiagnosticsLogger		logger;
+	
+	private AsyncDispatcher	async_dispatcher = new AsyncDispatcher( 10*1000 );
+
+	private AESemaphore			init_sem = new AESemaphore( "dm:init" );
+	
+	private volatile boolean initialized = false;
+	
+	private Object		lsn_lock			= new Object();
+	private String		local_service_name;
+	
+	protected
+	DeviceManagerImpl()
+	{
+		AEDiagnostics.addEvidenceGenerator( this );
+
+		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+			public void azureusCoreRunning(AzureusCore core) {
+				initWithCore(core);
+			}
+		});
+	}
+	
+	private TranscodeManager
+	ensureInitialised(
+		boolean 	partial )
+	{
+		AzureusCore core =  AzureusCoreFactory.getSingleton();
+		
+		if ( core.isStarted()){
+		
+			initWithCore( core );
+			
+		}else if ( core.isInitThread()){
+			
+			Debug.out( "This is bad" );
+			
+			initWithCore( core );
+		}
+		
+		if ( partial ){
+			
+			long start = SystemTime.getMonotonousTime();
+			
+			while( !init_sem.reserve(250)){
+				
+				if ( transcode_manager != null ){
+					
+					break;
+				}
+				
+				if ( SystemTime.getMonotonousTime() - start >= 30*1000 ){
+					
+					Debug.out( "Timeout waiting for init" );
+					
+					AEDiagnostics.dumpThreads();
+					
+					break;
+				}
+			}
+		}else{
+			if ( !init_sem.reserve( 30*1000 )){
+				
+				Debug.out( "Timeout waiting for init" );
+				
+				AEDiagnostics.dumpThreads();
+			}
+		}
+		
+		return( transcode_manager );
+	}
+	
+	private void 
+	initWithCore(
+		final AzureusCore core ) 
+	{
+		synchronized( this ){
+			
+			if ( azureus_core != null ){
+				
+				return;
+			}
+		
+			azureus_core = core;
+		}
+		
+		try{
+			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(
+					new String[]{
+						AUTO_SEARCH_CONFIG_KEY,
+						AUTO_HIDE_OLD_CONFIG_KEY,
+					},
+					new ParameterListener()
+					{
+						public void 
+						parameterChanged(
+							String name ) 
+						{
+							auto_search 		= COConfigurationManager.getBooleanParameter( AUTO_SEARCH_CONFIG_KEY, true );
+							auto_hide_old_days	= COConfigurationManager.getIntParameter( AUTO_HIDE_OLD_CONFIG_KEY, AUTO_HIDE_OLD_DAYS_DEFAULT );
+						}
+					});
+			
+			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 );
+	
+			upnp_manager = new DeviceManagerUPnPImpl( this );
+	
+			loadConfig();
+					
+			new DeviceiTunesManager( this );
+					
+			drive_manager = new DeviceDriveManager( this );
+			
+			transcode_manager = new TranscodeManagerImpl( this );
+			
+			transcode_manager.initialise();
+			
+			core.addLifecycleListener(
+				new AzureusCoreLifecycleAdapter()
+				{
+					public void
+					stopping(
+						AzureusCore		core )
+					{					
+						synchronized( DeviceManagerImpl.this ){
+					
+							if ( config_dirty || config_unclean ){
+								
+								saveConfig();
+							}
+							
+							closing	= true;
+							
+							transcode_manager.close();
+							
+							DeviceImpl[] devices = getDevices();
+							
+							for ( DeviceImpl device: devices ){
+								
+								device.close();
+							}
+						}
+					}
+				});
+			
+			upnp_manager.initialise();
+			
+			SimpleTimer.addPeriodicEvent(
+					"DeviceManager:update",
+					DEVICE_UPDATE_PERIOD,
+					new TimerEventPerformer()
+					{
+						private int tick_count = 0;
+						
+						public void 
+						perform(
+							TimerEvent event ) 
+						{
+							List<DeviceImpl> copy;
+							
+							tick_count++;
+							
+							transcode_manager.updateStatus( tick_count );
+							
+							synchronized( DeviceManagerImpl.this ){
+	
+								if( device_list.size() == 0 ){
+									
+									return;
+								}
+								
+								copy = new ArrayList<DeviceImpl>( device_list );
+							}
+							
+							for ( DeviceImpl device: copy ){
+								
+								device.updateStatus( tick_count );
+							}
+							
+							if ( 	auto_hide_old_days > 0 && 
+									tick_count % DEVICE_AUTO_HIDE_CHECK_TICKS == 0 ){
+								
+								long	now = SystemTime.getCurrentTime();
+								
+								int	num_hidden = 0;
+								
+								for ( DeviceImpl device: copy ){
+																		
+									if ( 	device.isLivenessDetectable() &&
+											!device.isTagged()){
+										
+										int type = device.getType();
+										
+										if ( type == Device.DT_CONTENT_DIRECTORY ){
+											
+										}else if ( type == Device.DT_MEDIA_RENDERER ){
+											
+											DeviceMediaRenderer rend = (DeviceMediaRenderer)device;
+											
+											if ( rend.getRendererSpecies() != DeviceMediaRenderer.RS_OTHER ){
+												
+												continue;
+											}
+										}else{
+											
+											continue;
+										}
+										
+										long age = now - device.getLastSeen();
+										
+										if ( age > auto_hide_old_days*24*60*60*1000L ){
+											
+											if ( !device.isHidden()){
+												
+												log( "Auto-hiding '" +  device.getName() + "'" );
+													
+												device.setHidden( true );
+
+												device.setAutoHidden( true );
+											
+												num_hidden++;
+											}
+										}else{
+											
+											if ( device.isHidden() && device.isAutoHidden()){
+												
+												log( "Auto-showing '" +  device.getName() + "'" );
+												
+												device.setAutoHidden( false );
+												
+												device.setHidden( false );
+											}
+										}
+									}
+								}
+							
+								if ( num_hidden > 0 ){
+										
+									Logger.log(					
+										new LogAlert(
+											true,
+											LogAlert.AT_INFORMATION,
+											MessageText.getString(
+												"device.autohide.alert",
+												new String[]{
+													String.valueOf( num_hidden ),
+													String.valueOf( auto_hide_old_days )
+												})));
+								}
+							}
+						}
+					});
+			
+			initialized = true;
+			
+			listeners.dispatch( LT_INITIALIZED, null );
+			
+			core.addPowerManagementListener( this );
+			
+		}finally{
+			
+			init_sem.releaseForever();
+		}
+	}
+	
+	protected void
+	manageOD()
+	{
+		DeviceImpl[] devices = getDevices();
+		
+		for ( DeviceImpl device: devices ){
+			
+			if ( device.getType() == Device.DT_OFFLINE_DOWNLOADER ){
+				
+				((DeviceOfflineDownloaderImpl)device).checkConfig();
+			}
+		}
+	}
+	
+	protected void
+	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 
+	getUPnPManager()
+	{
+		return( upnp_manager );
+	}
+	
+	public String 
+	getLocalServiceName() 
+	{
+		synchronized( lsn_lock ){
+			
+			if ( local_service_name == null ){
+				
+					// try to use the media server's name
+				
+				try{
+					local_service_name = (String)getUPnPManager().getUPnPAVIPC().invoke( "getServiceName", new Object[]{});
+									
+				}catch( Throwable e ){
+				}
+				
+				if ( local_service_name == null ){
+					
+					local_service_name = Constants.APP_NAME;
+					
+					try{
+						String cn = PlatformManagerFactory.getPlatformManager().getComputerName();
+						
+						if ( cn != null && cn.length() > 0 ){
+						
+							local_service_name += " on " + cn;
+						}
+					}catch( Throwable e ){
+					}
+				}
+			}
+			
+			return( local_service_name );
+		}
+	}
+	
+	public boolean
+	isTiVoEnabled()
+	{
+		return( tivo_manager.isEnabled());
+	}
+	
+	public void
+	setTiVoEnabled(
+		boolean	enabled )
+	{
+		tivo_manager.setEnabled( enabled );
+	}
+	
+	public TranscodeProvider[]
+	getProviders()
+	{
+		TranscodeManager tm = ensureInitialised( true );
+		
+		if ( tm == null ){
+			
+			return( new TranscodeProvider[0] );
+		}
+		
+		return( tm.getProviders());
+	}
+	
+	public DeviceTemplate[] 
+	getDeviceTemplates(
+		int		device_type )
+	{
+		if ( transcode_manager == null || device_type != Device.DT_MEDIA_RENDERER ){
+			
+			return( new DeviceTemplate[0] );
+		}
+		
+		TranscodeProvider[] providers = transcode_manager.getProviders();
+		
+		List<DeviceTemplate> result = new ArrayList<DeviceTemplate>();
+		
+		for ( TranscodeProvider provider: providers ){
+			
+			TranscodeProfile[] profiles = provider.getProfiles();
+			
+			Map<String,DeviceMediaRendererTemplateImpl>	class_map = new HashMap<String, DeviceMediaRendererTemplateImpl>();
+			
+			for ( TranscodeProfile profile: profiles ){
+				
+				String	classification = profile.getDeviceClassification();
+				
+				if ( classification.startsWith( "apple." )){
+					
+					classification = "apple.";
+				}
+				
+				boolean	auto = 
+					classification.equals( "sony.PS3" ) ||
+					classification.equals( "microsoft.XBox" ) ||
+					classification.equals( "apple." ) ||
+					classification.equals( "nintendo.Wii" ) ||
+					classification.equals( "browser.generic" );
+				
+				DeviceMediaRendererTemplateImpl temp = class_map.get( classification );
+				
+				if ( temp == null ){
+					
+					temp = new DeviceMediaRendererTemplateImpl( this, classification, auto );
+					
+					class_map.put( classification, temp );
+					
+					result.add( temp );
+				}
+				
+				temp.addProfile( profile );
+			}
+		}
+		
+		return( result.toArray( new DeviceTemplate[ result.size() ]));
+	}
+	
+	public DeviceManufacturer[] 
+  	getDeviceManufacturers(
+  		int		device_type )
+	{
+		DeviceTemplate[] templates = getDeviceTemplates( device_type );
+		
+		Map<String,DeviceManufacturerImpl>	map = new HashMap<String, DeviceManufacturerImpl>();
+		
+		for ( DeviceTemplate template: templates ){
+			
+			if ( template.getType() != device_type ){
+				
+				continue;
+			}
+			
+			String	man_str = template.getManufacturer();
+			
+			DeviceManufacturerImpl man = map.get( man_str );
+			
+			if ( man == null ){
+				
+				man = new DeviceManufacturerImpl( man_str );
+				
+				map.put( man_str, man );
+			}
+			
+			man.addTemplate( template );
+		}
+		
+		return( map.values().toArray( new DeviceManufacturer[ map.size() ] ));
+	}
+	
+	public Device 
+	addVirtualDevice(
+		int 		type, 
+		String		uid,
+		String		classification,
+		String		name )
+	
+		throws DeviceManagerException
+	{
+		return( createDevice( type, uid, classification, name, true ));
+	}
+	
+	public Device 
+	addInetDevice(
+		int 		type, 
+		String		uid,
+		String		classification,
+		String		name,
+		InetAddress address)
+	
+		throws DeviceManagerException
+	{
+		Device device = createDevice( type, uid, classification, name, false );
+		device.setAddress(address);
+		return device;
+	}
+	
+	protected Device
+	createDevice(
+		int						device_type,
+		String					uid,
+		String					classification,
+		String					name,
+		boolean					manual )
+	
+		throws DeviceManagerException
+	{
+		if ( device_type == Device.DT_MEDIA_RENDERER ){
+			
+			DeviceImpl res;
+			
+			if ( manual ){
+				
+				res = new DeviceMediaRendererManual( this, uid, classification, true, name );
+				
+			}else{
+				
+				res = new DeviceMediaRendererImpl( this, uid, classification, true, name );
+			}
+			
+			res = addDevice( res );
+			
+			return( res );
+			
+		}else{
+			
+			throw( new DeviceManagerException( "Can't manually create this device type" ));
+		}
+	}
+	
+	public void
+	search(
+		final int					millis,
+		final DeviceSearchListener	listener )
+	{
+		new AEThread2( "DM:search", true )
+		{
+			public void
+			run()
+			{
+				synchronized( DeviceManagerImpl.this ){
+				
+					explicit_search++;
+				}
+				
+				tivo_manager.search();
+				
+				drive_manager.search();
+				
+				AESemaphore	sem = new AESemaphore( "DM:search" );
+				
+				DeviceManagerListener	dm_listener =
+					new DeviceManagerListener()
+					{
+						public void
+						deviceAdded(
+							Device		device )
+						{
+							listener.deviceFound( device );
+						}
+						
+						public void
+						deviceChanged(
+							Device		device )
+						{
+						}
+						
+						public void
+						deviceAttentionRequest(
+							Device		device )
+						{	
+						}
+						
+						public void
+						deviceRemoved(
+							Device		device )
+						{
+						}
+
+						public void 
+						deviceManagerLoaded() {
+						}
+					};
+					
+				try{
+					addListener( dm_listener );
+				
+					upnp_manager.search();
+					
+					sem.reserve( millis );
+					
+				}finally{
+					
+					synchronized( DeviceManagerImpl.this ){
+						
+						explicit_search--;
+					}
+					
+					removeListener( dm_listener );
+					
+					listener.complete();
+				}
+			}
+		}.start();
+	}
+	
+	protected DeviceImpl
+	getDevice(
+		String		id )
+	{
+		synchronized( this ){
+
+			return( device_map.get( id ));
+		}
+	}
+	
+	protected DeviceImpl
+	addDevice(
+		DeviceImpl		device )
+	{
+		return( addDevice( device, true ));
+	}
+	
+	protected DeviceImpl
+	addDevice(
+		DeviceImpl		device,
+		boolean			is_alive )
+	{
+			// for xbox (currently) we automagically replace a manual entry with an auto one as we may have
+			// added the manual one when receiving a previous browse before getting the UPnP renderer details
+			
+		DeviceImpl	existing = null;
+		
+		synchronized( this ){
+						
+			existing = device_map.get( device.getID());
+			
+			if ( existing != null ){
+				
+				existing.updateFrom( device, is_alive );
+												
+			}else{
+			
+				if ( device.getType() == Device.DT_MEDIA_RENDERER ){
+					
+					DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
+					
+					if ( renderer.getRendererSpecies() == DeviceMediaRenderer.RS_XBOX && !renderer.isManual()){
+						
+						for ( DeviceImpl d: device_list ){
+							
+							if ( d.getType() == Device.DT_MEDIA_RENDERER ){
+								
+								DeviceMediaRenderer r = (DeviceMediaRenderer)d;
+								
+								if ( r.getRendererSpecies() == DeviceMediaRenderer.RS_XBOX && r.isManual()){
+									
+									existing = d;
+
+									log( "Merging " + device.getString() + " -> " + existing.getString());
+										
+									String	secondary_id = device.getID();
+									
+									existing.setSecondaryID( secondary_id );
+									
+									existing.updateFrom( device, is_alive );
+								}
+							}
+						}
+					}
+				}
+			}
+			
+			if ( existing == null ){
+			
+				device_list.add( device );
+				
+				device_map.put( device.getID(), device );
+			}
+		}
+		
+		if ( existing != null ){
+			
+				// don't trigger config save here, if anything has changed it will have been handled
+				// by the updateFrom call above
+			
+			// if anything has changed then the updateFrom methods should have indicated this
+			// so there's no need to blindly fire a change event here
+			// deviceChanged( existing, false );
+			
+			applyUpdates( existing );
+			
+			return( existing );
+		}
+		
+		try{
+			disable_events.add( device );
+		
+			device.initialise();
+			
+			if ( is_alive ){
+			
+				device.alive();
+			}
+			
+			applyUpdates( device );
+			
+		}finally{
+			
+			disable_events.remove( device );
+		}
+		deviceAdded( device );
+		
+		configDirty();
+		
+		return( device );
+	}
+	
+	protected void
+	applyUpdates(
+		DeviceImpl		device )
+	{
+		if ( device.getType() == Device.DT_MEDIA_RENDERER ){
+			
+			DeviceMediaRenderer renderer = (DeviceMediaRenderer)device;
+			
+			if ( renderer instanceof DeviceUPnPImpl ){
+				
+				UPnPDevice upnp_device = ((DeviceUPnPImpl)renderer).getUPnPDevice();
+				
+				if ( upnp_device != null ){
+					
+					String lc_manufacturer 	= getOptionalLC( upnp_device.getManufacturer());
+					String lc_model			= getOptionalLC( upnp_device.getModelName());
+					String lc_fname			= getOptionalLC( upnp_device.getFriendlyName());
+					
+					if ( lc_manufacturer.startsWith( "samsung" )){
+						
+						device.setPersistentStringProperty( DeviceImpl.PP_REND_CLASSIFICATION, "samsung.generic" );
+						
+						TranscodeProfile[] profiles = device.getTranscodeProfiles();
+						
+						if ( profiles.length == 0 ){
+							
+							device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_NEVER );
+							
+						}else{
+							
+							device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_WHEN_REQUIRED );
+						}
+					}else if ( lc_manufacturer.startsWith( "western digital" )){
+							
+							device.setPersistentStringProperty( DeviceImpl.PP_REND_CLASSIFICATION, "western.digital.generic" );
+							
+							TranscodeProfile[] profiles = device.getTranscodeProfiles();
+							
+							if ( profiles.length == 0 ){
+								
+								device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_NEVER );
+								
+							}else{
+								
+								device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_WHEN_REQUIRED );
+							}
+					}else if ( lc_manufacturer.startsWith( "sony" ) && lc_fname.startsWith( "bravia" )){
+							
+						device.setPersistentStringProperty( DeviceImpl.PP_REND_CLASSIFICATION, "sony.bravia" );
+							
+					}else if ( lc_model.equals( "windows media player" )){
+						
+						String model_number = upnp_device.getModelNumber();
+						
+						if ( model_number != null ){
+							
+							try{
+								int num = Integer.parseInt( model_number );
+								
+								if ( num >= 12 ){
+									
+									device.setPersistentStringProperty( DeviceImpl.PP_REND_CLASSIFICATION, "ms_wmp.generic" );
+									
+									TranscodeProfile[] profiles = device.getTranscodeProfiles();
+									
+									if ( profiles.length == 0 ){
+										
+										device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_NEVER );
+										
+									}else{
+										
+										device.setTranscodeRequirement( TranscodeTarget.TRANSCODE_WHEN_REQUIRED );
+									}
+								}
+							}catch( Throwable e ){
+								
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	private String
+	getOptionalLC(
+		String	str )
+	{
+		if ( str == null ){
+			
+			return( "" );
+		}
+		
+		return( str.toLowerCase().trim());
+	}
+	
+	protected void
+	removeDevice(
+		DeviceImpl		device )
+	{
+		synchronized( this ){
+			
+			DeviceImpl existing = device_map.remove( device.getID());
+			
+			if ( existing == null ){
+				
+				return;
+			}
+			
+			device_list.remove( device );
+			
+			String secondary_id = device.getSecondaryID();
+			
+			if ( secondary_id != null ){
+				
+				device_map.remove( secondary_id );
+			}
+		}
+		
+		device.destroy();
+		
+		deviceRemoved( device );
+		
+		configDirty();
+	}
+
+	public boolean
+	isBusy(
+		int	device_type )
+	{
+			// transcoding is rolled into renderers
+		
+		if ( device_type == Device.DT_UNKNOWN || device_type == Device.DT_MEDIA_RENDERER ){
+			
+			if ( getTranscodeManager().getQueue().isTranscoding()){
+				
+				return( true );
+			}
+		}
+		
+		DeviceImpl[] devices = getDevices();
+					
+		for ( DeviceImpl device: devices ){
+			
+			if ( device.isBusy()){
+				
+				if ( device_type == Device.DT_UNKNOWN || device_type == device.getType()){
+				
+					return( true );
+				}
+			}
+		}
+		
+		return( false );
+	}
+	
+	public DeviceImpl[]
+  	getDevices()
+	{
+		synchronized( this ){
+			
+			return( device_list.toArray( new DeviceImpl[ device_list.size()] ));
+		}
+	}
+  		
+	public boolean
+	getAutoSearch()
+	{
+		return( auto_search );
+	}
+	
+	public void
+	setAutoSearch(
+		boolean	auto )
+	{
+		COConfigurationManager.setParameter( AUTO_SEARCH_CONFIG_KEY, auto );
+	}
+	
+	public int
+	getAutoHideOldDevicesDays()
+	{
+		return( COConfigurationManager.getIntParameter( AUTO_HIDE_OLD_CONFIG_KEY, AUTO_HIDE_OLD_DAYS_DEFAULT ));
+	}
+	
+	public void
+	setAutoHideOldDevicesDays(
+		int		days )
+	{
+		COConfigurationManager.setParameter( AUTO_HIDE_OLD_CONFIG_KEY, days );
+	}
+	
+	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());
+	}
+	
+		// 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
+	getOfflineDownloadingIsAuto()
+	{
+		return( od_is_auto );
+	}
+	
+	public void
+	setOfflineDownloadingIsAuto(
+		boolean		auto )
+	{
+		COConfigurationManager.setParameter( OD_IS_AUTO_CONFIG_KEY, auto );
+	}
+
+	public boolean
+	getOfflineDownloadingIncludePrivate()
+	{
+		return( od_include_private );	
+	}
+	
+	public void
+	setOfflineDownloadingIncludePrivate(
+		boolean		include )
+	{
+		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
+	removeManualDownloads(
+		Download[]		downloads )
+	{
+		for ( Download d: downloads ){
+			
+			d.setBooleanAttribute( od_manual_ta, false );
+		}
+		
+		manageOD();
+	}
+	
+		// sdsd
+	
+	protected boolean
+	isExplicitSearch()
+	{
+		synchronized( this ){
+			
+			return( explicit_search > 0 );
+		}
+	}
+	
+	protected boolean
+	isClosing()
+	{
+		synchronized( this ){
+		
+			return( closing );
+		}
+	}
+	
+	protected void
+	loadConfig()
+	{
+		if ( !FileUtil.resilientConfigFileExists( CONFIG_FILE )){
+			
+			return;
+		}
+		
+		log( "Loading configuration" );
+				
+		synchronized( this ){
+			
+			Map map = FileUtil.readResilientConfigFile( CONFIG_FILE );
+			
+			List	l_devices = (List)map.get( "devices" );
+			
+			if ( l_devices != null ){
+				
+				for (int i=0;i<l_devices.size();i++){
+					
+					Map	m = (Map)l_devices.get(i);
+					
+					try{
+						DeviceImpl device = DeviceImpl.importFromBEncodedMapStatic(this,  m );
+						
+						device_list.add( device );
+						
+						device_map.put( device.getID(), device );
+						
+						String secondary_id = device.getSecondaryID();
+						
+						if ( secondary_id != null ){
+							
+							device_map.put( secondary_id, device );
+						}
+							
+						device.initialise();
+					
+						log( "    loaded " + device.getString());
+						
+					}catch( Throwable e ){
+						
+						log( "Failed to import subscription from " + m, e );
+					}
+				}
+			}
+		}
+	}
+	
+	protected void
+	configDirty(
+		DeviceImpl		device,
+		boolean			save_changes )
+	{
+		deviceChanged( device, save_changes );
+	}
+	
+	protected void
+	configDirty()
+	{
+		synchronized( this ){
+			
+			if ( config_dirty ){
+				
+				return;
+			}
+			
+			config_dirty = true;
+		
+			new DelayedEvent( 
+				"Subscriptions:save", 5000,
+				new AERunnable()
+				{
+					public void 
+					runSupport() 
+					{
+						synchronized( DeviceManagerImpl.this ){
+							
+							if ( !config_dirty ){
+
+								return;
+							}
+							
+							saveConfig();
+						}	
+					}
+				});
+		}
+	}
+	
+	protected void
+	saveConfig()
+	{
+		log( "Saving configuration" );
+		
+		synchronized( this ){
+			
+			if ( closing ){
+				
+					// to late to try writing
+				
+				return;
+			}
+			
+			config_dirty 	= false;
+			config_unclean	= false;
+			
+			if ( device_list.size() == 0 ){
+				
+				FileUtil.deleteResilientConfigFile( CONFIG_FILE );
+				
+			}else{
+				
+				Map map = new HashMap();
+				
+				List	l_devices = new ArrayList();
+				
+				map.put( "devices", l_devices );
+				
+				Iterator<DeviceImpl>	it = device_list.iterator();
+				
+				while( it.hasNext()){
+					
+					DeviceImpl device = it.next();
+						
+					try{
+						Map d = new HashMap();
+						
+						device.exportToBEncodedMap( d, false );
+						
+						l_devices.add( d );
+						
+					}catch( Throwable e ){
+						
+						log( "Failed to save device " + device.getString(), e );
+					}
+				}
+				
+				FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
+			}
+		}
+	}
+	
+	protected void
+	deviceAdded(
+		DeviceImpl		device )
+	{
+		configDirty();
+		
+		// I'd rather put this in a listener, but for now this will ensure
+		// it gets QOS'd even before any listeners are added
+		
+		try{
+			PlatformDevicesMessenger.qosFoundDevice(device);
+			
+		}catch( Throwable e ){
+			
+			Debug.out(e);
+		}
+		
+		listeners.dispatch( LT_DEVICE_ADDED, device );
+	}
+	
+	
+	protected void
+	deviceChanged(
+		DeviceImpl		device,
+		boolean			save_changes )
+	{
+		if ( save_changes ){
+			
+			configDirty();
+			
+		}else{
+			
+			synchronized( this ){
+
+				config_unclean = true;
+			}
+		}
+			
+		if ( !disable_events.contains( device )){
+		
+			//System.out.println(System.currentTimeMillis() + "] CHANGE -> " + device.getID() + "/" + device.getName() + " via " + Debug.getCompressedStackTrace());
+			
+			listeners.dispatch( LT_DEVICE_CHANGED, device );
+		}
+	}
+	
+	protected void
+	deviceRemoved(
+		DeviceImpl		device )
+	{
+		configDirty();
+		
+		listeners.dispatch( LT_DEVICE_REMOVED, device );
+	}
+	
+	protected void
+	requestAttention(
+		DeviceImpl		device )
+	{
+		listeners.dispatch( LT_DEVICE_ATTENTION, device );
+	}
+	
+	protected URL
+	getStreamURL(
+		TranscodeFileImpl		file,
+		String					host )
+	{
+		IPCInterface ipc = upnp_manager.getUPnPAVIPC();
+		
+		if ( ipc != null ){
+
+			try{
+				DiskManagerFileInfo f = file.getTargetFile();
+				
+				String str = (String)ipc.invoke( "getContentURL", new Object[]{ f });
+				
+				if ( str != null && str.length() > 0 ){
+					
+					if ( host != null ){
+						
+						str = str.replace( "127.0.0.1", host );
+					}
+					
+					return( new URL( str ));
+				}
+			}catch( Throwable e ){
+				
+			}
+		}
+		
+		return( null );
+	}
+	
+	protected String
+	getMimeType(
+		TranscodeFileImpl		file )
+	{
+		if ( getMimeType_fails > 5 ){
+			
+			return( null );
+		}
+		
+		IPCInterface ipc = upnp_manager.getUPnPAVIPC();
+		
+		if ( ipc != null ){
+
+			try{
+				DiskManagerFileInfo f = file.getTargetFile();
+				
+				String str = (String)ipc.invoke( "getMimeType", new Object[]{ f });
+				
+				if ( str != null && str.length() > 0 ){
+					
+					return( str );
+				}
+			}catch( Throwable e ){
+				
+				getMimeType_fails++;
+				
+				e.printStackTrace();
+			}
+		}
+		
+		return( null );
+	}
+	
+	public File
+	getDefaultWorkingDirectory()
+	{
+		return( getDefaultWorkingDirectory( false ));
+	}
+	
+	public File
+	getDefaultWorkingDirectory(
+		boolean		persist )
+	{
+		String def = COConfigurationManager.getStringParameter( CONFIG_DEFAULT_WORK_DIR, "" ).trim();
+		
+		if ( def.length() == 0 ){
+			
+			String	def_dir = COConfigurationManager.getStringParameter( "Default save path" );
+
+			def = def_dir + File.separator + TRANSCODE_DIR_DEFAULT;
+		}
+		
+		File f = new File( def );
+		
+		if ( !f.exists()){
+		
+				// migration from Azureus Downloads to Vuze Downloads
+			
+			if ( f.getName().equals( TRANSCODE_DIR_DEFAULT )){
+				
+				String	parent = f.getParentFile().getName();
+				
+				if ( parent.equals( "Azureus Downloads" ) || parent.equals( "Vuze Downloads" )){
+					
+					String	def_dir = COConfigurationManager.getStringParameter( "Default save path" );
+
+					f = new File( def_dir, TRANSCODE_DIR_DEFAULT );
+				}
+			}
+			if ( persist ){
+			
+				f.mkdirs();
+			}
+		}
+		
+		return( f );
+	}
+	
+	public void
+	setDefaultWorkingDirectory(
+		File		dir )
+	{
+		File existing = getDefaultWorkingDirectory( false );
+		
+		if ( !existing.getAbsolutePath().equals( dir.getAbsolutePath())){
+			
+				// default has changed, reset all device save locations so that they pick up the change
+				
+			DeviceImpl[] devices = getDevices();
+			
+			for ( DeviceImpl device: devices ){
+		
+				device.resetWorkingDirectory();
+			}
+		}
+		
+		COConfigurationManager.setParameter( CONFIG_DEFAULT_WORK_DIR, dir.getAbsolutePath());
+	}
+	
+	public boolean
+	getDisableSleep()
+	{
+		return( COConfigurationManager.getBooleanParameter( CONFIG_DISABLE_SLEEP, true ));
+	}
+	
+	public void
+	setDisableSleep(
+		boolean		b )
+	{
+		COConfigurationManager.setParameter( CONFIG_DISABLE_SLEEP, b );
+	}
+	
+	public TranscodeManagerImpl
+	getTranscodeManager()
+	{
+		if ( transcode_manager == null ){
+			
+			ensureInitialised( false );
+		}
+		
+		return( transcode_manager );
+	}
+	
+	public UnassociatedDevice[]
+	getUnassociatedDevices()
+	{
+		return( upnp_manager.getUnassociatedDevices());
+	}
+	
+	public String
+	getPowerName()
+	{
+		return( "Transcode" );
+	}
+	
+	public boolean
+	requestPowerStateChange(
+		int		new_state,
+		Object	data )
+	{
+		if ( getDisableSleep()){
+			
+			if ( getTranscodeManager().getQueue().isTranscoding()){
+				
+				return( false );
+			}
+		}
+		
+		return( true );
+	}
+
+	public void
+	informPowerStateChange(
+		int		new_state,
+		Object	data )
+	{
+		
+	}
+	
+  	public void
+  	addListener(
+  		DeviceManagerListener		listener )
+  	{
+  		listeners.addListener( listener );
+  		
+  		if (initialized) {
+
+  			listeners.dispatch( listener, LT_INITIALIZED, null );
+  		}
+  	}
+  	
+	protected boolean
+	browseReceived(
+		TrackerWebPageRequest		request,
+		Map<String,Object>			browser_args )
+	{
+		for ( DeviceManagerDiscoveryListener l: discovery_listeners ){
+			
+			try{
+				if ( l.browseReceived( request, browser_args )){
+									
+					return( true );
+				}
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+		
+		return( false );
+	}
+	
+	protected VuzeFile
+	exportVuzeFile(
+		DeviceImpl		device )
+	
+		throws IOException
+	{
+		VuzeFile	vf = VuzeFileHandler.getSingleton().create();
+		
+		Map	map = new HashMap();
+		
+		Map device_map = new HashMap();
+		
+		map.put( "device", device_map );
+		
+		device.exportToBEncodedMap( device_map, true );
+		
+		vf.addComponent( VuzeFileComponent.COMP_TYPE_DEVICE, map );
+		
+		return( vf );
+	}
+	
+	private void
+	importVuzeFile(
+		Map			map,
+		boolean		warn_user )
+	{
+		Map	m = (Map)map.get( "device" );
+					
+		try{
+			DeviceImpl device = DeviceImpl.importFromBEncodedMapStatic( this, m );
+			
+			DeviceImpl existing;
+			
+			synchronized( this ){
+				
+				existing = device_map.get( device.getID());
+			}
+			
+			if ( existing == null ){
+				
+				if ( warn_user ){
+					
+					UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+		
+					String details = MessageText.getString(
+							"device.import.desc",
+							new String[]{ device.getName()});
+					
+					long res = ui_manager.showMessageBox(
+							"device.import.title",
+							"!" + details + "!",
+							UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+					
+					if ( res != UIManagerEvent.MT_YES ){	
+					
+						return;
+					}
+				}
+				
+				addDevice( device, false );
+				
+			}else{
+				
+				if ( warn_user ){
+					
+					UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+					
+					String details = MessageText.getString(
+							"device.import.dup.desc",
+							new String[]{ existing.getName()});
+					
+					ui_manager.showMessageBox(
+							"device.import.dup.title",
+							"!" + details + "!",
+							UIManagerEvent.MT_OK );
+				}
+				
+			}
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+	}
+	
+	public void
+	addDiscoveryListener(
+		DeviceManagerDiscoveryListener	listener )
+	{
+		discovery_listeners.add( listener );
+	}
+	
+	public void
+	removeDiscoveryListener(
+		DeviceManagerDiscoveryListener	listener )
+	{
+		discovery_listeners.remove( listener );
+	}
+  	
+  	public void
+  	removeListener(
+  		DeviceManagerListener		listener )
+  	{
+  		listeners.removeListener( listener );
+  	}
+  	
+  public Device findDevice(UPnPDevice upnpDevice) {
+  	DeviceImpl[] devices = getDevices();
+  	for (DeviceImpl device : devices) {
+			if (device instanceof DeviceUPnPImpl) {
+				DeviceUPnPImpl deviceUPnP = (DeviceUPnPImpl) device;
+				UPnPDevice uPnPDevice2 = deviceUPnP.getUPnPDevice();
+				if (upnpDevice.equals(uPnPDevice2)) {
+					return device;
+				}
+			}
+		}
+  	return null;
+  }
+  	
+	protected AEDiagnosticsLogger
+	getLogger()
+	{
+		synchronized( logger_lock ){
+			
+			if ( logger == null ){
+				
+				logger = AEDiagnostics.getLogger( LOGGER_NAME );
+			}
+			
+			return( logger );
+		}
+	}
+	
+	public void 
+	log(
+		String 		s,
+		Throwable 	e )
+	{
+		AEDiagnosticsLogger diag_logger = getLogger();
+		
+		diag_logger.log( s );
+		diag_logger.log( e );
+	}
+	
+	public void 
+	log(
+		String 	s )
+	{
+		AEDiagnosticsLogger diag_logger = getLogger();
+		
+		diag_logger.log( s );
+	}
+ 	
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		writer.println( "Devices" );
+			
+		try{
+			writer.indent();
+			
+			DeviceImpl[] devices = getDevices();
+			
+			for ( DeviceImpl device: devices ){
+				
+				device.generate( writer );
+			}
+			
+			if ( transcode_manager != null ){
+			
+				transcode_manager.generate( writer );
+			}
+		}finally{
+			
+			writer.exdent();
+		}
+	}
+	
+	protected static class
+	DeviceManufacturerImpl
+		implements DeviceManufacturer
+	{
+		private String 	name;
+		
+		private List<DeviceTemplate>	templates = new ArrayList<DeviceTemplate>();
+		
+		protected
+		DeviceManufacturerImpl(
+			String		_name )
+		{
+			name	= _name;
+		}
+		
+		protected void
+		addTemplate(
+			DeviceTemplate	t )
+		{
+			templates.add( t );
+		}
+		
+		public String
+		getName()
+		{
+			return( name );
+		}
+		
+		public DeviceTemplate[]
+		getDeviceTemplates()
+		{
+			return( templates.toArray( new DeviceTemplate[ templates.size()] ));
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerRSSFeed.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerRSSFeed.java
index 241f706..a9094dd 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerRSSFeed.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerRSSFeed.java
@@ -1,511 +1,510 @@
-/*
- * 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.devices.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.net.URLDecoder;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-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.XMLEscapeWriter;
-import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
-import org.gudy.azureus2.plugins.torrent.Torrent;
-import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
-import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;
-
-import com.aelitis.azureus.core.devices.Device;
-import com.aelitis.azureus.core.devices.DeviceManager;
-import com.aelitis.azureus.core.rssgen.RSSGeneratorPlugin;
-import com.aelitis.azureus.core.tag.Tag;
-import com.aelitis.azureus.core.tag.TagManager;
-import com.aelitis.azureus.core.tag.TagManagerFactory;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-
-import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
-
-public class 
-DeviceManagerRSSFeed 
-	implements RSSGeneratorPlugin.Provider
-{
-	private static final String PROVIDER = "devices";
-	
-	private DeviceManagerImpl		manager;
-		
-	private RSSGeneratorPlugin		generator;
-	
-	protected
-	DeviceManagerRSSFeed(
-		DeviceManagerImpl	_manager )
-	{
-		manager 	= _manager;
-		generator	= RSSGeneratorPlugin.getSingleton();
-		
-		if ( generator != null ){
-		
-			generator.registerProvider( PROVIDER, this );
-		}
-	}
-		
-	public boolean
-	isEnabled()
-	{
-		return( manager.isRSSPublishEnabled());
-	}
-	
-	public String
-	getFeedURL()
-	{
-		return( generator==null?"Feature Disabled":( 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);
-		
-		DeviceImpl[] devices = manager.getDevices();
-		
-		OutputStream os = response.getOutputStream();
-
-		XMLEscapeWriter pw = new XMLEscapeWriter( new PrintWriter(new OutputStreamWriter( os, "UTF-8" )));
-
-		pw.setEnabled( false );
-
-		boolean hide_generic = COConfigurationManager.getBooleanParameter( DeviceManager.CONFIG_VIEW_HIDE_REND_GENERIC, true );
-		
-		boolean show_only_tagged = COConfigurationManager.getBooleanParameter( DeviceManager.CONFIG_VIEW_SHOW_ONLY_TAGGED, false);
-
-		if ( path.length() <= 1 ){
-			
-			response.setContentType( "text/html; charset=UTF-8" );
-			
-			pw.println( "<HTML><HEAD><TITLE>Vuze Device Feeds</TITLE></HEAD><BODY>" );
-			
-			for ( DeviceImpl d: devices ){
-			
-				if ( 	d.getType() != Device.DT_MEDIA_RENDERER || 
-						d.isHidden() || 
-						!d.isRSSPublishEnabled() || 
-						( hide_generic && d.isNonSimple()) || 
-						( show_only_tagged && !d.isTagged())){
-					
-					continue;
-				}
-
-				String	name = d.getName();
-							
-				String	device_url = PROVIDER + "/" + URLEncoder.encode( name, "UTF-8" );
-				
-				pw.println( "<LI><A href=\"" + device_url + "\">" + name + "</A>  -  <font size=\"-1\"><a href=\"" + device_url + "?format=html\">html</a></font></LI>" );
-			}
-			
-			pw.println( "</BODY></HTML>" );
-			
-		}else{
-			
-			String	device_name = URLDecoder.decode( path.substring( 1 ), "UTF-8" );
-			
-			DeviceImpl	device = null;
-			
-			for ( DeviceImpl d: devices ){
-				
-				if ( d.getName().equals( device_name ) && d.isRSSPublishEnabled()){
-					
-					device = d;
-					
-					break;
-				}
-			}
-			
-			if ( device == null ){
-				
-				response.setReplyStatus( 404 );
-				
-				return( true );
-			}
-			
-			TranscodeFileImpl[] _files = device.getFiles();
-			
-			List<TranscodeFileImpl>	files = new ArrayList<TranscodeFileImpl>( _files.length );
-			
-			files.addAll( Arrays.asList( _files ));
-			
-			Collections.sort(
-				files,
-				new Comparator<TranscodeFileImpl>()
-				{
-					public int  
-					compare(
-						TranscodeFileImpl f1, 
-						TranscodeFileImpl f2) 
-					{
-						long	added1 = f1.getCreationDateMillis()/1000;
-						long	added2 = f2.getCreationDateMillis()/1000;
-
-						return((int)(added2 - added1 ));
-					}
-				});
-			
-			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();
-			}
-			
-			String channel_title = "Vuze Device: " + escape( device.getName());
-
-			boolean	html = request.getURL().contains( "format=html" );
-
-			if ( html ){
-				
-				response.setContentType( "text/html; charset=UTF-8" );
-				
-				pw.println( "<HTML><HEAD><TITLE>" + channel_title + "</TITLE></HEAD><BODY>" );
-
-				
-				for ( TranscodeFileImpl file: files ){
-					
-		  			if ( !file.isComplete()){
-		  					
-		  				if ( !file.isTemplate()){
-		  						
-		  					continue;
-		  				}
-		  			}
-	  				
-	  				URL stream_url = file.getStreamURL( feed_url.getHost() );
-	  				
-	  				if ( stream_url != null ){
-	  					
-	  					String url_ext = stream_url.toExternalForm();
-	  						
-	  					pw.println( "<p>" );
-	  					
-	  					pw.println( "<a href=\"" + url_ext + "\">" + escape( file.getName()) + "</a>" );
-	  						
-	  					url_ext += url_ext.indexOf('?') == -1?"?":"&";
-	  					
-	  					url_ext += "action=download";
-	  					
-	  					pw.println( "  -  <font size=\"-1\"><a href=\"" + url_ext + "\">save</a></font>" );
-
-	  				}
-				}
-
-				pw.println( "</BODY></HTML>" );
-				
-			}else{
-				boolean	debug = request.getURL().contains( "format=debug" );
-				
-				if ( debug ){
-					
-					response.setContentType( "text/html; charset=UTF-8" );
-					
-					pw.println( "<HTML><HEAD><TITLE>" + channel_title + "</TITLE></HEAD><BODY>" );
-					
-					pw.println( "<pre>" );
-					
-					pw.setEnabled( true );
-					
-				}else{
-					
-					response.setContentType( "application/xml" );
-				}
-				
-				try{
-					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>" );
-											
-					pw.println( "<title>" + channel_title + "</title>" );
-					pw.println( "<link>http://vuze.com</link>" );
-					pw.println( "<atom:link href=\"" + feed_url.toExternalForm() + "\" rel=\"self\" type=\"application/rss+xml\" />" );
-					
-					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>");
-					
-							
-
-												
-					String	feed_date_key = "devices.feed_date." + device.getID();
-					
-					long feed_date = COConfigurationManager.getLongParameter( feed_date_key );
-		
-					boolean new_date = false;
-					
-					for ( TranscodeFileImpl file: files ){
-						
-						long	file_date = file.getCreationDateMillis();
-						
-						if ( file_date > feed_date ){
-							
-							new_date = true;
-							
-							feed_date = file_date;
-						}
-					}
-					
-					if ( new_date ){
-						
-						COConfigurationManager.setParameter( feed_date_key, feed_date );
-					}
-					
-					pw.println(	"<pubDate>" + TimeFormatter.getHTTPDate( feed_date ) + "</pubDate>" );
-		
-					for ( TranscodeFileImpl file: files ){
-												
-			  			if ( !file.isComplete()){
-			  					
-			  				if ( !file.isTemplate()){
-			  						
-			  					continue;
-			  				}
-			  			}
-			  		
-						try{
-			  				pw.println( "<item>" );
-			  				
-			  				pw.println( "<title>" + escape( file.getName()) + "</title>" );
-			  								
-			  				pw.println(	"<pubDate>" + TimeFormatter.getHTTPDate( file.getCreationDateMillis()) + "</pubDate>" );
-			  				
-			  				pw.println( "<guid isPermaLink=\"false\">" + escape( file.getKey()) + "</guid>" );
-			  				
-			  				String[] categories = file.getCategories();
-			  				
-			  				for ( String category: categories ){
-			  					
-			  					pw.println( "<category>" + escape(category) + "</category>" );
-			  				}
-			  				
-			  				String[] tags = file.getTags( true );
-			  				
-			  				for ( String tag: tags ){
-			  					
-			  					pw.println( "<tag>" + escape( tag ) + "</tag>" );
-			  				}
-			  				
-			  				String mediaContent = "";
-			  				
-			  				URL stream_url = file.getStreamURL( feed_url.getHost() );
-			  				
-			  				if ( stream_url != null ){
-			  					
-			  					String url_ext = stream_url.toExternalForm();
-			  					
-			  					long fileSize = file.getTargetFile().getLength();
-			  					
-			  					pw.println( "<link>" + url_ext + "</link>" );
-			  					
-			  					mediaContent = "<media:content medium=\"video\" fileSize=\"" +
-													fileSize + "\" url=\"" + url_ext + "\""; 
-			  					
-			  					String	mime_type = file.getMimeType();
-			  					
-			  					if ( mime_type != null ){
-			  						
-			  						mediaContent += " type=\"" + mime_type + "\"";
-			  					}
-			  				
-								pw.println("<enclosure url=\"" + url_ext
-										+ "\" length=\"" + fileSize
-										+ (mime_type == null ? "" : "\" type=\"" + mime_type)
-										+ "\"></enclosure>");		
-			  				}
-			  				
-			   				String	thumb_url		= null;
-			  				String	author			= null;
-			  				String	description		= null;
-			  				
-			  				try{
-			  					Torrent torrent = file.getSourceFile().getDownload().getTorrent();
-			  				
-			  					TOTorrent toTorrent = PluginCoreUtils.unwrap(torrent);
-							
-			  					long duration_secs = PlatformTorrentUtils.getContentVideoRunningTime(toTorrent);
-			  					
-			  					if ( mediaContent.length() > 0 && duration_secs > 0 ){
-			  						
-			  						mediaContent += " duration=\"" + duration_secs + "\"";
-			  					}
-			  					  					
-			  					thumb_url = PlatformTorrentUtils.getContentThumbnailUrl(toTorrent);
-			  					
-			  					author = PlatformTorrentUtils.getContentAuthor(toTorrent);
-			  								
-			  					description= PlatformTorrentUtils.getContentDescription(toTorrent);
-			  					
-			  					if ( description != null ){
-			  						
-			  						description = escapeMultiline( description );
-		
-			  						/*
-			  						if ( thumb_url != null ){
-			  							
-			  		
-			  							pw.println( "<description type=\"text/html\">" + 
-			  								escape( "<div style=\"text-align: justify;padding: 5px;\"><img style=\"float: left;margin-right: 15px;margin-bottom: 15px;\" src=\"" + thumb_url + "\"/>" ) +
-			  								description + 
-			  								escape( "</div>" ) +
-			  								"</description>" );
-			  						}else{
-			  						*/	
-			  							pw.println( "<description>" + description + "</description>");
-			  						//}
-			   					}					
-			  				}catch( Throwable e ){
-			  				}
-			
-			  					// media elements
-			  				
-			  				if ( mediaContent.length() > 0 ){
-			  					  						
-			  					pw.println( mediaContent += "></media:content>" );
-			  				}
-			
-			  				pw.println( "<media:title>" + escape( file.getName()) + "</media:title>" );
-			
-							if ( description != null ){
-									
-								pw.println( "<media:description>" + description + "</media:description>" );
-							}
-							
-							if ( thumb_url != null ) {
-									
-								pw.println("<media:thumbnail url=\"" + thumb_url + "\"/>" );
-							}
-			 
-			 					// iTunes elements
-			 					
-							if ( thumb_url != null ) {
-									
-								pw.println("<itunes:image href=\"" + thumb_url + "\"/>");
-							}
-			
-			 				if ( author != null ){
-			  					
-			  					pw.println("<itunes:author>" + escape(author) + "</itunees:author>");
-			  				}
-			  				
-			  				pw.println( "<itunes:summary>" + escape( file.getName()) + "</itunes:summary>" );
-			  				pw.println( "<itunes:duration>" + TimeFormatter.formatColon( file.getDurationMillis()/1000 ) + "</itunes:duration>" );
-			  				
-			  				pw.println( "</item>" );
-			  				
-						}catch( Throwable e ){
-							
-							Debug.out(e);
-						}
-					}
-				
-					pw.println( "</channel>" );
-					
-					pw.println( "</rss>" );
-					
-				}finally{
-					
-					if ( debug ){
-						
-						pw.setEnabled( false );
-						
-						pw.println( "</pre>" );
-						
-						pw.println( "</BODY></HTML>" );
-					}
-				}
-			}
-		}
-		
-		pw.flush();
-		
-		return( true );
-	}
-	
-	protected String
-	escape(
-		String	str )
-	{
-		return( XUXmlWriter.escapeXML(str));
-	}
-
-	protected String
-	escapeMultiline(
-		String	str )
-	{
-		return( XUXmlWriter.escapeXML(str.replaceAll("[\r\n]+", "<BR>")));
-	}
-}
+/*
+ * Created on Jul 13, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.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.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+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.XMLEscapeWriter;
+import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;
+
+import com.aelitis.azureus.core.devices.Device;
+import com.aelitis.azureus.core.devices.DeviceManager;
+import com.aelitis.azureus.core.rssgen.RSSGeneratorPlugin;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManager;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
+
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+
+public class 
+DeviceManagerRSSFeed 
+	implements RSSGeneratorPlugin.Provider
+{
+	private static final String PROVIDER = "devices";
+	
+	private DeviceManagerImpl		manager;
+		
+	private RSSGeneratorPlugin		generator;
+	
+	protected
+	DeviceManagerRSSFeed(
+		DeviceManagerImpl	_manager )
+	{
+		manager 	= _manager;
+		generator	= RSSGeneratorPlugin.getSingleton();
+		
+		if ( generator != null ){
+		
+			generator.registerProvider( PROVIDER, this );
+		}
+	}
+		
+	public boolean
+	isEnabled()
+	{
+		return( manager.isRSSPublishEnabled());
+	}
+	
+	public String
+	getFeedURL()
+	{
+		return( generator==null?"Feature Disabled":( 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);
+		
+		DeviceImpl[] devices = manager.getDevices();
+		
+		OutputStream os = response.getOutputStream();
+
+		XMLEscapeWriter pw = new XMLEscapeWriter( new PrintWriter(new OutputStreamWriter( os, "UTF-8" )));
+
+		pw.setEnabled( false );
+
+		boolean hide_generic = COConfigurationManager.getBooleanParameter( DeviceManager.CONFIG_VIEW_HIDE_REND_GENERIC, true );
+		
+		boolean show_only_tagged = COConfigurationManager.getBooleanParameter( DeviceManager.CONFIG_VIEW_SHOW_ONLY_TAGGED, false);
+
+		if ( path.length() <= 1 ){
+			
+			response.setContentType( "text/html; charset=UTF-8" );
+			
+			pw.println( "<HTML><HEAD><TITLE>Vuze Device Feeds</TITLE></HEAD><BODY>" );
+			
+			for ( DeviceImpl d: devices ){
+			
+				if ( 	d.getType() != Device.DT_MEDIA_RENDERER || 
+						d.isHidden() || 
+						!d.isRSSPublishEnabled() || 
+						( hide_generic && d.isNonSimple()) || 
+						( show_only_tagged && !d.isTagged())){
+					
+					continue;
+				}
+
+				String	name = d.getName();
+							
+				String	device_url = PROVIDER + "/" + URLEncoder.encode( name, "UTF-8" );
+				
+				pw.println( "<LI><A href=\"" + device_url + "\">" + name + "</A>  -  <font size=\"-1\"><a href=\"" + device_url + "?format=html\">html</a></font></LI>" );
+			}
+			
+			pw.println( "</BODY></HTML>" );
+			
+		}else{
+			
+			String	device_name = URLDecoder.decode( path.substring( 1 ), "UTF-8" );
+			
+			DeviceImpl	device = null;
+			
+			for ( DeviceImpl d: devices ){
+				
+				if ( d.getName().equals( device_name ) && d.isRSSPublishEnabled()){
+					
+					device = d;
+					
+					break;
+				}
+			}
+			
+			if ( device == null ){
+				
+				response.setReplyStatus( 404 );
+				
+				return( true );
+			}
+			
+			TranscodeFileImpl[] _files = device.getFiles();
+			
+			List<TranscodeFileImpl>	files = new ArrayList<TranscodeFileImpl>( _files.length );
+			
+			files.addAll( Arrays.asList( _files ));
+			
+			Collections.sort(
+				files,
+				new Comparator<TranscodeFileImpl>()
+				{
+					public int  
+					compare(
+						TranscodeFileImpl f1, 
+						TranscodeFileImpl f2) 
+					{
+						long	added1 = f1.getCreationDateMillis()/1000;
+						long	added2 = f2.getCreationDateMillis()/1000;
+
+						return((int)(added2 - added1 ));
+					}
+				});
+			
+			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();
+			}
+			
+			String channel_title = "Vuze Device: " + escape( device.getName());
+
+			boolean	html = request.getURL().contains( "format=html" );
+
+			if ( html ){
+				
+				response.setContentType( "text/html; charset=UTF-8" );
+				
+				pw.println( "<HTML><HEAD><TITLE>" + channel_title + "</TITLE></HEAD><BODY>" );
+
+				
+				for ( TranscodeFileImpl file: files ){
+					
+		  			if ( !file.isComplete()){
+		  					
+		  				if ( !file.isTemplate()){
+		  						
+		  					continue;
+		  				}
+		  			}
+	  				
+	  				URL stream_url = file.getStreamURL( feed_url.getHost() );
+	  				
+	  				if ( stream_url != null ){
+	  					
+	  					String url_ext = stream_url.toExternalForm();
+	  						
+	  					pw.println( "<p>" );
+	  					
+	  					pw.println( "<a href=\"" + url_ext + "\">" + escape( file.getName()) + "</a>" );
+	  						
+	  					url_ext += url_ext.indexOf('?') == -1?"?":"&";
+	  					
+	  					url_ext += "action=download";
+	  					
+	  					pw.println( "  -  <font size=\"-1\"><a href=\"" + url_ext + "\">save</a></font>" );
+
+	  				}
+				}
+
+				pw.println( "</BODY></HTML>" );
+				
+			}else{
+				boolean	debug = request.getURL().contains( "format=debug" );
+				
+				if ( debug ){
+					
+					response.setContentType( "text/html; charset=UTF-8" );
+					
+					pw.println( "<HTML><HEAD><TITLE>" + channel_title + "</TITLE></HEAD><BODY>" );
+					
+					pw.println( "<pre>" );
+					
+					pw.setEnabled( true );
+					
+				}else{
+					
+					response.setContentType( "application/xml" );
+				}
+				
+				try{
+					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>" );
+											
+					pw.println( "<title>" + channel_title + "</title>" );
+					pw.println( "<link>http://vuze.com</link>" );
+					pw.println( "<atom:link href=\"" + feed_url.toExternalForm() + "\" rel=\"self\" type=\"application/rss+xml\" />" );
+					
+					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>");
+					
+							
+
+												
+					String	feed_date_key = "devices.feed_date." + device.getID();
+					
+					long feed_date = COConfigurationManager.getLongParameter( feed_date_key );
+		
+					boolean new_date = false;
+					
+					for ( TranscodeFileImpl file: files ){
+						
+						long	file_date = file.getCreationDateMillis();
+						
+						if ( file_date > feed_date ){
+							
+							new_date = true;
+							
+							feed_date = file_date;
+						}
+					}
+					
+					if ( new_date ){
+						
+						COConfigurationManager.setParameter( feed_date_key, feed_date );
+					}
+					
+					pw.println(	"<pubDate>" + TimeFormatter.getHTTPDate( feed_date ) + "</pubDate>" );
+		
+					for ( TranscodeFileImpl file: files ){
+												
+			  			if ( !file.isComplete()){
+			  					
+			  				if ( !file.isTemplate()){
+			  						
+			  					continue;
+			  				}
+			  			}
+			  		
+						try{
+			  				pw.println( "<item>" );
+			  				
+			  				pw.println( "<title>" + escape( file.getName()) + "</title>" );
+			  								
+			  				pw.println(	"<pubDate>" + TimeFormatter.getHTTPDate( file.getCreationDateMillis()) + "</pubDate>" );
+			  				
+			  				pw.println( "<guid isPermaLink=\"false\">" + escape( file.getKey()) + "</guid>" );
+			  				
+			  				String[] categories = file.getCategories();
+			  				
+			  				for ( String category: categories ){
+			  					
+			  					pw.println( "<category>" + escape(category) + "</category>" );
+			  				}
+			  				
+			  				String[] tags = file.getTags( true );
+			  				
+			  				for ( String tag: tags ){
+			  					
+			  					pw.println( "<tag>" + escape( tag ) + "</tag>" );
+			  				}
+			  				
+			  				String mediaContent = "";
+			  				
+			  				URL stream_url = file.getStreamURL( feed_url.getHost() );
+			  				
+			  				if ( stream_url != null ){
+			  					
+			  					String url_ext = stream_url.toExternalForm();
+			  					
+			  					long fileSize = file.getTargetFile().getLength();
+			  					
+			  					pw.println( "<link>" + url_ext + "</link>" );
+			  					
+			  					mediaContent = "<media:content medium=\"video\" fileSize=\"" +
+													fileSize + "\" url=\"" + url_ext + "\""; 
+			  					
+			  					String	mime_type = file.getMimeType();
+			  					
+			  					if ( mime_type != null ){
+			  						
+			  						mediaContent += " type=\"" + mime_type + "\"";
+			  					}
+			  				
+								pw.println("<enclosure url=\"" + url_ext
+										+ "\" length=\"" + fileSize
+										+ (mime_type == null ? "" : "\" type=\"" + mime_type)
+										+ "\"></enclosure>");		
+			  				}
+			  				
+			   				String	thumb_url		= null;
+			  				String	author			= null;
+			  				String	description		= null;
+			  				
+			  				try{
+			  					Torrent torrent = file.getSourceFile().getDownload().getTorrent();
+			  				
+			  					TOTorrent toTorrent = PluginCoreUtils.unwrap(torrent);
+							
+			  					long duration_secs = PlatformTorrentUtils.getContentVideoRunningTime(toTorrent);
+			  					
+			  					if ( mediaContent.length() > 0 && duration_secs > 0 ){
+			  						
+			  						mediaContent += " duration=\"" + duration_secs + "\"";
+			  					}
+			  					  					
+			  					thumb_url = PlatformTorrentUtils.getContentThumbnailUrl(toTorrent);
+			  					
+			  					author = PlatformTorrentUtils.getContentAuthor(toTorrent);
+			  								
+			  					description= PlatformTorrentUtils.getContentDescription(toTorrent);
+			  					
+			  					if ( description != null ){
+			  						
+			  						description = escapeMultiline( description );
+		
+			  						/*
+			  						if ( thumb_url != null ){
+			  							
+			  		
+			  							pw.println( "<description type=\"text/html\">" + 
+			  								escape( "<div style=\"text-align: justify;padding: 5px;\"><img style=\"float: left;margin-right: 15px;margin-bottom: 15px;\" src=\"" + thumb_url + "\"/>" ) +
+			  								description + 
+			  								escape( "</div>" ) +
+			  								"</description>" );
+			  						}else{
+			  						*/	
+			  							pw.println( "<description>" + description + "</description>");
+			  						//}
+			   					}					
+			  				}catch( Throwable e ){
+			  				}
+			
+			  					// media elements
+			  				
+			  				if ( mediaContent.length() > 0 ){
+			  					  						
+			  					pw.println( mediaContent += "></media:content>" );
+			  				}
+			
+			  				pw.println( "<media:title>" + escape( file.getName()) + "</media:title>" );
+			
+							if ( description != null ){
+									
+								pw.println( "<media:description>" + description + "</media:description>" );
+							}
+							
+							if ( thumb_url != null ) {
+									
+								pw.println("<media:thumbnail url=\"" + thumb_url + "\"/>" );
+							}
+			 
+			 					// iTunes elements
+			 					
+							if ( thumb_url != null ) {
+									
+								pw.println("<itunes:image href=\"" + thumb_url + "\"/>");
+							}
+			
+			 				if ( author != null ){
+			  					
+			  					pw.println("<itunes:author>" + escape(author) + "</itunees:author>");
+			  				}
+			  				
+			  				pw.println( "<itunes:summary>" + escape( file.getName()) + "</itunes:summary>" );
+			  				pw.println( "<itunes:duration>" + TimeFormatter.formatColon( file.getDurationMillis()/1000 ) + "</itunes:duration>" );
+			  				
+			  				pw.println( "</item>" );
+			  				
+						}catch( Throwable e ){
+							
+							Debug.out(e);
+						}
+					}
+				
+					pw.println( "</channel>" );
+					
+					pw.println( "</rss>" );
+					
+				}finally{
+					
+					if ( debug ){
+						
+						pw.setEnabled( false );
+						
+						pw.println( "</pre>" );
+						
+						pw.println( "</BODY></HTML>" );
+					}
+				}
+			}
+		}
+		
+		pw.flush();
+		
+		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/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerUPnPImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerUPnPImpl.java
index 9e9e93e..4f6cc20 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerUPnPImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceManagerUPnPImpl.java
@@ -1,1074 +1,1102 @@
-/*
- * 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.impl;
-
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.NetworkInterface;
-import java.net.URL;
-import java.util.*;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.PluginEvent;
-import org.gudy.azureus2.plugins.PluginEventListener;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.PluginListener;
-import org.gudy.azureus2.plugins.ipc.IPCInterface;
-import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
-import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
-import org.gudy.azureus2.plugins.utils.UTTimer;
-import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory;
-import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument;
-import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.pluginsimpl.local.ipc.IPCInterfaceImpl;
-
-import com.aelitis.azureus.core.content.AzureusContentDownload;
-import com.aelitis.azureus.core.content.AzureusContentFile;
-import com.aelitis.azureus.core.content.AzureusContentFilter;
-import com.aelitis.azureus.core.devices.DeviceMediaRenderer;
-import com.aelitis.azureus.core.devices.TranscodeTarget;
-import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice;
-import com.aelitis.azureus.core.util.UUIDGenerator;
-import com.aelitis.net.upnp.UPnP;
-import com.aelitis.net.upnp.UPnPAdapter;
-import com.aelitis.net.upnp.UPnPDevice;
-import com.aelitis.net.upnp.UPnPFactory;
-import com.aelitis.net.upnp.UPnPListener;
-import com.aelitis.net.upnp.UPnPRootDevice;
-import com.aelitis.net.upnp.UPnPRootDeviceListener;
-import com.aelitis.net.upnp.UPnPSSDPListener;
-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_ROOT_DEVICE = new Object();
-		
-	private DeviceManagerImpl		manager;
-	private PluginInterface			plugin_interface;
-	private UPnP 					upnp;
-	private TorrentAttribute		ta_category;
-	
-	private volatile IPCInterface			upnpav_ipc;
-	
-	private Map<InetAddress,String>		unassociated_devices = new HashMap<InetAddress, String>();
-	
-	private Set<String>					access_logs	= new HashSet<String>();
-	
-	protected
-	DeviceManagerUPnPImpl(
-		DeviceManagerImpl		_manager )
-	{
-		manager	= _manager;
-	}
-	
-	protected void
-	initialise()
-	{
-		plugin_interface = PluginInitializer.getDefaultInterface();
-		
-		ta_category = plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_CATEGORY );
-		
-		plugin_interface.addListener(
-				new PluginListener()
-				{
-					public void
-					initializationComplete()
-					{
-							// startup can take a while as adding the upnp listener can sync call back device added and result
-							// in device details loading etc
-						
-						new AEThread2( "DMUPnPAsyncStart", true )
-						{
-							public void
-							run()
-							{
-								startUp();
-							}
-						}.start();
-					}
-					
-					public void
-					closedownInitiated()
-					{
-					}
-					
-					public void
-					closedownComplete()
-					{
-					}
-				});
-	}
-	
-	protected DeviceManagerImpl
-	getManager()
-	{
-		return( manager );
-	}
-	
-	protected TorrentAttribute
-	getCategoryAttibute()
-	{
-		return( ta_category );
-	}
-	
-	protected void
-	startUp()
-	{
-		UPnPAdapter adapter = 
-			new UPnPAdapter()
-			{
-				public SimpleXMLParserDocument
-				parseXML(
-					String	data )
-				
-					throws SimpleXMLParserDocumentException
-				{
-					return( plugin_interface.getUtilities().getSimpleXMLParserDocumentFactory().create( data ));
-				}
-				
-				public ResourceDownloaderFactory
-				getResourceDownloaderFactory()
-				{
-					return( plugin_interface.getUtilities().getResourceDownloaderFactory());
-				}
-				
-				public UTTimer
-				createTimer(
-					String	name )
-				{
-					return( plugin_interface.getUtilities().createTimer( name ));
-				}
-				
-				public void
-				createThread(
-					String				name,
-					final Runnable		runnable )
-				{
-					plugin_interface.getUtilities().createThread( name, runnable );
-				}
-				
-				public Comparator
-				getAlphanumericComparator()
-				{
-					return( plugin_interface.getUtilities().getFormatters().getAlphanumericComparator( true ));
-				}
-
-				public void
-				log(
-					Throwable	e )
-				{
-					Debug.printStackTrace(e);
-				}
-				
-				public void
-				trace(
-					String	str )
-				{
-					// System.out.println( str );
-				}
-				
-				public void
-				log(
-					String	str )
-				{
-					// System.out.println( str );
-				}
-				
-				public String
-				getTraceDir()
-				{
-					return( plugin_interface.getPluginDirectoryName());
-				}
-			};
-		
-		try{
-			upnp = UPnPFactory.getSingleton( adapter, null );
-			
-			
-			upnp.addRootDeviceListener(
-				new UPnPListener()
-				{
-					public boolean
-					deviceDiscovered(
-						String		USN,
-						URL			location )
-					{
-						return( true );
-					}
-					
-					public void
-					rootDeviceFound(
-						UPnPRootDevice		device )
-					{
-						handleDevice( device, true );
-					}
-				});
-		
-			upnp.getSSDP().addListener(
-				new UPnPSSDPListener()
-				{
-					private Map<InetAddress,Boolean>	liveness_map = new HashMap<InetAddress, Boolean>();
-					
-					public void
-					receivedResult(
-						NetworkInterface	network_interface,
-						InetAddress			local_address,
-						InetAddress			originator,
-						String				USN,
-						URL					location,
-						String				ST,
-						String				AL )
-					{
-					}
-					
-					public void
-					receivedNotify(
-						NetworkInterface	network_interface,
-						InetAddress			local_address,
-						InetAddress			originator,
-						String				USN,
-						URL					location,
-						String				NT,
-						String				NTS )
-					{
-						alive( originator, NTS.indexOf( "byebye") == -1 );
-					}
-
-					public String[]
-					receivedSearch(
-						NetworkInterface	network_interface,
-						InetAddress			local_address,
-						InetAddress			originator,
-						String				ST )
-					{
-						alive( originator, true );
-						
-						return( null );
-					}
-					
-					public void
-					interfaceChanged(
-						NetworkInterface	network_interface )
-					{
-					}
-					
-					private void
-					alive(
-						InetAddress		address,
-						boolean			alive )
-					{
-						synchronized( liveness_map ){
-						
-							Boolean	b = liveness_map.get( address );
-							
-							if ( b != null && b == alive ){
-								
-								return;
-							}
-							
-							liveness_map.put( address, alive );
-						}
-												
-						DeviceImpl[] devices = manager.getDevices();
-
-						for ( DeviceImpl d: devices ){
-												
-							if ( d instanceof DeviceMediaRendererImpl ){
-									
-								DeviceMediaRendererImpl r = (DeviceMediaRendererImpl)d;
-									
-								InetAddress device_address = r.getAddress();
-									
-								if ( device_address != null && device_address.equals( address )){
-										
-									if ( r.isAlive() != alive ){
-										
-										if ( alive ){
-											
-											r.alive();
-											
-										}else{
-											
-											r.dead();
-										}
-									}
-								}
-							}
-						}
-					}
-				});
-			
-		}catch( Throwable e ){
-			
-			manager.log( "UPnP device manager failed", e );
-		}
-		
-		try{			
-			plugin_interface.addEventListener(
-					new PluginEventListener()
-					{
-						public void 
-						handleEvent(
-							PluginEvent ev )
-						{
-							int	type = ev.getType();
-							
-							if ( 	type == PluginEvent.PEV_PLUGIN_OPERATIONAL ||
-									type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL ){
-								
-								PluginInterface pi = (PluginInterface)ev.getValue();
-			
-								if ( pi.getPluginID().equals( "azupnpav" )){
-				
-									if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL ){
-									
-										upnpav_ipc = pi.getIPC();
-
-										addListener( pi );
-										
-									}else{
-										
-										upnpav_ipc = null;
-									}
-								}
-							}
-						}
-					});
-			
-			PluginInterface pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azupnpav" );
-
-			if ( pi == null ){
-				
-				manager.log( "No UPnPAV plugin found" );
-				
-			}else{
-				
-				upnpav_ipc = pi.getIPC();
-				
-				addListener( pi );
-			}			
-		}catch( Throwable e ){
-			
-			manager.log( "Failed to hook into UPnPAV", e );
-		}
-		
-		manager.UPnPManagerStarted();
-	}
-	
-	protected void
-	addListener(
-		PluginInterface	pi )
-	{
-		try{			
-			IPCInterface my_ipc = 
-				new IPCInterfaceImpl(
-					new Object()
-					{
-						public Map<String,Object>
-						browseReceived(
-							TrackerWebPageRequest		request,
-							Map<String,Object>			browser_args )
-						{
-							Map headers = request.getHeaders();
-							
-							String user_agent 	= (String)headers.get( "user-agent" );
-							String client_info 	= (String)headers.get( "x-av-client-info" );
-							
-							InetSocketAddress client_address = request.getClientAddress2();
-								
-							DeviceMediaRenderer	explicit_renderer = null;
-							
-							boolean	handled = false;
-														
-							if ( user_agent != null ){
-								
-								String lc_agent = user_agent.toLowerCase();
-								
-								if ( lc_agent.contains( "playstation 3")){
-									
-									handlePS3( client_address );
-									
-									handled = true;
-									
-								}else if ( lc_agent.contains( "xbox")){
-								
-									handleXBox( client_address );
-									
-									handled = true;
-									
-								}else if ( lc_agent.contains( "nintendo wii")){
-								
-									handleWii( client_address );
-																		
-									handled = true;
-								}
-
-							}
-							
-							if ( client_info != null ){
-							
-								String	lc_info = client_info.toLowerCase();
-								
-								if ( lc_info.contains( "playstation 3")){
-									
-									handlePS3( client_address );
-									
-									handled = true;
-									
-								}else if ( lc_info.contains( "azureus" ) || lc_info.contains( "vuze" )){
-									
-									explicit_renderer = handleVuzeMSBrowser( client_address, client_info );
-																		
-									handled = true;
-								}
-							}
-							
-							if ( !handled ){
-								
-								handled = manager.browseReceived( request, browser_args );
-							}
-							
-							if ( !handled ){
-								
-								String	 source = (String)browser_args.get( "source" );
-								
-								if ( source != null && source.equalsIgnoreCase( "http" )){
-									
-									handleBrowser( client_address );
-																		
-									handled = true;
-								}
-							}
-							
-							/**
-							System.out.println( 
-									"Received browse: " + request.getClientAddress() +
-									", agent=" + user_agent +
-									", info=" + client_info +
-									", handled=" + handled + ", " + request.getURL());
-									System.out.println("\n\n");
-								/**/
-
-							
-							DeviceImpl[] devices = manager.getDevices();
-							
-							final List<DeviceMediaRendererImpl>	browse_devices = new ArrayList<DeviceMediaRendererImpl>();
-							
-							boolean	restrict_access = false;
-							
-							for ( DeviceImpl device: devices ){
-							
-								if ( device instanceof DeviceMediaRendererImpl ){
-								
-									DeviceMediaRendererImpl renderer = (DeviceMediaRendererImpl)device;
-									
-									if ( explicit_renderer != null ){
-										
-										if ( renderer != explicit_renderer ){
-											
-											continue;
-										}
-									}
-									
-									InetAddress device_address = renderer.getAddress();
-									
-									try{
-										if ( device_address != null ){
-														
-												// just test on IP, should be OK
-											
-											if ( device_address.equals( client_address.getAddress())){
-					
-												if ( renderer.canFilterFilesView()){
-												
-													boolean	skip = false;
-													
-													if ( renderer.canRestrictAccess()){
-														
-														String restriction = renderer.getAccessRestriction().trim();
-														
-														if ( restriction.length() > 0 ){
-															
-															String x = client_address.getAddress().getHostAddress();
-															
-															skip = true;
-															
-															String[] ips = restriction.split( "," );
-															
-															for ( String ip: ips ){
-																
-																if ( ip.startsWith( "-" )){
-																	
-																	ip = ip.substring(1);
-																	
-																	if ( ip.equals( x )){
-																		
-																		break;
-																	}
-																}else{
-																	
-																	if ( ip.startsWith( "+" )){
-																		
-																		ip = ip.substring(1);
-																	}
-																	
-																	if ( ip.equals( x )){
-																	
-																		skip = false;
-																		
-																		break;
-																	}
-																}
-															}
-														}
-													}
-													
-													if ( skip ){
-													
-														restrict_access = true;
-														
-														String	host = client_address.getAddress().getHostAddress();
-														
-														synchronized( access_logs){
-															
-															if ( !access_logs.contains( host )){
-																
-																access_logs.add( host );
-															
-																manager.log( "Ignoring browse from " + host + " due to access restriction for '" + renderer.getName() + "'" );
-															}
-														}
-													}
-														
-													browse_devices.add( renderer );
-													
-													renderer.browseReceived();
-												}
-											}
-										}
-									}catch( Throwable e ){
-										
-										Debug.out( e );
-									}
-								}
-							}
-							
-							Map<String,Object> result = new HashMap<String, Object>();
-							
-							if ( browse_devices.size() > 0 ){
-								
-								synchronized( unassociated_devices ){
-									
-									unassociated_devices.remove( client_address.getAddress() );
-								}
-								
-								final boolean f_restrict_access = restrict_access;
-								
-								result.put(
-									"filter",
-									new AzureusContentFilter()
-									{
-										public boolean
-										isVisible(
-											AzureusContentDownload	download,
-											Map<String,Object>		browse_args )
-										{
-											if ( f_restrict_access ){
-												
-												return( false );
-											}
-											
-											boolean	visible = false;
-											
-											for ( DeviceUPnPImpl device: browse_devices ){
-												
-												if ( device.isVisible( download )){
-													
-													visible	= true;
-												}
-											}
-											
-											return( visible );
-										}
-										
-										public boolean
-										isVisible(
-											AzureusContentFile		file,
-											Map<String,Object>		browse_args )
-										{
-											if ( f_restrict_access ){
-												
-												return( false );
-											}
-											
-											boolean	visible = false;
-											
-											for ( DeviceUPnPImpl device: browse_devices ){
-												
-												if ( device.isVisible( file )){
-													
-													visible	= true;
-												}
-											}
-											
-											return( visible );
-										}
-									});
-							}else{
-								
-								if ( request.getHeader().substring(0,4).equalsIgnoreCase( "POST" )){
-									
-									synchronized( unassociated_devices ){
-									
-										unassociated_devices.put( client_address.getAddress(), user_agent );
-									}
-								}
-							}
-								
-							return( result );
-						}
-					});
-			
-			if ( upnpav_ipc.canInvoke( "addBrowseListener", new Object[]{ my_ipc })){
-								
-				DeviceImpl[] devices = manager.getDevices();
-				
-				for ( DeviceImpl device: devices ){
-				
-					if ( device instanceof DeviceUPnPImpl ){
-					
-						DeviceUPnPImpl u_d = (DeviceUPnPImpl)device;
-
-						u_d.resetUPNPAV();
-					}
-				}
-				
-				upnpav_ipc.invoke( "addBrowseListener", new Object[]{ my_ipc });
-
-			}else{
-				
-				manager.log( "UPnPAV plugin needs upgrading" );
-			}
-		}catch( Throwable e ){
-			
-			manager.log( "Failed to hook into UPnPAV", e );
-		}
-	}
-	
-	protected void
-	injectDiscoveryCache(
-		Map		cache )
-	{
-		try{
-			upnp.injectDiscoveryCache( cache );
-			
-		}catch( Throwable e ){
-	
-			Debug.out( e );
-		}
-	}
-	
-	public UnassociatedDevice[]
-	getUnassociatedDevices()
-	{
-		List<UnassociatedDevice> result = new ArrayList<UnassociatedDevice>();
-		
-		Map<InetAddress,String> ud;
-		
-		synchronized( unassociated_devices ){
-
-			ud = new HashMap<InetAddress,String>( unassociated_devices );
-		}
-		
-		DeviceImpl[] devices = manager.getDevices();
-
-		for ( final Map.Entry<InetAddress, String> entry: ud.entrySet()){
-			
-			InetAddress	address = entry.getKey();
-			
-			boolean already_assoc = false;
-
-			for ( DeviceImpl d: devices ){
-								
-				if ( d instanceof DeviceMediaRendererImpl ){
-					
-					DeviceMediaRendererImpl r = (DeviceMediaRendererImpl)d;
-					
-					InetAddress device_address = r.getAddress();
-					
-					if ( d.isAlive() && device_address != null && device_address.equals( address )){
-						
-						already_assoc = true;
-						
-						break;
-					}
-				}
-			}
-			
-			if ( !already_assoc ){
-				
-				result.add(
-					new UnassociatedDevice()
-					{
-						public InetAddress
-						getAddress()
-						{
-							return( entry.getKey());
-						}
-						
-						public String
-						getDescription()
-						{
-							return( entry.getValue());
-						}
-					});
-			}
-		}
-		
-		return( result.toArray( new UnassociatedDevice[result.size()]));
-	}
-	
-	public PluginInterface
-	getPluginInterface()
-	{
-		return( plugin_interface );
-	}
-	
-	protected IPCInterface
-	getUPnPAVIPC()
-	{
-		return( upnpav_ipc );
-	}
-	
-	public void
-	search()
-	{	
-		if ( upnp != null ){
-	
-			// if the user has removed items we need to re-inject them
-
-			UPnPRootDevice[] devices = upnp.getRootDevices();
-			
-			for ( UPnPRootDevice device: devices ){
-				
-				handleDevice( device, false );
-			}
-			
-			String[] STs = {
-				"upnp:rootdevice",
-				"urn:schemas-upnp-org:device:MediaRenderer:1",
-				"urn:schemas-upnp-org:service:ContentDirectory:1",
-			};
-			
-			upnp.search( STs );
-		}
-	}
-	
-	protected void
-	handleXBox(
-		InetSocketAddress	address )
-	{
-		// normally we can detect the xbox renderer and things work automagically. However, on
-		// occasion we receive the browse before detection and if the device's IP has changed
-		// we need to associate its new address here otherwise association of browse to device
-		// fails
-		
-		DeviceImpl[] devices = manager.getDevices();
-		
-		boolean	found = false;
-		
-		for ( DeviceImpl device: devices ){
-			
-			if ( device instanceof DeviceMediaRendererImpl ){
-				
-				DeviceMediaRendererImpl renderer = (DeviceMediaRendererImpl)device;
-				
-				if ( device.getRendererSpecies() == DeviceMediaRenderer.RS_XBOX ){
-
-					found = true;
-					
-					if (!device.isAlive()){
-				
-						renderer.setAddress( address.getAddress());
-						
-						device.alive();
-					}
-				}
-			}
-		}
-		
-		if ( !found ){
-			
-			manager.addDevice( new DeviceMediaRendererImpl( manager, "Xbox 360" ));
-		}
-	}
-	
-	protected void
-	handlePS3(
-		InetSocketAddress	address )
-	{
-		handleGeneric( address, "ps3", "PS3" );
-	}
-
-	protected void
-	handleWii(
-		InetSocketAddress	address )
-	{
-		handleGeneric( address, "wii", "Wii" );
-	}
-	
-	protected void
-	handleBrowser(
-		InetSocketAddress	address )
-	{
-		handleGeneric( address, "browser", "Browser" );
-	}
-	
-	protected DeviceMediaRenderer
-	handleVuzeMSBrowser(
-		InetSocketAddress	address,
-		String				info )
-	{
-		String[] bits = info.split( ";" );
-		
-		String	client = "";
-		
-		for ( String bit: bits ){
-			
-			String[] temp = bit.split( "=" );
-			
-			if ( temp.length == 2 && temp[0].trim().equalsIgnoreCase( "mn")){
-				
-				client = temp[1].trim();
-				
-				if ( client.startsWith( "\"" )){
-					
-					client = client.substring(1);
-				}
-				
-				if ( client.endsWith( "\"" )){
-					
-					client = client.substring( 0, client.length()-1);
-				}
-			}
-		}
-		
-		if ( client.length() == 0 ){
-			
-			client = "Vuze on " + address.getAddress().getHostAddress();
-		}
-		
-		DeviceMediaRenderer result = handleGeneric( address, "vuze-ms-browser." + client, client );
-		
-		result.setTranscodeRequirement( TranscodeTarget.TRANSCODE_NEVER );
-		
-		return( result );
-	}
-	
-	protected DeviceMediaRenderer
-	handleGeneric(
-		InetSocketAddress	address,
-		String				unique_name,
-		String				display_name )
-	{
-		String uid;
-		
-		synchronized( this ){
-			
-			uid = COConfigurationManager.getStringParameter( "devices.upnp.uid." + unique_name, "" );
-			
-			if ( uid.length() == 0 ){
-				
-				uid = UUIDGenerator.generateUUIDString();
-				
-				COConfigurationManager.setParameter( "devices.upnp.uid." + unique_name, uid );
-				
-				COConfigurationManager.save();
-			}
-		}
-		
-		DeviceMediaRendererImpl newDevice = new DeviceMediaRendererImpl( manager, uid, unique_name, false, display_name );
-		
-		DeviceMediaRendererImpl device = (DeviceMediaRendererImpl)manager.addDevice( newDevice );
-		
-			// there's auto-hide code to hide devices created by receiving a browser event
-			// when a concrete upnp-based version is discovered at the same IP
-			// we don't want this happening for these generic devices, especially the Browser one
-			// as it is straight forward to get browse events from this on an IP that also
-			// happens to be exposing UPnP devices (e.g. windows media player)
-		
-		device.setPersistentBooleanProperty( DeviceImpl.PP_DONT_AUTO_HIDE, true );
-		
-		device.setAddress( address.getAddress());
-		
-		device.alive();
-
-		return device;
-	}
-	
-	protected void
-	handleDevice(
-		UPnPRootDevice		root_device,
-		boolean				update_if_found )
-	{
-		if ( !manager.getAutoSearch()){
-			
-			if ( !manager.isExplicitSearch()){
-				
-				return;
-			}
-		}
-		
-		handleDevice( root_device.getDevice(), update_if_found );
-	}
-	
-	protected void
-	handleDevice(
-		UPnPDevice	device,
-		boolean		update_if_found )
-	{
-		UPnPService[] 	services = device.getServices();
-		
-		List<DeviceUPnPImpl>	new_devices = new ArrayList<DeviceUPnPImpl>();
-		
-		List<UPnPWANConnection>	igd_services = new ArrayList<UPnPWANConnection>();
-		
-		for ( UPnPService service: services ){
-				
-			String	service_type = service.getServiceType();
-				
-			if ( 	service_type.equalsIgnoreCase( "urn:schemas-upnp-org:service:WANIPConnection:1") || 
-					service_type.equalsIgnoreCase( "urn:schemas-upnp-org:service:WANPPPConnection:1")){
-				
-				UPnPWANConnection	wan_service = (UPnPWANConnection)service.getSpecificService();
-				
-				igd_services.add( wan_service );				
-
-			}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 ));
-				}
-			}
-		}
-		
-		if ( igd_services.size() > 0 ){
-			
-			new_devices.add( new DeviceInternetGatewayImpl( manager, device, igd_services ));
-		}
-		
-		if ( device.getDeviceType().equals( "urn:schemas-upnp-org:device:MediaRenderer:1" )){
-				
-			new_devices.add( new DeviceMediaRendererImpl( manager, device ));
-		}
-		
-		for ( final DeviceUPnPImpl new_device: new_devices ){
-				
-			final DeviceImpl actual_device;
-			
-			DeviceImpl existing = manager.getDevice( new_device.getID());
-			
-			if ( !update_if_found && existing != null ){
-					
-				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 );
-			}
-			
-			UPnPRootDevice current_root = device.getRootDevice();
-			
-			UPnPRootDevice existing_root = (UPnPRootDevice)actual_device.getTransientProperty( KEY_ROOT_DEVICE );
-			
-			if ( current_root != existing_root ){
-				
-				actual_device.setTransientProperty( KEY_ROOT_DEVICE, current_root );
-				
-				current_root.addListener(
-					new UPnPRootDeviceListener()
-					{
-						public void
-						lost(
-							UPnPRootDevice	root,
-							boolean			replaced )
-						{
-							if ( !replaced ){
-								
-								actual_device.dead();
-							}
-						}
-					});
-			}
-		}
-		
-		for (UPnPDevice d: device.getSubDevices()){
-			
-			handleDevice( d, update_if_found );
-		}
-	}
-}
\ No newline at end of file
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.net.URL;
+import java.util.*;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.PluginEvent;
+import org.gudy.azureus2.plugins.PluginEventListener;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.PluginListener;
+import org.gudy.azureus2.plugins.ipc.IPCInterface;
+import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
+import org.gudy.azureus2.plugins.utils.UTTimer;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory;
+import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocument;
+import org.gudy.azureus2.plugins.utils.xml.simpleparser.SimpleXMLParserDocumentException;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.ipc.IPCInterfaceImpl;
+
+import com.aelitis.azureus.core.content.AzureusContentDownload;
+import com.aelitis.azureus.core.content.AzureusContentFile;
+import com.aelitis.azureus.core.content.AzureusContentFilter;
+import com.aelitis.azureus.core.devices.DeviceMediaRenderer;
+import com.aelitis.azureus.core.devices.TranscodeTarget;
+import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice;
+import com.aelitis.azureus.core.util.UUIDGenerator;
+import com.aelitis.net.upnp.UPnP;
+import com.aelitis.net.upnp.UPnPAdapter;
+import com.aelitis.net.upnp.UPnPDevice;
+import com.aelitis.net.upnp.UPnPFactory;
+import com.aelitis.net.upnp.UPnPListener;
+import com.aelitis.net.upnp.UPnPRootDevice;
+import com.aelitis.net.upnp.UPnPRootDeviceListener;
+import com.aelitis.net.upnp.UPnPSSDPListener;
+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_ROOT_DEVICE = new Object();
+		
+	private DeviceManagerImpl		manager;
+	private PluginInterface			plugin_interface;
+	private UPnP 					upnp;
+	private TorrentAttribute		ta_category;
+	
+	private volatile IPCInterface			upnpav_ipc;
+	
+	private Map<InetAddress,String>		unassociated_devices = new HashMap<InetAddress, String>();
+	
+	private Set<String>					access_logs	= new HashSet<String>();
+	
+	protected
+	DeviceManagerUPnPImpl(
+		DeviceManagerImpl		_manager )
+	{
+		manager	= _manager;
+	}
+	
+	protected void
+	initialise()
+	{
+		plugin_interface = PluginInitializer.getDefaultInterface();
+		
+		ta_category = plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_CATEGORY );
+		
+		plugin_interface.addListener(
+				new PluginListener()
+				{
+					public void
+					initializationComplete()
+					{
+							// startup can take a while as adding the upnp listener can sync call back device added and result
+							// in device details loading etc
+						
+						new AEThread2( "DMUPnPAsyncStart", true )
+						{
+							public void
+							run()
+							{
+								startUp();
+							}
+						}.start();
+					}
+					
+					public void
+					closedownInitiated()
+					{
+					}
+					
+					public void
+					closedownComplete()
+					{
+					}
+				});
+	}
+	
+	protected DeviceManagerImpl
+	getManager()
+	{
+		return( manager );
+	}
+	
+	protected TorrentAttribute
+	getCategoryAttibute()
+	{
+		return( ta_category );
+	}
+	
+	protected void
+	startUp()
+	{
+		UPnPAdapter adapter = 
+			new UPnPAdapter()
+			{
+				public SimpleXMLParserDocument
+				parseXML(
+					String	data )
+				
+					throws SimpleXMLParserDocumentException
+				{
+					return( plugin_interface.getUtilities().getSimpleXMLParserDocumentFactory().create( data ));
+				}
+				
+				public ResourceDownloaderFactory
+				getResourceDownloaderFactory()
+				{
+					return( plugin_interface.getUtilities().getResourceDownloaderFactory());
+				}
+				
+				public UTTimer
+				createTimer(
+					String	name )
+				{
+					return( plugin_interface.getUtilities().createTimer( name ));
+				}
+				
+				public void
+				createThread(
+					String				name,
+					final Runnable		runnable )
+				{
+					plugin_interface.getUtilities().createThread( name, runnable );
+				}
+				
+				public Comparator
+				getAlphanumericComparator()
+				{
+					return( plugin_interface.getUtilities().getFormatters().getAlphanumericComparator( true ));
+				}
+
+				public void
+				log(
+					Throwable	e )
+				{
+					Debug.printStackTrace(e);
+				}
+				
+				public void
+				trace(
+					String	str )
+				{
+					// System.out.println( str );
+				}
+				
+				public void
+				log(
+					String	str )
+				{
+					// System.out.println( str );
+				}
+				
+				public String
+				getTraceDir()
+				{
+					return( plugin_interface.getPluginDirectoryName());
+				}
+			};
+		
+		try{
+			upnp = UPnPFactory.getSingleton( adapter, null );
+			
+			
+			upnp.addRootDeviceListener(
+				new UPnPListener()
+				{
+					public boolean
+					deviceDiscovered(
+						String		USN,
+						URL			location )
+					{
+						return( true );
+					}
+					
+					public void
+					rootDeviceFound(
+						UPnPRootDevice		device )
+					{
+						handleDevice( device, true );
+					}
+				});
+		
+			upnp.getSSDP().addListener(
+				new UPnPSSDPListener()
+				{
+					private Map<InetAddress,Boolean>	liveness_map = new HashMap<InetAddress, Boolean>();
+					
+					public void
+					receivedResult(
+						NetworkInterface	network_interface,
+						InetAddress			local_address,
+						InetAddress			originator,
+						String				USN,
+						URL					location,
+						String				ST,
+						String				AL )
+					{
+					}
+					
+					public void
+					receivedNotify(
+						NetworkInterface	network_interface,
+						InetAddress			local_address,
+						InetAddress			originator,
+						String				USN,
+						URL					location,
+						String				NT,
+						String				NTS )
+					{
+						alive( originator, NTS.indexOf( "byebye") == -1 );
+					}
+
+					public String[]
+					receivedSearch(
+						NetworkInterface	network_interface,
+						InetAddress			local_address,
+						InetAddress			originator,
+						String				ST )
+					{
+						alive( originator, true );
+						
+						return( null );
+					}
+					
+					public void
+					interfaceChanged(
+						NetworkInterface	network_interface )
+					{
+					}
+					
+					private void
+					alive(
+						InetAddress		address,
+						boolean			alive )
+					{
+						synchronized( liveness_map ){
+						
+							Boolean	b = liveness_map.get( address );
+							
+							if ( b != null && b == alive ){
+								
+								return;
+							}
+							
+							liveness_map.put( address, alive );
+						}
+												
+						DeviceImpl[] devices = manager.getDevices();
+
+						for ( DeviceImpl d: devices ){
+												
+							if ( d instanceof DeviceMediaRendererImpl ){
+									
+								DeviceMediaRendererImpl r = (DeviceMediaRendererImpl)d;
+									
+								InetAddress device_address = r.getAddress();
+									
+								if ( device_address != null && device_address.equals( address )){
+										
+									if ( r.isAlive() != alive ){
+										
+										if ( alive ){
+											
+											r.alive();
+											
+										}else{
+											
+											r.dead();
+										}
+									}
+								}
+							}
+						}
+					}
+				});
+			
+		}catch( Throwable e ){
+			
+			manager.log( "UPnP device manager failed", e );
+		}
+		
+		try{			
+			plugin_interface.addEventListener(
+					new PluginEventListener()
+					{
+						public void 
+						handleEvent(
+							PluginEvent ev )
+						{
+							int	type = ev.getType();
+							
+							if ( 	type == PluginEvent.PEV_PLUGIN_OPERATIONAL ||
+									type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL ){
+								
+								PluginInterface pi = (PluginInterface)ev.getValue();
+			
+								if ( pi.getPluginID().equals( "azupnpav" )){
+				
+									if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL ){
+									
+										upnpav_ipc = pi.getIPC();
+
+										addListener( pi );
+										
+									}else{
+										
+										upnpav_ipc = null;
+									}
+								}
+							}
+						}
+					});
+			
+			PluginInterface pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azupnpav" );
+
+			if ( pi == null ){
+				
+				manager.log( "No UPnPAV plugin found" );
+				
+			}else{
+				
+				upnpav_ipc = pi.getIPC();
+				
+				addListener( pi );
+			}			
+		}catch( Throwable e ){
+			
+			manager.log( "Failed to hook into UPnPAV", e );
+		}
+		
+		manager.UPnPManagerStarted();
+	}
+	
+	protected void
+	addListener(
+		PluginInterface	pi )
+	{
+		try{			
+			IPCInterface my_ipc = 
+				new IPCInterfaceImpl(
+					new Object()
+					{
+						public Map<String,Object>
+						browseReceived(
+							TrackerWebPageRequest		request,
+							Map<String,Object>			browser_args )
+						{
+							Map headers = request.getHeaders();
+							
+							String user_agent 	= (String)headers.get( "user-agent" );
+							String client_info 	= (String)headers.get( "x-av-client-info" );
+							
+							InetSocketAddress client_address = request.getClientAddress2();
+								
+							DeviceMediaRenderer	explicit_renderer = null;
+							
+							boolean	handled = false;
+														
+							if ( user_agent != null ){
+								
+								String lc_agent = user_agent.toLowerCase();
+								
+								if ( lc_agent.contains( "playstation 3")){
+									
+									handlePS3( client_address );
+									
+									handled = true;
+									
+								}else if ( lc_agent.contains( "xbox")){
+								
+									handleXBox( client_address );
+									
+									handled = true;
+									
+								}else if ( lc_agent.contains( "nintendo wii")){
+								
+									handleWii( client_address );
+																		
+									handled = true;
+								}
+
+							}
+							
+							if ( client_info != null ){
+							
+								String	lc_info = client_info.toLowerCase();
+								
+								if ( lc_info.contains( "playstation 3")){
+									
+									handlePS3( client_address );
+									
+									handled = true;
+									
+								}else if ( lc_info.contains( "azureus" ) || lc_info.contains( "vuze" )){
+									
+									explicit_renderer = handleVuzeMSBrowser( client_address, client_info );
+																		
+									handled = true;
+								}
+							}
+							
+							if ( !handled ){
+								
+								handled = manager.browseReceived( request, browser_args );
+							}
+							
+							if ( !handled ){
+								
+								String	 source = (String)browser_args.get( "source" );
+								
+								if ( source != null && source.equalsIgnoreCase( "http" )){
+									
+									handleBrowser( client_address );
+																		
+									handled = true;
+								}
+							}
+							
+							/**
+							System.out.println( 
+									"Received browse: " + request.getClientAddress() +
+									", agent=" + user_agent +
+									", info=" + client_info +
+									", handled=" + handled + ", " + request.getURL());
+									System.out.println("\n\n");
+								/**/
+
+							
+							DeviceImpl[] devices = manager.getDevices();
+							
+							final List<DeviceMediaRendererImpl>	browse_devices = new ArrayList<DeviceMediaRendererImpl>();
+							
+							boolean	restrict_access = false;
+							
+							for ( DeviceImpl device: devices ){
+							
+								if ( device instanceof DeviceMediaRendererImpl ){
+								
+									DeviceMediaRendererImpl renderer = (DeviceMediaRendererImpl)device;
+									
+									if ( explicit_renderer != null ){
+										
+										if ( renderer != explicit_renderer ){
+											
+											continue;
+										}
+									}
+									
+									InetAddress device_address = renderer.getAddress();
+									
+									try{
+										if ( device_address != null ){
+														
+												// just test on IP, should be OK
+											
+											if ( device_address.equals( client_address.getAddress())){
+					
+												if ( renderer.canFilterFilesView()){
+												
+													boolean	skip = false;
+													
+													if ( renderer.canRestrictAccess()){
+														
+														String restriction = renderer.getAccessRestriction().trim();
+														
+														if ( restriction.length() > 0 ){
+															
+															String x = client_address.getAddress().getHostAddress();
+															
+															skip = true;
+															
+															String[] ips = restriction.split( "," );
+															
+															for ( String ip: ips ){
+																
+																if ( ip.startsWith( "-" )){
+																	
+																	ip = ip.substring(1);
+																	
+																	if ( ip.equals( x )){
+																		
+																		break;
+																	}
+																}else{
+																	
+																	if ( ip.startsWith( "+" )){
+																		
+																		ip = ip.substring(1);
+																	}
+																	
+																	if ( ip.equals( x )){
+																	
+																		skip = false;
+																		
+																		break;
+																	}
+																}
+															}
+														}
+													}
+													
+													if ( skip ){
+													
+														restrict_access = true;
+														
+														String	host = client_address.getAddress().getHostAddress();
+														
+														synchronized( access_logs){
+															
+															if ( !access_logs.contains( host )){
+																
+																access_logs.add( host );
+															
+																manager.log( "Ignoring browse from " + host + " due to access restriction for '" + renderer.getName() + "'" );
+															}
+														}
+													}
+														
+													browse_devices.add( renderer );
+													
+													renderer.browseReceived();
+												}
+											}
+										}
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}
+								}
+							}
+							
+							Map<String,Object> result = new HashMap<String, Object>();
+							
+							if ( browse_devices.size() > 0 ){
+								
+								synchronized( unassociated_devices ){
+									
+									unassociated_devices.remove( client_address.getAddress() );
+								}
+								
+								final boolean f_restrict_access = restrict_access;
+								
+								result.put(
+									"filter",
+									new AzureusContentFilter()
+									{
+										public boolean
+										isVisible(
+											AzureusContentDownload	download,
+											Map<String,Object>		browse_args )
+										{
+											if ( f_restrict_access ){
+												
+												return( false );
+											}
+											
+											boolean	visible = false;
+											
+											for ( DeviceUPnPImpl device: browse_devices ){
+												
+												if ( device.isVisible( download )){
+													
+													visible	= true;
+												}
+											}
+											
+											return( visible );
+										}
+										
+										public boolean
+										isVisible(
+											AzureusContentFile		file,
+											Map<String,Object>		browse_args )
+										{
+											if ( f_restrict_access ){
+												
+												return( false );
+											}
+											
+											boolean	visible = false;
+											
+											for ( DeviceUPnPImpl device: browse_devices ){
+												
+												if ( device.isVisible( file )){
+													
+													visible	= true;
+												}
+											}
+											
+											return( visible );
+										}
+									});
+							}else{
+								
+								if ( request.getHeader().substring(0,4).equalsIgnoreCase( "POST" )){
+									
+									synchronized( unassociated_devices ){
+									
+										unassociated_devices.put( client_address.getAddress(), user_agent );
+									}
+								}
+							}
+								
+							return( result );
+						}
+					});
+			
+			if ( upnpav_ipc.canInvoke( "addBrowseListener", new Object[]{ my_ipc })){
+								
+				DeviceImpl[] devices = manager.getDevices();
+				
+				for ( DeviceImpl device: devices ){
+				
+					if ( device instanceof DeviceUPnPImpl ){
+					
+						DeviceUPnPImpl u_d = (DeviceUPnPImpl)device;
+
+						u_d.resetUPNPAV();
+					}
+				}
+				
+				upnpav_ipc.invoke( "addBrowseListener", new Object[]{ my_ipc });
+
+			}else{
+				
+				manager.log( "UPnPAV plugin needs upgrading" );
+			}
+		}catch( Throwable e ){
+			
+			manager.log( "Failed to hook into UPnPAV", e );
+		}
+	}
+	
+	protected void
+	injectDiscoveryCache(
+		Map		cache )
+	{
+		try{
+			upnp.injectDiscoveryCache( cache );
+			
+		}catch( Throwable e ){
+	
+			Debug.out( e );
+		}
+	}
+	
+	public UnassociatedDevice[]
+	getUnassociatedDevices()
+	{
+		List<UnassociatedDevice> result = new ArrayList<UnassociatedDevice>();
+		
+		Map<InetAddress,String> ud;
+		
+		synchronized( unassociated_devices ){
+
+			ud = new HashMap<InetAddress,String>( unassociated_devices );
+		}
+		
+		DeviceImpl[] devices = manager.getDevices();
+
+		for ( final Map.Entry<InetAddress, String> entry: ud.entrySet()){
+			
+			InetAddress	address = entry.getKey();
+			
+			boolean already_assoc = false;
+
+			for ( DeviceImpl d: devices ){
+								
+				if ( d instanceof DeviceMediaRendererImpl ){
+					
+					DeviceMediaRendererImpl r = (DeviceMediaRendererImpl)d;
+					
+					InetAddress device_address = r.getAddress();
+					
+					if ( d.isAlive() && device_address != null && device_address.equals( address )){
+						
+						already_assoc = true;
+						
+						break;
+					}
+				}
+			}
+			
+			if ( !already_assoc ){
+				
+				result.add(
+					new UnassociatedDevice()
+					{
+						public InetAddress
+						getAddress()
+						{
+							return( entry.getKey());
+						}
+						
+						public String
+						getDescription()
+						{
+							return( entry.getValue());
+						}
+					});
+			}
+		}
+		
+		return( result.toArray( new UnassociatedDevice[result.size()]));
+	}
+	
+	public PluginInterface
+	getPluginInterface()
+	{
+		return( plugin_interface );
+	}
+	
+	protected IPCInterface
+	getUPnPAVIPC()
+	{
+		return( upnpav_ipc );
+	}
+	
+	public void
+	search()
+	{	
+		if ( upnp != null ){
+	
+			// if the user has removed items we need to re-inject them
+
+			UPnPRootDevice[] devices = upnp.getRootDevices();
+			
+			for ( UPnPRootDevice device: devices ){
+				
+				handleDevice( device, false );
+			}
+			
+			String[] STs = {
+				"upnp:rootdevice",
+				"urn:schemas-upnp-org:device:MediaRenderer:1",
+				"urn:schemas-upnp-org:service:ContentDirectory:1",
+			};
+			
+			upnp.search( STs );
+		}
+	}
+	
+	protected void
+	handleXBox(
+		InetSocketAddress	address )
+	{
+		// normally we can detect the xbox renderer and things work automagically. However, on
+		// occasion we receive the browse before detection and if the device's IP has changed
+		// we need to associate its new address here otherwise association of browse to device
+		// fails
+		
+		DeviceImpl[] devices = manager.getDevices();
+		
+		boolean	found = false;
+		
+		for ( DeviceImpl device: devices ){
+			
+			if ( device instanceof DeviceMediaRendererImpl ){
+				
+				DeviceMediaRendererImpl renderer = (DeviceMediaRendererImpl)device;
+				
+				if ( device.getRendererSpecies() == DeviceMediaRenderer.RS_XBOX ){
+
+					found = true;
+					
+					if (!device.isAlive()){
+				
+						renderer.setAddress( address.getAddress());
+						
+						device.alive();
+					}
+				}
+			}
+		}
+		
+		if ( !found ){
+			
+			manager.addDevice( new DeviceMediaRendererImpl( manager, "Xbox 360" ));
+		}
+	}
+	
+	protected void
+	handlePS3(
+		InetSocketAddress	address )
+	{
+		handleGeneric( address, "ps3", "PS3" );
+	}
+
+	protected void
+	handleWii(
+		InetSocketAddress	address )
+	{
+		handleGeneric( address, "wii", "Wii" );
+	}
+	
+	protected void
+	handleBrowser(
+		InetSocketAddress	address )
+	{
+		handleGeneric( address, "browser", "Browser" );
+	}
+	
+	protected DeviceMediaRenderer
+	handleVuzeMSBrowser(
+		InetSocketAddress	address,
+		String				info )
+	{
+		String[] bits = info.split( ";" );
+		
+		String	client = "";
+		
+		for ( String bit: bits ){
+			
+			String[] temp = bit.split( "=" );
+			
+			if ( temp.length == 2 && temp[0].trim().equalsIgnoreCase( "mn")){
+				
+				client = temp[1].trim();
+				
+				if ( client.startsWith( "\"" )){
+					
+					client = client.substring(1);
+				}
+				
+				if ( client.endsWith( "\"" )){
+					
+					client = client.substring( 0, client.length()-1);
+				}
+			}
+		}
+		
+		if ( client.length() == 0 ){
+			
+			client = "Vuze on " + address.getAddress().getHostAddress();
+		}
+		
+		DeviceMediaRenderer result = handleGeneric( address, "vuze-ms-browser." + client, client );
+		
+		result.setTranscodeRequirement( TranscodeTarget.TRANSCODE_NEVER );
+		
+		return( result );
+	}
+	
+	protected DeviceMediaRenderer
+	handleGeneric(
+		InetSocketAddress	address,
+		String				unique_name,
+		String				display_name )
+	{
+		String uid;
+		
+		synchronized( this ){
+			
+				// don't use 'unique-name' directly as a key as it might incldued non-ascii chars which must not
+				// be used as a key in a bencoded map
+				// migrated from prefix of "devices.upnp.uid." to "devices.upnp.uid2."
+			
+			String un_key;
+			
+			try{
+				un_key = Base32.encode( unique_name.getBytes( "UTF-8" ));
+				
+			}catch( Throwable e ){
+				
+				un_key = Base32.encode( unique_name.getBytes());
+			}
+			
+			String	new_key = "devices.upnp.uid2." + un_key;
+			
+			uid = COConfigurationManager.getStringParameter( new_key, "" );
+			
+			if ( uid.length() == 0 ){
+				
+				String old_key = "devices.upnp.uid." + unique_name;
+				
+				uid = COConfigurationManager.getStringParameter( old_key, "" );
+				
+				if ( uid.length() > 0 ){
+					
+					COConfigurationManager.setParameter( new_key, uid );
+					
+					COConfigurationManager.removeParameter( old_key );
+					
+				}else{
+					
+					uid = UUIDGenerator.generateUUIDString();
+					
+					COConfigurationManager.setParameter( new_key, uid );
+					
+					COConfigurationManager.save();
+				}
+			}
+		}
+		
+		DeviceMediaRendererImpl newDevice = new DeviceMediaRendererImpl( manager, uid, unique_name, false, display_name );
+		
+		DeviceMediaRendererImpl device = (DeviceMediaRendererImpl)manager.addDevice( newDevice );
+		
+			// there's auto-hide code to hide devices created by receiving a browser event
+			// when a concrete upnp-based version is discovered at the same IP
+			// we don't want this happening for these generic devices, especially the Browser one
+			// as it is straight forward to get browse events from this on an IP that also
+			// happens to be exposing UPnP devices (e.g. windows media player)
+		
+		device.setPersistentBooleanProperty( DeviceImpl.PP_DONT_AUTO_HIDE, true );
+		
+		device.setAddress( address.getAddress());
+		
+		device.alive();
+
+		return device;
+	}
+	
+	protected void
+	handleDevice(
+		UPnPRootDevice		root_device,
+		boolean				update_if_found )
+	{
+		if ( !manager.getAutoSearch()){
+			
+			if ( !manager.isExplicitSearch()){
+				
+				return;
+			}
+		}
+		
+		handleDevice( root_device.getDevice(), update_if_found );
+	}
+	
+	protected void
+	handleDevice(
+		UPnPDevice	device,
+		boolean		update_if_found )
+	{
+		UPnPService[] 	services = device.getServices();
+		
+		List<DeviceUPnPImpl>	new_devices = new ArrayList<DeviceUPnPImpl>();
+		
+		List<UPnPWANConnection>	igd_services = new ArrayList<UPnPWANConnection>();
+		
+		for ( UPnPService service: services ){
+				
+			String	service_type = service.getServiceType();
+				
+			if ( 	service_type.equalsIgnoreCase( "urn:schemas-upnp-org:service:WANIPConnection:1") || 
+					service_type.equalsIgnoreCase( "urn:schemas-upnp-org:service:WANPPPConnection:1")){
+				
+				UPnPWANConnection	wan_service = (UPnPWANConnection)service.getSpecificService();
+				
+				igd_services.add( wan_service );				
+
+			}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 ));
+				}
+			}
+		}
+		
+		if ( igd_services.size() > 0 ){
+			
+			new_devices.add( new DeviceInternetGatewayImpl( manager, device, igd_services ));
+		}
+		
+		if ( device.getDeviceType().equals( "urn:schemas-upnp-org:device:MediaRenderer:1" )){
+				
+			new_devices.add( new DeviceMediaRendererImpl( manager, device ));
+		}
+		
+		for ( final DeviceUPnPImpl new_device: new_devices ){
+				
+			final DeviceImpl actual_device;
+			
+			DeviceImpl existing = manager.getDevice( new_device.getID());
+			
+			if ( !update_if_found && existing != null ){
+					
+				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 );
+			}
+			
+			UPnPRootDevice current_root = device.getRootDevice();
+			
+			UPnPRootDevice existing_root = (UPnPRootDevice)actual_device.getTransientProperty( KEY_ROOT_DEVICE );
+			
+			if ( current_root != existing_root ){
+				
+				actual_device.setTransientProperty( KEY_ROOT_DEVICE, current_root );
+				
+				current_root.addListener(
+					new UPnPRootDeviceListener()
+					{
+						public void
+						lost(
+							UPnPRootDevice	root,
+							boolean			replaced )
+						{
+							if ( !replaced ){
+								
+								actual_device.dead();
+							}
+						}
+					});
+			}
+		}
+		
+		for (UPnPDevice d: device.getSubDevices()){
+			
+			handleDevice( d, update_if_found );
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererImpl.java
index 35b08cb..9ea4c57 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererImpl.java
@@ -1,358 +1,560 @@
-/*
- * 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.File;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.util.List;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.IndentWriter;
-
-import com.aelitis.azureus.core.devices.*;
-import com.aelitis.net.upnp.UPnPDevice;
-import com.aelitis.net.upnp.impl.device.UPnPDeviceImpl;
-
-public class 
-DeviceMediaRendererImpl
-	extends DeviceUPnPImpl
-	implements DeviceMediaRenderer
-{
-	public
-	DeviceMediaRendererImpl(
-		DeviceManagerImpl	_manager,
-		UPnPDevice			_device )
-	{
-		super( _manager, _device, Device.DT_MEDIA_RENDERER );
-	}
-	
-	public
-	DeviceMediaRendererImpl(
-		DeviceManagerImpl	_manager,
-		String				_classification )
-	{
-		super( _manager, Device.DT_MEDIA_RENDERER, _classification );
-	}
-	
-	public
-	DeviceMediaRendererImpl(
-		DeviceManagerImpl	_manager,
-		String				_uuid,
-		String				_classification,
-		boolean				_manual,
-		String				_name )
-	{
-		super( _manager, Device.DT_MEDIA_RENDERER, _uuid, _classification, _manual, _name );
-	}
-	
-	public
-	DeviceMediaRendererImpl(
-		DeviceManagerImpl	_manager,
-		String				_uuid,
-		String				_classification,
-		boolean				_manual )
-	{
-		super( _manager, Device.DT_MEDIA_RENDERER, _uuid, _classification, _manual );
-	}
-	
-	protected
-	DeviceMediaRendererImpl(
-		DeviceManagerImpl	_manager,
-		Map					_map )
-	
-		throws IOException
-	{
-		super(_manager, _map );
-	}
-	
-	public void setAddress(InetAddress address) {
-		super.setAddress(address);
-		
-		if ( getType() == DT_MEDIA_RENDERER) {
-			//System.out.println("Set Address " + address.getHostAddress() + "; " + getName() + "/" + getClassification());
-
-			boolean hasUPnPDevice = getUPnPDevice() != null;
-			DeviceImpl[] devices = getManager().getDevices();
-			for (DeviceImpl device : devices) {
-				if (device == this || device.getID().equals(getID())
-						|| !((device instanceof DeviceUPnPImpl))) {
-					continue;
-				}
-				DeviceUPnPImpl deviceUPnP = ((DeviceUPnPImpl) device);
-				if (!address.equals(device.getAddress()) || !device.isAlive()) {
-					continue;
-				}
-				
-				
-				if (hasUPnPDevice) {
-					boolean no_auto_hide = device.getPersistentBooleanProperty( DeviceImpl.PP_DONT_AUTO_HIDE, false );
-
-					if (device.getType() == DT_MEDIA_RENDERER && !no_auto_hide ) {
-						// prefer UPnP Device over Manual one added by a Browse event
-						if (deviceUPnP.getUPnPDevice() != null) {
-							int fileCount = deviceUPnP.getFileCount();
-							if (fileCount == 0 && !device.isHidden()) {
-								log("Hiding " + device.getName() + "/"
-										+ device.getClassification() + "/" + device.getID()
-										+ " due to " + getName() + "/" + getClassification() + "/"
-										+ getID());
-  							device.setHidden(true);
-							}
-						}
-					}
-				} else {
-					if (device.getType() == DT_MEDIA_RENDERER ){
-						boolean no_auto_hide = getPersistentBooleanProperty( DeviceImpl.PP_DONT_AUTO_HIDE, false );
-
-						if ( !no_auto_hide ){
-							int fileCount = getFileCount();
-							// prefer UPnP Device over Manual one added by a Browse event
-							if (fileCount == 0 && !isHidden()) {
-								log("hiding " + getName() + "/" + getClassification() + "/"
-										+ getID() + " due to " + device.getName() + "/"
-										+ device.getClassification() + "/" + device.getID());
-								setHidden(true);
-							} else if (fileCount > 0 && Constants.IS_CVS_VERSION && isHidden()) {
-								// Fix beta bug where we hid devices that had files.  Remove after 4605
-								setHidden(false);
-							}
-						}
-					} else {
-						// Device has UPnP stuff, but did not register itself as
-						// renderer.
-  					UPnPDevice upnpDevice = deviceUPnP.getUPnPDevice();
-  					if (upnpDevice != null) {
-    					String manufacturer = upnpDevice.getManufacturer();
-    					if (manufacturer == null || !manufacturer.startsWith("Vuze")) {
-    						log("Linked " + getName() + " to UPnP Device " + device.getName());
-      					setUPnPDevice(upnpDevice);
-      					setDirty();
-    					}
-  					}
-					}
-				}
-				break;
-			}
-		}
-	}
-	
-	@Override
-	protected boolean
-	updateFrom(
-		DeviceImpl		_other,
-		boolean			_is_alive )
-	{
-		if ( !super.updateFrom( _other, _is_alive )){
-			
-			return( false );
-		}
-		
-		if ( !( _other instanceof DeviceMediaRendererImpl )){
-			
-			Debug.out( "Inconsistent" );
-			
-			return( false );
-		}
-		
-		DeviceMediaRendererImpl other = (DeviceMediaRendererImpl)_other;
-		
-		return( true );
-	}
-	
-	@Override
-	protected void
-	initialise()
-	{
-		super.initialise();
-	}
-	
-	@Override
-	protected void
-	destroy()
-	{
-		super.destroy();
-	}
-	
-	public boolean
-	canCopyToDevice()
-	{
-		return( false );
-	}
-	
-	public boolean
-	getAutoCopyToDevice()
-	{
-		return( false );
-	}
-		
-	public void
-	setAutoCopyToDevice(
-		boolean		auto )
-	{
-	}
-	
-	public int
-	getCopyToDevicePending()
-	{
-		return( 0 );
-	}
-	
-	public boolean
-	canAutoStartDevice()
-	{
-		return( false );
-	}
-	
-	public boolean
-	getAutoStartDevice()
-	{
-		return( false );
-	}
-	
-	public void
-	setAutoStartDevice(
-		boolean		auto )
-	{
-	}
-	
-	public boolean
-	canCopyToFolder()
-	{
-		return( false );
-	}
-	
-	public void
-	setCanCopyToFolder(
-		boolean		can )
-	{
-		// nothing to do
-	}
-	
-	public File
-	getCopyToFolder()
-	{
-		return( null );
-	}
-	
-	public void
-	setCopyToFolder(
-		File		file )
-	{
-	}
-	
-	public int
-	getCopyToFolderPending()
-	{
-		return( 0 );
-	}
-	
-	public boolean
-	getAutoCopyToFolder()
-	{
-		return( false );
-	}
-		
-	public void
-	setAutoCopyToFolder(
-		boolean		auto )
-	{
-	}
-	
-	public void 
-	manualCopy() 
-	
-		throws DeviceManagerException 
-	{
-		throw( new DeviceManagerException( "Unsupported" ));
-	}
-	
-	public boolean
-	canShowCategories()
-	{
-		return( false );
-	}
-	
-	public void
-	setShowCategories(
-		boolean	b )
-	{
-		setPersistentBooleanProperty( PP_REND_SHOW_CAT, b );
-	}
-	
-	public boolean
-	getShowCategories()
-	{
-		return( getPersistentBooleanProperty( PP_REND_SHOW_CAT, getShowCategoriesDefault()));
-	}
-	
-	protected boolean
-	getShowCategoriesDefault()
-	{
-		return( false );
-	}
-	
-	@Override
-	protected void
-	getDisplayProperties(
-		List<String[]>	dp )
-	{
-		super.getDisplayProperties( dp );
-
-		if ( canCopyToFolder()){
-			
-			addDP( dp, "devices.copy.folder.auto", getAutoCopyToFolder());
-			addDP( dp, "devices.copy.folder.dest", getCopyToFolder());
-		}
-		
-		if ( canCopyToDevice()){
-			addDP( dp, "devices.copy.device.auto", getAutoCopyToDevice());
-		}
-		
-		if ( canShowCategories()){
-			
-			addDP( dp, "devices.cat.show", getShowCategories());
-
-		}
-		super.getTTDisplayProperties( dp );
-	}	
-	
-	@Override
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		super.generate( writer );
-		
-		try{
-			writer.indent();
-	
-			generateTT( writer );
-			
-		}finally{
-			
-			writer.exdent();
-		}
-	}
-}
+/*
+ * Created on Jan 28, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
+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.IndentWriter;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.PluginManager;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.sharing.ShareManager;
+import org.gudy.azureus2.plugins.sharing.ShareResourceDir;
+import org.gudy.azureus2.plugins.sharing.ShareResourceFile;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+
+import com.aelitis.azureus.core.devices.*;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManager;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.Taggable;
+import com.aelitis.net.upnp.UPnPDevice;
+
+public class 
+DeviceMediaRendererImpl
+	extends DeviceUPnPImpl
+	implements DeviceMediaRenderer
+{
+	private static final int INSTALL_CHECK_PERIOD	= 60*1000;
+	private static final int TAG_SHARE_CHECK_TICKS	= INSTALL_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
+
+	public
+	DeviceMediaRendererImpl(
+		DeviceManagerImpl	_manager,
+		UPnPDevice			_device )
+	{
+		super( _manager, _device, Device.DT_MEDIA_RENDERER );
+	}
+	
+	public
+	DeviceMediaRendererImpl(
+		DeviceManagerImpl	_manager,
+		String				_classification )
+	{
+		super( _manager, Device.DT_MEDIA_RENDERER, _classification );
+	}
+	
+	public
+	DeviceMediaRendererImpl(
+		DeviceManagerImpl	_manager,
+		String				_uuid,
+		String				_classification,
+		boolean				_manual,
+		String				_name )
+	{
+		super( _manager, Device.DT_MEDIA_RENDERER, _uuid, _classification, _manual, _name );
+	}
+	
+	public
+	DeviceMediaRendererImpl(
+		DeviceManagerImpl	_manager,
+		String				_uuid,
+		String				_classification,
+		boolean				_manual )
+	{
+		super( _manager, Device.DT_MEDIA_RENDERER, _uuid, _classification, _manual );
+	}
+	
+	protected
+	DeviceMediaRendererImpl(
+		DeviceManagerImpl	_manager,
+		Map					_map )
+	
+		throws IOException
+	{
+		super(_manager, _map );
+	}
+	
+	public void setAddress(InetAddress address) {
+		super.setAddress(address);
+		
+		if ( getType() == DT_MEDIA_RENDERER) {
+			//System.out.println("Set Address " + address.getHostAddress() + "; " + getName() + "/" + getClassification());
+
+			boolean hasUPnPDevice = getUPnPDevice() != null;
+			DeviceImpl[] devices = getManager().getDevices();
+			for (DeviceImpl device : devices) {
+				if (device == this || device.getID().equals(getID())
+						|| !((device instanceof DeviceUPnPImpl))) {
+					continue;
+				}
+				DeviceUPnPImpl deviceUPnP = ((DeviceUPnPImpl) device);
+				if (!address.equals(device.getAddress()) || !device.isAlive()) {
+					continue;
+				}
+				
+				
+				if (hasUPnPDevice) {
+					boolean no_auto_hide = device.getPersistentBooleanProperty( DeviceImpl.PP_DONT_AUTO_HIDE, false );
+
+					if (device.getType() == DT_MEDIA_RENDERER && !no_auto_hide ) {
+						// prefer UPnP Device over Manual one added by a Browse event
+						if (deviceUPnP.getUPnPDevice() != null) {
+							int fileCount = deviceUPnP.getFileCount();
+							if (fileCount == 0 && !device.isHidden()) {
+								log("Hiding " + device.getName() + "/"
+										+ device.getClassification() + "/" + device.getID()
+										+ " due to " + getName() + "/" + getClassification() + "/"
+										+ getID());
+  							device.setHidden(true);
+							}
+						}
+					}
+				} else {
+					if (device.getType() == DT_MEDIA_RENDERER ){
+						boolean no_auto_hide = getPersistentBooleanProperty( DeviceImpl.PP_DONT_AUTO_HIDE, false );
+
+						if ( !no_auto_hide ){
+							int fileCount = getFileCount();
+							// prefer UPnP Device over Manual one added by a Browse event
+							if (fileCount == 0 && !isHidden()) {
+								log("hiding " + getName() + "/" + getClassification() + "/"
+										+ getID() + " due to " + device.getName() + "/"
+										+ device.getClassification() + "/" + device.getID());
+								setHidden(true);
+							} else if (fileCount > 0 && Constants.IS_CVS_VERSION && isHidden()) {
+								// Fix beta bug where we hid devices that had files.  Remove after 4605
+								setHidden(false);
+							}
+						}
+					} else {
+						// Device has UPnP stuff, but did not register itself as
+						// renderer.
+  					UPnPDevice upnpDevice = deviceUPnP.getUPnPDevice();
+  					if (upnpDevice != null) {
+    					String manufacturer = upnpDevice.getManufacturer();
+    					if (manufacturer == null || !manufacturer.startsWith("Vuze")) {
+    						log("Linked " + getName() + " to UPnP Device " + device.getName());
+      					setUPnPDevice(upnpDevice);
+      					setDirty();
+    					}
+  					}
+					}
+				}
+				break;
+			}
+		}
+	}
+	
+	@Override
+	protected boolean
+	updateFrom(
+		DeviceImpl		_other,
+		boolean			_is_alive )
+	{
+		if ( !super.updateFrom( _other, _is_alive )){
+			
+			return( false );
+		}
+		
+		if ( !( _other instanceof DeviceMediaRendererImpl )){
+			
+			Debug.out( "Inconsistent" );
+			
+			return( false );
+		}
+		
+		DeviceMediaRendererImpl other = (DeviceMediaRendererImpl)_other;
+		
+		return( true );
+	}
+	
+	@Override
+	protected void
+	initialise()
+	{
+		super.initialise();
+	}
+	
+	private static TorrentAttribute	share_ta;
+	private static List<Object[]>	share_requests		= new ArrayList<Object[]>();
+	private static AsyncDispatcher	share_dispatcher 	= new AsyncDispatcher();
+	
+	protected void
+	updateStatus(
+		int		tick_count )
+	{
+		super.updateStatus(tick_count);
+		
+		if ( 	tick_count > 0 && 
+				tick_count % TAG_SHARE_CHECK_TICKS == 0 ){
+			
+			long	tag_id = getAutoShareToTagID();
+			
+			if ( tag_id != -1 ){
+				
+				synchronized( DeviceMediaRendererImpl.class ){
+					
+					if ( share_ta == null ){
+						
+						share_ta = PluginInitializer.getDefaultInterface().getTorrentManager().getPluginAttribute( "DeviceMediaRendererImpl:tag_share" );
+					}
+				}
+				
+				TagManager tm = TagManagerFactory.getTagManager();
+				
+				Tag assigned_tag = tm.lookupTagByUID( tag_id );
+
+				if ( assigned_tag != null ){
+							
+					assigned_tag.setPublic( false );	// not going to want this to be public
+
+					synchronized( share_requests ){
+						
+						if ( share_requests.size() == 0 ){
+						
+							Set<Taggable> taggables = assigned_tag.getTagged();
+							
+							Set<String>	done_files = new HashSet<String>();
+							
+							for ( Taggable temp: taggables ){
+								
+								if ( !( temp instanceof DownloadManager )){
+									
+									continue;
+								}
+								
+								DownloadManager dm = (DownloadManager)temp;
+								
+								Download download = PluginCoreUtils.wrap( dm );
+								
+								String attr = download.getAttribute( share_ta );
+								
+								if ( attr != null ){
+									
+									done_files.add( attr );
+								}
+							}
+					
+							TranscodeFileImpl[] files = getFiles();
+							
+							for ( TranscodeFileImpl file: files ){
+								
+								if ( file.isComplete()){
+									
+									try{
+										File target_file = file.getTargetFile().getFile( true );
+										
+										long size = target_file.length();
+										
+										if ( target_file.exists() && size > 0 ){
+											
+											String suffix = " (" + file.getProfileName() + " - " + DisplayFormatters.formatByteCountToKiBEtc( size ) + ")";
+											
+											String share_name	= file.getName() + suffix;
+											String key 			= target_file.getName() + suffix;
+											
+											if ( !done_files.contains( key )){
+												
+												share_requests.add( new Object[]{ key, target_file, share_name, assigned_tag });												
+											}
+										}
+									}catch( Throwable e ){
+										
+									}
+								}
+							}
+							
+							if ( share_requests.size() > 0 ){
+								
+								shareRequestAdded();
+							}
+						}
+					}
+				}
+			}
+		}	
+	}
+	
+	private void
+	shareRequestAdded()
+	{
+		share_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void 
+				runSupport() 
+				{
+					List<Object[]>	to_process;
+					
+					synchronized( share_requests ){
+
+						to_process = new ArrayList<Object[]>( share_requests );
+					}
+					
+					for ( Object[] entry: to_process ){
+						
+						try{
+							String	key 	= (String)entry[0];
+							File	file	= (File)entry[1];
+							String	name 	= (String)entry[2];
+							Tag		tag 	= (Tag)entry[3];
+							
+							log( "Auto sharing " + name + " (" + file + ") to tag " + tag.getTagName( true ));
+							
+							Map<String,String>	properties = new HashMap<String, String>();
+
+							properties.put( ShareManager.PR_USER_DATA, "device:autoshare" );
+							
+								// currently no way for user to explicitly specify the networks to use so use defaults
+							
+							String[] networks = AENetworkClassifier.getDefaultNetworks();
+							
+							String networks_str = "";
+							
+							for ( String net: networks ){
+								
+								networks_str += (networks_str.length()==0?"":",") + net;
+							}
+							
+							properties.put( ShareManager.PR_NETWORKS, networks_str );
+							
+							properties.put( ShareManager.PR_TAGS, String.valueOf( tag.getTagUID()));
+							
+							PluginInterface pi = PluginInitializer.getDefaultInterface();
+							
+							ShareResourceFile srf = pi.getShareManager().addFile( file, properties );
+															
+							Torrent torrent = srf.getItem().getTorrent();								
+													
+							final Download download = pi.getPluginManager().getDefaultPluginInterface().getShortCuts().getDownload( torrent.getHash());
+	
+							if ( download == null ){
+								
+								throw( new Exception( "Download no longer exists" ));
+							}
+
+							DownloadManager dm = PluginCoreUtils.unwrap( download );
+							
+							dm.getDownloadState().setDisplayName( name );
+														
+							download.setAttribute( share_ta, key );
+							
+						}catch( Throwable e ){
+							
+							log( "Auto sharing failed", e );
+						}
+					}
+					
+					synchronized( share_requests ){
+						
+						share_requests.removeAll( to_process );
+					}
+				}
+			});
+	}
+	
+	@Override
+	protected void
+	destroy()
+	{
+		super.destroy();
+	}
+	
+	public boolean
+	canCopyToDevice()
+	{
+		return( false );
+	}
+	
+	public boolean
+	getAutoCopyToDevice()
+	{
+		return( false );
+	}
+		
+	public void
+	setAutoCopyToDevice(
+		boolean		auto )
+	{
+	}
+	
+	public int
+	getCopyToDevicePending()
+	{
+		return( 0 );
+	}
+	
+	public boolean
+	canAutoStartDevice()
+	{
+		return( false );
+	}
+	
+	public boolean
+	getAutoStartDevice()
+	{
+		return( false );
+	}
+	
+	public void
+	setAutoStartDevice(
+		boolean		auto )
+	{
+	}
+	
+	public boolean
+	canCopyToFolder()
+	{
+		return( false );
+	}
+	
+	public void
+	setCanCopyToFolder(
+		boolean		can )
+	{
+		// nothing to do
+	}
+	
+	public File
+	getCopyToFolder()
+	{
+		return( null );
+	}
+	
+	public void
+	setCopyToFolder(
+		File		file )
+	{
+	}
+	
+	public int
+	getCopyToFolderPending()
+	{
+		return( 0 );
+	}
+	
+	public boolean
+	getAutoCopyToFolder()
+	{
+		return( false );
+	}
+		
+	public void
+	setAutoCopyToFolder(
+		boolean		auto )
+	{
+	}
+	
+	public void 
+	manualCopy() 
+	
+		throws DeviceManagerException 
+	{
+		throw( new DeviceManagerException( "Unsupported" ));
+	}
+	
+	public boolean
+	canShowCategories()
+	{
+		return( false );
+	}
+	
+	public void
+	setShowCategories(
+		boolean	b )
+	{
+		setPersistentBooleanProperty( PP_REND_SHOW_CAT, b );
+	}
+	
+	public boolean
+	getShowCategories()
+	{
+		return( getPersistentBooleanProperty( PP_REND_SHOW_CAT, getShowCategoriesDefault()));
+	}
+	
+	protected boolean
+	getShowCategoriesDefault()
+	{
+		return( false );
+	}
+	
+	@Override
+	protected void
+	getDisplayProperties(
+		List<String[]>	dp )
+	{
+		super.getDisplayProperties( dp );
+
+		if ( canCopyToFolder()){
+			
+			addDP( dp, "devices.copy.folder.auto", getAutoCopyToFolder());
+			addDP( dp, "devices.copy.folder.dest", getCopyToFolder());
+		}
+		
+		if ( canCopyToDevice()){
+			addDP( dp, "devices.copy.device.auto", getAutoCopyToDevice());
+		}
+		
+		if ( canShowCategories()){
+			
+			addDP( dp, "devices.cat.show", getShowCategories());
+
+		}
+		super.getTTDisplayProperties( dp );
+	}	
+	
+	@Override
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		super.generate( writer );
+		
+		try{
+			writer.indent();
+	
+			generateTT( writer );
+			
+		}finally{
+			
+			writer.exdent();
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererManual.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererManual.java
index 78f9b40..8411ae7 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererManual.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererManual.java
@@ -1,649 +1,648 @@
-/*
- * Created on Jul 10, 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.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-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.AsyncDispatcher;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.FileUtil;
-import org.gudy.azureus2.core3.util.IndentWriter;
-
-import com.aelitis.azureus.core.devices.DeviceManagerException;
-import com.aelitis.azureus.core.devices.TranscodeException;
-import com.aelitis.azureus.core.devices.TranscodeFile;
-import com.aelitis.azureus.core.devices.TranscodeTargetListener;
-
-
-public class 
-DeviceMediaRendererManual 
-	extends DeviceMediaRendererImpl
-{
-	private static final Object	COPY_ERROR_KEY 		= new Object();
-	private static final Object	COPY_PENDING_KEY 	= new Object();
-
-	private boolean				can_copy_to_folder	= true;
-	private boolean				copy_outstanding;
-	private boolean				copy_outstanding_set;
-	private AEThread2			copy_thread;
-	private AESemaphore			copy_sem = new AESemaphore( "Device:copy" );
-	private AsyncDispatcher		async_dispatcher = new AsyncDispatcher( 5000 );
-
-	protected
-	DeviceMediaRendererManual(
-		DeviceManagerImpl	_manager,
-		String				_uid,
-		String				_classification,
-		boolean				_manual,
-		String				_name )
-	{
-		super( _manager, _uid, _classification, _manual, _name );
-	}
-	
-	protected
-	DeviceMediaRendererManual(
-		DeviceManagerImpl	_manager,
-		Map					_map )
-	
-		throws IOException
-	{
-		super(_manager, _map );
-	}
-	
-	protected void
-	initialise()
-	{
-		super.initialise();
-		
-		if ( getPersistentBooleanProperty( PP_COPY_OUTSTANDING, false )){
-		
-			setCopyOutstanding();
-		}
-		
-		addListener( 
-			new TranscodeTargetListener()
-			{
-				public void
-				fileAdded(
-					TranscodeFile		file )
-				{
-					updateStatus( file );
-				}
-				
-				public void
-				fileChanged(
-					TranscodeFile		file,
-					int					type,
-					Object				data )
-				{
-					updateStatus( file );
-				}
-				
-				public void
-				fileRemoved(
-					TranscodeFile		file )
-				{	
-						// do this to pick up change in copy-to-device state caused by removal
-					
-					setCopyOutstanding();
-				}
-				
-				private void
-				updateStatus(
-					TranscodeFile		file )
-				{
-					if ( file.isComplete() && !file.isCopiedToDevice()){
-						
-						setCopyOutstanding();
-					}
-				}
-			});
-	}
-	
-	public boolean 
-	canAssociate() 
-	{
-		return( false );
-	}
-	
-	public boolean
-	canRestrictAccess()
-	{
-		return( false );
-	}
-	
-	public boolean
-	canFilterFilesView() 
-	{
-		return( false );
-	}
-	
-	public boolean
-	isBrowsable()
-	{
-		return( false );
-	}
-	
-	public boolean
-	canCopyToFolder()
-	{
-		return( can_copy_to_folder );
-	}
-	
-	public void
-	setCanCopyToFolder(
-		boolean		can )
-	{
-		can_copy_to_folder = can;
-		
-		if ( !can ){
-			
-			setPersistentBooleanProperty( PP_COPY_OUTSTANDING, false );
-			
-			synchronized( this ){
-				copy_outstanding 		= false;
-				copy_outstanding_set	= false;
-			}
-		}
-	}
-	
-	public File
-	getCopyToFolder()
-	{
-		String str = getPersistentStringProperty( PP_COPY_TO_FOLDER, null );
-		
-		if ( str == null ){
-			
-			return( null );
-		}
-		
-		return( new File( str ));
-	}
-	
-	public void
-	setCopyToFolder(
-		File		file )
-	{
-		setPersistentStringProperty( PP_COPY_TO_FOLDER, file==null?null:file.getAbsolutePath());
-		
-		if ( getAutoCopyToFolder()){
-			
-			setCopyOutstanding();
-		}
-	}
-	
-	public boolean
-	isLivenessDetectable()
-	{
-		return( getPersistentBooleanProperty( PP_LIVENESS_DETECTABLE, false ));
-	}
-	
-	public void
-	setLivenessDetectable(
-		boolean	b )
-	{
-		setPersistentBooleanProperty( PP_LIVENESS_DETECTABLE, true );
-	}
-	
-	public int
-	getCopyToFolderPending()
-	{
-		if ( !can_copy_to_folder ){
-			
-			return( 0 );
-		}
-		
-		synchronized( this ){
-			
-			if ( !copy_outstanding ){
-				
-				return( 0 );
-			}
-		}
-
-		TranscodeFileImpl[] files = getFiles();
-		
-		int result = 0;
-			
-		for ( TranscodeFileImpl file: files ){
-
-			if ( file.isComplete() && !file.isCopiedToDevice()){
-				
-				result++;
-			}
-		}
-		
-		return( result );
-	}
-	
-	public boolean
-	getAutoCopyToFolder()
-	{
-		return( getPersistentBooleanProperty( PP_AUTO_COPY, PP_AUTO_COPY_DEFAULT  ));
-	}
-		
-	public void
-	setAutoCopyToFolder(
-		boolean		auto )
-	{
-		setPersistentBooleanProperty( PP_AUTO_COPY, auto );
-			
-		setCopyOutstanding();
-	}
-	
-	public void 
-	manualCopy() 
-	
-		throws DeviceManagerException 
-	{
-		if ( getAutoCopyToFolder()){
-			
-			throw( new DeviceManagerException( "Operation prohibited - auto copy enabled" ));
-		}
-		
-		doCopy();
-	}
-	
-	protected void
-	setCopyOutstanding()
-	{
-		if ( !can_copy_to_folder ){
-			
-			return;
-		}
-		
-		synchronized( this ){
-			
-			copy_outstanding_set = true;
-			
-			if ( copy_thread == null ){
-				
-				copy_thread = 
-					new AEThread2( "Device:copier", true )
-					{
-						public void
-						run()
-						{
-							performCopy();
-						}
-					};
-									
-				copy_thread.start();
-			}
-			
-			copy_sem.release();
-		}
-	}
-	
-	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()
-	{
-		if ( !can_copy_to_folder ){
-			
-			return;
-		}
-		
-		synchronized( this ){
-
-			copy_outstanding = true;
-		
-			async_dispatcher.dispatch(
-				new AERunnable()
-				{
-					public void
-					runSupport()
-					{
-						setPersistentBooleanProperty( PP_COPY_OUTSTANDING, true );
-					}
-				});
-		}
-		
-		while( true ){
-			
-			if ( copy_sem.reserve( 10*1000 )){
-				
-				while( copy_sem.reserveIfAvailable());
-			}
-						
-			boolean	auto_copy = getAutoCopyToFolder();
-			
-			boolean	nothing_to_do = false;
-			
-			synchronized( this ){
-
-				if ( !auto_copy ){
-											
-					copy_thread = null;
-						
-					nothing_to_do = true;
-					
-				}else{
-
-					copy_outstanding_set = false;
-				}
-			}
-			
-			if ( nothing_to_do ){
-				
-				setError( COPY_ERROR_KEY, null );
-				
-				int pending = getCopyToFolderPending();
-				
-				if ( pending == 0 ){
-					
-					setInfo( COPY_PENDING_KEY, null );
-					
-				}else{
-					
-					String str = MessageText.getString( "devices.info.copypending", new String[]{ String.valueOf( pending ) });
-					
-					setInfo( COPY_PENDING_KEY, str );
-				}
-				return;
-			}
-			
-
-			if ( doCopy()){
-				
-				break;
-			}
-		}
-	}
-	
-	protected boolean
-	doCopy()
-	{
-		if ( !can_copy_to_folder ){
-			
-			return( true );
-		}
-		
-		setInfo( COPY_PENDING_KEY, null );
-
-		
-		File	copy_to = getCopyToFolder();
-		
-		List<TranscodeFileImpl>	to_copy = new ArrayList<TranscodeFileImpl>();
-
-		boolean	borked = false;
-		
-		TranscodeFileImpl[] files = getFiles();
-			
-		int	pending = 0;
-		
-		for ( TranscodeFileImpl file: files ){
-				
-			if ( file.isComplete() && !file.isCopiedToDevice()){
-				
-				pending++;
-				
-				if ( file.getCopyToDeviceFails() < 3 ){
-				
-					to_copy.add( file );
-					
-				}else{
-						
-					String info = (String)file.getTransientProperty( COPY_ERROR_KEY );
-					
-					setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copyfail") + (info==null?"":(" - " + info)));
-
-					borked = true;
-				}
-			}
-		}
-		
-		boolean	try_copy = false;
-		
-		if ( to_copy.size() > 0 ){
-			
-				// handle case where device is auto-detectable and copy-to is missing
-			
-			if ( isLivenessDetectable() && !isAlive() && ( copy_to == null || !copy_to.exists())){
-			
-				String str = MessageText.getString( "devices.info.copypending2", new String[]{ String.valueOf( pending ) });
-				
-				setInfo( COPY_PENDING_KEY, str );
-				
-				borked = true;
-				
-			}else{
-				setInfo( COPY_PENDING_KEY, null );
-				
-				boolean	sub_borked = false;
-				
-				if ( copy_to == null ){
-				
-					setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copytonotset" ));
-					
-					sub_borked = true;
-					
-				}else if ( !copy_to.exists()){
-					
-					// due to the two-phase mount of android devices and the fact that the
-					// copy-to location is %root$/videos, the root might exist but the sub-folder 
-					// not. 
-					
-					File parent = copy_to.getParentFile();
-					
-					if ( parent != null && parent.canWrite()){
-						
-						copy_to.mkdir();
-					}
-					
-					if ( !copy_to.exists()){
-					
-						setError( COPY_ERROR_KEY, MessageText.getString( "device.error.mountrequired", new String[]{copy_to.getAbsolutePath()}));
-
-						sub_borked = true;
-					}
-
-					//setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copytomissing", new String[]{copy_to.getAbsolutePath()}));
-					//sub_borked = true;
-				}
-				
-				if ( !sub_borked ){
-				
-					if ( !copy_to.canWrite()){
-					
-						setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copytonowrite", new String[]{copy_to.getAbsolutePath()}));
-					
-						sub_borked = true;
-					
-					}else{
-					
-						try_copy = true;
-					
-						setError( COPY_ERROR_KEY, null );
-					}
-				}
-			
-				borked = borked | sub_borked;
-			}
-		} else {
-
-			setInfo( COPY_PENDING_KEY, null );
-		}
-		
-		synchronized( this ){
-
-				// all done, tidy up and exit
-			
-			if ( to_copy.size() == 0 && !copy_outstanding_set && !borked ){
-					
-				copy_outstanding = false;
-				
-				async_dispatcher.dispatch(
-					new AERunnable()
-					{
-						public void
-						runSupport()
-						{
-							setError( COPY_ERROR_KEY, null );
-
-							setPersistentBooleanProperty( PP_COPY_OUTSTANDING, false );
-						}
-					});
-				
-				copy_thread = null;
-				
-				return( true );
-			}
-		}
-		
-		if ( try_copy ){
-			
-			try{
-				setBusy( true );
-				
-				for ( TranscodeFileImpl transcode_file: to_copy ){
-					
-					try{
-						transcode_file.setCopyingToDevice( true );
-
-						File	file = transcode_file.getTargetFile().getFile();
-						
-						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 );
-																						
-							log( "Copied file '" + file + ": to " + copy_to );
-							
-							transcode_file.setCopiedToDevice( true );
-							
-						}catch( Throwable e ){
-							
-							copy_to.delete();
-							
-							transcode_file.setCopyToDeviceFailed();
-							
-							transcode_file.setTransientProperty( COPY_ERROR_KEY, Debug.getNestedExceptionMessage( e ));
-							
-							log( "Failed to copy file " + file, e );
-						}
-					}catch( TranscodeException e ){
-		
-						// file has been deleted
-					}
-				}
-			}finally{
-					
-				setBusy( false );
-			}
-		}
-		
-		return( false );
-	}
-	
-	public boolean
-	isExportable()
-	{
-		return( true );
-	}
-	
-	protected void
-	getDisplayProperties(
-		List<String[]>	dp )
-	{
-		super.getDisplayProperties( dp );
-		
-		addDP( dp, "devices.copy.pending", copy_outstanding );
-	}
-	
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		super.generate( writer );
-		
-		try{
-			writer.indent();
-	
-			writer.println( "auto_copy=" + getAutoCopyToFolder() + ", copy_to=" + getCopyToFolder() + ", copy_os=" + copy_outstanding );
-			
-		}finally{
-			
-			writer.exdent();
-		}
-	}
-
-	// @see com.aelitis.azureus.core.devices.impl.DeviceImpl#getStatus()
-	public String getStatus() {
-		String s = super.getStatus();
-
-		if (COConfigurationManager.getIntParameter("User Mode") > 0 && getCopyToFolder() != null) {
-			s += " (" + getCopyToFolder().getPath() + ")";
-		}
-
-		return s;
-	}
-}
+/*
+ * Created on Jul 10, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+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.AsyncDispatcher;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.core3.util.IndentWriter;
+
+import com.aelitis.azureus.core.devices.DeviceManagerException;
+import com.aelitis.azureus.core.devices.TranscodeException;
+import com.aelitis.azureus.core.devices.TranscodeFile;
+import com.aelitis.azureus.core.devices.TranscodeTargetListener;
+
+
+public class 
+DeviceMediaRendererManual 
+	extends DeviceMediaRendererImpl
+{
+	private static final Object	COPY_ERROR_KEY 		= new Object();
+	private static final Object	COPY_PENDING_KEY 	= new Object();
+
+	private boolean				can_copy_to_folder	= true;
+	private boolean				copy_outstanding;
+	private boolean				copy_outstanding_set;
+	private AEThread2			copy_thread;
+	private AESemaphore			copy_sem = new AESemaphore( "Device:copy" );
+	private AsyncDispatcher		async_dispatcher = new AsyncDispatcher( 5000 );
+
+	protected
+	DeviceMediaRendererManual(
+		DeviceManagerImpl	_manager,
+		String				_uid,
+		String				_classification,
+		boolean				_manual,
+		String				_name )
+	{
+		super( _manager, _uid, _classification, _manual, _name );
+	}
+	
+	protected
+	DeviceMediaRendererManual(
+		DeviceManagerImpl	_manager,
+		Map					_map )
+	
+		throws IOException
+	{
+		super(_manager, _map );
+	}
+	
+	protected void
+	initialise()
+	{
+		super.initialise();
+		
+		if ( getPersistentBooleanProperty( PP_COPY_OUTSTANDING, false )){
+		
+			setCopyOutstanding();
+		}
+		
+		addListener( 
+			new TranscodeTargetListener()
+			{
+				public void
+				fileAdded(
+					TranscodeFile		file )
+				{
+					updateStatus( file );
+				}
+				
+				public void
+				fileChanged(
+					TranscodeFile		file,
+					int					type,
+					Object				data )
+				{
+					updateStatus( file );
+				}
+				
+				public void
+				fileRemoved(
+					TranscodeFile		file )
+				{	
+						// do this to pick up change in copy-to-device state caused by removal
+					
+					setCopyOutstanding();
+				}
+				
+				private void
+				updateStatus(
+					TranscodeFile		file )
+				{
+					if ( file.isComplete() && !file.isCopiedToDevice()){
+						
+						setCopyOutstanding();
+					}
+				}
+			});
+	}
+	
+	public boolean 
+	canAssociate() 
+	{
+		return( false );
+	}
+	
+	public boolean
+	canRestrictAccess()
+	{
+		return( false );
+	}
+	
+	public boolean
+	canFilterFilesView() 
+	{
+		return( false );
+	}
+	
+	public boolean
+	isBrowsable()
+	{
+		return( false );
+	}
+	
+	public boolean
+	canCopyToFolder()
+	{
+		return( can_copy_to_folder );
+	}
+	
+	public void
+	setCanCopyToFolder(
+		boolean		can )
+	{
+		can_copy_to_folder = can;
+		
+		if ( !can ){
+			
+			setPersistentBooleanProperty( PP_COPY_OUTSTANDING, false );
+			
+			synchronized( this ){
+				copy_outstanding 		= false;
+				copy_outstanding_set	= false;
+			}
+		}
+	}
+	
+	public File
+	getCopyToFolder()
+	{
+		String str = getPersistentStringProperty( PP_COPY_TO_FOLDER, null );
+		
+		if ( str == null ){
+			
+			return( null );
+		}
+		
+		return( new File( str ));
+	}
+	
+	public void
+	setCopyToFolder(
+		File		file )
+	{
+		setPersistentStringProperty( PP_COPY_TO_FOLDER, file==null?null:file.getAbsolutePath());
+		
+		if ( getAutoCopyToFolder()){
+			
+			setCopyOutstanding();
+		}
+	}
+	
+	public boolean
+	isLivenessDetectable()
+	{
+		return( getPersistentBooleanProperty( PP_LIVENESS_DETECTABLE, false ));
+	}
+	
+	public void
+	setLivenessDetectable(
+		boolean	b )
+	{
+		setPersistentBooleanProperty( PP_LIVENESS_DETECTABLE, true );
+	}
+	
+	public int
+	getCopyToFolderPending()
+	{
+		if ( !can_copy_to_folder ){
+			
+			return( 0 );
+		}
+		
+		synchronized( this ){
+			
+			if ( !copy_outstanding ){
+				
+				return( 0 );
+			}
+		}
+
+		TranscodeFileImpl[] files = getFiles();
+		
+		int result = 0;
+			
+		for ( TranscodeFileImpl file: files ){
+
+			if ( file.isComplete() && !file.isCopiedToDevice()){
+				
+				result++;
+			}
+		}
+		
+		return( result );
+	}
+	
+	public boolean
+	getAutoCopyToFolder()
+	{
+		return( getPersistentBooleanProperty( PP_AUTO_COPY, PP_AUTO_COPY_DEFAULT  ));
+	}
+		
+	public void
+	setAutoCopyToFolder(
+		boolean		auto )
+	{
+		setPersistentBooleanProperty( PP_AUTO_COPY, auto );
+			
+		setCopyOutstanding();
+	}
+	
+	public void 
+	manualCopy() 
+	
+		throws DeviceManagerException 
+	{
+		if ( getAutoCopyToFolder()){
+			
+			throw( new DeviceManagerException( "Operation prohibited - auto copy enabled" ));
+		}
+		
+		doCopy();
+	}
+	
+	protected void
+	setCopyOutstanding()
+	{
+		if ( !can_copy_to_folder ){
+			
+			return;
+		}
+		
+		synchronized( this ){
+			
+			copy_outstanding_set = true;
+			
+			if ( copy_thread == null ){
+				
+				copy_thread = 
+					new AEThread2( "Device:copier", true )
+					{
+						public void
+						run()
+						{
+							performCopy();
+						}
+					};
+									
+				copy_thread.start();
+			}
+			
+			copy_sem.release();
+		}
+	}
+	
+	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()
+	{
+		if ( !can_copy_to_folder ){
+			
+			return;
+		}
+		
+		synchronized( this ){
+
+			copy_outstanding = true;
+		
+			async_dispatcher.dispatch(
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						setPersistentBooleanProperty( PP_COPY_OUTSTANDING, true );
+					}
+				});
+		}
+		
+		while( true ){
+			
+			if ( copy_sem.reserve( 10*1000 )){
+				
+				while( copy_sem.reserveIfAvailable());
+			}
+						
+			boolean	auto_copy = getAutoCopyToFolder();
+			
+			boolean	nothing_to_do = false;
+			
+			synchronized( this ){
+
+				if ( !auto_copy ){
+											
+					copy_thread = null;
+						
+					nothing_to_do = true;
+					
+				}else{
+
+					copy_outstanding_set = false;
+				}
+			}
+			
+			if ( nothing_to_do ){
+				
+				setError( COPY_ERROR_KEY, null );
+				
+				int pending = getCopyToFolderPending();
+				
+				if ( pending == 0 ){
+					
+					setInfo( COPY_PENDING_KEY, null );
+					
+				}else{
+					
+					String str = MessageText.getString( "devices.info.copypending", new String[]{ String.valueOf( pending ) });
+					
+					setInfo( COPY_PENDING_KEY, str );
+				}
+				return;
+			}
+			
+
+			if ( doCopy()){
+				
+				break;
+			}
+		}
+	}
+	
+	protected boolean
+	doCopy()
+	{
+		if ( !can_copy_to_folder ){
+			
+			return( true );
+		}
+		
+		setInfo( COPY_PENDING_KEY, null );
+
+		
+		File	copy_to = getCopyToFolder();
+		
+		List<TranscodeFileImpl>	to_copy = new ArrayList<TranscodeFileImpl>();
+
+		boolean	borked = false;
+		
+		TranscodeFileImpl[] files = getFiles();
+			
+		int	pending = 0;
+		
+		for ( TranscodeFileImpl file: files ){
+				
+			if ( file.isComplete() && !file.isCopiedToDevice()){
+				
+				pending++;
+				
+				if ( file.getCopyToDeviceFails() < 3 ){
+				
+					to_copy.add( file );
+					
+				}else{
+						
+					String info = (String)file.getTransientProperty( COPY_ERROR_KEY );
+					
+					setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copyfail") + (info==null?"":(" - " + info)));
+
+					borked = true;
+				}
+			}
+		}
+		
+		boolean	try_copy = false;
+		
+		if ( to_copy.size() > 0 ){
+			
+				// handle case where device is auto-detectable and copy-to is missing
+			
+			if ( isLivenessDetectable() && !isAlive() && ( copy_to == null || !copy_to.exists())){
+			
+				String str = MessageText.getString( "devices.info.copypending2", new String[]{ String.valueOf( pending ) });
+				
+				setInfo( COPY_PENDING_KEY, str );
+				
+				borked = true;
+				
+			}else{
+				setInfo( COPY_PENDING_KEY, null );
+				
+				boolean	sub_borked = false;
+				
+				if ( copy_to == null ){
+				
+					setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copytonotset" ));
+					
+					sub_borked = true;
+					
+				}else if ( !copy_to.exists()){
+					
+					// due to the two-phase mount of android devices and the fact that the
+					// copy-to location is %root$/videos, the root might exist but the sub-folder 
+					// not. 
+					
+					File parent = copy_to.getParentFile();
+					
+					if ( parent != null && parent.canWrite()){
+						
+						copy_to.mkdir();
+					}
+					
+					if ( !copy_to.exists()){
+					
+						setError( COPY_ERROR_KEY, MessageText.getString( "device.error.mountrequired", new String[]{copy_to.getAbsolutePath()}));
+
+						sub_borked = true;
+					}
+
+					//setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copytomissing", new String[]{copy_to.getAbsolutePath()}));
+					//sub_borked = true;
+				}
+				
+				if ( !sub_borked ){
+				
+					if ( !copy_to.canWrite()){
+					
+						setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copytonowrite", new String[]{copy_to.getAbsolutePath()}));
+					
+						sub_borked = true;
+					
+					}else{
+					
+						try_copy = true;
+					
+						setError( COPY_ERROR_KEY, null );
+					}
+				}
+			
+				borked = borked | sub_borked;
+			}
+		} else {
+
+			setInfo( COPY_PENDING_KEY, null );
+		}
+		
+		synchronized( this ){
+
+				// all done, tidy up and exit
+			
+			if ( to_copy.size() == 0 && !copy_outstanding_set && !borked ){
+					
+				copy_outstanding = false;
+				
+				async_dispatcher.dispatch(
+					new AERunnable()
+					{
+						public void
+						runSupport()
+						{
+							setError( COPY_ERROR_KEY, null );
+
+							setPersistentBooleanProperty( PP_COPY_OUTSTANDING, false );
+						}
+					});
+				
+				copy_thread = null;
+				
+				return( true );
+			}
+		}
+		
+		if ( try_copy ){
+			
+			try{
+				setBusy( true );
+				
+				for ( TranscodeFileImpl transcode_file: to_copy ){
+					
+					try{
+						transcode_file.setCopyingToDevice( true );
+
+						File	file = transcode_file.getTargetFile().getFile();
+						
+						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 );
+																						
+							log( "Copied file '" + file + ": to " + copy_to );
+							
+							transcode_file.setCopiedToDevice( true );
+							
+						}catch( Throwable e ){
+							
+							copy_to.delete();
+							
+							transcode_file.setCopyToDeviceFailed();
+							
+							transcode_file.setTransientProperty( COPY_ERROR_KEY, Debug.getNestedExceptionMessage( e ));
+							
+							log( "Failed to copy file " + file, e );
+						}
+					}catch( TranscodeException e ){
+		
+						// file has been deleted
+					}
+				}
+			}finally{
+					
+				setBusy( false );
+			}
+		}
+		
+		return( false );
+	}
+	
+	public boolean
+	isExportable()
+	{
+		return( true );
+	}
+	
+	protected void
+	getDisplayProperties(
+		List<String[]>	dp )
+	{
+		super.getDisplayProperties( dp );
+		
+		addDP( dp, "devices.copy.pending", copy_outstanding );
+	}
+	
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		super.generate( writer );
+		
+		try{
+			writer.indent();
+	
+			writer.println( "auto_copy=" + getAutoCopyToFolder() + ", copy_to=" + getCopyToFolder() + ", copy_os=" + copy_outstanding );
+			
+		}finally{
+			
+			writer.exdent();
+		}
+	}
+
+	// @see com.aelitis.azureus.core.devices.impl.DeviceImpl#getStatus()
+	public String getStatus() {
+		String s = super.getStatus();
+
+		if (COConfigurationManager.getIntParameter("User Mode") > 0 && getCopyToFolder() != null) {
+			s += " (" + getCopyToFolder().getPath() + ")";
+		}
+
+		return s;
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererTemplateImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererTemplateImpl.java
index 1754ad5..4b4f429 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererTemplateImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceMediaRendererTemplateImpl.java
@@ -1,158 +1,157 @@
-/*
- * Created on Jul 10, 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.util.*;
-
-import com.aelitis.azureus.core.devices.Device;
-import com.aelitis.azureus.core.devices.DeviceManagerException;
-import com.aelitis.azureus.core.devices.DeviceMediaRenderer;
-import com.aelitis.azureus.core.devices.DeviceMediaRendererTemplate;
-import com.aelitis.azureus.core.devices.TranscodeProfile;
-
-public class 
-DeviceMediaRendererTemplateImpl
-	implements DeviceMediaRendererTemplate
-{
-	private List<TranscodeProfile>		profiles = new ArrayList<TranscodeProfile>();
-	
-	private final DeviceManagerImpl		manager;
-	private final String				classification;
-	private final String				name;
-	private final String				manufacturer;
-	private final boolean				auto;
-	
-	protected
-	DeviceMediaRendererTemplateImpl(
-		DeviceManagerImpl	_manager,
-		String				_classification,
-		boolean				_auto )
-	{
-		manager			= _manager;
-		classification 	= _classification;
-		auto			= _auto;
-		
-		int	pos = classification.indexOf( '.' );
-		
-		if ( pos == -1 ){
-			
-			manufacturer = classification;
-			
-		}else{
-			
-			manufacturer = classification.substring( 0, pos );
-		}
-		
-		pos = classification.lastIndexOf( '.' );
-		
-		if ( pos == -1 ){
-			
-			name = classification;
-			
-		}else{
-			
-			name = classification.substring( pos+1 );
-		}
-	}
-	
-	protected void
-	addProfile(
-		TranscodeProfile	profile )
-	{
-		profiles.add( profile );
-	}
-	
-	public TranscodeProfile[]
-	getProfiles()
-	{
-		return( profiles.toArray(new TranscodeProfile[profiles.size()]));
-	}
-	
-	public int
-	getType()
-	{
-		return( Device.DT_MEDIA_RENDERER );
-	}
-	
-	public String
-	getName()
-	{
-		return( name );
-	}
-	
-	public String
-	getManufacturer()
-	{
-		return( manufacturer );
-	}
-	
-	public String
-	getClassification()
-	{
-		return( classification );
-	}
-	
-	public String
-	getShortDescription()
-	{
-		return( null );
-	}
-	
-	public int
-	getRendererSpecies()
-	{
-		return( DeviceMediaRenderer.RS_OTHER );
-	}
-	
-	public boolean
-	isAuto()
-	{
-		return( auto );
-	}
-	
-	public Device
-	createInstance(
-		String		name )
-	
-		throws DeviceManagerException
-	{
-		return( createInstance( name, null, true ));
-	}
-	
-	public Device
-	createInstance(
-		String		name,
-		String		uid,
-		boolean		manual )
-	
-		throws DeviceManagerException
-	{
-		if ( auto ){
-			
-			throw( new DeviceManagerException( "Device can't be added manually" ));
-		}
-		
-		Device res = manager.createDevice( Device.DT_MEDIA_RENDERER, uid, classification, name, manual );
-		
-		return( res );
-	}
-}
\ No newline at end of file
+/*
+ * Created on Jul 10, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.util.*;
+
+import com.aelitis.azureus.core.devices.Device;
+import com.aelitis.azureus.core.devices.DeviceManagerException;
+import com.aelitis.azureus.core.devices.DeviceMediaRenderer;
+import com.aelitis.azureus.core.devices.DeviceMediaRendererTemplate;
+import com.aelitis.azureus.core.devices.TranscodeProfile;
+
+public class 
+DeviceMediaRendererTemplateImpl
+	implements DeviceMediaRendererTemplate
+{
+	private List<TranscodeProfile>		profiles = new ArrayList<TranscodeProfile>();
+	
+	private final DeviceManagerImpl		manager;
+	private final String				classification;
+	private final String				name;
+	private final String				manufacturer;
+	private final boolean				auto;
+	
+	protected
+	DeviceMediaRendererTemplateImpl(
+		DeviceManagerImpl	_manager,
+		String				_classification,
+		boolean				_auto )
+	{
+		manager			= _manager;
+		classification 	= _classification;
+		auto			= _auto;
+		
+		int	pos = classification.indexOf( '.' );
+		
+		if ( pos == -1 ){
+			
+			manufacturer = classification;
+			
+		}else{
+			
+			manufacturer = classification.substring( 0, pos );
+		}
+		
+		pos = classification.lastIndexOf( '.' );
+		
+		if ( pos == -1 ){
+			
+			name = classification;
+			
+		}else{
+			
+			name = classification.substring( pos+1 );
+		}
+	}
+	
+	protected void
+	addProfile(
+		TranscodeProfile	profile )
+	{
+		profiles.add( profile );
+	}
+	
+	public TranscodeProfile[]
+	getProfiles()
+	{
+		return( profiles.toArray(new TranscodeProfile[profiles.size()]));
+	}
+	
+	public int
+	getType()
+	{
+		return( Device.DT_MEDIA_RENDERER );
+	}
+	
+	public String
+	getName()
+	{
+		return( name );
+	}
+	
+	public String
+	getManufacturer()
+	{
+		return( manufacturer );
+	}
+	
+	public String
+	getClassification()
+	{
+		return( classification );
+	}
+	
+	public String
+	getShortDescription()
+	{
+		return( null );
+	}
+	
+	public int
+	getRendererSpecies()
+	{
+		return( DeviceMediaRenderer.RS_OTHER );
+	}
+	
+	public boolean
+	isAuto()
+	{
+		return( auto );
+	}
+	
+	public Device
+	createInstance(
+		String		name )
+	
+		throws DeviceManagerException
+	{
+		return( createInstance( name, null, true ));
+	}
+	
+	public Device
+	createInstance(
+		String		name,
+		String		uid,
+		boolean		manual )
+	
+		throws DeviceManagerException
+	{
+		if ( auto ){
+			
+			throw( new DeviceManagerException( "Device can't be added manually" ));
+		}
+		
+		Device res = manager.createDevice( Device.DT_MEDIA_RENDERER, uid, classification, name, manual );
+		
+		return( res );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceOfflineDownloaderImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceOfflineDownloaderImpl.java
index 324da54..56bf97f 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceOfflineDownloaderImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceOfflineDownloaderImpl.java
@@ -1,1736 +1,1735 @@
-/*
- * 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.*;
-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.UPnPException;
-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;
-		boolean	force_status	= false;
-		
-		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;
-					
-				}catch( Throwable e ){
-					
-					error_status = MessageText.getString( "device.od.error.opfailexcep", new String[]{ "GetFreeSpace", Debug.getNestedExceptionMessage( e )});
-
-					log( "Failed to get free space", e );
-
-				}
-			}
-			
-			if ( space_on_device == 0 ){
-				
-				error_status 	= MessageText.getString( "device.od.error.nospace" );
-				force_status	= true;
-			}
-
-			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 = Constants.PAT_SPLIT_COMMA.split(set_dl_result);
-				
-				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 = 
-										addTorrent( 										
-											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, force_status );
-		}
-	}
-
-	private String
-	addTorrent(
-		String		hash_str,
-		String		torrent_data )
-	
-		throws UPnPException
-	{
-		int	chunk_size = 40*1024;
-		
-		int	length = torrent_data.length();
-		
-		if ( length < chunk_size ){
-		
-			return( service.addDownload( client_id,	hash_str, torrent_data ));
-			
-		}else{
-			
-			String status = "";
-			
-			int	rem = length;
-			
-			for( int i=0; i<length; i+=chunk_size ){
-			
-				int	size = Math.min( rem, chunk_size );
-				
-				status = service.addDownloadChunked(
-					client_id,	
-					hash_str,
-					torrent_data.substring( i, i+size ),
-					i,
-					length );
-					
-				rem -= size;
-			}
-			
-			return( status );
-		}
-	}
-	
-	protected void
-	updateError(
-		String	str,
-		boolean	force )
-	{
-		if ( str == null ){
-			
-			setError( ERROR_KEY_OD, null );
-			
-			consec_errors = 0;
-			
-			consec_success++;
-			
-		}else{
-			
-				// if device isn't connectable then replace the error with something more
-				// user-friendly
-			
-			try{
-			
-				if ( !service.getGenericService().isConnectable()){
-					
-					str = MessageText.getString( "device.od.error.notfound" );
-				}
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-			
-			consec_errors++;
-			
-			consec_success = 0;
-			
-			if ( consec_errors > 2 || force ){
-				
-				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.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();
-		}
-	}
-
-	@Override
-	public boolean 
-	isAlive() 
-	{
-		if ( super.isAlive()){
-			
-				// more restrictive test here to sync alive state with 'appears to be offline'
-				// error messages
-			
-			return( service.getGenericService().isConnectable());
-		}
-		
-		return( false );
-	}
-	
-	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(
-		boolean		force )
-	
-		throws DeviceManagerException
-	{
-		if ( space_on_device >= 0 && !force ){
-			
-			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 );
-		}
-	}
-}
+/*
+ * Created on Jan 28, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.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.*;
+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.UPnPException;
+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;
+		boolean	force_status	= false;
+		
+		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;
+					
+				}catch( Throwable e ){
+					
+					error_status = MessageText.getString( "device.od.error.opfailexcep", new String[]{ "GetFreeSpace", Debug.getNestedExceptionMessage( e )});
+
+					log( "Failed to get free space", e );
+
+				}
+			}
+			
+			if ( space_on_device == 0 ){
+				
+				error_status 	= MessageText.getString( "device.od.error.nospace" );
+				force_status	= true;
+			}
+
+			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 = Constants.PAT_SPLIT_COMMA.split(set_dl_result);
+				
+				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 = 
+										addTorrent( 										
+											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, force_status );
+		}
+	}
+
+	private String
+	addTorrent(
+		String		hash_str,
+		String		torrent_data )
+	
+		throws UPnPException
+	{
+		int	chunk_size = 40*1024;
+		
+		int	length = torrent_data.length();
+		
+		if ( length < chunk_size ){
+		
+			return( service.addDownload( client_id,	hash_str, torrent_data ));
+			
+		}else{
+			
+			String status = "";
+			
+			int	rem = length;
+			
+			for( int i=0; i<length; i+=chunk_size ){
+			
+				int	size = Math.min( rem, chunk_size );
+				
+				status = service.addDownloadChunked(
+					client_id,	
+					hash_str,
+					torrent_data.substring( i, i+size ),
+					i,
+					length );
+					
+				rem -= size;
+			}
+			
+			return( status );
+		}
+	}
+	
+	protected void
+	updateError(
+		String	str,
+		boolean	force )
+	{
+		if ( str == null ){
+			
+			setError( ERROR_KEY_OD, null );
+			
+			consec_errors = 0;
+			
+			consec_success++;
+			
+		}else{
+			
+				// if device isn't connectable then replace the error with something more
+				// user-friendly
+			
+			try{
+			
+				if ( !service.getGenericService().isConnectable()){
+					
+					str = MessageText.getString( "device.od.error.notfound" );
+				}
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+			
+			consec_errors++;
+			
+			consec_success = 0;
+			
+			if ( consec_errors > 2 || force ){
+				
+				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.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();
+		}
+	}
+
+	@Override
+	public boolean 
+	isAlive() 
+	{
+		if ( super.isAlive()){
+			
+				// more restrictive test here to sync alive state with 'appears to be offline'
+				// error messages
+			
+			return( service.getGenericService().isConnectable());
+		}
+		
+		return( false );
+	}
+	
+	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(
+		boolean		force )
+	
+		throws DeviceManagerException
+	{
+		if ( space_on_device >= 0 && !force ){
+			
+			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/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceTivo.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceTivo.java
index 42d14a1..91f1995 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceTivo.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceTivo.java
@@ -1,1077 +1,1076 @@
-/*
- * Created on Jul 24, 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.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.net.URLEncoder;
-import java.util.*;
-
-
-import org.gudy.azureus2.core3.util.Constants;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.IndentWriter;
-import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
-import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
-import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;
-import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl;
-
-import com.aelitis.azureus.core.devices.TranscodeFile;
-
-public class 
-DeviceTivo
-	extends DeviceMediaRendererImpl
-{
-	private static final boolean	TRACE	= false;
-	
-	private static final String		NL				= "\r\n";
-	
-	private static Map<String,Comparator<ItemInfo>>	sort_comparators = new HashMap<String, Comparator<ItemInfo>>();
-	
-	static {
-		sort_comparators.put(
-			"Type",
-			new Comparator<ItemInfo>()
-			{
-				public int 
-				compare(
-					ItemInfo o1, ItemInfo o2 )
-				{
-					if ( o1.isContainer() == o2.isContainer()){
-						
-						return( 0 );
-					}
-					
-					if ( o1.isContainer()){
-						
-						return( -1 );
-					}
-					
-					return( 1 );
-				}
-			});
-		
-		sort_comparators.put(
-			"Title",
-			new Comparator<ItemInfo>()
-			{
-				Comparator<String> c = new FormattersImpl().getAlphanumericComparator( true );
-				
-				public int 
-				compare(
-					ItemInfo o1, ItemInfo o2 )
-				{
-					return( c.compare( o1.getName(), o2.getName()));
-				}
-			});
-		
-		sort_comparators.put(
-			"CreationDate",
-			new Comparator<ItemInfo>()
-			{
-				public int 
-				compare(
-					ItemInfo o1, ItemInfo o2 )
-				{
-					long	res = o1.getCreationMillis() - o2.getCreationMillis();
-					
-					if ( res < 0 ){
-						return( -1 );
-					}else if ( res > 0 ){
-						return( 1 );
-					}else{
-						return( 0 );
-					}
-				}
-			});
-		
-		sort_comparators.put( "LastChangeDate", sort_comparators.get( "CreationDate" ));
-		sort_comparators.put( "CaptureDate", sort_comparators.get( "CreationDate" ));
-	}
-	
-	private String		server_name;
-	private boolean		tried_tcp_beacon;
-	
-	protected
-	DeviceTivo(
-		DeviceManagerImpl	_manager,
-		String				_uid,
-		String				_classification )
-	{
-		super( _manager, _uid, _classification, false );
-		
-		setName( "TiVo", true );
-	}
-
-	protected
-	DeviceTivo(
-		DeviceManagerImpl	_manager,
-		Map					_map )
-	
-		throws IOException
-	{
-		super( _manager, _map );
-	}
-	
-	protected boolean
-	updateFrom(
-		DeviceImpl		_other,
-		boolean			_is_alive )
-	{
-		if ( !super.updateFrom( _other, _is_alive )){
-			
-			return( false );
-		}
-		
-		if ( !( _other instanceof DeviceTivo )){
-			
-			Debug.out( "Inconsistent" );
-			
-			return( false );
-		}
-		
-		DeviceTivo other = (DeviceTivo)_other;
-		
-		return( true );
-	}
-	
-	protected void
-	initialise()
-	{
-		super.initialise();
-	}
-	
-	public boolean
-	canFilterFilesView()
-	{
-		return( false );
-	}
-	
-	public boolean 
-	canAssociate()
-	{
-		return( true );
-	}
-	
-	public boolean
-	canRestrictAccess()
-	{
-			// guess we could implement this one day
-		
-		return( false );
-	}
-	
-	public boolean
-	canShowCategories()
-	{
-		return( true );
-	}
-	
-	protected boolean
-	getShowCategoriesDefault()
-	{
-		return( true );
-	}
-	
-	protected String
-	getMachineName()
-	{
-		return( getPersistentStringProperty( PP_TIVO_MACHINE, null ));
-	}
-	
-	protected void
-	found(
-		DeviceTivoManager	_tivo_manager,
-		InetAddress			_address,
-		String				_server_name,
-		String				_machine )
-	{
-		boolean	first_time = false;
-		
-		synchronized( this ){
-		
-			if ( server_name == null ){
-			
-				server_name	= _server_name;
-				
-				first_time = true;
-			}
-		}
-		
-		if ( _machine == null && !tried_tcp_beacon ){
-			
-			try{
-				Socket socket = new Socket();
-			
-				try{
-					socket.connect( new InetSocketAddress( _address, 2190 ), 5000 );
-					
-					socket.setSoTimeout( 5000 );
-	
-					DataOutputStream dos = new DataOutputStream( socket.getOutputStream());
-					
-					byte[]	beacon_out = _tivo_manager.encodeBeacon( false, 0 );
-					
-					dos.writeInt( beacon_out.length );		
-				
-					dos.write( beacon_out );				
-						
-					DataInputStream dis = new DataInputStream( socket.getInputStream());
-					
-					int len = dis.readInt();
-				
-					if ( len < 65536 ){
-						
-						byte[] bytes = new byte[len];
-	
-						int	pos = 0;
-						
-						while( pos < len ){
-						
-							int read = dis.read( bytes, pos, len-pos );
-							
-							pos += read;
-						}
-						
-						Map<String,String> beacon_in = _tivo_manager.decodeBeacon( bytes, len );
-						
-						_machine = beacon_in.get( "machine" );
-					}	
-				}finally{
-					
-					socket.close();
-				}
-			}catch( Throwable e ){
-				
-			}finally{
-				
-				tried_tcp_beacon = true;
-			}
-		}
-		
-		if ( _machine != null ){
-			
-			String existing = getMachineName();
-			
-			if ( existing == null || !existing.equals( _machine )){
-				
-				setPersistentStringProperty( PP_TIVO_MACHINE, _machine );
-			}
-		}
-		
-		setAddress( _address );
-							
-		alive();
-		
-		if ( first_time ){
-			
-			browseReceived();
-		}
-	}
-	
-
-	protected boolean 
-	generate(
-		TrackerWebPageRequest 	request,
-		TrackerWebPageResponse 	response ) 
-	
-		throws IOException 
-	{
-		InetSocketAddress	local_address = request.getLocalAddress();
-		
-		if ( local_address == null ){
-			
-			return( false );
-		}
-		
-		String	host = local_address.getAddress().getHostAddress();
-		
-		String	url = request.getURL();
-		
-		if ( TRACE ){
-			System.out.println( "url: " + url );
-		}
-		
-		if ( !url.startsWith( "/TiVoConnect?" )){
-			
-			return( false );
-		}
-		
-		int pos = url.indexOf( '?' );
-		
-		if ( pos == -1 ){
-			
-			return(false );
-		}
-		
-		String[]	bits = url.substring( pos+1 ).split( "&" );
-		
-		Map<String,String>	args = new HashMap<String, String>();
-		
-		for ( String bit: bits ){
-			
-			String[] x = bit.split( "=" );
-			
-			args.put( x[0], URLDecoder.decode( x[1], "UTF-8" ));
-		}
-		
-		if ( TRACE ){
-			System.out.println( "args: " + args );
-		}
-		
-			// root folder /TiVoConnect?Command=QueryContainer&Container=%2F
-		
-		String	command = args.get( "Command" );
-		
-		if ( command == null ){
-			
-			return( false );
-		}
-		
-		String reply = null;
-
-		if ( command.equals( "QueryContainer" )){
-			
-			String	container = args.get( "Container" );
-			
-			if ( container == null ){
-				
-				return( false );
-			}
-						
-			if ( container.equals( "/" )){
-			
-				reply =
-				"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + NL +
-				"<TiVoContainer>" + NL +
-				"    <Details>" + NL +
-				"        <Title>" + server_name + "</Title>" + NL +
-				"        <ContentType>x-container/tivo-server</ContentType>" + NL +
-				"        <SourceFormat>x-container/folder</SourceFormat>" + NL +
-				"        <TotalItems>1</TotalItems>" + NL +
-				"    </Details>" + NL +
-				"    <Item>" + NL +
-				"        <Details>" + NL +
-				"            <Title>" + server_name + "</Title>" + NL +
-				"            <ContentType>x-container/tivo-videos</ContentType>" + NL +
-				"            <SourceFormat>x-container/folder</SourceFormat>" + NL +
-				"        </Details>" + NL +
-				"        <Links>" + NL +
-				"            <Content>" + NL +
-				"                <Url>/TiVoConnect?Command=QueryContainer&Container=" + urlencode( "/Content" ) + "</Url>" + NL +
-				"                <ContentType>x-container/tivo-videos</ContentType>" + NL +
-				"            </Content>" + NL +
-				"        </Links>" + NL +
-				"    </Item>" + NL +
-				"    <ItemStart>0</ItemStart>" + NL +
-				"    <ItemCount>1</ItemCount>" + NL +
-				"</TiVoContainer>";
-				
-			}else if ( container.startsWith( "/Content" )){
-				
-				boolean	show_categories = getShowCategories();
-				
-				String	recurse = args.get( "Recurse" );
-				
-				if ( recurse != null && recurse.equals( "Yes" )){
-					
-					show_categories = false;
-				}
-				
-				TranscodeFileImpl[] tfs = getFiles();
-				
-				String	category_or_tag = null;
-				
-				Map<String,ContainerInfo>	categories_or_tags = null;
-
-				if ( show_categories ){
-					
-					if ( container.startsWith( "/Content/" )){
-						
-						category_or_tag = container.substring( container.lastIndexOf( '/' ) + 1 );
-						
-					}else{
-						
-						categories_or_tags = new HashMap<String,ContainerInfo>();
-					}
-				}
-				
-					// build list of applicable items
-				
-				List<ItemInfo> items = new ArrayList<ItemInfo>( tfs.length );
-									
-				for ( TranscodeFileImpl file: tfs ){
-						
-					if ( !file.isComplete()){
-						
-							// see if we can set up a stream xcode for this but only if we
-							// know the duration and the transcode is in progress (done in setup)
-						
-						if ( !setupStreamXCode( file )){
-							
-							continue;
-						}
-					}
-												
-					if ( category_or_tag != null ){
-					
-						boolean	hit = false;
-
-						String[]	cats 	= file.getCategories();
-						String[]	tags	= file.getTags( true );
-						
-						for ( String[] strs: new String[][]{ cats,tags }){
-						
-							for ( String c: strs ){
-								
-								if ( c.equals( category_or_tag )){
-									
-									hit = true;
-								}
-							}
-						}
-					
-						if ( !hit ){
-							
-							continue;
-						}
-					}
-					
-					FileInfo	info = new FileInfo( file, host );
-					
-					if ( info.isOK()){
-						
-						boolean	skip = false;
-						
-						if ( categories_or_tags != null ){
-							
-							String[]	cats 	= file.getCategories();
-							String[]	tags	= file.getTags( true );
-
-							if ( cats.length > 0 || tags.length > 0 ){
-								
-								skip = true;
-
-								for ( String[] strs: new String[][]{ cats,tags }){
-									
-									for ( String s: strs ){
-										
-										ContainerInfo cont = categories_or_tags.get( s );
-										
-										if ( cont == null ){
-											
-											items.add( cont = new ContainerInfo( s ));
-											
-											categories_or_tags.put( s, cont );
-										}
-																
-										cont.addChild();
-									}
-								}
-							}
-						}
-						
-						if ( !skip ){
-						
-							items.add( info );
-						}
-					}
-				}
-								
-					// sort
-				
-				String	sort_order = args.get( "SortOrder" );
-				
-				if ( sort_order != null ){
-					
-					String[] keys = Constants.PAT_SPLIT_COMMA.split(sort_order);
-					
-					final List<Comparator<ItemInfo>> 	comparators = new  ArrayList<Comparator<ItemInfo>>();
-					final List<Boolean>					reverses	= new ArrayList<Boolean>();
-					
-					for ( String key: keys ){
-						
-						boolean	reverse = false;
-						
-						if ( key.startsWith( "!" )){
-							
-							reverse = true;
-							
-							key = key.substring(1);
-						}
-						
-						Comparator<ItemInfo> comp = sort_comparators.get( key );
-						
-						if ( comp != null ){
-							
-							comparators.add( comp );
-							reverses.add( reverse );
-						}
-					}
-					
-					if ( comparators.size() > 0 ){
-						
-						Collections.sort(
-							items,
-							new Comparator<ItemInfo>()
-							{
-								public int 
-								compare(
-									ItemInfo i1, 
-									ItemInfo i2) 
-								{
-									for ( int i=0;i<comparators.size();i++){
-										
-										Comparator<ItemInfo> comp = comparators.get(i);
-										
-										int res = comp.compare( i1, i2 );
-										
-										if ( res != 0 ){
-											
-											if ( reverses.get(i)){
-												
-												if ( res < 0 ){
-													
-													res = 1;
-													
-												}else{
-													
-													res = -1;
-												}
-											}
-											
-											return( res );
-										}
-									}
-									
-									return( 0 );
-								}
-							});
-					}
-				}
-				
-					// select items to return
-				
-				String	item_count		= args.get( "ItemCount" );
-				String	anchor_offset 	= args.get( "AnchorOffset" );
-				String	anchor 			= args.get( "AnchorItem" );
-				
-				int	num_items;
-				
-				if ( item_count == null ){
-				
-					num_items = items.size();
-					
-				}else{
-					
-						// can be negative if X items from end
-					
-					num_items = Integer.parseInt( item_count );
-				}
-				
-				int	anchor_index;	// either one before or one after item to be returned depending on count +ve/-ve
-				
-				if ( num_items < 0 ){
-					
-					anchor_index = items.size();
-					
-				}else{
-					
-					anchor_index = -1;
-				}
-				
-				if ( anchor != null ){
-						
-					for (int i=0;i<items.size();i++){
-						
-						ItemInfo info = items.get(i);
-						
-						if ( anchor.equals( info.getLinkURL())){
-							
-							anchor_index = i;
-						}
-					}
-				}
-				
-				if ( anchor_offset != null ){
-					
-					anchor_index += Integer.parseInt( anchor_offset );
-					
-					if ( anchor_index < -1 ){
-						
-						anchor_index = -1;
-						
-					}else if ( anchor_index > items.size()){
-						
-						anchor_index = items.size();
-					}
-				}
-				
-				int	start_index;
-				int end_index;
-				
-				if ( num_items > 0 ){
-					
-					start_index = anchor_index + 1;
-					
-					end_index	= anchor_index + num_items;
-					
-				}else{
-					
-					start_index = anchor_index + num_items;
-					
-					end_index	= anchor_index - 1;
-				}
-
-				if ( start_index < 0 ){
-					
-					start_index = 0;
-				}
-				
-				if ( end_index >= items.size()){
-					
-					end_index = items.size() - 1;
-				}
-				
-				int	num_to_return = end_index - start_index + 1;
-				
-				if ( num_to_return < 0 ){
-					
-					num_to_return = 0;
-				}
-								
-				String machine = getMachineName();
-				
-				if ( machine == null ){
-				
-						// default until we find out what it is - can't see any way to get it apart from wait for broadcast
-					
-					machine = "TivoHDDVR";
-				}
-				
-				String	header = 
-				"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + NL +
-				"<TiVoContainer>" + NL +
-				"    <Tivos>" + NL +
-				"      <Tivo>" + machine + "</Tivo>" + NL +
-				"    </Tivos>" + NL +
-				"    <ItemStart>" + start_index + "</ItemStart>" + NL +
-				"    <ItemCount>" + num_to_return + "</ItemCount>" + NL +
-				"    <Details>" + NL +
-				"        <Title>" + escape( container ) + "</Title>" + NL +
-				"        <ContentType>x-container/tivo-videos</ContentType>" + NL +
-				"        <SourceFormat>x-container/folder</SourceFormat>" + NL +
-				"        <TotalItems>" + items.size() + "</TotalItems>" + NL +
-				"    </Details>" + NL;
-				
-				reply = header;
-				
-				for ( int i=start_index;i<=end_index;i++ ){
-					
-					ItemInfo	item = items.get(i);
-					
-					if ( item instanceof FileInfo ){
-						
-						FileInfo file = (FileInfo)item;
-						
-						long	file_size = file.getTargetSize();
-						
-						String	title 	= escape( file.getName());
-						String	desc	= title;
-							
-						int MAX_TITLE_LENGTH = 30;
-						
-						if ( title.length() > MAX_TITLE_LENGTH ){
-							
-								// TiVo has problems displaying a truncated title if it has
-								// no spaces in it
-							
-							String 	temp = "";
-							
-							for ( int j=0;j<title.length();j++){
-								
-								char c = title.charAt( j );
-								
-								if ( Character.isLetterOrDigit( c )){
-									
-									temp += c;
-								}else{
-									
-									temp += ' ';
-								}
-							}
-							
-							int space_pos = temp.indexOf( ' ' );
-							
-							if ( space_pos == -1 || space_pos > MAX_TITLE_LENGTH ){
-								
-								temp = temp.substring( 0, 30 ) + "...";
-							}
-							
-							title = temp;
-						}
-						
-						reply +=
-						
-						"    <Item>" + NL +
-						"        <Details>" + NL +
-						"            <Title>" + title + "</Title>" + NL +
-						"            <ContentType>video/x-tivo-mpeg</ContentType>" + NL +
-						"            <SourceFormat>video/x-ms-wmv</SourceFormat>" + NL;
-						
-						if ( file_size > 0 ){
-							reply +=
-								"            <SourceSize>" + file_size + "</SourceSize>" + NL;
-						}else{
-							long est_size = file.getEstimatedTargetSize();
-							
-							if ( est_size > 0 ){
-								reply +=
-									"            <SourceSize>" + est_size + "</SourceSize>" + NL;
-							}
-						}
-						
-						reply +=
-						"            <Duration>" + file.getDurationMillis() + "</Duration>" + NL +
-						"            <Description>" + desc + "</Description>" + NL +
-						"            <SourceChannel>0</SourceChannel>" + NL +
-						"            <SourceStation></SourceStation>" + NL +
-						"            <SeriesId></SeriesId>" + NL +
-						"            <CaptureDate>" + file.getCaptureDate() + "</CaptureDate>" + NL + 
-						"        </Details>" + NL +
-						"        <Links>" + NL +
-						"            <Content>" + NL +
-						"                <ContentType>video/x-tivo-mpeg</ContentType>" + NL +
-						"                    <AcceptsParams>No</AcceptsParams>" + NL +
-						"                    <Url>" + file.getLinkURL() + "</Url>" + NL +
-						"                </Content>" + NL +
-						"                <CustomIcon>" + NL +
-						"                    <ContentType>video/*</ContentType>" + NL +
-						"                    <AcceptsParams>No</AcceptsParams>" + NL +
-						"                    <Url>urn:tivo:image:save-until-i-delete-recording</Url>" + NL +
-						"                </CustomIcon>" + NL +
-						"        </Links>" + NL +
-						"    </Item>" + NL;
-						
-					}else{
-						
-						ContainerInfo cont = (ContainerInfo)item;
-						
-						reply +=
-						"    <Item>" + NL +
-						"        <Details>" + NL +
-						"            <Title>" + cont.getName() + "</Title>" + NL +
-						"            <ContentType>x-container/tivo-videos</ContentType>" + NL +
-						"            <SourceFormat>x-container/folder</SourceFormat>" + NL +
-						"            <TotalItems>" + cont.getChildCount() + "</TotalItems>" + NL +
-						"        </Details>" + NL +
-						"        <Links>" + NL +
-						"            <Content>" + NL +
-						"                <Url>" + cont.getLinkURL() + "</Url>" + NL +
-						"                <ContentType>x-container/tivo-videos</ContentType>" + NL +
-						"            </Content>" + NL +
-						"        </Links>" + NL +
-						"    </Item>" + NL;
-					}
-				}
-				
-				String footer =
-				"</TiVoContainer>";
-				
-				reply += footer;
-			}
-			
-	
-		}else if ( command.equals( "QueryFormats")){
-		
-			String source_format = args.get( "SourceFormat" );
-			
-			if ( source_format != null && source_format.startsWith( "video" )){
-				
-					// /TiVoConnect?Command=QueryFormats&SourceFormat=video%2Fx-tivo-mpeg
-				
-				reply = 
-				"<?xml version=\"1.0\" encoding=\"utf-8\"?>" + NL +
-				"<TiVoFormats><Format>" + NL +
-				"<ContentType>video/x-tivo-mpeg</ContentType><Description/>" + NL +
-				"</Format></TiVoFormats>";
-			}
-		}
-		
-		if ( reply == null ){
-			
-			return( false );
-		}
-		
-		if ( TRACE ){
-			System.out.println( "->" + reply );
-		}
-		
-		response.setContentType( "text/xml" );
-		
-		response.getOutputStream().write( reply.getBytes( "UTF-8" ));
-		
-		return( true );
-	}
-	
-	protected static String
-	urlencode(
-		String	str )
-	{
-		try{
-			return( URLEncoder.encode( str, "UTF-8" ));
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			return( str );
-		}
-	}
-	
-	protected static String
-	escape(
-		String	str )
-	{
-		return( XUXmlWriter.escapeXML( str ));
-	}
-	
-	protected void
-	getDisplayProperties(
-		List<String[]>	dp )
-	{
-		super.getDisplayProperties( dp );
-		
-		addDP( dp, "devices.tivo.machine", getMachineName());
-	}
-	
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		super.generate( writer );
-		
-		try{
-			writer.indent();
-	
-			writer.println( "tico_machine=" + getMachineName());
-			
-		}finally{
-			
-			writer.exdent();
-		}
-	}
-	
-	protected abstract static class
-	ItemInfo
-	{
-		protected abstract String
-		getName();
-		
-		protected abstract String
-		getLinkURL();
-		
-		protected abstract boolean
-		isContainer();
-		
-		public abstract long
-		getCreationMillis();
-
-	}
-	
-	protected static class
-	ContainerInfo
-		extends ItemInfo
-	{
-		private String		name;
-		
-		private int		child_count;
-		
-		protected
-		ContainerInfo(
-			String	_name )
-		{
-			name	= _name;
-		}
-		
-		protected String
-		getName()
-		{
-			return( name );
-		}
-		
-		protected String
-		getLinkURL()
-		{
-			return( "/TiVoConnect?Command=QueryContainer&Container=" + urlencode( "/Content/" + name ));
-		}
-		
-		protected void
-		addChild()
-		{
-			child_count++;
-		}
-		
-		protected int
-		getChildCount()
-		{
-			return( child_count );
-		}
-		
-		public long
-		getCreationMillis()
-		{
-			return( 0 );
-		}
-		
-		protected boolean
-		isContainer()
-		{
-			return( true );
-		}
-	}
-	
-	protected static class
-	FileInfo
-		extends ItemInfo
-	{
-		private TranscodeFile	file;
-		private String			stream_url;
-		private long			target_size;
-		private long			creation_millis;
-		
-		boolean	ok;
-		
-		protected
-		FileInfo(
-			TranscodeFile		_file,
-			String				_host )
-		{
-			file	= _file;
-			
-			try{
-				URL url = file.getStreamURL( _host );
-				
-				if ( url == null ){
-					
-					return;
-				}
-				
-				stream_url = url.toExternalForm();
-								
-				try{
-					if ( file.isComplete()){
-						
-						target_size = file.getTargetFile().getLength();
-					}				
-				}catch( Throwable e ){	
-				}
-				
-				creation_millis =  file.getCreationDateMillis();
-				
-				ok = true;
-				
-			}catch( Throwable e ){
-				
-			}
-		}
-		
-		protected boolean
-		isOK()
-		{
-			return( ok );
-		}
-		
-		protected String
-		getName()
-		{
-			return( file.getName());
-		}
-		
-		protected String
-		getLinkURL()
-		{
-			return( stream_url );
-		}
-		
-		protected long
-		getTargetSize()
-		{
-			return( target_size );
-		}
-		
-		protected long
-		getEstimatedTargetSize()
-		{
-				// TODO: we need access to max bitrate info... and then use duration and increase by, say, 5%
-			
-			try{
-				long	duration_secs = getDurationMillis()/1000;
-				
-				if ( duration_secs == 0 ){
-						
-					long length = file.getSourceFile().getLength();
-				
-					return( length * 10 );
-					
-				}else{
-					long mb_per_sec = 3;	// upper limit of 3 MB a sec assumed
-						
-					return( duration_secs * mb_per_sec*1024*1024L );
-				}
-			}catch( Throwable e ){
-			}
-				
-			return( 0 );
-		}
-		
-		protected long
-		getDurationMillis()
-		{
-			return( file.getDurationMillis());
-		}
-		
-		public long
-		getCreationMillis()
-		{
-			return( creation_millis );
-		}
-		
-		protected String
-		getCaptureDate()
-		{
-			return( "0x" + Long.toString( creation_millis/1000, 16 ));
-		}
-		
-		protected boolean
-		isContainer()
-		{
-			return( false );
-		}
-	}
-}
+/*
+ * Created on Jul 24, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.*;
+
+
+import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.IndentWriter;
+import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageRequest;
+import org.gudy.azureus2.plugins.tracker.web.TrackerWebPageResponse;
+import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl;
+
+import com.aelitis.azureus.core.devices.TranscodeFile;
+
+public class 
+DeviceTivo
+	extends DeviceMediaRendererImpl
+{
+	private static final boolean	TRACE	= false;
+	
+	private static final String		NL				= "\r\n";
+	
+	private static Map<String,Comparator<ItemInfo>>	sort_comparators = new HashMap<String, Comparator<ItemInfo>>();
+	
+	static {
+		sort_comparators.put(
+			"Type",
+			new Comparator<ItemInfo>()
+			{
+				public int 
+				compare(
+					ItemInfo o1, ItemInfo o2 )
+				{
+					if ( o1.isContainer() == o2.isContainer()){
+						
+						return( 0 );
+					}
+					
+					if ( o1.isContainer()){
+						
+						return( -1 );
+					}
+					
+					return( 1 );
+				}
+			});
+		
+		sort_comparators.put(
+			"Title",
+			new Comparator<ItemInfo>()
+			{
+				Comparator<String> c = new FormattersImpl().getAlphanumericComparator( true );
+				
+				public int 
+				compare(
+					ItemInfo o1, ItemInfo o2 )
+				{
+					return( c.compare( o1.getName(), o2.getName()));
+				}
+			});
+		
+		sort_comparators.put(
+			"CreationDate",
+			new Comparator<ItemInfo>()
+			{
+				public int 
+				compare(
+					ItemInfo o1, ItemInfo o2 )
+				{
+					long	res = o1.getCreationMillis() - o2.getCreationMillis();
+					
+					if ( res < 0 ){
+						return( -1 );
+					}else if ( res > 0 ){
+						return( 1 );
+					}else{
+						return( 0 );
+					}
+				}
+			});
+		
+		sort_comparators.put( "LastChangeDate", sort_comparators.get( "CreationDate" ));
+		sort_comparators.put( "CaptureDate", sort_comparators.get( "CreationDate" ));
+	}
+	
+	private String		server_name;
+	private boolean		tried_tcp_beacon;
+	
+	protected
+	DeviceTivo(
+		DeviceManagerImpl	_manager,
+		String				_uid,
+		String				_classification )
+	{
+		super( _manager, _uid, _classification, false );
+		
+		setName( "TiVo", true );
+	}
+
+	protected
+	DeviceTivo(
+		DeviceManagerImpl	_manager,
+		Map					_map )
+	
+		throws IOException
+	{
+		super( _manager, _map );
+	}
+	
+	protected boolean
+	updateFrom(
+		DeviceImpl		_other,
+		boolean			_is_alive )
+	{
+		if ( !super.updateFrom( _other, _is_alive )){
+			
+			return( false );
+		}
+		
+		if ( !( _other instanceof DeviceTivo )){
+			
+			Debug.out( "Inconsistent" );
+			
+			return( false );
+		}
+		
+		DeviceTivo other = (DeviceTivo)_other;
+		
+		return( true );
+	}
+	
+	protected void
+	initialise()
+	{
+		super.initialise();
+	}
+	
+	public boolean
+	canFilterFilesView()
+	{
+		return( false );
+	}
+	
+	public boolean 
+	canAssociate()
+	{
+		return( true );
+	}
+	
+	public boolean
+	canRestrictAccess()
+	{
+			// guess we could implement this one day
+		
+		return( false );
+	}
+	
+	public boolean
+	canShowCategories()
+	{
+		return( true );
+	}
+	
+	protected boolean
+	getShowCategoriesDefault()
+	{
+		return( true );
+	}
+	
+	protected String
+	getMachineName()
+	{
+		return( getPersistentStringProperty( PP_TIVO_MACHINE, null ));
+	}
+	
+	protected void
+	found(
+		DeviceTivoManager	_tivo_manager,
+		InetAddress			_address,
+		String				_server_name,
+		String				_machine )
+	{
+		boolean	first_time = false;
+		
+		synchronized( this ){
+		
+			if ( server_name == null ){
+			
+				server_name	= _server_name;
+				
+				first_time = true;
+			}
+		}
+		
+		if ( _machine == null && !tried_tcp_beacon ){
+			
+			try{
+				Socket socket = new Socket();
+			
+				try{
+					socket.connect( new InetSocketAddress( _address, 2190 ), 5000 );
+					
+					socket.setSoTimeout( 5000 );
+	
+					DataOutputStream dos = new DataOutputStream( socket.getOutputStream());
+					
+					byte[]	beacon_out = _tivo_manager.encodeBeacon( false, 0 );
+					
+					dos.writeInt( beacon_out.length );		
+				
+					dos.write( beacon_out );				
+						
+					DataInputStream dis = new DataInputStream( socket.getInputStream());
+					
+					int len = dis.readInt();
+				
+					if ( len < 65536 ){
+						
+						byte[] bytes = new byte[len];
+	
+						int	pos = 0;
+						
+						while( pos < len ){
+						
+							int read = dis.read( bytes, pos, len-pos );
+							
+							pos += read;
+						}
+						
+						Map<String,String> beacon_in = _tivo_manager.decodeBeacon( bytes, len );
+						
+						_machine = beacon_in.get( "machine" );
+					}	
+				}finally{
+					
+					socket.close();
+				}
+			}catch( Throwable e ){
+				
+			}finally{
+				
+				tried_tcp_beacon = true;
+			}
+		}
+		
+		if ( _machine != null ){
+			
+			String existing = getMachineName();
+			
+			if ( existing == null || !existing.equals( _machine )){
+				
+				setPersistentStringProperty( PP_TIVO_MACHINE, _machine );
+			}
+		}
+		
+		setAddress( _address );
+							
+		alive();
+		
+		if ( first_time ){
+			
+			browseReceived();
+		}
+	}
+	
+
+	protected boolean 
+	generate(
+		TrackerWebPageRequest 	request,
+		TrackerWebPageResponse 	response ) 
+	
+		throws IOException 
+	{
+		InetSocketAddress	local_address = request.getLocalAddress();
+		
+		if ( local_address == null ){
+			
+			return( false );
+		}
+		
+		String	host = local_address.getAddress().getHostAddress();
+		
+		String	url = request.getURL();
+		
+		if ( TRACE ){
+			System.out.println( "url: " + url );
+		}
+		
+		if ( !url.startsWith( "/TiVoConnect?" )){
+			
+			return( false );
+		}
+		
+		int pos = url.indexOf( '?' );
+		
+		if ( pos == -1 ){
+			
+			return(false );
+		}
+		
+		String[]	bits = url.substring( pos+1 ).split( "&" );
+		
+		Map<String,String>	args = new HashMap<String, String>();
+		
+		for ( String bit: bits ){
+			
+			String[] x = bit.split( "=" );
+			
+			args.put( x[0], URLDecoder.decode( x[1], "UTF-8" ));
+		}
+		
+		if ( TRACE ){
+			System.out.println( "args: " + args );
+		}
+		
+			// root folder /TiVoConnect?Command=QueryContainer&Container=%2F
+		
+		String	command = args.get( "Command" );
+		
+		if ( command == null ){
+			
+			return( false );
+		}
+		
+		String reply = null;
+
+		if ( command.equals( "QueryContainer" )){
+			
+			String	container = args.get( "Container" );
+			
+			if ( container == null ){
+				
+				return( false );
+			}
+						
+			if ( container.equals( "/" )){
+			
+				reply =
+				"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + NL +
+				"<TiVoContainer>" + NL +
+				"    <Details>" + NL +
+				"        <Title>" + server_name + "</Title>" + NL +
+				"        <ContentType>x-container/tivo-server</ContentType>" + NL +
+				"        <SourceFormat>x-container/folder</SourceFormat>" + NL +
+				"        <TotalItems>1</TotalItems>" + NL +
+				"    </Details>" + NL +
+				"    <Item>" + NL +
+				"        <Details>" + NL +
+				"            <Title>" + server_name + "</Title>" + NL +
+				"            <ContentType>x-container/tivo-videos</ContentType>" + NL +
+				"            <SourceFormat>x-container/folder</SourceFormat>" + NL +
+				"        </Details>" + NL +
+				"        <Links>" + NL +
+				"            <Content>" + NL +
+				"                <Url>/TiVoConnect?Command=QueryContainer&Container=" + urlencode( "/Content" ) + "</Url>" + NL +
+				"                <ContentType>x-container/tivo-videos</ContentType>" + NL +
+				"            </Content>" + NL +
+				"        </Links>" + NL +
+				"    </Item>" + NL +
+				"    <ItemStart>0</ItemStart>" + NL +
+				"    <ItemCount>1</ItemCount>" + NL +
+				"</TiVoContainer>";
+				
+			}else if ( container.startsWith( "/Content" )){
+				
+				boolean	show_categories = getShowCategories();
+				
+				String	recurse = args.get( "Recurse" );
+				
+				if ( recurse != null && recurse.equals( "Yes" )){
+					
+					show_categories = false;
+				}
+				
+				TranscodeFileImpl[] tfs = getFiles();
+				
+				String	category_or_tag = null;
+				
+				Map<String,ContainerInfo>	categories_or_tags = null;
+
+				if ( show_categories ){
+					
+					if ( container.startsWith( "/Content/" )){
+						
+						category_or_tag = container.substring( container.lastIndexOf( '/' ) + 1 );
+						
+					}else{
+						
+						categories_or_tags = new HashMap<String,ContainerInfo>();
+					}
+				}
+				
+					// build list of applicable items
+				
+				List<ItemInfo> items = new ArrayList<ItemInfo>( tfs.length );
+									
+				for ( TranscodeFileImpl file: tfs ){
+						
+					if ( !file.isComplete()){
+						
+							// see if we can set up a stream xcode for this but only if we
+							// know the duration and the transcode is in progress (done in setup)
+						
+						if ( !setupStreamXCode( file )){
+							
+							continue;
+						}
+					}
+												
+					if ( category_or_tag != null ){
+					
+						boolean	hit = false;
+
+						String[]	cats 	= file.getCategories();
+						String[]	tags	= file.getTags( true );
+						
+						for ( String[] strs: new String[][]{ cats,tags }){
+						
+							for ( String c: strs ){
+								
+								if ( c.equals( category_or_tag )){
+									
+									hit = true;
+								}
+							}
+						}
+					
+						if ( !hit ){
+							
+							continue;
+						}
+					}
+					
+					FileInfo	info = new FileInfo( file, host );
+					
+					if ( info.isOK()){
+						
+						boolean	skip = false;
+						
+						if ( categories_or_tags != null ){
+							
+							String[]	cats 	= file.getCategories();
+							String[]	tags	= file.getTags( true );
+
+							if ( cats.length > 0 || tags.length > 0 ){
+								
+								skip = true;
+
+								for ( String[] strs: new String[][]{ cats,tags }){
+									
+									for ( String s: strs ){
+										
+										ContainerInfo cont = categories_or_tags.get( s );
+										
+										if ( cont == null ){
+											
+											items.add( cont = new ContainerInfo( s ));
+											
+											categories_or_tags.put( s, cont );
+										}
+																
+										cont.addChild();
+									}
+								}
+							}
+						}
+						
+						if ( !skip ){
+						
+							items.add( info );
+						}
+					}
+				}
+								
+					// sort
+				
+				String	sort_order = args.get( "SortOrder" );
+				
+				if ( sort_order != null ){
+					
+					String[] keys = Constants.PAT_SPLIT_COMMA.split(sort_order);
+					
+					final List<Comparator<ItemInfo>> 	comparators = new  ArrayList<Comparator<ItemInfo>>();
+					final List<Boolean>					reverses	= new ArrayList<Boolean>();
+					
+					for ( String key: keys ){
+						
+						boolean	reverse = false;
+						
+						if ( key.startsWith( "!" )){
+							
+							reverse = true;
+							
+							key = key.substring(1);
+						}
+						
+						Comparator<ItemInfo> comp = sort_comparators.get( key );
+						
+						if ( comp != null ){
+							
+							comparators.add( comp );
+							reverses.add( reverse );
+						}
+					}
+					
+					if ( comparators.size() > 0 ){
+						
+						Collections.sort(
+							items,
+							new Comparator<ItemInfo>()
+							{
+								public int 
+								compare(
+									ItemInfo i1, 
+									ItemInfo i2) 
+								{
+									for ( int i=0;i<comparators.size();i++){
+										
+										Comparator<ItemInfo> comp = comparators.get(i);
+										
+										int res = comp.compare( i1, i2 );
+										
+										if ( res != 0 ){
+											
+											if ( reverses.get(i)){
+												
+												if ( res < 0 ){
+													
+													res = 1;
+													
+												}else{
+													
+													res = -1;
+												}
+											}
+											
+											return( res );
+										}
+									}
+									
+									return( 0 );
+								}
+							});
+					}
+				}
+				
+					// select items to return
+				
+				String	item_count		= args.get( "ItemCount" );
+				String	anchor_offset 	= args.get( "AnchorOffset" );
+				String	anchor 			= args.get( "AnchorItem" );
+				
+				int	num_items;
+				
+				if ( item_count == null ){
+				
+					num_items = items.size();
+					
+				}else{
+					
+						// can be negative if X items from end
+					
+					num_items = Integer.parseInt( item_count );
+				}
+				
+				int	anchor_index;	// either one before or one after item to be returned depending on count +ve/-ve
+				
+				if ( num_items < 0 ){
+					
+					anchor_index = items.size();
+					
+				}else{
+					
+					anchor_index = -1;
+				}
+				
+				if ( anchor != null ){
+						
+					for (int i=0;i<items.size();i++){
+						
+						ItemInfo info = items.get(i);
+						
+						if ( anchor.equals( info.getLinkURL())){
+							
+							anchor_index = i;
+						}
+					}
+				}
+				
+				if ( anchor_offset != null ){
+					
+					anchor_index += Integer.parseInt( anchor_offset );
+					
+					if ( anchor_index < -1 ){
+						
+						anchor_index = -1;
+						
+					}else if ( anchor_index > items.size()){
+						
+						anchor_index = items.size();
+					}
+				}
+				
+				int	start_index;
+				int end_index;
+				
+				if ( num_items > 0 ){
+					
+					start_index = anchor_index + 1;
+					
+					end_index	= anchor_index + num_items;
+					
+				}else{
+					
+					start_index = anchor_index + num_items;
+					
+					end_index	= anchor_index - 1;
+				}
+
+				if ( start_index < 0 ){
+					
+					start_index = 0;
+				}
+				
+				if ( end_index >= items.size()){
+					
+					end_index = items.size() - 1;
+				}
+				
+				int	num_to_return = end_index - start_index + 1;
+				
+				if ( num_to_return < 0 ){
+					
+					num_to_return = 0;
+				}
+								
+				String machine = getMachineName();
+				
+				if ( machine == null ){
+				
+						// default until we find out what it is - can't see any way to get it apart from wait for broadcast
+					
+					machine = "TivoHDDVR";
+				}
+				
+				String	header = 
+				"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + NL +
+				"<TiVoContainer>" + NL +
+				"    <Tivos>" + NL +
+				"      <Tivo>" + machine + "</Tivo>" + NL +
+				"    </Tivos>" + NL +
+				"    <ItemStart>" + start_index + "</ItemStart>" + NL +
+				"    <ItemCount>" + num_to_return + "</ItemCount>" + NL +
+				"    <Details>" + NL +
+				"        <Title>" + escape( container ) + "</Title>" + NL +
+				"        <ContentType>x-container/tivo-videos</ContentType>" + NL +
+				"        <SourceFormat>x-container/folder</SourceFormat>" + NL +
+				"        <TotalItems>" + items.size() + "</TotalItems>" + NL +
+				"    </Details>" + NL;
+				
+				reply = header;
+				
+				for ( int i=start_index;i<=end_index;i++ ){
+					
+					ItemInfo	item = items.get(i);
+					
+					if ( item instanceof FileInfo ){
+						
+						FileInfo file = (FileInfo)item;
+						
+						long	file_size = file.getTargetSize();
+						
+						String	title 	= escape( file.getName());
+						String	desc	= title;
+							
+						int MAX_TITLE_LENGTH = 30;
+						
+						if ( title.length() > MAX_TITLE_LENGTH ){
+							
+								// TiVo has problems displaying a truncated title if it has
+								// no spaces in it
+							
+							String 	temp = "";
+							
+							for ( int j=0;j<title.length();j++){
+								
+								char c = title.charAt( j );
+								
+								if ( Character.isLetterOrDigit( c )){
+									
+									temp += c;
+								}else{
+									
+									temp += ' ';
+								}
+							}
+							
+							int space_pos = temp.indexOf( ' ' );
+							
+							if ( space_pos == -1 || space_pos > MAX_TITLE_LENGTH ){
+								
+								temp = temp.substring( 0, 30 ) + "...";
+							}
+							
+							title = temp;
+						}
+						
+						reply +=
+						
+						"    <Item>" + NL +
+						"        <Details>" + NL +
+						"            <Title>" + title + "</Title>" + NL +
+						"            <ContentType>video/x-tivo-mpeg</ContentType>" + NL +
+						"            <SourceFormat>video/x-ms-wmv</SourceFormat>" + NL;
+						
+						if ( file_size > 0 ){
+							reply +=
+								"            <SourceSize>" + file_size + "</SourceSize>" + NL;
+						}else{
+							long est_size = file.getEstimatedTargetSize();
+							
+							if ( est_size > 0 ){
+								reply +=
+									"            <SourceSize>" + est_size + "</SourceSize>" + NL;
+							}
+						}
+						
+						reply +=
+						"            <Duration>" + file.getDurationMillis() + "</Duration>" + NL +
+						"            <Description>" + desc + "</Description>" + NL +
+						"            <SourceChannel>0</SourceChannel>" + NL +
+						"            <SourceStation></SourceStation>" + NL +
+						"            <SeriesId></SeriesId>" + NL +
+						"            <CaptureDate>" + file.getCaptureDate() + "</CaptureDate>" + NL + 
+						"        </Details>" + NL +
+						"        <Links>" + NL +
+						"            <Content>" + NL +
+						"                <ContentType>video/x-tivo-mpeg</ContentType>" + NL +
+						"                    <AcceptsParams>No</AcceptsParams>" + NL +
+						"                    <Url>" + file.getLinkURL() + "</Url>" + NL +
+						"                </Content>" + NL +
+						"                <CustomIcon>" + NL +
+						"                    <ContentType>video/*</ContentType>" + NL +
+						"                    <AcceptsParams>No</AcceptsParams>" + NL +
+						"                    <Url>urn:tivo:image:save-until-i-delete-recording</Url>" + NL +
+						"                </CustomIcon>" + NL +
+						"        </Links>" + NL +
+						"    </Item>" + NL;
+						
+					}else{
+						
+						ContainerInfo cont = (ContainerInfo)item;
+						
+						reply +=
+						"    <Item>" + NL +
+						"        <Details>" + NL +
+						"            <Title>" + cont.getName() + "</Title>" + NL +
+						"            <ContentType>x-container/tivo-videos</ContentType>" + NL +
+						"            <SourceFormat>x-container/folder</SourceFormat>" + NL +
+						"            <TotalItems>" + cont.getChildCount() + "</TotalItems>" + NL +
+						"        </Details>" + NL +
+						"        <Links>" + NL +
+						"            <Content>" + NL +
+						"                <Url>" + cont.getLinkURL() + "</Url>" + NL +
+						"                <ContentType>x-container/tivo-videos</ContentType>" + NL +
+						"            </Content>" + NL +
+						"        </Links>" + NL +
+						"    </Item>" + NL;
+					}
+				}
+				
+				String footer =
+				"</TiVoContainer>";
+				
+				reply += footer;
+			}
+			
+	
+		}else if ( command.equals( "QueryFormats")){
+		
+			String source_format = args.get( "SourceFormat" );
+			
+			if ( source_format != null && source_format.startsWith( "video" )){
+				
+					// /TiVoConnect?Command=QueryFormats&SourceFormat=video%2Fx-tivo-mpeg
+				
+				reply = 
+				"<?xml version=\"1.0\" encoding=\"utf-8\"?>" + NL +
+				"<TiVoFormats><Format>" + NL +
+				"<ContentType>video/x-tivo-mpeg</ContentType><Description/>" + NL +
+				"</Format></TiVoFormats>";
+			}
+		}
+		
+		if ( reply == null ){
+			
+			return( false );
+		}
+		
+		if ( TRACE ){
+			System.out.println( "->" + reply );
+		}
+		
+		response.setContentType( "text/xml" );
+		
+		response.getOutputStream().write( reply.getBytes( "UTF-8" ));
+		
+		return( true );
+	}
+	
+	protected static String
+	urlencode(
+		String	str )
+	{
+		try{
+			return( URLEncoder.encode( str, "UTF-8" ));
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( str );
+		}
+	}
+	
+	protected static String
+	escape(
+		String	str )
+	{
+		return( XUXmlWriter.escapeXML( str ));
+	}
+	
+	protected void
+	getDisplayProperties(
+		List<String[]>	dp )
+	{
+		super.getDisplayProperties( dp );
+		
+		addDP( dp, "devices.tivo.machine", getMachineName());
+	}
+	
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		super.generate( writer );
+		
+		try{
+			writer.indent();
+	
+			writer.println( "tico_machine=" + getMachineName());
+			
+		}finally{
+			
+			writer.exdent();
+		}
+	}
+	
+	protected abstract static class
+	ItemInfo
+	{
+		protected abstract String
+		getName();
+		
+		protected abstract String
+		getLinkURL();
+		
+		protected abstract boolean
+		isContainer();
+		
+		public abstract long
+		getCreationMillis();
+
+	}
+	
+	protected static class
+	ContainerInfo
+		extends ItemInfo
+	{
+		private String		name;
+		
+		private int		child_count;
+		
+		protected
+		ContainerInfo(
+			String	_name )
+		{
+			name	= _name;
+		}
+		
+		protected String
+		getName()
+		{
+			return( name );
+		}
+		
+		protected String
+		getLinkURL()
+		{
+			return( "/TiVoConnect?Command=QueryContainer&Container=" + urlencode( "/Content/" + name ));
+		}
+		
+		protected void
+		addChild()
+		{
+			child_count++;
+		}
+		
+		protected int
+		getChildCount()
+		{
+			return( child_count );
+		}
+		
+		public long
+		getCreationMillis()
+		{
+			return( 0 );
+		}
+		
+		protected boolean
+		isContainer()
+		{
+			return( true );
+		}
+	}
+	
+	protected static class
+	FileInfo
+		extends ItemInfo
+	{
+		private TranscodeFile	file;
+		private String			stream_url;
+		private long			target_size;
+		private long			creation_millis;
+		
+		boolean	ok;
+		
+		protected
+		FileInfo(
+			TranscodeFile		_file,
+			String				_host )
+		{
+			file	= _file;
+			
+			try{
+				URL url = file.getStreamURL( _host );
+				
+				if ( url == null ){
+					
+					return;
+				}
+				
+				stream_url = url.toExternalForm();
+								
+				try{
+					if ( file.isComplete()){
+						
+						target_size = file.getTargetFile().getLength();
+					}				
+				}catch( Throwable e ){	
+				}
+				
+				creation_millis =  file.getCreationDateMillis();
+				
+				ok = true;
+				
+			}catch( Throwable e ){
+				
+			}
+		}
+		
+		protected boolean
+		isOK()
+		{
+			return( ok );
+		}
+		
+		protected String
+		getName()
+		{
+			return( file.getName());
+		}
+		
+		protected String
+		getLinkURL()
+		{
+			return( stream_url );
+		}
+		
+		protected long
+		getTargetSize()
+		{
+			return( target_size );
+		}
+		
+		protected long
+		getEstimatedTargetSize()
+		{
+				// TODO: we need access to max bitrate info... and then use duration and increase by, say, 5%
+			
+			try{
+				long	duration_secs = getDurationMillis()/1000;
+				
+				if ( duration_secs == 0 ){
+						
+					long length = file.getSourceFile().getLength();
+				
+					return( length * 10 );
+					
+				}else{
+					long mb_per_sec = 3;	// upper limit of 3 MB a sec assumed
+						
+					return( duration_secs * mb_per_sec*1024*1024L );
+				}
+			}catch( Throwable e ){
+			}
+				
+			return( 0 );
+		}
+		
+		protected long
+		getDurationMillis()
+		{
+			return( file.getDurationMillis());
+		}
+		
+		public long
+		getCreationMillis()
+		{
+			return( creation_millis );
+		}
+		
+		protected String
+		getCaptureDate()
+		{
+			return( "0x" + Long.toString( creation_millis/1000, 16 ));
+		}
+		
+		protected boolean
+		isContainer()
+		{
+			return( false );
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceTivoManager.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceTivoManager.java
index 935687e..093626a 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceTivoManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceTivoManager.java
@@ -1,632 +1,631 @@
-/*
- * Created on Jul 24, 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.util.*;
-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;
-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.platform.PlatformManagerFactory;
-import org.gudy.azureus2.plugins.PluginInterface;
-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 org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-
-import com.aelitis.azureus.core.devices.Device;
-import com.aelitis.azureus.core.devices.DeviceManagerException;
-import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
-
-
-public class 
-DeviceTivoManager 
-{
-	private static final String		LF				= "\n";
-	private static final int		CONTROL_PORT	= 2190;
-	
-	private DeviceManagerImpl		device_manager;
-	private PluginInterface 		plugin_interface;
-	
-	private boolean	is_enabled;
-	private String	uid;
-	
-	private Searcher	current_search;
-	
-	private volatile boolean	manager_destroyed;
-	
-	protected
-	DeviceTivoManager(
-		DeviceManagerImpl		_dm )
-	{
-		device_manager = _dm;
-	}
-	
-	protected void
-	startUp()
-	{
-		plugin_interface = PluginInitializer.getDefaultInterface();
-
-		if ( COConfigurationManager.getStringParameter("ui").equals("az2")){
-			
-			is_enabled = false;
-			
-		}else{
-		
-			is_enabled = COConfigurationManager.getBooleanParameter( "devices.tivo.enabled", true );
-		}
-		
-		uid = COConfigurationManager.getStringParameter( "devices.tivo.uid", null );
-		
-		if ( uid == null ){
-			
-			byte[] bytes = new byte[8];
-			
-			RandomUtils.nextBytes( bytes );
-			
-			uid = Base32.encode( bytes );
-			
-			COConfigurationManager.setParameter( "devices.tivo.uid", uid );
-		}
-		
-		boolean	found_tivo = false;
-		
-		for ( Device device: device_manager.getDevices()){
-			
-			if ( device instanceof DeviceTivo ){
-				
-				found_tivo = true;
-				
-				break;
-			}
-		}
-			
-		if ( found_tivo || device_manager.getAutoSearch()){
-			
-			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, false );
-	}
-	
-	protected void
-	search(
-		boolean		persistent,
-		boolean		async )
-	{
-		try{
-			synchronized( this ){
-				
-				if ( current_search == null ){
-					
-					current_search = new Searcher( persistent, async );
-					
-				}else{
-					
-					if ( !current_search.wakeup()){
-						
-						current_search = new Searcher( persistent, async );
-					}
-				}
-			}
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-	}
-	
-	protected byte[]
-	encodeBeacon(
-		boolean		is_broadcast,
-		int			my_port )
-	
-		throws IOException
-	{
-		String beacon = 
-			"tivoconnect=1" + LF +
-			"swversion=1" + LF +	
-			"method=" + (is_broadcast?"broadcast":"connected") + LF +
-			"identity=" + uid + LF +
-			"machine=" + device_manager.getLocalServiceName() + LF +
-			"platform=pc" + LF +
-			"services=TiVoMediaServer:" + my_port + "/http";
-
-		return( beacon.getBytes( "ISO-8859-1" ));
-	}
-	
-	protected Map<String,String>
-	decodeBeacon(
-		byte[]		buffer,
-		int			length )
-		
-		throws IOException
-	{
-		String str = new String( buffer, 0, length, "ISO-8859-1" );
-		
-		String[]	lines = str.split( LF );
-		
-		Map<String,String>	map = new HashMap<String, String>();
-		
-		for (String line:lines ){
-			
-			int pos = line.indexOf( '=' );
-			
-			if ( pos > 0 ){
-				
-				map.put( line.substring( 0, pos ).trim().toLowerCase(), line.substring( pos+ 1 ).trim());
-			}
-		}
-		
-		return( map );
-	}
-	
-	protected boolean
-	receiveBeacon(
-		InetAddress	sender,
-		byte[]		buffer,
-		int			length )
-	{
-		if ( is_enabled ){
-			
-			try{
-				Map<String,String>	map = decodeBeacon( buffer, length );
-				
-				String id = map.get( "identity" );
-				
-				if ( id == null || id.equals( uid )){
-					
-					return( false );
-				}
-				
-				String platform = map.get( "platform" );
-				
-				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 ){
-				
-				log( "Failed to decode beacon", e );
-			}
-		}
-		
-		return( false );
-	}
-	
-	protected DeviceTivo
-	foundTiVo(
-		InetAddress		address,
-		String			uid,
-		String			classification,
-		String			machine )
-	{
-		uid	= "tivo:" + uid;
-		
-		DeviceImpl[] devices = device_manager.getDevices();
-		
-		String server_name = device_manager.getLocalServiceName();
-		
-		for ( DeviceImpl device: devices ){
-			
-			if ( device instanceof DeviceTivo ){
-				
-				DeviceTivo tivo = (DeviceTivo)device;
-				
-				if ( device.getID().equals( uid )){
-				
-					if ( classification != null ){
-						
-						String existing_classification = device.getClassification();
-						
-						if ( !classification.equals( existing_classification )){
-							
-							device.setPersistentStringProperty( DeviceImpl.PP_REND_CLASSIFICATION,classification );
-						}
-					}
-					
-					tivo.found( this, address, server_name, machine );
-					
-					return( tivo );
-				}
-			}
-		}
-		
-			// unfortunately we can't deduce the series from the browse request so start off with a series 3
-			// this will be corrected later if we receive a beacon which *does* contain the series details
-		
-		if ( classification == null ){
-			
-			classification = "tivo.series3";
-		}
-		
-		DeviceTivo new_device = new DeviceTivo( device_manager, uid, classification );
-		
-		DeviceTivo result = (DeviceTivo)device_manager.addDevice( new_device );
-		
-			// possible race here so handle case where device already present
-		
-		if ( result == new_device ){
-		
-			new_device.found( this, address, server_name, machine );
-		}
-		
-		return( result );
-	}
-	
-	protected void
-	log(
-		String		str )
-	{
-		if ( device_manager == null ){
-			
-			System.out.println( str );
-			
-		}else{
-			
-			device_manager.log( "TiVo: " + str );
-		}
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable 	e )
-	{
-		if ( device_manager == null ){
-			
-			System.out.println( str );
-			
-			e.printStackTrace();
-			
-		}else{
-		
-			device_manager.log( "TiVo: " + str, e );
-		}
-	}
-	
-	protected class
-	Searcher
-	{
-		private static final int	LIFE_MILLIS = 10*1000;
-		
-		private long start = SystemTime.getMonotonousTime();
-		
-		private int		tcp_port;
-		
-		private DatagramSocket 		control_socket;
-		private TrackerWebContext 	twc;
-		private TimerEventPeriodic	timer_event;
-		
-		private volatile boolean		persistent;
-		
-		private volatile boolean		search_destroyed;
-		
-		protected
-		Searcher(
-			boolean		_persistent,
-			boolean		_async )
-		
-			throws DeviceManagerException
-		{
-			try{
-				int	last_port = COConfigurationManager.getIntParameter( "devices.tivo.net.tcp.port", 0 );
-				
-				if ( last_port > 0 ){
-					
-					try{
-						ServerSocket ss = new ServerSocket( last_port );
-					
-						ss.setReuseAddress( true );
-						
-						ss.close();
-						
-					}catch( Throwable e ){
-						
-						last_port = 0;
-					}
-				}
-				
-				twc = plugin_interface.getTracker().createWebContext( last_port, Tracker.PR_HTTP );
-				
-				tcp_port = twc.getURLs()[0].getPort();
-
-				COConfigurationManager.setParameter( "devices.tivo.net.tcp.port", tcp_port );
-				
-				twc.addPageGenerator(
-					new TrackerWebPageGenerator()
-					{
-						public boolean 
-						generate(
-							TrackerWebPageRequest 	request,
-							TrackerWebPageResponse 	response )
-						
-							throws IOException 
-						{
-							String	id = (String)request.getHeaders().get( "tsn" );
-							
-							if ( id == null ){
-								
-								id = (String)request.getHeaders().get( "tivo_tcd_id" );	
-							}
-							
-							if ( id != null && is_enabled ){
-								
-								persistent = true;
-								
-								DeviceTivo tivo = foundTiVo( request.getClientAddress2().getAddress(), id, null, null );
-								
-								return( tivo.generate( request, response ));
-							}
-							
-							return( false );
-						}
-					});
-								
-				control_socket  = new DatagramSocket( null );
-					
-				control_socket.setReuseAddress( true );
-					
-				try{
-					control_socket.setSoTimeout( 60*1000 );
-					
-				}catch( Throwable e ){
-				}
-				
-				InetAddress bind = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress();
-				
-				control_socket.bind( new InetSocketAddress( bind, CONTROL_PORT ));
-		
-				timer_event = 
-					SimpleTimer.addPeriodicEvent(
-						"Tivo:Beacon",
-						60*1000,
-						new TimerEventPerformer()
-						{
-							public void 
-							perform(
-								TimerEvent 	event )
-							{
-								if ( !( manager_destroyed || search_destroyed )){
-								
-									sendBeacon();
-								}
-								
-									// see if time to auto-shutdown searching
-								
-								if ( !persistent ){
-								
-									synchronized( DeviceTivoManager.this ){
-									
-										if ( SystemTime.getMonotonousTime() - start >= LIFE_MILLIS ){
-											
-											log( "Terminating search, no devices found" );
-											
-											current_search = null;
-											
-											destroy();
-										}
-									}
-								}
-							}
-						});	
-				
-				final AESemaphore start_sem = new AESemaphore( "TiVo:CtrlListener" );
-				
-				new AEThread2( "TiVo:CtrlListener", true )
-				{
-					public void
-					run()
-					{
-						start_sem.release();
-						
-						long	successful_accepts 	= 0;
-						long	failed_accepts		= 0;
-		
-						while( !( manager_destroyed || search_destroyed )){
-							
-							try{
-								byte[] buf = new byte[8192];
-								
-								DatagramPacket packet = new DatagramPacket(buf, buf.length );
-												
-								control_socket.receive( packet );
-									
-								successful_accepts++;
-								
-								failed_accepts	 = 0;
-								
-								if ( receiveBeacon( packet.getAddress(), packet.getData(), packet.getLength())){
-									
-									persistent = true;
-								}
-								
-							}catch( SocketTimeoutException e ){
-															
-							}catch( Throwable e ){
-								
-								if ( control_socket != null && !search_destroyed && !manager_destroyed ){
-								
-									failed_accepts++;
-								
-									log( "UDP receive on port " + CONTROL_PORT + " failed", e );
-								}
-								
-								if (( failed_accepts > 100 && successful_accepts == 0 ) || failed_accepts > 1000 ){
-									
-									log( "    too many failures, abandoning" );
-		
-									break;
-								}
-							}
-						}				
-					}
-				}.start();
-					
-				if ( _async ){
-					
-					new DelayedEvent( 
-						"search:delay", 
-						5000,
-						new AERunnable()
-						{
-							public void
-							runSupport()
-							{
-								sendBeacon();
-							}
-						});	
-				}else{
-					
-					start_sem.reserve( 5000 );
-				
-					sendBeacon();
-				}
-
-				log( "Initiated device search" );
-				
-			}catch( Throwable e ){
-			
-				log( "Failed to initialise search", e );
-
-				destroy();
-				
-				throw( new DeviceManagerException( "Creation failed",e ));
-			}
-		}
-		
-		protected void
-		sendBeacon()
-		{
-			if ( is_enabled ){
-				
-				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 );
-				}
-			}
-		}
-		
-		protected boolean
-		wakeup()
-		{
-			synchronized( DeviceTivoManager.this ){
-				
-				if ( search_destroyed ){
-					
-					return( false );
-				}
-				
-				start = SystemTime.getMonotonousTime();
-			}
-			
-			sendBeacon();
-			
-			return( true );
-		}
-		
-		protected void
-		destroy()
-		{
-			search_destroyed = true;
-			
-			if ( twc != null ){
-				
-				twc.destroy();
-				
-				twc = null;
-			}
-			
-			if ( timer_event != null ){
-				
-				timer_event.cancel();
-				
-				timer_event = null;
-			}
-			
-			if ( control_socket != null ){
-				
-				try{
-					control_socket.close();
-					
-				}catch( Throwable e ){
-				}
-				
-				control_socket = null;
-			}
-		}
-	}
-}
+/*
+ * Created on Jul 24, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.util.*;
+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;
+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.platform.PlatformManagerFactory;
+import org.gudy.azureus2.plugins.PluginInterface;
+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 org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+
+import com.aelitis.azureus.core.devices.Device;
+import com.aelitis.azureus.core.devices.DeviceManagerException;
+import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
+
+
+public class 
+DeviceTivoManager 
+{
+	private static final String		LF				= "\n";
+	private static final int		CONTROL_PORT	= 2190;
+	
+	private DeviceManagerImpl		device_manager;
+	private PluginInterface 		plugin_interface;
+	
+	private boolean	is_enabled;
+	private String	uid;
+	
+	private Searcher	current_search;
+	
+	private volatile boolean	manager_destroyed;
+	
+	protected
+	DeviceTivoManager(
+		DeviceManagerImpl		_dm )
+	{
+		device_manager = _dm;
+	}
+	
+	protected void
+	startUp()
+	{
+		plugin_interface = PluginInitializer.getDefaultInterface();
+
+		if ( COConfigurationManager.getStringParameter("ui").equals("az2")){
+			
+			is_enabled = false;
+			
+		}else{
+		
+			is_enabled = COConfigurationManager.getBooleanParameter( "devices.tivo.enabled", true );
+		}
+		
+		uid = COConfigurationManager.getStringParameter( "devices.tivo.uid", null );
+		
+		if ( uid == null ){
+			
+			byte[] bytes = new byte[8];
+			
+			RandomUtils.nextBytes( bytes );
+			
+			uid = Base32.encode( bytes );
+			
+			COConfigurationManager.setParameter( "devices.tivo.uid", uid );
+		}
+		
+		boolean	found_tivo = false;
+		
+		for ( Device device: device_manager.getDevices()){
+			
+			if ( device instanceof DeviceTivo ){
+				
+				found_tivo = true;
+				
+				break;
+			}
+		}
+			
+		if ( found_tivo || device_manager.getAutoSearch()){
+			
+			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, false );
+	}
+	
+	protected void
+	search(
+		boolean		persistent,
+		boolean		async )
+	{
+		try{
+			synchronized( this ){
+				
+				if ( current_search == null ){
+					
+					current_search = new Searcher( persistent, async );
+					
+				}else{
+					
+					if ( !current_search.wakeup()){
+						
+						current_search = new Searcher( persistent, async );
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+	}
+	
+	protected byte[]
+	encodeBeacon(
+		boolean		is_broadcast,
+		int			my_port )
+	
+		throws IOException
+	{
+		String beacon = 
+			"tivoconnect=1" + LF +
+			"swversion=1" + LF +	
+			"method=" + (is_broadcast?"broadcast":"connected") + LF +
+			"identity=" + uid + LF +
+			"machine=" + device_manager.getLocalServiceName() + LF +
+			"platform=pc" + LF +
+			"services=TiVoMediaServer:" + my_port + "/http";
+
+		return( beacon.getBytes( "ISO-8859-1" ));
+	}
+	
+	protected Map<String,String>
+	decodeBeacon(
+		byte[]		buffer,
+		int			length )
+		
+		throws IOException
+	{
+		String str = new String( buffer, 0, length, "ISO-8859-1" );
+		
+		String[]	lines = str.split( LF );
+		
+		Map<String,String>	map = new HashMap<String, String>();
+		
+		for (String line:lines ){
+			
+			int pos = line.indexOf( '=' );
+			
+			if ( pos > 0 ){
+				
+				map.put( line.substring( 0, pos ).trim().toLowerCase(), line.substring( pos+ 1 ).trim());
+			}
+		}
+		
+		return( map );
+	}
+	
+	protected boolean
+	receiveBeacon(
+		InetAddress	sender,
+		byte[]		buffer,
+		int			length )
+	{
+		if ( is_enabled ){
+			
+			try{
+				Map<String,String>	map = decodeBeacon( buffer, length );
+				
+				String id = map.get( "identity" );
+				
+				if ( id == null || id.equals( uid )){
+					
+					return( false );
+				}
+				
+				String platform = map.get( "platform" );
+				
+				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 ){
+				
+				log( "Failed to decode beacon", e );
+			}
+		}
+		
+		return( false );
+	}
+	
+	protected DeviceTivo
+	foundTiVo(
+		InetAddress		address,
+		String			uid,
+		String			classification,
+		String			machine )
+	{
+		uid	= "tivo:" + uid;
+		
+		DeviceImpl[] devices = device_manager.getDevices();
+		
+		String server_name = device_manager.getLocalServiceName();
+		
+		for ( DeviceImpl device: devices ){
+			
+			if ( device instanceof DeviceTivo ){
+				
+				DeviceTivo tivo = (DeviceTivo)device;
+				
+				if ( device.getID().equals( uid )){
+				
+					if ( classification != null ){
+						
+						String existing_classification = device.getClassification();
+						
+						if ( !classification.equals( existing_classification )){
+							
+							device.setPersistentStringProperty( DeviceImpl.PP_REND_CLASSIFICATION,classification );
+						}
+					}
+					
+					tivo.found( this, address, server_name, machine );
+					
+					return( tivo );
+				}
+			}
+		}
+		
+			// unfortunately we can't deduce the series from the browse request so start off with a series 3
+			// this will be corrected later if we receive a beacon which *does* contain the series details
+		
+		if ( classification == null ){
+			
+			classification = "tivo.series3";
+		}
+		
+		DeviceTivo new_device = new DeviceTivo( device_manager, uid, classification );
+		
+		DeviceTivo result = (DeviceTivo)device_manager.addDevice( new_device );
+		
+			// possible race here so handle case where device already present
+		
+		if ( result == new_device ){
+		
+			new_device.found( this, address, server_name, machine );
+		}
+		
+		return( result );
+	}
+	
+	protected void
+	log(
+		String		str )
+	{
+		if ( device_manager == null ){
+			
+			System.out.println( str );
+			
+		}else{
+			
+			device_manager.log( "TiVo: " + str );
+		}
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable 	e )
+	{
+		if ( device_manager == null ){
+			
+			System.out.println( str );
+			
+			e.printStackTrace();
+			
+		}else{
+		
+			device_manager.log( "TiVo: " + str, e );
+		}
+	}
+	
+	protected class
+	Searcher
+	{
+		private static final int	LIFE_MILLIS = 10*1000;
+		
+		private long start = SystemTime.getMonotonousTime();
+		
+		private int		tcp_port;
+		
+		private DatagramSocket 		control_socket;
+		private TrackerWebContext 	twc;
+		private TimerEventPeriodic	timer_event;
+		
+		private volatile boolean		persistent;
+		
+		private volatile boolean		search_destroyed;
+		
+		protected
+		Searcher(
+			boolean		_persistent,
+			boolean		_async )
+		
+			throws DeviceManagerException
+		{
+			try{
+				int	last_port = COConfigurationManager.getIntParameter( "devices.tivo.net.tcp.port", 0 );
+				
+				if ( last_port > 0 ){
+					
+					try{
+						ServerSocket ss = new ServerSocket( last_port );
+					
+						ss.setReuseAddress( true );
+						
+						ss.close();
+						
+					}catch( Throwable e ){
+						
+						last_port = 0;
+					}
+				}
+				
+				twc = plugin_interface.getTracker().createWebContext( last_port, Tracker.PR_HTTP );
+				
+				tcp_port = twc.getURLs()[0].getPort();
+
+				COConfigurationManager.setParameter( "devices.tivo.net.tcp.port", tcp_port );
+				
+				twc.addPageGenerator(
+					new TrackerWebPageGenerator()
+					{
+						public boolean 
+						generate(
+							TrackerWebPageRequest 	request,
+							TrackerWebPageResponse 	response )
+						
+							throws IOException 
+						{
+							String	id = (String)request.getHeaders().get( "tsn" );
+							
+							if ( id == null ){
+								
+								id = (String)request.getHeaders().get( "tivo_tcd_id" );	
+							}
+							
+							if ( id != null && is_enabled ){
+								
+								persistent = true;
+								
+								DeviceTivo tivo = foundTiVo( request.getClientAddress2().getAddress(), id, null, null );
+								
+								return( tivo.generate( request, response ));
+							}
+							
+							return( false );
+						}
+					});
+								
+				control_socket  = new DatagramSocket( null );
+					
+				control_socket.setReuseAddress( true );
+					
+				try{
+					control_socket.setSoTimeout( 60*1000 );
+					
+				}catch( Throwable e ){
+				}
+				
+				InetAddress bind = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress();
+				
+				control_socket.bind( new InetSocketAddress( bind, CONTROL_PORT ));
+		
+				timer_event = 
+					SimpleTimer.addPeriodicEvent(
+						"Tivo:Beacon",
+						60*1000,
+						new TimerEventPerformer()
+						{
+							public void 
+							perform(
+								TimerEvent 	event )
+							{
+								if ( !( manager_destroyed || search_destroyed )){
+								
+									sendBeacon();
+								}
+								
+									// see if time to auto-shutdown searching
+								
+								if ( !persistent ){
+								
+									synchronized( DeviceTivoManager.this ){
+									
+										if ( SystemTime.getMonotonousTime() - start >= LIFE_MILLIS ){
+											
+											log( "Terminating search, no devices found" );
+											
+											current_search = null;
+											
+											destroy();
+										}
+									}
+								}
+							}
+						});	
+				
+				final AESemaphore start_sem = new AESemaphore( "TiVo:CtrlListener" );
+				
+				new AEThread2( "TiVo:CtrlListener", true )
+				{
+					public void
+					run()
+					{
+						start_sem.release();
+						
+						long	successful_accepts 	= 0;
+						long	failed_accepts		= 0;
+		
+						while( !( manager_destroyed || search_destroyed )){
+							
+							try{
+								byte[] buf = new byte[8192];
+								
+								DatagramPacket packet = new DatagramPacket(buf, buf.length );
+												
+								control_socket.receive( packet );
+									
+								successful_accepts++;
+								
+								failed_accepts	 = 0;
+								
+								if ( receiveBeacon( packet.getAddress(), packet.getData(), packet.getLength())){
+									
+									persistent = true;
+								}
+								
+							}catch( SocketTimeoutException e ){
+															
+							}catch( Throwable e ){
+								
+								if ( control_socket != null && !search_destroyed && !manager_destroyed ){
+								
+									failed_accepts++;
+								
+									log( "UDP receive on port " + CONTROL_PORT + " failed", e );
+								}
+								
+								if (( failed_accepts > 100 && successful_accepts == 0 ) || failed_accepts > 1000 ){
+									
+									log( "    too many failures, abandoning" );
+		
+									break;
+								}
+							}
+						}				
+					}
+				}.start();
+					
+				if ( _async ){
+					
+					new DelayedEvent( 
+						"search:delay", 
+						5000,
+						new AERunnable()
+						{
+							public void
+							runSupport()
+							{
+								sendBeacon();
+							}
+						});	
+				}else{
+					
+					start_sem.reserve( 5000 );
+				
+					sendBeacon();
+				}
+
+				log( "Initiated device search" );
+				
+			}catch( Throwable e ){
+			
+				log( "Failed to initialise search", e );
+
+				destroy();
+				
+				throw( new DeviceManagerException( "Creation failed",e ));
+			}
+		}
+		
+		protected void
+		sendBeacon()
+		{
+			if ( is_enabled ){
+				
+				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 );
+				}
+			}
+		}
+		
+		protected boolean
+		wakeup()
+		{
+			synchronized( DeviceTivoManager.this ){
+				
+				if ( search_destroyed ){
+					
+					return( false );
+				}
+				
+				start = SystemTime.getMonotonousTime();
+			}
+			
+			sendBeacon();
+			
+			return( true );
+		}
+		
+		protected void
+		destroy()
+		{
+			search_destroyed = true;
+			
+			if ( twc != null ){
+				
+				twc.destroy();
+				
+				twc = null;
+			}
+			
+			if ( timer_event != null ){
+				
+				timer_event.cancel();
+				
+				timer_event = null;
+			}
+			
+			if ( control_socket != null ){
+				
+				try{
+					control_socket.close();
+					
+				}catch( Throwable e ){
+				}
+				
+				control_socket = null;
+			}
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceUPnPImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceUPnPImpl.java
index be3e799..1198189 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceUPnPImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceUPnPImpl.java
@@ -2,20 +2,19 @@
  * 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -49,6 +48,7 @@ import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.content.AzureusContentDownload;
 import com.aelitis.azureus.core.content.AzureusContentFile;
 import com.aelitis.azureus.core.content.AzureusPlatformContentDirectory;
+import com.aelitis.azureus.core.devices.DeviceUPnP;
 import com.aelitis.azureus.core.devices.TranscodeException;
 import com.aelitis.azureus.core.devices.TranscodeFile;
 import com.aelitis.azureus.core.devices.TranscodeJob;
@@ -72,7 +72,7 @@ import com.aelitis.net.upnp.UPnPRootDevice;
 public abstract class 
 DeviceUPnPImpl
 	extends DeviceImpl
-	implements TranscodeTargetListener, DownloadManagerListener
+	implements DeviceUPnP, TranscodeTargetListener, DownloadManagerListener
 {
 	private static final Object UPNPAV_FILE_KEY = new Object();
 		
@@ -251,7 +251,7 @@ DeviceUPnPImpl
 		return( upnp_manager );
 	}
 	
-	protected UPnPDevice
+	public UPnPDevice
 	getUPnPDevice()
 	{
 		return( device_may_be_null );
@@ -266,6 +266,7 @@ DeviceUPnPImpl
 			// triggers any address change logic
 			setAddress(getAddress());
 		}
+		setDirty(false);
 	}
 	
 	public boolean
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceiTunes.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceiTunes.java
index 3158b4e..9957cbe 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceiTunes.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceiTunes.java
@@ -1,743 +1,742 @@
-/*
- * Created on Feb 10, 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.File;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-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.AsyncDispatcher;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.IndentWriter;
-import org.gudy.azureus2.core3.util.SystemTime;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.ipc.IPCInterface;
-
-import com.aelitis.azureus.core.devices.*;
-import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice;
-
-public class 
-DeviceiTunes
-	extends DeviceMediaRendererImpl
-	implements DeviceMediaRenderer
-{
-	private static final String UID = "a5d7869e-1ab9-6098-fef9-88476d988455";
-	
-	private static final Object	ERRROR_KEY_ITUNES 	= new Object();
-	private static final Object	COPY_PENDING_KEY 	= new Object();
-
-	private static final int INSTALL_CHECK_PERIOD	= 60*1000;
-	private static final int RUNNING_CHECK_PERIOD	= 30*1000;
-	private static final int DEVICE_CHECK_PERIOD	= 10*1000;
-	
-	private static final int INSTALL_CHECK_TICKS	= INSTALL_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
-	private static final int RUNNING_CHECK_TICKS	= RUNNING_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
-	private static final int DEVICE_CHECK_TICKS		= DEVICE_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
-	
-	private static final Object	COPY_ERROR_KEY = new Object();
-	
-	private PluginInterface		itunes;
-	
-	private volatile boolean				is_installed;
-	private volatile boolean				is_running;
-	
-	private boolean				copy_outstanding;
-	private boolean				copy_outstanding_set;
-	private AEThread2			copy_thread;
-	private AESemaphore			copy_sem = new AESemaphore( "Device:copy" );
-	private AsyncDispatcher		async_dispatcher = new AsyncDispatcher( 5000 );
-	
-	private long				last_update_fail;
-	private int					consec_fails;
-	
-	private volatile boolean	manual_copy_activated;
-	
-	protected
-	DeviceiTunes(
-		DeviceManagerImpl	_manager,
-		PluginInterface		_itunes )
-	{
-		super( _manager, UID, "iTunes", true );
-		
-		itunes	= _itunes;
-	}
-
-	protected
-	DeviceiTunes(
-		DeviceManagerImpl	_manager,
-		Map					_map )
-	
-		throws IOException
-	{
-		super( _manager, _map );
-	}
-	
-	protected boolean
-	updateFrom(
-		DeviceImpl		_other,
-		boolean			_is_alive )
-	{
-		if ( !super.updateFrom( _other, _is_alive )){
-			
-			return( false );
-		}
-		
-		if ( !( _other instanceof DeviceiTunes )){
-			
-			Debug.out( "Inconsistent" );
-			
-			return( false );
-		}
-		
-		DeviceiTunes other = (DeviceiTunes)_other;
-		
-		itunes = other.itunes;
-		
-		return( true );
-	}
-	
-	protected void
-	initialise()
-	{
-		super.initialise();
-		
-		if ( getPersistentBooleanProperty( PP_COPY_OUTSTANDING, false )){
-		
-			setCopyOutstanding();
-		}
-		
-		addListener( 
-			new TranscodeTargetListener()
-			{
-				public void
-				fileAdded(
-					TranscodeFile		file )
-				{
-					if ( file.isComplete() && !file.isCopiedToDevice()){
-						
-						setCopyOutstanding();
-					}
-				}
-				
-				public void
-				fileChanged(
-					TranscodeFile		file,
-					int					type,
-					Object				data )
-				{
-					if ( file.isComplete() && !file.isCopiedToDevice()){
-						
-						setCopyOutstanding();
-					}
-				}
-				
-				public void
-				fileRemoved(
-					TranscodeFile		file )
-				{
-					copy_sem.release();
-				}
-			});
-	}
-	
-	protected String
-	getDeviceClassification()
-	{
-		return( "apple." );
-	}
-	
-	public int
-	getRendererSpecies()
-	{
-		return( RS_ITUNES );
-	}
-	
-	public InetAddress
-	getAddress()
-	{
-		return( null );
-	}
-	
-	public boolean
-	canRemove()
-	{
-			// no user-initiated removal, they need to uninstall the plugin
-		
-		return( false );
-	}
-	
-	public boolean 
-	isLivenessDetectable() 
-	{
-		return( true );
-	}
-	
-	@Override
-	public URL
-	getWikiURL()
-	{
-		try{
-			return( new URL( MessageText.getString( "device.wiki.itunes" )) );
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			return( null );
-		}
-	}
-	
-	protected void
-	destroy()
-	{
-		super.destroy();
-	}
-	
-	protected void
-	updateStatus(
-		int		tick_count )
-	{
-		super.updateStatus( tick_count );
-		
-		updateStatusSupport( tick_count );
-		
-		if ( is_installed && is_running ){
-			
-			alive();
-			
-		}else{
-			
-			dead();
-		}
-	}
-	
-	protected void
-	updateStatusSupport(
-		int		tick_count )
-	{
-		if ( itunes == null ){
-			
-			return;
-		}
-		
-		if ( !is_installed ){
-			
-			if ( tick_count % INSTALL_CHECK_TICKS == 0 ){
-				
-				updateiTunesStatus();
-				
-				return;
-			}
-		}
-		
-		if ( !is_running ){
-			
-			if ( tick_count % RUNNING_CHECK_TICKS == 0 ){
-				
-				updateiTunesStatus();
-				
-				return;
-			}
-		}
-		
-		if ( tick_count % DEVICE_CHECK_TICKS == 0 ){
-
-			updateiTunesStatus();
-		}
-	}
-	
-	protected void
-	updateiTunesStatus()
-	{	
-		if ( getManager().isClosing()){
-			
-			return;
-		}
-		
-		IPCInterface	ipc = itunes.getIPC();
-		
-		try{
-			Map<String,Object> properties = (Map<String,Object>)ipc.invoke( "getProperties", new Object[]{} );
-
-			is_installed = (Boolean)properties.get( "installed" );
-			
-			boolean	was_running = is_running;
-			
-			is_running	 = (Boolean)properties.get( "running" );
-			
-			if ( is_running && !was_running ){
-				
-				copy_sem.release();
-			}
-			
-			if ( !( is_installed || is_running )){
-				
-				last_update_fail = 0;
-			}
-			
-			String	info = null;
-			
-			if ( getCopyToDevicePending() > 0 ){
-				
-				if ( !is_installed ){
-					
-					info = MessageText.getString( "device.itunes.install" );
-					
-				}else if ( !is_running ){
-					
-					if ( !getAutoStartDevice()){
-					
-						info = MessageText.getString( "device.itunes.start" );
-					}
-				}
-			}
-				
-			setInfo( ERRROR_KEY_ITUNES, info );
-			
-			Throwable error = (Throwable)properties.get( "error" );
-			
-			if ( error != null ){
-				
-				throw( error );
-			}
-			
-			/*
-			List<Map<String,Object>> sources = (List<Map<String,Object>>)properties.get( "sources" );
-			
-			if ( sources != null ){
-				
-				for ( Map<String,Object> source: sources ){
-					
-					System.out.println( source );
-				}
-			}
-			*/
-			
-			last_update_fail 	= 0;
-			consec_fails		= 0;
-			
-			setError( ERRROR_KEY_ITUNES, null );
-			
-		}catch( Throwable e ){
-			
-			long	now = SystemTime.getMonotonousTime();
-			
-			consec_fails++;
-			
-			if ( last_update_fail == 0 ){
-				
-				last_update_fail = now;
-				
-			}else if ( now - last_update_fail > 60*1000 && consec_fails >= 3 ){
-							
-				setError( ERRROR_KEY_ITUNES, MessageText.getString( "device.itunes.install_problem" ));
-			}
-			
-			log( "iTunes IPC failed", e );
-		}
-	}
-	
-	public boolean
-	canCopyToDevice()
-	{
-		return( true );
-	}
-	
-	public boolean
-	getAutoCopyToDevice()
-	{
-			// default is true for itunes
-		
-		return( getPersistentBooleanProperty( PP_AUTO_COPY, true  ));
-	}
-		
-	public void
-	setAutoCopyToDevice(
-		boolean		auto )
-	{
-		setPersistentBooleanProperty( PP_AUTO_COPY, auto );
-		
-		setCopyOutstanding();
-	}
-	
-	public int
-	getCopyToDevicePending()
-	{
-		synchronized( this ){
-		
-			if ( !copy_outstanding ){
-				
-				return( 0 );
-			}
-		}
-
-		TranscodeFileImpl[] files = getFiles();
-		
-		int result = 0;
-			
-		for ( TranscodeFileImpl file: files ){
-
-			if ( file.isComplete() && !file.isCopiedToDevice()){
-				
-				result++;
-			}
-		}
-		
-		return( result );
-	}
-	
-	public void 
-	manualCopy() 
-	
-		throws DeviceManagerException 
-	{
-		if ( getAutoCopyToDevice()){
-			
-			throw( new DeviceManagerException( "Operation prohibited - auto copy enabled" ));
-		}
-		
-		manual_copy_activated = true;
-		
-		setCopyOutstanding();
-	}
-	
-	protected void
-	setCopyOutstanding()
-	{
-		synchronized( this ){
-			
-			copy_outstanding_set = true;
-			
-			if ( copy_thread == null ){
-				
-				copy_thread = 
-					new AEThread2( "Device:copier", true )
-					{
-						public void
-						run()
-						{
-							performCopy();
-						}
-					};
-									
-				copy_thread.start();
-			}
-			
-			copy_sem.release();
-		}
-	}
-	
-	public boolean
-	canAutoStartDevice()
-	{
-		return( true );
-	}
-	
-	public boolean
-	getAutoStartDevice()
-	{
-		return( getPersistentBooleanProperty( PP_AUTO_START, PR_AUTO_START_DEFAULT ));
-	}
-	
-	public void
-	setAutoStartDevice(
-		boolean		auto )
-	{
-		setPersistentBooleanProperty( PP_AUTO_START, auto );
-		
-		if ( auto ){
-			
-			copy_sem.release();
-		}
-	}
-	
-	public boolean
-	canAssociate()
-	{
-		return( false );
-	}
-	
-	public boolean
-	canRestrictAccess()
-	{
-		return( false );
-	}
-	
-	public void
-	associate(
-		UnassociatedDevice	assoc )
-	{
-	}
-	
-	protected void
-	performCopy()
-	{
-		synchronized( this ){
-
-			copy_outstanding = true;
-		
-			async_dispatcher.dispatch(
-				new AERunnable()
-				{
-					public void
-					runSupport()
-					{
-						setPersistentBooleanProperty( PP_COPY_OUTSTANDING, true );
-					}
-				});
-		}
-		
-		while( true ){
-			
-			if ( copy_sem.reserve( 60*1000 )){
-				
-				while( copy_sem.reserveIfAvailable());
-			}
-				
-			if ( !getAutoCopyToDevice()){
-				
-				if ( manual_copy_activated ){
-					
-					manual_copy_activated = false;
-					
-				}else{
-					
-					TranscodeFileImpl[] files = getFiles();
-					
-					int to_copy = 0;
-					
-					for ( TranscodeFileImpl file: files ){
-							
-						if ( file.isComplete() && !file.isCopiedToDevice()){
-							
-							to_copy++;
-						}
-					}
-					
-					if ( to_copy == 0 ){
-						
-						setInfo( COPY_PENDING_KEY, null );
-					}else{
-					
-						String str = MessageText.getString( "devices.info.copypending3", new String[]{ String.valueOf( to_copy ) });
-	
-						setInfo( COPY_PENDING_KEY, str );
-					}
-					
-					continue;
-				}
-			}
-			
-			setInfo( COPY_PENDING_KEY, null );
-
-			boolean	auto_start = getAutoStartDevice();
-			
-			synchronized( this ){
-
-				if ( itunes == null || ( !is_running && !( auto_start && is_installed ))){
-					
-					if ( !( copy_outstanding || copy_outstanding_set )){
-						
-						copy_thread = null;
-						
-						break;
-					}
-					
-					continue;
-				}
-
-				copy_outstanding_set = false;
-			}
-						
-			TranscodeFileImpl[] files = getFiles();
-				
-			List<TranscodeFileImpl>	to_copy = new ArrayList<TranscodeFileImpl>();
-				
-			boolean	borked_exist = false;
-			
-			for ( TranscodeFileImpl file: files ){
-					
-				if ( file.isComplete() && !file.isCopiedToDevice()){
-					
-					if ( file.getCopyToDeviceFails() < 3 ){
-					
-						to_copy.add( file );
-						
-					}else{
-						
-						borked_exist = true;
-					}
-				}
-			}
-				
-			if ( borked_exist ){
-				
-				setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copyfail2") );
-			}
-			
-			synchronized( this ){
-
-				if ( to_copy.size() == 0 && !copy_outstanding_set && !borked_exist ){
-						
-					copy_outstanding = false;
-					
-					async_dispatcher.dispatch(
-						new AERunnable()
-						{
-							public void
-							runSupport()
-							{
-								setError( COPY_ERROR_KEY, null );
-
-								setPersistentBooleanProperty( PP_COPY_OUTSTANDING, false );
-							}
-						});
-					
-					copy_thread = null;
-					
-					break;
-				}
-			}
-			
-			for ( TranscodeFileImpl transcode_file: to_copy ){
-				
-				try{
-					File	file = transcode_file.getTargetFile().getFile();
-					
-					try{
-						IPCInterface	ipc = itunes.getIPC();
-						
-						if ( !is_running ){
-							
-							log( "Auto-starting iTunes" );
-						}
-
-						Map<String,Object> result = (Map<String,Object>)ipc.invoke( "addFileToLibrary", new Object[]{ file } );
-		
-						Throwable error = (Throwable)result.get( "error" );
-						
-						if ( error != null ){
-							
-							throw( error );
-						}
-						
-						is_running = true;
-						
-						log( "Added file '" + file + ": " + result );
-						
-						transcode_file.setCopiedToDevice( true );
-						
-					}catch( Throwable e ){
-						
-						transcode_file.setCopyToDeviceFailed();
-						
-						log( "Failed to copy file " + file, e );
-					}
-				}catch( TranscodeException e ){
-
-					// file has been deleted
-				}
-			}
-		}
-	}
-	
-	public boolean 
-	isBrowsable()
-	{
-		return( false );
-	}
-	
-	public browseLocation[] 
-	getBrowseLocations() 
-	{
-		return null;
-	}
-	
-	protected void
-	getDisplayProperties(
-		List<String[]>	dp )
-	{
-		super.getDisplayProperties( dp );
-		
-		if ( itunes == null ){
-			
-			addDP( dp, "devices.comp.missing", "<null>" );
-
-		}else{
-			
-			updateiTunesStatus();
-			
-			addDP( dp, "devices.installed", is_installed );
-				
-			addDP( dp, "MyTrackerView.status.started", is_running );
-			
-			addDP( dp, "devices.copy.pending", copy_outstanding );
-			
-			addDP( dp, "devices.auto.start", getAutoStartDevice());
-		}
-	}
-	
-	public String
-	getStatus()
-	{
-		if ( is_running ){
-			
-			return( MessageText.getString( "device.itunes.status.running" ));
-			
-		}else if ( is_installed ){
-			
-			return( MessageText.getString( "device.itunes.status.notrunning" ));
-
-		}else{
-			
-			return( MessageText.getString( "device.itunes.status.notinstalled" ));
-		}     
-	}
-	
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		super.generate( writer );
-		
-		try{
-			writer.indent();
-	
-			writer.println( "itunes=" + itunes + ", installed=" + is_installed + ", running=" + is_running + ", auto_start=" + getAutoStartDevice());
-			writer.println( "copy_os=" + copy_outstanding + ", last_fail=" + new SimpleDateFormat().format( new Date( last_update_fail )));
-			
-		}finally{
-			
-			writer.exdent();
-		}
-	}
-}
+/*
+ * Created on Feb 10, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+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.AsyncDispatcher;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.IndentWriter;
+import org.gudy.azureus2.core3.util.SystemTime;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.ipc.IPCInterface;
+
+import com.aelitis.azureus.core.devices.*;
+import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice;
+
+public class 
+DeviceiTunes
+	extends DeviceMediaRendererImpl
+	implements DeviceMediaRenderer
+{
+	private static final String UID = "a5d7869e-1ab9-6098-fef9-88476d988455";
+	
+	private static final Object	ERRROR_KEY_ITUNES 	= new Object();
+	private static final Object	COPY_PENDING_KEY 	= new Object();
+
+	private static final int INSTALL_CHECK_PERIOD	= 60*1000;
+	private static final int RUNNING_CHECK_PERIOD	= 30*1000;
+	private static final int DEVICE_CHECK_PERIOD	= 10*1000;
+	
+	private static final int INSTALL_CHECK_TICKS	= INSTALL_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
+	private static final int RUNNING_CHECK_TICKS	= RUNNING_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
+	private static final int DEVICE_CHECK_TICKS		= DEVICE_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
+	
+	private static final Object	COPY_ERROR_KEY = new Object();
+	
+	private PluginInterface		itunes;
+	
+	private volatile boolean				is_installed;
+	private volatile boolean				is_running;
+	
+	private boolean				copy_outstanding;
+	private boolean				copy_outstanding_set;
+	private AEThread2			copy_thread;
+	private AESemaphore			copy_sem = new AESemaphore( "Device:copy" );
+	private AsyncDispatcher		async_dispatcher = new AsyncDispatcher( 5000 );
+	
+	private long				last_update_fail;
+	private int					consec_fails;
+	
+	private volatile boolean	manual_copy_activated;
+	
+	protected
+	DeviceiTunes(
+		DeviceManagerImpl	_manager,
+		PluginInterface		_itunes )
+	{
+		super( _manager, UID, "iTunes", true );
+		
+		itunes	= _itunes;
+	}
+
+	protected
+	DeviceiTunes(
+		DeviceManagerImpl	_manager,
+		Map					_map )
+	
+		throws IOException
+	{
+		super( _manager, _map );
+	}
+	
+	protected boolean
+	updateFrom(
+		DeviceImpl		_other,
+		boolean			_is_alive )
+	{
+		if ( !super.updateFrom( _other, _is_alive )){
+			
+			return( false );
+		}
+		
+		if ( !( _other instanceof DeviceiTunes )){
+			
+			Debug.out( "Inconsistent" );
+			
+			return( false );
+		}
+		
+		DeviceiTunes other = (DeviceiTunes)_other;
+		
+		itunes = other.itunes;
+		
+		return( true );
+	}
+	
+	protected void
+	initialise()
+	{
+		super.initialise();
+		
+		if ( getPersistentBooleanProperty( PP_COPY_OUTSTANDING, false )){
+		
+			setCopyOutstanding();
+		}
+		
+		addListener( 
+			new TranscodeTargetListener()
+			{
+				public void
+				fileAdded(
+					TranscodeFile		file )
+				{
+					if ( file.isComplete() && !file.isCopiedToDevice()){
+						
+						setCopyOutstanding();
+					}
+				}
+				
+				public void
+				fileChanged(
+					TranscodeFile		file,
+					int					type,
+					Object				data )
+				{
+					if ( file.isComplete() && !file.isCopiedToDevice()){
+						
+						setCopyOutstanding();
+					}
+				}
+				
+				public void
+				fileRemoved(
+					TranscodeFile		file )
+				{
+					copy_sem.release();
+				}
+			});
+	}
+	
+	protected String
+	getDeviceClassification()
+	{
+		return( "apple." );
+	}
+	
+	public int
+	getRendererSpecies()
+	{
+		return( RS_ITUNES );
+	}
+	
+	public InetAddress
+	getAddress()
+	{
+		return( null );
+	}
+	
+	public boolean
+	canRemove()
+	{
+			// no user-initiated removal, they need to uninstall the plugin
+		
+		return( false );
+	}
+	
+	public boolean 
+	isLivenessDetectable() 
+	{
+		return( true );
+	}
+	
+	@Override
+	public URL
+	getWikiURL()
+	{
+		try{
+			return( new URL( MessageText.getString( "device.wiki.itunes" )) );
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( null );
+		}
+	}
+	
+	protected void
+	destroy()
+	{
+		super.destroy();
+	}
+	
+	protected void
+	updateStatus(
+		int		tick_count )
+	{
+		super.updateStatus( tick_count );
+		
+		updateStatusSupport( tick_count );
+		
+		if ( is_installed && is_running ){
+			
+			alive();
+			
+		}else{
+			
+			dead();
+		}
+	}
+	
+	protected void
+	updateStatusSupport(
+		int		tick_count )
+	{
+		if ( itunes == null ){
+			
+			return;
+		}
+		
+		if ( !is_installed ){
+			
+			if ( tick_count % INSTALL_CHECK_TICKS == 0 ){
+				
+				updateiTunesStatus();
+				
+				return;
+			}
+		}
+		
+		if ( !is_running ){
+			
+			if ( tick_count % RUNNING_CHECK_TICKS == 0 ){
+				
+				updateiTunesStatus();
+				
+				return;
+			}
+		}
+		
+		if ( tick_count % DEVICE_CHECK_TICKS == 0 ){
+
+			updateiTunesStatus();
+		}
+	}
+	
+	protected void
+	updateiTunesStatus()
+	{	
+		if ( getManager().isClosing()){
+			
+			return;
+		}
+		
+		IPCInterface	ipc = itunes.getIPC();
+		
+		try{
+			Map<String,Object> properties = (Map<String,Object>)ipc.invoke( "getProperties", new Object[]{} );
+
+			is_installed = (Boolean)properties.get( "installed" );
+			
+			boolean	was_running = is_running;
+			
+			is_running	 = (Boolean)properties.get( "running" );
+			
+			if ( is_running && !was_running ){
+				
+				copy_sem.release();
+			}
+			
+			if ( !( is_installed || is_running )){
+				
+				last_update_fail = 0;
+			}
+			
+			String	info = null;
+			
+			if ( getCopyToDevicePending() > 0 ){
+				
+				if ( !is_installed ){
+					
+					info = MessageText.getString( "device.itunes.install" );
+					
+				}else if ( !is_running ){
+					
+					if ( !getAutoStartDevice()){
+					
+						info = MessageText.getString( "device.itunes.start" );
+					}
+				}
+			}
+				
+			setInfo( ERRROR_KEY_ITUNES, info );
+			
+			Throwable error = (Throwable)properties.get( "error" );
+			
+			if ( error != null ){
+				
+				throw( error );
+			}
+			
+			/*
+			List<Map<String,Object>> sources = (List<Map<String,Object>>)properties.get( "sources" );
+			
+			if ( sources != null ){
+				
+				for ( Map<String,Object> source: sources ){
+					
+					System.out.println( source );
+				}
+			}
+			*/
+			
+			last_update_fail 	= 0;
+			consec_fails		= 0;
+			
+			setError( ERRROR_KEY_ITUNES, null );
+			
+		}catch( Throwable e ){
+			
+			long	now = SystemTime.getMonotonousTime();
+			
+			consec_fails++;
+			
+			if ( last_update_fail == 0 ){
+				
+				last_update_fail = now;
+				
+			}else if ( now - last_update_fail > 60*1000 && consec_fails >= 3 ){
+							
+				setError( ERRROR_KEY_ITUNES, MessageText.getString( "device.itunes.install_problem" ));
+			}
+			
+			log( "iTunes IPC failed", e );
+		}
+	}
+	
+	public boolean
+	canCopyToDevice()
+	{
+		return( true );
+	}
+	
+	public boolean
+	getAutoCopyToDevice()
+	{
+			// default is true for itunes
+		
+		return( getPersistentBooleanProperty( PP_AUTO_COPY, true  ));
+	}
+		
+	public void
+	setAutoCopyToDevice(
+		boolean		auto )
+	{
+		setPersistentBooleanProperty( PP_AUTO_COPY, auto );
+		
+		setCopyOutstanding();
+	}
+	
+	public int
+	getCopyToDevicePending()
+	{
+		synchronized( this ){
+		
+			if ( !copy_outstanding ){
+				
+				return( 0 );
+			}
+		}
+
+		TranscodeFileImpl[] files = getFiles();
+		
+		int result = 0;
+			
+		for ( TranscodeFileImpl file: files ){
+
+			if ( file.isComplete() && !file.isCopiedToDevice()){
+				
+				result++;
+			}
+		}
+		
+		return( result );
+	}
+	
+	public void 
+	manualCopy() 
+	
+		throws DeviceManagerException 
+	{
+		if ( getAutoCopyToDevice()){
+			
+			throw( new DeviceManagerException( "Operation prohibited - auto copy enabled" ));
+		}
+		
+		manual_copy_activated = true;
+		
+		setCopyOutstanding();
+	}
+	
+	protected void
+	setCopyOutstanding()
+	{
+		synchronized( this ){
+			
+			copy_outstanding_set = true;
+			
+			if ( copy_thread == null ){
+				
+				copy_thread = 
+					new AEThread2( "Device:copier", true )
+					{
+						public void
+						run()
+						{
+							performCopy();
+						}
+					};
+									
+				copy_thread.start();
+			}
+			
+			copy_sem.release();
+		}
+	}
+	
+	public boolean
+	canAutoStartDevice()
+	{
+		return( true );
+	}
+	
+	public boolean
+	getAutoStartDevice()
+	{
+		return( getPersistentBooleanProperty( PP_AUTO_START, PR_AUTO_START_DEFAULT ));
+	}
+	
+	public void
+	setAutoStartDevice(
+		boolean		auto )
+	{
+		setPersistentBooleanProperty( PP_AUTO_START, auto );
+		
+		if ( auto ){
+			
+			copy_sem.release();
+		}
+	}
+	
+	public boolean
+	canAssociate()
+	{
+		return( false );
+	}
+	
+	public boolean
+	canRestrictAccess()
+	{
+		return( false );
+	}
+	
+	public void
+	associate(
+		UnassociatedDevice	assoc )
+	{
+	}
+	
+	protected void
+	performCopy()
+	{
+		synchronized( this ){
+
+			copy_outstanding = true;
+		
+			async_dispatcher.dispatch(
+				new AERunnable()
+				{
+					public void
+					runSupport()
+					{
+						setPersistentBooleanProperty( PP_COPY_OUTSTANDING, true );
+					}
+				});
+		}
+		
+		while( true ){
+			
+			if ( copy_sem.reserve( 60*1000 )){
+				
+				while( copy_sem.reserveIfAvailable());
+			}
+				
+			if ( !getAutoCopyToDevice()){
+				
+				if ( manual_copy_activated ){
+					
+					manual_copy_activated = false;
+					
+				}else{
+					
+					TranscodeFileImpl[] files = getFiles();
+					
+					int to_copy = 0;
+					
+					for ( TranscodeFileImpl file: files ){
+							
+						if ( file.isComplete() && !file.isCopiedToDevice()){
+							
+							to_copy++;
+						}
+					}
+					
+					if ( to_copy == 0 ){
+						
+						setInfo( COPY_PENDING_KEY, null );
+					}else{
+					
+						String str = MessageText.getString( "devices.info.copypending3", new String[]{ String.valueOf( to_copy ) });
+	
+						setInfo( COPY_PENDING_KEY, str );
+					}
+					
+					continue;
+				}
+			}
+			
+			setInfo( COPY_PENDING_KEY, null );
+
+			boolean	auto_start = getAutoStartDevice();
+			
+			synchronized( this ){
+
+				if ( itunes == null || ( !is_running && !( auto_start && is_installed ))){
+					
+					if ( !( copy_outstanding || copy_outstanding_set )){
+						
+						copy_thread = null;
+						
+						break;
+					}
+					
+					continue;
+				}
+
+				copy_outstanding_set = false;
+			}
+						
+			TranscodeFileImpl[] files = getFiles();
+				
+			List<TranscodeFileImpl>	to_copy = new ArrayList<TranscodeFileImpl>();
+				
+			boolean	borked_exist = false;
+			
+			for ( TranscodeFileImpl file: files ){
+					
+				if ( file.isComplete() && !file.isCopiedToDevice()){
+					
+					if ( file.getCopyToDeviceFails() < 3 ){
+					
+						to_copy.add( file );
+						
+					}else{
+						
+						borked_exist = true;
+					}
+				}
+			}
+				
+			if ( borked_exist ){
+				
+				setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copyfail2") );
+			}
+			
+			synchronized( this ){
+
+				if ( to_copy.size() == 0 && !copy_outstanding_set && !borked_exist ){
+						
+					copy_outstanding = false;
+					
+					async_dispatcher.dispatch(
+						new AERunnable()
+						{
+							public void
+							runSupport()
+							{
+								setError( COPY_ERROR_KEY, null );
+
+								setPersistentBooleanProperty( PP_COPY_OUTSTANDING, false );
+							}
+						});
+					
+					copy_thread = null;
+					
+					break;
+				}
+			}
+			
+			for ( TranscodeFileImpl transcode_file: to_copy ){
+				
+				try{
+					File	file = transcode_file.getTargetFile().getFile();
+					
+					try{
+						IPCInterface	ipc = itunes.getIPC();
+						
+						if ( !is_running ){
+							
+							log( "Auto-starting iTunes" );
+						}
+
+						Map<String,Object> result = (Map<String,Object>)ipc.invoke( "addFileToLibrary", new Object[]{ file } );
+		
+						Throwable error = (Throwable)result.get( "error" );
+						
+						if ( error != null ){
+							
+							throw( error );
+						}
+						
+						is_running = true;
+						
+						log( "Added file '" + file + ": " + result );
+						
+						transcode_file.setCopiedToDevice( true );
+						
+					}catch( Throwable e ){
+						
+						transcode_file.setCopyToDeviceFailed();
+						
+						log( "Failed to copy file " + file, e );
+					}
+				}catch( TranscodeException e ){
+
+					// file has been deleted
+				}
+			}
+		}
+	}
+	
+	public boolean 
+	isBrowsable()
+	{
+		return( false );
+	}
+	
+	public browseLocation[] 
+	getBrowseLocations() 
+	{
+		return null;
+	}
+	
+	protected void
+	getDisplayProperties(
+		List<String[]>	dp )
+	{
+		super.getDisplayProperties( dp );
+		
+		if ( itunes == null ){
+			
+			addDP( dp, "devices.comp.missing", "<null>" );
+
+		}else{
+			
+			updateiTunesStatus();
+			
+			addDP( dp, "devices.installed", is_installed );
+				
+			addDP( dp, "MyTrackerView.status.started", is_running );
+			
+			addDP( dp, "devices.copy.pending", copy_outstanding );
+			
+			addDP( dp, "devices.auto.start", getAutoStartDevice());
+		}
+	}
+	
+	public String
+	getStatus()
+	{
+		if ( is_running ){
+			
+			return( MessageText.getString( "device.itunes.status.running" ));
+			
+		}else if ( is_installed ){
+			
+			return( MessageText.getString( "device.itunes.status.notrunning" ));
+
+		}else{
+			
+			return( MessageText.getString( "device.itunes.status.notinstalled" ));
+		}     
+	}
+	
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		super.generate( writer );
+		
+		try{
+			writer.indent();
+	
+			writer.println( "itunes=" + itunes + ", installed=" + is_installed + ", running=" + is_running + ", auto_start=" + getAutoStartDevice());
+			writer.println( "copy_os=" + copy_outstanding + ", last_fail=" + new SimpleDateFormat().format( new Date( last_update_fail )));
+			
+		}finally{
+			
+			writer.exdent();
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceiTunesManager.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceiTunesManager.java
index 5d74cf7..e2cadd2 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceiTunesManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/DeviceiTunesManager.java
@@ -1,169 +1,168 @@
-/*
- * Created on Feb 10, 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 org.gudy.azureus2.plugins.PluginEvent;
-import org.gudy.azureus2.plugins.PluginEventListener;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.PluginListener;
-import org.gudy.azureus2.plugins.PluginManager;
-
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreRunningListener;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-
-public class 
-DeviceiTunesManager 
-{
-	private DeviceManagerImpl		device_manager;
-	
-	private DeviceiTunes			itunes_device;
-	
-	protected
-	DeviceiTunesManager(
-		DeviceManagerImpl		_dm )
-	{
-		device_manager = _dm;
-
-		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
-			public void azureusCoreRunning(AzureusCore core) {
-				init(core);
-			}
-		});
-	}
-	
-	private void init(
-			AzureusCore azureus_core )
-	{
-		
-		final PluginManager pm = azureus_core.getPluginManager();
-		
-		final PluginInterface default_pi = pm.getDefaultPluginInterface();
-		
-		default_pi.addListener(
-			new PluginListener()
-			{
-				public void
-				initializationComplete()
-				{
-					default_pi.addEventListener(
-						new PluginEventListener()
-						{
-							public void 
-							handleEvent(
-								PluginEvent ev )
-							{
-								int	type = ev.getType();
-								
-								if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL ){
-									
-									pluginAdded((PluginInterface)ev.getValue());
-								}
-								if ( type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL ){
-									
-									pluginRemoved((PluginInterface)ev.getValue());
-								}
-							}
-						});
-					
-					PluginInterface[] plugins = pm.getPlugins();
-					
-					for ( PluginInterface pi: plugins ){
-						
-						if ( pi.getPluginState().isOperational()){
-						
-							pluginAdded( pi );
-						}
-					}
-				}
-				
-				public void
-				closedownInitiated()
-				{	
-				}
-				
-				public void
-				closedownComplete()
-				{
-				}
-			});
-	}
-	
-	protected void
-	pluginAdded(
-		PluginInterface		pi )
-	{
-		if ( pi.getPluginState().isBuiltIn()){
-			
-			return;
-		}
-		
-		String plugin_id = pi.getPluginID();
-		
-		if ( plugin_id.equals( "azitunes" )){
-			
-			DeviceiTunes new_device;
-			
-			synchronized( this ){
-				
-				if ( itunes_device == null ){
-					
-					itunes_device = new_device = new DeviceiTunes( device_manager, pi );
-					
-				}else{
-					
-					return;
-				}
-			}
-			
-			device_manager.addDevice( new_device, false );
-		}
-	}	
-	
-	protected void
-	pluginRemoved(
-		PluginInterface		pi )
-	{
-		String plugin_id = pi.getPluginID();
-		
-		if ( plugin_id.equals( "azitunes" )){
-			
-			DeviceiTunes existing_device;
-
-			synchronized( this ){
-				
-				if ( itunes_device != null ){
-
-					existing_device = itunes_device;
-					
-					itunes_device = null;
-					
-				}else{
-					
-					return;
-				}
-			}
-			
-			existing_device.remove();
-		}
-	}
-}
+/*
+ * Created on Feb 10, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import org.gudy.azureus2.plugins.PluginEvent;
+import org.gudy.azureus2.plugins.PluginEventListener;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.PluginListener;
+import org.gudy.azureus2.plugins.PluginManager;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+
+public class 
+DeviceiTunesManager 
+{
+	private DeviceManagerImpl		device_manager;
+	
+	private DeviceiTunes			itunes_device;
+	
+	protected
+	DeviceiTunesManager(
+		DeviceManagerImpl		_dm )
+	{
+		device_manager = _dm;
+
+		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+			public void azureusCoreRunning(AzureusCore core) {
+				init(core);
+			}
+		});
+	}
+	
+	private void init(
+			AzureusCore azureus_core )
+	{
+		
+		final PluginManager pm = azureus_core.getPluginManager();
+		
+		final PluginInterface default_pi = pm.getDefaultPluginInterface();
+		
+		default_pi.addListener(
+			new PluginListener()
+			{
+				public void
+				initializationComplete()
+				{
+					default_pi.addEventListener(
+						new PluginEventListener()
+						{
+							public void 
+							handleEvent(
+								PluginEvent ev )
+							{
+								int	type = ev.getType();
+								
+								if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL ){
+									
+									pluginAdded((PluginInterface)ev.getValue());
+								}
+								if ( type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL ){
+									
+									pluginRemoved((PluginInterface)ev.getValue());
+								}
+							}
+						});
+					
+					PluginInterface[] plugins = pm.getPlugins();
+					
+					for ( PluginInterface pi: plugins ){
+						
+						if ( pi.getPluginState().isOperational()){
+						
+							pluginAdded( pi );
+						}
+					}
+				}
+				
+				public void
+				closedownInitiated()
+				{	
+				}
+				
+				public void
+				closedownComplete()
+				{
+				}
+			});
+	}
+	
+	protected void
+	pluginAdded(
+		PluginInterface		pi )
+	{
+		if ( pi.getPluginState().isBuiltIn()){
+			
+			return;
+		}
+		
+		String plugin_id = pi.getPluginID();
+		
+		if ( plugin_id.equals( "azitunes" )){
+			
+			DeviceiTunes new_device;
+			
+			synchronized( this ){
+				
+				if ( itunes_device == null ){
+					
+					itunes_device = new_device = new DeviceiTunes( device_manager, pi );
+					
+				}else{
+					
+					return;
+				}
+			}
+			
+			device_manager.addDevice( new_device, false );
+		}
+	}	
+	
+	protected void
+	pluginRemoved(
+		PluginInterface		pi )
+	{
+		String plugin_id = pi.getPluginID();
+		
+		if ( plugin_id.equals( "azitunes" )){
+			
+			DeviceiTunes existing_device;
+
+			synchronized( this ){
+				
+				if ( itunes_device != null ){
+
+					existing_device = itunes_device;
+					
+					itunes_device = null;
+					
+				}else{
+					
+					return;
+				}
+			}
+			
+			existing_device.remove();
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeFileImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeFileImpl.java
index 9a94477..94ae5c6 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeFileImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeFileImpl.java
@@ -1,916 +1,915 @@
-/*
- * Created on Feb 18, 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.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadException;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-
-import com.aelitis.azureus.core.devices.Device;
-import com.aelitis.azureus.core.devices.TranscodeException;
-import com.aelitis.azureus.core.devices.TranscodeFile;
-import com.aelitis.azureus.core.devices.TranscodeJob;
-import com.aelitis.azureus.core.devices.TranscodeProviderAnalysis;
-import com.aelitis.azureus.core.devices.TranscodeTargetListener;
-import com.aelitis.azureus.core.download.DiskManagerFileInfoDelegate;
-import com.aelitis.azureus.core.download.DiskManagerFileInfoFile;
-import com.aelitis.azureus.core.tag.Tag;
-import com.aelitis.azureus.core.tag.TagManager;
-import com.aelitis.azureus.core.tag.TagManagerFactory;
-import com.aelitis.azureus.util.ImportExportUtils;
-
-class
-TranscodeFileImpl
-	implements TranscodeFile
-{	
-	protected static final String		KEY_FILE			= "file";
-	
-	private static final TagManager	tag_manager = TagManagerFactory.getTagManager();
-	
-	private static final String			KEY_PROFILE_NAME		= "pn";
-	private static final String			KEY_SOURCE_FILE_HASH	= "sf_hash";
-	private static final String			KEY_SOURCE_FILE_INDEX	= "sf_index";
-	private static final String			KEY_SOURCE_FILE_LINK	= "sf_link";
-	private static final String			KEY_NO_XCODE			= "no_xcode";
-	private static final String			KEY_FOR_JOB				= "fj";
-
-	private static final String			KEY_DURATION			= "at_dur";
-	private static final String			KEY_VIDEO_WIDTH			= "at_vw";
-	private static final String			KEY_VIDEO_HEIGHT		= "at_vh";
-	private static final String			KEY_XCODE_SIZE			= "at_xs";
-	private static final String			KEY_DATE				= "at_dt";
-	private static final String			KEY_CATEGORIES			= PT_CATEGORY;
-	private static final String			KEY_TAGS				= PT_TAGS;
-	private static final String			KEY_COPY_TO_OVERRIDE	= "ct_over";
-	private static final String			KEY_COPYING	= "copying";
-
-	private DeviceImpl					device;
-	private String						key;
-	private Map<String,Map<String,?>>	files_map;
-
-		// don't store any local state here, store it in the map as this is just a wrapper
-		// for the underlying map and there can be multiple such wrappers concurrent
-	
-	protected 
-	TranscodeFileImpl(
-		DeviceImpl					_device,
-		String						_key,
-		String						_profile_name,
-		Map<String,Map<String,?>>	_files_map,
-		File						_file,
-		boolean						_for_job )
-	{
-		device		= _device;
-		key			= _key;
-		files_map	= _files_map;
-
-		getMap( true );
-		
-		setString( KEY_FILE, _file.getAbsolutePath());
-		
-		setString( KEY_PROFILE_NAME, _profile_name );
-		
-		setLong( KEY_DATE, SystemTime.getCurrentTime());
-		
-		setBoolean( KEY_FOR_JOB, _for_job );
-		
-		setBoolean( KEY_COPYING, false );
-	}
-	
-	protected
-	TranscodeFileImpl(
-		DeviceImpl					_device,
-		String						_key,
-		Map<String,Map<String,?>>	_map )
-	
-		throws IOException
-	{
-		device			= _device;
-		key				= _key;
-		files_map		= _map;
-		
-		Map<String,?> map = getMap();
-		
-		if ( map == null || !map.containsKey( KEY_FILE )){
-			
-			throw( new IOException( "File has been deleted" ));
-		}
-	}
-	
-	
-	protected String
-	getKey()
-	{
-		return( key );
-	}
-	
-	public String
-	getName()
-	{
-		TranscodeJob job = getJob();
-
-		String text;
-		
-		if ( job == null){
-			
-			try{
-				DiskManagerFileInfo sourceFile = getSourceFile();
-				
-				try {
-					Download download = sourceFile.getDownload();
-					
-					if ( download == null ){
-						
-						text = sourceFile.getFile().getName();
-						
-					}else{
-						
-						text = download.getName();
-						
-						DiskManagerFileInfo[] fileInfo = download.getDiskManagerFileInfo();
-						
-						if (fileInfo.length > 1) {
-							
-							text += ": " + sourceFile.getFile( true ).getName();
-						}
-					}
-				}catch (DownloadException e ){
-					
-					text = sourceFile.getFile().getName();
-				}
-			
-			}catch( Throwable e ){
-
-				text = "";
-			}
-		}else{
-			
-			text = job.getName();
-		}
-		
-		return( text );
-	}
-	
-	public Device
-	getDevice()
-	{
-		return( device );
-	}
-	
-	public TranscodeJobImpl
-	getJob()
-	{
-		if ( isComplete()){
-			
-			return( null );
-		}
-		
-		return( device.getManager().getTranscodeManager().getQueue().getJob( this ));
-	}
-	
-	public File 
-	getCacheFile() 
-	
-		throws TranscodeException
-	{
-		String	file_str = getString( KEY_FILE );
-		
-		if ( file_str == null ){
-			
-			throw( new TranscodeException( "File has been deleted" ));
-		}
-		
-		return(new File( file_str ));
-	}
-	
-	protected void
-	setCacheFile(
-		File		file )
-	{
-		setString( KEY_FILE, file.getAbsolutePath());
-	}
-	
-	protected void
-	checkDeleted()
-	
-		throws TranscodeException
-	{
-		if ( isDeleted()){
-			
-			throw( new TranscodeException( "File has been deleted" ));
-		}
-	}
-	
-	public DiskManagerFileInfo 
-	getSourceFile()  
-	
-		throws TranscodeException
-	{
-		checkDeleted();
-		
-			// options are either a download file or a link to an existing non-torrent based file
-		
-		String	hash = getString( KEY_SOURCE_FILE_HASH );
-		
-		if ( hash != null ){
-			
-			try{
-				Download download = PluginInitializer.getDefaultInterface().getDownloadManager().getDownload( Base32.decode(hash));
-				
-				if ( download != null ){
-					
-					int index = (int)getLong( KEY_SOURCE_FILE_INDEX );
-					
-					return( download.getDiskManagerFileInfo(index) );
-				}
-				
-			}catch( Throwable e ){
-				
-			}
-		}
-		
-		String	link = getString( KEY_SOURCE_FILE_LINK );
-			
-		if ( link != null ){
-				
-			File link_file = new File( link );
-				
-				// if we're not transcoding then always return the source even if doesn't exist
-			
-			if ( link_file.exists() || getBoolean( KEY_NO_XCODE )){
-		
-				return( new DiskManagerFileInfoFile( link_file ));
-			}
-		}
-		
-		// Debug.out( "Source file doesn't exist (hash=" + hash + ",link=" + link +"), returning cache file" );
-		
-		return( new DiskManagerFileInfoFile( getCacheFile()));
-	}
-	
-	protected void
-	setSourceFile(
-		DiskManagerFileInfo		file )
-	{
-		try{
-			Download download = file.getDownload();
-			
-			if ( download != null && download.getTorrent() != null ){
-				
-				setString( KEY_SOURCE_FILE_HASH, Base32.encode( download.getTorrent().getHash() ));
-				
-				setLong( KEY_SOURCE_FILE_INDEX, file.getIndex());
-			}
-		}catch( Throwable e ){
-		}
-		
-		setString( KEY_SOURCE_FILE_LINK, file.getFile().getAbsolutePath());
-	}
-	
-	public DiskManagerFileInfo 
-	getTargetFile() 
-	
-		throws TranscodeException
-	{
-			// options are either the cached file, if it exists, or failing that the
-			// source file if transcoding not required
-		
-		File	cache_file = getCacheFile();
-		
-		if ( cache_file.exists() && cache_file.length() > 0 ){
-		
-			return( new DiskManagerFileInfoFile( cache_file ));
-		}
-		
-		if ( getBoolean( KEY_NO_XCODE )){
-			
-			DiskManagerFileInfo res = getSourceFile();
-			
-			if ( res instanceof DiskManagerFileInfoFile ){
-				
-				return( res );
-				
-			}else{
-				
-				try{
-					return( new DiskManagerFileInfoDelegate( res ));
-					
-				}catch( Throwable e ){
-					
-					Debug.out( e );
-					
-					return( res );
-				}
-			}
-		}
-		
-			// Debug.out( "Target file for " + cache_file + " doesn't exist" );
-		
-		return( new DiskManagerFileInfoFile( cache_file ));
-	}
-	
-	protected void
-	setTranscodeRequired(
-		boolean	required )
-	
-		throws TranscodeException
-	{
-		setBoolean( KEY_NO_XCODE, !required );
-		
-		if ( !required ){
-			
-				// reset the file name as previous
-			
-			device.revertFileName( this );
-		}
-	}
-	
-	public boolean
-	getTranscodeRequired()
-	{
-		return( !getBoolean( KEY_NO_XCODE ));
-	}
-	
-	protected void
-	setComplete(
-		boolean b )
-	{
-		setBoolean( PT_COMPLETE, b );
-	}
-	
-	public boolean
-	isComplete()
-	{
-		return( getBoolean( PT_COMPLETE ));
-	}
-	
-	public boolean
-	isTemplate()
-	{
-		return( !getBoolean( KEY_FOR_JOB ));
-	}
-	
-	protected void
-	setCopiedToDevice(
-		boolean b )
-	{
-
-		setBoolean( PT_COPIED, b );
-		
-		setLong( PT_COPY_FAILED, 0 );
-
-		setCopyingToDevice(false);
-	}
-	
-	protected void
-	setCopyToDeviceFailed()
-	{
-		setLong( PT_COPY_FAILED, getLong( PT_COPY_FAILED ) + 1 );
-
-		setCopyingToDevice(false);
-	}
-	
-	public long
-	getCopyToDeviceFails()
-	{
-		return( getLong( PT_COPY_FAILED ));
-	}
-	
-	public boolean
-	isCopiedToDevice()
-	{
-		return( getBoolean( PT_COPIED ));
-	}
-	
-	public void 
-	retryCopyToDevice() 
-	{		
-		if ( isCopiedToDevice()){
-			
-			setCopiedToDevice( false );
-			
-		}else{
-			
-			setLong( PT_COPY_FAILED, 0 );
-		}
-	}
-	
-	protected void
-	setProfileName(
-		String s )
-	{
-		setString( KEY_PROFILE_NAME, s );
-	}
-	
-	public String
-	getProfileName()
-	{
-		String s = getString( KEY_PROFILE_NAME );
-		
-		if ( s == null ){
-			
-			s = "Unknown";
-		}
-		
-		return( s );
-	}
-	
-	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 )
-	
-		throws TranscodeException
-	{
-		checkDeleted();
-		
-		long	duration		= analysis.getLongProperty( TranscodeProviderAnalysis.PT_DURATION_MILLIS );
-		long	video_width		= analysis.getLongProperty( TranscodeProviderAnalysis.PT_VIDEO_WIDTH );
-		long	video_height	= analysis.getLongProperty( TranscodeProviderAnalysis.PT_VIDEO_HEIGHT );
-		long	xcode_size		= analysis.getLongProperty( TranscodeProviderAnalysis.PT_ESTIMATED_XCODE_SIZE );
-
-		if ( duration > 0 ){
-			
-			setLong( KEY_DURATION, duration );
-		}
-		
-		if ( video_width > 0 && video_height > 0 ){
-			
-			setLong( KEY_VIDEO_WIDTH, video_width );
-			
-			setLong( KEY_VIDEO_HEIGHT, video_height );
-		}
-		
-		if ( xcode_size > 0 ){
-			
-			setLong( KEY_XCODE_SIZE, xcode_size );
-		}
-	}
-	
-	protected void
-	setResolution(
-		int		video_width,
-		int		video_height )
-	{
-		if ( video_width > 0 && video_height > 0 ){
-			
-			setLong( KEY_VIDEO_WIDTH, video_width );
-			
-			setLong( KEY_VIDEO_HEIGHT, video_height );
-		}
-	}
-	
-	public long
-	getDurationMillis()
-	{
-		return( getLong( KEY_DURATION ));
-	}
-	
-	public long
-	getVideoWidth()
-	{
-		return( getLong( KEY_VIDEO_WIDTH ));
-	}
-	
-	public long
-	getVideoHeight()
-	{
-		return( getLong( KEY_VIDEO_HEIGHT ));
-	}
-	
-	public long
-	getEstimatedTranscodeSize()
-	{
-		return( getLong( KEY_XCODE_SIZE ));
-	}
-	
-	public String[] 
-	getCategories() 
-	{
-		String cats = getString( KEY_CATEGORIES );
-		
-		if ( cats == null || cats.length() == 0 ){
-			
-			return( new String[0] );
-		}
-		
-		return( Constants.PAT_SPLIT_COMMA.split(cats));
-	}
-	
-	public void
-	setCategories(
-		String[]		cats )
-	{
-		String[] existing = getCategories();
-		
-		if ( existing.length == 0 && existing.length == cats.length ){
-			
-			return;
-		}
-		
-		String	str = "";
-		
-		for ( String cat: cats ){
-			
-			cat = cat.replaceAll( ",", "" ).trim();
-			
-			if ( cat.length() > 0 ){
-				
-				str += (str.length()==0?"":",") + cat;
-			}
-		}
-		
-		setString( KEY_CATEGORIES, str );
-	}
-	
-	public String[] 
-	getTags(
-		boolean	localize ) 
-	{
-		String tags_str = getString( KEY_TAGS );
-		
-		if ( tags_str == null || tags_str.length() == 0 ){
-			
-			return( new String[0] );
-		}
-		
-		String[] tags = Constants.PAT_SPLIT_COMMA.split(tags_str);
-		
-		if ( localize ){
-			
-			List<String> derp = null;
-			
-			int	pos = 0;
-			
-			for ( String s: tags ){
-			
-				try{
-					Tag tag = tag_manager.lookupTagByUID( Long.parseLong( s ));
-					
-					if ( tag == null ){
-						
-						throw( new Exception()); // handled below
-					}
-					
-					String tag_name = tag.getTagName( true );
-			
-					if ( derp == null ){
-						
-						tags[pos++] = tag_name;
-						
-					}else{
-						
-						derp.add( tag_name );
-					}
-				}catch( Throwable e ){
-					
-					if ( derp == null ){
-						
-						derp = new ArrayList<String>();
-						
-						for ( int i=0;i<pos;i++){
-							
-							derp.add( tags[i]);
-						}
-					}
-				}
-			}
-			
-			if ( derp == null ){
-				
-				return( tags );
-			}
-			
-			return( derp.toArray( new String[ derp.size()]));
-			
-		}else{
-		
-			return( tags );
-		}
-	}
-	
-	public void
-	setTags(
-		String[]		tags )
-	{
-		String[] existing = getTags( false );
-		
-		if ( existing.length == 0 && existing.length == tags.length ){
-			
-			return;
-		}
-		
-		String	str = "";
-		
-		for ( String tag: tags ){
-			
-			tag = tag.replaceAll( ",", "" ).trim();
-			
-			if ( tag.length() > 0 ){
-				
-				str += (str.length()==0?"":",") + tag;
-			}
-		}
-		
-		setString( KEY_TAGS, str );
-	}
-	
-	public long
-	getCreationDateMillis()
-	{
-		return( getLong( KEY_DATE ));
-	}
-	
-	public File
-	getCacheFileIfExists()
-	{
-		try{
-			return( getCacheFile());
-			
-		}catch( Throwable e ){
-			
-			return( null );
-		}
-	}
-	
-	public URL
-	getStreamURL()
-	{
-		return( device.getStreamURL( this, null ));
-	}
-	
-	public URL
-	getStreamURL(
-		String	host )
-	{
-		return( device.getStreamURL( this, host ));
-	}
-	
-	public String
-	getMimeType()
-	{
-		return( device.getMimeType( this ));
-	}
-	
-	public void
-	delete(
-		boolean	delete_contents )
-	
-		throws TranscodeException 
-	{
-		device.deleteFile( this, delete_contents, true );
-	}
-	
-	protected void
-	deleteCacheFile()
-	
-		throws TranscodeException 
-	{
-		device.deleteFile( this, true, false );
-	}
-	
-	public boolean
-	isDeleted()
-	{
-		return( getMap() == null );
-	}
-	
-	private Map<String,?>
-	getMap()
-	{
-		return( getMap( false ));
-	}
-	
-	private Map<String,?>
-	getMap(
-		boolean	create )
-	{		
-		synchronized( files_map ){
-	
-			Map<String,?> map = files_map.get( key );
-			
-			if ( map == null && create ){
-				
-				map = new HashMap<String, Object>();
-				
-				files_map.put( key, map );
-			}
-			
-			return( map );
-		}
-	}
-	
-	protected boolean
-	getBoolean(
-		String		key )
-	{
-		return( getLong(key)==1);
-	}
-	
-	protected void
-	setBoolean(
-		String		key,
-		boolean		b )
-	{
-		setLong(key,b?1:0);
-	}
-	
-	protected long
-	getLong(
-		String		key )
-	{
-		try{
-			Map<String,?>	map = getMap();
-			
-			return(ImportExportUtils.importLong( map, key, 0 ));
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			return( 0 );
-		}
-	}
-	
-	protected void
-	setLong(
-		String		key,
-		long		value )
-	{	
-		if ( getLong( key ) == value ){
-			
-			return;
-		}
-		
-		synchronized( files_map ){
-
-			try{
-				Map<String,?>	map = getMap();
-
-				ImportExportUtils.exportLong( map, key, value);
-								
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}
-		
-		device.fileDirty( this, TranscodeTargetListener.CT_PROPERTY, key );
-	}
-	
-	protected String
-	getString(
-		String		key )
-	{
-		try{
-			Map<String,?>	map = getMap();
-
-			return(ImportExportUtils.importString( map, key ));
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			return( "" );
-		}
-	}
-	
-	protected void
-	setString(
-		String		key,
-		String		value )
-	{
-		String existing = getString( key );
-		
-		if ( existing == null && value == null ){
-			
-			return;
-			
-		}else if ( existing == null || value == null ){
-			
-		}else if ( existing.equals( value )){
-			
-			return;
-		}
-		
-		synchronized( files_map ){
-			
-			Map<String,?>	map = getMap();
-			
-			try{
-				ImportExportUtils.exportString( map, key, value );
-								
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}
-		
-		device.fileDirty( this, TranscodeTargetListener.CT_PROPERTY, key );
-	}
-	
-	public void
-	setTransientProperty(
-		Object		key2,
-		Object		value )
-	{
-		device.setTransientProperty( key, key2, value );
-	}
-			
-	public Object
-	getTransientProperty(
-		Object		key2 )
-	{
-		return( device.getTransientProperty( key, key2 ));
-	}
-	
-	public boolean
-	equals(
-		Object	other )
-	{
-		if ( other instanceof TranscodeFileImpl ){
-			
-			return( key.equals(((TranscodeFileImpl)other).key));
-		}
-		
-		return( false );
-	}
-	
-	public int
-	hashCode()
-	{
-		return( key.hashCode());
-	}
-	
-	protected String
-	getString()
-	{
-		Map<String,?> map = getMap();
-		
-		if ( map == null ){
-			
-			return( key + ": deleted" );
-			
-		}else{
-			
-			return( key + ": " + map );
-		}
-	}
-
-	public void 
-	setCopyingToDevice(
-			boolean b)
-	{
-		setBoolean(KEY_COPYING, b);
-	}
-	
-	public boolean
-	isCopyingToDevice()
-	{
-		return getBoolean(KEY_COPYING);
-	}
-}
\ No newline at end of file
+/*
+ * Created on Feb 18, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadException;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+
+import com.aelitis.azureus.core.devices.Device;
+import com.aelitis.azureus.core.devices.TranscodeException;
+import com.aelitis.azureus.core.devices.TranscodeFile;
+import com.aelitis.azureus.core.devices.TranscodeJob;
+import com.aelitis.azureus.core.devices.TranscodeProviderAnalysis;
+import com.aelitis.azureus.core.devices.TranscodeTargetListener;
+import com.aelitis.azureus.core.download.DiskManagerFileInfoDelegate;
+import com.aelitis.azureus.core.download.DiskManagerFileInfoFile;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManager;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.util.ImportExportUtils;
+
+class
+TranscodeFileImpl
+	implements TranscodeFile
+{	
+	protected static final String		KEY_FILE			= "file";
+	
+	private static final TagManager	tag_manager = TagManagerFactory.getTagManager();
+	
+	private static final String			KEY_PROFILE_NAME		= "pn";
+	private static final String			KEY_SOURCE_FILE_HASH	= "sf_hash";
+	private static final String			KEY_SOURCE_FILE_INDEX	= "sf_index";
+	private static final String			KEY_SOURCE_FILE_LINK	= "sf_link";
+	private static final String			KEY_NO_XCODE			= "no_xcode";
+	private static final String			KEY_FOR_JOB				= "fj";
+
+	private static final String			KEY_DURATION			= "at_dur";
+	private static final String			KEY_VIDEO_WIDTH			= "at_vw";
+	private static final String			KEY_VIDEO_HEIGHT		= "at_vh";
+	private static final String			KEY_XCODE_SIZE			= "at_xs";
+	private static final String			KEY_DATE				= "at_dt";
+	private static final String			KEY_CATEGORIES			= PT_CATEGORY;
+	private static final String			KEY_TAGS				= PT_TAGS;
+	private static final String			KEY_COPY_TO_OVERRIDE	= "ct_over";
+	private static final String			KEY_COPYING	= "copying";
+
+	private DeviceImpl					device;
+	private String						key;
+	private Map<String,Map<String,?>>	files_map;
+
+		// don't store any local state here, store it in the map as this is just a wrapper
+		// for the underlying map and there can be multiple such wrappers concurrent
+	
+	protected 
+	TranscodeFileImpl(
+		DeviceImpl					_device,
+		String						_key,
+		String						_profile_name,
+		Map<String,Map<String,?>>	_files_map,
+		File						_file,
+		boolean						_for_job )
+	{
+		device		= _device;
+		key			= _key;
+		files_map	= _files_map;
+
+		getMap( true );
+		
+		setString( KEY_FILE, _file.getAbsolutePath());
+		
+		setString( KEY_PROFILE_NAME, _profile_name );
+		
+		setLong( KEY_DATE, SystemTime.getCurrentTime());
+		
+		setBoolean( KEY_FOR_JOB, _for_job );
+		
+		setBoolean( KEY_COPYING, false );
+	}
+	
+	protected
+	TranscodeFileImpl(
+		DeviceImpl					_device,
+		String						_key,
+		Map<String,Map<String,?>>	_map )
+	
+		throws IOException
+	{
+		device			= _device;
+		key				= _key;
+		files_map		= _map;
+		
+		Map<String,?> map = getMap();
+		
+		if ( map == null || !map.containsKey( KEY_FILE )){
+			
+			throw( new IOException( "File has been deleted" ));
+		}
+	}
+	
+	
+	protected String
+	getKey()
+	{
+		return( key );
+	}
+	
+	public String
+	getName()
+	{
+		TranscodeJob job = getJob();
+
+		String text;
+		
+		if ( job == null){
+			
+			try{
+				DiskManagerFileInfo sourceFile = getSourceFile();
+				
+				try {
+					Download download = sourceFile.getDownload();
+					
+					if ( download == null ){
+						
+						text = sourceFile.getFile().getName();
+						
+					}else{
+						
+						text = download.getName();
+						
+						DiskManagerFileInfo[] fileInfo = download.getDiskManagerFileInfo();
+						
+						if (fileInfo.length > 1) {
+							
+							text += ": " + sourceFile.getFile( true ).getName();
+						}
+					}
+				}catch (DownloadException e ){
+					
+					text = sourceFile.getFile().getName();
+				}
+			
+			}catch( Throwable e ){
+
+				text = "";
+			}
+		}else{
+			
+			text = job.getName();
+		}
+		
+		return( text );
+	}
+	
+	public Device
+	getDevice()
+	{
+		return( device );
+	}
+	
+	public TranscodeJobImpl
+	getJob()
+	{
+		if ( isComplete()){
+			
+			return( null );
+		}
+		
+		return( device.getManager().getTranscodeManager().getQueue().getJob( this ));
+	}
+	
+	public File 
+	getCacheFile() 
+	
+		throws TranscodeException
+	{
+		String	file_str = getString( KEY_FILE );
+		
+		if ( file_str == null ){
+			
+			throw( new TranscodeException( "File has been deleted" ));
+		}
+		
+		return(new File( file_str ));
+	}
+	
+	protected void
+	setCacheFile(
+		File		file )
+	{
+		setString( KEY_FILE, file.getAbsolutePath());
+	}
+	
+	protected void
+	checkDeleted()
+	
+		throws TranscodeException
+	{
+		if ( isDeleted()){
+			
+			throw( new TranscodeException( "File has been deleted" ));
+		}
+	}
+	
+	public DiskManagerFileInfo 
+	getSourceFile()  
+	
+		throws TranscodeException
+	{
+		checkDeleted();
+		
+			// options are either a download file or a link to an existing non-torrent based file
+		
+		String	hash = getString( KEY_SOURCE_FILE_HASH );
+		
+		if ( hash != null ){
+			
+			try{
+				Download download = PluginInitializer.getDefaultInterface().getDownloadManager().getDownload( Base32.decode(hash));
+				
+				if ( download != null ){
+					
+					int index = (int)getLong( KEY_SOURCE_FILE_INDEX );
+					
+					return( download.getDiskManagerFileInfo(index) );
+				}
+				
+			}catch( Throwable e ){
+				
+			}
+		}
+		
+		String	link = getString( KEY_SOURCE_FILE_LINK );
+			
+		if ( link != null ){
+				
+			File link_file = new File( link );
+				
+				// if we're not transcoding then always return the source even if doesn't exist
+			
+			if ( link_file.exists() || getBoolean( KEY_NO_XCODE )){
+		
+				return( new DiskManagerFileInfoFile( link_file ));
+			}
+		}
+		
+		// Debug.out( "Source file doesn't exist (hash=" + hash + ",link=" + link +"), returning cache file" );
+		
+		return( new DiskManagerFileInfoFile( getCacheFile()));
+	}
+	
+	protected void
+	setSourceFile(
+		DiskManagerFileInfo		file )
+	{
+		try{
+			Download download = file.getDownload();
+			
+			if ( download != null && download.getTorrent() != null ){
+				
+				setString( KEY_SOURCE_FILE_HASH, Base32.encode( download.getTorrent().getHash() ));
+				
+				setLong( KEY_SOURCE_FILE_INDEX, file.getIndex());
+			}
+		}catch( Throwable e ){
+		}
+		
+		setString( KEY_SOURCE_FILE_LINK, file.getFile().getAbsolutePath());
+	}
+	
+	public DiskManagerFileInfo 
+	getTargetFile() 
+	
+		throws TranscodeException
+	{
+			// options are either the cached file, if it exists, or failing that the
+			// source file if transcoding not required
+		
+		File	cache_file = getCacheFile();
+		
+		if ( cache_file.exists() && cache_file.length() > 0 ){
+		
+			return( new DiskManagerFileInfoFile( cache_file ));
+		}
+		
+		if ( getBoolean( KEY_NO_XCODE )){
+			
+			DiskManagerFileInfo res = getSourceFile();
+			
+			if ( res instanceof DiskManagerFileInfoFile ){
+				
+				return( res );
+				
+			}else{
+				
+				try{
+					return( new DiskManagerFileInfoDelegate( res ));
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+					
+					return( res );
+				}
+			}
+		}
+		
+			// Debug.out( "Target file for " + cache_file + " doesn't exist" );
+		
+		return( new DiskManagerFileInfoFile( cache_file ));
+	}
+	
+	protected void
+	setTranscodeRequired(
+		boolean	required )
+	
+		throws TranscodeException
+	{
+		setBoolean( KEY_NO_XCODE, !required );
+		
+		if ( !required ){
+			
+				// reset the file name as previous
+			
+			device.revertFileName( this );
+		}
+	}
+	
+	public boolean
+	getTranscodeRequired()
+	{
+		return( !getBoolean( KEY_NO_XCODE ));
+	}
+	
+	protected void
+	setComplete(
+		boolean b )
+	{
+		setBoolean( PT_COMPLETE, b );
+	}
+	
+	public boolean
+	isComplete()
+	{
+		return( getBoolean( PT_COMPLETE ));
+	}
+	
+	public boolean
+	isTemplate()
+	{
+		return( !getBoolean( KEY_FOR_JOB ));
+	}
+	
+	protected void
+	setCopiedToDevice(
+		boolean b )
+	{
+
+		setBoolean( PT_COPIED, b );
+		
+		setLong( PT_COPY_FAILED, 0 );
+
+		setCopyingToDevice(false);
+	}
+	
+	protected void
+	setCopyToDeviceFailed()
+	{
+		setLong( PT_COPY_FAILED, getLong( PT_COPY_FAILED ) + 1 );
+
+		setCopyingToDevice(false);
+	}
+	
+	public long
+	getCopyToDeviceFails()
+	{
+		return( getLong( PT_COPY_FAILED ));
+	}
+	
+	public boolean
+	isCopiedToDevice()
+	{
+		return( getBoolean( PT_COPIED ));
+	}
+	
+	public void 
+	retryCopyToDevice() 
+	{		
+		if ( isCopiedToDevice()){
+			
+			setCopiedToDevice( false );
+			
+		}else{
+			
+			setLong( PT_COPY_FAILED, 0 );
+		}
+	}
+	
+	protected void
+	setProfileName(
+		String s )
+	{
+		setString( KEY_PROFILE_NAME, s );
+	}
+	
+	public String
+	getProfileName()
+	{
+		String s = getString( KEY_PROFILE_NAME );
+		
+		if ( s == null ){
+			
+			s = "Unknown";
+		}
+		
+		return( s );
+	}
+	
+	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 )
+	
+		throws TranscodeException
+	{
+		checkDeleted();
+		
+		long	duration		= analysis.getLongProperty( TranscodeProviderAnalysis.PT_DURATION_MILLIS );
+		long	video_width		= analysis.getLongProperty( TranscodeProviderAnalysis.PT_VIDEO_WIDTH );
+		long	video_height	= analysis.getLongProperty( TranscodeProviderAnalysis.PT_VIDEO_HEIGHT );
+		long	xcode_size		= analysis.getLongProperty( TranscodeProviderAnalysis.PT_ESTIMATED_XCODE_SIZE );
+
+		if ( duration > 0 ){
+			
+			setLong( KEY_DURATION, duration );
+		}
+		
+		if ( video_width > 0 && video_height > 0 ){
+			
+			setLong( KEY_VIDEO_WIDTH, video_width );
+			
+			setLong( KEY_VIDEO_HEIGHT, video_height );
+		}
+		
+		if ( xcode_size > 0 ){
+			
+			setLong( KEY_XCODE_SIZE, xcode_size );
+		}
+	}
+	
+	protected void
+	setResolution(
+		int		video_width,
+		int		video_height )
+	{
+		if ( video_width > 0 && video_height > 0 ){
+			
+			setLong( KEY_VIDEO_WIDTH, video_width );
+			
+			setLong( KEY_VIDEO_HEIGHT, video_height );
+		}
+	}
+	
+	public long
+	getDurationMillis()
+	{
+		return( getLong( KEY_DURATION ));
+	}
+	
+	public long
+	getVideoWidth()
+	{
+		return( getLong( KEY_VIDEO_WIDTH ));
+	}
+	
+	public long
+	getVideoHeight()
+	{
+		return( getLong( KEY_VIDEO_HEIGHT ));
+	}
+	
+	public long
+	getEstimatedTranscodeSize()
+	{
+		return( getLong( KEY_XCODE_SIZE ));
+	}
+	
+	public String[] 
+	getCategories() 
+	{
+		String cats = getString( KEY_CATEGORIES );
+		
+		if ( cats == null || cats.length() == 0 ){
+			
+			return( new String[0] );
+		}
+		
+		return( Constants.PAT_SPLIT_COMMA.split(cats));
+	}
+	
+	public void
+	setCategories(
+		String[]		cats )
+	{
+		String[] existing = getCategories();
+		
+		if ( existing.length == 0 && existing.length == cats.length ){
+			
+			return;
+		}
+		
+		String	str = "";
+		
+		for ( String cat: cats ){
+			
+			cat = cat.replaceAll( ",", "" ).trim();
+			
+			if ( cat.length() > 0 ){
+				
+				str += (str.length()==0?"":",") + cat;
+			}
+		}
+		
+		setString( KEY_CATEGORIES, str );
+	}
+	
+	public String[] 
+	getTags(
+		boolean	localize ) 
+	{
+		String tags_str = getString( KEY_TAGS );
+		
+		if ( tags_str == null || tags_str.length() == 0 ){
+			
+			return( new String[0] );
+		}
+		
+		String[] tags = Constants.PAT_SPLIT_COMMA.split(tags_str);
+		
+		if ( localize ){
+			
+			List<String> derp = null;
+			
+			int	pos = 0;
+			
+			for ( String s: tags ){
+			
+				try{
+					Tag tag = tag_manager.lookupTagByUID( Long.parseLong( s ));
+					
+					if ( tag == null ){
+						
+						throw( new Exception()); // handled below
+					}
+					
+					String tag_name = tag.getTagName( true );
+			
+					if ( derp == null ){
+						
+						tags[pos++] = tag_name;
+						
+					}else{
+						
+						derp.add( tag_name );
+					}
+				}catch( Throwable e ){
+					
+					if ( derp == null ){
+						
+						derp = new ArrayList<String>();
+						
+						for ( int i=0;i<pos;i++){
+							
+							derp.add( tags[i]);
+						}
+					}
+				}
+			}
+			
+			if ( derp == null ){
+				
+				return( tags );
+			}
+			
+			return( derp.toArray( new String[ derp.size()]));
+			
+		}else{
+		
+			return( tags );
+		}
+	}
+	
+	public void
+	setTags(
+		String[]		tags )
+	{
+		String[] existing = getTags( false );
+		
+		if ( existing.length == 0 && existing.length == tags.length ){
+			
+			return;
+		}
+		
+		String	str = "";
+		
+		for ( String tag: tags ){
+			
+			tag = tag.replaceAll( ",", "" ).trim();
+			
+			if ( tag.length() > 0 ){
+				
+				str += (str.length()==0?"":",") + tag;
+			}
+		}
+		
+		setString( KEY_TAGS, str );
+	}
+	
+	public long
+	getCreationDateMillis()
+	{
+		return( getLong( KEY_DATE ));
+	}
+	
+	public File
+	getCacheFileIfExists()
+	{
+		try{
+			return( getCacheFile());
+			
+		}catch( Throwable e ){
+			
+			return( null );
+		}
+	}
+	
+	public URL
+	getStreamURL()
+	{
+		return( device.getStreamURL( this, null ));
+	}
+	
+	public URL
+	getStreamURL(
+		String	host )
+	{
+		return( device.getStreamURL( this, host ));
+	}
+	
+	public String
+	getMimeType()
+	{
+		return( device.getMimeType( this ));
+	}
+	
+	public void
+	delete(
+		boolean	delete_contents )
+	
+		throws TranscodeException 
+	{
+		device.deleteFile( this, delete_contents, true );
+	}
+	
+	protected void
+	deleteCacheFile()
+	
+		throws TranscodeException 
+	{
+		device.deleteFile( this, true, false );
+	}
+	
+	public boolean
+	isDeleted()
+	{
+		return( getMap() == null );
+	}
+	
+	private Map<String,?>
+	getMap()
+	{
+		return( getMap( false ));
+	}
+	
+	private Map<String,?>
+	getMap(
+		boolean	create )
+	{		
+		synchronized( files_map ){
+	
+			Map<String,?> map = files_map.get( key );
+			
+			if ( map == null && create ){
+				
+				map = new HashMap<String, Object>();
+				
+				files_map.put( key, map );
+			}
+			
+			return( map );
+		}
+	}
+	
+	protected boolean
+	getBoolean(
+		String		key )
+	{
+		return( getLong(key)==1);
+	}
+	
+	protected void
+	setBoolean(
+		String		key,
+		boolean		b )
+	{
+		setLong(key,b?1:0);
+	}
+	
+	protected long
+	getLong(
+		String		key )
+	{
+		try{
+			Map<String,?>	map = getMap();
+			
+			return(ImportExportUtils.importLong( map, key, 0 ));
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( 0 );
+		}
+	}
+	
+	protected void
+	setLong(
+		String		key,
+		long		value )
+	{	
+		if ( getLong( key ) == value ){
+			
+			return;
+		}
+		
+		synchronized( files_map ){
+
+			try{
+				Map<String,?>	map = getMap();
+
+				ImportExportUtils.exportLong( map, key, value);
+								
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+		
+		device.fileDirty( this, TranscodeTargetListener.CT_PROPERTY, key );
+	}
+	
+	protected String
+	getString(
+		String		key )
+	{
+		try{
+			Map<String,?>	map = getMap();
+
+			return(ImportExportUtils.importString( map, key ));
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( "" );
+		}
+	}
+	
+	protected void
+	setString(
+		String		key,
+		String		value )
+	{
+		String existing = getString( key );
+		
+		if ( existing == null && value == null ){
+			
+			return;
+			
+		}else if ( existing == null || value == null ){
+			
+		}else if ( existing.equals( value )){
+			
+			return;
+		}
+		
+		synchronized( files_map ){
+			
+			Map<String,?>	map = getMap();
+			
+			try{
+				ImportExportUtils.exportString( map, key, value );
+								
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+		
+		device.fileDirty( this, TranscodeTargetListener.CT_PROPERTY, key );
+	}
+	
+	public void
+	setTransientProperty(
+		Object		key2,
+		Object		value )
+	{
+		device.setTransientProperty( key, key2, value );
+	}
+			
+	public Object
+	getTransientProperty(
+		Object		key2 )
+	{
+		return( device.getTransientProperty( key, key2 ));
+	}
+	
+	public boolean
+	equals(
+		Object	other )
+	{
+		if ( other instanceof TranscodeFileImpl ){
+			
+			return( key.equals(((TranscodeFileImpl)other).key));
+		}
+		
+		return( false );
+	}
+	
+	public int
+	hashCode()
+	{
+		return( key.hashCode());
+	}
+	
+	protected String
+	getString()
+	{
+		Map<String,?> map = getMap();
+		
+		if ( map == null ){
+			
+			return( key + ": deleted" );
+			
+		}else{
+			
+			return( key + ": " + map );
+		}
+	}
+
+	public void 
+	setCopyingToDevice(
+			boolean b)
+	{
+		setBoolean(KEY_COPYING, b);
+	}
+	
+	public boolean
+	isCopyingToDevice()
+	{
+		return getBoolean(KEY_COPYING);
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeJobImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeJobImpl.java
index 083a3f6..8bd5e22 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeJobImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeJobImpl.java
@@ -1,945 +1,944 @@
-/*
- * Created on Feb 6, 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.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.*;
-
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadException;
-import org.gudy.azureus2.plugins.download.DownloadRemovalVetoException;
-import org.gudy.azureus2.plugins.download.DownloadWillBeRemovedListener;
-import org.gudy.azureus2.plugins.peers.PeerManager;
-import org.gudy.azureus2.plugins.peers.PeerManagerStats;
-import org.gudy.azureus2.plugins.torrent.Torrent;
-import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
-
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.devices.TranscodeAnalysisListener;
-import com.aelitis.azureus.core.devices.TranscodeJob;
-import com.aelitis.azureus.core.devices.TranscodeProfile;
-import com.aelitis.azureus.core.devices.TranscodeException;
-import com.aelitis.azureus.core.devices.TranscodeActionVetoException;
-import com.aelitis.azureus.core.devices.TranscodeTarget;
-import com.aelitis.azureus.core.download.DiskManagerFileInfoFile;
-import com.aelitis.azureus.core.download.DiskManagerFileInfoURL;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.util.ImportExportUtils;
-
-public class 
-TranscodeJobImpl 
-	implements TranscodeJob, DownloadWillBeRemovedListener
-{
-	private static final int TRANSCODE_OK_DL_PERCENT	= 90;
-	
-	private TranscodeQueueImpl		queue;
-	private TranscodeTarget			target;
-	private TranscodeProfile		profile;
-	private DiskManagerFileInfo		file;
-	private TranscodeFileImpl		transcode_file;
-	
-	private boolean					is_stream;
-	private volatile InputStream	stream;
-	private AESemaphore				stream_sem = new AESemaphore( "TJ:s" );
-	
-	private int						transcode_requirement;
-	
-	private int						state 				= ST_QUEUED;
-	private int						percent_complete	= 0;
-	private int						eta					= Integer.MAX_VALUE;
-	private String					error;
-	private long					started_on;
-	private long					paused_on;
-	private long					process_time;
-	
-	private boolean					use_direct_input;
-	private boolean					prefer_direct_input;
-	
-	private boolean					auto_retry_enabled	= true;
-	private boolean					auto_retry;
-	private int						auto_retry_count;
-	
-	private Download				download;
-	private volatile boolean		download_ok;
-	
-	protected
-	TranscodeJobImpl(
-		TranscodeQueueImpl		_queue,
-		TranscodeTarget			_target,
-		TranscodeProfile		_profile,
-		DiskManagerFileInfo		_file,
-		boolean					_add_stopped,
-		int						_transcode_requirement,
-		boolean					_is_stream )
-	
-		throws TranscodeException
-	{
-		queue					= _queue;
-		target					= _target;
-		profile					= _profile;
-		file					= _file;
-		transcode_requirement	= _transcode_requirement;
-		is_stream				= _is_stream;
-		
-		if ( _add_stopped ){
-			
-			state = ST_STOPPED;
-		}
-		
-		init();
-	}
-	
-	protected
-	TranscodeJobImpl(
-		TranscodeQueueImpl		_queue,
-		Map<String,Object>		map )
-	
-		throws IOException, TranscodeException
-	{
-		queue	= _queue;
-		
-		state = ImportExportUtils.importInt( map, "state" );
-		
-		if ( state == ST_RUNNING ){
-			
-			state = ST_QUEUED;
-		}
-		
-		error = ImportExportUtils.importString( map, "error", null );
-		
-		String	target_id = ImportExportUtils.importString( map, "target" );
-		
-		target = queue.lookupTarget( target_id );
-		
-		String	profile_id = ImportExportUtils.importString( map, "profile" );
-		
-		profile = queue.lookupProfile( profile_id );
-		
-		String file_str = ImportExportUtils.importString( map, "file" );
-		
-		if ( file_str == null ){
-			
-			byte[] dl_hash = ByteFormatter.decodeString( ImportExportUtils.importString( map, "dl_hash" ));
-			
-			int file_index = ImportExportUtils.importInt( map, "file_index" );
-			
-			file = queue.lookupFile( dl_hash, file_index );
-		}else{
-		
-			file = new DiskManagerFileInfoFile( new File( file_str ));
-		}
-		
-		transcode_requirement	= ImportExportUtils.importInt( map, "trans_req", TranscodeTarget.TRANSCODE_UNKNOWN );
-		
-		auto_retry_enabled = ImportExportUtils.importBoolean( map, "ar_enable", true );
-		
-		prefer_direct_input = ImportExportUtils.importBoolean( map, "pdi", false );
-		
-		init();
-	}
-
-	protected Map<String,Object>
-	toMap()
-	
-		throws IOException
-	{
-		try{
-			Map<String,Object> map = new HashMap<String, Object>();
-			
-			synchronized( this ){
-				
-				ImportExportUtils.exportInt( map, "state", state );
-				ImportExportUtils.exportString( map, "error", error );
-				
-				ImportExportUtils.exportString( map, "target", target.getID());
-				
-				ImportExportUtils.exportString( map, "profile", profile.getUID());
-				
-				try{
-					Download download = file.getDownload();
-					
-					ImportExportUtils.exportString( map, "dl_hash", ByteFormatter.encodeString( download.getTorrent().getHash()));
-	
-					ImportExportUtils.exportInt( map, "file_index", file.getIndex());
-	
-				}catch( DownloadException e ){
-					
-						// external file
-					
-					ImportExportUtils.exportString( map, "file", file.getFile().getAbsolutePath());
-				}
-			
-				ImportExportUtils.exportInt( map, "trans_req", transcode_requirement );
-					
-				ImportExportUtils.exportBoolean( map, "ar_enable", auto_retry_enabled );
-				
-				ImportExportUtils.exportBoolean( map, "pdi", prefer_direct_input );
-			}
-			
-			return( map );
-			
-		}catch( Throwable e ){
-			
-			throw( new IOException( "Export failed: " + Debug.getNestedExceptionMessage(e)));
-		}
-	}
-	
-	protected void
-	init()
-	
-		throws TranscodeException
-	{
-		transcode_file = ((DeviceImpl)target.getDevice()).allocateFile( profile, getTranscodeRequirement() == TranscodeTarget.TRANSCODE_NEVER, file, true );
-		
-		try{
-			download = file.getDownload();
-			
-			if ( download != null ){
-				
-				download.addDownloadWillBeRemovedListener( this );
-			}
-		}catch( Throwable e ){
-		}
-		
-		updateStatus( false );
-	}
-	
-	protected void
-	updateStatus()
-	{
-		updateStatus( true );
-	}
-	
-	protected void
-	updateStatus(
-		boolean	report_change )
-	{
-		synchronized( this ){
-			
-			if ( download_ok ){
-				
-				return;
-			}
-			
-			long	downloaded 	= file.getDownloaded();
-			long	length		= file.getLength();
-			
-			if ( download == null || downloaded == length ){
-				
-				download_ok = true;
-				
-			}else{
-
-				Torrent torrent = download.getTorrent();
-						
-				if ( 	PlatformTorrentUtils.isContent( torrent, false ) || 
-						PlatformTorrentUtils.getContentNetworkID( PluginCoreUtils.unwrap( torrent )) == ContentNetwork.CONTENT_NETWORK_VHDNL ){
-					
-					download_ok = true;
-					
-				}else{
-					
-					int	percent_done = (int)( 100*downloaded/length );
-					
-					if ( percent_done >= TRANSCODE_OK_DL_PERCENT ){
-						
-						download_ok = true;
-						
-					}else{
-						
-						PeerManager pm = download.getPeerManager();
-						
-						if ( pm != null ){
-							
-							PeerManagerStats stats = pm.getStats();
-							
-							int connected_seeds 	= stats.getConnectedSeeds();
-							int connected_leechers	= stats.getConnectedLeechers();
-							
-							
-							if ( connected_seeds > 10 && connected_seeds > connected_leechers ){
-								
-								download_ok = true;
-							}
-						}else{
-							
-							int state = download.getState();
-							
-							if ( state == Download.ST_STOPPED ){
-								
-								try{
-									download.restart();
-									
-								}catch( Throwable e ){
-									
-									Debug.out( e );
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-		
-		if ( download_ok && report_change ){
-			
-			queue.jobChanged( this, true, false );
-		}
-	}
-	
-	public long
-	getDownloadETA()
-	{
-		if ( download_ok ){
-			
-			return( 0 );
-		}
-		
-		if ( file.getDownloaded() == file.getLength()){
-			
-			return( 0 );
-		}
-
-		if ( file.isSkipped() || file.isDeleted()){
-				
-			return( Long.MAX_VALUE );
-		}
-			
-		try{
-			long	eta = PluginCoreUtils.unwrap( download ).getStats().getSmoothedETA();
-			
-			if ( eta < 0 ){
-				
-				return( Long.MAX_VALUE );
-			}
-			
-			long adjusted = eta*100/TRANSCODE_OK_DL_PERCENT;
-			
-			if ( adjusted == 0 ){
-				
-				adjusted = 1;
-			}
-			
-			return( adjusted );
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			return( Long.MAX_VALUE );
-		}
-	}
-	
-	protected boolean
-	canUseDirectInput()
-	{
-		if ( file instanceof DiskManagerFileInfoURL ){
-			
-			return( true );
-		}
-		
-		long	length = file.getLength();
-
-		return( file.getDownloaded() == length &&
-				file.getFile().length() == length );
-	}
-	
-	protected boolean
-	useDirectInput()
-	{
-		synchronized( this ){
-
-			return( use_direct_input || 
-					( getPreferDirectInput() && canUseDirectInput()));
-		}
-	}
-	
-	protected void
-	setUseDirectInput()
-	{
-		synchronized( this ){
-
-			use_direct_input = true;
-		}
-	}
-	
-	public void
-	setPreferDirectInput(
-		boolean		prefer )
-	{
-		synchronized( this ){
-		
-			prefer_direct_input = prefer;
-		}
-	}
-	
-	public boolean
-	getPreferDirectInput()
-	{
-		synchronized( this ){
-		
-			return( prefer_direct_input );
-		}
-	}
-	
-	protected void
-	setAutoRetry(
-		boolean		_auto_retry )
-	{
-		synchronized( this ){
-
-			if ( _auto_retry ){
-				
-				auto_retry 	= true;
-				
-				auto_retry_count++;
-				
-			}else{
-				
-				auto_retry = false;
-			}
-		}
-	}
-	
-	protected boolean
-	isAutoRetry()
-	{
-		synchronized( this ){
-			
-			return( auto_retry );
-		}
-	}
-	
-	protected int
-	getAutoRetryCount()
-	{
-		synchronized( this ){
-
-			return( auto_retry_count );
-		}
-	}
-	
-	public void
-	setEnableAutoRetry(
-		boolean		enabled )
-	{
-		auto_retry_enabled = enabled;
-	}
-	
-	public boolean 
-	getEnableAutoRetry() 
-	{
-		return( auto_retry_enabled );
-	}
-	
-	protected boolean
-	isStream()
-	{
-		return( is_stream );
-	}
-	
-	protected void
-	setStream(
-		InputStream		_stream )
-	{
-		stream		= _stream;
-		
-		stream_sem.releaseForever();
-	}
-	
-	protected InputStream
-	getStream(
-		int		wait_for_millis )
-	
-		throws IOException
-	{
-		if ( state == ST_FAILED ){
-			
-			throw( new IOException( "Transcode job failed: " + error ));
-			
-		}else if ( state == ST_CANCELLED ){
-			
-			throw( new IOException( "Transcode job cancelled" ));
-
-		}else if ( state == ST_REMOVED ){
-			
-			throw( new IOException( "Transcode job removed" ));
-		}
-		
-		stream_sem.reserve( wait_for_millis );
-		
-		return( stream );
-	}
-	
-	public void 
-	downloadWillBeRemoved(
-		Download 	download )
-
-		throws DownloadRemovalVetoException
-	{
-		if ( queue.getIndex( this ) == 0 || state == ST_COMPLETE ){
-			
-			download.removeDownloadWillBeRemovedListener( this );
-			
-		}else{
-			
-			throw( new DownloadRemovalVetoException( 
-					MessageText.getString( "devices.xcode.remove.vetoed",
-						new String[]{ download.getName()})));
-		}
-	}
-	
-	public String
-	getName()
-	{
-		if ( download != null ){
-		
-			if ( download.getDiskManagerFileInfo().length == 1 ){
-				
-				return( download.getName());
-			}
-			
-			return( download.getName() + ": " + file.getFile().getName());
-			
-		}else{
-			
-			return( file.getFile().getName());
-		}
-	}
-	
-	protected void
-	reset()
-	{
-		state 				= ST_QUEUED;
-		error 				= null;
-		percent_complete	= 0;
-		eta					= Integer.MAX_VALUE;
-	}
-	
-	protected void
-	starts()
-	{
-		synchronized( this ){
-		
-			started_on 	= SystemTime.getMonotonousTime();
-			paused_on	= 0;
-
-				// this is for an Azureus restart with a paused job - we don't want to change the
-				// state as we want it to re-pause...
-			
-			if ( state != ST_PAUSED ){
-			
-				state = ST_RUNNING;				
-			}
-		}
-		
-		queue.jobChanged( this, false, true );
-	}
-	
-	protected void
-	failed(
-		Throwable	e )
-	{
-		queue.log( "Transcode failed", e );
-		
-		synchronized( this ){
-			
-			if ( state != ST_STOPPED ){
-			
-				state = ST_FAILED;
-			
-				error = Debug.getNestedExceptionMessage( e );
-				
-					// process_time filled with negative pause time, so add to it
-				
-				process_time += SystemTime.getMonotonousTime() - started_on;
-				
-				started_on = paused_on = 0;
-			}
-		}
-		
-		queue.jobChanged( this, false, true );
-	}
-	
-	protected void
-	complete()
-	{
-		synchronized( this ){
-		
-			state = ST_COMPLETE;
-			
-				// process_time filled with negative pause time, so add to it
-			
-			process_time += SystemTime.getMonotonousTime() - started_on;
-			
-			started_on = paused_on = 0;
-		}
-		
-		if ( download != null ){
-			
-			download.removeDownloadWillBeRemovedListener( this );
-		}
-		
-		transcode_file.setComplete( true );
-		
-		queue.jobChanged( this, false, false );
-	}
-	
-	protected void
-	updateProgress(
-		int		_done,
-		int		_eta )
-	{
-		if ( percent_complete != _done || eta != _eta){
-		
-			percent_complete	= _done;
-			eta					= _eta;
-			
-			queue.jobChanged( this, false, false );
-		}
-	}
-	
-	public TranscodeTarget
-	getTarget()
-	{
-		return( target );
-	}
-	
-	public int
-	getTranscodeRequirement()
-	{
-		if ( transcode_requirement >= 0 ){
-			
-			return( transcode_requirement );
-		}
-		
-		return( getDevice().getTranscodeRequirement());
-	}
-	
-	public void
-	analyseNow(
-		TranscodeAnalysisListener	listener )
-	
-		throws TranscodeException
-	{
-		queue.analyse( this, listener );
-	}
-	
-	protected DeviceImpl
-	getDevice()
-	{
-		return((DeviceImpl)target );
-	}
-	
-	public TranscodeProfile
-	getProfile()
-	{
-		return( profile );
-	}
-	
-	public DiskManagerFileInfo
-	getFile()
-	{
-		return( file );
-	}
-	
-	public TranscodeFileImpl 
-	getTranscodeFile() 
-	{
-		return( transcode_file );
-	}
-	
-	public int
-	getIndex()
-	{
-		return( queue.getIndex( this ));
-	}
-	
-	public int
-	getState()
-	{
-		return( state );
-	}
-	
-	public int
-	getPercentComplete()
-	{
-		return( percent_complete );
-	}
-	
-	public long
-	getETASecs()
-	{
-		if ( eta <= 0 ){
-			
-			return( 0 );
-			
-		}else if ( eta == Integer.MAX_VALUE ){
-			
-			return( Long.MAX_VALUE );
-			
-		}else{
-			
-			return( eta );
-		}
-	}
-	
-	public String
-	getETA()
-	{
-		if ( eta < 0 ){
-			
-			return( null );
-			
-		}else if ( eta == Integer.MAX_VALUE ){
-			
-			return( Constants.INFINITY_STRING );
-			
-		}else{
-			
-			return( TimeFormatter.format( eta ));
-		}
-	}
-	
-	public String
-	getError()
-	{
-		return( error );
-	}
-	
-	public boolean
-	canPause()
-	{
-		synchronized( this ){
-
-			return( !use_direct_input );
-		}
-	}
-	
-	public void
-	pause()
-	{
-		synchronized( this ){
-			
-			if ( use_direct_input ){
-				
-				return;
-			}
-			
-			if ( state == ST_RUNNING ){
-		
-				state = ST_PAUSED;
-				
-				paused_on = SystemTime.getMonotonousTime();
-				
-			}else{
-				
-				return;
-			}
-		}
-		
-		queue.jobChanged( this, false, true );
-	}
-	
-	public void
-	resume()
-	{
-		synchronized( this ){
-
-			if ( state == ST_PAUSED ){
-				
-				state = ST_RUNNING;
-
-				if ( paused_on > 0 && started_on > 0 ){
-					
-					process_time -= SystemTime.getMonotonousTime() - paused_on;
-				}
-			}else{
-				
-				return;
-			}
-		}
-		
-		queue.jobChanged( this, false, true );
-	}
-	
-	public void
-	queue()
-	{
-		boolean	do_resume;
-	
-		synchronized( this ){
-
-			do_resume = state == ST_PAUSED;
-		}
-		
-		if ( do_resume ){
-			
-			resume();
-			
-			return;
-		}
-
-		synchronized( this ){
-			
-			if ( state != ST_QUEUED ){
-		
-				if ( 	state == ST_RUNNING ||
-						state == ST_PAUSED ){
-					
-					stop();
-				}
-								
-				reset();
-				
-					// manual start, scrub error details
-				
-				use_direct_input 	= false;
-				auto_retry			= false;
-				auto_retry_count	= 0;
-				is_stream			= false;
-
-			}else{
-				
-				return;
-			}
-		}
-		
-		queue.jobChanged( this, true, true);
-	}
-	
-	public void
-	stop()
-	{
-		synchronized( this ){
-			
-			if ( state != ST_STOPPED ){
-		
-				state = ST_STOPPED;
-				
-				process_time = 0;
-
-				started_on = 0;
-				
-			}else{
-				
-				return;
-			}
-		}
-		
-		queue.jobChanged( this, true, true );
-	}
-	
-	public void
-	remove()
-	
-		throws TranscodeActionVetoException
-	{
-		queue.remove( this, false );
-	}
-	
-	public void
-	removeForce()
-	{
-		try{
-			queue.remove( this, true );
-			
-		}catch( TranscodeActionVetoException e ){
-			
-			Debug.out( e );
-		}
-	}
-	
-	protected void
-	destroy()
-	{
-		boolean	delete_file;
-		
-		synchronized( this ){
-			
-			delete_file = state != ST_COMPLETE;
-			
-			state = ST_REMOVED;
-		}
-		
-		if ( delete_file && !isStream()){
-			
-			try{
-				transcode_file.delete( true );
-				
-			}catch( Throwable e ){
-				
-				queue.log( "Faile to destroy job", e );
-			}
-		}
-	}
-	
-	public void 
-	moveUp() 
-	{
-		queue.moveUp( this );
-	}
-	
-	public void 
-	moveDown() 
-	{
-		queue.moveDown( this );
-	}
-	
-	public long
-	getProcessTime()
-	{
-		if ( state == ST_COMPLETE ){
-		
-			return process_time;
-		}
-		
-		if ( started_on == 0 ){
-			
-			if (  process_time > 0 ){
-				
-				return process_time;
-			}
-			
-			return 0;
-		}
-			// process_time filled with pause
-		
-		return SystemTime.getMonotonousTime() - started_on + process_time;
-	}
-		
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		writer.println( "target=" + target.getID() + ", profile=" + profile.getName() + ", file=" + file );
-		writer.println( "tfile=" + transcode_file.getString());
-		writer.println( "stream=" + is_stream + ", state=" + state + ", treq=" + transcode_requirement + ", %=" + percent_complete + ", error=" + error );
-	}
-}
+/*
+ * Created on Feb 6, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.*;
+
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadException;
+import org.gudy.azureus2.plugins.download.DownloadRemovalVetoException;
+import org.gudy.azureus2.plugins.download.DownloadWillBeRemovedListener;
+import org.gudy.azureus2.plugins.peers.PeerManager;
+import org.gudy.azureus2.plugins.peers.PeerManagerStats;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+
+import com.aelitis.azureus.core.cnetwork.ContentNetwork;
+import com.aelitis.azureus.core.devices.TranscodeAnalysisListener;
+import com.aelitis.azureus.core.devices.TranscodeJob;
+import com.aelitis.azureus.core.devices.TranscodeProfile;
+import com.aelitis.azureus.core.devices.TranscodeException;
+import com.aelitis.azureus.core.devices.TranscodeActionVetoException;
+import com.aelitis.azureus.core.devices.TranscodeTarget;
+import com.aelitis.azureus.core.download.DiskManagerFileInfoFile;
+import com.aelitis.azureus.core.download.DiskManagerFileInfoURL;
+import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
+import com.aelitis.azureus.util.ImportExportUtils;
+
+public class 
+TranscodeJobImpl 
+	implements TranscodeJob, DownloadWillBeRemovedListener
+{
+	private static final int TRANSCODE_OK_DL_PERCENT	= 90;
+	
+	private TranscodeQueueImpl		queue;
+	private TranscodeTarget			target;
+	private TranscodeProfile		profile;
+	private DiskManagerFileInfo		file;
+	private TranscodeFileImpl		transcode_file;
+	
+	private boolean					is_stream;
+	private volatile InputStream	stream;
+	private AESemaphore				stream_sem = new AESemaphore( "TJ:s" );
+	
+	private int						transcode_requirement;
+	
+	private int						state 				= ST_QUEUED;
+	private int						percent_complete	= 0;
+	private int						eta					= Integer.MAX_VALUE;
+	private String					error;
+	private long					started_on;
+	private long					paused_on;
+	private long					process_time;
+	
+	private boolean					use_direct_input;
+	private boolean					prefer_direct_input;
+	
+	private boolean					auto_retry_enabled	= true;
+	private boolean					auto_retry;
+	private int						auto_retry_count;
+	
+	private Download				download;
+	private volatile boolean		download_ok;
+	
+	protected
+	TranscodeJobImpl(
+		TranscodeQueueImpl		_queue,
+		TranscodeTarget			_target,
+		TranscodeProfile		_profile,
+		DiskManagerFileInfo		_file,
+		boolean					_add_stopped,
+		int						_transcode_requirement,
+		boolean					_is_stream )
+	
+		throws TranscodeException
+	{
+		queue					= _queue;
+		target					= _target;
+		profile					= _profile;
+		file					= _file;
+		transcode_requirement	= _transcode_requirement;
+		is_stream				= _is_stream;
+		
+		if ( _add_stopped ){
+			
+			state = ST_STOPPED;
+		}
+		
+		init();
+	}
+	
+	protected
+	TranscodeJobImpl(
+		TranscodeQueueImpl		_queue,
+		Map<String,Object>		map )
+	
+		throws IOException, TranscodeException
+	{
+		queue	= _queue;
+		
+		state = ImportExportUtils.importInt( map, "state" );
+		
+		if ( state == ST_RUNNING ){
+			
+			state = ST_QUEUED;
+		}
+		
+		error = ImportExportUtils.importString( map, "error", null );
+		
+		String	target_id = ImportExportUtils.importString( map, "target" );
+		
+		target = queue.lookupTarget( target_id );
+		
+		String	profile_id = ImportExportUtils.importString( map, "profile" );
+		
+		profile = queue.lookupProfile( profile_id );
+		
+		String file_str = ImportExportUtils.importString( map, "file" );
+		
+		if ( file_str == null ){
+			
+			byte[] dl_hash = ByteFormatter.decodeString( ImportExportUtils.importString( map, "dl_hash" ));
+			
+			int file_index = ImportExportUtils.importInt( map, "file_index" );
+			
+			file = queue.lookupFile( dl_hash, file_index );
+		}else{
+		
+			file = new DiskManagerFileInfoFile( new File( file_str ));
+		}
+		
+		transcode_requirement	= ImportExportUtils.importInt( map, "trans_req", TranscodeTarget.TRANSCODE_UNKNOWN );
+		
+		auto_retry_enabled = ImportExportUtils.importBoolean( map, "ar_enable", true );
+		
+		prefer_direct_input = ImportExportUtils.importBoolean( map, "pdi", false );
+		
+		init();
+	}
+
+	protected Map<String,Object>
+	toMap()
+	
+		throws IOException
+	{
+		try{
+			Map<String,Object> map = new HashMap<String, Object>();
+			
+			synchronized( this ){
+				
+				ImportExportUtils.exportInt( map, "state", state );
+				ImportExportUtils.exportString( map, "error", error );
+				
+				ImportExportUtils.exportString( map, "target", target.getID());
+				
+				ImportExportUtils.exportString( map, "profile", profile.getUID());
+				
+				try{
+					Download download = file.getDownload();
+					
+					ImportExportUtils.exportString( map, "dl_hash", ByteFormatter.encodeString( download.getTorrent().getHash()));
+	
+					ImportExportUtils.exportInt( map, "file_index", file.getIndex());
+	
+				}catch( DownloadException e ){
+					
+						// external file
+					
+					ImportExportUtils.exportString( map, "file", file.getFile().getAbsolutePath());
+				}
+			
+				ImportExportUtils.exportInt( map, "trans_req", transcode_requirement );
+					
+				ImportExportUtils.exportBoolean( map, "ar_enable", auto_retry_enabled );
+				
+				ImportExportUtils.exportBoolean( map, "pdi", prefer_direct_input );
+			}
+			
+			return( map );
+			
+		}catch( Throwable e ){
+			
+			throw( new IOException( "Export failed: " + Debug.getNestedExceptionMessage(e)));
+		}
+	}
+	
+	protected void
+	init()
+	
+		throws TranscodeException
+	{
+		transcode_file = ((DeviceImpl)target.getDevice()).allocateFile( profile, getTranscodeRequirement() == TranscodeTarget.TRANSCODE_NEVER, file, true );
+		
+		try{
+			download = file.getDownload();
+			
+			if ( download != null ){
+				
+				download.addDownloadWillBeRemovedListener( this );
+			}
+		}catch( Throwable e ){
+		}
+		
+		updateStatus( false );
+	}
+	
+	protected void
+	updateStatus()
+	{
+		updateStatus( true );
+	}
+	
+	protected void
+	updateStatus(
+		boolean	report_change )
+	{
+		synchronized( this ){
+			
+			if ( download_ok ){
+				
+				return;
+			}
+			
+			long	downloaded 	= file.getDownloaded();
+			long	length		= file.getLength();
+			
+			if ( download == null || downloaded == length ){
+				
+				download_ok = true;
+				
+			}else{
+
+				Torrent torrent = download.getTorrent();
+						
+				if ( 	PlatformTorrentUtils.isContent( torrent, false ) || 
+						PlatformTorrentUtils.getContentNetworkID( PluginCoreUtils.unwrap( torrent )) == ContentNetwork.CONTENT_NETWORK_VHDNL ){
+					
+					download_ok = true;
+					
+				}else{
+					
+					int	percent_done = (int)( 100*downloaded/length );
+					
+					if ( percent_done >= TRANSCODE_OK_DL_PERCENT ){
+						
+						download_ok = true;
+						
+					}else{
+						
+						PeerManager pm = download.getPeerManager();
+						
+						if ( pm != null ){
+							
+							PeerManagerStats stats = pm.getStats();
+							
+							int connected_seeds 	= stats.getConnectedSeeds();
+							int connected_leechers	= stats.getConnectedLeechers();
+							
+							
+							if ( connected_seeds > 10 && connected_seeds > connected_leechers ){
+								
+								download_ok = true;
+							}
+						}else{
+							
+							int state = download.getState();
+							
+							if ( state == Download.ST_STOPPED ){
+								
+								try{
+									download.restart();
+									
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		
+		if ( download_ok && report_change ){
+			
+			queue.jobChanged( this, true, false );
+		}
+	}
+	
+	public long
+	getDownloadETA()
+	{
+		if ( download_ok ){
+			
+			return( 0 );
+		}
+		
+		if ( file.getDownloaded() == file.getLength()){
+			
+			return( 0 );
+		}
+
+		if ( file.isSkipped() || file.isDeleted()){
+				
+			return( Long.MAX_VALUE );
+		}
+			
+		try{
+			long	eta = PluginCoreUtils.unwrap( download ).getStats().getSmoothedETA();
+			
+			if ( eta < 0 ){
+				
+				return( Long.MAX_VALUE );
+			}
+			
+			long adjusted = eta*100/TRANSCODE_OK_DL_PERCENT;
+			
+			if ( adjusted == 0 ){
+				
+				adjusted = 1;
+			}
+			
+			return( adjusted );
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( Long.MAX_VALUE );
+		}
+	}
+	
+	protected boolean
+	canUseDirectInput()
+	{
+		if ( file instanceof DiskManagerFileInfoURL ){
+			
+			return( true );
+		}
+		
+		long	length = file.getLength();
+
+		return( file.getDownloaded() == length &&
+				file.getFile().length() == length );
+	}
+	
+	protected boolean
+	useDirectInput()
+	{
+		synchronized( this ){
+
+			return( use_direct_input || 
+					( getPreferDirectInput() && canUseDirectInput()));
+		}
+	}
+	
+	protected void
+	setUseDirectInput()
+	{
+		synchronized( this ){
+
+			use_direct_input = true;
+		}
+	}
+	
+	public void
+	setPreferDirectInput(
+		boolean		prefer )
+	{
+		synchronized( this ){
+		
+			prefer_direct_input = prefer;
+		}
+	}
+	
+	public boolean
+	getPreferDirectInput()
+	{
+		synchronized( this ){
+		
+			return( prefer_direct_input );
+		}
+	}
+	
+	protected void
+	setAutoRetry(
+		boolean		_auto_retry )
+	{
+		synchronized( this ){
+
+			if ( _auto_retry ){
+				
+				auto_retry 	= true;
+				
+				auto_retry_count++;
+				
+			}else{
+				
+				auto_retry = false;
+			}
+		}
+	}
+	
+	protected boolean
+	isAutoRetry()
+	{
+		synchronized( this ){
+			
+			return( auto_retry );
+		}
+	}
+	
+	protected int
+	getAutoRetryCount()
+	{
+		synchronized( this ){
+
+			return( auto_retry_count );
+		}
+	}
+	
+	public void
+	setEnableAutoRetry(
+		boolean		enabled )
+	{
+		auto_retry_enabled = enabled;
+	}
+	
+	public boolean 
+	getEnableAutoRetry() 
+	{
+		return( auto_retry_enabled );
+	}
+	
+	protected boolean
+	isStream()
+	{
+		return( is_stream );
+	}
+	
+	protected void
+	setStream(
+		InputStream		_stream )
+	{
+		stream		= _stream;
+		
+		stream_sem.releaseForever();
+	}
+	
+	protected InputStream
+	getStream(
+		int		wait_for_millis )
+	
+		throws IOException
+	{
+		if ( state == ST_FAILED ){
+			
+			throw( new IOException( "Transcode job failed: " + error ));
+			
+		}else if ( state == ST_CANCELLED ){
+			
+			throw( new IOException( "Transcode job cancelled" ));
+
+		}else if ( state == ST_REMOVED ){
+			
+			throw( new IOException( "Transcode job removed" ));
+		}
+		
+		stream_sem.reserve( wait_for_millis );
+		
+		return( stream );
+	}
+	
+	public void 
+	downloadWillBeRemoved(
+		Download 	download )
+
+		throws DownloadRemovalVetoException
+	{
+		if ( queue.getIndex( this ) == 0 || state == ST_COMPLETE ){
+			
+			download.removeDownloadWillBeRemovedListener( this );
+			
+		}else{
+			
+			throw( new DownloadRemovalVetoException( 
+					MessageText.getString( "devices.xcode.remove.vetoed",
+						new String[]{ download.getName()})));
+		}
+	}
+	
+	public String
+	getName()
+	{
+		if ( download != null ){
+		
+			if ( download.getDiskManagerFileInfo().length == 1 ){
+				
+				return( download.getName());
+			}
+			
+			return( download.getName() + ": " + file.getFile().getName());
+			
+		}else{
+			
+			return( file.getFile().getName());
+		}
+	}
+	
+	protected void
+	reset()
+	{
+		state 				= ST_QUEUED;
+		error 				= null;
+		percent_complete	= 0;
+		eta					= Integer.MAX_VALUE;
+	}
+	
+	protected void
+	starts()
+	{
+		synchronized( this ){
+		
+			started_on 	= SystemTime.getMonotonousTime();
+			paused_on	= 0;
+
+				// this is for an Azureus restart with a paused job - we don't want to change the
+				// state as we want it to re-pause...
+			
+			if ( state != ST_PAUSED ){
+			
+				state = ST_RUNNING;				
+			}
+		}
+		
+		queue.jobChanged( this, false, true );
+	}
+	
+	protected void
+	failed(
+		Throwable	e )
+	{
+		queue.log( "Transcode failed", e );
+		
+		synchronized( this ){
+			
+			if ( state != ST_STOPPED ){
+			
+				state = ST_FAILED;
+			
+				error = Debug.getNestedExceptionMessage( e );
+				
+					// process_time filled with negative pause time, so add to it
+				
+				process_time += SystemTime.getMonotonousTime() - started_on;
+				
+				started_on = paused_on = 0;
+			}
+		}
+		
+		queue.jobChanged( this, false, true );
+	}
+	
+	protected void
+	complete()
+	{
+		synchronized( this ){
+		
+			state = ST_COMPLETE;
+			
+				// process_time filled with negative pause time, so add to it
+			
+			process_time += SystemTime.getMonotonousTime() - started_on;
+			
+			started_on = paused_on = 0;
+		}
+		
+		if ( download != null ){
+			
+			download.removeDownloadWillBeRemovedListener( this );
+		}
+		
+		transcode_file.setComplete( true );
+		
+		queue.jobChanged( this, false, false );
+	}
+	
+	protected void
+	updateProgress(
+		int		_done,
+		int		_eta )
+	{
+		if ( percent_complete != _done || eta != _eta){
+		
+			percent_complete	= _done;
+			eta					= _eta;
+			
+			queue.jobChanged( this, false, false );
+		}
+	}
+	
+	public TranscodeTarget
+	getTarget()
+	{
+		return( target );
+	}
+	
+	public int
+	getTranscodeRequirement()
+	{
+		if ( transcode_requirement >= 0 ){
+			
+			return( transcode_requirement );
+		}
+		
+		return( getDevice().getTranscodeRequirement());
+	}
+	
+	public void
+	analyseNow(
+		TranscodeAnalysisListener	listener )
+	
+		throws TranscodeException
+	{
+		queue.analyse( this, listener );
+	}
+	
+	protected DeviceImpl
+	getDevice()
+	{
+		return((DeviceImpl)target );
+	}
+	
+	public TranscodeProfile
+	getProfile()
+	{
+		return( profile );
+	}
+	
+	public DiskManagerFileInfo
+	getFile()
+	{
+		return( file );
+	}
+	
+	public TranscodeFileImpl 
+	getTranscodeFile() 
+	{
+		return( transcode_file );
+	}
+	
+	public int
+	getIndex()
+	{
+		return( queue.getIndex( this ));
+	}
+	
+	public int
+	getState()
+	{
+		return( state );
+	}
+	
+	public int
+	getPercentComplete()
+	{
+		return( percent_complete );
+	}
+	
+	public long
+	getETASecs()
+	{
+		if ( eta <= 0 ){
+			
+			return( 0 );
+			
+		}else if ( eta == Integer.MAX_VALUE ){
+			
+			return( Long.MAX_VALUE );
+			
+		}else{
+			
+			return( eta );
+		}
+	}
+	
+	public String
+	getETA()
+	{
+		if ( eta < 0 ){
+			
+			return( null );
+			
+		}else if ( eta == Integer.MAX_VALUE ){
+			
+			return( Constants.INFINITY_STRING );
+			
+		}else{
+			
+			return( TimeFormatter.format( eta ));
+		}
+	}
+	
+	public String
+	getError()
+	{
+		return( error );
+	}
+	
+	public boolean
+	canPause()
+	{
+		synchronized( this ){
+
+			return( !use_direct_input );
+		}
+	}
+	
+	public void
+	pause()
+	{
+		synchronized( this ){
+			
+			if ( use_direct_input ){
+				
+				return;
+			}
+			
+			if ( state == ST_RUNNING ){
+		
+				state = ST_PAUSED;
+				
+				paused_on = SystemTime.getMonotonousTime();
+				
+			}else{
+				
+				return;
+			}
+		}
+		
+		queue.jobChanged( this, false, true );
+	}
+	
+	public void
+	resume()
+	{
+		synchronized( this ){
+
+			if ( state == ST_PAUSED ){
+				
+				state = ST_RUNNING;
+
+				if ( paused_on > 0 && started_on > 0 ){
+					
+					process_time -= SystemTime.getMonotonousTime() - paused_on;
+				}
+			}else{
+				
+				return;
+			}
+		}
+		
+		queue.jobChanged( this, false, true );
+	}
+	
+	public void
+	queue()
+	{
+		boolean	do_resume;
+	
+		synchronized( this ){
+
+			do_resume = state == ST_PAUSED;
+		}
+		
+		if ( do_resume ){
+			
+			resume();
+			
+			return;
+		}
+
+		synchronized( this ){
+			
+			if ( state != ST_QUEUED ){
+		
+				if ( 	state == ST_RUNNING ||
+						state == ST_PAUSED ){
+					
+					stop();
+				}
+								
+				reset();
+				
+					// manual start, scrub error details
+				
+				use_direct_input 	= false;
+				auto_retry			= false;
+				auto_retry_count	= 0;
+				is_stream			= false;
+
+			}else{
+				
+				return;
+			}
+		}
+		
+		queue.jobChanged( this, true, true);
+	}
+	
+	public void
+	stop()
+	{
+		synchronized( this ){
+			
+			if ( state != ST_STOPPED ){
+		
+				state = ST_STOPPED;
+				
+				process_time = 0;
+
+				started_on = 0;
+				
+			}else{
+				
+				return;
+			}
+		}
+		
+		queue.jobChanged( this, true, true );
+	}
+	
+	public void
+	remove()
+	
+		throws TranscodeActionVetoException
+	{
+		queue.remove( this, false );
+	}
+	
+	public void
+	removeForce()
+	{
+		try{
+			queue.remove( this, true );
+			
+		}catch( TranscodeActionVetoException e ){
+			
+			Debug.out( e );
+		}
+	}
+	
+	protected void
+	destroy()
+	{
+		boolean	delete_file;
+		
+		synchronized( this ){
+			
+			delete_file = state != ST_COMPLETE;
+			
+			state = ST_REMOVED;
+		}
+		
+		if ( delete_file && !isStream()){
+			
+			try{
+				transcode_file.delete( true );
+				
+			}catch( Throwable e ){
+				
+				queue.log( "Faile to destroy job", e );
+			}
+		}
+	}
+	
+	public void 
+	moveUp() 
+	{
+		queue.moveUp( this );
+	}
+	
+	public void 
+	moveDown() 
+	{
+		queue.moveDown( this );
+	}
+	
+	public long
+	getProcessTime()
+	{
+		if ( state == ST_COMPLETE ){
+		
+			return process_time;
+		}
+		
+		if ( started_on == 0 ){
+			
+			if (  process_time > 0 ){
+				
+				return process_time;
+			}
+			
+			return 0;
+		}
+			// process_time filled with pause
+		
+		return SystemTime.getMonotonousTime() - started_on + process_time;
+	}
+		
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		writer.println( "target=" + target.getID() + ", profile=" + profile.getName() + ", file=" + file );
+		writer.println( "tfile=" + transcode_file.getString());
+		writer.println( "stream=" + is_stream + ", state=" + state + ", treq=" + transcode_requirement + ", %=" + percent_complete + ", error=" + error );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeJobOutputLeecher.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeJobOutputLeecher.java
index 8fa1efa..878aadc 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeJobOutputLeecher.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeJobOutputLeecher.java
@@ -1,608 +1,607 @@
-/*
- * Created on Feb 11, 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.*;
-import java.util.*;
-
-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.SHA1Simple;
-import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
-import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.plugins.disk.DiskManagerListener;
-import org.gudy.azureus2.plugins.disk.DiskManagerRandomReadRequest;
-import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadException;
-import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
-import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
-
-import com.aelitis.azureus.core.devices.TranscodeException;
-import com.aelitis.azureus.core.devices.TranscodeJob;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-public class 
-TranscodeJobOutputLeecher
-	implements DiskManagerFileInfo
-{	
-	private TranscodeJobImpl		job;
-	private TranscodeFileImpl		file;
-	
-	private File	save_to;
-	private byte[]	hash;
-	
-	public
-	TranscodeJobOutputLeecher(
-		TranscodeJobImpl		_job,
-		TranscodeFileImpl		_file )
-	
-		throws TranscodeException
-	{
-		job		= _job;
-		file	= _file;
-		
-		save_to = file.getCacheFile();
-		
-		try{
-			hash = new SHA1Simple().calculateHash( save_to.getAbsolutePath().getBytes( "UTF-8" ));
-			
-		}catch( Throwable e ){
-			
-			Debug.out(e);
-		}
-	}
-	
-	
-	public void 
-	setPriority(
-		boolean b )
-	{
-	}
-	
-	public int 
-	getNumericPriorty() 
-	{
-		return( 0 );
-	}
-	
-	public int 
-	getNumericPriority() 
-	{
-		return( 0 );
-	}
-	
-	public void 
-	setNumericPriority(
-		int priority) 
-	{
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public void 
-	setSkipped(
-		boolean b )
-	{
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public void
-	setDeleted(boolean b)
-	{
-	}	
-	
-	public void
-	setLink(
-		File	link_destination )
-	{	
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public File
-	getLink()
-	{
-		return( null );
-	}
-		 	
-	public int 
-	getAccessMode()
-	{
-		return( READ );
-	}
-	
-	public long 
-	getDownloaded()
-	{
-		return( getLength());
-	}
-	
-	public long
-	getLength()
-	{
-		if ( file.isComplete()){
-			
-			try{
-				return( file.getTargetFile().getLength());
-				
-			}catch( Throwable e ){
-				
-				return( -1 );
-			}
-		}else{
-			
-			return( -1 );
-		}
-	}
-	
-	public File 
-	getFile()
-	{
-		return( save_to );
-	}
-		
-	public File
-	getFile(
-		boolean	follow_link )
-	{
-		return( save_to );
-	}
-	
-	public int
-	getIndex()
-	{
-		return( 0 );
-	}
-	
-	public int 
-	getFirstPieceNumber()
-	{
-		return( 0 );
-	}
-	
-	public long
-	getPieceSize()
-	{
-		return( 32*1024 );
-	}
-	
-	public int 
-	getNumPieces()
-	{
-		return( -1 );
-	}
-		
-	public boolean 
-	isPriority()
-	{
-		return( false );
-	}
-	
-	public boolean 
-	isSkipped()
-	{
-		return( false );
-	}
-	
-	public boolean
-	isDeleted()
-	{
-		return( false );
-	}
-	
-	public byte[] 
-	getDownloadHash() 
-	
-		throws DownloadException 
-	{
-		return( hash );
-	}
-	
-	public Download 
-	getDownload()
-	
-         throws DownloadException
-    {
-		throw( new DownloadException( "Not supported" ));
-    }
-	
-	public DiskManagerChannel
-	createChannel()
-	
-		throws DownloadException
-	{
-		return( new Channel());
-	}
-	
-	public DiskManagerRandomReadRequest
-	createRandomReadRequest(
-		long						file_offset,
-		long						length,
-		boolean						reverse_order,
-		DiskManagerListener			listener )
-	
-		throws DownloadException
-	{
-		throw( new DownloadException( "Not supported" ));
-	}
-	
-	protected class
-	Channel
-		implements DiskManagerChannel
-	{
-		private volatile boolean		channel_destroyed;
-		private volatile long			channel_position;
-		
-		private RandomAccessFile		raf;
-		
-		public DiskManagerRequest
-		createRequest()
-		{
-			return( new request());
-		}
-		
-		public DiskManagerFileInfo
-		getFile()
-		{
-			return( TranscodeJobOutputLeecher.this );
-		}
-		
-		public long 
-		getPosition() 
-		{
-			return( channel_position );
-		}
-		
-		public boolean 
-		isDestroyed() 
-		{
-			return( channel_destroyed );
-		}
-		
-		public void
-		destroy()
-		{
-			synchronized( this ){
-				
-				channel_destroyed	= true;
-				
-				if ( raf != null ){
-					
-					try{
-						raf.close();
-						
-					}catch( Throwable e ){
-					}
-					
-					raf = null;
-				}
-			}
-		}
-		
-		protected int
-		read(
-			byte[]		buffer,
-			long		offset,
-			int			length )
-		
-			throws IOException
-		{
-			synchronized( this ){
-				
-				if ( channel_destroyed ){
-					
-					throw( new IOException( "Channel destroyed" ));
-				}
-				
-				if ( raf == null ){
-					
-					if ( save_to.exists()){
-						
-						raf = new RandomAccessFile( save_to, "r" );
-						
-					}else{
-						
-						int state = job.getState();
-						
-						if ( state == TranscodeJob.ST_REMOVED ){
-							
-							throw( new IOException( "Job has been removed" ));
-							
-						}else if ( 	state == TranscodeJob.ST_FAILED ||
-									state == TranscodeJob.ST_CANCELLED ){
-							
-							throw( new IOException( "Job has failed or been cancelled" ));
-							
-						}else if ( 	state == TranscodeJob.ST_COMPLETE ){
-							
-							throw( new IOException( "Job is complete but file missing" ));
-						}
-
-							// fall through and return 0 read
-					}
-				}
-				
-				if ( raf != null ){
-					
-					if ( raf.length() > offset ){
-						
-						raf.seek( offset );
-						
-						return( raf.read( buffer, 0, length ));
-						
-					}else{
-					
-							// data not yet available or file complete
-						
-						if ( file.isComplete()){
-							
-							return( -1 );
-						}
-					}
-				}
-			}
-			
-			try{
-				Thread.sleep( 500 );
-				
-			}catch( Throwable e ){
-				
-				throw( new IOException( "Interrupted" ));
-			}
-	
-			return( 0 );
-		}
-		
-		protected class
-		request
-			implements DiskManagerRequest
-		{
-			private long		offset;
-			private long		length;
-			
-			private long		position;
-			
-			private int			max_read_chunk = 128*1024;;
-			
-			private volatile boolean	request_cancelled;
-			
-			private CopyOnWriteList<DiskManagerListener>		listeners = new CopyOnWriteList<DiskManagerListener>();
-			
-			public void
-			setType(
-				int			type )
-			{
-				if ( type != DiskManagerRequest.REQUEST_READ ){
-					
-					throw( new RuntimeException( "Not supported" ));
-				}
-			}
-			
-			public void
-			setOffset(
-				long		_offset )
-			{
-				offset		= _offset;
-			}
-			
-			public void
-			setLength(
-				long		_length )
-			{
-					// length can be -1 here meaning 'to the end'
-				
-				length		= _length==-1?Long.MAX_VALUE:_length;
-			}
-				
-			public void
-			setMaximumReadChunkSize(
-				int 	size )
-			{
-				if ( size > 16*1024 ){
-				
-					max_read_chunk = size;
-				}
-			}
-			
-			public long
-			getAvailableBytes()
-			{
-				return( getRemaining());
-			}
-						
-			public long
-			getRemaining()
-			{
-				return( length==Long.MAX_VALUE?length:(offset + length - position ));
-			}
-			
-			public void
-			run()
-			{
-				try{				
-					byte[] buffer = new byte[max_read_chunk];
-					
-					long	rem		= length;
-					long	pos 	= offset;
-					
-					while( rem > 0 ){
-						
-						if ( request_cancelled ){
-							
-							throw( new Exception( "Cancelled" ));
-							
-						}else if ( channel_destroyed ){
-							
-							throw( new Exception( "Destroyed" ));
-						}
-						
-						int	chunk = (int)Math.min( rem, max_read_chunk );
-						
-						int	len = read( buffer, pos, chunk );
-							
-						if ( len == -1 ){
-							
-							if ( length == Long.MAX_VALUE ){
-								
-								break;
-								
-							}else{
-								
-								throw( new Exception( "Premature end of stream (complete)" ));
-							}
-						}else if ( len == 0 ){
-							
-							sendEvent( new event( pos ));
-							
-						}else{
-															
-							sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
-							
-							rem -= len;
-							pos	+= len;
-						}
-					}
-				}catch( Throwable e ){
-					
-					sendEvent( new event( e ));
-				}
-			}
-			
-			public void
-			cancel()
-			{
-				request_cancelled = true;
-			}
-			
-			public void
-			setUserAgent(
-				String		agent )
-			{	
-			}
-			
-			protected void
-			sendEvent(
-				event		ev )
-			{					
-				for ( DiskManagerListener l: listeners ){
-					
-					l.eventOccurred( ev );
-				}
-			}
-			
-			public void
-			addListener(
-				DiskManagerListener	listener )
-			{
-				listeners.add( listener );
-			}
-			
-			public void
-			removeListener(
-				DiskManagerListener	listener )
-			{
-				listeners.remove( listener );
-			}
-		
-			protected class
-			event
-				implements DiskManagerEvent
-			{
-				private int					event_type;
-				private Throwable			error;
-				private PooledByteBuffer	buffer;
-				private long				event_offset;
-				private int					event_length;
-				
-				protected
-				event(
-					Throwable		_error )
-				{
-					event_type	= DiskManagerEvent.EVENT_TYPE_FAILED;
-					error		= _error;
-				}
-					
-				protected 
-				event(
-					long				_offset )
-				{
-					event_type		= DiskManagerEvent.EVENT_TYPE_BLOCKED;
-
-					event_offset	= _offset;	
-					
-					channel_position = _offset;
-				}
-				
-				protected
-				event(
-					PooledByteBuffer	_buffer,
-					long				_offset,
-					int					_length )
-				{
-					event_type		= DiskManagerEvent.EVENT_TYPE_SUCCESS;
-					buffer			= _buffer;
-					event_offset	= _offset;
-					event_length	= _length;
-					
-					channel_position = _offset + _length - 1;
-				}
-				
-				public int
-				getType()
-				{
-					return( event_type );
-				}
-				
-				public DiskManagerRequest
-				getRequest()
-				{
-					return( request.this );
-				}
-				
-				public long
-				getOffset()
-				{
-					return( event_offset );
-				}
-				
-				public int
-				getLength()
-				{
-					return( event_length );
-				}
-				
-				public PooledByteBuffer
-				getBuffer()
-				{
-					return( buffer );
-				}
-				
-				public Throwable
-				getFailure()
-				{
-					return( error );
-				}
-			}
-		}
-	}
-}
+/*
+ * Created on Feb 11, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.*;
+import java.util.*;
+
+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.SHA1Simple;
+import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
+import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.disk.DiskManagerListener;
+import org.gudy.azureus2.plugins.disk.DiskManagerRandomReadRequest;
+import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadException;
+import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
+import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
+
+import com.aelitis.azureus.core.devices.TranscodeException;
+import com.aelitis.azureus.core.devices.TranscodeJob;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
+public class 
+TranscodeJobOutputLeecher
+	implements DiskManagerFileInfo
+{	
+	private TranscodeJobImpl		job;
+	private TranscodeFileImpl		file;
+	
+	private File	save_to;
+	private byte[]	hash;
+	
+	public
+	TranscodeJobOutputLeecher(
+		TranscodeJobImpl		_job,
+		TranscodeFileImpl		_file )
+	
+		throws TranscodeException
+	{
+		job		= _job;
+		file	= _file;
+		
+		save_to = file.getCacheFile();
+		
+		try{
+			hash = new SHA1Simple().calculateHash( save_to.getAbsolutePath().getBytes( "UTF-8" ));
+			
+		}catch( Throwable e ){
+			
+			Debug.out(e);
+		}
+	}
+	
+	
+	public void 
+	setPriority(
+		boolean b )
+	{
+	}
+	
+	public int 
+	getNumericPriorty() 
+	{
+		return( 0 );
+	}
+	
+	public int 
+	getNumericPriority() 
+	{
+		return( 0 );
+	}
+	
+	public void 
+	setNumericPriority(
+		int priority) 
+	{
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public void 
+	setSkipped(
+		boolean b )
+	{
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public void
+	setDeleted(boolean b)
+	{
+	}	
+	
+	public void
+	setLink(
+		File	link_destination )
+	{	
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public File
+	getLink()
+	{
+		return( null );
+	}
+		 	
+	public int 
+	getAccessMode()
+	{
+		return( READ );
+	}
+	
+	public long 
+	getDownloaded()
+	{
+		return( getLength());
+	}
+	
+	public long
+	getLength()
+	{
+		if ( file.isComplete()){
+			
+			try{
+				return( file.getTargetFile().getLength());
+				
+			}catch( Throwable e ){
+				
+				return( -1 );
+			}
+		}else{
+			
+			return( -1 );
+		}
+	}
+	
+	public File 
+	getFile()
+	{
+		return( save_to );
+	}
+		
+	public File
+	getFile(
+		boolean	follow_link )
+	{
+		return( save_to );
+	}
+	
+	public int
+	getIndex()
+	{
+		return( 0 );
+	}
+	
+	public int 
+	getFirstPieceNumber()
+	{
+		return( 0 );
+	}
+	
+	public long
+	getPieceSize()
+	{
+		return( 32*1024 );
+	}
+	
+	public int 
+	getNumPieces()
+	{
+		return( -1 );
+	}
+		
+	public boolean 
+	isPriority()
+	{
+		return( false );
+	}
+	
+	public boolean 
+	isSkipped()
+	{
+		return( false );
+	}
+	
+	public boolean
+	isDeleted()
+	{
+		return( false );
+	}
+	
+	public byte[] 
+	getDownloadHash() 
+	
+		throws DownloadException 
+	{
+		return( hash );
+	}
+	
+	public Download 
+	getDownload()
+	
+         throws DownloadException
+    {
+		throw( new DownloadException( "Not supported" ));
+    }
+	
+	public DiskManagerChannel
+	createChannel()
+	
+		throws DownloadException
+	{
+		return( new Channel());
+	}
+	
+	public DiskManagerRandomReadRequest
+	createRandomReadRequest(
+		long						file_offset,
+		long						length,
+		boolean						reverse_order,
+		DiskManagerListener			listener )
+	
+		throws DownloadException
+	{
+		throw( new DownloadException( "Not supported" ));
+	}
+	
+	protected class
+	Channel
+		implements DiskManagerChannel
+	{
+		private volatile boolean		channel_destroyed;
+		private volatile long			channel_position;
+		
+		private RandomAccessFile		raf;
+		
+		public DiskManagerRequest
+		createRequest()
+		{
+			return( new request());
+		}
+		
+		public DiskManagerFileInfo
+		getFile()
+		{
+			return( TranscodeJobOutputLeecher.this );
+		}
+		
+		public long 
+		getPosition() 
+		{
+			return( channel_position );
+		}
+		
+		public boolean 
+		isDestroyed() 
+		{
+			return( channel_destroyed );
+		}
+		
+		public void
+		destroy()
+		{
+			synchronized( this ){
+				
+				channel_destroyed	= true;
+				
+				if ( raf != null ){
+					
+					try{
+						raf.close();
+						
+					}catch( Throwable e ){
+					}
+					
+					raf = null;
+				}
+			}
+		}
+		
+		protected int
+		read(
+			byte[]		buffer,
+			long		offset,
+			int			length )
+		
+			throws IOException
+		{
+			synchronized( this ){
+				
+				if ( channel_destroyed ){
+					
+					throw( new IOException( "Channel destroyed" ));
+				}
+				
+				if ( raf == null ){
+					
+					if ( save_to.exists()){
+						
+						raf = new RandomAccessFile( save_to, "r" );
+						
+					}else{
+						
+						int state = job.getState();
+						
+						if ( state == TranscodeJob.ST_REMOVED ){
+							
+							throw( new IOException( "Job has been removed" ));
+							
+						}else if ( 	state == TranscodeJob.ST_FAILED ||
+									state == TranscodeJob.ST_CANCELLED ){
+							
+							throw( new IOException( "Job has failed or been cancelled" ));
+							
+						}else if ( 	state == TranscodeJob.ST_COMPLETE ){
+							
+							throw( new IOException( "Job is complete but file missing" ));
+						}
+
+							// fall through and return 0 read
+					}
+				}
+				
+				if ( raf != null ){
+					
+					if ( raf.length() > offset ){
+						
+						raf.seek( offset );
+						
+						return( raf.read( buffer, 0, length ));
+						
+					}else{
+					
+							// data not yet available or file complete
+						
+						if ( file.isComplete()){
+							
+							return( -1 );
+						}
+					}
+				}
+			}
+			
+			try{
+				Thread.sleep( 500 );
+				
+			}catch( Throwable e ){
+				
+				throw( new IOException( "Interrupted" ));
+			}
+	
+			return( 0 );
+		}
+		
+		protected class
+		request
+			implements DiskManagerRequest
+		{
+			private long		offset;
+			private long		length;
+			
+			private long		position;
+			
+			private int			max_read_chunk = 128*1024;;
+			
+			private volatile boolean	request_cancelled;
+			
+			private CopyOnWriteList<DiskManagerListener>		listeners = new CopyOnWriteList<DiskManagerListener>();
+			
+			public void
+			setType(
+				int			type )
+			{
+				if ( type != DiskManagerRequest.REQUEST_READ ){
+					
+					throw( new RuntimeException( "Not supported" ));
+				}
+			}
+			
+			public void
+			setOffset(
+				long		_offset )
+			{
+				offset		= _offset;
+			}
+			
+			public void
+			setLength(
+				long		_length )
+			{
+					// length can be -1 here meaning 'to the end'
+				
+				length		= _length==-1?Long.MAX_VALUE:_length;
+			}
+				
+			public void
+			setMaximumReadChunkSize(
+				int 	size )
+			{
+				if ( size > 16*1024 ){
+				
+					max_read_chunk = size;
+				}
+			}
+			
+			public long
+			getAvailableBytes()
+			{
+				return( getRemaining());
+			}
+						
+			public long
+			getRemaining()
+			{
+				return( length==Long.MAX_VALUE?length:(offset + length - position ));
+			}
+			
+			public void
+			run()
+			{
+				try{				
+					byte[] buffer = new byte[max_read_chunk];
+					
+					long	rem		= length;
+					long	pos 	= offset;
+					
+					while( rem > 0 ){
+						
+						if ( request_cancelled ){
+							
+							throw( new Exception( "Cancelled" ));
+							
+						}else if ( channel_destroyed ){
+							
+							throw( new Exception( "Destroyed" ));
+						}
+						
+						int	chunk = (int)Math.min( rem, max_read_chunk );
+						
+						int	len = read( buffer, pos, chunk );
+							
+						if ( len == -1 ){
+							
+							if ( length == Long.MAX_VALUE ){
+								
+								break;
+								
+							}else{
+								
+								throw( new Exception( "Premature end of stream (complete)" ));
+							}
+						}else if ( len == 0 ){
+							
+							sendEvent( new event( pos ));
+							
+						}else{
+															
+							sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
+							
+							rem -= len;
+							pos	+= len;
+						}
+					}
+				}catch( Throwable e ){
+					
+					sendEvent( new event( e ));
+				}
+			}
+			
+			public void
+			cancel()
+			{
+				request_cancelled = true;
+			}
+			
+			public void
+			setUserAgent(
+				String		agent )
+			{	
+			}
+			
+			protected void
+			sendEvent(
+				event		ev )
+			{					
+				for ( DiskManagerListener l: listeners ){
+					
+					l.eventOccurred( ev );
+				}
+			}
+			
+			public void
+			addListener(
+				DiskManagerListener	listener )
+			{
+				listeners.add( listener );
+			}
+			
+			public void
+			removeListener(
+				DiskManagerListener	listener )
+			{
+				listeners.remove( listener );
+			}
+		
+			protected class
+			event
+				implements DiskManagerEvent
+			{
+				private int					event_type;
+				private Throwable			error;
+				private PooledByteBuffer	buffer;
+				private long				event_offset;
+				private int					event_length;
+				
+				protected
+				event(
+					Throwable		_error )
+				{
+					event_type	= DiskManagerEvent.EVENT_TYPE_FAILED;
+					error		= _error;
+				}
+					
+				protected 
+				event(
+					long				_offset )
+				{
+					event_type		= DiskManagerEvent.EVENT_TYPE_BLOCKED;
+
+					event_offset	= _offset;	
+					
+					channel_position = _offset;
+				}
+				
+				protected
+				event(
+					PooledByteBuffer	_buffer,
+					long				_offset,
+					int					_length )
+				{
+					event_type		= DiskManagerEvent.EVENT_TYPE_SUCCESS;
+					buffer			= _buffer;
+					event_offset	= _offset;
+					event_length	= _length;
+					
+					channel_position = _offset + _length - 1;
+				}
+				
+				public int
+				getType()
+				{
+					return( event_type );
+				}
+				
+				public DiskManagerRequest
+				getRequest()
+				{
+					return( request.this );
+				}
+				
+				public long
+				getOffset()
+				{
+					return( event_offset );
+				}
+				
+				public int
+				getLength()
+				{
+					return( event_length );
+				}
+				
+				public PooledByteBuffer
+				getBuffer()
+				{
+					return( buffer );
+				}
+				
+				public Throwable
+				getFailure()
+				{
+					return( error );
+				}
+			}
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeManagerImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeManagerImpl.java
index 6ace86d..d3b9c08 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeManagerImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeManagerImpl.java
@@ -1,1012 +1,1011 @@
-/*
- * Created on Feb 4, 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.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.gudy.azureus2.core3.category.Category;
-import org.gudy.azureus2.core3.category.CategoryListener;
-import org.gudy.azureus2.core3.category.CategoryManager;
-import org.gudy.azureus2.core3.category.CategoryManagerListener;
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.global.GlobalManagerAdapter;
-import org.gudy.azureus2.core3.global.GlobalManagerListener;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.*;
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
-import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.devices.*;
-import com.aelitis.azureus.core.tag.Tag;
-import com.aelitis.azureus.core.tag.TagDownload;
-import com.aelitis.azureus.core.tag.TagFeature;
-import com.aelitis.azureus.core.tag.TagFeatureListener;
-import com.aelitis.azureus.core.tag.TagFeatureTranscode;
-import com.aelitis.azureus.core.tag.TagListener;
-import com.aelitis.azureus.core.tag.TagManager;
-import com.aelitis.azureus.core.tag.TagManagerFactory;
-import com.aelitis.azureus.core.tag.TagType;
-import com.aelitis.azureus.core.tag.Taggable;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-public class 
-TranscodeManagerImpl
-	implements TranscodeManager
-{
-	private DeviceManagerImpl		device_manager;
-	private AzureusCore				azureus_core;
-	
-	private volatile TranscodeProviderVuze	vuzexcode_provider;
-	
-	private CopyOnWriteList<TranscodeManagerListener>	listeners = new CopyOnWriteList<TranscodeManagerListener>();
-	
-	private TranscodeQueueImpl		queue = new TranscodeQueueImpl( this );
-	
-	private AESemaphore	init_sem 	= new AESemaphore( "TM:init" );
-
-	private boolean hooked_categories;
-	
-	private Map<Category,Object[]> 	category_map = new HashMap<Category, Object[]>();
-	private CategoryListener		category_listener;
-	private GlobalManagerListener	category_dl_listener;
-	private TorrentAttribute		category_ta;
-	
-	private boolean 				hooked_tags;
-
-	private Map<Tag,Object[]> 		tag_map = new HashMap<Tag, Object[]>();
-	private TagListener				tag_listener;
-
-	private TorrentAttribute		tag_ta;
-
-	protected
-	TranscodeManagerImpl(
-		DeviceManagerImpl		_dm )
-	{
-		device_manager	= _dm;
-		
-		azureus_core = AzureusCoreFactory.getSingleton();
-		
-		PluginInterface default_pi = PluginInitializer.getDefaultInterface();
-		
-		category_ta = default_pi.getTorrentManager().getPluginAttribute( "xcode.cat.done" );
-		tag_ta 		= default_pi.getTorrentManager().getPluginAttribute( "xcode.tag.done" );
-		
-		final AESemaphore	plugin_sem 	= new AESemaphore( "TM:plugin" );
-
-		default_pi.addListener(
-			new PluginListener()
-			{
-				public void
-				initializationComplete()
-				{
-					try{
-						PluginInterface default_pi = PluginInitializer.getDefaultInterface();
-						
-						default_pi.addEventListener(
-							new PluginEventListener()
-							{
-								public void 
-								handleEvent(
-									PluginEvent ev )
-								{
-									int	type = ev.getType();
-									
-									if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL ){
-										
-										pluginAdded((PluginInterface)ev.getValue());
-									}
-									if ( type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL ){
-										
-										pluginRemoved((PluginInterface)ev.getValue());
-									}
-								}
-							});
-						
-						PluginInterface[] plugins = default_pi.getPluginManager().getPlugins();
-						
-						for ( PluginInterface pi: plugins ){
-							
-							if ( pi.getPluginState().isOperational()){
-							
-								pluginAdded( pi );
-							}
-						}
-					}finally{
-						
-						plugin_sem.releaseForever();
-					}
-				}
-				
-				public void
-				closedownInitiated()
-				{
-					plugin_sem.releaseForever();
-					
-						// we don't want things hanging around for init if we're closing
-					
-					init_sem.releaseForever();
-				}
-				
-				public void
-				closedownComplete()
-				{
-				}
-			});
-		
-		if ( !plugin_sem.reserve( 30*1000 )){
-			
-			Debug.out( "Timeout waiting for init" );
-			
-			AEDiagnostics.dumpThreads();
-		}
-	}
-	
-	protected void
-	initialise()
-	{
-		queue.initialise();
-		
-		init_sem.releaseForever();
-	}
-	
-	protected void
-	pluginAdded(
-		PluginInterface		pi )
-	{
-		if ( pi.getPluginState().isBuiltIn()){
-			
-			return;
-		}
-		
-		String plugin_id = pi.getPluginID();
-		
-		if ( plugin_id.equals( "vuzexcode" )){
-			
-			boolean		added		= false;
-			boolean		updated		= false;
-			
-			TranscodeProviderVuze provider	= null;
-			
-			synchronized( this ){
-				
-				if ( vuzexcode_provider == null ){
-					
-					vuzexcode_provider = new TranscodeProviderVuze( this, pi );
-			
-					added = true;
-					
-				}else if ( pi != vuzexcode_provider.getPluginInterface()){
-										
-					vuzexcode_provider.update( pi );
-					
-					updated = true;
-				}
-				
-				provider = vuzexcode_provider;
-			}
-			
-			if ( added ){
-				
-				for ( TranscodeManagerListener listener: listeners ){
-					
-					try{
-						listener.providerAdded( provider );
-						
-					}catch( Throwable e ){
-						
-						Debug.out( e );
-					}
-				}
-			}else if ( updated ){
-				
-				for ( TranscodeManagerListener listener: listeners ){
-					
-					try{
-						listener.providerUpdated( provider );
-						
-					}catch( Throwable e ){
-						
-						Debug.out( e );
-					}
-				}
-			}
-		}
-	}
-	
-	protected void
-	pluginRemoved(
-		PluginInterface		pi )
-	{
-		String plugin_id = pi.getPluginID();
-		
-		if ( plugin_id.equals( "vuzexcode" )){
-			
-			TranscodeProviderVuze provider	= null;
-
-			synchronized( this ){
-				
-				if ( vuzexcode_provider != null ){
-
-					provider = vuzexcode_provider;
-					
-					vuzexcode_provider.destroy();
-					
-					vuzexcode_provider = null;
-				}
-			}
-			
-			if ( provider != null ){
-				
-				for ( TranscodeManagerListener listener: listeners ){
-					
-					try{
-						listener.providerRemoved( provider );
-						
-					}catch( Throwable e ){
-						
-						Debug.out( e );
-					}
-				}
-			}
-		}
-	}
-	
-	protected void
-	updateStatus(
-		int	tick_count )
-	{
-		if ( queue != null ){
-			
-			queue.updateStatus( tick_count );
-			
-			if ( !hooked_categories ){
-				
-				hooked_categories = true;
-				
-				CategoryManager.addCategoryManagerListener(
-					new CategoryManagerListener()
-					{
-						public void
-						categoryAdded(
-							Category category )
-						{
-						}
-							
-						public void
-						categoryRemoved(
-							Category category )
-						{
-						}
-						
-						public void
-						categoryChanged(
-							Category category )
-						{
-							checkCategories();
-						}
-					});
-				
-				checkCategories();
-			}
-			
-			if ( !hooked_tags ){
-				
-				hooked_tags = true;
-				
-				TagManagerFactory.getTagManager().addTagFeatureListener(
-					TagFeature.TF_XCODE,
-					new TagFeatureListener()
-					{
-						public void 
-						tagFeatureChanged(
-							Tag tag, 
-							int feature ) 
-						{
-							checkTags();
-						}
-					});
-					
-				
-				checkTags();
-			}
-		}
-	}
-	
-	private void
-	checkCategories()
-	{
-		Category[] cats = CategoryManager.getCategories();
-		
-		Map<Category,Object[]> active_map = new HashMap<Category, Object[]>();
-		
-		for ( Category cat: cats ){
-			
-			String target = cat.getStringAttribute( Category.AT_AUTO_TRANSCODE_TARGET );
-			
-			if ( target != null ){
-				
-				String device_id = null;
-				
-				if ( target.endsWith( "/blank" )){
-					
-					device_id = target.substring( 0, target.length() - 6 );
-				}
-				
-				DeviceMediaRenderer		target_dmr			= null;
-				TranscodeProfile		target_profile 		= null;
-				
-				for ( DeviceImpl device: device_manager.getDevices()){
-				
-					if ( !( device instanceof DeviceMediaRenderer )){
-						
-						continue;
-					}
-					
-					DeviceMediaRenderer dmr = (DeviceMediaRenderer)device;
-					
-					if ( device_id != null ){
-						
-						if ( device.getID().equals( device_id )){
-							
-							target_dmr		 	= dmr;
-							target_profile		= device.getBlankProfile();
-							
-							break;
-						}
-					}else{
-						
-						TranscodeProfile[] profs = device.getTranscodeProfiles();
-						
-						for ( TranscodeProfile prof: profs ){
-							
-							if ( prof.getUID().equals( target )){
-								
-								target_dmr	= dmr;
-								target_profile	= prof;
-								
-								break;
-							}
-						}
-					}
-				}
-			
-				if ( target_dmr != null ){
-					
-					active_map.put( cat, new Object[]{ target_dmr, target_profile });					
-				}
-			}
-		}
-		
-		Map<Category,Object[]> to_process = new HashMap<Category, Object[]>();
-		
-		synchronized( category_map ){
-			
-			if ( category_listener == null ){
-				
-				category_listener = 
-					new CategoryListener()
-					{
-						public void	
-						downloadManagerAdded(
-							Category 			cat, 
-							DownloadManager 	manager )
-						{
-							Object[]	details;
-							
-							synchronized( category_map ){
-
-								details = category_map.get( cat );
-							}
-							
-							if ( details != null ){
-								
-								processCategory( cat, details, manager );
-							}
-						}
-					
-						public void	
-						downloadManagerRemoved(
-							Category 			cat, 
-							DownloadManager 	removed )
-						{							
-						}
-					};
-			}
-			
-			Iterator<Category>	it = category_map.keySet().iterator();
-			
-			while( it.hasNext()){
-				
-				Category c = it.next();
-				
-				if ( !active_map.containsKey( c )){
-					
-					c.removeCategoryListener( category_listener );
-					
-					it.remove();
-				}
-			}
-			
-			for ( final Category c: active_map.keySet()){
-				
-				if ( !category_map.containsKey( c )){
-					
-					to_process.put( c, active_map.get(c));
-					
-					c.addCategoryListener( category_listener );
-					
-					category_map.put( c, active_map.get(c));
-					
-					if ( c.getType() == Category.TYPE_UNCATEGORIZED ){
-						
-						if ( category_dl_listener == null ){
-						
-								// new downloads don't get a category-change event fired when added
-								// we also want to delay things a bit to allow other components
-								// to set an initial category. there's no hurry anyways
-							
-							category_dl_listener = 
-								new GlobalManagerAdapter()
-								{
-									public void
-									downloadManagerAdded(
-										final DownloadManager	dm )
-									{
-										new DelayedEvent( 
-											"TM:cat-check",
-											10*1000,
-											new AERunnable()
-											{
-												public void
-												runSupport()
-												{
-													Category dm_c = dm.getDownloadState().getCategory();
-													
-													if ( dm_c == null || dm_c == c ){
-														
-															// still uncategorised
-													
-														Object[]	details;
-														
-														synchronized( category_map ){
-	
-															details = category_map.get( c );
-														}
-														
-														if ( details != null ){
-															
-															processCategory( c, details, dm );
-														}
-													}
-												}
-											});
-									}
-									public void
-									downloadManagerRemoved(
-										DownloadManager	dm )
-									{
-									}
-								};
-						
-								
-							azureus_core.getGlobalManager().addListener( category_dl_listener, false );
-						}
-					}
-				}
-			}
-		}
-		
-		if ( to_process.size() > 0 ){
-			
-			List<DownloadManager> downloads = azureus_core.getGlobalManager().getDownloadManagers();
-			
-			for ( Map.Entry<Category, Object[]> entry: to_process.entrySet()){
-				
-				Category 	c 		= entry.getKey();
-				Object[]	details = entry.getValue();
-				
-				List<DownloadManager> list = c.getDownloadManagers( downloads );
-				
-				for( DownloadManager dm: list ){
-					
-					processCategory( c, details, dm );
-				}
-			}
-		}
-	}
-	
-	private void
-	processCategory(
-		Category		cat,
-		Object[]		details,
-		DownloadManager	dm )
-	{
-		Download download = PluginCoreUtils.wrap( dm );
-		
-		if ( download == null ){
-			
-			return;
-		}
-		
-		if ( download.getFlag( Download.FLAG_LOW_NOISE )){
-			
-			return;
-		}
-		
-		String str = download.getAttribute( category_ta );
-		
-		String cat_name = cat.getName();
-		
-		if ( cat.getType() == Category.TYPE_UNCATEGORIZED ){
-			
-			cat_name = "<none>";
-		}
-		
-		String	cat_tag = cat_name + ";";
-		
-		if ( str != null && str.contains( cat_tag )){
-			
-			return;
-		}
-		
-		try{
-			DeviceMediaRenderer		device 	= (DeviceMediaRenderer)details[0];
-			TranscodeProfile		profile	= (TranscodeProfile)details[1];
-						
-			log( "Category " + cat_name + " - adding " + download.getName() + " to " + device.getName() + "/" + profile.getName());
-			
-			DiskManagerFileInfo[] dm_files = download.getDiskManagerFileInfo();
-			
-			int	num_added = 0;
-			
-			for ( DiskManagerFileInfo dm_file: dm_files ){
-				
-					// limit number of files we can add to avoid crazyness
-				
-				if ( num_added > 64 ){
-					
-					break;
-				}
-				
-					// could be smarter here and check extension or whatever
-				
-				if ( dm_files.length == 1 || dm_file.getLength() >= 128*1024 ){
-					
-					try{
-						queue.add( device, profile, dm_file, false  );
-					
-						num_added++;
-						
-					}catch( Throwable e ){
-						
-						log( "    add failed", e );
-					}
-				}
-			}
-		}finally{
-			
-			download.setAttribute( category_ta, str==null?cat_tag:(str+cat_tag));
-		}
-	}
-	
-	
-	
-	private void
-	checkTags()
-	{
-		TagManager tm = TagManagerFactory.getTagManager();
-		
-		Map<Tag,Object[]> active_map = new HashMap<Tag, Object[]>();
-		
-		for ( TagType tt: tm.getTagTypes()){
-			
-			if ( !tt.hasTagTypeFeature( TagFeature.TF_XCODE )){
-				
-				continue;
-			}
-			
-
-			for ( Tag tag: tt.getTags()){
-			
-				TagFeatureTranscode tfx = (TagFeatureTranscode)tag;
-				
-				if ( !tfx.supportsTagTranscode()){
-					
-					continue;
-				}
-				
-				String[] target_details = tfx.getTagTranscodeTarget();
-				
-				if ( target_details != null ){
-					
-					String	target = target_details[0];
-					
-					String device_id = null;
-					
-					if ( target.endsWith( "/blank" )){
-						
-						device_id = target.substring( 0, target.length() - 6 );
-					}
-					
-					DeviceMediaRenderer		target_dmr			= null;
-					TranscodeProfile		target_profile 		= null;
-					
-					for ( DeviceImpl device: device_manager.getDevices()){
-					
-						if ( !( device instanceof DeviceMediaRenderer )){
-							
-							continue;
-						}
-						
-						DeviceMediaRenderer dmr = (DeviceMediaRenderer)device;
-						
-						if ( device_id != null ){
-							
-							if ( device.getID().equals( device_id )){
-								
-								target_dmr		 	= dmr;
-								target_profile		= device.getBlankProfile();
-								
-								break;
-							}
-						}else{
-							
-							TranscodeProfile[] profs = device.getTranscodeProfiles();
-							
-							for ( TranscodeProfile prof: profs ){
-								
-								if ( prof.getUID().equals( target )){
-									
-									target_dmr	= dmr;
-									target_profile	= prof;
-									
-									break;
-								}
-							}
-						}
-					}
-				
-					if ( target_dmr != null ){
-						
-						active_map.put( tag, new Object[]{ target_dmr, target_profile });					
-					}
-				}
-			}
-		}
-		
-		Map<Tag,Object[]> to_process = new HashMap<Tag, Object[]>();
-		
-		synchronized( tag_map ){
-			
-			if ( tag_listener == null ){
-				
-				tag_listener = 
-					new TagListener()
-					{
-						public void
-						taggableAdded(
-							Tag			tag,
-							Taggable	tagged )
-						{
-							Object[]	details;
-							
-							synchronized( tag_map ){
-
-								details = tag_map.get( tag );
-							}
-							
-							if ( details != null ){
-								
-								processTag( tag, details, (DownloadManager)tagged );
-							}
-						}
-						
-						public void
-						taggableSync(
-							Tag			tag )
-						{
-							
-						}
-						
-						public void
-						taggableRemoved(
-							Tag			tag,
-							Taggable	tagged )
-						{
-							
-						}
-					};
-			}
-			
-			Iterator<Tag>	it = tag_map.keySet().iterator();
-			
-			while( it.hasNext()){
-				
-				Tag t = it.next();
-				
-				if ( !active_map.containsKey( t )){
-					
-					t.removeTagListener( tag_listener );
-					
-					it.remove();
-				}
-			}
-			
-			for ( final Tag tag: active_map.keySet()){
-				
-				if ( !tag_map.containsKey( tag )){
-					
-					to_process.put( tag, active_map.get( tag ));
-					
-					tag.addTagListener( tag_listener, false );
-					
-					tag_map.put( tag, active_map.get( tag ));
-				}
-			}
-		}
-		
-		if ( to_process.size() > 0 ){
-						
-			for ( Map.Entry<Tag, Object[]> entry: to_process.entrySet()){
-				
-				Tag		 	tag 	= entry.getKey();
-				Object[]	details = entry.getValue();
-				
-				Set<DownloadManager> list = ((TagDownload)tag).getTaggedDownloads();
-				
-				for( DownloadManager dm: list ){
-					
-					processTag( tag, details, dm );
-				}
-			}
-		}
-	}
-	
-	
-	
-	private void
-	processTag(
-		Tag				tag,
-		Object[]		details,
-		DownloadManager	dm )
-	{
-		Download download = PluginCoreUtils.wrap( dm );
-		
-		if ( download == null ){
-			
-			return;
-		}
-		
-		if ( download.getFlag( Download.FLAG_LOW_NOISE )){
-			
-			return;
-		}
-		
-		String str = download.getAttribute( tag_ta );
-		
-		String tag_name = tag.getTagName( true );
-		
-		String	tag_tag = tag.getTagType().getTagType() + "." + tag.getTagID() + ";";
-		
-		if ( str != null && str.contains( tag_tag )){
-			
-			return;
-		}
-		
-		try{
-			DeviceMediaRenderer		device 	= (DeviceMediaRenderer)details[0];
-			TranscodeProfile		profile	= (TranscodeProfile)details[1];
-						
-			log( "Tag " + tag_name + " - adding " + download.getName() + " to " + device.getName() + "/" + profile.getName());
-			
-			DiskManagerFileInfo[] dm_files = download.getDiskManagerFileInfo();
-			
-			int	num_added = 0;
-			
-			for ( DiskManagerFileInfo dm_file: dm_files ){
-				
-					// limit number of files we can add to avoid crazyness
-				
-				if ( num_added > 64 ){
-					
-					break;
-				}
-				
-					// could be smarter here and check extension or whatever
-				
-				if ( dm_files.length == 1 || dm_file.getLength() >= 128*1024 ){
-					
-					try{
-						queue.add( device, profile, dm_file, false  );
-					
-						num_added++;
-						
-					}catch( Throwable e ){
-						
-						log( "    add failed", e );
-					}
-				}
-			}
-		}finally{
-			
-			download.setAttribute( tag_ta, str==null?tag_tag:(str+tag_tag));
-		}
-	}
-	
-	public TranscodeProvider[]
-	getProviders()
-	{
-		TranscodeProviderVuze	vp = vuzexcode_provider;
-
-		if ( vp == null ){
-		
-			return( new TranscodeProvider[0] );
-		}
-		
-		return( new TranscodeProvider[]{ vp });
-	}
-	
-	protected TranscodeProvider
-	getProvider(
-		int		p_id )
-	
-		throws TranscodeException
-	{
-		TranscodeProviderVuze	vp = vuzexcode_provider;
-
-		if ( p_id == TranscodeProvider.TP_VUZE && vp != null ){
-			
-			return( vp );
-		}
-		
-		throw( new TranscodeException( "Transcode provider not registered" ));
-	}
-	
-	protected TranscodeProfile
-	getProfileFromUID(
-		String		uid )
-	{
-		for ( TranscodeProvider provider: getProviders()){
-			
-			TranscodeProfile profile = provider.getProfile( uid );
-			
-			if ( profile != null ){
-				
-				return( profile );
-			}
-		}
-		
-		return( null );
-	}
-	
-	public TranscodeQueueImpl
-	getQueue() 
-	{
-		if ( !init_sem.reserve(30*1000)){
-			
-			Debug.out( "Timeout waiting for init" );
-			
-			AEDiagnostics.dumpThreads();
-		}
-		
-		return( queue );
-	}
-	
-	protected DeviceManagerImpl
-	getManager()
-	{
-		return( device_manager );
-	}
-	
-	protected TranscodeTarget
-	lookupTarget(
-		String		target_id )
-	
-		throws TranscodeException
-	{
-		Device device = device_manager.getDevice( target_id );
-		
-		if ( device instanceof TranscodeTarget ){
-			
-			return((TranscodeTarget)device);
-		}
-		
-		throw( new TranscodeException( "Transcode target with id " + target_id + " not found" ));
-	}
-	
-	protected DiskManagerFileInfo
-	lookupFile(
-		byte[]		hash,
-		int			index )
-	
-		throws TranscodeException
-	{
-		try{
-			Download download = PluginInitializer.getDefaultInterface().getDownloadManager().getDownload( hash );
-			
-			if ( download == null ){
-				
-				throw( new TranscodeException( "Download with hash " + ByteFormatter.encodeString( hash ) + " not found" ));
-			}
-		
-			return( download.getDiskManagerFileInfo()[index]);
-			
-		}catch( Throwable e ){
-			
-			throw( new TranscodeException( "Download with hash " + ByteFormatter.encodeString( hash ) + " not found", e ));
-
-		}
-	}
-	
-	protected void
-	close()
-	{
-		queue.close();
-	}
-	
-	public void
-	addListener(
-		TranscodeManagerListener		listener )
-	{
-		listeners.add( listener );
-	}
-	
-	public void
-	removeListener(
-		TranscodeManagerListener		listener )
-	{
-		listeners.remove( listener );
-	}
-	
-	protected void
-	log(
-		String	str )
-	{
-		device_manager.log( "Trans: " + str );
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable	e )
-	{
-		device_manager.log( "Trans: " + str, e );
-	}
-	
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		writer.println( "Transcode Manager: vuze provider=" + vuzexcode_provider );
-		
-		queue.generate( writer );
-	}
-}
+/*
+ * Created on Feb 4, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.gudy.azureus2.core3.category.Category;
+import org.gudy.azureus2.core3.category.CategoryListener;
+import org.gudy.azureus2.core3.category.CategoryManager;
+import org.gudy.azureus2.core3.category.CategoryManagerListener;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.global.GlobalManagerAdapter;
+import org.gudy.azureus2.core3.global.GlobalManagerListener;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.*;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.devices.*;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagDownload;
+import com.aelitis.azureus.core.tag.TagFeature;
+import com.aelitis.azureus.core.tag.TagFeatureListener;
+import com.aelitis.azureus.core.tag.TagFeatureTranscode;
+import com.aelitis.azureus.core.tag.TagListener;
+import com.aelitis.azureus.core.tag.TagManager;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
+import com.aelitis.azureus.core.tag.Taggable;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
+public class 
+TranscodeManagerImpl
+	implements TranscodeManager
+{
+	private DeviceManagerImpl		device_manager;
+	private AzureusCore				azureus_core;
+	
+	private volatile TranscodeProviderVuze	vuzexcode_provider;
+	
+	private CopyOnWriteList<TranscodeManagerListener>	listeners = new CopyOnWriteList<TranscodeManagerListener>();
+	
+	private TranscodeQueueImpl		queue = new TranscodeQueueImpl( this );
+	
+	private AESemaphore	init_sem 	= new AESemaphore( "TM:init" );
+
+	private boolean hooked_categories;
+	
+	private Map<Category,Object[]> 	category_map = new HashMap<Category, Object[]>();
+	private CategoryListener		category_listener;
+	private GlobalManagerListener	category_dl_listener;
+	private TorrentAttribute		category_ta;
+	
+	private boolean 				hooked_tags;
+
+	private Map<Tag,Object[]> 		tag_map = new HashMap<Tag, Object[]>();
+	private TagListener				tag_listener;
+
+	private TorrentAttribute		tag_ta;
+
+	protected
+	TranscodeManagerImpl(
+		DeviceManagerImpl		_dm )
+	{
+		device_manager	= _dm;
+		
+		azureus_core = AzureusCoreFactory.getSingleton();
+		
+		PluginInterface default_pi = PluginInitializer.getDefaultInterface();
+		
+		category_ta = default_pi.getTorrentManager().getPluginAttribute( "xcode.cat.done" );
+		tag_ta 		= default_pi.getTorrentManager().getPluginAttribute( "xcode.tag.done" );
+		
+		final AESemaphore	plugin_sem 	= new AESemaphore( "TM:plugin" );
+
+		default_pi.addListener(
+			new PluginListener()
+			{
+				public void
+				initializationComplete()
+				{
+					try{
+						PluginInterface default_pi = PluginInitializer.getDefaultInterface();
+						
+						default_pi.addEventListener(
+							new PluginEventListener()
+							{
+								public void 
+								handleEvent(
+									PluginEvent ev )
+								{
+									int	type = ev.getType();
+									
+									if ( type == PluginEvent.PEV_PLUGIN_OPERATIONAL ){
+										
+										pluginAdded((PluginInterface)ev.getValue());
+									}
+									if ( type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL ){
+										
+										pluginRemoved((PluginInterface)ev.getValue());
+									}
+								}
+							});
+						
+						PluginInterface[] plugins = default_pi.getPluginManager().getPlugins();
+						
+						for ( PluginInterface pi: plugins ){
+							
+							if ( pi.getPluginState().isOperational()){
+							
+								pluginAdded( pi );
+							}
+						}
+					}finally{
+						
+						plugin_sem.releaseForever();
+					}
+				}
+				
+				public void
+				closedownInitiated()
+				{
+					plugin_sem.releaseForever();
+					
+						// we don't want things hanging around for init if we're closing
+					
+					init_sem.releaseForever();
+				}
+				
+				public void
+				closedownComplete()
+				{
+				}
+			});
+		
+		if ( !plugin_sem.reserve( 30*1000 )){
+			
+			Debug.out( "Timeout waiting for init" );
+			
+			AEDiagnostics.dumpThreads();
+		}
+	}
+	
+	protected void
+	initialise()
+	{
+		queue.initialise();
+		
+		init_sem.releaseForever();
+	}
+	
+	protected void
+	pluginAdded(
+		PluginInterface		pi )
+	{
+		if ( pi.getPluginState().isBuiltIn()){
+			
+			return;
+		}
+		
+		String plugin_id = pi.getPluginID();
+		
+		if ( plugin_id.equals( "vuzexcode" )){
+			
+			boolean		added		= false;
+			boolean		updated		= false;
+			
+			TranscodeProviderVuze provider	= null;
+			
+			synchronized( this ){
+				
+				if ( vuzexcode_provider == null ){
+					
+					vuzexcode_provider = new TranscodeProviderVuze( this, pi );
+			
+					added = true;
+					
+				}else if ( pi != vuzexcode_provider.getPluginInterface()){
+										
+					vuzexcode_provider.update( pi );
+					
+					updated = true;
+				}
+				
+				provider = vuzexcode_provider;
+			}
+			
+			if ( added ){
+				
+				for ( TranscodeManagerListener listener: listeners ){
+					
+					try{
+						listener.providerAdded( provider );
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+				}
+			}else if ( updated ){
+				
+				for ( TranscodeManagerListener listener: listeners ){
+					
+					try{
+						listener.providerUpdated( provider );
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+				}
+			}
+		}
+	}
+	
+	protected void
+	pluginRemoved(
+		PluginInterface		pi )
+	{
+		String plugin_id = pi.getPluginID();
+		
+		if ( plugin_id.equals( "vuzexcode" )){
+			
+			TranscodeProviderVuze provider	= null;
+
+			synchronized( this ){
+				
+				if ( vuzexcode_provider != null ){
+
+					provider = vuzexcode_provider;
+					
+					vuzexcode_provider.destroy();
+					
+					vuzexcode_provider = null;
+				}
+			}
+			
+			if ( provider != null ){
+				
+				for ( TranscodeManagerListener listener: listeners ){
+					
+					try{
+						listener.providerRemoved( provider );
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+				}
+			}
+		}
+	}
+	
+	protected void
+	updateStatus(
+		int	tick_count )
+	{
+		if ( queue != null ){
+			
+			queue.updateStatus( tick_count );
+			
+			if ( !hooked_categories ){
+				
+				hooked_categories = true;
+				
+				CategoryManager.addCategoryManagerListener(
+					new CategoryManagerListener()
+					{
+						public void
+						categoryAdded(
+							Category category )
+						{
+						}
+							
+						public void
+						categoryRemoved(
+							Category category )
+						{
+						}
+						
+						public void
+						categoryChanged(
+							Category category )
+						{
+							checkCategories();
+						}
+					});
+				
+				checkCategories();
+			}
+			
+			if ( !hooked_tags ){
+				
+				hooked_tags = true;
+				
+				TagManagerFactory.getTagManager().addTagFeatureListener(
+					TagFeature.TF_XCODE,
+					new TagFeatureListener()
+					{
+						public void 
+						tagFeatureChanged(
+							Tag tag, 
+							int feature ) 
+						{
+							checkTags();
+						}
+					});
+					
+				
+				checkTags();
+			}
+		}
+	}
+	
+	private void
+	checkCategories()
+	{
+		Category[] cats = CategoryManager.getCategories();
+		
+		Map<Category,Object[]> active_map = new HashMap<Category, Object[]>();
+		
+		for ( Category cat: cats ){
+			
+			String target = cat.getStringAttribute( Category.AT_AUTO_TRANSCODE_TARGET );
+			
+			if ( target != null ){
+				
+				String device_id = null;
+				
+				if ( target.endsWith( "/blank" )){
+					
+					device_id = target.substring( 0, target.length() - 6 );
+				}
+				
+				DeviceMediaRenderer		target_dmr			= null;
+				TranscodeProfile		target_profile 		= null;
+				
+				for ( DeviceImpl device: device_manager.getDevices()){
+				
+					if ( !( device instanceof DeviceMediaRenderer )){
+						
+						continue;
+					}
+					
+					DeviceMediaRenderer dmr = (DeviceMediaRenderer)device;
+					
+					if ( device_id != null ){
+						
+						if ( device.getID().equals( device_id )){
+							
+							target_dmr		 	= dmr;
+							target_profile		= device.getBlankProfile();
+							
+							break;
+						}
+					}else{
+						
+						TranscodeProfile[] profs = device.getTranscodeProfiles();
+						
+						for ( TranscodeProfile prof: profs ){
+							
+							if ( prof.getUID().equals( target )){
+								
+								target_dmr	= dmr;
+								target_profile	= prof;
+								
+								break;
+							}
+						}
+					}
+				}
+			
+				if ( target_dmr != null ){
+					
+					active_map.put( cat, new Object[]{ target_dmr, target_profile });					
+				}
+			}
+		}
+		
+		Map<Category,Object[]> to_process = new HashMap<Category, Object[]>();
+		
+		synchronized( category_map ){
+			
+			if ( category_listener == null ){
+				
+				category_listener = 
+					new CategoryListener()
+					{
+						public void	
+						downloadManagerAdded(
+							Category 			cat, 
+							DownloadManager 	manager )
+						{
+							Object[]	details;
+							
+							synchronized( category_map ){
+
+								details = category_map.get( cat );
+							}
+							
+							if ( details != null ){
+								
+								processCategory( cat, details, manager );
+							}
+						}
+					
+						public void	
+						downloadManagerRemoved(
+							Category 			cat, 
+							DownloadManager 	removed )
+						{							
+						}
+					};
+			}
+			
+			Iterator<Category>	it = category_map.keySet().iterator();
+			
+			while( it.hasNext()){
+				
+				Category c = it.next();
+				
+				if ( !active_map.containsKey( c )){
+					
+					c.removeCategoryListener( category_listener );
+					
+					it.remove();
+				}
+			}
+			
+			for ( final Category c: active_map.keySet()){
+				
+				if ( !category_map.containsKey( c )){
+					
+					to_process.put( c, active_map.get(c));
+					
+					c.addCategoryListener( category_listener );
+					
+					category_map.put( c, active_map.get(c));
+					
+					if ( c.getType() == Category.TYPE_UNCATEGORIZED ){
+						
+						if ( category_dl_listener == null ){
+						
+								// new downloads don't get a category-change event fired when added
+								// we also want to delay things a bit to allow other components
+								// to set an initial category. there's no hurry anyways
+							
+							category_dl_listener = 
+								new GlobalManagerAdapter()
+								{
+									public void
+									downloadManagerAdded(
+										final DownloadManager	dm )
+									{
+										new DelayedEvent( 
+											"TM:cat-check",
+											10*1000,
+											new AERunnable()
+											{
+												public void
+												runSupport()
+												{
+													Category dm_c = dm.getDownloadState().getCategory();
+													
+													if ( dm_c == null || dm_c == c ){
+														
+															// still uncategorised
+													
+														Object[]	details;
+														
+														synchronized( category_map ){
+	
+															details = category_map.get( c );
+														}
+														
+														if ( details != null ){
+															
+															processCategory( c, details, dm );
+														}
+													}
+												}
+											});
+									}
+									public void
+									downloadManagerRemoved(
+										DownloadManager	dm )
+									{
+									}
+								};
+						
+								
+							azureus_core.getGlobalManager().addListener( category_dl_listener, false );
+						}
+					}
+				}
+			}
+		}
+		
+		if ( to_process.size() > 0 ){
+			
+			List<DownloadManager> downloads = azureus_core.getGlobalManager().getDownloadManagers();
+			
+			for ( Map.Entry<Category, Object[]> entry: to_process.entrySet()){
+				
+				Category 	c 		= entry.getKey();
+				Object[]	details = entry.getValue();
+				
+				List<DownloadManager> list = c.getDownloadManagers( downloads );
+				
+				for( DownloadManager dm: list ){
+					
+					processCategory( c, details, dm );
+				}
+			}
+		}
+	}
+	
+	private void
+	processCategory(
+		Category		cat,
+		Object[]		details,
+		DownloadManager	dm )
+	{
+		Download download = PluginCoreUtils.wrap( dm );
+		
+		if ( download == null ){
+			
+			return;
+		}
+		
+		if ( download.getFlag( Download.FLAG_LOW_NOISE )){
+			
+			return;
+		}
+		
+		String str = download.getAttribute( category_ta );
+		
+		String cat_name = cat.getName();
+		
+		if ( cat.getType() == Category.TYPE_UNCATEGORIZED ){
+			
+			cat_name = "<none>";
+		}
+		
+		String	cat_tag = cat_name + ";";
+		
+		if ( str != null && str.contains( cat_tag )){
+			
+			return;
+		}
+		
+		try{
+			DeviceMediaRenderer		device 	= (DeviceMediaRenderer)details[0];
+			TranscodeProfile		profile	= (TranscodeProfile)details[1];
+						
+			log( "Category " + cat_name + " - adding " + download.getName() + " to " + device.getName() + "/" + profile.getName());
+			
+			DiskManagerFileInfo[] dm_files = download.getDiskManagerFileInfo();
+			
+			int	num_added = 0;
+			
+			for ( DiskManagerFileInfo dm_file: dm_files ){
+				
+					// limit number of files we can add to avoid crazyness
+				
+				if ( num_added > 64 ){
+					
+					break;
+				}
+				
+					// could be smarter here and check extension or whatever
+				
+				if ( dm_files.length == 1 || dm_file.getLength() >= 128*1024 ){
+					
+					try{
+						queue.add( device, profile, dm_file, false  );
+					
+						num_added++;
+						
+					}catch( Throwable e ){
+						
+						log( "    add failed", e );
+					}
+				}
+			}
+		}finally{
+			
+			download.setAttribute( category_ta, str==null?cat_tag:(str+cat_tag));
+		}
+	}
+	
+	
+	
+	private void
+	checkTags()
+	{
+		TagManager tm = TagManagerFactory.getTagManager();
+		
+		Map<Tag,Object[]> active_map = new HashMap<Tag, Object[]>();
+		
+		for ( TagType tt: tm.getTagTypes()){
+			
+			if ( !tt.hasTagTypeFeature( TagFeature.TF_XCODE )){
+				
+				continue;
+			}
+			
+
+			for ( Tag tag: tt.getTags()){
+			
+				TagFeatureTranscode tfx = (TagFeatureTranscode)tag;
+				
+				if ( !tfx.supportsTagTranscode()){
+					
+					continue;
+				}
+				
+				String[] target_details = tfx.getTagTranscodeTarget();
+				
+				if ( target_details != null ){
+					
+					String	target = target_details[0];
+					
+					String device_id = null;
+					
+					if ( target.endsWith( "/blank" )){
+						
+						device_id = target.substring( 0, target.length() - 6 );
+					}
+					
+					DeviceMediaRenderer		target_dmr			= null;
+					TranscodeProfile		target_profile 		= null;
+					
+					for ( DeviceImpl device: device_manager.getDevices()){
+					
+						if ( !( device instanceof DeviceMediaRenderer )){
+							
+							continue;
+						}
+						
+						DeviceMediaRenderer dmr = (DeviceMediaRenderer)device;
+						
+						if ( device_id != null ){
+							
+							if ( device.getID().equals( device_id )){
+								
+								target_dmr		 	= dmr;
+								target_profile		= device.getBlankProfile();
+								
+								break;
+							}
+						}else{
+							
+							TranscodeProfile[] profs = device.getTranscodeProfiles();
+							
+							for ( TranscodeProfile prof: profs ){
+								
+								if ( prof.getUID().equals( target )){
+									
+									target_dmr	= dmr;
+									target_profile	= prof;
+									
+									break;
+								}
+							}
+						}
+					}
+				
+					if ( target_dmr != null ){
+						
+						active_map.put( tag, new Object[]{ target_dmr, target_profile });					
+					}
+				}
+			}
+		}
+		
+		Map<Tag,Object[]> to_process = new HashMap<Tag, Object[]>();
+		
+		synchronized( tag_map ){
+			
+			if ( tag_listener == null ){
+				
+				tag_listener = 
+					new TagListener()
+					{
+						public void
+						taggableAdded(
+							Tag			tag,
+							Taggable	tagged )
+						{
+							Object[]	details;
+							
+							synchronized( tag_map ){
+
+								details = tag_map.get( tag );
+							}
+							
+							if ( details != null ){
+								
+								processTag( tag, details, (DownloadManager)tagged );
+							}
+						}
+						
+						public void
+						taggableSync(
+							Tag			tag )
+						{
+							
+						}
+						
+						public void
+						taggableRemoved(
+							Tag			tag,
+							Taggable	tagged )
+						{
+							
+						}
+					};
+			}
+			
+			Iterator<Tag>	it = tag_map.keySet().iterator();
+			
+			while( it.hasNext()){
+				
+				Tag t = it.next();
+				
+				if ( !active_map.containsKey( t )){
+					
+					t.removeTagListener( tag_listener );
+					
+					it.remove();
+				}
+			}
+			
+			for ( final Tag tag: active_map.keySet()){
+				
+				if ( !tag_map.containsKey( tag )){
+					
+					to_process.put( tag, active_map.get( tag ));
+					
+					tag.addTagListener( tag_listener, false );
+					
+					tag_map.put( tag, active_map.get( tag ));
+				}
+			}
+		}
+		
+		if ( to_process.size() > 0 ){
+						
+			for ( Map.Entry<Tag, Object[]> entry: to_process.entrySet()){
+				
+				Tag		 	tag 	= entry.getKey();
+				Object[]	details = entry.getValue();
+				
+				Set<DownloadManager> list = ((TagDownload)tag).getTaggedDownloads();
+				
+				for( DownloadManager dm: list ){
+					
+					processTag( tag, details, dm );
+				}
+			}
+		}
+	}
+	
+	
+	
+	private void
+	processTag(
+		Tag				tag,
+		Object[]		details,
+		DownloadManager	dm )
+	{
+		Download download = PluginCoreUtils.wrap( dm );
+		
+		if ( download == null ){
+			
+			return;
+		}
+		
+		if ( download.getFlag( Download.FLAG_LOW_NOISE )){
+			
+			return;
+		}
+		
+		String str = download.getAttribute( tag_ta );
+		
+		String tag_name = tag.getTagName( true );
+		
+		String	tag_tag = tag.getTagType().getTagType() + "." + tag.getTagID() + ";";
+		
+		if ( str != null && str.contains( tag_tag )){
+			
+			return;
+		}
+		
+		try{
+			DeviceMediaRenderer		device 	= (DeviceMediaRenderer)details[0];
+			TranscodeProfile		profile	= (TranscodeProfile)details[1];
+						
+			log( "Tag " + tag_name + " - adding " + download.getName() + " to " + device.getName() + "/" + profile.getName());
+			
+			DiskManagerFileInfo[] dm_files = download.getDiskManagerFileInfo();
+			
+			int	num_added = 0;
+			
+			for ( DiskManagerFileInfo dm_file: dm_files ){
+				
+					// limit number of files we can add to avoid crazyness
+				
+				if ( num_added > 64 ){
+					
+					break;
+				}
+				
+					// could be smarter here and check extension or whatever
+				
+				if ( dm_files.length == 1 || dm_file.getLength() >= 128*1024 ){
+					
+					try{
+						queue.add( device, profile, dm_file, false  );
+					
+						num_added++;
+						
+					}catch( Throwable e ){
+						
+						log( "    add failed", e );
+					}
+				}
+			}
+		}finally{
+			
+			download.setAttribute( tag_ta, str==null?tag_tag:(str+tag_tag));
+		}
+	}
+	
+	public TranscodeProvider[]
+	getProviders()
+	{
+		TranscodeProviderVuze	vp = vuzexcode_provider;
+
+		if ( vp == null ){
+		
+			return( new TranscodeProvider[0] );
+		}
+		
+		return( new TranscodeProvider[]{ vp });
+	}
+	
+	protected TranscodeProvider
+	getProvider(
+		int		p_id )
+	
+		throws TranscodeException
+	{
+		TranscodeProviderVuze	vp = vuzexcode_provider;
+
+		if ( p_id == TranscodeProvider.TP_VUZE && vp != null ){
+			
+			return( vp );
+		}
+		
+		throw( new TranscodeException( "Transcode provider not registered" ));
+	}
+	
+	protected TranscodeProfile
+	getProfileFromUID(
+		String		uid )
+	{
+		for ( TranscodeProvider provider: getProviders()){
+			
+			TranscodeProfile profile = provider.getProfile( uid );
+			
+			if ( profile != null ){
+				
+				return( profile );
+			}
+		}
+		
+		return( null );
+	}
+	
+	public TranscodeQueueImpl
+	getQueue() 
+	{
+		if ( !init_sem.reserve(30*1000)){
+			
+			Debug.out( "Timeout waiting for init" );
+			
+			AEDiagnostics.dumpThreads();
+		}
+		
+		return( queue );
+	}
+	
+	protected DeviceManagerImpl
+	getManager()
+	{
+		return( device_manager );
+	}
+	
+	protected TranscodeTarget
+	lookupTarget(
+		String		target_id )
+	
+		throws TranscodeException
+	{
+		Device device = device_manager.getDevice( target_id );
+		
+		if ( device instanceof TranscodeTarget ){
+			
+			return((TranscodeTarget)device);
+		}
+		
+		throw( new TranscodeException( "Transcode target with id " + target_id + " not found" ));
+	}
+	
+	protected DiskManagerFileInfo
+	lookupFile(
+		byte[]		hash,
+		int			index )
+	
+		throws TranscodeException
+	{
+		try{
+			Download download = PluginInitializer.getDefaultInterface().getDownloadManager().getDownload( hash );
+			
+			if ( download == null ){
+				
+				throw( new TranscodeException( "Download with hash " + ByteFormatter.encodeString( hash ) + " not found" ));
+			}
+		
+			return( download.getDiskManagerFileInfo()[index]);
+			
+		}catch( Throwable e ){
+			
+			throw( new TranscodeException( "Download with hash " + ByteFormatter.encodeString( hash ) + " not found", e ));
+
+		}
+	}
+	
+	protected void
+	close()
+	{
+		queue.close();
+	}
+	
+	public void
+	addListener(
+		TranscodeManagerListener		listener )
+	{
+		listeners.add( listener );
+	}
+	
+	public void
+	removeListener(
+		TranscodeManagerListener		listener )
+	{
+		listeners.remove( listener );
+	}
+	
+	protected void
+	log(
+		String	str )
+	{
+		device_manager.log( "Trans: " + str );
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable	e )
+	{
+		device_manager.log( "Trans: " + str, e );
+	}
+	
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		writer.println( "Transcode Manager: vuze provider=" + vuzexcode_provider );
+		
+		queue.generate( writer );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipe.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipe.java
index 952532e..86d4ddb 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipe.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipe.java
@@ -1,569 +1,568 @@
-/*
- * Created on Feb 12, 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.io.InputStream;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.Average;
-import org.gudy.azureus2.core3.util.Debug;
-
-public abstract class 
-TranscodePipe 
-{
-	private final int BUFFER_SIZE 		= 128*1024;
-	private final int BUFFER_CACHE_SIZE	= BUFFER_SIZE*3;
-	
-	protected volatile boolean	paused;
-	protected volatile boolean	destroyed;
-
-	protected volatile int		bytes_available;
-	protected volatile int		max_bytes_per_sec;
-
-	protected List<Socket>		sockets 		= new ArrayList<Socket>();
-
-	private ServerSocket		server_socket;
-	private AEThread2			refiller;
-
-	private LinkedList<bufferCache>		buffer_cache = new LinkedList<bufferCache>();
-	private int							buffer_cache_size;
-	
-	private Average 	connection_speed 	= Average.getInstance(1000, 10);  //average over 10s, update every 1000ms
-	private Average 	write_speed 		= Average.getInstance(1000, 10);  //average over 10s, update every 1000ms
-
-	private errorListener		error_listener;
-	
-	protected
-	TranscodePipe(
-		errorListener		_error_listener )
-	
-		throws IOException
-	{
-		error_listener	= _error_listener;
-		
-		server_socket = new ServerSocket( 0, 50, InetAddress.getByName( "127.0.0.1" ));
-		
-		new AEThread2( "TranscodePipe", true )
-		{
-			public void
-			run()
-			{
-				while( !destroyed ){
-					
-					try{
-						final Socket	socket = server_socket.accept();
-						
-						connection_speed.addValue( 1 );
-						
-						new AEThread2( "TranscodePipe", true )
-						{
-							public void
-							run()
-							{
-								handleSocket( socket );
-							}
-						}.start();
-						
-					}catch( Throwable e ){
-						
-						if ( !destroyed ){
-												
-							destroy();
-						}
-						
-						break;
-					}
-				}
-			}
-		}.start();
-	}
-
-	public long
-	getConnectionRate()
-	{
-		return( connection_speed.getAverage());
-	}
-	
-	public long
-	getWriteSpeed()
-	{
-		return(write_speed.getAverage());
-	}
-	
-	protected abstract void
-	handleSocket(
-		Socket		socket );
-	
-	protected void
-	handlePipe(
-		final InputStream		is,
-		final OutputStream		os )
-	{
-		new AEThread2( "TranscodePipe:c", true )
-		{
-			public void
-			run()
-			{
-				final int BUFFER_SIZE = 128*1024;
-				
-				byte[]	buffer = new byte[ BUFFER_SIZE ];
-
-				while( !destroyed ){
-					
-					try{							
-						int	limit;
-
-						if ( paused ){
-							
-							Thread.sleep(250);
-							
-							limit = 1;
-							
-						}else{
-													
-							if ( max_bytes_per_sec > 0 ){
-								
-								limit = bytes_available;
-								
-								if ( limit <= 0 ){
-									
-									Thread.sleep( 25 );
-									
-									continue;
-								}
-								
-								limit = Math.min( BUFFER_SIZE, limit );
-								
-							}else{
-								
-								limit = BUFFER_SIZE;
-							}
-						}
-						
-						int len =  is.read( buffer, 0, limit );
-							
-						if ( len <= 0 ){
-								
-							break;
-						}
-							
-						if ( max_bytes_per_sec > 0 ){
-						
-							bytes_available -= len;
-						}
-						
-						os.write( buffer, 0, len );						
-						
-						write_speed.addValue( len );
-						
-					}catch( Throwable e ){
-						
-						break;
-					}
-				}
-				
-				try{
-					os.flush();
-					
-				}catch( Throwable e ){
-				}
-				
-				try{
-					is.close();
-					
-				}catch( Throwable e ){
-				}
-				
-				try{
-					os.close();
-					
-				}catch( Throwable e ){
-				}
-			}
-		}.start();
-	}
-	
-	protected RandomAccessFile
-	reserveRAF()
-	
-		throws IOException
-	{
-		throw( new IOException( "Not implemented" ));
-	}
-	
-	protected void
-	releaseRAF(
-		RandomAccessFile		raf )
-	{
-	}
-	
-	protected void
-	handleRAF(
-		final OutputStream		os,
-		final long				position,
-		final long				length )
-	{
-		new AEThread2( "TranscodePipe:c", true )
-		{
-			public void
-			run()
-			{
-				RandomAccessFile	raf = null;
-				
-				try{
-					raf = reserveRAF();
-
-					long	pos	= position;
-					
-					long	rem = length;
-					
-					while( !destroyed && rem > 0){
-																	
-						int	limit;
-
-						if ( paused ){
-							
-							Thread.sleep(250);
-							
-							limit = 1;
-							
-						}else{
-													
-							if ( max_bytes_per_sec > 0 ){
-								
-								limit = bytes_available;
-								
-								if ( limit <= 0 ){
-									
-									Thread.sleep( 25 );
-									
-									continue;
-								}
-								
-								limit = Math.min( BUFFER_SIZE, limit );
-								
-							}else{
-								
-								limit = BUFFER_SIZE;
-							}
-							
-							limit = (int)Math.min( rem, limit );
-						}
-						
-						int	read_length	= 0;
-						
-						int		buffer_start 	= 0;
-						byte[] 	buffer			= null;
-						
-						synchronized( TranscodePipe.this ){
-						
-							int	c_num = 0;
-							
-							Iterator<bufferCache> it = buffer_cache.iterator();
-							
-							while( it.hasNext()){
-								
-								bufferCache b = it.next();
-								
-								long	rel_offset = pos - b.offset;
-								
-								if ( rel_offset >= 0 ){
-									
-									byte[] 	data = b.data;
-									
-									long avail = data.length - rel_offset;
-									
-									if ( avail > 0 ){
-										
-										read_length = (int)Math.min( avail, limit );
-										
-										buffer 			= data;
-										buffer_start 	= (int)rel_offset;
-										
-										//System.out.println( "using cache entry: o_offset=" + pos + ",r_offset=" + rel_offset+",len=" + read_length );
-										
-										if ( c_num > 0 ){
-										
-											it.remove();
-										
-											buffer_cache.addFirst( b );
-										}
-										
-										break;
-									}
-								}
-								
-								c_num++;
-							}
-							
-							if ( buffer == null ){
-							
-								buffer = new byte[ limit ];
-
-								raf.seek( pos );
-							
-								read_length =  raf.read( buffer );
-								
-								if ( read_length != limit ){
-									
-									Debug.out( "eh?");
-									
-									throw( new IOException( "Inconsistent" ));
-								}
-								
-								bufferCache b = new bufferCache( pos, buffer );
-								
-								// System.out.println( "adding to cache: o_offset=" + pos + ", size=" + limit );
-								
-								buffer_cache.addFirst( b );
-								
-								buffer_cache_size += limit;
-								
-								while( buffer_cache_size > BUFFER_CACHE_SIZE ){
-									
-									b = buffer_cache.removeLast();
-									
-									buffer_cache_size -= b.data.length;
-								}
-							}
-						}
-							
-						if ( read_length <= 0 ){
-								
-							break;
-						}
-							
-						rem -= read_length;
-						pos += read_length;
-						
-						if ( max_bytes_per_sec > 0 ){
-						
-							bytes_available -= read_length;
-						}
-						
-						os.write( buffer, buffer_start, read_length );		
-						
-						write_speed.addValue( read_length );
-					}
-					
-					os.flush();
-					
-				}catch( Throwable e ){
-				
-					if ( raf != null ){
-						
-						try{
-							synchronized( TranscodePipe.this ){
-
-								raf.seek( 0 );
-							
-								raf.read( new byte[1] );
-							}
-						}catch( Throwable f ){
-							
-							reportError( e );
-						}
-					}			
-				}finally{
-					
-					try{
-						os.close();
-						
-					}catch( Throwable e ){
-					}
-					
-					if ( raf != null ){
-						
-						releaseRAF( raf );
-					}
-				}
-			}
-		}.start();
-	}
-	
-	protected void
-	pause()
-	{
-		paused = true;
-	}
-
-	protected void
-	resume()
-	{
-		paused = false;
-	}
-	
-	public void 
-	setMaxBytesPerSecond(
-		int		 max ) 
-	{
-		if ( max == max_bytes_per_sec ){
-			
-			return;
-		}
-		
-		max_bytes_per_sec = max;
-		
-		synchronized( this ){
-			
-			if ( refiller == null  ){
-				
-				refiller = 
-					new AEThread2( "refiller", true )
-					{
-						public void 
-						run() 
-						{
-							int	count = 0;
-							
-							while( !destroyed ){
-								
-								if ( max_bytes_per_sec == 0 ){
-									
-									synchronized( TranscodePipe.this ){
-										
-										if ( max_bytes_per_sec == 0 ){
-										
-											refiller = null;
-										
-											break;
-										}
-									}
-								}
-								
-								count++;
-								
-								bytes_available += max_bytes_per_sec/10;
-								
-								if ( count%10 == 0 ){
-									
-									bytes_available += max_bytes_per_sec%10;
-								}
-								
-								try{
-									Thread.sleep(100);
-									
-								}catch( Throwable e ){
-									
-									Debug.printStackTrace(e);
-									
-									break;
-								}
-							}
-						}
-					};
-					
-				refiller.start();
-			}
-		}
-	}
-	
-	protected int
-	getPort()
-	{
-		return( server_socket.getLocalPort());
-	}
-	
-	protected boolean
-	destroy()
-	{
-		synchronized( this ){
-			
-			if ( destroyed ){
-				
-				return( false );
-			}
-			
-			destroyed	= true;
-		}
-
-		for (Socket s: sockets ){
-			
-			try{			
-				s.close();
-				
-			}catch( Throwable e ){	
-			}
-		}
-		
-		sockets.clear();
-		
-		try{
-			server_socket.close();
-			
-		}catch( Throwable e ){
-		
-			Debug.printStackTrace(e);
-		}
-		
-		return( true );
-	}
-	
-	protected void
-	reportError(
-		Throwable 	error )
-	{
-		if ( error_listener != null ){
-			
-			error_listener.error( error );
-			
-		}else{
-			
-			Debug.out( error );
-		}
-	}
-	
-	private class
-	bufferCache
-	{
-		private long	offset;
-		private byte[]	data;
-		
-		protected
-		bufferCache(
-			long		_offset,
-			byte[]		_data )
-		{
-			offset	= _offset;
-			data	= _data;
-		}
-	}
-	
-	
-	protected interface
-	errorListener
-	{
-		public void
-		error(
-			Throwable e );
-	}
-}
+/*
+ * Created on Feb 12, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.Average;
+import org.gudy.azureus2.core3.util.Debug;
+
+public abstract class 
+TranscodePipe 
+{
+	private final int BUFFER_SIZE 		= 128*1024;
+	private final int BUFFER_CACHE_SIZE	= BUFFER_SIZE*3;
+	
+	protected volatile boolean	paused;
+	protected volatile boolean	destroyed;
+
+	protected volatile int		bytes_available;
+	protected volatile int		max_bytes_per_sec;
+
+	protected List<Socket>		sockets 		= new ArrayList<Socket>();
+
+	private ServerSocket		server_socket;
+	private AEThread2			refiller;
+
+	private LinkedList<bufferCache>		buffer_cache = new LinkedList<bufferCache>();
+	private int							buffer_cache_size;
+	
+	private Average 	connection_speed 	= Average.getInstance(1000, 10);  //average over 10s, update every 1000ms
+	private Average 	write_speed 		= Average.getInstance(1000, 10);  //average over 10s, update every 1000ms
+
+	private errorListener		error_listener;
+	
+	protected
+	TranscodePipe(
+		errorListener		_error_listener )
+	
+		throws IOException
+	{
+		error_listener	= _error_listener;
+		
+		server_socket = new ServerSocket( 0, 50, InetAddress.getByName( "127.0.0.1" ));
+		
+		new AEThread2( "TranscodePipe", true )
+		{
+			public void
+			run()
+			{
+				while( !destroyed ){
+					
+					try{
+						final Socket	socket = server_socket.accept();
+						
+						connection_speed.addValue( 1 );
+						
+						new AEThread2( "TranscodePipe", true )
+						{
+							public void
+							run()
+							{
+								handleSocket( socket );
+							}
+						}.start();
+						
+					}catch( Throwable e ){
+						
+						if ( !destroyed ){
+												
+							destroy();
+						}
+						
+						break;
+					}
+				}
+			}
+		}.start();
+	}
+
+	public long
+	getConnectionRate()
+	{
+		return( connection_speed.getAverage());
+	}
+	
+	public long
+	getWriteSpeed()
+	{
+		return(write_speed.getAverage());
+	}
+	
+	protected abstract void
+	handleSocket(
+		Socket		socket );
+	
+	protected void
+	handlePipe(
+		final InputStream		is,
+		final OutputStream		os )
+	{
+		new AEThread2( "TranscodePipe:c", true )
+		{
+			public void
+			run()
+			{
+				final int BUFFER_SIZE = 128*1024;
+				
+				byte[]	buffer = new byte[ BUFFER_SIZE ];
+
+				while( !destroyed ){
+					
+					try{							
+						int	limit;
+
+						if ( paused ){
+							
+							Thread.sleep(250);
+							
+							limit = 1;
+							
+						}else{
+													
+							if ( max_bytes_per_sec > 0 ){
+								
+								limit = bytes_available;
+								
+								if ( limit <= 0 ){
+									
+									Thread.sleep( 25 );
+									
+									continue;
+								}
+								
+								limit = Math.min( BUFFER_SIZE, limit );
+								
+							}else{
+								
+								limit = BUFFER_SIZE;
+							}
+						}
+						
+						int len =  is.read( buffer, 0, limit );
+							
+						if ( len <= 0 ){
+								
+							break;
+						}
+							
+						if ( max_bytes_per_sec > 0 ){
+						
+							bytes_available -= len;
+						}
+						
+						os.write( buffer, 0, len );						
+						
+						write_speed.addValue( len );
+						
+					}catch( Throwable e ){
+						
+						break;
+					}
+				}
+				
+				try{
+					os.flush();
+					
+				}catch( Throwable e ){
+				}
+				
+				try{
+					is.close();
+					
+				}catch( Throwable e ){
+				}
+				
+				try{
+					os.close();
+					
+				}catch( Throwable e ){
+				}
+			}
+		}.start();
+	}
+	
+	protected RandomAccessFile
+	reserveRAF()
+	
+		throws IOException
+	{
+		throw( new IOException( "Not implemented" ));
+	}
+	
+	protected void
+	releaseRAF(
+		RandomAccessFile		raf )
+	{
+	}
+	
+	protected void
+	handleRAF(
+		final OutputStream		os,
+		final long				position,
+		final long				length )
+	{
+		new AEThread2( "TranscodePipe:c", true )
+		{
+			public void
+			run()
+			{
+				RandomAccessFile	raf = null;
+				
+				try{
+					raf = reserveRAF();
+
+					long	pos	= position;
+					
+					long	rem = length;
+					
+					while( !destroyed && rem > 0){
+																	
+						int	limit;
+
+						if ( paused ){
+							
+							Thread.sleep(250);
+							
+							limit = 1;
+							
+						}else{
+													
+							if ( max_bytes_per_sec > 0 ){
+								
+								limit = bytes_available;
+								
+								if ( limit <= 0 ){
+									
+									Thread.sleep( 25 );
+									
+									continue;
+								}
+								
+								limit = Math.min( BUFFER_SIZE, limit );
+								
+							}else{
+								
+								limit = BUFFER_SIZE;
+							}
+							
+							limit = (int)Math.min( rem, limit );
+						}
+						
+						int	read_length	= 0;
+						
+						int		buffer_start 	= 0;
+						byte[] 	buffer			= null;
+						
+						synchronized( TranscodePipe.this ){
+						
+							int	c_num = 0;
+							
+							Iterator<bufferCache> it = buffer_cache.iterator();
+							
+							while( it.hasNext()){
+								
+								bufferCache b = it.next();
+								
+								long	rel_offset = pos - b.offset;
+								
+								if ( rel_offset >= 0 ){
+									
+									byte[] 	data = b.data;
+									
+									long avail = data.length - rel_offset;
+									
+									if ( avail > 0 ){
+										
+										read_length = (int)Math.min( avail, limit );
+										
+										buffer 			= data;
+										buffer_start 	= (int)rel_offset;
+										
+										//System.out.println( "using cache entry: o_offset=" + pos + ",r_offset=" + rel_offset+",len=" + read_length );
+										
+										if ( c_num > 0 ){
+										
+											it.remove();
+										
+											buffer_cache.addFirst( b );
+										}
+										
+										break;
+									}
+								}
+								
+								c_num++;
+							}
+							
+							if ( buffer == null ){
+							
+								buffer = new byte[ limit ];
+
+								raf.seek( pos );
+							
+								read_length =  raf.read( buffer );
+								
+								if ( read_length != limit ){
+									
+									Debug.out( "eh?");
+									
+									throw( new IOException( "Inconsistent" ));
+								}
+								
+								bufferCache b = new bufferCache( pos, buffer );
+								
+								// System.out.println( "adding to cache: o_offset=" + pos + ", size=" + limit );
+								
+								buffer_cache.addFirst( b );
+								
+								buffer_cache_size += limit;
+								
+								while( buffer_cache_size > BUFFER_CACHE_SIZE ){
+									
+									b = buffer_cache.removeLast();
+									
+									buffer_cache_size -= b.data.length;
+								}
+							}
+						}
+							
+						if ( read_length <= 0 ){
+								
+							break;
+						}
+							
+						rem -= read_length;
+						pos += read_length;
+						
+						if ( max_bytes_per_sec > 0 ){
+						
+							bytes_available -= read_length;
+						}
+						
+						os.write( buffer, buffer_start, read_length );		
+						
+						write_speed.addValue( read_length );
+					}
+					
+					os.flush();
+					
+				}catch( Throwable e ){
+				
+					if ( raf != null ){
+						
+						try{
+							synchronized( TranscodePipe.this ){
+
+								raf.seek( 0 );
+							
+								raf.read( new byte[1] );
+							}
+						}catch( Throwable f ){
+							
+							reportError( e );
+						}
+					}			
+				}finally{
+					
+					try{
+						os.close();
+						
+					}catch( Throwable e ){
+					}
+					
+					if ( raf != null ){
+						
+						releaseRAF( raf );
+					}
+				}
+			}
+		}.start();
+	}
+	
+	protected void
+	pause()
+	{
+		paused = true;
+	}
+
+	protected void
+	resume()
+	{
+		paused = false;
+	}
+	
+	public void 
+	setMaxBytesPerSecond(
+		int		 max ) 
+	{
+		if ( max == max_bytes_per_sec ){
+			
+			return;
+		}
+		
+		max_bytes_per_sec = max;
+		
+		synchronized( this ){
+			
+			if ( refiller == null  ){
+				
+				refiller = 
+					new AEThread2( "refiller", true )
+					{
+						public void 
+						run() 
+						{
+							int	count = 0;
+							
+							while( !destroyed ){
+								
+								if ( max_bytes_per_sec == 0 ){
+									
+									synchronized( TranscodePipe.this ){
+										
+										if ( max_bytes_per_sec == 0 ){
+										
+											refiller = null;
+										
+											break;
+										}
+									}
+								}
+								
+								count++;
+								
+								bytes_available += max_bytes_per_sec/10;
+								
+								if ( count%10 == 0 ){
+									
+									bytes_available += max_bytes_per_sec%10;
+								}
+								
+								try{
+									Thread.sleep(100);
+									
+								}catch( Throwable e ){
+									
+									Debug.printStackTrace(e);
+									
+									break;
+								}
+							}
+						}
+					};
+					
+				refiller.start();
+			}
+		}
+	}
+	
+	protected int
+	getPort()
+	{
+		return( server_socket.getLocalPort());
+	}
+	
+	protected boolean
+	destroy()
+	{
+		synchronized( this ){
+			
+			if ( destroyed ){
+				
+				return( false );
+			}
+			
+			destroyed	= true;
+		}
+
+		for (Socket s: sockets ){
+			
+			try{			
+				s.close();
+				
+			}catch( Throwable e ){	
+			}
+		}
+		
+		sockets.clear();
+		
+		try{
+			server_socket.close();
+			
+		}catch( Throwable e ){
+		
+			Debug.printStackTrace(e);
+		}
+		
+		return( true );
+	}
+	
+	protected void
+	reportError(
+		Throwable 	error )
+	{
+		if ( error_listener != null ){
+			
+			error_listener.error( error );
+			
+		}else{
+			
+			Debug.out( error );
+		}
+	}
+	
+	private class
+	bufferCache
+	{
+		private long	offset;
+		private byte[]	data;
+		
+		protected
+		bufferCache(
+			long		_offset,
+			byte[]		_data )
+		{
+			offset	= _offset;
+			data	= _data;
+		}
+	}
+	
+	
+	protected interface
+	errorListener
+	{
+		public void
+		error(
+			Throwable e );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeFileSource.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeFileSource.java
index 0089156..ecdbaea 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeFileSource.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeFileSource.java
@@ -1,369 +1,368 @@
-/*
- * Created on Feb 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.devices.impl;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.net.Socket;
-import java.util.*;
-
-public class 
-TranscodePipeFileSource 
-	extends TranscodePipe
-{
-	private static final String NL = "\r\n";
-	
-	private File		source_file;
-	
-	private RandomAccessFile	raf;
-	private int					raf_count;
-		
-	protected
-	TranscodePipeFileSource(
-		File			_source_file,
-		errorListener	_error_listener )
-	
-		throws IOException
-	{
-		super( _error_listener );
-		
-		source_file	= _source_file;
-	}		
-
-	
-	protected void
-	handleSocket(
-		Socket		socket )
-	{
-		synchronized( this ){
-			
-			if ( destroyed ){
-				
-				try{
-					socket.close();
-					
-				}catch( Throwable e ){				
-				}
-				
-				return;
-			}
-			
-			sockets.add( socket );
-		}
-
-		try{
-			String	command	= null;
-			Map<String,String>		headers	= new HashMap<String, String>();
-
-			InputStream		is = socket.getInputStream();
-			OutputStream	os = socket.getOutputStream();
-			
-			while( true ){
-
-				String	line = "";
-			
-				while( !line.endsWith( NL )){
-					
-					byte[]	buffer = new byte[1];
-					
-					if ( is.read( buffer ) <= 0 ){
-						
-						throw( new IOException( "unexpected end of stream" ));
-					}
-					
-					line += new String( buffer );
-				}
-			
-				line = line.trim();
-				
-				if ( line.length() == 0 ){
-					
-					break;
-				}
-				
-				if ( command == null ){
-					
-					command	= line;
-					
-				}else{
-					
-					int	pos = line.indexOf(':');
-					
-					if ( pos == -1 ){
-						
-						return;
-					}
-					
-					String	lhs = line.substring(0,pos).trim().toLowerCase();
-					String	rhs = line.substring(pos+1).trim();
-					
-					headers.put( lhs, rhs );
-				}
-			}
-						
-			boolean	head	= false;
-			
-			//System.out.println( command + ": " + headers );
-			
-			if ( command == null ){
-				
-				throw( new IOException( "no method supplied" ));
-				
-			}else if ( command.startsWith( "GET " )){
-				
-			}else if ( command.startsWith( "HEAD " )){
-								
-				head	= true;
-				
-			}else{
-				
-				throw( new IOException( "unsupported method '" + command + "'" ));
-			}
-			
-			long	file_length = source_file.length();
-						
-			if ( head ){
-							
-				write( os, "HTTP/1.1 200 OK" + NL );
-				write( os, "Server: Azureus Media Server 1.0" + NL ); 
-				write( os, "Accept-Ranges: bytes" + NL );
-				write( os, "Content-Length: " + file_length + NL );
-				write( os, "Content-Range: 0-" + (file_length-1) + "/" + file_length + NL );
-
-				os.flush();
-
-			}else{
-				
-				String	ranges = (String)headers.get( "range" );
-					
-				long	request_start		= 0;
-				long	request_length		= 0;
-				
-				boolean	request_ok = false;
-				
-				if ( ranges == null ){
-										
-					write( os, "HTTP/1.1 200 OK" + NL );
-					write( os, "Server: Azureus Media Server 1.0" + NL ); 
-					write( os, "Connection: close" + NL );
-					write( os, "Accept-Ranges: bytes" + NL );
-					write( os, "Content-Range: 0-" + (file_length-1) + "/" + file_length + NL );
-					write( os, "Content-Length: " + file_length + NL + NL );
-					
-					request_length	= file_length;
-					
-					request_ok = true;
-					
-				}else{
-										
-					ranges = ranges.toLowerCase();
-					
-					if ( !ranges.startsWith("bytes=")){
-						
-						throw( new IOException( "invalid range: " + ranges ));
-					}
-					
-					ranges = ranges.substring( 6 );
-					
-					StringTokenizer	tok = new StringTokenizer( ranges, "," );
-					
-					if ( tok.countTokens() != 1 ){
-						
-						throw( new IOException( "invalid range - only single supported: " + ranges ));
-					}
-					
-					String	range = tok.nextToken();
-					
-					int pos	= range.indexOf('-');
-					
-					long	start;
-					long	end;
-																	
-					if ( pos < range.length()-1 ){
-						
-						end = Long.parseLong( range.substring(pos+1));
-						
-					}else{
-						
-						end = file_length-1;
-					}
-					
-					if ( pos > 0 ){
-						
-						start = Long.parseLong( range.substring(0,pos));
-						
-					}else{
-							// -500 = last 500 bytes of file
-						
-						start 	= file_length-end;
-						end		= file_length-1;
-					}
-	
-					request_length = ( end - start ) + 1;
-					
-						// prevent seeking too far
-					
-					if ( request_length < 0 ){
-						
-						write( os, "HTTP/1.1 416 Requested Range Not Satisfiable" + NL + NL );
-						
-					}else{		
-							
-						request_start	= start;
-						
-						write(  os, "HTTP/1.1 206 Partial content" + NL );
-							
-								
-						write(  os, "Server: Azureus Media Server 1.0" + NL ); 
-						write(  os, "Connection: close" + NL );					
-						write(  os, "Content-Range: bytes " + start + "-" + end + "/" + file_length + NL );
-						write(  os, "Content-Length: " + request_length + NL + NL );
-						
-						request_ok = true;
-					}
-				}
-					
-				os.flush();
-
-				if ( request_ok ){
-				
-					handleRAF( os, request_start, request_length );
-				}
-			}
-			
-			synchronized( this ){
-
-				if ( destroyed ){
-					
-					try{
-						socket.close();
-						
-					}catch( Throwable e ){				
-					}
-					
-					try{
-						is.close();
-						
-					}catch( Throwable e ){				
-					}
-					
-					sockets.remove( socket );
-					
-					return;
-				}
-			}			
-		}catch( Throwable e ){
-			
-			try{
-				socket.close();
-				
-			}catch( Throwable f ){
-			}
-			
-			synchronized( this ){
-
-				sockets.remove( socket );
-			}
-		}
-	}
-	
-	protected void
-	write(
-		OutputStream	os,
-		String			str )
-	
-		throws IOException
-	{
-		os.write( str.getBytes());
-	}
-	
-	@Override
-	protected RandomAccessFile
-	reserveRAF()
-	
-		throws IOException
-	{
-		synchronized( this ){
-			
-			if ( destroyed ){
-				
-				throw( new IOException( "destroyed" ));
-			}
-			
-			if ( raf == null ){
-						
-				raf = new RandomAccessFile( source_file, "r" );
-			}
-			
-			raf_count++;
-			
-			return( raf );
-		}
-	}
-	
-	@Override
-	protected void
-	releaseRAF(
-		RandomAccessFile	_raf )
-	{
-		synchronized( this ){
-
-			raf_count--;
-			
-			if ( raf_count == 0 ){
-				
-				try{
-					raf.close();
-					
-				}catch( Throwable e ){
-				}
-				
-				raf = null;
-			}
-		}
-	}
-	
-	protected boolean
-	destroy()
-	{
-		if ( super.destroy()){
-			
-			if ( raf != null ){	
-				
-				try{				
-					raf.close();
-					
-				}catch( Throwable e ){	
-				}
-				
-				raf = null;
-			}
-					
-			return( true );
-		}
-		
-		return( false );
-	}
-}
+/*
+ * Created on Feb 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.net.Socket;
+import java.util.*;
+
+public class 
+TranscodePipeFileSource 
+	extends TranscodePipe
+{
+	private static final String NL = "\r\n";
+	
+	private File		source_file;
+	
+	private RandomAccessFile	raf;
+	private int					raf_count;
+		
+	protected
+	TranscodePipeFileSource(
+		File			_source_file,
+		errorListener	_error_listener )
+	
+		throws IOException
+	{
+		super( _error_listener );
+		
+		source_file	= _source_file;
+	}		
+
+	
+	protected void
+	handleSocket(
+		Socket		socket )
+	{
+		synchronized( this ){
+			
+			if ( destroyed ){
+				
+				try{
+					socket.close();
+					
+				}catch( Throwable e ){				
+				}
+				
+				return;
+			}
+			
+			sockets.add( socket );
+		}
+
+		try{
+			String	command	= null;
+			Map<String,String>		headers	= new HashMap<String, String>();
+
+			InputStream		is = socket.getInputStream();
+			OutputStream	os = socket.getOutputStream();
+			
+			while( true ){
+
+				String	line = "";
+			
+				while( !line.endsWith( NL )){
+					
+					byte[]	buffer = new byte[1];
+					
+					if ( is.read( buffer ) <= 0 ){
+						
+						throw( new IOException( "unexpected end of stream" ));
+					}
+					
+					line += new String( buffer );
+				}
+			
+				line = line.trim();
+				
+				if ( line.length() == 0 ){
+					
+					break;
+				}
+				
+				if ( command == null ){
+					
+					command	= line;
+					
+				}else{
+					
+					int	pos = line.indexOf(':');
+					
+					if ( pos == -1 ){
+						
+						return;
+					}
+					
+					String	lhs = line.substring(0,pos).trim().toLowerCase();
+					String	rhs = line.substring(pos+1).trim();
+					
+					headers.put( lhs, rhs );
+				}
+			}
+						
+			boolean	head	= false;
+			
+			//System.out.println( command + ": " + headers );
+			
+			if ( command == null ){
+				
+				throw( new IOException( "no method supplied" ));
+				
+			}else if ( command.startsWith( "GET " )){
+				
+			}else if ( command.startsWith( "HEAD " )){
+								
+				head	= true;
+				
+			}else{
+				
+				throw( new IOException( "unsupported method '" + command + "'" ));
+			}
+			
+			long	file_length = source_file.length();
+						
+			if ( head ){
+							
+				write( os, "HTTP/1.1 200 OK" + NL );
+				write( os, "Server: Azureus Media Server 1.0" + NL ); 
+				write( os, "Accept-Ranges: bytes" + NL );
+				write( os, "Content-Length: " + file_length + NL );
+				write( os, "Content-Range: 0-" + (file_length-1) + "/" + file_length + NL );
+
+				os.flush();
+
+			}else{
+				
+				String	ranges = (String)headers.get( "range" );
+					
+				long	request_start		= 0;
+				long	request_length		= 0;
+				
+				boolean	request_ok = false;
+				
+				if ( ranges == null ){
+										
+					write( os, "HTTP/1.1 200 OK" + NL );
+					write( os, "Server: Azureus Media Server 1.0" + NL ); 
+					write( os, "Connection: close" + NL );
+					write( os, "Accept-Ranges: bytes" + NL );
+					write( os, "Content-Range: 0-" + (file_length-1) + "/" + file_length + NL );
+					write( os, "Content-Length: " + file_length + NL + NL );
+					
+					request_length	= file_length;
+					
+					request_ok = true;
+					
+				}else{
+										
+					ranges = ranges.toLowerCase();
+					
+					if ( !ranges.startsWith("bytes=")){
+						
+						throw( new IOException( "invalid range: " + ranges ));
+					}
+					
+					ranges = ranges.substring( 6 );
+					
+					StringTokenizer	tok = new StringTokenizer( ranges, "," );
+					
+					if ( tok.countTokens() != 1 ){
+						
+						throw( new IOException( "invalid range - only single supported: " + ranges ));
+					}
+					
+					String	range = tok.nextToken();
+					
+					int pos	= range.indexOf('-');
+					
+					long	start;
+					long	end;
+																	
+					if ( pos < range.length()-1 ){
+						
+						end = Long.parseLong( range.substring(pos+1));
+						
+					}else{
+						
+						end = file_length-1;
+					}
+					
+					if ( pos > 0 ){
+						
+						start = Long.parseLong( range.substring(0,pos));
+						
+					}else{
+							// -500 = last 500 bytes of file
+						
+						start 	= file_length-end;
+						end		= file_length-1;
+					}
+	
+					request_length = ( end - start ) + 1;
+					
+						// prevent seeking too far
+					
+					if ( request_length < 0 ){
+						
+						write( os, "HTTP/1.1 416 Requested Range Not Satisfiable" + NL + NL );
+						
+					}else{		
+							
+						request_start	= start;
+						
+						write(  os, "HTTP/1.1 206 Partial content" + NL );
+							
+								
+						write(  os, "Server: Azureus Media Server 1.0" + NL ); 
+						write(  os, "Connection: close" + NL );					
+						write(  os, "Content-Range: bytes " + start + "-" + end + "/" + file_length + NL );
+						write(  os, "Content-Length: " + request_length + NL + NL );
+						
+						request_ok = true;
+					}
+				}
+					
+				os.flush();
+
+				if ( request_ok ){
+				
+					handleRAF( os, request_start, request_length );
+				}
+			}
+			
+			synchronized( this ){
+
+				if ( destroyed ){
+					
+					try{
+						socket.close();
+						
+					}catch( Throwable e ){				
+					}
+					
+					try{
+						is.close();
+						
+					}catch( Throwable e ){				
+					}
+					
+					sockets.remove( socket );
+					
+					return;
+				}
+			}			
+		}catch( Throwable e ){
+			
+			try{
+				socket.close();
+				
+			}catch( Throwable f ){
+			}
+			
+			synchronized( this ){
+
+				sockets.remove( socket );
+			}
+		}
+	}
+	
+	protected void
+	write(
+		OutputStream	os,
+		String			str )
+	
+		throws IOException
+	{
+		os.write( str.getBytes());
+	}
+	
+	@Override
+	protected RandomAccessFile
+	reserveRAF()
+	
+		throws IOException
+	{
+		synchronized( this ){
+			
+			if ( destroyed ){
+				
+				throw( new IOException( "destroyed" ));
+			}
+			
+			if ( raf == null ){
+						
+				raf = new RandomAccessFile( source_file, "r" );
+			}
+			
+			raf_count++;
+			
+			return( raf );
+		}
+	}
+	
+	@Override
+	protected void
+	releaseRAF(
+		RandomAccessFile	_raf )
+	{
+		synchronized( this ){
+
+			raf_count--;
+			
+			if ( raf_count == 0 ){
+				
+				try{
+					raf.close();
+					
+				}catch( Throwable e ){
+				}
+				
+				raf = null;
+			}
+		}
+	}
+	
+	protected boolean
+	destroy()
+	{
+		if ( super.destroy()){
+			
+			if ( raf != null ){	
+				
+				try{				
+					raf.close();
+					
+				}catch( Throwable e ){	
+				}
+				
+				raf = null;
+			}
+					
+			return( true );
+		}
+		
+		return( false );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeStreamSource.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeStreamSource.java
index 1f62924..736b395 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeStreamSource.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeStreamSource.java
@@ -1,114 +1,113 @@
-/*
- * Created on Feb 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.devices.impl;
-
-import java.io.IOException;
-import java.net.Socket;
-
-
-public class 
-TranscodePipeStreamSource 
-	extends TranscodePipe
-{
-	private String			source_host;
-	private int				source_port;
-		
-	protected
-	TranscodePipeStreamSource(
-		String	_source_host,
-		int		_source_port )
-	
-		throws IOException
-	{
-		super( null );
-		
-		source_host	= _source_host;
-		source_port	= _source_port;
-	}		
-
-	
-	protected void
-	handleSocket(
-		Socket		socket1 )
-	{
-		synchronized( this ){
-			
-			if ( destroyed ){
-				
-				try{
-					socket1.close();
-					
-				}catch( Throwable e ){				
-				}
-				
-				return;
-			}
-			
-			sockets.add( socket1 );
-		}
-
-		try{
-			Socket socket2 = new Socket( source_host, source_port );
-	
-			synchronized( this ){
-
-				if ( destroyed ){
-					
-					try{
-						socket1.close();
-						
-					}catch( Throwable e ){				
-					}
-					
-					try{
-						socket2.close();
-						
-					}catch( Throwable e ){				
-					}
-					
-					sockets.remove( socket1 );
-					
-					return;
-				}
-				
-				sockets.add( socket2 );
-			}
-			
-			handlePipe( socket1.getInputStream(), socket2.getOutputStream());
-			
-			handlePipe( socket2.getInputStream(), socket1.getOutputStream());
-			
-		}catch( Throwable e ){
-			
-			try{
-				socket1.close();
-				
-			}catch( Throwable f ){
-			}
-			
-			synchronized( this ){
-
-				sockets.remove( socket1 );
-			}
-		}
-	}
-}
+/*
+ * Created on Feb 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.IOException;
+import java.net.Socket;
+
+
+public class 
+TranscodePipeStreamSource 
+	extends TranscodePipe
+{
+	private String			source_host;
+	private int				source_port;
+		
+	protected
+	TranscodePipeStreamSource(
+		String	_source_host,
+		int		_source_port )
+	
+		throws IOException
+	{
+		super( null );
+		
+		source_host	= _source_host;
+		source_port	= _source_port;
+	}		
+
+	
+	protected void
+	handleSocket(
+		Socket		socket1 )
+	{
+		synchronized( this ){
+			
+			if ( destroyed ){
+				
+				try{
+					socket1.close();
+					
+				}catch( Throwable e ){				
+				}
+				
+				return;
+			}
+			
+			sockets.add( socket1 );
+		}
+
+		try{
+			Socket socket2 = new Socket( source_host, source_port );
+	
+			synchronized( this ){
+
+				if ( destroyed ){
+					
+					try{
+						socket1.close();
+						
+					}catch( Throwable e ){				
+					}
+					
+					try{
+						socket2.close();
+						
+					}catch( Throwable e ){				
+					}
+					
+					sockets.remove( socket1 );
+					
+					return;
+				}
+				
+				sockets.add( socket2 );
+			}
+			
+			handlePipe( socket1.getInputStream(), socket2.getOutputStream());
+			
+			handlePipe( socket2.getInputStream(), socket1.getOutputStream());
+			
+		}catch( Throwable e ){
+			
+			try{
+				socket1.close();
+				
+			}catch( Throwable f ){
+			}
+			
+			synchronized( this ){
+
+				sockets.remove( socket1 );
+			}
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeStreamSource2.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeStreamSource2.java
index fb925df..e6339a4 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeStreamSource2.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodePipeStreamSource2.java
@@ -1,94 +1,93 @@
-/*
- * Created on Feb 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.devices.impl;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.Socket;
-
-
-public class 
-TranscodePipeStreamSource2 
-	extends TranscodePipe
-{
-	private streamListener		adapter;
-	
-	protected
-	TranscodePipeStreamSource2(
-		streamListener	_adapter )		
-	
-		throws IOException
-	{
-		super( null );
-		
-		adapter	= _adapter;
-	}		
-
-	
-	protected void
-	handleSocket(
-		Socket		socket1 )
-	{
-		synchronized( this ){
-			
-			if ( destroyed ){
-				
-				try{
-					socket1.close();
-					
-				}catch( Throwable e ){				
-				}
-				
-				return;
-			}
-			
-			sockets.add( socket1 );
-		}
-
-		try{
-		
-			adapter.gotStream( socket1.getInputStream());
-			
-		}catch( Throwable e ){
-			
-			synchronized( this ){
-				
-				try{
-					socket1.close();
-						
-				}catch( Throwable f ){				
-				}
-					
-				
-				sockets.remove( socket1 );
-			}
-		}
-	}
-	
-	interface
-	streamListener
-	{
-		public void
-		gotStream(
-			InputStream		is );
-	}
-}
+/*
+ * Created on Feb 9, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+
+
+public class 
+TranscodePipeStreamSource2 
+	extends TranscodePipe
+{
+	private streamListener		adapter;
+	
+	protected
+	TranscodePipeStreamSource2(
+		streamListener	_adapter )		
+	
+		throws IOException
+	{
+		super( null );
+		
+		adapter	= _adapter;
+	}		
+
+	
+	protected void
+	handleSocket(
+		Socket		socket1 )
+	{
+		synchronized( this ){
+			
+			if ( destroyed ){
+				
+				try{
+					socket1.close();
+					
+				}catch( Throwable e ){				
+				}
+				
+				return;
+			}
+			
+			sockets.add( socket1 );
+		}
+
+		try{
+		
+			adapter.gotStream( socket1.getInputStream());
+			
+		}catch( Throwable e ){
+			
+			synchronized( this ){
+				
+				try{
+					socket1.close();
+						
+				}catch( Throwable f ){				
+				}
+					
+				
+				sockets.remove( socket1 );
+			}
+		}
+	}
+	
+	interface
+	streamListener
+	{
+		public void
+		gotStream(
+			InputStream		is );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeProfileImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeProfileImpl.java
index 47e5f76..e3b7ec2 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeProfileImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeProfileImpl.java
@@ -1,123 +1,122 @@
-/*
- * Created on Feb 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.devices.impl;
-
-import java.io.File;
-import java.util.*;
-
-import com.aelitis.azureus.core.devices.TranscodeException;
-import com.aelitis.azureus.core.devices.TranscodeProfile;
-import com.aelitis.azureus.core.devices.TranscodeProvider;
-
-public class 
-TranscodeProfileImpl 
-	implements TranscodeProfile
-{
-	private TranscodeManagerImpl	manager;
-	private int						pid;
-	private String					uid;
-	private String 					name;
-	private Map<String,Object>		properties;
-	
-	protected 
-	TranscodeProfileImpl(
-		TranscodeManagerImpl	_manager,
-		int						_provider_id,
-		String					_uid,
-		String					_name,
-		Map<String,Object>		_properties )
-	{
-		manager		= _manager;
-		pid			= _provider_id;
-		uid			= _uid;
-		name		= _name;
-		properties	= _properties;
-	}
-	
-	public String
-	getUID()
-	{
-		return( uid );
-	}
-	
-	public String
-	getName()
-	{
-		String displayName = (String) properties.get("display-name");
-		return( displayName == null ? name : displayName );
-	}
-	
-	public TranscodeProvider
-	getProvider()
-	
-		throws TranscodeException
-	{
-		return( manager.getProvider( pid ));
-	}
-	
-	public boolean
-	isStreamable()
-	{
-		String	res = (String)properties.get( "streamable" );
-
-		return( res != null && res.equalsIgnoreCase( "yes" ));
-	}
-	
-	public String 
-	getFileExtension() 
-	{
-		return((String)properties.get( "file-ext" ));
-	}
-	
-	public String
-	getDeviceClassification()
-	{
-		return((String)properties.get( "device" ));
-	}
-	
-	public String
-	getDescription()
-	{
-		String	res = (String)properties.get( "desc" );
-		
-		return( res == null?"":res );
-	}
-	
-	public String
-	getIconURL()
-	{
-		return((String)properties.get( "icon-url" ));
-	}
-	
-	public int
-	getIconIndex()
-	{
-		Object o = properties.get( "icon-index" );
-		
-		if ( o instanceof Number ){
-			
-			return(((Number)o).intValue());
-		}
-		
-		return( 0 );
-	}
-}
+/*
+ * Created on Feb 5, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.File;
+import java.util.*;
+
+import com.aelitis.azureus.core.devices.TranscodeException;
+import com.aelitis.azureus.core.devices.TranscodeProfile;
+import com.aelitis.azureus.core.devices.TranscodeProvider;
+
+public class 
+TranscodeProfileImpl 
+	implements TranscodeProfile
+{
+	private TranscodeManagerImpl	manager;
+	private int						pid;
+	private String					uid;
+	private String 					name;
+	private Map<String,Object>		properties;
+	
+	protected 
+	TranscodeProfileImpl(
+		TranscodeManagerImpl	_manager,
+		int						_provider_id,
+		String					_uid,
+		String					_name,
+		Map<String,Object>		_properties )
+	{
+		manager		= _manager;
+		pid			= _provider_id;
+		uid			= _uid;
+		name		= _name;
+		properties	= _properties;
+	}
+	
+	public String
+	getUID()
+	{
+		return( uid );
+	}
+	
+	public String
+	getName()
+	{
+		String displayName = (String) properties.get("display-name");
+		return( displayName == null ? name : displayName );
+	}
+	
+	public TranscodeProvider
+	getProvider()
+	
+		throws TranscodeException
+	{
+		return( manager.getProvider( pid ));
+	}
+	
+	public boolean
+	isStreamable()
+	{
+		String	res = (String)properties.get( "streamable" );
+
+		return( res != null && res.equalsIgnoreCase( "yes" ));
+	}
+	
+	public String 
+	getFileExtension() 
+	{
+		return((String)properties.get( "file-ext" ));
+	}
+	
+	public String
+	getDeviceClassification()
+	{
+		return((String)properties.get( "device" ));
+	}
+	
+	public String
+	getDescription()
+	{
+		String	res = (String)properties.get( "desc" );
+		
+		return( res == null?"":res );
+	}
+	
+	public String
+	getIconURL()
+	{
+		return((String)properties.get( "icon-url" ));
+	}
+	
+	public int
+	getIconIndex()
+	{
+		Object o = properties.get( "icon-index" );
+		
+		if ( o instanceof Number ){
+			
+			return(((Number)o).intValue());
+		}
+		
+		return( 0 );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeProviderVuze.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeProviderVuze.java
index 9ca3d83..f234815 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeProviderVuze.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeProviderVuze.java
@@ -1,927 +1,926 @@
-/*
- * Created on Feb 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.devices.impl;
-
-import java.io.File;
-import java.net.URL;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.plugins.ipc.IPCException;
-import org.gudy.azureus2.plugins.ipc.IPCInterface;
-
-import com.aelitis.azureus.core.devices.TranscodeProfile;
-import com.aelitis.azureus.core.devices.TranscodeProvider;
-import com.aelitis.azureus.core.devices.TranscodeProviderAdapter;
-import com.aelitis.azureus.core.devices.TranscodeException;
-import com.aelitis.azureus.core.devices.TranscodeProviderAnalysis;
-import com.aelitis.azureus.core.devices.TranscodeProviderJob;
-import com.aelitis.azureus.core.download.DiskManagerFileInfoURL;
-
-public class 
-TranscodeProviderVuze 
-	implements TranscodeProvider
-{
-	private static final String PROFILE_PREFIX = "vuzexcode:";
-	
-	private TranscodeManagerImpl	manager;
-	private PluginInterface			plugin_interface;
-	
-	private volatile TranscodeProfile[]		profiles;
-	private Map<String,TranscodeProfile[]>	profile_classification_map = new HashMap<String, TranscodeProfile[]>();
-	
-	protected
-	TranscodeProviderVuze(
-		TranscodeManagerImpl	_manager,
-		PluginInterface			_plugin_interface )
-	{
-		manager					= _manager;
-
-		update(_plugin_interface);
-	}
-	
-	public int
-	getID()
-	{
-		return( TP_VUZE );
-	}
-	
-	public PluginInterface
-	getPluginInterface()
-	{
-		return( plugin_interface );
-	}
-	
-	protected void
-	update(
-		PluginInterface		pi )
-	{
-		plugin_interface		= pi;
-
-		try {
-			plugin_interface.getIPC().invoke("addProfileListChangedListener",
-					new Object[] {
-						new AERunnable() {
-							public void runSupport() {
-								
-								resetProfiles();
-							}
-						}
-					});
-		} catch (IPCException e) {
-		}
-		
-		resetProfiles();
-	}
-	
-	public String
-	getName()
-	{
-		return( plugin_interface.getPluginName() + ": version=" + plugin_interface.getPluginVersion());
-	}
-	
-	private void
-	resetProfiles()
-	{
-		synchronized( profile_classification_map ){
-						
-			profile_classification_map.clear();
-			
-			profiles = null;
-		}
-	}
-	
-	public TranscodeProfile[]
-	getProfiles()
-	{			
-		if ( profiles != null ){
-				
-			return( profiles );
-		}
-		
-		try{
-			Map<String, Map<String,Object>> profiles_map = (Map<String,Map<String,Object>>)plugin_interface.getIPC().invoke( "getProfiles", new Object[]{} );
-			
-			TranscodeProfile[] res = new TranscodeProfile[profiles_map.size()];
-			
-			int	index = 0;
-			
-			for ( Map.Entry<String, Map<String,Object>> entry : profiles_map.entrySet()){
-				
-				res[ index++] = new TranscodeProfileImpl( manager, TP_VUZE, PROFILE_PREFIX + entry.getKey(), entry.getKey(), entry.getValue());
-			}
-			
-			profiles	= res;
-			
-			return( res );
-			
-		}catch( Throwable e ){
-			
-			e.printStackTrace();
-			
-			return( new TranscodeProfile[0] );
-		}
-	}
-	
-	public TranscodeProfile[] 
-	getProfiles(
-		String classification_prefix ) 
-	{
-		classification_prefix = classification_prefix.toLowerCase();
-
-		TranscodeProfile[] profs = getProfiles();
-		
-		synchronized( profile_classification_map ){
-
-			TranscodeProfile[] 	res = profile_classification_map.get( classification_prefix );
-			
-			if ( res != null ){
-								
-				return( res );
-			}
-		}
-			
-		List<TranscodeProfile> c_profiles = new ArrayList<TranscodeProfile>();
-		
-		for ( TranscodeProfile p : profs ){
-			
-			String c = p.getDeviceClassification();
-			
-			if ( c == null ){
-				
-				manager.log( "Device classification missing for " + p.getName());
-				
-			}else{
-				
-				if ( c.toLowerCase().startsWith( classification_prefix )){
-					
-					c_profiles.add( p );
-				}
-			}
-		}
-		
-		TranscodeProfile[] res = c_profiles.toArray( new TranscodeProfile[ c_profiles.size()]);
-		 
-		synchronized( profile_classification_map ){
-			
-			if ( profs == profiles ){
-				
-				profile_classification_map.put( classification_prefix, res );
-			}
-		}
-		
-		return( res );
-	}
-	
-	public TranscodeProfile
-	getProfile(
-		String		UID )
-	{
-		TranscodeProfile[] profiles = getProfiles();
-		
-		for ( TranscodeProfile profile: profiles ){
-			
-			if ( profile.getUID().equals( UID )){
-				
-				return( profile );
-			}
-		}
-		
-		return( null );
-	}
-	
-	public TranscodeProfile 
-	addProfile(
-		File 		file ) 
-	
-		throws TranscodeException
-	{
-		try{
-			String uid = PROFILE_PREFIX + (String)plugin_interface.getIPC().invoke( "addProfile", new Object[]{ file } );
-			
-			resetProfiles();
-			
-			return( getProfile( uid ));
-			
-		}catch( Throwable e ){
-			
-			throw( new TranscodeException( "Failed to add profile", e ));
-		}
-	}
-	
-	public TranscodeProviderAnalysis
-	analyse( 
-		final TranscodeProviderAdapter	_adapter,
-		DiskManagerFileInfo				input,
-		TranscodeProfile				profile )	
-	
-		throws TranscodeException
-	{
-		try{
-			
-			URL 				source_url		= null;
-			File				source_file	 	= null;
-			
-			long	input_length = input.getLength();
-			
-			if ( input_length > 0 && input_length == input.getDownloaded()){
-				
-				File file = input.getFile();
-				
-				if ( file.exists() && file.length() == input_length ){
-					
-					source_file = file;
-				}
-			}
-			
-			TranscodePipe		pipe = null;
-
-			if ( source_file == null ){
-					
-				if ( input instanceof DiskManagerFileInfoURL ){
-					
-					source_url = ((DiskManagerFileInfoURL)input).getURL();
-					
-				}else{
-						// race condition here on auto-transcodes due to downloadadded listeners - can add the xcode to queue
-						// and schedule before added to upnpms - simple hack is to hang about a bit
-				
-					for ( int i=0; i<10; i++ ){
-	
-						PluginInterface av_pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azupnpav" );
-						
-						if ( av_pi == null ){
-						
-							throw( new TranscodeException( "Media Server plugin not found" ));
-						}
-						
-						IPCInterface av_ipc = av_pi.getIPC();
-						
-						String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ input });
-				
-						if ( url_str != null && url_str.length() > 0 ){
-						
-							source_url = new URL( url_str );
-					
-							pipe = new TranscodePipeStreamSource( source_url.getHost(), source_url.getPort());
-						
-							source_url = UrlUtils.setHost( source_url, "127.0.0.1" );
-		
-							source_url = UrlUtils.setPort( source_url, pipe.getPort());					
-						}
-					
-						if ( source_url != null ){
-							
-							break;
-							
-						}else{
-							
-							try{
-								Thread.sleep(1000);
-								
-							}catch( Throwable e ){
-								
-								break;
-							}
-						}
-					}
-				}
-			}
-			
-			if ( source_file == null && source_url == null ){
-			
-				throw( new TranscodeException( "File doesn't exist" ));
-			}
-
-			final TranscodePipe f_pipe = pipe;
-			
-			try{	
-				final IPCInterface	ipc = plugin_interface.getIPC();
-
-				final Object analysis_context;
-				
-				if ( source_url != null ){
-					
-					analysis_context = ipc.invoke(
-						"analyseContent",
-						new Object[]{ 
-							source_url,
-							profile.getName() });
-				}else{
-					
-					analysis_context = ipc.invoke(
-						"analyseContent",
-						new Object[]{ 
-							source_file,
-							profile.getName() });
-				}
-				
-				final Map<String,Object>	result = new HashMap<String, Object>();
-				
-				final TranscodeProviderAnalysisImpl analysis = 
-					new TranscodeProviderAnalysisImpl()
-					{
-						public void 
-						cancel() 
-						{
-							try{
-								ipc.invoke( "cancelAnalysis", new Object[]{ analysis_context });
-								
-							}catch( Throwable e ){
-								
-								Debug.printStackTrace( e );
-							}
-						}
-						
-						public boolean 
-						foundVideoStream() 
-						{
-							return( getLongProperty( PT_VIDEO_WIDTH ) > 0 );
-						}
-						
-						public boolean
-						getBooleanProperty(
-							int		property )
-						{
-							if ( property == PT_TRANSCODE_REQUIRED ){
-								
-								return( getBooleanProperty( "xcode_required", true ));
-								
-							}else{
-								
-								Debug.out( "Unknown property: " + property );
-								
-								return( false );
-							}
-						}
-						
-						public void
-						setBooleanProperty(
-							int		property,
-							boolean	value )
-						{
-							if ( property == PT_FORCE_TRANSCODE ){
-								
-								result.put( "force_xcode", value );
-								
-							}else{
-								
-								Debug.out( "Unknown property: " + property );
-							}
-						}
-						
-						public long
-						getLongProperty(
-							int		property )
-						{
-							if ( property == PT_DURATION_MILLIS ){
-								
-								long duration = getLongProperty( "duration_millis", 0 );
-								
-								long audio_duration	= getLongProperty( "audio_duration_millis", 0 );
-								
-								if ( duration <= 0 && audio_duration > 0 ){
-									
-									duration = audio_duration;
-								}
-								
-								if ( audio_duration > 0 && audio_duration < duration ){
-									
-									duration = audio_duration;
-								}
-							
-								return( duration );
-								
-							}else if ( property == PT_VIDEO_WIDTH ){
-								
-								return( getLongProperty( "video_width", 0 ));
-	
-							}else if ( property == PT_VIDEO_HEIGHT ){
-								
-								return( getLongProperty( "video_height", 0 ));
-	
-							}else if ( property == PT_SOURCE_SIZE ){
-								
-								return( getLongProperty( "source_size", 0 ));
-
-							}else if ( property == PT_ESTIMATED_XCODE_SIZE ){
-								
-								return( getLongProperty( "estimated_transcoded_size", 0 ));
-
-							}else{
-								
-								Debug.out( "Unknown property: " + property );
-								
-								return( 0 );
-							}
-						}
-						
-						protected boolean
-						getBooleanProperty(
-							String		name,
-							boolean		def )
-						{
-							Boolean b = (Boolean)result.get( name );
-							
-							if ( b != null ){
-								
-								return( b );
-							}
-							
-							return( def );
-						}
-						
-						protected long
-						getLongProperty(
-							String		name,
-							long		def )
-						{
-							Long l = (Long)result.get( name );
-							
-							if ( l != null ){
-								
-								return( l );
-							}
-							
-							return( def );
-						}
-						
-						public Map<String,Object>
-						getResult()
-						{
-							return( result );
-						}
-					};
-					
-				new AEThread2( "analysisStatus", true )
-				{
-					public void 
-					run() 
-					{
-						try{
-							while( true ){
-																
-								try{
-									Map status = (Map)ipc.invoke( "getAnalysisStatus", new Object[]{ analysis_context });
-									
-									long	state = (Long)status.get( "state" );
-									
-									if ( state == 0 ){
-	
-											// running
-										
-										Thread.sleep(50);
-										
-									}else if ( state == 1 ){
-										
-										_adapter.failed( new TranscodeException( "Analysis cancelled" ));
-										
-										break;
-										
-									}else if ( state == 2 ){
-										
-										_adapter.failed( new TranscodeException( "Analysis failed", (Throwable)status.get( "error" )));
-										
-										break;
-										
-									}else{
-										
-										result.putAll((Map<String,Object>)status.get( "result" ));
-										
-										_adapter.complete();
-										
-										break;
-									}
-								}catch( Throwable e ){
-									
-									_adapter.failed( new TranscodeException( "Failed to get status", e ));
-									
-									break;
-								}
-							}
-						}finally{
-							
-							if ( f_pipe != null ){
-							
-								f_pipe.destroy();
-							}
-						}
-					}
-				}.start();
-				
-				return( analysis );
-
-						
-			}catch( Throwable e ){
-				
-				if ( pipe != null ){
-				
-					pipe.destroy();
-				}
-				
-				throw( e );
-			}
-		}catch( TranscodeException e ){
-			
-			throw( e );
-				
-		}catch( Throwable e ){
-			
-			throw( new TranscodeException( "analysis failed", e ));
-		}
-	}
-	
-	public TranscodeProviderJob
-	transcode( 
-		final TranscodeProviderAdapter	_adapter,
-		TranscodeProviderAnalysis		analysis,
-		boolean							direct_input,
-		DiskManagerFileInfo				input,
-		TranscodeProfile				profile,
-		URL								output )
-	
-		throws TranscodeException
-	{
-		try{
-			PluginInterface av_pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azupnpav" );
-			
-			if ( av_pi == null ){
-			
-				throw( new TranscodeException( "Media Server plugin not found" ));
-			}
-			
-			final TranscodeProviderJob[] xcode_job = { null };
-			
-			URL 				source_url	= null;
-			TranscodePipe		pipe		= null;
-
-			if ( direct_input ){
-				
-				if ( input instanceof DiskManagerFileInfoURL ){
-					
-					((DiskManagerFileInfoURL)input).download();
-				}
-				
-				if ( input.getDownloaded() == input.getLength()){
-					
-					File	file = input.getFile();
-					
-					if ( file.exists() && file.length() == input.getLength()){
-						
-						source_url = file.toURI().toURL();
-					}
-				}
-				
-				if ( source_url == null ){
-				
-					manager.log( "Failed to use direct input as source file doesn't exist/incomplete" );
-				}
-			}
-			
-			if ( source_url == null ){
-				
-				if ( input instanceof DiskManagerFileInfoURL ){
-					
-					source_url = ((DiskManagerFileInfoURL)input).getURL();
-					
-				}else{
-					
-					IPCInterface av_ipc = av_pi.getIPC();
-					
-					String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ input });
-					
-					
-					if ( url_str == null || url_str.length() == 0 ){
-						
-							// see if we can use the file directly
-						
-						File source_file = input.getFile();
-						
-						if ( source_file.exists()){
-							
-							pipe = 
-								new TranscodePipeFileSource( 
-										source_file,
-										new TranscodePipe.errorListener()
-										{
-											public void 
-											error(
-												Throwable e )
-											{
-												_adapter.failed(
-													new TranscodeException( "File access error", e ));
-												
-												if ( xcode_job[0] != null ){
-													
-													xcode_job[0].cancel();
-												}
-											}
-										});
-							
-							source_url = new URL( "http://127.0.0.1:" + pipe.getPort() + "/" );
-							
-						}else{
-							
-							throw( new TranscodeException( "Source file doesn't exist" ));
-						}
-					}else{
-						
-						source_url = new URL( url_str );
-					
-						pipe = new TranscodePipeStreamSource( source_url.getHost(), source_url.getPort());
-						
-						source_url = UrlUtils.setHost( source_url, "127.0.0.1" );
-	
-						source_url = UrlUtils.setPort( source_url, pipe.getPort());		
-					}
-				}
-			}
-			
-			final TranscodePipe f_pipe = pipe;
-			
-			try{	
-				final IPCInterface	ipc = plugin_interface.getIPC();
-
-				final Object context;
-				
-				final TranscodeProviderAdapter	adapter;
-				
-				if ( output.getProtocol().equals( "tcp" )){
-					
-					adapter = _adapter;
-					
-					context = 
-						ipc.invoke(
-							"transcodeToTCP",
-							new Object[]{ 
-								((TranscodeProviderAnalysisImpl)analysis).getResult(),
-								source_url,
-								profile.getName(),
-								output.getPort() });
-				}else{
-					
-					final File file = new File( output.toURI());
-						
-					File	parent_dir = file.getParentFile();
-					
-					if ( parent_dir.exists()){
-						
-						if ( !parent_dir.canWrite()){
-							
-							throw( new TranscodeException( "Folder '" + parent_dir.getAbsolutePath() + "' isn't writable" ));
-						}
-					}else{
-						
-						if ( !parent_dir.mkdirs()){
-						
-							throw( new TranscodeException( "Failed to create folder '" + parent_dir.getAbsolutePath() + "'" ));
-						}
-					}
-					
-					adapter = 
-						new TranscodeProviderAdapter()
-						{
-							public void
-							updateProgress(
-								int		percent,
-								int		eta_secs,
-								int		width,
-								int		height )
-							{
-								_adapter.updateProgress( percent, eta_secs, width, height );
-							}
-							
-							public void
-							streamStats(
-								long					connect_rate,
-								long					write_speed )
-							{
-								_adapter.streamStats(connect_rate, write_speed);
-							}
-							
-							public void
-							failed(
-								TranscodeException		error )
-							{
-								try{
-									file.delete();
-									
-								}finally{
-									
-									_adapter.failed( error );
-								}
-							}
-							
-							public void
-							complete()
-							{
-								_adapter.complete();
-							}
-						};
-						
-					context = 
-						ipc.invoke(
-							"transcodeToFile",
-							new Object[]{ 
-								((TranscodeProviderAnalysisImpl)analysis).getResult(),
-								source_url,
-								profile.getName(),
-								file });
-				}
-	
-				new AEThread2( "xcodeStatus", true )
-					{
-						public void 
-						run() 
-						{
-							try{
-								boolean	in_progress = true;
-								
-								while( in_progress ){
-									
-									in_progress = false;
-									
-									if ( f_pipe != null ){
-										
-										adapter.streamStats( f_pipe.getConnectionRate(), f_pipe.getWriteSpeed());										
-									}
-									
-									try{
-										Map status = (Map)ipc.invoke( "getTranscodeStatus", new Object[]{ context });
-										
-										long	state = (Long)status.get( "state" );
-										
-										if ( state == 0 ){
-											
-											int	percent = (Integer)status.get( "percent" );
-											
-											Integer	i_eta	= (Integer)status.get( "eta_secs" );
-											
-											int eta = i_eta==null?-1:i_eta;
-											
-											Integer	i_width	= (Integer)status.get( "new_width" );
-											
-											int width = i_width==null?0:i_width;
-											
-											Integer	i_height	= (Integer)status.get( "new_height" );
-											
-											int height = i_height==null?0:i_height;
-											
-											adapter.updateProgress( percent, eta, width, height );
-											
-											if ( percent == 100 ){
-												
-												adapter.complete();
-		
-											}else{
-												
-												in_progress = true;
-											
-												Thread.sleep(1000);
-											}
-										}else if ( state == 1 ){
-											
-											adapter.failed( new TranscodeException( "Transcode cancelled" ));
-											
-										}else{
-																						
-											Boolean	perm_fail = (Boolean)status.get( "error_is_perm" );
-											
-											TranscodeException error = new TranscodeException( "Transcode failed", (Throwable)status.get( "error" ));
-											
-											if ( perm_fail != null && perm_fail ){
-												
-												error.setDisableRetry( true );
-											}
-											
-											adapter.failed( error );
-										}
-									}catch( Throwable e ){
-										
-										adapter.failed( new TranscodeException( "Failed to get status", e ));
-									}
-								}
-							}finally{
-								
-								if ( f_pipe != null ){
-								
-									f_pipe.destroy();
-								}
-							}
-						}
-					}.start();
-					
-			
-				xcode_job[0] = 
-					new TranscodeProviderJob()
-					{
-						public void
-						pause()
-						{
-							if ( f_pipe != null ){
-							
-								f_pipe.pause();
-							}
-						}
-						
-						public void
-						resume()
-						{
-							if ( f_pipe != null ){
-								
-								f_pipe.resume();
-							}
-						}
-	
-						public void 
-						cancel() 
-						{
-							try{
-								ipc.invoke( "cancelTranscode", new Object[]{ context });
-								
-							}catch( Throwable e ){
-								
-								Debug.printStackTrace( e );
-							}
-						}
-						
-						public void 
-						setMaxBytesPerSecond(
-							int		 max ) 
-						{
-							if ( f_pipe != null ){
-							
-								f_pipe.setMaxBytesPerSecond( max );
-							}
-						}
-					};
-					
-				return( xcode_job[0] );
-				
-			}catch( Throwable e ){
-				
-				if ( pipe != null ){
-				
-					pipe.destroy();
-				}
-				
-				throw( e );
-			}
-		}catch( TranscodeException e ){
-			
-			throw( e );
-				
-		}catch( Throwable e ){
-			
-			throw( new TranscodeException( "transcode failed", e ));
-		}
-	}
-	
-	public File
-	getAssetDirectory()
-	{
-		File file = plugin_interface.getPluginconfig().getPluginUserFile( "assets" );
-		
-		if ( !file.exists()){
-			
-			file.mkdirs();
-		}
-		
-		return( file );
-	}
-	
-	protected void
-	destroy()
-	{
-		// TODO
-	}
-	
-	protected interface
-	TranscodeProviderAnalysisImpl
-		extends TranscodeProviderAnalysis
-	{
-		public Map<String,Object>
-		getResult();
-	}
-}
+/*
+ * Created on Feb 5, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.File;
+import java.net.URL;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.ipc.IPCException;
+import org.gudy.azureus2.plugins.ipc.IPCInterface;
+
+import com.aelitis.azureus.core.devices.TranscodeProfile;
+import com.aelitis.azureus.core.devices.TranscodeProvider;
+import com.aelitis.azureus.core.devices.TranscodeProviderAdapter;
+import com.aelitis.azureus.core.devices.TranscodeException;
+import com.aelitis.azureus.core.devices.TranscodeProviderAnalysis;
+import com.aelitis.azureus.core.devices.TranscodeProviderJob;
+import com.aelitis.azureus.core.download.DiskManagerFileInfoURL;
+
+public class 
+TranscodeProviderVuze 
+	implements TranscodeProvider
+{
+	private static final String PROFILE_PREFIX = "vuzexcode:";
+	
+	private TranscodeManagerImpl	manager;
+	private PluginInterface			plugin_interface;
+	
+	private volatile TranscodeProfile[]		profiles;
+	private Map<String,TranscodeProfile[]>	profile_classification_map = new HashMap<String, TranscodeProfile[]>();
+	
+	protected
+	TranscodeProviderVuze(
+		TranscodeManagerImpl	_manager,
+		PluginInterface			_plugin_interface )
+	{
+		manager					= _manager;
+
+		update(_plugin_interface);
+	}
+	
+	public int
+	getID()
+	{
+		return( TP_VUZE );
+	}
+	
+	public PluginInterface
+	getPluginInterface()
+	{
+		return( plugin_interface );
+	}
+	
+	protected void
+	update(
+		PluginInterface		pi )
+	{
+		plugin_interface		= pi;
+
+		try {
+			plugin_interface.getIPC().invoke("addProfileListChangedListener",
+					new Object[] {
+						new AERunnable() {
+							public void runSupport() {
+								
+								resetProfiles();
+							}
+						}
+					});
+		} catch (IPCException e) {
+		}
+		
+		resetProfiles();
+	}
+	
+	public String
+	getName()
+	{
+		return( plugin_interface.getPluginName() + ": version=" + plugin_interface.getPluginVersion());
+	}
+	
+	private void
+	resetProfiles()
+	{
+		synchronized( profile_classification_map ){
+						
+			profile_classification_map.clear();
+			
+			profiles = null;
+		}
+	}
+	
+	public TranscodeProfile[]
+	getProfiles()
+	{			
+		if ( profiles != null ){
+				
+			return( profiles );
+		}
+		
+		try{
+			Map<String, Map<String,Object>> profiles_map = (Map<String,Map<String,Object>>)plugin_interface.getIPC().invoke( "getProfiles", new Object[]{} );
+			
+			TranscodeProfile[] res = new TranscodeProfile[profiles_map.size()];
+			
+			int	index = 0;
+			
+			for ( Map.Entry<String, Map<String,Object>> entry : profiles_map.entrySet()){
+				
+				res[ index++] = new TranscodeProfileImpl( manager, TP_VUZE, PROFILE_PREFIX + entry.getKey(), entry.getKey(), entry.getValue());
+			}
+			
+			profiles	= res;
+			
+			return( res );
+			
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+			
+			return( new TranscodeProfile[0] );
+		}
+	}
+	
+	public TranscodeProfile[] 
+	getProfiles(
+		String classification_prefix ) 
+	{
+		classification_prefix = classification_prefix.toLowerCase();
+
+		TranscodeProfile[] profs = getProfiles();
+		
+		synchronized( profile_classification_map ){
+
+			TranscodeProfile[] 	res = profile_classification_map.get( classification_prefix );
+			
+			if ( res != null ){
+								
+				return( res );
+			}
+		}
+			
+		List<TranscodeProfile> c_profiles = new ArrayList<TranscodeProfile>();
+		
+		for ( TranscodeProfile p : profs ){
+			
+			String c = p.getDeviceClassification();
+			
+			if ( c == null ){
+				
+				manager.log( "Device classification missing for " + p.getName());
+				
+			}else{
+				
+				if ( c.toLowerCase().startsWith( classification_prefix )){
+					
+					c_profiles.add( p );
+				}
+			}
+		}
+		
+		TranscodeProfile[] res = c_profiles.toArray( new TranscodeProfile[ c_profiles.size()]);
+		 
+		synchronized( profile_classification_map ){
+			
+			if ( profs == profiles ){
+				
+				profile_classification_map.put( classification_prefix, res );
+			}
+		}
+		
+		return( res );
+	}
+	
+	public TranscodeProfile
+	getProfile(
+		String		UID )
+	{
+		TranscodeProfile[] profiles = getProfiles();
+		
+		for ( TranscodeProfile profile: profiles ){
+			
+			if ( profile.getUID().equals( UID )){
+				
+				return( profile );
+			}
+		}
+		
+		return( null );
+	}
+	
+	public TranscodeProfile 
+	addProfile(
+		File 		file ) 
+	
+		throws TranscodeException
+	{
+		try{
+			String uid = PROFILE_PREFIX + (String)plugin_interface.getIPC().invoke( "addProfile", new Object[]{ file } );
+			
+			resetProfiles();
+			
+			return( getProfile( uid ));
+			
+		}catch( Throwable e ){
+			
+			throw( new TranscodeException( "Failed to add profile", e ));
+		}
+	}
+	
+	public TranscodeProviderAnalysis
+	analyse( 
+		final TranscodeProviderAdapter	_adapter,
+		DiskManagerFileInfo				input,
+		TranscodeProfile				profile )	
+	
+		throws TranscodeException
+	{
+		try{
+			
+			URL 				source_url		= null;
+			File				source_file	 	= null;
+			
+			long	input_length = input.getLength();
+			
+			if ( input_length > 0 && input_length == input.getDownloaded()){
+				
+				File file = input.getFile();
+				
+				if ( file.exists() && file.length() == input_length ){
+					
+					source_file = file;
+				}
+			}
+			
+			TranscodePipe		pipe = null;
+
+			if ( source_file == null ){
+					
+				if ( input instanceof DiskManagerFileInfoURL ){
+					
+					source_url = ((DiskManagerFileInfoURL)input).getURL();
+					
+				}else{
+						// race condition here on auto-transcodes due to downloadadded listeners - can add the xcode to queue
+						// and schedule before added to upnpms - simple hack is to hang about a bit
+				
+					for ( int i=0; i<10; i++ ){
+	
+						PluginInterface av_pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azupnpav" );
+						
+						if ( av_pi == null ){
+						
+							throw( new TranscodeException( "Media Server plugin not found" ));
+						}
+						
+						IPCInterface av_ipc = av_pi.getIPC();
+						
+						String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ input });
+				
+						if ( url_str != null && url_str.length() > 0 ){
+						
+							source_url = new URL( url_str );
+					
+							pipe = new TranscodePipeStreamSource( source_url.getHost(), source_url.getPort());
+						
+							source_url = UrlUtils.setHost( source_url, "127.0.0.1" );
+		
+							source_url = UrlUtils.setPort( source_url, pipe.getPort());					
+						}
+					
+						if ( source_url != null ){
+							
+							break;
+							
+						}else{
+							
+							try{
+								Thread.sleep(1000);
+								
+							}catch( Throwable e ){
+								
+								break;
+							}
+						}
+					}
+				}
+			}
+			
+			if ( source_file == null && source_url == null ){
+			
+				throw( new TranscodeException( "File doesn't exist" ));
+			}
+
+			final TranscodePipe f_pipe = pipe;
+			
+			try{	
+				final IPCInterface	ipc = plugin_interface.getIPC();
+
+				final Object analysis_context;
+				
+				if ( source_url != null ){
+					
+					analysis_context = ipc.invoke(
+						"analyseContent",
+						new Object[]{ 
+							source_url,
+							profile.getName() });
+				}else{
+					
+					analysis_context = ipc.invoke(
+						"analyseContent",
+						new Object[]{ 
+							source_file,
+							profile.getName() });
+				}
+				
+				final Map<String,Object>	result = new HashMap<String, Object>();
+				
+				final TranscodeProviderAnalysisImpl analysis = 
+					new TranscodeProviderAnalysisImpl()
+					{
+						public void 
+						cancel() 
+						{
+							try{
+								ipc.invoke( "cancelAnalysis", new Object[]{ analysis_context });
+								
+							}catch( Throwable e ){
+								
+								Debug.printStackTrace( e );
+							}
+						}
+						
+						public boolean 
+						foundVideoStream() 
+						{
+							return( getLongProperty( PT_VIDEO_WIDTH ) > 0 );
+						}
+						
+						public boolean
+						getBooleanProperty(
+							int		property )
+						{
+							if ( property == PT_TRANSCODE_REQUIRED ){
+								
+								return( getBooleanProperty( "xcode_required", true ));
+								
+							}else{
+								
+								Debug.out( "Unknown property: " + property );
+								
+								return( false );
+							}
+						}
+						
+						public void
+						setBooleanProperty(
+							int		property,
+							boolean	value )
+						{
+							if ( property == PT_FORCE_TRANSCODE ){
+								
+								result.put( "force_xcode", value );
+								
+							}else{
+								
+								Debug.out( "Unknown property: " + property );
+							}
+						}
+						
+						public long
+						getLongProperty(
+							int		property )
+						{
+							if ( property == PT_DURATION_MILLIS ){
+								
+								long duration = getLongProperty( "duration_millis", 0 );
+								
+								long audio_duration	= getLongProperty( "audio_duration_millis", 0 );
+								
+								if ( duration <= 0 && audio_duration > 0 ){
+									
+									duration = audio_duration;
+								}
+								
+								if ( audio_duration > 0 && audio_duration < duration ){
+									
+									duration = audio_duration;
+								}
+							
+								return( duration );
+								
+							}else if ( property == PT_VIDEO_WIDTH ){
+								
+								return( getLongProperty( "video_width", 0 ));
+	
+							}else if ( property == PT_VIDEO_HEIGHT ){
+								
+								return( getLongProperty( "video_height", 0 ));
+	
+							}else if ( property == PT_SOURCE_SIZE ){
+								
+								return( getLongProperty( "source_size", 0 ));
+
+							}else if ( property == PT_ESTIMATED_XCODE_SIZE ){
+								
+								return( getLongProperty( "estimated_transcoded_size", 0 ));
+
+							}else{
+								
+								Debug.out( "Unknown property: " + property );
+								
+								return( 0 );
+							}
+						}
+						
+						protected boolean
+						getBooleanProperty(
+							String		name,
+							boolean		def )
+						{
+							Boolean b = (Boolean)result.get( name );
+							
+							if ( b != null ){
+								
+								return( b );
+							}
+							
+							return( def );
+						}
+						
+						protected long
+						getLongProperty(
+							String		name,
+							long		def )
+						{
+							Long l = (Long)result.get( name );
+							
+							if ( l != null ){
+								
+								return( l );
+							}
+							
+							return( def );
+						}
+						
+						public Map<String,Object>
+						getResult()
+						{
+							return( result );
+						}
+					};
+					
+				new AEThread2( "analysisStatus", true )
+				{
+					public void 
+					run() 
+					{
+						try{
+							while( true ){
+																
+								try{
+									Map status = (Map)ipc.invoke( "getAnalysisStatus", new Object[]{ analysis_context });
+									
+									long	state = (Long)status.get( "state" );
+									
+									if ( state == 0 ){
+	
+											// running
+										
+										Thread.sleep(50);
+										
+									}else if ( state == 1 ){
+										
+										_adapter.failed( new TranscodeException( "Analysis cancelled" ));
+										
+										break;
+										
+									}else if ( state == 2 ){
+										
+										_adapter.failed( new TranscodeException( "Analysis failed", (Throwable)status.get( "error" )));
+										
+										break;
+										
+									}else{
+										
+										result.putAll((Map<String,Object>)status.get( "result" ));
+										
+										_adapter.complete();
+										
+										break;
+									}
+								}catch( Throwable e ){
+									
+									_adapter.failed( new TranscodeException( "Failed to get status", e ));
+									
+									break;
+								}
+							}
+						}finally{
+							
+							if ( f_pipe != null ){
+							
+								f_pipe.destroy();
+							}
+						}
+					}
+				}.start();
+				
+				return( analysis );
+
+						
+			}catch( Throwable e ){
+				
+				if ( pipe != null ){
+				
+					pipe.destroy();
+				}
+				
+				throw( e );
+			}
+		}catch( TranscodeException e ){
+			
+			throw( e );
+				
+		}catch( Throwable e ){
+			
+			throw( new TranscodeException( "analysis failed", e ));
+		}
+	}
+	
+	public TranscodeProviderJob
+	transcode( 
+		final TranscodeProviderAdapter	_adapter,
+		TranscodeProviderAnalysis		analysis,
+		boolean							direct_input,
+		DiskManagerFileInfo				input,
+		TranscodeProfile				profile,
+		URL								output )
+	
+		throws TranscodeException
+	{
+		try{
+			PluginInterface av_pi = plugin_interface.getPluginManager().getPluginInterfaceByID( "azupnpav" );
+			
+			if ( av_pi == null ){
+			
+				throw( new TranscodeException( "Media Server plugin not found" ));
+			}
+			
+			final TranscodeProviderJob[] xcode_job = { null };
+			
+			URL 				source_url	= null;
+			TranscodePipe		pipe		= null;
+
+			if ( direct_input ){
+				
+				if ( input instanceof DiskManagerFileInfoURL ){
+					
+					((DiskManagerFileInfoURL)input).download();
+				}
+				
+				if ( input.getDownloaded() == input.getLength()){
+					
+					File	file = input.getFile();
+					
+					if ( file.exists() && file.length() == input.getLength()){
+						
+						source_url = file.toURI().toURL();
+					}
+				}
+				
+				if ( source_url == null ){
+				
+					manager.log( "Failed to use direct input as source file doesn't exist/incomplete" );
+				}
+			}
+			
+			if ( source_url == null ){
+				
+				if ( input instanceof DiskManagerFileInfoURL ){
+					
+					source_url = ((DiskManagerFileInfoURL)input).getURL();
+					
+				}else{
+					
+					IPCInterface av_ipc = av_pi.getIPC();
+					
+					String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ input });
+					
+					
+					if ( url_str == null || url_str.length() == 0 ){
+						
+							// see if we can use the file directly
+						
+						File source_file = input.getFile();
+						
+						if ( source_file.exists()){
+							
+							pipe = 
+								new TranscodePipeFileSource( 
+										source_file,
+										new TranscodePipe.errorListener()
+										{
+											public void 
+											error(
+												Throwable e )
+											{
+												_adapter.failed(
+													new TranscodeException( "File access error", e ));
+												
+												if ( xcode_job[0] != null ){
+													
+													xcode_job[0].cancel();
+												}
+											}
+										});
+							
+							source_url = new URL( "http://127.0.0.1:" + pipe.getPort() + "/" );
+							
+						}else{
+							
+							throw( new TranscodeException( "Source file doesn't exist" ));
+						}
+					}else{
+						
+						source_url = new URL( url_str );
+					
+						pipe = new TranscodePipeStreamSource( source_url.getHost(), source_url.getPort());
+						
+						source_url = UrlUtils.setHost( source_url, "127.0.0.1" );
+	
+						source_url = UrlUtils.setPort( source_url, pipe.getPort());		
+					}
+				}
+			}
+			
+			final TranscodePipe f_pipe = pipe;
+			
+			try{	
+				final IPCInterface	ipc = plugin_interface.getIPC();
+
+				final Object context;
+				
+				final TranscodeProviderAdapter	adapter;
+				
+				if ( output.getProtocol().equals( "tcp" )){
+					
+					adapter = _adapter;
+					
+					context = 
+						ipc.invoke(
+							"transcodeToTCP",
+							new Object[]{ 
+								((TranscodeProviderAnalysisImpl)analysis).getResult(),
+								source_url,
+								profile.getName(),
+								output.getPort() });
+				}else{
+					
+					final File file = new File( output.toURI());
+						
+					File	parent_dir = file.getParentFile();
+					
+					if ( parent_dir.exists()){
+						
+						if ( !parent_dir.canWrite()){
+							
+							throw( new TranscodeException( "Folder '" + parent_dir.getAbsolutePath() + "' isn't writable" ));
+						}
+					}else{
+						
+						if ( !parent_dir.mkdirs()){
+						
+							throw( new TranscodeException( "Failed to create folder '" + parent_dir.getAbsolutePath() + "'" ));
+						}
+					}
+					
+					adapter = 
+						new TranscodeProviderAdapter()
+						{
+							public void
+							updateProgress(
+								int		percent,
+								int		eta_secs,
+								int		width,
+								int		height )
+							{
+								_adapter.updateProgress( percent, eta_secs, width, height );
+							}
+							
+							public void
+							streamStats(
+								long					connect_rate,
+								long					write_speed )
+							{
+								_adapter.streamStats(connect_rate, write_speed);
+							}
+							
+							public void
+							failed(
+								TranscodeException		error )
+							{
+								try{
+									file.delete();
+									
+								}finally{
+									
+									_adapter.failed( error );
+								}
+							}
+							
+							public void
+							complete()
+							{
+								_adapter.complete();
+							}
+						};
+						
+					context = 
+						ipc.invoke(
+							"transcodeToFile",
+							new Object[]{ 
+								((TranscodeProviderAnalysisImpl)analysis).getResult(),
+								source_url,
+								profile.getName(),
+								file });
+				}
+	
+				new AEThread2( "xcodeStatus", true )
+					{
+						public void 
+						run() 
+						{
+							try{
+								boolean	in_progress = true;
+								
+								while( in_progress ){
+									
+									in_progress = false;
+									
+									if ( f_pipe != null ){
+										
+										adapter.streamStats( f_pipe.getConnectionRate(), f_pipe.getWriteSpeed());										
+									}
+									
+									try{
+										Map status = (Map)ipc.invoke( "getTranscodeStatus", new Object[]{ context });
+										
+										long	state = (Long)status.get( "state" );
+										
+										if ( state == 0 ){
+											
+											int	percent = (Integer)status.get( "percent" );
+											
+											Integer	i_eta	= (Integer)status.get( "eta_secs" );
+											
+											int eta = i_eta==null?-1:i_eta;
+											
+											Integer	i_width	= (Integer)status.get( "new_width" );
+											
+											int width = i_width==null?0:i_width;
+											
+											Integer	i_height	= (Integer)status.get( "new_height" );
+											
+											int height = i_height==null?0:i_height;
+											
+											adapter.updateProgress( percent, eta, width, height );
+											
+											if ( percent == 100 ){
+												
+												adapter.complete();
+		
+											}else{
+												
+												in_progress = true;
+											
+												Thread.sleep(1000);
+											}
+										}else if ( state == 1 ){
+											
+											adapter.failed( new TranscodeException( "Transcode cancelled" ));
+											
+										}else{
+																						
+											Boolean	perm_fail = (Boolean)status.get( "error_is_perm" );
+											
+											TranscodeException error = new TranscodeException( "Transcode failed", (Throwable)status.get( "error" ));
+											
+											if ( perm_fail != null && perm_fail ){
+												
+												error.setDisableRetry( true );
+											}
+											
+											adapter.failed( error );
+										}
+									}catch( Throwable e ){
+										
+										adapter.failed( new TranscodeException( "Failed to get status", e ));
+									}
+								}
+							}finally{
+								
+								if ( f_pipe != null ){
+								
+									f_pipe.destroy();
+								}
+							}
+						}
+					}.start();
+					
+			
+				xcode_job[0] = 
+					new TranscodeProviderJob()
+					{
+						public void
+						pause()
+						{
+							if ( f_pipe != null ){
+							
+								f_pipe.pause();
+							}
+						}
+						
+						public void
+						resume()
+						{
+							if ( f_pipe != null ){
+								
+								f_pipe.resume();
+							}
+						}
+	
+						public void 
+						cancel() 
+						{
+							try{
+								ipc.invoke( "cancelTranscode", new Object[]{ context });
+								
+							}catch( Throwable e ){
+								
+								Debug.printStackTrace( e );
+							}
+						}
+						
+						public void 
+						setMaxBytesPerSecond(
+							int		 max ) 
+						{
+							if ( f_pipe != null ){
+							
+								f_pipe.setMaxBytesPerSecond( max );
+							}
+						}
+					};
+					
+				return( xcode_job[0] );
+				
+			}catch( Throwable e ){
+				
+				if ( pipe != null ){
+				
+					pipe.destroy();
+				}
+				
+				throw( e );
+			}
+		}catch( TranscodeException e ){
+			
+			throw( e );
+				
+		}catch( Throwable e ){
+			
+			throw( new TranscodeException( "transcode failed", e ));
+		}
+	}
+	
+	public File
+	getAssetDirectory()
+	{
+		File file = plugin_interface.getPluginconfig().getPluginUserFile( "assets" );
+		
+		if ( !file.exists()){
+			
+			file.mkdirs();
+		}
+		
+		return( file );
+	}
+	
+	protected void
+	destroy()
+	{
+		// TODO
+	}
+	
+	protected interface
+	TranscodeProviderAnalysisImpl
+		extends TranscodeProviderAnalysis
+	{
+		public Map<String,Object>
+		getResult();
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeQueueImpl.java b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeQueueImpl.java
index 19826e7..113ab30 100644
--- a/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeQueueImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/devices/impl/TranscodeQueueImpl.java
@@ -1,1742 +1,1741 @@
-/*
- * Created on Feb 6, 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.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.*;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.config.ParameterListener;
-import org.gudy.azureus2.core3.disk.DiskManagerPiece;
-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.core3.util.AESemaphore;
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.AsyncDispatcher;
-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.FileUtil;
-import org.gudy.azureus2.core3.util.IndentWriter;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.disk.DiskManager;
-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.utils.DelayedTask;
-import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
-
-import com.aelitis.azureus.core.devices.*;
-import com.aelitis.azureus.core.download.DiskManagerFileInfoURL;
-import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-import com.aelitis.azureus.core.util.average.Average;
-import com.aelitis.azureus.core.util.average.AverageFactory;
-
-public class 
-TranscodeQueueImpl 	
-	implements TranscodeQueue
-{
-	private static final String	CONFIG_FILE 			= "xcodejobs.config";
-
-	private static final Object KEY_XCODE_ERROR	= new Object();
-	
-	private TranscodeManagerImpl		manager;
-	
-	private List<TranscodeJobImpl>		queue		= new ArrayList<TranscodeJobImpl>();
-	private AESemaphore 				queue_sem 	= new AESemaphore( "XcodeQ" );
-	private AEThread2					queue_thread;
-	
-	private volatile TranscodeJobImpl	current_job;
-	
-	private AsyncDispatcher	anaylsis_dispatcher = new AsyncDispatcher();
-	
-	private CopyOnWriteList<TranscodeQueueListener>			listeners = new CopyOnWriteList<TranscodeQueueListener>();
-	private CopyOnWriteList<TranscodeQueueActionListener>	action_listeners = new CopyOnWriteList<TranscodeQueueActionListener>();
-	
-	private volatile boolean 	paused;
-	private volatile int		max_bytes_per_sec;
-	
-	private volatile boolean	config_dirty;
-	
-	protected
-	TranscodeQueueImpl(
-		TranscodeManagerImpl	_manager )
-	{
-		manager = _manager;
-	}
-	
-	protected void
-	initialise()
-	{	
-		loadConfig();
-		
-		COConfigurationManager.addAndFireParameterListeners(
-			new String[]{
-				"xcode.queue.paused",
-				"xcode.queue.maxbps",
-			},
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					String		name )
-				{
-					paused				= COConfigurationManager.getBooleanParameter( "xcode.queue.paused", false );
-					max_bytes_per_sec	= COConfigurationManager.getIntParameter( "xcode.queue.maxbps", 0 );
-				}
-			});
-		
-		DelayedTask delayed_task = 
-			UtilitiesImpl.addDelayedTask(
-				"TranscodeQueue:schedule", 
-				new Runnable()
-				{
-					public void
-					run()
-					{
-						schedule();
-					}
-				});
-		
-		delayed_task.queue();
-	}
-	
-	protected boolean
-	process(
-		final TranscodeJobImpl		job )
-	{				
-		TranscodePipe pipe = null;
-		
-		current_job = job;
-		
-		DeviceImpl	device = job.getDevice();
-		
-		device.setTranscoding( true );
-		
-		try{
-			job.starts();
-			
-			TranscodeProvider provider = job.getProfile().getProvider();
-			
-			final TranscodeException[] error = { null };
-			
-			TranscodeProfile profile = job.getProfile();
-
-			final TranscodeFileImpl		transcode_file = job.getTranscodeFile();
-
-			TranscodeProviderAnalysis 	provider_analysis;
-			
-			boolean xcode_required;
-			
-			if ( provider == null ){
-				
-				xcode_required = false;
-				
-				provider_analysis = null;
-				
-			}else{
-				
-				provider_analysis = analyse( job );
-				
-				xcode_required 	= provider_analysis.getBooleanProperty( TranscodeProviderAnalysis.PT_TRANSCODE_REQUIRED );
-								
-				int	tt_req;
-
-				if ( job.isStream()){
-					
-						// already advertised as a transcoded asset so no option not to
-						// transcode (as name/format would change if decided not to transcode and then
-						// this would confuse the clients)
-					
-					tt_req = TranscodeTarget.TRANSCODE_ALWAYS;
-					
-				}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 ){
-					
-					xcode_required = false;
-					
-				}else if ( tt_req == TranscodeTarget.TRANSCODE_ALWAYS ){
-					
-					xcode_required 	= true;
-					
-					provider_analysis.setBooleanProperty( TranscodeProviderAnalysis.PT_FORCE_TRANSCODE, true );
-				}
-			}
-			
-			if ( xcode_required ){
-				
-				final AESemaphore xcode_sem = new AESemaphore( "xcode:proc" );
-				
-				final TranscodeProviderJob[] provider_job = { null }; 
-	
-				TranscodeProviderAdapter xcode_adapter = 
-					new TranscodeProviderAdapter()
-					{
-						private boolean	resolution_updated;
-					
-						private final int ETA_AVERAGE_SIZE	= 10;
-						
-						private int		last_eta;
-						private int		eta_samples;
-						private Average eta_average 		= AverageFactory.MovingAverage(ETA_AVERAGE_SIZE);
-						private int		last_percent;
-						
-						private long	initial_file_downloaded 	= job.getFile().getDownloaded();
-						private long	file_size				 	= job.getFile().getLength();
-													
-						public void
-						updateProgress(
-							int			percent,
-							int			eta_secs,
-							int			new_width,
-							int			new_height )
-						{
-							last_eta 		= eta_secs;
-							last_percent	= percent;
-							
-							TranscodeProviderJob	prov_job = provider_job[0];
-							
-							if ( prov_job == null ){
-								
-								return;
-							}
-							
-							int	job_state = job.getState();
-							
-							if ( 	job_state == TranscodeJob.ST_CANCELLED || 
-									job_state == TranscodeJob.ST_REMOVED ){
-																
-								prov_job.cancel();
-								
-							}else if ( paused || job_state == TranscodeJob.ST_PAUSED ){
-									
-								prov_job.pause();
-								
-							}else{
-								
-								if ( job_state == TranscodeJob.ST_RUNNING ){
-									
-									prov_job.resume();
-								}
-								
-								job.updateProgress( percent, eta_secs );
-								
-								prov_job.setMaxBytesPerSecond( max_bytes_per_sec );
-								
-								if ( !resolution_updated ){
-									
-									if ( new_width > 0 && new_height > 0 ){
-									
-										transcode_file.setResolution( new_width, new_height );
-										
-										resolution_updated = true;
-									}	
-								}
-							}
-						}
-						
-						public void
-						streamStats(
-							long					connect_rate,
-							long					write_speed )
-						{
-								// problem on OSX with some files thrashing the indirect piped input
-								// and eventually failing - try and spot this behaviour and revert
-								// to direct input if needed
-							
-							if ( 	Constants.isOSX &&
-									job.getEnableAutoRetry() && 
-									job.canUseDirectInput() && 
-									job.getAutoRetryCount() == 0 ){
-								
-								if ( connect_rate > 5 && last_percent < 100 ){
-									
-									long eta = (long)eta_average.update(last_eta );
-
-									eta_samples++;
-									
-									if ( eta_samples >= ETA_AVERAGE_SIZE ){
-										
-										long	total_time = (eta*100 )/(100-last_percent);
-										
-										long 	total_write = total_time*write_speed;
-										
-										DiskManagerFileInfo file = job.getFile();
-										
-										long	length = file.getLength();
-
-										if ( length > 0 ){
-
-											double over_write = ((double)total_write)/length;
-										
-											if ( over_write > 5.0 ){
-													
-												failed( new TranscodeException( "Overwrite limit exceeded, abandoning transcode" ));
-													
-												provider_job[0].cancel();		
-											}
-										}	
-									}
-								}else{
-									
-									eta_samples = 0;
-								}
-							}
-						}
-						
-						public void
-						failed(
-							TranscodeException		e )
-						{
-							try{
-								if ( error[0] == null ){
-								
-									error[0] = e;
-								}
-								
-								if ( e.isRetryDisabled()){
-									
-									job.setEnableAutoRetry( false );
-								}
-							}finally{
-								
-								xcode_sem.release();
-							}
-						}
-						
-						public void 
-						complete() 
-						{
-							try{
-									// sanity check: for incomplete files at the start of the process ensure that they have completed
-								
-								long	current_downloaded = job.getFile().getDownloaded();
-															
-								if ( file_size > 0 && initial_file_downloaded < file_size && current_downloaded < file_size ){
-									
-									if ( error[0] == null ){
-										
-											// actually this ain't so simple as we stream data prior to hash check completion (otherwise for
-											// large piece sizes we could be waiting for 4MB to complete downloading before playback)
-											// and getDownloaded() only returns the verified data size 
-										
-										long	contiguous_downloaded = 0;
-										
-										try{
-											DiskManagerFileInfo	_file_info = job.getFile();
-											
-											Download download = _file_info.getDownload();
-										
-											org.gudy.azureus2.core3.disk.DiskManagerFileInfo file_info = PluginCoreUtils.unwrap( _file_info );
-											
-											TOTorrentFile torrent_file = file_info.getTorrentFile();
-											
-											TOTorrent	torrent = torrent_file.getTorrent();
-											
-											TOTorrentFile[]	torrent_files = torrent.getFiles();
-											
-											long	byte_start = 0;
-											
-											for ( TOTorrentFile tf: torrent_files ){
-												
-												if ( tf == torrent_file ){
-													
-													break;
-												}
-												
-												byte_start += tf.getLength();
-											}
-											
-											DiskManager dm = download.getDiskManager();
-														
-											if ( dm == null ){
-												
-												throw( new Exception( "Download stopped" ));
-											}
-											
-											DiskManagerPiece[] pieces = PluginCoreUtils.unwrap( dm ).getPieces();
-											
-											long piece_size = torrent.getPieceLength();
-											
-											int	first_piece_index 	= (int)( byte_start / piece_size );
-											int	first_piece_offset	= (int)( byte_start % piece_size );
-											
-											int	last_piece_index	= torrent_file.getLastPieceNumber();
-																					
-											DiskManagerPiece	first_piece = pieces[first_piece_index];
-																							
-											if ( !first_piece.isDone()){
-												
-												boolean[] blocks = first_piece.getWritten();
-															
-												if ( blocks == null ){
-													
-													if ( first_piece.isDone()){
-														
-														contiguous_downloaded = first_piece.getLength() - first_piece_offset;
-													}
-												}else{
-													
-													int	piece_offset = 0;
-													
-													for (int j=0;j<blocks.length;j++){
-													
-														if ( blocks[j] ){
-														
-															int	block_size = first_piece.getBlockSize( j );
-															
-															piece_offset = piece_offset + block_size;
-															
-															if ( contiguous_downloaded == 0 ){
-															
-																if ( piece_offset > first_piece_offset ){
-																	
-																	contiguous_downloaded = piece_offset - first_piece_offset;
-																}
-															}else{
-																
-																contiguous_downloaded += block_size;
-															}						
-														}else{
-															
-															break;
-														}
-													}
-												}	
-											}else{
-											
-												contiguous_downloaded = first_piece.getLength() - first_piece_offset; 
-											
-												for (int i=first_piece_index+1;i<=last_piece_index;i++){
-																									
-													DiskManagerPiece piece = pieces[i];
-													
-													if ( piece.isDone()){
-														
-														contiguous_downloaded += piece.getLength();
-														
-													}else{
-													
-														boolean[] blocks = piece.getWritten();
-																
-														if ( blocks == null ){
-															
-															if ( piece.isDone()){
-														
-																contiguous_downloaded += piece.getLength();
-																
-															}else{
-																
-																break;
-															}
-														}else{
-															
-															for (int j=0;j<blocks.length;j++){
-															
-																if ( blocks[j] ){
-																
-																	contiguous_downloaded += piece.getBlockSize( j );
-																	
-																}else{
-																	
-																	break;
-																}
-															}
-														}
-														
-														break;
-													}
-												}
-											}
-										}catch( Throwable e ){
-											
-											// Debug.out( e );
-										}
-										
-										if ( contiguous_downloaded < file_size ){
-										
-												// things might have improved, check again
-											
-											current_downloaded = job.getFile().getDownloaded();
-											
-											if ( current_downloaded < file_size ){
-		
-												Debug.out( "Premature transcode termination: init=" + initial_file_downloaded + ", curr=" + current_downloaded + ", len=" + file_size );
-		
-												error[0] = new TranscodeException( "Transcode terminated prematurely" );
-											}
-										}
-									}
-								}
-							}finally{
-							
-								xcode_sem.release();
-							}
-						}
-					};
-				
-				boolean	direct_input = job.useDirectInput();
-					
-				if ( job.isStream()){
-					
-					/*
-					provider_job[0] = 
-						provider.transcode(
-							adapter,
-							job.getFile(),
-							profile,
-							new File( "C:\\temp\\arse").toURI().toURL());
-					*/
-					
-					pipe = new TranscodePipeStreamSource2(
-								new TranscodePipeStreamSource2.streamListener()
-								{
-									public void 
-									gotStream(
-										InputStream is ) 
-									{
-										job.setStream( is );
-									}
-								});
-					
-					provider_job[0] = 
-						provider.transcode(
-							xcode_adapter,
-							provider_analysis,
-							direct_input,
-							job.getFile(),
-							profile,
-							new URL( "tcp://127.0.0.1:" + pipe.getPort()));
-	
-				}else{
-										
-					File output_file = transcode_file.getCacheFile();
-					
-					provider_job[0] = 
-						provider.transcode(
-							xcode_adapter,
-							provider_analysis,
-							direct_input,
-							job.getFile(),
-							profile,
-							output_file.toURI().toURL());
-				}
-				
-				provider_job[0].setMaxBytesPerSecond( max_bytes_per_sec );
-				
-				TranscodeQueueListener listener = 
-					new TranscodeQueueListener()
-					{
-						public void
-						jobAdded(
-							TranscodeJob		job )
-						{					
-						}
-						
-						public void
-						jobChanged(
-							TranscodeJob		changed_job )
-						{
-							if ( changed_job == job ){
-								
-								int	state = job.getState();
-								
-								if ( state == TranscodeJob.ST_PAUSED ){
-									
-									provider_job[0].pause();
-									
-								}else if ( state == TranscodeJob.ST_RUNNING ){
-										
-									provider_job[0].resume();
-									
-								}else if ( 	state == TranscodeJob.ST_CANCELLED ||
-											state == TranscodeJob.ST_STOPPED ){
-								
-									provider_job[0].cancel();
-								}
-							}
-						}
-						
-						public void
-						jobRemoved(
-							TranscodeJob		removed_job )
-						{	
-							if ( removed_job == job ){
-								
-								provider_job[0].cancel();
-							}
-						}
-					};
-					
-				try{
-					addListener( listener );
-				
-					xcode_sem.reserve();
-					
-				}finally{
-					
-					removeListener( listener );
-				}
-				
-				if ( error[0] != null ){
-					
-					throw( error[0] );
-				}
-			}else{
-				
-					// no transcode required...
-				
-				DiskManagerFileInfo source = job.getFile();
-				
-				transcode_file.setTranscodeRequired( false );
-				
-				if ( job.isStream()){
-					
-					PluginInterface av_pi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByID( "azupnpav" );
-					
-					if ( av_pi == null ){
-					
-						throw( new TranscodeException( "Media Server plugin not found" ));
-					}
-					
-					IPCInterface av_ipc = av_pi.getIPC();
-					
-					String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ source });
-					
-					
-					if ( url_str == null || url_str.length() == 0 ){
-						
-							// see if we can use the file directly
-						
-						File source_file = source.getFile();
-						
-						if ( source_file.exists()){
-							
-							job.setStream( new BufferedInputStream( new FileInputStream( source_file )));
-							
-						}else{
-							
-							throw( new TranscodeException( "No UPnPAV URL and file doesn't exist" ));
-						}
-					}else{
-						
-						URL source_url = new URL( url_str );
-					
-						job.setStream( source_url.openConnection().getInputStream());
-					}
-				}else{
-					boolean url_input_source = source instanceof DiskManagerFileInfoURL;
-					
-					if ( device.getAlwaysCacheFiles() || url_input_source ){
-						
-						PluginInterface av_pi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByID( "azupnpav" );
-						
-						if ( av_pi == null ){
-						
-							throw( new TranscodeException( "Media Server plugin not found" ));
-						}
-						
-						IPCInterface av_ipc = av_pi.getIPC();
-						
-						String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ source });
-						
-						InputStream	is;
-						
-						long		length;
-						
-						if ( url_str == null || url_str.length() == 0 ){
-							
-								// see if we can use the file directly
-							
-							if ( url_input_source ){
-								
-								((DiskManagerFileInfoURL)source).download();
-							}
-							
-							File source_file = source.getFile();
-							
-							if ( source_file.exists()){
-								
-								is = new BufferedInputStream( new FileInputStream( source_file ));
-								
-								length = source_file.length();
-								
-							}else{
-								
-								throw( new TranscodeException( "No UPnPAV URL and file doesn't exist" ));
-							}
-						}else{
-							
-							URL source_url = new URL( url_str );
-						
-							URLConnection connection = source_url.openConnection();
-							
-							is = source_url.openConnection().getInputStream();
-							
-							String s = connection.getHeaderField( "content-length" );
-							
-							if ( s != null ){
-								
-								length = Long.parseLong( s );
-								
-							}else{
-								
-								length = -1;
-							}
-						}
-						
-						OutputStream	os = null;
-						
-						final boolean[]	cancel_copy = { false };
-						
-						TranscodeQueueListener copy_listener = 
-							new TranscodeQueueListener()
-							{
-								public void
-								jobAdded(
-									TranscodeJob		job )
-								{					
-								}
-								
-								public void
-								jobChanged(
-									TranscodeJob		changed_job )
-								{
-									if ( changed_job == job ){
-										
-										int	state = job.getState();
-										
-										if ( state == TranscodeJob.ST_PAUSED ){
-																						
-										}else if ( state == TranscodeJob.ST_RUNNING ){
-																							
-										}else if ( 	state == TranscodeJob.ST_CANCELLED ||
-													state == TranscodeJob.ST_STOPPED ){
-										
-											cancel_copy[0] = true;
-										}
-									}
-								}
-								
-								public void
-								jobRemoved(
-									TranscodeJob		removed_job )
-								{	
-									if ( removed_job == job ){
-										
-										cancel_copy[0] = true;
-									}
-								}
-							};
-							
-						try{
-							addListener( copy_listener );
-
-							os = new FileOutputStream( transcode_file.getCacheFile());
-							
-							long	total_copied = 0;
-							
-							byte[] buffer = new byte[128*1024];
-							
-							while( true ){
-								
-								if ( cancel_copy[0] ){
-									
-									throw( new TranscodeException( "Copy cancelled" ));
-								}
-								
-								int	len = is.read( buffer );
-								
-								if ( len <= 0 ){
-									
-									break;
-								}
-								
-								os.write( buffer, 0, len );
-								
-								total_copied += len;
-								
-								if ( length > 0 ){
-								
-									job.updateProgress((int)( total_copied*100/length ), -1 );
-								}
-								
-								total_copied += len;
-							}
-						}finally{
-							
-							try{
-								is.close();
-								
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-							
-							try{
-								if ( os != null ){
-								
-									os.close();
-								}
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-							
-							removeListener( copy_listener );
-						}
-					}
-				}
-			}
-			
-			job.complete();
-			
-			return( true );
-			
-		}catch( Throwable e ){
-			
-			job.failed( e );
-			
-			e.printStackTrace();
-			
-			if ( 	!job.isStream() &&
-					job.getEnableAutoRetry() && 
-					job.getAutoRetryCount() == 0 && 
-					job.canUseDirectInput() && 
-					!job.useDirectInput()){
-				
-				log( "Auto-retrying transcode with direct input" );
-				
-				job.setUseDirectInput();
-				
-				job.setAutoRetry( true );
-				
-				queue_sem.release();
-			}
-			
-			return( false );
-			
-		}finally{
-			
-			if ( pipe != null ){
-				
-				pipe.destroy();
-			}
-			
-			device.setTranscoding( false );
-
-			current_job = null;
-		}
-	}
-	
-	protected void
-	schedule()
-	{
-		synchronized( this ){
-
-			if ( queue.size() > 0 && queue_thread == null ){
-				
-				queue_thread = new
-					AEThread2( "XcodeQ", true )
-					{
-						public void 
-						run() 
-						{
-							try{
-								while( true ){
-									
-									checkJobStatus();
-									
-									boolean got = queue_sem.reserve( 30*1000 );
-																			
-									TranscodeJobImpl	job = null;
-									
-									synchronized( TranscodeQueueImpl.this ){
-										
-										if ( !got ){
-											
-											if ( queue.size() == 0 ){
-												
-												queue_thread = null;
-												
-												return;
-											}
-										}
-										
-										for ( TranscodeJobImpl j: queue ){
-											
-											int state = j.getState();
-											
-												// pick up any existing paused ones (remember, paused=running but with transcode paused
-												
-											if ( state == TranscodeJob.ST_FAILED && j.isAutoRetry()){
-												
-												j.setAutoRetry( false );
-												
-												j.reset();
-												
-												job	= j;
-												
-												break;
-												
-											}else if ( state == TranscodeJob.ST_PAUSED ){
-	
-													// remember paused here is paused after an azureus
-													// restart as 'process' blocks on pause
-												
-												job = j;
-												
-											}else if ( state == TranscodeJob.ST_QUEUED ){
-												
-												if ( job == null && j.getDownloadETA() == 0 ){
-												
-													job = j;
-												}
-											}
-										}
-									}
-									
-									checkJobStatus();
-
-									if ( job != null ){
-									
-										if ( process( job )){
-										
-											try{
-												remove( job, true );
-												
-											}catch( TranscodeActionVetoException e ){
-												
-												Debug.out( e );
-											}
-										}																			
-									}
-								}
-							}finally{
-								
-								checkJobStatus();
-							}
-						}
-					};
-					
-				queue_thread.start();
-			}
-		}
-	}
-	
-	protected void
-	updateStatus(
-		int	tick_count )
-	{
-		int queue_size;
-		
-		synchronized( this ){
-			
-			queue_size = queue.size();
-		}
-		
-		if ( queue_size > 0 ){
-			
-			TranscodeJobImpl[] jobs = getJobs();
-			
-			for ( TranscodeJobImpl job: jobs ){
-				
-				job.updateStatus();
-			}
-		}	
-	}
-	
-	protected void
-	checkJobStatus()
-	{
-		Set<DeviceImpl> devices = new HashSet<DeviceImpl>( Arrays.asList(manager.getManager().getDevices()));
-		
-		synchronized( this ){
-			
-			for ( TranscodeJobImpl j: queue ){
-
-				if ( j.getState() == TranscodeJob.ST_FAILED ){
-					
-					DeviceImpl	device = j.getDevice();
-					
-					device.setError( KEY_XCODE_ERROR, MessageText.getString( "device.error.xcodefail" ));
-					
-					devices.remove( device );
-				}
-			}
-		}
-		
-		for ( DeviceImpl device: devices ){
-			
-			device.setError( KEY_XCODE_ERROR, null );
-		}
-	}
-	
-	public TranscodeJobImpl
-	add(
-		TranscodeTarget			target,
-		TranscodeProfile		profile,
-		DiskManagerFileInfo		file,
-		boolean					add_stopped )
-	
-		throws TranscodeException
-	{
-		return( add( target, profile, file, add_stopped, false, TranscodeTarget.TRANSCODE_UNKNOWN ));
-	}
-	
-	public TranscodeJobImpl
-	add(
-		TranscodeTarget			target,
-		TranscodeProfile		profile,
-		DiskManagerFileInfo		file,
-		int						transcode_requirement,
-		boolean					add_stopped )
-	
-		throws TranscodeException
-	{
-		return( add( target, profile, file, add_stopped, false, transcode_requirement ));
-	}
-	
-	public TranscodeJobImpl
-	add(
-		TranscodeTarget			target,
-		TranscodeProfile		profile,
-		DiskManagerFileInfo		file,
-		boolean					add_stopped,
-		boolean					stream,
-		int						transcode_requirement )
-	
-		throws TranscodeException
-	{
-		TranscodeFileImpl existing_tf = ((DeviceImpl)target.getDevice()).lookupFile( profile, file );
-		
-		if ( existing_tf != null ){
-			
-			List<TranscodeJobImpl>	to_remove = new ArrayList<TranscodeJobImpl>();
-			
-			synchronized( this ){
-	
-				for ( TranscodeJobImpl job: queue ){
-					
-					if ( job.getTarget() == target && job.getTranscodeFile().equals( existing_tf )){
-						
-						to_remove.add( job );
-					}
-				}
-			}
-			
-			for ( TranscodeJobImpl job: to_remove ){
-	
-				job.removeForce();
-			}
-			
-			if ( !stream ){
-			
-				existing_tf.delete( true );
-			}
-		}
-		
-		TranscodeJobImpl job = new TranscodeJobImpl( this, target, profile, file, add_stopped, transcode_requirement, stream );
-		
-		try{
-			synchronized( this ){
-				
-				queue.add( job );
-				
-				queue_sem.release();
-				
-				configDirty();
-			}
-			
-			for ( TranscodeQueueListener listener: listeners ){
-				
-				try{
-					listener.jobAdded( job );
-					
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace( e );
-				}
-			}
-		}finally{
-		
-			schedule();
-		}
-		
-		return( job );
-	}
-	
-	protected void
-	remove(
-		TranscodeJobImpl		job,
-		boolean					force )
-	
-		throws TranscodeActionVetoException
-	{
-		synchronized( this ){
-			
-			if ( !queue.contains( job )){
-				
-				return;
-			}
-		}
-		
-		if ( !force ){
-			
-			for ( TranscodeQueueActionListener l: action_listeners ){
-				
-				try{
-					l.jobWillBeActioned( job, TranscodeQueueActionListener.ACT_REMOVE );
-					
-				}catch( TranscodeActionVetoException e ){
-					
-					throw( e );
-					
-				}catch( Throwable e ){
-					
-					Debug.out( e);
-				}
-			}
-		}
-		
-		synchronized( this ){
-			
-			if ( !queue.remove( job )){
-				
-				return;
-			}
-		}
-		
-		configDirty();
-
-		job.destroy();
-		
-		for ( TranscodeQueueListener listener: listeners ){
-			
-			try{
-				listener.jobRemoved( job );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace( e );
-			}
-		}
-		
-		checkJobStatus();
-		
-		schedule();
-	}
-	
-	protected void
-	jobChanged(
-		TranscodeJob			job,
-		boolean					schedule,
-		boolean					persistable )
-	{
-
-		for ( TranscodeQueueListener listener: listeners ){
-			
-			try{
-				listener.jobChanged( job );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace( e );
-			}
-		}
-		
-		if ( persistable ){
-		
-			configDirty();
-		}
-		
-		if ( schedule ){
-			
-			queue_sem.release();
-			
-			schedule();
-		}
-	}
-	
-	protected int
-	getIndex(
-		TranscodeJobImpl		job )
-	{
-		synchronized( this ){
-		
-			return( queue.indexOf(job)+1);
-		}
-	}
-	
-	public TranscodeJobImpl[]
-	getJobs()
-	{
-		synchronized( this ){
-
-			return( queue.toArray( new TranscodeJobImpl[queue.size()]));
-		}
-	}
-	
-	public int
-	getJobCount()
-	{
-		synchronized( this ){
-
-			return( queue.size());
-		}	
-	}
-	
-	public TranscodeJob
-	getCurrentJob()
-	{
-		return( current_job );
-	}
-	
-	public boolean
-	isTranscoding()
-	{
-		return( current_job != null );
-	}
-	
-	protected TranscodeJobImpl
-	getJob(
-		TranscodeFile		for_file )
-	{
-		synchronized( this ){
-
-			for ( TranscodeJobImpl job: queue ){
-				
-				if ( job.getTranscodeFile().equals( for_file )){
-					
-					return( job );
-				}
-			}
-		}
-		
-		return( null );
-	}
-	
-	public void 
-	moveUp(
-		TranscodeJobImpl	job )
-	{
-		TranscodeJob[] updated;
-			
-		synchronized( this ){
-		
-			int index = queue.indexOf( job );
-			
-			if ( index <= 0 || queue.size() == 1 ){
-				
-				return;
-			}
-			
-			queue.remove( job );
-			
-			queue.add( index-1, job );
-			
-			updated = getJobs();
-		}
-		
-		for ( TranscodeJob j: updated ){
-			
-			jobChanged( j, false, true );
-		}
-	}
-	
-	public void 
-	moveDown(
-		TranscodeJobImpl	job )
-	{
-		TranscodeJob[] updated;
-
-		synchronized( this ){
-		
-			int index = queue.indexOf( job );
-			
-			if ( index < 0 || index == queue.size() - 1 ){
-				
-				return;
-			}
-			
-			queue.remove( job );
-			
-			queue.add( index+1, job );
-			
-			updated = getJobs();
-		}
-		
-		for ( TranscodeJob j: updated ){
-			
-			jobChanged( j, false, true );
-		}
-	}
-	
-	public void
-	pause()
-	{
-		if ( !paused ){
-			
-			if ( paused ){
-				
-				COConfigurationManager.setParameter( "xcode.paused", true );
-			}
-		}
-	}
-	
-	public boolean
-	isPaused()
-	{
-		return( paused );
-	}
-	
-	public void
-	resume()
-	{
-		if ( paused ){
-			
-			COConfigurationManager.setParameter( "xcode.queue.paused", false );
-		}
-	}
-	
-	public long
-	getMaxBytesPerSecond()
-	{
-		return( max_bytes_per_sec );
-	}
-	
-	public void
-	setMaxBytesPerSecond(
-		long		max )
-	{
-		COConfigurationManager.setParameter( "xcode.queue.maxbps", max );
-	}
-	
-	protected TranscodeTarget
-	lookupTarget(
-		String		target_id )
-	
-		throws TranscodeException
-	{
-		return( manager.lookupTarget( target_id ));
-	}
-	
-	protected TranscodeProfile
-	lookupProfile(
-		String		profile_id )
-	
-		throws TranscodeException
-	{
-		TranscodeProfile profile = manager.getProfileFromUID( profile_id );
-		
-		if ( profile == null ){
-			
-			throw( new TranscodeException( "Transcode profile with id '" + profile_id + "' not found" ));
-		}
-		
-		return( profile );
-	}
-	
-	protected DiskManagerFileInfo
-	lookupFile(
-		byte[]		hash,
-		int			index )
-	
-		throws TranscodeException
-	{
-		return( manager.lookupFile( hash, index ));
-	}
-	
-	protected void
-	analyse(
-		final TranscodeJobImpl			job,
-		final TranscodeAnalysisListener	listener )
-	
-		throws TranscodeException
-	{
-		anaylsis_dispatcher.dispatch(
-			new AERunnable()
-			{
-				public void 
-				runSupport() 
-				{
-					try{
-						TranscodeProviderAnalysis analysis = analyse( job );
-		
-						listener.analysisComplete( job, analysis );
-						
-					}catch( TranscodeException e ){
-						
-						listener.analysisFailed( job, e );
-						
-					}catch( Throwable e ){
-						
-						listener.analysisFailed( job, new TranscodeException( "Analysis failed", e ));
-					}
-				}
-			});
-	}
-	
-	protected TranscodeProviderAnalysis
-	analyse(
-		final TranscodeJobImpl			job )
-	
-		throws TranscodeException
-	{
-		TranscodeProvider provider = job.getProfile().getProvider();
-	
-		if ( provider == null ){
-			
-			throw( new TranscodeException( "Transcode provider not available" ));
-		}
-		
-		final TranscodeException[] error = { null };
-		
-		TranscodeProfile profile = job.getProfile();
-			
-		final AESemaphore analysis_sem = new AESemaphore( "analysis:proc" );		
-
-		final boolean	was_stopped = job.getState() == TranscodeJob.ST_STOPPED;
-		
-		TranscodeProviderAdapter analysis_adapter = 
-			new TranscodeProviderAdapter()
-			{
-				public void
-				updateProgress(
-					int		percent,
-					int		eta_secs,
-					int		width,
-					int		height )
-				{
-				}
-				
-				public void
-				streamStats(
-					long					connect_rate,
-					long					write_speed )
-				{
-				}
-				
-				public void
-				failed(
-					TranscodeException		e )
-				{
-					error[0] = e;
-					
-					analysis_sem.release();
-				}
-				
-				public void 
-				complete() 
-				{
-					analysis_sem.release();
-				}
-			};
-			
-		final TranscodeProviderAnalysis provider_analysis =	provider.analyse( analysis_adapter, job.getFile(), profile );
-		
-		TranscodeQueueListener analysis_q_listener = 
-			new TranscodeQueueListener()
-			{
-				public void
-				jobAdded(
-					TranscodeJob		job )
-				{					
-				}
-				
-				public void
-				jobChanged(
-					TranscodeJob		changed_job )
-				{
-					if ( changed_job == job ){
-						
-						int	state = job.getState();
-						
-						if ( 	state == TranscodeJob.ST_CANCELLED ){
-							
-							provider_analysis.cancel();
-							
-						}else if ( 	state == TranscodeJob.ST_STOPPED ){
-						
-								// only treat this as a failure if the job was initially
-								// running and has been explicitly stopped
-							
-							if ( !was_stopped ){
-							
-								provider_analysis.cancel();
-							}
-						}
-					}
-				}
-				
-				public void
-				jobRemoved(
-					TranscodeJob		removed_job )
-				{	
-					if ( removed_job == job ){
-						
-						provider_analysis.cancel();
-					}
-				}
-			};
-			
-		try{
-			addListener( analysis_q_listener );
-		
-			analysis_sem.reserve();
-			
-		}finally{
-			
-			removeListener( analysis_q_listener );
-		}
-		
-		if ( error[0] != null ){
-			
-			throw( error[0] );
-		}
-				
-		TranscodeFileImpl		transcode_file = job.getTranscodeFile();
-
-		transcode_file.update( provider_analysis );
-		
-		return( provider_analysis );
-	}
-	
-	protected void
-	configDirty()
-	{
-		synchronized( this ){
-			
-			if ( config_dirty ){
-				
-				return;
-			}
-			
-			config_dirty = true;
-		
-			new DelayedEvent( 
-				"TranscodeQueue:save", 5000,
-				new AERunnable()
-				{
-					public void 
-					runSupport() 
-					{
-						synchronized( TranscodeQueueImpl.this ){
-							
-							if ( !config_dirty ){
-
-								return;
-							}
-							
-							saveConfig();
-						}	
-					}
-				});
-		}
-	}
-	
-	protected void
-	loadConfig()
-	{
-		if ( !FileUtil.resilientConfigFileExists( CONFIG_FILE )){
-			
-			return;
-		}
-		
-		log( "Loading configuration" );
-			
-		try{
-			synchronized( this ){
-				
-				Map map = FileUtil.readResilientConfigFile( CONFIG_FILE );
-				
-				List<Map<String,Object>>	l_jobs = (List<Map<String,Object>>)map.get( "jobs" );
-				
-				if ( l_jobs != null ){
-					
-					for ( Map<String,Object> m: l_jobs ){
-						
-						try{
-							TranscodeJobImpl job = new TranscodeJobImpl( this, m );
-						
-							queue.add(job );
-							
-							queue_sem.release();
-							
-						}catch( Throwable e ){
-							
-							log( "Failed to restore job: " + m, e );
-						}
-					}
-				}
-			}
-		}catch( Throwable e ){
-			
-			log( "Configuration load failed", e );
-		}
-	}
-	
-	protected void
-	saveConfig()
-	{
-		synchronized( this ){
-
-			config_dirty = false;
-			
-			if ( queue.size() == 0 ){
-
-				FileUtil.deleteResilientConfigFile( CONFIG_FILE );
-
-			}else{
-				
-				Map<String,Object>	map = new HashMap<String,Object>();
-				
-				List<Map<String,Object>>	l_jobs = new ArrayList<Map<String,Object>>();
-				
-				map.put( "jobs", l_jobs );
-				
-				for ( TranscodeJobImpl job: queue ){
-				
-					if ( job.isStream()){
-						
-						continue;
-					}
-					
-					try{
-					
-						l_jobs.add( job.toMap());
-						
-					}catch( Throwable e ){
-						
-						log( "Failed to save job", e );
-					}
-				}
-				
-				FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
-			}
-		}
-	}
-	
-	protected void
-	close()
-	{
-		if ( config_dirty ){
-		
-			saveConfig();
-		}
-	}
-	
-	public void
-	addListener(
-		TranscodeQueueListener		listener )
-	{
-		if (!listeners.contains(listener)) {
-			listeners.add( listener );
-		}
-	}
-	
-	public void
-	removeListener(
-		TranscodeQueueListener		listener )
-	{
-		listeners.remove( listener );	
-	}
-	
-	public void
-	addActionListener(
-		TranscodeQueueActionListener		listener )
-	{
-		action_listeners.add( listener );
-	}
-	
-	public void
-	removeActionListener(
-		TranscodeQueueActionListener		listener )
-	{
-		action_listeners.remove( listener );	
-	}
-	
-	protected void
-	log( 
-		String	str )
-	{
-		manager.log( "Queue: " + str );
-	}
-	
-	protected void
-	log( 
-		String		str,
-		Throwable	e )
-	{
-		manager.log( "Queue: " + str, e );
-	}
-	
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		writer.println( "Transcode Queue: paused=" + paused + ",max_bps=" + max_bytes_per_sec );
-		
-		try{
-			writer.indent();
-	
-			TranscodeJobImpl[] jobs = getJobs();
-			
-			for ( TranscodeJobImpl job: jobs ){
-				
-				job.generate( writer );
-			}
-		}finally{
-			
-			writer.exdent();
-		}
-	}
-}
+/*
+ * Created on Feb 6, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.devices.impl;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.*;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.config.ParameterListener;
+import org.gudy.azureus2.core3.disk.DiskManagerPiece;
+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.core3.util.AESemaphore;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
+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.FileUtil;
+import org.gudy.azureus2.core3.util.IndentWriter;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.disk.DiskManager;
+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.utils.DelayedTask;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
+
+import com.aelitis.azureus.core.devices.*;
+import com.aelitis.azureus.core.download.DiskManagerFileInfoURL;
+import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.core.util.average.Average;
+import com.aelitis.azureus.core.util.average.AverageFactory;
+
+public class 
+TranscodeQueueImpl 	
+	implements TranscodeQueue
+{
+	private static final String	CONFIG_FILE 			= "xcodejobs.config";
+
+	private static final Object KEY_XCODE_ERROR	= new Object();
+	
+	private TranscodeManagerImpl		manager;
+	
+	private List<TranscodeJobImpl>		queue		= new ArrayList<TranscodeJobImpl>();
+	private AESemaphore 				queue_sem 	= new AESemaphore( "XcodeQ" );
+	private AEThread2					queue_thread;
+	
+	private volatile TranscodeJobImpl	current_job;
+	
+	private AsyncDispatcher	anaylsis_dispatcher = new AsyncDispatcher();
+	
+	private CopyOnWriteList<TranscodeQueueListener>			listeners = new CopyOnWriteList<TranscodeQueueListener>();
+	private CopyOnWriteList<TranscodeQueueActionListener>	action_listeners = new CopyOnWriteList<TranscodeQueueActionListener>();
+	
+	private volatile boolean 	paused;
+	private volatile int		max_bytes_per_sec;
+	
+	private volatile boolean	config_dirty;
+	
+	protected
+	TranscodeQueueImpl(
+		TranscodeManagerImpl	_manager )
+	{
+		manager = _manager;
+	}
+	
+	protected void
+	initialise()
+	{	
+		loadConfig();
+		
+		COConfigurationManager.addAndFireParameterListeners(
+			new String[]{
+				"xcode.queue.paused",
+				"xcode.queue.maxbps",
+			},
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					String		name )
+				{
+					paused				= COConfigurationManager.getBooleanParameter( "xcode.queue.paused", false );
+					max_bytes_per_sec	= COConfigurationManager.getIntParameter( "xcode.queue.maxbps", 0 );
+				}
+			});
+		
+		DelayedTask delayed_task = 
+			UtilitiesImpl.addDelayedTask(
+				"TranscodeQueue:schedule", 
+				new Runnable()
+				{
+					public void
+					run()
+					{
+						schedule();
+					}
+				});
+		
+		delayed_task.queue();
+	}
+	
+	protected boolean
+	process(
+		final TranscodeJobImpl		job )
+	{				
+		TranscodePipe pipe = null;
+		
+		current_job = job;
+		
+		DeviceImpl	device = job.getDevice();
+		
+		device.setTranscoding( true );
+		
+		try{
+			job.starts();
+			
+			TranscodeProvider provider = job.getProfile().getProvider();
+			
+			final TranscodeException[] error = { null };
+			
+			TranscodeProfile profile = job.getProfile();
+
+			final TranscodeFileImpl		transcode_file = job.getTranscodeFile();
+
+			TranscodeProviderAnalysis 	provider_analysis;
+			
+			boolean xcode_required;
+			
+			if ( provider == null ){
+				
+				xcode_required = false;
+				
+				provider_analysis = null;
+				
+			}else{
+				
+				provider_analysis = analyse( job );
+				
+				xcode_required 	= provider_analysis.getBooleanProperty( TranscodeProviderAnalysis.PT_TRANSCODE_REQUIRED );
+								
+				int	tt_req;
+
+				if ( job.isStream()){
+					
+						// already advertised as a transcoded asset so no option not to
+						// transcode (as name/format would change if decided not to transcode and then
+						// this would confuse the clients)
+					
+					tt_req = TranscodeTarget.TRANSCODE_ALWAYS;
+					
+				}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 ){
+					
+					xcode_required = false;
+					
+				}else if ( tt_req == TranscodeTarget.TRANSCODE_ALWAYS ){
+					
+					xcode_required 	= true;
+					
+					provider_analysis.setBooleanProperty( TranscodeProviderAnalysis.PT_FORCE_TRANSCODE, true );
+				}
+			}
+			
+			if ( xcode_required ){
+				
+				final AESemaphore xcode_sem = new AESemaphore( "xcode:proc" );
+				
+				final TranscodeProviderJob[] provider_job = { null }; 
+	
+				TranscodeProviderAdapter xcode_adapter = 
+					new TranscodeProviderAdapter()
+					{
+						private boolean	resolution_updated;
+					
+						private final int ETA_AVERAGE_SIZE	= 10;
+						
+						private int		last_eta;
+						private int		eta_samples;
+						private Average eta_average 		= AverageFactory.MovingAverage(ETA_AVERAGE_SIZE);
+						private int		last_percent;
+						
+						private long	initial_file_downloaded 	= job.getFile().getDownloaded();
+						private long	file_size				 	= job.getFile().getLength();
+													
+						public void
+						updateProgress(
+							int			percent,
+							int			eta_secs,
+							int			new_width,
+							int			new_height )
+						{
+							last_eta 		= eta_secs;
+							last_percent	= percent;
+							
+							TranscodeProviderJob	prov_job = provider_job[0];
+							
+							if ( prov_job == null ){
+								
+								return;
+							}
+							
+							int	job_state = job.getState();
+							
+							if ( 	job_state == TranscodeJob.ST_CANCELLED || 
+									job_state == TranscodeJob.ST_REMOVED ){
+																
+								prov_job.cancel();
+								
+							}else if ( paused || job_state == TranscodeJob.ST_PAUSED ){
+									
+								prov_job.pause();
+								
+							}else{
+								
+								if ( job_state == TranscodeJob.ST_RUNNING ){
+									
+									prov_job.resume();
+								}
+								
+								job.updateProgress( percent, eta_secs );
+								
+								prov_job.setMaxBytesPerSecond( max_bytes_per_sec );
+								
+								if ( !resolution_updated ){
+									
+									if ( new_width > 0 && new_height > 0 ){
+									
+										transcode_file.setResolution( new_width, new_height );
+										
+										resolution_updated = true;
+									}	
+								}
+							}
+						}
+						
+						public void
+						streamStats(
+							long					connect_rate,
+							long					write_speed )
+						{
+								// problem on OSX with some files thrashing the indirect piped input
+								// and eventually failing - try and spot this behaviour and revert
+								// to direct input if needed
+							
+							if ( 	Constants.isOSX &&
+									job.getEnableAutoRetry() && 
+									job.canUseDirectInput() && 
+									job.getAutoRetryCount() == 0 ){
+								
+								if ( connect_rate > 5 && last_percent < 100 ){
+									
+									long eta = (long)eta_average.update(last_eta );
+
+									eta_samples++;
+									
+									if ( eta_samples >= ETA_AVERAGE_SIZE ){
+										
+										long	total_time = (eta*100 )/(100-last_percent);
+										
+										long 	total_write = total_time*write_speed;
+										
+										DiskManagerFileInfo file = job.getFile();
+										
+										long	length = file.getLength();
+
+										if ( length > 0 ){
+
+											double over_write = ((double)total_write)/length;
+										
+											if ( over_write > 5.0 ){
+													
+												failed( new TranscodeException( "Overwrite limit exceeded, abandoning transcode" ));
+													
+												provider_job[0].cancel();		
+											}
+										}	
+									}
+								}else{
+									
+									eta_samples = 0;
+								}
+							}
+						}
+						
+						public void
+						failed(
+							TranscodeException		e )
+						{
+							try{
+								if ( error[0] == null ){
+								
+									error[0] = e;
+								}
+								
+								if ( e.isRetryDisabled()){
+									
+									job.setEnableAutoRetry( false );
+								}
+							}finally{
+								
+								xcode_sem.release();
+							}
+						}
+						
+						public void 
+						complete() 
+						{
+							try{
+									// sanity check: for incomplete files at the start of the process ensure that they have completed
+								
+								long	current_downloaded = job.getFile().getDownloaded();
+															
+								if ( file_size > 0 && initial_file_downloaded < file_size && current_downloaded < file_size ){
+									
+									if ( error[0] == null ){
+										
+											// actually this ain't so simple as we stream data prior to hash check completion (otherwise for
+											// large piece sizes we could be waiting for 4MB to complete downloading before playback)
+											// and getDownloaded() only returns the verified data size 
+										
+										long	contiguous_downloaded = 0;
+										
+										try{
+											DiskManagerFileInfo	_file_info = job.getFile();
+											
+											Download download = _file_info.getDownload();
+										
+											org.gudy.azureus2.core3.disk.DiskManagerFileInfo file_info = PluginCoreUtils.unwrap( _file_info );
+											
+											TOTorrentFile torrent_file = file_info.getTorrentFile();
+											
+											TOTorrent	torrent = torrent_file.getTorrent();
+											
+											TOTorrentFile[]	torrent_files = torrent.getFiles();
+											
+											long	byte_start = 0;
+											
+											for ( TOTorrentFile tf: torrent_files ){
+												
+												if ( tf == torrent_file ){
+													
+													break;
+												}
+												
+												byte_start += tf.getLength();
+											}
+											
+											DiskManager dm = download.getDiskManager();
+														
+											if ( dm == null ){
+												
+												throw( new Exception( "Download stopped" ));
+											}
+											
+											DiskManagerPiece[] pieces = PluginCoreUtils.unwrap( dm ).getPieces();
+											
+											long piece_size = torrent.getPieceLength();
+											
+											int	first_piece_index 	= (int)( byte_start / piece_size );
+											int	first_piece_offset	= (int)( byte_start % piece_size );
+											
+											int	last_piece_index	= torrent_file.getLastPieceNumber();
+																					
+											DiskManagerPiece	first_piece = pieces[first_piece_index];
+																							
+											if ( !first_piece.isDone()){
+												
+												boolean[] blocks = first_piece.getWritten();
+															
+												if ( blocks == null ){
+													
+													if ( first_piece.isDone()){
+														
+														contiguous_downloaded = first_piece.getLength() - first_piece_offset;
+													}
+												}else{
+													
+													int	piece_offset = 0;
+													
+													for (int j=0;j<blocks.length;j++){
+													
+														if ( blocks[j] ){
+														
+															int	block_size = first_piece.getBlockSize( j );
+															
+															piece_offset = piece_offset + block_size;
+															
+															if ( contiguous_downloaded == 0 ){
+															
+																if ( piece_offset > first_piece_offset ){
+																	
+																	contiguous_downloaded = piece_offset - first_piece_offset;
+																}
+															}else{
+																
+																contiguous_downloaded += block_size;
+															}						
+														}else{
+															
+															break;
+														}
+													}
+												}	
+											}else{
+											
+												contiguous_downloaded = first_piece.getLength() - first_piece_offset; 
+											
+												for (int i=first_piece_index+1;i<=last_piece_index;i++){
+																									
+													DiskManagerPiece piece = pieces[i];
+													
+													if ( piece.isDone()){
+														
+														contiguous_downloaded += piece.getLength();
+														
+													}else{
+													
+														boolean[] blocks = piece.getWritten();
+																
+														if ( blocks == null ){
+															
+															if ( piece.isDone()){
+														
+																contiguous_downloaded += piece.getLength();
+																
+															}else{
+																
+																break;
+															}
+														}else{
+															
+															for (int j=0;j<blocks.length;j++){
+															
+																if ( blocks[j] ){
+																
+																	contiguous_downloaded += piece.getBlockSize( j );
+																	
+																}else{
+																	
+																	break;
+																}
+															}
+														}
+														
+														break;
+													}
+												}
+											}
+										}catch( Throwable e ){
+											
+											// Debug.out( e );
+										}
+										
+										if ( contiguous_downloaded < file_size ){
+										
+												// things might have improved, check again
+											
+											current_downloaded = job.getFile().getDownloaded();
+											
+											if ( current_downloaded < file_size ){
+		
+												Debug.out( "Premature transcode termination: init=" + initial_file_downloaded + ", curr=" + current_downloaded + ", len=" + file_size );
+		
+												error[0] = new TranscodeException( "Transcode terminated prematurely" );
+											}
+										}
+									}
+								}
+							}finally{
+							
+								xcode_sem.release();
+							}
+						}
+					};
+				
+				boolean	direct_input = job.useDirectInput();
+					
+				if ( job.isStream()){
+					
+					/*
+					provider_job[0] = 
+						provider.transcode(
+							adapter,
+							job.getFile(),
+							profile,
+							new File( "C:\\temp\\arse").toURI().toURL());
+					*/
+					
+					pipe = new TranscodePipeStreamSource2(
+								new TranscodePipeStreamSource2.streamListener()
+								{
+									public void 
+									gotStream(
+										InputStream is ) 
+									{
+										job.setStream( is );
+									}
+								});
+					
+					provider_job[0] = 
+						provider.transcode(
+							xcode_adapter,
+							provider_analysis,
+							direct_input,
+							job.getFile(),
+							profile,
+							new URL( "tcp://127.0.0.1:" + pipe.getPort()));
+	
+				}else{
+										
+					File output_file = transcode_file.getCacheFile();
+					
+					provider_job[0] = 
+						provider.transcode(
+							xcode_adapter,
+							provider_analysis,
+							direct_input,
+							job.getFile(),
+							profile,
+							output_file.toURI().toURL());
+				}
+				
+				provider_job[0].setMaxBytesPerSecond( max_bytes_per_sec );
+				
+				TranscodeQueueListener listener = 
+					new TranscodeQueueListener()
+					{
+						public void
+						jobAdded(
+							TranscodeJob		job )
+						{					
+						}
+						
+						public void
+						jobChanged(
+							TranscodeJob		changed_job )
+						{
+							if ( changed_job == job ){
+								
+								int	state = job.getState();
+								
+								if ( state == TranscodeJob.ST_PAUSED ){
+									
+									provider_job[0].pause();
+									
+								}else if ( state == TranscodeJob.ST_RUNNING ){
+										
+									provider_job[0].resume();
+									
+								}else if ( 	state == TranscodeJob.ST_CANCELLED ||
+											state == TranscodeJob.ST_STOPPED ){
+								
+									provider_job[0].cancel();
+								}
+							}
+						}
+						
+						public void
+						jobRemoved(
+							TranscodeJob		removed_job )
+						{	
+							if ( removed_job == job ){
+								
+								provider_job[0].cancel();
+							}
+						}
+					};
+					
+				try{
+					addListener( listener );
+				
+					xcode_sem.reserve();
+					
+				}finally{
+					
+					removeListener( listener );
+				}
+				
+				if ( error[0] != null ){
+					
+					throw( error[0] );
+				}
+			}else{
+				
+					// no transcode required...
+				
+				DiskManagerFileInfo source = job.getFile();
+				
+				transcode_file.setTranscodeRequired( false );
+				
+				if ( job.isStream()){
+					
+					PluginInterface av_pi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByID( "azupnpav" );
+					
+					if ( av_pi == null ){
+					
+						throw( new TranscodeException( "Media Server plugin not found" ));
+					}
+					
+					IPCInterface av_ipc = av_pi.getIPC();
+					
+					String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ source });
+					
+					
+					if ( url_str == null || url_str.length() == 0 ){
+						
+							// see if we can use the file directly
+						
+						File source_file = source.getFile();
+						
+						if ( source_file.exists()){
+							
+							job.setStream( new BufferedInputStream( new FileInputStream( source_file )));
+							
+						}else{
+							
+							throw( new TranscodeException( "No UPnPAV URL and file doesn't exist" ));
+						}
+					}else{
+						
+						URL source_url = new URL( url_str );
+					
+						job.setStream( source_url.openConnection().getInputStream());
+					}
+				}else{
+					boolean url_input_source = source instanceof DiskManagerFileInfoURL;
+					
+					if ( device.getAlwaysCacheFiles() || url_input_source ){
+						
+						PluginInterface av_pi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByID( "azupnpav" );
+						
+						if ( av_pi == null ){
+						
+							throw( new TranscodeException( "Media Server plugin not found" ));
+						}
+						
+						IPCInterface av_ipc = av_pi.getIPC();
+						
+						String url_str = (String)av_ipc.invoke( "getContentURL", new Object[]{ source });
+						
+						InputStream	is;
+						
+						long		length;
+						
+						if ( url_str == null || url_str.length() == 0 ){
+							
+								// see if we can use the file directly
+							
+							if ( url_input_source ){
+								
+								((DiskManagerFileInfoURL)source).download();
+							}
+							
+							File source_file = source.getFile();
+							
+							if ( source_file.exists()){
+								
+								is = new BufferedInputStream( new FileInputStream( source_file ));
+								
+								length = source_file.length();
+								
+							}else{
+								
+								throw( new TranscodeException( "No UPnPAV URL and file doesn't exist" ));
+							}
+						}else{
+							
+							URL source_url = new URL( url_str );
+						
+							URLConnection connection = source_url.openConnection();
+							
+							is = source_url.openConnection().getInputStream();
+							
+							String s = connection.getHeaderField( "content-length" );
+							
+							if ( s != null ){
+								
+								length = Long.parseLong( s );
+								
+							}else{
+								
+								length = -1;
+							}
+						}
+						
+						OutputStream	os = null;
+						
+						final boolean[]	cancel_copy = { false };
+						
+						TranscodeQueueListener copy_listener = 
+							new TranscodeQueueListener()
+							{
+								public void
+								jobAdded(
+									TranscodeJob		job )
+								{					
+								}
+								
+								public void
+								jobChanged(
+									TranscodeJob		changed_job )
+								{
+									if ( changed_job == job ){
+										
+										int	state = job.getState();
+										
+										if ( state == TranscodeJob.ST_PAUSED ){
+																						
+										}else if ( state == TranscodeJob.ST_RUNNING ){
+																							
+										}else if ( 	state == TranscodeJob.ST_CANCELLED ||
+													state == TranscodeJob.ST_STOPPED ){
+										
+											cancel_copy[0] = true;
+										}
+									}
+								}
+								
+								public void
+								jobRemoved(
+									TranscodeJob		removed_job )
+								{	
+									if ( removed_job == job ){
+										
+										cancel_copy[0] = true;
+									}
+								}
+							};
+							
+						try{
+							addListener( copy_listener );
+
+							os = new FileOutputStream( transcode_file.getCacheFile());
+							
+							long	total_copied = 0;
+							
+							byte[] buffer = new byte[128*1024];
+							
+							while( true ){
+								
+								if ( cancel_copy[0] ){
+									
+									throw( new TranscodeException( "Copy cancelled" ));
+								}
+								
+								int	len = is.read( buffer );
+								
+								if ( len <= 0 ){
+									
+									break;
+								}
+								
+								os.write( buffer, 0, len );
+								
+								total_copied += len;
+								
+								if ( length > 0 ){
+								
+									job.updateProgress((int)( total_copied*100/length ), -1 );
+								}
+								
+								total_copied += len;
+							}
+						}finally{
+							
+							try{
+								is.close();
+								
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+							
+							try{
+								if ( os != null ){
+								
+									os.close();
+								}
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+							
+							removeListener( copy_listener );
+						}
+					}
+				}
+			}
+			
+			job.complete();
+			
+			return( true );
+			
+		}catch( Throwable e ){
+			
+			job.failed( e );
+			
+			e.printStackTrace();
+			
+			if ( 	!job.isStream() &&
+					job.getEnableAutoRetry() && 
+					job.getAutoRetryCount() == 0 && 
+					job.canUseDirectInput() && 
+					!job.useDirectInput()){
+				
+				log( "Auto-retrying transcode with direct input" );
+				
+				job.setUseDirectInput();
+				
+				job.setAutoRetry( true );
+				
+				queue_sem.release();
+			}
+			
+			return( false );
+			
+		}finally{
+			
+			if ( pipe != null ){
+				
+				pipe.destroy();
+			}
+			
+			device.setTranscoding( false );
+
+			current_job = null;
+		}
+	}
+	
+	protected void
+	schedule()
+	{
+		synchronized( this ){
+
+			if ( queue.size() > 0 && queue_thread == null ){
+				
+				queue_thread = new
+					AEThread2( "XcodeQ", true )
+					{
+						public void 
+						run() 
+						{
+							try{
+								while( true ){
+									
+									checkJobStatus();
+									
+									boolean got = queue_sem.reserve( 30*1000 );
+																			
+									TranscodeJobImpl	job = null;
+									
+									synchronized( TranscodeQueueImpl.this ){
+										
+										if ( !got ){
+											
+											if ( queue.size() == 0 ){
+												
+												queue_thread = null;
+												
+												return;
+											}
+										}
+										
+										for ( TranscodeJobImpl j: queue ){
+											
+											int state = j.getState();
+											
+												// pick up any existing paused ones (remember, paused=running but with transcode paused
+												
+											if ( state == TranscodeJob.ST_FAILED && j.isAutoRetry()){
+												
+												j.setAutoRetry( false );
+												
+												j.reset();
+												
+												job	= j;
+												
+												break;
+												
+											}else if ( state == TranscodeJob.ST_PAUSED ){
+	
+													// remember paused here is paused after an azureus
+													// restart as 'process' blocks on pause
+												
+												job = j;
+												
+											}else if ( state == TranscodeJob.ST_QUEUED ){
+												
+												if ( job == null && j.getDownloadETA() == 0 ){
+												
+													job = j;
+												}
+											}
+										}
+									}
+									
+									checkJobStatus();
+
+									if ( job != null ){
+									
+										if ( process( job )){
+										
+											try{
+												remove( job, true );
+												
+											}catch( TranscodeActionVetoException e ){
+												
+												Debug.out( e );
+											}
+										}																			
+									}
+								}
+							}finally{
+								
+								checkJobStatus();
+							}
+						}
+					};
+					
+				queue_thread.start();
+			}
+		}
+	}
+	
+	protected void
+	updateStatus(
+		int	tick_count )
+	{
+		int queue_size;
+		
+		synchronized( this ){
+			
+			queue_size = queue.size();
+		}
+		
+		if ( queue_size > 0 ){
+			
+			TranscodeJobImpl[] jobs = getJobs();
+			
+			for ( TranscodeJobImpl job: jobs ){
+				
+				job.updateStatus();
+			}
+		}	
+	}
+	
+	protected void
+	checkJobStatus()
+	{
+		Set<DeviceImpl> devices = new HashSet<DeviceImpl>( Arrays.asList(manager.getManager().getDevices()));
+		
+		synchronized( this ){
+			
+			for ( TranscodeJobImpl j: queue ){
+
+				if ( j.getState() == TranscodeJob.ST_FAILED ){
+					
+					DeviceImpl	device = j.getDevice();
+					
+					device.setError( KEY_XCODE_ERROR, MessageText.getString( "device.error.xcodefail" ));
+					
+					devices.remove( device );
+				}
+			}
+		}
+		
+		for ( DeviceImpl device: devices ){
+			
+			device.setError( KEY_XCODE_ERROR, null );
+		}
+	}
+	
+	public TranscodeJobImpl
+	add(
+		TranscodeTarget			target,
+		TranscodeProfile		profile,
+		DiskManagerFileInfo		file,
+		boolean					add_stopped )
+	
+		throws TranscodeException
+	{
+		return( add( target, profile, file, add_stopped, false, TranscodeTarget.TRANSCODE_UNKNOWN ));
+	}
+	
+	public TranscodeJobImpl
+	add(
+		TranscodeTarget			target,
+		TranscodeProfile		profile,
+		DiskManagerFileInfo		file,
+		int						transcode_requirement,
+		boolean					add_stopped )
+	
+		throws TranscodeException
+	{
+		return( add( target, profile, file, add_stopped, false, transcode_requirement ));
+	}
+	
+	public TranscodeJobImpl
+	add(
+		TranscodeTarget			target,
+		TranscodeProfile		profile,
+		DiskManagerFileInfo		file,
+		boolean					add_stopped,
+		boolean					stream,
+		int						transcode_requirement )
+	
+		throws TranscodeException
+	{
+		TranscodeFileImpl existing_tf = ((DeviceImpl)target.getDevice()).lookupFile( profile, file );
+		
+		if ( existing_tf != null ){
+			
+			List<TranscodeJobImpl>	to_remove = new ArrayList<TranscodeJobImpl>();
+			
+			synchronized( this ){
+	
+				for ( TranscodeJobImpl job: queue ){
+					
+					if ( job.getTarget() == target && job.getTranscodeFile().equals( existing_tf )){
+						
+						to_remove.add( job );
+					}
+				}
+			}
+			
+			for ( TranscodeJobImpl job: to_remove ){
+	
+				job.removeForce();
+			}
+			
+			if ( !stream ){
+			
+				existing_tf.delete( true );
+			}
+		}
+		
+		TranscodeJobImpl job = new TranscodeJobImpl( this, target, profile, file, add_stopped, transcode_requirement, stream );
+		
+		try{
+			synchronized( this ){
+				
+				queue.add( job );
+				
+				queue_sem.release();
+				
+				configDirty();
+			}
+			
+			for ( TranscodeQueueListener listener: listeners ){
+				
+				try{
+					listener.jobAdded( job );
+					
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace( e );
+				}
+			}
+		}finally{
+		
+			schedule();
+		}
+		
+		return( job );
+	}
+	
+	protected void
+	remove(
+		TranscodeJobImpl		job,
+		boolean					force )
+	
+		throws TranscodeActionVetoException
+	{
+		synchronized( this ){
+			
+			if ( !queue.contains( job )){
+				
+				return;
+			}
+		}
+		
+		if ( !force ){
+			
+			for ( TranscodeQueueActionListener l: action_listeners ){
+				
+				try{
+					l.jobWillBeActioned( job, TranscodeQueueActionListener.ACT_REMOVE );
+					
+				}catch( TranscodeActionVetoException e ){
+					
+					throw( e );
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e);
+				}
+			}
+		}
+		
+		synchronized( this ){
+			
+			if ( !queue.remove( job )){
+				
+				return;
+			}
+		}
+		
+		configDirty();
+
+		job.destroy();
+		
+		for ( TranscodeQueueListener listener: listeners ){
+			
+			try{
+				listener.jobRemoved( job );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace( e );
+			}
+		}
+		
+		checkJobStatus();
+		
+		schedule();
+	}
+	
+	protected void
+	jobChanged(
+		TranscodeJob			job,
+		boolean					schedule,
+		boolean					persistable )
+	{
+
+		for ( TranscodeQueueListener listener: listeners ){
+			
+			try{
+				listener.jobChanged( job );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace( e );
+			}
+		}
+		
+		if ( persistable ){
+		
+			configDirty();
+		}
+		
+		if ( schedule ){
+			
+			queue_sem.release();
+			
+			schedule();
+		}
+	}
+	
+	protected int
+	getIndex(
+		TranscodeJobImpl		job )
+	{
+		synchronized( this ){
+		
+			return( queue.indexOf(job)+1);
+		}
+	}
+	
+	public TranscodeJobImpl[]
+	getJobs()
+	{
+		synchronized( this ){
+
+			return( queue.toArray( new TranscodeJobImpl[queue.size()]));
+		}
+	}
+	
+	public int
+	getJobCount()
+	{
+		synchronized( this ){
+
+			return( queue.size());
+		}	
+	}
+	
+	public TranscodeJob
+	getCurrentJob()
+	{
+		return( current_job );
+	}
+	
+	public boolean
+	isTranscoding()
+	{
+		return( current_job != null );
+	}
+	
+	protected TranscodeJobImpl
+	getJob(
+		TranscodeFile		for_file )
+	{
+		synchronized( this ){
+
+			for ( TranscodeJobImpl job: queue ){
+				
+				if ( job.getTranscodeFile().equals( for_file )){
+					
+					return( job );
+				}
+			}
+		}
+		
+		return( null );
+	}
+	
+	public void 
+	moveUp(
+		TranscodeJobImpl	job )
+	{
+		TranscodeJob[] updated;
+			
+		synchronized( this ){
+		
+			int index = queue.indexOf( job );
+			
+			if ( index <= 0 || queue.size() == 1 ){
+				
+				return;
+			}
+			
+			queue.remove( job );
+			
+			queue.add( index-1, job );
+			
+			updated = getJobs();
+		}
+		
+		for ( TranscodeJob j: updated ){
+			
+			jobChanged( j, false, true );
+		}
+	}
+	
+	public void 
+	moveDown(
+		TranscodeJobImpl	job )
+	{
+		TranscodeJob[] updated;
+
+		synchronized( this ){
+		
+			int index = queue.indexOf( job );
+			
+			if ( index < 0 || index == queue.size() - 1 ){
+				
+				return;
+			}
+			
+			queue.remove( job );
+			
+			queue.add( index+1, job );
+			
+			updated = getJobs();
+		}
+		
+		for ( TranscodeJob j: updated ){
+			
+			jobChanged( j, false, true );
+		}
+	}
+	
+	public void
+	pause()
+	{
+		if ( !paused ){
+			
+			if ( paused ){
+				
+				COConfigurationManager.setParameter( "xcode.paused", true );
+			}
+		}
+	}
+	
+	public boolean
+	isPaused()
+	{
+		return( paused );
+	}
+	
+	public void
+	resume()
+	{
+		if ( paused ){
+			
+			COConfigurationManager.setParameter( "xcode.queue.paused", false );
+		}
+	}
+	
+	public long
+	getMaxBytesPerSecond()
+	{
+		return( max_bytes_per_sec );
+	}
+	
+	public void
+	setMaxBytesPerSecond(
+		long		max )
+	{
+		COConfigurationManager.setParameter( "xcode.queue.maxbps", max );
+	}
+	
+	protected TranscodeTarget
+	lookupTarget(
+		String		target_id )
+	
+		throws TranscodeException
+	{
+		return( manager.lookupTarget( target_id ));
+	}
+	
+	protected TranscodeProfile
+	lookupProfile(
+		String		profile_id )
+	
+		throws TranscodeException
+	{
+		TranscodeProfile profile = manager.getProfileFromUID( profile_id );
+		
+		if ( profile == null ){
+			
+			throw( new TranscodeException( "Transcode profile with id '" + profile_id + "' not found" ));
+		}
+		
+		return( profile );
+	}
+	
+	protected DiskManagerFileInfo
+	lookupFile(
+		byte[]		hash,
+		int			index )
+	
+		throws TranscodeException
+	{
+		return( manager.lookupFile( hash, index ));
+	}
+	
+	protected void
+	analyse(
+		final TranscodeJobImpl			job,
+		final TranscodeAnalysisListener	listener )
+	
+		throws TranscodeException
+	{
+		anaylsis_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void 
+				runSupport() 
+				{
+					try{
+						TranscodeProviderAnalysis analysis = analyse( job );
+		
+						listener.analysisComplete( job, analysis );
+						
+					}catch( TranscodeException e ){
+						
+						listener.analysisFailed( job, e );
+						
+					}catch( Throwable e ){
+						
+						listener.analysisFailed( job, new TranscodeException( "Analysis failed", e ));
+					}
+				}
+			});
+	}
+	
+	protected TranscodeProviderAnalysis
+	analyse(
+		final TranscodeJobImpl			job )
+	
+		throws TranscodeException
+	{
+		TranscodeProvider provider = job.getProfile().getProvider();
+	
+		if ( provider == null ){
+			
+			throw( new TranscodeException( "Transcode provider not available" ));
+		}
+		
+		final TranscodeException[] error = { null };
+		
+		TranscodeProfile profile = job.getProfile();
+			
+		final AESemaphore analysis_sem = new AESemaphore( "analysis:proc" );		
+
+		final boolean	was_stopped = job.getState() == TranscodeJob.ST_STOPPED;
+		
+		TranscodeProviderAdapter analysis_adapter = 
+			new TranscodeProviderAdapter()
+			{
+				public void
+				updateProgress(
+					int		percent,
+					int		eta_secs,
+					int		width,
+					int		height )
+				{
+				}
+				
+				public void
+				streamStats(
+					long					connect_rate,
+					long					write_speed )
+				{
+				}
+				
+				public void
+				failed(
+					TranscodeException		e )
+				{
+					error[0] = e;
+					
+					analysis_sem.release();
+				}
+				
+				public void 
+				complete() 
+				{
+					analysis_sem.release();
+				}
+			};
+			
+		final TranscodeProviderAnalysis provider_analysis =	provider.analyse( analysis_adapter, job.getFile(), profile );
+		
+		TranscodeQueueListener analysis_q_listener = 
+			new TranscodeQueueListener()
+			{
+				public void
+				jobAdded(
+					TranscodeJob		job )
+				{					
+				}
+				
+				public void
+				jobChanged(
+					TranscodeJob		changed_job )
+				{
+					if ( changed_job == job ){
+						
+						int	state = job.getState();
+						
+						if ( 	state == TranscodeJob.ST_CANCELLED ){
+							
+							provider_analysis.cancel();
+							
+						}else if ( 	state == TranscodeJob.ST_STOPPED ){
+						
+								// only treat this as a failure if the job was initially
+								// running and has been explicitly stopped
+							
+							if ( !was_stopped ){
+							
+								provider_analysis.cancel();
+							}
+						}
+					}
+				}
+				
+				public void
+				jobRemoved(
+					TranscodeJob		removed_job )
+				{	
+					if ( removed_job == job ){
+						
+						provider_analysis.cancel();
+					}
+				}
+			};
+			
+		try{
+			addListener( analysis_q_listener );
+		
+			analysis_sem.reserve();
+			
+		}finally{
+			
+			removeListener( analysis_q_listener );
+		}
+		
+		if ( error[0] != null ){
+			
+			throw( error[0] );
+		}
+				
+		TranscodeFileImpl		transcode_file = job.getTranscodeFile();
+
+		transcode_file.update( provider_analysis );
+		
+		return( provider_analysis );
+	}
+	
+	protected void
+	configDirty()
+	{
+		synchronized( this ){
+			
+			if ( config_dirty ){
+				
+				return;
+			}
+			
+			config_dirty = true;
+		
+			new DelayedEvent( 
+				"TranscodeQueue:save", 5000,
+				new AERunnable()
+				{
+					public void 
+					runSupport() 
+					{
+						synchronized( TranscodeQueueImpl.this ){
+							
+							if ( !config_dirty ){
+
+								return;
+							}
+							
+							saveConfig();
+						}	
+					}
+				});
+		}
+	}
+	
+	protected void
+	loadConfig()
+	{
+		if ( !FileUtil.resilientConfigFileExists( CONFIG_FILE )){
+			
+			return;
+		}
+		
+		log( "Loading configuration" );
+			
+		try{
+			synchronized( this ){
+				
+				Map map = FileUtil.readResilientConfigFile( CONFIG_FILE );
+				
+				List<Map<String,Object>>	l_jobs = (List<Map<String,Object>>)map.get( "jobs" );
+				
+				if ( l_jobs != null ){
+					
+					for ( Map<String,Object> m: l_jobs ){
+						
+						try{
+							TranscodeJobImpl job = new TranscodeJobImpl( this, m );
+						
+							queue.add(job );
+							
+							queue_sem.release();
+							
+						}catch( Throwable e ){
+							
+							log( "Failed to restore job: " + m, e );
+						}
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			log( "Configuration load failed", e );
+		}
+	}
+	
+	protected void
+	saveConfig()
+	{
+		synchronized( this ){
+
+			config_dirty = false;
+			
+			if ( queue.size() == 0 ){
+
+				FileUtil.deleteResilientConfigFile( CONFIG_FILE );
+
+			}else{
+				
+				Map<String,Object>	map = new HashMap<String,Object>();
+				
+				List<Map<String,Object>>	l_jobs = new ArrayList<Map<String,Object>>();
+				
+				map.put( "jobs", l_jobs );
+				
+				for ( TranscodeJobImpl job: queue ){
+				
+					if ( job.isStream()){
+						
+						continue;
+					}
+					
+					try{
+					
+						l_jobs.add( job.toMap());
+						
+					}catch( Throwable e ){
+						
+						log( "Failed to save job", e );
+					}
+				}
+				
+				FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
+			}
+		}
+	}
+	
+	protected void
+	close()
+	{
+		if ( config_dirty ){
+		
+			saveConfig();
+		}
+	}
+	
+	public void
+	addListener(
+		TranscodeQueueListener		listener )
+	{
+		if (!listeners.contains(listener)) {
+			listeners.add( listener );
+		}
+	}
+	
+	public void
+	removeListener(
+		TranscodeQueueListener		listener )
+	{
+		listeners.remove( listener );	
+	}
+	
+	public void
+	addActionListener(
+		TranscodeQueueActionListener		listener )
+	{
+		action_listeners.add( listener );
+	}
+	
+	public void
+	removeActionListener(
+		TranscodeQueueActionListener		listener )
+	{
+		action_listeners.remove( listener );	
+	}
+	
+	protected void
+	log( 
+		String	str )
+	{
+		manager.log( "Queue: " + str );
+	}
+	
+	protected void
+	log( 
+		String		str,
+		Throwable	e )
+	{
+		manager.log( "Queue: " + str, e );
+	}
+	
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		writer.println( "Transcode Queue: paused=" + paused + ",max_bps=" + max_bytes_per_sec );
+		
+		try{
+			writer.indent();
+	
+			TranscodeJobImpl[] jobs = getJobs();
+			
+			for ( TranscodeJobImpl job: jobs ){
+				
+				job.generate( writer );
+			}
+		}finally{
+			
+			writer.exdent();
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoDelegate.java b/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoDelegate.java
index da43f8d..418ab1d 100644
--- a/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoDelegate.java
+++ b/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoDelegate.java
@@ -1,785 +1,784 @@
-/*
- * Created on Feb 11, 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.download;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-import org.gudy.azureus2.core3.util.AESemaphore;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
-import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.plugins.disk.DiskManagerListener;
-import org.gudy.azureus2.plugins.disk.DiskManagerRandomReadRequest;
-import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadException;
-import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
-import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
-
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-import com.aelitis.azureus.core.util.QTFastStartRAF;
-
-public class 
-DiskManagerFileInfoDelegate
-	implements DiskManagerFileInfo
-{
-	private DiskManagerFileInfo		delegate;
-	private byte[]					hash;
-	
-	public
-	DiskManagerFileInfoDelegate(
-		DiskManagerFileInfo		_delegate )
-	
-		throws DownloadException
-	{
-		delegate		= _delegate;
-		
-		if ( delegate.getDownload() == null ){
-			
-			throw( new DownloadException( "Not supported" ));
-		}
-		
-		byte[]	delegate_hash = delegate.getDownloadHash();
-			
-		hash = delegate_hash.clone();
-			
-		hash[0] ^= 0x01;
-	}
-	
-	public void 
-	setPriority(
-		boolean b )
-	{
-		delegate.setPriority( b );
-	}
-	
-	public int 
-	getNumericPriorty() 
-	{
-		return( delegate.getNumericPriority());
-	}
-	
-	public int 
-	getNumericPriority() 
-	{
-		return( delegate.getNumericPriority());
-	}
-	
-	public void 
-	setNumericPriority(
-		int priority) 
-	{
-		delegate.setNumericPriority(priority);
-	}
-	
-	public void 
-	setSkipped(
-		boolean b )
-	{
-		delegate.setSkipped( b );
-	}
-	
-	public void
-	setDeleted(boolean b)
-	{
-		delegate.setDeleted(b);
-	}
-	
-	public void
-	setLink(
-		File	link_destination )
-	{	
-		delegate.setLink( link_destination );
-	}
-	
-	public File
-	getLink()
-	{
-		return( delegate.getLink());
-	}
-		 	
-	public int 
-	getAccessMode()
-	{
-		return( delegate.getAccessMode());
-	}
-	
-	public long 
-	getDownloaded()
-	{
-		return( delegate.getDownloaded());
-	}
-	
-	public long
-	getLength()
-	{
-		return( delegate.getLength());
-	}
-	
-	public File 
-	getFile()
-	{
-		return( delegate.getFile());
-	}
-	
-	public File 
-	getFile(
-		boolean follow_link ) 
-	{
-		return( delegate.getFile(follow_link));
-	}
-	
-	public int
-	getIndex()
-	{
-		return( delegate.getIndex());
-	}
-	
-	public int 
-	getFirstPieceNumber()
-	{
-		return( delegate.getFirstPieceNumber());
-	}
-	
-	public long
-	getPieceSize()
-	{
-		return( delegate.getPieceSize());
-	}
-	
-	public int 
-	getNumPieces()
-	{
-		return( delegate.getNumPieces());
-	}
-		
-	public boolean 
-	isPriority()
-	{
-		return( delegate.isPriority());
-	}
-	
-	public boolean 
-	isSkipped()
-	{
-		return( delegate.isSkipped());
-	}
-	
-	public boolean
-	isDeleted()
-	{
-		return( delegate.isDeleted());
-	}
-	
-	public byte[] 
-	getDownloadHash()
-    {
-		return( hash );
-    }
-	
-	public Download 
-	getDownload()
-	
-      throws DownloadException
-    {
-		throw( new DownloadException( "Not supported" ));
-    }
-	
-	public DiskManagerChannel
-	createChannel()
-	
-		throws DownloadException
-	{
-		return( new channel());
-	}
-	
-	public DiskManagerRandomReadRequest
-	createRandomReadRequest(
-		long						file_offset,
-		long						length,
-		boolean						reverse_order,
-		DiskManagerListener			listener )
-	
-		throws DownloadException
-	{
-		return( delegate.createRandomReadRequest( file_offset, length, reverse_order, listener));
-	}
-	
-	private class
-	channel
-		implements DiskManagerChannel
-	{
-		private DiskManagerChannel	delegate_channel;
-		
-		private volatile boolean	channel_destroyed;
-		
-		private
-		channel()
-		
-			throws DownloadException
-		{
-			delegate_channel = delegate.createChannel();
-		}
-		
-		public DiskManagerRequest
-		createRequest()
-		{
-			return( new request());
-		}
-		
-		public DiskManagerFileInfo
-		getFile()
-		{
-			return( DiskManagerFileInfoDelegate.this );
-		}
-		
-		public long 
-		getPosition() 
-		{
-			return( delegate_channel.getPosition());
-		}
-		
-		public boolean 
-		isDestroyed() 
-		{
-			return( delegate_channel.isDestroyed());
-		}
-		
-		public void
-		destroy()
-		{
-			delegate_channel.destroy();
-		}
-		
-		protected class
-		request
-			implements DiskManagerRequest
-		{
-			private DiskManagerRequest	delegate_request;
-			private volatile boolean	using_delegate;
-			
-			private long		offset;
-			private long		length;
-			
-			private volatile long	position;
-			
-			private String		user_agent;
-
-			private int			max_read_chunk = 128*1024;;
-
-			private volatile boolean	cancelled;
-			
-			
-			private CopyOnWriteList<DiskManagerListener>		listeners = new CopyOnWriteList<DiskManagerListener>();
-			
-			private
-			request()
-			{
-				delegate_request = delegate_channel.createRequest();
-			}
-			
-			public void
-			setType(
-				int			type )
-			{
-				if ( type != DiskManagerRequest.REQUEST_READ ){
-					
-					throw( new RuntimeException( "Not supported" ));
-				}
-				
-				delegate_request.setType( type );
-			}
-			
-			public void
-			setOffset(
-				long		_offset )
-			{
-				offset		= _offset;
-				
-				delegate_request.setOffset( offset ); 
-			}
-			
-			public void
-			setLength(
-				long		_length )
-			{
-				if ( _length < 0 ){
-					
-					throw( new RuntimeException( "Illegal argument" ));
-				}
-				
-				length		= _length;
-				
-				delegate_request.setLength( length );
-			}
-				
-			public void
-			setMaximumReadChunkSize(
-				int 	size )
-			{
-				max_read_chunk = size;
-				
-				delegate_request.setMaximumReadChunkSize( size );
-			}
-			
-			public void
-			setUserAgent(
-				String		agent )
-			{	
-				user_agent	= agent;
-				
-				delegate_request.setUserAgent( agent );
-			}
-
-			public long
-			getAvailableBytes()
-			{
-				if ( using_delegate ){
-					
-					return( delegate_request.getAvailableBytes());
-				}
-				
-				return( getRemaining());
-			}
-						
-			public long
-			getRemaining()
-			{
-				if ( using_delegate ){
-					
-					return( delegate_request.getRemaining());
-				}
-				
-				return( offset + length - position );
-			}
-			
-			public void
-			run()
-			{
-				boolean	for_stream = user_agent != null;
-				
-				if ( for_stream ){
-					
-					File file = delegate.getFile();
-					
-					String name = file.getName();
-					
-					int	dot_pos = name.lastIndexOf('.');
-					
-					String ext = dot_pos<0?"":name.substring(dot_pos+1);
-
-					for_stream = QTFastStartRAF.isSupportedExtension( ext );
-				}
-				
-				if ( for_stream ){
-					
-					QTFastStartRAF	raf = null;
-					
-					try{
-						raf = new QTFastStartRAF( getAccessor( max_read_chunk, user_agent ), true );
-						
-						raf.seek( offset );
-				
-						byte[] buffer = new byte[max_read_chunk];
-						
-						long	rem		= length;
-						long	pos 	= offset;
-						
-						while( rem > 0 ){
-							
-							if ( cancelled ){
-								
-								throw( new Exception( "Cancelled" ));
-								
-							}else if ( channel_destroyed ){
-								
-								throw( new Exception( "Destroyed" ));
-							}
-							
-							int	chunk = (int)Math.min( rem, max_read_chunk );
-							
-							int	len = raf.read( buffer, 0, chunk );
-													
-							sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
-							
-							rem -= len;
-							pos	+= len;
-							
-							position += len;
-						}
-					}catch( Throwable e ){
-						
-						sendEvent( new event( e ));
-						
-					}finally{
-						
-						if ( raf != null ){
-							
-							try{
-								raf.close();
-								
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-						}
-					}
-				}else{
-					
-					using_delegate	= true;
-					
-					delegate_request.addListener(
-						new DiskManagerListener()
-						{
-							public void
-							eventOccurred(
-								DiskManagerEvent	event )
-							{
-								sendEvent( event );
-							}
-						});
-						
-					delegate_request.run();
-				}
-			}
-			
-			public void
-			cancel()
-			{
-				cancelled = true;
-				
-				delegate_request.cancel();
-			}
-						
-			protected void
-			sendEvent(
-				DiskManagerEvent		ev )
-			{					
-				for ( DiskManagerListener l: listeners ){
-					
-					l.eventOccurred( ev );
-				}
-			}
-			
-			public void
-			addListener(
-				DiskManagerListener	listener )
-			{
-				listeners.add( listener );
-			}
-			
-			public void
-			removeListener(
-				DiskManagerListener	listener )
-			{
-				listeners.remove( listener );
-			}
-		
-			protected class
-			event
-				implements DiskManagerEvent
-			{
-				private int					event_type;
-				private Throwable			error;
-				private PooledByteBuffer	buffer;
-				private long				event_offset;
-				private int					event_length;
-				
-				protected
-				event(
-					Throwable		_error )
-				{
-					event_type	= DiskManagerEvent.EVENT_TYPE_FAILED;
-					error		= _error;
-				}
-								
-				protected
-				event(
-					PooledByteBuffer	_buffer,
-					long				_offset,
-					int					_length )
-				{
-					event_type		= DiskManagerEvent.EVENT_TYPE_SUCCESS;
-					buffer			= _buffer;
-					event_offset	= _offset;
-					event_length	= _length;
-				}
-				
-				public int
-				getType()
-				{
-					return( event_type );
-				}
-				
-				public long
-				getOffset()
-				{
-					return( event_offset );
-				}
-				
-				public int
-				getLength()
-				{
-					return( event_length );
-				}
-				
-				public PooledByteBuffer
-				getBuffer()
-				{
-					return( buffer );
-				}
-				
-				public Throwable
-				getFailure()
-				{
-					return( error );
-				}
-			}
-		}
-		
-		private QTFastStartRAF.FileAccessor
-		getAccessor(
-			final int			max_req_size,
-			final String		user_agent )
-		{
-			return( 
-				new QTFastStartRAF.FileAccessor()
-				{
-					private long				seek_position;
-					private DiskManagerRequest 	current_request;
-					private volatile boolean	closed;
-					
-					public String
-					getName()
-					{
-						try{
-							return( delegate.getDownload().getName() + "/" + delegate.getFile().getName());
-							
-						}catch( Throwable e ){
-							
-							Debug.out( e );
-							
-							return( delegate.getFile().getAbsolutePath());
-						}
-					}
-					
-					public long
-					getFilePointer()
-					
-						throws IOException
-					{
-						return( seek_position );
-					}
-					
-					public void
-					seek(
-						long		pos )
-					
-						throws IOException
-					{
-						seek_position = pos;
-					}
-
-					public void
-					skipBytes(
-						int		num )
-					
-						throws IOException
-					{
-						seek_position += num;
-					}
-					
-					public long
-					length()
-					
-						throws IOException
-					{
-						return( getLength());
-					}
-					
-					public int
-					read(
-						final byte[]	buffer,
-						final int		pos,
-						final int		len )
-					
-						throws IOException
-					{
-						synchronized( this ){
-							
-							if ( closed ){
-								
-								throw( new IOException( "closed" ));
-							}
-							
-							current_request = delegate_channel.createRequest();
-						}
-						
-						current_request.setType( DiskManagerRequest.REQUEST_READ );
-						current_request.setOffset( seek_position );
-						current_request.setLength( len );
-						
-						current_request.setMaximumReadChunkSize( max_req_size );
-						
-						if ( user_agent != null ){
-						
-							current_request.setUserAgent( user_agent );
-						}
-						
-						final AESemaphore	sem = new AESemaphore( "waiter" );
-						final Throwable[]	error = {null};
-						
-						current_request.addListener(
-							new DiskManagerListener()
-							{
-								private int write_pos 	= pos;
-								private int	rem			= len;
-								
-								public void
-								eventOccurred(
-									DiskManagerEvent	event )
-								{
-									int	type = event.getType();
-									
-									if ( type == DiskManagerEvent.EVENT_TYPE_SUCCESS ){
-										
-										PooledByteBuffer p_buffer = event.getBuffer();
-										
-										try{
-											ByteBuffer	bb = p_buffer.toByteBuffer();
-																					
-											bb.position( 0 );
-											
-											int	read = bb.remaining();
-
-											bb.get( buffer, write_pos, read );
-											
-											write_pos 	+= read;
-											rem			-= read;
-											
-											if ( rem == 0 ){
-												
-												sem.release();
-											}
-										}finally{
-											
-											p_buffer.returnToPool();
-										}
-									}else if ( type == DiskManagerEvent.EVENT_TYPE_FAILED ){
-									
-										error[0] = event.getFailure();
-										
-										sem.release();
-									}
-								}
-							});
-						
-						current_request.run();
-						
-						while( true ){
-							
-							if ( sem.reserve( 1000 )){
-								
-								if ( error[0] != null ){
-									
-									throw( new IOException( Debug.getNestedExceptionMessage( error[0] )));
-								}
-								
-								seek_position += len;
-								
-								return( len );
-								
-							}else{
-								
-								if ( closed ){
-									
-									throw( new IOException( "Closed" ));
-								}
-							}
-						}
-					}
-					
-					public int
-					readInt()
-					
-						throws IOException
-					{
-						byte[]	readBuffer = new byte[4];
-						
-						readFully( readBuffer );
-						
-						return ((readBuffer[0] << 24) + 
-								((readBuffer[1]&0xff) << 16) + 
-								((readBuffer[2]&0xff) << 8) + 
-								((readBuffer[3]&0xff) << 0));
-					}
-					
-					public long
-					readLong()
-					
-						throws IOException
-					{
-						byte[]	readBuffer = new byte[8];
-						
-						readFully( readBuffer );
-					  
-						return (	((long)readBuffer[0] << 56) +
-					                ((long)(readBuffer[1]&0xff) << 48) +
-					                ((long)(readBuffer[2]&0xff) << 40) +
-					                ((long)(readBuffer[3]&0xff) << 32) +
-					                ((long)(readBuffer[4]&0xff) << 24) +
-					                ((readBuffer[5]&0xff) << 16) +
-					                ((readBuffer[6]&0xff) <<  8) +
-					                ((readBuffer[7]&0xff) <<  0));					
-					}
-					
-					public void
-					readFully(
-						byte[]	buffer )
-					
-						throws IOException
-					{
-						read( buffer, 0, buffer.length );
-					}
-							
-					public void
-					close()
-					
-						throws IOException
-					{
-						synchronized( this ){
-						
-							closed	= true;
-							
-							if ( current_request != null ){
-								
-								current_request.cancel();
-							}
-						}
-					}
-				});
-		}
-	}
-}
+/*
+ * Created on Feb 11, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.download;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.gudy.azureus2.core3.util.AESemaphore;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
+import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.disk.DiskManagerListener;
+import org.gudy.azureus2.plugins.disk.DiskManagerRandomReadRequest;
+import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadException;
+import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
+import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
+
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.core.util.QTFastStartRAF;
+
+public class 
+DiskManagerFileInfoDelegate
+	implements DiskManagerFileInfo
+{
+	private DiskManagerFileInfo		delegate;
+	private byte[]					hash;
+	
+	public
+	DiskManagerFileInfoDelegate(
+		DiskManagerFileInfo		_delegate )
+	
+		throws DownloadException
+	{
+		delegate		= _delegate;
+		
+		if ( delegate.getDownload() == null ){
+			
+			throw( new DownloadException( "Not supported" ));
+		}
+		
+		byte[]	delegate_hash = delegate.getDownloadHash();
+			
+		hash = delegate_hash.clone();
+			
+		hash[0] ^= 0x01;
+	}
+	
+	public void 
+	setPriority(
+		boolean b )
+	{
+		delegate.setPriority( b );
+	}
+	
+	public int 
+	getNumericPriorty() 
+	{
+		return( delegate.getNumericPriority());
+	}
+	
+	public int 
+	getNumericPriority() 
+	{
+		return( delegate.getNumericPriority());
+	}
+	
+	public void 
+	setNumericPriority(
+		int priority) 
+	{
+		delegate.setNumericPriority(priority);
+	}
+	
+	public void 
+	setSkipped(
+		boolean b )
+	{
+		delegate.setSkipped( b );
+	}
+	
+	public void
+	setDeleted(boolean b)
+	{
+		delegate.setDeleted(b);
+	}
+	
+	public void
+	setLink(
+		File	link_destination )
+	{	
+		delegate.setLink( link_destination );
+	}
+	
+	public File
+	getLink()
+	{
+		return( delegate.getLink());
+	}
+		 	
+	public int 
+	getAccessMode()
+	{
+		return( delegate.getAccessMode());
+	}
+	
+	public long 
+	getDownloaded()
+	{
+		return( delegate.getDownloaded());
+	}
+	
+	public long
+	getLength()
+	{
+		return( delegate.getLength());
+	}
+	
+	public File 
+	getFile()
+	{
+		return( delegate.getFile());
+	}
+	
+	public File 
+	getFile(
+		boolean follow_link ) 
+	{
+		return( delegate.getFile(follow_link));
+	}
+	
+	public int
+	getIndex()
+	{
+		return( delegate.getIndex());
+	}
+	
+	public int 
+	getFirstPieceNumber()
+	{
+		return( delegate.getFirstPieceNumber());
+	}
+	
+	public long
+	getPieceSize()
+	{
+		return( delegate.getPieceSize());
+	}
+	
+	public int 
+	getNumPieces()
+	{
+		return( delegate.getNumPieces());
+	}
+		
+	public boolean 
+	isPriority()
+	{
+		return( delegate.isPriority());
+	}
+	
+	public boolean 
+	isSkipped()
+	{
+		return( delegate.isSkipped());
+	}
+	
+	public boolean
+	isDeleted()
+	{
+		return( delegate.isDeleted());
+	}
+	
+	public byte[] 
+	getDownloadHash()
+    {
+		return( hash );
+    }
+	
+	public Download 
+	getDownload()
+	
+      throws DownloadException
+    {
+		throw( new DownloadException( "Not supported" ));
+    }
+	
+	public DiskManagerChannel
+	createChannel()
+	
+		throws DownloadException
+	{
+		return( new channel());
+	}
+	
+	public DiskManagerRandomReadRequest
+	createRandomReadRequest(
+		long						file_offset,
+		long						length,
+		boolean						reverse_order,
+		DiskManagerListener			listener )
+	
+		throws DownloadException
+	{
+		return( delegate.createRandomReadRequest( file_offset, length, reverse_order, listener));
+	}
+	
+	private class
+	channel
+		implements DiskManagerChannel
+	{
+		private DiskManagerChannel	delegate_channel;
+		
+		private volatile boolean	channel_destroyed;
+		
+		private
+		channel()
+		
+			throws DownloadException
+		{
+			delegate_channel = delegate.createChannel();
+		}
+		
+		public DiskManagerRequest
+		createRequest()
+		{
+			return( new request());
+		}
+		
+		public DiskManagerFileInfo
+		getFile()
+		{
+			return( DiskManagerFileInfoDelegate.this );
+		}
+		
+		public long 
+		getPosition() 
+		{
+			return( delegate_channel.getPosition());
+		}
+		
+		public boolean 
+		isDestroyed() 
+		{
+			return( delegate_channel.isDestroyed());
+		}
+		
+		public void
+		destroy()
+		{
+			delegate_channel.destroy();
+		}
+		
+		protected class
+		request
+			implements DiskManagerRequest
+		{
+			private DiskManagerRequest	delegate_request;
+			private volatile boolean	using_delegate;
+			
+			private long		offset;
+			private long		length;
+			
+			private volatile long	position;
+			
+			private String		user_agent;
+
+			private int			max_read_chunk = 128*1024;;
+
+			private volatile boolean	cancelled;
+			
+			
+			private CopyOnWriteList<DiskManagerListener>		listeners = new CopyOnWriteList<DiskManagerListener>();
+			
+			private
+			request()
+			{
+				delegate_request = delegate_channel.createRequest();
+			}
+			
+			public void
+			setType(
+				int			type )
+			{
+				if ( type != DiskManagerRequest.REQUEST_READ ){
+					
+					throw( new RuntimeException( "Not supported" ));
+				}
+				
+				delegate_request.setType( type );
+			}
+			
+			public void
+			setOffset(
+				long		_offset )
+			{
+				offset		= _offset;
+				
+				delegate_request.setOffset( offset ); 
+			}
+			
+			public void
+			setLength(
+				long		_length )
+			{
+				if ( _length < 0 ){
+					
+					throw( new RuntimeException( "Illegal argument" ));
+				}
+				
+				length		= _length;
+				
+				delegate_request.setLength( length );
+			}
+				
+			public void
+			setMaximumReadChunkSize(
+				int 	size )
+			{
+				max_read_chunk = size;
+				
+				delegate_request.setMaximumReadChunkSize( size );
+			}
+			
+			public void
+			setUserAgent(
+				String		agent )
+			{	
+				user_agent	= agent;
+				
+				delegate_request.setUserAgent( agent );
+			}
+
+			public long
+			getAvailableBytes()
+			{
+				if ( using_delegate ){
+					
+					return( delegate_request.getAvailableBytes());
+				}
+				
+				return( getRemaining());
+			}
+						
+			public long
+			getRemaining()
+			{
+				if ( using_delegate ){
+					
+					return( delegate_request.getRemaining());
+				}
+				
+				return( offset + length - position );
+			}
+			
+			public void
+			run()
+			{
+				boolean	for_stream = user_agent != null;
+				
+				if ( for_stream ){
+					
+					File file = delegate.getFile();
+					
+					String name = file.getName();
+					
+					int	dot_pos = name.lastIndexOf('.');
+					
+					String ext = dot_pos<0?"":name.substring(dot_pos+1);
+
+					for_stream = QTFastStartRAF.isSupportedExtension( ext );
+				}
+				
+				if ( for_stream ){
+					
+					QTFastStartRAF	raf = null;
+					
+					try{
+						raf = new QTFastStartRAF( getAccessor( max_read_chunk, user_agent ), true );
+						
+						raf.seek( offset );
+				
+						byte[] buffer = new byte[max_read_chunk];
+						
+						long	rem		= length;
+						long	pos 	= offset;
+						
+						while( rem > 0 ){
+							
+							if ( cancelled ){
+								
+								throw( new Exception( "Cancelled" ));
+								
+							}else if ( channel_destroyed ){
+								
+								throw( new Exception( "Destroyed" ));
+							}
+							
+							int	chunk = (int)Math.min( rem, max_read_chunk );
+							
+							int	len = raf.read( buffer, 0, chunk );
+													
+							sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
+							
+							rem -= len;
+							pos	+= len;
+							
+							position += len;
+						}
+					}catch( Throwable e ){
+						
+						sendEvent( new event( e ));
+						
+					}finally{
+						
+						if ( raf != null ){
+							
+							try{
+								raf.close();
+								
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}
+					}
+				}else{
+					
+					using_delegate	= true;
+					
+					delegate_request.addListener(
+						new DiskManagerListener()
+						{
+							public void
+							eventOccurred(
+								DiskManagerEvent	event )
+							{
+								sendEvent( event );
+							}
+						});
+						
+					delegate_request.run();
+				}
+			}
+			
+			public void
+			cancel()
+			{
+				cancelled = true;
+				
+				delegate_request.cancel();
+			}
+						
+			protected void
+			sendEvent(
+				DiskManagerEvent		ev )
+			{					
+				for ( DiskManagerListener l: listeners ){
+					
+					l.eventOccurred( ev );
+				}
+			}
+			
+			public void
+			addListener(
+				DiskManagerListener	listener )
+			{
+				listeners.add( listener );
+			}
+			
+			public void
+			removeListener(
+				DiskManagerListener	listener )
+			{
+				listeners.remove( listener );
+			}
+		
+			protected class
+			event
+				implements DiskManagerEvent
+			{
+				private int					event_type;
+				private Throwable			error;
+				private PooledByteBuffer	buffer;
+				private long				event_offset;
+				private int					event_length;
+				
+				protected
+				event(
+					Throwable		_error )
+				{
+					event_type	= DiskManagerEvent.EVENT_TYPE_FAILED;
+					error		= _error;
+				}
+								
+				protected
+				event(
+					PooledByteBuffer	_buffer,
+					long				_offset,
+					int					_length )
+				{
+					event_type		= DiskManagerEvent.EVENT_TYPE_SUCCESS;
+					buffer			= _buffer;
+					event_offset	= _offset;
+					event_length	= _length;
+				}
+				
+				public int
+				getType()
+				{
+					return( event_type );
+				}
+				
+				public long
+				getOffset()
+				{
+					return( event_offset );
+				}
+				
+				public int
+				getLength()
+				{
+					return( event_length );
+				}
+				
+				public PooledByteBuffer
+				getBuffer()
+				{
+					return( buffer );
+				}
+				
+				public Throwable
+				getFailure()
+				{
+					return( error );
+				}
+			}
+		}
+		
+		private QTFastStartRAF.FileAccessor
+		getAccessor(
+			final int			max_req_size,
+			final String		user_agent )
+		{
+			return( 
+				new QTFastStartRAF.FileAccessor()
+				{
+					private long				seek_position;
+					private DiskManagerRequest 	current_request;
+					private volatile boolean	closed;
+					
+					public String
+					getName()
+					{
+						try{
+							return( delegate.getDownload().getName() + "/" + delegate.getFile().getName());
+							
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+							
+							return( delegate.getFile().getAbsolutePath());
+						}
+					}
+					
+					public long
+					getFilePointer()
+					
+						throws IOException
+					{
+						return( seek_position );
+					}
+					
+					public void
+					seek(
+						long		pos )
+					
+						throws IOException
+					{
+						seek_position = pos;
+					}
+
+					public void
+					skipBytes(
+						int		num )
+					
+						throws IOException
+					{
+						seek_position += num;
+					}
+					
+					public long
+					length()
+					
+						throws IOException
+					{
+						return( getLength());
+					}
+					
+					public int
+					read(
+						final byte[]	buffer,
+						final int		pos,
+						final int		len )
+					
+						throws IOException
+					{
+						synchronized( this ){
+							
+							if ( closed ){
+								
+								throw( new IOException( "closed" ));
+							}
+							
+							current_request = delegate_channel.createRequest();
+						}
+						
+						current_request.setType( DiskManagerRequest.REQUEST_READ );
+						current_request.setOffset( seek_position );
+						current_request.setLength( len );
+						
+						current_request.setMaximumReadChunkSize( max_req_size );
+						
+						if ( user_agent != null ){
+						
+							current_request.setUserAgent( user_agent );
+						}
+						
+						final AESemaphore	sem = new AESemaphore( "waiter" );
+						final Throwable[]	error = {null};
+						
+						current_request.addListener(
+							new DiskManagerListener()
+							{
+								private int write_pos 	= pos;
+								private int	rem			= len;
+								
+								public void
+								eventOccurred(
+									DiskManagerEvent	event )
+								{
+									int	type = event.getType();
+									
+									if ( type == DiskManagerEvent.EVENT_TYPE_SUCCESS ){
+										
+										PooledByteBuffer p_buffer = event.getBuffer();
+										
+										try{
+											ByteBuffer	bb = p_buffer.toByteBuffer();
+																					
+											bb.position( 0 );
+											
+											int	read = bb.remaining();
+
+											bb.get( buffer, write_pos, read );
+											
+											write_pos 	+= read;
+											rem			-= read;
+											
+											if ( rem == 0 ){
+												
+												sem.release();
+											}
+										}finally{
+											
+											p_buffer.returnToPool();
+										}
+									}else if ( type == DiskManagerEvent.EVENT_TYPE_FAILED ){
+									
+										error[0] = event.getFailure();
+										
+										sem.release();
+									}
+								}
+							});
+						
+						current_request.run();
+						
+						while( true ){
+							
+							if ( sem.reserve( 1000 )){
+								
+								if ( error[0] != null ){
+									
+									throw( new IOException( Debug.getNestedExceptionMessage( error[0] )));
+								}
+								
+								seek_position += len;
+								
+								return( len );
+								
+							}else{
+								
+								if ( closed ){
+									
+									throw( new IOException( "Closed" ));
+								}
+							}
+						}
+					}
+					
+					public int
+					readInt()
+					
+						throws IOException
+					{
+						byte[]	readBuffer = new byte[4];
+						
+						readFully( readBuffer );
+						
+						return ((readBuffer[0] << 24) + 
+								((readBuffer[1]&0xff) << 16) + 
+								((readBuffer[2]&0xff) << 8) + 
+								((readBuffer[3]&0xff) << 0));
+					}
+					
+					public long
+					readLong()
+					
+						throws IOException
+					{
+						byte[]	readBuffer = new byte[8];
+						
+						readFully( readBuffer );
+					  
+						return (	((long)readBuffer[0] << 56) +
+					                ((long)(readBuffer[1]&0xff) << 48) +
+					                ((long)(readBuffer[2]&0xff) << 40) +
+					                ((long)(readBuffer[3]&0xff) << 32) +
+					                ((long)(readBuffer[4]&0xff) << 24) +
+					                ((readBuffer[5]&0xff) << 16) +
+					                ((readBuffer[6]&0xff) <<  8) +
+					                ((readBuffer[7]&0xff) <<  0));					
+					}
+					
+					public void
+					readFully(
+						byte[]	buffer )
+					
+						throws IOException
+					{
+						read( buffer, 0, buffer.length );
+					}
+							
+					public void
+					close()
+					
+						throws IOException
+					{
+						synchronized( this ){
+						
+							closed	= true;
+							
+							if ( current_request != null ){
+								
+								current_request.cancel();
+							}
+						}
+					}
+				});
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoFile.java b/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoFile.java
index 0e0f01b..8761d4a 100644
--- a/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoFile.java
+++ b/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoFile.java
@@ -1,494 +1,493 @@
-/*
- * Created on Feb 11, 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.download;
-
-import java.io.File;
-
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.SHA1Simple;
-import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
-import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.plugins.disk.DiskManagerListener;
-import org.gudy.azureus2.plugins.disk.DiskManagerRandomReadRequest;
-import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadException;
-import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
-import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
-
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-import com.aelitis.azureus.core.util.QTFastStartRAF;
-
-public class 
-DiskManagerFileInfoFile
-	implements DiskManagerFileInfo
-{
-	private byte[]		hash;
-	private File		file;
-	
-	public
-	DiskManagerFileInfoFile(
-		File		_file )
-	{
-		file		= _file;
-		
-		try{
-			hash		= new SHA1Simple().calculateHash( file.getAbsolutePath().getBytes( "UTF-8" ));
-			
-		}catch( Throwable e ){
-			
-			Debug.out(e);
-		}
-	}
-	
-	public void 
-	setPriority(
-		boolean b )
-	{
-	}
-	
-	public int 
-	getNumericPriorty() 
-	{
-		return( 0 );
-	}
-	
-	public int 
-	getNumericPriority() 
-	{
-		return( 0 );
-	}
-	
-	public void 
-	setNumericPriority(
-		int priority) 
-	{
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public void 
-	setSkipped(
-		boolean b )
-	{
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public void
-	setDeleted(boolean b)
-	{
-	}
-	
-	
-	public void
-	setLink(
-		File	link_destination )
-	{	
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public File
-	getLink()
-	{
-		return( null );
-	}
-		 	
-	public int 
-	getAccessMode()
-	{
-		return( READ );
-	}
-	
-	public long 
-	getDownloaded()
-	{
-		return( getLength());
-	}
-	
-	public long
-	getLength()
-	{
-		return( file.length());
-	}
-	
-	public File 
-	getFile()
-	{
-		return( file );
-	}
-	
-	public File 
-	getFile(
-		boolean follow_link ) 
-	{
-		return( file );
-	}
-	
-	public int
-	getIndex()
-	{
-		return( 0 );
-	}
-	
-	public int 
-	getFirstPieceNumber()
-	{
-		return( 0 );
-	}
-	
-	public long
-	getPieceSize()
-	{
-		return( 32*1024 );
-	}
-	
-	public int 
-	getNumPieces()
-	{
-		long	piece_size = getPieceSize();
-		
-		return((int)(( getLength() + piece_size - 1 ) / piece_size ));
-	}
-		
-	public boolean 
-	isPriority()
-	{
-		return( false );
-	}
-	
-	public boolean 
-	isSkipped()
-	{
-		return( false );
-	}
-	
-	public boolean
-	isDeleted()
-	{
-		return( false );
-	}
-	
-	public byte[] 
-	getDownloadHash()
-    {
-		return( hash );
-    }
-	
-	public Download 
-	getDownload()
-	
-      throws DownloadException
-    {
-		throw( new DownloadException( "Not supported" ));
-    }
-	
-	public DiskManagerChannel
-	createChannel()
-	
-		throws DownloadException
-	{
-		return( new channel());
-	}
-	
-	public DiskManagerRandomReadRequest
-	createRandomReadRequest(
-		long						file_offset,
-		long						length,
-		boolean						reverse_order,
-		DiskManagerListener			listener )
-	
-		throws DownloadException
-	{
-		throw( new DownloadException( "Not supported" ));
-	}
-	
-	protected class
-	channel
-		implements DiskManagerChannel
-	{
-		private volatile boolean	channel_destroyed;
-		private volatile long		channel_position;
-		
-		public DiskManagerRequest
-		createRequest()
-		{
-			return( new request());
-		}
-		
-		public DiskManagerFileInfo
-		getFile()
-		{
-			return( DiskManagerFileInfoFile.this );
-		}
-		
-		public long 
-		getPosition() 
-		{
-			return( channel_position );
-		}
-		
-		public boolean 
-		isDestroyed() 
-		{
-			return( channel_destroyed );
-		}
-		
-		public void
-		destroy()
-		{
-			channel_destroyed	= true;
-		}
-		
-		protected class
-		request
-			implements DiskManagerRequest
-		{
-			private long		offset;
-			private long		length;
-			
-			private long		position;
-			
-			private int			max_read_chunk = 128*1024;;
-
-			private volatile boolean	cancelled;
-			
-			private String		user_agent;
-			
-			private CopyOnWriteList<DiskManagerListener>		listeners = new CopyOnWriteList<DiskManagerListener>();
-			
-			public void
-			setType(
-				int			type )
-			{
-				if ( type != DiskManagerRequest.REQUEST_READ ){
-					
-					throw( new RuntimeException( "Not supported" ));
-				}
-			}
-			
-			public void
-			setOffset(
-				long		_offset )
-			{
-				offset		= _offset;
-			}
-			
-			public void
-			setLength(
-				long		_length )
-			{
-				if ( _length < 0 ){
-					
-					throw( new RuntimeException( "Illegal argument" ));
-				}
-				
-				length		= _length;
-			}
-				
-			public void
-			setMaximumReadChunkSize(
-				int 	size )
-			{
-				max_read_chunk = size;
-			}
-			
-			public void
-			setUserAgent(
-				String		agent )
-			{	
-				user_agent	= agent;
-			}
-
-			
-			public long
-			getAvailableBytes()
-			{
-				return( getRemaining());
-			}
-						
-			public long
-			getRemaining()
-			{
-				return( offset + length - position );
-			}
-			
-			public void
-			run()
-			{
-				QTFastStartRAF	raf = null;
-				
-				String name = file.getName();
-				
-				int	dot_pos = name.lastIndexOf('.');
-				
-				String ext = dot_pos<0?"":name.substring(dot_pos+1);
-				
-				try{
-					raf = new QTFastStartRAF( file, user_agent != null && QTFastStartRAF.isSupportedExtension( ext ));
-					
-					raf.seek( offset );
-			
-					byte[] buffer = new byte[max_read_chunk];
-					
-					long	rem		= length;
-					long	pos 	= offset;
-					
-					while( rem > 0 ){
-						
-						if ( cancelled ){
-							
-							throw( new Exception( "Cancelled" ));
-							
-						}else if ( channel_destroyed ){
-							
-							throw( new Exception( "Destroyed" ));
-						}
-						
-						int	chunk = (int)Math.min( rem, max_read_chunk );
-						
-						int	len = raf.read( buffer, 0, chunk );
-												
-						sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
-						
-						rem -= len;
-						pos	+= len;
-					}
-				}catch( Throwable e ){
-					
-					sendEvent( new event( e ));
-					
-				}finally{
-					
-					if ( raf != null ){
-						
-						try{
-							raf.close();
-							
-						}catch( Throwable e ){
-							
-							Debug.out( e );
-						}
-					}
-				}
-			}
-			
-			public void
-			cancel()
-			{
-				cancelled = true;
-			}
-						
-			protected void
-			sendEvent(
-				event		ev )
-			{					
-				for ( DiskManagerListener l: listeners ){
-					
-					l.eventOccurred( ev );
-				}
-			}
-			
-			public void
-			addListener(
-				DiskManagerListener	listener )
-			{
-				listeners.add( listener );
-			}
-			
-			public void
-			removeListener(
-				DiskManagerListener	listener )
-			{
-				listeners.remove( listener );
-			}
-		
-			protected class
-			event
-				implements DiskManagerEvent
-			{
-				private int					event_type;
-				private Throwable			error;
-				private PooledByteBuffer	buffer;
-				private long				event_offset;
-				private int					event_length;
-				
-				protected
-				event(
-					Throwable		_error )
-				{
-					event_type	= DiskManagerEvent.EVENT_TYPE_FAILED;
-					error		= _error;
-				}
-								
-				protected
-				event(
-					PooledByteBuffer	_buffer,
-					long				_offset,
-					int					_length )
-				{
-					event_type		= DiskManagerEvent.EVENT_TYPE_SUCCESS;
-					buffer			= _buffer;
-					event_offset	= _offset;
-					event_length	= _length;
-					
-					channel_position = _offset + _length - 1;
-				}
-				
-				public int
-				getType()
-				{
-					return( event_type );
-				}
-				
-				public DiskManagerRequest
-				getRequest()
-				{
-					return( request.this );
-				}
-				
-				public long
-				getOffset()
-				{
-					return( event_offset );
-				}
-				
-				public int
-				getLength()
-				{
-					return( event_length );
-				}
-				
-				public PooledByteBuffer
-				getBuffer()
-				{
-					return( buffer );
-				}
-				
-				public Throwable
-				getFailure()
-				{
-					return( error );
-				}
-			}
-		}
-	}
-}
+/*
+ * Created on Feb 11, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.download;
+
+import java.io.File;
+
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.SHA1Simple;
+import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
+import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.disk.DiskManagerListener;
+import org.gudy.azureus2.plugins.disk.DiskManagerRandomReadRequest;
+import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadException;
+import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
+import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
+
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.core.util.QTFastStartRAF;
+
+public class 
+DiskManagerFileInfoFile
+	implements DiskManagerFileInfo
+{
+	private byte[]		hash;
+	private File		file;
+	
+	public
+	DiskManagerFileInfoFile(
+		File		_file )
+	{
+		file		= _file;
+		
+		try{
+			hash		= new SHA1Simple().calculateHash( file.getAbsolutePath().getBytes( "UTF-8" ));
+			
+		}catch( Throwable e ){
+			
+			Debug.out(e);
+		}
+	}
+	
+	public void 
+	setPriority(
+		boolean b )
+	{
+	}
+	
+	public int 
+	getNumericPriorty() 
+	{
+		return( 0 );
+	}
+	
+	public int 
+	getNumericPriority() 
+	{
+		return( 0 );
+	}
+	
+	public void 
+	setNumericPriority(
+		int priority) 
+	{
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public void 
+	setSkipped(
+		boolean b )
+	{
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public void
+	setDeleted(boolean b)
+	{
+	}
+	
+	
+	public void
+	setLink(
+		File	link_destination )
+	{	
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public File
+	getLink()
+	{
+		return( null );
+	}
+		 	
+	public int 
+	getAccessMode()
+	{
+		return( READ );
+	}
+	
+	public long 
+	getDownloaded()
+	{
+		return( getLength());
+	}
+	
+	public long
+	getLength()
+	{
+		return( file.length());
+	}
+	
+	public File 
+	getFile()
+	{
+		return( file );
+	}
+	
+	public File 
+	getFile(
+		boolean follow_link ) 
+	{
+		return( file );
+	}
+	
+	public int
+	getIndex()
+	{
+		return( 0 );
+	}
+	
+	public int 
+	getFirstPieceNumber()
+	{
+		return( 0 );
+	}
+	
+	public long
+	getPieceSize()
+	{
+		return( 32*1024 );
+	}
+	
+	public int 
+	getNumPieces()
+	{
+		long	piece_size = getPieceSize();
+		
+		return((int)(( getLength() + piece_size - 1 ) / piece_size ));
+	}
+		
+	public boolean 
+	isPriority()
+	{
+		return( false );
+	}
+	
+	public boolean 
+	isSkipped()
+	{
+		return( false );
+	}
+	
+	public boolean
+	isDeleted()
+	{
+		return( false );
+	}
+	
+	public byte[] 
+	getDownloadHash()
+    {
+		return( hash );
+    }
+	
+	public Download 
+	getDownload()
+	
+      throws DownloadException
+    {
+		throw( new DownloadException( "Not supported" ));
+    }
+	
+	public DiskManagerChannel
+	createChannel()
+	
+		throws DownloadException
+	{
+		return( new channel());
+	}
+	
+	public DiskManagerRandomReadRequest
+	createRandomReadRequest(
+		long						file_offset,
+		long						length,
+		boolean						reverse_order,
+		DiskManagerListener			listener )
+	
+		throws DownloadException
+	{
+		throw( new DownloadException( "Not supported" ));
+	}
+	
+	protected class
+	channel
+		implements DiskManagerChannel
+	{
+		private volatile boolean	channel_destroyed;
+		private volatile long		channel_position;
+		
+		public DiskManagerRequest
+		createRequest()
+		{
+			return( new request());
+		}
+		
+		public DiskManagerFileInfo
+		getFile()
+		{
+			return( DiskManagerFileInfoFile.this );
+		}
+		
+		public long 
+		getPosition() 
+		{
+			return( channel_position );
+		}
+		
+		public boolean 
+		isDestroyed() 
+		{
+			return( channel_destroyed );
+		}
+		
+		public void
+		destroy()
+		{
+			channel_destroyed	= true;
+		}
+		
+		protected class
+		request
+			implements DiskManagerRequest
+		{
+			private long		offset;
+			private long		length;
+			
+			private long		position;
+			
+			private int			max_read_chunk = 128*1024;;
+
+			private volatile boolean	cancelled;
+			
+			private String		user_agent;
+			
+			private CopyOnWriteList<DiskManagerListener>		listeners = new CopyOnWriteList<DiskManagerListener>();
+			
+			public void
+			setType(
+				int			type )
+			{
+				if ( type != DiskManagerRequest.REQUEST_READ ){
+					
+					throw( new RuntimeException( "Not supported" ));
+				}
+			}
+			
+			public void
+			setOffset(
+				long		_offset )
+			{
+				offset		= _offset;
+			}
+			
+			public void
+			setLength(
+				long		_length )
+			{
+				if ( _length < 0 ){
+					
+					throw( new RuntimeException( "Illegal argument" ));
+				}
+				
+				length		= _length;
+			}
+				
+			public void
+			setMaximumReadChunkSize(
+				int 	size )
+			{
+				max_read_chunk = size;
+			}
+			
+			public void
+			setUserAgent(
+				String		agent )
+			{	
+				user_agent	= agent;
+			}
+
+			
+			public long
+			getAvailableBytes()
+			{
+				return( getRemaining());
+			}
+						
+			public long
+			getRemaining()
+			{
+				return( offset + length - position );
+			}
+			
+			public void
+			run()
+			{
+				QTFastStartRAF	raf = null;
+				
+				String name = file.getName();
+				
+				int	dot_pos = name.lastIndexOf('.');
+				
+				String ext = dot_pos<0?"":name.substring(dot_pos+1);
+				
+				try{
+					raf = new QTFastStartRAF( file, user_agent != null && QTFastStartRAF.isSupportedExtension( ext ));
+					
+					raf.seek( offset );
+			
+					byte[] buffer = new byte[max_read_chunk];
+					
+					long	rem		= length;
+					long	pos 	= offset;
+					
+					while( rem > 0 ){
+						
+						if ( cancelled ){
+							
+							throw( new Exception( "Cancelled" ));
+							
+						}else if ( channel_destroyed ){
+							
+							throw( new Exception( "Destroyed" ));
+						}
+						
+						int	chunk = (int)Math.min( rem, max_read_chunk );
+						
+						int	len = raf.read( buffer, 0, chunk );
+												
+						sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
+						
+						rem -= len;
+						pos	+= len;
+					}
+				}catch( Throwable e ){
+					
+					sendEvent( new event( e ));
+					
+				}finally{
+					
+					if ( raf != null ){
+						
+						try{
+							raf.close();
+							
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}
+				}
+			}
+			
+			public void
+			cancel()
+			{
+				cancelled = true;
+			}
+						
+			protected void
+			sendEvent(
+				event		ev )
+			{					
+				for ( DiskManagerListener l: listeners ){
+					
+					l.eventOccurred( ev );
+				}
+			}
+			
+			public void
+			addListener(
+				DiskManagerListener	listener )
+			{
+				listeners.add( listener );
+			}
+			
+			public void
+			removeListener(
+				DiskManagerListener	listener )
+			{
+				listeners.remove( listener );
+			}
+		
+			protected class
+			event
+				implements DiskManagerEvent
+			{
+				private int					event_type;
+				private Throwable			error;
+				private PooledByteBuffer	buffer;
+				private long				event_offset;
+				private int					event_length;
+				
+				protected
+				event(
+					Throwable		_error )
+				{
+					event_type	= DiskManagerEvent.EVENT_TYPE_FAILED;
+					error		= _error;
+				}
+								
+				protected
+				event(
+					PooledByteBuffer	_buffer,
+					long				_offset,
+					int					_length )
+				{
+					event_type		= DiskManagerEvent.EVENT_TYPE_SUCCESS;
+					buffer			= _buffer;
+					event_offset	= _offset;
+					event_length	= _length;
+					
+					channel_position = _offset + _length - 1;
+				}
+				
+				public int
+				getType()
+				{
+					return( event_type );
+				}
+				
+				public DiskManagerRequest
+				getRequest()
+				{
+					return( request.this );
+				}
+				
+				public long
+				getOffset()
+				{
+					return( event_offset );
+				}
+				
+				public int
+				getLength()
+				{
+					return( event_length );
+				}
+				
+				public PooledByteBuffer
+				getBuffer()
+				{
+					return( buffer );
+				}
+				
+				public Throwable
+				getFailure()
+				{
+					return( error );
+				}
+			}
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoStream.java b/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoStream.java
index ac57197..92be56b 100644
--- a/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoStream.java
+++ b/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoStream.java
@@ -1,839 +1,838 @@
-/*
- * Created on Feb 11, 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.download;
-
-import java.io.*;
-import java.util.*;
-
-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.SHA1Simple;
-import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
-import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.plugins.disk.DiskManagerListener;
-import org.gudy.azureus2.plugins.disk.DiskManagerRandomReadRequest;
-import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadException;
-import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
-import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
-
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-
-public class 
-DiskManagerFileInfoStream
-	implements DiskManagerFileInfo
-{
-	private StreamFactory		stream_factory;
-	private File				save_to;
-	private byte[]				hash;
-	
-	private context				current_context;
-	
-	private Object	lock = this;
-	
-	public
-	DiskManagerFileInfoStream(
-		StreamFactory		_stream_factory,
-		File				_save_to )
-	{
-		stream_factory		= _stream_factory;
-		save_to				= _save_to;
-		
-		try{
-			hash		= new SHA1Simple().calculateHash( _save_to.getAbsolutePath().getBytes( "UTF-8" ));
-			
-		}catch( Throwable e ){
-			
-			Debug.out(e);
-		}
-	}
-	
-	public boolean
-	isComplete()
-	{
-		synchronized( lock ){
-
-			return( save_to.exists());
-		}
-	}
-	
-	public void
-	reset()
-	{
-		synchronized( lock ){
-
-			if ( current_context != null ){
-				
-				current_context.destroy( new Exception( "Reset" ));
-			}
-			
-			save_to.delete();
-		}
-	}
-	
-	public void 
-	setPriority(
-		boolean b )
-	{
-	}
-	
-	public void 
-	setSkipped(
-		boolean b )
-	{
-		throw( new RuntimeException( "Not supported" ));
-	}
-
-	public int 
-	getNumericPriority() 
-	{
-		return( 0 );
-	}
-	
-
-	public int 
-	getNumericPriorty() 
-	{
-		return( 0 );
-	}
-	
-	public void 
-	setNumericPriority(
-		int priority) 
-	{
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public void
-	setDeleted(boolean b)
-	{
-	}	
-	
-	public void
-	setLink(
-		File	link_destination )
-	{	
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public File
-	getLink()
-	{
-		return( null );
-	}
-		 	
-	public int 
-	getAccessMode()
-	{
-		return( READ );
-	}
-	
-	public long 
-	getDownloaded()
-	{
-		return( getLength());
-	}
-	
-	public long
-	getLength()
-	{
-		return( -1 );
-	}
-	
-	public File 
-	getFile()
-	{
-		return( save_to );
-	}
-		
-	public File
-	getFile(
-		boolean	follow_link )
-	{
-		return( save_to );
-	}
-	
-	public int
-	getIndex()
-	{
-		return( 0 );
-	}
-	
-	public int 
-	getFirstPieceNumber()
-	{
-		return( 0 );
-	}
-	
-	public long
-	getPieceSize()
-	{
-		return( 32*1024 );
-	}
-	
-	public int 
-	getNumPieces()
-	{
-		return( -1 );
-	}
-		
-	public boolean 
-	isPriority()
-	{
-		return( false );
-	}
-	
-	public boolean 
-	isSkipped()
-	{
-		return( false );
-	}
-	
-	public boolean
-	isDeleted()
-	{
-		return( false );
-	}
-	
-	public byte[] 
-	getDownloadHash() 
-	
-		throws DownloadException 
-	{
-		return( hash );
-	}
-	
-	public Download 
-	getDownload()
-	
-         throws DownloadException
-    {
-		throw( new DownloadException( "Not supported" ));
-    }
-	
-	public DiskManagerChannel
-	createChannel()
-	
-		throws DownloadException
-	{
-		try{
-			synchronized( lock ){
-				
-				if ( current_context == null ){
-					
-					current_context = new context();
-				}
-				
-				return( current_context.createChannel());
-			}
-		}catch( Throwable e ){
-			
-			throw( new DownloadException( "Channel creation failed", e ));
-		}
-	}
-	
-	public DiskManagerRandomReadRequest
-	createRandomReadRequest(
-		long						file_offset,
-		long						length,
-		boolean						reverse_order,
-		DiskManagerListener			listener )
-	
-		throws DownloadException
-	{
-		throw( new DownloadException( "Not supported" ));
-	}
-	
-	protected void
-	destroyed(
-		context		c )
-	{
-		synchronized( lock ){
-			
-			if ( current_context == c ){
-				
-				current_context = null;
-			}
-		}
-		
-		stream_factory.destroyed( c );
-	}
-	
-	protected class
-	context
-	{
-		private RandomAccessFile				raf;
-		private StreamFactory.StreamDetails		stream_details;
-		
-		private boolean				stream_got_eof;
-		
-		private List<channel>		channels	= new ArrayList<channel>();
-
-		private List<AESemaphore>	waiters 	= new ArrayList<AESemaphore>();
-		
-		private boolean				context_destroyed;
-		
-		protected
-		context()
-		
-			throws Exception
-		{
-			if ( save_to.exists()){
-				
-				raf = new RandomAccessFile( save_to, "r" );
-				
-				stream_got_eof = true;
-				
-			}else{
-				
-				final File	temp_file = new File( save_to.getAbsolutePath() + "._tmp_" );
-				
-				raf = new RandomAccessFile( temp_file, "rw" );
-
-				stream_details = stream_factory.getStream( this );
-				
-				final InputStream stream = stream_details.getStream();
-				
-				new AEThread2( "DMS:reader", true )
-				{
-					public void
-					run()
-					{
-						final int BUFF_SIZE = 128*1024;
-						
-						byte[]	buffer = new byte[BUFF_SIZE];
-						
-						try{
-							while( true ){
-								
-								int len = stream.read( buffer );
-								
-								if ( len <= 0 ){
-									
-									if ( stream_details.hasFailed()){
-										
-										throw( new IOException( "Stream failed" ));
-									}
-									
-									synchronized( lock ){
-
-										stream_got_eof	= true;
-									}
-									
-									break;
-								}
-								
-								synchronized( lock ){
-									
-									raf.seek( raf.length());
-									
-									raf.write( buffer, 0, len );
-									
-									for ( AESemaphore waiter: waiters ){
-										
-										waiter.release();
-									}
-								}
-							}								
-						}catch( Throwable e ){
-															
-							context.this.destroy( e );
-							
-						}finally{
-							
-							try{
-								stream.close();
-																	
-							}catch( Throwable e ){
-								
-							}
-							
-							Throwable failed = null;
-							
-							synchronized( lock ){
-								
-								stream_details = null;
-								
-								if ( stream_got_eof ){
-									
-									try{
-										raf.close();
-										
-										save_to.delete();
-										
-										temp_file.renameTo( save_to );
-										
-										raf = new RandomAccessFile( save_to, "r" );
-										
-									}catch( Throwable e ){
-																					
-										failed = e;
-									}
-								}
-							}
-							
-							if ( failed != null ){
-								
-								context.this.destroy( failed );
-							}
-						}
-					}
-				}.start();
-			}
-		}
-		
-		protected int
-		read(
-			byte[]		buffer,
-			long		offset,
-			int			length )
-		
-			throws IOException
-		{
-			AESemaphore	sem;
-			
-			synchronized( lock ){
-				
-				if ( raf.length() > offset ){
-					
-					raf.seek( offset );
-					
-					return( raf.read( buffer, 0, length ));
-				}	
-				
-				if ( stream_details == null ){
-					
-					if ( stream_got_eof ){
-						
-						return( -1 );
-					}
-					
-					throw( new IOException( "Premature end of stream (read)" ));
-				}
-				
-				sem = new AESemaphore( "DMS:block" );
-				
-				waiters.add( sem );
-			}
-			
-			try{
-				sem.reserve( 1000 );
-			
-			}finally{
-			
-				synchronized( lock ){
-
-					waiters.remove( sem );
-				}
-			}
-			
-			return( 0 );
-		}
-		
-		protected channel
-		createChannel()
-		{
-			synchronized( lock ){
-
-				channel c = new channel();
-				
-				channels.add( c );
-				
-				return( c );
-			}
-		}
-		
-		protected void
-		removeChannel(
-			channel	c )
-		{
-			synchronized( lock ){
-
-				channels.remove( c );
-			
-				if ( channels.size() == 0 && save_to.exists()){
-					
-					destroy( null );
-				}
-			}
-		}
-		
-		protected void
-		destroy(
-			Throwable error )
-		{
-			if ( error != null ){
-				
-				Debug.out( error );
-			}
-			
-			synchronized( lock ){
-
-				if ( context_destroyed ){
-					
-					return;
-				}
-				
-				context_destroyed = true;
-				
-				if ( channels != null ){
-					
-					List<channel> channels_copy = new ArrayList<channel>( channels );
-					
-					for ( channel c: channels_copy ){
-						
-						c.destroy();
-					}
-				}
-				
-				if ( raf != null ){
-					
-					try{
-						raf.close();
-						
-					}catch( Throwable e ){
-					}
-					
-					raf = null;
-				}
-				
-				if ( stream_details != null ){
-					
-					try{
-						stream_details.getStream().close();
-						
-					}catch( Throwable e ){
-						
-					}
-					
-					stream_details = null;
-				}
-				
-				if ( error != null ){
-				
-					save_to.delete();
-				}
-			}
-			
-			DiskManagerFileInfoStream.this.destroyed( this );
-		}
-	
-		protected class
-		channel
-			implements DiskManagerChannel
-		{
-			private volatile boolean	channel_destroyed;
-			private volatile long		channel_position;
-			
-			public DiskManagerRequest
-			createRequest()
-			{
-				return( new request());
-			}
-			
-			public DiskManagerFileInfo
-			getFile()
-			{
-				return( DiskManagerFileInfoStream.this );
-			}
-			
-			public long 
-			getPosition() 
-			{
-				return( channel_position );
-			}
-			
-			public boolean 
-			isDestroyed() 
-			{
-				return( channel_destroyed );
-			}
-			
-			public void
-			destroy()
-			{
-				channel_destroyed	= true;
-				
-				removeChannel( this );
-			}
-			
-			protected class
-			request
-				implements DiskManagerRequest
-			{
-				private long		offset;
-				private long		length;
-				
-				private long		position;
-				
-				private int			max_read_chunk = 128*1024;;
-				
-				private volatile boolean	request_cancelled;
-				
-				private CopyOnWriteList<DiskManagerListener>		listeners = new CopyOnWriteList<DiskManagerListener>();
-				
-				public void
-				setType(
-					int			type )
-				{
-					if ( type != DiskManagerRequest.REQUEST_READ ){
-						
-						throw( new RuntimeException( "Not supported" ));
-					}
-				}
-				
-				public void
-				setOffset(
-					long		_offset )
-				{
-					offset		= _offset;
-				}
-				
-				public void
-				setLength(
-					long		_length )
-				{
-						// length can be -1 here meaning 'to the end'
-					
-					length		= _length==-1?Long.MAX_VALUE:_length;
-				}
-					
-				public void
-				setMaximumReadChunkSize(
-					int 	size )
-				{
-					if ( size > 16*1024 ){
-					
-						max_read_chunk = size;
-					}
-				}
-				
-				public long
-				getAvailableBytes()
-				{
-					return( getRemaining());
-				}
-							
-				public long
-				getRemaining()
-				{
-					return( length==Long.MAX_VALUE?length:(offset + length - position ));
-				}
-				
-				public void
-				run()
-				{
-					try{				
-						byte[] buffer = new byte[max_read_chunk];
-						
-						long	rem		= length;
-						long	pos 	= offset;
-						
-						while( rem > 0 ){
-							
-							if ( request_cancelled ){
-								
-								throw( new Exception( "Cancelled" ));
-								
-							}else if ( channel_destroyed ){
-								
-								throw( new Exception( "Destroyed" ));
-							}
-							
-							int	chunk = (int)Math.min( rem, max_read_chunk );
-							
-							int	len = read( buffer, pos, chunk );
-								
-							if ( len == -1 ){
-								
-								if ( length == Long.MAX_VALUE ){
-									
-									break;
-									
-								}else{
-									
-									throw( new Exception( "Premature end of stream (complete)" ));
-								}
-							}else if ( len == 0 ){
-								
-								sendEvent( new event( pos ));
-								
-							}else{
-																
-								sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
-								
-								rem -= len;
-								pos	+= len;
-							}
-						}
-					}catch( Throwable e ){
-						
-						sendEvent( new event( e ));
-					}
-				}
-				
-				public void
-				cancel()
-				{
-					request_cancelled = true;
-				}
-				
-				public void
-				setUserAgent(
-					String		agent )
-				{	
-				}
-				
-				protected void
-				sendEvent(
-					event		ev )
-				{					
-					for ( DiskManagerListener l: listeners ){
-						
-						l.eventOccurred( ev );
-					}
-				}
-				
-				public void
-				addListener(
-					DiskManagerListener	listener )
-				{
-					listeners.add( listener );
-				}
-				
-				public void
-				removeListener(
-					DiskManagerListener	listener )
-				{
-					listeners.remove( listener );
-				}
-			
-				protected class
-				event
-					implements DiskManagerEvent
-				{
-					private int					event_type;
-					private Throwable			error;
-					private PooledByteBuffer	buffer;
-					private long				event_offset;
-					private int					event_length;
-					
-					protected
-					event(
-						Throwable		_error )
-					{
-						event_type	= DiskManagerEvent.EVENT_TYPE_FAILED;
-						error		= _error;
-					}
-						
-					protected 
-					event(
-						long				_offset )
-					{
-						event_type		= DiskManagerEvent.EVENT_TYPE_BLOCKED;
-
-						event_offset	= _offset;	
-						
-						channel_position	= _offset;
-					}
-					
-					protected
-					event(
-						PooledByteBuffer	_buffer,
-						long				_offset,
-						int					_length )
-					{
-						event_type		= DiskManagerEvent.EVENT_TYPE_SUCCESS;
-						buffer			= _buffer;
-						event_offset	= _offset;
-						event_length	= _length;
-						
-						channel_position	= _offset + _length - 1;
-					}
-					
-					public int
-					getType()
-					{
-						return( event_type );
-					}
-					
-					public DiskManagerRequest
-					getRequest()
-					{
-						return( request.this );
-					}
-					
-					public long
-					getOffset()
-					{
-						return( event_offset );
-					}
-					
-					public int
-					getLength()
-					{
-						return( event_length );
-					}
-					
-					public PooledByteBuffer
-					getBuffer()
-					{
-						return( buffer );
-					}
-					
-					public Throwable
-					getFailure()
-					{
-						return( error );
-					}
-				}
-			}
-		}
-	}
-
-	public interface
-	StreamFactory
-	{
-		public StreamDetails
-		getStream(
-			Object		requester )
-		
-			throws IOException;
-		
-		public void
-		destroyed(
-			Object		requester );
-		
-		public interface
-		StreamDetails
-		{
-			public InputStream
-			getStream();
-			
-			public boolean
-			hasFailed();
-		}
-	}
-}
+/*
+ * Created on Feb 11, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.download;
+
+import java.io.*;
+import java.util.*;
+
+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.SHA1Simple;
+import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
+import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.disk.DiskManagerListener;
+import org.gudy.azureus2.plugins.disk.DiskManagerRandomReadRequest;
+import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadException;
+import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
+import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
+
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+
+public class 
+DiskManagerFileInfoStream
+	implements DiskManagerFileInfo
+{
+	private StreamFactory		stream_factory;
+	private File				save_to;
+	private byte[]				hash;
+	
+	private context				current_context;
+	
+	private Object	lock = this;
+	
+	public
+	DiskManagerFileInfoStream(
+		StreamFactory		_stream_factory,
+		File				_save_to )
+	{
+		stream_factory		= _stream_factory;
+		save_to				= _save_to;
+		
+		try{
+			hash		= new SHA1Simple().calculateHash( _save_to.getAbsolutePath().getBytes( "UTF-8" ));
+			
+		}catch( Throwable e ){
+			
+			Debug.out(e);
+		}
+	}
+	
+	public boolean
+	isComplete()
+	{
+		synchronized( lock ){
+
+			return( save_to.exists());
+		}
+	}
+	
+	public void
+	reset()
+	{
+		synchronized( lock ){
+
+			if ( current_context != null ){
+				
+				current_context.destroy( new Exception( "Reset" ));
+			}
+			
+			save_to.delete();
+		}
+	}
+	
+	public void 
+	setPriority(
+		boolean b )
+	{
+	}
+	
+	public void 
+	setSkipped(
+		boolean b )
+	{
+		throw( new RuntimeException( "Not supported" ));
+	}
+
+	public int 
+	getNumericPriority() 
+	{
+		return( 0 );
+	}
+	
+
+	public int 
+	getNumericPriorty() 
+	{
+		return( 0 );
+	}
+	
+	public void 
+	setNumericPriority(
+		int priority) 
+	{
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public void
+	setDeleted(boolean b)
+	{
+	}	
+	
+	public void
+	setLink(
+		File	link_destination )
+	{	
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public File
+	getLink()
+	{
+		return( null );
+	}
+		 	
+	public int 
+	getAccessMode()
+	{
+		return( READ );
+	}
+	
+	public long 
+	getDownloaded()
+	{
+		return( getLength());
+	}
+	
+	public long
+	getLength()
+	{
+		return( -1 );
+	}
+	
+	public File 
+	getFile()
+	{
+		return( save_to );
+	}
+		
+	public File
+	getFile(
+		boolean	follow_link )
+	{
+		return( save_to );
+	}
+	
+	public int
+	getIndex()
+	{
+		return( 0 );
+	}
+	
+	public int 
+	getFirstPieceNumber()
+	{
+		return( 0 );
+	}
+	
+	public long
+	getPieceSize()
+	{
+		return( 32*1024 );
+	}
+	
+	public int 
+	getNumPieces()
+	{
+		return( -1 );
+	}
+		
+	public boolean 
+	isPriority()
+	{
+		return( false );
+	}
+	
+	public boolean 
+	isSkipped()
+	{
+		return( false );
+	}
+	
+	public boolean
+	isDeleted()
+	{
+		return( false );
+	}
+	
+	public byte[] 
+	getDownloadHash() 
+	
+		throws DownloadException 
+	{
+		return( hash );
+	}
+	
+	public Download 
+	getDownload()
+	
+         throws DownloadException
+    {
+		throw( new DownloadException( "Not supported" ));
+    }
+	
+	public DiskManagerChannel
+	createChannel()
+	
+		throws DownloadException
+	{
+		try{
+			synchronized( lock ){
+				
+				if ( current_context == null ){
+					
+					current_context = new context();
+				}
+				
+				return( current_context.createChannel());
+			}
+		}catch( Throwable e ){
+			
+			throw( new DownloadException( "Channel creation failed", e ));
+		}
+	}
+	
+	public DiskManagerRandomReadRequest
+	createRandomReadRequest(
+		long						file_offset,
+		long						length,
+		boolean						reverse_order,
+		DiskManagerListener			listener )
+	
+		throws DownloadException
+	{
+		throw( new DownloadException( "Not supported" ));
+	}
+	
+	protected void
+	destroyed(
+		context		c )
+	{
+		synchronized( lock ){
+			
+			if ( current_context == c ){
+				
+				current_context = null;
+			}
+		}
+		
+		stream_factory.destroyed( c );
+	}
+	
+	protected class
+	context
+	{
+		private RandomAccessFile				raf;
+		private StreamFactory.StreamDetails		stream_details;
+		
+		private boolean				stream_got_eof;
+		
+		private List<channel>		channels	= new ArrayList<channel>();
+
+		private List<AESemaphore>	waiters 	= new ArrayList<AESemaphore>();
+		
+		private boolean				context_destroyed;
+		
+		protected
+		context()
+		
+			throws Exception
+		{
+			if ( save_to.exists()){
+				
+				raf = new RandomAccessFile( save_to, "r" );
+				
+				stream_got_eof = true;
+				
+			}else{
+				
+				final File	temp_file = new File( save_to.getAbsolutePath() + "._tmp_" );
+				
+				raf = new RandomAccessFile( temp_file, "rw" );
+
+				stream_details = stream_factory.getStream( this );
+				
+				final InputStream stream = stream_details.getStream();
+				
+				new AEThread2( "DMS:reader", true )
+				{
+					public void
+					run()
+					{
+						final int BUFF_SIZE = 128*1024;
+						
+						byte[]	buffer = new byte[BUFF_SIZE];
+						
+						try{
+							while( true ){
+								
+								int len = stream.read( buffer );
+								
+								if ( len <= 0 ){
+									
+									if ( stream_details.hasFailed()){
+										
+										throw( new IOException( "Stream failed" ));
+									}
+									
+									synchronized( lock ){
+
+										stream_got_eof	= true;
+									}
+									
+									break;
+								}
+								
+								synchronized( lock ){
+									
+									raf.seek( raf.length());
+									
+									raf.write( buffer, 0, len );
+									
+									for ( AESemaphore waiter: waiters ){
+										
+										waiter.release();
+									}
+								}
+							}								
+						}catch( Throwable e ){
+															
+							context.this.destroy( e );
+							
+						}finally{
+							
+							try{
+								stream.close();
+																	
+							}catch( Throwable e ){
+								
+							}
+							
+							Throwable failed = null;
+							
+							synchronized( lock ){
+								
+								stream_details = null;
+								
+								if ( stream_got_eof ){
+									
+									try{
+										raf.close();
+										
+										save_to.delete();
+										
+										temp_file.renameTo( save_to );
+										
+										raf = new RandomAccessFile( save_to, "r" );
+										
+									}catch( Throwable e ){
+																					
+										failed = e;
+									}
+								}
+							}
+							
+							if ( failed != null ){
+								
+								context.this.destroy( failed );
+							}
+						}
+					}
+				}.start();
+			}
+		}
+		
+		protected int
+		read(
+			byte[]		buffer,
+			long		offset,
+			int			length )
+		
+			throws IOException
+		{
+			AESemaphore	sem;
+			
+			synchronized( lock ){
+				
+				if ( raf.length() > offset ){
+					
+					raf.seek( offset );
+					
+					return( raf.read( buffer, 0, length ));
+				}	
+				
+				if ( stream_details == null ){
+					
+					if ( stream_got_eof ){
+						
+						return( -1 );
+					}
+					
+					throw( new IOException( "Premature end of stream (read)" ));
+				}
+				
+				sem = new AESemaphore( "DMS:block" );
+				
+				waiters.add( sem );
+			}
+			
+			try{
+				sem.reserve( 1000 );
+			
+			}finally{
+			
+				synchronized( lock ){
+
+					waiters.remove( sem );
+				}
+			}
+			
+			return( 0 );
+		}
+		
+		protected channel
+		createChannel()
+		{
+			synchronized( lock ){
+
+				channel c = new channel();
+				
+				channels.add( c );
+				
+				return( c );
+			}
+		}
+		
+		protected void
+		removeChannel(
+			channel	c )
+		{
+			synchronized( lock ){
+
+				channels.remove( c );
+			
+				if ( channels.size() == 0 && save_to.exists()){
+					
+					destroy( null );
+				}
+			}
+		}
+		
+		protected void
+		destroy(
+			Throwable error )
+		{
+			if ( error != null ){
+				
+				Debug.out( error );
+			}
+			
+			synchronized( lock ){
+
+				if ( context_destroyed ){
+					
+					return;
+				}
+				
+				context_destroyed = true;
+				
+				if ( channels != null ){
+					
+					List<channel> channels_copy = new ArrayList<channel>( channels );
+					
+					for ( channel c: channels_copy ){
+						
+						c.destroy();
+					}
+				}
+				
+				if ( raf != null ){
+					
+					try{
+						raf.close();
+						
+					}catch( Throwable e ){
+					}
+					
+					raf = null;
+				}
+				
+				if ( stream_details != null ){
+					
+					try{
+						stream_details.getStream().close();
+						
+					}catch( Throwable e ){
+						
+					}
+					
+					stream_details = null;
+				}
+				
+				if ( error != null ){
+				
+					save_to.delete();
+				}
+			}
+			
+			DiskManagerFileInfoStream.this.destroyed( this );
+		}
+	
+		protected class
+		channel
+			implements DiskManagerChannel
+		{
+			private volatile boolean	channel_destroyed;
+			private volatile long		channel_position;
+			
+			public DiskManagerRequest
+			createRequest()
+			{
+				return( new request());
+			}
+			
+			public DiskManagerFileInfo
+			getFile()
+			{
+				return( DiskManagerFileInfoStream.this );
+			}
+			
+			public long 
+			getPosition() 
+			{
+				return( channel_position );
+			}
+			
+			public boolean 
+			isDestroyed() 
+			{
+				return( channel_destroyed );
+			}
+			
+			public void
+			destroy()
+			{
+				channel_destroyed	= true;
+				
+				removeChannel( this );
+			}
+			
+			protected class
+			request
+				implements DiskManagerRequest
+			{
+				private long		offset;
+				private long		length;
+				
+				private long		position;
+				
+				private int			max_read_chunk = 128*1024;;
+				
+				private volatile boolean	request_cancelled;
+				
+				private CopyOnWriteList<DiskManagerListener>		listeners = new CopyOnWriteList<DiskManagerListener>();
+				
+				public void
+				setType(
+					int			type )
+				{
+					if ( type != DiskManagerRequest.REQUEST_READ ){
+						
+						throw( new RuntimeException( "Not supported" ));
+					}
+				}
+				
+				public void
+				setOffset(
+					long		_offset )
+				{
+					offset		= _offset;
+				}
+				
+				public void
+				setLength(
+					long		_length )
+				{
+						// length can be -1 here meaning 'to the end'
+					
+					length		= _length==-1?Long.MAX_VALUE:_length;
+				}
+					
+				public void
+				setMaximumReadChunkSize(
+					int 	size )
+				{
+					if ( size > 16*1024 ){
+					
+						max_read_chunk = size;
+					}
+				}
+				
+				public long
+				getAvailableBytes()
+				{
+					return( getRemaining());
+				}
+							
+				public long
+				getRemaining()
+				{
+					return( length==Long.MAX_VALUE?length:(offset + length - position ));
+				}
+				
+				public void
+				run()
+				{
+					try{				
+						byte[] buffer = new byte[max_read_chunk];
+						
+						long	rem		= length;
+						long	pos 	= offset;
+						
+						while( rem > 0 ){
+							
+							if ( request_cancelled ){
+								
+								throw( new Exception( "Cancelled" ));
+								
+							}else if ( channel_destroyed ){
+								
+								throw( new Exception( "Destroyed" ));
+							}
+							
+							int	chunk = (int)Math.min( rem, max_read_chunk );
+							
+							int	len = read( buffer, pos, chunk );
+								
+							if ( len == -1 ){
+								
+								if ( length == Long.MAX_VALUE ){
+									
+									break;
+									
+								}else{
+									
+									throw( new Exception( "Premature end of stream (complete)" ));
+								}
+							}else if ( len == 0 ){
+								
+								sendEvent( new event( pos ));
+								
+							}else{
+																
+								sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
+								
+								rem -= len;
+								pos	+= len;
+							}
+						}
+					}catch( Throwable e ){
+						
+						sendEvent( new event( e ));
+					}
+				}
+				
+				public void
+				cancel()
+				{
+					request_cancelled = true;
+				}
+				
+				public void
+				setUserAgent(
+					String		agent )
+				{	
+				}
+				
+				protected void
+				sendEvent(
+					event		ev )
+				{					
+					for ( DiskManagerListener l: listeners ){
+						
+						l.eventOccurred( ev );
+					}
+				}
+				
+				public void
+				addListener(
+					DiskManagerListener	listener )
+				{
+					listeners.add( listener );
+				}
+				
+				public void
+				removeListener(
+					DiskManagerListener	listener )
+				{
+					listeners.remove( listener );
+				}
+			
+				protected class
+				event
+					implements DiskManagerEvent
+				{
+					private int					event_type;
+					private Throwable			error;
+					private PooledByteBuffer	buffer;
+					private long				event_offset;
+					private int					event_length;
+					
+					protected
+					event(
+						Throwable		_error )
+					{
+						event_type	= DiskManagerEvent.EVENT_TYPE_FAILED;
+						error		= _error;
+					}
+						
+					protected 
+					event(
+						long				_offset )
+					{
+						event_type		= DiskManagerEvent.EVENT_TYPE_BLOCKED;
+
+						event_offset	= _offset;	
+						
+						channel_position	= _offset;
+					}
+					
+					protected
+					event(
+						PooledByteBuffer	_buffer,
+						long				_offset,
+						int					_length )
+					{
+						event_type		= DiskManagerEvent.EVENT_TYPE_SUCCESS;
+						buffer			= _buffer;
+						event_offset	= _offset;
+						event_length	= _length;
+						
+						channel_position	= _offset + _length - 1;
+					}
+					
+					public int
+					getType()
+					{
+						return( event_type );
+					}
+					
+					public DiskManagerRequest
+					getRequest()
+					{
+						return( request.this );
+					}
+					
+					public long
+					getOffset()
+					{
+						return( event_offset );
+					}
+					
+					public int
+					getLength()
+					{
+						return( event_length );
+					}
+					
+					public PooledByteBuffer
+					getBuffer()
+					{
+						return( buffer );
+					}
+					
+					public Throwable
+					getFailure()
+					{
+						return( error );
+					}
+				}
+			}
+		}
+	}
+
+	public interface
+	StreamFactory
+	{
+		public StreamDetails
+		getStream(
+			Object		requester )
+		
+			throws IOException;
+		
+		public void
+		destroyed(
+			Object		requester );
+		
+		public interface
+		StreamDetails
+		{
+			public InputStream
+			getStream();
+			
+			public boolean
+			hasFailed();
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoURL.java b/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoURL.java
index 20d14fa..9689c0f 100644
--- a/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoURL.java
+++ b/azureus3/src/com/aelitis/azureus/core/download/DiskManagerFileInfoURL.java
@@ -1,870 +1,869 @@
-/*
- * Created on Feb 11, 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.download;
-
-import java.io.*;
-import java.net.HttpURLConnection;
-import java.net.PasswordAuthentication;
-import java.net.URL;
-import java.util.*;
-
-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.security.SEPasswordListener;
-import org.gudy.azureus2.core3.security.SESecurityManager;
-import org.gudy.azureus2.core3.util.AETemporaryFileHandler;
-import org.gudy.azureus2.core3.util.Base32;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.FileUtil;
-import org.gudy.azureus2.core3.util.SHA1Simple;
-import org.gudy.azureus2.core3.util.UrlUtils;
-import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
-import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
-import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
-import org.gudy.azureus2.plugins.disk.DiskManagerListener;
-import org.gudy.azureus2.plugins.disk.DiskManagerRandomReadRequest;
-import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadException;
-import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
-import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
-
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-import com.aelitis.azureus.plugins.extseed.ExternalSeedException;
-
-public class 
-DiskManagerFileInfoURL
-	implements DiskManagerFileInfo, SEPasswordListener
-{
-	private URL					url;
-	private byte[]				hash;
-	
-	private File				file;
-	
-	private Object	lock = new Object();
-	
-	private URL			redirected_url;
-	private int			consec_redirect_fails;
-
-	private volatile boolean		file_cached;
-	
-	public
-	DiskManagerFileInfoURL(
-		URL					_url )
-	{
-		url	= _url;
-		
-		String url_str = url.toExternalForm();
-		
-		String id_key = "azcdid=";
-		String dn_key = "azcddn=";
-		
-		int id_pos = url_str.indexOf( id_key );
-		int dn_pos = url_str.indexOf( dn_key );
-
-		int	min_pos = id_pos;
-		if ( min_pos == -1 ){
-			min_pos = dn_pos;
-		}else{
-			if ( dn_pos != -1 ){
-				min_pos = Math.min( min_pos, dn_pos );
-			}
-		}
-		
-		if ( min_pos > 0 ){
-			
-			try{				
-				url = new URL( url_str.substring( 0, min_pos-1 ) );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}
-		
-		try{
-			hash		= new SHA1Simple().calculateHash( ( "DiskManagerFileInfoURL" +  url.toExternalForm()).getBytes( "UTF-8" ));
-			
-		}catch( Throwable e ){
-			
-			Debug.out(e);
-		}
-		
-		String file_name;
-				
-		if ( dn_pos != -1 ){
-			
-			String dn = url_str.substring( dn_pos + dn_key.length());
-			
-			dn_pos = dn.indexOf( '&' );
-			
-			if ( dn_pos != -1 ){
-				
-				dn = dn.substring( 0, dn_pos );
-			}
-		
-			file_name = UrlUtils.decode( dn );
-			
-		}else{
-			
-			String path = url.getPath();
-			
-			int pos = path.lastIndexOf( "/" );
-			
-			if ( pos != -1 ){
-				
-				path = path.substring( pos+1 );
-			}
-			
-			path = path.trim();
-			
-			if ( url_str.length() > 0 ){
-				
-				file_name = UrlUtils.decode( path );
-				
-			}else{
-				
-				file_name = Base32.encode( hash );
-			}
-		}
-		
-		file_name = FileUtil.convertOSSpecificChars( file_name, false );
-		
-		try{
-			file = new File( AETemporaryFileHandler.createTempDir(), file_name );
-			
-		}catch( Throwable e ){
-		
-			file_name += ".tmp";
-			
-			file = new File( AETemporaryFileHandler.getTempDirectory(), file_name );
-		}
-	}
-	
-	public URL
-	getURL()
-	{
-		return( url );
-	}
-	
-	public void
-	download()
-	{
-		synchronized( lock ){
-			
-			if ( file_cached ){
-				
-				return;
-			}
-			
-			try{
-				channel chan = createChannel();
-				
-				channel.request req = chan.createRequest();
-				
-				req.setAll();
-				
-				final FileOutputStream fos = new FileOutputStream( file );
-				
-				boolean	ok = false;
-				
-				try{
-					req.addListener(
-						new DiskManagerListener()
-						{
-							public void
-							eventOccurred(
-								DiskManagerEvent	event )
-							{
-								if ( event.getType() == DiskManagerEvent.EVENT_TYPE_FAILED ){
-									
-									throw( new RuntimeException( event.getFailure()));
-								}
-								
-								PooledByteBuffer buffer = event.getBuffer();
-								
-								if ( buffer == null ){
-									
-									throw( new RuntimeException( "eh?" ));
-								}
-								
-								try{
-									
-									fos.write( buffer.toByteArray());
-									
-								}catch( IOException e ){
-									
-									throw( new RuntimeException( "Failed to write to " + file, e ));
-									
-								}finally{
-									
-									buffer.returnToPool();
-								}
-							}
-						});
-				
-					req.run();
-					
-					ok = true;
-					
-				}finally{
-					
-					try{
-						fos.close();
-						
-					}catch( Throwable e ){
-						
-						Debug.out( e );
-					}
-					
-					if ( !ok ){
-						
-						file.delete();
-						
-					}else{
-						
-						file_cached = true;
-					}
-				}
-			}catch( Throwable e ){
-				
-				Debug.out( "Failed to cache file from " + url, e );
-			}
-		}
-	}
-	
-	public void 
-	setPriority(
-		boolean b )
-	{
-	}
-	
-	public void 
-	setSkipped(
-		boolean b )
-	{
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public int 
-	getNumericPriority() 
-	{
-		return( 0 );
-	}
-	
-	public int 
-	getNumericPriorty() 
-	{
-		return( 0 );
-	}
-	
-	public void 
-	setNumericPriority(
-		int priority) 
-	{
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public void
-	setDeleted(boolean b)
-	{
-	}	
-	
-	public void
-	setLink(
-		File	link_destination )
-	{	
-		throw( new RuntimeException( "Not supported" ));
-	}
-	
-	public File
-	getLink()
-	{
-		return( null );
-	}
-		 	
-	public int 
-	getAccessMode()
-	{
-		return( READ );
-	}
-	
-	public long 
-	getDownloaded()
-	{
-		return( getLength());
-	}
-	
-	public long
-	getLength()
-	{
-		if ( file_cached ){
-			
-			long len = file.length();
-			
-			if ( len > 0 ){
-				
-				return( len );
-			}
-		}
-		
-		return( -1 );
-	}
-	
-	public File 
-	getFile()
-	{
-		return( file );
-	}
-		
-	public File
-	getFile(
-		boolean	follow_link )
-	{
-		return( file );
-	}
-	
-	public int
-	getIndex()
-	{
-		return( 0 );
-	}
-	
-	public int 
-	getFirstPieceNumber()
-	{
-		return( 0 );
-	}
-	
-	public long
-	getPieceSize()
-	{
-		return( 32*1024 );
-	}
-	
-	public int 
-	getNumPieces()
-	{
-		return( -1 );
-	}
-		
-	public boolean 
-	isPriority()
-	{
-		return( false );
-	}
-	
-	public boolean 
-	isSkipped()
-	{
-		return( false );
-	}
-	
-	public boolean
-	isDeleted()
-	{
-		return( false );
-	}
-	
-	public byte[] 
-	getDownloadHash() 
-	
-		throws DownloadException 
-	{
-		return( hash );
-	}
-	
-	public Download 
-	getDownload()
-	
-         throws DownloadException
-    {
-		throw( new DownloadException( "Not supported" ));
-    }
-	
-	public channel
-	createChannel()
-	
-		throws DownloadException
-	{
-		return( new channel());
-	}
-	
-	public DiskManagerRandomReadRequest
-	createRandomReadRequest(
-		long						file_offset,
-		long						length,
-		boolean						reverse_order,
-		DiskManagerListener			listener )
-	
-		throws DownloadException
-	{
-		throw( new DownloadException( "Not supported" ));
-	}
-	
-	public PasswordAuthentication
-	getAuthentication(
-		String		realm,
-		URL			tracker )
-	{
-		return( null );
-	}
-	
-	public void
-	setAuthenticationOutcome(
-		String		realm,
-		URL			tracker,
-		boolean		success )
-	{
-	}
-	
-	public void
-	clearPasswords()
-	{
-	}
-
-	protected class
-	channel
-		implements DiskManagerChannel
-	{
-		private volatile boolean	channel_destroyed;
-		private volatile long		channel_position;
-		
-		public request
-		createRequest()
-		{
-			return( new request());
-		}
-		
-		public DiskManagerFileInfo
-		getFile()
-		{
-			return( DiskManagerFileInfoURL.this );
-		}
-		
-		public long 
-		getPosition() 
-		{
-			return( channel_position );
-		}
-		
-		public boolean 
-		isDestroyed() 
-		{
-			return( channel_destroyed );
-		}
-		
-		public void
-		destroy()
-		{
-			channel_destroyed	= true;
-		}
-		
-		protected class
-		request
-			implements DiskManagerRequest
-		{
-			private long		offset;
-			private long		length;
-			private boolean		do_all_file;
-			
-			private long		position;
-			
-			private int			max_read_chunk = 128*1024;;
-			
-			private volatile boolean	request_cancelled;
-			
-			private CopyOnWriteList<DiskManagerListener>		listeners = new CopyOnWriteList<DiskManagerListener>();
-			
-			public void
-			setType(
-				int			type )
-			{
-				if ( type != DiskManagerRequest.REQUEST_READ ){
-					
-					throw( new RuntimeException( "Not supported" ));
-				}
-			}
-			
-			public void
-			setAll()
-			{
-				do_all_file = true;
-				offset		= 0;
-				setLength( -1 );
-			}
-			
-			public void
-			setOffset(
-				long		_offset )
-			{
-				offset		= _offset;
-			}
-			
-			public void
-			setLength(
-				long		_length )
-			{
-					// length can be -1 here meaning 'to the end'
-				
-				length		= _length==-1?Long.MAX_VALUE:_length;
-			}
-				
-			public void
-			setMaximumReadChunkSize(
-				int 	size )
-			{
-				if ( size > 16*1024 ){
-				
-					max_read_chunk = size;
-				}
-			}
-			
-			public long
-			getAvailableBytes()
-			{
-				return( getRemaining());
-			}
-						
-			public long
-			getRemaining()
-			{
-				return( length==Long.MAX_VALUE?length:(offset + length - position ));
-			}
-			
-			public void
-			run()
-			{
-				try{				
-					byte[] buffer = new byte[max_read_chunk];
-					
-					long	rem		= length;
-					long	pos 	= offset;
-						
-					InputStream	is = null;
-					
-					try{
-						SESecurityManager.setThreadPasswordHandler( DiskManagerFileInfoURL.this );
-						
-						// System.out.println( "Connecting to " + url + ": " + Thread.currentThread().getId());
-
-							HttpURLConnection	connection;
-							int					response;
-							
-							Set<String>	redirect_urls = new HashSet<String>();
-							
-redirect_loop:
-							while( true ){
-								
-								URL	target = redirected_url==null?url:redirected_url;
-								
-								for ( int ssl_loop=0; ssl_loop<2; ssl_loop++ ){
-									
-									try{
-										connection = (HttpURLConnection)target.openConnection();
-										
-										if ( connection instanceof HttpsURLConnection ){
-											
-											HttpsURLConnection ssl_con = (HttpsURLConnection)connection;
-											
-												// allow for certs that contain IP addresses rather than dns names
-					  	
-										ssl_con.setHostnameVerifier(
-											new HostnameVerifier()
-											{
-												public boolean
-												verify(
-													String		host,
-													SSLSession	session )
-												{
-													return( true );
-												}
-											});
-									}
-									
-									connection.setRequestProperty( "Connection", "Keep-Alive" );
-									
-									if ( !do_all_file ){
-									
-										connection.setRequestProperty( "Range", "bytes=" + offset + "-" + (offset+length-1));
-									}
-									
-									connection.setConnectTimeout( 20*1000 );
-																
-									connection.connect();
-									
-									connection.setReadTimeout( 10*1000 );
-																					
-									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 redirect_loop;
-										
-									}else if ( 	response == HttpURLConnection.HTTP_MOVED_TEMP ||
-												response == HttpURLConnection.HTTP_MOVED_PERM ){
-										
-											// auto redirect doesn't work from http to https or vice-versa
-										
-										String	move_to = connection.getHeaderField( "location" );
-										
-										if ( move_to != null ){
-											
-											if ( redirect_urls.contains( move_to ) || redirect_urls.size() > 32 ){
-												
-												throw( new ExternalSeedException( "redirect loop" )); 
-											}
-											
-											redirect_urls.add( move_to );
-											
-											redirected_url = new URL( move_to );
-											
-											continue redirect_loop;
-										}
-									}
-									
-									if ( redirected_url == null ){
-										
-										break redirect_loop;
-									}
-									
-										// try again with original URL
-									
-									consec_redirect_fails++;
-									
-									redirected_url = null;
-								
-								}catch( SSLException e ){
-									
-									if ( ssl_loop == 0 ){
-										
-										if ( SESecurityManager.installServerCertificates( target ) != null ){
-											
-												// certificate has been installed
-											
-											continue;	// retry with new certificate
-										}
-									}
-				
-									throw( e );
-								}
-								
-									// don't need another SSL loop
-								
-								break;
-							}
-						}
-						
-						URL final_url = connection.getURL();
-						
-						if ( consec_redirect_fails < 10 && !url.toExternalForm().equals( final_url.toExternalForm())){
-							
-							redirected_url = final_url;
-						}
-			            
-						is = connection.getInputStream();
-						
-						while( rem > 0 ){
-
-							if ( request_cancelled ){
-								
-								throw( new Exception( "Cancelled" ));
-								
-							}else if ( channel_destroyed ){
-								
-								throw( new Exception( "Destroyed" ));
-							}
-							
-							int	len = is.read( buffer );
-							
-							if ( len == -1 ){
-								
-								if ( length == Long.MAX_VALUE ){
-									
-									break;
-									
-								}else{
-									
-									throw( new Exception( "Premature end of stream (complete)" ));
-								}
-							}else if ( len == 0 ){
-								
-								sendEvent( new event( pos ));
-								
-							}else{
-																
-								sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
-								
-								rem -= len;
-								pos	+= len;
-							}
-						}
-					}finally{
-						
-						SESecurityManager.unsetThreadPasswordHandler();
-
-						// System.out.println( "Done to " + url + ": " + Thread.currentThread().getId() + ", outcome=" + outcome );
-
-						if ( is != null ){
-							
-							try{
-								is.close();
-								
-							}catch( Throwable e ){
-								
-							}
-						}
-					}							
-				}catch( Throwable e ){
-					
-					sendEvent( new event( e ));
-				}
-			}
-			
-			public void
-			cancel()
-			{
-				request_cancelled = true;
-			}
-			
-			public void
-			setUserAgent(
-				String		agent )
-			{	
-			}
-			
-			protected void
-			sendEvent(
-				event		ev )
-			{					
-				for ( DiskManagerListener l: listeners ){
-					
-					l.eventOccurred( ev );
-				}
-			}
-			
-			public void
-			addListener(
-				DiskManagerListener	listener )
-			{
-				listeners.add( listener );
-			}
-			
-			public void
-			removeListener(
-				DiskManagerListener	listener )
-			{
-				listeners.remove( listener );
-			}
-		
-			protected class
-			event
-				implements DiskManagerEvent
-			{
-				private int					event_type;
-				private Throwable			error;
-				private PooledByteBuffer	buffer;
-				private long				event_offset;
-				private int					event_length;
-				
-				protected
-				event(
-					Throwable		_error )
-				{
-					event_type	= DiskManagerEvent.EVENT_TYPE_FAILED;
-					error		= _error;
-				}
-					
-				protected 
-				event(
-					long				_offset )
-				{
-					event_type		= DiskManagerEvent.EVENT_TYPE_BLOCKED;
-
-					event_offset	= _offset;	
-					
-					channel_position	= _offset;
-				}
-				
-				protected
-				event(
-					PooledByteBuffer	_buffer,
-					long				_offset,
-					int					_length )
-				{
-					event_type		= DiskManagerEvent.EVENT_TYPE_SUCCESS;
-					buffer			= _buffer;
-					event_offset	= _offset;
-					event_length	= _length;
-					
-					channel_position	= _offset + _length - 1;
-				}
-				
-				public int
-				getType()
-				{
-					return( event_type );
-				}
-				
-				public DiskManagerRequest
-				getRequest()
-				{
-					return( request.this );
-				}
-				
-				public long
-				getOffset()
-				{
-					return( event_offset );
-				}
-				
-				public int
-				getLength()
-				{
-					return( event_length );
-				}
-				
-				public PooledByteBuffer
-				getBuffer()
-				{
-					return( buffer );
-				}
-				
-				public Throwable
-				getFailure()
-				{
-					return( error );
-				}
-			}
-		}
-	}
-}
+/*
+ * Created on Feb 11, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.download;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.PasswordAuthentication;
+import java.net.URL;
+import java.util.*;
+
+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.security.SEPasswordListener;
+import org.gudy.azureus2.core3.security.SESecurityManager;
+import org.gudy.azureus2.core3.util.AETemporaryFileHandler;
+import org.gudy.azureus2.core3.util.Base32;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.core3.util.SHA1Simple;
+import org.gudy.azureus2.core3.util.UrlUtils;
+import org.gudy.azureus2.plugins.disk.DiskManagerChannel;
+import org.gudy.azureus2.plugins.disk.DiskManagerEvent;
+import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.plugins.disk.DiskManagerListener;
+import org.gudy.azureus2.plugins.disk.DiskManagerRandomReadRequest;
+import org.gudy.azureus2.plugins.disk.DiskManagerRequest;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadException;
+import org.gudy.azureus2.plugins.utils.PooledByteBuffer;
+import org.gudy.azureus2.pluginsimpl.local.utils.PooledByteBufferImpl;
+
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.plugins.extseed.ExternalSeedException;
+
+public class 
+DiskManagerFileInfoURL
+	implements DiskManagerFileInfo, SEPasswordListener
+{
+	private URL					url;
+	private byte[]				hash;
+	
+	private File				file;
+	
+	private Object	lock = new Object();
+	
+	private URL			redirected_url;
+	private int			consec_redirect_fails;
+
+	private volatile boolean		file_cached;
+	
+	public
+	DiskManagerFileInfoURL(
+		URL					_url )
+	{
+		url	= _url;
+		
+		String url_str = url.toExternalForm();
+		
+		String id_key = "azcdid=";
+		String dn_key = "azcddn=";
+		
+		int id_pos = url_str.indexOf( id_key );
+		int dn_pos = url_str.indexOf( dn_key );
+
+		int	min_pos = id_pos;
+		if ( min_pos == -1 ){
+			min_pos = dn_pos;
+		}else{
+			if ( dn_pos != -1 ){
+				min_pos = Math.min( min_pos, dn_pos );
+			}
+		}
+		
+		if ( min_pos > 0 ){
+			
+			try{				
+				url = new URL( url_str.substring( 0, min_pos-1 ) );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+		
+		try{
+			hash		= new SHA1Simple().calculateHash( ( "DiskManagerFileInfoURL" +  url.toExternalForm()).getBytes( "UTF-8" ));
+			
+		}catch( Throwable e ){
+			
+			Debug.out(e);
+		}
+		
+		String file_name;
+				
+		if ( dn_pos != -1 ){
+			
+			String dn = url_str.substring( dn_pos + dn_key.length());
+			
+			dn_pos = dn.indexOf( '&' );
+			
+			if ( dn_pos != -1 ){
+				
+				dn = dn.substring( 0, dn_pos );
+			}
+		
+			file_name = UrlUtils.decode( dn );
+			
+		}else{
+			
+			String path = url.getPath();
+			
+			int pos = path.lastIndexOf( "/" );
+			
+			if ( pos != -1 ){
+				
+				path = path.substring( pos+1 );
+			}
+			
+			path = path.trim();
+			
+			if ( url_str.length() > 0 ){
+				
+				file_name = UrlUtils.decode( path );
+				
+			}else{
+				
+				file_name = Base32.encode( hash );
+			}
+		}
+		
+		file_name = FileUtil.convertOSSpecificChars( file_name, false );
+		
+		try{
+			file = new File( AETemporaryFileHandler.createTempDir(), file_name );
+			
+		}catch( Throwable e ){
+		
+			file_name += ".tmp";
+			
+			file = new File( AETemporaryFileHandler.getTempDirectory(), file_name );
+		}
+	}
+	
+	public URL
+	getURL()
+	{
+		return( url );
+	}
+	
+	public void
+	download()
+	{
+		synchronized( lock ){
+			
+			if ( file_cached ){
+				
+				return;
+			}
+			
+			try{
+				channel chan = createChannel();
+				
+				channel.request req = chan.createRequest();
+				
+				req.setAll();
+				
+				final FileOutputStream fos = new FileOutputStream( file );
+				
+				boolean	ok = false;
+				
+				try{
+					req.addListener(
+						new DiskManagerListener()
+						{
+							public void
+							eventOccurred(
+								DiskManagerEvent	event )
+							{
+								if ( event.getType() == DiskManagerEvent.EVENT_TYPE_FAILED ){
+									
+									throw( new RuntimeException( event.getFailure()));
+								}
+								
+								PooledByteBuffer buffer = event.getBuffer();
+								
+								if ( buffer == null ){
+									
+									throw( new RuntimeException( "eh?" ));
+								}
+								
+								try{
+									
+									fos.write( buffer.toByteArray());
+									
+								}catch( IOException e ){
+									
+									throw( new RuntimeException( "Failed to write to " + file, e ));
+									
+								}finally{
+									
+									buffer.returnToPool();
+								}
+							}
+						});
+				
+					req.run();
+					
+					ok = true;
+					
+				}finally{
+					
+					try{
+						fos.close();
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+					
+					if ( !ok ){
+						
+						file.delete();
+						
+					}else{
+						
+						file_cached = true;
+					}
+				}
+			}catch( Throwable e ){
+				
+				Debug.out( "Failed to cache file from " + url, e );
+			}
+		}
+	}
+	
+	public void 
+	setPriority(
+		boolean b )
+	{
+	}
+	
+	public void 
+	setSkipped(
+		boolean b )
+	{
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public int 
+	getNumericPriority() 
+	{
+		return( 0 );
+	}
+	
+	public int 
+	getNumericPriorty() 
+	{
+		return( 0 );
+	}
+	
+	public void 
+	setNumericPriority(
+		int priority) 
+	{
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public void
+	setDeleted(boolean b)
+	{
+	}	
+	
+	public void
+	setLink(
+		File	link_destination )
+	{	
+		throw( new RuntimeException( "Not supported" ));
+	}
+	
+	public File
+	getLink()
+	{
+		return( null );
+	}
+		 	
+	public int 
+	getAccessMode()
+	{
+		return( READ );
+	}
+	
+	public long 
+	getDownloaded()
+	{
+		return( getLength());
+	}
+	
+	public long
+	getLength()
+	{
+		if ( file_cached ){
+			
+			long len = file.length();
+			
+			if ( len > 0 ){
+				
+				return( len );
+			}
+		}
+		
+		return( -1 );
+	}
+	
+	public File 
+	getFile()
+	{
+		return( file );
+	}
+		
+	public File
+	getFile(
+		boolean	follow_link )
+	{
+		return( file );
+	}
+	
+	public int
+	getIndex()
+	{
+		return( 0 );
+	}
+	
+	public int 
+	getFirstPieceNumber()
+	{
+		return( 0 );
+	}
+	
+	public long
+	getPieceSize()
+	{
+		return( 32*1024 );
+	}
+	
+	public int 
+	getNumPieces()
+	{
+		return( -1 );
+	}
+		
+	public boolean 
+	isPriority()
+	{
+		return( false );
+	}
+	
+	public boolean 
+	isSkipped()
+	{
+		return( false );
+	}
+	
+	public boolean
+	isDeleted()
+	{
+		return( false );
+	}
+	
+	public byte[] 
+	getDownloadHash() 
+	
+		throws DownloadException 
+	{
+		return( hash );
+	}
+	
+	public Download 
+	getDownload()
+	
+         throws DownloadException
+    {
+		throw( new DownloadException( "Not supported" ));
+    }
+	
+	public channel
+	createChannel()
+	
+		throws DownloadException
+	{
+		return( new channel());
+	}
+	
+	public DiskManagerRandomReadRequest
+	createRandomReadRequest(
+		long						file_offset,
+		long						length,
+		boolean						reverse_order,
+		DiskManagerListener			listener )
+	
+		throws DownloadException
+	{
+		throw( new DownloadException( "Not supported" ));
+	}
+	
+	public PasswordAuthentication
+	getAuthentication(
+		String		realm,
+		URL			tracker )
+	{
+		return( null );
+	}
+	
+	public void
+	setAuthenticationOutcome(
+		String		realm,
+		URL			tracker,
+		boolean		success )
+	{
+	}
+	
+	public void
+	clearPasswords()
+	{
+	}
+
+	protected class
+	channel
+		implements DiskManagerChannel
+	{
+		private volatile boolean	channel_destroyed;
+		private volatile long		channel_position;
+		
+		public request
+		createRequest()
+		{
+			return( new request());
+		}
+		
+		public DiskManagerFileInfo
+		getFile()
+		{
+			return( DiskManagerFileInfoURL.this );
+		}
+		
+		public long 
+		getPosition() 
+		{
+			return( channel_position );
+		}
+		
+		public boolean 
+		isDestroyed() 
+		{
+			return( channel_destroyed );
+		}
+		
+		public void
+		destroy()
+		{
+			channel_destroyed	= true;
+		}
+		
+		protected class
+		request
+			implements DiskManagerRequest
+		{
+			private long		offset;
+			private long		length;
+			private boolean		do_all_file;
+			
+			private long		position;
+			
+			private int			max_read_chunk = 128*1024;;
+			
+			private volatile boolean	request_cancelled;
+			
+			private CopyOnWriteList<DiskManagerListener>		listeners = new CopyOnWriteList<DiskManagerListener>();
+			
+			public void
+			setType(
+				int			type )
+			{
+				if ( type != DiskManagerRequest.REQUEST_READ ){
+					
+					throw( new RuntimeException( "Not supported" ));
+				}
+			}
+			
+			public void
+			setAll()
+			{
+				do_all_file = true;
+				offset		= 0;
+				setLength( -1 );
+			}
+			
+			public void
+			setOffset(
+				long		_offset )
+			{
+				offset		= _offset;
+			}
+			
+			public void
+			setLength(
+				long		_length )
+			{
+					// length can be -1 here meaning 'to the end'
+				
+				length		= _length==-1?Long.MAX_VALUE:_length;
+			}
+				
+			public void
+			setMaximumReadChunkSize(
+				int 	size )
+			{
+				if ( size > 16*1024 ){
+				
+					max_read_chunk = size;
+				}
+			}
+			
+			public long
+			getAvailableBytes()
+			{
+				return( getRemaining());
+			}
+						
+			public long
+			getRemaining()
+			{
+				return( length==Long.MAX_VALUE?length:(offset + length - position ));
+			}
+			
+			public void
+			run()
+			{
+				try{				
+					byte[] buffer = new byte[max_read_chunk];
+					
+					long	rem		= length;
+					long	pos 	= offset;
+						
+					InputStream	is = null;
+					
+					try{
+						SESecurityManager.setThreadPasswordHandler( DiskManagerFileInfoURL.this );
+						
+						// System.out.println( "Connecting to " + url + ": " + Thread.currentThread().getId());
+
+							HttpURLConnection	connection;
+							int					response;
+							
+							Set<String>	redirect_urls = new HashSet<String>();
+							
+redirect_loop:
+							while( true ){
+								
+								URL	target = redirected_url==null?url:redirected_url;
+								
+								for ( int ssl_loop=0; ssl_loop<2; ssl_loop++ ){
+									
+									try{
+										connection = (HttpURLConnection)target.openConnection();
+										
+										if ( connection instanceof HttpsURLConnection ){
+											
+											HttpsURLConnection ssl_con = (HttpsURLConnection)connection;
+											
+												// allow for certs that contain IP addresses rather than dns names
+					  	
+										ssl_con.setHostnameVerifier(
+											new HostnameVerifier()
+											{
+												public boolean
+												verify(
+													String		host,
+													SSLSession	session )
+												{
+													return( true );
+												}
+											});
+									}
+									
+									connection.setRequestProperty( "Connection", "Keep-Alive" );
+									
+									if ( !do_all_file ){
+									
+										connection.setRequestProperty( "Range", "bytes=" + offset + "-" + (offset+length-1));
+									}
+									
+									connection.setConnectTimeout( 20*1000 );
+																
+									connection.connect();
+									
+									connection.setReadTimeout( 10*1000 );
+																					
+									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 redirect_loop;
+										
+									}else if ( 	response == HttpURLConnection.HTTP_MOVED_TEMP ||
+												response == HttpURLConnection.HTTP_MOVED_PERM ){
+										
+											// auto redirect doesn't work from http to https or vice-versa
+										
+										String	move_to = connection.getHeaderField( "location" );
+										
+										if ( move_to != null ){
+											
+											if ( redirect_urls.contains( move_to ) || redirect_urls.size() > 32 ){
+												
+												throw( new ExternalSeedException( "redirect loop" )); 
+											}
+											
+											redirect_urls.add( move_to );
+											
+											redirected_url = new URL( move_to );
+											
+											continue redirect_loop;
+										}
+									}
+									
+									if ( redirected_url == null ){
+										
+										break redirect_loop;
+									}
+									
+										// try again with original URL
+									
+									consec_redirect_fails++;
+									
+									redirected_url = null;
+								
+								}catch( SSLException e ){
+									
+									if ( ssl_loop == 0 ){
+										
+										if ( SESecurityManager.installServerCertificates( target ) != null ){
+											
+												// certificate has been installed
+											
+											continue;	// retry with new certificate
+										}
+									}
+				
+									throw( e );
+								}
+								
+									// don't need another SSL loop
+								
+								break;
+							}
+						}
+						
+						URL final_url = connection.getURL();
+						
+						if ( consec_redirect_fails < 10 && !url.toExternalForm().equals( final_url.toExternalForm())){
+							
+							redirected_url = final_url;
+						}
+			            
+						is = connection.getInputStream();
+						
+						while( rem > 0 ){
+
+							if ( request_cancelled ){
+								
+								throw( new Exception( "Cancelled" ));
+								
+							}else if ( channel_destroyed ){
+								
+								throw( new Exception( "Destroyed" ));
+							}
+							
+							int	len = is.read( buffer );
+							
+							if ( len == -1 ){
+								
+								if ( length == Long.MAX_VALUE ){
+									
+									break;
+									
+								}else{
+									
+									throw( new Exception( "Premature end of stream (complete)" ));
+								}
+							}else if ( len == 0 ){
+								
+								sendEvent( new event( pos ));
+								
+							}else{
+																
+								sendEvent( new event( new PooledByteBufferImpl( buffer, 0, len ), pos, len ));
+								
+								rem -= len;
+								pos	+= len;
+							}
+						}
+					}finally{
+						
+						SESecurityManager.unsetThreadPasswordHandler();
+
+						// System.out.println( "Done to " + url + ": " + Thread.currentThread().getId() + ", outcome=" + outcome );
+
+						if ( is != null ){
+							
+							try{
+								is.close();
+								
+							}catch( Throwable e ){
+								
+							}
+						}
+					}							
+				}catch( Throwable e ){
+					
+					sendEvent( new event( e ));
+				}
+			}
+			
+			public void
+			cancel()
+			{
+				request_cancelled = true;
+			}
+			
+			public void
+			setUserAgent(
+				String		agent )
+			{	
+			}
+			
+			protected void
+			sendEvent(
+				event		ev )
+			{					
+				for ( DiskManagerListener l: listeners ){
+					
+					l.eventOccurred( ev );
+				}
+			}
+			
+			public void
+			addListener(
+				DiskManagerListener	listener )
+			{
+				listeners.add( listener );
+			}
+			
+			public void
+			removeListener(
+				DiskManagerListener	listener )
+			{
+				listeners.remove( listener );
+			}
+		
+			protected class
+			event
+				implements DiskManagerEvent
+			{
+				private int					event_type;
+				private Throwable			error;
+				private PooledByteBuffer	buffer;
+				private long				event_offset;
+				private int					event_length;
+				
+				protected
+				event(
+					Throwable		_error )
+				{
+					event_type	= DiskManagerEvent.EVENT_TYPE_FAILED;
+					error		= _error;
+				}
+					
+				protected 
+				event(
+					long				_offset )
+				{
+					event_type		= DiskManagerEvent.EVENT_TYPE_BLOCKED;
+
+					event_offset	= _offset;	
+					
+					channel_position	= _offset;
+				}
+				
+				protected
+				event(
+					PooledByteBuffer	_buffer,
+					long				_offset,
+					int					_length )
+				{
+					event_type		= DiskManagerEvent.EVENT_TYPE_SUCCESS;
+					buffer			= _buffer;
+					event_offset	= _offset;
+					event_length	= _length;
+					
+					channel_position	= _offset + _length - 1;
+				}
+				
+				public int
+				getType()
+				{
+					return( event_type );
+				}
+				
+				public DiskManagerRequest
+				getRequest()
+				{
+					return( request.this );
+				}
+				
+				public long
+				getOffset()
+				{
+					return( event_offset );
+				}
+				
+				public int
+				getLength()
+				{
+					return( event_length );
+				}
+				
+				public PooledByteBuffer
+				getBuffer()
+				{
+					return( buffer );
+				}
+				
+				public Throwable
+				getFailure()
+				{
+					return( error );
+				}
+			}
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/download/DownloadManagerEnhancer.java b/azureus3/src/com/aelitis/azureus/core/download/DownloadManagerEnhancer.java
index 4282bbf..0161abf 100644
--- a/azureus3/src/com/aelitis/azureus/core/download/DownloadManagerEnhancer.java
+++ b/azureus3/src/com/aelitis/azureus/core/download/DownloadManagerEnhancer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/core/download/EnhancedDownloadManager.java b/azureus3/src/com/aelitis/azureus/core/download/EnhancedDownloadManager.java
index cef3552..9060320 100644
--- a/azureus3/src/com/aelitis/azureus/core/download/EnhancedDownloadManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/download/EnhancedDownloadManager.java
@@ -1,7 +1,7 @@
 /*
  * Created on 1 Nov 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/core/download/EnhancedDownloadManagerFile.java b/azureus3/src/com/aelitis/azureus/core/download/EnhancedDownloadManagerFile.java
index 22ac6ae..2d9adf2 100644
--- a/azureus3/src/com/aelitis/azureus/core/download/EnhancedDownloadManagerFile.java
+++ b/azureus3/src/com/aelitis/azureus/core/download/EnhancedDownloadManagerFile.java
@@ -1,7 +1,7 @@
 /*
  * Created on Sep 9, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/core/download/StreamManager.java b/azureus3/src/com/aelitis/azureus/core/download/StreamManager.java
index c8662ff..dec0978 100644
--- a/azureus3/src/com/aelitis/azureus/core/download/StreamManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/download/StreamManager.java
@@ -2,20 +2,19 @@
  * Created on Jun 21, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus3/src/com/aelitis/azureus/core/download/StreamManagerDownload.java b/azureus3/src/com/aelitis/azureus/core/download/StreamManagerDownload.java
index 552b236..1a91831 100644
--- a/azureus3/src/com/aelitis/azureus/core/download/StreamManagerDownload.java
+++ b/azureus3/src/com/aelitis/azureus/core/download/StreamManagerDownload.java
@@ -2,20 +2,19 @@
  * Created on Jun 21, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus3/src/com/aelitis/azureus/core/download/StreamManagerDownloadListener.java b/azureus3/src/com/aelitis/azureus/core/download/StreamManagerDownloadListener.java
index e08d4d4..4f41f5d 100644
--- a/azureus3/src/com/aelitis/azureus/core/download/StreamManagerDownloadListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/download/StreamManagerDownloadListener.java
@@ -2,20 +2,19 @@
  * Created on Jun 21, 2010
  * Created by Paul Gardner
  * 
- * Copyright 2010 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/ClientMessageContext.java b/azureus3/src/com/aelitis/azureus/core/messenger/ClientMessageContext.java
index a792585..0771325 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/ClientMessageContext.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/ClientMessageContext.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/ClientMessageContextImpl.java b/azureus3/src/com/aelitis/azureus/core/messenger/ClientMessageContextImpl.java
index d34a842..363466e 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/ClientMessageContextImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/ClientMessageContextImpl.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessage.java b/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessage.java
index 243ae6e..65b046b 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessage.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessage.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessenger.java b/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessenger.java
index dfd51e0..1f13341 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessenger.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessenger.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessengerException.java b/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessengerException.java
index 009d400..4a1d114 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessengerException.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessengerException.java
@@ -1,42 +1,41 @@
-/*
- * Created on May 7, 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.core.messenger;
-
-public class 
-PlatformMessengerException
-	extends Exception
-{
-	public
-	PlatformMessengerException(
-		String		str )
-	{
-		super( str );
-	}
-	
-	public 
-	PlatformMessengerException(
-		String		str,
-		Throwable 	cause )
-	{
-		super( str, cause );
-	}
-}
+/*
+ * Created on May 7, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.messenger;
+
+public class 
+PlatformMessengerException
+	extends Exception
+{
+	public
+	PlatformMessengerException(
+		String		str )
+	{
+		super( str );
+	}
+	
+	public 
+	PlatformMessengerException(
+		String		str,
+		Throwable 	cause )
+	{
+		super( str, cause );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessengerListener.java b/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessengerListener.java
index de75c26..dd880af 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessengerListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/PlatformMessengerListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/browser/BrowserMessage.java b/azureus3/src/com/aelitis/azureus/core/messenger/browser/BrowserMessage.java
index ff8127f..8d5dbf6 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/browser/BrowserMessage.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/browser/BrowserMessage.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 29, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/browser/BrowserMessageDispatcher.java b/azureus3/src/com/aelitis/azureus/core/messenger/browser/BrowserMessageDispatcher.java
index 5937268..0be16a1 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/browser/BrowserMessageDispatcher.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/browser/BrowserMessageDispatcher.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jun 2, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/AbstractBrowserMessageListener.java b/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/AbstractBrowserMessageListener.java
index a31502f..e74e880 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/AbstractBrowserMessageListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/AbstractBrowserMessageListener.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 29, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/BrowserMessageListener.java b/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/BrowserMessageListener.java
index 0b3cc55..359ce4f 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/BrowserMessageListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/BrowserMessageListener.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 29, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/MessageCompletionListener.java b/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/MessageCompletionListener.java
index 36f9a7c..0bd5029 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/MessageCompletionListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/browser/listeners/MessageCompletionListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.browser.listeners;
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformConfigMessenger.java b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformConfigMessenger.java
index 28bd414..0993a8e 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformConfigMessenger.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformConfigMessenger.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
@@ -48,16 +45,8 @@ public class PlatformConfigMessenger
 	
 	private static final String OP_LOG_PLUGIN = "log-plugin";
 
-	private static boolean allowSendDeviceList = false;
-
-	private static int iRPCVersion = 0;
-
-	private static String playAfterURL = null;
-
 	private static boolean sendStats = true;
 
-	private static boolean doUrlQOS = false;
-	
 	private static boolean platformLoginComplete = false;
 
 	protected static List platformLoginCompleteListeners = Collections.EMPTY_LIST;
@@ -118,20 +107,6 @@ public class PlatformConfigMessenger
 				
 
 				try {
-					List listDomains = (List) MapUtils.getMapObject(reply, "tracker-domains",
-							null, List.class);
-					if (listDomains != null) {
-						for (int i = 0; i < listDomains.size(); i++) {
-							String s = (String) listDomains.get(i);
-							PlatformTorrentUtils.addPlatformHost(s);
-							PlatformMessenger.debug("v3.login: got tracker domain of " + s);
-						}
-					}
-				} catch (Exception e) {
-					Debug.out(e);
-				}
-				
-				try {
 					List list = MapUtils.getMapList(reply, "external-links", Collections.EMPTY_LIST);
 					externalLinks.addAll(list);
 				} catch (Exception e) {
@@ -140,20 +115,10 @@ public class PlatformConfigMessenger
 				
 				try {
 					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) {
 				}
 				
 				
-				try {
-  				iRPCVersion = MapUtils.getMapInt(reply, "rpc-version", 0);
-  				playAfterURL = (String) MapUtils.getMapString(reply,
-  						"play-after-url", null);
-				} catch (Exception e) {
-					Debug.out(e);
-				}
-				
 				platformLoginComplete = true;
 				Object[] listeners = platformLoginCompleteListeners.toArray();
 				platformLoginCompleteListeners = Collections.EMPTY_LIST;
@@ -243,29 +208,10 @@ public class PlatformConfigMessenger
 	}
 
 	
-	/**
-	 * @return the iRPCVersion
-	 */
-	public static int getRPCVersion() {
-		return iRPCVersion;
-	}
-
-	public static String getPlayAfterURL() {
-		return playAfterURL;
-	}
-
 	public static boolean allowSendStats() {
 		return sendStats;
 	}
 
-	/**
-	 * @return
-	 *
-	 * @since 4.0.0.1
-	 */
-	public static boolean doUrlQOS() {
-		return doUrlQOS;
-	}
 	
 	public static void addPlatformLoginCompleteListener(
 			PlatformLoginCompleteListener l) {
@@ -290,11 +236,6 @@ public class PlatformConfigMessenger
 		public void platformLoginComplete();
 	}
 
-
-	public static boolean allowSendDeviceList() {
-		return allowSendDeviceList;
-	}
-	
 	public static boolean areLinksExternal(String url) {
 		for (String regex : externalLinks) {
 			try {
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformDevicesMessenger.java b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformDevicesMessenger.java
index 2a64a80..be11bd9 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformDevicesMessenger.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformDevicesMessenger.java
@@ -1,10 +1,12 @@
 /**
  * Created on Mar 12, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -140,60 +142,4 @@ public class PlatformDevicesMessenger
 		return deviceName.toString();
 		*/
 	}
-
-	public static void setupDeviceSender() {
-		if ( !COConfigurationManager.getStringParameter("ui").equals("az2")){
-
-			final DeviceManager deviceManager = DeviceManagerFactory.getSingleton();
-			Device[] devices = deviceManager.getDevices();
-			if (devices == null || devices.length == 0) {
-	  		deviceManager.addListener(new DeviceManagerListener() {
-	  		
-	  			public void deviceRemoved(Device device) {
-	  			}
-	  		
-	  			public void deviceChanged(Device device) {
-	  			}
-	  		
-	  			public void deviceAttentionRequest(Device device) {
-	  			}
-	  			
-	  			public void deviceAdded(Device device) {
-	  			}
-	  
-	  			public void deviceManagerLoaded() {
-	  				deviceManager.removeListener(this);
-	  				Device[] devices = deviceManager.getDevices();
-	  				if (devices != null && devices.length > 0) {
-	  					sendDeviceList(devices);
-	  				}
-	  			}
-	  		});
-			} else {
-				sendDeviceList(devices);
-			}
-		}
-	}
-
-	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) {
-				listRenderers.add(dev.getClassification());
-			}
-		}
-
-		if (listRenderers.size() == 0) {
-			return;
-		}
-		PlatformMessage message = new PlatformMessage("AZMSG", LISTENER_ID,
-				OP_REPORT_DEVICES, new Object[] {
-					"renderers",
-					listRenderers
-				}, 500);
-		PlatformMessenger.queueMessage(message, null);
-	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformMessengerConfig.java b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformMessengerConfig.java
index e06da4f..2b832ef 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformMessengerConfig.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformMessengerConfig.java
@@ -1,140 +1,139 @@
-/*
- * Created on Nov 26, 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.core.messenger.config;
-
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.AESemaphore;
-
-import com.aelitis.azureus.core.messenger.PlatformMessage;
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.PlatformMessengerException;
-import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
-
-public class 
-PlatformMessengerConfig 
-{
-	private String 		listener_id;
-	private boolean		send_azid;
-	
-	protected
-	PlatformMessengerConfig(
-		String		_listener_id,
-		boolean		_send_azid )
-	{
-		listener_id		= _listener_id;
-		send_azid		= _send_azid;
-	}
-	
-	protected Map
-	syncInvoke(
-		String 						operationID, 
-		Map 						parameters )
-	
-		throws PlatformMessengerException
-	{
-		PlatformMessage message = 
-			new PlatformMessage( 
-					"AZMSG", 
-					listener_id,
-					operationID, 
-					parameters, 
-					0 );
-
-		if ( !send_azid ){
-		
-			message.setSendAZID( false );
-		}
-		
-		final AESemaphore sem = new AESemaphore( "PlatformMessengerConfig:syncInvoke" );
-		
-		final Object[] result = { null };
-		
-		PlatformMessenger.queueMessage( 
-			message, 
-			new PlatformMessengerListener()
-			{
-				public void 
-				messageSent(
-					PlatformMessage 	message ) 
-				{
-				}
-	
-				public void 
-				replyReceived(
-					PlatformMessage 	message, 
-					String 				replyType,
-					Map 				reply )
-				{
-					try{
-						if ( replyType.equals( PlatformMessenger.REPLY_EXCEPTION )){
-							
-							String		e_message 	= (String)reply.get( "message" );
-
-							if ( e_message != null ){
-								
-								result[0] = new PlatformMessengerException( e_message );
-
-							}else{
-								
-								String		text 	= (String)reply.get( "text" );
-								
-								Throwable	e 		= (Throwable)reply.get( "Throwable" );
-								
-								if ( text == null && e == null ){
-									
-									result[0] = new PlatformMessengerException( "Unknown error" );
-									
-								}else if ( text == null ){
-									
-									result[0] = new PlatformMessengerException( "Failed to send RPC", e );
-									
-								}else if ( e == null ){
-									
-									result[0] = new PlatformMessengerException( text );
-									
-								}else{
-									
-									result[0] = new PlatformMessengerException( text, e );
-								}
-							}
-						}else{
-							
-							result[0] = reply;
-						}
-					}finally{
-						
-						sem.release();
-					}
-				}
-			});
-		
-		sem.reserve();
-		
-		if ( result[0] instanceof PlatformMessengerException ){
-			
-			throw((PlatformMessengerException)result[0]);
-		}
-		
-		return((Map)result[0]);
-	}
-}
+/*
+ * Created on Nov 26, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.messenger.config;
+
+import java.util.Map;
+
+import org.gudy.azureus2.core3.util.AESemaphore;
+
+import com.aelitis.azureus.core.messenger.PlatformMessage;
+import com.aelitis.azureus.core.messenger.PlatformMessenger;
+import com.aelitis.azureus.core.messenger.PlatformMessengerException;
+import com.aelitis.azureus.core.messenger.PlatformMessengerListener;
+
+public class 
+PlatformMessengerConfig 
+{
+	private String 		listener_id;
+	private boolean		send_azid;
+	
+	protected
+	PlatformMessengerConfig(
+		String		_listener_id,
+		boolean		_send_azid )
+	{
+		listener_id		= _listener_id;
+		send_azid		= _send_azid;
+	}
+	
+	protected Map
+	syncInvoke(
+		String 						operationID, 
+		Map 						parameters )
+	
+		throws PlatformMessengerException
+	{
+		PlatformMessage message = 
+			new PlatformMessage( 
+					"AZMSG", 
+					listener_id,
+					operationID, 
+					parameters, 
+					0 );
+
+		if ( !send_azid ){
+		
+			message.setSendAZID( false );
+		}
+		
+		final AESemaphore sem = new AESemaphore( "PlatformMessengerConfig:syncInvoke" );
+		
+		final Object[] result = { null };
+		
+		PlatformMessenger.queueMessage( 
+			message, 
+			new PlatformMessengerListener()
+			{
+				public void 
+				messageSent(
+					PlatformMessage 	message ) 
+				{
+				}
+	
+				public void 
+				replyReceived(
+					PlatformMessage 	message, 
+					String 				replyType,
+					Map 				reply )
+				{
+					try{
+						if ( replyType.equals( PlatformMessenger.REPLY_EXCEPTION )){
+							
+							String		e_message 	= (String)reply.get( "message" );
+
+							if ( e_message != null ){
+								
+								result[0] = new PlatformMessengerException( e_message );
+
+							}else{
+								
+								String		text 	= (String)reply.get( "text" );
+								
+								Throwable	e 		= (Throwable)reply.get( "Throwable" );
+								
+								if ( text == null && e == null ){
+									
+									result[0] = new PlatformMessengerException( "Unknown error" );
+									
+								}else if ( text == null ){
+									
+									result[0] = new PlatformMessengerException( "Failed to send RPC", e );
+									
+								}else if ( e == null ){
+									
+									result[0] = new PlatformMessengerException( text );
+									
+								}else{
+									
+									result[0] = new PlatformMessengerException( text, e );
+								}
+							}
+						}else{
+							
+							result[0] = reply;
+						}
+					}finally{
+						
+						sem.release();
+					}
+				}
+			});
+		
+		sem.reserve();
+		
+		if ( result[0] instanceof PlatformMessengerException ){
+			
+			throw((PlatformMessengerException)result[0]);
+		}
+		
+		return((Map)result[0]);
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformMetaSearchMessenger.java b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformMetaSearchMessenger.java
index 7f81712..09f5e8a 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformMetaSearchMessenger.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformMetaSearchMessenger.java
@@ -1,428 +1,427 @@
-/*
- * Created on May 6, 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.core.messenger.config;
-
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.messenger.PlatformMessenger;
-import com.aelitis.azureus.core.messenger.PlatformMessengerException;
-
-public class 
-PlatformMetaSearchMessenger 
-{
-	private static final int MAX_TEMPLATE_LIST		= 512;
-	
-	private static final PlatformMessengerConfig	dispatcher = 
-			new PlatformMessengerConfig( "searchtemplate", true );
-
-	private static final String OP_GET_TEMPLATE					= "get-template";
-	private static final String OP_GET_TEMPLATES				= "get-templates";
-	private static final String OP_LIST_POPULAR_TEMPLATES 		= "list-popular";
-	private static final String OP_LIST_FEATURED_TEMPLATES 		= "list-featured";
-	private static final String OP_TEMPLATE_SELECTED			= "template-selected";
-
-
-	public static templateDetails 
-	getTemplate(
-		String		extension_key,
-		long		template_id )
-	
-		throws PlatformMessengerException
-	{
-		Map parameters = getParameter( template_id );
-		
-		if ( extension_key != null ){
-			
-			parameters.put( "extension_key", extension_key );
-		}
-		
-		Map reply = dispatcher.syncInvoke(	OP_GET_TEMPLATE, parameters ); 
-
-		templateInfo info = getTemplateInfo( reply );
-		
-		if ( info == null ){
-			
-			throw( new PlatformMessengerException( "Invalid reply: " + reply ));
-		}
-		
-		String name 		= (String)reply.get( "name" );
-		String value		= (String)reply.get( "value" );
-		String engine_type	= (String)reply.get( "engine_id" );
-		
-		if ( name == null || value == null || engine_type == null ){
-			
-			throw( new PlatformMessengerException( "Invalid reply; field missing: " + reply ));
-		}
-		
-		int	type;
-		
-		if ( engine_type.equals( "json" )){
-		
-			type = templateDetails.ENGINE_TYPE_JSON;
-			
-		}else if ( engine_type.equals( "regexp" )){
-			
-			type = templateDetails.ENGINE_TYPE_REGEXP;
-			
-		}else{
-			
-			throw( new PlatformMessengerException( "Invalid type '" + engine_type + ": " + reply ));
-
-		}
-		
-		return( new templateDetails( info, type, name, value ));
-	}
-	
-	public static templateInfo[] 
-   	getTemplateDetails(
-   		String		extension_key,
-   		long[]		ids )
-   	
-   		throws PlatformMessengerException
-   	{
-		if( ids.length == 0 ){
-			
-			return( new templateInfo[0]);
-		}
-		
-		String	str = "";
-		
-		for (int i=0;i<ids.length;i++){
-			
-			str += (i==0?"":",") + ids[i];
-		}
-		
-   		Map parameters = new HashMap();
-   		
-		if ( extension_key != null ){
-			
-			parameters.put( "extension_key", extension_key );
-		}
-		
-   		parameters.put( "templateIds", str );
-
-   		Map reply = dispatcher.syncInvoke(	OP_GET_TEMPLATES, parameters ); 
-
-   		return( getTemplatesInfo( reply ));
-   	}
-	
-	public static templateInfo[] 
-	listTopPopularTemplates(
-		String		extension_key,
-		String		fud )
-	
-		throws PlatformMessengerException
-	{		
-		Map parameters = new HashMap();
-	
-		if ( extension_key != null ){
-			
-			parameters.put( "extension_key", extension_key );
-		}
-		
-		parameters.put( "fud", fud );
-		
-		Map reply = dispatcher.syncInvoke(	OP_LIST_POPULAR_TEMPLATES, parameters ); 
-
-		return( getTemplatesInfo( reply ));
-	}
-	
-	public static templateInfo[] 
-   	listAllPopularTemplates(
-   		String		extension_key,
-   		String		fud )
-   	
-   		throws PlatformMessengerException
-   	{
-   		Map parameters = new HashMap();
-   		
-		if ( extension_key != null ){
-			
-			parameters.put( "extension_key", extension_key );
-		}
-		
-		parameters.put( "fud", fud );
-		
-   		parameters.put( "page-num", new Long( 1 ));
-   		parameters.put( "items-per-page", new Long( MAX_TEMPLATE_LIST ));
-
-   		Map reply = dispatcher.syncInvoke(	OP_LIST_POPULAR_TEMPLATES, parameters ); 
-
-   		return( getTemplatesInfo( reply ));
-   	}
-	
-	public static templateInfo[] 
-	listFeaturedTemplates(
-		String		extension_key,
-		String		fud )
-	
-		throws PlatformMessengerException
-	{
-		Map parameters = new HashMap();
-		
-		if ( extension_key != null ){
-			
-			parameters.put( "extension_key", extension_key );
-		}
-		
-		parameters.put( "fud", fud );
-		
-		parameters.put( "page-num", new Long( 1 ));
-		parameters.put( "items-per-page", new Long( MAX_TEMPLATE_LIST ));
-
-		Map reply = dispatcher.syncInvoke(	OP_LIST_FEATURED_TEMPLATES, parameters ); 
-
-		return( getTemplatesInfo( reply ));
-	}
-	
-	protected static templateInfo[]
-	getTemplatesInfo(
-		Map		reply )
-	{		
-		List	templates = (List)reply.get( "templates" );
-
-		List	res = new ArrayList();
-		
-		for (int i=0;i<templates.size();i++){
-			
-			Map m = (Map)templates.get(i);
-			
-			templateInfo info = getTemplateInfo( m );
-			
-			if ( info != null ){
-				
-				res.add( info );
-			}
-		}
-		
-		templateInfo[] res_a = new templateInfo[ res.size()];
-
-		res.toArray( res_a );
-		
-		return( res_a );
-	}
-		
-	protected static templateInfo
-  	getTemplateInfo(
-  		Map		m )
-	{		
-		Long	id 		= (Long)m.get( "id" );
-		Boolean	show	= (Boolean)m.get( "show" );
-		Long	date 	= (Long)m.get( "modified_dt" );
-
-		float	rank_bias = 1;
-		
-		try{
-			String	str = (String)m.get( "rank_bias" );
-			
-			if ( str != null ){
-				
-				rank_bias = Float.parseFloat( str );
-			}
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-		
-		if ( show == null ){
-			
-			show = new Boolean( true );
-		}
-		
-		if ( id == null || show == null || date == null ){
-
-			PlatformMessenger.debug( "field missing from template info (" + m + ")" );
-
-		}else{
-
-			return( new templateInfo( id.longValue(), date.longValue(), show.booleanValue(), rank_bias ));
-
-			/*
-			SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.S");
-
-			format.setTimeZone( TimeZone.getTimeZone( "UTC" ));
-
-			try{
-
-				long	millis = format.parse( date ).getTime();
-
-				return( new templateInfo( id.longValue(), millis, show.booleanValue()));
-
-			}catch( Throwable e ){
-
-				PlatformMessenger.debug( "Invalid date received in template: " + m );
-			}
-			*/
-		}
-		
-		return( null );
-	}
-	                         	
-	public static void 
-	setTemplatetSelected(
-		String		extension_key,
-		long		template_id,
-		String		user_id,
-		boolean		is_selected )
-	
-		throws PlatformMessengerException
-	{
-		Map	parameters = getParameter( template_id );
-		
-		if ( extension_key != null ){
-			
-			parameters.put( "extension_key", extension_key );
-		}
-		
-		parameters.put( "userId", user_id );
-		parameters.put( "selected", new Boolean( is_selected ));
-		
-		dispatcher.syncInvoke(	OP_TEMPLATE_SELECTED, parameters ); 
-	}
-	
-	protected static Map
-	getParameter(
-		long		template_id )
-	{
-		Map parameters = new HashMap();
-		
-		parameters.put( "templateId", new Long( template_id ));
-
-		return( parameters );
-	}
-
-	public static class
-	templateInfo
-	{
-		private long		id;
-		private long		date;
-		private boolean		visible;
-		private float		rank_bias;
-		
-		protected
-		templateInfo(
-			long		_id,
-			long		_date,
-			boolean		_visible,
-			float		_rank_bias )
-		{
-			id			= _id;
-			date		= _date;
-			visible		= _visible;
-			rank_bias	= _rank_bias;
-		}
-		
-		public long
-		getId()
-		{
-			return( id );
-		}
-		
-		public long
-		getModifiedDate()
-		{
-			return( date );
-		}
-		
-		public boolean
-		isVisible()
-		{
-			return( visible );
-		}
-		
-		public float
-		getRankBias()
-		{
-			return( rank_bias );
-		}
-	}
-	
-	public static class
-	templateDetails
-	{
-		public static final int ENGINE_TYPE_JSON	= 1;
-		public static final int ENGINE_TYPE_REGEXP	= 2;
-		
-		private templateInfo		info;
-		
-		private int			type;
-		private String		name;
-		private String		value;
-		
-		protected
-		templateDetails(
-			templateInfo	_info,
-			int				_type,
-			String			_name,
-			String			_value )
-		{	
-			info		= _info;
-			type		= _type;
-			name		= _name;
-			value		= _value;
-		}
-		
-		public int
-		getType()
-		{
-			return( type );
-		}
-		
-		public long
-		getId()
-		{
-			return( info.getId());
-		}
-		
-		public long
-		getModifiedDate()
-		{
-			return( info.getModifiedDate());
-		}
-		
-		public float
-		getRankBias()
-		{
-			return( info.getRankBias());
-		}
-		
-		public boolean
-		isVisible()
-		{
-			return( info.isVisible());
-		}
-		
-		public String
-		getName()
-		{
-			return( name );
-		}
-		
-		public String
-		getValue()
-		{
-			return( value );
-		}
-	}
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.messenger.config;
+
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.Debug;
+
+import com.aelitis.azureus.core.messenger.PlatformMessenger;
+import com.aelitis.azureus.core.messenger.PlatformMessengerException;
+
+public class 
+PlatformMetaSearchMessenger 
+{
+	private static final int MAX_TEMPLATE_LIST		= 512;
+	
+	private static final PlatformMessengerConfig	dispatcher = 
+			new PlatformMessengerConfig( "searchtemplate", true );
+
+	private static final String OP_GET_TEMPLATE					= "get-template";
+	private static final String OP_GET_TEMPLATES				= "get-templates";
+	private static final String OP_LIST_POPULAR_TEMPLATES 		= "list-popular";
+	private static final String OP_LIST_FEATURED_TEMPLATES 		= "list-featured";
+	private static final String OP_TEMPLATE_SELECTED			= "template-selected";
+
+
+	public static templateDetails 
+	getTemplate(
+		String		extension_key,
+		long		template_id )
+	
+		throws PlatformMessengerException
+	{
+		Map parameters = getParameter( template_id );
+		
+		if ( extension_key != null ){
+			
+			parameters.put( "extension_key", extension_key );
+		}
+		
+		Map reply = dispatcher.syncInvoke(	OP_GET_TEMPLATE, parameters ); 
+
+		templateInfo info = getTemplateInfo( reply );
+		
+		if ( info == null ){
+			
+			throw( new PlatformMessengerException( "Invalid reply: " + reply ));
+		}
+		
+		String name 		= (String)reply.get( "name" );
+		String value		= (String)reply.get( "value" );
+		String engine_type	= (String)reply.get( "engine_id" );
+		
+		if ( name == null || value == null || engine_type == null ){
+			
+			throw( new PlatformMessengerException( "Invalid reply; field missing: " + reply ));
+		}
+		
+		int	type;
+		
+		if ( engine_type.equals( "json" )){
+		
+			type = templateDetails.ENGINE_TYPE_JSON;
+			
+		}else if ( engine_type.equals( "regexp" )){
+			
+			type = templateDetails.ENGINE_TYPE_REGEXP;
+			
+		}else{
+			
+			throw( new PlatformMessengerException( "Invalid type '" + engine_type + ": " + reply ));
+
+		}
+		
+		return( new templateDetails( info, type, name, value ));
+	}
+	
+	public static templateInfo[] 
+   	getTemplateDetails(
+   		String		extension_key,
+   		long[]		ids )
+   	
+   		throws PlatformMessengerException
+   	{
+		if( ids.length == 0 ){
+			
+			return( new templateInfo[0]);
+		}
+		
+		String	str = "";
+		
+		for (int i=0;i<ids.length;i++){
+			
+			str += (i==0?"":",") + ids[i];
+		}
+		
+   		Map parameters = new HashMap();
+   		
+		if ( extension_key != null ){
+			
+			parameters.put( "extension_key", extension_key );
+		}
+		
+   		parameters.put( "templateIds", str );
+
+   		Map reply = dispatcher.syncInvoke(	OP_GET_TEMPLATES, parameters ); 
+
+   		return( getTemplatesInfo( reply ));
+   	}
+	
+	public static templateInfo[] 
+	listTopPopularTemplates(
+		String		extension_key,
+		String		fud )
+	
+		throws PlatformMessengerException
+	{		
+		Map parameters = new HashMap();
+	
+		if ( extension_key != null ){
+			
+			parameters.put( "extension_key", extension_key );
+		}
+		
+		parameters.put( "fud", fud );
+		
+		Map reply = dispatcher.syncInvoke(	OP_LIST_POPULAR_TEMPLATES, parameters ); 
+
+		return( getTemplatesInfo( reply ));
+	}
+	
+	public static templateInfo[] 
+   	listAllPopularTemplates(
+   		String		extension_key,
+   		String		fud )
+   	
+   		throws PlatformMessengerException
+   	{
+   		Map parameters = new HashMap();
+   		
+		if ( extension_key != null ){
+			
+			parameters.put( "extension_key", extension_key );
+		}
+		
+		parameters.put( "fud", fud );
+		
+   		parameters.put( "page-num", new Long( 1 ));
+   		parameters.put( "items-per-page", new Long( MAX_TEMPLATE_LIST ));
+
+   		Map reply = dispatcher.syncInvoke(	OP_LIST_POPULAR_TEMPLATES, parameters ); 
+
+   		return( getTemplatesInfo( reply ));
+   	}
+	
+	public static templateInfo[] 
+	listFeaturedTemplates(
+		String		extension_key,
+		String		fud )
+	
+		throws PlatformMessengerException
+	{
+		Map parameters = new HashMap();
+		
+		if ( extension_key != null ){
+			
+			parameters.put( "extension_key", extension_key );
+		}
+		
+		parameters.put( "fud", fud );
+		
+		parameters.put( "page-num", new Long( 1 ));
+		parameters.put( "items-per-page", new Long( MAX_TEMPLATE_LIST ));
+
+		Map reply = dispatcher.syncInvoke(	OP_LIST_FEATURED_TEMPLATES, parameters ); 
+
+		return( getTemplatesInfo( reply ));
+	}
+	
+	protected static templateInfo[]
+	getTemplatesInfo(
+		Map		reply )
+	{		
+		List	templates = (List)reply.get( "templates" );
+
+		List	res = new ArrayList();
+		
+		for (int i=0;i<templates.size();i++){
+			
+			Map m = (Map)templates.get(i);
+			
+			templateInfo info = getTemplateInfo( m );
+			
+			if ( info != null ){
+				
+				res.add( info );
+			}
+		}
+		
+		templateInfo[] res_a = new templateInfo[ res.size()];
+
+		res.toArray( res_a );
+		
+		return( res_a );
+	}
+		
+	protected static templateInfo
+  	getTemplateInfo(
+  		Map		m )
+	{		
+		Long	id 		= (Long)m.get( "id" );
+		Boolean	show	= (Boolean)m.get( "show" );
+		Long	date 	= (Long)m.get( "modified_dt" );
+
+		float	rank_bias = 1;
+		
+		try{
+			String	str = (String)m.get( "rank_bias" );
+			
+			if ( str != null ){
+				
+				rank_bias = Float.parseFloat( str );
+			}
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+		
+		if ( show == null ){
+			
+			show = new Boolean( true );
+		}
+		
+		if ( id == null || show == null || date == null ){
+
+			PlatformMessenger.debug( "field missing from template info (" + m + ")" );
+
+		}else{
+
+			return( new templateInfo( id.longValue(), date.longValue(), show.booleanValue(), rank_bias ));
+
+			/*
+			SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.S");
+
+			format.setTimeZone( TimeZone.getTimeZone( "UTC" ));
+
+			try{
+
+				long	millis = format.parse( date ).getTime();
+
+				return( new templateInfo( id.longValue(), millis, show.booleanValue()));
+
+			}catch( Throwable e ){
+
+				PlatformMessenger.debug( "Invalid date received in template: " + m );
+			}
+			*/
+		}
+		
+		return( null );
+	}
+	                         	
+	public static void 
+	setTemplatetSelected(
+		String		extension_key,
+		long		template_id,
+		String		user_id,
+		boolean		is_selected )
+	
+		throws PlatformMessengerException
+	{
+		Map	parameters = getParameter( template_id );
+		
+		if ( extension_key != null ){
+			
+			parameters.put( "extension_key", extension_key );
+		}
+		
+		parameters.put( "userId", user_id );
+		parameters.put( "selected", new Boolean( is_selected ));
+		
+		dispatcher.syncInvoke(	OP_TEMPLATE_SELECTED, parameters ); 
+	}
+	
+	protected static Map
+	getParameter(
+		long		template_id )
+	{
+		Map parameters = new HashMap();
+		
+		parameters.put( "templateId", new Long( template_id ));
+
+		return( parameters );
+	}
+
+	public static class
+	templateInfo
+	{
+		private long		id;
+		private long		date;
+		private boolean		visible;
+		private float		rank_bias;
+		
+		protected
+		templateInfo(
+			long		_id,
+			long		_date,
+			boolean		_visible,
+			float		_rank_bias )
+		{
+			id			= _id;
+			date		= _date;
+			visible		= _visible;
+			rank_bias	= _rank_bias;
+		}
+		
+		public long
+		getId()
+		{
+			return( id );
+		}
+		
+		public long
+		getModifiedDate()
+		{
+			return( date );
+		}
+		
+		public boolean
+		isVisible()
+		{
+			return( visible );
+		}
+		
+		public float
+		getRankBias()
+		{
+			return( rank_bias );
+		}
+	}
+	
+	public static class
+	templateDetails
+	{
+		public static final int ENGINE_TYPE_JSON	= 1;
+		public static final int ENGINE_TYPE_REGEXP	= 2;
+		
+		private templateInfo		info;
+		
+		private int			type;
+		private String		name;
+		private String		value;
+		
+		protected
+		templateDetails(
+			templateInfo	_info,
+			int				_type,
+			String			_name,
+			String			_value )
+		{	
+			info		= _info;
+			type		= _type;
+			name		= _name;
+			value		= _value;
+		}
+		
+		public int
+		getType()
+		{
+			return( type );
+		}
+		
+		public long
+		getId()
+		{
+			return( info.getId());
+		}
+		
+		public long
+		getModifiedDate()
+		{
+			return( info.getModifiedDate());
+		}
+		
+		public float
+		getRankBias()
+		{
+			return( info.getRankBias());
+		}
+		
+		public boolean
+		isVisible()
+		{
+			return( info.isVisible());
+		}
+		
+		public String
+		getName()
+		{
+			return( name );
+		}
+		
+		public String
+		getValue()
+		{
+			return( value );
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformSubscriptionsMessenger.java b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformSubscriptionsMessenger.java
index 92de19b..ca2d311 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformSubscriptionsMessenger.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformSubscriptionsMessenger.java
@@ -1,337 +1,336 @@
-/*
- * Created on May 6, 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.core.messenger.config;
-
-import java.security.Signature;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.Base32;
-import org.gudy.azureus2.core3.util.ByteFormatter;
-import org.json.simple.JSONArray;
-
-
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.messenger.PlatformMessengerException;
-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 );
-
-	private static final String OP_CREATE_SUBS					= "create-subscription";
-	private static final String OP_UPDATE_SUBS					= "update-subscription";
-	private static final String OP_GET_SUBS_BY_SID				= "get-subscriptions";
-	private static final String OP_GET_POP_BY_SID				= "get-subscription-infos";
-	private static final String OP_SET_SELECTED					= "set-selected";
-
-	public static void
-	updateSubscription(
-		boolean		create,
-		String		name,
-		byte[]		public_key,
-		byte[]		private_key,
-		byte[]		sid,
-		int			version,
-		String		content )
-	
-		throws PlatformMessengerException
-	{
-		String operation = create?OP_CREATE_SUBS:OP_UPDATE_SUBS;
-		
-		checkEnabled( operation );
-		
-		Map parameters = new HashMap();
-		
-		String	sid_str = Base32.encode( sid );
-		String	pk_str	= Base32.encode(public_key) ;
-		
-		parameters.put( "name", name );
-		parameters.put( "subscription_id", sid_str );
-		parameters.put( "version_number", new Long( version ));
-		parameters.put( "content", content );				
-		
-		if ( create ){
-			
-			parameters.put( "public_key", pk_str );
-		}
-		
-		try{
-			Signature sig = CryptoECCUtils.getSignature( CryptoECCUtils.rawdataToPrivkey( private_key ));
-
-			sig.update( ( name + pk_str + sid_str + version + content ).getBytes( "UTF-8" ));
-			
-			byte[]	sig_bytes = sig.sign();
-			
-			/*
-			Signature verify = CryptoECCUtils.getSignature( CryptoECCUtils.rawdataToPubkey( public_key ));
-
-			verify.update( ( name + pk_str + sid_str + version + content ).getBytes( "UTF-8" ));
-			
-			boolean ok = verify.verify( sig_bytes );
-			*/
-			
-			parameters.put( "signature", Base32.encode( sig_bytes ));
-
-			dispatcher.syncInvoke( operation, parameters ); 
-			
-		}catch( Throwable e ){
-			
-			throw( new PlatformMessengerException( "Failed to create/update subscription", e ));
-		}
-	}
-	
-	public static subscriptionDetails 
-	getSubscriptionBySID(
-		byte[]		sid )
-	
-		throws PlatformMessengerException
-	{
-		checkEnabled( OP_GET_SUBS_BY_SID );
-		
-		Map parameters = new HashMap();
-		
-		List	sid_list = new JSONArray();
-
-		sid_list.add( Base32.encode( sid ));
-		
-		parameters.put( "subscription_ids", sid_list);
-		
-		Map reply = dispatcher.syncInvoke(	OP_GET_SUBS_BY_SID, parameters ); 
-
-		for (int i=0;i<sid_list.size();i++){
-			
-			Map	map = (Map)reply.get((String)sid_list.get(i));
-			
-			if ( map != null ){
-				
-				subscriptionDetails details = new subscriptionDetails( map );
-				
-				return( details );
-			}
-		}
-		
-		throw( new PlatformMessengerException( "Unknown sid '" + ByteFormatter.encodeString(sid) + "'" ));
-	}                       	
-	
-	public static long
-	getPopularityBySID(
-		byte[]		sid )
-	
-		throws PlatformMessengerException
-	{
-		checkEnabled( OP_GET_POP_BY_SID );
-		
-		Map parameters = new HashMap();
-		
-		List	sid_list = new JSONArray();
-		
-		sid_list.add( Base32.encode( sid ));
-					
-		parameters.put( "subscription_ids", sid_list );
-		
-		Map reply = dispatcher.syncInvoke(	OP_GET_POP_BY_SID, parameters ); 
-		
-		for (int i=0;i<sid_list.size();i++){
-			
-			Map	map = (Map)reply.get((String)sid_list.get(i));
-			
-			if ( map != null ){
-				
-				subscriptionInfo info = new subscriptionInfo( map );
-				
-				return( info.getPopularity());
-			}
-		}
-		
-		return( -1 );
-	}
-	
-	public static List[] 
-	setSelected(
-		List	sids )
-	
-		throws PlatformMessengerException
-	{
-		checkEnabled( OP_SET_SELECTED );
-		
-		Map parameters = new HashMap();
-		
-		List	sid_list 	= new JSONArray();		
-		for (int i=0;i<sids.size();i++){
-		
-			sid_list.add( Base32.encode( (byte[])sids.get(i) ));
-		}
-		
-		parameters.put( "subscription_ids", sid_list);
-		
-		Map reply = dispatcher.syncInvoke( OP_SET_SELECTED, parameters ); 
-		
-		List	versions = (List)reply.get( "version_numbers" );
-		
-		if ( versions == null ){
-			
-			// test
-			
-			versions = new ArrayList();
-			
-			for (int i=0;i<sids.size();i++){
-				
-				versions.add( new Long(1));
-			}
-		}
-		
-		List	popularities = (List)reply.get( "popularities" );
-		
-		if ( popularities == null ){
-			
-				// migrate
-			
-			popularities = new ArrayList();
-			
-			for (int i=0;i<sids.size();i++){
-				
-				popularities.add( new Long(-1));
-			}
-		}
-	
-		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
-	{
-		private Map		info;
-		
-		protected
-		subscriptionInfo(
-			Map		_info )
-		{
-			info	= _info;
-		}
-		
-		public long
-		getPopularity()
-		{
-			return(((Long)info.get( "popularity" )).intValue());
-		}
-	}
-	
-	public static class
-	subscriptionDetails
-	{
-		private Map		details;
-		
-		protected
-		subscriptionDetails(
-			Map		_details )
-		{	
-			details = _details;
-		}
-		
-		public String
-		getName()
-		{
-			return( getString( "name" ));
-		}
-		
-		public String
-		getContent()
-		{
-			return( getString( "content" ));
-		}
-		
-		public int
-		getPopularity()
-		{
-			Long	l_pop = (Long)details.get( "popularity" );
-			
-			if ( l_pop != null ){
-				
-				return( l_pop.intValue());
-			}
-			
-			return( -1 );
-		}
-		
-		protected String
-		getString(
-			String	key )
-		{
-			Object obj = details.get( key );
-			
-			if ( obj instanceof String ){
-				
-				return((String)obj);
-				
-			}else if ( obj instanceof byte[] ){
-					
-				byte[]	bytes = (byte[])obj;
-				
-				try{
-					return( new String( bytes, "UTF-8" ));
-					
-				}catch( Throwable e ){
-					
-					return( new String( bytes ));
-				}
-			}else{
-				
-				return( null );
-			}
-		}
-	}
-	
-	public static void
-	main(
-		String[]	args )
-	{
-		try{
-			AzureusCoreFactory.create();
-			
-			String short_id = "";
-			
-			long res = getPopularityBySID( Base32.decode( short_id ));
-			
-			System.out.println( res );
-			
-		}catch( Throwable e ){
-			
-			e.printStackTrace();
-		}
-	}
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.messenger.config;
+
+import java.security.Signature;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.Base32;
+import org.gudy.azureus2.core3.util.ByteFormatter;
+import org.json.simple.JSONArray;
+
+
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.messenger.PlatformMessengerException;
+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 );
+
+	private static final String OP_CREATE_SUBS					= "create-subscription";
+	private static final String OP_UPDATE_SUBS					= "update-subscription";
+	private static final String OP_GET_SUBS_BY_SID				= "get-subscriptions";
+	private static final String OP_GET_POP_BY_SID				= "get-subscription-infos";
+	private static final String OP_SET_SELECTED					= "set-selected";
+
+	public static void
+	updateSubscription(
+		boolean		create,
+		String		name,
+		byte[]		public_key,
+		byte[]		private_key,
+		byte[]		sid,
+		int			version,
+		String		content )
+	
+		throws PlatformMessengerException
+	{
+		String operation = create?OP_CREATE_SUBS:OP_UPDATE_SUBS;
+		
+		checkEnabled( operation );
+		
+		Map parameters = new HashMap();
+		
+		String	sid_str = Base32.encode( sid );
+		String	pk_str	= Base32.encode(public_key) ;
+		
+		parameters.put( "name", name );
+		parameters.put( "subscription_id", sid_str );
+		parameters.put( "version_number", new Long( version ));
+		parameters.put( "content", content );				
+		
+		if ( create ){
+			
+			parameters.put( "public_key", pk_str );
+		}
+		
+		try{
+			Signature sig = CryptoECCUtils.getSignature( CryptoECCUtils.rawdataToPrivkey( private_key ));
+
+			sig.update( ( name + pk_str + sid_str + version + content ).getBytes( "UTF-8" ));
+			
+			byte[]	sig_bytes = sig.sign();
+			
+			/*
+			Signature verify = CryptoECCUtils.getSignature( CryptoECCUtils.rawdataToPubkey( public_key ));
+
+			verify.update( ( name + pk_str + sid_str + version + content ).getBytes( "UTF-8" ));
+			
+			boolean ok = verify.verify( sig_bytes );
+			*/
+			
+			parameters.put( "signature", Base32.encode( sig_bytes ));
+
+			dispatcher.syncInvoke( operation, parameters ); 
+			
+		}catch( Throwable e ){
+			
+			throw( new PlatformMessengerException( "Failed to create/update subscription", e ));
+		}
+	}
+	
+	public static subscriptionDetails 
+	getSubscriptionBySID(
+		byte[]		sid )
+	
+		throws PlatformMessengerException
+	{
+		checkEnabled( OP_GET_SUBS_BY_SID );
+		
+		Map parameters = new HashMap();
+		
+		List	sid_list = new JSONArray();
+
+		sid_list.add( Base32.encode( sid ));
+		
+		parameters.put( "subscription_ids", sid_list);
+		
+		Map reply = dispatcher.syncInvoke(	OP_GET_SUBS_BY_SID, parameters ); 
+
+		for (int i=0;i<sid_list.size();i++){
+			
+			Map	map = (Map)reply.get((String)sid_list.get(i));
+			
+			if ( map != null ){
+				
+				subscriptionDetails details = new subscriptionDetails( map );
+				
+				return( details );
+			}
+		}
+		
+		throw( new PlatformMessengerException( "Unknown sid '" + ByteFormatter.encodeString(sid) + "'" ));
+	}                       	
+	
+	public static long
+	getPopularityBySID(
+		byte[]		sid )
+	
+		throws PlatformMessengerException
+	{
+		checkEnabled( OP_GET_POP_BY_SID );
+		
+		Map parameters = new HashMap();
+		
+		List	sid_list = new JSONArray();
+		
+		sid_list.add( Base32.encode( sid ));
+					
+		parameters.put( "subscription_ids", sid_list );
+		
+		Map reply = dispatcher.syncInvoke(	OP_GET_POP_BY_SID, parameters ); 
+		
+		for (int i=0;i<sid_list.size();i++){
+			
+			Map	map = (Map)reply.get((String)sid_list.get(i));
+			
+			if ( map != null ){
+				
+				subscriptionInfo info = new subscriptionInfo( map );
+				
+				return( info.getPopularity());
+			}
+		}
+		
+		return( -1 );
+	}
+	
+	public static List[] 
+	setSelected(
+		List	sids )
+	
+		throws PlatformMessengerException
+	{
+		checkEnabled( OP_SET_SELECTED );
+		
+		Map parameters = new HashMap();
+		
+		List	sid_list 	= new JSONArray();		
+		for (int i=0;i<sids.size();i++){
+		
+			sid_list.add( Base32.encode( (byte[])sids.get(i) ));
+		}
+		
+		parameters.put( "subscription_ids", sid_list);
+		
+		Map reply = dispatcher.syncInvoke( OP_SET_SELECTED, parameters ); 
+		
+		List	versions = (List)reply.get( "version_numbers" );
+		
+		if ( versions == null ){
+			
+			// test
+			
+			versions = new ArrayList();
+			
+			for (int i=0;i<sids.size();i++){
+				
+				versions.add( new Long(1));
+			}
+		}
+		
+		List	popularities = (List)reply.get( "popularities" );
+		
+		if ( popularities == null ){
+			
+				// migrate
+			
+			popularities = new ArrayList();
+			
+			for (int i=0;i<sids.size();i++){
+				
+				popularities.add( new Long(-1));
+			}
+		}
+	
+		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
+	{
+		private Map		info;
+		
+		protected
+		subscriptionInfo(
+			Map		_info )
+		{
+			info	= _info;
+		}
+		
+		public long
+		getPopularity()
+		{
+			return(((Long)info.get( "popularity" )).intValue());
+		}
+	}
+	
+	public static class
+	subscriptionDetails
+	{
+		private Map		details;
+		
+		protected
+		subscriptionDetails(
+			Map		_details )
+		{	
+			details = _details;
+		}
+		
+		public String
+		getName()
+		{
+			return( getString( "name" ));
+		}
+		
+		public String
+		getContent()
+		{
+			return( getString( "content" ));
+		}
+		
+		public int
+		getPopularity()
+		{
+			Long	l_pop = (Long)details.get( "popularity" );
+			
+			if ( l_pop != null ){
+				
+				return( l_pop.intValue());
+			}
+			
+			return( -1 );
+		}
+		
+		protected String
+		getString(
+			String	key )
+		{
+			Object obj = details.get( key );
+			
+			if ( obj instanceof String ){
+				
+				return((String)obj);
+				
+			}else if ( obj instanceof byte[] ){
+					
+				byte[]	bytes = (byte[])obj;
+				
+				try{
+					return( new String( bytes, "UTF-8" ));
+					
+				}catch( Throwable e ){
+					
+					return( new String( bytes ));
+				}
+			}else{
+				
+				return( null );
+			}
+		}
+	}
+	
+	public static void
+	main(
+		String[]	args )
+	{
+		try{
+			AzureusCoreFactory.create();
+			
+			String short_id = "";
+			
+			long res = getPopularityBySID( Base32.decode( short_id ));
+			
+			System.out.println( res );
+			
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformTorrentMessenger.java b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformTorrentMessenger.java
index db50ff9..530f0e7 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformTorrentMessenger.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformTorrentMessenger.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformVuzeActivitiesMessenger.java b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformVuzeActivitiesMessenger.java
index 7725b5c..206563f 100644
--- a/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformVuzeActivitiesMessenger.java
+++ b/azureus3/src/com/aelitis/azureus/core/messenger/config/PlatformVuzeActivitiesMessenger.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 28, 2008 
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/CookieParameter.java b/azureus3/src/com/aelitis/azureus/core/metasearch/CookieParameter.java
index 7dc3857..8e710ed 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/CookieParameter.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/CookieParameter.java
@@ -1,44 +1,43 @@
-/*
- * Created on May 6, 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.core.metasearch;
-
-public class CookieParameter {
-	
-	String name;
-	String value;
-	
-	public CookieParameter(String name, String value) {
-		super();
-		this.name = name;
-		this.value = value;
-	}
-	
-	public String getName() {
-		return name;
-	}
-	
-	public String getValue() {
-		return value;
-	}
-	
-	
-
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+public class CookieParameter {
+	
+	String name;
+	String value;
+	
+	public CookieParameter(String name, String value) {
+		super();
+		this.name = name;
+		this.value = value;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public String getValue() {
+		return value;
+	}
+	
+	
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/Engine.java b/azureus3/src/com/aelitis/azureus/core/metasearch/Engine.java
index fe2ecad..2dd5d9a 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/Engine.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/Engine.java
@@ -1,288 +1,288 @@
-/*
- * Created on May 6, 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.core.metasearch;
-
-import java.io.*;
-import java.util.Map;
-
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-
-
-public interface 
-Engine 
-{	
-	/**
-	 * AZ_VERSION:
-	 * 1: Original
-	 * 2: field value substitution in JSON engine type using ${FIELD_ID}
-	 * 3: field value substitution in REGEX engine type using ${FIELD_NO}
-	 */
-	public static final int	AZ_VERSION		= 3;
-	
-	public static final Object	VUZE_FILE_COMPONENT_ENGINE_KEY = new Object();
-	
-		// Don't change these values as they get persisted
-	
-	public static final int FIELD_NAME 			= 1;
-	public static final int FIELD_DATE 			= 2;
-	public static final int FIELD_SIZE 			= 3;
-	public static final int FIELD_PEERS 		= 4;
-	public static final int FIELD_SEEDS 		= 5;
-	public static final int FIELD_CATEGORY 		= 6;
-	public static final int FIELD_COMMENTS 		= 7;
-	public static final int FIELD_CONTENT_TYPE 	= 8;
-	public static final int FIELD_DISCARD	 	= 9;
-	public static final int FIELD_VOTES		 	= 10;
-	public static final int FIELD_SUPERSEEDS 	= 11;
-	public static final int FIELD_PRIVATE	 	= 12;
-	public static final int FIELD_DRMKEY        = 13;
-	public static final int FIELD_VOTES_DOWN    = 14;
-	
-	
-	public static final int FIELD_TORRENTLINK 	= 102;
-	public static final int FIELD_CDPLINK 		= 103;
-	public static final int FIELD_PLAYLINK 		= 104;
-	public static final int FIELD_DOWNLOADBTNLINK 		= 105;
-	
-	public static final int FIELD_HASH			= 200;
-	public static final int FIELD_RANK    = 201;
-	
-	public static final int[] FIELD_IDS = {
-		FIELD_NAME, FIELD_DATE, FIELD_SIZE, FIELD_PEERS, FIELD_SEEDS, FIELD_CATEGORY,
-		FIELD_COMMENTS, FIELD_CONTENT_TYPE, FIELD_DISCARD, 
-		FIELD_TORRENTLINK, FIELD_CDPLINK, FIELD_PLAYLINK,FIELD_DOWNLOADBTNLINK, FIELD_VOTES, FIELD_SUPERSEEDS,
-		FIELD_PRIVATE, FIELD_DRMKEY, FIELD_VOTES_DOWN, FIELD_HASH, FIELD_RANK
-	};
-		
-	public static final String[] FIELD_NAMES = {
-		"TITLE", "DATE", "SIZE", "PEERS", "SEEDS", "CAT",
-		"COMMENTS", "CONTENT_TYPE", "DISCARD",
-		"TORRENT", "CDP", "PLAY","DLBTN", "VOTES", "XSEEDS",
-		"PRIVATE", "DRMKEY", "VOTESDOWN", "HASH", "RANK"
-	};
-	
-	public static final int ENGINE_TYPE_REGEX		= 1;
-	public static final int ENGINE_TYPE_JSON		= 2;
-	public static final int ENGINE_TYPE_PLUGIN		= 3;
-	public static final int ENGINE_TYPE_RSS			= 4;
-	
-	
-	public static final int	ENGINE_SOURCE_UNKNOWN				= 0;
-	public static final int	ENGINE_SOURCE_VUZE					= 1;
-	public static final int	ENGINE_SOURCE_LOCAL					= 2;
-	public static final int	ENGINE_SOURCE_RSS					= 3;
-	
-	public static final int	SEL_STATE_DESELECTED			= 0;
-	public static final int	SEL_STATE_AUTO_SELECTED			= 1;
-	public static final int	SEL_STATE_MANUAL_SELECTED		= 2;
-	
-	public static final int AUTO_DL_SUPPORTED_UNKNOWN		= 0;
-	public static final int AUTO_DL_SUPPORTED_YES			= 1;
-	public static final int AUTO_DL_SUPPORTED_NO			= 2;
-	
-		/**
-		 * don't change these as they are externalised
-		 */
-	public static final String[] ENGINE_SOURCE_STRS = { "unknown","vuze","local","rss","unused" };
-	public static final String[] SEL_STATE_STRINGS	= { "no", "auto", "manual" };
-	public static final String[] ENGINE_TYPE_STRS 	= { "unknown","regexp","json", "plugin" };
-	
-	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	SC_REMOVE_DUP_HASH	= "remove_dup_hash";
-
-	
-	public static final String	CT_VIDEO	= "video";
-	public static final String	CT_AUDIO	= "audio";
-	public static final String	CT_GAME		= "game";
-	
-	public int getType();
-		
-	public Result[]
-	search(
-		SearchParameter[] 	searchParameters,
-		Map					context,
-		int					desired_max_matches,
-		int					absolute_max_matches,
-		String				headers,
-		ResultListener		listener )
-	
-		throws SearchException;
-	
-	public String 
-	getName();
-	
-	public String
-	getNameEx();
-	
-	public long 
-	getId();
-	
-	public String
-	getUID();
-	
-	public int
-	getVersion();
-	            
-	public long 
-	getLastUpdated();
-	
-	public String 
-	getIcon();
-
-	public String
-	getDownloadLinkCSS();
-	
-	public boolean
-	isActive();
-	
-	public boolean
-	isMine();
-	
-	public boolean
-	isPublic();
-	
-	public void
-	setMine(
-		boolean		mine );
-	
-	public int
-	getSelectionState();
-	
-	public void
-	setSelectionState(
-		int			state );
-	
-	public void
-	recordSelectionState();
-	
-	public void
-	checkSelectionStateRecorded();
-		
-	public int
-	getSource();
-	
-	public void
-	setSource(
-		int		source );
-	
-	public String
-	getReferer();
-	
-	public float
-	getRankBias();
-	
-	public void
-	setRankBias(
-		float		bias );
-	
-	public void
-	setPreferredDelta(
-		float	delta  );
-	
-	public float
-	getPreferredWeighting();
-	
-	public float
-	applyRankBias(
-		float	rank );
-	
-	public boolean
-	supportsField(
-		int		field_id );
-	
-	public boolean
-	supportsContext(
-		String	context_key );
-	
-	public boolean
-	isShareable();
-	
-	public boolean
-	isAuthenticated();
-	
-		/**
-		 * @return one of AUTO_DL constants above
-		 */
-	
-	public int
-	getAutoDownloadSupported();
-	
-	public int
-	getAZVersion();
-	
-	public void
-	addPotentialAssociation(
-		String		key );
-	
-	public Map<String,Object> 
-	exportToBencodedMap() 
-	
-		throws IOException;
-	
-	public Map<String,Object> 
-	exportToBencodedMap(
-		boolean		generic )
-	
-		throws IOException;
-
-	public String
-	exportToJSONString()
-	
-		throws IOException;
-	
-	public void
-	exportToVuzeFile(
-		File	target )
-	
-		throws IOException;
-	
-	public VuzeFile
-	exportToVuzeFile()
-	
-		throws IOException;
-	
-		/**
-		 * Tests for sameness in terms of function (ignores id, selection state etc)
-		 * @param other
-		 * @return
-		 */
-	
-	public boolean
-	sameLogicAs(
-		Engine	other );
-	
-		/**
-		 * resets to initial state (e.g. if the engine has state pertaining to what has/hasn't been downloaded
-		 * such as etags then this will be cleared)
-		 */
-	
-	public void
-	reset();
-	
-	public void
-	delete();
-	
-	public String
-	getString();
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+import java.io.*;
+import java.util.Map;
+
+import com.aelitis.azureus.core.vuzefile.VuzeFile;
+
+
+public interface 
+Engine 
+{	
+	/**
+	 * AZ_VERSION:
+	 * 1: Original
+	 * 2: field value substitution in JSON engine type using ${FIELD_ID}
+	 * 3: field value substitution in REGEX engine type using ${FIELD_NO}
+	 * 4: JSON engine now supports [x] in Entry Path, where x is the array index
+	 */
+	public static final int	AZ_VERSION		= 4;
+	
+	public static final Object	VUZE_FILE_COMPONENT_ENGINE_KEY = new Object();
+	
+		// Don't change these values as they get persisted
+	
+	public static final int FIELD_NAME 			= 1;
+	public static final int FIELD_DATE 			= 2;
+	public static final int FIELD_SIZE 			= 3;
+	public static final int FIELD_PEERS 		= 4;
+	public static final int FIELD_SEEDS 		= 5;
+	public static final int FIELD_CATEGORY 		= 6;
+	public static final int FIELD_COMMENTS 		= 7;
+	public static final int FIELD_CONTENT_TYPE 	= 8;
+	public static final int FIELD_DISCARD	 	= 9;
+	public static final int FIELD_VOTES		 	= 10;
+	public static final int FIELD_SUPERSEEDS 	= 11;
+	public static final int FIELD_PRIVATE	 	= 12;
+	public static final int FIELD_DRMKEY        = 13;
+	public static final int FIELD_VOTES_DOWN    = 14;
+	
+	
+	public static final int FIELD_TORRENTLINK 	= 102;
+	public static final int FIELD_CDPLINK 		= 103;
+	public static final int FIELD_PLAYLINK 		= 104;
+	public static final int FIELD_DOWNLOADBTNLINK 		= 105;
+	
+	public static final int FIELD_HASH			= 200;
+	public static final int FIELD_RANK    = 201;
+	
+	public static final int[] FIELD_IDS = {
+		FIELD_NAME, FIELD_DATE, FIELD_SIZE, FIELD_PEERS, FIELD_SEEDS, FIELD_CATEGORY,
+		FIELD_COMMENTS, FIELD_CONTENT_TYPE, FIELD_DISCARD, 
+		FIELD_TORRENTLINK, FIELD_CDPLINK, FIELD_PLAYLINK,FIELD_DOWNLOADBTNLINK, FIELD_VOTES, FIELD_SUPERSEEDS,
+		FIELD_PRIVATE, FIELD_DRMKEY, FIELD_VOTES_DOWN, FIELD_HASH, FIELD_RANK
+	};
+		
+	public static final String[] FIELD_NAMES = {
+		"TITLE", "DATE", "SIZE", "PEERS", "SEEDS", "CAT",
+		"COMMENTS", "CONTENT_TYPE", "DISCARD",
+		"TORRENT", "CDP", "PLAY","DLBTN", "VOTES", "XSEEDS",
+		"PRIVATE", "DRMKEY", "VOTESDOWN", "HASH", "RANK"
+	};
+	
+	public static final int ENGINE_TYPE_REGEX		= 1;
+	public static final int ENGINE_TYPE_JSON		= 2;
+	public static final int ENGINE_TYPE_PLUGIN		= 3;
+	public static final int ENGINE_TYPE_RSS			= 4;
+	
+	
+	public static final int	ENGINE_SOURCE_UNKNOWN				= 0;
+	public static final int	ENGINE_SOURCE_VUZE					= 1;
+	public static final int	ENGINE_SOURCE_LOCAL					= 2;
+	public static final int	ENGINE_SOURCE_RSS					= 3;
+	
+	public static final int	SEL_STATE_DESELECTED			= 0;
+	public static final int	SEL_STATE_AUTO_SELECTED			= 1;
+	public static final int	SEL_STATE_MANUAL_SELECTED		= 2;
+	
+	public static final int AUTO_DL_SUPPORTED_UNKNOWN		= 0;
+	public static final int AUTO_DL_SUPPORTED_YES			= 1;
+	public static final int AUTO_DL_SUPPORTED_NO			= 2;
+	
+		/**
+		 * don't change these as they are externalised
+		 */
+	public static final String[] ENGINE_SOURCE_STRS = { "unknown","vuze","local","rss","unused" };
+	public static final String[] SEL_STATE_STRINGS	= { "no", "auto", "manual" };
+	public static final String[] ENGINE_TYPE_STRS 	= { "unknown","regexp","json", "plugin" };
+	
+	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	SC_REMOVE_DUP_HASH	= "remove_dup_hash";
+
+	
+	public static final String	CT_VIDEO	= "video";
+	public static final String	CT_AUDIO	= "audio";
+	public static final String	CT_GAME		= "game";
+	
+	public int getType();
+		
+	public Result[]
+	search(
+		SearchParameter[] 	searchParameters,
+		Map					context,
+		int					desired_max_matches,
+		int					absolute_max_matches,
+		String				headers,
+		ResultListener		listener )
+	
+		throws SearchException;
+	
+	public String 
+	getName();
+	
+	public String
+	getNameEx();
+	
+	public long 
+	getId();
+	
+	public String
+	getUID();
+	
+	public int
+	getVersion();
+	            
+	public long 
+	getLastUpdated();
+	
+	public String 
+	getIcon();
+
+	public String
+	getDownloadLinkCSS();
+	
+	public boolean
+	isActive();
+	
+	public boolean
+	isMine();
+	
+	public boolean
+	isPublic();
+	
+	public void
+	setMine(
+		boolean		mine );
+	
+	public int
+	getSelectionState();
+	
+	public void
+	setSelectionState(
+		int			state );
+	
+	public void
+	recordSelectionState();
+	
+	public void
+	checkSelectionStateRecorded();
+		
+	public int
+	getSource();
+	
+	public void
+	setSource(
+		int		source );
+	
+	public String
+	getReferer();
+	
+	public float
+	getRankBias();
+	
+	public void
+	setRankBias(
+		float		bias );
+	
+	public void
+	setPreferredDelta(
+		float	delta  );
+	
+	public float
+	getPreferredWeighting();
+	
+	public float
+	applyRankBias(
+		float	rank );
+	
+	public boolean
+	supportsField(
+		int		field_id );
+	
+	public boolean
+	supportsContext(
+		String	context_key );
+	
+	public boolean
+	isShareable();
+	
+	public boolean
+	isAuthenticated();
+	
+		/**
+		 * @return one of AUTO_DL constants above
+		 */
+	
+	public int
+	getAutoDownloadSupported();
+	
+	public int
+	getAZVersion();
+	
+	public void
+	addPotentialAssociation(
+		String		key );
+	
+	public Map<String,Object> 
+	exportToBencodedMap() 
+	
+		throws IOException;
+	
+	public Map<String,Object> 
+	exportToBencodedMap(
+		boolean		generic )
+	
+		throws IOException;
+
+	public String
+	exportToJSONString()
+	
+		throws IOException;
+	
+	public void
+	exportToVuzeFile(
+		File	target )
+	
+		throws IOException;
+	
+	public VuzeFile
+	exportToVuzeFile()
+	
+		throws IOException;
+	
+		/**
+		 * Tests for sameness in terms of function (ignores id, selection state etc)
+		 * @param other
+		 * @return
+		 */
+	
+	public boolean
+	sameLogicAs(
+		Engine	other );
+	
+		/**
+		 * resets to initial state (e.g. if the engine has state pertaining to what has/hasn't been downloaded
+		 * such as etags then this will be cleared)
+		 */
+	
+	public void
+	reset();
+	
+	public void
+	delete();
+	
+	public String
+	getString();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearch.java b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearch.java
index c223714..19448af 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearch.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearch.java
@@ -1,126 +1,125 @@
-/*
- * Created on May 6, 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.core.metasearch;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Map;
-
-public interface 
-MetaSearch 
-{	
-	public Engine
-	importFromBEncodedMap(
-		Map<String,Object>		map )
-	
-		throws IOException;
-	
-	public Engine[] 
-	search(
-		ResultListener 		listener,
-		SearchParameter[] 	searchParameters,
-		String				headers,
-		int					max_per_engine );
-	
-	public Engine[] 
-  	search(
-  		ResultListener 		listener,
-  		SearchParameter[] 	searchParameters,
-  		String				headers,
-  		Map<String,String>	context,
-  		int					max_per_engine );
-	
-	public Engine[] 
-	search(
-		Engine[]			engine,
-		ResultListener 		listener,
-		SearchParameter[] 	searchParameters,
-		String				headers,
-		int					max_per_engine );
-	
-	public Engine[] 
-  	search(
-  		Engine[]			engine,
-  		ResultListener 		listener,
-  		SearchParameter[] 	searchParameters,
-  		String				headers,
-  		Map<String,String>	context,
-  		int					max_per_engine );
-	
-	public String
-	getFUD();
-	
-	public Engine[] 
-	getEngines(
-		boolean		active_only,
-		boolean		ensure_up_to_date );
-	
-	public Engine
-	getEngine(
-		long		id );
-	
-	public Engine
-	getEngineByUID(
-		String		uid );
-	
-	public void 
-	addEngine( 
-		Engine 		engine );
-	
-	public Engine 
-	addEngine( 
-		long		id )
-	
-		throws MetaSearchException;
-	
-	public Engine
-	createRSSEngine(
-		String	name,
-		URL		url )
-	
-		throws MetaSearchException;
-	
-	public void 
-	removeEngine(
-		Engine 		engine );
-	
-	public int
-	getEngineCount();
-	
-	public void
-	enginePreferred(
-		Engine		engine );
-	
-	public void
-	exportEngines(
-		File	to_file )
-	
-		throws MetaSearchException;
-	
-	public void
-	addListener(
-		MetaSearchListener		listener );
-	
-	public void
-	removeListener(
-		MetaSearchListener		listener );
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Map;
+
+public interface 
+MetaSearch 
+{	
+	public Engine
+	importFromBEncodedMap(
+		Map<String,Object>		map )
+	
+		throws IOException;
+	
+	public Engine[] 
+	search(
+		ResultListener 		listener,
+		SearchParameter[] 	searchParameters,
+		String				headers,
+		int					max_per_engine );
+	
+	public Engine[] 
+  	search(
+  		ResultListener 		listener,
+  		SearchParameter[] 	searchParameters,
+  		String				headers,
+  		Map<String,String>	context,
+  		int					max_per_engine );
+	
+	public Engine[] 
+	search(
+		Engine[]			engine,
+		ResultListener 		listener,
+		SearchParameter[] 	searchParameters,
+		String				headers,
+		int					max_per_engine );
+	
+	public Engine[] 
+  	search(
+  		Engine[]			engine,
+  		ResultListener 		listener,
+  		SearchParameter[] 	searchParameters,
+  		String				headers,
+  		Map<String,String>	context,
+  		int					max_per_engine );
+	
+	public String
+	getFUD();
+	
+	public Engine[] 
+	getEngines(
+		boolean		active_only,
+		boolean		ensure_up_to_date );
+	
+	public Engine
+	getEngine(
+		long		id );
+	
+	public Engine
+	getEngineByUID(
+		String		uid );
+	
+	public void 
+	addEngine( 
+		Engine 		engine );
+	
+	public Engine 
+	addEngine( 
+		long		id )
+	
+		throws MetaSearchException;
+	
+	public Engine
+	createRSSEngine(
+		String	name,
+		URL		url )
+	
+		throws MetaSearchException;
+	
+	public void 
+	removeEngine(
+		Engine 		engine );
+	
+	public int
+	getEngineCount();
+	
+	public void
+	enginePreferred(
+		Engine		engine );
+	
+	public void
+	exportEngines(
+		File	to_file )
+	
+		throws MetaSearchException;
+	
+	public void
+	addListener(
+		MetaSearchListener		listener );
+	
+	public void
+	removeListener(
+		MetaSearchListener		listener );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchException.java b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchException.java
index 5933023..e52e496 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchException.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchException.java
@@ -1,42 +1,41 @@
-/*
- * Created on May 15, 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.core.metasearch;
-
-public class 
-MetaSearchException
-	extends Exception
-{
-	public
-	MetaSearchException(
-		String			str )
-	{
-		super( str );
-	}
-	
-	public
-	MetaSearchException(
-		String			str,
-		Throwable		cause )
-	{
-		super( str, cause );
-	}
-}
+/*
+ * Created on May 15, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+public class 
+MetaSearchException
+	extends Exception
+{
+	public
+	MetaSearchException(
+		String			str )
+	{
+		super( str );
+	}
+	
+	public
+	MetaSearchException(
+		String			str,
+		Throwable		cause )
+	{
+		super( str, cause );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchListener.java b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchListener.java
index 1581e4d..5e9cab0 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchListener.java
@@ -1,38 +1,37 @@
-/*
- * Created on Aug 11, 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.core.metasearch;
-
-public interface 
-MetaSearchListener 
-{
-	public void
-	engineAdded(
-		Engine		engine );
-	
-	public void
-	engineUpdated(
-		Engine		engine );
-	
-	public void
-	engineRemoved(
-		Engine		engine );
-}
+/*
+ * Created on Aug 11, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+public interface 
+MetaSearchListener 
+{
+	public void
+	engineAdded(
+		Engine		engine );
+	
+	public void
+	engineUpdated(
+		Engine		engine );
+	
+	public void
+	engineRemoved(
+		Engine		engine );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManager.java b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManager.java
index f2d1df7..f965adb 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManager.java
@@ -1,75 +1,74 @@
-/*
- * Created on May 6, 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.core.metasearch;
-
-import java.util.Map;
-
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-
-public interface 
-MetaSearchManager 
-{
-	public MetaSearch
-	getMetaSearch();
-	
-	public boolean
-	isAutoMode();
-			
-	public void
-	setSelectedEngines(
-		long[]		ids,
-		boolean		auto )
-	
-		throws MetaSearchException;
-	
-	public Engine
-	addEngine(
-		long		id,
-		int			type,
-		String		name,
-		String		json_value )
-	
-		throws MetaSearchException;
-	
-	public boolean
-	isImportable(
-		VuzeFile		vf );
-	
-	public Engine
-	importEngine(
-		Map			map,
-		boolean		warn_user )
-	
-		throws MetaSearchException;
-	
-	public void
-	addListener(
-		MetaSearchManagerListener		listener );
-	
-	public void
-	removeListener(
-		MetaSearchManagerListener		listener );
-	
-	public void
-	log(
-		String		str );
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+import java.util.Map;
+
+import com.aelitis.azureus.core.vuzefile.VuzeFile;
+
+public interface 
+MetaSearchManager 
+{
+	public MetaSearch
+	getMetaSearch();
+	
+	public boolean
+	isAutoMode();
+			
+	public void
+	setSelectedEngines(
+		long[]		ids,
+		boolean		auto )
+	
+		throws MetaSearchException;
+	
+	public Engine
+	addEngine(
+		long		id,
+		int			type,
+		String		name,
+		String		json_value )
+	
+		throws MetaSearchException;
+	
+	public boolean
+	isImportable(
+		VuzeFile		vf );
+	
+	public Engine
+	importEngine(
+		Map			map,
+		boolean		warn_user )
+	
+		throws MetaSearchException;
+	
+	public void
+	addListener(
+		MetaSearchManagerListener		listener );
+	
+	public void
+	removeListener(
+		MetaSearchManagerListener		listener );
+	
+	public void
+	log(
+		String		str );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManagerFactory.java b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManagerFactory.java
index 3fc960e..6a634a9 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManagerFactory.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManagerFactory.java
@@ -1,40 +1,39 @@
-/*
- * Created on May 6, 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.core.metasearch;
-
-import com.aelitis.azureus.core.metasearch.impl.MetaSearchManagerImpl;
-
-public class 
-MetaSearchManagerFactory 
-{
-	public static void
-	preInitialise()
-	{
-		MetaSearchManagerImpl.preInitialise();
-	}
-	
-	public static MetaSearchManager
-	getSingleton()
-	{
-		return( MetaSearchManagerImpl.getSingleton());
-	}
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+import com.aelitis.azureus.core.metasearch.impl.MetaSearchManagerImpl;
+
+public class 
+MetaSearchManagerFactory 
+{
+	public static void
+	preInitialise()
+	{
+		MetaSearchManagerImpl.preInitialise();
+	}
+	
+	public static MetaSearchManager
+	getSingleton()
+	{
+		return( MetaSearchManagerImpl.getSingleton());
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManagerListener.java b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManagerListener.java
index 966c7f7..b2187bd 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManagerListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/MetaSearchManagerListener.java
@@ -1,30 +1,29 @@
-/*
- * Created on Jan 25, 2010
- * Created by Paul Gardner
- * 
- * Copyright 2010 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.metasearch;
-
-public interface 
-MetaSearchManagerListener 
-{
-	public void
-	searchRequest(
-		String		term );
-}
+/*
+ * Created on Jan 25, 2010
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+public interface 
+MetaSearchManagerListener 
+{
+	public void
+	searchRequest(
+		String		term );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/Result.java b/azureus3/src/com/aelitis/azureus/core/metasearch/Result.java
index b781082..40d2d00 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/Result.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/Result.java
@@ -1,377 +1,382 @@
-/*
- * Created on May 6, 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.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 org.apache.commons.lang.Entities;
-import org.gudy.azureus2.core3.util.DisplayFormatters;
-import org.json.simple.JSONObject;
-
-import com.aelitis.azureus.core.metasearch.utils.MomentsAgoDateFormatter;
-
-public abstract class Result {
-	private static final String HTML_TAGS = "(\\<(/?[^\\>]+)\\>)" ;
-	private static final String DUPLICATE_SPACES = "\\s{2,}";
-
-	private Engine		engine;
-	
-	public abstract Date getPublishedDate();
-	
-	public abstract String getCategory();
-	public abstract void setCategory(String category);
-	
-	public abstract String getContentType();
-	public abstract void setContentType(String contentType);
-	
-	public abstract String getName();
-	public abstract long getSize();
-	public abstract int getNbPeers();
-	public abstract int getNbSeeds();
-	public abstract int getNbSuperSeeds();
-	public abstract int getComments();
-	public abstract int getVotes();
-	public abstract int getVotesDown();
-	public abstract boolean isPrivate();
-	
-	public abstract String getDRMKey();
-	
-	//Links
-	public abstract String getDownloadLink();
-	public abstract String getDownloadButtonLink();
-	public abstract String getCDPLink();
-	public abstract String getPlayLink();
-	public abstract float getAccuracy();  // 0.0 -> 1.0 and -1 if not supported
-	
-	
-	public abstract String getSearchQuery();
-	
-	public abstract String getUID();
-	public abstract String getHash();
-	
-	protected
-	Result(
-		Engine		_engine )
-	{
-		engine	= _engine;
-	}
-	
-	public Engine
-	getEngine()
-	{
-		return( engine );
-	}
-	
-	public String toString() {
-		return getName() + " : " + getNbSeeds() + " s, " + getNbPeers() + "p, "  ;
-	}
-	
-	
-	/*
-	public String getNameHTML() {		
-		if(getName() != null) {
-			return( getName());
-			//return( XUXmlWriter.escapeXML( getName()));
-			//return Entities.XML.escape(getName());
-		}
-		return null;
-	}
-	
-	public String getCategoryHTML() {
-		if(getCategory() != null) {
-			return( getCategory());
-			//return Entities.XML.escape(getCategory());
-		}
-		return null;
-	}
-	*/
-	
-	/**
-	 * 
-	 * @return a value between 0 and 1 representing the rank of the result
-	 */
-	public float getRank() {
-
-		int seeds = getNbSeeds();
-		int peers = getNbPeers();
-		
-		if ( seeds < 0 ){
-			seeds = 0;
-		}
-		
-		if ( peers < 0 ){
-			peers = 0;
-		}
-		
-		int totalVirtualPeers = 3 * seeds + peers + 2;
-		
-		int superSeeds = getNbSuperSeeds();
-		if(superSeeds > 0) {
-			totalVirtualPeers  += 50 * superSeeds;
-		}
-		
-		int votes = getVotes();
-		if(votes > 0) {
-			if(votes > 50) {
-				votes = 50;
-			}
-			totalVirtualPeers += 5 * votes;
-		}
-		
-		int votesDown = getVotesDown();
-		if(votesDown > 0) {
-			totalVirtualPeers -= 200 * votesDown;
-		}
-		
-		if(totalVirtualPeers < 2) totalVirtualPeers = 2;
-		
-		float rank = (float) (Math.log(totalVirtualPeers)/Math.log(10)) / 5f;
-		
-		if(rank > 2f) rank = 2f;
-		
-		if(isPrivate()) {
-			rank /= 2;
-		}
-		
-		String queryString = getSearchQuery();
-		String name = getName();
-		if(queryString != null && name != null) {
-			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;
-				}
-			}
-		}
-		
-		rank = applyRankBias( rank );
-		
-		return rank;
-	}
-	
-	protected float
-	applyRankBias(
-		float	_rank )
-	{
-		float rank = engine.applyRankBias( _rank );
-		
-		/*
-		if ( rank != _rank ){
-			
-			System.out.println( "bias applied for " + engine.getName() + ": " + _rank + "-> " + rank );
-		}
-		*/
-		
-		return( rank );
-	}
-	
-	public Map toJSONMap() {
-		Map object = new JSONObject();
-		try {
-			object.put("d", MomentsAgoDateFormatter.getMomentsAgoString(this.getPublishedDate()));
-			object.put("ts", "" + this.getPublishedDate().getTime());
-		} catch(Exception e) {
-			object.put("d", "unknown");
-			object.put("ts", "0");
-		}
-		
-		object.put("c", this.getCategory());
-		object.put("n",this.getName());
-		
-		int	super_seeds = getNbSuperSeeds();
-		int	seeds		= getNbSeeds();
-		
-		int	seed_total = -1;
-		
-		if ( super_seeds > 0 ){
-			
-			seed_total = 10*super_seeds + new Random().nextInt(10);
-		}
-		
-		if ( seeds > 0 ){
-			
-			if ( seed_total == -1 ){
-				
-				seed_total = 0;
-			}
-			
-			seed_total += seeds;
-		}
-		
-		object.put("s","" + seed_total);
-			
-		if(this.getNbPeers() >= 0) {
-			object.put("p","" + this.getNbPeers());
-		} else {
-			object.put("p","-1");
-		}
-		
-		int	comments = getComments();
-		
-		if ( comments >= 0 ){
-		
-			object.put( "co", "" + comments );
-		}
-		
-		long size = this.getSize();
-		if(size >= 0) {
-				// max three digits for display purposes
-			
-			String size_str = DisplayFormatters.formatByteCountToKiBEtc( size );
-		
-			size_str = DisplayFormatters.trimDigits( size_str, 3 );
-			
-			object.put("l", size_str );
-			object.put("lb", "" + size  );
-		} else {
-			object.put("l", "-1");
-			object.put("lb", "0");
-		}
-		
-		object.put("r", "" + this.getRank());
-		
-		object.put("ct", this.getContentType());
-		
-		float accuracy = getAccuracy();
-		
-		if ( accuracy >= 0 ){
-			if ( accuracy > 1 ){
-				accuracy = 1;
-			}
-			object.put ("ac", "" + accuracy );
-		}
-		
-		if ( this.getCDPLink().length() > 0 ){
-			object.put("cdp", this.getCDPLink());
-		}
-		
-			// This is also used by subscription code to extract download link so if you
-			// change this you'll need to change that too...
-		
-		if ( this.getDownloadLink().length() > 0 ){
-			object.put("dl", this.getDownloadLink());
-		}
-		
-		if ( this.getDownloadButtonLink().length() > 0 ){
-			object.put("dbl", this.getDownloadButtonLink());
-		}
-		
-		if ( this.getPlayLink().length() > 0 ){
-			object.put("pl", this.getPlayLink());
-		}
-		
-		if ( this.getVotes() >= 0 ){
-			object.put("v", "" + this.getVotes());
-		}
-		
-		if ( this.getVotesDown() >= 0 ){
-			object.put("vd", "" + this.getVotesDown());
-		}
-		
-		String drmKey = getDRMKey();
-		if(drmKey != null) {
-			object.put("dk",drmKey);
-		}
-		
-			// used by subscriptions...
-		
-		String uid = getUID();
-		if ( uid != null ){
-			object.put( "u", uid );
-		}
-		object.put("pr", this.isPrivate() ? "1" : "0");
-
-		String hash = getHash();
-		if ( hash != null ){
-			object.put( "h", hash );
-		}
-		
-		return object;
-	}
-	
-	public static void
-	adjustRelativeTerms(
-		Map		map )
-	{
-		String	ts = (String)map.get( "ts" );
-		
-		if ( ts != null ){
-			
-			long	l_ts = Long.parseLong(ts);
-			
-			if ( l_ts > 0 ){
-				
-				map.put("d", MomentsAgoDateFormatter.getMomentsAgoString(new Date( l_ts )));
-
-			}
-		}
-	}
-	
-	protected static final String removeHTMLTags(String input) {
-		if ( input == null ){
-			return( null );
-		}
-		String result = input.replaceAll(HTML_TAGS, " ");
-		return result.replaceAll(DUPLICATE_SPACES, " ").trim();
-	}
-
-	protected static final String unescapeEntities( String input )
-	{
-		if ( input == null ){
-			return( null );
-		}
-		return( Entities.HTML40.unescape( input ));
-	}
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.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 org.apache.commons.lang.Entities;
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.json.simple.JSONObject;
+
+import com.aelitis.azureus.core.metasearch.utils.MomentsAgoDateFormatter;
+
+public abstract class Result {
+	private static final String HTML_TAGS = "(\\<(/?[^\\>]+)\\>)" ;
+	private static final String DUPLICATE_SPACES = "\\s{2,}";
+
+	private Engine		engine;
+	
+	public abstract Date getPublishedDate();
+	
+	public abstract String getCategory();
+	public abstract void setCategory(String category);
+	
+	public abstract String getContentType();
+	public abstract void setContentType(String contentType);
+	
+	public abstract String getName();
+	public abstract long getSize();
+	public abstract int getNbPeers();
+	public abstract int getNbSeeds();
+	public abstract int getNbSuperSeeds();
+	public abstract int getComments();
+	public abstract int getVotes();
+	public abstract int getVotesDown();
+	public abstract boolean isPrivate();
+	
+	public abstract String getDRMKey();
+	
+	//Links
+	public abstract String getDownloadLink();
+	public abstract String getDownloadButtonLink();
+	public abstract String getCDPLink();
+	public abstract String getPlayLink();
+	public abstract float getAccuracy();  // 0.0 -> 1.0 and -1 if not supported
+	
+	
+	public abstract String getSearchQuery();
+	
+	public abstract String getUID();
+	public abstract String getHash();
+	
+	protected
+	Result(
+		Engine		_engine )
+	{
+		engine	= _engine;
+	}
+	
+	public Engine
+	getEngine()
+	{
+		return( engine );
+	}
+	
+	public String toString() {
+		return getName() + " : " + getNbSeeds() + " s, " + getNbPeers() + "p, "  ;
+	}
+	
+	
+	/*
+	public String getNameHTML() {		
+		if(getName() != null) {
+			return( getName());
+			//return( XUXmlWriter.escapeXML( getName()));
+			//return Entities.XML.escape(getName());
+		}
+		return null;
+	}
+	
+	public String getCategoryHTML() {
+		if(getCategory() != null) {
+			return( getCategory());
+			//return Entities.XML.escape(getCategory());
+		}
+		return null;
+	}
+	*/
+	
+	/**
+	 * 
+	 * @return a value between 0 and 1 representing the rank of the result
+	 */
+	public float getRank() {
+
+		int seeds = getNbSeeds();
+		int peers = getNbPeers();
+		
+		if ( seeds < 0 ){
+			seeds = 0;
+		}
+		
+		if ( peers < 0 ){
+			peers = 0;
+		}
+		
+		int totalVirtualPeers = 3 * seeds + peers + 2;
+		
+		int superSeeds = getNbSuperSeeds();
+		if(superSeeds > 0) {
+			totalVirtualPeers  += 50 * superSeeds;
+		}
+		
+		int votes = getVotes();
+		if(votes > 0) {
+			if(votes > 50) {
+				votes = 50;
+			}
+			totalVirtualPeers += 5 * votes;
+		}
+		
+		int votesDown = getVotesDown();
+		if(votesDown > 0) {
+			totalVirtualPeers -= 200 * votesDown;
+		}
+		
+		if(totalVirtualPeers < 2) totalVirtualPeers = 2;
+		
+		float rank = (float) (Math.log(totalVirtualPeers)/Math.log(10)) / 5f;
+		
+		if(rank > 2f) rank = 2f;
+		
+		if(isPrivate()) {
+			rank /= 2;
+		}
+		
+		String queryString = getSearchQuery();
+		String name = getName();
+		if(queryString != null && name != null) {
+			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;
+				}
+			}
+		}
+		
+		rank = applyRankBias( rank );
+		
+		return rank;
+	}
+	
+	protected float
+	applyRankBias(
+		float	_rank )
+	{
+		float rank = engine.applyRankBias( _rank );
+		
+		/*
+		if ( rank != _rank ){
+			
+			System.out.println( "bias applied for " + engine.getName() + ": " + _rank + "-> " + rank );
+		}
+		*/
+		
+		return( rank );
+	}
+	
+	public Map toJSONMap() {
+		Map object = new JSONObject();
+		Date pub_date = this.getPublishedDate();
+		if ( pub_date == null ){
+			object.put("d", "unknown");
+			object.put("ts", "0");
+		}else{
+			try {
+				object.put("d", MomentsAgoDateFormatter.getMomentsAgoString(pub_date));
+				object.put("ts", "" + pub_date.getTime());
+			} catch(Exception e) {
+				object.put("d", "unknown");
+				object.put("ts", "0");
+			}
+		}
+		
+		object.put("c", this.getCategory());
+		object.put("n",this.getName());
+		
+		int	super_seeds = getNbSuperSeeds();
+		int	seeds		= getNbSeeds();
+		
+		int	seed_total = -1;
+		
+		if ( super_seeds > 0 ){
+			
+			seed_total = 10*super_seeds + new Random().nextInt(10);
+		}
+		
+		if ( seeds > 0 ){
+			
+			if ( seed_total == -1 ){
+				
+				seed_total = 0;
+			}
+			
+			seed_total += seeds;
+		}
+		
+		object.put("s","" + seed_total);
+			
+		if(this.getNbPeers() >= 0) {
+			object.put("p","" + this.getNbPeers());
+		} else {
+			object.put("p","-1");
+		}
+		
+		int	comments = getComments();
+		
+		if ( comments >= 0 ){
+		
+			object.put( "co", "" + comments );
+		}
+		
+		long size = this.getSize();
+		if(size >= 0) {
+				// max three digits for display purposes
+			
+			String size_str = DisplayFormatters.formatByteCountToKiBEtc( size );
+		
+			size_str = DisplayFormatters.trimDigits( size_str, 3 );
+			
+			object.put("l", size_str );
+			object.put("lb", "" + size  );
+		} else {
+			object.put("l", "-1");
+			object.put("lb", "0");
+		}
+		
+		object.put("r", "" + this.getRank());
+		
+		object.put("ct", this.getContentType());
+		
+		float accuracy = getAccuracy();
+		
+		if ( accuracy >= 0 ){
+			if ( accuracy > 1 ){
+				accuracy = 1;
+			}
+			object.put ("ac", "" + accuracy );
+		}
+		
+		if ( this.getCDPLink().length() > 0 ){
+			object.put("cdp", this.getCDPLink());
+		}
+		
+			// This is also used by subscription code to extract download link so if you
+			// change this you'll need to change that too...
+		
+		if ( this.getDownloadLink().length() > 0 ){
+			object.put("dl", this.getDownloadLink());
+		}
+		
+		if ( this.getDownloadButtonLink().length() > 0 ){
+			object.put("dbl", this.getDownloadButtonLink());
+		}
+		
+		if ( this.getPlayLink().length() > 0 ){
+			object.put("pl", this.getPlayLink());
+		}
+		
+		if ( this.getVotes() >= 0 ){
+			object.put("v", "" + this.getVotes());
+		}
+		
+		if ( this.getVotesDown() >= 0 ){
+			object.put("vd", "" + this.getVotesDown());
+		}
+		
+		String drmKey = getDRMKey();
+		if(drmKey != null) {
+			object.put("dk",drmKey);
+		}
+		
+			// used by subscriptions...
+		
+		String uid = getUID();
+		if ( uid != null ){
+			object.put( "u", uid );
+		}
+		object.put("pr", this.isPrivate() ? "1" : "0");
+
+		String hash = getHash();
+		if ( hash != null ){
+			object.put( "h", hash );
+		}
+		
+		return object;
+	}
+	
+	public static void
+	adjustRelativeTerms(
+		Map		map )
+	{
+		String	ts = (String)map.get( "ts" );
+		
+		if ( ts != null ){
+			
+			long	l_ts = Long.parseLong(ts);
+			
+			if ( l_ts > 0 ){
+				
+				map.put("d", MomentsAgoDateFormatter.getMomentsAgoString(new Date( l_ts )));
+
+			}
+		}
+	}
+	
+	protected static final String removeHTMLTags(String input) {
+		if ( input == null ){
+			return( null );
+		}
+		String result = input.replaceAll(HTML_TAGS, " ");
+		return result.replaceAll(DUPLICATE_SPACES, " ").trim();
+	}
+
+	protected static final String unescapeEntities( String input )
+	{
+		if ( input == null ){
+			return( null );
+		}
+		return( Entities.HTML40.unescape( input ));
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/ResultListener.java b/azureus3/src/com/aelitis/azureus/core/metasearch/ResultListener.java
index 58375e7..346ced3 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/ResultListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/ResultListener.java
@@ -1,38 +1,37 @@
-/*
- * Created on May 6, 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.core.metasearch;
-
-
-public interface ResultListener {
-	
-	public void contentReceived(Engine engine, String content );
-	
-	public void matchFound( Engine engine, String[] fields );
-	
-	public void resultsReceived(Engine engine,Result[] results);
-	
-	public void resultsComplete(Engine engine);
-	
-	public void engineFailed(Engine engine, Throwable cause );
-	
-	public void engineRequiresLogin(Engine engine, Throwable cause );
-
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+
+public interface ResultListener {
+	
+	public void contentReceived(Engine engine, String content );
+	
+	public void matchFound( Engine engine, String[] fields );
+	
+	public void resultsReceived(Engine engine,Result[] results);
+	
+	public void resultsComplete(Engine engine);
+	
+	public void engineFailed(Engine engine, Throwable cause );
+	
+	public void engineRequiresLogin(Engine engine, Throwable cause );
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/SearchException.java b/azureus3/src/com/aelitis/azureus/core/metasearch/SearchException.java
index 717bf12..8e69428 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/SearchException.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/SearchException.java
@@ -1,37 +1,36 @@
-/*
- * Created on May 6, 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.core.metasearch;
-
-public class SearchException extends Exception {
-	
-	public SearchException(Throwable t) {
-		super(t);
-	}
-	
-	public SearchException(String description,Throwable t) {
-		super(description,t);
-	}
-	
-	public SearchException(String description) {
-		super(description);
-	}
-
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+public class SearchException extends Exception {
+	
+	public SearchException(Throwable t) {
+		super(t);
+	}
+	
+	public SearchException(String description,Throwable t) {
+		super(description,t);
+	}
+	
+	public SearchException(String description) {
+		super(description);
+	}
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/SearchParameter.java b/azureus3/src/com/aelitis/azureus/core/metasearch/SearchParameter.java
index 2d78959..d9bcb44 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/SearchParameter.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/SearchParameter.java
@@ -1,44 +1,43 @@
-/*
- * Created on May 6, 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.core.metasearch;
-
-public class SearchParameter {
-	
-	private String matchPattern;
-	private String value;
-	
-	
-	public SearchParameter(String matchPattern, String value) {
-		this.matchPattern = matchPattern;
-		this.value = value;
-	}
-
-
-	public String getMatchPattern() {
-		return matchPattern;
-	}
-
-
-	public String getValue() {
-		return value;
-	}
-
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch;
+
+public class SearchParameter {
+	
+	private String matchPattern;
+	private String value;
+	
+	
+	public SearchParameter(String matchPattern, String value) {
+		this.matchPattern = matchPattern;
+		this.value = value;
+	}
+
+
+	public String getMatchPattern() {
+		return matchPattern;
+	}
+
+
+	public String getValue() {
+		return value;
+	}
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParser.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParser.java
index 5ea20dc..a69301e 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParser.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParser.java
@@ -1,29 +1,28 @@
-/*
- * Created on May 6, 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.core.metasearch.impl;
-
-import java.util.Date;
-
-public abstract class DateParser {
-
-	public abstract Date parseDate(String date);
-	
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl;
+
+import java.util.Date;
+
+public abstract class DateParser {
+
+	public abstract Date parseDate(String date);
+	
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParserClassic.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParserClassic.java
index 52c36d3..dfb9b82 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParserClassic.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParserClassic.java
@@ -1,332 +1,331 @@
-/*
- * Created on May 6, 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.core.metasearch.impl;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.StringTokenizer;
-import java.util.TimeZone;
-
-import org.gudy.azureus2.pluginsimpl.local.utils.xml.rss.RSSUtils;
-
-public class DateParserClassic extends DateParser {
-	
-	static boolean DEBUG = false;
-	
-	TimeZone timeZone;
-	DateFormat ddMMMyyyyFormat;
-	DateFormat ddMMMyyFormat;
-	DateFormat MMddyyyyFormat;
-	
-	DateFormat userDateFormat;
-	
-	boolean auto;
-	
-	public DateParserClassic() {
-		this("GMT",true,null);
-	}
-	
-	public DateParserClassic(String timeZone,boolean auto, String dateFormat) {
-		
-		this.timeZone = TimeZone.getTimeZone(timeZone);
-		this.auto = auto;
-		
-		if(!auto) {
-			if(dateFormat != null) {
-				userDateFormat = new SimpleDateFormat(dateFormat);
-				userDateFormat.setTimeZone(this.timeZone);
-			} else {
-				//TODO : in debug mode throw an Exception telling the user he needs to provide a dateFormat in manual mode
-			}
-		}
-		
-		ddMMMyyyyFormat = new SimpleDateFormat("dd MMM yyyy");
-		ddMMMyyyyFormat.setTimeZone(this.timeZone);
-		
-		ddMMMyyFormat = new SimpleDateFormat("dd MMM yy");
-		ddMMMyyFormat.setTimeZone(this.timeZone);
-		
-		MMddyyyyFormat = new SimpleDateFormat("MM-dd yyyy");
-		MMddyyyyFormat.setTimeZone(this.timeZone);
-		
-	}
-	
-	public Date parseDate(String date) {
-		Date result =  null;
-		if(auto) {
-			 result = parseDateInternal(date);
-		} else {
-			if(userDateFormat != null) {
-				try {
-					result = userDateFormat.parse(date);
-				} catch(Exception e) {
-					//TODO : in debug mode, throw an exception to tell the user that his dateFormat is invalid / didn't parse a date
-				}
-			}
-		}
-		if(DEBUG) {
-			System.out.println(date + " > " + (result==null?"null": result.toString()));
-		}
-		
-		return result;
-	}
-	
-	private Date parseDateInternal(String s) {
-		if(s == null) {
-			return null;
-		}
-		s = s.toLowerCase().trim();
-		
-		// screw this mess, first off lets see if we have an RSS feed compatible date
-		
-		Date d = RSSUtils.parseRSSDate( s );
-		if ( d != null ){
-			return( d );
-		}
-		//"Today hh:mm" and "Y-day hh:mm" cases
-		if(s.startsWith("today ") || s.startsWith("y-day ")) {
-			try {
-				Calendar calendar = new GregorianCalendar();
-				calendar.setTimeZone(timeZone);
-				String time = s.substring(6);
-				StringTokenizer st = new StringTokenizer(time,":");
-				int hours = Integer.parseInt(st.nextToken());
-				int minutes = Integer.parseInt(st.nextToken());
-				calendar.set(Calendar.HOUR_OF_DAY, hours);
-				calendar.set(Calendar.MINUTE,minutes);
-				if(s.startsWith("y-day ")) {
-					calendar.add(Calendar.DATE, -1);
-				}
-				return calendar.getTime();
-			} catch(Exception e) {
-				e.printStackTrace();
-				return null;
-			}
-		}
-		
-		//"07-25 2006", "02-01 02:53" and "03 Mar 2006" cases
-		if(s.length() > 3) { 
-			String thirdCharacter = s.substring(2,3);
-			
-			//"07-25 2006" and "02-01 02:53" cases
-			if(thirdCharacter.equals("-")) {
-				if(s.length() > 9) {
-					String ninthCharacter = s.substring(8,9);
-					//"02-01 02:53" case
-					if(ninthCharacter.equals(":")) {
-						try {
-							int month = Integer.parseInt(s.substring(0,2));
-							int day = Integer.parseInt(s.substring(3,5));
-							int hours = Integer.parseInt(s.substring(6,8));
-							int minutes = Integer.parseInt(s.substring(9,11));
-							Calendar calendar = new GregorianCalendar();
-							calendar.setTimeZone(timeZone);
-							calendar.set(Calendar.MONTH, month-1);
-							calendar.set(Calendar.DAY_OF_MONTH,day);
-							calendar.set(Calendar.HOUR_OF_DAY, hours);
-							calendar.set(Calendar.MINUTE,minutes);
-							return calendar.getTime();
-						} catch (Exception e) {
-							e.printStackTrace();
-						}
-					} 
-					//"07-25 2006"
-					else {
-						try {
-							return MMddyyyyFormat.parse(s);
-						} catch (Exception e) {
-							e.printStackTrace();
-						}	
-					}
-				} else {
-					//"03-25" case
-					try {
-						int month = Integer.parseInt(s.substring(0,2));
-						int day = Integer.parseInt(s.substring(3,5));
-						Calendar calendar = new GregorianCalendar();
-						calendar.setTimeZone(timeZone);
-						calendar.set(Calendar.MONTH, month);
-						calendar.set(Calendar.DAY_OF_MONTH,day);
-						return calendar.getTime();
-					} catch (Exception e) {
-						e.printStackTrace();
-					}
-				}
-				
-			} else if(s.length() == 9 && s.indexOf(" ") != -1){
-				//"21 Mar 08" case
-				try {
-					return ddMMMyyFormat.parse(s);
-				} catch (Exception e) {
-					if(DEBUG) {e.printStackTrace();}
-				}	
-			}
-			
-			//"03 Mar 2006" case
-			if(thirdCharacter.equals(" ")) {
-				try {
-					return ddMMMyyyyFormat.parse(s);
-				} catch (Exception e) {
-					if(DEBUG) {e.printStackTrace();}
-				}
-			}
-		}
-		
-		//Age based stuff
-		if(		s.endsWith(" ago") ||
-				s.indexOf("month")!= -1 || 
-				s.indexOf("hour") != -1 || 
-				s.indexOf("day") != -1 || 
-				s.indexOf("week") != -1 || 
-				s.indexOf("year") != -1) {
-			
-			s= s.replaceAll(" ago", "");
-			StringTokenizer st = new StringTokenizer(s," ");
-			if(st.countTokens() >= 2) {
-				try {
-					Calendar calendar = new GregorianCalendar();
-					while(st.hasMoreTokens()) {
-						float value = Float.parseFloat(st.nextToken());
-						String unit = st.nextToken();
-						
-						calendar.setTimeZone(timeZone);
-						if(unit.startsWith("min")) {
-							calendar.add(Calendar.MINUTE, -(int)value);
-						}
-						if(unit.startsWith("hour")) {
-							calendar.add(Calendar.HOUR_OF_DAY, -(int)value);
-						}
-						if(unit.startsWith("day")) {
-							calendar.add(Calendar.DATE, -(int)value);
-						}
-						if(unit.startsWith("week")) {
-							calendar.add(Calendar.WEEK_OF_YEAR, -(int)value);
-						}
-						if(unit.startsWith("month")) {
-							calendar.add(Calendar.MONTH, -(int)value);
-						}
-						if(unit.startsWith("year")) {
-							calendar.add(Calendar.YEAR, -(int)value);
-						}
-					}
-					return calendar.getTime();
-				} catch (Exception e) {
-					if(DEBUG) {e.printStackTrace();}
-				}
-			}
-		}
-		
-		if(s.equals("today")) {
-			Calendar calendar = new GregorianCalendar();
-			calendar.setTimeZone(timeZone);
-			//calendar.set(Calendar.HOUR_OF_DAY,12);
-			//calendar.set(Calendar.MINUTE,0);
-			return calendar.getTime();
-		}
-		
-		if(s.equals("yesterday")) {
-			Calendar calendar = new GregorianCalendar();
-			calendar.setTimeZone(timeZone);
-			calendar.add(Calendar.DATE, -1);
-			//calendar.set(Calendar.HOUR_OF_DAY,12);
-			//calendar.set(Calendar.MINUTE,0);
-			return calendar.getTime();
-		}
-		
-		try {
-			StringTokenizer st = new StringTokenizer(s," ");
-			Calendar calendar = new GregorianCalendar();
-			calendar.setTimeZone(timeZone);
-			while(st.hasMoreTokens()) {
-					String element = st.nextToken();
-					int field = -1;
-					int end_offset = -1;
-					if(element.endsWith("h")) {
-						field = Calendar.HOUR_OF_DAY;
-						end_offset = 1;
-					}
-					if(element.endsWith("d")) {
-						field = Calendar.DAY_OF_MONTH;
-						end_offset = 1;
-					}
-					if(element.endsWith("w")) {
-						field = Calendar.WEEK_OF_YEAR;
-						end_offset = 1;
-					}
-					if(element.endsWith("m")) {
-						field = Calendar.MONTH;
-						end_offset = 1;
-					}
-					if(element.endsWith("mon")) {
-						field = Calendar.MONTH;
-						end_offset = 3;
-					}
-					if(element.endsWith("y")) {
-						field = Calendar.YEAR;
-						end_offset = 1;
-					}
-					if(field != -1 && end_offset != -1) {
-						int value = (int) (Float.parseFloat(element.substring(0,element.length() - end_offset)));
-						calendar.add(field,-value);
-					}
-			}
-			
-			return calendar.getTime();
-			
-		} catch (Exception e) {
-			if(DEBUG) {e.printStackTrace();}
-		}
-		
-		return null;
-	}
-	
-	
-	public static void main(String args[]) {
-		DEBUG = true;
-		DateParserClassic dateParser = new DateParserClassic();
-		
-		dateParser.parseDate("Today 05:34");
-		dateParser.parseDate("Y-Day 21:55");
-		dateParser.parseDate("07-25 2006");
-		dateParser.parseDate("02-01 02:53");
-		dateParser.parseDate("03 Mar 2006");
-		dateParser.parseDate("0 minute ago");
-		dateParser.parseDate("3 hours ago");
-		dateParser.parseDate("2 days ago");
-		dateParser.parseDate("10 months ago");
-		dateParser.parseDate("45 mins ago");
-		dateParser.parseDate("Today");
-		dateParser.parseDate("Yesterday");
-		dateParser.parseDate("16.9w");
-		dateParser.parseDate("22.6h");
-		dateParser.parseDate("1.7d");
-		dateParser.parseDate("2d 7h");
-		dateParser.parseDate("1w");
-		dateParser.parseDate("1w 4d");
-		dateParser.parseDate("1mon 1w");
-		dateParser.parseDate( "2013-08-11T18:30:00.000Z" );
-	}
-	
-
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.StringTokenizer;
+import java.util.TimeZone;
+
+import org.gudy.azureus2.pluginsimpl.local.utils.xml.rss.RSSUtils;
+
+public class DateParserClassic extends DateParser {
+	
+	static boolean DEBUG = false;
+	
+	TimeZone timeZone;
+	DateFormat ddMMMyyyyFormat;
+	DateFormat ddMMMyyFormat;
+	DateFormat MMddyyyyFormat;
+	
+	DateFormat userDateFormat;
+	
+	boolean auto;
+	
+	public DateParserClassic() {
+		this("GMT",true,null);
+	}
+	
+	public DateParserClassic(String timeZone,boolean auto, String dateFormat) {
+		
+		this.timeZone = TimeZone.getTimeZone(timeZone);
+		this.auto = auto;
+		
+		if(!auto) {
+			if(dateFormat != null) {
+				userDateFormat = new SimpleDateFormat(dateFormat);
+				userDateFormat.setTimeZone(this.timeZone);
+			} else {
+				//TODO : in debug mode throw an Exception telling the user he needs to provide a dateFormat in manual mode
+			}
+		}
+		
+		ddMMMyyyyFormat = new SimpleDateFormat("dd MMM yyyy");
+		ddMMMyyyyFormat.setTimeZone(this.timeZone);
+		
+		ddMMMyyFormat = new SimpleDateFormat("dd MMM yy");
+		ddMMMyyFormat.setTimeZone(this.timeZone);
+		
+		MMddyyyyFormat = new SimpleDateFormat("MM-dd yyyy");
+		MMddyyyyFormat.setTimeZone(this.timeZone);
+		
+	}
+	
+	public Date parseDate(String date) {
+		Date result =  null;
+		if(auto) {
+			 result = parseDateInternal(date);
+		} else {
+			if(userDateFormat != null) {
+				try {
+					result = userDateFormat.parse(date);
+				} catch(Exception e) {
+					//TODO : in debug mode, throw an exception to tell the user that his dateFormat is invalid / didn't parse a date
+				}
+			}
+		}
+		if(DEBUG) {
+			System.out.println(date + " > " + (result==null?"null": result.toString()));
+		}
+		
+		return result;
+	}
+	
+	private Date parseDateInternal(String s) {
+		if(s == null) {
+			return null;
+		}
+		s = s.toLowerCase().trim();
+		
+		// screw this mess, first off lets see if we have an RSS feed compatible date
+		
+		Date d = RSSUtils.parseRSSDate( s );
+		if ( d != null ){
+			return( d );
+		}
+		//"Today hh:mm" and "Y-day hh:mm" cases
+		if(s.startsWith("today ") || s.startsWith("y-day ")) {
+			try {
+				Calendar calendar = new GregorianCalendar();
+				calendar.setTimeZone(timeZone);
+				String time = s.substring(6);
+				StringTokenizer st = new StringTokenizer(time,":");
+				int hours = Integer.parseInt(st.nextToken());
+				int minutes = Integer.parseInt(st.nextToken());
+				calendar.set(Calendar.HOUR_OF_DAY, hours);
+				calendar.set(Calendar.MINUTE,minutes);
+				if(s.startsWith("y-day ")) {
+					calendar.add(Calendar.DATE, -1);
+				}
+				return calendar.getTime();
+			} catch(Exception e) {
+				e.printStackTrace();
+				return null;
+			}
+		}
+		
+		//"07-25 2006", "02-01 02:53" and "03 Mar 2006" cases
+		if(s.length() > 3) { 
+			String thirdCharacter = s.substring(2,3);
+			
+			//"07-25 2006" and "02-01 02:53" cases
+			if(thirdCharacter.equals("-")) {
+				if(s.length() > 9) {
+					String ninthCharacter = s.substring(8,9);
+					//"02-01 02:53" case
+					if(ninthCharacter.equals(":")) {
+						try {
+							int month = Integer.parseInt(s.substring(0,2));
+							int day = Integer.parseInt(s.substring(3,5));
+							int hours = Integer.parseInt(s.substring(6,8));
+							int minutes = Integer.parseInt(s.substring(9,11));
+							Calendar calendar = new GregorianCalendar();
+							calendar.setTimeZone(timeZone);
+							calendar.set(Calendar.MONTH, month-1);
+							calendar.set(Calendar.DAY_OF_MONTH,day);
+							calendar.set(Calendar.HOUR_OF_DAY, hours);
+							calendar.set(Calendar.MINUTE,minutes);
+							return calendar.getTime();
+						} catch (Exception e) {
+							e.printStackTrace();
+						}
+					} 
+					//"07-25 2006"
+					else {
+						try {
+							return MMddyyyyFormat.parse(s);
+						} catch (Exception e) {
+							e.printStackTrace();
+						}	
+					}
+				} else {
+					//"03-25" case
+					try {
+						int month = Integer.parseInt(s.substring(0,2));
+						int day = Integer.parseInt(s.substring(3,5));
+						Calendar calendar = new GregorianCalendar();
+						calendar.setTimeZone(timeZone);
+						calendar.set(Calendar.MONTH, month);
+						calendar.set(Calendar.DAY_OF_MONTH,day);
+						return calendar.getTime();
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+				
+			} else if(s.length() == 9 && s.indexOf(" ") != -1){
+				//"21 Mar 08" case
+				try {
+					return ddMMMyyFormat.parse(s);
+				} catch (Exception e) {
+					if(DEBUG) {e.printStackTrace();}
+				}	
+			}
+			
+			//"03 Mar 2006" case
+			if(thirdCharacter.equals(" ")) {
+				try {
+					return ddMMMyyyyFormat.parse(s);
+				} catch (Exception e) {
+					if(DEBUG) {e.printStackTrace();}
+				}
+			}
+		}
+		
+		//Age based stuff
+		if(		s.endsWith(" ago") ||
+				s.indexOf("month")!= -1 || 
+				s.indexOf("hour") != -1 || 
+				s.indexOf("day") != -1 || 
+				s.indexOf("week") != -1 || 
+				s.indexOf("year") != -1) {
+			
+			s= s.replaceAll(" ago", "");
+			StringTokenizer st = new StringTokenizer(s," ");
+			if(st.countTokens() >= 2) {
+				try {
+					Calendar calendar = new GregorianCalendar();
+					while(st.hasMoreTokens()) {
+						float value = Float.parseFloat(st.nextToken());
+						String unit = st.nextToken();
+						
+						calendar.setTimeZone(timeZone);
+						if(unit.startsWith("min")) {
+							calendar.add(Calendar.MINUTE, -(int)value);
+						}
+						if(unit.startsWith("hour")) {
+							calendar.add(Calendar.HOUR_OF_DAY, -(int)value);
+						}
+						if(unit.startsWith("day")) {
+							calendar.add(Calendar.DATE, -(int)value);
+						}
+						if(unit.startsWith("week")) {
+							calendar.add(Calendar.WEEK_OF_YEAR, -(int)value);
+						}
+						if(unit.startsWith("month")) {
+							calendar.add(Calendar.MONTH, -(int)value);
+						}
+						if(unit.startsWith("year")) {
+							calendar.add(Calendar.YEAR, -(int)value);
+						}
+					}
+					return calendar.getTime();
+				} catch (Exception e) {
+					if(DEBUG) {e.printStackTrace();}
+				}
+			}
+		}
+		
+		if(s.equals("today")) {
+			Calendar calendar = new GregorianCalendar();
+			calendar.setTimeZone(timeZone);
+			//calendar.set(Calendar.HOUR_OF_DAY,12);
+			//calendar.set(Calendar.MINUTE,0);
+			return calendar.getTime();
+		}
+		
+		if(s.equals("yesterday")) {
+			Calendar calendar = new GregorianCalendar();
+			calendar.setTimeZone(timeZone);
+			calendar.add(Calendar.DATE, -1);
+			//calendar.set(Calendar.HOUR_OF_DAY,12);
+			//calendar.set(Calendar.MINUTE,0);
+			return calendar.getTime();
+		}
+		
+		try {
+			StringTokenizer st = new StringTokenizer(s," ");
+			Calendar calendar = new GregorianCalendar();
+			calendar.setTimeZone(timeZone);
+			while(st.hasMoreTokens()) {
+					String element = st.nextToken();
+					int field = -1;
+					int end_offset = -1;
+					if(element.endsWith("h")) {
+						field = Calendar.HOUR_OF_DAY;
+						end_offset = 1;
+					}
+					if(element.endsWith("d")) {
+						field = Calendar.DAY_OF_MONTH;
+						end_offset = 1;
+					}
+					if(element.endsWith("w")) {
+						field = Calendar.WEEK_OF_YEAR;
+						end_offset = 1;
+					}
+					if(element.endsWith("m")) {
+						field = Calendar.MONTH;
+						end_offset = 1;
+					}
+					if(element.endsWith("mon")) {
+						field = Calendar.MONTH;
+						end_offset = 3;
+					}
+					if(element.endsWith("y")) {
+						field = Calendar.YEAR;
+						end_offset = 1;
+					}
+					if(field != -1 && end_offset != -1) {
+						int value = (int) (Float.parseFloat(element.substring(0,element.length() - end_offset)));
+						calendar.add(field,-value);
+					}
+			}
+			
+			return calendar.getTime();
+			
+		} catch (Exception e) {
+			if(DEBUG) {e.printStackTrace();}
+		}
+		
+		return null;
+	}
+	
+	
+	public static void main(String args[]) {
+		DEBUG = true;
+		DateParserClassic dateParser = new DateParserClassic();
+		
+		dateParser.parseDate("Today 05:34");
+		dateParser.parseDate("Y-Day 21:55");
+		dateParser.parseDate("07-25 2006");
+		dateParser.parseDate("02-01 02:53");
+		dateParser.parseDate("03 Mar 2006");
+		dateParser.parseDate("0 minute ago");
+		dateParser.parseDate("3 hours ago");
+		dateParser.parseDate("2 days ago");
+		dateParser.parseDate("10 months ago");
+		dateParser.parseDate("45 mins ago");
+		dateParser.parseDate("Today");
+		dateParser.parseDate("Yesterday");
+		dateParser.parseDate("16.9w");
+		dateParser.parseDate("22.6h");
+		dateParser.parseDate("1.7d");
+		dateParser.parseDate("2d 7h");
+		dateParser.parseDate("1w");
+		dateParser.parseDate("1w 4d");
+		dateParser.parseDate("1mon 1w");
+		dateParser.parseDate( "2013-08-11T18:30:00.000Z" );
+	}
+	
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java
index d0f5582..7be70c1 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/DateParserRegex.java
@@ -1,469 +1,468 @@
-/*
- * Created on May 6, 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.core.metasearch.impl;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.TimeZone;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class DateParserRegex extends DateParser {
-	
-	static boolean DEBUG = false;
-	
-	TimeZone timeZone;
-	DateFormat userDateFormat;
-	boolean auto;
-	
-	private static final Pattern hasLettersPattern = Pattern.compile("(?i).*[a-z]");
-	private static final Pattern isAgeBasedPattern = Pattern.compile("(?i)(ago)|(min)|(hour)|(day)|(week)|(month)|(year)|([0-9](h|d|w|m|y))");
-	private static final Pattern getTimeComponent = Pattern.compile("(?i)([0-9]{2}):([0-9]{2})(:([0-9]{2}))?( ?(a|p)m)?");
-	private static final Pattern timeBasedDateWithLettersPattern = Pattern.compile("(?i)([0-9]{1,2})[^ ]{0,2}(?: |-)([a-z]{3,10})\\.?(?: |-)?([0-9]{2,4})?");
-	private static final Pattern timeBasedDateWithLettersPatternMonthFirst = Pattern.compile("(?i)([a-z]{3,10})\\.?(?: |-)?([0-9]{1,2})[^ ]{0,2}(?: |-)([0-9]{2,4})?");
-	private static final Pattern todayPattern = Pattern.compile("(?i)(t.?day)");
-	private static final Pattern yesterdayPattern = Pattern.compile("(?i)(y[a-z\\-]+day)");
-	private static final Pattern agoSpacerPattern = Pattern.compile("(?i)([0-9])([a-z])");
-	private static final Pattern agoTimeRangePattern = Pattern.compile("(?i)([0-9.]+) ([a-z\\(\\)]+)");
-	private static final Pattern numbersOnlyDatePattern = Pattern.compile("([0-9]{2,4})[ \\-\\./]([0-9]{2,4})[ \\-\\./]?([0-9]{2,4})?");
-	
-	private static final String[] MONTHS_LIST = new String[] {
-		" january janvier enero januar",
-		" february fevrier f�vrier febrero februar",
-		" march mars marzo marz marz m�rz" ,
-		" april avril abril april ",
-		" may mai mayo mai",
-		" june juin junio juni",
-		" july juillet julio juli",
-		" august aout ao�t agosto august",
-		" september septembre septiembre september",
-		" october octobre octubre oktober",
-		" november novembre noviembre november",
-		" december decembre d�cembre diciembre dezember"};
-	
-	public DateParserRegex() {
-		this("GMT-7",true,null);
-	}
-	
-	public DateParserRegex(String timeZone,boolean auto, String dateFormat) {
-		
-		this.timeZone = TimeZone.getTimeZone(timeZone);
-		this.auto = auto;
-		
-		if(!auto) {
-			if(dateFormat != null) {
-				userDateFormat = new SimpleDateFormat(dateFormat);
-				userDateFormat.setTimeZone(this.timeZone);
-			} else {
-				//TODO : in debug mode throw an Exception telling the user he needs to provide a dateFormat in manual mode
-			}
-		}
-
-	}
-	
-	public Date parseDate(String date) {
-		Date result =  null;
-		if(auto) {
-			 result = parseDateInternal(date);
-		} else {
-			if(userDateFormat != null) {
-				try {
-					result = userDateFormat.parse(date);
-				} catch(Exception e) {
-					//TODO : in debug mode, throw an exception to tell the user that his dateFormat is invalid / didn't parse a date
-				}
-			}
-		}
-		if(DEBUG && result != null) {
-			System.out.println(date + " > " + result.toString());
-		}
-		
-		return result;
-	}
-	
-	private Date parseDateInternal(final String input) {
-		
-		if(input == null) {
-			return null;
-		}
-		
-		String s = input;
-		
-		Calendar calendar = new GregorianCalendar(timeZone);
-		
-		//Find if there is any time information in the date
-		Matcher matcher = getTimeComponent.matcher(s);
-		//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()) {
-			//We have a date with letters, could be age-based or time based (with a literal month)
-			
-			//Try to determine if it is age-based or time-based
-			matcher = isAgeBasedPattern.matcher(s);
-			if(matcher.find()) {
-				//Age Based date
-				
-				matcher = todayPattern.matcher(s);
-				if(matcher.find()) {
-					//Nothing to do for today as we base our initial date on the current one
-				} else {
-					matcher = yesterdayPattern.matcher(s);
-					if(matcher.find()) {
-						calendar.add(Calendar.DATE, -1);
-					} else {
-						//We're in the real "ago" case, let's remove " ago" if it's there
-						s = s.replaceAll("ago","").trim();
-						matcher = agoSpacerPattern.matcher(s);
-						s = matcher.replaceAll("$1 $2");
-						matcher = agoTimeRangePattern.matcher(s);
-						boolean seenHoursAsLowerCaseH = false;
-						while(matcher.find()) {
-							String unit = matcher.group(2);
-							
-							if(unit.equals("h")) {
-								seenHoursAsLowerCaseH = true;
-							}
-							
-							
-							String lUnit = unit.toLowerCase();
-							float value = Float.parseFloat(matcher.group(1));
-							int intValue = (int) value;
-							if(lUnit.startsWith("sec")) {
-								calendar.add(Calendar.SECOND, -intValue);
-							} else if(lUnit.startsWith("min") || (unit.equals("m") && seenHoursAsLowerCaseH)) {
-								calendar.add(Calendar.MINUTE, -intValue);
-								int seconds = (int) ((value - intValue)*60f);
-								calendar.add(Calendar.SECOND, -seconds);
-							} else if(lUnit.startsWith("h")) {
-								calendar.add(Calendar.HOUR_OF_DAY, -intValue);
-								int seconds = (int) ((value - intValue)*3600f);
-								calendar.add(Calendar.SECOND, -seconds);
-							} else if(lUnit.startsWith("d")) {
-								calendar.add(Calendar.DATE, -intValue);
-								int seconds = (int) ((value - intValue)*86400f);
-								calendar.add(Calendar.SECOND, -seconds);
-							} else if(lUnit.startsWith("w")) {
-								calendar.add(Calendar.WEEK_OF_YEAR, -intValue);
-								//604800 seconds in a week
-								int seconds = (int) ((value - intValue)*640800f);
-								calendar.add(Calendar.SECOND, -seconds);
-							} //The month case when m is not a minute
-							  else if(lUnit.startsWith("m")) {
-								calendar.add(Calendar.MONTH, -intValue);
-								//about 720 hours per month
-								int hours = (int) ((value - intValue)*720f);
-								calendar.add(Calendar.HOUR_OF_DAY, -hours);
-							} else if(lUnit.startsWith("y")) {
-								calendar.add(Calendar.YEAR, -intValue);
-								//about 8760 hours per year
-								int hours = (int) ((value - intValue)*8760);
-								calendar.add(Calendar.HOUR_OF_DAY, -hours);
-							} else {
-								//System.out.println("Unit not matched : " + unit);
-							}
-						}
-						
-					}
-					
-				}
-				
-				//System.out.println(input + " > " + calendar.getTime());
-				
-				
-			} else {
-				//Time based date
-				//System.out.println("DL : " + s);
-				matcher = timeBasedDateWithLettersPattern.matcher(s);
-				if(matcher.find()) {
-					int day = Integer.parseInt(matcher.group(1));
-					calendar.set(Calendar.DAY_OF_MONTH,day);
-					
-					String monthStr = " " + matcher.group(2).toLowerCase();
-					int month = -1;
-					for(int i = 0 ; i < MONTHS_LIST.length ; i++) {
-						if(MONTHS_LIST[i].indexOf(monthStr) != -1) {
-							month = i;
-						}
-					}
-					if(month > -1) {
-						calendar.set(Calendar.MONTH,month);
-					}
-					
-					boolean hasYear = matcher.group(3) != null;
-					if(hasYear) {
-						int year = Integer.parseInt(matcher.group(3));
-						if(year < 100) {
-							year += 2000;
-						}
-						calendar.set(Calendar.YEAR,year);
-					}
-					
-					calendar.set(Calendar.HOUR_OF_DAY,0);
-					calendar.set(Calendar.MINUTE,0);
-					calendar.set(Calendar.SECOND,0);
-					calendar.set(Calendar.MILLISECOND,0);
-
-					//System.out.println(input + " > " + calendar.getTime() + "( " + calendar.getTimeZone() + " )");
-					
-				} else {
-					matcher = timeBasedDateWithLettersPatternMonthFirst.matcher(s);
-					if(matcher.find()) {
-						int day = Integer.parseInt(matcher.group(2));
-						calendar.set(Calendar.DAY_OF_MONTH,day);
-						
-						String monthStr = " " + matcher.group(1).toLowerCase();
-						int month = -1;
-						for(int i = 0 ; i < MONTHS_LIST.length ; i++) {
-							if(MONTHS_LIST[i].indexOf(monthStr) != -1) {
-								month = i;
-							}
-						}
-						if(month > -1) {
-							calendar.set(Calendar.MONTH,month);
-						}
-						
-						boolean hasYear = matcher.group(3) != null;
-						if(hasYear) {
-							int year = Integer.parseInt(matcher.group(3));
-							if(year < 100) {
-								year += 2000;
-							}
-							calendar.set(Calendar.YEAR,year);
-						}
-						
-						calendar.set(Calendar.HOUR_OF_DAY,0);
-						calendar.set(Calendar.MINUTE,0);
-						calendar.set(Calendar.SECOND,0);
-						calendar.set(Calendar.MILLISECOND,0);
-
-						//System.out.println(input + " > " + calendar.getTime() + "( " + calendar.getTimeZone() + " )");
-						
-					} else {
-						Date d = new DateParserClassic().parseDate( input );
-						
-						if ( d != null ){
-							return( d );
-						}
-						
-						System.err.println("DateParserRegex: Unparseable date : " + input);
-					}
-				}
-			}
-		} else {
-			//We have a date with only numbers
-			//System.out.println("DN : " + s );//+ "(" + input + ")");
-			//Let's assume a default order of m/d and switch if it doesn't make sense
-			matcher = numbersOnlyDatePattern.matcher(s);
-			if(matcher.find()) {
-				try {
-				
-					String g1 = matcher.group(1);
-					String g2 = matcher.group(2);
-					String g3 = matcher.group(3);
-					
-					int i1 = Integer.parseInt(g1);
-					int i2 = Integer.parseInt(g2);
-					
-					if(g3 != null) {
-						int i3 = Integer.parseInt(g3);
-						
-						int day = i1;
-						int month = i2;
-						int year = i3;
-						
-						if(month > 12) {
-							day = i2;
-							month = i1;
-						}
-						
-						if(year < 100) {
-							year += 2000;
-						}
-						
-						if(g1.length() == 4) {
-							year = i1;
-							day = i3;
-						}
-
-						calendar.set(Calendar.YEAR,year);
-						calendar.set(Calendar.MONTH,month-1);
-						calendar.set(Calendar.DAY_OF_MONTH,day);
-						
-					} else {
-						//2 numbers only, we assume it's day and month
-						int month = i1;
-						int day = i2;
-						if(month > 12) {
-							day = i1;
-							month = i2;
-						}
-						if(month > 12) {
-							//TODO : fire an exception ?
-							System.err.println("DateParserRegex: Unparseable date : " + input);
-						} else {
-							calendar.set(Calendar.MONTH, month-1);
-							calendar.set(Calendar.DAY_OF_MONTH, day);
-						}
-					}
-					
-					calendar.set(Calendar.HOUR_OF_DAY,0);
-					calendar.set(Calendar.MINUTE,0);
-					calendar.set(Calendar.SECOND,0);
-					calendar.set(Calendar.MILLISECOND,0);
-
-				} catch (Exception e) {
-					e.printStackTrace();
-				}
-				
-			}
-			
-			//System.out.println(input + " > " + calendar.getTime());
-		}
-		
-		//Extract the time information
-		matcher = getTimeComponent.matcher(input);
-		if(matcher.find()) {
-			try {
-				int hours = Integer.parseInt(matcher.group(1));
-				
-				int minutes = Integer.parseInt(matcher.group(2));
-				calendar.set(Calendar.MINUTE,minutes);
-				
-				boolean amPMModifier = matcher.group(5) !=  null;
-				
-				boolean hasSeconds = matcher.group(4) != null;
-				
-				if(hasSeconds) {
-					int seconds = Integer.parseInt(matcher.group(4));
-					calendar.set(Calendar.SECOND, seconds);
-				}
-				
-				if(amPMModifier) {
-					String amPm = matcher.group(5).trim().toLowerCase();
-					if(amPm.equals("am")) {
-						calendar.set(Calendar.AM_PM,Calendar.AM);
-					} else {
-						calendar.set(Calendar.AM_PM,Calendar.PM);
-					}
-					calendar.set(Calendar.HOUR, hours);
-					
-				} else {
-					calendar.set(Calendar.HOUR_OF_DAY, hours);
-				}
-			} catch(Exception e) {
-				e.printStackTrace();
-			}
-		}
-		
-		int nbBack = 0;
-		Calendar calendarCompare = new GregorianCalendar();
-		
-//		if(calendar.after(calendarCompare)) {
-//			System.err.println("maintenant ici: "+calendarCompare.getTimeInMillis()+"  --  "+calendarCompare.getTime()+"  --  "+calendarCompare);
-//			System.err.println("maintenant la bas: "+calendar.getTimeInMillis()+"  --  "+calendar.getTime()+"  --  "+calendar);
-//			System.err.println("CALENDARS: after? " + calendar.after(calendarCompare) + " // before? " + calendar.before(calendarCompare));
-//		}
-		while(calendar.after(calendarCompare) && nbBack++ < 50) {
-			calendar.add(Calendar.YEAR, -1);
-		}
-		
-		//calendar.setTimeZone(TimeZone.getDefault());
-		return calendar.getTime();
-	}
-	
-	
-	public static void main(String args[]) {
-		DEBUG = true;
-		DateParserRegex dateParser = new DateParserRegex();
-		
-		dateParser.parseDate("Today 05:34");
-		dateParser.parseDate("Y-Day 21:55");
-		dateParser.parseDate("07-25 2006");
-		dateParser.parseDate("02-01 02:53");
-		dateParser.parseDate("02-01 02:53 am");
-		dateParser.parseDate("02-01 02:53 pm");
-		dateParser.parseDate("03 Mar 2006");
-		dateParser.parseDate("0 minute ago");
-		dateParser.parseDate("3 hours ago");
-		dateParser.parseDate("2 days ago");
-		dateParser.parseDate("10 months ago");
-		dateParser.parseDate("45 mins ago");
-		dateParser.parseDate("Today");
-		dateParser.parseDate("Yesterday");
-		dateParser.parseDate("16.9w");
-		dateParser.parseDate("22.6h");
-		dateParser.parseDate("1.7d");
-		dateParser.parseDate("2d 7h");
-		dateParser.parseDate("1w");
-		dateParser.parseDate("1w 4d");
-		dateParser.parseDate("1mon 1w");
-		dateParser.parseDate("22.11.");		// 22 nov
-		dateParser.parseDate("22 Apr 08");	//
-		dateParser.parseDate("3 months");	//
-		dateParser.parseDate("1 day");		//
-		dateParser.parseDate("3 weeks");	//
-		dateParser.parseDate("1 year");		//
-		dateParser.parseDate("4 hours ago");	//
-		dateParser.parseDate("yesterday");	//
-		dateParser.parseDate("2 days ago");	//
-		dateParser.parseDate("1 month ago");	//
-		dateParser.parseDate("2 months ago");	//
-		dateParser.parseDate("06/18");		// 18 Jun
-		dateParser.parseDate("02:10");		// at 2:10am today
-		dateParser.parseDate("2005-02-26 20:55:10");	//
-		dateParser.parseDate("2005-02-26 10:55:10 PM");
-		dateParser.parseDate("2005-02-26 10:55:10 AM");
-		dateParser.parseDate("25-04-08");	//
-		dateParser.parseDate("142 Day(s) ago");	//
-		dateParser.parseDate("6 Minute(s) ago");	//
-		dateParser.parseDate("1 Hour(s) ago");	//
-		dateParser.parseDate("1.4h");		// 1.4 hours ago
-		dateParser.parseDate("3.5d");		// 3 and a half days ago
-		dateParser.parseDate("392w");		// 392 weeks ago
-		dateParser.parseDate("01st Mar");	//
-		dateParser.parseDate("19th Apr");	//
-		dateParser.parseDate("03rd Apr");	//
-		dateParser.parseDate("2nd Apr");	//
-		dateParser.parseDate("3rd Nov");	//
-		dateParser.parseDate("04-28");		//
-		dateParser.parseDate("2007-07-14");	//
-		dateParser.parseDate("2008.04.28");	//
-		dateParser.parseDate("16/04/08");	//
-		dateParser.parseDate("20-Dec-07");	//
-		dateParser.parseDate("2009-01-12 at 03:36:38" );
-		dateParser.parseDate("2013-08-11T18:30:00.000Z" );
-	}
-	
-
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class DateParserRegex extends DateParser {
+	
+	static boolean DEBUG = false;
+	
+	TimeZone timeZone;
+	DateFormat userDateFormat;
+	boolean auto;
+	
+	private static final Pattern hasLettersPattern = Pattern.compile("(?i).*[a-z]");
+	private static final Pattern isAgeBasedPattern = Pattern.compile("(?i)(ago)|(min)|(hour)|(day)|(week)|(month)|(year)|([0-9](h|d|w|m|y))");
+	private static final Pattern getTimeComponent = Pattern.compile("(?i)([0-9]{2}):([0-9]{2})(:([0-9]{2}))?( ?(a|p)m)?");
+	private static final Pattern timeBasedDateWithLettersPattern = Pattern.compile("(?i)([0-9]{1,2})[^ ]{0,2}(?: |-)([a-z]{3,10})\\.?(?: |-)?([0-9]{2,4})?");
+	private static final Pattern timeBasedDateWithLettersPatternMonthFirst = Pattern.compile("(?i)([a-z]{3,10})\\.?(?: |-)?([0-9]{1,2})[^ ]{0,2}(?: |-)([0-9]{2,4})?");
+	private static final Pattern todayPattern = Pattern.compile("(?i)(t.?day)");
+	private static final Pattern yesterdayPattern = Pattern.compile("(?i)(y[a-z\\-]+day)");
+	private static final Pattern agoSpacerPattern = Pattern.compile("(?i)([0-9])([a-z])");
+	private static final Pattern agoTimeRangePattern = Pattern.compile("(?i)([0-9.]+) ([a-z\\(\\)]+)");
+	private static final Pattern numbersOnlyDatePattern = Pattern.compile("([0-9]{2,4})[ \\-\\./]([0-9]{2,4})[ \\-\\./]?([0-9]{2,4})?");
+	
+	private static final String[] MONTHS_LIST = new String[] {
+		" january janvier enero januar",
+		" february fevrier f�vrier febrero februar",
+		" march mars marzo marz marz m�rz" ,
+		" april avril abril april ",
+		" may mai mayo mai",
+		" june juin junio juni",
+		" july juillet julio juli",
+		" august aout ao�t agosto august",
+		" september septembre septiembre september",
+		" october octobre octubre oktober",
+		" november novembre noviembre november",
+		" december decembre d�cembre diciembre dezember"};
+	
+	public DateParserRegex() {
+		this("GMT-7",true,null);
+	}
+	
+	public DateParserRegex(String timeZone,boolean auto, String dateFormat) {
+		
+		this.timeZone = TimeZone.getTimeZone(timeZone);
+		this.auto = auto;
+		
+		if(!auto) {
+			if(dateFormat != null) {
+				userDateFormat = new SimpleDateFormat(dateFormat);
+				userDateFormat.setTimeZone(this.timeZone);
+			} else {
+				//TODO : in debug mode throw an Exception telling the user he needs to provide a dateFormat in manual mode
+			}
+		}
+
+	}
+	
+	public Date parseDate(String date) {
+		Date result =  null;
+		if(auto) {
+			 result = parseDateInternal(date);
+		} else {
+			if(userDateFormat != null) {
+				try {
+					result = userDateFormat.parse(date);
+				} catch(Exception e) {
+					//TODO : in debug mode, throw an exception to tell the user that his dateFormat is invalid / didn't parse a date
+				}
+			}
+		}
+		if(DEBUG && result != null) {
+			System.out.println(date + " > " + result.toString());
+		}
+		
+		return result;
+	}
+	
+	private Date parseDateInternal(final String input) {
+		
+		if(input == null) {
+			return null;
+		}
+		
+		String s = input;
+		
+		Calendar calendar = new GregorianCalendar(timeZone);
+		
+		//Find if there is any time information in the date
+		Matcher matcher = getTimeComponent.matcher(s);
+		//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()) {
+			//We have a date with letters, could be age-based or time based (with a literal month)
+			
+			//Try to determine if it is age-based or time-based
+			matcher = isAgeBasedPattern.matcher(s);
+			if(matcher.find()) {
+				//Age Based date
+				
+				matcher = todayPattern.matcher(s);
+				if(matcher.find()) {
+					//Nothing to do for today as we base our initial date on the current one
+				} else {
+					matcher = yesterdayPattern.matcher(s);
+					if(matcher.find()) {
+						calendar.add(Calendar.DATE, -1);
+					} else {
+						//We're in the real "ago" case, let's remove " ago" if it's there
+						s = s.replaceAll("ago","").trim();
+						matcher = agoSpacerPattern.matcher(s);
+						s = matcher.replaceAll("$1 $2");
+						matcher = agoTimeRangePattern.matcher(s);
+						boolean seenHoursAsLowerCaseH = false;
+						while(matcher.find()) {
+							String unit = matcher.group(2);
+							
+							if(unit.equals("h")) {
+								seenHoursAsLowerCaseH = true;
+							}
+							
+							
+							String lUnit = unit.toLowerCase();
+							float value = Float.parseFloat(matcher.group(1));
+							int intValue = (int) value;
+							if(lUnit.startsWith("sec")) {
+								calendar.add(Calendar.SECOND, -intValue);
+							} else if(lUnit.startsWith("min") || (unit.equals("m") && seenHoursAsLowerCaseH)) {
+								calendar.add(Calendar.MINUTE, -intValue);
+								int seconds = (int) ((value - intValue)*60f);
+								calendar.add(Calendar.SECOND, -seconds);
+							} else if(lUnit.startsWith("h")) {
+								calendar.add(Calendar.HOUR_OF_DAY, -intValue);
+								int seconds = (int) ((value - intValue)*3600f);
+								calendar.add(Calendar.SECOND, -seconds);
+							} else if(lUnit.startsWith("d")) {
+								calendar.add(Calendar.DATE, -intValue);
+								int seconds = (int) ((value - intValue)*86400f);
+								calendar.add(Calendar.SECOND, -seconds);
+							} else if(lUnit.startsWith("w")) {
+								calendar.add(Calendar.WEEK_OF_YEAR, -intValue);
+								//604800 seconds in a week
+								int seconds = (int) ((value - intValue)*640800f);
+								calendar.add(Calendar.SECOND, -seconds);
+							} //The month case when m is not a minute
+							  else if(lUnit.startsWith("m")) {
+								calendar.add(Calendar.MONTH, -intValue);
+								//about 720 hours per month
+								int hours = (int) ((value - intValue)*720f);
+								calendar.add(Calendar.HOUR_OF_DAY, -hours);
+							} else if(lUnit.startsWith("y")) {
+								calendar.add(Calendar.YEAR, -intValue);
+								//about 8760 hours per year
+								int hours = (int) ((value - intValue)*8760);
+								calendar.add(Calendar.HOUR_OF_DAY, -hours);
+							} else {
+								//System.out.println("Unit not matched : " + unit);
+							}
+						}
+						
+					}
+					
+				}
+				
+				//System.out.println(input + " > " + calendar.getTime());
+				
+				
+			} else {
+				//Time based date
+				//System.out.println("DL : " + s);
+				matcher = timeBasedDateWithLettersPattern.matcher(s);
+				if(matcher.find()) {
+					int day = Integer.parseInt(matcher.group(1));
+					calendar.set(Calendar.DAY_OF_MONTH,day);
+					
+					String monthStr = " " + matcher.group(2).toLowerCase();
+					int month = -1;
+					for(int i = 0 ; i < MONTHS_LIST.length ; i++) {
+						if(MONTHS_LIST[i].indexOf(monthStr) != -1) {
+							month = i;
+						}
+					}
+					if(month > -1) {
+						calendar.set(Calendar.MONTH,month);
+					}
+					
+					boolean hasYear = matcher.group(3) != null;
+					if(hasYear) {
+						int year = Integer.parseInt(matcher.group(3));
+						if(year < 100) {
+							year += 2000;
+						}
+						calendar.set(Calendar.YEAR,year);
+					}
+					
+					calendar.set(Calendar.HOUR_OF_DAY,0);
+					calendar.set(Calendar.MINUTE,0);
+					calendar.set(Calendar.SECOND,0);
+					calendar.set(Calendar.MILLISECOND,0);
+
+					//System.out.println(input + " > " + calendar.getTime() + "( " + calendar.getTimeZone() + " )");
+					
+				} else {
+					matcher = timeBasedDateWithLettersPatternMonthFirst.matcher(s);
+					if(matcher.find()) {
+						int day = Integer.parseInt(matcher.group(2));
+						calendar.set(Calendar.DAY_OF_MONTH,day);
+						
+						String monthStr = " " + matcher.group(1).toLowerCase();
+						int month = -1;
+						for(int i = 0 ; i < MONTHS_LIST.length ; i++) {
+							if(MONTHS_LIST[i].indexOf(monthStr) != -1) {
+								month = i;
+							}
+						}
+						if(month > -1) {
+							calendar.set(Calendar.MONTH,month);
+						}
+						
+						boolean hasYear = matcher.group(3) != null;
+						if(hasYear) {
+							int year = Integer.parseInt(matcher.group(3));
+							if(year < 100) {
+								year += 2000;
+							}
+							calendar.set(Calendar.YEAR,year);
+						}
+						
+						calendar.set(Calendar.HOUR_OF_DAY,0);
+						calendar.set(Calendar.MINUTE,0);
+						calendar.set(Calendar.SECOND,0);
+						calendar.set(Calendar.MILLISECOND,0);
+
+						//System.out.println(input + " > " + calendar.getTime() + "( " + calendar.getTimeZone() + " )");
+						
+					} else {
+						Date d = new DateParserClassic().parseDate( input );
+						
+						if ( d != null ){
+							return( d );
+						}
+						
+						System.err.println("DateParserRegex: Unparseable date : " + input);
+					}
+				}
+			}
+		} else {
+			//We have a date with only numbers
+			//System.out.println("DN : " + s );//+ "(" + input + ")");
+			//Let's assume a default order of m/d and switch if it doesn't make sense
+			matcher = numbersOnlyDatePattern.matcher(s);
+			if(matcher.find()) {
+				try {
+				
+					String g1 = matcher.group(1);
+					String g2 = matcher.group(2);
+					String g3 = matcher.group(3);
+					
+					int i1 = Integer.parseInt(g1);
+					int i2 = Integer.parseInt(g2);
+					
+					if(g3 != null) {
+						int i3 = Integer.parseInt(g3);
+						
+						int day = i1;
+						int month = i2;
+						int year = i3;
+						
+						if(month > 12) {
+							day = i2;
+							month = i1;
+						}
+						
+						if(year < 100) {
+							year += 2000;
+						}
+						
+						if(g1.length() == 4) {
+							year = i1;
+							day = i3;
+						}
+
+						calendar.set(Calendar.YEAR,year);
+						calendar.set(Calendar.MONTH,month-1);
+						calendar.set(Calendar.DAY_OF_MONTH,day);
+						
+					} else {
+						//2 numbers only, we assume it's day and month
+						int month = i1;
+						int day = i2;
+						if(month > 12) {
+							day = i1;
+							month = i2;
+						}
+						if(month > 12) {
+							//TODO : fire an exception ?
+							System.err.println("DateParserRegex: Unparseable date : " + input);
+						} else {
+							calendar.set(Calendar.MONTH, month-1);
+							calendar.set(Calendar.DAY_OF_MONTH, day);
+						}
+					}
+					
+					calendar.set(Calendar.HOUR_OF_DAY,0);
+					calendar.set(Calendar.MINUTE,0);
+					calendar.set(Calendar.SECOND,0);
+					calendar.set(Calendar.MILLISECOND,0);
+
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+				
+			}
+			
+			//System.out.println(input + " > " + calendar.getTime());
+		}
+		
+		//Extract the time information
+		matcher = getTimeComponent.matcher(input);
+		if(matcher.find()) {
+			try {
+				int hours = Integer.parseInt(matcher.group(1));
+				
+				int minutes = Integer.parseInt(matcher.group(2));
+				calendar.set(Calendar.MINUTE,minutes);
+				
+				boolean amPMModifier = matcher.group(5) !=  null;
+				
+				boolean hasSeconds = matcher.group(4) != null;
+				
+				if(hasSeconds) {
+					int seconds = Integer.parseInt(matcher.group(4));
+					calendar.set(Calendar.SECOND, seconds);
+				}
+				
+				if(amPMModifier) {
+					String amPm = matcher.group(5).trim().toLowerCase();
+					if(amPm.equals("am")) {
+						calendar.set(Calendar.AM_PM,Calendar.AM);
+					} else {
+						calendar.set(Calendar.AM_PM,Calendar.PM);
+					}
+					calendar.set(Calendar.HOUR, hours);
+					
+				} else {
+					calendar.set(Calendar.HOUR_OF_DAY, hours);
+				}
+			} catch(Exception e) {
+				e.printStackTrace();
+			}
+		}
+		
+		int nbBack = 0;
+		Calendar calendarCompare = new GregorianCalendar();
+		
+//		if(calendar.after(calendarCompare)) {
+//			System.err.println("maintenant ici: "+calendarCompare.getTimeInMillis()+"  --  "+calendarCompare.getTime()+"  --  "+calendarCompare);
+//			System.err.println("maintenant la bas: "+calendar.getTimeInMillis()+"  --  "+calendar.getTime()+"  --  "+calendar);
+//			System.err.println("CALENDARS: after? " + calendar.after(calendarCompare) + " // before? " + calendar.before(calendarCompare));
+//		}
+		while(calendar.after(calendarCompare) && nbBack++ < 50) {
+			calendar.add(Calendar.YEAR, -1);
+		}
+		
+		//calendar.setTimeZone(TimeZone.getDefault());
+		return calendar.getTime();
+	}
+	
+	
+	public static void main(String args[]) {
+		DEBUG = true;
+		DateParserRegex dateParser = new DateParserRegex();
+		
+		dateParser.parseDate("Today 05:34");
+		dateParser.parseDate("Y-Day 21:55");
+		dateParser.parseDate("07-25 2006");
+		dateParser.parseDate("02-01 02:53");
+		dateParser.parseDate("02-01 02:53 am");
+		dateParser.parseDate("02-01 02:53 pm");
+		dateParser.parseDate("03 Mar 2006");
+		dateParser.parseDate("0 minute ago");
+		dateParser.parseDate("3 hours ago");
+		dateParser.parseDate("2 days ago");
+		dateParser.parseDate("10 months ago");
+		dateParser.parseDate("45 mins ago");
+		dateParser.parseDate("Today");
+		dateParser.parseDate("Yesterday");
+		dateParser.parseDate("16.9w");
+		dateParser.parseDate("22.6h");
+		dateParser.parseDate("1.7d");
+		dateParser.parseDate("2d 7h");
+		dateParser.parseDate("1w");
+		dateParser.parseDate("1w 4d");
+		dateParser.parseDate("1mon 1w");
+		dateParser.parseDate("22.11.");		// 22 nov
+		dateParser.parseDate("22 Apr 08");	//
+		dateParser.parseDate("3 months");	//
+		dateParser.parseDate("1 day");		//
+		dateParser.parseDate("3 weeks");	//
+		dateParser.parseDate("1 year");		//
+		dateParser.parseDate("4 hours ago");	//
+		dateParser.parseDate("yesterday");	//
+		dateParser.parseDate("2 days ago");	//
+		dateParser.parseDate("1 month ago");	//
+		dateParser.parseDate("2 months ago");	//
+		dateParser.parseDate("06/18");		// 18 Jun
+		dateParser.parseDate("02:10");		// at 2:10am today
+		dateParser.parseDate("2005-02-26 20:55:10");	//
+		dateParser.parseDate("2005-02-26 10:55:10 PM");
+		dateParser.parseDate("2005-02-26 10:55:10 AM");
+		dateParser.parseDate("25-04-08");	//
+		dateParser.parseDate("142 Day(s) ago");	//
+		dateParser.parseDate("6 Minute(s) ago");	//
+		dateParser.parseDate("1 Hour(s) ago");	//
+		dateParser.parseDate("1.4h");		// 1.4 hours ago
+		dateParser.parseDate("3.5d");		// 3 and a half days ago
+		dateParser.parseDate("392w");		// 392 weeks ago
+		dateParser.parseDate("01st Mar");	//
+		dateParser.parseDate("19th Apr");	//
+		dateParser.parseDate("03rd Apr");	//
+		dateParser.parseDate("2nd Apr");	//
+		dateParser.parseDate("3rd Nov");	//
+		dateParser.parseDate("04-28");		//
+		dateParser.parseDate("2007-07-14");	//
+		dateParser.parseDate("2008.04.28");	//
+		dateParser.parseDate("16/04/08");	//
+		dateParser.parseDate("20-Dec-07");	//
+		dateParser.parseDate("2009-01-12 at 03:36:38" );
+		dateParser.parseDate("2013-08-11T18:30:00.000Z" );
+	}
+	
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/EngineImpl.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/EngineImpl.java
index d3269f0..9ea8489 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/EngineImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/EngineImpl.java
@@ -1,1621 +1,1620 @@
-/*
- * Created on May 6, 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.core.metasearch.impl;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.URLDecoder;
-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;
-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.UrlUtils;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-
-import com.aelitis.azureus.core.messenger.config.PlatformMetaSearchMessenger;
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.Result;
-import com.aelitis.azureus.core.metasearch.ResultListener;
-import com.aelitis.azureus.core.metasearch.SearchException;
-import com.aelitis.azureus.core.metasearch.SearchLoginException;
-import com.aelitis.azureus.core.metasearch.SearchParameter;
-import com.aelitis.azureus.core.metasearch.impl.plugin.PluginEngine;
-import com.aelitis.azureus.core.metasearch.impl.web.json.JSONEngine;
-import com.aelitis.azureus.core.metasearch.impl.web.regex.RegexEngine;
-import com.aelitis.azureus.core.metasearch.impl.web.rss.RSSEngine;
-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.util.ConstantsVuze;
-import com.aelitis.azureus.util.ImportExportUtils;
-import com.aelitis.azureus.util.JSONUtils;
-
-
-public abstract class 
-EngineImpl
-	implements Engine
-{
-	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,
-		Map					map )
-	
-		throws IOException
-	{
-		int	type = ((Long)map.get( "type" )).intValue();
-		
-		if ( type == Engine.ENGINE_TYPE_JSON ){
-			
-			return( JSONEngine.importFromBEncodedMap( meta_search, map ));
-			
-		}else if ( type == Engine.ENGINE_TYPE_REGEX ){
-			
-			return( RegexEngine.importFromBEncodedMap( meta_search, map ));
-			
-		}else if ( type == Engine.ENGINE_TYPE_PLUGIN ){
-			
-			return( PluginEngine.importFromBEncodedMap( meta_search, map ));
-			
-		}else if ( type == Engine.ENGINE_TYPE_RSS ){
-			
-			return( RSSEngine.importFromBEncodedMap( meta_search, map ));
-			
-		}else{
-			
-			throw( new IOException( "Unknown engine type " + type ));
-		}
-	}
-	
-	public static Engine
-	importFromJSONString(
-		MetaSearchImpl	meta_search,
-		int				type,
-		long			id,
-		long			last_updated,
-		float			rank_bias,
-		String			name,
-		String			content )
-	
-		throws IOException
-	{
-		JSONObject map = (JSONObject)JSONUtils.decodeJSON( content );
-		
-		if ( type == Engine.ENGINE_TYPE_JSON ){
-			
-			return( JSONEngine.importFromJSONString( meta_search, id, last_updated, rank_bias, name, map ));
-			
-		}else if ( type == Engine.ENGINE_TYPE_REGEX ){
-			
-			return( RegexEngine.importFromJSONString( meta_search, id, last_updated, rank_bias, name, map ));
-			
-		}else if ( type == Engine.ENGINE_TYPE_RSS ){
-			
-			return( RSSEngine.importFromJSONString( meta_search, id, last_updated, rank_bias, name, map ));
-			
-		}else{
-			
-			throw( new IOException( "Unknown engine type " + type ));
-		}	
-	}
-	
-		// if you extend this with state pertaining to what has been downloaded then
-		// make sure you extend the code in reset();
-	
-	protected static final String		LD_COOKIES				= "cookies";
-	protected static final String		LD_ETAG					= "etag";
-	protected static final String		LD_LAST_MODIFIED		= "last_mod";
-	
-	protected static final String		LD_LAST_UPDATE_CHECK	= "last_update_check";
-	protected static final String		LD_UPDATE_CHECK_SECS	= "update_check_secs";
-	protected static final String		LD_CREATED_BY_ME		= "mine";
-	
-	protected static final String		LD_AUTO_DL_SUPPORTED	= "auto_dl_supported";
-	protected static final String		LD_LINK_IS_TORRENT		= "link_is_torrent";
-
-	
-	private MetaSearchImpl	meta_search;
-	
-	private int			type;
-	private long		id;
-	private long		last_updated;
-	private String		name;
-	
-	private byte[]		uid;
-	private int			version;
-	
-	private boolean		is_public					= true;
-	
-	private int			az_version;
-	
-	private int			selection_state				= SEL_STATE_DESELECTED;
-	private boolean		selection_state_recorded	= true;
-	
-	private int			source	= ENGINE_SOURCE_UNKNOWN;
-	
-	private float		rank_bias		= 1;
-	private float		preferred_count	= 0;
-	
-	
-		// first mappings used to canonicalise names and map field to same field
-		// typically used for categories (musak->music)
-	
-	private List		first_level_mapping	= new ArrayList();
-	
-		// second mappings used to generate derived field values
-		// typically used to derive content_type from category (music->AUDIO)
-	
-	private List		second_level_mapping	= new ArrayList();
-
-		// applicable to non-vuze hosted templates
-	
-	private String 		update_url;
-	private int			update_check_default_secs;
-	
-	private Map			user_data;
-	
-		// manual constructor
-	
-	protected
-	EngineImpl(
-		MetaSearchImpl	_meta_search,
-		int 			_type, 
-		long 			_id,
-		long			_last_updated,
-		float			_rank_bias,
-		String 			_name )
-	{
-		meta_search		= _meta_search;
-		type			= _type;
-		id				= _id;
-		last_updated	= _last_updated;
-		rank_bias		= _rank_bias;
-		name			= _name;
-		
-		version			= 1;
-		az_version		= AZ_VERSION;
-			
-		allocateUID( id );
-	}
-	
-		// bencoded constructor
-	
-	protected 
-	EngineImpl(
-		MetaSearchImpl	_meta_search,
-		Map				map )
-	
-		throws IOException
-	{
-		meta_search		= _meta_search;
-		
-		type			= ((Long)map.get( "type" )).intValue();
-		
-		Long l_id = (Long)map.get( "id");
-		
-		id				= l_id==null?meta_search.getManager().getLocalTemplateID():l_id.longValue();
-		last_updated	= ImportExportUtils.importLong( map, "last_updated" );
-		name			= ImportExportUtils.importString( map, "name" );
-		
-		selection_state	= (int)ImportExportUtils.importLong( map, "selected", SEL_STATE_DESELECTED );
-		
-		selection_state_recorded = ImportExportUtils.importBoolean(map,"select_rec", true );
-		
-		source			= (int)ImportExportUtils.importLong( map, "source", ENGINE_SOURCE_UNKNOWN );
-		
-		rank_bias		= ImportExportUtils.importFloat( map, "rank_bias", 1.0f );
-		preferred_count	= ImportExportUtils.importFloat( map, "pref_count", 0.0f );
-		
-		first_level_mapping 	= importBEncodedMappings( map, "l1_map" );
-		second_level_mapping 	= importBEncodedMappings( map, "l2_map" );
-		
-		version = (int)ImportExportUtils.importLong( map, "version", 1 );
-		
-		az_version = (int)ImportExportUtils.importLong( map, "az_version", AZ_VERSION );
-
-		if ( az_version > AZ_VERSION ){
-			
-			throw( new IOException( MessageText.getString("metasearch.template.version.bad", new String[]{ name })));
-		}
-		
-		uid		= (byte[])map.get( "uid" );
-		
-		if ( uid == null ){
-			
-			allocateUID( id );
-		}
-		
-		update_url 					= ImportExportUtils.importString( map, "update_url" );
-		update_check_default_secs	= (int)ImportExportUtils.importLong( map, "update_url_check_secs", DEFAULT_UPDATE_CHECK_SECS );
-	}
-	
-		// bencoded export
-	
-	protected void
-	exportToBencodedMap(
-		Map			map,
-		boolean		generic )
-	
-		throws IOException
-	{
-		map.put( "type", new Long( type ));
-		
-		ImportExportUtils.exportString( map, "name", name );
-		
-		map.put( "source", new Long( source ));
-
-		exportBEncodedMappings( map, "l1_map", first_level_mapping );
-		exportBEncodedMappings( map, "l2_map", second_level_mapping );
-
-		map.put( "version", new Long( version ));
-		map.put( "az_version", new Long( az_version ));
-
-		ImportExportUtils.exportFloat( map, "rank_bias", rank_bias );
-
-		if ( !generic ){
-			
-			map.put( "id", new Long( id ));
-			
-			map.put( "last_updated", new Long( last_updated ));
-		
-			map.put( "selected", new Long( selection_state ));
-		
-			ImportExportUtils.exportBoolean( map, "select_rec", selection_state_recorded );
-			
-			ImportExportUtils.exportFloat( map, "pref_count", preferred_count );
-		
-			map.put( "uid", uid );
-		}
-		
-		if ( update_url != null ){
-		
-			ImportExportUtils.exportString( map, "update_url", update_url );
-		}
-		
-		if ( update_check_default_secs != DEFAULT_UPDATE_CHECK_SECS ){
-			map.put( "update_url_check_secs", new Long( update_check_default_secs ));
-		}
-	}
-	
-		// json constructor
-	
-	protected 
-	EngineImpl(
-		MetaSearchImpl	meta_search,
-		int				type,
-		long			id,
-		long			last_updated,
-		float			rank_bias,
-		String			name,
-		JSONObject		map )
-	
-		throws IOException
-	{
-		this( meta_search, type, id, last_updated, rank_bias, name );
-		
-		first_level_mapping 	= importJSONMappings( map, "value_map", true );
-		second_level_mapping 	= importJSONMappings( map, "ctype_map", false );
-		
-		version 	= (int)ImportExportUtils.importLong( map, "version", 1 );
-		az_version 	= (int)ImportExportUtils.importLong( map, "az_version", AZ_VERSION );
-		
-		if ( az_version > AZ_VERSION ){
-			
-			throw( new IOException( MessageText.getString( "metasearch.template.version.bad", new String[]{ name })));
-		}
-		
-		String uid_str		= (String)map.get( "uid" );
-		
-		if ( uid_str == null ){
-			
-			allocateUID( id );
-			
-		}else{
-			
-			uid = Base32.decode( uid_str );
-		}
-		
-		update_url 					= ImportExportUtils.importString( map, "update_url" );
-		update_check_default_secs	= (int)ImportExportUtils.importLong( map, "update_url_check_secs", DEFAULT_UPDATE_CHECK_SECS );
-	}
-	
-		// json export
-	
-	protected void
-	exportToJSONObject(
-		JSONObject		res )
-	
-		throws IOException
-	{
-		exportJSONMappings( res, "value_map", first_level_mapping, true );
-		exportJSONMappings( res, "ctype_map", second_level_mapping, false );
-		
-		res.put( "version", new Long( version ));
-		res.put( "az_version", new Long( az_version ));
-		
-		res.put( "uid", Base32.encode( uid ));
-		
-		if ( update_url != null ){
-			
-			ImportExportUtils.exportJSONString( res, "update_url", update_url );
-		}
-		
-		res.put( "update_url_check_secs", new Long( update_check_default_secs ));
-	}
-	
-	protected List
-	importJSONMappings(
-		JSONObject		map,
-		String			str,
-		boolean			level_1 )
-	
-		throws IOException
-	{
-		List	result = new ArrayList();
-			
-		JSONObject	field_map = (JSONObject)map.get( str );
-		
-		if ( field_map != null ){
-			
-			Iterator	it = field_map.entrySet().iterator();
-			
-			while( it.hasNext()){
-				
-				Map.Entry	entry = (Map.Entry)it.next();
-				
-				String	key 		= (String)entry.getKey();
-				List	mappings 	= (List)entry.getValue();
-				
-					// limited support for the moment: 
-					//		level one always maps to same field
-					//		level two always maps to content type
-				
-				int	from_field 	= vuzeFieldToID( key );
-				
-				if ( from_field == -1 ){
-					
-					log( "Unrecognised remapping key '" + key + "'" );
-					
-					continue;
-				
-				}
-				
-				int	to_field	= level_1?from_field:FIELD_CONTENT_TYPE;
-				
-				List	frs_l = new ArrayList();
-				
-				for (int i=0;i<mappings.size();i++){
-					
-					JSONObject mapping = (JSONObject)mappings.get(i);
-					
-					String	from_str 	= URLDecoder.decode((String)mapping.get( level_1?"from_string":"cat_string" ),"UTF-8");
-
-					if ( from_str == null ){
-						
-						log( "'from' value missing in " + mapping );
-						
-						continue;
-					}
-					
-					from_str 	= URLDecoder.decode( from_str, "UTF-8" );
-					
-					String	to_str 		= URLDecoder.decode((String)mapping.get( level_1?"to_string":"media_type" ),"UTF-8");
-					
-					if ( to_str == null ){
-						
-						log( "'to' value missing in " + mapping );
-						
-						continue;
-					}
-					
-					frs_l.add( new FieldRemapping( from_str, to_str ));
-				}
-				
-				FieldRemapping[] frs = (FieldRemapping[])frs_l.toArray( new FieldRemapping[frs_l.size()]);
-
-				result.add( new FieldRemapper( from_field, to_field, frs ));
-			}
-		}
-		
-		return( result );
-	}
-	
-	protected void
-	exportJSONMappings(
-		JSONObject			res,
-		String				str,
-		List				l,
-		boolean				level_1 )
-	{
-		JSONObject	field_map = new JSONObject();
-		
-		res.put( str, field_map );
-		
-		for (int i=0;i<l.size();i++){
-			
-			FieldRemapper remapper = (FieldRemapper)l.get(i);
-			
-			int	from_field	= remapper.getInField();
-			//int	to_field	= remapper.getOutField();
-			
-			String from_field_str = vuzeIDToField( from_field );
-			
-			JSONArray	mappings = new JSONArray();
-			
-			field_map.put( from_field_str, mappings );
-			
-			FieldRemapping[] frs = remapper.getMappings();
-			
-			for (int j=0;j<frs.length;j++){
-				
-				FieldRemapping fr = frs[j];
-				
-				String from_str = UrlUtils.encode( fr.getMatchString());
-				
-				String to_str	= fr.getReplacement();
-				
-				JSONObject map = new JSONObject();
-				
-				mappings.add( map );
-				
-				map.put( level_1?"from_string":"cat_string", from_str );
-				map.put( level_1?"to_string":"media_type", to_str );
-			}
-		}
-	}
-			
-	protected List
-	importBEncodedMappings(
-		Map		map,
-		String	name )
-	
-		throws IOException
-	{
-		List	result = new ArrayList();
-		
-		List	l = (List)map.get(name);
-		
-		if ( l != null ){
-			
-			for (int i=0;i<l.size();i++){
-				
-				Map	entry = (Map)l.get(i);
-				
-				int	from_field 	= ((Long)entry.get( "from" )).intValue();
-				int	to_field 	= ((Long)entry.get( "to" )).intValue();
-				
-				List	l2 = (List)entry.get( "maps" );
-				
-				FieldRemapping[]	mappings = new FieldRemapping[ l2.size() ];
-				
-				for (int j=0;j<mappings.length;j++){
-					
-					Map	entry2 = (Map)l2.get(j);
-					
-					String	from_str 	= ImportExportUtils.importString( entry2, "from" );
-					String	to_str 		= ImportExportUtils.importString( entry2, "to" );
-					
-					mappings[j] = new FieldRemapping( from_str, to_str );
-				}
-				
-				result.add( new FieldRemapper( from_field, to_field, mappings ));
-			}
-		}
-		
-		return( result );
-	}
-	
-	protected void
-	exportBEncodedMappings(
-		Map		map,
-		String	name,
-		List	mappings )
-	
-		throws IOException
-	{
-		List	l = new ArrayList();
-		
-		map.put( name, l );
-		
-		for ( int i=0;i<mappings.size();i++){
-			
-			FieldRemapper mapper = (FieldRemapper)mappings.get(i);
-			
-			Map m = new HashMap();
-			
-			l.add( m );
-			
-			m.put( "from", new Long( mapper.getInField()));
-			m.put( "to", new Long( mapper.getOutField()));
-			
-			List l2 = new ArrayList();
-			
-			m.put( "maps", l2 );
-			
-			FieldRemapping[] frs = mapper.getMappings();
-			
-			for (int j=0;j<frs.length;j++){
-				
-				FieldRemapping fr = frs[j];
-				
-				Map m2 = new HashMap();
-				
-				l2.add( m2 );
-				
-				ImportExportUtils.exportString( m2, "from", fr.getMatchString());
-				ImportExportUtils.exportString( m2, "to", fr.getReplacement());
-			}
-		}
-	}
-	
-	public String
-	exportToJSONString()
-	
-		throws IOException
-	{
-		JSONObject	obj = new JSONObject();
-		
-		exportToJSONObject( obj );
-		
-		return( obj.toString());
-	}
-	
-	public int
-	getAZVersion()
-	{
-		return( az_version );
-	}
-	
-	public int
-	getVersion()
-	{
-		return( version );
-	}
-	
-	protected void
-	setVersion(
-		int		_v )
-	{
-		version	= _v;
-	}
-	
-	public String
-	getUID()
-	{
-		return( Base32.encode( uid ));
-	}
-	
-	protected void
-	setUID(
-		String	str )
-	{
-		uid	= Base32.decode( str );
-	}
-	
-	protected void
-	allocateUID(
-		long		id )
-	{
-		uid = new byte[10];
-
-		if ( id >= 0 && id < Integer.MAX_VALUE ){
-		
-				// id is a vuze one, derive uid from it as already unique
-			
-			uid[0] 	= (byte)(id>>24);
-			uid[1]	= (byte)(id>>16);
-			uid[2]	= (byte)(id>>8);
-			uid[3]	= (byte)id;
-
-		}else{
-	
-			RandomUtils.nextSecureBytes( uid );
-			
-			configDirty();
-		}
-	}
-
-	public boolean
-	sameLogicAs(
-		Engine	other )
-	{
-		try{
-			Map	m1 = exportToBencodedMap();
-			Map	m2 = other.exportToBencodedMap();
-		
-			String[]	to_remove = 
-				{	"type", 
-					"id", 
-					"last_updated",
-					"selected",
-					"select_rec",
-					"source",
-					"rank_bias",
-					"pref_count",
-					"version", 
-					"az_version", 
-					"uid" };
-			
-			for (int i=0;i<to_remove.length;i++){
-				
-				m1.remove( to_remove[i] );
-				m2.remove( to_remove[i] );
-			}
-			
-			return( BEncoder.mapsAreIdentical( m1, m2 ));
-			
-		}catch( Throwable e ){
-			
-			Debug.printStackTrace(e);
-			
-			return( false );
-		}
-	}
-		
-	public Result[]
-	search(
-		SearchParameter[] 		params,
-		Map						context,
-		int						desired_max_matches,
-		int						absolute_max_matches,
-		String					headers,
-		final ResultListener	listener )
-	
-		throws SearchException
-	{
-		if ( context == null ){
-			
-			context = new HashMap();
-		}
-		
-		try{
-			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 ){
-				
-				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];
-				}
-				
-				if ( inform_result.size() > 0 ){
-				
-					listener.resultsReceived( this, inform_result.toArray( new Result[ inform_result.size()] ));
-				}
-				
-				if ( inform_complete ){
-				
-					listener.resultsComplete( this );
-				}
-			}
-			
-			return( results );
-			
-		}catch( Throwable e ){
-			
-			if ( e instanceof SearchLoginException ){
-				
-				if ( listener != null ){
-				
-					listener.engineRequiresLogin(this, e);
-				}
-				
-				throw((SearchLoginException)e);
-				
-			}else if ( e instanceof SearchException ){
-				
-				if ( listener != null ){
-				
-					listener.engineFailed( this, e);
-				}
-				
-				throw((SearchException)e);
-				
-			}else{
-				
-				if ( listener != null ){
-				
-					listener.engineFailed( this, e);
-				}
-				
-				throw( new SearchException( "Search failed", e ));
-			}
-		}
-	}
-	
-	protected Result[]
-	searchAndMap(
-		SearchParameter[] 			params,
-		Map							context,
-		int							desired_max_matches,
-		int							absolute_max_matches,
-		String						headers,
-		final ResultListener		listener )
-	
-		throws SearchException
-	{
-			// default values
-		
-		context.put( Engine.SC_AZID, 	ConstantsVuze.AZID );
-
-		if ( context.get( Engine.SC_SOURCE ) == null ){
-			
-			context.put( Engine.SC_SOURCE, "search" );
-		}
-		
-		Result[] results = 
-			 searchSupport( 
-					params, 
-					context,
-					desired_max_matches,
-					absolute_max_matches,
-					headers, 
-					new ResultListener()
-					{
-						public void 
-						contentReceived(
-							Engine 		engine, 
-							String 		content )
-						{
-							if ( listener != null ){
-								listener.contentReceived(engine, content);
-							}
-						}
-					
-						public void 
-						matchFound( 
-							Engine 		engine, 
-							String[] 	fields )
-						{
-							if ( listener != null ){
-								listener.matchFound(engine, fields);
-							}
-						}
-						
-						public void 
-						resultsReceived(
-							Engine 		engine,
-							Result[] 	results)
-						{
-							if ( listener != null ){
-								listener.resultsReceived(engine, mapResults( results ));
-							}
-						}
-						
-						public void 
-						resultsComplete(
-							Engine engine )
-						{
-							if ( listener != null ){
-								listener.resultsComplete(engine);
-							}
-						}
-						
-						public void 
-						engineFailed(
-							Engine engine, 
-							Throwable cause )
-						{
-							log( "Search failed", cause );
-							
-							if ( listener != null ){
-								listener.engineFailed(engine, cause);
-							}
-						}
-						
-						public void 
-						engineRequiresLogin(
-							Engine engine, 
-							Throwable cause )
-						{
-							log( "Search requires login", cause );
-							
-							if ( listener != null ){
-								listener.engineRequiresLogin(engine, cause);
-							}
-						}
-					});
-		 
-		 return( mapResults( results ));
-	}
-	
-	protected Result[]
-	mapResults(
-		Result[]	results )
-	{
-		for (int i=0;i<results.length;i++){
-			
-			Result result = results[i];
-			
-			for (int j=0;j<first_level_mapping.size();j++){
-				
-				FieldRemapper mapper = (FieldRemapper)first_level_mapping.get(j);
-				
-				mapper.remap( result );
-			}
-			
-			for (int j=0;j<second_level_mapping.size();j++){
-				
-				FieldRemapper mapper = (FieldRemapper)second_level_mapping.get(j);
-				
-				mapper.remap( result );
-			}
-		}
-		
-		return( results );
-	}
-	
-	protected abstract Result[]
-	searchSupport(
-		SearchParameter[] 	params,
-		Map					searchContext,
-		int					desired_max_matches,
-		int					absolute_max_matches,
-		String				headers,
-		ResultListener		listener )
-	
-		throws SearchException;
-	
-	public void
-	delete()
-	{
-		meta_search.removeEngine( this );
-	}
-	
-	protected MetaSearchImpl
-	getMetaSearch()
-	{
-		return( meta_search );
-	}
-	
-	protected int
-	vuzeFieldToID(
-		String	field )
-	{
-		for (int i=0;i<FIELD_NAMES.length;i++){
-			
-			if ( field.equalsIgnoreCase( FIELD_NAMES[i] )){
-				
-				return( FIELD_IDS[i]);
-			}
-		}
-		
-		return( -1 );
-	}
-	
-	protected String
-	vuzeIDToField(
-		int		id )
-	{
-		for (int i=0;i<FIELD_IDS.length;i++){
-			
-			if ( id == FIELD_IDS[i] ){
-				
-				return( FIELD_NAMES[i]);
-			}
-		}
-		
-		return( null );
-	}
-
-	public int
-	getType()
-	{
-		return( type );
-	}
-	
-	protected void
-	setId(
-		long		_id )
-	{
-		id	= _id;
-	}
-	
-	public long 
-	getId()
-	{
-		return id;
-	}
-	
-	public long
-	getLastUpdated()
-	{
-		return( last_updated );
-	}
-	
-	public String 
-	getName() 
-	{
-		return( name );
-	}
-	
-	protected void
-	setName(
-		String		n )
-	{
-		name		= n;
-	}
-	
-	public boolean
-	isActive()
-	{
-		return(	getSelectionState() != SEL_STATE_DESELECTED );
-	}
-	
-	public boolean
-	isPublic()
-	{
-		return( is_public );
-	}
-	
-	protected void
-	setPublic(
-		boolean		p )
-	{
-		is_public = p;
-	}
-	
-	public int
-	getSelectionState()
-	{
-		return( selection_state );
-	}
-	
-	public void
-	setSelectionState(
-		int		state )
-	{
-		if ( state != selection_state ){
-		
-				// only record transitions to or from manual selection for non-local templates
-			
-			if ( getSource() == ENGINE_SOURCE_VUZE ){
-				
-				if ( 	state == SEL_STATE_MANUAL_SELECTED || 
-						selection_state == SEL_STATE_MANUAL_SELECTED ){
-					
-					selection_state_recorded = false;
-					
-					checkSelectionStateRecorded();
-				}
-			}
-			
-			selection_state	= state;
-						
-			configDirty();
-		}
-	}
-	
-	public boolean
-	isAuthenticated()
-	{
-		return( false );
-	}
-	
-	public void
-	recordSelectionState()
-	{
-		selection_state_recorded = false;
-		
-		checkSelectionStateRecorded();
-	}
-	
-	public void
-	checkSelectionStateRecorded()
-	{
-		if ( !selection_state_recorded ){
-			
-			try{
-				boolean selected = selection_state != SEL_STATE_DESELECTED;
-				
-				log( "Marking template id " + getId() + " as selected=" + selected );
-				
-				PlatformMetaSearchMessenger.setTemplatetSelected( meta_search.getManager().getExtensionKey(), getId(), ConstantsVuze.AZID, selected);
-				
-				selection_state_recorded = true;
-				
-			}catch( Throwable e ){
-				
-				log( "Failed to record selection state", e );
-			}
-		}
-	}
-	
-	public int
-	getSource()
-	{
-		return( source );
-	}
-	
-	public void
-	setSource(
-		int		_source )
-	{
-		if ( source != _source ){
-		
-			source	= _source;
-		
-			configDirty();
-		}
-	}
-	
-	public float
-	getRankBias()
-	{
-		return( rank_bias );
-	}
-	
-	public void
-	setRankBias(
-		float	_rank_bias )
-	{
-		if ( rank_bias != _rank_bias ){
-			
-			rank_bias	= _rank_bias;
-		
-			configDirty();
-		}
-	}
-	
-	public void
-	setPreferredDelta(
-		float	 delta )
-	{
-		float new_pref = preferred_count + delta;
-		
-		new_pref = Math.max( 0, new_pref );
-		new_pref = Math.min( 10, new_pref );
-		
-		if ( new_pref != preferred_count ){
-			
-			preferred_count = new_pref;
-			
-			configDirty();
-		}
-	}
-	
-	public float
-	getPreferredWeighting()
-	{
-		return( preferred_count );
-	}
-	
-	public float
-	applyRankBias(
-		float	_rank )
-	{
-		float rank = _rank*rank_bias;
-				
-		rank *= (1 + 0.025 * preferred_count );
-		
-		rank = Math.min( rank, 1.0f );
-		
-		rank = Math.max( rank, 0.0f );
-		
-		// System.out.println( getName() + " (" + rank_bias+"/"+preferred_count + "): " + _rank + " -> " + rank );
-		
-		return( rank );
-	}
-	
-	public boolean
-	isMine()
-	{
-		return( getLocalBoolean( LD_CREATED_BY_ME, false ));
-	}
-	
-	public void
-	setMine(
-		boolean		mine )
-	{
-		setLocalBoolean( LD_CREATED_BY_ME, mine );
-	}
-	
-	protected String
-	getUpdateURL()
-	{
-		return( update_url );
-	}
-	
-	protected void
-	setUpdateURL(
-		String	url )
-	{
-		update_url	= url;
-	}
-	
-	protected int
-	getUpdateCheckSecs()
-	{
-		long	l = getLocalLong( LD_UPDATE_CHECK_SECS, 0 );
-		
-		if ( l != 0 ){
-			
-			return((int)l);
-		}
-		
-		return( update_check_default_secs );
-	}
-	
-	protected void
-	setDefaultUpdateCheckSecs(
-		int		secs )
-	{
-		update_check_default_secs = secs;
-	}
-	
-	protected void
-	setLocalUpdateCheckSecs(
-		int		secs )
-	{
-		setLocalLong( LD_UPDATE_CHECK_SECS, secs );
-	}
-			
-	protected long
-	getLastUpdateCheck()
-	{
-		return( getLocalLong( LD_LAST_UPDATE_CHECK, 0 ));
-	}
-	
-	protected void
-	setLastUpdateCheck(
-		long		when )
-	{
-		setLocalLong( LD_LAST_UPDATE_CHECK, when );
-	}
-	
-	public int 
-	getAutoDownloadSupported() 
-	{
-			// default impl based on availability of fields that permit auto-dl
-			// overridden in RSS engine ( for example ) to be based on explicit
-			// channel tag
-		
-		boolean ok =
-			supportsField( Engine.FIELD_TORRENTLINK ) || 
-			supportsField( Engine.FIELD_DOWNLOADBTNLINK );
-
-		return( ok?AUTO_DL_SUPPORTED_YES:AUTO_DL_SUPPORTED_NO );
-	}
-	protected void
-	configDirty()
-	{
-		if ( meta_search != null ){
-			
-			meta_search.configDirty();
-		}
-	}
-	
-	public void
-	addPotentialAssociation(
-		String	key )
-	{
-		meta_search.addPotentialAssociation( this, key );
-	}
-	
-	public void
-	exportToVuzeFile(
-		File	target )
-	
-		throws IOException
-	{
-		VuzeFile	vf = VuzeFileHandler.getSingleton().create();
-		
-		vf.addComponent(
-			VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE,
-			exportToBencodedMap());
-		
-		vf.write( target );
-	}
-	
-	public VuzeFile
-	exportToVuzeFile()
-	
-		throws IOException
-	{
-		return( exportToVuzeFile( false ));
-	}
-	
-	public VuzeFile
-	exportToVuzeFile(
-		boolean		generic )
-	
-		throws IOException
-	{
-		VuzeFile	vf = VuzeFileHandler.getSingleton().create();
-		
-		vf.addComponent(
-			VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE,
-			exportToBencodedMap( generic ));
-		
-		return( vf );
-	}
-	
-	private String
-	getLocalKey()
-	{
-		return( "metasearch.engine." + id + ".local" );
-	}
-	
-	public void
-	reset()
-	{
-		synchronized( this ){
-			
-			Map map = COConfigurationManager.getMapParameter( getLocalKey(), new HashMap());
-
-			map.remove(	LD_COOKIES );
-			map.remove(	LD_ETAG );
-			map.remove(	LD_LAST_MODIFIED );
-			
-			COConfigurationManager.setParameter( getLocalKey(), map );
-		}
-	}
-	
-	protected void
-	setLocalString(
-		String		key,
-		String		value )
-	{
-		synchronized( this ){
-	
-			String	existing = getLocalString( key );
-			
-			if ( existing != null && value != null && existing.equals( value )){
-				
-				return;
-			}
-			
-			Map map = COConfigurationManager.getMapParameter( getLocalKey(), new HashMap());
-			
-			try{
-				ImportExportUtils.exportString(map, key, value);
-				
-				COConfigurationManager.setParameter( getLocalKey(), map );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace( e );
-			}
-		}
-	}
-	
-	protected String
-	getLocalString(
-		String		key )
-	{
-		synchronized( this ){
-		
-			Map map = COConfigurationManager.getMapParameter( getLocalKey(), new HashMap());
-			
-			try{
-				return( ImportExportUtils.importString( map, key ));
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace( e );
-				
-				return( null );
-			}
-		}
-	}
-	
-	protected void
-	setLocalBoolean(
-		String		key,
-		boolean		value )
-	{
-		setLocalLong( key, value?1:0 );
-	}
-	
-	protected boolean
-	getLocalBoolean(
-		String		key,
-		boolean		def )
-	{
-		return( getLocalLong( key, def?1:0 ) == 1 );
-	}
-	
-	protected void
-	setLocalLong(
-		String		key,
-		long		value )
-	{
-		synchronized( this ){
-	
-			long	existing = getLocalLong( key, 0 );
-			
-			if ( existing == value ){
-				
-				return;
-			}
-			
-			Map map = COConfigurationManager.getMapParameter( getLocalKey(), new HashMap());
-			
-			try{
-				map.put( key, new Long( value));
-				
-				COConfigurationManager.setParameter( getLocalKey(), map );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace( e );
-			}
-		}
-	}
-	
-	protected long
-	getLocalLong(
-		String		key,
-		long		def )
-	{
-		synchronized( this ){
-		
-			Map map = COConfigurationManager.getMapParameter( getLocalKey(), new HashMap());
-			
-			try{
-				return( ImportExportUtils.importLong( map, key, def ));
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace( e );
-				
-				return( def );
-			}
-		}
-	}
-	
-	protected void
-	setUserData(
-		Object	key,
-		Object	value )
-	{
-		synchronized( this ){
-			
-			if ( user_data == null ){
-				
-				if ( key == null ){
-					
-					return;
-				}
-				
-				user_data = new HashMap(4);
-			}
-			
-			if ( key == null ){
-				
-				user_data.remove( key );
-				
-				if ( user_data.size() == 0 ){
-					
-					user_data = null;
-				}
-			}else{
-				
-				user_data.put( key, value );
-			}
-		}
-	}
-	
-	protected Object
-	getUserData(
-		Object		key )
-	{
-		synchronized( this ){
-			
-			if ( user_data == null ){
-
-				return( null );
-			}
-			
-			return( user_data.get( key ));
-		}
-	}
-	
-	protected File
-	getDebugFile()
-	{
-		if ( logging_enabled ){
-		
-			return( new File( AEDiagnostics.getLogDir(), "MetaSearch_Engine_" + getId() + ".txt" ));
-			
-		}else{
-			
-			return( null );
-		}
-	}
-	
-	protected synchronized void
-	debugStart()
-	{
-		File f = getDebugFile();
-		
-		if ( f != null ){
-			
-			f.delete();
-		}
-	}
-	
-	protected synchronized void
-	debugLog(
-		String		str )
-	{
-		File f = getDebugFile();
-		
-		if ( f != null ){
-			
-			PrintWriter	 pw = null;
-			
-			try{
-				pw = new PrintWriter(new FileWriter( f, true ));
-				
-				pw.println( str );
-				
-			}catch( Throwable e ){
-				
-			}finally{
-				
-				if ( pw != null ){
-					
-					pw.close();
-				}
-			}
-		}
-	}
-	
-	protected void
-	log(
-		String		str )
-	{
-		if ( meta_search != null ){
-		
-			meta_search.log( "Engine " + getId() + ": " + str );
-		}
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable	e )
-	{
-		if ( meta_search != null ){
-		
-			meta_search.log( "Engine " + getId() + ": " + str, e );
-		}
-	}
-	
-	public String
-	getString()
-	{
-		return( "id=" + getId() + ", name=" + getName() + ", source=" + ENGINE_SOURCE_STRS[getSource()] + ", selected=" + SEL_STATE_STRINGS[getSelectionState()] + ", rb=" + rank_bias + ", pref=" + preferred_count );
-	}
-	
-	public String
-	getString(
-		boolean		full )
-	{
-		return( getString());
-	}
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URLDecoder;
+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;
+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.UrlUtils;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+
+import com.aelitis.azureus.core.messenger.config.PlatformMetaSearchMessenger;
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.Result;
+import com.aelitis.azureus.core.metasearch.ResultListener;
+import com.aelitis.azureus.core.metasearch.SearchException;
+import com.aelitis.azureus.core.metasearch.SearchLoginException;
+import com.aelitis.azureus.core.metasearch.SearchParameter;
+import com.aelitis.azureus.core.metasearch.impl.plugin.PluginEngine;
+import com.aelitis.azureus.core.metasearch.impl.web.json.JSONEngine;
+import com.aelitis.azureus.core.metasearch.impl.web.regex.RegexEngine;
+import com.aelitis.azureus.core.metasearch.impl.web.rss.RSSEngine;
+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.util.ConstantsVuze;
+import com.aelitis.azureus.util.ImportExportUtils;
+import com.aelitis.azureus.util.JSONUtils;
+
+
+public abstract class 
+EngineImpl
+	implements Engine
+{
+	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,
+		Map					map )
+	
+		throws IOException
+	{
+		int	type = ((Long)map.get( "type" )).intValue();
+		
+		if ( type == Engine.ENGINE_TYPE_JSON ){
+			
+			return( JSONEngine.importFromBEncodedMap( meta_search, map ));
+			
+		}else if ( type == Engine.ENGINE_TYPE_REGEX ){
+			
+			return( RegexEngine.importFromBEncodedMap( meta_search, map ));
+			
+		}else if ( type == Engine.ENGINE_TYPE_PLUGIN ){
+			
+			return( PluginEngine.importFromBEncodedMap( meta_search, map ));
+			
+		}else if ( type == Engine.ENGINE_TYPE_RSS ){
+			
+			return( RSSEngine.importFromBEncodedMap( meta_search, map ));
+			
+		}else{
+			
+			throw( new IOException( "Unknown engine type " + type ));
+		}
+	}
+	
+	public static Engine
+	importFromJSONString(
+		MetaSearchImpl	meta_search,
+		int				type,
+		long			id,
+		long			last_updated,
+		float			rank_bias,
+		String			name,
+		String			content )
+	
+		throws IOException
+	{
+		JSONObject map = (JSONObject)JSONUtils.decodeJSON( content );
+		
+		if ( type == Engine.ENGINE_TYPE_JSON ){
+			
+			return( JSONEngine.importFromJSONString( meta_search, id, last_updated, rank_bias, name, map ));
+			
+		}else if ( type == Engine.ENGINE_TYPE_REGEX ){
+			
+			return( RegexEngine.importFromJSONString( meta_search, id, last_updated, rank_bias, name, map ));
+			
+		}else if ( type == Engine.ENGINE_TYPE_RSS ){
+			
+			return( RSSEngine.importFromJSONString( meta_search, id, last_updated, rank_bias, name, map ));
+			
+		}else{
+			
+			throw( new IOException( "Unknown engine type " + type ));
+		}	
+	}
+	
+		// if you extend this with state pertaining to what has been downloaded then
+		// make sure you extend the code in reset();
+	
+	protected static final String		LD_COOKIES				= "cookies";
+	protected static final String		LD_ETAG					= "etag";
+	protected static final String		LD_LAST_MODIFIED		= "last_mod";
+	
+	protected static final String		LD_LAST_UPDATE_CHECK	= "last_update_check";
+	protected static final String		LD_UPDATE_CHECK_SECS	= "update_check_secs";
+	protected static final String		LD_CREATED_BY_ME		= "mine";
+	
+	protected static final String		LD_AUTO_DL_SUPPORTED	= "auto_dl_supported";
+	protected static final String		LD_LINK_IS_TORRENT		= "link_is_torrent";
+
+	
+	private MetaSearchImpl	meta_search;
+	
+	private int			type;
+	private long		id;
+	private long		last_updated;
+	private String		name;
+	
+	private byte[]		uid;
+	private int			version;
+	
+	private boolean		is_public					= true;
+	
+	private int			az_version;
+	
+	private int			selection_state				= SEL_STATE_DESELECTED;
+	private boolean		selection_state_recorded	= true;
+	
+	private int			source	= ENGINE_SOURCE_UNKNOWN;
+	
+	private float		rank_bias		= 1;
+	private float		preferred_count	= 0;
+	
+	
+		// first mappings used to canonicalise names and map field to same field
+		// typically used for categories (musak->music)
+	
+	private List		first_level_mapping	= new ArrayList();
+	
+		// second mappings used to generate derived field values
+		// typically used to derive content_type from category (music->AUDIO)
+	
+	private List		second_level_mapping	= new ArrayList();
+
+		// applicable to non-vuze hosted templates
+	
+	private String 		update_url;
+	private int			update_check_default_secs;
+	
+	private Map			user_data;
+	
+		// manual constructor
+	
+	protected
+	EngineImpl(
+		MetaSearchImpl	_meta_search,
+		int 			_type, 
+		long 			_id,
+		long			_last_updated,
+		float			_rank_bias,
+		String 			_name )
+	{
+		meta_search		= _meta_search;
+		type			= _type;
+		id				= _id;
+		last_updated	= _last_updated;
+		rank_bias		= _rank_bias;
+		name			= _name;
+		
+		version			= 1;
+		az_version		= AZ_VERSION;
+			
+		allocateUID( id );
+	}
+	
+		// bencoded constructor
+	
+	protected 
+	EngineImpl(
+		MetaSearchImpl	_meta_search,
+		Map				map )
+	
+		throws IOException
+	{
+		meta_search		= _meta_search;
+		
+		type			= ((Long)map.get( "type" )).intValue();
+		
+		Long l_id = (Long)map.get( "id");
+		
+		id				= l_id==null?meta_search.getManager().getLocalTemplateID():l_id.longValue();
+		last_updated	= ImportExportUtils.importLong( map, "last_updated" );
+		name			= ImportExportUtils.importString( map, "name" );
+		
+		selection_state	= (int)ImportExportUtils.importLong( map, "selected", SEL_STATE_DESELECTED );
+		
+		selection_state_recorded = ImportExportUtils.importBoolean(map,"select_rec", true );
+		
+		source			= (int)ImportExportUtils.importLong( map, "source", ENGINE_SOURCE_UNKNOWN );
+		
+		rank_bias		= ImportExportUtils.importFloat( map, "rank_bias", 1.0f );
+		preferred_count	= ImportExportUtils.importFloat( map, "pref_count", 0.0f );
+		
+		first_level_mapping 	= importBEncodedMappings( map, "l1_map" );
+		second_level_mapping 	= importBEncodedMappings( map, "l2_map" );
+		
+		version = (int)ImportExportUtils.importLong( map, "version", 1 );
+		
+		az_version = (int)ImportExportUtils.importLong( map, "az_version", AZ_VERSION );
+
+		if ( az_version > AZ_VERSION ){
+			
+			throw( new IOException( MessageText.getString("metasearch.template.version.bad", new String[]{ name })));
+		}
+		
+		uid		= (byte[])map.get( "uid" );
+		
+		if ( uid == null ){
+			
+			allocateUID( id );
+		}
+		
+		update_url 					= ImportExportUtils.importString( map, "update_url" );
+		update_check_default_secs	= (int)ImportExportUtils.importLong( map, "update_url_check_secs", DEFAULT_UPDATE_CHECK_SECS );
+	}
+	
+		// bencoded export
+	
+	protected void
+	exportToBencodedMap(
+		Map			map,
+		boolean		generic )
+	
+		throws IOException
+	{
+		map.put( "type", new Long( type ));
+		
+		ImportExportUtils.exportString( map, "name", name );
+		
+		map.put( "source", new Long( source ));
+
+		exportBEncodedMappings( map, "l1_map", first_level_mapping );
+		exportBEncodedMappings( map, "l2_map", second_level_mapping );
+
+		map.put( "version", new Long( version ));
+		map.put( "az_version", new Long( az_version ));
+
+		ImportExportUtils.exportFloat( map, "rank_bias", rank_bias );
+
+		if ( !generic ){
+			
+			map.put( "id", new Long( id ));
+			
+			map.put( "last_updated", new Long( last_updated ));
+		
+			map.put( "selected", new Long( selection_state ));
+		
+			ImportExportUtils.exportBoolean( map, "select_rec", selection_state_recorded );
+			
+			ImportExportUtils.exportFloat( map, "pref_count", preferred_count );
+		
+			map.put( "uid", uid );
+		}
+		
+		if ( update_url != null ){
+		
+			ImportExportUtils.exportString( map, "update_url", update_url );
+		}
+		
+		if ( update_check_default_secs != DEFAULT_UPDATE_CHECK_SECS ){
+			map.put( "update_url_check_secs", new Long( update_check_default_secs ));
+		}
+	}
+	
+		// json constructor
+	
+	protected 
+	EngineImpl(
+		MetaSearchImpl	meta_search,
+		int				type,
+		long			id,
+		long			last_updated,
+		float			rank_bias,
+		String			name,
+		JSONObject		map )
+	
+		throws IOException
+	{
+		this( meta_search, type, id, last_updated, rank_bias, name );
+		
+		first_level_mapping 	= importJSONMappings( map, "value_map", true );
+		second_level_mapping 	= importJSONMappings( map, "ctype_map", false );
+		
+		version 	= (int)ImportExportUtils.importLong( map, "version", 1 );
+		az_version 	= (int)ImportExportUtils.importLong( map, "az_version", AZ_VERSION );
+		
+		if ( az_version > AZ_VERSION ){
+			
+			throw( new IOException( MessageText.getString( "metasearch.template.version.bad", new String[]{ name })));
+		}
+		
+		String uid_str		= (String)map.get( "uid" );
+		
+		if ( uid_str == null ){
+			
+			allocateUID( id );
+			
+		}else{
+			
+			uid = Base32.decode( uid_str );
+		}
+		
+		update_url 					= ImportExportUtils.importString( map, "update_url" );
+		update_check_default_secs	= (int)ImportExportUtils.importLong( map, "update_url_check_secs", DEFAULT_UPDATE_CHECK_SECS );
+	}
+	
+		// json export
+	
+	protected void
+	exportToJSONObject(
+		JSONObject		res )
+	
+		throws IOException
+	{
+		exportJSONMappings( res, "value_map", first_level_mapping, true );
+		exportJSONMappings( res, "ctype_map", second_level_mapping, false );
+		
+		res.put( "version", new Long( version ));
+		res.put( "az_version", new Long( az_version ));
+		
+		res.put( "uid", Base32.encode( uid ));
+		
+		if ( update_url != null ){
+			
+			ImportExportUtils.exportJSONString( res, "update_url", update_url );
+		}
+		
+		res.put( "update_url_check_secs", new Long( update_check_default_secs ));
+	}
+	
+	protected List
+	importJSONMappings(
+		JSONObject		map,
+		String			str,
+		boolean			level_1 )
+	
+		throws IOException
+	{
+		List	result = new ArrayList();
+			
+		JSONObject	field_map = (JSONObject)map.get( str );
+		
+		if ( field_map != null ){
+			
+			Iterator	it = field_map.entrySet().iterator();
+			
+			while( it.hasNext()){
+				
+				Map.Entry	entry = (Map.Entry)it.next();
+				
+				String	key 		= (String)entry.getKey();
+				List	mappings 	= (List)entry.getValue();
+				
+					// limited support for the moment: 
+					//		level one always maps to same field
+					//		level two always maps to content type
+				
+				int	from_field 	= vuzeFieldToID( key );
+				
+				if ( from_field == -1 ){
+					
+					log( "Unrecognised remapping key '" + key + "'" );
+					
+					continue;
+				
+				}
+				
+				int	to_field	= level_1?from_field:FIELD_CONTENT_TYPE;
+				
+				List	frs_l = new ArrayList();
+				
+				for (int i=0;i<mappings.size();i++){
+					
+					JSONObject mapping = (JSONObject)mappings.get(i);
+					
+					String	from_str 	= URLDecoder.decode((String)mapping.get( level_1?"from_string":"cat_string" ),"UTF-8");
+
+					if ( from_str == null ){
+						
+						log( "'from' value missing in " + mapping );
+						
+						continue;
+					}
+					
+					from_str 	= URLDecoder.decode( from_str, "UTF-8" );
+					
+					String	to_str 		= URLDecoder.decode((String)mapping.get( level_1?"to_string":"media_type" ),"UTF-8");
+					
+					if ( to_str == null ){
+						
+						log( "'to' value missing in " + mapping );
+						
+						continue;
+					}
+					
+					frs_l.add( new FieldRemapping( from_str, to_str ));
+				}
+				
+				FieldRemapping[] frs = (FieldRemapping[])frs_l.toArray( new FieldRemapping[frs_l.size()]);
+
+				result.add( new FieldRemapper( from_field, to_field, frs ));
+			}
+		}
+		
+		return( result );
+	}
+	
+	protected void
+	exportJSONMappings(
+		JSONObject			res,
+		String				str,
+		List				l,
+		boolean				level_1 )
+	{
+		JSONObject	field_map = new JSONObject();
+		
+		res.put( str, field_map );
+		
+		for (int i=0;i<l.size();i++){
+			
+			FieldRemapper remapper = (FieldRemapper)l.get(i);
+			
+			int	from_field	= remapper.getInField();
+			//int	to_field	= remapper.getOutField();
+			
+			String from_field_str = vuzeIDToField( from_field );
+			
+			JSONArray	mappings = new JSONArray();
+			
+			field_map.put( from_field_str, mappings );
+			
+			FieldRemapping[] frs = remapper.getMappings();
+			
+			for (int j=0;j<frs.length;j++){
+				
+				FieldRemapping fr = frs[j];
+				
+				String from_str = UrlUtils.encode( fr.getMatchString());
+				
+				String to_str	= fr.getReplacement();
+				
+				JSONObject map = new JSONObject();
+				
+				mappings.add( map );
+				
+				map.put( level_1?"from_string":"cat_string", from_str );
+				map.put( level_1?"to_string":"media_type", to_str );
+			}
+		}
+	}
+			
+	protected List
+	importBEncodedMappings(
+		Map		map,
+		String	name )
+	
+		throws IOException
+	{
+		List	result = new ArrayList();
+		
+		List	l = (List)map.get(name);
+		
+		if ( l != null ){
+			
+			for (int i=0;i<l.size();i++){
+				
+				Map	entry = (Map)l.get(i);
+				
+				int	from_field 	= ((Long)entry.get( "from" )).intValue();
+				int	to_field 	= ((Long)entry.get( "to" )).intValue();
+				
+				List	l2 = (List)entry.get( "maps" );
+				
+				FieldRemapping[]	mappings = new FieldRemapping[ l2.size() ];
+				
+				for (int j=0;j<mappings.length;j++){
+					
+					Map	entry2 = (Map)l2.get(j);
+					
+					String	from_str 	= ImportExportUtils.importString( entry2, "from" );
+					String	to_str 		= ImportExportUtils.importString( entry2, "to" );
+					
+					mappings[j] = new FieldRemapping( from_str, to_str );
+				}
+				
+				result.add( new FieldRemapper( from_field, to_field, mappings ));
+			}
+		}
+		
+		return( result );
+	}
+	
+	protected void
+	exportBEncodedMappings(
+		Map		map,
+		String	name,
+		List	mappings )
+	
+		throws IOException
+	{
+		List	l = new ArrayList();
+		
+		map.put( name, l );
+		
+		for ( int i=0;i<mappings.size();i++){
+			
+			FieldRemapper mapper = (FieldRemapper)mappings.get(i);
+			
+			Map m = new HashMap();
+			
+			l.add( m );
+			
+			m.put( "from", new Long( mapper.getInField()));
+			m.put( "to", new Long( mapper.getOutField()));
+			
+			List l2 = new ArrayList();
+			
+			m.put( "maps", l2 );
+			
+			FieldRemapping[] frs = mapper.getMappings();
+			
+			for (int j=0;j<frs.length;j++){
+				
+				FieldRemapping fr = frs[j];
+				
+				Map m2 = new HashMap();
+				
+				l2.add( m2 );
+				
+				ImportExportUtils.exportString( m2, "from", fr.getMatchString());
+				ImportExportUtils.exportString( m2, "to", fr.getReplacement());
+			}
+		}
+	}
+	
+	public String
+	exportToJSONString()
+	
+		throws IOException
+	{
+		JSONObject	obj = new JSONObject();
+		
+		exportToJSONObject( obj );
+		
+		return( obj.toString());
+	}
+	
+	public int
+	getAZVersion()
+	{
+		return( az_version );
+	}
+	
+	public int
+	getVersion()
+	{
+		return( version );
+	}
+	
+	protected void
+	setVersion(
+		int		_v )
+	{
+		version	= _v;
+	}
+	
+	public String
+	getUID()
+	{
+		return( Base32.encode( uid ));
+	}
+	
+	protected void
+	setUID(
+		String	str )
+	{
+		uid	= Base32.decode( str );
+	}
+	
+	protected void
+	allocateUID(
+		long		id )
+	{
+		uid = new byte[10];
+
+		if ( id >= 0 && id < Integer.MAX_VALUE ){
+		
+				// id is a vuze one, derive uid from it as already unique
+			
+			uid[0] 	= (byte)(id>>24);
+			uid[1]	= (byte)(id>>16);
+			uid[2]	= (byte)(id>>8);
+			uid[3]	= (byte)id;
+
+		}else{
+	
+			RandomUtils.nextSecureBytes( uid );
+			
+			configDirty();
+		}
+	}
+
+	public boolean
+	sameLogicAs(
+		Engine	other )
+	{
+		try{
+			Map	m1 = exportToBencodedMap();
+			Map	m2 = other.exportToBencodedMap();
+		
+			String[]	to_remove = 
+				{	"type", 
+					"id", 
+					"last_updated",
+					"selected",
+					"select_rec",
+					"source",
+					"rank_bias",
+					"pref_count",
+					"version", 
+					"az_version", 
+					"uid" };
+			
+			for (int i=0;i<to_remove.length;i++){
+				
+				m1.remove( to_remove[i] );
+				m2.remove( to_remove[i] );
+			}
+			
+			return( BEncoder.mapsAreIdentical( m1, m2 ));
+			
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+			
+			return( false );
+		}
+	}
+		
+	public Result[]
+	search(
+		SearchParameter[] 		params,
+		Map						context,
+		int						desired_max_matches,
+		int						absolute_max_matches,
+		String					headers,
+		final ResultListener	listener )
+	
+		throws SearchException
+	{
+		if ( context == null ){
+			
+			context = new HashMap();
+		}
+		
+		try{
+			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 ){
+				
+				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];
+				}
+				
+				if ( inform_result.size() > 0 ){
+				
+					listener.resultsReceived( this, inform_result.toArray( new Result[ inform_result.size()] ));
+				}
+				
+				if ( inform_complete ){
+				
+					listener.resultsComplete( this );
+				}
+			}
+			
+			return( results );
+			
+		}catch( Throwable e ){
+			
+			if ( e instanceof SearchLoginException ){
+				
+				if ( listener != null ){
+				
+					listener.engineRequiresLogin(this, e);
+				}
+				
+				throw((SearchLoginException)e);
+				
+			}else if ( e instanceof SearchException ){
+				
+				if ( listener != null ){
+				
+					listener.engineFailed( this, e);
+				}
+				
+				throw((SearchException)e);
+				
+			}else{
+				
+				if ( listener != null ){
+				
+					listener.engineFailed( this, e);
+				}
+				
+				throw( new SearchException( "Search failed", e ));
+			}
+		}
+	}
+	
+	protected Result[]
+	searchAndMap(
+		SearchParameter[] 			params,
+		Map							context,
+		int							desired_max_matches,
+		int							absolute_max_matches,
+		String						headers,
+		final ResultListener		listener )
+	
+		throws SearchException
+	{
+			// default values
+		
+		context.put( Engine.SC_AZID, 	ConstantsVuze.AZID );
+
+		if ( context.get( Engine.SC_SOURCE ) == null ){
+			
+			context.put( Engine.SC_SOURCE, "search" );
+		}
+		
+		Result[] results = 
+			 searchSupport( 
+					params, 
+					context,
+					desired_max_matches,
+					absolute_max_matches,
+					headers, 
+					new ResultListener()
+					{
+						public void 
+						contentReceived(
+							Engine 		engine, 
+							String 		content )
+						{
+							if ( listener != null ){
+								listener.contentReceived(engine, content);
+							}
+						}
+					
+						public void 
+						matchFound( 
+							Engine 		engine, 
+							String[] 	fields )
+						{
+							if ( listener != null ){
+								listener.matchFound(engine, fields);
+							}
+						}
+						
+						public void 
+						resultsReceived(
+							Engine 		engine,
+							Result[] 	results)
+						{
+							if ( listener != null ){
+								listener.resultsReceived(engine, mapResults( results ));
+							}
+						}
+						
+						public void 
+						resultsComplete(
+							Engine engine )
+						{
+							if ( listener != null ){
+								listener.resultsComplete(engine);
+							}
+						}
+						
+						public void 
+						engineFailed(
+							Engine engine, 
+							Throwable cause )
+						{
+							log( "Search failed", cause );
+							
+							if ( listener != null ){
+								listener.engineFailed(engine, cause);
+							}
+						}
+						
+						public void 
+						engineRequiresLogin(
+							Engine engine, 
+							Throwable cause )
+						{
+							log( "Search requires login", cause );
+							
+							if ( listener != null ){
+								listener.engineRequiresLogin(engine, cause);
+							}
+						}
+					});
+		 
+		 return( mapResults( results ));
+	}
+	
+	protected Result[]
+	mapResults(
+		Result[]	results )
+	{
+		for (int i=0;i<results.length;i++){
+			
+			Result result = results[i];
+			
+			for (int j=0;j<first_level_mapping.size();j++){
+				
+				FieldRemapper mapper = (FieldRemapper)first_level_mapping.get(j);
+				
+				mapper.remap( result );
+			}
+			
+			for (int j=0;j<second_level_mapping.size();j++){
+				
+				FieldRemapper mapper = (FieldRemapper)second_level_mapping.get(j);
+				
+				mapper.remap( result );
+			}
+		}
+		
+		return( results );
+	}
+	
+	protected abstract Result[]
+	searchSupport(
+		SearchParameter[] 	params,
+		Map					searchContext,
+		int					desired_max_matches,
+		int					absolute_max_matches,
+		String				headers,
+		ResultListener		listener )
+	
+		throws SearchException;
+	
+	public void
+	delete()
+	{
+		meta_search.removeEngine( this );
+	}
+	
+	protected MetaSearchImpl
+	getMetaSearch()
+	{
+		return( meta_search );
+	}
+	
+	protected int
+	vuzeFieldToID(
+		String	field )
+	{
+		for (int i=0;i<FIELD_NAMES.length;i++){
+			
+			if ( field.equalsIgnoreCase( FIELD_NAMES[i] )){
+				
+				return( FIELD_IDS[i]);
+			}
+		}
+		
+		return( -1 );
+	}
+	
+	protected String
+	vuzeIDToField(
+		int		id )
+	{
+		for (int i=0;i<FIELD_IDS.length;i++){
+			
+			if ( id == FIELD_IDS[i] ){
+				
+				return( FIELD_NAMES[i]);
+			}
+		}
+		
+		return( null );
+	}
+
+	public int
+	getType()
+	{
+		return( type );
+	}
+	
+	protected void
+	setId(
+		long		_id )
+	{
+		id	= _id;
+	}
+	
+	public long 
+	getId()
+	{
+		return id;
+	}
+	
+	public long
+	getLastUpdated()
+	{
+		return( last_updated );
+	}
+	
+	public String 
+	getName() 
+	{
+		return( name );
+	}
+	
+	protected void
+	setName(
+		String		n )
+	{
+		name		= n;
+	}
+	
+	public boolean
+	isActive()
+	{
+		return(	getSelectionState() != SEL_STATE_DESELECTED );
+	}
+	
+	public boolean
+	isPublic()
+	{
+		return( is_public );
+	}
+	
+	protected void
+	setPublic(
+		boolean		p )
+	{
+		is_public = p;
+	}
+	
+	public int
+	getSelectionState()
+	{
+		return( selection_state );
+	}
+	
+	public void
+	setSelectionState(
+		int		state )
+	{
+		if ( state != selection_state ){
+		
+				// only record transitions to or from manual selection for non-local templates
+			
+			if ( getSource() == ENGINE_SOURCE_VUZE ){
+				
+				if ( 	state == SEL_STATE_MANUAL_SELECTED || 
+						selection_state == SEL_STATE_MANUAL_SELECTED ){
+					
+					selection_state_recorded = false;
+					
+					checkSelectionStateRecorded();
+				}
+			}
+			
+			selection_state	= state;
+						
+			configDirty();
+		}
+	}
+	
+	public boolean
+	isAuthenticated()
+	{
+		return( false );
+	}
+	
+	public void
+	recordSelectionState()
+	{
+		selection_state_recorded = false;
+		
+		checkSelectionStateRecorded();
+	}
+	
+	public void
+	checkSelectionStateRecorded()
+	{
+		if ( !selection_state_recorded ){
+			
+			try{
+				boolean selected = selection_state != SEL_STATE_DESELECTED;
+				
+				log( "Marking template id " + getId() + " as selected=" + selected );
+				
+				PlatformMetaSearchMessenger.setTemplatetSelected( meta_search.getManager().getExtensionKey(), getId(), ConstantsVuze.AZID, selected);
+				
+				selection_state_recorded = true;
+				
+			}catch( Throwable e ){
+				
+				log( "Failed to record selection state", e );
+			}
+		}
+	}
+	
+	public int
+	getSource()
+	{
+		return( source );
+	}
+	
+	public void
+	setSource(
+		int		_source )
+	{
+		if ( source != _source ){
+		
+			source	= _source;
+		
+			configDirty();
+		}
+	}
+	
+	public float
+	getRankBias()
+	{
+		return( rank_bias );
+	}
+	
+	public void
+	setRankBias(
+		float	_rank_bias )
+	{
+		if ( rank_bias != _rank_bias ){
+			
+			rank_bias	= _rank_bias;
+		
+			configDirty();
+		}
+	}
+	
+	public void
+	setPreferredDelta(
+		float	 delta )
+	{
+		float new_pref = preferred_count + delta;
+		
+		new_pref = Math.max( 0, new_pref );
+		new_pref = Math.min( 10, new_pref );
+		
+		if ( new_pref != preferred_count ){
+			
+			preferred_count = new_pref;
+			
+			configDirty();
+		}
+	}
+	
+	public float
+	getPreferredWeighting()
+	{
+		return( preferred_count );
+	}
+	
+	public float
+	applyRankBias(
+		float	_rank )
+	{
+		float rank = _rank*rank_bias;
+				
+		rank *= (1 + 0.025 * preferred_count );
+		
+		rank = Math.min( rank, 1.0f );
+		
+		rank = Math.max( rank, 0.0f );
+		
+		// System.out.println( getName() + " (" + rank_bias+"/"+preferred_count + "): " + _rank + " -> " + rank );
+		
+		return( rank );
+	}
+	
+	public boolean
+	isMine()
+	{
+		return( getLocalBoolean( LD_CREATED_BY_ME, false ));
+	}
+	
+	public void
+	setMine(
+		boolean		mine )
+	{
+		setLocalBoolean( LD_CREATED_BY_ME, mine );
+	}
+	
+	protected String
+	getUpdateURL()
+	{
+		return( update_url );
+	}
+	
+	protected void
+	setUpdateURL(
+		String	url )
+	{
+		update_url	= url;
+	}
+	
+	protected int
+	getUpdateCheckSecs()
+	{
+		long	l = getLocalLong( LD_UPDATE_CHECK_SECS, 0 );
+		
+		if ( l != 0 ){
+			
+			return((int)l);
+		}
+		
+		return( update_check_default_secs );
+	}
+	
+	protected void
+	setDefaultUpdateCheckSecs(
+		int		secs )
+	{
+		update_check_default_secs = secs;
+	}
+	
+	protected void
+	setLocalUpdateCheckSecs(
+		int		secs )
+	{
+		setLocalLong( LD_UPDATE_CHECK_SECS, secs );
+	}
+			
+	protected long
+	getLastUpdateCheck()
+	{
+		return( getLocalLong( LD_LAST_UPDATE_CHECK, 0 ));
+	}
+	
+	protected void
+	setLastUpdateCheck(
+		long		when )
+	{
+		setLocalLong( LD_LAST_UPDATE_CHECK, when );
+	}
+	
+	public int 
+	getAutoDownloadSupported() 
+	{
+			// default impl based on availability of fields that permit auto-dl
+			// overridden in RSS engine ( for example ) to be based on explicit
+			// channel tag
+		
+		boolean ok =
+			supportsField( Engine.FIELD_TORRENTLINK ) || 
+			supportsField( Engine.FIELD_DOWNLOADBTNLINK );
+
+		return( ok?AUTO_DL_SUPPORTED_YES:AUTO_DL_SUPPORTED_NO );
+	}
+	protected void
+	configDirty()
+	{
+		if ( meta_search != null ){
+			
+			meta_search.configDirty();
+		}
+	}
+	
+	public void
+	addPotentialAssociation(
+		String	key )
+	{
+		meta_search.addPotentialAssociation( this, key );
+	}
+	
+	public void
+	exportToVuzeFile(
+		File	target )
+	
+		throws IOException
+	{
+		VuzeFile	vf = VuzeFileHandler.getSingleton().create();
+		
+		vf.addComponent(
+			VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE,
+			exportToBencodedMap());
+		
+		vf.write( target );
+	}
+	
+	public VuzeFile
+	exportToVuzeFile()
+	
+		throws IOException
+	{
+		return( exportToVuzeFile( false ));
+	}
+	
+	public VuzeFile
+	exportToVuzeFile(
+		boolean		generic )
+	
+		throws IOException
+	{
+		VuzeFile	vf = VuzeFileHandler.getSingleton().create();
+		
+		vf.addComponent(
+			VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE,
+			exportToBencodedMap( generic ));
+		
+		return( vf );
+	}
+	
+	private String
+	getLocalKey()
+	{
+		return( "metasearch.engine." + id + ".local" );
+	}
+	
+	public void
+	reset()
+	{
+		synchronized( this ){
+			
+			Map map = COConfigurationManager.getMapParameter( getLocalKey(), new HashMap());
+
+			map.remove(	LD_COOKIES );
+			map.remove(	LD_ETAG );
+			map.remove(	LD_LAST_MODIFIED );
+			
+			COConfigurationManager.setParameter( getLocalKey(), map );
+		}
+	}
+	
+	protected void
+	setLocalString(
+		String		key,
+		String		value )
+	{
+		synchronized( this ){
+	
+			String	existing = getLocalString( key );
+			
+			if ( existing != null && value != null && existing.equals( value )){
+				
+				return;
+			}
+			
+			Map map = COConfigurationManager.getMapParameter( getLocalKey(), new HashMap());
+			
+			try{
+				ImportExportUtils.exportString(map, key, value);
+				
+				COConfigurationManager.setParameter( getLocalKey(), map );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace( e );
+			}
+		}
+	}
+	
+	protected String
+	getLocalString(
+		String		key )
+	{
+		synchronized( this ){
+		
+			Map map = COConfigurationManager.getMapParameter( getLocalKey(), new HashMap());
+			
+			try{
+				return( ImportExportUtils.importString( map, key ));
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace( e );
+				
+				return( null );
+			}
+		}
+	}
+	
+	protected void
+	setLocalBoolean(
+		String		key,
+		boolean		value )
+	{
+		setLocalLong( key, value?1:0 );
+	}
+	
+	protected boolean
+	getLocalBoolean(
+		String		key,
+		boolean		def )
+	{
+		return( getLocalLong( key, def?1:0 ) == 1 );
+	}
+	
+	protected void
+	setLocalLong(
+		String		key,
+		long		value )
+	{
+		synchronized( this ){
+	
+			long	existing = getLocalLong( key, 0 );
+			
+			if ( existing == value ){
+				
+				return;
+			}
+			
+			Map map = COConfigurationManager.getMapParameter( getLocalKey(), new HashMap());
+			
+			try{
+				map.put( key, new Long( value));
+				
+				COConfigurationManager.setParameter( getLocalKey(), map );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace( e );
+			}
+		}
+	}
+	
+	protected long
+	getLocalLong(
+		String		key,
+		long		def )
+	{
+		synchronized( this ){
+		
+			Map map = COConfigurationManager.getMapParameter( getLocalKey(), new HashMap());
+			
+			try{
+				return( ImportExportUtils.importLong( map, key, def ));
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace( e );
+				
+				return( def );
+			}
+		}
+	}
+	
+	protected void
+	setUserData(
+		Object	key,
+		Object	value )
+	{
+		synchronized( this ){
+			
+			if ( user_data == null ){
+				
+				if ( key == null ){
+					
+					return;
+				}
+				
+				user_data = new HashMap(4);
+			}
+			
+			if ( key == null ){
+				
+				user_data.remove( key );
+				
+				if ( user_data.size() == 0 ){
+					
+					user_data = null;
+				}
+			}else{
+				
+				user_data.put( key, value );
+			}
+		}
+	}
+	
+	protected Object
+	getUserData(
+		Object		key )
+	{
+		synchronized( this ){
+			
+			if ( user_data == null ){
+
+				return( null );
+			}
+			
+			return( user_data.get( key ));
+		}
+	}
+	
+	protected File
+	getDebugFile()
+	{
+		if ( logging_enabled ){
+		
+			return( new File( AEDiagnostics.getLogDir(), "MetaSearch_Engine_" + getId() + ".txt" ));
+			
+		}else{
+			
+			return( null );
+		}
+	}
+	
+	protected synchronized void
+	debugStart()
+	{
+		File f = getDebugFile();
+		
+		if ( f != null ){
+			
+			f.delete();
+		}
+	}
+	
+	protected synchronized void
+	debugLog(
+		String		str )
+	{
+		File f = getDebugFile();
+		
+		if ( f != null ){
+			
+			PrintWriter	 pw = null;
+			
+			try{
+				pw = new PrintWriter(new FileWriter( f, true ));
+				
+				pw.println( str );
+				
+			}catch( Throwable e ){
+				
+			}finally{
+				
+				if ( pw != null ){
+					
+					pw.close();
+				}
+			}
+		}
+	}
+	
+	protected void
+	log(
+		String		str )
+	{
+		if ( meta_search != null ){
+		
+			meta_search.log( "Engine " + getId() + ": " + str );
+		}
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable	e )
+	{
+		if ( meta_search != null ){
+		
+			meta_search.log( "Engine " + getId() + ": " + str, e );
+		}
+	}
+	
+	public String
+	getString()
+	{
+		return( "id=" + getId() + ", name=" + getName() + ", source=" + ENGINE_SOURCE_STRS[getSource()] + ", selected=" + SEL_STATE_STRINGS[getSelectionState()] + ", rb=" + rank_bias + ", pref=" + preferred_count );
+	}
+	
+	public String
+	getString(
+		boolean		full )
+	{
+		return( getString());
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/FieldRemapper.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/FieldRemapper.java
index fb6d7e6..317fb08 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/FieldRemapper.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/FieldRemapper.java
@@ -1,103 +1,102 @@
-/*
- * Created on May 6, 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.core.metasearch.impl;
-
-import java.util.regex.Matcher;
-
-import com.aelitis.azureus.core.metasearch.Result;
-import com.aelitis.azureus.core.metasearch.Engine;
-
-public class FieldRemapper {
-	
-	private int inField;
-	private int outField;
-	
-	private FieldRemapping[] fieldRemappings;
-
-	
-	public 
-	FieldRemapper(
-		int 				inField, 
-		int 				outField,
-		FieldRemapping[] 	fieldRemappings) 
-	{
-		super();
-		this.inField = inField;
-		this.outField = outField;
-		this.fieldRemappings = fieldRemappings;
-	}
-
-	public int
-	getInField()
-	{
-		return( inField );
-	}
-	
-	public int
-	getOutField()
-	{
-		return( outField );
-	}
-	
-	public FieldRemapping[]
-	getMappings()
-	{
-		return( fieldRemappings );
-	}
-
-	public void 
-	remap(
-		Result r )
-	{
-		String input = null;
-		switch(inField) {
-			case Engine.FIELD_CATEGORY :
-				input = r.getCategory();
-				break;
-		}
-		
-		String output = null;
-		if(input != null) {
-			for(int i = 0 ; i < fieldRemappings.length ; i++) {
-				if(fieldRemappings[i].getMatch() != null && fieldRemappings[i].getReplacement() != null) {
-					Matcher matcher = fieldRemappings[i].getMatch().matcher(input);
-					if(matcher.matches()) {
-						output = matcher.replaceAll(fieldRemappings[i].getReplacement());
-						i = fieldRemappings.length;
-					}
-				}
-			}
-		}
-		
-		if(output != null) {
-			switch(outField) {
-			case Engine.FIELD_CATEGORY :
-				r.setCategory(output);
-				break;
-			case Engine.FIELD_CONTENT_TYPE :
-				r.setContentType(output);
-				break;
-			}
-		}
-		
-	}
-
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl;
+
+import java.util.regex.Matcher;
+
+import com.aelitis.azureus.core.metasearch.Result;
+import com.aelitis.azureus.core.metasearch.Engine;
+
+public class FieldRemapper {
+	
+	private int inField;
+	private int outField;
+	
+	private FieldRemapping[] fieldRemappings;
+
+	
+	public 
+	FieldRemapper(
+		int 				inField, 
+		int 				outField,
+		FieldRemapping[] 	fieldRemappings) 
+	{
+		super();
+		this.inField = inField;
+		this.outField = outField;
+		this.fieldRemappings = fieldRemappings;
+	}
+
+	public int
+	getInField()
+	{
+		return( inField );
+	}
+	
+	public int
+	getOutField()
+	{
+		return( outField );
+	}
+	
+	public FieldRemapping[]
+	getMappings()
+	{
+		return( fieldRemappings );
+	}
+
+	public void 
+	remap(
+		Result r )
+	{
+		String input = null;
+		switch(inField) {
+			case Engine.FIELD_CATEGORY :
+				input = r.getCategory();
+				break;
+		}
+		
+		String output = null;
+		if(input != null) {
+			for(int i = 0 ; i < fieldRemappings.length ; i++) {
+				if(fieldRemappings[i].getMatch() != null && fieldRemappings[i].getReplacement() != null) {
+					Matcher matcher = fieldRemappings[i].getMatch().matcher(input);
+					if(matcher.matches()) {
+						output = matcher.replaceAll(fieldRemappings[i].getReplacement());
+						i = fieldRemappings.length;
+					}
+				}
+			}
+		}
+		
+		if(output != null) {
+			switch(outField) {
+			case Engine.FIELD_CATEGORY :
+				r.setCategory(output);
+				break;
+			case Engine.FIELD_CONTENT_TYPE :
+				r.setContentType(output);
+				break;
+			}
+		}
+		
+	}
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/FieldRemapping.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/FieldRemapping.java
index e6e6857..aaf98d3 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/FieldRemapping.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/FieldRemapping.java
@@ -1,55 +1,54 @@
-/*
- * Created on May 6, 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.core.metasearch.impl;
-
-import java.util.regex.Pattern;
-
-public class FieldRemapping {
-	
-	private String  match_str;
-	
-	private Pattern match;
-	private String replace;
-	
-	public FieldRemapping(String match, String replace) {
-		
-		this.match_str 	= match;
-		this.match 		= Pattern.compile(match);
-		this.replace 	=replace;
-	}
-	
-	public String
-	getMatchString()
-	{
-		return(match_str );
-	}
-	
-	public Pattern getMatch() {
-		return match;
-	}
-	
-	public String getReplacement() {
-		return replace;
-	}
-	
-	
-	
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl;
+
+import java.util.regex.Pattern;
+
+public class FieldRemapping {
+	
+	private String  match_str;
+	
+	private Pattern match;
+	private String replace;
+	
+	public FieldRemapping(String match, String replace) {
+		
+		this.match_str 	= match;
+		this.match 		= Pattern.compile(match);
+		this.replace 	=replace;
+	}
+	
+	public String
+	getMatchString()
+	{
+		return(match_str );
+	}
+	
+	public Pattern getMatch() {
+		return match;
+	}
+	
+	public String getReplacement() {
+		return replace;
+	}
+	
+	
+	
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/MetaSearchImpl.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/MetaSearchImpl.java
index b11ba39..3e51a2d 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/MetaSearchImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/MetaSearchImpl.java
@@ -1,1358 +1,1357 @@
-/*
- * Created on May 6, 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.core.metasearch.impl;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.*;
-
-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.BDecoder;
-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.FileUtil;
-import org.gudy.azureus2.core3.util.IndentWriter;
-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;
-import org.gudy.azureus2.core3.util.TimerEventPerformer;
-import org.gudy.azureus2.core3.util.TimerEventPeriodic;
-import org.gudy.azureus2.plugins.utils.StaticUtilities;
-import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
-import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory;
-import org.gudy.azureus2.plugins.utils.search.SearchProvider;
-
-import com.aelitis.azureus.core.messenger.config.PlatformMetaSearchMessenger;
-import com.aelitis.azureus.core.metasearch.*;
-import com.aelitis.azureus.core.metasearch.impl.plugin.PluginEngine;
-import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
-import com.aelitis.azureus.core.metasearch.impl.web.rss.RSSEngine;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-import com.aelitis.azureus.core.vuzefile.VuzeFileComponent;
-import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
-
-public class 
-MetaSearchImpl
-	implements MetaSearch
-{
-	private static final String	CONFIG_FILE = "metasearch.config";
-		
-	private MetaSearchManagerImpl	manager;
-	
-	private CopyOnWriteList<EngineImpl> engines 	= new CopyOnWriteList<EngineImpl>();
-	private Map<String,Long>			plugin_map	= new HashMap<String,Long>();
-	
-	private boolean config_dirty;
-	
-	private CopyOnWriteList<MetaSearchListener> 	listeners 	= new CopyOnWriteList<MetaSearchListener>();
-	
-	private TimerEventPeriodic	update_check_timer;
-	
-	private static final int 	UPDATE_CHECK_PERIOD		= 15*60*1000;
-	private static final int	MIN_UPDATE_CHECK_SECS	= 10*60;
-	
-	private Object				MS_UPDATE_CONSEC_FAIL_KEY = new Object();
-	
-	private AsyncDispatcher		update_dispatcher = new AsyncDispatcher();
-	
-	protected 
-	MetaSearchImpl(
-		MetaSearchManagerImpl		_manager )
-	{
-		manager	= _manager;
-		
-		loadConfig();
-	}
-	
-	protected MetaSearchManagerImpl
-	getManager()
-	{
-		return( manager );
-	}
-	
-	public Engine
-	importFromBEncodedMap(
-		Map<String,Object>		map )
-	
-		throws IOException
-	{
-		return( EngineImpl.importFromBEncodedMap( this, map )); 
-	}
-	
-	public Engine
-	importFromJSONString(
-		int			type,
-		long		id,
-		long		last_updated,
-		float		rank_bias,
-		String		name,
-		String		content )
-	
-		throws IOException
-	{
-		return( EngineImpl.importFromJSONString( this, type, id, last_updated, rank_bias, name, content ));
-	}
-	
-	public EngineImpl
-	importFromPlugin(
-		String				_pid,
-		SearchProvider		provider )
-	
-		throws IOException
-	{
-		synchronized( this ){
-
-				// unfortunately pid can be internationalised and thus musn't be used as a key to
-				// a bencoded-map as it can lead of nastyness. Delete any existing entries that have
-				// got out of control
-			
-			Iterator<String>	it = plugin_map.keySet().iterator();
-			
-			while( it.hasNext()){
-				
-				if ( it.next().length() > 1024 ){
-					
-					Debug.out( "plugin_map corrupted, resetting" );
-							
-					plugin_map.clear();
-					
-					break;
-				}
-			}
-			
-			String pid = Base32.encode( _pid.getBytes( "UTF-8" ));
-			
-			Long	l_id = plugin_map.get( pid );
-			
-			long	id;
-			
-			if ( l_id == null ){
-				
-				id = manager.getLocalTemplateID();
-						
-				plugin_map.put( pid, new Long( id ));
-						
-				configDirty();
-
-			}else{
-				
-				id = l_id.longValue();
-			}
-			
-			EngineImpl engine = (EngineImpl)getEngine( id );
-			
-			if ( engine == null ){
-				
-				engine = new PluginEngine( this, id, provider );
-				
-				engine.setSource( Engine.ENGINE_SOURCE_LOCAL );
-				
-				engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
-				
-				addEngine( engine );
-				
-			}else{
-				
-				if ( engine instanceof PluginEngine ){
-					
-					((PluginEngine)engine).setProvider( provider );
-					
-				}else{
-					
-					Debug.out( "Inconsistent: plugin must be a PluginEngine!" );
-					
-					plugin_map.remove( pid );
-					
-					removeEngine( engine );
-					
-					throw( new IOException( "Inconsistent" ));
-				}
-			}
-			
-			return( engine );
-		}	
-	}
-	
-	public SearchProvider
-	resolveProvider(
-		PluginEngine	for_engine )
-	{
-		List<EngineImpl> l = engines.getList();
-
-		for ( EngineImpl e: l ){
-			
-			if ( e instanceof PluginEngine ){
-				
-				PluginEngine pe = (PluginEngine)e;
-				
-				SearchProvider provider = pe.getProvider();
-				
-				if ( provider != null ){
-					
-					if ( pe.getName().equals( for_engine.getName())){
-						
-						return( provider );
-					}
-				}
-			}
-		}
-		
-		return( null );
-	}
-	
-	public Engine 
-	createRSSEngine(
-		String		name,
-		URL 		url )
-	
-		throws MetaSearchException 
-	{
-		EngineImpl engine = 
-			new RSSEngine( 
-					this, 
-					manager.getLocalTemplateID(), 
-					SystemTime.getCurrentTime(), 
-					1.0f,
-					name, 
-					url.toExternalForm(), 
-					false,
-					WebEngine.AM_TRANSPARENT,
-					null,
-					new String[0] );
-		
-		engine.setSource( Engine.ENGINE_SOURCE_RSS );
-		
-		addEngine( engine, false );
-				
-		log( "Created RSS engine '" + url + "'" );
-		
-		return( engine );
-	}
-	
-	protected void
-	enableUpdateChecks()
-	{
-		synchronized( this ){
-			
-			if ( update_check_timer == null ){
-				
-				update_check_timer = SimpleTimer.addPeriodicEvent(
-						"MS:updater",
-						UPDATE_CHECK_PERIOD,
-						new TimerEventPerformer()
-						{
-							public void 
-							perform(
-								TimerEvent event) 
-							{
-								checkUpdates();
-							}
-						});
-			}
-		}
-	}
-	private void
-	checkUpdates()
-	{
-		update_dispatcher.dispatch(
-			new AERunnable()
-			{
-				public void 
-				runSupport() 
-				{
-					checkUpdatesSupport();
-				}
-			});
-	}
-	
-	private void
-	checkUpdatesSupport()
-	{
-		Iterator<EngineImpl> it = engines.iterator();
-		
-		while( it.hasNext()){
-				
-			EngineImpl	engine = (EngineImpl)it.next();
-				
-			String	update_url = engine.getUpdateURL();
-			
-			if ( update_url != null ){
-				
-				long	now				= SystemTime.getCurrentTime();
-				
-				long	last_check 		= engine.getLastUpdateCheck();
-				
-				if ( last_check > now ){
-					
-					last_check = now;
-					
-					engine.setLastUpdateCheck( now );
-				}
-				
-				long	check_secs	= engine.getUpdateCheckSecs();
-				
-				if ( check_secs < MIN_UPDATE_CHECK_SECS ){
-					
-					log( "Engine '" + engine.getName() + "': Update check period too small (" + check_secs + " secs) adjusting to " + MIN_UPDATE_CHECK_SECS + ": " + engine.getName());
-					
-					check_secs = MIN_UPDATE_CHECK_SECS;
-				}
-				
-				long	check_millis	= check_secs*1000;
-				
-				long	next_check		= last_check + check_millis;
-				
-				Object	consec_fails_o = engine.getUserData( MS_UPDATE_CONSEC_FAIL_KEY );
-				
-				int	consec_fails = consec_fails_o==null?0:((Integer)consec_fails_o).intValue();
-				
-				if ( consec_fails > 0 ){
-					
-					next_check += ( UPDATE_CHECK_PERIOD << consec_fails );
-				}
-				
-				if ( next_check < now ){
-				
-					if ( updateEngine( engine )){
-						
-						consec_fails	= 0;
-						
-						engine.setLastUpdateCheck( now );
-						
-					}else{
-						
-						consec_fails++;
-						
-						if ( consec_fails > 3 ){
-							
-							consec_fails	= 0;
-							
-								// skip to next scheduled update time
-							
-							engine.setLastUpdateCheck( now );
-						}
-					}
-					
-					engine.setUserData( MS_UPDATE_CONSEC_FAIL_KEY, consec_fails==0?null:new Integer( consec_fails ));
-				}
-			}
-		}
-	}
-	
-	protected boolean
-	updateEngine(
-		EngineImpl		engine )
-	{
-		String	update_url = engine.getUpdateURL();
-
-		int	pos = update_url.indexOf('?');
-		
-		if ( pos == -1 ){
-			
-			update_url += "?";
-			
-		}else{
-			
-			update_url += "&";
-		}
-		
-		update_url += 	"az_template_uid=" + engine.getUID() + 
-						"&az_template_version=" + engine.getVersion() +
-						"&az_version=" + Constants.AZUREUS_VERSION +
-					    "&az_locale=" + MessageText.getCurrentLocale().toString() +
-					    "&az_rand=" + RandomUtils.nextAbsoluteLong();
-		
-		log( "Engine " + engine.getName() + ": auto-update check via " + update_url );
-		
-		try{
-			ResourceDownloaderFactory rdf = StaticUtilities.getResourceDownloaderFactory();
-			
-			ResourceDownloader url_rd = rdf.create( new URL( update_url ));
-			
-			ResourceDownloader rd = rdf.getMetaRefreshDownloader( url_rd );
-			
-			InputStream is = rd.download();
-			
-			try{
-				Map<String,Object> map = BDecoder.decode( new BufferedInputStream( is ));
-				
-				log( "    update check reply: " + map );
-				
-					// reply is either "response" meaning "no update" and giving possibly changed update secs
-					// or Vuze file with updated template
-				
-				Map<String,Object> response = (Map<String,Object>)map.get( "response" );
-				
-				if ( response != null ){
-					
-					Long	update_secs = (Long)response.get( "update_url_check_secs" );
-					
-					if ( update_secs == null ){
-						
-						engine.setLocalUpdateCheckSecs( 0 );
-						
-					}else{
-						
-						int	check_secs = update_secs.intValue();
-						
-						if ( check_secs < MIN_UPDATE_CHECK_SECS ){
-							
-							log( "    update check secs for to small, min is " + MIN_UPDATE_CHECK_SECS);
-							
-							check_secs = MIN_UPDATE_CHECK_SECS;
-						}
-							
-						engine.setLocalUpdateCheckSecs( check_secs );
-					}
-					
-					return( true );
-					
-				}else{
-					
-					VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( map );
-					
-					if ( vf == null ){
-						
-						log( "    failed to decode vuze file" );
-						
-						return( false );
-					}
-										
-					Engine[] updated_engines = manager.loadFromVuzeFile( vf );
-					
-					if ( updated_engines.length > 0 ){
-						
-						String	existing_uid = engine.getUID();
-						
-						boolean	found = false;
-						
-						String	engine_str = "";
-						
-						for (int i=0;i<updated_engines.length;i++){
-							
-							Engine updated_engine = updated_engines[i];
-							
-							engine_str += (i==0?"":",") + updated_engine.getName() + ": uid=" + updated_engine.getUID() + ",version=" + updated_engine.getVersion();
-							
-							if ( updated_engine.getUID().equals( existing_uid )){
-								
-								found	= true;
-							}
-						}
-						
-						if ( !found ){
-							
-							log( "    existing engine not found in updated set, deleting" );
-							
-							engine.delete();
-							
-						}
-							
-						log( "    update complete: new engines=" + engine_str );
-						
-					}else{
-						
-						log( "    no engines found in vuze file" );
-					}
-					
-					return( true );
-				}
-			}finally{
-				
-				is.close();
-			}
-		}catch( Throwable e ){
-			
-			log( "    update check failed", e );
-			
-			return( false );
-		}
-	}
-	
-	public void 
-	addEngine(
-		Engine 	engine )
-	{
-		addEngine( (EngineImpl)engine, false );
-	}
-	
-	public Engine 
-	addEngine(
-		long 		id )
-	
-		throws MetaSearchException 
-	{
-		try{
-
-			PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( manager.getExtensionKey(), id );
-		
-			log( "Downloading definition of template " + id );
-			log( details.getValue());
-		
-			if ( details.isVisible()){
-			
-				Engine engine = 
-					importFromJSONString( 
-						details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
-						details.getId(),
-						details.getModifiedDate(),
-						details.getRankBias(),
-						details.getName(),
-						details.getValue());
-				
-				engine.setSource( Engine.ENGINE_SOURCE_VUZE );
-				engine.setSelectionState( Engine.SEL_STATE_DESELECTED );
-				
-				addEngine( engine );
-				
-				return( engine );
-				
-			}else{
-				
-				throw( new MetaSearchException( "Search template is not visible" ));
-			}
-		}catch( MetaSearchException e ){
-			
-			throw( e );
-			
-		}catch( Throwable e ){
-		
-			throw( new MetaSearchException( "Template load failed", e ));
-		}	
-	}
-		
-	public void 
-	addEngine(
-		EngineImpl 	new_engine,
-		boolean		loading )
-	{		
-		boolean	add_op = true;
-		
-		synchronized( this ){
-			
-			Iterator<EngineImpl>	it = engines.iterator();
-			
-			while( it.hasNext()){
-				
-				Engine existing_engine = it.next();
-				
-				if ( existing_engine.getId() == new_engine.getId()){
-					
-					log( "Updating engine with same ID " + existing_engine.getId() + ": " + existing_engine.getName() + "/" + existing_engine.getUID());
-					
-					it.remove();
-					
-					new_engine.setUID( existing_engine.getUID());
-					
-					if ( existing_engine.sameLogicAs( new_engine )){
-						
-						new_engine.setVersion( existing_engine.getVersion());
-
-					}else{
-						
-						new_engine.setVersion( existing_engine.getVersion() + 1 );
-						
-						log( "    new version=" + new_engine.getVersion());
-					}
-					 
-					add_op = false;
-					
-				}else if ( existing_engine.getUID().equals( new_engine.getUID())){
-					
-					log( "Removing engine with same UID " + existing_engine.getUID() + "(" + existing_engine.getName() + ")" );
-					
-					it.remove();
-				}
-			}
-			
-			engines.add( new_engine );
-		}
-		
-		if ( new_engine.getUpdateURL() != null ){
-			
-			enableUpdateChecks();
-		}
-		
-		if ( !loading ){
-			
-			log( "Engine '" + new_engine.getName() + "' added" );
-			
-			saveConfig();
-		
-			Iterator<MetaSearchListener> it = listeners.iterator();
-			
-			while( it.hasNext()){
-				
-				MetaSearchListener listener = it.next();
-				
-				try{
-					if ( add_op ){
-						
-						listener.engineAdded( new_engine );
-						
-					}else{
-						
-						listener.engineUpdated( new_engine );
-					}
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-		}
-	}
-	
-	public void 
-	removeEngine(
-		Engine 	engine )
-	{
-		if ( engines.remove((EngineImpl)engine )){
-		
-			log( "Engine '" + engine.getName() + "' removed" );
-			
-			saveConfig();
-			
-			Iterator<MetaSearchListener> it = listeners.iterator();
-			
-			while( it.hasNext()){
-				
-				try{
-	
-					it.next().engineRemoved( engine );
-	
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-		}
-	}
-	
-	public String
-	getFUD()
-	{
-		List<EngineImpl> l = engines.getList();
-		
-		List<Long>	ids = new ArrayList<Long>();
-		
-		for ( EngineImpl engine: l ){
-			
-			if ( engine.getSource() == Engine.ENGINE_SOURCE_VUZE ){
-				
-				ids.add( engine.getId());
-			}
-		}
-		
-		Collections.sort( ids );
-		
-		String	fud = "";
-
-		for ( Long id: ids ){
-		
-			fud += (fud.length()==0?"":",") +id; 
-		}
-		
-		return( fud );
-	}
-	
-	protected void
-	addPotentialAssociation(
-		EngineImpl		engine,
-		String			key )
-	{
-		manager.addPotentialAssociation(engine, key);	
-	}
-	
-	public Engine[] 
-	getEngines(
-		boolean		active_only,
-		boolean		ensure_up_to_date )
-	{
-		if ( ensure_up_to_date ){
-			
-			manager.ensureEnginesUpToDate();
-		}
-		
-		List<EngineImpl> l = engines.getList();
-				
-		List<EngineImpl> result;
-		
-		if ( active_only ){
-			
-			result = new ArrayList<EngineImpl>();
-			
-			for (int i=0;i<l.size();i++){
-				
-				EngineImpl	e = l.get(i);
-				
-				if ( e.isActive()){
-					
-					result.add( e );
-				}
-			}
-		}else{
-			
-			result = l;
-		}
-		
-		return( (Engine[])result.toArray( new Engine[ result.size() ]));
-	}
-	
-	public Engine
-	getEngine(
-		long		id )
-	{
-		List<EngineImpl> l = engines.getList();
-		
-		for( int i=0;i<l.size();i++){
-			
-			Engine e = l.get(i);
-			
-			if ( e.getId() == id ){
-				
-				return( e );
-			}
-		}
-
-		return( null );
-	}
-	
-	public Engine
-	getEngineByUID(
-		String	uid )
-	{
-		List<EngineImpl> l = engines.getList();
-		
-		for( int i=0;i<l.size();i++){
-			
-			Engine e = l.get(i);
-			
-			if ( e.getUID().equals( uid )){
-				
-				return( e );
-			}
-		}
-
-		return( null );
-	}
-	
-	public int
-	getEngineCount()
-	{
-		return( engines.size());
-	}
-	
-	public Engine[] 
-	search(
-		final ResultListener 	original_listener,
-		SearchParameter[] 		searchParameters,
-		String					headers,
-		int						max_results_per_engine )
-	{
-		return( search( original_listener, searchParameters, headers, new HashMap<String,String>(), max_results_per_engine ));
-	}
-	
-	public Engine[] 
-  	search(
-  		final ResultListener 	original_listener,
-  		SearchParameter[] 		searchParameters,
-  		String					headers,
-  		Map<String,String>		context,
-  		int						max_results_per_engine )
-  	{
-  		return( search( null, original_listener, searchParameters, headers, context, max_results_per_engine ));
-  	}
-	
-	public Engine[] 
-	search(
-		Engine[]				engines,
-		final ResultListener 	listener,
-		SearchParameter[] 		search_parameters,
-		String					headers,
-		final int				max_results_per_engine )
-	{
-		return( search( engines, listener, search_parameters, headers, new HashMap<String,String>(), max_results_per_engine ));
-	}
-	
-	public void
-	enginePreferred(
-		Engine		engine )
-	{
-		Engine[] engines = getEngines( true, false );
-		
-		int	num_other_preferred = 0;
-		
-		for ( Engine e: engines ){
-			
-			if ( e.getId() == engine.getId()){
-				
-				e.setPreferredDelta( +1 );
-				
-			}else{
-				
-				if ( e.getPreferredWeighting() > 0 ){
-					
-					num_other_preferred++;
-				}
-			}
-		}
-				
-		if ( num_other_preferred > 0 ){
-			
-			float negative_weighting = -1.0f / num_other_preferred;
-		
-			for ( Engine e: engines ){
-			
-				if ( e.getId() != engine.getId() && e.getPreferredWeighting() > 0 ){
-				
-					e.setPreferredDelta( negative_weighting );
-				}
-			}
-		}
-	}
-	
-	public Engine[] 
-  	search(
-  		Engine[]				engines,
-  		final ResultListener 	original_listener,
-  		SearchParameter[] 		searchParameters,
-  		String					headers,
-  		Map<String,String>		context,
-  		final int				max_results_per_engine )
-	{
-		String batch_millis_str = context.get( Engine.SC_BATCH_PERIOD );
-		
-		final long batch_millis = batch_millis_str==null?0:Long.parseLong( batch_millis_str );
-		
-		String rem_dups_str = context.get( Engine.SC_REMOVE_DUP_HASH );
-		
-		final boolean rem_dups = rem_dups_str==null?false:rem_dups_str.equalsIgnoreCase( "true" );
-
-		ResultListener	listener = 
-			new ResultListener()
-			{
-					// 	single thread listener calls
-			
-				private AsyncDispatcher dispatcher = new AsyncDispatcher( 5000 );
-
-				final private Map<Engine,List<Result[]>>	pending_results = new HashMap<Engine,List<Result[]>>();
-				
-				final private Map<Engine,Set<String>>	result_hashes = new HashMap<Engine, Set<String>>();
-				
-				public void
-				contentReceived(
-					final Engine engine, 
-					final String content ) 
-				{
-					dispatcher.dispatch(
-							new AERunnable()
-							{
-								public void
-								runSupport()
-								{
-									original_listener.contentReceived( engine, content );
-								}
-							});
-				}
-				
-				public void 
-				matchFound(
-					final Engine 	engine, 
-					final String[] 	fields )
-				{
-					dispatcher.dispatch(
-							new AERunnable()
-							{
-								public void
-								runSupport()
-								{
-									original_listener.matchFound( engine, fields );
-								}
-							});	
-				}
-				
-				public void 
-				resultsReceived(
-					final Engine 	engine,
-					final Result[] 	results )
-				{
-					dispatcher.dispatch(
-						new AERunnable()
-						{
-							public void
-							runSupport()
-							{
-								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{
-								
-									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 );
-								}
-							}
-						});
-				}
-			
-				public void 
-				resultsComplete(
-					final Engine engine )
-				{
-					dispatcher.dispatch(
-							new AERunnable()
-							{
-								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 );
-					}
-				}
-				
-				protected Result[]
-             	truncateResults(
-             		Engine		engine,
-             		Result[] 	a_results,
-             		int			max )
-             	{
-					Set<String>	hash_set = result_hashes.get( engine );
-					
-					if ( hash_set == null ){
-						
-						hash_set = new HashSet<String>();
-						
-						result_hashes.put( engine, hash_set );
-					}
-						
-					List<Result>	results = new ArrayList<Result>( a_results.length );
-					
-					for ( Result r: a_results ){
-							
-						String name = r.getName();
-							
-						if ( name == null || name.trim().length() == 0 ){
-								
-							continue;
-						}
-					
-						if ( rem_dups ){
-
-							String hash = r.getHash();
-							
-							if ( 	hash == null ||
-									hash.length() == 0 ){
-								
-								results.add( r );
-								
-							}else{
-								
-								if ( !hash_set.contains( hash )){
-									
-									results.add( r );
-									
-									hash_set.add( hash );
-								}
-							}
-						}else{
-							
-							results.add( r );
-						}
-					}
-					
-             		if ( max < results.size() ){
-             		
-             			log( "Truncating search results for " + engine.getName() + " from " + results.size() + " to " + max );
-             			
-             			Collections.sort(
-             				results,
-             				new Comparator<Result>()
-             				{
-             					Map<Result,Float>	ranks = new HashMap<Result, Float>();
-             					
-             					public int 
-             					compare(
-             						Result r1, 
-             						Result r2) 
-             					{						
-             						Float	rank1 = (Float)ranks.get(r1);
-             						
-             						if ( rank1 == null ){	
-             							rank1 = new Float(r1.getRank());
-             							ranks.put( r1, rank1 );
-             						}
-             						
-             						Float	rank2 = (Float)ranks.get(r2);
-             						
-             						if ( rank2 == null ){	
-             							rank2 = new Float(r2.getRank());
-             							ranks.put( r2, rank2 );
-             						}
-             						
-             						return( rank2.compareTo( rank1 ));
-             					}
-             				});
-             		
-             			Result[] x = new Result[max];
-             			
-             			int	pos = 0;
-             			
-             			while( pos < max ){
-             			
-             				x[pos] = results.get( pos );
-             				
-             				pos++;
-             			}
-             			
-             			return( x );
-             			
-             		}else{
-             			
-             			return( results.toArray( new Result[ results.size()] ));
-             		}
-             	}
-				
-				public void 
-				engineFailed(
-					final Engine 	engine,
-					final Throwable	e )
-				{
-					dispatcher.dispatch(
-							new AERunnable()
-							{
-								public void
-								runSupport()
-								{
-									original_listener.engineFailed( engine, e );
-								}
-							});
-				}
-				
-				public void 
-				engineRequiresLogin(
-					final Engine 	engine,
-					final Throwable	e )
-				{
-					dispatcher.dispatch(
-							new AERunnable()
-							{
-								public void
-								runSupport()
-								{
-									original_listener.engineRequiresLogin( engine, e );
-								}
-							});
-				}
-			};
-			
-		SearchExecuter se = new SearchExecuter( context, listener );
-		
-		if ( engines == null ){
-			
-			engines = getEngines( true, true );
-		}
-		
-		String	engines_str = "";
-		
-		for (int i=0;i<engines.length;i++){
-			
-			engines_str += (i==0?"":",") + engines[i].getId();
-		}
-		
-		log( "Search: engines=" + engines_str );
-		
-		for (int i=0;i<engines.length;i++){
-			
-			se.search( engines[i], searchParameters, headers, max_results_per_engine );
-		}
-		
-		return( engines );
-	}
-	
-	public void
-	exportEngines(
-		File	target )
-	
-		throws MetaSearchException
-	{
-		Engine[] engines = getEngines( true, false );
-		
-		VuzeFile	vf = VuzeFileHandler.getSingleton().create();
-		
-		for ( Engine engine: engines ){
-		
-			try{
-				vf.addComponent(
-					VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE,
-					engine.exportToBencodedMap());
-				
-			}catch( IOException e ){
-				
-				Debug.out( e );
-			}
-			
-		}
-		
-		try{
-			vf.write( target );
-			
-		}catch( IOException e ){
-			
-			throw( new MetaSearchException( "Failed to write file", e ));
-		}
-	}
-	
-	public void
-	addListener(
-		MetaSearchListener		listener )
-	{
-		listeners.add( listener );
-	}
-	
-	public void
-	removeListener(
-		MetaSearchListener		listener )
-	{
-		listeners.remove( listener );
-	}
-	
-	protected void
-	loadConfig()
-	{
-		log( "Loading configuration" );
-		
-		synchronized( this ){
-			
-			Map<String,Object> map = FileUtil.readResilientConfigFile( CONFIG_FILE );
-			
-			List<Map<String,Object>>	l_engines = (List<Map<String,Object>>)map.get( "engines" );
-			
-			if( l_engines != null ){
-				
-				for (int i=0;i<l_engines.size();i++){
-					
-					Map<String,Object>	m = (Map<String,Object>)l_engines.get(i);
-					
-					try{
-						Engine e = importFromBEncodedMap( m );
-						
-						addEngine( (EngineImpl)e, true );
-						
-						log( "    loaded " + e.getString());
-						
-					}catch( Throwable e ){
-						
-						log( "Failed to import engine from " + m, e );
-					}
-				}
-			}
-			
-			Map<String,Long>	p_map = (Map<String,Long>)map.get( "plugin_map" );
-			
-			if ( p_map != null ){
-				
-				plugin_map = p_map;
-			}
-		
-			if ( update_check_timer != null ){
-				
-				checkUpdates();
-			}
-		}
-	}
-	
-	protected void
-	configDirty()
-	{
-		synchronized( this ){
-			
-			if ( config_dirty ){
-				
-				return;
-			}
-			
-			config_dirty = true;
-		
-			new DelayedEvent( 
-				"MetaSearch:save", 5000,
-				new AERunnable()
-				{
-					public void 
-					runSupport() 
-					{
-						synchronized( MetaSearchImpl.this ){
-							
-							if ( !config_dirty ){
-
-								return;
-							}
-							
-							saveConfig();
-						}	
-					}
-				});
-		}
-	}
-	
-	protected void
-	saveConfig()
-	{
-		log( "Saving configuration" );
-		
-		synchronized( this ){
-			
-			config_dirty = false;
-			
-			Map<String,Object> map = new HashMap<String, Object>();
-			
-			List<Map<String,Object>>	l_engines = new ArrayList<Map<String,Object>>();
-			
-			map.put( "engines", l_engines );
-			
-			Iterator<EngineImpl>	it = engines.iterator();
-			
-			while( it.hasNext()){
-				
-				Engine e = it.next();
-			
-				try{
-					
-					l_engines.add( e.exportToBencodedMap());
-					
-				}catch( Throwable f ){
-					
-					log( "Failed to export engine " + e.getName(), f );
-				}
-			}
-			
-			if ( plugin_map != null ){
-				
-				map.put( "plugin_map", plugin_map );
-			}
-			
-			FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
-		}
-	}
-	
-	protected void
-	log(
-		String	str )
-	{
-		manager.log( "search :"  + str );
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable 	e )
-	{
-		manager.log( "search :"  +  str, e );
-	}
-	
-	protected void
-	generate(
-		IndentWriter		writer )
-	{
-		Iterator<EngineImpl> it = engines.iterator();
-		
-		while( it.hasNext()){
-				
-			EngineImpl	e = it.next();
-			
-			writer.println( e.getString( true ));
-		}	
-	}
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+
+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.BDecoder;
+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.FileUtil;
+import org.gudy.azureus2.core3.util.IndentWriter;
+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;
+import org.gudy.azureus2.core3.util.TimerEventPerformer;
+import org.gudy.azureus2.core3.util.TimerEventPeriodic;
+import org.gudy.azureus2.plugins.utils.StaticUtilities;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory;
+import org.gudy.azureus2.plugins.utils.search.SearchProvider;
+
+import com.aelitis.azureus.core.messenger.config.PlatformMetaSearchMessenger;
+import com.aelitis.azureus.core.metasearch.*;
+import com.aelitis.azureus.core.metasearch.impl.plugin.PluginEngine;
+import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
+import com.aelitis.azureus.core.metasearch.impl.web.rss.RSSEngine;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.core.vuzefile.VuzeFile;
+import com.aelitis.azureus.core.vuzefile.VuzeFileComponent;
+import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
+
+public class 
+MetaSearchImpl
+	implements MetaSearch
+{
+	private static final String	CONFIG_FILE = "metasearch.config";
+		
+	private MetaSearchManagerImpl	manager;
+	
+	private CopyOnWriteList<EngineImpl> engines 	= new CopyOnWriteList<EngineImpl>();
+	private Map<String,Long>			plugin_map	= new HashMap<String,Long>();
+	
+	private boolean config_dirty;
+	
+	private CopyOnWriteList<MetaSearchListener> 	listeners 	= new CopyOnWriteList<MetaSearchListener>();
+	
+	private TimerEventPeriodic	update_check_timer;
+	
+	private static final int 	UPDATE_CHECK_PERIOD		= 15*60*1000;
+	private static final int	MIN_UPDATE_CHECK_SECS	= 10*60;
+	
+	private Object				MS_UPDATE_CONSEC_FAIL_KEY = new Object();
+	
+	private AsyncDispatcher		update_dispatcher = new AsyncDispatcher();
+	
+	protected 
+	MetaSearchImpl(
+		MetaSearchManagerImpl		_manager )
+	{
+		manager	= _manager;
+		
+		loadConfig();
+	}
+	
+	protected MetaSearchManagerImpl
+	getManager()
+	{
+		return( manager );
+	}
+	
+	public Engine
+	importFromBEncodedMap(
+		Map<String,Object>		map )
+	
+		throws IOException
+	{
+		return( EngineImpl.importFromBEncodedMap( this, map )); 
+	}
+	
+	public Engine
+	importFromJSONString(
+		int			type,
+		long		id,
+		long		last_updated,
+		float		rank_bias,
+		String		name,
+		String		content )
+	
+		throws IOException
+	{
+		return( EngineImpl.importFromJSONString( this, type, id, last_updated, rank_bias, name, content ));
+	}
+	
+	public EngineImpl
+	importFromPlugin(
+		String				_pid,
+		SearchProvider		provider )
+	
+		throws IOException
+	{
+		synchronized( this ){
+
+				// unfortunately pid can be internationalised and thus musn't be used as a key to
+				// a bencoded-map as it can lead of nastyness. Delete any existing entries that have
+				// got out of control
+			
+			Iterator<String>	it = plugin_map.keySet().iterator();
+			
+			while( it.hasNext()){
+				
+				if ( it.next().length() > 1024 ){
+					
+					Debug.out( "plugin_map corrupted, resetting" );
+							
+					plugin_map.clear();
+					
+					break;
+				}
+			}
+			
+			String pid = Base32.encode( _pid.getBytes( "UTF-8" ));
+			
+			Long	l_id = plugin_map.get( pid );
+			
+			long	id;
+			
+			if ( l_id == null ){
+				
+				id = manager.getLocalTemplateID();
+						
+				plugin_map.put( pid, new Long( id ));
+						
+				configDirty();
+
+			}else{
+				
+				id = l_id.longValue();
+			}
+			
+			EngineImpl engine = (EngineImpl)getEngine( id );
+			
+			if ( engine == null ){
+				
+				engine = new PluginEngine( this, id, provider );
+				
+				engine.setSource( Engine.ENGINE_SOURCE_LOCAL );
+				
+				engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
+				
+				addEngine( engine );
+				
+			}else{
+				
+				if ( engine instanceof PluginEngine ){
+					
+					((PluginEngine)engine).setProvider( provider );
+					
+				}else{
+					
+					Debug.out( "Inconsistent: plugin must be a PluginEngine!" );
+					
+					plugin_map.remove( pid );
+					
+					removeEngine( engine );
+					
+					throw( new IOException( "Inconsistent" ));
+				}
+			}
+			
+			return( engine );
+		}	
+	}
+	
+	public SearchProvider
+	resolveProvider(
+		PluginEngine	for_engine )
+	{
+		List<EngineImpl> l = engines.getList();
+
+		for ( EngineImpl e: l ){
+			
+			if ( e instanceof PluginEngine ){
+				
+				PluginEngine pe = (PluginEngine)e;
+				
+				SearchProvider provider = pe.getProvider();
+				
+				if ( provider != null ){
+					
+					if ( pe.getName().equals( for_engine.getName())){
+						
+						return( provider );
+					}
+				}
+			}
+		}
+		
+		return( null );
+	}
+	
+	public Engine 
+	createRSSEngine(
+		String		name,
+		URL 		url )
+	
+		throws MetaSearchException 
+	{
+		EngineImpl engine = 
+			new RSSEngine( 
+					this, 
+					manager.getLocalTemplateID(), 
+					SystemTime.getCurrentTime(), 
+					1.0f,
+					name, 
+					url.toExternalForm(), 
+					false,
+					WebEngine.AM_TRANSPARENT,
+					null,
+					new String[0] );
+		
+		engine.setSource( Engine.ENGINE_SOURCE_RSS );
+		
+		addEngine( engine, false );
+				
+		log( "Created RSS engine '" + url + "'" );
+		
+		return( engine );
+	}
+	
+	protected void
+	enableUpdateChecks()
+	{
+		synchronized( this ){
+			
+			if ( update_check_timer == null ){
+				
+				update_check_timer = SimpleTimer.addPeriodicEvent(
+						"MS:updater",
+						UPDATE_CHECK_PERIOD,
+						new TimerEventPerformer()
+						{
+							public void 
+							perform(
+								TimerEvent event) 
+							{
+								checkUpdates();
+							}
+						});
+			}
+		}
+	}
+	private void
+	checkUpdates()
+	{
+		update_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void 
+				runSupport() 
+				{
+					checkUpdatesSupport();
+				}
+			});
+	}
+	
+	private void
+	checkUpdatesSupport()
+	{
+		Iterator<EngineImpl> it = engines.iterator();
+		
+		while( it.hasNext()){
+				
+			EngineImpl	engine = (EngineImpl)it.next();
+				
+			String	update_url = engine.getUpdateURL();
+			
+			if ( update_url != null ){
+				
+				long	now				= SystemTime.getCurrentTime();
+				
+				long	last_check 		= engine.getLastUpdateCheck();
+				
+				if ( last_check > now ){
+					
+					last_check = now;
+					
+					engine.setLastUpdateCheck( now );
+				}
+				
+				long	check_secs	= engine.getUpdateCheckSecs();
+				
+				if ( check_secs < MIN_UPDATE_CHECK_SECS ){
+					
+					log( "Engine '" + engine.getName() + "': Update check period too small (" + check_secs + " secs) adjusting to " + MIN_UPDATE_CHECK_SECS + ": " + engine.getName());
+					
+					check_secs = MIN_UPDATE_CHECK_SECS;
+				}
+				
+				long	check_millis	= check_secs*1000;
+				
+				long	next_check		= last_check + check_millis;
+				
+				Object	consec_fails_o = engine.getUserData( MS_UPDATE_CONSEC_FAIL_KEY );
+				
+				int	consec_fails = consec_fails_o==null?0:((Integer)consec_fails_o).intValue();
+				
+				if ( consec_fails > 0 ){
+					
+					next_check += ( UPDATE_CHECK_PERIOD << consec_fails );
+				}
+				
+				if ( next_check < now ){
+				
+					if ( updateEngine( engine )){
+						
+						consec_fails	= 0;
+						
+						engine.setLastUpdateCheck( now );
+						
+					}else{
+						
+						consec_fails++;
+						
+						if ( consec_fails > 3 ){
+							
+							consec_fails	= 0;
+							
+								// skip to next scheduled update time
+							
+							engine.setLastUpdateCheck( now );
+						}
+					}
+					
+					engine.setUserData( MS_UPDATE_CONSEC_FAIL_KEY, consec_fails==0?null:new Integer( consec_fails ));
+				}
+			}
+		}
+	}
+	
+	protected boolean
+	updateEngine(
+		EngineImpl		engine )
+	{
+		String	update_url = engine.getUpdateURL();
+
+		int	pos = update_url.indexOf('?');
+		
+		if ( pos == -1 ){
+			
+			update_url += "?";
+			
+		}else{
+			
+			update_url += "&";
+		}
+		
+		update_url += 	"az_template_uid=" + engine.getUID() + 
+						"&az_template_version=" + engine.getVersion() +
+						"&az_version=" + Constants.AZUREUS_VERSION +
+					    "&az_locale=" + MessageText.getCurrentLocale().toString() +
+					    "&az_rand=" + RandomUtils.nextAbsoluteLong();
+		
+		log( "Engine " + engine.getName() + ": auto-update check via " + update_url );
+		
+		try{
+			ResourceDownloaderFactory rdf = StaticUtilities.getResourceDownloaderFactory();
+			
+			ResourceDownloader url_rd = rdf.create( new URL( update_url ));
+			
+			ResourceDownloader rd = rdf.getMetaRefreshDownloader( url_rd );
+			
+			InputStream is = rd.download();
+			
+			try{
+				Map<String,Object> map = BDecoder.decode( new BufferedInputStream( is ));
+				
+				log( "    update check reply: " + map );
+				
+					// reply is either "response" meaning "no update" and giving possibly changed update secs
+					// or Vuze file with updated template
+				
+				Map<String,Object> response = (Map<String,Object>)map.get( "response" );
+				
+				if ( response != null ){
+					
+					Long	update_secs = (Long)response.get( "update_url_check_secs" );
+					
+					if ( update_secs == null ){
+						
+						engine.setLocalUpdateCheckSecs( 0 );
+						
+					}else{
+						
+						int	check_secs = update_secs.intValue();
+						
+						if ( check_secs < MIN_UPDATE_CHECK_SECS ){
+							
+							log( "    update check secs for to small, min is " + MIN_UPDATE_CHECK_SECS);
+							
+							check_secs = MIN_UPDATE_CHECK_SECS;
+						}
+							
+						engine.setLocalUpdateCheckSecs( check_secs );
+					}
+					
+					return( true );
+					
+				}else{
+					
+					VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( map );
+					
+					if ( vf == null ){
+						
+						log( "    failed to decode vuze file" );
+						
+						return( false );
+					}
+										
+					Engine[] updated_engines = manager.loadFromVuzeFile( vf );
+					
+					if ( updated_engines.length > 0 ){
+						
+						String	existing_uid = engine.getUID();
+						
+						boolean	found = false;
+						
+						String	engine_str = "";
+						
+						for (int i=0;i<updated_engines.length;i++){
+							
+							Engine updated_engine = updated_engines[i];
+							
+							engine_str += (i==0?"":",") + updated_engine.getName() + ": uid=" + updated_engine.getUID() + ",version=" + updated_engine.getVersion();
+							
+							if ( updated_engine.getUID().equals( existing_uid )){
+								
+								found	= true;
+							}
+						}
+						
+						if ( !found ){
+							
+							log( "    existing engine not found in updated set, deleting" );
+							
+							engine.delete();
+							
+						}
+							
+						log( "    update complete: new engines=" + engine_str );
+						
+					}else{
+						
+						log( "    no engines found in vuze file" );
+					}
+					
+					return( true );
+				}
+			}finally{
+				
+				is.close();
+			}
+		}catch( Throwable e ){
+			
+			log( "    update check failed", e );
+			
+			return( false );
+		}
+	}
+	
+	public void 
+	addEngine(
+		Engine 	engine )
+	{
+		addEngine( (EngineImpl)engine, false );
+	}
+	
+	public Engine 
+	addEngine(
+		long 		id )
+	
+		throws MetaSearchException 
+	{
+		try{
+
+			PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( manager.getExtensionKey(), id );
+		
+			log( "Downloading definition of template " + id );
+			log( details.getValue());
+		
+			if ( details.isVisible()){
+			
+				Engine engine = 
+					importFromJSONString( 
+						details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
+						details.getId(),
+						details.getModifiedDate(),
+						details.getRankBias(),
+						details.getName(),
+						details.getValue());
+				
+				engine.setSource( Engine.ENGINE_SOURCE_VUZE );
+				engine.setSelectionState( Engine.SEL_STATE_DESELECTED );
+				
+				addEngine( engine );
+				
+				return( engine );
+				
+			}else{
+				
+				throw( new MetaSearchException( "Search template is not visible" ));
+			}
+		}catch( MetaSearchException e ){
+			
+			throw( e );
+			
+		}catch( Throwable e ){
+		
+			throw( new MetaSearchException( "Template load failed", e ));
+		}	
+	}
+		
+	public void 
+	addEngine(
+		EngineImpl 	new_engine,
+		boolean		loading )
+	{		
+		boolean	add_op = true;
+		
+		synchronized( this ){
+			
+			Iterator<EngineImpl>	it = engines.iterator();
+			
+			while( it.hasNext()){
+				
+				Engine existing_engine = it.next();
+				
+				if ( existing_engine.getId() == new_engine.getId()){
+					
+					log( "Updating engine with same ID " + existing_engine.getId() + ": " + existing_engine.getName() + "/" + existing_engine.getUID());
+					
+					it.remove();
+					
+					new_engine.setUID( existing_engine.getUID());
+					
+					if ( existing_engine.sameLogicAs( new_engine )){
+						
+						new_engine.setVersion( existing_engine.getVersion());
+
+					}else{
+						
+						new_engine.setVersion( existing_engine.getVersion() + 1 );
+						
+						log( "    new version=" + new_engine.getVersion());
+					}
+					 
+					add_op = false;
+					
+				}else if ( existing_engine.getUID().equals( new_engine.getUID())){
+					
+					log( "Removing engine with same UID " + existing_engine.getUID() + "(" + existing_engine.getName() + ")" );
+					
+					it.remove();
+				}
+			}
+			
+			engines.add( new_engine );
+		}
+		
+		if ( new_engine.getUpdateURL() != null ){
+			
+			enableUpdateChecks();
+		}
+		
+		if ( !loading ){
+			
+			log( "Engine '" + new_engine.getName() + "' added" );
+			
+			saveConfig();
+		
+			Iterator<MetaSearchListener> it = listeners.iterator();
+			
+			while( it.hasNext()){
+				
+				MetaSearchListener listener = it.next();
+				
+				try{
+					if ( add_op ){
+						
+						listener.engineAdded( new_engine );
+						
+					}else{
+						
+						listener.engineUpdated( new_engine );
+					}
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+		}
+	}
+	
+	public void 
+	removeEngine(
+		Engine 	engine )
+	{
+		if ( engines.remove((EngineImpl)engine )){
+		
+			log( "Engine '" + engine.getName() + "' removed" );
+			
+			saveConfig();
+			
+			Iterator<MetaSearchListener> it = listeners.iterator();
+			
+			while( it.hasNext()){
+				
+				try{
+	
+					it.next().engineRemoved( engine );
+	
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+		}
+	}
+	
+	public String
+	getFUD()
+	{
+		List<EngineImpl> l = engines.getList();
+		
+		List<Long>	ids = new ArrayList<Long>();
+		
+		for ( EngineImpl engine: l ){
+			
+			if ( engine.getSource() == Engine.ENGINE_SOURCE_VUZE ){
+				
+				ids.add( engine.getId());
+			}
+		}
+		
+		Collections.sort( ids );
+		
+		String	fud = "";
+
+		for ( Long id: ids ){
+		
+			fud += (fud.length()==0?"":",") +id; 
+		}
+		
+		return( fud );
+	}
+	
+	protected void
+	addPotentialAssociation(
+		EngineImpl		engine,
+		String			key )
+	{
+		manager.addPotentialAssociation(engine, key);	
+	}
+	
+	public Engine[] 
+	getEngines(
+		boolean		active_only,
+		boolean		ensure_up_to_date )
+	{
+		if ( ensure_up_to_date ){
+			
+			manager.ensureEnginesUpToDate();
+		}
+		
+		List<EngineImpl> l = engines.getList();
+				
+		List<EngineImpl> result;
+		
+		if ( active_only ){
+			
+			result = new ArrayList<EngineImpl>();
+			
+			for (int i=0;i<l.size();i++){
+				
+				EngineImpl	e = l.get(i);
+				
+				if ( e.isActive()){
+					
+					result.add( e );
+				}
+			}
+		}else{
+			
+			result = l;
+		}
+		
+		return( (Engine[])result.toArray( new Engine[ result.size() ]));
+	}
+	
+	public Engine
+	getEngine(
+		long		id )
+	{
+		List<EngineImpl> l = engines.getList();
+		
+		for( int i=0;i<l.size();i++){
+			
+			Engine e = l.get(i);
+			
+			if ( e.getId() == id ){
+				
+				return( e );
+			}
+		}
+
+		return( null );
+	}
+	
+	public Engine
+	getEngineByUID(
+		String	uid )
+	{
+		List<EngineImpl> l = engines.getList();
+		
+		for( int i=0;i<l.size();i++){
+			
+			Engine e = l.get(i);
+			
+			if ( e.getUID().equals( uid )){
+				
+				return( e );
+			}
+		}
+
+		return( null );
+	}
+	
+	public int
+	getEngineCount()
+	{
+		return( engines.size());
+	}
+	
+	public Engine[] 
+	search(
+		final ResultListener 	original_listener,
+		SearchParameter[] 		searchParameters,
+		String					headers,
+		int						max_results_per_engine )
+	{
+		return( search( original_listener, searchParameters, headers, new HashMap<String,String>(), max_results_per_engine ));
+	}
+	
+	public Engine[] 
+  	search(
+  		final ResultListener 	original_listener,
+  		SearchParameter[] 		searchParameters,
+  		String					headers,
+  		Map<String,String>		context,
+  		int						max_results_per_engine )
+  	{
+  		return( search( null, original_listener, searchParameters, headers, context, max_results_per_engine ));
+  	}
+	
+	public Engine[] 
+	search(
+		Engine[]				engines,
+		final ResultListener 	listener,
+		SearchParameter[] 		search_parameters,
+		String					headers,
+		final int				max_results_per_engine )
+	{
+		return( search( engines, listener, search_parameters, headers, new HashMap<String,String>(), max_results_per_engine ));
+	}
+	
+	public void
+	enginePreferred(
+		Engine		engine )
+	{
+		Engine[] engines = getEngines( true, false );
+		
+		int	num_other_preferred = 0;
+		
+		for ( Engine e: engines ){
+			
+			if ( e.getId() == engine.getId()){
+				
+				e.setPreferredDelta( +1 );
+				
+			}else{
+				
+				if ( e.getPreferredWeighting() > 0 ){
+					
+					num_other_preferred++;
+				}
+			}
+		}
+				
+		if ( num_other_preferred > 0 ){
+			
+			float negative_weighting = -1.0f / num_other_preferred;
+		
+			for ( Engine e: engines ){
+			
+				if ( e.getId() != engine.getId() && e.getPreferredWeighting() > 0 ){
+				
+					e.setPreferredDelta( negative_weighting );
+				}
+			}
+		}
+	}
+	
+	public Engine[] 
+  	search(
+  		Engine[]				engines,
+  		final ResultListener 	original_listener,
+  		SearchParameter[] 		searchParameters,
+  		String					headers,
+  		Map<String,String>		context,
+  		final int				max_results_per_engine )
+	{
+		String batch_millis_str = context.get( Engine.SC_BATCH_PERIOD );
+		
+		final long batch_millis = batch_millis_str==null?0:Long.parseLong( batch_millis_str );
+		
+		String rem_dups_str = context.get( Engine.SC_REMOVE_DUP_HASH );
+		
+		final boolean rem_dups = rem_dups_str==null?false:rem_dups_str.equalsIgnoreCase( "true" );
+
+		ResultListener	listener = 
+			new ResultListener()
+			{
+					// 	single thread listener calls
+			
+				private AsyncDispatcher dispatcher = new AsyncDispatcher( 5000 );
+
+				final private Map<Engine,List<Result[]>>	pending_results = new HashMap<Engine,List<Result[]>>();
+				
+				final private Map<Engine,Set<String>>	result_hashes = new HashMap<Engine, Set<String>>();
+				
+				public void
+				contentReceived(
+					final Engine engine, 
+					final String content ) 
+				{
+					dispatcher.dispatch(
+							new AERunnable()
+							{
+								public void
+								runSupport()
+								{
+									original_listener.contentReceived( engine, content );
+								}
+							});
+				}
+				
+				public void 
+				matchFound(
+					final Engine 	engine, 
+					final String[] 	fields )
+				{
+					dispatcher.dispatch(
+							new AERunnable()
+							{
+								public void
+								runSupport()
+								{
+									original_listener.matchFound( engine, fields );
+								}
+							});	
+				}
+				
+				public void 
+				resultsReceived(
+					final Engine 	engine,
+					final Result[] 	results )
+				{
+					dispatcher.dispatch(
+						new AERunnable()
+						{
+							public void
+							runSupport()
+							{
+								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{
+								
+									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 );
+								}
+							}
+						});
+				}
+			
+				public void 
+				resultsComplete(
+					final Engine engine )
+				{
+					dispatcher.dispatch(
+							new AERunnable()
+							{
+								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 );
+					}
+				}
+				
+				protected Result[]
+             	truncateResults(
+             		Engine		engine,
+             		Result[] 	a_results,
+             		int			max )
+             	{
+					Set<String>	hash_set = result_hashes.get( engine );
+					
+					if ( hash_set == null ){
+						
+						hash_set = new HashSet<String>();
+						
+						result_hashes.put( engine, hash_set );
+					}
+						
+					List<Result>	results = new ArrayList<Result>( a_results.length );
+					
+					for ( Result r: a_results ){
+							
+						String name = r.getName();
+							
+						if ( name == null || name.trim().length() == 0 ){
+								
+							continue;
+						}
+					
+						if ( rem_dups ){
+
+							String hash = r.getHash();
+							
+							if ( 	hash == null ||
+									hash.length() == 0 ){
+								
+								results.add( r );
+								
+							}else{
+								
+								if ( !hash_set.contains( hash )){
+									
+									results.add( r );
+									
+									hash_set.add( hash );
+								}
+							}
+						}else{
+							
+							results.add( r );
+						}
+					}
+					
+             		if ( max < results.size() ){
+             		
+             			log( "Truncating search results for " + engine.getName() + " from " + results.size() + " to " + max );
+             			
+             			Collections.sort(
+             				results,
+             				new Comparator<Result>()
+             				{
+             					Map<Result,Float>	ranks = new HashMap<Result, Float>();
+             					
+             					public int 
+             					compare(
+             						Result r1, 
+             						Result r2) 
+             					{						
+             						Float	rank1 = (Float)ranks.get(r1);
+             						
+             						if ( rank1 == null ){	
+             							rank1 = new Float(r1.getRank());
+             							ranks.put( r1, rank1 );
+             						}
+             						
+             						Float	rank2 = (Float)ranks.get(r2);
+             						
+             						if ( rank2 == null ){	
+             							rank2 = new Float(r2.getRank());
+             							ranks.put( r2, rank2 );
+             						}
+             						
+             						return( rank2.compareTo( rank1 ));
+             					}
+             				});
+             		
+             			Result[] x = new Result[max];
+             			
+             			int	pos = 0;
+             			
+             			while( pos < max ){
+             			
+             				x[pos] = results.get( pos );
+             				
+             				pos++;
+             			}
+             			
+             			return( x );
+             			
+             		}else{
+             			
+             			return( results.toArray( new Result[ results.size()] ));
+             		}
+             	}
+				
+				public void 
+				engineFailed(
+					final Engine 	engine,
+					final Throwable	e )
+				{
+					dispatcher.dispatch(
+							new AERunnable()
+							{
+								public void
+								runSupport()
+								{
+									original_listener.engineFailed( engine, e );
+								}
+							});
+				}
+				
+				public void 
+				engineRequiresLogin(
+					final Engine 	engine,
+					final Throwable	e )
+				{
+					dispatcher.dispatch(
+							new AERunnable()
+							{
+								public void
+								runSupport()
+								{
+									original_listener.engineRequiresLogin( engine, e );
+								}
+							});
+				}
+			};
+			
+		SearchExecuter se = new SearchExecuter( context, listener );
+		
+		if ( engines == null ){
+			
+			engines = getEngines( true, true );
+		}
+		
+		String	engines_str = "";
+		
+		for (int i=0;i<engines.length;i++){
+			
+			engines_str += (i==0?"":",") + engines[i].getId();
+		}
+		
+		log( "Search: engines=" + engines_str );
+		
+		for (int i=0;i<engines.length;i++){
+			
+			se.search( engines[i], searchParameters, headers, max_results_per_engine );
+		}
+		
+		return( engines );
+	}
+	
+	public void
+	exportEngines(
+		File	target )
+	
+		throws MetaSearchException
+	{
+		Engine[] engines = getEngines( true, false );
+		
+		VuzeFile	vf = VuzeFileHandler.getSingleton().create();
+		
+		for ( Engine engine: engines ){
+		
+			try{
+				vf.addComponent(
+					VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE,
+					engine.exportToBencodedMap());
+				
+			}catch( IOException e ){
+				
+				Debug.out( e );
+			}
+			
+		}
+		
+		try{
+			vf.write( target );
+			
+		}catch( IOException e ){
+			
+			throw( new MetaSearchException( "Failed to write file", e ));
+		}
+	}
+	
+	public void
+	addListener(
+		MetaSearchListener		listener )
+	{
+		listeners.add( listener );
+	}
+	
+	public void
+	removeListener(
+		MetaSearchListener		listener )
+	{
+		listeners.remove( listener );
+	}
+	
+	protected void
+	loadConfig()
+	{
+		log( "Loading configuration" );
+		
+		synchronized( this ){
+			
+			Map<String,Object> map = FileUtil.readResilientConfigFile( CONFIG_FILE );
+			
+			List<Map<String,Object>>	l_engines = (List<Map<String,Object>>)map.get( "engines" );
+			
+			if( l_engines != null ){
+				
+				for (int i=0;i<l_engines.size();i++){
+					
+					Map<String,Object>	m = (Map<String,Object>)l_engines.get(i);
+					
+					try{
+						Engine e = importFromBEncodedMap( m );
+						
+						addEngine( (EngineImpl)e, true );
+						
+						log( "    loaded " + e.getString());
+						
+					}catch( Throwable e ){
+						
+						log( "Failed to import engine from " + m, e );
+					}
+				}
+			}
+			
+			Map<String,Long>	p_map = (Map<String,Long>)map.get( "plugin_map" );
+			
+			if ( p_map != null ){
+				
+				plugin_map = p_map;
+			}
+		
+			if ( update_check_timer != null ){
+				
+				checkUpdates();
+			}
+		}
+	}
+	
+	public void
+	configDirty()
+	{
+		synchronized( this ){
+			
+			if ( config_dirty ){
+				
+				return;
+			}
+			
+			config_dirty = true;
+		
+			new DelayedEvent( 
+				"MetaSearch:save", 5000,
+				new AERunnable()
+				{
+					public void 
+					runSupport() 
+					{
+						synchronized( MetaSearchImpl.this ){
+							
+							if ( !config_dirty ){
+
+								return;
+							}
+							
+							saveConfig();
+						}	
+					}
+				});
+		}
+	}
+	
+	protected void
+	saveConfig()
+	{
+		log( "Saving configuration" );
+		
+		synchronized( this ){
+			
+			config_dirty = false;
+			
+			Map<String,Object> map = new HashMap<String, Object>();
+			
+			List<Map<String,Object>>	l_engines = new ArrayList<Map<String,Object>>();
+			
+			map.put( "engines", l_engines );
+			
+			Iterator<EngineImpl>	it = engines.iterator();
+			
+			while( it.hasNext()){
+				
+				Engine e = it.next();
+			
+				try{
+					
+					l_engines.add( e.exportToBencodedMap());
+					
+				}catch( Throwable f ){
+					
+					log( "Failed to export engine " + e.getName(), f );
+				}
+			}
+			
+			if ( plugin_map != null ){
+				
+				map.put( "plugin_map", plugin_map );
+			}
+			
+			FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
+		}
+	}
+	
+	protected void
+	log(
+		String	str )
+	{
+		manager.log( "search :"  + str );
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable 	e )
+	{
+		manager.log( "search :"  +  str, e );
+	}
+	
+	protected void
+	generate(
+		IndentWriter		writer )
+	{
+		Iterator<EngineImpl> it = engines.iterator();
+		
+		while( it.hasNext()){
+				
+			EngineImpl	e = it.next();
+			
+			writer.println( e.getString( true ));
+		}	
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/MetaSearchManagerImpl.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/MetaSearchManagerImpl.java
index 5968765..bab8983 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/MetaSearchManagerImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/MetaSearchManagerImpl.java
@@ -1,2153 +1,2152 @@
-/*
- * Created on May 6, 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.core.metasearch.impl;
-
-import java.io.File;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.*;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
-
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.PluginListener;
-import org.gudy.azureus2.plugins.ui.UIManager;
-import org.gudy.azureus2.plugins.ui.UIManagerEvent;
-import org.gudy.azureus2.plugins.utils.FeatureManager;
-import org.gudy.azureus2.plugins.utils.StaticUtilities;
-import org.gudy.azureus2.plugins.utils.FeatureManager.FeatureDetails;
-import org.gudy.azureus2.plugins.utils.FeatureManager.Licence;
-import org.gudy.azureus2.plugins.utils.search.Search;
-import org.gudy.azureus2.plugins.utils.search.SearchException;
-import org.gudy.azureus2.plugins.utils.search.SearchInitiator;
-import org.gudy.azureus2.plugins.utils.search.SearchInstance;
-import org.gudy.azureus2.plugins.utils.search.SearchListener;
-import org.gudy.azureus2.plugins.utils.search.SearchObserver;
-import org.gudy.azureus2.plugins.utils.search.SearchProvider;
-import org.gudy.azureus2.plugins.utils.search.SearchProviderResults;
-import org.gudy.azureus2.plugins.utils.search.SearchResult;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
-
-import com.aelitis.azureus.core.custom.Customization;
-import com.aelitis.azureus.core.custom.CustomizationManager;
-import com.aelitis.azureus.core.custom.CustomizationManagerFactory;
-import com.aelitis.azureus.core.messenger.config.PlatformMetaSearchMessenger;
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.MetaSearch;
-import com.aelitis.azureus.core.metasearch.MetaSearchException;
-import com.aelitis.azureus.core.metasearch.MetaSearchManager;
-import com.aelitis.azureus.core.metasearch.MetaSearchManagerListener;
-import com.aelitis.azureus.core.metasearch.Result;
-import com.aelitis.azureus.core.metasearch.ResultListener;
-import com.aelitis.azureus.core.metasearch.SearchParameter;
-import com.aelitis.azureus.core.metasearch.impl.plugin.PluginEngine;
-import com.aelitis.azureus.core.subs.Subscription;
-import com.aelitis.azureus.core.subs.SubscriptionManager;
-import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
-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.util.ConstantsVuze;
-import com.aelitis.azureus.util.ImportExportUtils;
-
-public class 
-MetaSearchManagerImpl
-	implements MetaSearchManager, UtilitiesImpl.searchManager, AEDiagnosticsEvidenceGenerator
-{
-	private static final boolean AUTO_MODE_DEFAULT		= true;
-	
-	
-	private static final String	LOGGER_NAME = "MetaSearch";
-	
-	private static final int REFRESH_MILLIS = 23*60*60*1000;
-	
-	private static MetaSearchManagerImpl singleton;	
-	
-	public static void
-	preInitialise()
-	{
-		VuzeFileHandler.getSingleton().addProcessor(
-			new VuzeFileProcessor()
-			{
-				public void
-				process(
-					VuzeFile[]		files,
-					int				expected_types )
-				{
-					for (int i=0;i<files.length;i++){
-						
-						VuzeFile	vf = files[i];
-						
-						VuzeFileComponent[] comps = vf.getComponents();
-						
-						for (int j=0;j<comps.length;j++){
-							
-							VuzeFileComponent comp = comps[j];
-							
-							int	comp_type = comp.getType();
-							
-							if ( comp_type == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
-								
-								try{
-									Engine e = 
-										getSingleton().importEngine(
-											comp.getContent(), 
-											(expected_types & VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE) == 0 );
-									
-									comp.setProcessed();
-									
-									if ( e != null ){
-										
-										comp.setData( Engine.VUZE_FILE_COMPONENT_ENGINE_KEY, e );
-									}
-								}catch( Throwable e ){
-									
-									Debug.printStackTrace(e);
-								}
-							}else if ( comp_type == VuzeFileComponent.COMP_TYPE_METASEARCH_OPERATION ){
-								
-								getSingleton().addOperation( comp.getContent());
-								
-								comp.setProcessed();
-							}
-						}
-					}
-				}
-			});	
-		
-		TorrentUtils.addTorrentAttributeListener(
-				new TorrentUtils.torrentAttributeListener()
-				{
-					public void 
-					attributeSet(
-						TOTorrent 	torrent,
-						String 		attribute, 
-						Object 		value )
-					{
-						if ( 	attribute == TorrentUtils.TORRENT_AZ_PROP_OBTAINED_FROM && 
-								!TorrentUtils.isReallyPrivate( torrent )){
-							
-							try{
-								getSingleton().checkPotentialAssociations( torrent.getHash(), (String)value );
-								
-							}catch( Throwable e ){
-								
-								Debug.printStackTrace(e);
-							}
-						}
-					}
-				});
-	}
-	
-	public static synchronized MetaSearchManagerImpl
-	getSingleton()
-	{
-		if ( singleton == null ){
-			
-			singleton = new MetaSearchManagerImpl();
-		}
-		return( singleton );
-	}
-	
-	private MetaSearchImpl	meta_search;
-	private AsyncDispatcher	dispatcher = new AsyncDispatcher( 10000 );
-	
-	private AESemaphore	initial_refresh_sem = new AESemaphore( "MetaSearch:initrefresh" );
-	
-	private AESemaphore	refresh_sem = new AESemaphore( "MetaSearch:refresh", 1 );
-	
-	private boolean	checked_customization;
-	
-	private AsyncDispatcher					op_dispatcher 	= new AsyncDispatcher(5*1000);
-	private List<MetaSearchManagerListener>	listeners 		= new ArrayList<MetaSearchManagerListener>();
-	private List<Map>						operations		= new ArrayList<Map>();
-	
-	private String		extension_key;
-	
-	private Map<String,EngineImpl>	potential_associations = 
-		new LinkedHashMap<String,EngineImpl>(32,0.75f,true)
-		{
-			protected boolean 
-			removeEldestEntry(
-		   		Map.Entry<String,EngineImpl> eldest) 
-			{
-				return size() > 32;
-			}
-		};
-	protected
-	MetaSearchManagerImpl()
-	{
-		meta_search = new MetaSearchImpl( this );
-		
-		AEDiagnostics.addEvidenceGenerator( this );
-		
-		extension_key = COConfigurationManager.getStringParameter( "metasearch.extkey.latest", "" );
-
-		if ( extension_key.length() == 0 ){
-			
-			extension_key = null;
-		}
-		
-		setupExtensions();
-		
-		SimpleTimer.addPeriodicEvent(
-			"MetaSearchRefresh",
-			REFRESH_MILLIS,
-			new TimerEventPerformer()
-			{
-				public void 
-				perform(
-					TimerEvent 	event ) 
-				{
-					refresh();
-				}
-			});
-		
-		refresh();
-		
-		UtilitiesImpl.addSearchManager( this );
-	}
-	
-	public void 
-	addProvider(
-		PluginInterface		pi,
-		SearchProvider 		provider ) 
-	{
-		String	id = pi.getPluginID() + "." + provider.getProperty( SearchProvider.PR_NAME );
-		
-		try{
-			meta_search.importFromPlugin( id, provider );
-			
-		}catch( Throwable e ){
-			
-			Debug.out( "Failed to add search provider '" + id + "' (" + provider + ")", e );
-		}
-	}
-	
-	public void 
-	removeProvider(
-		PluginInterface		pi,
-		SearchProvider 		provider ) 
-	{
-		String	id = pi.getPluginID() + "." + provider.getProperty( SearchProvider.PR_NAME );
-		
-		try{
-			Engine[] engines = meta_search.getEngines( false, false );
-			
-			for ( Engine engine: engines ){
-				
-				if ( engine instanceof PluginEngine ){
-					
-					PluginEngine pe = (PluginEngine)engine;
-					
-					if ( pe.getProvider() == provider ){
-						
-						engine.delete();
-					}
-				}
-			}
-		}catch( Throwable e ){
-			
-			Debug.out( "Failed to remove search provider '" + id + "' (" + provider + ")", e );
-		}
-	}
-	
-	public SearchProvider[]
-  	getProviders()
-	{
-		Engine[] engines = meta_search.getEngines( true, false );
-		
-		SearchProvider[] result = new SearchProvider[engines.length];
-		
-		for (int i=0;i<engines.length;i++){
-				
-			result[i] = new engineInfo( engines[i] );
-		}
-		
-		return( result );
-	}
-	
-	public Search 
-	createSearch(
-		String 		provider_ids,
-		String 		properties_str )
-	
-		throws SearchException 
-	{
-		String[]	bits = XUXmlWriter.splitWithEscape( provider_ids, ',' );
-		
-		long[]	pids = new long[ bits.length ];
-		
-		for ( int i=0; i<bits.length; i++ ){
-			
-			pids[i] = Long.parseLong( bits[i] );
-		}
-
-		Map<String,String>	properties = new HashMap<String, String>();
-		
-		bits = XUXmlWriter.splitWithEscape( properties_str, ',' );
-
-		for ( int i=0; i<bits.length; i++ ){
-
-			String[] x = XUXmlWriter.splitWithEscape( bits[i], '=' );
-			
-			properties.put( x[0].trim(), x[1].trim());
-		}
-		
-		return( createSearch( pids, properties, null ));
-	}
-	
-  	public Search
-  	createSearch(
-  		SearchProvider[]	providers,
-  		Map<String,String>	properties,
-  		SearchListener		listener )
-  	
-  		throws SearchException
-  	{
-  		long[]	pids;
-  		
-  		if ( providers == null ){
-  			
-  			pids = new long[0];
-  			
-  		}else{
-  			
-  			pids = new long[providers.length];
-  			
-  			for (int i=0;i<pids.length;i++){
-			
-  				Long	id = (Long)providers[i].getProperty( SearchProvider.PR_ID );
-			
-  				if ( id == null ){
-				
-  					throw( new SearchException( "Unknown provider - no id available" ));
-  				}
-  				
-  				pids[i] = id;
-			}
-  		}
-  		
-  		return( createSearch( pids, properties, listener ));
-  	}
-  	
-  	protected Search
-  	createSearch(
-  		long[]				provider_ids,
-  		Map<String,String>	properties,
-  		SearchListener		listener )
-  	
-  		throws SearchException
-  	{
-		List<SearchParameter>	sps = new ArrayList<SearchParameter>();
-
- 		String	search_term = properties.get( SearchInitiator.PR_SEARCH_TERM );
- 		
- 		if ( search_term == null ){
- 			
- 			throw( new SearchException( "Search term is mandatory" ));
- 		}
- 		
-		sps.add( new SearchParameter( "s", search_term ));
-
- 		String	mature 		= properties.get( SearchInitiator.PR_MATURE );
-  		
-		if ( mature != null ){
-			
-			sps.add( new SearchParameter( "m", mature.toString()));
-		}
-	
-		SearchParameter[] parameters = (SearchParameter[])sps.toArray(new SearchParameter[ sps.size()] );
-
-		Map<String,String>	context = new HashMap<String, String>();
-		
-		context.put( Engine.SC_FORCE_FULL, "true" );
-
-		String	headers 		= null;
-		int		max_per_engine	= 256;
-		
-		SearchObject search = new SearchObject( listener );
-		
-		Engine[]	used_engines;
-		
-		if ( provider_ids.length == 0 ){
-			
-			used_engines = getMetaSearch().search( search, parameters, headers, context, max_per_engine );
-
-		}else{
-			
-			List<Engine>	selected_engines = new ArrayList<Engine>();
-			
-			for ( long id: provider_ids ){
-				
-				Engine engine = meta_search.getEngine( id );
-				
-				if ( engine == null ){
-					
-					throw( new SearchException( "Unknown engine id - " + id ));
-					
-				}else{
-					
-					selected_engines.add( engine );
-				}
-			}
-			
-			Engine[] engines = selected_engines.toArray( new Engine[ selected_engines.size()] );
-	
-			used_engines = getMetaSearch().search( engines, search, parameters, headers, context, max_per_engine );
-		}
-		
-		search.setEnginesUsed( used_engines );
-		
-		return( search );
-  	}
-	
-	protected void
-	refresh()
-	{
-		dispatcher.dispatch(
-			new AERunnable()
-			{
-				public void 
-				runSupport() 
-				{
-					if ( dispatcher.getQueueSize() == 0 ){
-						
-						try{
-							syncRefresh();
-														
-						}catch( Throwable e ){
-							
-						}
-					}
-				}
-			});
-	}
-	
-	protected void
-	ensureEnginesUpToDate()
-	{
-		long timeout = meta_search.getEngineCount() == 0?(30*1000):(10*1000);
-		
-		if ( !initial_refresh_sem.reserve( timeout )){
-			
-			log( "Timeout waiting for initial refresh to complete, continuing" );
-		}
-	}
-	
-	protected void
-	syncRefresh()
-	
-		throws MetaSearchException
-	{
-		boolean refresh_completed 	= false;
-		boolean	first_run			= false;
-		
-		try{
-			refresh_sem.reserve();
-			
-			first_run = COConfigurationManager.getBooleanParameter( "metasearch.refresh.first_run", true );
-			
-			if ( !checked_customization ){
-				
-				checked_customization = true;
-				
-				CustomizationManager cust_man = CustomizationManagerFactory.getSingleton();
-				
-				Customization cust = cust_man.getActiveCustomization();
-				
-				if ( cust != null ){
-					
-					String cust_name 	= COConfigurationManager.getStringParameter( "metasearch.custom.name", "" );
-					String cust_version = COConfigurationManager.getStringParameter( "metasearch.custom.version", "0" );
-					
-					boolean	new_name 	= !cust_name.equals( cust.getName());
-					boolean	new_version = org.gudy.azureus2.core3.util.Constants.compareVersions( cust_version, cust.getVersion() ) < 0;
-					
-					if ( new_name || new_version ){
-
-						log( "Customization: checking templates for " + cust.getName() + "/" + cust.getVersion());
-						
-						try{
-							InputStream[] streams = cust.getResources( Customization.RT_META_SEARCH_TEMPLATES );
-							
-							if ( streams.length > 0 && new_name ){
-								
-									// reset engines
-								
-								log( "    setting auto-mode to false" );
-								
-								setAutoMode( false );
-								
-								/*
-								Engine[]	engines = meta_search.getEngines( false, false );
-
-								for (int i=0;i<engines.length;i++){
-									
-									Engine engine = engines[i];
-									
-									if ( engine.getSelectionState()) == Engine.SEL_STATE_MANUAL_SELECTED ){
-										
-									}
-								}
-								*/
-							}
-							for (int i=0;i<streams.length;i++){
-								
-								InputStream is = streams[i];
-								
-								try{
-									VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile(is);
-									
-									if ( vf != null ){
-										
-										VuzeFileComponent[] comps = vf.getComponents();
-										
-										for (int j=0;j<comps.length;j++){
-											
-											VuzeFileComponent comp = comps[j];
-											
-											if ( comp.getType() == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
-												
-												try{
-													Engine e = 
-														getSingleton().importEngine( comp.getContent(), false ); 
-													
-													log( "    updated " + e.getName());
-													
-													e.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
-													
-												}catch( Throwable e ){
-													
-													Debug.printStackTrace(e);
-												}
-											}
-										}
-									}
-								}finally{
-									
-									try{
-										is.close();
-										
-									}catch( Throwable e ){
-									}
-								}
-							}
-						}finally{
-							
-							COConfigurationManager.setParameter( "metasearch.custom.name", cust.getName());
-							COConfigurationManager.setParameter( "metasearch.custom.version", cust.getVersion());
-						}
-					}
-				}
-			}
-			
-			log( "Refreshing engines" );
-					
-				// featured templates are always shown - can't be deselected
-				// popular ones are selected if in 'auto' mode
-				// manually selected ones are, well, manually selected
-			
-			Map<Long,PlatformMetaSearchMessenger.templateInfo>		vuze_selected_ids 		= new HashMap<Long, PlatformMetaSearchMessenger.templateInfo>();
-			Map<Long,PlatformMetaSearchMessenger.templateInfo>		vuze_preload_ids 		= new HashMap<Long,PlatformMetaSearchMessenger.templateInfo>();
-			
-			Set<Long>		featured_ids 			= new HashSet<Long>();
-			Set<Long>		popular_ids 			= new HashSet<Long>();
-			Set<Long>		manual_vuze_ids 		= new HashSet<Long>();
-			
-			boolean		auto_mode = isAutoMode();
-					
-			Engine[]	engines = meta_search.getEngines( false, false );
-	
-			String	fud = meta_search.getFUD();
-			
-			try{
-				PlatformMetaSearchMessenger.templateInfo[] featured = PlatformMetaSearchMessenger.listFeaturedTemplates( extension_key, fud );
-				
-				String featured_str = "";
-				
-				for (int i=0;i<featured.length;i++){
-					
-					PlatformMetaSearchMessenger.templateInfo template = featured[i];
-					
-					if ( !template.isVisible()){
-						
-						continue;
-					}
-					
-					Long key = new Long( template.getId());
-					
-					vuze_selected_ids.put( key,	template );
-					
-					featured_ids.add( key );
-					
-					featured_str += (featured_str.length()==0?"":",") + key;
-				}
-					
-				log( "Featured templates: " + featured_str );
-				
-				if ( auto_mode || first_run ){
-					
-					PlatformMetaSearchMessenger.templateInfo[] popular = PlatformMetaSearchMessenger.listTopPopularTemplates( extension_key, fud );
-					
-					String popular_str = "";
-					String preload_str = "";
-					
-					for (int i=0;i<popular.length;i++){
-						
-						PlatformMetaSearchMessenger.templateInfo template = popular[i];
-						
-						if ( !template.isVisible()){
-							
-							continue;
-						}
-						
-						Long	key = new Long( template.getId());
-						
-						if ( auto_mode ){
-							
-							if ( !vuze_selected_ids.containsKey( key )){
-								
-								vuze_selected_ids.put( key,	template );
-								
-								popular_ids.add( key );
-								
-								popular_str += (popular_str.length()==0?"":",") + key;
-							}
-						}else{
-							
-							if ( !vuze_preload_ids.containsKey( key )){
-								
-								vuze_preload_ids.put( key, template );
-																
-								preload_str += (preload_str.length()==0?"":",") + key;
-							}
-						}
-					}
-					
-					log( "Popular templates: " + popular_str );
-					
-					if ( preload_str.length() > 0 ){
-						
-						log( "Pre-load templates: " + popular_str );
-					}
-				}
-						
-					// pick up explicitly selected vuze ones
-				
-				String manual_str = "";
-				
-				for (int i=0;i<engines.length;i++){
-					
-					Engine	engine = engines[i];
-					
-					Long key = new Long( engine.getId());
-					
-					if ( 	engine.getSource() == Engine.ENGINE_SOURCE_VUZE &&
-							engine.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED &&
-							!vuze_selected_ids.containsKey( key )){
-						
-						manual_vuze_ids.add( key );
-					}
-				}
-				
-				if ( manual_vuze_ids.size() > 0 ){
-					
-					long[]	manual_ids = new long[manual_vuze_ids.size()];
-					
-					Iterator<Long> it = manual_vuze_ids.iterator();
-					
-					int	pos = 0;
-					
-					while( it.hasNext()){
-						
-						manual_ids[pos++] = it.next().longValue();
-					}
-					
-					PlatformMetaSearchMessenger.templateInfo[] manual = PlatformMetaSearchMessenger.getTemplateDetails( extension_key, manual_ids );
-										
-					for (int i=0;i<manual.length;i++){
-						
-						PlatformMetaSearchMessenger.templateInfo template = manual[i];
-						
-						if ( !template.isVisible()){
-							
-							continue;
-						}
-						
-						Long	key = new Long( template.getId());
-													
-						vuze_selected_ids.put( key, template );
-														
-						manual_str += (manual_str.length()==0?"":",") + key;
-					}
-				}
-				
-				log( "Manual templates: " + manual_str );
-				
-				Map<Long,Engine> existing_engine_map = new HashMap<Long,Engine>();
-				
-				String existing_str = "";
-				
-				for (int i=0;i<engines.length;i++){
-					
-					Engine	engine = engines[i];
-					
-					Long key = new Long( engine.getId());
-	
-					existing_engine_map.put( key, engine );
-					
-					existing_str += (existing_str.length()==0?"":",") + key + 
-										"[source=" + Engine.ENGINE_SOURCE_STRS[engine.getSource()] +
-										",type=" + engine.getType() + 
-										",selected=" + Engine.SEL_STATE_STRINGS[engine.getSelectionState()] + "]";
-				}
-				
-				log( "Existing templates: " + existing_str );
-				
-					// we've compiled a list of the engines we should have and their latest dates
-				
-					// update any that are out of date
-				
-				Iterator<Map.Entry<Long,PlatformMetaSearchMessenger.templateInfo>> it = vuze_selected_ids.entrySet().iterator();
-				
-				while( it.hasNext()){
-					
-					Map.Entry<Long,PlatformMetaSearchMessenger.templateInfo> entry = it.next();
-					
-					vuze_preload_ids.remove( entry.getKey());
-					
-					long	id 			= entry.getKey().longValue();
-					
-					PlatformMetaSearchMessenger.templateInfo template = entry.getValue();
-					
-					long	modified 	= template.getModifiedDate();
-									
-					Engine this_engine = (Engine)existing_engine_map.get( new Long(id));
-					
-					boolean	update = this_engine == null || this_engine.getLastUpdated() < modified;
-	
-					if ( update ){
-						
-						PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( extension_key, id );
-	
-						log( "Downloading definition of template " + id );
-						log( details.getValue());
-						
-						if ( details.isVisible()){
-							
-							try{
-								this_engine = 
-									meta_search.importFromJSONString( 
-										details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
-										details.getId(),
-										details.getModifiedDate(),
-										details.getRankBias(),
-										details.getName(),
-										details.getValue());
-								
-								this_engine.setSource( Engine.ENGINE_SOURCE_VUZE );
-																
-								meta_search.addEngine( this_engine );
-								
-							}catch( Throwable e ){
-								
-								log( "Failed to import engine '" + details.getValue() + "'", e );
-							}
-						}	
-					}else if ( this_engine.getRankBias() != template.getRankBias()){
-						
-						this_engine.setRankBias( template.getRankBias());
-						
-						log( "Updating rank bias for " + this_engine.getString() + " to " + template.getRankBias());
-
-					}else{
-						
-						log( "Not updating " + this_engine.getString() + " as unchanged" );
-					}
-					
-					if ( this_engine != null ){
-							
-						int sel_state = this_engine.getSelectionState();
-						
-						if ( sel_state == Engine.SEL_STATE_DESELECTED ){
-						
-							log( "Auto-selecting " + this_engine.getString());
-							
-							this_engine.setSelectionState( Engine.SEL_STATE_AUTO_SELECTED );
-							
-						}else if ( auto_mode && sel_state == Engine.SEL_STATE_MANUAL_SELECTED ){
-							
-							log( "Switching Manual to Auto select for " + this_engine.getString());
-							
-							this_engine.setSelectionState( Engine.SEL_STATE_AUTO_SELECTED );
-						}
-					}
-				}
-				
-					// do any pre-loads
-				
-				it = vuze_preload_ids.entrySet().iterator();
-				
-				while( it.hasNext()){
-					
-					Map.Entry<Long,PlatformMetaSearchMessenger.templateInfo> entry = it.next();
-					
-					long	id 			= ((Long)entry.getKey()).longValue();
-									
-					Engine this_engine = (Engine)existing_engine_map.get( new Long(id));
-						
-					if ( this_engine == null ){
-						
-						PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( extension_key, id );
-	
-						log( "Downloading pre-load definition of template " + id );
-						log( details.getValue());
-						
-						if ( details.isVisible()){
-							
-							try{
-								this_engine = 
-									meta_search.importFromJSONString( 
-										details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
-										details.getId(),
-										details.getModifiedDate(),
-										details.getRankBias(),
-										details.getName(),
-										details.getValue());
-								
-								this_engine.setSource( Engine.ENGINE_SOURCE_VUZE );
-								
-								this_engine.setSelectionState( Engine.SEL_STATE_DESELECTED );
-																
-								meta_search.addEngine( this_engine );
-								
-							}catch( Throwable e ){
-								
-								log( "Failed to import engine '" + details.getValue() + "'", e );
-							}
-						}			
-					}
-				}
-				
-					// deselect any not in use
-				
-				for (int i=0;i<engines.length;i++){
-					
-					Engine	engine = engines[i];
-					
-					if ( 	engine.getSource() == Engine.ENGINE_SOURCE_VUZE &&
-							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");
-						
-						engine.setSelectionState( Engine.SEL_STATE_DESELECTED );
-					}
-				}
-				
-					// finally pick up any unreported selection changes and re-affirm positive selections
-				
-				for (int i=0;i<engines.length;i++){
-					
-					Engine	engine = engines[i];
-					
-					if ( 	engine.getSource() == Engine.ENGINE_SOURCE_VUZE &&
-							engine.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED ){
-						
-						engine.recordSelectionState();
-						
-					}else{
-						
-						engine.checkSelectionStateRecorded();
-					}
-				}
-				
-				refresh_completed = true;
-				
-			}catch( Throwable e ){
-				
-				log( "Refresh failed", e );
-				
-				throw( new MetaSearchException( "Refresh failed", e ));
-			}
-		}finally{
-			
-			if ( first_run && refresh_completed ){
-				
-				COConfigurationManager.setParameter( "metasearch.refresh.first_run", false );
-			}
-			
-			refresh_sem.release();
-			
-			initial_refresh_sem.releaseForever();
-		}
-	}
-	
-	public MetaSearch 
-	getMetaSearch() 
-	{
-		return( meta_search );
-	}
-	
-	public boolean
-	isAutoMode()
-	{
-		return( COConfigurationManager.getBooleanParameter( "metasearch.auto.mode", AUTO_MODE_DEFAULT ));
-	}
-	
-	protected void
-	setAutoMode(
-		boolean	auto )
-	{
-		COConfigurationManager.setParameter( "metasearch.auto.mode", auto );
-	}
-	
-	public void
-	setSelectedEngines(
-		long[]		ids,
-		boolean		auto )
-	
-		throws MetaSearchException
-	{
-		try{
-			String	s = "";
-			
-			for (int i=0;i<ids.length;i++){
-				
-				s += (i==0?"":",") + ids[i];
-			}
-			
-			log( "setSelectedIds: " + s + ", auto=" + auto );
-			
-				// first update state of auto and existing engines 
-			
-			COConfigurationManager.setParameter( "metasearch.auto.mode", auto );
-
-			Engine[]	engines = meta_search.getEngines( false, false );
-			
-			Map<Long,Engine>	engine_map = new HashMap<Long,Engine>();
-			
-			for( int i=0;i<engines.length;i++){
-				
-				engine_map.put( new Long( engines[i].getId()), engines[i] );
-			}
-				
-			Set<Engine> selected_engine_set = new HashSet<Engine>();
-			
-			for (int i=0;i<ids.length;i++){
-				
-				long	 id = ids[i];
-				
-				Engine existing = (Engine)engine_map.get(new Long(id));
-				
-				if ( existing != null ){
-					
-					existing.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
-					
-					selected_engine_set.add( existing );
-				}
-			}
-		
-				// now refresh - this will pick up latest state of things
-			
-			syncRefresh();
-			
-			engines = meta_search.getEngines( false, false );
-
-				// next add in any missing engines
-			
-			for (int i=0;i<ids.length;i++){
-				
-				long	 id = ids[i];
-				
-				Engine existing = (Engine)engine_map.get(new Long(id));
-				
-				if ( existing == null ){
-														
-					PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( extension_key, id );
-	
-					log( "Downloading definition of template " + id );
-					log( details.getValue());
-					
-					Engine new_engine = 
-						meta_search.importFromJSONString( 
-							details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
-							details.getId(),
-							details.getModifiedDate(),
-							details.getRankBias(),
-							details.getName(),
-							details.getValue());
-							
-					new_engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
-										
-					new_engine.setSource( Engine.ENGINE_SOURCE_VUZE );
-						
-					meta_search.addEngine( new_engine );
-					
-					selected_engine_set.add( new_engine );
-				}
-			}
-			
-				// deselect any existing manually selected ones that are no longer selected
-			
-			for( int i=0;i<engines.length;i++){
-
-				Engine e = engines[i];
-				
-				if ( e.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED ){
-					
-					if ( !selected_engine_set.contains( e )){
-				
-						e.setSelectionState( Engine.SEL_STATE_DESELECTED  );
-					}
-				}
-			}
-		}catch( Throwable e ){
-			
-			e.printStackTrace();
-			
-			if ( e instanceof MetaSearchException ){
-				
-				throw((MetaSearchException)e);
-			}
-			
-			throw( new MetaSearchException( "Failed to set selected engines", e ));
-		}
-	}
-	
-	public Engine
-	addEngine(
-		long		id,
-		int			type,
-		String		name,
-		String		json_value )
-	
-		throws MetaSearchException
-	{
-		if ( id == -1 ){
-			
-			id = getLocalTemplateID();
-		}
-		
-		try{
-			Engine engine = 
-				meta_search.importFromJSONString( 
-					type, id, SystemTime.getCurrentTime(), 1, name, json_value );
-			
-			engine.setSource( Engine.ENGINE_SOURCE_LOCAL );
-			
-			engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
-			
-			meta_search.addEngine( engine );
-			
-			return( engine );
-			
-		}catch( Throwable e ){
-			
-			throw( new MetaSearchException( "Failed to add engine", e ));
-		}
-	}
-	
-	public boolean
-	isImportable(
-		VuzeFile		vf )
-	{
-		VuzeFileComponent[] comps = vf.getComponents();
-		
-		for (int j=0;j<comps.length;j++){
-			
-			VuzeFileComponent comp = comps[j];
-			
-			int	comp_type = comp.getType();
-			
-			if ( comp_type == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
-				
-				try{
-					EngineImpl engine = (EngineImpl)meta_search.importFromBEncodedMap( comp.getContent());
-					
-					long	id = engine.getId();
-					
-					Engine existing = meta_search.getEngine( id );
-					
-					if ( existing != null ){
-						
-						if ( existing.getSelectionState() == Engine.SEL_STATE_DESELECTED || !existing.sameLogicAs( engine )){
-							
-							return( true );
-						}
-					}else{
-						try{						
-							Engine[] engines = meta_search.getEngines( false, false );
-								
-							boolean is_new = true;
-							
-							for ( Engine e: engines ){
-									
-								if ( e.getSelectionState() != Engine.SEL_STATE_DESELECTED && e.sameLogicAs( engine )){
-										
-									is_new = false;
-									
-									break;
-								}
-							}
-							
-							if ( is_new ){
-								
-								return( true );
-							}
-						}catch( Throwable e ){	
-						}	
-					}
-				}catch( Throwable e ){				
-				}
-			}
-		}
-		
-		return( false );
-	}
-	
-	public Engine
-	importEngine(
-		Map			map,
-		boolean		warn_user )
-	
-		throws MetaSearchException
-	{
-		try{
-			EngineImpl engine = (EngineImpl)meta_search.importFromBEncodedMap(map);
-			
-			long	id = engine.getId();
-			
-			Engine existing = meta_search.getEngine( id );
-			
-			if ( existing != null ){
-				
-				if ( existing.sameLogicAs( engine )){
-					
-					if ( warn_user ){
-						
-						UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-						
-						String details = MessageText.getString(
-								"metasearch.addtemplate.dup.desc",
-								new String[]{ engine.getName() });
-						
-						ui_manager.showMessageBox(
-								"metasearch.addtemplate.dup.title",
-								"!" + details + "!",
-								UIManagerEvent.MT_OK );
-					}
-					
-					return( existing );
-				}
-			}else{
-									
-				try{						
-					Engine[] engines = meta_search.getEngines( false, false );
-						
-					for ( Engine e: engines ){
-							
-						if ( e.sameLogicAs( engine )){
-								
-							return( e );
-						}
-					}
-				}catch( Throwable e ){
-					
-				}
-			}
-			
-			if ( warn_user ){
-				
-				UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-				
-				String details = MessageText.getString(
-						"metasearch.addtemplate.desc",
-						new String[]{ engine.getName() });
-				
-				long res = ui_manager.showMessageBox(
-						"metasearch.addtemplate.title",
-						"!" + details + "!",
-						UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
-				
-				if ( res != UIManagerEvent.MT_YES ){
-					
-					throw( new MetaSearchException( "User declined the template" ));
-				}
-			}
-				// if local template then we try to use the id as is otherwise we emsure that
-				// it is a local one
-			
-			if ( id >= 0 && id < Integer.MAX_VALUE ){
-				
-				id = getLocalTemplateID();
-				
-				engine.setId( id );
-			}
-			
-			engine.setSource( Engine.ENGINE_SOURCE_LOCAL );
-			
-			engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
-			
-			meta_search.addEngine( engine );
-			
-			if ( warn_user ){
-				
-				UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-				
-				String details = MessageText.getString(
-						"metasearch.addtemplate.done.desc",
-						new String[]{ engine.getName() });
-				
-				ui_manager.showMessageBox(
-						"metasearch.addtemplate.done.title",
-						"!" + details + "!",
-						UIManagerEvent.MT_OK );
-			}
-			
-			return( engine );
-			
-		}catch( Throwable e ){
-			
-			if ( warn_user ){
-				
-				UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-				
-				String details = MessageText.getString(
-						"metasearch.addtemplate.failed.desc",
-						new String[]{ Debug.getNestedExceptionMessage(e) });
-				
-				ui_manager.showMessageBox(
-						"metasearch.addtemplate.failed.title",
-						"!" + details + "!",
-						UIManagerEvent.MT_OK );
-			}
-			
-			throw( new MetaSearchException( "Failed to add engine", e ));
-		}
-	}
-	
-	protected void
-	addPotentialAssociation(
-		EngineImpl		engine,
-		String			key )
-	{		
-		if ( engine.isShareable() && !engine.isAuthenticated()){
-			
-			synchronized( potential_associations ){
-				
-				potential_associations.put( key, engine );
-			}
-		}
-	}
-	
-	private void
-	checkPotentialAssociations(
-		byte[]		hash,
-		String		key )
-	{
-		EngineImpl	engine;
-		
-		synchronized( potential_associations ){
-			
-			engine = potential_associations.remove( key );
-		}
-	
-		if ( engine != null ){
-	
-			try{
-				VuzeFile vf = engine.exportToVuzeFile( true );
-				
-				byte[] bytes = vf.exportToBytes();
-												
-				String url_str = "vuze://?body=" + new String( bytes, Constants.BYTE_ENCODING );
-								
-				SubscriptionManager sub_man = SubscriptionManagerFactory.getSingleton();
-		
-				Subscription subs =
-					sub_man.createSingletonRSS(
-						vf.getName() + ": " + engine.getName() + " (v" + engine.getVersion() + ")",
-						new URL( url_str ),
-						Integer.MAX_VALUE );
-			
-				subs.setSubscribed( true );
-			
-				subs.addAssociation( hash );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}
-	}
-	
-	public Engine[]
-	loadFromVuzeFile(
-		File		file )
-	{
-		VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( file.getAbsolutePath());
-		
-		if ( vf != null ){
-			
-			return( loadFromVuzeFile( vf ));
-		}
-		
-		return( new Engine[0]);
-	}
-	
-	public Engine[]
-	loadFromVuzeFile(
-		VuzeFile		vf )
-	{
-		List<Engine>	result = new ArrayList<Engine>();
-		
-		VuzeFileComponent[] comps = vf.getComponents();
-		
-		for (int j=0;j<comps.length;j++){
-			
-			VuzeFileComponent comp = comps[j];
-			
-			if ( comp.getType() == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
-				
-				try{
-					result.add( importEngine( comp.getContent(), false ));
-											
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-		}
-		
-		return(result.toArray(new Engine[result.size()]));
-	}
-	
-	public long
-	getLocalTemplateID()
-	{
-		synchronized( this ){
-			
-			Random random = new Random();
-			
-			while( true ){
-			
-				long id = ((long)Integer.MAX_VALUE) + random.nextInt( Integer.MAX_VALUE );
-				
-				if ( meta_search.getEngine( id ) == null ){
-					
-					return( id );
-				}
-			}
-		}
-	}
-	
-	public void
-	addListener(
-		MetaSearchManagerListener		listener )
-	{			
-		synchronized( listeners ){
-			
-			listeners.add( listener );
-		}
-			
-		dispatchOps();
-	}
-	
-	public void
-	removeListener(
-		MetaSearchManagerListener		listener )
-	{
-		
-	}
-	
-	private void
-	addOperation(
-		Map		map )
-	{
-		synchronized( listeners ){
-			
-			operations.add( map );
-		}
-		
-		dispatchOps();
-	}
-	
-	private void
-	dispatchOps()
-	{
-		op_dispatcher.dispatch(
-			new AERunnable()
-			{
-				public void
-				runSupport()
-				{
-					List<MetaSearchManagerListener>	l;
-					List<Map>						o;
-					
-					synchronized( listeners ){
-					
-						if ( listeners.size() == 0 || operations.size() == 0 ){
-							
-							return;
-						}
-						
-						l = new ArrayList<MetaSearchManagerListener>( listeners );
-						
-						o = new ArrayList<Map>( operations );
-						
-						operations.clear();
-					}
-					
-					for ( MetaSearchManagerListener listener: l ){
-						
-						for ( Map operation: o ){
-					
-							try{
-
-								int	type = ImportExportUtils.importInt( operation, "type", -1 );
-								
-								if ( type == 1 ){
-									
-									String	term = ImportExportUtils.importString( operation, "term", null );
-								
-									if ( term == null ){
-										
-										Debug.out( "search term missing" );
-										
-									}else{
-										
-										listener.searchRequest( term );
-									}
-								}else{
-								
-									Debug.out( "unknown operation type " + type );
-								}								
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-						}
-					}
-				}
-			});
-	}
-	
-	private void
-	setupExtensions()
-	{
-		PluginInterface pi = PluginInitializer.getDefaultInterface();
-		
-		final FeatureManager fm = pi.getUtilities().getFeatureManager();
-					
-		fm.addListener(
-			new FeatureManager.FeatureManagerListener()
-			{
-				public void
-				licenceAdded(
-					Licence	licence )
-				{
-					getExtensions( fm, false );
-				}
-				
-				public void
-				licenceChanged(
-					Licence	licence )
-				{
-					getExtensions( fm, false );
-				}
-				
-				public void
-				licenceRemoved(
-					Licence	licence )
-				{
-					getExtensions( fm, false );
-				}
-			});
-		
-		if ( pi.getPluginState().isInitialisationComplete()){
-			
-			getExtensions( fm, true );
-			
-		}else{
-			
-			pi.addListener(
-				new PluginListener()
-				{
-					public void
-					initializationComplete()
-					{
-						getExtensions( fm, false );
-					}
-					
-					public void
-					closedownInitiated()
-					{
-					}
-					
-					public void
-					closedownComplete()
-					{	
-					}
-				});
-		}
-	}
-	
-	private void
-	getExtensions(
-		FeatureManager		fm,
-		boolean				init )
-	{
-		String	existing_ext 	= extension_key;
-		String	latest_ext		= null;
-		
-		FeatureDetails[] fds = fm.getFeatureDetails( "core" );
-		
-		for ( FeatureDetails fd: fds ){
-				
-			if ( !fd.hasExpired()){
-				
-				String finger_print = (String)fd.getProperty( FeatureDetails.PR_FINGERPRINT );
-					
-				if ( finger_print != null ){
-				
-					latest_ext = fd.getLicence().getShortID() + "-" + finger_print;
-					
-					break;
-				}
-			}
-		}
-
-		if ( existing_ext != latest_ext ){
-			
-			if ( existing_ext == null || latest_ext == null || !existing_ext.equals( latest_ext )){
-				
-				extension_key	= latest_ext;
-				
-				COConfigurationManager.setParameter( "metasearch.extkey.latest", latest_ext==null?"":latest_ext );
-				
-				if ( !init ){
-					
-					refresh();
-				}
-			}
-		}
-	}
-	
-	protected String
-	getExtensionKey()
-	{
-		return( extension_key );
-	}
-	
-	public void 
-	log(
-		String 		s,
-		Throwable 	e )
-	{
-		AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( LOGGER_NAME );
-		
-		diag_logger.log( s );
-		diag_logger.log( e );
-		
-		if ( ConstantsVuze.DIAG_TO_STDOUT ){
-			
-			System.out.println(Thread.currentThread().getName() + "|"
-					+ System.currentTimeMillis() + "] " + s + ": " + Debug.getNestedExceptionMessage(e));
-		}	
-	}
-	
-	public void 
-	log(
-		String 	s )
-	{
-		AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( LOGGER_NAME );
-		
-		diag_logger.log( s );
-		
-		if ( ConstantsVuze.DIAG_TO_STDOUT ){
-			
-			System.out.println(Thread.currentThread().getName() + "|"
-					+ System.currentTimeMillis() + "] " + s);
-		}
-	}
-	
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		writer.println( "Metasearch: auto=" + isAutoMode());
-			
-		try{
-			writer.indent();
-
-			meta_search.generate( writer );
-			
-		}finally{
-			
-			writer.exdent();
-		}
-	}
-	
-	protected static class
-	SearchObject
-		implements Search, ResultListener
-	{
-		private SearchListener		listener;
-		
-		private Map<Long,engineInfo>	engine_map = new HashMap<Long, engineInfo>();
-		private boolean					engines_set;
-		
-		private List<SearchProviderResults>	pending_results = new ArrayList<SearchProviderResults>();
-		
-		private boolean	is_complete;
-		
-		protected
-		SearchObject(
-			SearchListener	_listener )
-		{
-			listener = _listener;
-		}
-		
-		protected void
-		setEnginesUsed(
-			Engine[]	engines )
-		{
-			boolean	report_complete;
-			
-			synchronized( engine_map ){
-				
-				for ( Engine e: engines ){
-					
-					getInfo( e );
-				}
-				
-				engines_set = true;
-				
-				report_complete = reportOverallComplete();
-			}
-			
-			if ( listener != null && report_complete ){
-					
-				listener.completed();
-			}
-		}
-		
-		private boolean
-		reportOverallComplete()
-		{
-			if ( is_complete || !engines_set ){
-				
-				return( false );
-			}
-			
-			for ( engineInfo info: engine_map.values()){
-				
-				if ( !info.isComplete()){
-					
-					return( false );
-				}
-			}
-			
-			is_complete = true;
-			
-			return( true );
-		}
-		
-		protected engineInfo
-		getInfo(
-			Engine		engine )
-		{
-			synchronized( engine_map ){
-
-				engineInfo res = engine_map.get( engine.getId());
-				
-				if ( res == null ){
-					
-					res = new engineInfo( engine );
-					
-					engine_map.put( engine.getId(), res );
-				}
-				
-				return( res );
-			}
-		}
-		
-		public void 
-		contentReceived(
-			Engine 		engine, 
-			String 		content )
-		{	
-				// boring
-		}
-		
-		public void 
-		matchFound( 
-			Engine 		engine, 
-			String[] 	fields )
-		{	
-			// boring
-		}
-		
-		public void 
-		resultsReceived(
-			Engine 			engine,
-			final Result[] 	results )
-		{
-			SearchProviderResults	result;
-
-			synchronized( engine_map ){
-				
-				final engineInfo info = getInfo( engine );
-				
-				result = 
-					new SearchProviderResults()
-					{
-						public SearchProvider
-						getProvider()
-						{
-							return( info );
-						}
-						
-						public SearchResult[]
-						getResults()
-						{
-							return( wrapResults( results ));
-						}
-						
-						public boolean
-						isComplete()
-						{
-							return( false );
-						}
-						
-						public SearchException
-						getError()
-						{
-							return( null );
-						}
-					};
-					
-				pending_results.add( result );
-			}
-			
-			if ( listener != null ){
-				
-				listener.receivedResults( new SearchProviderResults[]{ result });
-			}
-		}
-		
-		public void 
-		resultsComplete(
-			Engine 		engine )
-		{
-			boolean					report_complete;
-			SearchProviderResults	result;
-			
-			synchronized( engine_map ){
-				
-				final engineInfo info = getInfo( engine );
-				
-				info.setComplete();
-				
-				report_complete = reportOverallComplete();
-			
-				result = 
-					new SearchProviderResults()
-					{
-						public SearchProvider
-						getProvider()
-						{
-							return( info );
-						}
-						
-						public SearchResult[]
-						getResults()
-						{
-							return( new SearchResult[0] );
-						}
-						
-						public boolean
-						isComplete()
-						{
-							return( true );
-						}
-						
-						public SearchException
-						getError()
-						{
-							return( null );
-						}
-					};
-					
-				pending_results.add( result );
-			}
-			
-			if ( listener != null ){
-				
-				listener.receivedResults( new SearchProviderResults[]{ result });
-				
-				if ( report_complete ){
-					
-					listener.completed();
-				}
-			}
-		}
-		
-		protected void
-		failed(
-			Engine						engine,
-			final SearchException		error )
-		{
-			boolean					report_complete;
-			SearchProviderResults	result;
-			
-			synchronized( engine_map ){
-				
-				final engineInfo info = getInfo( engine );
-				
-				info.setComplete();
-				
-				report_complete = reportOverallComplete();
-				
-				result = 
-						new SearchProviderResults()
-						{
-							public SearchProvider
-							getProvider()
-							{
-								return( info );
-							}
-							
-							public SearchResult[]
-							getResults()
-							{
-								return( new SearchResult[0] );
-							}
-							
-							public boolean
-							isComplete()
-							{
-								return( false );
-							}
-							
-							public SearchException
-							getError()
-							{
-								return( error );
-							}
-						};
-						
-				pending_results.add( result );
-			}
-			
-			if ( listener != null ){
-				
-				listener.receivedResults( new SearchProviderResults[]{ result });
-				
-				if ( report_complete ){
-					
-					listener.completed();
-				}
-			}
-		}
-		
-		public void 
-		engineFailed(
-			Engine 		engine, 
-			Throwable 	cause )
-		{
-			failed( engine, new SearchException( "Search failed", cause ));
-		}
-		
-		public void 
-		engineRequiresLogin(
-			Engine 		engine, 
-			Throwable 	cause )
-		{
-			failed( engine, new SearchException( "Authentication required", cause ));
-		}
-		
-		protected SearchResult[]
-		wrapResults(
-			Result[]	res )
-		{
-			SearchResult[] x = new SearchResult[ res.length ];
-			
-			for ( int i=0;i<x.length;i++){
-				
-				x[i] = new resultWrapper( res[i] );
-			}
-			
-			return( x );
-		}
-		
-		public SearchProviderResults[]
-     	getResults()
-		{
-     		synchronized( engine_map ){
-
-     			SearchProviderResults[] result = pending_results.toArray( new SearchProviderResults[pending_results.size()]);
-     			
-     			pending_results.clear();
-     			
-     			return( result );
-     		}
-		}
-     	
-     	public boolean
-     	isComplete()
-     	{
-     		synchronized( engine_map ){
-     			
-     			if ( !is_complete ){
-     				
-     				return( false );
-     			}
-     			
-     			if ( pending_results.size() > 0 ){
-     				
-     				return( false );
-     			}
-     			
-     			return( true );
-     		}
-     	}
-     	
-     	protected static class
-     	resultWrapper
-     		implements SearchResult
-     	{
-     		private Result	result;
-     		
-     		protected
-     		resultWrapper(
-     			Result		_result )
-     		{
-     			result	= _result;
-     		}
-     		
-     		public Object
-     		getProperty(
-     			int		property_name )
-     		{
-     			switch( property_name ){
-	     			case PR_NAME:{
-	     			
-	     				return( result.getName());
-	     			}
-	     			case PR_PUB_DATE:{
-	     				
-	     				return( result.getPublishedDate());
-	     			}
-	     			case PR_SIZE:{
-	     				
-	     				return( result.getSize());
-	     			}
-	     			case PR_LEECHER_COUNT:{
-	     				
-	     				return( new Long( result.getNbPeers()));
-	     			}
-	     			case PR_SEED_COUNT:{
-	     				
-	     				return( new Long( result.getNbSeeds()));
-	     			}
-	     			case PR_SUPER_SEED_COUNT:{
-	     				
-	     				return( new Long( result.getNbSuperSeeds()));
-	     			}
-	     			case PR_CATEGORY:{
-	     				
-	     				return( result.getCategory());
-	     			}
-	     			case PR_COMMENTS:{
-	     				
-	     				return( new Long( result.getComments()));
-	     			}
-	     			case PR_VOTES:{
-	     				
-	     				return( new Long( result.getVotes()));
-	     			}
-	     			case PR_CONTENT_TYPE:{
-	     				
-	     				return( result.getContentType());
-	     			}
-	     			case PR_DETAILS_LINK:{
-	     				
-	     				return( result.getCDPLink());
-	     			}
-	     			case PR_DOWNLOAD_LINK:{
-	     				
-	     				return( result.getDownloadLink());
-	     			}
-	     			case PR_PLAY_LINK:{
-	     				
-	     				return( result.getPlayLink());
-	     			}
-	     			case PR_PRIVATE:{
-	     				
-	     				return( result.isPrivate());
-	     			}
-	     			case PR_DRM_KEY:{
-	     				
-	     				return( result.getDRMKey());
-	     			}
-	     			case PR_DOWNLOAD_BUTTON_LINK:{
-	     				
-	     				return( result.getDownloadButtonLink());
-	     			}
-	     			case PR_RANK:{
-	     			
-	     				float rank = result.getRank();
-	     				
-	     				return( new Long(rank==-1?-1:(long)( rank * 100 )));
-	     			}
-	     			case PR_ACCURACY:{
-	     			
-	     				float accuracy = result.getAccuracy();
-	     				
-	     				return( new Long(accuracy==-1?-1:(long)( accuracy * 100 )));
-	     			}
-	     			case PR_VOTES_DOWN:{
-	     				
-	     				return( new Long( result.getVotesDown()));
-	     			}
-	     			case PR_UID:{
-	     			
-	     				return( result.getUID());
-	     			}
-	     			case PR_HASH:{
-	     				
-	     				String base32_hash = result.getHash();
-	     				
-	     				if ( base32_hash != null ){
-	     					
-	     					return( Base32.decode( base32_hash ));
-	     				}
-	     				
-	     				return( null );
-	     			}
-	     			default:{
-	     				
-	     				Debug.out( "Unknown property type " + property_name );
-	     			}
-     			}
-     			
-     			return( null );
-     		}
-     	}
-	}
-	
-    protected static class
-    engineInfo
-    	implements SearchProvider
-    {
-    	private Engine		engine;
-     		
-    	private boolean		complete;
-    	
-    	protected
-    	engineInfo(
-    		Engine		_engine )
-    	{
-    		engine	= _engine;
-    	}
-    
-    	protected void
-    	setComplete()
-    	{
-    		complete	= true;
-    	}
-    	
-    	protected boolean
-    	isComplete()
-    	{
-    		return( complete );
-    	}
-    	
-		public SearchInstance
-		search(
-			Map<String,Object>	search_parameters,
-			SearchObserver		observer )
-		
-			throws SearchException
-		{
-			throw( new SearchException( "Not supported" ));
-		}
-		
-		public Object
-		getProperty(
-			int			property )
-		{
-			if ( property == PR_ID ){
-				
-				return( engine.getId());
-				
-			}else if ( property == PR_NAME ){
-				
-				return( engine.getName());
-				
-			}else{
-				
-				return( null );
-			}
-		}
-		
-		public void
-		setProperty(
-			int			property,
-			Object		value )
-		{
-			Debug.out( "Not supported" );
-		}
-	}
-    
-    public static void
-    main(
-    	String[]	args )
-    {
-    	try{
-			VuzeFile	vf = VuzeFileHandler.getSingleton().create();
-			
-			Map contents = new HashMap();
-			
-			contents.put( "type", new Long( 1 ));
-			contents.put( "term", "donkey" );
-			
-			vf.addComponent(
-				VuzeFileComponent.COMP_TYPE_METASEARCH_OPERATION,
-				contents);
-			
-			vf.write( new File( "C:\\temp\\search.vuze" ));
-			
-    	}catch( Throwable e ){
-    		
-    		e.printStackTrace();
-    	}
-    }
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.core3.xml.util.XUXmlWriter;
+
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.PluginListener;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.UIManagerEvent;
+import org.gudy.azureus2.plugins.utils.FeatureManager;
+import org.gudy.azureus2.plugins.utils.StaticUtilities;
+import org.gudy.azureus2.plugins.utils.FeatureManager.FeatureDetails;
+import org.gudy.azureus2.plugins.utils.FeatureManager.Licence;
+import org.gudy.azureus2.plugins.utils.search.Search;
+import org.gudy.azureus2.plugins.utils.search.SearchException;
+import org.gudy.azureus2.plugins.utils.search.SearchInitiator;
+import org.gudy.azureus2.plugins.utils.search.SearchInstance;
+import org.gudy.azureus2.plugins.utils.search.SearchListener;
+import org.gudy.azureus2.plugins.utils.search.SearchObserver;
+import org.gudy.azureus2.plugins.utils.search.SearchProvider;
+import org.gudy.azureus2.plugins.utils.search.SearchProviderResults;
+import org.gudy.azureus2.plugins.utils.search.SearchResult;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
+
+import com.aelitis.azureus.core.custom.Customization;
+import com.aelitis.azureus.core.custom.CustomizationManager;
+import com.aelitis.azureus.core.custom.CustomizationManagerFactory;
+import com.aelitis.azureus.core.messenger.config.PlatformMetaSearchMessenger;
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.MetaSearch;
+import com.aelitis.azureus.core.metasearch.MetaSearchException;
+import com.aelitis.azureus.core.metasearch.MetaSearchManager;
+import com.aelitis.azureus.core.metasearch.MetaSearchManagerListener;
+import com.aelitis.azureus.core.metasearch.Result;
+import com.aelitis.azureus.core.metasearch.ResultListener;
+import com.aelitis.azureus.core.metasearch.SearchParameter;
+import com.aelitis.azureus.core.metasearch.impl.plugin.PluginEngine;
+import com.aelitis.azureus.core.subs.Subscription;
+import com.aelitis.azureus.core.subs.SubscriptionManager;
+import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
+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.util.ConstantsVuze;
+import com.aelitis.azureus.util.ImportExportUtils;
+
+public class 
+MetaSearchManagerImpl
+	implements MetaSearchManager, UtilitiesImpl.searchManager, AEDiagnosticsEvidenceGenerator
+{
+	private static final boolean AUTO_MODE_DEFAULT		= true;
+	
+	
+	private static final String	LOGGER_NAME = "MetaSearch";
+	
+	private static final int REFRESH_MILLIS = 23*60*60*1000;
+	
+	private static MetaSearchManagerImpl singleton;	
+	
+	public static void
+	preInitialise()
+	{
+		VuzeFileHandler.getSingleton().addProcessor(
+			new VuzeFileProcessor()
+			{
+				public void
+				process(
+					VuzeFile[]		files,
+					int				expected_types )
+				{
+					for (int i=0;i<files.length;i++){
+						
+						VuzeFile	vf = files[i];
+						
+						VuzeFileComponent[] comps = vf.getComponents();
+						
+						for (int j=0;j<comps.length;j++){
+							
+							VuzeFileComponent comp = comps[j];
+							
+							int	comp_type = comp.getType();
+							
+							if ( comp_type == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
+								
+								try{
+									Engine e = 
+										getSingleton().importEngine(
+											comp.getContent(), 
+											(expected_types & VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE) == 0 );
+									
+									comp.setProcessed();
+									
+									if ( e != null ){
+										
+										comp.setData( Engine.VUZE_FILE_COMPONENT_ENGINE_KEY, e );
+									}
+								}catch( Throwable e ){
+									
+									Debug.printStackTrace(e);
+								}
+							}else if ( comp_type == VuzeFileComponent.COMP_TYPE_METASEARCH_OPERATION ){
+								
+								getSingleton().addOperation( comp.getContent());
+								
+								comp.setProcessed();
+							}
+						}
+					}
+				}
+			});	
+		
+		TorrentUtils.addTorrentAttributeListener(
+				new TorrentUtils.torrentAttributeListener()
+				{
+					public void 
+					attributeSet(
+						TOTorrent 	torrent,
+						String 		attribute, 
+						Object 		value )
+					{
+						if ( 	attribute == TorrentUtils.TORRENT_AZ_PROP_OBTAINED_FROM && 
+								!TorrentUtils.isReallyPrivate( torrent )){
+							
+							try{
+								getSingleton().checkPotentialAssociations( torrent.getHash(), (String)value );
+								
+							}catch( Throwable e ){
+								
+								Debug.printStackTrace(e);
+							}
+						}
+					}
+				});
+	}
+	
+	public static synchronized MetaSearchManagerImpl
+	getSingleton()
+	{
+		if ( singleton == null ){
+			
+			singleton = new MetaSearchManagerImpl();
+		}
+		return( singleton );
+	}
+	
+	private MetaSearchImpl	meta_search;
+	private AsyncDispatcher	dispatcher = new AsyncDispatcher( 10000 );
+	
+	private AESemaphore	initial_refresh_sem = new AESemaphore( "MetaSearch:initrefresh" );
+	
+	private AESemaphore	refresh_sem = new AESemaphore( "MetaSearch:refresh", 1 );
+	
+	private boolean	checked_customization;
+	
+	private AsyncDispatcher					op_dispatcher 	= new AsyncDispatcher(5*1000);
+	private List<MetaSearchManagerListener>	listeners 		= new ArrayList<MetaSearchManagerListener>();
+	private List<Map>						operations		= new ArrayList<Map>();
+	
+	private String		extension_key;
+	
+	private Map<String,EngineImpl>	potential_associations = 
+		new LinkedHashMap<String,EngineImpl>(32,0.75f,true)
+		{
+			protected boolean 
+			removeEldestEntry(
+		   		Map.Entry<String,EngineImpl> eldest) 
+			{
+				return size() > 32;
+			}
+		};
+	protected
+	MetaSearchManagerImpl()
+	{
+		meta_search = new MetaSearchImpl( this );
+		
+		AEDiagnostics.addEvidenceGenerator( this );
+		
+		extension_key = COConfigurationManager.getStringParameter( "metasearch.extkey.latest", "" );
+
+		if ( extension_key.length() == 0 ){
+			
+			extension_key = null;
+		}
+		
+		setupExtensions();
+		
+		SimpleTimer.addPeriodicEvent(
+			"MetaSearchRefresh",
+			REFRESH_MILLIS,
+			new TimerEventPerformer()
+			{
+				public void 
+				perform(
+					TimerEvent 	event ) 
+				{
+					refresh();
+				}
+			});
+		
+		refresh();
+		
+		UtilitiesImpl.addSearchManager( this );
+	}
+	
+	public void 
+	addProvider(
+		PluginInterface		pi,
+		SearchProvider 		provider ) 
+	{
+		String	id = pi.getPluginID() + "." + provider.getProperty( SearchProvider.PR_NAME );
+		
+		try{
+			meta_search.importFromPlugin( id, provider );
+			
+		}catch( Throwable e ){
+			
+			Debug.out( "Failed to add search provider '" + id + "' (" + provider + ")", e );
+		}
+	}
+	
+	public void 
+	removeProvider(
+		PluginInterface		pi,
+		SearchProvider 		provider ) 
+	{
+		String	id = pi.getPluginID() + "." + provider.getProperty( SearchProvider.PR_NAME );
+		
+		try{
+			Engine[] engines = meta_search.getEngines( false, false );
+			
+			for ( Engine engine: engines ){
+				
+				if ( engine instanceof PluginEngine ){
+					
+					PluginEngine pe = (PluginEngine)engine;
+					
+					if ( pe.getProvider() == provider ){
+						
+						engine.delete();
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			Debug.out( "Failed to remove search provider '" + id + "' (" + provider + ")", e );
+		}
+	}
+	
+	public SearchProvider[]
+  	getProviders()
+	{
+		Engine[] engines = meta_search.getEngines( true, false );
+		
+		SearchProvider[] result = new SearchProvider[engines.length];
+		
+		for (int i=0;i<engines.length;i++){
+				
+			result[i] = new engineInfo( engines[i] );
+		}
+		
+		return( result );
+	}
+	
+	public Search 
+	createSearch(
+		String 		provider_ids,
+		String 		properties_str )
+	
+		throws SearchException 
+	{
+		String[]	bits = XUXmlWriter.splitWithEscape( provider_ids, ',' );
+		
+		long[]	pids = new long[ bits.length ];
+		
+		for ( int i=0; i<bits.length; i++ ){
+			
+			pids[i] = Long.parseLong( bits[i] );
+		}
+
+		Map<String,String>	properties = new HashMap<String, String>();
+		
+		bits = XUXmlWriter.splitWithEscape( properties_str, ',' );
+
+		for ( int i=0; i<bits.length; i++ ){
+
+			String[] x = XUXmlWriter.splitWithEscape( bits[i], '=' );
+			
+			properties.put( x[0].trim(), x[1].trim());
+		}
+		
+		return( createSearch( pids, properties, null ));
+	}
+	
+  	public Search
+  	createSearch(
+  		SearchProvider[]	providers,
+  		Map<String,String>	properties,
+  		SearchListener		listener )
+  	
+  		throws SearchException
+  	{
+  		long[]	pids;
+  		
+  		if ( providers == null ){
+  			
+  			pids = new long[0];
+  			
+  		}else{
+  			
+  			pids = new long[providers.length];
+  			
+  			for (int i=0;i<pids.length;i++){
+			
+  				Long	id = (Long)providers[i].getProperty( SearchProvider.PR_ID );
+			
+  				if ( id == null ){
+				
+  					throw( new SearchException( "Unknown provider - no id available" ));
+  				}
+  				
+  				pids[i] = id;
+			}
+  		}
+  		
+  		return( createSearch( pids, properties, listener ));
+  	}
+  	
+  	protected Search
+  	createSearch(
+  		long[]				provider_ids,
+  		Map<String,String>	properties,
+  		SearchListener		listener )
+  	
+  		throws SearchException
+  	{
+		List<SearchParameter>	sps = new ArrayList<SearchParameter>();
+
+ 		String	search_term = properties.get( SearchInitiator.PR_SEARCH_TERM );
+ 		
+ 		if ( search_term == null ){
+ 			
+ 			throw( new SearchException( "Search term is mandatory" ));
+ 		}
+ 		
+		sps.add( new SearchParameter( "s", search_term ));
+
+ 		String	mature 		= properties.get( SearchInitiator.PR_MATURE );
+  		
+		if ( mature != null ){
+			
+			sps.add( new SearchParameter( "m", mature.toString()));
+		}
+	
+		SearchParameter[] parameters = (SearchParameter[])sps.toArray(new SearchParameter[ sps.size()] );
+
+		Map<String,String>	context = new HashMap<String, String>();
+		
+		context.put( Engine.SC_FORCE_FULL, "true" );
+
+		String	headers 		= null;
+		int		max_per_engine	= 256;
+		
+		SearchObject search = new SearchObject( listener );
+		
+		Engine[]	used_engines;
+		
+		if ( provider_ids.length == 0 ){
+			
+			used_engines = getMetaSearch().search( search, parameters, headers, context, max_per_engine );
+
+		}else{
+			
+			List<Engine>	selected_engines = new ArrayList<Engine>();
+			
+			for ( long id: provider_ids ){
+				
+				Engine engine = meta_search.getEngine( id );
+				
+				if ( engine == null ){
+					
+					throw( new SearchException( "Unknown engine id - " + id ));
+					
+				}else{
+					
+					selected_engines.add( engine );
+				}
+			}
+			
+			Engine[] engines = selected_engines.toArray( new Engine[ selected_engines.size()] );
+	
+			used_engines = getMetaSearch().search( engines, search, parameters, headers, context, max_per_engine );
+		}
+		
+		search.setEnginesUsed( used_engines );
+		
+		return( search );
+  	}
+	
+	protected void
+	refresh()
+	{
+		dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void 
+				runSupport() 
+				{
+					if ( dispatcher.getQueueSize() == 0 ){
+						
+						try{
+							syncRefresh();
+														
+						}catch( Throwable e ){
+							
+						}
+					}
+				}
+			});
+	}
+	
+	protected void
+	ensureEnginesUpToDate()
+	{
+		long timeout = meta_search.getEngineCount() == 0?(30*1000):(10*1000);
+		
+		if ( !initial_refresh_sem.reserve( timeout )){
+			
+			log( "Timeout waiting for initial refresh to complete, continuing" );
+		}
+	}
+	
+	protected void
+	syncRefresh()
+	
+		throws MetaSearchException
+	{
+		boolean refresh_completed 	= false;
+		boolean	first_run			= false;
+		
+		try{
+			refresh_sem.reserve();
+			
+			first_run = COConfigurationManager.getBooleanParameter( "metasearch.refresh.first_run", true );
+			
+			if ( !checked_customization ){
+				
+				checked_customization = true;
+				
+				CustomizationManager cust_man = CustomizationManagerFactory.getSingleton();
+				
+				Customization cust = cust_man.getActiveCustomization();
+				
+				if ( cust != null ){
+					
+					String cust_name 	= COConfigurationManager.getStringParameter( "metasearch.custom.name", "" );
+					String cust_version = COConfigurationManager.getStringParameter( "metasearch.custom.version", "0" );
+					
+					boolean	new_name 	= !cust_name.equals( cust.getName());
+					boolean	new_version = org.gudy.azureus2.core3.util.Constants.compareVersions( cust_version, cust.getVersion() ) < 0;
+					
+					if ( new_name || new_version ){
+
+						log( "Customization: checking templates for " + cust.getName() + "/" + cust.getVersion());
+						
+						try{
+							InputStream[] streams = cust.getResources( Customization.RT_META_SEARCH_TEMPLATES );
+							
+							if ( streams.length > 0 && new_name ){
+								
+									// reset engines
+								
+								log( "    setting auto-mode to false" );
+								
+								setAutoMode( false );
+								
+								/*
+								Engine[]	engines = meta_search.getEngines( false, false );
+
+								for (int i=0;i<engines.length;i++){
+									
+									Engine engine = engines[i];
+									
+									if ( engine.getSelectionState()) == Engine.SEL_STATE_MANUAL_SELECTED ){
+										
+									}
+								}
+								*/
+							}
+							for (int i=0;i<streams.length;i++){
+								
+								InputStream is = streams[i];
+								
+								try{
+									VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile(is);
+									
+									if ( vf != null ){
+										
+										VuzeFileComponent[] comps = vf.getComponents();
+										
+										for (int j=0;j<comps.length;j++){
+											
+											VuzeFileComponent comp = comps[j];
+											
+											if ( comp.getType() == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
+												
+												try{
+													Engine e = 
+														getSingleton().importEngine( comp.getContent(), false ); 
+													
+													log( "    updated " + e.getName());
+													
+													e.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
+													
+												}catch( Throwable e ){
+													
+													Debug.printStackTrace(e);
+												}
+											}
+										}
+									}
+								}finally{
+									
+									try{
+										is.close();
+										
+									}catch( Throwable e ){
+									}
+								}
+							}
+						}finally{
+							
+							COConfigurationManager.setParameter( "metasearch.custom.name", cust.getName());
+							COConfigurationManager.setParameter( "metasearch.custom.version", cust.getVersion());
+						}
+					}
+				}
+			}
+			
+			log( "Refreshing engines" );
+					
+				// featured templates are always shown - can't be deselected
+				// popular ones are selected if in 'auto' mode
+				// manually selected ones are, well, manually selected
+			
+			Map<Long,PlatformMetaSearchMessenger.templateInfo>		vuze_selected_ids 		= new HashMap<Long, PlatformMetaSearchMessenger.templateInfo>();
+			Map<Long,PlatformMetaSearchMessenger.templateInfo>		vuze_preload_ids 		= new HashMap<Long,PlatformMetaSearchMessenger.templateInfo>();
+			
+			Set<Long>		featured_ids 			= new HashSet<Long>();
+			Set<Long>		popular_ids 			= new HashSet<Long>();
+			Set<Long>		manual_vuze_ids 		= new HashSet<Long>();
+			
+			boolean		auto_mode = isAutoMode();
+					
+			Engine[]	engines = meta_search.getEngines( false, false );
+	
+			String	fud = meta_search.getFUD();
+			
+			try{
+				PlatformMetaSearchMessenger.templateInfo[] featured = PlatformMetaSearchMessenger.listFeaturedTemplates( extension_key, fud );
+				
+				String featured_str = "";
+				
+				for (int i=0;i<featured.length;i++){
+					
+					PlatformMetaSearchMessenger.templateInfo template = featured[i];
+					
+					if ( !template.isVisible()){
+						
+						continue;
+					}
+					
+					Long key = new Long( template.getId());
+					
+					vuze_selected_ids.put( key,	template );
+					
+					featured_ids.add( key );
+					
+					featured_str += (featured_str.length()==0?"":",") + key;
+				}
+					
+				log( "Featured templates: " + featured_str );
+				
+				if ( auto_mode || first_run ){
+					
+					PlatformMetaSearchMessenger.templateInfo[] popular = PlatformMetaSearchMessenger.listTopPopularTemplates( extension_key, fud );
+					
+					String popular_str = "";
+					String preload_str = "";
+					
+					for (int i=0;i<popular.length;i++){
+						
+						PlatformMetaSearchMessenger.templateInfo template = popular[i];
+						
+						if ( !template.isVisible()){
+							
+							continue;
+						}
+						
+						Long	key = new Long( template.getId());
+						
+						if ( auto_mode ){
+							
+							if ( !vuze_selected_ids.containsKey( key )){
+								
+								vuze_selected_ids.put( key,	template );
+								
+								popular_ids.add( key );
+								
+								popular_str += (popular_str.length()==0?"":",") + key;
+							}
+						}else{
+							
+							if ( !vuze_preload_ids.containsKey( key )){
+								
+								vuze_preload_ids.put( key, template );
+																
+								preload_str += (preload_str.length()==0?"":",") + key;
+							}
+						}
+					}
+					
+					log( "Popular templates: " + popular_str );
+					
+					if ( preload_str.length() > 0 ){
+						
+						log( "Pre-load templates: " + popular_str );
+					}
+				}
+						
+					// pick up explicitly selected vuze ones
+				
+				String manual_str = "";
+				
+				for (int i=0;i<engines.length;i++){
+					
+					Engine	engine = engines[i];
+					
+					Long key = new Long( engine.getId());
+					
+					if ( 	engine.getSource() == Engine.ENGINE_SOURCE_VUZE &&
+							engine.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED &&
+							!vuze_selected_ids.containsKey( key )){
+						
+						manual_vuze_ids.add( key );
+					}
+				}
+				
+				if ( manual_vuze_ids.size() > 0 ){
+					
+					long[]	manual_ids = new long[manual_vuze_ids.size()];
+					
+					Iterator<Long> it = manual_vuze_ids.iterator();
+					
+					int	pos = 0;
+					
+					while( it.hasNext()){
+						
+						manual_ids[pos++] = it.next().longValue();
+					}
+					
+					PlatformMetaSearchMessenger.templateInfo[] manual = PlatformMetaSearchMessenger.getTemplateDetails( extension_key, manual_ids );
+										
+					for (int i=0;i<manual.length;i++){
+						
+						PlatformMetaSearchMessenger.templateInfo template = manual[i];
+						
+						if ( !template.isVisible()){
+							
+							continue;
+						}
+						
+						Long	key = new Long( template.getId());
+													
+						vuze_selected_ids.put( key, template );
+														
+						manual_str += (manual_str.length()==0?"":",") + key;
+					}
+				}
+				
+				log( "Manual templates: " + manual_str );
+				
+				Map<Long,Engine> existing_engine_map = new HashMap<Long,Engine>();
+				
+				String existing_str = "";
+				
+				for (int i=0;i<engines.length;i++){
+					
+					Engine	engine = engines[i];
+					
+					Long key = new Long( engine.getId());
+	
+					existing_engine_map.put( key, engine );
+					
+					existing_str += (existing_str.length()==0?"":",") + key + 
+										"[source=" + Engine.ENGINE_SOURCE_STRS[engine.getSource()] +
+										",type=" + engine.getType() + 
+										",selected=" + Engine.SEL_STATE_STRINGS[engine.getSelectionState()] + "]";
+				}
+				
+				log( "Existing templates: " + existing_str );
+				
+					// we've compiled a list of the engines we should have and their latest dates
+				
+					// update any that are out of date
+				
+				Iterator<Map.Entry<Long,PlatformMetaSearchMessenger.templateInfo>> it = vuze_selected_ids.entrySet().iterator();
+				
+				while( it.hasNext()){
+					
+					Map.Entry<Long,PlatformMetaSearchMessenger.templateInfo> entry = it.next();
+					
+					vuze_preload_ids.remove( entry.getKey());
+					
+					long	id 			= entry.getKey().longValue();
+					
+					PlatformMetaSearchMessenger.templateInfo template = entry.getValue();
+					
+					long	modified 	= template.getModifiedDate();
+									
+					Engine this_engine = (Engine)existing_engine_map.get( new Long(id));
+					
+					boolean	update = this_engine == null || this_engine.getLastUpdated() < modified;
+	
+					if ( update ){
+						
+						PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( extension_key, id );
+	
+						log( "Downloading definition of template " + id );
+						log( details.getValue());
+						
+						if ( details.isVisible()){
+							
+							try{
+								this_engine = 
+									meta_search.importFromJSONString( 
+										details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
+										details.getId(),
+										details.getModifiedDate(),
+										details.getRankBias(),
+										details.getName(),
+										details.getValue());
+								
+								this_engine.setSource( Engine.ENGINE_SOURCE_VUZE );
+																
+								meta_search.addEngine( this_engine );
+								
+							}catch( Throwable e ){
+								
+								log( "Failed to import engine '" + details.getValue() + "'", e );
+							}
+						}	
+					}else if ( this_engine.getRankBias() != template.getRankBias()){
+						
+						this_engine.setRankBias( template.getRankBias());
+						
+						log( "Updating rank bias for " + this_engine.getString() + " to " + template.getRankBias());
+
+					}else{
+						
+						log( "Not updating " + this_engine.getString() + " as unchanged" );
+					}
+					
+					if ( this_engine != null ){
+							
+						int sel_state = this_engine.getSelectionState();
+						
+						if ( sel_state == Engine.SEL_STATE_DESELECTED ){
+						
+							log( "Auto-selecting " + this_engine.getString());
+							
+							this_engine.setSelectionState( Engine.SEL_STATE_AUTO_SELECTED );
+							
+						}else if ( auto_mode && sel_state == Engine.SEL_STATE_MANUAL_SELECTED ){
+							
+							log( "Switching Manual to Auto select for " + this_engine.getString());
+							
+							this_engine.setSelectionState( Engine.SEL_STATE_AUTO_SELECTED );
+						}
+					}
+				}
+				
+					// do any pre-loads
+				
+				it = vuze_preload_ids.entrySet().iterator();
+				
+				while( it.hasNext()){
+					
+					Map.Entry<Long,PlatformMetaSearchMessenger.templateInfo> entry = it.next();
+					
+					long	id 			= ((Long)entry.getKey()).longValue();
+									
+					Engine this_engine = (Engine)existing_engine_map.get( new Long(id));
+						
+					if ( this_engine == null ){
+						
+						PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( extension_key, id );
+	
+						log( "Downloading pre-load definition of template " + id );
+						log( details.getValue());
+						
+						if ( details.isVisible()){
+							
+							try{
+								this_engine = 
+									meta_search.importFromJSONString( 
+										details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
+										details.getId(),
+										details.getModifiedDate(),
+										details.getRankBias(),
+										details.getName(),
+										details.getValue());
+								
+								this_engine.setSource( Engine.ENGINE_SOURCE_VUZE );
+								
+								this_engine.setSelectionState( Engine.SEL_STATE_DESELECTED );
+																
+								meta_search.addEngine( this_engine );
+								
+							}catch( Throwable e ){
+								
+								log( "Failed to import engine '" + details.getValue() + "'", e );
+							}
+						}			
+					}
+				}
+				
+					// deselect any not in use
+				
+				for (int i=0;i<engines.length;i++){
+					
+					Engine	engine = engines[i];
+					
+					if ( 	engine.getSource() == Engine.ENGINE_SOURCE_VUZE &&
+							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");
+						
+						engine.setSelectionState( Engine.SEL_STATE_DESELECTED );
+					}
+				}
+				
+					// finally pick up any unreported selection changes and re-affirm positive selections
+				
+				for (int i=0;i<engines.length;i++){
+					
+					Engine	engine = engines[i];
+					
+					if ( 	engine.getSource() == Engine.ENGINE_SOURCE_VUZE &&
+							engine.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED ){
+						
+						engine.recordSelectionState();
+						
+					}else{
+						
+						engine.checkSelectionStateRecorded();
+					}
+				}
+				
+				refresh_completed = true;
+				
+			}catch( Throwable e ){
+				
+				log( "Refresh failed", e );
+				
+				throw( new MetaSearchException( "Refresh failed", e ));
+			}
+		}finally{
+			
+			if ( first_run && refresh_completed ){
+				
+				COConfigurationManager.setParameter( "metasearch.refresh.first_run", false );
+			}
+			
+			refresh_sem.release();
+			
+			initial_refresh_sem.releaseForever();
+		}
+	}
+	
+	public MetaSearch 
+	getMetaSearch() 
+	{
+		return( meta_search );
+	}
+	
+	public boolean
+	isAutoMode()
+	{
+		return( COConfigurationManager.getBooleanParameter( "metasearch.auto.mode", AUTO_MODE_DEFAULT ));
+	}
+	
+	protected void
+	setAutoMode(
+		boolean	auto )
+	{
+		COConfigurationManager.setParameter( "metasearch.auto.mode", auto );
+	}
+	
+	public void
+	setSelectedEngines(
+		long[]		ids,
+		boolean		auto )
+	
+		throws MetaSearchException
+	{
+		try{
+			String	s = "";
+			
+			for (int i=0;i<ids.length;i++){
+				
+				s += (i==0?"":",") + ids[i];
+			}
+			
+			log( "setSelectedIds: " + s + ", auto=" + auto );
+			
+				// first update state of auto and existing engines 
+			
+			COConfigurationManager.setParameter( "metasearch.auto.mode", auto );
+
+			Engine[]	engines = meta_search.getEngines( false, false );
+			
+			Map<Long,Engine>	engine_map = new HashMap<Long,Engine>();
+			
+			for( int i=0;i<engines.length;i++){
+				
+				engine_map.put( new Long( engines[i].getId()), engines[i] );
+			}
+				
+			Set<Engine> selected_engine_set = new HashSet<Engine>();
+			
+			for (int i=0;i<ids.length;i++){
+				
+				long	 id = ids[i];
+				
+				Engine existing = (Engine)engine_map.get(new Long(id));
+				
+				if ( existing != null ){
+					
+					existing.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
+					
+					selected_engine_set.add( existing );
+				}
+			}
+		
+				// now refresh - this will pick up latest state of things
+			
+			syncRefresh();
+			
+			engines = meta_search.getEngines( false, false );
+
+				// next add in any missing engines
+			
+			for (int i=0;i<ids.length;i++){
+				
+				long	 id = ids[i];
+				
+				Engine existing = (Engine)engine_map.get(new Long(id));
+				
+				if ( existing == null ){
+														
+					PlatformMetaSearchMessenger.templateDetails details = PlatformMetaSearchMessenger.getTemplate( extension_key, id );
+	
+					log( "Downloading definition of template " + id );
+					log( details.getValue());
+					
+					Engine new_engine = 
+						meta_search.importFromJSONString( 
+							details.getType()==PlatformMetaSearchMessenger.templateDetails.ENGINE_TYPE_JSON?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX,
+							details.getId(),
+							details.getModifiedDate(),
+							details.getRankBias(),
+							details.getName(),
+							details.getValue());
+							
+					new_engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
+										
+					new_engine.setSource( Engine.ENGINE_SOURCE_VUZE );
+						
+					meta_search.addEngine( new_engine );
+					
+					selected_engine_set.add( new_engine );
+				}
+			}
+			
+				// deselect any existing manually selected ones that are no longer selected
+			
+			for( int i=0;i<engines.length;i++){
+
+				Engine e = engines[i];
+				
+				if ( e.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED ){
+					
+					if ( !selected_engine_set.contains( e )){
+				
+						e.setSelectionState( Engine.SEL_STATE_DESELECTED  );
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+			
+			if ( e instanceof MetaSearchException ){
+				
+				throw((MetaSearchException)e);
+			}
+			
+			throw( new MetaSearchException( "Failed to set selected engines", e ));
+		}
+	}
+	
+	public Engine
+	addEngine(
+		long		id,
+		int			type,
+		String		name,
+		String		json_value )
+	
+		throws MetaSearchException
+	{
+		if ( id == -1 ){
+			
+			id = getLocalTemplateID();
+		}
+		
+		try{
+			Engine engine = 
+				meta_search.importFromJSONString( 
+					type, id, SystemTime.getCurrentTime(), 1, name, json_value );
+			
+			engine.setSource( Engine.ENGINE_SOURCE_LOCAL );
+			
+			engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
+			
+			meta_search.addEngine( engine );
+			
+			return( engine );
+			
+		}catch( Throwable e ){
+			
+			throw( new MetaSearchException( "Failed to add engine", e ));
+		}
+	}
+	
+	public boolean
+	isImportable(
+		VuzeFile		vf )
+	{
+		VuzeFileComponent[] comps = vf.getComponents();
+		
+		for (int j=0;j<comps.length;j++){
+			
+			VuzeFileComponent comp = comps[j];
+			
+			int	comp_type = comp.getType();
+			
+			if ( comp_type == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
+				
+				try{
+					EngineImpl engine = (EngineImpl)meta_search.importFromBEncodedMap( comp.getContent());
+					
+					long	id = engine.getId();
+					
+					Engine existing = meta_search.getEngine( id );
+					
+					if ( existing != null ){
+						
+						if ( existing.getSelectionState() == Engine.SEL_STATE_DESELECTED || !existing.sameLogicAs( engine )){
+							
+							return( true );
+						}
+					}else{
+						try{						
+							Engine[] engines = meta_search.getEngines( false, false );
+								
+							boolean is_new = true;
+							
+							for ( Engine e: engines ){
+									
+								if ( e.getSelectionState() != Engine.SEL_STATE_DESELECTED && e.sameLogicAs( engine )){
+										
+									is_new = false;
+									
+									break;
+								}
+							}
+							
+							if ( is_new ){
+								
+								return( true );
+							}
+						}catch( Throwable e ){	
+						}	
+					}
+				}catch( Throwable e ){				
+				}
+			}
+		}
+		
+		return( false );
+	}
+	
+	public Engine
+	importEngine(
+		Map			map,
+		boolean		warn_user )
+	
+		throws MetaSearchException
+	{
+		try{
+			EngineImpl engine = (EngineImpl)meta_search.importFromBEncodedMap(map);
+			
+			long	id = engine.getId();
+			
+			Engine existing = meta_search.getEngine( id );
+			
+			if ( existing != null ){
+				
+				if ( existing.sameLogicAs( engine )){
+					
+					if ( warn_user ){
+						
+						UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+						
+						String details = MessageText.getString(
+								"metasearch.addtemplate.dup.desc",
+								new String[]{ engine.getName() });
+						
+						ui_manager.showMessageBox(
+								"metasearch.addtemplate.dup.title",
+								"!" + details + "!",
+								UIManagerEvent.MT_OK );
+					}
+					
+					return( existing );
+				}
+			}else{
+									
+				try{						
+					Engine[] engines = meta_search.getEngines( false, false );
+						
+					for ( Engine e: engines ){
+							
+						if ( e.sameLogicAs( engine )){
+								
+							return( e );
+						}
+					}
+				}catch( Throwable e ){
+					
+				}
+			}
+			
+			if ( warn_user ){
+				
+				UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+				
+				String details = MessageText.getString(
+						"metasearch.addtemplate.desc",
+						new String[]{ engine.getName() });
+				
+				long res = ui_manager.showMessageBox(
+						"metasearch.addtemplate.title",
+						"!" + details + "!",
+						UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+				
+				if ( res != UIManagerEvent.MT_YES ){
+					
+					throw( new MetaSearchException( "User declined the template" ));
+				}
+			}
+				// if local template then we try to use the id as is otherwise we emsure that
+				// it is a local one
+			
+			if ( id >= 0 && id < Integer.MAX_VALUE ){
+				
+				id = getLocalTemplateID();
+				
+				engine.setId( id );
+			}
+			
+			engine.setSource( Engine.ENGINE_SOURCE_LOCAL );
+			
+			engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
+			
+			meta_search.addEngine( engine );
+			
+			if ( warn_user ){
+				
+				UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+				
+				String details = MessageText.getString(
+						"metasearch.addtemplate.done.desc",
+						new String[]{ engine.getName() });
+				
+				ui_manager.showMessageBox(
+						"metasearch.addtemplate.done.title",
+						"!" + details + "!",
+						UIManagerEvent.MT_OK );
+			}
+			
+			return( engine );
+			
+		}catch( Throwable e ){
+			
+			if ( warn_user ){
+				
+				UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+				
+				String details = MessageText.getString(
+						"metasearch.addtemplate.failed.desc",
+						new String[]{ Debug.getNestedExceptionMessage(e) });
+				
+				ui_manager.showMessageBox(
+						"metasearch.addtemplate.failed.title",
+						"!" + details + "!",
+						UIManagerEvent.MT_OK );
+			}
+			
+			throw( new MetaSearchException( "Failed to add engine", e ));
+		}
+	}
+	
+	protected void
+	addPotentialAssociation(
+		EngineImpl		engine,
+		String			key )
+	{		
+		if ( engine.isShareable() && !engine.isAuthenticated()){
+			
+			synchronized( potential_associations ){
+				
+				potential_associations.put( key, engine );
+			}
+		}
+	}
+	
+	private void
+	checkPotentialAssociations(
+		byte[]		hash,
+		String		key )
+	{
+		EngineImpl	engine;
+		
+		synchronized( potential_associations ){
+			
+			engine = potential_associations.remove( key );
+		}
+	
+		if ( engine != null ){
+	
+			try{
+				VuzeFile vf = engine.exportToVuzeFile( true );
+				
+				byte[] bytes = vf.exportToBytes();
+												
+				String url_str = "vuze://?body=" + new String( bytes, Constants.BYTE_ENCODING );
+								
+				SubscriptionManager sub_man = SubscriptionManagerFactory.getSingleton();
+		
+				Subscription subs =
+					sub_man.createSingletonRSS(
+						vf.getName() + ": " + engine.getName() + " (v" + engine.getVersion() + ")",
+						new URL( url_str ),
+						Integer.MAX_VALUE );
+			
+				subs.setSubscribed( true );
+			
+				subs.addAssociation( hash );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+	}
+	
+	public Engine[]
+	loadFromVuzeFile(
+		File		file )
+	{
+		VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( file.getAbsolutePath());
+		
+		if ( vf != null ){
+			
+			return( loadFromVuzeFile( vf ));
+		}
+		
+		return( new Engine[0]);
+	}
+	
+	public Engine[]
+	loadFromVuzeFile(
+		VuzeFile		vf )
+	{
+		List<Engine>	result = new ArrayList<Engine>();
+		
+		VuzeFileComponent[] comps = vf.getComponents();
+		
+		for (int j=0;j<comps.length;j++){
+			
+			VuzeFileComponent comp = comps[j];
+			
+			if ( comp.getType() == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
+				
+				try{
+					result.add( importEngine( comp.getContent(), false ));
+											
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+		}
+		
+		return(result.toArray(new Engine[result.size()]));
+	}
+	
+	public long
+	getLocalTemplateID()
+	{
+		synchronized( this ){
+			
+			Random random = new Random();
+			
+			while( true ){
+			
+				long id = ((long)Integer.MAX_VALUE) + random.nextInt( Integer.MAX_VALUE );
+				
+				if ( meta_search.getEngine( id ) == null ){
+					
+					return( id );
+				}
+			}
+		}
+	}
+	
+	public void
+	addListener(
+		MetaSearchManagerListener		listener )
+	{			
+		synchronized( listeners ){
+			
+			listeners.add( listener );
+		}
+			
+		dispatchOps();
+	}
+	
+	public void
+	removeListener(
+		MetaSearchManagerListener		listener )
+	{
+		
+	}
+	
+	private void
+	addOperation(
+		Map		map )
+	{
+		synchronized( listeners ){
+			
+			operations.add( map );
+		}
+		
+		dispatchOps();
+	}
+	
+	private void
+	dispatchOps()
+	{
+		op_dispatcher.dispatch(
+			new AERunnable()
+			{
+				public void
+				runSupport()
+				{
+					List<MetaSearchManagerListener>	l;
+					List<Map>						o;
+					
+					synchronized( listeners ){
+					
+						if ( listeners.size() == 0 || operations.size() == 0 ){
+							
+							return;
+						}
+						
+						l = new ArrayList<MetaSearchManagerListener>( listeners );
+						
+						o = new ArrayList<Map>( operations );
+						
+						operations.clear();
+					}
+					
+					for ( MetaSearchManagerListener listener: l ){
+						
+						for ( Map operation: o ){
+					
+							try{
+
+								int	type = ImportExportUtils.importInt( operation, "type", -1 );
+								
+								if ( type == 1 ){
+									
+									String	term = ImportExportUtils.importString( operation, "term", null );
+								
+									if ( term == null ){
+										
+										Debug.out( "search term missing" );
+										
+									}else{
+										
+										listener.searchRequest( term );
+									}
+								}else{
+								
+									Debug.out( "unknown operation type " + type );
+								}								
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}
+					}
+				}
+			});
+	}
+	
+	private void
+	setupExtensions()
+	{
+		PluginInterface pi = PluginInitializer.getDefaultInterface();
+		
+		final FeatureManager fm = pi.getUtilities().getFeatureManager();
+					
+		fm.addListener(
+			new FeatureManager.FeatureManagerListener()
+			{
+				public void
+				licenceAdded(
+					Licence	licence )
+				{
+					getExtensions( fm, false );
+				}
+				
+				public void
+				licenceChanged(
+					Licence	licence )
+				{
+					getExtensions( fm, false );
+				}
+				
+				public void
+				licenceRemoved(
+					Licence	licence )
+				{
+					getExtensions( fm, false );
+				}
+			});
+		
+		if ( pi.getPluginState().isInitialisationComplete()){
+			
+			getExtensions( fm, true );
+			
+		}else{
+			
+			pi.addListener(
+				new PluginListener()
+				{
+					public void
+					initializationComplete()
+					{
+						getExtensions( fm, false );
+					}
+					
+					public void
+					closedownInitiated()
+					{
+					}
+					
+					public void
+					closedownComplete()
+					{	
+					}
+				});
+		}
+	}
+	
+	private void
+	getExtensions(
+		FeatureManager		fm,
+		boolean				init )
+	{
+		String	existing_ext 	= extension_key;
+		String	latest_ext		= null;
+		
+		FeatureDetails[] fds = fm.getFeatureDetails( "core" );
+		
+		for ( FeatureDetails fd: fds ){
+				
+			if ( !fd.hasExpired()){
+				
+				String finger_print = (String)fd.getProperty( FeatureDetails.PR_FINGERPRINT );
+					
+				if ( finger_print != null ){
+				
+					latest_ext = fd.getLicence().getShortID() + "-" + finger_print;
+					
+					break;
+				}
+			}
+		}
+
+		if ( existing_ext != latest_ext ){
+			
+			if ( existing_ext == null || latest_ext == null || !existing_ext.equals( latest_ext )){
+				
+				extension_key	= latest_ext;
+				
+				COConfigurationManager.setParameter( "metasearch.extkey.latest", latest_ext==null?"":latest_ext );
+				
+				if ( !init ){
+					
+					refresh();
+				}
+			}
+		}
+	}
+	
+	protected String
+	getExtensionKey()
+	{
+		return( extension_key );
+	}
+	
+	public void 
+	log(
+		String 		s,
+		Throwable 	e )
+	{
+		AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( LOGGER_NAME );
+		
+		diag_logger.log( s );
+		diag_logger.log( e );
+		
+		if ( ConstantsVuze.DIAG_TO_STDOUT ){
+			
+			System.out.println(Thread.currentThread().getName() + "|"
+					+ System.currentTimeMillis() + "] " + s + ": " + Debug.getNestedExceptionMessage(e));
+		}	
+	}
+	
+	public void 
+	log(
+		String 	s )
+	{
+		AEDiagnosticsLogger diag_logger = AEDiagnostics.getLogger( LOGGER_NAME );
+		
+		diag_logger.log( s );
+		
+		if ( ConstantsVuze.DIAG_TO_STDOUT ){
+			
+			System.out.println(Thread.currentThread().getName() + "|"
+					+ System.currentTimeMillis() + "] " + s);
+		}
+	}
+	
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		writer.println( "Metasearch: auto=" + isAutoMode());
+			
+		try{
+			writer.indent();
+
+			meta_search.generate( writer );
+			
+		}finally{
+			
+			writer.exdent();
+		}
+	}
+	
+	protected static class
+	SearchObject
+		implements Search, ResultListener
+	{
+		private SearchListener		listener;
+		
+		private Map<Long,engineInfo>	engine_map = new HashMap<Long, engineInfo>();
+		private boolean					engines_set;
+		
+		private List<SearchProviderResults>	pending_results = new ArrayList<SearchProviderResults>();
+		
+		private boolean	is_complete;
+		
+		protected
+		SearchObject(
+			SearchListener	_listener )
+		{
+			listener = _listener;
+		}
+		
+		protected void
+		setEnginesUsed(
+			Engine[]	engines )
+		{
+			boolean	report_complete;
+			
+			synchronized( engine_map ){
+				
+				for ( Engine e: engines ){
+					
+					getInfo( e );
+				}
+				
+				engines_set = true;
+				
+				report_complete = reportOverallComplete();
+			}
+			
+			if ( listener != null && report_complete ){
+					
+				listener.completed();
+			}
+		}
+		
+		private boolean
+		reportOverallComplete()
+		{
+			if ( is_complete || !engines_set ){
+				
+				return( false );
+			}
+			
+			for ( engineInfo info: engine_map.values()){
+				
+				if ( !info.isComplete()){
+					
+					return( false );
+				}
+			}
+			
+			is_complete = true;
+			
+			return( true );
+		}
+		
+		protected engineInfo
+		getInfo(
+			Engine		engine )
+		{
+			synchronized( engine_map ){
+
+				engineInfo res = engine_map.get( engine.getId());
+				
+				if ( res == null ){
+					
+					res = new engineInfo( engine );
+					
+					engine_map.put( engine.getId(), res );
+				}
+				
+				return( res );
+			}
+		}
+		
+		public void 
+		contentReceived(
+			Engine 		engine, 
+			String 		content )
+		{	
+				// boring
+		}
+		
+		public void 
+		matchFound( 
+			Engine 		engine, 
+			String[] 	fields )
+		{	
+			// boring
+		}
+		
+		public void 
+		resultsReceived(
+			Engine 			engine,
+			final Result[] 	results )
+		{
+			SearchProviderResults	result;
+
+			synchronized( engine_map ){
+				
+				final engineInfo info = getInfo( engine );
+				
+				result = 
+					new SearchProviderResults()
+					{
+						public SearchProvider
+						getProvider()
+						{
+							return( info );
+						}
+						
+						public SearchResult[]
+						getResults()
+						{
+							return( wrapResults( results ));
+						}
+						
+						public boolean
+						isComplete()
+						{
+							return( false );
+						}
+						
+						public SearchException
+						getError()
+						{
+							return( null );
+						}
+					};
+					
+				pending_results.add( result );
+			}
+			
+			if ( listener != null ){
+				
+				listener.receivedResults( new SearchProviderResults[]{ result });
+			}
+		}
+		
+		public void 
+		resultsComplete(
+			Engine 		engine )
+		{
+			boolean					report_complete;
+			SearchProviderResults	result;
+			
+			synchronized( engine_map ){
+				
+				final engineInfo info = getInfo( engine );
+				
+				info.setComplete();
+				
+				report_complete = reportOverallComplete();
+			
+				result = 
+					new SearchProviderResults()
+					{
+						public SearchProvider
+						getProvider()
+						{
+							return( info );
+						}
+						
+						public SearchResult[]
+						getResults()
+						{
+							return( new SearchResult[0] );
+						}
+						
+						public boolean
+						isComplete()
+						{
+							return( true );
+						}
+						
+						public SearchException
+						getError()
+						{
+							return( null );
+						}
+					};
+					
+				pending_results.add( result );
+			}
+			
+			if ( listener != null ){
+				
+				listener.receivedResults( new SearchProviderResults[]{ result });
+				
+				if ( report_complete ){
+					
+					listener.completed();
+				}
+			}
+		}
+		
+		protected void
+		failed(
+			Engine						engine,
+			final SearchException		error )
+		{
+			boolean					report_complete;
+			SearchProviderResults	result;
+			
+			synchronized( engine_map ){
+				
+				final engineInfo info = getInfo( engine );
+				
+				info.setComplete();
+				
+				report_complete = reportOverallComplete();
+				
+				result = 
+						new SearchProviderResults()
+						{
+							public SearchProvider
+							getProvider()
+							{
+								return( info );
+							}
+							
+							public SearchResult[]
+							getResults()
+							{
+								return( new SearchResult[0] );
+							}
+							
+							public boolean
+							isComplete()
+							{
+								return( false );
+							}
+							
+							public SearchException
+							getError()
+							{
+								return( error );
+							}
+						};
+						
+				pending_results.add( result );
+			}
+			
+			if ( listener != null ){
+				
+				listener.receivedResults( new SearchProviderResults[]{ result });
+				
+				if ( report_complete ){
+					
+					listener.completed();
+				}
+			}
+		}
+		
+		public void 
+		engineFailed(
+			Engine 		engine, 
+			Throwable 	cause )
+		{
+			failed( engine, new SearchException( "Search failed", cause ));
+		}
+		
+		public void 
+		engineRequiresLogin(
+			Engine 		engine, 
+			Throwable 	cause )
+		{
+			failed( engine, new SearchException( "Authentication required", cause ));
+		}
+		
+		protected SearchResult[]
+		wrapResults(
+			Result[]	res )
+		{
+			SearchResult[] x = new SearchResult[ res.length ];
+			
+			for ( int i=0;i<x.length;i++){
+				
+				x[i] = new resultWrapper( res[i] );
+			}
+			
+			return( x );
+		}
+		
+		public SearchProviderResults[]
+     	getResults()
+		{
+     		synchronized( engine_map ){
+
+     			SearchProviderResults[] result = pending_results.toArray( new SearchProviderResults[pending_results.size()]);
+     			
+     			pending_results.clear();
+     			
+     			return( result );
+     		}
+		}
+     	
+     	public boolean
+     	isComplete()
+     	{
+     		synchronized( engine_map ){
+     			
+     			if ( !is_complete ){
+     				
+     				return( false );
+     			}
+     			
+     			if ( pending_results.size() > 0 ){
+     				
+     				return( false );
+     			}
+     			
+     			return( true );
+     		}
+     	}
+     	
+     	protected static class
+     	resultWrapper
+     		implements SearchResult
+     	{
+     		private Result	result;
+     		
+     		protected
+     		resultWrapper(
+     			Result		_result )
+     		{
+     			result	= _result;
+     		}
+     		
+     		public Object
+     		getProperty(
+     			int		property_name )
+     		{
+     			switch( property_name ){
+	     			case PR_NAME:{
+	     			
+	     				return( result.getName());
+	     			}
+	     			case PR_PUB_DATE:{
+	     				
+	     				return( result.getPublishedDate());
+	     			}
+	     			case PR_SIZE:{
+	     				
+	     				return( result.getSize());
+	     			}
+	     			case PR_LEECHER_COUNT:{
+	     				
+	     				return( new Long( result.getNbPeers()));
+	     			}
+	     			case PR_SEED_COUNT:{
+	     				
+	     				return( new Long( result.getNbSeeds()));
+	     			}
+	     			case PR_SUPER_SEED_COUNT:{
+	     				
+	     				return( new Long( result.getNbSuperSeeds()));
+	     			}
+	     			case PR_CATEGORY:{
+	     				
+	     				return( result.getCategory());
+	     			}
+	     			case PR_COMMENTS:{
+	     				
+	     				return( new Long( result.getComments()));
+	     			}
+	     			case PR_VOTES:{
+	     				
+	     				return( new Long( result.getVotes()));
+	     			}
+	     			case PR_CONTENT_TYPE:{
+	     				
+	     				return( result.getContentType());
+	     			}
+	     			case PR_DETAILS_LINK:{
+	     				
+	     				return( result.getCDPLink());
+	     			}
+	     			case PR_DOWNLOAD_LINK:{
+	     				
+	     				return( result.getDownloadLink());
+	     			}
+	     			case PR_PLAY_LINK:{
+	     				
+	     				return( result.getPlayLink());
+	     			}
+	     			case PR_PRIVATE:{
+	     				
+	     				return( result.isPrivate());
+	     			}
+	     			case PR_DRM_KEY:{
+	     				
+	     				return( result.getDRMKey());
+	     			}
+	     			case PR_DOWNLOAD_BUTTON_LINK:{
+	     				
+	     				return( result.getDownloadButtonLink());
+	     			}
+	     			case PR_RANK:{
+	     			
+	     				float rank = result.getRank();
+	     				
+	     				return( new Long(rank==-1?-1:(long)( rank * 100 )));
+	     			}
+	     			case PR_ACCURACY:{
+	     			
+	     				float accuracy = result.getAccuracy();
+	     				
+	     				return( new Long(accuracy==-1?-1:(long)( accuracy * 100 )));
+	     			}
+	     			case PR_VOTES_DOWN:{
+	     				
+	     				return( new Long( result.getVotesDown()));
+	     			}
+	     			case PR_UID:{
+	     			
+	     				return( result.getUID());
+	     			}
+	     			case PR_HASH:{
+	     				
+	     				String base32_hash = result.getHash();
+	     				
+	     				if ( base32_hash != null ){
+	     					
+	     					return( Base32.decode( base32_hash ));
+	     				}
+	     				
+	     				return( null );
+	     			}
+	     			default:{
+	     				
+	     				Debug.out( "Unknown property type " + property_name );
+	     			}
+     			}
+     			
+     			return( null );
+     		}
+     	}
+	}
+	
+    protected static class
+    engineInfo
+    	implements SearchProvider
+    {
+    	private Engine		engine;
+     		
+    	private boolean		complete;
+    	
+    	protected
+    	engineInfo(
+    		Engine		_engine )
+    	{
+    		engine	= _engine;
+    	}
+    
+    	protected void
+    	setComplete()
+    	{
+    		complete	= true;
+    	}
+    	
+    	protected boolean
+    	isComplete()
+    	{
+    		return( complete );
+    	}
+    	
+		public SearchInstance
+		search(
+			Map<String,Object>	search_parameters,
+			SearchObserver		observer )
+		
+			throws SearchException
+		{
+			throw( new SearchException( "Not supported" ));
+		}
+		
+		public Object
+		getProperty(
+			int			property )
+		{
+			if ( property == PR_ID ){
+				
+				return( engine.getId());
+				
+			}else if ( property == PR_NAME ){
+				
+				return( engine.getName());
+				
+			}else{
+				
+				return( null );
+			}
+		}
+		
+		public void
+		setProperty(
+			int			property,
+			Object		value )
+		{
+			Debug.out( "Not supported" );
+		}
+	}
+    
+    public static void
+    main(
+    	String[]	args )
+    {
+    	try{
+			VuzeFile	vf = VuzeFileHandler.getSingleton().create();
+			
+			Map contents = new HashMap();
+			
+			contents.put( "type", new Long( 1 ));
+			contents.put( "term", "donkey" );
+			
+			vf.addComponent(
+				VuzeFileComponent.COMP_TYPE_METASEARCH_OPERATION,
+				contents);
+			
+			vf.write( new File( "C:\\temp\\search.vuze" ));
+			
+    	}catch( Throwable e ){
+    		
+    		e.printStackTrace();
+    	}
+    }
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/SearchExecuter.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/SearchExecuter.java
index 8d4c945..1e9af8c 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/SearchExecuter.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/SearchExecuter.java
@@ -1,69 +1,68 @@
-/*
- * Created on May 6, 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.core.metasearch.impl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.AEThread2;
-
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.ResultListener;
-import com.aelitis.azureus.core.metasearch.SearchException;
-import com.aelitis.azureus.core.metasearch.SearchParameter;
-
-
-public class 
-SearchExecuter 
-{
-	private Map				context;
-	private ResultListener 	listener;
-	
-	public 
-	SearchExecuter(
-		Map				_context,
-		ResultListener	_listener ) 
-	{
-		context		= _context;
-		listener 	= _listener;
-	}
-	
-	public void 
-	search(
-		final Engine 			engine,
-		final SearchParameter[] searchParameters, 
-		final String 			headers,
-		final int				desired_max_matches )
-	{
-		new AEThread2( "MetaSearch: " + engine.getName() + " runner", true )
-		{
-			public void 
-			run() 
-			{
-				try{
-					engine.search( searchParameters, context, desired_max_matches, -1, headers, listener );
-					
-				}catch( SearchException e ){
-				}
-			}
-		}.start();
-	}
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.gudy.azureus2.core3.util.AEThread2;
+
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.ResultListener;
+import com.aelitis.azureus.core.metasearch.SearchException;
+import com.aelitis.azureus.core.metasearch.SearchParameter;
+
+
+public class 
+SearchExecuter 
+{
+	private Map				context;
+	private ResultListener 	listener;
+	
+	public 
+	SearchExecuter(
+		Map				_context,
+		ResultListener	_listener ) 
+	{
+		context		= _context;
+		listener 	= _listener;
+	}
+	
+	public void 
+	search(
+		final Engine 			engine,
+		final SearchParameter[] searchParameters, 
+		final String 			headers,
+		final int				desired_max_matches )
+	{
+		new AEThread2( "MetaSearch: " + engine.getName() + " runner", true )
+		{
+			public void 
+			run() 
+			{
+				try{
+					engine.search( searchParameters, context, desired_max_matches, -1, headers, listener );
+					
+				}catch( SearchException e ){
+				}
+			}
+		}.start();
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/plugin/PluginEngine.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/plugin/PluginEngine.java
index b1230f3..6472bfa 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/plugin/PluginEngine.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/plugin/PluginEngine.java
@@ -1,385 +1,384 @@
-/*
- * 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 com.aelitis.azureus.core.metasearch.impl.plugin;
-
-import java.io.IOException;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.AESemaphore;
-import org.gudy.azureus2.core3.util.Debug;
-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 com.aelitis.azureus.core.metasearch.*;
-import com.aelitis.azureus.core.metasearch.impl.*;
-
-public class 
-PluginEngine
-	extends EngineImpl
-{
-	private static int[][] FIELD_MAP = {
-		
-		{ SearchResult.PR_CATEGORY,				Engine.FIELD_CATEGORY },
-		{ SearchResult.PR_COMMENTS,				Engine.FIELD_COMMENTS },
-		{ SearchResult.PR_CONTENT_TYPE,			Engine.FIELD_CONTENT_TYPE },
-		{ SearchResult.PR_DETAILS_LINK,			Engine.FIELD_CDPLINK },
-		{ SearchResult.PR_DOWNLOAD_BUTTON_LINK,	Engine.FIELD_DOWNLOADBTNLINK },
-		{ SearchResult.PR_DOWNLOAD_LINK,		Engine.FIELD_TORRENTLINK },
-		{ SearchResult.PR_DRM_KEY,				Engine.FIELD_DRMKEY },
-		{ SearchResult.PR_LEECHER_COUNT,		Engine.FIELD_PEERS },
-		{ SearchResult.PR_NAME,					Engine.FIELD_NAME },
-		{ SearchResult.PR_PLAY_LINK,			Engine.FIELD_PLAYLINK },
-		{ SearchResult.PR_PRIVATE,				Engine.FIELD_PRIVATE },
-		{ SearchResult.PR_PUB_DATE,				Engine.FIELD_DATE },
-		{ SearchResult.PR_SEED_COUNT,			Engine.FIELD_SEEDS },
-		{ SearchResult.PR_SIZE,					Engine.FIELD_SIZE },
-		{ SearchResult.PR_SUPER_SEED_COUNT,		Engine.FIELD_SUPERSEEDS },
-		{ SearchResult.PR_VOTES,				Engine.FIELD_VOTES },
-	};
-		
-		
-	public static EngineImpl
-	importFromBEncodedMap(
-		MetaSearchImpl		meta_search,
-		Map					map )
-	
-		throws IOException
-	{
-		return( new PluginEngine( meta_search, map ));
-	}
-	
-	private SearchProvider			provider;
-	
-	public
-	PluginEngine(
-		MetaSearchImpl		_meta_search,
-		long				_id,
-		SearchProvider		_provider )
-	{
-		super( _meta_search, Engine.ENGINE_TYPE_PLUGIN, _id, 0, 1.0f, (String)_provider.getProperty( SearchProvider.PR_NAME ));
-		
-		provider	= _provider;
-		
-		setSource( ENGINE_SOURCE_LOCAL );
-	}
-	
-	protected
-	PluginEngine(
-		MetaSearchImpl		_meta_search,
-		Map					_map )
-	
-		throws IOException
-	{
-		super( _meta_search, _map );
-		
-			// recovery from when incorrectly defaulted to 0.0
-		
-		if ( getRankBias() == 0.0f ){
-			
-			setRankBias( 1.0f );
-		}
-		
-		setSource( ENGINE_SOURCE_LOCAL );
-	}
-	
-	public Map 
-	exportToBencodedMap()
-	
-		throws IOException
-	{
-		return( exportToBencodedMap( false ));
-	}
-	
-	public Map 
-	exportToBencodedMap(
-		boolean	generic )
-	
-		throws IOException 
-	{
-		Map	res = new HashMap();
-				
-		super.exportToBencodedMap( res, generic );
-		
-		return( res );
-	}
-	
-	public void
-	setProvider(
-		SearchProvider		_provider )
-	{
-		provider	= _provider;
-	}
-	
-	public SearchProvider
-	getProvider()
-	{
-		return( provider );
-	}
-	
-	protected boolean
-	useAccuracyForRank()
-	{
-		if ( provider == null ){
-			
-			return( false );
-		}
-		
-		Boolean val = (Boolean)provider.getProperty( SearchProvider.PR_USE_ACCURACY_FOR_RANK );
-		
-		if ( val == null ){
-			
-			return( false );
-		}
-		
-		return( val.booleanValue());
-	}
-	public boolean
-	isActive()
-	{
-		return( provider != null && super.isActive());
-	}
-	
-	public String 
-	getNameEx() 
-	{
-		return( super.getName() + ": (plugin)" );
-	}
-	
-	public String 
-	getDownloadLinkCSS() 
-	{
-		if ( provider == null ){
-			
-			return( null );
-		}
-		
-		return((String)provider.getProperty( SearchProvider.PR_DOWNLOAD_LINK_LOCATOR ));
-	}
-	
-	public boolean 
-	supportsField(
-		int		field )
-	{
-		if ( provider == null ){
-			
-			return( false );
-		}
-		
-		int[] supports = (int[])provider.getProperty( SearchProvider.PR_SUPPORTS_RESULT_FIELDS );
-		
-		if ( supports == null ){
-			
-			return( true );
-		}
-		
-		for (int i=0;i<FIELD_MAP.length;i++){
-			
-			int[]	entry = FIELD_MAP[i];
-			
-			if ( entry[1] == field ){
-				
-				for (int j=0;j<supports.length;j++){
-					
-					if ( supports[j] == entry[0] ){
-						
-						return( true );
-					}
-				}
-				
-				break;
-			}
-		}
-		
-		return( false );
-	}
-	
-	public boolean
-	supportsContext(
-		String	context_key )
-	{
-		return( false );
-	}
-	
-	public boolean 
-	isShareable() 
-	{
-		return( false );
-	}
-	
-	public String 
-	getIcon() 
-	{
-		if ( provider == null ){
-			
-			return( null );
-		}
-		
-		return((String)provider.getProperty( SearchProvider.PR_ICON_URL ));
-	}
-	
-	public String 
-	getReferer() 
-	{
-		if ( provider == null ){
-			
-			return( null );
-		}
-		
-		return((String)provider.getProperty( SearchProvider.PR_REFERER ));
-	}
-	
-	protected Result[] 
-	searchSupport(
-		SearchParameter[] 		params, 
-		Map						searchContext,
-		final int 				desired_max_matches,
-		final int				absolute_max_matches,
-		String 					headers, 
-		final ResultListener 	listener )
-	
-		throws SearchException 
-	{
-		if ( provider == null ){
-			
-			provider = getMetaSearch().resolveProvider( this );
-			
-			if ( provider == null ){
-				
-				return( new Result[0]  );
-			}
-		}
-		
-		Map search_parameters = new HashMap();
-		
-		String	term = null;
-		
-		for (int i=0;i<params.length;i++){
-			
-			SearchParameter param = params[i];
-			
-			String pattern 	= param.getMatchPattern();
-			String value	= param.getValue();
-			
-			if ( pattern.equals( "s" )){
-				
-				term = value;
-				
-				search_parameters.put( SearchProvider.SP_SEARCH_TERM, value );
-				
-			}else if ( pattern.equals( "m" )){
-			
-				search_parameters.put( SearchProvider.SP_MATURE, new Boolean(value ));
-
-			}else{
-				
-				Debug.out( "Unrecognised search parameter '" + pattern + "=" + value + "' ignored" );
-			}
-		}
-			
-		final String f_term = term;
-		
-		try{
-			final List<PluginResult>	results = new ArrayList<PluginResult>();
-			
-			final AESemaphore	sem = new AESemaphore( "waiter" );
-
-			provider.search( 
-				search_parameters,
-				new SearchObserver()
-				{
-					private boolean	complete = false;
-					
-					public void 
-					resultReceived(
-						SearchInstance 		search,
-						SearchResult 		result )
-					{
-						PluginResult p_result = new PluginResult( PluginEngine.this, result, f_term );
-						
-						synchronized( this ){
-							
-							if ( complete ){
-								
-								return;
-							}
-							
-							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;
-								
-								sem.release();
-							}
-						}
-					}
-					
-					public void 
-					cancelled() 
-					{
-						sem.release();
-					}
-					
-					public void 
-					complete() 
-					{
-						sem.release();
-					}
-					
-					public Object 
-					getProperty(
-						int property ) 
-					{
-						if ( property == PR_MAX_RESULTS_WANTED ){
-							
-							return( new Long( desired_max_matches ));
-						}
-						
-						return( null );
-					}
-				});
-			
-			sem.reserve();
-			
-			if ( listener != null ){
-				
-				listener.resultsComplete( this );
-			}
-			
-			return((Result[])results.toArray(new Result[results.size()]));
-			
-		}catch( Throwable e ){
-			
-			throw( new SearchException( "Search failed", e ));
-		}
-	}
-}
+/*
+ * Created on Jun 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl.plugin;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.AESemaphore;
+import org.gudy.azureus2.core3.util.Debug;
+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 com.aelitis.azureus.core.metasearch.*;
+import com.aelitis.azureus.core.metasearch.impl.*;
+
+public class 
+PluginEngine
+	extends EngineImpl
+{
+	private static int[][] FIELD_MAP = {
+		
+		{ SearchResult.PR_CATEGORY,				Engine.FIELD_CATEGORY },
+		{ SearchResult.PR_COMMENTS,				Engine.FIELD_COMMENTS },
+		{ SearchResult.PR_CONTENT_TYPE,			Engine.FIELD_CONTENT_TYPE },
+		{ SearchResult.PR_DETAILS_LINK,			Engine.FIELD_CDPLINK },
+		{ SearchResult.PR_DOWNLOAD_BUTTON_LINK,	Engine.FIELD_DOWNLOADBTNLINK },
+		{ SearchResult.PR_DOWNLOAD_LINK,		Engine.FIELD_TORRENTLINK },
+		{ SearchResult.PR_DRM_KEY,				Engine.FIELD_DRMKEY },
+		{ SearchResult.PR_LEECHER_COUNT,		Engine.FIELD_PEERS },
+		{ SearchResult.PR_NAME,					Engine.FIELD_NAME },
+		{ SearchResult.PR_PLAY_LINK,			Engine.FIELD_PLAYLINK },
+		{ SearchResult.PR_PRIVATE,				Engine.FIELD_PRIVATE },
+		{ SearchResult.PR_PUB_DATE,				Engine.FIELD_DATE },
+		{ SearchResult.PR_SEED_COUNT,			Engine.FIELD_SEEDS },
+		{ SearchResult.PR_SIZE,					Engine.FIELD_SIZE },
+		{ SearchResult.PR_SUPER_SEED_COUNT,		Engine.FIELD_SUPERSEEDS },
+		{ SearchResult.PR_VOTES,				Engine.FIELD_VOTES },
+	};
+		
+		
+	public static EngineImpl
+	importFromBEncodedMap(
+		MetaSearchImpl		meta_search,
+		Map					map )
+	
+		throws IOException
+	{
+		return( new PluginEngine( meta_search, map ));
+	}
+	
+	private SearchProvider			provider;
+	
+	public
+	PluginEngine(
+		MetaSearchImpl		_meta_search,
+		long				_id,
+		SearchProvider		_provider )
+	{
+		super( _meta_search, Engine.ENGINE_TYPE_PLUGIN, _id, 0, 1.0f, (String)_provider.getProperty( SearchProvider.PR_NAME ));
+		
+		provider	= _provider;
+		
+		setSource( ENGINE_SOURCE_LOCAL );
+	}
+	
+	protected
+	PluginEngine(
+		MetaSearchImpl		_meta_search,
+		Map					_map )
+	
+		throws IOException
+	{
+		super( _meta_search, _map );
+		
+			// recovery from when incorrectly defaulted to 0.0
+		
+		if ( getRankBias() == 0.0f ){
+			
+			setRankBias( 1.0f );
+		}
+		
+		setSource( ENGINE_SOURCE_LOCAL );
+	}
+	
+	public Map 
+	exportToBencodedMap()
+	
+		throws IOException
+	{
+		return( exportToBencodedMap( false ));
+	}
+	
+	public Map 
+	exportToBencodedMap(
+		boolean	generic )
+	
+		throws IOException 
+	{
+		Map	res = new HashMap();
+				
+		super.exportToBencodedMap( res, generic );
+		
+		return( res );
+	}
+	
+	public void
+	setProvider(
+		SearchProvider		_provider )
+	{
+		provider	= _provider;
+	}
+	
+	public SearchProvider
+	getProvider()
+	{
+		return( provider );
+	}
+	
+	protected boolean
+	useAccuracyForRank()
+	{
+		if ( provider == null ){
+			
+			return( false );
+		}
+		
+		Boolean val = (Boolean)provider.getProperty( SearchProvider.PR_USE_ACCURACY_FOR_RANK );
+		
+		if ( val == null ){
+			
+			return( false );
+		}
+		
+		return( val.booleanValue());
+	}
+	public boolean
+	isActive()
+	{
+		return( provider != null && super.isActive());
+	}
+	
+	public String 
+	getNameEx() 
+	{
+		return( super.getName() + ": (plugin)" );
+	}
+	
+	public String 
+	getDownloadLinkCSS() 
+	{
+		if ( provider == null ){
+			
+			return( null );
+		}
+		
+		return((String)provider.getProperty( SearchProvider.PR_DOWNLOAD_LINK_LOCATOR ));
+	}
+	
+	public boolean 
+	supportsField(
+		int		field )
+	{
+		if ( provider == null ){
+			
+			return( false );
+		}
+		
+		int[] supports = (int[])provider.getProperty( SearchProvider.PR_SUPPORTS_RESULT_FIELDS );
+		
+		if ( supports == null ){
+			
+			return( true );
+		}
+		
+		for (int i=0;i<FIELD_MAP.length;i++){
+			
+			int[]	entry = FIELD_MAP[i];
+			
+			if ( entry[1] == field ){
+				
+				for (int j=0;j<supports.length;j++){
+					
+					if ( supports[j] == entry[0] ){
+						
+						return( true );
+					}
+				}
+				
+				break;
+			}
+		}
+		
+		return( false );
+	}
+	
+	public boolean
+	supportsContext(
+		String	context_key )
+	{
+		return( false );
+	}
+	
+	public boolean 
+	isShareable() 
+	{
+		return( false );
+	}
+	
+	public String 
+	getIcon() 
+	{
+		if ( provider == null ){
+			
+			return( null );
+		}
+		
+		return((String)provider.getProperty( SearchProvider.PR_ICON_URL ));
+	}
+	
+	public String 
+	getReferer() 
+	{
+		if ( provider == null ){
+			
+			return( null );
+		}
+		
+		return((String)provider.getProperty( SearchProvider.PR_REFERER ));
+	}
+	
+	protected Result[] 
+	searchSupport(
+		SearchParameter[] 		params, 
+		Map						searchContext,
+		final int 				desired_max_matches,
+		final int				absolute_max_matches,
+		String 					headers, 
+		final ResultListener 	listener )
+	
+		throws SearchException 
+	{
+		if ( provider == null ){
+			
+			provider = getMetaSearch().resolveProvider( this );
+			
+			if ( provider == null ){
+				
+				return( new Result[0]  );
+			}
+		}
+		
+		Map search_parameters = new HashMap();
+		
+		String	term = null;
+		
+		for (int i=0;i<params.length;i++){
+			
+			SearchParameter param = params[i];
+			
+			String pattern 	= param.getMatchPattern();
+			String value	= param.getValue();
+			
+			if ( pattern.equals( "s" )){
+				
+				term = value;
+				
+				search_parameters.put( SearchProvider.SP_SEARCH_TERM, value );
+				
+			}else if ( pattern.equals( "m" )){
+			
+				search_parameters.put( SearchProvider.SP_MATURE, new Boolean(value ));
+
+			}else{
+				
+				Debug.out( "Unrecognised search parameter '" + pattern + "=" + value + "' ignored" );
+			}
+		}
+			
+		final String f_term = term;
+		
+		try{
+			final List<PluginResult>	results = new ArrayList<PluginResult>();
+			
+			final AESemaphore	sem = new AESemaphore( "waiter" );
+
+			provider.search( 
+				search_parameters,
+				new SearchObserver()
+				{
+					private boolean	complete = false;
+					
+					public void 
+					resultReceived(
+						SearchInstance 		search,
+						SearchResult 		result )
+					{
+						PluginResult p_result = new PluginResult( PluginEngine.this, result, f_term );
+						
+						synchronized( this ){
+							
+							if ( complete ){
+								
+								return;
+							}
+							
+							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;
+								
+								sem.release();
+							}
+						}
+					}
+					
+					public void 
+					cancelled() 
+					{
+						sem.release();
+					}
+					
+					public void 
+					complete() 
+					{
+						sem.release();
+					}
+					
+					public Object 
+					getProperty(
+						int property ) 
+					{
+						if ( property == PR_MAX_RESULTS_WANTED ){
+							
+							return( new Long( desired_max_matches ));
+						}
+						
+						return( null );
+					}
+				});
+			
+			sem.reserve();
+			
+			if ( listener != null ){
+				
+				listener.resultsComplete( this );
+			}
+			
+			return((Result[])results.toArray(new Result[results.size()]));
+			
+		}catch( Throwable e ){
+			
+			throw( new SearchException( "Search failed", e ));
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/plugin/PluginResult.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/plugin/PluginResult.java
index 817965c..2eed855 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/plugin/PluginResult.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/plugin/PluginResult.java
@@ -1,398 +1,397 @@
-/*
- * 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 com.aelitis.azureus.core.metasearch.impl.plugin;
-
-import java.util.Date;
-import java.util.Map;
-
-import org.gudy.azureus2.core3.util.Base32;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.LightHashMap;
-import org.gudy.azureus2.plugins.utils.search.SearchResult;
-
-import com.aelitis.azureus.core.metasearch.*;
-
-public class 
-PluginResult 
-	extends Result
-{
-	private static final Object NULL_OBJECT = PluginResult.class;
-	
-	private SearchResult			result;
-	private String					search_term;
-	
-	private Map		property_cache = new LightHashMap();
-	
-	protected
-	PluginResult(
-		PluginEngine		_engine,
-		SearchResult		_result,
-		String				_search_term )
-	{
-		super( _engine );
-		
-		result			= _result;
-		search_term		= _search_term;
-	}
-	
-	public Date
-	getPublishedDate()
-	{
-		return((Date)getResultProperty( SearchResult.PR_PUB_DATE ));
-	}
-	
-	public String 
-	getCategory()
-	{
-		return(getStringProperty( SearchResult.PR_CATEGORY ));
-	}
-	
-	public void 
-	setCategory(
-		String category )
-	{	
-	}
-	
-	public String 
-	getContentType()
-	{
-		return(getStringProperty( SearchResult.PR_CONTENT_TYPE ));
-
-	}
-	
-	public void 
-	setContentType(
-		String contentType )
-	{	
-	}
-	
-	public String 
-	getName()
-	{
-		return(getStringProperty( SearchResult.PR_NAME ));
-	}
-	
-	public long 
-	getSize()
-	{
-		return(getLongProperty( SearchResult.PR_SIZE ));
-	}
-	
-	public int 
-	getNbPeers()
-	{
-		return(getIntProperty( SearchResult.PR_LEECHER_COUNT ));
-	}
-	
-	public int 
-	getNbSeeds()
-	{
-		return(getIntProperty( SearchResult.PR_SEED_COUNT ));
-	}
-	
-	public int 
-	getNbSuperSeeds()
-	{
-		return(getIntProperty( SearchResult.PR_SUPER_SEED_COUNT ));
-	}
-	
-	public int 
-	getComments()
-	{
-		return(getIntProperty( SearchResult.PR_COMMENTS ));
-	}
-	
-	public int 
-	getVotes()
-	{
-		return(getIntProperty( SearchResult.PR_VOTES ));
-	}
-	
-	public int 
-	getVotesDown()
-	{
-		return(getIntProperty( SearchResult.PR_VOTES_DOWN ));
-	}
-	
-	public boolean 
-	isPrivate()
-	{
-		return( getBooleanProperty( SearchResult.PR_PRIVATE ));
-	}
-	
-	
-	public String 
-	getDRMKey()
-	{
-		return(getStringProperty( SearchResult.PR_DRM_KEY ));
-	}
-	
-	public String 
-	getDownloadLink()
-	{
-		return(getStringProperty( SearchResult.PR_DOWNLOAD_LINK ));
-	}
-	
-	public String 
-	getDownloadButtonLink()
-	{
-		return(getStringProperty( SearchResult.PR_DOWNLOAD_BUTTON_LINK ));
-	}
-	
-	public String 
-	getCDPLink()
-	{
-		return( getStringProperty( SearchResult.PR_DETAILS_LINK ));
-
-	}
-	
-	public String 
-	getPlayLink()
-	{
-		return(getStringProperty( SearchResult.PR_PLAY_LINK ));
-	}
-	
-	public String 
-	getUID() 
-	{
-		return(getStringProperty( SearchResult.PR_UID ));
-	}
-	
-	public String 
-	getHash() 
-	{
-		byte[] hash = getByteArrayProperty( SearchResult.PR_HASH );
-		
-		if ( hash == null ){
-			
-			return( null );
-		}
-		
-		return( Base32.encode( hash ));
-	}
-	
-	public float 
-	getRank() 
-	{
-		if (((PluginEngine)getEngine()).useAccuracyForRank()){
-			
-			return( applyRankBias( getAccuracy()));
-		}
-		
-		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 ){
-			
-			return( super.getRank());
-		}
-		
-		float rank = l_rank;
-		
-		if ( rank > 100 ){
-			
-			rank = 100;
-			
-		}else if ( rank < 0 ){
-			
-			rank = 0;
-		}
-		
-		return( applyRankBias( rank / 100 ));
-	}
-	
-	public float 
-	getAccuracy()
-	{
-		long	l_accuracy = getLongProperty( SearchResult.PR_ACCURACY );
-		
-		if ( l_accuracy == Long.MIN_VALUE ){
-			
-			return( -1 );
-		}
-		
-		float accuracy = l_accuracy;
-		
-		if ( accuracy > 100 ){
-			
-			accuracy = 100;
-			
-		}else if ( accuracy < 0 ){
-			
-			accuracy = 0;
-		}
-		
-		return( accuracy / 100 );
-	}
-
-	public String 
-	getSearchQuery()
-	{
-		return( search_term );
-	}
-	
-	protected int
-	getIntProperty(
-		int		name )
-	{
-		return((int)getLongProperty( name ));
-	}
-	
-	protected long
-	getLongProperty(
-		int		name )
-	{
-		return( getLongProperty( name, Long.MIN_VALUE ));
-	}
-	
-	protected long
-	getLongProperty(
-		int		name,
-		long	def )
-	{
-		try{
-			Long	l = (Long)getResultProperty( name );
-			
-			if ( l == null ){
-				
-				return( def );
-			}
-			
-			return( l.longValue());
-			
-		}catch( Throwable e ){
-			
-			Debug.out( "Invalid value returned for Long property " + name );
-			
-			return( def );
-		}
-	}
-	
-	protected boolean
-	getBooleanProperty(
-		int		name )
-	{
-		return( getBooleanProperty( name, false ));
-	}
-	
-	protected boolean
-	getBooleanProperty(
-		int		name,
-		boolean	def )
-	{
-		try{
-			Boolean	b = (Boolean)getResultProperty( name );
-			
-			if ( b == null ){
-				
-				return( def );
-			}
-			
-			return( b.booleanValue());
-			
-		}catch( Throwable e ){
-			
-			Debug.out( "Invalid value returned for Boolean property " + name );
-			
-			return( def );
-		}
-	}
-	
-	protected String
-	getStringProperty(
-		int		name )
-	{
-		return( getStringProperty( name, "" ));
-	}
-	
-	protected String
-	getStringProperty(
-		int		name,
-		String	def )
-	{
-		try{
-			String	l = (String)getResultProperty( name );
-			
-			if ( l == null ){
-				
-				return( def );
-			}
-			
-			return( unescapeEntities( removeHTMLTags( l )));
-			
-		}catch( Throwable e ){
-			
-			Debug.out( "Invalid value returned for String property " + name );
-			
-			return( def );
-		}
-	}
-	
-	protected byte[]
-	getByteArrayProperty(
-		int		name )
-	{
-		try{
-			return((byte[])getResultProperty( name ));
-				
-		}catch( Throwable e ){
-			
-			Debug.out( "Invalid value returned for byte[] property " + name );
-			
-			return( null );
-		}
-	}
-	
-	protected synchronized Object
-	getResultProperty(
-		int		prop )
-	{
-		Integer i_prop = new Integer( prop );
-		
-		Object	res = property_cache.get( i_prop );
-		
-		if ( res == null ){
-			
-			res = result.getProperty( prop );
-			
-			if ( res == null ){
-				
-				res = NULL_OBJECT;
-			}
-			
-			property_cache.put( i_prop, res );
-		}
-		
-		if ( res == NULL_OBJECT ){
-			
-			return( null );
-		}
-		
-		return( res );
-	}
-}
+/*
+ * Created on Jun 20, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl.plugin;
+
+import java.util.Date;
+import java.util.Map;
+
+import org.gudy.azureus2.core3.util.Base32;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.LightHashMap;
+import org.gudy.azureus2.plugins.utils.search.SearchResult;
+
+import com.aelitis.azureus.core.metasearch.*;
+
+public class 
+PluginResult 
+	extends Result
+{
+	private static final Object NULL_OBJECT = PluginResult.class;
+	
+	private SearchResult			result;
+	private String					search_term;
+	
+	private Map		property_cache = new LightHashMap();
+	
+	protected
+	PluginResult(
+		PluginEngine		_engine,
+		SearchResult		_result,
+		String				_search_term )
+	{
+		super( _engine );
+		
+		result			= _result;
+		search_term		= _search_term;
+	}
+	
+	public Date
+	getPublishedDate()
+	{
+		return((Date)getResultProperty( SearchResult.PR_PUB_DATE ));
+	}
+	
+	public String 
+	getCategory()
+	{
+		return(getStringProperty( SearchResult.PR_CATEGORY ));
+	}
+	
+	public void 
+	setCategory(
+		String category )
+	{	
+	}
+	
+	public String 
+	getContentType()
+	{
+		return(getStringProperty( SearchResult.PR_CONTENT_TYPE ));
+
+	}
+	
+	public void 
+	setContentType(
+		String contentType )
+	{	
+	}
+	
+	public String 
+	getName()
+	{
+		return(getStringProperty( SearchResult.PR_NAME ));
+	}
+	
+	public long 
+	getSize()
+	{
+		return(getLongProperty( SearchResult.PR_SIZE ));
+	}
+	
+	public int 
+	getNbPeers()
+	{
+		return(getIntProperty( SearchResult.PR_LEECHER_COUNT ));
+	}
+	
+	public int 
+	getNbSeeds()
+	{
+		return(getIntProperty( SearchResult.PR_SEED_COUNT ));
+	}
+	
+	public int 
+	getNbSuperSeeds()
+	{
+		return(getIntProperty( SearchResult.PR_SUPER_SEED_COUNT ));
+	}
+	
+	public int 
+	getComments()
+	{
+		return(getIntProperty( SearchResult.PR_COMMENTS ));
+	}
+	
+	public int 
+	getVotes()
+	{
+		return(getIntProperty( SearchResult.PR_VOTES ));
+	}
+	
+	public int 
+	getVotesDown()
+	{
+		return(getIntProperty( SearchResult.PR_VOTES_DOWN ));
+	}
+	
+	public boolean 
+	isPrivate()
+	{
+		return( getBooleanProperty( SearchResult.PR_PRIVATE ));
+	}
+	
+	
+	public String 
+	getDRMKey()
+	{
+		return(getStringProperty( SearchResult.PR_DRM_KEY ));
+	}
+	
+	public String 
+	getDownloadLink()
+	{
+		return(getStringProperty( SearchResult.PR_DOWNLOAD_LINK ));
+	}
+	
+	public String 
+	getDownloadButtonLink()
+	{
+		return(getStringProperty( SearchResult.PR_DOWNLOAD_BUTTON_LINK ));
+	}
+	
+	public String 
+	getCDPLink()
+	{
+		return( getStringProperty( SearchResult.PR_DETAILS_LINK ));
+
+	}
+	
+	public String 
+	getPlayLink()
+	{
+		return(getStringProperty( SearchResult.PR_PLAY_LINK ));
+	}
+	
+	public String 
+	getUID() 
+	{
+		return(getStringProperty( SearchResult.PR_UID ));
+	}
+	
+	public String 
+	getHash() 
+	{
+		byte[] hash = getByteArrayProperty( SearchResult.PR_HASH );
+		
+		if ( hash == null ){
+			
+			return( null );
+		}
+		
+		return( Base32.encode( hash ));
+	}
+	
+	public float 
+	getRank() 
+	{
+		if (((PluginEngine)getEngine()).useAccuracyForRank()){
+			
+			return( applyRankBias( getAccuracy()));
+		}
+		
+		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 ){
+			
+			return( super.getRank());
+		}
+		
+		float rank = l_rank;
+		
+		if ( rank > 100 ){
+			
+			rank = 100;
+			
+		}else if ( rank < 0 ){
+			
+			rank = 0;
+		}
+		
+		return( applyRankBias( rank / 100 ));
+	}
+	
+	public float 
+	getAccuracy()
+	{
+		long	l_accuracy = getLongProperty( SearchResult.PR_ACCURACY );
+		
+		if ( l_accuracy == Long.MIN_VALUE ){
+			
+			return( -1 );
+		}
+		
+		float accuracy = l_accuracy;
+		
+		if ( accuracy > 100 ){
+			
+			accuracy = 100;
+			
+		}else if ( accuracy < 0 ){
+			
+			accuracy = 0;
+		}
+		
+		return( accuracy / 100 );
+	}
+
+	public String 
+	getSearchQuery()
+	{
+		return( search_term );
+	}
+	
+	protected int
+	getIntProperty(
+		int		name )
+	{
+		return((int)getLongProperty( name ));
+	}
+	
+	protected long
+	getLongProperty(
+		int		name )
+	{
+		return( getLongProperty( name, Long.MIN_VALUE ));
+	}
+	
+	protected long
+	getLongProperty(
+		int		name,
+		long	def )
+	{
+		try{
+			Long	l = (Long)getResultProperty( name );
+			
+			if ( l == null ){
+				
+				return( def );
+			}
+			
+			return( l.longValue());
+			
+		}catch( Throwable e ){
+			
+			Debug.out( "Invalid value returned for Long property " + name );
+			
+			return( def );
+		}
+	}
+	
+	protected boolean
+	getBooleanProperty(
+		int		name )
+	{
+		return( getBooleanProperty( name, false ));
+	}
+	
+	protected boolean
+	getBooleanProperty(
+		int		name,
+		boolean	def )
+	{
+		try{
+			Boolean	b = (Boolean)getResultProperty( name );
+			
+			if ( b == null ){
+				
+				return( def );
+			}
+			
+			return( b.booleanValue());
+			
+		}catch( Throwable e ){
+			
+			Debug.out( "Invalid value returned for Boolean property " + name );
+			
+			return( def );
+		}
+	}
+	
+	protected String
+	getStringProperty(
+		int		name )
+	{
+		return( getStringProperty( name, "" ));
+	}
+	
+	protected String
+	getStringProperty(
+		int		name,
+		String	def )
+	{
+		try{
+			String	l = (String)getResultProperty( name );
+			
+			if ( l == null ){
+				
+				return( def );
+			}
+			
+			return( unescapeEntities( removeHTMLTags( l )));
+			
+		}catch( Throwable e ){
+			
+			Debug.out( "Invalid value returned for String property " + name );
+			
+			return( def );
+		}
+	}
+	
+	protected byte[]
+	getByteArrayProperty(
+		int		name )
+	{
+		try{
+			return((byte[])getResultProperty( name ));
+				
+		}catch( Throwable e ){
+			
+			Debug.out( "Invalid value returned for byte[] property " + name );
+			
+			return( null );
+		}
+	}
+	
+	protected synchronized Object
+	getResultProperty(
+		int		prop )
+	{
+		Integer i_prop = new Integer( prop );
+		
+		Object	res = property_cache.get( i_prop );
+		
+		if ( res == null ){
+			
+			res = result.getProperty( prop );
+			
+			if ( res == null ){
+				
+				res = NULL_OBJECT;
+			}
+			
+			property_cache.put( i_prop, res );
+		}
+		
+		if ( res == NULL_OBJECT ){
+			
+			return( null );
+		}
+		
+		return( res );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/FieldMapping.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/FieldMapping.java
index 463b780..8e0f4de 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/FieldMapping.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/FieldMapping.java
@@ -1,44 +1,43 @@
-/*
- * Created on May 6, 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.core.metasearch.impl.web;
-
-public class FieldMapping {
-	
-	private String name;
-	private int field;
-	
-	public FieldMapping(String name,int field) {
-		this.name = name;
-		this.field = field;
-	}
-
-	public String
-	getName()
-	{
-		return( name );
-	}
-	
-	public int
-	getField()
-	{
-		return( field );
-	}
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl.web;
+
+public class FieldMapping {
+	
+	private String name;
+	private int field;
+	
+	public FieldMapping(String name,int field) {
+		this.name = name;
+		this.field = field;
+	}
+
+	public String
+	getName()
+	{
+		return( name );
+	}
+	
+	public int
+	getField()
+	{
+		return( field );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/WebEngine.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/WebEngine.java
index f59f111..20f6a14 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/WebEngine.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/WebEngine.java
@@ -1,1408 +1,1547 @@
-/*
- * Created on May 6, 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.core.metasearch.impl.web;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.Proxy;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.nio.charset.Charset;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.TorrentUtils;
-import org.gudy.azureus2.core3.util.UrlUtils;
-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.metasearch.SearchException;
-import com.aelitis.azureus.core.metasearch.SearchLoginException;
-import com.aelitis.azureus.core.metasearch.SearchParameter;
-import com.aelitis.azureus.core.metasearch.impl.*;
-import com.aelitis.azureus.core.proxy.AEProxyFactory;
-import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
-import com.aelitis.azureus.core.util.GeneralUtils;
-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.util.ImportExportUtils;
-import com.aelitis.azureus.util.UrlFilter;
-
-public abstract class 
-WebEngine 
-	extends EngineImpl 
-{
-	public static final String	AM_TRANSPARENT 	= "transparent";
-	public static final String	AM_PROXY		= "proxy";
-	
-	private static final boolean NEEDS_AUTH_DEFAULT				= false;
-	private static final boolean AUTOMATIC_DATE_PARSER_DEFAULT 	= true;
-	
-	static private final Pattern baseTagPattern = Pattern.compile("(?i)<base.*?href=\"([^\"]+)\".*?>");
-	static private final Pattern rootURLPattern = Pattern.compile("(https?://[^/]+)");
-	static private final Pattern baseURLPattern = Pattern.compile("(https?://.*/)");
-		
-	
-	private String 			searchURLFormat;
-	private String 			timeZone;
-	private boolean			automaticDateParser;
-	private String 			userDateFormat;
-	private String			downloadLinkCSS;
-	private FieldMapping[]	mappings;
-
-	
-	private String rootPage;
-	private String basePage;
-
-	private DateParser dateParser;
-	
-	private boolean needsAuth;
-	private String	authMethod;
-	private String loginPageUrl;
-	private String iconUrl;
-	private String[] requiredCookies;
-	
-	private String local_cookies;
-	
-
-		// manual test constructor
-	
-	public 
-	WebEngine(
-		MetaSearchImpl	meta_search,
-		int 			type, 
-		long 			id, 
-		long 			last_updated, 
-		float			rank_bias,
-		String 			name,
-		String 			searchURLFormat,
-		String 			timeZone,
-		boolean 		automaticDateParser,
-		String 			userDateFormat, 
-		FieldMapping[] 	mappings,
-		boolean			needs_auth,
-		String			auth_method,
-		String			login_url,
-		String[]		required_cookies )
-	{	
-		super( meta_search, type, id, last_updated, rank_bias, name );
-
-		this.searchURLFormat 		= searchURLFormat;
-		this.timeZone 				= timeZone;
-		this.automaticDateParser 	= automaticDateParser;
-		this.userDateFormat 		= userDateFormat;
-		this.mappings				= mappings;
-		this.needsAuth				= needs_auth;
-		this.authMethod				= auth_method;
-		this.loginPageUrl			= login_url;
-		this.requiredCookies		= required_cookies;
-		
-		init();
-	}
-	
-		// bencoded constructor
-	
-	protected 
-	WebEngine(
-		MetaSearchImpl	meta_search,
-		Map				map )
-	
-		throws IOException
-	{
-		super( meta_search, map );
-		
-		searchURLFormat 	= ImportExportUtils.importString( map, "web.search_url_format" );
-		timeZone			= ImportExportUtils.importString( map, "web.time_zone" );
-		userDateFormat		= ImportExportUtils.importString( map, "web.date_format" );
-		downloadLinkCSS		= ImportExportUtils.importString( map, "web.dl_link_css" );
-		
-		needsAuth			= ImportExportUtils.importBoolean(map, "web.needs_auth", NEEDS_AUTH_DEFAULT );
-		authMethod			= ImportExportUtils.importString( map, "web.auth_method", WebEngine.AM_TRANSPARENT );
-		loginPageUrl 		= ImportExportUtils.importString( map, "web.login_page" );
-		requiredCookies 	= ImportExportUtils.importStringArray( map, "web.required_cookies" );
-
-		automaticDateParser	= ImportExportUtils.importBoolean( map, "web.auto_date", AUTOMATIC_DATE_PARSER_DEFAULT );
-		iconUrl 		= ImportExportUtils.importString( map, "web.icon_url" );
-
-		List	maps = (List)map.get( "web.maps" );
-		
-		mappings = new FieldMapping[maps.size()];
-		
-		for (int i=0;i<mappings.length;i++){
-			
-			Map	m = (Map)maps.get(i);
-			
-			mappings[i] = 
-				new FieldMapping(
-						ImportExportUtils.importString( m, "name" ),
-					((Long)m.get( "field")).intValue());
-		}
-		
-		init();
-	}
-	
-	protected void
-	exportToBencodedMap(
-		Map		map,
-		boolean	generic )
-	
-		throws IOException
-	{
-		super.exportToBencodedMap( map, generic );
-		
-		if ( generic ){
-			
-			if ( searchURLFormat != null ){
-				ImportExportUtils.exportString( map, "web.search_url_format", 		searchURLFormat );
-			}
-			if ( timeZone != null ){
-				ImportExportUtils.exportString( map, "web.time_zone", 				timeZone );
-			}
-			if ( userDateFormat != null ){
-				ImportExportUtils.exportString( map, "web.date_format", 			userDateFormat );
-			}
-			if ( downloadLinkCSS != null ){
-				ImportExportUtils.exportString( map, "web.dl_link_css",				downloadLinkCSS );
-			}
-			
-			if ( needsAuth != NEEDS_AUTH_DEFAULT ){
-				ImportExportUtils.exportBoolean( map, "web.needs_auth",				needsAuth );
-			}
-			if ( authMethod != null && !authMethod.equals( WebEngine.AM_TRANSPARENT )){
-				ImportExportUtils.exportString( map, "web.auth_method",				authMethod );
-			}
-			if ( loginPageUrl != null ){
-				ImportExportUtils.exportString( map, "web.login_page",				loginPageUrl );
-			}
-			if ( iconUrl != null ) {
-				ImportExportUtils.exportString(map, "web.icon_url", iconUrl);
-			}
-			if ( requiredCookies != null && requiredCookies.length > 0 ){
-				ImportExportUtils.exportStringArray( map, "web.required_cookies",	requiredCookies );
-			}
-			if (automaticDateParser != AUTOMATIC_DATE_PARSER_DEFAULT ){
-				ImportExportUtils.exportBoolean( map, "web.auto_date", automaticDateParser );
-			}
-
-		}else{
-			ImportExportUtils.exportString( map, "web.search_url_format", 		searchURLFormat );
-			ImportExportUtils.exportString( map, "web.time_zone", 				timeZone );		
-			ImportExportUtils.exportString( map, "web.date_format", 			userDateFormat );
-			ImportExportUtils.exportString( map, "web.dl_link_css",				downloadLinkCSS );
-			
-			ImportExportUtils.exportBoolean( map, "web.needs_auth",				needsAuth );
-			ImportExportUtils.exportString( map, "web.auth_method",				authMethod );
-			ImportExportUtils.exportString( map, "web.login_page",				loginPageUrl );
-			ImportExportUtils.exportString( map, "web.icon_url", iconUrl);
-			ImportExportUtils.exportStringArray( map, "web.required_cookies",	requiredCookies );
-	
-			ImportExportUtils.exportBoolean( map, "web.auto_date", automaticDateParser );
-		}
-		
-		List	maps = new ArrayList();
-		
-		map.put( "web.maps", maps );
-		
-		for (int i=0;i<mappings.length;i++){
-			
-			FieldMapping fm = mappings[i];
-			
-			Map m = new HashMap();
-			
-			ImportExportUtils.exportString( m, "name", fm.getName());
-			m.put( "field", new Long( fm.getField()));
-			
-			maps.add( m );
-		}
-	}
-	
-		// json encoded constructor
-	
-	protected 
-	WebEngine(
-		MetaSearchImpl	meta_search,
-		int				type,
-		long			id,
-		long			last_updated,
-		float			rank_bias,
-		String			name,
-		JSONObject		map )
-	
-		throws IOException
-	{
-		super( meta_search, type, id, last_updated, rank_bias, name, map );
-		
-		searchURLFormat 	= ImportExportUtils.importURL( map, "searchURL" );
-		timeZone			= ImportExportUtils.importString( map, "timezone" );
-		userDateFormat		= ImportExportUtils.importString( map, "time_format" );
-		downloadLinkCSS		= ImportExportUtils.importURL( map, "download_link" );
-
-		
-		needsAuth			= ImportExportUtils.importBoolean( map, "needs_auth", false );
-		authMethod			= ImportExportUtils.importString( map, "auth_method", WebEngine.AM_TRANSPARENT );
-		loginPageUrl 		= ImportExportUtils.importURL( map, "login_page" );
-		iconUrl 		= ImportExportUtils.importURL( map, "icon_url" );
-		
-		requiredCookies 	= ImportExportUtils.importStringArray( map, "required_cookies" );
-		
-		automaticDateParser	= userDateFormat == null || userDateFormat.trim().length() == 0;
-
-		List	maps = (List)map.get( "column_map" );
-		
-		List	conv_maps = new ArrayList();
-		
-		for (int i=0;i<maps.size();i++){
-			
-			Map	m = (Map)maps.get(i);
-				
-				// wha? getting some nulls here :( 
-				// from JSON like "column_map\":[null,null,{\"group_nb\":\"3
-			
-			if ( m == null ){
-				
-				continue;
-			}
-			
-				// backwards compact from when there was a mapping entry
-			
-			Map test = (Map)m.get( "mapping" );
-			
-			if ( test != null ){
-				
-				m = test;
-			}
-			
-			String	vuze_field 	= ImportExportUtils.importString( m, "vuze_field" ).toUpperCase();
-			
-			String	field_name	= ImportExportUtils.importString( m, "group_nb" );	// regexp case
-			
-			if ( field_name == null ){
-				
-				field_name = ImportExportUtils.importString( m, "field_name" );	// json case
-			}
-			
-			if ( vuze_field == null || field_name == null ){
-				
-				log( "Missing field mapping name/value in '" + m + "'" );
-
-			}
-			int	field_id = vuzeFieldToID( vuze_field );
-			
-			if ( field_id == -1 ){
-				
-				log( "Unrecognised field mapping '" + vuze_field + "'" );
-				
-				continue;
-			}
-			
-			conv_maps.add( new FieldMapping( field_name, field_id ));
-		}
-		
-		mappings = (FieldMapping[])conv_maps.toArray( new FieldMapping[conv_maps.size()]);
-		
-		init();
-	}
-	
-	protected void
-	exportToJSONObject(
-		JSONObject		res )
-	
-		throws IOException
-	{		
-		super.exportToJSONObject( res );
-		
-		ImportExportUtils.exportJSONURL( res, "searchURL", searchURLFormat );
-		
-		ImportExportUtils.exportJSONString( res, "timezone", 	timeZone );	
-		
-		if ( downloadLinkCSS != null ){
-			
-			ImportExportUtils.exportJSONURL( res, "download_link", downloadLinkCSS );
-		}
-		
-		ImportExportUtils.exportJSONBoolean( res, "needs_auth",				needsAuth );
-		ImportExportUtils.exportJSONString( res, "auth_method",				authMethod );
-		ImportExportUtils.exportJSONURL( res, "login_page",					loginPageUrl );
-		ImportExportUtils.exportJSONURL( res, "icon_url",					iconUrl );
-		ImportExportUtils.exportJSONStringArray( res, "required_cookies",	requiredCookies );
- 
-		if ( !automaticDateParser ){
-			
-			ImportExportUtils.exportJSONString( res, "time_format",	userDateFormat );
-		}
-		
-		JSONArray	maps = new JSONArray();
-		
-		res.put( "column_map", maps );
-
-		for (int i=0;i<mappings.length;i++){
-			
-			FieldMapping fm = mappings[i];
-			
-			int	field_id = fm.getField();
-			
-			String	field_value = vuzeIDToField( field_id );
-			
-			if ( field_value == null ){
-				
-				log( "JSON export: unknown field id " + field_id );
-				
-			}else{
-							
-				JSONObject entry = new JSONObject();
-
-				maps.add( entry );
-					
-				entry.put( "vuze_field", field_value );
-				
-				if ( getType() == ENGINE_TYPE_JSON ){
-					
-					entry.put( "field_name", fm.getName());
-					
-				}else{
-					
-					entry.put( "group_nb", fm.getName());
-				}
-			}
-		}	
-	}
-	
-	protected void
-	init()
-	{
-		try {
-			Matcher m = rootURLPattern.matcher(searchURLFormat);
-			if(m.find()) {
-				this.rootPage = m.group(1);
-			}
-		} catch(Exception e) {
-			//Didn't find the root url within the URL
-			this.rootPage = null;
-		}
-		
-		try {
-			Matcher m = baseURLPattern.matcher(searchURLFormat);
-			if(m.find()) {
-				this.basePage = m.group(1);
-			}
-		} catch(Exception e) {
-			//Didn't find the root url within the URL
-			this.basePage = null;
-		}
-		
-		this.dateParser = new DateParserRegex(timeZone,automaticDateParser,userDateFormat);
-		
-		local_cookies = getLocalString( LD_COOKIES );
-		
-			// normalise to permit == to be safely used when testing method
-		
-		authMethod = authMethod.intern();
-		
-			// see if we have explicit cookie information in the URL:
-		
-		int	cook_pos = searchURLFormat.indexOf( ":COOKIE:" );
-					
-		if ( cook_pos != -1 ){
-			
-			String explicit_cookie = searchURLFormat.substring( cook_pos + 8 );
-			
-			setNeedsAuth( true );
-			
-			setCookies( explicit_cookie );
-			
-			setRequiredCookies( CookieParser.getCookiesNames( explicit_cookie ));
-			
-			searchURLFormat = searchURLFormat.substring( 0, cook_pos );
-			
-			setPublic( false );
-			
-			String	name = getName();
-			
-			int	n_pos = name.indexOf( ":COOKIE:" );
-			
-			if ( n_pos != -1 ){
-				
-				setName( name.substring( 0, n_pos ));
-			}
-		}
-	}
-	
-	public String 
-	getNameEx() 
-	{
-		String url = getRootPage();
-		
-		if ( url == null || url.length() == 0 ){
-			
-			url = searchURLFormat;
-		}
-		
-		String name = getName();
-		
-		if ( name.indexOf( url ) == -1 ){
-			
-			return( name + " (" + url + ")");
-			
-		}else{
-			
-			return( name );
-		}
-		     
-	}
-	
-	public String 
-	getReferer() 
-	{
-		return( getRootPage());
-	}
-	
-	public boolean
-	supportsContext(
-		String	context_key )
-	{
-		try{
-			URL	url = new URL( searchURLFormat );
-			
-			String	host = url.getHost();
-			
-			if ( org.gudy.azureus2.core3.util.Constants.isAzureusDomain( host )){
-				
-				return( true );
-			}
-			
-			if ( UrlFilter.getInstance().isWhitelisted( searchURLFormat )){
-				
-				return( true );
-			}
-			
-				// allow local addresses for testing purposes
-			
-			InetAddress iad = InetAddress.getByName(host);
-			
-			if ( 	iad.isLoopbackAddress() ||
-					iad.isLinkLocalAddress() ||
-					iad.isSiteLocalAddress()){
-				
-				return( true );
-			}
-		}catch( Throwable e ){
-		}
-		
-		return( false );
-	}
-	
-	public boolean 
-	isShareable() 
-	{
-		try{
-			return( !UrlUtils.containsPasskey( new URL( searchURLFormat )));
-			
-		}catch( Throwable e ){
-			
-			return( true );
-		}
-	}
-	
-	protected pageDetails 
-	getWebPageContent(
-		SearchParameter[] 	searchParameters,
-		Map<String,String>	searchContext,
-		String				headers,
-		boolean				only_if_modified )
-	
-		throws SearchException
-	{
-		String searchURL = searchURLFormat;
-
-		try{
-			pageDetails	details = getWebPageContentSupport( null, null, searchURL, searchParameters, searchContext, headers, only_if_modified );
-		
-			return( details );
-			
-		}catch( SearchException e ){
-			
-			try{
-				URL 			original_url	= new URL( searchURL );
-				
-				PluginProxy 	plugin_proxy	= AEProxyFactory.getPluginProxy( "getting search results ", original_url );
-				
-				if ( plugin_proxy == null ){
-					
-					throw( e );
-					
-				}else{
-					
-					URL 	url		= plugin_proxy.getURL();
-					Proxy 	proxy	= plugin_proxy.getProxy();
-
-					boolean	ok = false;
-					
-					try{
-						String proxy_host = original_url.getHost() + (original_url.getPort()==-1?"":(":" + original_url.getPort()));
-						
-						pageDetails	details = getWebPageContentSupport( proxy, proxy_host, url.toExternalForm(), searchParameters, searchContext, headers, only_if_modified );
-					
-						ok = true;
-						
-						return( details );
-						
-					}finally{
-						
-						plugin_proxy.setOK( ok );
-					}
-				}
-			}catch( Throwable f ){
-				
-				throw( e );
-			}
-		}
-	}
-	
-	private pageDetails 
-	getWebPageContentSupport(
-		Proxy				proxy,
-		String				proxy_host,
-		String				searchURL,
-		SearchParameter[] 	searchParameters,
-		Map<String,String>	searchContext,
-		String				headers,
-		boolean				only_if_modified )
-	
-		throws SearchException
-	{
-		
-		try {
-			TorrentUtils.setTLSDescription( "Search: " + getName());
-			
-			if ( requiresLogin()){
-				
-				throw new SearchLoginException("login required");
-			}
-						
-			boolean vuze_file = searchURL.toLowerCase().startsWith( "vuze:" );
-			
-			if ( !vuze_file ){
-				
-				String[]	from_strs 	= new String[ searchParameters.length ];
-				String[]	to_strs 	= new String[ searchParameters.length ];
-				
-				for( int i = 0 ; i < searchParameters.length ; i++ ){
-					
-					SearchParameter parameter = searchParameters[i];
-					
-					from_strs[i]	= "%" + parameter.getMatchPattern();
-					to_strs[i]		= URLEncoder.encode(parameter.getValue(),"UTF-8");
-				}
-				
-				searchURL = GeneralUtils.replaceAll( searchURL, from_strs, to_strs );
-					
-				Iterator<Map.Entry<String, String>>	it = searchContext.entrySet().iterator();
-				
-				while( it.hasNext()){
-					
-					Map.Entry<String, String>	entry = it.next();
-					
-					String	key 	= entry.getKey();
-						
-					if ( supportsContext( key )){
-						
-						if ( searchURL.indexOf('?') == -1 ){
-							
-							searchURL += "?";
-							
-						}else{
-							
-							searchURL += "&";
-						}
-						
-						String	value 	= entry.getValue();
-	
-						searchURL += key + "=" + URLEncoder.encode( value, "UTF-8" );
-					}
-				}
-			}
-			
-			//System.out.println(searchURL);
-			
-			
-				// hack to support POST by encoding into URL
-			
-				// http://xxxx/index.php?main=search&azmethod=post_basic:SearchString1=%s&SearchString=&search=Search
-				
-			ResourceDownloaderFactory rdf = StaticUtilities.getResourceDownloaderFactory();
-
-			URL					initial_url;
-			ResourceDownloader 	initial_url_rd;
-					
-			
-			int	post_pos = searchURL.indexOf( "azmethod=" );
-			
-			if ( post_pos > 0 ){
-				
-				String post_params = searchURL.substring( post_pos+9 );
-				
-				searchURL = searchURL.substring( 0, post_pos-1 );
-				
-				debugLog( "search_url: " + searchURL + ", post=" + post_params );
-
-				initial_url = new URL(searchURL);
-
-				int	sep = post_params.indexOf( ':' );
-				
-				String	type = post_params.substring( 0, sep );
-				
-				if ( !type.equals( "post_basic" )){
-					
-					throw( new SearchException( "Only basic type supported" ));
-				}
-				
-				post_params = post_params.substring( sep+1 );
-				
-					// already URL encoded
-				
-				if ( proxy == null ){
-				
-					initial_url_rd = rdf.create( initial_url, post_params );
-					
-				}else{
-					
-					initial_url_rd = rdf.create( initial_url, post_params, proxy );
-				}
-				
-				initial_url_rd.setProperty( "URL_Content-Type", "application/x-www-form-urlencoded" );
-				
-			}else{
-			
-				debugLog( "search_url: " + searchURL );
-			
-				initial_url = new URL(searchURL);
-			
-				if ( proxy == null ){
-				
-					initial_url_rd = rdf.create( initial_url );
-					
-				}else{
-					
-					initial_url_rd = rdf.create( initial_url, proxy );
-				}
-			}
-			
-			if ( proxy_host != null ){
-				
-				initial_url_rd.setProperty( "URL_HOST", proxy_host );
-			}
-			
-			setHeaders( initial_url_rd, headers );
-				
-			if ( needsAuth && local_cookies != null ){
-				
-				initial_url_rd.setProperty( "URL_Cookie", local_cookies );				
-			}
-				
-			if ( only_if_modified ){
-				
-				String last_modified 	= getLocalString( LD_LAST_MODIFIED );
-				String etag				= getLocalString( LD_ETAG );
-
-				if ( last_modified != null ){
-					
-					initial_url_rd.setProperty( "URL_If-Modified-Since", last_modified );
-				}
-				
-				if ( etag != null ){
-					
-					initial_url_rd.setProperty( "URL_If-None-Match", etag );
-				}
-			}
-			
-			InputStream	is = null;
-			
-			try{
-				String content_charset = "UTF-8";
-	
-				ResourceDownloader mr_rd = null;
-				
-				if ( initial_url.getProtocol().equalsIgnoreCase( "file" )){
-					
-						// handle file://c:/ - map to file:/c:/
-					
-					String	str = initial_url.toExternalForm();
-					
-					if ( initial_url.getAuthority() != null ){
-					
-						str = str.replaceFirst( "://", ":/" );
-					}
-									
-					int	pos = str.indexOf( '?' );
-					
-					if ( pos != -1 ){
-						
-						str = str.substring( 0, pos );
-					}
-					
-					is = new FileInputStream( new File( new URL( str ).toURI()));
-					
-				}else{
-					
-					if ( proxy == null ){
-						
-						initial_url_rd.setProperty( "URL_Connect_Timeout", 10*1000 );
-						
-						initial_url_rd.setProperty( "URL_Read_Timeout", 10*1000 ); 
-					}
-					
-					mr_rd = rdf.getMetaRefreshDownloader( initial_url_rd );
-	
-					try{
-					
-						is = mr_rd.download();
-						
-					}catch( ResourceDownloaderException e ){
-					
-						Long	response = (Long)mr_rd.getProperty( "URL_HTTP_Response" );
-						
-						if ( response != null && response.longValue() == 304 ){
-							
-								// not modified
-							
-							return( new pageDetails( initial_url, initial_url, "" ));
-							
-						}else{
-							
-							throw( e );
-						}
-					}
-	
-				
-					if ( needsAuth ){
-						
-						List	cookies_list = (List)mr_rd.getProperty( "URL_Set-Cookie" );
-						
-						List	cookies_set = new ArrayList();
-						
-						if ( cookies_list != null ){
-							
-							for (int i=0;i<cookies_list.size();i++){
-								
-								String[] cookies = ((String)cookies_list.get(i)).split(";");
-								
-								for (int j=0;j<cookies.length;j++){
-									
-									String	cookie = cookies[j].trim();
-									
-									if ( cookie.indexOf('=') != -1 ){
-										
-										cookies_set.add( cookie );
-									}
-								}
-							}
-						}
-						
-							// well, not much we can do with the cookies anyway as in general the ones
-							// set are the ones missing/expired, not the existing ones. That is, we can't
-							// deduce anything from the fact that a required cookie is not 'set' here
-							// the most we could do is catch a server that explicitly deleted invalid
-							// cookies by expiring it, but I doubt this is a common practice.
-						
-							// Also note the complexity of cookie syntax
-							// Set-Cookie: old standard using expires=, new using MaxAge
-							// Set-Cookie2:
-							// Maybe use http://jcookie.sourceforge.net/ if needed
-					}
-					
-					if ( only_if_modified ){
-						
-						String last_modified 	= extractProperty( mr_rd.getProperty( "URL_Last-Modified" ));
-						String etag				= extractProperty( mr_rd.getProperty( "URL_ETag" ));
-						
-						if ( last_modified != null ){
-							
-							setLocalString( LD_LAST_MODIFIED, last_modified );
-						}
-						
-						if ( etag != null ){
-							
-							setLocalString( LD_ETAG, etag );
-						}
-					}
-					
-					List cts = (List)mr_rd.getProperty( "URL_Content-Type" );
-												
-					if ( cts != null && cts.size() > 0 ){
-						
-						String	content_type = (String)cts.get(0);
-						
-						int	pos = content_type.toLowerCase().indexOf( "charset" );
-						
-						if ( pos != -1 ){
-							
-							content_type = content_type.substring( pos+1 );
-							
-							pos = content_type.indexOf('=');
-							
-							if ( pos != -1 ){
-								
-								content_type = content_type.substring( pos+1 ).trim();
-								
-								pos = content_type.indexOf(';');
-								
-								if ( pos != -1 ){
-									
-									content_type = content_type.substring(0,pos).trim();
-								}
-								
-								if ( content_type.startsWith("\"" )){
-									
-									content_type = content_type.substring(1).trim();
-								}
-								
-								if ( content_type.endsWith("\"" )){
-									
-									content_type = content_type.substring(0,content_type.length()-1).trim();
-								}
-								
-								try{
-									if ( Charset.isSupported( content_type )){
-										
-										debugLog( "charset: " + content_type );
-										
-										content_charset = content_type;
-									}
-								}catch( Throwable e ){
-									
-									try{
-											// handle lowercase 'utf-8' for example
-										
-										content_type = content_type.toUpperCase();
-										
-										if ( Charset.isSupported( content_type )){
-											
-											debugLog( "charset: " + content_type );
-											
-											content_charset = content_type;
-										}
-									}catch( Throwable f ){
-										
-										log( "Content type '" + content_type + "' not supported", f );
-									}
-								}
-							}
-						}
-					}
-				}
-				
-				ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
-										
-				byte[] buffer = new byte[8192];			
-	
-				while( true ){
-					
-					int	len = is.read( buffer );
-					
-					if ( len <= 0 ){
-						
-						break;
-					}
-					
-					baos.write( buffer, 0, len );
-				}
-				
-				byte[] data = baos.toByteArray();
-				
-				if ( vuze_file ){
-					
-					try{
-						VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
-						
-						VuzeFile vf = vfh.loadVuzeFile( data );
-						
-						vfh.handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_NONE );
-						
-					}catch( Throwable e ){
-						
-						Debug.out( e );
-					}
-					
-					return( new pageDetails( initial_url, initial_url, null ));
-				}
-				
-				String 	page = null;
-				
-				String	content = new String( data, 0, Math.min( data.length, 2048 ), content_charset );
-				
-				String	lc_content = content.toLowerCase();
-				
-				{
-						// first look for xml charset
-				
-						// e.g. <?xml version="1.0" encoding="windows-1251" ?>
-	
-					int	pos1 = lc_content.indexOf( "<?xml" );
-					
-					if ( pos1 != -1 ){
-						
-						int pos2 = lc_content.indexOf( "?>" );
-						
-						if ( pos2 != -1 ){
-												
-							int pos3 = lc_content.indexOf( "encoding", pos1 );
-							
-							if ( pos3 != -1 ){
-								
-								pos3 = lc_content.indexOf( "\"", pos3 );
-							}
-							
-							if ( pos3 > pos1 && pos3 < pos2 ){
-															
-								pos3++;
-								
-								int pos4 = lc_content.indexOf( "\"", pos3 );
-								
-								if ( pos4 > pos3 && pos4 < pos2 ){
-									
-									String	encoding = content.substring( pos3, pos4 ).trim();
-									
-									try{
-										if ( Charset.isSupported( encoding )){
-											
-											debugLog( "charset from xml tag: " + encoding );
-											
-											content_charset = encoding;
-											
-												// some feeds have crap at the start which makes pos2 mismatch for the above '?' - adjust if necessary
-											
-											int data_start = pos2;
-											
-											int	max_skip	= 64;
-											
-											while( data[data_start] != '?' && max_skip-- > 0 ){
-												
-												data_start++;
-											}
-											
-											page = content.substring( 0, pos3 ) + "utf-8" + content.substring( pos4, pos2 ) + new String( data, data_start, data.length - data_start, content_charset );							
-										}
-									}catch( Throwable e ){
-										
-										log( "Content type '" + encoding + "' not supported", e );
-									}
-								}
-							}
-						}
-					}
-				}
-				
-				if ( page == null ){
-						
-						// next look for http-equiv charset
-					
-						// e.g. <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
-	
-					int	pos = 0;
-					
-					while( true ){
-					
-						int	pos1 = lc_content.indexOf( "http-equiv", pos );
-					
-						if ( pos1 != -1 ){
-						
-							int	pos2 = lc_content.indexOf( ">", pos1 );
-							
-							if ( pos2 != -1 ){
-								
-								int	pos3 = lc_content.indexOf( "charset", pos1 );
-								
-								if ( pos3 != -1 && pos3 < pos2 ){
-								
-									pos3 = lc_content.indexOf( "=", pos3 );
-									
-									if ( pos3 != -1 ){
-										
-										pos3++;
-										
-										int pos4 = lc_content.indexOf( "\"", pos3 );
-										
-										if ( pos4 != -1 ){
-											
-											int pos5 = lc_content.indexOf( ";", pos3 );
-										
-											if ( pos5 != -1 && pos5 < pos4 ){
-												
-												pos4 = pos5;
-											}
-											
-											String encoding = content.substring( pos3, pos4 ).trim();
-											
-											try{
-												if ( Charset.isSupported( encoding )){
-													
-													debugLog( "charset from http-equiv : " + encoding );
-													
-													content_charset = encoding;
-													
-														// some feeds have crap at the start which makes pos2 mismatch for the above '?' - adjust if necessary
-													
-													int data_start = pos2;
-													
-													int	max_skip	= 64;
-													
-													while( data[data_start] != '?' && max_skip-- > 0 ){
-														
-														data_start++;
-													}
-													
-													page = content.substring( 0, pos3 ) + "utf-8" + content.substring( pos4, pos2 ) + new String( data, data_start, data.length - data_start, content_charset );							
-												}
-											}catch( Throwable e ){
-												
-												log( "Content type '" + encoding + "' not supported", e );
-											}
-											
-											break;
-										}
-									}
-								}
-								
-								pos = pos2;
-								
-							}else{
-								
-								break;
-							}
-						}else{
-							
-							break;
-						}
-					}
-				}
-				
-				if ( page == null ){
-					
-					page = new String( data, content_charset );
-				}
-				
-				debugLog( "page:" );
-				debugLog( page );
-	
-				// List 	cookie = (List)url_rd.getProperty( "URL_Set-Cookie" );
-				
-				try {
-					Matcher m = baseTagPattern.matcher(page);
-					if(m.find()) {
-						basePage = m.group(1);
-						
-						debugLog( "base_page: " + basePage );
-					}
-				} catch(Exception e) {
-					//No BASE tag in the page
-				}
-				
-				URL	final_url = initial_url;
-				
-				if ( mr_rd != null ){
-					
-					URL	x = (URL)mr_rd.getProperty( "URL_URL" );
-		
-					if ( x != null ){
-						
-						final_url = x;
-					}
-				}
-				
-				return( new pageDetails( initial_url, final_url, page ));
-				
-			}finally{
-				
-				if ( is != null ){
-					
-					is.close();
-				}
-			}
-				
-		}catch( SearchException e ){
-			
-			throw( e );
-			
-		}catch( Throwable e) {
-			
-			// e.printStackTrace();
-			
-			debugLog( "Failed to load page: " + Debug.getNestedExceptionMessageAndStack(e));
-			
-			throw( new SearchException( "Failed to load page", e ));
-			
-		}finally{
-			
-			TorrentUtils.setTLSDescription( null );
-		}
-	}
-
-	protected String
-	extractProperty(
-		Object	o )
-	{
-		if ( o instanceof String ){
-			
-			return((String)o);
-			
-		}else if ( o instanceof List ){
-			
-			List	l = (List)o;
-			
-			if ( l.size() > 0 ){
-				
-				if ( l.size() > 1 ){
-					
-					Debug.out( "Property has multiple values!" );
-				}
-				
-				Object x = l.get(0);
-				
-				if ( x instanceof String ){
-					
-					return((String)x);
-					
-				}else{
-					
-					Debug.out( "Property value isn't a String:" + x );
-				}
-			}
-		}
-		
-		return( null );
-	}
-	
-	protected void
-	setHeaders(
-		ResourceDownloader		rd,
-		String					encoded_headers )
-	{
-		UrlUtils.setBrowserHeaders( rd, encoded_headers, rootPage );
-	}
-	
-	public String getIcon() {
-		if (iconUrl != null) {
-			return iconUrl;
-		}
-		if(rootPage != null) {
-			return rootPage + "/favicon.ico";
-		}
-		return null;
-	}
-	
-	protected FieldMapping[]
-	getMappings()
-	{
-		return( mappings );
-	}
-	
-	public boolean
-	supportsField(
-		int		field_id )
-	{
-		for (int i=0;i<mappings.length;i++){
-			
-			if ( mappings[i].getField() == field_id ){
-				
-				return( true );
-			}
-		}
-		
-		return( false );
-	}
-	
-	protected String
-	getRootPage()
-	{
-		return( rootPage );
-	}
-	
-	protected String
-	getBasePage()
-	{
-		return( basePage );
-	}
-	
-	protected DateParser
-	getDateParser()
-	{
-		return( dateParser );
-	}
-	
-	public String 
-	getDownloadLinkCSS()
-	{
-		if ( downloadLinkCSS == null ){
-			
-			return( "" );
-		}
-		
-		return( downloadLinkCSS );
-	}
-	
-	public boolean requiresLogin() {
-		return needsAuth && ! CookieParser.cookiesContain(requiredCookies, local_cookies);
-	}
-	
-	public void setCookies(String cookies) {
-		this.local_cookies = cookies;
-		
-		setLocalString( LD_COOKIES, cookies );
-	}
-
-	public String
-	getSearchUrl(
-		boolean		raw )
-	{
-		if ( raw ){
-			
-			return( searchURLFormat );
-		}else{
-			
-			return( getSearchUrl());
-		}
-	}
-	
-	public String
-	getSearchUrl()
-	{
-		return( searchURLFormat.replaceAll("%s", ""));
-	}
-	
-	public void
-	setSearchUrl(
-		String		str )
-	{
-		searchURLFormat = str;
-		
-		init();
-	}
-	
-	public String getLoginPageUrl() {
-		//Let's try with no login page url
-		//return loginPageUrl;
-		return searchURLFormat.replaceAll("%s", "");
-	}
-
-	public void setLoginPageUrl(String loginPageUrl) {
-		this.loginPageUrl = loginPageUrl;
-	}
-
-	public String[] getRequiredCookies() {
-		return requiredCookies;
-	}
-
-	public void setRequiredCookies(String[] requiredCookies) {
-		this.requiredCookies = requiredCookies;
-	}
-
-	public boolean isNeedsAuth() {
-		return needsAuth;
-	}
-
-	public boolean
-	isAuthenticated()
-	{
-		return( isNeedsAuth());
-	}
-	
-	protected void
-	setNeedsAuth(
-		boolean	b )
-	{
-		needsAuth = b;
-	}
-	
-	public String
-	getAuthMethod()
-	{
-		return( authMethod );
-	}
-	
-	public String getCookies() {
-		return local_cookies;
-	}
-	
-	public String
-	getString()
-	{
-		return( getString( false ));
-	}
-	
-	public String
-	getString(
-		boolean		full )
-	{
-		return( 	super.getString() + 
-						(full?(", url=" + searchURLFormat ):"") +
-						", auth=" + isNeedsAuth() +
-						(isNeedsAuth()?" [cookies=" + local_cookies + "]":"" ));
-	}
-	
-	public static class
-	pageDetails
-	{
-		private URL			initial_url;
-		private URL			final_url;
-		private String		content;
-		
-		protected
-		pageDetails(
-			URL		_initial_url,
-			URL		_final_url,
-			String	_content )
-		{
-			initial_url		= _initial_url;
-			final_url		= _final_url;
-			content			= _content;
-		}
-
-		public URL
-		getInitialURL()
-		{
-			return( initial_url );
-		}
-
-		public URL
-		getFinalURL()
-		{
-			return( final_url );
-		}
-		
-		public String
-		getContent()
-		{
-			return( content );
-		}
-	}
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl.web;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.Proxy;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.gudy.azureus2.core3.util.AENetworkClassifier;
+import org.gudy.azureus2.core3.util.AddressUtils;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.TorrentUtils;
+import org.gudy.azureus2.core3.util.UrlUtils;
+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.metasearch.SearchException;
+import com.aelitis.azureus.core.metasearch.SearchLoginException;
+import com.aelitis.azureus.core.metasearch.SearchParameter;
+import com.aelitis.azureus.core.metasearch.impl.*;
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
+import com.aelitis.azureus.core.util.GeneralUtils;
+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.util.ImportExportUtils;
+import com.aelitis.azureus.util.UrlFilter;
+
+public abstract class 
+WebEngine 
+	extends EngineImpl 
+{
+	public static final String	AM_TRANSPARENT 	= "transparent";
+	public static final String	AM_PROXY		= "proxy";
+	
+	private static final boolean NEEDS_AUTH_DEFAULT				= false;
+	private static final boolean AUTOMATIC_DATE_PARSER_DEFAULT 	= true;
+	
+	static private final Pattern baseTagPattern = Pattern.compile("(?i)<base.*?href=\"([^\"]+)\".*?>");
+	static private final Pattern rootURLPattern = Pattern.compile("((?:tor:)?https?://[^/]+)");
+	static private final Pattern baseURLPattern = Pattern.compile("((?:tor:)?https?://.*/)");
+		
+	
+	private String 			searchURLFormat;
+	private String 			timeZone;
+	private boolean			automaticDateParser;
+	private String 			userDateFormat;
+	private String			downloadLinkCSS;
+	private FieldMapping[]	mappings;
+
+	
+	private String rootPage;
+	private String basePage;
+
+	private DateParser dateParser;
+	
+	private boolean needsAuth;
+	private String	authMethod;
+	private String loginPageUrl;
+	private String iconUrl;
+	private String[] requiredCookies;
+	
+	private String local_cookies;
+	
+
+		// manual test constructor
+	
+	public 
+	WebEngine(
+		MetaSearchImpl	meta_search,
+		int 			type, 
+		long 			id, 
+		long 			last_updated, 
+		float			rank_bias,
+		String 			name,
+		String 			searchURLFormat,
+		String 			timeZone,
+		boolean 		automaticDateParser,
+		String 			userDateFormat, 
+		FieldMapping[] 	mappings,
+		boolean			needs_auth,
+		String			auth_method,
+		String			login_url,
+		String[]		required_cookies )
+	{	
+		super( meta_search, type, id, last_updated, rank_bias, name );
+
+		this.searchURLFormat 		= searchURLFormat;
+		this.timeZone 				= timeZone;
+		this.automaticDateParser 	= automaticDateParser;
+		this.userDateFormat 		= userDateFormat;
+		this.mappings				= mappings;
+		this.needsAuth				= needs_auth;
+		this.authMethod				= auth_method;
+		this.loginPageUrl			= login_url;
+		this.requiredCookies		= required_cookies;
+		
+		init();
+	}
+	
+		// bencoded constructor
+	
+	protected 
+	WebEngine(
+		MetaSearchImpl	meta_search,
+		Map				map )
+	
+		throws IOException
+	{
+		super( meta_search, map );
+		
+		searchURLFormat 	= ImportExportUtils.importString( map, "web.search_url_format" );
+		timeZone			= ImportExportUtils.importString( map, "web.time_zone" );
+		userDateFormat		= ImportExportUtils.importString( map, "web.date_format" );
+		downloadLinkCSS		= ImportExportUtils.importString( map, "web.dl_link_css" );
+		
+		needsAuth			= ImportExportUtils.importBoolean(map, "web.needs_auth", NEEDS_AUTH_DEFAULT );
+		authMethod			= ImportExportUtils.importString( map, "web.auth_method", WebEngine.AM_TRANSPARENT );
+		loginPageUrl 		= ImportExportUtils.importString( map, "web.login_page" );
+		requiredCookies 	= ImportExportUtils.importStringArray( map, "web.required_cookies" );
+
+		automaticDateParser	= ImportExportUtils.importBoolean( map, "web.auto_date", AUTOMATIC_DATE_PARSER_DEFAULT );
+		iconUrl 		= ImportExportUtils.importString( map, "web.icon_url" );
+
+		List	maps = (List)map.get( "web.maps" );
+		
+		mappings = new FieldMapping[maps.size()];
+		
+		for (int i=0;i<mappings.length;i++){
+			
+			Map	m = (Map)maps.get(i);
+			
+			mappings[i] = 
+				new FieldMapping(
+						ImportExportUtils.importString( m, "name" ),
+					((Long)m.get( "field")).intValue());
+		}
+		
+		init();
+	}
+	
+	protected void
+	exportToBencodedMap(
+		Map		map,
+		boolean	generic )
+	
+		throws IOException
+	{
+		super.exportToBencodedMap( map, generic );
+		
+		if ( generic ){
+			
+			if ( searchURLFormat != null ){
+				ImportExportUtils.exportString( map, "web.search_url_format", 		searchURLFormat );
+			}
+			if ( timeZone != null ){
+				ImportExportUtils.exportString( map, "web.time_zone", 				timeZone );
+			}
+			if ( userDateFormat != null ){
+				ImportExportUtils.exportString( map, "web.date_format", 			userDateFormat );
+			}
+			if ( downloadLinkCSS != null ){
+				ImportExportUtils.exportString( map, "web.dl_link_css",				downloadLinkCSS );
+			}
+			
+			if ( needsAuth != NEEDS_AUTH_DEFAULT ){
+				ImportExportUtils.exportBoolean( map, "web.needs_auth",				needsAuth );
+			}
+			if ( authMethod != null && !authMethod.equals( WebEngine.AM_TRANSPARENT )){
+				ImportExportUtils.exportString( map, "web.auth_method",				authMethod );
+			}
+			if ( loginPageUrl != null ){
+				ImportExportUtils.exportString( map, "web.login_page",				loginPageUrl );
+			}
+			if ( iconUrl != null ) {
+				ImportExportUtils.exportString(map, "web.icon_url", iconUrl);
+			}
+			if ( requiredCookies != null && requiredCookies.length > 0 ){
+				ImportExportUtils.exportStringArray( map, "web.required_cookies",	requiredCookies );
+			}
+			if (automaticDateParser != AUTOMATIC_DATE_PARSER_DEFAULT ){
+				ImportExportUtils.exportBoolean( map, "web.auto_date", automaticDateParser );
+			}
+
+		}else{
+			ImportExportUtils.exportString( map, "web.search_url_format", 		searchURLFormat );
+			ImportExportUtils.exportString( map, "web.time_zone", 				timeZone );		
+			ImportExportUtils.exportString( map, "web.date_format", 			userDateFormat );
+			ImportExportUtils.exportString( map, "web.dl_link_css",				downloadLinkCSS );
+			
+			ImportExportUtils.exportBoolean( map, "web.needs_auth",				needsAuth );
+			ImportExportUtils.exportString( map, "web.auth_method",				authMethod );
+			ImportExportUtils.exportString( map, "web.login_page",				loginPageUrl );
+			ImportExportUtils.exportString( map, "web.icon_url", iconUrl);
+			ImportExportUtils.exportStringArray( map, "web.required_cookies",	requiredCookies );
+	
+			ImportExportUtils.exportBoolean( map, "web.auto_date", automaticDateParser );
+		}
+		
+		List	maps = new ArrayList();
+		
+		map.put( "web.maps", maps );
+		
+		for (int i=0;i<mappings.length;i++){
+			
+			FieldMapping fm = mappings[i];
+			
+			Map m = new HashMap();
+			
+			ImportExportUtils.exportString( m, "name", fm.getName());
+			m.put( "field", new Long( fm.getField()));
+			
+			maps.add( m );
+		}
+	}
+	
+		// json encoded constructor
+	
+	protected 
+	WebEngine(
+		MetaSearchImpl	meta_search,
+		int				type,
+		long			id,
+		long			last_updated,
+		float			rank_bias,
+		String			name,
+		JSONObject		map )
+	
+		throws IOException
+	{
+		super( meta_search, type, id, last_updated, rank_bias, name, map );
+		
+		searchURLFormat 	= ImportExportUtils.importURL( map, "searchURL" );
+		timeZone			= ImportExportUtils.importString( map, "timezone" );
+		userDateFormat		= ImportExportUtils.importString( map, "time_format" );
+		downloadLinkCSS		= ImportExportUtils.importURL( map, "download_link" );
+
+		
+		needsAuth			= ImportExportUtils.importBoolean( map, "needs_auth", false );
+		authMethod			= ImportExportUtils.importString( map, "auth_method", WebEngine.AM_TRANSPARENT );
+		loginPageUrl 		= ImportExportUtils.importURL( map, "login_page" );
+		iconUrl 		= ImportExportUtils.importURL( map, "icon_url" );
+		
+		requiredCookies 	= ImportExportUtils.importStringArray( map, "required_cookies" );
+		
+		automaticDateParser	= userDateFormat == null || userDateFormat.trim().length() == 0;
+
+		List	maps = (List)map.get( "column_map" );
+		
+		List	conv_maps = new ArrayList();
+		
+		for (int i=0;i<maps.size();i++){
+			
+			Map	m = (Map)maps.get(i);
+				
+				// wha? getting some nulls here :( 
+				// from JSON like "column_map\":[null,null,{\"group_nb\":\"3
+			
+			if ( m == null ){
+				
+				continue;
+			}
+			
+				// backwards compact from when there was a mapping entry
+			
+			Map test = (Map)m.get( "mapping" );
+			
+			if ( test != null ){
+				
+				m = test;
+			}
+			
+			String	vuze_field 	= ImportExportUtils.importString( m, "vuze_field" ).toUpperCase();
+			
+			String	field_name	= ImportExportUtils.importString( m, "group_nb" );	// regexp case
+			
+			if ( field_name == null ){
+				
+				field_name = ImportExportUtils.importString( m, "field_name" );	// json case
+			}
+			
+			if ( vuze_field == null || field_name == null ){
+				
+				log( "Missing field mapping name/value in '" + m + "'" );
+
+			}
+			int	field_id = vuzeFieldToID( vuze_field );
+			
+			if ( field_id == -1 ){
+				
+				log( "Unrecognised field mapping '" + vuze_field + "'" );
+				
+				continue;
+			}
+			
+			conv_maps.add( new FieldMapping( field_name, field_id ));
+		}
+		
+		mappings = (FieldMapping[])conv_maps.toArray( new FieldMapping[conv_maps.size()]);
+		
+		init();
+	}
+	
+	protected void
+	exportToJSONObject(
+		JSONObject		res )
+	
+		throws IOException
+	{		
+		super.exportToJSONObject( res );
+		
+		ImportExportUtils.exportJSONURL( res, "searchURL", searchURLFormat );
+		
+		ImportExportUtils.exportJSONString( res, "timezone", 	timeZone );	
+		
+		if ( downloadLinkCSS != null ){
+			
+			ImportExportUtils.exportJSONURL( res, "download_link", downloadLinkCSS );
+		}
+		
+		ImportExportUtils.exportJSONBoolean( res, "needs_auth",				needsAuth );
+		ImportExportUtils.exportJSONString( res, "auth_method",				authMethod );
+		ImportExportUtils.exportJSONURL( res, "login_page",					loginPageUrl );
+		ImportExportUtils.exportJSONURL( res, "icon_url",					iconUrl );
+		ImportExportUtils.exportJSONStringArray( res, "required_cookies",	requiredCookies );
+ 
+		if ( !automaticDateParser ){
+			
+			ImportExportUtils.exportJSONString( res, "time_format",	userDateFormat );
+		}
+		
+		JSONArray	maps = new JSONArray();
+		
+		res.put( "column_map", maps );
+
+		for (int i=0;i<mappings.length;i++){
+			
+			FieldMapping fm = mappings[i];
+			
+			int	field_id = fm.getField();
+			
+			String	field_value = vuzeIDToField( field_id );
+			
+			if ( field_value == null ){
+				
+				log( "JSON export: unknown field id " + field_id );
+				
+			}else{
+							
+				JSONObject entry = new JSONObject();
+
+				maps.add( entry );
+					
+				entry.put( "vuze_field", field_value );
+				
+				if ( getType() == ENGINE_TYPE_JSON ){
+					
+					entry.put( "field_name", fm.getName());
+					
+				}else{
+					
+					entry.put( "group_nb", fm.getName());
+				}
+			}
+		}	
+	}
+	
+	protected void
+	init()
+	{
+		try {
+			Matcher m = rootURLPattern.matcher(searchURLFormat);
+			if(m.find()) {
+				this.rootPage = m.group(1);
+			}
+		} catch(Exception e) {
+			//Didn't find the root url within the URL
+			this.rootPage = null;
+		}
+		
+		try {
+			Matcher m = baseURLPattern.matcher(searchURLFormat);
+			if(m.find()) {
+				this.basePage = m.group(1);
+			}
+		} catch(Exception e) {
+			//Didn't find the root url within the URL
+			this.basePage = null;
+		}
+		
+		this.dateParser = new DateParserRegex(timeZone,automaticDateParser,userDateFormat);
+		
+		local_cookies = getLocalString( LD_COOKIES );
+		
+			// normalise to permit == to be safely used when testing method
+		
+		authMethod = authMethod.intern();
+		
+			// see if we have explicit cookie information in the URL:
+		
+		int	cook_pos = searchURLFormat.indexOf( ":COOKIE:" );
+					
+		if ( cook_pos != -1 ){
+			
+			String explicit_cookie = searchURLFormat.substring( cook_pos + 8 );
+			
+			setNeedsAuth( true );
+			
+			setCookies( explicit_cookie );
+			
+			setRequiredCookies( CookieParser.getCookiesNames( explicit_cookie ));
+			
+			searchURLFormat = searchURLFormat.substring( 0, cook_pos );
+			
+			setPublic( false );
+			
+			String	name = getName();
+			
+			int	n_pos = name.indexOf( ":COOKIE:" );
+			
+			if ( n_pos != -1 ){
+				
+				setName( name.substring( 0, n_pos ));
+			}
+		}
+	}
+	
+	public String 
+	getNameEx() 
+	{
+		String url = getRootPage();
+		
+		if ( url == null || url.length() == 0 ){
+			
+			url = searchURLFormat;
+		}
+		
+		String name = getName();
+		
+		if ( name.indexOf( url ) == -1 ){
+			
+			return( name + " (" + url + ")");
+			
+		}else{
+			
+			return( name );
+		}
+		     
+	}
+	
+	public String 
+	getReferer() 
+	{
+		return( getRootPage());
+	}
+	
+	public boolean
+	supportsContext(
+		String	context_key )
+	{
+		try{
+			URL	url = new URL( searchURLFormat );
+			
+			String	host = url.getHost();
+			
+			if ( org.gudy.azureus2.core3.util.Constants.isAzureusDomain( host )){
+				
+				return( true );
+			}
+			
+			if ( UrlFilter.getInstance().isWhitelisted( searchURLFormat )){
+				
+				return( true );
+			}
+			
+			
+				// allow local addresses for testing purposes
+			
+			InetAddress iad = AddressUtils.getByName(host);
+			
+			if ( 	iad.isLoopbackAddress() ||
+					iad.isLinkLocalAddress() ||
+					iad.isSiteLocalAddress()){
+				
+				return( true );
+			}
+		}catch( Throwable e ){
+		}
+		
+		return( false );
+	}
+	
+	public boolean 
+	isShareable() 
+	{
+		try{
+			return( !UrlUtils.containsPasskey( new URL( searchURLFormat )));
+			
+		}catch( Throwable e ){
+			
+			return( true );
+		}
+	}
+	
+	protected pageDetails 
+	getWebPageContent(
+		SearchParameter[] 	searchParameters,
+		Map<String,String>	searchContext,
+		String				headers,
+		boolean				only_if_modified )
+	
+		throws SearchException
+	{
+		return( getWebPageContent( searchParameters, searchContext, headers, only_if_modified, null ));
+	}
+	
+	protected pageDetails 
+	getWebPageContent(
+		SearchParameter[] 		searchParameters,
+		Map<String,String>		searchContext,
+		String					headers,
+		boolean					only_if_modified,
+		pageDetailsVerifier		verifier )
+	
+		throws SearchException
+	{
+		String searchURL = searchURLFormat;
+
+		if ( searchURL.toLowerCase( Locale.US ).startsWith( "tor:" )){
+			
+				// strip out any stuff we probably don't want to send
+			
+			searchContext = new HashMap<String, String>();
+			
+			String target_resource = searchURLFormat.substring( 4 );
+			
+			URL location;
+			
+			try{
+
+				location = new URL( target_resource );
+				
+			}catch( MalformedURLException e ){
+				
+				throw( new SearchException( e ));
+			}
+			
+			Map<String,Object>	options = new HashMap<String,Object>();
+		
+			options.put( AEProxyFactory.PO_PEER_NETWORKS, new String[]{ AENetworkClassifier.AT_TOR });
+		
+			PluginProxy plugin_proxy = 
+				AEProxyFactory.getPluginProxy( 
+					"Web engine download of '" + target_resource + "'",
+					location,
+					options,
+					true );
+
+			if ( plugin_proxy == null ){
+				
+				throw( new SearchException( "No Tor plugin proxy available for '" + target_resource + "'" ));
+			}
+
+			URL 	url		= plugin_proxy.getURL();
+			Proxy 	proxy	= plugin_proxy.getProxy();
+
+			boolean	ok = false;
+			
+			try{
+				String proxy_host = location.getHost() + (location.getPort()==-1?"":(":" + location.getPort()));
+				
+				pageDetails	details = getWebPageContentSupport( proxy, proxy_host, url.toExternalForm(), searchParameters, searchContext, headers, only_if_modified );
+			
+				String content = details.getContent();
+				
+				content = content.replaceAll( "(?i)http://", "tor:http://" );
+				content = content.replaceAll( "(?i)https://", "tor:https://" );
+				content = content.replaceAll( "(?i)ftp://", "tor:ftp://" );
+				
+				details.setContent( content );
+				
+				if ( verifier != null ){
+					
+					verifier.verify( details );
+				}
+				
+				ok = true;
+				
+				return( details );
+				
+			}finally{
+				
+				plugin_proxy.setOK( ok );
+			}
+		}
+		
+		try{
+			try{
+				URL url = new URL( searchURL );
+			
+				if ( AENetworkClassifier.categoriseAddress( url.getHost()) != AENetworkClassifier.AT_PUBLIC ){
+					
+					// strip out any stuff we probably don't want to send
+					
+					searchContext = new HashMap<String, String>();
+				}
+			}catch( Throwable e ){
+			}
+			
+			pageDetails	details = getWebPageContentSupport( null, null, searchURL, searchParameters, searchContext, headers, only_if_modified );
+		
+			if ( verifier != null ){
+				
+				verifier.verify( details );
+			}
+			
+			return( details );
+			
+		}catch( SearchException e ){
+			
+			try{
+				URL 			original_url	= new URL( searchURL );
+				
+				PluginProxy 	plugin_proxy	= AEProxyFactory.getPluginProxy( "getting search results ", original_url );
+				
+				if ( plugin_proxy == null ){
+					
+					throw( e );
+					
+				}else{
+					
+					URL 	url		= plugin_proxy.getURL();
+					Proxy 	proxy	= plugin_proxy.getProxy();
+
+					boolean	ok = false;
+					
+					try{
+						String proxy_host = original_url.getHost() + (original_url.getPort()==-1?"":(":" + original_url.getPort()));
+						
+						pageDetails	details = getWebPageContentSupport( proxy, proxy_host, url.toExternalForm(), searchParameters, searchContext, headers, only_if_modified );
+					
+						if ( verifier != null ){
+							
+							verifier.verify( details );;
+						}
+						
+						ok = true;
+						
+						return( details );
+						
+					}finally{
+						
+						plugin_proxy.setOK( ok );
+					}
+				}
+			}catch( Throwable f ){
+				
+				throw( e );
+			}
+		}
+	}
+	
+	private pageDetails 
+	getWebPageContentSupport(
+		Proxy				proxy,
+		String				proxy_host,
+		String				searchURL,
+		SearchParameter[] 	searchParameters,
+		Map<String,String>	searchContext,
+		String				headers,
+		boolean				only_if_modified )
+	
+		throws SearchException
+	{
+		
+		try {
+			TorrentUtils.setTLSDescription( "Search: " + getName());
+			
+			if ( requiresLogin()){
+				
+				throw new SearchLoginException("login required");
+			}
+						
+			boolean vuze_file = searchURL.toLowerCase().startsWith( "vuze:" );
+			
+			if ( !vuze_file ){
+				
+				String[]	from_strs 	= new String[ searchParameters.length ];
+				String[]	to_strs 	= new String[ searchParameters.length ];
+				
+				for( int i = 0 ; i < searchParameters.length ; i++ ){
+					
+					SearchParameter parameter = searchParameters[i];
+					
+					from_strs[i]	= "%" + parameter.getMatchPattern();
+					to_strs[i]		= URLEncoder.encode(parameter.getValue(),"UTF-8");
+				}
+				
+				searchURL = GeneralUtils.replaceAll( searchURL, from_strs, to_strs );
+					
+				Iterator<Map.Entry<String, String>>	it = searchContext.entrySet().iterator();
+				
+				while( it.hasNext()){
+					
+					Map.Entry<String, String>	entry = it.next();
+					
+					String	key 	= entry.getKey();
+						
+					if ( supportsContext( key )){
+						
+						if ( searchURL.indexOf('?') == -1 ){
+							
+							searchURL += "?";
+							
+						}else{
+							
+							searchURL += "&";
+						}
+						
+						String	value 	= entry.getValue();
+	
+						searchURL += key + "=" + URLEncoder.encode( value, "UTF-8" );
+					}
+				}
+			}
+			
+			//System.out.println(searchURL);
+			
+			
+				// hack to support POST by encoding into URL
+			
+				// http://xxxx/index.php?main=search&azmethod=post_basic:SearchString1=%s&SearchString=&search=Search
+				
+			ResourceDownloaderFactory rdf = StaticUtilities.getResourceDownloaderFactory();
+
+			URL					initial_url;
+			ResourceDownloader 	initial_url_rd;
+					
+			
+			int	post_pos = searchURL.indexOf( "azmethod=" );
+			
+			if ( post_pos > 0 ){
+				
+				String post_params = searchURL.substring( post_pos+9 );
+				
+				searchURL = searchURL.substring( 0, post_pos-1 );
+				
+				debugLog( "search_url: " + searchURL + ", post=" + post_params );
+
+				initial_url = new URL(searchURL);
+
+				int	sep = post_params.indexOf( ':' );
+				
+				String	type = post_params.substring( 0, sep );
+				
+				if ( !type.equals( "post_basic" )){
+					
+					throw( new SearchException( "Only basic type supported" ));
+				}
+				
+				post_params = post_params.substring( sep+1 );
+				
+					// already URL encoded
+				
+				if ( proxy == null ){
+				
+					initial_url_rd = rdf.create( initial_url, post_params );
+					
+				}else{
+					
+					initial_url_rd = rdf.create( initial_url, post_params, proxy );
+				}
+				
+				initial_url_rd.setProperty( "URL_Content-Type", "application/x-www-form-urlencoded" );
+				
+			}else{
+			
+				debugLog( "search_url: " + searchURL );
+			
+				initial_url = new URL(searchURL);
+			
+				if ( proxy == null ){
+				
+					initial_url_rd = rdf.create( initial_url );
+					
+				}else{
+					
+					initial_url_rd = rdf.create( initial_url, proxy );
+				}
+			}
+			
+			if ( proxy_host != null ){
+				
+				initial_url_rd.setProperty( "URL_HOST", proxy_host );
+			}
+			
+			setHeaders( initial_url_rd, headers );
+				
+			if ( needsAuth && local_cookies != null ){
+				
+				initial_url_rd.setProperty( "URL_Cookie", local_cookies );				
+			}
+				
+			if ( only_if_modified ){
+				
+				String last_modified 	= getLocalString( LD_LAST_MODIFIED );
+				String etag				= getLocalString( LD_ETAG );
+
+				if ( last_modified != null ){
+					
+					initial_url_rd.setProperty( "URL_If-Modified-Since", last_modified );
+				}
+				
+				if ( etag != null ){
+					
+					initial_url_rd.setProperty( "URL_If-None-Match", etag );
+				}
+			}
+			
+			InputStream	is = null;
+			
+			try{
+				String content_charset = "UTF-8";
+	
+				ResourceDownloader mr_rd = null;
+				
+				if ( initial_url.getProtocol().equalsIgnoreCase( "file" )){
+					
+						// handle file://c:/ - map to file:/c:/
+					
+					String	str = initial_url.toExternalForm();
+					
+					if ( initial_url.getAuthority() != null ){
+					
+						str = str.replaceFirst( "://", ":/" );
+					}
+									
+					int	pos = str.indexOf( '?' );
+					
+					if ( pos != -1 ){
+						
+						str = str.substring( 0, pos );
+					}
+					
+					is = new FileInputStream( new File( new URL( str ).toURI()));
+					
+				}else{
+					
+					if ( proxy == null ){
+						
+						initial_url_rd.setProperty( "URL_Connect_Timeout", 10*1000 );
+						
+						initial_url_rd.setProperty( "URL_Read_Timeout", 10*1000 ); 
+					}
+					
+					mr_rd = rdf.getMetaRefreshDownloader( initial_url_rd );
+	
+					try{
+					
+						is = mr_rd.download();
+						
+					}catch( ResourceDownloaderException e ){
+					
+						Long	response = (Long)mr_rd.getProperty( "URL_HTTP_Response" );
+						
+						if ( response != null && response.longValue() == 304 ){
+							
+								// not modified
+							
+							return( new pageDetails( initial_url, initial_url, "" ));
+							
+						}else{
+							
+							throw( e );
+						}
+					}
+	
+				
+					if ( needsAuth ){
+						
+						List	cookies_list = (List)mr_rd.getProperty( "URL_Set-Cookie" );
+						
+						List	cookies_set = new ArrayList();
+						
+						if ( cookies_list != null ){
+							
+							for (int i=0;i<cookies_list.size();i++){
+								
+								String[] cookies = ((String)cookies_list.get(i)).split(";");
+								
+								for (int j=0;j<cookies.length;j++){
+									
+									String	cookie = cookies[j].trim();
+									
+									if ( cookie.indexOf('=') != -1 ){
+										
+										cookies_set.add( cookie );
+									}
+								}
+							}
+						}
+						
+							// well, not much we can do with the cookies anyway as in general the ones
+							// set are the ones missing/expired, not the existing ones. That is, we can't
+							// deduce anything from the fact that a required cookie is not 'set' here
+							// the most we could do is catch a server that explicitly deleted invalid
+							// cookies by expiring it, but I doubt this is a common practice.
+						
+							// Also note the complexity of cookie syntax
+							// Set-Cookie: old standard using expires=, new using MaxAge
+							// Set-Cookie2:
+							// Maybe use http://jcookie.sourceforge.net/ if needed
+					}
+					
+					if ( only_if_modified ){
+						
+						String last_modified 	= extractProperty( mr_rd.getProperty( "URL_Last-Modified" ));
+						String etag				= extractProperty( mr_rd.getProperty( "URL_ETag" ));
+						
+						if ( last_modified != null ){
+							
+							setLocalString( LD_LAST_MODIFIED, last_modified );
+						}
+						
+						if ( etag != null ){
+							
+							setLocalString( LD_ETAG, etag );
+						}
+					}
+					
+					List cts = (List)mr_rd.getProperty( "URL_Content-Type" );
+												
+					if ( cts != null && cts.size() > 0 ){
+						
+						String	content_type = (String)cts.get(0);
+						
+						int	pos = content_type.toLowerCase().indexOf( "charset" );
+						
+						if ( pos != -1 ){
+							
+							content_type = content_type.substring( pos+1 );
+							
+							pos = content_type.indexOf('=');
+							
+							if ( pos != -1 ){
+								
+								content_type = content_type.substring( pos+1 ).trim();
+								
+								pos = content_type.indexOf(';');
+								
+								if ( pos != -1 ){
+									
+									content_type = content_type.substring(0,pos).trim();
+								}
+								
+								if ( content_type.startsWith("\"" )){
+									
+									content_type = content_type.substring(1).trim();
+								}
+								
+								if ( content_type.endsWith("\"" )){
+									
+									content_type = content_type.substring(0,content_type.length()-1).trim();
+								}
+								
+								try{
+									if ( Charset.isSupported( content_type )){
+										
+										debugLog( "charset: " + content_type );
+										
+										content_charset = content_type;
+									}
+								}catch( Throwable e ){
+									
+									try{
+											// handle lowercase 'utf-8' for example
+										
+										content_type = content_type.toUpperCase();
+										
+										if ( Charset.isSupported( content_type )){
+											
+											debugLog( "charset: " + content_type );
+											
+											content_charset = content_type;
+										}
+									}catch( Throwable f ){
+										
+										log( "Content type '" + content_type + "' not supported", f );
+									}
+								}
+							}
+						}
+					}
+				}
+				
+				ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
+										
+				byte[] buffer = new byte[8192];			
+	
+				while( true ){
+					
+					int	len = is.read( buffer );
+					
+					if ( len <= 0 ){
+						
+						break;
+					}
+					
+					baos.write( buffer, 0, len );
+				}
+				
+				byte[] data = baos.toByteArray();
+				
+				if ( vuze_file ){
+					
+					try{
+						VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
+						
+						VuzeFile vf = vfh.loadVuzeFile( data );
+						
+						vfh.handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_NONE );
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+					
+					return( new pageDetails( initial_url, initial_url, null ));
+				}
+				
+				String 	page = null;
+				
+				String	content = new String( data, 0, Math.min( data.length, 2048 ), content_charset );
+				
+				String	lc_content = content.toLowerCase();
+				
+				{
+						// first look for xml charset
+				
+						// e.g. <?xml version="1.0" encoding="windows-1251" ?>
+	
+					int	pos1 = lc_content.indexOf( "<?xml" );
+					
+					if ( pos1 != -1 ){
+						
+						int pos2 = lc_content.indexOf( "?>" );
+						
+						if ( pos2 != -1 ){
+												
+							int pos3 = lc_content.indexOf( "encoding", pos1 );
+							
+							if ( pos3 != -1 ){
+								
+								pos3 = lc_content.indexOf( "\"", pos3 );
+							}
+							
+							if ( pos3 > pos1 && pos3 < pos2 ){
+															
+								pos3++;
+								
+								int pos4 = lc_content.indexOf( "\"", pos3 );
+								
+								if ( pos4 > pos3 && pos4 < pos2 ){
+									
+									String	encoding = content.substring( pos3, pos4 ).trim();
+									
+									try{
+										if ( Charset.isSupported( encoding )){
+											
+											debugLog( "charset from xml tag: " + encoding );
+											
+											content_charset = encoding;
+											
+												// some feeds have crap at the start which makes pos2 mismatch for the above '?' - adjust if necessary
+											
+											int data_start = pos2;
+											
+											int	max_skip	= 64;
+											
+											while( data[data_start] != '?' && max_skip-- > 0 ){
+												
+												data_start++;
+											}
+											
+											page = content.substring( 0, pos3 ) + "utf-8" + content.substring( pos4, pos2 ) + new String( data, data_start, data.length - data_start, content_charset );							
+										}
+									}catch( Throwable e ){
+										
+										log( "Content type '" + encoding + "' not supported", e );
+									}
+								}
+							}
+						}
+					}
+				}
+				
+				if ( page == null ){
+						
+						// next look for http-equiv charset
+					
+						// e.g. <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
+	
+					int	pos = 0;
+					
+					while( true ){
+					
+						int	pos1 = lc_content.indexOf( "http-equiv", pos );
+					
+						if ( pos1 != -1 ){
+						
+							int	pos2 = lc_content.indexOf( ">", pos1 );
+							
+							if ( pos2 != -1 ){
+								
+								int	pos3 = lc_content.indexOf( "charset", pos1 );
+								
+								if ( pos3 != -1 && pos3 < pos2 ){
+								
+									pos3 = lc_content.indexOf( "=", pos3 );
+									
+									if ( pos3 != -1 ){
+										
+										pos3++;
+										
+										int pos4 = lc_content.indexOf( "\"", pos3 );
+										
+										if ( pos4 != -1 ){
+											
+											int pos5 = lc_content.indexOf( ";", pos3 );
+										
+											if ( pos5 != -1 && pos5 < pos4 ){
+												
+												pos4 = pos5;
+											}
+											
+											String encoding = content.substring( pos3, pos4 ).trim();
+											
+											try{
+												if ( Charset.isSupported( encoding )){
+													
+													debugLog( "charset from http-equiv : " + encoding );
+													
+													content_charset = encoding;
+													
+														// some feeds have crap at the start which makes pos2 mismatch for the above '?' - adjust if necessary
+													
+													int data_start = pos2;
+													
+													int	max_skip	= 64;
+													
+													while( data[data_start] != '?' && max_skip-- > 0 ){
+														
+														data_start++;
+													}
+													
+													page = content.substring( 0, pos3 ) + "utf-8" + content.substring( pos4, pos2 ) + new String( data, data_start, data.length - data_start, content_charset );							
+												}
+											}catch( Throwable e ){
+												
+												log( "Content type '" + encoding + "' not supported", e );
+											}
+											
+											break;
+										}
+									}
+								}
+								
+								pos = pos2;
+								
+							}else{
+								
+								break;
+							}
+						}else{
+							
+							break;
+						}
+					}
+				}
+				
+				if ( page == null ){
+					
+					page = new String( data, content_charset );
+				}
+				
+				debugLog( "page:" );
+				debugLog( page );
+	
+				// List 	cookie = (List)url_rd.getProperty( "URL_Set-Cookie" );
+				
+				try {
+					Matcher m = baseTagPattern.matcher(page);
+					if(m.find()) {
+						basePage = m.group(1);
+						
+						debugLog( "base_page: " + basePage );
+					}
+				} catch(Exception e) {
+					//No BASE tag in the page
+				}
+				
+				URL	final_url = initial_url;
+				
+				if ( mr_rd != null ){
+					
+					URL	x = (URL)mr_rd.getProperty( "URL_URL" );
+		
+					if ( x != null ){
+						
+						final_url = x;
+					}
+				}
+				
+				return( new pageDetails( initial_url, final_url, page ));
+				
+			}finally{
+				
+				if ( is != null ){
+					
+					is.close();
+				}
+			}
+				
+		}catch( SearchException e ){
+			
+			throw( e );
+			
+		}catch( Throwable e) {
+			
+			// e.printStackTrace();
+			
+			debugLog( "Failed to load page: " + Debug.getNestedExceptionMessageAndStack(e));
+			
+			throw( new SearchException( "Failed to load page", e ));
+			
+		}finally{
+			
+			TorrentUtils.setTLSDescription( null );
+		}
+	}
+
+	protected String
+	extractProperty(
+		Object	o )
+	{
+		if ( o instanceof String ){
+			
+			return((String)o);
+			
+		}else if ( o instanceof List ){
+			
+			List	l = (List)o;
+			
+			if ( l.size() > 0 ){
+				
+				if ( l.size() > 1 ){
+					
+					Debug.out( "Property has multiple values!" );
+				}
+				
+				Object x = l.get(0);
+				
+				if ( x instanceof String ){
+					
+					return((String)x);
+					
+				}else{
+					
+					Debug.out( "Property value isn't a String:" + x );
+				}
+			}
+		}
+		
+		return( null );
+	}
+	
+	protected void
+	setHeaders(
+		ResourceDownloader		rd,
+		String					encoded_headers )
+	{
+		UrlUtils.setBrowserHeaders( rd, encoded_headers, rootPage );
+	}
+	
+	public String getIcon() {
+		if (iconUrl != null) {
+			return iconUrl;
+		}
+		if(rootPage != null) {
+			return rootPage + "/favicon.ico";
+		}
+		return null;
+	}
+	
+	protected FieldMapping[]
+	getMappings()
+	{
+		return( mappings );
+	}
+	
+	public boolean
+	supportsField(
+		int		field_id )
+	{
+		for (int i=0;i<mappings.length;i++){
+			
+			if ( mappings[i].getField() == field_id ){
+				
+				return( true );
+			}
+		}
+		
+		return( false );
+	}
+	
+	protected String
+	getRootPage()
+	{
+		return( rootPage );
+	}
+	
+	protected String
+	getBasePage()
+	{
+		return( basePage );
+	}
+	
+	protected DateParser
+	getDateParser()
+	{
+		return( dateParser );
+	}
+	
+	public String 
+	getDownloadLinkCSS()
+	{
+		if ( downloadLinkCSS == null ){
+			
+			return( "" );
+		}
+		
+		return( downloadLinkCSS );
+	}
+	
+	public boolean requiresLogin() {
+		return needsAuth && ! CookieParser.cookiesContain(requiredCookies, local_cookies);
+	}
+	
+	public void setCookies(String cookies) {
+		this.local_cookies = cookies;
+		
+		setLocalString( LD_COOKIES, cookies );
+	}
+
+	public String
+	getSearchUrl(
+		boolean		raw )
+	{
+		if ( raw ){
+			
+			return( searchURLFormat );
+		}else{
+			
+			return( getSearchUrl());
+		}
+	}
+	
+	public String
+	getSearchUrl()
+	{
+		return( searchURLFormat.replaceAll("%s", ""));
+	}
+	
+	public void
+	setSearchUrl(
+		String		str )
+	{
+		searchURLFormat = str;
+		
+		init();
+		
+		getMetaSearch().configDirty();
+	}
+	
+	public String getLoginPageUrl() {
+		//Let's try with no login page url
+		//return loginPageUrl;
+		return searchURLFormat.replaceAll("%s", "");
+	}
+
+	public void setLoginPageUrl(String loginPageUrl) {
+		this.loginPageUrl = loginPageUrl;
+	}
+
+	public String[] getRequiredCookies() {
+		return requiredCookies;
+	}
+
+	public void setRequiredCookies(String[] requiredCookies) {
+		this.requiredCookies = requiredCookies;
+	}
+
+	public boolean isNeedsAuth() {
+		return needsAuth;
+	}
+
+	public boolean
+	isAuthenticated()
+	{
+		return( isNeedsAuth());
+	}
+	
+	protected void
+	setNeedsAuth(
+		boolean	b )
+	{
+		needsAuth = b;
+	}
+	
+	public String
+	getAuthMethod()
+	{
+		return( authMethod );
+	}
+	
+	public String getCookies() {
+		return local_cookies;
+	}
+	
+	public String
+	getString()
+	{
+		return( getString( false ));
+	}
+	
+	public String
+	getString(
+		boolean		full )
+	{
+		return( 	super.getString() + 
+						(full?(", url=" + searchURLFormat ):"") +
+						", auth=" + isNeedsAuth() +
+						(isNeedsAuth()?" [cookies=" + local_cookies + "]":"" ));
+	}
+	
+	public static class
+	pageDetails
+	{
+		private URL			initial_url;
+		private URL			final_url;
+		private String		content;
+		
+		private Object		verified_state;
+		
+		protected
+		pageDetails(
+			URL		_initial_url,
+			URL		_final_url,
+			String	_content )
+		{
+			initial_url		= _initial_url;
+			final_url		= _final_url;
+			content			= _content;
+		}
+
+		public URL
+		getInitialURL()
+		{
+			return( initial_url );
+		}
+
+		public URL
+		getFinalURL()
+		{
+			return( final_url );
+		}
+		
+		public String
+		getContent()
+		{
+			return( content );
+		}
+		
+		private void
+		setContent(
+			String		_content )
+		{
+			content	= _content;
+		}
+		
+		public void
+		setVerifiedState(
+			Object		state )
+		{
+			verified_state = state;
+		}
+		
+		public Object
+		getVerifiedState()
+		{
+			return( verified_state );
+		}
+	}
+	
+	public interface
+	pageDetailsVerifier
+	{
+		public void
+		verify(
+			pageDetails	details )
+		
+			throws SearchException;
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/WebResult.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/WebResult.java
index 47a65d8..4c07500 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/WebResult.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/WebResult.java
@@ -1,513 +1,514 @@
-/*
- * Created on May 6, 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.core.metasearch.impl.web;
-
-import java.util.Date;
-import java.util.StringTokenizer;
-
-import org.apache.commons.lang.*;
-import org.gudy.azureus2.core3.util.Base32;
-import org.gudy.azureus2.core3.util.ByteFormatter;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.UrlUtils;
-
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.Result;
-import com.aelitis.azureus.core.metasearch.impl.DateParser;
-
-public class WebResult extends Result {
-	
-	
-	
-	String searchQuery;
-	
-	String rootPageURL;
-	String basePageURL;
-	DateParser dateParser;
-	
-	
-	String contentType = "";
-	String name;
-	String category = "";
-	
-	String drmKey = null;
-	
-	Date publishedDate;
-	
-	long size = -1;
-	int nbPeers = -1;
-	int nbSeeds = -1;
-	int nbSuperSeeds = -1;
-	int	comments	= -1;
-	int votes = -1;
-	int votesDown = -1;
-	float rank = -1;
-	
-	boolean privateTorrent;
-	
-	String cdpLink;
-	String torrentLink;
-	String downloadButtonLink;
-	String playLink;
-	
-	String uid;
-	String hash;
-	
-	public WebResult(Engine engine, String rootPageURL,String basePageURL,DateParser dateParser,String searchQuery) {
-		super( engine );
-		this.rootPageURL = rootPageURL;
-		this.basePageURL = basePageURL;
-		this.dateParser = dateParser;
-		this.searchQuery = searchQuery;
-	}
-		
-	public void setName(String name) {
-		if(name != null) {
-			this.name = name;
-		}
-	}
-	
-	public void setNameFromHTML(String name) {
-		if(name != null) {
-			name = removeHTMLTags(name);
-			this.name = Entities.HTML40.unescape(name);
-		}
-	}
-	
-	public void setCommentsFromHTML(String comments) {
-		if(comments != null) {
-			comments = removeHTMLTags(comments);
-			comments = Entities.HTML40.unescape(comments);
-			comments = comments.replaceAll(",", "");
-			comments = comments.replaceAll(" ", "");
-			try{
-				this.comments = Integer.parseInt(comments);
-			}catch( Throwable e ){
-				//e.printStackTrace();
-			}
-		}
-	}
-	public void setCategoryFromHTML(String category) {
-		if(category != null) {
-			category = removeHTMLTags(category);
-			this.category = Entities.HTML40.unescape(category).trim();
-			/*int separator = this.category.indexOf(">");
-			
-			if(separator != -1) {
-				this.category = this.category.substring(separator+1).trim();
-			}*/
-		}
-	}
-	
-	public void
-	setUID(
-		String	_uid )
-	{
-		uid	= _uid;
-	}
-	
-	public String
-	getUID()
-	{
-		return( uid );
-	}
-	
-	public void setNbPeersFromHTML(String nbPeers) {
-		if(nbPeers != null) {
-			nbPeers = removeHTMLTags(nbPeers);
-			String nbPeersS = Entities.HTML40.unescape(nbPeers);
-			nbPeersS = nbPeersS.replaceAll(",", "");
-			nbPeersS = nbPeersS.replaceAll(" ", "");
-			try {
-				this.nbPeers = Integer.parseInt(nbPeersS);
-			} catch(Throwable e) {
-				//this.nbPeers = 0;
-				//e.printStackTrace();
-			}
-		}
-	}	
-	
-	public void setNbSeedsFromHTML(String nbSeeds) {
-		if(nbSeeds != null) {
-			nbSeeds = removeHTMLTags(nbSeeds);
-			String nbSeedsS = Entities.HTML40.unescape(nbSeeds);
-			nbSeedsS = nbSeedsS.replaceAll(",", "");
-			nbSeedsS = nbSeedsS.replaceAll(" ", "");
-			try {
-				this.nbSeeds = Integer.parseInt(nbSeedsS);
-			} catch(Throwable e) {
-				//this.nbSeeds = 0;
-				//e.printStackTrace();
-			}
-		}
-	}
-	
-	public void setNbSuperSeedsFromHTML(String nbSuperSeeds) {
-		if(nbSuperSeeds != null) {
-			nbSuperSeeds = removeHTMLTags(nbSuperSeeds);
-			String nbSuperSeedsS = Entities.HTML40.unescape(nbSuperSeeds);
-			nbSuperSeedsS = nbSuperSeedsS.replaceAll(",", "");
-			nbSuperSeedsS = nbSuperSeedsS.replaceAll(" ", "");
-			try {
-				this.nbSuperSeeds = Integer.parseInt(nbSuperSeedsS);
-			} catch(Throwable e) {
-				//this.nbSeeds = 0;
-				//e.printStackTrace();
-			}
-		}
-	}
-
-	public void setRankFromHTML( String rank_str, float divisor ){
-		if (rank_str == null) {
-			return;
-		}
-		try{
-			float f = Float.parseFloat( rank_str.trim() );
-			
-			rank = f / divisor;
-		}catch( Throwable e ){
-		}
-	}
-
-	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( applyRankBias( rank ));
-		}
-		
-		return( super.getRank());
-	}
-	
-	public void setPublishedDate(Date date) {
-		this.publishedDate = date;
-	}
-	
-	public void setPublishedDateFromHTML(String publishedDate) {
-		if(publishedDate != null) {
-			publishedDate = removeHTMLTags(publishedDate);
-			String publishedDateS = Entities.HTML40.unescape(publishedDate).replace((char)160,(char)32);
-			this.publishedDate = dateParser.parseDate(publishedDateS);
-		}
-	}
-	
-
-	public void setSizeFromHTML(String size) {
-		if(size != null) {
-			size = removeHTMLTags(size);
-			String sizeS = Entities.HTML40.unescape(size).replace((char)160,(char)32);
-			sizeS = sizeS.replaceAll("<[^>]+>", " ");
-			//Add a space between the digits and unit if there is none
-			sizeS = sizeS.replaceFirst("(\\d)([a-zA-Z])", "$1 $2");
-			try {
-				StringTokenizer st = new StringTokenizer(sizeS," ");
-				double base = Double.parseDouble(st.nextToken());
-				String unit = "b";
-				try {
-					unit = st.nextToken().toLowerCase();
-				} catch(Throwable e) {
-					//No unit
-				}
-				long multiplier = 1;
-				long KB_UNIT = 1024;
-				long KIB_UNIT = 1024;
-				if("mb".equals(unit)) {
-					multiplier = KB_UNIT*KB_UNIT;
-				} else if("mib".equals(unit)) {
-					multiplier = KIB_UNIT*KIB_UNIT;
-				} else if("m".equals(unit)) {
-					multiplier = KIB_UNIT*KIB_UNIT;
-				} else if("gb".equals(unit)) {
-					multiplier = KB_UNIT*KB_UNIT*KB_UNIT;
-				} else if("gib".equals(unit)) {
-					multiplier = KIB_UNIT*KIB_UNIT*KIB_UNIT;
-				} else if("g".equals(unit)) {
-					multiplier = KIB_UNIT*KIB_UNIT*KIB_UNIT;
-				} else if("kb".equals(unit)) {
-					multiplier = KB_UNIT;
-				} else if("kib".equals(unit)) {
-					multiplier = KIB_UNIT;
-				} else if("k".equals(unit)) {
-					multiplier = KIB_UNIT;
-				}
-				
-				this.size = (long) (base * multiplier);
-			} catch(Throwable e) {
-				//e.printStackTrace();
-			}
-		}
-	}
-	
-	public void setVotesFromHTML(String votes_str) {
-		if(votes_str != null) {
-			votes_str = removeHTMLTags(votes_str);
-			votes_str = Entities.HTML40.unescape(votes_str);
-			votes_str = votes_str.replaceAll(",", "");
-			votes_str = votes_str.replaceAll(" ", "");
-			try {
-				this.votes = Integer.parseInt(votes_str);
-			} catch(Throwable e) {
-				//e.printStackTrace();
-			}
-		}
-	}	
-	
-	public void setVotesDownFromHTML(String votes_str) {
-		if(votes_str != null) {
-			votes_str = removeHTMLTags(votes_str);
-			votes_str = Entities.HTML40.unescape(votes_str);
-			votes_str = votes_str.replaceAll(",", "");
-			votes_str = votes_str.replaceAll(" ", "");
-			try {
-				this.votesDown = Integer.parseInt(votes_str);
-			} catch(Throwable e) {
-				//e.printStackTrace();
-			}
-		}
-	}
-	
-	public void setPrivateFromHTML(String privateTorrent) {
-		if(privateTorrent != null && ! "".equals(privateTorrent)) {
-			this.privateTorrent = true;
-		}
-	}
-	
-	public int
-	getVotes()
-	{
-		return( votes );
-	}
-	
-	public int
-	getVotesDown()
-	{
-		return( votesDown );
-	}
-	
-	public void setCDPLink(String cdpLink) {
-		this.cdpLink = UrlUtils.unescapeXML(cdpLink);
-	}
-	
-	public void setDownloadButtonLink(String downloadButtonLink) {
-		this.downloadButtonLink = UrlUtils.unescapeXML(downloadButtonLink);
-	}
-	
-	public void setTorrentLink(String torrentLink) {
-		this.torrentLink = UrlUtils.unescapeXML(torrentLink);
-	}
-	
-	public void setPlayLink(String playLink) {
-		this.playLink = playLink;
-	}
-	
-	public String getContentType() {
-		return this.contentType;
-	}
-	
-	public String getPlayLink() {
-		return( reConstructLink(  playLink ));
-	}
-	
-	public void setCategory(String category) {
-		this.category = category;
-		
-	}
-	
-	public void setContentType(String contentType) {
-		this.contentType = contentType;
-		
-	}
-	
-	public void setDrmKey(String drmKey) {
-		this.drmKey = drmKey;
-	}
-	
-	public void
-	setHash(
-		String	_hash )
-	{
-		try{
-			hash = _hash.trim();
-			
-			if ( hash.length() == 32 ){
-				
-					// base 32 hash
-				
-			}else if ( hash.length() == 40 ){
-				
-					// base 16
-				
-				hash = Base32.encode( ByteFormatter.decodeString( hash ));
-				
-			}else{
-				
-				hash = null;
-			}
-		}catch( Throwable e ){
-			
-			Debug.printStackTrace(e);
-			
-			hash = null;
-		}
-		
-		if(hash != null && downloadButtonLink == null) {
-			setDownloadButtonLink(UrlUtils.normaliseMagnetURI(hash));			
-		}
-		if(hash != null && torrentLink == null) {
-			setTorrentLink(UrlUtils.normaliseMagnetURI(hash));			
-		}
-	}
-	
-	public String
-	getHash()
-	{
-		return( hash );
-	}
-
-	public String getCDPLink() {
-		
-		return reConstructLink(cdpLink);
-	}
-
-	public String getCategory() {
-		return category;
-	}
-
-	public String getDownloadLink() {
-
-		return reConstructLink(torrentLink);
-		
-	}
-	
-	public String getDownloadButtonLink() {
-
-		//If we don't have a download button link, but we do have a direct download link,
-		//then we should use the direct download link...
-		if(downloadButtonLink != null) {
-			return reConstructLink(downloadButtonLink);
-		} else {
-			return getDownloadLink();
-		}
-		
-	}
-	
-	private String 
-	reConstructLink(
-		String link) 
-	{
-		if ( link != null ){
-			
-			String lc_link = link.toLowerCase();
-			
-			if ( 	lc_link.startsWith("http://") || 
-					lc_link.startsWith("https://") ||
-					lc_link.startsWith("azplug:") ||
-					lc_link.startsWith("magnet:") ||
-					lc_link.startsWith("bc:") ||
-					lc_link.startsWith("bctp:") ||
-					lc_link.startsWith("dht:" )){
-				
-				return( link );
-			}
-			
-			if ( link.startsWith("/")){
-				
-				return((rootPageURL==null?"":rootPageURL) + link );
-			}
-			
-			return((basePageURL==null?"":basePageURL) + link );
-		}
-		
-		return( "" );
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public int getNbPeers() {
-		return nbPeers;
-	}
-
-	public int getNbSeeds() {
-		return nbSeeds;
-	}
-	
-	public int getNbSuperSeeds() {
-		return nbSuperSeeds;
-	}
-
-	public Date getPublishedDate() {
-		return publishedDate;
-	}
-
-	public long getSize() {
-		return size;
-	}
-	
-	public int
-	getComments()
-	{
-		return( comments );
-	}
-	
-	public String getSearchQuery() {
-		return searchQuery;
-	}
-	
-	public boolean isPrivate() {
-		return privateTorrent;
-	}
-	
-	public String getDRMKey() {
-		return drmKey;
-	}
-	
-	public float getAccuracy() {
-		return -1;
-	}
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl.web;
+
+import java.util.Date;
+import java.util.StringTokenizer;
+
+import org.apache.commons.lang.*;
+import org.gudy.azureus2.core3.util.Base32;
+import org.gudy.azureus2.core3.util.ByteFormatter;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.UrlUtils;
+
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.Result;
+import com.aelitis.azureus.core.metasearch.impl.DateParser;
+
+public class WebResult extends Result {
+	
+	
+	
+	String searchQuery;
+	
+	String rootPageURL;
+	String basePageURL;
+	DateParser dateParser;
+	
+	
+	String contentType = "";
+	String name;
+	String category = "";
+	
+	String drmKey = null;
+	
+	Date publishedDate;
+	
+	long size = -1;
+	int nbPeers = -1;
+	int nbSeeds = -1;
+	int nbSuperSeeds = -1;
+	int	comments	= -1;
+	int votes = -1;
+	int votesDown = -1;
+	float rank = -1;
+	
+	boolean privateTorrent;
+	
+	String cdpLink;
+	String torrentLink;
+	String downloadButtonLink;
+	String playLink;
+	
+	String uid;
+	String hash;
+	
+	public WebResult(Engine engine, String rootPageURL,String basePageURL,DateParser dateParser,String searchQuery) {
+		super( engine );
+		this.rootPageURL = rootPageURL;
+		this.basePageURL = basePageURL;
+		this.dateParser = dateParser;
+		this.searchQuery = searchQuery;
+	}
+		
+	public void setName(String name) {
+		if(name != null) {
+			this.name = name;
+		}
+	}
+	
+	public void setNameFromHTML(String name) {
+		if(name != null) {
+			name = removeHTMLTags(name);
+			this.name = Entities.HTML40.unescape(name);
+		}
+	}
+	
+	public void setCommentsFromHTML(String comments) {
+		if(comments != null) {
+			comments = removeHTMLTags(comments);
+			comments = Entities.HTML40.unescape(comments);
+			comments = comments.replaceAll(",", "");
+			comments = comments.replaceAll(" ", "");
+			try{
+				this.comments = Integer.parseInt(comments);
+			}catch( Throwable e ){
+				//e.printStackTrace();
+			}
+		}
+	}
+	public void setCategoryFromHTML(String category) {
+		if(category != null) {
+			category = removeHTMLTags(category);
+			this.category = Entities.HTML40.unescape(category).trim();
+			/*int separator = this.category.indexOf(">");
+			
+			if(separator != -1) {
+				this.category = this.category.substring(separator+1).trim();
+			}*/
+		}
+	}
+	
+	public void
+	setUID(
+		String	_uid )
+	{
+		uid	= _uid;
+	}
+	
+	public String
+	getUID()
+	{
+		return( uid );
+	}
+	
+	public void setNbPeersFromHTML(String nbPeers) {
+		if(nbPeers != null) {
+			nbPeers = removeHTMLTags(nbPeers);
+			String nbPeersS = Entities.HTML40.unescape(nbPeers);
+			nbPeersS = nbPeersS.replaceAll(",", "");
+			nbPeersS = nbPeersS.replaceAll(" ", "");
+			try {
+				this.nbPeers = Integer.parseInt(nbPeersS);
+			} catch(Throwable e) {
+				//this.nbPeers = 0;
+				//e.printStackTrace();
+			}
+		}
+	}	
+	
+	public void setNbSeedsFromHTML(String nbSeeds) {
+		if(nbSeeds != null) {
+			nbSeeds = removeHTMLTags(nbSeeds);
+			String nbSeedsS = Entities.HTML40.unescape(nbSeeds);
+			nbSeedsS = nbSeedsS.replaceAll(",", "");
+			nbSeedsS = nbSeedsS.replaceAll(" ", "");
+			try {
+				this.nbSeeds = Integer.parseInt(nbSeedsS);
+			} catch(Throwable e) {
+				//this.nbSeeds = 0;
+				//e.printStackTrace();
+			}
+		}
+	}
+	
+	public void setNbSuperSeedsFromHTML(String nbSuperSeeds) {
+		if(nbSuperSeeds != null) {
+			nbSuperSeeds = removeHTMLTags(nbSuperSeeds);
+			String nbSuperSeedsS = Entities.HTML40.unescape(nbSuperSeeds);
+			nbSuperSeedsS = nbSuperSeedsS.replaceAll(",", "");
+			nbSuperSeedsS = nbSuperSeedsS.replaceAll(" ", "");
+			try {
+				this.nbSuperSeeds = Integer.parseInt(nbSuperSeedsS);
+			} catch(Throwable e) {
+				//this.nbSeeds = 0;
+				//e.printStackTrace();
+			}
+		}
+	}
+
+	public void setRankFromHTML( String rank_str, float divisor ){
+		if (rank_str == null) {
+			return;
+		}
+		try{
+			float f = Float.parseFloat( rank_str.trim() );
+			
+			rank = f / divisor;
+		}catch( Throwable e ){
+		}
+	}
+
+	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( applyRankBias( rank ));
+		}
+		
+		return( super.getRank());
+	}
+	
+	public void setPublishedDate(Date date) {
+		this.publishedDate = date;
+	}
+	
+	public void setPublishedDateFromHTML(String publishedDate) {
+		if(publishedDate != null) {
+			publishedDate = removeHTMLTags(publishedDate);
+			String publishedDateS = Entities.HTML40.unescape(publishedDate).replace((char)160,(char)32);
+			this.publishedDate = dateParser.parseDate(publishedDateS);
+		}
+	}
+	
+
+	public void setSizeFromHTML(String size) {
+		if(size != null) {
+			size = removeHTMLTags(size);
+			String sizeS = Entities.HTML40.unescape(size).replace((char)160,(char)32);
+			sizeS = sizeS.replaceAll("<[^>]+>", " ");
+			//Add a space between the digits and unit if there is none
+			sizeS = sizeS.replaceFirst("(\\d)([a-zA-Z])", "$1 $2");
+			try {
+				StringTokenizer st = new StringTokenizer(sizeS," ");
+				double base = Double.parseDouble(st.nextToken());
+				String unit = "b";
+				try {
+					unit = st.nextToken().toLowerCase();
+				} catch(Throwable e) {
+					//No unit
+				}
+				long multiplier = 1;
+				long KB_UNIT = 1024;
+				long KIB_UNIT = 1024;
+				if("mb".equals(unit)) {
+					multiplier = KB_UNIT*KB_UNIT;
+				} else if("mib".equals(unit)) {
+					multiplier = KIB_UNIT*KIB_UNIT;
+				} else if("m".equals(unit)) {
+					multiplier = KIB_UNIT*KIB_UNIT;
+				} else if("gb".equals(unit)) {
+					multiplier = KB_UNIT*KB_UNIT*KB_UNIT;
+				} else if("gib".equals(unit)) {
+					multiplier = KIB_UNIT*KIB_UNIT*KIB_UNIT;
+				} else if("g".equals(unit)) {
+					multiplier = KIB_UNIT*KIB_UNIT*KIB_UNIT;
+				} else if("kb".equals(unit)) {
+					multiplier = KB_UNIT;
+				} else if("kib".equals(unit)) {
+					multiplier = KIB_UNIT;
+				} else if("k".equals(unit)) {
+					multiplier = KIB_UNIT;
+				}
+				
+				this.size = (long) (base * multiplier);
+			} catch(Throwable e) {
+				//e.printStackTrace();
+			}
+		}
+	}
+	
+	public void setVotesFromHTML(String votes_str) {
+		if(votes_str != null) {
+			votes_str = removeHTMLTags(votes_str);
+			votes_str = Entities.HTML40.unescape(votes_str);
+			votes_str = votes_str.replaceAll(",", "");
+			votes_str = votes_str.replaceAll(" ", "");
+			try {
+				this.votes = Integer.parseInt(votes_str);
+			} catch(Throwable e) {
+				//e.printStackTrace();
+			}
+		}
+	}	
+	
+	public void setVotesDownFromHTML(String votes_str) {
+		if(votes_str != null) {
+			votes_str = removeHTMLTags(votes_str);
+			votes_str = Entities.HTML40.unescape(votes_str);
+			votes_str = votes_str.replaceAll(",", "");
+			votes_str = votes_str.replaceAll(" ", "");
+			try {
+				this.votesDown = Integer.parseInt(votes_str);
+			} catch(Throwable e) {
+				//e.printStackTrace();
+			}
+		}
+	}
+	
+	public void setPrivateFromHTML(String privateTorrent) {
+		if(privateTorrent != null && ! "".equals(privateTorrent)) {
+			this.privateTorrent = true;
+		}
+	}
+	
+	public int
+	getVotes()
+	{
+		return( votes );
+	}
+	
+	public int
+	getVotesDown()
+	{
+		return( votesDown );
+	}
+	
+	public void setCDPLink(String cdpLink) {
+		this.cdpLink = UrlUtils.unescapeXML(cdpLink);
+	}
+	
+	public void setDownloadButtonLink(String downloadButtonLink) {
+		this.downloadButtonLink = UrlUtils.unescapeXML(downloadButtonLink);
+	}
+	
+	public void setTorrentLink(String torrentLink) {
+		this.torrentLink = UrlUtils.unescapeXML(torrentLink);
+	}
+	
+	public void setPlayLink(String playLink) {
+		this.playLink = playLink;
+	}
+	
+	public String getContentType() {
+		return this.contentType;
+	}
+	
+	public String getPlayLink() {
+		return( reConstructLink(  playLink ));
+	}
+	
+	public void setCategory(String category) {
+		this.category = category;
+		
+	}
+	
+	public void setContentType(String contentType) {
+		this.contentType = contentType;
+		
+	}
+	
+	public void setDrmKey(String drmKey) {
+		this.drmKey = drmKey;
+	}
+	
+	public void
+	setHash(
+		String	_hash )
+	{
+		try{
+			hash = _hash.trim();
+			
+			if ( hash.length() == 32 ){
+				
+					// base 32 hash
+				
+			}else if ( hash.length() == 40 ){
+				
+					// base 16
+				
+				hash = Base32.encode( ByteFormatter.decodeString( hash ));
+				
+			}else{
+				
+				hash = null;
+			}
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+			
+			hash = null;
+		}
+		
+		if(hash != null && downloadButtonLink == null) {
+			setDownloadButtonLink(UrlUtils.normaliseMagnetURI(hash));			
+		}
+		if(hash != null && torrentLink == null) {
+			setTorrentLink(UrlUtils.normaliseMagnetURI(hash));			
+		}
+	}
+	
+	public String
+	getHash()
+	{
+		return( hash );
+	}
+
+	public String getCDPLink() {
+		
+		return reConstructLink(cdpLink);
+	}
+
+	public String getCategory() {
+		return category;
+	}
+
+	public String getDownloadLink() {
+
+		return reConstructLink(torrentLink);
+		
+	}
+	
+	public String getDownloadButtonLink() {
+
+		//If we don't have a download button link, but we do have a direct download link,
+		//then we should use the direct download link...
+		if(downloadButtonLink != null) {
+			return reConstructLink(downloadButtonLink);
+		} else {
+			return getDownloadLink();
+		}
+		
+	}
+	
+	private String 
+	reConstructLink(
+		String link) 
+	{
+		if ( link != null ){
+			
+			String lc_link = link.toLowerCase();
+			
+			if ( 	lc_link.startsWith("http://") || 
+					lc_link.startsWith("https://") ||
+					lc_link.startsWith("tor:http://") || 
+					lc_link.startsWith("tor:https://") || 
+					lc_link.startsWith("azplug:") ||
+					lc_link.startsWith("magnet:") ||
+					lc_link.startsWith("bc:") ||
+					lc_link.startsWith("bctp:") ||
+					lc_link.startsWith("dht:" )){
+				
+				return( link );
+			}
+			
+			if ( link.startsWith("/")){
+				
+				return((rootPageURL==null?"":rootPageURL) + link );
+			}
+			
+			return((basePageURL==null?"":basePageURL) + link );
+		}
+		
+		return( "" );
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public int getNbPeers() {
+		return nbPeers;
+	}
+
+	public int getNbSeeds() {
+		return nbSeeds;
+	}
+	
+	public int getNbSuperSeeds() {
+		return nbSuperSeeds;
+	}
+
+	public Date getPublishedDate() {
+		return publishedDate;
+	}
+
+	public long getSize() {
+		return size;
+	}
+	
+	public int
+	getComments()
+	{
+		return( comments );
+	}
+	
+	public String getSearchQuery() {
+		return searchQuery;
+	}
+	
+	public boolean isPrivate() {
+		return privateTorrent;
+	}
+	
+	public String getDRMKey() {
+		return drmKey;
+	}
+	
+	public float getAccuracy() {
+		return -1;
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/json/JSONEngine.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/json/JSONEngine.java
index f6661e4..647e10d 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/json/JSONEngine.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/json/JSONEngine.java
@@ -1,494 +1,505 @@
-/*
- * Created on May 6, 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.core.metasearch.impl.web.json;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.TreeMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.UrlUtils;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.json.simple.JSONValue;
-
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.Result;
-import com.aelitis.azureus.core.metasearch.ResultListener;
-import com.aelitis.azureus.core.metasearch.SearchException;
-import com.aelitis.azureus.core.metasearch.SearchParameter;
-import com.aelitis.azureus.core.metasearch.impl.EngineImpl;
-import com.aelitis.azureus.core.metasearch.impl.MetaSearchImpl;
-import com.aelitis.azureus.core.metasearch.impl.web.FieldMapping;
-import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
-import com.aelitis.azureus.core.metasearch.impl.web.WebResult;
-import com.aelitis.azureus.util.ImportExportUtils;
-
-public class 
-JSONEngine 
-	extends WebEngine 
-{
-	private final static String variablePattern = "\\$\\{[^}]+\\}";
-	private final static Pattern patternVariable = Pattern.compile(variablePattern);
-
-	public static EngineImpl
-	importFromBEncodedMap(
-		MetaSearchImpl	meta_search,
-		Map				map )
-	
-		throws IOException
-	{
-		return( new JSONEngine( meta_search, map ));
-	}
-	
-	public static Engine
-	importFromJSONString(
-		MetaSearchImpl	meta_search,
-		long			id,
-		long			last_updated,
-		float			rank_bias,
-		String			name,
-		JSONObject		map )
-	
-		throws IOException
-	{
-		return( new JSONEngine( meta_search, id, last_updated, rank_bias, name, map ));
-	}
-	
-	private String resultsEntryPath;
-	private String rankDivisorPath;
-	
-	private float rankDivisor = 1.0f;
-
-	
-		// explicit test constructor
-
-	public 
-	JSONEngine(
-		MetaSearchImpl		meta_search,
-		long 				id,
-		long 				last_updated,
-		float				rank_bias,
-		String 				name,
-		String 				searchURLFormat,
-		String 				timeZone,
-		boolean 			automaticDateFormat,
-		String 				userDateFormat,
-		String 				resultsEntryPath,
-		FieldMapping[] 		mappings,
-		boolean				needs_auth,
-		String				auth_method,
-		String				login_url,
-		String[]			required_cookies )
-	{
-		super( 	meta_search, 
-				Engine.ENGINE_TYPE_JSON, 
-				id,
-				last_updated,
-				rank_bias,
-				name,
-				searchURLFormat,
-				timeZone,
-				automaticDateFormat,
-				userDateFormat,
-				mappings,
-				needs_auth,
-				auth_method,
-				login_url,
-				required_cookies );		
-		
-		this.resultsEntryPath = resultsEntryPath;
-		
-		setSource( Engine.ENGINE_SOURCE_LOCAL );
-		
-		setSelectionState( SEL_STATE_MANUAL_SELECTED );
-	}
-	
-		// bencoded constructor
-	
-	protected 
-	JSONEngine(
-		MetaSearchImpl	meta_search,
-		Map				map )
-	
-		throws IOException
-	{
-		super( meta_search, map );
-		
-		resultsEntryPath = ImportExportUtils.importString( map, "json.path" );
-		rankDivisorPath = ImportExportUtils.importString( map, "rank.divisor.path" );
-	}
-	
-		// json constructor
-	
-	protected 
-	JSONEngine(
-		MetaSearchImpl	meta_search,
-		long			id,
-		long			last_updated,
-		float			rank_bias,
-		String			name,
-		JSONObject		map )
-	
-		throws IOException
-	{
-		super( meta_search, Engine.ENGINE_TYPE_JSON, id, last_updated, rank_bias, name, map );
-				
-		resultsEntryPath = ImportExportUtils.importString( map, "json_result_key" );
-		rankDivisorPath = ImportExportUtils.importString( map, "rank_divisor_key" );
-	}
-	
-	public Map 
-	exportToBencodedMap()
-	
-		throws IOException
-	{
-		return( exportToBencodedMap( false ));
-	}
-	
-	public Map 
-	exportToBencodedMap(
-		boolean		generic )
-	
-		throws IOException
-	{
-		Map	res = new HashMap();
-		
-		ImportExportUtils.exportString( res, "json.path", resultsEntryPath );
-		
-		ImportExportUtils.exportString(res, "rank.divisor.path", rankDivisorPath);
-		
-		super.exportToBencodedMap( res, generic );
-		
-		return( res );
-	}
-	
-	protected void
-	exportToJSONObject(
-		JSONObject		res )
-	
-		throws IOException
-	{
-		res.put( "json_result_key", resultsEntryPath );
-		
-		res.put("rank_divisor_key", rankDivisorPath);
-
-		super.exportToJSONObject( res );
-	}
-	
-	protected Result[]
-	searchSupport(
-		SearchParameter[] 	searchParameters,
-		Map					searchContext,
-		int					desired_max_matches,
-		int					absolute_max_matches,
-		String				headers, 
-		ResultListener		listener )
-	
-		throws SearchException
-	{	
-		debugStart();
-		
-		pageDetails page_details = super.getWebPageContent( searchParameters, searchContext, headers, false );
-		
-		String	page = page_details.getContent();
-		
-		if ( listener != null ){
-			listener.contentReceived( this, page );
-		}
-		
-		
-		String searchQuery = null;
-		
-		for(int i = 0 ; i < searchParameters.length ; i++) {
-			if(searchParameters[i].getMatchPattern().equals("s")) {
-				searchQuery = searchParameters[i].getValue();
-			}
-		}
-		
-		FieldMapping[] mappings = getMappings();
-
-		try {
-			Object jsonObject;
-			
-			try{
-				jsonObject = JSONValue.parse(page);
-				
-			}catch( Throwable e ){
-				
-					// fix a vaguely common error: trailing \ before end-of-string:    - \",  
-				
-				String temp_page = page.replaceAll( "\\\\\",", "\"," );
-				
-				try{
-					jsonObject = JSONValue.parse( temp_page );
-					
-				}catch( Throwable f ){
-					
-					throw( e );
-				}
-			}
-						
-			if (rankDivisorPath != null) {
-				String[] split = rankDivisorPath.split("\\.");
-				try {
-					if (split.length > 0) {
-						Object jsonRankDivisor = jsonObject;
-  					for (int i = 0; i < split.length - 1; i++) {
-  						String key = split[i];
-  						jsonRankDivisor = ((JSONObject)jsonRankDivisor).get(key);
-  					}
-  					if (jsonRankDivisor instanceof Map) {
-  						jsonRankDivisor = ((Map) jsonRankDivisor).get(split[split.length - 1]);
-  					}
-  					
-  					rankDivisor = ((Number) jsonRankDivisor).floatValue();
-					}
-				} catch (Exception e) {
-				}
-			}
-
-			JSONArray resultArray = null;
-			
-			if(resultsEntryPath != null) {
-				StringTokenizer st = new StringTokenizer(resultsEntryPath,".");
-				if(jsonObject instanceof JSONArray && st.countTokens() > 0) {
-					JSONArray array = (JSONArray) jsonObject;
-					if(array.size() == 1) {
-						jsonObject = array.get(0);
-					}
-				}
-				while(st.hasMoreTokens()) {
-					try {
-						jsonObject = ((JSONObject)jsonObject).get(st.nextToken());
-					} catch(Throwable t) {
-						throw new SearchException("Invalid entry path : " + resultsEntryPath,t);
-					}
-				}
-			}
-			
-			try{
-				resultArray = (JSONArray) jsonObject;
-				
-			}catch(Throwable t){
-				
-				throw new SearchException("Object is not a result array. Check the JSON service and/or the entry path");
-			}
-
-				
-			if ( resultArray != null ){
-				
-				List results = new ArrayList();
-				
-				Throwable	decode_failure 		= null;
-				
-				for(int i = 0 ; i < resultArray.size() ; i++) {
-					
-					Object obj = resultArray.get(i);
-					
-					if(obj instanceof JSONObject) {
-						JSONObject jsonEntry = (JSONObject) obj;
-						
-						if ( absolute_max_matches >= 0 ){
-							if ( --absolute_max_matches < 0 ){
-								break;
-							}
-						}
-						
-						if ( listener != null ){
-							
-								// sort for consistent order
-							
-							Iterator it = new TreeMap( jsonEntry ).entrySet().iterator();
-							
-							String[]	groups = new String[ jsonEntry.size()];
-							
-							int	pos = 0;
-							
-							while( it.hasNext()){
-								
-								Map.Entry entry = (Map.Entry)it.next();
-								
-								Object key 		= entry.getKey();
-								Object value 	= entry.getValue();
-								
-								if ( key != null && value != null ){
-								
-									groups[pos++] = key.toString() + "=" + UrlUtils.encode( value.toString());
-									
-								}else{
-									
-									groups[pos++] = "";
-								}
-							}
-							
-							listener.matchFound( this, groups );
-						}
-						
-						WebResult result = new WebResult(this,getRootPage(),getBasePage(),getDateParser(),searchQuery);
-							
-						try{
-							for(int j = 0 ; j < mappings.length ; j++) {
-								String fieldFrom = mappings[j].getName();
-								if(fieldFrom != null) {
-									int fieldTo = mappings[j].getField();
-									
-									String fieldContent = null;
-									Matcher matcher = patternVariable.matcher(fieldFrom);
-									if (matcher.find()) {
-										fieldContent = fieldFrom;
-										do {
-											String key = matcher.group();
-											key = key.substring(2, key.length() - 1);
-											Object replaceValObject = jsonEntry.get(key);
-											String replaceVal = replaceValObject == null ? ""
-													: replaceValObject.toString();
-											fieldContent = fieldContent.replaceFirst(variablePattern,
-													replaceVal);
-										} while (matcher.find());
-									} else {
-										Object fieldContentObj = jsonEntry.get(fieldFrom);
-										fieldContent = fieldContentObj == null ? ""
-												: fieldContentObj.toString();
-									}
-									if(fieldContent != null) {
-										
-										switch(fieldTo) {
-										case FIELD_NAME :
-											result.setNameFromHTML(fieldContent);
-											break;
-										case FIELD_SIZE :
-											result.setSizeFromHTML(fieldContent);
-											break;
-										case FIELD_PEERS :
-											result.setNbPeersFromHTML(fieldContent);
-											break;
-										case FIELD_SEEDS :
-											result.setNbSeedsFromHTML(fieldContent);
-											break;
-										case FIELD_CATEGORY :
-											result.setCategoryFromHTML(fieldContent);
-											break;
-										case FIELD_DATE :
-											result.setPublishedDateFromHTML(fieldContent);
-											break;
-										case FIELD_COMMENTS :
-											result.setCommentsFromHTML(fieldContent);
-											break;
-										case FIELD_CDPLINK :
-											result.setCDPLink(fieldContent);
-											break;
-										case FIELD_TORRENTLINK :
-											result.setTorrentLink(fieldContent);
-											break;
-										case FIELD_PLAYLINK :
-											result.setPlayLink(fieldContent);
-											break;
-										case FIELD_DOWNLOADBTNLINK :
-											result.setDownloadButtonLink(fieldContent);
-											break;
-										case FIELD_VOTES :
-											result.setVotesFromHTML(fieldContent);
-											break;
-										case FIELD_SUPERSEEDS :
-											result.setNbSuperSeedsFromHTML(fieldContent);
-											break;
-										case FIELD_PRIVATE :
-											result.setPrivateFromHTML(fieldContent);
-											break;
-										case FIELD_DRMKEY :
-											result.setDrmKey(fieldContent);
-											break;
-										case FIELD_VOTES_DOWN :
-											result.setVotesDownFromHTML(fieldContent);
-											break;
-										case FIELD_HASH :
-											result.setHash(fieldContent);
-											break;
-										case FIELD_RANK : {
-											result.setRankFromHTML(fieldContent, rankDivisor);
-											break;
-										}
-										default:
-											break;
-										}
-									}
-								}
-							}
-														
-							results.add(result);
-							
-						}catch( Throwable e ){
-							
-							decode_failure = e;
-						}
-					}
-				}
-				
-				if ( results.size() == 0 && decode_failure != null ){
-					
-					throw( decode_failure );
-				}
-				
-				Result[] res = (Result[]) results.toArray(new Result[results.size()]);
-
-				debugLog( "success: found " + res.length + " results" );
-				
-				return( res );
-				
-			}else{
-			
-				debugLog( "success: no result array found so no results" );
-				
-				return( new Result[0]);
-			}
-			
-		}catch( Throwable e ){
-			
-			debugLog( "failed: " + Debug.getNestedExceptionMessageAndStack( e ));
-			
-			if ( e instanceof SearchException ){
-				
-				throw((SearchException)e );
-			}
-			
-			String content_str = page;
-			
-			if ( content_str.length() > 256 ){
-				
-				content_str = content_str.substring( 0, 256 ) + "...";
-			}
-			
-			//System.out.println( page );
-			
-			throw( new SearchException( "JSON matching failed for " + getName() + ", content=" + content_str, e ));
-		}
-	}
-	
-
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl.web.json;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.UrlUtils;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.Result;
+import com.aelitis.azureus.core.metasearch.ResultListener;
+import com.aelitis.azureus.core.metasearch.SearchException;
+import com.aelitis.azureus.core.metasearch.SearchParameter;
+import com.aelitis.azureus.core.metasearch.impl.EngineImpl;
+import com.aelitis.azureus.core.metasearch.impl.MetaSearchImpl;
+import com.aelitis.azureus.core.metasearch.impl.web.FieldMapping;
+import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
+import com.aelitis.azureus.core.metasearch.impl.web.WebResult;
+import com.aelitis.azureus.util.ImportExportUtils;
+
+public class 
+JSONEngine 
+	extends WebEngine 
+{
+	private final static String variablePattern = "\\$\\{[^}]+\\}";
+	private final static Pattern patternVariable = Pattern.compile(variablePattern);
+
+	public static EngineImpl
+	importFromBEncodedMap(
+		MetaSearchImpl	meta_search,
+		Map				map )
+	
+		throws IOException
+	{
+		return( new JSONEngine( meta_search, map ));
+	}
+	
+	public static Engine
+	importFromJSONString(
+		MetaSearchImpl	meta_search,
+		long			id,
+		long			last_updated,
+		float			rank_bias,
+		String			name,
+		JSONObject		map )
+	
+		throws IOException
+	{
+		return( new JSONEngine( meta_search, id, last_updated, rank_bias, name, map ));
+	}
+	
+	private String resultsEntryPath;
+	private String rankDivisorPath;
+	
+	private float rankDivisor = 1.0f;
+
+	
+		// explicit test constructor
+
+	public 
+	JSONEngine(
+		MetaSearchImpl		meta_search,
+		long 				id,
+		long 				last_updated,
+		float				rank_bias,
+		String 				name,
+		String 				searchURLFormat,
+		String 				timeZone,
+		boolean 			automaticDateFormat,
+		String 				userDateFormat,
+		String 				resultsEntryPath,
+		FieldMapping[] 		mappings,
+		boolean				needs_auth,
+		String				auth_method,
+		String				login_url,
+		String[]			required_cookies )
+	{
+		super( 	meta_search, 
+				Engine.ENGINE_TYPE_JSON, 
+				id,
+				last_updated,
+				rank_bias,
+				name,
+				searchURLFormat,
+				timeZone,
+				automaticDateFormat,
+				userDateFormat,
+				mappings,
+				needs_auth,
+				auth_method,
+				login_url,
+				required_cookies );		
+		
+		this.resultsEntryPath = resultsEntryPath;
+		
+		setSource( Engine.ENGINE_SOURCE_LOCAL );
+		
+		setSelectionState( SEL_STATE_MANUAL_SELECTED );
+	}
+	
+		// bencoded constructor
+	
+	protected 
+	JSONEngine(
+		MetaSearchImpl	meta_search,
+		Map				map )
+	
+		throws IOException
+	{
+		super( meta_search, map );
+		
+		resultsEntryPath = ImportExportUtils.importString( map, "json.path" );
+		rankDivisorPath = ImportExportUtils.importString( map, "rank.divisor.path" );
+	}
+	
+		// json constructor
+	
+	protected 
+	JSONEngine(
+		MetaSearchImpl	meta_search,
+		long			id,
+		long			last_updated,
+		float			rank_bias,
+		String			name,
+		JSONObject		map )
+	
+		throws IOException
+	{
+		super( meta_search, Engine.ENGINE_TYPE_JSON, id, last_updated, rank_bias, name, map );
+				
+		resultsEntryPath = ImportExportUtils.importString( map, "json_result_key" );
+		resultsEntryPath = UrlUtils.decode(resultsEntryPath);
+		rankDivisorPath = ImportExportUtils.importString( map, "rank_divisor_key" );
+	}
+	
+	public Map 
+	exportToBencodedMap()
+	
+		throws IOException
+	{
+		return( exportToBencodedMap( false ));
+	}
+	
+	public Map 
+	exportToBencodedMap(
+		boolean		generic )
+	
+		throws IOException
+	{
+		Map	res = new HashMap();
+		
+		ImportExportUtils.exportString( res, "json.path", resultsEntryPath );
+		
+		ImportExportUtils.exportString(res, "rank.divisor.path", rankDivisorPath);
+		
+		super.exportToBencodedMap( res, generic );
+		
+		return( res );
+	}
+	
+	protected void
+	exportToJSONObject(
+		JSONObject		res )
+	
+		throws IOException
+	{
+		res.put( "json_result_key", resultsEntryPath );
+		
+		res.put("rank_divisor_key", rankDivisorPath);
+
+		super.exportToJSONObject( res );
+	}
+	
+	protected Result[]
+	searchSupport(
+		SearchParameter[] 	searchParameters,
+		Map					searchContext,
+		int					desired_max_matches,
+		int					absolute_max_matches,
+		String				headers, 
+		ResultListener		listener )
+	
+		throws SearchException
+	{	
+		debugStart();
+		
+		pageDetails page_details = super.getWebPageContent( searchParameters, searchContext, headers, false );
+		
+		String	page = page_details.getContent();
+		
+		if ( listener != null ){
+			listener.contentReceived( this, page );
+		}
+		
+		
+		String searchQuery = null;
+		
+		for(int i = 0 ; i < searchParameters.length ; i++) {
+			if(searchParameters[i].getMatchPattern().equals("s")) {
+				searchQuery = searchParameters[i].getValue();
+			}
+		}
+		
+		FieldMapping[] mappings = getMappings();
+
+		try {
+			Object jsonObject;
+			
+			try{
+				jsonObject = JSONValue.parse(page);
+				
+			}catch( Throwable e ){
+				
+					// fix a vaguely common error: trailing \ before end-of-string:    - \",  
+				
+				String temp_page = page.replaceAll( "\\\\\",", "\"," );
+				
+				try{
+					jsonObject = JSONValue.parse( temp_page );
+					
+				}catch( Throwable f ){
+					
+					throw( e );
+				}
+			}
+						
+			if (rankDivisorPath != null) {
+				String[] split = rankDivisorPath.split("\\.");
+				try {
+					if (split.length > 0) {
+						Object jsonRankDivisor = jsonObject;
+  					for (int i = 0; i < split.length - 1; i++) {
+  						String key = split[i];
+  						jsonRankDivisor = ((JSONObject)jsonRankDivisor).get(key);
+  					}
+  					if (jsonRankDivisor instanceof Map) {
+  						jsonRankDivisor = ((Map) jsonRankDivisor).get(split[split.length - 1]);
+  					}
+  					
+  					rankDivisor = ((Number) jsonRankDivisor).floatValue();
+					}
+				} catch (Exception e) {
+				}
+			}
+
+			JSONArray resultArray = null;
+			
+			if(resultsEntryPath != null) {
+				String[] split = resultsEntryPath.split("\\.");
+				if(jsonObject instanceof JSONArray && split.length > 0 && !split[0].startsWith("[")) {
+					JSONArray array = (JSONArray) jsonObject;
+					if(array.size() == 1) {
+						jsonObject = array.get(0);
+					}
+				}
+				for (String pathEntry : split) {
+					if ( jsonObject == null ){
+						throw new SearchException("Invalid entry path : " + resultsEntryPath );
+					}
+					
+					try{
+						if (pathEntry.startsWith("[") && pathEntry.endsWith("]")) {
+							int idx = Integer.parseInt(pathEntry.substring(1, pathEntry.length() - 1));
+							jsonObject = ((JSONArray) jsonObject).get(idx);
+						} else {
+							jsonObject = ((JSONObject)jsonObject).get(pathEntry);
+						}
+						
+					}catch( Throwable t ){
+						
+						throw new SearchException("Invalid entry path : " + resultsEntryPath,t);
+					}
+				}
+			}
+			
+			try{
+				resultArray = (JSONArray) jsonObject;
+				
+			}catch(Throwable t){
+				
+				throw new SearchException("Object is not a result array. Check the JSON service and/or the entry path");
+			}
+
+				
+			if ( resultArray != null ){
+				
+				List results = new ArrayList();
+				
+				Throwable	decode_failure 		= null;
+				
+				for(int i = 0 ; i < resultArray.size() ; i++) {
+					
+					Object obj = resultArray.get(i);
+					
+					if(obj instanceof JSONObject) {
+						JSONObject jsonEntry = (JSONObject) obj;
+						
+						if ( absolute_max_matches >= 0 ){
+							if ( --absolute_max_matches < 0 ){
+								break;
+							}
+						}
+						
+						if ( listener != null ){
+							
+								// sort for consistent order
+							
+							Iterator it = new TreeMap( jsonEntry ).entrySet().iterator();
+							
+							String[]	groups = new String[ jsonEntry.size()];
+							
+							int	pos = 0;
+							
+							while( it.hasNext()){
+								
+								Map.Entry entry = (Map.Entry)it.next();
+								
+								Object key 		= entry.getKey();
+								Object value 	= entry.getValue();
+								
+								if ( key != null && value != null ){
+								
+									groups[pos++] = key.toString() + "=" + UrlUtils.encode( value.toString());
+									
+								}else{
+									
+									groups[pos++] = "";
+								}
+							}
+							
+							listener.matchFound( this, groups );
+						}
+						
+						WebResult result = new WebResult(this,getRootPage(),getBasePage(),getDateParser(),searchQuery);
+							
+						try{
+							for(int j = 0 ; j < mappings.length ; j++) {
+								String fieldFrom = mappings[j].getName();
+								if(fieldFrom != null) {
+									int fieldTo = mappings[j].getField();
+									
+									String fieldContent = null;
+									Matcher matcher = patternVariable.matcher(fieldFrom);
+									if (matcher.find()) {
+										fieldContent = fieldFrom;
+										do {
+											String key = matcher.group();
+											key = key.substring(2, key.length() - 1);
+											Object replaceValObject = jsonEntry.get(key);
+											String replaceVal = replaceValObject == null ? ""
+													: replaceValObject.toString();
+											fieldContent = fieldContent.replaceFirst(variablePattern,
+													replaceVal);
+										} while (matcher.find());
+									} else {
+										Object fieldContentObj = jsonEntry.get(fieldFrom);
+										fieldContent = fieldContentObj == null ? ""
+												: fieldContentObj.toString();
+									}
+									if(fieldContent != null) {
+										
+										switch(fieldTo) {
+										case FIELD_NAME :
+											result.setNameFromHTML(fieldContent);
+											break;
+										case FIELD_SIZE :
+											result.setSizeFromHTML(fieldContent);
+											break;
+										case FIELD_PEERS :
+											result.setNbPeersFromHTML(fieldContent);
+											break;
+										case FIELD_SEEDS :
+											result.setNbSeedsFromHTML(fieldContent);
+											break;
+										case FIELD_CATEGORY :
+											result.setCategoryFromHTML(fieldContent);
+											break;
+										case FIELD_DATE :
+											result.setPublishedDateFromHTML(fieldContent);
+											break;
+										case FIELD_COMMENTS :
+											result.setCommentsFromHTML(fieldContent);
+											break;
+										case FIELD_CDPLINK :
+											result.setCDPLink(fieldContent);
+											break;
+										case FIELD_TORRENTLINK :
+											result.setTorrentLink(fieldContent);
+											break;
+										case FIELD_PLAYLINK :
+											result.setPlayLink(fieldContent);
+											break;
+										case FIELD_DOWNLOADBTNLINK :
+											result.setDownloadButtonLink(fieldContent);
+											break;
+										case FIELD_VOTES :
+											result.setVotesFromHTML(fieldContent);
+											break;
+										case FIELD_SUPERSEEDS :
+											result.setNbSuperSeedsFromHTML(fieldContent);
+											break;
+										case FIELD_PRIVATE :
+											result.setPrivateFromHTML(fieldContent);
+											break;
+										case FIELD_DRMKEY :
+											result.setDrmKey(fieldContent);
+											break;
+										case FIELD_VOTES_DOWN :
+											result.setVotesDownFromHTML(fieldContent);
+											break;
+										case FIELD_HASH :
+											result.setHash(fieldContent);
+											break;
+										case FIELD_RANK : {
+											result.setRankFromHTML(fieldContent, rankDivisor);
+											break;
+										}
+										default:
+											break;
+										}
+									}
+								}
+							}
+														
+							results.add(result);
+							
+						}catch( Throwable e ){
+							
+							decode_failure = e;
+						}
+					}
+				}
+				
+				if ( results.size() == 0 && decode_failure != null ){
+					
+					throw( decode_failure );
+				}
+				
+				Result[] res = (Result[]) results.toArray(new Result[results.size()]);
+
+				debugLog( "success: found " + res.length + " results" );
+				
+				return( res );
+				
+			}else{
+			
+				debugLog( "success: no result array found so no results" );
+				
+				return( new Result[0]);
+			}
+			
+		}catch( Throwable e ){
+			
+			debugLog( "failed: " + Debug.getNestedExceptionMessageAndStack( e ));
+			
+			if ( e instanceof SearchException ){
+				
+				throw((SearchException)e );
+			}
+			
+			String content_str = page;
+			
+			if ( content_str.length() > 256 ){
+				
+				content_str = content_str.substring( 0, 256 ) + "...";
+			}
+			
+			//System.out.println( page );
+			
+			throw( new SearchException( "JSON matching failed for " + getName() + ", content=" + content_str, e ));
+		}
+	}
+	
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/regex/RegexEngine.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/regex/RegexEngine.java
index a986591..f49fcde 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/regex/RegexEngine.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/regex/RegexEngine.java
@@ -1,564 +1,567 @@
-/*
- * Created on May 6, 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.core.metasearch.impl.web.regex;
-
-import java.io.*;
-import java.net.URLDecoder;
-import java.util.*;
-import java.util.regex.*;
-
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.TimeLimitedTask;
-import org.gudy.azureus2.core3.util.UrlUtils;
-import org.json.simple.JSONObject;
-
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.Result;
-import com.aelitis.azureus.core.metasearch.ResultListener;
-import com.aelitis.azureus.core.metasearch.SearchException;
-import com.aelitis.azureus.core.metasearch.SearchLoginException;
-import com.aelitis.azureus.core.metasearch.SearchParameter;
-import com.aelitis.azureus.core.metasearch.impl.EngineImpl;
-import com.aelitis.azureus.core.metasearch.impl.MetaSearchImpl;
-import com.aelitis.azureus.core.metasearch.impl.web.FieldMapping;
-import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
-import com.aelitis.azureus.core.metasearch.impl.web.WebResult;
-import com.aelitis.azureus.util.ImportExportUtils;
-
-public class 
-RegexEngine 
-	extends WebEngine 
-{	
-	private final static String variablePattern = "\\$\\{[^}]+\\}";
-	private final static Pattern patternVariable = Pattern.compile(variablePattern);
-	
-	public static EngineImpl
-	importFromBEncodedMap(
-		MetaSearchImpl		meta_search,
-		Map					map )
-	
-		throws IOException
-	{
-		return( new RegexEngine( meta_search, map ));
-	}
-	
-	public static Engine
-	importFromJSONString(
-		MetaSearchImpl		meta_search,
-		long				id,
-		long				last_updated,
-		float				rank_bias,
-		String				name,
-		JSONObject			map )
-	
-		throws IOException
-	{
-		return( new RegexEngine( meta_search, id, last_updated, rank_bias, name, map ));
-	}
-
-	private String		pattern_str;
-	private Pattern[] 	patterns = {};
-
-	
-		// explicit test constructor
-	
-	public 
-	RegexEngine(
-		MetaSearchImpl		meta_search,
-		long 				id,
-		long 				last_updated,
-		float				rank_bias,
-		String 				name,
-		String 				searchURLFormat,
-		String 				resultPattern,
-		String 				timeZone,
-		boolean 			automaticDateFormat,
-		String 				userDateFormat,
-		FieldMapping[] 		mappings,
-		boolean				needs_auth,
-		String				auth_method,
-		String				login_url,
-		String[]			required_cookies )
-	{
-		super( 	meta_search, 
-				Engine.ENGINE_TYPE_REGEX, 
-				id,
-				last_updated,
-				rank_bias,
-				name,
-				searchURLFormat,
-				timeZone,
-				automaticDateFormat,
-				userDateFormat, 
-				mappings,
-				needs_auth,
-				auth_method,
-				login_url,
-				required_cookies );		
-
-		init( resultPattern );
-		
-		setSource( ENGINE_SOURCE_LOCAL );
-		
-		setSelectionState( SEL_STATE_MANUAL_SELECTED );
-	}
-	
-		// bencoded 
-	
-	protected 
-	RegexEngine(
-		MetaSearchImpl		meta_search,
-		Map					map )
-	
-		throws IOException
-	{
-		super( meta_search, map );
-		
-		String	resultPattern = ImportExportUtils.importString( map, "regex.pattern" );
-
-		init( resultPattern );
-	}
-	
-		// json
-	
-	protected 
-	RegexEngine(
-		MetaSearchImpl		meta_search,
-		long				id,
-		long				last_updated,
-		float				rank_bias,
-		String				name,
-		JSONObject			map )
-	
-		throws IOException
-	{
-		super( meta_search, Engine.ENGINE_TYPE_REGEX, id, last_updated, rank_bias, name, map );
-		
-		String	resultPattern = ImportExportUtils.importString( map, "regexp" );
-
-		resultPattern = URLDecoder.decode( resultPattern, "UTF-8" );
-		
-		init( resultPattern );
-	}
-	
-	public Map 
-	exportToBencodedMap()
-	
-		throws IOException
-	{
-		return( exportToBencodedMap( false ));
-	}
-	
-	public Map 
-	exportToBencodedMap(
-		boolean		generic ) 
-	
-		throws IOException
-	{
-		Map	res = new HashMap();
-		
-		ImportExportUtils.exportString( res, "regex.pattern", pattern_str );
-		
-		super.exportToBencodedMap( res, generic );
-		
-		return( res );
-	}
-
-	protected void
-	exportToJSONObject(
-		JSONObject		res )
-	
-		throws IOException
-	{
-		res.put( "regexp", UrlUtils.encode( pattern_str ));
-
-		super.exportToJSONObject( res );
-	}
-	
-	protected void
-	init(
-		String			resultPattern )
-	{
-		pattern_str 	= resultPattern.trim();
-		patterns = new Pattern[]{
-				
-			Pattern.compile( pattern_str),
-			Pattern.compile( pattern_str, Pattern.DOTALL | Pattern.MULTILINE )
-		};
-	}
-	
-	protected Result[] 
-	searchSupport(
-		final SearchParameter[] 	searchParameters,
-		Map							searchContext,
-		final int					desired_max_matches,
-		final int					o_absolute_max_matches,
-		final String				headers,
-		final ResultListener		listener )
-	
-		throws SearchException 
-	{
-		debugStart();
-				
-		final pageDetails page_details = getWebPageContent( searchParameters, searchContext, headers, false );
-		
-		final String	page = page_details.getContent();
-		
-		if ( listener != null ){
-			
-			listener.contentReceived( this, page );
-		}
-		
-		debugLog( "pattern: " + pattern_str );
-		
-		/*
-		if ( getId() == 3 ){
-			
-			writeToFile( "C:\\temp\\template.txt", page );
-			writeToFile( "C:\\temp\\pattern.txt", pattern.pattern());
-			
-			String page2 = readFile( "C:\\temp\\template.txt" );
-			
-			Set s1 = new HashSet();
-			Set s2 = new HashSet();
-			
-			for (int i=0;i<page.length();i++){
-				s1.add( new Character( page.charAt(i)));
-			}
-			for (int i=0;i<page2.length();i++){
-				s2.add( new Character( page2.charAt(i)));
-			}
-			
-			s1.removeAll(s2);
-			
-			Iterator it = s1.iterator();
-			
-			while( it.hasNext()){
-				
-				Character c = (Character)it.next();
-				
-				System.out.println( "diff: " + c + "/" + (int)c.charValue());
-			}
-			
-		}
-		
-		try{
-			regexptest();
-		}catch( Throwable e ){
-			
-		}
-		 */
-				
-		try{
-			TimeLimitedTask task = new TimeLimitedTask(
-				"MetaSearch:regexpr",
-				30*1000,
-				Thread.NORM_PRIORITY - 1,
-				new TimeLimitedTask.task()
-				{
-					public Object
-					run()
-					
-						throws Exception
-					{
-						int	max_matches = o_absolute_max_matches;
-								
-						if ( max_matches < 0 || max_matches > 1024 ){
-							
-							max_matches = 1024;
-						}
-						
-						String searchQuery = null;
-						
-						for(int i = 0 ; i < searchParameters.length ; i++) {
-							if(searchParameters[i].getMatchPattern().equals("s")) {
-								searchQuery = searchParameters[i].getValue();
-							}
-						}
-						
-						
-						FieldMapping[] mappings = getMappings();
-	
-						try{						
-							List results = new ArrayList();
-								
-							for ( int pat_num=0;pat_num<patterns.length;pat_num++){
-								
-									// only try subsequent patterns if all previous have failed to 
-									// find results
-								
-								if ( results.size() > 0 ){
-									
-									break;
-								}
-								
-								Pattern pattern = patterns[pat_num];
-								
-								Matcher m = pattern.matcher( page );
-									
-								while( m.find()){
-									
-									if ( max_matches >= 0 ){
-										if ( --max_matches < 0 ){
-											break;
-										}
-									}
-									
-									if ( listener != null ){
-										
-										String[]	groups = new String[m.groupCount()];
-										
-										for (int i=0;i<groups.length;i++){
-											
-											groups[i] = m.group(i+1);
-										}
-										
-										listener.matchFound( RegexEngine.this, groups );
-									}
-									
-									debugLog( "Found match:" );
-									
-									WebResult result = new WebResult(RegexEngine.this,getRootPage(),getBasePage(),getDateParser(),searchQuery);
-									
-									int	fields_matched = 0;
-									
-									for(int i = 0 ; i < mappings.length ; i++) {
-										String fieldFrom = mappings[i].getName();
-										
-										String fieldContent = null;
-										Matcher matcher = patternVariable.matcher(fieldFrom);
-										if (matcher.find()) {
-											fieldContent = fieldFrom;
-											do {
-												String key = matcher.group();
-												key = key.substring(2, key.length() - 1);
-												try {
-													int groupNo = Integer.parseInt(key);
-													
-													fieldContent = fieldContent.replaceFirst(variablePattern,
-															m.group(groupNo));
-													
-												} catch (Exception e) {
-													
-												}
-											} while (matcher.find());
-										} else {
-											try {
-												int groupNo = Integer.parseInt(fieldFrom);
-												fieldContent = m.group(groupNo);
-											} catch(Exception e) {
-												//In "Debug/Test" mode, we should fire an exception / notification
-											}
-										}
-										
-										if (fieldContent != null) {
-											
-											int fieldTo = mappings[i].getField();
-											
-											debugLog( "    " + fieldTo + "=" + fieldContent );
-											
-											fields_matched++;
-											
-											switch(fieldTo) {
-												case FIELD_NAME :
-													result.setNameFromHTML(fieldContent);
-													break;
-												case FIELD_SIZE :
-													result.setSizeFromHTML(fieldContent);
-													break;
-												case FIELD_PEERS :
-													result.setNbPeersFromHTML(fieldContent);
-													break;
-												case FIELD_SEEDS :
-													result.setNbSeedsFromHTML(fieldContent);
-													break;
-												case FIELD_CATEGORY :
-													result.setCategoryFromHTML(fieldContent);
-													break;
-												case FIELD_DATE :
-													result.setPublishedDateFromHTML(fieldContent);
-													break;
-												case FIELD_CDPLINK :
-													result.setCDPLink(fieldContent);
-													break;
-												case FIELD_TORRENTLINK :
-													result.setTorrentLink(fieldContent);
-													break;
-												case FIELD_PLAYLINK :
-													result.setPlayLink(fieldContent);
-													break;
-												case FIELD_DOWNLOADBTNLINK :
-													result.setDownloadButtonLink(fieldContent);
-													break;
-												case FIELD_COMMENTS :
-													result.setCommentsFromHTML(fieldContent);
-													break;
-												case FIELD_VOTES :
-													result.setVotesFromHTML(fieldContent);
-													break;
-												case FIELD_SUPERSEEDS :
-													result.setNbSuperSeedsFromHTML(fieldContent);
-													break;
-												case FIELD_PRIVATE :
-													result.setPrivateFromHTML(fieldContent);
-													break;
-												case FIELD_DRMKEY :
-													result.setDrmKey(fieldContent);
-													break;
-												case FIELD_VOTES_DOWN :
-													result.setVotesDownFromHTML(fieldContent);
-													break;
-												case FIELD_HASH :
-													result.setHash(fieldContent);
-													break;
-												default:
-													fields_matched--;
-													break;
-											}
-										}
-									}
-									
-										// ignore "matches" that don't actually populate any fields 
-									
-									if ( fields_matched > 0 ){
-									
-										results.add(result);
-									}
-								}
-							}
-							
-								// hack - if no results and redirected to https and auth required then
-								// assume we need to log in...
-							
-							if ( results.size() == 0 && isNeedsAuth()){
-								
-								if ( 	page_details.getInitialURL().getProtocol().equalsIgnoreCase( "http" ) &&
-										page_details.getFinalURL().getProtocol().equalsIgnoreCase( "https" )){
-									
-									throw new SearchLoginException("login possibly required");
-								}
-							}
-							
-							return (Result[]) results.toArray(new Result[results.size()]);
-							
-						}catch (Throwable e){
-							
-							log( "Failed process result", e );
-				
-							if ( e instanceof SearchException ){
-								
-								throw((SearchException)e );
-							}
-							
-							throw new SearchException(e);
-						}
-					}
-				});
-			
-			Result[] res = (Result[])task.run();
-			
-			debugLog( "success: found " + res.length + " results" );
-			
-			return( res );
-			
-		}catch( Throwable e ){
-			
-			debugLog( "failed: " + Debug.getNestedExceptionMessageAndStack( e ));
-			
-			if ( e instanceof SearchException ){
-				
-				throw((SearchException)e );
-			}
-			
-			throw( new SearchException( "Regex matching failed", e ));
-		}
-	}
-	
-	/*
-	protected void
-	writeToFile(
-		String		file,
-		String		str )
-	{
-		try{
-			PrintWriter pw = new PrintWriter( new FileWriter( new File( file )));
-			
-			pw.println( str );
-			
-			pw.close();
-			
-		}catch( Throwable e ){
-			
-			e.printStackTrace();
-		}
-	}
-	
-	private static String
-	readFile(
-		String	file )
-	{
-		try{
-			StringBuffer sb = new StringBuffer();
-			
-			LineNumberReader lnr = new LineNumberReader( new FileReader( new File( file )));
-			
-			while( true ){
-				
-				String 	line = lnr.readLine();
-				
-				if ( line == null ){
-					
-					break;
-				}
-				
-				sb.append( line );
-			}
-			
-			return( sb.toString());
-			
-		}catch( Throwable e ){
-			
-			e.printStackTrace();
-			
-			return( null );
-		}
-	}
-	
-	private static void
-	regexptest()
-	
-		throws Exception
-	{
-		Pattern pattern = Pattern.compile( readFile( "C:\\temp\\pattern.txt" ));
-		
-		String	page = readFile( "C:\\temp\\template.txt" );
-		
-		Matcher m = pattern.matcher( page);
-		
-		while(m.find()) {
-			
-			int groups = m.groupCount();
-			
-			System.out.println( "found match: groups = " + groups );
-		}
-	}
-	*/
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.impl.web.regex;
+
+import java.io.*;
+import java.net.URLDecoder;
+import java.util.*;
+import java.util.regex.*;
+
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.TimeLimitedTask;
+import org.gudy.azureus2.core3.util.UrlUtils;
+import org.json.simple.JSONObject;
+
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.Result;
+import com.aelitis.azureus.core.metasearch.ResultListener;
+import com.aelitis.azureus.core.metasearch.SearchException;
+import com.aelitis.azureus.core.metasearch.SearchLoginException;
+import com.aelitis.azureus.core.metasearch.SearchParameter;
+import com.aelitis.azureus.core.metasearch.impl.EngineImpl;
+import com.aelitis.azureus.core.metasearch.impl.MetaSearchImpl;
+import com.aelitis.azureus.core.metasearch.impl.web.FieldMapping;
+import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
+import com.aelitis.azureus.core.metasearch.impl.web.WebResult;
+import com.aelitis.azureus.util.ImportExportUtils;
+
+public class 
+RegexEngine 
+	extends WebEngine 
+{	
+	private final static String variablePattern = "\\$\\{[^}]+\\}";
+	private final static Pattern patternVariable = Pattern.compile(variablePattern);
+	
+	public static EngineImpl
+	importFromBEncodedMap(
+		MetaSearchImpl		meta_search,
+		Map					map )
+	
+		throws IOException
+	{
+		return( new RegexEngine( meta_search, map ));
+	}
+	
+	public static Engine
+	importFromJSONString(
+		MetaSearchImpl		meta_search,
+		long				id,
+		long				last_updated,
+		float				rank_bias,
+		String				name,
+		JSONObject			map )
+	
+		throws IOException
+	{
+		return( new RegexEngine( meta_search, id, last_updated, rank_bias, name, map ));
+	}
+
+	private String		pattern_str;
+	private Pattern[] 	patterns = {};
+
+	
+		// explicit test constructor
+	
+	public 
+	RegexEngine(
+		MetaSearchImpl		meta_search,
+		long 				id,
+		long 				last_updated,
+		float				rank_bias,
+		String 				name,
+		String 				searchURLFormat,
+		String 				resultPattern,
+		String 				timeZone,
+		boolean 			automaticDateFormat,
+		String 				userDateFormat,
+		FieldMapping[] 		mappings,
+		boolean				needs_auth,
+		String				auth_method,
+		String				login_url,
+		String[]			required_cookies )
+	{
+		super( 	meta_search, 
+				Engine.ENGINE_TYPE_REGEX, 
+				id,
+				last_updated,
+				rank_bias,
+				name,
+				searchURLFormat,
+				timeZone,
+				automaticDateFormat,
+				userDateFormat, 
+				mappings,
+				needs_auth,
+				auth_method,
+				login_url,
+				required_cookies );		
+
+		init( resultPattern );
+		
+		setSource( ENGINE_SOURCE_LOCAL );
+		
+		setSelectionState( SEL_STATE_MANUAL_SELECTED );
+	}
+	
+		// bencoded 
+	
+	protected 
+	RegexEngine(
+		MetaSearchImpl		meta_search,
+		Map					map )
+	
+		throws IOException
+	{
+		super( meta_search, map );
+		
+		String	resultPattern = ImportExportUtils.importString( map, "regex.pattern" );
+
+		init( resultPattern );
+	}
+	
+		// json
+	
+	protected 
+	RegexEngine(
+		MetaSearchImpl		meta_search,
+		long				id,
+		long				last_updated,
+		float				rank_bias,
+		String				name,
+		JSONObject			map )
+	
+		throws IOException
+	{
+		super( meta_search, Engine.ENGINE_TYPE_REGEX, id, last_updated, rank_bias, name, map );
+		
+		String	resultPattern = ImportExportUtils.importString( map, "regexp" );
+
+		resultPattern = URLDecoder.decode( resultPattern, "UTF-8" );
+		
+		init( resultPattern );
+	}
+	
+	public Map 
+	exportToBencodedMap()
+	
+		throws IOException
+	{
+		return( exportToBencodedMap( false ));
+	}
+	
+	public Map 
+	exportToBencodedMap(
+		boolean		generic ) 
+	
+		throws IOException
+	{
+		Map	res = new HashMap();
+		
+		ImportExportUtils.exportString( res, "regex.pattern", pattern_str );
+		
+		super.exportToBencodedMap( res, generic );
+		
+		return( res );
+	}
+
+	protected void
+	exportToJSONObject(
+		JSONObject		res )
+	
+		throws IOException
+	{
+		res.put( "regexp", UrlUtils.encode( pattern_str ));
+
+		super.exportToJSONObject( res );
+	}
+	
+	protected void
+	init(
+		String			resultPattern )
+	{
+		pattern_str 	= resultPattern.trim();
+		if (pattern_str.length() == 0) {
+			patterns = new Pattern[0];
+		} else {
+  		patterns = new Pattern[]{
+  				
+  			Pattern.compile( pattern_str),
+  			Pattern.compile( pattern_str, Pattern.DOTALL | Pattern.MULTILINE )
+  		};
+		}
+	}
+	
+	protected Result[] 
+	searchSupport(
+		final SearchParameter[] 	searchParameters,
+		Map							searchContext,
+		final int					desired_max_matches,
+		final int					o_absolute_max_matches,
+		final String				headers,
+		final ResultListener		listener )
+	
+		throws SearchException 
+	{
+		debugStart();
+				
+		final pageDetails page_details = getWebPageContent( searchParameters, searchContext, headers, false );
+		
+		final String	page = page_details.getContent();
+		
+		if ( listener != null ){
+			
+			listener.contentReceived( this, page );
+		}
+		
+		debugLog( "pattern: " + pattern_str );
+		
+		/*
+		if ( getId() == 3 ){
+			
+			writeToFile( "C:\\temp\\template.txt", page );
+			writeToFile( "C:\\temp\\pattern.txt", pattern.pattern());
+			
+			String page2 = readFile( "C:\\temp\\template.txt" );
+			
+			Set s1 = new HashSet();
+			Set s2 = new HashSet();
+			
+			for (int i=0;i<page.length();i++){
+				s1.add( new Character( page.charAt(i)));
+			}
+			for (int i=0;i<page2.length();i++){
+				s2.add( new Character( page2.charAt(i)));
+			}
+			
+			s1.removeAll(s2);
+			
+			Iterator it = s1.iterator();
+			
+			while( it.hasNext()){
+				
+				Character c = (Character)it.next();
+				
+				System.out.println( "diff: " + c + "/" + (int)c.charValue());
+			}
+			
+		}
+		
+		try{
+			regexptest();
+		}catch( Throwable e ){
+			
+		}
+		 */
+				
+		try{
+			TimeLimitedTask task = new TimeLimitedTask(
+				"MetaSearch:regexpr",
+				30*1000,
+				Thread.NORM_PRIORITY - 1,
+				new TimeLimitedTask.task()
+				{
+					public Object
+					run()
+					
+						throws Exception
+					{
+						int	max_matches = o_absolute_max_matches;
+								
+						if ( max_matches < 0 || max_matches > 1024 ){
+							
+							max_matches = 1024;
+						}
+						
+						String searchQuery = null;
+						
+						for(int i = 0 ; i < searchParameters.length ; i++) {
+							if(searchParameters[i].getMatchPattern().equals("s")) {
+								searchQuery = searchParameters[i].getValue();
+							}
+						}
+						
+						
+						FieldMapping[] mappings = getMappings();
+	
+						try{						
+							List results = new ArrayList();
+								
+							for ( int pat_num=0;pat_num<patterns.length;pat_num++){
+								
+									// only try subsequent patterns if all previous have failed to 
+									// find results
+								
+								if ( results.size() > 0 ){
+									
+									break;
+								}
+								
+								Pattern pattern = patterns[pat_num];
+								
+								Matcher m = pattern.matcher( page );
+									
+								while( m.find()){
+									
+									if ( max_matches >= 0 ){
+										if ( --max_matches < 0 ){
+											break;
+										}
+									}
+									
+									if ( listener != null ){
+										
+										String[]	groups = new String[m.groupCount()];
+										
+										for (int i=0;i<groups.length;i++){
+											
+											groups[i] = m.group(i+1);
+										}
+										
+										listener.matchFound( RegexEngine.this, groups );
+									}
+									
+									debugLog( "Found match:" );
+									
+									WebResult result = new WebResult(RegexEngine.this,getRootPage(),getBasePage(),getDateParser(),searchQuery);
+									
+									int	fields_matched = 0;
+									
+									for(int i = 0 ; i < mappings.length ; i++) {
+										String fieldFrom = mappings[i].getName();
+										
+										String fieldContent = null;
+										Matcher matcher = patternVariable.matcher(fieldFrom);
+										if (matcher.find()) {
+											fieldContent = fieldFrom;
+											do {
+												String key = matcher.group();
+												key = key.substring(2, key.length() - 1);
+												try {
+													int groupNo = Integer.parseInt(key);
+													
+													fieldContent = fieldContent.replaceFirst(variablePattern,
+															m.group(groupNo));
+													
+												} catch (Exception e) {
+													
+												}
+											} while (matcher.find());
+										} else {
+											try {
+												int groupNo = Integer.parseInt(fieldFrom);
+												fieldContent = m.group(groupNo);
+											} catch(Exception e) {
+												//In "Debug/Test" mode, we should fire an exception / notification
+											}
+										}
+										
+										if (fieldContent != null) {
+											
+											int fieldTo = mappings[i].getField();
+											
+											debugLog( "    " + fieldTo + "=" + fieldContent );
+											
+											fields_matched++;
+											
+											switch(fieldTo) {
+												case FIELD_NAME :
+													result.setNameFromHTML(fieldContent);
+													break;
+												case FIELD_SIZE :
+													result.setSizeFromHTML(fieldContent);
+													break;
+												case FIELD_PEERS :
+													result.setNbPeersFromHTML(fieldContent);
+													break;
+												case FIELD_SEEDS :
+													result.setNbSeedsFromHTML(fieldContent);
+													break;
+												case FIELD_CATEGORY :
+													result.setCategoryFromHTML(fieldContent);
+													break;
+												case FIELD_DATE :
+													result.setPublishedDateFromHTML(fieldContent);
+													break;
+												case FIELD_CDPLINK :
+													result.setCDPLink(fieldContent);
+													break;
+												case FIELD_TORRENTLINK :
+													result.setTorrentLink(fieldContent);
+													break;
+												case FIELD_PLAYLINK :
+													result.setPlayLink(fieldContent);
+													break;
+												case FIELD_DOWNLOADBTNLINK :
+													result.setDownloadButtonLink(fieldContent);
+													break;
+												case FIELD_COMMENTS :
+													result.setCommentsFromHTML(fieldContent);
+													break;
+												case FIELD_VOTES :
+													result.setVotesFromHTML(fieldContent);
+													break;
+												case FIELD_SUPERSEEDS :
+													result.setNbSuperSeedsFromHTML(fieldContent);
+													break;
+												case FIELD_PRIVATE :
+													result.setPrivateFromHTML(fieldContent);
+													break;
+												case FIELD_DRMKEY :
+													result.setDrmKey(fieldContent);
+													break;
+												case FIELD_VOTES_DOWN :
+													result.setVotesDownFromHTML(fieldContent);
+													break;
+												case FIELD_HASH :
+													result.setHash(fieldContent);
+													break;
+												default:
+													fields_matched--;
+													break;
+											}
+										}
+									}
+									
+										// ignore "matches" that don't actually populate any fields 
+									
+									if ( fields_matched > 0 ){
+									
+										results.add(result);
+									}
+								}
+							}
+							
+								// hack - if no results and redirected to https and auth required then
+								// assume we need to log in...
+							
+							if ( results.size() == 0 && isNeedsAuth()){
+								
+								if ( 	page_details.getInitialURL().getProtocol().equalsIgnoreCase( "http" ) &&
+										page_details.getFinalURL().getProtocol().equalsIgnoreCase( "https" )){
+									
+									throw new SearchLoginException("login possibly required");
+								}
+							}
+							
+							return (Result[]) results.toArray(new Result[results.size()]);
+							
+						}catch (Throwable e){
+							
+							log( "Failed process result", e );
+				
+							if ( e instanceof SearchException ){
+								
+								throw((SearchException)e );
+							}
+							
+							throw new SearchException(e);
+						}
+					}
+				});
+			
+			Result[] res = (Result[])task.run();
+			
+			debugLog( "success: found " + res.length + " results" );
+			
+			return( res );
+			
+		}catch( Throwable e ){
+			
+			debugLog( "failed: " + Debug.getNestedExceptionMessageAndStack( e ));
+			
+			if ( e instanceof SearchException ){
+				
+				throw((SearchException)e );
+			}
+			
+			throw( new SearchException( "Regex matching failed", e ));
+		}
+	}
+	
+	/*
+	protected void
+	writeToFile(
+		String		file,
+		String		str )
+	{
+		try{
+			PrintWriter pw = new PrintWriter( new FileWriter( new File( file )));
+			
+			pw.println( str );
+			
+			pw.close();
+			
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+		}
+	}
+	
+	private static String
+	readFile(
+		String	file )
+	{
+		try{
+			StringBuffer sb = new StringBuffer();
+			
+			LineNumberReader lnr = new LineNumberReader( new FileReader( new File( file )));
+			
+			while( true ){
+				
+				String 	line = lnr.readLine();
+				
+				if ( line == null ){
+					
+					break;
+				}
+				
+				sb.append( line );
+			}
+			
+			return( sb.toString());
+			
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+			
+			return( null );
+		}
+	}
+	
+	private static void
+	regexptest()
+	
+		throws Exception
+	{
+		Pattern pattern = Pattern.compile( readFile( "C:\\temp\\pattern.txt" ));
+		
+		String	page = readFile( "C:\\temp\\template.txt" );
+		
+		Matcher m = pattern.matcher( page);
+		
+		while(m.find()) {
+			
+			int groups = m.groupCount();
+			
+			System.out.println( "found match: groups = " + groups );
+		}
+	}
+	*/
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/rss/RSSEngine.java b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/rss/RSSEngine.java
index 8745fca..0b3be80 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/rss/RSSEngine.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/impl/web/rss/RSSEngine.java
@@ -7,6 +7,7 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -189,7 +190,44 @@ RSSEngine
 		
 		boolean	only_if_mod = !searchContext.containsKey( Engine.SC_FORCE_FULL );
 		
-		pageDetails page_details = super.getWebPageContent( searchParameters, searchContext, headers, only_if_mod );
+		pageDetails page_details = 
+			super.getWebPageContent( 
+				searchParameters, 
+				searchContext, 
+				headers, 
+				only_if_mod,
+				new pageDetailsVerifier() {
+					
+					public void 
+					verify(
+						pageDetails details )
+							
+						throws SearchException
+					{
+						try{
+							String	page = details.getContent();
+	
+							if ( page != null && page.length() > 0 ){
+								
+								ByteArrayInputStream bais = new ByteArrayInputStream( page.getBytes("UTF-8"));
+								
+								RSSFeed rssFeed = StaticUtilities.getRSSFeed( details.getInitialURL(), bais );
+		
+								details.setVerifiedState( rssFeed );
+							}
+						}catch( Throwable e ){
+							
+							debugLog( "failed: " + Debug.getNestedExceptionMessageAndStack( e ));
+							
+							if ( e instanceof SearchException ){
+								
+								throw((SearchException)e );
+							}
+							
+							throw( new SearchException( "RSS matching failed", e ));
+						}
+					}
+				});
 		
 		String	page = page_details.getContent();
 		
@@ -203,10 +241,8 @@ RSSEngine
 			return( new Result[0]);
 		}
 		
-		try {
-			ByteArrayInputStream bais = new ByteArrayInputStream( page.getBytes("UTF-8"));
-			
-			RSSFeed rssFeed = StaticUtilities.getRSSFeed( bais );
+		try{
+			RSSFeed rssFeed = (RSSFeed)page_details.getVerifiedState();
 			
 			RSSChannel[] channels = rssFeed.getChannels();
 			
@@ -257,7 +293,9 @@ RSSEngine
 					
 						String link_url = cdp_link.toExternalForm();
 						
-						if ( link_url.toLowerCase().startsWith( "http" )){
+						String lc_url = link_url.toLowerCase( Locale.US );
+						
+						if ( lc_url.startsWith( "http" ) || lc_url.startsWith( "tor:http" )){
 						
 							result.setCDPLink( link_url );
 							
@@ -702,7 +740,7 @@ RSSEngine
 			return( res );
 			
 			
-		}catch ( Throwable e ){
+		}catch( Throwable e ){
 			
 			debugLog( "failed: " + Debug.getNestedExceptionMessageAndStack( e ));
 			
@@ -730,11 +768,14 @@ RSSEngine
 			
 			String content_type = con.getContentType();
 
-			log( "Testing link " + url + " to see if torrent link -> content type=" + content_type );
-			
-			if ( content_type.equalsIgnoreCase( "application/x-bittorrent" )){
+			if ( content_type != null ){
 				
-				return( true );
+				log( "Testing link " + url + " to see if torrent link -> content type=" + content_type );
+				
+				if ( content_type.equalsIgnoreCase( "application/x-bittorrent" )){
+					
+					return( true );
+				}
 			}
 			
 			return( false );
diff --git a/azureus3/src/com/aelitis/azureus/core/metasearch/utils/MomentsAgoDateFormatter.java b/azureus3/src/com/aelitis/azureus/core/metasearch/utils/MomentsAgoDateFormatter.java
index 192aad6..4db8b4b 100644
--- a/azureus3/src/com/aelitis/azureus/core/metasearch/utils/MomentsAgoDateFormatter.java
+++ b/azureus3/src/com/aelitis/azureus/core/metasearch/utils/MomentsAgoDateFormatter.java
@@ -1,154 +1,153 @@
-/*
- * Created on May 6, 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.core.metasearch.utils;
-
-import java.text.DateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.SimpleTimeZone;
-
-/**
-* Improvement based on AZWEB-318.
-*
-* @version 3.2.1.0 6/19/2007
-* @since 3.2.1.0 6/19/2007
-*/
-public class MomentsAgoDateFormatter {
-
-   // A list of id's that we use in the two maps to ensure we have valid refs
-   private static final Integer ID_YEAR = new Integer(Calendar.YEAR);
-   private static final Integer ID_MONTH = new Integer(Calendar.MONTH);
-   private static final Integer ID_WEEK_OF_YEAR = new Integer(Calendar.WEEK_OF_YEAR);
-   private static final Integer ID_DAY = new Integer(Calendar.DAY_OF_MONTH);
-   private static final Integer ID_HOUR_OF_DAY = new Integer(Calendar.HOUR_OF_DAY);
-   private static final Integer ID_MINUTE = new Integer(Calendar.MINUTE);
-   private static final Integer ID_SECOND = new Integer(Calendar.SECOND);
-
-   // A list of units we're comparing.
-   private static final Long MS_IN_YEAR   = new Long(31536000000L);
-   private static final Long MS_IN_MONTH  = new Long(2678400000L);
-   private static final Long MS_IN_WEEK   = new Long(604800000L);
-   private static final Long MS_IN_DAY    = new Long(86400000L);
-   private static final Long MS_IN_HOUR   = new Long(3600000L);
-   private static final Long MS_IN_MINUTE = new Long(60000L);
-   private static final Long MS_IN_SECOND = new Long(1000L);
-
-   // A few externalized strings to display to the user
-   private static final String AGO = " ago";
-   private static final String PLURAL = "s";
-
-   private static final Map CONVERSION_MAP = new HashMap();
-
-   // Build the map at system start
-   static {
-       CONVERSION_MAP.put(ID_YEAR, MS_IN_YEAR);
-       CONVERSION_MAP.put(ID_MONTH, MS_IN_MONTH);
-       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);
-   }
-
-   private static final Map UNIT_MAP =
-       new HashMap();
-
-   // Build the map at system start
-   static {
-       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, " hr");
-   }
-
-   /**
-    * Returns "x <units of time> ago on <formatted pastDate>" by comparing the
-    * given pastDate with the current time.  All formats are converted to GMT
-    * time.  In the future the user might have their own locale, in which case
-    * we will display the time in their own locale (neat!)
-    *
-    * @param pastDate A date in the past
-    * @param format The format for the pastDate
-    * @return "x <units of time> ago on <formatted pastDate in GMT time>"
-    */
-   public static String getMomentsAgoString(Date pastDate, DateFormat format) {
-       String timeAgo = getMomentsAgoString(pastDate);
-       format.setTimeZone(new SimpleTimeZone(0, "GMT"));
-       if (timeAgo.length() > 0) timeAgo = timeAgo.concat(" on ");
-       return timeAgo.concat(format.format(pastDate));
-   }
-
-   /**
-    * Returns "x <units of time> ago on <formatted pastDate>" by comparing the
-    * given pastDate with the current time.
-    *
-    * @param pastDate A default locale date in the past
-    * @return "x <units of time> ago"
-    */
-   public static String getMomentsAgoString(Date pastDate) {
-       Calendar then = Calendar.getInstance();
-       then.setTime(pastDate);
-       Calendar now = Calendar.getInstance();
-       String result = null;
-       result = handleUnit(then, now, ID_YEAR);
-       if (result == null) {
-           result = handleUnit(then, now, ID_MONTH);
-           if (result == null) {
-               result = handleUnit(then, now, ID_WEEK_OF_YEAR);
-               if (result == null) {
-                   result = handleUnit(then, now, ID_DAY);
-                   if (result == null) {
-                       result = handleUnit(then, now, ID_HOUR_OF_DAY);
-                       if (result == null) {
-                           return "< 1 h";
-                       }
-                   }
-               }
-           }
-       }
-       return result;
-   }
-
-   /**
-    * Checks to see if the unit we're comparing is less than the difference of
-    * the given "then" and "now" dates in milliseconds.
-    *
-    * @param then The date we're evaluating
-    * @param now The current time
-    * @param field The field which we're evaluating ("units")
-    * @return null if then is 0 "units" from now, otherwise a displayable
-    *         string that will notify the user how long ago then was from now.
-    */
-   private static String handleUnit(Calendar then, Calendar now,
-           Integer field) {
-       String result = null;
-       long diff = now.getTimeInMillis() - then.getTimeInMillis();
-       long comparison = ((Long)CONVERSION_MAP.get(field)).longValue();
-       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);
-       }
-       return result;
-   }
-}
\ No newline at end of file
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.metasearch.utils;
+
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SimpleTimeZone;
+
+/**
+* Improvement based on AZWEB-318.
+*
+* @version 3.2.1.0 6/19/2007
+* @since 3.2.1.0 6/19/2007
+*/
+public class MomentsAgoDateFormatter {
+
+   // A list of id's that we use in the two maps to ensure we have valid refs
+   private static final Integer ID_YEAR = new Integer(Calendar.YEAR);
+   private static final Integer ID_MONTH = new Integer(Calendar.MONTH);
+   private static final Integer ID_WEEK_OF_YEAR = new Integer(Calendar.WEEK_OF_YEAR);
+   private static final Integer ID_DAY = new Integer(Calendar.DAY_OF_MONTH);
+   private static final Integer ID_HOUR_OF_DAY = new Integer(Calendar.HOUR_OF_DAY);
+   private static final Integer ID_MINUTE = new Integer(Calendar.MINUTE);
+   private static final Integer ID_SECOND = new Integer(Calendar.SECOND);
+
+   // A list of units we're comparing.
+   private static final Long MS_IN_YEAR   = new Long(31536000000L);
+   private static final Long MS_IN_MONTH  = new Long(2678400000L);
+   private static final Long MS_IN_WEEK   = new Long(604800000L);
+   private static final Long MS_IN_DAY    = new Long(86400000L);
+   private static final Long MS_IN_HOUR   = new Long(3600000L);
+   private static final Long MS_IN_MINUTE = new Long(60000L);
+   private static final Long MS_IN_SECOND = new Long(1000L);
+
+   // A few externalized strings to display to the user
+   private static final String AGO = " ago";
+   private static final String PLURAL = "s";
+
+   private static final Map CONVERSION_MAP = new HashMap();
+
+   // Build the map at system start
+   static {
+       CONVERSION_MAP.put(ID_YEAR, MS_IN_YEAR);
+       CONVERSION_MAP.put(ID_MONTH, MS_IN_MONTH);
+       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);
+   }
+
+   private static final Map UNIT_MAP =
+       new HashMap();
+
+   // Build the map at system start
+   static {
+       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, " hr");
+   }
+
+   /**
+    * Returns "x <units of time> ago on <formatted pastDate>" by comparing the
+    * given pastDate with the current time.  All formats are converted to GMT
+    * time.  In the future the user might have their own locale, in which case
+    * we will display the time in their own locale (neat!)
+    *
+    * @param pastDate A date in the past
+    * @param format The format for the pastDate
+    * @return "x <units of time> ago on <formatted pastDate in GMT time>"
+    */
+   public static String getMomentsAgoString(Date pastDate, DateFormat format) {
+       String timeAgo = getMomentsAgoString(pastDate);
+       format.setTimeZone(new SimpleTimeZone(0, "GMT"));
+       if (timeAgo.length() > 0) timeAgo = timeAgo.concat(" on ");
+       return timeAgo.concat(format.format(pastDate));
+   }
+
+   /**
+    * Returns "x <units of time> ago on <formatted pastDate>" by comparing the
+    * given pastDate with the current time.
+    *
+    * @param pastDate A default locale date in the past
+    * @return "x <units of time> ago"
+    */
+   public static String getMomentsAgoString(Date pastDate) {
+       Calendar then = Calendar.getInstance();
+       then.setTime(pastDate);
+       Calendar now = Calendar.getInstance();
+       String result = null;
+       result = handleUnit(then, now, ID_YEAR);
+       if (result == null) {
+           result = handleUnit(then, now, ID_MONTH);
+           if (result == null) {
+               result = handleUnit(then, now, ID_WEEK_OF_YEAR);
+               if (result == null) {
+                   result = handleUnit(then, now, ID_DAY);
+                   if (result == null) {
+                       result = handleUnit(then, now, ID_HOUR_OF_DAY);
+                       if (result == null) {
+                           return "< 1 h";
+                       }
+                   }
+               }
+           }
+       }
+       return result;
+   }
+
+   /**
+    * Checks to see if the unit we're comparing is less than the difference of
+    * the given "then" and "now" dates in milliseconds.
+    *
+    * @param then The date we're evaluating
+    * @param now The current time
+    * @param field The field which we're evaluating ("units")
+    * @return null if then is 0 "units" from now, otherwise a displayable
+    *         string that will notify the user how long ago then was from now.
+    */
+   private static String handleUnit(Calendar then, Calendar now,
+           Integer field) {
+       String result = null;
+       long diff = now.getTimeInMillis() - then.getTimeInMillis();
+       long comparison = ((Long)CONVERSION_MAP.get(field)).longValue();
+       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);
+       }
+       return result;
+   }
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/peer/cache/CacheDiscoverer.java b/azureus3/src/com/aelitis/azureus/core/peer/cache/CacheDiscoverer.java
index bb68ae1..79f07b8 100644
--- a/azureus3/src/com/aelitis/azureus/core/peer/cache/CacheDiscoverer.java
+++ b/azureus3/src/com/aelitis/azureus/core/peer/cache/CacheDiscoverer.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 1, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/core/peer/cache/CacheDiscovery.java b/azureus3/src/com/aelitis/azureus/core/peer/cache/CacheDiscovery.java
index 5c2b829..4724d99 100644
--- a/azureus3/src/com/aelitis/azureus/core/peer/cache/CacheDiscovery.java
+++ b/azureus3/src/com/aelitis/azureus/core/peer/cache/CacheDiscovery.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 1, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/core/peer/cache/CachePeer.java b/azureus3/src/com/aelitis/azureus/core/peer/cache/CachePeer.java
index 2209b86..4f2f4a0 100644
--- a/azureus3/src/com/aelitis/azureus/core/peer/cache/CachePeer.java
+++ b/azureus3/src/com/aelitis/azureus/core/peer/cache/CachePeer.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 1, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/core/peer/cache/cachelogic/CLCacheDiscovery.java b/azureus3/src/com/aelitis/azureus/core/peer/cache/cachelogic/CLCacheDiscovery.java
index 8f0c395..9573638 100644
--- a/azureus3/src/com/aelitis/azureus/core/peer/cache/cachelogic/CLCacheDiscovery.java
+++ b/azureus3/src/com/aelitis/azureus/core/peer/cache/cachelogic/CLCacheDiscovery.java
@@ -1,7 +1,7 @@
 /*
  * Created on Jan 31, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/Subscription.java b/azureus3/src/com/aelitis/azureus/core/subs/Subscription.java
index 0f227f9..a0f66e1 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/Subscription.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/Subscription.java
@@ -1,245 +1,250 @@
-/*
- * Created on Jul 11, 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.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;
-	
-	public static final Object	VUZE_FILE_COMPONENT_SUBSCRIPTION_KEY = new Object();
-
-		/**
-		 * Returns local name if set
-		 * @return
-		 */
-	
-	public String
-	getName();
-	
-	public String
-	getName(
-		boolean	use_local );
-	
-	public void
-	setLocalName(
-		String		str );
-	
-	public void
-	setName(
-		String		str )
-	
-		throws SubscriptionException;
-	
-	public String
-	getNameEx();
-	
-	public String
-	getID();
-	
-	public byte[]
-	getPublicKey();
-	
-	public int
-	getVersion();
-
-	public long
-	getAddTime();
-	
-	public int
-	getHighestVersion();
-	
-	public void
-	resetHighestVersion();
-
-	public int
-	getAZVersion();
-	
-	public boolean
-	isMine();
-	
-	public boolean
-	isPublic();
-	
-	public void
-	setPublic(
-		boolean	is_public )
-	
-		throws SubscriptionException;
-	
-	public boolean
-	isUpdateable();
-	
-	public boolean
-	isShareable();
-	
-	public boolean
-	isSearchTemplate();
-	
-	public boolean
-	isSearchTemplateImportable();
-	
-	public VuzeFile
-	getSearchTemplateVuzeFile();
-	
-	public String
-	getJSON()
-	
-		throws SubscriptionException;
-	
-	public boolean
-	setJSON(
-		String		json )
-	
-		throws SubscriptionException;
-	
-	public boolean
-	isSubscribed();
-	
-	public void
-	setSubscribed(
-		boolean		subscribed );
-	
-	public void
-	getPopularity(
-		SubscriptionPopularityListener	listener )
-	
-		throws SubscriptionException;
-	
-	public boolean
-	setDetails(
-		String		name,
-		boolean		is_public,
-		String		json )
-	
-		throws SubscriptionException;
-	
-	public String
-	getReferer();
-	
-	public long
-	getCachedPopularity();
-	
-	public void
-	addAssociation(
-		byte[]		hash );
-	
-	public void
-	addPotentialAssociation(
-		String		result_id,
-		String		key );
-
-	public int
-	getAssociationCount();
-	
-	public boolean
-	hasAssociation(
-		byte[]		hash );
-	
-	public String
-	getCategory();
-	
-	public void
-	setCategory(
-		String	category );
-	
-	public long
-	getTagID();
-	
-	public void
-	setTagID(
-		long	tag_id );
-	
-	
-	public Engine
-	getEngine()
-	
-		throws SubscriptionException;
-	
-	public Subscription
-	cloneWithNewEngine(
-		Engine 	engine )
-	
-		throws SubscriptionException;
-	
-	public boolean
-	isAutoDownloadSupported();
-	
-	public VuzeFile
-	getVuzeFile()
-	
-		throws SubscriptionException;
-		
-	public void
-	setCreatorRef(
-		String	str );
-	
-	public String
-	getCreatorRef();
-	
-	public void
-	reset();
-	
-	public void
-	remove();
-	
-	public SubscriptionManager
-	getManager();
-	
-	public SubscriptionHistory
-	getHistory();
-	
-		/**
-		 * shortcut to help plugin interface
-		 * @param l
-		 */
-	
-	public SubscriptionResult[]
-	getResults(
-		boolean		include_deleted );
-	
-	public void
-	addListener(
-		SubscriptionListener		l );
-	
-	public void
-	removeListener(
-		SubscriptionListener		l );
-	
-	public void
-	setUserData(
-		Object		key,
-		Object		data );
-	
-	public Object
-	getUserData(
-		Object		key );
-	
-	public String
-	getString();
-}
+/*
+ * Created on Jul 11, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.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;
+	
+	public static final Object	VUZE_FILE_COMPONENT_SUBSCRIPTION_KEY = new Object();
+
+		/**
+		 * Returns local name if set
+		 * @return
+		 */
+	
+	public String
+	getName();
+	
+	public String
+	getName(
+		boolean	use_local );
+	
+	public void
+	setLocalName(
+		String		str );
+	
+	public void
+	setName(
+		String		str )
+	
+		throws SubscriptionException;
+	
+	public String
+	getNameEx();
+	
+	public String
+	getID();
+	
+	public byte[]
+	getPublicKey();
+	
+	public int
+	getVersion();
+
+	public long
+	getAddTime();
+	
+	public int
+	getHighestVersion();
+	
+	public void
+	resetHighestVersion();
+
+	public int
+	getAZVersion();
+	
+	public boolean
+	isMine();
+	
+	public boolean
+	isPublic();
+	
+	public void
+	setPublic(
+		boolean	is_public )
+	
+		throws SubscriptionException;
+	
+	public boolean
+	isUpdateable();
+	
+	public boolean
+	isShareable();
+	
+	public boolean
+	isSearchTemplate();
+	
+	public boolean
+	isSearchTemplateImportable();
+	
+	public VuzeFile
+	getSearchTemplateVuzeFile();
+	
+	public String
+	getJSON()
+	
+		throws SubscriptionException;
+	
+	public boolean
+	setJSON(
+		String		json )
+	
+		throws SubscriptionException;
+	
+	public boolean
+	isSubscribed();
+	
+	public void
+	setSubscribed(
+		boolean		subscribed );
+	
+	public void
+	getPopularity(
+		SubscriptionPopularityListener	listener )
+	
+		throws SubscriptionException;
+	
+	public boolean
+	setDetails(
+		String		name,
+		boolean		is_public,
+		String		json )
+	
+		throws SubscriptionException;
+	
+	public String
+	getReferer();
+	
+	public long
+	getCachedPopularity();
+	
+	public void
+	addAssociation(
+		byte[]		hash );
+	
+	public void
+	addPotentialAssociation(
+		String		result_id,
+		String		key );
+
+	public int
+	getAssociationCount();
+	
+	public boolean
+	hasAssociation(
+		byte[]		hash );
+	
+	public String
+	getCategory();
+	
+	public void
+	setCategory(
+		String	category );
+	
+	public long
+	getTagID();
+	
+	public void
+	setTagID(
+		long	tag_id );
+	
+	
+	public Engine
+	getEngine()
+	
+		throws SubscriptionException;
+	
+	public Subscription
+	cloneWithNewEngine(
+		Engine 	engine )
+	
+		throws SubscriptionException;
+	
+	public boolean
+	isAutoDownloadSupported();
+	
+	public VuzeFile
+	getVuzeFile()
+	
+		throws SubscriptionException;
+		
+	public void
+	setCreatorRef(
+		String	str );
+	
+	public String
+	getCreatorRef();
+	
+	public void
+	reset();
+	
+	public void
+	remove();
+	
+	public SubscriptionManager
+	getManager();
+	
+	public SubscriptionHistory
+	getHistory();
+	
+		/**
+		 * shortcut to help plugin interface
+		 * @param l
+		 */
+	
+	public SubscriptionResult[]
+	getResults(
+		boolean		include_deleted );
+	
+	public String
+	getURI();
+	
+	public void
+	requestAttention();
+	
+	public void
+	addListener(
+		SubscriptionListener		l );
+	
+	public void
+	removeListener(
+		SubscriptionListener		l );
+	
+	public void
+	setUserData(
+		Object		key,
+		Object		data );
+	
+	public Object
+	getUserData(
+		Object		key );
+	
+	public String
+	getString();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionAssociationLookup.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionAssociationLookup.java
index c976d26..a1d408e 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionAssociationLookup.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionAssociationLookup.java
@@ -1,29 +1,28 @@
-/*
- * Created on Jul 28, 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.core.subs;
-
-public interface
-SubscriptionAssociationLookup 
-{
-	public void
-	cancel();
-}
+/*
+ * Created on Jul 28, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+public interface
+SubscriptionAssociationLookup 
+{
+	public void
+	cancel();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionDownloadListener.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionDownloadListener.java
index e59c780..974f328 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionDownloadListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionDownloadListener.java
@@ -1,35 +1,34 @@
-/*
- * Created on Aug 8, 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.core.subs;
-
-public interface 
-SubscriptionDownloadListener 
-{
-	public void
-	complete(
-		Subscription		subs );
-	
-	public void
-	failed(
-		Subscription			subs,
-		SubscriptionException	error );
-}
+/*
+ * Created on Aug 8, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+public interface 
+SubscriptionDownloadListener 
+{
+	public void
+	complete(
+		Subscription		subs );
+	
+	public void
+	failed(
+		Subscription			subs,
+		SubscriptionException	error );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionException.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionException.java
index c388e2f..147bbb0 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionException.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionException.java
@@ -1,42 +1,41 @@
-/*
- * Created on Jul 11, 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.core.subs;
-
-public class 
-SubscriptionException 
-	extends Exception
-{
-	public
-	SubscriptionException(
-		String		str )
-	{
-		super( str );
-	}
-	
-	public
-	SubscriptionException(
-		String		str,
-		Throwable	e )
-	{
-		super( str, e );
-	}
-}
+/*
+ * Created on Jul 11, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+public class 
+SubscriptionException 
+	extends Exception
+{
+	public
+	SubscriptionException(
+		String		str )
+	{
+		super( str );
+	}
+	
+	public
+	SubscriptionException(
+		String		str,
+		Throwable	e )
+	{
+		super( str, e );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionHistory.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionHistory.java
index 618975a..75197a9 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionHistory.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionHistory.java
@@ -1,110 +1,113 @@
-/*
- * Created on Aug 6, 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.core.subs;
-
-public interface 
-SubscriptionHistory 
-{
-	public static final int	DEFAULT_CHECK_INTERVAL_MINS		= 120;
-
-	public boolean
-	isEnabled();
-	
-	public void
-	setEnabled(
-		boolean		enabled );
-	
-	public boolean
-	isAutoDownload();
-	
-	public void
-	setAutoDownload(
-		boolean		auto_dl );
-
-	public void
-	setDetails(
-		boolean		enabled,
-		boolean		auto_dl );
-	
-	public void
-	deleteResults(
-		String[]		result_ids );
-	
-	public void
-	deleteAllResults();
-	
-	public void
-	markAllResultsRead();
-	
-	public void
-	markAllResultsUnread();
-	
-	public void
-	markResults(
-		String[]		result_ids,
-		boolean[]		read );
-	
-	public void
-	reset();
-	
-	public long
-	getLastScanTime();
-	
-	public long
-	getLastNewResultTime();
-	
-	public long
-	getNextScanTime();
-	
-	public int
-	getNumUnread();
-	
-	public int
-	getNumRead();
-	
-	public int
-	getCheckFrequencyMins();
-	
-	public String
-	getLastError();
-	
-	public boolean
-	isAuthFail();
-	
-	public int
-	getConsecFails();
-	
-	public SubscriptionResult[]
-	getResults(
-		boolean		include_deleted );
-	
-	public SubscriptionResult
-	getResult(
-		String		result_id );
-	
-	public boolean
-	getDownloadWithReferer();
-	
-	public void
-	setDownloadWithReferer(
-		boolean		b );
-}
+/*
+ * Created on Aug 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+public interface 
+SubscriptionHistory 
+{
+	public static final int	DEFAULT_CHECK_INTERVAL_MINS		= 120;
+
+	public boolean
+	isEnabled();
+	
+	public void
+	setEnabled(
+		boolean		enabled );
+	
+	public boolean
+	isAutoDownload();
+	
+	public void
+	setAutoDownload(
+		boolean		auto_dl );
+
+	public void
+	setDetails(
+		boolean		enabled,
+		boolean		auto_dl );
+	
+	public void
+	deleteResults(
+		String[]		result_ids );
+	
+	public void
+	deleteAllResults();
+	
+	public void
+	markAllResultsRead();
+	
+	public void
+	markAllResultsUnread();
+	
+	public void
+	markResults(
+		String[]		result_ids,
+		boolean[]		read );
+	
+	public void
+	reset();
+	
+	public long
+	getLastScanTime();
+	
+	public long
+	getLastNewResultTime();
+	
+	public long
+	getNextScanTime();
+	
+	public int
+	getNumUnread();
+	
+	public int
+	getNumRead();
+	
+	public int
+	getCheckFrequencyMins();
+	
+	public void
+	setCheckFrequencyMins(
+		int		mins );
+	
+	public String
+	getLastError();
+	
+	public boolean
+	isAuthFail();
+	
+	public int
+	getConsecFails();
+	
+	public SubscriptionResult[]
+	getResults(
+		boolean		include_deleted );
+	
+	public SubscriptionResult
+	getResult(
+		String		result_id );
+	
+	public boolean
+	getDownloadWithReferer();
+	
+	public void
+	setDownloadWithReferer(
+		boolean		b );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionListener.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionListener.java
index ce511ea..4bdb521 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionListener.java
@@ -1,35 +1,34 @@
-/*
- * Created on Aug 5, 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.core.subs;
-
-public interface 
-SubscriptionListener 
-{
-	public void
-	subscriptionChanged(
-		Subscription		subs );
-	
-	public void
-	subscriptionDownloaded(
-		Subscription		subs,
-		boolean				auto );
-}
+/*
+ * Created on Aug 5, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+public interface 
+SubscriptionListener 
+{
+	public void
+	subscriptionChanged(
+		Subscription		subs );
+	
+	public void
+	subscriptionDownloaded(
+		Subscription		subs,
+		boolean				auto );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionLookupListener.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionLookupListener.java
index 59dfb06..1aa8bde 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionLookupListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionLookupListener.java
@@ -1,41 +1,40 @@
-/*
- * Created on Jul 11, 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.core.subs;
-
-public interface 
-SubscriptionLookupListener 
-{
-	public void
-	found(
-		byte[]					hash,
-		Subscription			subscription );
-	
-	public void
-	complete(
-		byte[]					hash,
-		Subscription[]			subscriptions );
-	
-	public void
-	failed(
-		byte[]					hash,
-		SubscriptionException	error );
-}
+/*
+ * Created on Jul 11, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+public interface 
+SubscriptionLookupListener 
+{
+	public void
+	found(
+		byte[]					hash,
+		Subscription			subscription );
+	
+	public void
+	complete(
+		byte[]					hash,
+		Subscription[]			subscriptions );
+	
+	public void
+	failed(
+		byte[]					hash,
+		SubscriptionException	error );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManager.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManager.java
index f795c9d..dffba9d 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManager.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManager.java
@@ -1,173 +1,185 @@
-/*
- * Created on Jul 11, 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.core.subs;
-
-import java.net.URL;
-import java.util.Map;
-
-import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
-
-public interface 
-SubscriptionManager
-	extends UtilitiesImpl.PluginSubscriptionManager
-{
-	public Subscription
-	create(
-		String		name,
-		boolean		is_public,
-		String		json )
-		
-		throws SubscriptionException;
-	
-	public Subscription
-	createRSS(
-		String		name,
-		URL			url,
-		int			check_interval_mins,
-		Map			user_data )
-		
-		throws SubscriptionException;
-	
-		// creates a subscription that will always have the same identity for the given parameters
-		// and can't be updated
-	
-	public Subscription
-	createSingletonRSS(
-		String		name,
-		URL			url,
-		int			check_interval_mins )
-	
-		throws SubscriptionException;
-	
-	public int
-	getKnownSubscriptionCount();
-	
-	public int
-	getSubscriptionCount(
-		boolean	subscribed_only );
-	
-	public Subscription[]
-	getSubscriptions();
-	
-	public Subscription[]
-   	getSubscriptions(
-   		boolean	subscribed_only );
-
-	public Subscription
-	getSubscriptionByID(
-		String			id );
-	
-		/**
-		 * Full lookup
-		 * @param hash
-		 * @param listener
-		 * @return
-		 * @throws SubscriptionException
-		 */
-	
-	public SubscriptionAssociationLookup
-	lookupAssociations(
-		byte[]						hash,
-		SubscriptionLookupListener	listener )
-	
-		throws SubscriptionException;
-	
-		/**
-		 * Cached view of hash's subs
-		 * @param hash
-		 * @return
-		 */
-	
-	public Subscription[]
-	getKnownSubscriptions(
-		byte[]						hash );
-	
-	public Subscription[]
-	getLinkedSubscriptions(
-		byte[]						hash );
-	
-	public SubscriptionScheduler
-	getScheduler();
-	
-	public int
-	getMaxNonDeletedResults();
-	
-	public void
-	setMaxNonDeletedResults(
-		int			max );
-	
-	public boolean
-	getAutoStartDownloads();
-	
-	public void
-	setAutoStartDownloads(
-		boolean		auto_start );
-
-	public int
-	getAutoStartMinMB();
-	
-	public void
-	setAutoStartMinMB(
-		int			mb );
-
-	public int
-	getAutoStartMaxMB();
-	
-	public void
-	setAutoStartMaxMB(
-		int			mb );
-
-	public boolean
-	isRSSPublishEnabled();
-	
-	public void
-	setRSSPublishEnabled(
-		boolean		enabled );
-	
-	public boolean
-	isSearchEnabled();
-	
-	public void
-	setSearchEnabled(
-		boolean		enabled );
-	
-	public boolean
-	isSubsDownloadEnabled();
-	
-	public void
-	setSubsDownloadEnabled(
-		boolean		enabled );
-	
-	public boolean
-	hideSearchTemplates();
-	
-	public String
-	getRSSLink();
-	
-	public void
-	addListener(
-		SubscriptionManagerListener	listener );
-	
-	public void
-	removeListener(
-		SubscriptionManagerListener	listener );
-}
+/*
+ * Created on Jul 11, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+import java.net.URL;
+import java.util.Map;
+
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
+
+public interface 
+SubscriptionManager
+	extends UtilitiesImpl.PluginSubscriptionManager
+{
+	public Subscription
+	create(
+		String		name,
+		boolean		is_public,
+		String		json )
+		
+		throws SubscriptionException;
+	
+	public Subscription
+	createRSS(
+		String		name,
+		URL			url,
+		int			check_interval_mins,
+		Map			user_data )
+		
+		throws SubscriptionException;
+	
+		// creates a subscription that will always have the same identity for the given parameters
+		// and can't be updated
+	
+	public Subscription
+	createSingletonRSS(
+		String		name,
+		URL			url,
+		int			check_interval_mins )
+	
+		throws SubscriptionException;
+	
+	public Subscription
+	createFromURI(
+		String		uri )
+	
+		throws SubscriptionException;
+	
+	public int
+	getKnownSubscriptionCount();
+	
+	public int
+	getSubscriptionCount(
+		boolean	subscribed_only );
+	
+	public Subscription[]
+	getSubscriptions();
+	
+	public Subscription[]
+   	getSubscriptions(
+   		boolean	subscribed_only );
+
+	public Subscription
+	getSubscriptionByID(
+		String			id );
+	
+		/**
+		 * Full lookup
+		 * @param hash
+		 * @param listener
+		 * @return
+		 * @throws SubscriptionException
+		 */
+	
+	public SubscriptionAssociationLookup
+	lookupAssociations(
+		byte[]						hash,
+		SubscriptionLookupListener	listener )
+	
+		throws SubscriptionException;
+	
+		/**
+		 * Cached view of hash's subs
+		 * @param hash
+		 * @return
+		 */
+	
+	public Subscription[]
+	getKnownSubscriptions(
+		byte[]						hash );
+	
+	public Subscription[]
+	getLinkedSubscriptions(
+		byte[]						hash );
+	
+	public SubscriptionScheduler
+	getScheduler();
+	
+	public int
+	getMaxNonDeletedResults();
+	
+	public void
+	setMaxNonDeletedResults(
+		int			max );
+	
+	public boolean
+	getAutoStartDownloads();
+	
+	public void
+	setAutoStartDownloads(
+		boolean		auto_start );
+
+	public int
+	getAutoStartMinMB();
+	
+	public void
+	setAutoStartMinMB(
+		int			mb );
+
+	public int
+	getAutoStartMaxMB();
+	
+	public void
+	setAutoStartMaxMB(
+		int			mb );
+
+	public boolean
+	isRSSPublishEnabled();
+	
+	public void
+	setRSSPublishEnabled(
+		boolean		enabled );
+	
+	public boolean
+	isSearchEnabled();
+	
+	public void
+	setSearchEnabled(
+		boolean		enabled );
+	
+	public boolean
+	isSubsDownloadEnabled();
+	
+	public void
+	setSubsDownloadEnabled(
+		boolean		enabled );
+	
+	public boolean
+	hideSearchTemplates();
+	
+	public String
+	getRSSLink();
+	
+	public void
+	setRateLimits(
+		String		limits );
+	
+	public String
+	getRateLimits();
+	
+	public void
+	addListener(
+		SubscriptionManagerListener	listener );
+	
+	public void
+	removeListener(
+		SubscriptionManagerListener	listener );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManagerFactory.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManagerFactory.java
index 2648316..1146a2a 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManagerFactory.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManagerFactory.java
@@ -1,95 +1,94 @@
-/*
- * Created on Jul 11, 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.core.subs;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-
-public class 
-SubscriptionManagerFactory 
-{
-	final private static Class<SubscriptionManager> impl_class; 
-
-	static{
-		
-		String impl = System.getProperty( "az.factory.subscriptionmanager.impl", "com.aelitis.azureus.core.subs.impl.SubscriptionManagerImpl" );
-		
-		Class<SubscriptionManager> temp = null;
-		
-		if ( impl.length() > 0 ){
-			
-			try{
-				temp = (Class<SubscriptionManager>)SubscriptionManagerFactory.class.getClassLoader().loadClass( impl );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( "Failed to load SubscriptionManager class: " + impl );
-			}
-		}
-		
-		impl_class = temp;
-	}
-
-	private static SubscriptionManager	singleton;
-	
-	public static void
-	preInitialise()
-	{
-		if ( impl_class != null ){
-			
-			try{
-				impl_class.getMethod( "preInitialise" ).invoke( null, (Object[])null );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( "preInitialise failed", e );
-			}
-		}
-	}
-	
-	public static SubscriptionManager
-	getSingleton()
-	{
-		synchronized( SubscriptionManagerFactory.class ){
-			
-			if ( singleton != null ){
-				
-				return( singleton );
-			}
-		
-			if ( impl_class == null ){
-				
-				throw( new RuntimeException( "No Implementation" ));
-			}
-			
-			try{
-				singleton = (SubscriptionManager)impl_class.getMethod( "getSingleton", boolean.class ).invoke( null, false );
-			
-				return( singleton );
-				
-			}catch( Throwable e ){
-				
-				throw( new RuntimeException( "No Implementation", e ));
-			}
-		}
-	}
-}
+/*
+ * Created on Jul 11, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+import org.gudy.azureus2.core3.util.Debug;
+
+
+public class 
+SubscriptionManagerFactory 
+{
+	final private static Class<SubscriptionManager> impl_class; 
+
+	static{
+		
+		String impl = System.getProperty( "az.factory.subscriptionmanager.impl", "com.aelitis.azureus.core.subs.impl.SubscriptionManagerImpl" );
+		
+		Class<SubscriptionManager> temp = null;
+		
+		if ( impl.length() > 0 ){
+			
+			try{
+				temp = (Class<SubscriptionManager>)SubscriptionManagerFactory.class.getClassLoader().loadClass( impl );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( "Failed to load SubscriptionManager class: " + impl );
+			}
+		}
+		
+		impl_class = temp;
+	}
+
+	private static SubscriptionManager	singleton;
+	
+	public static void
+	preInitialise()
+	{
+		if ( impl_class != null ){
+			
+			try{
+				impl_class.getMethod( "preInitialise" ).invoke( null, (Object[])null );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( "preInitialise failed", e );
+			}
+		}
+	}
+	
+	public static SubscriptionManager
+	getSingleton()
+	{
+		synchronized( SubscriptionManagerFactory.class ){
+			
+			if ( singleton != null ){
+				
+				return( singleton );
+			}
+		
+			if ( impl_class == null ){
+				
+				throw( new RuntimeException( "No Implementation" ));
+			}
+			
+			try{
+				singleton = (SubscriptionManager)impl_class.getMethod( "getSingleton", boolean.class ).invoke( null, false );
+			
+				return( singleton );
+				
+			}catch( Throwable e ){
+				
+				throw( new RuntimeException( "No Implementation", e ));
+			}
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManagerListener.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManagerListener.java
index 93ddd14..1803006 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManagerListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionManagerListener.java
@@ -1,46 +1,51 @@
-/*
- * Created on Jul 29, 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.core.subs;
-
-public interface 
-SubscriptionManagerListener 
-{
-	public void
-	subscriptionAdded(
-		Subscription		subscription );
-	
-	public void
-	subscriptionChanged(
-		Subscription		subscription );
-	
-	public void
-	subscriptionSelected(
-		Subscription		subscription );
-	
-	public void
-	subscriptionRemoved(
-		Subscription		subscription );
-	
-	public void
-	associationsChanged(
-		byte[]				association_hash );
-}
+/*
+ * Created on Jul 29, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+import java.net.URL;
+
+public interface 
+SubscriptionManagerListener 
+{
+	public void
+	subscriptionAdded(
+		Subscription		subscription );
+	
+	public void
+	subscriptionChanged(
+		Subscription		subscription );
+	
+	public void
+	subscriptionSelected(
+		Subscription		subscription );
+	
+	public void
+	subscriptionRemoved(
+		Subscription		subscription );
+	
+	public void
+	associationsChanged(
+		byte[]				association_hash );
+	
+	public void
+	subscriptionRequested(
+		URL					url );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionPopularityListener.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionPopularityListener.java
index f01b10b..c6046a2 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionPopularityListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionPopularityListener.java
@@ -1,34 +1,33 @@
-/*
- * Created on Jul 29, 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.core.subs;
-
-public interface 
-SubscriptionPopularityListener 
-{
-	public void
-	gotPopularity(
-		long						popularity );
-	
-	public void
-	failed(
-		SubscriptionException		error );
-}
+/*
+ * Created on Jul 29, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+public interface 
+SubscriptionPopularityListener 
+{
+	public void
+	gotPopularity(
+		long						popularity );
+	
+	public void
+	failed(
+		SubscriptionException		error );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionResult.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionResult.java
index 3ae0bf1..d8fac21 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionResult.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionResult.java
@@ -1,64 +1,63 @@
-/*
- * Created on Aug 6, 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.core.subs;
-
-import java.util.Map;
-
-import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
-
-public interface 
-SubscriptionResult 
-	extends UtilitiesImpl.PluginSubscriptionResult
-{
-	public String
-	getID();
-	
-	public Map
-	toJSONMap();
-	
-		/**
-		 * See SearchResult properties for list
-		 * @return
-		 */
-	
-	public Map<Integer,Object>
-	toPropertyMap();
-	
-	public String
-	getDownloadLink();
-	
-	public String
-	getPlayLink();
-	
-	public void
-	setRead(
-		boolean		read );
-	
-	public boolean
-	getRead();
-	
-	public void
-	delete();
-	
-	public boolean
-	isDeleted();
-}
+/*
+ * Created on Aug 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+import java.util.Map;
+
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
+
+public interface 
+SubscriptionResult 
+	extends UtilitiesImpl.PluginSubscriptionResult
+{
+	public String
+	getID();
+	
+	public Map
+	toJSONMap();
+	
+		/**
+		 * See SearchResult properties for list
+		 * @return
+		 */
+	
+	public Map<Integer,Object>
+	toPropertyMap();
+	
+	public String
+	getDownloadLink();
+	
+	public String
+	getPlayLink();
+	
+	public void
+	setRead(
+		boolean		read );
+	
+	public boolean
+	getRead();
+	
+	public void
+	delete();
+	
+	public boolean
+	isDeleted();
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionScheduler.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionScheduler.java
index 5929ec9..345df28 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionScheduler.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionScheduler.java
@@ -1,53 +1,52 @@
-/*
- * Created on Aug 6, 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.core.subs;
-
-public interface 
-SubscriptionScheduler 
-{
-	public void
-	download(
-		Subscription		subs,
-		boolean				is_auto )
-	
-		throws SubscriptionException;
-	
-	public void
-	downloadAsync(
-		Subscription		subs,
-		boolean				is_auto )
-	
-		throws SubscriptionException;
-	
-	public void
-	download(
-		Subscription					subs,
-		boolean							is_auto,
-		SubscriptionDownloadListener	listener )
-	
-		throws SubscriptionException;
-	
-	public void
-	download(
-		Subscription		subs,
-		SubscriptionResult	result );
-}
+/*
+ * Created on Aug 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+public interface 
+SubscriptionScheduler 
+{
+	public boolean
+	download(
+		Subscription		subs,
+		boolean				is_auto )
+	
+		throws SubscriptionException;
+	
+	public void
+	downloadAsync(
+		Subscription		subs,
+		boolean				is_auto )
+	
+		throws SubscriptionException;
+	
+	public void
+	download(
+		Subscription					subs,
+		boolean							is_auto,
+		SubscriptionDownloadListener	listener )
+	
+		throws SubscriptionException;
+	
+	public void
+	download(
+		Subscription		subs,
+		SubscriptionResult	result );
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionUtils.java b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionUtils.java
index 6ba5ca0..99e3700 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionUtils.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/SubscriptionUtils.java
@@ -1,115 +1,114 @@
-/*
- * Created on Sep 22, 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.core.subs;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-
-import com.aelitis.azureus.core.AzureusCore;
-
-public class 
-SubscriptionUtils 
-{
-	public static SubscriptionDownloadDetails[]
-	getAllCachedDownloadDetails(AzureusCore core)
-	{
-		List<DownloadManager> 	dms 	= core.getGlobalManager().getDownloadManagers();
-		
-		List<SubscriptionDownloadDetails>	result 	= new ArrayList<SubscriptionDownloadDetails>();
-		
-		SubscriptionManager sub_man = SubscriptionManagerFactory.getSingleton();
-		
-		for (int i=0;i<dms.size();i++){
-			
-			DownloadManager	dm = dms.get(i);
-			
-			TOTorrent torrent = dm.getTorrent();
-			
-			if ( torrent != null ){
-				
-				try{
-					Subscription[] subs = sub_man.getKnownSubscriptions( torrent.getHash());
-					
-					if ( subs != null && subs.length > 0 ){
-						
-						if ( sub_man.hideSearchTemplates()){
-							
-							List<Subscription>	filtered = new ArrayList<Subscription>();
-							
-							for ( Subscription s: subs ){
-								
-								if ( !s.isSearchTemplate()){
-									
-									filtered.add( s );
-								}
-							}
-							
-							if ( filtered.size() > 0 ){
-							
-								result.add( new SubscriptionDownloadDetails( dm, filtered.toArray( new Subscription[filtered.size()] )));
-							}
-						}else{
-							
-							result.add( new SubscriptionDownloadDetails( dm, subs ));
-						}
-					}
-				}catch( Throwable e ){
-				}
-			}
-		}
-		
-		return(result.toArray( new SubscriptionDownloadDetails[result.size()]));
-	}
-	
-
-	
-	public static class
-	SubscriptionDownloadDetails
-	{
-		private DownloadManager		download;
-		private Subscription[]		subscriptions;
-		
-		protected
-		SubscriptionDownloadDetails(
-			DownloadManager		dm,
-			Subscription[]		subs )
-		{
-			download 		= dm;
-			subscriptions	= subs;
-		}
-		
-		public DownloadManager
-		getDownload()
-		{
-			return( download );
-		}
-		
-		public Subscription[]
-		getSubscriptions()
-		{
-			return( subscriptions );
-		}
-	}
-}
+/*
+ * Created on Sep 22, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+
+import com.aelitis.azureus.core.AzureusCore;
+
+public class 
+SubscriptionUtils 
+{
+	public static SubscriptionDownloadDetails[]
+	getAllCachedDownloadDetails(AzureusCore core)
+	{
+		List<DownloadManager> 	dms 	= core.getGlobalManager().getDownloadManagers();
+		
+		List<SubscriptionDownloadDetails>	result 	= new ArrayList<SubscriptionDownloadDetails>();
+		
+		SubscriptionManager sub_man = SubscriptionManagerFactory.getSingleton();
+		
+		for (int i=0;i<dms.size();i++){
+			
+			DownloadManager	dm = dms.get(i);
+			
+			TOTorrent torrent = dm.getTorrent();
+			
+			if ( torrent != null ){
+				
+				try{
+					Subscription[] subs = sub_man.getKnownSubscriptions( torrent.getHash());
+					
+					if ( subs != null && subs.length > 0 ){
+						
+						if ( sub_man.hideSearchTemplates()){
+							
+							List<Subscription>	filtered = new ArrayList<Subscription>();
+							
+							for ( Subscription s: subs ){
+								
+								if ( !s.isSearchTemplate()){
+									
+									filtered.add( s );
+								}
+							}
+							
+							if ( filtered.size() > 0 ){
+							
+								result.add( new SubscriptionDownloadDetails( dm, filtered.toArray( new Subscription[filtered.size()] )));
+							}
+						}else{
+							
+							result.add( new SubscriptionDownloadDetails( dm, subs ));
+						}
+					}
+				}catch( Throwable e ){
+				}
+			}
+		}
+		
+		return(result.toArray( new SubscriptionDownloadDetails[result.size()]));
+	}
+	
+
+	
+	public static class
+	SubscriptionDownloadDetails
+	{
+		private DownloadManager		download;
+		private Subscription[]		subscriptions;
+		
+		protected
+		SubscriptionDownloadDetails(
+			DownloadManager		dm,
+			Subscription[]		subs )
+		{
+			download 		= dm;
+			subscriptions	= subs;
+		}
+		
+		public DownloadManager
+		getDownload()
+		{
+			return( download );
+		}
+		
+		public Subscription[]
+		getSubscriptions()
+		{
+			return( subscriptions );
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionBodyImpl.java b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionBodyImpl.java
index ab93377..93eec6a 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionBodyImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionBodyImpl.java
@@ -1,526 +1,525 @@
-/*
- * Created on Jul 15, 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.core.subs.impl;
-
-import java.io.File;
-import java.io.IOException;
-import java.security.Signature;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.BEncoder;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.SHA1Simple;
-
-import com.aelitis.azureus.core.security.CryptoECCUtils;
-import com.aelitis.azureus.core.subs.Subscription;
-import com.aelitis.azureus.core.subs.SubscriptionException;
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-import com.aelitis.azureus.core.vuzefile.VuzeFileComponent;
-import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
-
-public class 
-SubscriptionBodyImpl 
-{
-	private static final int SIMPLE_ID_LENGTH				= 10;
-
-	protected static byte[]
-	encode(
-		byte[]		hash,
-		int			version,
-		int			size )
-	{
-		int hash_len = hash.length;
-		
-		byte[]	result = new byte[ hash_len + 4 + 4 ];
-		
-		System.arraycopy( hash, 0, result, 0, hash_len );
-		System.arraycopy( SubscriptionImpl.intToBytes(version), 0, result, hash_len, 4 );
-		System.arraycopy( SubscriptionImpl.intToBytes(size), 0, result, hash_len+4, 4 );
-
-		return( result );
-	}
-	
-	protected static byte[]
-	sign(
-		byte[]		private_key,
-		byte[]		hash,
-		int			version,
-		int			size )
-	
-		throws Exception
-	{
-		Signature signature = CryptoECCUtils.getSignature( CryptoECCUtils.rawdataToPrivkey( private_key ));
-		
-		// key for signature is hash + version + size so we have some
-		// control over auto-update process and prevent people from injecting
-		// potentially huge bogus updates
-	
-		signature.update( encode( hash, version, size ));
-
-		return( signature.sign());
-	}
-	
-	protected static boolean
-	verify(
-		byte[]		public_key,
-		byte[]		hash,
-		int			version,
-		int			size,
-		byte[]		sig )
-	{
-		try{
-			Signature signature = CryptoECCUtils.getSignature( CryptoECCUtils.rawdataToPubkey( public_key ));
-	
-			signature.update( encode( hash, version, size ));
-	
-			return( signature.verify( sig ));
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-			
-			return( false );
-		}
-	}
-	
-	protected static byte[]
-	deriveShortID(
-		byte[]		public_key,
-		Map			singleton_details )
-	{
-		if ( singleton_details != null ){
-			
-			return( deriveSingletonShortID( singleton_details ));
-							
-		}else{
-		
-			byte[]	hash = new SHA1Simple().calculateHash( public_key );
-
-			byte[]	short_id = new byte[SIMPLE_ID_LENGTH];
-
-			System.arraycopy( hash, 0, short_id, 0, SIMPLE_ID_LENGTH );
-		
-			return( short_id );
-		}
-	}
-	
-	protected static byte[]
-  	deriveSingletonShortID(
-  		Map			singleton_details )
-  	{
-  		byte[]	short_id = new byte[SIMPLE_ID_LENGTH];
-
-  		byte[] 	explicit_sid = new SHA1Simple().calculateHash((byte[])singleton_details.get( "key" ));
-  			
-  		System.arraycopy( explicit_sid, 0, short_id, 0, SIMPLE_ID_LENGTH );
-  		
-  		return( short_id );
-  	}
-	
-	private SubscriptionManagerImpl		manager;
-	
-	private String	name;
-	private boolean	is_public;
-	private byte[]	public_key;
-	private int		version;
-	private int		az_version;
-	private String	json;
-	private Map		singleton_details;
-	
-	
-	
-	private byte[]	hash;
-	private byte[]	sig;
-	private int		sig_data_size;
-	
-	private Map		map;
-
-		// load constructor
-	
-	protected 
-	SubscriptionBodyImpl(
-		SubscriptionManagerImpl	_manager,
-		SubscriptionImpl		_subs )
-			
-		throws SubscriptionException
-	{
-		manager	= _manager;
-
-		try{
-			File vuze_file = manager.getVuzeFile( _subs );
-	
-			VuzeFile	vf = VuzeFileHandler.getSingleton().loadVuzeFile( vuze_file.getAbsolutePath());
-	
-			if ( vf == null ){
-				
-				throw( new IOException( "Failed to load vuze file '" + vuze_file + "'" ));
-			}
-					
-			load(  vf.getComponents()[0].getContent(), false );
-			
-		}catch( Throwable e ){
-			
-			rethrow( e );
-		}
-	}
-	
-		// import constructor
-	
-	protected 
-	SubscriptionBodyImpl(
-		SubscriptionManagerImpl	_manager,
-		Map						_map )
-	
-		throws IOException
-	{
-		manager	= _manager;
-
-		load( _map, true );
-	}
-	
-	protected void
-	load(
-		Map			_map,
-		boolean		_verify )
-	
-		throws IOException
-	{
-		map		= _map;
-		
-		hash 	= (byte[])map.get( "hash" );
-		sig	 	= (byte[])map.get( "sig" );
-		Long	l_size	= (Long)map.get( "size" );
-		
-		Map	details = (Map)map.get( "details" );
-		
-		if ( details == null || hash == null || sig == null || l_size == null ){
-			
-			throw( new IOException( "Invalid subscription - details missing" ));
-		}
-		
-		sig_data_size	= l_size.intValue();
-		
-		name		= new String((byte[])details.get( "name" ), "UTF-8" );
-		public_key	= (byte[])details.get( "public_key" );
-		version		= ((Long)details.get( "version" )).intValue();
-		is_public	= ((Long)details.get( "is_public" )).intValue()==1; 
-		json		= new String((byte[])details.get( "json"), "UTF-8" );
-		
-		singleton_details = (Map)details.get( "sin_details" );
-		
-		Long l_az_version	= (Long)details.get( "az_version" );
-		
-		az_version = l_az_version==null?Subscription.AZ_VERSION:l_az_version.intValue();
-		
-		if ( _verify ){
-			
-				// verify
-			
-			byte[] contents = BEncoder.encode( details );
-			
-			byte[] actual_hash = new SHA1Simple().calculateHash( contents );
-	
-			if ( !Arrays.equals( actual_hash, hash )){
-				
-					// backwards compat for pre-az_version
-							
-				Map details_copy = new HashMap( details );
-				
-				details_copy.remove( "az_version" );
-				
-				contents = BEncoder.encode( details_copy );
-				
-				actual_hash = new SHA1Simple().calculateHash( contents );
-			}
-			
-			if ( !Arrays.equals( actual_hash, hash )){
-
-				throw( new IOException( "Hash mismatch" ));
-			}
-			
-			if ( sig_data_size != contents.length ){
-				
-				throw( new IOException( "Signature data length mismatch" ));
-			}
-			
-			if ( !verify( public_key, hash, version, sig_data_size, sig )){
-					
-				throw( new IOException( "Signature verification failed" ));
-			}
-		}
-	}
-	
-		// create constructor
-	
-	protected
-	SubscriptionBodyImpl(
-		SubscriptionManagerImpl	_manager,
-		String					_name,
-		boolean					_is_public,
-		String					_json_content,
-		byte[]					_public_key,
-		int						_version,
-		int						_az_version,
-		Map						_singleton_details )
-	
-		throws IOException
-	{
-		manager		= _manager;
-		
-		name		= _name;
-		is_public	= _is_public;
-		public_key	= _public_key;
-		version		= _version;
-		az_version	= _az_version;
-		json		= _json_content;
-		
-		singleton_details	= _singleton_details;
-		
-		map			= new HashMap();
-		
-		Map details = new HashMap();
-			
-		map.put( "details", details );
-		
-		details.put( "name", name.getBytes( "UTF-8" ));
-		details.put( "is_public", new Long( is_public?1:0 ));
-		details.put( "public_key", public_key );
-		details.put( "version", new Long( version ));
-		details.put( "az_version", new Long( az_version ));
-		details.put( "json", _json_content.getBytes( "UTF-8" ));
-		
-		if ( singleton_details != null ){
-			
-			details.put( "sin_details", singleton_details );
-		}
-	}
-	
-	protected void
-	updateDetails(
-		SubscriptionImpl		subs,
-		Map						details )
-	
-		throws IOException
-	{
-		is_public	= subs.isPublic();
-		version		= subs.getVersion();
-		az_version	= subs.getAZVersion();
-		name		= subs.getName(false);
-		
-		details.put( "name",name.getBytes( "UTF-8" ));
-		details.put( "is_public", new Long( is_public?1:0 ));
-		details.put( "version", new Long( version ));
-		details.put( "az_version", new Long( az_version ));
-		
-		if ( json != null ){
-		
-			details.put( "json", json.getBytes( "UTF-8" ));
-		}
-		
-		if ( singleton_details != null ){
-			
-			details.put( "sin_details", singleton_details );
-		}
-	}
-	
-	protected String
-	getName()
-	{
-		return( name );
-	}
-	
-	protected byte[]
-	getPublicKey()
-	{
-		return( public_key );
-	}
-	
-	public byte[]
-	getShortID()
-	{
-		return( deriveShortID( public_key, singleton_details ));
-	}
-	
-	protected boolean
-	isPublic()
-	{
-		return( is_public );
-	}
-	
-	protected String
-	getJSON()
-	{
-		return( json );
-	}
-	
-	protected Map
-	getSingletonDetails()
-	{
-		return( singleton_details );
-	}
-	
-	protected void
-	setJSON(
-		String		_json )
-	{
-		json	= _json;
-	}
-	
-	protected int
-	getVersion()
-	{
-		return( version );
-	}
-	
-	protected int
-	getAZVersion()
-	{
-		return( az_version );
-	}
-	
-		// derived data
-	
-	protected byte[]
-	getHash()
-	{
-		return( hash );
-	}
-
-	protected byte[]
-	getSig()
-	{
-		return( sig );
-	}
-	
-	protected int
-	getSigDataSize()
-	{
-		return( sig_data_size );
-	}
-	
-	protected void
-	writeVuzeFile(
-		SubscriptionImpl		subs )
-	
-		throws SubscriptionException
-	{
-		try{
-			File file = manager.getVuzeFile( subs );
-							
-			Map	details = (Map)map.get( "details" );
-			
-			updateDetails( subs, details );
-			
-			byte[] contents = BEncoder.encode( details );
-					
-			byte[] new_hash = new SHA1Simple().calculateHash( contents );
-			
-			byte[] old_hash	= (byte[])map.get( "hash" );
-			
-				// backward compat from before az_version was introduced
-			
-			if ( old_hash != null && !Arrays.equals( old_hash, new_hash )){
-					
-				Map details_copy = new HashMap( details );
-				
-				details_copy.remove( "az_version" );
-				
-				contents = BEncoder.encode( details_copy );
-				
-				new_hash = new SHA1Simple().calculateHash( contents );
-			}
-			
-			if ( old_hash == null || !Arrays.equals( old_hash, new_hash )){
-				
-				byte[]	private_key = subs.getPrivateKey();
-				
-				if ( private_key == null ){
-					
-					throw( new SubscriptionException( "Only the originator of a subscription can modify it" ));
-				}
-							
-				map.put( "size", new Long( contents.length ));
-				
-				try{				
-					map.put( "hash", new_hash );
-					map.put( "sig", sign( private_key, new_hash, version, contents.length ));
-					
-				}catch( Throwable e ){
-					
-					throw( new SubscriptionException( "Crypto failed: " + Debug.getNestedExceptionMessage(e)));
-				}
-			}
-			
-			File	backup_file	= null;
-			
-			if ( file.exists()){
-				
-				backup_file = new File( file.getParent(), file.getName() + ".bak" );
-				
-				backup_file.delete();
-				
-				if ( !file.renameTo( backup_file )){
-					
-					throw( new SubscriptionException( "Backup failed" ));
-				}
-			}
-			
-			try{
-				VuzeFile	vf = VuzeFileHandler.getSingleton().create();
-				
-				vf.addComponent( VuzeFileComponent.COMP_TYPE_SUBSCRIPTION, map );
-				
-				vf.write( file );
-			
-				hash			= new_hash;
-				sig				= (byte[])map.get( "sig" );
-				sig_data_size	= contents.length;
-				
-			}catch( Throwable e ){
-				
-				if ( backup_file != null ){
-					
-					backup_file.renameTo( file );
-				}
-				
-				throw( new SubscriptionException( "File write failed: " + Debug.getNestedExceptionMessage(e)));
-			}
-		}catch( Throwable e ){
-			
-			rethrow( e );
-		}
-	}
-	
-	protected void
-	rethrow(
-		Throwable e )
-	
-		throws SubscriptionException
-	{
-		if ( e instanceof SubscriptionException ){
-			
-			throw((SubscriptionException)e);
-		}
-		
-		throw( new SubscriptionException( "Operation failed", e ));
-	}
-}
+/*
+ * Created on Jul 15, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.Signature;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.BEncoder;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.SHA1Simple;
+
+import com.aelitis.azureus.core.security.CryptoECCUtils;
+import com.aelitis.azureus.core.subs.Subscription;
+import com.aelitis.azureus.core.subs.SubscriptionException;
+import com.aelitis.azureus.core.vuzefile.VuzeFile;
+import com.aelitis.azureus.core.vuzefile.VuzeFileComponent;
+import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
+
+public class 
+SubscriptionBodyImpl 
+{
+	private static final int SIMPLE_ID_LENGTH				= 10;
+
+	protected static byte[]
+	encode(
+		byte[]		hash,
+		int			version,
+		int			size )
+	{
+		int hash_len = hash.length;
+		
+		byte[]	result = new byte[ hash_len + 4 + 4 ];
+		
+		System.arraycopy( hash, 0, result, 0, hash_len );
+		System.arraycopy( SubscriptionImpl.intToBytes(version), 0, result, hash_len, 4 );
+		System.arraycopy( SubscriptionImpl.intToBytes(size), 0, result, hash_len+4, 4 );
+
+		return( result );
+	}
+	
+	protected static byte[]
+	sign(
+		byte[]		private_key,
+		byte[]		hash,
+		int			version,
+		int			size )
+	
+		throws Exception
+	{
+		Signature signature = CryptoECCUtils.getSignature( CryptoECCUtils.rawdataToPrivkey( private_key ));
+		
+		// key for signature is hash + version + size so we have some
+		// control over auto-update process and prevent people from injecting
+		// potentially huge bogus updates
+	
+		signature.update( encode( hash, version, size ));
+
+		return( signature.sign());
+	}
+	
+	protected static boolean
+	verify(
+		byte[]		public_key,
+		byte[]		hash,
+		int			version,
+		int			size,
+		byte[]		sig )
+	{
+		try{
+			Signature signature = CryptoECCUtils.getSignature( CryptoECCUtils.rawdataToPubkey( public_key ));
+	
+			signature.update( encode( hash, version, size ));
+	
+			return( signature.verify( sig ));
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+			
+			return( false );
+		}
+	}
+	
+	protected static byte[]
+	deriveShortID(
+		byte[]		public_key,
+		Map			singleton_details )
+	{
+		if ( singleton_details != null ){
+			
+			return( deriveSingletonShortID( singleton_details ));
+							
+		}else{
+		
+			byte[]	hash = new SHA1Simple().calculateHash( public_key );
+
+			byte[]	short_id = new byte[SIMPLE_ID_LENGTH];
+
+			System.arraycopy( hash, 0, short_id, 0, SIMPLE_ID_LENGTH );
+		
+			return( short_id );
+		}
+	}
+	
+	protected static byte[]
+  	deriveSingletonShortID(
+  		Map			singleton_details )
+  	{
+  		byte[]	short_id = new byte[SIMPLE_ID_LENGTH];
+
+  		byte[] 	explicit_sid = new SHA1Simple().calculateHash((byte[])singleton_details.get( "key" ));
+  			
+  		System.arraycopy( explicit_sid, 0, short_id, 0, SIMPLE_ID_LENGTH );
+  		
+  		return( short_id );
+  	}
+	
+	private SubscriptionManagerImpl		manager;
+	
+	private String	name;
+	private boolean	is_public;
+	private byte[]	public_key;
+	private int		version;
+	private int		az_version;
+	private String	json;
+	private Map		singleton_details;
+	
+	
+	
+	private byte[]	hash;
+	private byte[]	sig;
+	private int		sig_data_size;
+	
+	private Map		map;
+
+		// load constructor
+	
+	protected 
+	SubscriptionBodyImpl(
+		SubscriptionManagerImpl	_manager,
+		SubscriptionImpl		_subs )
+			
+		throws SubscriptionException
+	{
+		manager	= _manager;
+
+		try{
+			File vuze_file = manager.getVuzeFile( _subs );
+	
+			VuzeFile	vf = VuzeFileHandler.getSingleton().loadVuzeFile( vuze_file.getAbsolutePath());
+	
+			if ( vf == null ){
+				
+				throw( new IOException( "Failed to load vuze file '" + vuze_file + "'" ));
+			}
+					
+			load(  vf.getComponents()[0].getContent(), false );
+			
+		}catch( Throwable e ){
+			
+			rethrow( e );
+		}
+	}
+	
+		// import constructor
+	
+	protected 
+	SubscriptionBodyImpl(
+		SubscriptionManagerImpl	_manager,
+		Map						_map )
+	
+		throws IOException
+	{
+		manager	= _manager;
+
+		load( _map, true );
+	}
+	
+	protected void
+	load(
+		Map			_map,
+		boolean		_verify )
+	
+		throws IOException
+	{
+		map		= _map;
+		
+		hash 	= (byte[])map.get( "hash" );
+		sig	 	= (byte[])map.get( "sig" );
+		Long	l_size	= (Long)map.get( "size" );
+		
+		Map	details = (Map)map.get( "details" );
+		
+		if ( details == null || hash == null || sig == null || l_size == null ){
+			
+			throw( new IOException( "Invalid subscription - details missing" ));
+		}
+		
+		sig_data_size	= l_size.intValue();
+		
+		name		= new String((byte[])details.get( "name" ), "UTF-8" );
+		public_key	= (byte[])details.get( "public_key" );
+		version		= ((Long)details.get( "version" )).intValue();
+		is_public	= ((Long)details.get( "is_public" )).intValue()==1; 
+		json		= new String((byte[])details.get( "json"), "UTF-8" );
+		
+		singleton_details = (Map)details.get( "sin_details" );
+		
+		Long l_az_version	= (Long)details.get( "az_version" );
+		
+		az_version = l_az_version==null?Subscription.AZ_VERSION:l_az_version.intValue();
+		
+		if ( _verify ){
+			
+				// verify
+			
+			byte[] contents = BEncoder.encode( details );
+			
+			byte[] actual_hash = new SHA1Simple().calculateHash( contents );
+	
+			if ( !Arrays.equals( actual_hash, hash )){
+				
+					// backwards compat for pre-az_version
+							
+				Map details_copy = new HashMap( details );
+				
+				details_copy.remove( "az_version" );
+				
+				contents = BEncoder.encode( details_copy );
+				
+				actual_hash = new SHA1Simple().calculateHash( contents );
+			}
+			
+			if ( !Arrays.equals( actual_hash, hash )){
+
+				throw( new IOException( "Hash mismatch" ));
+			}
+			
+			if ( sig_data_size != contents.length ){
+				
+				throw( new IOException( "Signature data length mismatch" ));
+			}
+			
+			if ( !verify( public_key, hash, version, sig_data_size, sig )){
+					
+				throw( new IOException( "Signature verification failed" ));
+			}
+		}
+	}
+	
+		// create constructor
+	
+	protected
+	SubscriptionBodyImpl(
+		SubscriptionManagerImpl	_manager,
+		String					_name,
+		boolean					_is_public,
+		String					_json_content,
+		byte[]					_public_key,
+		int						_version,
+		int						_az_version,
+		Map						_singleton_details )
+	
+		throws IOException
+	{
+		manager		= _manager;
+		
+		name		= _name;
+		is_public	= _is_public;
+		public_key	= _public_key;
+		version		= _version;
+		az_version	= _az_version;
+		json		= _json_content;
+		
+		singleton_details	= _singleton_details;
+		
+		map			= new HashMap();
+		
+		Map details = new HashMap();
+			
+		map.put( "details", details );
+		
+		details.put( "name", name.getBytes( "UTF-8" ));
+		details.put( "is_public", new Long( is_public?1:0 ));
+		details.put( "public_key", public_key );
+		details.put( "version", new Long( version ));
+		details.put( "az_version", new Long( az_version ));
+		details.put( "json", _json_content.getBytes( "UTF-8" ));
+		
+		if ( singleton_details != null ){
+			
+			details.put( "sin_details", singleton_details );
+		}
+	}
+	
+	protected void
+	updateDetails(
+		SubscriptionImpl		subs,
+		Map						details )
+	
+		throws IOException
+	{
+		is_public	= subs.isPublic();
+		version		= subs.getVersion();
+		az_version	= subs.getAZVersion();
+		name		= subs.getName(false);
+		
+		details.put( "name",name.getBytes( "UTF-8" ));
+		details.put( "is_public", new Long( is_public?1:0 ));
+		details.put( "version", new Long( version ));
+		details.put( "az_version", new Long( az_version ));
+		
+		if ( json != null ){
+		
+			details.put( "json", json.getBytes( "UTF-8" ));
+		}
+		
+		if ( singleton_details != null ){
+			
+			details.put( "sin_details", singleton_details );
+		}
+	}
+	
+	protected String
+	getName()
+	{
+		return( name );
+	}
+	
+	protected byte[]
+	getPublicKey()
+	{
+		return( public_key );
+	}
+	
+	public byte[]
+	getShortID()
+	{
+		return( deriveShortID( public_key, singleton_details ));
+	}
+	
+	protected boolean
+	isPublic()
+	{
+		return( is_public );
+	}
+	
+	protected String
+	getJSON()
+	{
+		return( json );
+	}
+	
+	protected Map
+	getSingletonDetails()
+	{
+		return( singleton_details );
+	}
+	
+	protected void
+	setJSON(
+		String		_json )
+	{
+		json	= _json;
+	}
+	
+	protected int
+	getVersion()
+	{
+		return( version );
+	}
+	
+	protected int
+	getAZVersion()
+	{
+		return( az_version );
+	}
+	
+		// derived data
+	
+	protected byte[]
+	getHash()
+	{
+		return( hash );
+	}
+
+	protected byte[]
+	getSig()
+	{
+		return( sig );
+	}
+	
+	protected int
+	getSigDataSize()
+	{
+		return( sig_data_size );
+	}
+	
+	protected void
+	writeVuzeFile(
+		SubscriptionImpl		subs )
+	
+		throws SubscriptionException
+	{
+		try{
+			File file = manager.getVuzeFile( subs );
+							
+			Map	details = (Map)map.get( "details" );
+			
+			updateDetails( subs, details );
+			
+			byte[] contents = BEncoder.encode( details );
+					
+			byte[] new_hash = new SHA1Simple().calculateHash( contents );
+			
+			byte[] old_hash	= (byte[])map.get( "hash" );
+			
+				// backward compat from before az_version was introduced
+			
+			if ( old_hash != null && !Arrays.equals( old_hash, new_hash )){
+					
+				Map details_copy = new HashMap( details );
+				
+				details_copy.remove( "az_version" );
+				
+				contents = BEncoder.encode( details_copy );
+				
+				new_hash = new SHA1Simple().calculateHash( contents );
+			}
+			
+			if ( old_hash == null || !Arrays.equals( old_hash, new_hash )){
+				
+				byte[]	private_key = subs.getPrivateKey();
+				
+				if ( private_key == null ){
+					
+					throw( new SubscriptionException( "Only the originator of a subscription can modify it" ));
+				}
+							
+				map.put( "size", new Long( contents.length ));
+				
+				try{				
+					map.put( "hash", new_hash );
+					map.put( "sig", sign( private_key, new_hash, version, contents.length ));
+					
+				}catch( Throwable e ){
+					
+					throw( new SubscriptionException( "Crypto failed: " + Debug.getNestedExceptionMessage(e)));
+				}
+			}
+			
+			File	backup_file	= null;
+			
+			if ( file.exists()){
+				
+				backup_file = new File( file.getParent(), file.getName() + ".bak" );
+				
+				backup_file.delete();
+				
+				if ( !file.renameTo( backup_file )){
+					
+					throw( new SubscriptionException( "Backup failed" ));
+				}
+			}
+			
+			try{
+				VuzeFile	vf = VuzeFileHandler.getSingleton().create();
+				
+				vf.addComponent( VuzeFileComponent.COMP_TYPE_SUBSCRIPTION, map );
+				
+				vf.write( file );
+			
+				hash			= new_hash;
+				sig				= (byte[])map.get( "sig" );
+				sig_data_size	= contents.length;
+				
+			}catch( Throwable e ){
+				
+				if ( backup_file != null ){
+					
+					backup_file.renameTo( file );
+				}
+				
+				throw( new SubscriptionException( "File write failed: " + Debug.getNestedExceptionMessage(e)));
+			}
+		}catch( Throwable e ){
+			
+			rethrow( e );
+		}
+	}
+	
+	protected void
+	rethrow(
+		Throwable e )
+	
+		throws SubscriptionException
+	{
+		if ( e instanceof SubscriptionException ){
+			
+			throw((SubscriptionException)e);
+		}
+		
+		throw( new SubscriptionException( "Operation failed", e ));
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionDownloader.java b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionDownloader.java
index 9404852..3bff68e 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionDownloader.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionDownloader.java
@@ -1,169 +1,168 @@
-/*
- * Created on Aug 6, 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.core.subs.impl;
-
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.Result;
-import com.aelitis.azureus.core.metasearch.SearchLoginException;
-import com.aelitis.azureus.core.metasearch.SearchParameter;
-import com.aelitis.azureus.core.subs.*;
-import com.aelitis.azureus.util.JSONUtils;
-
-public class 
-SubscriptionDownloader 
-{
-	private SubscriptionManagerImpl		manager;
-	private SubscriptionImpl			subs;
-	
-	protected
-	SubscriptionDownloader(
-		SubscriptionManagerImpl	_manager,
-		SubscriptionImpl		_subs )
-	
-		throws SubscriptionException
-	{
-		manager	= _manager;
-		subs	= _subs;
-	}
-	
-	protected void
-	download()
-	
-		throws SubscriptionException
-	{
-		log( "Downloading" );
-		
-		Map map = JSONUtils.decodeJSON( subs.getJSON());
-		
-		Long 	engine_id 	= (Long)map.get( "engine_id" );
-		String	search_term	= (String)map.get( "search_term" );
-		Map		filters		= (Map)map.get( "filters" );
-
-		Engine engine = manager.getEngine( subs, map, false );
-		
-		if ( engine == null ){
-			
-			throw( new SubscriptionException( "Download failed, search engine " + engine_id + " not found" ));
-		}
-		
-		List	sps = new ArrayList();
-		
-		if ( search_term != null ){
-			
-			sps.add( new SearchParameter( "s", search_term ));
-		
-			log( "    Using search term '" + search_term + "' for engine " + engine.getString());
-		}
-		
-		/*
-		if ( mature != null ){
-			
-			sps.add( new SearchParameter( "m", mature.toString()));
-		}
-		*/
-		
-		SearchParameter[] parameters = (SearchParameter[])sps.toArray(new SearchParameter[ sps.size()] );
-
-		
-		SubscriptionHistoryImpl history = (SubscriptionHistoryImpl)subs.getHistory();
-		
-		try{	
-			Map	context = new HashMap();
-			
-			context.put( Engine.SC_SOURCE, 	"subscription" );
-			
-			Result[] results = engine.search( parameters, context, -1, -1, null, null );
-		
-			log( "    Got " + results.length + " results" );
-			
-			SubscriptionResultFilter result_filter = new SubscriptionResultFilter(filters );
-
-			results = result_filter.filter( results );
-			
-			log( "    Post-filter: " + results.length + " results" );
-
-			SubscriptionResultImpl[]	s_results = new SubscriptionResultImpl[results.length];
-			
-			for( int i=0;i<results.length;i++){
-				
-				SubscriptionResultImpl	s_result = new SubscriptionResultImpl( history, results[i] );
-				
-				s_results[i] = s_result;
-			}
-			
-			SubscriptionResultImpl[] all_results = history.reconcileResults( engine, s_results );
-						
-			checkAutoDownload( all_results );
-			
-			history.setLastError( null, false );
-			
-		}catch( Throwable e ){
-			
-			log( "    Download failed", e);
-			
-			history.setLastError( Debug.getNestedExceptionMessage( e ),e instanceof SearchLoginException );
-			
-			throw( new SubscriptionException( "Search failed", e ));
-		}
-	}
-	
-	protected void
-	checkAutoDownload(
-		SubscriptionResultImpl[]	results )
-	{
-		if ( !subs.getHistory().isAutoDownload()){
-			
-			return;
-		}
-		
-		for (int i=0;i<results.length;i++){
-			
-			SubscriptionResultImpl	result = results[i];
-			
-			if ( result.isDeleted() || result.getRead()){
-				
-				continue;
-			}
-						
-			manager.getScheduler().download( subs, result );
-		}
-	}
-	
-	protected void
-	log(
-		String		str )
-	{
-		manager.log( str );
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable	e )
-	{
-		manager.log( str, e );
-	}
-}
+/*
+ * Created on Aug 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs.impl;
+
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.Debug;
+
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.Result;
+import com.aelitis.azureus.core.metasearch.SearchLoginException;
+import com.aelitis.azureus.core.metasearch.SearchParameter;
+import com.aelitis.azureus.core.subs.*;
+import com.aelitis.azureus.util.JSONUtils;
+
+public class 
+SubscriptionDownloader 
+{
+	private SubscriptionManagerImpl		manager;
+	private SubscriptionImpl			subs;
+	
+	protected
+	SubscriptionDownloader(
+		SubscriptionManagerImpl	_manager,
+		SubscriptionImpl		_subs )
+	
+		throws SubscriptionException
+	{
+		manager	= _manager;
+		subs	= _subs;
+	}
+	
+	protected void
+	download()
+	
+		throws SubscriptionException
+	{
+		log( "Downloading" );
+		
+		Map map = JSONUtils.decodeJSON( subs.getJSON());
+		
+		Long 	engine_id 	= (Long)map.get( "engine_id" );
+		String	search_term	= (String)map.get( "search_term" );
+		Map		filters		= (Map)map.get( "filters" );
+
+		Engine engine = manager.getEngine( subs, map, false );
+		
+		if ( engine == null ){
+			
+			throw( new SubscriptionException( "Download failed, search engine " + engine_id + " not found" ));
+		}
+		
+		List	sps = new ArrayList();
+		
+		if ( search_term != null ){
+			
+			sps.add( new SearchParameter( "s", search_term ));
+		
+			log( "    Using search term '" + search_term + "' for engine " + engine.getString());
+		}
+		
+		/*
+		if ( mature != null ){
+			
+			sps.add( new SearchParameter( "m", mature.toString()));
+		}
+		*/
+		
+		SearchParameter[] parameters = (SearchParameter[])sps.toArray(new SearchParameter[ sps.size()] );
+
+		
+		SubscriptionHistoryImpl history = (SubscriptionHistoryImpl)subs.getHistory();
+		
+		try{	
+			Map	context = new HashMap();
+			
+			context.put( Engine.SC_SOURCE, 	"subscription" );
+			
+			Result[] results = engine.search( parameters, context, -1, -1, null, null );
+		
+			log( "    Got " + results.length + " results" );
+			
+			SubscriptionResultFilter result_filter = new SubscriptionResultFilter(filters );
+
+			results = result_filter.filter( results );
+			
+			log( "    Post-filter: " + results.length + " results" );
+
+			SubscriptionResultImpl[]	s_results = new SubscriptionResultImpl[results.length];
+			
+			for( int i=0;i<results.length;i++){
+				
+				SubscriptionResultImpl	s_result = new SubscriptionResultImpl( history, results[i] );
+				
+				s_results[i] = s_result;
+			}
+			
+			SubscriptionResultImpl[] all_results = history.reconcileResults( engine, s_results );
+						
+			checkAutoDownload( all_results );
+			
+			history.setLastError( null, false );
+			
+		}catch( Throwable e ){
+			
+			log( "    Download failed", e);
+			
+			history.setLastError( Debug.getNestedExceptionMessage( e ),e instanceof SearchLoginException );
+			
+			throw( new SubscriptionException( "Search failed", e ));
+		}
+	}
+	
+	protected void
+	checkAutoDownload(
+		SubscriptionResultImpl[]	results )
+	{
+		if ( !subs.getHistory().isAutoDownload()){
+			
+			return;
+		}
+		
+		for (int i=0;i<results.length;i++){
+			
+			SubscriptionResultImpl	result = results[i];
+			
+			if ( result.isDeleted() || result.getRead()){
+				
+				continue;
+			}
+						
+			manager.getScheduler().download( subs, result );
+		}
+	}
+	
+	protected void
+	log(
+		String		str )
+	{
+		manager.log( str );
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable	e )
+	{
+		manager.log( str, e );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionHistoryImpl.java b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionHistoryImpl.java
index d904fdb..a59e278 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionHistoryImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionHistoryImpl.java
@@ -1,992 +1,1030 @@
-/*
- * Created on Aug 6, 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.core.subs.impl;
-
-import java.util.*;
-
-import org.gudy.azureus2.core3.download.DownloadManager;
-import org.gudy.azureus2.core3.global.GlobalManager;
-import org.gudy.azureus2.core3.util.Base32;
-import org.gudy.azureus2.core3.util.ByteArrayHashMap;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.HashWrapper;
-import org.gudy.azureus2.core3.util.SystemTime;
-
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.subs.SubscriptionHistory;
-import com.aelitis.azureus.core.subs.SubscriptionResult;
-
-public class 
-SubscriptionHistoryImpl
-	implements SubscriptionHistory
-{
-	private final SubscriptionManagerImpl		manager;
-	private final SubscriptionImpl				subs;
-	
-	private boolean		enabled;
-	private boolean		auto_dl;
-	
-	private long		last_scan;
-	private long		last_new_result;
-	private int			num_unread;
-	private int			num_read;
-	
-	private String			last_error;
-	private boolean			auth_failed;
-	private int				consec_fails;
-	
-	private boolean			auto_dl_supported;
-	
-	private boolean			dl_with_ref	= true;
-	
-	protected
-	SubscriptionHistoryImpl(
-		SubscriptionManagerImpl		_manager,
-		SubscriptionImpl			_subs )
-	{
-		manager		= _manager;
-		subs		= _subs;
-		
-		loadConfig();
-	}
-	
-	protected SubscriptionResultImpl[]
-	reconcileResults(
-		Engine							engine,
-		SubscriptionResultImpl[]		latest_results )
-	{
-		auto_dl_supported	= engine.getAutoDownloadSupported() == Engine.AUTO_DL_SUPPORTED_YES;
-		
-		int	new_unread 	= 0;
-		int new_read	= 0;
-					
-		if ( last_scan == 0 ){
-				
-					// first download feed -> mark all existing as read
-						
-			GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
-			
-			for (int i=0;i<latest_results.length;i++){
-					
-				SubscriptionResultImpl result = latest_results[i];
-				
-				result.setReadInternal(true);
-				
-					// see if we can associate result with existing download
-				
-				try{
-					String hash_str = result.getAssetHash();
-					
-					if ( hash_str != null ){
-						
-						byte[] hash = Base32.decode( hash_str );
-						
-						DownloadManager dm = gm.getDownloadManager( new HashWrapper( hash ));
-						
-						if ( dm != null ){
-							
-							log( "Adding existing association on first read for '" + dm.getDisplayName());
-							
-							subs.addAssociation( hash );
-						}
-					}
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-		}
-		
-		long	now = SystemTime.getCurrentTime();
-		
-		SubscriptionResultImpl[] result;
-		
-		int	max_results = manager.getMaxNonDeletedResults();
-		
-		synchronized( this ){
-			
-			boolean	got_new_or_changed_result	= false;
-			
-			SubscriptionResultImpl[] existing_results = manager.loadResults( subs );
-					
-			ByteArrayHashMap	result_key_map 	= new ByteArrayHashMap();
-			ByteArrayHashMap	result_key2_map = new ByteArrayHashMap();
-			
-			List	new_results = new ArrayList();
-
-			for (int i=0;i<existing_results.length;i++){
-				
-				SubscriptionResultImpl r = existing_results[i];
-				
-				result_key_map.put( r.getKey1(), r );
-				
-				byte[]	key2 = r.getKey2();
-				
-				if ( key2 != null ){
-					
-					result_key2_map.put( key2, r );
-				}
-				
-				new_results.add( r );
-				
-				if ( !r.isDeleted()){
-					
-					if ( r.getRead()){
-						
-						new_read++;
-						
-					}else{
-						
-						new_unread++;
-					}
-				}
-			}
-						
-			for (int i=0;i<latest_results.length;i++){
-
-				SubscriptionResultImpl r = latest_results[i];
-				
-					// we first of all insist on names uniqueness
-				
-				SubscriptionResultImpl existing = (SubscriptionResultImpl)result_key_map.get( r.getKey1());
-				
-				if ( existing == null ){
-					
-						// only if non-unique name do we fall back and use UID to remove duplicate
-						// entries where the name has changed
-					
-					byte[]	key2 = r.getKey2();
-					
-					if ( key2 != null ){
-						
-						existing = (SubscriptionResultImpl)result_key2_map.get( key2 );
-					}
-				}
-				
-				if ( existing == null ){
-					
-					last_new_result = now;
-					
-					new_results.add( r );
-					
-					result_key_map.put( r.getKey1(), r );
-					
-					byte[]	key2 = r.getKey2();
-					
-					if ( key2 != null ){
-						
-						result_key2_map.put( key2, r );
-					}
-					
-					got_new_or_changed_result = true;
-				
-					if ( r.getRead()){
-						
-						new_read++;
-						
-					}else{
-					
-						new_unread++;
-					}
-				}else{
-					
-					if ( existing.updateFrom( r )){
-						
-						got_new_or_changed_result = true;
-					}
-				}
-			}
-			
-				// see if we need to delete any old ones
-			
-			if ( max_results > 0 && (new_unread + new_read ) > max_results ){
-				
-				for (int i=0;i<new_results.size();i++){
-					
-					SubscriptionResultImpl r = (SubscriptionResultImpl)new_results.get(i);
-					
-					if ( !r.isDeleted()){
-						
-						if ( r.getRead()){
-							
-							new_read--;
-							
-						}else{
-							
-							new_unread--;
-						}
-						
-						r.deleteInternal();
-						
-						got_new_or_changed_result = true;
-						
-						if (( new_unread + new_read ) <= max_results ){
-							
-							break;
-						}
-					}
-				}
-			}
-			
-			if ( got_new_or_changed_result ){
-				
-				result = (SubscriptionResultImpl[])new_results.toArray( new SubscriptionResultImpl[new_results.size()]);
-				
-				manager.saveResults( subs, result );
-				
-			}else{
-				
-				result = existing_results;
-			}
-		
-			last_scan 	= now;
-			num_unread	= new_unread;
-			num_read	= new_read;
-		}
-		
-			// always save config as we have a new scan time
-		
-		saveConfig();
-		
-		return( result );
-	}
-	
-	public boolean
-	isEnabled()
-	{
-		return( enabled );
-	}
-	
-	public void
-	setEnabled(
-		boolean		_enabled )
-	{
-		if ( _enabled != enabled ){
-			
-			enabled	= _enabled;
-		
-			saveConfig();
-		}
-	}
-	
-	public boolean
-	isAutoDownload()
-	{
-		return( auto_dl );
-	}
-	
-	public void
-	setAutoDownload(
-		boolean		_auto_dl )
-	{
-		if ( _auto_dl != auto_dl ){
-			
-			auto_dl	= _auto_dl;
-		
-			saveConfig();
-			
-			if ( auto_dl ){
-				
-				downloadNow();
-			}
-		}
-	}
-	
-	public void 
-	setDetails(
-		boolean 	_enabled, 
-		boolean 	_auto_dl ) 
-	{
-		if ( enabled != _enabled || auto_dl != _auto_dl ){
-			
-			enabled	= _enabled;
-			auto_dl	= _auto_dl;
-			
-			saveConfig();
-			
-			if ( enabled && auto_dl ){
-				
-				downloadNow();
-			}
-		}
-	}
-	
-	protected void
-	downloadNow()
-	{
-		try{
-			subs.getManager().getScheduler().downloadAsync( subs, false );
-			
-		}catch( Throwable e ){
-			
-			log( "Failed to initiate download", e );
-		}
-	}
-	
-	public long
-	getLastScanTime()
-	{
-		return( last_scan );
-	}
-	
-	public long 
-	getLastNewResultTime() 
-	{
-		return( last_new_result );
-	}
-	
-	public long
-	getNextScanTime()
-	{
-		Map	schedule = subs.getScheduleConfig();
-		
-		if ( schedule.size() == 0  ){
-			
-			log( "Schedule is empty!");
-			
-			return( Long.MAX_VALUE );
-			
-		}else{
-			
-			try{
-			
-				long	interval_min = ((Long)schedule.get( "interval" )).longValue();
-				
-				if ( interval_min == Integer.MAX_VALUE || interval_min == Long.MAX_VALUE ){
-					
-					return( Long.MAX_VALUE );
-				}
-				
-				if ( last_scan == 0 ){
-					
-						// never scanned, scan immediately
-					
-					return( SystemTime.getCurrentTime());
-					
-				}else{
-				
-					return( last_scan + interval_min*60*1000 );
-				}
-			}catch( Throwable e ){
-				
-				log( "Failed to decode schedule " + schedule, e );
-				
-				return( Long.MAX_VALUE );
-			}
-		}
-	}
-	
-	public int
-	getCheckFrequencyMins()
-	{
-		Map	schedule = subs.getScheduleConfig();
-		
-		if ( schedule.size() == 0  ){
-			
-			return( DEFAULT_CHECK_INTERVAL_MINS );
-			
-		}else{
-			
-			try{		
-				int	interval_min = ((Long)schedule.get( "interval" )).intValue();
-				
-				return( interval_min );
-				
-			}catch( Throwable e ){
-								
-				return( DEFAULT_CHECK_INTERVAL_MINS );
-			}
-		}
-	}
-	
-	public int
-	getNumUnread()
-	{
-		return( num_unread );
-	}
-	
-	public int
-	getNumRead()
-	{
-		return( num_read );
-	}
-	
-	public SubscriptionResult[]
-	getResults(
-		boolean		include_deleted )
-	{
-		SubscriptionResult[] results;
-		
-		synchronized( this ){
-			
-			results = manager.loadResults( subs );
-		}
-		
-		if ( include_deleted ){
-			
-			return( results );
-			
-		}else{
-			
-			List	l = new ArrayList( results.length );
-			
-			for (int i=0;i<results.length;i++){
-				
-				if ( !results[i].isDeleted()){
-					
-					l.add( results[i] );
-				}
-			}
-			
-			return((SubscriptionResult[])l.toArray( new SubscriptionResult[l.size()]));
-		}
-	}
-	
-	public SubscriptionResult
-	getResult(
-		String		result_id )
-	{
-		SubscriptionResult[] results = getResults( true );
-		
-		for (int i=0;i<results.length;i++){
-			
-			if ( results[i].getID().equals( result_id )){
-				
-				return( results[i] );
-			}
-		}
-		
-		return( null );
-	}
-	
-	protected void
-	updateResult(
-		SubscriptionResultImpl 	result )
-	{
-		byte[]	key = result.getKey1();
-		
-		boolean	changed = false;
-
-		synchronized( this ){
-			
-			SubscriptionResultImpl[] results = manager.loadResults( subs );
-						
-			for (int i=0;i<results.length;i++){
-				
-				if ( Arrays.equals( results[i].getKey1(), key )){
-					
-					results[i] = result;
-					
-					changed	= true;
-				}
-			}
-			
-			if ( changed ){
-				
-				updateReadUnread( results );
-				
-				manager.saveResults( subs, results );
-			}
-		}
-		
-		if ( changed ){
-			
-			saveConfig();
-		}
-		
-		if ( isAutoDownload() && !result.getRead() && !result.isDeleted()){
-			
-			manager.getScheduler().download( subs, result );		
-		}
-	}
-	
-
-	public void 
-	deleteResults(
-		String[] result_ids )
-	{
-		ByteArrayHashMap rids = new ByteArrayHashMap();
-		
-		for (int i=0;i<result_ids.length;i++){
-			
-			rids.put( Base32.decode( result_ids[i]), "" );
-		}
-	
-		boolean	changed = false;
-
-		synchronized( this ){
-				
-			SubscriptionResultImpl[] results = manager.loadResults( subs );
-
-			for (int i=0;i<results.length;i++){
-				
-				SubscriptionResultImpl result = results[i];
-				
-				if ( !result.isDeleted() && rids.containsKey( result.getKey1())){
-					
-					changed = true;
-					
-					result.deleteInternal();
-				}
-			}
-			
-			if ( changed ){
-				
-				updateReadUnread( results );
-				
-				manager.saveResults( subs, results );
-			}
-		}
-		
-		if ( changed ){
-			
-			saveConfig();
-		}
-	}
-	
-	public void
-	deleteAllResults()
-	{
-		boolean	changed = false;
-		
-		synchronized( this ){
-						
-			SubscriptionResultImpl[] results = manager.loadResults( subs );
-
-			for (int i=0;i<results.length;i++){
-				
-				SubscriptionResultImpl result = results[i];
-				
-				if ( !result.isDeleted()){
-					
-					changed = true;
-				
-					result.deleteInternal();
-				}
-			}
-			
-			if ( changed ){
-				
-				updateReadUnread( results );
-				
-				manager.saveResults( subs, results );
-			}
-		}
-		
-		if ( changed ){
-			
-			saveConfig();
-		}
-	}
-	
-	public void
-	markAllResultsRead()
-	{
-		boolean	changed = false;
-		
-		synchronized( this ){
-						
-			SubscriptionResultImpl[] results = manager.loadResults( subs );
-
-			for (int i=0;i<results.length;i++){
-				
-				SubscriptionResultImpl result = results[i];
-				
-				if ( !result.getRead()){
-					
-					changed = true;
-				
-					result.setReadInternal( true );
-				}
-			}
-			
-			if ( changed ){
-				
-				updateReadUnread( results );
-				
-				manager.saveResults( subs, results );
-			}
-		}
-		
-		if ( changed ){
-			
-			saveConfig();
-		}
-	}
-	
-	public void
-	markAllResultsUnread()
-	{
-		boolean	changed = false;
-		
-		synchronized( this ){
-						
-			SubscriptionResultImpl[] results = manager.loadResults( subs );
-
-			for (int i=0;i<results.length;i++){
-				
-				SubscriptionResultImpl result = results[i];
-				
-				if ( result.getRead()){
-					
-					changed = true;
-				
-					result.setReadInternal( false );
-				}
-			}
-			
-			if ( changed ){
-				
-				updateReadUnread( results );
-				
-				manager.saveResults( subs, results );
-			}
-		}
-		
-		if ( changed ){
-			
-			saveConfig();
-		}
-	}
-	
-	public void 
-	markResults(
-		String[] 		result_ids,
-		boolean[]		reads )
-	{
-		ByteArrayHashMap rid_map = new ByteArrayHashMap();
-		
-		for (int i=0;i<result_ids.length;i++){
-			
-			rid_map.put( Base32.decode( result_ids[i]), new Boolean( reads[i] ));
-		}
-	
-		boolean	changed = false;
-
-		List	newly_unread = new ArrayList();
-		
-		synchronized( this ){
-						
-			SubscriptionResultImpl[] results = manager.loadResults( subs );
-
-			for (int i=0;i<results.length;i++){
-				
-				SubscriptionResultImpl result = results[i];
-				
-				if ( result.isDeleted()){
-					
-					continue;
-				}
-				
-				Boolean	b_read = (Boolean)rid_map.get( result.getKey1());
-				
-				if ( b_read != null ){
-					
-					boolean	read = b_read.booleanValue();
-					
-					if ( result.getRead() != read ){
-						
-						changed = true;
-					
-						result.setReadInternal( read );
-						
-						if ( !read ){
-							
-							newly_unread.add( result );
-						}
-					}
-				}
-			}
-			
-			if ( changed ){
-				
-				updateReadUnread( results );
-				
-				manager.saveResults( subs, results );
-			}
-		}
-		
-		if ( changed ){
-			
-			saveConfig();
-		}
-		
-		if ( isAutoDownload()){
-			
-			for (int i=0;i<newly_unread.size();i++){
-				
-				manager.getScheduler().download( subs, (SubscriptionResult)newly_unread.get(i));
-			}
-		}
-	}
-	
-	public void 
-	reset() 
-	{
-		synchronized( this ){
-			
-			SubscriptionResultImpl[] results = manager.loadResults( subs );
-			
-			if ( results.length > 0 ){
-				
-				results = new SubscriptionResultImpl[0];
-								
-				manager.saveResults( subs, results );
-			}
-			
-			updateReadUnread( results );
-		}
-		
-		last_error		= null;
-		last_new_result	= 0;
-		last_scan		= 0;
-					
-		saveConfig();
-	}
-	
-	protected void
-	checkMaxResults(
-		int		max_results )
-	{
-		if ( max_results <= 0 ){
-			
-			return;
-		}
-		
-		boolean	changed = false;
-
-		synchronized( this ){
-
-			if ((num_unread + num_read ) > max_results ){
-
-				SubscriptionResultImpl[] results = manager.loadResults( subs );
-				
-				for (int i=0;i<results.length;i++){
-					
-					SubscriptionResultImpl r = results[i];
-					
-					if ( !r.isDeleted()){
-						
-						if ( r.getRead()){
-							
-							num_read--;
-							
-						}else{
-							
-							num_unread--;
-						}
-						
-						r.deleteInternal();
-						
-						changed = true;
-						
-						if (( num_unread + num_read ) <= max_results ){
-							
-							break;
-						}
-					}
-				}
-				
-				if ( changed ){
-					
-					manager.saveResults( subs, results );
-				}
-			}
-		}
-		
-		if ( changed ){
-			
-			saveConfig();
-		}
-	}
-	
-	protected void
-	updateReadUnread(
-		SubscriptionResultImpl[]	results )
-	{
-		int	new_unread	= 0;
-		int	new_read	= 0;
-		
-		for (int i=0;i<results.length;i++){
-			
-			SubscriptionResultImpl result = results[i];
-			
-			if ( !result.isDeleted()){
-				
-				if ( result.getRead()){
-					
-					new_read++;
-					
-				}else{
-					
-					new_unread++;
-				}
-			}
-		}
-		
-		num_read	= new_read;
-		num_unread	= new_unread;
-	}
-	
-	protected boolean
-	isAutoDownloadSupported()
-	{
-		return( auto_dl_supported );
-	}
-	
-	protected void
-	setFatalError(
-		String		_error )
-	{
-		last_error		= _error;
-		consec_fails	= 1024;
-	}
-	
-	protected void
-	setLastError(
-		String		_last_error,
-		boolean		_auth_failed )
-	{
-		last_error 		= _last_error;
-		auth_failed		= _auth_failed;
-		
-		if ( last_error == null ){
-			
-			consec_fails = 0;
-			
-		}else{
-			
-			consec_fails++;
-		}
-		
-		subs.fireChanged();
-	}
-	
-	public String
-	getLastError()
-	{
-		return( last_error );
-	}
-	
-	public boolean
-	isAuthFail()
-	{
-		return( auth_failed );
-	}
-	
-	public int 
-	getConsecFails() 
-	{
-		return( consec_fails );
-	}
-	
-	public boolean
-	getDownloadWithReferer()
-	{
-		return( dl_with_ref );
-	}
-	
-	public void
-	setDownloadWithReferer(
-		boolean		b )
-	{
-		if ( b != dl_with_ref ){
-			
-			dl_with_ref = b;
-			
-			saveConfig();
-		}
-	}
-	
-	protected void
-	loadConfig()
-	{
-		Map	map = subs.getHistoryConfig();
-		
-		Long	l_enabled	= (Long)map.get( "enabled" );		
-		enabled				= l_enabled==null?true:l_enabled.longValue()==1;
-		
-		Long	l_auto_dl	= (Long)map.get( "auto_dl" );		
-		auto_dl				= l_auto_dl==null?false:l_auto_dl.longValue()==1;
-		
-		Long	l_last_scan = (Long)map.get( "last_scan" );		
-		last_scan			= l_last_scan==null?0:l_last_scan.longValue();
-		
-		Long	l_last_new 	= (Long)map.get( "last_new" );		
-		last_new_result		= l_last_new==null?0:l_last_new.longValue();
-		
-		Long	l_num_unread 	= (Long)map.get( "num_unread" );		
-		num_unread				= l_num_unread==null?0:l_num_unread.intValue();
-
-		Long	l_num_read 	= (Long)map.get( "num_read" );		
-		num_read			= l_num_read==null?0:l_num_read.intValue();
-		
-			// migration - if we've already downloaded this feed then we default to being
-			// enabled
-		
-		Long	l_auto_dl_s	= (Long)map.get( "auto_dl_supported" );		
-		auto_dl_supported	= l_auto_dl_s==null?(last_scan>0):l_auto_dl_s.longValue()==1;
-
-		Long	l_dl_with_ref	= (Long)map.get( "dl_with_ref" );		
-		dl_with_ref	= l_dl_with_ref==null?true:l_dl_with_ref.longValue()==1;
-
-	}
-	
-	protected void
-	saveConfig()
-	{
-		Map	map = new HashMap();
-		
-		map.put( "enabled", new Long( enabled?1:0 ));
-		map.put( "auto_dl", new Long( auto_dl?1:0 ));
-		map.put( "auto_dl_supported", new Long( auto_dl_supported?1:0));
-		map.put( "last_scan", new Long( last_scan ));
-		map.put( "last_new", new Long( last_new_result ));
-		map.put( "num_unread", new Long( num_unread ));
-		map.put( "num_read", new Long( num_read ));
-		map.put( "dl_with_ref", new Long( dl_with_ref?1:0 ));
-
-		subs.updateHistoryConfig( map );
-	}
-	
-	protected void
-	log(
-		String		str )
-	{
-		subs.log( "History: " + str );
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable	e )
-	{
-		subs.log( "History: " + str, e );
-	}
-	
-	protected String
-	getString()
-	{
-		return( "unread=" + num_unread + ",read=" + num_read+ ",last_err=" + last_error );
-	}
-}
+/*
+ * Created on Aug 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs.impl;
+
+import java.util.*;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.global.GlobalManager;
+import org.gudy.azureus2.core3.util.Base32;
+import org.gudy.azureus2.core3.util.ByteArrayHashMap;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.HashWrapper;
+import org.gudy.azureus2.core3.util.SystemTime;
+
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.subs.SubscriptionHistory;
+import com.aelitis.azureus.core.subs.SubscriptionResult;
+
+public class 
+SubscriptionHistoryImpl
+	implements SubscriptionHistory
+{
+	private final SubscriptionManagerImpl		manager;
+	private final SubscriptionImpl				subs;
+	
+	private boolean		enabled;
+	private boolean		auto_dl;
+	
+	private long		last_scan;
+	private long		last_new_result;
+	private int			num_unread;
+	private int			num_read;
+	
+	private String			last_error;
+	private boolean			auth_failed;
+	private int				consec_fails;
+	
+	private boolean			auto_dl_supported;
+	
+	private boolean			dl_with_ref	= true;
+	
+	private int				interval_override;
+	
+	protected
+	SubscriptionHistoryImpl(
+		SubscriptionManagerImpl		_manager,
+		SubscriptionImpl			_subs )
+	{
+		manager		= _manager;
+		subs		= _subs;
+		
+		loadConfig();
+	}
+	
+	protected SubscriptionResultImpl[]
+	reconcileResults(
+		Engine							engine,
+		SubscriptionResultImpl[]		latest_results )
+	{
+		auto_dl_supported	= engine.getAutoDownloadSupported() == Engine.AUTO_DL_SUPPORTED_YES;
+		
+		int	new_unread 	= 0;
+		int new_read	= 0;
+					
+		if ( last_scan == 0 ){
+				
+					// first download feed -> mark all existing as read
+						
+			GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
+			
+			for (int i=0;i<latest_results.length;i++){
+					
+				SubscriptionResultImpl result = latest_results[i];
+				
+				result.setReadInternal(true);
+				
+					// see if we can associate result with existing download
+				
+				try{
+					String hash_str = result.getAssetHash();
+					
+					if ( hash_str != null ){
+						
+						byte[] hash = Base32.decode( hash_str );
+						
+						DownloadManager dm = gm.getDownloadManager( new HashWrapper( hash ));
+						
+						if ( dm != null ){
+							
+							log( "Adding existing association on first read for '" + dm.getDisplayName());
+							
+							subs.addAssociation( hash );
+						}
+					}
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+		}
+		
+		long	now = SystemTime.getCurrentTime();
+		
+		SubscriptionResultImpl[] result;
+		
+		int	max_results = manager.getMaxNonDeletedResults();
+		
+		synchronized( this ){
+			
+			boolean	got_new_or_changed_result	= false;
+			
+			SubscriptionResultImpl[] existing_results = manager.loadResults( subs );
+					
+			ByteArrayHashMap	result_key_map 	= new ByteArrayHashMap();
+			ByteArrayHashMap	result_key2_map = new ByteArrayHashMap();
+			
+			List	new_results = new ArrayList();
+
+			for (int i=0;i<existing_results.length;i++){
+				
+				SubscriptionResultImpl r = existing_results[i];
+				
+				result_key_map.put( r.getKey1(), r );
+				
+				byte[]	key2 = r.getKey2();
+				
+				if ( key2 != null ){
+					
+					result_key2_map.put( key2, r );
+				}
+				
+				new_results.add( r );
+				
+				if ( !r.isDeleted()){
+					
+					if ( r.getRead()){
+						
+						new_read++;
+						
+					}else{
+						
+						new_unread++;
+					}
+				}
+			}
+						
+			for (int i=0;i<latest_results.length;i++){
+
+				SubscriptionResultImpl r = latest_results[i];
+				
+					// we first of all insist on names uniqueness
+				
+				SubscriptionResultImpl existing = (SubscriptionResultImpl)result_key_map.get( r.getKey1());
+				
+				if ( existing == null ){
+					
+						// only if non-unique name do we fall back and use UID to remove duplicate
+						// entries where the name has changed
+					
+					byte[]	key2 = r.getKey2();
+					
+					if ( key2 != null ){
+						
+						existing = (SubscriptionResultImpl)result_key2_map.get( key2 );
+					}
+				}
+				
+				if ( existing == null ){
+					
+					last_new_result = now;
+					
+					new_results.add( r );
+					
+					result_key_map.put( r.getKey1(), r );
+					
+					byte[]	key2 = r.getKey2();
+					
+					if ( key2 != null ){
+						
+						result_key2_map.put( key2, r );
+					}
+					
+					got_new_or_changed_result = true;
+				
+					if ( r.getRead()){
+						
+						new_read++;
+						
+					}else{
+					
+						new_unread++;
+					}
+				}else{
+					
+					if ( existing.updateFrom( r )){
+						
+						got_new_or_changed_result = true;
+					}
+				}
+			}
+			
+				// see if we need to delete any old ones
+			
+			if ( max_results > 0 && (new_unread + new_read ) > max_results ){
+				
+				for (int i=0;i<new_results.size();i++){
+					
+					SubscriptionResultImpl r = (SubscriptionResultImpl)new_results.get(i);
+					
+					if ( !r.isDeleted()){
+						
+						if ( r.getRead()){
+							
+							new_read--;
+							
+						}else{
+							
+							new_unread--;
+						}
+						
+						r.deleteInternal();
+						
+						got_new_or_changed_result = true;
+						
+						if (( new_unread + new_read ) <= max_results ){
+							
+							break;
+						}
+					}
+				}
+			}
+			
+			if ( got_new_or_changed_result ){
+				
+				result = (SubscriptionResultImpl[])new_results.toArray( new SubscriptionResultImpl[new_results.size()]);
+				
+				manager.saveResults( subs, result );
+				
+			}else{
+				
+				result = existing_results;
+			}
+		
+			last_scan 	= now;
+			num_unread	= new_unread;
+			num_read	= new_read;
+		}
+		
+			// always save config as we have a new scan time
+		
+		saveConfig();
+		
+		return( result );
+	}
+	
+	public boolean
+	isEnabled()
+	{
+		return( enabled );
+	}
+	
+	public void
+	setEnabled(
+		boolean		_enabled )
+	{
+		if ( _enabled != enabled ){
+			
+			enabled	= _enabled;
+		
+			saveConfig();
+		}
+	}
+	
+	public boolean
+	isAutoDownload()
+	{
+		return( auto_dl );
+	}
+	
+	public void
+	setAutoDownload(
+		boolean		_auto_dl )
+	{
+		if ( _auto_dl != auto_dl ){
+			
+			auto_dl	= _auto_dl;
+		
+			saveConfig();
+			
+			if ( auto_dl ){
+				
+				downloadNow();
+			}
+		}
+	}
+	
+	public void 
+	setDetails(
+		boolean 	_enabled, 
+		boolean 	_auto_dl ) 
+	{
+		if ( enabled != _enabled || auto_dl != _auto_dl ){
+			
+			enabled	= _enabled;
+			auto_dl	= _auto_dl;
+			
+			saveConfig();
+			
+			if ( enabled && auto_dl ){
+				
+				downloadNow();
+			}
+		}
+	}
+	
+	protected void
+	downloadNow()
+	{
+		try{
+			subs.getManager().getScheduler().downloadAsync( subs, false );
+			
+		}catch( Throwable e ){
+			
+			log( "Failed to initiate download", e );
+		}
+	}
+	
+	public long
+	getLastScanTime()
+	{
+		return( last_scan );
+	}
+	
+	public long 
+	getLastNewResultTime() 
+	{
+		return( last_new_result );
+	}
+	
+	public long
+	getNextScanTime()
+	{
+		if ( interval_override > 0 ){
+			
+			if ( last_scan == 0 ){
+				
+					// never scanned, scan immediately
+				
+				return( SystemTime.getCurrentTime());
+				
+			}else{
+			
+				return( last_scan + interval_override*60*1000 );
+			}
+		}
+		
+		Map	schedule = subs.getScheduleConfig();
+		
+		if ( schedule.size() == 0  ){
+			
+			log( "Schedule is empty!");
+			
+			return( Long.MAX_VALUE );
+			
+		}else{
+			
+			try{
+			
+				long	interval_min = ((Long)schedule.get( "interval" )).longValue();
+				
+				if ( interval_min == Integer.MAX_VALUE || interval_min == Long.MAX_VALUE ){
+					
+					return( Long.MAX_VALUE );
+				}
+				
+				if ( last_scan == 0 ){
+					
+						// never scanned, scan immediately
+					
+					return( SystemTime.getCurrentTime());
+					
+				}else{
+				
+					return( last_scan + interval_min*60*1000 );
+				}
+			}catch( Throwable e ){
+				
+				log( "Failed to decode schedule " + schedule, e );
+				
+				return( Long.MAX_VALUE );
+			}
+		}
+	}
+	
+	public int
+	getCheckFrequencyMins()
+	{
+		if ( interval_override > 0 ){
+			
+			return( interval_override );
+		}
+		
+		Map	schedule = subs.getScheduleConfig();
+		
+		if ( schedule.size() == 0  ){
+			
+			return( DEFAULT_CHECK_INTERVAL_MINS );
+			
+		}else{
+			
+			try{		
+				int	interval_min = ((Long)schedule.get( "interval" )).intValue();
+				
+				return( interval_min );
+				
+			}catch( Throwable e ){
+								
+				return( DEFAULT_CHECK_INTERVAL_MINS );
+			}
+		}
+	}
+	
+	public void
+	setCheckFrequencyMins(
+		int		mins )
+	{
+		interval_override		= mins;
+		
+		saveConfig();
+		
+		subs.fireChanged();
+	}
+	
+	public int
+	getNumUnread()
+	{
+		return( num_unread );
+	}
+	
+	public int
+	getNumRead()
+	{
+		return( num_read );
+	}
+	
+	public SubscriptionResult[]
+	getResults(
+		boolean		include_deleted )
+	{
+		SubscriptionResult[] results;
+		
+		synchronized( this ){
+			
+			results = manager.loadResults( subs );
+		}
+		
+		if ( include_deleted ){
+			
+			return( results );
+			
+		}else{
+			
+			List	l = new ArrayList( results.length );
+			
+			for (int i=0;i<results.length;i++){
+				
+				if ( !results[i].isDeleted()){
+					
+					l.add( results[i] );
+				}
+			}
+			
+			return((SubscriptionResult[])l.toArray( new SubscriptionResult[l.size()]));
+		}
+	}
+	
+	public SubscriptionResult
+	getResult(
+		String		result_id )
+	{
+		SubscriptionResult[] results = getResults( true );
+		
+		for (int i=0;i<results.length;i++){
+			
+			if ( results[i].getID().equals( result_id )){
+				
+				return( results[i] );
+			}
+		}
+		
+		return( null );
+	}
+	
+	protected void
+	updateResult(
+		SubscriptionResultImpl 	result )
+	{
+		byte[]	key = result.getKey1();
+		
+		boolean	changed = false;
+
+		synchronized( this ){
+			
+			SubscriptionResultImpl[] results = manager.loadResults( subs );
+						
+			for (int i=0;i<results.length;i++){
+				
+				if ( Arrays.equals( results[i].getKey1(), key )){
+					
+					results[i] = result;
+					
+					changed	= true;
+				}
+			}
+			
+			if ( changed ){
+				
+				updateReadUnread( results );
+				
+				manager.saveResults( subs, results );
+			}
+		}
+		
+		if ( changed ){
+			
+			saveConfig();
+		}
+		
+		if ( isAutoDownload() && !result.getRead() && !result.isDeleted()){
+			
+			manager.getScheduler().download( subs, result );		
+		}
+	}
+	
+
+	public void 
+	deleteResults(
+		String[] result_ids )
+	{
+		ByteArrayHashMap rids = new ByteArrayHashMap();
+		
+		for (int i=0;i<result_ids.length;i++){
+			
+			rids.put( Base32.decode( result_ids[i]), "" );
+		}
+	
+		boolean	changed = false;
+
+		synchronized( this ){
+				
+			SubscriptionResultImpl[] results = manager.loadResults( subs );
+
+			for (int i=0;i<results.length;i++){
+				
+				SubscriptionResultImpl result = results[i];
+				
+				if ( !result.isDeleted() && rids.containsKey( result.getKey1())){
+					
+					changed = true;
+					
+					result.deleteInternal();
+				}
+			}
+			
+			if ( changed ){
+				
+				updateReadUnread( results );
+				
+				manager.saveResults( subs, results );
+			}
+		}
+		
+		if ( changed ){
+			
+			saveConfig();
+		}
+	}
+	
+	public void
+	deleteAllResults()
+	{
+		boolean	changed = false;
+		
+		synchronized( this ){
+						
+			SubscriptionResultImpl[] results = manager.loadResults( subs );
+
+			for (int i=0;i<results.length;i++){
+				
+				SubscriptionResultImpl result = results[i];
+				
+				if ( !result.isDeleted()){
+					
+					changed = true;
+				
+					result.deleteInternal();
+				}
+			}
+			
+			if ( changed ){
+				
+				updateReadUnread( results );
+				
+				manager.saveResults( subs, results );
+			}
+		}
+		
+		if ( changed ){
+			
+			saveConfig();
+		}
+	}
+	
+	public void
+	markAllResultsRead()
+	{
+		boolean	changed = false;
+		
+		synchronized( this ){
+						
+			SubscriptionResultImpl[] results = manager.loadResults( subs );
+
+			for (int i=0;i<results.length;i++){
+				
+				SubscriptionResultImpl result = results[i];
+				
+				if ( !result.getRead()){
+					
+					changed = true;
+				
+					result.setReadInternal( true );
+				}
+			}
+			
+			if ( changed ){
+				
+				updateReadUnread( results );
+				
+				manager.saveResults( subs, results );
+			}
+		}
+		
+		if ( changed ){
+			
+			saveConfig();
+		}
+	}
+	
+	public void
+	markAllResultsUnread()
+	{
+		boolean	changed = false;
+		
+		synchronized( this ){
+						
+			SubscriptionResultImpl[] results = manager.loadResults( subs );
+
+			for (int i=0;i<results.length;i++){
+				
+				SubscriptionResultImpl result = results[i];
+				
+				if ( result.getRead()){
+					
+					changed = true;
+				
+					result.setReadInternal( false );
+				}
+			}
+			
+			if ( changed ){
+				
+				updateReadUnread( results );
+				
+				manager.saveResults( subs, results );
+			}
+		}
+		
+		if ( changed ){
+			
+			saveConfig();
+		}
+	}
+	
+	public void 
+	markResults(
+		String[] 		result_ids,
+		boolean[]		reads )
+	{
+		ByteArrayHashMap rid_map = new ByteArrayHashMap();
+		
+		for (int i=0;i<result_ids.length;i++){
+			
+			rid_map.put( Base32.decode( result_ids[i]), new Boolean( reads[i] ));
+		}
+	
+		boolean	changed = false;
+
+		List	newly_unread = new ArrayList();
+		
+		synchronized( this ){
+						
+			SubscriptionResultImpl[] results = manager.loadResults( subs );
+
+			for (int i=0;i<results.length;i++){
+				
+				SubscriptionResultImpl result = results[i];
+				
+				if ( result.isDeleted()){
+					
+					continue;
+				}
+				
+				Boolean	b_read = (Boolean)rid_map.get( result.getKey1());
+				
+				if ( b_read != null ){
+					
+					boolean	read = b_read.booleanValue();
+					
+					if ( result.getRead() != read ){
+						
+						changed = true;
+					
+						result.setReadInternal( read );
+						
+						if ( !read ){
+							
+							newly_unread.add( result );
+						}
+					}
+				}
+			}
+			
+			if ( changed ){
+				
+				updateReadUnread( results );
+				
+				manager.saveResults( subs, results );
+			}
+		}
+		
+		if ( changed ){
+			
+			saveConfig();
+		}
+		
+		if ( isAutoDownload()){
+			
+			for (int i=0;i<newly_unread.size();i++){
+				
+				manager.getScheduler().download( subs, (SubscriptionResult)newly_unread.get(i));
+			}
+		}
+	}
+	
+	public void 
+	reset() 
+	{
+		synchronized( this ){
+			
+			SubscriptionResultImpl[] results = manager.loadResults( subs );
+			
+			if ( results.length > 0 ){
+				
+				results = new SubscriptionResultImpl[0];
+								
+				manager.saveResults( subs, results );
+			}
+			
+			updateReadUnread( results );
+		}
+		
+		last_error		= null;
+		last_new_result	= 0;
+		last_scan		= 0;
+					
+		saveConfig();
+	}
+	
+	protected void
+	checkMaxResults(
+		int		max_results )
+	{
+		if ( max_results <= 0 ){
+			
+			return;
+		}
+		
+		boolean	changed = false;
+
+		synchronized( this ){
+
+			if ((num_unread + num_read ) > max_results ){
+
+				SubscriptionResultImpl[] results = manager.loadResults( subs );
+				
+				for (int i=0;i<results.length;i++){
+					
+					SubscriptionResultImpl r = results[i];
+					
+					if ( !r.isDeleted()){
+						
+						if ( r.getRead()){
+							
+							num_read--;
+							
+						}else{
+							
+							num_unread--;
+						}
+						
+						r.deleteInternal();
+						
+						changed = true;
+						
+						if (( num_unread + num_read ) <= max_results ){
+							
+							break;
+						}
+					}
+				}
+				
+				if ( changed ){
+					
+					manager.saveResults( subs, results );
+				}
+			}
+		}
+		
+		if ( changed ){
+			
+			saveConfig();
+		}
+	}
+	
+	protected void
+	updateReadUnread(
+		SubscriptionResultImpl[]	results )
+	{
+		int	new_unread	= 0;
+		int	new_read	= 0;
+		
+		for (int i=0;i<results.length;i++){
+			
+			SubscriptionResultImpl result = results[i];
+			
+			if ( !result.isDeleted()){
+				
+				if ( result.getRead()){
+					
+					new_read++;
+					
+				}else{
+					
+					new_unread++;
+				}
+			}
+		}
+		
+		num_read	= new_read;
+		num_unread	= new_unread;
+	}
+	
+	protected boolean
+	isAutoDownloadSupported()
+	{
+		return( auto_dl_supported );
+	}
+	
+	protected void
+	setFatalError(
+		String		_error )
+	{
+		last_error		= _error;
+		consec_fails	= 1024;
+	}
+	
+	protected void
+	setLastError(
+		String		_last_error,
+		boolean		_auth_failed )
+	{
+		last_error 		= _last_error;
+		auth_failed		= _auth_failed;
+		
+		if ( last_error == null ){
+			
+			consec_fails = 0;
+			
+		}else{
+			
+			consec_fails++;
+		}
+		
+		subs.fireChanged();
+	}
+	
+	public String
+	getLastError()
+	{
+		return( last_error );
+	}
+	
+	public boolean
+	isAuthFail()
+	{
+		return( auth_failed );
+	}
+	
+	public int 
+	getConsecFails() 
+	{
+		return( consec_fails );
+	}
+	
+	public boolean
+	getDownloadWithReferer()
+	{
+		return( dl_with_ref );
+	}
+	
+	public void
+	setDownloadWithReferer(
+		boolean		b )
+	{
+		if ( b != dl_with_ref ){
+			
+			dl_with_ref = b;
+			
+			saveConfig();
+		}
+	}
+	
+	protected void
+	loadConfig()
+	{
+		Map	map = subs.getHistoryConfig();
+		
+		Long	l_enabled	= (Long)map.get( "enabled" );		
+		enabled				= l_enabled==null?true:l_enabled.longValue()==1;
+		
+		Long	l_auto_dl	= (Long)map.get( "auto_dl" );		
+		auto_dl				= l_auto_dl==null?false:l_auto_dl.longValue()==1;
+		
+		Long	l_last_scan = (Long)map.get( "last_scan" );		
+		last_scan			= l_last_scan==null?0:l_last_scan.longValue();
+		
+		Long	l_last_new 	= (Long)map.get( "last_new" );		
+		last_new_result		= l_last_new==null?0:l_last_new.longValue();
+		
+		Long	l_num_unread 	= (Long)map.get( "num_unread" );		
+		num_unread				= l_num_unread==null?0:l_num_unread.intValue();
+
+		Long	l_num_read 	= (Long)map.get( "num_read" );		
+		num_read			= l_num_read==null?0:l_num_read.intValue();
+		
+			// migration - if we've already downloaded this feed then we default to being
+			// enabled
+		
+		Long	l_auto_dl_s	= (Long)map.get( "auto_dl_supported" );		
+		auto_dl_supported	= l_auto_dl_s==null?(last_scan>0):l_auto_dl_s.longValue()==1;
+
+		Long	l_dl_with_ref	= (Long)map.get( "dl_with_ref" );		
+		dl_with_ref	= l_dl_with_ref==null?true:l_dl_with_ref.longValue()==1;
+		
+		Long	l_interval_override	= (Long)map.get( "interval_override" );		
+		interval_override	= l_interval_override==null?0:l_interval_override.intValue();
+
+	}
+	
+	protected void
+	saveConfig()
+	{
+		Map	map = new HashMap();
+		
+		map.put( "enabled", new Long( enabled?1:0 ));
+		map.put( "auto_dl", new Long( auto_dl?1:0 ));
+		map.put( "auto_dl_supported", new Long( auto_dl_supported?1:0));
+		map.put( "last_scan", new Long( last_scan ));
+		map.put( "last_new", new Long( last_new_result ));
+		map.put( "num_unread", new Long( num_unread ));
+		map.put( "num_read", new Long( num_read ));
+		map.put( "dl_with_ref", new Long( dl_with_ref?1:0 ));
+
+		if ( interval_override > 0 ){
+			map.put( "interval_override", new Long( interval_override ));
+		}
+		
+		subs.updateHistoryConfig( map );
+	}
+	
+	protected void
+	log(
+		String		str )
+	{
+		subs.log( "History: " + str );
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable	e )
+	{
+		subs.log( "History: " + str, e );
+	}
+	
+	protected String
+	getString()
+	{
+		return( "unread=" + num_unread + ",read=" + num_read+ ",last_err=" + last_error );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionImpl.java b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionImpl.java
index 5af89e3..59cf389 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionImpl.java
@@ -1,2153 +1,2167 @@
-/*
- * Created on Jul 11, 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.core.subs.impl;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.security.KeyPair;
-import java.util.*;
-
-import org.bouncycastle.util.encoders.Base64;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentCreator;
-import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
-import org.gudy.azureus2.core3.util.AEThread2;
-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.ByteFormatter;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.FileUtil;
-import org.gudy.azureus2.core3.util.HashWrapper;
-import org.gudy.azureus2.core3.util.IndentWriter;
-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.core3.util.TorrentUtils;
-import org.json.simple.JSONObject;
-
-import com.aelitis.azureus.core.lws.LightWeightSeed;
-import com.aelitis.azureus.core.lws.LightWeightSeedAdapter;
-import com.aelitis.azureus.core.lws.LightWeightSeedManager;
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.MetaSearchManagerFactory;
-import com.aelitis.azureus.core.security.CryptoECCUtils;
-import com.aelitis.azureus.core.subs.Subscription;
-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.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;
-import com.aelitis.azureus.util.ImportExportUtils;
-import com.aelitis.azureus.util.JSONUtils;
-
-public class 
-SubscriptionImpl 
-	implements Subscription 
-{
-	public static final int	ADD_TYPE_CREATE		= 1;
-	public static final int	ADD_TYPE_IMPORT		= 2;
-	public static final int	ADD_TYPE_LOOKUP		= 3;
-		
-	private static final int MAX_ASSOCIATIONS				= 256;
-	private static final int MIN_RECENT_ASSOC_TO_RETAIN		= 16;
-		
-	//private static final byte[] GENERIC_PUBLIC_KEY 		= {(byte)0x04,(byte)0xd0,(byte)0x1a,(byte)0xd9,(byte)0xb9,(byte)0x99,(byte)0xd8,(byte)0x49,(byte)0x15,(byte)0x5f,(byte)0xe9,(byte)0x6b,(byte)0x3c,(byte)0xd8,(byte)0x18,(byte)0x81,(byte)0xf7,(byte)0x92,(byte)0x15,(byte)0x3f,(byte)0x24,(byte)0xaa,(byte)0x35,(byte)0x6f,(byte)0x52,(byte)0x01,(byte)0x79,(byte)0x2e,(byte)0x93,(byte)0xf6,(byte)0xf1,(byte)0x57,(byte)0x13,(byte)0x2a,(byte)0x3c,(byte)0x31,(byte)0x66,(byte)0xa5,(byte)0x34,(byte)0x [...]
-	// private static final byte[] GENERIC_PRIVATE_KEY 	= {(byte)0x71,(byte)0xc3,(byte)0xe8,(byte)0x6c,(byte)0x56,(byte)0xbb,(byte)0x30,(byte)0x14,(byte)0x9e,(byte)0x19,(byte)0xa5,(byte)0x3d,(byte)0xcb,(byte)0x47,(byte)0xbb,(byte)0x6d,(byte)0x57,(byte)0x57,(byte)0xd3,(byte)0x59,(byte)0xce,(byte)0x8f,(byte)0x79,(byte)0xe5};
-
-	protected static byte[]
-	intToBytes(
-		int		version )
-	{
-		return( new byte[]{ (byte)(version>>24), (byte)(version>>16),(byte)(version>>8),(byte)version } );
-	}
-	
-	protected static int
-	bytesToInt(
-		byte[]		bytes )
-	{
-		return( (bytes[0]<<24)&0xff000000 | (bytes[1] << 16)&0x00ff0000 | (bytes[2] << 8)&0x0000ff00 | bytes[3]&0x000000ff );
-	}
-		
-	private SubscriptionManagerImpl		manager;
-	
-	private byte[]			public_key;
-	private byte[]			private_key;
-	
-	private String			name;
-	private String			name_ex;
-	
-	private int				version;
-	private int				az_version;
-	
-	private boolean			is_public;
-	private Map				singleton_details;
-	
-	private byte[]			hash;
-	private byte[]			sig;
-	private int				sig_data_size;
-	
-	private int				add_type;
-	private long			add_time;
-	
-	private boolean			is_subscribed;
-	
-	private int				highest_prompted_version;
-	
-	private byte[]			short_id;
-
-	private String			id;
-
-	private List			associations = new ArrayList();
-	
-	private int				fixed_random;
-	
-	private long			popularity				= -1;
-	
-	private long			last_auto_upgrade_check	= -1;
-	private boolean			published;
-	
-	private boolean			server_published;
-	private boolean			server_publication_outstanding;
-	
-	private boolean			singleton_sp_attempted;
-	private String			local_name;
-	
-	private LightWeightSeed	lws;
-	private int				lws_skip_check;
-	
-	private boolean			destroyed;
-	
-	private Map				history_map;
-	private Map				schedule_map;
-	
-	private Map				user_data = new LightHashMap();
-	
-	private final 			SubscriptionHistoryImpl	history;
-	
-	private String			referer;
-	
-	private CopyOnWriteList	listeners = new CopyOnWriteList();
-	
-	private Map				verify_cache_details;
-	private boolean			verify_cache_result;
-	
-	private String			creator_ref;
-	private String			category;
-	private long			tag_id = -1;
-	
-	protected static String
-	getSkeletonJSON(
-		Engine		engine,
-		int			check_interval_mins )
-	{
-		JSONObject	map = new JSONObject();
-		
-		map.put( "engine_id", new Long( engine.getId()));
-		
-		map.put( "search_term", "" );
-
-		map.put( "filters", new HashMap());
-		
-		map.put( "options", new HashMap());
-		
-		Map schedule = new HashMap();
-		
-		schedule.put( "interval", new Long( check_interval_mins ));
-		
-		List	days = new ArrayList();
-		
-		for (int i=1;i<=7;i++){
-			
-			days.add( String.valueOf(i));
-		}
-		
-		schedule.put( "days", days );
-		
-		map.put( "schedule", schedule );
-		
-		embedEngines( map, engine );
-		
-		return( JSONUtils.encodeToJSON( map ));
-	}
-	
-	
-		// new subs constructor
-	
-	protected
-	SubscriptionImpl(
-		SubscriptionManagerImpl		_manager,
-		String						_name,
-		boolean						_public,
-		Map							_singleton_details,
-		String						_json_content,
-		int							_add_type )
-	
-		throws SubscriptionException
-	{
-		manager	= _manager;
-		
-		history_map	= new HashMap();
-
-		history = new SubscriptionHistoryImpl( manager, this );
-		
-		name				= _name;
-		is_public			= _public;
-		singleton_details	= _singleton_details;
-		
-		version				= 1;
-		az_version			= AZ_VERSION;
-		
-		add_type			= _add_type;
-		add_time			= SystemTime.getCurrentTime();
-		
-		is_subscribed		= true;
-
-		try{
-			KeyPair	kp = CryptoECCUtils.createKeys();
-				
-			public_key 			= CryptoECCUtils.keyToRawdata( kp.getPublic());
-			private_key 		= CryptoECCUtils.keyToRawdata( kp.getPrivate());
-						
-			
-			fixed_random	= RandomUtils.nextInt();
-			
-			init();
-			
-			String json_content = embedEngines( _json_content );
-			
-			SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, name, is_public, json_content, public_key, version, az_version, singleton_details );
-						
-			syncToBody( body );
-			
-		}catch( Throwable e ){
-			
-			throw( new SubscriptionException( "Failed to create subscription", e ));
-		}
-	}
-	
-		// cache detail constructor
-	
-	protected
-	SubscriptionImpl(
-		SubscriptionManagerImpl		_manager,
-		Map							map )
-	
-		throws IOException
-	{
-		manager	= _manager;
-				
-		fromMap( map );
-		
-		history = new SubscriptionHistoryImpl( manager, this );
-
-		init();
-	}
-
-		// import constructor
-	
-	protected
-	SubscriptionImpl(
-		SubscriptionManagerImpl		_manager,
-		SubscriptionBodyImpl		_body,
-		int							_add_type,
-		boolean						_is_subscribed )
-	
-		throws SubscriptionException
-	{
-		manager	= _manager;
-			
-		history_map	= new HashMap();
-		
-		history = new SubscriptionHistoryImpl( manager, this );
-		
-		syncFromBody( _body );
-		
-		add_type		= _add_type;
-		add_time		= SystemTime.getCurrentTime();
-		
-		is_subscribed	= _is_subscribed;
-		
-		fixed_random	= RandomUtils.nextInt();
-		
-		init();
-				
-		syncToBody( _body );
-	}
-	
-	protected void
-	syncFromBody(
-		SubscriptionBodyImpl	body )
-	
-		throws SubscriptionException
-	{
-		public_key			= body.getPublicKey();
-		version				= body.getVersion();
-		az_version			= body.getAZVersion();
-				
-		name				= body.getName();
-		is_public			= body.isPublic();
-		singleton_details	= body.getSingletonDetails();
-		
-		if ( az_version > AZ_VERSION ){
-			
-			throw( new SubscriptionException( MessageText.getString( "subscription.version.bad", new String[]{ name })));
-		}
-	}
-	
-	protected void
-	syncToBody(
-		SubscriptionBodyImpl		body )
-	
-		throws SubscriptionException
-	{
-			// this picks up latest values of version, name + is_public from here
-		
-		body.writeVuzeFile( this );
-		
-		hash 			= body.getHash();
-		sig				= body.getSig();
-		sig_data_size	= body.getSigDataSize();
-	}
-	
-	protected Map
-	toMap()
-	
-		throws IOException
-	{
-		synchronized( this ){
-			
-			Map	map = new HashMap();
-			
-			map.put( "name", name.getBytes( "UTF-8" ));
-			
-			map.put( "public_key", public_key );
-						
-			map.put( "version", new Long( version ));
-			
-			map.put( "az_version", new Long( az_version ));
-			
-			map.put( "is_public", new Long( is_public?1:0 ));
-			
-			if ( singleton_details != null ){
-				
-				map.put( "sin_details", singleton_details );
-				map.put( "spa", new Long( singleton_sp_attempted?1:0 ));
-			}
-			
-			if ( local_name != null ){
-				
-				map.put( "local_name", local_name );
-			}
-				// body data
-			
-			map.put( "hash", hash );
-			map.put( "sig", sig );
-			map.put( "sig_data_size", new Long( sig_data_size ));
-			
-				// local data
-			
-			if ( private_key != null ){
-				
-				map.put( "private_key", private_key );
-			}
-
-			map.put( "add_type", new Long( add_type ));
-			map.put( "add_time", new Long( add_time ));
-			
-			map.put( "subscribed", new Long( is_subscribed?1:0 ));
-			
-			map.put( "pop", new Long( popularity ));
-			
-			map.put( "rand", new Long( fixed_random ));
-			
-			map.put( "hupv", new Long( highest_prompted_version ));
-			
-			map.put( "sp", new Long( server_published?1:0 ));
-			map.put( "spo", new Long( server_publication_outstanding?1:0 ));
-						
-			if ( associations.size() > 0 ){
-				
-				List	l_assoc = new ArrayList();
-				
-				map.put( "assoc", l_assoc );
-				
-				for (int i=0;i<associations.size();i++){
-					
-					association assoc = (association)associations.get(i);
-					
-					Map m = new HashMap();
-					
-					l_assoc.add( m );
-					
-					m.put( "h", assoc.getHash());
-					m.put( "w", new Long( assoc.getWhen()));
-				}
-			}
-			
-			map.put( "history", history_map );
-			
-			if ( creator_ref != null ){
-				
-				map.put( "cref", creator_ref.getBytes( "UTF-8" ));
-			}
-			
-			if ( category != null ){
-				
-				map.put( "cat", category.getBytes( "UTF-8" ));
-			}
-			
-			if ( tag_id != -1 ){
-				
-				map.put( "tag", tag_id );
-			}
-			
-			return( map );
-		}
-	}
-	
-	protected void
-	fromMap(
-		Map		map )
-	
-		throws IOException
-	{
-		name				= new String((byte[])map.get( "name"), "UTF-8" );
-		public_key			= (byte[])map.get( "public_key" );
-		private_key			= (byte[])map.get( "private_key" );
-		version				= ((Long)map.get( "version" )).intValue();
-		az_version			= (int)ImportExportUtils.importLong( map, "az_version", AZ_VERSION );
-		is_public			= ((Long)map.get( "is_public")).intValue() == 1;
-		singleton_details	= (Map)map.get( "sin_details" );
-		
-		hash			= (byte[])map.get( "hash" );
-		sig				= (byte[])map.get( "sig" );
-		sig_data_size	= ((Long)map.get( "sig_data_size" )).intValue();
-		
-		fixed_random	= ((Long)map.get( "rand" )).intValue();
-		
-		add_type		= ((Long)map.get( "add_type" )).intValue();		
-		add_time		= ((Long)map.get( "add_time" )).longValue();
-		
-		is_subscribed	= ((Long)map.get( "subscribed" )).intValue()==1;
-				
-		popularity		= ((Long)map.get( "pop" )).longValue();
-		
-		highest_prompted_version = ((Long)map.get( "hupv" )).intValue();
-		
-		server_published = ((Long)map.get( "sp" )).intValue()==1;
-		server_publication_outstanding = ((Long)map.get( "spo" )).intValue()==1;
-		
-		Long	l_spa = (Long)map.get( "spa" );
-		
-		if ( l_spa != null ){
-			singleton_sp_attempted = l_spa.longValue()==1; 
-		}
-		
-		byte[]	b_local_name = (byte[])map.get( "local_name" );
-		
-		if ( b_local_name != null ){
-			
-			local_name = new String( b_local_name, "UTF-8" );
-		}
-		
-		List	l_assoc = (List)map.get( "assoc" );
-		
-		if ( l_assoc != null ){
-			
-			for (int i=0;i<l_assoc.size();i++){
-				
-				Map	m = (Map)l_assoc.get(i);
-				
-				byte[]		hash 	= (byte[])m.get("h");
-				long		when	= ((Long)m.get( "w" )).longValue();
-				
-				associations.add( new association( hash, when ));
-			}
-		}
-		
-		history_map = (Map)map.get( "history" );
-		
-		if ( history_map == null ){
-			
-			history_map = new HashMap();
-		}
-		
-		byte[] b_cref = (byte[])map.get( "cref" );
-		
-		if ( b_cref != null ){
-			
-			creator_ref = new String( b_cref, "UTF-8" );
-		}
-		
-		byte[] b_cat = (byte[])map.get( "cat" );
-		
-		if ( b_cat != null ){
-			
-			category = new String( b_cat, "UTF-8" );
-		}
-		
-		Long l_tag_id = (Long)map.get( "tag" );
-		
-		if ( l_tag_id != null ){
-			
-			tag_id = l_tag_id;
-		}
-	}
-	
-	protected Map
-	getScheduleConfig()
-	{
-		if ( schedule_map == null ){
-			
-			try{		
-				Map map = JSONUtils.decodeJSON( getJSON());
-
-				schedule_map = (Map)map.get( "schedule" );
-				
-				if ( schedule_map == null ){
-					
-					schedule_map = new HashMap();
-				}
-			}catch( Throwable e ){
-				
-				log( "Failed to load schedule", e );
-				
-				schedule_map = new HashMap();
-			}
-		}
-		
-		return( schedule_map );
-	}
-	
-	protected Map
-	getHistoryConfig()
-	{
-		return( history_map );
-	}
-	
-	protected void
-	updateHistoryConfig(
-		Map		_history_map )
-	{
-		history_map = _history_map;
-		
-		fireChanged();
-	}
-	
-	protected void
-	upgrade(
-		SubscriptionBodyImpl		body )
-	
-		throws SubscriptionException
-	{
-			// pick up details from the body (excluding json that is maintained in body only)
-		
-		syncFromBody( body );
-		
-			// write to file
-		
-		syncToBody(body);
-		
-		fireChanged();
-	}
-	
-	protected void
-	init()
-	{
-		short_id = SubscriptionBodyImpl.deriveShortID( public_key, singleton_details );
-		id = null;
-	}
-	
-	public boolean
-	isSingleton()
-	{
-		return( singleton_details != null );
-	}
-	
-	public boolean
-	isShareable()
-	{
-		try{
-			return( getEngine().isShareable() && !isSingleton());
-			
-		}catch( Throwable e ){
-			
-			Debug.printStackTrace(e);
-			
-			return( false );
-		}
-	}
-	
-	public boolean
-	isSearchTemplate()
-	{
-		return( getName(false).startsWith( "Search Template:" ));
-	}
-	
-	protected Map
-	getSingletonDetails()
-	{
-		return( singleton_details );
-	}
-	
-	protected boolean
-	getSingletonPublishAttempted()
-	{
-		return( singleton_sp_attempted );
-	}
-	
-	protected void
-	setSingletonPublishAttempted()
-	{
-		if ( !singleton_sp_attempted ){
-			
-			singleton_sp_attempted = true;
-		
-			manager.configDirty( this );
-		}
-	}
-	
-	public String
-	getName()
-	{
-		return( getName( true ));
-	}
-	
-	public String
-	getName(
-		boolean	use_local )
-	{
-		return( local_name==null?name:local_name );
-	}
-	
-	public void
-	setLocalName(
-		String		str )
-	{
-		local_name = str;
-		
-		manager.configDirty( this );
-		
-		fireChanged();
-	}
-	
-	public void
-	setName(
-		String		_name )
-	
-		throws SubscriptionException
-	{
-		if ( !name.equals( _name )){
-			
-			boolean	ok = false;
-			
-			String	old_name 	= name;
-			int		old_version	= version;
-			
-			try{
-				name	= _name;
-				
-				version++;
-				
-				SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );
-					
-				syncToBody( body );
-				
-				versionUpdated( body, false );
-				
-				ok	= true;
-				
-			}finally{
-				
-				if ( !ok ){
-					
-					name 	= old_name;
-					version	= old_version;
-				}
-			}
-			
-			fireChanged();
-		}
-	}
-	
-	public String
-	getNameEx()
-	{
-		if ( name_ex == null ){
-			
-			try{
-				Map map = JSONUtils.decodeJSON( getJSON());
-				
-				String	search_term	= (String)map.get( "search_term" );
-				Map		filters		= (Map)map.get( "filters" );
-	
-				Engine engine = manager.getEngine( this, map, true );
-
-				String	engine_name = engine.getNameEx();
-				
-				if ( name.startsWith( engine_name )){
-					
-					name_ex = name;
-					
-				}else if ( engine_name.startsWith( name )){
-					
-					name_ex = engine_name;
-					
-				}else{
-					
-					name_ex = name + ": " + engine.getNameEx();
-				}
-				
-				if ( search_term != null && search_term.length() > 0 ){
-					
-					name_ex += ", query=" + search_term;
-				}
-				
-				if ( filters != null && filters.size() > 0 ){
-					
-					name_ex += ", filters=" + new SubscriptionResultFilter(filters).getString();
-				}
-				
-			}catch( Throwable e ){
-				
-				name_ex = name + ": " + Debug.getNestedExceptionMessage(e);
-			}
-		}
-		
-		return( name_ex );
-	}
-	
-	public long
-	getAddTime()
-	{
-		return( add_time );
-	}
-	
-	public boolean
-	isPublic()
-	{
-		return( is_public );
-	}
-	
-	public void
-	setPublic(
-		boolean		_is_public )
-	
-		throws SubscriptionException
-	{
-		if ( is_public != _is_public ){
-				
-			boolean	ok = false;
-			
-			boolean	old_public	= is_public;
-			int		old_version	= version;
-			
-			try{
-				is_public	= _is_public;
-				
-				version++;
-								
-				SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );
-				
-				syncToBody( body );
-				
-				versionUpdated( body, false );
-
-				ok = true;
-				
-			}finally{
-				
-				if ( !ok ){
-				
-					version		= old_version;
-					is_public	= old_public;
-				}
-			}
-			
-			fireChanged();
-		}
-	}
-	
-	protected boolean
-	getServerPublicationOutstanding()
-	{
-		return( server_publication_outstanding );
-	}
-	
-	protected void
-	setServerPublicationOutstanding()	
-	{
-		if ( !server_publication_outstanding ){
-			
-			server_publication_outstanding = true;
-		
-			fireChanged();
-		}
-	}
-	
-	protected void
-	setServerPublished()
-	{
-		if ( server_publication_outstanding || !server_published ){
-			
-			server_published 				= true;
-			server_publication_outstanding	= false;
-			
-			fireChanged();
-		}
-	}
-	
-	protected boolean
-	getServerPublished()
-	{
-		return( server_published );
-	}
-	
-	public String
-	getJSON()
-	
-		throws SubscriptionException
-	{
-		try{
-			SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );
-
-			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
-	setJSON(
-		String		_json )
-	
-		throws SubscriptionException
-	{
-		String json = embedEngines( _json );
-		
-		SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );		
-		
-		String	old_json = body.getJSON();
-		
-		if ( !json.equals( old_json )){
-			
-			boolean	ok = false;
-			
-			int		old_version	= version;
-			
-			try{				
-				version++;
-													
-				body.setJSON( json );
-				
-				syncToBody( body );
-				
-				versionUpdated( body, true );
-
-				referer = null;
-				
-				ok	= true;
-				
-			}finally{
-				
-				if ( !ok ){
-					
-					version	= old_version;
-				}
-			}
-			
-			fireChanged();
-			
-			return( true );
-		}
-		
-		return( false );
-	}
-	
-	protected String
-	embedEngines(
-		String		json_in )
-	{
-			// see if we need to embed private search templates
-		
-		Map map = JSONUtils.decodeJSON( json_in );
-		
-		long 	engine_id 	= ((Long)map.get( "engine_id" )).longValue();
-
-		String	json_out	= json_in;
-		
-		if ( engine_id >= Integer.MAX_VALUE || engine_id < 0 ){
-			
-			Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().getEngine( engine_id );
-
-			if ( engine == null ){
-				
-				log( "Private search template with id '" + engine_id + "' not found!!!!" );
-				
-			}else{
-				
-				try{								
-					embedEngines( map, engine );
-					
-					json_out = JSONUtils.encodeToJSON( map );
-					
-
-					log( "Embedded private search template '" + engine.getName() + "'" );
-					
-				}catch( Throwable e ){
-					
-					log( "Failed to embed private search template", e );
-				}
-			}
-		}
-		
-		return( json_out );
-	}
-	
-	protected static void
-	embedEngines(
-		Map			map,
-		Engine		engine )
-	{
-		Map	engines = new HashMap();
-		
-		map.put( "engines", engines );
-		
-		Map	engine_map = new HashMap();
-		
-		try{
-		
-			String	engine_str = new String( Base64.encode( BEncoder.encode( engine.exportToBencodedMap())), "UTF-8" );
-		
-			engine_map.put( "content", engine_str );
-		
-			engines.put( String.valueOf( engine.getId()), engine_map );
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-	}
-
-	protected Engine
-	extractEngine(
-		Map		json_map,
-		long	id )
-	{
-		Map engines = (Map)json_map.get( "engines" );
-		
-		if ( engines != null ){
-			
-			Map	engine_map = (Map)engines.get( String.valueOf( id ));
-			
-			if ( engine_map != null ){
-				
-				String	engine_str = (String)engine_map.get( "content" );
-				
-				try{
-				
-					Map map = BDecoder.decode( Base64.decode( engine_str.getBytes( "UTF-8" )));
-						
-					return( MetaSearchManagerFactory.getSingleton().getMetaSearch().importFromBEncodedMap(map));
-					
-				}catch( Throwable e ){
-					
-					log( "failed to import engine", e );
-				}
-			}
-		}
-		
-		return( null );
-	}
-	
-	public Subscription
-	cloneWithNewEngine(
-		Engine		engine )
-	
-		throws SubscriptionException
-	{
-		try{	
-			String	json = getJSON();
-			
-			Map map = JSONUtils.decodeJSON( json );
-
-			long	id = ((Long)map.get( "engine_id" )).longValue();
-	
-			if ( id == engine.getId()){
-					
-				embedEngines(map, engine);
-				
-				SubscriptionImpl subs = new SubscriptionImpl( manager, getName(), engine.isPublic(), null, JSONUtils.encodeToJSON(map), SubscriptionImpl.ADD_TYPE_CREATE );
-
-				subs = manager.addSubscription( subs );
-				
-				setLocalName( getName( false ) + " (old)" );
-				
-				return( subs );
-		
-			}else{
-				
-				throw( new SubscriptionException( "Engine mismatch" ));
-			}
-		}catch( Throwable e ){
-			
-			throw( new SubscriptionException( "Failed to export engine", e ));
-		}
-	}
-	
-	public Engine
-	getEngine()
-	
-		throws SubscriptionException
-	{
-		return( getEngine( true ));
-	}
-	
-	protected Engine
-	getEngine(
-		boolean		local_only )
-	
-		throws SubscriptionException
-	{
-		Map map = JSONUtils.decodeJSON( getJSON());
-					
-		return( manager.getEngine( this, map, local_only ));
-	}
-	
-	protected void
-	engineUpdated(
-		Engine		engine )
-	{
-		try{
-			String	json = getJSON();
-			
-			Map map = JSONUtils.decodeJSON( json );
-
-			long	id = ((Long)map.get( "engine_id" )).longValue();
-			
-			if ( id == engine.getId()){
-								
-				if ( setJSON( json )){
-					
-					log( "Engine has been updated, saved" );
-				}
-			}
-		}catch( Throwable e ){
-			
-			log( "Engine update failed", e );
-		}
-	}
-	
-	public boolean
-	setDetails(
-		String		_name,
-		boolean		_is_public,
-		String		_json )
-	
-		throws SubscriptionException
-	{
-		_json = embedEngines( _json );
-		
-		SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );		
-		
-		String	old_json = body.getJSON();
-		
-		boolean	json_changed = !_json.equals( old_json );
-		
-		if ( 	!_name.equals( name ) ||
-				_is_public != is_public ||
-				json_changed ){
-			
-			boolean	ok = false;
-			
-			String	old_name	= name;
-			boolean	old_public	= is_public;
-			int		old_version	= version;
-			
-			try{
-				is_public	= _is_public;			
-				name		= _name;
-
-				body.setJSON( _json );
-				
-				version++;
-												
-				syncToBody( body );
-				
-				versionUpdated( body, json_changed );
-
-				ok = true;
-				
-			}finally{
-				
-				if ( !ok ){
-				
-					version		= old_version;
-					is_public	= old_public;
-					name		= old_name;
-				}
-			}
-			
-			fireChanged();
-			
-			return( true );
-		}
-		
-		return( false );
-	}
-	
-	protected void
-	versionUpdated(
-		SubscriptionBodyImpl		body,
-		boolean						json_changed )
-	{
-		if ( json_changed ){
-			
-			try{		
-				Map map = JSONUtils.decodeJSON( body.getJSON());
-
-				schedule_map = (Map)map.get( "schedule" );
-				
-			}catch( Throwable e ){
-			}
-		}
-		
-		name_ex = null;
-		
-		if ( is_public ){
-			
-			manager.updatePublicSubscription( this );
-			
-			setPublished( false );
-			
-			synchronized( this ){
-
-				for (int i=0;i<associations.size();i++){
-					
-					((association)associations.get(i)).setPublished( false );
-				}
-			}
-		}	
-	}
-	
-	public byte[]
-	getPublicKey()
-	{
-		return( public_key );
-	}
-	
-	public byte[]
-	getShortID()
-	{
-		return( short_id );
-	}
-	
-	public String
-	getID()
-	{
-		if (id == null) {
-			id = Base32.encode(getShortID());
-		}
-		return( id );
-	}
-	
-	protected byte[]
-	getPrivateKey()
-	{
-		return( private_key );
-	}
-	
-	protected int
-	getFixedRandom()
-	{
-		return( fixed_random );
-	}
-	
-	public int
-	getVersion()
-	{
-		return( version );
-	}
-	
-	public int
-	getAZVersion()
-	{
-		return( az_version );
-	}
-	
-	protected void
-	setHighestUserPromptedVersion(
-		int		v )
-	{
-		if ( v < version ){
-			
-			v  = version;
-		}
-		
-		if ( highest_prompted_version != v ){
-			
-			highest_prompted_version = v;
-			
-			fireChanged();
-		}
-	}
-	
-	protected int
-	getHighestUserPromptedVersion()
-	{
-		return( highest_prompted_version );
-	}
-	
-	public int
-	getHighestVersion()
-	{
-		return( Math.max( version, highest_prompted_version ));
-	}
-	
-	public void
-	resetHighestVersion()
-	{
-		if ( highest_prompted_version > 0 ){
-			
-			highest_prompted_version = 0;
-			
-			fireChanged();
-			
-			manager.checkUpgrade(this);
-		}
-	}
-	
-	public boolean
-	isMine()
-	{
-		if ( private_key == null ){
-			
-			return( false );
-		}
-		
-		if ( isSingleton() && add_type != ADD_TYPE_CREATE ){
-			
-			return( false );
-		}
-		
-		return( true );
-	}
-	
-	public boolean
-	isUpdateable()
-	{
-		return( private_key != null );
-	}
-	
-	public boolean
-	isSubscribed()
-	{
-		return( is_subscribed );
-	}
-	
-	public void
-	setSubscribed(
-		boolean			s )
-	{
-		if ( is_subscribed != s ){
-			
-			is_subscribed = s;
-			
-			if ( is_subscribed ){
-				
-				manager.setSelected( this );
-				
-			}else{
-				
-				reset();
-			}
-			
-			fireChanged();
-		}
-	}
-	
-	public boolean 
-	isAutoDownloadSupported() 
-	{
-		return( history.isAutoDownloadSupported());
-	}
-	
-	public void
-	getPopularity(
-		final SubscriptionPopularityListener	listener )
-	
-		throws SubscriptionException
-	{
-		new AEThread2( "subs:popwait", true )
-		{
-			public void
-			run()
-			{		
-				try{
-					manager.getPopularity( 
-						SubscriptionImpl.this,
-						new SubscriptionPopularityListener()
-						{
-							public void
-							gotPopularity(
-								long						pop )
-							{
-								if ( pop != popularity ){
-									
-									popularity = pop;
-									
-									fireChanged();
-								}
-								
-								listener.gotPopularity( popularity );
-							}
-							
-							public void
-							failed(
-								SubscriptionException		e )
-							{
-								if ( popularity == -1 ){
-									
-									listener.failed( new SubscriptionException( "Failed to read popularity", e ));
-									
-								}else{
-									
-									listener.gotPopularity( popularity );
-								}
-							}
-						});
-					
-				}catch( Throwable e ){
-					
-					if ( popularity == -1 ){
-					
-						listener.failed( new SubscriptionException( "Failed to read popularity", e ));
-						
-					}else{
-						
-						listener.gotPopularity( popularity );
-					}
-				}
-			}
-		}.start();
-	}
-	
-	public long 
-	getCachedPopularity() 
-	{
-		return( popularity );
-	}
-	
-	protected void
-	setCachedPopularity(
-		long		pop )
-	{
-		if ( pop != popularity ){
-			
-			popularity		= pop;
-			
-			fireChanged();
-		}
-	}
-	
-	public String
-	getReferer()
-	{
-		if ( referer == null ){
-			
-			try{
-				Map map = JSONUtils.decodeJSON( getJSON());
-						
-				Engine engine = manager.getEngine( this, map, false );
-				
-				if ( engine != null ){
-										
-					referer = engine.getReferer();
-				}
-			}catch( Throwable e ){
-				
-				log( "Failed to get referer", e );
-			}
-			
-			if ( referer == null ){
-				
-				referer = "";
-			}
-		}
-		
-		return( referer );
-	}
-	
-	protected void
-	checkPublish()
-	{
-		synchronized( this ){
-			
-			if ( destroyed ){
-				
-				return;
-			}
-				
-				// singleton's not available for upgrade
-			
-			if ( isSingleton()){
-				
-				return;
-			}
-			
-				// nothing to do for unsubscribed ones
-			
-			if ( !isSubscribed()){
-				
-				return;
-			}
-			
-			if ( popularity > 100 ){
-			
-					// one off test on whether to track so we have around 100 active
-				
-				if ( lws_skip_check == 2 ){
-					
-					return;
-					
-				}else if ( lws_skip_check == 0 ){
-									
-					if ( RandomUtils.nextInt((int)(( popularity + 99 ) / 100 )) == 0 ){
-						
-						lws_skip_check = 1;
-						
-					}else{
-						
-						lws_skip_check = 2;
-						
-						return;
-					}
-				}
-			}
-			
-			if ( hash != null ){
-				
-				boolean	create = false;
-
-				if ( lws == null ){
-					
-					create = true;
-					
-				}else{
-					
-					if ( !Arrays.equals( lws.getHash().getBytes(), hash )){
-			
-						lws.remove();
-						
-						create = true;
-					}
-				}
-				
-				if ( create ){
-										
-					try{
-						File original_data_location = manager.getVuzeFile( this );
-
-						if ( original_data_location.exists()){
-							
-								// make a version based filename to avoid issues regarding multiple
-								// versions
-							
-							final File	versioned_data_location = new File( original_data_location.getParent(), original_data_location.getName() + "." + getVersion());
-							
-							if ( !versioned_data_location.exists()){
-								
-								if ( !FileUtil.copyFile( original_data_location, versioned_data_location )){
-									
-									throw( new Exception( "Failed to copy file to '" + versioned_data_location + "'" ));
-								}
-							}
-							
-							lws = LightWeightSeedManager.getSingleton().add(
-									getName(),
-									new HashWrapper( hash ),
-									TorrentUtils.getDecentralisedEmptyURL(),
-									versioned_data_location,
-									new LightWeightSeedAdapter()
-									{
-										public TOTorrent 
-										getTorrent(
-											byte[] 		hash,
-											URL 		announce_url, 
-											File 		data_location) 
-										
-											throws Exception
-										{
-											log( " - generating torrent: " + Debug.getCompressedStackTrace());
-											
-											TOTorrentCreator creator = 
-												TOTorrentFactory.createFromFileOrDirWithFixedPieceLength( 
-														data_location, 
-														announce_url,
-														256*1024 );
-									
-											TOTorrent t = creator.create();
-											
-											t.setHashOverride( hash );
-											
-											return( t );
-										}
-									});
-						}
-								
-					}catch( Throwable e ){
-						
-						log( "Failed to create light-weight-seed", e );
-					}
-				}
-			}
-		}
-	}
-	
-	protected synchronized boolean
-	canAutoUpgradeCheck()
-	{
-		if ( isSingleton()){
-			
-			return( false );
-		}
-		
-		long	now = SystemTime.getMonotonousTime();
-		
-		if ( last_auto_upgrade_check == -1 || now - last_auto_upgrade_check > 4*60*60*1000 ){
-			
-			last_auto_upgrade_check = now;
-			
-			return( true );
-		}
-		
-		return( false );
-	}
-	
-	public void
-	addAssociation(
-		byte[]		hash )
-	{
-		synchronized( this ){
-	
-			for (int i=0;i<associations.size();i++){
-				
-				association assoc = (association)associations.get(i);
-				
-				if ( Arrays.equals( assoc.getHash(), hash )){
-					
-					return;
-				}
-			}
-			
-			associations.add( new association( hash, SystemTime.getCurrentTime()));
-			
-			if ( associations.size() > MAX_ASSOCIATIONS ){
-				
-				associations.remove( RandomUtils.nextInt( MAX_ASSOCIATIONS - MIN_RECENT_ASSOC_TO_RETAIN ));
-			}
-		}
-		
-		fireChanged();
-		
-		manager.associationAdded( this, hash);
-	}
-	
-	public boolean
-	hasAssociation(
-		byte[]		hash )
-	{
-		synchronized( this ){
-	
-			for (int i=0;i<associations.size();i++){
-				
-				association assoc = (association)associations.get(i);
-				
-				if ( Arrays.equals( assoc.getHash(), hash )){
-					
-					return( true );
-				}
-			}
-		}
-			
-		return( false );	
-	}
-	
-	public void
-	addPotentialAssociation(
-		String		result_id,
-		String		key )
-	{
-		manager.addPotentialAssociation( this, result_id, key );
-	}
-	
-	public int
-	getAssociationCount()
-	{
-		synchronized( this ){
-			
-			return( associations.size());
-		}
-	}
-	
-	protected association
-	getAssociationForPublish()
-	{
-		synchronized( this ){
-			
-			int	num_assoc = associations.size();
-			
-				// first set in order of most recent
-			
-			for (int i=num_assoc-1;i>=Math.max( 0, num_assoc-MIN_RECENT_ASSOC_TO_RETAIN);i--){
-				
-				association assoc = (association)associations.get(i);
-				
-				if ( !assoc.getPublished()){
-					
-					assoc.setPublished( true );
-					
-					return( assoc );
-				}
-			}
-			
-				// remaining randomised
-			
-			int	rem = associations.size() - MIN_RECENT_ASSOC_TO_RETAIN;
-			
-			if ( rem > 0 ){
-				
-				List l = new ArrayList( associations.subList( 0, rem ));
-				
-				Collections.shuffle( l );
-				
-				for (int i=0;i<l.size();i++){
-					
-					association assoc = (association)l.get(i);
-
-					if ( !assoc.getPublished()){
-						
-						assoc.setPublished( true );
-						
-						return( assoc );
-					}
-				}
-			}
-		}
-		
-		return( null );
-	}
-	
-	protected boolean
-	getPublished()
-	{
-		return( published );
-	}
-	
-	protected void
-	setPublished(
-		boolean		b )
-	{
-		published = b;
-	}
-	
-	protected int
-	getVerifiedPublicationVersion(
-		Map		details )
-	{
-			// singleton versions always 1 and each instance has separate private key so
-			// verification will always fail so save to just return current version
-		
-		if ( isSingleton()){
-			
-			return( getVersion());
-		}
-		
-		if ( !verifyPublicationDetails( details )){
-			
-			return( -1 );
-		}
-
-		return( getPublicationVersion( details ));
-	}
-	
-	protected static int
-	getPublicationVersion(
-		Map		details )
-	{
-		return(((Long)details.get("v")).intValue());
-	}
-	
-	protected byte[]
-	getPublicationHash()
-	{
-		return( hash );
-	}
-	
-	protected static byte[]
-	getPublicationHash(
-		Map		details )
-	{
-		return((byte[])details.get( "h" ));
-	}
-	
-	protected static int
-	getPublicationSize(
-		Map		details )
-	{
-		return(((Long)details.get("z")).intValue());
-	}
-	
-	protected Map
-	getPublicationDetails()
-	{
-		Map	result = new HashMap();
-		
-		result.put( "v", new Long( version ));
-			
-		if ( singleton_details == null ){
-			
-			result.put( "h", hash );
-			result.put( "z", new Long( sig_data_size ));
-			result.put( "s", sig );
-
-		}else{
-			
-			result.put( "x", singleton_details );
-		}
-		
-		return( result );
-	}
-	
-	protected boolean
-	verifyPublicationDetails(
-		Map		details )
-	{
-		synchronized( this ){
-			
-			if ( BEncoder.mapsAreIdentical( verify_cache_details, details )){
-								
-				return( verify_cache_result );
-			}
-		}
-				
-		byte[]	hash 	= (byte[])details.get( "h" );
-		int		version	= ((Long)details.get( "v" )).intValue();
-		int		size	= ((Long)details.get( "z" )).intValue();
-		byte[]	sig		= (byte[])details.get( "s" );
-		
-		boolean	result = SubscriptionBodyImpl.verify( public_key, hash, version, size, sig );
-		
-		synchronized( this ){
-			
-			verify_cache_details 	= details;
-			verify_cache_result		= result;
-		}
-		
-		return( result );
-	}
-	
-	public void
-	setCreatorRef(
-		String	ref )
-	{
-		creator_ref = ref;
-		
-		fireChanged();
-	}
-	
-	public String
-	getCreatorRef()
-	{
-		return( creator_ref );
-	}
-	
-	public void
-	setCategory(
-		String	_category )
-	{
-		if ( _category == null && category == null ){
-			
-			return;
-		}
-		
-		if ( _category != null && category != null && _category.equals( category )){
-			
-			return;
-		}
-				
-		manager.setCategoryOnExisting( this, category, _category );
-		
-		category = _category;
-
-		fireChanged();
-	}
-	
-	public String
-	getCategory()
-	{
-		return( category );
-	}
-
-	public void
-	setTagID(
-		long	_tag_id )
-	{
-
-		if ( _tag_id == tag_id ){
-			
-			return;
-		}
-			
-		// don't update existing download tagging at the moment
-		//manager.setTagOnExisting( this, tag, _tag );
-		
-		tag_id = _tag_id;
-
-		fireChanged();
-	}
-	
-	public long
-	getTagID()
-	{
-		return( tag_id );
-	}
-	
-	protected void
-	fireChanged()
-	{
-		manager.configDirty( this );
-		
-		Iterator it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((SubscriptionListener)it.next()).subscriptionChanged( this );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-	}
-
-	protected void
-	fireDownloaded(
-		boolean	was_auto )
-	{
-
-		Iterator it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((SubscriptionListener)it.next()).subscriptionDownloaded( this, was_auto );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-	}
-	
-	public void
-	addListener(
-		SubscriptionListener	l )
-	{
-		listeners.add( l );
-	}
-	
-	public void
-	removeListener(
-		SubscriptionListener	l )
-	{
-		listeners.remove( l );
-	}
-	
-	public SubscriptionHistory 
-	getHistory() 
-	{
-		return( history );
-	}
-	
-	public SubscriptionManager
-	getManager()
-	{
-		return( manager );
-	}
-	
-	public VuzeFile 
-	getVuzeFile() 
-	
-		throws SubscriptionException
-	{
-		try{
-			return( VuzeFileHandler.getSingleton().loadVuzeFile( manager.getVuzeFile( this ).getAbsolutePath()));
-			
-		}catch( Throwable e ){
-			
-			throw( new SubscriptionException( "Failed to get Vuze file", e ));
-		}
-	}
-	
-	public VuzeFile 
-	getSearchTemplateVuzeFile()
-	{
-		if ( !isSearchTemplate()){
-			
-			return( null );
-		}
-		
-		Object[] details = manager.getSearchTemplateVuzeFile( this );
-		
-		if ( details != null ){
-			
-			return((VuzeFile)details[0]);
-		}
-		
-		return( null );
-	}
-	
-	public boolean 
-	isSearchTemplateImportable() 
-	{
-		return( manager.isSearchTemplateImportable( this ));
-	}
-	
-	protected void
-	destroy()
-	{
-		LightWeightSeed l;
-		
-		synchronized( this ){
-			
-			destroyed	= true;
-			
-			l = lws;
-		}
-		
-		if ( l != null ){
-			
-			l.remove();
-		}
-	}
-	
-	public void
-	reset()
-	{
-		getHistory().reset();
-		
-		try{
-			getEngine().reset();
-			
-		}catch( Throwable e ){
-			
-			Debug.printStackTrace(e);
-		}
-	}
-	
-	public void
-	remove()
-	{
-		destroy();
-		
-		manager.removeSubscription( this );
-	}
-	
-	protected boolean
-	isRemoved()
-	{
-		synchronized( this ){
-
-			return( destroyed );
-		}
-	}
-	
-	public SubscriptionResult[]
-  	getResults(
-  		boolean		include_deleted )
-	{
-		return( getHistory().getResults( include_deleted ));
-	}
-	
-	public void
-	setUserData(
-		Object		key,
-		Object		data )
-	{
-		synchronized( user_data ){
-			
-			if ( data == null ){
-				
-				user_data.remove( key );
-				
-			}else{
-				
-				user_data.put( key, data );
-			}
-		}
-	}
-	
-	public Object
-	getUserData(
-		Object		key )
-	{
-		synchronized( user_data ){
-
-			return( user_data.get( key ));
-		}
-	}
-	
-	protected void
-	log(
-		String		str )
-	{
-		manager.log( getString() + ": " + str );
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable	e )
-	{
-		manager.log( getString() + ": " + str, e );
-	}
-	
-	public String
-	getString()
-	{
-		return( "name=" + name + 
-					",sid=" + ByteFormatter.encodeString( short_id ) + 
-					",ver=" + version + 
-					",pub=" + is_public +
-					",mine=" + isMine() +
-					",sub=" + is_subscribed +
-					(is_subscribed?(",hist={" + history.getString() + "}"):"") +
-					",pop=" + popularity + 
-					(server_publication_outstanding?",spo=true":""));
-	}
-	
-	protected void
-	generate(
-		IndentWriter		writer )
-	{
-		String	engine_str;
-		
-		try{
-			
-			engine_str = "" + getEngine().getId();
-			
-		}catch( Throwable e ){
-			
-			engine_str = Debug.getNestedExceptionMessage(e);
-		}
-		
-		writer.println( getString() + ": engine=" + engine_str );
-			
-		try{
-			writer.indent();
-			
-			synchronized( this ){
-
-				for (int i=0;i<associations.size();i++){
-					
-					((association)associations.get(i)).generate( writer );
-				}
-			}
-		}finally{
-			
-			writer.exdent();
-		}
-	}
-	
-	protected static class
-	association
-	{
-		private byte[]	hash;
-		private long	when;
-		private boolean	published;
-		
-		protected
-		association(
-			byte[]		_hash,
-			long		_when )
-		{
-			hash		= _hash;
-			when		= _when;
-		}
-		
-		protected byte[]
-		getHash()
-		{
-			return( hash );
-		}
-		
-		protected long
-		getWhen()
-		{
-			return( when );
-		}
-		
-		protected boolean
-		getPublished()
-		{
-			return( published );
-		}
-		
-		protected void
-		setPublished(
-			boolean		b )
-		{
-			published = b;
-		}
-		
-		protected String
-		getString()
-		{
-			return( ByteFormatter.encodeString( hash ) + ", pub=" + published );
-		}
-		
-		protected void
-		generate(
-			IndentWriter		writer )
-		{
-			writer.println( getString());
-		}
-	}
-}
+/*
+ * Created on Jul 11, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.security.KeyPair;
+import java.util.*;
+
+import org.bouncycastle.util.encoders.Base64;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentCreator;
+import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
+import org.gudy.azureus2.core3.util.AEThread2;
+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.ByteFormatter;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.FileUtil;
+import org.gudy.azureus2.core3.util.HashWrapper;
+import org.gudy.azureus2.core3.util.IndentWriter;
+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.core3.util.TorrentUtils;
+import org.gudy.azureus2.core3.util.UrlUtils;
+import org.json.simple.JSONObject;
+
+import com.aelitis.azureus.core.lws.LightWeightSeed;
+import com.aelitis.azureus.core.lws.LightWeightSeedAdapter;
+import com.aelitis.azureus.core.lws.LightWeightSeedManager;
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.MetaSearchManagerFactory;
+import com.aelitis.azureus.core.security.CryptoECCUtils;
+import com.aelitis.azureus.core.subs.Subscription;
+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.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;
+import com.aelitis.azureus.util.ImportExportUtils;
+import com.aelitis.azureus.util.JSONUtils;
+
+public class 
+SubscriptionImpl 
+	implements Subscription 
+{
+	public static final int	ADD_TYPE_CREATE		= 1;
+	public static final int	ADD_TYPE_IMPORT		= 2;
+	public static final int	ADD_TYPE_LOOKUP		= 3;
+		
+	private static final int MAX_ASSOCIATIONS				= 256;
+	private static final int MIN_RECENT_ASSOC_TO_RETAIN		= 16;
+		
+	//private static final byte[] GENERIC_PUBLIC_KEY 		= {(byte)0x04,(byte)0xd0,(byte)0x1a,(byte)0xd9,(byte)0xb9,(byte)0x99,(byte)0xd8,(byte)0x49,(byte)0x15,(byte)0x5f,(byte)0xe9,(byte)0x6b,(byte)0x3c,(byte)0xd8,(byte)0x18,(byte)0x81,(byte)0xf7,(byte)0x92,(byte)0x15,(byte)0x3f,(byte)0x24,(byte)0xaa,(byte)0x35,(byte)0x6f,(byte)0x52,(byte)0x01,(byte)0x79,(byte)0x2e,(byte)0x93,(byte)0xf6,(byte)0xf1,(byte)0x57,(byte)0x13,(byte)0x2a,(byte)0x3c,(byte)0x31,(byte)0x66,(byte)0xa5,(byte)0x34,(byte)0x [...]
+	// private static final byte[] GENERIC_PRIVATE_KEY 	= {(byte)0x71,(byte)0xc3,(byte)0xe8,(byte)0x6c,(byte)0x56,(byte)0xbb,(byte)0x30,(byte)0x14,(byte)0x9e,(byte)0x19,(byte)0xa5,(byte)0x3d,(byte)0xcb,(byte)0x47,(byte)0xbb,(byte)0x6d,(byte)0x57,(byte)0x57,(byte)0xd3,(byte)0x59,(byte)0xce,(byte)0x8f,(byte)0x79,(byte)0xe5};
+
+	protected static byte[]
+	intToBytes(
+		int		version )
+	{
+		return( new byte[]{ (byte)(version>>24), (byte)(version>>16),(byte)(version>>8),(byte)version } );
+	}
+	
+	protected static int
+	bytesToInt(
+		byte[]		bytes )
+	{
+		return( (bytes[0]<<24)&0xff000000 | (bytes[1] << 16)&0x00ff0000 | (bytes[2] << 8)&0x0000ff00 | bytes[3]&0x000000ff );
+	}
+		
+	private SubscriptionManagerImpl		manager;
+	
+	private byte[]			public_key;
+	private byte[]			private_key;
+	
+	private String			name;
+	private String			name_ex;
+	
+	private int				version;
+	private int				az_version;
+	
+	private boolean			is_public;
+	private Map				singleton_details;
+	
+	private byte[]			hash;
+	private byte[]			sig;
+	private int				sig_data_size;
+	
+	private int				add_type;
+	private long			add_time;
+	
+	private boolean			is_subscribed;
+	
+	private int				highest_prompted_version;
+	
+	private byte[]			short_id;
+
+	private String			id;
+
+	private List			associations = new ArrayList();
+	
+	private int				fixed_random;
+	
+	private long			popularity				= -1;
+	
+	private long			last_auto_upgrade_check	= -1;
+	private boolean			published;
+	
+	private boolean			server_published;
+	private boolean			server_publication_outstanding;
+	
+	private boolean			singleton_sp_attempted;
+	private String			local_name;
+	
+	private LightWeightSeed	lws;
+	private int				lws_skip_check;
+	
+	private boolean			destroyed;
+	
+	private Map				history_map;
+	private Map				schedule_map;
+	
+	private Map				user_data = new LightHashMap();
+	
+	private final 			SubscriptionHistoryImpl	history;
+	
+	private String			referer;
+	
+	private CopyOnWriteList	listeners = new CopyOnWriteList();
+	
+	private Map				verify_cache_details;
+	private boolean			verify_cache_result;
+	
+	private String			creator_ref;
+	private String			category;
+	private long			tag_id = -1;
+	
+	protected static String
+	getSkeletonJSON(
+		Engine		engine,
+		int			check_interval_mins )
+	{
+		JSONObject	map = new JSONObject();
+		
+		map.put( "engine_id", new Long( engine.getId()));
+		
+		map.put( "search_term", "" );
+
+		map.put( "filters", new HashMap());
+		
+		map.put( "options", new HashMap());
+		
+		Map schedule = new HashMap();
+		
+		schedule.put( "interval", new Long( check_interval_mins ));
+		
+		List	days = new ArrayList();
+		
+		for (int i=1;i<=7;i++){
+			
+			days.add( String.valueOf(i));
+		}
+		
+		schedule.put( "days", days );
+		
+		map.put( "schedule", schedule );
+		
+		embedEngines( map, engine );
+		
+		return( JSONUtils.encodeToJSON( map ));
+	}
+	
+	
+		// new subs constructor
+	
+	protected
+	SubscriptionImpl(
+		SubscriptionManagerImpl		_manager,
+		String						_name,
+		boolean						_public,
+		Map							_singleton_details,
+		String						_json_content,
+		int							_add_type )
+	
+		throws SubscriptionException
+	{
+		manager	= _manager;
+		
+		history_map	= new HashMap();
+
+		history = new SubscriptionHistoryImpl( manager, this );
+		
+		name				= _name;
+		is_public			= _public;
+		singleton_details	= _singleton_details;
+		
+		version				= 1;
+		az_version			= AZ_VERSION;
+		
+		add_type			= _add_type;
+		add_time			= SystemTime.getCurrentTime();
+		
+		is_subscribed		= true;
+
+		try{
+			KeyPair	kp = CryptoECCUtils.createKeys();
+				
+			public_key 			= CryptoECCUtils.keyToRawdata( kp.getPublic());
+			private_key 		= CryptoECCUtils.keyToRawdata( kp.getPrivate());
+						
+			
+			fixed_random	= RandomUtils.nextInt();
+			
+			init();
+			
+			String json_content = embedEngines( _json_content );
+			
+			SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, name, is_public, json_content, public_key, version, az_version, singleton_details );
+						
+			syncToBody( body );
+			
+		}catch( Throwable e ){
+			
+			throw( new SubscriptionException( "Failed to create subscription", e ));
+		}
+	}
+	
+		// cache detail constructor
+	
+	protected
+	SubscriptionImpl(
+		SubscriptionManagerImpl		_manager,
+		Map							map )
+	
+		throws IOException
+	{
+		manager	= _manager;
+				
+		fromMap( map );
+		
+		history = new SubscriptionHistoryImpl( manager, this );
+
+		init();
+	}
+
+		// import constructor
+	
+	protected
+	SubscriptionImpl(
+		SubscriptionManagerImpl		_manager,
+		SubscriptionBodyImpl		_body,
+		int							_add_type,
+		boolean						_is_subscribed )
+	
+		throws SubscriptionException
+	{
+		manager	= _manager;
+			
+		history_map	= new HashMap();
+		
+		history = new SubscriptionHistoryImpl( manager, this );
+		
+		syncFromBody( _body );
+		
+		add_type		= _add_type;
+		add_time		= SystemTime.getCurrentTime();
+		
+		is_subscribed	= _is_subscribed;
+		
+		fixed_random	= RandomUtils.nextInt();
+		
+		init();
+				
+		syncToBody( _body );
+	}
+	
+	protected void
+	syncFromBody(
+		SubscriptionBodyImpl	body )
+	
+		throws SubscriptionException
+	{
+		public_key			= body.getPublicKey();
+		version				= body.getVersion();
+		az_version			= body.getAZVersion();
+				
+		name				= body.getName();
+		is_public			= body.isPublic();
+		singleton_details	= body.getSingletonDetails();
+		
+		if ( az_version > AZ_VERSION ){
+			
+			throw( new SubscriptionException( MessageText.getString( "subscription.version.bad", new String[]{ name })));
+		}
+	}
+	
+	protected void
+	syncToBody(
+		SubscriptionBodyImpl		body )
+	
+		throws SubscriptionException
+	{
+			// this picks up latest values of version, name + is_public from here
+		
+		body.writeVuzeFile( this );
+		
+		hash 			= body.getHash();
+		sig				= body.getSig();
+		sig_data_size	= body.getSigDataSize();
+	}
+	
+	protected Map
+	toMap()
+	
+		throws IOException
+	{
+		synchronized( this ){
+			
+			Map	map = new HashMap();
+			
+			map.put( "name", name.getBytes( "UTF-8" ));
+			
+			map.put( "public_key", public_key );
+						
+			map.put( "version", new Long( version ));
+			
+			map.put( "az_version", new Long( az_version ));
+			
+			map.put( "is_public", new Long( is_public?1:0 ));
+			
+			if ( singleton_details != null ){
+				
+				map.put( "sin_details", singleton_details );
+				map.put( "spa", new Long( singleton_sp_attempted?1:0 ));
+			}
+			
+			if ( local_name != null ){
+				
+				map.put( "local_name", local_name );
+			}
+				// body data
+			
+			map.put( "hash", hash );
+			map.put( "sig", sig );
+			map.put( "sig_data_size", new Long( sig_data_size ));
+			
+				// local data
+			
+			if ( private_key != null ){
+				
+				map.put( "private_key", private_key );
+			}
+
+			map.put( "add_type", new Long( add_type ));
+			map.put( "add_time", new Long( add_time ));
+			
+			map.put( "subscribed", new Long( is_subscribed?1:0 ));
+			
+			map.put( "pop", new Long( popularity ));
+			
+			map.put( "rand", new Long( fixed_random ));
+			
+			map.put( "hupv", new Long( highest_prompted_version ));
+			
+			map.put( "sp", new Long( server_published?1:0 ));
+			map.put( "spo", new Long( server_publication_outstanding?1:0 ));
+						
+			if ( associations.size() > 0 ){
+				
+				List	l_assoc = new ArrayList();
+				
+				map.put( "assoc", l_assoc );
+				
+				for (int i=0;i<associations.size();i++){
+					
+					association assoc = (association)associations.get(i);
+					
+					Map m = new HashMap();
+					
+					l_assoc.add( m );
+					
+					m.put( "h", assoc.getHash());
+					m.put( "w", new Long( assoc.getWhen()));
+				}
+			}
+			
+			map.put( "history", history_map );
+			
+			if ( creator_ref != null ){
+				
+				map.put( "cref", creator_ref.getBytes( "UTF-8" ));
+			}
+			
+			if ( category != null ){
+				
+				map.put( "cat", category.getBytes( "UTF-8" ));
+			}
+			
+			if ( tag_id != -1 ){
+				
+				map.put( "tag", tag_id );
+			}
+			
+			return( map );
+		}
+	}
+	
+	protected void
+	fromMap(
+		Map		map )
+	
+		throws IOException
+	{
+		name				= new String((byte[])map.get( "name"), "UTF-8" );
+		public_key			= (byte[])map.get( "public_key" );
+		private_key			= (byte[])map.get( "private_key" );
+		version				= ((Long)map.get( "version" )).intValue();
+		az_version			= (int)ImportExportUtils.importLong( map, "az_version", AZ_VERSION );
+		is_public			= ((Long)map.get( "is_public")).intValue() == 1;
+		singleton_details	= (Map)map.get( "sin_details" );
+		
+		hash			= (byte[])map.get( "hash" );
+		sig				= (byte[])map.get( "sig" );
+		sig_data_size	= ((Long)map.get( "sig_data_size" )).intValue();
+		
+		fixed_random	= ((Long)map.get( "rand" )).intValue();
+		
+		add_type		= ((Long)map.get( "add_type" )).intValue();		
+		add_time		= ((Long)map.get( "add_time" )).longValue();
+		
+		is_subscribed	= ((Long)map.get( "subscribed" )).intValue()==1;
+				
+		popularity		= ((Long)map.get( "pop" )).longValue();
+		
+		highest_prompted_version = ((Long)map.get( "hupv" )).intValue();
+		
+		server_published = ((Long)map.get( "sp" )).intValue()==1;
+		server_publication_outstanding = ((Long)map.get( "spo" )).intValue()==1;
+		
+		Long	l_spa = (Long)map.get( "spa" );
+		
+		if ( l_spa != null ){
+			singleton_sp_attempted = l_spa.longValue()==1; 
+		}
+		
+		byte[]	b_local_name = (byte[])map.get( "local_name" );
+		
+		if ( b_local_name != null ){
+			
+			local_name = new String( b_local_name, "UTF-8" );
+		}
+		
+		List	l_assoc = (List)map.get( "assoc" );
+		
+		if ( l_assoc != null ){
+			
+			for (int i=0;i<l_assoc.size();i++){
+				
+				Map	m = (Map)l_assoc.get(i);
+				
+				byte[]		hash 	= (byte[])m.get("h");
+				long		when	= ((Long)m.get( "w" )).longValue();
+				
+				associations.add( new association( hash, when ));
+			}
+		}
+		
+		history_map = (Map)map.get( "history" );
+		
+		if ( history_map == null ){
+			
+			history_map = new HashMap();
+		}
+		
+		byte[] b_cref = (byte[])map.get( "cref" );
+		
+		if ( b_cref != null ){
+			
+			creator_ref = new String( b_cref, "UTF-8" );
+		}
+		
+		byte[] b_cat = (byte[])map.get( "cat" );
+		
+		if ( b_cat != null ){
+			
+			category = new String( b_cat, "UTF-8" );
+		}
+		
+		Long l_tag_id = (Long)map.get( "tag" );
+		
+		if ( l_tag_id != null ){
+			
+			tag_id = l_tag_id;
+		}
+	}
+	
+	protected Map
+	getScheduleConfig()
+	{
+		if ( schedule_map == null ){
+			
+			try{		
+				Map map = JSONUtils.decodeJSON( getJSON());
+
+				schedule_map = (Map)map.get( "schedule" );
+				
+				if ( schedule_map == null ){
+					
+					schedule_map = new HashMap();
+				}
+			}catch( Throwable e ){
+				
+				log( "Failed to load schedule", e );
+				
+				schedule_map = new HashMap();
+			}
+		}
+		
+		return( schedule_map );
+	}
+	
+	protected Map
+	getHistoryConfig()
+	{
+		return( history_map );
+	}
+	
+	protected void
+	updateHistoryConfig(
+		Map		_history_map )
+	{
+		history_map = _history_map;
+		
+		fireChanged();
+	}
+	
+	protected void
+	upgrade(
+		SubscriptionBodyImpl		body )
+	
+		throws SubscriptionException
+	{
+			// pick up details from the body (excluding json that is maintained in body only)
+		
+		syncFromBody( body );
+		
+			// write to file
+		
+		syncToBody(body);
+		
+		fireChanged();
+	}
+	
+	protected void
+	init()
+	{
+		short_id = SubscriptionBodyImpl.deriveShortID( public_key, singleton_details );
+		id = null;
+	}
+	
+	public boolean
+	isSingleton()
+	{
+		return( singleton_details != null );
+	}
+	
+	public boolean
+	isShareable()
+	{
+		try{
+			return( getEngine().isShareable() && !isSingleton());
+			
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+			
+			return( false );
+		}
+	}
+	
+	public boolean
+	isSearchTemplate()
+	{
+		return( getName(false).startsWith( "Search Template:" ));
+	}
+	
+	protected Map
+	getSingletonDetails()
+	{
+		return( singleton_details );
+	}
+	
+	protected boolean
+	getSingletonPublishAttempted()
+	{
+		return( singleton_sp_attempted );
+	}
+	
+	protected void
+	setSingletonPublishAttempted()
+	{
+		if ( !singleton_sp_attempted ){
+			
+			singleton_sp_attempted = true;
+		
+			manager.configDirty( this );
+		}
+	}
+	
+	public String
+	getName()
+	{
+		return( getName( true ));
+	}
+	
+	public String
+	getName(
+		boolean	use_local )
+	{
+		return( local_name==null?name:local_name );
+	}
+	
+	public String
+	getURI()
+	{
+		String str = "sub:?name=" + UrlUtils.encode(getName()) + "&id=" + Base32.encode(getShortID()) + "&v=" + getVersion();
+		
+		return( "azplug:?id=subscription&arg=" + UrlUtils.encode( str ));
+	}
+	
+	public void 
+	requestAttention() 
+	{
+		manager.selectSubscription( this );
+	}
+	
+	public void
+	setLocalName(
+		String		str )
+	{
+		local_name = str;
+		
+		manager.configDirty( this );
+		
+		fireChanged();
+	}
+	
+	public void
+	setName(
+		String		_name )
+	
+		throws SubscriptionException
+	{
+		if ( !name.equals( _name )){
+			
+			boolean	ok = false;
+			
+			String	old_name 	= name;
+			int		old_version	= version;
+			
+			try{
+				name	= _name;
+				
+				version++;
+				
+				SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );
+					
+				syncToBody( body );
+				
+				versionUpdated( body, false );
+				
+				ok	= true;
+				
+			}finally{
+				
+				if ( !ok ){
+					
+					name 	= old_name;
+					version	= old_version;
+				}
+			}
+			
+			fireChanged();
+		}
+	}
+	
+	public String
+	getNameEx()
+	{
+		if ( name_ex == null ){
+			
+			try{
+				Map map = JSONUtils.decodeJSON( getJSON());
+				
+				String	search_term	= (String)map.get( "search_term" );
+				Map		filters		= (Map)map.get( "filters" );
+	
+				Engine engine = manager.getEngine( this, map, true );
+
+				String	engine_name = engine.getNameEx();
+				
+				if ( name.startsWith( engine_name )){
+					
+					name_ex = name;
+					
+				}else if ( engine_name.startsWith( name )){
+					
+					name_ex = engine_name;
+					
+				}else{
+					
+					name_ex = name + ": " + engine.getNameEx();
+				}
+				
+				if ( search_term != null && search_term.length() > 0 ){
+					
+					name_ex += ", query=" + search_term;
+				}
+				
+				if ( filters != null && filters.size() > 0 ){
+					
+					name_ex += ", filters=" + new SubscriptionResultFilter(filters).getString();
+				}
+				
+			}catch( Throwable e ){
+				
+				name_ex = name + ": " + Debug.getNestedExceptionMessage(e);
+			}
+		}
+		
+		return( name_ex );
+	}
+	
+	public long
+	getAddTime()
+	{
+		return( add_time );
+	}
+	
+	public boolean
+	isPublic()
+	{
+		return( is_public );
+	}
+	
+	public void
+	setPublic(
+		boolean		_is_public )
+	
+		throws SubscriptionException
+	{
+		if ( is_public != _is_public ){
+				
+			boolean	ok = false;
+			
+			boolean	old_public	= is_public;
+			int		old_version	= version;
+			
+			try{
+				is_public	= _is_public;
+				
+				version++;
+								
+				SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );
+				
+				syncToBody( body );
+				
+				versionUpdated( body, false );
+
+				ok = true;
+				
+			}finally{
+				
+				if ( !ok ){
+				
+					version		= old_version;
+					is_public	= old_public;
+				}
+			}
+			
+			fireChanged();
+		}
+	}
+	
+	protected boolean
+	getServerPublicationOutstanding()
+	{
+		return( server_publication_outstanding );
+	}
+	
+	protected void
+	setServerPublicationOutstanding()	
+	{
+		if ( !server_publication_outstanding ){
+			
+			server_publication_outstanding = true;
+		
+			fireChanged();
+		}
+	}
+	
+	protected void
+	setServerPublished()
+	{
+		if ( server_publication_outstanding || !server_published ){
+			
+			server_published 				= true;
+			server_publication_outstanding	= false;
+			
+			fireChanged();
+		}
+	}
+	
+	protected boolean
+	getServerPublished()
+	{
+		return( server_published );
+	}
+	
+	public String
+	getJSON()
+	
+		throws SubscriptionException
+	{
+		try{
+			SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );
+
+			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
+	setJSON(
+		String		_json )
+	
+		throws SubscriptionException
+	{
+		String json = embedEngines( _json );
+		
+		SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );		
+		
+		String	old_json = body.getJSON();
+		
+		if ( !json.equals( old_json )){
+			
+			boolean	ok = false;
+			
+			int		old_version	= version;
+			
+			try{				
+				version++;
+													
+				body.setJSON( json );
+				
+				syncToBody( body );
+				
+				versionUpdated( body, true );
+
+				referer = null;
+				
+				ok	= true;
+				
+			}finally{
+				
+				if ( !ok ){
+					
+					version	= old_version;
+				}
+			}
+			
+			fireChanged();
+			
+			return( true );
+		}
+		
+		return( false );
+	}
+	
+	protected String
+	embedEngines(
+		String		json_in )
+	{
+			// see if we need to embed private search templates
+		
+		Map map = JSONUtils.decodeJSON( json_in );
+		
+		long 	engine_id 	= ((Long)map.get( "engine_id" )).longValue();
+
+		String	json_out	= json_in;
+		
+		if ( engine_id >= Integer.MAX_VALUE || engine_id < 0 ){
+			
+			Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().getEngine( engine_id );
+
+			if ( engine == null ){
+				
+				log( "Private search template with id '" + engine_id + "' not found!!!!" );
+				
+			}else{
+				
+				try{								
+					embedEngines( map, engine );
+					
+					json_out = JSONUtils.encodeToJSON( map );
+					
+
+					log( "Embedded private search template '" + engine.getName() + "'" );
+					
+				}catch( Throwable e ){
+					
+					log( "Failed to embed private search template", e );
+				}
+			}
+		}
+		
+		return( json_out );
+	}
+	
+	protected static void
+	embedEngines(
+		Map			map,
+		Engine		engine )
+	{
+		Map	engines = new HashMap();
+		
+		map.put( "engines", engines );
+		
+		Map	engine_map = new HashMap();
+		
+		try{
+		
+			String	engine_str = new String( Base64.encode( BEncoder.encode( engine.exportToBencodedMap())), "UTF-8" );
+		
+			engine_map.put( "content", engine_str );
+		
+			engines.put( String.valueOf( engine.getId()), engine_map );
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+	}
+
+	protected Engine
+	extractEngine(
+		Map		json_map,
+		long	id )
+	{
+		Map engines = (Map)json_map.get( "engines" );
+		
+		if ( engines != null ){
+			
+			Map	engine_map = (Map)engines.get( String.valueOf( id ));
+			
+			if ( engine_map != null ){
+				
+				String	engine_str = (String)engine_map.get( "content" );
+				
+				try{
+				
+					Map map = BDecoder.decode( Base64.decode( engine_str.getBytes( "UTF-8" )));
+						
+					return( MetaSearchManagerFactory.getSingleton().getMetaSearch().importFromBEncodedMap(map));
+					
+				}catch( Throwable e ){
+					
+					log( "failed to import engine", e );
+				}
+			}
+		}
+		
+		return( null );
+	}
+	
+	public Subscription
+	cloneWithNewEngine(
+		Engine		engine )
+	
+		throws SubscriptionException
+	{
+		try{	
+			String	json = getJSON();
+			
+			Map map = JSONUtils.decodeJSON( json );
+
+			long	id = ((Long)map.get( "engine_id" )).longValue();
+	
+			if ( id == engine.getId()){
+					
+				embedEngines(map, engine);
+				
+				SubscriptionImpl subs = new SubscriptionImpl( manager, getName(), engine.isPublic(), null, JSONUtils.encodeToJSON(map), SubscriptionImpl.ADD_TYPE_CREATE );
+
+				subs = manager.addSubscription( subs );
+				
+				setLocalName( getName( false ) + " (old)" );
+				
+				return( subs );
+		
+			}else{
+				
+				throw( new SubscriptionException( "Engine mismatch" ));
+			}
+		}catch( Throwable e ){
+			
+			throw( new SubscriptionException( "Failed to export engine", e ));
+		}
+	}
+	
+	public Engine
+	getEngine()
+	
+		throws SubscriptionException
+	{
+		return( getEngine( true ));
+	}
+	
+	protected Engine
+	getEngine(
+		boolean		local_only )
+	
+		throws SubscriptionException
+	{
+		Map map = JSONUtils.decodeJSON( getJSON());
+					
+		return( manager.getEngine( this, map, local_only ));
+	}
+	
+	protected void
+	engineUpdated(
+		Engine		engine )
+	{
+		try{
+			String	json = getJSON();
+			
+			Map map = JSONUtils.decodeJSON( json );
+
+			long	id = ((Long)map.get( "engine_id" )).longValue();
+			
+			if ( id == engine.getId()){
+								
+				if ( setJSON( json )){
+					
+					log( "Engine has been updated, saved" );
+				}
+			}
+		}catch( Throwable e ){
+			
+			log( "Engine update failed", e );
+		}
+	}
+	
+	public boolean
+	setDetails(
+		String		_name,
+		boolean		_is_public,
+		String		_json )
+	
+		throws SubscriptionException
+	{
+		_json = embedEngines( _json );
+		
+		SubscriptionBodyImpl body = new SubscriptionBodyImpl( manager, this );		
+		
+		String	old_json = body.getJSON();
+		
+		boolean	json_changed = !_json.equals( old_json );
+		
+		if ( 	!_name.equals( name ) ||
+				_is_public != is_public ||
+				json_changed ){
+			
+			boolean	ok = false;
+			
+			String	old_name	= name;
+			boolean	old_public	= is_public;
+			int		old_version	= version;
+			
+			try{
+				is_public	= _is_public;			
+				name		= _name;
+
+				body.setJSON( _json );
+				
+				version++;
+												
+				syncToBody( body );
+				
+				versionUpdated( body, json_changed );
+
+				ok = true;
+				
+			}finally{
+				
+				if ( !ok ){
+				
+					version		= old_version;
+					is_public	= old_public;
+					name		= old_name;
+				}
+			}
+			
+			fireChanged();
+			
+			return( true );
+		}
+		
+		return( false );
+	}
+	
+	protected void
+	versionUpdated(
+		SubscriptionBodyImpl		body,
+		boolean						json_changed )
+	{
+		if ( json_changed ){
+			
+			try{		
+				Map map = JSONUtils.decodeJSON( body.getJSON());
+
+				schedule_map = (Map)map.get( "schedule" );
+				
+			}catch( Throwable e ){
+			}
+		}
+		
+		name_ex = null;
+		
+		if ( is_public ){
+			
+			manager.updatePublicSubscription( this );
+			
+			setPublished( false );
+			
+			synchronized( this ){
+
+				for (int i=0;i<associations.size();i++){
+					
+					((association)associations.get(i)).setPublished( false );
+				}
+			}
+		}	
+	}
+	
+	public byte[]
+	getPublicKey()
+	{
+		return( public_key );
+	}
+	
+	public byte[]
+	getShortID()
+	{
+		return( short_id );
+	}
+	
+	public String
+	getID()
+	{
+		if (id == null) {
+			id = Base32.encode(getShortID());
+		}
+		return( id );
+	}
+	
+	protected byte[]
+	getPrivateKey()
+	{
+		return( private_key );
+	}
+	
+	protected int
+	getFixedRandom()
+	{
+		return( fixed_random );
+	}
+	
+	public int
+	getVersion()
+	{
+		return( version );
+	}
+	
+	public int
+	getAZVersion()
+	{
+		return( az_version );
+	}
+	
+	protected void
+	setHighestUserPromptedVersion(
+		int		v )
+	{
+		if ( v < version ){
+			
+			v  = version;
+		}
+		
+		if ( highest_prompted_version != v ){
+			
+			highest_prompted_version = v;
+			
+			fireChanged();
+		}
+	}
+	
+	protected int
+	getHighestUserPromptedVersion()
+	{
+		return( highest_prompted_version );
+	}
+	
+	public int
+	getHighestVersion()
+	{
+		return( Math.max( version, highest_prompted_version ));
+	}
+	
+	public void
+	resetHighestVersion()
+	{
+		if ( highest_prompted_version > 0 ){
+			
+			highest_prompted_version = 0;
+			
+			fireChanged();
+			
+			manager.checkUpgrade(this);
+		}
+	}
+	
+	public boolean
+	isMine()
+	{
+		if ( private_key == null ){
+			
+			return( false );
+		}
+		
+		if ( isSingleton() && add_type != ADD_TYPE_CREATE ){
+			
+			return( false );
+		}
+		
+		return( true );
+	}
+	
+	public boolean
+	isUpdateable()
+	{
+		return( private_key != null );
+	}
+	
+	public boolean
+	isSubscribed()
+	{
+		return( is_subscribed );
+	}
+	
+	public void
+	setSubscribed(
+		boolean			s )
+	{
+		if ( is_subscribed != s ){
+			
+			is_subscribed = s;
+			
+			if ( is_subscribed ){
+				
+				manager.setSelected( this );
+				
+			}else{
+				
+				reset();
+			}
+			
+			fireChanged();
+		}
+	}
+	
+	public boolean 
+	isAutoDownloadSupported() 
+	{
+		return( history.isAutoDownloadSupported());
+	}
+	
+	public void
+	getPopularity(
+		final SubscriptionPopularityListener	listener )
+	
+		throws SubscriptionException
+	{
+		new AEThread2( "subs:popwait", true )
+		{
+			public void
+			run()
+			{		
+				try{
+					manager.getPopularity( 
+						SubscriptionImpl.this,
+						new SubscriptionPopularityListener()
+						{
+							public void
+							gotPopularity(
+								long						pop )
+							{
+								if ( pop != popularity ){
+									
+									popularity = pop;
+									
+									fireChanged();
+								}
+								
+								listener.gotPopularity( popularity );
+							}
+							
+							public void
+							failed(
+								SubscriptionException		e )
+							{
+								if ( popularity == -1 ){
+									
+									listener.failed( new SubscriptionException( "Failed to read popularity", e ));
+									
+								}else{
+									
+									listener.gotPopularity( popularity );
+								}
+							}
+						});
+					
+				}catch( Throwable e ){
+					
+					if ( popularity == -1 ){
+					
+						listener.failed( new SubscriptionException( "Failed to read popularity", e ));
+						
+					}else{
+						
+						listener.gotPopularity( popularity );
+					}
+				}
+			}
+		}.start();
+	}
+	
+	public long 
+	getCachedPopularity() 
+	{
+		return( popularity );
+	}
+	
+	protected void
+	setCachedPopularity(
+		long		pop )
+	{
+		if ( pop != popularity ){
+			
+			popularity		= pop;
+			
+			fireChanged();
+		}
+	}
+	
+	public String
+	getReferer()
+	{
+		if ( referer == null ){
+			
+			try{
+				Map map = JSONUtils.decodeJSON( getJSON());
+						
+				Engine engine = manager.getEngine( this, map, false );
+				
+				if ( engine != null ){
+										
+					referer = engine.getReferer();
+				}
+			}catch( Throwable e ){
+				
+				log( "Failed to get referer", e );
+			}
+			
+			if ( referer == null ){
+				
+				referer = "";
+			}
+		}
+		
+		return( referer );
+	}
+	
+	protected void
+	checkPublish()
+	{
+		synchronized( this ){
+			
+			if ( destroyed ){
+				
+				return;
+			}
+				
+				// singleton's not available for upgrade
+			
+			if ( isSingleton()){
+				
+				return;
+			}
+			
+				// nothing to do for unsubscribed ones
+			
+			if ( !isSubscribed()){
+				
+				return;
+			}
+			
+			if ( popularity > 100 ){
+			
+					// one off test on whether to track so we have around 100 active
+				
+				if ( lws_skip_check == 2 ){
+					
+					return;
+					
+				}else if ( lws_skip_check == 0 ){
+									
+					if ( RandomUtils.nextInt((int)(( popularity + 99 ) / 100 )) == 0 ){
+						
+						lws_skip_check = 1;
+						
+					}else{
+						
+						lws_skip_check = 2;
+						
+						return;
+					}
+				}
+			}
+			
+			if ( hash != null ){
+				
+				boolean	create = false;
+
+				if ( lws == null ){
+					
+					create = true;
+					
+				}else{
+					
+					if ( !Arrays.equals( lws.getHash().getBytes(), hash )){
+			
+						lws.remove();
+						
+						create = true;
+					}
+				}
+				
+				if ( create ){
+										
+					try{
+						File original_data_location = manager.getVuzeFile( this );
+
+						if ( original_data_location.exists()){
+							
+								// make a version based filename to avoid issues regarding multiple
+								// versions
+							
+							final File	versioned_data_location = new File( original_data_location.getParent(), original_data_location.getName() + "." + getVersion());
+							
+							if ( !versioned_data_location.exists()){
+								
+								if ( !FileUtil.copyFile( original_data_location, versioned_data_location )){
+									
+									throw( new Exception( "Failed to copy file to '" + versioned_data_location + "'" ));
+								}
+							}
+							
+							lws = LightWeightSeedManager.getSingleton().add(
+									getName(),
+									new HashWrapper( hash ),
+									TorrentUtils.getDecentralisedEmptyURL(),
+									versioned_data_location,
+									new LightWeightSeedAdapter()
+									{
+										public TOTorrent 
+										getTorrent(
+											byte[] 		hash,
+											URL 		announce_url, 
+											File 		data_location) 
+										
+											throws Exception
+										{
+											log( " - generating torrent: " + Debug.getCompressedStackTrace());
+											
+											TOTorrentCreator creator = 
+												TOTorrentFactory.createFromFileOrDirWithFixedPieceLength( 
+														data_location, 
+														announce_url,
+														256*1024 );
+									
+											TOTorrent t = creator.create();
+											
+											t.setHashOverride( hash );
+											
+											return( t );
+										}
+									});
+						}
+								
+					}catch( Throwable e ){
+						
+						log( "Failed to create light-weight-seed", e );
+					}
+				}
+			}
+		}
+	}
+	
+	protected synchronized boolean
+	canAutoUpgradeCheck()
+	{
+		if ( isSingleton()){
+			
+			return( false );
+		}
+		
+		long	now = SystemTime.getMonotonousTime();
+		
+		if ( last_auto_upgrade_check == -1 || now - last_auto_upgrade_check > 4*60*60*1000 ){
+			
+			last_auto_upgrade_check = now;
+			
+			return( true );
+		}
+		
+		return( false );
+	}
+	
+	public void
+	addAssociation(
+		byte[]		hash )
+	{
+		synchronized( this ){
+	
+			for (int i=0;i<associations.size();i++){
+				
+				association assoc = (association)associations.get(i);
+				
+				if ( Arrays.equals( assoc.getHash(), hash )){
+					
+					return;
+				}
+			}
+			
+			associations.add( new association( hash, SystemTime.getCurrentTime()));
+			
+			if ( associations.size() > MAX_ASSOCIATIONS ){
+				
+				associations.remove( RandomUtils.nextInt( MAX_ASSOCIATIONS - MIN_RECENT_ASSOC_TO_RETAIN ));
+			}
+		}
+		
+		fireChanged();
+		
+		manager.associationAdded( this, hash);
+	}
+	
+	public boolean
+	hasAssociation(
+		byte[]		hash )
+	{
+		synchronized( this ){
+	
+			for (int i=0;i<associations.size();i++){
+				
+				association assoc = (association)associations.get(i);
+				
+				if ( Arrays.equals( assoc.getHash(), hash )){
+					
+					return( true );
+				}
+			}
+		}
+			
+		return( false );	
+	}
+	
+	public void
+	addPotentialAssociation(
+		String		result_id,
+		String		key )
+	{
+		manager.addPotentialAssociation( this, result_id, key );
+	}
+	
+	public int
+	getAssociationCount()
+	{
+		synchronized( this ){
+			
+			return( associations.size());
+		}
+	}
+	
+	protected association
+	getAssociationForPublish()
+	{
+		synchronized( this ){
+			
+			int	num_assoc = associations.size();
+			
+				// first set in order of most recent
+			
+			for (int i=num_assoc-1;i>=Math.max( 0, num_assoc-MIN_RECENT_ASSOC_TO_RETAIN);i--){
+				
+				association assoc = (association)associations.get(i);
+				
+				if ( !assoc.getPublished()){
+					
+					assoc.setPublished( true );
+					
+					return( assoc );
+				}
+			}
+			
+				// remaining randomised
+			
+			int	rem = associations.size() - MIN_RECENT_ASSOC_TO_RETAIN;
+			
+			if ( rem > 0 ){
+				
+				List l = new ArrayList( associations.subList( 0, rem ));
+				
+				Collections.shuffle( l );
+				
+				for (int i=0;i<l.size();i++){
+					
+					association assoc = (association)l.get(i);
+
+					if ( !assoc.getPublished()){
+						
+						assoc.setPublished( true );
+						
+						return( assoc );
+					}
+				}
+			}
+		}
+		
+		return( null );
+	}
+	
+	protected boolean
+	getPublished()
+	{
+		return( published );
+	}
+	
+	protected void
+	setPublished(
+		boolean		b )
+	{
+		published = b;
+	}
+	
+	protected int
+	getVerifiedPublicationVersion(
+		Map		details )
+	{
+			// singleton versions always 1 and each instance has separate private key so
+			// verification will always fail so save to just return current version
+		
+		if ( isSingleton()){
+			
+			return( getVersion());
+		}
+		
+		if ( !verifyPublicationDetails( details )){
+			
+			return( -1 );
+		}
+
+		return( getPublicationVersion( details ));
+	}
+	
+	protected static int
+	getPublicationVersion(
+		Map		details )
+	{
+		return(((Long)details.get("v")).intValue());
+	}
+	
+	protected byte[]
+	getPublicationHash()
+	{
+		return( hash );
+	}
+	
+	protected static byte[]
+	getPublicationHash(
+		Map		details )
+	{
+		return((byte[])details.get( "h" ));
+	}
+	
+	protected static int
+	getPublicationSize(
+		Map		details )
+	{
+		return(((Long)details.get("z")).intValue());
+	}
+	
+	protected Map
+	getPublicationDetails()
+	{
+		Map	result = new HashMap();
+		
+		result.put( "v", new Long( version ));
+			
+		if ( singleton_details == null ){
+			
+			result.put( "h", hash );
+			result.put( "z", new Long( sig_data_size ));
+			result.put( "s", sig );
+
+		}else{
+			
+			result.put( "x", singleton_details );
+		}
+		
+		return( result );
+	}
+	
+	protected boolean
+	verifyPublicationDetails(
+		Map		details )
+	{
+		synchronized( this ){
+			
+			if ( BEncoder.mapsAreIdentical( verify_cache_details, details )){
+								
+				return( verify_cache_result );
+			}
+		}
+				
+		byte[]	hash 	= (byte[])details.get( "h" );
+		int		version	= ((Long)details.get( "v" )).intValue();
+		int		size	= ((Long)details.get( "z" )).intValue();
+		byte[]	sig		= (byte[])details.get( "s" );
+		
+		boolean	result = SubscriptionBodyImpl.verify( public_key, hash, version, size, sig );
+		
+		synchronized( this ){
+			
+			verify_cache_details 	= details;
+			verify_cache_result		= result;
+		}
+		
+		return( result );
+	}
+	
+	public void
+	setCreatorRef(
+		String	ref )
+	{
+		creator_ref = ref;
+		
+		fireChanged();
+	}
+	
+	public String
+	getCreatorRef()
+	{
+		return( creator_ref );
+	}
+	
+	public void
+	setCategory(
+		String	_category )
+	{
+		if ( _category == null && category == null ){
+			
+			return;
+		}
+		
+		if ( _category != null && category != null && _category.equals( category )){
+			
+			return;
+		}
+				
+		manager.setCategoryOnExisting( this, category, _category );
+		
+		category = _category;
+
+		fireChanged();
+	}
+	
+	public String
+	getCategory()
+	{
+		return( category );
+	}
+
+	public void
+	setTagID(
+		long	_tag_id )
+	{
+
+		if ( _tag_id == tag_id ){
+			
+			return;
+		}
+			
+		// don't update existing download tagging at the moment
+		//manager.setTagOnExisting( this, tag, _tag );
+		
+		tag_id = _tag_id;
+
+		fireChanged();
+	}
+	
+	public long
+	getTagID()
+	{
+		return( tag_id );
+	}
+	
+	protected void
+	fireChanged()
+	{
+		manager.configDirty( this );
+		
+		Iterator it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((SubscriptionListener)it.next()).subscriptionChanged( this );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+	}
+
+	protected void
+	fireDownloaded(
+		boolean	was_auto )
+	{
+
+		Iterator it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((SubscriptionListener)it.next()).subscriptionDownloaded( this, was_auto );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+	}
+	
+	public void
+	addListener(
+		SubscriptionListener	l )
+	{
+		listeners.add( l );
+	}
+	
+	public void
+	removeListener(
+		SubscriptionListener	l )
+	{
+		listeners.remove( l );
+	}
+	
+	public SubscriptionHistory 
+	getHistory() 
+	{
+		return( history );
+	}
+	
+	public SubscriptionManager
+	getManager()
+	{
+		return( manager );
+	}
+	
+	public VuzeFile 
+	getVuzeFile() 
+	
+		throws SubscriptionException
+	{
+		try{
+			return( VuzeFileHandler.getSingleton().loadVuzeFile( manager.getVuzeFile( this ).getAbsolutePath()));
+			
+		}catch( Throwable e ){
+			
+			throw( new SubscriptionException( "Failed to get Vuze file", e ));
+		}
+	}
+	
+	public VuzeFile 
+	getSearchTemplateVuzeFile()
+	{
+		if ( !isSearchTemplate()){
+			
+			return( null );
+		}
+		
+		Object[] details = manager.getSearchTemplateVuzeFile( this );
+		
+		if ( details != null ){
+			
+			return((VuzeFile)details[0]);
+		}
+		
+		return( null );
+	}
+	
+	public boolean 
+	isSearchTemplateImportable() 
+	{
+		return( manager.isSearchTemplateImportable( this ));
+	}
+	
+	protected void
+	destroy()
+	{
+		LightWeightSeed l;
+		
+		synchronized( this ){
+			
+			destroyed	= true;
+			
+			l = lws;
+		}
+		
+		if ( l != null ){
+			
+			l.remove();
+		}
+	}
+	
+	public void
+	reset()
+	{
+		getHistory().reset();
+		
+		try{
+			getEngine().reset();
+			
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+		}
+	}
+	
+	public void
+	remove()
+	{
+		destroy();
+		
+		manager.removeSubscription( this );
+	}
+	
+	protected boolean
+	isRemoved()
+	{
+		synchronized( this ){
+
+			return( destroyed );
+		}
+	}
+	
+	public SubscriptionResult[]
+  	getResults(
+  		boolean		include_deleted )
+	{
+		return( getHistory().getResults( include_deleted ));
+	}
+	
+	public void
+	setUserData(
+		Object		key,
+		Object		data )
+	{
+		synchronized( user_data ){
+			
+			if ( data == null ){
+				
+				user_data.remove( key );
+				
+			}else{
+				
+				user_data.put( key, data );
+			}
+		}
+	}
+	
+	public Object
+	getUserData(
+		Object		key )
+	{
+		synchronized( user_data ){
+
+			return( user_data.get( key ));
+		}
+	}
+	
+	protected void
+	log(
+		String		str )
+	{
+		manager.log( getString() + ": " + str );
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable	e )
+	{
+		manager.log( getString() + ": " + str, e );
+	}
+	
+	public String
+	getString()
+	{
+		return( "name=" + name + 
+					",sid=" + ByteFormatter.encodeString( short_id ) + 
+					",ver=" + version + 
+					",pub=" + is_public +
+					",mine=" + isMine() +
+					",sub=" + is_subscribed +
+					(is_subscribed?(",hist={" + history.getString() + "}"):"") +
+					",pop=" + popularity + 
+					(server_publication_outstanding?",spo=true":""));
+	}
+	
+	protected void
+	generate(
+		IndentWriter		writer )
+	{
+		String	engine_str;
+		
+		try{
+			
+			engine_str = "" + getEngine().getId();
+			
+		}catch( Throwable e ){
+			
+			engine_str = Debug.getNestedExceptionMessage(e);
+		}
+		
+		writer.println( getString() + ": engine=" + engine_str );
+			
+		try{
+			writer.indent();
+			
+			synchronized( this ){
+
+				for (int i=0;i<associations.size();i++){
+					
+					((association)associations.get(i)).generate( writer );
+				}
+			}
+		}finally{
+			
+			writer.exdent();
+		}
+	}
+	
+	protected static class
+	association
+	{
+		private byte[]	hash;
+		private long	when;
+		private boolean	published;
+		
+		protected
+		association(
+			byte[]		_hash,
+			long		_when )
+		{
+			hash		= _hash;
+			when		= _when;
+		}
+		
+		protected byte[]
+		getHash()
+		{
+			return( hash );
+		}
+		
+		protected long
+		getWhen()
+		{
+			return( when );
+		}
+		
+		protected boolean
+		getPublished()
+		{
+			return( published );
+		}
+		
+		protected void
+		setPublished(
+			boolean		b )
+		{
+			published = b;
+		}
+		
+		protected String
+		getString()
+		{
+			return( ByteFormatter.encodeString( hash ) + ", pub=" + published );
+		}
+		
+		protected void
+		generate(
+			IndentWriter		writer )
+		{
+			writer.println( getString());
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionManagerImpl.java b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionManagerImpl.java
index 2a5182b..aea62a1 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionManagerImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionManagerImpl.java
@@ -1,6303 +1,6599 @@
-/*
- * Created on Jul 11, 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.core.subs.impl;
-
-import java.io.*;
-import java.net.InetSocketAddress;
-import java.net.URL;
-import java.security.KeyPair;
-import java.util.*;
-import java.util.regex.Pattern;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-import org.bouncycastle.util.encoders.Base64;
-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.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.PluginException;
-import org.gudy.azureus2.plugins.utils.Utilities;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.download.*;
-import org.gudy.azureus2.plugins.peers.PeerManager;
-import org.gudy.azureus2.plugins.torrent.Torrent;
-import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
-import org.gudy.azureus2.plugins.torrent.TorrentManager;
-import org.gudy.azureus2.plugins.ui.UIManager;
-import org.gudy.azureus2.plugins.ui.UIManagerEvent;
-import org.gudy.azureus2.plugins.utils.DelayedTask;
-import org.gudy.azureus2.plugins.utils.StaticUtilities;
-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 org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl;
-import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
-
-import com.aelitis.azureus.core.AzureusCore;
-import com.aelitis.azureus.core.AzureusCoreRunningListener;
-import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.custom.Customization;
-import com.aelitis.azureus.core.custom.CustomizationManager;
-import com.aelitis.azureus.core.custom.CustomizationManagerFactory;
-import com.aelitis.azureus.core.dht.DHT;
-import com.aelitis.azureus.core.lws.LightWeightSeed;
-import com.aelitis.azureus.core.lws.LightWeightSeedManager;
-import com.aelitis.azureus.core.messenger.config.PlatformSubscriptionsMessenger;
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.MetaSearchListener;
-import com.aelitis.azureus.core.metasearch.MetaSearchManagerFactory;
-import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
-import com.aelitis.azureus.core.metasearch.impl.web.rss.RSSEngine;
-import com.aelitis.azureus.core.security.CryptoECCUtils;
-import com.aelitis.azureus.core.subs.*;
-import com.aelitis.azureus.core.subs.SubscriptionUtils.SubscriptionDownloadDetails;
-import com.aelitis.azureus.core.tag.Tag;
-import com.aelitis.azureus.core.tag.TagManagerFactory;
-import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-import com.aelitis.azureus.core.vuzefile.*;
-import com.aelitis.azureus.plugins.dht.*;
-import com.aelitis.azureus.plugins.magnet.MagnetPlugin;
-import com.aelitis.azureus.plugins.magnet.MagnetPluginProgressListener;
-import com.aelitis.azureus.util.ImportExportUtils;
-import com.aelitis.azureus.util.UrlFilter;
-import com.aelitis.net.magneturi.MagnetURIHandler;
-
-
-public class 
-SubscriptionManagerImpl 
-	implements SubscriptionManager, AEDiagnosticsEvidenceGenerator
-{	
-	private static final String	CONFIG_FILE = "subscriptions.config";
-	private static final String	LOGGER_NAME = "Subscriptions";
-
-	private static final String CONFIG_MAX_RESULTS 			= "subscriptions.max.non.deleted.results";
-	private static final String CONFIG_AUTO_START_DLS 		= "subscriptions.auto.start.downloads";
-	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	CONFIG_RSS_ENABLE			= "subscriptions.config.rss_enable";
-
-	private static final String	CONFIG_ENABLE_SEARCH			= "subscriptions.config.search_enable";
-	
-	private static final String	CONFIG_HIDE_SEARCH_TEMPLATES	= "subscriptions.config.hide_search_templates";
-	
-	private static final String	CONFIG_DL_SUBS_ENABLE		= "subscriptions.config.dl_subs_enable";
-
-	private static final int DELETE_UNUSED_AFTER_MILLIS = 2*7*24*60*60*1000;
-	
-	
-	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()
-			{
-				public void
-				process(
-					VuzeFile[]		files,
-					int				expected_types )
-				{
-					for (int i=0;i<files.length;i++){
-						
-						VuzeFile	vf = files[i];
-						
-						VuzeFileComponent[] comps = vf.getComponents();
-						
-						for (int j=0;j<comps.length;j++){
-							
-							VuzeFileComponent comp = comps[j];
-							
-							int	type = comp.getType();
-							
-							if ( 	type == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION ||
-									type == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION_SINGLETON ){
-								
-								try{
-									Subscription subs = ((SubscriptionManagerImpl)getSingleton( false )).importSubscription(
-											type,
-											comp.getContent(),
-											( expected_types & 
-												( VuzeFileComponent.COMP_TYPE_SUBSCRIPTION | VuzeFileComponent.COMP_TYPE_SUBSCRIPTION_SINGLETON )) == 0 );
-									
-									comp.setProcessed();
-									
-									comp.setData( Subscription.VUZE_FILE_COMPONENT_SUBSCRIPTION_KEY, subs );
-									
-								}catch( Throwable e ){
-									
-									Debug.printStackTrace(e);
-								}
-							}
-						}
-					}
-				}
-			});		
-	}
-		
-	public static SubscriptionManager
-	getSingleton(
-		boolean		stand_alone )
-	{
-		preInitialise();
-		
-		synchronized( SubscriptionManagerImpl.class ){
-			
-			if ( singleton != null ){
-			
-				return( singleton );
-			}
-			
-			singleton = new SubscriptionManagerImpl( stand_alone );
-		}
-		
-			// saw deadlock here when adding core listener while synced on class - rework
-			// to avoid 
-		
-		if ( !stand_alone ){
-			
-			singleton.initialise();
-		}
-		
-		return( singleton );
-	}
-	
-	
-	private boolean		started;
-		
-	private static final int	TIMER_PERIOD		= 30*1000;
-	
-	private static final int	ASSOC_CHECK_PERIOD	= 5*60*1000;
-	private static final int	ASSOC_CHECK_TICKS	= ASSOC_CHECK_PERIOD/TIMER_PERIOD;
-	
-	private static final int	SERVER_PUB_CHECK_PERIOD	= 10*60*1000;
-	private static final int	SERVER_PUB_CHECK_TICKS	= SERVER_PUB_CHECK_PERIOD/TIMER_PERIOD;
-	
-	private static final int	TIDY_POT_ASSOC_PERIOD	= 30*60*1000;
-	private static final int	TIDY_POT_ASSOC_TICKS	= TIDY_POT_ASSOC_PERIOD/TIMER_PERIOD;
-
-	private static final int	SET_SELECTED_PERIOD		= 23*60*60*1000;
-	private static final int	SET_SELECTED_FIRST_TICK	= 3*60*1000 /TIMER_PERIOD;
-	private static final int	SET_SELECTED_TICKS		= SET_SELECTED_PERIOD/TIMER_PERIOD;
-
-	private static final Object	SP_LAST_ATTEMPTED	= new Object();
-	private static final Object	SP_CONSEC_FAIL		= new Object();
-	
-	private AzureusCore		azureus_core;
-	
-	private volatile DHTPlugin	dht_plugin;
-	
-	private List<SubscriptionImpl>		subscriptions	= new ArrayList<SubscriptionImpl>();
-	
-	private boolean	config_dirty;
-	
-	private static final int PUB_ASSOC_CONC_MAX				= 3;
-	private static final int PUB_SLEEPING_ASSOC_CONC_MAX	= 1;
-	
-	private int		publish_associations_active;
-	private boolean	publish_next_asyc_pending;
-	
-	private boolean publish_subscription_active;
-	
-	private TorrentAttribute		ta_subs_download;
-	private TorrentAttribute		ta_subs_download_rd;
-	private TorrentAttribute		ta_subscription_info;
-	private TorrentAttribute		ta_category;
-	
-	private boolean					periodic_lookup_in_progress;
-	private int						priority_lookup_pending;
-	
-	private CopyOnWriteList<SubscriptionManagerListener>			listeners = new CopyOnWriteList<SubscriptionManagerListener>();
-	
-	private SubscriptionSchedulerImpl	scheduler;
-	
-	private List<Object[]>				potential_associations	= new ArrayList<Object[]>();
-	private Map<HashWrapper,Object[]>	potential_associations2	= new HashMap<HashWrapper,Object[]>();
-	
-	private boolean					meta_search_listener_added;
-	
-	private Pattern					exclusion_pattern = Pattern.compile( "azdev[0-9]+\\.azureus\\.com" );
-	
-	private SubscriptionRSSFeed		rss_publisher;
-	
-	private AEDiagnosticsLogger		logger;
-	
-	
-	protected
-	SubscriptionManagerImpl(
-		boolean	stand_alone )
-	{
-		if ( !stand_alone ){
-			
-			loadConfig();
-	
-			AEDiagnostics.addEvidenceGenerator( this );
-			
-			CustomizationManager cust_man = CustomizationManagerFactory.getSingleton();
-			
-			Customization cust = cust_man.getActiveCustomization();
-			
-			if ( cust != null ){
-				
-				String cust_name 	= COConfigurationManager.getStringParameter( "subscriptions.custom.name", "" );
-				String cust_version = COConfigurationManager.getStringParameter( "subscriptions.custom.version", "0" );
-				
-				boolean	new_name 	= !cust_name.equals( cust.getName());
-				boolean	new_version = org.gudy.azureus2.core3.util.Constants.compareVersions( cust_version, cust.getVersion() ) < 0;
-				
-				if ( new_name || new_version ){
-
-					log( "Customization: checking templates for " + cust.getName() + "/" + cust.getVersion());
-					
-					try{
-						InputStream[] streams = cust.getResources( Customization.RT_SUBSCRIPTIONS );
-						
-						for (int i=0;i<streams.length;i++){
-							
-							InputStream is = streams[i];
-							
-							try{
-								VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile(is);
-								
-								if ( vf != null ){
-									
-									VuzeFileComponent[] comps = vf.getComponents();
-									
-									for (int j=0;j<comps.length;j++){
-										
-										VuzeFileComponent comp = comps[j];
-										
-										int type = comp.getType();
-										
-										if ( 	type == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION ||
-												type == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION_SINGLETON	){
-											
-											try{
-												importSubscription(
-														type,
-														comp.getContent(),
-														false );
-												
-												comp.setProcessed();
-												
-											}catch( Throwable e ){
-												
-												Debug.printStackTrace(e);
-											}
-										}
-									}
-								}
-							}finally{
-								
-								try{
-									is.close();
-									
-								}catch( Throwable e ){
-								}
-							}
-						}
-					}finally{
-						
-						COConfigurationManager.setParameter( "subscriptions.custom.name", cust.getName());
-						COConfigurationManager.setParameter( "subscriptions.custom.version", cust.getVersion());
-					}
-				}
-			}
-			
-			scheduler = new SubscriptionSchedulerImpl( this );
-		}
-	}
-	
-	protected void
-	initialise()
-	{
-		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
-			public void azureusCoreRunning(final AzureusCore core) {
-				initWithCore(core);
-			}
-		});
-	}
-
-	protected void
-	initWithCore(
-		AzureusCore 	_core )
-	{
-		synchronized( this ){
-			
-			if ( started ){
-				
-				return;
-			}
-			
-			started	= true;
-		}
-
-		azureus_core = _core;
-		
-		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" );
-		ta_subs_download_rd 	= tm.getPluginAttribute( "azsubs.subs_dl_rd" );
-		ta_subscription_info 	= tm.getPluginAttribute( "azsubs.subs_info" );
-		ta_category				= tm.getAttribute( TorrentAttribute.TA_CATEGORY );
-		
-		PluginInterface  dht_plugin_pi  = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass( DHTPlugin.class );
-				
-		if ( dht_plugin_pi != null ){
-			
-			dht_plugin = (DHTPlugin)dht_plugin_pi.getPlugin();
-
-			/*
-			if ( Constants.isCVSVersion()){
-				
-				addListener(
-						new SubscriptionManagerListener()
-						{
-							public void 
-							subscriptionAdded(
-								Subscription subscription ) 
-							{
-							}
-				
-							public void
-							subscriptionChanged(
-								Subscription		subscription )
-							{
-							}
-							
-							public void 
-							subscriptionRemoved(
-								Subscription subscription ) 
-							{
-							}
-							
-							public void 
-							associationsChanged(
-								byte[] hash )
-							{
-								System.out.println( "Subscriptions changed: " + ByteFormatter.encodeString( hash ));
-								
-								Subscription[] subs = getKnownSubscriptions( hash );
-							
-								for (int i=0;i<subs.length;i++){
-									
-									System.out.println( "    " + subs[i].getString());
-								}
-							}
-						});	
-			}
-			*/
-			
-			default_pi.getDownloadManager().addListener(
-				new DownloadManagerListener()
-				{
-					public void
-					downloadAdded(
-						Download	download )
-					{
-						Torrent	torrent = download.getTorrent();
-						
-						if ( torrent != null ){
-							
-							byte[]	hash = torrent.getHash();
-							
-							Object[] entry;
-							
-							synchronized( potential_associations2 ){
-								
-								entry = (Object[])potential_associations2.remove( new HashWrapper( hash ));
-							}
-							
-							if ( entry != null ){
-								
-								SubscriptionImpl[] subs = (SubscriptionImpl[])entry[0];
-								
-								String	subs_str = "";
-								for (int i=0;i<subs.length;i++){
-									subs_str += (i==0?"":",") + subs[i].getName();
-								}
-								
-								log( "Applying deferred asocciation for " + ByteFormatter.encodeString( hash ) + " -> " + subs_str );
-								
-								recordAssociationsSupport(
-									hash,
-									subs,
-									((Boolean)entry[1]).booleanValue());
-							}
-						}
-					}
-					
-					public void
-					downloadRemoved(
-						Download	download )
-					{	
-					}
-				},
-				false );
-			
-			TorrentUtils.addTorrentAttributeListener(
-				new TorrentUtils.torrentAttributeListener()
-				{
-					public void 
-					attributeSet(
-						TOTorrent 	torrent,
-						String 		attribute, 
-						Object 		value )
-					{
-						if ( attribute == TorrentUtils.TORRENT_AZ_PROP_OBTAINED_FROM ){
-							
-							try{
-								checkPotentialAssociations( torrent.getHash(), (String)value );
-								
-							}catch( Throwable e ){
-								
-								Debug.printStackTrace(e);
-							}
-						}
-					}
-				});
-				
-			DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "Subscriptions", 
-					new Runnable()
-					{
-						public void 
-						run() 
-						{
-							new AEThread2( "Subscriptions:delayInit", true )
-							{
-								public void
-								run()
-								{
-									asyncInit();
-								}
-							}.start();
-							
-						}
-						
-						protected void
-						asyncInit()
-						{
-							Download[] downloads = default_pi.getDownloadManager().getDownloads();
-									
-							for (int i=0;i<downloads.length;i++){
-								
-								Download download = downloads[i];
-								
-								if ( download.getBooleanAttribute( ta_subs_download )){
-									
-									Map	rd = download.getMapAttribute( ta_subs_download_rd );
-									
-									boolean	delete_it;
-									
-									if ( rd == null ){
-										
-										delete_it = true;
-										
-									}else{
-										
-										delete_it = !recoverSubscriptionUpdate( download, rd );
-									}
-									
-									if ( delete_it ){
-										
-										removeDownload( download, true );
-									}
-								}
-							}
-								
-							default_pi.getDownloadManager().addListener(
-								new DownloadManagerListener()
-								{
-									public void
-									downloadAdded(
-										final Download	download )
-									{
-											// if ever changed to handle non-persistent then you need to fix init deadlock
-											// potential with share-hoster plugin
-										
-										if ( download.isPersistent()){
-											
-											if ( !dht_plugin.isInitialising()){
-								
-													// if new download then we want to check out its subscription status 
-												
-												lookupAssociations( download.getMapAttribute( ta_subscription_info ) == null );
-												
-											}else{
-												
-												new AEThread2( "Subscriptions:delayInit", true )
-												{
-													public void
-													run()
-													{
-														lookupAssociations( download.getMapAttribute( ta_subscription_info ) == null );
-													}
-												}.start();
-											}
-										}
-									}
-									
-									public void
-									downloadRemoved(
-										Download	download )
-									{
-									}
-								},
-								false );
-							
-							for (int i=0;i<PUB_ASSOC_CONC_MAX;i++){
-							
-								if ( publishAssociations()){
-									
-									break;
-								}
-							}
-							
-							publishSubscriptions();
-							
-							COConfigurationManager.addParameterListener(
-									CONFIG_MAX_RESULTS,
-									new ParameterListener()
-									{
-										public void 
-										parameterChanged(
-											String	 name )
-										{
-											final int	max_results = COConfigurationManager.getIntParameter( CONFIG_MAX_RESULTS );
-											
-											new AEThread2( "Subs:max results changer", true )
-											{
-												public void
-												run()
-												{
-													checkMaxResults( max_results );
-												}
-											}.start();
-										}
-									});
-							
-							SimpleTimer.addPeriodicEvent(
-									"SubscriptionChecker",
-									TIMER_PERIOD,
-									new TimerEventPerformer()
-									{
-										private int	ticks;
-										
-										public void 
-										perform(
-											TimerEvent event )
-										{
-											ticks++;
-											
-											checkStuff( ticks );
-										}
-									});
-						}
-					});
-		
-			delayed_task.queue();
-		}
-		
-		if ( isSearchEnabled()){
-			
-			try{
-				default_pi.getUtilities().registerSearchProvider(
-					new SearchProvider()
-					{
-						private Map<Integer,Object>	properties = new HashMap<Integer, Object>();
-						
-						{
-							properties.put( PR_NAME, MessageText.getString( "ConfigView.section.Subscriptions" ));
-							
-							try{
-								URL url = 
-									MagnetURIHandler.getSingleton().registerResource(
-										new MagnetURIHandler.ResourceProvider()
-										{
-											public String
-											getUID()
-											{
-												return( SubscriptionManager.class.getName() + ".2" );
-											}
-											
-											public String
-											getFileType()
-											{
-												return( "png" );
-											}
-													
-											public byte[]
-											getData()
-											{
-												InputStream is = getClass().getClassLoader().getResourceAsStream( "com/aelitis/azureus/ui/images/subscription_icon_1616.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
-						{		
-							try{
-								return( searchSubscriptions( search_parameters, observer ));
-								
-							}catch( Throwable e ){
-								
-								throw( new SearchException( "Search failed", e ));
-							}
-						}
-						
-						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" );
-			}
-		}
-		
-		default_pi.getUtilities().registerJSONRPCServer(
-			new Utilities.JSONServer()
-			{
-				private List<String>	methods = new ArrayList<String>();
-				
-				{
-					methods.add( "vuze-subs-list" );
-				}
-				
-				public String
-				getName()
-				{
-					return( "Subscriptions" );
-				}
-				
-				public List<String> 
-				getSupportedMethods() 
-				{
-					return( methods );
-				}
-				
-				public Map 
-				call(
-					String 		method, 
-					Map		 	args )
-						
-					throws PluginException 
-				{
-					throw( new PluginException( "derp" ));
-				}
-			});
-	}
-
-	protected Object[]
-	getSearchTemplateVuzeFile(
-		SubscriptionImpl	sub )
-	{
-		try{
-			String subs_url_str = ((RSSEngine)sub.getEngine()).getSearchUrl( true );
-			
-			URL subs_url = new URL( subs_url_str );
-			
-			final byte[] vf_bytes = FileUtil.readInputStreamAsByteArray(subs_url.openConnection().getInputStream());
-
-			VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( vf_bytes );
-			
-			if ( MetaSearchManagerFactory.getSingleton().isImportable( vf )){
-	
-				return( new Object[]{ vf, vf_bytes });
-			}
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-		
-		return( null );
-	}
-	
-	public boolean 
-	isSearchTemplateImportable(
-		SubscriptionImpl	sub )
-	{
-		try{
-			String subs_url_str = ((RSSEngine)sub.getEngine()).getSearchUrl( true );
-			
-			URL subs_url = new URL( subs_url_str );
-			
-			final byte[] vf_bytes = FileUtil.readInputStreamAsByteArray(subs_url.openConnection().getInputStream());
-
-			VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( vf_bytes );
-			
-			return( MetaSearchManagerFactory.getSingleton().isImportable( vf ));
-	
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-		
-		return( false );
-	}
-	
-	public SearchInstance
-	searchSubscriptions(
-		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 ){
-		
-			try{
-				observer.complete();
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}else{
-		
-			new AEThread2( "Subscriptions:search", true )
-			{
-				public void
-				run()
-				{
-					final Set<String>	hashes = new HashSet<String>();
-					
-					searchMatcher	matcher = new searchMatcher( term );
-
-					try{				
-						List<SubscriptionResult>	matches = matchSubscriptionResults( matcher );
-							
-						for ( final SubscriptionResult result: matches ){
-							
-							final Map result_properties = result.toPropertyMap();
-							
-							byte[] hash = (byte[])result_properties.get( SearchResult.PR_HASH );
-														
-							if ( hash != null ){
-															
-								String hash_str = Base32.encode( hash );
-							
-								if ( hashes.contains( hash_str )){
-								
-									continue;
-								}
-							
-								hashes.add( hash_str );
-							}
-							
-							SearchResult search_result = 
-								new SearchResult()
-								{
-									public Object
-									getProperty(
-										int		property_name )
-									{
-										return( result_properties.get( property_name ));
-									}
-								};
-						
-							try{
-								observer.resultReceived( si, search_result );
-								
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-						}
-												
-						Map<String,Object[]> template_matches = new HashMap<String, Object[]>();
-								
-						Engine[] engines = MetaSearchManagerFactory.getSingleton().getMetaSearch().getEngines( false, false );
-						
-						Map<Subscription,List<String>>	sub_dl_name_map = null;
-						
-						for ( Subscription sub: getSubscriptions( false )){
-							
-							if ( !sub.isSearchTemplate()){
-								
-								continue;
-							}
-							
-							String	sub_name = sub.getName(false);
-														
-							Engine sub_engine = sub.getEngine();
-							
-							if ( sub_engine.isActive() || !(sub_engine instanceof RSSEngine )){
-								
-								continue;
-							}
-							
-							int	pos = sub_name.indexOf( ":" );
-							
-							String t_name = sub_name.substring( pos+1 );
-							
-							pos	= t_name.indexOf( "(v" );
-							
-							int t_ver;
-							
-							if ( pos == -1 ){
-								
-								t_ver = 1;
-								
-							}else{
-								
-								String s = t_name.substring( pos+2, t_name.length()-1);
-								
-								t_name = t_name.substring( 0, pos );
-								
-								try{
-							
-									t_ver = Integer.parseInt(s);
-									
-								}catch( Throwable e ){
-									
-									t_ver = 1;
-								}
-							}
-							
-							t_name = t_name.trim();
-							
-							boolean skip = false;
-							
-							for ( Engine e: engines ){
-								
-								if ( e != sub_engine && e.sameLogicAs( sub_engine )){
-									
-									skip = true;
-									
-									break;
-								}
-								
-								if ( e.getName().equalsIgnoreCase( t_name )){
-									
-									if ( e.getVersion() >= t_ver ){
-										
-										skip = true;
-									}
-								}
-							}
-							
-							if ( skip ){
-								
-								continue;
-							}
-							
-							if ( sub_dl_name_map == null ){
-								
-								sub_dl_name_map = new HashMap<Subscription, List<String>>();
-								
-								SubscriptionDownloadDetails[] sdds = SubscriptionUtils.getAllCachedDownloadDetails( azureus_core );
-								
-								for ( SubscriptionDownloadDetails sdd: sdds ){
-									
-									String name = sdd.getDownload().getDisplayName();
-									
-									if ( matcher.matches( name )){
-										
-										Subscription[] x = sdd.getSubscriptions();
-										
-										for ( Subscription s: x ){
-											
-											List<String> g = sub_dl_name_map.get( s );
-											
-											if ( g == null ){
-												
-												g = new ArrayList<String>();
-												
-												sub_dl_name_map.put( s, g );
-											}
-											
-											g.add( name );
-										}
-									}
-								}
-							}
-							
-							List<String> names = sub_dl_name_map.get( sub );
-							
-							if ( names == null ){
-								
-								continue;
-							}
-													
-							String key = t_name.toLowerCase();
-							
-							Object[] entry = template_matches.get( key );
-							
-							if ( entry == null ){
-								
-								entry = new Object[]{ sub, t_ver };
-								
-								template_matches.put( key, entry );
-								
-							}else{
-								
-								if ( t_ver > (Integer)entry[1]){
-									
-									entry[0]	= sub;
-									entry[1]	= t_ver;
-								}
-							}
-						}
-						
-						List<SubscriptionImpl>	interesting = new ArrayList<SubscriptionImpl>();
-						
-						for ( Object[] entry: template_matches.values()){
-						
-							interesting.add((SubscriptionImpl)entry[0]);
-						}
-						
-						Collections.sort(
-							interesting,
-							new Comparator<Subscription>()
-							{
-								public int 
-								compare(
-									Subscription o1,
-									Subscription o2) 
-								{
-									long res = o2.getCachedPopularity() - o1.getCachedPopularity();
-									
-									if ( res < 0 ){
-										return( -1 );
-									}else if ( res > 0 ){
-										return( 1 );
-									}else{
-										return( 0 );
-									}
-								}
-							});
-						
-						int	added = 0;
-						
-						for ( final SubscriptionImpl sub: interesting ){
-								
-							if ( added >= 3 ){
-								
-								break;
-							}
-							
-							try{
-								Object[] vf_entry = getSearchTemplateVuzeFile( sub );
-								
-								if ( vf_entry != null ){
-									
-									final byte[] vf_bytes = (byte[])vf_entry[1];
-									
-									final URL url = 
-										MagnetURIHandler.getSingleton().registerResource(
-											new MagnetURIHandler.ResourceProvider()
-											{
-												public String
-												getUID()
-												{
-													return( SubscriptionManager.class.getName() + ".sid." + sub.getID() );
-												}
-												
-												public String
-												getFileType()
-												{
-													return( "vuze" );
-												}
-														
-												public byte[]
-												getData()
-												{
-													return( vf_bytes );
-												}
-											});
-											
-									SearchResult search_result = 
-										new SearchResult()
-										{
-											public Object
-											getProperty(
-												int		property_name )
-											{
-												if ( property_name == SearchResult.PR_NAME ){
-													
-													return( sub.getName());
-													
-												}else if ( 	property_name == SearchResult.PR_DOWNLOAD_LINK ||
-															property_name == SearchResult.PR_DOWNLOAD_BUTTON_LINK ){
-													
-													return( url.toExternalForm());
-													
-												}else if ( property_name == SearchResult.PR_PUB_DATE ){
-													
-													return( new Date(sub.getAddTime()));
-													
-												}else if ( property_name == SearchResult.PR_SIZE ){
-													
-													return( 1024L );
-													
-												}else if ( 	property_name == SearchResult.PR_SEED_COUNT ||
-															property_name == SearchResult.PR_VOTES ){
-																							
-													return((long)sub.getCachedPopularity());
-													
-												}else if ( property_name == SearchResult.PR_RANK ){
-												
-													return( 100L );
-												}
-												
-												return( null );
-											}
-										};
-							
-									added++;
-										
-									try{
-										observer.resultReceived( si, search_result );
-										
-									}catch( Throwable e ){
-										
-										Debug.out( e );
-									}
-								}
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-						}
-					}catch( Throwable e ){
-						
-						Debug.out( e );
-						
-					}finally{
-						
-						observer.complete();
-					}
-				}
-			}.start();
-		}
-		
-		return( si );
-	}
-	
-	private List<SubscriptionResult>
-	matchSubscriptionResults(
-		searchMatcher	matcher  )
-	{
-		List<SubscriptionResult> result = new ArrayList<SubscriptionResult>();
-				
-		for ( Subscription sub: getSubscriptions( true )){
-			
-			SubscriptionResult[] results = sub.getResults( false );
-			
-			for ( SubscriptionResult r: results ){
-				
-				Map properties = r.toPropertyMap();
-				
-				String name = (String)properties.get( SearchResult.PR_NAME );
-				
-				if ( name == null ){
-					
-					continue;
-				}
-				
-				if ( matcher.matches( name )){
-					
-					result.add( r );
-				}
-			}
-		}
-		
-		return( result );
-	}
-	
-	protected void
-	checkMaxResults(
-		int		max )
-	{
-		Subscription[] subs = getSubscriptions();
-		
-		for (int i=0;i<subs.length;i++){
-			
-			((SubscriptionHistoryImpl)subs[i].getHistory()).checkMaxResults( max );
-		}
-	}
-	
-	public SubscriptionScheduler
-	getScheduler()
-	{
-		return( scheduler );
-	}
-	
-	public boolean
-	isRSSPublishEnabled()
-	{
-		return( COConfigurationManager.getBooleanParameter( CONFIG_RSS_ENABLE, false ));
-	}
-	
-	public void
-	setRSSPublishEnabled(
-		boolean		enabled )
-	{
-		COConfigurationManager.setParameter( CONFIG_RSS_ENABLE, enabled );
-	}
-	
-	public boolean
-	isSearchEnabled()
-	{
-		return( COConfigurationManager.getBooleanParameter( CONFIG_ENABLE_SEARCH, true ));
-	}
-	
-	public void
-	setSearchEnabled(
-		boolean		enabled )
-	{
-		COConfigurationManager.setParameter( CONFIG_ENABLE_SEARCH, enabled );
-	}
-	
-	public boolean
-	hideSearchTemplates()
-	{
-		return( COConfigurationManager.getBooleanParameter( CONFIG_HIDE_SEARCH_TEMPLATES, true ));
-	}
-	
-	public boolean
-	isSubsDownloadEnabled()
-	{
-		return( COConfigurationManager.getBooleanParameter( CONFIG_DL_SUBS_ENABLE, true ));
-	}
-	
-	public void
-	setSubsDownloadEnabled(
-		boolean		enabled )
-	{
-		COConfigurationManager.setParameter( CONFIG_DL_SUBS_ENABLE, enabled );
-	}
-	
-	public String
-	getRSSLink()
-	{
-		return( rss_publisher.getFeedURL());
-	}
-	
-	public Subscription 
-	create(
-		String			name,
-		boolean			public_subs,
-		String			json )
-	
-		throws SubscriptionException 
-	{
-		name = getUniqueName( name );
-		
-		SubscriptionImpl subs = new SubscriptionImpl( this, name, public_subs, null, json, SubscriptionImpl.ADD_TYPE_CREATE );
-		
-		log( "Created new subscription: " + subs.getString());
-		
-		if ( subs.isPublic()){
-			
-			updatePublicSubscription( subs );
-		}
-		
-		return( addSubscription( subs ));
-	}
-	
-	public Subscription
-	createSingletonRSS(
-		String		name,
-		URL			url,
-		int			check_interval_mins )
-		
-		throws SubscriptionException
-	{
-		return( createSingletonRSSSupport( name, url, true, check_interval_mins, SubscriptionImpl.ADD_TYPE_CREATE, true ));
-	}
-	
-	protected SubscriptionImpl
-	lookupSingletonRSS(
-		String		name,
-		URL			url,
-		boolean		is_public,
-		int			check_interval_mins )
-		
-		throws SubscriptionException
-	{
-		checkURL( url );
-		
-		Map	singleton_details = getSingletonMap(name, url, is_public, check_interval_mins);
-		
-		byte[] sid = SubscriptionBodyImpl.deriveSingletonShortID(singleton_details);
-		
-		return( getSubscriptionFromSID( sid ));
-	}
-	
-			
-	protected Subscription
-	createSingletonRSSSupport(
-		String		name,
-		URL			url,
-		boolean		is_public,
-		int			check_interval_mins,
-		int			add_type,
-		boolean		subscribe )
-		
-		throws SubscriptionException
-	{
-		checkURL( url );
-		
-		try{
-			Subscription existing = lookupSingletonRSS( name, url, is_public, check_interval_mins );
-			
-			if ( existing != null ){
-				
-				return( existing );
-			}
-			
-			Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().createRSSEngine( name, url );
-			
-			String	json = SubscriptionImpl.getSkeletonJSON( engine, check_interval_mins );
-			
-			Map	singleton_details = getSingletonMap(name, url, is_public, check_interval_mins);
-			
-			SubscriptionImpl subs = new SubscriptionImpl( this, name, is_public, singleton_details, json, add_type );
-			
-			subs.setSubscribed( subscribe );
-			
-			log( "Created new singleton subscription: " + subs.getString());
-							
-			subs = addSubscription( subs );
-			
-			return( subs );
-			
-		}catch( SubscriptionException e ){
-			
-			throw((SubscriptionException)e);
-			
-		}catch( Throwable e ){
-			
-			throw( new SubscriptionException( "Failed to create subscription", e ));
-		}
-	}
-	
-	protected String
-	getUniqueName(
-		String	name )
-	{
-		for ( int i=0;i<1024;i++){
-			
-			String	test_name = name + (i==0?"":(" (" + i + ")"));
-			
-			if ( getSubscriptionFromName( test_name ) == null ){
-
-				return( test_name );
-			}
-		}
-		
-		return( name );
-	}
-	
-	protected Map
-	getSingletonMap(
-		String		name,
-		URL			url,
-		boolean		is_public,
-		int			check_interval_mins )
-	
-		throws SubscriptionException
-	{
-		try{
-			Map	singleton_details = new HashMap();
-			
-			if ( url.getProtocol().equalsIgnoreCase( "vuze" )){
-				
-					// hack to minimise encoded url length for our own urls
-				
-				singleton_details.put( "key", url.toExternalForm().getBytes( Constants.BYTE_ENCODING ));
-
-			}else{
-				singleton_details.put( "key", url.toExternalForm().getBytes( "UTF-8" ));
-			}
-						
-			String	name2 = name.length() > 64?name.substring(0,64):name;
-			
-			singleton_details.put( "name", name2 );
-			
-			if ( check_interval_mins != SubscriptionHistoryImpl.DEFAULT_CHECK_INTERVAL_MINS ){
-				
-				singleton_details.put( "ci", new Long( check_interval_mins ));
-			}
-			
-			return( singleton_details );
-		
-		}catch( Throwable e ){
-			
-			throw( new SubscriptionException( "Failed to create subscription", e ));
-		}
-	}
-	
-	protected SubscriptionImpl
-	createSingletonSubscription(
-		Map			singleton_details,
-		int			add_type,
-		boolean		subscribe )
-	
-		throws SubscriptionException 
-	{
-		try{
-			String name = ImportExportUtils.importString( singleton_details, "name", "(Anonymous)" );
-			
-			URL	url = new URL( ImportExportUtils.importString( singleton_details, "key" ));
-			
-			int	check_interval_mins = (int)ImportExportUtils.importLong( singleton_details, "ci", SubscriptionHistoryImpl.DEFAULT_CHECK_INTERVAL_MINS );
-			
-				// only defined type is singleton rss
-			
-			SubscriptionImpl s = (SubscriptionImpl)createSingletonRSSSupport( name, url, true, check_interval_mins, add_type, subscribe );
-			
-			return( s );
-			
-		}catch( Throwable e ){
-			
-			log( "Creation of singleton from " + singleton_details + " failed", e );
-			
-			throw( new SubscriptionException( "Creation of singleton from " + singleton_details + " failed", e ));
-		}
-	}
-	
-	public Subscription 
-	createRSS(
-		String		name,
-		URL			url,
-		int			check_interval_mins,
-		Map			user_data )
-	
-		throws SubscriptionException 
-	{
-		checkURL( url );
-		
-		try{
-			name = getUniqueName(name);
-		
-			Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().createRSSEngine( name, url );
-			
-			String	json = SubscriptionImpl.getSkeletonJSON( engine, check_interval_mins );
-			
-				// engine name may have been modified so re-read it for subscription default
-			
-			SubscriptionImpl subs = new SubscriptionImpl( this, engine.getName(), engine.isPublic(), null, json, SubscriptionImpl.ADD_TYPE_CREATE );
-			
-			if ( user_data != null ){
-				
-				Iterator it = user_data.entrySet().iterator();
-				
-				while( it.hasNext()){
-					
-					Map.Entry entry = (Map.Entry)it.next();
-					
-					subs.setUserData( entry.getKey(), entry.getValue());
-				}
-			}
-			
-			log( "Created new subscription: " + subs.getString());
-					
-			subs = addSubscription( subs );
-			
-			if ( subs.isPublic()){
-			
-				updatePublicSubscription( subs );
-			}
-			
-			return( subs );
-			
-		}catch( Throwable e ){
-			
-			throw( new SubscriptionException( "Failed to create subscription", e ));
-		}
-	}
-
-	protected void
-	checkURL(
-		URL		url )
-	
-		throws SubscriptionException
-	{
-		if ( url.getHost().trim().length() == 0 ){
-			
-			String protocol = url.getProtocol().toLowerCase();
-			
-			if ( ! ( protocol.equals( "azplug" ) || protocol.equals( "file" ) || protocol.equals( "vuze" ))){
-			
-				throw( new SubscriptionException( "Invalid URL '" + url + "'" ));
-			}
-		}
-	}
-	
-	protected SubscriptionImpl
-	addSubscription(
-		SubscriptionImpl		subs )
-	{
-		SubscriptionImpl existing;
-		
-		synchronized( this ){
-
-			int index = Collections.binarySearch(subscriptions, subs, new Comparator<Subscription>() {
-				public int compare(Subscription arg0, Subscription arg1) {
-					return arg0.getID().compareTo(arg1.getID());
-				}
-			});
-			if (index < 0) {
-				existing = null;
-				index = -1 * index - 1; // best guess
-
-				subscriptions.add( index, subs );
-			
-				saveConfig();
-			} else {
-				existing = (SubscriptionImpl) subscriptions.get(index);
-			}
-		}
-		
-		if ( existing != null ){
-			
-			log( "Attempted to add subscription when already present: " + subs.getString());
-			
-			subs.destroy();
-			
-			return( existing );
-		}
-		
-		if ( subs.isMine()){
-			
-			addMetaSearchListener();
-		}
-		
-		if ( subs.getCachedPopularity() == -1 ){
-			
-			try{
-				subs.getPopularity(
-					new SubscriptionPopularityListener()
-					{
-						public void
-						gotPopularity(
-							long						popularity )
-						{
-						}
-						
-						public void
-						failed(
-							SubscriptionException		error )
-						{
-						}
-					});
-				
-			}catch( Throwable e ){
-				
-				log( "", e );
-			}
-		}
-		
-		Iterator it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				((SubscriptionManagerListener)it.next()).subscriptionAdded( subs );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-		
-		if ( subs.isSubscribed() && subs.isPublic()){
-			
-			setSelected( subs );
-		}
-		
-		if ( dht_plugin != null ){
-				
-			new AEThread2( "Publish check", true )
-			{
-				public void
-				run()
-				{
-					publishSubscriptions();
-				}
-			}.start();
-		}
-		
-		return( subs );
-	}
-	
-	protected void
-	addMetaSearchListener()
-	{
-		synchronized( this ){
-			
-			if ( meta_search_listener_added ){
-				
-				return;
-			}
-			
-			meta_search_listener_added = true;
-		}
-		
-		MetaSearchManagerFactory.getSingleton().getMetaSearch().addListener(
-			new MetaSearchListener()
-			{
-				public void
-				engineAdded(
-					Engine		engine )
-				{
-					
-				}
-				
-				public void
-				engineUpdated(
-					Engine		engine )
-				{
-					synchronized( SubscriptionManagerImpl.this ){
-						
-						for (int i=0;i<subscriptions.size();i++){
-							
-							SubscriptionImpl	subs = (SubscriptionImpl)subscriptions.get(i);
-							
-							if ( subs.isMine()){
-								
-								subs.engineUpdated( engine );
-							}
-						}
-					}
-				}
-				
-				public void
-				engineRemoved(
-					Engine		engine )
-				{
-					
-				}
-			});
-	}
-	
-	protected void
-	changeSubscription(
-		SubscriptionImpl		subs )
-	{
-		if ( !subs.isRemoved()){
-			
-			Iterator it = listeners.iterator();
-			
-			while( it.hasNext()){
-				
-				try{
-					((SubscriptionManagerListener)it.next()).subscriptionChanged( subs );
-					
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-		}
-	}
-	
-	protected void
-	selectSubscription(
-		SubscriptionImpl		subs )
-	{
-		if ( !subs.isRemoved()){
-
-			Iterator it = listeners.iterator();
-			
-			while( it.hasNext()){
-				
-				try{
-					((SubscriptionManagerListener)it.next()).subscriptionSelected( subs );
-					
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-		}
-	}
-	
-	protected void
-	removeSubscription(
-		SubscriptionImpl		subs )
-	{
-		synchronized( this ){
-			
-			if ( subscriptions.remove( subs )){
-			
-				saveConfig();
-				
-			}else{
-			
-				return;
-			}
-		}
-		
-		try{
-			Engine engine = subs.getEngine( true );
-			
-			if ( engine.getType() == Engine.ENGINE_TYPE_RSS ){
-				
-				engine.delete();
-				
-				log( "Removed engine " + engine.getName() + " due to subscription removal" );
-			}
-			
-		}catch( Throwable e ){
-			
-			log( "Failed to check for engine deletion", e );
-		}
-		
-		Iterator<SubscriptionManagerListener> it = listeners.iterator();
-		
-		while( it.hasNext()){
-			
-			try{
-				it.next().subscriptionRemoved( subs );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-		
-		try{
-			FileUtil.deleteResilientFile( getResultsFile( subs ));
-			
-			File vuze_file = getVuzeFile( subs );
-			
-			vuze_file.delete();
-			
-			new File( vuze_file.getParent(), vuze_file.getName() + ".bak" ).delete();
-			
-		}catch( Throwable e ){
-			
-			log( "Failed to delete results/vuze file", e );
-		}
-	}
-	
-	protected void
-	updatePublicSubscription(
-		SubscriptionImpl		subs )
-	{		
-		if ( subs.isSingleton()){
-			
-				// never update singletons
-			
-			subs.setServerPublished();
-			
-		}else{
-			
-			Long	l_last_pub 	= (Long)subs.getUserData( SP_LAST_ATTEMPTED );
-			Long	l_consec_fail = (Long)subs.getUserData( SP_CONSEC_FAIL );
-			
-			if ( l_last_pub != null && l_consec_fail != null ){
-				
-				long	delay = SERVER_PUB_CHECK_PERIOD;
-				
-				for (int i=0;i<l_consec_fail.longValue();i++){
-					
-					delay <<= 1;
-					
-					if ( delay > 24*60*60*1000 ){
-						
-						break;
-					}
-				}
-				
-				if ( l_last_pub.longValue() + delay > SystemTime.getMonotonousTime()){
-					
-					return;
-				}
-			}
-			
-			try{		
-				File vf = getVuzeFile( subs );
-	
-				byte[] bytes = FileUtil.readFileAsByteArray( vf );
-				
-				byte[]	encoded_subs = Base64.encode( bytes );
-	
-				PlatformSubscriptionsMessenger.updateSubscription(
-						!subs.getServerPublished(),
-						subs.getName(false),
-						subs.getPublicKey(),
-						subs.getPrivateKey(),
-						subs.getShortID(),
-						subs.getVersion(),
-						new String( encoded_subs ));
-				
-				subs.setUserData( SP_LAST_ATTEMPTED, null );
-				subs.setUserData( SP_CONSEC_FAIL, null );
-
-				subs.setServerPublished();
-				
-				log( "    Updated public subscription " + subs.getString());
-				
-			}catch( Throwable e ){
-				
-				log( "    Failed to update public subscription " + subs.getString(), e );
-				
-				subs.setUserData( SP_LAST_ATTEMPTED, new Long( SystemTime.getMonotonousTime()));
-				
-				subs.setUserData( SP_CONSEC_FAIL, new Long( l_consec_fail==null?1:(l_consec_fail.longValue()+1)));
-
-				subs.setServerPublicationOutstanding();
-			}
-		}
-	}
-	
-	protected void
-	checkSingletonPublish(
-		SubscriptionImpl		subs )
-	
-		throws SubscriptionException
-	{
-		if ( subs.getSingletonPublishAttempted()){
-			
-			throw( new SubscriptionException( "Singleton publish already attempted" ));
-		}
-		
-		subs.setSingletonPublishAttempted();
-		
-		try{
-			File vf = getVuzeFile( subs );
-	
-			byte[] bytes = FileUtil.readFileAsByteArray( vf );
-			
-			byte[]	encoded_subs = Base64.encode( bytes );
-			
-				// use a transient key-pair as we won't have the private key in general
-			
-			KeyPair	kp = CryptoECCUtils.createKeys();
-			
-			byte[] public_key 		= CryptoECCUtils.keyToRawdata( kp.getPublic());
-			byte[] private_key 		= CryptoECCUtils.keyToRawdata( kp.getPrivate());
-	
-			PlatformSubscriptionsMessenger.updateSubscription(
-					true,
-					subs.getName(false),
-					public_key,
-					private_key,
-					subs.getShortID(),
-					1,
-					new String( encoded_subs ));
-			
-			log( "    created singleton public subscription " + subs.getString());
-			
-		}catch( Throwable e ){
-			
-			throw( new SubscriptionException( "Failed to publish singleton", e ));
-		}
-	}
-	
-	protected void
-	checkServerPublications(
-		List		subs )
-	{
-		for (int i=0;i<subs.size();i++){
-			
-			SubscriptionImpl	sub = (SubscriptionImpl)subs.get(i);
-			
-			if ( sub.getServerPublicationOutstanding()){
-				
-				updatePublicSubscription( sub );
-			}
-		}
-	}
-	
-	protected void
-	checkStuff(
-		int		ticks )
-	{
-		long now = SystemTime.getCurrentTime();
-		
-		List<SubscriptionImpl> subs;
-		
-		synchronized( this ){
-			
-			subs = new ArrayList<SubscriptionImpl>( subscriptions );
-		}
-		
-		SubscriptionImpl	expired_subs = null;
-		
-		for (int i=0;i<subs.size();i++){
-			
-			SubscriptionImpl sub = subs.get( i );
-			
-			if ( !( sub.isMine() || sub.isSubscribed())){
-				
-				long	age = now - sub.getAddTime();
-				
-				if ( age > DELETE_UNUSED_AFTER_MILLIS ){
-					
-					if ( 	expired_subs == null || 
-							( sub.getAddTime() < expired_subs.getAddTime())){
-						
-						expired_subs = sub;
-					}
-					
-					continue;
-				}
-			}
-			
-			
-			sub.checkPublish();
-		}
-		
-		if ( expired_subs != null ){
-			
-			log( "Removing unsubscribed subscription '" + expired_subs.getName() + "' as expired" );
-					
-			expired_subs.remove();
-		}
-		
-		if ( ticks % ASSOC_CHECK_TICKS == 0 ){
-			
-			lookupAssociations( false );
-		}
-		
-		if ( ticks % SERVER_PUB_CHECK_TICKS == 0 ){
-			
-			checkServerPublications( subs );
-		}
-		
-		if ( ticks % TIDY_POT_ASSOC_TICKS == 0 ){
-			
-			tidyPotentialAssociations();
-		}
-		
-		if ( 	ticks == SET_SELECTED_FIRST_TICK ||
-				ticks % SET_SELECTED_TICKS == 0 ){
-			
-			setSelected( subs );
-		}
-	}
-	
-	public Subscription
-	importSubscription(
-		int			type,
-		Map			map,
-		boolean		warn_user )
-	
-		throws SubscriptionException
-	{
-		boolean	log_errors = true;
-		
-		try{
-			try{
-				if ( type == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION_SINGLETON ){
-					
-					String	name = new String((byte[])map.get( "name" ), "UTF-8" );
-					
-					URL	url = new URL( new String((byte[])map.get( "url" ), "UTF-8" ));
-					
-					Long	l_interval = (Long)map.get( "check_interval_mins" );
-					
-					int	check_interval_mins = l_interval==null?SubscriptionHistoryImpl.DEFAULT_CHECK_INTERVAL_MINS:l_interval.intValue();
-					
-					Long	l_public = (Long)map.get( "public" );
-					
-					boolean is_public = l_public==null?true:l_public.longValue()==1;
-					
-					SubscriptionImpl existing = lookupSingletonRSS(name, url, is_public, check_interval_mins );
-					
-					if ( UrlFilter.getInstance().urlCanRPC( url.toExternalForm())){
-						
-						warn_user = false;
-					}
-					
-					if ( existing != null && existing.isSubscribed()){
-						
-						if ( warn_user ){
-							
-							UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-							
-							String details = MessageText.getString(
-									"subscript.add.dup.desc",
-									new String[]{ existing.getName()});
-							
-							ui_manager.showMessageBox(
-									"subscript.add.dup.title",
-									"!" + details + "!",
-									UIManagerEvent.MT_OK );
-						}
-						
-						selectSubscription( existing );
-						
-						return( existing );
-						
-					}else{
-						
-						if ( warn_user ){
-							
-							UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-				
-							String details = MessageText.getString(
-									"subscript.add.desc",
-									new String[]{ name });
-							
-							long res = ui_manager.showMessageBox(
-									"subscript.add.title",
-									"!" + details + "!",
-									UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
-							
-							if ( res != UIManagerEvent.MT_YES ){	
-							
-								log_errors = false;
-								
-								throw( new SubscriptionException( "User declined addition" ));
-							}
-						}
-						
-						if ( existing == null ){
-					
-							SubscriptionImpl new_subs = (SubscriptionImpl)createSingletonRSSSupport( name, url, is_public, check_interval_mins, SubscriptionImpl.ADD_TYPE_IMPORT, true );
-																	
-							log( "Imported new singleton subscription: " + new_subs.getString());
-									
-							return( new_subs );
-							
-						}else{
-							
-							existing.setSubscribed( true );
-							
-							selectSubscription( existing );
-							
-							return( existing );
-						}
-					}
-				}else{
-					
-					SubscriptionBodyImpl body = new SubscriptionBodyImpl( this, map );
-							
-					SubscriptionImpl existing = getSubscriptionFromSID( body.getShortID());
-					
-					if ( existing != null && existing.isSubscribed()){
-					
-						if ( existing.getVersion() >= body.getVersion()){
-							
-							log( "Not upgrading subscription: " + existing.getString() + " as supplied (" +  body.getVersion() + ") is not more recent than existing (" + existing.getVersion() + ")");
-							
-							if ( warn_user ){
-								
-								UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-								
-								String details = MessageText.getString(
-										"subscript.add.dup.desc",
-										new String[]{ existing.getName()});
-								
-								ui_manager.showMessageBox(
-										"subscript.add.dup.title",
-										"!" + details + "!",
-										UIManagerEvent.MT_OK );
-							}
-								// we have a newer one, ignore
-							
-							selectSubscription( existing );
-							
-							return( existing );
-							
-						}else{
-							
-							if ( warn_user ){
-								
-								UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-				
-								String details = MessageText.getString(
-										"subscript.add.upgrade.desc",
-										new String[]{ existing.getName()});
-								
-								long res = ui_manager.showMessageBox(
-										"subscript.add.upgrade.title",
-										"!" + details + "!",
-										UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
-								
-								if ( res != UIManagerEvent.MT_YES ){	
-								
-									throw( new SubscriptionException( "User declined upgrade" ));
-								}
-							}
-							
-							log( "Upgrading subscription: " + existing.getString());
-			
-							existing.upgrade( body );
-							
-							saveConfig();
-							
-							subscriptionUpdated();
-							
-							return( existing );
-						}
-					}else{
-						
-						SubscriptionImpl new_subs = null;
-						
-						String	subs_name;
-						
-						if ( existing == null ){
-							
-							new_subs = new SubscriptionImpl( this, body, SubscriptionImpl.ADD_TYPE_IMPORT, true );
-							
-							subs_name = new_subs.getName();
-							
-						}else{
-							
-							subs_name = existing.getName();
-						}
-						
-						if ( warn_user ){
-							
-							UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-				
-							String details = MessageText.getString(
-									"subscript.add.desc",
-									new String[]{ subs_name });
-							
-							long res = ui_manager.showMessageBox(
-									"subscript.add.title",
-									"!" + details + "!",
-									UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
-							
-							if ( res != UIManagerEvent.MT_YES ){	
-							
-								throw( new SubscriptionException( "User declined addition" ));
-							}
-						}
-						
-						if ( new_subs == null ){
-							
-							existing.setSubscribed( true );
-							
-							selectSubscription( existing );
-							
-							return( existing );
-							
-						}else{
-							
-							log( "Imported new subscription: " + new_subs.getString());
-						
-							new_subs = addSubscription( new_subs );
-						
-							return( new_subs );
-						}
-					}
-				}
-			}catch( Throwable e ){
-				
-				throw( new SubscriptionException( "Subscription import failed", e ));
-			}
-		}catch( SubscriptionException e ){
-			
-			if ( warn_user && log_errors ){
-				
-				UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-				
-				String details = MessageText.getString(
-						"subscript.import.fail.desc",
-						new String[]{ Debug.getNestedExceptionMessage(e)});
-				
-				ui_manager.showMessageBox(
-						"subscript.import.fail.title",
-						"!" + details + "!",
-						UIManagerEvent.MT_OK );
-			}
-			
-			throw( e );
-		}
-	}
-	
-	public Subscription[]
-	getSubscriptions()
-	{
-		synchronized( this ){
-			
-			return((SubscriptionImpl[])subscriptions.toArray( new SubscriptionImpl[subscriptions.size()]));
-		}
-	}
-	
-	public Subscription[]
-	getSubscriptions(
-		boolean	subscribed_only )
-	{
-		if ( !subscribed_only ){
-			
-			return( getSubscriptions());
-		}
-		
-		List	result = new ArrayList();
-				
-		synchronized( this ){
-			
-			for (int i=0;i<subscriptions.size();i++){
-				
-				SubscriptionImpl subs = (SubscriptionImpl)subscriptions.get(i);
-				
-				if ( subs.isSubscribed()){
-					
-					result.add( subs );
-				}
-			}
-		}
-		
-		return((SubscriptionImpl[])result.toArray( new SubscriptionImpl[result.size()]));
-	}
-	
-	public int
-	getSubscriptionCount(
-		boolean	subscribed_only )
-	{
-		if ( subscribed_only ){
-	
-			int total = 0;
-			
-			synchronized( this ){
-				
-				for ( Subscription subs: subscriptions ){
-					
-					if ( subs.isSubscribed()){
-						
-						total++;
-					}
-				}
-			}
-			
-			return( total );
-			
-		}else{
-			
-			synchronized( this ){
-				
-				return( subscriptions.size());
-			}
-		}
-	}
-
-	protected SubscriptionImpl
-	getSubscriptionFromName(
-		String		name )
-	{
-		synchronized( this ){
-			
-			for (int i=0;i<subscriptions.size();i++){
-				
-				SubscriptionImpl s = (SubscriptionImpl)subscriptions.get(i);
-				
-				if ( s.getName().equalsIgnoreCase( name )){
-					
-					return( s );
-				}
-			}
-		}
-		
-		return( null );
-	}
-	
-	public Subscription
-	getSubscriptionByID(
-		String		id )
-	{
-		synchronized( this ){
-			
-  		int index = Collections.binarySearch(subscriptions, id, new Comparator() {
-  			public int compare(Object o1, Object o2) {
-  				String id1 = (o1 instanceof Subscription) ? ((Subscription) o1).getID() : o1.toString();
-  				String id2 = (o2 instanceof Subscription) ? ((Subscription) o2).getID() : o2.toString();
-  				return id1.compareTo(id2);
-  			}
-  		});
-  		
-  		if (index >= 0) {
-  			return subscriptions.get(index);
-  		}
-		}
-		
-		return null;
-	}
-	
-	protected SubscriptionImpl
-	getSubscriptionFromSID(
-		byte[]		sid )
-	{
-		return (SubscriptionImpl) getSubscriptionByID( Base32.encode(sid));
-	}
-	
-	protected File
-	getSubsDir()
-	
-		throws IOException
-	{
-		File dir = new File(SystemProperties.getUserPath());
-
-		dir = new File( dir, "subs" );
- 		
- 		if ( !dir.exists()){
- 			
- 			if ( !dir.mkdirs()){
- 				
- 				throw( new IOException( "Failed to create '" + dir + "'" ));
- 			}
- 		}	
- 		
- 		return( dir );
-	}
-	
-	protected File
-	getVuzeFile(
-		SubscriptionImpl 		subs )
-	
-		throws IOException
-	{
- 		File dir = getSubsDir();
- 		
- 		return( new File( dir, ByteFormatter.encodeString( subs.getShortID()) + ".vuze" ));
-	}
-	
-	protected File
-	getResultsFile(
-		SubscriptionImpl 		subs )
-	
-		throws IOException
-	{
- 		File dir = getSubsDir();
- 		
- 		return( new File( dir, ByteFormatter.encodeString( subs.getShortID()) + ".results" ));
-	}
-	
-	public int
-	getKnownSubscriptionCount()
-	{
-		PluginInterface pi = PluginInitializer.getDefaultInterface();
-
-		Download[] downloads = pi.getDownloadManager().getDownloads();
-
-		ByteArrayHashMap<String> results = new ByteArrayHashMap<String>(Math.max( 16, downloads.length * 2 ));
-		
-		try{			
-			for ( Download download: downloads ){
-				
-				Map	m = download.getMapAttribute( ta_subscription_info );
-				
-				if ( m != null ){
-					
-					List s = (List)m.get("s");
-					
-					if ( s != null && s.size() > 0 ){
-												
-						for (int i=0;i<s.size();i++){
-							
-							byte[]	sid = (byte[])s.get(i);
-							
-							results.put( sid, "" );
-						}
-					}
-				}
-			}
-		}catch( Throwable e ){
-			
-			log( "Failed to get known subscriptions", e );
-		}
-		
-		return( results.size());
-	}
-	
-	public Subscription[]
-	getKnownSubscriptions(
-		byte[]						hash )
-	{
-		PluginInterface pi = PluginInitializer.getDefaultInterface();
-
-		try{
-			Download download = pi.getDownloadManager().getDownload( hash );
-			
-			if ( download != null ){
-				
-				Map	m = download.getMapAttribute( ta_subscription_info );
-				
-				if ( m != null ){
-					
-					List s = (List)m.get("s");
-					
-					if ( s != null && s.size() > 0 ){
-						
-						List	result = new ArrayList( s.size());
-						
-						boolean hide_search = hideSearchTemplates();
-						
-						for (int i=0;i<s.size();i++){
-							
-							byte[]	sid = (byte[])s.get(i);
-							
-							SubscriptionImpl subs = getSubscriptionFromSID(sid);
-							
-							if ( subs != null ){
-								
-								if ( isVisible( subs )){
-								
-									if ( hide_search && subs.isSearchTemplate()){
-									
-									}else{
-										
-										result.add( subs );
-									}
-								}
-							}
-						}
-						
-						return((Subscription[])result.toArray( new Subscription[result.size()]));
-					}
-				}
-			}
-		}catch( Throwable e ){
-			
-			log( "Failed to get known subscriptions", e );
-		}
-		
-		return( new Subscription[0] );
-	}
-	
-	protected boolean
-	subscriptionExists(
-		Download			download,
-		SubscriptionImpl	subs )
-	{
-		byte[]	sid = subs.getShortID();
-	
-		Map	m = download.getMapAttribute( ta_subscription_info );
-		
-		if ( m != null ){
-			
-			List s = (List)m.get("s");
-			
-			if ( s != null && s.size() > 0 ){
-								
-				for (int i=0;i<s.size();i++){
-					
-					byte[]	x = (byte[])s.get(i);
-					
-					if ( Arrays.equals( x, sid )){
-						
-						return( true );
-					}
-				}
-			}
-		}
-		
-		return( false );
-	}
-	
-	protected boolean
-	isVisible(
-		SubscriptionImpl		subs )
-	{
-			// to avoid development links polluting production we filter out such subscriptions
-		
-		if ( Constants.isCVSVersion() || subs.isSubscribed()){
-			
-			return( true );
-		}
-		
-		try{
-			Engine engine = subs.getEngine( true );
-			
-			if ( engine instanceof WebEngine ){
-				
-				String url = ((WebEngine)engine).getSearchUrl();
-				
-				try{
-					String host = new URL( url ).getHost();
-					
-					return( !exclusion_pattern.matcher( host ).matches());
-					
-				}catch( Throwable e ){
-				}
-			}
-			
-			return( true );
-			
-		}catch( Throwable e ){
-			
-			log( "isVisible failed for " + subs.getString(), e );
-			
-			return( false );
-		}
-	}
-		
-	public Subscription[]
-	getLinkedSubscriptions(
-		byte[]						hash )
-	{
-		PluginInterface pi = PluginInitializer.getDefaultInterface();
-
-		try{
-			Download download = pi.getDownloadManager().getDownload( hash );
-			
-			if ( download != null ){
-				
-				Map	m = download.getMapAttribute( ta_subscription_info );
-				
-				if ( m != null ){
-					
-					List s = (List)m.get("s");
-					
-					if ( s != null && s.size() > 0 ){
-						
-						List	result = new ArrayList( s.size());
-						
-						for (int i=0;i<s.size();i++){
-							
-							byte[]	sid = (byte[])s.get(i);
-							
-							SubscriptionImpl subs = getSubscriptionFromSID(sid);
-							
-							if ( subs != null ){
-								
-								if ( subs.hasAssociation( hash )){
-								
-									result.add( subs );
-								}
-							}
-						}
-						
-						return((Subscription[])result.toArray( new Subscription[result.size()]));
-					}
-				}
-			}
-		}catch( Throwable e ){
-			
-			log( "Failed to get known subscriptions", e );
-		}
-		
-		return( new Subscription[0] );
-	}
-	
-	protected void
-	lookupAssociations(
-		boolean		high_priority )
-	{
-		synchronized( this ){
-			
-			if ( periodic_lookup_in_progress ){
-				
-				if ( high_priority ){
-				
-					priority_lookup_pending++;
-				}
-				
-				return;
-			}
-			
-			periodic_lookup_in_progress  = true;
-		}
-		
-		try{
-			PluginInterface pi = PluginInitializer.getDefaultInterface();
-			
-			Download[] downloads = pi.getDownloadManager().getDownloads();
-					
-			long	now = SystemTime.getCurrentTime();
-			
-			long		newest_time		= 0;
-			Download	newest_download	= null;
-			
-			
-			for( int i=0;i<downloads.length;i++){
-				
-				Download	download = downloads[i];
-				
-				if ( download.getTorrent() == null || !download.isPersistent()){
-					
-					continue;
-				}
-				
-				Map	map = download.getMapAttribute( ta_subscription_info );
-				
-				if ( map == null ){
-					
-					map = new LightHashMap();
-					
-				}else{
-					
-					map = new LightHashMap( map );
-				}	
-				
-				Long	l_last_check = (Long)map.get( "lc" );
-				
-				long	last_check = l_last_check==null?0:l_last_check.longValue();
-				
-				if ( last_check > now ){
-					
-					last_check = now;
-					
-					map.put( "lc", new Long( last_check ));
-					
-					download.setMapAttribute( ta_subscription_info, map );
-				}
-				
-				List	subs = (List)map.get( "s" );
-				
-				int	sub_count = subs==null?0:subs.size();
-				
-				if ( sub_count > 8 ){
-					
-					continue;
-				}
-				
-				long	create_time = download.getCreationTime();
-				
-				int	time_between_checks = (sub_count + 1) * 24*60*60*1000 + (int)(create_time%4*60*60*1000);
-				
-				if ( now - last_check >= time_between_checks ){
-					
-					if ( create_time > newest_time ){
-						
-						newest_time		= create_time;
-						newest_download	= download;
-					}
-				}
-			}
-			
-			if ( newest_download != null ){
-			
-				byte[] hash = newest_download.getTorrent().getHash();
-				
-				log( "Association lookup starts for " + newest_download.getName() + "/" + ByteFormatter.encodeString( hash ));
-
-				lookupAssociationsSupport( 
-					hash,
-					new	SubscriptionLookupListener()
-					{
-						public void
-						found(
-							byte[]					hash,
-							Subscription			subscription )
-						{							
-						}
-						
-						public void
-						failed(
-							byte[]					hash,
-							SubscriptionException	error )
-						{
-							log( "Association lookup failed for " + ByteFormatter.encodeString( hash ), error );
-
-							associationLookupComplete();
-						}
-						
-						public void 
-						complete(
-							byte[] 			hash,
-							Subscription[]	subs )
-						{
-							log( "Association lookup complete for " + ByteFormatter.encodeString( hash ));
-							
-							associationLookupComplete();
-						}
-					});
-						
-			}else{
-				
-				associationLookupComplete();
-			}
-		}catch( Throwable e ){
-			
-			log( "Association lookup check failed", e );
-
-			associationLookupComplete();			
-		}
-	}
-	
-	protected void
-	associationLookupComplete()
-	{
-		boolean	recheck;
-		
-		synchronized( this ){
-			
-			periodic_lookup_in_progress = false;
-			
-			recheck = priority_lookup_pending > 0;
-				
-			if ( recheck ){
-				
-				priority_lookup_pending--;
-			}
-		}
-		
-		if ( recheck ){
-			
-			new AEThread2( "SM:priAssLookup", true )
-			{
-				public void run() 
-				{
-					lookupAssociations( false );
-				}
-			}.start();
-		}
-	}
-	
-	protected void
-	setSelected(
-		List		subs )
-	{
-		List	sids 		= new ArrayList();
-		List	used_subs	= new ArrayList();
-		
-		for (int i=0;i<subs.size();i++){
-			
-			SubscriptionImpl	sub = (SubscriptionImpl)subs.get(i);
-			
-			if ( sub.isSubscribed()){
-				
-				if ( sub.isPublic()){
-				
-					used_subs.add( sub );
-				
-					sids.add( sub.getShortID());
-					
-				}else{
-					
-					checkInitialDownload( sub );
-				}
-			}
-		}
-		
-		if ( sids.size() > 0 ){
-			
-			try{
-				List[] result = PlatformSubscriptionsMessenger.setSelected( sids );
-				
-				List	versions 		= result[0];
-				List	popularities	= result[1];
-				
-				log( "Popularity update: updated " + sids.size());
-				
-				final List dht_pops = new ArrayList();
-				
-				for (int i=0;i<sids.size();i++){
-					
-					SubscriptionImpl sub = (SubscriptionImpl)used_subs.get(i);
-					
-					int	latest_version = ((Long)versions.get(i)).intValue();
-					
-					if ( latest_version > sub.getVersion()){
-						
-						updateSubscription( sub, latest_version );
-						
-					}else{
-						
-						checkInitialDownload( sub );
-					}
-					
-					if ( latest_version > 0 ){
-						
-						try{
-							long	pop = ((Long)popularities.get(i)).longValue();
-							
-							if ( pop >= 0 && pop != sub.getCachedPopularity()){
-								
-								sub.setCachedPopularity( pop );
-							}
-						}catch( Throwable e ){
-							
-							log( "Popularity update: Failed to extract popularity", e );
-						}
-					}else{
-						
-						dht_pops.add( sub );
-					}
-				}
-				
-				if ( dht_pops.size() <= 3 ){
-					
-					for (int i=0;i<dht_pops.size();i++){
-							
-						updatePopularityFromDHT((SubscriptionImpl)dht_pops.get(i), false );
-					}
-				}else{
-					
-					new AEThread2( "SM:asyncPop", true )
-					{
-						public void
-						run()
-						{
-							for (int i=0;i<dht_pops.size();i++){
-								
-								updatePopularityFromDHT((SubscriptionImpl)dht_pops.get(i), true );
-							}
-						}
-					}.start();
-				}
-			}catch( Throwable e ){
-				
-				log( "Popularity update: Failed to record selected subscriptions", e );
-			}
-		}else{
-			
-			log( "Popularity update: No selected, public subscriptions" );
-		}
-	}
-	
-	protected void
-	checkUpgrade(
-		SubscriptionImpl		sub )
-	{
-		setSelected( sub );
-	}
-	
-	protected void
-	setSelected(
-		final SubscriptionImpl	sub )
-	{
-		if ( sub.isSubscribed()){
-			
-			if ( sub.isPublic()){
-			
-				new DelayedEvent( 
-					"SM:setSelected",
-					0,
-					new AERunnable()
-					{
-						public void
-						runSupport()
-						{
-							try{
-								List	sids = new ArrayList();
-								
-								sids.add( sub.getShortID());
-							
-								List[] result = PlatformSubscriptionsMessenger.setSelected( sids );
-								
-								log( "setSelected: " + sub.getName());
-								
-								int	latest_version = ((Long)result[0].get(0)).intValue();
-								
-								if ( latest_version == 0 ){
-									
-									if ( sub.isSingleton()){
-									
-										checkSingletonPublish( sub );
-									}
-								}else if ( latest_version > sub.getVersion()){
-									
-									updateSubscription( sub, latest_version );
-									
-								}else{
-									
-									checkInitialDownload( sub );
-								}
-								
-								if ( latest_version > 0 ){
-									
-									try{
-										long	pop = ((Long)result[1].get(0)).longValue();
-										
-										if ( pop >= 0 && pop != sub.getCachedPopularity()){
-											
-											sub.setCachedPopularity( pop );
-										}
-									}catch( Throwable e ){
-										
-										log( "Popularity update: Failed to extract popularity", e );
-									}
-								}else{
-									
-									updatePopularityFromDHT( sub, true );
-								}
-							}catch( Throwable e ){
-								
-								log( "setSelected: failed for " + sub.getName(), e );
-							}
-						}
-					});
-			}else{
-				
-				checkInitialDownload( sub );
-			}
-		}
-	}
-	
-	protected void
-	checkInitialDownload(
-		SubscriptionImpl		subs )
-	{
-		if ( subs.getHistory().getLastScanTime() == 0 ){
-			
-			scheduler.download( 
-				subs, 
-				true,
-				new SubscriptionDownloadListener()
-				{
-					public void
-					complete(
-						Subscription		subs )
-					{
-						log( "Initial download of " + subs.getName() + " complete" );
-					}
-					
-					public void
-					failed(
-						Subscription			subs,
-						SubscriptionException	error )
-					{
-						log( "Initial download of " + subs.getName() + " failed", error );
-					}
-				});
-		}
-	}
-	
-	public SubscriptionAssociationLookup
-	lookupAssociations(
-		final byte[] 							hash,
-		final SubscriptionLookupListener		listener )
-	
-		throws SubscriptionException
-	{
-		if ( dht_plugin != null && !dht_plugin.isInitialising()){
-			
-			return( lookupAssociationsSupport( hash, listener ));
-		}
-		
-		final boolean[]	cancelled = { false };
-		
-		final SubscriptionAssociationLookup[]	actual_res = { null };
-		
-		final SubscriptionAssociationLookup res = 
-			new SubscriptionAssociationLookup()
-			{
-				public void 
-				cancel() 
-				{
-					log( "    Association lookup cancelled" );
-	
-					synchronized( actual_res ){
-						
-						cancelled[0] = true;
-						
-						if ( actual_res[0] != null ){
-							
-							actual_res[0].cancel();
-						}
-					}
-				}
-			};
-			
-		new AEThread2( "SM:initwait", true )
-		{
-			public void
-			run()
-			{
-				try{
-					SubscriptionAssociationLookup x = lookupAssociationsSupport( hash, listener );
-					
-					synchronized( actual_res ){
-
-						actual_res[0] = x;
-						
-						if ( cancelled[0] ){
-							
-							x.cancel();
-						}
-					}
-					
-				}catch( SubscriptionException e ){
-					
-					listener.failed( hash, e );
-				}
-				
-			}
-		}.start();
-		
-		return( res );
-	}
-	
-	protected SubscriptionAssociationLookup
-	lookupAssociationsSupport(
-		final byte[] 							hash,
-		final SubscriptionLookupListener		listener )
-	
-		throws SubscriptionException 
-	{
-		log( "Looking up associations for '" + ByteFormatter.encodeString( hash ));
-		
-		final String	key = "subscription:assoc:" + ByteFormatter.encodeString( hash ); 
-			
-		final boolean[]	cancelled = { false };
-		
-		dht_plugin.get(
-			getKeyBytes(key),
-			"Subs assoc read: " + Base32.encode( hash ).substring( 0, 16 ),
-			DHTPlugin.FLAG_SINGLE_VALUE,
-			30,
-			60*1000,
-			true,
-			true,
-			new DHTPluginOperationListener()
-			{
-				private Map<HashWrapper,Integer>	hits 					= new HashMap<HashWrapper, Integer>();
-				private AESemaphore					hits_sem				= new AESemaphore( "Subs:lookup" );
-				private List<Subscription>			found_subscriptions 	= new ArrayList<Subscription>();
-				
-				private boolean	complete;
-				
-				private AsyncDispatcher 	dispatcher = new AsyncDispatcher();
-				
-				public boolean
-				diversified()
-				{
-					return( true );
-				}
-				
-				public void 
-				starts(
-					byte[] 				key ) 
-				{
-				}
-				
-				public void
-				valueRead(
-					DHTPluginContact	originator,
-					DHTPluginValue		value )
-				{
-					if ( isCancelled2()){
-						
-						return;
-					}
-					
-					byte[]	val = value.getValue();
-					
-					if ( val.length > 4 ){
-						
-						final int	ver = ((val[0]<<16)&0xff0000) | ((val[1]<<8)&0xff00) | (val[2]&0xff);
-
-						final byte[]	sid = new byte[ val.length - 4 ];
-						
-						System.arraycopy( val, 4, sid, 0, sid.length );
-												
-						HashWrapper hw = new HashWrapper( sid );
-						
-						boolean	new_sid = false;
-						
-						synchronized( hits ){
-							
-							if ( complete ){
-								
-								return;
-							}
-							
-							Integer v = (Integer)hits.get(hw);
-							
-							if ( v != null ){
-								
-								if ( ver > v.intValue()){
-									
-									hits.put( hw, new Integer( ver ));								
-								}
-							}else{
-								
-								new_sid = true;
-																
-								hits.put( hw, new Integer( ver ));
-							}
-						}
-						
-						if ( new_sid ){
-							
-							log( "    Found subscription " + ByteFormatter.encodeString( sid ) + " version " + ver );
-
-								// check if already subscribed
-							
-							SubscriptionImpl subs = getSubscriptionFromSID( sid );
-							
-							if ( subs != null ){
-								
-								synchronized( hits ){
-								
-									found_subscriptions.add( subs );
-								}
-								
-								try{
-									listener.found( hash, subs );
-									
-								}catch( Throwable e ){
-									
-									Debug.printStackTrace(e);
-								}
-																
-								hits_sem.release();
-								
-							}else{
-								
-									// don't want to block the DHT processing
-								
-								dispatcher.dispatch(
-									new AERunnable()
-									{
-										public void
-										runSupport()
-										{
-											lookupSubscription( 
-												hash, 
-												sid, 
-												ver,
-												new subsLookupListener()
-												{
-													private boolean sem_done = false;
-													
-													public void
-													found(
-														byte[]					hash,
-														Subscription			subscription )
-													{
-													}
-													
-													public void
-													complete(
-														byte[]					hash,
-														Subscription[]			subscriptions )
-													{
-														done( subscriptions );
-													}
-													
-													public void
-													failed(
-														byte[]					hash,
-														SubscriptionException	error )
-													{
-														done( new Subscription[0]);
-													}
-													
-													protected void
-													done(
-														Subscription[]			subs )
-													{
-														if ( isCancelled()){
-															
-															return;
-														}
-														
-														synchronized( this ){
-															
-															if ( sem_done ){
-																
-																return;
-															}
-															
-															sem_done = true;
-														}
-														
-														if ( subs.length > 0 ){
-															
-															synchronized( hits ){
-															
-																found_subscriptions.add( subs[0] );
-															}
-															
-															try{
-																listener.found( hash, subs[0] );
-																
-															}catch( Throwable e ){
-																
-																Debug.printStackTrace(e);
-															}
-														}
-																									
-														hits_sem.release();
-													}
-													
-													public boolean 
-													isCancelled() 
-													{
-														return( isCancelled2());
-													}
-												});
-										}
-									});
-							}
-						}
-					}
-				}
-				
-				public void
-				valueWritten(
-					DHTPluginContact	target,
-					DHTPluginValue		value )
-				{
-				}
-				
-				public void
-				complete(
-					byte[]				original_key,
-					boolean				timeout_occurred )
-				{
-					dispatcher.dispatch(
-						new AERunnable()
-						{
-							public void
-							runSupport()
-							{
-								int	num_hits;
-								
-								synchronized( hits ){
-									
-									if ( complete ){
-										
-										return;
-									}
-									
-									complete = true;
-									
-									num_hits = hits.size();
-								}
-								
-								
-								for (int i=0;i<num_hits;i++){
-									
-									if ( isCancelled2()){
-										
-										return;
-									}
-	
-									hits_sem.reserve();
-								}
-	
-								if ( isCancelled2()){
-									
-									return;
-								}
-	
-								SubscriptionImpl[] s;
-								
-								synchronized( hits ){
-									
-									s = (SubscriptionImpl[])found_subscriptions.toArray( new SubscriptionImpl[ found_subscriptions.size() ]);
-								}
-								
-								log( "    Association lookup complete - " + s.length + " found" );
-	
-								try{	
-										// record zero assoc here for completeness
-									
-									recordAssociations( hash, s, true );
-									
-								}finally{
-									
-									listener.complete( hash, s );
-								}
-							}
-						});
-				}
-				
-				protected boolean
-				isCancelled2()
-				{
-					synchronized( cancelled ){
-						
-						return( cancelled[0] );
-					}
-				}
-			});
-		
-		return( 
-			new SubscriptionAssociationLookup()
-			{
-				public void 
-				cancel() 
-				{
-					log( "    Association lookup cancelled" );
-
-					synchronized( cancelled ){
-						
-						cancelled[0] = true;
-					}
-				}
-			});
-	}
-	
-	interface 
-	subsLookupListener
-		extends SubscriptionLookupListener
-	{
-		public boolean
-		isCancelled();
-	}
-	
-	protected void
-	getPopularity(
-		final SubscriptionImpl					subs,
-		final SubscriptionPopularityListener	listener )
-	
-		throws SubscriptionException
-	{
-		try{
-			long pop = PlatformSubscriptionsMessenger.getPopularityBySID( subs.getShortID());
-
-			if ( pop >= 0 ){	
-				
-				log( "Got popularity of " + subs.getName() + " from platform: " + pop );
-				
-				listener.gotPopularity( pop );
-
-				return;
-				
-			}else{
-				
-					// unknown sid - if singleton try to register for popularity tracking purposes
-				
-				if ( subs.isSingleton()){
-					
-					try{
-						checkSingletonPublish( subs );
-						
-					}catch( Throwable e ){						
-					}
-					
-					listener.gotPopularity( subs.isSubscribed()?1:0 );
-						
-					return;
-				}
-			}
-			
-		}catch( Throwable e ){
-			
-			log( "Subscription lookup via platform failed", e );
-		}
-		
-		getPopularityFromDHT( subs, listener, true );
-	}
-	
-	protected void
-	getPopularityFromDHT(
-		final SubscriptionImpl					subs,
-		final SubscriptionPopularityListener	listener,
-		final boolean							sync )
-
-	{
-		if ( dht_plugin != null && !dht_plugin.isInitialising()){
-
-			getPopularitySupport( subs, listener, sync );
-			
-		}else{
-			
-			new AEThread2( "SM:popwait", true )
-			{
-				public void
-				run()
-				{
-					getPopularitySupport( subs, listener, sync );
-				}
-			}.start();
-		}
-	}
-	
-	protected void
-	updatePopularityFromDHT(
-		final SubscriptionImpl		subs,
-		boolean						sync )
-	{
-		getPopularityFromDHT(
-			subs,
-			new SubscriptionPopularityListener()
-			{
-				public void
-				gotPopularity(
-					long						popularity )
-				{
-					subs.setCachedPopularity( popularity );
-				}
-				
-				public void
-				failed(
-					SubscriptionException		error )
-				{
-					log( "Failed to update subscription popularity from DHT", error );
-				}
-			},
-			sync );
-	}
-	
-	protected void
-	getPopularitySupport(
-		final SubscriptionImpl					subs,
-		final SubscriptionPopularityListener	listener,
-		final boolean							sync )
-	{
-		log( "Getting popularity of " + subs.getName() + " from DHT" );
-
-		byte[]	hash = subs.getPublicationHash();
-		
-		final AESemaphore sem = new AESemaphore( "SM:pop" );
-		
-		final long[] result = { -1 };
-		
-		final int timeout = 15*1000;
-		
-		dht_plugin.get(
-				hash,
-				"Popularity lookup for subscription " + subs.getName(),
-				DHT.FLAG_STATS,
-				5,
-				timeout,
-				false,
-				true,
-				new DHTPluginOperationListener()
-				{
-					private boolean	diversified;
-					
-					private int	hits = 0;
-					
-					public boolean
-					diversified()
-					{
-						diversified = true;
-						
-						return( false );
-					}
-					
-					public void 
-					starts(
-						byte[] 				key ) 
-					{
-					}
-					
-					public void
-					valueRead(
-						DHTPluginContact	originator,
-						DHTPluginValue		value )
-					{
-						DHTPluginKeyStats stats = dht_plugin.decodeStats( value );
-						
-						if ( stats != null ){
-							
-							result[0] = Math.max( result[0], stats.getEntryCount());
-						
-							hits++;
-							
-							if ( hits >= 3 ){
-								
-								done();
-							}
-						}
-					}
-					
-					public void
-					valueWritten(
-						DHTPluginContact	target,
-						DHTPluginValue		value )
-					{
-						
-					}
-					
-					public void
-					complete(
-						byte[]				key,
-						boolean				timeout_occurred )
-					{
-						if ( diversified ){
-							
-								// TODO: fix?
-							
-							result[0] *= 11;
-							
-							if ( result[0] == 0 ){
-								
-								result[0] = 10;
-							}
-						}
-						
-						done();
-					}
-					
-					protected void
-					done()
-					{						
-						if ( sync ){
-			
-							sem.release();
-
-						}else{
-							
-							if ( result[0] == -1 ){
-								
-								log( "Failed to get popularity of " + subs.getName() + " from DHT" );
-					
-								listener.failed( new SubscriptionException( "Timeout" ));
-								
-							}else{
-							
-								log( "Get popularity of " + subs.getName() + " from DHT: " + result[0] );
-					
-								listener.gotPopularity( result[0] );
-							}
-						}
-					}
-				});
-		
-		if ( sync ){
-			
-			sem.reserve( timeout );
-			
-			if ( result[0] == -1 ){
-				
-				log( "Failed to get popularity of " + subs.getName() + " from DHT" );
-	
-				listener.failed( new SubscriptionException( "Timeout" ));
-				
-			}else{
-			
-				log( "Get popularity of " + subs.getName() + " from DHT: " + result[0] );
-	
-				listener.gotPopularity( result[0] );
-			}
-		}
-	}
-	
-	protected void
-	lookupSubscription(
-		final byte[]						association_hash,
-		final byte[]						sid,
-		final int							version,
-		final subsLookupListener			listener )
-	{
-		try{
-			SubscriptionImpl subs = getSubscriptionFromPlatform( sid, SubscriptionImpl.ADD_TYPE_LOOKUP );
-
-			log( "Added temporary subscription: " + subs.getString());
-			
-			subs = addSubscription( subs );
-			
-			listener.complete( association_hash, new Subscription[]{ subs });
-			
-			return;
-			
-		}catch( Throwable e ){
-			
-			if ( listener.isCancelled()){
-				
-				return;
-			}
-			
-			final String sid_str = ByteFormatter.encodeString( sid );
-			
-			log( "Subscription lookup via platform for " + sid_str + " failed", e );
-			
-			if ( getSubscriptionDownloadCount() > 8 ){
-				
-				log( "Too many existing subscription downloads" );
-				
-				listener.complete( association_hash, new Subscription[0]);
-
-				return;
-			}
-			
-				// fall back to DHT
-			
-			log( "Subscription lookup via DHT starts for " + sid_str );
-
-			final String	key = "subscription:publish:" + ByteFormatter.encodeString( sid ) + ":" + version; 
-			
-			dht_plugin.get(
-				getKeyBytes(key),
-				"Subs lookup read: " + ByteFormatter.encodeString( sid ) + ":" + version,
-				DHTPlugin.FLAG_SINGLE_VALUE,
-				12,
-				60*1000,
-				false,
-				true,
-				new DHTPluginOperationListener()
-				{
-					private boolean listener_handled;
-					
-					public boolean
-					diversified()
-					{
-						return( true );
-					}
-					
-					public void 
-					starts(
-						byte[] 				key ) 
-					{
-					}
-					
-					public void
-					valueRead(
-						DHTPluginContact	originator,
-						DHTPluginValue		value )
-					{
-						byte[]	data = value.getValue();
-								
-						try{
-							final Map	details = decodeSubscriptionDetails( data );
-							
-							if ( SubscriptionImpl.getPublicationVersion( details ) == version ){
-																
-								Map	singleton_details = (Map)details.get( "x" );
-								
-								if ( singleton_details == null ){
-									
-									synchronized( this ){
-										
-										if ( listener_handled  ){
-											
-											return;
-										}
-										
-										listener_handled = true;
-									}
-									
-									log( "    found " + sid_str + ", non-singleton" );
-
-									new AEThread2( "Subs:lookup download", true )
-									{
-										public void
-										run()
-										{
-											downloadSubscription( 
-												association_hash,
-												SubscriptionImpl.getPublicationHash( details ),
-												sid,
-												version,
-												SubscriptionImpl.getPublicationSize( details ),
-												listener );
-										}
-									}.start();
-									
-								}else{
-																			
-									synchronized( this ){
-											
-										if ( listener_handled  ){
-												
-											return;
-										}
-											
-										listener_handled = true;
-									}
-									
-									log( "    found " + sid_str + ", singleton" );
-
-									try{
-										SubscriptionImpl subs = createSingletonSubscription( singleton_details, SubscriptionImpl.ADD_TYPE_LOOKUP, false );
-																			
-										listener.complete( association_hash, new Subscription[]{ subs });
-																			
-									}catch( Throwable e ){
-																					
-										listener.failed( association_hash, new SubscriptionException( "Subscription creation failed", e ));
-									}
-								}
-							}else{
-								
-								log( "    found " + sid_str + " but version mismatch" );
-
-							}
-						}catch( Throwable e ){
-							
-							log( "    found " + sid_str + " but verification failed", e );
-
-						}
-					}
-					
-					public void
-					valueWritten(
-						DHTPluginContact	target,
-						DHTPluginValue		value )
-					{
-					}
-					
-					public void
-					complete(
-						byte[]				original_key,
-						boolean				timeout_occurred )
-					{
-						if ( listener.isCancelled()){
-							
-							return;
-						}
-						
-						log( "    " + sid_str + " complete" );
-						
-						synchronized( this ){
-							
-							if ( !listener_handled ){
-						
-								listener_handled = true;
-								
-								listener.complete( association_hash, new Subscription[0] );
-							}
-						}
-					}
-				});
-		}
-	}
-	
-	protected SubscriptionImpl
-	getSubscriptionFromPlatform(
-		byte[]		sid,
-		int			add_type )
-	
-		throws SubscriptionException
-	{
-		try{
-			PlatformSubscriptionsMessenger.subscriptionDetails details = PlatformSubscriptionsMessenger.getSubscriptionBySID( sid );
-			
-			SubscriptionImpl res = getSubscriptionFromVuzeFileContent( sid, add_type, details.getContent());
-			
-			int	pop = details.getPopularity();
-			
-			if ( pop >= 0 ){
-				
-				res.setCachedPopularity( pop );
-			}
-			
-			return( res );
-			
-		}catch( SubscriptionException e ){
-			
-			throw( e );
-			
-		}catch( Throwable e ){
-			
-			throw( new SubscriptionException( "Failed to read subscription from platform", e ));
-		}
-	}
-	
-	protected SubscriptionImpl
-	getSubscriptionFromVuzeFile(
-		byte[]		sid,
-		int			add_type,
-		File		file )
-	
-		throws SubscriptionException
-	{
-		VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
-		
-		String	file_str = file.getAbsolutePath();
-		
-		VuzeFile vf = vfh.loadVuzeFile( file_str );
-
-		if ( vf == null ){
-			
-			log( "Failed to load vuze file from " + file_str );
-			
-			throw( new SubscriptionException( "Failed to load vuze file from " + file_str ));
-		}
-		
-		return( getSubscriptionFromVuzeFile( sid, add_type, vf ));
-	}
-	
-	protected SubscriptionImpl
-	getSubscriptionFromVuzeFileContent(
-		byte[]		sid,
-		int			add_type,
-		String		content )
-	
-		throws SubscriptionException
-	{
-		VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
-		
-		VuzeFile vf = vfh.loadVuzeFile( Base64.decode( content ));
-
-		if ( vf == null ){
-			
-			log( "Failed to load vuze file from " + content );
-			
-			throw( new SubscriptionException( "Failed to load vuze file from content" ));
-		}
-	
-		return( getSubscriptionFromVuzeFile( sid, add_type, vf ));
-	}
-	
-	protected SubscriptionImpl
-	getSubscriptionFromVuzeFile(
-		byte[]		sid,
-		int			add_type,
-		VuzeFile	vf )
-	
-		throws SubscriptionException
-	{
-		VuzeFileComponent[] comps = vf.getComponents();
-		
-		for (int j=0;j<comps.length;j++){
-			
-			VuzeFileComponent comp = comps[j];
-			
-			if ( comp.getType() == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION ){
-				
-				Map map = comp.getContent();
-				
-				try{
-					SubscriptionBodyImpl body = new SubscriptionBodyImpl( SubscriptionManagerImpl.this, map );
-												
-					SubscriptionImpl new_subs = new SubscriptionImpl( SubscriptionManagerImpl.this, body, add_type, false );
-							
-					if ( Arrays.equals( new_subs.getShortID(), sid )){
-													
-						return( new_subs );
-					}
-				}catch( Throwable e ){
-					
-					log( "Subscription decode failed", e );
-				}
-			}
-		}
-		
-		throw( new SubscriptionException( "Subscription not found" ));
-	}
-	
-	protected void 
-	downloadSubscription(
-		final byte[]						association_hash,
-		byte[]								torrent_hash,
-		final byte[]						sid,
-		int									version,
-		int									size,
-		final subsLookupListener		 	listener )
-	{
-		try{
-			Object[] res = downloadTorrent( torrent_hash, size );
-			
-			if ( listener.isCancelled()){
-				
-				return;
-			}
-			
-			if ( res == null ){
-				
-				listener.complete( association_hash, new Subscription[0] );
-				
-				return;
-			}
-
-			downloadSubscription(
-				(TOTorrent)res[0], 
-				(InetSocketAddress)res[1],
-				sid,
-				version,
-				"Subscription " + ByteFormatter.encodeString( sid ) + " for " + ByteFormatter.encodeString( association_hash ),
-				new downloadListener()
-				{
-					public void
-					complete(
-						File		data_file )
-					{
-						boolean	reported = false;
-						
-						try{
-							if ( listener.isCancelled()){
-								
-								return;
-							}
-							
-							SubscriptionImpl subs = getSubscriptionFromVuzeFile( sid, SubscriptionImpl.ADD_TYPE_LOOKUP, data_file );
-						
-							log( "Added temporary subscription: " + subs.getString());
-							
-							subs = addSubscription( subs );
-							
-							listener.complete( association_hash, new Subscription[]{ subs });
-							
-							reported = true;
-	
-						}catch( Throwable e ){
-							
-							log( "Subscription decode failed", e );
-							
-						}finally{
-														
-							if ( !reported ){
-								
-								listener.complete( association_hash, new Subscription[0] );
-							}
-						}
-					}
-					
-					public void
-					complete(
-						Download	download,	
-						File		torrent_file )
-					{
-						File	data_file = new File( download.getSavePath());
-						
-						try{
-							removeDownload( download, false );
-
-							complete( data_file );
-							
-						}catch( Throwable e ){
-							
-							log( "Failed to remove download", e );
-							
-							listener.complete( association_hash, new Subscription[0] );
-							
-						}finally{
-							
-							torrent_file.delete();
-							
-							data_file.delete();
-						}
-					}
-						
-					public void
-					failed(
-						Throwable	error )
-					{
-						listener.complete( association_hash, new Subscription[0] );
-					}
-					
-					public Map
-					getRecoveryData()
-					{
-						return( null );
-					}
-					
-					public boolean
-					isCancelled()
-					{
-						return( listener.isCancelled());
-					}
-				});
-				
-		}catch( Throwable e ){
-			
-			log( "Subscription download failed",e );
-			
-			listener.complete( association_hash, new Subscription[0] );
-		}
-	}
-	
-	protected int
-	getSubscriptionDownloadCount()
-	{
-		PluginInterface pi = PluginInitializer.getDefaultInterface();
-		
-		Download[] downloads = pi.getDownloadManager().getDownloads();
-		
-		int	res = 0;
-		
-		for( int i=0;i<downloads.length;i++){
-			
-			Download	download = downloads[i];
-			
-			if ( download.getBooleanAttribute( ta_subs_download )){
-				
-				res++;
-			}
-		}
-		
-		return( res );
-	}
-	
-	protected void
-	associationAdded(
-		SubscriptionImpl			subscription,
-		byte[]						association_hash )
-	{
-		recordAssociations( association_hash, new SubscriptionImpl[]{ subscription }, false );
-
-		if ( dht_plugin != null ){
-			
-			publishAssociations();
-		}
-	}
-	
-	protected void
-	addPotentialAssociation(
-		SubscriptionImpl			subs,
-		String						result_id,
-		String						key )
-	{
-		if ( key == null ){
-			
-			Debug.out( "Attempt to add null key!" );
-			
-			return;
-		}
-		
-		log( "Added potential association: " + subs.getName() + "/" + result_id + " -> " + key );
-		
-		synchronized( potential_associations ){
-			
-			potential_associations.add( new Object[]{ subs, result_id, key, new Long( System.currentTimeMillis())} );
-			
-			if ( potential_associations.size() > 512 ){
-				
-				potential_associations.remove(0);
-			}
-		}
-	}
-	
-	protected void
-	checkPotentialAssociations(
-		byte[]				hash,
-		String				key )
-	{
-		log( "Checking potential association: " + key + " -> " + ByteFormatter.encodeString( hash ));
-		
-		SubscriptionImpl 	subs 		= null;
-		String				result_id	= null;
-		
-		synchronized( potential_associations ){
-
-			Iterator<Object[]> it = potential_associations.iterator();
-			
-			while( it.hasNext()){
-				
-				Object[]	entry = it.next();
-				
-				String	this_key = (String)entry[2];
-				
-					// startswith as actual URL may have had additional parameters added such as azid
-				
-				if ( key.startsWith( this_key )){
-					
-					subs		= (SubscriptionImpl)entry[0];
-					result_id	= (String)entry[1];
-					
-					log( "    key matched to subscription " + subs.getName() + "/" + result_id);
-
-					it.remove();
-					
-					break;
-				}
-			}
-		}
-		
-		if ( subs == null ){
-			
-			log( "    no potential associations found" );
-			
-		}else{
-			
-			SubscriptionResult	result = subs.getHistory().getResult( result_id );
-			
-			if ( result != null ){
-				
-				log( "    result found, marking as read" );
-
-				result.setRead( true );
-				
-			}else{
-				
-				log( "    result not found" );
-			}
-			
-			log( "    adding association" );
-			
-			subs.addAssociation( hash );
-		}
-	}
-	
-	protected void
-	tidyPotentialAssociations()
-	{
-		long	now = SystemTime.getCurrentTime();
-		
-		synchronized( potential_associations ){
-			
-			Iterator it = potential_associations.iterator();
-			
-			while( it.hasNext() && potential_associations.size() > 16 ){
-				
-				Object[]	entry = (Object[])it.next();
-				
-				long	created = ((Long)entry[3]).longValue();
-				
-				if ( created > now ){
-					
-					entry[3] = new Long( now );
-					
-				}else if ( now - created > 60*60*1000 ){
-					
-					SubscriptionImpl 	subs = (SubscriptionImpl)entry[0];
-
-					String	result_id	= (String)entry[1];
-					String	key			= (String)entry[2];
-
-					log( "Removing expired potential association: " + subs.getName() + "/" + result_id + " -> " + key );
-					
-					it.remove();
-				}
-			}
-		}
-		
-		synchronized( potential_associations2 ){
-			
-			Iterator it = potential_associations2.entrySet().iterator();
-			
-			while( it.hasNext() && potential_associations2.size() > 16 ){
-				
-				Map.Entry	map_entry = (Map.Entry)it.next();
-				
-				byte[]		hash = ((HashWrapper)map_entry.getKey()).getBytes();
-				
-				Object[]	entry = (Object[])map_entry.getValue();
-				
-				long	created = ((Long)entry[2]).longValue();
-				
-				if ( created > now ){
-					
-					entry[2] = new Long( now );
-					
-				}else if ( now - created > 60*60*1000 ){
-					
-					SubscriptionImpl[] 	subs = (SubscriptionImpl[])entry[0];
-
-					String	subs_str = "";
-					
-					for (int i=0;i<subs.length;i++){
-						subs_str += (i==0?"":",") + subs[i].getName();
-					}
-					
-					log( "Removing expired potential association: " + ByteFormatter.encodeString(hash) + " -> " + subs_str );
-					
-					it.remove();
-				}
-			}
-		}
-	}
-	
-	protected void
-	recordAssociations(
-		byte[]						association_hash,
-		SubscriptionImpl[]			subscriptions,
-		boolean						full_lookup )
-	{
-		HashWrapper	hw = new HashWrapper( association_hash );
-		
-		synchronized( potential_associations2 ){
-			
-			potential_associations2.put( hw, new Object[]{ subscriptions, new Boolean( full_lookup ), new Long( SystemTime.getCurrentTime())});
-		}
-			
-		if ( recordAssociationsSupport( association_hash, subscriptions, full_lookup )){
-			
-			synchronized( potential_associations2 ){
-
-				potential_associations2.remove( hw );
-			}
-		}else{
-			
-			log( "Deferring association for " + ByteFormatter.encodeString( association_hash ));
-		}
-	}
-	
-	protected boolean
-	recordAssociationsSupport(
-		byte[]						association_hash,
-		SubscriptionImpl[]			subscriptions,
-		boolean						full_lookup )
-	{
-		PluginInterface pi = PluginInitializer.getDefaultInterface();
-
-		boolean	download_found	= false;
-		boolean	changed 		= false;
-		
-		try{
-			Download download = pi.getDownloadManager().getDownload( association_hash );
-			
-			if ( download != null ){
-					
-				if ( subscriptions.length > 0 ){
-					
-					String	category = subscriptions[0].getCategory();
-					
-					if ( category != null ){
-						
-						String existing = download.getAttribute( ta_category );
-								
-						if ( existing == null ){
-									
-							download.setAttribute( ta_category, category );
-						}
-					}
-					
-					long	tag_id = subscriptions[0].getTagID();
-					
-					if ( tag_id >= 0 ){
-						
-						Tag tag = TagManagerFactory.getTagManager().lookupTagByUID( tag_id );
-
-						if ( tag != null ){
-							
-							org.gudy.azureus2.core3.download.DownloadManager core_dm = PluginCoreUtils.unwrap( download );
-							
-							if ( !tag.hasTaggable( core_dm )){
-								
-								tag.addTaggable( core_dm );
-							}
-						}
-					}
-					
-				}
-				
-				download_found = true;
-				
-				Map	map = download.getMapAttribute( ta_subscription_info );
-				
-				if ( map == null ){
-					
-					map = new LightHashMap();
-					
-				}else{
-					
-					map = new LightHashMap( map );
-				}
-				
-				List	s = (List)map.get( "s" );
-				
-				for (int i=0;i<subscriptions.length;i++){
-				
-					byte[]	sid = subscriptions[i].getShortID();
-					
-					if ( s == null ){
-						
-						s = new ArrayList();
-						
-						s.add( sid );
-						
-						changed	= true;
-						
-						map.put( "s", s );
-						
-					}else{
-						
-						boolean found = false;
-						
-						for (int j=0;j<s.size();j++){
-							
-							byte[]	existing = (byte[])s.get(j);
-							
-							if ( Arrays.equals( sid, existing )){
-								
-								found = true;
-								
-								break;
-							}
-						}
-						
-						if ( !found ){
-						
-							s.add( sid );
-								
-							changed	= true;
-						}
-					}
-				}
-				
-				if ( full_lookup ){
-				
-					map.put( "lc", new Long( SystemTime.getCurrentTime()));
-					
-					changed	= true;
-				}
-				
-				if ( changed ){
-				
-					download.setMapAttribute( ta_subscription_info, map );
-				}
-			}
-		}catch( Throwable e ){
-			
-			log( "Failed to record associations", e );
-		}
-		
-		if ( changed ){
-			
-			Iterator it = listeners.iterator();
-			
-			while( it.hasNext()){
-				
-				try{
-					((SubscriptionManagerListener)it.next()).associationsChanged( association_hash );
-					
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace(e);
-				}
-			}
-		}
-		
-		return( download_found );
-	}
-	
-	protected boolean
-	publishAssociations()
-	{
-		SubscriptionImpl 				subs_to_publish		= null;
-		SubscriptionImpl.association	assoc_to_publish 	= null;
-
-		synchronized( this ){
-			
-			if ( publish_associations_active >= ( dht_plugin.isSleeping()?PUB_SLEEPING_ASSOC_CONC_MAX:PUB_ASSOC_CONC_MAX )){
-				
-				return( false );
-			}			
-			
-			publish_associations_active++;
-			
-			List shuffled_subs = new ArrayList( subscriptions );
-
-			Collections.shuffle( shuffled_subs );
-							
-			for (int i=0;i<shuffled_subs.size();i++){
-					
-				SubscriptionImpl sub = (SubscriptionImpl)shuffled_subs.get( i );
-					
-				if ( sub.isSubscribed() && sub.isPublic()){
-					
-					assoc_to_publish 	= sub.getAssociationForPublish();
-						
-					if ( assoc_to_publish != null ){
-							
-						subs_to_publish		= sub;
-
-						break;
-					}
-				}
-			}
-		}
-		
-		if ( assoc_to_publish != null ){
-		
-			publishAssociation( subs_to_publish, assoc_to_publish );
-			
-			return( false );
-			
-		}else{
-					
-			log( "Publishing Associations Complete" );
-					
-			synchronized( this ){
-
-				publish_associations_active--;
-			}
-			
-			return( true );
-		}
-	}
-	
-	protected void
-	publishAssociation(
-		final SubscriptionImpl					subs,
-		final SubscriptionImpl.association		assoc )
-	{
-		log( "Checking association '" + subs.getString() + "' -> '" + assoc.getString() + "'" );
-		
-		byte[]	sub_id 		= subs.getShortID();
-		int		sub_version	= subs.getVersion();
-		
-		byte[]	assoc_hash	= assoc.getHash();
-		
-		final String	key = "subscription:assoc:" + ByteFormatter.encodeString( assoc_hash ); 
-				
-		final byte[]	put_value = new byte[sub_id.length + 4];
-		
-		System.arraycopy( sub_id, 0, put_value, 4, sub_id.length );
-		
-		put_value[0]	= (byte)(sub_version>>16);
-		put_value[1]	= (byte)(sub_version>>8);
-		put_value[2]	= (byte)sub_version;
-		put_value[3]	= (byte)subs.getFixedRandom();
-		
-		dht_plugin.get(
-			getKeyBytes(key),
-			"Subs assoc read: " + Base32.encode( assoc_hash ).substring( 0, 16 ),
-			DHTPlugin.FLAG_SINGLE_VALUE,
-			30,
-			60*1000,
-			false,
-			false,
-			new DHTPluginOperationListener()
-			{
-				private int			hits;
-				private boolean		diversified;
-				private int			max_ver;
-				
-				public boolean
-				diversified()
-				{
-					diversified = true;
-					
-					return( false );
-				}
-				
-				public void 
-				starts(
-					byte[] 				key ) 
-				{
-				}
-				
-				public void
-				valueRead(
-					DHTPluginContact	originator,
-					DHTPluginValue		value )
-				{
-					byte[]	val = value.getValue();
-					
-					if ( val.length == put_value.length ){
-						
-						boolean	diff = false;
-						
-						for (int i=4;i<val.length;i++){
-							
-							if ( val[i] != put_value[i] ){
-								
-								diff = true;
-								
-								break;
-							}
-						}
-						
-						if ( !diff ){
-							
-							hits++;
-							
-							int	ver = ((val[0]<<16)&0xff0000) | ((val[1]<<8)&0xff00) | (val[2]&0xff);
-							
-							if ( ver > max_ver ){
-								
-								max_ver = ver;
-							}
-						}
-					}
-				}
-				
-				public void
-				valueWritten(
-					DHTPluginContact	target,
-					DHTPluginValue		value )
-				{
-				}
-				
-				public void
-				complete(
-					byte[]				original_key,
-					boolean				timeout_occurred )
-				{
-					log( "Checked association '" + subs.getString() + "' -> '" + assoc.getString() + "' - max_ver=" + max_ver + ",hits=" + hits + ",div=" + diversified );
-
-					if ( max_ver > subs.getVersion()){
-						
-						if ( !subs.isMine()){
-						
-							updateSubscription( subs, max_ver );
-						}
-					}
-					
-					if ( hits < 10 && !diversified ){			
-			
-						log( "    Publishing association '" + subs.getString() + "' -> '" + assoc.getString() + "', existing=" + hits );
-
-						byte flags = DHTPlugin.FLAG_ANON;
-						
-						if ( hits < 3 && !diversified ){
-							
-							flags |= DHTPlugin.FLAG_PRECIOUS;
-						}
-						
-						dht_plugin.put(
-							getKeyBytes(key),
-							"Subs assoc write: " + Base32.encode( assoc.getHash()).substring( 0, 16 ) + " -> " + Base32.encode( subs.getShortID() ) + ":" + subs.getVersion(),
-							put_value,
-							flags,
-							new DHTPluginOperationListener()
-							{
-								public boolean
-								diversified()
-								{
-									return( true );
-								}
-								
-								public void 
-								starts(
-									byte[] 				key ) 
-								{
-								}
-								
-								public void
-								valueRead(
-									DHTPluginContact	originator,
-									DHTPluginValue		value )
-								{
-								}
-								
-								public void
-								valueWritten(
-									DHTPluginContact	target,
-									DHTPluginValue		value )
-								{
-								}
-								
-								public void
-								complete(
-									byte[]				key,
-									boolean				timeout_occurred )
-								{
-									log( "        completed '" + subs.getString() + "' -> '" + assoc.getString() + "'" );
-				
-									publishNext();
-								}
-							});
-					}else{
-						
-						log( "    Not publishing association '" + subs.getString() + "' -> '" + assoc.getString() + "', existing =" + hits );
-
-						publishNext();
-					}
-				}
-				
-				protected void
-				publishNext()
-				{
-					synchronized( SubscriptionManagerImpl.this ){
-						
-						publish_associations_active--;
-					}
-					
-					publishNextAssociation();
-				}
-			});
-	}
-	
-	private void
-	publishNextAssociation()
-	{
-		boolean	dht_sleeping = dht_plugin.isSleeping();
-		
-		if ( dht_sleeping ){
-			
-			synchronized( this ){
-				
-				if ( publish_next_asyc_pending ){
-					
-					return;
-				}
-				
-				publish_next_asyc_pending = true;
-			}
-			
-			SimpleTimer.addEvent(
-				"subs:pn:async",
-				SystemTime.getCurrentTime() + 60*1000,
-				new TimerEventPerformer()
-				{
-					public void 
-					perform(
-						TimerEvent event) 
-					{
-						synchronized( SubscriptionManagerImpl.this ){
-							
-							publish_next_asyc_pending = false;
-						}
-						
-						publishAssociations();
-					}
-				});
-			
-			return;
-		}
-		
-		publishAssociations();
-	}
-	
-	protected void
-	subscriptionUpdated()
-	{
-		if ( dht_plugin != null ){
-			
-			publishSubscriptions();
-		}
-	}
-	
-	protected void
-	publishSubscriptions()
-	{
-		List	 shuffled_subs;
-
-		synchronized( this ){
-			
-			if ( publish_subscription_active ){
-				
-				return;
-			}			
-			
-			shuffled_subs = new ArrayList( subscriptions );
-
-			publish_subscription_active = true;
-		}
-	
-		boolean	publish_initiated = false;
-		
-		try{
-			Collections.shuffle( shuffled_subs );
-						
-			for (int i=0;i<shuffled_subs.size();i++){
-				
-				SubscriptionImpl sub = (SubscriptionImpl)shuffled_subs.get( i );
-				
-				if ( sub.isSubscribed() && sub.isPublic() && !sub.getPublished()){
-									
-					sub.setPublished( true );
-					
-					publishSubscription( sub );
-					
-					publish_initiated = true;
-					
-					break;
-				}
-			}
-		}finally{
-			
-			if ( !publish_initiated ){
-				
-				log( "Publishing Subscriptions Complete" );
-				
-				synchronized( this ){
-	
-					publish_subscription_active = false;
-				}
-			}
-		}
-	}
-	
-	protected void
-	publishSubscription(
-		final SubscriptionImpl					subs )
-	{
-		log( "Checking subscription publication '" + subs.getString() + "'" );
-		
-		byte[]	sub_id 		= subs.getShortID();
-		int		sub_version	= subs.getVersion();
-				
-		final String	key = "subscription:publish:" + ByteFormatter.encodeString( sub_id ) + ":" + sub_version; 
-						
-		dht_plugin.get(
-			getKeyBytes(key),
-			"Subs presence read: " + ByteFormatter.encodeString( sub_id ) + ":" + sub_version,
-			DHTPlugin.FLAG_SINGLE_VALUE,
-			24,
-			60*1000,
-			false,
-			false,
-			new DHTPluginOperationListener()
-			{
-				private int		hits;
-				private boolean	diversified;
-				
-				public boolean
-				diversified()
-				{					
-					diversified = true;
-					
-					return( false );
-				}
-				
-				public void 
-				starts(
-					byte[] 				key ) 
-				{
-				}
-				
-				public void
-				valueRead(
-					DHTPluginContact	originator,
-					DHTPluginValue		value )
-				{					
-					byte[]	data = value.getValue();
-						
-					try{
-						Map	details = decodeSubscriptionDetails( data );
-
-						if ( subs.getVerifiedPublicationVersion( details ) == subs.getVersion()){
-						
-							hits++;
-						}
-					}catch( Throwable e ){
-						
-					}
-				}
-				
-				public void
-				valueWritten(
-					DHTPluginContact	target,
-					DHTPluginValue		value )
-				{
-				}
-				
-				public void
-				complete(
-					byte[]				original_key,
-					boolean				timeout_occurred )
-				{
-					log( "Checked subscription publication '" + subs.getString() + "' - hits=" + hits + ",div=" + diversified );
-
-					if ( hits < 10 && !diversified ){			
-			
-						log( "    Publishing subscription '" + subs.getString() + ", existing=" + hits );
-
-						try{
-							byte[]	put_value = encodeSubscriptionDetails( subs );						
-							
-							if ( put_value.length < DHTPlugin.MAX_VALUE_SIZE ){
-								
-								byte	flags = DHTPlugin.FLAG_SINGLE_VALUE;
-								
-								if ( hits < 3 && !diversified ){
-									
-									flags |= DHTPlugin.FLAG_PRECIOUS;
-								}
-								
-								dht_plugin.put(
-									getKeyBytes(key),
-									"Subs presence write: " + Base32.encode( subs.getShortID() ) + ":" + subs.getVersion(),
-									put_value,
-									flags,
-									new DHTPluginOperationListener()
-									{
-										public boolean
-										diversified()
-										{
-											return( true );
-										}
-										
-										public void 
-										starts(
-											byte[] 				key ) 
-										{
-										}
-										
-										public void
-										valueRead(
-											DHTPluginContact	originator,
-											DHTPluginValue		value )
-										{
-										}
-										
-										public void
-										valueWritten(
-											DHTPluginContact	target,
-											DHTPluginValue		value )
-										{
-										}
-										
-										public void
-										complete(
-											byte[]				key,
-											boolean				timeout_occurred )
-										{
-											log( "        completed '" + subs.getString() + "'" );
-						
-											publishNext();
-										}
-									});
-								
-							}else{
-								
-								publishNext();
-							}
-						}catch( Throwable e ){
-							
-							Debug.printStackTrace( e );
-							
-							publishNext();
-						}
-						
-					}else{
-						
-						log( "    Not publishing subscription '" + subs.getString() + "', existing =" + hits );
-
-						publishNext();
-					}
-				}
-				
-				protected void
-				publishNext()
-				{
-					synchronized( SubscriptionManagerImpl.this ){
-						
-						publish_subscription_active = false;
-					}
-					
-					publishSubscriptions();
-				}
-			});
-	}
-	
-	protected void
-	updateSubscription(
-		final SubscriptionImpl		subs,
-		final int					new_version )
-	{
-		log( "Subscription " + subs.getString() + " - higher version found: " + new_version );
-		
-		if ( !subs.canAutoUpgradeCheck()){
-			
-			log( "    Checked too recently or not updateable, ignoring" );
-			
-			return;
-		}
-		
-		if ( subs.getHighestUserPromptedVersion() >= new_version ){
-			
-			log( "    User has already been prompted for version " + new_version + " so ignoring" );
-			
-			return;
-		}
-					
-		byte[]	sub_id 		= subs.getShortID();
-			
-		try{
-			PlatformSubscriptionsMessenger.subscriptionDetails details = PlatformSubscriptionsMessenger.getSubscriptionBySID( sub_id );
-			
-			if ( !askIfCanUpgrade( subs, new_version )){
-				
-				return;
-			}
-			
-			VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
-			
-			VuzeFile vf = vfh.loadVuzeFile( Base64.decode( details.getContent()));
-							
-			vfh.handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_SUBSCRIPTION );
-			
-			return;
-			
-		}catch( Throwable e ){
-			
-			log( "Failed to read subscription from platform, trying DHT" );
-		}
-		
-		log( "Checking subscription '" + subs.getString() + "' upgrade to version " + new_version );
-
-		final String	key = "subscription:publish:" + ByteFormatter.encodeString( sub_id ) + ":" + new_version; 
-						
-		dht_plugin.get(
-			getKeyBytes(key),
-			"Subs update read: " + Base32.encode( sub_id ) + ":" + new_version,
-			DHTPlugin.FLAG_SINGLE_VALUE,
-			12,
-			60*1000,
-			false,
-			false,
-			new DHTPluginOperationListener()
-			{
-				private byte[]	verified_hash;
-				private int		verified_size;
-				
-				public boolean
-				diversified()
-				{
-					return( true );
-				}
-				
-				public void 
-				starts(
-					byte[] 				key ) 
-				{
-				}
-				
-				public void
-				valueRead(
-					DHTPluginContact	originator,
-					DHTPluginValue		value )
-				{
-					byte[]	data = value.getValue();
-							
-					try{
-						Map	details = decodeSubscriptionDetails( data );
-						
-						if ( 	verified_hash == null && 
-								subs.getVerifiedPublicationVersion( details ) == new_version ){
-							
-							verified_hash 	= SubscriptionImpl.getPublicationHash( details );
-							verified_size	= SubscriptionImpl.getPublicationSize( details );
-						}
-						
-					}catch( Throwable e ){
-						
-					}
-				}
-				
-				public void
-				valueWritten(
-					DHTPluginContact	target,
-					DHTPluginValue		value )
-				{
-				}
-				
-				public void
-				complete(
-					byte[]				original_key,
-					boolean				timeout_occurred )
-				{
-					if ( verified_hash != null ){			
-			
-						log( "    Subscription '" + subs.getString() + " upgrade verified as authentic" );
-
-						updateSubscription( subs, new_version, verified_hash, verified_size );
-						
-					}else{
-						
-						log( "    Subscription '" + subs.getString() + " upgrade not verified" );
-					}
-				}
-			});
-	}
-	
-	protected byte[]
-	encodeSubscriptionDetails(
-		SubscriptionImpl		subs )
-	
-		throws IOException
-	{
-		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();
-				
-		GZIPOutputStream os = new GZIPOutputStream( baos );
-
-		os.write( encoded );
-		
-		os.close();
-		
-		byte[] compressed = baos.toByteArray();
-		
-		byte	header;
-		byte[]	data;
-		
-		if ( compressed.length < encoded.length ){
-			
-			header 	= 1;
-			data	= compressed; 
-		}else{
-			
-			header	= 0;
-			data	= encoded;
-		}
-				
-		byte[] result = new byte[data.length+1];
-		
-		result[0] = header;
-		
-		System.arraycopy( data, 0, result, 1, data.length );
-		
-		return( result );
-	}
-	
-	protected Map
-	decodeSubscriptionDetails(
-		byte[]			data )
-	
-		throws IOException
-	{
-		byte[]	to_decode;
-		
-		if ( data[0] == 0 ){
-			
-			to_decode = new byte[ data.length-1 ];
-			
-			System.arraycopy( data, 1, to_decode, 0, data.length - 1 );
-			
-		}else{
-			
-			GZIPInputStream is = new GZIPInputStream(new ByteArrayInputStream( data, 1, data.length - 1 ));
-			
-			to_decode = FileUtil.readInputStreamAsByteArray( is );
-			
-			is.close();
-		}
-		
-		Map res = BDecoder.decode( to_decode );
-		
-			// remove any injected random seed
-		
-		res.remove( "!" );
-		
-		return( res );
-	}
-	
-	protected void
-	updateSubscription(
-		final SubscriptionImpl			subs,
-		final int						update_version,
-		final byte[]					update_hash,
-		final int						update_size )
-	{
-		log( "Subscription " + subs.getString() + " - update hash=" + ByteFormatter.encodeString( update_hash ) + ", size=" + update_size );
-
-		new AEThread2( "SubsUpdate", true )
-		{
-			public void
-			run()
-			{
-				try{
-					Object[] res = downloadTorrent( update_hash, update_size );
-					
-					if ( res != null ){
-					
-						updateSubscription( subs, update_version, (TOTorrent)res[0], (InetSocketAddress)res[1] );
-					}
-				}catch( Throwable e ){
-					
-					log( "    update failed", e );
-				}
-			}
-		}.start();
-	}
-	
-	protected Object[]
-	downloadTorrent(
-		byte[]		hash,
-		int			update_size )
-	{
-		if ( !isSubsDownloadEnabled()){
-			
-			log( "    Can't download subscription " + Base32.encode( hash ) + " as feature disabled" );
-			
-			return( null );
-		}
-		
-		final MagnetPlugin	magnet_plugin = getMagnetPlugin();
-	
-		if ( magnet_plugin == null ){
-		
-			log( "    Can't download, no magnet plugin" );
-		
-			return( null );
-		}
-
-		try{
-			final InetSocketAddress[] sender = { null };
-			
-			byte[] torrent_data = magnet_plugin.download(
-				new MagnetPluginProgressListener()
-				{
-					public void
-					reportSize(
-						long	size )
-					{
-					}
-					
-					public void
-					reportActivity(
-						String	str )
-					{
-						log( "    MagnetDownload: " + str );
-					}
-					
-					public void
-					reportCompleteness(
-						int		percent )
-					{
-					}
-					
-					public void
-					reportContributor(
-						InetSocketAddress	address )
-					{
-						synchronized( sender ){
-						
-							sender[0] = address;
-						}
-					}
-
-					public boolean 
-					verbose() 
-					{
-						return( false );
-					}
-					
-					public boolean 
-					cancelled() 
-					{
-						return( false );
-					}
-				},
-				hash,
-				"",
-				new InetSocketAddress[0],
-				300*1000,
-				MagnetPlugin.FL_DISABLE_MD_LOOKUP );
-			
-			if ( torrent_data == null ){
-				
-				log( "    download failed - timeout" );
-				
-				return( null );
-			}
-			
-			log( "Subscription torrent downloaded" );
-			
-			TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedByteArray( torrent_data );
-		
-				// update size is just that of signed content, torrent itself is .vuze file
-				// so take this into account
-			
-			if ( torrent.getSize() > update_size + 10*1024 ){
-			
-				log( "Subscription download abandoned, torrent size is " + torrent.getSize() + ", underlying data size is " + update_size );
-				
-				return( null );
-			}
-			
-			if ( torrent.getSize() > 4*1024*1024 ){
-				
-				log( "Subscription download abandoned, torrent size is too large (" + torrent.getSize() + ")" );
-				
-				return( null );
-			}
-			
-			synchronized( sender ){
-			
-				return( new Object[]{ torrent, sender[0] });
-			}
-			
-		}catch( Throwable e ){
-			
-			log( "    download failed", e );
-			
-			return( null );
-		}
-	}
-	
-	protected void
-	downloadSubscription(
-		final TOTorrent			torrent,
-		final InetSocketAddress	peer,
-		byte[]					subs_id,
-		int						version,
-		String					name,
-		final downloadListener	listener )
-	{
-		try{
-				// testing purposes, see if local exists
-			
-			LightWeightSeed lws = LightWeightSeedManager.getSingleton().get( new HashWrapper( torrent.getHash()));
-	
-			if ( lws != null ){
-				
-				log( "Light weight seed found" );
-				
-				listener.complete( lws.getDataLocation());
-				
-			}else{
-				String	sid = ByteFormatter.encodeString( subs_id );
-				
-				File	dir = getSubsDir();
-				
-				dir = new File( dir, "temp" );
-				
-				if ( !dir.exists()){
-					
-					if ( !dir.mkdirs()){
-						
-						throw( new IOException( "Failed to create dir '" + dir + "'" ));
-					}
-				}
-				
-				final File	torrent_file 	= new File( dir, sid + "_" + version + ".torrent" );
-				final File	data_file 		= new File( dir, sid + "_" + version + ".vuze" );
-	
-				PluginInterface pi = PluginInitializer.getDefaultInterface();
-			
-				final DownloadManager dm = pi.getDownloadManager();
-				
-				Download download = dm.getDownload( torrent.getHash());
-				
-				if ( download == null ){
-					
-					log( "Adding download for subscription '" + new String(torrent.getName()) + "'" );
-					
-					boolean is_update = getSubscriptionFromSID( subs_id ) != null;
-					
-					PlatformTorrentUtils.setContentTitle(torrent, (is_update?"Update":"Download") + " for subscription '" + name + "'" );
-					
-						// PlatformTorrentUtils.setContentThumbnail(torrent, thumbnail);
-						
-					TorrentUtils.setFlag( torrent, TorrentUtils.TORRENT_FLAG_LOW_NOISE, true );
-					
-					Torrent t = new TorrentImpl( torrent );
-					
-					t.setDefaultEncoding();
-					
-					t.writeToFile( torrent_file );
-					
-					download = dm.addDownload( t, torrent_file, data_file );
-					
-					download.setFlag( Download.FLAG_DISABLE_AUTO_FILE_MOVE, true );
-
-					download.setBooleanAttribute( ta_subs_download, true );
-					
-					Map rd = listener.getRecoveryData();
-					
-					if ( rd != null ){
-						
-						download.setMapAttribute( ta_subs_download_rd, rd );
-					}
-				}else{
-					
-					log( "Existing download found for subscription '" + new String(torrent.getName()) + "'" );
-				}
-				
-				final Download f_download = download;
-				
-				final TimerEventPeriodic[] event = { null };
-				
-				event[0] = 
-					SimpleTimer.addPeriodicEvent(
-						"SM:cancelTimer",
-						10*1000,
-						new TimerEventPerformer()
-						{
-							private long	start_time = SystemTime.getMonotonousTime();
-							
-							public void 
-							perform(
-								TimerEvent ev ) 
-							{
-								boolean	kill = false;
-								
-								try{	
-									Download download = dm.getDownload( torrent.getHash());
-									
-									if ( listener.isCancelled() || download == null ){
-										
-										kill = true;
-										
-									}else{
-										
-										int	state = download.getState();
-										
-										if ( state == Download.ST_ERROR ){
-											
-											log( "Download entered error state, removing" );
-											
-											kill = true;
-											
-										}else{
-											
-											long	now = SystemTime.getMonotonousTime();
-											
-											long	running_for = now - start_time;
-											
-											if ( running_for > 2*60*1000 ){
-												
-												DownloadScrapeResult scrape = download.getLastScrapeResult();
-												
-												if ( scrape == null || scrape.getSeedCount() <= 0 ){
-													
-													log( "Download has no seeds, removing" );
-													
-													kill = true;
-												}
-											}else if ( running_for > 4*60*1000 ){
-												
-												if ( download.getStats().getDownloaded() == 0 ){
-													
-													log( "Download has zero downloaded, removing" );
-													
-													kill = true;
-												}
-											}else if ( running_for > 10*60*1000 ){
-												
-												log( "Download hasn't completed in permitted time, removing" );
-												
-												kill = true;
-											}
-										}
-									}
-								}catch( Throwable e ){
-									
-									log( "Download failed", e );
-
-									kill = true;
-								}
-								
-								if ( kill && event[0] != null ){
-									
-									try{
-										event[0].cancel();
-										
-										if ( !listener.isCancelled()){
-																					
-											listener.failed( new SubscriptionException( "Download abandoned" ));
-										}
-									}finally{
-										
-										removeDownload( f_download, true );
-									
-										torrent_file.delete();
-									}
-								}
-							}
-						});
-				
-				download.addCompletionListener(
-					new DownloadCompletionListener()
-					{
-						public void 
-						onCompletion(
-							Download d ) 
-						{
-							listener.complete( d, torrent_file );
-						}
-					});
-				
-				if ( download.isComplete()){
-					
-					listener.complete( download, torrent_file  );
-					
-				}else{
-								
-					download.setForceStart( true );
-					
-					if ( peer != null ){
-					
-						download.addPeerListener(
-							new DownloadPeerListener()
-							{
-								public void
-								peerManagerAdded(
-									Download		download,
-									PeerManager		peer_manager )
-								{									
-									InetSocketAddress tcp = AddressUtils.adjustTCPAddress( peer, true );
-									InetSocketAddress udp = AddressUtils.adjustUDPAddress( peer, true );
-									
-									log( "    Injecting peer into download: " + tcp );
-
-									peer_manager.addPeer( tcp.getAddress().getHostAddress(), tcp.getPort(), udp.getPort(), true );
-								}
-								
-								public void
-								peerManagerRemoved(
-									Download		download,
-									PeerManager		peer_manager )
-								{							
-								}
-							});
-					}
-				}
-			}
-		}catch( Throwable e ){
-			
-			log( "Failed to add download", e );
-			
-			listener.failed( e );
-		}
-	}
-	
-	protected interface
-	downloadListener
-	{
-		public void
-		complete(
-			File		data_file );
-		
-		public void
-		complete(
-			Download	download,	
-			File		torrent_file );
-			
-		public void
-		failed(
-			Throwable	error );
-		
-		public Map
-		getRecoveryData();
-		
-		public boolean
-		isCancelled();
-	}
-	
-	protected void
-	updateSubscription(
-		final SubscriptionImpl		subs,
-		final int					new_version,
-		TOTorrent					torrent,
-		InetSocketAddress			peer )
-	{
-		log( "Subscription " + subs.getString() + " - update torrent: " + new String( torrent.getName()));
-
-		if ( !askIfCanUpgrade( subs, new_version )){
-			
-			return;
-		}
-			
-		downloadSubscription(
-			torrent,
-			peer,
-			subs.getShortID(),
-			new_version,
-			subs.getName(false),
-			new downloadListener()
-			{
-				public void
-				complete(
-					File		data_file )
-				{
-					updateSubscription( subs, data_file );
-				}
-				
-				public void
-				complete(
-					Download	download,	
-					File		torrent_file )
-				{
-					updateSubscription( subs, download, torrent_file, new File( download.getSavePath()));
-				}
-					
-				public void
-				failed(
-					Throwable	error )
-				{
-					log( "Failed to download subscription", error );
-				}
-				
-				public Map
-				getRecoveryData()
-				{
-					Map	rd = new HashMap();
-					
-					rd.put( "sid", subs.getShortID());
-					rd.put( "ver", new Long( new_version ));
-					
-					return( rd );
-				}
-				
-				public boolean
-				isCancelled()
-				{
-					return( false );
-				}
-			});
-	}
-
-	protected boolean
-	askIfCanUpgrade(
-		SubscriptionImpl		subs,
-		int						new_version )
-	{
-		subs.setHighestUserPromptedVersion( new_version );
-		
-		UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-		
-		String details = MessageText.getString(
-				"subscript.add.upgradeto.desc",
-				new String[]{ String.valueOf(new_version), subs.getName()});
-		
-		long res = ui_manager.showMessageBox(
-				"subscript.add.upgrade.title",
-				"!" + details + "!",
-				UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
-		
-		if ( res != UIManagerEvent.MT_YES ){	
-		
-			log( "    User declined upgrade" );
-			
-			return( false );
-		}
-		
-		return( true );
-	}
-	
-	protected boolean
-	recoverSubscriptionUpdate(
-		Download				download,
-		final Map				rd )
-	{
-		byte[]	sid 	= (byte[])rd.get( "sid" );
-		int		version = ((Long)rd.get( "ver" )).intValue();
-		
-		final SubscriptionImpl subs = getSubscriptionFromSID( sid );
-		
-		if ( subs == null ){
-		
-			log( "Can't recover '" + download.getName() + "' - subscription " + ByteFormatter.encodeString( sid ) +  " not found" );
-			
-			return( false );
-		}
-		
-		downloadSubscription(
-				((TorrentImpl)download.getTorrent()).getTorrent(),
-				null,
-				subs.getShortID(),
-				version,
-				subs.getName(false),
-				new downloadListener()
-				{
-					public void
-					complete(
-						File		data_file )
-					{
-						updateSubscription( subs, data_file );
-					}
-					
-					public void
-					complete(
-						Download	download,	
-						File		torrent_file )
-					{
-						updateSubscription( subs, download, torrent_file, new File( download.getSavePath()));
-					}
-						
-					public void
-					failed(
-						Throwable	error )
-					{
-						log( "Failed to download subscription", error );
-					}
-					
-					public Map
-					getRecoveryData()
-					{
-						return( rd );
-					}
-					
-					public boolean
-					isCancelled()
-					{
-						return( false );
-					}
-				});
-		
-		return( true );
-	}
-	
-	protected void
-	updateSubscription(
-		SubscriptionImpl		subs,
-		Download				download,
-		File					torrent_file,
-		File					data_file )
-	{
-		try{
-			removeDownload( download, false );
-		
-			try{				
-				updateSubscription( subs, data_file );
-											
-			}finally{
-				
-				if ( !data_file.delete()){
-					
-					log( "Failed to delete update file '" + data_file + "'" );
-				}
-				
-				if ( !torrent_file.delete()){
-					
-					log( "Failed to delete update torrent '" + torrent_file + "'" );
-				}
-			}
-		}catch( Throwable e ){
-			
-			log( "Failed to remove update download", e );
-		}
-	}
-	
-	protected void
-	removeDownload(
-		Download		download,
-		boolean			remove_data )
-	{
-		try{
-			download.stop();
-			
-		}catch( Throwable e ){
-		}
-		
-		try{
-			download.remove( true, remove_data );
-			
-			log( "Removed download '" + download.getName() + "'" );
-			
-		}catch( Throwable e ){
-			
-			log( "Failed to remove download '" + download.getName() + "'", e );
-		}
-	}
-	
-	protected void
-	updateSubscription(
-		SubscriptionImpl		subs,
-		File					data_location )
-	{
-		log( "Updating subscription '" + subs.getString() + " using '" + data_location + "'" );
-		
-		VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
-			
-		VuzeFile vf = vfh.loadVuzeFile( data_location.getAbsolutePath());
-						
-		vfh.handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_SUBSCRIPTION );
-	}
-	
-	protected MagnetPlugin
-	getMagnetPlugin()
-	{
-		PluginInterface  pi  = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass( MagnetPlugin.class );
-	
-		if ( pi == null ){
-			
-			return( null );
-		}
-		
-		return((MagnetPlugin)pi.getPlugin());
-	}
-	
-	protected Engine
-	getEngine(
-		SubscriptionImpl		subs,
-		Map						json_map,
-		boolean					local_only )
-	
-		throws SubscriptionException
-	{
-		long id = ((Long)json_map.get( "engine_id" )).longValue();
-		
-		Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().getEngine( id );
-		
-		if ( engine != null ){
-			
-			return( engine );
-		}
-
-		if ( !local_only ){
-			
-			try{
-				if ( id >= 0 && id < Integer.MAX_VALUE ){
-								
-					log( "Engine " + id + " not present, loading" );
-						
-						// vuze template but user hasn't yet loaded it
-						
-					try{
-						engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().addEngine( id );
-									
-						return( engine );
-						
-					}catch( Throwable e ){
-					
-						throw( new SubscriptionException( "Failed to load engine '" + id + "'", e ));
-					}
-				}
-			}catch( Throwable e ){
-				
-				log( "Failed to load search template", e );
-			}
-		}
-		
-		engine = subs.extractEngine( json_map, id );
-		
-		if ( engine != null ){
-			
-			return( engine );
-		}
-		
-		throw( new SubscriptionException( "Failed to extract engine id " + id ));
-	}
-	
-	protected SubscriptionResultImpl[]
-	loadResults(
-		SubscriptionImpl			subs )
-	{
-		List	results = new ArrayList();
-		
-		try{
-			File	f = getResultsFile( subs );
-			
-			Map	map = FileUtil.readResilientFile( f );
-			
-			List	list = (List)map.get( "results" );
-			
-			if ( list != null ){
-			
-				SubscriptionHistoryImpl	history = (SubscriptionHistoryImpl)subs.getHistory();
-				
-				for (int i=0;i<list.size();i++){
-					
-					Map	result_map =(Map)list.get(i);
-					
-					try{
-						SubscriptionResultImpl result = new SubscriptionResultImpl( history, result_map );
-						
-						results.add( result );
-						
-					}catch( Throwable e ){
-						
-						log( "Failed to decode result '" + result_map + "'", e );
-					}
-				}
-			}
-			
-		}catch( Throwable e ){
-			
-			log( "Failed to load results for '" + subs.getName() + "' - continuing with empty result set", e );
-		}
-		
-		return((SubscriptionResultImpl[])results.toArray( new SubscriptionResultImpl[results.size()] ));
-	}
-	
-	protected void
-  	setCategoryOnExisting(
-  		SubscriptionImpl	subscription,
-  		String				old_category,
-  		String				new_category )
-  	{
-		PluginInterface default_pi = PluginInitializer.getDefaultInterface();
-
-  		Download[] downloads 	= default_pi.getDownloadManager().getDownloads();
-  		 		 		
-  		for ( Download d: downloads ){
-  			 			
-  			if ( subscriptionExists( d, subscription )){
-  					
-				String existing = d.getAttribute( ta_category );
-
-				if ( existing == null || existing.equals( old_category )){
-					
-					d.setAttribute( ta_category, new_category );
-				}
-  			}
-  		}
-  	}
-	
-	public int
-	getMaxNonDeletedResults()
-	{
-		return( COConfigurationManager.getIntParameter( CONFIG_MAX_RESULTS ));
-	}
-	
-	public void
-	setMaxNonDeletedResults(
-		int		max )
-	{
-		if ( max != getMaxNonDeletedResults()){
-			
-			COConfigurationManager.setParameter( CONFIG_MAX_RESULTS, max );
-		}
-	}
-	
-	public boolean
-	getAutoStartDownloads()
-	{
-		return( COConfigurationManager.getBooleanParameter( CONFIG_AUTO_START_DLS ));		
-	}
-	
-	public void
-	setAutoStartDownloads(
-		boolean		auto_start )
-	{
-		if ( auto_start != getAutoStartDownloads()){
-			
-			COConfigurationManager.setParameter( CONFIG_AUTO_START_DLS, auto_start );
-		}		
-	}
-	
-	public int
-	getAutoStartMinMB()
-	{
-		return( COConfigurationManager.getIntParameter( CONFIG_AUTO_START_MIN_MB ));
-	}
-	
-	public void
-	setAutoStartMinMB(
-		int			mb )
-	{
-		if ( mb != getAutoStartMinMB()){
-			
-			COConfigurationManager.setParameter( CONFIG_AUTO_START_MIN_MB, mb );
-		}
-	}
-
-	public int
-	getAutoStartMaxMB()
-	{
-		return( COConfigurationManager.getIntParameter( CONFIG_AUTO_START_MAX_MB ));
-	}
-	
-	public void
-	setAutoStartMaxMB(
-		int			mb )
-	{
-		if ( mb != getAutoStartMaxMB()){
-			
-			COConfigurationManager.setParameter( CONFIG_AUTO_START_MAX_MB, mb );
-		}
-	}
-	
-	protected boolean
-	shouldAutoStart(
-		Torrent		torrent )
-	{
-		if ( getAutoStartDownloads()){
-			
-			long	min = getAutoStartMinMB()*1024*1024L;
-			long	max = getAutoStartMaxMB()*1024*1024L;
-			
-			if ( min <= 0 && max <= 0 ){
-				
-				return( true );
-			}
-			
-			long size = torrent.getSize();
-			
-			if ( min > 0 && size < min ){
-				
-				return( false );
-			}
-			
-			if ( max > 0 && size > max ){
-				
-				return( false );
-			}
-			
-			return( true );
-			
-		}else{
-			
-			return( false );
-		}
-	}
-	
-	protected void
- 	saveResults(
- 		SubscriptionImpl			subs,
- 		SubscriptionResultImpl[]	results )
- 	{
-		try{
-			File	f = getResultsFile( subs );
-	
-			Map	map = new HashMap();
-			
-			List	list = new ArrayList( results.length );
-			
-			map.put( "results", list );
-			
-			for (int i=0;i<results.length;i++){
-				
-				list.add( results[i].toBEncodedMap());
-			}
-			
-			FileUtil.writeResilientFile( f, map );
-			
-		}catch( Throwable e ){
-			
-			log( "Failed to save results for '" + subs.getName(), e );
-		}
- 	}
-	
-	private void
-	loadConfig()
-	{
-		if ( !FileUtil.resilientConfigFileExists( CONFIG_FILE )){
-			
-			return;
-		}
-		
-		log( "Loading configuration" );
-		
-		boolean	some_are_mine = false;
-		
-		synchronized( this ){
-			
-			Map map = FileUtil.readResilientConfigFile( CONFIG_FILE );
-			
-			List	l_subs = (List)map.get( "subs" );
-			
-			if ( l_subs != null ){
-				
-				for (int i=0;i<l_subs.size();i++){
-					
-					Map	m = (Map)l_subs.get(i);
-					
-					try{
-						SubscriptionImpl sub = new SubscriptionImpl( this, m );
-
-						int index = Collections.binarySearch(subscriptions, sub, new Comparator<Subscription>() {
-							public int compare(Subscription arg0, Subscription arg1) {
-								return arg0.getID().compareTo(arg1.getID());
-							}
-						});
-						if (index < 0) {
-							index = -1 * index - 1; // best guess
-
-							subscriptions.add( index, sub );
-						}
-
-						if ( sub.isMine()){
-							
-							some_are_mine = true;
-						}
-						
-						log( "    loaded " + sub.getString());
-						
-					}catch( Throwable e ){
-						
-						log( "Failed to import subscription from " + m, e );
-					}
-				}
-			}
-		}
-		
-		if ( some_are_mine ){
-							
-			addMetaSearchListener();
-		}
-	}
-	
-	protected void
-	configDirty(
-		SubscriptionImpl		subs )
-	{
-		changeSubscription( subs );
-		
-		configDirty();
-	}
-	
-	protected void
-	configDirty()
-	{
-		synchronized( this ){
-			
-			if ( config_dirty ){
-				
-				return;
-			}
-			
-			config_dirty = true;
-		
-			new DelayedEvent( 
-				"Subscriptions:save", 5000,
-				new AERunnable()
-				{
-					public void 
-					runSupport() 
-					{
-						synchronized( SubscriptionManagerImpl.this ){
-							
-							if ( !config_dirty ){
-
-								return;
-							}
-							
-							saveConfig();
-						}	
-					}
-				});
-		}
-	}
-	
-	protected void
-	saveConfig()
-	{
-		log( "Saving configuration" );
-		
-		synchronized( this ){
-			
-			config_dirty = false;
-			
-			if ( subscriptions.size() == 0 ){
-				
-				FileUtil.deleteResilientConfigFile( CONFIG_FILE );
-				
-			}else{
-				
-				Map map = new HashMap();
-				
-				List	l_subs = new ArrayList();
-				
-				map.put( "subs", l_subs );
-				
-				Iterator	it = subscriptions.iterator();
-				
-				while( it.hasNext()){
-					
-					SubscriptionImpl sub = (SubscriptionImpl)it.next();
-						
-					try{
-						l_subs.add( sub.toMap());
-						
-					}catch( Throwable e ){
-						
-						log( "Failed to save subscription " + sub.getString(), e );
-					}
-				}
-				
-				FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
-			}
-		}
-	}
-	
-	private byte[]
-	getKeyBytes( 
-		String		key )
-	{
-		try{
-			return( key.getBytes( "UTF-8" ));
-			
-		}catch( UnsupportedEncodingException e ){
-			
-			Debug.out( e );
-			
-			return( key.getBytes());
-		}
-	}
-	private AEDiagnosticsLogger
-	getLogger()
-	{
-			// sync not required (and has caused deadlock) as AEDiagnostics handles singleton
-		
-		if ( logger == null ){
-			
-			logger = AEDiagnostics.getLogger( LOGGER_NAME );
-		}
-		
-		return( logger );
-	}
-	
-	public void 
-	log(
-		String 		s,
-		Throwable 	e )
-	{
-		AEDiagnosticsLogger diag_logger = getLogger();
-		
-		diag_logger.log( s );
-		diag_logger.log( e );
-	}
-	
-	public void 
-	log(
-		String 	s )
-	{
-		AEDiagnosticsLogger diag_logger = getLogger();
-		
-		diag_logger.log( s );
-	}
-	
-	public void
-	addListener(
-		SubscriptionManagerListener	listener )
-	{
-		listeners.add( listener );
-	}
-	
-	public void
-	removeListener(
-		SubscriptionManagerListener	listener )
-	{
-		listeners.remove( listener );
-	}
-	
-	public void
-	generate(
-		IndentWriter		writer )
-	{
-		writer.println( "Subscriptions" );
-			
-		try{
-			writer.indent();
-
-			Subscription[] subs = getSubscriptions();
-			
-			for (int i=0;i<subs.length;i++){
-				
-				SubscriptionImpl sub = (SubscriptionImpl)subs[i];
-				
-				sub.generate( writer );
-			}
-			
-		}finally{
-			
-			writer.exdent();
-		}
-	}
-	
-	private class
-	searchMatcher
-	{
-		private String[]	bits;
-		private int[]		bit_types;
-		private Pattern[]	bit_patterns;
-
-		protected 
-		searchMatcher(
-			String		term )
-		{
-			bits = Constants.PAT_SPLIT_SPACE.split(term.toLowerCase() );
-			
-			bit_types 		= new int[bits.length];
-			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 ){
-						}
-					}
-				}
-			}
-		}
-		
-		public boolean
-		matches(
-			String		str )
-		{			
-			// 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'
-									
-			str = str.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 = str.contains( bit );
-						
-					}else{
-					
-						hit = bit_patterns[i].matcher( str ).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;
-						}
-					}
-				}
-			}
-			
-			boolean res = match && at_least_one;
-				
-			return( res );
-		}
-	}
-	
-	public static void
-	main(
-		String[]	args )
-	{
-		final String 	NAME 	= "lalalal";
-		final String	URL_STR	= "http://www.vuze.com/feed/publisher/ALL/1";
-		
-		try{
-			//AzureusCoreFactory.create();
-			/*
-			Subscription subs = 
-				getSingleton(true).createSingletonRSS(
-						NAME,
-						new URL( URL_STR ),
-						240 );
-			
-			subs.getVuzeFile().write( new File( "C:\\temp\\srss.vuze" ));
-			
-			subs.remove();
-			*/
-			
-			VuzeFile	vf = VuzeFileHandler.getSingleton().create();
-			
-			Map	map = new HashMap();
-			
-			map.put( "name", NAME );
-			map.put( "url", URL_STR );
-			map.put( "public", new Long( 0 ));
-			map.put( "check_interval_mins", new Long( 345 ));
-			
-			vf.addComponent( VuzeFileComponent.COMP_TYPE_SUBSCRIPTION_SINGLETON, map );
-			
-			vf.write( new File( "C:\\temp\\srss_2.vuze" ) );
-
-		}catch( Throwable e ){
-			
-			e.printStackTrace();
-		}
-	}
-}
+/*
+ * Created on Jul 11, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs.impl;
+
+import java.io.*;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.security.KeyPair;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import org.bouncycastle.util.encoders.Base64;
+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.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.PluginException;
+import org.gudy.azureus2.plugins.utils.Utilities;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.download.*;
+import org.gudy.azureus2.plugins.peers.PeerManager;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
+import org.gudy.azureus2.plugins.torrent.TorrentManager;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.UIManagerEvent;
+import org.gudy.azureus2.plugins.utils.DelayedTask;
+import org.gudy.azureus2.plugins.utils.StaticUtilities;
+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 org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl;
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.custom.Customization;
+import com.aelitis.azureus.core.custom.CustomizationManager;
+import com.aelitis.azureus.core.custom.CustomizationManagerFactory;
+import com.aelitis.azureus.core.lws.LightWeightSeed;
+import com.aelitis.azureus.core.lws.LightWeightSeedManager;
+import com.aelitis.azureus.core.messenger.config.PlatformSubscriptionsMessenger;
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.MetaSearchListener;
+import com.aelitis.azureus.core.metasearch.MetaSearchManagerFactory;
+import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
+import com.aelitis.azureus.core.metasearch.impl.web.rss.RSSEngine;
+import com.aelitis.azureus.core.security.CryptoECCUtils;
+import com.aelitis.azureus.core.subs.*;
+import com.aelitis.azureus.core.subs.SubscriptionUtils.SubscriptionDownloadDetails;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+import com.aelitis.azureus.core.vuzefile.*;
+import com.aelitis.azureus.plugins.dht.*;
+import com.aelitis.azureus.plugins.magnet.MagnetPlugin;
+import com.aelitis.azureus.plugins.magnet.MagnetPluginProgressListener;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginUtils;
+import com.aelitis.azureus.util.ImportExportUtils;
+import com.aelitis.azureus.util.UrlFilter;
+import com.aelitis.net.magneturi.MagnetURIHandler;
+
+
+public class 
+SubscriptionManagerImpl 
+	implements SubscriptionManager, AEDiagnosticsEvidenceGenerator
+{	
+	private static final String	CONFIG_FILE = "subscriptions.config";
+	private static final String	LOGGER_NAME = "Subscriptions";
+
+	private static final String CONFIG_MAX_RESULTS 			= "subscriptions.max.non.deleted.results";
+	private static final String CONFIG_AUTO_START_DLS 		= "subscriptions.auto.start.downloads";
+	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	CONFIG_RSS_ENABLE			= "subscriptions.config.rss_enable";
+
+	private static final String	CONFIG_ENABLE_SEARCH			= "subscriptions.config.search_enable";
+	
+	private static final String	CONFIG_HIDE_SEARCH_TEMPLATES	= "subscriptions.config.hide_search_templates";
+	
+	private static final String	CONFIG_DL_SUBS_ENABLE		= "subscriptions.config.dl_subs_enable";
+	private static final String	CONFIG_DL_RATE_LIMITS		= "subscriptions.config.rate_limits";
+
+	private static final int DELETE_UNUSED_AFTER_MILLIS = 2*7*24*60*60*1000;
+	
+	
+	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()
+			{
+				public void
+				process(
+					VuzeFile[]		files,
+					int				expected_types )
+				{
+					for (int i=0;i<files.length;i++){
+						
+						VuzeFile	vf = files[i];
+						
+						VuzeFileComponent[] comps = vf.getComponents();
+						
+						for (int j=0;j<comps.length;j++){
+							
+							VuzeFileComponent comp = comps[j];
+							
+							int	type = comp.getType();
+							
+							if ( 	type == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION ||
+									type == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION_SINGLETON ){
+								
+								try{
+									Subscription subs = ((SubscriptionManagerImpl)getSingleton( false )).importSubscription(
+											type,
+											comp.getContent(),
+											( expected_types & 
+												( VuzeFileComponent.COMP_TYPE_SUBSCRIPTION | VuzeFileComponent.COMP_TYPE_SUBSCRIPTION_SINGLETON )) == 0 );
+									
+									comp.setProcessed();
+									
+									comp.setData( Subscription.VUZE_FILE_COMPONENT_SUBSCRIPTION_KEY, subs );
+									
+								}catch( Throwable e ){
+									
+									Debug.printStackTrace(e);
+								}
+							}
+						}
+					}
+				}
+			});		
+	}
+		
+	public static SubscriptionManager
+	getSingleton(
+		boolean		stand_alone )
+	{
+		preInitialise();
+		
+		synchronized( SubscriptionManagerImpl.class ){
+			
+			if ( singleton != null ){
+			
+				return( singleton );
+			}
+			
+			singleton = new SubscriptionManagerImpl( stand_alone );
+		}
+		
+			// saw deadlock here when adding core listener while synced on class - rework
+			// to avoid 
+		
+		if ( !stand_alone ){
+			
+			singleton.initialise();
+		}
+		
+		return( singleton );
+	}
+	
+	
+	private boolean		started;
+		
+	private static final int	TIMER_PERIOD		= 30*1000;
+	
+	private static final int	ASSOC_CHECK_PERIOD	= 5*60*1000;
+	private static final int	ASSOC_CHECK_TICKS	= ASSOC_CHECK_PERIOD/TIMER_PERIOD;
+	
+	private static final int	CHAT_CHECK_PERIOD	= 3*60*1000;
+	private static final int	CHAT_CHECK_TICKS	= CHAT_CHECK_PERIOD/TIMER_PERIOD;
+
+	private static final int	SERVER_PUB_CHECK_PERIOD	= 10*60*1000;
+	private static final int	SERVER_PUB_CHECK_TICKS	= SERVER_PUB_CHECK_PERIOD/TIMER_PERIOD;
+	
+	private static final int	TIDY_POT_ASSOC_PERIOD	= 30*60*1000;
+	private static final int	TIDY_POT_ASSOC_TICKS	= TIDY_POT_ASSOC_PERIOD/TIMER_PERIOD;
+
+	private static final int	SET_SELECTED_PERIOD		= 23*60*60*1000;
+	private static final int	SET_SELECTED_FIRST_TICK	= 3*60*1000 /TIMER_PERIOD;
+	private static final int	SET_SELECTED_TICKS		= SET_SELECTED_PERIOD/TIMER_PERIOD;
+
+	private static final Object	SP_LAST_ATTEMPTED	= new Object();
+	private static final Object	SP_CONSEC_FAIL		= new Object();
+	
+	private AzureusCore		azureus_core;
+	
+	private volatile DHTPlugin	dht_plugin;
+	
+	private List<SubscriptionImpl>		subscriptions	= new ArrayList<SubscriptionImpl>();
+	
+	private boolean	config_dirty;
+	
+	private static final int PUB_ASSOC_CONC_MAX				= 3;
+	private static final int PUB_SLEEPING_ASSOC_CONC_MAX	= 1;
+	
+	private int		publish_associations_active;
+	private boolean	publish_next_asyc_pending;
+	
+	private boolean publish_subscription_active;
+	
+	private TorrentAttribute		ta_subs_download;
+	private TorrentAttribute		ta_subs_download_rd;
+	private TorrentAttribute		ta_subscription_info;
+	private TorrentAttribute		ta_category;
+	private TorrentAttribute		ta_networks;
+	
+	private boolean					periodic_lookup_in_progress;
+	private int						priority_lookup_pending;
+	
+	private CopyOnWriteList<SubscriptionManagerListener>			listeners = new CopyOnWriteList<SubscriptionManagerListener>();
+	
+	private SubscriptionSchedulerImpl	scheduler;
+	
+	private List<Object[]>				potential_associations	= new ArrayList<Object[]>();
+	private Map<HashWrapper,Object[]>	potential_associations2	= new HashMap<HashWrapper,Object[]>();
+	
+	private boolean					meta_search_listener_added;
+	
+	private Pattern					exclusion_pattern = Pattern.compile( "azdev[0-9]+\\.azureus\\.com" );
+	
+	private SubscriptionRSSFeed		rss_publisher;
+	
+	private AEDiagnosticsLogger		logger;
+	
+	
+	protected
+	SubscriptionManagerImpl(
+		boolean	stand_alone )
+	{
+		if ( !stand_alone ){
+			
+			loadConfig();
+	
+			AEDiagnostics.addEvidenceGenerator( this );
+			
+			CustomizationManager cust_man = CustomizationManagerFactory.getSingleton();
+			
+			Customization cust = cust_man.getActiveCustomization();
+			
+			if ( cust != null ){
+				
+				String cust_name 	= COConfigurationManager.getStringParameter( "subscriptions.custom.name", "" );
+				String cust_version = COConfigurationManager.getStringParameter( "subscriptions.custom.version", "0" );
+				
+				boolean	new_name 	= !cust_name.equals( cust.getName());
+				boolean	new_version = org.gudy.azureus2.core3.util.Constants.compareVersions( cust_version, cust.getVersion() ) < 0;
+				
+				if ( new_name || new_version ){
+
+					log( "Customization: checking templates for " + cust.getName() + "/" + cust.getVersion());
+					
+					try{
+						InputStream[] streams = cust.getResources( Customization.RT_SUBSCRIPTIONS );
+						
+						for (int i=0;i<streams.length;i++){
+							
+							InputStream is = streams[i];
+							
+							try{
+								VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile(is);
+								
+								if ( vf != null ){
+									
+									VuzeFileComponent[] comps = vf.getComponents();
+									
+									for (int j=0;j<comps.length;j++){
+										
+										VuzeFileComponent comp = comps[j];
+										
+										int type = comp.getType();
+										
+										if ( 	type == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION ||
+												type == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION_SINGLETON	){
+											
+											try{
+												importSubscription(
+														type,
+														comp.getContent(),
+														false );
+												
+												comp.setProcessed();
+												
+											}catch( Throwable e ){
+												
+												Debug.printStackTrace(e);
+											}
+										}
+									}
+								}
+							}finally{
+								
+								try{
+									is.close();
+									
+								}catch( Throwable e ){
+								}
+							}
+						}
+					}finally{
+						
+						COConfigurationManager.setParameter( "subscriptions.custom.name", cust.getName());
+						COConfigurationManager.setParameter( "subscriptions.custom.version", cust.getVersion());
+					}
+				}
+			}
+			
+			scheduler = new SubscriptionSchedulerImpl( this );
+		}
+	}
+	
+	protected void
+	initialise()
+	{
+		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+			public void azureusCoreRunning(final AzureusCore core) {
+				initWithCore(core);
+			}
+		});
+	}
+
+	protected void
+	initWithCore(
+		AzureusCore 	_core )
+	{
+		synchronized( this ){
+			
+			if ( started ){
+				
+				return;
+			}
+			
+			started	= true;
+		}
+
+		azureus_core = _core;
+		
+		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" );
+		ta_subs_download_rd 	= tm.getPluginAttribute( "azsubs.subs_dl_rd" );
+		ta_subscription_info 	= tm.getPluginAttribute( "azsubs.subs_info" );
+		ta_category				= tm.getAttribute( TorrentAttribute.TA_CATEGORY );
+		ta_networks 			= tm.getAttribute( TorrentAttribute.TA_NETWORKS );
+
+		PluginInterface  dht_plugin_pi  = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass( DHTPlugin.class );
+				
+		if ( dht_plugin_pi != null ){
+			
+			dht_plugin = (DHTPlugin)dht_plugin_pi.getPlugin();
+
+			/*
+			if ( Constants.isCVSVersion()){
+				
+				addListener(
+						new SubscriptionManagerListener()
+						{
+							public void 
+							subscriptionAdded(
+								Subscription subscription ) 
+							{
+							}
+				
+							public void
+							subscriptionChanged(
+								Subscription		subscription )
+							{
+							}
+							
+							public void 
+							subscriptionRemoved(
+								Subscription subscription ) 
+							{
+							}
+							
+							public void 
+							associationsChanged(
+								byte[] hash )
+							{
+								System.out.println( "Subscriptions changed: " + ByteFormatter.encodeString( hash ));
+								
+								Subscription[] subs = getKnownSubscriptions( hash );
+							
+								for (int i=0;i<subs.length;i++){
+									
+									System.out.println( "    " + subs[i].getString());
+								}
+							}
+						});	
+			}
+			*/
+			
+			default_pi.getDownloadManager().addListener(
+				new DownloadManagerListener()
+				{
+					public void
+					downloadAdded(
+						Download	download )
+					{
+						Torrent	torrent = download.getTorrent();
+						
+						if ( torrent != null ){
+							
+							byte[]	hash = torrent.getHash();
+							
+							Object[] entry;
+							
+							synchronized( potential_associations2 ){
+								
+								entry = (Object[])potential_associations2.remove( new HashWrapper( hash ));
+							}
+							
+							if ( entry != null ){
+								
+								SubscriptionImpl[] subs = (SubscriptionImpl[])entry[0];
+								
+								String	subs_str = "";
+								for (int i=0;i<subs.length;i++){
+									subs_str += (i==0?"":",") + subs[i].getName();
+								}
+								
+								log( "Applying deferred asocciation for " + ByteFormatter.encodeString( hash ) + " -> " + subs_str );
+								
+								recordAssociationsSupport(
+									hash,
+									subs,
+									((Boolean)entry[1]).booleanValue());
+							}
+						}
+					}
+					
+					public void
+					downloadRemoved(
+						Download	download )
+					{	
+					}
+				},
+				false );
+			
+			TorrentUtils.addTorrentAttributeListener(
+				new TorrentUtils.torrentAttributeListener()
+				{
+					public void 
+					attributeSet(
+						TOTorrent 	torrent,
+						String 		attribute, 
+						Object 		value )
+					{
+						if ( attribute == TorrentUtils.TORRENT_AZ_PROP_OBTAINED_FROM ){
+							
+							try{
+								checkPotentialAssociations( torrent.getHash(), (String)value );
+								
+							}catch( Throwable e ){
+								
+								Debug.printStackTrace(e);
+							}
+						}
+					}
+				});
+				
+			DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "Subscriptions", 
+					new Runnable()
+					{
+						public void 
+						run() 
+						{
+							new AEThread2( "Subscriptions:delayInit", true )
+							{
+								public void
+								run()
+								{
+									asyncInit();
+								}
+							}.start();
+							
+						}
+						
+						protected void
+						asyncInit()
+						{
+							Download[] downloads = default_pi.getDownloadManager().getDownloads();
+									
+							for (int i=0;i<downloads.length;i++){
+								
+								Download download = downloads[i];
+								
+								if ( download.getBooleanAttribute( ta_subs_download )){
+									
+									Map	rd = download.getMapAttribute( ta_subs_download_rd );
+									
+									boolean	delete_it;
+									
+									if ( rd == null ){
+										
+										delete_it = true;
+										
+									}else{
+										
+										delete_it = !recoverSubscriptionUpdate( download, rd );
+									}
+									
+									if ( delete_it ){
+										
+										removeDownload( download, true );
+									}
+								}
+							}
+								
+							default_pi.getDownloadManager().addListener(
+								new DownloadManagerListener()
+								{
+									public void
+									downloadAdded(
+										final Download	download )
+									{
+											// if ever changed to handle non-persistent then you need to fix init deadlock
+											// potential with share-hoster plugin
+										
+										if ( !downloadIsIgnored( download )){
+											
+											if ( !dht_plugin.isInitialising()){
+								
+													// if new download then we want to check out its subscription status 
+												
+												lookupAssociations( download.getMapAttribute( ta_subscription_info ) == null );
+												
+											}else{
+												
+												new AEThread2( "Subscriptions:delayInit", true )
+												{
+													public void
+													run()
+													{
+														lookupAssociations( download.getMapAttribute( ta_subscription_info ) == null );
+													}
+												}.start();
+											}
+										}
+									}
+									
+									public void
+									downloadRemoved(
+										Download	download )
+									{
+									}
+								},
+								false );
+							
+							for (int i=0;i<PUB_ASSOC_CONC_MAX;i++){
+							
+								if ( publishAssociations()){
+									
+									break;
+								}
+							}
+							
+							publishSubscriptions();
+							
+							COConfigurationManager.addParameterListener(
+									CONFIG_MAX_RESULTS,
+									new ParameterListener()
+									{
+										public void 
+										parameterChanged(
+											String	 name )
+										{
+											final int	max_results = COConfigurationManager.getIntParameter( CONFIG_MAX_RESULTS );
+											
+											new AEThread2( "Subs:max results changer", true )
+											{
+												public void
+												run()
+												{
+													checkMaxResults( max_results );
+												}
+											}.start();
+										}
+									});
+							
+							SimpleTimer.addPeriodicEvent(
+									"SubscriptionChecker",
+									TIMER_PERIOD,
+									new TimerEventPerformer()
+									{
+										private int	ticks;
+										
+										public void 
+										perform(
+											TimerEvent event )
+										{
+											ticks++;
+											
+											checkStuff( ticks );
+										}
+									});
+						}
+					});
+		
+			delayed_task.queue();
+		}
+		
+		if ( isSearchEnabled()){
+			
+			try{
+				default_pi.getUtilities().registerSearchProvider(
+					new SearchProvider()
+					{
+						private Map<Integer,Object>	properties = new HashMap<Integer, Object>();
+						
+						{
+							properties.put( PR_NAME, MessageText.getString( "ConfigView.section.Subscriptions" ));
+							
+							try{
+								URL url = 
+									MagnetURIHandler.getSingleton().registerResource(
+										new MagnetURIHandler.ResourceProvider()
+										{
+											public String
+											getUID()
+											{
+												return( SubscriptionManager.class.getName() + ".2" );
+											}
+											
+											public String
+											getFileType()
+											{
+												return( "png" );
+											}
+													
+											public byte[]
+											getData()
+											{
+												InputStream is = getClass().getClassLoader().getResourceAsStream( "com/aelitis/azureus/ui/images/subscription_icon_1616.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
+						{		
+							try{
+								return( searchSubscriptions( search_parameters, observer ));
+								
+							}catch( Throwable e ){
+								
+								throw( new SearchException( "Search failed", e ));
+							}
+						}
+						
+						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" );
+			}
+		}
+		
+		default_pi.getUtilities().registerJSONRPCServer(
+			new Utilities.JSONServer()
+			{
+				private List<String>	methods = new ArrayList<String>();
+				
+				{
+					methods.add( "vuze-subs-list" );
+				}
+				
+				public String
+				getName()
+				{
+					return( "Subscriptions" );
+				}
+				
+				public List<String> 
+				getSupportedMethods() 
+				{
+					return( methods );
+				}
+				
+				public Map 
+				call(
+					String 		method, 
+					Map		 	args )
+						
+					throws PluginException 
+				{
+					throw( new PluginException( "derp" ));
+				}
+			});
+	}
+
+	protected Object[]
+	getSearchTemplateVuzeFile(
+		SubscriptionImpl	sub )
+	{
+		try{
+			String subs_url_str = ((RSSEngine)sub.getEngine()).getSearchUrl( true );
+			
+			URL subs_url = new URL( subs_url_str );
+			
+			final byte[] vf_bytes = FileUtil.readInputStreamAsByteArray(subs_url.openConnection().getInputStream());
+
+			VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( vf_bytes );
+			
+			if ( MetaSearchManagerFactory.getSingleton().isImportable( vf )){
+	
+				return( new Object[]{ vf, vf_bytes });
+			}
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+		
+		return( null );
+	}
+	
+	public boolean 
+	isSearchTemplateImportable(
+		SubscriptionImpl	sub )
+	{
+		try{
+			String subs_url_str = ((RSSEngine)sub.getEngine()).getSearchUrl( true );
+			
+			URL subs_url = new URL( subs_url_str );
+			
+			final byte[] vf_bytes = FileUtil.readInputStreamAsByteArray(subs_url.openConnection().getInputStream());
+
+			VuzeFile vf = VuzeFileHandler.getSingleton().loadVuzeFile( vf_bytes );
+			
+			return( MetaSearchManagerFactory.getSingleton().isImportable( vf ));
+	
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+		
+		return( false );
+	}
+	
+	public SearchInstance
+	searchSubscriptions(
+		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 ){
+		
+			try{
+				observer.complete();
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}else{
+		
+			new AEThread2( "Subscriptions:search", true )
+			{
+				public void
+				run()
+				{
+					final Set<String>	hashes = new HashSet<String>();
+					
+					searchMatcher	matcher = new searchMatcher( term );
+
+					try{				
+						List<SubscriptionResult>	matches = matchSubscriptionResults( matcher );
+							
+						for ( final SubscriptionResult result: matches ){
+							
+							final Map result_properties = result.toPropertyMap();
+							
+							byte[] hash = (byte[])result_properties.get( SearchResult.PR_HASH );
+														
+							if ( hash != null ){
+															
+								String hash_str = Base32.encode( hash );
+							
+								if ( hashes.contains( hash_str )){
+								
+									continue;
+								}
+							
+								hashes.add( hash_str );
+							}
+							
+							SearchResult search_result = 
+								new SearchResult()
+								{
+									public Object
+									getProperty(
+										int		property_name )
+									{
+										return( result_properties.get( property_name ));
+									}
+								};
+						
+							try{
+								observer.resultReceived( si, search_result );
+								
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}
+												
+						Map<String,Object[]> template_matches = new HashMap<String, Object[]>();
+								
+						Engine[] engines = MetaSearchManagerFactory.getSingleton().getMetaSearch().getEngines( false, false );
+						
+						Map<Subscription,List<String>>	sub_dl_name_map = null;
+						
+						for ( Subscription sub: getSubscriptions( false )){
+							
+							if ( !sub.isSearchTemplate()){
+								
+								continue;
+							}
+							
+							String	sub_name = sub.getName(false);
+														
+							Engine sub_engine = sub.getEngine();
+							
+							if ( sub_engine.isActive() || !(sub_engine instanceof RSSEngine )){
+								
+								continue;
+							}
+							
+							int	pos = sub_name.indexOf( ":" );
+							
+							String t_name = sub_name.substring( pos+1 );
+							
+							pos	= t_name.indexOf( "(v" );
+							
+							int t_ver;
+							
+							if ( pos == -1 ){
+								
+								t_ver = 1;
+								
+							}else{
+								
+								String s = t_name.substring( pos+2, t_name.length()-1);
+								
+								t_name = t_name.substring( 0, pos );
+								
+								try{
+							
+									t_ver = Integer.parseInt(s);
+									
+								}catch( Throwable e ){
+									
+									t_ver = 1;
+								}
+							}
+							
+							t_name = t_name.trim();
+							
+							boolean skip = false;
+							
+							for ( Engine e: engines ){
+								
+								if ( e != sub_engine && e.sameLogicAs( sub_engine )){
+									
+									skip = true;
+									
+									break;
+								}
+								
+								if ( e.getName().equalsIgnoreCase( t_name )){
+									
+									if ( e.getVersion() >= t_ver ){
+										
+										skip = true;
+									}
+								}
+							}
+							
+							if ( skip ){
+								
+								continue;
+							}
+							
+							if ( sub_dl_name_map == null ){
+								
+								sub_dl_name_map = new HashMap<Subscription, List<String>>();
+								
+								SubscriptionDownloadDetails[] sdds = SubscriptionUtils.getAllCachedDownloadDetails( azureus_core );
+								
+								for ( SubscriptionDownloadDetails sdd: sdds ){
+									
+									String name = sdd.getDownload().getDisplayName();
+									
+									if ( matcher.matches( name )){
+										
+										Subscription[] x = sdd.getSubscriptions();
+										
+										for ( Subscription s: x ){
+											
+											List<String> g = sub_dl_name_map.get( s );
+											
+											if ( g == null ){
+												
+												g = new ArrayList<String>();
+												
+												sub_dl_name_map.put( s, g );
+											}
+											
+											g.add( name );
+										}
+									}
+								}
+							}
+							
+							List<String> names = sub_dl_name_map.get( sub );
+							
+							if ( names == null ){
+								
+								continue;
+							}
+													
+							String key = t_name.toLowerCase();
+							
+							Object[] entry = template_matches.get( key );
+							
+							if ( entry == null ){
+								
+								entry = new Object[]{ sub, t_ver };
+								
+								template_matches.put( key, entry );
+								
+							}else{
+								
+								if ( t_ver > (Integer)entry[1]){
+									
+									entry[0]	= sub;
+									entry[1]	= t_ver;
+								}
+							}
+						}
+						
+						List<SubscriptionImpl>	interesting = new ArrayList<SubscriptionImpl>();
+						
+						for ( Object[] entry: template_matches.values()){
+						
+							interesting.add((SubscriptionImpl)entry[0]);
+						}
+						
+						Collections.sort(
+							interesting,
+							new Comparator<Subscription>()
+							{
+								public int 
+								compare(
+									Subscription o1,
+									Subscription o2) 
+								{
+									long res = o2.getCachedPopularity() - o1.getCachedPopularity();
+									
+									if ( res < 0 ){
+										return( -1 );
+									}else if ( res > 0 ){
+										return( 1 );
+									}else{
+										return( 0 );
+									}
+								}
+							});
+						
+						int	added = 0;
+						
+						for ( final SubscriptionImpl sub: interesting ){
+								
+							if ( added >= 3 ){
+								
+								break;
+							}
+							
+							try{
+								Object[] vf_entry = getSearchTemplateVuzeFile( sub );
+								
+								if ( vf_entry != null ){
+									
+									final byte[] vf_bytes = (byte[])vf_entry[1];
+									
+									final URL url = 
+										MagnetURIHandler.getSingleton().registerResource(
+											new MagnetURIHandler.ResourceProvider()
+											{
+												public String
+												getUID()
+												{
+													return( SubscriptionManager.class.getName() + ".sid." + sub.getID() );
+												}
+												
+												public String
+												getFileType()
+												{
+													return( "vuze" );
+												}
+														
+												public byte[]
+												getData()
+												{
+													return( vf_bytes );
+												}
+											});
+											
+									SearchResult search_result = 
+										new SearchResult()
+										{
+											public Object
+											getProperty(
+												int		property_name )
+											{
+												if ( property_name == SearchResult.PR_NAME ){
+													
+													return( sub.getName());
+													
+												}else if ( 	property_name == SearchResult.PR_DOWNLOAD_LINK ||
+															property_name == SearchResult.PR_DOWNLOAD_BUTTON_LINK ){
+													
+													return( url.toExternalForm());
+													
+												}else if ( property_name == SearchResult.PR_PUB_DATE ){
+													
+													return( new Date(sub.getAddTime()));
+													
+												}else if ( property_name == SearchResult.PR_SIZE ){
+													
+													return( 1024L );
+													
+												}else if ( 	property_name == SearchResult.PR_SEED_COUNT ||
+															property_name == SearchResult.PR_VOTES ){
+																							
+													return((long)sub.getCachedPopularity());
+													
+												}else if ( property_name == SearchResult.PR_RANK ){
+												
+													return( 100L );
+												}
+												
+												return( null );
+											}
+										};
+							
+									added++;
+										
+									try{
+										observer.resultReceived( si, search_result );
+										
+									}catch( Throwable e ){
+										
+										Debug.out( e );
+									}
+								}
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+						
+					}finally{
+						
+						observer.complete();
+					}
+				}
+			}.start();
+		}
+		
+		return( si );
+	}
+	
+	private List<SubscriptionResult>
+	matchSubscriptionResults(
+		searchMatcher	matcher  )
+	{
+		List<SubscriptionResult> result = new ArrayList<SubscriptionResult>();
+				
+		for ( Subscription sub: getSubscriptions( true )){
+			
+			SubscriptionResult[] results = sub.getResults( false );
+			
+			for ( SubscriptionResult r: results ){
+				
+				Map properties = r.toPropertyMap();
+				
+				String name = (String)properties.get( SearchResult.PR_NAME );
+				
+				if ( name == null ){
+					
+					continue;
+				}
+				
+				if ( matcher.matches( name )){
+					
+					result.add( r );
+				}
+			}
+		}
+		
+		return( result );
+	}
+	
+	protected void
+	checkMaxResults(
+		int		max )
+	{
+		Subscription[] subs = getSubscriptions();
+		
+		for (int i=0;i<subs.length;i++){
+			
+			((SubscriptionHistoryImpl)subs[i].getHistory()).checkMaxResults( max );
+		}
+	}
+	
+	public SubscriptionScheduler
+	getScheduler()
+	{
+		return( scheduler );
+	}
+	
+	public boolean
+	isRSSPublishEnabled()
+	{
+		return( COConfigurationManager.getBooleanParameter( CONFIG_RSS_ENABLE, false ));
+	}
+	
+	public void
+	setRSSPublishEnabled(
+		boolean		enabled )
+	{
+		COConfigurationManager.setParameter( CONFIG_RSS_ENABLE, enabled );
+	}
+	
+	public boolean
+	isSearchEnabled()
+	{
+		return( COConfigurationManager.getBooleanParameter( CONFIG_ENABLE_SEARCH, true ));
+	}
+	
+	public void
+	setSearchEnabled(
+		boolean		enabled )
+	{
+		COConfigurationManager.setParameter( CONFIG_ENABLE_SEARCH, enabled );
+	}
+	
+	public boolean
+	hideSearchTemplates()
+	{
+		return( COConfigurationManager.getBooleanParameter( CONFIG_HIDE_SEARCH_TEMPLATES, true ));
+	}
+	
+	public boolean
+	isSubsDownloadEnabled()
+	{
+		return( COConfigurationManager.getBooleanParameter( CONFIG_DL_SUBS_ENABLE, true ));
+	}
+	
+	public void
+	setSubsDownloadEnabled(
+		boolean		enabled )
+	{
+		COConfigurationManager.setParameter( CONFIG_DL_SUBS_ENABLE, enabled );
+	}
+	
+	public void
+	setRateLimits(
+		String		limits )
+	{
+		COConfigurationManager.setParameter( CONFIG_DL_RATE_LIMITS, limits );
+
+	}
+	
+	public String
+	getRateLimits()
+	{
+		return( COConfigurationManager.getStringParameter( CONFIG_DL_RATE_LIMITS, "" ));
+	}
+	
+	public String
+	getRSSLink()
+	{
+		return( rss_publisher.getFeedURL());
+	}
+	
+	public Subscription 
+	create(
+		String			name,
+		boolean			public_subs,
+		String			json )
+	
+		throws SubscriptionException 
+	{
+		name = getUniqueName( name );
+		
+		SubscriptionImpl subs = new SubscriptionImpl( this, name, public_subs, null, json, SubscriptionImpl.ADD_TYPE_CREATE );
+		
+		log( "Created new subscription: " + subs.getString());
+		
+		if ( subs.isPublic()){
+			
+			updatePublicSubscription( subs );
+		}
+		
+		return( addSubscription( subs ));
+	}
+	
+	public Subscription
+	createSingletonRSS(
+		String		name,
+		URL			url,
+		int			check_interval_mins )
+		
+		throws SubscriptionException
+	{
+		return( createSingletonRSSSupport( name, url, true, check_interval_mins, SubscriptionImpl.ADD_TYPE_CREATE, true ));
+	}
+	
+	public Subscription
+	createFromURI(
+		String		uri )
+		
+		throws SubscriptionException
+	{
+		final AESemaphore sem = new AESemaphore( "subswait" );
+		
+		final Object[] result = { null };
+		
+		byte[] 	sid 		= null;
+		int		version		= -1;
+
+		
+		int	pos = uri.indexOf( '?' );
+		
+		String[] bits = uri.substring(pos+1).split( "&" );
+		
+		for ( String bit: bits ){
+			
+			String[] temp = bit.split( "=" );
+			
+			if ( temp.length != 2 ){
+				
+				continue;
+			}
+			
+			String lhs 	= temp[0].toLowerCase( Locale.US );
+			String	rhs	= temp[1];
+			
+			if ( lhs.equals( "id" )){
+				
+				sid = Base32.decode( rhs );
+				
+			}else if ( lhs.equals( "v" )){
+				
+				version = Integer.parseInt( rhs );
+			}
+		}
+		
+		if ( sid == null || version == -1 ){
+			
+			throw( new SubscriptionException( "Invalid URI" ));
+		}
+		
+		lookupSubscription( 
+			new byte[20], 
+			sid, 
+			version, 
+			new subsLookupListener() {
+				
+				public void 
+				found(
+					byte[] 			hash, 
+					Subscription 	subscription ) 
+				{
+				}
+				
+				public void 
+				failed(
+					byte[] 					hash, 
+					SubscriptionException 	error ) 
+					
+				{	
+					synchronized( result ){
+						
+						result[0] = error;
+					}
+					
+					sem.release();
+				}
+				
+				public void 
+				complete(
+					byte[] 			hash, 
+					Subscription[] 	subscriptions )
+				{
+					synchronized( result ){
+						
+						if ( subscriptions.length > 0 ){
+						
+							result[0] = subscriptions[0];
+							
+						}else{
+							
+							result[0] = new SubscriptionException( "Subscription not found" );
+						}
+					}
+					
+					sem.release();
+				}
+				
+				public boolean 
+				isCancelled() 
+				{
+					return( false );
+				}
+			});
+		
+		sem.reserve();
+		
+		if ( result[0] instanceof Subscription ){
+			
+			return((Subscription)result[0]);
+			
+		}else{
+			
+			throw((SubscriptionException)result[0]);
+		}
+	}
+	
+	protected SubscriptionImpl
+	lookupSingletonRSS(
+		String		name,
+		URL			url,
+		boolean		is_public,
+		int			check_interval_mins )
+		
+		throws SubscriptionException
+	{
+		checkURL( url );
+		
+		Map	singleton_details = getSingletonMap(name, url, is_public, check_interval_mins);
+		
+		byte[] sid = SubscriptionBodyImpl.deriveSingletonShortID(singleton_details);
+		
+		return( getSubscriptionFromSID( sid ));
+	}
+	
+			
+	protected Subscription
+	createSingletonRSSSupport(
+		String		name,
+		URL			url,
+		boolean		is_public,
+		int			check_interval_mins,
+		int			add_type,
+		boolean		subscribe )
+		
+		throws SubscriptionException
+	{
+		checkURL( url );
+		
+		try{
+			Subscription existing = lookupSingletonRSS( name, url, is_public, check_interval_mins );
+			
+			if ( existing != null ){
+				
+				return( existing );
+			}
+			
+			Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().createRSSEngine( name, url );
+			
+			String	json = SubscriptionImpl.getSkeletonJSON( engine, check_interval_mins );
+			
+			Map	singleton_details = getSingletonMap(name, url, is_public, check_interval_mins);
+			
+			SubscriptionImpl subs = new SubscriptionImpl( this, name, is_public, singleton_details, json, add_type );
+			
+			subs.setSubscribed( subscribe );
+			
+			log( "Created new singleton subscription: " + subs.getString());
+							
+			subs = addSubscription( subs );
+			
+			return( subs );
+			
+		}catch( SubscriptionException e ){
+			
+			throw((SubscriptionException)e);
+			
+		}catch( Throwable e ){
+			
+			throw( new SubscriptionException( "Failed to create subscription", e ));
+		}
+	}
+	
+	protected String
+	getUniqueName(
+		String	name )
+	{
+		for ( int i=0;i<1024;i++){
+			
+			String	test_name = name + (i==0?"":(" (" + i + ")"));
+			
+			if ( getSubscriptionFromName( test_name ) == null ){
+
+				return( test_name );
+			}
+		}
+		
+		return( name );
+	}
+	
+	protected Map
+	getSingletonMap(
+		String		name,
+		URL			url,
+		boolean		is_public,
+		int			check_interval_mins )
+	
+		throws SubscriptionException
+	{
+		try{
+			Map	singleton_details = new HashMap();
+			
+			if ( url.getProtocol().equalsIgnoreCase( "vuze" )){
+				
+					// hack to minimise encoded url length for our own urls
+				
+				singleton_details.put( "key", url.toExternalForm().getBytes( Constants.BYTE_ENCODING ));
+
+			}else{
+				singleton_details.put( "key", url.toExternalForm().getBytes( "UTF-8" ));
+			}
+						
+			String	name2 = name.length() > 64?name.substring(0,64):name;
+			
+			singleton_details.put( "name", name2 );
+			
+			if ( check_interval_mins != SubscriptionHistoryImpl.DEFAULT_CHECK_INTERVAL_MINS ){
+				
+				singleton_details.put( "ci", new Long( check_interval_mins ));
+			}
+			
+			return( singleton_details );
+		
+		}catch( Throwable e ){
+			
+			throw( new SubscriptionException( "Failed to create subscription", e ));
+		}
+	}
+	
+	protected SubscriptionImpl
+	createSingletonSubscription(
+		Map			singleton_details,
+		int			add_type,
+		boolean		subscribe )
+	
+		throws SubscriptionException 
+	{
+		try{
+			String name = ImportExportUtils.importString( singleton_details, "name", "(Anonymous)" );
+			
+			URL	url = new URL( ImportExportUtils.importString( singleton_details, "key" ));
+			
+			int	check_interval_mins = (int)ImportExportUtils.importLong( singleton_details, "ci", SubscriptionHistoryImpl.DEFAULT_CHECK_INTERVAL_MINS );
+			
+				// only defined type is singleton rss
+			
+			SubscriptionImpl s = (SubscriptionImpl)createSingletonRSSSupport( name, url, true, check_interval_mins, add_type, subscribe );
+			
+			return( s );
+			
+		}catch( Throwable e ){
+			
+			log( "Creation of singleton from " + singleton_details + " failed", e );
+			
+			throw( new SubscriptionException( "Creation of singleton from " + singleton_details + " failed", e ));
+		}
+	}
+	
+	public void
+	requestSubscription(
+		URL			url )
+	{
+		for ( SubscriptionManagerListener listener: listeners ){
+			
+			try{
+				listener.subscriptionRequested(url);
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}
+	}
+	
+	public Subscription 
+	createRSS(
+		String		name,
+		URL			url,
+		int			check_interval_mins,
+		Map			user_data )
+	
+		throws SubscriptionException 
+	{
+		checkURL( url );
+		
+		try{
+			name = getUniqueName(name);
+		
+			Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().createRSSEngine( name, url );
+			
+			String	json = SubscriptionImpl.getSkeletonJSON( engine, check_interval_mins );
+			
+				// engine name may have been modified so re-read it for subscription default
+			
+			SubscriptionImpl subs = new SubscriptionImpl( this, engine.getName(), engine.isPublic(), null, json, SubscriptionImpl.ADD_TYPE_CREATE );
+			
+			if ( user_data != null ){
+				
+				Iterator it = user_data.entrySet().iterator();
+				
+				while( it.hasNext()){
+					
+					Map.Entry entry = (Map.Entry)it.next();
+					
+					subs.setUserData( entry.getKey(), entry.getValue());
+				}
+			}
+			
+			log( "Created new subscription: " + subs.getString());
+					
+			subs = addSubscription( subs );
+			
+			if ( subs.isPublic()){
+			
+				updatePublicSubscription( subs );
+			}
+			
+			return( subs );
+			
+		}catch( Throwable e ){
+			
+			throw( new SubscriptionException( "Failed to create subscription", e ));
+		}
+	}
+
+	protected void
+	checkURL(
+		URL		url )
+	
+		throws SubscriptionException
+	{
+		if ( url.getHost().trim().length() == 0 ){
+			
+			String protocol = url.getProtocol().toLowerCase();
+			
+			if ( ! ( protocol.equals( "azplug" ) || protocol.equals( "file" ) || protocol.equals( "vuze" ))){
+			
+				throw( new SubscriptionException( "Invalid URL '" + url + "'" ));
+			}
+		}
+	}
+	
+	protected SubscriptionImpl
+	addSubscription(
+		SubscriptionImpl		subs )
+	{
+		SubscriptionImpl existing;
+		
+		synchronized( this ){
+
+			int index = Collections.binarySearch(subscriptions, subs, new Comparator<Subscription>() {
+				public int compare(Subscription arg0, Subscription arg1) {
+					return arg0.getID().compareTo(arg1.getID());
+				}
+			});
+			if (index < 0) {
+				existing = null;
+				index = -1 * index - 1; // best guess
+
+				subscriptions.add( index, subs );
+			
+				saveConfig();
+			} else {
+				existing = (SubscriptionImpl) subscriptions.get(index);
+			}
+		}
+		
+		if ( existing != null ){
+			
+			log( "Attempted to add subscription when already present: " + subs.getString());
+			
+			subs.destroy();
+			
+			return( existing );
+		}
+		
+		if ( subs.isMine()){
+			
+			addMetaSearchListener();
+		}
+		
+		if ( subs.getCachedPopularity() == -1 ){
+			
+			try{
+				subs.getPopularity(
+					new SubscriptionPopularityListener()
+					{
+						public void
+						gotPopularity(
+							long						popularity )
+						{
+						}
+						
+						public void
+						failed(
+							SubscriptionException		error )
+						{
+						}
+					});
+				
+			}catch( Throwable e ){
+				
+				log( "", e );
+			}
+		}
+		
+		Iterator it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				((SubscriptionManagerListener)it.next()).subscriptionAdded( subs );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+		
+		if ( subs.isSubscribed() && subs.isPublic()){
+			
+			setSelected( subs );
+		}
+		
+		if ( dht_plugin != null ){
+				
+			new AEThread2( "Publish check", true )
+			{
+				public void
+				run()
+				{
+					publishSubscriptions();
+				}
+			}.start();
+		}
+		
+		return( subs );
+	}
+	
+	protected void
+	addMetaSearchListener()
+	{
+		synchronized( this ){
+			
+			if ( meta_search_listener_added ){
+				
+				return;
+			}
+			
+			meta_search_listener_added = true;
+		}
+		
+		MetaSearchManagerFactory.getSingleton().getMetaSearch().addListener(
+			new MetaSearchListener()
+			{
+				public void
+				engineAdded(
+					Engine		engine )
+				{
+					
+				}
+				
+				public void
+				engineUpdated(
+					Engine		engine )
+				{
+					synchronized( SubscriptionManagerImpl.this ){
+						
+						for (int i=0;i<subscriptions.size();i++){
+							
+							SubscriptionImpl	subs = (SubscriptionImpl)subscriptions.get(i);
+							
+							if ( subs.isMine()){
+								
+								subs.engineUpdated( engine );
+							}
+						}
+					}
+				}
+				
+				public void
+				engineRemoved(
+					Engine		engine )
+				{
+					
+				}
+			});
+	}
+	
+	protected void
+	changeSubscription(
+		SubscriptionImpl		subs )
+	{
+		if ( !subs.isRemoved()){
+			
+			Iterator it = listeners.iterator();
+			
+			while( it.hasNext()){
+				
+				try{
+					((SubscriptionManagerListener)it.next()).subscriptionChanged( subs );
+					
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+		}
+	}
+	
+	protected void
+	selectSubscription(
+		SubscriptionImpl		subs )
+	{
+		if ( !subs.isRemoved()){
+
+			Iterator it = listeners.iterator();
+			
+			while( it.hasNext()){
+				
+				try{
+					((SubscriptionManagerListener)it.next()).subscriptionSelected( subs );
+					
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+		}
+	}
+	
+	protected void
+	removeSubscription(
+		SubscriptionImpl		subs )
+	{
+		synchronized( this ){
+			
+			if ( subscriptions.remove( subs )){
+			
+				saveConfig();
+				
+			}else{
+			
+				return;
+			}
+		}
+		
+		try{
+			Engine engine = subs.getEngine( true );
+			
+			if ( engine.getType() == Engine.ENGINE_TYPE_RSS ){
+				
+				engine.delete();
+				
+				log( "Removed engine " + engine.getName() + " due to subscription removal" );
+			}
+			
+		}catch( Throwable e ){
+			
+			log( "Failed to check for engine deletion", e );
+		}
+		
+		Iterator<SubscriptionManagerListener> it = listeners.iterator();
+		
+		while( it.hasNext()){
+			
+			try{
+				it.next().subscriptionRemoved( subs );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+		
+		try{
+			FileUtil.deleteResilientFile( getResultsFile( subs ));
+			
+			File vuze_file = getVuzeFile( subs );
+			
+			vuze_file.delete();
+			
+			new File( vuze_file.getParent(), vuze_file.getName() + ".bak" ).delete();
+			
+		}catch( Throwable e ){
+			
+			log( "Failed to delete results/vuze file", e );
+		}
+	}
+	
+	private AsyncDispatcher	async_dispatcher = new AsyncDispatcher();
+	
+	protected void
+	updatePublicSubscription(
+		final SubscriptionImpl		subs )
+	{		
+		if ( subs.isSingleton()){
+			
+				// never update singletons
+			
+			subs.setServerPublished();
+			
+		}else{
+				// the update is blocking on the messenger server and this method can be called
+				// from the UI thread so back things off for the publishing
+			
+			final AESemaphore sem = new AESemaphore( "pub:async" );
+			
+			async_dispatcher.dispatch(
+				new AERunnable()
+				{	
+					@Override
+					public void 
+					runSupport() 
+					{
+						try{
+							Long	l_last_pub 	= (Long)subs.getUserData( SP_LAST_ATTEMPTED );
+							Long	l_consec_fail = (Long)subs.getUserData( SP_CONSEC_FAIL );
+							
+							if ( l_last_pub != null && l_consec_fail != null ){
+								
+								long	delay = SERVER_PUB_CHECK_PERIOD;
+								
+								for (int i=0;i<l_consec_fail.longValue();i++){
+									
+									delay <<= 1;
+									
+									if ( delay > 24*60*60*1000 ){
+										
+										break;
+									}
+								}
+								
+								if ( l_last_pub.longValue() + delay > SystemTime.getMonotonousTime()){
+									
+									return;
+								}
+							}
+	
+							try{		
+								File vf = getVuzeFile( subs );
+					
+								byte[] bytes = FileUtil.readFileAsByteArray( vf );
+								
+								byte[]	encoded_subs = Base64.encode( bytes );
+					
+								PlatformSubscriptionsMessenger.updateSubscription(
+										!subs.getServerPublished(),
+										subs.getName(false),
+										subs.getPublicKey(),
+										subs.getPrivateKey(),
+										subs.getShortID(),
+										subs.getVersion(),
+										new String( encoded_subs ));
+								
+								subs.setUserData( SP_LAST_ATTEMPTED, null );
+								subs.setUserData( SP_CONSEC_FAIL, null );
+				
+								subs.setServerPublished();
+								
+								log( "    Updated public subscription " + subs.getString());
+								
+							}catch( Throwable e ){
+								
+								log( "    Failed to update public subscription " + subs.getString(), e );
+								
+								subs.setUserData( SP_LAST_ATTEMPTED, new Long( SystemTime.getMonotonousTime()));
+								
+								subs.setUserData( SP_CONSEC_FAIL, new Long( l_consec_fail==null?1:(l_consec_fail.longValue()+1)));
+				
+								subs.setServerPublicationOutstanding();
+							}
+						}finally{
+							
+							sem.release();
+						}
+					}
+				});
+			
+			sem.reserve( 5000 );	// give it a chance to work synchronously
+		}
+	}
+	
+	protected void
+	checkSingletonPublish(
+		SubscriptionImpl		subs )
+	
+		throws SubscriptionException
+	{
+		if ( subs.getSingletonPublishAttempted()){
+			
+			throw( new SubscriptionException( "Singleton publish already attempted" ));
+		}
+		
+		subs.setSingletonPublishAttempted();
+		
+		try{
+			File vf = getVuzeFile( subs );
+	
+			byte[] bytes = FileUtil.readFileAsByteArray( vf );
+			
+			byte[]	encoded_subs = Base64.encode( bytes );
+			
+				// use a transient key-pair as we won't have the private key in general
+			
+			KeyPair	kp = CryptoECCUtils.createKeys();
+			
+			byte[] public_key 		= CryptoECCUtils.keyToRawdata( kp.getPublic());
+			byte[] private_key 		= CryptoECCUtils.keyToRawdata( kp.getPrivate());
+	
+			PlatformSubscriptionsMessenger.updateSubscription(
+					true,
+					subs.getName(false),
+					public_key,
+					private_key,
+					subs.getShortID(),
+					1,
+					new String( encoded_subs ));
+			
+			log( "    created singleton public subscription " + subs.getString());
+			
+		}catch( Throwable e ){
+			
+			throw( new SubscriptionException( "Failed to publish singleton", e ));
+		}
+	}
+	
+	protected void
+	checkServerPublications(
+		List		subs )
+	{
+		for (int i=0;i<subs.size();i++){
+			
+			SubscriptionImpl	sub = (SubscriptionImpl)subs.get(i);
+			
+			if ( sub.getServerPublicationOutstanding()){
+				
+				updatePublicSubscription( sub );
+			}
+		}
+	}
+	
+	private static final Object	SUBS_CHAT_KEY	= new Object();
+	
+	protected void
+	checkStuff(
+		int		ticks )
+	{
+		long now = SystemTime.getCurrentTime();
+		
+		List<SubscriptionImpl> subs;
+		
+		synchronized( this ){
+			
+			subs = new ArrayList<SubscriptionImpl>( subscriptions );
+		}
+		
+		SubscriptionImpl	expired_subs = null;
+		
+		for (int i=0;i<subs.size();i++){
+			
+			SubscriptionImpl sub = subs.get( i );
+			
+			if ( !( sub.isMine() || sub.isSubscribed())){
+				
+				long	age = now - sub.getAddTime();
+				
+				if ( age > DELETE_UNUSED_AFTER_MILLIS ){
+					
+					if ( 	expired_subs == null || 
+							( sub.getAddTime() < expired_subs.getAddTime())){
+						
+						expired_subs = sub;
+					}
+					
+					continue;
+				}
+			}
+			
+			
+			sub.checkPublish();
+		}
+		
+		if ( expired_subs != null ){
+			
+			log( "Removing unsubscribed subscription '" + expired_subs.getName() + "' as expired" );
+					
+			expired_subs.remove();
+		}
+		
+		if ( ticks % CHAT_CHECK_TICKS == 0 ){
+			
+			List<SubscriptionImpl> subs_copy = new ArrayList<SubscriptionImpl>( subs );
+			
+			Collections.shuffle( subs_copy );
+			
+			long mono_now = SystemTime.getMonotonousTime();
+			
+			for ( final SubscriptionImpl sub: subs_copy ){
+				
+				if ( !sub.isSubscribed()){
+					
+					continue;
+				}
+				
+				if ( sub.isSearchTemplate()){
+					
+					continue;
+				}
+				
+				Long data = (Long)sub.getUserData( SUBS_CHAT_KEY );
+				
+				if ( data != null ){
+					
+					if ( data < 0 || mono_now - data < 4*60*60*1000 ){
+						
+						continue;
+					}
+				}
+				
+				boolean	ok = false;
+				
+				try{
+					Engine engine = sub.getEngine();
+					
+					if ( engine instanceof WebEngine ){
+						
+						String url = ((WebEngine)engine).getSearchUrl( true );
+						
+						ok = true;
+						
+						sub.setUserData( SUBS_CHAT_KEY, -1L );
+						
+						BuddyPluginUtils.peekChatAsync(
+							AENetworkClassifier.AT_PUBLIC,
+							"Subscription: " + url,
+							new Runnable()
+							{
+								public void 
+								run() 
+								{
+									sub.setUserData( SUBS_CHAT_KEY, SystemTime.getMonotonousTime());
+								}
+							});
+							
+							// just fire off one at a time
+						
+						break;
+					}
+				}catch( Throwable e ){
+					
+				}
+
+				if ( !ok ){
+					
+					sub.setUserData( SUBS_CHAT_KEY, -2L );
+				}
+			}
+		}
+		
+		if ( ticks % ASSOC_CHECK_TICKS == 0 ){
+			
+			lookupAssociations( false );
+		}
+		
+		if ( ticks % SERVER_PUB_CHECK_TICKS == 0 ){
+			
+			checkServerPublications( subs );
+		}
+		
+		if ( ticks % TIDY_POT_ASSOC_TICKS == 0 ){
+			
+			tidyPotentialAssociations();
+		}
+		
+		if ( 	ticks == SET_SELECTED_FIRST_TICK ||
+				ticks % SET_SELECTED_TICKS == 0 ){
+			
+			setSelected( subs );
+		}
+	}
+	
+	public Subscription
+	importSubscription(
+		int			type,
+		Map			map,
+		boolean		warn_user )
+	
+		throws SubscriptionException
+	{
+		boolean	log_errors = true;
+		
+		try{
+			try{
+				if ( type == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION_SINGLETON ){
+					
+					String	name = new String((byte[])map.get( "name" ), "UTF-8" );
+					
+					URL	url = new URL( new String((byte[])map.get( "url" ), "UTF-8" ));
+					
+					Long	l_interval = (Long)map.get( "check_interval_mins" );
+					
+					int	check_interval_mins = l_interval==null?SubscriptionHistoryImpl.DEFAULT_CHECK_INTERVAL_MINS:l_interval.intValue();
+					
+					Long	l_public = (Long)map.get( "public" );
+					
+					boolean is_public = l_public==null?true:l_public.longValue()==1;
+					
+					SubscriptionImpl existing = lookupSingletonRSS(name, url, is_public, check_interval_mins );
+					
+					if ( UrlFilter.getInstance().urlCanRPC( url.toExternalForm())){
+						
+						warn_user = false;
+					}
+					
+					if ( existing != null && existing.isSubscribed()){
+						
+						if ( warn_user ){
+							
+							UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+							
+							String details = MessageText.getString(
+									"subscript.add.dup.desc",
+									new String[]{ existing.getName()});
+							
+							ui_manager.showMessageBox(
+									"subscript.add.dup.title",
+									"!" + details + "!",
+									UIManagerEvent.MT_OK );
+						}
+						
+						selectSubscription( existing );
+						
+						return( existing );
+						
+					}else{
+						
+						if ( warn_user ){
+							
+							UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+				
+							String details = MessageText.getString(
+									"subscript.add.desc",
+									new String[]{ name });
+							
+							long res = ui_manager.showMessageBox(
+									"subscript.add.title",
+									"!" + details + "!",
+									UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+							
+							if ( res != UIManagerEvent.MT_YES ){	
+							
+								log_errors = false;
+								
+								throw( new SubscriptionException( "User declined addition" ));
+							}
+						}
+						
+						if ( existing == null ){
+					
+							SubscriptionImpl new_subs = (SubscriptionImpl)createSingletonRSSSupport( name, url, is_public, check_interval_mins, SubscriptionImpl.ADD_TYPE_IMPORT, true );
+																	
+							log( "Imported new singleton subscription: " + new_subs.getString());
+									
+							return( new_subs );
+							
+						}else{
+							
+							existing.setSubscribed( true );
+							
+							selectSubscription( existing );
+							
+							return( existing );
+						}
+					}
+				}else{
+					
+					SubscriptionBodyImpl body = new SubscriptionBodyImpl( this, map );
+							
+					SubscriptionImpl existing = getSubscriptionFromSID( body.getShortID());
+					
+					if ( existing != null && existing.isSubscribed()){
+					
+						if ( existing.getVersion() >= body.getVersion()){
+							
+							log( "Not upgrading subscription: " + existing.getString() + " as supplied (" +  body.getVersion() + ") is not more recent than existing (" + existing.getVersion() + ")");
+							
+							if ( warn_user ){
+								
+								UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+								
+								String details = MessageText.getString(
+										"subscript.add.dup.desc",
+										new String[]{ existing.getName()});
+								
+								ui_manager.showMessageBox(
+										"subscript.add.dup.title",
+										"!" + details + "!",
+										UIManagerEvent.MT_OK );
+							}
+								// we have a newer one, ignore
+							
+							selectSubscription( existing );
+							
+							return( existing );
+							
+						}else{
+							
+							if ( warn_user ){
+								
+								UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+				
+								String details = MessageText.getString(
+										"subscript.add.upgrade.desc",
+										new String[]{ existing.getName()});
+								
+								long res = ui_manager.showMessageBox(
+										"subscript.add.upgrade.title",
+										"!" + details + "!",
+										UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+								
+								if ( res != UIManagerEvent.MT_YES ){	
+								
+									throw( new SubscriptionException( "User declined upgrade" ));
+								}
+							}
+							
+							log( "Upgrading subscription: " + existing.getString());
+			
+							existing.upgrade( body );
+							
+							saveConfig();
+							
+							subscriptionUpdated();
+							
+							return( existing );
+						}
+					}else{
+						
+						SubscriptionImpl new_subs = null;
+						
+						String	subs_name;
+						
+						if ( existing == null ){
+							
+							new_subs = new SubscriptionImpl( this, body, SubscriptionImpl.ADD_TYPE_IMPORT, true );
+							
+							subs_name = new_subs.getName();
+							
+						}else{
+							
+							subs_name = existing.getName();
+						}
+						
+						if ( warn_user ){
+							
+							UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+				
+							String details = MessageText.getString(
+									"subscript.add.desc",
+									new String[]{ subs_name });
+							
+							long res = ui_manager.showMessageBox(
+									"subscript.add.title",
+									"!" + details + "!",
+									UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+							
+							if ( res != UIManagerEvent.MT_YES ){	
+							
+								throw( new SubscriptionException( "User declined addition" ));
+							}
+						}
+						
+						if ( new_subs == null ){
+							
+							existing.setSubscribed( true );
+							
+							selectSubscription( existing );
+							
+							return( existing );
+							
+						}else{
+							
+							log( "Imported new subscription: " + new_subs.getString());
+						
+							new_subs = addSubscription( new_subs );
+						
+							return( new_subs );
+						}
+					}
+				}
+			}catch( Throwable e ){
+				
+				throw( new SubscriptionException( "Subscription import failed", e ));
+			}
+		}catch( SubscriptionException e ){
+			
+			if ( warn_user && log_errors ){
+				
+				UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+				
+				String details = MessageText.getString(
+						"subscript.import.fail.desc",
+						new String[]{ Debug.getNestedExceptionMessage(e)});
+				
+				ui_manager.showMessageBox(
+						"subscript.import.fail.title",
+						"!" + details + "!",
+						UIManagerEvent.MT_OK );
+			}
+			
+			throw( e );
+		}
+	}
+	
+	public Subscription[]
+	getSubscriptions()
+	{
+		synchronized( this ){
+			
+			return((SubscriptionImpl[])subscriptions.toArray( new SubscriptionImpl[subscriptions.size()]));
+		}
+	}
+	
+	public Subscription[]
+	getSubscriptions(
+		boolean	subscribed_only )
+	{
+		if ( !subscribed_only ){
+			
+			return( getSubscriptions());
+		}
+		
+		List	result = new ArrayList();
+				
+		synchronized( this ){
+			
+			for (int i=0;i<subscriptions.size();i++){
+				
+				SubscriptionImpl subs = (SubscriptionImpl)subscriptions.get(i);
+				
+				if ( subs.isSubscribed()){
+					
+					result.add( subs );
+				}
+			}
+		}
+		
+		return((SubscriptionImpl[])result.toArray( new SubscriptionImpl[result.size()]));
+	}
+	
+	public int
+	getSubscriptionCount(
+		boolean	subscribed_only )
+	{
+		if ( subscribed_only ){
+	
+			int total = 0;
+			
+			synchronized( this ){
+				
+				for ( Subscription subs: subscriptions ){
+					
+					if ( subs.isSubscribed()){
+						
+						total++;
+					}
+				}
+			}
+			
+			return( total );
+			
+		}else{
+			
+			synchronized( this ){
+				
+				return( subscriptions.size());
+			}
+		}
+	}
+
+	protected SubscriptionImpl
+	getSubscriptionFromName(
+		String		name )
+	{
+		synchronized( this ){
+			
+			for (int i=0;i<subscriptions.size();i++){
+				
+				SubscriptionImpl s = (SubscriptionImpl)subscriptions.get(i);
+				
+				if ( s.getName().equalsIgnoreCase( name )){
+					
+					return( s );
+				}
+			}
+		}
+		
+		return( null );
+	}
+	
+	public Subscription
+	getSubscriptionByID(
+		String		id )
+	{
+		synchronized( this ){
+			
+  		int index = Collections.binarySearch(subscriptions, id, new Comparator() {
+  			public int compare(Object o1, Object o2) {
+  				String id1 = (o1 instanceof Subscription) ? ((Subscription) o1).getID() : o1.toString();
+  				String id2 = (o2 instanceof Subscription) ? ((Subscription) o2).getID() : o2.toString();
+  				return id1.compareTo(id2);
+  			}
+  		});
+  		
+  		if (index >= 0) {
+  			return subscriptions.get(index);
+  		}
+		}
+		
+		return null;
+	}
+	
+	protected SubscriptionImpl
+	getSubscriptionFromSID(
+		byte[]		sid )
+	{
+		return (SubscriptionImpl) getSubscriptionByID( Base32.encode(sid));
+	}
+	
+	protected File
+	getSubsDir()
+	
+		throws IOException
+	{
+		File dir = new File(SystemProperties.getUserPath());
+
+		dir = new File( dir, "subs" );
+ 		
+ 		if ( !dir.exists()){
+ 			
+ 			if ( !dir.mkdirs()){
+ 				
+ 				throw( new IOException( "Failed to create '" + dir + "'" ));
+ 			}
+ 		}	
+ 		
+ 		return( dir );
+	}
+	
+	protected File
+	getVuzeFile(
+		SubscriptionImpl 		subs )
+	
+		throws IOException
+	{
+ 		File dir = getSubsDir();
+ 		
+ 		return( new File( dir, ByteFormatter.encodeString( subs.getShortID()) + ".vuze" ));
+	}
+	
+	protected File
+	getResultsFile(
+		SubscriptionImpl 		subs )
+	
+		throws IOException
+	{
+ 		File dir = getSubsDir();
+ 		
+ 		return( new File( dir, ByteFormatter.encodeString( subs.getShortID()) + ".results" ));
+	}
+	
+	public int
+	getKnownSubscriptionCount()
+	{
+		PluginInterface pi = PluginInitializer.getDefaultInterface();
+
+		Download[] downloads = pi.getDownloadManager().getDownloads();
+
+		ByteArrayHashMap<String> results = new ByteArrayHashMap<String>(Math.max( 16, downloads.length * 2 ));
+		
+		try{			
+			for ( Download download: downloads ){
+				
+				Map	m = download.getMapAttribute( ta_subscription_info );
+				
+				if ( m != null ){
+					
+					List s = (List)m.get("s");
+					
+					if ( s != null && s.size() > 0 ){
+												
+						for (int i=0;i<s.size();i++){
+							
+							byte[]	sid = (byte[])s.get(i);
+							
+							results.put( sid, "" );
+						}
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			log( "Failed to get known subscriptions", e );
+		}
+		
+		return( results.size());
+	}
+	
+	public Subscription[]
+	getKnownSubscriptions(
+		byte[]						hash )
+	{
+		PluginInterface pi = PluginInitializer.getDefaultInterface();
+
+		try{
+			Download download = pi.getDownloadManager().getDownload( hash );
+			
+			if ( download != null ){
+				
+				Map	m = download.getMapAttribute( ta_subscription_info );
+				
+				if ( m != null ){
+					
+					List s = (List)m.get("s");
+					
+					if ( s != null && s.size() > 0 ){
+						
+						List	result = new ArrayList( s.size());
+						
+						boolean hide_search = hideSearchTemplates();
+						
+						for (int i=0;i<s.size();i++){
+							
+							byte[]	sid = (byte[])s.get(i);
+							
+							SubscriptionImpl subs = getSubscriptionFromSID(sid);
+							
+							if ( subs != null ){
+								
+								if ( isVisible( subs )){
+								
+									if ( hide_search && subs.isSearchTemplate()){
+									
+									}else{
+										
+										result.add( subs );
+									}
+								}
+							}
+						}
+						
+						return((Subscription[])result.toArray( new Subscription[result.size()]));
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			log( "Failed to get known subscriptions", e );
+		}
+		
+		return( new Subscription[0] );
+	}
+	
+	protected boolean
+	subscriptionExists(
+		Download			download,
+		SubscriptionImpl	subs )
+	{
+		byte[]	sid = subs.getShortID();
+	
+		Map	m = download.getMapAttribute( ta_subscription_info );
+		
+		if ( m != null ){
+			
+			List s = (List)m.get("s");
+			
+			if ( s != null && s.size() > 0 ){
+								
+				for (int i=0;i<s.size();i++){
+					
+					byte[]	x = (byte[])s.get(i);
+					
+					if ( Arrays.equals( x, sid )){
+						
+						return( true );
+					}
+				}
+			}
+		}
+		
+		return( false );
+	}
+	
+	private boolean
+	downloadIsIgnored(
+		Download		download )
+	{
+		if ( download.getTorrent() == null || !download.isPersistent()){
+			
+			return( true );
+		}
+		
+		String[] nets = PluginCoreUtils.unwrap( download ).getDownloadState().getNetworks();
+		
+		boolean	non_pub_found = false;
+		
+		for ( String net: nets ){
+			
+			if ( net == AENetworkClassifier.AT_PUBLIC ){
+				
+				return( false );
+				
+			}else{
+			
+				non_pub_found = true;
+			}
+		}
+		
+		return( non_pub_found );
+	}
+	
+	protected boolean
+	isVisible(
+		SubscriptionImpl		subs )
+	{
+			// to avoid development links polluting production we filter out such subscriptions
+		
+		if ( Constants.isCVSVersion() || subs.isSubscribed()){
+			
+			return( true );
+		}
+		
+		try{
+			Engine engine = subs.getEngine( true );
+			
+			if ( engine instanceof WebEngine ){
+				
+				String url = ((WebEngine)engine).getSearchUrl();
+				
+				try{
+					String host = new URL( url ).getHost();
+					
+					return( !exclusion_pattern.matcher( host ).matches());
+					
+				}catch( Throwable e ){
+				}
+			}
+			
+			return( true );
+			
+		}catch( Throwable e ){
+			
+			log( "isVisible failed for " + subs.getString(), e );
+			
+			return( false );
+		}
+	}
+		
+	public Subscription[]
+	getLinkedSubscriptions(
+		byte[]						hash )
+	{
+		PluginInterface pi = PluginInitializer.getDefaultInterface();
+
+		try{
+			Download download = pi.getDownloadManager().getDownload( hash );
+			
+			if ( download != null ){
+				
+				Map	m = download.getMapAttribute( ta_subscription_info );
+				
+				if ( m != null ){
+					
+					List s = (List)m.get("s");
+					
+					if ( s != null && s.size() > 0 ){
+						
+						List	result = new ArrayList( s.size());
+						
+						for (int i=0;i<s.size();i++){
+							
+							byte[]	sid = (byte[])s.get(i);
+							
+							SubscriptionImpl subs = getSubscriptionFromSID(sid);
+							
+							if ( subs != null ){
+								
+								if ( subs.hasAssociation( hash )){
+								
+									result.add( subs );
+								}
+							}
+						}
+						
+						return((Subscription[])result.toArray( new Subscription[result.size()]));
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			log( "Failed to get known subscriptions", e );
+		}
+		
+		return( new Subscription[0] );
+	}
+	
+	protected void
+	lookupAssociations(
+		boolean		high_priority )
+	{
+		synchronized( this ){
+			
+			if ( periodic_lookup_in_progress ){
+				
+				if ( high_priority ){
+				
+					priority_lookup_pending++;
+				}
+				
+				return;
+			}
+			
+			periodic_lookup_in_progress  = true;
+		}
+		
+		try{
+			PluginInterface pi = PluginInitializer.getDefaultInterface();
+			
+			Download[] downloads = pi.getDownloadManager().getDownloads();
+					
+			long	now = SystemTime.getCurrentTime();
+			
+			long		newest_time		= 0;
+			Download	newest_download	= null;
+			
+			
+			for( int i=0;i<downloads.length;i++){
+				
+				Download	download = downloads[i];
+				
+				if ( downloadIsIgnored( download )){
+					
+					continue;
+				}
+				
+				Map	map = download.getMapAttribute( ta_subscription_info );
+				
+				if ( map == null ){
+					
+					map = new LightHashMap();
+					
+				}else{
+					
+					map = new LightHashMap( map );
+				}	
+				
+				Long	l_last_check = (Long)map.get( "lc" );
+				
+				long	last_check = l_last_check==null?0:l_last_check.longValue();
+				
+				if ( last_check > now ){
+					
+					last_check = now;
+					
+					map.put( "lc", new Long( last_check ));
+					
+					download.setMapAttribute( ta_subscription_info, map );
+				}
+				
+				List	subs = (List)map.get( "s" );
+				
+				int	sub_count = subs==null?0:subs.size();
+				
+				if ( sub_count > 8 ){
+					
+					continue;
+				}
+				
+				long	create_time = download.getCreationTime();
+				
+				int	time_between_checks = (sub_count + 1) * 24*60*60*1000 + (int)(create_time%4*60*60*1000);
+				
+				if ( now - last_check >= time_between_checks ){
+					
+					if ( create_time > newest_time ){
+						
+						newest_time		= create_time;
+						newest_download	= download;
+					}
+				}
+			}
+			
+			if ( newest_download != null ){
+			
+				byte[] hash = newest_download.getTorrent().getHash();
+				
+				log( "Association lookup starts for " + newest_download.getName() + "/" + ByteFormatter.encodeString( hash ));
+
+				lookupAssociationsSupport( 
+					hash,
+					new	SubscriptionLookupListener()
+					{
+						public void
+						found(
+							byte[]					hash,
+							Subscription			subscription )
+						{							
+						}
+						
+						public void
+						failed(
+							byte[]					hash,
+							SubscriptionException	error )
+						{
+							log( "Association lookup failed for " + ByteFormatter.encodeString( hash ), error );
+
+							associationLookupComplete();
+						}
+						
+						public void 
+						complete(
+							byte[] 			hash,
+							Subscription[]	subs )
+						{
+							log( "Association lookup complete for " + ByteFormatter.encodeString( hash ));
+							
+							associationLookupComplete();
+						}
+					});
+						
+			}else{
+				
+				associationLookupComplete();
+			}
+		}catch( Throwable e ){
+			
+			log( "Association lookup check failed", e );
+
+			associationLookupComplete();			
+		}
+	}
+	
+	protected void
+	associationLookupComplete()
+	{
+		boolean	recheck;
+		
+		synchronized( this ){
+			
+			periodic_lookup_in_progress = false;
+			
+			recheck = priority_lookup_pending > 0;
+				
+			if ( recheck ){
+				
+				priority_lookup_pending--;
+			}
+		}
+		
+		if ( recheck ){
+			
+			new AEThread2( "SM:priAssLookup", true )
+			{
+				public void run() 
+				{
+					lookupAssociations( false );
+				}
+			}.start();
+		}
+	}
+	
+	protected void
+	setSelected(
+		List		subs )
+	{
+		List	sids 		= new ArrayList();
+		List	used_subs	= new ArrayList();
+		
+		for (int i=0;i<subs.size();i++){
+			
+			SubscriptionImpl	sub = (SubscriptionImpl)subs.get(i);
+			
+			if ( sub.isSubscribed()){
+				
+				if ( sub.isPublic()){
+				
+					used_subs.add( sub );
+				
+					sids.add( sub.getShortID());
+					
+				}else{
+					
+					checkInitialDownload( sub );
+				}
+			}
+		}
+		
+		if ( sids.size() > 0 ){
+			
+			try{
+				List[] result = PlatformSubscriptionsMessenger.setSelected( sids );
+				
+				List	versions 		= result[0];
+				List	popularities	= result[1];
+				
+				log( "Popularity update: updated " + sids.size());
+				
+				final List dht_pops = new ArrayList();
+				
+				for (int i=0;i<sids.size();i++){
+					
+					SubscriptionImpl sub = (SubscriptionImpl)used_subs.get(i);
+					
+					int	latest_version = ((Long)versions.get(i)).intValue();
+					
+					if ( latest_version > sub.getVersion()){
+						
+						updateSubscription( sub, latest_version );
+						
+					}else{
+						
+						checkInitialDownload( sub );
+					}
+					
+					if ( latest_version > 0 ){
+						
+						try{
+							long	pop = ((Long)popularities.get(i)).longValue();
+							
+							if ( pop >= 0 && pop != sub.getCachedPopularity()){
+								
+								sub.setCachedPopularity( pop );
+							}
+						}catch( Throwable e ){
+							
+							log( "Popularity update: Failed to extract popularity", e );
+						}
+					}else{
+						
+						dht_pops.add( sub );
+					}
+				}
+				
+				if ( dht_pops.size() <= 3 ){
+					
+					for (int i=0;i<dht_pops.size();i++){
+							
+						updatePopularityFromDHT((SubscriptionImpl)dht_pops.get(i), false );
+					}
+				}else{
+					
+					new AEThread2( "SM:asyncPop", true )
+					{
+						public void
+						run()
+						{
+							for (int i=0;i<dht_pops.size();i++){
+								
+								updatePopularityFromDHT((SubscriptionImpl)dht_pops.get(i), true );
+							}
+						}
+					}.start();
+				}
+			}catch( Throwable e ){
+				
+				log( "Popularity update: Failed to record selected subscriptions", e );
+			}
+		}else{
+			
+			log( "Popularity update: No selected, public subscriptions" );
+		}
+	}
+	
+	protected void
+	checkUpgrade(
+		SubscriptionImpl		sub )
+	{
+		setSelected( sub );
+	}
+	
+	protected void
+	setSelected(
+		final SubscriptionImpl	sub )
+	{
+		if ( sub.isSubscribed()){
+			
+			if ( sub.isPublic()){
+			
+				new DelayedEvent( 
+					"SM:setSelected",
+					0,
+					new AERunnable()
+					{
+						public void
+						runSupport()
+						{
+							try{
+								List	sids = new ArrayList();
+								
+								sids.add( sub.getShortID());
+							
+								List[] result = PlatformSubscriptionsMessenger.setSelected( sids );
+								
+								log( "setSelected: " + sub.getName());
+								
+								int	latest_version = ((Long)result[0].get(0)).intValue();
+								
+								if ( latest_version == 0 ){
+									
+									if ( sub.isSingleton()){
+									
+										checkSingletonPublish( sub );
+									}
+								}else if ( latest_version > sub.getVersion()){
+									
+									updateSubscription( sub, latest_version );
+									
+								}else{
+									
+									checkInitialDownload( sub );
+								}
+								
+								if ( latest_version > 0 ){
+									
+									try{
+										long	pop = ((Long)result[1].get(0)).longValue();
+										
+										if ( pop >= 0 && pop != sub.getCachedPopularity()){
+											
+											sub.setCachedPopularity( pop );
+										}
+									}catch( Throwable e ){
+										
+										log( "Popularity update: Failed to extract popularity", e );
+									}
+								}else{
+									
+									updatePopularityFromDHT( sub, true );
+								}
+							}catch( Throwable e ){
+								
+								log( "setSelected: failed for " + sub.getName(), e );
+							}
+						}
+					});
+			}else{
+				
+				checkInitialDownload( sub );
+			}
+		}
+	}
+	
+	protected void
+	checkInitialDownload(
+		SubscriptionImpl		subs )
+	{
+		if ( subs.getHistory().getLastScanTime() == 0 ){
+			
+			scheduler.download( 
+				subs, 
+				true,
+				new SubscriptionDownloadListener()
+				{
+					public void
+					complete(
+						Subscription		subs )
+					{
+						log( "Initial download of " + subs.getName() + " complete" );
+					}
+					
+					public void
+					failed(
+						Subscription			subs,
+						SubscriptionException	error )
+					{
+						log( "Initial download of " + subs.getName() + " failed", error );
+					}
+				});
+		}
+	}
+	
+	public SubscriptionAssociationLookup
+	lookupAssociations(
+		final byte[] 							hash,
+		final SubscriptionLookupListener		listener )
+	
+		throws SubscriptionException
+	{
+		try{
+			Download download = PluginInitializer.getDefaultInterface().getDownloadManager().getDownload( hash );
+		
+			if ( download != null ){
+				
+				String[]	networks = download.getListAttribute( ta_networks );
+
+				boolean	public_net = false;
+				
+				for ( String net: networks ){
+					
+					if ( net == AENetworkClassifier.AT_PUBLIC ){
+						
+						public_net = true;
+					}
+				}
+				
+				if ( !public_net ){
+					
+					listener.failed( hash, new SubscriptionException( "Download doesn't use public network" ));
+					
+					return( null );
+				}
+			}			
+		}catch( Throwable e ){
+		}
+		
+		if ( dht_plugin != null && !dht_plugin.isInitialising()){
+			
+			return( lookupAssociationsSupport( hash, listener ));
+		}
+		
+		final boolean[]	cancelled = { false };
+		
+		final SubscriptionAssociationLookup[]	actual_res = { null };
+		
+		final SubscriptionAssociationLookup res = 
+			new SubscriptionAssociationLookup()
+			{
+				public void 
+				cancel() 
+				{
+					log( "    Association lookup cancelled" );
+	
+					synchronized( actual_res ){
+						
+						cancelled[0] = true;
+						
+						if ( actual_res[0] != null ){
+							
+							actual_res[0].cancel();
+						}
+					}
+				}
+			};
+			
+		new AEThread2( "SM:initwait", true )
+		{
+			public void
+			run()
+			{
+				try{
+					SubscriptionAssociationLookup x = lookupAssociationsSupport( hash, listener );
+					
+					synchronized( actual_res ){
+
+						actual_res[0] = x;
+						
+						if ( cancelled[0] ){
+							
+							x.cancel();
+						}
+					}
+					
+				}catch( SubscriptionException e ){
+					
+					listener.failed( hash, e );
+				}
+				
+			}
+		}.start();
+		
+		return( res );
+	}
+	
+	protected SubscriptionAssociationLookup
+	lookupAssociationsSupport(
+		final byte[] 							hash,
+		final SubscriptionLookupListener		listener )
+	
+		throws SubscriptionException 
+	{
+		log( "Looking up associations for '" + ByteFormatter.encodeString( hash ));
+		
+		final String	key = "subscription:assoc:" + ByteFormatter.encodeString( hash ); 
+			
+		final boolean[]	cancelled = { false };
+		
+		dht_plugin.get(
+			getKeyBytes(key),
+			"Subs assoc read: " + Base32.encode( hash ).substring( 0, 16 ),
+			DHTPlugin.FLAG_SINGLE_VALUE,
+			30,
+			60*1000,
+			true,
+			true,
+			new DHTPluginOperationListener()
+			{
+				private Map<HashWrapper,Integer>	hits 					= new HashMap<HashWrapper, Integer>();
+				private AESemaphore					hits_sem				= new AESemaphore( "Subs:lookup" );
+				private List<Subscription>			found_subscriptions 	= new ArrayList<Subscription>();
+				
+				private boolean	complete;
+				
+				private AsyncDispatcher 	dispatcher = new AsyncDispatcher();
+				
+				public boolean
+				diversified()
+				{
+					return( true );
+				}
+				
+				public void 
+				starts(
+					byte[] 				key ) 
+				{
+				}
+				
+				public void
+				valueRead(
+					DHTPluginContact	originator,
+					DHTPluginValue		value )
+				{
+					if ( isCancelled2()){
+						
+						return;
+					}
+					
+					byte[]	val = value.getValue();
+					
+					if ( val.length > 4 ){
+						
+						final int	ver = ((val[0]<<16)&0xff0000) | ((val[1]<<8)&0xff00) | (val[2]&0xff);
+
+						final byte[]	sid = new byte[ val.length - 4 ];
+						
+						System.arraycopy( val, 4, sid, 0, sid.length );
+												
+						HashWrapper hw = new HashWrapper( sid );
+						
+						boolean	new_sid = false;
+						
+						synchronized( hits ){
+							
+							if ( complete ){
+								
+								return;
+							}
+							
+							Integer v = (Integer)hits.get(hw);
+							
+							if ( v != null ){
+								
+								if ( ver > v.intValue()){
+									
+									hits.put( hw, new Integer( ver ));								
+								}
+							}else{
+								
+								new_sid = true;
+																
+								hits.put( hw, new Integer( ver ));
+							}
+						}
+						
+						if ( new_sid ){
+							
+							log( "    Found subscription " + ByteFormatter.encodeString( sid ) + " version " + ver );
+
+								// check if already subscribed
+							
+							SubscriptionImpl subs = getSubscriptionFromSID( sid );
+							
+							if ( subs != null ){
+								
+								synchronized( hits ){
+								
+									found_subscriptions.add( subs );
+								}
+								
+								try{
+									listener.found( hash, subs );
+									
+								}catch( Throwable e ){
+									
+									Debug.printStackTrace(e);
+								}
+																
+								hits_sem.release();
+								
+							}else{
+								
+									// don't want to block the DHT processing
+								
+								dispatcher.dispatch(
+									new AERunnable()
+									{
+										public void
+										runSupport()
+										{
+											lookupSubscription( 
+												hash, 
+												sid, 
+												ver,
+												new subsLookupListener()
+												{
+													private boolean sem_done = false;
+													
+													public void
+													found(
+														byte[]					hash,
+														Subscription			subscription )
+													{
+													}
+													
+													public void
+													complete(
+														byte[]					hash,
+														Subscription[]			subscriptions )
+													{
+														done( subscriptions );
+													}
+													
+													public void
+													failed(
+														byte[]					hash,
+														SubscriptionException	error )
+													{
+														done( new Subscription[0]);
+													}
+													
+													protected void
+													done(
+														Subscription[]			subs )
+													{
+														if ( isCancelled()){
+															
+															return;
+														}
+														
+														synchronized( this ){
+															
+															if ( sem_done ){
+																
+																return;
+															}
+															
+															sem_done = true;
+														}
+														
+														if ( subs.length > 0 ){
+															
+															synchronized( hits ){
+															
+																found_subscriptions.add( subs[0] );
+															}
+															
+															try{
+																listener.found( hash, subs[0] );
+																
+															}catch( Throwable e ){
+																
+																Debug.printStackTrace(e);
+															}
+														}
+																									
+														hits_sem.release();
+													}
+													
+													public boolean 
+													isCancelled() 
+													{
+														return( isCancelled2());
+													}
+												});
+										}
+									});
+							}
+						}
+					}
+				}
+				
+				public void
+				valueWritten(
+					DHTPluginContact	target,
+					DHTPluginValue		value )
+				{
+				}
+				
+				public void
+				complete(
+					byte[]				original_key,
+					boolean				timeout_occurred )
+				{
+					dispatcher.dispatch(
+						new AERunnable()
+						{
+							public void
+							runSupport()
+							{
+								int	num_hits;
+								
+								synchronized( hits ){
+									
+									if ( complete ){
+										
+										return;
+									}
+									
+									complete = true;
+									
+									num_hits = hits.size();
+								}
+								
+								
+								for (int i=0;i<num_hits;i++){
+									
+									if ( isCancelled2()){
+										
+										return;
+									}
+	
+									hits_sem.reserve();
+								}
+	
+								if ( isCancelled2()){
+									
+									return;
+								}
+	
+								SubscriptionImpl[] s;
+								
+								synchronized( hits ){
+									
+									s = (SubscriptionImpl[])found_subscriptions.toArray( new SubscriptionImpl[ found_subscriptions.size() ]);
+								}
+								
+								log( "    Association lookup complete - " + s.length + " found" );
+	
+								try{	
+										// record zero assoc here for completeness
+									
+									recordAssociations( hash, s, true );
+									
+								}finally{
+									
+									listener.complete( hash, s );
+								}
+							}
+						});
+				}
+				
+				protected boolean
+				isCancelled2()
+				{
+					synchronized( cancelled ){
+						
+						return( cancelled[0] );
+					}
+				}
+			});
+		
+		return( 
+			new SubscriptionAssociationLookup()
+			{
+				public void 
+				cancel() 
+				{
+					log( "    Association lookup cancelled" );
+
+					synchronized( cancelled ){
+						
+						cancelled[0] = true;
+					}
+				}
+			});
+	}
+	
+	interface 
+	subsLookupListener
+		extends SubscriptionLookupListener
+	{
+		public boolean
+		isCancelled();
+	}
+	
+	protected void
+	getPopularity(
+		final SubscriptionImpl					subs,
+		final SubscriptionPopularityListener	listener )
+	
+		throws SubscriptionException
+	{
+		try{
+			long pop = PlatformSubscriptionsMessenger.getPopularityBySID( subs.getShortID());
+
+			if ( pop >= 0 ){	
+				
+				log( "Got popularity of " + subs.getName() + " from platform: " + pop );
+				
+				listener.gotPopularity( pop );
+
+				return;
+				
+			}else{
+				
+					// unknown sid - if singleton try to register for popularity tracking purposes
+				
+				if ( subs.isSingleton()){
+					
+					try{
+						checkSingletonPublish( subs );
+						
+					}catch( Throwable e ){						
+					}
+					
+					listener.gotPopularity( subs.isSubscribed()?1:0 );
+						
+					return;
+				}
+			}
+			
+		}catch( Throwable e ){
+			
+			log( "Subscription lookup via platform failed", e );
+		}
+		
+		getPopularityFromDHT( subs, listener, true );
+	}
+	
+	protected void
+	getPopularityFromDHT(
+		final SubscriptionImpl					subs,
+		final SubscriptionPopularityListener	listener,
+		final boolean							sync )
+
+	{
+		if ( dht_plugin != null && !dht_plugin.isInitialising()){
+
+			getPopularitySupport( subs, listener, sync );
+			
+		}else{
+			
+			new AEThread2( "SM:popwait", true )
+			{
+				public void
+				run()
+				{
+					getPopularitySupport( subs, listener, sync );
+				}
+			}.start();
+		}
+	}
+	
+	protected void
+	updatePopularityFromDHT(
+		final SubscriptionImpl		subs,
+		boolean						sync )
+	{
+		getPopularityFromDHT(
+			subs,
+			new SubscriptionPopularityListener()
+			{
+				public void
+				gotPopularity(
+					long						popularity )
+				{
+					subs.setCachedPopularity( popularity );
+				}
+				
+				public void
+				failed(
+					SubscriptionException		error )
+				{
+					log( "Failed to update subscription popularity from DHT", error );
+				}
+			},
+			sync );
+	}
+	
+	protected void
+	getPopularitySupport(
+		final SubscriptionImpl					subs,
+		final SubscriptionPopularityListener	listener,
+		final boolean							sync )
+	{
+		log( "Getting popularity of " + subs.getName() + " from DHT" );
+
+		byte[]	hash = subs.getPublicationHash();
+		
+		final AESemaphore sem = new AESemaphore( "SM:pop" );
+		
+		final long[] result = { -1 };
+		
+		final int timeout = 15*1000;
+		
+		dht_plugin.get(
+				hash,
+				"Popularity lookup for subscription " + subs.getName(),
+				DHTPlugin.FLAG_STATS,
+				5,
+				timeout,
+				false,
+				true,
+				new DHTPluginOperationListener()
+				{
+					private boolean	diversified;
+					
+					private int	hits = 0;
+					
+					public boolean
+					diversified()
+					{
+						diversified = true;
+						
+						return( false );
+					}
+					
+					public void 
+					starts(
+						byte[] 				key ) 
+					{
+					}
+					
+					public void
+					valueRead(
+						DHTPluginContact	originator,
+						DHTPluginValue		value )
+					{
+						DHTPluginKeyStats stats = dht_plugin.decodeStats( value );
+						
+						if ( stats != null ){
+							
+							result[0] = Math.max( result[0], stats.getEntryCount());
+						
+							hits++;
+							
+							if ( hits >= 3 ){
+								
+								done();
+							}
+						}
+					}
+					
+					public void
+					valueWritten(
+						DHTPluginContact	target,
+						DHTPluginValue		value )
+					{
+						
+					}
+					
+					public void
+					complete(
+						byte[]				key,
+						boolean				timeout_occurred )
+					{
+						if ( diversified ){
+							
+								// TODO: fix?
+							
+							result[0] *= 11;
+							
+							if ( result[0] == 0 ){
+								
+								result[0] = 10;
+							}
+						}
+						
+						done();
+					}
+					
+					protected void
+					done()
+					{						
+						if ( sync ){
+			
+							sem.release();
+
+						}else{
+							
+							if ( result[0] == -1 ){
+								
+								log( "Failed to get popularity of " + subs.getName() + " from DHT" );
+					
+								listener.failed( new SubscriptionException( "Timeout" ));
+								
+							}else{
+							
+								log( "Get popularity of " + subs.getName() + " from DHT: " + result[0] );
+					
+								listener.gotPopularity( result[0] );
+							}
+						}
+					}
+				});
+		
+		if ( sync ){
+			
+			sem.reserve( timeout );
+			
+			if ( result[0] == -1 ){
+				
+				log( "Failed to get popularity of " + subs.getName() + " from DHT" );
+	
+				listener.failed( new SubscriptionException( "Timeout" ));
+				
+			}else{
+			
+				log( "Get popularity of " + subs.getName() + " from DHT: " + result[0] );
+	
+				listener.gotPopularity( result[0] );
+			}
+		}
+	}
+	
+	protected void
+	lookupSubscription(
+		final byte[]						association_hash,
+		final byte[]						sid,
+		final int							version,
+		final subsLookupListener			listener )
+	{
+		try{
+			SubscriptionImpl subs = getSubscriptionFromPlatform( sid, SubscriptionImpl.ADD_TYPE_LOOKUP );
+
+			log( "Added temporary subscription: " + subs.getString());
+			
+			subs = addSubscription( subs );
+			
+			listener.complete( association_hash, new Subscription[]{ subs });
+			
+			return;
+			
+		}catch( Throwable e ){
+			
+			if ( listener.isCancelled()){
+				
+				return;
+			}
+			
+			final String sid_str = ByteFormatter.encodeString( sid );
+			
+			log( "Subscription lookup via platform for " + sid_str + " failed", e );
+			
+			if ( getSubscriptionDownloadCount() > 8 ){
+				
+				log( "Too many existing subscription downloads" );
+				
+				listener.complete( association_hash, new Subscription[0]);
+
+				return;
+			}
+			
+				// fall back to DHT
+			
+			log( "Subscription lookup via DHT starts for " + sid_str );
+
+			final String	key = "subscription:publish:" + ByteFormatter.encodeString( sid ) + ":" + version; 
+			
+			dht_plugin.get(
+				getKeyBytes(key),
+				"Subs lookup read: " + ByteFormatter.encodeString( sid ) + ":" + version,
+				DHTPlugin.FLAG_SINGLE_VALUE,
+				12,
+				60*1000,
+				false,
+				true,
+				new DHTPluginOperationListener()
+				{
+					private boolean listener_handled;
+					
+					public boolean
+					diversified()
+					{
+						return( true );
+					}
+					
+					public void 
+					starts(
+						byte[] 				key ) 
+					{
+					}
+					
+					public void
+					valueRead(
+						DHTPluginContact	originator,
+						DHTPluginValue		value )
+					{
+						byte[]	data = value.getValue();
+								
+						try{
+							final Map	details = decodeSubscriptionDetails( data );
+							
+							if ( SubscriptionImpl.getPublicationVersion( details ) == version ){
+																
+								Map	singleton_details = (Map)details.get( "x" );
+								
+								if ( singleton_details == null ){
+									
+									synchronized( this ){
+										
+										if ( listener_handled  ){
+											
+											return;
+										}
+										
+										listener_handled = true;
+									}
+									
+									log( "    found " + sid_str + ", non-singleton" );
+
+									new AEThread2( "Subs:lookup download", true )
+									{
+										public void
+										run()
+										{
+											downloadSubscription( 
+												association_hash,
+												SubscriptionImpl.getPublicationHash( details ),
+												sid,
+												version,
+												SubscriptionImpl.getPublicationSize( details ),
+												listener );
+										}
+									}.start();
+									
+								}else{
+																			
+									synchronized( this ){
+											
+										if ( listener_handled  ){
+												
+											return;
+										}
+											
+										listener_handled = true;
+									}
+									
+									log( "    found " + sid_str + ", singleton" );
+
+									try{
+										SubscriptionImpl subs = createSingletonSubscription( singleton_details, SubscriptionImpl.ADD_TYPE_LOOKUP, false );
+																			
+										listener.complete( association_hash, new Subscription[]{ subs });
+																			
+									}catch( Throwable e ){
+																					
+										listener.failed( association_hash, new SubscriptionException( "Subscription creation failed", e ));
+									}
+								}
+							}else{
+								
+								log( "    found " + sid_str + " but version mismatch" );
+
+							}
+						}catch( Throwable e ){
+							
+							log( "    found " + sid_str + " but verification failed", e );
+
+						}
+					}
+					
+					public void
+					valueWritten(
+						DHTPluginContact	target,
+						DHTPluginValue		value )
+					{
+					}
+					
+					public void
+					complete(
+						byte[]				original_key,
+						boolean				timeout_occurred )
+					{
+						if ( listener.isCancelled()){
+							
+							return;
+						}
+						
+						log( "    " + sid_str + " complete" );
+						
+						synchronized( this ){
+							
+							if ( !listener_handled ){
+						
+								listener_handled = true;
+								
+								listener.complete( association_hash, new Subscription[0] );
+							}
+						}
+					}
+				});
+		}
+	}
+	
+	protected SubscriptionImpl
+	getSubscriptionFromPlatform(
+		byte[]		sid,
+		int			add_type )
+	
+		throws SubscriptionException
+	{
+		try{
+			PlatformSubscriptionsMessenger.subscriptionDetails details = PlatformSubscriptionsMessenger.getSubscriptionBySID( sid );
+			
+			SubscriptionImpl res = getSubscriptionFromVuzeFileContent( sid, add_type, details.getContent());
+			
+			int	pop = details.getPopularity();
+			
+			if ( pop >= 0 ){
+				
+				res.setCachedPopularity( pop );
+			}
+			
+			return( res );
+			
+		}catch( SubscriptionException e ){
+			
+			throw( e );
+			
+		}catch( Throwable e ){
+			
+			throw( new SubscriptionException( "Failed to read subscription from platform", e ));
+		}
+	}
+	
+	protected SubscriptionImpl
+	getSubscriptionFromVuzeFile(
+		byte[]		sid,
+		int			add_type,
+		File		file )
+	
+		throws SubscriptionException
+	{
+		VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
+		
+		String	file_str = file.getAbsolutePath();
+		
+		VuzeFile vf = vfh.loadVuzeFile( file_str );
+
+		if ( vf == null ){
+			
+			log( "Failed to load vuze file from " + file_str );
+			
+			throw( new SubscriptionException( "Failed to load vuze file from " + file_str ));
+		}
+		
+		return( getSubscriptionFromVuzeFile( sid, add_type, vf ));
+	}
+	
+	protected SubscriptionImpl
+	getSubscriptionFromVuzeFileContent(
+		byte[]		sid,
+		int			add_type,
+		String		content )
+	
+		throws SubscriptionException
+	{
+		VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
+		
+		VuzeFile vf = vfh.loadVuzeFile( Base64.decode( content ));
+
+		if ( vf == null ){
+			
+			log( "Failed to load vuze file from " + content );
+			
+			throw( new SubscriptionException( "Failed to load vuze file from content" ));
+		}
+	
+		return( getSubscriptionFromVuzeFile( sid, add_type, vf ));
+	}
+	
+	protected SubscriptionImpl
+	getSubscriptionFromVuzeFile(
+		byte[]		sid,
+		int			add_type,
+		VuzeFile	vf )
+	
+		throws SubscriptionException
+	{
+		VuzeFileComponent[] comps = vf.getComponents();
+		
+		for (int j=0;j<comps.length;j++){
+			
+			VuzeFileComponent comp = comps[j];
+			
+			if ( comp.getType() == VuzeFileComponent.COMP_TYPE_SUBSCRIPTION ){
+				
+				Map map = comp.getContent();
+				
+				try{
+					SubscriptionBodyImpl body = new SubscriptionBodyImpl( SubscriptionManagerImpl.this, map );
+												
+					SubscriptionImpl new_subs = new SubscriptionImpl( SubscriptionManagerImpl.this, body, add_type, false );
+							
+					if ( Arrays.equals( new_subs.getShortID(), sid )){
+													
+						return( new_subs );
+					}
+				}catch( Throwable e ){
+					
+					log( "Subscription decode failed", e );
+				}
+			}
+		}
+		
+		throw( new SubscriptionException( "Subscription not found" ));
+	}
+	
+	protected void 
+	downloadSubscription(
+		final byte[]						association_hash,
+		byte[]								torrent_hash,
+		final byte[]						sid,
+		int									version,
+		int									size,
+		final subsLookupListener		 	listener )
+	{
+		try{
+			Object[] res = downloadTorrent( torrent_hash, size );
+			
+			if ( listener.isCancelled()){
+				
+				return;
+			}
+			
+			if ( res == null ){
+				
+				listener.complete( association_hash, new Subscription[0] );
+				
+				return;
+			}
+
+			downloadSubscription(
+				(TOTorrent)res[0], 
+				(InetSocketAddress)res[1],
+				sid,
+				version,
+				"Subscription " + ByteFormatter.encodeString( sid ) + " for " + ByteFormatter.encodeString( association_hash ),
+				new downloadListener()
+				{
+					public void
+					complete(
+						File		data_file )
+					{
+						boolean	reported = false;
+						
+						try{
+							if ( listener.isCancelled()){
+								
+								return;
+							}
+							
+							SubscriptionImpl subs = getSubscriptionFromVuzeFile( sid, SubscriptionImpl.ADD_TYPE_LOOKUP, data_file );
+						
+							log( "Added temporary subscription: " + subs.getString());
+							
+							subs = addSubscription( subs );
+							
+							listener.complete( association_hash, new Subscription[]{ subs });
+							
+							reported = true;
+	
+						}catch( Throwable e ){
+							
+							log( "Subscription decode failed", e );
+							
+						}finally{
+														
+							if ( !reported ){
+								
+								listener.complete( association_hash, new Subscription[0] );
+							}
+						}
+					}
+					
+					public void
+					complete(
+						Download	download,	
+						File		torrent_file )
+					{
+						File	data_file = new File( download.getSavePath());
+						
+						try{
+							removeDownload( download, false );
+
+							complete( data_file );
+							
+						}catch( Throwable e ){
+							
+							log( "Failed to remove download", e );
+							
+							listener.complete( association_hash, new Subscription[0] );
+							
+						}finally{
+							
+							torrent_file.delete();
+							
+							data_file.delete();
+						}
+					}
+						
+					public void
+					failed(
+						Throwable	error )
+					{
+						listener.complete( association_hash, new Subscription[0] );
+					}
+					
+					public Map
+					getRecoveryData()
+					{
+						return( null );
+					}
+					
+					public boolean
+					isCancelled()
+					{
+						return( listener.isCancelled());
+					}
+				});
+				
+		}catch( Throwable e ){
+			
+			log( "Subscription download failed",e );
+			
+			listener.complete( association_hash, new Subscription[0] );
+		}
+	}
+	
+	protected int
+	getSubscriptionDownloadCount()
+	{
+		PluginInterface pi = PluginInitializer.getDefaultInterface();
+		
+		Download[] downloads = pi.getDownloadManager().getDownloads();
+		
+		int	res = 0;
+		
+		for( int i=0;i<downloads.length;i++){
+			
+			Download	download = downloads[i];
+			
+			if ( download.getBooleanAttribute( ta_subs_download )){
+				
+				res++;
+			}
+		}
+		
+		return( res );
+	}
+	
+	protected void
+	associationAdded(
+		SubscriptionImpl			subscription,
+		byte[]						association_hash )
+	{
+		recordAssociations( association_hash, new SubscriptionImpl[]{ subscription }, false );
+
+		if ( dht_plugin != null ){
+			
+			publishAssociations();
+		}
+	}
+	
+	protected void
+	addPotentialAssociation(
+		SubscriptionImpl			subs,
+		String						result_id,
+		String						key )
+	{
+		if ( key == null ){
+			
+			Debug.out( "Attempt to add null key!" );
+			
+			return;
+		}
+		
+		log( "Added potential association: " + subs.getName() + "/" + result_id + " -> " + key );
+		
+		synchronized( potential_associations ){
+			
+			potential_associations.add( new Object[]{ subs, result_id, key, new Long( System.currentTimeMillis())} );
+			
+			if ( potential_associations.size() > 512 ){
+				
+				potential_associations.remove(0);
+			}
+		}
+	}
+	
+	protected void
+	checkPotentialAssociations(
+		byte[]				hash,
+		String				key )
+	{
+		log( "Checking potential association: " + key + " -> " + ByteFormatter.encodeString( hash ));
+		
+		SubscriptionImpl 	subs 		= null;
+		String				result_id	= null;
+		
+		synchronized( potential_associations ){
+
+			Iterator<Object[]> it = potential_associations.iterator();
+			
+			while( it.hasNext()){
+				
+				Object[]	entry = it.next();
+				
+				String	this_key = (String)entry[2];
+				
+					// startswith as actual URL may have had additional parameters added such as azid
+				
+				if ( key.startsWith( this_key )){
+					
+					subs		= (SubscriptionImpl)entry[0];
+					result_id	= (String)entry[1];
+					
+					log( "    key matched to subscription " + subs.getName() + "/" + result_id);
+
+					it.remove();
+					
+					break;
+				}
+			}
+		}
+		
+		if ( subs == null ){
+			
+			log( "    no potential associations found" );
+			
+		}else{
+			
+			SubscriptionResult	result = subs.getHistory().getResult( result_id );
+			
+			if ( result != null ){
+				
+				log( "    result found, marking as read" );
+
+				result.setRead( true );
+				
+			}else{
+				
+				log( "    result not found" );
+			}
+			
+			log( "    adding association" );
+			
+			subs.addAssociation( hash );
+		}
+	}
+	
+	protected void
+	tidyPotentialAssociations()
+	{
+		long	now = SystemTime.getCurrentTime();
+		
+		synchronized( potential_associations ){
+			
+			Iterator it = potential_associations.iterator();
+			
+			while( it.hasNext() && potential_associations.size() > 16 ){
+				
+				Object[]	entry = (Object[])it.next();
+				
+				long	created = ((Long)entry[3]).longValue();
+				
+				if ( created > now ){
+					
+					entry[3] = new Long( now );
+					
+				}else if ( now - created > 60*60*1000 ){
+					
+					SubscriptionImpl 	subs = (SubscriptionImpl)entry[0];
+
+					String	result_id	= (String)entry[1];
+					String	key			= (String)entry[2];
+
+					log( "Removing expired potential association: " + subs.getName() + "/" + result_id + " -> " + key );
+					
+					it.remove();
+				}
+			}
+		}
+		
+		synchronized( potential_associations2 ){
+			
+			Iterator it = potential_associations2.entrySet().iterator();
+			
+			while( it.hasNext() && potential_associations2.size() > 16 ){
+				
+				Map.Entry	map_entry = (Map.Entry)it.next();
+				
+				byte[]		hash = ((HashWrapper)map_entry.getKey()).getBytes();
+				
+				Object[]	entry = (Object[])map_entry.getValue();
+				
+				long	created = ((Long)entry[2]).longValue();
+				
+				if ( created > now ){
+					
+					entry[2] = new Long( now );
+					
+				}else if ( now - created > 60*60*1000 ){
+					
+					SubscriptionImpl[] 	subs = (SubscriptionImpl[])entry[0];
+
+					String	subs_str = "";
+					
+					for (int i=0;i<subs.length;i++){
+						subs_str += (i==0?"":",") + subs[i].getName();
+					}
+					
+					log( "Removing expired potential association: " + ByteFormatter.encodeString(hash) + " -> " + subs_str );
+					
+					it.remove();
+				}
+			}
+		}
+	}
+	
+	protected void
+	recordAssociations(
+		byte[]						association_hash,
+		SubscriptionImpl[]			subscriptions,
+		boolean						full_lookup )
+	{
+		HashWrapper	hw = new HashWrapper( association_hash );
+		
+		synchronized( potential_associations2 ){
+			
+			potential_associations2.put( hw, new Object[]{ subscriptions, new Boolean( full_lookup ), new Long( SystemTime.getCurrentTime())});
+		}
+			
+		if ( recordAssociationsSupport( association_hash, subscriptions, full_lookup )){
+			
+			synchronized( potential_associations2 ){
+
+				potential_associations2.remove( hw );
+			}
+		}else{
+			
+			log( "Deferring association for " + ByteFormatter.encodeString( association_hash ));
+		}
+	}
+	
+	protected boolean
+	recordAssociationsSupport(
+		byte[]						association_hash,
+		SubscriptionImpl[]			subscriptions,
+		boolean						full_lookup )
+	{
+		PluginInterface pi = PluginInitializer.getDefaultInterface();
+
+		boolean	download_found	= false;
+		boolean	changed 		= false;
+		
+		try{
+			Download download = pi.getDownloadManager().getDownload( association_hash );
+			
+			if ( download != null ){
+					
+				if ( subscriptions.length > 0 ){
+					
+					String	category = subscriptions[0].getCategory();
+					
+					if ( category != null ){
+						
+						String existing = download.getAttribute( ta_category );
+								
+						if ( existing == null ){
+									
+							download.setAttribute( ta_category, category );
+						}
+					}
+					
+					long	tag_id = subscriptions[0].getTagID();
+					
+					if ( tag_id >= 0 ){
+						
+						Tag tag = TagManagerFactory.getTagManager().lookupTagByUID( tag_id );
+
+						if ( tag != null ){
+							
+							org.gudy.azureus2.core3.download.DownloadManager core_dm = PluginCoreUtils.unwrap( download );
+							
+							if ( !tag.hasTaggable( core_dm )){
+								
+								tag.addTaggable( core_dm );
+							}
+						}
+					}
+					
+				}
+				
+				download_found = true;
+				
+				Map	map = download.getMapAttribute( ta_subscription_info );
+				
+				if ( map == null ){
+					
+					map = new LightHashMap();
+					
+				}else{
+					
+					map = new LightHashMap( map );
+				}
+				
+				List	s = (List)map.get( "s" );
+				
+				for (int i=0;i<subscriptions.length;i++){
+				
+					byte[]	sid = subscriptions[i].getShortID();
+					
+					if ( s == null ){
+						
+						s = new ArrayList();
+						
+						s.add( sid );
+						
+						changed	= true;
+						
+						map.put( "s", s );
+						
+					}else{
+						
+						boolean found = false;
+						
+						for (int j=0;j<s.size();j++){
+							
+							byte[]	existing = (byte[])s.get(j);
+							
+							if ( Arrays.equals( sid, existing )){
+								
+								found = true;
+								
+								break;
+							}
+						}
+						
+						if ( !found ){
+						
+							s.add( sid );
+								
+							changed	= true;
+						}
+					}
+				}
+				
+				if ( full_lookup ){
+				
+					map.put( "lc", new Long( SystemTime.getCurrentTime()));
+					
+					changed	= true;
+				}
+				
+				if ( changed ){
+				
+					download.setMapAttribute( ta_subscription_info, map );
+				}
+			}
+		}catch( Throwable e ){
+			
+			log( "Failed to record associations", e );
+		}
+		
+		if ( changed ){
+			
+			Iterator it = listeners.iterator();
+			
+			while( it.hasNext()){
+				
+				try{
+					((SubscriptionManagerListener)it.next()).associationsChanged( association_hash );
+					
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace(e);
+				}
+			}
+		}
+		
+		return( download_found );
+	}
+	
+	protected boolean
+	publishAssociations()
+	{
+		SubscriptionImpl 				subs_to_publish		= null;
+		SubscriptionImpl.association	assoc_to_publish 	= null;
+
+		synchronized( this ){
+			
+			if ( publish_associations_active >= ( dht_plugin.isSleeping()?PUB_SLEEPING_ASSOC_CONC_MAX:PUB_ASSOC_CONC_MAX )){
+				
+				return( false );
+			}			
+			
+			publish_associations_active++;
+			
+			List shuffled_subs = new ArrayList( subscriptions );
+
+			Collections.shuffle( shuffled_subs );
+							
+			for (int i=0;i<shuffled_subs.size();i++){
+					
+				SubscriptionImpl sub = (SubscriptionImpl)shuffled_subs.get( i );
+					
+				if ( sub.isSubscribed() && sub.isPublic()){
+					
+					assoc_to_publish 	= sub.getAssociationForPublish();
+						
+					if ( assoc_to_publish != null ){
+							
+						subs_to_publish		= sub;
+
+						break;
+					}
+				}
+			}
+		}
+		
+		if ( assoc_to_publish != null ){
+		
+			publishAssociation( subs_to_publish, assoc_to_publish );
+			
+			return( false );
+			
+		}else{
+					
+			log( "Publishing Associations Complete" );
+					
+			synchronized( this ){
+
+				publish_associations_active--;
+			}
+			
+			return( true );
+		}
+	}
+	
+	protected void
+	publishAssociation(
+		final SubscriptionImpl					subs,
+		final SubscriptionImpl.association		assoc )
+	{
+		log( "Checking association '" + subs.getString() + "' -> '" + assoc.getString() + "'" );
+		
+		byte[]	sub_id 		= subs.getShortID();
+		int		sub_version	= subs.getVersion();
+		
+		byte[]	assoc_hash	= assoc.getHash();
+		
+		final String	key = "subscription:assoc:" + ByteFormatter.encodeString( assoc_hash ); 
+				
+		final byte[]	put_value = new byte[sub_id.length + 4];
+		
+		System.arraycopy( sub_id, 0, put_value, 4, sub_id.length );
+		
+		put_value[0]	= (byte)(sub_version>>16);
+		put_value[1]	= (byte)(sub_version>>8);
+		put_value[2]	= (byte)sub_version;
+		put_value[3]	= (byte)subs.getFixedRandom();
+		
+		dht_plugin.get(
+			getKeyBytes(key),
+			"Subs assoc read: " + Base32.encode( assoc_hash ).substring( 0, 16 ),
+			DHTPlugin.FLAG_SINGLE_VALUE,
+			30,
+			60*1000,
+			false,
+			false,
+			new DHTPluginOperationListener()
+			{
+				private int			hits;
+				private boolean		diversified;
+				private int			max_ver;
+				
+				public boolean
+				diversified()
+				{
+					diversified = true;
+					
+					return( false );
+				}
+				
+				public void 
+				starts(
+					byte[] 				key ) 
+				{
+				}
+				
+				public void
+				valueRead(
+					DHTPluginContact	originator,
+					DHTPluginValue		value )
+				{
+					byte[]	val = value.getValue();
+					
+					if ( val.length == put_value.length ){
+						
+						boolean	diff = false;
+						
+						for (int i=4;i<val.length;i++){
+							
+							if ( val[i] != put_value[i] ){
+								
+								diff = true;
+								
+								break;
+							}
+						}
+						
+						if ( !diff ){
+							
+							hits++;
+							
+							int	ver = ((val[0]<<16)&0xff0000) | ((val[1]<<8)&0xff00) | (val[2]&0xff);
+							
+							if ( ver > max_ver ){
+								
+								max_ver = ver;
+							}
+						}
+					}
+				}
+				
+				public void
+				valueWritten(
+					DHTPluginContact	target,
+					DHTPluginValue		value )
+				{
+				}
+				
+				public void
+				complete(
+					byte[]				original_key,
+					boolean				timeout_occurred )
+				{
+					log( "Checked association '" + subs.getString() + "' -> '" + assoc.getString() + "' - max_ver=" + max_ver + ",hits=" + hits + ",div=" + diversified );
+
+					if ( max_ver > subs.getVersion()){
+						
+						if ( !subs.isMine()){
+						
+							updateSubscription( subs, max_ver );
+						}
+					}
+					
+					if ( hits < 10 && !diversified ){			
+			
+						log( "    Publishing association '" + subs.getString() + "' -> '" + assoc.getString() + "', existing=" + hits );
+
+						byte flags = DHTPlugin.FLAG_ANON;
+						
+						if ( hits < 3 && !diversified ){
+							
+							flags |= DHTPlugin.FLAG_PRECIOUS;
+						}
+						
+						dht_plugin.put(
+							getKeyBytes(key),
+							"Subs assoc write: " + Base32.encode( assoc.getHash()).substring( 0, 16 ) + " -> " + Base32.encode( subs.getShortID() ) + ":" + subs.getVersion(),
+							put_value,
+							flags,
+							new DHTPluginOperationListener()
+							{
+								public boolean
+								diversified()
+								{
+									return( true );
+								}
+								
+								public void 
+								starts(
+									byte[] 				key ) 
+								{
+								}
+								
+								public void
+								valueRead(
+									DHTPluginContact	originator,
+									DHTPluginValue		value )
+								{
+								}
+								
+								public void
+								valueWritten(
+									DHTPluginContact	target,
+									DHTPluginValue		value )
+								{
+								}
+								
+								public void
+								complete(
+									byte[]				key,
+									boolean				timeout_occurred )
+								{
+									log( "        completed '" + subs.getString() + "' -> '" + assoc.getString() + "'" );
+				
+									publishNext();
+								}
+							});
+					}else{
+						
+						log( "    Not publishing association '" + subs.getString() + "' -> '" + assoc.getString() + "', existing =" + hits );
+
+						publishNext();
+					}
+				}
+				
+				protected void
+				publishNext()
+				{
+					synchronized( SubscriptionManagerImpl.this ){
+						
+						publish_associations_active--;
+					}
+					
+					publishNextAssociation();
+				}
+			});
+	}
+	
+	private void
+	publishNextAssociation()
+	{
+		boolean	dht_sleeping = dht_plugin.isSleeping();
+		
+		if ( dht_sleeping ){
+			
+			synchronized( this ){
+				
+				if ( publish_next_asyc_pending ){
+					
+					return;
+				}
+				
+				publish_next_asyc_pending = true;
+			}
+			
+			SimpleTimer.addEvent(
+				"subs:pn:async",
+				SystemTime.getCurrentTime() + 60*1000,
+				new TimerEventPerformer()
+				{
+					public void 
+					perform(
+						TimerEvent event) 
+					{
+						synchronized( SubscriptionManagerImpl.this ){
+							
+							publish_next_asyc_pending = false;
+						}
+						
+						publishAssociations();
+					}
+				});
+			
+			return;
+		}
+		
+		publishAssociations();
+	}
+	
+	protected void
+	subscriptionUpdated()
+	{
+		if ( dht_plugin != null ){
+			
+			publishSubscriptions();
+		}
+	}
+	
+	protected void
+	publishSubscriptions()
+	{
+		List	 shuffled_subs;
+
+		synchronized( this ){
+			
+			if ( publish_subscription_active ){
+				
+				return;
+			}			
+			
+			shuffled_subs = new ArrayList( subscriptions );
+
+			publish_subscription_active = true;
+		}
+	
+		boolean	publish_initiated = false;
+		
+		try{
+			Collections.shuffle( shuffled_subs );
+						
+			for (int i=0;i<shuffled_subs.size();i++){
+				
+				SubscriptionImpl sub = (SubscriptionImpl)shuffled_subs.get( i );
+				
+				if ( sub.isSubscribed() && sub.isPublic() && !sub.getPublished()){
+									
+					sub.setPublished( true );
+					
+					publishSubscription( sub );
+					
+					publish_initiated = true;
+					
+					break;
+				}
+			}
+		}finally{
+			
+			if ( !publish_initiated ){
+				
+				log( "Publishing Subscriptions Complete" );
+				
+				synchronized( this ){
+	
+					publish_subscription_active = false;
+				}
+			}
+		}
+	}
+	
+	protected void
+	publishSubscription(
+		final SubscriptionImpl					subs )
+	{
+		log( "Checking subscription publication '" + subs.getString() + "'" );
+		
+		byte[]	sub_id 		= subs.getShortID();
+		int		sub_version	= subs.getVersion();
+				
+		final String	key = "subscription:publish:" + ByteFormatter.encodeString( sub_id ) + ":" + sub_version; 
+						
+		dht_plugin.get(
+			getKeyBytes(key),
+			"Subs presence read: " + ByteFormatter.encodeString( sub_id ) + ":" + sub_version,
+			DHTPlugin.FLAG_SINGLE_VALUE,
+			24,
+			60*1000,
+			false,
+			false,
+			new DHTPluginOperationListener()
+			{
+				private int		hits;
+				private boolean	diversified;
+				
+				public boolean
+				diversified()
+				{					
+					diversified = true;
+					
+					return( false );
+				}
+				
+				public void 
+				starts(
+					byte[] 				key ) 
+				{
+				}
+				
+				public void
+				valueRead(
+					DHTPluginContact	originator,
+					DHTPluginValue		value )
+				{					
+					byte[]	data = value.getValue();
+						
+					try{
+						Map	details = decodeSubscriptionDetails( data );
+
+						if ( subs.getVerifiedPublicationVersion( details ) == subs.getVersion()){
+						
+							hits++;
+						}
+					}catch( Throwable e ){
+						
+					}
+				}
+				
+				public void
+				valueWritten(
+					DHTPluginContact	target,
+					DHTPluginValue		value )
+				{
+				}
+				
+				public void
+				complete(
+					byte[]				original_key,
+					boolean				timeout_occurred )
+				{
+					log( "Checked subscription publication '" + subs.getString() + "' - hits=" + hits + ",div=" + diversified );
+
+					if ( hits < 10 && !diversified ){			
+			
+						log( "    Publishing subscription '" + subs.getString() + ", existing=" + hits );
+
+						try{
+							byte[]	put_value = encodeSubscriptionDetails( subs );						
+							
+							if ( put_value.length < DHTPlugin.MAX_VALUE_SIZE ){
+								
+								byte	flags = DHTPlugin.FLAG_SINGLE_VALUE;
+								
+								if ( hits < 3 && !diversified ){
+									
+									flags |= DHTPlugin.FLAG_PRECIOUS;
+								}
+								
+								dht_plugin.put(
+									getKeyBytes(key),
+									"Subs presence write: " + Base32.encode( subs.getShortID() ) + ":" + subs.getVersion(),
+									put_value,
+									flags,
+									new DHTPluginOperationListener()
+									{
+										public boolean
+										diversified()
+										{
+											return( true );
+										}
+										
+										public void 
+										starts(
+											byte[] 				key ) 
+										{
+										}
+										
+										public void
+										valueRead(
+											DHTPluginContact	originator,
+											DHTPluginValue		value )
+										{
+										}
+										
+										public void
+										valueWritten(
+											DHTPluginContact	target,
+											DHTPluginValue		value )
+										{
+										}
+										
+										public void
+										complete(
+											byte[]				key,
+											boolean				timeout_occurred )
+										{
+											log( "        completed '" + subs.getString() + "'" );
+						
+											publishNext();
+										}
+									});
+								
+							}else{
+								
+								publishNext();
+							}
+						}catch( Throwable e ){
+							
+							Debug.printStackTrace( e );
+							
+							publishNext();
+						}
+						
+					}else{
+						
+						log( "    Not publishing subscription '" + subs.getString() + "', existing =" + hits );
+
+						publishNext();
+					}
+				}
+				
+				protected void
+				publishNext()
+				{
+					synchronized( SubscriptionManagerImpl.this ){
+						
+						publish_subscription_active = false;
+					}
+					
+					publishSubscriptions();
+				}
+			});
+	}
+	
+	protected void
+	updateSubscription(
+		final SubscriptionImpl		subs,
+		final int					new_version )
+	{
+		log( "Subscription " + subs.getString() + " - higher version found: " + new_version );
+		
+		if ( !subs.canAutoUpgradeCheck()){
+			
+			log( "    Checked too recently or not updateable, ignoring" );
+			
+			return;
+		}
+		
+		if ( subs.getHighestUserPromptedVersion() >= new_version ){
+			
+			log( "    User has already been prompted for version " + new_version + " so ignoring" );
+			
+			return;
+		}
+					
+		byte[]	sub_id 		= subs.getShortID();
+			
+		try{
+			PlatformSubscriptionsMessenger.subscriptionDetails details = PlatformSubscriptionsMessenger.getSubscriptionBySID( sub_id );
+			
+			if ( !askIfCanUpgrade( subs, new_version )){
+				
+				return;
+			}
+			
+			VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
+			
+			VuzeFile vf = vfh.loadVuzeFile( Base64.decode( details.getContent()));
+							
+			vfh.handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_SUBSCRIPTION );
+			
+			return;
+			
+		}catch( Throwable e ){
+			
+			log( "Failed to read subscription from platform, trying DHT" );
+		}
+		
+		log( "Checking subscription '" + subs.getString() + "' upgrade to version " + new_version );
+
+		final String	key = "subscription:publish:" + ByteFormatter.encodeString( sub_id ) + ":" + new_version; 
+						
+		dht_plugin.get(
+			getKeyBytes(key),
+			"Subs update read: " + Base32.encode( sub_id ) + ":" + new_version,
+			DHTPlugin.FLAG_SINGLE_VALUE,
+			12,
+			60*1000,
+			false,
+			false,
+			new DHTPluginOperationListener()
+			{
+				private byte[]	verified_hash;
+				private int		verified_size;
+				
+				public boolean
+				diversified()
+				{
+					return( true );
+				}
+				
+				public void 
+				starts(
+					byte[] 				key ) 
+				{
+				}
+				
+				public void
+				valueRead(
+					DHTPluginContact	originator,
+					DHTPluginValue		value )
+				{
+					byte[]	data = value.getValue();
+							
+					try{
+						Map	details = decodeSubscriptionDetails( data );
+						
+						if ( 	verified_hash == null && 
+								subs.getVerifiedPublicationVersion( details ) == new_version ){
+							
+							verified_hash 	= SubscriptionImpl.getPublicationHash( details );
+							verified_size	= SubscriptionImpl.getPublicationSize( details );
+						}
+						
+					}catch( Throwable e ){
+						
+					}
+				}
+				
+				public void
+				valueWritten(
+					DHTPluginContact	target,
+					DHTPluginValue		value )
+				{
+				}
+				
+				public void
+				complete(
+					byte[]				original_key,
+					boolean				timeout_occurred )
+				{
+					if ( verified_hash != null ){			
+			
+						log( "    Subscription '" + subs.getString() + " upgrade verified as authentic" );
+
+						updateSubscription( subs, new_version, verified_hash, verified_size );
+						
+					}else{
+						
+						log( "    Subscription '" + subs.getString() + " upgrade not verified" );
+					}
+				}
+			});
+	}
+	
+	protected byte[]
+	encodeSubscriptionDetails(
+		SubscriptionImpl		subs )
+	
+		throws IOException
+	{
+		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();
+				
+		GZIPOutputStream os = new GZIPOutputStream( baos );
+
+		os.write( encoded );
+		
+		os.close();
+		
+		byte[] compressed = baos.toByteArray();
+		
+		byte	header;
+		byte[]	data;
+		
+		if ( compressed.length < encoded.length ){
+			
+			header 	= 1;
+			data	= compressed; 
+		}else{
+			
+			header	= 0;
+			data	= encoded;
+		}
+				
+		byte[] result = new byte[data.length+1];
+		
+		result[0] = header;
+		
+		System.arraycopy( data, 0, result, 1, data.length );
+		
+		return( result );
+	}
+	
+	protected Map
+	decodeSubscriptionDetails(
+		byte[]			data )
+	
+		throws IOException
+	{
+		byte[]	to_decode;
+		
+		if ( data[0] == 0 ){
+			
+			to_decode = new byte[ data.length-1 ];
+			
+			System.arraycopy( data, 1, to_decode, 0, data.length - 1 );
+			
+		}else{
+			
+			GZIPInputStream is = new GZIPInputStream(new ByteArrayInputStream( data, 1, data.length - 1 ));
+			
+			to_decode = FileUtil.readInputStreamAsByteArray( is );
+			
+			is.close();
+		}
+		
+		Map res = BDecoder.decode( to_decode );
+		
+			// remove any injected random seed
+		
+		res.remove( "!" );
+		
+		return( res );
+	}
+	
+	protected void
+	updateSubscription(
+		final SubscriptionImpl			subs,
+		final int						update_version,
+		final byte[]					update_hash,
+		final int						update_size )
+	{
+		log( "Subscription " + subs.getString() + " - update hash=" + ByteFormatter.encodeString( update_hash ) + ", size=" + update_size );
+
+		new AEThread2( "SubsUpdate", true )
+		{
+			public void
+			run()
+			{
+				try{
+					Object[] res = downloadTorrent( update_hash, update_size );
+					
+					if ( res != null ){
+					
+						updateSubscription( subs, update_version, (TOTorrent)res[0], (InetSocketAddress)res[1] );
+					}
+				}catch( Throwable e ){
+					
+					log( "    update failed", e );
+				}
+			}
+		}.start();
+	}
+	
+	protected Object[]
+	downloadTorrent(
+		byte[]		hash,
+		int			update_size )
+	{
+		if ( !isSubsDownloadEnabled()){
+			
+			log( "    Can't download subscription " + Base32.encode( hash ) + " as feature disabled" );
+			
+			return( null );
+		}
+		
+		final MagnetPlugin	magnet_plugin = getMagnetPlugin();
+	
+		if ( magnet_plugin == null ){
+		
+			log( "    Can't download, no magnet plugin" );
+		
+			return( null );
+		}
+
+		try{
+			final InetSocketAddress[] sender = { null };
+			
+			byte[] torrent_data = magnet_plugin.download(
+				new MagnetPluginProgressListener()
+				{
+					public void
+					reportSize(
+						long	size )
+					{
+					}
+					
+					public void
+					reportActivity(
+						String	str )
+					{
+						log( "    MagnetDownload: " + str );
+					}
+					
+					public void
+					reportCompleteness(
+						int		percent )
+					{
+					}
+					
+					public void
+					reportContributor(
+						InetSocketAddress	address )
+					{
+						synchronized( sender ){
+						
+							sender[0] = address;
+						}
+					}
+
+					public boolean 
+					verbose() 
+					{
+						return( false );
+					}
+					
+					public boolean 
+					cancelled() 
+					{
+						return( false );
+					}
+				},
+				hash,
+				"",
+				new InetSocketAddress[0],
+				300*1000,
+				MagnetPlugin.FL_DISABLE_MD_LOOKUP );
+			
+			if ( torrent_data == null ){
+				
+				log( "    download failed - timeout" );
+				
+				return( null );
+			}
+			
+			log( "Subscription torrent downloaded" );
+			
+			TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedByteArray( torrent_data );
+		
+				// update size is just that of signed content, torrent itself is .vuze file
+				// so take this into account
+			
+			if ( torrent.getSize() > update_size + 10*1024 ){
+			
+				log( "Subscription download abandoned, torrent size is " + torrent.getSize() + ", underlying data size is " + update_size );
+				
+				return( null );
+			}
+			
+			if ( torrent.getSize() > 4*1024*1024 ){
+				
+				log( "Subscription download abandoned, torrent size is too large (" + torrent.getSize() + ")" );
+				
+				return( null );
+			}
+			
+			synchronized( sender ){
+			
+				return( new Object[]{ torrent, sender[0] });
+			}
+			
+		}catch( Throwable e ){
+			
+			log( "    download failed", e );
+			
+			return( null );
+		}
+	}
+	
+	protected void
+	downloadSubscription(
+		final TOTorrent			torrent,
+		final InetSocketAddress	peer,
+		byte[]					subs_id,
+		int						version,
+		String					name,
+		final downloadListener	listener )
+	{
+		try{
+				// testing purposes, see if local exists
+			
+			LightWeightSeed lws = LightWeightSeedManager.getSingleton().get( new HashWrapper( torrent.getHash()));
+	
+			if ( lws != null ){
+				
+				log( "Light weight seed found" );
+				
+				listener.complete( lws.getDataLocation());
+				
+			}else{
+				String	sid = ByteFormatter.encodeString( subs_id );
+				
+				File	dir = getSubsDir();
+				
+				dir = new File( dir, "temp" );
+				
+				if ( !dir.exists()){
+					
+					if ( !dir.mkdirs()){
+						
+						throw( new IOException( "Failed to create dir '" + dir + "'" ));
+					}
+				}
+				
+				final File	torrent_file 	= new File( dir, sid + "_" + version + ".torrent" );
+				final File	data_file 		= new File( dir, sid + "_" + version + ".vuze" );
+	
+				PluginInterface pi = PluginInitializer.getDefaultInterface();
+			
+				final DownloadManager dm = pi.getDownloadManager();
+				
+				Download download = dm.getDownload( torrent.getHash());
+				
+				if ( download == null ){
+					
+					log( "Adding download for subscription '" + new String(torrent.getName()) + "'" );
+					
+					boolean is_update = getSubscriptionFromSID( subs_id ) != null;
+					
+					PlatformTorrentUtils.setContentTitle(torrent, (is_update?"Update":"Download") + " for subscription '" + name + "'" );
+					
+						// PlatformTorrentUtils.setContentThumbnail(torrent, thumbnail);
+						
+					TorrentUtils.setFlag( torrent, TorrentUtils.TORRENT_FLAG_LOW_NOISE, true );
+					
+					Torrent t = new TorrentImpl( torrent );
+					
+					t.setDefaultEncoding();
+					
+					t.writeToFile( torrent_file );
+					
+					download = dm.addDownload( t, torrent_file, data_file );
+					
+					download.setFlag( Download.FLAG_DISABLE_AUTO_FILE_MOVE, true );
+
+					download.setBooleanAttribute( ta_subs_download, true );
+					
+					Map rd = listener.getRecoveryData();
+					
+					if ( rd != null ){
+						
+						download.setMapAttribute( ta_subs_download_rd, rd );
+					}
+				}else{
+					
+					log( "Existing download found for subscription '" + new String(torrent.getName()) + "'" );
+				}
+				
+				final Download f_download = download;
+				
+				final TimerEventPeriodic[] event = { null };
+				
+				event[0] = 
+					SimpleTimer.addPeriodicEvent(
+						"SM:cancelTimer",
+						10*1000,
+						new TimerEventPerformer()
+						{
+							private long	start_time = SystemTime.getMonotonousTime();
+							
+							public void 
+							perform(
+								TimerEvent ev ) 
+							{
+								boolean	kill = false;
+								
+								try{	
+									Download download = dm.getDownload( torrent.getHash());
+									
+									if ( listener.isCancelled() || download == null ){
+										
+										kill = true;
+										
+									}else{
+										
+										int	state = download.getState();
+										
+										if ( state == Download.ST_ERROR ){
+											
+											log( "Download entered error state, removing" );
+											
+											kill = true;
+											
+										}else{
+											
+											long	now = SystemTime.getMonotonousTime();
+											
+											long	running_for = now - start_time;
+											
+											if ( running_for > 10*60*1000 ){
+												
+												log( "Download hasn't completed in permitted time, removing" );
+												
+												kill = true;
+												
+											}else if ( running_for > 4*60*1000 ){
+												
+												if ( download.getStats().getDownloaded() == 0 ){
+													
+													log( "Download has zero downloaded, removing" );
+													
+													kill = true;
+												}
+											}else if ( running_for > 2*60*1000 ){
+													
+												DownloadScrapeResult scrape = download.getLastScrapeResult();
+												
+												if ( scrape == null || scrape.getSeedCount() <= 0 ){
+													
+													log( "Download has no seeds, removing" );
+													
+													kill = true;
+												}
+											}
+										}
+									}
+								}catch( Throwable e ){
+									
+									log( "Download failed", e );
+
+									kill = true;
+								}
+								
+								if ( kill && event[0] != null ){
+									
+									try{
+										event[0].cancel();
+										
+										if ( !listener.isCancelled()){
+																					
+											listener.failed( new SubscriptionException( "Download abandoned" ));
+										}
+									}finally{
+										
+										removeDownload( f_download, true );
+									
+										torrent_file.delete();
+									}
+								}
+							}
+						});
+				
+				download.addCompletionListener(
+					new DownloadCompletionListener()
+					{
+						public void 
+						onCompletion(
+							Download d ) 
+						{
+							listener.complete( d, torrent_file );
+						}
+					});
+				
+				if ( download.isComplete()){
+					
+					listener.complete( download, torrent_file  );
+					
+				}else{
+								
+					download.setForceStart( true );
+					
+					if ( peer != null ){
+					
+						download.addPeerListener(
+							new DownloadPeerListener()
+							{
+								public void
+								peerManagerAdded(
+									Download		download,
+									PeerManager		peer_manager )
+								{									
+									InetSocketAddress tcp = AddressUtils.adjustTCPAddress( peer, true );
+									InetSocketAddress udp = AddressUtils.adjustUDPAddress( peer, true );
+									
+									log( "    Injecting peer into download: " + tcp );
+
+									peer_manager.addPeer( tcp.getAddress().getHostAddress(), tcp.getPort(), udp.getPort(), true );
+								}
+								
+								public void
+								peerManagerRemoved(
+									Download		download,
+									PeerManager		peer_manager )
+								{							
+								}
+							});
+					}
+				}
+			}
+		}catch( Throwable e ){
+			
+			log( "Failed to add download", e );
+			
+			listener.failed( e );
+		}
+	}
+	
+	protected interface
+	downloadListener
+	{
+		public void
+		complete(
+			File		data_file );
+		
+		public void
+		complete(
+			Download	download,	
+			File		torrent_file );
+			
+		public void
+		failed(
+			Throwable	error );
+		
+		public Map
+		getRecoveryData();
+		
+		public boolean
+		isCancelled();
+	}
+	
+	protected void
+	updateSubscription(
+		final SubscriptionImpl		subs,
+		final int					new_version,
+		TOTorrent					torrent,
+		InetSocketAddress			peer )
+	{
+		log( "Subscription " + subs.getString() + " - update torrent: " + new String( torrent.getName()));
+
+		if ( !askIfCanUpgrade( subs, new_version )){
+			
+			return;
+		}
+			
+		downloadSubscription(
+			torrent,
+			peer,
+			subs.getShortID(),
+			new_version,
+			subs.getName(false),
+			new downloadListener()
+			{
+				public void
+				complete(
+					File		data_file )
+				{
+					updateSubscription( subs, data_file );
+				}
+				
+				public void
+				complete(
+					Download	download,	
+					File		torrent_file )
+				{
+					updateSubscription( subs, download, torrent_file, new File( download.getSavePath()));
+				}
+					
+				public void
+				failed(
+					Throwable	error )
+				{
+					log( "Failed to download subscription", error );
+				}
+				
+				public Map
+				getRecoveryData()
+				{
+					Map	rd = new HashMap();
+					
+					rd.put( "sid", subs.getShortID());
+					rd.put( "ver", new Long( new_version ));
+					
+					return( rd );
+				}
+				
+				public boolean
+				isCancelled()
+				{
+					return( false );
+				}
+			});
+	}
+
+	protected boolean
+	askIfCanUpgrade(
+		SubscriptionImpl		subs,
+		int						new_version )
+	{
+		subs.setHighestUserPromptedVersion( new_version );
+		
+		UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+		
+		String details = MessageText.getString(
+				"subscript.add.upgradeto.desc",
+				new String[]{ String.valueOf(new_version), subs.getName()});
+		
+		long res = ui_manager.showMessageBox(
+				"subscript.add.upgrade.title",
+				"!" + details + "!",
+				UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+		
+		if ( res != UIManagerEvent.MT_YES ){	
+		
+			log( "    User declined upgrade" );
+			
+			return( false );
+		}
+		
+		return( true );
+	}
+	
+	protected boolean
+	recoverSubscriptionUpdate(
+		Download				download,
+		final Map				rd )
+	{
+		byte[]	sid 	= (byte[])rd.get( "sid" );
+		int		version = ((Long)rd.get( "ver" )).intValue();
+		
+		final SubscriptionImpl subs = getSubscriptionFromSID( sid );
+		
+		if ( subs == null ){
+		
+			log( "Can't recover '" + download.getName() + "' - subscription " + ByteFormatter.encodeString( sid ) +  " not found" );
+			
+			return( false );
+		}
+		
+		downloadSubscription(
+				((TorrentImpl)download.getTorrent()).getTorrent(),
+				null,
+				subs.getShortID(),
+				version,
+				subs.getName(false),
+				new downloadListener()
+				{
+					public void
+					complete(
+						File		data_file )
+					{
+						updateSubscription( subs, data_file );
+					}
+					
+					public void
+					complete(
+						Download	download,	
+						File		torrent_file )
+					{
+						updateSubscription( subs, download, torrent_file, new File( download.getSavePath()));
+					}
+						
+					public void
+					failed(
+						Throwable	error )
+					{
+						log( "Failed to download subscription", error );
+					}
+					
+					public Map
+					getRecoveryData()
+					{
+						return( rd );
+					}
+					
+					public boolean
+					isCancelled()
+					{
+						return( false );
+					}
+				});
+		
+		return( true );
+	}
+	
+	protected void
+	updateSubscription(
+		SubscriptionImpl		subs,
+		Download				download,
+		File					torrent_file,
+		File					data_file )
+	{
+		try{
+			removeDownload( download, false );
+		
+			try{				
+				updateSubscription( subs, data_file );
+											
+			}finally{
+				
+				if ( !data_file.delete()){
+					
+					log( "Failed to delete update file '" + data_file + "'" );
+				}
+				
+				if ( !torrent_file.delete()){
+					
+					log( "Failed to delete update torrent '" + torrent_file + "'" );
+				}
+			}
+		}catch( Throwable e ){
+			
+			log( "Failed to remove update download", e );
+		}
+	}
+	
+	protected void
+	removeDownload(
+		Download		download,
+		boolean			remove_data )
+	{
+		try{
+			download.stop();
+			
+		}catch( Throwable e ){
+		}
+		
+		try{
+			download.remove( true, remove_data );
+			
+			log( "Removed download '" + download.getName() + "'" );
+			
+		}catch( Throwable e ){
+			
+			log( "Failed to remove download '" + download.getName() + "'", e );
+		}
+	}
+	
+	protected void
+	updateSubscription(
+		SubscriptionImpl		subs,
+		File					data_location )
+	{
+		log( "Updating subscription '" + subs.getString() + " using '" + data_location + "'" );
+		
+		VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
+			
+		VuzeFile vf = vfh.loadVuzeFile( data_location.getAbsolutePath());
+						
+		vfh.handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_SUBSCRIPTION );
+	}
+	
+	protected MagnetPlugin
+	getMagnetPlugin()
+	{
+		PluginInterface  pi  = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByClass( MagnetPlugin.class );
+	
+		if ( pi == null ){
+			
+			return( null );
+		}
+		
+		return((MagnetPlugin)pi.getPlugin());
+	}
+	
+	protected Engine
+	getEngine(
+		SubscriptionImpl		subs,
+		Map						json_map,
+		boolean					local_only )
+	
+		throws SubscriptionException
+	{
+		long id = ((Long)json_map.get( "engine_id" )).longValue();
+		
+		Engine engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().getEngine( id );
+		
+		if ( engine != null ){
+			
+			return( engine );
+		}
+
+		if ( !local_only ){
+			
+			try{
+				if ( id >= 0 && id < Integer.MAX_VALUE ){
+								
+					log( "Engine " + id + " not present, loading" );
+						
+						// vuze template but user hasn't yet loaded it
+						
+					try{
+						engine = MetaSearchManagerFactory.getSingleton().getMetaSearch().addEngine( id );
+									
+						return( engine );
+						
+					}catch( Throwable e ){
+					
+						throw( new SubscriptionException( "Failed to load engine '" + id + "'", e ));
+					}
+				}
+			}catch( Throwable e ){
+				
+				log( "Failed to load search template", e );
+			}
+		}
+		
+		engine = subs.extractEngine( json_map, id );
+		
+		if ( engine != null ){
+			
+			return( engine );
+		}
+		
+		throw( new SubscriptionException( "Failed to extract engine id " + id ));
+	}
+	
+	protected SubscriptionResultImpl[]
+	loadResults(
+		SubscriptionImpl			subs )
+	{
+		List	results = new ArrayList();
+		
+		try{
+			File	f = getResultsFile( subs );
+			
+			Map	map = FileUtil.readResilientFile( f );
+			
+			List	list = (List)map.get( "results" );
+			
+			if ( list != null ){
+			
+				SubscriptionHistoryImpl	history = (SubscriptionHistoryImpl)subs.getHistory();
+				
+				for (int i=0;i<list.size();i++){
+					
+					Map	result_map =(Map)list.get(i);
+					
+					try{
+						SubscriptionResultImpl result = new SubscriptionResultImpl( history, result_map );
+						
+						results.add( result );
+						
+					}catch( Throwable e ){
+						
+						log( "Failed to decode result '" + result_map + "'", e );
+					}
+				}
+			}
+			
+		}catch( Throwable e ){
+			
+			log( "Failed to load results for '" + subs.getName() + "' - continuing with empty result set", e );
+		}
+		
+		return((SubscriptionResultImpl[])results.toArray( new SubscriptionResultImpl[results.size()] ));
+	}
+	
+	protected void
+  	setCategoryOnExisting(
+  		SubscriptionImpl	subscription,
+  		String				old_category,
+  		String				new_category )
+  	{
+		PluginInterface default_pi = PluginInitializer.getDefaultInterface();
+
+  		Download[] downloads 	= default_pi.getDownloadManager().getDownloads();
+  		 		 		
+  		for ( Download d: downloads ){
+  			 			
+  			if ( subscriptionExists( d, subscription )){
+  					
+				String existing = d.getAttribute( ta_category );
+
+				if ( existing == null || existing.equals( old_category )){
+					
+					d.setAttribute( ta_category, new_category );
+				}
+  			}
+  		}
+  	}
+	
+	public int
+	getMaxNonDeletedResults()
+	{
+		return( COConfigurationManager.getIntParameter( CONFIG_MAX_RESULTS ));
+	}
+	
+	public void
+	setMaxNonDeletedResults(
+		int		max )
+	{
+		if ( max != getMaxNonDeletedResults()){
+			
+			COConfigurationManager.setParameter( CONFIG_MAX_RESULTS, max );
+		}
+	}
+	
+	public boolean
+	getAutoStartDownloads()
+	{
+		return( COConfigurationManager.getBooleanParameter( CONFIG_AUTO_START_DLS ));		
+	}
+	
+	public void
+	setAutoStartDownloads(
+		boolean		auto_start )
+	{
+		if ( auto_start != getAutoStartDownloads()){
+			
+			COConfigurationManager.setParameter( CONFIG_AUTO_START_DLS, auto_start );
+		}		
+	}
+	
+	public int
+	getAutoStartMinMB()
+	{
+		return( COConfigurationManager.getIntParameter( CONFIG_AUTO_START_MIN_MB ));
+	}
+	
+	public void
+	setAutoStartMinMB(
+		int			mb )
+	{
+		if ( mb != getAutoStartMinMB()){
+			
+			COConfigurationManager.setParameter( CONFIG_AUTO_START_MIN_MB, mb );
+		}
+	}
+
+	public int
+	getAutoStartMaxMB()
+	{
+		return( COConfigurationManager.getIntParameter( CONFIG_AUTO_START_MAX_MB ));
+	}
+	
+	public void
+	setAutoStartMaxMB(
+		int			mb )
+	{
+		if ( mb != getAutoStartMaxMB()){
+			
+			COConfigurationManager.setParameter( CONFIG_AUTO_START_MAX_MB, mb );
+		}
+	}
+	
+	protected boolean
+	shouldAutoStart(
+		Torrent		torrent )
+	{
+		if ( getAutoStartDownloads()){
+			
+			long	min = getAutoStartMinMB()*1024*1024L;
+			long	max = getAutoStartMaxMB()*1024*1024L;
+			
+			if ( min <= 0 && max <= 0 ){
+				
+				return( true );
+			}
+			
+			long size = torrent.getSize();
+			
+			if ( min > 0 && size < min ){
+				
+				return( false );
+			}
+			
+			if ( max > 0 && size > max ){
+				
+				return( false );
+			}
+			
+			return( true );
+			
+		}else{
+			
+			return( false );
+		}
+	}
+	
+	protected void
+ 	saveResults(
+ 		SubscriptionImpl			subs,
+ 		SubscriptionResultImpl[]	results )
+ 	{
+		try{
+			File	f = getResultsFile( subs );
+	
+			Map	map = new HashMap();
+			
+			List	list = new ArrayList( results.length );
+			
+			map.put( "results", list );
+			
+			for (int i=0;i<results.length;i++){
+				
+				list.add( results[i].toBEncodedMap());
+			}
+			
+			FileUtil.writeResilientFile( f, map );
+			
+		}catch( Throwable e ){
+			
+			log( "Failed to save results for '" + subs.getName(), e );
+		}
+ 	}
+	
+	private void
+	loadConfig()
+	{
+		if ( !FileUtil.resilientConfigFileExists( CONFIG_FILE )){
+			
+			return;
+		}
+		
+		log( "Loading configuration" );
+		
+		boolean	some_are_mine = false;
+		
+		synchronized( this ){
+			
+			Map map = FileUtil.readResilientConfigFile( CONFIG_FILE );
+			
+			List	l_subs = (List)map.get( "subs" );
+			
+			if ( l_subs != null ){
+				
+				for (int i=0;i<l_subs.size();i++){
+					
+					Map	m = (Map)l_subs.get(i);
+					
+					try{
+						SubscriptionImpl sub = new SubscriptionImpl( this, m );
+
+						int index = Collections.binarySearch(subscriptions, sub, new Comparator<Subscription>() {
+							public int compare(Subscription arg0, Subscription arg1) {
+								return arg0.getID().compareTo(arg1.getID());
+							}
+						});
+						if (index < 0) {
+							index = -1 * index - 1; // best guess
+
+							subscriptions.add( index, sub );
+						}
+
+						if ( sub.isMine()){
+							
+							some_are_mine = true;
+						}
+						
+						log( "    loaded " + sub.getString());
+						
+					}catch( Throwable e ){
+						
+						log( "Failed to import subscription from " + m, e );
+					}
+				}
+			}
+		}
+		
+		if ( some_are_mine ){
+							
+			addMetaSearchListener();
+		}
+	}
+	
+	protected void
+	configDirty(
+		SubscriptionImpl		subs )
+	{
+		changeSubscription( subs );
+		
+		configDirty();
+	}
+	
+	protected void
+	configDirty()
+	{
+		synchronized( this ){
+			
+			if ( config_dirty ){
+				
+				return;
+			}
+			
+			config_dirty = true;
+		
+			new DelayedEvent( 
+				"Subscriptions:save", 5000,
+				new AERunnable()
+				{
+					public void 
+					runSupport() 
+					{
+						synchronized( SubscriptionManagerImpl.this ){
+							
+							if ( !config_dirty ){
+
+								return;
+							}
+							
+							saveConfig();
+						}	
+					}
+				});
+		}
+	}
+	
+	protected void
+	saveConfig()
+	{
+		log( "Saving configuration" );
+		
+		synchronized( this ){
+			
+			config_dirty = false;
+			
+			if ( subscriptions.size() == 0 ){
+				
+				FileUtil.deleteResilientConfigFile( CONFIG_FILE );
+				
+			}else{
+				
+				Map map = new HashMap();
+				
+				List	l_subs = new ArrayList();
+				
+				map.put( "subs", l_subs );
+				
+				Iterator	it = subscriptions.iterator();
+				
+				while( it.hasNext()){
+					
+					SubscriptionImpl sub = (SubscriptionImpl)it.next();
+						
+					try{
+						l_subs.add( sub.toMap());
+						
+					}catch( Throwable e ){
+						
+						log( "Failed to save subscription " + sub.getString(), e );
+					}
+				}
+				
+				FileUtil.writeResilientConfigFile( CONFIG_FILE, map );
+			}
+		}
+	}
+	
+	private byte[]
+	getKeyBytes( 
+		String		key )
+	{
+		try{
+			return( key.getBytes( "UTF-8" ));
+			
+		}catch( UnsupportedEncodingException e ){
+			
+			Debug.out( e );
+			
+			return( key.getBytes());
+		}
+	}
+	private AEDiagnosticsLogger
+	getLogger()
+	{
+			// sync not required (and has caused deadlock) as AEDiagnostics handles singleton
+		
+		if ( logger == null ){
+			
+			logger = AEDiagnostics.getLogger( LOGGER_NAME );
+		}
+		
+		return( logger );
+	}
+	
+	public void 
+	log(
+		String 		s,
+		Throwable 	e )
+	{
+		AEDiagnosticsLogger diag_logger = getLogger();
+		
+		diag_logger.log( s );
+		diag_logger.log( e );
+	}
+	
+	public void 
+	log(
+		String 	s )
+	{
+		AEDiagnosticsLogger diag_logger = getLogger();
+		
+		diag_logger.log( s );
+	}
+	
+	public void
+	addListener(
+		SubscriptionManagerListener	listener )
+	{
+		listeners.add( listener );
+	}
+	
+	public void
+	removeListener(
+		SubscriptionManagerListener	listener )
+	{
+		listeners.remove( listener );
+	}
+	
+	public void
+	generate(
+		IndentWriter		writer )
+	{
+		writer.println( "Subscriptions" );
+			
+		try{
+			writer.indent();
+
+			Subscription[] subs = getSubscriptions();
+			
+			for (int i=0;i<subs.length;i++){
+				
+				SubscriptionImpl sub = (SubscriptionImpl)subs[i];
+				
+				sub.generate( writer );
+			}
+			
+		}finally{
+			
+			writer.exdent();
+		}
+	}
+	
+	private class
+	searchMatcher
+	{
+		private String[]	bits;
+		private int[]		bit_types;
+		private Pattern[]	bit_patterns;
+
+		protected 
+		searchMatcher(
+			String		term )
+		{
+			bits = Constants.PAT_SPLIT_SPACE.split(term.toLowerCase() );
+			
+			bit_types 		= new int[bits.length];
+			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 ){
+						}
+					}
+				}
+			}
+		}
+		
+		public boolean
+		matches(
+			String		str )
+		{			
+			// 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'
+									
+			str = str.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 = str.contains( bit );
+						
+					}else{
+					
+						hit = bit_patterns[i].matcher( str ).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;
+						}
+					}
+				}
+			}
+			
+			boolean res = match && at_least_one;
+				
+			return( res );
+		}
+	}
+	
+	public static void
+	main(
+		String[]	args )
+	{
+		final String 	NAME 	= "lalalal";
+		final String	URL_STR	= "http://www.vuze.com/feed/publisher/ALL/1";
+		
+		try{
+			//AzureusCoreFactory.create();
+			/*
+			Subscription subs = 
+				getSingleton(true).createSingletonRSS(
+						NAME,
+						new URL( URL_STR ),
+						240 );
+			
+			subs.getVuzeFile().write( new File( "C:\\temp\\srss.vuze" ));
+			
+			subs.remove();
+			*/
+			
+			VuzeFile	vf = VuzeFileHandler.getSingleton().create();
+			
+			Map	map = new HashMap();
+			
+			map.put( "name", NAME );
+			map.put( "url", URL_STR );
+			map.put( "public", new Long( 0 ));
+			map.put( "check_interval_mins", new Long( 345 ));
+			
+			vf.addComponent( VuzeFileComponent.COMP_TYPE_SUBSCRIPTION_SINGLETON, map );
+			
+			vf.write( new File( "C:\\temp\\srss_2.vuze" ) );
+
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionRSSFeed.java b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionRSSFeed.java
index 20c006d..67ebd1d 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionRSSFeed.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionRSSFeed.java
@@ -1,336 +1,335 @@
-/*
- * 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();
-		
-		if ( generator != null ){
-			
-			generator.registerProvider( PROVIDER, this );
-		}
-	}
-		
-	public boolean
-	isEnabled()
-	{
-		return( manager.isRSSPublishEnabled());
-	}
-	
-	public String
-	getFeedURL()
-	{
-		return( generator==null?"Feature Disabled":( 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 ){
-	
-					if ( s.isSearchTemplate()){
-						
-						continue;
-					}
-					
-					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>")));
-	}
-}
+/*
+ * Created on Jul 13, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.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();
+		
+		if ( generator != null ){
+			
+			generator.registerProvider( PROVIDER, this );
+		}
+	}
+		
+	public boolean
+	isEnabled()
+	{
+		return( manager.isRSSPublishEnabled());
+	}
+	
+	public String
+	getFeedURL()
+	{
+		return( generator==null?"Feature Disabled":( 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 ){
+	
+					if ( s.isSearchTemplate()){
+						
+						continue;
+					}
+					
+					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/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionResultImpl.java b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionResultImpl.java
index c960d91..faa4be0 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionResultImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionResultImpl.java
@@ -1,356 +1,378 @@
-/*
- * Created on Aug 7, 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.core.subs.impl;
-
-import java.util.*;
-
-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;
-import com.aelitis.azureus.util.JSONUtils;
-
-public class 
-SubscriptionResultImpl 
-	implements SubscriptionResult
-{
-	final private SubscriptionHistoryImpl	history;
-	
-	private byte[]		key1;
-	private byte[]		key2;
-	private boolean		read;
-	private boolean		deleted;
-	
-	private String		result_json;
-	
-	protected
-	SubscriptionResultImpl(
-		SubscriptionHistoryImpl		_history,
-		Result						result )
-	{
-		history = _history;
-		
-		Map	map = result.toJSONMap();
-		
-		result_json 	= JSONUtils.encodeToJSON( map );
-		read			= false;
-		
-		String	key1_str =  result.getEngine().getId() + ":" + result.getName();
-		
-		try{
-			byte[] sha1 = new SHA1Simple().calculateHash( key1_str.getBytes( "UTF-8" ));
-			
-			key1 = new byte[10];
-			
-			System.arraycopy( sha1, 0, key1, 0, 10 );
-			
-		}catch( Throwable e ){
-			
-			Debug.printStackTrace(e);
-		}
-		
-		String	uid = result.getUID();
-		
-		if ( uid != null && uid.length() > 0 ){
-		
-			String	key2_str = result.getEngine().getId() + ":" + uid;
-			
-			try{
-				byte[] sha1 = new SHA1Simple().calculateHash( key2_str.getBytes( "UTF-8" ));
-				
-				key2 = new byte[10];
-				
-				System.arraycopy( sha1, 0, key2, 0, 10 );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-	}
-	
-	protected 
-	SubscriptionResultImpl(
-		SubscriptionHistoryImpl		_history,
-		Map							map )
-	{
-		history = _history;
-		
-		key1		= (byte[])map.get( "key" );
-		key2		= (byte[])map.get( "key2" );
-		
-		read		= ((Long)map.get( "read")).intValue()==1;
-		
-		Long	l_deleted = (Long)map.get( "deleted" );
-		
-		if ( l_deleted != null ){
-			
-			deleted	= true;
-			
-		}else{
-		
-			try{
-				result_json	= new String((byte[])map.get( "result_json" ), "UTF-8" );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-	}
-	
-	protected boolean
-	updateFrom(
-		SubscriptionResultImpl	other )
-	{
-		if ( deleted ){
-			
-			return( false );
-		}
-		
-		if ( getJSON().equals( other.getJSON())){
-			
-			return( false );
-			
-		}else{
-			
-			key2		= other.getKey2();
-			result_json = other.getJSON();
-			
-			return( true );
-		}
-	}
-	
-	public String
-	getID()
-	{
-		return( Base32.encode( key1 ));
-	}
-	
-	protected byte[]
-	getKey1()
-	{
-		return( key1 );
-	}
-	
-	protected byte[]
-	getKey2()
-	{
-   		return( key2 );
-   	}
-	
-	public boolean
-	getRead()
-	{
-		return( read );
-	}
-	
-	public void
-	setRead(
-		boolean	_read )
-	{
-		if ( read != _read ){
-			
-			read	= _read;
-			
-			history.updateResult( this );
-		}
-	}
-	
-	protected void
-	setReadInternal(
-		boolean	_read )
-	{
-		read	= _read;
-	}
-	
-	public void
-	delete()
-	{
-		if ( !deleted ){
-			
-			deleted	= true;
-			
-			history.updateResult( this );
-		}
-	}
-	
-	protected void
-	deleteInternal()
-	{
-		deleted = true;
-	}
-	
-	public boolean
-	isDeleted()
-	{
-		return( deleted );
-	}
-	
-	protected Map
-	toBEncodedMap()
-	{
-		Map		map	= new HashMap();
-		
-		map.put( "key", key1 );
-		
-		if ( key2 != null ){
-			map.put( "key2", key2 );
-		}
-		
-		map.put( "read", new Long(read?1:0));
-		
-		if ( deleted ){
-			
-			map.put( "deleted", new Long(1));
-			
-		}else{
-		
-			try{
-				map.put( "result_json", result_json.getBytes( "UTF-8" ));
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-		
-		return( map );
-	}
-	
-	public Map
-	toJSONMap()
-	{
-		Map	map = JSONUtils.decodeJSON( result_json );
-		
-		map.put( "subs_is_read", new Boolean( read ));
-		map.put( "subs_id", getID());
-		
-		Result.adjustRelativeTerms( map );
-		
-			// migration - trim digits
-		
-		String size = (String)map.get( "l" );
-
-		if ( size != null ){
-			
-			size = DisplayFormatters.trimDigits( size, 3 );
-			
-			map.put( "l", size );
-		}
-		
-		return( map );
-	}
-	
-	private String
-	getJSON()
-	{
-		return( result_json );
-	}
-	
-	public String 
-	getDownloadLink() 
-	{
-		Map map = toJSONMap();
-		
-		String	link = (String)map.get( "dbl" );
-		
-		if ( link == null ){
-			
-			link = (String)map.get( "dl" );
-		}		
-		
-		return( link );
-	}
-	
-	public String 
-	getPlayLink() 
-	{
-		return((String)toJSONMap().get( "pl" ));
-	}
-	
-	public String 
-	getAssetHash() 
-	{
-		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, Base32.decode( 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 );
-	}
-}
+/*
+ * Created on Aug 7, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs.impl;
+
+import java.util.*;
+
+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;
+import com.aelitis.azureus.util.JSONUtils;
+
+public class 
+SubscriptionResultImpl 
+	implements SubscriptionResult
+{
+	final private SubscriptionHistoryImpl	history;
+	
+	private byte[]		key1;
+	private byte[]		key2;
+	private boolean		read;
+	private boolean		deleted;
+	
+	private String		result_json;
+	
+	protected
+	SubscriptionResultImpl(
+		SubscriptionHistoryImpl		_history,
+		Result						result )
+	{
+		history = _history;
+		
+		Map	map = result.toJSONMap();
+		
+		result_json 	= JSONUtils.encodeToJSON( map );
+		read			= false;
+		
+		String	key1_str =  result.getEngine().getId() + ":" + result.getName();
+		
+		try{
+			byte[] sha1 = new SHA1Simple().calculateHash( key1_str.getBytes( "UTF-8" ));
+			
+			key1 = new byte[10];
+			
+			System.arraycopy( sha1, 0, key1, 0, 10 );
+			
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+		}
+		
+		String	uid = result.getUID();
+		
+		if ( uid != null && uid.length() > 0 ){
+		
+			String	key2_str = result.getEngine().getId() + ":" + uid;
+			
+			try{
+				byte[] sha1 = new SHA1Simple().calculateHash( key2_str.getBytes( "UTF-8" ));
+				
+				key2 = new byte[10];
+				
+				System.arraycopy( sha1, 0, key2, 0, 10 );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+	}
+	
+	protected 
+	SubscriptionResultImpl(
+		SubscriptionHistoryImpl		_history,
+		Map							map )
+	{
+		history = _history;
+		
+		key1		= (byte[])map.get( "key" );
+		key2		= (byte[])map.get( "key2" );
+		
+		read		= ((Long)map.get( "read")).intValue()==1;
+		
+		Long	l_deleted = (Long)map.get( "deleted" );
+		
+		if ( l_deleted != null ){
+			
+			deleted	= true;
+			
+		}else{
+		
+			try{
+				result_json	= new String((byte[])map.get( "result_json" ), "UTF-8" );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+	}
+	
+	protected boolean
+	updateFrom(
+		SubscriptionResultImpl	other )
+	{
+		if ( deleted ){
+			
+			return( false );
+		}
+		
+		if ( getJSON().equals( other.getJSON())){
+			
+			return( false );
+			
+		}else{
+			
+			key2		= other.getKey2();
+			result_json = other.getJSON();
+			
+			return( true );
+		}
+	}
+	
+	public String
+	getID()
+	{
+		return( Base32.encode( key1 ));
+	}
+	
+	protected byte[]
+	getKey1()
+	{
+		return( key1 );
+	}
+	
+	protected byte[]
+	getKey2()
+	{
+   		return( key2 );
+   	}
+	
+	public boolean
+	getRead()
+	{
+		return( read );
+	}
+	
+	public void
+	setRead(
+		boolean	_read )
+	{
+		if ( read != _read ){
+			
+			read	= _read;
+			
+			history.updateResult( this );
+		}
+	}
+	
+	protected void
+	setReadInternal(
+		boolean	_read )
+	{
+		read	= _read;
+	}
+	
+	public void
+	delete()
+	{
+		if ( !deleted ){
+			
+			deleted	= true;
+			
+			history.updateResult( this );
+		}
+	}
+	
+	protected void
+	deleteInternal()
+	{
+		deleted = true;
+	}
+	
+	public boolean
+	isDeleted()
+	{
+		return( deleted );
+	}
+	
+	protected Map
+	toBEncodedMap()
+	{
+		Map		map	= new HashMap();
+		
+		map.put( "key", key1 );
+		
+		if ( key2 != null ){
+			map.put( "key2", key2 );
+		}
+		
+		map.put( "read", new Long(read?1:0));
+		
+		if ( deleted ){
+			
+			map.put( "deleted", new Long(1));
+			
+		}else{
+		
+			try{
+				map.put( "result_json", result_json.getBytes( "UTF-8" ));
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+		
+		return( map );
+	}
+	
+	public Map
+	toJSONMap()
+	{
+		Map	map = JSONUtils.decodeJSON( result_json );
+		
+		map.put( "subs_is_read", new Boolean( read ));
+		map.put( "subs_id", getID());
+		
+		Result.adjustRelativeTerms( map );
+		
+			// migration - trim digits
+		
+		String size = (String)map.get( "l" );
+
+		if ( size != null ){
+			
+			size = DisplayFormatters.trimDigits( size, 3 );
+			
+			map.put( "l", size );
+		}
+		
+		return( map );
+	}
+	
+	private String
+	getJSON()
+	{
+		return( result_json );
+	}
+	
+	public String 
+	getDownloadLink() 
+	{
+		Map map = toJSONMap();
+		
+			// meh, for magnet URIs we might well have a decent magnet stored against the "dl" and a
+			// link constructed from the hash only as "dlb" - check WebResult.java. So ignore the
+			// default one when a better one is available
+		
+		String	link = (String)map.get( "dbl" );
+		
+		if ( link != null ){
+			
+			if ( link.toLowerCase( Locale.US ).startsWith( "magnet:" )){
+				
+				String dl_link = (String)map.get( "dl" );
+				
+				if ( dl_link != null && dl_link.toLowerCase( Locale.US ).startsWith( "magnet:" )){
+					
+					link = dl_link;
+				}
+			}
+		}
+		
+		if ( link == null ){
+			
+			link = (String)map.get( "dl" );
+		}		
+		
+		return( link );
+	}
+	
+	public String 
+	getPlayLink() 
+	{
+		return((String)toJSONMap().get( "pl" ));
+	}
+	
+	public String 
+	getAssetHash() 
+	{
+		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	cdp_link = (String)map.get( "cdp" );
+
+		if ( cdp_link != null ){
+			result.put( SearchResult.PR_DETAILS_LINK, cdp_link );
+		}
+		
+		String	hash = (String)map.get( "h" );
+		if ( hash != null ){
+			result.put( SearchResult.PR_HASH, Base32.decode( 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/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionSchedulerImpl.java b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionSchedulerImpl.java
index 82e0809..821d286 100644
--- a/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionSchedulerImpl.java
+++ b/azureus3/src/com/aelitis/azureus/core/subs/impl/SubscriptionSchedulerImpl.java
@@ -1,684 +1,857 @@
-/*
- * Created on Aug 6, 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.core.subs.impl;
-
-import java.io.InputStream;
-import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
-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.AEThread2;
-import org.gudy.azureus2.core3.util.AsyncDispatcher;
-import org.gudy.azureus2.core3.util.SimpleTimer;
-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.TorrentUtils;
-import org.gudy.azureus2.core3.util.UrlUtils;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.download.DownloadManager;
-import org.gudy.azureus2.plugins.torrent.Torrent;
-import org.gudy.azureus2.plugins.utils.DelayedTask;
-import org.gudy.azureus2.plugins.utils.StaticUtilities;
-import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
-import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl;
-import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
-
-import com.aelitis.azureus.core.subs.Subscription;
-import com.aelitis.azureus.core.subs.SubscriptionDownloadListener;
-import com.aelitis.azureus.core.subs.SubscriptionException;
-import com.aelitis.azureus.core.subs.SubscriptionHistory;
-import com.aelitis.azureus.core.subs.SubscriptionManagerListener;
-import com.aelitis.azureus.core.subs.SubscriptionResult;
-import com.aelitis.azureus.core.subs.SubscriptionScheduler;
-
-import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
-import com.aelitis.azureus.util.ConstantsVuze;
-import com.aelitis.azureus.util.UrlFilter;
-
-public class 
-SubscriptionSchedulerImpl 
-	implements SubscriptionScheduler, SubscriptionManagerListener
-{
-	private static final Object			SCHEDULER_NEXT_SCAN_KEY 			= new Object();
-	private static final Object			SCHEDULER_FAILED_SCAN_CONSEC_KEY 	= new Object();
-	private static final Object			SCHEDULER_FAILED_SCAN_TIME_KEY 		= new Object();
-	
-	private static final int			FAIL_INIT_DELAY		= 10*60*1000;
-	private static final int			FAIL_MAX_DELAY		= 8*60*60*1000;
-	
-	private SubscriptionManagerImpl		manager;
-	
-	private Map	active_subscription_downloaders = new HashMap();
-	private boolean active_subs_download_is_auto;
-	
-	private Set	active_result_downloaders		= new HashSet();
-	
-	private AsyncDispatcher	result_downloader = new AsyncDispatcher();
-
-	private boolean		schedulng_permitted;
-	
-	private TimerEvent	schedule_event;
-	private boolean		schedule_in_progress;
-	private long		last_schedule;
-	
-	
-	protected
-	SubscriptionSchedulerImpl(
-		SubscriptionManagerImpl		_manager )
-	{
-		manager	= _manager;
-		
-		manager.addListener( this );
-		
-		DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "Subscriptions Scheduler", 
-			new Runnable()
-			{
-				public void
-				run()
-				{
-					synchronized( SubscriptionSchedulerImpl.this ){
-						
-						schedulng_permitted	= true;
-					}
-					
-					calculateSchedule();
-				}
-			});
-		
-		delayed_task.queue();
-	}
-	
-	public void 
-	downloadAsync(
-		Subscription 	subs, 
-		boolean 		is_auto )
-	
-		throws SubscriptionException 
-	{
-		download(
-			subs,
-			is_auto,
-			new SubscriptionDownloadListener()
-			{
-				public void
-				complete(
-					Subscription		subs )
-				{
-				}
-				
-				public void
-				failed(
-					Subscription			subs,
-					SubscriptionException	error )
-				{
-					log( "Async download of " + subs.getName() + " failed", error );
-				}
-			});
-	}
-	
-	public void 
-	download(
-		final Subscription 					subs,
-		final boolean						is_auto,
-		final SubscriptionDownloadListener 	listener )
-	{
-		new AEThread2( "SS:download", true )
-		{
-			public void
-			run()
-			{
-				try{
-					download( subs, is_auto );
-					
-					listener.complete( subs );
-					
-				}catch( SubscriptionException e ){
-					
-					listener.failed( subs, e );
-					
-				}catch( Throwable e ){
-					
-					listener.failed( subs, new SubscriptionException( "Download failed", e ));
-				}
-			}
-		}.start();
-	}
-	
-	public void 
-	download(
-		Subscription 	subs,
-		boolean			is_auto )
-	
-		throws SubscriptionException 
-	{
-		SubscriptionDownloader downloader;
-		
-		AESemaphore	sem = null;
-		
-		synchronized( active_subscription_downloaders ){
-			
-			List	waiting = (List)active_subscription_downloaders.get( subs );
-			
-			if ( waiting != null ){
-				
-				sem = new AESemaphore( "SS:waiter" );
-				
-				waiting.add( sem );
-				
-				if ( !is_auto ){
-					
-					active_subs_download_is_auto = false;
-				}
-			}else{
-							
-				active_subscription_downloaders.put( subs, new ArrayList());
-				
-				active_subs_download_is_auto = is_auto;
-			}
-	
-			downloader = new SubscriptionDownloader(manager, (SubscriptionImpl)subs );
-		}
-		
-		try{
-			if ( sem == null ){
-			
-				downloader.download();
-				
-			}else{
-				
-				sem.reserve();
-			}
-		}finally{
-			
-			boolean	was_auto;
-			
-			synchronized( active_subscription_downloaders ){
-
-				List waiting = (List)active_subscription_downloaders.remove( subs );
-				
-				if ( waiting != null ){
-					
-					for (int i=0;i<waiting.size();i++){
-						
-						((AESemaphore)waiting.get(i)).release();
-					}
-				}
-				
-				was_auto = active_subs_download_is_auto;
-			}
-			
-			((SubscriptionImpl)subs).fireDownloaded( was_auto );
-		}
-	}
-	
-	public void
-	download(
-		final Subscription			subs,
-		final SubscriptionResult	result )
-	{
-		String download_link = result.getDownloadLink();
-		
-		if ( download_link == null ){
-			
-			log( subs.getName() + ": can't download " + result.getID() + " as no direct download link available" );
-			
-			return;
-		}
-
-		if ( UrlFilter.getInstance().isWhitelisted( download_link )){
-			
-			ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetworkForURL( download_link );
-			
-			if ( cn == null ){
-				
-				cn = ConstantsVuze.getDefaultContentNetwork();
-			}
-			
-			download_link = cn.appendURLSuffix( download_link, false, true );
-		}
-		
-		final String	key = subs.getID() + ":" + result.getID();
-		final String	dl	= download_link;
-		
-		synchronized( active_result_downloaders ){
-
-			if ( active_result_downloaders.contains( key )){
-				
-				return;
-			}
-		
-			active_result_downloaders.add( key );
-			
-			result_downloader.dispatch(
-				new AERunnable()
-				{
-					public void 
-					runSupport() 
-					{
-						try{
-							boolean	retry = true;
-						
-							boolean	use_ref			= subs.getHistory().getDownloadWithReferer();
-							
-							boolean tried_ref_switch = false;
-							
-							while( retry ){
-								
-								retry = false;
-							
-								try{
-									TorrentUtils.setTLSDescription( "Subscription: " + subs.getName());
-
-									URL url = new URL(dl);
-																		
-									ResourceDownloaderFactory rdf = StaticUtilities.getResourceDownloaderFactory();
-									
-									ResourceDownloader url_rd = rdf.create( url );
-											
-									String referer = use_ref?subs.getReferer():null;
-									
-									UrlUtils.setBrowserHeaders( url_rd, referer );
-									
-									Engine engine = subs.getEngine();
-									
-									if ( engine instanceof WebEngine ){
-										
-										WebEngine we = (WebEngine)engine;
-										
-										if ( we.isNeedsAuth()){
-											
-											String cookies = we.getCookies();
-											
-											if ( cookies != null && cookies.length() > 0 ){
-												
-												url_rd.setProperty( "URL_Cookie", cookies );
-											}
-										}
-									}
-									
-									ResourceDownloader mr_rd = rdf.getMetaRefreshDownloader( url_rd );
-		
-									InputStream is = mr_rd.download();
-		
-									Torrent torrent = new TorrentImpl( TOTorrentFactory.deserialiseFromBEncodedInputStream( is ));
-														
-									// PlatformTorrentUtils.setContentTitle(torrent, torr );
-							
-									DownloadManager dm = PluginInitializer.getDefaultInterface().getDownloadManager();
-									
-									Download	download;
-									
-									boolean auto_start = manager.shouldAutoStart( torrent );
-									
-									if ( auto_start ){
-									
-										download = dm.addDownload( torrent );
-										
-									}else{
-									
-										download = dm.addDownloadStopped( torrent, null, null );
-									}
-									
-									log( subs.getName() + ": added download " + download.getName()+ ": auto-start=" + auto_start );
-
-									subs.addAssociation( torrent.getHash());
-									
-									result.setRead( true );
-																		
-									if ( tried_ref_switch ){
-										
-										subs.getHistory().setDownloadWithReferer( use_ref );
-									}
-								}catch( Throwable e ){
-									
-									log( subs.getName() + ": Failed to download result " + dl, e );
-									
-									if ( e instanceof TOTorrentException && !tried_ref_switch ){
-										
-										use_ref 			= !use_ref;
-										
-										tried_ref_switch	= true;
-										
-										retry				= true;
-										
-										log( subs.getName() + ": Retrying " + (use_ref?"with referer":"without referer" ));
-									}
-								}finally{
-									
-									TorrentUtils.setTLSDescription( null );
-								}
-							}
-						}finally{
-							
-							synchronized( active_result_downloaders ){
-
-								active_result_downloaders.remove( key );
-							}
-							
-							calculateSchedule();
-						}
-					}
-				});
-		}
-	}
-	
-	protected void
-	calculateSchedule()
-	{
-		Subscription[]	subs = manager.getSubscriptions( true );
-		
-		synchronized( this ){
-			
-			if ( !schedulng_permitted ){
-				
-				return;
-			}
-			
-			if ( schedule_in_progress ){
-				
-				return;
-			}
-			
-			long	next_ready_time = Long.MAX_VALUE;
-			
-			for (int i=0;i<subs.length;i++){
-				
-				Subscription sub = subs[i];
-								
-				SubscriptionHistory history = sub.getHistory();
-				
-				if ( !history.isEnabled()){
-					
-					continue;
-				}
-				
-				long	next_scan = getNextScan( sub );
-				
-				sub.setUserData( SCHEDULER_NEXT_SCAN_KEY, new Long( next_scan ));
-				
-				if ( next_scan < next_ready_time ){
-					
-					next_ready_time = next_scan;
-				}
-			}
-		
-			long	 old_when = 0;
-			
-			if ( schedule_event != null ){
-				
-				old_when = schedule_event.getWhen();
-				
-				schedule_event.cancel();
-				
-				schedule_event = null;
-			}
-			
-			if ( next_ready_time < Long.MAX_VALUE ){
-				
-				long	now = SystemTime.getCurrentTime();
-				
-				if ( 	now < last_schedule ||
-						now - last_schedule < 30*1000 ){
-					
-					if ( next_ready_time - now < 30*1000 ){
-						
-						next_ready_time = now + 30*1000;
-					}
-				}
-					
-				if ( next_ready_time < now ){
-					
-					next_ready_time = now;
-				}
-				
-				log( "Calculate : " + 
-						"old_time=" + new SimpleDateFormat().format(new Date(old_when)) +
-						", new_time=" + new SimpleDateFormat().format(new Date(next_ready_time)));
-						
-				schedule_event = SimpleTimer.addEvent(
-					"SS:Scheduler",
-					next_ready_time,
-					new TimerEventPerformer()
-					{
-						public void 
-						perform(
-							TimerEvent event ) 
-						{
-							synchronized( SubscriptionSchedulerImpl.this ){
-								
-								if ( schedule_in_progress ){
-									
-									return;
-								}
-								
-								schedule_in_progress = true;
-								
-								last_schedule = SystemTime.getCurrentTime();
-								
-								schedule_event = null;
-							}
-							
-							new AEThread2( "SS:Sched", true )
-							{
-								public void
-								run()
-								{
-									try{
-										schedule();
-
-									}finally{
-										
-										synchronized( SubscriptionSchedulerImpl.this ){
-											
-											schedule_in_progress = false;
-										}
-										
-										calculateSchedule();
-									}
-								}
-							}.start();						
-						}
-					});
-			}
-		}
-	}
-	
-	protected void
-	schedule()
-	{
-		Subscription[]	subs = manager.getSubscriptions( true );
-		
-		long now = SystemTime.getCurrentTime();
-			
-		for (int i=0;i<subs.length;i++){
-			
-			Subscription sub = subs[i];
-						
-			SubscriptionHistory history = sub.getHistory();
-			
-			if ( !history.isEnabled()){
-				
-				continue;
-			}
-			
-			synchronized( this ){
-				
-				Long	scan_due = (Long)sub.getUserData( SCHEDULER_NEXT_SCAN_KEY );
-				
-				if ( scan_due == null ){
-					
-					continue;
-				}
-				
-				long diff = now - scan_due.longValue();
-				
-				if ( diff < -10*1000 ){
-				
-					continue;
-				}
-				
-				sub.setUserData( SCHEDULER_NEXT_SCAN_KEY, null );
-			}
-			
-			long	last_scan = history.getLastScanTime();
-
-			try{
-					
-				download( sub, true );
-				
-			}catch( Throwable e ){
-				
-			}finally{
-				
-				long	new_last_scan = history.getLastScanTime();
-
-				if ( new_last_scan == last_scan ){
-					
-					scanFailed( sub );
-					
-				}else{
-					
-					scanSuccess( sub );
-				}
-			}
-		}
-	}
-	
-	protected long
-	getNextScan(
-		Subscription		sub )
-	{
-		SubscriptionHistory	history = sub.getHistory();
-				
-		Long fail_count = (Long)sub.getUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY );
-		
-		if ( fail_count != null ){
-			
-			long 	fail_time = ((Long)sub.getUserData( SCHEDULER_FAILED_SCAN_TIME_KEY )).longValue();
-			
-			long	fails = fail_count.longValue();
-			
-			long	backoff = FAIL_INIT_DELAY;
-			
-			for (int i=1;i<fails;i++){
-				
-				backoff <<= 1;
-				
-				if ( backoff > FAIL_MAX_DELAY ){
-					
-					backoff = FAIL_MAX_DELAY;
-					
-					break;
-				}
-			}
-			
-			return( fail_time + backoff );
-		}
-
-		return( history.getNextScanTime() );
-	}
-	
-	protected void
-	scanSuccess(
-		Subscription		sub )
-	{
-		sub.setUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY, null );
-	}
-	
-	protected void
-	scanFailed(
-		Subscription		sub )
-	{
-		sub.setUserData( SCHEDULER_FAILED_SCAN_TIME_KEY, new Long( SystemTime.getCurrentTime()));
-		
-		Long fail_count = (Long)sub.getUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY );
-		
-		if ( fail_count == null ){
-			
-			fail_count = new Long(1);
-			
-		}else{
-			
-			fail_count = new Long(fail_count.longValue()+1);
-		}
-		
-		sub.setUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY, fail_count );
-	}
-	
-	protected void
-	log(
-		String		str )
-	{
-		manager.log( "Scheduler: " + str );
-	}
-	
-	protected void
-	log(
-		String		str,
-		Throwable 	e )
-	{
-		manager.log( "Scheduler: " + str, e );
-	}
-	
-	public void
-	subscriptionAdded(
-		Subscription		subscription )
-	{
-		calculateSchedule();
-	}
-	
-	public void
-	subscriptionChanged(
-		Subscription		subscription )
-	{
-		calculateSchedule();
-	}
-	
-	public void 
-	subscriptionSelected(
-		Subscription subscription )
-	{		
-	}
-	
-	public void
-	subscriptionRemoved(
-		Subscription		subscription )
-	{
-		calculateSchedule();
-	}
-	
-	public void
-	associationsChanged(
-		byte[]				association_hash )
-	{
-	}
-}
+/*
+ * Created on Aug 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.core.subs.impl;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import org.gudy.azureus2.core3.torrent.TOTorrentException;
+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.AEThread2;
+import org.gudy.azureus2.core3.util.AsyncDispatcher;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.SimpleTimer;
+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.TorrentUtils;
+import org.gudy.azureus2.core3.util.UrlUtils;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadManager;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+import org.gudy.azureus2.plugins.utils.DelayedTask;
+import org.gudy.azureus2.plugins.utils.StaticUtilities;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloader;
+import org.gudy.azureus2.plugins.utils.resourcedownloader.ResourceDownloaderFactory;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.torrent.TorrentImpl;
+import org.gudy.azureus2.pluginsimpl.local.utils.UtilitiesImpl;
+
+import com.aelitis.azureus.core.proxy.AEProxyFactory;
+import com.aelitis.azureus.core.proxy.AEProxyFactory.PluginProxy;
+import com.aelitis.azureus.core.subs.Subscription;
+import com.aelitis.azureus.core.subs.SubscriptionDownloadListener;
+import com.aelitis.azureus.core.subs.SubscriptionException;
+import com.aelitis.azureus.core.subs.SubscriptionHistory;
+import com.aelitis.azureus.core.subs.SubscriptionManagerListener;
+import com.aelitis.azureus.core.subs.SubscriptionResult;
+import com.aelitis.azureus.core.subs.SubscriptionScheduler;
+import com.aelitis.azureus.core.cnetwork.ContentNetwork;
+import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
+import com.aelitis.azureus.util.ConstantsVuze;
+import com.aelitis.azureus.util.UrlFilter;
+
+public class 
+SubscriptionSchedulerImpl 
+	implements SubscriptionScheduler, SubscriptionManagerListener
+{
+	private static final Object			SCHEDULER_NEXT_SCAN_KEY 			= new Object();
+	private static final Object			SCHEDULER_FAILED_SCAN_CONSEC_KEY 	= new Object();
+	private static final Object			SCHEDULER_FAILED_SCAN_TIME_KEY 		= new Object();
+	
+	private static final int			FAIL_INIT_DELAY		= 10*60*1000;
+	private static final int			FAIL_MAX_DELAY		= 8*60*60*1000;
+	
+	private SubscriptionManagerImpl		manager;
+	
+	private Map	active_subscription_downloaders = new HashMap();
+	private boolean active_subs_download_is_auto;
+	
+	private Map<String,Long>	rate_limit_map = new HashMap<String, Long>();
+	
+	private Set	active_result_downloaders		= new HashSet();
+	
+	private AsyncDispatcher	result_downloader = new AsyncDispatcher();
+
+	private boolean		schedulng_permitted;
+	
+	private TimerEvent	schedule_event;
+	private boolean		schedule_in_progress;
+	private long		last_schedule;
+	
+	
+	protected
+	SubscriptionSchedulerImpl(
+		SubscriptionManagerImpl		_manager )
+	{
+		manager	= _manager;
+		
+		manager.addListener( this );
+		
+		DelayedTask delayed_task = UtilitiesImpl.addDelayedTask( "Subscriptions Scheduler", 
+			new Runnable()
+			{
+				public void
+				run()
+				{
+					synchronized( SubscriptionSchedulerImpl.this ){
+						
+						schedulng_permitted	= true;
+					}
+					
+					calculateSchedule();
+				}
+			});
+		
+		delayed_task.queue();
+	}
+	
+	public void 
+	downloadAsync(
+		Subscription 	subs, 
+		boolean 		is_auto )
+	
+		throws SubscriptionException 
+	{
+		download(
+			subs,
+			is_auto,
+			new SubscriptionDownloadListener()
+			{
+				public void
+				complete(
+					Subscription		subs )
+				{
+				}
+				
+				public void
+				failed(
+					Subscription			subs,
+					SubscriptionException	error )
+				{
+					log( "Async download of " + subs.getName() + " failed", error );
+				}
+			});
+	}
+	
+	public void 
+	download(
+		final Subscription 					subs,
+		final boolean						is_auto,
+		final SubscriptionDownloadListener 	listener )
+	{
+		new AEThread2( "SS:download", true )
+		{
+			public void
+			run()
+			{
+				try{
+					download( subs, is_auto );
+					
+					listener.complete( subs );
+					
+				}catch( SubscriptionException e ){
+					
+					listener.failed( subs, e );
+					
+				}catch( Throwable e ){
+					
+					listener.failed( subs, new SubscriptionException( "Download failed", e ));
+				}
+			}
+		}.start();
+	}
+	
+	public boolean 
+	download(
+		Subscription 	subs,
+		boolean			is_auto )
+	
+		throws SubscriptionException 
+	{
+		SubscriptionDownloader downloader;
+		
+		AESemaphore	sem = null;
+		
+		String rate_limits = manager.getRateLimits().trim();
+
+		synchronized( active_subscription_downloaders ){
+			
+			if ( rate_limits.length() > 0 ){
+				
+				try{
+					Engine engine = subs.getEngine();
+					
+					if ( engine instanceof WebEngine ){
+						
+						String url_str = ((WebEngine)engine).getSearchUrl( true );
+						
+						String host = new URL( url_str ).getHost();
+						
+						String[] bits = rate_limits.split( "," );
+						
+						for ( String bit: bits ){
+							
+							String[] temp = bit.trim().split( "=" );
+							
+							if ( temp.length == 2 ){
+								
+								String 	lhs = temp[0].trim();
+								
+								if ( lhs.equals( host )){
+									
+									int mins = Integer.parseInt( temp[1].trim());
+									
+									if ( mins > 0 ){
+										
+										long	now = SystemTime.getMonotonousTime();
+										
+										Long last = rate_limit_map.get( host );
+										
+										if ( last != null && now - last < mins*60*1000 ){
+											
+											if ( is_auto ){
+											
+												return( false );
+											
+											}else{
+											
+												throw( new SubscriptionException( "Rate limiting prevents download from " + host ));
+											}
+										}
+										
+										rate_limit_map.put( host, now );
+									}
+								}
+							}
+						}
+					}	
+				}catch( SubscriptionException e ){
+					
+					throw( e );
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+			
+			List	waiting = (List)active_subscription_downloaders.get( subs );
+			
+			if ( waiting != null ){
+				
+				sem = new AESemaphore( "SS:waiter" );
+				
+				waiting.add( sem );
+				
+				if ( !is_auto ){
+					
+					active_subs_download_is_auto = false;
+				}
+			}else{
+							
+				active_subscription_downloaders.put( subs, new ArrayList());
+				
+				active_subs_download_is_auto = is_auto;
+			}
+	
+			downloader = new SubscriptionDownloader(manager, (SubscriptionImpl)subs );
+		}
+		
+		try{
+			if ( sem == null ){
+			
+				downloader.download();
+				
+			}else{
+				
+				sem.reserve();
+			}
+			
+			return( true );
+			
+		}finally{
+			
+			boolean	was_auto;
+			
+			synchronized( active_subscription_downloaders ){
+
+				List waiting = (List)active_subscription_downloaders.remove( subs );
+				
+				if ( waiting != null ){
+					
+					for (int i=0;i<waiting.size();i++){
+						
+						((AESemaphore)waiting.get(i)).release();
+					}
+				}
+				
+				was_auto = active_subs_download_is_auto;
+			}
+			
+			((SubscriptionImpl)subs).fireDownloaded( was_auto );
+		}
+	}
+	
+	public void
+	download(
+		final Subscription			subs,
+		final SubscriptionResult	result )
+	{
+		String download_link = result.getDownloadLink();
+		
+		if ( download_link == null ){
+			
+			log( subs.getName() + ": can't download " + result.getID() + " as no direct download link available" );
+			
+			return;
+		}
+
+		if ( UrlFilter.getInstance().isWhitelisted( download_link )){
+			
+			ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetworkForURL( download_link );
+			
+			if ( cn == null ){
+				
+				cn = ConstantsVuze.getDefaultContentNetwork();
+			}
+			
+			download_link = cn.appendURLSuffix( download_link, false, true );
+		}
+		
+		final String	key = subs.getID() + ":" + result.getID();
+		final String	dl	= download_link;
+		
+		synchronized( active_result_downloaders ){
+
+			if ( active_result_downloaders.contains( key )){
+				
+				return;
+			}
+		
+			active_result_downloaders.add( key );
+			
+			result_downloader.dispatch(
+				new AERunnable()
+				{
+					public void 
+					runSupport() 
+					{
+						try{
+							boolean	retry = true;
+						
+							boolean	use_ref			= subs.getHistory().getDownloadWithReferer();
+							
+							boolean tried_ref_switch = false;
+							
+							while( retry ){
+								
+								retry = false;
+							
+								try{
+									TorrentUtils.setTLSDescription( "Subscription: " + subs.getName());
+
+									URL original_url = new URL(dl);
+													
+									PluginProxy plugin_proxy 	= null;
+									URL			current_url 	= original_url;
+									
+									Torrent torrent = null;
+									
+									try{
+
+										while( true ){
+											
+											try{
+												ResourceDownloaderFactory rdf = StaticUtilities.getResourceDownloaderFactory();
+												
+												ResourceDownloader url_rd = rdf.create( current_url, plugin_proxy==null?null:plugin_proxy.getProxy());
+												
+												if ( plugin_proxy != null ){
+													
+													url_rd.setProperty( "URL_HOST", original_url.getHost());
+												}
+																										
+												String referer = use_ref?subs.getReferer():null;
+												
+												UrlUtils.setBrowserHeaders( url_rd, referer );
+												
+												Engine engine = subs.getEngine();
+												
+												if ( engine instanceof WebEngine ){
+													
+													WebEngine we = (WebEngine)engine;
+													
+													if ( we.isNeedsAuth()){
+														
+														String cookies = we.getCookies();
+														
+														if ( cookies != null && cookies.length() > 0 ){
+															
+															url_rd.setProperty( "URL_Cookie", cookies );
+														}
+													}
+												}
+												
+												ResourceDownloader mr_rd = rdf.getMetaRefreshDownloader( url_rd );
+					
+												InputStream is = mr_rd.download();
+					
+												torrent = new TorrentImpl( TOTorrentFactory.deserialiseFromBEncodedInputStream( is ));
+												
+												break;
+												
+											}catch( Throwable e ){
+												
+												if ( plugin_proxy == null ){
+													
+													plugin_proxy = AEProxyFactory.getPluginProxy( "Subscription result download", original_url );
+												
+													if ( plugin_proxy != null ){
+													
+														current_url = plugin_proxy.getURL();
+														
+														continue;
+													}
+												}
+												
+												throw( e );
+											}
+										}
+									}finally{
+										
+										if ( plugin_proxy != null ){
+											
+											plugin_proxy.setOK( torrent != null);
+										}					
+										
+									}
+									
+									// PlatformTorrentUtils.setContentTitle(torrent, torr );
+							
+									DownloadManager dm = PluginInitializer.getDefaultInterface().getDownloadManager();
+									
+									Download	download;
+									
+									boolean auto_start = manager.shouldAutoStart( torrent );
+									
+									if ( auto_start ){
+									
+										download = dm.addDownload( torrent );
+										
+									}else{
+									
+										download = dm.addDownloadStopped( torrent, null, null );
+									}
+									
+									log( subs.getName() + ": added download " + download.getName()+ ": auto-start=" + auto_start );
+
+									subs.addAssociation( torrent.getHash());
+									
+									result.setRead( true );
+																		
+									if ( tried_ref_switch ){
+										
+										subs.getHistory().setDownloadWithReferer( use_ref );
+									}
+								}catch( Throwable e ){
+									
+									log( subs.getName() + ": Failed to download result " + dl, e );
+									
+									if ( e instanceof TOTorrentException && !tried_ref_switch ){
+										
+										use_ref 			= !use_ref;
+										
+										tried_ref_switch	= true;
+										
+										retry				= true;
+										
+										log( subs.getName() + ": Retrying " + (use_ref?"with referer":"without referer" ));
+									}
+								}finally{
+									
+									TorrentUtils.setTLSDescription( null );
+								}
+							}
+						}finally{
+							
+							synchronized( active_result_downloaders ){
+
+								active_result_downloaders.remove( key );
+							}
+							
+							calculateSchedule();
+						}
+					}
+				});
+		}
+	}
+	
+	protected void
+	calculateSchedule()
+	{
+		Subscription[]	subs = manager.getSubscriptions( true );
+		
+		synchronized( this ){
+			
+			if ( !schedulng_permitted ){
+				
+				return;
+			}
+			
+			if ( schedule_in_progress ){
+				
+				return;
+			}
+			
+			long	next_ready_time = Long.MAX_VALUE;
+			
+			Subscription	next_ready_subs = null;
+			
+			for (int i=0;i<subs.length;i++){
+				
+				Subscription sub = subs[i];
+								
+				SubscriptionHistory history = sub.getHistory();
+				
+				if ( !history.isEnabled()){
+					
+					continue;
+				}
+				
+				long	next_scan = getNextScan( sub );
+				
+				sub.setUserData( SCHEDULER_NEXT_SCAN_KEY, new Long( next_scan ));
+				
+				if ( next_scan < next_ready_time ){
+					
+					next_ready_time = next_scan;
+					
+					next_ready_subs = sub;
+				}
+			}
+		
+			long	 old_when = 0;
+			
+			if ( schedule_event != null ){
+				
+				old_when = schedule_event.getWhen();
+				
+				schedule_event.cancel();
+				
+				schedule_event = null;
+			}
+			
+			if ( next_ready_time < Long.MAX_VALUE ){
+				
+				long	now = SystemTime.getCurrentTime();
+				
+				if ( 	now < last_schedule ||
+						now - last_schedule < 30*1000 ){
+					
+					if ( next_ready_time - now < 30*1000 ){
+						
+						next_ready_time = now + 30*1000;
+					}
+				}
+					
+				if ( next_ready_time < now ){
+					
+					next_ready_time = now;
+				}
+				
+				log( "Calculate : " + 
+						"old_time=" + new SimpleDateFormat().format(new Date(old_when)) +
+						", new_time=" + new SimpleDateFormat().format(new Date(next_ready_time)) +
+						", next_sub=" + next_ready_subs.getName());
+						
+				schedule_event = SimpleTimer.addEvent(
+					"SS:Scheduler",
+					next_ready_time,
+					new TimerEventPerformer()
+					{
+						public void 
+						perform(
+							TimerEvent event ) 
+						{
+							synchronized( SubscriptionSchedulerImpl.this ){
+								
+								if ( schedule_in_progress ){
+									
+									return;
+								}
+								
+								schedule_in_progress = true;
+								
+								last_schedule = SystemTime.getCurrentTime();
+								
+								schedule_event = null;
+							}
+							
+							new AEThread2( "SS:Sched", true )
+							{
+								public void
+								run()
+								{
+									try{
+										schedule();
+
+									}finally{
+										
+										synchronized( SubscriptionSchedulerImpl.this ){
+											
+											schedule_in_progress = false;
+										}
+										
+										calculateSchedule();
+									}
+								}
+							}.start();						
+						}
+					});
+			}
+		}
+	}
+	
+	protected void
+	schedule()
+	{
+		Subscription[]	subs = manager.getSubscriptions( true );
+		
+		long now = SystemTime.getCurrentTime();
+		
+		subs = subs.clone();
+		
+		synchronized( this ){
+
+			Arrays.sort(
+				subs,
+				new Comparator<Subscription>()
+				{
+					public int 
+					compare(
+						Subscription s1, 
+						Subscription s2) 
+					{
+						Long	l1 = (Long)s1.getUserData( SCHEDULER_NEXT_SCAN_KEY );
+						Long	l2 = (Long)s2.getUserData( SCHEDULER_NEXT_SCAN_KEY );
+
+						if ( l1 == l2 ){
+							
+							return( 0 );
+							
+						}else if ( l1 == null ){
+							
+							return( 1 );
+							
+						}else if ( l2 == null ){
+							
+							return( -1 );
+							
+						}else{
+							
+							long diff = l1 - l2;
+							
+							if ( diff < 0 ){
+								
+								return( -1 )
+										;
+							}else if ( diff < 0 ){
+								
+								return( 1 );
+							}else{
+								
+								return( 0 );
+							}
+						}
+					}		
+				});
+		}
+		
+		for (int i=0;i<subs.length;i++){
+			
+			Subscription sub = subs[i];
+						
+			SubscriptionHistory history = sub.getHistory();
+			
+			if ( !history.isEnabled()){
+				
+				continue;
+			}
+			
+			synchronized( this ){
+				
+				Long	scan_due = (Long)sub.getUserData( SCHEDULER_NEXT_SCAN_KEY );
+				
+				if ( scan_due == null ){
+					
+					continue;
+				}
+				
+				long diff = now - scan_due.longValue();
+				
+				if ( diff < -10*1000 ){
+				
+					continue;
+				}
+				
+				sub.setUserData( SCHEDULER_NEXT_SCAN_KEY, null );
+			}
+			
+			long	last_scan = history.getLastScanTime();
+
+			boolean	download_attempted = true;
+			
+			try{	
+				download_attempted = download( sub, true );
+				
+			}catch( Throwable e ){
+								
+			}finally{
+				
+				if ( download_attempted ){
+					
+					long	new_last_scan = history.getLastScanTime();
+	
+					if ( new_last_scan == last_scan ){
+						
+						scanFailed( sub );
+						
+					}else{
+						
+						scanSuccess( sub );
+					}
+				}
+			}
+		}
+	}
+	
+	protected long
+	getNextScan(
+		Subscription		sub )
+	{
+		SubscriptionHistory	history = sub.getHistory();
+				
+		Long fail_count = (Long)sub.getUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY );
+		
+		if ( fail_count != null ){
+			
+			long 	fail_time = ((Long)sub.getUserData( SCHEDULER_FAILED_SCAN_TIME_KEY )).longValue();
+			
+			long	fails = fail_count.longValue();
+			
+			long	backoff = FAIL_INIT_DELAY;
+			
+			for (int i=1;i<fails;i++){
+				
+				backoff <<= 1;
+				
+				if ( backoff > FAIL_MAX_DELAY ){
+					
+					backoff = FAIL_MAX_DELAY;
+					
+					break;
+				}
+			}
+			
+			return( fail_time + backoff );
+		}
+
+		return( history.getNextScanTime() );
+	}
+	
+	protected void
+	scanSuccess(
+		Subscription		sub )
+	{
+		sub.setUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY, null );
+	}
+	
+	protected void
+	scanFailed(
+		Subscription		sub )
+	{
+		sub.setUserData( SCHEDULER_FAILED_SCAN_TIME_KEY, new Long( SystemTime.getCurrentTime()));
+		
+		Long fail_count = (Long)sub.getUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY );
+		
+		if ( fail_count == null ){
+			
+			fail_count = new Long(1);
+			
+		}else{
+			
+			fail_count = new Long(fail_count.longValue()+1);
+		}
+		
+		sub.setUserData( SCHEDULER_FAILED_SCAN_CONSEC_KEY, fail_count );
+	}
+	
+	protected void
+	log(
+		String		str )
+	{
+		manager.log( "Scheduler: " + str );
+	}
+	
+	protected void
+	log(
+		String		str,
+		Throwable 	e )
+	{
+		manager.log( "Scheduler: " + str, e );
+	}
+	
+	public void
+	subscriptionAdded(
+		Subscription		subscription )
+	{
+		calculateSchedule();
+	}
+	
+	public void
+	subscriptionChanged(
+		Subscription		subscription )
+	{
+		calculateSchedule();
+	}
+	
+	public void 
+	subscriptionSelected(
+		Subscription subscription )
+	{		
+	}
+	
+	public void
+	subscriptionRemoved(
+		Subscription		subscription )
+	{
+		calculateSchedule();
+	}
+	
+	public void
+	associationsChanged(
+		byte[]				association_hash )
+	{
+	}
+	
+	public void
+	subscriptionRequested(
+		URL					url )
+	{	
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/core/torrent/HasBeenOpenedListener.java b/azureus3/src/com/aelitis/azureus/core/torrent/HasBeenOpenedListener.java
index 3ef9c8b..43b1fda 100644
--- a/azureus3/src/com/aelitis/azureus/core/torrent/HasBeenOpenedListener.java
+++ b/azureus3/src/com/aelitis/azureus/core/torrent/HasBeenOpenedListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 28, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/core/torrent/PlatformTorrentUtils.java b/azureus3/src/com/aelitis/azureus/core/torrent/PlatformTorrentUtils.java
index f1f2679..621d803 100644
--- a/azureus3/src/com/aelitis/azureus/core/torrent/PlatformTorrentUtils.java
+++ b/azureus3/src/com/aelitis/azureus/core/torrent/PlatformTorrentUtils.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/SBC_ChatOverview.java b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/SBC_ChatOverview.java
new file mode 100644
index 0000000..61a219c
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/SBC_ChatOverview.java
@@ -0,0 +1,491 @@
+/**
+ * Created on May 10, 2013
+ *
+ * Copyright (C) Azureus Software, 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.plugins.net.buddy.swt;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+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.Text;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener;
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.Utils;
+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.TableViewFactory;
+
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.common.ToolBarItem;
+import com.aelitis.azureus.ui.common.table.TableColumnCore;
+import com.aelitis.azureus.ui.common.table.TableRowCore;
+import com.aelitis.azureus.ui.common.table.TableSelectionListener;
+import com.aelitis.azureus.ui.common.table.TableViewFilterCheck;
+import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
+import com.aelitis.azureus.ui.common.updater.UIUpdatable;
+import com.aelitis.azureus.ui.swt.columns.tag.*;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
+import com.aelitis.azureus.ui.swt.views.skin.InfoBarUtil;
+import com.aelitis.azureus.ui.swt.views.skin.SkinView;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginUtils;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.*;
+import com.aelitis.azureus.plugins.net.buddy.swt.columns.*;
+
+/**
+ * @author TuxPaper
+ * @created May 10, 2013
+ *
+ */
+public class SBC_ChatOverview
+	extends SkinView
+	implements 	UIUpdatable, UIPluginViewToolBarListener, TableViewFilterCheck<ChatInstance>, 
+				ChatManagerListener, TableViewSWTMenuFillListener, TableSelectionListener
+{
+
+	private static final String TABLE_CHAT = "ChatsView";
+
+	TableViewSWT<ChatInstance> tv;
+
+	private Text txtFilter;
+
+	private Composite table_parent;
+
+	private boolean columnsAdded = false;
+
+	private boolean listener_added;
+	
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener#toolBarItemActivated(com.aelitis.azureus.ui.common.ToolBarItem, long, java.lang.Object)
+	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
+			Object datasource) {
+		if ( tv == null || !tv.isVisible()){
+			return( false );
+		}
+		if (item.getID().equals("remove")) {
+			
+			Object[] datasources = tv.getSelectedDataSources().toArray();
+			
+			if ( datasources.length > 0 ){
+				
+				for (Object object : datasources) {
+					if (object instanceof ChatInstance) {
+						ChatInstance chat = (ChatInstance) object;
+						chat.destroy();
+					}
+				}
+				
+				return true;
+			}
+		}
+		
+		return false;
+	}
+
+	// @see com.aelitis.azureus.ui.common.table.TableViewFilterCheck#filterSet(java.lang.String)
+	public void filterSet(String filter) {
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener#refreshToolBarItems(java.util.Map)
+	public void refreshToolBarItems(Map<String, Long> list) {
+		if ( tv == null || !tv.isVisible()){
+			return;
+		}
+
+		boolean canEnable = false;
+		Object[] datasources = tv.getSelectedDataSources().toArray();
+		
+		if ( datasources.length > 0 ){
+			
+			for (Object object : datasources) {
+				if (object instanceof ChatInstance ) {
+					
+				}
+			}
+		}
+
+		list.put("remove", canEnable ? UIToolBarItem.STATE_ENABLED : 0);
+	}
+
+	// @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI()
+	public void updateUI() {
+		if (tv != null) {
+			tv.refreshTable(false);
+		}
+	}
+
+	// @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName()
+	public String getUpdateUIName() {
+		return "TagsView";
+	}
+
+	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectInitialShow(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
+	public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) {
+		initColumns();
+
+		new InfoBarUtil(skinObject, "chatsview.infobar", false,
+				"chats.infobar", "chats.view.infobar") {
+			public boolean allowShow() {
+				return true;
+			}
+		};
+
+		return null;
+	}
+
+	protected void initColumns() {
+		synchronized (SBC_ChatOverview.class) {
+
+			if (columnsAdded) {
+
+				return;
+			}
+
+			columnsAdded = true;
+		}
+
+		TableColumnManager tableManager = TableColumnManager.getInstance();
+
+		tableManager.registerColumn(ChatInstance.class, ColumnChatName.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnChatName(column);
+					}
+				});
+
+		tableManager.registerColumn(ChatInstance.class, ColumnChatMessageCount.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnChatMessageCount(column);
+					}
+				});
+		
+		tableManager.registerColumn(ChatInstance.class, ColumnChatUserCount.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnChatUserCount(column);
+					}
+				});
+
+		tableManager.registerColumn(ChatInstance.class, ColumnChatFavorite.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnChatFavorite(column);
+					}
+				});
+
+		tableManager.registerColumn(ChatInstance.class, ColumnChatMsgOutstanding.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnChatMsgOutstanding(column);
+					}
+				});
+
+		
+			// last
+		
+		tableManager.registerColumn(ChatInstance.class, ColumnChatStatus.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnChatStatus(column);
+					}
+				});
+
+		tableManager.setDefaultColumnNames(TABLE_CHAT,
+			new String[] {
+				
+				ColumnChatName.COLUMN_ID,
+				ColumnChatMessageCount.COLUMN_ID,
+				ColumnChatUserCount.COLUMN_ID,
+				ColumnChatFavorite.COLUMN_ID,
+				ColumnChatMsgOutstanding.COLUMN_ID,
+				
+				ColumnChatStatus.COLUMN_ID,
+
+			});
+		
+		tableManager.setDefaultSortColumnName(TABLE_CHAT, ColumnTagName.COLUMN_ID);
+	}
+
+	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectHidden(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
+	public Object skinObjectHidden(SWTSkinObject skinObject, Object params) {
+
+		if (tv != null) {
+
+			tv.delete();
+
+			tv = null;
+		}
+
+		Utils.disposeSWTObjects(new Object[] {
+			table_parent,
+		});
+		
+		BuddyPluginBeta beta = BuddyPluginUtils.getBetaPlugin();
+		
+		if ( beta != null) {
+			
+			beta.removeListener( this );
+			
+			listener_added = false;
+		}
+
+
+		return super.skinObjectHidden(skinObject, params);
+	}
+
+	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectShown(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
+	public Object skinObjectShown(SWTSkinObject skinObject, Object params) {
+		super.skinObjectShown(skinObject, params);
+		SWTSkinObject so_list = getSkinObject("chats-list");
+
+		if (so_list != null) {
+			initTable((Composite) so_list.getControl());
+		} else {
+			System.out.println("NO chats-list");
+			return null;
+		}
+		
+		if (tv == null) {
+			return null;
+		}
+
+		BuddyPluginBeta beta = BuddyPluginUtils.getBetaPlugin();
+		
+		if ( beta != null) {
+			
+			if ( !listener_added ){
+				
+				listener_added = true;
+			
+				beta.addListener(this, true);
+			}
+		}
+
+		return null;
+	}
+
+	@Override
+	public Object 
+	skinObjectDestroyed(
+		SWTSkinObject skinObject, 
+		Object params) 
+	{
+		if ( listener_added ){
+		
+			listener_added = false;
+			
+			BuddyPluginBeta beta = BuddyPluginUtils.getBetaPlugin();
+			
+			if ( beta != null) {
+				
+				beta.removeListener( this );
+			}
+		}			
+		
+		return super.skinObjectDestroyed(skinObject, params);
+	}
+	
+	/**
+	 * @param control
+	 *
+	 * @since 4.6.0.5
+	 */
+	private void initTable(Composite control) {
+		if ( tv == null ){
+			
+			tv = TableViewFactory.createTableViewSWT(ChatInstance.class, TABLE_CHAT, TABLE_CHAT,
+					new TableColumnCore[0], ColumnTagName.COLUMN_ID, SWT.MULTI
+							| SWT.FULL_SELECTION | SWT.VIRTUAL);
+			if (txtFilter != null) {
+				tv.enableFilterCheck(txtFilter, this);
+			}
+			tv.setRowDefaultHeight(16);
+	
+			table_parent = new Composite(control, SWT.BORDER);
+			table_parent.setLayoutData(Utils.getFilledFormData());
+			GridLayout layout = new GridLayout();
+			layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0;
+			table_parent.setLayout(layout);
+	
+			tv.addMenuFillListener( this );
+			tv.addSelectionListener(this, false);
+			
+			tv.initialize(table_parent);
+		}
+		
+		control.layout(true);
+	}
+
+	public void 
+	fillMenu(
+		String 	sColumnName, 
+		Menu 	menu )
+	{
+		List<Object>	ds = tv.getSelectedDataSources();
+		
+		final List<ChatInstance>	chats = new ArrayList<ChatInstance>();
+		
+		for ( Object obj: ds ){
+			
+			if ( obj instanceof ChatInstance ){
+				
+				chats.add((ChatInstance)obj);
+			}
+		}
+					
+		MenuItem itemRemove = new MenuItem(menu, SWT.PUSH);
+		
+		Messages.setLanguageText(itemRemove, "MySharesView.menu.remove");
+		
+		Utils.setMenuItemImage(itemRemove, "delete");
+
+		itemRemove.setEnabled(chats.size() > 0);
+
+		itemRemove.addListener(SWT.Selection, new Listener() {
+			public void 
+			handleEvent(
+				Event e ) 
+			{
+				for ( ChatInstance chat: chats ){
+					
+					chat.remove();
+				}
+			}   
+		});
+		
+		new MenuItem( menu, SWT.SEPARATOR );
+	}
+
+	public void 
+	addThisColumnSubMenu(
+		String 	sColumnName, 
+		Menu	menuThisColumn )
+	{
+		
+	}
+	
+	public void 
+	selected(
+		TableRowCore[] row )
+	{
+	  	UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+	  	if (uiFunctions != null) {
+	  		uiFunctions.refreshIconBar();
+	  	}
+	}
+
+	public void 
+	deselected(
+		TableRowCore[] rows )
+	{
+	  	UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+	  	if (uiFunctions != null) {
+	  		uiFunctions.refreshIconBar();
+	  	}
+	}
+	
+	public void 
+	focusChanged(
+		TableRowCore focus )
+	{
+	  	UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+	  	if (uiFunctions != null) {
+	  		uiFunctions.refreshIconBar();
+	  	}
+	}
+
+	public void 
+	defaultSelected(
+		TableRowCore[] 	rows, 
+		int 			stateMask )
+	{
+		if ( rows.length == 1 ){
+			
+			Object obj = rows[0].getDataSource();
+			
+			if ( obj instanceof ChatInstance ){
+				
+				ChatInstance chat = (ChatInstance)obj;
+				
+				BuddyPluginBeta beta = BuddyPluginUtils.getBetaPlugin();
+				
+				if ( beta != null) {
+					
+					try{
+						beta.showChat( chat.getClone());
+						
+					}catch( Throwable e ){
+						
+						Debug.out( e );
+					}
+				}
+			}
+		}
+	}
+
+	public void chatAdded(ChatInstance chat) {
+		if ( !chat.isInvisible()){
+			tv.addDataSource(chat);
+		}
+	}
+
+	public void chatChanged(ChatInstance chat) {
+		if (tv == null || tv.isDisposed()) {
+			return;
+		}
+		TableRowCore row = tv.getRow(chat);
+		if (row != null) {
+			row.invalidate(true);
+		}
+	}
+
+	public void chatRemoved(ChatInstance chat) {
+		tv.removeDataSource(chat);
+	}
+	
+	public void 
+	mouseEnter(
+		TableRowCore row )
+	{
+	}
+
+	public void 
+	mouseExit(
+		TableRowCore row)
+	{	
+	}
+	
+	// @see com.aelitis.azureus.ui.common.table.TableViewFilterCheck#filterCheck(java.lang.Object, java.lang.String, boolean)
+	public boolean filterCheck(ChatInstance ds, String filter, boolean regex) {
+		return false;
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatFavorite.java b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatFavorite.java
new file mode 100644
index 0000000..1c4b347
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatFavorite.java
@@ -0,0 +1,74 @@
+/*
+ * File    : CategoryItem.java
+ * Created : 01 feb. 2004
+ * By      : TuxPaper
+ *
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.net.buddy.swt.columns;
+
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.ChatInstance;
+import com.aelitis.azureus.ui.swt.columns.ColumnCheckBox;
+
+
+
+public class 
+ColumnChatFavorite
+	extends ColumnCheckBox
+{	
+	public static String COLUMN_ID = "chat.fave";
+
+	public 
+	ColumnChatFavorite(
+		TableColumn column ) 
+	{
+		super( column, 60 );
+		column.setRefreshInterval( TableColumn.INTERVAL_LIVE );
+	}
+	
+	@Override
+	protected Boolean 
+	getCheckBoxState(
+		Object datasource ) 
+	{
+		ChatInstance chat = (ChatInstance)datasource;
+		
+		if ( chat != null ){
+							
+			return( chat.isFavourite());
+		}
+		
+		return( null );
+	}
+	
+	@Override
+	protected void 
+	setCheckBoxState(
+		Object 	datasource,
+		boolean set ) 
+	{
+		ChatInstance chat = (ChatInstance)datasource;
+		
+		if ( chat != null ){
+			
+			chat.setFavourite( set );
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatMessageCount.java b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatMessageCount.java
new file mode 100644
index 0000000..cd3d224
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatMessageCount.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2013 Azureus Software, 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.plugins.net.buddy.swt.columns;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.*;
+
+public class ColumnChatMessageCount
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "chat.msg.count";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+
+	/** Default Constructor */
+	public ColumnChatMessageCount(TableColumn column) {
+		column.setWidth(60);
+		column.setAlignment( TableColumn.ALIGN_CENTER );
+		column.setRefreshInterval( TableColumn.INTERVAL_LIVE );
+		column.addListeners(this);
+	}
+
+	public void refresh(TableCell cell) {
+		ChatInstance chat = (ChatInstance) cell.getDataSource();
+		int num = -1;
+		if (chat != null) {
+			num = chat.getMessageCount( true );
+		}
+		
+		if (!cell.setSortValue(num) && cell.isValid()) {
+			return;
+		}
+
+		if (!cell.isShown()) {
+			return;
+		}
+		
+		cell.setText(num==-1?"":(num<100?String.valueOf( num ):"100+"));
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatMsgOutstanding.java b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatMsgOutstanding.java
new file mode 100644
index 0000000..0e23505
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatMsgOutstanding.java
@@ -0,0 +1,69 @@
+/*
+ * File    : CategoryItem.java
+ * Created : 01 feb. 2004
+ * By      : TuxPaper
+ *
+ * Copyright (C) Azureus Software, 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 ( 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.plugins.net.buddy.swt.columns;
+
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.ChatInstance;
+import com.aelitis.azureus.ui.swt.columns.ColumnCheckBox;
+
+
+
+public class 
+ColumnChatMsgOutstanding
+	extends ColumnCheckBox
+{	
+	public static String COLUMN_ID = "chat.msg.out";
+
+	public 
+	ColumnChatMsgOutstanding(
+		TableColumn column ) 
+	{
+		super( column, 80, true );
+		
+		column.setRefreshInterval( TableColumn.INTERVAL_LIVE );
+	}
+	
+	@Override
+	protected Boolean 
+	getCheckBoxState(
+		Object datasource ) 
+	{
+		ChatInstance chat = (ChatInstance)datasource;
+		
+		if ( chat != null ){
+							
+			return( chat.getMessageOutstanding());
+		}
+		
+		return( null );
+	}
+	
+	@Override
+	protected void 
+	setCheckBoxState(
+		Object 	datasource,
+		boolean set ) 
+	{
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatName.java b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatName.java
new file mode 100644
index 0000000..4e3564e
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatName.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2013 Azureus Software, 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.plugins.net.buddy.swt.columns;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.*;
+
+public class ColumnChatName
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "chat.name";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+
+	/** Default Constructor */
+	public ColumnChatName(TableColumn column) {
+		column.setWidth(220);
+		column.addListeners(this);
+	}
+
+	public void refresh(TableCell cell) {
+		ChatInstance chat = (ChatInstance) cell.getDataSource();
+		String chat_name = null;
+		if (chat != null) {
+			chat_name = chat.getName();
+		}
+		
+		if ( chat_name == null ){
+			chat_name = "";
+		}
+		
+		if (!cell.setSortValue(chat_name) && cell.isValid()) {
+			return;
+		}
+
+		if (!cell.isShown()) {
+			return;
+		}
+		
+		cell.setText(chat_name);
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatStatus.java b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatStatus.java
new file mode 100644
index 0000000..78454cd
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatStatus.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 2013 Azureus Software, 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.plugins.net.buddy.swt.columns;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.*;
+
+public class ColumnChatStatus
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "chat.status";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+
+	/** Default Constructor */
+	public ColumnChatStatus(TableColumn column) {
+		column.setWidth(400);
+		column.setRefreshInterval( TableColumn.INTERVAL_LIVE );
+		column.addListeners(this);
+	}
+
+	public void refresh(TableCell cell) {
+		ChatInstance chat = (ChatInstance) cell.getDataSource();
+		String status = null;
+		if (chat != null) {
+			status = chat.getStatus();
+		}
+		
+		if ( status == null ){
+			status = "";
+		}
+		
+		if (!cell.setSortValue(status) && cell.isValid()) {
+			return;
+		}
+
+		if (!cell.isShown()) {
+			return;
+		}
+		
+		cell.setText(status);
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatUserCount.java b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatUserCount.java
new file mode 100644
index 0000000..1a10ec4
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/plugins/net/buddy/swt/columns/ColumnChatUserCount.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2013 Azureus Software, 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.plugins.net.buddy.swt.columns;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.*;
+
+public class ColumnChatUserCount
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "chat.user.count";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+
+	/** Default Constructor */
+	public ColumnChatUserCount(TableColumn column) {
+		column.setWidth(40);
+		column.setAlignment( TableColumn.ALIGN_CENTER );
+		column.setRefreshInterval( TableColumn.INTERVAL_LIVE );
+		column.addListeners(this);
+	}
+
+	public void refresh(TableCell cell) {
+		ChatInstance chat = (ChatInstance) cell.getDataSource();
+		int num = -1;
+		if (chat != null) {
+			num = chat.getEstimatedNodes();
+		}
+		
+		if (!cell.setSortValue(num) && cell.isValid()) {
+			return;
+		}
+
+		if (!cell.isShown()) {
+			return;
+		}
+		
+		cell.setText(num==-1?"":(num<100?String.valueOf( num ):"100+"));
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/images/check-ro-yes.png b/azureus3/src/com/aelitis/azureus/ui/images/check-ro-yes.png
new file mode 100644
index 0000000..8435f23
Binary files /dev/null and b/azureus3/src/com/aelitis/azureus/ui/images/check-ro-yes.png differ
diff --git a/azureus3/src/com/aelitis/azureus/ui/images/sb/20px-archive.png b/azureus3/src/com/aelitis/azureus/ui/images/sb/20px-archive.png
new file mode 100644
index 0000000..89020e5
Binary files /dev/null and b/azureus3/src/com/aelitis/azureus/ui/images/sb/20px-archive.png differ
diff --git a/azureus3/src/com/aelitis/azureus/ui/images/sb/20px-chat-ov.png b/azureus3/src/com/aelitis/azureus/ui/images/sb/20px-chat-ov.png
new file mode 100644
index 0000000..6a9c79f
Binary files /dev/null and b/azureus3/src/com/aelitis/azureus/ui/images/sb/20px-chat-ov.png differ
diff --git a/azureus3/src/com/aelitis/azureus/ui/images/sb/20px-tag-ov.png b/azureus3/src/com/aelitis/azureus/ui/images/sb/20px-tag-ov.png
new file mode 100644
index 0000000..0843fa2
Binary files /dev/null and b/azureus3/src/com/aelitis/azureus/ui/images/sb/20px-tag-ov.png differ
diff --git a/azureus3/src/com/aelitis/azureus/ui/images/sb/allpeers.png b/azureus3/src/com/aelitis/azureus/ui/images/sb/allpeers.png
new file mode 100644
index 0000000..06a91f7
Binary files /dev/null and b/azureus3/src/com/aelitis/azureus/ui/images/sb/allpeers.png differ
diff --git a/azureus3/src/com/aelitis/azureus/ui/images/tb/sec_l_l_disabled.png b/azureus3/src/com/aelitis/azureus/ui/images/tb/sec_l_l_disabled.png
new file mode 100644
index 0000000..030ba72
Binary files /dev/null and b/azureus3/src/com/aelitis/azureus/ui/images/tb/sec_l_l_disabled.png differ
diff --git a/azureus3/src/com/aelitis/azureus/ui/images/tb/sec_m_disabled.png b/azureus3/src/com/aelitis/azureus/ui/images/tb/sec_m_disabled.png
new file mode 100644
index 0000000..3111ca1
Binary files /dev/null and b/azureus3/src/com/aelitis/azureus/ui/images/tb/sec_m_disabled.png differ
diff --git a/azureus3/src/com/aelitis/azureus/ui/images/tb/sec_r_r_disabled.png b/azureus3/src/com/aelitis/azureus/ui/images/tb/sec_r_r_disabled.png
new file mode 100644
index 0000000..e4edec2
Binary files /dev/null and b/azureus3/src/com/aelitis/azureus/ui/images/tb/sec_r_r_disabled.png differ
diff --git a/azureus3/src/com/aelitis/azureus/ui/selectedcontent/DownloadUrlInfoContentNetwork.java b/azureus3/src/com/aelitis/azureus/ui/selectedcontent/DownloadUrlInfoContentNetwork.java
index 6ff7c7f..cd92506 100644
--- a/azureus3/src/com/aelitis/azureus/ui/selectedcontent/DownloadUrlInfoContentNetwork.java
+++ b/azureus3/src/com/aelitis/azureus/ui/selectedcontent/DownloadUrlInfoContentNetwork.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 9, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentV3.java b/azureus3/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentV3.java
index 0482d3a..26ea5ad 100644
--- a/azureus3/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentV3.java
+++ b/azureus3/src/com/aelitis/azureus/ui/selectedcontent/SelectedContentV3.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jun 9, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/SkinConstants.java b/azureus3/src/com/aelitis/azureus/ui/skin/SkinConstants.java
index 4abf12c..74dd343 100644
--- a/azureus3/src/com/aelitis/azureus/ui/skin/SkinConstants.java
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/SkinConstants.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3.properties
index 693fb86..9ae8849 100644
--- a/azureus3/src/com/aelitis/azureus/ui/skin/skin3.properties
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3.properties
@@ -5,6 +5,9 @@ skin.include=skin3_topbar,\
              skin3_sidebar,\
              skin3_activities,\
              skin3_tags,\
+             skin3_tag_discovery,\
+             skin3_chats,\
+             skin3_archive_dls,\
              skin3_tab_browse,\
              skin3_tab_searchresults,\
              skin3_constants,\
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_archive_dls.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_archive_dls.properties
new file mode 100644
index 0000000..7bd7913
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_archive_dls.properties
@@ -0,0 +1,73 @@
+
+archivedlsview.type=container
+archivedlsview.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SBC_ArchivedDownloadsView
+archivedlsview.widgets=\
+	archivedlsview.toparea,\
+	archivedlsview.list
+archivedlsview.attach.template=template.fill
+
+archivedlsview.toparea.type=container
+archivedlsview.toparea.widgets=\
+	archivedlsview.title,\
+	archivedlsview.filterbox
+archivedlsview.toparea.attach.template=template.fill
+archivedlsview.toparea.attach.top=0,5
+archivedlsview.toparea.attach.bottom=
+
+archivedlsview.title.type=text,{archivedlsview.view.heading}
+archivedlsview.title.view=title
+archivedlsview.title.attach.left=0,5
+archivedlsview.title.v-align=center
+archivedlsview.title.text.size=15px
+archivedlsview.title.text.style=bold
+
+
+archivedlsview.filterbox.type=textbox
+archivedlsview.filterbox.style=search
+archivedlsview.filterbox.view=filterbox
+archivedlsview.filterbox.attach.left=
+archivedlsview.filterbox.attach.right=100,0
+archivedlsview.filterbox.height=20
+archivedlsview.filterbox.width=200
+archivedlsview.filterbox.visible=1
+
+archivedlsview.list.type=container
+archivedlsview.list.attach.template=template.fill
+archivedlsview.list.attach.top=archivedlsview.toparea,0
+archivedlsview.list.view=archived-dls-list
+
+#
+
+archivedlsview.infobar.type=container
+archivedlsview.infobar.color=#F1F9F8
+archivedlsview.infobar.widgets=\
+  archivedls.infobar.line1,\
+  archivedls.infobar.line2,\
+  archivedls.infobar.close
+archivedlsview.infobar.attach.template=template.fill
+
+archivedls.infobar.line1.type=text
+archivedls.infobar.line1.text.size=19px
+archivedls.infobar.line1.view=infobar-title-1
+archivedls.infobar.line1.text.style._windows=bold
+archivedls.infobar.line1.text.color=#707070
+archivedls.infobar.line1.attach.left=0,10
+archivedls.infobar.line1.attach.top=0,15
+archivedls.infobar.line1.attach.right=archivedls.infobar.close,-5
+
+archivedls.infobar.line2.type=text
+archivedls.infobar.line2.view=infobar-title-2
+archivedls.infobar.line2.text.color=#808080
+archivedls.infobar.line2.text.size=15px
+archivedls.infobar.line2.text.urlcolor={color.links.normal}
+archivedls.infobar.line2.text.urlcolor-pressed={color.links.dark}
+archivedls.infobar.line2.attach.left=0,10
+archivedls.infobar.line2.attach.right=100,-10
+archivedls.infobar.line2.attach.top=archivedls.infobar.line1,4
+archivedls.infobar.line2.attach.bottom=100,-10
+
+archivedls.infobar.close.type=image,{template.imagedir}/dismissX.gif
+archivedls.infobar.close.view=close
+archivedls.infobar.close.cursor=hand
+archivedls.infobar.close.attach.right=100,-10
+archivedls.infobar.close.attach.top=0,7
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_chats.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_chats.properties
new file mode 100644
index 0000000..c0b3fe1
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_chats.properties
@@ -0,0 +1,75 @@
+
+chatsview.type=container
+chatsview.onshow.skinviewclass=com.aelitis.azureus.plugins.net.buddy.swt.SBC_ChatOverview
+chatsview.widgets=\
+	chatsview.toparea,\
+	chatsview.list
+chatsview.attach.template=template.fill
+
+chatsview.toparea.type=container
+chatsview.toparea.widgets=\
+	chatsview.title,\
+	chatsview.filterbox
+chatsview.toparea.attach.template=template.fill
+chatsview.toparea.attach.top=0,5
+chatsview.toparea.attach.bottom=
+
+
+chatsview.title.type=text,{chats.view.heading}
+chatsview.title.view=title
+chatsview.title.attach.top=0,5
+chatsview.title.attach.left=0,5
+chatsview.title.v-align=center
+chatsview.title.text.size=15px
+chatsview.title.text.style=bold
+
+chatsview.filterbox.type=textbox
+chatsview.filterbox.style=search
+chatsview.filterbox.view=filterbox
+chatsview.filterbox.attach.top=0,2
+chatsview.filterbox.attach.left=
+chatsview.filterbox.attach.right=100,0
+chatsview.filterbox.height=20
+chatsview.filterbox.width=200
+chatsview.filterbox.visible=0
+
+chatsview.list.type=container
+chatsview.list.attach.template=template.fill
+chatsview.list.attach.top=chatsview.toparea,0
+chatsview.list.view=chats-list
+
+##
+
+chatsview.infobar.type=container
+chatsview.infobar.color=#F1F9F8
+chatsview.infobar.widgets=\
+  chats.infobar.line1,\
+  chats.infobar.line2,\
+  chats.infobar.close
+chatsview.infobar.attach.template=template.fill
+
+chats.infobar.line1.type=text
+chats.infobar.line1.text.size=19px
+chats.infobar.line1.view=infobar-title-1
+chats.infobar.line1.text.style._windows=bold
+chats.infobar.line1.text.color=#707070
+chats.infobar.line1.attach.left=0,10
+chats.infobar.line1.attach.top=0,15
+chats.infobar.line1.attach.right=chats.infobar.close,-5
+
+chats.infobar.line2.type=text
+chats.infobar.line2.view=infobar-title-2
+chats.infobar.line2.text.color=#808080
+chats.infobar.line2.text.size=15px
+chats.infobar.line2.text.urlcolor={color.links.normal}
+chats.infobar.line2.text.urlcolor-pressed={color.links.dark}
+chats.infobar.line2.attach.left=0,10
+chats.infobar.line2.attach.right=100,-10
+chats.infobar.line2.attach.top=chats.infobar.line1,4
+chats.infobar.line2.attach.bottom=100,-10
+
+chats.infobar.close.type=image,{template.imagedir}/dismissX.gif
+chats.infobar.close.view=close
+chats.infobar.close.cursor=hand
+chats.infobar.close.attach.right=100,-10
+chats.infobar.close.attach.top=0,7
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_constants.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_constants.properties
index a5465b7..9390a09 100644
--- a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_constants.properties
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_constants.properties
@@ -209,9 +209,12 @@ image.toolbar.table_normal=multi-index,20,13,{template.imagedir}/tb/tb-buttons.p
 image.toolbar.table_large=multi-index,20,12,{template.imagedir}/tb/tb-buttons.png
 
 image.toolbar.2nd.m-bg={template.imagedir}/tb/sec_m.png
+image.toolbar.2nd.m-bg-disabled={template.imagedir}/tb/sec_m_disabled.png
 image.toolbar.2nd.l-bg={template.imagedir}/tb/sec_l_l.png,{template.imagedir}/tb/sec_m.png
+image.toolbar.2nd.l-bg-disabled={template.imagedir}/tb/sec_l_l_disabled.png,{template.imagedir}/tb/sec_m_disabled.png
 image.toolbar.2nd.l-bg-down={template.imagedir}/tb/sec_l_l_down.png,{template.imagedir}/tb/sec_m_down.png
 image.toolbar.2nd.r-bg={template.imagedir}/tb/sec_m.png,{template.imagedir}/tb/sec_m.png,{template.imagedir}/tb/sec_r_r.png
+image.toolbar.2nd.r-bg-disabled={template.imagedir}/tb/sec_m_disabled.png,{template.imagedir}/tb/sec_m_disabled.png,{template.imagedir}/tb/sec_r_r_disabled.png
 image.toolbar.2nd.r-bg-down={template.imagedir}/tb/sec_m_down.png,{template.imagedir}/tb/sec_m_down.png,{template.imagedir}/tb/sec_r_r_down.png
 image.toolbar.2nd.lr-bg={template.imagedir}/tb/sec_l_l.png,{template.imagedir}/tb/sec_m.png,{template.imagedir}/tb/sec_r_r.png
 image.toolbar.2nd.lr-bg-down={template.imagedir}/tb/sec_l_l_down.png,{template.imagedir}/tb/sec_m_down.png,{template.imagedir}/tb/sec_r_r_down.png
@@ -247,6 +250,10 @@ image.sidebar.tag-green={template.imagedir}/sb/20px-tag-green.png
 image.sidebar.tag-red={template.imagedir}/sb/20px-tag-red.png
 image.sidebar.tag.vhdn={template.imagedir}/sb/20px-tag-vhdn.png
 image.sidebar.tag.featcon={template.imagedir}/sb/20px-tag-featcon.png
+image.sidebar.allpeers={template.imagedir}/sb/allpeers.png
+image.sidebar.tag-overview={template.imagedir}/sb/20px-tag-ov.png
+image.sidebar.chat-overview={template.imagedir}/sb/20px-chat-ov.png
+image.sidebar.archive={template.imagedir}/sb/20px-archive.png
 
 image.sidebar.device.renderer={template.imagedir}/sb/ic_device_rend.png
 image.sidebar.device.mediaserver={template.imagedir}/sb/ic_device_ms.png
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_addtag.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_addtag.properties
new file mode 100644
index 0000000..21c36b4
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_addtag.properties
@@ -0,0 +1,63 @@
+shell.type=container
+shell.width=500
+shell.title={TagAddWindow.title}
+shell.widgets=dlg.addtag,shell.bottomline,shell.bottom
+
+dlg.addtag.type=container
+dlg.addtag.attach.top=0,10
+dlg.addtag.attach.bottom=shell.bottomline,-10
+dlg.addtag.attach.left=0,10
+dlg.addtag.attach.right=100,-10
+dlg.addtag.widgets=dlg.addtag.title,\
+	dlg.addtag.textbox,\
+	dlg.addtag.public,\
+	dlg.addtag.subtitle,\
+	dlg.addtag.public.info
+
+dlg.addtag.title.type=text,{TagAddWindow.message}
+dlg.addtag.title.v-align=center
+dlg.addtag.title.attach.top=dlg.addtag.textbox,0,top
+dlg.addtag.title.attach.bottom=dlg.addtag.textbox,0,bottom
+dlg.addtag.title.attach.left=0,0
+dlg.addtag.title.attach.right=
+
+dlg.addtag.textbox.type=textbox
+dlg.addtag.textbox.view=tag-name
+dlg.addtag.textbox.attach.top=0,0
+dlg.addtag.textbox.attach.left=dlg.addtag.title,5
+dlg.addtag.textbox.attach.right=100,0
+
+dlg.addtag.subtitle.type=text,{TagAddWindow.subtitle}
+dlg.addtag.subtitle.attach.top=dlg.addtag.textbox,3
+dlg.addtag.subtitle.attach.left=0,0
+dlg.addtag.subtitle.attach.right=100,0
+
+
+dlg.addtag.public.type=checkbox
+dlg.addtag.public.view=tag-share
+dlg.addtag.public.text={TagAddWindow.public.checkbox}
+dlg.addtag.public.attach.top=dlg.addtag.subtitle,20
+dlg.addtag.public.attach.left=0,0
+dlg.addtag.public.attach.right=100,0
+
+dlg.addtag.public.info.type=text,{TagAddWindow.public.info}
+dlg.addtag.public.info.attach.top=dlg.addtag.public,5
+dlg.addtag.public.info.attach.left=0,0
+dlg.addtag.public.info.attach.right=100,0
+
+###
+
+shell.bottom.type=container
+shell.bottom.view=bottom-area
+shell.bottom.attach.top=
+shell.bottom.attach.bottom=100,0
+shell.bottom.attach.left=0,0
+shell.bottom.attach.right=100,0
+shell.bottom.minheight=40
+
+shell.bottomline.type=container
+shell.bottomline.height=1
+shell.bottomline.color=COLOR_WIDGET_BORDER
+shell.bottomline.attach.left=0,0
+shell.bottomline.attach.right=100,0
+shell.bottomline.attach.bottom=shell.bottom,0
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_generic_notop.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_generic_notop.properties
new file mode 100644
index 0000000..e0859b8
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_generic_notop.properties
@@ -0,0 +1,79 @@
+template.imagedir=com/aelitis/azureus/ui/images
+
+template.innerborder.x=60
+template.outerborder.x=40
+template.textalpha=230
+color.links.normal=#006eae
+color.links.dark=#003a5c
+color.fadedtext=#666666
+
+color.top=#b7c8d4
+color.title=#005186
+color.line=#ffffff
+color.main=#ecf2f6
+color.line2=#bac8d5
+ 
+shell.type=container
+shell.width=554
+shell.widgets=shell.main,\
+              shell.bottom,\
+              shell.bottomline
+
+shell.main.type=container
+shell.main.color={color.main}
+shell.main.attach.left=0,0
+shell.main.attach.right=100,0
+shell.main.attach.bottom=shell.bottomline,0
+shell.main.attach.top=0,0
+shell.main.widgets=main.group
+shell.main.minheight=100
+
+main.group.type=container
+main.group.attach.left=0,0
+main.group.attach.top=0,20
+main.group.attach.right=100,0
+main.group.attach.bottom=100,-20
+main.group.widgets=maintext,maintext.icon,section.extra
+
+maintext.icon.type=image
+maintext.icon.drawmode=left
+maintext.icon.h-padding=7
+maintext.icon.view=text-icon
+maintext.icon.attach.left=0,{template.outerborder.x}
+maintext.icon.attach.top=0,0
+
+maintext.type=text,{remote.pairing.subtitle}
+maintext.view=middle-title
+maintext.text.size=120%
+maintext.text.color=#005186
+maintext.text.style=bold
+maintext.attach.left=maintext.icon
+maintext.attach.top=0,0
+maintext.attach.right=100,-{template.outerborder.x}
+maintext.align=center
+maintext.minheight=40
+
+section.extra.type=container
+section.extra.view=middle-extra
+section.extra.attach.left=0,{template.outerborder.x}
+section.extra.attach.top=maintext,5
+section.extra.attach.bottom=100,0
+section.extra.attach.right=100,-{template.outerborder.x}
+
+###
+
+shell.bottom.type=container
+shell.bottom.view=bottom-area
+shell.bottom.color=#FFFFFF
+shell.bottom.attach.top=
+shell.bottom.attach.bottom=100,0
+shell.bottom.attach.left=0,0
+shell.bottom.attach.right=100,0
+shell.bottom.minheight=40
+
+shell.bottomline.type=container
+shell.bottomline.height=1
+shell.bottomline.color={color.line2}
+shell.bottomline.attach.left=0,0
+shell.bottomline.attach.right=100,0
+shell.bottomline.attach.bottom=shell.bottom,0
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_opentorrent_options_instance.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_opentorrent_options_instance.properties
index dad7726..2932779 100644
--- a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_opentorrent_options_instance.properties
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_opentorrent_options_instance.properties
@@ -54,7 +54,7 @@ torrentinfo.trackername.attach.right=100,-{padding}
 
 toptions.filearea.type=expanditem
 toptions.filearea.view=expanditem-files
-toptions.filearea.widgets=filearea.table,filearea.buttons
+toptions.filearea.widgets=filearea.table,filearea.buttons,filearea.filter
 toptions.filearea.fillheight=1
 toptions.filearea.expanded=1
 
@@ -68,10 +68,20 @@ filearea.table.attach.bottom=filearea.buttons,-2
 filearea.buttons.type=container
 filearea.buttons.view=filearea-buttons
 filearea.buttons.attach.left=0,{padding}
-filearea.buttons.attach.right=100,-{padding}
+filearea.buttons.attach.right=filearea.filter,-{padding}
 filearea.buttons.attach.top=
 filearea.buttons.attach.bottom=100,-2
 
+filearea.filter.type=textbox
+filearea.filter.view=filearea-filter
+filearea.filter.style=search
+filearea.filter.width=150
+filearea.filter.attach.left=
+filearea.filter.attach.right=100,-{padding}
+filearea.filter.attach.top=filearea.table,{padding}
+filearea.filter.attach.bottom=
+filearea.filter.message={TorrentDetailsView.filter}
+
 #########
 
 toptions.saveto.type=expanditem
@@ -113,7 +123,7 @@ toptions.peer.type=expanditem
 toptions.peer.view=expanditem-peer
 toptions.peer.minUserMode=1
 toptions.peer.text={OpenTorrentOptions.header.peeroptions}
-toptions.peer.widgets=peeroptions.sources,peeroptions.trackers,peeroptions.ipfilter
+toptions.peer.widgets=peeroptions.sources,peeroptions.trackers,peeroptions.updownlimit,peeroptions.ipfilter
 
 peeroptions.sources.type=container
 peeroptions.sources.view=peer-sources
@@ -129,10 +139,17 @@ peeroptions.trackers.attach.top=peeroptions.sources
 peeroptions.trackers.attach.left=0,{padding}
 peeroptions.trackers.attach.right=
 
+peeroptions.updownlimit.type=container
+peeroptions.updownlimit.view=updownlimit
+peeroptions.updownlimit.attach.bottom=100,-{padding}
+peeroptions.updownlimit.attach.top=peeroptions.sources
+peeroptions.updownlimit.attach.left=peeroptions.trackers,{padding}
+peeroptions.updownlimit.attach.right=
+
 peeroptions.ipfilter.type=container
 peeroptions.ipfilter.view=ipfilter
 peeroptions.ipfilter.attach.bottom=100,-{padding}
 peeroptions.ipfilter.attach.top=peeroptions.sources,{padding}
-peeroptions.ipfilter.attach.left=peeroptions.trackers,{padding}
+peeroptions.ipfilter.attach.left=peeroptions.updownlimit,{padding}
 peeroptions.ipfilter.attach.right=
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_sidebar_popout.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_sidebar_popout.properties
new file mode 100644
index 0000000..9900144
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_dlg_sidebar_popout.properties
@@ -0,0 +1,15 @@
+
+shell.type=container
+shell.width=600
+shell.height=400
+shell.widgets=shell.main
+
+shell.main.type=container
+shell.main.view=content-area
+shell.main.attach.left=0,0
+shell.main.attach.right=100,0
+shell.main.attach.bottom=100,0
+shell.main.attach.top=0,0
+
+mdientry.toolbar.visible=0
+
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_sidebar.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_sidebar.properties
index 5d6bbf9..66a241d 100644
--- a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_sidebar.properties
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_sidebar.properties
@@ -1,4 +1,27 @@
 
+## mdi #################################################################
+#                                                                      #
+# !! main.sidebar.list !!!!!!!!!!! .sash !!!!! main.sidebar.content !! #
+# !                            !           !                         ! #
+# ! ## .topline #############  !           !                         ! #
+# !                            !           !                         ! #
+# ! ## main.sidebar #########  ! sidebar-  !    sidebar-contents     ! #
+# ! #                       #  !           !                         ! #
+# ! # @@ sidebar.middle @@  #  !   sash    !                         ! #
+# ! # @                  @  #  !           !                         ! #
+# ! # @   sidebar-list   @  #  !           !                         ! #
+# ! # @                  @  #  !           !                         ! #
+# ! # @                  @  #  !           !                         ! #
+# ! # @                  @  #  !           !                         ! #
+# ! # @                  @  #  !           !                         ! #
+# ! # @@@@@@@@@@@@@@@@@@@@  #  !           !                         ! #
+# ! #                       #  !           !                         ! #
+# ! #########################  !           !                         ! #
+# !                            !           !                         ! #
+# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #
+#                                                                      #
+########################################################################
+
 main.area.body.type=container
 main.area.body.attach.top=main.area.toolbar,0
 main.area.body.attach.bottom=100,0
@@ -36,7 +59,7 @@ main.sidebar.list.attach.top=0,0
 main.sidebar.list.attach.bottom=100,0
 main.sidebar.list.attach.left=0,0
 main.sidebar.list.attach.right=
-main.sidebar.list.widgets=main.sidebar,main.sidebar.topline
+main.sidebar.list.widgets=main.sidebar,main.sidebar.topline,main.sidebar.plugins
 #main.sidebar.list.minwidth=125
 
 
@@ -48,12 +71,20 @@ main.sidebar.topline.attach.right=100,0
 main.sidebar.topline.color=COLOR_WIDGET_NORMAL_SHADOW
 
 main.sidebar.type=container
+main.sidebar.view=sidebar-container
 main.sidebar.attach.top=main.sidebar.topline,0
-main.sidebar.attach.bottom=100,0
+main.sidebar.attach.bottom=main.sidebar.plugins,0
 main.sidebar.attach.left=0,0
 main.sidebar.attach.right=100,0
 main.sidebar.widgets=sidebar.middle
 
+main.sidebar.plugins.type=container
+main.sidebar.plugins.view=sidebar-plugins
+main.sidebar.plugins.attach.top=
+main.sidebar.plugins.attach.bottom=100,0
+main.sidebar.plugins.attach.left=0,0
+main.sidebar.plugins.attach.right=100,0
+
 sidebar.middle.type=container
 sidebar.middle.view=sidebar-list
 sidebar.middle.attach.top=0,0
@@ -85,6 +116,7 @@ main.area.beta.type=browser
 main.area.beta.view=welcome
 main.area.beta.url=http://dev.vuze.com/beta.start
 main.area.beta.attach.template=template.fill
+main.area.beta.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SBC_GenericBrowsePage
 
 main.area.plus.type=browser
 main.area.plus.view=plus-ftux
@@ -101,3 +133,10 @@ main.generic.browse.view=browser
 main.generic.browse.attach.template=template.fill
 main.generic.browse.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SBC_GenericBrowsePage
 
+###
+
+tabfolder.fill.type=tabfolder
+tabfolder.fill.border=1
+#we create skinviewclass manually to ensure it's there before everything else
+#classic.area.body.onshow.skinviewclass=com.aelitis.azureus.ui.swt.mdi.TabbedMDI
+tabfolder.fill.attach.template=template.fill
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_tag_discovery.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_tag_discovery.properties
new file mode 100644
index 0000000..45e7cef
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_tag_discovery.properties
@@ -0,0 +1,67 @@
+
+tagdiscoveryview.type=container
+tagdiscoveryview.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.SBC_TagDiscovery
+tagdiscoveryview.widgets=\
+	tagdiscoveryview.toparea,\
+	tagdiscoveryview.list
+tagdiscoveryview.attach.template=template.fill
+
+tagdiscoveryview.toparea.type=container
+tagdiscoveryview.toparea.widgets=\
+	tagdiscoveryview.title,\
+	tagdiscoveryview.scanbutton,\
+  tagdiscoveryview.filterbutton,\
+	tagdiscoveryview.filterbox,\
+	tagdiscoveryview.filterarea
+tagdiscoveryview.toparea.attach.template=template.fill
+tagdiscoveryview.toparea.attach.top=0,5
+tagdiscoveryview.toparea.attach.bottom=
+
+
+tagdiscoveryview.title.type=text,{tag.discovery.view.heading}
+tagdiscoveryview.title.view=title
+tagdiscoveryview.title.attach.top=tagdiscoveryview.scanbutton,0,center
+tagdiscoveryview.title.attach.left=tagdiscoveryview.scanbutton,5
+tagdiscoveryview.title.v-align=center
+tagdiscoveryview.title.text.size=15px
+tagdiscoveryview.title.text.style=bold
+
+tagdiscoveryview.filterbutton.type=toggle
+tagdiscoveryview.filterbutton.text={tag.discovery.view.options}
+tagdiscoveryview.filterbutton.view=filter-button
+tagdiscoveryview.filterbutton.attach.top=0,0
+tagdiscoveryview.filterbutton.attach.right=tagdiscoveryview.filterbox,-10
+
+tagdiscoveryview.scanbutton.type=button,Scan
+tagdiscoveryview.scanbutton.text={Generic.words.scan}
+tagdiscoveryview.scanbutton.view=scan-button
+tagdiscoveryview.scanbutton.attach.left=0,10
+tagdiscoveryview.scanbutton.attach.top=0,0
+
+
+tagdiscoveryview.filterbox.type=textbox
+tagdiscoveryview.filterbox.style=search
+tagdiscoveryview.filterbox.view=filterbox
+tagdiscoveryview.filterbox.attach.top=0,2
+tagdiscoveryview.filterbox.attach.left=
+tagdiscoveryview.filterbox.attach.right=100,0
+tagdiscoveryview.filterbox.height=20
+tagdiscoveryview.filterbox.width=200
+tagdiscoveryview.filterbox.visible=0
+
+tagdiscoveryview.filterarea.type=container
+tagdiscoveryview.filterarea.visible=0
+tagdiscoveryview.filterarea.view=filterarea
+tagdiscoveryview.filterarea.attach.top=tagdiscoveryview.filterbutton,5
+tagdiscoveryview.filterarea.attach.bottom=100,-1
+tagdiscoveryview.filterarea.attach.left=tagdiscoveryview.title,0,left
+tagdiscoveryview.filterarea.attach.right=100,-5
+tagdiscoveryview.filterarea.widgets=tagdiscoveryview.filterarea.nooo
+
+tagdiscoveryview.filterarea.nooo.type=text,No options yet!
+tagdiscoveryview.filterarea.attach.template=template.fill
+
+tagdiscoveryview.list.type=container
+tagdiscoveryview.list.attach.template=template.fill
+tagdiscoveryview.list.attach.top=tagdiscoveryview.toparea,0
+tagdiscoveryview.list.view=tag-discovery-list
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_tags.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_tags.properties
index eb55ffb..057b5c3 100644
--- a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_tags.properties
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_tags.properties
@@ -9,24 +9,32 @@ tagsview.attach.template=template.fill
 tagsview.toparea.type=container
 tagsview.toparea.widgets=\
 	tagsview.title,\
+	tagsview.addtag,\
 	tagsview.filterbox
 tagsview.toparea.attach.template=template.fill
 tagsview.toparea.attach.top=0,5
 tagsview.toparea.attach.bottom=
 
-
 tagsview.title.type=text,{tags.view.heading}
 tagsview.title.view=title
-tagsview.title.attach.top=0,5
+tagsview.title.attach.top=tagsview.addtag,0,center
 tagsview.title.attach.left=0,5
 tagsview.title.v-align=center
 tagsview.title.text.size=15px
 tagsview.title.text.style=bold
 
+
+tagsview.addtag.type=button
+tagsview.addtag.text={label.add.tag}
+tagsview.addtag.view=add-tag
+tagsview.addtag.attach.right=tagsview.filterbox,-10
+tagsview.addtag.attach.top=0,0
+
+
 tagsview.filterbox.type=textbox
 tagsview.filterbox.style=search
 tagsview.filterbox.view=filterbox
-tagsview.filterbox.attach.top=0,2
+tagsview.filterbox.attach.top=tagsview.addtag,0,center
 tagsview.filterbox.attach.left=
 tagsview.filterbox.attach.right=100,0
 tagsview.filterbox.height=20
@@ -37,3 +45,37 @@ tagsview.list.type=container
 tagsview.list.attach.template=template.fill
 tagsview.list.attach.top=tagsview.toparea,0
 tagsview.list.view=tags-list
+
+##
+
+tagsview.infobar.type=container
+tagsview.infobar.color=#F1F9F8
+tagsview.infobar.widgets=\
+  tags.infobar.line1,\
+  tags.infobar.line2,\
+  tags.infobar.close
+tagsview.infobar.attach.template=template.fill
+
+tags.infobar.line1.type=text
+tags.infobar.line1.text.size=19px
+tags.infobar.line1.view=infobar-title-1
+tags.infobar.line1.text.style._windows=bold
+tags.infobar.line1.text.color=#707070
+tags.infobar.line1.attach.left=0,10
+tags.infobar.line1.attach.top=0,15
+tags.infobar.line1.attach.right=tags.infobar.close,-5
+
+tags.infobar.line2.type=text
+tags.infobar.line2.view=infobar-title-2
+tags.infobar.line2.text.color=#808080
+tags.infobar.line2.text.size=15px
+tags.infobar.line2.attach.left=0,10
+tags.infobar.line2.attach.right=100,-10
+tags.infobar.line2.attach.top=tags.infobar.line1,4
+tags.infobar.line2.attach.bottom=100,-10
+
+tags.infobar.close.type=image,{template.imagedir}/dismissX.gif
+tags.infobar.close.view=close
+tags.infobar.close.cursor=hand
+tags.infobar.close.attach.right=100,-10
+tags.infobar.close.attach.top=0,7
diff --git a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_toolbar.properties b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_toolbar.properties
index 30833ee..e8b67be 100644
--- a/azureus3/src/com/aelitis/azureus/ui/skin/skin3_toolbar.properties
+++ b/azureus3/src/com/aelitis/azureus/ui/skin/skin3_toolbar.properties
@@ -21,7 +21,6 @@ classic.area.middle.attach.right=100,0
 classic.area.toolbar.type=container
 classic.area.toolbar.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.ToolBarView
 classic.area.toolbar.widgets=main.area.topgap,\
-													 classic.area.toolbar.2nd,\
                            maintabs.vcenter,\
                            maintabs.area.sidebarpop
 classic.area.toolbar.view=global-toolbar
@@ -44,7 +43,7 @@ main.area.toolbar.widgets=main.area.toolbar.add,\
   maintabs.area.search,\
   maintabs.area.bottompad,\
   maintabs.area.sidebarpop
-main.area.toolbar.height._mac=28
+main.area.toolbar.height._mac=33
 
 maintabs.area.bottompad.type=container
 maintabs.area.bottompad.height=1
@@ -57,7 +56,7 @@ main.area.toolbar.add.text={ConfigView.section.style.dropdiraction.opentorrents}
 main.area.toolbar.add.image={template.imagedir}/tb/tb_opentorrent.png
 main.area.toolbar.add.attach.left=maintabs.area.sidebarpop,5
 main.area.toolbar.add.attach.top=0,1
-main.area.toolbar.add.attach.bottom=
+main.area.toolbar.add.attach.bottom=100,0
 main.area.toolbar.add.attach.right=
 main.area.toolbar.add.attach.top._mac=0,0
 
@@ -73,7 +72,6 @@ mdientry.toolbar.full.height=26
 mdientry.toolbar.type=container
 mdientry.toolbar.onshow.skinviewclass=com.aelitis.azureus.ui.swt.views.skin.ToolBarView
 mdientry.toolbar.widgets=main.area.topgap,\
-                           mdientry.toolbar.2nd,\
                            maintabs.bottom.line,\
                            maintabs.vcenter
 mdientry.toolbar.view=view-toolbar
@@ -151,16 +149,7 @@ sidebarpop.expand.tooltip={sidebar.expand.tooltip}
 sidebarpop.expand.cursor=hand
 
 
-classic.area.toolbar.2nd.type=container
-classic.area.toolbar.2nd.view=toolbar-2nd
-classic.area.toolbar.2nd.attach.top=main.area.topgap,0
-classic.area.toolbar.2nd.attach.bottom=100,-3
-
-mdientry.toolbar.2nd.type=container
-mdientry.toolbar.2nd.view=toolbar-2nd
-mdientry.toolbar.2nd.attach.top=main.area.topgap,0
-mdientry.toolbar.2nd.attach.bottom=100,0
-mdientry.toolbar.2nd.attach.left=0,0
+toolbar.group.type=container
 
 maintabs.area.search.type=container
 maintabs.area.search.view=topbar-area-search
@@ -169,7 +158,7 @@ maintabs.area.search.widgets=widget.search-button1,\
 	                           widget.search-area
 maintabs.area.search.attach.left=main.area.toolbar.add,10
 maintabs.area.search.attach.top=main.area.toolbar.add,0,center
-maintabs.area.search.attach.top._mac=0,2
+maintabs.area.search.attach.top._mac=0,4
 maintabs.area.search.attach.bottom=100,0
 maintabs.area.search.attach.right=maintabs.area.plus,-5
 
@@ -256,9 +245,9 @@ toolbar.area.item.title.width=55
 
 toolbar.area.sitem.type=container
 toolbar.area.sitem.widgets=toolbar.area.sitem.imagearea
-toolbar.area.sitem.propogate=1
 toolbar.area.sitem.attach.top=0,0
 toolbar.area.sitem.cursor=hand
+toolbar.area.sitem.propogate=1
 
 toolbar.area.sitem.imagearea.type=container
 toolbar.area.sitem.imagearea.view=toolbar-item-imagearea
@@ -266,6 +255,8 @@ toolbar.area.sitem.imagearea.widgets=toolbar.area.sitem.image
 toolbar.area.sitem.imagearea.attach.left=0,0
 toolbar.area.sitem.imagearea.attach.right=100,0
 toolbar.area.sitem.imagearea.background={image.toolbar.2nd.m-bg}
+toolbar.area.sitem.imagearea.background-disabled={image.toolbar.2nd.m-bg-disabled}
+toolbar.area.sitem.imagearea.background-disabled-over={image.toolbar.2nd.m-bg-disabled}
 toolbar.area.sitem.imagearea.background-over={image.toolbar.2nd.m-bg}
 toolbar.area.sitem.imagearea.background-down={template.imagedir}/tb/sec_r_l_down.png,{template.imagedir}/tb/sec_m_down.png,{template.imagedir}/tb/sec_l_r_down.png
 toolbar.area.sitem.imagearea.background.drawmode=tile-x
@@ -276,12 +267,10 @@ toolbar.area.sitem.image.type=image
 toolbar.area.sitem.image.view=toolbar-item-image
 toolbar.area.sitem.image.attach.left=0,0
 toolbar.area.sitem.image.attach.right=100,0
-toolbar.area.sitem.image.attach.top=0,0
-toolbar.area.sitem.image.attach.bottom=100,0
-toolbar.area.sitem.image.align=center
-toolbar.area.sitem.image.v-align=center
+toolbar.area.sitem.image.attach.top=0,2
+toolbar.area.sitem.image.attach.bottom=100,-2
 toolbar.area.sitem.image.cursor=hand
-toolbar.area.sitem.image.drawmode=center
+toolbar.area.sitem.image.drawmode=scaledown
 toolbar.area.sitem.image.width=1
 
 toolbar.area.sitem.title.type=text
@@ -312,6 +301,7 @@ toolbar.area.sitem.l.imagearea.attach.bottom=100,0
 toolbar.area.sitem.l.imagearea.attach.left=0,0
 toolbar.area.sitem.l.imagearea.attach.right=100,0
 toolbar.area.sitem.l.imagearea.background={image.toolbar.2nd.l-bg}
+toolbar.area.sitem.l.imagearea.background-disabled={image.toolbar.2nd.l-bg-disabled}
 toolbar.area.sitem.l.imagearea.background-over={image.toolbar.2nd.l-bg}
 toolbar.area.sitem.l.imagearea.background-down={image.toolbar.2nd.l-bg-down}
 toolbar.area.sitem.l.imagearea.background.drawmode=tile-x
@@ -332,6 +322,7 @@ toolbar.area.sitem.r.imagearea.attach.bottom=100,0
 toolbar.area.sitem.r.imagearea.attach.left=0,0
 toolbar.area.sitem.r.imagearea.attach.right=100,0
 toolbar.area.sitem.r.imagearea.background={image.toolbar.2nd.r-bg}
+toolbar.area.sitem.r.imagearea.background-disabled={image.toolbar.2nd.r-bg-disabled}
 toolbar.area.sitem.r.imagearea.background-over={image.toolbar.2nd.r-bg}
 toolbar.area.sitem.r.imagearea.background-down={image.toolbar.2nd.r-bg-down}
 toolbar.area.sitem.r.imagearea.background.drawmode=tile-x
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/Initializer.java b/azureus3/src/com/aelitis/azureus/ui/swt/Initializer.java
index 32cd33f..ada4ee4 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/Initializer.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/Initializer.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 29, 2006 2:13:41 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
@@ -29,7 +26,6 @@ import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.widgets.Display;
 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.global.GlobalManager;
@@ -62,17 +58,15 @@ import com.aelitis.azureus.core.versioncheck.VersionCheckClient;
 import com.aelitis.azureus.core.versioncheck.VersionCheckClientListener;
 import com.aelitis.azureus.ui.IUIIntializer;
 import com.aelitis.azureus.ui.InitializerListener;
+import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.swt.browser.listener.*;
 import com.aelitis.azureus.ui.swt.browser.msg.MessageDispatcherSWT;
 import com.aelitis.azureus.ui.swt.devices.DeviceManagerUI;
 import com.aelitis.azureus.ui.swt.feature.FeatureManagerUI;
-import com.aelitis.azureus.ui.swt.shells.main.MainWindow;
 import com.aelitis.azureus.ui.swt.shells.main.MainWindowFactory;
-import com.aelitis.azureus.ui.swt.shells.main.MainWindowFactory.MainWindowInitStub;
 import com.aelitis.azureus.ui.swt.subscriptions.SubscriptionManagerUI;
 import com.aelitis.azureus.ui.swt.utils.UIMagnetHandler;
-import com.aelitis.azureus.util.ConstantsVuze;
 import com.aelitis.azureus.util.InitialisationFunctions;
 
 /**
@@ -402,15 +396,21 @@ public class Initializer
 		core.addLifecycleListener(new AzureusCoreLifecycleAdapter() {
 			private GlobalManager gm;
 
-			public void componentCreated(AzureusCore core,
-					AzureusCoreComponent component) {
+			public void 
+			componentCreated(
+				AzureusCore 			core,
+				AzureusCoreComponent 	component )
+			{
 				Initializer.this.reportPercent(curPercent + 1);
-				if (component instanceof GlobalManager) {
+				
+				if (component instanceof GlobalManager){
+					
 					reportCurrentTaskByKey("splash.initializePlugins");
 
 					gm = (GlobalManager) component;
 
 					InitialisationFunctions.earlyInitialisation(core);
+					
 				}
 			}
 
@@ -458,12 +458,20 @@ public class Initializer
 					//Finally, open torrents if any.
 					for (int i = 0; i < args.length; i++) {
 	
-						try {
-							TorrentOpener.openTorrent(args[i]);
-	
-						} catch (Throwable e) {
-	
-							Debug.printStackTrace(e);
+						String arg = args[i];
+						
+						if ( arg.equalsIgnoreCase( "--open" )){
+							
+								// can get this here so skip as not a torrent!
+							
+						}else{
+							try {
+								TorrentOpener.openTorrent( arg );
+		
+							} catch (Throwable e) {
+		
+								Debug.printStackTrace(e);
+							}
 						}
 					}
 				}
@@ -508,16 +516,16 @@ public class Initializer
 
 		boolean uiClassic = COConfigurationManager.getStringParameter("ui").equals("az2");
 
-		if (!uiClassic) {
-  		try{
-  			new SubscriptionManagerUI();
-  			
-  		}catch( Throwable e ){
-  			
-  			Debug.printStackTrace(e);
-  		}
+		try{
+			new SubscriptionManagerUI();
+			
+		}catch( Throwable e ){
+			
+			Debug.printStackTrace(e);
+		}
 
   		
+		if (!uiClassic) {
   		try{
   			new DeviceManagerUI( core );
   				
@@ -557,6 +565,25 @@ public class Initializer
 		new CertificateTrustWindow();
 
 		InstallPluginWizard.register(core, display);
+		
+			// finally check if an explicit open has been requested in case hidden in tray atm
+		
+		for (int i = 0; i < args.length; i++) {
+			
+			String arg = args[i];
+			
+			if ( arg.equalsIgnoreCase( "--open" )){
+				
+				UIFunctions uif = UIFunctionsManager.getUIFunctions();
+				
+				if ( uif != null ){
+				
+					uif.bringToFront();
+				}
+				
+				break;
+			}
+		}
 	}
 
 	public void stopIt(boolean isForRestart, boolean isCloseAreadyInProgress)
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/UIConfigDefaultsSWTv3.java b/azureus3/src/com/aelitis/azureus/ui/swt/UIConfigDefaultsSWTv3.java
index 791436e..a4b16e4 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/UIConfigDefaultsSWTv3.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/UIConfigDefaultsSWTv3.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/BrowserContext.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/BrowserContext.java
index 98ac68a..adba75e 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/BrowserContext.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/BrowserContext.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 19, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
@@ -24,18 +21,26 @@ import java.util.*;
 import java.util.List;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.*;
+import org.eclipse.swt.browser.TitleListener;
+import org.eclipse.swt.browser.TitleEvent;
+import org.eclipse.swt.browser.ProgressListener;
+import org.eclipse.swt.browser.ProgressEvent;
+import org.eclipse.swt.browser.LocationListener;
+import org.eclipse.swt.browser.LocationEvent;
+import org.eclipse.swt.browser.OpenWindowListener;
+import org.eclipse.swt.browser.CloseWindowListener;
+import org.eclipse.swt.browser.WindowEvent;
 import org.eclipse.swt.events.DisposeEvent;
 import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.widgets.*;
-
 import org.gudy.azureus2.core3.util.*;
 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.BrowserWrapper;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
 import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
@@ -275,7 +280,7 @@ public class BrowserContext
 					final Shell shell = ShellFactory.createMainShell(SWT.SHELL_TRIM);
 					shell.setLayout(new FillLayout());
 					shell.setSize(920, 500);
-					Browser subBrowser = new Browser(shell,
+					BrowserWrapper subBrowser = BrowserWrapper.createBrowser(shell,
 							Utils.getInitialBrowserStyle(SWT.NONE));
 					subBrowser.addCloseWindowListener(new CloseWindowListener() {
 						public void close(WindowEvent event) {
@@ -283,10 +288,11 @@ public class BrowserContext
 						}
 					});
 					shell.open();
-					event.browser = subBrowser;
+					subBrowser.setBrowser( event );
+					
 				} else {
 
-					final BrowserWrapper subBrowser = new BrowserWrapper(browser.getBrowser(),
+					final BrowserWrapper subBrowser = BrowserWrapper.createBrowser(browser.getControl(),
 							Utils.getInitialBrowserStyle(SWT.NONE));
 					subBrowser.addLocationListener(new LocationListener() {
 						public void changed(LocationEvent arg0) {
@@ -315,11 +321,13 @@ public class BrowserContext
 							});
 						}
 					});
-					event.browser = subBrowser.getBrowser();
+					subBrowser.setBrowser( event );
 				}
 			}
 		});
 		
+		final BrowserWrapper bw = browser;
+		
 		browser.addLocationListener(new LocationListener() {
 			private TimerEvent timerevent;
 
@@ -432,7 +440,7 @@ public class BrowserContext
 							&& !event_location.equals("about:blank") 
 							&& !isPageLoadingOrRecent) {
   					event.doit = false;
-						String[] contentTypes = getContentTypes(event_location, ((Browser)event.widget).getUrl());
+						String[] contentTypes = getContentTypes(event_location, bw.getUrl());
 
 						boolean isTorrent = false;
 						for (String s : contentTypes) {
@@ -446,7 +454,7 @@ public class BrowserContext
 							}
 						}
 						
-						if (!isTorrent || !openTorrent(event)) {
+						if (!isTorrent || !openTorrent( bw, event)) {
 							Utils.launch(event.location);
 						}
   					return;
@@ -492,7 +500,7 @@ public class BrowserContext
 							
 							if ( test_for_torrent || test_for_vuze ){
 								
-								String[] contentTypes = getContentTypes(event_location, ((Browser)event.widget).getUrl());
+								String[] contentTypes = getContentTypes(event_location, bw.getUrl());
 
 								for (String s : contentTypes) {
 									
@@ -517,7 +525,7 @@ public class BrowserContext
 						
 						if ( isTorrent ){
 							
-							openTorrent(event);
+							openTorrent(bw,event);
 							
 						}else if ( isVuzeFile ){
 							
@@ -528,14 +536,14 @@ public class BrowserContext
 								String referer_str = null;
 
 								try{
-									referer_str = new URL(((Browser)event.widget).getUrl()).toExternalForm();
+									referer_str = new URL(bw.getUrl()).toExternalForm();
 
 								}catch( Throwable e ){
 								}
 																
 								Map headers = UrlUtils.getBrowserHeaders( referer_str );
 																		
-								String cookies = (String) ((Browser)event.widget).getData("current-cookies");
+								String cookies = (String) bw.getData("current-cookies");
 								
 								if ( cookies != null ){
 									
@@ -584,7 +592,7 @@ public class BrowserContext
 		this.display = browser.getDisplay();
 	}
 
-	protected boolean openTorrent(LocationEvent event) {
+	protected boolean openTorrent(BrowserWrapper browser, LocationEvent event) {
 		event.doit = false;
 		setPageLoading(false, event.location);
 		
@@ -592,7 +600,7 @@ public class BrowserContext
 			String referer_str = null;
 
 			try{
-				referer_str = new URL(((Browser)event.widget).getUrl()).toExternalForm();
+				referer_str = new URL(browser.getUrl()).toExternalForm();
 
 			}catch( Throwable e ){
 			}
@@ -600,7 +608,7 @@ public class BrowserContext
 			final Map headers = UrlUtils.getBrowserHeaders( referer_str );
 						
 			
-			String cookies = (String) ((Browser)event.widget).getData("current-cookies");
+			String cookies = (String)browser.getData("current-cookies");
 			
 			if (cookies != null ){
 				
@@ -829,6 +837,7 @@ public class BrowserContext
 	 * @param browser holds the context in its application data map
 	 * @return the browser's context or <code>null</code> if there is none
 	 */
+	/*
 	public static BrowserContext getContext(Browser browser) {
 		Object data = browser.getData(CONTEXT_KEY);
 		if (data != null && !(data instanceof BrowserContext)) {
@@ -839,7 +848,8 @@ public class BrowserContext
 
 		return (BrowserContext) data;
 	}
-
+	*/
+	
 	public void addMessageListener(BrowserMessageListener listener) {
 		messageDispatcherSWT.addListener(listener);
 	}
@@ -925,7 +935,7 @@ public class BrowserContext
 	}
 
 	public void widgetDisposed(DisposeEvent event) {
-		if (event.widget == browser.getBrowser()) {
+		if (event.widget == browser.getControl()) {
 			deregisterBrowser();
 		}
 	}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/BrowserWrapper.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/BrowserWrapper.java
deleted file mode 100644
index fb7970b..0000000
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/BrowserWrapper.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Created on Oct 2, 2012
- * Created by Paul Gardner
- * 
- * Copyright 2012 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 org.eclipse.swt.browser.Browser;
-import org.eclipse.swt.browser.CloseWindowListener;
-import org.eclipse.swt.browser.LocationListener;
-import org.eclipse.swt.browser.OpenWindowListener;
-import org.eclipse.swt.browser.ProgressListener;
-import org.eclipse.swt.browser.StatusTextListener;
-import org.eclipse.swt.browser.TitleListener;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Shell;
-
-public class 
-BrowserWrapper 
-{
-	private Browser		browser;
-	
-	public
-	BrowserWrapper(
-		Composite		composite,
-		int				style )
-	{
-		browser = new Browser( composite, style );
-	}
-	
-	public 
-	BrowserWrapper(
-		Browser		_browser )
-	{
-		browser = _browser;
-	}
-	
-	public Browser
-	getBrowser()
-	{
-		return( browser );
-	}
-	
-	public void
-	setVisible(
-		boolean		visible )
-	{
-		browser.setVisible( visible );
-	}
-	
-	public boolean
-	isVisible()
-	{
-		return( browser.isVisible());
-	}
-	
-	public boolean
-	isDisposed()
-	{
-		return( browser.isDisposed());
-	}
-	
-	public void
-	dispose()
-	{
-		browser.dispose();
-	}
-	
-	public boolean
-	execute(
-		String		str )
-	{
-		//System.out.println( "execute: " + str );
-		
-		return( browser.execute( str ));
-	}
-	
-	public boolean
-	isBackEnabled()
-	{
-		return( browser.isBackEnabled());
-	}
-	
-	public String
-	getUrl()
-	{
-		return( browser.getUrl());
-	}
-	
-	public void
-	setUrl(
-		String		url )
-	{
-		browser.setUrl( url );
-	}
-	
-	public void
-	setText(
-		String		text )
-	{
-		browser.setText( text );
-	}
-	
-	public void
-	setData(
-		String		key,
-		Object		value )
-	{
-		browser.setData(key, value);
-	}
-
-	public Object
-	getData(
-		String	key )
-	{
-		return( browser.getData( key ));
-	}
-	
-	public void
-	back()
-	{
-		browser.back();
-	}
-	
-	public void
-	refresh()
-	{
-		browser.refresh();
-	}
-	
-	public void
-	update()
-	{
-		browser.update();
-	}
-	
-	public Shell
-	getShell()
-	{
-		return( browser.getShell());
-	}
-	
-	public Display
-	getDisplay()
-	{
-		return( browser.getDisplay());
-	}
-	
-	public Composite
-	getParent()
-	{
-		return( browser.getParent());
-	}
-	
-	public Object
-	getLayoutData()
-	{
-		return( browser.getLayoutData());
-	}
-	
-	public void
-	setLayoutData(
-		Object	data )
-	{
-		browser.setLayoutData( data );
-	}
-	
-	public void
-	setFocus()
-	{
-		browser.setFocus();
-	}
-	
-	public void
-	addListener(
-		int			type,
-		Listener	l )
-	{
-		browser.addListener( type, l );
-	}
-	
-	public void
-	addLocationListener(
-		LocationListener		l )
-	{
-		browser.addLocationListener( l );
-	}
-	
-	public void
-	removeLocationListener(
-		LocationListener		l )
-	{
-		browser.removeLocationListener( l );
-	}
-	
-	public void
-	addTitleListener(
-		TitleListener		l )
-	{
-		browser.addTitleListener( l );
-	}
-	
-	public void
-	addProgressListener(
-		ProgressListener		l )
-	{
-		browser.addProgressListener( l );
-	}
-	
-	public void
-	removeProgressListener(
-		ProgressListener		l )
-	{
-		browser.removeProgressListener( l );
-	}
-	
-	public void
-	addOpenWindowListener(
-		OpenWindowListener		l )
-	{
-		browser.addOpenWindowListener( l );
-	}
-	
-	public void
-	addCloseWindowListener(
-		CloseWindowListener		l )
-	{
-		browser.addCloseWindowListener( l );
-	}
-	
-	public void
-	addDisposeListener(
-		DisposeListener		l )
-	{
-		browser.addDisposeListener( l );
-	}
-	
-	public void
-	removeDisposeListener(
-		DisposeListener		l )
-	{
-		browser.removeDisposeListener( l );
-	}
-	
-	public void
-	addStatusTextListener(
-		StatusTextListener		l )
-	{
-		browser.addStatusTextListener( l );
-	}
-	
-	public void
-	removeStatusTextListener(
-		StatusTextListener		l )
-	{
-		browser.removeStatusTextListener( l );
-	}
-}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/ClientMessageContextSWT.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/ClientMessageContextSWT.java
deleted file mode 100644
index a5e6231..0000000
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/ClientMessageContextSWT.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * Created on Jun 1, 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 org.eclipse.swt.browser.Browser;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.widgets.Control;
-
-import com.aelitis.azureus.core.messenger.ClientMessageContext;
-
-/**
- * @author TuxPaper
- * @created Jun 1, 2008
- *
- */
-public interface ClientMessageContextSWT
-	extends ClientMessageContext
-{
-	/**
-	 * Attaches this context and its message dispatcher to the browser.
-	 * 
-	 * @param browser the browser to be attached
-	 * @param widgetWaitingIndicator Widget to be shown when browser is loading
-	 */
-	public abstract void registerBrowser(final Browser browser,
-			Control widgetWaitingIndicator);
-
-	/**
-	 * Detaches everything from this context's browser.
-	 */
-	public abstract void deregisterBrowser();
-
-	/**
-	 * Deregisters the browser before it's disposed.
-	 * 
-	 * @param event used to verify it's the correct context
-	 * 
-	 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
-	 */
-	public abstract void widgetDisposed(DisposeEvent event);
-}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/CookiesListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/CookiesListener.java
index e2ac93d..417bfe6 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/CookiesListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/CookiesListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.browser;
 
 public interface CookiesListener {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/OpenCloseSearchDetailsListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/OpenCloseSearchDetailsListener.java
index 477eef0..c51c367 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/OpenCloseSearchDetailsListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/OpenCloseSearchDetailsListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.browser;
 
 import java.util.Map;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ConfigListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ConfigListener.java
index 3bbf4fd..03efd46 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ConfigListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ConfigListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,21 +13,17 @@
  * 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.browser.listener;
 
 import java.util.Map;
 
-import org.eclipse.swt.browser.Browser;
-
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.util.AEDiagnostics;
 import org.gudy.azureus2.core3.util.AEDiagnosticsLogger;
 import org.gudy.azureus2.core3.util.Constants;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import org.gudy.azureus2.ui.swt.update.UpdateMonitor;
 
 import com.aelitis.azureus.core.AzureusCore;
@@ -37,7 +33,6 @@ import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
 import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.browser.BrowserWrapper;
 import com.aelitis.azureus.util.ConstantsVuze;
 import com.aelitis.azureus.util.MapUtils;
 import com.aelitis.net.magneturi.MagnetURIHandler;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/DisplayListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/DisplayListener.java
index 2f065ad..db37282 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/DisplayListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/DisplayListener.java
@@ -1,10 +1,27 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.browser.listener;
 
 import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.eclipse.swt.browser.Browser;
 import org.eclipse.swt.dnd.*;
 import org.eclipse.swt.widgets.Display;
 import org.gudy.azureus2.core3.download.DownloadManager;
@@ -12,6 +29,7 @@ import org.gudy.azureus2.core3.torrent.TOTorrent;
 import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.donations.DonationWindow;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
@@ -31,7 +49,6 @@ import com.aelitis.azureus.ui.selectedcontent.*;
 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.browser.BrowserWrapper;
 import com.aelitis.azureus.ui.swt.feature.FeatureManagerUI;
 import com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry;
 import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
@@ -40,7 +57,7 @@ import com.aelitis.azureus.ui.swt.skin.*;
 import com.aelitis.azureus.ui.swt.views.skin.SBC_BurnFTUX;
 import com.aelitis.azureus.ui.swt.views.skin.SBC_PlusFTUX;
 import com.aelitis.azureus.util.*;
-
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.PluginManager;
 import org.gudy.azureus2.plugins.ui.*;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/DownloadUrlInfoSWT.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/DownloadUrlInfoSWT.java
index 41ec0ce..441c678 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/DownloadUrlInfoSWT.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/DownloadUrlInfoSWT.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 17, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginCookieListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginCookieListener.java
index b4a9956..b07932f 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginCookieListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginCookieListener.java
@@ -1,9 +1,26 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.browser.listener;
 
 import java.net.URLDecoder;
 
 
-import org.eclipse.swt.browser.Browser;
 import org.eclipse.swt.browser.LocationEvent;
 import org.eclipse.swt.browser.LocationListener;
 import org.eclipse.swt.browser.ProgressEvent;
@@ -11,7 +28,7 @@ import org.eclipse.swt.browser.ProgressListener;
 import org.eclipse.swt.browser.StatusTextEvent;
 import org.eclipse.swt.browser.StatusTextListener;
 
-import com.aelitis.azureus.ui.swt.browser.BrowserWrapper;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import com.aelitis.azureus.ui.swt.browser.CookiesListener;
 
 public class ExternalLoginCookieListener
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginListener.java
index d83955b..07b33b7 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.browser.listener;
 
 public interface ExternalLoginListener {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginWindow.java
index 36715fd..503d654 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/ExternalLoginWindow.java
@@ -1,10 +1,27 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.browser.listener;
 
 import java.util.*;
 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;
@@ -20,6 +37,7 @@ 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.BrowserWrapper;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
 import org.gudy.azureus2.ui.swt.progress.ProgressWindow;
@@ -27,7 +45,6 @@ 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.browser.BrowserWrapper;
 import com.aelitis.azureus.ui.swt.browser.CookiesListener;
 
 public class ExternalLoginWindow {
@@ -90,7 +107,7 @@ public class ExternalLoginWindow {
 			explain.setText(MessageText.getString("externalLogin.explanation", new String[]{ name }));
 		}
 		
-		browser = new BrowserWrapper( Utils.createSafeBrowser(shell, SWT.BORDER));
+		browser = Utils.createSafeBrowser(shell, SWT.BORDER);
 		if (browser == null) {
 			shell.dispose();
 			return;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/MetaSearchListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/MetaSearchListener.java
index 365fe3b..6d7fb7d 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/MetaSearchListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/MetaSearchListener.java
@@ -1,2078 +1,2077 @@
-/*
- * Created on May 6, 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.ui.swt.browser.listener;
-
-import java.io.File;
-import java.net.URL;
-import java.util.*;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Shell;
-
-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.global.GlobalManagerListener;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.torrent.TOTorrent;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-
-import com.aelitis.azureus.core.AzureusCore;
-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.custom.CustomizationManagerFactory;
-import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
-import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener;
-import com.aelitis.azureus.core.messenger.config.PlatformConfigMessenger;
-import com.aelitis.azureus.core.metasearch.*;
-import com.aelitis.azureus.core.metasearch.impl.web.CookieParser;
-import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
-import com.aelitis.azureus.core.subs.Subscription;
-import com.aelitis.azureus.core.subs.SubscriptionDownloadListener;
-import com.aelitis.azureus.core.subs.SubscriptionException;
-import com.aelitis.azureus.core.subs.SubscriptionHistory;
-import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
-import com.aelitis.azureus.core.subs.SubscriptionResult;
-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.swt.browser.OpenCloseSearchDetailsListener;
-import com.aelitis.azureus.ui.swt.views.skin.TorrentListViewsUtils;
-import com.aelitis.azureus.util.*;
-
-public class MetaSearchListener extends AbstractBrowserMessageListener {
-	
-	public static final String LISTENER_ID = "metasearch";
-
-	public static final String OP_SEARCH				= "search";
-		
-	public static final String OP_GET_ENGINES 			= "get-engines";
-	public static final String OP_GET_ALL_ENGINES 		= "get-all-engines";
-	public static final String OP_ENGINE_PREFERRED		= "engine-preferred";
-
-	public static final String OP_CHANGE_ENGINE_SELECTION 	= "change-engine-selection";
-	
-	public static final String OP_SET_SELECTED_ENGINES 	= "set-selected-engines";
-
-	public static final String OP_GET_AUTO_MODE		 	= "get-auto-mode";
-	
-	public static final String OP_SAVE_TEMPLATE		 	= "save-template";
-	public static final String OP_LOAD_TEMPLATE		 	= "load-template";
-	public static final String OP_DELETE_TEMPLATE		= "delete-template";
-	public static final String OP_TEST_TEMPLATE			= "test-template";
-	
-	public static final String OP_EXPORT_TEMPLATE		= "export-template";
-	public static final String OP_IMPORT_TEMPLATE		= "import-template";
-	
-	public static final String OP_OPEN_SEARCH_RESULTS	= "open-search-results";
-	public static final String OP_CLOSE_SEARCH_RESULTS	= "close-search-results";
-	
-	public static final String OP_LOAD_TORRENT			= "load-torrent";
-	public static final String OP_HAS_LOAD_TORRENT		= "has-load-torrent";
-	
-	public static final String OP_ENGINE_LOGIN			= "engine-login";
-	public static final String OP_GET_LOGIN_COOKIES		= "get-login-cookies";
-	
-	public static final String OP_CREATE_SUBSCRIPTION   		= "create-subscription";
-	public static final String OP_READ_SUBSCRIPTION   			= "read-subscription";
-	public static final String OP_UPDATE_SUBSCRIPTION   		= "update-subscription";
-	public static final String OP_READ_SUBSCRIPTION_RESULTS   	= "read-subscription-results";
-	public static final String OP_DELETE_SUBSCRIPTION_RESULTS   = "delete-subscription-results";
-	public static final String OP_MARK_SUBSCRIPTION_RESULTS	   	= "mark-subscription-results";
-	public static final String OP_DOWNLOAD_SUBSCRIPTION   		= "download-subscription";
-	public static final String OP_SUBSCRIPTION_SET_AUTODL   	= "subscription-set-auto-download";
-
-	public static final String OP_IS_CUSTOMISED   				= "is-customized";
-
-	public static final String OP_ADD_EXTERNAL_LINKS   				= "add-external-links";
-
-	private static final Set	active_subs_auth = new HashSet();
-	
-	private static final Set	pending_play_now_urls = new HashSet();
-	
-	static{
-		TorrentUtils.addTorrentAttributeListener(
-			new TorrentUtils.torrentAttributeListener()
-			{
-				public void 
-				attributeSet(
-					TOTorrent 	torrent,
-					String 		attribute, 
-					Object 		value )
-				{
-					if ( attribute == TorrentUtils.TORRENT_AZ_PROP_OBTAINED_FROM ){
-						
-						try{
-							String torrent_url = (String)value;
-							
-							boolean hook_dm = false;
-							
-							synchronized(pending_play_now_urls ){
-								
-								if ( pending_play_now_urls.remove( torrent_url )){
-									
-										// ok, we now have the torrent associated with the URL
-																		
-									hook_dm = true;
-								}
-							}
-							
-							if ( !hook_dm ) {
-								return;
-							}
-							
-							if (!AzureusCoreFactory.isCoreRunning()) {
-								// shouldn't happen, but..
-								Debug.out("Core wasn't available for pending play now" );
-								
-							} else {
-								
-								final HashWrapper hash = torrent.getHashWrapper();
-								
-								AzureusCore core = AzureusCoreFactory.getSingleton();
-								
-								final GlobalManager gm = core.getGlobalManager();
-					
-								DownloadManager existing = gm.getDownloadManager( hash );
-								
-								if ( existing != null) {
-
-									playOrStream( existing );
-	
-									return;
-								}
-	
-								GlobalManagerListener l = 
-									new GlobalManagerAdapter() 
-									{
-										private final long listener_add_time = SystemTime.getMonotonousTime();
-										
-										public void 
-										downloadManagerAdded(
-											DownloadManager dm )
-										{
-											try{	
-												TOTorrent t = dm.getTorrent();
-												
-												if ( t.getHashWrapper().equals( hash )){
-													
-													gm.removeListener( this );
-													
-													playOrStream( dm );
-												}
-											
-											}catch( Throwable e ){
-												
-												Debug.out( e );
-												
-											}finally{
-												
-												if ( SystemTime.getMonotonousTime() - listener_add_time > 5*60*1000 ){
-													
-													gm.removeListener( this );
-												}
-											}
-										}
-									};
-									
-								gm.addListener( l, false );
-							}
-						}catch( Throwable e ){
-							
-							Debug.printStackTrace(e);
-						}
-					}
-				}				
-			});
-	}
-	
-	private static void
-	playOrStream(
-		final DownloadManager		download )
-	{
-		new AEThread2( "MSL:POS", true )
-		{
-			public void
-			run()
-			{
-				TorrentListViewsUtils.playOrStream( download, -1 );
-			}
-		}.start();
-	}
-	
-	private final OpenCloseSearchDetailsListener openCloseSearchDetailsListener;
-	
-	
-	public 
-	MetaSearchListener(
-		OpenCloseSearchDetailsListener openCloseSearchDetailsListener )
-	{
-		super(LISTENER_ID);
-		
-		this.openCloseSearchDetailsListener = openCloseSearchDetailsListener;
-	}
-	
-	public void handleMessage(BrowserMessage message) {
-		
-		String opid = message.getOperationId();
-
-		MetaSearchManager metaSearchManager = MetaSearchManagerFactory.getSingleton();
-		
-		metaSearchManager.log( "BrowserListener: received " + message );
-		
-		if (OP_SEARCH.equals(opid)) {
-			
-			Map decodedMap = message.getDecodedMap();
-			
-
-			search( decodedMap, null );
-
-		}else if ( OP_ENGINE_PREFERRED.equals( opid )){
-			
-			final Map decodedMap = message.getDecodedMap();
-			
-			long engine_id = ((Long)decodedMap.get("engine_id")).longValue();
-
-			Engine engine = getEngineFromId( engine_id );
-
-			if ( engine != null ){
-				
-				metaSearchManager.getMetaSearch().enginePreferred( engine );
-			}
-
-		} else if(OP_ENGINE_LOGIN.equals(opid)) {
-			
-			final Map decodedMap = message.getDecodedMap();
-			
-			long engine_id = ((Long)decodedMap.get("engine_id")).longValue();
-			
-			final Long	sid = (Long)decodedMap.get( "sid" );
-
-			final Engine engine = getEngineFromId(engine_id);
-			
-			if ( engine != null && engine instanceof WebEngine){
-				
-				final WebEngine webEngine = (WebEngine) engine;
-
-				Utils.execSWTThread( new Runnable() {
-					public void run() {
-						new ExternalLoginWindow(
-							new ExternalLoginListener() 
-							{
-								private String previous_cookies;
-								
-								private boolean	search_done;
-								
-								public void 
-								canceled(
-									ExternalLoginWindow 	window ) 
-								{
-									/* gouss doesn't wan't anything on cancel
-									if ( !outcome_informed ){
-										
-										outcome_informed = true;
-										
-										Map params = getParams( webEngine );
-										
-										params.put( "error", "operation cancelled" );
-										
-										sendBrowserMessage("metasearch", "engineFailed", params );
-									}
-									*/
-								}
-	
-								public void 
-								cookiesFound(
-									ExternalLoginWindow 	window,
-									String 					cookies ) 
-								{
-									if ( handleCookies( cookies, false )){
-										
-										window.close();									
-									}
-								}
-	
-								public void 
-								done(
-									ExternalLoginWindow 	window,
-									String 					cookies )
-								{
-									handleCookies( cookies, true );
-									
-									/*
-									if ( !outcome_informed ){
-										
-										outcome_informed = true;
-										
-										Map params = getParams( webEngine );
-																				
-										sendBrowserMessage("metasearch", "engineCompleted", params );
-									}
-									*/
-								}
-								
-								private boolean
-								handleCookies(
-									String		cookies,
-									boolean		force_if_ready )
-								{
-									if ( search_done ){
-										
-										return( false );
-									}
-									
-									String[] required = webEngine.getRequiredCookies();
-									
-									boolean	skip_search = required.length == 0 && !force_if_ready;
-									
-									if ( CookieParser.cookiesContain( required, cookies )){
-											
-										webEngine.setCookies(cookies);
-										
-										if ( previous_cookies == null || !previous_cookies.equals( cookies )){
-											
-											previous_cookies = cookies;
-											
-											if ( !skip_search ){
-												
-													// search operation will report outcome
-												
-												search_done	= true;
-												
-												search( decodedMap, webEngine );
-											}
-										}
-									}
-	
-									return( search_done );
-								}
-								
-								/*
-								protected Map
-								getParams(
-									Engine	engine )
-								{
-									Map params = new HashMap();
-									params.put("id", new Long(engine.getId()));
-									params.put("name", engine.getName());
-									params.put("favicon", engine.getIcon());
-									params.put("dl_link_css", engine.getDownloadLinkCSS());
-									params.put("shareable", new Boolean( engine.isShareable()));
-									
-									if ( sid != null ){
-										params.put( "sid", sid );
-									}
-									return( params );
-								}
-								*/
-							},
-						webEngine.getName(),
-						webEngine.getLoginPageUrl(),
-						false,
-						webEngine.getAuthMethod(),
-						engine.isMine());
-					}
-				});
-			}else{
-				
-				Map params = new HashMap();
-				
-				if ( sid != null ){
-					params.put( "sid", sid );
-				}
-				params.put( "error", "engine not found or not a web engine" );
-				
-				sendBrowserMessage("metasearch", "engineFailed", params );
-			}
-		} else if(OP_GET_LOGIN_COOKIES.equals(opid)) {
-			
-			final Map decodedMap = message.getDecodedMap();
-			
-			final String url = ((String) decodedMap.get("url")).replaceAll("%s", "");
-			
-			Utils.execSWTThread( new Runnable() {
-				public void run() {
-					new ExternalLoginWindow(
-						new ExternalLoginListener() 
-						{	
-						public void canceled(ExternalLoginWindow window) {
-							sendBrowserMessage("metasearch", "setCookiesFailed", new HashMap() );
-						};
-						public void cookiesFound(ExternalLoginWindow window, String cookies) {};
-						public void done(ExternalLoginWindow window, String cookies) {
-							String[] cookieNames = CookieParser.getCookiesNames(cookies);
-							Map params = new HashMap();
-							params.put("cookieNames", cookieNames);
-							params.put("currentCookie",cookies);
-							params.put("cookieMethod", window.proxyCaptureModeRequired()?WebEngine.AM_PROXY:WebEngine.AM_TRANSPARENT );
-							sendBrowserMessage("metasearch", "setCookies", params );
-						};
-						}, 
-						url, 
-						url,
-						true,
-						WebEngine.AM_PROXY,
-						true );
-				}
-			});
-			
-			
-		} else if(OP_GET_ENGINES.equals(opid)) {
-			String subscriptionId  = null;
-			
-			try {
-				final Map decodedMap = message.getDecodedMap();
-
-				subscriptionId		= ((String)decodedMap.get("subs_id"));
-			} catch(Exception e) {
-				//No parameters
-			}
-			
-			Engine[] engines = null;
-			
-			if ( subscriptionId != null ){
-				
-				engines = new Engine[0];
-				
-				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( subscriptionId );
-				
-				if ( subs != null ){
-				
-					try{
-						Engine engine = subs.getEngine();
-						
-						if ( engine != null ){
-							
-							engines = new Engine[]{ engine };
-						}
-					}catch( Throwable e ){
-					
-						Debug.out( e );
-					}
-				}
-			}
-			
-			if ( engines == null ){
-				
-				engines = metaSearchManager.getMetaSearch().getEngines( true, true );
-			}
-			
-			List params = new ArrayList();
-			for(int i = 0 ; i < engines.length ; i++) {
-				Engine engine = engines[i];
-				
-				if ( !engine.isActive() || engine.getSource() == Engine.ENGINE_SOURCE_UNKNOWN ){
-					
-						// don't skip if this is an explicit get
-					
-					if ( subscriptionId == null ){
-					
-						continue;
-					}
-				}
-				Map engineMap = new HashMap();
-				engineMap.put("id", new Long(engine.getId()));
-				engineMap.put("name", engine.getName());
-				engineMap.put("favicon", engine.getIcon());
-				engineMap.put("dl_link_css", engine.getDownloadLinkCSS());
-				engineMap.put("selected", Engine.SEL_STATE_STRINGS[ engine.getSelectionState()]);
-				engineMap.put("type", Engine.ENGINE_SOURCE_STRS[ engine.getSource()]);
-				engineMap.put("shareable", new Boolean( engine.isShareable()));
-				params.add(engineMap);
-			}
-			sendBrowserMessage("metasearch", "enginesUsed",params);
-			
-		} else if(OP_GET_ALL_ENGINES.equals(opid)) {
-
-			Engine[] engines = metaSearchManager.getMetaSearch().getEngines( false, true );
-			List params = new ArrayList();
-			for(int i = 0 ; i < engines.length ; i++) {
-				Engine engine = engines[i];
-				
-				if ( engine.getSource() == Engine.ENGINE_SOURCE_UNKNOWN ){
-					continue;
-				}
-				
-				Map engineMap = new HashMap();
-				engineMap.put("id", new Long(engine.getId()));
-				engineMap.put("name", engine.getName());
-				engineMap.put("favicon", engine.getIcon());
-				engineMap.put("dl_link_css", engine.getDownloadLinkCSS());
-				engineMap.put("selected", Engine.SEL_STATE_STRINGS[ engine.getSelectionState()]);
-				engineMap.put("type", Engine.ENGINE_SOURCE_STRS[ engine.getSource()]);
-				engineMap.put("shareable", new Boolean( engine.isShareable()));
-				params.add(engineMap);
-			}
-			sendBrowserMessage("metasearch", "engineList",params);
-			
-		} else if( OP_SET_SELECTED_ENGINES.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-
-			List template_ids = (List)decodedMap.get( "template_ids" );
-			
-			long[] ids = new long[template_ids.size()];
-			
-			for (int i=0;i<ids.length;i++ ){
-				
-				Map m = (Map)template_ids.get(i);
-				
-				ids[i] = ((Long)m.get("id")).longValue();
-			}
-			
-			boolean	auto = ((Boolean)decodedMap.get( "auto" )).booleanValue();
-			
-				// there's some code that attempts to switch to 'auto=true' on first use as
-				// when 3110 defaults to false and the decision was made to switch this
-				// disable the behaviour if we are customised
-			
-			
-			Boolean	is_default = (Boolean)decodedMap.get( "set_default" );
-			
-			boolean skip = false;
-			
-			if ( is_default != null && is_default.booleanValue()){
-				
-				if ( CustomizationManagerFactory.getSingleton().getActiveCustomization() != null ){
-					
-					skip = true;
-				}
-			}
-			
-			try{
-				if ( !skip ){
-					
-					metaSearchManager.setSelectedEngines( ids, auto );
-				}
-				
-				Map params = new HashMap();
-				sendBrowserMessage("metasearch", "setSelectedCompleted",params);
-
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				Map params = new HashMap();
-				params.put("error",Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage("metasearch", "setSelectedFailed",params);
-			}
-		} else if( OP_CHANGE_ENGINE_SELECTION.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-
-			MetaSearch ms = metaSearchManager.getMetaSearch();
-			
-			Engine[] engines = ms.getEngines( false, true );
-			
-			Set selected = new HashSet();
-			
-			for (int i=0;i<engines.length;i++){
-				
-				Engine e = engines[i];
-				
-				if ( e.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED ){
-					
-					selected.add( new Long( e.getId()));
-				}
-			}
-			
-			List l_engines = (List)decodedMap.get( "engines" );
-			
-			for (int i=0;i<l_engines.size();i++){
-				
-				Map	map = (Map)l_engines.get(i);
-				
-				long id = ((Long)map.get("id")).longValue();
-
-				String str = (String)map.get( "selected");
-				
-				if ( str.equalsIgnoreCase( Engine.SEL_STATE_STRINGS[Engine.SEL_STATE_MANUAL_SELECTED])){
-					
-					selected.add( new Long( id ));
-					
-				}else if ( str.equalsIgnoreCase( Engine.SEL_STATE_STRINGS[Engine.SEL_STATE_DESELECTED])){
-					
-					selected.remove( new Long( id ));
-				}
-			}
-			
-			long[] ids = new long[selected.size()];
-			
-			Iterator it = selected.iterator();
-			
-			int	pos = 0;
-			
-			while( it.hasNext()){
-				
-				long	 id = ((Long)it.next()).longValue();
-				
-				ids[pos++] = id;
-			}
-						
-			try{
-				metaSearchManager.setSelectedEngines( ids, metaSearchManager.isAutoMode());
-				
-				Map params = new HashMap();
-				sendBrowserMessage("metasearch", "changeEngineSelectionCompleted",params);
-
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				Map params = new HashMap();
-				params.put("error",Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage("metasearch", "changeEngineSelectionFailed",params);
-			}	
-		} else if(OP_GET_AUTO_MODE.equals(opid)) {
-						
-			boolean mode = metaSearchManager.isAutoMode();
-			
-			Map params = new HashMap();
-			
-			params.put( "auto", new Boolean( mode ));
-
-			boolean custom = CustomizationManagerFactory.getSingleton().getActiveCustomization() != null;
-						
-			params.put( "is_custom", new Boolean( custom ));
-
-			sendBrowserMessage("metasearch", "getAutoModeResult",params);
-			
-		} else if( OP_SAVE_TEMPLATE.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-
-			String	type_str = (String)decodedMap.get( "type" );
-			
-			String	name = (String)decodedMap.get( "name" );
-			
-			Long	l_id	= (Long)decodedMap.get( "id" );
-			
-			long	id = l_id == null?-1:l_id.longValue();
-			
-			String	json = (String)decodedMap.get( "value" );
-			
-			String	cookies = (String)decodedMap.get( "current_cookie" );
-			
-			
-			try{
-				Engine engine = 
-					metaSearchManager.addEngine( 
-							id, 
-							type_str.equals( "json" )?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX, 
-							name, 
-							json );
-				
-				engine.setMine( true );
-				
-				if(cookies!= null && engine instanceof WebEngine) {
-					WebEngine we = (WebEngine) engine;
-					we.setCookies(cookies);
-				}
-				
-				Map params = new HashMap();
-				params.put( "id", new Long( engine.getId() ));
-	
-				sendBrowserMessage( "metasearch", "saveTemplateCompleted", params );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				Map params = new HashMap();
-				params.put( "id", new Long( id ));
-				params.put("error",Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage("metasearch", "saveTemplateFailed",params);
-			}
-		} else if( OP_LOAD_TEMPLATE.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-
-			long	id	= ((Long)decodedMap.get( "id" )).longValue();
-			
-			Engine engine = metaSearchManager.getMetaSearch().getEngine( id );
-		
-			if ( engine == null ){
-			
-				Map params = new HashMap();
-				params.put( "id", new Long( id ));
-				params.put("error","Template not found");
-
-				sendBrowserMessage("metasearch", "loadTemplateFailed",params);
-				
-			}else{
-				
-				try{
-					Map params = new HashMap();
-					params.put("id", new Long(engine.getId()));
-					params.put("name", engine.getName());
-					params.put("type", Engine.ENGINE_TYPE_STRS[ engine.getType()]);
-					params.put("value", JSONObject.escape( engine.exportToJSONString()));
-					params.put("shareable", new Boolean( engine.isShareable()));
-					
-					params.put("uid", engine.getUID());
-					
-					params.put("supports_direct_download", 
-									new Boolean( 	engine.supportsField( Engine.FIELD_TORRENTLINK ) ||
-													engine.supportsField( Engine.FIELD_DOWNLOADBTNLINK )));
-					
-					params.put( "auto_dl_supported", new Boolean( engine.getAutoDownloadSupported() == Engine.AUTO_DL_SUPPORTED_YES ));
-
-					sendBrowserMessage( "metasearch", "loadTemplateCompleted", params );
-					
-				}catch( Throwable e ){
-					
-					Debug.out( e );
-					
-					Map params = new HashMap();
-					params.put( "id", new Long( id ));
-					params.put("error",Debug.getNestedExceptionMessage(e));
-
-					sendBrowserMessage("metasearch", "loadTemplateFailed",params);
-				}
-			}		
-		} else if( OP_DELETE_TEMPLATE.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-
-			long	id	= ((Long)decodedMap.get( "id" )).longValue();
-			
-			Engine engine = metaSearchManager.getMetaSearch().getEngine( id );
-			
-			if ( engine == null ){
-			
-				Map params = new HashMap();
-				params.put( "id", new Long( id ));
-				params.put( "error", "Template not found" );
-
-				sendBrowserMessage("metasearch", "deleteTemplateFailed",params);
-			
-			}else if ( engine.getSource() != Engine.ENGINE_SOURCE_LOCAL ){
-			
-				Map params = new HashMap();
-				params.put( "id", new Long( id ));
-				params.put( "error", "Template is not local" );
-
-				sendBrowserMessage("metasearch", "deleteTemplateFailed",params);
-				
-			}else{
-				
-				engine.delete();
-				
-				Map params = new HashMap();
-				params.put( "id", new Long( id ));
-				sendBrowserMessage( "metasearch", "deleteTemplateCompleted", params );
-			}
-		} else if( OP_TEST_TEMPLATE.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-
-			final long	id		= ((Long)decodedMap.get( "id" )).longValue();
-			long	match_count	= ((Long)decodedMap.get( "max_matches" )).longValue();
-			
-			String searchText 	= (String) decodedMap.get("searchText");
-			String headers		= (String) decodedMap.get("headers");
-
-			final Long	sid = (Long)decodedMap.get( "sid" );
-
-			Engine engine = metaSearchManager.getMetaSearch().getEngine( id );
-			
-			if ( engine == null ){
-			
-				Map params = new HashMap();
-				params.put( "id", new Long( id ));
-				params.put( "error", "Template not found" );
-				if ( sid != null )params.put( "sid", sid );
-
-				sendBrowserMessage("metasearch", "testTemplateFailed",params);
-			
-			}else{
-				
-				SearchParameter parameter = new SearchParameter("s",searchText);
-				SearchParameter[] parameters = new SearchParameter[] {parameter};
-
-				try{
-				
-					engine.search(
-							parameters, 
-							new HashMap(),
-							(int)match_count,
-							(int)match_count,
-							headers,
-							new ResultListener()
-							{
-								private String	content;
-								private List	matches = new ArrayList();
-								
-								public void 
-								contentReceived(
-									Engine 		engine, 
-									String 		_content )
-								{
-									content = _content;
-								}
-								
-								public void 
-								matchFound(
-									Engine 		engine,
-									String[] 	fields) 
-								{
-									matches.add( fields );
-								}
-								
-								public void 
-								resultsReceived(
-									Engine 		engine,
-									Result[] 	results )
-								{								
-								}
-								
-								public void 
-								resultsComplete(
-									Engine 		engine )
-								{
-									Map params = new HashMap();
-									params.put( "id", new Long( id ));
-									if ( sid != null )params.put( "sid", sid );
-									params.put( "content", JSONObject.escape( content ));
-	
-									JSONArray	l_matches = new JSONArray();
-									
-									params.put( "matches", l_matches );
-									
-									for (int i=0;i<matches.size();i++){
-										
-										String[]	match = (String[])matches.get(i);
-										
-										JSONArray	l_match = new JSONArray();
-										
-										l_matches.add( l_match );
-										
-										for (int j=0;j<match.length;j++){
-											
-											l_match.add( match[j] );
-										}
-									}
-																
-									sendBrowserMessage( "metasearch", "testTemplateCompleted", params );
-				
-								}
-								
-								public void 
-								engineFailed(
-									Engine 		engine,
-									Throwable 	e )
-								{
-									Debug.out( e );
-									
-									Map params = new HashMap();
-									params.put( "id", new Long( id ));
-									params.put( "error", Debug.getNestedExceptionMessage( e ));
-									if ( sid != null )params.put( "sid", sid );
-	
-									sendBrowserMessage("metasearch", "testTemplateFailed",params);
-								}
-								
-								public void 
-								engineRequiresLogin(
-									Engine 		engine,
-									Throwable 	e )
-								{
-									Map params = new HashMap();
-									params.put( "id", new Long( id ));
-									params.put( "error", Debug.getNestedExceptionMessage( e ));
-									if ( sid != null )params.put( "sid", sid );
-	
-									sendBrowserMessage("metasearch", "testTemplateRequiresLogin",params);
-								}
-							});
-				}catch( SearchException e ){
-						// listener handles
-				}
-			}	
-		} else if ( OP_EXPORT_TEMPLATE.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-
-			final long	id		= ((Long)decodedMap.get( "id" )).longValue();
-			
-			final Engine engine = metaSearchManager.getMetaSearch().getEngine( id );
-			
-			if ( engine == null ){
-				
-				Map params = new HashMap();
-				params.put( "error", "template '" + id + "' not found" );
-
-				sendBrowserMessage("metasearch", "exportTemplateFailed",params);
-				
-			}else{
-				final Shell shell = Utils.findAnyShell();
-				
-				shell.getDisplay().asyncExec(
-					new AERunnable() 
-					{
-						public void 
-						runSupport()
-						{
-							FileDialog dialog = 
-								new FileDialog( shell, SWT.SYSTEM_MODAL | SWT.SAVE );
-							
-							dialog.setFilterPath( TorrentOpener.getFilterPathData() );
-													
-							dialog.setText(MessageText.getString("metasearch.export.select.template.file"));
-							
-							dialog.setFilterExtensions(new String[] {
-									"*.vuze",
-									"*.vuz",
-									Constants.FILE_WILDCARD
-								});
-							dialog.setFilterNames(new String[] {
-									"*.vuze",
-									"*.vuz",
-									Constants.FILE_WILDCARD
-								});
-							
-							String path = TorrentOpener.setFilterPathData( dialog.open());
-		
-							if ( path != null ){
-								
-								String lc = path.toLowerCase();
-								
-								if ( !lc.endsWith( ".vuze" ) && !lc.endsWith( ".vuz" )){
-									
-									path += ".vuze";
-								}
-								
-								try{
-									engine.exportToVuzeFile( new File( path ));
-									
-									Map params = new HashMap();
-									params.put( "id", new Long( id ));
-									sendBrowserMessage( "metasearch", "exportTemplateCompleted", params );
-
-								}catch( Throwable e ){
-									
-									Debug.out( e );
-									
-									Map params = new HashMap();
-									params.put( "id", new Long( id ));
-									params.put( "error", "save failed: " + Debug.getNestedExceptionMessage(e));
-
-									sendBrowserMessage("metasearch", "exportTemplateFailed",params);
-								}
-							}else{
-								
-								Map params = new HashMap();
-								params.put( "id", new Long( id ));
-								params.put( "error", "operation cancelled" );
-
-								sendBrowserMessage("metasearch", "exportTemplateFailed",params);
-							}
-						}
-					});
-			}
-		}else if ( OP_IMPORT_TEMPLATE.equals(opid)){
-						
-			final Shell shell = Utils.findAnyShell();
-			
-			shell.getDisplay().asyncExec(
-				new AERunnable() 
-				{
-					public void 
-					runSupport()
-					{
-						FileDialog dialog = 
-							new FileDialog( shell, SWT.SYSTEM_MODAL | SWT.OPEN );
-						
-						dialog.setFilterPath( TorrentOpener.getFilterPathData() );
-												
-						dialog.setText(MessageText.getString("metasearch.import.select.template.file"));
-						
-						dialog.setFilterExtensions(new String[] {
-								"*.vuze",
-								"*.vuz",
-								Constants.FILE_WILDCARD
-							});
-						dialog.setFilterNames(new String[] {
-								"*.vuze",
-								"*.vuz",
-								Constants.FILE_WILDCARD
-							});
-						
-						String path = TorrentOpener.setFilterPathData( dialog.open());
-	
-						if ( path != null ){
-							
-							VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
-							
-							VuzeFile vf = vfh.loadAndHandleVuzeFile( path, VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE );
-							
-							if ( vf == null ){
-								
-								Map params = new HashMap();
-								params.put( "error", "invalid .vuze file" );
-
-								sendBrowserMessage("metasearch", "importTemplateFailed",params);
-								
-							}else{
-								
-								VuzeFileComponent[] comps = vf.getComponents();
-								
-								for (int i=0;i<comps.length;i++){
-									
-									VuzeFileComponent comp = comps[i];
-									
-									if ( comp.getType() == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
-										
-										Engine engine = (Engine)comp.getData( Engine.VUZE_FILE_COMPONENT_ENGINE_KEY );
-										
-										if ( engine != null ){
-											
-											Map params = new HashMap();
-											params.put( "id", new Long( engine.getId()));
-											sendBrowserMessage( "metasearch", "importTemplateCompleted", params );
-
-											return;
-										}
-									}
-								}
-								
-								Map params = new HashMap();
-								params.put( "error", "invalid search template file" );
-
-								sendBrowserMessage("metasearch", "importTemplateFailed",params);
-							}
-						}else{
-							
-							Map params = new HashMap();
-								// don't change this message as the UI uses it!
-							params.put( "error", "operation cancelled" );
-
-							sendBrowserMessage("metasearch", "importTemplateFailed",params);
-						}
-					}
-				});
-		}else if ( OP_OPEN_SEARCH_RESULTS.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-			openCloseSearchDetailsListener.openSearchResults(decodedMap);
-		}else if ( OP_CLOSE_SEARCH_RESULTS.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-			openCloseSearchDetailsListener.closeSearchResults(decodedMap);
-		}else if(OP_LOAD_TORRENT.equals(opid)) {
-			Map decodedMap = message.getDecodedMap();
-			
-			String torrentUrl		= (String) decodedMap.get( "torrent_url" );
-			String referer_str	= (String) decodedMap.get( "referer_url" );
-			
-			if ( UrlFilter.getInstance().isWhitelisted( torrentUrl )){
-				
-				ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetworkForURL( torrentUrl );
-				
-				if ( cn == null ){
-					
-					cn = ConstantsVuze.getDefaultContentNetwork();
-				}
-				
-				torrentUrl = cn.appendURLSuffix( torrentUrl, false, true );
-			}
-			
-			try {
-			
-				Map headers = UrlUtils.getBrowserHeaders( referer_str );
-				
-				String subscriptionId		= ((String)decodedMap.get("subs_id"));
-				String subscriptionResultId = ((String)decodedMap.get("subs_rid"));
-				
-				if ( subscriptionId != null ){
-					
-					Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( subscriptionId );
-					
-					if ( subs != null ){
-					
-						try{
-							Engine engine = subs.getEngine();
-							
-							if ( engine != null && engine instanceof WebEngine ){
-								
-								WebEngine webEngine = (WebEngine) engine;
-								
-								if ( webEngine.isNeedsAuth()){
-									
-									headers.put( "Cookie",webEngine.getCookies());
-								}
-							}
-						}catch( Throwable e ){
-						
-							Debug.out( e );
-						}
-						
-						if ( subscriptionResultId != null ){ 
-						
-							subs.addPotentialAssociation( subscriptionResultId, torrentUrl );
-						}
-					}
-				}else{
-					try{
-						long engineID		= ((Long)decodedMap.get("engine_id")).longValue();
-
-						Engine engine = metaSearchManager.getMetaSearch().getEngine( engineID );
-						
-						if ( engine != null ){
-							
-							engine.addPotentialAssociation( torrentUrl );
-						}
-						
-						if ( engine != null && engine instanceof WebEngine ){
-							
-							WebEngine webEngine = (WebEngine) engine;
-							
-							if ( webEngine.isNeedsAuth()){
-								
-								headers.put( "Cookie",webEngine.getCookies());
-							}
-						}
-					}catch( Throwable e ){
-					
-						Debug.printStackTrace(e);
-					}
-				}
-				
-				Boolean	play_now = (Boolean)decodedMap.get( "play-now" );
-				
-				if ( play_now != null && play_now.booleanValue()){
-					
-					synchronized( MetaSearchListener.class ){
-						
-						pending_play_now_urls.add( torrentUrl );
-					}
-				}
-				
-				PluginInitializer.getDefaultInterface().getDownloadManager().addDownload(
-						new URL(torrentUrl), 
-						headers );
-				
-				Map params = new HashMap();
-				params.put("torrent_url",torrentUrl);
-				params.put("referer_url",referer_str);
-				sendBrowserMessage("metasearch", "loadTorrentCompleted",params);
-				
-			} catch(Exception e) {
-				Map params = new HashMap();
-				params.put("torrent_url",torrentUrl);
-				params.put("referer_url",referer_str);
-				params.put( "error", e.getMessage() );
-				sendBrowserMessage("metasearch", "loadTorrentFailed",params);
-			}
-				
-		}else if(OP_HAS_LOAD_TORRENT.equals(opid)) {
-			
-			Map params = new HashMap();
-			params.put("result","1");
-			sendBrowserMessage("metasearch", "hasLoadTorrent",params);
-			
-		}else if(OP_CREATE_SUBSCRIPTION.equals(opid)) {
-			
-			Map decodedMap = message.getDecodedMap();
-			
-			Long	 tid = (Long) decodedMap.get("tid");
-
-			String 		name 		= (String) decodedMap.get( "name" );
-			Boolean 	isPublic	= (Boolean) decodedMap.get( "is_public" );
-			Map			options		= (Map)decodedMap.get( "options" );
-			
-			Boolean 	isEnabled		= (Boolean)options.get( "is_enabled" );
-			Boolean 	autoDownload	= (Boolean)options.get( "auto_dl" );
-
-			Map result = new HashMap();
-
-			if ( tid != null )result.put( "tid", tid );
-
-			try{
-				JSONObject	payload = new JSONObject();
-				
-					// change this you need to change update too below
-				
-				payload.put( "engine_id", decodedMap.get( "engine_id" ));
-				payload.put( "search_term", decodedMap.get( "search_term" ));
-				payload.put( "filters", decodedMap.get( "filters" ));
-				payload.put( "schedule", decodedMap.get( "schedule" ));
-				payload.put( "options", decodedMap.get( "options" ));
-				
-				Subscription subs = SubscriptionManagerFactory.getSingleton().create(name, isPublic.booleanValue(), payload.toString());
-				
-				subs.getHistory().setDetails(
-					isEnabled==null?true:isEnabled.booleanValue(),
-					autoDownload==null?false:autoDownload.booleanValue());
-								
-				result.put( "id", subs.getID());
-				
-				sendBrowserMessage( "metasearch", "createSubscriptionCompleted", result );
-
-			} catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				result.put( "error", "create failed: " + Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage( "metasearch", "createSubscriptionFailed", result );
-			}
-		}else if( OP_READ_SUBSCRIPTION.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-			
-			final Long	 tid = (Long) decodedMap.get("tid");
-
-			final String sid = (String) decodedMap.get("id");
-			
-			Map result = new HashMap();
-
-			if ( tid != null )result.put( "tid", tid );
-
-			try{
-				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
-				
-				if ( subs == null ){
-					
-					result.put( "error", "Subscription not found" );
-
-					sendBrowserMessage("metasearch", "readSubscriptionFailed",result);
-					
-				}else{
-								
-					boolean	shareable = subs.isShareable();
-					
-						// override public flag if not shareable
-					
-					result.put( "id", subs.getID());
-					result.put( "name", subs.getName());
-					result.put( "is_public", new Boolean( shareable && subs.isPublic()));
-					result.put( "is_author", new Boolean( subs.isMine()));
-					result.put( "is_shareable", new Boolean( shareable ));
-					result.put( "auto_dl_supported", new Boolean( subs.isAutoDownloadSupported()));
-					
-					SubscriptionHistory history = subs.getHistory();
-					
-					Map	options = new HashMap();
-
-					result.put( "options", options );
-
-					options.put( "is_enabled", new Boolean( history.isEnabled()));
-					options.put( "auto_dl", new Boolean( history.isAutoDownload()));
-					
-					Map	info = new HashMap();
-
-					result.put( "info", info );
-					
-					info.put( "last_scan", new Long( history.getLastScanTime()));
-					info.put( "last_new", new Long( history.getLastNewResultTime()));
-					info.put( "num_unread", new Long( history.getNumUnread()));
-					info.put( "num_read", new Long( history.getNumRead()));
-					
-					String json = subs.getJSON();
-					
-					Map map = JSONUtils.decodeJSON( json );
-					
-					result.put( "engine_id", map.get( "engine_id" ));
-					result.put( "search_term", map.get( "search_term" ));
-					result.put( "filters", map.get( "filters" ));
-					result.put( "schedule", map.get( "schedule" ));
-					
-					sendBrowserMessage( "metasearch", "readSubscriptionCompleted", result );
-				}
-			} catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage("metasearch", "readSubscriptionFailed",result);
-			}
-		}else if (OP_UPDATE_SUBSCRIPTION.equals(opid)) {
-			
-			Map decodedMap = message.getDecodedMap();
-			
-			final Long	 tid = (Long) decodedMap.get("tid");
-			
-			final String 	name 		= (String)decodedMap.get("name");
-			final Boolean 	isPublic	= (Boolean)decodedMap.get( "is_public" );
-			final String 	sid 		= (String)decodedMap.get("id");
-			
-			Map			options		= (Map)decodedMap.get( "options" );
-			
-			Boolean 	isEnabled		= (Boolean)options.get( "is_enabled" );
-			Boolean 	autoDownload	= (Boolean)options.get( "auto_dl" );
-
-			Map result = new HashMap();
-
-			if ( tid != null )result.put( "tid", tid );
-
-			try{
-				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
-				
-				if ( subs == null ){
-					
-					result.put( "error", "Subscription not found" );
-
-					sendBrowserMessage("metasearch", "updateSubscriptionFailed",result);
-					
-				}else{
-					
-					JSONObject	payload = new JSONObject();
-					
-						// change this you need to change create too above
-				
-					payload.put( "engine_id", decodedMap.get( "engine_id" ));
-					payload.put( "search_term", decodedMap.get( "search_term" ));
-					payload.put( "filters", decodedMap.get( "filters" ));
-					payload.put( "schedule", decodedMap.get( "schedule" ));
-					payload.put( "options", decodedMap.get( "options" ));
-				
-					boolean	changed = subs.setDetails( name, isPublic.booleanValue(), payload.toString());
-					
-					subs.getHistory().setDetails(
-							isEnabled==null?true:isEnabled.booleanValue(),
-							autoDownload==null?false:autoDownload.booleanValue());
-
-					if ( changed ){
-						
-						subs.reset();
-						
-						try{
-							subs.getManager().getScheduler().downloadAsync(subs, true);
-							
-						}catch( Throwable e ){
-							
-							Debug.out(e);
-						}
-					}
-					
-					result.put( "id", subs.getID());
-					
-					sendBrowserMessage( "metasearch", "updateSubscriptionCompleted", result );
-				}
-			} catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				result.put( "error", "update failed: " + Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage("metasearch", "updateSubscriptionFailed",result);
-			}
-			
-		}else if (OP_SUBSCRIPTION_SET_AUTODL.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-			
-			String 	sid = (String)decodedMap.get("id");
-			
-			Long	tid = (Long) decodedMap.get("tid");
-
-			Boolean 	autoDownload	= (Boolean)decodedMap.get( "auto_dl" );
-
-			Map result = new HashMap();
-
-			if ( tid != null )result.put( "tid", tid );
-
-			try{
-				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
-				
-				if ( subs == null ){
-					
-					result.put( "error", "Subscription not found" );
-
-					sendBrowserMessage("metasearch", "setSubscriptionAutoDownloadFailed",result);
-					
-				}else{
-					
-					subs.getHistory().setAutoDownload( autoDownload.booleanValue());
-					
-					sendBrowserMessage( "metasearch", "setSubscriptionAutoDownloadCompleted", result );
-				}
-			} catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				result.put( "error", "update failed: " + Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage("metasearch", "setSubscriptionAutoDownloadFailed",result);
-			}
-			
-		}else if(OP_READ_SUBSCRIPTION_RESULTS.equals(opid)) {
-			
-			Map decodedMap = message.getDecodedMap();
-			
-			final Long	 tid = (Long) decodedMap.get("tid");
-			
-			final String sid = (String) decodedMap.get("id");
-			
-			final Map result = new HashMap();
-
-			if ( tid != null )result.put( "tid", tid );
-
-			try{
-				final Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
-				
-				if ( subs == null ){
-								
-					result.put( "error", "Subscription not found" );
-
-					sendBrowserMessage("metasearch", "readSubscriptionResultsFailed",result);
-					
-				}else{
-						
-					result.put( "id", subs.getID());
-										
-					if ( !handleSubscriptionAuth( subs, result )){
-					
-						if ( subs.getHistory().getLastScanTime() == 0 ){
-							
-							subs.getManager().getScheduler().download(
-									subs,
-									false,
-									new SubscriptionDownloadListener()
-									{
-										public void
-										complete(
-											Subscription		subs )
-										{
-											if ( !handleSubscriptionAuth( subs, result )){
-												
-												encodeResults( subs, result );
-											
-												sendBrowserMessage( "metasearch", "readSubscriptionResultsCompleted", result );
-												
-												openCloseSearchDetailsListener.resizeMainBrowser();
-												
-											}
-										}
-										
-										public void
-										failed(
-											Subscription			subs,
-											SubscriptionException	error )
-										{
-											Debug.out( error );
-											
-											result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(error));
-	
-											sendBrowserMessage( "metasearch", "readSubscriptionResultsFailed", result );
-	
-										}
-									});
-						}else{
-													
-							encodeResults( subs, result );
-							
-							sendBrowserMessage( "metasearch", "readSubscriptionResultsCompleted", result );
-					
-							openCloseSearchDetailsListener.resizeMainBrowser();
-						}
-					}
-				}
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage("metasearch", "readSubscriptionFailed",result);
-			}
-		}else if( OP_DELETE_SUBSCRIPTION_RESULTS.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-						
-			String sid = (String)decodedMap.get("id");
-			
-			List	rids	= (List)decodedMap.get( "rids" );
-			
-			try{
-				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
-				
-				if ( subs == null ){
-					
-					Map params = new HashMap();
-					
-					params.put( "error", "Subscription not found" );
-
-					sendBrowserMessage("metasearch", "deleteSubscriptionResultsFailed",params);
-					
-				}else{
-					
-					String[]	rids_a = (String[])rids.toArray( new String[rids.size()]);
-					
-					subs.getHistory().deleteResults( rids_a );
-					
-					Map result = new HashMap();
-					
-					result.put( "rids", rids);
-					
-					sendBrowserMessage( "metasearch", "deleteSubscriptionResultsCompleted", result );
-				}
-			} catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				Map params = new HashMap();
-
-				params.put( "error", "delete failed: " + Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage("metasearch", "deleteSubscriptionResultsFailed",params);
-			}
-		}else if( OP_MARK_SUBSCRIPTION_RESULTS.equals(opid)){
-			
-			Map decodedMap = message.getDecodedMap();
-						
-			String sid = (String)decodedMap.get("id");
-			
-			List	rids	= (List)decodedMap.get( "rids" );
-			List	reads	= (List)decodedMap.get( "reads" );
-			
-			Map result = new HashMap();		
-
-			try{
-				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
-				
-				if ( subs == null ){
-					
-					result.put( "error", "Subscription not found" );
-
-					sendBrowserMessage("metasearch", "markSubscriptionResultsFailed",result);
-					
-				}else{
-					
-					String[]	rids_a = (String[])rids.toArray( new String[rids.size()]);
-					
-					boolean[]	reads_a = new boolean[reads.size()];
-					
-					for (int i=0;i<reads.size();i++){
-						
-						reads_a[i] = ((Boolean)reads.get(i)).booleanValue();
-					}
-					
-					subs.getHistory().markResults( rids_a, reads_a );
-					
-					result.put( "rids", rids);
-					result.put( "reads", reads);
-										
-					sendBrowserMessage( "metasearch", "markSubscriptionResultsCompleted", result );
-				}
-			} catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				result.put( "error", "mark failed: " + Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage("metasearch", "markSubscriptionResultsFailed",result);
-			}
-		}else if( OP_DOWNLOAD_SUBSCRIPTION.equals(opid)) {
-			
-			Map decodedMap = message.getDecodedMap();
-			
-			final Long	 tid = (Long) decodedMap.get("tid");
-
-			final String sid = (String) decodedMap.get("id");
-			
-			final Map result = new HashMap();
-
-			if ( tid != null )result.put( "tid", tid );
-
-			try{
-				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
-				
-				if ( subs == null ){
-					
-					result.put( "error", "Subscription not found" );
-
-					sendBrowserMessage("metasearch", "downloadSubscriptionFailed", result );
-					
-				}else{
-					
-					result.put( "id", subs.getID());
-					
-					if ( !handleSubscriptionAuth( subs, result )){
-
-						subs.getManager().getScheduler().download(
-							subs,
-							false,
-							new SubscriptionDownloadListener()
-							{
-								public void
-								complete(
-									Subscription		subs )
-								{
-									if ( !handleSubscriptionAuth( subs, result )){
-
-										encodeResults( subs, result );
-									
-										sendBrowserMessage( "metasearch", "downloadSubscriptionCompleted", result );
-									}
-								}
-								
-								public void
-								failed(
-									Subscription			subs,
-									SubscriptionException	error )
-								{
-									Debug.out( error );
-									
-									result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(error));
-	
-									sendBrowserMessage( "metasearch", "downloadSubscriptionFailed", result );
-	
-								}
-							});
-					}
-				}
-			} catch( Throwable e ){
-				
-				Debug.out( e );
-				
-				result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(e));
-
-				sendBrowserMessage( "metasearch", "downloadSubscriptionFailed", result );
-			}
-		}else if( OP_IS_CUSTOMISED.equals(opid)) {
-			
-			boolean custom = CustomizationManagerFactory.getSingleton().getActiveCustomization() != null;
-			
-			Map params = new HashMap();
-			
-			params.put( "is_custom", new Boolean( custom ));
-
-			sendBrowserMessage( "metasearch", "isCustomizedResult", params );
-		}else if( OP_ADD_EXTERNAL_LINKS.equals(opid)) {
-			Map decodedMap = message.getDecodedMap();
-
-			List list = MapUtils.getMapList(decodedMap, "external-links", Collections.EMPTY_LIST);
-			for (Object o : list) {
-				if (o instanceof String) {
-					String link = (String) o;
-					PlatformConfigMessenger.addLinkExternal(link);
-				}
-			}
-		}
-	}
-	
-	protected boolean
-	handleSubscriptionAuth(
-		final Subscription		subs,
-		final Map				result )
-	{
-		if ( subs.getHistory().isAuthFail()){
-			
-			try{
-				Engine engine = subs.getEngine();
-				
-				if ( engine instanceof WebEngine ){
-				
-					final WebEngine webEngine = (WebEngine)engine;
-				
-					synchronized( active_subs_auth ){
-						
-						if ( active_subs_auth.contains( subs )){
-							
-							return( false );
-						}
-						
-						active_subs_auth.add( subs );
-					}
-					
-					Utils.execSWTThread( new Runnable() {
-						public void run() {
-							new ExternalLoginWindow(
-								new ExternalLoginListener() 
-								{
-									private String previous_cookies;
-									
-									private boolean	result_sent;
-									
-									public void 
-									canceled(
-										ExternalLoginWindow 	window ) 
-									{
-										try{
-											encodeResults( subs, result );
-											
-											sendBrowserMessage( "metasearch", "readSubscriptionResultsCompleted", result );
-											
-										}finally{
-											
-											completed();
-										}
-									}
-		
-									public void 
-									cookiesFound(
-										ExternalLoginWindow 	window,
-										String 					cookies ) 
-									{
-										if ( handleCookies( cookies, false )){
-											
-											window.close();									
-										}
-									}
-		
-									public void 
-									done(
-										ExternalLoginWindow 	window,
-										String 					cookies )
-									{
-										try{
-											if ( !handleCookies( cookies, true )){
-												
-												encodeResults( subs, result );
-												
-												sendBrowserMessage( "metasearch", "readSubscriptionResultsCompleted", result );
-											}
-										}finally{
-											
-											completed();
-										}
-									}
-									
-									private void
-									completed()
-									{
-										synchronized( active_subs_auth ){
-
-											active_subs_auth.remove( subs );
-										}
-									}
-									
-									private boolean
-									handleCookies(
-										String		cookies,
-										boolean		force_if_ready )
-									{
-										if ( result_sent ){
-											
-											return( false );
-										}
-										
-										String[] required = webEngine.getRequiredCookies();
-										
-										boolean	skip = required.length == 0 && !force_if_ready;
-										
-										if ( CookieParser.cookiesContain( required, cookies )){
-												
-											webEngine.setCookies(cookies);
-											
-											if ( previous_cookies == null || !previous_cookies.equals( cookies )){
-												
-												previous_cookies = cookies;
-												
-												if ( !skip ){
-													
-														// search operation will report outcome
-													
-													result_sent	= true;
-													
-													try{
-														subs.getManager().getScheduler().download(
-															subs,
-															false,
-															new SubscriptionDownloadListener()
-															{
-																public void
-																complete(
-																	Subscription		subs )
-																{
-																	result.put( "id", subs.getID());
-																	
-																	encodeResults( subs, result );
-																	
-																	sendBrowserMessage( "metasearch", "readSubscriptionResultsCompleted", result );
-																}
-																
-																public void
-																failed(
-																	Subscription			subs,
-																	SubscriptionException	error )
-																{
-																	Debug.out( error );
-																	
-																	result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(error));
-	
-																	sendBrowserMessage( "metasearch", "readSubscriptionResultsFailed", result );
-																}
-															});		
-													}catch( Throwable error ){
-														
-														Debug.out( error );
-														
-														result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(error));
-	
-														sendBrowserMessage( "metasearch", "readSubscriptionResultsFailed", result );
-													}
-												}
-											}
-										}
-		
-										return( result_sent );
-									}
-								},
-							webEngine.getName(),
-							webEngine.getLoginPageUrl(),
-							false,
-							webEngine.getAuthMethod(),
-							subs.isMine());
-						}
-					});
-					
-					return( true );
-					
-				}else{
-					
-					return( false );
-				}
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-				
-				return( false );
-			}
-		}else{
-			
-			return( false );
-		}
-	}
-	
-	protected void
-	search(
-		Map		decodedMap,
-		Engine	target )
-	{
-		String searchText = (String) decodedMap.get("searchText");
-		
-		String headers = (String)decodedMap.get( "headers" );
-		
-		final Long	sid = (Long)decodedMap.get( "sid" );
-
-		Boolean	mature = (Boolean)decodedMap.get( "mature" );
-		
-		Long	l_max_per_engine = (Long)decodedMap.get( "maxResultsPerEngine" );
-
-		int	max_per_engine = l_max_per_engine==null?100:l_max_per_engine.intValue();
-		
-		if ( max_per_engine < 1 ){
-			
-			max_per_engine = 1;
-		}
-		
-		if ( target == null ){
-		
-				// override engine selection for subscriptions
-			
-			String subscriptionId		= ((String)decodedMap.get("subs_id"));
-			
-			if ( subscriptionId != null ){
-				
-				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( subscriptionId );
-				
-				if ( subs != null ){
-				
-					try{
-						Engine engine = subs.getEngine();
-						
-						if ( engine != null ){
-							
-							target = engine;
-						}
-					}catch( Throwable e ){
-					
-						Debug.out( e );
-					}
-				}
-			}
-		}
-		
-		ResultListener listener = new ResultListener() {
-			
-			public void 
-			contentReceived(
-				Engine engine, 
-				String content ) 
-			{
-			}
-			
-			public void 
-			matchFound(
-				Engine 		engine, 
-				String[] 	fields ) 
-			{
-			}
-			
-			public void engineFailed(Engine engine, Throwable e) {
-				
-				Debug.out( e );
-				
-				Map params = getParams( engine );
-				
-				params.put( "error", Debug.getNestedExceptionMessage( e ));
-				
-				sendBrowserMessage("metasearch", "engineFailed", params );
-			}
-			
-			public void engineRequiresLogin(Engine engine, Throwable e) {
-				Map params = getParams( engine );
-				
-				params.put( "error", Debug.getNestedExceptionMessage( e ));
-				
-				sendBrowserMessage("metasearch", "engineRequiresLogin", params );
-			}
-			
-			public void resultsComplete(Engine engine) {
-			
-				sendBrowserMessage("metasearch", "engineCompleted", getParams( engine ));
-			}
-			
-			public void resultsReceived(Engine engine,Result[] results) {
-				Map params = getParams(engine);
-				List resultsList = new ArrayList(results.length);
-				for(int i = 0 ; i < results.length ; i++) {
-					Result result = results[i];
-					resultsList.add(result.toJSONMap());
-				}
-				params.put("results", resultsList);
-				sendBrowserMessage("metasearch", "resultsReceived",params);
-			}
-			
-			protected Map
-			getParams(
-				Engine	engine )
-			{
-				Map params = new HashMap();
-				params.put("id", new Long(engine.getId()));
-				params.put("name", engine.getName());
-				params.put("favicon", engine.getIcon());
-				params.put("dl_link_css", engine.getDownloadLinkCSS());
-				params.put("shareable", new Boolean( engine.isShareable()));
-				
-				if ( sid != null ){
-					params.put( "sid", sid );
-				}
-				return( params );
-			}
-		};
-		
-		List	sps = new ArrayList();
-					
-		sps.add( new SearchParameter( "s", searchText ));
-		
-		if ( mature != null ){
-			
-			sps.add( new SearchParameter( "m", mature.toString()));
-		}
-		
-		SearchParameter[] parameters = (SearchParameter[])sps.toArray(new SearchParameter[ sps.size()] );
-		
-		MetaSearchManager metaSearchManager = MetaSearchManagerFactory.getSingleton();
-
-		Map<String,String>	context = new HashMap<String, String>();
-		
-		context.put( Engine.SC_FORCE_FULL, "true" );
-		
-		context.put( Engine.SC_BATCH_PERIOD, "1000" );
-		
-		context.put( Engine.SC_REMOVE_DUP_HASH, "true" );
-		
-		if ( target == null ){
-		
-			metaSearchManager.getMetaSearch().search( listener, parameters, headers, context, max_per_engine );
-			
-		}else{
-			
-			metaSearchManager.getMetaSearch().search( new Engine[]{ target }, listener, parameters, headers, context, max_per_engine );
-
-		}
-	}
-	
-	protected void
-	encodeResults(
-		Subscription	subs,
-		Map				result )
-	{
-		JSONArray	results_list = new JSONArray();
-		
-		SubscriptionResult[]	results = subs.getHistory().getResults( false );
-		
-		for(int i=0; i<results.length; i++){
-			
-			SubscriptionResult r = results[i];
-			
-			results_list.add( r.toJSONMap());
-		}
-		
-		result.put( "results", results_list );
-		
-		
-	}
-	
-	protected Engine
-	getEngineFromId(
-			long id )
-	{
-		MetaSearchManager metaSearchManager = MetaSearchManagerFactory.getSingleton();
-		
-		Engine[] engines = metaSearchManager.getMetaSearch().getEngines( false, true );
-		for(int i = 0 ; i < engines.length ; i++) {
-			Engine engine = engines[i];
-			if(engine.getId() == id) {
-				return engine;
-			}	
-		}
-		return null;
-	}
-	
-	public boolean 
-	sendBrowserMessage(
-		String 		key, 
-		String 		op, 
-		Map 		params )
-	{
-		MetaSearchManagerFactory.getSingleton().log( "BrowserListener: sent " + op + ": " + params );
-
-		return( context.sendBrowserMessage(key, op, params));
-	}
-	
-	public boolean 
-	sendBrowserMessage(
-		String 			key, 
-		String 			op, 
-		Collection 		params )
-	{
-		MetaSearchManagerFactory.getSingleton().log( "BrowserListener: sent " + op + ": " + params );
-
-		return( context.sendBrowserMessage(key, op, params));
-	}
-
-}
+/*
+ * Created on May 6, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.browser.listener;
+
+import java.io.File;
+import java.net.URL;
+import java.util.*;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Shell;
+
+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.global.GlobalManagerListener;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.torrent.TOTorrent;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+
+import com.aelitis.azureus.core.AzureusCore;
+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.custom.CustomizationManagerFactory;
+import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
+import com.aelitis.azureus.core.messenger.browser.listeners.AbstractBrowserMessageListener;
+import com.aelitis.azureus.core.messenger.config.PlatformConfigMessenger;
+import com.aelitis.azureus.core.metasearch.*;
+import com.aelitis.azureus.core.metasearch.impl.web.CookieParser;
+import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
+import com.aelitis.azureus.core.subs.Subscription;
+import com.aelitis.azureus.core.subs.SubscriptionDownloadListener;
+import com.aelitis.azureus.core.subs.SubscriptionException;
+import com.aelitis.azureus.core.subs.SubscriptionHistory;
+import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
+import com.aelitis.azureus.core.subs.SubscriptionResult;
+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.swt.browser.OpenCloseSearchDetailsListener;
+import com.aelitis.azureus.ui.swt.views.skin.TorrentListViewsUtils;
+import com.aelitis.azureus.util.*;
+
+public class MetaSearchListener extends AbstractBrowserMessageListener {
+	
+	public static final String LISTENER_ID = "metasearch";
+
+	public static final String OP_SEARCH				= "search";
+		
+	public static final String OP_GET_ENGINES 			= "get-engines";
+	public static final String OP_GET_ALL_ENGINES 		= "get-all-engines";
+	public static final String OP_ENGINE_PREFERRED		= "engine-preferred";
+
+	public static final String OP_CHANGE_ENGINE_SELECTION 	= "change-engine-selection";
+	
+	public static final String OP_SET_SELECTED_ENGINES 	= "set-selected-engines";
+
+	public static final String OP_GET_AUTO_MODE		 	= "get-auto-mode";
+	
+	public static final String OP_SAVE_TEMPLATE		 	= "save-template";
+	public static final String OP_LOAD_TEMPLATE		 	= "load-template";
+	public static final String OP_DELETE_TEMPLATE		= "delete-template";
+	public static final String OP_TEST_TEMPLATE			= "test-template";
+	
+	public static final String OP_EXPORT_TEMPLATE		= "export-template";
+	public static final String OP_IMPORT_TEMPLATE		= "import-template";
+	
+	public static final String OP_OPEN_SEARCH_RESULTS	= "open-search-results";
+	public static final String OP_CLOSE_SEARCH_RESULTS	= "close-search-results";
+	
+	public static final String OP_LOAD_TORRENT			= "load-torrent";
+	public static final String OP_HAS_LOAD_TORRENT		= "has-load-torrent";
+	
+	public static final String OP_ENGINE_LOGIN			= "engine-login";
+	public static final String OP_GET_LOGIN_COOKIES		= "get-login-cookies";
+	
+	public static final String OP_CREATE_SUBSCRIPTION   		= "create-subscription";
+	public static final String OP_READ_SUBSCRIPTION   			= "read-subscription";
+	public static final String OP_UPDATE_SUBSCRIPTION   		= "update-subscription";
+	public static final String OP_READ_SUBSCRIPTION_RESULTS   	= "read-subscription-results";
+	public static final String OP_DELETE_SUBSCRIPTION_RESULTS   = "delete-subscription-results";
+	public static final String OP_MARK_SUBSCRIPTION_RESULTS	   	= "mark-subscription-results";
+	public static final String OP_DOWNLOAD_SUBSCRIPTION   		= "download-subscription";
+	public static final String OP_SUBSCRIPTION_SET_AUTODL   	= "subscription-set-auto-download";
+
+	public static final String OP_IS_CUSTOMISED   				= "is-customized";
+
+	public static final String OP_ADD_EXTERNAL_LINKS   				= "add-external-links";
+
+	private static final Set	active_subs_auth = new HashSet();
+	
+	private static final Set	pending_play_now_urls = new HashSet();
+	
+	static{
+		TorrentUtils.addTorrentAttributeListener(
+			new TorrentUtils.torrentAttributeListener()
+			{
+				public void 
+				attributeSet(
+					TOTorrent 	torrent,
+					String 		attribute, 
+					Object 		value )
+				{
+					if ( attribute == TorrentUtils.TORRENT_AZ_PROP_OBTAINED_FROM ){
+						
+						try{
+							String torrent_url = (String)value;
+							
+							boolean hook_dm = false;
+							
+							synchronized(pending_play_now_urls ){
+								
+								if ( pending_play_now_urls.remove( torrent_url )){
+									
+										// ok, we now have the torrent associated with the URL
+																		
+									hook_dm = true;
+								}
+							}
+							
+							if ( !hook_dm ) {
+								return;
+							}
+							
+							if (!AzureusCoreFactory.isCoreRunning()) {
+								// shouldn't happen, but..
+								Debug.out("Core wasn't available for pending play now" );
+								
+							} else {
+								
+								final HashWrapper hash = torrent.getHashWrapper();
+								
+								AzureusCore core = AzureusCoreFactory.getSingleton();
+								
+								final GlobalManager gm = core.getGlobalManager();
+					
+								DownloadManager existing = gm.getDownloadManager( hash );
+								
+								if ( existing != null) {
+
+									playOrStream( existing );
+	
+									return;
+								}
+	
+								GlobalManagerListener l = 
+									new GlobalManagerAdapter() 
+									{
+										private final long listener_add_time = SystemTime.getMonotonousTime();
+										
+										public void 
+										downloadManagerAdded(
+											DownloadManager dm )
+										{
+											try{	
+												TOTorrent t = dm.getTorrent();
+												
+												if ( t.getHashWrapper().equals( hash )){
+													
+													gm.removeListener( this );
+													
+													playOrStream( dm );
+												}
+											
+											}catch( Throwable e ){
+												
+												Debug.out( e );
+												
+											}finally{
+												
+												if ( SystemTime.getMonotonousTime() - listener_add_time > 5*60*1000 ){
+													
+													gm.removeListener( this );
+												}
+											}
+										}
+									};
+									
+								gm.addListener( l, false );
+							}
+						}catch( Throwable e ){
+							
+							Debug.printStackTrace(e);
+						}
+					}
+				}				
+			});
+	}
+	
+	private static void
+	playOrStream(
+		final DownloadManager		download )
+	{
+		new AEThread2( "MSL:POS", true )
+		{
+			public void
+			run()
+			{
+				TorrentListViewsUtils.playOrStream( download, -1 );
+			}
+		}.start();
+	}
+	
+	private final OpenCloseSearchDetailsListener openCloseSearchDetailsListener;
+	
+	
+	public 
+	MetaSearchListener(
+		OpenCloseSearchDetailsListener openCloseSearchDetailsListener )
+	{
+		super(LISTENER_ID);
+		
+		this.openCloseSearchDetailsListener = openCloseSearchDetailsListener;
+	}
+	
+	public void handleMessage(BrowserMessage message) {
+		
+		String opid = message.getOperationId();
+
+		MetaSearchManager metaSearchManager = MetaSearchManagerFactory.getSingleton();
+		
+		metaSearchManager.log( "BrowserListener: received " + message );
+		
+		if (OP_SEARCH.equals(opid)) {
+			
+			Map decodedMap = message.getDecodedMap();
+			
+
+			search( decodedMap, null );
+
+		}else if ( OP_ENGINE_PREFERRED.equals( opid )){
+			
+			final Map decodedMap = message.getDecodedMap();
+			
+			long engine_id = ((Long)decodedMap.get("engine_id")).longValue();
+
+			Engine engine = getEngineFromId( engine_id );
+
+			if ( engine != null ){
+				
+				metaSearchManager.getMetaSearch().enginePreferred( engine );
+			}
+
+		} else if(OP_ENGINE_LOGIN.equals(opid)) {
+			
+			final Map decodedMap = message.getDecodedMap();
+			
+			long engine_id = ((Long)decodedMap.get("engine_id")).longValue();
+			
+			final Long	sid = (Long)decodedMap.get( "sid" );
+
+			final Engine engine = getEngineFromId(engine_id);
+			
+			if ( engine != null && engine instanceof WebEngine){
+				
+				final WebEngine webEngine = (WebEngine) engine;
+
+				Utils.execSWTThread( new Runnable() {
+					public void run() {
+						new ExternalLoginWindow(
+							new ExternalLoginListener() 
+							{
+								private String previous_cookies;
+								
+								private boolean	search_done;
+								
+								public void 
+								canceled(
+									ExternalLoginWindow 	window ) 
+								{
+									/* gouss doesn't wan't anything on cancel
+									if ( !outcome_informed ){
+										
+										outcome_informed = true;
+										
+										Map params = getParams( webEngine );
+										
+										params.put( "error", "operation cancelled" );
+										
+										sendBrowserMessage("metasearch", "engineFailed", params );
+									}
+									*/
+								}
+	
+								public void 
+								cookiesFound(
+									ExternalLoginWindow 	window,
+									String 					cookies ) 
+								{
+									if ( handleCookies( cookies, false )){
+										
+										window.close();									
+									}
+								}
+	
+								public void 
+								done(
+									ExternalLoginWindow 	window,
+									String 					cookies )
+								{
+									handleCookies( cookies, true );
+									
+									/*
+									if ( !outcome_informed ){
+										
+										outcome_informed = true;
+										
+										Map params = getParams( webEngine );
+																				
+										sendBrowserMessage("metasearch", "engineCompleted", params );
+									}
+									*/
+								}
+								
+								private boolean
+								handleCookies(
+									String		cookies,
+									boolean		force_if_ready )
+								{
+									if ( search_done ){
+										
+										return( false );
+									}
+									
+									String[] required = webEngine.getRequiredCookies();
+									
+									boolean	skip_search = required.length == 0 && !force_if_ready;
+									
+									if ( CookieParser.cookiesContain( required, cookies )){
+											
+										webEngine.setCookies(cookies);
+										
+										if ( previous_cookies == null || !previous_cookies.equals( cookies )){
+											
+											previous_cookies = cookies;
+											
+											if ( !skip_search ){
+												
+													// search operation will report outcome
+												
+												search_done	= true;
+												
+												search( decodedMap, webEngine );
+											}
+										}
+									}
+	
+									return( search_done );
+								}
+								
+								/*
+								protected Map
+								getParams(
+									Engine	engine )
+								{
+									Map params = new HashMap();
+									params.put("id", new Long(engine.getId()));
+									params.put("name", engine.getName());
+									params.put("favicon", engine.getIcon());
+									params.put("dl_link_css", engine.getDownloadLinkCSS());
+									params.put("shareable", new Boolean( engine.isShareable()));
+									
+									if ( sid != null ){
+										params.put( "sid", sid );
+									}
+									return( params );
+								}
+								*/
+							},
+						webEngine.getName(),
+						webEngine.getLoginPageUrl(),
+						false,
+						webEngine.getAuthMethod(),
+						engine.isMine());
+					}
+				});
+			}else{
+				
+				Map params = new HashMap();
+				
+				if ( sid != null ){
+					params.put( "sid", sid );
+				}
+				params.put( "error", "engine not found or not a web engine" );
+				
+				sendBrowserMessage("metasearch", "engineFailed", params );
+			}
+		} else if(OP_GET_LOGIN_COOKIES.equals(opid)) {
+			
+			final Map decodedMap = message.getDecodedMap();
+			
+			final String url = ((String) decodedMap.get("url")).replaceAll("%s", "");
+			
+			Utils.execSWTThread( new Runnable() {
+				public void run() {
+					new ExternalLoginWindow(
+						new ExternalLoginListener() 
+						{	
+						public void canceled(ExternalLoginWindow window) {
+							sendBrowserMessage("metasearch", "setCookiesFailed", new HashMap() );
+						};
+						public void cookiesFound(ExternalLoginWindow window, String cookies) {};
+						public void done(ExternalLoginWindow window, String cookies) {
+							String[] cookieNames = CookieParser.getCookiesNames(cookies);
+							Map params = new HashMap();
+							params.put("cookieNames", cookieNames);
+							params.put("currentCookie",cookies);
+							params.put("cookieMethod", window.proxyCaptureModeRequired()?WebEngine.AM_PROXY:WebEngine.AM_TRANSPARENT );
+							sendBrowserMessage("metasearch", "setCookies", params );
+						};
+						}, 
+						url, 
+						url,
+						true,
+						WebEngine.AM_PROXY,
+						true );
+				}
+			});
+			
+			
+		} else if(OP_GET_ENGINES.equals(opid)) {
+			String subscriptionId  = null;
+			
+			try {
+				final Map decodedMap = message.getDecodedMap();
+
+				subscriptionId		= ((String)decodedMap.get("subs_id"));
+			} catch(Exception e) {
+				//No parameters
+			}
+			
+			Engine[] engines = null;
+			
+			if ( subscriptionId != null ){
+				
+				engines = new Engine[0];
+				
+				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( subscriptionId );
+				
+				if ( subs != null ){
+				
+					try{
+						Engine engine = subs.getEngine();
+						
+						if ( engine != null ){
+							
+							engines = new Engine[]{ engine };
+						}
+					}catch( Throwable e ){
+					
+						Debug.out( e );
+					}
+				}
+			}
+			
+			if ( engines == null ){
+				
+				engines = metaSearchManager.getMetaSearch().getEngines( true, true );
+			}
+			
+			List params = new ArrayList();
+			for(int i = 0 ; i < engines.length ; i++) {
+				Engine engine = engines[i];
+				
+				if ( !engine.isActive() || engine.getSource() == Engine.ENGINE_SOURCE_UNKNOWN ){
+					
+						// don't skip if this is an explicit get
+					
+					if ( subscriptionId == null ){
+					
+						continue;
+					}
+				}
+				Map engineMap = new HashMap();
+				engineMap.put("id", new Long(engine.getId()));
+				engineMap.put("name", engine.getName());
+				engineMap.put("favicon", engine.getIcon());
+				engineMap.put("dl_link_css", engine.getDownloadLinkCSS());
+				engineMap.put("selected", Engine.SEL_STATE_STRINGS[ engine.getSelectionState()]);
+				engineMap.put("type", Engine.ENGINE_SOURCE_STRS[ engine.getSource()]);
+				engineMap.put("shareable", new Boolean( engine.isShareable()));
+				params.add(engineMap);
+			}
+			sendBrowserMessage("metasearch", "enginesUsed",params);
+			
+		} else if(OP_GET_ALL_ENGINES.equals(opid)) {
+
+			Engine[] engines = metaSearchManager.getMetaSearch().getEngines( false, true );
+			List params = new ArrayList();
+			for(int i = 0 ; i < engines.length ; i++) {
+				Engine engine = engines[i];
+				
+				if ( engine.getSource() == Engine.ENGINE_SOURCE_UNKNOWN ){
+					continue;
+				}
+				
+				Map engineMap = new HashMap();
+				engineMap.put("id", new Long(engine.getId()));
+				engineMap.put("name", engine.getName());
+				engineMap.put("favicon", engine.getIcon());
+				engineMap.put("dl_link_css", engine.getDownloadLinkCSS());
+				engineMap.put("selected", Engine.SEL_STATE_STRINGS[ engine.getSelectionState()]);
+				engineMap.put("type", Engine.ENGINE_SOURCE_STRS[ engine.getSource()]);
+				engineMap.put("shareable", new Boolean( engine.isShareable()));
+				params.add(engineMap);
+			}
+			sendBrowserMessage("metasearch", "engineList",params);
+			
+		} else if( OP_SET_SELECTED_ENGINES.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+
+			List template_ids = (List)decodedMap.get( "template_ids" );
+			
+			long[] ids = new long[template_ids.size()];
+			
+			for (int i=0;i<ids.length;i++ ){
+				
+				Map m = (Map)template_ids.get(i);
+				
+				ids[i] = ((Long)m.get("id")).longValue();
+			}
+			
+			boolean	auto = ((Boolean)decodedMap.get( "auto" )).booleanValue();
+			
+				// there's some code that attempts to switch to 'auto=true' on first use as
+				// when 3110 defaults to false and the decision was made to switch this
+				// disable the behaviour if we are customised
+			
+			
+			Boolean	is_default = (Boolean)decodedMap.get( "set_default" );
+			
+			boolean skip = false;
+			
+			if ( is_default != null && is_default.booleanValue()){
+				
+				if ( CustomizationManagerFactory.getSingleton().getActiveCustomization() != null ){
+					
+					skip = true;
+				}
+			}
+			
+			try{
+				if ( !skip ){
+					
+					metaSearchManager.setSelectedEngines( ids, auto );
+				}
+				
+				Map params = new HashMap();
+				sendBrowserMessage("metasearch", "setSelectedCompleted",params);
+
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				Map params = new HashMap();
+				params.put("error",Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage("metasearch", "setSelectedFailed",params);
+			}
+		} else if( OP_CHANGE_ENGINE_SELECTION.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+
+			MetaSearch ms = metaSearchManager.getMetaSearch();
+			
+			Engine[] engines = ms.getEngines( false, true );
+			
+			Set selected = new HashSet();
+			
+			for (int i=0;i<engines.length;i++){
+				
+				Engine e = engines[i];
+				
+				if ( e.getSelectionState() == Engine.SEL_STATE_MANUAL_SELECTED ){
+					
+					selected.add( new Long( e.getId()));
+				}
+			}
+			
+			List l_engines = (List)decodedMap.get( "engines" );
+			
+			for (int i=0;i<l_engines.size();i++){
+				
+				Map	map = (Map)l_engines.get(i);
+				
+				long id = ((Long)map.get("id")).longValue();
+
+				String str = (String)map.get( "selected");
+				
+				if ( str.equalsIgnoreCase( Engine.SEL_STATE_STRINGS[Engine.SEL_STATE_MANUAL_SELECTED])){
+					
+					selected.add( new Long( id ));
+					
+				}else if ( str.equalsIgnoreCase( Engine.SEL_STATE_STRINGS[Engine.SEL_STATE_DESELECTED])){
+					
+					selected.remove( new Long( id ));
+				}
+			}
+			
+			long[] ids = new long[selected.size()];
+			
+			Iterator it = selected.iterator();
+			
+			int	pos = 0;
+			
+			while( it.hasNext()){
+				
+				long	 id = ((Long)it.next()).longValue();
+				
+				ids[pos++] = id;
+			}
+						
+			try{
+				metaSearchManager.setSelectedEngines( ids, metaSearchManager.isAutoMode());
+				
+				Map params = new HashMap();
+				sendBrowserMessage("metasearch", "changeEngineSelectionCompleted",params);
+
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				Map params = new HashMap();
+				params.put("error",Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage("metasearch", "changeEngineSelectionFailed",params);
+			}	
+		} else if(OP_GET_AUTO_MODE.equals(opid)) {
+						
+			boolean mode = metaSearchManager.isAutoMode();
+			
+			Map params = new HashMap();
+			
+			params.put( "auto", new Boolean( mode ));
+
+			boolean custom = CustomizationManagerFactory.getSingleton().getActiveCustomization() != null;
+						
+			params.put( "is_custom", new Boolean( custom ));
+
+			sendBrowserMessage("metasearch", "getAutoModeResult",params);
+			
+		} else if( OP_SAVE_TEMPLATE.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+
+			String	type_str = (String)decodedMap.get( "type" );
+			
+			String	name = (String)decodedMap.get( "name" );
+			
+			Long	l_id	= (Long)decodedMap.get( "id" );
+			
+			long	id = l_id == null?-1:l_id.longValue();
+			
+			String	json = (String)decodedMap.get( "value" );
+			
+			String	cookies = (String)decodedMap.get( "current_cookie" );
+			
+			
+			try{
+				Engine engine = 
+					metaSearchManager.addEngine( 
+							id, 
+							type_str.equals( "json" )?Engine.ENGINE_TYPE_JSON:Engine.ENGINE_TYPE_REGEX, 
+							name, 
+							json );
+				
+				engine.setMine( true );
+				
+				if(cookies!= null && engine instanceof WebEngine) {
+					WebEngine we = (WebEngine) engine;
+					we.setCookies(cookies);
+				}
+				
+				Map params = new HashMap();
+				params.put( "id", new Long( engine.getId() ));
+	
+				sendBrowserMessage( "metasearch", "saveTemplateCompleted", params );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				Map params = new HashMap();
+				params.put( "id", new Long( id ));
+				params.put("error",Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage("metasearch", "saveTemplateFailed",params);
+			}
+		} else if( OP_LOAD_TEMPLATE.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+
+			long	id	= ((Long)decodedMap.get( "id" )).longValue();
+			
+			Engine engine = metaSearchManager.getMetaSearch().getEngine( id );
+		
+			if ( engine == null ){
+			
+				Map params = new HashMap();
+				params.put( "id", new Long( id ));
+				params.put("error","Template not found");
+
+				sendBrowserMessage("metasearch", "loadTemplateFailed",params);
+				
+			}else{
+				
+				try{
+					Map params = new HashMap();
+					params.put("id", new Long(engine.getId()));
+					params.put("name", engine.getName());
+					params.put("type", Engine.ENGINE_TYPE_STRS[ engine.getType()]);
+					params.put("value", JSONObject.escape( engine.exportToJSONString()));
+					params.put("shareable", new Boolean( engine.isShareable()));
+					
+					params.put("uid", engine.getUID());
+					
+					params.put("supports_direct_download", 
+									new Boolean( 	engine.supportsField( Engine.FIELD_TORRENTLINK ) ||
+													engine.supportsField( Engine.FIELD_DOWNLOADBTNLINK )));
+					
+					params.put( "auto_dl_supported", new Boolean( engine.getAutoDownloadSupported() == Engine.AUTO_DL_SUPPORTED_YES ));
+
+					sendBrowserMessage( "metasearch", "loadTemplateCompleted", params );
+					
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+					
+					Map params = new HashMap();
+					params.put( "id", new Long( id ));
+					params.put("error",Debug.getNestedExceptionMessage(e));
+
+					sendBrowserMessage("metasearch", "loadTemplateFailed",params);
+				}
+			}		
+		} else if( OP_DELETE_TEMPLATE.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+
+			long	id	= ((Long)decodedMap.get( "id" )).longValue();
+			
+			Engine engine = metaSearchManager.getMetaSearch().getEngine( id );
+			
+			if ( engine == null ){
+			
+				Map params = new HashMap();
+				params.put( "id", new Long( id ));
+				params.put( "error", "Template not found" );
+
+				sendBrowserMessage("metasearch", "deleteTemplateFailed",params);
+			
+			}else if ( engine.getSource() != Engine.ENGINE_SOURCE_LOCAL ){
+			
+				Map params = new HashMap();
+				params.put( "id", new Long( id ));
+				params.put( "error", "Template is not local" );
+
+				sendBrowserMessage("metasearch", "deleteTemplateFailed",params);
+				
+			}else{
+				
+				engine.delete();
+				
+				Map params = new HashMap();
+				params.put( "id", new Long( id ));
+				sendBrowserMessage( "metasearch", "deleteTemplateCompleted", params );
+			}
+		} else if( OP_TEST_TEMPLATE.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+
+			final long	id		= ((Long)decodedMap.get( "id" )).longValue();
+			long	match_count	= ((Long)decodedMap.get( "max_matches" )).longValue();
+			
+			String searchText 	= (String) decodedMap.get("searchText");
+			String headers		= (String) decodedMap.get("headers");
+
+			final Long	sid = (Long)decodedMap.get( "sid" );
+
+			Engine engine = metaSearchManager.getMetaSearch().getEngine( id );
+			
+			if ( engine == null ){
+			
+				Map params = new HashMap();
+				params.put( "id", new Long( id ));
+				params.put( "error", "Template not found" );
+				if ( sid != null )params.put( "sid", sid );
+
+				sendBrowserMessage("metasearch", "testTemplateFailed",params);
+			
+			}else{
+				
+				SearchParameter parameter = new SearchParameter("s",searchText);
+				SearchParameter[] parameters = new SearchParameter[] {parameter};
+
+				try{
+				
+					engine.search(
+							parameters, 
+							new HashMap(),
+							(int)match_count,
+							(int)match_count,
+							headers,
+							new ResultListener()
+							{
+								private String	content;
+								private List	matches = new ArrayList();
+								
+								public void 
+								contentReceived(
+									Engine 		engine, 
+									String 		_content )
+								{
+									content = _content;
+								}
+								
+								public void 
+								matchFound(
+									Engine 		engine,
+									String[] 	fields) 
+								{
+									matches.add( fields );
+								}
+								
+								public void 
+								resultsReceived(
+									Engine 		engine,
+									Result[] 	results )
+								{								
+								}
+								
+								public void 
+								resultsComplete(
+									Engine 		engine )
+								{
+									Map params = new HashMap();
+									params.put( "id", new Long( id ));
+									if ( sid != null )params.put( "sid", sid );
+									params.put( "content", JSONObject.escape( content ));
+	
+									JSONArray	l_matches = new JSONArray();
+									
+									params.put( "matches", l_matches );
+									
+									for (int i=0;i<matches.size();i++){
+										
+										String[]	match = (String[])matches.get(i);
+										
+										JSONArray	l_match = new JSONArray();
+										
+										l_matches.add( l_match );
+										
+										for (int j=0;j<match.length;j++){
+											
+											l_match.add( match[j] );
+										}
+									}
+																
+									sendBrowserMessage( "metasearch", "testTemplateCompleted", params );
+				
+								}
+								
+								public void 
+								engineFailed(
+									Engine 		engine,
+									Throwable 	e )
+								{
+									Debug.out( e );
+									
+									Map params = new HashMap();
+									params.put( "id", new Long( id ));
+									params.put( "error", Debug.getNestedExceptionMessage( e ));
+									if ( sid != null )params.put( "sid", sid );
+	
+									sendBrowserMessage("metasearch", "testTemplateFailed",params);
+								}
+								
+								public void 
+								engineRequiresLogin(
+									Engine 		engine,
+									Throwable 	e )
+								{
+									Map params = new HashMap();
+									params.put( "id", new Long( id ));
+									params.put( "error", Debug.getNestedExceptionMessage( e ));
+									if ( sid != null )params.put( "sid", sid );
+	
+									sendBrowserMessage("metasearch", "testTemplateRequiresLogin",params);
+								}
+							});
+				}catch( SearchException e ){
+						// listener handles
+				}
+			}	
+		} else if ( OP_EXPORT_TEMPLATE.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+
+			final long	id		= ((Long)decodedMap.get( "id" )).longValue();
+			
+			final Engine engine = metaSearchManager.getMetaSearch().getEngine( id );
+			
+			if ( engine == null ){
+				
+				Map params = new HashMap();
+				params.put( "error", "template '" + id + "' not found" );
+
+				sendBrowserMessage("metasearch", "exportTemplateFailed",params);
+				
+			}else{
+				final Shell shell = Utils.findAnyShell();
+				
+				shell.getDisplay().asyncExec(
+					new AERunnable() 
+					{
+						public void 
+						runSupport()
+						{
+							FileDialog dialog = 
+								new FileDialog( shell, SWT.SYSTEM_MODAL | SWT.SAVE );
+							
+							dialog.setFilterPath( TorrentOpener.getFilterPathData() );
+													
+							dialog.setText(MessageText.getString("metasearch.export.select.template.file"));
+							
+							dialog.setFilterExtensions(new String[] {
+									"*.vuze",
+									"*.vuz",
+									Constants.FILE_WILDCARD
+								});
+							dialog.setFilterNames(new String[] {
+									"*.vuze",
+									"*.vuz",
+									Constants.FILE_WILDCARD
+								});
+							
+							String path = TorrentOpener.setFilterPathData( dialog.open());
+		
+							if ( path != null ){
+								
+								String lc = path.toLowerCase();
+								
+								if ( !lc.endsWith( ".vuze" ) && !lc.endsWith( ".vuz" )){
+									
+									path += ".vuze";
+								}
+								
+								try{
+									engine.exportToVuzeFile( new File( path ));
+									
+									Map params = new HashMap();
+									params.put( "id", new Long( id ));
+									sendBrowserMessage( "metasearch", "exportTemplateCompleted", params );
+
+								}catch( Throwable e ){
+									
+									Debug.out( e );
+									
+									Map params = new HashMap();
+									params.put( "id", new Long( id ));
+									params.put( "error", "save failed: " + Debug.getNestedExceptionMessage(e));
+
+									sendBrowserMessage("metasearch", "exportTemplateFailed",params);
+								}
+							}else{
+								
+								Map params = new HashMap();
+								params.put( "id", new Long( id ));
+								params.put( "error", "operation cancelled" );
+
+								sendBrowserMessage("metasearch", "exportTemplateFailed",params);
+							}
+						}
+					});
+			}
+		}else if ( OP_IMPORT_TEMPLATE.equals(opid)){
+						
+			final Shell shell = Utils.findAnyShell();
+			
+			shell.getDisplay().asyncExec(
+				new AERunnable() 
+				{
+					public void 
+					runSupport()
+					{
+						FileDialog dialog = 
+							new FileDialog( shell, SWT.SYSTEM_MODAL | SWT.OPEN );
+						
+						dialog.setFilterPath( TorrentOpener.getFilterPathData() );
+												
+						dialog.setText(MessageText.getString("metasearch.import.select.template.file"));
+						
+						dialog.setFilterExtensions(new String[] {
+								"*.vuze",
+								"*.vuz",
+								Constants.FILE_WILDCARD
+							});
+						dialog.setFilterNames(new String[] {
+								"*.vuze",
+								"*.vuz",
+								Constants.FILE_WILDCARD
+							});
+						
+						String path = TorrentOpener.setFilterPathData( dialog.open());
+	
+						if ( path != null ){
+							
+							VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
+							
+							VuzeFile vf = vfh.loadAndHandleVuzeFile( path, VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE );
+							
+							if ( vf == null ){
+								
+								Map params = new HashMap();
+								params.put( "error", "invalid .vuze file" );
+
+								sendBrowserMessage("metasearch", "importTemplateFailed",params);
+								
+							}else{
+								
+								VuzeFileComponent[] comps = vf.getComponents();
+								
+								for (int i=0;i<comps.length;i++){
+									
+									VuzeFileComponent comp = comps[i];
+									
+									if ( comp.getType() == VuzeFileComponent.COMP_TYPE_METASEARCH_TEMPLATE ){
+										
+										Engine engine = (Engine)comp.getData( Engine.VUZE_FILE_COMPONENT_ENGINE_KEY );
+										
+										if ( engine != null ){
+											
+											Map params = new HashMap();
+											params.put( "id", new Long( engine.getId()));
+											sendBrowserMessage( "metasearch", "importTemplateCompleted", params );
+
+											return;
+										}
+									}
+								}
+								
+								Map params = new HashMap();
+								params.put( "error", "invalid search template file" );
+
+								sendBrowserMessage("metasearch", "importTemplateFailed",params);
+							}
+						}else{
+							
+							Map params = new HashMap();
+								// don't change this message as the UI uses it!
+							params.put( "error", "operation cancelled" );
+
+							sendBrowserMessage("metasearch", "importTemplateFailed",params);
+						}
+					}
+				});
+		}else if ( OP_OPEN_SEARCH_RESULTS.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+			openCloseSearchDetailsListener.openSearchResults(decodedMap);
+		}else if ( OP_CLOSE_SEARCH_RESULTS.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+			openCloseSearchDetailsListener.closeSearchResults(decodedMap);
+		}else if(OP_LOAD_TORRENT.equals(opid)) {
+			Map decodedMap = message.getDecodedMap();
+			
+			String torrentUrl		= (String) decodedMap.get( "torrent_url" );
+			String referer_str	= (String) decodedMap.get( "referer_url" );
+			
+			if ( UrlFilter.getInstance().isWhitelisted( torrentUrl )){
+				
+				ContentNetwork cn = ContentNetworkManagerFactory.getSingleton().getContentNetworkForURL( torrentUrl );
+				
+				if ( cn == null ){
+					
+					cn = ConstantsVuze.getDefaultContentNetwork();
+				}
+				
+				torrentUrl = cn.appendURLSuffix( torrentUrl, false, true );
+			}
+			
+			try {
+			
+				Map headers = UrlUtils.getBrowserHeaders( referer_str );
+				
+				String subscriptionId		= ((String)decodedMap.get("subs_id"));
+				String subscriptionResultId = ((String)decodedMap.get("subs_rid"));
+				
+				if ( subscriptionId != null ){
+					
+					Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( subscriptionId );
+					
+					if ( subs != null ){
+					
+						try{
+							Engine engine = subs.getEngine();
+							
+							if ( engine != null && engine instanceof WebEngine ){
+								
+								WebEngine webEngine = (WebEngine) engine;
+								
+								if ( webEngine.isNeedsAuth()){
+									
+									headers.put( "Cookie",webEngine.getCookies());
+								}
+							}
+						}catch( Throwable e ){
+						
+							Debug.out( e );
+						}
+						
+						if ( subscriptionResultId != null ){ 
+						
+							subs.addPotentialAssociation( subscriptionResultId, torrentUrl );
+						}
+					}
+				}else{
+					try{
+						long engineID		= ((Long)decodedMap.get("engine_id")).longValue();
+
+						Engine engine = metaSearchManager.getMetaSearch().getEngine( engineID );
+						
+						if ( engine != null ){
+							
+							engine.addPotentialAssociation( torrentUrl );
+						}
+						
+						if ( engine != null && engine instanceof WebEngine ){
+							
+							WebEngine webEngine = (WebEngine) engine;
+							
+							if ( webEngine.isNeedsAuth()){
+								
+								headers.put( "Cookie",webEngine.getCookies());
+							}
+						}
+					}catch( Throwable e ){
+					
+						Debug.printStackTrace(e);
+					}
+				}
+				
+				Boolean	play_now = (Boolean)decodedMap.get( "play-now" );
+				
+				if ( play_now != null && play_now.booleanValue()){
+					
+					synchronized( MetaSearchListener.class ){
+						
+						pending_play_now_urls.add( torrentUrl );
+					}
+				}
+				
+				PluginInitializer.getDefaultInterface().getDownloadManager().addDownload(
+						new URL(torrentUrl), 
+						headers );
+				
+				Map params = new HashMap();
+				params.put("torrent_url",torrentUrl);
+				params.put("referer_url",referer_str);
+				sendBrowserMessage("metasearch", "loadTorrentCompleted",params);
+				
+			} catch(Exception e) {
+				Map params = new HashMap();
+				params.put("torrent_url",torrentUrl);
+				params.put("referer_url",referer_str);
+				params.put( "error", e.getMessage() );
+				sendBrowserMessage("metasearch", "loadTorrentFailed",params);
+			}
+				
+		}else if(OP_HAS_LOAD_TORRENT.equals(opid)) {
+			
+			Map params = new HashMap();
+			params.put("result","1");
+			sendBrowserMessage("metasearch", "hasLoadTorrent",params);
+			
+		}else if(OP_CREATE_SUBSCRIPTION.equals(opid)) {
+			
+			Map decodedMap = message.getDecodedMap();
+			
+			Long	 tid = (Long) decodedMap.get("tid");
+
+			String 		name 		= (String) decodedMap.get( "name" );
+			Boolean 	isPublic	= (Boolean) decodedMap.get( "is_public" );
+			Map			options		= (Map)decodedMap.get( "options" );
+			
+			Boolean 	isEnabled		= (Boolean)options.get( "is_enabled" );
+			Boolean 	autoDownload	= (Boolean)options.get( "auto_dl" );
+
+			Map result = new HashMap();
+
+			if ( tid != null )result.put( "tid", tid );
+
+			try{
+				JSONObject	payload = new JSONObject();
+				
+					// change this you need to change update too below
+				
+				payload.put( "engine_id", decodedMap.get( "engine_id" ));
+				payload.put( "search_term", decodedMap.get( "search_term" ));
+				payload.put( "filters", decodedMap.get( "filters" ));
+				payload.put( "schedule", decodedMap.get( "schedule" ));
+				payload.put( "options", decodedMap.get( "options" ));
+				
+				Subscription subs = SubscriptionManagerFactory.getSingleton().create(name, isPublic.booleanValue(), payload.toString());
+				
+				subs.getHistory().setDetails(
+					isEnabled==null?true:isEnabled.booleanValue(),
+					autoDownload==null?false:autoDownload.booleanValue());
+								
+				result.put( "id", subs.getID());
+				
+				sendBrowserMessage( "metasearch", "createSubscriptionCompleted", result );
+
+			} catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				result.put( "error", "create failed: " + Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage( "metasearch", "createSubscriptionFailed", result );
+			}
+		}else if( OP_READ_SUBSCRIPTION.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+			
+			final Long	 tid = (Long) decodedMap.get("tid");
+
+			final String sid = (String) decodedMap.get("id");
+			
+			Map result = new HashMap();
+
+			if ( tid != null )result.put( "tid", tid );
+
+			try{
+				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
+				
+				if ( subs == null ){
+					
+					result.put( "error", "Subscription not found" );
+
+					sendBrowserMessage("metasearch", "readSubscriptionFailed",result);
+					
+				}else{
+								
+					boolean	shareable = subs.isShareable();
+					
+						// override public flag if not shareable
+					
+					result.put( "id", subs.getID());
+					result.put( "name", subs.getName());
+					result.put( "is_public", new Boolean( shareable && subs.isPublic()));
+					result.put( "is_author", new Boolean( subs.isMine()));
+					result.put( "is_shareable", new Boolean( shareable ));
+					result.put( "auto_dl_supported", new Boolean( subs.isAutoDownloadSupported()));
+					
+					SubscriptionHistory history = subs.getHistory();
+					
+					Map	options = new HashMap();
+
+					result.put( "options", options );
+
+					options.put( "is_enabled", new Boolean( history.isEnabled()));
+					options.put( "auto_dl", new Boolean( history.isAutoDownload()));
+					
+					Map	info = new HashMap();
+
+					result.put( "info", info );
+					
+					info.put( "last_scan", new Long( history.getLastScanTime()));
+					info.put( "last_new", new Long( history.getLastNewResultTime()));
+					info.put( "num_unread", new Long( history.getNumUnread()));
+					info.put( "num_read", new Long( history.getNumRead()));
+					
+					String json = subs.getJSON();
+					
+					Map map = JSONUtils.decodeJSON( json );
+					
+					result.put( "engine_id", map.get( "engine_id" ));
+					result.put( "search_term", map.get( "search_term" ));
+					result.put( "filters", map.get( "filters" ));
+					result.put( "schedule", map.get( "schedule" ));
+					
+					sendBrowserMessage( "metasearch", "readSubscriptionCompleted", result );
+				}
+			} catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage("metasearch", "readSubscriptionFailed",result);
+			}
+		}else if (OP_UPDATE_SUBSCRIPTION.equals(opid)) {
+			
+			Map decodedMap = message.getDecodedMap();
+			
+			final Long	 tid = (Long) decodedMap.get("tid");
+			
+			final String 	name 		= (String)decodedMap.get("name");
+			final Boolean 	isPublic	= (Boolean)decodedMap.get( "is_public" );
+			final String 	sid 		= (String)decodedMap.get("id");
+			
+			Map			options		= (Map)decodedMap.get( "options" );
+			
+			Boolean 	isEnabled		= (Boolean)options.get( "is_enabled" );
+			Boolean 	autoDownload	= (Boolean)options.get( "auto_dl" );
+
+			Map result = new HashMap();
+
+			if ( tid != null )result.put( "tid", tid );
+
+			try{
+				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
+				
+				if ( subs == null ){
+					
+					result.put( "error", "Subscription not found" );
+
+					sendBrowserMessage("metasearch", "updateSubscriptionFailed",result);
+					
+				}else{
+					
+					JSONObject	payload = new JSONObject();
+					
+						// change this you need to change create too above
+				
+					payload.put( "engine_id", decodedMap.get( "engine_id" ));
+					payload.put( "search_term", decodedMap.get( "search_term" ));
+					payload.put( "filters", decodedMap.get( "filters" ));
+					payload.put( "schedule", decodedMap.get( "schedule" ));
+					payload.put( "options", decodedMap.get( "options" ));
+				
+					boolean	changed = subs.setDetails( name, isPublic.booleanValue(), payload.toString());
+					
+					subs.getHistory().setDetails(
+							isEnabled==null?true:isEnabled.booleanValue(),
+							autoDownload==null?false:autoDownload.booleanValue());
+
+					if ( changed ){
+						
+						subs.reset();
+						
+						try{
+							subs.getManager().getScheduler().downloadAsync(subs, true);
+							
+						}catch( Throwable e ){
+							
+							Debug.out(e);
+						}
+					}
+					
+					result.put( "id", subs.getID());
+					
+					sendBrowserMessage( "metasearch", "updateSubscriptionCompleted", result );
+				}
+			} catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				result.put( "error", "update failed: " + Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage("metasearch", "updateSubscriptionFailed",result);
+			}
+			
+		}else if (OP_SUBSCRIPTION_SET_AUTODL.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+			
+			String 	sid = (String)decodedMap.get("id");
+			
+			Long	tid = (Long) decodedMap.get("tid");
+
+			Boolean 	autoDownload	= (Boolean)decodedMap.get( "auto_dl" );
+
+			Map result = new HashMap();
+
+			if ( tid != null )result.put( "tid", tid );
+
+			try{
+				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
+				
+				if ( subs == null ){
+					
+					result.put( "error", "Subscription not found" );
+
+					sendBrowserMessage("metasearch", "setSubscriptionAutoDownloadFailed",result);
+					
+				}else{
+					
+					subs.getHistory().setAutoDownload( autoDownload.booleanValue());
+					
+					sendBrowserMessage( "metasearch", "setSubscriptionAutoDownloadCompleted", result );
+				}
+			} catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				result.put( "error", "update failed: " + Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage("metasearch", "setSubscriptionAutoDownloadFailed",result);
+			}
+			
+		}else if(OP_READ_SUBSCRIPTION_RESULTS.equals(opid)) {
+			
+			Map decodedMap = message.getDecodedMap();
+			
+			final Long	 tid = (Long) decodedMap.get("tid");
+			
+			final String sid = (String) decodedMap.get("id");
+			
+			final Map result = new HashMap();
+
+			if ( tid != null )result.put( "tid", tid );
+
+			try{
+				final Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
+				
+				if ( subs == null ){
+								
+					result.put( "error", "Subscription not found" );
+
+					sendBrowserMessage("metasearch", "readSubscriptionResultsFailed",result);
+					
+				}else{
+						
+					result.put( "id", subs.getID());
+										
+					if ( !handleSubscriptionAuth( subs, result )){
+					
+						if ( subs.getHistory().getLastScanTime() == 0 ){
+							
+							subs.getManager().getScheduler().download(
+									subs,
+									false,
+									new SubscriptionDownloadListener()
+									{
+										public void
+										complete(
+											Subscription		subs )
+										{
+											if ( !handleSubscriptionAuth( subs, result )){
+												
+												encodeResults( subs, result );
+											
+												sendBrowserMessage( "metasearch", "readSubscriptionResultsCompleted", result );
+												
+												openCloseSearchDetailsListener.resizeMainBrowser();
+												
+											}
+										}
+										
+										public void
+										failed(
+											Subscription			subs,
+											SubscriptionException	error )
+										{
+											Debug.out( error );
+											
+											result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(error));
+	
+											sendBrowserMessage( "metasearch", "readSubscriptionResultsFailed", result );
+	
+										}
+									});
+						}else{
+													
+							encodeResults( subs, result );
+							
+							sendBrowserMessage( "metasearch", "readSubscriptionResultsCompleted", result );
+					
+							openCloseSearchDetailsListener.resizeMainBrowser();
+						}
+					}
+				}
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage("metasearch", "readSubscriptionFailed",result);
+			}
+		}else if( OP_DELETE_SUBSCRIPTION_RESULTS.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+						
+			String sid = (String)decodedMap.get("id");
+			
+			List	rids	= (List)decodedMap.get( "rids" );
+			
+			try{
+				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
+				
+				if ( subs == null ){
+					
+					Map params = new HashMap();
+					
+					params.put( "error", "Subscription not found" );
+
+					sendBrowserMessage("metasearch", "deleteSubscriptionResultsFailed",params);
+					
+				}else{
+					
+					String[]	rids_a = (String[])rids.toArray( new String[rids.size()]);
+					
+					subs.getHistory().deleteResults( rids_a );
+					
+					Map result = new HashMap();
+					
+					result.put( "rids", rids);
+					
+					sendBrowserMessage( "metasearch", "deleteSubscriptionResultsCompleted", result );
+				}
+			} catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				Map params = new HashMap();
+
+				params.put( "error", "delete failed: " + Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage("metasearch", "deleteSubscriptionResultsFailed",params);
+			}
+		}else if( OP_MARK_SUBSCRIPTION_RESULTS.equals(opid)){
+			
+			Map decodedMap = message.getDecodedMap();
+						
+			String sid = (String)decodedMap.get("id");
+			
+			List	rids	= (List)decodedMap.get( "rids" );
+			List	reads	= (List)decodedMap.get( "reads" );
+			
+			Map result = new HashMap();		
+
+			try{
+				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
+				
+				if ( subs == null ){
+					
+					result.put( "error", "Subscription not found" );
+
+					sendBrowserMessage("metasearch", "markSubscriptionResultsFailed",result);
+					
+				}else{
+					
+					String[]	rids_a = (String[])rids.toArray( new String[rids.size()]);
+					
+					boolean[]	reads_a = new boolean[reads.size()];
+					
+					for (int i=0;i<reads.size();i++){
+						
+						reads_a[i] = ((Boolean)reads.get(i)).booleanValue();
+					}
+					
+					subs.getHistory().markResults( rids_a, reads_a );
+					
+					result.put( "rids", rids);
+					result.put( "reads", reads);
+										
+					sendBrowserMessage( "metasearch", "markSubscriptionResultsCompleted", result );
+				}
+			} catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				result.put( "error", "mark failed: " + Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage("metasearch", "markSubscriptionResultsFailed",result);
+			}
+		}else if( OP_DOWNLOAD_SUBSCRIPTION.equals(opid)) {
+			
+			Map decodedMap = message.getDecodedMap();
+			
+			final Long	 tid = (Long) decodedMap.get("tid");
+
+			final String sid = (String) decodedMap.get("id");
+			
+			final Map result = new HashMap();
+
+			if ( tid != null )result.put( "tid", tid );
+
+			try{
+				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( sid );
+				
+				if ( subs == null ){
+					
+					result.put( "error", "Subscription not found" );
+
+					sendBrowserMessage("metasearch", "downloadSubscriptionFailed", result );
+					
+				}else{
+					
+					result.put( "id", subs.getID());
+					
+					if ( !handleSubscriptionAuth( subs, result )){
+
+						subs.getManager().getScheduler().download(
+							subs,
+							false,
+							new SubscriptionDownloadListener()
+							{
+								public void
+								complete(
+									Subscription		subs )
+								{
+									if ( !handleSubscriptionAuth( subs, result )){
+
+										encodeResults( subs, result );
+									
+										sendBrowserMessage( "metasearch", "downloadSubscriptionCompleted", result );
+									}
+								}
+								
+								public void
+								failed(
+									Subscription			subs,
+									SubscriptionException	error )
+								{
+									Debug.out( error );
+									
+									result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(error));
+	
+									sendBrowserMessage( "metasearch", "downloadSubscriptionFailed", result );
+	
+								}
+							});
+					}
+				}
+			} catch( Throwable e ){
+				
+				Debug.out( e );
+				
+				result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(e));
+
+				sendBrowserMessage( "metasearch", "downloadSubscriptionFailed", result );
+			}
+		}else if( OP_IS_CUSTOMISED.equals(opid)) {
+			
+			boolean custom = CustomizationManagerFactory.getSingleton().getActiveCustomization() != null;
+			
+			Map params = new HashMap();
+			
+			params.put( "is_custom", new Boolean( custom ));
+
+			sendBrowserMessage( "metasearch", "isCustomizedResult", params );
+		}else if( OP_ADD_EXTERNAL_LINKS.equals(opid)) {
+			Map decodedMap = message.getDecodedMap();
+
+			List list = MapUtils.getMapList(decodedMap, "external-links", Collections.EMPTY_LIST);
+			for (Object o : list) {
+				if (o instanceof String) {
+					String link = (String) o;
+					PlatformConfigMessenger.addLinkExternal(link);
+				}
+			}
+		}
+	}
+	
+	protected boolean
+	handleSubscriptionAuth(
+		final Subscription		subs,
+		final Map				result )
+	{
+		if ( subs.getHistory().isAuthFail()){
+			
+			try{
+				Engine engine = subs.getEngine();
+				
+				if ( engine instanceof WebEngine ){
+				
+					final WebEngine webEngine = (WebEngine)engine;
+				
+					synchronized( active_subs_auth ){
+						
+						if ( active_subs_auth.contains( subs )){
+							
+							return( false );
+						}
+						
+						active_subs_auth.add( subs );
+					}
+					
+					Utils.execSWTThread( new Runnable() {
+						public void run() {
+							new ExternalLoginWindow(
+								new ExternalLoginListener() 
+								{
+									private String previous_cookies;
+									
+									private boolean	result_sent;
+									
+									public void 
+									canceled(
+										ExternalLoginWindow 	window ) 
+									{
+										try{
+											encodeResults( subs, result );
+											
+											sendBrowserMessage( "metasearch", "readSubscriptionResultsCompleted", result );
+											
+										}finally{
+											
+											completed();
+										}
+									}
+		
+									public void 
+									cookiesFound(
+										ExternalLoginWindow 	window,
+										String 					cookies ) 
+									{
+										if ( handleCookies( cookies, false )){
+											
+											window.close();									
+										}
+									}
+		
+									public void 
+									done(
+										ExternalLoginWindow 	window,
+										String 					cookies )
+									{
+										try{
+											if ( !handleCookies( cookies, true )){
+												
+												encodeResults( subs, result );
+												
+												sendBrowserMessage( "metasearch", "readSubscriptionResultsCompleted", result );
+											}
+										}finally{
+											
+											completed();
+										}
+									}
+									
+									private void
+									completed()
+									{
+										synchronized( active_subs_auth ){
+
+											active_subs_auth.remove( subs );
+										}
+									}
+									
+									private boolean
+									handleCookies(
+										String		cookies,
+										boolean		force_if_ready )
+									{
+										if ( result_sent ){
+											
+											return( false );
+										}
+										
+										String[] required = webEngine.getRequiredCookies();
+										
+										boolean	skip = required.length == 0 && !force_if_ready;
+										
+										if ( CookieParser.cookiesContain( required, cookies )){
+												
+											webEngine.setCookies(cookies);
+											
+											if ( previous_cookies == null || !previous_cookies.equals( cookies )){
+												
+												previous_cookies = cookies;
+												
+												if ( !skip ){
+													
+														// search operation will report outcome
+													
+													result_sent	= true;
+													
+													try{
+														subs.getManager().getScheduler().download(
+															subs,
+															false,
+															new SubscriptionDownloadListener()
+															{
+																public void
+																complete(
+																	Subscription		subs )
+																{
+																	result.put( "id", subs.getID());
+																	
+																	encodeResults( subs, result );
+																	
+																	sendBrowserMessage( "metasearch", "readSubscriptionResultsCompleted", result );
+																}
+																
+																public void
+																failed(
+																	Subscription			subs,
+																	SubscriptionException	error )
+																{
+																	Debug.out( error );
+																	
+																	result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(error));
+	
+																	sendBrowserMessage( "metasearch", "readSubscriptionResultsFailed", result );
+																}
+															});		
+													}catch( Throwable error ){
+														
+														Debug.out( error );
+														
+														result.put( "error", "read failed: " + Debug.getNestedExceptionMessage(error));
+	
+														sendBrowserMessage( "metasearch", "readSubscriptionResultsFailed", result );
+													}
+												}
+											}
+										}
+		
+										return( result_sent );
+									}
+								},
+							webEngine.getName(),
+							webEngine.getLoginPageUrl(),
+							false,
+							webEngine.getAuthMethod(),
+							subs.isMine());
+						}
+					});
+					
+					return( true );
+					
+				}else{
+					
+					return( false );
+				}
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+				
+				return( false );
+			}
+		}else{
+			
+			return( false );
+		}
+	}
+	
+	protected void
+	search(
+		Map		decodedMap,
+		Engine	target )
+	{
+		String searchText = (String) decodedMap.get("searchText");
+		
+		String headers = (String)decodedMap.get( "headers" );
+		
+		final Long	sid = (Long)decodedMap.get( "sid" );
+
+		Boolean	mature = (Boolean)decodedMap.get( "mature" );
+		
+		Long	l_max_per_engine = (Long)decodedMap.get( "maxResultsPerEngine" );
+
+		int	max_per_engine = l_max_per_engine==null?100:l_max_per_engine.intValue();
+		
+		if ( max_per_engine < 1 ){
+			
+			max_per_engine = 1;
+		}
+		
+		if ( target == null ){
+		
+				// override engine selection for subscriptions
+			
+			String subscriptionId		= ((String)decodedMap.get("subs_id"));
+			
+			if ( subscriptionId != null ){
+				
+				Subscription subs = SubscriptionManagerFactory.getSingleton().getSubscriptionByID( subscriptionId );
+				
+				if ( subs != null ){
+				
+					try{
+						Engine engine = subs.getEngine();
+						
+						if ( engine != null ){
+							
+							target = engine;
+						}
+					}catch( Throwable e ){
+					
+						Debug.out( e );
+					}
+				}
+			}
+		}
+		
+		ResultListener listener = new ResultListener() {
+			
+			public void 
+			contentReceived(
+				Engine engine, 
+				String content ) 
+			{
+			}
+			
+			public void 
+			matchFound(
+				Engine 		engine, 
+				String[] 	fields ) 
+			{
+			}
+			
+			public void engineFailed(Engine engine, Throwable e) {
+				
+				Debug.out( e );
+				
+				Map params = getParams( engine );
+				
+				params.put( "error", Debug.getNestedExceptionMessage( e ));
+				
+				sendBrowserMessage("metasearch", "engineFailed", params );
+			}
+			
+			public void engineRequiresLogin(Engine engine, Throwable e) {
+				Map params = getParams( engine );
+				
+				params.put( "error", Debug.getNestedExceptionMessage( e ));
+				
+				sendBrowserMessage("metasearch", "engineRequiresLogin", params );
+			}
+			
+			public void resultsComplete(Engine engine) {
+			
+				sendBrowserMessage("metasearch", "engineCompleted", getParams( engine ));
+			}
+			
+			public void resultsReceived(Engine engine,Result[] results) {
+				Map params = getParams(engine);
+				List resultsList = new ArrayList(results.length);
+				for(int i = 0 ; i < results.length ; i++) {
+					Result result = results[i];
+					resultsList.add(result.toJSONMap());
+				}
+				params.put("results", resultsList);
+				sendBrowserMessage("metasearch", "resultsReceived",params);
+			}
+			
+			protected Map
+			getParams(
+				Engine	engine )
+			{
+				Map params = new HashMap();
+				params.put("id", new Long(engine.getId()));
+				params.put("name", engine.getName());
+				params.put("favicon", engine.getIcon());
+				params.put("dl_link_css", engine.getDownloadLinkCSS());
+				params.put("shareable", new Boolean( engine.isShareable()));
+				
+				if ( sid != null ){
+					params.put( "sid", sid );
+				}
+				return( params );
+			}
+		};
+		
+		List	sps = new ArrayList();
+					
+		sps.add( new SearchParameter( "s", searchText ));
+		
+		if ( mature != null ){
+			
+			sps.add( new SearchParameter( "m", mature.toString()));
+		}
+		
+		SearchParameter[] parameters = (SearchParameter[])sps.toArray(new SearchParameter[ sps.size()] );
+		
+		MetaSearchManager metaSearchManager = MetaSearchManagerFactory.getSingleton();
+
+		Map<String,String>	context = new HashMap<String, String>();
+		
+		context.put( Engine.SC_FORCE_FULL, "true" );
+		
+		context.put( Engine.SC_BATCH_PERIOD, "1000" );
+		
+		context.put( Engine.SC_REMOVE_DUP_HASH, "true" );
+		
+		if ( target == null ){
+		
+			metaSearchManager.getMetaSearch().search( listener, parameters, headers, context, max_per_engine );
+			
+		}else{
+			
+			metaSearchManager.getMetaSearch().search( new Engine[]{ target }, listener, parameters, headers, context, max_per_engine );
+
+		}
+	}
+	
+	protected void
+	encodeResults(
+		Subscription	subs,
+		Map				result )
+	{
+		JSONArray	results_list = new JSONArray();
+		
+		SubscriptionResult[]	results = subs.getHistory().getResults( false );
+		
+		for(int i=0; i<results.length; i++){
+			
+			SubscriptionResult r = results[i];
+			
+			results_list.add( r.toJSONMap());
+		}
+		
+		result.put( "results", results_list );
+		
+		
+	}
+	
+	protected Engine
+	getEngineFromId(
+			long id )
+	{
+		MetaSearchManager metaSearchManager = MetaSearchManagerFactory.getSingleton();
+		
+		Engine[] engines = metaSearchManager.getMetaSearch().getEngines( false, true );
+		for(int i = 0 ; i < engines.length ; i++) {
+			Engine engine = engines[i];
+			if(engine.getId() == id) {
+				return engine;
+			}	
+		}
+		return null;
+	}
+	
+	public boolean 
+	sendBrowserMessage(
+		String 		key, 
+		String 		op, 
+		Map 		params )
+	{
+		MetaSearchManagerFactory.getSingleton().log( "BrowserListener: sent " + op + ": " + params );
+
+		return( context.sendBrowserMessage(key, op, params));
+	}
+	
+	public boolean 
+	sendBrowserMessage(
+		String 			key, 
+		String 			op, 
+		Collection 		params )
+	{
+		MetaSearchManagerFactory.getSingleton().log( "BrowserListener: sent " + op + ": " + params );
+
+		return( context.sendBrowserMessage(key, op, params));
+	}
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/TorrentListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/TorrentListener.java
index e6a0563..5dd58ae 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/TorrentListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/TorrentListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.browser.listener;
 
 import java.io.File;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/VuzeListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/VuzeListener.java
index 57d424d..da71b8e 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/VuzeListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/listener/VuzeListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.browser.listener;
 
 import java.util.Map;
@@ -75,11 +93,8 @@ public class VuzeListener
 			FeatureManagerUI.createTrial();
 
 		}else if (OP_RUN_SPEED_TEST.equals(opid)) {
-			Map decodedMap = message.getDecodedMap();
 			
-			boolean allowShaperLogicProbe = MapUtils.getMapBoolean(decodedMap,
-					"allowShaperLogicProbe", false);
-			SpeedTestSelector.runMLABTest(allowShaperLogicProbe, null);
+			SpeedTestSelector.runMLABTest( null);
 
 		}else if (OP_GET_MODE.equals(opid)) {
 			Map decodedMap = message.getDecodedMap();
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/browser/msg/MessageDispatcherSWT.java b/azureus3/src/com/aelitis/azureus/ui/swt/browser/msg/MessageDispatcherSWT.java
index 40cb544..b5eef50 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/browser/msg/MessageDispatcherSWT.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/browser/msg/MessageDispatcherSWT.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 29, 2006 10:16:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
 
@@ -23,8 +20,6 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.eclipse.swt.browser.*;
-
 import org.gudy.azureus2.core3.util.AEThread2;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.ui.swt.Utils;
@@ -33,7 +28,9 @@ import com.aelitis.azureus.core.messenger.ClientMessageContext;
 import com.aelitis.azureus.core.messenger.browser.BrowserMessage;
 import com.aelitis.azureus.core.messenger.browser.BrowserMessageDispatcher;
 import com.aelitis.azureus.core.messenger.browser.listeners.BrowserMessageListener;
-import com.aelitis.azureus.ui.swt.browser.BrowserWrapper;
+
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
+
 import com.aelitis.azureus.util.JSONUtils;
 import com.aelitis.azureus.util.UrlFilter;
 
@@ -49,7 +46,7 @@ public class MessageDispatcherSWT
 
 	private BrowserWrapper browser;
 
-	private BrowserFunction browserFunction;
+	private BrowserWrapper.BrowserFunction browserFunction;
 
 	/**
 	 * Registers itself as a listener to receive sequence number reset message.
@@ -62,42 +59,46 @@ public class MessageDispatcherSWT
 		this.browser = browser;
 		
 		try {
-  		browserFunction = new BrowserFunction(browser.getBrowser(), "sendMessageToAZ") {
-  			public Object function(Object[] args) {
-  				if (args == null) {
-  					context.debug("sendMessageToAZ: arguments null on " + browser.getUrl());
-  					return null;
-  				}
-  				if (args.length != 3 && args.length != 2) {
-  					context.debug("sendMessageToAZ: # arguments not 2 or 3 (" + args.length + ") on " + browser.getUrl());
-  					return null;
-  				}
-  				
-  				if (!(args[0] instanceof String)) {
-  					context.debug("sendMessageToAZ: Param 1 not String");
-  					return null;
-  				}
-  				if (!(args[1] instanceof String)) {
-  					context.debug("sendMessageToAZ: Param 2 not String");
-  					return null;
-  				}
-  				Map<?, ?> params = Collections.EMPTY_MAP;
-  				if (args.length == 3) {
-    				if (!(args[2] instanceof String)) {
-    					context.debug("sendMessageToAZ: Param 3 not String");
-    					return null;
-    				}
-   
-    				params = JSONUtils.decodeJSON((String)args[2]);
-  				}
-  				
-  
-  				BrowserMessage message = new BrowserMessage((String) args[0], (String) args[1], params);
-  				message.setReferer(browser.getUrl());
-  				dispatch(message);
-  				return null;
-  			}
-  		};
+	  		browserFunction = browser.addBrowserFunction(
+	  			"sendMessageToAZ",
+	  			new BrowserWrapper.BrowserFunction()
+	  			{
+		  			public Object function(Object[] args) {
+		  				if (args == null) {
+		  					context.debug("sendMessageToAZ: arguments null on " + browser.getUrl());
+		  					return null;
+		  				}
+		  				if (args.length != 3 && args.length != 2) {
+		  					context.debug("sendMessageToAZ: # arguments not 2 or 3 (" + args.length + ") on " + browser.getUrl());
+		  					return null;
+		  				}
+		  				
+		  				if (!(args[0] instanceof String)) {
+		  					context.debug("sendMessageToAZ: Param 1 not String");
+		  					return null;
+		  				}
+		  				if (!(args[1] instanceof String)) {
+		  					context.debug("sendMessageToAZ: Param 2 not String");
+		  					return null;
+		  				}
+		  				Map<?, ?> params = Collections.EMPTY_MAP;
+		  				if (args.length == 3) {
+		    				if (!(args[2] instanceof String)) {
+		    					context.debug("sendMessageToAZ: Param 3 not String");
+		    					return null;
+		    				}
+		   
+		    				params = JSONUtils.decodeJSON((String)args[2]);
+		  				}
+		  				
+		  
+		  				BrowserMessage message = new BrowserMessage((String) args[0], (String) args[1], params);
+		  				message.setReferer(browser.getUrl());
+		  				dispatch(message);
+		  				return null;
+		  			}
+		  		});
+  		
 		} catch (Throwable t) {
 			Debug.out(t);
 		}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/ColumnCheckBox.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/ColumnCheckBox.java
index 11e86fa..38c4565 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/ColumnCheckBox.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/ColumnCheckBox.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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;
@@ -45,13 +43,17 @@ ColumnCheckBox
 	implements TableCellRefreshListener, TableColumnExtraInfoListener, TableCellMouseListener
 {	
 	private static final UISWTGraphic tick_icon;
+	private static final UISWTGraphic tick_ro_icon;
 	private static final UISWTGraphic cross_icon;
 	
 	static {
-		tick_icon = new UISWTGraphicImpl(ImageLoader.getInstance().getImage("check_yes"));
-		cross_icon = new UISWTGraphicImpl(ImageLoader.getInstance().getImage("check_no"));
+		tick_icon 		= new UISWTGraphicImpl(ImageLoader.getInstance().getImage("check_yes"));
+		tick_ro_icon 	= new UISWTGraphicImpl(ImageLoader.getInstance().getImage("check_ro_yes"));
+		cross_icon 		= new UISWTGraphicImpl(ImageLoader.getInstance().getImage("check_no"));
 	}
 	
+	private boolean	read_only;
+	
 	public void 
 	fillTableColumnInfo(
 		TableColumnInfo info) 
@@ -66,18 +68,33 @@ ColumnCheckBox
 	public 
 	ColumnCheckBox(
 		TableColumn column,
-		int width ) 
+		int 		width,
+		boolean		read_only )
 	{
+		this.read_only = read_only;
+		
 		column.setWidth(width);
 		column.setType( TableColumn.TYPE_GRAPHIC );
 		column.addListeners(this);
+		
+		if ( read_only ){
+			column.removeCellMouseListener( this );
+		}
 	}
 
 	public 
 	ColumnCheckBox(
 		TableColumn column ) 
 	{
-		this(column, 40);
+		this(column, 40,false);
+	}
+	
+	public 
+	ColumnCheckBox(
+		TableColumn column,
+		int 		width )
+	{
+		this( column, width,false );
 	}
 	
 	protected abstract Boolean
@@ -144,12 +161,12 @@ ColumnCheckBox
 			if ( state ){
 				
 				sortVal = 2;
-				icon 	= tick_icon;
+				icon 	= read_only?tick_ro_icon:tick_icon;
 				
 			}else{
 				
 				sortVal = 1;
-				icon 	= cross_icon;
+				icon 	= read_only?null:cross_icon;
 			}
 		}
 		
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLDate.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLDate.java
new file mode 100644
index 0000000..f78c7ef
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLDate.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 2015 Azureus Software, 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.columns.archivedls;
+
+
+import org.gudy.azureus2.plugins.download.DownloadStub.DownloadStubEx;
+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 org.gudy.azureus2.plugins.ui.tables.TableColumnExtraInfoListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
+import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator;
+import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer;
+
+
+public class 
+ColumnArchiveDLDate
+	implements TableColumnExtraInfoListener, TableCellRefreshListener
+{
+	public static String COLUMN_ID = "archive.date";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+				TableColumn.CAT_TIME,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+
+	public 
+	ColumnArchiveDLDate(
+		TableColumn column) 
+	{
+		column.setWidth(TableColumnCreator.DATE_COLUMN_WIDTH);
+		column.addListeners(this);
+	}
+
+	public void 
+	refresh(
+		TableCell cell ) 
+	{
+		TableColumn tc = cell.getTableColumn();
+		
+		if (tc instanceof ColumnDateSizer) {
+			
+			DownloadStubEx dl = (DownloadStubEx) cell.getDataSource();
+			
+			((ColumnDateSizer) tc).refresh(cell, dl.getCreationDate());
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLFileCount.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLFileCount.java
new file mode 100644
index 0000000..6922d3d
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLFileCount.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (C) 2013 Azureus Software, 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.columns.archivedls;
+
+import org.gudy.azureus2.plugins.download.DownloadStub;
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+public class ColumnArchiveDLFileCount
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "filecount";
+
+	public void 
+	fillTableColumnInfo(
+		TableColumnInfo info) 
+	{
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+	
+	public 
+	ColumnArchiveDLFileCount(
+		TableColumn column) 
+	{
+		column.setWidth(70);
+		column.setAlignment(TableColumn.ALIGN_TRAIL );
+		column.setMinWidthAuto(true);
+		
+		column.addListeners(this);
+	}
+
+	public void 
+	refresh(
+		TableCell cell )
+	{
+		DownloadStub dl = (DownloadStub) cell.getDataSource();
+		
+		long	count = 0;
+		
+		if ( dl != null ){
+			
+			count = dl.getStubFiles().length;
+		}
+		
+
+		if ( !cell.setSortValue(count) && cell.isValid()){
+			
+			//return;
+		}
+
+		if ( !cell.isShown()){
+			
+			return;
+		}
+		
+		cell.setText( String.valueOf( count ));
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLName.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLName.java
new file mode 100644
index 0000000..891fce0
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLName.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) 2013 Azureus Software, 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.columns.archivedls;
+
+import org.gudy.azureus2.core3.util.ByteFormatter;
+import org.gudy.azureus2.plugins.download.DownloadStub;
+import org.gudy.azureus2.plugins.ui.tables.*;
+import org.gudy.azureus2.ui.swt.debug.ObfusticateCellText;
+
+public class ColumnArchiveDLName
+	implements TableCellRefreshListener, TableColumnExtraInfoListener, ObfusticateCellText
+{
+	public static String COLUMN_ID = "name";
+
+	public void 
+	fillTableColumnInfo(
+		TableColumnInfo info) 
+	{
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+	
+	public 
+	ColumnArchiveDLName(
+		TableColumn column) 
+	{
+		column.setWidth(400);
+		column.addListeners(this);
+	}
+
+	public void 
+	refresh(
+		TableCell cell )
+	{
+		DownloadStub dl = (DownloadStub) cell.getDataSource();
+		
+		String name = null;
+		
+		if ( dl != null ){
+			
+			name = dl.getName();
+		}
+		
+		if ( name == null ){
+			
+			name = "";
+		}
+
+		if ( !cell.setSortValue(name) && cell.isValid()){
+			
+			return;
+		}
+
+		if (!cell.isShown()){
+			
+			return;
+		}
+		
+		cell.setText(name);
+	}
+	
+	public String 
+	getObfusticatedText(
+		TableCell 	cell) 
+	{
+		DownloadStub dl = (DownloadStub) cell.getDataSource();
+		
+		if ( dl == null ){
+			
+			return( "" );
+		}
+		
+		return( ByteFormatter.encodeString(dl.getTorrentHash()));
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLSize.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLSize.java
new file mode 100644
index 0000000..476d50a
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLSize.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright (C) 2013 Azureus Software, 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.columns.archivedls;
+
+import org.gudy.azureus2.core3.util.DisplayFormatters;
+import org.gudy.azureus2.plugins.download.DownloadStub;
+import org.gudy.azureus2.plugins.ui.tables.*;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
+
+public class ColumnArchiveDLSize
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "size";
+
+	public void 
+	fillTableColumnInfo(
+		TableColumnInfo info) 
+	{
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+	
+	public 
+	ColumnArchiveDLSize(
+		TableColumn column) 
+	{
+		column.setWidth(70);
+		column.setAlignment(TableColumn.ALIGN_TRAIL );
+		column.setMinWidthAuto(true);
+		
+		column.addListeners(this);
+	}
+
+	public void 
+	refresh(
+		TableCell cell )
+	{
+		DownloadStub dl = (DownloadStub) cell.getDataSource();
+		
+		long	size = 0;
+		
+		if ( dl != null ){
+			
+			size = dl.getTorrentSize();
+		}
+		
+
+		if ( !cell.setSortValue(size) && cell.isValid()){
+			
+			//return;
+		}
+
+		if ( !cell.isShown()){
+			
+			return;
+		}
+		
+		cell.setText(DisplayFormatters.formatByteCountToKiBEtc( size ));
+		
+		if (Utils.getUserMode() > 0 && (cell instanceof TableCellSWT)) {
+			if (size >= 0x40000000l) {
+				((TableCellSWT) cell).setTextAlpha(200 | 0x100);
+			} else if (size < 0x100000) {
+				((TableCellSWT) cell).setTextAlpha(180);
+			} else {
+				((TableCellSWT) cell).setTextAlpha(255);
+			}
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLTags.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLTags.java
new file mode 100644
index 0000000..2628589
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/archivedls/ColumnArchiveDLTags.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright (C) 2013 Azureus Software, 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.columns.archivedls;
+
+import org.gudy.azureus2.plugins.download.DownloadStub.DownloadStubEx;
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+public class ColumnArchiveDLTags
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "tags";
+
+	public void 
+	fillTableColumnInfo(
+		TableColumnInfo info) 
+	{
+		info.addCategories(new String[] {
+			TableColumn.CAT_CONTENT,
+		});
+		
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+	
+	public 
+	ColumnArchiveDLTags(
+		TableColumn column) 
+	{
+		column.setPosition( TableColumn.POSITION_INVISIBLE );
+		column.setWidth(100);
+		column.addListeners(this);
+	}
+
+	public void 
+	refresh(
+		TableCell cell )
+	{
+		DownloadStubEx dl = (DownloadStubEx) cell.getDataSource();
+		
+		String text = "";
+		
+		if ( dl != null ){
+			
+			String[] tags = dl.getManualTags();
+			
+			if ( tags != null ){
+				
+				for ( String t: tags ){
+					
+					text += (text.length()==0?"":", ") + t;
+				}
+			}
+		}
+	
+		if ( !cell.setSortValue( text ) && cell.isValid()){
+			
+			return;
+		}
+
+		if (!cell.isShown()){
+			
+			return;
+		}
+		
+		cell.setText( text );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionAutoDownload.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionAutoDownload.java
index b195067..e984ef2 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionAutoDownload.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionAutoDownload.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -47,6 +47,7 @@ public class ColumnSubscriptionAutoDownload
 	/** Default Constructor */
 	public ColumnSubscriptionAutoDownload(String sTableID) {
 		super(COLUMN_ID, ALIGN_CENTER, POSITION_LAST, 100, sTableID);
+		setRefreshInterval(INTERVAL_LIVE);
 		setMinWidth(100);
 		setMaxWidth(100);
 	}
@@ -69,7 +70,11 @@ public class ColumnSubscriptionAutoDownload
 			return;
 		}
 		
-		cell.setText( DisplayFormatters.getYesNo( autoDownload ));
+		if ( sub.isAutoDownloadSupported()){
+			cell.setText( DisplayFormatters.getYesNo( autoDownload ));
+		}else{
+			cell.setText( "" );
+		}
 		return;
 		
 	}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionCategory.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionCategory.java
index c660a1a..b5846dc 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionCategory.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionCategory.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -45,12 +45,13 @@ public class ColumnSubscriptionCategory
 	/** Default Constructor */
 	public ColumnSubscriptionCategory(String sTableID) {
 		super(COLUMN_ID, POSITION_LAST, 100, sTableID);
+		setRefreshInterval(INTERVAL_LIVE);
 		setMinWidth(100);
 		setMaxWidth(100);
 	}
 
 	public void refresh(TableCell cell) {
-		int nbResults = 0;
+		
 		Subscription sub = (Subscription) cell.getDataSource();
 		String category = null;
 		if (sub != null) {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionLastChecked.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionLastChecked.java
index e1a8ea0..cc9e1ff 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionLastChecked.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionLastChecked.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -50,7 +50,7 @@ ColumnSubscriptionLastChecked
 	{
 		super(Subscription.class, COLUMN_ID, TableColumnCreator.DATE_COLUMN_WIDTH,
 				sTableID);
-		
+		setRefreshInterval(INTERVAL_LIVE);
 		setMinWidth(100);
 		
 		setMultiline( false );
@@ -80,7 +80,11 @@ ColumnSubscriptionLastChecked
 			return;
 		}
 		
-		if ( timestamp <= 0 ){
+		if ( sub.isSearchTemplate()){
+			
+			cell.setText( "" );
+			
+		}else  if ( timestamp <= 0 ){
 		
 			cell.setText( "--" );
 			
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionName.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionName.java
index b74b0a2..a5cb041 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionName.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionName.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -60,6 +60,7 @@ public class ColumnSubscriptionName
 	/** Default Constructor */
 	public ColumnSubscriptionName(String sTableID) {
 		super(COLUMN_ID, POSITION_LAST, 350, sTableID);
+		setRefreshInterval(INTERVAL_LIVE);
 		setMinWidth(300);
 	}
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbNewResults.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbNewResults.java
index ab480d6..b60ac97 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbNewResults.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbNewResults.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -45,6 +45,7 @@ public class ColumnSubscriptionNbNewResults
 	/** Default Constructor */
 	public ColumnSubscriptionNbNewResults(String sTableID) {
 		super(COLUMN_ID, POSITION_LAST, 100, sTableID);
+		setRefreshInterval(INTERVAL_LIVE);
 		setMinWidth(100);
 		setMaxWidth(100);
 		setAlignment(ALIGN_TRAIL);
@@ -65,7 +66,11 @@ public class ColumnSubscriptionNbNewResults
 			return;
 		}
 		
-		cell.setText("" + nbResults);
+		if ( sub.isSearchTemplate()){
+			cell.setText( "" );
+		}else{
+			cell.setText("" + nbResults);
+		}
 		return;
 		
 	}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbResults.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbResults.java
index d5904a0..c32bb04 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbResults.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNbResults.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -45,6 +45,7 @@ public class ColumnSubscriptionNbResults
 	/** Default Constructor */
 	public ColumnSubscriptionNbResults(String sTableID) {
 		super(COLUMN_ID, POSITION_LAST, 100, sTableID);
+		setRefreshInterval(INTERVAL_LIVE);
 		setMinWidth(100);
 		setMaxWidth(100);
 		setAlignment(ALIGN_TRAIL);
@@ -65,7 +66,11 @@ public class ColumnSubscriptionNbResults
 			return;
 		}
 		
-		cell.setText("" + nbResults);
+		if ( sub.isSearchTemplate()){
+			cell.setText( "" );
+		}else{
+			cell.setText("" + nbResults);
+		}
 		return;
 		
 	}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNew.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNew.java
index 0636af5..bafe8ba 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNew.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionNew.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -53,6 +53,7 @@ public class ColumnSubscriptionNew
 		super(COLUMN_ID, tableID);
 
 		initializeAsGraphic(WIDTH);
+		setRefreshInterval(INTERVAL_LIVE);
 		setMinWidth(WIDTH);
 		setMaxWidth(WIDTH);
 		setVisible(true);
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionSubscribers.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionSubscribers.java
index eb801cd..26ef937 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionSubscribers.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionSubscribers.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -45,8 +45,10 @@ public class ColumnSubscriptionSubscribers
 	/** Default Constructor */
 	public ColumnSubscriptionSubscribers(String sTableID) {
 		super(COLUMN_ID, POSITION_INVISIBLE, 100, sTableID);
+		setRefreshInterval(INTERVAL_LIVE);
 		setMinWidth(100);
 		setMaxWidth(100);
+		setAlignment(ALIGN_TRAIL);
 	}
 
 	public void refresh(TableCell cell) {
@@ -64,7 +66,11 @@ public class ColumnSubscriptionSubscribers
 			return;
 		}
 		
-		cell.setText("" + nbSubsribers);
+		if ( nbSubsribers < 0 ){
+			cell.setText("");
+		}else{
+			cell.setText("" + nbSubsribers);
+		}
 		return;
 		
 	}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionTag.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionTag.java
index 005d93d..a2b8ae5 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionTag.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/subscriptions/ColumnSubscriptionTag.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2008 Vuze Inc., All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -50,6 +50,7 @@ public class ColumnSubscriptionTag
 	/** Default Constructor */
 	public ColumnSubscriptionTag(String sTableID) {
 		super(COLUMN_ID, POSITION_LAST, 100, sTableID);
+		setRefreshInterval(INTERVAL_LIVE);
 		setMinWidth(100);
 		setMaxWidth(100);
 	}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagCopyOnComp.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagCopyOnComp.java
new file mode 100644
index 0000000..9408d23
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagCopyOnComp.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright (C) 2013 Azureus Software, 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.columns.tag;
+
+import java.io.File;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagFeatureFileLocation;
+
+public class ColumnTagCopyOnComp
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "tag.copyoncomp";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+
+	/** Default Constructor */
+	public ColumnTagCopyOnComp(TableColumn column) {
+		column.setWidth(200);
+		column.addListeners(this);
+	}
+
+	public void refresh(TableCell cell) {
+		Tag tag = (Tag) cell.getDataSource();
+		if ( tag instanceof TagFeatureFileLocation ){
+			TagFeatureFileLocation fl = (TagFeatureFileLocation)tag;
+			
+			if ( fl.supportsTagCopyOnComplete()){
+	
+				File target_file = fl.getTagCopyOnCompleteFolder();
+				
+				String target;
+				
+				if ( target_file == null ){
+					target = "";
+				}else{
+					target = target_file.getAbsolutePath();
+				}
+				
+				if (!cell.setSortValue(target) && cell.isValid()) {
+					return;
+				}
+		
+				if (!cell.isShown()) {
+					return;
+				}
+				
+				cell.setText(target);
+			}
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagDownLimit.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagDownLimit.java
index 5cbf9ed..727fc6c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagDownLimit.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagDownLimit.java
@@ -17,6 +17,7 @@
 
 package com.aelitis.azureus.ui.swt.columns.tag;
 
+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.tables.*;
@@ -67,7 +68,7 @@ public class ColumnTagDownLimit
 					return;
 				}
 				
-				cell.setText( sortVal==0?Constants.INFINITY_STRING:DisplayFormatters.formatByteCountToKiBEtcPerSec( sortVal ));
+				cell.setText( sortVal==-1?MessageText.getString("MyTorrentsView.menu.setSpeed.disabled"):(sortVal==0?Constants.INFINITY_STRING:DisplayFormatters.formatByteCountToKiBEtcPerSec( sortVal )));
 			}
 		}
 	}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagGroup.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagGroup.java
new file mode 100644
index 0000000..e6b8c1d
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagGroup.java
@@ -0,0 +1,82 @@
+/*
+ * File    : CategoryItem.java
+ * Created : 01 feb. 2004
+ * By      : TuxPaper
+ *
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.columns.tag;
+
+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 org.gudy.azureus2.plugins.ui.tables.TableColumnExtraInfoListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
+
+import com.aelitis.azureus.core.tag.Tag;
+
+
+
+public class ColumnTagGroup
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "tag.group";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+				TableColumn.CAT_CONTENT,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+
+	/** Default Constructor */
+	public ColumnTagGroup(TableColumn column) {
+		column.setWidth(70);
+		column.setRefreshInterval(TableColumn.INTERVAL_LIVE);
+		column.setPosition( TableColumn.POSITION_INVISIBLE );
+		column.addListeners(this);
+	}
+
+	public void refresh(TableCell cell) {
+		Tag tag = (Tag) cell.getDataSource();
+		
+		String text = null;
+		
+		if ( tag != null ){
+			
+			text = tag.getGroup();
+		}
+		
+		if ( text == null ){
+			
+			text = "";
+		}
+
+		if ( !cell.setSortValue( text ) && cell.isValid()){
+			
+			return;
+		}
+
+		if ( !cell.isShown()){
+			
+			return;
+		}
+		
+		cell.setText( text );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagMaxSR.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagMaxSR.java
index 78b2865..038306b 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagMaxSR.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagMaxSR.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tag;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagMinSR.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagMinSR.java
index ac7f65e..0739c1a 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagMinSR.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagMinSR.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tag;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagName.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagName.java
index f095391..eb5475c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagName.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagName.java
@@ -50,6 +50,13 @@ public class ColumnTagName
 			tagName = "";
 		}
 
+		String desc = tag==null?null:tag.getDescription();
+		
+		if ( desc != null ){
+		
+			cell.setToolTip( desc );
+		}
+		
 		if (!cell.setSortValue(tagName) && cell.isValid()) {
 			return;
 		}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagProperties.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagProperties.java
index 2b0be0f..793153d 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagProperties.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagProperties.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,13 +18,11 @@
  * 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.tag;
 
+import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.plugins.ui.tables.TableCell;
 import org.gudy.azureus2.plugins.ui.tables.TableCellRefreshListener;
 import org.gudy.azureus2.plugins.ui.tables.TableColumn;
@@ -31,6 +30,7 @@ import org.gudy.azureus2.plugins.ui.tables.TableColumnExtraInfoListener;
 import org.gudy.azureus2.plugins.ui.tables.TableColumnInfo;
 
 import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagFeatureExecOnAssign;
 import com.aelitis.azureus.core.tag.TagFeatureProperties;
 
 
@@ -86,6 +86,35 @@ ColumnTagProperties
 			}
 		}
 		
+		if ( tag instanceof TagFeatureExecOnAssign ){
+			
+			TagFeatureExecOnAssign eoa = (TagFeatureExecOnAssign)tag;
+			
+			int	actions = eoa.getSupportedActions();
+			
+			if ( actions != TagFeatureExecOnAssign.ACTION_NONE ){
+							
+				String actions_str = "";
+				
+				if ( eoa.supportsAction( TagFeatureExecOnAssign.ACTION_DESTROY )){
+					
+					boolean enabled = eoa.isActionEnabled( TagFeatureExecOnAssign.ACTION_DESTROY );
+					
+					if ( enabled ){
+					
+						actions_str += MessageText.getString( "FileItem.delete") + "=Y";
+					}
+				}
+				
+				if ( actions_str.length() > 0 ){
+					
+					text += (text.length()==0?"":"; ") +  MessageText.getString( "label.exec.on.assign" ) + ": ";
+
+					text += actions_str;
+				}
+			}
+		}
+				
 
 		if ( !cell.setSortValue( text ) && cell.isValid()){
 			
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagPublic.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagPublic.java
index e513c54..160da82 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagPublic.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagPublic.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tag;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagRSSFeed.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagRSSFeed.java
index 60e6e86..59f4d09 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagRSSFeed.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagRSSFeed.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tag;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagUpLimit.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagUpLimit.java
index 749bbfb..0270478 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagUpLimit.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagUpLimit.java
@@ -17,6 +17,7 @@
 
 package com.aelitis.azureus.ui.swt.columns.tag;
 
+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.tables.*;
@@ -67,7 +68,7 @@ public class ColumnTagUpLimit
 					return;
 				}
 				
-				cell.setText( sortVal==0?Constants.INFINITY_STRING:DisplayFormatters.formatByteCountToKiBEtcPerSec( sortVal ));
+				cell.setText( sortVal==-1?MessageText.getString("MyTorrentsView.menu.setSpeed.disabled"):(sortVal==0?Constants.INFINITY_STRING:DisplayFormatters.formatByteCountToKiBEtcPerSec( sortVal )));
 			}
 		}
 	}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagUploadPriority.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagUploadPriority.java
index b14ad14..4cb846c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagUploadPriority.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagUploadPriority.java
@@ -3,11 +3,12 @@
  * Created : 01 feb. 2004
  * By      : TuxPaper
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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.tag;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagVisible.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagVisible.java
new file mode 100644
index 0000000..1f92368
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tag/ColumnTagVisible.java
@@ -0,0 +1,73 @@
+/*
+ * File    : CategoryItem.java
+ * Created : 01 feb. 2004
+ * By      : TuxPaper
+ *
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.columns.tag;
+
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.ui.swt.columns.ColumnCheckBox;
+
+
+
+public class 
+ColumnTagVisible
+	extends ColumnCheckBox
+{	
+	public static String COLUMN_ID = "tag.visible";
+
+	public 
+	ColumnTagVisible(
+		TableColumn column ) 
+	{
+		super( column, 60 );
+	}
+	
+	@Override
+	protected Boolean 
+	getCheckBoxState(
+		Object datasource ) 
+	{
+		Tag tag = (Tag)datasource;
+		
+		if ( tag != null ){
+						
+			return( tag.isVisible());
+		}
+		
+		return( null );
+	}
+	
+	@Override
+	protected void 
+	setCheckBoxState(
+		Object 	datasource,
+		boolean set ) 
+	{
+		Tag tag = (Tag)datasource;
+		
+		if ( tag != null ){
+							
+			tag.setVisible( set );
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryAddedOn.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryAddedOn.java
new file mode 100644
index 0000000..0e592b8
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryAddedOn.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2014 Azureus Software, 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.columns.tagdiscovery;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator;
+import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer;
+
+import com.aelitis.azureus.core.tag.TagDiscovery;
+
+public class ColumnTagDiscoveryAddedOn
+	implements TableColumnExtraInfoListener, TableCellRefreshListener
+{
+	public static String COLUMN_ID = "tag.discovery.addedon";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			TableColumn.CAT_TIME,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+
+	/** Default Constructor */
+	public ColumnTagDiscoveryAddedOn(TableColumn column) {
+		column.setWidth(TableColumnCreator.DATE_COLUMN_WIDTH);
+		column.addListeners(this);
+	}
+
+	public void refresh(TableCell cell) {
+		TableColumn tc = cell.getTableColumn();
+		if (tc instanceof ColumnDateSizer) {
+			TagDiscovery discovery = (TagDiscovery) cell.getDataSource();
+			((ColumnDateSizer) tc).refresh(cell, discovery.getTimestamp());
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryName.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryName.java
new file mode 100644
index 0000000..9001353
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryName.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2014 Azureus Software, 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.columns.tagdiscovery;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagDiscovery;
+
+public class ColumnTagDiscoveryName
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "tag.discovery.name";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+
+	/** Default Constructor */
+	public ColumnTagDiscoveryName(TableColumn column) {
+		column.setWidth(100);
+		column.addListeners(this);
+	}
+
+	public void refresh(TableCell cell) {
+		TagDiscovery discovery = (TagDiscovery) cell.getDataSource();
+		cell.setText(discovery.getName());
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryNetwork.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryNetwork.java
new file mode 100644
index 0000000..337bf0e
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryNetwork.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2014 Azureus Software, 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.columns.tagdiscovery;
+
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+import com.aelitis.azureus.core.tag.TagDiscovery;
+
+public class ColumnTagDiscoveryNetwork
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "networks";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_INTERMEDIATE);
+	}
+
+	/** Default Constructor */
+	public ColumnTagDiscoveryNetwork(TableColumn column) {
+		column.setWidth(60);
+		column.addListeners(this);
+	}
+
+	public void refresh(TableCell cell) {
+		TagDiscovery discovery = (TagDiscovery) cell.getDataSource();
+		cell.setText(discovery.getNetwork());
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryTorrent.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryTorrent.java
new file mode 100644
index 0000000..f50796e
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/tagdiscovery/ColumnTagDiscoveryTorrent.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2014 Azureus Software, 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.columns.tagdiscovery;
+
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
+import org.gudy.azureus2.plugins.ui.tables.*;
+
+import com.aelitis.azureus.core.tag.TagDiscovery;
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
+
+public class ColumnTagDiscoveryTorrent
+	implements TableCellRefreshListener, TableColumnExtraInfoListener
+{
+	public static String COLUMN_ID = "tag.discovery.torrent";
+
+	public void fillTableColumnInfo(TableColumnInfo info) {
+		info.addCategories(new String[] {
+			TableColumn.CAT_ESSENTIAL,
+		});
+		info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
+	}
+
+	/** Default Constructor */
+	public ColumnTagDiscoveryTorrent(TableColumn column) {
+		column.setWidth(200);
+		column.addListeners(this);
+		TableContextMenuItem menuShowTorrent = column.addContextMenuItem(
+				"ConfigView.option.dm.dblclick.details",
+				TableColumn.MENU_STYLE_COLUMN_DATA);
+
+		menuShowTorrent.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				if (target instanceof TagDiscovery) {
+					UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+					if (uiFunctions != null) {
+						byte[] hash = ((TagDiscovery) target).getHash();
+						uiFunctions.getMDI().showEntryByID(
+								MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS,
+								hash);
+					}
+				}
+			}
+		});
+	}
+
+	public void refresh(TableCell cell) {
+		TagDiscovery discovery = (TagDiscovery) cell.getDataSource();
+		cell.setText(discovery.getTorrentName());
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnControls.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnControls.java
index f1194ed..71e402b 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnControls.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnControls.java
@@ -1,10 +1,12 @@
 /**
  * Created on April 28, 2007 
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnProgressETA.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnProgressETA.java
index 5f70883..6f91d85 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnProgressETA.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnProgressETA.java
@@ -1,11 +1,27 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.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.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerState;
@@ -256,9 +272,10 @@ public class ColumnProgressETA
 		long speed = showSpeed ? getSpeed(ds) : 0;
 
 		//System.out.println("REFRESH " + sortValue + ";" + ds);
+		Comparable old = cell.getSortValue();
 		boolean sortChanged = cell.setSortValue(sortValue);
 
-		if (sortChanged) {
+		if (sortChanged && old != null && !(old instanceof String)) {
 			UIFunctionsManagerSWT.getUIFunctionsSWT().refreshIconBar();
 		}
 
@@ -471,7 +488,7 @@ public class ColumnProgressETA
 
 	private int getPercentDone(Object ds) {
 		if (ds instanceof DownloadManager) {
-			return ((DownloadManager) ds).getStats().getDownloadCompleted(true);
+			return ((DownloadManager) ds).getStats().getPercentDoneExcludingDND();
 		} else if (ds instanceof DiskManagerFileInfo) {
 			DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) ds;
 			long length = fileInfo.getLength();
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnStream.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnStream.java
index 6eff269..dc15bb8 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnStream.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnStream.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 25, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -185,7 +187,7 @@ public class ColumnStream
 					public void run() {
 						Object ds = cell.getDataSource();
 						// first call may take forever
-						PlayUtils.canStreamDS(ds, -1);
+						PlayUtils.canStreamDS(ds, -1,true);
 						skipPaint = false;
 					}
 				};
@@ -200,8 +202,8 @@ public class ColumnStream
 		if (noIconForYou(ds, cell)) {
 			sortVal = 0;
 		} else {
-			boolean canStream = PlayUtils.canStreamDS(ds, -1);
-			boolean canPlay = PlayUtils.canPlayDS(ds, -1);
+			boolean canStream = PlayUtils.canStreamDS(ds, -1,false);
+			boolean canPlay = PlayUtils.canPlayDS(ds, -1,false);
 			sortVal = (canStream ? 2 : 0) + (canPlay ? 1 : 0);
 		}
 
@@ -215,7 +217,7 @@ public class ColumnStream
 		if (event.eventType == TableRowMouseEvent.EVENT_MOUSEDOWN
 				&& event.button == 1) {
 			Object ds = event.cell.getDataSource();
-			if (PlayUtils.canStreamDS(ds, -1) || PlayUtils.canPlayDS(ds, -1)) {
+			if (PlayUtils.canStreamDS(ds, -1,true) || PlayUtils.canPlayDS(ds, -1,true)) {
 				TorrentListViewsUtils.playOrStreamDataSource(ds, "column", true, false);
 			}
 		}
@@ -228,7 +230,7 @@ public class ColumnStream
 			cell.setToolTip(null);
 			return;
 		}
-		if (PlayUtils.canStreamDS(ds, -1) || PlayUtils.canPlayDS(ds, -1)) {
+		if (PlayUtils.canStreamDS(ds, -1,false) || PlayUtils.canPlayDS(ds, -1,false)) {
 			cell.setToolTip(null);
 			return;
 		}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbAndName.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbAndName.java
index 3c94922..95ace76 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbAndName.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbAndName.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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;
@@ -112,6 +110,10 @@ public class ColumnThumbAndName
 				}
 				Object[] o = (Object[]) target;
 				for (Object object : o) {
+					if (object instanceof TableRowCore) {
+						TableRowCore row = (TableRowCore) object;
+						object = row.getDataSource(true);
+					}
 					if (object instanceof DownloadManager) {
 						final DownloadManager dm = (DownloadManager) object;
 						String msg_key_prefix = "MyTorrentsView.menu.rename.displayed.enter.";
@@ -119,6 +121,7 @@ public class ColumnThumbAndName
 						SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
 								msg_key_prefix + "title", msg_key_prefix + "message");
 						entryWindow.setPreenteredText(dm.getDisplayName(), false);
+						entryWindow.maintainWhitespace( true );	// apparently users want to be able to prefix with spaces
 						entryWindow.prompt(new UIInputReceiverListener() {
 							public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
 								if (!entryWindow.hasSubmittedInput()) {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbnail.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbnail.java
index 13575f8..b5bb0bd 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbnail.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnThumbnail.java
@@ -3,11 +3,12 @@
  * Created : 24 nov. 2003
  * By      : Olivier
  *
- * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -17,9 +18,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnTorrentFileProgress.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnTorrentFileProgress.java
index 10e6eba..7f808dc 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnTorrentFileProgress.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnTorrentFileProgress.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.columns.torrent;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnUnopened.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnUnopened.java
index 79b39b0..f1b1d45 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnUnopened.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/torrent/ColumnUnopened.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 19, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -26,6 +28,7 @@ import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
 import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
 
 import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
+import com.aelitis.azureus.ui.common.table.TableRowCore;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
 
 import org.gudy.azureus2.plugins.download.Download;
@@ -95,12 +98,20 @@ public class ColumnUnopened
 				Object[] dataSources = (Object[])target;
 				
 				for ( Object _ds: dataSources ){
-										
-					DownloadManager dm = (DownloadManager)_ds;
-					
-					boolean x = PlatformTorrentUtils.getHasBeenOpened( dm );
-					
-					PlatformTorrentUtils.setHasBeenOpened(dm, !x );
+
+					if (_ds instanceof TableRowCore) {
+						TableRowCore row = (TableRowCore) _ds;
+						_ds = row.getDataSource(true);
+					}
+
+					if ( _ds instanceof DownloadManager ){
+						
+						DownloadManager dm = (DownloadManager)_ds;
+						
+						boolean x = PlatformTorrentUtils.getHasBeenOpened( dm );
+						
+						PlatformTorrentUtils.setHasBeenOpened(dm, !x );
+					}
 				}
 			}
 		});
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/utils/ColumnImageClickArea.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/utils/ColumnImageClickArea.java
index 2ee726e..7be39bb 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/utils/ColumnImageClickArea.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/utils/ColumnImageClickArea.java
@@ -1,10 +1,12 @@
 /**
  * Created on April 29, 2007 
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/utils/TableColumnCreatorV3.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/utils/TableColumnCreatorV3.java
index f2b0fce..00c2b4c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/utils/TableColumnCreatorV3.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/utils/TableColumnCreatorV3.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.columns.utils;
 
 import java.lang.reflect.Constructor;
@@ -110,7 +128,6 @@ public class TableColumnCreatorV3
 			}
 		}
 
-		System.out.println("upgradeColumns; old=" + oldOrder.length + ";cur=" + listCurrentOrder.size() + ";" + Debug.getCompressedStackTrace());
 		if (oldOrder.length == listCurrentOrder.size()) {
 			List<String> listOldOrder = Arrays.asList(oldOrder);
 			if (listOldOrder.containsAll(listCurrentOrder)) {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityActions.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityActions.java
index 119c991..36ac043 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityActions.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityActions.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 25, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -144,7 +146,7 @@ public class ColumnActivityActions
 		}
 
 		DownloadManager dm = entry.getDownloadManger();
-		boolean canPlay = PlayUtils.canPlayDS(entry, -1);
+		boolean canPlay = PlayUtils.canPlayDS(entry, -1,false);
 		boolean canDL = dm == null && entry.getDownloadManger() == null
 				&& (entry.getTorrent() != null || entry.getAssetHash() != null);
 		boolean canRun = !canPlay && dm != null;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityDate.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityDate.java
index 022a726..63512bc 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityDate.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityDate.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 25, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityNew.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityNew.java
index e5a501c..3cfa8e6 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityNew.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityNew.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 25, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityText.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityText.java
index 115beb5..764a485 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityText.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityText.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 25, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityType.java b/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityType.java
index 848a044..d84e6f2 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityType.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/columns/vuzeactivity/ColumnActivityType.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 25, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceInfoArea.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceInfoArea.java
index f9f5151..ff1be85 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceInfoArea.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceInfoArea.java
@@ -1,10 +1,12 @@
 /**
  * Created on Mar 2, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceInternetView.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceInternetView.java
index 020d927..72d4b6e 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceInternetView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceInternetView.java
@@ -1,462 +1,464 @@
-/*
- * Created on Feb 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.ui.swt.devices;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.StyleRange;
-import org.eclipse.swt.custom.StyledText;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Color;
-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.Label;
-import org.gudy.azureus2.core3.util.AEThread2;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.ui.swt.Messages;
-import org.gudy.azureus2.ui.swt.mainwindow.Colors;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
-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.devices.Device;
-import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
-import com.aelitis.azureus.plugins.net.netstatus.NetStatusPlugin;
-import com.aelitis.azureus.plugins.net.netstatus.swt.NetStatusPluginTester;
-
-public class 
-DeviceInternetView 
-	extends DeviceManagerUI.categoryView
-{
-	private DeviceManagerUI		device_manager_ui;
-	
-	private NetStatusPlugin		plugin;
-	
-	private Composite		main;
-
-	private Button			start_button;
-	private Button			cancel_button;
-	private StyledText 		log;
-	
-	private static final int				
-		selected_tests = 	NetStatusPluginTester.TEST_INBOUND | 
-							NetStatusPluginTester.TEST_OUTBOUND |
-							NetStatusPluginTester.TEST_NAT_PROXIES;
-	
-	private NetStatusPluginTester		current_test;
-	
-	private static final int LOG_NORMAL 	= 1;
-	private static final int LOG_SUCCESS 	= 2;
-	private static final int LOG_ERROR 		= 3;
-	private static final int LOG_INFO 		= 4;
-	
-	private int	log_type	= LOG_NORMAL;
-
-	protected
-	DeviceInternetView(
-		DeviceManagerUI	dm_ui,
-		String			title )
-	{
-		super( dm_ui, Device.DT_INTERNET, title );
-		
-		device_manager_ui	= dm_ui;
-	}
-	
-	public void 
-	initialize(
-		Composite parent )
-	{  
-		PluginInterface pi = device_manager_ui.getPluginInterface().getPluginManager().getPluginInterfaceByClass( NetStatusPlugin.class  );
-		
-		plugin = (NetStatusPlugin)pi.getPlugin();
-		
-		main = new Composite( parent, SWT.NONE);
-		GridLayout layout = new GridLayout();
-		layout.numColumns = 1;
-		layout.marginTop = 4;
-		layout.marginBottom = 4;
-		layout.marginHeight = 4;
-		layout.marginWidth = 4;
-		main.setLayout(layout);
-		GridData grid_data = new GridData(GridData.FILL_BOTH );
-		main.setLayoutData(grid_data);
-		
-		Label info_lab = new Label( main, SWT.NONE );
-		
-		info_lab.setText( "Test your internet connection" );
-		
-			// control
-		
-		Composite control = new Composite(main, SWT.NONE);
-		layout = new GridLayout();
-		layout.numColumns = 3;
-		layout.marginHeight = 4;
-		layout.marginWidth = 4;
-		control.setLayout(layout);
-
-		grid_data = new GridData(GridData.FILL_HORIZONTAL);
-		grid_data.horizontalSpan = 1;
-		control.setLayoutData(grid_data);
-
-				// start
-		
-			start_button = new Button( control, SWT.PUSH );
-				
-		 	Messages.setLanguageText( start_button, "ConfigView.section.start");
-		 	
-		 	start_button.addSelectionListener(
-		 		new SelectionAdapter()
-		 		{
-		 			public void
-		 			widgetSelected(
-		 				SelectionEvent e )
-		 			{
-		 				start_button.setEnabled( false );
-		 				
-		 				cancel_button.setEnabled( true );
-		 				
-		 				startTest();
-		 			}
-		 		});
-		 	
-		 		// cancel
-		 	
-		 	cancel_button = new Button( control, SWT.PUSH );
-		 	
-		 	Messages.setLanguageText( cancel_button, "UpdateWindow.cancel");
-		 	
-		 	cancel_button.addSelectionListener(
-		 		new SelectionAdapter()
-		 		{
-		 			public void
-		 			widgetSelected(
-		 				SelectionEvent e )
-		 			{
-		 				cancel_button.setEnabled( false );
-		 						 				
-		 				cancelTest();
-		 			}
-		 		});
-		
-		 	cancel_button.setEnabled( false );
-		 	
-				
-			// log area
-		
-		log = new StyledText(main,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
-		grid_data = new GridData(GridData.FILL_BOTH);
-		grid_data.horizontalSpan = 1;
-		grid_data.horizontalIndent = 4;
-		log.setLayoutData(grid_data);
-		log.setIndent( 4 );
-	}
-	
-	protected void
-	startTest()
-	{
-		CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD,
-				new AzureusCoreRunningListener() {
-					public void azureusCoreRunning(AzureusCore core) {
-						startTestSupport(core);
-					}
-				});
-	}
-	
-	protected void
-	cancelTest()
-	{
-		new AEThread2( "NetStatus:cancel", true )
-			{
-				public void
-				run()
-				{
-					cancelTestSupport();
-				}
-			}.start();
-	}
-	
-	protected void
-	startTestSupport(
-			AzureusCore core)
-	{
-		try{
-			synchronized( this ){
-				
-				if ( current_test != null ){
-					
-					Debug.out( "Test already running!!!!" );
-					
-					return;
-				}
-				
-				int tests = selected_tests;
-				
-				if ( NetworkAdmin.getSingleton().isIPV6Enabled()){
-					
-					tests |= NetStatusPluginTester.TEST_IPV6;
-				}
-				
-				current_test = 
-					new NetStatusPluginTester(
-						plugin,
-						tests,
-						new NetStatusPluginTester.loggerProvider()
-						{
-							public void 
-							log(
-								String str) 
-							{
-								println( str );
-							}
-							
-							public void 
-							logSuccess(
-								String str) 
-							{
-								try{
-									log_type = LOG_SUCCESS;
-									
-									println( str );
-									
-								}finally{
-									
-									log_type = LOG_NORMAL;
-								}
-							}
-							
-							public void 
-							logInfo(
-								String str) 
-							{
-								try{
-									log_type = LOG_INFO;
-									
-									println( str );
-									
-								}finally{
-									
-									log_type = LOG_NORMAL;
-								}
-							}
-							
-							public void 
-							logFailure(
-								String str) 
-							{
-								try{
-									log_type = LOG_ERROR;
-									
-									println( str );
-									
-								}finally{
-									
-									log_type = LOG_NORMAL;
-								}
-							}
-						});
-			}
-			
-			println( "Test starting", true );
-			
-			current_test.run(core);
-			
-			println( current_test.isCancelled()?"Test Cancelled":"Test complete" );
-			
-		}catch( Throwable e ){
-			
-		}finally{
-			
-			try{
-				Composite c = main;
-				
-				if ( c != null && !c.isDisposed()){
-					
-					try{
-						c.getDisplay().asyncExec(
-							new Runnable()
-							{
-								public void
-								run()
-								{
-									if ( !start_button.isDisposed()){
-										
-										start_button.setEnabled( true );
-									}
-									
-									if ( !cancel_button.isDisposed()){
-										
-										cancel_button.setEnabled( false );
-									}
-								}
-							});
-						
-					}catch( Throwable e ){
-					}
-				}
-			}finally{
-				
-				synchronized( this ){
-
-					current_test.cancel();
-					
-					current_test = null;
-				}
-			}
-		}
-	}
-	
-	protected void
-	println(
-		String		str )
-	{
-		print( str + "\n", false );
-	}
-	
-	protected void
-	println(
-		String		str,
-		boolean		clear_first )
-	{
-		print( str + "\n", clear_first );
-	}
-	
-	protected void
-	print(
-		final String		str,
-		final boolean		clear_first )
-	{		
-		if ( !( log.isDisposed() || log.getDisplay().isDisposed())){
-			
-			final int f_log_type = log_type;
-			
-			log.getDisplay().asyncExec(
-					new Runnable()
-					{
-						public void
-						run()
-						{
-							if ( log.isDisposed()){
-								
-								return;
-							}
-							
-							int	start;
-							
-							if ( clear_first ){
-							
-								start	= 0;
-								
-								log.setText( str );
-								
-							}else{
-							
-								start = log.getText().length();
-								
-								log.append( str );
-							}
-							
-							Color 	color;
-							
-							if ( f_log_type == LOG_NORMAL ){
-								
-								color = Colors.black;
-								
-							}else if ( f_log_type == LOG_SUCCESS ){
-								
-								color = Colors.green;
-															
-							}else if ( f_log_type == LOG_INFO ){
-								
-								color = Colors.blue;
-								
-							}else{
-								
-								color = Colors.red;
-							}
-							
-							StyleRange styleRange = new StyleRange();
-							styleRange.start = start;
-							styleRange.length = str.length();
-							styleRange.foreground = color;
-							log.setStyleRange(styleRange);
-							
-							log.setSelection( log.getText().length());
-						}
-					});
-		}
-	}
-	
-	protected void
-	cancelTestSupport()
-	{
-		synchronized( this ){
-			
-			if ( current_test != null ){
-				
-				println( "Cancelling test..." );
-				
-				current_test.cancel();
-			}
-		}
-	}
-	
-	public Composite 
-	getComposite()
-	{
-		return( main );
-	}
-
-	public boolean eventOccurred(UISWTViewEvent event) {
-    switch (event.getType()) {
-      case UISWTViewEvent.TYPE_CREATE:
-      	//swtView = (UISWTView)event.getData();
-        break;
-
-      case UISWTViewEvent.TYPE_DESTROY:
-        break;
-
-      case UISWTViewEvent.TYPE_INITIALIZE:
-        initialize((Composite)event.getData());
-        break;
-
-      case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
-      	Messages.updateLanguageForControl(getComposite());
-        break;
-
-      case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
-        break;
-        
-      case UISWTViewEvent.TYPE_FOCUSGAINED:
-      	break;
-        
-      case UISWTViewEvent.TYPE_REFRESH:
-        break;
-    }
-
-    return true;
-  }
-}
+/*
+ * Created on Feb 2, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.devices;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+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.Label;
+import org.gudy.azureus2.core3.util.AEThread2;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.mainwindow.Colors;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+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.devices.Device;
+import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
+import com.aelitis.azureus.plugins.net.netstatus.NetStatusPlugin;
+import com.aelitis.azureus.plugins.net.netstatus.swt.NetStatusPluginTester;
+
+public class 
+DeviceInternetView 
+	extends DeviceManagerUI.categoryView
+{
+	private DeviceManagerUI		device_manager_ui;
+	
+	private NetStatusPlugin		plugin;
+	
+	private Composite		main;
+
+	private Button			start_button;
+	private Button			cancel_button;
+	private StyledText 		log;
+	
+	private static final int				
+		selected_tests = 	NetStatusPluginTester.TEST_INBOUND | 
+							NetStatusPluginTester.TEST_OUTBOUND |
+							NetStatusPluginTester.TEST_NAT_PROXIES |
+							NetStatusPluginTester.TEST_VUZE_SERVICES |
+							NetStatusPluginTester.TEST_PROXY_CONNECT;
+	
+	private NetStatusPluginTester		current_test;
+	
+	private static final int LOG_NORMAL 	= 1;
+	private static final int LOG_SUCCESS 	= 2;
+	private static final int LOG_ERROR 		= 3;
+	private static final int LOG_INFO 		= 4;
+	
+	private int	log_type	= LOG_NORMAL;
+
+	protected
+	DeviceInternetView(
+		DeviceManagerUI	dm_ui,
+		String			title )
+	{
+		super( dm_ui, Device.DT_INTERNET, title );
+		
+		device_manager_ui	= dm_ui;
+	}
+	
+	public void 
+	initialize(
+		Composite parent )
+	{  
+		PluginInterface pi = device_manager_ui.getPluginInterface().getPluginManager().getPluginInterfaceByClass( NetStatusPlugin.class  );
+		
+		plugin = (NetStatusPlugin)pi.getPlugin();
+		
+		main = new Composite( parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 1;
+		layout.marginTop = 4;
+		layout.marginBottom = 4;
+		layout.marginHeight = 4;
+		layout.marginWidth = 4;
+		main.setLayout(layout);
+		GridData grid_data = new GridData(GridData.FILL_BOTH );
+		main.setLayoutData(grid_data);
+		
+		Label info_lab = new Label( main, SWT.NONE );
+		
+		Messages.setLanguageText( info_lab, "label.test.internet");
+		
+			// control
+		
+		Composite control = new Composite(main, SWT.NONE);
+		layout = new GridLayout();
+		layout.numColumns = 3;
+		layout.marginHeight = 4;
+		layout.marginWidth = 4;
+		control.setLayout(layout);
+
+		grid_data = new GridData(GridData.FILL_HORIZONTAL);
+		grid_data.horizontalSpan = 1;
+		control.setLayoutData(grid_data);
+
+				// start
+		
+			start_button = new Button( control, SWT.PUSH );
+				
+		 	Messages.setLanguageText( start_button, "ConfigView.section.start");
+		 	
+		 	start_button.addSelectionListener(
+		 		new SelectionAdapter()
+		 		{
+		 			public void
+		 			widgetSelected(
+		 				SelectionEvent e )
+		 			{
+		 				start_button.setEnabled( false );
+		 				
+		 				cancel_button.setEnabled( true );
+		 				
+		 				startTest();
+		 			}
+		 		});
+		 	
+		 		// cancel
+		 	
+		 	cancel_button = new Button( control, SWT.PUSH );
+		 	
+		 	Messages.setLanguageText( cancel_button, "UpdateWindow.cancel");
+		 	
+		 	cancel_button.addSelectionListener(
+		 		new SelectionAdapter()
+		 		{
+		 			public void
+		 			widgetSelected(
+		 				SelectionEvent e )
+		 			{
+		 				cancel_button.setEnabled( false );
+		 						 				
+		 				cancelTest();
+		 			}
+		 		});
+		
+		 	cancel_button.setEnabled( false );
+		 	
+				
+			// log area
+		
+		log = new StyledText(main,SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+		grid_data = new GridData(GridData.FILL_BOTH);
+		grid_data.horizontalSpan = 1;
+		grid_data.horizontalIndent = 4;
+		log.setLayoutData(grid_data);
+		log.setIndent( 4 );
+	}
+	
+	protected void
+	startTest()
+	{
+		CoreWaiterSWT.waitForCore(TriggerInThread.NEW_THREAD,
+				new AzureusCoreRunningListener() {
+					public void azureusCoreRunning(AzureusCore core) {
+						startTestSupport(core);
+					}
+				});
+	}
+	
+	protected void
+	cancelTest()
+	{
+		new AEThread2( "NetStatus:cancel", true )
+			{
+				public void
+				run()
+				{
+					cancelTestSupport();
+				}
+			}.start();
+	}
+	
+	protected void
+	startTestSupport(
+			AzureusCore core)
+	{
+		try{
+			synchronized( this ){
+				
+				if ( current_test != null ){
+					
+					Debug.out( "Test already running!!!!" );
+					
+					return;
+				}
+				
+				int tests = selected_tests;
+				
+				if ( NetworkAdmin.getSingleton().isIPV6Enabled()){
+					
+					tests |= NetStatusPluginTester.TEST_IPV6;
+				}
+				
+				current_test = 
+					new NetStatusPluginTester(
+						plugin,
+						tests,
+						new NetStatusPluginTester.loggerProvider()
+						{
+							public void 
+							log(
+								String 		str,
+								boolean		detailed )
+							{
+								println( str );
+							}
+							
+							public void 
+							logSuccess(
+								String str) 
+							{
+								try{
+									log_type = LOG_SUCCESS;
+									
+									println( str );
+									
+								}finally{
+									
+									log_type = LOG_NORMAL;
+								}
+							}
+							
+							public void 
+							logInfo(
+								String str) 
+							{
+								try{
+									log_type = LOG_INFO;
+									
+									println( str );
+									
+								}finally{
+									
+									log_type = LOG_NORMAL;
+								}
+							}
+							
+							public void 
+							logFailure(
+								String str) 
+							{
+								try{
+									log_type = LOG_ERROR;
+									
+									println( str );
+									
+								}finally{
+									
+									log_type = LOG_NORMAL;
+								}
+							}
+						});
+			}
+			
+			println( "Test starting", true );
+			
+			current_test.run(core);
+			
+			println( current_test.isCancelled()?"Test Cancelled":"Test complete" );
+			
+		}catch( Throwable e ){
+			
+		}finally{
+			
+			try{
+				Composite c = main;
+				
+				if ( c != null && !c.isDisposed()){
+					
+					try{
+						c.getDisplay().asyncExec(
+							new Runnable()
+							{
+								public void
+								run()
+								{
+									if ( !start_button.isDisposed()){
+										
+										start_button.setEnabled( true );
+									}
+									
+									if ( !cancel_button.isDisposed()){
+										
+										cancel_button.setEnabled( false );
+									}
+								}
+							});
+						
+					}catch( Throwable e ){
+					}
+				}
+			}finally{
+				
+				synchronized( this ){
+
+					current_test.cancel();
+					
+					current_test = null;
+				}
+			}
+		}
+	}
+	
+	protected void
+	println(
+		String		str )
+	{
+		print( str + "\n", false );
+	}
+	
+	protected void
+	println(
+		String		str,
+		boolean		clear_first )
+	{
+		print( str + "\n", clear_first );
+	}
+	
+	protected void
+	print(
+		final String		str,
+		final boolean		clear_first )
+	{		
+		if ( !( log.isDisposed() || log.getDisplay().isDisposed())){
+			
+			final int f_log_type = log_type;
+			
+			log.getDisplay().asyncExec(
+					new Runnable()
+					{
+						public void
+						run()
+						{
+							if ( log.isDisposed()){
+								
+								return;
+							}
+							
+							int	start;
+							
+							if ( clear_first ){
+							
+								start	= 0;
+								
+								log.setText( str );
+								
+							}else{
+							
+								start = log.getText().length();
+								
+								log.append( str );
+							}
+							
+							Color 	color;
+							
+							if ( f_log_type == LOG_NORMAL ){
+								
+								color = Colors.black;
+								
+							}else if ( f_log_type == LOG_SUCCESS ){
+								
+								color = Colors.green;
+															
+							}else if ( f_log_type == LOG_INFO ){
+								
+								color = Colors.blue;
+								
+							}else{
+								
+								color = Colors.red;
+							}
+							
+							StyleRange styleRange = new StyleRange();
+							styleRange.start = start;
+							styleRange.length = str.length();
+							styleRange.foreground = color;
+							log.setStyleRange(styleRange);
+							
+							log.setSelection( log.getText().length());
+						}
+					});
+		}
+	}
+	
+	protected void
+	cancelTestSupport()
+	{
+		synchronized( this ){
+			
+			if ( current_test != null ){
+				
+				println( "Cancelling test..." );
+				
+				current_test.cancel();
+			}
+		}
+	}
+	
+	public Composite 
+	getComposite()
+	{
+		return( main );
+	}
+
+	public boolean eventOccurred(UISWTViewEvent event) {
+    switch (event.getType()) {
+      case UISWTViewEvent.TYPE_CREATE:
+      	//swtView = (UISWTView)event.getData();
+        break;
+
+      case UISWTViewEvent.TYPE_DESTROY:
+        break;
+
+      case UISWTViewEvent.TYPE_INITIALIZE:
+        initialize((Composite)event.getData());
+        break;
+
+      case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
+      	Messages.updateLanguageForControl(getComposite());
+        break;
+
+      case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
+        break;
+        
+      case UISWTViewEvent.TYPE_FOCUSGAINED:
+      	break;
+        
+      case UISWTViewEvent.TYPE_REFRESH:
+        break;
+    }
+
+    return true;
+  }
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceManagerUI.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceManagerUI.java
index 28e5f28..b5b49a7 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceManagerUI.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DeviceManagerUI.java
@@ -1,5391 +1,5549 @@
-/*
- * 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.ui.swt.devices;
-
-
-import java.io.File;
-import java.net.InetAddress;
-import java.net.URL;
-import java.util.*;
-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.dnd.DND;
-import org.eclipse.swt.dnd.DragSource;
-import org.eclipse.swt.dnd.DragSourceAdapter;
-import org.eclipse.swt.dnd.DragSourceEvent;
-import org.eclipse.swt.dnd.DropTarget;
-import org.eclipse.swt.dnd.TextTransfer;
-import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.MenuAdapter;
-import org.eclipse.swt.events.MenuEvent;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.events.MouseMoveListener;
-import org.eclipse.swt.events.MouseTrackAdapter;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-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.config.COConfigurationManager;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.platform.PlatformManager;
-import org.gudy.azureus2.platform.PlatformManagerFactory;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.PluginManager;
-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.*;
-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.tables.TableContextMenuItem;
-import org.gudy.azureus2.plugins.ui.tables.TableManager;
-import org.gudy.azureus2.plugins.ui.tables.TableRow;
-import org.gudy.azureus2.plugins.utils.StaticUtilities;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.ui.swt.*;
-import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
-import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
-import org.gudy.azureus2.ui.swt.plugins.*;
-import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
-import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
-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.core.AzureusCoreRunningListener;
-import com.aelitis.azureus.core.devices.*;
-import com.aelitis.azureus.core.devices.DeviceManager.DeviceManufacturer;
-import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice;
-import com.aelitis.azureus.core.download.DiskManagerFileInfoFile;
-import com.aelitis.azureus.core.download.DiskManagerFileInfoStream;
-import com.aelitis.azureus.core.download.DiskManagerFileInfoURL;
-import com.aelitis.azureus.core.download.StreamManager;
-import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger;
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-import com.aelitis.azureus.ui.UIFunctions;
-import com.aelitis.azureus.ui.UIFunctionsManager;
-import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
-import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager;
-import com.aelitis.azureus.ui.mdi.*;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.devices.add.*;
-import com.aelitis.azureus.ui.swt.devices.add.DeviceTemplateChooser.DeviceTemplateClosedListener;
-import com.aelitis.azureus.ui.swt.devices.add.ManufacturerChooser.ClosedListener;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
-import com.aelitis.azureus.ui.swt.imageloader.ImageLoader.ImageDownloaderListener;
-import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
-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.SkinViewManager.SkinViewManagerListener;
-import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
-import com.aelitis.azureus.util.PlayUtils;
-import com.aelitis.net.upnpms.UPNPMSBrowser;
-import com.aelitis.net.upnpms.UPNPMSBrowserFactory;
-import com.aelitis.net.upnpms.UPNPMSBrowserListener;
-import com.aelitis.net.upnpms.UPNPMSContainer;
-import com.aelitis.net.upnpms.UPNPMSItem;
-import com.aelitis.net.upnpms.UPNPMSNode;
-import com.aelitis.net.upnpms.UPnPMSException;
-
-public class 
-DeviceManagerUI 
-{
-	// Not supported for Unix and OSX PPC
-	public static boolean DISABLED;
-	
-	private static final int MIN_FILE_SIZE_FOR_XCODE	= 128*1024;
-	private static final int MAX_FILES_FOR_MULTI_XCODE	= 64;
-	
-	private static final Object	DEVICE_IVIEW_KEY = new Object();
-	
-	private static final String CONFIG_VIEW_TYPE				= "device.sidebar.ui.viewtype";
-	
-	public static final String CONFIG_VIEW_HIDE_REND_GENERIC	= DeviceManager.CONFIG_VIEW_HIDE_REND_GENERIC;
-	public static final String CONFIG_VIEW_SHOW_ONLY_TAGGED		= DeviceManager.CONFIG_VIEW_SHOW_ONLY_TAGGED;
-	
-	private static final String SPINNER_IMAGE_ID 	= "image.sidebar.vitality.dl";
-	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_RENDERER_VITALITY 	= false;
-	private static final boolean	SHOW_OD_VITALITY 		= true;
-	
-	//private static final String[] to_copy_indicator_colors = { "#000000", "#000000", "#168866", "#1c5620" };
-	
-	private DeviceManager			device_manager;
-	private DeviceManagerListener	device_manager_listener;
-	private boolean					device_manager_listener_added;
-	
-	private final PluginInterface	plugin_interface;
-	private final UIManager			ui_manager;
-	
-	private UISWTInstance			swt_ui;
-	
-	private boolean		ui_setup;
-	
-	private MultipleDocumentInterfaceSWT		mdi;
-	private boolean		sidebar_built;
-	
-	private static final int SBV_SIMPLE		= 0;
-	private static final int SBV_FULL		= 0x7FFFFFFF;
-	
-	private int			side_bar_view_type		= COConfigurationManager.getIntParameter( CONFIG_VIEW_TYPE, SBV_SIMPLE );
-	private boolean		side_bar_hide_rend_gen	= COConfigurationManager.getBooleanParameter( CONFIG_VIEW_HIDE_REND_GENERIC, true );
-	private boolean		side_bar_show_tagged	= COConfigurationManager.getBooleanParameter( CONFIG_VIEW_SHOW_ONLY_TAGGED, false );
-	
-	private int			next_sidebar_id;
-		
-	private List<categoryView>	categories = new ArrayList<categoryView>();
-	
-	
-	private MenuItemListener properties_listener;
-	private MenuItemListener hide_listener;
-	private MenuItemListener rename_listener;
-	private MenuItemListener export_listener;
-	
-	private MenuItemFillListener	will_remove_listener;
-	private MenuItemListener 		remove_listener;
-	
-	private MenuItemFillListener	show_fill_listener;
-	private MenuItemListener 		show_listener;
-
-	private MenuItemFillListener	will_tag_listener;
-	private MenuItemListener 		tag_listener;
-
-	private MenuItemFillListener will_browse_listener;
-	
-	private boolean	offline_menus_setup;
-
-	private MdiEntry mdiEntryOverview;
-
-	private boolean needsAddAllDevices;
-
-	private MdiEntry entryHeader;
-	
-	private static final String	OXC_NOTHING		= "Nothing";
-	private static final String	OXC_QUIT_VUZE	= AzureusCore.CA_QUIT_VUZE;
-	private static final String	OXC_SLEEP		= AzureusCore.CA_SLEEP;
-	private static final String	OXC_HIBERNATE	= AzureusCore.CA_HIBERNATE;
-	private static final String	OXC_SHUTDOWN	= AzureusCore.CA_SHUTDOWN;
-	
-	private String 	oxc_action		= OXC_NOTHING;
-	private boolean	oxc_trigger_set	= false;
-	
-	private static final int	MAX_MS_DISPLAY_LINE_DEFAULT = 5000;
-	
-	private static int	max_ms_display_lines;
-	
-	static{
-		COConfigurationManager.addAndFireParameterListener(
-			"Plugin.default.device.config.ms.maxlines",
-			new org.gudy.azureus2.core3.config.ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					String name ) 
-				{
-					max_ms_display_lines = COConfigurationManager.getIntParameter( name, MAX_MS_DISPLAY_LINE_DEFAULT );
-				}
-			});
-	}
-	static {
-		try {
-  		if (Constants.isOSX) {
-  			String arch = System.getProperty("os.arch", "");
-  			DISABLED = arch.equalsIgnoreCase("powerpc") || arch.equalsIgnoreCase("ppc");
-  		} else {
-  			DISABLED = Constants.isUnix;
-  		}
-  		DISABLED |= Utils.isAZ2UI();
-		} catch (Throwable t) {
-			// Benefit of the doubt?
-			DISABLED = false;
-		}
-	}
-	
-	public
-	DeviceManagerUI(
-		AzureusCore			core )
-	{
-		plugin_interface = PluginInitializer.getDefaultInterface();
-		
-		ui_manager = plugin_interface.getUIManager();
-
-		if (DISABLED) {
-			return;
-		}
-
-		ui_manager.addUIListener(
-				new UIManagerListener()
-				{
-					public void
-					UIAttached(
-						UIInstance		instance )
-					{
-						if ( instance instanceof UISWTInstance ){
-							
-							swt_ui	= (UISWTInstance)instance;
-							
-							AzureusCoreFactory.addCoreRunningListener(
-								new AzureusCoreRunningListener() 
-								{
-									public void 
-									azureusCoreRunning(
-										AzureusCore core )
-									{
-										uiAttachedAndCoreRunning(core);
-
-									}
-								});
-
-						}
-					}
-					
-					public void
-					UIDetached(
-						UIInstance		instance )
-					{
-					}
-				});
-	}
-
-	private void uiAttachedAndCoreRunning(AzureusCore core) {
-		Utils.execSWTThread(new AERunnable() {
-			public void runSupport() {
-				MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
-				
-				if (mdi != null) {
-					
-					setupUI(mdi);
-				} else {
-					
-					SkinViewManager.addListener(new SkinViewManagerListener() {
-						public void skinViewAdded(SkinView skinview) {
-							
-							if (skinview instanceof SideBar) {
-								
-								setupUI((SideBar) skinview);
-								SkinViewManager.RemoveListener(this);
-							}
-						}
-					});
-				}
-			}
-		});
-		
-		UIExitUtilsSWT.addListener(
-			new UIExitUtilsSWT.canCloseListener()
-			{
-				public boolean 
-				canClose() 
-				{
-					try{
-						if ( device_manager == null ){
-							
-								// not yet init, safe to close
-							
-							return( true );
-						}
-						
-						final TranscodeJob job = device_manager.getTranscodeManager().getQueue().getCurrentJob();
-
-						if ( job == null || job.getState() != TranscodeJob.ST_RUNNING ){
-
-							return( true );
-						}
-
-						if ( job.getTranscodeFile().getDevice().isHidden()){
-							
-							// The assumption here is that if the device is hidden either the user shouldn't be concerned
-							// about the loss of active transcode as either it is something that they don't know about or
-							// alternative canClose listeners have been registered to handle the situation (e.g. burn-in-progress)
-
-							return( true );
-						}
-						
-						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 ( Throwable e ){
-						
-						Debug.out(e);
-						
-						return true;
-					}
-				}
-			});
-	}
-
-
-	protected DeviceManager
-	getDeviceManager()
-	{
-		return( device_manager );
-	}
-	
-	protected PluginInterface
-	getPluginInterface()
-	{
-		return( plugin_interface );
-	}
-	
-	protected void
-	setupUI(
-		MultipleDocumentInterfaceSWT			mdi )	
-	{
-		synchronized( this ){
-			
-			if ( ui_setup ){
-				
-				return;
-			}
-			
-			ui_setup = true;
-		}
-		
-		this.mdi		= mdi;
-
-		device_manager 	= DeviceManagerFactory.getSingleton();
-		
-		setupMenuListeners();
-
-		mdi.registerEntry(SideBar.SIDEBAR_SECTION_DEVICES,
-				new MdiEntryCreationListener() {
-					public MdiEntry createMDiEntry(String id) {
-						if ( sidebar_built ){
-							removeAllDevices();
-							
-							buildSideBar( true );
-						} else {
-							buildSideBar(false);
-						}
-							
-						addAllDevices();
-						return mdiEntryOverview;
-					}
-				});
-
-		
-		device_manager.addListener(new DeviceManagerListener() {
-		
-			public void deviceRemoved(Device device) {
-			}
-		
-			public void deviceManagerLoaded() {
-				device_manager.removeListener(this);
-				setupUIwithDeviceManager();
-			}
-		
-			public void deviceChanged(Device device) {
-			}
-		
-			public void deviceAttentionRequest(Device device) {
-			}
-		
-			public void deviceAdded(Device device) {
-			}
-		});
-	}
-
-	
-	private void
-	setupUIwithDeviceManager()
-	{
-		boolean	add_all = false;
-		
-		synchronized( this ){
-			
-			device_manager_listener = 
-				new DeviceManagerListener()
-				{
-					public void 
-					deviceAdded(
-						Device device ) 
-					{
-						addOrChangeDevice( device );
-					}
-					
-					public void
-					deviceChanged(
-						Device		device )
-					{
-						addOrChangeDevice( device );
-					}
-					
-					public void
-					deviceAttentionRequest(
-						Device		device )
-					{
-						showDevice( device );
-					}
-					
-					public void
-					deviceRemoved(
-						Device		device )
-					{
-						removeDevice( device );
-					}
-					
-					public void 
-					deviceManagerLoaded() {
-					}
-				};
-				
-			if ( needsAddAllDevices ){
-				
-				add_all = true;
-				
-				needsAddAllDevices = false;
-			}
-		}
-		
-		TranscodeManager transMan = device_manager.getTranscodeManager();
-
-		TranscodeQueue transQ = transMan.getQueue();
-
-		transQ.addListener(
-				new TranscodeQueueListener()
-				{
-					int	last_job_count = 0;
-
-					public void
-					jobAdded(
-							TranscodeJob		job )
-					{
-						check();
-					}
-
-					public void
-					jobChanged(
-							TranscodeJob		job )
-					{
-						check();
-					}
-
-					public void
-					jobRemoved(
-							TranscodeJob		job )
-					{
-						check();
-					}
-
-					protected void
-					check()
-					{
-						try{
-							int job_count = device_manager.getTranscodeManager().getQueue().getJobCount();
-	
-							if ( job_count != last_job_count ){
-	
-								if ( job_count == 0 || last_job_count == 0 ){
-	
-									MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-	
-									if ( mdi != null ){
-	
-										MdiEntry main_entry = mdi.getEntry( SideBar.SIDEBAR_SECTION_DEVICES );
-	
-										if ( main_entry != null ){
-	
-											ViewTitleInfoManager.refreshTitleInfo( main_entry.getViewTitleInfo());
-										}
-									}
-								}
-	
-								last_job_count = job_count;
-							}
-						}finally{
-							
-							checkOXCState();
-						}
-					}
-				});
-		
-		setupListeners();
-		
-		//buildSideBar( false );
-		
-		setupConfigUI(); // MDIEntry not required
-
-		if ( add_all ){
-			
-			addAllDevices();
-		}
-		
-		setupTranscodeMenus(); // MDIEntry not required
-	}
-	
-	public void setupConfigUI() {
-		BasicPluginConfigModel configModel = ui_manager.createBasicPluginConfigModel(
-				ConfigSection.SECTION_ROOT, "Devices");
-
-			// auto search
-		
-		final BooleanParameter as = 
-			configModel.addBooleanParameter2( 
-				"device.search.auto", "device.search.auto",
-				device_manager.getAutoSearch());
-		
-		as.addListener(
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					Parameter param) 
-				{
-					device_manager.setAutoSearch( as.getValue());
-					
-					if ( device_manager.getAutoSearch()){
-						
-						search();
-					}
-				}
-			});
-		
-		final BooleanParameter qosParam = configModel.addBooleanParameter2(
-				PlatformDevicesMessenger.CFG_SEND_QOS, "devices.turnon.qos", false);
-		
-			// send qos
-		
-		qosParam.setValue(COConfigurationManager.getBooleanParameter( PlatformDevicesMessenger.CFG_SEND_QOS, false));
-		
-		qosParam.addListener(
-			new ParameterListener() {
-				public void parameterChanged(Parameter param) {
-					COConfigurationManager.setParameter(
-							PlatformDevicesMessenger.CFG_SEND_QOS, qosParam.getValue());
-				}
-			});
-
-			// config - simple view
-		
-		final BooleanParameter config_simple_view = 
-			configModel.addBooleanParameter2( 
-				CONFIG_VIEW_TYPE, "devices.sidebar.simple",
-				side_bar_view_type == SBV_SIMPLE );
-		
-		config_simple_view.addListener(
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					Parameter param) 
-				{
-					COConfigurationManager.setParameter( CONFIG_VIEW_TYPE, config_simple_view.getValue()?SBV_SIMPLE:SBV_FULL );
-				}
-			});	
-		
-		COConfigurationManager.addParameterListener(
-			CONFIG_VIEW_TYPE,
-			new org.gudy.azureus2.core3.config.ParameterListener()
-			{
-				public void 
-				parameterChanged(String 
-					parameterName ) 
-				{
-					config_simple_view.setValue( COConfigurationManager.getIntParameter( CONFIG_VIEW_TYPE, SBV_SIMPLE ) == SBV_SIMPLE );
-				}
-			});
-			
-			// generic devices
-		
-		configModel.addBooleanParameter2( 
-				"!" + CONFIG_VIEW_HIDE_REND_GENERIC + "!", "devices.sidebar.hide.rend.generic",
-				side_bar_hide_rend_gen );
-		
-		configModel.addBooleanParameter2( 
-				"!" + CONFIG_VIEW_SHOW_ONLY_TAGGED + "!", "devices.sidebar.show.only.tagged",
-				side_bar_show_tagged );
-
-			// auto-hide old devices
-		
-		final IntParameter auto_hide_old = 
-			configModel.addIntParameter2(
-				"device.config.autohide.old.devices", "device.config.autohide.old.devices",
-				device_manager.getAutoHideOldDevicesDays(), 0, 2048 );
-		
-		auto_hide_old.addListener(
-				new ParameterListener()
-				{
-					public void 
-					parameterChanged(
-						Parameter param) 
-					{
-						device_manager.setAutoHideOldDevicesDays( auto_hide_old.getValue());
-					}
-				});
-		
-		// transcoding
-		
-			// default dir
-		
-		String def = device_manager.getDefaultWorkingDirectory().getAbsolutePath();
-		
-		final DirectoryParameter def_work_dir = configModel.addDirectoryParameter2( "device.config.xcode.workdir", "device.config.xcode.workdir", def );
-		
-		def_work_dir.setValue( def );
-		
-		def_work_dir.addListener(
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					Parameter param ) 
-				{
-					device_manager.setDefaultWorkingDirectory(new File( def_work_dir.getValue()));
-				}
-			});
-		
-			// 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 );
-				}
-			});
-
-			// disable sleep
-		
-		final BooleanParameter disable_sleep = 
-			configModel.addBooleanParameter2( 
-				"device.config.xcode.disable_sleep", "device.config.xcode.disable_sleep",
-				device_manager.getDisableSleep());
-				
-		
-		disable_sleep.addListener(
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					Parameter param) 
-				{
-					device_manager.setDisableSleep( disable_sleep.getValue());
-				}
-			});
-		
-			// itunes
-		
-		final ActionParameter btnITunes = configModel.addActionParameter2("devices.button.installitunes", "UpdateWindow.columns.install");
-		btnITunes.setEnabled(false);
-		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
-			public void azureusCoreRunning(AzureusCore core) {
-				boolean hasItunes = core.getPluginManager().getPluginInterfaceByID(
-						"azitunes") != null;
-				btnITunes.setEnabled(!hasItunes);
-			}
-		});
-
-		btnITunes.addListener(new ParameterListener() {
-			public void parameterChanged(Parameter param) {
-				CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
-					public void azureusCoreRunning(AzureusCore core) {
-						try {
-							PluginInstaller installer = core.getPluginManager().getPluginInstaller();
-							
-							StandardPlugin itunes_plugin = installer.getStandardPlugin("azitunes");
-							
-							if ( itunes_plugin == null ){
-							
-								Debug.out( "iTunes standard plugin not found");
-								
-							}else{
-							
-								itunes_plugin.install(false);
-							}
-						} catch (Throwable e) {
-							
-							Debug.printStackTrace(e);
-						}
-					}
-				});
-			}
-		});
-		
-		configModel.createGroup(
-			"device.xcode.group",
-			new Parameter[]
-			{
-					def_work_dir, max_xcode, disable_sleep, btnITunes
-			});
-		
-		// media servers
-			
-			// max lines
-		
-		final IntParameter max_ms_lines = 
-			configModel.addIntParameter2( 
-				"device.config.ms.maxlines", "device.config.ms.maxlines",
-				MAX_MS_DISPLAY_LINE_DEFAULT, 
-				0, Integer.MAX_VALUE );
-		
-		configModel.createGroup(
-				"device.ms.group",
-				new Parameter[]
-				{
-					max_ms_lines
-				});
-		
-			// 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());
-					
-					rebuildSideBarIfExists();
-				}
-			});
-		
-				// 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,
-			});
-		
-		
-			// play now
-		
-		final StreamManager sm = StreamManager.getSingleton();
-		
-		final IntParameter pn_buffer = 
-			configModel.addIntParameter2( 
-				"device.playnow.buffer", "device.playnow.buffer",
-				sm.getBufferSecs());
-		
-		pn_buffer.addListener(
-				new ParameterListener()
-				{
-					public void 
-					parameterChanged(
-						Parameter param) 
-					{
-						sm.setBufferSecs( pn_buffer.getValue());
-					}
-				});
-		
-		final IntParameter pn_min_buffer = 
-			configModel.addIntParameter2( 
-				"device.playnow.min_buffer", "device.playnow.min_buffer",
-				sm.getMinBufferSecs());
-		
-		pn_min_buffer.addListener(
-				new ParameterListener()
-				{
-					public void 
-					parameterChanged(
-						Parameter param) 
-					{
-						sm.setMinBufferSecs( pn_buffer.getValue());
-					}
-				});
-		
-		configModel.createGroup(
-				"device.playnow.group",
-				new Parameter[]
-				{
-						pn_buffer, pn_min_buffer,
-				});
-			
-		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());
-					
-					rebuildSideBarIfExists();
-				}
-			});
-		
-	}
-	
-	protected void
-	setupMenuListeners()
-	{
-		properties_listener = 
-			new MenuItemListener() 
-			{
-				public void 
-				selected(
-					MenuItem menu, 
-					Object target) 
-				{
-					if (target instanceof MdiEntry) {
-						MdiEntry info = (MdiEntry) target;
-						Device device = (Device)info.getDatasource();
-					
-						showProperties( device );
-					}
-				}
-			};
-		
-		hide_listener = 
-			new MenuItemListener() 
-			{
-				public void 
-				selected(
-					MenuItem menu, 
-					Object target) 
-				{
-					if (target instanceof MdiEntry){
-						
-						MdiEntry info = (MdiEntry) target;
-						
-						Device device = (Device)info.getDatasource();
-					
-						device.setHidden( true );
-					}
-				}
-			};
-		
-		will_tag_listener = 
-				new MenuItemFillListener() 
-				{
-					public void 
-					menuWillBeShown(
-						MenuItem 	menu, 
-						Object 		targets) 
-					{
-						Object[]	rows;
-						
-						if ( targets instanceof Object[] ){
-							
-							rows = (Object[])targets;
-							
-						}else{
-							
-							rows = new Object[]{ targets };
-						}
-						
-						if ( rows.length > 0 && rows[0] instanceof MdiEntry ){
-													
-							MdiEntry info = (MdiEntry)rows[0];
-						
-							Device device = (Device)info.getDatasource();
-							
-							menu.setData( device.isTagged());
-							
-						}else{
-							
-							menu.setEnabled( false );
-						}
-					}
-				};
-				
-		tag_listener = 
-			new MenuItemListener() 
-			{
-				public void 
-				selected(
-					MenuItem menu, 
-					Object target) 
-				{
-					if (target instanceof MdiEntry){
-						
-						MdiEntry info = (MdiEntry) target;
-						
-						Device device = (Device)info.getDatasource();
-					
-						device.setTagged( !device.isTagged());
-					}
-				}
-			};
-				
-		rename_listener = 
-				new MenuItemListener() 
-				{
-					public void 
-					selected(
-						MenuItem menu, 
-						Object target) 
-					{
-						if (target instanceof MdiEntry){
-							
-							MdiEntry info = (MdiEntry) target;
-							
-							final Device device = (Device)info.getDatasource();
-							
-							UISWTInputReceiver entry = (UISWTInputReceiver)swt_ui.getInputReceiver();
-							
-							entry.setPreenteredText(device.getName(), false );
-							
-							entry.maintainWhitespace(false);
-							
-							entry.allowEmptyInput( false );
-							
-							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, false );
-									}
-								}
-							});		
-						}
-					}
-				};
-
-		export_listener = 
-			new MenuItemListener() 
-			{
-				public void 
-				selected(
-					MenuItem menu, 
-					Object target) 
-				{
-					if ( target instanceof MdiEntry){
-						
-						MdiEntry info = (MdiEntry) target;
-						
-						Device device = (Device)info.getDatasource();
-						
-						export( device );
-					}
-				}
-			};
-			
-		will_remove_listener = 
-				new MenuItemFillListener() 
-				{
-					public void 
-					menuWillBeShown(
-						MenuItem 	menu, 
-						Object 		targets) 
-					{
-						Object[]	rows;
-						
-						if ( targets instanceof Object[] ){
-							
-							rows = (Object[])targets;
-							
-						}else{
-							
-							rows = new Object[]{ targets };
-						}
-						
-						if ( rows.length > 0 && rows[0] instanceof MdiEntry ){
-													
-							MdiEntry info = (MdiEntry)rows[0];
-						
-							Device device = (Device)info.getDatasource();
-							
-							menu.setEnabled( device.canRemove());
-							
-						}else{
-							
-							menu.setEnabled( false );
-						}
-					}
-				};
-				
-		remove_listener = 
-			new MenuItemListener() 
-			{
-				public void 
-				selected(
-					MenuItem menu, 
-					Object target) 
-				{
-					if (target instanceof MdiEntry){
-						
-						MdiEntry info = (MdiEntry) target;
-						
-						Device device = (Device)info.getDatasource();
-					
-						device.remove();
-					}
-				}
-			};
-			
-		will_browse_listener = 
-				new MenuItemFillListener() 
-				{
-					public void 
-					menuWillBeShown(
-						MenuItem 	menu, 
-						Object 		targets) 
-					{
-						menu.removeAllChildItems();
-				
-						boolean	enabled = false;
-						
-						Object[]	rows;
-						
-						if ( targets instanceof Object[] ){
-							
-							rows = (Object[])targets;
-							
-						}else{
-							
-							rows = new Object[]{ targets };
-						}
-						
-						if ( rows.length > 0 && rows[0] instanceof MdiEntry ){
-													
-							MdiEntry info = (MdiEntry)rows[0];
-						
-							Device device = (Device)info.getDatasource();
-					
-							Device.browseLocation[] locs = device.getBrowseLocations();
-							
-							enabled = locs != null && locs.length > 0;
-							
-							if ( enabled ){
-								
-								MenuManager menuManager = ui_manager.getMenuManager();
-	
-								for ( final Device.browseLocation loc: locs ){
-								
-									MenuItem loc_menu = menuManager.addMenuItem( menu, loc.getName());
-									
-									loc_menu.addListener(
-										new MenuItemListener()
-										{
-											public void 
-											selected(
-												MenuItem 	menu,
-												Object 		target ) 
-											{
-												Utils.launch( loc.getURL().toExternalForm());
-											}
-										});
-								}
-							}
-						}
-						
-						menu.setEnabled( enabled );
-					}
-				};
-			
-		show_listener = 
-			new MenuItemListener() 
-			{
-				public void 
-				selected(
-					MenuItem menu, 
-					Object target) 
-				{
-					if ( target instanceof MdiEntry ){
-						
-						MdiEntry info = (MdiEntry)target;
-												
-						Object ds = info.getDatasource();
-						
-						if ( ds instanceof Device ){
-							
-								// shouldn't get here really as its hidden :)
-							
-							Device device = (Device)ds;
-					
-							device.setHidden( true );
-							
-						}else{
-							
-							int	category_type = ds==null?Device.DT_UNKNOWN:(Integer)ds;
-							
-							Device[] devices = device_manager.getDevices();
-							
-							for ( Device device: devices ){
-								
-								if ( 	category_type == Device.DT_UNKNOWN ||
-										device.getType() == category_type && device.isHidden()){
-									
-									device.setHidden( false );
-								}
-							}
-						}
-					}
-				}
-			};
-			
-		show_fill_listener = 
-				new MenuItemFillListener() 
-				{
-					public void 
-					menuWillBeShown(
-						MenuItem 	menu, 
-						Object 		targets) 
-					{
-						boolean	enabled = false;
-						
-						Object[]	rows;
-						
-						if ( targets instanceof Object[] ){
-							
-							rows = (Object[])targets;
-							
-						}else{
-							
-							rows = new Object[]{ targets };
-						}
-						
-						for ( Object row: rows ){
-							
-							if ( row instanceof MdiEntry ){
-								
-								MdiEntry info = (MdiEntry)row;
-														
-								Object ds = info.getDatasource();
-								
-								if ( ds instanceof Device ){
-																	
-								}else{
-									
-									int	category_type = ds==null?Device.DT_UNKNOWN:(Integer)ds;
-										
-									Device[] devices = device_manager.getDevices();
-									
-									for ( Device device: devices ){
-										
-										if ( 	category_type == Device.DT_UNKNOWN ||
-												device.getType() == category_type && device.isHidden()){
-											
-											if ( device.isHidden()){
-												
-												enabled = true;
-											}
-										}
-									}
-								}
-							}
-						}
-						
-						menu.setEnabled( enabled );
-					}
-			
-				};
-	}
-	
-	private void 
-	export(
-		final Device	device ) 
-	{
-		Utils.execSWTThread(
-			new AERunnable() 
-			{
-				public void 
-				runSupport()
-				{
-					FileDialog dialog = 
-						new FileDialog( Utils.findAnyShell(), SWT.SYSTEM_MODAL | SWT.SAVE );
-					
-					dialog.setFilterPath( TorrentOpener.getFilterPathData() );
-											
-					dialog.setText(MessageText.getString("device.export.select.template.file"));
-					
-					dialog.setFilterExtensions(new String[] {
-							"*.vuze",
-							"*.vuz",
-							Constants.FILE_WILDCARD
-						});
-					dialog.setFilterNames(new String[] {
-							"*.vuze",
-							"*.vuz",
-							Constants.FILE_WILDCARD
-						});
-					
-					String path = TorrentOpener.setFilterPathData( dialog.open());
-
-					if ( path != null ){
-						
-						String lc = path.toLowerCase();
-						
-						if ( !lc.endsWith( ".vuze" ) && !lc.endsWith( ".vuz" )){
-							
-							path += ".vuze";
-						}
-						
-						try{
-							VuzeFile vf = device.getVuzeFile();
-							
-							vf.write( new File( path ));
-							
-						}catch( Throwable e ){
-							
-							Debug.out( e );
-						}
-					}
-				}
-			});
-	}
-	
-	protected void
-	setupListeners()
-	{
-		COConfigurationManager.addAndFireParameterListeners( 
-			new String[]{
-				CONFIG_VIEW_TYPE,
-				CONFIG_VIEW_HIDE_REND_GENERIC,
-				CONFIG_VIEW_SHOW_ONLY_TAGGED,
-			},
-			new org.gudy.azureus2.core3.config.ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					String parameterName )
-				{
-					side_bar_view_type = COConfigurationManager.getIntParameter( CONFIG_VIEW_TYPE, SBV_SIMPLE );
-					
-					side_bar_hide_rend_gen = COConfigurationManager.getBooleanParameter( CONFIG_VIEW_HIDE_REND_GENERIC, true );
-					
-					side_bar_show_tagged = COConfigurationManager.getBooleanParameter( CONFIG_VIEW_SHOW_ONLY_TAGGED, false );
-
-					rebuildSideBarIfExists();
-				}
-			});
-	}
-	
-	protected static void
-	hideIcon(
-		MdiEntryVitalityImage	x )
-	{
-		if ( x == null ){
-			return;
-		}
-		
-		x.setVisible( false );
-		x.setToolTip( "" );
-	}
-	
-	protected static void
-	showIcon(
-		MdiEntryVitalityImage	x ,
-		String					t )
-	{
-		if ( x == null ){
-			return;
-		}
-		
-		x.setToolTip( t );
-		x.setVisible( true );
-	}
-	
-	protected void
-	rebuildSideBarIfExists()
-	{
-		MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-		
-		if ( mdi != null ){
-		
-			MdiEntry entry = mdi.getEntry( SideBar.SIDEBAR_HEADER_DEVICES );
-		
-			if (entry != null) {
-			
-				rebuildSideBar();
-			}
-		}
-	}
-
-	protected void
-	rebuildSideBar()
-	{
-			
-		if ( sidebar_built ){
-			removeAllDevices();
-			
-			buildSideBar( true );
-		} else {
-			buildSideBar(false);
-		}
-			
-		addAllDevices();
-	}
-	
-	private String
-	getHeaderToolTip()
-	{
-		if ( side_bar_hide_rend_gen || side_bar_show_tagged ){
-			
-			Device[] devices = device_manager.getDevices();
-			
-			int generic 	= 0;
-			int	untagged	= 0;
-			
-			for ( Device device: devices ){
-				
-				if ( device.isHidden()){
-					
-					continue;
-				}
-				
-				if ( device.getType() != Device.DT_MEDIA_RENDERER ){
-					
-					continue;
-				}
-				
-				DeviceMediaRenderer rend = (DeviceMediaRenderer)device;
-				
-				if ( rend.isNonSimple()){
-					
-					generic++;
-				}
-				
-				if ( !rend.isTagged()){
-					
-					untagged++;
-				}
-			}
-			
-			if ( !side_bar_show_tagged ){
-				
-				untagged = 0;
-			}
-			
-			if ( generic > 0 || untagged > 0 ){
-			
-				return( MessageText.getString( "devices.sidebar.mainheader.tooltip", new String[]{ String.valueOf( generic + untagged )} ));
-			}
-		}
-		
-		return( null );
-	}
-	
-	protected MdiEntry buildSideBar(boolean rebuild) {
-		MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-
-		if (mdi == null) {
-			return null;
-		}
-
-		if (entryHeader == null) {
-			entryHeader = mdi.getEntry(MultipleDocumentInterface.SIDEBAR_HEADER_DEVICES);
-			if (entryHeader != null) {
-				setupHeader(mdi, entryHeader);
-			}
-		}
-
-		mdiEntryOverview = mdi.getEntry(SideBar.SIDEBAR_SECTION_DEVICES);
-
-		if (mdiEntryOverview == null) {
-			mdiEntryOverview = mdi.createEntryFromSkinRef(
-					SideBar.SIDEBAR_HEADER_DEVICES, SideBar.SIDEBAR_SECTION_DEVICES,
-					"devicesview", MessageText.getString("mdi.entry.about.devices"), 
-					new ViewTitleInfo()
-					{
-						public Object 
-						getTitleInfoProperty(
-							int propertyID )
-						{
-							if ( propertyID == TITLE_INDICATOR_TEXT_TOOLTIP ){
-							
-								return( getHeaderToolTip());
-							}
-							
-							return( null );
-						}
-					},
-					null, false, "");
-			
-			mdiEntryOverview.setImageLeftID("image.sidebar.aboutdevices");
-		}
-
-		if (rebuild) {
-			for (categoryView category : categories) {
-				category.destroy();
-			}
-		}
-
-		categories.clear();
-
-		if (side_bar_view_type == SBV_FULL) {
-			buildCategories();
-		}
-
-		sidebar_built = true;
-
-		return mdiEntryOverview;
-	}	
-	
-	private void buildCategories() {
-		MenuManager menu_manager = ui_manager.getMenuManager();
-		// renderers
-
-		categoryView renderers_category = addDeviceCategory(
-				Device.DT_MEDIA_RENDERER, "device.renderer.view.title",
-				"image.sidebar.device.renderer");
-
-		categories.add(renderers_category);
-
-		MenuItem re_menu_item = menu_manager.addMenuItem("sidebar."
-				+ renderers_category.getKey(), "device.show");
-
-		re_menu_item.addListener(show_listener);
-		re_menu_item.addFillListener(show_fill_listener);
-
-		re_menu_item = menu_manager.addMenuItem( "sidebar." + renderers_category.getKey(), "sep_re");
-
-		re_menu_item.setStyle( MenuItem.STYLE_SEPARATOR );
-		
-		re_menu_item = menu_manager.addMenuItem(
-				"sidebar." + renderers_category.getKey(),
-				"device.renderer.remove_all");
-
-		re_menu_item.addListener(new MenuItemListener() {
-			public void selected(MenuItem menu, Object target) {
-				
-				new AEThread2( "doit" )
-				{
-					public void
-					run()
-					{
-						UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-										
-						long res = ui_manager.showMessageBox(
-								"device.mediaserver.remove_all.title",
-								"device.renderer.remove_all.desc",
-								UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
-						
-						if ( res == UIManagerEvent.MT_YES ){
-							
-							Device[] devices = device_manager.getDevices();
-							
-							for ( Device d: devices ){
-								
-								if ( d.getType() == Device.DT_MEDIA_RENDERER ){
-									
-									if ( d.canRemove()){
-										
-										d.remove();
-									}
-								}
-							}
-						}
-					}
-				}.start();
-			}
-		});
-		// media servers
-
-		categoryView media_servers_category = addDeviceCategory(
-				Device.DT_CONTENT_DIRECTORY, "device.mediaserver.view.title",
-				"image.sidebar.device.mediaserver");
-
-		categories.add(media_servers_category);
-
-		MenuItem ms_menu_item = menu_manager.addMenuItem("sidebar."
-				+ media_servers_category.getKey(), "device.show");
-
-		ms_menu_item.addListener(show_listener);
-		ms_menu_item.addFillListener(show_fill_listener);
-
-		ms_menu_item = menu_manager.addMenuItem(
-				"sidebar." + media_servers_category.getKey(),
-				"device.mediaserver.configure");
-
-		ms_menu_item.addListener(new MenuItemListener() {
-			public void selected(MenuItem menu, Object target) {
-				UIFunctions uif = UIFunctionsManager.getUIFunctions();
-
-				if (uif != null) {
-
-					uif.openView(UIFunctions.VIEW_CONFIG, "upnpmediaserver.name");
-				}
-			}
-		});
-		
-		ms_menu_item = menu_manager.addMenuItem( "sidebar." + media_servers_category.getKey(), "sep_ms");
-
-		ms_menu_item.setStyle( MenuItem.STYLE_SEPARATOR );
-		
-		ms_menu_item = menu_manager.addMenuItem(
-				"sidebar." + media_servers_category.getKey(),
-				"device.mediaserver.remove_all");
-
-		ms_menu_item.addListener(new MenuItemListener() {
-			public void selected(MenuItem menu, Object target) {
-				
-				new AEThread2( "doit" )
-				{
-					public void
-					run()
-					{
-						UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
-										
-						long res = ui_manager.showMessageBox(
-								"device.mediaserver.remove_all.title",
-								"device.mediaserver.remove_all.desc",
-								UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
-						
-						if ( res == UIManagerEvent.MT_YES ){
-							
-							Device[] devices = device_manager.getDevices();
-							
-							for ( Device d: devices ){
-								
-								if ( d.getType() == Device.DT_CONTENT_DIRECTORY ){
-									
-									if ( d.canRemove()){
-										
-										d.remove();
-									}
-								}
-							}
-						}
-					}
-				}.start();
-			}
-		});
-
-		// routers
-
-		categoryView routers_category = addDeviceCategory(
-				Device.DT_INTERNET_GATEWAY, "device.router.view.title",
-				"image.sidebar.device.router");
-
-		categories.add(routers_category);
-
-		MenuItem rt_menu_item = menu_manager.addMenuItem("sidebar."
-				+ routers_category.getKey(), "device.show");
-
-		rt_menu_item.addListener(show_listener);
-		rt_menu_item.addFillListener(show_fill_listener);
-
-		rt_menu_item = menu_manager.addMenuItem(
-				"sidebar." + routers_category.getKey(), "device.router.configure");
-
-		rt_menu_item.addListener(new MenuItemListener() {
-			public void selected(MenuItem menu, Object target) {
-				UIFunctions uif = UIFunctionsManager.getUIFunctions();
-
-				if (uif != null) {
-
-					uif.openView(UIFunctions.VIEW_CONFIG, "UPnP");
-				}
-			}
-		});
-
-		// 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");
-
-		categories.add(internet_category);
-	}
-
-	private void setupHeader(MultipleDocumentInterface mdi,
-			final MdiEntry entryHeader) {
-		addDefaultDropListener(entryHeader);
-
-		/* and away you go!
-		SideBarVitalityImage addDevice = entryHeader.addVitalityImage("image.sidebar.subs.add");
-		
-		addDevice.setToolTip("Add Device");
-		
-		addDevice.addListener(
-			new SideBarVitalityImageListener() 
-			{
-				public void 
-				sbVitalityImage_clicked(
-					int x, int y) 
-				{
-					addNewDevice();
-					//new DevicesWizard( DeviceManagerUI.this );
-				}
-			});
-		*/
-
-		// Rollup spinner/warning/info
-		entryHeader.setViewTitleInfo(new ViewTitleInfo() {
-			private int last_indicator = 0;
-
-			MdiEntryVitalityImage spinner = entryHeader.addVitalityImage(SPINNER_IMAGE_ID);
-
-			MdiEntryVitalityImage warning = entryHeader.addVitalityImage(ALERT_IMAGE_ID);
-
-			MdiEntryVitalityImage info = entryHeader.addVitalityImage(INFO_IMAGE_ID);
-
-			{
-				hideIcon(spinner);
-				hideIcon(warning);
-				hideIcon(info);
-			}
-
-			public Object getTitleInfoProperty(int propertyID) {
-				boolean expanded = entryHeader.isExpanded();
-
-				if (propertyID == TITLE_INDICATOR_TEXT) {
-
-					spinner.setVisible(!expanded && device_manager.isBusy( Device.DT_UNKNOWN ));
-
-					if (!expanded) {
-
-						Device[] devices = device_manager.getDevices();
-
-						last_indicator = 0;
-
-						String all_errors = "";
-						String all_infos = "";
-
-						for (Device device : devices) {
-
-							String error = device.getError();
-
-							if (error != null) {
-
-								all_errors += (all_errors.length() == 0 ? "" : "; ") + error;
-							}
-
-							String info = device.getInfo();
-
-							if (info != null) {
-
-								all_infos += (all_infos.length() == 0 ? "" : "; ") + info;
-							}
-
-							if (device instanceof DeviceMediaRenderer) {
-
-								if (SHOW_RENDERER_VITALITY) {
-
-									DeviceMediaRenderer renderer = (DeviceMediaRenderer) device;
-
-									last_indicator += renderer.getCopyToDevicePending()
-											+ renderer.getCopyToFolderPending();
-								}
-							} else if (device instanceof DeviceOfflineDownloader) {
-
-								if (SHOW_OD_VITALITY) {
-
-									DeviceOfflineDownloader dod = (DeviceOfflineDownloader) device;
-
-									last_indicator += dod.getTransferingCount();
-								}
-							}
-						}
-
-						if (all_errors.length() > 0) {
-
-							hideIcon(info);
-
-							showIcon(warning, all_errors);
-
-						} else {
-
-							hideIcon(warning);
-
-							if (all_infos.length() > 0) {
-
-								showIcon(info, all_infos);
-
-							} else {
-
-								hideIcon(info);
-							}
-						}
-
-						if (last_indicator > 0) {
-
-							return (String.valueOf(last_indicator));
-						}
-					} else {
-
-						hideIcon(warning);
-						hideIcon(info);
-
-					}
-				} else if (propertyID == TITLE_INDICATOR_COLOR) {
-
-					/*
-					if ( last_indicator > 0 ){
-						
-						if ( SHOW_VITALITY ){
-							
-							return( to_copy_indicator_colors );
-						}
-					}
-					*/
-				} else if (propertyID == TITLE_INDICATOR_TEXT_TOOLTIP ) {
-					
-					return( getHeaderToolTip());
-				}
-
-				return null;
-			}
-		});
-
-		///////// Turn On
-		device_manager.addListener(new DeviceManagerListener() {
-
-			public void deviceRemoved(Device device) {
-			}
-
-			public void deviceManagerLoaded() {
-				device_manager.removeListener(this);
-				if (entryHeader == null || entryHeader.isDisposed()) {
-					return;
-				}
-	  		PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager();
-	  		PluginInterface pi;
-	  		pi = pm.getPluginInterfaceByID("vuzexcode");
-				if (device_manager.getTranscodeManager().getProviders().length == 0 || pi == null) {
-					// provider plugin not installed yet
-
-					final MdiEntryVitalityImage turnon = entryHeader.addVitalityImage("image.sidebar.turnon");
-					if (turnon != null) {
-						turnon.addListener(new MdiEntryVitalityImageListener() {
-							public void mdiEntryVitalityImage_clicked(int x, int y) {
-								DevicesFTUX.ensureInstalled(null);
-							}
-						});
-
-						device_manager.getTranscodeManager().addListener(
-								new TranscodeManagerListener() {
-									public void providerAdded(TranscodeProvider provider) {
-										// only triggers when vuzexcode is avail
-										turnon.setVisible(false);
-									}
-
-									public void providerUpdated(TranscodeProvider provider) {
-									}
-
-									public void providerRemoved(TranscodeProvider provider) {
-									}
-								});
-					}
-				} else {
-					// provider plugin installed, but we had a bug in older versions,
-					// so fixup
-					DevicesFTUX.alreadyInstalledFixup();
-				}
-			}
-
-			public void deviceChanged(Device device) {
-			}
-
-			public void deviceAttentionRequest(Device device) {
-			}
-
-			public void deviceAdded(Device device) {
-			}
-		});
-
-		//////// Beta
-
-		MdiEntryVitalityImage beta = entryHeader.addVitalityImage("image.sidebar.beta");
-		if (beta != null) {
-			beta.setAlignment(SWT.LEFT);
-		}
-
-		///////// Menu
-
-		MenuManager menu_manager = ui_manager.getMenuManager();
-
-		createOverallMenu(menu_manager, "sidebar." + SideBar.SIDEBAR_HEADER_DEVICES);
-		createOverallMenu(menu_manager, "sidebar." + SideBar.SIDEBAR_SECTION_DEVICES);
-	}
-
-	private void createOverallMenu(final MenuManager menu_manager, String parentID) {
-		MenuItem de_menu_item = menu_manager.addMenuItem(parentID, "device.search");
-
-		de_menu_item.addListener(new MenuItemListener() {
-			public void selected(MenuItem menu, Object target) {
-				search();
-			}
-		});
-
-			// show generic
-
-		de_menu_item = menu_manager.addMenuItem(parentID, "device.showGeneric");
-		de_menu_item.setStyle(MenuItem.STYLE_CHECK);
-		de_menu_item.addFillListener(new MenuItemFillListener() {
-			public void menuWillBeShown(MenuItem menu, Object data) {
-				
-				boolean is_hidden = COConfigurationManager.getBooleanParameter(CONFIG_VIEW_HIDE_REND_GENERIC, true);
-				
-				menu.setData( !is_hidden );
-				
-				boolean	enabled = false;
-				
-				if ( is_hidden ){
-					
-					Device[] devices = device_manager.getDevices();
-										
-					for ( Device d: devices ){
-		
-						if ( d.isHidden()){
-							
-							continue;
-						}
-						
-						if ( d instanceof  DeviceMediaRenderer ){
-							
-							DeviceMediaRenderer rend = (DeviceMediaRenderer)d;
-						
-							if ( rend.isNonSimple()){
-								
-								enabled = true;
-							}
-						}
-					}
-				}else{
-					
-					enabled = true;
-				}
-				
-				menu.setEnabled( enabled );
-			}
-		});
-		de_menu_item.addListener(new MenuItemListener() {
-			public void selected(MenuItem menu, Object target) {
-				COConfigurationManager.setParameter(CONFIG_VIEW_HIDE_REND_GENERIC,
-						!COConfigurationManager.getBooleanParameter(
-								CONFIG_VIEW_HIDE_REND_GENERIC, true));
-			}
-		});
-
-			// show tagged
-
-		de_menu_item = menu_manager.addMenuItem(parentID, "device.onlyShowTagged");
-		de_menu_item.setStyle(MenuItem.STYLE_CHECK);
-		de_menu_item.addFillListener(new MenuItemFillListener() {
-			public void menuWillBeShown(MenuItem menu, Object data) {
-				menu.setData(COConfigurationManager.getBooleanParameter(
-						CONFIG_VIEW_SHOW_ONLY_TAGGED, false));
-				
-				Device[] devices = device_manager.getDevices();
-				
-				boolean has_tagged = false;
-				
-				for ( Device d: devices ){
-					
-					if ( d.isTagged()){
-						
-						has_tagged = true;
-						
-						break;
-					}
-				}
-				
-				menu.setEnabled( has_tagged );
-			}
-		});
-		
-		de_menu_item.addListener(new MenuItemListener() {
-			public void selected(MenuItem menu, Object target) {
-				COConfigurationManager.setParameter(CONFIG_VIEW_SHOW_ONLY_TAGGED,
-						!COConfigurationManager.getBooleanParameter(
-								CONFIG_VIEW_SHOW_ONLY_TAGGED, false));
-			}
-		});
-		
-			// show hidden
-		
-		de_menu_item = menu_manager.addMenuItem(parentID, "device.show");
-
-		de_menu_item.addListener(show_listener);
-		de_menu_item.addFillListener(show_fill_listener);
-
-			// simple
-
-		de_menu_item = menu_manager.addMenuItem(parentID, "devices.sidebar.simple");
-
-		de_menu_item.setStyle(MenuItem.STYLE_CHECK);
-
-		de_menu_item.addFillListener(new MenuItemFillListener() {
-			public void menuWillBeShown(MenuItem menu, Object data) {
-				menu.setData(COConfigurationManager.getIntParameter(CONFIG_VIEW_TYPE,
-						SBV_SIMPLE) == SBV_SIMPLE);
-			}
-		});
-
-		de_menu_item.addListener(new MenuItemListener() {
-			public void selected(MenuItem menu, Object target) {
-				COConfigurationManager.setParameter(CONFIG_VIEW_TYPE,
-						((Boolean) menu.getData()) ? SBV_SIMPLE : SBV_FULL);
-			}
-		});
-
-		de_menu_item = menu_manager.addMenuItem(parentID, "sep");
-
-		de_menu_item.setStyle(MenuItem.STYLE_SEPARATOR);
-
-			// on complete do
-		
-		final MenuItem de_oxc_menu = menu_manager.addMenuItem(parentID, "devices.sidebar.onxcodecomplete");
-
-		de_oxc_menu.setStyle(MenuItem.STYLE_MENU );
-
-		de_oxc_menu.addFillListener(
-			new MenuItemFillListener()
-			{
-				public void 
-				menuWillBeShown(
-					MenuItem menu, Object data) 
-				{
-					menu.removeAllChildItems();
-					
-					final List<MenuItem> oxc_items = new ArrayList<MenuItem>();
-					
-					final MenuItem oxc_nothing = menu_manager.addMenuItem( de_oxc_menu, "devices.sidebar.oxc.nothing" );
-					oxc_items.add( oxc_nothing );
-					oxc_nothing.setStyle( MenuItem.STYLE_CHECK );
-					oxc_nothing.setData( oxc_action == OXC_NOTHING );
-					
-					final MenuItem oxc_close_vuze = menu_manager.addMenuItem( de_oxc_menu, "devices.sidebar.oxc.closevuze" );
-					oxc_items.add( oxc_close_vuze );
-					oxc_close_vuze.setStyle( MenuItem.STYLE_CHECK );
-					oxc_close_vuze.setData( oxc_action == OXC_QUIT_VUZE  );
-					
-					PlatformManager pm = PlatformManagerFactory.getPlatformManager();
-					
-					int	sdt = pm.getShutdownTypes();
-					
-					final Map<MenuItem,String>	oxc_pm_map = new HashMap<MenuItem,String>();
-					
-					for ( int type: PlatformManager.SD_ALL ){
-						
-						if ( ( sdt | type ) != 0 ){
-							
-							String	action = OXC_NOTHING;
-							
-							if ( type == PlatformManager.SD_SLEEP ){
-								action = OXC_SLEEP;
-							}else if ( type == PlatformManager.SD_HIBERNATE ){
-								action = OXC_HIBERNATE;
-							}else if ( type == PlatformManager.SD_SHUTDOWN ){
-								action = OXC_SHUTDOWN;
-							}else{
-								Debug.out( "Unknown type: " + type );
-							}
-							
-							MenuItem oxc_pm = menu_manager.addMenuItem( de_oxc_menu, "devices.sidebar.oxc.pm." + type );
-							oxc_items.add( oxc_pm );
-							oxc_pm.setStyle( MenuItem.STYLE_CHECK );
-							oxc_pm.setData( oxc_action == action );
-							
-							oxc_pm_map.put( oxc_pm, action );
-						}
-					}
-					
-					MenuItemListener oxc_mil = 
-						new MenuItemListener()
-						{
-							public void 
-							selected(
-								MenuItem menu, 
-								Object target) 
-							{
-								if ((Boolean)menu.getData()){
-									
-									if ( menu == oxc_nothing ){
-										
-										setOXCState( OXC_NOTHING );
-										
-									}else if ( menu == oxc_close_vuze ){
-										
-										setOXCState( OXC_QUIT_VUZE );
-										
-									}else{
-										
-										setOXCState( oxc_pm_map.get(menu ));
-									}
-								}
-							}
-						};
-						
-					for ( MenuItem mi: oxc_items ){
-						
-						mi.addListener( oxc_mil );
-					}
-				};
-			});
-		
-		de_menu_item = menu_manager.addMenuItem(parentID, "sep2");
-
-		de_menu_item.setStyle(MenuItem.STYLE_SEPARATOR);
-
-		// options 
-
-		de_menu_item = menu_manager.addMenuItem(parentID, "MainWindow.menu.view.configuration");
-
-		de_menu_item.addListener(new MenuItemListener() {
-			public void selected(MenuItem menu, Object target) {
-				UIFunctions uif = UIFunctionsManager.getUIFunctions();
-
-				if (uif != null) {
-
-					uif.openView(UIFunctions.VIEW_CONFIG, "Devices");
-				}
-			}
-		});
-
-		if (Constants.isCVSVersion()) {
-			de_menu_item = menu_manager.addMenuItem(parentID, "!(CVS Only)Show FTUX!");
-
-			de_menu_item.addListener(new MenuItemListener() {
-				public void selected(MenuItem menu, Object target) {
-					DevicesFTUX.showForDebug();
-				}
-			});
-
-		}
-	}
-
-	/**
-	 * 
-	 *
-	 * @since 4.1.0.5
-	 */
-	protected void addNewDevice() {
-		ManufacturerChooser mfChooser = new ManufacturerChooser();
-		mfChooser.open(new ClosedListener() {
-			public void MfChooserClosed(DeviceManufacturer mf) {
-				if (mf == null) {
-					return;
-				}
-				DeviceTemplateChooser deviceTemplateChooser = new DeviceTemplateChooser(mf);
-				
-				deviceTemplateChooser.open(new DeviceTemplateClosedListener() {
-					public void deviceTemplateChooserClosed(DeviceTemplate deviceTemplate) {
-						if (deviceTemplate == null) {
-							return;
-						}
-
-						Device device;
-						try {
-							device = deviceTemplate.createInstance(deviceTemplate.getName() + " test!" );
-							device.requestAttention();
-						} catch (DeviceManagerException e) {
-							Debug.out(e);
-						}
-
-						/*  Don't really need to choose a profile now..
-						TranscodeProfile[] profiles = null;// deviceTemplate.getTranscodeProfiles();
-						new TranscodeChooser(profiles) {
-							public void closed() {
-								Utils.openMessageBox(null, 0, "CHOSE", "You chose "
-										+ (selectedProfile == null ? "NULL"
-												: selectedProfile.getName()));
-								
-							}
-						};
-						*/
-					}
-				});
-			}
-		});
-	}
-
-	private void
-	setOXCState(
-		String		new_action )
-	{
-		oxc_action = new_action;
-			
-		checkOXCState();			
-	}
-	
-	private void
-	checkOXCState()
-	{
-		if ( oxc_action == OXC_NOTHING ){
-			
-			oxc_trigger_set	= false;
-			
-			return;
-		}
-		
-		int	jobs = device_manager.getTranscodeManager().getQueue().getJobCount();
-		
-		if ( jobs > 0 ){
-			
-			oxc_trigger_set	= true;
-
-		}else{
-			
-			if ( oxc_trigger_set ){
-					
-				oxc_trigger_set = false;
-				
-				AzureusCoreFactory.getSingleton().executeCloseAction( oxc_action, MessageText.getString( "core.shutdown.xcode" ));
-			}
-		}
-	}
-	
-	private void 
-	setupTranscodeMenus()
-	{					
-			// top level menus
-				
-		final String[] tables = {
-				TableManager.TABLE_MYTORRENTS_INCOMPLETE,
-				TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG,
-				TableManager.TABLE_MYTORRENTS_COMPLETE,
-				TableManager.TABLE_MYTORRENTS_COMPLETE_BIG,
-				TableManager.TABLE_TORRENT_FILES,
-				TableManager.TABLE_MYTORRENTS_UNOPENED,
-				TableManager.TABLE_MYTORRENTS_UNOPENED_BIG,
-				TableManager.TABLE_MYTORRENTS_ALL_BIG,
-			};
-		
-		TableManager table_manager = plugin_interface.getUIManager().getTableManager();
-		
-		MenuItemFillListener	menu_fill_listener = 
-			new MenuItemFillListener()
-			{
-				public void
-				menuWillBeShown(
-					MenuItem	menu,
-					Object		_target )
-				{
-					final TableRow[]	target;
-					
-					if ( _target instanceof TableRow ){
-						
-						target = new TableRow[]{ (TableRow)_target };
-						
-					}else{
-						
-						target = (TableRow[])_target;
-					}
-					
-					boolean	enabled = target.length > 0;
-					
-					for ( TableRow row: target ){
-						
-						Object obj = row.getDataSource();
-					
-						if ( obj instanceof Download ){
-						
-							Download download = (Download)obj;
-
-							if ( download.getState() == Download.ST_ERROR ){
-								
-								enabled = false;
-							}
-						}else{
-							
-							DiskManagerFileInfo file = (DiskManagerFileInfo)obj;
-							
-							try{
-								if ( file.getDownload().getState() == Download.ST_ERROR ){
-								
-									enabled = false;
-								}
-							}catch( Throwable e ){
-								
-								enabled = false;
-							}
-						}
-					}
-					
-					menu.setEnabled( enabled );
-					
-					menu.removeAllChildItems();
-					
-					if ( enabled ){
-						
-						Device[] devices = device_manager.getDevices();
-						
-						int	devices_added = 0;
-						
-						for ( Device device: devices ){
-							
-							if ( device.isHidden()){
-								
-								continue;
-							}
-							
-							if ( device instanceof TranscodeTarget ){
-								
-								devices_added++;
-								
-								final TranscodeTarget renderer = (TranscodeTarget)device;
-								
-								TranscodeProfile[] profiles = renderer.getTranscodeProfiles();
-								
-
-								TableContextMenuItem device_item =
-									plugin_interface.getUIManager().getTableManager().addContextMenuItem(
-										(TableContextMenuItem)menu,
-										"!" + device.getName() + (profiles.length==0?" (No Profiles)":"") + "!");
-								
-								device_item.setStyle( MenuItem.STYLE_MENU );
-								
-								if ( profiles.length == 0 ){
-									
-									device_item.setEnabled( false );
-									
-								}else{
-
-									Arrays.sort(profiles, new Comparator<TranscodeProfile>() {
-										public int compare(TranscodeProfile o1, TranscodeProfile o2) {
-											int i1 = o1.getIconIndex();
-											int i2 = o2.getIconIndex();
-											
-											if ( i1 == i2 ){
-											
-												return o1.getName().compareToIgnoreCase(o2.getName());
-											}else{
-												
-												return( i1 - i2 );
-											}
-										}
-									});
-
-									
-									for ( final TranscodeProfile profile: profiles ){
-										
-										TableContextMenuItem profile_item =
-											plugin_interface.getUIManager().getTableManager().addContextMenuItem(
-												device_item,
-												"!" + profile.getName() + "!");
-
-										profile_item.addMultiListener(
-											new MenuItemListener()
-											{
-												public void 
-												selected(
-													MenuItem 	menu,
-													Object 		x ) 
-												{													
-													for ( TableRow row: target ){
-														
-														Object obj = row.getDataSource();
-													
-														try{
-															if ( obj instanceof Download ){
-															
-																Download download = (Download)obj;
-	
-																addDownload( renderer, profile, -1, download );
-																	
-															}else{
-																
-																DiskManagerFileInfo file = (DiskManagerFileInfo)obj;
-																
-																addFile( renderer, profile, -1, file );
-															}
-														}catch( Throwable e ){
-															
-															Debug.out( e );
-														}
-													}
-												}
-											});
-									}
-								}
-							}
-						}
-						
-						if ( devices_added == 0 ){
-						
-							TableContextMenuItem device_item =
-								plugin_interface.getUIManager().getTableManager().addContextMenuItem(
-									(TableContextMenuItem)menu,
-									"!(No Devices)!");
-							
-							device_item.setEnabled( false );
-
-						}
-					}
-				}
-			};
-		
-		// 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.xcode" );
-			
-			menu.setStyle(TableContextMenuItem.STYLE_MENU);
-		
-			menu.addFillListener( menu_fill_listener );				
-		}
-	}
-	
-	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()
-	{
-      	device_manager.search(
-      			10*1000,
-      			new DeviceSearchListener()
-      			{
-      				public void 
-      				deviceFound(
-      					Device device ) 
-      				{
-      				}
-      				
-      				public void 
-      				complete() 
-      				{
-      				}
-      			});
-	}
-	
-	protected void
-	addOrChangeDevice(
-		final Device		device )
-	{
-		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 ){
-			
-			for ( categoryView view: categories ){
-				
-				if ( view.getDeviceType() == type ){
-					
-					parent_key = view.getKey();
-					
-					break;
-				}
-			}
-		}else{
-			
-			if ( type != Device.DT_MEDIA_RENDERER && type != Device.DT_OFFLINE_DOWNLOADER ){
-				
-				return;
-			}
-			
-			parent_key = SideBar.SIDEBAR_HEADER_DEVICES;
-		}
-		
-		if ( parent_key == null ){
-			
-			Debug.out( "Unknown device type: " + device.getString());
-			
-			return;
-		}
-			
-		boolean	hide_device = device.isHidden();
-		
-		if ( type == Device.DT_MEDIA_RENDERER && side_bar_hide_rend_gen ){
-			
-			DeviceMediaRenderer rend = (DeviceMediaRenderer)device;
-			
-			if ( rend.isNonSimple()){
-				
-				hide_device = true;
-			}
-		}
-		
-		if ( side_bar_show_tagged && !device.isTagged()){
-				
-			hide_device = true;
-		}
-		
-		if ( hide_device ){
-			
-			removeDevice( device );
-			
-			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();
-
-					device.setTransientProperty( DEVICE_IVIEW_KEY, new_di );
-
-					setupEntry(new_di, device, parent);
-				}
-			}else{
-				
-				ViewTitleInfoManager.refreshTitleInfo( existing_di.getView());
-				
-				setStatus( device, existing_di );
-			}
-		}
-	}
-	
-	private void setupEntry(deviceItem new_di, final Device device, String parent) {
-		synchronized( DeviceManagerUI.this ){
-			
-			if ( new_di.isDestroyed()){
-				
-				return;
-			}
-			
-			deviceView view = new deviceView( parent, device );
-			
-			new_di.setView( view );
-			
-			String key = parent + "/" + device.getID() + ":" + nextSidebarID();
-
-			final MdiEntry	entry;
-			
-			int	device_type = device.getType();
-			
-			if ( device_type == Device.DT_MEDIA_RENDERER ){
-
-				entry = 
-						mdi.createEntryFromSkinRef(
-								parent,
-								key, "devicerendererview",
-								device.getName(),
-								view, null, false, null);
-				
-			}else if ( device_type == Device.DT_OFFLINE_DOWNLOADER ){
-				
-				entry = 
-						mdi.createEntryFromSkinRef(
-								parent,
-								key, "devicesodview",
-								device.getName(),
-								view, null, false, null);
-				entry.setExpanded(true);
-
-				
-				DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device;
-				
-				String	id;
-				
-				String manufacturer = dod.getManufacturer();
-				
-				if ( manufacturer.toLowerCase().contains( "vuze" )){
-					
-					id = "vuze";
-
-				}else if ( manufacturer.toLowerCase().contains( "belkin" )){
-					
-					id = "bel";
-					
-				}else{
-					
-					id = "other";
-				}
-				
-				entry.setImageLeftID( "image.sidebar.device.od." + id + ".small" );
-
-			}else{
-				
-				entry = mdi.createEntryFromEventListener(parent, view, key, false,
-						device, null);
-				entry.setExpanded(true);
-
-			}
-			
-			entry.setDatasource( device );
-			
-			entry.setLogID(parent + "-" + device.getName());
-
-			new_di.setMdiEntry( entry );
-
-			setStatus( device, new_di );
-			
-			if ( device instanceof TranscodeTarget ){
-				
-				entry.addListener(
-						new MdiEntryDropListener()
-						{
-							public boolean 
-							mdiEntryDrop(
-									MdiEntry 		entry, 
-									Object 				payload  )
-							{
-								return handleDrop((TranscodeTarget)device, payload );
-							}
-						});
-			}
-			
-			final MenuManager menu_manager = ui_manager.getMenuManager();
-
-			boolean	need_sep = false;
-			
-			if ( device instanceof TranscodeTarget ){
-				
-				need_sep = true;
-				
-				MenuItem explore_menu_item = menu_manager.addMenuItem("sidebar." + key, "v3.menu.device.exploreTranscodes");
-				
-				explore_menu_item.addListener(new MenuItemListener() {
-					public void selected(MenuItem menu, Object target) {
-		 				ManagerUtils.open( ((TranscodeTarget) device).getWorkingDirectory());
-					}
-				});
-			}
-			
-			if ( device instanceof DeviceMediaRenderer ){
-				
-				need_sep = true;
-				// filter view
-				
-				final DeviceMediaRenderer renderer = (DeviceMediaRenderer) device;
-				
-				if ( renderer.canFilterFilesView()){
-					MenuItem filterfiles_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.only.show");
-					filterfiles_menu_item.setStyle(MenuItem.STYLE_CHECK);
-					
-					filterfiles_menu_item.addFillListener(new MenuItemFillListener() {
-						public void menuWillBeShown(MenuItem menu, Object data) {
-							menu.setData(new Boolean(renderer.getFilterFilesView()));
-						}
-					});
-					filterfiles_menu_item.addListener(new MenuItemListener() {
-						public void selected(MenuItem menu, Object target) {
-			 				renderer.setFilterFilesView( (Boolean) menu.getData());
-						}
-					});
-				}
-				
-				// show cats
-				
-				if ( renderer.canShowCategories()){
-					MenuItem showcat_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.show.cat");
-					showcat_menu_item.setStyle(MenuItem.STYLE_CHECK);
-					
-					showcat_menu_item.addFillListener(new MenuItemFillListener() {
-						public void menuWillBeShown(MenuItem menu, Object data) {
-							menu.setData(new Boolean(renderer.getShowCategories()));
-						}
-					});
-					showcat_menu_item.addListener(new MenuItemListener() {
-						public void selected(MenuItem menu, Object target) {
-			 				renderer.setShowCategories( (Boolean) menu.getData());
-						}
-					});
-				}
-
-				// cache files
-				
-				MenuItem alwayscache_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.always.cache");
-				alwayscache_menu_item.setStyle(MenuItem.STYLE_CHECK);
-				
-				alwayscache_menu_item.addFillListener(new MenuItemFillListener() {
-					public void menuWillBeShown(MenuItem menu, Object data) {
-						menu.setData(new Boolean(renderer.getAlwaysCacheFiles()));
-					}
-				});
-				alwayscache_menu_item.addListener(new MenuItemListener() {
-					public void selected(MenuItem menu, Object target) {
-		 				renderer.setAlwaysCacheFiles( (Boolean) menu.getData());
-					}
-				});
-				
-			}
-			
-			if ( need_sep ){
-				
-				menu_manager.addMenuItem("sidebar." + key, "1" ).setStyle( MenuItem.STYLE_SEPARATOR );
-			}
-			
-			need_sep = false;
-			
-			if ( device instanceof DeviceMediaRenderer ){
-				
-				final DeviceMediaRenderer renderer = (DeviceMediaRenderer) device;
-
-				if ( renderer.canCopyToFolder()){
-					
-					need_sep = true;
-					
-					MenuItem autocopy_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.autoCopy");
-					autocopy_menu_item.setStyle(MenuItem.STYLE_CHECK);
-					
-					autocopy_menu_item.addFillListener(new MenuItemFillListener() {
-						public void menuWillBeShown(MenuItem menu, Object data) {
-							menu.setData(new Boolean(renderer.getAutoCopyToFolder()));
-						}
-					});
-					autocopy_menu_item.addListener(new MenuItemListener() {
-						public void selected(MenuItem menu, Object target) {
-			 				renderer.setAutoCopyToFolder((Boolean) menu.getData());
-						}
-					});
-					
-					final MenuItem mancopy_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.mancopy");
-					mancopy_menu_item.setStyle(MenuItem.STYLE_PUSH);
-					
-					mancopy_menu_item.addListener(new MenuItemListener() {
-						public void 
-						selected(
-								MenuItem menu, Object target) 
-						{
-							try{
-								renderer.manualCopy();
-								
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-						}
-					});
-					
-					mancopy_menu_item.addFillListener(
-							new MenuItemFillListener()
-							{
-								public void 
-								menuWillBeShown(
-										MenuItem menu, Object data )
-								{
-									boolean	enabled = false;
-									
-									if ( !renderer.getAutoCopyToFolder()){
-										
-										File target = renderer.getCopyToFolder();
-										
-										if ( target != null && target.exists()){
-											
-											enabled = renderer.getCopyToFolderPending() > 0;
-										}
-									}
-									mancopy_menu_item.setEnabled( enabled );
-								}
-							});
-					
-					MenuItem setcopyto_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.setcopyto");
-					setcopyto_menu_item.setStyle(MenuItem.STYLE_PUSH);
-					
-					
-					setcopyto_menu_item.addListener(new MenuItemListener() {
-						public void 
-						selected(
-								MenuItem menu, Object target) 
-						{
-							Shell shell = Utils.findAnyShell();
-							
-							DirectoryDialog dd = new DirectoryDialog( shell );
-							
-							File existing = renderer.getCopyToFolder();
-							
-							if ( existing != null ){
-								
-								dd.setFilterPath( existing.getAbsolutePath());
-							}
-							
-							dd.setText( MessageText.getString( "devices.xcode.setcopyto.title" ));
-							
-							String	path = dd.open();
-							
-							if ( path != null ){
-								
-								renderer.setCopyToFolder( new File( path ));
-							}
-						}
-					});
-
-
-				}
-				
-				if ( renderer.canCopyToDevice()){
-					
-					need_sep = true;
-					
-					MenuItem autocopy_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.autoCopy.device");
-					autocopy_menu_item.setStyle(MenuItem.STYLE_CHECK);
-					
-					autocopy_menu_item.addFillListener(new MenuItemFillListener() {
-						public void menuWillBeShown(MenuItem menu, Object data) {
-							menu.setData(new Boolean(renderer.getAutoCopyToDevice()));
-						}
-					});
-					autocopy_menu_item.addListener(new MenuItemListener() {
-						public void selected(MenuItem menu, Object target) {
-			 				renderer.setAutoCopyToDevice((Boolean) menu.getData());
-						}
-					});
-					
-					final MenuItem mancopy_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.mancopy");
-					mancopy_menu_item.setStyle(MenuItem.STYLE_PUSH);
-					
-					mancopy_menu_item.addListener(new MenuItemListener() {
-						public void 
-						selected(
-							MenuItem menu, Object target) 
-						{
-							try{
-								renderer.manualCopy();
-								
-							}catch( Throwable e ){
-								
-								Debug.out( e );
-							}
-						}
-					});
-					
-					mancopy_menu_item.addFillListener(
-							new MenuItemFillListener()
-							{
-								public void 
-								menuWillBeShown(
-										MenuItem menu, Object data )
-								{
-									boolean	enabled = false;
-									
-									if ( !renderer.getAutoCopyToDevice()){
-										
-										enabled = renderer.getCopyToDevicePending() > 0;
-									}
-									
-									mancopy_menu_item.setEnabled( enabled );
-								}
-							});
-				}
-				
-				if ( renderer.canAutoStartDevice()){
-					
-					need_sep = true;
-					
-					MenuItem autostart_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.autoStart");
-					autostart_menu_item.setStyle(MenuItem.STYLE_CHECK);
-					
-					autostart_menu_item.addFillListener(new MenuItemFillListener() {
-						public void menuWillBeShown(MenuItem menu, Object data) {
-							menu.setData(new Boolean(renderer.getAutoStartDevice()));
-						}
-					});
-					autostart_menu_item.addListener(new MenuItemListener() {
-						public void selected(MenuItem menu, Object target) {
-			 				renderer.setAutoStartDevice((Boolean) menu.getData());
-						}
-					});
-				}
-				
-				if ( renderer.canAssociate()){
-					
-					need_sep = true;
-					
-					final MenuItem menu_associate = menu_manager.addMenuItem(
-							"sidebar." + key, "devices.associate");
-					
-					menu_associate.setStyle(MenuItem.STYLE_MENU);
-
-					menu_associate.addFillListener(
-							new MenuItemFillListener()
-							{
-								public void 
-								menuWillBeShown(
-										MenuItem menu, Object data )
-								{
-									menu_associate.removeAllChildItems();
-									
-									if ( renderer.isAlive()){
-										
-										InetAddress a = renderer.getAddress();
-										
-										String address = a==null?"":a.getHostAddress();
-										
-										MenuItem menu_none = menu_manager.addMenuItem(
-												menu_associate,
-												"!" + MessageText.getString( "devices.associate.already" ) + ": " + address + "!" );
-
-										menu_none.setEnabled( false );
-										
-										menu_associate.setEnabled( true );
-										
-									}else{
-										
-										UnassociatedDevice[] unassoc = device_manager.getUnassociatedDevices();
-										
-										if ( unassoc.length == 0 ){
-
-											menu_associate.setEnabled( false );
-											
-										}else{
-											
-											menu_associate.setEnabled( true );
-											
-											for ( final UnassociatedDevice un: unassoc ){
-												
-												MenuItem menu_un = menu_manager.addMenuItem(
-														menu_associate,
-														"!" + un.getAddress().getHostAddress() + ": " + un.getDescription() + "!");
-													
-													menu_un.addListener(
-															new MenuItemListener() 
-															{
-																public void 
-																selected(
-																		MenuItem 	menu, 
-																		Object 		target)
-																{
-																	renderer.associate( un );
-																}
-															});
-											}
-										}
-									}
-								}
-							});
-
-				}
-				
-				if ( renderer.canRestrictAccess()){
-					
-					need_sep = true;
-					
-					final MenuItem menu_ra = menu_manager.addMenuItem(
-							"sidebar." + key, "devices.restrict_access");
-					
-					menu_ra.addListener(
-						new MenuItemListener() 
-						{
-							public void 
-							selected(
-								MenuItem menu, 
-								Object target) 
-							{
-								if (target instanceof MdiEntry){
-																		
-									UISWTInputReceiver entry = (UISWTInputReceiver)swt_ui.getInputReceiver();
-									
-									entry.setMessage( "devices.restrict_access.msg" );
-									
-									entry.setPreenteredText( renderer.getAccessRestriction(), false );
-									
-									entry.maintainWhitespace( false );
-									
-									entry.allowEmptyInput( true );
-									
-									entry.setLocalisedTitle(
-										MessageText.getString("devices.restrict_access.prompt",
-											new String[]{
-										device.getName()
-									}));
-			
-									entry.prompt(new UIInputReceiverListener(){
-										public void UIInputReceiverClosed( UIInputReceiver entry ){
-											if (!entry.hasSubmittedInput()) {
-												return;
-											}
-											String input = entry.getSubmittedInput().trim();
-																							
-											renderer.setAccessRestriction( input );
-											
-										}
-									});		
-								}
-							}
-						});
-				}
-				
-				final TranscodeProfile[] transcodeProfiles = renderer.getTranscodeProfiles();
-				
-				if (transcodeProfiles.length > 0) {
-					Arrays.sort(transcodeProfiles, new Comparator<TranscodeProfile>() {
-						public int compare(TranscodeProfile o1, TranscodeProfile o2) {
-							int i1 = o1.getIconIndex();
-							int i2 = o2.getIconIndex();
-							
-							if ( i1 == i2 ){
-								
-								return o1.getName().compareToIgnoreCase(o2.getName());
-							}else{
-								
-								return( i1 - i2 );
-							}
-						}
-					});
-
-					need_sep = true;
-					
-					MenuItem menu_default_profile = menu_manager.addMenuItem(
-							"sidebar." + key, "v3.menu.device.defaultprofile");
-					menu_default_profile.setStyle(MenuItem.STYLE_MENU);
-					
-					MenuItem menu_profile_never = menu_manager.addMenuItem( menu_default_profile, "v3.menu.device.defaultprofile.never");
-					
-					menu_profile_never.setStyle(MenuItem.STYLE_CHECK );
-					menu_profile_never.setData(Boolean.TRUE);
-					menu_profile_never.addListener(new MenuItemListener() {
-						public void selected(MenuItem menu, Object target) {
-							renderer.setTranscodeRequirement(((Boolean)menu.getData())?TranscodeTarget.TRANSCODE_NEVER:TranscodeTarget.TRANSCODE_WHEN_REQUIRED );
-						}});
-
-
-					menu_profile_never.addFillListener(new MenuItemFillListener() {
-						public void menuWillBeShown(MenuItem menu, Object data) {
-							boolean never = renderer.getTranscodeRequirement() == TranscodeTarget.TRANSCODE_NEVER;
-							menu.setData( never );
-						}});
-					
-					MenuItem menu_profile_none = menu_manager.addMenuItem(
-							menu_default_profile, "option.askeverytime");
-					menu_profile_none.setStyle(MenuItem.STYLE_RADIO);
-					menu_profile_none.setData(Boolean.FALSE);
-					menu_profile_none.addListener(new MenuItemListener() {
-						public void selected(MenuItem menu, Object target) {
-							renderer.setDefaultTranscodeProfile(null);
-						}
-					});
-					
-					menu_profile_none.addFillListener(new MenuItemFillListener() {
-						public void menuWillBeShown(MenuItem menu, Object data) {
-							if ( transcodeProfiles.length <= 1 ){
-								menu.setData( Boolean.FALSE );
-								menu.setEnabled( false );
-							}else{
-								TranscodeProfile profile = null;
-								try {
-									profile = renderer.getDefaultTranscodeProfile();
-								} catch (TranscodeException e) {
-								}
-								menu.setData((profile == null) ? Boolean.TRUE
-										: Boolean.FALSE);
-								
-								menu.setEnabled( renderer.getTranscodeRequirement() != TranscodeTarget.TRANSCODE_NEVER  );
-							}
-						}
-					});
-					
-					for (final TranscodeProfile profile : transcodeProfiles) {
-						MenuItem menuItem = menu_manager.addMenuItem(
-								menu_default_profile, "!" + profile.getName() + "!");
-							menuItem.setStyle(MenuItem.STYLE_RADIO);
-							menuItem.setData(Boolean.FALSE);
-							menuItem.addListener(new MenuItemListener() {
-								public void selected(MenuItem menu, Object target) {
-									renderer.setDefaultTranscodeProfile(profile);
-								}
-							});
-							
-							menuItem.addFillListener(new MenuItemFillListener() {
-								public void menuWillBeShown(MenuItem menu, Object data) {
-									if ( transcodeProfiles.length <= 1 ){
-										menu.setData( Boolean.TRUE );
-										menu.setEnabled( false );
-									}else{
-										TranscodeProfile dprofile = null;
-										try {
-											dprofile = renderer.getDefaultTranscodeProfile();
-										} catch (TranscodeException e) {
-										}
-										menu.setData((profile.equals(dprofile))
-												? Boolean.TRUE : Boolean.FALSE);
-										
-										menu.setEnabled( renderer.getTranscodeRequirement() != TranscodeTarget.TRANSCODE_NEVER );
-									}
-								}
-							});
-					}
-				}
-				
-				// publish to RSS feed
-				
-				if ( true ){
-					
-					need_sep = true;
-					
-					final MenuItem rss_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.rsspub");
-					rss_menu_item.setStyle(MenuItem.STYLE_CHECK);
-
-					rss_menu_item.addFillListener(new MenuItemFillListener() {
-						public void menuWillBeShown(MenuItem menu, Object data) {
-							rss_menu_item.setEnabled( device_manager.isRSSPublishEnabled());
-							
-							menu.setData(new Boolean(device_manager.isRSSPublishEnabled() && renderer.isRSSPublishEnabled()));
-						}
-					});
-					rss_menu_item.addListener(new MenuItemListener() {
-						public void selected(MenuItem menu, Object target) {
-			 				renderer.setRSSPublishEnabled((Boolean) menu.getData());
-						}
-					});
-					
-					rss_menu_item.setEnabled( device_manager.isRSSPublishEnabled());
-				}
-			}
-
-			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;
-				
-				MenuItem browse_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.browse");
-				
-				browse_menu_item.setStyle( MenuItem.STYLE_MENU );
-				
-				browse_menu_item.addFillListener( will_browse_listener );
-			}
-			
-			
-			if ( need_sep ){
-				
-				menu_manager.addMenuItem("sidebar." + key, "s2" ).setStyle( MenuItem.STYLE_SEPARATOR );
-			}
-			
-				// rename
-			
-			MenuItem rename_menu_item = menu_manager.addMenuItem("sidebar." + key, "MyTorrentsView.menu.rename" );
-			
-			rename_menu_item.addListener( rename_listener );									
-			
-				// export
-			
-			if ( device.isExportable()){
-				
-				MenuItem export_item = menu_manager.addMenuItem("sidebar." + key,"Subscription.menu.export");
-				
-				export_item.addListener( export_listener );
-			}
-			
-				// hide
-			
-			MenuItem hide_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.hide");
-			
-			hide_menu_item.addListener( hide_listener );
-			
-				// tag
-			
-			MenuItem tag_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.tag");
-			
-			tag_menu_item.setStyle( MenuItem.STYLE_CHECK );
-			
-			tag_menu_item.addFillListener( will_tag_listener );
-
-			tag_menu_item.addListener(tag_listener );
-
-				// remove
-			
-			MenuItem remove_menu_item = menu_manager.addMenuItem("sidebar." + key, "MySharesView.menu.remove");
-			
-			remove_menu_item.addFillListener( will_remove_listener );
-				
-			remove_menu_item.addListener( remove_listener );
-
-				// sep
-			
-			menu_manager.addMenuItem("sidebar." + key, "s3" ).setStyle( MenuItem.STYLE_SEPARATOR );
-			
-			final URL wiki_url = device.getWikiURL();
-			
-			if ( wiki_url != null ){
-				
-				MenuItem wiki_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.wiki");
-
-				wiki_menu_item.addListener(
-					new MenuItemListener()
-					{
-						public void 
-						selected(
-							MenuItem 	menu,
-							Object 		target ) 
-						{
-							Utils.launch( wiki_url.toExternalForm());
-						}
-					});
-			}
-			
-			// props
-			
-			MenuItem menu_item = menu_manager.addMenuItem("sidebar." + key,"Subscription.menu.properties");
-			
-			menu_item.addListener( properties_listener );
-		}
-	}
-
-	protected static String
-	getDeviceImageID(
-		Device		device )
-	{
-		String imageID = device.getImageID();
-		if (imageID != null) {
-			return imageID;
-		}
-		
-		if (!(device instanceof DeviceMediaRenderer)) {
-			return "" + DeviceMediaRenderer.RS_OTHER;
-		}
-
-		int	species = ((DeviceMediaRenderer)device).getRendererSpecies();
-		
-		String	id;
-		
-		if ( species != DeviceMediaRenderer.RS_OTHER ){
-		
-			id = String.valueOf( species );
-			
-		}else{
-			
-			String	classification = device.getClassification();
-			
-			if ( classification.equals( "sony.PSP")){
-				
-				id = "psp";
-				
-			}else if ( classification.startsWith( "tivo.")){
-				
-				id = "tivo";
-			
-			}else if ( classification.startsWith( "samsung.")){
-
-				id = "samsung";
-				
-			}else if ( classification.startsWith( "western.digital.")){
-
-				id = "wdtv";
-				
-			}else if ( classification.startsWith( "boxee.")){
-
-				id = "boxee";
-
-			}else if ( classification.startsWith( "sony.bravia")){
-
-				id = "bravia";
-				
-			}else if ( classification.startsWith( "ms_wmp.")){
-
-				// update skin3_constants.properties!
-			
-				id = "mswmp";
-				
-			}else if ( classification.toLowerCase().contains( "android")){
-
-				id = "android";
-
-			}else if ( classification.toLowerCase().contains( "neotv")){
-
-				id = "neotv";
-
-			}else if ( classification.startsWith( "vuze-ms-browser.")){
-
-				id = "vuze";
-				
-			}else{
-				
-				if (device.isGenericUSB()) {
-					id = "usb";
-
-				} else {
-
-					id = String.valueOf( species );
-				}
-			}
-		}
-		
-		return( id );
-	}
-	
-	protected void
-	showDevice(
-		Device		device )
-	{
-		synchronized( this ){
-			
-			final deviceItem existing_di = (deviceItem)device.getTransientProperty( DEVICE_IVIEW_KEY );
-
-			if ( existing_di != null ){
-				
-				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-				
-				if ( mdi != null ){
-				
-					mdi.showEntry(existing_di.getMdiEntry());
-				}
-			}
-		}
-	}
-	
-	public static boolean
-	handleDrop(
-		final TranscodeTarget		target,
-		final Object				payload )
-	{
-		return( handleDropSupport( target, payload, true ));
-	}
-	
-	private static boolean
-	handleDropSupport(
-		final TranscodeTarget		target,
-		final Object				payload,
-		final boolean				allow_retry )
-	{
-		if (	!(payload instanceof String[]) && 
-				!(payload instanceof String) &&
-				!(payload instanceof URLTransfer.URLType )){
-					
-			return false;
-		}
-		TranscodeChooser deviceChooser = new TranscodeChooser(target) {
-			
-			public void 
-			closed() 
-			{
-				if ( selectedTranscodeTarget != null && selectedProfile != null ){
-					
-					handleDrop(
-						selectedTranscodeTarget, 
-						selectedProfile, 
-						payload,
-						getTranscodeRequirement());
-				}
-			}
-		};
-		
-		deviceChooser.show(
-			new Runnable()
-			{
-				public void
-				run()
-				{
-					if ( allow_retry ){
-					
-						handleDropSupport( target, payload, false );
-					}
-				}
-			});
-		return true;
-	}
-
-	protected static void
-	addDownload(
-		TranscodeTarget		target,
-		TranscodeProfile 	profile,
-		int					transcode_requirement,
-		byte[]				hash )
-	{
-		try{
-		
-			addDownload( target, profile, transcode_requirement, AzureusCoreFactory.getSingleton().getPluginManager().getDefaultPluginInterface().getShortCuts().getDownload(hash));
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-	}
-	
-	protected static void
-	addDownload(
-		TranscodeTarget		target,
-		TranscodeProfile 	profile,
-		int					transcode_requirement,
-		Download			download )
-	{
-			// we could use the primary file
-			// int index = DownloadManagerEnhancer.getSingleton().getEnhancedDownload(hash).getPrimaryFile().getIndex();
-			// DiskManagerFileInfo dm_file = plugin_interface.getShortCuts().getDownload(hash).getDiskManagerFileInfo()[index];
-	
-			// but lets just grab all files
-
-		DiskManagerFileInfo[] dm_files = download.getDiskManagerFileInfo();
-		
-		int	num_added = 0;
-		
-		for ( DiskManagerFileInfo dm_file: dm_files ){
-			
-				// limit number of files we can add to avoid crazyness
-			
-			if ( num_added > MAX_FILES_FOR_MULTI_XCODE ){
-				
-				break;
-			}
-			
-				// could be smarter here and check extension or whatever
-			
-			if ( dm_files.length == 1 || dm_file.getLength() >= MIN_FILE_SIZE_FOR_XCODE ){
-				
-				addFile( target, profile, transcode_requirement, dm_file );
-				
-				num_added++;
-			}
-		}
-	}
-	
-	protected static void
-	addFile(
-		TranscodeTarget			target,
-		TranscodeProfile 		profile,
-		int						transcode_requirement,
-		DiskManagerFileInfo		file )
-	{
-		try{
-			DeviceManagerFactory.getSingleton().getTranscodeManager().getQueue().add(
-				target,
-				profile,
-				file,
-				transcode_requirement,
-				false );
-			
-		}catch( Throwable e ){
-			
-			Debug.out( e );
-		}
-	}
-	
-	protected static void
-	addDirectory(
-		TranscodeTarget			target,
-		TranscodeProfile 		profile,
-		int						transcode_requirement,
-		File					file )
-	{
-		if ( !file.isDirectory()){
-			
-			return;
-		}
-		
-		File[]	files = file.listFiles();
-		
-		int	num_added = 0;
-		
-		for ( File f: files ){
-		
-			if ( num_added > MAX_FILES_FOR_MULTI_XCODE ){
-				
-				break;
-			}
-			
-			if ( f.isDirectory()){
-				
-				continue;
-			}
-			
-			if ( f.length() > MIN_FILE_SIZE_FOR_XCODE ){
-				
-				addFile( target, profile, transcode_requirement, f );
-				
-				num_added++;
-			}
-		}
-	}
-	
-	protected static void
-	addFile(
-		TranscodeTarget			target,
-		TranscodeProfile 		profile,
-		int						transcode_requirement,
-		File					file )
-	{
-		if ( file.exists() && file.isFile()){
-
-			try{
-				DeviceManagerFactory.getSingleton().getTranscodeManager().getQueue().add(
-					target,
-					profile,
-					new DiskManagerFileInfoFile( file ),
-					transcode_requirement,
-					false );
-				
-			}catch( Throwable e ){
-				
-				Debug.out( e );
-			}
-		}else{
-			
-			Debug.out( "Drop to " + target.getDevice().getName() + " for " + file + " failed, file doesn't exist" );
-		}
-	}
-	
-	protected static void
-	addURL(
-		TranscodeTarget			target,
-		TranscodeProfile 		profile,
-		int						transcode_requirement,
-		String					url )
-	{
-		try{
-			DeviceManagerFactory.getSingleton().getTranscodeManager().getQueue().add(
-				target,
-				profile,
-				new DiskManagerFileInfoURL( new URL( url )),
-				transcode_requirement,
-				false );
-				
-		}catch( Throwable e ){
-				
-			Debug.out( e );
-		}
-	}
-	
-	protected static void
-	handleDrop(
-		TranscodeTarget		target,
-		TranscodeProfile 	profile,
-		Object				payload,
-		int					transcode_requirement )
-	{
-		if ( payload instanceof String[]){
-			
-			String[]	files = (String[])payload;
-			
-			for ( String file: files ){
-			
-				File f = new File( file );
-
-				if ( f.isFile()){
-				
-					addFile( target, profile, transcode_requirement, f );
-					
-				}else{
-					
-					addDirectory( target, profile, transcode_requirement, f );
-				}
-			}
-		}else if ( payload instanceof String ){
-			
-			String stuff = (String)payload;
-			
-			if ( stuff.startsWith( "DownloadManager\n" ) ||stuff.startsWith( "DiskManagerFileInfo\n" )){
-				
-				String[]	bits =  Constants.PAT_SPLIT_SLASH_N.split(stuff);
-				
-				for (int i=1;i<bits.length;i++){
-					
-					String	hash_str = bits[i];
-					
-					int	pos = hash_str.indexOf(';');
-					
-					try{
-
-						if ( pos == -1 ){
-							
-							byte[]	 hash = Base32.decode( bits[i] );
-			
-							addDownload( target, profile, transcode_requirement, hash );
-										
-						}else{
-							
-							String[] files = hash_str.split(";");
-							
-							byte[]	 hash = Base32.decode( files[0].trim());
-							
-							DiskManagerFileInfo[] dm_files = AzureusCoreFactory.getSingleton().getPluginManager().getDefaultPluginInterface().getShortCuts().getDownload(hash).getDiskManagerFileInfo();
-							
-							for (int j=1;j<files.length;j++){
-								
-								DiskManagerFileInfo dm_file = dm_files[Integer.parseInt(files[j].trim())];
-								
-								addFile( target, profile, transcode_requirement, dm_file );
-							}
-						}
-					}catch( Throwable e ){
-						
-						Debug.out( "Failed to get download for hash " + bits[1] );
-					}
-				}
-			}else if ( stuff.startsWith( "TranscodeFile\n" )){
-				
-				String[]	bits =  Constants.PAT_SPLIT_SLASH_N.split(stuff);
-				
-				for (int i=1;i<bits.length;i++){
-					
-					File f = new File( bits[i] );
-
-					if ( f.isFile()){
-					
-						addFile( target, profile, transcode_requirement, f );
-					}
-				}
-			}else if ( stuff.startsWith( "http:" ) || stuff.startsWith( "https://" )){
-				
-				addURL( target, profile, transcode_requirement, stuff );
-			}
-		}else if ( payload instanceof URLTransfer.URLType ){
-			
-			String url = ((URLTransfer.URLType)payload).linkURL;
-			
-			if ( url != null ){
-				
-				addURL( target, profile, transcode_requirement, url );
-			}
-		}
-	}
-	
-	protected void
-	setStatus(
-		Device			device,
-		deviceItem		sbi )
-	{
-		sbi.setStatus( device );
-	}
-	
-	protected void
-	addAllDevices()
-	{
-		synchronized( this ){
-		
-			if ( device_manager_listener == null ){
-			
-				needsAddAllDevices = true;
-			
-				return;
-			}
-
-			if ( !device_manager_listener_added ){
-		
-				device_manager_listener_added	= true;
-				
-				device_manager.addListener( device_manager_listener );
-			}
-		}
-			
-			Device[] devices = device_manager.getDevices();
-			
-			Arrays.sort(
-				devices,
-				new Comparator<Device>()
-				{
-					public int 
-					compare(
-						Device o1, 
-						Device o2) 
-					{
-						return( o1.getName().compareToIgnoreCase( o2.getName()));
-					}
-				});
-			
-			for ( Device device: devices ){
-				
-				addOrChangeDevice( device );
-			}
-	}
-	
-	protected void
-	removeAllDevices()
-	{
-		synchronized( this ){
-		
-			if ( device_manager_listener_added ){
-			
-				device_manager_listener_added	= false;
-
-				device_manager.removeListener( device_manager_listener );
-			}
-		}
-
-		Device[] devices = device_manager.getDevices();
-		
-		for ( Device device: devices ){
-			
-			removeDevice( device );
-		}
-	}
-	
-	protected void
-	removeDevice(
-		final Device		device )
-	{
-		synchronized( this ){
-			
-			final deviceItem existing_di = (deviceItem)device.getTransientProperty( DEVICE_IVIEW_KEY );
-			
-			if ( existing_di != null ){
-				
-				device.setTransientProperty( DEVICE_IVIEW_KEY, null );
-				
-				existing_di.destroy();
-			}
-		}
-	}
-	
-	protected categoryView
-	addDeviceCategory(
-		int			device_type,
-		String		category_title,
-		String		category_image_id )
-	{
-		String key = "Device_" + category_title + ":" + nextSidebarID();
-		
-		categoryView eventListener;
-		
-		if ( device_type == Device.DT_INTERNET ){
-			
-			eventListener = new DeviceInternetView( this, category_title );
-					
-		}else{
-			
-			eventListener = new categoryViewGeneric( this, device_type, category_title );
-		}
-		
-		MdiEntry entry = mdi.createEntryFromEventListener(
-				SideBar.SIDEBAR_HEADER_DEVICES, eventListener, key, false, new Integer(
-						device_type), null);
-
-		addDefaultDropListener( entry );
-		
-		entry.setImageLeftID( category_image_id );
-				
-		eventListener.setDetails( entry, key );
-		
-		return( eventListener );
-	}
-	
-	protected void
-	addDefaultDropListener(
-		MdiEntry		mainSbEntry )
-	{
-		mainSbEntry.addListener(
-				new MdiEntryDropListener()
-				{
-					public boolean 
-					mdiEntryDrop(
-						MdiEntry 		entry, 
-						Object 				payload  )
-					{
-						return handleDrop(null, payload);
-					}
-				});
-	}
-	
-	protected void
-	showProperties(
-		Device		device )
-	{
-		String[][] props = device.getDisplayProperties();
-		
-		new PropertiesWindow( device.getName(), props[0], props[1] );
-	}
-	
-	protected int
-	nextSidebarID()
-	{
-		synchronized( this ){
-			
-			return( next_sidebar_id++ );
-		}
-	}
-	
-	protected abstract static class
-	categoryView
-		implements 	ViewTitleInfo, UISWTViewEventListener
-	{
-		private DeviceManagerUI	ui;
-		private int				device_type;
-		private String			title;
-			
-		private String			key;
-			
-		private MdiEntryVitalityImage spinner;
-		private MdiEntryVitalityImage warning;
-		private MdiEntryVitalityImage info;
-		
-		private int				last_indicator;
-		private MdiEntry mdiEntry;
-		private UISWTView swtView;
-		
-		protected
-		categoryView(
-			DeviceManagerUI		_ui,
-			int					_device_type,
-			String				_title )
-		{
-			ui				= _ui;
-			device_type		= _device_type;
-			title			= _title;
-		}
-		
-		protected void
-		setDetails(
-			MdiEntry	entry,
-			String			_key )
-		{
-			mdiEntry = entry;
-			
-			key			= _key;
-			
-			spinner = entry.addVitalityImage( SPINNER_IMAGE_ID );
-
-			hideIcon( spinner );
-			
-			warning = entry.addVitalityImage( ALERT_IMAGE_ID );
-
-			hideIcon( warning );
-			
-			info = entry.addVitalityImage( INFO_IMAGE_ID );
-
-			hideIcon( info );
-		}
-		
-		
-		protected int
-		getDeviceType()
-		{
-			return( device_type );
-		}
-		
-		protected String
-		getKey()
-		{
-			return( key );
-		}
-		
-		protected String
-		getTitle()
-		{
-			return( MessageText.getString( title ));
-		}
-		
-		public Object 
-		getTitleInfoProperty(
-			int propertyID ) 
-		{
-			boolean expanded = mdiEntry != null && mdiEntry.isExpanded();
-			
-			if ( propertyID == TITLE_TEXT ){
-				
-				return( getTitle());
-				
-			}else if ( propertyID == TITLE_INDICATOR_TEXT ){
-			
-				if ( device_type == Device.DT_MEDIA_RENDERER || device_type == Device.DT_OFFLINE_DOWNLOADER ){ 
-				
-					if ( spinner != null ){
-					
-						spinner.setVisible( !expanded && ui.getDeviceManager().isBusy( device_type ));
-					}
-					
-					if ( !expanded ){
-										
-						Device[] devices = ui.getDeviceManager().getDevices();
-						
-						last_indicator = 0;
-						
-						String all_errors 	= "";
-						String all_infos	= "";
-						
-						for ( Device device: devices ){
-							
-							if ( device_type != device.getType()){
-									
-								continue;
-							}
-							
-							String error = device.getError();
-							
-							if ( error != null ){
-								
-								all_errors += (all_errors.length()==0?"":"; ") + error;
-							}
-							
-							String info = device.getInfo();
-							
-							if ( info != null ){
-								
-								all_infos += (all_infos.length()==0?"":"; ") + info;
-							}
-							
-							if ( device instanceof DeviceMediaRenderer ){
-						
-								if ( SHOW_RENDERER_VITALITY ){
-									
-									DeviceMediaRenderer	renderer = (DeviceMediaRenderer)device;
-									
-									last_indicator += renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending();
-								}
-							}else if ( device instanceof DeviceOfflineDownloader ){
-								
-								if ( SHOW_OD_VITALITY ){
-									
-									DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device;
-									
-									last_indicator += dod.getTransferingCount();
-								}
-							}
-						}
-						
-						if ( all_errors.length() > 0 ){
-							 
-							showIcon( warning, all_errors );
-													
-						}else{
-							
-							hideIcon( warning );
-							
-							if ( all_infos.length() > 0 ){
-							
-								showIcon( info, all_infos );
-																			
-							}else{
-							
-								hideIcon( info );
-							}
-						}
-						
-						if ( last_indicator > 0 ){
-														
-							return( String.valueOf( last_indicator ));
-						}
-					}else{
-						
-						hideIcon( warning );
-						hideIcon( info );
-					}
-				}
-			}else if ( propertyID == TITLE_INDICATOR_COLOR ){
-				
-				/*
-				if ( last_indicator > 0 ){
-				
-					if ( SHOW_VITALITY ){
-					
-						return( to_copy_indicator_colors );
-					}
-				}
-				*/
-			}
-			
-			return null;
-		}
-		
-		protected void
-		destroy()
-		{
-			if ( Utils.isThisThreadSWT()){
-				
-				mdiEntry.close(false);
-				
-			}else{
-				
-				Utils.execSWTThread(
-						new Runnable()
-						{
-							public void
-							run()
-							{
-								mdiEntry.close(false);
-																
-							}
-						});
-			}
-		}
-
-		public boolean eventOccurred(UISWTViewEvent event) {
-	    switch (event.getType()) {
-	      case UISWTViewEvent.TYPE_CREATE:
-	      	swtView = (UISWTView)event.getData();
-	      	swtView.setTitle(title);
-	        break;
-	    }
-
-	    return true;
-	  }
-	}
-	
-	protected static class
-	categoryViewGeneric
-		extends 	categoryView
-	{
-		private Composite		composite;
-		
-		protected
-		categoryViewGeneric(
-			DeviceManagerUI		_ui,
-			int					_device_type,
-			String				_title )
-		{
-			super( _ui, _device_type, _title );
-		}
-		
-		public void 
-		initialize(
-			Composite parent_composite )
-		{  
-			composite = new Composite( parent_composite, SWT.NULL );
-			
-			FormLayout layout = new FormLayout();
-			
-			layout.marginTop	= 4;
-			layout.marginLeft	= 4;
-			layout.marginRight	= 4;
-			layout.marginBottom	= 4;
-			
-			composite.setLayout( layout );
-
-			FormData data = new FormData();
-			data.left = new FormAttachment(0,0);
-			data.right = new FormAttachment(100,0);
-			data.top = new FormAttachment(composite,0);
-			data.bottom = new FormAttachment(100,0);
-
-
-			Label label = new Label( composite, SWT.NULL );
-			
-			label.setText( "Nothing to show for " + getTitle());
-			
-			label.setLayoutData( data );
-		}
-		
-		public Composite 
-		getComposite()
-		{
-			return( composite );
-		}
-		
-		public boolean eventOccurred(UISWTViewEvent event) {
-	    switch (event.getType()) {
-	      case UISWTViewEvent.TYPE_CREATE:
-	      	//swtView = (UISWTView)event.getData();
-	        break;
-
-	      case UISWTViewEvent.TYPE_DESTROY:
-	        break;
-
-	      case UISWTViewEvent.TYPE_INITIALIZE:
-	        initialize((Composite)event.getData());
-	        break;
-
-	      case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
-	      	Messages.updateLanguageForControl(getComposite());
-	        break;
-
-	      case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
-	        break;
-	        
-	      case UISWTViewEvent.TYPE_FOCUSGAINED:
-	      	break;
-	        
-	      case UISWTViewEvent.TYPE_REFRESH:
-	        break;
-	    }
-
-	    return true;
-	  }
-	}
-	
-	protected class
-	deviceView
-		implements 	ViewTitleInfo, TranscodeTargetListener, UISWTViewEventListener
-	{
-		private String			parent_key;
-		private Device			device;
-		
-		private Composite		parent_composite;
-		private Composite		composite;
-		
-		private int last_indicator;
-		private UISWTView swtView;
-
-		protected
-		deviceView(
-			String			_parent_key,
-			Device			_device )
-		{
-			parent_key	= _parent_key;
-			device		= _device;
-			
-			if ( device instanceof DeviceMediaRenderer ){
-				
-				DeviceMediaRenderer	renderer = (DeviceMediaRenderer)device;
-
-				renderer.addListener( this );
-			}
-		}
-			
-		public void 
-		initialize(
-			Composite _parent_composite )
-		{  
-			parent_composite	= _parent_composite;
-
-			composite = new Composite( parent_composite, SWT.NULL );
-			
-			FormLayout layout = new FormLayout();
-			
-			layout.marginTop	= 4;
-			layout.marginLeft	= 4;
-			layout.marginRight	= 4;
-			layout.marginBottom	= 4;
-			
-			composite.setLayout( layout );
-			
-			if ( device instanceof DeviceContentDirectory ){
-				
-				Label  ms_label = new Label( composite, SWT.NULL );				
-				ms_label.setText( "Media Server: " + device.getName());
-				
-				final Button refresh = new Button( composite, SWT.PUSH );				
-				refresh.setText( "Refresh" );
-
-				final StyledText   info = 
-					new StyledText(composite, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL)
-					{
-						private boolean adding = false;
-						private Event	last_event;
-						
-						public void
-						addListener(
-							int 			eventType, 
-							final Listener	listener)
-						{
-							if ( eventType == SWT.MouseDown && !adding ){
-								
-								try{
-									adding = true;
-								
-									super.addListener(
-										eventType,
-										new Listener()
-										{
-											public void 
-											handleEvent(
-												Event event )
-											{
-												if ( event.type == SWT.MouseDown && event != last_event ){
-													
-													if ( event.button == 1 && event.stateMask != SWT.CONTROL ){
-														
-														last_event = event;
-														
-														try{
-																// this code is to allow a click+drag operation to work as StyledText needs a selection
-																// before it will initiate a drag
-															
-															int offset = getOffsetAtLocation( new Point( event.x, event.y ));
-															
-															final StyleRange style = getStyleRangeAtOffset(offset);
-															
-															if ( style != null ){
-																
-																Object data = style.data;
-																
-																if ( data instanceof UPNPMSItem ){
-																	
-																	int line 		= getLineAtOffset(offset);
-																	int lineOffset 	= getOffsetAtLine(line);	
-																	
-																	setSelection( lineOffset, lineOffset + getLine( line ).length());
-																}
-															}	
-														}catch( Throwable e){
-														}
-													}
-												}
-																								
-												listener.handleEvent( event );
-											}	
-											
-										});
-								}finally{
-									
-									adding = false;
-								}
-							}else{
-								
-								super.addListener(eventType, listener);
-							}
-						}
-					};
-
-				info.setEditable( false );
-				
-				info.setSelectionForeground( info.getForeground());
-				info.setSelectionBackground( info.getBackground());
-				
-				FormData data = new FormData();				
-				data.left 	= new FormAttachment(0,0);
-				data.bottom = new FormAttachment(info,-8);
-				ms_label.setLayoutData( data );
-				
-				
-				data = new FormData();
-				data.left 	= new FormAttachment(ms_label,4 );
-				data.top 	= new FormAttachment(composite,0);
-				refresh.setLayoutData( data );
-									
-
-				data = new FormData();				
-				data.left 	= new FormAttachment(0,0);
-				data.right 	= new FormAttachment(100,0);
-				data.top 	= new FormAttachment(refresh,4);
-				data.bottom = new FormAttachment(100,0);
-				info.setLayoutData( data );
-
-				final Runnable do_refresh =
-					new Runnable()
-					{
-						private	UPNPMSItem dragging_item;
-						
-						{
-							final DragSource drag_source = new DragSource(info, DND.DROP_MOVE | DND.DROP_COPY);
-							
-							drag_source.setTransfer( new Transfer[] { TextTransfer.getInstance() });
-							
-							drag_source.addDragListener(
-								new DragSourceAdapter() 
-								{	
-									public void 
-									dragStart(
-										DragSourceEvent event ) 
-									{		
-										event.doit = false;
-										
-										try{
-											int offset = info.getOffsetAtLocation(new Point(event.x, event.y));
-											
-											StyleRange style = info.getStyleRangeAtOffset(offset);
-											
-											if ( style != null ){
-												
-												Object data = style.data;
-												
-												if ( data instanceof UPNPMSItem ){
-													
-													UPNPMSItem item = (UPNPMSItem)data;
-														
-													if ( item.getURL() != null ){
-													
-														dragging_item = item;
-													
-														event.doit = true;
-													}
-												}
-											}
-										}catch( Throwable e ){	
-										}
-									}
-									
-									public void 
-									dragSetData(
-										DragSourceEvent event) 
-									{
-										if ( dragging_item != null ){
-											
-											String url = dragging_item.getURL().toExternalForm();
-											
-												// these parameters are used to identify this as a content-data relative
-												// URL as opposed to a torrent download one, and also provide the content name
-											
-											url += ( url.contains( "?" )?"&":"?") + "azcdid=" + RandomUtils.INSTANCE_ID + "&azcddn=" + UrlUtils.encode( dragging_item.getTitle());
-																					
-											event.data = url;
-											
-										}else{
-											
-											event.data 	= null;
-											event.doit	= false;
-										}
-									}
-									
-									public void 
-									dragFinished(
-										DragSourceEvent event) 
-									{
-										dragging_item = null;
-										
-										try{
-											Point selection = info.getSelection();
-											
-											info.setSelection( selection.x, selection.x );
-											
-										}catch( Throwable e ){	
-										}
-									}
-								});
-							
-							final DropTarget drop_target = new DropTarget(info, DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK);
-							
-							drop_target.setTransfer(new Transfer[0]);
-
-							info.addDisposeListener(
-								new DisposeListener() 
-								{
-									public void 
-									widgetDisposed(
-										DisposeEvent e ) 
-									{
-										if (!drag_source.isDisposed()) {
-											drag_source.dispose();
-										}
-										
-										if (!drop_target.isDisposed()) {
-											drop_target.dispose();
-										}
-									}
-								});
-							
-					
-							
-							info.addMouseListener(
-								new MouseListener()
-								{
-									public void 
-									mouseDoubleClick(
-										MouseEvent arg0) 
-									{
-									}
-									
-									public void 
-									mouseDown(
-										MouseEvent event) 
-									{
-										if ( info.isDisposed()){
-											return;
-										}
-										
-										try{
-											int offset = info.getOffsetAtLocation(new Point (event.x, event.y));
-											
-											StyleRange style = info.getStyleRangeAtOffset(offset);
-											
-											if ( style != null ){
-												
-												Object data = style.data;
-												
-												if ( data instanceof UPNPMSItem ){
-													
-													UPNPMSItem item = (UPNPMSItem)data;
-													
-													if (	event.button == 3 || 
-															(event.button == 1 && event.stateMask == SWT.CONTROL)){
-														
-														  final Menu menu = new Menu(info.getShell(),SWT.POP_UP);
-														  
-														  final URL url = item.getURL();
-															
-														  if ( url != null ){
-	
-															  org.eclipse.swt.widgets.MenuItem   menu_item = new org.eclipse.swt.widgets.MenuItem( menu,SWT.NONE );
-		
-															  menu_item.setText( MessageText.getString( "devices.copy_url"));
-		
-															  menu_item.addSelectionListener(
-																  new SelectionAdapter()
-																  {
-																	  public void 
-																	  widgetSelected(
-																			  SelectionEvent arg0) 
-																	  {
-																		  ClipboardCopy.copyToClipBoard(url.toExternalForm());
-																	  }
-																  });
-															  
-															 
-															  menu_item = new org.eclipse.swt.widgets.MenuItem( menu,SWT.NONE );
-																	
-															  menu_item.setText( MessageText.getString( "iconBar.run"));
-			
-															  menu_item.addSelectionListener(
-																  new SelectionAdapter()
-																  {
-																	  public void 
-																	  widgetSelected(
-																		  SelectionEvent arg0) 
-																	  {
-																		 Utils.launch( url );
-																	  }
-																  });
-															 
-														  
-															  menu_item.setEnabled( item.getItemClass() != UPNPMSItem.IC_OTHER );
-														  }
-														  
-														  info.setMenu( menu );
-	
-														  menu.addMenuListener(
-																  new MenuAdapter()
-																  {
-																	  public void 
-																	  menuHidden(
-																			  MenuEvent arg0 )
-																	  {
-																		  if ( info.getMenu() == menu ){
-																		  
-																			  info.setMenu( null );
-																		  }
-																	  }
-																  });
-	
-														  menu.setVisible( true );
-													}
-												}
-											}
-										}catch( Throwable e ){
-										}
-									}
-									
-									public void 
-									mouseUp(
-										MouseEvent event) 
-									{
-										if ( info.isDisposed()){
-											return;
-										}
-										
-										try{
-											int offset = info.getOffsetAtLocation(new Point (event.x, event.y));
-											
-											StyleRange style = info.getStyleRangeAtOffset(offset);
-											
-											if ( style != null ){
-												
-												Object data = style.data;
-												
-												if ( data instanceof UPNPMSItem ){
-													
-													UPNPMSItem item = (UPNPMSItem)data;
-													
-													if ( event.button == 1 ){
-															
-														if ( style.underline ){
-														
-															URL url = item.getURL();
-														
-															if ( url != null ){
-															
-																PlayUtils.playURL( url, item.getTitle());
-															}
-														}
-													}
-												}
-											}
-										}catch( Throwable e ){
-										}
-									}
-								});
-					
-							info.addMouseTrackListener(
-									new MouseTrackAdapter()
-									{
-										@Override
-										public void 
-										mouseHover(
-											MouseEvent event ) 
-										{
-											if ( info.isDisposed()){
-												return;
-											}
-											
-											String tooltip = "";
-											
-											try{
-												int offset = info.getOffsetAtLocation(new Point (event.x, event.y));
-												
-												StyleRange style = info.getStyleRangeAtOffset(offset);
-												
-												if ( style != null ){
-													
-													Object data = style.data;
-													
-													if ( data instanceof UPNPMSItem ){
-														
-														UPNPMSItem item = (UPNPMSItem)data;
-														
-														if ( item != null ){
-															
-															tooltip = DisplayFormatters.formatByteCountToKiBEtc( item.getSize());
-														}
-													}
-												}
-											}catch( Throwable e ){
-												
-											}
-											
-											info.setToolTipText( tooltip );
-										}
-									});
-							
-							info.addMouseMoveListener(
-								new MouseMoveListener()
-								{
-									private StyleRange	last_style;
-									
-									public void 
-									mouseMove(
-										MouseEvent event) 
-									{
-										try{
-											int offset = info.getOffsetAtLocation(new Point (event.x, event.y));
-										
-											StyleRange style = info.getStyleRangeAtOffset(offset);
-										
-											if ( style != last_style ){
-												
-												last_style = style;
-												
-												info.setToolTipText( "" );
-											}
-										}catch( Throwable e ){											
-										}
-									}
-								});
-						}
-						
-						boolean play_available;
-						
-						public void
-						run()
-						{
-							boolean	went_async = false;
-							
-							try{
-								refresh.setEnabled( false );
-							
-								info.setText( "" );
-								
-								play_available = PlayUtils.isEMPAvailable();
-								
-								final DeviceContentDirectory cd = (DeviceContentDirectory)device;
-								
-								final List<URL> endpoints = cd.getControlURLs();
-				
-								if ( endpoints == null || endpoints.size() == 0 ){
-				
-									info.append( "Media Server is offline" );
-									
-								}else{
-									
-									new AEThread2( "CD:populate" )
-									{
-										private int				line_count;
-										private List<Object[]>	lines_to_add = new ArrayList<Object[]>();
-										
-										
-										public void
-										run()
-										{
-											try{
-												String client_name = device_manager.getLocalServiceName();
-												
-												UPNPMSBrowser browser = 
-													UPNPMSBrowserFactory.create( 
-														client_name, 
-														endpoints,
-														new UPNPMSBrowserListener()
-														{
-															public void 
-															setPreferredURL(
-																URL url )
-															{
-																cd.setPreferredControlURL( url );
-															}
-														});
-												
-												print( browser.getRoot(), "" );
-																				
-											}catch( Throwable e ){
-												
-												Debug.out( e );
-												
-											}finally{
-												
-												Utils.execSWTThread(
-														new Runnable()
-														{
-															public void
-															run()
-															{
-																if ( !refresh.isDisposed()){
-															
-																	refresh.setEnabled( true );
-																}
-															}
-														});
-											}
-										}
-										
-										private boolean
-										print(
-											UPNPMSContainer		container,
-											String				indent )
-										
-											throws UPnPMSException
-										{
-											if ( !appendLine( indent, container )){
-												
-												return( false );
-											}
-											
-											try{
-												indent += "\t\t";
-												
-												List<UPNPMSNode> kids = container.getChildren();
-												
-												for ( UPNPMSNode kid: kids ){
-												
-													if ( kid instanceof UPNPMSContainer){
-													
-														if ( !print((UPNPMSContainer)kid, indent )){
-															
-															return( false );
-														}
-														
-													}else{
-														
-														if ( !print((UPNPMSItem)kid, indent )){
-															
-															return( false );
-														}
-													}
-												}
-												
-												return( true );
-												
-											}finally{
-											
-												updateInfo();
-											}
-										}
-										
-										private boolean
-										print(
-											UPNPMSItem			item,
-											String				indent )
-										{
-											return( appendLine( indent, item ));
-										}
-										
-										private boolean
-										appendLine(
-											String	indent,
-											Object	obj )
-										{
-											line_count++;
-											
-											if ( line_count >= max_ms_display_lines ){
-												
-												if ( line_count == max_ms_display_lines ){
-												
-													lines_to_add.add( new Object[]{ indent, "Too many entries, output truncated..." });
-												}
-												
-												return( false );
-												
-											}else{
-											
-												lines_to_add.add( new Object[]{ indent, obj });
-												
-												return( true );
-											}
-										}
-										
-										private void
-										updateInfo()
-										{
-											if ( info.isDisposed()){
-												
-												return;
-											}
-											
-											final List<Object[]> temp = lines_to_add;
-											
-											lines_to_add = new ArrayList<Object[]>();
-											
-											Utils.execSWTThread(
-												new Runnable()
-												{
-													public void
-													run()
-													{
-														if ( info.isDisposed()){
-															
-															return;
-														}
-														
-														for ( Object[] entry: temp ){
-															
-															String	indent 	= (String)entry[0];
-															Object	obj		= entry[1];
-															
-															String line = indent;
-															
-															if ( obj instanceof UPNPMSContainer ){
-																
-																UPNPMSContainer container = (UPNPMSContainer)obj;
-															
-																line += container.getTitle();
-																
-																line += "\r\n";
-																
-																int	start_pos = info.getCharCount();
-																															
-																info.append( line );
-																
-																StyleRange style = new StyleRange(start_pos, line.length(), null, null, SWT.BOLD );
-																										
-																info.setStyleRange( style );
-															
-															}else if ( obj instanceof UPNPMSItem ){
-																
-																UPNPMSItem item = (UPNPMSItem)obj;
-																
-																line += item.getTitle();
-																
-																line += "\r\n";
-																
-																int	start_pos = info.getCharCount();
-																															
-																info.append( line );
-																
-																String item_class = item.getItemClass();
-																
-																if ( 	play_available &&
-																		item.getURL() != null &&
-																		(	item_class == UPNPMSItem.IC_VIDEO ||
-																			item_class == UPNPMSItem.IC_AUDIO )){
-																	
-																	StyleRange style = new StyleRange(start_pos + indent.length(), line.length() - indent.length(), null, null, SWT.NORMAL );
-																			
-																	style.underline 		= true;
-																	style.underlineStyle 	= SWT.UNDERLINE_LINK;
-																	
-																	style.data = item;
-																	
-																	info.setStyleRange( style );
-																	
-																}else{
-																	
-																	StyleRange style = new StyleRange(start_pos, line.length(), null, null, SWT.ITALIC );
-																	
-																	style.data = item;
-																	
-																	info.setStyleRange( style );
-																}
-															}else{
-																
-																line += (String)obj;
-																
-																line += "\r\n";
-																
-																int	start_pos = info.getCharCount();
-																															
-																info.append( line );
-																
-																StyleRange style = new StyleRange(start_pos, line.length(), null, null, SWT.NULL );
-																										
-																info.setStyleRange( style );
-															}
-														}
-													}
-												});
-										}
-									}.start();
-									
-									went_async = true;
-								}
-							}finally{
-								if ( !went_async ){
-								
-									refresh.setEnabled( true );
-								}
-							}
-						}
-					};
-					
-				do_refresh.run();
-				
-				refresh.addListener(
-					SWT.Selection,
-					new Listener()
-					{
-						public void 
-						handleEvent(Event arg0) 
-						{
-							do_refresh.run();
-						}
-					});
-			}else{
-				
-				FormData data = new FormData();
-				
-				data.left 	= new FormAttachment(0,0);
-				data.right 	= new FormAttachment(100,0);
-				data.top 	= new FormAttachment(composite,0);
-				data.bottom = new FormAttachment(100,0);
-
-				Label label = new Label( composite, SWT.NULL );
-				
-				label.setText( "Nothing to show for " + device.getName());
-				
-				label.setLayoutData( data );
-			}
-		}
-		
-		public Composite 
-		getComposite()
-		{
-			return( composite );
-		}
-		
-		public Object 
-		getTitleInfoProperty(
-			int propertyID ) 
-		{		
-			if ( propertyID == TITLE_TEXT ){
-				
-				return( getTitle());
-				
-			} else if (propertyID == TITLE_IMAGEID) {
-				String imageID = null;
-				final String id = getDeviceImageID( device );
-				
-				if ( id != null ){
-					
-					imageID = "image.sidebar.device." + id + ".small";
-
-					if (id.startsWith("http")) {
-						if (ImageLoader.getInstance().imageAdded_NoSWT(id)) {
-							imageID = id;
-						} else {
-  						Utils.execSWTThreadLater(0, new AERunnable() {
-  							public void runSupport() {
-  								ImageLoader.getInstance().getUrlImage(id, new ImageDownloaderListener() {
-  									public void imageDownloaded(Image image, boolean returnedImmediately) {
-  										ViewTitleInfoManager.refreshTitleInfo( deviceView.this );
-  									}
-  								});
-  							}
-  						});
-						}
-					}
-				}
-				
-				return imageID;
-				
-			}else if ( propertyID == TITLE_INDICATOR_TEXT ){
-				
-				if ( device instanceof DeviceMediaRenderer ){
-					
-					if ( SHOW_RENDERER_VITALITY ){
-					
-						DeviceMediaRenderer	renderer = (DeviceMediaRenderer)device;
-					
-					
-						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 ){
-					
-						return( to_copy_indicator_colors );
-					}
-				}
-				*/
-			}else if ( propertyID == TITLE_ACTIVE_STATE ){
-
-				if ( device.isLivenessDetectable()){
-				
-					return( new Long( device.isAlive()?1:2 ));
-				}
-			}else if ( propertyID == TITLE_INDICATOR_TEXT_TOOLTIP){
-
-				return( device.getStatus());
-			}
-			
-			return null;
-		}
-		
-		public String
-		getTitle()
-		{
-			return( device.getName());
-		}
-		
-		public void
-		fileAdded(
-			TranscodeFile		file )
-		{	
-		}
-		
-		public void
-		fileChanged(
-			TranscodeFile		file,
-			int					type,
-			Object				data )
-		{
-			if ( 	type == TranscodeTargetListener.CT_PROPERTY &&
-					data == TranscodeFile.PT_COMPLETE ){
-				
-				refreshTitles();
-			}
-		}
-		
-		protected void
-		refreshTitles()
-		{
-			ViewTitleInfoManager.refreshTitleInfo( this );
-
-			String	key = parent_key;
-			
-			while( key != null ){
-			
-				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-				
-				if ( mdi == null ){
-					
-					break;
-					
-				}else{
-					
-					MdiEntry parent = mdi.getEntry( key );
-				
-					if ( parent != null ){
-					
-						ViewTitleInfoManager.refreshTitleInfo(parent.getViewTitleInfo());
-						
-						key = parent.getParentID();
-					} else {
-						key = null;
-					}
-				}
-			}
-		}
-		
-		public void
-		fileRemoved(
-			TranscodeFile		file )
-		{	
-		}
-		
-		private void
-		delete()
-		{
-			if ( device instanceof DeviceMediaRenderer ){
-				
-				DeviceMediaRenderer	renderer = (DeviceMediaRenderer)device;
-
-				renderer.removeListener( this );
-			}
-		}
-
-		public boolean eventOccurred(UISWTViewEvent event) {
-	    switch (event.getType()) {
-	      case UISWTViewEvent.TYPE_CREATE:
-	      	swtView = (UISWTView)event.getData();
-	      	swtView.setTitle(getTitle());
-	        break;
-
-	      case UISWTViewEvent.TYPE_DESTROY:
-	        delete();
-	        break;
-
-	      case UISWTViewEvent.TYPE_INITIALIZE:
-	        initialize((Composite)event.getData());
-	        break;
-
-	      case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
-	      	Messages.updateLanguageForControl(getComposite());
-	      	swtView.setTitle(getTitle());
-	        break;
-
-	      case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
-	        break;
-	        
-	      case UISWTViewEvent.TYPE_FOCUSGAINED:
-	      	break;
-	        
-	      case UISWTViewEvent.TYPE_REFRESH:
-	        break;
-	    }
-
-	    return true;
-	  }
-
-	}
-	
-	private static class
-	deviceItem
-	{		
-		private deviceView			view;
-		private MdiEntry		sb_entry;
-		private boolean				destroyed;
-		
-		private MdiEntryVitalityImage	warning;
-		private MdiEntryVitalityImage	spinner;
-		private MdiEntryVitalityImage	info;
-		
-		protected
-		deviceItem()
-		{
-		}
-		
-		protected void
-		setMdiEntry(
-			MdiEntry	_sb_entry )
-		{
-			sb_entry	= _sb_entry;
-			
-			warning = sb_entry.addVitalityImage( ALERT_IMAGE_ID );
-			
-			hideIcon( warning );
-			
-			spinner = sb_entry.addVitalityImage( SPINNER_IMAGE_ID );
-			
-			hideIcon( spinner );
-			
-			info = sb_entry.addVitalityImage( INFO_IMAGE_ID );
-			
-			hideIcon( info );
-		}
-		
-		protected MdiEntry
-		getMdiEntry()
-		{
-			return( sb_entry );
-		}
-		
-		protected void
-		setView(
-			deviceView		_view )
-		{
-			view	= _view;
-		}
-		
-		protected deviceView
-		getView()
-		{
-			return( view );
-		}
-		
-		protected void
-		setStatus(
-			Device	device )
-		{
-				// possible during initialisation, status will be shown again on complete
-			
-			if ( warning != null && info != null ){
-							
-				String error = device.getError();
-				
-				if ( error != null ){
-				 
-					hideIcon( info );
-					
-					warning.setToolTip( error );
-					
-					warning.setImageID( ALERT_IMAGE_ID );
-					
-					warning.setVisible( true );
-					
-				}else{
-					
-					hideIcon( warning );
-					
-					String info_str = device.getInfo();
-					
-					if ( info_str != null ){
-						
-						showIcon( info, info_str );
-						
-					}else{
-						
-						hideIcon( info );
-					}
-				}
-			}
-			
-			if ( spinner != null ){
-						
-				spinner.setVisible( device.isBusy());
-			}
-			
-			if ( view != null ){
-				
-				view.refreshTitles();
-			}
-		}
-		
-		protected boolean
-		isDestroyed()
-		{
-			return( destroyed );
-		}
-		
-		protected void
-		destroy()
-		{
-			destroyed = true;
-			
-			if (sb_entry != null) {
-				sb_entry.close(false);
-			}
-		}
-		
-		public void 
-		activate() 
-		{
-			MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-			
-			if ( mdi != null && sb_entry != null ){
-				
-				mdi.showEntryByID(sb_entry.getId());
-			}
-		}
-	}
-}
+/*
+ * Created on Jan 27, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.devices;
+
+
+import java.io.File;
+import java.net.InetAddress;
+import java.net.URL;
+import java.util.*;
+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.dnd.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+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.config.COConfigurationManager;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.platform.PlatformManager;
+import org.gudy.azureus2.platform.PlatformManagerFactory;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.PluginManager;
+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.*;
+import org.gudy.azureus2.plugins.ui.config.*;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
+import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
+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.plugins.utils.StaticUtilities;
+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.mainwindow.ClipboardCopy;
+import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
+import org.gudy.azureus2.ui.swt.plugins.*;
+import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
+import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
+import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.devices.*;
+import com.aelitis.azureus.core.devices.DeviceManager.DeviceManufacturer;
+import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice;
+import com.aelitis.azureus.core.download.DiskManagerFileInfoFile;
+import com.aelitis.azureus.core.download.DiskManagerFileInfoURL;
+import com.aelitis.azureus.core.download.StreamManager;
+import com.aelitis.azureus.core.messenger.config.PlatformDevicesMessenger;
+import com.aelitis.azureus.core.tag.*;
+import com.aelitis.azureus.core.vuzefile.VuzeFile;
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
+import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager;
+import com.aelitis.azureus.ui.mdi.*;
+import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
+import com.aelitis.azureus.ui.swt.devices.add.DeviceTemplateChooser;
+import com.aelitis.azureus.ui.swt.devices.add.DeviceTemplateChooser.DeviceTemplateClosedListener;
+import com.aelitis.azureus.ui.swt.devices.add.ManufacturerChooser;
+import com.aelitis.azureus.ui.swt.devices.add.ManufacturerChooser.ClosedListener;
+import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+import com.aelitis.azureus.ui.swt.imageloader.ImageLoader.ImageDownloaderListener;
+import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
+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.SkinViewManager.SkinViewManagerListener;
+import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
+import com.aelitis.azureus.util.PlayUtils;
+import com.aelitis.net.upnpms.*;
+
+public class 
+DeviceManagerUI 
+{
+	private static final String CONFIG_SECTION_ID = "Devices";
+
+	// Not supported for Unix and OSX PPC
+	public static boolean DISABLED;
+	
+	private static final int MIN_FILE_SIZE_FOR_XCODE	= 128*1024;
+	private static final int MAX_FILES_FOR_MULTI_XCODE	= 64;
+	
+	private static final Object	DEVICE_IVIEW_KEY = new Object();
+	
+	private static final String CONFIG_VIEW_TYPE				= "device.sidebar.ui.viewtype";
+	
+	public static final String CONFIG_VIEW_HIDE_REND_GENERIC	= DeviceManager.CONFIG_VIEW_HIDE_REND_GENERIC;
+	public static final String CONFIG_VIEW_SHOW_ONLY_TAGGED		= DeviceManager.CONFIG_VIEW_SHOW_ONLY_TAGGED;
+	
+	private static final String SPINNER_IMAGE_ID 	= "image.sidebar.vitality.dl";
+	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_RENDERER_VITALITY 	= false;
+	private static final boolean	SHOW_OD_VITALITY 		= true;
+	
+	//private static final String[] to_copy_indicator_colors = { "#000000", "#000000", "#168866", "#1c5620" };
+	
+	private DeviceManager			device_manager;
+	private DeviceManagerListener	device_manager_listener;
+	private boolean					device_manager_listener_added;
+	
+	private final PluginInterface	plugin_interface;
+	private final UIManager			ui_manager;
+	
+	private UISWTInstance			swt_ui;
+	
+	private boolean		ui_setup;
+	
+	private MultipleDocumentInterfaceSWT		mdi;
+	private boolean		sidebar_built;
+	
+	private static final int SBV_SIMPLE		= 0;
+	private static final int SBV_FULL		= 0x7FFFFFFF;
+	
+	private int			side_bar_view_type		= COConfigurationManager.getIntParameter( CONFIG_VIEW_TYPE, SBV_SIMPLE );
+	private boolean		side_bar_hide_rend_gen	= COConfigurationManager.getBooleanParameter( CONFIG_VIEW_HIDE_REND_GENERIC, true );
+	private boolean		side_bar_show_tagged	= COConfigurationManager.getBooleanParameter( CONFIG_VIEW_SHOW_ONLY_TAGGED, false );
+	
+	private int			next_sidebar_id;
+		
+	private List<categoryView>	categories = new ArrayList<categoryView>();
+	
+	
+	private MenuItemListener properties_listener;
+	private MenuItemListener hide_listener;
+	private MenuItemListener rename_listener;
+	private MenuItemListener export_listener;
+	
+	private MenuItemFillListener	will_remove_listener;
+	private MenuItemListener 		remove_listener;
+	
+	private MenuItemFillListener	show_fill_listener;
+	private MenuItemListener 		show_listener;
+
+	private MenuItemFillListener	will_tag_listener;
+	private MenuItemListener 		tag_listener;
+
+	private MenuItemFillListener will_browse_listener;
+	
+	private boolean	offline_menus_setup;
+
+	private MdiEntry mdiEntryOverview;
+
+	private boolean needsAddAllDevices;
+
+	private MdiEntry entryHeader;
+	
+	private static final String	OXC_NOTHING		= "Nothing";
+	private static final String	OXC_QUIT_VUZE	= AzureusCore.CA_QUIT_VUZE;
+	private static final String	OXC_SLEEP		= AzureusCore.CA_SLEEP;
+	private static final String	OXC_HIBERNATE	= AzureusCore.CA_HIBERNATE;
+	private static final String	OXC_SHUTDOWN	= AzureusCore.CA_SHUTDOWN;
+	
+	private String 	oxc_action		= OXC_NOTHING;
+	private boolean	oxc_trigger_set	= false;
+	
+	private static final int	MAX_MS_DISPLAY_LINE_DEFAULT = 5000;
+	
+	private static int	max_ms_display_lines;
+	
+	static{
+		COConfigurationManager.addAndFireParameterListener(
+			"Plugin.default.device.config.ms.maxlines",
+			new org.gudy.azureus2.core3.config.ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					String name ) 
+				{
+					max_ms_display_lines = COConfigurationManager.getIntParameter( name, MAX_MS_DISPLAY_LINE_DEFAULT );
+				}
+			});
+	}
+	static {
+		try {
+  		if (Constants.isOSX) {
+  			String arch = System.getProperty("os.arch", "");
+  			DISABLED = arch.equalsIgnoreCase("powerpc") || arch.equalsIgnoreCase("ppc");
+  		} else {
+  			DISABLED = Constants.isUnix;
+  		}
+  		DISABLED |= Utils.isAZ2UI();
+		} catch (Throwable t) {
+			// Benefit of the doubt?
+			DISABLED = false;
+		}
+	}
+	
+	public
+	DeviceManagerUI(
+		AzureusCore			core )
+	{
+		plugin_interface = PluginInitializer.getDefaultInterface();
+		
+		ui_manager = plugin_interface.getUIManager();
+
+		if (DISABLED) {
+			return;
+		}
+
+		ui_manager.addUIListener(
+				new UIManagerListener()
+				{
+					public void
+					UIAttached(
+						UIInstance		instance )
+					{
+						if ( instance instanceof UISWTInstance ){
+							
+							swt_ui	= (UISWTInstance)instance;
+							
+							AzureusCoreFactory.addCoreRunningListener(
+								new AzureusCoreRunningListener() 
+								{
+									public void 
+									azureusCoreRunning(
+										AzureusCore core )
+									{
+										uiAttachedAndCoreRunning(core);
+
+									}
+								});
+
+						}
+					}
+					
+					public void
+					UIDetached(
+						UIInstance		instance )
+					{
+					}
+				});
+	}
+
+	private void uiAttachedAndCoreRunning(AzureusCore core) {
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
+				
+				if (mdi != null) {
+					
+					setupUI(mdi);
+				} else {
+					
+					SkinViewManager.addListener(new SkinViewManagerListener() {
+						public void skinViewAdded(SkinView skinview) {
+							
+							if (skinview instanceof SideBar) {
+								
+								setupUI((SideBar) skinview);
+								SkinViewManager.RemoveListener(this);
+							}
+						}
+					});
+				}
+			}
+		});
+		
+		UIExitUtilsSWT.addListener(
+			new UIExitUtilsSWT.canCloseListener()
+			{
+				public boolean 
+				canClose() 
+				{
+					try{
+						if ( device_manager == null ){
+							
+								// not yet init, safe to close
+							
+							return( true );
+						}
+						
+						final TranscodeJob job = device_manager.getTranscodeManager().getQueue().getCurrentJob();
+
+						if ( job == null || job.getState() != TranscodeJob.ST_RUNNING ){
+
+							return( true );
+						}
+
+						if ( job.getTranscodeFile().getDevice().isHidden()){
+							
+							// The assumption here is that if the device is hidden either the user shouldn't be concerned
+							// about the loss of active transcode as either it is something that they don't know about or
+							// alternative canClose listeners have been registered to handle the situation (e.g. burn-in-progress)
+
+							return( true );
+						}
+						
+						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 ( Throwable e ){
+						
+						Debug.out(e);
+						
+						return true;
+					}
+				}
+			});
+	}
+
+
+	protected DeviceManager
+	getDeviceManager()
+	{
+		return( device_manager );
+	}
+	
+	protected PluginInterface
+	getPluginInterface()
+	{
+		return( plugin_interface );
+	}
+	
+	protected void
+	setupUI(
+		MultipleDocumentInterfaceSWT			mdi )	
+	{
+		synchronized( this ){
+			
+			if ( ui_setup ){
+				
+				return;
+			}
+			
+			ui_setup = true;
+		}
+		
+		this.mdi		= mdi;
+
+		device_manager 	= DeviceManagerFactory.getSingleton();
+		
+		setupMenuListeners();
+
+		mdi.registerEntry(SideBar.SIDEBAR_SECTION_DEVICES,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						if ( sidebar_built ){
+							removeAllDevices();
+							
+							buildSideBar( true );
+						} else {
+							buildSideBar(false);
+						}
+							
+						addAllDevices();
+						return mdiEntryOverview;
+					}
+				});
+
+		
+		device_manager.addListener(new DeviceManagerListener() {
+		
+			public void deviceRemoved(Device device) {
+			}
+		
+			public void deviceManagerLoaded() {
+				device_manager.removeListener(this);
+				setupUIwithDeviceManager();
+			}
+		
+			public void deviceChanged(Device device) {
+			}
+		
+			public void deviceAttentionRequest(Device device) {
+			}
+		
+			public void deviceAdded(Device device) {
+			}
+		});
+	}
+
+	
+	private void
+	setupUIwithDeviceManager()
+	{
+		boolean	add_all = false;
+		
+		synchronized( this ){
+			
+			device_manager_listener = 
+				new DeviceManagerListener()
+				{
+					public void 
+					deviceAdded(
+						Device device ) 
+					{
+						addOrChangeDevice( device );
+					}
+					
+					public void
+					deviceChanged(
+						Device		device )
+					{
+						addOrChangeDevice( device );
+					}
+					
+					public void
+					deviceAttentionRequest(
+						Device		device )
+					{
+						showDevice( device );
+					}
+					
+					public void
+					deviceRemoved(
+						Device		device )
+					{
+						removeDevice( device );
+					}
+					
+					public void 
+					deviceManagerLoaded() {
+					}
+				};
+				
+			if ( needsAddAllDevices ){
+				
+				add_all = true;
+				
+				needsAddAllDevices = false;
+			}
+		}
+		
+		TranscodeManager transMan = device_manager.getTranscodeManager();
+
+		TranscodeQueue transQ = transMan.getQueue();
+
+		transQ.addListener(
+				new TranscodeQueueListener()
+				{
+					int	last_job_count = 0;
+
+					public void
+					jobAdded(
+							TranscodeJob		job )
+					{
+						check();
+					}
+
+					public void
+					jobChanged(
+							TranscodeJob		job )
+					{
+						check();
+					}
+
+					public void
+					jobRemoved(
+							TranscodeJob		job )
+					{
+						check();
+					}
+
+					protected void
+					check()
+					{
+						try{
+							int job_count = device_manager.getTranscodeManager().getQueue().getJobCount();
+	
+							if ( job_count != last_job_count ){
+	
+								if ( job_count == 0 || last_job_count == 0 ){
+	
+									MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+	
+									if ( mdi != null ){
+	
+										MdiEntry main_entry = mdi.getEntry( SideBar.SIDEBAR_SECTION_DEVICES );
+	
+										if ( main_entry != null ){
+	
+											ViewTitleInfoManager.refreshTitleInfo( main_entry.getViewTitleInfo());
+										}
+									}
+								}
+	
+								last_job_count = job_count;
+							}
+						}finally{
+							
+							checkOXCState();
+						}
+					}
+				});
+		
+		setupListeners();
+		
+		//buildSideBar( false );
+		
+		setupConfigUI(); // MDIEntry not required
+
+		if ( add_all ){
+			
+			addAllDevices();
+		}
+		
+		setupTranscodeMenus(); // MDIEntry not required
+	}
+	
+	public void setupConfigUI() {
+		BasicPluginConfigModel configModel = ui_manager.createBasicPluginConfigModel(
+				ConfigSection.SECTION_ROOT, CONFIG_SECTION_ID);
+
+			// auto search
+		
+		final BooleanParameter as = 
+			configModel.addBooleanParameter2( 
+				"device.search.auto", "device.search.auto",
+				device_manager.getAutoSearch());
+		
+		as.addListener(
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					Parameter param) 
+				{
+					device_manager.setAutoSearch( as.getValue());
+					
+					if ( device_manager.getAutoSearch()){
+						
+						search();
+					}
+				}
+			});
+		
+		final BooleanParameter qosParam = configModel.addBooleanParameter2(
+				PlatformDevicesMessenger.CFG_SEND_QOS, "devices.turnon.qos", false);
+		
+			// send qos
+		
+		qosParam.setValue(COConfigurationManager.getBooleanParameter( PlatformDevicesMessenger.CFG_SEND_QOS, false));
+		
+		qosParam.addListener(
+			new ParameterListener() {
+				public void parameterChanged(Parameter param) {
+					COConfigurationManager.setParameter(
+							PlatformDevicesMessenger.CFG_SEND_QOS, qosParam.getValue());
+				}
+			});
+
+			// config - simple view
+		
+		final BooleanParameter config_simple_view = 
+			configModel.addBooleanParameter2( 
+				CONFIG_VIEW_TYPE, "devices.sidebar.simple",
+				side_bar_view_type == SBV_SIMPLE );
+		
+		config_simple_view.addListener(
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					Parameter param) 
+				{
+					COConfigurationManager.setParameter( CONFIG_VIEW_TYPE, config_simple_view.getValue()?SBV_SIMPLE:SBV_FULL );
+				}
+			});	
+		
+		COConfigurationManager.addParameterListener(
+			CONFIG_VIEW_TYPE,
+			new org.gudy.azureus2.core3.config.ParameterListener()
+			{
+				public void 
+				parameterChanged(String 
+					parameterName ) 
+				{
+					config_simple_view.setValue( COConfigurationManager.getIntParameter( CONFIG_VIEW_TYPE, SBV_SIMPLE ) == SBV_SIMPLE );
+				}
+			});
+			
+			// generic devices
+		
+		configModel.addBooleanParameter2( 
+				"!" + CONFIG_VIEW_HIDE_REND_GENERIC + "!", "devices.sidebar.hide.rend.generic",
+				side_bar_hide_rend_gen );
+		
+		configModel.addBooleanParameter2( 
+				"!" + CONFIG_VIEW_SHOW_ONLY_TAGGED + "!", "devices.sidebar.show.only.tagged",
+				side_bar_show_tagged );
+
+			// auto-hide old devices
+		
+		final IntParameter auto_hide_old = 
+			configModel.addIntParameter2(
+				"device.config.autohide.old.devices", "device.config.autohide.old.devices",
+				device_manager.getAutoHideOldDevicesDays(), 0, 2048 );
+		
+		auto_hide_old.addListener(
+				new ParameterListener()
+				{
+					public void 
+					parameterChanged(
+						Parameter param) 
+					{
+						device_manager.setAutoHideOldDevicesDays( auto_hide_old.getValue());
+					}
+				});
+		
+		// transcoding
+		
+			// default dir
+		
+		String def = device_manager.getDefaultWorkingDirectory().getAbsolutePath();
+		
+		final DirectoryParameter def_work_dir = configModel.addDirectoryParameter2( "device.config.xcode.workdir", "device.config.xcode.workdir", def );
+		
+		def_work_dir.setValue( def );
+		
+		def_work_dir.addListener(
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					Parameter param ) 
+				{
+					device_manager.setDefaultWorkingDirectory(new File( def_work_dir.getValue()));
+				}
+			});
+		
+			// 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 );
+				}
+			});
+
+			// disable sleep
+		
+		final BooleanParameter disable_sleep = 
+			configModel.addBooleanParameter2( 
+				"device.config.xcode.disable_sleep", "device.config.xcode.disable_sleep",
+				device_manager.getDisableSleep());
+				
+		
+		disable_sleep.addListener(
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					Parameter param) 
+				{
+					device_manager.setDisableSleep( disable_sleep.getValue());
+				}
+			});
+		
+			// itunes
+		
+		final ActionParameter btnITunes = configModel.addActionParameter2("devices.button.installitunes", "UpdateWindow.columns.install");
+		btnITunes.setEnabled(false);
+		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+			public void azureusCoreRunning(AzureusCore core) {
+				boolean hasItunes = core.getPluginManager().getPluginInterfaceByID(
+						"azitunes") != null;
+				btnITunes.setEnabled(!hasItunes);
+			}
+		});
+
+		btnITunes.addListener(new ParameterListener() {
+			public void parameterChanged(Parameter param) {
+				CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
+					public void azureusCoreRunning(AzureusCore core) {
+						try {
+							PluginInstaller installer = core.getPluginManager().getPluginInstaller();
+							
+							StandardPlugin itunes_plugin = installer.getStandardPlugin("azitunes");
+							
+							if ( itunes_plugin == null ){
+							
+								Debug.out( "iTunes standard plugin not found");
+								
+							}else{
+							
+								itunes_plugin.install(false);
+							}
+						} catch (Throwable e) {
+							
+							Debug.printStackTrace(e);
+						}
+					}
+				});
+			}
+		});
+		
+		configModel.createGroup(
+			"device.xcode.group",
+			new Parameter[]
+			{
+					def_work_dir, max_xcode, disable_sleep, btnITunes
+			});
+		
+		// media servers
+			
+			// max lines
+		
+		final IntParameter max_ms_lines = 
+			configModel.addIntParameter2( 
+				"device.config.ms.maxlines", "device.config.ms.maxlines",
+				MAX_MS_DISPLAY_LINE_DEFAULT, 
+				0, Integer.MAX_VALUE );
+		
+		configModel.createGroup(
+				"device.ms.group",
+				new Parameter[]
+				{
+					max_ms_lines
+				});
+		
+			// 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());
+					
+					rebuildSideBarIfExists();
+				}
+			});
+		
+				// 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,
+			});
+		
+		
+			// play now
+		
+		final StreamManager sm = StreamManager.getSingleton();
+		
+		final IntParameter pn_buffer = 
+			configModel.addIntParameter2( 
+				"device.playnow.buffer", "device.playnow.buffer",
+				sm.getBufferSecs());
+		
+		pn_buffer.addListener(
+				new ParameterListener()
+				{
+					public void 
+					parameterChanged(
+						Parameter param) 
+					{
+						sm.setBufferSecs( pn_buffer.getValue());
+					}
+				});
+		
+		final IntParameter pn_min_buffer = 
+			configModel.addIntParameter2( 
+				"device.playnow.min_buffer", "device.playnow.min_buffer",
+				sm.getMinBufferSecs());
+		
+		pn_min_buffer.addListener(
+				new ParameterListener()
+				{
+					public void 
+					parameterChanged(
+						Parameter param) 
+					{
+						sm.setMinBufferSecs( pn_buffer.getValue());
+					}
+				});
+		
+		configModel.createGroup(
+				"device.playnow.group",
+				new Parameter[]
+				{
+						pn_buffer, pn_min_buffer,
+				});
+			
+		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());
+					
+					rebuildSideBarIfExists();
+				}
+			});
+		
+	}
+	
+	protected void
+	setupMenuListeners()
+	{
+		properties_listener = 
+			new MenuItemListener() 
+			{
+				public void 
+				selected(
+					MenuItem menu, 
+					Object target) 
+				{
+					if (target instanceof MdiEntry) {
+						MdiEntry info = (MdiEntry) target;
+						Device device = (Device)info.getDatasource();
+					
+						showProperties( device );
+					}
+				}
+			};
+		
+		hide_listener = 
+			new MenuItemListener() 
+			{
+				public void 
+				selected(
+					MenuItem menu, 
+					Object target) 
+				{
+					if (target instanceof MdiEntry){
+						
+						MdiEntry info = (MdiEntry) target;
+						
+						Device device = (Device)info.getDatasource();
+					
+						device.setHidden( true );
+					}
+				}
+			};
+		
+		will_tag_listener = 
+				new MenuItemFillListener() 
+				{
+					public void 
+					menuWillBeShown(
+						MenuItem 	menu, 
+						Object 		targets) 
+					{
+						Object[]	rows;
+						
+						if ( targets instanceof Object[] ){
+							
+							rows = (Object[])targets;
+							
+						}else{
+							
+							rows = new Object[]{ targets };
+						}
+						
+						if ( rows.length > 0 && rows[0] instanceof MdiEntry ){
+													
+							MdiEntry info = (MdiEntry)rows[0];
+						
+							Device device = (Device)info.getDatasource();
+							
+							menu.setData( device.isTagged());
+							
+						}else{
+							
+							menu.setEnabled( false );
+						}
+					}
+				};
+				
+		tag_listener = 
+			new MenuItemListener() 
+			{
+				public void 
+				selected(
+					MenuItem menu, 
+					Object target) 
+				{
+					if (target instanceof MdiEntry){
+						
+						MdiEntry info = (MdiEntry) target;
+						
+						Device device = (Device)info.getDatasource();
+					
+						device.setTagged( !device.isTagged());
+					}
+				}
+			};
+				
+		rename_listener = 
+				new MenuItemListener() 
+				{
+					public void 
+					selected(
+						MenuItem menu, 
+						Object target) 
+					{
+						if (target instanceof MdiEntry){
+							
+							MdiEntry info = (MdiEntry) target;
+							
+							final Device device = (Device)info.getDatasource();
+							
+							UISWTInputReceiver entry = (UISWTInputReceiver)swt_ui.getInputReceiver();
+							
+							entry.setPreenteredText(device.getName(), false );
+							
+							entry.maintainWhitespace(false);
+							
+							entry.allowEmptyInput( false );
+							
+							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, false );
+									}
+								}
+							});		
+						}
+					}
+				};
+
+		export_listener = 
+			new MenuItemListener() 
+			{
+				public void 
+				selected(
+					MenuItem menu, 
+					Object target) 
+				{
+					if ( target instanceof MdiEntry){
+						
+						MdiEntry info = (MdiEntry) target;
+						
+						Device device = (Device)info.getDatasource();
+						
+						export( device );
+					}
+				}
+			};
+			
+		will_remove_listener = 
+				new MenuItemFillListener() 
+				{
+					public void 
+					menuWillBeShown(
+						MenuItem 	menu, 
+						Object 		targets) 
+					{
+						Object[]	rows;
+						
+						if ( targets instanceof Object[] ){
+							
+							rows = (Object[])targets;
+							
+						}else{
+							
+							rows = new Object[]{ targets };
+						}
+						
+						if ( rows.length > 0 && rows[0] instanceof MdiEntry ){
+													
+							MdiEntry info = (MdiEntry)rows[0];
+						
+							Device device = (Device)info.getDatasource();
+							
+							menu.setEnabled( device.canRemove());
+							
+						}else{
+							
+							menu.setEnabled( false );
+						}
+					}
+				};
+				
+		remove_listener = 
+			new MenuItemListener() 
+			{
+				public void 
+				selected(
+					MenuItem menu, 
+					Object target) 
+				{
+					if (target instanceof MdiEntry){
+						
+						MdiEntry info = (MdiEntry) target;
+						
+						Device device = (Device)info.getDatasource();
+					
+						device.remove();
+					}
+				}
+			};
+			
+		will_browse_listener = 
+				new MenuItemFillListener() 
+				{
+					public void 
+					menuWillBeShown(
+						MenuItem 	menu, 
+						Object 		targets) 
+					{
+						menu.removeAllChildItems();
+				
+						boolean	enabled = false;
+						
+						Object[]	rows;
+						
+						if ( targets instanceof Object[] ){
+							
+							rows = (Object[])targets;
+							
+						}else{
+							
+							rows = new Object[]{ targets };
+						}
+						
+						if ( rows.length > 0 && rows[0] instanceof MdiEntry ){
+													
+							MdiEntry info = (MdiEntry)rows[0];
+						
+							Device device = (Device)info.getDatasource();
+					
+							Device.browseLocation[] locs = device.getBrowseLocations();
+							
+							enabled = locs != null && locs.length > 0;
+							
+							if ( enabled ){
+								
+								MenuManager menuManager = ui_manager.getMenuManager();
+	
+								for ( final Device.browseLocation loc: locs ){
+								
+									MenuItem loc_menu = menuManager.addMenuItem( menu, loc.getName());
+									
+									loc_menu.addListener(
+										new MenuItemListener()
+										{
+											public void 
+											selected(
+												MenuItem 	menu,
+												Object 		target ) 
+											{
+												Utils.launch( loc.getURL().toExternalForm());
+											}
+										});
+								}
+							}
+						}
+						
+						menu.setEnabled( enabled );
+					}
+				};
+			
+		show_listener = 
+			new MenuItemListener() 
+			{
+				public void 
+				selected(
+					MenuItem menu, 
+					Object target) 
+				{
+					if ( target instanceof MdiEntry ){
+						
+						MdiEntry info = (MdiEntry)target;
+												
+						Object ds = info.getDatasource();
+						
+						if ( ds instanceof Device ){
+							
+								// shouldn't get here really as its hidden :)
+							
+							Device device = (Device)ds;
+					
+							device.setHidden( true );
+							
+						}else{
+							
+							int	category_type = ds==null?Device.DT_UNKNOWN:(Integer)ds;
+							
+							Device[] devices = device_manager.getDevices();
+							
+							for ( Device device: devices ){
+								
+								if ( 	category_type == Device.DT_UNKNOWN ||
+										device.getType() == category_type && device.isHidden()){
+									
+									device.setHidden( false );
+								}
+							}
+						}
+					}
+				}
+			};
+			
+		show_fill_listener = 
+				new MenuItemFillListener() 
+				{
+					public void 
+					menuWillBeShown(
+						MenuItem 	menu, 
+						Object 		targets) 
+					{
+						boolean	enabled = false;
+						
+						Object[]	rows;
+						
+						if ( targets instanceof Object[] ){
+							
+							rows = (Object[])targets;
+							
+						}else{
+							
+							rows = new Object[]{ targets };
+						}
+						
+						for ( Object row: rows ){
+							
+							if ( row instanceof MdiEntry ){
+								
+								MdiEntry info = (MdiEntry)row;
+														
+								Object ds = info.getDatasource();
+								
+								if ( ds instanceof Device ){
+																	
+								}else{
+									
+									int	category_type = ds==null?Device.DT_UNKNOWN:(Integer)ds;
+										
+									Device[] devices = device_manager.getDevices();
+									
+									for ( Device device: devices ){
+										
+										if ( 	category_type == Device.DT_UNKNOWN ||
+												device.getType() == category_type && device.isHidden()){
+											
+											if ( device.isHidden()){
+												
+												enabled = true;
+											}
+										}
+									}
+								}
+							}
+						}
+						
+						menu.setEnabled( enabled );
+					}
+			
+				};
+	}
+	
+	private void 
+	export(
+		final Device	device ) 
+	{
+		Utils.execSWTThread(
+			new AERunnable() 
+			{
+				public void 
+				runSupport()
+				{
+					FileDialog dialog = 
+						new FileDialog( Utils.findAnyShell(), SWT.SYSTEM_MODAL | SWT.SAVE );
+					
+					dialog.setFilterPath( TorrentOpener.getFilterPathData() );
+											
+					dialog.setText(MessageText.getString("device.export.select.template.file"));
+					
+					dialog.setFilterExtensions(new String[] {
+							"*.vuze",
+							"*.vuz",
+							Constants.FILE_WILDCARD
+						});
+					dialog.setFilterNames(new String[] {
+							"*.vuze",
+							"*.vuz",
+							Constants.FILE_WILDCARD
+						});
+					
+					String path = TorrentOpener.setFilterPathData( dialog.open());
+
+					if ( path != null ){
+						
+						String lc = path.toLowerCase();
+						
+						if ( !lc.endsWith( ".vuze" ) && !lc.endsWith( ".vuz" )){
+							
+							path += ".vuze";
+						}
+						
+						try{
+							VuzeFile vf = device.getVuzeFile();
+							
+							vf.write( new File( path ));
+							
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}
+				}
+			});
+	}
+	
+	protected void
+	setupListeners()
+	{
+		COConfigurationManager.addAndFireParameterListeners( 
+			new String[]{
+				CONFIG_VIEW_TYPE,
+				CONFIG_VIEW_HIDE_REND_GENERIC,
+				CONFIG_VIEW_SHOW_ONLY_TAGGED,
+			},
+			new org.gudy.azureus2.core3.config.ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					String parameterName )
+				{
+					side_bar_view_type = COConfigurationManager.getIntParameter( CONFIG_VIEW_TYPE, SBV_SIMPLE );
+					
+					side_bar_hide_rend_gen = COConfigurationManager.getBooleanParameter( CONFIG_VIEW_HIDE_REND_GENERIC, true );
+					
+					side_bar_show_tagged = COConfigurationManager.getBooleanParameter( CONFIG_VIEW_SHOW_ONLY_TAGGED, false );
+
+					rebuildSideBarIfExists();
+				}
+			});
+	}
+	
+	protected static void
+	hideIcon(
+		MdiEntryVitalityImage	x )
+	{
+		if ( x == null ){
+			return;
+		}
+		
+		x.setVisible( false );
+		x.setToolTip( "" );
+	}
+	
+	protected static void
+	showIcon(
+		MdiEntryVitalityImage	x ,
+		String					t )
+	{
+		if ( x == null ){
+			return;
+		}
+		
+		x.setToolTip( t );
+		x.setVisible( true );
+	}
+	
+	protected void
+	rebuildSideBarIfExists()
+	{
+		MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+		
+		if ( mdi != null ){
+		
+			MdiEntry entry = mdi.getEntry( SideBar.SIDEBAR_HEADER_DEVICES );
+		
+			if (entry != null) {
+			
+				rebuildSideBar();
+			}
+		}
+	}
+
+	protected void
+	rebuildSideBar()
+	{
+			
+		if ( sidebar_built ){
+			removeAllDevices();
+			
+			buildSideBar( true );
+		} else {
+			buildSideBar(false);
+		}
+			
+		addAllDevices();
+	}
+	
+	private String
+	getHeaderToolTip()
+	{
+		if ( side_bar_hide_rend_gen || side_bar_show_tagged ){
+			
+			Device[] devices = device_manager.getDevices();
+			
+			int generic 	= 0;
+			int	untagged	= 0;
+			
+			for ( Device device: devices ){
+				
+				if ( device.isHidden()){
+					
+					continue;
+				}
+				
+				if ( device.getType() != Device.DT_MEDIA_RENDERER ){
+					
+					continue;
+				}
+				
+				DeviceMediaRenderer rend = (DeviceMediaRenderer)device;
+				
+				if ( rend.isNonSimple()){
+					
+					generic++;
+				}
+				
+				if ( !rend.isTagged()){
+					
+					untagged++;
+				}
+			}
+			
+			if ( !side_bar_show_tagged ){
+				
+				untagged = 0;
+			}
+			
+			if ( generic > 0 || untagged > 0 ){
+			
+				return( MessageText.getString( "devices.sidebar.mainheader.tooltip", new String[]{ String.valueOf( generic + untagged )} ));
+			}
+		}
+		
+		return( null );
+	}
+	
+	protected MdiEntry buildSideBar(boolean rebuild) {
+		MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+
+		if (mdi == null) {
+			return null;
+		}
+
+		if (entryHeader == null) {
+			entryHeader = mdi.getEntry(MultipleDocumentInterface.SIDEBAR_HEADER_DEVICES);
+			if (entryHeader != null) {
+				setupHeader(mdi, entryHeader);
+			}
+		}
+
+		mdiEntryOverview = mdi.getEntry(SideBar.SIDEBAR_SECTION_DEVICES);
+
+		if (mdiEntryOverview == null) {
+			mdiEntryOverview = mdi.createEntryFromSkinRef(
+					SideBar.SIDEBAR_HEADER_DEVICES, SideBar.SIDEBAR_SECTION_DEVICES,
+					"devicesview", MessageText.getString("mdi.entry.about.devices"), 
+					new ViewTitleInfo()
+					{
+						public Object 
+						getTitleInfoProperty(
+							int propertyID )
+						{
+							if ( propertyID == TITLE_INDICATOR_TEXT_TOOLTIP ){
+							
+								return( getHeaderToolTip());
+							}
+							
+							return( null );
+						}
+					},
+					null, false, "");
+			
+			mdiEntryOverview.setImageLeftID("image.sidebar.aboutdevices");
+		}
+
+		if (rebuild) {
+			for (categoryView category : categories) {
+				category.destroy();
+			}
+		}
+
+		categories.clear();
+
+		if (side_bar_view_type == SBV_FULL) {
+			buildCategories();
+		}
+
+		sidebar_built = true;
+
+		return mdiEntryOverview;
+	}	
+	
+	private void buildCategories() {
+		MenuManager menu_manager = ui_manager.getMenuManager();
+		// renderers
+
+		categoryView renderers_category = addDeviceCategory(
+				Device.DT_MEDIA_RENDERER, "device.renderer.view.title",
+				"image.sidebar.device.renderer");
+
+		categories.add(renderers_category);
+
+		MenuItem re_menu_item = menu_manager.addMenuItem("sidebar."
+				+ renderers_category.getKey(), "device.show");
+
+		re_menu_item.addListener(show_listener);
+		re_menu_item.addFillListener(show_fill_listener);
+
+		re_menu_item = menu_manager.addMenuItem( "sidebar." + renderers_category.getKey(), "sep_re");
+
+		re_menu_item.setStyle( MenuItem.STYLE_SEPARATOR );
+		
+		re_menu_item = menu_manager.addMenuItem(
+				"sidebar." + renderers_category.getKey(),
+				"device.renderer.remove_all");
+
+		re_menu_item.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				
+				new AEThread2( "doit" )
+				{
+					public void
+					run()
+					{
+						UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+										
+						long res = ui_manager.showMessageBox(
+								"device.mediaserver.remove_all.title",
+								"device.renderer.remove_all.desc",
+								UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+						
+						if ( res == UIManagerEvent.MT_YES ){
+							
+							Device[] devices = device_manager.getDevices();
+							
+							for ( Device d: devices ){
+								
+								if ( d.getType() == Device.DT_MEDIA_RENDERER ){
+									
+									if ( d.canRemove()){
+										
+										d.remove();
+									}
+								}
+							}
+						}
+					}
+				}.start();
+			}
+		});
+		// media servers
+
+		categoryView media_servers_category = addDeviceCategory(
+				Device.DT_CONTENT_DIRECTORY, "device.mediaserver.view.title",
+				"image.sidebar.device.mediaserver");
+
+		categories.add(media_servers_category);
+
+		MenuItem ms_menu_item = menu_manager.addMenuItem("sidebar."
+				+ media_servers_category.getKey(), "device.show");
+
+		ms_menu_item.addListener(show_listener);
+		ms_menu_item.addFillListener(show_fill_listener);
+
+		ms_menu_item = menu_manager.addMenuItem(
+				"sidebar." + media_servers_category.getKey(),
+				"device.mediaserver.configure");
+
+		ms_menu_item.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				UIFunctions uif = UIFunctionsManager.getUIFunctions();
+
+				if (uif != null) {
+					uif.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+							"upnpmediaserver.name");
+				}
+			}
+		});
+		
+		ms_menu_item = menu_manager.addMenuItem( "sidebar." + media_servers_category.getKey(), "sep_ms");
+
+		ms_menu_item.setStyle( MenuItem.STYLE_SEPARATOR );
+		
+		ms_menu_item = menu_manager.addMenuItem(
+				"sidebar." + media_servers_category.getKey(),
+				"device.mediaserver.remove_all");
+
+		ms_menu_item.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				
+				new AEThread2( "doit" )
+				{
+					public void
+					run()
+					{
+						UIManager ui_manager = StaticUtilities.getUIManager( 120*1000 );
+										
+						long res = ui_manager.showMessageBox(
+								"device.mediaserver.remove_all.title",
+								"device.mediaserver.remove_all.desc",
+								UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+						
+						if ( res == UIManagerEvent.MT_YES ){
+							
+							Device[] devices = device_manager.getDevices();
+							
+							for ( Device d: devices ){
+								
+								if ( d.getType() == Device.DT_CONTENT_DIRECTORY ){
+									
+									if ( d.canRemove()){
+										
+										d.remove();
+									}
+								}
+							}
+						}
+					}
+				}.start();
+			}
+		});
+
+		// routers
+
+		categoryView routers_category = addDeviceCategory(
+				Device.DT_INTERNET_GATEWAY, "device.router.view.title",
+				"image.sidebar.device.router");
+
+		categories.add(routers_category);
+
+		MenuItem rt_menu_item = menu_manager.addMenuItem("sidebar."
+				+ routers_category.getKey(), "device.show");
+
+		rt_menu_item.addListener(show_listener);
+		rt_menu_item.addFillListener(show_fill_listener);
+
+		rt_menu_item = menu_manager.addMenuItem(
+				"sidebar." + routers_category.getKey(), "device.router.configure");
+
+		rt_menu_item.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				UIFunctions uif = UIFunctionsManager.getUIFunctions();
+
+				if (uif != null) {
+
+					uif.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+							"UPnP");
+				}
+			}
+		});
+
+		// 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");
+
+		categories.add(internet_category);
+	}
+
+	private void setupHeader(MultipleDocumentInterface mdi,
+			final MdiEntry entryHeader) {
+		addDefaultDropListener(entryHeader);
+
+		/* and away you go!
+		SideBarVitalityImage addDevice = entryHeader.addVitalityImage("image.sidebar.subs.add");
+		
+		addDevice.setToolTip("Add Device");
+		
+		addDevice.addListener(
+			new SideBarVitalityImageListener() 
+			{
+				public void 
+				sbVitalityImage_clicked(
+					int x, int y) 
+				{
+					addNewDevice();
+					//new DevicesWizard( DeviceManagerUI.this );
+				}
+			});
+		*/
+
+		// Rollup spinner/warning/info
+		entryHeader.setViewTitleInfo(new ViewTitleInfo() {
+			private int last_indicator = 0;
+
+			MdiEntryVitalityImage spinner = entryHeader.addVitalityImage(SPINNER_IMAGE_ID);
+
+			MdiEntryVitalityImage warning = entryHeader.addVitalityImage(ALERT_IMAGE_ID);
+
+			MdiEntryVitalityImage info = entryHeader.addVitalityImage(INFO_IMAGE_ID);
+
+			{
+				hideIcon(spinner);
+				hideIcon(warning);
+				hideIcon(info);
+			}
+
+			public Object getTitleInfoProperty(int propertyID) {
+				boolean expanded = entryHeader.isExpanded();
+
+				if (propertyID == TITLE_INDICATOR_TEXT) {
+
+					spinner.setVisible(!expanded && device_manager.isBusy( Device.DT_UNKNOWN ));
+
+					if (!expanded) {
+
+						Device[] devices = device_manager.getDevices();
+
+						last_indicator = 0;
+
+						String all_errors = "";
+						String all_infos = "";
+
+						for (Device device : devices) {
+
+							String error = device.getError();
+
+							if (error != null) {
+
+								all_errors += (all_errors.length() == 0 ? "" : "; ") + error;
+							}
+
+							String info = device.getInfo();
+
+							if (info != null) {
+
+								all_infos += (all_infos.length() == 0 ? "" : "; ") + info;
+							}
+
+							if (device instanceof DeviceMediaRenderer) {
+
+								if (SHOW_RENDERER_VITALITY) {
+
+									DeviceMediaRenderer renderer = (DeviceMediaRenderer) device;
+
+									last_indicator += renderer.getCopyToDevicePending()
+											+ renderer.getCopyToFolderPending();
+								}
+							} else if (device instanceof DeviceOfflineDownloader) {
+
+								if (SHOW_OD_VITALITY) {
+
+									DeviceOfflineDownloader dod = (DeviceOfflineDownloader) device;
+
+									last_indicator += dod.getTransferingCount();
+								}
+							}
+						}
+
+						if (all_errors.length() > 0) {
+
+							hideIcon(info);
+
+							showIcon(warning, all_errors);
+
+						} else {
+
+							hideIcon(warning);
+
+							if (all_infos.length() > 0) {
+
+								showIcon(info, all_infos);
+
+							} else {
+
+								hideIcon(info);
+							}
+						}
+
+						if (last_indicator > 0) {
+
+							return (String.valueOf(last_indicator));
+						}
+					} else {
+
+						hideIcon(warning);
+						hideIcon(info);
+
+					}
+				} else if (propertyID == TITLE_INDICATOR_COLOR) {
+
+					/*
+					if ( last_indicator > 0 ){
+						
+						if ( SHOW_VITALITY ){
+							
+							return( to_copy_indicator_colors );
+						}
+					}
+					*/
+				} else if (propertyID == TITLE_INDICATOR_TEXT_TOOLTIP ) {
+					
+					return( getHeaderToolTip());
+				}
+
+				return null;
+			}
+		});
+
+		///////// Turn On
+		device_manager.addListener(new DeviceManagerListener() {
+
+			public void deviceRemoved(Device device) {
+			}
+
+			public void deviceManagerLoaded() {
+				device_manager.removeListener(this);
+				if (entryHeader == null || entryHeader.isDisposed()) {
+					return;
+				}
+	  		PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager();
+	  		PluginInterface pi;
+	  		pi = pm.getPluginInterfaceByID("vuzexcode");
+				if (device_manager.getTranscodeManager().getProviders().length == 0 || pi == null) {
+					// provider plugin not installed yet
+
+					final MdiEntryVitalityImage turnon = entryHeader.addVitalityImage("image.sidebar.turnon");
+					if (turnon != null) {
+						turnon.addListener(new MdiEntryVitalityImageListener() {
+							public void mdiEntryVitalityImage_clicked(int x, int y) {
+								DevicesFTUX.ensureInstalled(null);
+							}
+						});
+
+						device_manager.getTranscodeManager().addListener(
+								new TranscodeManagerListener() {
+									public void providerAdded(TranscodeProvider provider) {
+										// only triggers when vuzexcode is avail
+										turnon.setVisible(false);
+									}
+
+									public void providerUpdated(TranscodeProvider provider) {
+									}
+
+									public void providerRemoved(TranscodeProvider provider) {
+									}
+								});
+					}
+				} else {
+					// provider plugin installed, but we had a bug in older versions,
+					// so fixup
+					DevicesFTUX.alreadyInstalledFixup();
+				}
+			}
+
+			public void deviceChanged(Device device) {
+			}
+
+			public void deviceAttentionRequest(Device device) {
+			}
+
+			public void deviceAdded(Device device) {
+			}
+		});
+
+		//////// Beta
+
+		MdiEntryVitalityImage beta = entryHeader.addVitalityImage("image.sidebar.beta");
+		if (beta != null) {
+			beta.setAlignment(SWT.LEFT);
+		}
+
+		///////// Menu
+
+		MenuManager menu_manager = ui_manager.getMenuManager();
+
+		createOverallMenu(menu_manager, "sidebar." + SideBar.SIDEBAR_HEADER_DEVICES);
+		createOverallMenu(menu_manager, "sidebar." + SideBar.SIDEBAR_SECTION_DEVICES);
+	}
+
+	private void createOverallMenu(final MenuManager menu_manager, String parentID) {
+		MenuItem de_menu_item = menu_manager.addMenuItem(parentID, "device.search");
+
+		de_menu_item.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				search();
+			}
+		});
+
+			// show generic
+
+		de_menu_item = menu_manager.addMenuItem(parentID, "device.showGeneric");
+		de_menu_item.setStyle(MenuItem.STYLE_CHECK);
+		de_menu_item.addFillListener(new MenuItemFillListener() {
+			public void menuWillBeShown(MenuItem menu, Object data) {
+				
+				boolean is_hidden = COConfigurationManager.getBooleanParameter(CONFIG_VIEW_HIDE_REND_GENERIC, true);
+				
+				menu.setData( !is_hidden );
+				
+				boolean	enabled = false;
+				
+				if ( is_hidden ){
+					
+					Device[] devices = device_manager.getDevices();
+										
+					for ( Device d: devices ){
+		
+						if ( d.isHidden()){
+							
+							continue;
+						}
+						
+						if ( d instanceof  DeviceMediaRenderer ){
+							
+							DeviceMediaRenderer rend = (DeviceMediaRenderer)d;
+						
+							if ( rend.isNonSimple()){
+								
+								enabled = true;
+							}
+						}
+					}
+				}else{
+					
+					enabled = true;
+				}
+				
+				menu.setEnabled( enabled );
+			}
+		});
+		de_menu_item.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				COConfigurationManager.setParameter(CONFIG_VIEW_HIDE_REND_GENERIC,
+						!COConfigurationManager.getBooleanParameter(
+								CONFIG_VIEW_HIDE_REND_GENERIC, true));
+			}
+		});
+
+			// show tagged
+
+		de_menu_item = menu_manager.addMenuItem(parentID, "device.onlyShowTagged");
+		de_menu_item.setStyle(MenuItem.STYLE_CHECK);
+		de_menu_item.addFillListener(new MenuItemFillListener() {
+			public void menuWillBeShown(MenuItem menu, Object data) {
+				menu.setData(COConfigurationManager.getBooleanParameter(
+						CONFIG_VIEW_SHOW_ONLY_TAGGED, false));
+				
+				Device[] devices = device_manager.getDevices();
+				
+				boolean has_tagged = false;
+				
+				for ( Device d: devices ){
+					
+					if ( d.isTagged()){
+						
+						has_tagged = true;
+						
+						break;
+					}
+				}
+				
+				menu.setEnabled( has_tagged );
+			}
+		});
+		
+		de_menu_item.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				COConfigurationManager.setParameter(CONFIG_VIEW_SHOW_ONLY_TAGGED,
+						!COConfigurationManager.getBooleanParameter(
+								CONFIG_VIEW_SHOW_ONLY_TAGGED, false));
+			}
+		});
+		
+			// show hidden
+		
+		de_menu_item = menu_manager.addMenuItem(parentID, "device.show");
+
+		de_menu_item.addListener(show_listener);
+		de_menu_item.addFillListener(show_fill_listener);
+
+			// simple
+
+		de_menu_item = menu_manager.addMenuItem(parentID, "devices.sidebar.simple");
+
+		de_menu_item.setStyle(MenuItem.STYLE_CHECK);
+
+		de_menu_item.addFillListener(new MenuItemFillListener() {
+			public void menuWillBeShown(MenuItem menu, Object data) {
+				menu.setData(COConfigurationManager.getIntParameter(CONFIG_VIEW_TYPE,
+						SBV_SIMPLE) == SBV_SIMPLE);
+			}
+		});
+
+		de_menu_item.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				COConfigurationManager.setParameter(CONFIG_VIEW_TYPE,
+						((Boolean) menu.getData()) ? SBV_SIMPLE : SBV_FULL);
+			}
+		});
+
+		de_menu_item = menu_manager.addMenuItem(parentID, "sep");
+
+		de_menu_item.setStyle(MenuItem.STYLE_SEPARATOR);
+
+			// on complete do
+		
+		final MenuItem de_oxc_menu = menu_manager.addMenuItem(parentID, "devices.sidebar.onxcodecomplete");
+
+		de_oxc_menu.setStyle(MenuItem.STYLE_MENU );
+
+		de_oxc_menu.addFillListener(
+			new MenuItemFillListener()
+			{
+				public void 
+				menuWillBeShown(
+					MenuItem menu, Object data) 
+				{
+					menu.removeAllChildItems();
+					
+					final List<MenuItem> oxc_items = new ArrayList<MenuItem>();
+					
+					final MenuItem oxc_nothing = menu_manager.addMenuItem( de_oxc_menu, "devices.sidebar.oxc.nothing" );
+					oxc_items.add( oxc_nothing );
+					oxc_nothing.setStyle( MenuItem.STYLE_CHECK );
+					oxc_nothing.setData( oxc_action == OXC_NOTHING );
+					
+					final MenuItem oxc_close_vuze = menu_manager.addMenuItem( de_oxc_menu, "devices.sidebar.oxc.closevuze" );
+					oxc_items.add( oxc_close_vuze );
+					oxc_close_vuze.setStyle( MenuItem.STYLE_CHECK );
+					oxc_close_vuze.setData( oxc_action == OXC_QUIT_VUZE  );
+					
+					PlatformManager pm = PlatformManagerFactory.getPlatformManager();
+					
+					int	sdt = pm.getShutdownTypes();
+					
+					final Map<MenuItem,String>	oxc_pm_map = new HashMap<MenuItem,String>();
+					
+					for ( int type: PlatformManager.SD_ALL ){
+						
+						if ( ( sdt | type ) != 0 ){
+							
+							String	action = OXC_NOTHING;
+							
+							if ( type == PlatformManager.SD_SLEEP ){
+								action = OXC_SLEEP;
+							}else if ( type == PlatformManager.SD_HIBERNATE ){
+								action = OXC_HIBERNATE;
+							}else if ( type == PlatformManager.SD_SHUTDOWN ){
+								action = OXC_SHUTDOWN;
+							}else{
+								Debug.out( "Unknown type: " + type );
+							}
+							
+							MenuItem oxc_pm = menu_manager.addMenuItem( de_oxc_menu, "devices.sidebar.oxc.pm." + type );
+							oxc_items.add( oxc_pm );
+							oxc_pm.setStyle( MenuItem.STYLE_CHECK );
+							oxc_pm.setData( oxc_action == action );
+							
+							oxc_pm_map.put( oxc_pm, action );
+						}
+					}
+					
+					MenuItemListener oxc_mil = 
+						new MenuItemListener()
+						{
+							public void 
+							selected(
+								MenuItem menu, 
+								Object target) 
+							{
+								if ((Boolean)menu.getData()){
+									
+									if ( menu == oxc_nothing ){
+										
+										setOXCState( OXC_NOTHING );
+										
+									}else if ( menu == oxc_close_vuze ){
+										
+										setOXCState( OXC_QUIT_VUZE );
+										
+									}else{
+										
+										setOXCState( oxc_pm_map.get(menu ));
+									}
+								}
+							}
+						};
+						
+					for ( MenuItem mi: oxc_items ){
+						
+						mi.addListener( oxc_mil );
+					}
+				};
+			});
+		
+		de_menu_item = menu_manager.addMenuItem(parentID, "sep2");
+
+		de_menu_item.setStyle(MenuItem.STYLE_SEPARATOR);
+
+		// options 
+
+		de_menu_item = menu_manager.addMenuItem(parentID, "MainWindow.menu.view.configuration");
+
+		de_menu_item.addListener(new MenuItemListener() {
+			public void selected(MenuItem menu, Object target) {
+				UIFunctions uif = UIFunctionsManager.getUIFunctions();
+
+				if (uif != null) {
+
+					uif.getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+							CONFIG_SECTION_ID);
+				}
+			}
+		});
+
+		if (Constants.isCVSVersion()) {
+			de_menu_item = menu_manager.addMenuItem(parentID, "!(CVS Only)Show FTUX!");
+
+			de_menu_item.addListener(new MenuItemListener() {
+				public void selected(MenuItem menu, Object target) {
+					DevicesFTUX.showForDebug();
+				}
+			});
+
+		}
+	}
+
+	/**
+	 * 
+	 *
+	 * @since 4.1.0.5
+	 */
+	protected void addNewDevice() {
+		ManufacturerChooser mfChooser = new ManufacturerChooser();
+		mfChooser.open(new ClosedListener() {
+			public void MfChooserClosed(DeviceManufacturer mf) {
+				if (mf == null) {
+					return;
+				}
+				DeviceTemplateChooser deviceTemplateChooser = new DeviceTemplateChooser(mf);
+				
+				deviceTemplateChooser.open(new DeviceTemplateClosedListener() {
+					public void deviceTemplateChooserClosed(DeviceTemplate deviceTemplate) {
+						if (deviceTemplate == null) {
+							return;
+						}
+
+						Device device;
+						try {
+							device = deviceTemplate.createInstance(deviceTemplate.getName() + " test!" );
+							device.requestAttention();
+						} catch (DeviceManagerException e) {
+							Debug.out(e);
+						}
+
+						/*  Don't really need to choose a profile now..
+						TranscodeProfile[] profiles = null;// deviceTemplate.getTranscodeProfiles();
+						new TranscodeChooser(profiles) {
+							public void closed() {
+								Utils.openMessageBox(null, 0, "CHOSE", "You chose "
+										+ (selectedProfile == null ? "NULL"
+												: selectedProfile.getName()));
+								
+							}
+						};
+						*/
+					}
+				});
+			}
+		});
+	}
+
+	private void
+	setOXCState(
+		String		new_action )
+	{
+		oxc_action = new_action;
+			
+		checkOXCState();			
+	}
+	
+	private void
+	checkOXCState()
+	{
+		if ( oxc_action == OXC_NOTHING ){
+			
+			oxc_trigger_set	= false;
+			
+			return;
+		}
+		
+		int	jobs = device_manager.getTranscodeManager().getQueue().getJobCount();
+		
+		if ( jobs > 0 ){
+			
+			oxc_trigger_set	= true;
+
+		}else{
+			
+			if ( oxc_trigger_set ){
+					
+				oxc_trigger_set = false;
+				
+				AzureusCoreFactory.getSingleton().executeCloseAction( oxc_action, MessageText.getString( "core.shutdown.xcode" ));
+			}
+		}
+	}
+	
+	private void 
+	setupTranscodeMenus()
+	{					
+			// top level menus
+				
+		final String[] tables = {
+				TableManager.TABLE_MYTORRENTS_INCOMPLETE,
+				TableManager.TABLE_MYTORRENTS_INCOMPLETE_BIG,
+				TableManager.TABLE_MYTORRENTS_COMPLETE,
+				TableManager.TABLE_MYTORRENTS_COMPLETE_BIG,
+				TableManager.TABLE_TORRENT_FILES,
+				TableManager.TABLE_MYTORRENTS_UNOPENED,
+				TableManager.TABLE_MYTORRENTS_UNOPENED_BIG,
+				TableManager.TABLE_MYTORRENTS_ALL_BIG,
+			};
+		
+		TableManager table_manager = plugin_interface.getUIManager().getTableManager();
+		
+		MenuItemFillListener	menu_fill_listener = 
+			new MenuItemFillListener()
+			{
+				public void
+				menuWillBeShown(
+					MenuItem	menu,
+					Object		_target )
+				{
+					final TableRow[]	target;
+					
+					if ( _target instanceof TableRow ){
+						
+						target = new TableRow[]{ (TableRow)_target };
+						
+					}else{
+						
+						target = (TableRow[])_target;
+					}
+					
+					boolean	enabled = target.length > 0;
+					
+					for ( TableRow row: target ){
+						
+						Object obj = row.getDataSource();
+					
+						if ( obj instanceof Download ){
+						
+							Download download = (Download)obj;
+
+							if ( download.getState() == Download.ST_ERROR ){
+								
+								enabled = false;
+							}
+						}else{
+							
+							DiskManagerFileInfo file = (DiskManagerFileInfo)obj;
+							
+							try{
+								if ( file.getDownload().getState() == Download.ST_ERROR ){
+								
+									enabled = false;
+								}
+							}catch( Throwable e ){
+								
+								enabled = false;
+							}
+						}
+					}
+					
+					menu.setEnabled( enabled );
+					
+					menu.removeAllChildItems();
+					
+					if ( enabled ){
+						
+						Device[] devices = device_manager.getDevices();
+						
+						int	devices_added = 0;
+						
+						for ( Device device: devices ){
+							
+							if ( device.isHidden()){
+								
+								continue;
+							}
+							
+							if ( device instanceof TranscodeTarget ){
+								
+								devices_added++;
+								
+								final TranscodeTarget renderer = (TranscodeTarget)device;
+								
+								TranscodeProfile[] profiles = renderer.getTranscodeProfiles();
+								
+
+								TableContextMenuItem device_item =
+									plugin_interface.getUIManager().getTableManager().addContextMenuItem(
+										(TableContextMenuItem)menu,
+										"!" + device.getName() + (profiles.length==0?" (No Profiles)":"") + "!");
+								
+								device_item.setStyle( MenuItem.STYLE_MENU );
+								
+								if ( profiles.length == 0 ){
+									
+									device_item.setEnabled( false );
+									
+								}else{
+
+									Arrays.sort(profiles, new Comparator<TranscodeProfile>() {
+										public int compare(TranscodeProfile o1, TranscodeProfile o2) {
+											int i1 = o1.getIconIndex();
+											int i2 = o2.getIconIndex();
+											
+											if ( i1 == i2 ){
+											
+												return o1.getName().compareToIgnoreCase(o2.getName());
+											}else{
+												
+												return( i1 - i2 );
+											}
+										}
+									});
+
+									
+									for ( final TranscodeProfile profile: profiles ){
+										
+										TableContextMenuItem profile_item =
+											plugin_interface.getUIManager().getTableManager().addContextMenuItem(
+												device_item,
+												"!" + profile.getName() + "!");
+
+										profile_item.addMultiListener(
+											new MenuItemListener()
+											{
+												public void 
+												selected(
+													MenuItem 	menu,
+													Object 		x ) 
+												{													
+													for ( TableRow row: target ){
+														
+														Object obj = row.getDataSource();
+													
+														try{
+															if ( obj instanceof Download ){
+															
+																Download download = (Download)obj;
+	
+																addDownload( renderer, profile, -1, download );
+																	
+															}else{
+																
+																DiskManagerFileInfo file = (DiskManagerFileInfo)obj;
+																
+																addFile( renderer, profile, -1, file );
+															}
+														}catch( Throwable e ){
+															
+															Debug.out( e );
+														}
+													}
+												}
+											});
+									}
+								}
+							}
+						}
+						
+						if ( devices_added == 0 ){
+						
+							TableContextMenuItem device_item =
+								plugin_interface.getUIManager().getTableManager().addContextMenuItem(
+									(TableContextMenuItem)menu,
+									"!(No Devices)!");
+							
+							device_item.setEnabled( false );
+
+						}
+					}
+				}
+			};
+		
+		// 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.xcode" );
+			
+			menu.setStyle(TableContextMenuItem.STYLE_MENU);
+		
+			menu.addFillListener( menu_fill_listener );				
+		}
+	}
+	
+	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()
+	{
+      	device_manager.search(
+      			10*1000,
+      			new DeviceSearchListener()
+      			{
+      				public void 
+      				deviceFound(
+      					Device device ) 
+      				{
+      				}
+      				
+      				public void 
+      				complete() 
+      				{
+      				}
+      			});
+	}
+	
+	protected void
+	addOrChangeDevice(
+		final Device		device )
+	{
+		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 ){
+			
+			for ( categoryView view: categories ){
+				
+				if ( view.getDeviceType() == type ){
+					
+					parent_key = view.getKey();
+					
+					break;
+				}
+			}
+		}else{
+			
+			if ( type != Device.DT_MEDIA_RENDERER && type != Device.DT_OFFLINE_DOWNLOADER ){
+				
+				return;
+			}
+			
+			parent_key = SideBar.SIDEBAR_HEADER_DEVICES;
+		}
+		
+		if ( parent_key == null ){
+			
+			Debug.out( "Unknown device type: " + device.getString());
+			
+			return;
+		}
+			
+		boolean	hide_device = device.isHidden();
+		
+		if ( type == Device.DT_MEDIA_RENDERER && side_bar_hide_rend_gen ){
+			
+			DeviceMediaRenderer rend = (DeviceMediaRenderer)device;
+			
+			if ( rend.isNonSimple()){
+				
+				hide_device = true;
+			}
+		}
+		
+		if ( side_bar_show_tagged && !device.isTagged()){
+				
+			hide_device = true;
+		}
+		
+		if ( hide_device ){
+			
+			removeDevice( device );
+			
+			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();
+
+					device.setTransientProperty( DEVICE_IVIEW_KEY, new_di );
+
+					setupEntry(new_di, device, parent);
+				}
+			}else{
+				
+				ViewTitleInfoManager.refreshTitleInfo( existing_di.getView());
+				
+				setStatus( device, existing_di );
+			}
+		}
+	}
+	
+	private void setupEntry(deviceItem new_di, final Device device, String parent) {
+		synchronized( DeviceManagerUI.this ){
+			
+			if ( new_di.isDestroyed()){
+				
+				return;
+			}
+			
+			deviceView view = new deviceView( parent, device );
+			
+			new_di.setView( view );
+			
+			String key = parent + "/" + device.getID() + ":" + nextSidebarID();
+
+			final MdiEntry	entry;
+			
+			int	device_type = device.getType();
+			
+			if ( device_type == Device.DT_MEDIA_RENDERER ){
+
+				entry = 
+						mdi.createEntryFromSkinRef(
+								parent,
+								key, "devicerendererview",
+								device.getName(),
+								view, null, false, null);
+				
+			}else if ( device_type == Device.DT_OFFLINE_DOWNLOADER ){
+				
+				entry = 
+						mdi.createEntryFromSkinRef(
+								parent,
+								key, "devicesodview",
+								device.getName(),
+								view, null, false, null);
+				entry.setExpanded(true);
+
+				
+				DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device;
+				
+				String	id;
+				
+				String manufacturer = dod.getManufacturer();
+				
+				if ( manufacturer.toLowerCase().contains( "vuze" )){
+					
+					id = "vuze";
+
+				}else if ( manufacturer.toLowerCase().contains( "belkin" )){
+					
+					id = "bel";
+					
+				}else{
+					
+					id = "other";
+				}
+				
+				entry.setImageLeftID( "image.sidebar.device.od." + id + ".small" );
+
+			}else{
+				
+				entry = mdi.createEntryFromEventListener(parent, view, key, false,
+						device, null);
+				entry.setExpanded(true);
+
+			}
+			
+			entry.setDatasource( device );
+			
+			entry.setLogID(parent + "-" + device.getName());
+
+			new_di.setMdiEntry( entry );
+
+			setStatus( device, new_di );
+			
+			if ( device instanceof TranscodeTarget ){
+				
+				entry.addListener(
+						new MdiEntryDropListener()
+						{
+							public boolean 
+							mdiEntryDrop(
+									MdiEntry 		entry, 
+									Object 				payload  )
+							{
+								return handleDrop((TranscodeTarget)device, payload );
+							}
+						});
+			}
+			
+			final MenuManager menu_manager = ui_manager.getMenuManager();
+
+			boolean	need_sep = false;
+			
+			if ( device instanceof TranscodeTarget ){
+				
+				need_sep = true;
+				
+				MenuItem explore_menu_item = menu_manager.addMenuItem("sidebar." + key, "v3.menu.device.exploreTranscodes");
+				
+				explore_menu_item.addListener(new MenuItemListener() {
+					public void selected(MenuItem menu, Object target) {
+		 				ManagerUtils.open( ((TranscodeTarget) device).getWorkingDirectory());
+					}
+				});
+			}
+			
+			if ( device instanceof DeviceMediaRenderer ){
+				
+				need_sep = true;
+				// filter view
+				
+				final DeviceMediaRenderer renderer = (DeviceMediaRenderer) device;
+				
+				if ( renderer.canFilterFilesView()){
+					MenuItem filterfiles_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.only.show");
+					filterfiles_menu_item.setStyle(MenuItem.STYLE_CHECK);
+					
+					filterfiles_menu_item.addFillListener(new MenuItemFillListener() {
+						public void menuWillBeShown(MenuItem menu, Object data) {
+							menu.setData(new Boolean(renderer.getFilterFilesView()));
+						}
+					});
+					filterfiles_menu_item.addListener(new MenuItemListener() {
+						public void selected(MenuItem menu, Object target) {
+			 				renderer.setFilterFilesView( (Boolean) menu.getData());
+						}
+					});
+				}
+				
+				// show cats
+				
+				if ( renderer.canShowCategories()){
+					MenuItem showcat_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.show.cat");
+					showcat_menu_item.setStyle(MenuItem.STYLE_CHECK);
+					
+					showcat_menu_item.addFillListener(new MenuItemFillListener() {
+						public void menuWillBeShown(MenuItem menu, Object data) {
+							menu.setData(new Boolean(renderer.getShowCategories()));
+						}
+					});
+					showcat_menu_item.addListener(new MenuItemListener() {
+						public void selected(MenuItem menu, Object target) {
+			 				renderer.setShowCategories( (Boolean) menu.getData());
+						}
+					});
+				}
+
+				// cache files
+				
+				MenuItem alwayscache_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.always.cache");
+				alwayscache_menu_item.setStyle(MenuItem.STYLE_CHECK);
+				
+				alwayscache_menu_item.addFillListener(new MenuItemFillListener() {
+					public void menuWillBeShown(MenuItem menu, Object data) {
+						menu.setData(new Boolean(renderer.getAlwaysCacheFiles()));
+					}
+				});
+				alwayscache_menu_item.addListener(new MenuItemListener() {
+					public void selected(MenuItem menu, Object target) {
+		 				renderer.setAlwaysCacheFiles( (Boolean) menu.getData());
+					}
+				});
+				
+			}
+			
+			if ( need_sep ){
+				
+				menu_manager.addMenuItem("sidebar." + key, "1" ).setStyle( MenuItem.STYLE_SEPARATOR );
+			}
+			
+			need_sep = false;
+			
+			if ( device instanceof DeviceMediaRenderer ){
+				
+				final DeviceMediaRenderer renderer = (DeviceMediaRenderer) device;
+
+				if ( renderer.canCopyToFolder()){
+					
+					need_sep = true;
+					
+					MenuItem autocopy_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.autoCopy");
+					autocopy_menu_item.setStyle(MenuItem.STYLE_CHECK);
+					
+					autocopy_menu_item.addFillListener(new MenuItemFillListener() {
+						public void menuWillBeShown(MenuItem menu, Object data) {
+							menu.setData(new Boolean(renderer.getAutoCopyToFolder()));
+						}
+					});
+					autocopy_menu_item.addListener(new MenuItemListener() {
+						public void selected(MenuItem menu, Object target) {
+			 				renderer.setAutoCopyToFolder((Boolean) menu.getData());
+						}
+					});
+					
+					final MenuItem mancopy_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.mancopy");
+					mancopy_menu_item.setStyle(MenuItem.STYLE_PUSH);
+					
+					mancopy_menu_item.addListener(new MenuItemListener() {
+						public void 
+						selected(
+								MenuItem menu, Object target) 
+						{
+							try{
+								renderer.manualCopy();
+								
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}
+					});
+					
+					mancopy_menu_item.addFillListener(
+							new MenuItemFillListener()
+							{
+								public void 
+								menuWillBeShown(
+										MenuItem menu, Object data )
+								{
+									boolean	enabled = false;
+									
+									if ( !renderer.getAutoCopyToFolder()){
+										
+										File target = renderer.getCopyToFolder();
+										
+										if ( target != null && target.exists()){
+											
+											enabled = renderer.getCopyToFolderPending() > 0;
+										}
+									}
+									mancopy_menu_item.setEnabled( enabled );
+								}
+							});
+					
+					MenuItem setcopyto_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.setcopyto");
+					setcopyto_menu_item.setStyle(MenuItem.STYLE_PUSH);
+					
+					
+					setcopyto_menu_item.addListener(new MenuItemListener() {
+						public void 
+						selected(
+								MenuItem menu, Object target) 
+						{
+							Shell shell = Utils.findAnyShell();
+							
+							DirectoryDialog dd = new DirectoryDialog( shell );
+							
+							File existing = renderer.getCopyToFolder();
+							
+							if ( existing != null ){
+								
+								dd.setFilterPath( existing.getAbsolutePath());
+							}
+							
+							dd.setText( MessageText.getString( "devices.xcode.setcopyto.title" ));
+							
+							String	path = dd.open();
+							
+							if ( path != null ){
+								
+								renderer.setCopyToFolder( new File( path ));
+							}
+						}
+					});
+
+
+				}
+				
+				if ( renderer.canCopyToDevice()){
+					
+					need_sep = true;
+					
+					MenuItem autocopy_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.autoCopy.device");
+					autocopy_menu_item.setStyle(MenuItem.STYLE_CHECK);
+					
+					autocopy_menu_item.addFillListener(new MenuItemFillListener() {
+						public void menuWillBeShown(MenuItem menu, Object data) {
+							menu.setData(new Boolean(renderer.getAutoCopyToDevice()));
+						}
+					});
+					autocopy_menu_item.addListener(new MenuItemListener() {
+						public void selected(MenuItem menu, Object target) {
+			 				renderer.setAutoCopyToDevice((Boolean) menu.getData());
+						}
+					});
+					
+					final MenuItem mancopy_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.mancopy");
+					mancopy_menu_item.setStyle(MenuItem.STYLE_PUSH);
+					
+					mancopy_menu_item.addListener(new MenuItemListener() {
+						public void 
+						selected(
+							MenuItem menu, Object target) 
+						{
+							try{
+								renderer.manualCopy();
+								
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}
+					});
+					
+					mancopy_menu_item.addFillListener(
+							new MenuItemFillListener()
+							{
+								public void 
+								menuWillBeShown(
+										MenuItem menu, Object data )
+								{
+									boolean	enabled = false;
+									
+									if ( !renderer.getAutoCopyToDevice()){
+										
+										enabled = renderer.getCopyToDevicePending() > 0;
+									}
+									
+									mancopy_menu_item.setEnabled( enabled );
+								}
+							});
+				}
+				
+				if ( renderer.canAutoStartDevice()){
+					
+					need_sep = true;
+					
+					MenuItem autostart_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.autoStart");
+					autostart_menu_item.setStyle(MenuItem.STYLE_CHECK);
+					
+					autostart_menu_item.addFillListener(new MenuItemFillListener() {
+						public void menuWillBeShown(MenuItem menu, Object data) {
+							menu.setData(new Boolean(renderer.getAutoStartDevice()));
+						}
+					});
+					autostart_menu_item.addListener(new MenuItemListener() {
+						public void selected(MenuItem menu, Object target) {
+			 				renderer.setAutoStartDevice((Boolean) menu.getData());
+						}
+					});
+				}
+				
+				if ( renderer.canAssociate()){
+					
+					need_sep = true;
+					
+					final MenuItem menu_associate = menu_manager.addMenuItem(
+							"sidebar." + key, "devices.associate");
+					
+					menu_associate.setStyle(MenuItem.STYLE_MENU);
+
+					menu_associate.addFillListener(
+							new MenuItemFillListener()
+							{
+								public void 
+								menuWillBeShown(
+										MenuItem menu, Object data )
+								{
+									menu_associate.removeAllChildItems();
+									
+									if ( renderer.isAlive()){
+										
+										InetAddress a = renderer.getAddress();
+										
+										String address = a==null?"":a.getHostAddress();
+										
+										MenuItem menu_none = menu_manager.addMenuItem(
+												menu_associate,
+												"!" + MessageText.getString( "devices.associate.already" ) + ": " + address + "!" );
+
+										menu_none.setEnabled( false );
+										
+										menu_associate.setEnabled( true );
+										
+									}else{
+										
+										UnassociatedDevice[] unassoc = device_manager.getUnassociatedDevices();
+										
+										if ( unassoc.length == 0 ){
+
+											menu_associate.setEnabled( false );
+											
+										}else{
+											
+											menu_associate.setEnabled( true );
+											
+											for ( final UnassociatedDevice un: unassoc ){
+												
+												MenuItem menu_un = menu_manager.addMenuItem(
+														menu_associate,
+														"!" + un.getAddress().getHostAddress() + ": " + un.getDescription() + "!");
+													
+													menu_un.addListener(
+															new MenuItemListener() 
+															{
+																public void 
+																selected(
+																		MenuItem 	menu, 
+																		Object 		target)
+																{
+																	renderer.associate( un );
+																}
+															});
+											}
+										}
+									}
+								}
+							});
+
+				}
+				
+				if ( renderer.canRestrictAccess()){
+					
+					need_sep = true;
+					
+					final MenuItem menu_ra = menu_manager.addMenuItem(
+							"sidebar." + key, "devices.restrict_access");
+					
+					menu_ra.addListener(
+						new MenuItemListener() 
+						{
+							public void 
+							selected(
+								MenuItem menu, 
+								Object target) 
+							{
+								if (target instanceof MdiEntry){
+																		
+									UISWTInputReceiver entry = (UISWTInputReceiver)swt_ui.getInputReceiver();
+									
+									entry.setMessage( "devices.restrict_access.msg" );
+									
+									entry.setPreenteredText( renderer.getAccessRestriction(), false );
+									
+									entry.maintainWhitespace( false );
+									
+									entry.allowEmptyInput( true );
+									
+									entry.setLocalisedTitle(
+										MessageText.getString("devices.restrict_access.prompt",
+											new String[]{
+										device.getName()
+									}));
+			
+									entry.prompt(new UIInputReceiverListener(){
+										public void UIInputReceiverClosed( UIInputReceiver entry ){
+											if (!entry.hasSubmittedInput()) {
+												return;
+											}
+											String input = entry.getSubmittedInput().trim();
+																							
+											renderer.setAccessRestriction( input );
+											
+										}
+									});		
+								}
+							}
+						});
+				}
+				
+				final TranscodeProfile[] transcodeProfiles = renderer.getTranscodeProfiles();
+				
+				if (transcodeProfiles.length > 0) {
+					Arrays.sort(transcodeProfiles, new Comparator<TranscodeProfile>() {
+						public int compare(TranscodeProfile o1, TranscodeProfile o2) {
+							int i1 = o1.getIconIndex();
+							int i2 = o2.getIconIndex();
+							
+							if ( i1 == i2 ){
+								
+								return o1.getName().compareToIgnoreCase(o2.getName());
+							}else{
+								
+								return( i1 - i2 );
+							}
+						}
+					});
+
+					need_sep = true;
+					
+					MenuItem menu_default_profile = menu_manager.addMenuItem(
+							"sidebar." + key, "v3.menu.device.defaultprofile");
+					menu_default_profile.setStyle(MenuItem.STYLE_MENU);
+					
+					MenuItem menu_profile_never = menu_manager.addMenuItem( menu_default_profile, "v3.menu.device.defaultprofile.never");
+					
+					menu_profile_never.setStyle(MenuItem.STYLE_CHECK );
+					menu_profile_never.setData(Boolean.TRUE);
+					menu_profile_never.addListener(new MenuItemListener() {
+						public void selected(MenuItem menu, Object target) {
+							renderer.setTranscodeRequirement(((Boolean)menu.getData())?TranscodeTarget.TRANSCODE_NEVER:TranscodeTarget.TRANSCODE_WHEN_REQUIRED );
+						}});
+
+
+					menu_profile_never.addFillListener(new MenuItemFillListener() {
+						public void menuWillBeShown(MenuItem menu, Object data) {
+							boolean never = renderer.getTranscodeRequirement() == TranscodeTarget.TRANSCODE_NEVER;
+							menu.setData( never );
+						}});
+					
+					MenuItem menu_profile_none = menu_manager.addMenuItem(
+							menu_default_profile, "option.askeverytime");
+					menu_profile_none.setStyle(MenuItem.STYLE_RADIO);
+					menu_profile_none.setData(Boolean.FALSE);
+					menu_profile_none.addListener(new MenuItemListener() {
+						public void selected(MenuItem menu, Object target) {
+							renderer.setDefaultTranscodeProfile(null);
+						}
+					});
+					
+					menu_profile_none.addFillListener(new MenuItemFillListener() {
+						public void menuWillBeShown(MenuItem menu, Object data) {
+							if ( transcodeProfiles.length <= 1 ){
+								menu.setData( Boolean.FALSE );
+								menu.setEnabled( false );
+							}else{
+								TranscodeProfile profile = null;
+								try {
+									profile = renderer.getDefaultTranscodeProfile();
+								} catch (TranscodeException e) {
+								}
+								menu.setData((profile == null) ? Boolean.TRUE
+										: Boolean.FALSE);
+								
+								menu.setEnabled( renderer.getTranscodeRequirement() != TranscodeTarget.TRANSCODE_NEVER  );
+							}
+						}
+					});
+					
+					for (final TranscodeProfile profile : transcodeProfiles) {
+						MenuItem menuItem = menu_manager.addMenuItem(
+								menu_default_profile, "!" + profile.getName() + "!");
+							menuItem.setStyle(MenuItem.STYLE_RADIO);
+							menuItem.setData(Boolean.FALSE);
+							menuItem.addListener(new MenuItemListener() {
+								public void selected(MenuItem menu, Object target) {
+									renderer.setDefaultTranscodeProfile(profile);
+								}
+							});
+							
+							menuItem.addFillListener(new MenuItemFillListener() {
+								public void menuWillBeShown(MenuItem menu, Object data) {
+									if ( transcodeProfiles.length <= 1 ){
+										menu.setData( Boolean.TRUE );
+										menu.setEnabled( false );
+									}else{
+										TranscodeProfile dprofile = null;
+										try {
+											dprofile = renderer.getDefaultTranscodeProfile();
+										} catch (TranscodeException e) {
+										}
+										menu.setData((profile.equals(dprofile))
+												? Boolean.TRUE : Boolean.FALSE);
+										
+										menu.setEnabled( renderer.getTranscodeRequirement() != TranscodeTarget.TRANSCODE_NEVER );
+									}
+								}
+							});
+					}
+				}
+				
+				// publish to RSS feed
+				
+				if ( true ){
+					
+					need_sep = true;
+					
+					final MenuItem rss_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.rsspub");
+					rss_menu_item.setStyle(MenuItem.STYLE_CHECK);
+
+					rss_menu_item.addFillListener(new MenuItemFillListener() {
+						public void menuWillBeShown(MenuItem menu, Object data) {
+							rss_menu_item.setEnabled( device_manager.isRSSPublishEnabled());
+							
+							menu.setData(new Boolean(device_manager.isRSSPublishEnabled() && renderer.isRSSPublishEnabled()));
+						}
+					});
+					rss_menu_item.addListener(new MenuItemListener() {
+						public void selected(MenuItem menu, Object target) {
+			 				renderer.setRSSPublishEnabled((Boolean) menu.getData());
+						}
+					});
+					
+					rss_menu_item.setEnabled( device_manager.isRSSPublishEnabled());
+				}
+				
+						// auto-share with tag
+				
+				
+				if ( true ){
+					
+					need_sep = true;
+					
+					final MenuItem aswt_menu_item = menu_manager.addMenuItem("sidebar." + key, "devices.xcode.tagshare");
+					aswt_menu_item.setStyle(MenuItem.STYLE_MENU);				
+					
+					aswt_menu_item.addFillListener(
+						new MenuItemFillListener()
+						{
+							public void 
+							menuWillBeShown(
+								MenuItem 	menu, 
+								Object 		data ) 
+							{		
+								addTagSubMenu( menu_manager, menu, renderer );
+							}
+						});
+				}
+			}
+
+			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;
+				
+				MenuItem browse_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.browse");
+				
+				browse_menu_item.setStyle( MenuItem.STYLE_MENU );
+				
+				browse_menu_item.addFillListener( will_browse_listener );
+			}
+			
+			
+			if ( need_sep ){
+				
+				menu_manager.addMenuItem("sidebar." + key, "s2" ).setStyle( MenuItem.STYLE_SEPARATOR );
+			}
+			
+				// rename
+			
+			MenuItem rename_menu_item = menu_manager.addMenuItem("sidebar." + key, "MyTorrentsView.menu.rename" );
+			
+			rename_menu_item.addListener( rename_listener );									
+			
+				// export
+			
+			if ( device.isExportable()){
+				
+				MenuItem export_item = menu_manager.addMenuItem("sidebar." + key,"Subscription.menu.export");
+				
+				export_item.addListener( export_listener );
+			}
+			
+				// hide
+			
+			MenuItem hide_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.hide");
+			
+			hide_menu_item.addListener( hide_listener );
+			
+				// tag
+			
+			MenuItem tag_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.tag");
+			
+			tag_menu_item.setStyle( MenuItem.STYLE_CHECK );
+			
+			tag_menu_item.addFillListener( will_tag_listener );
+
+			tag_menu_item.addListener(tag_listener );
+
+				// remove
+			
+			MenuItem remove_menu_item = menu_manager.addMenuItem("sidebar." + key, "MySharesView.menu.remove");
+			
+			remove_menu_item.addFillListener( will_remove_listener );
+				
+			remove_menu_item.addListener( remove_listener );
+
+				// sep
+			
+			menu_manager.addMenuItem("sidebar." + key, "s3" ).setStyle( MenuItem.STYLE_SEPARATOR );
+			
+			final URL wiki_url = device.getWikiURL();
+			
+			if ( wiki_url != null ){
+				
+				MenuItem wiki_menu_item = menu_manager.addMenuItem("sidebar." + key, "device.wiki");
+
+				wiki_menu_item.addListener(
+					new MenuItemListener()
+					{
+						public void 
+						selected(
+							MenuItem 	menu,
+							Object 		target ) 
+						{
+							Utils.launch( wiki_url.toExternalForm());
+						}
+					});
+			}
+			
+			// props
+			
+			MenuItem menu_item = menu_manager.addMenuItem("sidebar." + key,"Subscription.menu.properties");
+			
+			menu_item.addListener( properties_listener );
+		}
+	}
+
+	protected static String
+	getDeviceImageID(
+		Device		device )
+	{
+		String imageID = device.getImageID();
+		if (imageID != null) {
+			return imageID;
+		}
+		
+		if (!(device instanceof DeviceMediaRenderer)) {
+			return "" + DeviceMediaRenderer.RS_OTHER;
+		}
+
+		int	species = ((DeviceMediaRenderer)device).getRendererSpecies();
+		
+		String	id;
+		
+		if ( species != DeviceMediaRenderer.RS_OTHER ){
+		
+			id = String.valueOf( species );
+			
+		}else{
+			
+			String	classification = device.getClassification();
+			
+			if ( classification.equals( "sony.PSP")){
+				
+				id = "psp";
+				
+			}else if ( classification.startsWith( "tivo.")){
+				
+				id = "tivo";
+			
+			}else if ( classification.startsWith( "samsung.")){
+
+				id = "samsung";
+				
+			}else if ( classification.startsWith( "western.digital.")){
+
+				id = "wdtv";
+				
+			}else if ( classification.startsWith( "boxee.")){
+
+				id = "boxee";
+
+			}else if ( classification.startsWith( "sony.bravia")){
+
+				id = "bravia";
+				
+			}else if ( classification.startsWith( "ms_wmp.")){
+
+				// update skin3_constants.properties!
+			
+				id = "mswmp";
+				
+			}else if ( classification.toLowerCase().contains( "android")){
+
+				id = "android";
+
+			}else if ( classification.toLowerCase().contains( "neotv")){
+
+				id = "neotv";
+
+			}else if ( classification.startsWith( "vuze-ms-browser.")){
+
+				id = "vuze";
+				
+			}else{
+				
+				if (device.isGenericUSB()) {
+					id = "usb";
+
+				} else {
+
+					id = String.valueOf( species );
+				}
+			}
+		}
+		
+		return( id );
+	}
+	
+	private static void 
+	addTagSubMenu(
+		MenuManager						menu_manager,
+		MenuItem						menu,
+		final DeviceMediaRenderer		device )
+	{
+		menu.removeAllChildItems();
+
+		TagManager tm = TagManagerFactory.getTagManager();
+		
+		List<Tag> tags = tm.getTagType( TagType.TT_DOWNLOAD_MANUAL ).getTags();
+		
+		tags = TagUIUtils.sortTags( tags );
+					
+		long	tag_id = device.getAutoShareToTagID();
+			
+		Tag assigned_tag = tm.lookupTagByUID( tag_id );
+		
+		MenuItem m = menu_manager.addMenuItem( menu, "label.no.tag" );
+				
+		m.setStyle( MenuItem.STYLE_RADIO );
+							
+		m.setData( new Boolean( assigned_tag == null ));
+				
+		m.addListener(
+			new MenuItemListener() 
+			{
+				public void
+				selected(
+					MenuItem			menu,
+					Object 				target )
+				{
+					device.setAutoShareToTagID( -1 );
+				}
+			});
+				
+
+		m = menu_manager.addMenuItem( menu, "sep1" );
+				
+		m.setStyle( MenuItem.STYLE_SEPARATOR );
+	
+		
+		List<String>	menu_names 		= new ArrayList<String>();
+		Map<String,Tag>	menu_name_map 	= new IdentityHashMap<String, Tag>();
+
+		for ( Tag t: tags ){
+			
+			if ( !t.isTagAuto()){
+				
+				String name = t.getTagName( true );
+				
+				menu_names.add( name );
+				menu_name_map.put( name, t );
+			}
+		}
+			
+		List<Object>	menu_structure = MenuBuildUtils.splitLongMenuListIntoHierarchy( menu_names, TagUIUtils.MAX_TOP_LEVEL_TAGS_IN_MENU );
+		
+		for ( Object obj: menu_structure ){
+
+			List<Tag>	bucket_tags = new ArrayList<Tag>();
+			
+			MenuItem parent_menu;
+			
+			if ( obj instanceof String ){
+				
+				parent_menu = menu;
+				
+				bucket_tags.add( menu_name_map.get((String)obj));
+				
+			}else{
+				
+				Object[]	entry = (Object[])obj;
+				
+				List<String>	tag_names = (List<String>)entry[1];
+				
+				boolean	has_selected = false;
+				
+				for ( String name: tag_names ){
+					
+					Tag tag = menu_name_map.get( name );
+					
+					bucket_tags.add( tag );
+					
+					if ( assigned_tag == tag ){
+						
+						has_selected = true;
+					}
+				}
+				
+				parent_menu = menu_manager.addMenuItem (menu, "!" + (String)entry[0] + (has_selected?" (*)":"") + "!" );
+				
+				parent_menu.setStyle( MenuItem.STYLE_MENU );
+			}
+			
+			for ( final Tag tag: bucket_tags ){
+			
+				m = menu_manager.addMenuItem( parent_menu, tag.getTagName( false ));
+						
+				m.setStyle( MenuItem.STYLE_RADIO );
+											
+				m.setData( new Boolean( assigned_tag == tag ));
+						
+				m.addListener(
+					new MenuItemListener() 
+					{
+						public void
+						selected(
+							MenuItem			menu,
+							Object 				target )
+						{
+							device.setAutoShareToTagID( tag.getTagUID());
+						}
+					});
+			}
+		}
+		
+		m = menu_manager.addMenuItem( menu, "sep2" );
+			
+		m.setStyle( MenuItem.STYLE_SEPARATOR );
+
+		m = menu_manager.addMenuItem( menu, "label.add.tag" );
+		
+		m.addListener(
+			new MenuItemListener() 
+			{
+				public void
+				selected(
+					MenuItem			menu,
+					Object 				target )
+				{
+					TagUIUtils.createManualTag(new UIFunctions.TagReturner() {
+						public void returnedTags(Tag[] tags) {
+							if ( tags != null ){
+								for (Tag new_tag : tags) {
+									device.setAutoShareToTagID( new_tag.getTagUID());
+								}
+							}
+						}
+					});
+					
+				}
+			});
+	}
+
+	protected void
+	showDevice(
+		Device		device )
+	{
+		synchronized( this ){
+			
+			final deviceItem existing_di = (deviceItem)device.getTransientProperty( DEVICE_IVIEW_KEY );
+
+			if ( existing_di != null ){
+				
+				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+				
+				if ( mdi != null ){
+				
+					mdi.showEntry(existing_di.getMdiEntry());
+				}
+			}
+		}
+	}
+	
+	public static boolean
+	handleDrop(
+		final TranscodeTarget		target,
+		final Object				payload )
+	{
+		return( handleDropSupport( target, payload, true ));
+	}
+	
+	private static boolean
+	handleDropSupport(
+		final TranscodeTarget		target,
+		final Object				payload,
+		final boolean				allow_retry )
+	{
+		if (	!(payload instanceof String[]) && 
+				!(payload instanceof String) &&
+				!(payload instanceof URLTransfer.URLType )){
+					
+			return false;
+		}
+		TranscodeChooser deviceChooser = new TranscodeChooser(target) {
+			
+			public void 
+			closed() 
+			{
+				if ( selectedTranscodeTarget != null && selectedProfile != null ){
+					
+					handleDrop(
+						selectedTranscodeTarget, 
+						selectedProfile, 
+						payload,
+						getTranscodeRequirement());
+				}
+			}
+		};
+		
+		deviceChooser.show(
+			new Runnable()
+			{
+				public void
+				run()
+				{
+					if ( allow_retry ){
+					
+						handleDropSupport( target, payload, false );
+					}
+				}
+			});
+		return true;
+	}
+
+	protected static void
+	addDownload(
+		TranscodeTarget		target,
+		TranscodeProfile 	profile,
+		int					transcode_requirement,
+		byte[]				hash )
+	{
+		try{
+		
+			addDownload( target, profile, transcode_requirement, AzureusCoreFactory.getSingleton().getPluginManager().getDefaultPluginInterface().getShortCuts().getDownload(hash));
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+	}
+	
+	protected static void
+	addDownload(
+		TranscodeTarget		target,
+		TranscodeProfile 	profile,
+		int					transcode_requirement,
+		Download			download )
+	{
+			// we could use the primary file
+			// int index = DownloadManagerEnhancer.getSingleton().getEnhancedDownload(hash).getPrimaryFile().getIndex();
+			// DiskManagerFileInfo dm_file = plugin_interface.getShortCuts().getDownload(hash).getDiskManagerFileInfo()[index];
+	
+			// but lets just grab all files
+
+		DiskManagerFileInfo[] dm_files = download.getDiskManagerFileInfo();
+		
+		int	num_added = 0;
+		
+		for ( DiskManagerFileInfo dm_file: dm_files ){
+			
+				// limit number of files we can add to avoid crazyness
+			
+			if ( num_added > MAX_FILES_FOR_MULTI_XCODE ){
+				
+				break;
+			}
+			
+				// could be smarter here and check extension or whatever
+			
+			if ( dm_files.length == 1 || dm_file.getLength() >= MIN_FILE_SIZE_FOR_XCODE ){
+				
+				addFile( target, profile, transcode_requirement, dm_file );
+				
+				num_added++;
+			}
+		}
+	}
+	
+	protected static void
+	addFile(
+		TranscodeTarget			target,
+		TranscodeProfile 		profile,
+		int						transcode_requirement,
+		DiskManagerFileInfo		file )
+	{
+		try{
+			DeviceManagerFactory.getSingleton().getTranscodeManager().getQueue().add(
+				target,
+				profile,
+				file,
+				transcode_requirement,
+				false );
+			
+		}catch( Throwable e ){
+			
+			Debug.out( e );
+		}
+	}
+	
+	protected static void
+	addDirectory(
+		TranscodeTarget			target,
+		TranscodeProfile 		profile,
+		int						transcode_requirement,
+		File					file )
+	{
+		if ( !file.isDirectory()){
+			
+			return;
+		}
+		
+		File[]	files = file.listFiles();
+		
+		int	num_added = 0;
+		
+		for ( File f: files ){
+		
+			if ( num_added > MAX_FILES_FOR_MULTI_XCODE ){
+				
+				break;
+			}
+			
+			if ( f.isDirectory()){
+				
+				continue;
+			}
+			
+			if ( f.length() > MIN_FILE_SIZE_FOR_XCODE ){
+				
+				addFile( target, profile, transcode_requirement, f );
+				
+				num_added++;
+			}
+		}
+	}
+	
+	protected static void
+	addFile(
+		TranscodeTarget			target,
+		TranscodeProfile 		profile,
+		int						transcode_requirement,
+		File					file )
+	{
+		if ( file.exists() && file.isFile()){
+
+			try{
+				DeviceManagerFactory.getSingleton().getTranscodeManager().getQueue().add(
+					target,
+					profile,
+					new DiskManagerFileInfoFile( file ),
+					transcode_requirement,
+					false );
+				
+			}catch( Throwable e ){
+				
+				Debug.out( e );
+			}
+		}else{
+			
+			Debug.out( "Drop to " + target.getDevice().getName() + " for " + file + " failed, file doesn't exist" );
+		}
+	}
+	
+	protected static void
+	addURL(
+		TranscodeTarget			target,
+		TranscodeProfile 		profile,
+		int						transcode_requirement,
+		String					url )
+	{
+		try{
+			DeviceManagerFactory.getSingleton().getTranscodeManager().getQueue().add(
+				target,
+				profile,
+				new DiskManagerFileInfoURL( new URL( url )),
+				transcode_requirement,
+				false );
+				
+		}catch( Throwable e ){
+				
+			Debug.out( e );
+		}
+	}
+	
+	protected static void
+	handleDrop(
+		TranscodeTarget		target,
+		TranscodeProfile 	profile,
+		Object				payload,
+		int					transcode_requirement )
+	{
+		if ( payload instanceof String[]){
+			
+			String[]	files = (String[])payload;
+			
+			for ( String file: files ){
+			
+				File f = new File( file );
+
+				if ( f.isFile()){
+				
+					addFile( target, profile, transcode_requirement, f );
+					
+				}else{
+					
+					addDirectory( target, profile, transcode_requirement, f );
+				}
+			}
+		}else if ( payload instanceof String ){
+			
+			String stuff = (String)payload;
+			
+			if ( stuff.startsWith( "DownloadManager\n" ) ||stuff.startsWith( "DiskManagerFileInfo\n" )){
+				
+				String[]	bits =  Constants.PAT_SPLIT_SLASH_N.split(stuff);
+				
+				for (int i=1;i<bits.length;i++){
+					
+					String	hash_str = bits[i];
+					
+					int	pos = hash_str.indexOf(';');
+					
+					try{
+
+						if ( pos == -1 ){
+							
+							byte[]	 hash = Base32.decode( bits[i] );
+			
+							addDownload( target, profile, transcode_requirement, hash );
+										
+						}else{
+							
+							String[] files = hash_str.split(";");
+							
+							byte[]	 hash = Base32.decode( files[0].trim());
+							
+							DiskManagerFileInfo[] dm_files = AzureusCoreFactory.getSingleton().getPluginManager().getDefaultPluginInterface().getShortCuts().getDownload(hash).getDiskManagerFileInfo();
+							
+							for (int j=1;j<files.length;j++){
+								
+								DiskManagerFileInfo dm_file = dm_files[Integer.parseInt(files[j].trim())];
+								
+								addFile( target, profile, transcode_requirement, dm_file );
+							}
+						}
+					}catch( Throwable e ){
+						
+						Debug.out( "Failed to get download for hash " + bits[1] );
+					}
+				}
+			}else if ( stuff.startsWith( "TranscodeFile\n" )){
+				
+				String[]	bits =  Constants.PAT_SPLIT_SLASH_N.split(stuff);
+				
+				for (int i=1;i<bits.length;i++){
+					
+					File f = new File( bits[i] );
+
+					if ( f.isFile()){
+					
+						addFile( target, profile, transcode_requirement, f );
+					}
+				}
+			}else if ( stuff.startsWith( "http:" ) || stuff.startsWith( "https://" )){
+				
+				addURL( target, profile, transcode_requirement, stuff );
+			}
+		}else if ( payload instanceof URLTransfer.URLType ){
+			
+			String url = ((URLTransfer.URLType)payload).linkURL;
+			
+			if ( url != null ){
+				
+				addURL( target, profile, transcode_requirement, url );
+			}
+		}
+	}
+	
+	protected void
+	setStatus(
+		Device			device,
+		deviceItem		sbi )
+	{
+		sbi.setStatus( device );
+	}
+	
+	protected void
+	addAllDevices()
+	{
+		synchronized( this ){
+		
+			if ( device_manager_listener == null ){
+			
+				needsAddAllDevices = true;
+			
+				return;
+			}
+
+			if ( !device_manager_listener_added ){
+		
+				device_manager_listener_added	= true;
+				
+				device_manager.addListener( device_manager_listener );
+			}
+		}
+			
+			Device[] devices = device_manager.getDevices();
+			
+			Arrays.sort(
+				devices,
+				new Comparator<Device>()
+				{
+					public int 
+					compare(
+						Device o1, 
+						Device o2) 
+					{
+						return( o1.getName().compareToIgnoreCase( o2.getName()));
+					}
+				});
+			
+			for ( Device device: devices ){
+				
+				addOrChangeDevice( device );
+			}
+	}
+	
+	protected void
+	removeAllDevices()
+	{
+		synchronized( this ){
+		
+			if ( device_manager_listener_added ){
+			
+				device_manager_listener_added	= false;
+
+				device_manager.removeListener( device_manager_listener );
+			}
+		}
+
+		Device[] devices = device_manager.getDevices();
+		
+		for ( Device device: devices ){
+			
+			removeDevice( device );
+		}
+	}
+	
+	protected void
+	removeDevice(
+		final Device		device )
+	{
+		synchronized( this ){
+			
+			final deviceItem existing_di = (deviceItem)device.getTransientProperty( DEVICE_IVIEW_KEY );
+			
+			if ( existing_di != null ){
+				
+				device.setTransientProperty( DEVICE_IVIEW_KEY, null );
+				
+				existing_di.destroy();
+			}
+		}
+	}
+	
+	protected categoryView
+	addDeviceCategory(
+		int			device_type,
+		String		category_title,
+		String		category_image_id )
+	{
+		String key = "Device_" + category_title + ":" + nextSidebarID();
+		
+		categoryView eventListener;
+		
+		if ( device_type == Device.DT_INTERNET ){
+			
+			eventListener = new DeviceInternetView( this, category_title );
+					
+		}else{
+			
+			eventListener = new categoryViewGeneric( this, device_type, category_title );
+		}
+		
+		MdiEntry entry = mdi.createEntryFromEventListener(
+				SideBar.SIDEBAR_HEADER_DEVICES, eventListener, key, false, new Integer(
+						device_type), null);
+
+		addDefaultDropListener( entry );
+		
+		entry.setImageLeftID( category_image_id );
+				
+		eventListener.setDetails( entry, key );
+		
+		return( eventListener );
+	}
+	
+	protected void
+	addDefaultDropListener(
+		MdiEntry		mainSbEntry )
+	{
+		mainSbEntry.addListener(
+				new MdiEntryDropListener()
+				{
+					public boolean 
+					mdiEntryDrop(
+						MdiEntry 		entry, 
+						Object 				payload  )
+					{
+						return handleDrop(null, payload);
+					}
+				});
+	}
+	
+	protected void
+	showProperties(
+		Device		device )
+	{
+		String[][] props = device.getDisplayProperties();
+		
+		new PropertiesWindow( device.getName(), props[0], props[1] );
+	}
+	
+	protected int
+	nextSidebarID()
+	{
+		synchronized( this ){
+			
+			return( next_sidebar_id++ );
+		}
+	}
+	
+	protected abstract static class
+	categoryView
+		implements 	ViewTitleInfo, UISWTViewEventListener
+	{
+		private DeviceManagerUI	ui;
+		private int				device_type;
+		private String			title;
+			
+		private String			key;
+			
+		private MdiEntryVitalityImage spinner;
+		private MdiEntryVitalityImage warning;
+		private MdiEntryVitalityImage info;
+		
+		private int				last_indicator;
+		private MdiEntry mdiEntry;
+		private UISWTView swtView;
+		
+		protected
+		categoryView(
+			DeviceManagerUI		_ui,
+			int					_device_type,
+			String				_title )
+		{
+			ui				= _ui;
+			device_type		= _device_type;
+			title			= _title;
+		}
+		
+		protected void
+		setDetails(
+			MdiEntry	entry,
+			String			_key )
+		{
+			mdiEntry = entry;
+			
+			key			= _key;
+			
+			spinner = entry.addVitalityImage( SPINNER_IMAGE_ID );
+
+			hideIcon( spinner );
+			
+			warning = entry.addVitalityImage( ALERT_IMAGE_ID );
+
+			hideIcon( warning );
+			
+			info = entry.addVitalityImage( INFO_IMAGE_ID );
+
+			hideIcon( info );
+		}
+		
+		
+		protected int
+		getDeviceType()
+		{
+			return( device_type );
+		}
+		
+		protected String
+		getKey()
+		{
+			return( key );
+		}
+		
+		protected String
+		getTitle()
+		{
+			return( MessageText.getString( title ));
+		}
+		
+		public Object 
+		getTitleInfoProperty(
+			int propertyID ) 
+		{
+			boolean expanded = mdiEntry != null && mdiEntry.isExpanded();
+			
+			if ( propertyID == TITLE_TEXT ){
+				
+				return( getTitle());
+				
+			}else if ( propertyID == TITLE_INDICATOR_TEXT ){
+			
+				if ( device_type == Device.DT_MEDIA_RENDERER || device_type == Device.DT_OFFLINE_DOWNLOADER ){ 
+				
+					if ( spinner != null ){
+					
+						spinner.setVisible( !expanded && ui.getDeviceManager().isBusy( device_type ));
+					}
+					
+					if ( !expanded ){
+										
+						Device[] devices = ui.getDeviceManager().getDevices();
+						
+						last_indicator = 0;
+						
+						String all_errors 	= "";
+						String all_infos	= "";
+						
+						for ( Device device: devices ){
+							
+							if ( device_type != device.getType()){
+									
+								continue;
+							}
+							
+							String error = device.getError();
+							
+							if ( error != null ){
+								
+								all_errors += (all_errors.length()==0?"":"; ") + error;
+							}
+							
+							String info = device.getInfo();
+							
+							if ( info != null ){
+								
+								all_infos += (all_infos.length()==0?"":"; ") + info;
+							}
+							
+							if ( device instanceof DeviceMediaRenderer ){
+						
+								if ( SHOW_RENDERER_VITALITY ){
+									
+									DeviceMediaRenderer	renderer = (DeviceMediaRenderer)device;
+									
+									last_indicator += renderer.getCopyToDevicePending() + renderer.getCopyToFolderPending();
+								}
+							}else if ( device instanceof DeviceOfflineDownloader ){
+								
+								if ( SHOW_OD_VITALITY ){
+									
+									DeviceOfflineDownloader dod = (DeviceOfflineDownloader)device;
+									
+									last_indicator += dod.getTransferingCount();
+								}
+							}
+						}
+						
+						if ( all_errors.length() > 0 ){
+							 
+							showIcon( warning, all_errors );
+													
+						}else{
+							
+							hideIcon( warning );
+							
+							if ( all_infos.length() > 0 ){
+							
+								showIcon( info, all_infos );
+																			
+							}else{
+							
+								hideIcon( info );
+							}
+						}
+						
+						if ( last_indicator > 0 ){
+														
+							return( String.valueOf( last_indicator ));
+						}
+					}else{
+						
+						hideIcon( warning );
+						hideIcon( info );
+					}
+				}
+			}else if ( propertyID == TITLE_INDICATOR_COLOR ){
+				
+				/*
+				if ( last_indicator > 0 ){
+				
+					if ( SHOW_VITALITY ){
+					
+						return( to_copy_indicator_colors );
+					}
+				}
+				*/
+			}
+			
+			return null;
+		}
+		
+		protected void
+		destroy()
+		{
+			if ( Utils.isThisThreadSWT()){
+				
+				mdiEntry.close(false);
+				
+			}else{
+				
+				Utils.execSWTThread(
+						new Runnable()
+						{
+							public void
+							run()
+							{
+								mdiEntry.close(false);
+																
+							}
+						});
+			}
+		}
+
+		public boolean eventOccurred(UISWTViewEvent event) {
+	    switch (event.getType()) {
+	      case UISWTViewEvent.TYPE_CREATE:
+	      	swtView = (UISWTView)event.getData();
+	      	swtView.setTitle(title);
+	        break;
+	    }
+
+	    return true;
+	  }
+	}
+	
+	protected static class
+	categoryViewGeneric
+		extends 	categoryView
+	{
+		private Composite		composite;
+		
+		protected
+		categoryViewGeneric(
+			DeviceManagerUI		_ui,
+			int					_device_type,
+			String				_title )
+		{
+			super( _ui, _device_type, _title );
+		}
+		
+		public void 
+		initialize(
+			Composite parent_composite )
+		{  
+			composite = new Composite( parent_composite, SWT.NULL );
+			
+			FormLayout layout = new FormLayout();
+			
+			layout.marginTop	= 4;
+			layout.marginLeft	= 4;
+			layout.marginRight	= 4;
+			layout.marginBottom	= 4;
+			
+			composite.setLayout( layout );
+
+			FormData data = new FormData();
+			data.left = new FormAttachment(0,0);
+			data.right = new FormAttachment(100,0);
+			data.top = new FormAttachment(composite,0);
+			data.bottom = new FormAttachment(100,0);
+
+
+			Label label = new Label( composite, SWT.NULL );
+			
+			label.setText( "Nothing to show for " + getTitle());
+			
+			label.setLayoutData( data );
+		}
+		
+		public Composite 
+		getComposite()
+		{
+			return( composite );
+		}
+		
+		public boolean eventOccurred(UISWTViewEvent event) {
+	    switch (event.getType()) {
+	      case UISWTViewEvent.TYPE_CREATE:
+	      	//swtView = (UISWTView)event.getData();
+	        break;
+
+	      case UISWTViewEvent.TYPE_DESTROY:
+	        break;
+
+	      case UISWTViewEvent.TYPE_INITIALIZE:
+	        initialize((Composite)event.getData());
+	        break;
+
+	      case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
+	      	Messages.updateLanguageForControl(getComposite());
+	        break;
+
+	      case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
+	        break;
+	        
+	      case UISWTViewEvent.TYPE_FOCUSGAINED:
+	      	break;
+	        
+	      case UISWTViewEvent.TYPE_REFRESH:
+	        break;
+	    }
+
+	    return true;
+	  }
+	}
+	
+	protected class
+	deviceView
+		implements 	ViewTitleInfo, TranscodeTargetListener, UISWTViewEventListener
+	{
+		private String			parent_key;
+		private Device			device;
+		
+		private Composite		parent_composite;
+		private Composite		composite;
+		
+		private int last_indicator;
+		private UISWTView swtView;
+
+		protected
+		deviceView(
+			String			_parent_key,
+			Device			_device )
+		{
+			parent_key	= _parent_key;
+			device		= _device;
+			
+			if ( device instanceof DeviceMediaRenderer ){
+				
+				DeviceMediaRenderer	renderer = (DeviceMediaRenderer)device;
+
+				renderer.addListener( this );
+			}
+		}
+			
+		public void 
+		initialize(
+			Composite _parent_composite )
+		{  
+			parent_composite	= _parent_composite;
+
+			composite = new Composite( parent_composite, SWT.NULL );
+			
+			FormLayout layout = new FormLayout();
+			
+			layout.marginTop	= 4;
+			layout.marginLeft	= 4;
+			layout.marginRight	= 4;
+			layout.marginBottom	= 4;
+			
+			composite.setLayout( layout );
+			
+			if ( device instanceof DeviceContentDirectory ){
+				
+				Label  ms_label = new Label( composite, SWT.NULL );				
+				ms_label.setText( "Media Server: " + device.getName());
+				
+				final Button refresh = new Button( composite, SWT.PUSH );				
+				refresh.setText( "Refresh" );
+
+				final StyledText   info = 
+					new StyledText(composite, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL)
+					{
+						private boolean adding = false;
+						private Event	last_event;
+						
+						public void
+						addListener(
+							int 			eventType, 
+							final Listener	listener)
+						{
+							if ( eventType == SWT.MouseDown && !adding ){
+								
+								try{
+									adding = true;
+								
+									super.addListener(
+										eventType,
+										new Listener()
+										{
+											public void 
+											handleEvent(
+												Event event )
+											{
+												if ( event.type == SWT.MouseDown && event != last_event ){
+													
+													if ( event.button == 1 && event.stateMask != SWT.CONTROL ){
+														
+														last_event = event;
+														
+														try{
+																// this code is to allow a click+drag operation to work as StyledText needs a selection
+																// before it will initiate a drag
+															
+															int offset = getOffsetAtLocation( new Point( event.x, event.y ));
+															
+															final StyleRange style = getStyleRangeAtOffset(offset);
+															
+															if ( style != null ){
+																
+																Object data = style.data;
+																
+																if ( data instanceof UPNPMSItem ){
+																	
+																	int line 		= getLineAtOffset(offset);
+																	int lineOffset 	= getOffsetAtLine(line);	
+																	
+																	setSelection( lineOffset, lineOffset + getLine( line ).length());
+																}
+															}	
+														}catch( Throwable e){
+														}
+													}
+												}
+																								
+												listener.handleEvent( event );
+											}	
+											
+										});
+								}finally{
+									
+									adding = false;
+								}
+							}else{
+								
+								super.addListener(eventType, listener);
+							}
+						}
+					};
+
+				info.setEditable( false );
+				
+				info.setSelectionForeground( info.getForeground());
+				info.setSelectionBackground( info.getBackground());
+				
+				FormData data = new FormData();				
+				data.left 	= new FormAttachment(0,0);
+				data.bottom = new FormAttachment(info,-8);
+				ms_label.setLayoutData( data );
+				
+				
+				data = new FormData();
+				data.left 	= new FormAttachment(ms_label,4 );
+				data.top 	= new FormAttachment(composite,0);
+				refresh.setLayoutData( data );
+									
+
+				data = new FormData();				
+				data.left 	= new FormAttachment(0,0);
+				data.right 	= new FormAttachment(100,0);
+				data.top 	= new FormAttachment(refresh,4);
+				data.bottom = new FormAttachment(100,0);
+				info.setLayoutData( data );
+
+				final Runnable do_refresh =
+					new Runnable()
+					{
+						private	UPNPMSItem dragging_item;
+						
+						{
+							final DragSource drag_source = new DragSource(info, DND.DROP_MOVE | DND.DROP_COPY);
+							
+							drag_source.setTransfer( new Transfer[] { TextTransfer.getInstance() });
+							
+							drag_source.addDragListener(
+								new DragSourceAdapter() 
+								{	
+									public void 
+									dragStart(
+										DragSourceEvent event ) 
+									{		
+										event.doit = false;
+										
+										try{
+											int offset = info.getOffsetAtLocation(new Point(event.x, event.y));
+											
+											StyleRange style = info.getStyleRangeAtOffset(offset);
+											
+											if ( style != null ){
+												
+												Object data = style.data;
+												
+												if ( data instanceof UPNPMSItem ){
+													
+													UPNPMSItem item = (UPNPMSItem)data;
+														
+													if ( item.getURL() != null ){
+													
+														dragging_item = item;
+													
+														event.doit = true;
+													}
+												}
+											}
+										}catch( Throwable e ){	
+										}
+									}
+									
+									public void 
+									dragSetData(
+										DragSourceEvent event) 
+									{
+										if ( dragging_item != null ){
+											
+											String url = dragging_item.getURL().toExternalForm();
+											
+												// these parameters are used to identify this as a content-data relative
+												// URL as opposed to a torrent download one, and also provide the content name
+											
+											url += ( url.contains( "?" )?"&":"?") + "azcdid=" + RandomUtils.INSTANCE_ID + "&azcddn=" + UrlUtils.encode( dragging_item.getTitle());
+																					
+											event.data = url;
+											
+										}else{
+											
+											event.data 	= null;
+											event.doit	= false;
+										}
+									}
+									
+									public void 
+									dragFinished(
+										DragSourceEvent event) 
+									{
+										dragging_item = null;
+										
+										try{
+											Point selection = info.getSelection();
+											
+											info.setSelection( selection.x, selection.x );
+											
+										}catch( Throwable e ){	
+										}
+									}
+								});
+							
+							final DropTarget drop_target = new DropTarget(info, DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK);
+							
+							drop_target.setTransfer(new Transfer[0]);
+
+							info.addDisposeListener(
+								new DisposeListener() 
+								{
+									public void 
+									widgetDisposed(
+										DisposeEvent e ) 
+									{
+										if (!drag_source.isDisposed()) {
+											drag_source.dispose();
+										}
+										
+										if (!drop_target.isDisposed()) {
+											drop_target.dispose();
+										}
+									}
+								});
+							
+					
+							
+							info.addMouseListener(
+								new MouseListener()
+								{
+									public void 
+									mouseDoubleClick(
+										MouseEvent arg0) 
+									{
+									}
+									
+									public void 
+									mouseDown(
+										MouseEvent event) 
+									{
+										if ( info.isDisposed()){
+											return;
+										}
+										
+										try{
+											int offset = info.getOffsetAtLocation(new Point (event.x, event.y));
+											
+											StyleRange style = info.getStyleRangeAtOffset(offset);
+											
+											if ( style != null ){
+												
+												Object data = style.data;
+												
+												if ( data instanceof UPNPMSItem ){
+													
+													UPNPMSItem item = (UPNPMSItem)data;
+													
+													if (	event.button == 3 || 
+															(event.button == 1 && event.stateMask == SWT.CONTROL)){
+														
+														  final Menu menu = new Menu(info.getShell(),SWT.POP_UP);
+														  
+														  final URL url = item.getURL();
+															
+														  if ( url != null ){
+	
+															  org.eclipse.swt.widgets.MenuItem   menu_item = new org.eclipse.swt.widgets.MenuItem( menu,SWT.NONE );
+		
+															  menu_item.setText( MessageText.getString( "devices.copy_url"));
+		
+															  menu_item.addSelectionListener(
+																  new SelectionAdapter()
+																  {
+																	  public void 
+																	  widgetSelected(
+																			  SelectionEvent arg0) 
+																	  {
+																		  ClipboardCopy.copyToClipBoard(url.toExternalForm());
+																	  }
+																  });
+															  
+															 
+															  menu_item = new org.eclipse.swt.widgets.MenuItem( menu,SWT.NONE );
+																	
+															  menu_item.setText( MessageText.getString( "iconBar.run"));
+			
+															  menu_item.addSelectionListener(
+																  new SelectionAdapter()
+																  {
+																	  public void 
+																	  widgetSelected(
+																		  SelectionEvent arg0) 
+																	  {
+																		 Utils.launch( url );
+																	  }
+																  });
+															 
+														  
+															  menu_item.setEnabled( item.getItemClass() != UPNPMSItem.IC_OTHER );
+														  }
+														  
+														  info.setMenu( menu );
+	
+														  menu.addMenuListener(
+																  new MenuAdapter()
+																  {
+																	  public void 
+																	  menuHidden(
+																			  MenuEvent arg0 )
+																	  {
+																		  if ( info.getMenu() == menu ){
+																		  
+																			  info.setMenu( null );
+																		  }
+																	  }
+																  });
+	
+														  menu.setVisible( true );
+													}
+												}
+											}
+										}catch( Throwable e ){
+										}
+									}
+									
+									public void 
+									mouseUp(
+										MouseEvent event) 
+									{
+										if ( info.isDisposed()){
+											return;
+										}
+										
+										try{
+											int offset = info.getOffsetAtLocation(new Point (event.x, event.y));
+											
+											StyleRange style = info.getStyleRangeAtOffset(offset);
+											
+											if ( style != null ){
+												
+												Object data = style.data;
+												
+												if ( data instanceof UPNPMSItem ){
+													
+													UPNPMSItem item = (UPNPMSItem)data;
+													
+													if ( event.button == 1 ){
+															
+														if ( style.underline ){
+														
+															URL url = item.getURL();
+														
+															if ( url != null ){
+															
+																PlayUtils.playURL( url, item.getTitle());
+															}
+														}
+													}
+												}
+											}
+										}catch( Throwable e ){
+										}
+									}
+								});
+					
+							info.addMouseTrackListener(
+									new MouseTrackAdapter()
+									{
+										@Override
+										public void 
+										mouseHover(
+											MouseEvent event ) 
+										{
+											if ( info.isDisposed()){
+												return;
+											}
+											
+											String tooltip = "";
+											
+											try{
+												int offset = info.getOffsetAtLocation(new Point (event.x, event.y));
+												
+												StyleRange style = info.getStyleRangeAtOffset(offset);
+												
+												if ( style != null ){
+													
+													Object data = style.data;
+													
+													if ( data instanceof UPNPMSItem ){
+														
+														UPNPMSItem item = (UPNPMSItem)data;
+														
+														if ( item != null ){
+															
+															tooltip = DisplayFormatters.formatByteCountToKiBEtc( item.getSize());
+														}
+													}
+												}
+											}catch( Throwable e ){
+												
+											}
+											
+											info.setToolTipText( tooltip );
+										}
+									});
+							
+							info.addMouseMoveListener(
+								new MouseMoveListener()
+								{
+									private StyleRange	last_style;
+									
+									public void 
+									mouseMove(
+										MouseEvent event) 
+									{
+										try{
+											int offset = info.getOffsetAtLocation(new Point (event.x, event.y));
+										
+											StyleRange style = info.getStyleRangeAtOffset(offset);
+										
+											if ( style != last_style ){
+												
+												last_style = style;
+												
+												info.setToolTipText( "" );
+											}
+										}catch( Throwable e ){											
+										}
+									}
+								});
+						}
+						
+						boolean play_available;
+						
+						public void
+						run()
+						{
+							boolean	went_async = false;
+							
+							try{
+								refresh.setEnabled( false );
+							
+								info.setText( "" );
+								
+								play_available = PlayUtils.isEMPAvailable();
+								
+								final DeviceContentDirectory cd = (DeviceContentDirectory)device;
+								
+								final List<URL> endpoints = cd.getControlURLs();
+				
+								if ( endpoints == null || endpoints.size() == 0 ){
+				
+									info.append( "Media Server is offline" );
+									
+								}else{
+									
+									new AEThread2( "CD:populate" )
+									{
+										private int				line_count;
+										private List<Object[]>	lines_to_add = new ArrayList<Object[]>();
+										
+										
+										public void
+										run()
+										{
+											try{
+												String client_name = device_manager.getLocalServiceName();
+												
+												UPNPMSBrowser browser = 
+													UPNPMSBrowserFactory.create( 
+														client_name, 
+														endpoints,
+														new UPNPMSBrowserListener()
+														{
+															public void 
+															setPreferredURL(
+																URL url )
+															{
+																cd.setPreferredControlURL( url );
+															}
+														});
+												
+												print( browser.getRoot(), "" );
+																				
+											}catch( Throwable e ){
+												
+												Debug.out( e );
+												
+											}finally{
+												
+												Utils.execSWTThread(
+														new Runnable()
+														{
+															public void
+															run()
+															{
+																if ( !refresh.isDisposed()){
+															
+																	refresh.setEnabled( true );
+																}
+															}
+														});
+											}
+										}
+										
+										private boolean
+										print(
+											UPNPMSContainer		container,
+											String				indent )
+										
+											throws UPnPMSException
+										{
+											if ( !appendLine( indent, container )){
+												
+												return( false );
+											}
+											
+											try{
+												indent += "\t\t";
+												
+												List<UPNPMSNode> kids = container.getChildren();
+												
+												for ( UPNPMSNode kid: kids ){
+												
+													if ( kid instanceof UPNPMSContainer){
+													
+														if ( !print((UPNPMSContainer)kid, indent )){
+															
+															return( false );
+														}
+														
+													}else{
+														
+														if ( !print((UPNPMSItem)kid, indent )){
+															
+															return( false );
+														}
+													}
+												}
+												
+												return( true );
+												
+											}finally{
+											
+												updateInfo();
+											}
+										}
+										
+										private boolean
+										print(
+											UPNPMSItem			item,
+											String				indent )
+										{
+											return( appendLine( indent, item ));
+										}
+										
+										private boolean
+										appendLine(
+											String	indent,
+											Object	obj )
+										{
+											line_count++;
+											
+											if ( line_count >= max_ms_display_lines ){
+												
+												if ( line_count == max_ms_display_lines ){
+												
+													lines_to_add.add( new Object[]{ indent, "Too many entries, output truncated..." });
+												}
+												
+												return( false );
+												
+											}else{
+											
+												lines_to_add.add( new Object[]{ indent, obj });
+												
+												return( true );
+											}
+										}
+										
+										private void
+										updateInfo()
+										{
+											if ( info.isDisposed()){
+												
+												return;
+											}
+											
+											final List<Object[]> temp = lines_to_add;
+											
+											lines_to_add = new ArrayList<Object[]>();
+											
+											Utils.execSWTThread(
+												new Runnable()
+												{
+													public void
+													run()
+													{
+														if ( info.isDisposed()){
+															
+															return;
+														}
+														
+														for ( Object[] entry: temp ){
+															
+															String	indent 	= (String)entry[0];
+															Object	obj		= entry[1];
+															
+															String line = indent;
+															
+															if ( obj instanceof UPNPMSContainer ){
+																
+																UPNPMSContainer container = (UPNPMSContainer)obj;
+															
+																line += container.getTitle();
+																
+																line += "\r\n";
+																
+																int	start_pos = info.getCharCount();
+																															
+																info.append( line );
+																
+																StyleRange style = new StyleRange(start_pos, line.length(), null, null, SWT.BOLD );
+																										
+																info.setStyleRange( style );
+															
+															}else if ( obj instanceof UPNPMSItem ){
+																
+																UPNPMSItem item = (UPNPMSItem)obj;
+																
+																line += item.getTitle();
+																
+																line += "\r\n";
+																
+																int	start_pos = info.getCharCount();
+																															
+																info.append( line );
+																
+																String item_class = item.getItemClass();
+																
+																if ( 	play_available &&
+																		item.getURL() != null &&
+																		(	item_class == UPNPMSItem.IC_VIDEO ||
+																			item_class == UPNPMSItem.IC_AUDIO )){
+																	
+																	StyleRange style = new StyleRange(start_pos + indent.length(), line.length() - indent.length(), null, null, SWT.NORMAL );
+																			
+																	style.underline 		= true;
+																	style.underlineStyle 	= SWT.UNDERLINE_LINK;
+																	
+																	style.data = item;
+																	
+																	info.setStyleRange( style );
+																	
+																}else{
+																	
+																	StyleRange style = new StyleRange(start_pos, line.length(), null, null, SWT.ITALIC );
+																	
+																	style.data = item;
+																	
+																	info.setStyleRange( style );
+																}
+															}else{
+																
+																line += (String)obj;
+																
+																line += "\r\n";
+																
+																int	start_pos = info.getCharCount();
+																															
+																info.append( line );
+																
+																StyleRange style = new StyleRange(start_pos, line.length(), null, null, SWT.NULL );
+																										
+																info.setStyleRange( style );
+															}
+														}
+													}
+												});
+										}
+									}.start();
+									
+									went_async = true;
+								}
+							}finally{
+								if ( !went_async ){
+								
+									refresh.setEnabled( true );
+								}
+							}
+						}
+					};
+					
+				do_refresh.run();
+				
+				refresh.addListener(
+					SWT.Selection,
+					new Listener()
+					{
+						public void 
+						handleEvent(Event arg0) 
+						{
+							do_refresh.run();
+						}
+					});
+			}else{
+				
+				FormData data = new FormData();
+				
+				data.left 	= new FormAttachment(0,0);
+				data.right 	= new FormAttachment(100,0);
+				data.top 	= new FormAttachment(composite,0);
+				data.bottom = new FormAttachment(100,0);
+
+				Label label = new Label( composite, SWT.NULL );
+				
+				label.setText( "Nothing to show for " + device.getName());
+				
+				label.setLayoutData( data );
+			}
+		}
+		
+		public Composite 
+		getComposite()
+		{
+			return( composite );
+		}
+		
+		public Object 
+		getTitleInfoProperty(
+			int propertyID ) 
+		{		
+			if ( propertyID == TITLE_TEXT ){
+				
+				return( getTitle());
+				
+			} else if (propertyID == TITLE_IMAGEID) {
+				String imageID = null;
+				final String id = getDeviceImageID( device );
+				
+				if ( id != null ){
+					
+					imageID = "image.sidebar.device." + id + ".small";
+
+					if (id.startsWith("http")) {
+						if (ImageLoader.getInstance().imageAdded_NoSWT(id)) {
+							imageID = id;
+						} else {
+  						Utils.execSWTThreadLater(0, new AERunnable() {
+  							public void runSupport() {
+  								ImageLoader.getInstance().getUrlImage(id, new ImageDownloaderListener() {
+  									public void imageDownloaded(Image image, boolean returnedImmediately) {
+  										ViewTitleInfoManager.refreshTitleInfo( deviceView.this );
+  									}
+  								});
+  							}
+  						});
+						}
+					}
+				}
+				
+				return imageID;
+				
+			}else if ( propertyID == TITLE_INDICATOR_TEXT ){
+				
+				if ( device instanceof DeviceMediaRenderer ){
+					
+					if ( SHOW_RENDERER_VITALITY ){
+					
+						DeviceMediaRenderer	renderer = (DeviceMediaRenderer)device;
+					
+					
+						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 ){
+					
+						return( to_copy_indicator_colors );
+					}
+				}
+				*/
+			}else if ( propertyID == TITLE_ACTIVE_STATE ){
+
+				if ( device.isLivenessDetectable()){
+				
+					return( new Long( device.isAlive()?1:2 ));
+				}
+			}else if ( propertyID == TITLE_INDICATOR_TEXT_TOOLTIP){
+
+				return( device.getStatus());
+			}
+			
+			return null;
+		}
+		
+		public String
+		getTitle()
+		{
+			return( device.getName());
+		}
+		
+		public void
+		fileAdded(
+			TranscodeFile		file )
+		{	
+		}
+		
+		public void
+		fileChanged(
+			TranscodeFile		file,
+			int					type,
+			Object				data )
+		{
+			if ( 	type == TranscodeTargetListener.CT_PROPERTY &&
+					data == TranscodeFile.PT_COMPLETE ){
+				
+				refreshTitles();
+			}
+		}
+		
+		protected void
+		refreshTitles()
+		{
+			ViewTitleInfoManager.refreshTitleInfo( this );
+
+			String	key = parent_key;
+			
+			while( key != null ){
+			
+				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+				
+				if ( mdi == null ){
+					
+					break;
+					
+				}else{
+					
+					MdiEntry parent = mdi.getEntry( key );
+				
+					if ( parent != null ){
+					
+						ViewTitleInfoManager.refreshTitleInfo(parent.getViewTitleInfo());
+						
+						key = parent.getParentID();
+					} else {
+						key = null;
+					}
+				}
+			}
+		}
+		
+		public void
+		fileRemoved(
+			TranscodeFile		file )
+		{	
+		}
+		
+		private void
+		delete()
+		{
+			if ( device instanceof DeviceMediaRenderer ){
+				
+				DeviceMediaRenderer	renderer = (DeviceMediaRenderer)device;
+
+				renderer.removeListener( this );
+			}
+		}
+
+		public boolean eventOccurred(UISWTViewEvent event) {
+	    switch (event.getType()) {
+	      case UISWTViewEvent.TYPE_CREATE:
+	      	swtView = (UISWTView)event.getData();
+	      	swtView.setTitle(getTitle());
+	        break;
+
+	      case UISWTViewEvent.TYPE_DESTROY:
+	        delete();
+	        break;
+
+	      case UISWTViewEvent.TYPE_INITIALIZE:
+	        initialize((Composite)event.getData());
+	        break;
+
+	      case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
+	      	Messages.updateLanguageForControl(getComposite());
+	      	swtView.setTitle(getTitle());
+	        break;
+
+	      case UISWTViewEvent.TYPE_DATASOURCE_CHANGED:
+	        break;
+	        
+	      case UISWTViewEvent.TYPE_FOCUSGAINED:
+	      	break;
+	        
+	      case UISWTViewEvent.TYPE_REFRESH:
+	        break;
+	    }
+
+	    return true;
+	  }
+
+	}
+	
+	private static class
+	deviceItem
+	{		
+		private deviceView			view;
+		private MdiEntry		sb_entry;
+		private boolean				destroyed;
+		
+		private MdiEntryVitalityImage	warning;
+		private MdiEntryVitalityImage	spinner;
+		private MdiEntryVitalityImage	info;
+		
+		protected
+		deviceItem()
+		{
+		}
+		
+		protected void
+		setMdiEntry(
+			MdiEntry	_sb_entry )
+		{
+			sb_entry	= _sb_entry;
+			
+			warning = sb_entry.addVitalityImage( ALERT_IMAGE_ID );
+			
+			hideIcon( warning );
+			
+			spinner = sb_entry.addVitalityImage( SPINNER_IMAGE_ID );
+			
+			hideIcon( spinner );
+			
+			info = sb_entry.addVitalityImage( INFO_IMAGE_ID );
+			
+			hideIcon( info );
+		}
+		
+		protected MdiEntry
+		getMdiEntry()
+		{
+			return( sb_entry );
+		}
+		
+		protected void
+		setView(
+			deviceView		_view )
+		{
+			view	= _view;
+		}
+		
+		protected deviceView
+		getView()
+		{
+			return( view );
+		}
+		
+		protected void
+		setStatus(
+			Device	device )
+		{
+				// possible during initialisation, status will be shown again on complete
+			
+			if ( warning != null && info != null ){
+							
+				String error = device.getError();
+				
+				if ( error != null ){
+				 
+					hideIcon( info );
+					
+					warning.setToolTip( error );
+					
+					warning.setImageID( ALERT_IMAGE_ID );
+					
+					warning.setVisible( true );
+					
+				}else{
+					
+					hideIcon( warning );
+					
+					String info_str = device.getInfo();
+					
+					if ( info_str != null ){
+						
+						showIcon( info, info_str );
+						
+					}else{
+						
+						hideIcon( info );
+					}
+				}
+			}
+			
+			if ( spinner != null ){
+						
+				spinner.setVisible( device.isBusy());
+			}
+			
+			if ( view != null ){
+				
+				view.refreshTitles();
+			}
+		}
+		
+		protected boolean
+		isDestroyed()
+		{
+			return( destroyed );
+		}
+		
+		protected void
+		destroy()
+		{
+			destroyed = true;
+			
+			if (sb_entry != null) {
+				sb_entry.close(false);
+			}
+		}
+		
+		public void 
+		activate() 
+		{
+			MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+			
+			if ( mdi != null && sb_entry != null ){
+				
+				mdi.showEntryByID(sb_entry.getId());
+			}
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesFTUX.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesFTUX.java
index 17c595a..7f86a68 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesFTUX.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesFTUX.java
@@ -1,10 +1,12 @@
 /**
  * Created on Mar 7, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -22,7 +24,6 @@ import java.util.*;
 import java.util.List;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.Browser;
 import org.eclipse.swt.events.*;
 import org.eclipse.swt.layout.FormAttachment;
 import org.eclipse.swt.layout.FormData;
@@ -54,10 +55,9 @@ import com.aelitis.azureus.ui.mdi.MdiEntry;
 import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.mdi.MdiEntryVitalityImage;
 import com.aelitis.azureus.ui.swt.browser.BrowserContext;
-import com.aelitis.azureus.ui.swt.browser.BrowserWrapper;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 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;
 
 /**
@@ -130,7 +130,7 @@ public class DevicesFTUX
 		Utils.setShellIcon(shell);
 
 		try {
-			browser = new BrowserWrapper( Utils.createSafeBrowser(shell, SWT.NONE));
+			browser = Utils.createSafeBrowser(shell, SWT.NONE);
 			if (browser != null) {
   			BrowserContext context = new BrowserContext("DevicesFTUX", browser, null, true);
   
@@ -253,7 +253,7 @@ public class DevicesFTUX
 		lblLearnMore.setLayoutData(fd);
 		
 		fd = new FormData();
-		fd.top = new FormAttachment(browser.getBrowser(), 0);
+		fd.top = new FormAttachment(browser.getControl(), 0);
 		fd.bottom = new FormAttachment(100, 0);
 		fd.left = new FormAttachment(0, 0);
 		fd.right = new FormAttachment(100, 0);
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesODFTUX.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesODFTUX.java
index d398f84..1f8409f 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesODFTUX.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesODFTUX.java
@@ -1,10 +1,12 @@
 /**
  * Created on Mar 7, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesWizard.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesWizard.java
index c57f6b8..2de4bd6 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesWizard.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/DevicesWizard.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.devices;
 
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/SBC_DevicesODView.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/SBC_DevicesODView.java
index 4a7f67b..9eb4eda 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/SBC_DevicesODView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/SBC_DevicesODView.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 24, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/SBC_DevicesView.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/SBC_DevicesView.java
index 9b29e6a..2b1edfb 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/SBC_DevicesView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/SBC_DevicesView.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 24, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -28,9 +30,11 @@ import org.eclipse.swt.dnd.*;
 import org.eclipse.swt.events.*;
 import org.eclipse.swt.layout.GridLayout;
 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.internat.MessageText;
 import org.gudy.azureus2.core3.util.Debug;
@@ -48,7 +52,6 @@ import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
 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.TableViewFactory;
-import org.gudy.azureus2.ui.swt.views.table.impl.TableViewSWTImpl;
 import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
 import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
 
@@ -56,10 +59,7 @@ import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.AzureusCoreRunningListener;
 import com.aelitis.azureus.core.devices.*;
-import com.aelitis.azureus.core.tag.Tag;
-import com.aelitis.azureus.core.tag.TagManager;
-import com.aelitis.azureus.core.tag.TagManagerFactory;
-import com.aelitis.azureus.core.tag.TagType;
+import com.aelitis.azureus.core.tag.*;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.UserPrompterResultListener;
@@ -67,14 +67,18 @@ import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.common.table.*;
 import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdatable;
+import com.aelitis.azureus.ui.selectedcontent.SelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.columns.torrent.ColumnThumbnail;
 import com.aelitis.azureus.ui.swt.devices.columns.*;
 import com.aelitis.azureus.ui.swt.mdi.MdiEntrySWT;
 import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
-import com.aelitis.azureus.ui.swt.skin.*;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectText;
+import com.aelitis.azureus.ui.swt.utils.TagUIUtilsV3;
 import com.aelitis.azureus.ui.swt.views.skin.InfoBarUtil;
 import com.aelitis.azureus.ui.swt.views.skin.SkinView;
 import com.aelitis.azureus.ui.swt.views.skin.TorrentListViewsUtils;
@@ -407,6 +411,8 @@ public class SBC_DevicesView
 		// 7) Go to 1
 		//DevicesFTUX.ensureInstalled();
 
+		updateSelectedContent();
+		
 		return null;
 	}
 
@@ -528,13 +534,7 @@ public class SBC_DevicesView
 		tvFiles.addSelectionListener(new TableSelectionListener() {
 
 			public void selected(TableRowCore[] row) {
-				SelectedContentManager.clearCurrentlySelectedContent();
-
-				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
-				if (uiFunctions != null) {
-					uiFunctions.refreshIconBar();
-				}
-				
+				updateSelectedContent();
 			}
 
 			public void mouseExit(TableRowCore row) {
@@ -544,29 +544,16 @@ public class SBC_DevicesView
 			}
 
 			public void focusChanged(TableRowCore focus) {
-				SelectedContentManager.clearCurrentlySelectedContent();
-				
-				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
-				if (uiFunctions != null) {
-					uiFunctions.refreshIconBar();
-				}
 			}
 
 			public void deselected(TableRowCore[] rows) {
-				SelectedContentManager.clearCurrentlySelectedContent();
-				
-				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
-				if (uiFunctions != null) {
-					uiFunctions.refreshIconBar();
-				}
+				updateSelectedContent();
 			}
 
 			public void defaultSelected(TableRowCore[] rows, int stateMask) {
-				SelectedContentManager.clearCurrentlySelectedContent();
-				
 			}
 		}, false);
-
+		
 		tvFiles.addLifeCycleListener(new TableLifeCycleListener() {
 			public void tableViewInitialized() {
 				if (transTarget == null) {
@@ -581,6 +568,7 @@ public class SBC_DevicesView
 				} else {
 					tvFiles.addDataSources(transTarget.getFiles());
 				}
+				updateSelectedContent();
 			}
 
 			public void tableViewDestroyed() {
@@ -1245,20 +1233,27 @@ public class SBC_DevicesView
 		
 		item_create.addListener(SWT.Selection, new Listener() {
 			public void handleEvent(Event event) {
-				
-				Tag new_tag = TagUIUtils.createManualTag();
-				
-				if ( new_tag != null ){
-					
-					String[] tags = new String[]{ String.valueOf( new_tag.getTagUID()) };
-					
-					for ( TranscodeFile file: files ){
-						
-						file.setTags( tags );
+
+				TagUIUtilsV3.showCreateTagDialog(new UIFunctions.TagReturner() {
+					public void returnedTags(Tag[] tags) {
+						if ( tags != null ){
+							for (Tag new_tag : tags) {
+								if ( new_tag != null ){
+									
+									String[] tagUIDs = new String[]{ String.valueOf( new_tag.getTagUID()) };
+									
+									for ( TranscodeFile file: files ){
+										
+										file.setTags( tagUIDs );
+									}
+									
+									COConfigurationManager.setParameter( "Library.TagInSideBar", true );
+								}
+							}
+						}
 					}
-					
-					COConfigurationManager.setParameter( "Library.TagInSideBar", true );
-				}
+				});
+				
 			}
 		});
 	}
@@ -1298,6 +1293,8 @@ public class SBC_DevicesView
 				| SWT.FULL_SELECTION);
 		tvDevices.setRowDefaultHeight(25);
 		tvDevices.setHeaderVisible(true);
+		
+		
 
 		Composite parent = new Composite(control, SWT.NONE);
 		parent.setLayoutData(Utils.getFilledFormData());
@@ -1939,4 +1936,21 @@ public class SBC_DevicesView
 			Debug.out( "failed to init drag-n-drop", t);
 		}
 	}
+	
+	public void updateSelectedContent() {
+		TableView tv = tvFiles!=null?tvFiles:tvDevices;
+		Object[] dataSources = tv.getSelectedDataSources(true);
+		List<SelectedContent> listSelected = new ArrayList<SelectedContent>(
+				dataSources.length);
+		for (Object ds : dataSources) {
+			if (ds instanceof DiskManagerFileInfo) {
+				DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) ds;
+				listSelected.add(new SelectedContent(fileInfo.getDownloadManager(),
+						fileInfo.getIndex()));
+			}
+		}
+		SelectedContent[] sc = listSelected.toArray(new SelectedContent[0]);
+		SelectedContentManager.changeCurrentlySelectedContent(tv.getTableID(),
+				null, tv);
+	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/TranscodeChooser.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/TranscodeChooser.java
index d3380f8..61d04a8 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/TranscodeChooser.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/TranscodeChooser.java
@@ -1,10 +1,12 @@
 /**
  * Created on Mar 1, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/add/DeviceTemplateChooser.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/add/DeviceTemplateChooser.java
index f35c164..efbc047 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/add/DeviceTemplateChooser.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/add/DeviceTemplateChooser.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 16, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/add/ManufacturerChooser.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/add/ManufacturerChooser.java
index 2fb25f6..e7c4308 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/add/ManufacturerChooser.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/add/ManufacturerChooser.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 14, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Completion.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Completion.java
index 0bd5ede..5582c55 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Completion.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Completion.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Name.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Name.java
index 81e556c..5b083b9 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Name.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Name.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Remaining.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Remaining.java
index 9cacf1d..fe03169 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Remaining.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Remaining.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Status.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Status.java
index 2371438..aad0216 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Status.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnOD_Status.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Category.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Category.java
index d2fd2a5..3afdcdd 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Category.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Category.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Completion.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Completion.java
index 76bc0f8..ca9b89f 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Completion.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Completion.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_CopiedToDevice.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_CopiedToDevice.java
index 3e7fbab..d1ac19c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_CopiedToDevice.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_CopiedToDevice.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Device.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Device.java
index ccc1e26..6722504 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Device.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Device.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Duration.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Duration.java
index 03e3452..b772282 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Duration.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Duration.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Name.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Name.java
index 7d79cf7..278b18b 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Name.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Name.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Profile.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Profile.java
index 52d307d..b3ab412 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Profile.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Profile.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Rank.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Rank.java
index 8adfbad..a8e1661 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Rank.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Rank.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Resolution.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Resolution.java
index 0032e24..c15a2d7 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Resolution.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Resolution.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Status.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Status.java
index 689e66d..1edeb7c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Status.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Status.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Tags.java b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Tags.java
index 023571e..b5fe64f 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Tags.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/devices/columns/ColumnTJ_Tags.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 26, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/extlistener/StimulusRPC.java b/azureus3/src/com/aelitis/azureus/ui/swt/extlistener/StimulusRPC.java
index f94f19f..63ae260 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/extlistener/StimulusRPC.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/extlistener/StimulusRPC.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.extlistener;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerInstallWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerInstallWindow.java
index fbf7900..11bcabf 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerInstallWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerInstallWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on Mar 6, 2010 11:01:46 AM
- * Copyright (C) 2010 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.feature;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerUI.java b/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerUI.java
index 2c4031c..6e22db3 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerUI.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerUI.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.feature;
 
 import java.util.*;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerUIListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerUIListener.java
index c60adf3..59d2011 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerUIListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/feature/FeatureManagerUIListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.feature;
 
 import java.util.HashMap;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/mdi/BaseMDI.java b/azureus3/src/com/aelitis/azureus/ui/swt/mdi/BaseMDI.java
index 2390296..3f4f510 100755
--- a/azureus3/src/com/aelitis/azureus/ui/swt/mdi/BaseMDI.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/mdi/BaseMDI.java
@@ -1,27 +1,65 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.mdi;
 
+import java.lang.reflect.Constructor;
 import java.util.*;
 import java.util.regex.Pattern;
 
+import org.eclipse.swt.widgets.Menu;
 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.util.*;
+import org.gudy.azureus2.plugins.PluginInterface;
+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.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionHolder;
+import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionRepository;
+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.PluginsMenuHelper;
 import org.gudy.azureus2.ui.swt.mainwindow.PluginsMenuHelper.IViewInfo;
 import org.gudy.azureus2.ui.swt.mainwindow.PluginsMenuHelper.PluginAddedViewListener;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
 
 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.aelitis.azureus.ui.common.updater.UIUpdatable;
 import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
 import com.aelitis.azureus.ui.mdi.*;
 import com.aelitis.azureus.ui.skin.SkinConstants;
+import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 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.sidebar.SideBarEntrySWT;
 import com.aelitis.azureus.util.ConstantsVuze;
 import com.aelitis.azureus.util.ContentNetworkUtils;
 import com.aelitis.azureus.util.MapUtils;
@@ -36,16 +74,22 @@ public abstract class BaseMDI
 	private Map<String, MdiEntryCreationListener2> mapIdToCreationListener2 = new LightHashMap<String, MdiEntryCreationListener2>();
 
 	// Sync changes to entry maps on mapIdEntry
-	protected Map<String, MdiEntrySWT> mapIdToEntry = new LightHashMap<String, MdiEntrySWT>();
+	protected Map<String, MdiEntrySWT> mapIdToEntry = new LinkedHashMap<String, MdiEntrySWT>(8);
 
 	private List<MdiListener> listeners = new ArrayList<MdiListener>();
 
 	private List<MdiEntryLoadedListener> listLoadListeners = new ArrayList<MdiEntryLoadedListener>();
 
-	private static LinkedHashMap<String, Object> mapAutoOpen = new LinkedHashMap<String, Object>();
+	private List<MdiSWTMenuHackListener> listMenuHackListners;
+
+	private LinkedHashMap<String, Object> mapAutoOpen = new LinkedHashMap<String, Object>();
 
 	private String[] preferredOrder;
 
+	private boolean mapAutoOpenLoaded = false;
+
+	private String closeableConfigFile = "sidebarauto.config";
+
 	public void addListener(MdiListener l) {
 		synchronized (listeners) {
 			if (listeners.contains(l)) {
@@ -121,17 +165,74 @@ public abstract class BaseMDI
 		}
 	}
 
-	public abstract MdiEntry createEntryFromEventListener(String parentID,
-			UISWTViewEventListener l, String id, boolean closeable, Object datasource, String preferedAfterID);
-
-	public abstract MdiEntry createEntryFromView(String parentID, UISWTViewCore iview,
-			String id, Object datasource, boolean closeable, boolean show,
-			boolean expand);
+	// @see com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT#createEntryFromEventListener(java.lang.String, org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener, java.lang.String, boolean, java.lang.Object, java.lang.String)
+	public final MdiEntry createEntryFromEventListener(String parentID,
+			UISWTViewEventListener l, String id, boolean closeable, Object datasource, String preferedAfterID) {
+		return createEntryFromEventListener(parentID, null, l, id, closeable, datasource, preferedAfterID);
+	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT#createEntryFromEventListener(java.lang.String, java.lang.String, org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener, java.lang.String, boolean, java.lang.Object, java.lang.String)
+	 */
+	public abstract MdiEntry createEntryFromEventListener(String parentEntryID,
+			String parentViewID, UISWTViewEventListener l, String id,
+			boolean closeable, Object datasource, String preferredAfterID);
+	
+	// @see com.aelitis.azureus.ui.mdi.MultipleDocumentInterface#createEntryFromSkinRef(java.lang.String, java.lang.String, java.lang.String, java.lang.String, com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo, java.lang.Object, boolean, java.lang.String)
 	public abstract MdiEntry createEntryFromSkinRef(String parentID, String id,
 			String configID, String title, ViewTitleInfo titleInfo, Object params,
 			boolean closeable, String preferedAfterID);
 
+	// @see com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT#createEntryFromEventListener(java.lang.String, java.lang.Class, java.lang.String, boolean, java.lang.Object, java.lang.String)
+	public MdiEntry createEntryFromEventListener(final String parentID,
+			Class<? extends UISWTViewEventListener> cla, String id, boolean closeable,
+			Object data, String preferedAfterID) {
+		final MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
+		if (mdi == null) {
+			return null;
+		}
+
+		if (id == null) {
+			id = cla.getName();
+			int i = id.lastIndexOf('.');
+			if (i > 0) {
+				id = id.substring(i + 1);
+			}
+		}
+
+		MdiEntry entry = mdi.getEntry(id);
+		if (entry != null) {
+			if (data != null) {
+				entry.setDatasource(data);
+			}
+			return entry;
+		}
+		UISWTViewEventListener l = null;
+		if (data != null) {
+			try {
+				Constructor<?> constructor = cla.getConstructor(new Class[] {
+					data.getClass()
+				});
+				l = (UISWTViewEventListener) constructor.newInstance(new Object[] {
+					data
+				});
+			} catch (Exception e) {
+			}
+		}
+
+		try {
+			if (l == null) {
+				l = cla.newInstance();
+			}
+			return mdi.createEntryFromEventListener(parentID, l, id, closeable, data,
+					preferedAfterID);
+		} catch (Exception e) {
+			Debug.out(e);
+		}
+
+		return null;
+	}
+	
 	public MdiEntry getCurrentEntry() {
 		return currentEntry;
 	}
@@ -191,33 +292,58 @@ public abstract class BaseMDI
 			return null;
 		}
 		MdiEntrySWT entry = getEntrySWT(id);
-		if (entry == null) {
-			return null;
+		if (entry instanceof UISWTViewCore) {
+			return (UISWTViewCore) entry;
 		}
-		return entry.getCoreView();
+		return null;
 	}
 
 	public String getUpdateUIName() {
-		if (currentEntry == null || currentEntry.getView() == null) {
+		if (currentEntry == null) {
 			return "MDI";
 		}
-		return currentEntry.getView().getViewID();
+		return currentEntry.getId();
 	}
 
+	// @see com.aelitis.azureus.ui.mdi.MultipleDocumentInterface#registerEntry(java.lang.String, com.aelitis.azureus.ui.mdi.MdiEntryCreationListener2)
 	public void registerEntry(String id, MdiEntryCreationListener2 l) {
+		if (mapIdToCreationListener.containsKey(id)) {
+			System.err.println("Warning: MDIEntry " + id
+					+ " Creation Listener being registered twice. "
+					+ Debug.getCompressedStackTrace());
+		}
 		mapIdToCreationListener2.put(id, l);
 		
 		createIfAutoOpen(id);
 	}
+	
+	// @see com.aelitis.azureus.ui.mdi.MultipleDocumentInterface#deregisterEntry(java.lang.String, com.aelitis.azureus.ui.mdi.MdiEntryCreationListener2)
+	public void deregisterEntry(String id, MdiEntryCreationListener2 l) {
+		MdiEntryCreationListener2 l2 = mapIdToCreationListener2.get(id);
+		if (l == l2) {
+			mapIdToCreationListener2.remove(id);
+		}
+	}
 
 	private boolean createIfAutoOpen(String id) {
 		Object o = mapAutoOpen.get(id);
 		if (o instanceof Map<?, ?>) {
 			Map<?, ?> autoOpenMap = (Map<?, ?>) o;
 
-			return createEntryByCreationListener(id, autoOpenMap.get("datasource"), autoOpenMap) != null;
+			return createEntryByCreationListener(id, autoOpenMap.get("datasource"),
+					autoOpenMap) != null;
 		}
-		return false;
+
+		boolean created = false;
+		String[] autoOpenIDs = mapAutoOpen.keySet().toArray(new String[0]);
+		for (String autoOpenID : autoOpenIDs) {
+			if (Pattern.matches(id, autoOpenID)) {
+				Map<?, ?> autoOpenMap = (Map<?, ?>) mapAutoOpen.get(autoOpenID);
+				created |= createEntryByCreationListener(autoOpenID,
+						autoOpenMap.get("datasource"), autoOpenMap) != null;
+			}
+		}
+		return created;
 	}
 
 	private MdiEntry createEntryByCreationListener(String id, Object ds, Map<?, ?> autoOpenMap) {
@@ -265,18 +391,75 @@ public abstract class BaseMDI
 		return null;
 	}
 
+	// @see com.aelitis.azureus.ui.mdi.MultipleDocumentInterface#registerEntry(java.lang.String, com.aelitis.azureus.ui.mdi.MdiEntryCreationListener)
 	public void registerEntry(String id, MdiEntryCreationListener l) {
+		if (mapIdToCreationListener.containsKey(id)
+				|| mapIdToCreationListener2.containsKey(id)) {
+			System.err.println("Warning: MDIEntry " + id
+					+ " Creation Listener being registered twice. "
+					+ Debug.getCompressedStackTrace());
+		}
 		mapIdToCreationListener.put(id, l);
 		
 		createIfAutoOpen(id);
 	}
 
+	// @see com.aelitis.azureus.ui.mdi.MultipleDocumentInterface#deregisterEntry(java.lang.String, com.aelitis.azureus.ui.mdi.MdiEntryCreationListener)
+	public void deregisterEntry(String id, MdiEntryCreationListener l) {
+		MdiEntryCreationListener l2 = mapIdToCreationListener.get(id);
+		if (l == l2) {
+			mapIdToCreationListener.remove(id);
+		}
+	}
+	
 	public boolean showEntryByID(String id) {
 		return loadEntryByID(id, true);
 	}
 
+	public boolean showEntryByID(String id, Object datasource) {
+		return loadEntryByID(id, true, false, datasource);
+	}
+
 	@Override
 	public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) {
+		UIManager ui_manager = PluginInitializer.getDefaultInterface().getUIManager();
+		ui_manager.addUIListener(new UIManagerListener() {
+			public void UIDetached(UIInstance instance) {
+			}
+			
+			public void UIAttached(UIInstance instance) {
+				if (instance instanceof UISWTInstance) {
+					final AESemaphore wait_sem = new AESemaphore( "SideBar:wait" );
+					
+					Utils.execSWTThread(new AERunnable() {
+						public void runSupport() {
+							try{
+								try {
+									loadCloseables();
+								} catch (Throwable t) {
+									Debug.out(t);
+								}
+	
+								setupPluginViews();
+								
+							}finally{
+								
+								wait_sem.release();
+							}
+						}
+					});
+					
+						// we need to wait for the loadCloseables to complete as there is code in MainMDISetup that runs on the 'UIAttachedComplete'
+						// callback that needs the closables to be loaded (when setting 'start tab') otherwise the order gets broken
+					
+					if ( !wait_sem.reserve(10*1000)){
+						
+						Debug.out( "eh?");
+					}
+				}
+			}
+		});
+
 		return null;
 	}
 
@@ -313,6 +496,13 @@ public abstract class BaseMDI
 		if (id == null) {
 			return false;
 		}
+
+		@SuppressWarnings("deprecation")
+		boolean loadedOnce = wasEntryLoadedOnce(id);
+		if (loadedOnce && onlyLoadOnce) {
+			return false;
+		}
+
 		MdiEntry entry = getEntry(id);
 		if (entry != null) {
 			if (datasource != null) {
@@ -324,12 +514,6 @@ public abstract class BaseMDI
 			return true;
 		}
 
-		@SuppressWarnings("deprecation")
-		boolean loadedOnce = wasEntryLoadedOnce(id);
-		if (loadedOnce && onlyLoadOnce) {
-			return false;
-		}
-
 		MdiEntry mdiEntry = createEntryByCreationListener(id, datasource, null);
 		if (mdiEntry != null) {
 			if (onlyLoadOnce) {
@@ -397,8 +581,11 @@ public abstract class BaseMDI
 	}
 
 	public void loadCloseables() {
+		if (closeableConfigFile == null) {
+			return;
+		}
 		try{
-			Map<?,?> loadedMap = FileUtil.readResilientConfigFile("sidebarauto.config", true);
+			Map<?,?> loadedMap = FileUtil.readResilientConfigFile(closeableConfigFile , true);
 			if (loadedMap.isEmpty()) {
 				return;
 			}
@@ -434,6 +621,10 @@ public abstract class BaseMDI
 		}catch( Throwable e ){
 			
 			Debug.out( e );
+			
+		}finally{
+		
+			mapAutoOpenLoaded  = true;
 		}
 	}
 
@@ -442,6 +633,13 @@ public abstract class BaseMDI
 		"rawtypes"
 	})
 	public void saveCloseables() {
+		if (!mapAutoOpenLoaded) {
+			return;
+		}
+		if (closeableConfigFile == null) {
+			return;
+		}
+
 		try{
 			// update auto open info
 			for (Iterator<String> iter = new ArrayList<String>(mapAutoOpen.keySet()).iterator(); iter.hasNext();) {
@@ -479,7 +677,7 @@ public abstract class BaseMDI
 				//System.out.println( "saved " + id );
 			}
 			
-			FileUtil.writeResilientConfigFile("sidebarauto.config", map );
+			FileUtil.writeResilientConfigFile(closeableConfigFile, map );
 			
 		}catch( Throwable e ){
 			
@@ -509,13 +707,12 @@ public abstract class BaseMDI
 			String parentID = MapUtils.getMapString(autoOpenInfo, "parentID", SIDEBAR_HEADER_PLUGINS);
 
 			if (viewInfo != null) {
-				if (viewInfo.view != null) {
-					entry = createEntryFromView(parentID, viewInfo.view, id, datasource,
-							true, false, true);
-				} else if (viewInfo.event_listener != null) {
+				if (viewInfo.event_listener != null) {
 					entry = createEntryFromEventListener(parentID,
 							viewInfo.event_listener, id, true, datasource,null);
-  				entry.setTitle(title);
+					if (entry != null) {
+						entry.setTitle(title);
+					}
 				}
 			}
 
@@ -558,7 +755,7 @@ public abstract class BaseMDI
 					}
 				}
 			}
-
+			
 			return entry != null;
 		} catch (Throwable e) {
 			Debug.out(e);
@@ -583,8 +780,9 @@ public abstract class BaseMDI
 			MdiEntrySWT[] entriesSWT = getEntriesSWT();
 			for (MdiEntrySWT entry : entriesSWT) {
 				if (id.equals(entry.getParentID())) {
-					mapIdToEntry.remove(entry);
-					removeChildrenOf(entry.getId());
+					String kid_id = entry.getId();
+					mapIdToEntry.remove(kid_id);
+					removeChildrenOf(kid_id);
 				}
 			}
 		}
@@ -626,4 +824,143 @@ public abstract class BaseMDI
 	public String[] getPreferredOrder() {
 		return preferredOrder == null ? new String[0] : preferredOrder;
 	}
+	
+	public int getEntriesCount() {
+		return mapIdToEntry.size();
+	}
+
+	public void setCloseableConfigFile(String closeableConfigFile) {
+		this.closeableConfigFile = closeableConfigFile;
+	}
+	
+	public void addListener(MdiSWTMenuHackListener l) {
+		synchronized (this) {
+			if (listMenuHackListners == null) {
+				listMenuHackListners = new ArrayList<MdiSWTMenuHackListener>(1);
+			}
+			if (!listMenuHackListners.contains(l)) {
+				listMenuHackListners.add(l);
+			}
+		}
+	}
+
+	public void removeListener(MdiSWTMenuHackListener l) {
+		synchronized (this) {
+			if (listMenuHackListners == null) {
+				listMenuHackListners = new ArrayList<MdiSWTMenuHackListener>(1);
+			}
+			listMenuHackListners.remove(l);
+		}
+	}
+
+	public MdiSWTMenuHackListener[] getMenuHackListeners() {
+		synchronized (this) {
+			if (listMenuHackListners == null) {
+				return new MdiSWTMenuHackListener[0];
+			}
+			return listMenuHackListners.toArray(new MdiSWTMenuHackListener[0]);
+		}
+	}
+
+
+	public void fillMenu(Menu menu, final MdiEntry entry, String menuID) {
+		org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items;
+		
+		menu_items = MenuItemManager.getInstance().getAllAsArray(menuID);
+
+		MenuBuildUtils.addPluginMenuItems(menu_items, menu, false, true,
+				new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Object[] {
+					entry
+				}));
+
+		if (entry != null) {
+
+			menu_items = MenuItemManager.getInstance().getAllAsArray(
+					"sidebar." + entry.getId());
+
+			if (menu_items.length == 0) {
+
+				if (entry instanceof UISWTView) {
+
+					PluginInterface pi = ((UISWTView) entry).getPluginInterface();
+
+					if (pi != null) {
+
+						final List<String> relevant_sections = new ArrayList<String>();
+
+						List<ConfigSectionHolder> sections = ConfigSectionRepository.getInstance().getHolderList();
+
+						for (ConfigSectionHolder cs : sections) {
+
+							if (pi == cs.getPluginInterface()) {
+
+								relevant_sections.add(cs.configSectionGetName());
+							}
+						}
+
+						if (relevant_sections.size() > 0) {
+
+							MenuItem mi = pi.getUIManager().getMenuManager().addMenuItem(
+									"sidebar." + entry.getId(),
+									"MainWindow.menu.view.configuration");
+
+							mi.addListener(new MenuItemListener() {
+								public void selected(MenuItem menu, Object target) {
+									UIFunctions uif = UIFunctionsManager.getUIFunctions();
+
+									if (uif != null) {
+
+										for (String s : relevant_sections) {
+
+											uif.getMDI().showEntryByID(
+													MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG, s);
+										}
+									}
+								}
+							});
+
+							menu_items = MenuItemManager.getInstance().getAllAsArray(
+									"sidebar." + entry.getId());
+						}
+					}
+				}
+			}
+
+			MenuBuildUtils.addPluginMenuItems(menu_items, menu, false, true,
+					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Object[] {
+						entry
+					}));
+
+			MdiSWTMenuHackListener[] menuHackListeners = getMenuHackListeners();
+			for (MdiSWTMenuHackListener l : menuHackListeners) {
+				try {
+					l.menuWillBeShown(entry, menu);
+				} catch (Exception e) {
+					Debug.out(e);
+				}
+			}
+			if (currentEntry instanceof SideBarEntrySWT) {
+				menuHackListeners = ((SideBarEntrySWT) entry).getMenuHackListeners();
+				for (MdiSWTMenuHackListener l : menuHackListeners) {
+					try {
+						l.menuWillBeShown(entry, menu);
+					} catch (Exception e) {
+						Debug.out(e);
+					}
+				}
+			}
+		}
+			
+		menu_items = MenuItemManager.getInstance().getAllAsArray(menuID + "._end_");
+
+		if ( menu_items.length > 0 ){
+			
+			MenuBuildUtils.addPluginMenuItems(menu_items, menu, false, true,
+					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Object[] {
+						entry
+					}));
+		}
+	}
+
+
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/mdi/BaseMdiEntry.java b/azureus3/src/com/aelitis/azureus/ui/swt/mdi/BaseMdiEntry.java
index 161b0cf..950426c 100755
--- a/azureus3/src/com/aelitis/azureus/ui/swt/mdi/BaseMdiEntry.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/mdi/BaseMdiEntry.java
@@ -1,29 +1,41 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.mdi;
 
 import java.util.*;
+import java.util.List;
 
 import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-
+import org.eclipse.swt.widgets.*;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults;
 import org.gudy.azureus2.core3.config.impl.ConfigurationParameterNotFoundException;
 import org.gudy.azureus2.core3.download.DownloadManager;
-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.core3.util.LightHashMap;
-import org.gudy.azureus2.plugins.ui.UIPluginView;
-import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
+import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarEnablerBase;
 import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
 import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.plugins.PluginUISWTSkinObject;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
 import org.gudy.azureus2.ui.swt.pluginsimpl.*;
 
-import com.aelitis.azureus.ui.common.ToolBarEnabler;
 import com.aelitis.azureus.ui.common.viewtitleinfo.*;
 import com.aelitis.azureus.ui.mdi.*;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
@@ -35,20 +47,13 @@ import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectContainer;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectListener;
 
 public abstract class BaseMdiEntry
-	implements MdiEntrySWT, ViewTitleInfoListener
+	extends UISWTViewImpl
+	implements MdiEntrySWT, ViewTitleInfoListener, AEDiagnosticsEvidenceGenerator
 {
 	protected final MultipleDocumentInterface mdi;
 
-	protected final String id;
-
 	protected String logID;
 
-	protected Object datasource;
-
-	protected Class<? extends UIPluginView> viewClass;
-
-	protected UISWTViewCore view;
-
 	private String skinRef;
 
 	private List<MdiCloseListener> listCloseListeners = null;
@@ -63,19 +68,12 @@ public abstract class BaseMdiEntry
 
 	private List<MdiEntryDatasourceListener> listDatasourceListeners = null;
 
+	private List<MdiSWTMenuHackListener> listMenuHackListners;
+	
 	protected ViewTitleInfo viewTitleInfo;
 
-	private SWTSkinObject skinObject;
-
-	private String title;
-
-	private String titleID;
-
-	private UISWTViewEventListener eventListener;
-
-	private String parentID;
-
-	private boolean pullTitleFromView;
+	/** Parent MDIEntry.  Doesn't mean that this view is embedded inside the parentID */
+	private String parentEntryID;
 
 	private boolean closeable;
 
@@ -93,23 +91,21 @@ public abstract class BaseMdiEntry
 
 	private SWTSkinObject soMaster;
 
-	private Set<UIToolBarEnablerBase> setToolBarEnablers = new HashSet<UIToolBarEnablerBase>(1);
-
 	private String preferredAfterID;
 
-	private Map<Object,Object>	user_data;
-	
-	@SuppressWarnings("unused")
+	private boolean hasBeenOpened;
+
 	private BaseMdiEntry() {
+		super(null, null, false);
 		mdi = null;
-		id = null;
 		setDefaultExpanded(false);
+		AEDiagnostics.addEvidenceGenerator(this);
 	}
 
-	public BaseMdiEntry(MultipleDocumentInterface mdi, String id) {
+	public BaseMdiEntry(MultipleDocumentInterface mdi, String id, String parentViewID) {
+		super(id, parentViewID, true);
 		this.mdi = mdi;
-		this.id = id;
-		this.pullTitleFromView = true;
+		AEDiagnostics.addEvidenceGenerator(this);
 
 		if (id == null) {
 			logID = "null";
@@ -124,10 +120,16 @@ public abstract class BaseMdiEntry
 		setDefaultExpanded(false);
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getId()
+	 */
 	public String getId() {
 		return id;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#addVitalityImage(java.lang.String)
+	 */
 	public MdiEntryVitalityImage addVitalityImage(String imageID) {
 		return null;
 	}
@@ -136,15 +138,15 @@ public abstract class BaseMdiEntry
 	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#close()
 	 */
 	public boolean close(boolean forceClose) {
-		if (!forceClose && view instanceof UISWTViewImpl) {
-			if (!((UISWTViewImpl) view).requestClose()) {
+		if (!forceClose) {
+			if (!requestClose()) {
 				return false;
 			}
 		}
 
 		setCloseable(closeable);
 		disposed = true;
-		ViewTitleInfoManager.removeListener(this);
+		ViewTitleInfoManager.removeListener(this); 
 
 		return true;
 	}
@@ -153,6 +155,9 @@ public abstract class BaseMdiEntry
 		return datasource;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getExportableDatasource()
+	 */
 	public String getExportableDatasource() {
 		if (viewTitleInfo != null) {
 			Object ds = viewTitleInfo.getTitleInfoProperty(ViewTitleInfo2.TITLE_EXPORTABLE_DATASOURCE);
@@ -163,55 +168,37 @@ public abstract class BaseMdiEntry
 		return null;
 	}
 	
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getDatasource()
+	 */
 	public Object getDatasource() {
 		return PluginCoreUtils.convert(datasource, false);
 	}
 
-	public void setDatasource(Object datasource) {
-		this.datasource = datasource;
-
-		triggerDatasourceListeners();
-
-		if (view != null) {
-			view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, datasource);
-		}
-
-		if (isAdded()) {
-			if (skinObject != null) {
-				skinObject.triggerListeners(
-						SWTSkinObjectListener.EVENT_DATASOURCE_CHANGED, datasource);
-			}
-		}
-	}
-
-	public UIPluginView getView() {
-		return view;
-	}
-
-	public UISWTViewCore getCoreView() {
-		return view;
-	}
-
-	public Class<? extends UIPluginView> getViewClass() {
-		return viewClass;
-	}
-
-	public void setViewClass(Class<? extends UIPluginView> viewClass) {
-		this.viewClass = viewClass;
-	}
-
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getLogID()
+	 */
 	public String getLogID() {
 		return logID;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getMDI()
+	 */
 	public MultipleDocumentInterface getMDI() {
 		return mdi;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getParentID()
+	 */
 	public String getParentID() {
-		return parentID;
+		return parentEntryID;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#setParentID(java.lang.String)
+	 */
 	public void setParentID(String id) {
 		if (id == null || "Tools".equals(id)) {
 			if (getId().equals(MultipleDocumentInterface.SIDEBAR_HEADER_DVD)
@@ -225,15 +212,23 @@ public abstract class BaseMdiEntry
 			Debug.out("Setting Parent to same ID as child! " + id);
 			return;
 		}
-		parentID = id;
+		parentEntryID = id;
 		// ensure parent gets created if it isn't there already
-		mdi.loadEntryByID(parentID, false);
+		if (mdi != null) {
+			mdi.loadEntryByID(parentEntryID, false);
+		}
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getVitalityImages()
+	 */
 	public MdiEntryVitalityImage[] getVitalityImages() {
 		return null;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#isCloseable()
+	 */
 	public boolean isCloseable() {
 		return closeable;
 	}
@@ -242,6 +237,9 @@ public abstract class BaseMdiEntry
 		return collapseDisabled;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#setCollapseDisabled(boolean)
+	 */
 	public void setCollapseDisabled(boolean collapseDisabled) {
 		this.collapseDisabled = collapseDisabled;
 		setExpanded(true);
@@ -280,10 +278,14 @@ public abstract class BaseMdiEntry
 			}
 		}
 
-		MdiEntry parentEntry = mdi.getEntry(parentID);
-		if (parentEntry instanceof BaseMdiEntry) {
-			((BaseMdiEntry) parentEntry).triggerChildCloseListeners(this, user);
+		if (parentEntryID != null && mdi != null) {
+  		MdiEntry parentEntry = mdi.getEntry(parentEntryID);
+  		if (parentEntry instanceof BaseMdiEntry) {
+  			((BaseMdiEntry) parentEntry).triggerChildCloseListeners(this, user);
+  		}
 		}
+
+		triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
 	}
 
 	public void addListener(MdiChildCloseListener l) {
@@ -362,7 +364,7 @@ public abstract class BaseMdiEntry
 			listOpenListeners.add(l);
 		}
 
-		if (view != null) {
+		if (hasBeenOpened) {
 			l.mdiEntryOpen(this);
 		}
 	}
@@ -377,6 +379,7 @@ public abstract class BaseMdiEntry
 
 	public void triggerOpenListeners() {
 		Object[] list;
+		hasBeenOpened = true;
 		synchronized (this) {
 			if (listOpenListeners == null) {
 				return;
@@ -481,6 +484,9 @@ public abstract class BaseMdiEntry
 		return handled;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#setLogID(java.lang.String)
+	 */
 	public void setLogID(String logID) {
 		if (logID == null || logID.equals("" + this.logID)) {
 			return;
@@ -516,103 +522,55 @@ public abstract class BaseMdiEntry
 				}
 			}
 
-			String newTitle = (String) viewTitleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_TEXT);
-			if (newTitle != null) {
-				setPullTitleFromView(false);
-				setTitle(newTitle);
-			}
-
 			String imageID = (String) viewTitleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_IMAGEID);
 			if (imageID != null) {
 				setImageLeftID(imageID.length() == 0 ? null : imageID);
 			}
 
 			ViewTitleInfoManager.addListener(this);
+			
+			if (getEventListener() == null && (viewTitleInfo instanceof UISWTViewEventListener)) {
+				try {
+					setEventListener((UISWTViewEventListener) viewTitleInfo, true);
+				} catch (UISWTViewEventCancelledException e) {
+				}
+			}
 		}
+		redraw();
 	}
 
-	/**
-	 * @deprecated For azburn
-	 */
-	// @see com.aelitis.azureus.ui.mdi.MdiEntry#addToolbarEnabler(com.aelitis.azureus.ui.common.ToolBarEnabler)
-	public void addToolbarEnabler(ToolBarEnabler enabler) {
-		addToolbarEnabler((UIToolBarEnablerBase) enabler);
-	}
-
-	public void addToolbarEnabler(UIToolBarEnablerBase enabler) {
-		setToolBarEnablers.add(enabler);
-		setToolbarVisibility(setToolBarEnablers.size() > 0);
-	}
-
-	protected void setToolbarVisibility(boolean visible) {
-	}
 
-	public void removeToolbarEnabler(UIToolBarEnablerBase enabler) {
-		setToolBarEnablers.remove(enabler);
-		setToolbarVisibility(setToolBarEnablers.size() > 0);
-	}
-
-	public UIToolBarEnablerBase[] getToolbarEnablers() {
-		if (view != null) {
-			UIPluginViewToolBarListener listener = view.getToolBarListener();
-			if (listener != null) {
-				return new UIToolBarEnablerBase[] { listener };
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl2#setPluginSkinObject(org.gudy.azureus2.ui.swt.plugins.PluginUISWTSkinObject, org.eclipse.swt.widgets.Composite)
+	 */
+	@Override
+	public void setPluginSkinObject(PluginUISWTSkinObject skinObject) {
+		super.setPluginSkinObject(skinObject);
+		Object initialDataSource = (datasource == null
+				|| ((datasource instanceof Object[])
+						&& ((Object[]) datasource).length == 0)) ? getInitialDataSource()
+								: datasource;
+		if (initialDataSource != null) {
+			if (skinObject instanceof SWTSkinObject) {
+				((SWTSkinObject) skinObject).triggerListeners(
+						SWTSkinObjectListener.EVENT_DATASOURCE_CHANGED, initialDataSource);
 			}
+			triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, initialDataSource);
 		}
-		return setToolBarEnablers.toArray(new UIToolBarEnablerBase[0]);
 	}
 
-	public void setCoreView(UISWTViewCore view) {
-		if (this.view != null && view == null) {
-  		this.view.triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
-		}
-		this.view = view;
-		if (view == null) {
-			return;
-		}
-
-		UISWTViewEventListener eventListener = view.getEventListener();
-		if (view instanceof ViewTitleInfo) {
-			setViewTitleInfo((ViewTitleInfo) view);
-		} else if (eventListener instanceof ViewTitleInfo) {
-			setViewTitleInfo((ViewTitleInfo) eventListener);
-		}
-
-		if (view instanceof UIToolBarEnablerBase) {
-			addToolbarEnabler((UIToolBarEnablerBase) view);
-		} else if (eventListener instanceof UIToolBarEnablerBase) {
-			addToolbarEnabler((UIToolBarEnablerBase) eventListener);
-		}
-
-		if (datasource != null) {
-			view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, datasource);
-		}
+	public void setSkinObjectMaster(SWTSkinObject soMaster) {
+		this.soMaster = soMaster;
 	}
 
+	
 	public SWTSkinObject getSkinObject() {
-		return skinObject;
-	}
-
-	public void setSkinObject(SWTSkinObject skinObject, SWTSkinObject soMaster) {
-		this.skinObject = skinObject;
-		this.soMaster = soMaster;
-		if (datasource != null) {
-			if (skinObject != null) {
-				skinObject.triggerListeners(
-						SWTSkinObjectListener.EVENT_DATASOURCE_CHANGED, datasource);
-			}
-			if (view != null) {
-				view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, datasource);
-			}
-		}
-		if (skinObject != null) {
-			setToolbarVisibility(setToolBarEnablers.size() > 0);
-		}
+		return (SWTSkinObject) getPluginSkinObject();
 	}
-
+	
 	public SWTSkinObject getSkinObjectMaster() {
 		if (soMaster == null) {
-			return skinObject;
+			return getSkinObject();
 		}
 		return soMaster;
 	}
@@ -628,52 +586,50 @@ public abstract class BaseMdiEntry
 		return skinRef;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getTitle()
+	 */
 	public String getTitle() {
-		if (title != null && !isPullTitleFromView()) {
-			return title;
-		}
-		if (view != null) {
-			return view.getFullTitle();
-		}
-		return title;
-	}
-
-	public void setTitle(String title) {
-		if (title == null) {
-			return;
-		}
-		if (title.startsWith("{") && title.endsWith("}") && title.length() > 2) {
-			setTitleID(title.substring(1, title.length() - 1));
-			return;
-		}
-		if (title.equals(this.title)) {
-			return;
+		if (viewTitleInfo != null) {
+			String viewTitle = (String) viewTitleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_TEXT);
+			if (viewTitle != null && viewTitle.length() > 0) {
+				return viewTitle;
+			}
 		}
-		this.title = title;
-		this.titleID = null;
-		redraw();
+		return super.getFullTitle();
 	}
-
-	public void setTitleID(String titleID) {
-		String title = MessageText.getString(titleID);
-		setTitle(title.startsWith("{") ? title.substring(1) : title);
-		this.titleID = titleID;
+	
+	public void updateLanguage() {
+		triggerEvent(UISWTViewEvent.TYPE_LANGUAGEUPDATE, null);
 	}
+	
+	
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl2#triggerEvent(int, java.lang.Object)
+	 */
+	@Override
+	public void triggerEvent(int eventType, Object data) {
+		super.triggerEvent(eventType, data);
+		
+		if (eventType == UISWTViewEvent.TYPE_LANGUAGEUPDATE) {
+			if (getTitleID() != null) {
+				setTitleID(getTitleID());
+			} else {
+				if (viewTitleInfo != null) {
+					viewTitleInfoRefresh(viewTitleInfo);
+				}
+				updateUI();
+			}
 
-	public void updateLanguage() {
-		if (view != null) {
-			view.triggerEvent(UISWTViewEvent.TYPE_LANGUAGEUPDATE, null);
-		}
-		if (titleID != null) {
-			setTitleID(titleID);
-		} else {
-			if (viewTitleInfo != null) {
-				viewTitleInfoRefresh(viewTitleInfo);
+			SWTSkinObject skinObjectMaster = getSkinObjectMaster();
+			if (skinObjectMaster != null) {
+				skinObjectMaster.triggerListeners(SWTSkinObjectListener.EVENT_LANGUAGE_CHANGE);
 			}
-			updateUI();
 		}
+
 	}
 
+
 	public void show() {
 		if (skinObject == null) {
 			return;
@@ -686,6 +642,8 @@ public abstract class BaseMdiEntry
 			//uif.refreshIconBar(); // needed?
 			uif.refreshTorrentMenu();
 		}
+		
+		
 
 		SWTSkinObject skinObject = getSkinObjectMaster();
 		skinObject.setVisible(true);
@@ -702,30 +660,37 @@ public abstract class BaseMdiEntry
 			// This causes double show because createSkinObject already calls show
 			//container.triggerListeners(SWTSkinObjectListener.EVENT_SHOW);
 		}
-		if (view != null) {
-			Composite c = view.getComposite();
-			if (c != null && !c.isDisposed()) {
-				c.setData("BaseMDIEntry", this);
-				c.setVisible(true);
-				c.getParent().layout();
-			}
 
-			try {
-				view.triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
-			} catch (Exception e) {
-				Debug.out(e);
-			}
+		Composite c = getComposite();
+		if (c != null && !c.isDisposed()) {
+			c.setData("BaseMDIEntry", this);
+			c.setVisible(true);
+			c.getParent().layout();
 		}
+
+		try {
+			triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
+		} catch (Exception e) {
+			Debug.out(e);
+		}
+		setToolbarVisibility(hasToolbarEnableers());
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#hide()
+	 */
 	public void hide() {
 		Utils.execSWTThread(new AERunnable() {
 			public void runSupport() {
 				swt_hide();
 			}
 		});
+		setToolbarVisibility(false);
 	}
 	
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#requestAttention()
+	 */
 	public void
 	requestAttention()
 	{
@@ -742,82 +707,34 @@ public abstract class BaseMdiEntry
 				oldComposite.getShell().update();
 			}
 		}
-		if (view != null) {
-			Composite oldComposite = view.getComposite();
-			if (oldComposite != null && !oldComposite.isDisposed()) {
 
-				oldComposite.setVisible(false);
-				oldComposite.getShell().update();
-			}
+		Composite oldComposite = getComposite();
+		if (oldComposite != null && !oldComposite.isDisposed()) {
 
-			try {
-				view.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
-			} catch (Exception e) {
-				Debug.out(e);
-			}
+			oldComposite.setVisible(false);
+			oldComposite.getShell().update();
 		}
-	}
 
-	public UISWTViewEventListener getEventListener() {
-		return eventListener;
-	}
-
-	public void setEventListener(UISWTViewEventListener _eventListener) {
-		this.eventListener = _eventListener;
-
-		if (view != null) {
-			return;
-		}
 		try {
-			setCoreView(new UISWTViewImpl(parentID, id, _eventListener,
-					datasource));
+			triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
 		} catch (Exception e) {
 			Debug.out(e);
 		}
-
-		if (_eventListener instanceof UISWTViewEventListenerHolder) {
-			UISWTViewEventListenerHolder h = (UISWTViewEventListenerHolder) _eventListener;
-			UISWTViewEventListener delegatedEventListener = h.getDelegatedEventListener(view);
-			if (delegatedEventListener != null) {
-				this.eventListener = delegatedEventListener;
-			}
-		}
-
-		if (eventListener instanceof UIToolBarEnablerBase) {
-			addToolbarEnabler((UIToolBarEnablerBase) eventListener);
-		}
-		if ((eventListener instanceof ViewTitleInfo) && viewTitleInfo == null) {
-			setViewTitleInfo((ViewTitleInfo) eventListener);
-		}
-
-
-		if (eventListener instanceof BasicPluginViewImpl) {
-			if ("image.sidebar.plugin".equals(getImageLeftID())) {
-				setImageLeftID("image.sidebar.logview");
-			}
-		}
-	}
-
-	public boolean isPullTitleFromView() {
-		return pullTitleFromView;
-	}
-
-	public void setPullTitleFromView(boolean pullTitleFromView) {
-		this.pullTitleFromView = pullTitleFromView;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#updateUI()
+	 */
 	public void updateUI() {
-		if (view == null) {
+		if (getEventListener() == null) {
 			return;
 		}
 		Utils.execSWTThread(new AERunnable() {
 			public void runSupport() {
-				if (view != null && !isDisposed()) {
-					view.triggerEvent(UISWTViewEvent.TYPE_REFRESH, null);
-				}
-				if (isPullTitleFromView() && isAdded()) {
-					setTitle(view.getFullTitle());
+				if (!isDisposed()) {
+					triggerEvent(UISWTViewEvent.TYPE_REFRESH, null);
 				}
+				// XXX What about title changes?
 			}
 		});
 	}
@@ -826,16 +743,14 @@ public abstract class BaseMdiEntry
 		return disposed;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getAutoOpenInfo()
+	 */
 	public Map<String, Object> getAutoOpenInfo() {
 		Map<String, Object> autoOpenInfo = new LightHashMap<String, Object>();
 		if (getParentID() != null) {
 			autoOpenInfo.put("parentID", getParentID());
 		}
-		UISWTViewEventListener eventListener = getEventListener();
-		if (eventListener != null) {
-			autoOpenInfo.put("eventListenerClass",
-					eventListener.getClass().getName());
-		}
 		autoOpenInfo.put("title", getTitle());
 		Object datasource = getDatasourceCore();
 		if (datasource instanceof DownloadManager) {
@@ -866,12 +781,13 @@ public abstract class BaseMdiEntry
 	
 	public void setCloseable(boolean closeable) {
 		this.closeable = closeable;
-		if (closeable) {
 
-			mdi.informAutoOpenSet(this, getAutoOpenInfo());
-			COConfigurationManager.setParameter("SideBar.AutoOpen." + id, true);
-		} else {
-			COConfigurationManager.removeParameter("SideBar.AutoOpen." + id);
+		if (mdi != null) {
+  		if (closeable) {
+  			mdi.informAutoOpenSet(this, getAutoOpenInfo());
+  		} else {
+  			mdi.removeEntryAutoOpen(id);
+  		}
 		}
 	}
 
@@ -885,8 +801,11 @@ public abstract class BaseMdiEntry
 		return isExpanded == null
 				? COConfigurationManager.getBooleanParameter("SideBar.Expanded." + id)
 				: isExpanded;
-	}
+			}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#setExpanded(boolean)
+	 */
 	public void setExpanded(boolean expanded) {
 		isExpanded = expanded;
 		boolean defExpanded = true;
@@ -902,6 +821,9 @@ public abstract class BaseMdiEntry
 		}
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#isAdded()
+	 */
 	public boolean isAdded() {
 		return added;
 	}
@@ -909,6 +831,13 @@ public abstract class BaseMdiEntry
 	public void setDisposed(boolean b) {
 		disposed = b;
 		added = !b;
+		
+		if (added) {
+			if (getSkinObject() != null) {
+				getSkinObject().triggerListeners(
+						SWTSkinObjectListener.EVENT_DATASOURCE_CHANGED, datasource);
+			}
+		}
 	}
 
 	public void setImageLeftID(String id) {
@@ -917,6 +846,9 @@ public abstract class BaseMdiEntry
 		redraw();
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getImageLeftID()
+	 */
 	public String getImageLeftID() {
 		return imageLeftID;
 	}
@@ -957,6 +889,9 @@ public abstract class BaseMdiEntry
 		}
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoListener#viewTitleInfoRefresh(com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo)
+	 */
 	public void viewTitleInfoRefresh(ViewTitleInfo titleInfoToRefresh) {
 		if (titleInfoToRefresh == null || this.viewTitleInfo != titleInfoToRefresh) {
 			return;
@@ -965,12 +900,6 @@ public abstract class BaseMdiEntry
 			return;
 		}
 
-		String newText = (String) viewTitleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_TEXT);
-		if (newText != null) {
-			setPullTitleFromView(false);
-			setTitle(newText);
-		}
-
 		String imageID = (String) viewTitleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_IMAGEID);
 		if (imageID != null) {
 			setImageLeftID(imageID.length() == 0 ? null : imageID);
@@ -987,42 +916,179 @@ public abstract class BaseMdiEntry
 	public void build() {
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#setPreferredAfterID(java.lang.String)
+	 */
 	public void setPreferredAfterID(String preferredAfterID) {
 		this.preferredAfterID = preferredAfterID;
 	}
 
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#getPreferredAfterID()
+	 */
 	public String getPreferredAfterID() {
 		return preferredAfterID;
 	}
 	
-	public void
-	setUserData(
-		Object		key,
-		Object		data )
-	{
-		synchronized( this ){
-			
-			if ( user_data == null ){
-				
-				user_data = new LightHashMap<Object,Object>();
+	public boolean requestClose() {
+		return triggerEventRaw(UISWTViewEvent.TYPE_CLOSE, null);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.core3.util.AEDiagnosticsEvidenceGenerator#generate(org.gudy.azureus2.core3.util.IndentWriter)
+	 */
+	public void generate(IndentWriter writer) {
+		writer.println("View: " + id + ": " + getTitle());
+
+		try {
+			writer.indent();
+
+			writer.println("Parent: " + getParentID());
+			//writer.println("Created: " + created);
+			writer.println("Added: " + added);
+			writer.println("closeable: " + closeable);
+			writer.println("Disposed: " + disposed);
+			writer.println("hasBeenOpened: " + hasBeenOpened);
+			//writer.println("hasFocus: " + hasFocus);
+			//writer.println("haveSentInitialize: " + haveSentInitialize);
+			writer.println("control type: " + getControlType());
+			writer.println("hasEventListener: " + (getEventListener() != null));
+			writer.println("hasViewTitleInfo: " + (viewTitleInfo != null));
+			writer.println("skinRef: " + skinRef);
+		} catch (Exception e) {
+
+		} finally {
+
+			writer.exdent();
+		}
+
+		if (getEventListener() instanceof AEDiagnosticsEvidenceGenerator) {
+
+			try {
+				writer.indent();
+
+				((AEDiagnosticsEvidenceGenerator) getEventListener()).generate(writer);
+			} catch (Exception e) {
+
+			} finally {
+
+				writer.exdent();
 			}
-			
-			user_data.put( key, data );
 		}
 	}
 	
-	public Object
-	getUserData(
-		Object 		key )
-	{
-		synchronized( this ){
-			
-			if ( user_data == null ){
-				
-				return( null );
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.UISWTViewImpl2#closeView()
+	 */
+	@Override
+	public void closeView() {
+		// This essentially calls mdi.closeEntry(id)
+		//UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
+		//if (uiFunctions != null) {
+		//	uiFunctions.closePluginView(this);
+		//}
+		if (mdi != null) {
+			mdi.closeEntry(id);
+		}
+
+		super.closeView();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl2#setEventListener(org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener, boolean)
+	 */
+	@Override
+	public void setEventListener(UISWTViewEventListener _eventListener,
+			boolean doCreate)
+	throws UISWTViewEventCancelledException {
+		UISWTViewEventListener eventListener = getEventListener();
+		if (eventListener instanceof UIToolBarEnablerBase) {
+			removeToolbarEnabler((UIToolBarEnablerBase) eventListener);
+		}
+		if ((eventListener instanceof ViewTitleInfo) && viewTitleInfo == eventListener) {
+			setViewTitleInfo(null);
+		}
+		
+		if (_eventListener instanceof UISWTViewEventListenerHolder) {
+			UISWTViewEventListenerHolder h = (UISWTViewEventListenerHolder) _eventListener;
+			UISWTViewEventListener delegatedEventListener = h.getDelegatedEventListener(this);
+			if (delegatedEventListener != null) {
+				_eventListener = delegatedEventListener;
 			}
+		}
+
+		if (_eventListener instanceof UIToolBarEnablerBase) {
+			addToolbarEnabler((UIToolBarEnablerBase) _eventListener);
+		}
+		if ((_eventListener instanceof ViewTitleInfo) && viewTitleInfo == null) {
+			setViewTitleInfo((ViewTitleInfo) _eventListener);
+		}
+	
+	
+		if (_eventListener instanceof BasicPluginViewImpl) {
+			String existing_id = getImageLeftID();
 			
-			return( user_data.get( key ));
+			if (existing_id==null||"image.sidebar.plugin".equals(existing_id)) {
+				setImageLeftID("image.sidebar.logview");
+			}
+		}
+	
+
+		super.setEventListener(_eventListener, doCreate);
+	}
+	
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.UISWTViewImpl2#setDatasource(java.lang.Object)
+	 */
+	@Override
+	public void setDatasource(Object datasource) {
+		super.setDatasource(datasource);
+
+		triggerDatasourceListeners();
+		if (isAdded()) {
+			if (getSkinObject() != null) {
+				getSkinObject().triggerListeners(
+						SWTSkinObjectListener.EVENT_DATASOURCE_CHANGED, datasource);
+			}
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.UISWTViewImpl2#setTitle(java.lang.String)
+	 */
+	@Override
+	public void setTitle(String title) {
+		super.setTitle(title);
+		redraw();
+	}
+
+	public void addListener(MdiSWTMenuHackListener l) {
+		synchronized (this) {
+			if (listMenuHackListners == null) {
+				listMenuHackListners = new ArrayList<MdiSWTMenuHackListener>(1);
+			}
+			if (!listMenuHackListners.contains(l)) {
+				listMenuHackListners.add(l);
+			}
+		}
+	}
+
+	public void removeListener(MdiSWTMenuHackListener l) {
+		synchronized (this) {
+			if (listMenuHackListners == null) {
+				listMenuHackListners = new ArrayList<MdiSWTMenuHackListener>(1);
+			}
+			listMenuHackListners.remove(l);
 		}
 	}
+	
+	public MdiSWTMenuHackListener[] getMenuHackListeners() {
+		synchronized (this) {
+			if (listMenuHackListners == null) {
+				return new MdiSWTMenuHackListener[0];
+			}
+			return listMenuHackListners.toArray(new MdiSWTMenuHackListener[0]);
+		}
+	}
+
 }
\ No newline at end of file
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/mdi/TabbedEntry.java b/azureus3/src/com/aelitis/azureus/ui/swt/mdi/TabbedEntry.java
index 30717f0..0a37f6f 100755
--- a/azureus3/src/com/aelitis/azureus/ui/swt/mdi/TabbedEntry.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/mdi/TabbedEntry.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.mdi;
 
 import org.eclipse.swt.SWT;
@@ -5,17 +23,16 @@ import org.eclipse.swt.custom.CTabItem;
 import org.eclipse.swt.events.DisposeEvent;
 import org.eclipse.swt.events.DisposeListener;
 import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Image;
 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.util.AERunnable;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
-import org.gudy.azureus2.ui.swt.plugins.UISWTView;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewEventCancelledException;
 
 import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
 import com.aelitis.azureus.ui.mdi.MdiEntryVitalityImage;
@@ -23,6 +40,11 @@ import com.aelitis.azureus.ui.swt.skin.SWTSkin;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectContainer;
 
+/**
+ * MDI Entry that is a {@link CTabItem} and belongs wo {@link TabbedMDI}
+ * <p>
+ * TODO: VitalityImages
+ */
 public class TabbedEntry
 	extends BaseMdiEntry implements DisposeListener
 {
@@ -36,8 +58,8 @@ public class TabbedEntry
 
 	private static long uniqueNumber = 0;
 
-	public TabbedEntry(TabbedMDI mdi, SWTSkin skin, String id) {
-		super(mdi, id);
+	public TabbedEntry(TabbedMDI mdi, SWTSkin skin, String id, String parentViewID) {
+		super(mdi, id, parentViewID);
 		this.skin = skin;
 	}
 
@@ -62,7 +84,7 @@ public class TabbedEntry
 		buildonSWTItemSet = false;
 
 		Control control = swtItem.getControl();
-		if (control == null) {
+		if (control == null || control.isDisposed()) {
 			Composite parent = swtItem.getParent();
 			SWTSkinObject soParent = (SWTSkinObject) parent.getData("SkinObject");
 
@@ -94,11 +116,16 @@ public class TabbedEntry
 					if (oldSelection != null) {
 						swtItem.getParent().setSelection(oldSelection);
 					}
-					setSkinObject(skinObject, skinObject);
+					setPluginSkinObject(skinObject);
+					setSkinObjectMaster(skinObject);
+
+
+					initialize((Composite) control);
 				} finally {
 					shell.setCursor(cursor);
 				}
-			} else if (view != null) {
+			} else {
+				// XXX: This needs to be merged into BaseMDIEntry.initialize
 				try {
 					SWTSkinObjectContainer soContents = (SWTSkinObjectContainer) skin.createSkinObject(
 							"MdiIView." + uniqueNumber++, "mdi.content.item",
@@ -111,8 +138,7 @@ public class TabbedEntry
 					//viewComposite.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND));
 
 					boolean doGridLayout = true;
-					UISWTView swtView = view;
-					if (swtView.getControlType() == UISWTViewCore.CONTROLTYPE_SKINOBJECT) {
+					if (getControlType() == UISWTViewCore.CONTROLTYPE_SKINOBJECT) {
 						doGridLayout = false;
 					}
 					if (doGridLayout) {
@@ -122,13 +148,11 @@ public class TabbedEntry
   					viewComposite.setLayoutData(Utils.getFilledFormData());
 					}
 
-					UISWTViewCore uiViewCore = view;
-					uiViewCore.setSkinObject(soContents, soContents.getComposite());
+					setPluginSkinObject(soContents);
 
-					view.initialize(viewComposite);
-					setTitle(view.getFullTitle());
+					initialize(viewComposite);
 
-					Composite iviewComposite = view.getComposite();
+					Composite iviewComposite = getComposite();
 					control = iviewComposite;
 					if (doGridLayout) {
 						Object existingLayoutData = iviewComposite.getLayoutData();
@@ -141,52 +165,39 @@ public class TabbedEntry
 						}
 					}
 
-					//soContents is invisible, so of course iviwComposite is invisible
-					//We should do the one time layout on the first show..
-					//if (iviewComposite.isVisible()) {
-					//	parent.layout(true, true);
-					//}
-
 					CTabItem oldSelection = swtItem.getParent().getSelection();
 					swtItem.getParent().setSelection(swtItem);
-					swtItem.setControl(soContents.getControl());
+					swtItem.setControl(viewComposite);
 					if (oldSelection != null) {
 						swtItem.getParent().setSelection(oldSelection);
 					}
-					setSkinObject(soContents, soContents);
+					setSkinObjectMaster(soContents);
 				} catch (Exception e) {
 					Debug.out("Error creating sidebar content area for " + id, e);
-					close(true);
-				}
-
-			} else if (viewClass != null) {
-				try {
-					UISWTViewCore view = (UISWTViewCore) viewClass.newInstance();
-
-					if (view != null) {
-						setCoreView(view);
-						// now that we have an view, go through show one more time
-						return swt_build();
+					try {
+						setEventListener(null, false);
+					} catch (UISWTViewEventCancelledException e1) {
 					}
 					close(true);
-					return false;
-				} catch (Exception e) {
-					Debug.out(e);
-					close(true);
 				}
+
 			}
 
 			if (control != null && !control.isDisposed()) {
 				control.setData("BaseMDIEntry", this);
+				/** XXX Removed this because we can dispose of the control and still
+				 * want the tab (ie. destroy on focus lost, rebuild on focus gain)
 				control.addDisposeListener(new DisposeListener() {
 					public void widgetDisposed(DisposeEvent e) {
 						close(true);
 					}
 				});
+				*/
 			} else {
 				return false;
 			}
 		}
+		
 		return true;
 	}
 
@@ -232,12 +243,30 @@ public class TabbedEntry
 		return null; // new SideBarVitalityImageSWT(this, imageID);
 	}
 
-	/* (non-Javadoc)
-	 * @see com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry#isCloseable()
-	 */
 	public boolean isCloseable() {
 		// override.. we don't support non-closeable
-		return true;
+		return ((TabbedMDI) getMDI()).isMainMDI ? true : super.isCloseable();
+	}
+	
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry#setCloseable(boolean)
+	 */
+	@Override
+	public void setCloseable(boolean closeable) {
+		// override.. we don't support non-closeable for main
+		if (((TabbedMDI) getMDI()).isMainMDI) {
+			closeable = true;
+		}
+		super.setCloseable(closeable);
+		Utils.execSWTThread(new AERunnable() {
+			@Override
+			public void runSupport() {
+				if (swtItem == null || swtItem.isDisposed()) {
+					return;
+				}
+				swtItem.setShowClose(isCloseable());
+			}
+		});
 	}
 
 	public void setSwtItem(CTabItem swtItem) {
@@ -252,9 +281,12 @@ public class TabbedEntry
 		String title = getTitle();
 		if (title != null) {
 			swtItem.setText(escapeAccelerators(title));
-		} else if (viewClass != null) {
-			swtItem.setText(viewClass.getSimpleName());
 		}
+
+		updateLeftImage();
+		
+		swtItem.setShowClose(isCloseable());
+
 		if (buildonSWTItemSet) {
 			build();
 		}
@@ -274,7 +306,14 @@ public class TabbedEntry
 		super.setTitle(title);
 
 		if (swtItem != null) {
-			swtItem.setText(escapeAccelerators(title));
+			Utils.execSWTThread(new AERunnable() {
+				public void runSupport() {
+					if (swtItem == null || swtItem.isDisposed()) {
+						return;
+					}
+					swtItem.setText(escapeAccelerators(getTitle()));
+				}
+			});
 		}
 	}
 
@@ -297,12 +336,9 @@ public class TabbedEntry
 		Utils.execSWTThread(new Runnable() {
 			public void run() {
 				if (swtItem != null && !swtItem.isDisposed()) {
+					// this will triggerCloseListeners
 					swtItem.dispose();
 					swtItem = null;
-				} else if (view != null) {
-					setCoreView(null);
-
-					triggerCloseListeners(!SWTThread.getInstance().isTerminated());
 				}
 			}
 		});
@@ -310,20 +346,60 @@ public class TabbedEntry
 	}
 
 	public void redraw() {
+		Utils.execSWTThread(new AERunnable() {
+			@Override
+			public void runSupport() {
+				if (swtItem == null || swtItem.isDisposed()) {
+					return;
+				}
+				// recalculate the size of tab (in case indicator text changed)
+				swtItem.getParent().notifyListeners(SWT.Resize, new Event());
+				// redraw indicator text
+				swtItem.getParent().redraw();
+			}
+		});
+	}
+	
+	// @see com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry#setImageLeftID(java.lang.String)
+	public void setImageLeftID(String id) {
+		super.setImageLeftID(id);
+		updateLeftImage();
+	}
+	
+	// @see com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry#setImageLeft(org.eclipse.swt.graphics.Image)
+	public void setImageLeft(Image imageLeft) {
+		super.setImageLeft(imageLeft);
+		updateLeftImage();
+	}
+
+	private void updateLeftImage() {
+		if (swtItem == null) {
+			return;
+		}
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				if (swtItem == null || swtItem.isDisposed()) {
+					return;
+				}
+				Image image = getImageLeft(null);
+				swtItem.setImage(image);
+			}
+		});
 	}
 
 	public void widgetDisposed(DisposeEvent e) {
 		setSwtItem(null);
 
 		triggerCloseListeners(!SWTThread.getInstance().isTerminated());
-
-		UISWTViewCore view = getCoreView();
-		if (view != null) {
-			setCoreView(null);
+		
+		try {
+			setEventListener(null, false);
+		} catch (UISWTViewEventCancelledException e1) {
 		}
+
 		SWTSkinObject so = getSkinObject();
 		if (so != null) {
-			setSkinObject(null, null);
+			setSkinObjectMaster(null);
 			so.getSkin().removeSkinObject(so);
 		}
 		
@@ -341,12 +417,6 @@ public class TabbedEntry
 					return;
 				}
 
-				try {
-					COConfigurationManager.removeParameter("SideBar.AutoOpen." + id);
-				} catch (Exception e2) {
-					Debug.out(e2);
-				}
-
 				mdi.removeItem(TabbedEntry.this);
 				mdi.removeEntryAutoOpen(id);
 			}
@@ -374,30 +444,16 @@ public class TabbedEntry
 			return;
 		}
 
-		String textIndicator = null;
-		try {
-			textIndicator = (String) viewTitleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_INDICATOR_TEXT);
-		} catch (Exception e) {
-			Debug.out(e);
-		}
-		if (textIndicator != null) {
-			setPullTitleFromView(false);
-		}
-		
 		String newText = (String) viewTitleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_TEXT);
 		if (newText != null) {
-			if (textIndicator != null) {
-				newText += " (" + textIndicator + ")";
-			}
-			setPullTitleFromView(false);
 			setTitle(newText);
-		} else if (view != null) {
-			newText = view.getFullTitle();
-			if (textIndicator != null) {
-				newText += " (" + textIndicator + ")";
+		} else {
+			String titleID = getTitleID();
+			if (titleID != null) {
+				setTitleID(titleID);
 			}
-			setTitle(newText);
 		}
+		redraw();
 	}
 	
 	// @see com.aelitis.azureus.ui.mdi.MdiEntry#isSelectable()
@@ -418,4 +474,14 @@ public class TabbedEntry
 	public void removeListener(MdiSWTMenuHackListener l) {
 		// TODO Auto-generated method stub
 	}
+	
+	// @see com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry#setParentID(java.lang.String)
+	public void setParentID(String id) {
+		// Do not set
+	}
+	
+	// @see com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry#getParentID()
+	public String getParentID() {
+		return null;
+	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/mdi/TabbedMDI.java b/azureus3/src/com/aelitis/azureus/ui/swt/mdi/TabbedMDI.java
index baaab43..3bbc16d 100755
--- a/azureus3/src/com/aelitis/azureus/ui/swt/mdi/TabbedMDI.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/mdi/TabbedMDI.java
@@ -1,50 +1,120 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.mdi;
 
+import java.lang.reflect.Field;
+import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.Map;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.CTabFolder;
-import org.eclipse.swt.custom.CTabFolder2Adapter;
-import org.eclipse.swt.custom.CTabFolderEvent;
-import org.eclipse.swt.custom.CTabItem;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.custom.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
 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.ConfigurationManager;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.util.*;
-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.plugins.download.Download;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.ui.swt.MenuBuildUtils;
+import org.gudy.azureus2.ui.swt.MenuBuildUtils.MenuBuilder;
 import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.plugins.PluginUISWTSkinObject;
-import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewEventCancelledException;
+import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
 import org.gudy.azureus2.ui.swt.views.IViewAlwaysInitialize;
 
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
 import com.aelitis.azureus.ui.mdi.MdiEntry;
+import com.aelitis.azureus.ui.mdi.MdiEntryVitalityImage;
+import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
+import com.aelitis.azureus.ui.swt.skin.SWTSkin;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectTabFolder;
 import com.aelitis.azureus.ui.swt.utils.ColorCache;
 
 public class TabbedMDI
 	extends BaseMDI
-	implements AEDiagnosticsEvidenceGenerator
+	implements TabbedMdiInterface, AEDiagnosticsEvidenceGenerator, ParameterListener
 {
 	private CTabFolder tabFolder;
 
 	private LinkedList<MdiEntry>	select_history = new LinkedList<MdiEntry>();
+
+	protected boolean minimized;
 	
+	private int iFolderHeightAdj;
+
+	private String props_prefix;
+
+	private DownloadManager		maximizeTo;
+
+	private int minimumCharacters = 25;
+
+	protected boolean isMainMDI;
+
+	private Map mapUserClosedTabs;
+
+	private boolean maximizeVisible = false;
+
+	private boolean minimizeVisible = false;
+
+	private TabbedMdiMaximizeListener maximizeListener;
+
 	public TabbedMDI() {
 		super();
 		AEDiagnostics.addEvidenceGenerator(this);
+		mapUserClosedTabs = new HashMap();
+		isMainMDI = true;
 	}
 
+	/**
+	 * @param parent
+	 */
+	public TabbedMDI(Composite parent, String id) {
+		this.props_prefix = id;
+		minimumCharacters = 0;
+		isMainMDI = false;
+		setCloseableConfigFile(null);
+
+		SWTSkin skin = SWTSkinFactory.getInstance();
+		SWTSkinObjectTabFolder soFolder = new SWTSkinObjectTabFolder(skin,
+				skin.getSkinProperties(), id, "tabfolder.fill", parent);
+		setMainSkinObject(soFolder);
+		soFolder.addListener(this);
+		skin.addSkinObject(soFolder);
+		
+		String key = props_prefix + ".closedtabs";
+		
+		mapUserClosedTabs = COConfigurationManager.getMapParameter(key, new HashMap());
+		COConfigurationManager.addParameterListener(key, this);
+	}
+	
+
 	public Object skinObjectCreated(SWTSkinObject skinObject, Object params) {
 		super.skinObjectCreated(skinObject, params);
 
@@ -59,51 +129,17 @@ public class TabbedMDI
 		return null;
 	}
 	
-	// @see com.aelitis.azureus.ui.swt.mdi.BaseMDI#skinObjectInitialShow(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
-	public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) {
-
-		UIManager ui_manager = PluginInitializer.getDefaultInterface().getUIManager();
-		ui_manager.addUIListener(new UIManagerListener() {
-			public void UIDetached(UIInstance instance) {
-			}
-			
-			public void UIAttached(UIInstance instance) {
-				if (instance instanceof UISWTInstance) {
-					
-					final AESemaphore wait_sem = new AESemaphore( "TabbedMDI:wait" );
-					
-					Utils.execSWTThread(new AERunnable() {
-						public void runSupport() {
-							try{
-								try {
-									loadCloseables();
-								} catch (Throwable t) {
-									Debug.out(t);
-								}
-	
-								setupPluginViews();
-								
-							}finally{
-								
-								wait_sem.release();
-							}
-						}
-					});
-					
-						// we need to wait for the loadCloseables to complete as there is code in MainMDISetup that runs on the 'UIAttachedComplete'
-						// callback that needs the closables to be loaded (when setting 'start tab') otherwise the order gets broken
-				
-					if ( !wait_sem.reserve(10*1000)){
-						
-						Debug.out( "eh?");
-					}
-				}
-			}
-		});
-
-		return super.skinObjectInitialShow(skinObject, params);
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.BaseMDI#skinObjectDestroyed(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
+	 */
+	@Override
+	public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) {
+		String key = props_prefix + ".closedtabs";
+		COConfigurationManager.removeParameterListener( key, this );
+		
+		return super.skinObjectDestroyed(skinObject, params);
 	}
-
+	
 	private void creatMDI() {
 		if (soMain instanceof SWTSkinObjectTabFolder) {
 			tabFolder = ((SWTSkinObjectTabFolder) soMain).getTabFolder();
@@ -112,17 +148,27 @@ public class TabbedMDI
 					| SWT.BORDER | SWT.CLOSE);
 		}
 
-		COConfigurationManager.addAndFireParameterListener("GUI_SWT_bFancyTab",
-				new ParameterListener() {
-					public void parameterChanged(String parameterName) {
-						Utils.execSWTThread(new AERunnable() {
-							public void runSupport() {
-								boolean simple = !COConfigurationManager.getBooleanParameter("GUI_SWT_bFancyTab");
-								tabFolder.setSimple(simple);
-							}
-						});
-					}
-				});
+		iFolderHeightAdj = tabFolder.computeSize(SWT.DEFAULT, 0).y;
+
+		if (isMainMDI) {
+  		COConfigurationManager.addAndFireParameterListener("GUI_SWT_bFancyTab",
+  				new ParameterListener() {
+  					public void parameterChanged(String parameterName) {
+  						Utils.execSWTThread(new AERunnable() {
+  							public void runSupport() {
+  								boolean simple = !COConfigurationManager.getBooleanParameter("GUI_SWT_bFancyTab");
+  								tabFolder.setSimple(simple);
+  							}
+  						});
+  					}
+  				});
+  		tabFolder.setSimple(!COConfigurationManager.getBooleanParameter("GUI_SWT_bFancyTab"));
+		} else {
+			tabFolder.setSimple(true);
+			tabFolder.setMaximizeVisible(maximizeVisible);
+			tabFolder.setMinimizeVisible(minimizeVisible);
+			tabFolder.setUnselectedCloseVisible(false);
+		}
 
 		Display display = tabFolder.getDisplay();
 
@@ -144,104 +190,497 @@ public class TabbedMDI
 		}, true);
 		tabFolder.setSelectionForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
 
-		tabFolder.setSimple(!COConfigurationManager.getBooleanParameter("GUI_SWT_bFancyTab"));
-
-		tabFolder.setMinimumCharacters(25);
+		if (minimumCharacters > 0) {
+			tabFolder.setMinimumCharacters(minimumCharacters);
+		}
 
+		// XXX TVSWT_Common had SWT.Activate too
 		tabFolder.addListener(SWT.Selection, new Listener() {
 			public void handleEvent(Event event) {
 				TabbedEntry entry = (TabbedEntry) event.item.getData("TabbedEntry");				
 				showEntry(entry);
 			}
 		});
-		
-		tabFolder.addCTabFolder2Listener(
-			new CTabFolder2Adapter()
-			{
-				@Override
-				public void 
-				close(
-					CTabFolderEvent event )
-				{
-					final TabbedEntry entry = (TabbedEntry) event.item.getData("TabbedEntry");
-					
-					if ( select_history.remove( entry )){
-						
-						if ( select_history.size() > 0 ){
-							
-							MdiEntry next = select_history.getLast();
-							
-							if ( !next.isDisposed() && next != entry ){
-								
-								event.doit = false;
 
-								showEntry( next );
-								
-								Utils.execSWTThreadLater(
-									0, 
-									new AERunnable() 
-									{
-										public void 
-										runSupport() 
-										{
-											entry.close( true );
-										}
-									});
+		tabFolder.addMouseListener(new MouseAdapter() {
+			public void mouseDown(MouseEvent e) {
+				if (tabFolder.getMinimized()) {
+					restore();
+					// If the user clicked down on the restore button, and we restore
+					// before the CTabFolder does, CTabFolder will minimize us again
+					// There's no way that I know of to determine if the mouse is 
+					// on that button!
+
+					// one of these will tell tabFolder to cancel
+					e.button = 0;
+					tabFolder.notifyListeners(SWT.MouseExit, null);
+				}
+			}
+			public void mouseDoubleClick(MouseEvent e) {
+				if (!tabFolder.getMinimized() && tabFolder.getMaximizeVisible()) {
+					minimize();
+				}
+			}
+		});
+
+		tabFolder.addCTabFolder2Listener(new CTabFolder2Adapter() {
+			public void minimize(CTabFolderEvent event) {
+				TabbedMDI.this.minimize();
+			}
+
+
+			public void maximize(CTabFolderEvent event) {
+				if (maximizeListener != null) {
+					maximizeListener.maximizePressed();
+				}
+			}
+
+
+			public void restore(CTabFolderEvent event_maybe_null) {
+				TabbedMDI.this.restore();
+			}
+
+
+			@Override
+			public void close(CTabFolderEvent event) {
+				final TabbedEntry entry = (TabbedEntry) event.item.getData(
+						"TabbedEntry");
+
+				if (select_history.remove(entry)) {
+
+					if (select_history.size() > 0) {
+
+						final MdiEntry next = select_history.getLast();
+
+						if (!next.isDisposed() && next != entry) {
+							
+							// If tabfolder's selected entry is the one we are closing,
+							// CTabFolder will try to move to next CTabItem.  Disable
+							// this feature by moving tabfolder's selection away from us
+							CTabItem[] items = tabFolder.getItems();
+							for (int i = 0; i < items.length; i++) {
+								CTabItem item = items[i];
+								TabbedEntry scanEntry = getEntryFromTabItem(item);
+								if (scanEntry == next) {
+									tabFolder.setSelection(item);
+									break;
+								}
 							}
+
+							showEntry(next);
 						}
 					}
 				}
-			});
+
+				// since showEntry is slightly delayed, we must slightly delay 
+				// the closing of the entry the user clicked.  Otherwise, it would close
+				// first, and the first tab would auto-select (on windows), and then
+				// the "next" tab would select.
+				if (props_prefix != null) {
+  				Utils.execSWTThreadLater(0, new AERunnable() {
+  
+  					@Override
+  					public void runSupport() {
+  						String view_id = entry.getViewID();
+  						String key = props_prefix + ".closedtabs";
+  
+  						Map closedtabs = COConfigurationManager.getMapParameter(key,
+  								new HashMap());
+  
+  						if (!closedtabs.containsKey(view_id)) {
+  
+  							closedtabs.put(view_id, entry.getTitle());
+  
+  							// this will trigger listener which will remove the tab
+  							COConfigurationManager.setParameter(key, closedtabs);
+  						}
+  					}
+  				});
+				}
+			}
+		});
 		
-		tabFolder.getDisplay().addFilter(SWT.KeyDown, new Listener() {
-			public void handleEvent(Event event) {
-				if ( tabFolder.isDisposed()){
+		if (isMainMDI) {
+  		tabFolder.getDisplay().addFilter(SWT.KeyDown, new Listener() {
+  			public void handleEvent(Event event) {
+  				if ( tabFolder.isDisposed()){
+  					return;
+  				}
+  				// Another window has control, skip filter
+  				Control focus_control = tabFolder.getDisplay().getFocusControl();
+  				if (focus_control != null
+  						&& focus_control.getShell() != tabFolder.getShell()) {
+  					return;
+  				}
+  
+  				int key = event.character;
+  				if ((event.stateMask & SWT.MOD1) != 0 && event.character <= 26
+  						&& event.character > 0)
+  					key += 'a' - 1;
+  
+  				// ESC or CTRL+F4 closes current Tab
+  				if (key == SWT.ESC
+  						|| (event.keyCode == SWT.F4 && event.stateMask == SWT.CTRL)) {
+  					MdiEntry entry = getCurrentEntry();
+  					if (entry != null) {
+  						entry.close(false);
+  					}
+  					event.doit = false;
+  				} else if (event.keyCode == SWT.F6
+  						|| (event.character == SWT.TAB && (event.stateMask & SWT.CTRL) != 0)) {
+  					// F6 or Ctrl-Tab selects next Tab
+  					// On Windows the tab key will not reach this filter, as it is
+  					// processed by the traversal TRAVERSE_TAB_NEXT.  It's unknown
+  					// what other OSes do, so the code is here in case we get TAB
+  					if ((event.stateMask & SWT.SHIFT) == 0) {
+  						event.doit = false;
+  						selectNextTab(true);
+  						// Shift+F6 or Ctrl+Shift+Tab selects previous Tab
+  					} else if (event.stateMask == SWT.SHIFT) {
+  						selectNextTab(false);
+  						event.doit = false;
+  					}
+  				}
+  			}
+  		});
+		}
+
+		tabFolder.addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				saveCloseables();
+			}
+		});
+		
+		tabFolder.getTabHeight();
+		final Menu menu = new Menu( tabFolder );
+		tabFolder.setMenu(menu);
+		MenuBuildUtils.addMaintenanceListenerForMenu(menu, new MenuBuilder() {
+			public void buildMenu(Menu root_menu, MenuEvent event) {
+				Point cursorLocation = event.display.getCursorLocation();
+				Point ptOnControl = tabFolder.toControl(cursorLocation.x,
+						cursorLocation.y);
+				if (ptOnControl.y > tabFolder.getTabHeight()) {
 					return;
 				}
-				// Another window has control, skip filter
-				Control focus_control = tabFolder.getDisplay().getFocusControl();
-				if (focus_control != null
-						&& focus_control.getShell() != tabFolder.getShell()) {
-					return;
+
+				final CTabItem item = tabFolder.getItem(
+						tabFolder.toControl(cursorLocation.x, cursorLocation.y));
+
+				boolean need_sep = false;
+
+				if (item == null) {
+
+					need_sep = mapUserClosedTabs.size() > 0;
+					if (need_sep) {
+  					for (Object id : mapUserClosedTabs.keySet()) {
+  						final String view_id = (String) id;
+
+  						MenuItem mi = new MenuItem(menu, SWT.PUSH);
+
+  						String title;
+  						
+  						Object oTitle = mapUserClosedTabs.get(id);
+  						if (oTitle instanceof String && ((String) oTitle).length() > 0) {
+								title = (String) oTitle;
+							} else {
+								title = MessageText.getString(getViewTitleID(view_id));
+							}
+  						mi.setText(title);
+
+  						mi.addListener(SWT.Selection, new Listener() {
+  							public void handleEvent(Event event) {
+  								String key = props_prefix + ".closedtabs";
+
+  								Map closedtabs = COConfigurationManager.getMapParameter(key,
+  										new HashMap());
+
+  								if (closedtabs.containsKey(view_id)) {
+
+  									closedtabs.remove(view_id);
+
+  									COConfigurationManager.setParameter(key, closedtabs);
+  								}
+  								
+  								showEntryByID(view_id);
+  							}
+  						});
+  						
+  					}
+					}
 				}
 
-				int key = event.character;
-				if ((event.stateMask & SWT.MOD1) != 0 && event.character <= 26
-						&& event.character > 0)
-					key += 'a' - 1;
+				if (need_sep) {
+					new MenuItem(menu, SWT.SEPARATOR);
+				}
+
+				
+				TabbedEntry entry = null;
+				if (item != null) {
+					entry = getEntryFromTabItem(item);
+					showEntry(entry);
+				}
+
+				fillMenu(menu, entry, isMainMDI ? "sidebar" : props_prefix);
+
+			}
+		});
+
+		CTabFolderRenderer renderer = new CTabFolderRenderer(tabFolder) {
+			/* (non-Javadoc)
+			 * @see org.eclipse.swt.custom.CTabFolderRenderer#computeSize(int, int, org.eclipse.swt.graphics.GC, int, int)
+			 */
+			@Override
+			protected Point computeSize(int part, int state, GC gc, int wHint,
+					int hHint) {
+				gc.setAntialias(SWT.ON);
+				Point pt = super.computeSize(part, state, gc, wHint, hHint);
+				if (tabFolder.isDisposed()) {
+					return pt;
+				}
 
-				// ESC or CTRL+F4 closes current Tab
-				if (key == SWT.ESC
-						|| (event.keyCode == SWT.F4 && event.stateMask == SWT.CTRL)) {
-					MdiEntry entry = getCurrentEntry();
+				if (part >= 0) {
+					TabbedEntry entry = getEntryFromTabItem(tabFolder.getItem(part));
 					if (entry != null) {
-						entry.close(false);
+						ViewTitleInfo viewTitleInfo = entry.getViewTitleInfo();
+						if (viewTitleInfo != null) {
+							Object titleRight = viewTitleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_INDICATOR_TEXT);
+							if (titleRight != null) {
+								Point size = gc.textExtent(titleRight.toString(), 0);
+								pt.x += size.x + 10 + 2;
+							}
+						}
+						
+						
+						MdiEntryVitalityImage[] vitalityImages = entry.getVitalityImages();
+						ImageLoader imageLoader = ImageLoader.getInstance();
+						for (MdiEntryVitalityImage mdiEntryVitalityImage : vitalityImages) {
+							if (mdiEntryVitalityImage != null && mdiEntryVitalityImage.isVisible()) {
+								String imageID = mdiEntryVitalityImage.getImageID();
+								Image image = imageLoader.getImage(imageID);
+								if (ImageLoader.isRealImage(image)) {
+									pt.x += image.getBounds().x + 5;
+								}
+							}
+							
+						}
 					}
-					event.doit = false;
-				} else if (event.keyCode == SWT.F6
-						|| (event.character == SWT.TAB && (event.stateMask & SWT.CTRL) != 0)) {
-					// F6 or Ctrl-Tab selects next Tab
-					// On Windows the tab key will not reach this filter, as it is
-					// processed by the traversal TRAVERSE_TAB_NEXT.  It's unknown
-					// what other OSes do, so the code is here in case we get TAB
-					if ((event.stateMask & SWT.SHIFT) == 0) {
-						event.doit = false;
-						selectNextTab(true);
-						// Shift+F6 or Ctrl+Shift+Tab selects previous Tab
-					} else if (event.stateMask == SWT.SHIFT) {
-						selectNextTab(false);
-						event.doit = false;
+				}
+				return pt;
+			}
+			
+			/* (non-Javadoc)
+			 * @see org.eclipse.swt.custom.CTabFolderRenderer#draw(int, int, org.eclipse.swt.graphics.Rectangle, org.eclipse.swt.graphics.GC)
+			 */
+			@Override
+			protected void draw(int part, int state, Rectangle bounds, GC gc) {
+				try {
+					super.draw(part, state, bounds, gc);
+				} catch (Throwable t) {
+					Debug.out(t);
+				}
+				if (part < 0) {
+					return;
+				}
+				try {
+					CTabItem item = getTabFolder().getItem(part);
+					TabbedEntry entry = getEntryFromTabItem(item);
+					if (entry == null) {
+						return;
 					}
+
+					ViewTitleInfo viewTitleInfo = entry.getViewTitleInfo();
+					if (viewTitleInfo != null) {
+						Object titleRight = viewTitleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_INDICATOR_TEXT);
+						if (titleRight != null) {
+							String textIndicator = titleRight.toString();
+							int x1IndicatorOfs = 0;
+							int SIDEBAR_SPACING = 0;
+							int x2 = bounds.x + bounds.width;
+							
+							if (item.getShowClose()) {
+								try {
+									Field fldCloseRect = item.getClass().getDeclaredField("closeRect");
+									fldCloseRect.setAccessible(true);
+									Rectangle closeBounds = (Rectangle) fldCloseRect.get(item);
+									if (closeBounds != null && closeBounds.x > 0) {
+										x2 = closeBounds.x;
+									}
+								} catch (Exception e) {
+									x2 -= 20;
+								}
+							}
+							gc.setAntialias(SWT.ON);
+
+							Point textSize = gc.textExtent(textIndicator);
+							//Point minTextSize = gc.textExtent("99");
+							//if (textSize.x < minTextSize.x + 2) {
+							//	textSize.x = minTextSize.x + 2;
+							//}
+
+							int width = textSize.x + 10;
+							x1IndicatorOfs += width + SIDEBAR_SPACING;
+							int startX = x2 - x1IndicatorOfs;
+
+							int textOffsetY = 0;
+
+							int height = textSize.y + 1;
+							int startY = bounds.y + ((bounds.height - height) / 2) + 1;
+
+							//gc.fillRectangle(startX, startY, width, height);
+
+							//Pattern pattern;
+							//Color color1;
+							//Color color2;
+
+							Color default_color = ColorCache.getSchemedColor(gc.getDevice(), "#5b6e87");
+							
+							Object color =  viewTitleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_INDICATOR_COLOR);
+
+							if ( color instanceof int[] ){
+								
+								gc.setBackground(ColorCache.getColor( gc.getDevice(),(int[])color ));
+								
+							}else{
+								
+								gc.setBackground( default_color );
+							}
+							
+
+							Color text_color = Colors.white;
+							
+							gc.fillRoundRectangle(startX, startY, width, height, textSize.y * 2 / 3,
+									height * 2 / 3);
+							
+							if ( color != null ){
+								
+								Color bg = gc.getBackground();
+								
+								int	red 	= bg.getRed();
+								int green 	= bg.getGreen();
+								int blue	= bg.getBlue();
+								
+								double brightness = Math.sqrt( red*red*0.299+green*green*0.587+blue*blue*0.114);
+								
+								if ( brightness >= 130 ){
+									text_color = Colors.black;
+								}
+								
+								gc.setBackground( default_color );
+								
+								gc.drawRoundRectangle(startX, startY, width, height, textSize.y * 2 / 3,
+										height * 2 / 3);
+							}
+							gc.setForeground(text_color);
+							GCStringPrinter.printString(gc, textIndicator, new Rectangle(startX,
+									startY + textOffsetY, width, height), true, false, SWT.CENTER);
+						
+						}
+					}
+
+				} catch (Throwable t) {
+					Debug.out(t);
 				}
 			}
-		});
+		};
+		tabFolder.setRenderer(renderer);
+		
+		if (minimizeVisible) {
+			boolean toMinimize = ConfigurationManager.getInstance().getBooleanParameter(props_prefix + ".subViews.minimized");
+			setMinimized(toMinimize);
+		}
+	}
+	
+	private String
+	getViewTitleID(
+		String	view_id )
+	{
+		String history_key = "swt.ui.table.tab.view.namecache." + view_id;
 
-		tabFolder.addDisposeListener(new DisposeListener() {
-			public void widgetDisposed(DisposeEvent e) {
-				saveCloseables();
+		String id = COConfigurationManager.getStringParameter( history_key, "" );
+
+		if ( id.length() == 0 ){
+			
+			String test = view_id + ".title.full";
+			
+			if ( MessageText.keyExists( test )){
+			
+				return( test );
 			}
-		});
+			
+			id = "!" + view_id + "!";
+		}
+		
+		return( id );
+	}
+
+
+
+	private void minimize() {
+		minimized = true;
+
+		tabFolder.setMinimized(true);
+		CTabItem[] items = tabFolder.getItems();
+		String tt = MessageText.getString("label.click.to.restore");
+		for (int i = 0; i < items.length; i++) {
+			CTabItem tabItem = items[i];
+			tabItem.setToolTipText(tt);
+			Control control = tabItem.getControl();
+			if (control != null && !control.isDisposed()) {
+				tabItem.getControl().setVisible(false);
+			}
+		}
+
+		tabFolder.getParent().notifyListeners(SWT.Resize, null);
+
+		showEntry(null);
+
+		ConfigurationManager configMan = ConfigurationManager.getInstance();
+		configMan.setParameter(props_prefix + ".subViews.minimized", true);
 	}
+	
+	private void restore() {
+
+		minimized = false;
+		tabFolder.setMinimized(false);
+		CTabItem selection = tabFolder.getSelection();
+		if (selection != null) {
+			TabbedEntry tabbedEntry = getEntryFromTabItem(selection);
+
+			showEntry(tabbedEntry);
+
+			/* Already done by TabbedEntry.swt_build 
+			Control control = selection.getControl();
+			if (control == null || control.isDisposed()) {
+				selectedView.initialize(tabFolder);
+				selection.setControl(selectedView.getComposite());
+				control = selection.getControl();
+				triggerTabViewDataSourceChanged(selectedView, tv, new Object[][] {
+					null,
+					null
+				});
+			}
+			selection.getControl().setVisible(true);
+			*/
+			tabbedEntry.updateUI();
+		}
+
+		if (tabFolder.getMaximizeVisible()) {
+			CTabItem[] items = tabFolder.getItems();
+			String tt = MessageText.getString("label.dblclick.to.min");
+
+			for (int i = 0; i < items.length; i++) {
+				CTabItem tabItem = items[i];
+				tabItem.setToolTipText(tt);
+			}
+		}
+
+		tabFolder.getParent().notifyListeners(SWT.Resize, null);
+
+		ConfigurationManager configMan = ConfigurationManager.getInstance();
+		configMan.setParameter(props_prefix + ".subViews.minimized", false);
+	}
+
+
 
 	private void selectNextTab(boolean selectNext) {
 		if (tabFolder == null || tabFolder.isDisposed()) {
@@ -261,7 +700,7 @@ public class TabbedMDI
 
 		// instead of .setSelection, use showEntry which will ensure view de/activations
 		CTabItem item = tabFolder.getItem(index);
-		MdiEntry entry = (MdiEntry) item.getData("TabbedEntry");
+		MdiEntry entry = getEntryFromTabItem(item);
 
 		if (entry != null) {
 			showEntry(entry);
@@ -284,17 +723,20 @@ public class TabbedMDI
 			return;
 		}
 		
-		select_history.remove( newEntry );
-		
-		select_history.add( newEntry );
-			
-		if ( select_history.size() > 64 ){
-			
-			select_history.removeFirst();
+		if (newEntry != null) {
+  		select_history.remove( newEntry );
+  		
+  		select_history.add( newEntry );
+  			
+  		if ( select_history.size() > 64 ){
+  			
+  			select_history.removeFirst();
+  		}
 		}
 		
 		MdiEntry oldEntry = currentEntry;
-		if (newEntry == oldEntry) {
+		if (newEntry == oldEntry && oldEntry != null) {
+			((BaseMdiEntry) newEntry).show();
 			triggerSelectionListener(newEntry, newEntry);
 			return;
 		}
@@ -305,18 +747,13 @@ public class TabbedMDI
 
 		currentEntry = (MdiEntrySWT) newEntry; // assumed MdiEntrySWT
 
-		((BaseMdiEntry) newEntry).show();
+		if (currentEntry instanceof BaseMdiEntry) {
+			((BaseMdiEntry) newEntry).show();
+		}
 
 		triggerSelectionListener(newEntry, oldEntry);
 	}
 
-	public void updateUI() {
-		MdiEntry currentEntry = getCurrentEntry();
-		if (currentEntry != null) {
-			currentEntry.updateUI();
-		}
-	}
-	
 	private MdiEntry createEntryFromSkinRef(String parentID, String id,
 			String configID, String title, ViewTitleInfo titleInfo, Object params,
 			boolean closeable, int index) {
@@ -325,10 +762,12 @@ public class TabbedMDI
 			return oldEntry;
 		}
 
-		TabbedEntry entry = new TabbedEntry(this, skin, id);
+		TabbedEntry entry = new TabbedEntry(this, skin, id, null);
 		entry.setTitle(title);
 		entry.setSkinRef(configID, params);
-		setupNewEntry(entry, id, index);
+		entry.setViewTitleInfo(titleInfo);
+		
+		setupNewEntry(entry, id, index, closeable);
 		return entry;
 	}
 	
@@ -341,20 +780,29 @@ public class TabbedMDI
 				params, closeable, "".equals(preferedAfterID) ? 0 : -1);
 	}
 
-	public MdiEntry createEntryFromEventListener(String parentID,
-			UISWTViewEventListener l, String id, boolean closeable, Object datasource, String preferredAfterID) {
+	public MdiEntry createEntryFromEventListener(String parentEntryID,
+			String parentViewID, UISWTViewEventListener l, String id,
+			boolean closeable, Object datasource, String preferredAfterID) {
+		if (isEntryClosedByUser(id)) {
+			return null;
+		}
 		MdiEntry oldEntry = getEntry(id);
 		if (oldEntry != null) {
 			return oldEntry;
 		}
 
-		TabbedEntry entry = new TabbedEntry(this, skin, id);
+		TabbedEntry entry = new TabbedEntry(this, skin, id, parentViewID);
 
+		try {
+			entry.setEventListener(l, true);
+		} catch (UISWTViewEventCancelledException e) {
+			entry.close(true);
+			return null;
+		}
 		entry.setDatasource(datasource);
 		entry.setPreferredAfterID(preferredAfterID);
-		entry.setEventListener(l);
 
-		setupNewEntry(entry, id, -1);
+		setupNewEntry(entry, id, -1, closeable);
 
 		if (l instanceof IViewAlwaysInitialize) {
 			entry.build();
@@ -363,49 +811,22 @@ public class TabbedMDI
 		return entry;
 	}
 
-	public MdiEntry createEntryFromView(String parentID, UISWTViewCore view,
-			String id, Object datasource, boolean closeable, boolean show,
-			boolean expand) {
-		if (id == null) {
-			id = view.getClass().getName();
-			int i = id.lastIndexOf('.');
-			if (i > 0) {
-				id = id.substring(i + 1);
-			}
-		}
-
-		MdiEntry oldEntry = getEntry(id);
-		if (oldEntry != null) {
-			if (show) {
-				showEntry(oldEntry);
-			}
-			return oldEntry;
-		}
-
-		TabbedEntry entry = new TabbedEntry(this, skin, id);
-
-		entry.setCoreView(view);
-		entry.setDatasource(datasource);
-
-		setupNewEntry(entry, id, -1);
-
-		if (view instanceof IViewAlwaysInitialize) {
-			entry.build();
-		}
+	private boolean isEntryClosedByUser(String id) {
 		
-		if (show) {
-			showEntry(entry);
+		if (mapUserClosedTabs.containsKey(id)) {
+			return true;
 		}
-		return entry;
+		// TODO Auto-generated method stub
+		return false;
 	}
 
 	private void setupNewEntry(final TabbedEntry entry, final String id,
-			final int index) {
+			final int index, boolean closeable) {
 		synchronized (mapIdToEntry) {
 			mapIdToEntry.put(id, entry);
 		}
 
-		entry.setCloseable(true);
+		entry.setCloseable(closeable);
 
 		Utils.execSWTThreadLater(0, new AERunnable() {
 			public void runSupport() {
@@ -415,10 +836,13 @@ public class TabbedMDI
 	}
 
 	private void swt_setupNewEntry(TabbedEntry entry, String id, int index) {
+		if (tabFolder == null || tabFolder.isDisposed()) {
+			return;
+		}
 		if (index < 0 || index >= tabFolder.getItemCount()) {
 			index = tabFolder.getItemCount();
 		}
-		CTabItem cTabItem = new CTabItem(tabFolder, SWT.CLOSE, index);
+		CTabItem cTabItem = new CTabItem(tabFolder, SWT.NONE, index);
 		cTabItem.addDisposeListener(new DisposeListener() {
 			public void widgetDisposed(DisposeEvent e) {
 				if (tabFolder.getItemCount() == 0) {
@@ -428,6 +852,31 @@ public class TabbedMDI
 		});
 		cTabItem.setData("TabbedEntry", entry);
 		entry.setSwtItem(cTabItem);
+		
+		if (tabFolder.getItemCount() == 1) {
+  		Utils.execSWTThreadLater(0, new AERunnable() {
+  			
+  			@Override
+  			public void runSupport() {
+  				if (currentEntry != null || tabFolder.isDisposed()) {
+  					return;
+  				}
+  				CTabItem selection = tabFolder.getSelection();
+  				if (selection == null) {
+  					return;
+  				}
+  				TabbedEntry entry = getEntryFromTabItem(selection);
+  				showEntry(entry);
+  			}
+  		});
+		}
+	}
+	
+	private TabbedEntry getEntryFromTabItem(CTabItem item) {
+		if (item.isDisposed()) {
+			return null;
+		}
+		return (TabbedEntry) item.getData("TabbedEntry");
 	}
 
 	public String getUpdateUIName() {
@@ -447,8 +896,7 @@ public class TabbedMDI
 			}
 
 			
-			UISWTViewCore view = entry.getCoreView();
-			if (!(view instanceof AEDiagnosticsEvidenceGenerator)) {
+			if (!(entry instanceof AEDiagnosticsEvidenceGenerator)) {
 				writer.println("TabbedMdi View (No Generator): " + entry.getId());
 				try {
 					writer.indent();
@@ -484,4 +932,134 @@ public class TabbedMDI
 	public MdiEntry createHeader(String id, String title, String preferredAfterID) {
 		return null;
 	}
+	
+	public CTabFolder getTabFolder() {
+		return tabFolder;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.TabbedMdiInterface#setMaximizeVisible(boolean)
+	 */
+	public void setMaximizeVisible(final boolean visible) {
+		maximizeVisible = visible;
+		Utils.execSWTThread(new AERunnable() {
+			@Override
+			public void runSupport() {
+				if (tabFolder == null || tabFolder.isDisposed()) {
+					return;
+				}
+				tabFolder.setMaximizeVisible(visible);
+			}
+		});
+	}
+	
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.TabbedMdiInterface#setMinimizeVisible(boolean)
+	 */
+	public void setMinimizeVisible(final boolean visible) {
+		minimizeVisible = visible;
+		if (minimizeVisible) {
+			boolean toMinimize = ConfigurationManager.getInstance().getBooleanParameter(props_prefix + ".subViews.minimized");
+			setMinimized(toMinimize);
+		}
+		Utils.execSWTThread(new AERunnable() {
+			@Override
+			public void runSupport() {
+				if (tabFolder == null || tabFolder.isDisposed()) {
+					return;
+				}
+				tabFolder.setMinimizeVisible(visible);
+			}
+		});
+	}
+
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.TabbedMdiInterface#getMinimized()
+	 */
+	public boolean getMinimized() {
+		return minimized;
+	}
+	
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.TabbedMdiInterface#setMinimized(boolean)
+	 */
+	public void setMinimized(final boolean minimized) {
+		this.minimized = minimized;
+		Utils.execSWTThread(new AERunnable() {
+			@Override
+			public void runSupport() {
+				if (tabFolder == null || tabFolder.isDisposed()) {
+					return;
+				}
+				
+				if (minimized) {
+					minimize(); 
+				} else {
+					restore();
+				}
+			}
+		});
+	}
+	
+	public int getFolderHeight() {
+		return iFolderHeightAdj;
+	}
+	
+
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#dataSourceChanged(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
+	 */
+	@Override
+	public Object dataSourceChanged(SWTSkinObject skinObject, final Object ds) {
+		Utils.execSWTThread(new Runnable() {
+			public void run() {
+				if (tabFolder == null || tabFolder.isDisposed()) {
+					return;
+				}
+
+				if (ds instanceof Object[]) {
+					Object[] temp = (Object[]) ds;
+					if (temp.length == 1) {
+						Object obj = temp[0];
+
+						if (obj instanceof DownloadManager) {
+							maximizeTo = (DownloadManager) obj;
+						} else if (obj instanceof Download) {
+							maximizeTo = PluginCoreUtils.unwrap((Download) obj);
+						}
+					}
+				}
+
+				setMaximizeVisible(maximizeTo != null);
+
+			}
+		});
+
+		return super.dataSourceChanged(skinObject, ds);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.core3.config.ParameterListener#parameterChanged(java.lang.String)
+	 */
+	public void parameterChanged(String parameterName) {
+		if (isDisposed()) {
+			return;
+		}
+
+		mapUserClosedTabs = COConfigurationManager.getMapParameter(parameterName, new HashMap());
+		
+		for (Object id : mapUserClosedTabs.keySet()) {
+			String view_id = (String) id;
+			if (entryExists(view_id)) {
+				closeEntry(view_id);
+			}
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.TabbedMdiInterface#setTabbedMdiMaximizeListener(com.aelitis.azureus.ui.swt.mdi.TabbedMdiMaximizeListener)
+	 */
+	public void setTabbedMdiMaximizeListener(TabbedMdiMaximizeListener l) {
+		maximizeListener = l;
+	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstallWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstallWindow.java
index 169b2bb..cc457bf 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstallWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstallWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on Mar 15, 2010 02:29 PM
- * Copyright (C) 2010 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.player;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstaller.java b/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstaller.java
index 6d8bd02..160a61e 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstaller.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstaller.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.player;
 
 import java.util.HashMap;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstallerListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstallerListener.java
index 461ac4a..3a9850b 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstallerListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/player/PlayerInstallerListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.player;
 
 public interface PlayerInstallerListener {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstallWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstallWindow.java
index 40aee51..a073338 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstallWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstallWindow.java
@@ -1,6 +1,6 @@
 /*
  * Created on Mar 15, 2010 02:29 PM
- * Copyright (C) 2010 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.plugininstall;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstaller.java b/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstaller.java
index 9fc0545..f2b3b5c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstaller.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstaller.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.plugininstall;
 
 import java.util.HashMap;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstallerListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstallerListener.java
index 70791f9..1b69c98 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstallerListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/plugininstall/SimplePluginInstallerListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.plugininstall;
 
 public interface SimplePluginInstallerListener {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/search/SearchHandler.java b/azureus3/src/com/aelitis/azureus/ui/swt/search/SearchHandler.java
index 387c6ac..87e5221 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/search/SearchHandler.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/search/SearchHandler.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2014 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
@@ -26,6 +25,7 @@ import java.util.Locale;
 import org.eclipse.swt.SWT;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.UrlUtils;
 import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.ui.swt.Utils;
@@ -52,6 +52,29 @@ SearchHandler
 		String		sSearchText,
 		boolean		toSubscribe )
 	{
+		if ( !toSubscribe ){
+			
+			try{
+				
+				if ( 	COConfigurationManager.getBooleanParameter("rcm.overall.enabled",true) &&
+						COConfigurationManager.getBooleanParameter( "Plugin.aercm.rcm.search.enable", false ) && 
+						AzureusCoreFactory.isCoreRunning()){
+					
+					final PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( "aercm");
+
+					if (	pi != null && 
+							pi.getPluginState().isOperational() &&
+							pi.getIPC().canInvoke("lookupByExpression", new Object[]{ "" })){
+
+						pi.getIPC().invoke("lookupByExpression", new Object[]{ sSearchText });
+					}
+				}
+			}catch (Throwable e ){
+
+				Debug.out(e);
+			}
+		}
+		
 		boolean	internal_search = !COConfigurationManager.getBooleanParameter( "browser.external.search" );
 		
 		if ( internal_search ){
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/BrowserWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/BrowserWindow.java
index 0b8da40..3eef6aa 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/BrowserWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/BrowserWindow.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,28 +13,31 @@
  * 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.shells;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.*;
+import org.eclipse.swt.browser.TitleListener;
+import org.eclipse.swt.browser.TitleEvent;
+import org.eclipse.swt.browser.ProgressListener;
+import org.eclipse.swt.browser.ProgressEvent;
+import org.eclipse.swt.browser.StatusTextListener;
+import org.eclipse.swt.browser.StatusTextEvent;
+import org.eclipse.swt.browser.CloseWindowListener;
+import org.eclipse.swt.browser.WindowEvent;
 import org.eclipse.swt.events.*;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.widgets.*;
-
 import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 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.ClientMessageContext;
 import com.aelitis.azureus.ui.swt.browser.BrowserContext;
-import com.aelitis.azureus.ui.swt.browser.BrowserWrapper;
 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.TorrentListener;
@@ -117,7 +120,7 @@ public class BrowserWindow
 		});
 
 
-		browser = new BrowserWrapper( Utils.createSafeBrowser(shell, SWT.NONE));
+		browser = Utils.createSafeBrowser(shell, SWT.NONE);
 		
 		if (browser == null) {
 			shell.dispose();
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/RemotePairingWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/RemotePairingWindow.java
index fea088a..997463f 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/RemotePairingWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/RemotePairingWindow.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 5, 2010
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/DebugMenuHelper.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/DebugMenuHelper.java
index d6861ab..2471d08 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/DebugMenuHelper.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/DebugMenuHelper.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.shells.main;
 
 import org.eclipse.swt.SWT;
@@ -237,6 +255,9 @@ public class DebugMenuHelper
 			800, 550,
 			1024, 718,
 			1280, 700,
+			1440, 850,
+			1600, 1050,
+			1920, 1150
 		};
 		for (int i = 0; i < sizes.length; i += 2) {
 			final int x = sizes[i];
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainHelpers.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainHelpers.java
index 2ba6cb9..44f872a 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainHelpers.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainHelpers.java
@@ -2,20 +2,19 @@
  * Created on Sep 14, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainMDISetup.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainMDISetup.java
index 36219ef..5985a18 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainMDISetup.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainMDISetup.java
@@ -1,32 +1,74 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.shells.main;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 import org.eclipse.swt.widgets.Menu;
-
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.config.ParameterListener;
 import org.gudy.azureus2.core3.config.impl.ConfigurationChecker;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.tracker.host.TRHost;
+import org.gudy.azureus2.core3.tracker.host.TRHostListener;
+import org.gudy.azureus2.core3.tracker.host.TRHostTorrent;
 import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AsyncController;
+import org.gudy.azureus2.core3.util.Base32;
 import org.gudy.azureus2.core3.util.DisplayFormatters;
 import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.ui.*;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadStub;
+import org.gudy.azureus2.plugins.download.DownloadStubEvent;
+import org.gudy.azureus2.plugins.download.DownloadStubListener;
+import org.gudy.azureus2.plugins.sharing.ShareManager;
+import org.gudy.azureus2.plugins.sharing.ShareManagerListener;
+import org.gudy.azureus2.plugins.sharing.ShareResource;
+import org.gudy.azureus2.plugins.ui.UIInstance;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.UIManagerListener2;
 import org.gudy.azureus2.plugins.ui.menus.MenuItem;
 import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
 import org.gudy.azureus2.plugins.ui.menus.MenuManager;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.mainwindow.MenuFactory;
-import org.gudy.azureus2.ui.swt.views.ConfigView;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
+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.utils.ManagerUtils;
 
 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.cnetwork.ContentNetworkManagerFactory;
+import com.aelitis.azureus.core.tag.Tag;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.table.TableView;
@@ -52,15 +94,22 @@ public class MainMDISetup
 			setupSidebarVuzeUI(mdi);
 		}
 
-		mdi.registerEntry(SideBar.SIDEBAR_TORRENT_DETAILS_PREFIX + ".*",
+		mdi.registerEntry(SideBar.SIDEBAR_SECTION_TORRENT_DETAILS + ".*",
 				new MdiEntryCreationListener2() {
 					public MdiEntry createMDiEntry(MultipleDocumentInterface mdi,
 							String id, Object datasource, Map<?, ?> params) {
+						String hash = DataSourceUtils.getHash(datasource);
+						if (hash != null) {
+							id = MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS 
+									+ "_" + hash;
+						}
 						return createTorrentDetailEntry(mdi, id, datasource);
 					}
 				});
 
-		PluginInitializer.getDefaultInterface().getUIManager().addUIListener(
+		PluginInterface pi = PluginInitializer.getDefaultInterface();
+
+		pi.getUIManager().addUIListener(
 				new UIManagerListener2() {
 					public void UIDetached(UIInstance instance) {
 					}
@@ -137,6 +186,27 @@ public class MainMDISetup
 			}
 		});
 
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_ALLPEERS,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						MdiEntry entry = mdi.createEntryFromEventListener(
+								MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS,
+								new PeersSuperView(), id, true, null, null);
+						entry.setImageLeftID("image.sidebar.allpeers");
+						return entry;
+					}
+				});
+		
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_LOGGER,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						MdiEntry entry = mdi.createEntryFromEventListener(
+								MultipleDocumentInterface.SIDEBAR_HEADER_PLUGINS,
+								new LoggerView(), id, true, null, null);
+						return entry;
+					}
+				});
+
 		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_TAGS,
 				new MdiEntryCreationListener() {
 					public MdiEntry createMDiEntry(String id) {
@@ -144,24 +214,352 @@ public class MainMDISetup
 								MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS,
 								MultipleDocumentInterface.SIDEBAR_SECTION_TAGS, "tagsview",
 								"{mdi.entry.tagsoverview}", null, null, true, null);
-						// TODO: Don't steal blue icon
-						entry.setImageLeftID("image.sidebar.tag-blue");
+						entry.setImageLeftID("image.sidebar.tag-overview");
 						return entry;
 					}
 				});
-		PluginInterface pi = PluginInitializer.getDefaultInterface();
-		if (pi != null) {
-			UIManager uim = pi.getUIManager();
-			if (uim != null) {
-				MenuItem menuItem = uim.getMenuManager().addMenuItem(
-						MenuManager.MENU_MENUBAR, "tags.view.heading");
-				menuItem.addListener(new MenuItemListener() {
-					public void selected(MenuItem menu, Object target) {
-						UIFunctionsManager.getUIFunctions().getMDI().showEntryByID(
-								MultipleDocumentInterface.SIDEBAR_SECTION_TAGS);
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_TAG_DISCOVERY,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						MdiEntry entry = mdi.createEntryFromSkinRef(
+								MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS,
+								MultipleDocumentInterface.SIDEBAR_SECTION_TAG_DISCOVERY, "tagdiscoveryview",
+								"{mdi.entry.tagdiscovery}", null, null, true, null);
+						entry.setImageLeftID("image.sidebar.tag-overview");
+						return entry;
+					}
+				});
+		
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_CHAT,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						MdiEntry entry = mdi.createEntryFromSkinRef(
+								MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS,
+								MultipleDocumentInterface.SIDEBAR_SECTION_CHAT, "chatsview",
+								"{mdi.entry.chatsoverview}", null, null, true, null);
+						entry.setImageLeftID("image.sidebar.chat-overview");
+						return entry;
+					}
+				});
+		
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_ARCHIVED_DOWNLOADS,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						
+						final org.gudy.azureus2.plugins.download.DownloadManager download_manager = PluginInitializer.getDefaultInterface().getDownloadManager();
+						
+						final ViewTitleInfo title_info = 
+							new ViewTitleInfo() 
+							{
+								public Object 
+								getTitleInfoProperty(
+									int propertyID) 
+								{
+									if ( propertyID == TITLE_INDICATOR_TEXT ){
+										
+										int num = download_manager.getDownloadStubCount();
+																				
+										return( String.valueOf( num ) );
+									}
+									
+									return null;
+								}
+							};
+						
+						MdiEntry entry = mdi.createEntryFromSkinRef(
+								MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS,
+								MultipleDocumentInterface.SIDEBAR_SECTION_ARCHIVED_DOWNLOADS, "archivedlsview",
+								"{mdi.entry.archiveddownloadsview}", 
+								title_info, null, true, null);
+						
+						entry.setImageLeftID( "image.sidebar.archive" );
+						
+						final DownloadStubListener stub_listener =
+							new DownloadStubListener() 
+							{	
+								public void 
+								downloadStubEventOccurred(
+									DownloadStubEvent event )
+								{
+									ViewTitleInfoManager.refreshTitleInfo( title_info );
+								}
+							};
+							
+						download_manager.addDownloadStubListener( stub_listener, false );
+						
+						entry.addListener(
+							new MdiCloseListener() {
+								
+								public void 
+								mdiEntryClosed(
+									MdiEntry entry, boolean userClosed) 
+								{
+									download_manager.removeDownloadStubListener( stub_listener );
+								}
+							});
+						
+						entry.addListener(
+								new MdiEntryDropListener()
+								{	
+									public boolean 
+									mdiEntryDrop(
+										MdiEntry 		entry, 
+										Object 			data ) 
+									{
+										if ( data instanceof String ){
+										
+											String str = (String)data;
+											
+											if ( str.startsWith( "DownloadManager\n" )){
+												
+												String[] bits = str.split( "\n" );
+												
+												org.gudy.azureus2.plugins.download.DownloadManager dm = PluginInitializer.getDefaultInterface().getDownloadManager();
+												
+												List<Download> downloads = new ArrayList<Download>();
+												
+												boolean	failed = false;
+												
+												for ( int i=1;i<bits.length;i++ ){
+													
+													byte[]	 hash = Base32.decode( bits[i] );
+													
+													try{
+														Download download = dm.getDownload( hash );
+														
+														if ( download.canStubbify()){
+															
+															downloads.add( download );
+															
+														}else{
+															
+															failed = true;
+														}
+													}catch( Throwable e ){	
+													}
+												}
+																									
+												final boolean f_failed = failed;
+												
+												ManagerUtils.moveToArchive( 
+													downloads, 
+													new ManagerUtils.ArchiveCallback()
+													{
+														boolean error = f_failed;
+														
+														public void
+														failed(
+															DownloadStub		original,
+															Throwable			e )
+														{
+															error = true;
+														}
+														
+														public void
+														completed()
+														{
+															if ( error ){
+																
+																String title 	= MessageText.getString( "archive.failed.title" );
+																String text 	= MessageText.getString( "archive.failed.text" );
+																
+																MessageBoxShell prompter = 
+																	new MessageBoxShell(
+																		title, text, 
+																		new String[] { MessageText.getString("Button.ok") }, 0 );
+																																
+																prompter.setAutoCloseInMS(0);
+																
+																prompter.open( null );
+															}
+														}
+													});
+											}
+											
+											return( true );
+										}
+										
+										return false;
+									}
+								});
+						
+						return entry;
 					}
 				});
+		
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_OPTIONS,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						MdiEntry entry = mdi.createEntryFromEventListener(
+								MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS,
+								TorrentOptionsView.class,
+								MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_OPTIONS, true,
+								null, null);
+						return entry;
+					}
+				});
+		
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_MY_SHARES,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						MdiEntry entry = mdi.createEntryFromEventListener(
+								MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS,
+								MySharesView.class,
+								MultipleDocumentInterface.SIDEBAR_SECTION_MY_SHARES, true,
+								null, null);
+						return entry;
+					}
+				});
+		
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_MY_TRACKER,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						MdiEntry entry = mdi.createEntryFromEventListener(
+								MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS,
+								MyTrackerView.class,
+								MultipleDocumentInterface.SIDEBAR_SECTION_MY_TRACKER, true,
+								null, null);
+						return entry;
+					}
+				});
+		
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_CLIENT_STATS,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						MdiEntry entry = mdi.createEntryFromEventListener(
+								MultipleDocumentInterface.SIDEBAR_HEADER_PLUGINS,
+								ClientStatsView.class,
+								MultipleDocumentInterface.SIDEBAR_SECTION_CLIENT_STATS, true,
+								null, null);
+						return entry;
+					}
+				});
+		
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+				new MdiEntryCreationListener2() {
+
+					public MdiEntry createMDiEntry(MultipleDocumentInterface mdi,
+							String id, Object datasource, Map<?, ?> params) {
+
+						String section = (datasource instanceof String)
+								? ((String) datasource) : null;
+
+						boolean uiClassic = COConfigurationManager.getStringParameter(
+								"ui").equals("az2");
+						if (uiClassic || COConfigurationManager.getBooleanParameter(
+								"Show Options In Side Bar")) {
+  						MdiEntry entry = ((MultipleDocumentInterfaceSWT) mdi).createEntryFromEventListener(
+  								MultipleDocumentInterface.SIDEBAR_HEADER_PLUGINS,
+  								ConfigView.class,
+  								MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG, true, null,
+  								null);
+  						return entry;
+						}
+						
+						ConfigShell.getInstance().open(section);
+						return null;
+					}
+				});
+		
+		try {
+			final ShareManager share_manager = pi.getShareManager();
+			if (share_manager.getShares().length > 0) {
+				mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_MY_SHARES);
+			} else {
+  			share_manager.addListener(new ShareManagerListener() {
+  				
+  				public void resourceModified(ShareResource old_resource,
+  						ShareResource new_resource) {
+  				}
+  				
+  				public void resourceDeleted(ShareResource resource) {
+  				}
+  				
+  				public void resourceAdded(ShareResource resource) {
+  					share_manager.removeListener(this);
+						mdi.loadEntryByID(
+								MultipleDocumentInterface.SIDEBAR_SECTION_MY_SHARES, false);
+  				}
+  				
+  				public void reportProgress(int percent_complete) {
+  				}
+  				
+  				public void reportCurrentTask(String task_description) {
+  				}
+  			});
 			}
+			
+
+		} catch (Throwable t) {
+		}
+		
+		// Load Tracker View on first host of file
+		TRHost trackerHost = AzureusCoreFactory.getSingleton().getTrackerHost();
+		trackerHost.addListener(new TRHostListener() {
+			boolean done = false;
+			
+			public void torrentRemoved(TRHostTorrent t) {
+			}
+			
+			public void torrentChanged(TRHostTorrent t) {
+			}
+			
+			public void torrentAdded(TRHostTorrent t) {
+				if (done) {
+					return;
+				}
+				TRHost trackerHost = AzureusCoreFactory.getSingleton().getTrackerHost();
+				trackerHost.removeListener(this);
+				done = true;
+				mdi.loadEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_MY_TRACKER,
+						false);
+			}
+			
+			public boolean handleExternalRequest(InetSocketAddress client_address,
+					String user, String url, URL absolute_url, String header, InputStream is,
+					OutputStream os, AsyncController async)
+							throws IOException {
+				return false;
+			}
+		});
+
+		UIManager uim = pi.getUIManager();
+		if (uim != null) {
+			MenuItem menuItem = uim.getMenuManager().addMenuItem(
+					MenuManager.MENU_MENUBAR, "tags.view.heading");
+			menuItem.addListener(new MenuItemListener() {
+				public void selected(MenuItem menu, Object target) {
+					UIFunctionsManager.getUIFunctions().getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_TAGS);
+				}
+			});
+
+			menuItem = uim.getMenuManager().addMenuItem(
+					MenuManager.MENU_MENUBAR, "tag.discovery.view.heading");
+			menuItem.addListener(new MenuItemListener() {
+				public void selected(MenuItem menu, Object target) {
+					UIFunctionsManager.getUIFunctions().getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_TAG_DISCOVERY);
+				}
+			});
+
+			menuItem = uim.getMenuManager().addMenuItem(
+					MenuManager.MENU_MENUBAR, "chats.view.heading");
+			menuItem.addListener(new MenuItemListener() {
+				public void selected(MenuItem menu, Object target) {
+					UIFunctionsManager.getUIFunctions().getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_CHAT);
+				}
+			});
+			
+			menuItem = uim.getMenuManager().addMenuItem(
+					MenuManager.MENU_MENUBAR, "archivedlsview.view.heading");
+			menuItem.addListener(new MenuItemListener() {
+				public void selected(MenuItem menu, Object target) {
+					UIFunctionsManager.getUIFunctions().getMDI().showEntryByID(
+							MultipleDocumentInterface.SIDEBAR_SECTION_ARCHIVED_DOWNLOADS );
+				}
+			});
 		}
 
 		//		System.out.println("Activate sidebar " + startTab + " took "
@@ -187,17 +585,25 @@ public class MainMDISetup
 						return entry;
 					}
 				});
-
-		mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_LIBRARY);
-
-		mdi.registerEntry(ConfigView.VIEW_ID, new MdiEntryCreationListener() {
-			public MdiEntry createMDiEntry(String id) {
-				MdiEntry entry = mdi.createEntryFromEventListener(
-						MultipleDocumentInterface.SIDEBAR_HEADER_PLUGINS, new ConfigView(),
-						id, true, null, null);
-				return entry;
+		
+		mdi.registerEntry("Tag\\..*", new MdiEntryCreationListener2() {
+			
+			public MdiEntry createMDiEntry(MultipleDocumentInterface mdi, String id,
+					Object datasource, Map<?, ?> params) {
+				// TODO: auto-open entries will have null datasource and id of:
+				//"Tag." + tag.getTagType().getTagType() + "." + tag.getTagID();
+				
+				if (datasource instanceof Tag) {
+					Tag tag = (Tag) datasource;
+					
+					return SB_Transfers.setupTag(tag);
+				}
+				
+				return null;
 			}
 		});
+
+		mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_LIBRARY);
 	}
 
 	private static void setupSidebarVuzeUI(final MultipleDocumentInterfaceSWT mdi) {
@@ -208,7 +614,6 @@ public class MainMDISetup
 			MultipleDocumentInterface.SIDEBAR_HEADER_VUZE,
 			MultipleDocumentInterface.SIDEBAR_HEADER_DISCOVERY,
 			MultipleDocumentInterface.SIDEBAR_HEADER_DEVICES,
-			MultipleDocumentInterface.SIDEBAR_HEADER_SUBSCRIPTIONS,
 			MultipleDocumentInterface.SIDEBAR_HEADER_DVD,
 			MultipleDocumentInterface.SIDEBAR_HEADER_PLUGINS,
 		};
@@ -251,8 +656,9 @@ public class MainMDISetup
 								UIFunctions uif = UIFunctionsManager.getUIFunctions();
 
 								if (uif != null) {
-
-									uif.openView(UIFunctions.VIEW_CONFIG, "plugins");
+									uif.getMDI().showEntryByID(
+											MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+											"plugins");
 								}
 							}
 						});
@@ -286,18 +692,6 @@ public class MainMDISetup
 		}
 		*/
 
-		if ( COConfigurationManager.getBooleanParameter( "Show Options In Side Bar" )){
-			
-			mdi.registerEntry(ConfigView.VIEW_ID, new MdiEntryCreationListener() {
-				public MdiEntry createMDiEntry(String id) {
-					MdiEntry entry = mdi.createEntryFromEventListener(
-							MultipleDocumentInterface.SIDEBAR_HEADER_PLUGINS, new ConfigView(),
-							id, true, null, null);
-					return entry;
-				}
-			});
-		}
-		
 		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_ABOUTPLUGINS,
 				new MdiEntryCreationListener() {
 					public MdiEntry createMDiEntry(String id) {
@@ -378,14 +772,14 @@ public class MainMDISetup
 					return "image.sidebar.details";
 				}
 
-				DownloadManager manager = SBC_TorrentDetailsView.dataSourceToDownloadManager(ds);
+				DownloadManager manager = DataSourceUtils.getDM(ds);
 				if (manager == null) {
 					return null;
 				}
 
 				if (propertyID == TITLE_TEXT) {
 					if (Utils.isAZ2UI()) {
-						int completed = manager.getStats().getCompleted();
+						int completed = manager.getStats().getPercentDoneExcludingDND();
 						return DisplayFormatters.formatPercentFromThousands(completed)
 								+ " : " + manager.getDisplayName();
 					}
@@ -394,13 +788,13 @@ public class MainMDISetup
 				}
 
 				if (propertyID == TITLE_INDICATOR_TEXT && !Utils.isAZ2UI()) {
-					int completed = manager.getStats().getCompleted();
+					int completed = manager.getStats().getPercentDoneExcludingDND();
 					if (completed != 1000) {
 						return (completed / 10) + "%";
 					}
 				} else if (propertyID == TITLE_INDICATOR_TEXT_TOOLTIP) {
 					String s = "";
-					int completed = manager.getStats().getCompleted();
+					int completed = manager.getStats().getPercentDoneExcludingDND();
 					if (completed != 1000) {
 						s = (completed / 10) + "% Complete\n";
 					}
@@ -422,7 +816,7 @@ public class MainMDISetup
 					// todo: This even work?
 					TableView<?> tv = SelectedContentManager.getCurrentlySelectedTableView();
 					menuTree.setData("TableView", tv);
-					DownloadManager manager = SBC_TorrentDetailsView.dataSourceToDownloadManager(torrentDetailEntry.getDatasource());
+					DownloadManager manager = DataSourceUtils.getDM(torrentDetailEntry.getDatasource());
 					if (manager != null) {
 						menuTree.setData("downloads", new DownloadManager[] {
 							manager
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainMenu.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainMenu.java
index d5b35be..03abe87 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainMenu.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainMenu.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.shells.main;
 
 import org.eclipse.swt.SWT;
@@ -12,20 +30,23 @@ import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.SystemProperties;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager;
+import org.gudy.azureus2.ui.swt.KeyBindings;
+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.*;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UIToolBarManagerImpl;
 
 import com.aelitis.azureus.core.cnetwork.ContentNetwork;
 import com.aelitis.azureus.core.util.FeatureAvailability;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
+import com.aelitis.azureus.ui.skin.SkinConstants;
 import com.aelitis.azureus.ui.swt.feature.FeatureManagerUI;
-import com.aelitis.azureus.ui.swt.shells.RemotePairingWindow;
 import com.aelitis.azureus.ui.swt.skin.SWTSkin;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinUtils;
 import com.aelitis.azureus.ui.swt.views.skin.SBC_PlusFTUX;
@@ -200,9 +221,24 @@ public class MainMenu
 			viewMenu.addListener(SWT.Show, new Listener() {
 				public void handleEvent(Event event) {
 					Utils.disposeSWTObjects(viewMenu.getItems());
-					buildSimpleViewMenu(viewMenu);
+					buildSimpleViewMenu(viewMenu,-1);
 				}
 			});
+			
+				// hack to handle key binding before menu is actually created...
+			
+			final KeyBindings.KeyBindingInfo binding_info = KeyBindings.getKeyBindingInfo( "v3.MainWindow.menu.view." + SkinConstants.VIEWID_PLUGINBAR );
+			
+			if ( binding_info != null ){
+				Display.getDefault().addFilter(SWT.KeyDown, new Listener() {
+					public void handleEvent(Event event) {
+						if (event.keyCode == binding_info.accelerator ){
+							Utils.disposeSWTObjects(viewMenu.getItems());
+							buildSimpleViewMenu(viewMenu, event.keyCode);
+						}
+					}
+				});
+			}
 		} catch (Exception e) {
 			Debug.out("Error creating View Menu", e);
 		}
@@ -213,7 +249,7 @@ public class MainMenu
 	 *
 	 * @since 4.5.0.3
 	 */
-	protected void buildSimpleViewMenu(final Menu viewMenu) {
+	private void buildSimpleViewMenu(final Menu viewMenu, int accelerator) {
 		try {
 			
 			MenuFactory.addMenuItem(viewMenu, SWT.CHECK, PREFIX_V3 + ".view.sidebar",
@@ -225,6 +261,36 @@ public class MainMenu
 							}
 						}
 					});
+			
+			if (COConfigurationManager.getIntParameter("User Mode") > 1) {
+				
+				SWTSkin skin = SWTSkinFactory.getInstance();
+				
+				SWTSkinObject plugin_bar = skin.getSkinObject(SkinConstants.VIEWID_PLUGINBAR);
+				
+				if ( plugin_bar != null ){
+				
+					MenuItem mi = 
+						MainMenu.createViewMenuItem(skin, viewMenu,
+							"v3.MainWindow.menu.view." + SkinConstants.VIEWID_PLUGINBAR,
+							SkinConstants.VIEWID_PLUGINBAR + ".visible",
+							SkinConstants.VIEWID_PLUGINBAR, true, -1);
+					
+					if ( accelerator != -1 && mi.getAccelerator() == accelerator ){
+						
+						Listener[] listeners = mi.getListeners( SWT.Selection );
+						
+						for ( Listener l: listeners ){
+							
+							try{
+								l.handleEvent( null );
+								
+							}catch( Throwable e ){
+							}
+						}
+					}
+				}
+			}
 
 			/////////
 			
@@ -302,10 +368,16 @@ public class MainMenu
 				MenuFactory.addSeparatorMenuItem(viewMenu);
 			}
 
-			MenuFactory.addMenuItem(viewMenu, SWT.RADIO, PREFIX_V3
+				// Ubuntu Unity (14.04) with SWT 4508 crashes when global View menu triggered as it appears
+				// that radio menu items aren't supported
+				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=419729#c9
+			
+			int simple_advanced_menu_type = Constants.isLinux?SWT.CHECK:SWT.RADIO;
+			
+			MenuFactory.addMenuItem(viewMenu, simple_advanced_menu_type, PREFIX_V3
 					+ ".view.asSimpleList", new Listener() {
 				public void handleEvent(Event event) {
-					ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class);
+					UIToolBarManager tb = UIToolBarManagerImpl.getInstance();
 					if (tb != null) {
 						UIToolBarItem item = tb.getToolBarItem("modeBig");
 						if (item != null) {
@@ -316,10 +388,10 @@ public class MainMenu
 					}
 				}
 			});
-			MenuFactory.addMenuItem(viewMenu, SWT.RADIO, PREFIX_V3
+			MenuFactory.addMenuItem(viewMenu, simple_advanced_menu_type, PREFIX_V3
 					+ ".view.asAdvancedList", new Listener() {
 				public void handleEvent(Event event) {
-					ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class);
+					UIToolBarManager tb = UIToolBarManagerImpl.getInstance();
 					if (tb != null) {
 						UIToolBarItem item = tb.getToolBarItem("modeSmall");
 						if (item != null) {
@@ -356,7 +428,7 @@ public class MainMenu
 					MenuItem itemShowAsSimple = MenuFactory.findMenuItem(viewMenu,
 							PREFIX_V3 + ".view.asSimpleList");
 					if (itemShowAsSimple != null) {
-						ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class);
+						UIToolBarManager tb = UIToolBarManagerImpl.getInstance();
 						if (tb != null) {
 							UIToolBarItem item = tb.getToolBarItem("modeBig");
 							long state = item == null ? 0 : item.getState();
@@ -367,7 +439,7 @@ public class MainMenu
 					MenuItem itemShowAsAdv = MenuFactory.findMenuItem(viewMenu, PREFIX_V3
 							+ ".view.asAdvancedList");
 					if (itemShowAsAdv != null) {
-						ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class);
+						UIToolBarManager tb = UIToolBarManagerImpl.getInstance();
 						if (tb != null) {
 							UIToolBarItem item = tb.getToolBarItem("modeSmall");
 							long state = item == null ? 0 : item.getState();
@@ -450,6 +522,7 @@ public class MainMenu
 			MenuFactory.addSeparatorMenuItem(helpMenu);
 			MenuFactory.addCheckUpdateMenuItem(helpMenu);
 			MenuFactory.addBetaMenuItem(helpMenu);
+			MenuFactory.addVoteMenuItem(helpMenu);
 		}
 		
 		if (FeatureManagerUI.enabled) {
@@ -465,6 +538,7 @@ public class MainMenu
 		MenuFactory.addSeparatorMenuItem(helpMenu);
 		MenuFactory.addConfigWizardMenuItem(helpMenu);
 		MenuFactory.addNatTestMenuItem(helpMenu);
+		MenuFactory.addNetStatusMenuItem(helpMenu);
 		MenuFactory.addSpeedTestMenuItem(helpMenu);
 		MenuFactory.addAdvancedHelpMenuItem(helpMenu);
 
@@ -504,36 +578,49 @@ public class MainMenu
 	}
 
 	private void addCommunityMenu() {
-		MenuItem item = MenuFactory.createTopLevelMenuItem(menuBar,
-				MENU_ID_COMMUNITY);
-		Menu communityMenu = item.getMenu();
-
-		MenuFactory.addMenuItem(communityMenu, MENU_ID_COMMUNITY_FORUMS,
-				new Listener() {
-					public void handleEvent(Event e) {
-						Utils.launch(ContentNetworkUtils.getUrl(
-								ConstantsVuze.getDefaultContentNetwork(),
-								ContentNetwork.SERVICE_FORUMS));
-					}
-				});
-
-		MenuFactory.addMenuItem(communityMenu, MENU_ID_COMMUNITY_WIKI,
-				new Listener() {
-					public void handleEvent(Event e) {
-						Utils.launch(ContentNetworkUtils.getUrl(
-								ConstantsVuze.getDefaultContentNetwork(),
-								ContentNetwork.SERVICE_WIKI));
-					}
-				});
+		MenuItem item = MenuFactory.createTopLevelMenuItem(menuBar,	MENU_ID_COMMUNITY);
+		
+		final Menu communityMenu = item.getMenu();
+
+		communityMenu.addListener(
+			SWT.Show, 
+			new Listener() 
+			{
+				public void 
+				handleEvent( Event event) 
+				{
+					Utils.disposeSWTObjects( communityMenu.getItems());
+		
+					MenuFactory.addMenuItem(communityMenu, MENU_ID_COMMUNITY_FORUMS,
+						new Listener() {
+							public void handleEvent(Event e) {
+								Utils.launch(ContentNetworkUtils.getUrl(
+										ConstantsVuze.getDefaultContentNetwork(),
+										ContentNetwork.SERVICE_FORUMS));
+							}
+						});
 
-		MenuFactory.addMenuItem(communityMenu, MENU_ID_COMMUNITY_BLOG,
-				new Listener() {
-					public void handleEvent(Event e) {
-						Utils.launch(ContentNetworkUtils.getUrl(
-								ConstantsVuze.getDefaultContentNetwork(),
-								ContentNetwork.SERVICE_BLOG));
-					}
-				});
+					MenuFactory.addMenuItem(communityMenu, MENU_ID_COMMUNITY_WIKI,
+						new Listener() {
+							public void handleEvent(Event e) {
+								Utils.launch(ContentNetworkUtils.getUrl(
+										ConstantsVuze.getDefaultContentNetwork(),
+										ContentNetwork.SERVICE_WIKI));
+							}
+						});
+			
+					MenuBuildUtils.addChatMenu( communityMenu, MENU_ID_COMMUNITY_CHAT, "General: Help" );
+					
+					MenuFactory.addMenuItem(communityMenu, MENU_ID_COMMUNITY_BLOG,
+						new Listener() {
+							public void handleEvent(Event e) {
+								Utils.launch(ContentNetworkUtils.getUrl(
+										ConstantsVuze.getDefaultContentNetwork(),
+										ContentNetwork.SERVICE_BLOG));
+							}
+						});
+				}
+			});
 	}
 
 	//====================================
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindow.java
index b423ced..d33aa18 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindow.java
@@ -2,20 +2,19 @@
  * Created on Sep 13, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 package com.aelitis.azureus.ui.swt.shells.main;
@@ -71,4 +70,4 @@ MainWindow
 	dispose(
 		boolean for_restart,
 		boolean close_already_in_progress );
-}
\ No newline at end of file
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowDelayStub.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowDelayStub.java
index abcf0de..09dea53 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowDelayStub.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowDelayStub.java
@@ -1,878 +1,933 @@
-/*
- * Created on Sep 13, 2012
- * Created by Paul Gardner
- * 
- * Copyright 2012 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.shells.main;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.torrent.impl.TorrentOpenOptions;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager;
-import org.gudy.azureus2.ui.swt.UIExitUtilsSWT;
-import org.gudy.azureus2.ui.swt.Utils;
-import org.gudy.azureus2.ui.swt.mainwindow.*;
-import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar;
-import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
-import org.gudy.azureus2.ui.swt.plugins.UISWTView;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
-import org.gudy.azureus2.ui.systray.SystemTraySWT;
-
-import com.aelitis.azureus.core.*;
-import com.aelitis.azureus.ui.*;
-import com.aelitis.azureus.ui.common.updater.UIUpdater;
-import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
-import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT;
-
-public class 
-MainWindowDelayStub 
-	implements MainWindow
-{
-	private Display			display;
-	private IUIIntializer	initialiser;
-	
-	private Shell			shell;
-	
-	private AzureusCore		core;
-	private AESemaphore		core_sem = new AESemaphore("");
-	
-	private volatile MainWindow		main_window;
-	
-	private SystemTraySWT	swt_tray;
-	
-	private UIFunctionsSWT	delayed_uif = new UIFunctionsSWTImpl();
-	
-	public
-	MainWindowDelayStub(
-		AzureusCore 			_core, 
-		Display 				_display,
-		IUIIntializer			_uiInitializer )
-	{
-		core		= _core;
-		display		= _display;
-		initialiser	= _uiInitializer;
-		
-		init();
-		
-		core_sem.releaseForever();
-	}
-	
-	public
-	MainWindowDelayStub(
-		Display 		_display, 
-		IUIIntializer 	_uiInitializer )
-	{
-		display		= _display;
-		initialiser	= _uiInitializer;
-		
-		init();
-	}
-	
-	private void
-	init()
-	{		
-		final AESemaphore sem = new AESemaphore( "shell:create" );
-		
-		Utils.execSWTThread(
-			new Runnable()
-			{
-				public void
-				run()
-				{
-					try{
-						shell = new Shell(display, SWT.SHELL_TRIM);
-
-						UIFunctionsManagerSWT.setUIFunctions( delayed_uif );
-						
-						boolean bEnableTray = COConfigurationManager.getBooleanParameter("Enable System Tray");
-
-						if ( bEnableTray ){
-						
-							swt_tray = SystemTraySWT.getTray();
-						}
-						
-						MainHelpers.initTransferBar();
-						
-						if ( initialiser != null ){
-						
-							initialiser.initializationComplete();
-							
-							initialiser.abortProgress();
-						}
-						
-						AERunStateHandler.addListener(
-							new AERunStateHandler.RunStateChangeListener()
-							{
-								private boolean	handled = false;
-								
-								public void 
-								runStateChanged(
-									long run_state )
-								{
-									if ( AERunStateHandler.isDelayedUI() || handled ){
-										
-										return;
-									}
-									
-									handled = true;
-									
-									checkMainWindow();
-								}
-							}, false );
-					}finally{
-						
-						sem.release();
-					}
-				}
-			});
-		
-		sem.reserve();
-	}
-	
-	private void
-	log(
-		String	str )
-	{
-		Debug.out( str );
-	}
-	
-	public void
-	init(
-		AzureusCore		_core )
-	{
-		core	= _core;
-				
-		core_sem.releaseForever();
-	}
-		
-	
-		// barp
-	
-	private interface
-	Fixup
-	{
-		public void
-		fix(
-			MainWindow mw );
-	}
-	
-	private interface
-	Fixup2
-	{
-		public Object
-		fix(
-			MainWindow mw );
-	}
-	
-	private interface
-	Fixup3
-	{
-		public void
-		fix(
-			UIFunctionsSWT uif );
-	}
-	
-	private interface
-	Fixup4
-	{
-		public Object
-		fix(
-			UIFunctionsSWT uif );
-	}
-	
-	private void
-	checkMainWindow()
-	{
-		boolean	activated = false;
-		
-		synchronized( this ){
-			
-			if ( main_window == null ){
-				
-				final AESemaphore wait_sem = new AESemaphore( "cmw" );
-				
-				AzureusCoreLifecycleListener listener = 
-					new AzureusCoreLifecycleAdapter()
-					{
-						public void
-						componentCreated(
-							AzureusCore				core,
-							AzureusCoreComponent	component )
-						{
-							if ( component instanceof UIFunctions ){
-								
-								wait_sem.release();
-							}
-						}
-					};
-					
-				core.addLifecycleListener( listener );
-				
-				main_window = new MainWindowImpl( core, display, null );
-				
-				if ( !wait_sem.reserve( 30*1000 )){
-					
-					Debug.out( "Gave up waiting for UIFunction component to be created" );
-				}
-				
-				activated = true;
-			}
-		}
-		
-		if ( activated ){
-			
-			AERunStateHandler.setResourceMode( AERunStateHandler.RS_ALL_ACTIVE );
-		}
-	}
-	
-	private void
-	fixup(
-		Fixup	f )
-	{
-		core_sem.reserve();
-		
-		checkMainWindow();
-		
-		f.fix( main_window );
-	}
-	
-	private Object
-	fixup(
-		Fixup2	f )
-	{
-		core_sem.reserve();
-		
-		checkMainWindow();
-		
-		return( f.fix( main_window ));
-	}
-	
-	private void
-	fixup(
-		Fixup3	f )
-	{
-		core_sem.reserve();
-					
-		checkMainWindow();
-		
-		UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
-		
-		if ( uif == delayed_uif ){
-			
-			Debug.out( "eh?" );
-			
-		}else{
-			
-			f.fix( uif );
-		}
-	}
-	
-	private Object
-	fixup(
-		Fixup4	f )
-	{
-		core_sem.reserve();
-					
-		checkMainWindow();
-		
-		UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
-		
-		if ( uif == delayed_uif ){
-			
-			Debug.out( "eh?" );
-			
-			return( null );
-			
-		}else{
-			
-			return( f.fix( uif ));
-		}
-	}
-	
-		// toot
-	
-	public Shell
-	getShell()
-	{		
-		return( shell );
-	}
-
-	public IMainMenu 
-	getMainMenu()
-	{
-		return((IMainMenu)fixup( new Fixup2(){public Object fix( MainWindow mw){ return( mw.getMainMenu()); }}));
-	}
-	
-	
-	public IMainStatusBar 
-	getMainStatusBar()
-	{
-		if ( main_window != null ){
-			
-			return( main_window.getMainStatusBar());
-		}
-				
-		return( null );
-	}
-	
-	public boolean
-	isReady()
-	{
-		log( "isReady" );
-		
-		return( false );
-	}
-	
-	public void 
-	setVisible(
-		final boolean visible, 
-		final boolean tryTricks )
-	{
-		fixup( new Fixup(){public void fix( MainWindow mw){ mw.setVisible( visible, tryTricks ); }});
-	}
-	
-	public UISWTInstanceImpl
-	getUISWTInstanceImpl()
-	{
-		log( "getUISWTInstanceImpl" );
-		
-		return( null );
-	}
-
-	public void 
-	setSelectedLanguageItem()
-	{
-		log( "setSelectedLanguageItem" );	
-	}
-	
-	public boolean 
-	dispose(
-		final boolean for_restart,
-		final boolean close_already_in_progress )
-	{
-		if ( main_window != null ){
-			
-			return( main_window.dispose(for_restart, close_already_in_progress));
-		}
-		
-		log( "dispose" );
-		
-		UIExitUtilsSWT.uiShutdown();
-
-		if ( swt_tray != null ){
-			
-			swt_tray.dispose();
-		}
-		
-		try{
-			AllTransfersBar transfer_bar = AllTransfersBar.getBarIfOpen(core.getGlobalManager());
-			
-			if ( transfer_bar != null ){
-				
-				transfer_bar.forceSaveLocation();
-			}
-		}catch( Exception ignore ){
-		}
-
-		if (!SWTThread.getInstance().isTerminated()) {
-			Utils.getOffOfSWTThread(new AERunnable() {
-				public void runSupport() {
-					if (!SWTThread.getInstance().isTerminated()) {
-						SWTThread.getInstance().getInitializer().stopIt( for_restart, false);
-					}
-				}
-			});
-		}
-
-		return true;
-	}
-	
-	
-	
-	public boolean 
-	isVisible(
-		int windowElement)
-	{
-		log( "isVisible" );
-		
-		return( false );	
-	}
-
-	public void 
-	setVisible(
-		int 		windowElement, 
-		boolean 	value )
-	{
-		log( "setVisible" );	
-	}
-
-	public void 
-	setHideAll(
-		boolean hide) 
-	{
-		log( "setHideAll" );	
-	}
-	
-	public Rectangle 
-	getMetrics(
-		int windowElement)
-	{
-		log( "getMetrics" );	
-
-		return( null );
-	}
-	
-	private class
-	UIFunctionsSWTImpl
-		implements UIFunctionsSWT
-	{
-		public void 
-		bringToFront()
-		{	
-			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.bringToFront(); }});
-		}
-
-		public void 
-		bringToFront(
-			final boolean tryTricks)
-		{	
-			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.bringToFront( tryTricks ); }});
-		}
-
-		public void
-		runOnUIThread(
-			final int			ui_type,
-			final Runnable		runnable )
-		{
-			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.runOnUIThread( ui_type, runnable ); }});
-		}
-		
-		public void 
-		refreshLanguage()
-		{	
-			log( "refreshLanguage" );
-		}
-
-		public void 
-		refreshIconBar()
-		{	
-			log( "refreshIconBar" );
-		}
-
-		public void 
-		setStatusText(
-			String string )
-		{	
-		}
-
-		public void 
-		setStatusText(
-			int statustype, 
-			String string, 
-			UIStatusTextClickListener l)
-		{	
-			log( "setStatusText" );
-		}
-
-		public boolean 
-		dispose(
-			boolean for_restart, 
-			boolean close_already_in_progress )
-		{
-			return( MainWindowDelayStub.this.dispose( for_restart, close_already_in_progress ));
-		}
-
-		public boolean 
-		viewURL(
-			String url, 
-			String target, 
-			int w, 
-			int h, 
-			boolean allowResize,
-			boolean isModal)
-		{
-			log( "viewURL" );
-			
-			return( false );
-		}
-
-		public boolean 
-		viewURL(
-			String url, 
-			String target, 
-			double wPct, 
-			double hPct,
-			boolean allowResize, 
-			boolean isModal)
-		{
-			log( "viewURL" );
-			
-			return( false );
-		}
-
-		public void 
-		viewURL(
-			String url, 
-			String target, 
-			String sourceRef)
-		{
-			log( "viewURL" );			
-		}
-
-
-		public UIFunctionsUserPrompter 
-		getUserPrompter(
-			String 		title, 
-			String 		text,
-			String[] 	buttons, 
-			int 		defaultOption)
-		{
-			log( "getUserPrompter" );
-			
-			return( null );
-		}
-
-		public void 
-		promptUser(
-			String title, 
-			String text, 
-			String[] buttons,
-			int defaultOption, 
-			String rememberID, 
-			String rememberText,
-			boolean bRememberByDefault, 
-			int autoCloseInMS, 
-			UserPrompterResultListener l)
-		{
-			log( "promptUser" );
-		}
-		
-
-		public UIUpdater 
-		getUIUpdater()
-		{			
-			return( UIUpdaterSWT.getInstance());
-		}
-
-
-		public void 
-		openView(
-			final int 		viewID, 
-			final Object 	datasource )
-		{
-				// OSX Vuze->Preferences menu
-			
-			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.openView( viewID, datasource ); }});
-		}
-		
-		public void 
-		doSearch(
-			String searchText )
-		{
-			log( "doSearch" );
-		}
-		
-		public void 
-		doSearch(
-			String searchText, 
-			boolean toSubscribe )
-		{
-			log( "doSearch" );
-		}
-
-		public void
-		installPlugin(
-			String			plugin_id,
-			String			resource_prefix,
-			actionListener	listener )
-		{
-			log( "installPlugin" );
-		}
-		
-
-		public void
-		performAction(
-			final int				action_id,
-			final Object			args,
-			final actionListener	listener )
-		{
-				// auto-update restart prompt (for example)
-			
-			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.performAction( action_id, args, listener ); }});
-		}
-		
-		public MultipleDocumentInterface 
-		getMDI()
-		{
-			log( "getMDI" );
-			
-			return( null );
-		}
-
-
-		public void 
-		forceNotify(
-			int iconID, 
-			String title, 
-			String text, 
-			String details,
-			Object[] relatedObjects, 
-			int timeoutSecs)
-		{
-			log( "forceNotify" );
-		}
-		
-		
-		public Shell 
-		getMainShell()
-		{			
-			return( shell );
-		}
-
-
-		public void 
-		addPluginView(
-			String viewID, 
-			UISWTViewEventListener l)
-		{
-			log( "addPluginView" );
-		}
-
-
-		public void 
-		closeDownloadBars()
-		{
-		}
-
-		public boolean 
-		isGlobalTransferBarShown()
-		{
-			if (!AzureusCoreFactory.isCoreRunning()) {
-				return false;
-			}
-			
-			return AllTransfersBar.getManager().isOpen(
-					AzureusCoreFactory.getSingleton().getGlobalManager());
-		}
-
-		public void 
-		showGlobalTransferBar() 
-		{
-			AllTransfersBar.open(getMainShell());
-		}
-
-		public void 
-		closeGlobalTransferBar() 
-		{
-			AllTransfersBar.closeAllTransfersBar();
-		}
-
-
-		public UISWTView[] 
-		getPluginViews()
-		{
-			log( "getPluginViews" );
-			
-			return( new UISWTView[0] );
-		}
-
-
-		public void 
-		openPluginView(
-			String sParentID, 
-			String sViewID,
-			UISWTViewEventListener l, 
-			Object dataSource, 
-			boolean bSetFocus)
-		{
-			log( "openPluginView" );
-		}
-
-		public void 
-		openPluginView(
-			final UISWTViewCore view, 
-			final String name)
-		{
-			log( "openPluginView" );
-		}
-
-
-		public void 
-		removePluginView(
-			String viewID)
-		{
-			log( "removePluginView" );
-		}
-
-
-		public void 
-		closePluginView(
-			UISWTViewCore view)
-		{
-			log( "closePluginView" );
-		}
-
-		public void 
-		closePluginViews(
-			String sViewID )
-		{
-			log( "closePluginViews" );
-		}
-
-		public UISWTInstance 
-		getUISWTInstance()
-		{
-			log( "getUISWTInstance" );
-			
-			return( null );
-		}
-
-		public void 
-		refreshTorrentMenu()
-		{
-			log( "refreshTorrentMenu" );
-		}
-
-		public IMainStatusBar 
-		getMainStatusBar()
-		{			
-			return( null );
-		}
-
-
-		public IMainMenu 
-		createMainMenu(
-			final Shell shell)
-		{
-				// OSX Vuze->About menu
-
-			return((IMainMenu)fixup( new Fixup4(){public Object fix( UIFunctionsSWT uif){ return( uif.createMainMenu( shell )); }}));
-		}
-
-		public IMainWindow 
-		getMainWindow()
-		{
-			return( MainWindowDelayStub.this );
-		}
-
-		public void 
-		closeAllDetails()
-		{
-			log( "closeAllDetails" );
-		}
-
-
-		public boolean 
-		hasDetailViews()
-		{
-			log( "hasDetailViews" );
-			
-			return( false );
-		}
-		
-		public Shell 
-		showCoreWaitDlg()
-		{
-			return( null );
-		}
-		
-		public boolean 
-		isProgramInstalled(
-			final String extension, 
-			final String name ) 
-		{
-			return((Boolean)fixup( new Fixup4(){public Object fix( UIFunctionsSWT uif){ return( uif.isProgramInstalled( extension, name )); }}));
-		}
-		
-		public MultipleDocumentInterfaceSWT 
-		getMDISWT()
-		{
-			log( "getMDISWT" );
-			
-			return( null );
-		}
-
-		public void 
-		promptForSearch()
-		{
-			log( "promptForSearch" );
-		}
-
-		public UIToolBarManager 
-		getToolBarManager()
-		{
-			log( "getToolBarManager" );
-			
-			return( null );
-		}
-		
-		public void
-		openRemotePairingWindow()
-		{
-			log( "openRemotePairingWindow" );
-		}
-		
-		public void
-		playOrStreamDataSource(
-			Object 		ds, 
-			String 		referal,
-			boolean 	launch_already_checked, 
-			boolean 	complete_only )
-		{
-			log( "playOrStreamDataSource" );
-		}
-		
-		public void 
-		setHideAll( 
-			boolean hidden) 
-		{
-			log( "setHideAll" );
-		}
-
-		public boolean addTorrentWithOptions(boolean force,
-				TorrentOpenOptions torrentOptions) {
-			log( "addTorrentWithOptions" );
-			return false;
-		}
-		
-		public void showErrorMessage(String keyPrefix, String details,
-				String[] textParams) {
-			log( "showErrorMessage" );
-		}
-		
-		public void openTorrentOpenOptions(Shell shell, String sPathOfFilesToOpen,
-				String[] sFilesToOpen, boolean defaultToStopped, boolean forceOpen) {
-			log("openTorrentOpenOptions");
-		}
-
-		public void openTorrentWindow() {
-			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.openTorrentWindow(); }});
-		}
-	}
-}
+/*
+ * Created on Sep 13, 2012
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.shells.main;
+
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.torrent.impl.TorrentOpenOptions;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager;
+import org.gudy.azureus2.ui.swt.UIExitUtilsSWT;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.mainwindow.*;
+import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
+import org.gudy.azureus2.ui.systray.SystemTraySWT;
+
+import com.aelitis.azureus.core.*;
+import com.aelitis.azureus.ui.*;
+import com.aelitis.azureus.ui.common.updater.UIUpdater;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
+import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
+import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
+import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
+import com.aelitis.azureus.ui.swt.mdi.TabbedMDI;
+import com.aelitis.azureus.ui.swt.mdi.TabbedMdiInterface;
+import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT;
+
+public class 
+MainWindowDelayStub 
+	implements MainWindow
+{
+	private Display			display;
+	private IUIIntializer	initialiser;
+	
+	private Shell			shell;
+	
+	private AzureusCore		core;
+	private AESemaphore		core_sem = new AESemaphore("");
+	
+	private volatile MainWindow		main_window;
+	
+	private SystemTraySWT	swt_tray;
+	
+	private volatile UIFunctionsSWT	delayed_uif = new UIFunctionsSWTImpl();
+	
+	public
+	MainWindowDelayStub(
+		AzureusCore 			_core, 
+		Display 				_display,
+		IUIIntializer			_uiInitializer )
+	{
+		core		= _core;
+		display		= _display;
+		initialiser	= _uiInitializer;
+		
+		init();
+		
+		core_sem.releaseForever();
+	}
+	
+	public
+	MainWindowDelayStub(
+		Display 		_display, 
+		IUIIntializer 	_uiInitializer )
+	{
+		display		= _display;
+		initialiser	= _uiInitializer;
+		
+		init();
+	}
+	
+	private void
+	init()
+	{		
+		final AESemaphore sem = new AESemaphore( "shell:create" );
+		
+		Utils.execSWTThread(
+			new Runnable()
+			{
+				public void
+				run()
+				{
+					try{
+						shell = new Shell(display, SWT.SHELL_TRIM);
+
+						UIFunctionsManagerSWT.setUIFunctions( delayed_uif );
+						
+						boolean bEnableTray = COConfigurationManager.getBooleanParameter("Enable System Tray");
+
+						if ( bEnableTray ){
+						
+							swt_tray = SystemTraySWT.getTray();
+						}
+						
+						MainHelpers.initTransferBar();
+						
+						if ( initialiser != null ){
+						
+							initialiser.initializationComplete();
+							
+							initialiser.abortProgress();
+						}
+						
+						AERunStateHandler.addListener(
+							new AERunStateHandler.RunStateChangeListener()
+							{
+								private boolean	handled = false;
+								
+								public void 
+								runStateChanged(
+									long run_state )
+								{
+									if ( AERunStateHandler.isDelayedUI() || handled ){
+										
+										return;
+									}
+									
+									handled = true;
+									
+									checkMainWindow();
+								}
+							}, false );
+					}finally{
+						
+						sem.release();
+					}
+				}
+			});
+		
+		sem.reserve();
+	}
+	
+	private void
+	log(
+		String	str )
+	{
+		Debug.out( str );
+	}
+	
+	public void
+	init(
+		AzureusCore		_core )
+	{
+		core	= _core;
+				
+		core_sem.releaseForever();
+	}
+		
+	
+		// barp
+	
+	private interface
+	Fixup
+	{
+		public void
+		fix(
+			MainWindow mw );
+	}
+	
+	private interface
+	Fixup2
+	{
+		public Object
+		fix(
+			MainWindow mw );
+	}
+	
+	private interface
+	Fixup3
+	{
+		public void
+		fix(
+			UIFunctionsSWT uif );
+	}
+	
+	private interface
+	Fixup4
+	{
+		public Object
+		fix(
+			UIFunctionsSWT uif );
+	}
+	
+	private void
+	checkMainWindow()
+	{
+		boolean	activated = false;
+		
+		synchronized( this ){
+			
+			if ( main_window == null ){
+				
+				final AESemaphore wait_sem = new AESemaphore( "cmw" );
+				
+				AzureusCoreLifecycleListener listener = 
+					new AzureusCoreLifecycleAdapter()
+					{
+						public void
+						componentCreated(
+							AzureusCore				core,
+							AzureusCoreComponent	component )
+						{
+							if ( component instanceof UIFunctions ){
+								
+								wait_sem.release();
+							}
+						}
+					};
+					
+				core.addLifecycleListener( listener );
+				
+				main_window = new MainWindowImpl( core, display, null );
+				
+				if ( !wait_sem.reserve( 30*1000 )){
+					
+					Debug.out( "Gave up waiting for UIFunction component to be created" );
+				}
+				
+				activated = true;
+			}
+		}
+		
+		if ( activated ){
+			
+			AERunStateHandler.setResourceMode( AERunStateHandler.RS_ALL_ACTIVE );
+		}
+	}
+	
+	private void
+	fixup(
+		Fixup	f )
+	{
+		core_sem.reserve();
+		
+		checkMainWindow();
+		
+		f.fix( main_window );
+	}
+	
+	private Object
+	fixup(
+		Fixup2	f )
+	{
+		core_sem.reserve();
+		
+		checkMainWindow();
+		
+		return( f.fix( main_window ));
+	}
+	
+	private void
+	fixup(
+		Fixup3	f )
+	{
+		core_sem.reserve();
+					
+		checkMainWindow();
+		
+		UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
+		
+		if ( uif == delayed_uif ){
+			
+			Debug.out( "eh?" );
+			
+		}else{
+			
+			f.fix( uif );
+		}
+	}
+	
+	private Object
+	fixup(
+		Fixup4	f )
+	{
+		core_sem.reserve();
+					
+		checkMainWindow();
+		
+		UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
+		
+		if ( uif == delayed_uif ){
+			
+			Debug.out( "eh?" );
+			
+			return( null );
+			
+		}else{
+			
+			return( f.fix( uif ));
+		}
+	}
+	
+		// toot
+	
+	public Shell
+	getShell()
+	{		
+		return( shell );
+	}
+
+	public IMainMenu 
+	getMainMenu()
+	{
+		return((IMainMenu)fixup( new Fixup2(){public Object fix( MainWindow mw){ return( mw.getMainMenu()); }}));
+	}
+	
+	
+	public IMainStatusBar 
+	getMainStatusBar()
+	{
+		if ( main_window != null ){
+			
+			return( main_window.getMainStatusBar());
+		}
+				
+		return( null );
+	}
+	
+	public boolean
+	isReady()
+	{
+		log( "isReady" );
+		
+		return( false );
+	}
+	
+	public void 
+	setVisible(
+		final boolean visible, 
+		final boolean tryTricks )
+	{
+		fixup( new Fixup(){public void fix( MainWindow mw){ mw.setVisible( visible, tryTricks ); }});
+	}
+	
+	public UISWTInstanceImpl
+	getUISWTInstanceImpl()
+	{
+		log( "getUISWTInstanceImpl" );
+		
+		return( null );
+	}
+
+	public void 
+	setSelectedLanguageItem()
+	{
+		log( "setSelectedLanguageItem" );	
+	}
+	
+	public boolean 
+	dispose(
+		final boolean for_restart,
+		final boolean close_already_in_progress )
+	{
+		if ( main_window != null ){
+			
+			return( main_window.dispose(for_restart, close_already_in_progress));
+		}
+		
+		log( "dispose" );
+		
+		UIExitUtilsSWT.uiShutdown();
+
+		if ( swt_tray != null ){
+			
+			swt_tray.dispose();
+		}
+		
+		try{
+			AllTransfersBar transfer_bar = AllTransfersBar.getBarIfOpen(core.getGlobalManager());
+			
+			if ( transfer_bar != null ){
+				
+				transfer_bar.forceSaveLocation();
+			}
+		}catch( Exception ignore ){
+		}
+
+		if (!SWTThread.getInstance().isTerminated()) {
+			Utils.getOffOfSWTThread(new AERunnable() {
+				public void runSupport() {
+					if (!SWTThread.getInstance().isTerminated()) {
+						SWTThread.getInstance().getInitializer().stopIt( for_restart, false);
+					}
+				}
+			});
+		}
+
+		return true;
+	}
+	
+	
+	
+	public boolean 
+	isVisible(
+		int windowElement)
+	{
+		log( "isVisible" );
+		
+		return( false );	
+	}
+
+	public void 
+	setVisible(
+		int 		windowElement, 
+		boolean 	value )
+	{
+		log( "setVisible" );	
+	}
+
+	public void 
+	setHideAll(
+		boolean hide) 
+	{
+		log( "setHideAll" );	
+	}
+	
+	public Rectangle 
+	getMetrics(
+		int windowElement)
+	{
+		log( "getMetrics" );	
+
+		return( null );
+	}
+	
+	private class
+	UIFunctionsSWTImpl
+		implements UIFunctionsSWT
+	{
+		public void 
+		bringToFront()
+		{	
+			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.bringToFront(); }});
+		}
+
+		public void 
+		bringToFront(
+			final boolean tryTricks)
+		{	
+			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.bringToFront( tryTricks ); }});
+		}
+
+		public int 
+		getVisibilityState() 
+		{
+			UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
+			
+			if ( uif != null && uif != this ){
+				
+				return( uif.getVisibilityState());
+			}
+			
+			return( VS_TRAY_ONLY );
+		}
+		
+		public void
+		runOnUIThread(
+			final int			ui_type,
+			final Runnable		runnable )
+		{
+			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.runOnUIThread( ui_type, runnable ); }});
+		}
+		
+		public void 
+		refreshLanguage()
+		{	
+			log( "refreshLanguage" );
+		}
+
+		public void 
+		refreshIconBar()
+		{	
+			log( "refreshIconBar" );
+		}
+
+		public void 
+		setStatusText(
+			String string )
+		{	
+		}
+
+		public void 
+		setStatusText(
+			int statustype, 
+			String string, 
+			UIStatusTextClickListener l)
+		{	
+			log( "setStatusText" );
+		}
+
+		public boolean 
+		dispose(
+			boolean for_restart, 
+			boolean close_already_in_progress )
+		{
+			return( MainWindowDelayStub.this.dispose( for_restart, close_already_in_progress ));
+		}
+
+		public boolean 
+		viewURL(
+			String url, 
+			String target, 
+			int w, 
+			int h, 
+			boolean allowResize,
+			boolean isModal)
+		{
+			log( "viewURL" );
+			
+			return( false );
+		}
+
+		public boolean 
+		viewURL(
+			String url, 
+			String target, 
+			double wPct, 
+			double hPct,
+			boolean allowResize, 
+			boolean isModal)
+		{
+			log( "viewURL" );
+			
+			return( false );
+		}
+
+		public void 
+		viewURL(
+			String url, 
+			String target, 
+			String sourceRef)
+		{
+			log( "viewURL" );			
+		}
+
+
+		public UIFunctionsUserPrompter 
+		getUserPrompter(
+			String 		title, 
+			String 		text,
+			String[] 	buttons, 
+			int 		defaultOption)
+		{
+			log( "getUserPrompter" );
+			
+			return( null );
+		}
+
+		public void 
+		promptUser(
+			String title, 
+			String text, 
+			String[] buttons,
+			int defaultOption, 
+			String rememberID, 
+			String rememberText,
+			boolean bRememberByDefault, 
+			int autoCloseInMS, 
+			UserPrompterResultListener l)
+		{
+			log( "promptUser" );
+		}
+		
+
+		public UIUpdater 
+		getUIUpdater()
+		{			
+			return( UIUpdaterSWT.getInstance());
+		}
+
+
+		public void 
+		openView(
+			final int 		viewID, 
+			final Object 	datasource )
+		{
+				// OSX Vuze->Preferences menu
+			
+			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.openView( viewID, datasource ); }});
+		}
+		
+		public void 
+		doSearch(
+			String searchText )
+		{
+			log( "doSearch" );
+		}
+		
+		public void 
+		doSearch(
+			String searchText, 
+			boolean toSubscribe )
+		{
+			log( "doSearch" );
+		}
+
+		public void
+		installPlugin(
+			String			plugin_id,
+			String			resource_prefix,
+			actionListener	listener )
+		{
+			log( "installPlugin" );
+		}
+		
+
+		public void
+		performAction(
+			final int				action_id,
+			final Object			args,
+			final actionListener	listener )
+		{
+				// auto-update restart prompt (for example)
+			
+			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.performAction( action_id, args, listener ); }});
+		}
+		
+		public MultipleDocumentInterface 
+		getMDI()
+		{
+			log( "getMDI" );
+			
+			return( null );
+		}
+
+
+		public void 
+		forceNotify(
+			int iconID, 
+			String title, 
+			String text, 
+			String details,
+			Object[] relatedObjects, 
+			int timeoutSecs)
+		{
+			log( "forceNotify" );
+		}
+		
+		
+		public Shell 
+		getMainShell()
+		{			
+			return( shell );
+		}
+
+
+		public void 
+		addPluginView(
+			String viewID, 
+			UISWTViewEventListener l)
+		{
+			log( "addPluginView" );
+		}
+
+
+		public void 
+		closeDownloadBars()
+		{
+		}
+
+		public boolean 
+		isGlobalTransferBarShown()
+		{
+			if (!AzureusCoreFactory.isCoreRunning()) {
+				return false;
+			}
+			
+			return AllTransfersBar.getManager().isOpen(
+					AzureusCoreFactory.getSingleton().getGlobalManager());
+		}
+
+		public void 
+		showGlobalTransferBar() 
+		{
+			AllTransfersBar.open(getMainShell());
+		}
+
+		public void 
+		closeGlobalTransferBar() 
+		{
+			AllTransfersBar.closeAllTransfersBar();
+		}
+
+
+		public UISWTView[] 
+		getPluginViews()
+		{
+			log( "getPluginViews" );
+			
+			return( new UISWTView[0] );
+		}
+
+
+		public void 
+		openPluginView(
+			String sParentID, 
+			String sViewID,
+			UISWTViewEventListener l, 
+			Object dataSource, 
+			boolean bSetFocus)
+		{
+			log( "openPluginView" );
+		}
+
+		public void 
+		openPluginView(
+			final UISWTViewCore view, 
+			final String name)
+		{
+			log( "openPluginView" );
+		}
+
+
+		public void 
+		removePluginView(
+			String viewID)
+		{
+			log( "removePluginView" );
+		}
+
+
+		public void 
+		closePluginView(
+			UISWTViewCore view)
+		{
+			log( "closePluginView" );
+		}
+
+		public void 
+		closePluginViews(
+			String sViewID )
+		{
+			log( "closePluginViews" );
+		}
+
+		public UISWTInstance 
+		getUISWTInstance()
+		{
+			log( "getUISWTInstance" );
+			
+			return( null );
+		}
+
+		public void 
+		refreshTorrentMenu()
+		{
+			log( "refreshTorrentMenu" );
+		}
+
+		public IMainStatusBar 
+		getMainStatusBar()
+		{			
+			return( null );
+		}
+
+
+		public IMainMenu 
+		createMainMenu(
+			final Shell shell)
+		{
+				// OSX Vuze->About menu
+
+			return((IMainMenu)fixup( new Fixup4(){public Object fix( UIFunctionsSWT uif){ return( uif.createMainMenu( shell )); }}));
+		}
+
+		public IMainWindow 
+		getMainWindow()
+		{
+			return( MainWindowDelayStub.this );
+		}
+
+		public void 
+		closeAllDetails()
+		{
+			log( "closeAllDetails" );
+		}
+
+
+		public boolean 
+		hasDetailViews()
+		{
+			log( "hasDetailViews" );
+			
+			return( false );
+		}
+		
+		public Shell 
+		showCoreWaitDlg()
+		{
+			return( null );
+		}
+		
+		public boolean 
+		isProgramInstalled(
+			final String extension, 
+			final String name ) 
+		{
+			return((Boolean)fixup( new Fixup4(){public Object fix( UIFunctionsSWT uif){ return( uif.isProgramInstalled( extension, name )); }}));
+		}
+		
+		public MultipleDocumentInterfaceSWT 
+		getMDISWT()
+		{
+			log( "getMDISWT" );
+			
+			return( null );
+		}
+
+		public void 
+		promptForSearch()
+		{
+			log( "promptForSearch" );
+		}
+
+		public UIToolBarManager 
+		getToolBarManager()
+		{
+			log( "getToolBarManager" );
+			
+			return( null );
+		}
+		
+		public void
+		openRemotePairingWindow()
+		{
+			log( "openRemotePairingWindow" );
+		}
+		
+		public void
+		playOrStreamDataSource(
+			Object 		ds, 
+			String 		referal,
+			boolean 	launch_already_checked, 
+			boolean 	complete_only )
+		{
+			log( "playOrStreamDataSource" );
+		}
+		
+		public void 
+		setHideAll( 
+			boolean hidden) 
+		{
+			log( "setHideAll" );
+		}
+
+		public void 
+		showErrorMessage(
+			String 		keyPrefix, 
+			String 		details,
+			String[] 	textParams) 
+		{
+			log( "showErrorMessage" );
+		}
+		
+		// @see com.aelitis.azureus.ui.UIFunctions#showCreateTagDialog(org.gudy.azureus2.ui.swt.views.utils.TagUIUtils.TagReturner)
+		public void showCreateTagDialog(
+				TagReturner tagReturner) 
+		{
+			log( "showAddTagDialog" );
+		}
+
+		public boolean 
+		addTorrentWithOptions(
+			final boolean 				force,
+			final TorrentOpenOptions 	torrentOptions) 
+		{
+			return((Boolean)fixup( new Fixup4(){public Object fix( UIFunctionsSWT uif){ return( uif.addTorrentWithOptions( force, torrentOptions )); }}));
+		}
+				
+		public void 
+		openTorrentOpenOptions(
+			final Shell shell, 
+			final String sPathOfFilesToOpen,
+			final String[] sFilesToOpen, 
+			final boolean defaultToStopped, 
+			final boolean forceOpen) 
+		{
+			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.openTorrentOpenOptions( shell, sPathOfFilesToOpen, sFilesToOpen, defaultToStopped, forceOpen);}});
+		}
+
+		public void 
+		openTorrentOpenOptions(
+			final Shell 				shell,
+			final String 				sPathOfFilesToOpen, 
+			final String[] 				sFilesToOpen,
+			final Map<String, Object> 	options ) 
+		{
+			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.openTorrentOpenOptions( shell, sPathOfFilesToOpen, sFilesToOpen, options);}});
+		}
+		
+		public void 
+		openTorrentWindow() 
+		{
+			fixup( new Fixup3(){public void fix( UIFunctionsSWT uif){ uif.openTorrentWindow(); }});
+		}
+		
+		/* (non-Javadoc)
+		 * @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#createTabbedMDI(org.eclipse.swt.widgets.Composite)
+		 */
+		public TabbedMdiInterface createTabbedMDI(Composite parent, String id) {
+			log( "createTabbedMDI" );
+			return null;
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowFactory.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowFactory.java
index ec82d4a..08e2826 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowFactory.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowFactory.java
@@ -2,20 +2,19 @@
  * Created on Sep 13, 2012
  * Created by Paul Gardner
  * 
- * Copyright 2012 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.
- * 
+ * Copyright (C) Azureus Software, 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowImpl.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowImpl.java
index f58704d..b5c27d7 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowImpl.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/MainWindowImpl.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 29, 2006 2:07:38 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.shells.main;
 
@@ -26,11 +23,12 @@ import java.util.*;
 import java.util.List;
 
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
 import org.eclipse.swt.events.*;
 import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.layout.FormData;
 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.ConfigurationChecker;
@@ -52,6 +50,7 @@ import org.gudy.azureus2.plugins.sharing.ShareManager;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
 import org.gudy.azureus2.ui.swt.*;
 import org.gudy.azureus2.ui.swt.associations.AssociationChecker;
+import org.gudy.azureus2.ui.swt.components.shell.ShellManager;
 import org.gudy.azureus2.ui.swt.config.wizard.ConfigureWizard;
 import org.gudy.azureus2.ui.swt.debug.ObfusticateImage;
 import org.gudy.azureus2.ui.swt.debug.ObfusticateShell;
@@ -382,46 +381,8 @@ public class MainWindowImpl
 		
 		if (!Constants.isSafeMode) {
 			
-			if (core.getTrackerHost().getTorrents().length > 0) {
-				Utils.execSWTThreadLater(0, new Runnable() {
-					public void run() {
-						uiFunctions.openView(UIFunctions.VIEW_MYTRACKER, null);
-					}
-				});
-			}
-
-			// share manager init is async so we need to deal with this
-			PluginInterface default_pi = PluginInitializer.getDefaultInterface();
-			try {
-				final ShareManager share_manager = default_pi.getShareManager();
-
-				default_pi.addListener(new PluginListener() {
-					public void initializationComplete() {
-					}
-
-					public void closedownInitiated() {
-						int share_count = share_manager.getShares().length;
-						COConfigurationManager.setParameter("GUI_SWT_share_count_at_close",
-								share_count);
-					}
-
-					public void closedownComplete() {
-					}
-				});
-
-				if (share_manager.getShares().length > 0
-						|| COConfigurationManager.getIntParameter("GUI_SWT_share_count_at_close") > 0) {
-
-					Utils.execSWTThreadLater(0, new Runnable() {
-						public void run() {
-							uiFunctions.openView(UIFunctions.VIEW_MYSHARES, null);
-						}
-					});
-				}
-			} catch (ShareException e) {
-				Debug.out(e);
-			}
-			
+			// We used to open up share view here.  Moved to MainMDISetup.. param not used now
+			COConfigurationManager.removeParameter("GUI_SWT_share_count_at_close");
 			
 			MainHelpers.initTransferBar();
 			
@@ -586,12 +547,6 @@ public class MainWindowImpl
 				}
 			});
 			
-			try {
-				PlatformDevicesMessenger.setupDeviceSender();
-			} catch (Exception e) {
-				Debug.out("failed to setup device sender ", e);
-			}
-
 			increaseProgress(uiInitializer, "v3.splash.initSkin");
 
 			skin = SWTSkinFactory.getInstance();
@@ -1176,12 +1131,13 @@ public class MainWindowImpl
 		if (disposedOrDisposing) {
 			return true;
 		}
-		return Utils.execSWTThreadWithBool("v3.MainWindow.dispose",
+		Boolean b = Utils.execSWTThreadWithBool("v3.MainWindow.dispose",
 				new AERunnableBoolean() {
 					public boolean runSupport() {
 						return _dispose(for_restart, close_already_in_progress);
 					}
 				});
+		return b == null || b;
 	}
 
 	private boolean _dispose(final boolean bForRestart, boolean bCloseAlreadyInProgress) {
@@ -1412,6 +1368,26 @@ public class MainWindowImpl
 				System.out.println("---------SHOWN AT " + SystemTime.getCurrentTime()
 						+ ";" + (SystemTime.getCurrentTime() - Initializer.startTime)
 						+ "ms");
+				
+					// bring back and stand-alone shells 
+				
+				ShellManager.sharedManager().performForShells(
+						new Listener()
+						{
+							public void 
+							handleEvent(
+								Event event) 
+							{
+								Shell this_shell = (Shell)event.widget;
+								
+								if ( this_shell.getParent() == null && !this_shell.isVisible()){
+								
+									this_shell.setVisible( true );
+									
+									this_shell.moveAbove( shell );
+								}
+							}
+						});
 			}
 		});
 
@@ -1514,7 +1490,7 @@ public class MainWindowImpl
 		
 		if ( run_speed_test ){
 
-			SpeedTestSelector.runMLABTest(false,
+			SpeedTestSelector.runMLABTest(
 				new AERunnable() 
 				{
 					public void 
@@ -1742,6 +1718,23 @@ public class MainWindowImpl
 		COConfigurationManager.setParameter("window.maximized",
 				shell.getMaximized());
 		shell.setVisible(false);
+		
+		ShellManager.sharedManager().performForShells(
+			new Listener()
+			{
+				public void 
+				handleEvent(
+					Event event) 
+				{
+					Shell shell = (Shell)event.widget;
+					
+					if ( shell.getParent() == null ){
+						
+						shell.setVisible( false );
+					}
+				}
+			});
+		
 		MiniBarManager.getManager().setAllVisible(true);
 	}
 
@@ -1847,14 +1840,152 @@ public class MainWindowImpl
 			Menu topbarMenu = new Menu(shell, SWT.POP_UP);
 
 			if (COConfigurationManager.getIntParameter("User Mode") > 1) {
-				MainMenu.createViewMenuItem(skin, topbarMenu,
+				MenuItem mi = 
+					MainMenu.createViewMenuItem(skin, topbarMenu,
 						"v3.MainWindow.menu.view." + SkinConstants.VIEWID_PLUGINBAR,
 						SkinConstants.VIEWID_PLUGINBAR + ".visible",
 						SkinConstants.VIEWID_PLUGINBAR, true, -1);
+				
+				if ( Utils.isAZ2UI()){
+					
+						// remove any accelerator as it doesn't work on this menu and we don't have a View menu entry
+					
+					String str = mi.getText();
+					
+					int pos = str.indexOf( "\t" );
+					
+					if ( pos != -1 ){
+						
+						str = str.substring(0,pos).trim();
+						
+						mi.setText( str );
+					}
+					
+					mi.setAccelerator( SWT.NULL );
+				}
 			}
 
 			new MenuItem(topbarMenu, SWT.SEPARATOR);
 			
+			final MenuItem itemClipMon = new MenuItem(topbarMenu, SWT.CHECK );
+			Messages.setLanguageText(itemClipMon,
+					"label.monitor.clipboard");
+			itemClipMon.addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					COConfigurationManager.setParameter( "Monitor Clipboard For Torrents", itemClipMon.getSelection());
+				}
+			});
+			
+			boolean enabled = COConfigurationManager.getBooleanParameter( "Monitor Clipboard For Torrents" );
+			itemClipMon.setSelection( enabled );
+			
+			COConfigurationManager.addAndFireParameterListener(
+				"Monitor Clipboard For Torrents",
+				new ParameterListener() {
+					
+					private volatile 	AEThread2 monitor_thread;
+					private Clipboard 	clipboard;
+					
+					private String		last_text;
+					
+					public void parameterChanged(String parameterName){
+						
+						boolean enabled = COConfigurationManager.getBooleanParameter( parameterName );
+						
+						if ( enabled ){
+							
+							if ( clipboard == null ){
+								
+								clipboard = new Clipboard(Display.getDefault());
+							}
+							
+							if ( monitor_thread == null ){
+								
+								final AEThread2 new_thread[] = {null};
+								
+								monitor_thread = new_thread[0] = new
+									AEThread2( "Clipboard Monitor")
+									{
+										public void 
+										run() 
+										{
+											Runnable checker = 
+												new Runnable() 
+												{	
+													public void 
+													run() 
+													{
+														if ( monitor_thread != new_thread[0] || clipboard == null ){
+															
+															return;
+														}
+														
+														String text = (String)clipboard.getContents(TextTransfer.getInstance());
+																												
+														if ( text != null && text.length() <= 2048 ){
+															
+															if ( last_text == null || !last_text.equals( text )){
+																
+																last_text = text;
+																
+																addTorrentsFromClipboard( text );
+															}
+														}	
+													}
+												};
+												
+											while( true ){
+												
+												try{
+													
+													Utils.execSWTThread( checker );
+														
+												}catch( Throwable e ){
+													
+													Debug.out( e );
+													
+												}finally{
+													
+													if ( monitor_thread != new_thread[0] ){
+														
+														break;
+														
+													}else{
+														
+														try{	
+															Thread.sleep(500);
+															
+														}catch( Throwable e ){
+															
+															Debug.out( e );
+															
+															break;
+														}
+													}
+												}
+											}
+										}
+									};
+									
+								monitor_thread.start();
+							}
+						}else{
+							
+							monitor_thread 	= null;
+							last_text		= null;
+							
+							if ( clipboard != null ){
+								
+								clipboard.dispose();
+								
+								clipboard = null;
+							}
+						}
+					}
+				});
+			
+			new MenuItem(topbarMenu, SWT.SEPARATOR);
+			
 			final MenuItem itemExport = new MenuItem(topbarMenu, SWT.PUSH);
 			Messages.setLanguageText(itemExport,
 					"search.export.all");
@@ -1935,6 +2066,59 @@ public class MainWindowImpl
 		}
 	}
 
+	private void
+	addTorrentsFromClipboard(
+		String		text )
+	{
+		final String[] splitters = {
+				"\r\n",
+				"\n",
+				"\r",
+				"\t"
+			};
+
+		String[] lines = null;
+		
+		for (int i = 0; i < splitters.length; i++){
+			if (text.indexOf(splitters[i]) >= 0) {
+				lines = text.split(splitters[i]);
+				break;
+			}
+		}
+		
+		if ( lines == null ){
+			
+			lines = new String[]{ text };
+		}
+	
+		for ( int i=0; i<lines.length; i++ ){
+			
+			String line = lines[i].trim();
+			
+			if ( line.startsWith("\"") && line.endsWith("\"")){
+				
+				if (line.length() < 3){
+					
+					line = "";
+					
+				}else{
+					
+					line = line.substring(1, line.length() - 2);
+				}
+			}
+
+			if ( UrlUtils.isURL( line )){
+				
+				Map<String,Object>	options = new HashMap<String, Object>();
+				
+				options.put( UIFunctions.OTO_HIDE_ERRORS, true );
+				
+				TorrentOpener.openTorrent( line, options );
+			}
+		}
+	}
+	
+	
 	/**
 	 * @param skinObject
 	 */
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/UIFunctionsImpl.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/UIFunctionsImpl.java
index 7729061..a9ca659 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/UIFunctionsImpl.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/main/UIFunctionsImpl.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jul 13, 2006 6:15:55 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,15 +13,13 @@
  * 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.shells.main;
 
 import java.io.File;
-import java.lang.reflect.Constructor;
+import java.net.URL;
 import java.util.Locale;
+import java.util.Map;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.PaintEvent;
@@ -40,7 +38,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.torrent.TOTorrent;
-import org.gudy.azureus2.core3.torrent.TOTorrentException;
 import org.gudy.azureus2.core3.torrent.impl.TorrentOpenOptions;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.plugins.ui.UIInputReceiver;
@@ -54,24 +51,20 @@ import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.mainwindow.*;
 import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar;
 import org.gudy.azureus2.ui.swt.minibar.MiniBarManager;
-import org.gudy.azureus2.ui.swt.plugins.*;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
+import org.gudy.azureus2.ui.swt.pluginsimpl.*;
 import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
 import org.gudy.azureus2.ui.swt.shells.MessageSlideShell;
 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 com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.cnetwork.ContentNetwork;
-import com.aelitis.azureus.core.tag.Tag;
 import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
 import com.aelitis.azureus.ui.*;
 import com.aelitis.azureus.ui.common.table.TableView;
 import com.aelitis.azureus.ui.common.updater.UIUpdater;
-import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
 import com.aelitis.azureus.ui.mdi.MdiEntry;
 import com.aelitis.azureus.ui.mdi.MdiEntryOpenListener;
 import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
@@ -82,6 +75,8 @@ import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 import com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry;
 import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
+import com.aelitis.azureus.ui.swt.mdi.TabbedMDI;
+import com.aelitis.azureus.ui.swt.mdi.TabbedMdiInterface;
 import com.aelitis.azureus.ui.swt.plugininstall.SimplePluginInstaller;
 import com.aelitis.azureus.ui.swt.search.SearchHandler;
 import com.aelitis.azureus.ui.swt.shells.BrowserWindow;
@@ -92,6 +87,7 @@ import com.aelitis.azureus.ui.swt.skin.*;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter;
 import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT;
 import com.aelitis.azureus.ui.swt.utils.ColorCache;
+import com.aelitis.azureus.ui.swt.utils.TagUIUtilsV3;
 import com.aelitis.azureus.ui.swt.views.skin.*;
 import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog.SkinnedDialogClosedListener;
 import com.aelitis.azureus.ui.swt.views.skin.sidebar.SideBar;
@@ -176,6 +172,55 @@ public class UIFunctionsImpl
 		});
 	}
 
+	public int 
+	getVisibilityState() 
+	{
+		final Shell shell = getMainShell();
+		
+		if ( shell == null ){
+			
+			return( VS_MINIMIZED_TO_TRAY );		// not sure about this
+			
+		}else{
+			
+			final int[] result = { VS_MINIMIZED_TO_TRAY };
+			
+			final AESemaphore sem = new AESemaphore( "getVisibilityState" );
+			
+			if (
+				Utils.execSWTThread(
+					new AERunnable() 
+					{
+						public void 
+						runSupport() 
+						{
+							try{
+								if ( !shell.isVisible()){
+									
+									result[0] = VS_MINIMIZED_TO_TRAY;
+									
+								}else if ( shell.getMinimized()){
+									
+									result[0] = VS_MINIMIZED;
+									
+								}else{
+									
+									result[0] = VS_ACTIVE;
+								}
+							}finally{
+								
+								sem.release();
+							}
+						}
+					})){
+			
+				sem.reserve( 30*1000 );	// shouldn't block as if this is SWT thread code will run immediately, otherwise SWT thread shoudl be quick
+			}
+			
+			return( result[0] );
+		}
+	}
+	
 	// @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#closeDownloadBars()
 	public void closeDownloadBars() {
 		try {
@@ -270,26 +315,6 @@ public class UIFunctionsImpl
 		return null;
 	}
 
-	/* (non-Javadoc)
-	 * @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#openPluginView(org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore, java.lang.String)
-	 */
-	public void openPluginView(UISWTViewCore view, String name) {
-		try {
-			MultipleDocumentInterfaceSWT mdi = getMDISWT();
-			if (mdi == null) {
-				return;
-			}
-			if (mdi.createEntryFromView(
-					MultipleDocumentInterface.SIDEBAR_HEADER_PLUGINS, view, name, null,
-					true, true, true) != null) {
-				return;
-			}
-		} catch (Exception e) {
-			Logger.log(new LogEvent(LOGID, "openPluginView", e));
-		}
-
-	}
-
 	// @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#openPluginView(java.lang.String, java.lang.String, org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener, java.lang.Object, boolean)
 	public void openPluginView(String sParentID, String sViewID,
 			UISWTViewEventListener l, Object dataSource, boolean bSetFocus) {
@@ -402,184 +427,25 @@ public class UIFunctionsImpl
 		return mainWindow.getMainStatusBar();
 	}
 	
-	// @see com.aelitis.azureus.ui.UIFunctions#showConfig(java.lang.String)
-	public boolean showConfig(String section) {
-		try {
-			boolean uiClassic = COConfigurationManager.getStringParameter("ui").equals("az2");
-			if (uiClassic || COConfigurationManager.getBooleanParameter( "Show Options In Side Bar" )) {
-				openView(SideBar.SIDEBAR_HEADER_PLUGINS, ConfigView.class, null, section, true);
-			} else {
-				ConfigShell.getInstance().open(section);
-			}
-			return true;
-
-		} catch (Exception e) {
-			Logger.log(new LogEvent(LOGID, "showConfig", e));
-		}
-
-		return false;
-	}
-
+	// BurnPlugin uses this for VIEW_CONFIG
+	// RCM uses VIEW_MYTORRENTS and VIEW_CONFIG and VIEW_DM_DETAILS
+	@Deprecated
 	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) {
-		switch (viewID) {
-			case VIEW_CONSOLE:
-				openView(SideBar.SIDEBAR_HEADER_PLUGINS, LoggerView.class,
-						null, data, true);
-				break;
-
-			case VIEW_ALLPEERS:
-				openView(SideBar.SIDEBAR_HEADER_TRANSFERS, PeersSuperView.class,
-						null, data, true);
-				break;
-
-			case VIEW_PEERS_STATS:
-				openView(SideBar.SIDEBAR_HEADER_PLUGINS, ClientStatsView.class,
-						null, data, true);
-				break;
-
-			case VIEW_CONFIG:
-				showConfig((data instanceof String) ? (String) data : null);
-				break;
-
-			case VIEW_DM_DETAILS: {
-				String id = SideBar.SIDEBAR_TORRENT_DETAILS_PREFIX;
-				if (data instanceof DownloadManager) {
-					DownloadManager dm = (DownloadManager) data;
-					TOTorrent torrent = dm.getTorrent();
-					if (torrent != null) {
-						try {
-							id += torrent.getHashWrapper().toBase32String();
-						} catch (TOTorrentException e) {
-							e.printStackTrace();
-						}
-					}
-				}
-				
-				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-				if (mdi != null) {
-					mdi.loadEntryByID(id, true, false, data);
-				}
-			}
-				break;
-
-			case VIEW_DM_MULTI_OPTIONS:
-				openView(SideBar.SIDEBAR_HEADER_TRANSFERS,
-						TorrentOptionsView.class, null, data, true);
-				break;
-
-			case VIEW_MYSHARES:
-				openView(SideBar.SIDEBAR_HEADER_TRANSFERS,
-						MySharesView.class, null, data, true);
-				break;
-
-			case VIEW_MYTORRENTS: {
-				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-				if (mdi != null) {
-					mdi.showEntryByID(SideBar.SIDEBAR_SECTION_LIBRARY);
-				}
-			}
-				break;
-
-			case VIEW_MYTRACKER:
-				openView(SideBar.SIDEBAR_HEADER_TRANSFERS, MyTrackerView.class,
-						null, data, true);
-				break;
-
-			case VIEW_TAGS_OVERVIEW:{
-				
-				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-				
-				if ( mdi != null ){
-
-					mdi.showEntryByID( MultipleDocumentInterface.SIDEBAR_SECTION_TAGS);
-				}
-				
-				break;
-			}
-			case VIEW_TAG: {
-				
-				if ( data instanceof Tag ){
-					
-					Tag tag = (Tag)data;
-					
-					String id = "Tag." + tag.getTagType().getTagType() + "." + tag.getTagID();
-					
-					MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-					
-					if ( mdi != null ){
-						
-						mdi.loadEntryByID(id, true, false, data);
-					}
-				}
-				break;
-			}
-			default:
-				break;
+		MultipleDocumentInterface mdi = getMDI();
+		if (viewID == VIEW_CONFIG) {
+			mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG, data);
+		} else if (viewID == VIEW_DM_DETAILS) {
+			mdi.showEntryByID(
+					MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS, data);
+		} else if (viewID == VIEW_MYTORRENTS) {
+			mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_LIBRARY,
+					data);
+		} else {
+			System.err.println(
+					"DEPRECATED -- Use getMDI().showEntryByID(" + viewID + "..)");
 		}
 	}
-
-	private void openView(final String parentID,
-			final Class<? extends UISWTViewEventListener> cla, String id,
-			final Object data, final boolean closeable) {
-		final MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
-		if (mdi == null) {
-			return;
-		}
-
-		if (id == null) {
-			id = cla.getName();
-			int i = id.lastIndexOf('.');
-			if (i > 0) {
-				id = id.substring(i + 1);
-			}
-		}
-
-		UISWTViewCore viewFromID = mdi.getCoreViewFromID(id);
-		if (viewFromID != null) {
-			viewFromID.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, data);
-			mdi.showEntryByID(id);
-		}
-
-		final String _id = id;
-		Utils.execSWTThreadLater(0, new AERunnable() {
-
-			public void runSupport() {
-				if (mdi.showEntryByID(_id)) {
-					return;
-				}
-				UISWTViewEventListener l = null;
-				try {
-					Constructor<?> constructor = cla.getConstructor(new Class[] {
-						data.getClass()
-					});
-					l = (UISWTViewEventListener) constructor.newInstance(new Object[] {
-						data
-					});
-				} catch (Exception e) {
-				}
-
-				try {
-					if (l == null) {
-						l = cla.newInstance();
-					}
-					mdi.createEntryFromEventListener(parentID, l, _id, closeable,
-							data, null );
-				} catch (Exception e) {
-					Debug.out(e);
-				}
-				mdi.showEntryByID(_id);
-			}
-		});
-
-	}
+		
 	public UISWTInstance getUISWTInstance() {
 		UISWTInstanceImpl impl = mainWindow.getUISWTInstanceImpl();
 		if (impl == null) {
@@ -1019,12 +885,53 @@ public class UIFunctionsImpl
 		
 		if ( hit == null ){
 			
+			try{
+				File f = new File( str );
+			
+				if ( f.isFile()){
+				
+					String name = f.getName().toLowerCase();
+					
+					if ( name.endsWith( ".torrent" ) || name.endsWith( ".vuze" )){
+						
+						UIFunctionsSWT uif = UIFunctionsManagerSWT.getUIFunctionsSWT();
+			    		
+						if ( uif != null ){
+							
+			    			uif.openTorrentOpenOptions(
+			    				null, null, new String[] { f.getAbsolutePath() },
+			    				false, false);
+			    		
+			    			return( true );
+						}
+					}
+				}
+			}catch( Throwable e ){
+			}
+			
 			return( false );
 		}
 		
+		try{
+				// if it is just a trivial URL (no path/query) then most unlikely to refer to
+				// a torrent file so just launch the URL
+			
+			URL url = new URL( hit );
+			
+			String path = url.getPath();
+			
+			if (( path.length() == 0 || path.equals( "/" )) && url.getQuery() == null ){
+				
+				Utils.launch( url.toExternalForm());
+				
+				return( true );
+			}
+		}catch( Throwable e ){
+		}
+		
 		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
 		
-		new FileDownloadWindow( uiFunctions.getMainShell(), str, null, null, true );
+		new FileDownloadWindow( uiFunctions.getMainShell(), hit, null, null, true );
 			
 		return( true );
 	}
@@ -1106,11 +1013,7 @@ public class UIFunctionsImpl
 	}
 
 	public UIToolBarManager getToolBarManager() {
-		Object tb = SkinViewManager.getByClass(ToolBarView.class);
-		if (tb instanceof UIToolBarManager) {
-			return (UIToolBarManager) tb;
-		}
-		return null;
+		return UIToolBarManagerImpl.getInstance();
 	}
 	
 	public void
@@ -1186,20 +1089,29 @@ public class UIFunctionsImpl
 						boolean can_merge = TorrentUtils.canMergeAnnounceURLs(
 								torrentOptions.getTorrent(), fExistingDownload.getTorrent());
 
+						long	existed_for = SystemTime.getCurrentTime() - fExistingDownload.getCreationTime();
+
 						Shell mainShell = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell();
 
 						if ((Display.getDefault().getActiveShell() == null
 								|| !mainShell.isVisible() || mainShell.getMinimized())
 								&& (!can_merge)) {
 
-							new MessageSlideShell(Display.getCurrent(), SWT.ICON_INFORMATION,
-									MSG_ALREADY_EXISTS, null, new String[] {
-										":" + torrentOptions.sOriginatingLocation,
-										fExistingName,
-										MessageText.getString(MSG_ALREADY_EXISTS_NAME),
-									}, new Object[] {
-										fExistingDownload
-									}, -1);
+							
+								// seems we're getting some double additions (linux user reported but could be a general issue) so 
+								// don't warn if the matching download has been added recently
+							
+							if ( existed_for > 15*1000 ){
+								
+								new MessageSlideShell(Display.getCurrent(), SWT.ICON_INFORMATION,
+										MSG_ALREADY_EXISTS, null, new String[] {
+											":" + torrentOptions.sOriginatingLocation,
+											fExistingName,
+											MessageText.getString(MSG_ALREADY_EXISTS_NAME),
+										}, new Object[] {
+											fExistingDownload
+										}, -1);
+							}
 						} else {
 
 							if (can_merge) {
@@ -1228,13 +1140,17 @@ public class UIFunctionsImpl
 									}
 								});
 							} else {
-								MessageBoxShell mb = new MessageBoxShell(SWT.OK,
-										MSG_ALREADY_EXISTS, new String[] {
-											":" + torrentOptions.sOriginatingLocation,
-											fExistingName,
-											MessageText.getString(MSG_ALREADY_EXISTS_NAME),
-										});
-								mb.open(null);
+								
+								if ( existed_for > 15*1000 ){
+
+									MessageBoxShell mb = new MessageBoxShell(SWT.OK,
+											MSG_ALREADY_EXISTS, new String[] {
+												":" + torrentOptions.sOriginatingLocation,
+												fExistingName,
+												MessageText.getString(MSG_ALREADY_EXISTS_NAME),
+											});
+									mb.open(null);
+								}
 							}
 						}
 					}
@@ -1296,30 +1212,28 @@ public class UIFunctionsImpl
 				if ( looks_good ){
 				
 					return TorrentOpener.addTorrent(torrentOptions);
-					
-				}else{
-					
-					torrentOptions.setParentDir( "" );
-					
-					MessageBoxShell mb = 
-						new MessageBoxShell(
-							SWT.OK | SWT.ICON_ERROR,
-							"OpenTorrentWindow.mb.invaliddefsave", 
-							new String[]{ save_loc });
-					
-					mb.open(
-						new UserPrompterResultListener() 
-						{
-							public void 
-							prompterClosed(
-								int result) 
-							{
-								OpenTorrentOptionsWindow.addTorrent( torrentOptions );
-							}
-						});
-					
-					return( true );
 				}
+				
+				torrentOptions.setParentDir( "" );
+				
+				MessageBoxShell mb = 
+					new MessageBoxShell(
+						SWT.OK | SWT.ICON_ERROR,
+						"OpenTorrentWindow.mb.invaliddefsave", 
+						new String[]{ save_loc });
+				
+				mb.open(
+					new UserPrompterResultListener() 
+					{
+						public void 
+						prompterClosed(
+							int result) 
+						{
+							OpenTorrentOptionsWindow.addTorrent( torrentOptions );
+						}
+					});
+				
+				return( true );
 			}
 		}
 		
@@ -1347,10 +1261,52 @@ public class UIFunctionsImpl
 		}
 	}
 	
+	public void 
+	openTorrentOpenOptions(
+		Shell 					shell, 
+		String 					sPathOfFilesToOpen,
+		String[] 				sFilesToOpen, 
+		Map<String,Object>		options )
+	{
+		Boolean _defaultToStopped 	= (Boolean)options.get( UIFunctions.OTO_DEFAULT_TO_STOPPED );
+		boolean	defaultToStopped	= _defaultToStopped!=null?_defaultToStopped:UIFunctions.OTO_DEFAULT_TO_STOPPED_DEFAULT;
+
+		Boolean _hideErrors		 	= (Boolean)options.get( UIFunctions.OTO_HIDE_ERRORS );
+		boolean	hideErrors			= _hideErrors!=null?_hideErrors:UIFunctions.OTO_HIDE_ERRORS_DEFAULT;
+
+		TorrentOpenOptions torrentOptions = new TorrentOpenOptions();
+		if (defaultToStopped) {
+			torrentOptions.iStartID = TorrentOpenOptions.STARTMODE_STOPPED;
+		}
+		torrentOptions.setHideErrors( hideErrors );
+		
+		if (sFilesToOpen == null) {
+			new OpenTorrentWindow(shell);
+		} else {
+			// with no listener, Downloader will open options window if user configured
+			
+			Boolean _forceOpen 	= (Boolean)options.get( UIFunctions.OTO_FORCE_OPEN );
+			boolean	forceOpen	= _forceOpen!=null?_forceOpen:UIFunctions.OTO_FORCE_OPEN_DEFAULT;
+
+			TorrentOpener.openTorrentsFromStrings(
+					torrentOptions, shell,
+					sPathOfFilesToOpen, sFilesToOpen, null, null, forceOpen );
+		}
+	}
+	
 	/* (non-Javadoc)
 	 * @see com.aelitis.azureus.ui.swt.UIFunctionsSWT#openTorrentWindow()
 	 */
 	public void openTorrentWindow() {
 		new OpenTorrentWindow(Utils.findAnyShell());
 	}
+	
+	// @see com.aelitis.azureus.ui.UIFunctions#showCreateTagDialog()
+	public void showCreateTagDialog(TagReturner tagReturner) {
+		TagUIUtilsV3.showCreateTagDialog(tagReturner);
+	}
+	
+	public TabbedMdiInterface createTabbedMDI(Composite parent, String id) {
+		return new TabbedMDI(parent, id);
+	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/OpenTorrentOptionsWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/OpenTorrentOptionsWindow.java
index f957c0e..d2c9ad6 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/OpenTorrentOptionsWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/OpenTorrentOptionsWindow.java
@@ -22,18 +22,24 @@ import java.io.UnsupportedEncodingException;
 import java.util.*;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Pattern;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.StackLayout;
 import org.eclipse.swt.events.*;
 import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.*;
 import org.eclipse.swt.widgets.*;
+
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.config.StringIterator;
 import org.gudy.azureus2.core3.config.StringList;
 import org.gudy.azureus2.core3.config.impl.ConfigurationDefaults;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerAvailability;
+import org.gudy.azureus2.core3.download.DownloadManagerFactory;
 import org.gudy.azureus2.core3.internat.LocaleTorrentUtil;
 import org.gudy.azureus2.core3.internat.LocaleUtilDecoder;
 import org.gudy.azureus2.core3.internat.MessageText;
@@ -45,17 +51,22 @@ import org.gudy.azureus2.core3.torrent.impl.TorrentOpenFileOptions;
 import org.gudy.azureus2.core3.torrent.impl.TorrentOpenOptions;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.PluginManager;
+import org.gudy.azureus2.plugins.ipc.IPCInterface;
 import org.gudy.azureus2.plugins.ui.UIInputReceiver;
 import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
 import org.gudy.azureus2.plugins.ui.tables.TableColumn;
 import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener;
 import org.gudy.azureus2.ui.swt.*;
-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.MenuBuildUtils.MenuBuilder;
+import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
+import org.gudy.azureus2.ui.swt.config.generic.GenericIntParameter;
+import org.gudy.azureus2.ui.swt.config.generic.GenericParameterAdapter;
+import org.gudy.azureus2.ui.swt.mainwindow.*;
 import org.gudy.azureus2.ui.swt.maketorrent.MultiTrackerEditor;
 import org.gudy.azureus2.ui.swt.maketorrent.TrackerEditorListener;
 import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
+import org.gudy.azureus2.ui.swt.views.TrackerAvailView;
 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.TableViewFactory;
@@ -64,16 +75,21 @@ import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
 
 import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.core.tag.Tag;
-import com.aelitis.azureus.core.tag.TagFeatureFileLocation;
-import com.aelitis.azureus.core.tag.TagManagerFactory;
-import com.aelitis.azureus.core.tag.TagType;
-import com.aelitis.azureus.core.tag.TagTypeListener;
+import com.aelitis.azureus.core.content.ContentException;
+import com.aelitis.azureus.core.content.RelatedAttributeLookupListener;
+import com.aelitis.azureus.core.content.RelatedContentManager;
+import com.aelitis.azureus.core.tag.*;
+import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
+import com.aelitis.azureus.core.util.RegExUtil;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBeta.ChatInstance;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginUtils;
+import com.aelitis.azureus.plugins.net.buddy.BuddyPluginViewInterface;
 import com.aelitis.azureus.ui.IUIIntializer;
 import com.aelitis.azureus.ui.InitializerListener;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.table.TableRowCore;
 import com.aelitis.azureus.ui.common.table.TableSelectionListener;
+import com.aelitis.azureus.ui.common.table.TableViewFilterCheck;
 import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdatable;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
@@ -81,9 +97,11 @@ import com.aelitis.azureus.ui.swt.shells.main.UIFunctionsImpl;
 import com.aelitis.azureus.ui.swt.skin.*;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter;
 import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT;
+import com.aelitis.azureus.ui.swt.utils.TagUIUtilsV3;
 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.StandardButtonsArea;
+import com.aelitis.azureus.util.ImportExportUtils;
 
 @SuppressWarnings({
 	"unchecked",
@@ -258,6 +276,9 @@ public class OpenTorrentOptionsWindow
 	private List<OpenTorrentInstance>	selected_instances 	= new ArrayList<OpenTorrentOptionsWindow.OpenTorrentInstance>();
 	
 	private OpenTorrentInstance			multi_selection_instance;
+
+	protected List<String> listDiscoveredTags = new ArrayList<String>();
+	protected List<String> listTagsToCreate = new ArrayList<String>();
 	
 	public static OpenTorrentOptionsWindow
 	addTorrent(
@@ -583,6 +604,7 @@ public class OpenTorrentOptionsWindow
 						
 				}
 			}
+
 		}catch( Throwable e ){
 			
 			Debug.out( e );
@@ -837,34 +859,102 @@ public class OpenTorrentOptionsWindow
 							
 						final List<OpenTorrentInstance> instances = new ArrayList<OpenTorrentOptionsWindow.OpenTorrentInstance>( selected.size());
 							
+						final List<OpenTorrentInstance> non_simple_instances = new ArrayList<OpenTorrentOptionsWindow.OpenTorrentInstance>();
+								
+						boolean can_rtlf = false;
+						
 						for ( Object o: selected ){
 							
-							instances.add((OpenTorrentInstance)o );
-						}
+							OpenTorrentInstance oti = (OpenTorrentInstance)o;
+							
+							instances.add( oti );
+							
+							if ( !oti.getOptions().isSimpleTorrent()){
 								
-						MenuItem item = new MenuItem(menu, SWT.PUSH);
-						
-						Messages.setLanguageText(item, "OpenTorrentWindow.fileList.changeDestination");
+								non_simple_instances.add( oti );
+								
+								if ( oti.canRemoveTopLevelFolder()){
+									
+									can_rtlf = true;
+								}
+							}
+						}
+							
+						{
+							MenuItem item = new MenuItem(menu, SWT.PUSH);
+							
+							Messages.setLanguageText(item, "OpenTorrentWindow.fileList.changeDestination");
+							
+							item.addSelectionListener(
+								new SelectionAdapter() 
+								{
+									public void 
+									widgetSelected(
+										SelectionEvent e )
+									{
+										for ( Object obj: selected ){
+											
+											OpenTorrentInstance	instance = (OpenTorrentInstance)obj;
+											
+											instance.setSavePath();
+										}
+									}
+								});
+						}
 						
-						item.addSelectionListener(
-							new SelectionAdapter() 
-							{
-								public void 
-								widgetSelected(
-									SelectionEvent e )
+						{
+							MenuItem item = new MenuItem(menu, SWT.PUSH);
+							
+							Messages.setLanguageText(item, "OpenTorrentWindow.tlf.remove");
+							
+							item.addSelectionListener(
+								new SelectionAdapter() 
 								{
-									for ( Object obj: selected ){
-										
-										OpenTorrentInstance	instance = (OpenTorrentInstance)obj;
-										
-										instance.setSavePath();
+									public void 
+									widgetSelected(
+										SelectionEvent e )
+									{
+										for ( Object obj: selected ){
+											
+											OpenTorrentInstance	instance = (OpenTorrentInstance)obj;
+											
+											if ( instance.canRemoveTopLevelFolder()){
+											
+												instance.removeTopLevelFolder();
+											}
+										}
 									}
-								}
-							});
+								});
+							
+							item.setEnabled( can_rtlf );
+						}
+						
+						{
+							MenuItem item = new MenuItem(menu, SWT.CHECK );
+								
+							 item.setData( COConfigurationManager.getBooleanParameter( "open.torrent.window.rename.on.tlf.change" ));
+								
+							 Messages.setLanguageText(item, "OpenTorrentWindow.tlf.rename");
+
+							 item.addSelectionListener(
+								 new SelectionAdapter() 
+								 {
+									 public void 
+									 widgetSelected(
+											 SelectionEvent e )
+									 {
+										 COConfigurationManager.setParameter(
+												"open.torrent.window.rename.on.tlf.change", 
+												((MenuItem)e.widget).getSelection());
+									 }
+								 });
+							
+							item.setEnabled( non_simple_instances.size() > 0 );
+						}
 						
 						new MenuItem(menu, SWT.SEPARATOR);
 
-						item = new MenuItem(menu, SWT.PUSH);
+						MenuItem item = new MenuItem(menu, SWT.PUSH);
 						
 						Messages.setLanguageText(item, "Button.remove");
 						
@@ -1147,8 +1237,23 @@ public class OpenTorrentOptionsWindow
 		
 		if ( num == 1 ){
 			
-			text = open_instances.get(0).getOptions().getTorrentName();
+				// use a display name consistent with core
+			
+			TorrentOpenOptions options = open_instances.get(0).getOptions();
 
+			text = options.getTorrentName();
+			
+			TOTorrent t = options.getTorrent();
+			
+			if ( t != null ){
+			
+				String str = PlatformTorrentUtils.getContentTitle( t );
+				
+				if ( str != null && str.length() > 0 ){
+					
+					text = str;
+				}
+			}
 		}else{
 			
 			text =  MessageText.getString("label.num.torrents",new String[]{ String.valueOf( open_instances.size())});
@@ -1326,6 +1431,7 @@ public class OpenTorrentOptionsWindow
 	
 	protected class
 	OpenTorrentInstance
+		implements TableViewFilterCheck<TorrentOpenFileOptions>
 	{
 		final private HashWrapper						hash;
 		final private TorrentOpenOptions 				torrentOptions;
@@ -1340,6 +1446,8 @@ public class OpenTorrentOptionsWindow
 		/* prevents loop of modifications */
 		protected boolean bSkipDataDirModify = false;
 
+		private Button btnCheckComments;
+		private Button btnCheckAvailability;
 		private Button btnSwarmIt;
 
 		private Combo cmbDataDir;
@@ -1370,7 +1478,7 @@ public class OpenTorrentOptionsWindow
 
 		private SWTSkinObjectText soFileAreaInfo;
 
-		private TableViewSWT<Object> tvFiles;
+		private TableViewSWT<TorrentOpenFileOptions> tvFiles;
 
 		private SWTSkinObjectExpandItem soStartOptionsExpandItem;
 
@@ -1383,6 +1491,7 @@ public class OpenTorrentOptionsWindow
 		private Button btnUnmarkSelected;
 		private Button btnRename;
 		private Button btnRetarget;
+		private Composite tagButtonsArea;
 		
 		private 
 		OpenTorrentInstance(
@@ -1432,6 +1541,51 @@ public class OpenTorrentOptionsWindow
 					}
 				}
 			});
+			
+			if ( TagManagerFactory.getTagManager().isEnabled()){
+
+				try {
+					RelatedContentManager rcm = RelatedContentManager.getSingleton();
+					String[] networks = torrentOptions.getEnabledNetworks().keySet().toArray(new String[0]);
+					rcm.lookupAttributes(hash.getBytes(), networks,
+							new RelatedAttributeLookupListener() {
+
+								public void lookupStart() {
+								}
+
+								public void tagFound(String tag, String network) {
+									if (listDiscoveredTags.contains(tag)) {
+										return;
+									}
+									if (checkAlreadyHaveTag(torrentOptions.getInitialTags(), tag)) {
+										return;
+									}
+									listDiscoveredTags.add(tag);
+									Utils.execSWTThread(new Runnable() {
+										public void run() {
+											if (tagButtonsArea == null
+													|| tagButtonsArea.isDisposed()) {
+												return;
+											}
+											buildTagButtonPanel(tagButtonsArea, true);
+										}
+									});
+
+								}
+
+								public void lookupComplete() {
+								}
+
+								public void lookupFailed(ContentException error) {
+								}
+							});
+				} catch (ContentException e1) {
+					// TODO Auto-generated catch block
+					e1.printStackTrace();
+				}
+
+			}				
+
 		}
 		
 		private 
@@ -1485,7 +1639,7 @@ public class OpenTorrentOptionsWindow
 			if ( torrentOptions != null ){
 				SWTSkinObject so = skin.getSkinObject("filearea-table");
 				if (so instanceof SWTSkinObjectContainer) {
-					setupTVFiles((SWTSkinObjectContainer) so);
+					setupTVFiles((SWTSkinObjectContainer) so, (SWTSkinObjectTextbox)skin.getSkinObject("filearea-filter"));
 				}
 		
 				so = skin.getSkinObject("filearea-buttons");
@@ -1500,6 +1654,8 @@ public class OpenTorrentOptionsWindow
 				GridLayout gl = new GridLayout(2, false);
 				gl.marginHeight = gl.marginWidth = 0;
 				diskspaceComp.setLayout(gl);
+				Label l = new Label(diskspaceComp, SWT.NONE);
+				l.setText( "" );	// start with this to avoid UI re-layout from moving suff as user enters text etc
 			}
 		
 			if ( torrentOptions != null ){
@@ -1515,7 +1671,7 @@ public class OpenTorrentOptionsWindow
 		
 				so = skin.getSkinObject("peer-sources");
 				if (so instanceof SWTSkinObjectContainer) {
-					setupPeerSourcesOptions((SWTSkinObjectContainer) so);
+					setupPeerSourcesAndNetworkOptions((SWTSkinObjectContainer) so);
 				}
 		
 				so = skin.getSkinObject("trackers");
@@ -1523,6 +1679,11 @@ public class OpenTorrentOptionsWindow
 					setupTrackers((SWTSkinObjectContainer) so);
 				}
 				
+				so = skin.getSkinObject("updownlimit");
+				if (so instanceof SWTSkinObjectContainer) {
+					setupUpDownLimitOption((SWTSkinObjectContainer) so);
+				}
+			
 				so = skin.getSkinObject("ipfilter");
 				if (so instanceof SWTSkinObjectContainer) {
 					setupIPFilterOption((SWTSkinObjectContainer) so);
@@ -1589,179 +1750,1026 @@ public class OpenTorrentOptionsWindow
 			}
 		}
 		
-		private void checkSeedingMode() {
-			if ( torrentOptions == null ){
-				return;
-			}
+		private void
+		showAvailability()
+		{
+			final Shell avail_shell = ShellFactory.createShell( shell, SWT.DIALOG_TRIM | SWT.RESIZE );
+
+			Utils.setShellIcon(avail_shell);
+			 
+			GridLayout layout = new GridLayout();
+			layout.numColumns = 1;
+			layout.marginWidth = 0;
+			layout.marginHeight = 0;
+			avail_shell.setLayout(layout);
 			
-			// Check for seeding
-			boolean bTorrentValid = true;
-	
-			if (torrentOptions.iStartID == TorrentOpenOptions.STARTMODE_SEEDING) {
-				// check if all selected files exist
-				TorrentOpenFileOptions[] files = torrentOptions.getFiles();
-				for (int j = 0; j < files.length; j++) {
-					TorrentOpenFileOptions fileInfo = files[j];
-					if (!fileInfo.isToDownload())
-						continue;
-	
-					File file = fileInfo.getInitialLink();
-	
-					if (file == null) {
-	
-						file = fileInfo.getDestFileFullName();
-					}
-	
-					if (!file.exists()) {
-						fileInfo.isValid = false;
-						bTorrentValid = false;
-					} else if (!fileInfo.isValid) {
-						fileInfo.isValid = true;
+			Utils.verifyShellRect(avail_shell, true);
+
+			TOTorrent t = torrentOptions.getTorrent();
+
+			final TrackerAvailView view = new TrackerAvailView();
+			
+			String[] enabled_peer_sources = PEPeerSource.PS_SOURCES;
+			
+			if (torrentOptions.peerSource != null) {
+				List<String>	temp = new ArrayList<String>(Arrays.asList(enabled_peer_sources));
+				for (String peerSource : torrentOptions.peerSource.keySet()) {
+					boolean enable = torrentOptions.peerSource.get(peerSource);
+					if ( !enable ){
+						temp.remove( peerSource );
 					}
 				}
+				enabled_peer_sources = temp.toArray( new String[temp.size()]);
 			}
-	
-			torrentOptions.isValid = bTorrentValid;
-		}
-	
-		protected void cmbDataDirChanged() {
-	
-			if (bSkipDataDirModify || cmbDataDir == null) {
-				return;
-			}
-			String dirText = cmbDataDir.getText();
+
+			String[] enabled_networks = AENetworkClassifier.AT_NETWORKS;
 			
-			for ( TorrentOpenOptions too: torrentOptionsMulti ){
-				too.setParentDir( dirText);
-			}
+			Map<String,Boolean> enabledNetworks = torrentOptions.getEnabledNetworks();
 			
-			checkSeedingMode();
-	
-			if (!Utils.isCocoa || SWT.getVersion() > 3600) { // See Eclipse Bug 292449
-				File file = new File( dirText );
-				if (!file.isDirectory()) {
-					cmbDataDir.setBackground(Colors.colorErrorBG);
-					// make the error state visible
-					soExpandItemSaveTo.setExpanded(true);
-				} else {
-					cmbDataDir.setBackground(null);
+			if ( enabledNetworks != null ){
+				List<String>	temp = new ArrayList<String>(Arrays.asList(enabled_networks));
+				for (String net : enabledNetworks.keySet()) {
+					boolean enable = enabledNetworks.get(net);
+					if ( !enable ){
+						temp.remove( net );
+					}
 				}
-				cmbDataDir.redraw();
-				cmbDataDir.update();
-			}
-	
-			if (soExpandItemSaveTo != null) {
-				String s = MessageText.getString("OpenTorrentOptions.header.saveto",
-						new String[] { dirText });
-				soExpandItemSaveTo.setText(s);
-			}
-			diskFreeInfoRefreshPending = true;
-		}
-	
-		private long getCachedDirFreeSpace(File directory) {
-			FileStatsCacheItem item = (FileStatsCacheItem) fileStatCache.get(directory);
-			if (item == null)
-				fileStatCache.put(directory, item = new FileStatsCacheItem(directory));
-			return item.freeSpace;
-		}
-	
-		private boolean getCachedExistsStat(File directory) {
-			FileStatsCacheItem item = (FileStatsCacheItem) fileStatCache.get(directory);
-			if (item == null)
-				fileStatCache.put(directory, item = new FileStatsCacheItem(directory));
-			return item.exists;
-		}
-	
-		protected void setSelectedQueueLocation(int iLocation) {
-			torrentOptions.iQueueLocation = iLocation;
-	
-			updateStartOptionsHeader();
-		}
-	
-		private void updateStartOptionsHeader() {
-			if (soStartOptionsExpandItem == null) {
-				return;
+				enabled_networks = temp.toArray( new String[temp.size()]);
 			}
-	
-			String optionText = MessageText.getString("OpenTorrentWindow.startMode."
-					+ startModes[torrentOptions.iStartID])
-					+ ", "
-					+ MessageText.getString("OpenTorrentWindow.addPosition."
-							+ queueLocations[torrentOptions.iQueueLocation]);
-	
-			String s = MessageText.getString("OpenTorrentOptions.header.startoptions",
-					new String[] {
-						optionText
-					});
+					
+			final DownloadManagerAvailability availability = 
+				DownloadManagerFactory.getAvailability( 
+					t, 
+					torrentOptions.getTrackers( true ), 
+					enabled_peer_sources,
+					enabled_networks );
 			
-			List<Tag> initialtags = torrentOptions.getInitialTags();
+			view.dataSourceChanged( availability );
+
+			Composite comp = new Composite( avail_shell, SWT.NULL );
+			GridData gridData = new GridData( GridData.FILL_BOTH );
+			comp.setLayoutData(gridData);
 			
-			String tag_str;
+			layout = new GridLayout();
+			layout.numColumns = 1;
+			layout.marginWidth = 0;
+			layout.marginHeight = 0;
+			comp.setLayout(layout);
 			
-			if ( initialtags.size() == 0 ){
-				
-				tag_str = MessageText.getString( "label.none" );
-				
-			}else{
-				
-				tag_str = "";
-				
-				for ( Tag t: initialtags ){
-					
-					tag_str += (tag_str==""?"":", ") + t.getTagName( true );
+			view.initialize(comp);
+
+			view.viewActivated();
+			view.refresh();
+
+			final UIUpdatable viewUpdater = new UIUpdatable() {
+				public void updateUI() {
+					view.refresh();
 				}
-			}
+
+				public String getUpdateUIName() {
+					return view.getFullTitle();
+				}
+			};
 			
-			s += "        " + MessageText.getString( "OpenTorrentOptions.header.tags", new String[]{ tag_str });
+			UIUpdaterSWT.getInstance().addUpdater(viewUpdater);
+
+				// progress
 			
-			soStartOptionsExpandItem.setText(s);
-		}
-	
-		protected void setSelectedStartMode(int iStartID) {
-			torrentOptions.iStartID = iStartID;
-	
-			checkSeedingMode();
-			updateStartOptionsHeader();
-		}
-	
-		private void setupFileAreaButtons(SWTSkinObjectContainer so) {
-			Composite cButtons = so.getComposite();
+			Composite progressComp = new Composite( comp, SWT.NULL );
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			progressComp.setLayoutData(gridData);
 			
-			cButtons.setLayout(new GridLayout(7,false));
-	
-			List<Button>	buttons = new ArrayList<Button>();
+			layout = new GridLayout();
+			layout.numColumns = 2;
+			progressComp.setLayout(layout);
 			
-			btnSelectAll = new Button(cButtons, SWT.PUSH);
-			buttons.add( btnSelectAll );
-			Messages.setLanguageText(btnSelectAll, "Button.selectAll");
-			btnSelectAll.addListener(SWT.Selection, new Listener() {
-				public void handleEvent(Event event) {
-					tvFiles.selectAll();
-				}
-			});
+			Label progLabel = new Label(progressComp,SWT.NULL);
+			progLabel.setText( MessageText.getString("label.checking.sources"));
 			
-			btnMarkSelected = new Button(cButtons, SWT.PUSH);
-			buttons.add( btnMarkSelected );
-			Messages.setLanguageText(btnMarkSelected, "Button.mark");
-			btnMarkSelected.addListener(SWT.Selection, new Listener() {
-				public void handleEvent(Event event) {
-					TorrentOpenFileOptions[] infos = tvFiles.getSelectedDataSources().toArray(new TorrentOpenFileOptions[0]);
-					setToDownload( infos, true );
-				}
-			});
+			final Composite progBarComp = new Composite( progressComp, SWT.NULL );
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			//gridData.widthHint = 400;
+			progBarComp.setLayoutData(gridData);
 			
-			btnUnmarkSelected = new Button(cButtons, SWT.PUSH);
-			buttons.add( btnUnmarkSelected );
-			Messages.setLanguageText(btnUnmarkSelected, "Button.unmark");
-			btnUnmarkSelected.addListener(SWT.Selection, new Listener() {
-				public void handleEvent(Event event) {
-					TorrentOpenFileOptions[] infos = tvFiles.getSelectedDataSources().toArray(new TorrentOpenFileOptions[0]);
-					setToDownload( infos, false );
+			//Label padLabel = new Label(progressComp,SWT.NULL);
+			//gridData = new GridData(GridData.FILL_HORIZONTAL);
+			//padLabel.setLayoutData(gridData);
+			
+			final StackLayout	progStackLayout = new StackLayout();
+			
+			progBarComp.setLayout( progStackLayout);
+			
+			final ProgressBar progBarIndeterminate = new ProgressBar(progBarComp, SWT.HORIZONTAL | SWT.INDETERMINATE);
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			progBarIndeterminate.setLayoutData(gridData);
+			
+			final ProgressBar progBarComplete = new ProgressBar(progBarComp, SWT.HORIZONTAL );
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			progBarComplete.setLayoutData(gridData);
+			progBarComplete.setMaximum( 1 );
+			progBarComplete.setSelection( 1 );
+			
+			progStackLayout.topControl = progBarIndeterminate;
+			
+			new AEThread2( "ProgChecker" )
+			{
+				public void
+				run()
+				{
+					boolean	currently_updating = true;
+					
+					while( true ){
+						
+						if ( avail_shell.isDisposed()){
+							
+							return;
+						}
+						
+						final boolean	updating = view.isUpdating();
+						
+						if ( updating != currently_updating ){
+							
+							currently_updating = updating;
+							
+							Utils.execSWTThread(
+								new Runnable()
+								{
+									public void
+									run()
+									{
+										if ( !avail_shell.isDisposed()){
+										
+											progStackLayout.topControl = updating?progBarIndeterminate:progBarComplete;
+										
+											progBarComp.layout();
+										}
+									}
+								});
+						}
+						
+						try{
+							Thread.sleep(500);
+							
+						}catch( Throwable e ){
+							
+						}
+					}
+				}
+			}.start();
+			
+				// line
+			
+			Label labelSeparator = new Label( comp, SWT.SEPARATOR | SWT.HORIZONTAL);
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			labelSeparator.setLayoutData(gridData);
+			
+				// buttons
+			
+			Composite buttonComp = new Composite( comp, SWT.NULL );
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			buttonComp.setLayoutData(gridData);
+			
+			layout = new GridLayout();
+			layout.numColumns = 2;
+			buttonComp.setLayout(layout);
+			
+			new Label(buttonComp,SWT.NULL);
+			
+			Composite buttonArea = new Composite(buttonComp,SWT.NULL);
+			gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL);
+			gridData.grabExcessHorizontalSpace = true;
+			buttonArea.setLayoutData(gridData);
+			GridLayout layoutButtons = new GridLayout();
+			layoutButtons.numColumns = 1;
+			buttonArea.setLayout(layoutButtons);
+			
+			List<Button>	buttons = new ArrayList<Button>();
+			
+			Button bOK = new Button(buttonArea,SWT.PUSH);
+			buttons.add( bOK );
+			
+			bOK.setText(MessageText.getString("Button.ok"));
+			gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL);
+			gridData.grabExcessHorizontalSpace = true;
+			gridData.widthHint = 70;
+			bOK.setLayoutData(gridData);
+			bOK.addListener(SWT.Selection,new Listener() {
+				public void handleEvent(Event e) {
+					avail_shell.dispose();
+				}
+			});
+			
+			Utils.makeButtonsEqualWidth( buttons );
+			
+			avail_shell.setDefaultButton( bOK );
+			
+			avail_shell.addDisposeListener(new DisposeListener() {
+				public void widgetDisposed(DisposeEvent e) {
+					try{
+						UIUpdaterSWT.getInstance().removeUpdater(viewUpdater);
+						
+						if ( !btnCheckAvailability.isDisposed()){
+						
+							btnCheckAvailability.setEnabled( true );
+						}
+					}finally{
+						
+						availability.destroy();
+					}
+				}
+			});
+
+			btnCheckAvailability.setEnabled( false );
+			
+			avail_shell.setSize( 800, 400 );
+			avail_shell.layout(true, true);
+			
+			Utils.centerWindowRelativeTo(avail_shell,shell);
+			
+			String title = torrentOptions.getTorrentName();
+						
+			if ( t != null ){
+			
+				String str = PlatformTorrentUtils.getContentTitle( t );
+				
+				if ( str != null && str.length() > 0 ){
+					
+					title = str;
+				}
+			}
+			
+			Messages.setLanguageText( avail_shell, "torrent.avail.title", new String[]{ title });
+
+			avail_shell.open();
+		}
+		
+		private void
+		showComments()
+		{
+			final Shell comments_shell = ShellFactory.createShell( shell, SWT.DIALOG_TRIM | SWT.RESIZE );
+
+			Utils.setShellIcon(comments_shell);
+			 
+			GridLayout layout = new GridLayout();
+			layout.numColumns = 1;
+			layout.marginWidth = 0;
+			layout.marginHeight = 0;
+			comments_shell.setLayout(layout);
+			
+			Utils.verifyShellRect(comments_shell, true);
+
+			TOTorrent torrent = torrentOptions.getTorrent();
+			
+			String[] enabled_networks = AENetworkClassifier.AT_NETWORKS;
+			
+			Map<String,Boolean> enabledNetworks = torrentOptions.getEnabledNetworks();
+			
+			if ( enabledNetworks != null ){
+				List<String>	temp = new ArrayList<String>(Arrays.asList(enabled_networks));
+				for (String net : enabledNetworks.keySet()) {
+					boolean enable = enabledNetworks.get(net);
+					if ( !enable ){
+						temp.remove( net );
+					}
+				}
+				enabled_networks = temp.toArray( new String[temp.size()]);
+			}
+					
+			Composite comp = new Composite( comments_shell, SWT.NULL );
+			
+			GridData gridData = new GridData( GridData.FILL_BOTH );
+			comp.setLayoutData(gridData);
+			
+			layout = new GridLayout();
+			layout.numColumns = 1;
+			layout.marginWidth = 0;
+			layout.marginHeight = 0;
+			comp.setLayout(layout);
+			
+			Composite topComp = new Composite( comp, SWT.NULL );
+			layout = new GridLayout();
+			layout.numColumns = 1;
+			layout.marginWidth = 0;
+			layout.marginHeight = 0;
+			topComp.setLayout(layout);
+			gridData = new GridData( GridData.FILL_BOTH );
+			topComp.setLayoutData(gridData);
+			
+			String active_networks_str = "";
+			
+			for ( String net: enabled_networks ){
+				
+				active_networks_str += 
+						(active_networks_str.length()==0?"":", ") + 
+						MessageText.getString( "ConfigView.section.connection.networks." + net );
+			}
+			
+			if ( active_networks_str.length() == 0 ){
+				
+				active_networks_str = MessageText.getString( "PeersView.uniquepiece.none" );
+			}
+			
+			Label info_label = new Label( topComp, SWT.WRAP );
+			info_label.setText( MessageText.getString( "torrent.comments.info", new String[]{active_networks_str}));
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			gridData.horizontalIndent = 8;
+			gridData.verticalIndent = 8;
+			info_label.setLayoutData(gridData);
+			
+				// azrating plugin
+			
+			Group ratingComp = new Group( topComp, SWT.NULL );
+			layout = new GridLayout();
+			layout.numColumns = 1;
+			
+			ratingComp.setLayout(layout);
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			ratingComp.setLayoutData(gridData);
+			
+			ratingComp.setText( "Rating Plugin" );
+			
+			Composite ratingComp2 = new Composite( ratingComp, SWT.BORDER );
+			layout = new GridLayout();
+			layout.numColumns = 1;
+			layout.marginWidth = 4;
+			layout.marginHeight = 4;
+			ratingComp2.setLayout(layout);
+			gridData = new GridData( GridData.FILL_BOTH );
+			ratingComp2.setLayoutData(gridData);
+			ratingComp2.setBackground( Colors.white );
+			
+			final Label ratingText = new Label( ratingComp2, SWT.WRAP );
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			gridData.heightHint=ratingText.getFont().getFontData()[0].getHeight() * 2 + 16;
+			ratingText.setLayoutData(gridData);
+			ratingText.setBackground( Colors.white );
+			
+			final boolean[]	az_rating_in_progress = { false };
+			
+			try{
+				PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager();
+				
+				PluginInterface rating_pi = pm.getPluginInterfaceByID( "azrating" );
+					
+				if ( rating_pi != null ){
+					
+					final IPCInterface ipc = rating_pi.getIPC();
+					
+					if ( ipc.canInvoke( "lookupRatingByHash", new Object[]{ new String[0], new byte[0] })){
+							
+						final String[] f_enabled_networks = enabled_networks;
+						
+						az_rating_in_progress[0] = true;
+						
+						ratingText.setText( MessageText.getString( "label.searching" ));
+								
+						new AEThread2( "oto:rat" )
+						{
+							public void
+							run()
+							{	Map result = null;
+							
+								try{
+									result = (Map)ipc.invoke( "lookupRatingByHash", new Object[]{ f_enabled_networks, hash.getBytes() });
+																			
+								}catch( Throwable e ){
+									
+									e.printStackTrace();
+									
+								}finally{
+									
+									synchronized( az_rating_in_progress ){
+									
+										az_rating_in_progress[0] = false;
+									}
+									
+									if ( !ratingText.isDisposed()){
+									
+										final Map f_result = result;
+										
+										Utils.execSWTThread(
+											new Runnable()
+											{
+												public void
+												run()
+												{
+													if ( !ratingText.isDisposed()){
+														
+														String text 	= "";
+														String	tooltip = "";
+														
+														if ( f_result != null ){
+															
+															List<Map> ratings = (List<Map>)f_result.get( "ratings" );
+															
+															if ( ratings != null ){
+																
+																String 			scores_str = "";
+																List<String>	comments = new ArrayList<String>();
+																
+																double	total_score = 0;
+																int		score_num	= 0;
+																
+																for ( Map map: ratings ){
+																	
+																	try{
+																		int 	score	= ((Number)map.get( "score" )).intValue();
+																		
+																		total_score += score;
+																		score_num++;
+																		
+																		scores_str += (scores_str.length()==0?"":", ") + score;
+																		
+																		String comment 	= ImportExportUtils.importString(map, "comment" );
+																		
+																		if ( comment != null ){
+																			
+																			comment = comment.trim();
+																			
+																			if ( comment.length() > 0 ){
+																				
+																				comments.add( comment );
+																			}
+																		}
+																	}catch( Throwable e ){
+																		
+																	}
+																}
+																
+																if ( score_num > 0 ){
+																	
+																	double average = total_score/score_num;
+																	
+																	text = MessageText.getString( 
+																				"torrent.comment.rat1", 
+																				new String[]{
+																					DisplayFormatters.formatDecimal(average,1),
+																					scores_str
+																				});
+																	
+																	int num_comments = comments.size();
+																	
+																	if ( num_comments > 0 ){
+																		
+																		text += "\n    " + MessageText.getString( 
+																				"torrent.comment.rat2", 
+																				new String[]{
+																					comments.get(0) + (num_comments==1?"":"..." )
+																				});
+																																					
+																		for ( String comment: comments ){
+																				
+																			tooltip += (tooltip.length()==0?"":"\n") + comment;
+																		}
+																	}
+																}
+															}
+															
+															
+														}
+														
+														if ( text.length()==0 ){
+															
+															text = MessageText.getString( "PeersView.uniquepiece.none" );
+														}
+														
+														ratingText.setText( text );
+														ratingText.setToolTipText( tooltip );
+													}
+												}
+											});
+									}
+								}
+							}
+						}.start();
+						
+					}else{
+						
+						ratingText.setText( "Rating Plugin needs updating" );
+					}
+				}else{
+					
+					ratingText.setText( MessageText.getString( "torrent.comment.azrating.install" ));
+				}
+			}catch( Throwable e ){
+				
+				ratingText.setText( "Rating Plugin failed: " + Debug.getNestedExceptionMessage(e));
+			}
+			
+				// chat
+			
+			Group chatComp = new Group( topComp, SWT.NULL );
+			layout = new GridLayout();
+			layout.numColumns = 1;
+			chatComp.setLayout(layout);
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			chatComp.setLayoutData(gridData);
+			
+			chatComp.setText( "Chat Plugin" );
+			
+			Map<String,Object>	chat_properties = new HashMap<String, Object>();
+			
+			chat_properties.put( BuddyPluginViewInterface.VP_SWT_COMPOSITE, chatComp );
+			
+			final String[]f_enabled_networks = enabled_networks;
+			
+			final String  chat_key = BuddyPluginUtils.getChatKey( torrent );
+			
+			BuddyPluginViewInterface.DownloadAdapter 
+				adapter = new BuddyPluginViewInterface.DownloadAdapter(){
+					
+					public String[] 
+					getNetworks() 
+					{
+						return( f_enabled_networks );
+					}
+					
+					public DownloadManager 
+					getCoreDownload() 
+					{
+						return( null );
+					}
+					
+					public String 
+					getChatKey() 
+					{
+						return( chat_key );
+					}
+				};
+				
+			chat_properties.put( BuddyPluginViewInterface.VP_DOWNLOAD, adapter );
+
+			final Set<ChatInstance>	activated_chats = new HashSet<ChatInstance>();
+			
+			final BuddyPluginViewInterface.View chat_view = 
+				BuddyPluginUtils.buildChatView( 
+					chat_properties,
+					new BuddyPluginViewInterface.ViewListener() {
+						
+						public void 
+						chatActivated(
+							ChatInstance chat) 
+						{
+							synchronized( az_rating_in_progress ){
+								
+								activated_chats.add( chat );
+							}
+						}
+					});
+				
+			if ( chat_view == null ){
+				
+				Composite chatComp2 = new Composite( chatComp, SWT.BORDER );
+				layout = new GridLayout();
+				layout.numColumns = 1;
+				layout.marginWidth = 4;
+				layout.marginHeight = 4;
+				chatComp2.setLayout(layout);
+				gridData = new GridData( GridData.FILL_BOTH );
+				chatComp2.setLayoutData(gridData);
+				chatComp2.setBackground( Colors.white );
+				
+				final Label chatText = new Label( chatComp2, SWT.WRAP );
+				gridData = new GridData( GridData.FILL_HORIZONTAL );
+				gridData.heightHint=ratingText.getFont().getFontData()[0].getHeight() * 2 + 16;
+				chatText.setLayoutData(gridData);
+				chatText.setBackground( Colors.white );
+
+				chatText.setText( MessageText.getString( "torrent.comment.azmsgsync.install" ));
+			}
+			
+				// progress
+			
+			Composite progressComp = new Composite( comp, SWT.NULL );
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			progressComp.setLayoutData(gridData);
+			
+			layout = new GridLayout();
+			layout.numColumns = 2;
+			progressComp.setLayout(layout);
+			
+			Label progLabel = new Label(progressComp,SWT.NULL);
+			progLabel.setText( MessageText.getString("label.checking.comments"));
+			
+			final Composite progBarComp = new Composite( progressComp, SWT.NULL );
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			//gridData.widthHint = 300;
+			progBarComp.setLayoutData(gridData);
+			
+			//Label padLabel = new Label(progressComp,SWT.NULL);
+			//gridData = new GridData(GridData.FILL_HORIZONTAL);
+			//padLabel.setLayoutData(gridData);
+			
+			final StackLayout	progStackLayout = new StackLayout();
+			
+			progBarComp.setLayout( progStackLayout);
+			
+			final ProgressBar progBarIndeterminate = new ProgressBar(progBarComp, SWT.HORIZONTAL | SWT.INDETERMINATE);
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			progBarIndeterminate.setLayoutData(gridData);
+			
+			final ProgressBar progBarComplete = new ProgressBar(progBarComp, SWT.HORIZONTAL );
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			progBarComplete.setLayoutData(gridData);
+			progBarComplete.setMaximum( 1 );
+			progBarComplete.setSelection( 1 );
+			
+			progStackLayout.topControl = progBarIndeterminate;
+			
+			new AEThread2( "ProgChecker" )
+			{
+				public void
+				run()
+				{
+					boolean	currently_updating = true;
+					
+					while( true ){
+						
+						if ( comments_shell.isDisposed()){
+							
+							return;
+						}
+						
+						boolean in_progress = false;
+						
+						synchronized( az_rating_in_progress ){
+						
+							if ( az_rating_in_progress[0] ){
+								
+								in_progress = true;
+							}
+							
+							for ( ChatInstance inst: activated_chats ){
+								
+								if ( inst.getIncomingSyncState() != 0 ){
+									
+									in_progress = true;
+								}
+							}
+						}
+						
+						final boolean	updating = in_progress;
+						
+						if ( updating != currently_updating ){
+							
+							currently_updating = updating;
+							
+							Utils.execSWTThread(
+								new Runnable()
+								{
+									public void
+									run()
+									{
+										if ( !comments_shell.isDisposed()){
+										
+											progStackLayout.topControl = updating?progBarIndeterminate:progBarComplete;
+										
+											progBarComp.layout();
+										}
+									}
+								});
+						}
+						
+						try{
+							Thread.sleep(500);
+							
+						}catch( Throwable e ){
+							
+						}
+					}
+				}
+			}.start();
+			
+				// line
+			
+			Label labelSeparator = new Label( comp, SWT.SEPARATOR | SWT.HORIZONTAL);
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			labelSeparator.setLayoutData(gridData);
+			
+				// buttons
+			
+			Composite buttonComp = new Composite( comp, SWT.NULL );
+			gridData = new GridData( GridData.FILL_HORIZONTAL );
+			buttonComp.setLayoutData(gridData);
+			
+			layout = new GridLayout();
+			layout.numColumns = 2;
+			buttonComp.setLayout(layout);
+			
+			new Label(buttonComp,SWT.NULL);
+			
+			Composite buttonArea = new Composite(buttonComp,SWT.NULL);
+			gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL);
+			gridData.grabExcessHorizontalSpace = true;
+			buttonArea.setLayoutData(gridData);
+			GridLayout layoutButtons = new GridLayout();
+			layoutButtons.numColumns = 1;
+			buttonArea.setLayout(layoutButtons);
+			
+			List<Button>	buttons = new ArrayList<Button>();
+			
+			Button bOK = new Button(buttonArea,SWT.PUSH);
+			buttons.add( bOK );
+			
+			bOK.setText(MessageText.getString("Button.ok"));
+			gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_FILL);
+			gridData.grabExcessHorizontalSpace = true;
+			gridData.widthHint = 70;
+			bOK.setLayoutData(gridData);
+			bOK.addListener(SWT.Selection,new Listener() {
+				public void handleEvent(Event e) {
+					comments_shell.dispose();
+				}
+			});
+			
+			Utils.makeButtonsEqualWidth( buttons );
+			
+			comments_shell.setDefaultButton( bOK );
+			
+			comments_shell.addDisposeListener(new DisposeListener() {
+				public void widgetDisposed(DisposeEvent e) {
+					try{
+						if ( !btnCheckComments.isDisposed()){
+						
+							btnCheckComments.setEnabled( true );
+						}
+						
+						if ( chat_view != null ){
+							
+							chat_view.destroy();
+						}
+					}finally{
+						
+						
+					}
+				}
+			});
+
+			btnCheckComments.setEnabled( false );
+			
+			comments_shell.setSize( 600, 600 );
+			comments_shell.layout(true, true);
+			
+			Utils.centerWindowRelativeTo(comments_shell,shell);
+			
+			String title = torrentOptions.getTorrentName();
+						
+			if ( torrent != null ){
+			
+				String str = PlatformTorrentUtils.getContentTitle( torrent );
+				
+				if ( str != null && str.length() > 0 ){
+					
+					title = str;
+				}
+			}
+			
+			Messages.setLanguageText( comments_shell, "torrent.comments.title", new String[]{ title });
+
+			comments_shell.open();
+		}
+		
+		
+		
+		
+		private void checkSeedingMode() {
+			if ( torrentOptions == null ){
+				return;
+			}
+			
+			// Check for seeding
+			boolean bTorrentValid = true;
+	
+			if (torrentOptions.iStartID == TorrentOpenOptions.STARTMODE_SEEDING) {
+				// check if all selected files exist
+				TorrentOpenFileOptions[] files = torrentOptions.getFiles();
+				for (int j = 0; j < files.length; j++) {
+					TorrentOpenFileOptions fileInfo = files[j];
+					if (!fileInfo.isToDownload())
+						continue;
+	
+					File file = fileInfo.getInitialLink();
+	
+					if (file == null) {
+	
+						file = fileInfo.getDestFileFullName();
+					}
+	
+					if (!file.exists()) {
+						fileInfo.isValid = false;
+						bTorrentValid = false;
+					} else if (!fileInfo.isValid) {
+						fileInfo.isValid = true;
+					}
+				}
+			}
+	
+			torrentOptions.isValid = bTorrentValid;
+		}
+	
+		protected void cmbDataDirChanged() {
+	
+			if (bSkipDataDirModify || cmbDataDir == null) {
+				return;
+			}
+			String dirText = cmbDataDir.getText();
+			
+			for ( TorrentOpenOptions too: torrentOptionsMulti ){
+				too.setParentDir( dirText);
+			}
+			
+			checkSeedingMode();
+	
+			if (!Utils.isCocoa || SWT.getVersion() > 3600) { // See Eclipse Bug 292449
+				File file = new File( dirText );
+				if (!file.isDirectory()) {
+					cmbDataDir.setBackground(Colors.colorErrorBG);
+					// make the error state visible
+					soExpandItemSaveTo.setExpanded(true);
+				} else {
+					cmbDataDir.setBackground(null);
+				}
+				cmbDataDir.redraw();
+				cmbDataDir.update();
+			}
+	
+			if (soExpandItemSaveTo != null) {
+				String s = MessageText.getString("OpenTorrentOptions.header.saveto",
+						new String[] { dirText });
+				soExpandItemSaveTo.setText(s);
+			}
+			diskFreeInfoRefreshPending = true;
+		}
+	
+		private long getCachedDirFreeSpace(File directory) {
+			FileStatsCacheItem item = (FileStatsCacheItem) fileStatCache.get(directory);
+			if (item == null)
+				fileStatCache.put(directory, item = new FileStatsCacheItem(directory));
+			return item.freeSpace;
+		}
+	
+		private boolean getCachedExistsStat(File directory) {
+			FileStatsCacheItem item = (FileStatsCacheItem) fileStatCache.get(directory);
+			if (item == null)
+				fileStatCache.put(directory, item = new FileStatsCacheItem(directory));
+			return item.exists;
+		}
+	
+		protected void setSelectedQueueLocation(int iLocation) {
+			torrentOptions.iQueueLocation = iLocation;
+	
+			updateStartOptionsHeader();
+		}
+	
+		private void updateStartOptionsHeader() {
+			if (soStartOptionsExpandItem == null) {
+				return;
+			}
+	
+			String optionText = MessageText.getString("OpenTorrentWindow.startMode."
+					+ startModes[torrentOptions.iStartID])
+					+ ", "
+					+ MessageText.getString("OpenTorrentWindow.addPosition."
+							+ queueLocations[torrentOptions.iQueueLocation]);
+	
+			String s = MessageText.getString("OpenTorrentOptions.header.startoptions",
+					new String[] {
+						optionText
+					});
+			
+			List<Tag> initialtags = torrentOptions.getInitialTags();
+			
+			String tag_str = null;
+			int numTags = 0;
+			
+			if ( initialtags.size() > 0 ){
+				
+				tag_str = "";
+				
+				for ( Tag t: initialtags ){
+					numTags++;
+					tag_str += (tag_str==""?"":", ") + t.getTagName( true );
+				}
+			}
+
+
+			String[] tagsToCreate = listTagsToCreate.toArray(new String[0]);
+			for (String tagName : tagsToCreate) {
+				numTags++;
+				if (tag_str == null) {
+					tag_str = tagName;
+				} else {
+					tag_str += (tag_str==""?"":", ") + tagName;
+				}
+			}
+			
+			if (numTags == 0) {
+				tag_str = MessageText.getString( "label.none" );
+			}
+
+			
+			s += "        " + MessageText.getString( "OpenTorrentOptions.header.tags", new String[]{ tag_str });
+			
+			soStartOptionsExpandItem.setText(s);
+		}
+	
+		protected void setSelectedStartMode(int iStartID) {
+			torrentOptions.iStartID = iStartID;
+	
+			checkSeedingMode();
+			updateStartOptionsHeader();
+		}
+	
+		private void setupFileAreaButtons(SWTSkinObjectContainer so) {
+			
+			PluginInterface	swarm_pi = null;
+			
+			try{
+				if (COConfigurationManager.getBooleanParameter("rcm.overall.enabled",
+						true) && AzureusCoreFactory.isCoreRunning()) {
+					final PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID(
+							"aercm");
+	
+					if (pi != null && pi.getPluginState().isOperational()
+							&& pi.getIPC().canInvoke("lookupBySize", new Object[] {
+								new Long(0)
+							})){
+						
+						swarm_pi = pi;
+					}
+				}
+			}catch( Throwable e ){
+					
+			}
+			
+			Composite cButtonsArea = so.getComposite();
+			GridLayout layout = new GridLayout(1,false);
+			layout.marginWidth = layout.marginHeight = layout.marginBottom = layout.marginTop = layout.marginLeft = layout.marginRight = 0;
+			cButtonsArea.setLayout(layout);
+
+			Composite cButtonsTop = new Composite(cButtonsArea, SWT.NULL);
+			layout = new GridLayout(swarm_pi==null?6:7,false);
+			layout.marginWidth = layout.marginHeight = layout.marginBottom = layout.marginTop = layout.marginLeft = layout.marginRight = 0;
+			cButtonsTop.setLayout(layout);
+			GridData gridData = new GridData( GridData.FILL_HORIZONTAL);
+			cButtonsTop.setLayoutData( gridData );
+
+			
+			Canvas line = new Canvas(cButtonsArea,SWT.NO_BACKGROUND);
+			line.addListener(SWT.Paint, new Listener() {
+				public void handleEvent(Event e) {
+					Rectangle clientArea = ((Canvas) e.widget).getClientArea();
+					e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
+					e.gc.drawRectangle(clientArea);
+					clientArea.y++;
+					e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
+					e.gc.drawRectangle(clientArea);
+				}
+			});
+			gridData = new GridData(GridData.FILL_HORIZONTAL);
+			gridData.heightHint = 2;
+			line.setLayoutData(gridData);
+
+			Composite cButtonsBottom = new Composite(cButtonsArea, SWT.NULL);
+			layout = new GridLayout(3,false);
+			layout.marginWidth = layout.marginHeight = layout.marginBottom = layout.marginTop = layout.marginLeft = layout.marginRight = 0;
+			cButtonsBottom.setLayout(layout);
+			gridData = new GridData( GridData.FILL_HORIZONTAL);
+			cButtonsBottom.setLayoutData( gridData );
+			
+			List<Button>	buttons = new ArrayList<Button>();
+			
+			btnSelectAll = new Button(cButtonsTop, SWT.PUSH);
+			buttons.add( btnSelectAll );
+			Messages.setLanguageText(btnSelectAll, "Button.selectAll");
+			btnSelectAll.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					tvFiles.selectAll();
+				}
+			});
+			
+			btnMarkSelected = new Button(cButtonsTop, SWT.PUSH);
+			buttons.add( btnMarkSelected );
+			Messages.setLanguageText(btnMarkSelected, "Button.mark");
+			btnMarkSelected.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					TorrentOpenFileOptions[] infos = tvFiles.getSelectedDataSources().toArray(new TorrentOpenFileOptions[0]);
+					setToDownload( infos, true );
+				}
+			});
+			
+			btnUnmarkSelected = new Button(cButtonsTop, SWT.PUSH);
+			buttons.add( btnUnmarkSelected );
+			Messages.setLanguageText(btnUnmarkSelected, "Button.unmark");
+			btnUnmarkSelected.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					TorrentOpenFileOptions[] infos = tvFiles.getSelectedDataSources().toArray(new TorrentOpenFileOptions[0]);
+					setToDownload( infos, false );
 	
 				}
 			});
 			
-			btnRename = new Button(cButtons, SWT.PUSH);
+			btnRename = new Button(cButtonsTop, SWT.PUSH);
 			buttons.add( btnRename );
 			Messages.setLanguageText(btnRename, "Button.rename");
 			btnRename.addListener(SWT.Selection, new Listener() {
@@ -1772,7 +2780,7 @@ public class OpenTorrentOptionsWindow
 				}
 			});
 	
-			btnRetarget = new Button(cButtons, SWT.PUSH);
+			btnRetarget = new Button(cButtonsTop, SWT.PUSH);
 			buttons.add( btnRetarget );
 			Messages.setLanguageText(btnRetarget, "Button.retarget");
 			btnRetarget.addListener(SWT.Selection, new Listener() {
@@ -1783,51 +2791,72 @@ public class OpenTorrentOptionsWindow
 				}
 			});
 			
-			try {
-				if (COConfigurationManager.getBooleanParameter("rcm.overall.enabled",
-						true) && AzureusCoreFactory.isCoreRunning()) {
-					final PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID(
-							"aercm");
-	
-					if (pi != null && pi.getPluginState().isOperational()
-							&& pi.getIPC().canInvoke("lookupBySize", new Object[] {
-								new Long(0)
-							})) {
-	
-						Label pad = new Label(cButtons, SWT.NONE);
-						GridData gridData = new GridData( GridData.FILL_HORIZONTAL);
-						pad.setLayoutData( gridData );
-						
-						btnSwarmIt = new Button(cButtons, SWT.PUSH);
-						buttons.add( btnSwarmIt );
-						Messages.setLanguageText(btnSwarmIt, "Button.swarmit");
+			Label pad1 = new Label(cButtonsTop, SWT.NONE);
+			gridData = new GridData( GridData.FILL_HORIZONTAL);
+			pad1.setLayoutData( gridData );
+			
+			// swarm-it button
+			
+			if ( swarm_pi != null ){
+				final PluginInterface f_pi = swarm_pi;
+				
+				btnSwarmIt = new Button(cButtonsTop, SWT.PUSH);
+				buttons.add( btnSwarmIt );
+				Messages.setLanguageText(btnSwarmIt, "Button.swarmit");
 	
-						btnSwarmIt.addListener(SWT.Selection, new Listener() {
-							public void handleEvent(Event event) {
-								List<Object> selectedDataSources = tvFiles.getSelectedDataSources();
-								for (Object ds : selectedDataSources) {
-									TorrentOpenFileOptions file = (TorrentOpenFileOptions) ds;
+				btnSwarmIt.addListener(SWT.Selection, new Listener() {
+					public void handleEvent(Event event) {
+						List<Object> selectedDataSources = tvFiles.getSelectedDataSources();
+						for (Object ds : selectedDataSources) {
+							TorrentOpenFileOptions file = (TorrentOpenFileOptions) ds;
 	
-									try {
-										pi.getIPC().invoke("lookupBySize", new Object[] {
-											new Long(file.lSize)
-										});
+							try {
+								f_pi.getIPC().invoke("lookupBySize", new Object[] {
+									new Long(file.lSize)
+								});
 	
-									} catch (Throwable e) {
+							} catch (Throwable e) {
 	
-										Debug.out(e);
-									}
-									break;
-								}
+								Debug.out(e);
 							}
-						});
-	
-						btnSwarmIt.setEnabled(false);
+							break;
+						}
 					}
-				}
-			} catch (Throwable e) {
+				});
 	
+				btnSwarmIt.setEnabled(false);
 			}
+		
+			
+			Label pad2 = new Label(cButtonsBottom, SWT.NONE);
+			gridData = new GridData( GridData.FILL_HORIZONTAL);
+			pad2.setLayoutData( gridData );
+
+				// ratings etc
+			
+			btnCheckComments = new Button(cButtonsBottom, SWT.PUSH);
+			buttons.add( btnCheckComments );
+			Messages.setLanguageText(btnCheckComments, "label.comments");
+			
+			btnCheckComments.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					showComments();
+				}
+			});
+				// availability button
+			
+			btnCheckAvailability = new Button(cButtonsBottom, SWT.PUSH);
+			buttons.add( btnCheckAvailability );
+			Messages.setLanguageText(btnCheckAvailability, "label.check.avail");
+
+			btnCheckAvailability.addListener(SWT.Selection, new Listener() {
+				public void handleEvent(Event event) {
+					showAvailability();
+				}
+			});
+			
+			
+
 	
 			Utils.makeButtonsEqualWidth( buttons );
 			
@@ -1873,6 +2902,103 @@ public class OpenTorrentOptionsWindow
 			cmbDataDir = new Combo(soInputArea.getComposite(), SWT.NONE);
 			cmbDataDir.setLayoutData(Utils.getFilledFormData());
 	
+			cmbDataDir.addKeyListener(
+				new KeyListener(){					
+					public void keyReleased(KeyEvent e) {
+						if ( e.keyCode == SWT.SPACE && ( e.stateMask & SWT.MODIFIER_MASK ) != 0 ){
+							
+							e.doit = false;
+						}
+					}
+					
+					public void keyPressed(KeyEvent e) {
+												
+						if ( e.keyCode == SWT.SPACE && ( e.stateMask & SWT.MODIFIER_MASK ) != 0 ){
+						
+							e.doit = false;
+							
+							Menu menu = cmbDataDir.getMenu();
+							
+							if ( menu != null && !menu.isDisposed()){
+								
+								menu.dispose();
+							}
+							
+							menu = new Menu( cmbDataDir );
+														
+							String current_text = cmbDataDir.getText();
+							
+							String def = COConfigurationManager.getStringParameter(PARAM_DEFSAVEPATH);
+							
+							List<String> items = new ArrayList<String>( Arrays.asList( cmbDataDir.getItems()));
+							
+							if ( !items.contains( def )){
+								
+								items.add( def );
+							}
+							
+							List<String>	suggestions = new ArrayList<String>();
+							
+							for ( String item: items ){
+								
+								if ( item.toLowerCase(Locale.US).contains( current_text.toLowerCase( Locale.US ))){
+									
+									suggestions.add( item );
+								}
+							}
+						
+							if ( suggestions.size() == 0 ){
+							
+								MenuItem mi = new MenuItem( menu, SWT.PUSH );
+								
+								mi.setText( MessageText.getString( "label.no.suggestions" ));
+								
+								mi.setEnabled( false );
+								
+							}else{
+								
+								//Collections.sort( suggestions );
+								
+								for ( final String str: suggestions ){
+									
+									MenuItem mi = new MenuItem( menu, SWT.PUSH );
+									
+									mi.setText( str );
+									
+									mi.addSelectionListener(
+										new SelectionAdapter() {
+											
+											public void 
+											widgetSelected(SelectionEvent e) {
+												
+												cmbDataDir.setText( str );
+											}
+										});
+								}
+							}
+							
+							cmbDataDir.setMenu( menu );
+							
+							final Point cursorLocation = Display.getCurrent().getCursorLocation();
+														
+							menu.setLocation( cursorLocation.x-10, cursorLocation.y-10 );
+							
+							menu.setVisible( true );
+							
+							Utils.execSWTThread(
+								new Runnable() {
+									
+									public void run() {
+										// need to do this to get the menu item selected correctly
+										Display.getCurrent().setCursorLocation(cursorLocation.x+1,cursorLocation.y);
+									}
+								}, true );
+						}
+					}
+				});
+			
+			cmbDataDir.setToolTipText( MessageText.getString( "label.ctrl.space.for.suggestion" ));
+			
 			cmbDataDir.addModifyListener(new ModifyListener() {
 				public void modifyText(ModifyEvent e) {
 					cmbDataDirChanged();
@@ -1996,15 +3122,15 @@ public class OpenTorrentOptionsWindow
 				Messages.setLanguageText(label, "label.initial_tags");
 		
 				
-				Composite tagButtons 	= new Composite( tagRight, SWT.NULL);
+				tagButtonsArea 	= new Composite( tagRight, SWT.NULL);
 				gridData = new GridData(GridData.FILL_HORIZONTAL );
-				tagButtons.setLayoutData(gridData);
+				tagButtonsArea.setLayoutData(gridData);
 		
 				RowLayout tagLayout = new RowLayout();
 				tagLayout.pack = false;
-				tagButtons.setLayout( tagLayout);
+				tagButtonsArea.setLayout( tagLayout);
 				
-				buildTagButtonPanel( tagButtons );
+				buildTagButtonPanel( tagButtonsArea );
 				
 				Button addTag = new Button( tagRight, SWT.NULL );
 				addTag.setLayoutData( new GridData(GridData.VERTICAL_ALIGN_CENTER ));
@@ -2017,7 +3143,7 @@ public class OpenTorrentOptionsWindow
 						widgetSelected(
 							SelectionEvent e) 
 						{
-							TagUIUtils.createManualTag();
+							TagUIUtilsV3.showCreateTagDialog(null);
 						}
 					});
 			}
@@ -2054,7 +3180,7 @@ public class OpenTorrentOptionsWindow
 			final TagType tt = TagManagerFactory.getTagManager().getTagType( TagType.TT_DOWNLOAD_MANUAL );
 			
 			List<Tag> initialTags = torrentOptions.getInitialTags();
-	
+			
 			for ( final Tag tag: TagUIUtils.sortTags( tt.getTags())){
 				
 				if ( tag.canBePublic() && !tag.isTagAuto()){
@@ -2125,11 +3251,61 @@ public class OpenTorrentOptionsWindow
 					Menu menu = new Menu( but );
 					
 					but.setMenu( menu );
+					MenuBuildUtils.addMaintenanceListenerForMenu(menu, new MenuBuilder() {
+						public void buildMenu(Menu root_menu, MenuEvent menuEvent) {
+							TagUIUtils.createSideBarMenuItems(root_menu, tag);
+						}
+					});
 					
-					TagUIUtils.createSideBarMenuItems(menu, tag);
 				}
 			}
 			
+			String[] discoveredTags = listDiscoveredTags.toArray(new String[0]);
+			for (final String tagName : discoveredTags) {
+				boolean alreadyHave = checkAlreadyHaveTag(initialTags, tagName);
+				if (alreadyHave) {
+					break;
+				}
+				
+				final Button but = new Button( parent, SWT.TOGGLE );
+				but.setImage(ImageLoader.getInstance().getImage("image.sidebar.rcm"));
+
+				
+				if ( listTagsToCreate.contains( tagName )){
+					but.setSelection( true );
+				}
+
+				
+				but.setText( tagName );
+				
+				but.setToolTipText(MessageText.getString("tagtype.discovered"));
+				
+				but.addSelectionListener(
+					new SelectionAdapter() {
+						
+						public void 
+						widgetSelected(
+							SelectionEvent e) 
+						{
+							List<Tag>  tags = torrentOptions.getInitialTags();
+							
+							if ( but.getSelection()){
+								
+								listTagsToCreate.add(tagName);
+								
+							}else{
+								
+								listTagsToCreate.remove(tagName);
+								
+							}
+							
+							
+							updateStartOptionsHeader();
+						}
+					});
+				
+			}
+			
 			if ( is_rebuild ){
 			
 				parent.getParent().layout( true,  true );
@@ -2190,7 +3366,7 @@ public class OpenTorrentOptionsWindow
 				}, false );
 		}
 	
-		private void setupTVFiles(SWTSkinObjectContainer soFilesTable) {
+		private void setupTVFiles(SWTSkinObjectContainer soFilesTable, SWTSkinObjectTextbox soFilesFilter ) {
 			TableColumnManager tcm = TableColumnManager.getInstance();
 			if (tcm.getDefaultColumnNames(TABLEID_FILES) == null) {
 				tcm.registerColumn(TorrentOpenFileOptions.class,
@@ -2256,6 +3432,21 @@ public class OpenTorrentOptionsWindow
 			tvFiles.initialize(soFilesTable.getComposite());
 			tvFiles.setRowDefaultHeight(20);
 	
+			if ( torrentOptions.getFiles().length > 1 && soFilesFilter != null ){
+				
+				soFilesFilter.setVisible( true );
+				
+				Text text = soFilesFilter.getTextControl();
+								
+				tvFiles.enableFilterCheck(text, this);
+		
+			}else{
+				if ( soFilesFilter != null ){
+					
+					soFilesFilter.setVisible( false );
+				}
+			}
+			
 			tvFiles.addKeyListener(new KeyListener() {
 	
 				public void keyPressed(KeyEvent e) {
@@ -2264,11 +3455,13 @@ public class OpenTorrentOptionsWindow
 				public void keyReleased(KeyEvent e) {
 					if (e.keyCode == SWT.SPACE) {
 						TableRowCore focusedRow = tvFiles.getFocusedRow();
-						TorrentOpenFileOptions tfi_focus = ((TorrentOpenFileOptions) focusedRow.getDataSource());
-						boolean download = !tfi_focus.isToDownload();
-	
-						TorrentOpenFileOptions[] infos = tvFiles.getSelectedDataSources().toArray(new TorrentOpenFileOptions[0]);
-						setToDownload( infos, download );
+						if ( focusedRow != null ){
+							TorrentOpenFileOptions tfi_focus = ((TorrentOpenFileOptions) focusedRow.getDataSource());
+							boolean download = !tfi_focus.isToDownload();
+		
+							TorrentOpenFileOptions[] infos = tvFiles.getSelectedDataSources().toArray(new TorrentOpenFileOptions[0]);
+							setToDownload( infos, download );
+						}
 					}
 					if (e.keyCode == SWT.F2 && (e.stateMask & SWT.MODIFIER_MASK) == 0) {
 						TorrentOpenFileOptions[] infos = tvFiles.getSelectedDataSources().toArray(
@@ -2538,12 +3731,47 @@ public class OpenTorrentOptionsWindow
 						 new MenuItem(menu, SWT.SEPARATOR );
 						 
 						 item = new MenuItem(menu, SWT.PUSH);
-							Messages.setLanguageText(item, "OpenTorrentWindow.set.savepath");
-							item.addSelectionListener(new SelectionAdapter() {
+						
+						 Messages.setLanguageText(item, "OpenTorrentWindow.set.savepath");
+						
+						 item.addSelectionListener(new SelectionAdapter() {
 								public void widgetSelected(SelectionEvent e) {
 									setSavePath();
 								}
 							});
+							
+						 item = new MenuItem(menu, SWT.PUSH);
+						
+						 Messages.setLanguageText(item, "OpenTorrentWindow.tlf.remove");
+						
+						 item.addSelectionListener(new SelectionAdapter() {
+								public void widgetSelected(SelectionEvent e) {
+									removeTopLevelFolder();
+								}
+							});
+						 
+						 item.setEnabled( canRemoveTopLevelFolder());
+						 
+						 item = new MenuItem(menu, SWT.CHECK );
+						
+						 item.setSelection( COConfigurationManager.getBooleanParameter( "open.torrent.window.rename.on.tlf.change" ));
+							
+						 Messages.setLanguageText(item, "OpenTorrentWindow.tlf.rename");
+
+						 item.addSelectionListener(
+							 new SelectionAdapter() 
+							 {
+								 public void 
+								 widgetSelected(
+										 SelectionEvent e )
+								 {
+									 COConfigurationManager.setParameter(
+											"open.torrent.window.rename.on.tlf.change", 
+											((MenuItem)e.widget).getSelection());
+								 }
+							 });
+						 
+						 new MenuItem(menu, SWT.SEPARATOR );
 					}
 				}
 	
@@ -2578,6 +3806,47 @@ public class OpenTorrentOptionsWindow
 			tvFiles.addDataSources(torrentOptions.getFiles());
 		}
 	
+		public boolean 
+		filterCheck(
+			TorrentOpenFileOptions 	ds, 
+			String 					filter, 
+			boolean 				regex )
+		{
+			if ( filter == null || filter.length() == 0 ){
+				
+				return( true );
+			}
+			
+			try {
+				File file = ds.getDestFileFullName();
+
+				String name = filter.contains( File.separator )?file.getAbsolutePath():file.getName();
+				
+				String s = regex ? filter : "\\Q" + filter.replaceAll("\\s*[|;]\\s*", "\\\\E|\\\\Q") + "\\E";
+				
+				boolean	match_result = true;
+				
+				if ( regex && s.startsWith( "!" )){
+					
+					s = s.substring(1);
+					
+					match_result = false;
+				}
+				
+				Pattern pattern = RegExUtil.getCachedPattern( "fv:search", s, Pattern.CASE_INSENSITIVE);
+	  
+				return( pattern.matcher(name).find() == match_result );
+				
+			} catch (Exception e) {
+				
+				return true;
+			}	
+		}
+		
+		public void filterSet(String filter)
+		{
+		}
+		
 		protected void updateFileButtons() {
 			Utils.execSWTThread(new AERunnable() {
 				public void runSupport() {
@@ -2603,10 +3872,17 @@ public class OpenTorrentOptionsWindow
 						}
 					}
 					
-					btnSelectAll.setEnabled(  rows.length < torrentOptions.getFiles().length );
+					if ( btnSelectAll != null && !btnSelectAll.isDisposed()){						
+						btnSelectAll.setEnabled(  rows.length < torrentOptions.getFiles().length );
+					}
+					
+					if ( btnMarkSelected != null && !btnMarkSelected.isDisposed() ){
+						btnMarkSelected.setEnabled( hasRowsSelected && !all_marked );
+					}
 					
-					btnMarkSelected.setEnabled( hasRowsSelected && !all_marked );
-					btnUnmarkSelected.setEnabled( hasRowsSelected && !all_unmarked );
+					if ( btnUnmarkSelected != null && !btnUnmarkSelected.isDisposed() ){					
+						btnUnmarkSelected.setEnabled( hasRowsSelected && !all_unmarked );
+					}
 					
 					if (btnSwarmIt != null && !btnSwarmIt.isDisposed()){
 						boolean	enable=false;
@@ -2626,7 +3902,7 @@ public class OpenTorrentOptionsWindow
 				if (renameFilename == null) {
 					break;
 				}
-				torrentFileInfo.setDestFileName(renameFilename);
+				torrentFileInfo.setDestFileName(renameFilename,true);
 				TableRowCore row = tvFiles.getRow(torrentFileInfo);
 				if (row != null) {
 					row.invalidate(true);
@@ -2698,9 +3974,87 @@ public class OpenTorrentOptionsWindow
 					return;
 				}
 				
-				torrentOptions.setParentDir( new_parent.getAbsolutePath());
-				torrentOptions.setSubDir( newDir.getName());
-			
+				torrentOptions.setExplicitDataDir( new_parent.getAbsolutePath(), newDir.getName());
+				
+				if ( COConfigurationManager.getBooleanParameter( "open.torrent.window.rename.on.tlf.change" )){
+				
+					torrentOptions.setManualRename( new_parent.getName());
+					
+				}else{
+					
+					torrentOptions.setManualRename( null );
+				}
+				
+				updateDataDirCombo();
+				
+				cmbDataDirChanged();
+				
+				
+				/* old window used to reset this - not sure why, if the user's
+				 * made some per-file changes already then we should keep them
+				for ( TorrentOpenFileOptions tfi: torrentOptions.getFiles()){
+					
+					tfi.setFullDestName( null );
+				}
+				*/
+			}
+		}
+		
+		private boolean
+		canRemoveTopLevelFolder()
+		{
+			if ( torrentOptions.isSimpleTorrent()){
+				
+				return( false );
+				
+			}else{
+				
+				File oldDir = new File( torrentOptions.getDataDir());
+	
+				File newDir = oldDir.getParentFile();
+				
+				File newParent  = newDir.getParentFile();
+				
+					// newParent will be null if trying to remove the top level dir when already at a file system
+					// root (e.g. C:\) 
+					// we should of course be able to support this, but unfortunately there's lots of code in Vuze
+					// in places-i-don't-want-to-change that borks if we try and do this (feel free to try...)
+				
+				return( newParent != null );
+			}
+		}
+		
+		private void
+		removeTopLevelFolder()
+		{
+			if ( torrentOptions.isSimpleTorrent()){
+				
+				
+			}else{
+				
+				File oldDir = new File( torrentOptions.getDataDir());
+	
+				File newDir = oldDir.getParentFile();
+				
+				File newParent  = newDir.getParentFile();
+				if ( newParent == null ){
+					
+					Debug.out( "Invalid save path, parent folder is null" );
+					
+					return;
+				}
+				
+				torrentOptions.setExplicitDataDir( newParent.getAbsolutePath(), newDir.getName());
+				
+				if ( COConfigurationManager.getBooleanParameter( "open.torrent.window.rename.on.tlf.change" )){
+				
+					torrentOptions.setManualRename( newParent.getName());
+					
+				}else{
+					
+					torrentOptions.setManualRename( null );
+				}
+				
 				updateDataDirCombo();
 				
 				cmbDataDirChanged();
@@ -2889,17 +4243,51 @@ public class OpenTorrentOptionsWindow
 		private void setupInfoFields(SWTSkin skin) {
 			SWTSkinObject so;
 			so = skin.getSkinObject("torrentinfo-name");
+			TOTorrent torrent = torrentOptions.getTorrent();
+
 			if (so instanceof SWTSkinObjectText) {
-				((SWTSkinObjectText) so).setText(torrentOptions.getTorrentName());
+				
+				String hash_str = null;
+				
+				try{
+					hash_str = ByteFormatter.encodeString(torrentOptions.getTorrent().getHash());
+					
+				}catch( Throwable e ){
+				}
+				
+				SWTSkinObjectText text = (SWTSkinObjectText)so;
+				
+				text.setText( torrentOptions.getTorrentName() +  (hash_str==null?"":("\u00a0\u00a0\u00a0\u00a0[" + hash_str + "]")));
+				
+				if ( hash_str != null ){
+					
+					final String f_hash_str = hash_str;
+					
+					ClipboardCopy.addCopyToClipMenu(
+						text.getControl(),
+						new ClipboardCopy.copyToClipProvider2() {
+							
+							public String 
+							getMenuResource() 
+							{
+								return( "menu.copy.hash.to.clipboard" );
+							}
+							
+							public String 
+							getText() 
+							{
+								return( f_hash_str );
+							}
+						});
+				}
 			}
 	
 			so = skin.getSkinObject("torrentinfo-trackername");
 			
-			TOTorrent torrent = torrentOptions.getTorrent();
 			
 			if ( torrent != null ){
 				if (so instanceof SWTSkinObjectText) {
-					((SWTSkinObjectText) so).setText(TrackerNameItem.getTrackerName(torrent));
+					((SWTSkinObjectText) so).setText(TrackerNameItem.getTrackerName(torrent) + ((torrent==null||!torrent.getPrivate())?"":(" (private)")));
 				}
 		
 				so = skin.getSkinObject("torrentinfo-comment");
@@ -2916,7 +4304,7 @@ public class OpenTorrentOptionsWindow
 		
 				so = skin.getSkinObject("torrentinfo-createdon");
 				if (so instanceof SWTSkinObjectText) {
-					String creation_date = DisplayFormatters.formatDate(torrent.getCreationDate());
+					String creation_date = DisplayFormatters.formatDate(torrent.getCreationDate() * 1000l);
 					((SWTSkinObjectText) so).setText(creation_date);
 				}
 			}
@@ -2943,10 +4331,60 @@ public class OpenTorrentOptionsWindow
 				}});
 		}
 		
+		private void setupUpDownLimitOption(SWTSkinObjectContainer so) {
+			Composite parent = so.getComposite();
+	
+			parent.setBackgroundMode( SWT.INHERIT_FORCE );	// win 7 classic theme shows grey background without this
+			parent.setLayout( new GridLayout(4, false));
+			
+			GridData gridData = new GridData();
+			Label label = new Label(parent, SWT.NULL);
+			label.setText( MessageText.getString( "TableColumn.header.maxupspeed") + "[" + DisplayFormatters.getRateUnit(DisplayFormatters.UNIT_KB  ) + "]" );
+
+			gridData = new GridData();
+			GenericIntParameter paramMaxUploadSpeed = 
+				new GenericIntParameter(
+					new IntAdapter()
+					{
+						public void
+						setIntValue(
+							String	key,
+							int		value )
+						{
+							torrentOptions.setMaxUploadSpeed( value );
+						}
+					},
+					parent,
+					"torrentoptions.config.uploadspeed", 0, Integer.MAX_VALUE );
+			
+			paramMaxUploadSpeed.setLayoutData(gridData);
+
+			label = new Label(parent, SWT.NULL);
+			label.setText( MessageText.getString( "TableColumn.header.maxdownspeed") + "[" + DisplayFormatters.getRateUnit(DisplayFormatters.UNIT_KB  ) + "]" );
+
+			gridData = new GridData();
+			GenericIntParameter paramMaxDownloadSpeed = 
+				new GenericIntParameter(
+					new IntAdapter()
+					{
+						public void
+						setIntValue(
+							String	key,
+							int		value )
+						{
+							torrentOptions.setMaxDownloadSpeed( value );
+						}
+					},
+					parent,
+					"torrentoptions.config.downloadspeed", 0, Integer.MAX_VALUE );
+			
+			paramMaxDownloadSpeed.setLayoutData(gridData);
+		}
+		
 		private void setupIPFilterOption(SWTSkinObjectContainer so) {
 			Composite parent = so.getComposite();
 	
-			parent.setBackgroundMode( SWT.INHERIT_FORCE );	// win 7 classic theme sows grey background without this
+			parent.setBackgroundMode( SWT.INHERIT_FORCE );	// win 7 classic theme shows grey background without this
 			parent.setLayout( new GridLayout());
 			
 			Button button = new Button(parent, SWT.CHECK | SWT.WRAP );
@@ -2964,46 +4402,88 @@ public class OpenTorrentOptionsWindow
 	
 		}
 	
-		private void setupPeerSourcesOptions(SWTSkinObjectContainer so) {
+		private void setupPeerSourcesAndNetworkOptions(SWTSkinObjectContainer so) {
 			Composite parent = so.getComposite();
-			parent.setBackgroundMode( SWT.INHERIT_FORCE );	// win 7 classic theme sows grey background without this
+			parent.setBackgroundMode( SWT.INHERIT_FORCE );	// win 7 classic theme shows grey background without this
 
+		
 			Group peer_sources_group = new Group(parent, SWT.NULL);
-			Messages.setLanguageText(peer_sources_group,
-					"ConfigView.section.connection.group.peersources");
-			GridLayout peer_sources_layout = new GridLayout(3, true);
-			peer_sources_group.setLayout(peer_sources_layout);
-	
-			peer_sources_group.setLayoutData(Utils.getFilledFormData());
-	
-			//		Label label = new Label(peer_sources_group, SWT.WRAP);
-			//		Messages.setLanguageText(label,
-			//				"ConfigView.section.connection.group.peersources.info");
-			//		GridData gridData = new GridData();
-			//		label.setLayoutData(gridData);
-	
-			for (int i = 0; i < PEPeerSource.PS_SOURCES.length; i++) {
-	
-				final String p = PEPeerSource.PS_SOURCES[i];
-	
-				String config_name = "Peer Source Selection Default." + p;
-				String msg_text = "ConfigView.section.connection.peersource." + p;
-	
-				Button button = new Button(peer_sources_group, SWT.CHECK);
-				Messages.setLanguageText(button, msg_text);
-	
-				button.setSelection(COConfigurationManager.getBooleanParameter(config_name));
+			
+			{
+				Messages.setLanguageText(peer_sources_group,
+						"ConfigView.section.connection.group.peersources");
+				GridLayout peer_sources_layout = new GridLayout(3, true);
+				peer_sources_group.setLayout(peer_sources_layout);
 				
-				button.addSelectionListener(new SelectionAdapter() {
-					public void widgetSelected(SelectionEvent e) {
-						torrentOptions.peerSource.put(p, ((Button)e.widget).getSelection());
-					}
-				});
-	
-				GridData gridData = new GridData();
-				button.setLayoutData(gridData);
+				FormData form_data = Utils.getFilledFormData();
+				form_data.bottom = null;
+				peer_sources_group.setLayoutData(form_data);
+		
+				//		Label label = new Label(peer_sources_group, SWT.WRAP);
+				//		Messages.setLanguageText(label,
+				//				"ConfigView.section.connection.group.peersources.info");
+				//		GridData gridData = new GridData();
+				//		label.setLayoutData(gridData);
+		
+				for (int i = 0; i < PEPeerSource.PS_SOURCES.length; i++) {
+		
+					final String p = PEPeerSource.PS_SOURCES[i];
+		
+					String config_name = "Peer Source Selection Default." + p;
+					String msg_text = "ConfigView.section.connection.peersource." + p;
+		
+					Button button = new Button(peer_sources_group, SWT.CHECK);
+					Messages.setLanguageText(button, msg_text);
+		
+					button.setSelection(COConfigurationManager.getBooleanParameter(config_name));
+					
+					button.addSelectionListener(new SelectionAdapter() {
+						public void widgetSelected(SelectionEvent e) {
+							torrentOptions.peerSource.put(p, ((Button)e.widget).getSelection());
+						}
+					});
+		
+					GridData gridData = new GridData();
+					button.setLayoutData(gridData);
+				}
 			}
 	
+				// networks
+			
+			{				
+				Group network_group = new Group(parent, SWT.NULL);
+				Messages.setLanguageText(network_group,
+						"ConfigView.section.connection.group.networks");
+				GridLayout network_layout = new GridLayout(3, true);
+				network_group.setLayout(network_layout);
+		
+				FormData form_data = Utils.getFilledFormData();
+				form_data.top = new FormAttachment( peer_sources_group );
+				network_group.setLayoutData(form_data);
+		
+				for (int i = 0; i < AENetworkClassifier.AT_NETWORKS.length; i++) {
+		
+					final String nn = AENetworkClassifier.AT_NETWORKS[i];
+		
+					String msg_text = "ConfigView.section.connection.networks." + nn;
+		
+					Button button = new Button(network_group, SWT.CHECK);
+					Messages.setLanguageText(button, msg_text);
+		
+					Map<String,Boolean> enabledNetworks = torrentOptions.getEnabledNetworks();
+
+					button.setSelection(enabledNetworks.get( nn ));
+					
+					button.addSelectionListener(new SelectionAdapter() {
+						public void widgetSelected(SelectionEvent e) {
+							torrentOptions.setNetworkEnabled(nn, ((Button)e.widget).getSelection());
+						}
+					});
+		
+					GridData gridData = new GridData();
+					button.setLayoutData(gridData);
+				}
+			}
 		}
 	
 		private void updateDataDirCombo() {
@@ -3012,11 +4492,47 @@ public class OpenTorrentOptionsWindow
 				return;
 			}
 	
-			try {
+			try{
 				bSkipDataDirModify = true;
 	
-				cmbDataDir.setText( torrentOptions==null?"":torrentOptions.getParentDir());
-			} finally {
+				if ( torrentOptions == null ){
+					
+					String prev_parent = null;
+					
+					boolean not_same = false;
+					
+					for ( TorrentOpenOptions to: torrentOptionsMulti ){
+						
+						String parent = to.getParentDir();
+						
+						if ( prev_parent != null && !prev_parent.equals( parent )){
+							
+							not_same = true;
+							
+							break;
+						}
+						
+						prev_parent = parent;
+						
+					}
+					
+					if ( not_same ){
+											
+						cmbDataDir.setText( COConfigurationManager.getStringParameter(PARAM_DEFSAVEPATH));
+						
+					}else{
+						
+							// prev_parent can be null when we're tearing down the dialog...
+						
+						cmbDataDir.setText( prev_parent==null?"":prev_parent );
+					}
+				}else{
+					
+					cmbDataDir.setText( torrentOptions.getParentDir());
+				}
+				
+			}finally{
+				
 				bSkipDataDirModify = false;
 			}
 		}
@@ -3347,68 +4863,106 @@ public class OpenTorrentOptionsWindow
 			}
 	
 			String sDefaultPath = COConfigurationManager.getStringParameter(PARAM_DEFSAVEPATH);
-			if (!torrentOptions.getParentDir().equals(sDefaultPath)) {
-				// Move sDestDir to top of list
-	
-				// First, check to see if sDestDir is already in the list
-				File fDestDir = new File(torrentOptions.getParentDir());
-				int iDirPos = -1;
-				for (int i = 0; i < dirList.size(); i++) {
-					String sDirName = dirList.get(i);
-					File dir = new File(sDirName);
-					if (dir.equals(fDestDir)) {
-						iDirPos = i;
-						break;
+			
+			String dataDir;
+			
+			if ( torrentOptions.isExplicitDataDir()){
+				
+				dataDir = torrentOptions.getDataDir();
+			
+			}else{
+				
+				dataDir = torrentOptions.getParentDir();
+			}
+			
+			if (!dataDir.equals(sDefaultPath)) {
+				
+				int	 limit = COConfigurationManager.getIntParameter( "saveTo_list.max_entries" );
+
+				if ( limit >= 0 ){
+
+					// Move sDestDir to top of list
+		
+					// First, check to see if sDestDir is already in the list
+					File fDestDir = new File(dataDir);
+					int iDirPos = -1;
+					for (int i = 0; i < dirList.size(); i++) {
+						String sDirName = dirList.get(i);
+						File dir = new File(sDirName);
+						if (dir.equals(fDestDir)) {
+							iDirPos = i;
+							break;
+						}
 					}
-				}
-	
-				// If already in list, remove it
-				if (iDirPos > 0 && iDirPos < dirList.size())
-					dirList.remove(iDirPos);
-	
-				// and add it to the top
-				dirList.add(0, torrentOptions.getParentDir());
-	
-				// Limit
-				if (dirList.size() > 15)
-					dirList.remove(dirList.size() - 1);
-	
-				// Temporary list cleanup
-				try {
-					for (int j = 0; j < dirList.size(); j++) {
-						File dirJ = new File(dirList.get(j));
-						for (int i = 0; i < dirList.size(); i++) {
-							try {
-								if (i == j)
-									continue;
-	
-								File dirI = new File(dirList.get(i));
-	
-								if (dirI.equals(dirJ)) {
-									dirList.remove(i);
-									// dirList shifted up, fix indexes
-									if (j > i)
-										j--;
-									i--;
+		
+					// If already in list, remove it
+					if (iDirPos > 0 && iDirPos < dirList.size())
+						dirList.remove(iDirPos);
+		
+					// and add it to the top
+					dirList.add(0, dataDir );
+		
+					// Limit
+					if (limit > 0 && dirList.size() > limit){
+						dirList.remove(dirList.size() - 1);
+					}
+					
+					// Temporary list cleanup
+					try {
+						for (int j = 0; j < dirList.size(); j++) {
+							File dirJ = new File(dirList.get(j));
+							for (int i = 0; i < dirList.size(); i++) {
+								try {
+									if (i == j)
+										continue;
+		
+									File dirI = new File(dirList.get(i));
+		
+									if (dirI.equals(dirJ)) {
+										dirList.remove(i);
+										// dirList shifted up, fix indexes
+										if (j > i)
+											j--;
+										i--;
+									}
+								} catch (Exception e) {
+									// Ignore
 								}
-							} catch (Exception e) {
-								// Ignore
 							}
 						}
+					} catch (Exception e) {
+						// Ignore
 					}
-				} catch (Exception e) {
-					// Ignore
+		
+					COConfigurationManager.setParameter("saveTo_list", dirList);
+					COConfigurationManager.save();
 				}
-	
-				COConfigurationManager.setParameter("saveTo_list", dirList);
-				COConfigurationManager.save();
 			}
 	
-			if (COConfigurationManager.getBooleanParameter("DefaultDir.AutoUpdate")) {
-				COConfigurationManager.setParameter(PARAM_DEFSAVEPATH,
-						torrentOptions.getParentDir());
+			if (COConfigurationManager.getBooleanParameter("DefaultDir.AutoUpdate")){
+				COConfigurationManager.setParameter( PARAM_DEFSAVEPATH, dataDir );
 			}
 		
+			
+			if (listTagsToCreate.size() > 0) {
+				TagManager tagManager = TagManagerFactory.getTagManager();
+				TagType tagType = tagManager.getTagType(TagType.TT_DOWNLOAD_MANUAL);
+				String[] tagsToCreate = listTagsToCreate.toArray(new String[0]);
+				
+				List<Tag> initialTags = torrentOptions.getInitialTags();
+				
+				for (String tagName : tagsToCreate) {
+					try {
+						Tag tag = tagType.createTag(tagName, true);
+						tag.setPublic(true);
+						listTagsToCreate.remove(tagName);
+						initialTags.add(tag);
+					} catch (TagException e) {
+					}
+				}
+				torrentOptions.setInitialTags(initialTags);
+			}
+			
 			return true;
 		}
 		
@@ -3426,4 +4980,44 @@ public class OpenTorrentOptionsWindow
 		instanceChanged(
 			OpenTorrentInstance		instance );
 	}
+	
+	private class
+	IntAdapter
+		extends GenericParameterAdapter
+	{
+		public int
+		getIntValue(
+			String	key )
+		{
+			return( 0 );
+		}
+		
+		public int
+		getIntValue(
+			String	key,
+			int		def )
+		{
+			return( def );
+		}
+		
+		
+		public boolean
+		resetIntDefault(
+			String	key )
+		{
+			return( false );
+		}	
+	}
+
+	public boolean checkAlreadyHaveTag(List<Tag> initialTags, String tagName) {
+		boolean alreadyHave = false;
+		for (Tag tag : initialTags) {
+			if (tagName.equalsIgnoreCase(tag.getTagName(false))
+					|| tagName.equalsIgnoreCase(tag.getTagName(true))) {
+				alreadyHave = true;
+				break;
+			}
+		}
+		return alreadyHave;
+	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/OpenTorrentWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/OpenTorrentWindow.java
index fda2510..2a92350 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/OpenTorrentWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/OpenTorrentWindow.java
@@ -18,6 +18,7 @@
 package com.aelitis.azureus.ui.swt.shells.opentorrent;
 
 import java.io.*;
+import java.net.URL;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.dnd.Clipboard;
@@ -35,6 +36,12 @@ import org.gudy.azureus2.core3.torrent.impl.TorrentOpenOptions;
 import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloader;
 import org.gudy.azureus2.core3.torrentdownloader.TorrentDownloaderCallBackInterface;
 import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.ui.UIManager;
+import org.gudy.azureus2.plugins.ui.UIManagerEvent;
+import org.gudy.azureus2.plugins.utils.StaticUtilities;
+import org.gudy.azureus2.plugins.utils.subscriptions.SubscriptionManager;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.pluginsimpl.local.utils.xml.rss.RSSUtils;
 import org.gudy.azureus2.ui.swt.*;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
@@ -511,18 +518,60 @@ public class OpenTorrentWindow
 
 		// The default is to delete file on cancel
 		// We set this flag to false if we detected the file was not a torrent
-		if (!inf.getDeleteFileOnCancel()
-				&& (state == TorrentDownloader.STATE_CANCELLED
-						|| state == TorrentDownloader.STATE_ERROR
-						|| state == TorrentDownloader.STATE_DUPLICATE || state == TorrentDownloader.STATE_FINISHED)) {
+		if (!inf.getDeleteFileOnCancel() &&
+				(	state == TorrentDownloader.STATE_CANCELLED ||
+					state == TorrentDownloader.STATE_ERROR ||
+					state == TorrentDownloader.STATE_DUPLICATE || 
+					state == TorrentDownloader.STATE_FINISHED)){
 
 			File file = inf.getFile();
+			
 			// we already know it isn't a torrent.. we are just using the call
 			// to popup the message
-			TorrentUtil.isFileTorrent(file, inf.getURL());
+			
+			boolean	done = false;
+
+			if ( RSSUtils.isRSSFeed( file )){
+								
+				try{
+					URL url = new URL( inf.getURL() );
+					
+					UIManager ui_manager = StaticUtilities.getUIManager( 10*1000 );
+					
+					if ( ui_manager != null ){
+					
+						String details = MessageText.getString(
+								"subscription.request.add.message",
+								new String[]{ inf.getURL() });
+						
+						long res = ui_manager.showMessageBox(
+								"subscription.request.add.title",
+								"!" + details + "!",
+								UIManagerEvent.MT_YES | UIManagerEvent.MT_NO );
+						
+						if ( res == UIManagerEvent.MT_YES ){
+								
+							SubscriptionManager sm = PluginInitializer.getDefaultInterface().getUtilities().getSubscriptionManager();
+
+							sm.requestSubscription( url );
+							
+							done = true;
+						}
+					}				
+				}catch( Throwable e ){
+					
+					Debug.out( e );
+				}
+			}
+			
+			if ( !done ){
+				TorrentUtil.isFileTorrent(file, inf.getURL(), true );
+			}
+			
 			if (file.exists()) {
 				file.delete();
 			}
+			
 			return;
 		}
 
@@ -549,11 +598,16 @@ public class OpenTorrentWindow
 			int count = inf.getLastReadCount();
 			int numRead = inf.getTotalRead();
 
+				// some weird logic here that seems to want to bail early on a download if it doesn't look like it is a torrent (bnencode always starts with 'd'
+				// and using 'delete file on cancel' as some crazy marker to control this...
+			
+				// PARG - added '<' to prevent early abandoning of RSS feed content
+			
 			if (!inf.getDeleteFileOnCancel() && numRead >= 16384) {
 				inf.cancel();
 			} else if (numRead == count && count > 0) {
 				final byte[] bytes = inf.getLastReadBytes();
-				if (bytes[0] != 'd') {
+				if (bytes[0] != 'd' && bytes[0] != '<' ) {
 					inf.setDeleteFileOnCancel(false);
 				}
 			}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/TableColumnOTOF_Name.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/TableColumnOTOF_Name.java
index 0f6ace8..8808629 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/TableColumnOTOF_Name.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/opentorrent/TableColumnOTOF_Name.java
@@ -46,7 +46,7 @@ implements TableCellRefreshListener, TableColumnExtraInfoListener
 						return true;
 					
 					if (finalEdit) {
-						tfi.setDestFileName(value);
+						tfi.setDestFileName(value,true);
 					}
 
 					return true;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/shells/uiswitcher/UISwitcherWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/shells/uiswitcher/UISwitcherWindow.java
index 69af270..2392f9d 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/shells/uiswitcher/UISwitcherWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/shells/uiswitcher/UISwitcherWindow.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.shells.uiswitcher;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTBGImagePainter.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTBGImagePainter.java
index e7187da..84ae683 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTBGImagePainter.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTBGImagePainter.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import java.util.ArrayList;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTColorWithAlpha.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTColorWithAlpha.java
index 995846d..ca7b855 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTColorWithAlpha.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTColorWithAlpha.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jun 23, 2010
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkin.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkin.java
index 62146b4..c027715 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkin.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkin.java
@@ -1,6 +1,6 @@
 /*
  * Created on May 29, 2006 4:01:04 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
@@ -24,7 +21,6 @@ import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
 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;
@@ -954,21 +950,6 @@ public class SWTSkin
 
 		}
 
-		if (Constants.isWindows && (controlToLayout instanceof Browser) && false) {
-			if (newFormData.top != null) {
-				newFormData.top.offset -= 2;
-			}
-			if (newFormData.right != null) {
-				newFormData.right.offset += 2;
-			}
-			if (newFormData.left != null) {
-				newFormData.left.offset -= 2;
-			}
-			if (newFormData.bottom != null) {
-				newFormData.bottom.offset += 2;
-			}
-		}
-
 		if (!skinObject.getDefaultVisibility()) {
 			if (controlToLayout.getData("oldSize") == null) {
     		controlToLayout.setData("oldSize", new Point(properties.getIntValue(sConfigID + ".width",
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinButtonUtility.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinButtonUtility.java
index ef640d4..f2db75c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinButtonUtility.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinButtonUtility.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import java.util.ArrayList;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinCheckboxListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinCheckboxListener.java
index 857db53..a6a5432 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinCheckboxListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinCheckboxListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Dec 24, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinFactory.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinFactory.java
index e58d320..546bdc6 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinFactory.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinFactory.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 1, 2006 2:06:48 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinImageChanger.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinImageChanger.java
index 0efb201..e751af0 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinImageChanger.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinImageChanger.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinLayoutCompleteListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinLayoutCompleteListener.java
index f88136d..370cf3d 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinLayoutCompleteListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinLayoutCompleteListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObject.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObject.java
index 90ebb8e..d04df56 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObject.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObject.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import org.eclipse.swt.widgets.Control;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectAdapter.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectAdapter.java
index 1123f78..7968fb5 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectAdapter.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectAdapter.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBasic.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBasic.java
index 2a266e2..543a98e 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBasic.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBasic.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import java.util.*;
@@ -758,8 +773,13 @@ public class SWTSkinObjectBasic
 	 * @see com.aelitis.azureus.ui.swt.skin.SWTSkinObject#addListener(com.aelitis.azureus.ui.swt.skin.SWTSkinObjectListener)
 	 */
 	public void addListener(final SWTSkinObjectListener listener) {
+		int visibleStateAtAdd = isVisible;
 		listeners_mon.enter();
 		try {
+			if (listeners.contains(listener)) {
+				System.err.println("Already contains listener " + Debug.getCompressedStackTrace());
+				return;
+			}
 			listeners.add(listener);
 		} finally {
 			listeners_mon.exit();
@@ -774,9 +794,12 @@ public class SWTSkinObjectBasic
   				SWTSkinObjectListener.EVENT_DATASOURCE_CHANGED, datasource);
 		}
 
-		if (isVisible == 1 && initialized) {
-			Utils.execSWTThreadLater(0, new AERunnable() {
+		if (visibleStateAtAdd == 1 && initialized) {
+			Utils.execSWTThread(new AERunnable() {
 				public void runSupport() {
+					if (isVisible != 1) {
+						return;
+					}
 					listener.eventOccured(SWTSkinObjectBasic.this,
 							SWTSkinObjectListener.EVENT_SHOW, null);
 				}
@@ -834,35 +857,11 @@ public class SWTSkinObjectBasic
 			initialized = true;
 		} else if (eventType == SWTSkinObjectListener.EVENT_DATASOURCE_CHANGED) {
 			datasource = params;
+		} else if (eventType == SWTSkinObjectListener.EVENT_DESTROY && isVisible == 1) {
+			triggerListenersRaw(SWTSkinObjectListener.EVENT_HIDE, null);
 		}
 		
-		// process listeners added locally
-		SWTSkinObjectListener[] listenersArray = getListeners();
-		if (listenersArray.length > 0) {
-			// don't use iterator as triggering code may try to remove itself
-			for (SWTSkinObjectListener l : listenersArray) {
-				try {
-					l.eventOccured(this, eventType, params);
-				} catch (Exception e) {
-					Debug.out("Skin Event " + SWTSkinObjectListener.NAMES[eventType]
-							+ " caused an error for listener added locally", e);
-				}
-			}
-		}
-
-		// process listeners added to skin
-		SWTSkinObjectListener[] listeners = skin.getSkinObjectListeners(sViewID);
-		if (listeners.length > 0) {
-  		for (int i = 0; i < listeners.length; i++) {
-  			try {
-  				SWTSkinObjectListener l = listeners[i];
-  				l.eventOccured(this, eventType, params);
-  			} catch (Exception e) {
-  				Debug.out("Skin Event " + SWTSkinObjectListener.NAMES[eventType]
-  						+ " caused an error for listener added to skin", e);
-  			}
-  		}
-		}
+		triggerListenersRaw(eventType, params);
 
 		if (eventType == SWTSkinObjectListener.EVENT_CREATED && isVisible >= 0) {
 			triggerListeners(isVisible() ? SWTSkinObjectListener.EVENT_SHOW
@@ -899,6 +898,36 @@ public class SWTSkinObjectBasic
 		}
 	}
 
+	private void triggerListenersRaw(int eventType, Object params) {
+		// process listeners added locally
+		SWTSkinObjectListener[] listenersArray = getListeners();
+		if (listenersArray.length > 0) {
+			// don't use iterator as triggering code may try to remove itself
+			for (SWTSkinObjectListener l : listenersArray) {
+				try {
+					l.eventOccured(this, eventType, params);
+				} catch (Exception e) {
+					Debug.out("Skin Event " + SWTSkinObjectListener.NAMES[eventType]
+							+ " caused an error for listener added locally", e);
+				}
+			}
+		}
+
+		// process listeners added to skin
+		SWTSkinObjectListener[] listeners = skin.getSkinObjectListeners(sViewID);
+		if (listeners.length > 0) {
+  		for (int i = 0; i < listeners.length; i++) {
+  			try {
+  				SWTSkinObjectListener l = listeners[i];
+  				l.eventOccured(this, eventType, params);
+  			} catch (Exception e) {
+  				Debug.out("Skin Event " + SWTSkinObjectListener.NAMES[eventType]
+  						+ " caused an error for listener added to skin", e);
+  			}
+  		}
+		}
+	}
+
 	protected void setViewID(String viewID) {
 		sViewID = viewID;
 	}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBrowser.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBrowser.java
index 41c0f2a..a685584 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBrowser.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectBrowser.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,18 +13,12 @@
  * 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.skin;
 
 import java.net.InetSocketAddress;
-import java.net.Proxy;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.SWTError;
@@ -44,7 +38,7 @@ import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory;
 import com.aelitis.azureus.core.proxy.AEProxyFactory;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
 import com.aelitis.azureus.ui.swt.browser.BrowserContext;
-import com.aelitis.azureus.ui.swt.browser.BrowserWrapper;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import com.aelitis.azureus.ui.swt.browser.BrowserContext.loadingListener;
 import com.aelitis.azureus.ui.swt.browser.listener.*;
 import com.aelitis.azureus.util.UrlFilter;
@@ -270,7 +264,7 @@ public class SWTSkinObjectBrowser
 		}
 
 		try {
-			browser = new BrowserWrapper(cArea, Utils.getInitialBrowserStyle(SWT.NONE));
+			browser = BrowserWrapper.createBrowser(cArea, Utils.getInitialBrowserStyle(SWT.NONE));
 
 			browser.setLayoutData(Utils.getFilledFormData());
 			browser.getParent().layout(true);
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectButton.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectButton.java
index f019f2b..b493593 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectButton.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectButton.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 21, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectCheckbox.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectCheckbox.java
index 37e9565..60f897a 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectCheckbox.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectCheckbox.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 21, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectContainer.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectContainer.java
index 9e6914d..1937335 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectContainer.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectContainer.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 26, 2006 11:38:47 AM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectExpandBar.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectExpandBar.java
index 346be44..5aa3490 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectExpandBar.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectExpandBar.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import java.util.ArrayList;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectExpandItem.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectExpandItem.java
index 0ab5828..4349248 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectExpandItem.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectExpandItem.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 21, 2006 1:22:57 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectImage.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectImage.java
index 4ec6250..789d1f6 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectImage.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectImage.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import org.eclipse.swt.SWT;
@@ -25,6 +40,8 @@ public class SWTSkinObjectImage
 {
 	protected static final Long DRAW_SCALE = new Long(1);
 
+	protected static final Long DRAW_SCALEDOWN_OR_CENTER = new Long(8);
+
 	protected static final Long DRAW_STRETCH = new Long(2);
 
 	protected static final Long DRAW_NORMAL = new Long(0);
@@ -51,6 +68,8 @@ public class SWTSkinObjectImage
 
 	private int h_align;
 
+	private int drawAlpha = 255;
+
 	static {
 		paintListener = new PaintListener() {
 			public void paintControl(PaintEvent e) {
@@ -60,10 +79,15 @@ public class SWTSkinObjectImage
 					e.gc.setInterpolation(SWT.HIGH);
 				} catch (Exception ex) {
 				}
-
+				
 				final Canvas control = (Canvas) e.widget;
 				Image imgSrc = (Image) control.getData("image");
-				
+
+				Integer drawAlpha = (Integer) control.getData("drawAlpha");
+				if (drawAlpha != null) {
+					e.gc.setAlpha(drawAlpha);
+				}
+
 				//Long hpadding_obj = (Long) control.getData("hpadding");
 				//int hpadding = hpadding_obj == null ? 0 : hpadding_obj.intValue();
 
@@ -102,6 +126,14 @@ public class SWTSkinObjectImage
 				}
 				Rectangle imgSrcBounds = imgSrc.getBounds();
 				Point size = control.getSize();
+				
+				if (drawMode == DRAW_SCALEDOWN_OR_CENTER) {
+					if (size.x < imgSrcBounds.width || size.y < imgSrcBounds.height) {
+						drawMode = DRAW_SCALE;
+					} else {
+						drawMode = DRAW_CENTER;
+					}
+				}
 
 				if (drawMode == DRAW_STRETCH) {
 					e.gc.drawImage(imgSrc, 0, 0, imgSrcBounds.width, imgSrcBounds.height,
@@ -120,9 +152,14 @@ public class SWTSkinObjectImage
 				} else if (drawMode == DRAW_HCENTER) {
 					e.gc.drawImage(imgSrc, (size.x - imgSrcBounds.width) / 2, 0);
 				} else if (drawMode == DRAW_SCALE) {
-					// TODO: real scale..
+					float dx = (float) size.x / imgSrcBounds.width;
+					float dy = (float) size.y / imgSrcBounds.height ;
+					float d = Math.min(dx, dy);
+					int newX = (int) (imgSrcBounds.width * d);
+					int newY = (int) (imgSrcBounds.height * d);
+					
 					e.gc.drawImage(imgSrc, 0, 0, imgSrcBounds.width, imgSrcBounds.height,
-							0, 0, size.x, size.y);
+							(size.x - newX) / 2, (size.y - newY) / 2, newX, newY);
 				} else {
 					int x0 = 0;
 					int y0 = 0;
@@ -303,6 +340,8 @@ public class SWTSkinObjectImage
 					return null;
 				}
 
+				canvas.setData("drawAlpha", drawAlpha);
+
 				String oldImageID = (String) canvas.getData("ImageID");
 				if (sImageID != null && sImageID.equals(oldImageID)) {
 					return null;
@@ -330,6 +369,8 @@ public class SWTSkinObjectImage
 				Long drawMode;
 				if (sDrawMode.equals("scale")) {
 					drawMode = DRAW_SCALE;
+				} else if (sDrawMode.equals("scaledown")) {
+						drawMode = DRAW_SCALEDOWN_OR_CENTER;
 				} else if (sDrawMode.equals("stretch")) {
 					drawMode = DRAW_STRETCH;
 				} else if (sDrawMode.equals("center")) {
@@ -382,7 +423,7 @@ public class SWTSkinObjectImage
 					image = images[0];
 				}
 
-				if (image == null) {
+				if (image == null || image.isDisposed()) {
 					image = ImageLoader.noImage;
 				}
 
@@ -391,7 +432,7 @@ public class SWTSkinObjectImage
  
 				Rectangle imgBounds = image.getBounds();
 				if (drawMode != DRAW_CENTER && drawMode != DRAW_HCENTER
-						&& drawMode != DRAW_STRETCH) {
+						&& drawMode != DRAW_STRETCH && drawMode != DRAW_SCALEDOWN_OR_CENTER) {
 					canvas.setSize(imgBounds.width + hpadding, imgBounds.height);
 					canvas.setData("oldSize", canvas.getSize());
 				}
@@ -489,9 +530,11 @@ public class SWTSkinObjectImage
 
 	protected void swt_reallySetImage() {
 		if (currentImageID == null || customImage) {
+			drawAlpha = 255;
 			return;
 		}
 		
+		boolean removedDisabled = false;
 		ImageLoader imageLoader = skin.getImageLoader(properties);
 		boolean imageExists = imageLoader.imageExists(currentImageID);
 		if (!imageExists && imageLoader.imageExists(currentImageID + ".image")) {
@@ -502,6 +545,9 @@ public class SWTSkinObjectImage
 			for (int i = suffixes.length - 1; i >= 0; i--) {
 				String suffixToRemove = suffixes[i];
 				if (suffixToRemove != null) {
+					if (suffixToRemove.equals("-disabled")) {
+						removedDisabled = true;
+					}
 					currentImageID = currentImageID.substring(0, currentImageID.length()
 							- suffixToRemove.length());
 					if (imageLoader.imageExists(currentImageID)) {
@@ -513,8 +559,10 @@ public class SWTSkinObjectImage
 		}
 
 		if (imageExists) {
+			drawAlpha  = removedDisabled ? 64 : 255;
 			setCanvasImage(currentImageID, null);
 		} else {
+			drawAlpha = 255;
 			Utils.execSWTThread(new AERunnable() {
 				public void runSupport() {
 					FormData fd = (FormData) canvas.getLayoutData();
@@ -538,10 +586,12 @@ public class SWTSkinObjectImage
 			public void runSupport() {
 				customImage = true;
 				customImageID = null;
+				drawAlpha  = 255;
 				canvas.setData("image", image);
 				canvas.setData("ImageID", null);
 				canvas.setData("image-left", null);
 				canvas.setData("image-right", null);
+				canvas.setData("drawAlpha", null);
 
 				canvas.removePaintListener(paintListener);
 				canvas.addPaintListener(paintListener);
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectListener.java
index f329d99..9094e08 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectListener.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSash.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSash.java
index 9545831..8a08f50 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSash.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSash.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
@@ -32,6 +29,7 @@ import org.eclipse.swt.widgets.*;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.util.AERunnable;
+import org.gudy.azureus2.core3.util.AERunnableObject;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.ui.swt.Utils;
 
@@ -311,6 +309,10 @@ public class SWTSkinObjectSash
 	 * @since 3.1.0.1
 	 */
 	protected void handleShow() {
+		if ( sash.isDisposed()){
+			return;
+		}
+		
 		Long px = (Long) sash.getData("PX");
 		if (px == null) {
 			return;
@@ -413,6 +415,21 @@ public class SWTSkinObjectSash
 			}
 		});
 	}
+	
+	public int getAboveSize() {
+		Object o = Utils.execSWTThreadWithObject("getAboveSize", new AERunnableObject() {
+			public Object runSupport() {
+				if (sash == null || sash.isDisposed()) {
+					return -1;
+				}
+				return sash.getData("PX");
+			}
+		}, 1000);
+		if (o instanceof Number) {
+			return ((Number) o).intValue();
+		}
+		return -1;
+	}
 
 	public void setAboveSize(final int px) {
 		Utils.execSWTThread(new AERunnable() {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSeparator.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSeparator.java
index 26b3391..b2e81ab 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSeparator.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSeparator.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSlider.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSlider.java
index 65c759e..4eb45b6 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSlider.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectSlider.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTab.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTab.java
index 8c31e47..e07b640 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTab.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTab.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 21, 2006 1:22:57 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTabFolder.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTabFolder.java
index 16b4f13..f7fc94e 100755
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTabFolder.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTabFolder.java
@@ -1,8 +1,25 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.CTabFolder;
-import org.eclipse.swt.custom.CTabItem;
 import org.eclipse.swt.widgets.Composite;
 
 import org.gudy.azureus2.core3.util.Constants;
@@ -16,16 +33,22 @@ public class SWTSkinObjectTabFolder
 	public SWTSkinObjectTabFolder(SWTSkin skin, SWTSkinProperties properties,
 			String sID, String sConfigID, SWTSkinObject parent) {
 		super(skin, properties, null, sID, sConfigID, "tabfolder", parent);
-		createTabFolder();
-		
+		createTabFolder(null);
+	}
+
+	public SWTSkinObjectTabFolder(SWTSkin skin, SWTSkinProperties properties,
+			String sID, String sConfigID, Composite createOn) {
+		super(skin, properties, null, sID, sConfigID, "tabfolder", null);
+		createTabFolder(createOn);
 	}
 
-	private void createTabFolder() {
-		Composite createOn;
-		if (parent == null) {
-			createOn = skin.getShell();
-		} else {
-			createOn = (Composite) parent.getControl();
+	private void createTabFolder(Composite createOn) {
+		if (createOn == null) {
+  		if (parent == null) {
+  			createOn = skin.getShell();
+  		} else {
+  			createOn = (Composite) parent.getControl();
+  		}
 		}
 
 		int style = SWT.NONE;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText.java
index d3cd048..9a54af0 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText.java
@@ -1,6 +1,6 @@
 /*
  * Created on Aug 4, 2006 9:18:52 AM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText1.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText1.java
index 7eec119..77508d5 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText1.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText1.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 26, 2006 12:46:42 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText2.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText2.java
index b9af792..194058b 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText2.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText2.java
@@ -1,6 +1,6 @@
 /*
  * Created on Aug 4, 2006 9:03:19 AM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText_UrlClickedListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText_UrlClickedListener.java
index f7c1747..9b045f9 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText_UrlClickedListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectText_UrlClickedListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jan 15, 2010
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTextbox.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTextbox.java
index fe08fd3..5bcec90 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTextbox.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectTextbox.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 21, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectToggle.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectToggle.java
index 8802fdb..399bdb8 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectToggle.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinObjectToggle.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 21, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinProperties.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinProperties.java
index 0c03180..56ae863 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinProperties.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinProperties.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 26, 2006 7:28:15 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesClone.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesClone.java
index d5bfff1..807fcbb 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesClone.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesClone.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 26, 2006 7:25:11 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesImpl.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesImpl.java
index 8d85433..a17aa04 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesImpl.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesImpl.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 1, 2006 4:16:52 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesParam.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesParam.java
index 75ff4f1..5af0ab6 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesParam.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesParam.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 27, 2006 1:54:46 AM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesParamImpl.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesParamImpl.java
index 72b48a7..b8273eb 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesParamImpl.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinPropertiesParamImpl.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 27, 2006 1:48:36 AM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java
index 50bbc01..0cb3fd8 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSet.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import java.util.ArrayList;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSetListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSetListener.java
index 8896940..876f2c9 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSetListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinTabSetListener.java
@@ -1,6 +1,6 @@
 /*
  * Created on Jun 18, 2006 11:38:26 PM
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.skin;
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinToggleListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinToggleListener.java
index 14b3703..13edd5a 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinToggleListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinToggleListener.java
@@ -1,10 +1,12 @@
 /**
  * Created on Dec 24, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinUtils.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinUtils.java
index 1e45e8f..255fd48 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinUtils.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTSkinUtils.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import org.eclipse.swt.SWT;
@@ -236,7 +251,7 @@ public class SWTSkinUtils
 			final Point destSize, final Runnable runOnCompletion) {
 		final Control control = skinObject.getControl();
 		//System.out.println("slide to " + size + " via "+ Debug.getCompressedStackTrace());
-		boolean exit = Utils.execSWTThreadWithBool("slide",
+		Boolean exit = Utils.execSWTThreadWithBool("slide",
 				new AERunnableBoolean() {
 					public boolean runSupport() {
 						boolean exit = control.getData("slide.active") != null;
@@ -253,7 +268,7 @@ public class SWTSkinUtils
 					}
 				}, 1000);
 
-		if (exit) {
+		if (exit == null || exit) {
 			return;
 		}
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTTextPaintListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTTextPaintListener.java
index 08fea13..11d4c7f 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTTextPaintListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/skin/SWTTextPaintListener.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.skin;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionListWindow.java b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionListWindow.java
index 08747f2..b4dda43 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionListWindow.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionListWindow.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.subscriptions;
 
 import java.util.Arrays;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionMDIEntry.java b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionMDIEntry.java
index bd6b923..a039190 100755
--- a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionMDIEntry.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionMDIEntry.java
@@ -1,44 +1,35 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.subscriptions;
 
-import java.io.File;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
 
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Menu;
-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.*;
 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.*;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.ui.swt.*;
-import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
-import org.gudy.azureus2.ui.swt.plugins.UISWTInputReceiver;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
-import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
-import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
 
-import com.aelitis.azureus.core.metasearch.Engine;
-import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
+
 import com.aelitis.azureus.core.subs.*;
-import com.aelitis.azureus.core.tag.Tag;
-import com.aelitis.azureus.core.tag.TagManager;
-import com.aelitis.azureus.core.tag.TagManagerFactory;
-import com.aelitis.azureus.core.tag.TagType;
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-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.mdi.MdiEntry;
@@ -87,375 +78,24 @@ public class SubscriptionMDIEntry implements SubscriptionListener, ViewTitleInfo
 		PluginInterface pi = PluginInitializer.getDefaultInterface();
 		UIManager uim = pi.getUIManager();
 		
-		final MenuManager menuManager = uim.getMenuManager();
-		
-		MenuItem menuItem;
-		
-		menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.forcecheck");
-		menuItem.setText(MessageText.getString("Subscription.menu.forcecheck"));
-		menuItem.addListener(new SubsMenuItemListener() {
-			public void selected(MdiEntry info, Subscription subs) {
-				try {
-					subs.getManager().getScheduler().downloadAsync( subs, true );
-				} catch (SubscriptionException e) {
-					Debug.out(e);
-				}
-			}
-		});
-		
-		menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.clearall");
-		menuItem.addListener(new SubsMenuItemListener() {
-			public void selected(MdiEntry info, Subscription subs) {
-				subs.getHistory().markAllResultsRead();
-				refreshView();
-			}
-		});
-		
-		menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.dirtyall");
-		menuItem.addListener(new SubsMenuItemListener() {
-			public void selected(MdiEntry info, Subscription subs) {
-				subs.getHistory().markAllResultsUnread();
-				refreshView();
-			}
-		});
-
-		menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.deleteall");
-		menuItem.addListener(new SubsMenuItemListener() {
-			public void selected(MdiEntry info, Subscription subs) {
-				subs.getHistory().deleteAllResults();
-				refreshView();
-			}
-		});
-		
-		menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.reset");
-		menuItem.addListener(new SubsMenuItemListener() {
-			public void selected(MdiEntry info, Subscription subs) {
-				subs.getHistory().reset();
-				try{
-					subs.getEngine().reset();
-				}catch( Throwable e ){
-					Debug.printStackTrace(e);
-				}
-				try{
-					subs.getManager().getScheduler().downloadAsync(subs, true);
-					
-				}catch( Throwable e ){
-					
-					Debug.out(e);
-				}
-			}
-		});
-
-		try{
-			Engine engine = subs.getEngine();
+		final MenuManager menu_manager = uim.getMenuManager();
 				
-			if ( engine instanceof WebEngine ){
-				
-				if (((WebEngine)engine).isNeedsAuth()){
-					
-					menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.resetauth");
-					menuItem.addListener(new SubsMenuItemListener() {
-						public void selected(MdiEntry info, Subscription subs) {
-							try{
-								Engine engine = subs.getEngine();
-								
-								if ( engine instanceof WebEngine ){
-									
-									((WebEngine)engine).setCookies( null );
-								}
-							}catch( Throwable e ){
-								
-								Debug.printStackTrace(e);
-							}
-							
-							try{
-								subs.getManager().getScheduler().downloadAsync(subs, true);
-								
-							}catch( Throwable e ){
-								
-								Debug.out(e);
-							}
-						}
-					});
-					
-					menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.setcookies");
-					menuItem.addListener(new SubsMenuItemListener() {
-						public void selected(MdiEntry info, final Subscription subs) {
-							try{
-								Engine engine = subs.getEngine();
-								
-								if ( engine instanceof WebEngine ){
-									
-									final WebEngine we = (WebEngine)engine;
-									
-									UISWTInputReceiver entry = new SimpleTextEntryWindow();
-									
-									String[] req = we.getRequiredCookies();
-									
-									String	req_str = "";
-									
-									for ( String r:req ){
-										
-										req_str += (req_str.length()==0?"":";") + r + "=?";
-									}
-									entry.setPreenteredText( req_str, true );
-									entry.maintainWhitespace(false);
-									entry.allowEmptyInput( false );
-									entry.setTitle("general.enter.cookies");
-									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 ){
-								
-								Debug.printStackTrace(e);
-							}
-						}
-					});
-				}
-			}
-		}catch( Throwable e ){
-			
-			Debug.printStackTrace(e);
-		}
-		
-			// sep
-		
-		menuManager.addMenuItem("sidebar." + key,"s1").setStyle( MenuItem.STYLE_SEPARATOR );
-
-			// category
-		
-		menuItem = menuManager.addMenuItem("sidebar." + key, "MyTorrentsView.menu.setCategory");
-		menuItem.setStyle( MenuItem.STYLE_MENU );
-		
-		menuItem.addFillListener(
-			new MenuItemFillListener()
-			{
-				public void 
-				menuWillBeShown(
-					MenuItem 	menu, 
-					Object 		data ) 
-				{		
-					addCategorySubMenu( menuManager, menu );
-				}
-			});
-		
-			// tag
-		
-		menuItem = menuManager.addMenuItem("sidebar." + key, "label.tag");
-		menuItem.setStyle( MenuItem.STYLE_MENU );
-		
-		menuItem.addFillListener(
-			new MenuItemFillListener()
+		SubscriptionManagerUI.MenuCreator menu_creator = 
+			new SubscriptionManagerUI.MenuCreator()
 			{
-				public void 
-				menuWillBeShown(
-					MenuItem 	menu, 
-					Object 		data ) 
-				{		
-					addTagSubMenu( menuManager, menu );
+				public MenuItem
+				createMenu(
+					String 	resource_id )
+				{
+					return( menu_manager.addMenuItem("sidebar." + key, resource_id ));
 				}
-			});
-		
-		if ( subs.isUpdateable()){
-			
-			menuItem = menuManager.addMenuItem("sidebar." + key,"MyTorrentsView.menu.rename");
-			menuItem.addListener(new SubsMenuItemListener() {
-				public void selected(MdiEntry info, final Subscription subs) {
-					UISWTInputReceiver entry = new SimpleTextEntryWindow();
-					entry.setPreenteredText(subs.getName(), false );
-					entry.maintainWhitespace(false);
-					entry.allowEmptyInput( false );
-					entry.setLocalisedTitle(MessageText.getString("label.rename",
-							new String[] {
-								subs.getName()
-							}));
-					entry.prompt(new UIInputReceiverListener() {
-						public void UIInputReceiverClosed(UIInputReceiver entry) {
-							if (!entry.hasSubmittedInput()){
-								
-								return;
-							}
-							
-							String input = entry.getSubmittedInput().trim();
-							
-							if ( input.length() > 0 ){
-								
-								try{
-									subs.setName( input );
-									
-								}catch( Throwable e ){
-									
-									Debug.printStackTrace(e);
-								}
-							}
-						}
-					});
+				
+				public void refreshView() {
+					SubscriptionMDIEntry.this.refreshView();
 				}
-			});
-		}
-		
-		menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.upgrade");
-		menuItem.addListener(new SubsMenuItemListener() {
-			public void selected(MdiEntry info, Subscription subs) {
-				subs.resetHighestVersion();
-			}
-		});
+			};
 			
-		menuItem.addFillListener(
-			new MenuItemFillListener()
-			{
-				public void 
-				menuWillBeShown(
-					MenuItem 	menu, 
-					Object 		data ) 
-				{									
-					menu.setVisible( subs.getHighestVersion() > subs.getVersion());
-				}
-			});
-		
-		menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.export");
-		menuItem.addListener(new SubsMenuItemListener() {
-			public void selected(MdiEntry info, Subscription subs) {
-				export();
-			}
-		});
-		
-			// sep
-		
-		menuManager.addMenuItem("sidebar." + key,"s2").setStyle( MenuItem.STYLE_SEPARATOR );
-		
-			// change url
-		
-		try{
-			Engine engine = subs.getEngine();
-						
-			if ( engine instanceof WebEngine ){
-					
-				menuItem = menuManager.addMenuItem("sidebar." + key,"menu.change.url");
-				menuItem.addListener(new SubsMenuItemListener() {
-					public void selected(MdiEntry info, Subscription _subs) {
-						UISWTInputReceiver entry = new SimpleTextEntryWindow();
-						
-						try{
-							WebEngine web_engine = (WebEngine)subs.getEngine();
-	
-							entry.setPreenteredText(web_engine.getSearchUrl( true ), false );
-							entry.maintainWhitespace(false);
-							entry.allowEmptyInput( false );
-							entry.setLocalisedTitle(MessageText.getString("change.url.msg.title",
-									new String[] {
-										subs.getName()
-									}));
-							entry.setMessage( "change.url.msg.desc" );
-							entry.prompt(new UIInputReceiverListener() {
-								public void UIInputReceiverClosed(UIInputReceiver entry) {
-									if (!entry.hasSubmittedInput()){
-										
-										return;
-									}
-									
-									String input = entry.getSubmittedInput().trim();
-									
-									if ( input.length() > 0 ){
-										
-										try{
-											WebEngine web_engine = (WebEngine)subs.getEngine();
-											
-											web_engine.setSearchUrl( input );
-											
-											subs.cloneWithNewEngine( web_engine );
-											
-										}catch( Throwable e ){
-											
-											Debug.out(e);
-										}
-									}
-								}
-							});
-						}catch( Throwable e ){
-							
-							Debug.out( e );
-						}
-					}
-				});
-				
-			}
-		}catch( Throwable e ){
-			Debug.out( e );
-		}
-		
-			// rename
-		
-		menuItem = menuManager.addMenuItem("sidebar." + key, "MyTorrentsView.menu.rename" );
-		menuItem.addListener(new SubsMenuItemListener() {
-			public void selected(MdiEntry info, final Subscription subs) {
-				UISWTInputReceiver entry = new SimpleTextEntryWindow();
-				entry.maintainWhitespace(false);
-				entry.allowEmptyInput( false );
-				
-				entry.setPreenteredText(subs.getName(), false );
-				
-				entry.maintainWhitespace(false);
-				
-				entry.allowEmptyInput( false );
-				
-				entry.setLocalisedTitle(MessageText.getString("label.rename",
-						new String[] {
-						subs.getName()
-				}));
-		
-				entry.prompt(new UIInputReceiverListener() {
-					public void UIInputReceiverClosed(UIInputReceiver entry) {
-						if (!entry.hasSubmittedInput()) {
-							return;
-						}
-						String input = entry.getSubmittedInput().trim();
-						
-						if ( input.length() > 0 ){
-							
-							subs.setLocalName( input );
-						}
-					}
-				});
-			}
-		});
-		
-		
-		menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.remove");
-		menuItem.addListener(new SubsMenuItemListener() {
-			public void selected(MdiEntry info, Subscription subs) {
-				removeWithConfirm();
-			}
-		});
-		
-		menuManager.addMenuItem("sidebar." + key,"s3").setStyle( MenuItem.STYLE_SEPARATOR );
-
-		menuItem = menuManager.addMenuItem("sidebar." + key,"Subscription.menu.properties");
-		menuItem.addListener(new SubsMenuItemListener() {
-			public void selected(MdiEntry info, Subscription subs) {
-				showProperties();
-			}
-		});
+		SubscriptionManagerUI.createMenus( menu_manager, menu_creator, subs );
 		
 		subs.addListener(this); 
 	}
@@ -520,466 +160,6 @@ public class SubscriptionMDIEntry implements SubscriptionListener, ViewTitleInfo
 		}
 	}
 
-	private void 
-	addCategorySubMenu(
-		MenuManager				menu_manager,
-		MenuItem				menu )
-	{
-		menu.removeAllChildItems();
-
-		Category[] categories = CategoryManager.getCategories();
-		
-		Arrays.sort( categories );
-
-		MenuItem m;
-
-		if ( categories.length > 0 ){
-			
-			String	assigned_category = subs.getCategory();
-			
-			final Category uncat = CategoryManager.getCategory( Category.TYPE_UNCATEGORIZED );
-						
-			if ( uncat != null ){
-				
-				m = menu_manager.addMenuItem( menu, uncat.getName());
-				
-				m.setStyle( MenuItem.STYLE_RADIO );
-								
-				m.setData( new Boolean( assigned_category == null ));
-				
-				m.addListener(
-					new MenuItemListener() 
-					{
-						public void
-						selected(
-							MenuItem			menu,
-							Object 				target )
-						{
-							assignSelectedToCategory( uncat );
-						}
-					});
-				
-
-				m = menu_manager.addMenuItem( menu, "sep1" );
-				
-				m.setStyle( MenuItem.STYLE_SEPARATOR );
-			}
-
-			for ( int i=0; i<categories.length; i++ ){
-				
-				final Category cat = categories[i];
-				
-				if ( cat.getType() == Category.TYPE_USER) {
-					
-					m = menu_manager.addMenuItem( menu, "!" + cat.getName() + "!" );
-					
-					m.setStyle( MenuItem.STYLE_RADIO );
-										
-					m.setData( new Boolean( assigned_category != null && assigned_category.equals( cat.getName())));
-					
-					m.addListener(
-						new MenuItemListener() 
-						{
-							public void
-							selected(
-								MenuItem			menu,
-								Object 				target )
-							{
-								assignSelectedToCategory( cat );
-							}
-						});
-				}
-			}
-
-			m = menu_manager.addMenuItem( menu, "sep2" );
-			
-			m.setStyle( MenuItem.STYLE_SEPARATOR );
-		}
-
-		m = menu_manager.addMenuItem( menu, "MyTorrentsView.menu.setCategory.add" );
-		
-		m.addListener(
-				new MenuItemListener() 
-				{
-					public void
-					selected(
-						MenuItem			menu,
-						Object 				target )
-					{
-						addCategory( );
-					}
-				});
-
-	}
-
-	private void 
-	addCategory()	
-	{
-		CategoryAdderWindow adderWindow = new CategoryAdderWindow(Display.getDefault());
-		
-		Category newCategory = adderWindow.getNewCategory();
-		
-		if ( newCategory != null ){
-		
-			assignSelectedToCategory( newCategory );
-		}
-	}
-
-	private void 
-	assignSelectedToCategory(
-		Category 			category )
-	{
-		if ( category.getType() == Category.TYPE_UNCATEGORIZED ){
-		
-			subs.setCategory( null );
-			
-		}else{
-			
-			subs.setCategory( category.getName());
-		}
-	}
-
-	private void 
-	addTagSubMenu(
-		MenuManager				menu_manager,
-		MenuItem				menu )
-	{
-		menu.removeAllChildItems();
-
-		TagManager tm = TagManagerFactory.getTagManager();
-		
-		List<Tag> tags = tm.getTagType( TagType.TT_DOWNLOAD_MANUAL ).getTags();
-		
-		tags = TagUIUtils.sortTags( tags );
-					
-		long	tag_id = subs.getTagID();
-			
-		Tag assigned_tag = tm.lookupTagByUID( tag_id );
-		
-		MenuItem m = menu_manager.addMenuItem( menu, "label.no.tag" );
-				
-		m.setStyle( MenuItem.STYLE_RADIO );
-							
-		m.setData( new Boolean( assigned_tag == null ));
-				
-		m.addListener(
-			new MenuItemListener() 
-			{
-				public void
-				selected(
-					MenuItem			menu,
-					Object 				target )
-				{
-					subs.setTagID( -1 );
-				}
-			});
-				
-
-		m = menu_manager.addMenuItem( menu, "sep1" );
-				
-		m.setStyle( MenuItem.STYLE_SEPARATOR );
-	
-		
-		List<String>	menu_names 		= new ArrayList<String>();
-		Map<String,Tag>	menu_name_map 	= new IdentityHashMap<String, Tag>();
-
-		for ( Tag t: tags ){
-			
-			if ( !t.isTagAuto()){
-				
-				String name = t.getTagName( true );
-				
-				menu_names.add( name );
-				menu_name_map.put( name, t );
-			}
-		}
-			
-		List<Object>	menu_structure = MenuBuildUtils.splitLongMenuListIntoHierarchy( menu_names, TagUIUtils.MAX_TOP_LEVEL_TAGS_IN_MENU );
-		
-		for ( Object obj: menu_structure ){
-
-			List<Tag>	bucket_tags = new ArrayList<Tag>();
-			
-			MenuItem parent_menu;
-			
-			if ( obj instanceof String ){
-				
-				parent_menu = menu;
-				
-				bucket_tags.add( menu_name_map.get((String)obj));
-				
-			}else{
-				
-				Object[]	entry = (Object[])obj;
-				
-				List<String>	tag_names = (List<String>)entry[1];
-				
-				boolean	has_selected = false;
-				
-				for ( String name: tag_names ){
-					
-					Tag tag = menu_name_map.get( name );
-					
-					bucket_tags.add( tag );
-					
-					if ( assigned_tag == tag ){
-						
-						has_selected = true;
-					}
-				}
-				
-				parent_menu = menu_manager.addMenuItem (menu, "!" + (String)entry[0] + (has_selected?" (*)":"") + "!" );
-				
-				parent_menu.setStyle( MenuItem.STYLE_MENU );
-			}
-			
-			for ( final Tag tag: bucket_tags ){
-			
-				m = menu_manager.addMenuItem( parent_menu, tag.getTagName( false ));
-						
-				m.setStyle( MenuItem.STYLE_RADIO );
-											
-				m.setData( new Boolean( assigned_tag == tag ));
-						
-				m.addListener(
-					new MenuItemListener() 
-					{
-						public void
-						selected(
-							MenuItem			menu,
-							Object 				target )
-						{
-							subs.setTagID( tag.getTagUID());
-						}
-					});
-			}
-		}
-		
-		m = menu_manager.addMenuItem( menu, "sep2" );
-			
-		m.setStyle( MenuItem.STYLE_SEPARATOR );
-
-		m = menu_manager.addMenuItem( menu, "label.add.tag" );
-		
-		m.addListener(
-			new MenuItemListener() 
-			{
-				public void
-				selected(
-					MenuItem			menu,
-					Object 				target )
-				{
-					addTag();
-				}
-			});
-	}
-
-	private void 
-	addTag()	
-	{
-		Tag new_tag = TagUIUtils.createManualTag();
-		
-		if ( new_tag != null ){
-		
-			subs.setTagID( new_tag.getTagUID());
-		}
-	}
-	
-	
-	protected void export() {
-		Utils.execSWTThread(
-			new AERunnable() 
-			{
-				public void 
-				runSupport()
-				{
-					FileDialog dialog = 
-						new FileDialog( Utils.findAnyShell(), SWT.SYSTEM_MODAL | SWT.SAVE );
-					
-					dialog.setFilterPath( TorrentOpener.getFilterPathData() );
-											
-					dialog.setText(MessageText.getString("subscript.export.select.template.file"));
-					
-					dialog.setFilterExtensions(new String[] {
-							"*.vuze",
-							"*.vuz",
-							Constants.FILE_WILDCARD
-						});
-					dialog.setFilterNames(new String[] {
-							"*.vuze",
-							"*.vuz",
-							Constants.FILE_WILDCARD
-						});
-					
-					String path = TorrentOpener.setFilterPathData( dialog.open());
-
-					if ( path != null ){
-						
-						String lc = path.toLowerCase();
-						
-						if ( !lc.endsWith( ".vuze" ) && !lc.endsWith( ".vuz" )){
-							
-							path += ".vuze";
-						}
-						
-						try{
-							VuzeFile vf = subs.getVuzeFile();
-							
-							vf.write( new File( path ));
-							
-
-						}catch( Throwable e ){
-							
-							Debug.out( e );
-						}
-					}
-				}
-			});
-	}
-
-	protected void
-	removeWithConfirm( )
-	{
-		MessageBoxShell mb = 
-			new MessageBoxShell(
-				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 );
-		
-		mb.open(new UserPrompterResultListener() {
-			public void prompterClosed(int result) {
-				if (result == 0) {
-					subs.setSubscribed( false );
-				}
-			}
-		});
-	}
-	
-	protected void
-	showProperties()
-	{
-		SubscriptionHistory history = subs.getHistory();
-		
-		SimpleDateFormat df = new SimpleDateFormat();
-		
-		String last_error = history.getLastError();
-		
-		if ( last_error == null ){
-			last_error = "";
-		}
-		
-		String	engine_str;
-		String	auth_str	= String.valueOf(false);
-		
-		try{
-			Engine engine = subs.getEngine();
-			
-			engine_str = engine.getNameEx();
-			
-			if ( engine instanceof WebEngine ){
-			
-				WebEngine web_engine = (WebEngine)engine;
-				
-				if ( web_engine.isNeedsAuth()){
-					
-					auth_str = String.valueOf(true) + ": cookies=" + toString( web_engine.getRequiredCookies());
-				}
-			}
-		}catch( Throwable e ){
-			
-			engine_str 	= "Unknown";
-			auth_str	= "";
-		}
-		
-		String[] keys = {
-				"subs.prop.enabled",
-				"subs.prop.is_public",
-				"subs.prop.is_auto",
-				"subs.prop.is_auto_ok",
-				"subs.prop.update_period",
-				"subs.prop.last_scan",
-				"subs.prop.last_result",
-				"subs.prop.next_scan",
-				"subs.prop.last_error",
-				"subs.prop.num_read",
-				"subs.prop.num_unread",
-				"subs.prop.assoc",
-				"subs.prop.version",
-				"subs.prop.high_version",
-				"subscriptions.listwindow.popularity",
-				"subs.prop.template",
-				"subs.prop.auth",
-				"TableColumn.header.category",
-				"TableColumn.header.tag.name",
-			};
-		
-		String	category_str;
-		
-		String category = subs.getCategory();
-		
-		if ( category == null ){
-			
-			category_str = MessageText.getString( "Categories.uncategorized" );
-			
-		}else{
-			
-			category_str = category;
-		}
-				
-		Tag tag = TagManagerFactory.getTagManager().lookupTagByUID( subs.getTagID() );
-		
-		String tag_str = tag==null?"":tag.getTagName( true );
-		
-		int	 check_freq			= history.getCheckFrequencyMins();
-		long last_new_result 	= history.getLastNewResultTime();
-		long next_scan 			= history.getNextScanTime();
-		
-		String[] values = { 
-				String.valueOf( history.isEnabled()),
-				String.valueOf( subs.isPublic()),
-				String.valueOf( history.isAutoDownload()),
-				String.valueOf( subs.isAutoDownloadSupported()),
-				(check_freq==Integer.MAX_VALUE?"":(String.valueOf( history.getCheckFrequencyMins() + " " + MessageText.getString( "ConfigView.text.minutes")))),
-				df.format(new Date( history.getLastScanTime())),
-				( last_new_result==0?"":df.format(new Date( last_new_result ))),
-				( next_scan == Long.MAX_VALUE?"":df.format(new Date( next_scan ))),
-				(last_error.length()==0?MessageText.getString("PeersView.uniquepiece.none"):last_error),
-				String.valueOf( history.getNumRead()),
-				String.valueOf( history.getNumUnread()),
-				String.valueOf( subs.getAssociationCount()),
-				String.valueOf( subs.getVersion()),
-				subs.getHighestVersion() > subs.getVersion()?String.valueOf( subs.getHighestVersion()):null,
-				subs.getCachedPopularity()<=1?null:String.valueOf( subs.getCachedPopularity()),
-				engine_str,
-				auth_str,
-				category_str,
-				tag_str,
-			};
-		
-		new PropertiesWindow( subs.getName(), keys, values );
-	}
-
-	private String
-	toString(
-		String[]	strs )
-	{
-		String	res = "";
-		
-		for(int i=0;i<strs.length;i++){
-			res += (i==0?"":",") + strs[i];
-		}
-		
-		return( res );
-	}
-	
-
 	public Object 
 	getTitleInfoProperty(
 		int propertyID ) 
@@ -1034,20 +214,9 @@ public class SubscriptionMDIEntry implements SubscriptionListener, ViewTitleInfo
 		return( null );
 	}
 
-	public abstract static class SubsMenuItemListener implements MenuItemListener {
-		public final void selected(MenuItem menu, Object target) {
-			if (target instanceof MdiEntry) {
-				MdiEntry info = (MdiEntry) target;
-				Subscription subs = (Subscription) info.getDatasource();
-				
-				try {
-					selected(info, subs);
-				} catch (Throwable t) {
-					Debug.out(t);
-				}
-			}
-		}
-
-		public abstract void selected(MdiEntry info, Subscription subs);
+	protected void
+	removeWithConfirm()
+	{
+		SubscriptionManagerUI.removeWithConfirm( subs );
 	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionManagerUI.java b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionManagerUI.java
index b55d5be..d66b2f9 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionManagerUI.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionManagerUI.java
@@ -1,1301 +1,2308 @@
-/*
- * Created on Jul 29, 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.ui.swt.subscriptions;
-
-import java.util.*;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-
-import org.gudy.azureus2.core3.config.COConfigurationManager;
-import org.gudy.azureus2.core3.internat.MessageText;
-import org.gudy.azureus2.core3.util.*;
-import org.gudy.azureus2.plugins.PluginConfigListener;
-import org.gudy.azureus2.plugins.PluginInterface;
-import org.gudy.azureus2.plugins.download.Download;
-import org.gudy.azureus2.plugins.torrent.Torrent;
-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.model.BasicPluginConfigModel;
-import org.gudy.azureus2.plugins.ui.tables.*;
-import org.gudy.azureus2.plugins.utils.DelayedTask;
-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.Utils;
-import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
-import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewEventListenerHolder;
-import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
-
-import com.aelitis.azureus.core.subs.*;
-import com.aelitis.azureus.ui.UIFunctions;
-import com.aelitis.azureus.ui.UIFunctionsManager;
-import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
-import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager;
-import com.aelitis.azureus.ui.mdi.*;
-import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
-import com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry;
-import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
-
-public class 
-SubscriptionManagerUI 
-{
-	public static final Object	SUB_ENTRYINFO_KEY 		= new Object();
-	public static final Object	SUB_EDIT_MODE_KEY 	= new Object();
-	
-	private static final String ALERT_IMAGE_ID	= "image.sidebar.vitality.alert";
-	private static final String INFO_IMAGE_ID	= "image.sidebar.vitality.info";
-	
-
-	static final String EDIT_MODE_MARKER	= "&editMode=1";
-	
-	private Graphic	icon_rss_big;
-	private Graphic	icon_rss_small;
-	private Graphic	icon_rss_all_add_small;
-	private Graphic	icon_rss_all_add_big;
-	private Graphic	icon_rss_some_add_small;
-	private Graphic	icon_rss_some_add_big;
-	private List<Graphic>	icon_list	= new ArrayList<Graphic>();
-	
-	private List<TableColumn> columns = new ArrayList<TableColumn>();
-	protected UISWTInstance swt;
-	private UIManager ui_manager;
-	private PluginInterface default_pi;
-	private MdiEntry mdiEntryOverview;
-	
-	private boolean	sidebar_setup_done;
-	
-	public
-	SubscriptionManagerUI()
-	{
-		default_pi = PluginInitializer.getDefaultInterface();
-		
-		final TableManager	table_manager = default_pi.getUIManager().getTableManager();
-
-		Utils.getOffOfSWTThread(new AERunnable() {
-			public void runSupport() {
-				SubscriptionManagerFactory.getSingleton();
-			}
-		});
-		
-		if ( Constants.isCVSVersion()){			
-			
-				// check assoc
-			
-			{
-				final TableContextMenuItem menu_item_itorrents = 
-					table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_INCOMPLETE, "azsubs.contextmenu.lookupassoc");
-				final TableContextMenuItem menu_item_ctorrents 	= 
-					table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_COMPLETE, "azsubs.contextmenu.lookupassoc");
-				
-				menu_item_itorrents.setStyle(TableContextMenuItem.STYLE_PUSH);
-				menu_item_ctorrents.setStyle(TableContextMenuItem.STYLE_PUSH);
-		
-				MenuItemListener listener = 
-					new MenuItemListener()
-					{
-						public void 
-						selected(
-							MenuItem 	menu, 
-							Object 		target) 
-						{
-							TableRow[]	rows = (TableRow[])target;
-							
-							if ( rows.length > 0 ){
-								
-								Download download = (Download)rows[0].getDataSource();
-								
-								new SubscriptionListWindow(PluginCoreUtils.unwrap(download), false);
-							}
-							/*
-							for (int i=0;i<rows.length;i++){
-								
-								Download download = (Download)rows[i].getDataSource();
-								
-								Torrent t = download.getTorrent();
-								
-								if ( t != null ){
-									
-									try{
-										lookupAssociations( 
-											t.getHash(),
-											new SubscriptionLookupListener()
-											{
-												public void
-												found(
-													byte[]					hash,
-													Subscription			subscription )
-												{
-													log( "    lookup: found " + ByteFormatter.encodeString( hash ) + " -> " + subscription.getName());
-												}
-												
-												public void
-												complete(
-													byte[]					hash,
-													Subscription[]			subscriptions )
-												{
-													log( "    lookup: complete " + ByteFormatter.encodeString( hash ) + " -> " +subscriptions.length );
-		
-												}
-												
-												public void
-												failed(
-													byte[]					hash,
-													SubscriptionException	error )
-												{
-													log( "    lookup: failed", error );
-												}
-											});
-										
-									}catch( Throwable e ){
-										
-										log( "Lookup failed", e );
-									}
-								}	
-							}*/
-						}
-					};
-				
-				menu_item_itorrents.addMultiListener( listener );
-				menu_item_ctorrents.addMultiListener( listener );	
-			}
-			
-				// make assoc - CVS only as for testing purposes
-			
-			if ( false ){
-			
-				final TableContextMenuItem menu_item_itorrents = 
-					table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_INCOMPLETE, "azsubs.contextmenu.addassoc");
-				final TableContextMenuItem menu_item_ctorrents 	= 
-					table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_COMPLETE, "azsubs.contextmenu.addassoc");
-				
-				menu_item_itorrents.setStyle(TableContextMenuItem.STYLE_MENU);
-				menu_item_ctorrents.setStyle(TableContextMenuItem.STYLE_MENU);
-				
-				MenuItemFillListener	menu_fill_listener = 
-					new MenuItemFillListener()
-					{
-						public void
-						menuWillBeShown(
-							MenuItem	menu,
-							Object		target )
-						{	
-							SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
-
-							if ( subs_man == null ){
-								
-								return;
-							}
-							
-							TableRow[]	rows;
-							
-							if ( target instanceof TableRow[] ){
-								
-								rows = (TableRow[])target;
-								
-							}else{
-								
-								rows = new TableRow[]{ (TableRow)target };
-							}
-							
-							final List<byte[]>	hashes = new ArrayList<byte[]>();
-							
-							for (int i=0;i<rows.length;i++){
-								
-								Download	download = (Download)rows[i].getDataSource();
-							
-								if ( download != null ){
-									
-									Torrent torrent = download.getTorrent();
-									
-									if ( torrent != null ){
-										
-										hashes.add( torrent.getHash());
-									}
-								}
-							}
-														
-							menu.removeAllChildItems();
-							
-							boolean enabled = hashes.size() > 0;
-							
-							if ( enabled ){
-							
-								Subscription[] subs = subs_man.getSubscriptions( true );
-								
-								boolean	incomplete = ((TableContextMenuItem)menu).getTableID() == TableManager.TABLE_MYTORRENTS_INCOMPLETE;
-								
-								TableContextMenuItem parent = incomplete?menu_item_itorrents:menu_item_ctorrents;
-																
-								for (int i=0;i<subs.length;i++){
-									
-									final Subscription	sub = subs[i];
-									
-									TableContextMenuItem item =
-										table_manager.addContextMenuItem(
-											parent,
-											"!" + sub.getName() + "!");
-									
-									item.addListener(
-										new MenuItemListener()
-										{
-											public void 
-											selected(
-												MenuItem 	menu,
-												Object 		target ) 
-											{
-												for (int i=0;i<hashes.size();i++){
-													
-													sub.addAssociation( hashes.get(i));
-												}
-											}
-										});
-								}
-							}
-							
-							menu.setEnabled( enabled );
-						}
-					};
-					
-				menu_item_itorrents.addFillListener( menu_fill_listener );
-				menu_item_ctorrents.addFillListener( menu_fill_listener );		
-			}
-		}
-	
-		createSubsColumns( table_manager );
-
-		ui_manager = default_pi.getUIManager();
-
-		ui_manager.addUIListener(
-				new UIManagerListener()
-				{
-					public void
-					UIAttached(
-						UIInstance		instance )
-					{
-						if (!( instance instanceof UISWTInstance )){
-							return;
-
-						}
-						
-						swt = (UISWTInstance)instance;
-						
-						uiQuickInit();
-
-        		Utilities utilities = default_pi.getUtilities();
-        		
-        		final DelayedTask dt = utilities.createDelayedTask(new Runnable()
-        			{
-        				public void 
-        				run() 
-        				{
-        					Utils.execSWTThread(new AERunnable() {
-									
-										public void 
-										runSupport() 
-										{
-       								delayedInit();
-        						}
-        					});
-        				}
-        			});
-        			
-        			dt.queue();		
-					}
-
-					public void UIDetached(UIInstance instance) {
-					}
-				});
-	}
-	
-	void uiQuickInit() {
-		
-		final MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-		
-		if ( mdi == null ){
-			
-				// closing down
-			
-			return;
-		}
-
-		icon_rss_small			= loadGraphic( swt, "subscription_icon.png" );
-		icon_rss_big			= icon_rss_small;
-
-		icon_rss_all_add_small	= loadGraphic( swt, "subscription_icon_inactive.png" );
-		icon_rss_all_add_big	= icon_rss_all_add_small;
-		
-		icon_rss_some_add_small	= icon_rss_all_add_small;
-		icon_rss_some_add_big	= icon_rss_some_add_small;
-		
-
-		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_SUBSCRIPTIONS,
-				new MdiEntryCreationListener() {
-					public MdiEntry createMDiEntry(String id) {
-						setupSideBar( swt );
-						return mdiEntryOverview;
-					}
-				});
-		boolean uiClassic = COConfigurationManager.getStringParameter("ui").equals("az2");
-		if (uiClassic) {
-			registerAllSubscriptions();
-		}
-	}
-
-	void delayedInit() {
-		if (swt == null) {
-			return;
-		}
-		
-		SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
-		subs_man.addListener(
-			new SubscriptionManagerListener()
-			{
-				public void 
-				subscriptionAdded(
-					Subscription subscription ) 
-				{
-				}
-				
-				public void
-				subscriptionChanged(
-					Subscription		subscription )
-				{
-				}
-				
-				public void 
-				subscriptionSelected(
-					Subscription subscription )
-				{		
-				}
-				
-				public void 
-				subscriptionRemoved(
-					Subscription subscription ) 
-				{
-				}
-				
-				public void 
-				associationsChanged(
-					byte[] hash )
-				{
-					refreshColumns();
-				}
-			});	
-		
-		createConfigModel();
-	}
-
-	private void createConfigModel() {
-		final SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
-
-		BasicPluginConfigModel configModel = ui_manager.createBasicPluginConfigModel(
-				ConfigSection.SECTION_ROOT, "Subscriptions");
-
-		final IntParameter max_results = 
-			configModel.addIntParameter2( 
-				"subscriptions.config.maxresults", 
-				"subscriptions.config.maxresults", 
-				subs_man.getMaxNonDeletedResults());
-			
-			// search
-		
-		final BooleanParameter search_enable = 
-			configModel.addBooleanParameter2( 
-				"subscriptions.search.enable", "subscriptions.search.enable",
-				subs_man.isSearchEnabled());
-		
-		search_enable.addListener(
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					Parameter param) 
-				{
-					subs_man.setSearchEnabled( search_enable.getValue());
-				}
-			});
-		
-			// download subs enable
-		
-		final BooleanParameter download_subs_enable = 
-			configModel.addBooleanParameter2( 
-				"subscriptions.dl_subs.enable", "subscriptions.dl_subs.enable",
-				subs_man.isSubsDownloadEnabled());
-		
-		download_subs_enable.addListener(
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					Parameter param) 
-				{
-					subs_man.setSubsDownloadEnabled( download_subs_enable.getValue());
-				}
-			});
-		
-			// auto
-		
-		final BooleanParameter auto_start = configModel.addBooleanParameter2(
-				"subscriptions.config.autostartdls",
-				"subscriptions.config.autostartdls",
-				subs_man.getAutoStartDownloads());
-		
-		auto_start.addListener(
-			new ParameterListener()
-			{
-				public void 
-				parameterChanged(
-					Parameter param )
-				{
-					subs_man.setAutoStartDownloads( auto_start.getValue());
-				}
-			});
-		
-		final IntParameter min_auto_start_size = 
-			configModel.addIntParameter2( 
-				"subscriptions.config.autostart.min", 
-				"subscriptions.config.autostart.min", 
-				subs_man.getAutoStartMinMB());
-
-		final IntParameter max_auto_start_size = 
-			configModel.addIntParameter2( 
-				"subscriptions.config.autostart.max", 
-				"subscriptions.config.autostart.max", 
-				subs_man.getAutoStartMaxMB());
-
-		auto_start.addEnabledOnSelection( min_auto_start_size );
-		auto_start.addEnabledOnSelection( max_auto_start_size );
-		
-		configModel.createGroup( 
-			"subscriptions.config.auto", 
-			new Parameter[]{
-					auto_start, 
-					min_auto_start_size,
-					max_auto_start_size,
-			});
-		
-			// int param fires intermediate events so we have to rely on the save :(
-		
-		default_pi.getPluginconfig().addListener(
-			new PluginConfigListener()
-			{
-				public void 
-				configSaved() 
-				{
-					subs_man.setMaxNonDeletedResults(max_results.getValue());
-					subs_man.setAutoStartMinMB(min_auto_start_size.getValue());
-					subs_man.setAutoStartMaxMB(max_auto_start_size.getValue());
-				}
-			});
-
-		
-			// 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,
-			});
-	}
-
-	private void 
-	createSubsColumns(
-		TableManager table_manager )
-	{
-		final TableCellRefreshListener	subs_refresh_listener = 
-			new TableCellRefreshListener()
-			{
-				public void 
-				refresh(
-					TableCell _cell )
-				{
-					TableCellSWT cell = (TableCellSWT)_cell;
-					
-					SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
-					
-					Download	dl = (Download)cell.getDataSource();
-					
-					if ( dl == null ){
-						
-						return;
-					}
-					
-					Torrent	torrent = dl.getTorrent();
-					
-					if ( torrent != null ){
-						
-						Subscription[] subs = subs_man.getKnownSubscriptions( torrent.getHash());
-														
-						int	num_subscribed		= 0;
-						int	num_unsubscribed	= 0;
-						
-						for (int i=0;i<subs.length;i++){
-							
-							if ( subs[i].isSubscribed()){
-																
-								num_subscribed++;
-								
-							}else{
-								
-								num_unsubscribed++;
-							}
-						}
-						
-						Graphic graphic;
-						String	tooltip;
-						
-						int height = cell.getHeight();
-						
-						int	sort_order = 0;
-						
-						if ( subs.length == 0 ){
-							
-							graphic = null;
-							tooltip	= null;
-							
-						}else{
-						
-							if ( num_subscribed == subs.length ){
-								
-								graphic = height >= 22?icon_rss_all_add_big:icon_rss_all_add_small;
-								
-								tooltip = MessageText.getString( "subscript.all.subscribed" );
-								
-							}else if ( num_subscribed > 0 ){
-								
-								graphic = height >= 22?icon_rss_some_add_big:icon_rss_some_add_small;
-
-								tooltip = MessageText.getString( "subscript.some.subscribed" );
-
-								sort_order	= 10000;
-								
-							}else{
-								
-								graphic = height >= 22?icon_rss_big:icon_rss_small;
-								
-								tooltip = MessageText.getString( "subscript.none.subscribed" );
-								
-								sort_order	= 1000000;
-							}
-						}
-						
-						sort_order += 1000*num_unsubscribed + num_subscribed;
-						
-						cell.setMarginHeight(0);
-						cell.setGraphic( graphic );
-						cell.setToolTip( tooltip );
-						
-						cell.setSortValue( sort_order );
-						
-						cell.setCursorID( graphic==null?SWT.CURSOR_ARROW:SWT.CURSOR_HAND );
-
-					}else{
-						
-						cell.setCursorID( SWT.CURSOR_ARROW );
-						
-						cell.setSortValue( 0 );
-					}
-				}
-			};
-			
-		final TableCellMouseListener	subs_mouse_listener = 
-			new TableCellMouseListener()
-			{
-				public void 
-				cellMouseTrigger(
-					TableCellMouseEvent event )
-				{
-					if ( event.eventType == TableCellMouseEvent.EVENT_MOUSEDOWN ){
-						
-						
-						TableCell cell = event.cell;
-						
-						Download	dl = (Download)cell.getDataSource();
-						
-						Torrent	torrent = dl.getTorrent();
-						
-						if ( torrent != null ){
-							
-							SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
-							Subscription[] subs = subs_man.getKnownSubscriptions( torrent.getHash());
-							
-							if ( subs.length > 0 ){
-								
-								event.skipCoreFunctionality	= true;
-
-								new SubscriptionWizard(PluginCoreUtils.unwrap(dl));
-								
-								COConfigurationManager.setParameter( "subscriptions.wizard.shown", true );
-
-								refreshTitles( mdiEntryOverview );
-								
-								//new SubscriptionListWindow(PluginCoreUtils.unwrap(dl),true);
-							}
-						}
-					}
-				}
-			};
-			
-		table_manager.registerColumn(
-			Download.class, 
-			"azsubs.ui.column.subs", 
-			new TableColumnCreationListener() 
-			{
-				public void tableColumnCreated(TableColumn result) {
-					result.setAlignment(TableColumn.ALIGN_CENTER);
-					result.setPosition(TableColumn.POSITION_LAST);
-					result.setWidth(32);
-					result.setRefreshInterval(TableColumn.INTERVAL_INVALID_ONLY);
-					result.setType(TableColumn.TYPE_GRAPHIC);
-				
-					result.addCellRefreshListener( subs_refresh_listener );
-					result.addCellMouseListener( subs_mouse_listener );
-					result.setIconReference("image.subscription.column", true);
-					
-					synchronized (columns) {
-						columns.add(result);
-					}
-				}
-			});
-		
-		final TableCellRefreshListener	link_refresh_listener = 
-			new TableCellRefreshListener()
-			{
-				public void 
-				refresh(
-					TableCell _cell )
-				{
-					TableCellSWT cell = (TableCellSWT)_cell;
-					
-					SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
-					
-					Download	dl = (Download)cell.getDataSource();
-					
-					if ( dl == null ){
-						
-						return;
-					}
-					
-					String	str 		= "";
-					
-					Torrent	torrent = dl.getTorrent();
-					
-					if ( torrent != null ){
-						
-						byte[]	hash = torrent.getHash();
-						
-						Subscription[] subs = subs_man.getKnownSubscriptions( hash );
-														
-						for (int i=0;i<subs.length;i++){
-							
-							Subscription sub = subs[i];
-							
-							if ( sub.hasAssociation( hash )){
-								
-								str += (str.length()==0?"":"; ") + sub.getName();
-							}
-						}
-					}
-					
-					cell.setCursorID( str.length() > 0?SWT.CURSOR_HAND:SWT.CURSOR_ARROW );
-					
-					cell.setText( str );
-				}
-			};
-		
-			final TableCellMouseListener	link_mouse_listener = 
-				new TableCellMouseListener()
-				{
-					public void 
-					cellMouseTrigger(
-						TableCellMouseEvent event )
-					{
-						if ( event.eventType == TableCellMouseEvent.EVENT_MOUSEDOWN ){
-										
-							TableCell cell = event.cell;
-							
-							Download	dl = (Download)cell.getDataSource();
-							
-							Torrent	torrent = dl.getTorrent();
-
-							SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
-
-							if ( torrent != null ){
-								
-								byte[]	hash = torrent.getHash();
-								
-								Subscription[] subs = subs_man.getKnownSubscriptions( hash );
-																
-								for (int i=0;i<subs.length;i++){
-									
-									Subscription sub = subs[i];
-									
-									if ( sub.hasAssociation( hash )){
-										
-										String key = "Subscription_" + ByteFormatter.encodeString(sub.getPublicKey());
-										MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-										if ( mdi != null ){
-											mdi.showEntryByID(key);
-										}
-										break;
-									}
-								}
-							}
-						}
-					}
-				};
-				
-		table_manager.registerColumn(
-				Download.class, 
-				"azsubs.ui.column.subs_link", 
-				new TableColumnCreationListener() 
-				{
-					public void tableColumnCreated(TableColumn result) {
-						result.setAlignment(TableColumn.ALIGN_LEAD);
-						result.setPosition(TableColumn.POSITION_INVISIBLE);
-						result.setWidth(85);
-						result.setRefreshInterval(TableColumn.INTERVAL_INVALID_ONLY);
-						result.setType(TableColumn.TYPE_TEXT_ONLY);
-					
-						result.addCellRefreshListener( link_refresh_listener );
-						result.addCellMouseListener( link_mouse_listener );
-						result.setMinimumRequiredUserMode( Parameter.MODE_INTERMEDIATE );
-						
-						synchronized (columns) {
-							columns.add(result);
-						}
-					}
-				});
-	}
-	
-	protected void
-	setupSideBar(
-		final UISWTInstance		swt_ui )		
-	{
-		boolean uiClassic = COConfigurationManager.getStringParameter("ui").equals("az2");
-
-		MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
-		
-		if (mdi == null) {
-			return;
-		}
-		
-		mdiEntryOverview = mdi.createEntryFromEventListener(
-				MultipleDocumentInterface.SIDEBAR_HEADER_DISCOVERY, 
-				new UISWTViewEventListenerHolder(
-						MultipleDocumentInterface.SIDEBAR_SECTION_SUBSCRIPTIONS,
-						SubscriptionsView.class, null, null),
-				MultipleDocumentInterface.SIDEBAR_SECTION_SUBSCRIPTIONS, false, null, null );
-
-		if (mdiEntryOverview == null) {
-			return;
-		}
-			
-		synchronized( this ){
-				// seen double add buttons in the sidebar, not sure of cause but it would imply we are coming through here
-				// twice which can't be good - protect against that
-			
-			if( sidebar_setup_done ){
-				
-				return;
-			}
-			
-			sidebar_setup_done = true;
-		}
-		
-		mdiEntryOverview.setImageLeftID("image.sidebar.subscriptions");
-
-		setupHeader(mdi, mdiEntryOverview);
-
-//		MdiEntry headerEntry = mdi.getEntry(MultipleDocumentInterface.SIDEBAR_HEADER_DISCOVERY);
-//		if (headerEntry != null) {
-//			setupHeader(mdi, headerEntry);
-//		}
-
-		String parentID = "sidebar." + MultipleDocumentInterface.SIDEBAR_HEADER_DISCOVERY;
-
-		MenuManager menu_manager = ui_manager.getMenuManager();
-		
-		MenuItem mi = menu_manager.addMenuItem( parentID, "MainWindow.menu.view.configuration" );
-		
-		mi.addListener( 
-				new MenuItemListener() 
-				{
-					public void 
-					selected(
-						MenuItem menu, Object target ) 
-					{
-				      	 UIFunctions uif = UIFunctionsManager.getUIFunctions();
-				      	 
-				      	 if ( uif != null ){
-				      		 
-				      		 uif.openView( UIFunctions.VIEW_CONFIG, "Subscriptions" );
-				      	 }
-					}
-				});
-		
-		SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
-		subs_man.addListener(
-			new SubscriptionManagerListener()
-			{
-				public void 
-				subscriptionAdded(
-					Subscription 		subscription ) 
-				{
-					registerSubscriptionViewMdiEntry( subscription, false );
-				}
-	
-				public void
-				subscriptionChanged(
-					Subscription		subscription )
-				{
-					changeSubscription( subscription );
-				}
-				
-				public void 
-				subscriptionSelected(
-					Subscription sub )
-				{	
-					
-					String key = "Subscription_" + ByteFormatter.encodeString(sub.getPublicKey());
-					MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-					if ( mdi != null ){
-						mdi.showEntryByID(key);
-					}
-				}
-				
-				public void 
-				subscriptionRemoved(
-					Subscription 		subscription ) 
-				{
-					removeSubscription( subscription );
-				}
-				
-				public void
-				associationsChanged(
-					byte[]		association_hash )
-				{
-					 
-				}
-			});
-		
-		if (!uiClassic) {
-			registerAllSubscriptions();
-		}
-
-		mdi.addListener(
-			new MdiListener() 
-			{
-				private long last_select = 0;
-				
-				public void 
-				mdiEntrySelected(
-					MdiEntry new_entry,
-					MdiEntry old_entry ) 
-				{
-					if ( new_entry == old_entry && (new_entry instanceof BaseMdiEntry) ){
-						
-						UISWTViewEventListener eventListener = ((BaseMdiEntry)new_entry).getEventListener();
-						
-						if ( eventListener instanceof SubscriptionView ){
-							
-							try{
-								
-								if ( SystemTime.getMonotonousTime() - last_select > 1000 ){
-									
-									((SubscriptionView)eventListener).updateBrowser( false );
-								}
-							}finally{
-								
-								last_select = SystemTime.getMonotonousTime();
-							}
-						}
-					}
-				}
-			});
-	}
-	
-	private void setupHeader(MultipleDocumentInterface mdi,
-			final MdiEntry headerEntry) {
-
-		MdiEntryVitalityImage addSub = headerEntry.addVitalityImage("image.sidebar.subs.add");
-
-		if (addSub != null) {
-			addSub.setToolTip(MessageText.getString("subscriptions.add.tooltip"));
-
-			addSub.addListener(new MdiEntryVitalityImageListener() {
-				public void mdiEntryVitalityImage_clicked(int x, int y) {
-					new SubscriptionWizard();
-					
-					COConfigurationManager.setParameter( "subscriptions.wizard.shown", true );
-
-					refreshTitles( mdiEntryOverview );
-				}
-			});
-		}
-
-		final MdiEntryVitalityImage warnSub = headerEntry.addVitalityImage(ALERT_IMAGE_ID);
-		if (warnSub != null) {
-			warnSub.setVisible(false);
-		}
-
-		final MdiEntryVitalityImage infoSub = headerEntry.addVitalityImage(INFO_IMAGE_ID);
-		if (infoSub != null) {
-			infoSub.setVisible(false);
-		}
-
-		
-		headerEntry.setViewTitleInfo(
-			new ViewTitleInfo() 
-			{
-				private long	last_avail_calc = -1;
-				private int		last_avail;
-				
-				public Object 
-				getTitleInfoProperty(
-					int propertyID) 
-				{
-					Object result = null;
-	
-					// COConfigurationManager.setParameter( "subscriptions.wizard.shown", false );
-					
-					if (propertyID == TITLE_INDICATOR_TEXT) {
-	
-						boolean expanded = headerEntry.isExpanded();
-	
-						SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
-						
-						Subscription[] subs = subs_man.getSubscriptions(true);
-						
-						if ( expanded ){
-	
-							warnSub.setVisible(false);
-	
-						}else{
-	
-							int total = 0;
-							
-							boolean warn = false;
-	
-							String error_str = "";
-	
-							for (Subscription s : subs) {
-	
-								SubscriptionHistory history = s.getHistory();
-	
-								total += history.getNumUnread();
-	
-								String last_error = history.getLastError();
-	
-								if (last_error != null && last_error.length() > 0) {
-	
-									boolean auth_fail = history.isAuthFail();
-	
-									if (history.getConsecFails() >= 3 || auth_fail) {
-	
-										warn = true;
-	
-										if (error_str.length() > 128) {
-	
-											if (!error_str.endsWith(", ...")) {
-	
-												error_str += ", ...";
-											}
-										} else {
-	
-											error_str += (error_str.length() == 0 ? "" : ", ")
-													+ last_error;
-										}
-									}
-								}
-							}
-	
-							warnSub.setVisible(warn);
-							warnSub.setToolTip(error_str);
-							
-							if (total > 0) {
-	
-								result = String.valueOf( total );
-							}
-						}
-						
-						if ( subs.length == 0 && !COConfigurationManager.getBooleanParameter( "subscriptions.wizard.shown", false )){
-							
-							long now = SystemTime.getMonotonousTime();
-							
-							if ( 	last_avail_calc == -1 ||
-									now - last_avail_calc > 60*1000 ){
-								
-								last_avail = subs_man.getKnownSubscriptionCount();
-								
-								last_avail_calc = now;
-							}
-							
-							if ( last_avail > 0 ){
-								
-								infoSub.setVisible( true );
-								
-								infoSub.setToolTip( 
-									MessageText.getString(
-										"subscriptions.info.avail",
-										new String[]{
-											String.valueOf( last_avail )
-										}));
-							}
-						}else{
-							
-							infoSub.setVisible( false );
-						}
-					}
-	
-					return( result );
-				}
-			});
-	}
-
-	private void 
-	registerAllSubscriptions() 
-	{
-		SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
-	
-		Subscription[]	subs = subs_man.getSubscriptions( true );
-		
-		Arrays.sort(
-			subs,
-			new Comparator<Subscription>()
-			{
-				public int 
-				compare(
-					Subscription o1, Subscription o2 )
-				{
-					return( o1.getName().compareToIgnoreCase( o2.getName()));
-				}
-			});
-		
-		for (int i=0;i<subs.length;i++){
-			
-			registerSubscriptionViewMdiEntry( subs[i], false );
-		}
-	}
-
-	protected void
-	changeSubscription(
-		final Subscription	subs )
-	{
-		refreshTitles( mdiEntryOverview );
-
-		if ( subs.isSubscribed()){
-			
-				// if the subscription wasn't previously subscribed then there won't be an MDI entry registered for it yet
-				// do so now
-			
-			final String key = "Subscription_" + ByteFormatter.encodeString(subs.getPublicKey());				
-
-			MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-
-			if ( mdi != null ){
-				
-				if ( mdi.getEntry( key ) == null ){
-					
-					registerSubscriptionViewMdiEntry( subs, false );
-				}
-			}
-		}else{
-			
-			removeSubscription( subs);
-		}
-	}
-	
-	protected void
-	registerSubscriptionViewMdiEntry(
-		final Subscription		subs,
-		final boolean			show )
-	{
-		if ( !subs.isSubscribed()){
-			
-			return;
-		}
-		
-			// hack to hide useless entries
-		
-		String name = subs.getName();
-		
-		if ( name.startsWith( "Search Template: " )){
-			
-			return;
-		}
-	
-		refreshColumns();
-		
-		final String key = "Subscription_" + ByteFormatter.encodeString(subs.getPublicKey());				
-
-		MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-
-		if ( mdi == null ){
-			
-				// closing down
-			
-			return;
-		}
-
-		mdi.registerEntry(key, new MdiEntryCreationListener() {
-			public MdiEntry createMDiEntry(String id) {
-				return createSubscriptionMdiEntry(subs);
-			}
-		});
-
-		boolean uiClassic = COConfigurationManager.getStringParameter("ui").equals("az2");
-		if (uiClassic && !show) {
-			return;
-		}
-		
-		mdi.loadEntryByID(key, show, true, subs);
-	}
-	
-	private MdiEntry createSubscriptionMdiEntry(Subscription subs) {
-		
-		if (!subs.isSubscribed()) {
-			// user may have deleted subscrtipion, but our register is staill there
-			return null;
-		}
-		
-		MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
-		
-		if ( mdi == null ){
-			
-				// closing down
-		
-			return( null );
-		}
-	
-		final String key = "Subscription_" + ByteFormatter.encodeString(subs.getPublicKey());
-		
-		MdiEntry entry = mdi.createEntryFromEventListener(
-				MultipleDocumentInterface.SIDEBAR_HEADER_DISCOVERY,
-				new UISWTViewEventListenerHolder(key, SubscriptionView.class, subs, null),
-				key, true, subs, MultipleDocumentInterface.SIDEBAR_SECTION_SUBSCRIPTIONS);
-
-		// This sets up the entry (menu, etc)
-		SubscriptionMDIEntry entryInfo = new SubscriptionMDIEntry(subs, entry);
-		subs.setUserData(SUB_ENTRYINFO_KEY, entryInfo);
-
-		return entry;
-	}
-	
-	protected void
-	refreshTitles(
-		MdiEntry		entry )
-	{
-		MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-		
-		if ( mdi == null ){
-
-			return;
-		}
-		
-		while( entry != null ){
-	
-			ViewTitleInfoManager.refreshTitleInfo(entry.getViewTitleInfo());
-
-			String key = entry.getParentID();
-			
-			if ( key == null ){
-				
-				return;
-			}
-			
-			entry = mdi.getEntry( key );
-		}
-	}
-
-	protected void
-	removeSubscription(
-		final Subscription	subs )
-	{
-		synchronized( this ){
-
-			String key = "Subscription_" + ByteFormatter.encodeString(subs.getPublicKey());
-			MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
-			
-			if  (mdi != null ){
-				
-				mdi.closeEntry(key);
-			}
-
-		}
-		
-		refreshColumns();
-	}
-	
-	protected void
-	refreshColumns()
-	{
-		synchronized (columns) {
-  		for ( Iterator<TableColumn> iter = columns.iterator(); iter.hasNext();){
-  			
-  			TableColumn column = iter.next();
-  			
-  			column.invalidateCells();
-  		}
-		}
-	}
-	
-	protected Graphic
-	loadGraphic(
-		UISWTInstance	swt,
-		String			name )
-	{
-		Image	image = swt.loadImage( "com/aelitis/azureus/ui/images/" + name );
-
-		Graphic graphic = swt.createGraphic(image );
-		
-		icon_list.add( graphic );
-		
-		return( graphic );
-	}
-}
+/*
+ * Created on Jul 29, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.subscriptions;
+
+import java.io.File;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+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.internat.MessageText;
+import org.gudy.azureus2.core3.util.*;
+import org.gudy.azureus2.plugins.PluginConfigListener;
+import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.torrent.Torrent;
+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.model.BasicPluginConfigModel;
+import org.gudy.azureus2.plugins.ui.tables.*;
+import org.gudy.azureus2.plugins.utils.DelayedTask;
+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.*;
+import org.gudy.azureus2.ui.swt.mainwindow.ClipboardCopy;
+import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInputReceiver;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewEventListenerHolder;
+import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
+import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
+import org.gudy.azureus2.ui.swt.views.utils.TagUIUtils;
+
+import com.aelitis.azureus.core.metasearch.Engine;
+import com.aelitis.azureus.core.metasearch.impl.web.WebEngine;
+import com.aelitis.azureus.core.subs.*;
+import com.aelitis.azureus.core.tag.*;
+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.mdi.*;
+import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
+import com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry;
+import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
+import com.aelitis.azureus.ui.swt.utils.TagUIUtilsV3;
+
+public class 
+SubscriptionManagerUI 
+{
+	private static final String CONFIG_SECTION_ID = "Subscriptions";
+	public static final Object	SUB_ENTRYINFO_KEY 		= new Object();
+	public static final Object	SUB_EDIT_MODE_KEY 	= new Object();
+	
+	private static final String ALERT_IMAGE_ID	= "image.sidebar.vitality.alert";
+	private static final String INFO_IMAGE_ID	= "image.sidebar.vitality.info";
+	
+
+	static final String EDIT_MODE_MARKER	= "&editMode=1";
+	
+	private Graphic	icon_rss_big;
+	private Graphic	icon_rss_small;
+	private Graphic	icon_rss_all_add_small;
+	private Graphic	icon_rss_all_add_big;
+	private Graphic	icon_rss_some_add_small;
+	private Graphic	icon_rss_some_add_big;
+	private List<Graphic>	icon_list	= new ArrayList<Graphic>();
+	
+	private List<TableColumn> columns = new ArrayList<TableColumn>();
+	protected UISWTInstance swt;
+	private UIManager ui_manager;
+	private PluginInterface default_pi;
+	private MdiEntry mdiEntryOverview;
+	
+	private boolean	sidebar_setup_done;
+	
+	public
+	SubscriptionManagerUI()
+	{
+		default_pi = PluginInitializer.getDefaultInterface();
+		
+		final TableManager	table_manager = default_pi.getUIManager().getTableManager();
+
+		Utils.getOffOfSWTThread(new AERunnable() {
+			public void runSupport() {
+				SubscriptionManagerFactory.getSingleton();
+			}
+		});
+		
+		if ( Constants.isCVSVersion()){			
+			
+				// check assoc
+			
+			{
+				final TableContextMenuItem menu_item_itorrents = 
+					table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_INCOMPLETE, "azsubs.contextmenu.lookupassoc");
+				final TableContextMenuItem menu_item_ctorrents 	= 
+					table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_COMPLETE, "azsubs.contextmenu.lookupassoc");
+				
+				menu_item_itorrents.setStyle(TableContextMenuItem.STYLE_PUSH);
+				menu_item_ctorrents.setStyle(TableContextMenuItem.STYLE_PUSH);
+		
+				MenuItemListener listener = 
+					new MenuItemListener()
+					{
+						public void 
+						selected(
+							MenuItem 	menu, 
+							Object 		target) 
+						{
+							TableRow[]	rows = (TableRow[])target;
+							
+							if ( rows.length > 0 ){
+								
+								Download download = (Download)rows[0].getDataSource();
+								
+								new SubscriptionListWindow(PluginCoreUtils.unwrap(download), false);
+							}
+							/*
+							for (int i=0;i<rows.length;i++){
+								
+								Download download = (Download)rows[i].getDataSource();
+								
+								Torrent t = download.getTorrent();
+								
+								if ( t != null ){
+									
+									try{
+										lookupAssociations( 
+											t.getHash(),
+											new SubscriptionLookupListener()
+											{
+												public void
+												found(
+													byte[]					hash,
+													Subscription			subscription )
+												{
+													log( "    lookup: found " + ByteFormatter.encodeString( hash ) + " -> " + subscription.getName());
+												}
+												
+												public void
+												complete(
+													byte[]					hash,
+													Subscription[]			subscriptions )
+												{
+													log( "    lookup: complete " + ByteFormatter.encodeString( hash ) + " -> " +subscriptions.length );
+		
+												}
+												
+												public void
+												failed(
+													byte[]					hash,
+													SubscriptionException	error )
+												{
+													log( "    lookup: failed", error );
+												}
+											});
+										
+									}catch( Throwable e ){
+										
+										log( "Lookup failed", e );
+									}
+								}	
+							}*/
+						}
+					};
+				
+				menu_item_itorrents.addMultiListener( listener );
+				menu_item_ctorrents.addMultiListener( listener );	
+			}
+			
+				// make assoc - CVS only as for testing purposes
+			
+			if ( false ){
+			
+				final TableContextMenuItem menu_item_itorrents = 
+					table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_INCOMPLETE, "azsubs.contextmenu.addassoc");
+				final TableContextMenuItem menu_item_ctorrents 	= 
+					table_manager.addContextMenuItem(TableManager.TABLE_MYTORRENTS_COMPLETE, "azsubs.contextmenu.addassoc");
+				
+				menu_item_itorrents.setStyle(TableContextMenuItem.STYLE_MENU);
+				menu_item_ctorrents.setStyle(TableContextMenuItem.STYLE_MENU);
+				
+				MenuItemFillListener	menu_fill_listener = 
+					new MenuItemFillListener()
+					{
+						public void
+						menuWillBeShown(
+							MenuItem	menu,
+							Object		target )
+						{	
+							SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
+
+							if ( subs_man == null ){
+								
+								return;
+							}
+							
+							TableRow[]	rows;
+							
+							if ( target instanceof TableRow[] ){
+								
+								rows = (TableRow[])target;
+								
+							}else{
+								
+								rows = new TableRow[]{ (TableRow)target };
+							}
+							
+							final List<byte[]>	hashes = new ArrayList<byte[]>();
+							
+							for (int i=0;i<rows.length;i++){
+								
+								Download	download = (Download)rows[i].getDataSource();
+							
+								if ( download != null ){
+									
+									Torrent torrent = download.getTorrent();
+									
+									if ( torrent != null ){
+										
+										hashes.add( torrent.getHash());
+									}
+								}
+							}
+														
+							menu.removeAllChildItems();
+							
+							boolean enabled = hashes.size() > 0;
+							
+							if ( enabled ){
+							
+								Subscription[] subs = subs_man.getSubscriptions( true );
+								
+								boolean	incomplete = ((TableContextMenuItem)menu).getTableID() == TableManager.TABLE_MYTORRENTS_INCOMPLETE;
+								
+								TableContextMenuItem parent = incomplete?menu_item_itorrents:menu_item_ctorrents;
+																
+								for (int i=0;i<subs.length;i++){
+									
+									final Subscription	sub = subs[i];
+									
+									TableContextMenuItem item =
+										table_manager.addContextMenuItem(
+											parent,
+											"!" + sub.getName() + "!");
+									
+									item.addListener(
+										new MenuItemListener()
+										{
+											public void 
+											selected(
+												MenuItem 	menu,
+												Object 		target ) 
+											{
+												for (int i=0;i<hashes.size();i++){
+													
+													sub.addAssociation( hashes.get(i));
+												}
+											}
+										});
+								}
+							}
+							
+							menu.setEnabled( enabled );
+						}
+					};
+					
+				menu_item_itorrents.addFillListener( menu_fill_listener );
+				menu_item_ctorrents.addFillListener( menu_fill_listener );		
+			}
+		}
+	
+		createSubsColumns( table_manager );
+
+		ui_manager = default_pi.getUIManager();
+
+		ui_manager.addUIListener(
+				new UIManagerListener()
+				{
+					public void
+					UIAttached(
+						UIInstance		instance )
+					{
+						if (!( instance instanceof UISWTInstance )){
+							return;
+
+						}
+						
+						swt = (UISWTInstance)instance;
+						
+						uiQuickInit();
+
+        		Utilities utilities = default_pi.getUtilities();
+        		
+        		final DelayedTask dt = utilities.createDelayedTask(new Runnable()
+        			{
+        				public void 
+        				run() 
+        				{
+        					Utils.execSWTThread(new AERunnable() {
+									
+										public void 
+										runSupport() 
+										{
+       								delayedInit();
+        						}
+        					});
+        				}
+        			});
+        			
+        			dt.queue();		
+					}
+
+					public void UIDetached(UIInstance instance) {
+					}
+				});
+	}
+	
+	void uiQuickInit() {
+		
+		final MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+		
+		if ( mdi == null ){
+			
+				// closing down
+			
+			return;
+		}
+
+		icon_rss_small			= loadGraphic( swt, "subscription_icon.png" );
+		icon_rss_big			= icon_rss_small;
+
+		icon_rss_all_add_small	= loadGraphic( swt, "subscription_icon_inactive.png" );
+		icon_rss_all_add_big	= icon_rss_all_add_small;
+		
+		icon_rss_some_add_small	= icon_rss_all_add_small;
+		icon_rss_some_add_big	= icon_rss_some_add_small;
+		
+		mdi.registerEntry(MultipleDocumentInterface.SIDEBAR_SECTION_SUBSCRIPTIONS,
+				new MdiEntryCreationListener() {
+					public MdiEntry createMDiEntry(String id) {
+						setupSideBar( swt );
+						return mdiEntryOverview;
+					}
+				});
+		
+		mdi.registerEntry("Subscription_.*", new MdiEntryCreationListener2() {
+			// @see com.aelitis.azureus.ui.mdi.MdiEntryCreationListener2#createMDiEntry(com.aelitis.azureus.ui.mdi.MultipleDocumentInterface, java.lang.String, java.lang.Object, java.util.Map)
+			public MdiEntry createMDiEntry(MultipleDocumentInterface mdi, String id,
+					Object datasource, Map<?, ?> params) {
+				Subscription sub = null;
+				if (datasource instanceof Subscription) {
+					sub = (Subscription) datasource;
+				} else if (id.length() > 13) {
+					String publicKey = id.substring(13);
+					byte[] decodedPublicKey = ByteFormatter.decodeString(publicKey);
+					SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
+
+					Subscription[] subscriptions = subs_man.getSubscriptions();
+					for (Subscription subscription : subscriptions) {
+						if (Arrays.equals(subscription.getPublicKey(), decodedPublicKey)) {
+							sub = subscription;
+							break;
+						}
+					}
+				}
+				// hack to hide useless entries
+				if (sub != null && sub.isSearchTemplate()) {
+					return null;
+				}
+				return sub == null ? null : createSubscriptionMdiEntry(sub);
+			}
+		});
+
+		SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
+		subs_man.addListener(
+			new SubscriptionManagerListener()
+			{
+				public void 
+				subscriptionAdded(
+					Subscription 		subscription ) 
+				{
+				}
+	
+				public void
+				subscriptionChanged(
+					Subscription		sub )
+				{
+					
+					changeSubscription( sub );
+				}
+				
+				public void 
+				subscriptionSelected(
+					Subscription sub )
+				{	
+					
+					String key = "Subscription_" + ByteFormatter.encodeString(sub.getPublicKey());
+					MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+					if ( mdi != null ){
+						mdi.showEntryByID(key, sub);
+					}
+				}
+				
+				public void 
+				subscriptionRemoved(
+					Subscription 		subscription ) 
+				{
+					removeSubscription( subscription );
+				}
+				
+				public void
+				associationsChanged(
+					byte[]		association_hash )
+				{ 
+				}
+				
+				public void
+				subscriptionRequested(
+					URL					url )
+				{	
+				}
+			});
+	}
+
+	void delayedInit() {
+		if (swt == null) {
+			return;
+		}
+		
+		SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
+		subs_man.addListener(
+			new SubscriptionManagerListener()
+			{
+				public void 
+				subscriptionAdded(
+					Subscription subscription ) 
+				{
+				}
+				
+				public void
+				subscriptionChanged(
+					Subscription		subscription )
+				{
+				}
+				
+				public void 
+				subscriptionSelected(
+					Subscription subscription )
+				{		
+				}
+				
+				public void 
+				subscriptionRemoved(
+					Subscription subscription ) 
+				{
+				}
+				
+				public void 
+				associationsChanged(
+					byte[] hash )
+				{
+					refreshColumns();
+				}
+				
+				public void
+				subscriptionRequested(
+					final URL					url )
+				{
+					Utils.execSWTThread(
+						new AERunnable() 
+						{
+							public void
+							runSupport()
+							{
+								new SubscriptionWizard( url );
+							}
+						});
+				}
+			});	
+		
+		createConfigModel();
+	}
+
+	private void createConfigModel() {
+		final SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
+
+		BasicPluginConfigModel configModel = ui_manager.createBasicPluginConfigModel(
+				ConfigSection.SECTION_ROOT, CONFIG_SECTION_ID);
+
+		final IntParameter max_results = 
+			configModel.addIntParameter2( 
+				"subscriptions.config.maxresults", 
+				"subscriptions.config.maxresults", 
+				subs_man.getMaxNonDeletedResults());
+			
+			// search
+		
+		final BooleanParameter search_enable = 
+			configModel.addBooleanParameter2( 
+				"subscriptions.search.enable", "subscriptions.search.enable",
+				subs_man.isSearchEnabled());
+		
+		search_enable.addListener(
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					Parameter param) 
+				{
+					subs_man.setSearchEnabled( search_enable.getValue());
+				}
+			});
+		
+			// download subs enable
+		
+		final BooleanParameter download_subs_enable = 
+			configModel.addBooleanParameter2( 
+				"subscriptions.dl_subs.enable", "subscriptions.dl_subs.enable",
+				subs_man.isSubsDownloadEnabled());
+		
+		download_subs_enable.addListener(
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					Parameter param) 
+				{
+					subs_man.setSubsDownloadEnabled( download_subs_enable.getValue());
+				}
+			});
+		
+		
+			// rate limits
+		
+		final StringParameter rate_limits = configModel.addStringParameter2(
+				"subscriptions.config.ratelimits",
+				"subscriptions.config.ratelimits",
+				subs_man.getRateLimits());
+		
+		rate_limits.addListener(
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					Parameter param )
+				{
+					subs_man.setRateLimits(rate_limits.getValue());
+				}
+			});
+
+			// auto
+		
+		final BooleanParameter auto_start = configModel.addBooleanParameter2(
+				"subscriptions.config.autostartdls",
+				"subscriptions.config.autostartdls",
+				subs_man.getAutoStartDownloads());
+		
+		auto_start.addListener(
+			new ParameterListener()
+			{
+				public void 
+				parameterChanged(
+					Parameter param )
+				{
+					subs_man.setAutoStartDownloads( auto_start.getValue());
+				}
+			});
+		
+		final IntParameter min_auto_start_size = 
+			configModel.addIntParameter2( 
+				"subscriptions.config.autostart.min", 
+				"subscriptions.config.autostart.min", 
+				subs_man.getAutoStartMinMB());
+
+		final IntParameter max_auto_start_size = 
+			configModel.addIntParameter2( 
+				"subscriptions.config.autostart.max", 
+				"subscriptions.config.autostart.max", 
+				subs_man.getAutoStartMaxMB());
+
+		auto_start.addEnabledOnSelection( min_auto_start_size );
+		auto_start.addEnabledOnSelection( max_auto_start_size );
+		
+		configModel.createGroup( 
+			"subscriptions.config.auto", 
+			new Parameter[]{
+					auto_start, 
+					min_auto_start_size,
+					max_auto_start_size,
+			});
+		
+			// int param fires intermediate events so we have to rely on the save :(
+		
+		default_pi.getPluginconfig().addListener(
+			new PluginConfigListener()
+			{
+				public void 
+				configSaved() 
+				{
+					subs_man.setMaxNonDeletedResults(max_results.getValue());
+					subs_man.setAutoStartMinMB(min_auto_start_size.getValue());
+					subs_man.setAutoStartMaxMB(max_auto_start_size.getValue());
+				}
+			});
+
+		
+			// 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,
+			});
+	}
+
+	private void 
+	createSubsColumns(
+		TableManager table_manager )
+	{
+		final TableCellRefreshListener	subs_refresh_listener = 
+			new TableCellRefreshListener()
+			{
+				public void 
+				refresh(
+					TableCell _cell )
+				{
+					TableCellSWT cell = (TableCellSWT)_cell;
+					
+					SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
+					
+					Download	dl = (Download)cell.getDataSource();
+					
+					if ( dl == null ){
+						
+						return;
+					}
+					
+					Torrent	torrent = dl.getTorrent();
+					
+					if ( torrent != null ){
+						
+						Subscription[] subs = subs_man.getKnownSubscriptions( torrent.getHash());
+														
+						int	num_subscribed		= 0;
+						int	num_unsubscribed	= 0;
+						
+						for (int i=0;i<subs.length;i++){
+							
+							if ( subs[i].isSubscribed()){
+																
+								num_subscribed++;
+								
+							}else{
+								
+								num_unsubscribed++;
+							}
+						}
+						
+						Graphic graphic;
+						String	tooltip;
+						
+						int height = cell.getHeight();
+						
+						int	sort_order = 0;
+						
+						if ( subs.length == 0 ){
+							
+							graphic = null;
+							tooltip	= null;
+							
+						}else{
+						
+							if ( num_subscribed == subs.length ){
+								
+								graphic = height >= 22?icon_rss_all_add_big:icon_rss_all_add_small;
+								
+								tooltip = MessageText.getString( "subscript.all.subscribed" );
+								
+							}else if ( num_subscribed > 0 ){
+								
+								graphic = height >= 22?icon_rss_some_add_big:icon_rss_some_add_small;
+
+								tooltip = MessageText.getString( "subscript.some.subscribed" );
+
+								sort_order	= 10000;
+								
+							}else{
+								
+								graphic = height >= 22?icon_rss_big:icon_rss_small;
+								
+								tooltip = MessageText.getString( "subscript.none.subscribed" );
+								
+								sort_order	= 1000000;
+							}
+						}
+						
+						sort_order += 1000*num_unsubscribed + num_subscribed;
+						
+						cell.setMarginHeight(0);
+						cell.setGraphic( graphic );
+						cell.setToolTip( tooltip );
+						
+						cell.setSortValue( sort_order );
+						
+						cell.setCursorID( graphic==null?SWT.CURSOR_ARROW:SWT.CURSOR_HAND );
+
+					}else{
+						
+						cell.setCursorID( SWT.CURSOR_ARROW );
+						
+						cell.setSortValue( 0 );
+					}
+				}
+			};
+			
+		final TableCellMouseListener	subs_mouse_listener = 
+			new TableCellMouseListener()
+			{
+				public void 
+				cellMouseTrigger(
+					TableCellMouseEvent event )
+				{
+					if ( event.eventType == TableCellMouseEvent.EVENT_MOUSEDOWN ){
+						
+						
+						TableCell cell = event.cell;
+						
+						Download	dl = (Download)cell.getDataSource();
+						
+						Torrent	torrent = dl.getTorrent();
+						
+						if ( torrent != null ){
+							
+							SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
+							Subscription[] subs = subs_man.getKnownSubscriptions( torrent.getHash());
+							
+							if ( subs.length > 0 ){
+								
+								event.skipCoreFunctionality	= true;
+
+								new SubscriptionWizard(PluginCoreUtils.unwrap(dl));
+								
+								COConfigurationManager.setParameter( "subscriptions.wizard.shown", true );
+
+								refreshTitles( mdiEntryOverview );
+								
+								//new SubscriptionListWindow(PluginCoreUtils.unwrap(dl),true);
+							}
+						}
+					}
+				}
+			};
+			
+		table_manager.registerColumn(
+			Download.class, 
+			"azsubs.ui.column.subs", 
+			new TableColumnCreationListener() 
+			{
+				public void tableColumnCreated(TableColumn result) {
+					result.setAlignment(TableColumn.ALIGN_CENTER);
+					result.setPosition(TableColumn.POSITION_LAST);
+					result.setWidth(32);
+					result.setRefreshInterval(TableColumn.INTERVAL_INVALID_ONLY);
+					result.setType(TableColumn.TYPE_GRAPHIC);
+				
+					result.addCellRefreshListener( subs_refresh_listener );
+					result.addCellMouseListener( subs_mouse_listener );
+					result.setIconReference("image.subscription.column", true);
+					
+					synchronized (columns) {
+						columns.add(result);
+					}
+				}
+			});
+		
+		final TableCellRefreshListener	link_refresh_listener = 
+			new TableCellRefreshListener()
+			{
+				public void 
+				refresh(
+					TableCell _cell )
+				{
+					TableCellSWT cell = (TableCellSWT)_cell;
+					
+					SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
+					
+					Download	dl = (Download)cell.getDataSource();
+					
+					if ( dl == null ){
+						
+						return;
+					}
+					
+					String	str 		= "";
+					
+					Torrent	torrent = dl.getTorrent();
+					
+					if ( torrent != null ){
+						
+						byte[]	hash = torrent.getHash();
+						
+						Subscription[] subs = subs_man.getKnownSubscriptions( hash );
+														
+						for (int i=0;i<subs.length;i++){
+							
+							Subscription sub = subs[i];
+							
+							if ( sub.hasAssociation( hash )){
+								
+								str += (str.length()==0?"":"; ") + sub.getName();
+							}
+						}
+					}
+					
+					cell.setCursorID( str.length() > 0?SWT.CURSOR_HAND:SWT.CURSOR_ARROW );
+					
+					cell.setText( str );
+				}
+			};
+		
+			final TableCellMouseListener	link_mouse_listener = 
+				new TableCellMouseListener()
+				{
+					public void 
+					cellMouseTrigger(
+						TableCellMouseEvent event )
+					{
+						if ( event.eventType == TableCellMouseEvent.EVENT_MOUSEDOWN ){
+										
+							TableCell cell = event.cell;
+							
+							Download	dl = (Download)cell.getDataSource();
+							
+							Torrent	torrent = dl.getTorrent();
+
+							SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
+
+							if ( torrent != null ){
+								
+								byte[]	hash = torrent.getHash();
+								
+								Subscription[] subs = subs_man.getKnownSubscriptions( hash );
+																
+								for (int i=0;i<subs.length;i++){
+									
+									Subscription sub = subs[i];
+									
+									if ( sub.hasAssociation( hash )){
+										
+										String key = "Subscription_" + ByteFormatter.encodeString(sub.getPublicKey());
+										MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+										if ( mdi != null ){
+											mdi.showEntryByID(key, sub);
+										}
+										break;
+									}
+								}
+							}
+						}
+					}
+				};
+				
+		table_manager.registerColumn(
+				Download.class, 
+				"azsubs.ui.column.subs_link", 
+				new TableColumnCreationListener() 
+				{
+					public void tableColumnCreated(TableColumn result) {
+						result.setAlignment(TableColumn.ALIGN_LEAD);
+						result.setPosition(TableColumn.POSITION_INVISIBLE);
+						result.setWidth(85);
+						result.setRefreshInterval(TableColumn.INTERVAL_INVALID_ONLY);
+						result.setType(TableColumn.TYPE_TEXT_ONLY);
+					
+						result.addCellRefreshListener( link_refresh_listener );
+						result.addCellMouseListener( link_mouse_listener );
+						result.setMinimumRequiredUserMode( Parameter.MODE_INTERMEDIATE );
+						
+						synchronized (columns) {
+							columns.add(result);
+						}
+					}
+				});
+	}
+	
+	protected void
+	setupSideBar(
+		final UISWTInstance		swt_ui )		
+	{
+		boolean uiClassic = COConfigurationManager.getStringParameter("ui").equals("az2");
+
+		MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
+		
+		if (mdi == null) {
+			return;
+		}
+
+		mdiEntryOverview = mdi.createEntryFromEventListener(
+				MultipleDocumentInterface.SIDEBAR_HEADER_DISCOVERY, 
+				new UISWTViewEventListenerHolder(
+						MultipleDocumentInterface.SIDEBAR_SECTION_SUBSCRIPTIONS,
+						SubscriptionsView.class, null, null),
+				MultipleDocumentInterface.SIDEBAR_SECTION_SUBSCRIPTIONS, false, null, null );
+
+		if (mdiEntryOverview == null) {
+			return;
+		}
+		
+		mdiEntryOverview.setDefaultExpanded(true);
+			
+		synchronized( this ){
+				// seen double add buttons in the sidebar, not sure of cause but it would imply we are coming through here
+				// twice which can't be good - protect against that
+			
+			if( sidebar_setup_done ){
+				
+				return;
+			}
+			
+			sidebar_setup_done = true;
+		}
+		
+		mdiEntryOverview.setImageLeftID("image.sidebar.subscriptions");
+
+		setupHeader(mdi, mdiEntryOverview);
+
+//		MdiEntry headerEntry = mdi.getEntry(MultipleDocumentInterface.SIDEBAR_HEADER_DISCOVERY);
+//		if (headerEntry != null) {
+//			setupHeader(mdi, headerEntry);
+//		}
+
+		String parentID = "sidebar." + MultipleDocumentInterface.SIDEBAR_HEADER_DISCOVERY;
+
+		MenuManager menu_manager = ui_manager.getMenuManager();
+		
+		MenuItem mi = menu_manager.addMenuItem( parentID, "MainWindow.menu.view.configuration" );
+		
+		mi.addListener( 
+				new MenuItemListener() 
+				{
+					public void 
+					selected(
+						MenuItem menu, Object target ) 
+					{
+				      	 UIFunctions uif = UIFunctionsManager.getUIFunctions();
+				      	 
+				      	 if ( uif != null ){
+				      		 
+				      		 uif.getMDI().showEntryByID(
+				      				 MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG,
+				      				 CONFIG_SECTION_ID);
+				      	 }
+					}
+				});
+	}
+
+	private void setupHeader(MultipleDocumentInterface mdi,
+			final MdiEntry headerEntry) {
+
+		MdiEntryVitalityImage addSub = headerEntry.addVitalityImage("image.sidebar.subs.add");
+
+		if (addSub != null) {
+			addSub.setToolTip(MessageText.getString("subscriptions.add.tooltip"));
+
+			addSub.addListener(new MdiEntryVitalityImageListener() {
+				public void mdiEntryVitalityImage_clicked(int x, int y) {
+					new SubscriptionWizard();
+					
+					COConfigurationManager.setParameter( "subscriptions.wizard.shown", true );
+
+					refreshTitles( mdiEntryOverview );
+				}
+			});
+		}
+
+		final MdiEntryVitalityImage warnSub = headerEntry.addVitalityImage(ALERT_IMAGE_ID);
+		if (warnSub != null) {
+			warnSub.setVisible(false);
+		}
+
+		final MdiEntryVitalityImage infoSub = headerEntry.addVitalityImage(INFO_IMAGE_ID);
+		if (infoSub != null) {
+			infoSub.setVisible(false);
+		}
+
+		
+		headerEntry.setViewTitleInfo(
+			new ViewTitleInfo() 
+			{
+				private long	last_avail_calc = -1;
+				private int		last_avail;
+				
+				public Object 
+				getTitleInfoProperty(
+					int propertyID) 
+				{
+					Object result = null;
+	
+					// COConfigurationManager.setParameter( "subscriptions.wizard.shown", false );
+					
+					if (propertyID == TITLE_INDICATOR_TEXT) {
+	
+						boolean expanded = headerEntry.isExpanded();
+	
+						SubscriptionManager subs_man = SubscriptionManagerFactory.getSingleton();
+						
+						Subscription[] subs = subs_man.getSubscriptions(true);
+						
+						if ( expanded ){
+	
+							if (warnSub != null) {
+								warnSub.setVisible(false);
+							}
+	
+						}else{
+	
+							int total = 0;
+							
+							boolean warn = false;
+	
+							String error_str = "";
+	
+							for (Subscription s : subs) {
+	
+								SubscriptionHistory history = s.getHistory();
+	
+								total += history.getNumUnread();
+	
+								String last_error = history.getLastError();
+	
+								if (last_error != null && last_error.length() > 0) {
+	
+									boolean auth_fail = history.isAuthFail();
+	
+									if (history.getConsecFails() >= 3 || auth_fail) {
+	
+										warn = true;
+	
+										if (error_str.length() > 128) {
+	
+											if (!error_str.endsWith(", ...")) {
+	
+												error_str += ", ...";
+											}
+										} else {
+	
+											error_str += (error_str.length() == 0 ? "" : ", ")
+													+ last_error;
+										}
+									}
+								}
+							}
+	
+							if (warnSub != null) {
+								warnSub.setVisible(warn);
+								warnSub.setToolTip(error_str);
+							}
+							
+							if (total > 0) {
+	
+								result = String.valueOf( total );
+							}
+						}
+						
+						if (infoSub != null) {
+  						if ( subs.length == 0 && !COConfigurationManager.getBooleanParameter( "subscriptions.wizard.shown", false )){
+  							
+  							long now = SystemTime.getMonotonousTime();
+  							
+  							if ( 	last_avail_calc == -1 ||
+  									now - last_avail_calc > 60*1000 ){
+  								
+  								last_avail = subs_man.getKnownSubscriptionCount();
+  								
+  								last_avail_calc = now;
+  							}
+  							
+  							if ( last_avail > 0 ){
+  								
+  								infoSub.setVisible( true );
+  								
+  								infoSub.setToolTip( 
+  									MessageText.getString(
+  										"subscriptions.info.avail",
+  										new String[]{
+  											String.valueOf( last_avail )
+  										}));
+  							}
+  						}else{
+  							
+  							infoSub.setVisible( false );
+  						}
+						}
+					}
+	
+					return( result );
+				}
+			});
+	}
+
+	protected void
+	changeSubscription(
+		final Subscription	subs )
+	{
+		refreshTitles( mdiEntryOverview );
+
+		
+		if ( subs.isSubscribed()){
+			String key = "Subscription_" + ByteFormatter.encodeString(subs.getPublicKey());
+			MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+			if ( mdi != null ){
+				mdi.loadEntryByID(key, true, true, subs);
+			}
+
+		} else {
+			
+			removeSubscription( subs);
+		}
+	}
+	
+	
+	private MdiEntry createSubscriptionMdiEntry(Subscription subs) {
+		
+		if (!subs.isSubscribed()) {
+			// user may have deleted subscrtipion, but our register is staill there
+			return null;
+		}
+		
+		MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
+		
+		if ( mdi == null ){
+			
+				// closing down
+		
+			return( null );
+		}
+	
+		final String key = "Subscription_" + ByteFormatter.encodeString(subs.getPublicKey());
+		
+		MdiEntry entry = mdi.createEntryFromEventListener(
+				MultipleDocumentInterface.SIDEBAR_SECTION_SUBSCRIPTIONS,
+				new UISWTViewEventListenerHolder(key, SubscriptionView.class, subs, null),
+				key, true, subs, null);
+
+		// This sets up the entry (menu, etc)
+		SubscriptionMDIEntry entryInfo = new SubscriptionMDIEntry(subs, entry);
+		subs.setUserData(SUB_ENTRYINFO_KEY, entryInfo);
+
+		return entry;
+	}
+	
+	protected void
+	refreshTitles(
+		MdiEntry		entry )
+	{
+		MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+		
+		if ( mdi == null ){
+
+			return;
+		}
+		
+		while( entry != null ){
+	
+			ViewTitleInfoManager.refreshTitleInfo(entry.getViewTitleInfo());
+
+			String key = entry.getParentID();
+			
+			if ( key == null ){
+				
+				return;
+			}
+			
+			entry = mdi.getEntry( key );
+		}
+	}
+
+	protected void
+	removeSubscription(
+		final Subscription	subs )
+	{
+		synchronized( this ){
+
+			String key = "Subscription_" + ByteFormatter.encodeString(subs.getPublicKey());
+			MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
+			
+			if  (mdi != null ){
+				
+				mdi.closeEntry(key);
+			}
+
+		}
+		
+		refreshColumns();
+	}
+	
+	protected void
+	refreshColumns()
+	{
+		synchronized (columns) {
+  		for ( Iterator<TableColumn> iter = columns.iterator(); iter.hasNext();){
+  			
+  			TableColumn column = iter.next();
+  			
+  			column.invalidateCells();
+  		}
+		}
+	}
+	
+	protected Graphic
+	loadGraphic(
+		UISWTInstance	swt,
+		String			name )
+	{
+		Image	image = swt.loadImage( "com/aelitis/azureus/ui/images/" + name );
+
+		Graphic graphic = swt.createGraphic(image );
+		
+		icon_list.add( graphic );
+		
+		return( graphic );
+	}
+	
+	protected interface
+	MenuCreator
+	{
+		public MenuItem
+		createMenu(
+			String 	resource_id );
+		
+		public void
+		refreshView();
+	}
+	
+	protected static void
+	createMenus(
+		final MenuManager		menu_manager,
+		final MenuCreator		menu_creator,
+		final Subscription		subs )
+	{
+		boolean is_search_template = subs.isSearchTemplate();
+		
+		if ( !is_search_template ){
+			
+			MenuItem menuItem = menu_creator.createMenu( "Subscription.menu.forcecheck" );
+			menuItem.setText(MessageText.getString("Subscription.menu.forcecheck"));
+			menuItem.addListener(new SubsMenuItemListener() {
+				public void selected( Subscription subs) {
+					try {
+						subs.getManager().getScheduler().downloadAsync( subs, true );
+					} catch (SubscriptionException e) {
+						Debug.out(e);
+					}
+				}
+			});
+			
+			menuItem = menu_creator.createMenu( "Subscription.menu.clearall");
+			menuItem.addListener(new SubsMenuItemListener() {
+				public void selected( Subscription subs) {
+					subs.getHistory().markAllResultsRead();
+					menu_creator.refreshView();
+				}
+			});
+			
+			menuItem = menu_creator.createMenu( "Subscription.menu.dirtyall");
+			menuItem.addListener(new SubsMenuItemListener() {
+				public void selected( Subscription subs) {
+					subs.getHistory().markAllResultsUnread();
+					menu_creator.refreshView();
+				}
+			});
+	
+			menuItem = menu_creator.createMenu( "Subscription.menu.deleteall");
+			menuItem.addListener(new SubsMenuItemListener() {
+				public void selected( Subscription subs) {
+					subs.getHistory().deleteAllResults();
+					menu_creator.refreshView();
+				}
+			});
+			
+			menuItem = menu_creator.createMenu( "Subscription.menu.reset");
+			menuItem.addListener(new SubsMenuItemListener() {
+				public void selected( Subscription subs) {
+					subs.getHistory().reset();
+					try{
+						subs.getEngine().reset();
+					}catch( Throwable e ){
+						Debug.printStackTrace(e);
+					}
+					try{
+						subs.getManager().getScheduler().downloadAsync(subs, true);
+						
+					}catch( Throwable e ){
+						
+						Debug.out(e);
+					}
+				}
+			});
+	
+			try{
+				Engine engine = subs.getEngine();
+					
+				if ( engine instanceof WebEngine ){
+					
+					if (((WebEngine)engine).isNeedsAuth()){
+						
+						menuItem = menu_creator.createMenu( "Subscription.menu.resetauth");
+						menuItem.addListener(new SubsMenuItemListener() {
+							public void selected( Subscription subs) {
+								try{
+									Engine engine = subs.getEngine();
+									
+									if ( engine instanceof WebEngine ){
+										
+										((WebEngine)engine).setCookies( null );
+									}
+								}catch( Throwable e ){
+									
+									Debug.printStackTrace(e);
+								}
+								
+								try{
+									subs.getManager().getScheduler().downloadAsync(subs, true);
+									
+								}catch( Throwable e ){
+									
+									Debug.out(e);
+								}
+							}
+						});
+						
+						menuItem = menu_creator.createMenu( "Subscription.menu.setcookies");
+						menuItem.addListener(new SubsMenuItemListener() {
+							public void selected( final Subscription subs) {
+								try{
+									Engine engine = subs.getEngine();
+									
+									if ( engine instanceof WebEngine ){
+										
+										final WebEngine we = (WebEngine)engine;
+										
+										UISWTInputReceiver entry = new SimpleTextEntryWindow();
+										
+										String[] req = we.getRequiredCookies();
+										
+										String	req_str = "";
+										
+										for ( String r:req ){
+											
+											req_str += (req_str.length()==0?"":";") + r + "=?";
+										}
+										entry.setPreenteredText( req_str, true );
+										entry.maintainWhitespace(false);
+										entry.allowEmptyInput( false );
+										entry.setTitle("general.enter.cookies");
+										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 ){
+									
+									Debug.printStackTrace(e);
+								}
+							}
+						});
+					}
+				}
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+			
+				// sep
+			
+			menu_creator.createMenu( "s1").setStyle( MenuItem.STYLE_SEPARATOR );
+
+				// category
+			
+			menuItem = menu_creator.createMenu( "MyTorrentsView.menu.setCategory");
+			menuItem.setStyle( MenuItem.STYLE_MENU );
+			
+			menuItem.addFillListener(
+				new MenuItemFillListener()
+				{
+					public void 
+					menuWillBeShown(
+						MenuItem 	menu, 
+						Object 		data ) 
+					{		
+						addCategorySubMenu( menu_manager, menu, subs );
+					}
+				});
+			
+				// tag
+			
+			menuItem = menu_creator.createMenu( "label.tag");
+			
+			menuItem.setStyle( MenuItem.STYLE_MENU );
+			
+			menuItem.addFillListener(
+				new MenuItemFillListener()
+				{
+					public void 
+					menuWillBeShown(
+						MenuItem 	menu, 
+						Object 		data ) 
+					{		
+						addTagSubMenu( menu_manager, menu, subs );
+					}
+				});
+			
+				// chat
+			
+			try{
+				Engine engine = subs.getEngine();
+							
+				if ( engine instanceof WebEngine ){
+					
+					WebEngine web_engine = (WebEngine)subs.getEngine();
+					
+					final String url = web_engine.getSearchUrl( true );
+					
+					menuItem = menu_creator.createMenu( "label.chat");
+					
+					MenuBuildUtils.addChatMenu(
+						menu_manager, 
+						menuItem,
+						new MenuBuildUtils.ChatKeyResolver() 
+						{
+							public String getChatKey(Object object) {
+								
+								return( "Subscription: " + url );
+							}
+						});
+				}
+			}catch( Throwable e ){
+				
+			}
+			
+			if ( subs.isUpdateable()){
+				
+				menuItem = menu_creator.createMenu( "MyTorrentsView.menu.rename");
+				menuItem.addListener(new SubsMenuItemListener() {
+					public void selected( final Subscription subs) {
+						UISWTInputReceiver entry = new SimpleTextEntryWindow();
+						entry.setPreenteredText(subs.getName(), false );
+						entry.maintainWhitespace(false);
+						entry.allowEmptyInput( false );
+						entry.setLocalisedTitle(MessageText.getString("label.rename",
+								new String[] {
+									subs.getName()
+								}));
+						entry.prompt(new UIInputReceiverListener() {
+							public void UIInputReceiverClosed(UIInputReceiver entry) {
+								if (!entry.hasSubmittedInput()){
+									
+									return;
+								}
+								
+								String input = entry.getSubmittedInput().trim();
+								
+								if ( input.length() > 0 ){
+									
+									try{
+										subs.setName( input );
+										
+									}catch( Throwable e ){
+										
+										Debug.printStackTrace(e);
+									}
+								}
+							}
+						});
+					}
+				});
+			}
+			
+			menuItem = menu_creator.createMenu( "Subscription.menu.upgrade");
+			menuItem.addListener(new SubsMenuItemListener() {
+				public void selected( Subscription subs) {
+					subs.resetHighestVersion();
+				}
+			});
+				
+			menuItem.addFillListener(
+				new MenuItemFillListener()
+				{
+					public void 
+					menuWillBeShown(
+						MenuItem 	menu, 
+						Object 		data ) 
+					{									
+						menu.setVisible( subs.getHighestVersion() > subs.getVersion());
+					}
+				});
+		}
+		
+		MenuItem menuItem = menu_creator.createMenu( "label.copy.uri.to.clip");
+		menuItem.addListener(new SubsMenuItemListener() {
+			public void selected( Subscription subs) {
+				ClipboardCopy.copyToClipBoard( subs.getURI());
+			}
+		});
+		
+		menuItem = menu_creator.createMenu( "Subscription.menu.export");
+		menuItem.addListener(new SubsMenuItemListener() {
+			public void selected( Subscription subs) {
+				export( subs );
+			}
+		});
+		
+			// sep
+		
+		menu_creator.createMenu( "s2").setStyle( MenuItem.STYLE_SEPARATOR );
+		
+		if ( !is_search_template ){
+				// change url
+			
+			try{
+				Engine engine = subs.getEngine();
+							
+				if ( engine instanceof WebEngine ){
+						
+					menuItem = menu_creator.createMenu( "menu.change.url");
+					menuItem.addListener(new SubsMenuItemListener() {
+						public void selected( final Subscription subs) {
+							UISWTInputReceiver entry = new SimpleTextEntryWindow();
+							
+							try{
+								WebEngine web_engine = (WebEngine)subs.getEngine();
+		
+								entry.setPreenteredText(web_engine.getSearchUrl( true ), false );
+								entry.maintainWhitespace(false);
+								entry.allowEmptyInput( false );
+								entry.setLocalisedTitle(MessageText.getString("change.url.msg.title",
+										new String[] {
+											subs.getName()
+										}));
+								entry.setMessage( "change.url.msg.desc" );
+								entry.prompt(new UIInputReceiverListener() {
+									public void UIInputReceiverClosed(UIInputReceiver entry) {
+										if (!entry.hasSubmittedInput()){
+											
+											return;
+										}
+										
+										String input = entry.getSubmittedInput().trim();
+										
+										if ( input.length() > 0 ){
+											
+											try{
+												WebEngine web_engine = (WebEngine)subs.getEngine();
+												
+												web_engine.setSearchUrl( input );
+												
+												subs.cloneWithNewEngine( web_engine );
+												
+											}catch( Throwable e ){
+												
+												Debug.out(e);
+											}
+										}
+									}
+								});
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}
+					});
+					
+				}
+			}catch( Throwable e ){
+				Debug.out( e );
+			}
+			
+				// public
+			
+			menuItem = menu_creator.createMenu( "subs.prop.is_public");
+			menuItem.setStyle( MenuItem.STYLE_CHECK );
+			
+			menuItem.addFillListener( new MenuItemFillListener(){
+				public void menuWillBeShown( MenuItem menu, Object data ){
+					menu.setData( subs.isPublic());
+				}});
+		
+			menuItem.addListener(new SubsMenuItemListener() {
+				public void selected( Subscription subs) {
+					try{
+						subs.setPublic( !subs.isPublic());
+					}catch( Throwable e ){
+						Debug.out(e);
+					}
+				}
+			});
+			
+			if ( subs.isAutoDownloadSupported()){
+				
+					// auto-dl
+				
+				menuItem = menu_creator.createMenu( "subs.prop.is_auto");
+				menuItem.setStyle( MenuItem.STYLE_CHECK );
+				
+				menuItem.addFillListener( new MenuItemFillListener(){
+					public void menuWillBeShown( MenuItem menu, Object data ){
+						menu.setData( subs.getHistory().isAutoDownload());
+					}});
+				
+				menuItem.addListener(new SubsMenuItemListener() {
+					public void selected( Subscription subs) {
+						try{
+							subs.getHistory().setAutoDownload(!subs.getHistory().isAutoDownload());
+						}catch( Throwable e ){
+							Debug.out(e);
+						}
+					}
+				});
+			}
+			
+				// refresh period
+				
+			menuItem = menu_creator.createMenu(  "subs.prop.update_period" );
+			
+			menuItem.addFillListener( new MenuItemFillListener(){
+				public void menuWillBeShown( MenuItem menu, Object data ){
+					int check_freq = subs.getHistory().getCheckFrequencyMins();
+					
+					String text = MessageText.getString( "subs.prop.update_period" );
+					
+					if ( check_freq!=Integer.MAX_VALUE ){
+						
+						text += " (" +  check_freq + " " + MessageText.getString( "ConfigView.text.minutes") + ")";
+					}
+					
+					menu.setText( text + "..." );
+				}});
+			
+			
+			menuItem.addListener(new SubsMenuItemListener() {
+				public void selected( final Subscription subs) {
+					UISWTInputReceiver entry = new SimpleTextEntryWindow();
+					entry.maintainWhitespace(false);
+					entry.allowEmptyInput( false );
+					
+					int check_freq = subs.getHistory().getCheckFrequencyMins();
+					
+					entry.setPreenteredText( check_freq==Integer.MAX_VALUE?"":String.valueOf( check_freq ), false );
+					
+					entry.maintainWhitespace(false);
+					
+					entry.allowEmptyInput( false );
+					
+					entry.setLocalisedTitle(MessageText.getString("subscriptions.enter.freq"));
+			
+					entry.prompt(new UIInputReceiverListener() {
+						public void UIInputReceiverClosed(UIInputReceiver entry) {
+							if (!entry.hasSubmittedInput()) {
+								return;
+							}
+							String input = entry.getSubmittedInput().trim();
+							
+							if ( input.length() > 0 ){
+								
+								try{
+									subs.getHistory().setCheckFrequencyMins( Integer.parseInt( input ));
+									
+								}catch( Throwable e ){
+									
+								}
+							}
+						}
+					});
+				}
+			});
+		
+				// rename
+			
+			menuItem = menu_creator.createMenu( "MyTorrentsView.menu.rename" );
+			menuItem.addListener(new SubsMenuItemListener() {
+				public void selected( final Subscription subs) {
+					UISWTInputReceiver entry = new SimpleTextEntryWindow();
+					entry.maintainWhitespace(false);
+					entry.allowEmptyInput( false );
+					
+					entry.setPreenteredText(subs.getName(), false );
+					
+					entry.maintainWhitespace(false);
+					
+					entry.allowEmptyInput( false );
+					
+					entry.setLocalisedTitle(MessageText.getString("label.rename",
+							new String[] {
+							subs.getName()
+					}));
+			
+					entry.prompt(new UIInputReceiverListener() {
+						public void UIInputReceiverClosed(UIInputReceiver entry) {
+							if (!entry.hasSubmittedInput()) {
+								return;
+							}
+							String input = entry.getSubmittedInput().trim();
+							
+							if ( input.length() > 0 ){
+								
+								subs.setLocalName( input );
+							}
+						}
+					});
+				}
+			});
+		}
+		
+		
+		menuItem = menu_creator.createMenu( "Subscription.menu.remove");
+		menuItem.addListener(new SubsMenuItemListener() {
+			public void selected( Subscription subs) {
+				removeWithConfirm( subs );
+			}
+		});
+		
+		menu_creator.createMenu( "s3").setStyle( MenuItem.STYLE_SEPARATOR );
+
+		menuItem = menu_creator.createMenu( "Subscription.menu.properties");
+		menuItem.addListener(new SubsMenuItemListener() {
+			public void selected( Subscription subs){
+				showProperties( subs );
+			}
+		});
+	}
+	
+	private static void 
+	addCategorySubMenu(
+		MenuManager				menu_manager,
+		MenuItem				menu,
+		final Subscription		subs )
+	{
+		menu.removeAllChildItems();
+
+		Category[] categories = CategoryManager.getCategories();
+		
+		Arrays.sort( categories );
+
+		MenuItem m;
+
+		if ( categories.length > 0 ){
+			
+			String	assigned_category = subs.getCategory();
+			
+			final Category uncat = CategoryManager.getCategory( Category.TYPE_UNCATEGORIZED );
+						
+			if ( uncat != null ){
+				
+				m = menu_manager.addMenuItem( menu, uncat.getName());
+				
+				m.setStyle( MenuItem.STYLE_RADIO );
+								
+				m.setData( new Boolean( assigned_category == null ));
+				
+				m.addListener(
+					new MenuItemListener() 
+					{
+						public void
+						selected(
+							MenuItem			menu,
+							Object 				target )
+						{
+							assignSelectedToCategory( subs, uncat );
+						}
+					});
+				
+
+				m = menu_manager.addMenuItem( menu, "sep1" );
+				
+				m.setStyle( MenuItem.STYLE_SEPARATOR );
+			}
+
+			for ( int i=0; i<categories.length; i++ ){
+				
+				final Category cat = categories[i];
+				
+				if ( cat.getType() == Category.TYPE_USER) {
+					
+					m = menu_manager.addMenuItem( menu, "!" + cat.getName() + "!" );
+					
+					m.setStyle( MenuItem.STYLE_RADIO );
+										
+					m.setData( new Boolean( assigned_category != null && assigned_category.equals( cat.getName())));
+					
+					m.addListener(
+						new MenuItemListener() 
+						{
+							public void
+							selected(
+								MenuItem			menu,
+								Object 				target )
+							{
+								assignSelectedToCategory( subs, cat );
+							}
+						});
+				}
+			}
+
+			m = menu_manager.addMenuItem( menu, "sep2" );
+			
+			m.setStyle( MenuItem.STYLE_SEPARATOR );
+		}
+
+		m = menu_manager.addMenuItem( menu, "MyTorrentsView.menu.setCategory.add" );
+		
+		m.addListener(
+				new MenuItemListener() 
+				{
+					public void
+					selected(
+						MenuItem			menu,
+						Object 				target )
+					{
+						addCategory( subs );
+					}
+				});
+
+	}
+
+	private static void 
+	addCategory(
+		Subscription			subs )
+	{
+		CategoryAdderWindow adderWindow = new CategoryAdderWindow(Display.getDefault());
+		
+		Category newCategory = adderWindow.getNewCategory();
+		
+		if ( newCategory != null ){
+		
+			assignSelectedToCategory( subs, newCategory );
+		}
+	}
+
+	private static void 
+	assignSelectedToCategory(
+		Subscription		subs,
+		Category 			category )
+	{
+		if ( category.getType() == Category.TYPE_UNCATEGORIZED ){
+		
+			subs.setCategory( null );
+			
+		}else{
+			
+			subs.setCategory( category.getName());
+		}
+	}
+
+	private static void 
+	addTagSubMenu(
+		MenuManager				menu_manager,
+		MenuItem				menu,
+		final Subscription		subs )
+	{
+		menu.removeAllChildItems();
+
+		TagManager tm = TagManagerFactory.getTagManager();
+		
+		List<Tag> tags = tm.getTagType( TagType.TT_DOWNLOAD_MANUAL ).getTags();
+		
+		tags = TagUIUtils.sortTags( tags );
+					
+		long	tag_id = subs.getTagID();
+			
+		Tag assigned_tag = tm.lookupTagByUID( tag_id );
+		
+		MenuItem m = menu_manager.addMenuItem( menu, "label.no.tag" );
+				
+		m.setStyle( MenuItem.STYLE_RADIO );
+							
+		m.setData( new Boolean( assigned_tag == null ));
+				
+		m.addListener(
+			new MenuItemListener() 
+			{
+				public void
+				selected(
+					MenuItem			menu,
+					Object 				target )
+				{
+					subs.setTagID( -1 );
+				}
+			});
+				
+
+		m = menu_manager.addMenuItem( menu, "sep1" );
+				
+		m.setStyle( MenuItem.STYLE_SEPARATOR );
+	
+		
+		List<String>	menu_names 		= new ArrayList<String>();
+		Map<String,Tag>	menu_name_map 	= new IdentityHashMap<String, Tag>();
+
+		for ( Tag t: tags ){
+			
+			if ( !t.isTagAuto()){
+				
+				String name = t.getTagName( true );
+				
+				menu_names.add( name );
+				menu_name_map.put( name, t );
+			}
+		}
+			
+		List<Object>	menu_structure = MenuBuildUtils.splitLongMenuListIntoHierarchy( menu_names, TagUIUtils.MAX_TOP_LEVEL_TAGS_IN_MENU );
+		
+		for ( Object obj: menu_structure ){
+
+			List<Tag>	bucket_tags = new ArrayList<Tag>();
+			
+			MenuItem parent_menu;
+			
+			if ( obj instanceof String ){
+				
+				parent_menu = menu;
+				
+				bucket_tags.add( menu_name_map.get((String)obj));
+				
+			}else{
+				
+				Object[]	entry = (Object[])obj;
+				
+				List<String>	tag_names = (List<String>)entry[1];
+				
+				boolean	has_selected = false;
+				
+				for ( String name: tag_names ){
+					
+					Tag tag = menu_name_map.get( name );
+					
+					bucket_tags.add( tag );
+					
+					if ( assigned_tag == tag ){
+						
+						has_selected = true;
+					}
+				}
+				
+				parent_menu = menu_manager.addMenuItem (menu, "!" + (String)entry[0] + (has_selected?" (*)":"") + "!" );
+				
+				parent_menu.setStyle( MenuItem.STYLE_MENU );
+			}
+			
+			for ( final Tag tag: bucket_tags ){
+			
+				m = menu_manager.addMenuItem( parent_menu, tag.getTagName( false ));
+						
+				m.setStyle( MenuItem.STYLE_RADIO );
+											
+				m.setData( new Boolean( assigned_tag == tag ));
+						
+				m.addListener(
+					new MenuItemListener() 
+					{
+						public void
+						selected(
+							MenuItem			menu,
+							Object 				target )
+						{
+							subs.setTagID( tag.getTagUID());
+						}
+					});
+			}
+		}
+		
+		m = menu_manager.addMenuItem( menu, "sep2" );
+			
+		m.setStyle( MenuItem.STYLE_SEPARATOR );
+
+		m = menu_manager.addMenuItem( menu, "label.add.tag" );
+		
+		m.addListener(
+			new MenuItemListener() 
+			{
+				public void
+				selected(
+					MenuItem			menu,
+					Object 				target )
+				{
+					addTag( subs );
+				}
+			});
+	}
+
+	private static void 
+	addTag(
+		final Subscription			subs )
+	{
+		TagUIUtilsV3.showCreateTagDialog(new UIFunctions.TagReturner() {
+			public void returnedTags(Tag[] tags) {
+				if ( tags != null ){
+					for (Tag new_tag : tags) {
+						subs.setTagID( new_tag.getTagUID());
+					}
+				}
+			}
+		});
+	}
+	
+	
+	protected static void 
+	export(
+		final Subscription			subs )
+	{
+		Utils.execSWTThread(
+			new AERunnable() 
+			{
+				public void 
+				runSupport()
+				{
+					FileDialog dialog = 
+						new FileDialog( Utils.findAnyShell(), SWT.SYSTEM_MODAL | SWT.SAVE );
+					
+					dialog.setFilterPath( TorrentOpener.getFilterPathData() );
+											
+					dialog.setText(MessageText.getString("subscript.export.select.template.file"));
+					
+					dialog.setFilterExtensions(new String[] {
+							"*.vuze",
+							"*.vuz",
+							Constants.FILE_WILDCARD
+						});
+					dialog.setFilterNames(new String[] {
+							"*.vuze",
+							"*.vuz",
+							Constants.FILE_WILDCARD
+						});
+					
+					String path = TorrentOpener.setFilterPathData( dialog.open());
+
+					if ( path != null ){
+						
+						String lc = path.toLowerCase();
+						
+						if ( !lc.endsWith( ".vuze" ) && !lc.endsWith( ".vuz" )){
+							
+							path += ".vuze";
+						}
+						
+						try{
+							VuzeFile vf = subs.getVuzeFile();
+							
+							vf.write( new File( path ));
+							
+
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+					}
+				}
+			});
+	}
+
+	protected static void
+	removeWithConfirm( 
+		final Subscription		subs )
+	{
+		MessageBoxShell mb = 
+			new MessageBoxShell(
+				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 );
+		
+		mb.open(new UserPrompterResultListener() {
+			public void prompterClosed(int result) {
+				if (result == 0) {
+					subs.setSubscribed( false );
+				}
+			}
+		});
+	}
+	
+	protected static void
+	showProperties(
+		Subscription			subs )
+	{
+		SubscriptionHistory history = subs.getHistory();
+		
+		SimpleDateFormat df = new SimpleDateFormat();
+		
+		String last_error = history.getLastError();
+		
+		if ( last_error == null ){
+			last_error = "";
+		}
+		
+		String	engine_str;
+		String	auth_str	= String.valueOf(false);
+		
+		try{
+			Engine engine = subs.getEngine();
+			
+			engine_str = engine.getNameEx();
+			
+			if ( engine instanceof WebEngine ){
+			
+				WebEngine web_engine = (WebEngine)engine;
+				
+				if ( web_engine.isNeedsAuth()){
+					
+					auth_str = String.valueOf(true) + ": cookies=" + toString( web_engine.getRequiredCookies());
+				}
+			}
+			
+			engine_str +=  ", eid=" + engine.getId();
+			
+		}catch( Throwable e ){
+			
+			engine_str 	= "Unknown";
+			auth_str	= "";
+		}
+		
+		String[] keys = {
+				"subs.prop.enabled",
+				"subs.prop.is_public",
+				"subs.prop.is_auto",
+				"subs.prop.is_auto_ok",
+				"subs.prop.update_period",
+				"subs.prop.last_scan",
+				"subs.prop.last_result",
+				"subs.prop.next_scan",
+				"subs.prop.last_error",
+				"subs.prop.num_read",
+				"subs.prop.num_unread",
+				"subs.prop.assoc",
+				"subs.prop.version",
+				"subs.prop.high_version",
+				"subscriptions.listwindow.popularity",
+				"subs.prop.template",
+				"subs.prop.auth",
+				"TableColumn.header.category",
+				"TableColumn.header.tag.name",
+			};
+		
+		String	category_str;
+		
+		String category = subs.getCategory();
+		
+		if ( category == null ){
+			
+			category_str = MessageText.getString( "Categories.uncategorized" );
+			
+		}else{
+			
+			category_str = category;
+		}
+				
+		Tag tag = TagManagerFactory.getTagManager().lookupTagByUID( subs.getTagID() );
+		
+		String tag_str = tag==null?"":tag.getTagName( true );
+		
+		int	 check_freq			= history.getCheckFrequencyMins();
+		long last_new_result 	= history.getLastNewResultTime();
+		long next_scan 			= history.getNextScanTime();
+		
+		String[] values = { 
+				String.valueOf( history.isEnabled()),
+				String.valueOf( subs.isPublic()),
+				String.valueOf( history.isAutoDownload()),
+				String.valueOf( subs.isAutoDownloadSupported()),
+				(check_freq==Integer.MAX_VALUE?"":(String.valueOf( history.getCheckFrequencyMins() + " " + MessageText.getString( "ConfigView.text.minutes")))),
+				df.format(new Date( history.getLastScanTime())),
+				( last_new_result==0?"":df.format(new Date( last_new_result ))),
+				( next_scan == Long.MAX_VALUE?"":df.format(new Date( next_scan ))),
+				(last_error.length()==0?MessageText.getString("PeersView.uniquepiece.none"):last_error),
+				String.valueOf( history.getNumRead()),
+				String.valueOf( history.getNumUnread()),
+				String.valueOf( subs.getAssociationCount()),
+				String.valueOf( subs.getVersion()),
+				subs.getHighestVersion() > subs.getVersion()?String.valueOf( subs.getHighestVersion()):null,
+				subs.getCachedPopularity()<=1?null:String.valueOf( subs.getCachedPopularity()),
+				engine_str + ", sid=" + subs.getID(),
+				auth_str,
+				category_str,
+				tag_str,
+			};
+		
+		new PropertiesWindow( subs.getName(), keys, values );
+	}
+
+	private static String
+	toString(
+		String[]	strs )
+	{
+		String	res = "";
+		
+		for(int i=0;i<strs.length;i++){
+			res += (i==0?"":",") + strs[i];
+		}
+		
+		return( res );
+	}
+	
+	private abstract static class SubsMenuItemListener implements MenuItemListener {
+		public final void selected(MenuItem menu, Object target) {
+			if (target instanceof MdiEntry) {
+				MdiEntry info = (MdiEntry) target;
+				Subscription subs = (Subscription) info.getDatasource();
+				
+				try {
+					selected( subs);
+				} catch (Throwable t) {
+					Debug.out(t);
+				}
+			}else if ( target instanceof TableRow ){
+				
+				Object ds = ((TableRow)target).getDataSource();
+				
+				if ( ds instanceof Subscription ){
+					
+					try {
+						selected((Subscription)ds);
+						
+					} catch (Throwable t) {
+						Debug.out(t);
+					}
+				}
+			}
+		}
+
+		public abstract void selected(Subscription subs);
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionSelectedContent.java b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionSelectedContent.java
index 6e1656e..5e9f728 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionSelectedContent.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionSelectedContent.java
@@ -1,184 +1,183 @@
-/*
- * 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.ui.swt.subscriptions;
-
-import java.io.File;
-import java.net.URL;
-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.TOTorrentCreator;
-import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
-import org.gudy.azureus2.core3.util.AETemporaryFileHandler;
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.subs.Subscription;
-import com.aelitis.azureus.core.vuzefile.VuzeFile;
-import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo;
-import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
-import com.aelitis.azureus.ui.selectedcontent.ISelectedVuzeFileContent;
-
-public class 
-SubscriptionSelectedContent 
-	implements ISelectedVuzeFileContent
-{
-	private Subscription		subs;
-	
-		// if you add more fields here be sure to amend 'sameAs' logic below
-	
-	private TOTorrent			torrent;
-	
-	protected
-	SubscriptionSelectedContent(
-		Subscription		_subs )
-	{
-		subs	= _subs;
-	}
-		
-	public String 
-	getDisplayName() 
-	{
-		return( MessageText.getString( "subscriptions.column.name" ) + ": " + subs.getName());
-	}
-	
-	public String
-	getHash()
-	{
-		return( subs.getID());
-	}
-	
-	public VuzeFile
-	getVuzeFile()
-	{
-		try{
-			return( subs.getVuzeFile());
-			
-		}catch( Throwable e ){
-			
-			Debug.out(e);
-		}
-		
-		return( null );
-	}
-	
-	public TOTorrent
-	getTorrent()
-	{
-		synchronized( this ){
-			
-			if ( torrent == null ){
-				
-					// hack alert - we embed the vuze-file into a torrent to allow it to go through
-					// the normal share route, then pick it out again when the recipient 'downloads' it
-				
-				try{
-				
-					VuzeFile vf = subs.getVuzeFile();
-				
-						// if not corrupt....
-					
-					if ( vf != null ){
-						
-						File f1 = AETemporaryFileHandler.createTempFile();
-						
-						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://" ));
-							
-							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 ){
-					
-					Debug.out( e );
-				}
-			}
-		}
-		
-		return( torrent );
-	}
-
-	public void setHash(String hash) {
-	}
-
-	public DownloadManager getDownloadManager() {
-		return null;
-	}
-
-	public int getFileIndex() {
-		return 0;
-	}
-
-	public void setDownloadManager(DownloadManager dm) {
-	}
-
-	public void setTorrent(TOTorrent torrent) {
-	}
-
-	public void setDisplayName(String displayName) {
-	}
-
-	public DownloadUrlInfo getDownloadInfo() {
-		return null;
-	}
-
-	public void setDownloadInfo(DownloadUrlInfo downloadInfo) {
-	}
-	
-	public boolean 
-	sameAs(
-		ISelectedContent _other ) 
-	{
-		if ( _other == this ){
-			
-			return( true );
-		}
-		
-		if ( _other instanceof SubscriptionSelectedContent ){
-			
-			SubscriptionSelectedContent other = (SubscriptionSelectedContent)_other;
-			
-			return( subs == other.subs );
-		}
-		
-		return( false );
-	}
-}
+/*
+ * Created on Apr 8, 2009
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.subscriptions;
+
+import java.io.File;
+import java.net.URL;
+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.TOTorrentCreator;
+import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
+import org.gudy.azureus2.core3.util.AETemporaryFileHandler;
+import org.gudy.azureus2.core3.util.Debug;
+
+import com.aelitis.azureus.core.subs.Subscription;
+import com.aelitis.azureus.core.vuzefile.VuzeFile;
+import com.aelitis.azureus.ui.selectedcontent.DownloadUrlInfo;
+import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
+import com.aelitis.azureus.ui.selectedcontent.ISelectedVuzeFileContent;
+
+public class 
+SubscriptionSelectedContent 
+	implements ISelectedVuzeFileContent
+{
+	private Subscription		subs;
+	
+		// if you add more fields here be sure to amend 'sameAs' logic below
+	
+	private TOTorrent			torrent;
+	
+	protected
+	SubscriptionSelectedContent(
+		Subscription		_subs )
+	{
+		subs	= _subs;
+	}
+		
+	public String 
+	getDisplayName() 
+	{
+		return( MessageText.getString( "subscriptions.column.name" ) + ": " + subs.getName());
+	}
+	
+	public String
+	getHash()
+	{
+		return( subs.getID());
+	}
+	
+	public VuzeFile
+	getVuzeFile()
+	{
+		try{
+			return( subs.getVuzeFile());
+			
+		}catch( Throwable e ){
+			
+			Debug.out(e);
+		}
+		
+		return( null );
+	}
+	
+	public TOTorrent
+	getTorrent()
+	{
+		synchronized( this ){
+			
+			if ( torrent == null ){
+				
+					// hack alert - we embed the vuze-file into a torrent to allow it to go through
+					// the normal share route, then pick it out again when the recipient 'downloads' it
+				
+				try{
+				
+					VuzeFile vf = subs.getVuzeFile();
+				
+						// if not corrupt....
+					
+					if ( vf != null ){
+						
+						File f1 = AETemporaryFileHandler.createTempFile();
+						
+						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://" ));
+							
+							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 ){
+					
+					Debug.out( e );
+				}
+			}
+		}
+		
+		return( torrent );
+	}
+
+	public void setHash(String hash) {
+	}
+
+	public DownloadManager getDownloadManager() {
+		return null;
+	}
+
+	public int getFileIndex() {
+		return 0;
+	}
+
+	public void setDownloadManager(DownloadManager dm) {
+	}
+
+	public void setTorrent(TOTorrent torrent) {
+	}
+
+	public void setDisplayName(String displayName) {
+	}
+
+	public DownloadUrlInfo getDownloadInfo() {
+		return null;
+	}
+
+	public void setDownloadInfo(DownloadUrlInfo downloadInfo) {
+	}
+	
+	public boolean 
+	sameAs(
+		ISelectedContent _other ) 
+	{
+		if ( _other == this ){
+			
+			return( true );
+		}
+		
+		if ( _other instanceof SubscriptionSelectedContent ){
+			
+			SubscriptionSelectedContent other = (SubscriptionSelectedContent)_other;
+			
+			return( subs == other.subs );
+		}
+		
+		return( false );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionView.java b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionView.java
index 4c1889c..fc0d34f 100755
--- a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionView.java
@@ -1,15 +1,32 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.subscriptions;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListenerEx;
 
 
 public class
 SubscriptionView
-	implements SubscriptionsViewBase
+	implements SubscriptionsViewBase, UISWTViewCoreEventListenerEx
 {
 	private SubscriptionsViewBase		impl;
 	
@@ -21,6 +38,18 @@ SubscriptionView
 		impl = internal_subs?new SubscriptionViewInternal():new SubscriptionViewExternal();
 	}
 	
+	public boolean
+	isCloneable()
+	{
+		return( true );
+	}
+	
+	public UISWTViewCoreEventListener
+	getClone()
+	{
+		return( new SubscriptionView());
+	}
+	
 	public void
 	updateBrowser(
 		boolean	is_auto )
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionViewExternal.java b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionViewExternal.java
index fc5ab38..169832d 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionViewExternal.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionViewExternal.java
@@ -1,6 +1,21 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.subscriptions;
 
 
@@ -92,7 +107,10 @@ SubscriptionViewExternal
 			
 			String mode = xmweb_ui.getUtilities().getFeatureManager().isFeatureInstalled( "core" )?"plus":"trial";
 				
-			String query = "Subscription: " + subs.getName() + " ("+subs.getID() + ")";
+				// gotta escape the name on top of overall escaping below as unfortunately it gets un-escaped somewhere and then can confuse parsing of the URL in
+				// the remote search plugin
+			
+			String query = "Subscription: " + UrlUtils.encode(subs.getName()) + " ("+subs.getID() + ")";
 			
 			String search_url = 
 					test_url.substring( 0, pos+1 ) + 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionViewInternal.java b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionViewInternal.java
index cc954fb..d9374d1 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionViewInternal.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionViewInternal.java
@@ -1,17 +1,30 @@
-/**
- * 
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.subscriptions;
 
 import java.net.InetSocketAddress;
-import java.net.Proxy;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
 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;
@@ -41,7 +54,7 @@ import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
 import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.browser.BrowserContext;
-import com.aelitis.azureus.ui.swt.browser.BrowserWrapper;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import com.aelitis.azureus.ui.swt.browser.CookiesListener;
 import com.aelitis.azureus.ui.swt.browser.OpenCloseSearchDetailsListener;
 import com.aelitis.azureus.ui.swt.browser.listener.*;
@@ -345,11 +358,11 @@ SubscriptionViewInternal
 			return;
 		}
 		try{
-			mainBrowser = new BrowserWrapper(composite,Utils.getInitialBrowserStyle(SWT.NONE));
+			final BrowserWrapper bw = mainBrowser = BrowserWrapper.createBrowser(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);
+					bw.setUrl("about:blank");
+					bw.setVisible(false);
 				}
 			});
 			mainBrowserContext = 
@@ -410,11 +423,11 @@ SubscriptionViewInternal
 			data.bottom = new FormAttachment(100,0);
 			mainBrowser.setLayoutData(data);
 			
-			detailsBrowser = new BrowserWrapper(composite,Utils.getInitialBrowserStyle(SWT.NONE));
+			final BrowserWrapper db = detailsBrowser = BrowserWrapper.createBrowser(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);
+					db.setUrl("about:blank");
+					db.setVisible(false);
 				}
 			});
 			BrowserContext detailsContext = 
@@ -488,7 +501,7 @@ SubscriptionViewInternal
 			data = new FormData();
 			data.left = new FormAttachment(0,0);
 			data.right = new FormAttachment(100,0);
-			data.top = new FormAttachment(mainBrowser.getBrowser(),0);
+			data.top = new FormAttachment(mainBrowser.getControl(),0);
 			data.bottom = new FormAttachment(100,0);
 			detailsBrowser.setLayoutData(data);
 							
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionWizard.java b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionWizard.java
index 3f6b47f..25907ab 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionWizard.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionWizard.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.subscriptions;
 
 import java.net.URL;
@@ -98,26 +116,45 @@ public class SubscriptionWizard {
 	Subscription[] subscriptions;
 	
 	DownloadManager download;
+	URL				rss_feed_url;
+	
 	private ImageLoader imageLoader;
 	private TableViewSWT<Subscription> tvSubscriptions;
 	private static boolean columnsAdded = false;
 	
 	public SubscriptionWizard() {
-		this(null);
+		init();
+	}
+	
+	public 
+	SubscriptionWizard(
+		URL		url )
+	{
+		rss_feed_url	= url;
+		
+		init();
+	}
+	
+	public SubscriptionWizard(
+		DownloadManager _download) 
+	{
+		download = _download;
+
+		init();
 	}
 	
-	public SubscriptionWizard(final DownloadManager download) {
+	protected void 
+	init()
+	{
 		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
 			public void azureusCoreRunning(AzureusCore core) {
-				init(core, download);
+				init(core);
 			}
 		});
 	}
 
-	protected void init(AzureusCore core, DownloadManager download) {
+	protected void init(AzureusCore core) {
 		imageLoader = ImageLoader.getInstance();
-
-		this.download = download;
 		
 		/*SubscriptionDownloadDetails[] allSubscriptions = SubscriptionUtils.getAllCachedDownloadDetails();
 		List notYetSubscribed = new ArrayList(allSubscriptions.length);
@@ -1211,6 +1248,13 @@ public class SubscriptionWizard {
 		
 		String titleText = TITLE_OPT_IN;
 		
+		if ( mode != MODE_OPT_IN ){
+			if ( rss_feed_url != null ){
+				mode = MODE_CREATE_RSS;
+				feedUrl.setText( rss_feed_url.toExternalForm());
+				rss_feed_url = null;
+			}
+		}
 		switch (mode) {
 		case MODE_SUBSCRIBE :
 			mainLayout.topControl = availableSubscriptionComposite;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsView.java b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsView.java
index 77d8a67..1580826 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsView.java
@@ -1,5 +1,25 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.subscriptions;
 
+import java.net.URL;
+import java.util.ArrayList;
 import java.util.Map;
 
 import org.eclipse.swt.SWT;
@@ -11,13 +31,20 @@ 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.internat.MessageText;
 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.ui.UIManager;
 import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
+import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
+import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
+import org.gudy.azureus2.plugins.ui.tables.TableManager;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
 import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.plugins.UISWTView;
@@ -27,9 +54,13 @@ import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
 import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
 import org.gudy.azureus2.ui.swt.views.table.impl.TableViewFactory;
 
+import com.aelitis.azureus.core.metasearch.Engine;
 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.core.vuzefile.VuzeFile;
+import com.aelitis.azureus.core.vuzefile.VuzeFileComponent;
+import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.UserPrompterResultListener;
 import com.aelitis.azureus.ui.common.ToolBarItem;
@@ -59,6 +90,7 @@ public class SubscriptionsView
 	private UISWTView swtView;
 	
 	public SubscriptionsView() {
+		
 	}
 	
 	
@@ -79,6 +111,12 @@ public class SubscriptionsView
 	{		
 	}
 	
+	public void
+	subscriptionRequested(
+		URL					url )
+	{	
+	}
+	
 	/* (non-Javadoc)
 	 * @see com.aelitis.azureus.core.subs.SubscriptionManagerListener#subscriptionAdded(com.aelitis.azureus.core.subs.Subscription)
 	 */
@@ -261,13 +299,75 @@ public class SubscriptionsView
 			}
 		});
 		
+
 		view.addSelectionListener(new TableSelectionAdapter() {
+			
+			PluginInterface pi = PluginInitializer.getDefaultInterface();
+			UIManager uim = pi.getUIManager();
+			
+			MenuManager  menu_manager 	= uim.getMenuManager();
+			TableManager table_manager 	= uim.getTableManager();
+
+			ArrayList<TableContextMenuItem>	menu_items = new ArrayList<TableContextMenuItem>();
+			
+			SubscriptionManagerUI.MenuCreator menu_creator = 
+					new SubscriptionManagerUI.MenuCreator()
+					{
+						public MenuItem
+						createMenu(
+							String 	resource_id )
+						{
+							TableContextMenuItem menu = 
+								table_manager.addContextMenuItem( TABLE_ID, resource_id );
+							
+							menu_items.add( menu );
+							
+							return( menu );
+						}
+						
+						public void refreshView() 
+						{
+							
+						}
+					};
+					
 			public void defaultSelected(TableRowCore[] rows, int stateMask) {
 				if(rows.length == 1) {
 					TableRowCore row = rows[0];
 					
 					Subscription sub = (Subscription) row.getDataSource();
-					if(sub != null) {
+					if(sub == null) {
+						return;
+					}
+					
+					if (sub.isSearchTemplate()) {
+
+						try{
+							VuzeFile vf = sub.getSearchTemplateVuzeFile();
+							
+							if ( vf != null ){
+							
+								sub.setSubscribed( true );
+								
+								VuzeFileHandler.getSingleton().handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_NONE );
+								
+								
+								for ( VuzeFileComponent comp: vf.getComponents()){
+									
+									Engine engine = (Engine)comp.getData( Engine.VUZE_FILE_COMPONENT_ENGINE_KEY );
+									
+									if ( engine != null && engine.getSelectionState() == Engine.SEL_STATE_DESELECTED ){
+										
+										engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
+									}
+								}
+							}
+						}catch( Throwable e ){
+							
+							Debug.out( e );
+						}
+				} else {
+
 						String key = "Subscription_" + ByteFormatter.encodeString(sub.getPublicKey());
 						MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
 						if (mdi != null) {
@@ -286,8 +386,22 @@ public class SubscriptionsView
 					sels[i] = new SubscriptionSelectedContent((Subscription)rows[i].getDataSource());
 				}
 				
-				SelectedContentManager.changeCurrentlySelectedContent(view.getTableID(),
-						sels, view);
+				SelectedContentManager.changeCurrentlySelectedContent(view.getTableID(), sels, view);
+				
+				for ( TableContextMenuItem mi: menu_items ){
+					
+					mi.remove();
+				}
+				
+				if ( rows.length == 1 ){
+					
+					Subscription subs = (Subscription) rows[0].getDataSource();
+
+					if ( subs != null ){
+								
+						SubscriptionManagerUI.createMenus( menu_manager, menu_creator, subs );
+					}
+				}				
 			}
 			
 		}, false) ;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsViewBase.java b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsViewBase.java
index 13e786c..dab63f2 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsViewBase.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/subscriptions/SubscriptionsViewBase.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2014 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/toolbar/ToolBarItemSO.java b/azureus3/src/com/aelitis/azureus/ui/swt/toolbar/ToolBarItemSO.java
index 1a537f6..8e22902 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/toolbar/ToolBarItemSO.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/toolbar/ToolBarItemSO.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 22, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -19,13 +21,13 @@
 package com.aelitis.azureus.ui.swt.toolbar;
 
 import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener;
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager;
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UIToolBarItemImpl;
 
 import com.aelitis.azureus.ui.common.ToolBarItem;
 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.views.skin.ToolBarView;
 
 /**
  * @author TuxPaper
@@ -33,79 +35,31 @@ import com.aelitis.azureus.ui.swt.views.skin.ToolBarView;
  *
  */
 public class ToolBarItemSO
-	implements ToolBarItem
 {
-	String imageID = "image.toolbar.run";
-
-	String id;
+	private final static boolean DEBUG_TUX = false;
 
 	private SWTSkinButtonUtility skinButton;
 
 	private SWTSkinObjectText skinTitle;
 
-	boolean enabled = false;
-
-	private String textID;
-
-	private String tooltipID;
-
-	private boolean alwaysAvailable = false;
-
-	private final ToolBarView tbView;
-
-	private UIToolBarActivationListener defaultActivation;
-
-	private final boolean isPluginItem;
-
-	private String groupID = UIToolBarManager.GROUP_MAIN;
-
-	private long defaultState;
-
 	private boolean isDown;
 
-	/**
-	 * @param id
-	 * @param image
-	 */
-	public ToolBarItemSO(ToolBarView tbView, String id, String imageid) {
-		super();
-		this.tbView = tbView;
-		this.id = id;
-		imageID = imageid;
-		isPluginItem = false;
-	}
+	private UIToolBarItemImpl base;
 
-	public ToolBarItemSO(ToolBarView tbView, String id, String imageid,
-			String textID) {
-		super();
-		this.tbView = tbView;
-		this.id = id;
-		imageID = imageid;
-		this.textID = textID;
-		this.tooltipID = textID + ".tooltip";
-		isPluginItem = false;
-	}
-
-	public ToolBarItemSO(ToolBarView tbView, String id, boolean isPluginItem) {
-		this.tbView = tbView;
-		this.id = id;
-		this.isPluginItem = isPluginItem;
-	}
+	private SWTSkinObject so;
 
-	/* (non-Javadoc)
-	 * @see com.aelitis.azureus.ui.common.ToolBarItem#triggerToolBarItem(long, java.lang.Object)
-	 */
-	public boolean triggerToolBarItem(long activationType, Object datasource) {
-		return tbView.triggerToolBarItem(this, activationType, datasource);
+	public ToolBarItemSO(UIToolBarItemImpl base, SWTSkinObject so) {
+		this.base = base;
+		this.so = so;
 	}
 
-	public String getID() {
-		return id;
+	public SWTSkinObject getSO() {
+		return so;
 	}
 
 	public void setSkinButton(SWTSkinButtonUtility btn) {
 		this.skinButton = btn;
-		skinButton.setDisabled(!enabled);
+		updateUI();
 	}
 
 	public SWTSkinButtonUtility getSkinButton() {
@@ -114,116 +68,57 @@ public class ToolBarItemSO
 
 	public void setSkinTitle(SWTSkinObjectText s) {
 		skinTitle = s;
-	}
-
-	public long getState() {
-		long state = (isEnabled() ? STATE_ENABLED : 0) | (isDown ? STATE_DOWN : 0);
-
-		return state;
-	}
-
-	public void setState(long state) {
-		// TODO: This gets called a lot for the same toolbar item -- need to look
-		// into why.
-		setEnabled((state & STATE_ENABLED) > 0);
-		isDown = (state & STATE_DOWN) > 0;
-		if (skinButton != null) {
-			skinButton.getSkinObject().switchSuffix(isDown ? "-selected" : "", 4, false);
-		}
-	}
-
-	private boolean isEnabled() {
-		if (skinButton != null) {
-			return !skinButton.isDisabled();
-		}
-		return enabled;
+		skinTitle.setTextID(base.getTextID());
 	}
 
 	private void setEnabled(boolean enabled) {
-		if (alwaysAvailable && !enabled) {
+		if (DEBUG_TUX) {
+			if (Character.isDigit(base.getID().charAt(0))) {
+				//if (base.getID().equals("up")) {
+				System.out.println("setEnabeld " + enabled + "/" + base.getID()
+						+ ";sb=" + Debug.getCompressedStackTrace());
+			}
+		}
+		if (base.isAlwaysAvailable() && !enabled) {
 			return;
 		}
-		this.enabled = enabled;
 		if (skinButton != null) {
 			skinButton.setDisabled(!enabled);
 		}
 	}
 
-	public String getImageID() {
-		return imageID;
-	}
-
-	public void setImageID(String imageID) {
-		this.imageID = imageID;
-		if (skinButton != null) {
-			skinButton.setImage(imageID);
-		}
-	}
-
-	/**
-	 * @param textID the textID to set
-	 */
-	public void setTextID(String textID) {
-		this.textID = textID;
-		if (skinTitle != null) {
-			skinTitle.setTextID(textID);
-		}
-	}
-
-	/**
-	 * @return the textID
-	 */
-	public String getTextID() {
-		return textID;
-	}
-
-	public String getTooltipID() {
-		return tooltipID;
-	}
-
-	public void setTooltipID(String tooltipID) {
-		this.tooltipID = tooltipID;
-	}
-
-	public void setAlwaysAvailable(boolean alwaysAvailable) {
-		this.alwaysAvailable = alwaysAvailable;
-		if (alwaysAvailable) {
-			setEnabled(true);
-		}
-	}
-
-	public boolean isAlwaysAvailable() {
-		return alwaysAvailable;
-	}
-
-	public void setDefaultActivationListener(
-			UIToolBarActivationListener defaultActivation) {
-		this.defaultActivation = defaultActivation;
-	}
-
-	public UIToolBarActivationListener getDefaultActivationListener() {
-		return defaultActivation;
-	}
-
 	public void dispose() {
 		// ToolBarView will dispose of skinobjects
 		skinButton = null;
 		skinTitle = null;
 	}
 
-	public String getGroupID() {
-		return groupID;
+	public ToolBarItem getBase() {
+		return base;
 	}
 
-	public void setGroupID(String groupID) {
-		this.groupID = groupID;
+	public void updateUI() {
+		if (skinButton != null) {
+			skinButton.setImage(base.getImageID());
+		}
+		if (skinTitle != null) {
+			skinTitle.setTextID(base.getTextID());
+		}
+		if (base.isAlwaysAvailable()) {
+			setEnabled(true);
+		} else {
+			long state = base.getState();
+			setEnabled((state & UIToolBarItem.STATE_ENABLED) > 0);
+			isDown = (state & UIToolBarItem.STATE_DOWN) > 0;
+			if (skinButton != null) {
+				skinButton.getSkinObject().switchSuffix(isDown ? "-selected" : "", 4,
+						false);
+			}
+		}
 	}
 
-	public void setDefaultState(long state) {
-		this.defaultState = state;
+	public void setSO(SWTSkinObject so) {
+		this.so = so;
 	}
 
-	public long getDefaultState() {
-		return defaultState;
-	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/utils/TagUIUtilsV3.java b/azureus3/src/com/aelitis/azureus/ui/swt/utils/TagUIUtilsV3.java
new file mode 100644
index 0000000..e6c047e
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/utils/TagUIUtilsV3.java
@@ -0,0 +1,114 @@
+/**
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.utils;
+
+import org.eclipse.swt.SWT;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.internat.MessageText;
+import org.gudy.azureus2.core3.util.Debug;
+
+import com.aelitis.azureus.core.tag.*;
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.swt.skin.*;
+import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog;
+import com.aelitis.azureus.ui.swt.views.skin.StandardButtonsArea;
+
+/**
+ * @author TuxPaper
+ * @created Feb 26, 2015
+ *
+ */
+public class TagUIUtilsV3
+{
+
+	public static void showCreateTagDialog(final UIFunctions.TagReturner tagReturner) {
+		final SkinnedDialog dialog = new SkinnedDialog("skin3_dlg_addtag", "shell",
+				SWT.DIALOG_TRIM);
+		SWTSkin skin = dialog.getSkin();
+
+		final SWTSkinObjectTextbox tb = (SWTSkinObjectTextbox) skin.getSkinObject(
+				"tag-name");
+		final SWTSkinObjectCheckbox cb = (SWTSkinObjectCheckbox) skin.getSkinObject(
+				"tag-share");
+
+		if (tb == null || cb == null) {
+			return;
+		}
+
+		cb.setChecked(COConfigurationManager.getBooleanParameter(
+				"tag.sharing.default.checked"));
+
+		SWTSkinObject soButtonArea = skin.getSkinObject("bottom-area");
+		if (soButtonArea instanceof SWTSkinObjectContainer) {
+			StandardButtonsArea buttonsArea = new StandardButtonsArea() {
+				// @see com.aelitis.azureus.ui.swt.views.skin.StandardButtonsArea#clicked(int)
+				protected void clicked(int buttonValue) {
+					if (buttonValue == SWT.OK) {
+
+						String tag_name = tb.getText().trim();
+						TagType tt = TagManagerFactory.getTagManager().getTagType(
+								TagType.TT_DOWNLOAD_MANUAL);
+
+						Tag tag = tt.getTag(tag_name, true);
+
+						if (tag == null) {
+
+							try {
+
+								tag = tt.createTag(tag_name, true);
+
+								tag.setPublic(cb.isChecked());
+
+
+							} catch (TagException e) {
+
+								Debug.out(e);
+							}
+						}
+						
+						// return tag even if it already existed.  
+						// Case: assigning tag to DL, user enters same tag name because 
+						// they forgot they already had one
+						if (tagReturner != null && tag != null) {
+							tagReturner.returnedTags(new Tag[] {
+								tag
+							});
+						}
+
+					}
+					
+					dialog.close();
+				}
+			};
+			buttonsArea.setButtonIDs(new String[] {
+				MessageText.getString("Button.add"),
+				MessageText.getString("Button.cancel")
+			});
+			buttonsArea.setButtonVals(new Integer[] {
+				SWT.OK,
+				SWT.CANCEL
+			});
+			buttonsArea.swt_createButtons(
+					((SWTSkinObjectContainer) soButtonArea).getComposite());
+		}
+
+		dialog.open();
+	}
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/utils/TorrentUIUtilsV3.java b/azureus3/src/com/aelitis/azureus/ui/swt/utils/TorrentUIUtilsV3.java
index 79e52ae..c5cb97d 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/utils/TorrentUIUtilsV3.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/utils/TorrentUIUtilsV3.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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.utils;
@@ -174,7 +171,7 @@ public class TorrentUIUtilsV3
 										file.deleteOnExit();
 
 										// Do a quick check to see if it's a torrent
-										if (!TorrentUtil.isFileTorrent(file, file.getName())) {
+										if (!TorrentUtil.isFileTorrent(file, file.getName(), true)) {
 											return;
 										}
 
@@ -361,11 +358,16 @@ public class TorrentUIUtilsV3
 			image = (Image) Utils.execSWTThreadWithObject("thumbcreator",
 					new AERunnableObject() {
 						public Object runSupport() {
-
-							ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
-							Image image = new Image(Display.getDefault(), bis);
-
-							return image;
+							try{
+								ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
+								Image image = new Image(Display.getDefault(), bis);
+	
+								return image;
+								
+							}catch( Throwable e ){
+								
+								return( null );
+							}
 						}
 					}, 500);
 		}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/PieceGraphView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/PieceGraphView.java
index 60233b3..cf879eb 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/PieceGraphView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/PieceGraphView.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/TopBarView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/TopBarView.java
index 1fa90cc..aaa69d4 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/TopBarView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/TopBarView.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jun 27, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -28,7 +30,6 @@ import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.graphics.Transform;
 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.AERunnable;
@@ -37,7 +38,6 @@ import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
 import org.gudy.azureus2.ui.swt.pluginsimpl.*;
-import org.gudy.azureus2.ui.swt.views.stats.VivaldiView;
 
 import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
@@ -93,8 +93,32 @@ public class TopBarView
 				return null;
 			}
 		});
-		// trigger autobuild
-		skin.getSkinObject("topbar-area-plugin");
+		
+			// trigger autobuild and hook in events
+		
+		skin.getSkinObject("topbar-area-plugin").addListener(
+			new SWTSkinObjectListener() {
+				
+				public Object eventOccured(SWTSkinObject skinObject, int eventType,
+						Object params) {
+					if ( eventType == SWTSkinObjectListener.EVENT_SHOW ){
+						
+						if ( activeTopBar != null ){
+						
+							activeTopBar.triggerEvent( UISWTViewEvent.TYPE_FOCUSGAINED, null );
+						}
+					}else if ( eventType == SWTSkinObjectListener.EVENT_HIDE ){
+						
+						if ( activeTopBar != null ){
+							
+							activeTopBar.triggerEvent( UISWTViewEvent.TYPE_FOCUSLOST, null );
+						}
+					}
+					
+					return( null );
+				}
+			});
+		
 		return null;
 	}
 
@@ -325,9 +349,13 @@ public class TopBarView
 						new ViewDownSpeedGraph());
 				uiSWTinstance.addView(UISWTInstance.VIEW_TOPBAR, "ViewUpSpeedGraph",
 						new ViewUpSpeedGraph());
+				uiSWTinstance.addView(UISWTInstance.VIEW_TOPBAR, "ViewQuickConfig",
+						new ViewQuickConfig());
+				/* derp
 				uiSWTinstance.addView(UISWTInstance.VIEW_TOPBAR, "VivaldiView",
 						new VivaldiView(false));
-
+				*/
+				
 				registeredCoreSubViews = true;
 			}
 
@@ -336,8 +364,8 @@ public class TopBarView
 				for (UISWTViewEventListenerHolder l : pluginViews) {
 					if (l != null) {
 						try {
-							UISWTViewImpl view = new UISWTViewImpl(UISWTInstance.VIEW_TOPBAR,
-									l.getViewID(), l, null);
+							UISWTViewImpl view = new UISWTViewImpl(l.getViewID(), UISWTInstance.VIEW_TOPBAR, false);
+							view.setEventListener(l, true);
 							addTopBarView(view, cPluginArea);
 							if (toActiveView-- == 0) {
 								activateTopBar(view);
@@ -392,6 +420,10 @@ public class TopBarView
 		if (soTitle != null) {
 			soTitle.getControl().redraw();
 		}
+		
+		Utils.relayout(c);
+		
+		activeTopBar.triggerEvent( UISWTViewEvent.TYPE_FOCUSGAINED, null );
 	}
 
 	/**
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewDownSpeedGraph.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewDownSpeedGraph.java
index b15ee5f..eacd174 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewDownSpeedGraph.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewDownSpeedGraph.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
@@ -23,12 +20,13 @@ package com.aelitis.azureus.ui.swt.views;
 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.Canvas;
 import org.eclipse.swt.widgets.Composite;
-
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 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.util.SimpleTimer;
 import org.gudy.azureus2.core3.util.TimerEvent;
 import org.gudy.azureus2.core3.util.TimerEventPerformer;
@@ -95,7 +93,7 @@ public class ViewDownSpeedGraph
 
 	private void initialize(Composite composite) {
 		GridData gridData;
-
+		composite.setLayout( new GridLayout());
 		downSpeedCanvas = new Canvas(composite, SWT.DOUBLE_BUFFERED);
 		gridData = new GridData(GridData.FILL_BOTH);
 		downSpeedCanvas.setLayoutData(gridData);
@@ -121,7 +119,7 @@ public class ViewDownSpeedGraph
 	}
 
 	private String getFullTitle() {
-		return "DL Speed";
+		return( MessageText.getString("TableColumn.header.downspeed"));
 	}
 	
 	
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewQuickConfig.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewQuickConfig.java
new file mode 100644
index 0000000..1e01667
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewQuickConfig.java
@@ -0,0 +1,146 @@
+/**
+ * Copyright (C) Azureus Software, 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.views;
+
+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.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.config.IntParameter;
+import org.gudy.azureus2.ui.swt.plugins.UISWTView;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListener;
+import org.gudy.azureus2.ui.swt.views.configsections.ConfigSectionStartShutdown;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+
+/**
+ * @author TuxPaper
+ * @created Apr 7, 2007
+ *
+ */
+public class ViewQuickConfig
+	implements UISWTViewCoreEventListener
+{
+	private UISWTView swtView;
+	
+	Composite	composite;
+	
+	public ViewQuickConfig() {
+		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+			public void azureusCoreRunning(AzureusCore core) {
+			}
+		});
+	}
+
+
+	private void 
+	initialize(
+		Composite parent) 
+	{
+		parent.setLayout( new GridLayout());
+		
+		composite = new Composite( parent, SWT.BORDER );
+		
+		GridData gridData = new GridData(GridData.FILL_BOTH);
+		
+		composite.setLayoutData(gridData);
+		
+		GridLayout layout = new GridLayout(4, false);
+		
+		composite.setLayout(layout);
+		
+			// done downloading - 2
+		
+		ConfigSectionStartShutdown.addDoneDownloadingOption( composite, false );
+		
+			// max simul down - 2 
+		
+		Label label = new Label(composite, SWT.NULL);
+		gridData = new GridData();
+		gridData.horizontalIndent = 8;
+		label.setLayoutData( gridData );
+		Messages.setLanguageText(label, "ConfigView.label.maxdownloads.short");
+		
+		IntParameter maxDLs = new IntParameter( composite, "max downloads" );
+				
+		Utils.execSWTThreadLater(
+			100,
+			new Runnable() {
+				
+				public void run() {
+					composite.traverse( SWT.TRAVERSE_TAB_NEXT);
+				}
+			});
+	}
+
+	private void delete() {
+		Utils.disposeComposite(composite);
+	}
+
+	private String getFullTitle() {
+		return( MessageText.getString( "label.quick.config" ));
+	}
+	
+	
+
+	private Composite getComposite() {
+		return composite;
+	}
+
+	private void refresh() {
+
+	}
+
+	public boolean eventOccurred(UISWTViewEvent event) {
+    switch (event.getType()) {
+      case UISWTViewEvent.TYPE_CREATE:
+      	swtView = event.getView();
+      	swtView.setTitle(getFullTitle());
+        break;
+
+      case UISWTViewEvent.TYPE_DESTROY:
+        delete();
+        break;
+
+      case UISWTViewEvent.TYPE_INITIALIZE:
+        initialize((Composite)event.getData());
+        break;
+
+      case UISWTViewEvent.TYPE_LANGUAGEUPDATE:
+      	Messages.updateLanguageForControl(getComposite());
+      	swtView.setTitle(getFullTitle());
+        break;
+
+      case UISWTViewEvent.TYPE_REFRESH:
+        refresh();
+        break;
+      case UISWTViewEvent.TYPE_FOCUSGAINED:{
+    	  composite.traverse( SWT.TRAVERSE_TAB_NEXT);
+    	  break;
+      }
+    }
+
+    return true;
+  }
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewTitleInfoBetaP.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewTitleInfoBetaP.java
index 1dd368f..708b29c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewTitleInfoBetaP.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewTitleInfoBetaP.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.views;
 
 import java.io.InputStream;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewUpSpeedGraph.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewUpSpeedGraph.java
index a2a7a61..895ba3c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewUpSpeedGraph.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/ViewUpSpeedGraph.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,22 +13,20 @@
  * 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;
 
 import org.eclipse.swt.SWT;
 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.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.config.impl.TransferSpeedValidator;
 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.util.SimpleTimer;
 import org.gudy.azureus2.core3.util.TimerEvent;
 import org.gudy.azureus2.core3.util.TimerEventPerformer;
@@ -79,6 +77,7 @@ public class ViewUpSpeedGraph
 	private void initialize(Composite composite) {
 		GridData gridData;
 
+		composite.setLayout( new GridLayout());
 		upSpeedCanvas = new Canvas(composite, SWT.DOUBLE_BUFFERED);
 		gridData = new GridData(GridData.FILL_BOTH);
 		upSpeedCanvas.setLayoutData(gridData);
@@ -108,7 +107,7 @@ public class ViewUpSpeedGraph
 	}
 
 	private String getFullTitle() {
-		return "UL Speed";
+		return( MessageText.getString("TableColumn.header.upspeed"));
 	}
 
 	private Composite getComposite() {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/Browse.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/Browse.java
index 30f1b74..a613473 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/Browse.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/Browse.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/InfoBarUtil.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/InfoBarUtil.java
index c40dd33..b5ce184 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/InfoBarUtil.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/InfoBarUtil.java
@@ -1,10 +1,12 @@
 /**
  * Created on Mar 1, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -21,6 +23,7 @@ package com.aelitis.azureus.ui.swt.views.skin;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.layout.FormAttachment;
 import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.widgets.Control;
 
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.internat.MessageText;
@@ -92,7 +95,11 @@ public abstract class InfoBarUtil
 	}
 
 	protected void createInfoBar() {
-		Object ldForSO = forSO.getControl().getLayoutData();
+		Control control = forSO.getControl();
+		if (control == null || control.isDisposed()) {
+			return;
+		}
+		Object ldForSO = control.getLayoutData();
 		if (!(ldForSO instanceof FormData)) {
 			return;
 		}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/MyTorrentsView_Big.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/MyTorrentsView_Big.java
index a8b7650..2ed73b9 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/MyTorrentsView_Big.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/MyTorrentsView_Big.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.views.skin;
 
 import org.eclipse.swt.widgets.Composite;
@@ -20,11 +38,11 @@ public class MyTorrentsView_Big
 	private final int torrentFilterMode;
 
 	public MyTorrentsView_Big(AzureusCore _azureus_core, int torrentFilterMode,
-			TableColumnCore[] basicItems, Text txtFilter, Composite cCats) {
+			TableColumnCore[] basicItems, Text txtFilter, Composite cCatsTags) {
 		super( true );
 		this.torrentFilterMode = torrentFilterMode;
 		this.txtFilter = txtFilter;
-		this.cCategories = cCats;
+		this.cCategoriesAndTags = cCatsTags;
 		Class<?> forDataSourceType;
 		switch (torrentFilterMode) {
 			case SBC_LibraryView.TORRENTS_COMPLETE:
@@ -35,22 +53,13 @@ public class MyTorrentsView_Big
 				forDataSourceType = DownloadTypeIncomplete.class;
 				break;
 				
-			case SBC_LibraryView.TORRENTS_UNOPENED:
-				forDataSourceType = Download.class;
-				break;
-				
-			case SBC_LibraryView.TORRENTS_ALL:
-				forDataSourceType = Download.class;
-				break;
-
 			default:
-				forDataSourceType = null;
+				forDataSourceType = Download.class;
 				break;
 		}
 		init(
 				_azureus_core,
 				SB_Transfers.getTableIdFromFilterMode(torrentFilterMode, true),
-				torrentFilterMode == SBC_LibraryView.TORRENTS_INCOMPLETE ? false : true,
 				forDataSourceType, basicItems);
 		//setForceHeaderVisible(true);
 	}
@@ -66,7 +75,7 @@ public class MyTorrentsView_Big
 				return false;
 			}
 		} else if (torrentFilterMode == SBC_LibraryView.TORRENTS_ALL) {
-			if ( !isInCurrentCategory(dm)){
+			if ( !isInCurrentTag(dm)){
 				return(false );
 			}
 			return( isInCurrentTag(dm));
@@ -77,7 +86,8 @@ public class MyTorrentsView_Big
 
 	// @see org.gudy.azureus2.ui.swt.views.MyTorrentsView#defaultSelected(com.aelitis.azureus.ui.common.table.TableRowCore[])
 	public void defaultSelected(TableRowCore[] rows, int stateMask) {
-		SBC_LibraryTableView.doDefaultClick(rows, stateMask, !isSeedingView);
+		boolean neverPlay = DownloadTypeIncomplete.class.equals(getForDataSourceType());
+		SBC_LibraryTableView.doDefaultClick(rows, stateMask, neverPlay);
 	}
 
 	protected int getRowDefaultHeight() {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityTableView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityTableView.java
index f43fa54..4fa2aa9 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityTableView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityTableView.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 25, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -369,7 +371,11 @@ public class SBC_ActivityTableView
 		}
 		VuzeActivitiesEntry[] selectedEntries = view.getSelectedDataSources().toArray(
 				new VuzeActivitiesEntry[0]);
-		removeEntries(selectedEntries, 0);
+		
+		if ( selectedEntries.length > 0 ){
+		
+			removeEntries(selectedEntries, 0);
+		}
 	}
 
 	public TableViewSWT getView() {
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityView.java
index e84f81e..832e3e4 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ActivityView.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 2, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ArchivedDownloadsView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ArchivedDownloadsView.java
new file mode 100644
index 0000000..b7dadbc
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_ArchivedDownloadsView.java
@@ -0,0 +1,772 @@
+/**
+ * Created on May 10, 2013
+ *
+ * Copyright (C) Azureus Software, 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.views.skin;
+
+
+import java.io.File;
+import java.util.*;
+import java.util.regex.Pattern;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MenuEvent;
+import org.eclipse.swt.events.MenuListener;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+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.Text;
+import org.gudy.azureus2.core3.config.COConfigurationManager;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.plugins.download.Download;
+import org.gudy.azureus2.plugins.download.DownloadException;
+import org.gudy.azureus2.plugins.download.DownloadStub;
+import org.gudy.azureus2.plugins.download.DownloadStub.DownloadStubFile;
+import org.gudy.azureus2.plugins.download.DownloadStubEvent;
+import org.gudy.azureus2.plugins.download.DownloadStubListener;
+import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener;
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
+import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
+import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.TorrentUtil;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
+import org.gudy.azureus2.ui.swt.views.ArchivedFilesView;
+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.TableViewFactory;
+import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator;
+import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer;
+import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
+import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils.ArchiveCallback;
+
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.util.RegExUtil;
+import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.common.ToolBarItem;
+import com.aelitis.azureus.ui.common.table.*;
+import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
+import com.aelitis.azureus.ui.common.updater.UIUpdatable;
+import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
+import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
+import com.aelitis.azureus.ui.swt.columns.archivedls.*;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectTextbox;
+
+
+public class SBC_ArchivedDownloadsView
+	extends SkinView
+	implements 	UIUpdatable, UIPluginViewToolBarListener, TableViewFilterCheck<DownloadStub>,
+	TableViewSWTMenuFillListener, TableSelectionListener, DownloadStubListener
+{
+
+	private static final String TABLE_NAME = "ArchivedDownloads";
+
+	TableViewSWT<DownloadStub> tv;
+
+	private Text txtFilter;
+
+	private Composite table_parent;
+
+	private boolean columnsAdded = false;
+
+	private boolean dm_listener_added;
+
+	private boolean registeredCoreSubViews;
+
+	private Object datasource;
+	  
+	public Object 
+	skinObjectInitialShow(
+		SWTSkinObject 	skinObject, 
+		Object 			params) 
+	{		
+		initColumns();
+		
+		new InfoBarUtil(
+			skinObject, 
+			"archivedlsview.infobar", 
+			false,
+			"archivedls.infobar", 
+			"archivedls.view.infobar" ) 
+			{
+				public boolean 
+				allowShow() 
+				{
+					return( true );
+				}
+			};
+		
+		return( null );
+	}
+
+	protected void 
+	initColumns() 
+	{
+		synchronized (SBC_ArchivedDownloadsView.class) {
+
+			if ( columnsAdded ){
+
+				return;
+			}
+
+			columnsAdded = true;
+		}
+
+		TableColumnManager tableManager = TableColumnManager.getInstance();
+
+		tableManager.registerColumn(DownloadStub.class, ColumnArchiveDLName.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnArchiveDLName(column);
+					}
+				});
+
+		tableManager.registerColumn(DownloadStub.class, ColumnArchiveDLSize.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnArchiveDLSize(column);
+					}
+				});
+		
+		tableManager.registerColumn(DownloadStub.class, ColumnArchiveDLFileCount.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnArchiveDLFileCount(column);
+					}
+				});
+		
+		tableManager.registerColumn(DownloadStub.class,
+				ColumnArchiveDLDate.COLUMN_ID,
+				new TableColumnCoreCreationListener() {
+					public TableColumnCore createTableColumnCore(
+							Class<?> forDataSourceType, String tableID, String columnID) {
+						return new ColumnDateSizer(DownloadStub.class, columnID,
+								TableColumnCreator.DATE_COLUMN_WIDTH, tableID) {
+						};
+					}
+
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnArchiveDLDate(column);
+					}
+				});
+		
+		tableManager.registerColumn(DownloadStub.class, ColumnArchiveDLTags.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnArchiveDLTags(column);
+					}
+				});
+		
+		tableManager.setDefaultColumnNames(TABLE_NAME,
+				new String[] {
+					ColumnArchiveDLName.COLUMN_ID,
+					ColumnArchiveDLSize.COLUMN_ID,
+					ColumnArchiveDLFileCount.COLUMN_ID,
+					ColumnArchiveDLDate.COLUMN_ID,
+				});
+		
+		tableManager.setDefaultSortColumnName(TABLE_NAME, ColumnArchiveDLName.COLUMN_ID);
+	}
+
+	public Object 
+	skinObjectHidden(
+		SWTSkinObject skinObject, 
+		Object params) 
+	{
+		if ( tv != null ){
+
+			tv.delete();
+
+			tv = null;
+		}
+
+		Utils.disposeSWTObjects(new Object[] {
+			table_parent,
+		});
+		
+		if ( dm_listener_added ){
+		
+			PluginInitializer.getDefaultInterface().getDownloadManager().removeDownloadStubListener( this );
+			
+			dm_listener_added = false;
+		}
+
+		return super.skinObjectHidden(skinObject, params);
+	}
+
+	public Object 
+	skinObjectShown(
+		SWTSkinObject 	skinObject, 
+		Object 			params) 
+	{
+		super.skinObjectShown( skinObject, params );
+		
+		SWTSkinObjectTextbox soFilter = (SWTSkinObjectTextbox)getSkinObject( "filterbox" );
+		
+		if ( soFilter != null ){
+		
+			txtFilter = soFilter.getTextControl();
+		}
+		
+		SWTSkinObject so_list = getSkinObject( "archived-dls-list" );
+
+		if ( so_list != null ){
+			
+			initTable((Composite)so_list.getControl());
+			
+		}else{
+			
+			System.out.println("NO archived-dls-list");
+			
+			return( null );
+		}
+				
+		if ( tv == null ){
+			
+			return( null );
+		}
+
+		PluginInitializer.getDefaultInterface().getDownloadManager().addDownloadStubListener( this, true );
+		
+		dm_listener_added = true;
+		
+		return( null );
+	}
+
+	@Override
+	public Object 
+	skinObjectDestroyed(
+		SWTSkinObject 	skinObject, 
+		Object 			params) 
+	{
+		if ( dm_listener_added ){
+			
+			PluginInitializer.getDefaultInterface().getDownloadManager().removeDownloadStubListener( this );
+			
+			dm_listener_added = false;
+		}		
+		
+		return super.skinObjectDestroyed(skinObject, params);
+	}
+	
+
+	private void 
+	initTable(
+		Composite control )
+	{
+		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
+		
+		if ( uiFunctions != null ) {
+			
+			UISWTInstance pluginUI = uiFunctions.getUISWTInstance();
+			
+			registerPluginViews( pluginUI );
+		}
+
+		if ( tv == null ){
+			
+			tv = TableViewFactory.createTableViewSWT(
+					DownloadStub.class, TABLE_NAME, TABLE_NAME,
+					new TableColumnCore[0], 
+					ColumnArchiveDLName.COLUMN_ID, 
+					SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL);
+			
+			if ( txtFilter != null){
+				
+				tv.enableFilterCheck( txtFilter, this );
+			}
+			
+			tv.setRowDefaultHeight(16);
+			
+			tv.setEnableTabViews(true, true, null);
+	
+			table_parent = new Composite(control, SWT.BORDER);
+			
+			table_parent.setLayoutData(Utils.getFilledFormData());
+			
+			GridLayout layout = new GridLayout();
+			
+			layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0;
+			
+			table_parent.setLayout(layout);
+	
+			tv.addMenuFillListener(this);
+			tv.addSelectionListener( this, false );
+			
+			tv.initialize( table_parent );
+
+			tv.addCountChangeListener(
+				new TableCountChangeListener() 
+				{
+					public void 
+					rowRemoved(
+						TableRowCore row) 
+					{
+					}
+					
+					public void 
+					rowAdded(
+						TableRowCore row) 
+					{
+						if ( datasource == row.getDataSource()){
+							
+							tv.setSelectedRows(new TableRowCore[] { row });
+						}
+					}
+				});
+		}
+
+		control.layout( true );
+	}
+
+	private void 
+	registerPluginViews(
+		UISWTInstance pluginUI ) 
+	{
+		if ( registeredCoreSubViews ){
+			
+			return;
+		}
+			
+		pluginUI.addView(TABLE_NAME, "ArchivedFilesView", ArchivedFilesView.class, null);
+		
+		registeredCoreSubViews = true;
+	}
+
+	public boolean 
+	toolBarItemActivated(
+		ToolBarItem item, 
+		long activationType,
+		Object datasource) 
+	{
+		if ( tv == null || !tv.isVisible()){
+			
+			return( false );
+		}
+		
+		List<Object> datasources = tv.getSelectedDataSources();
+		
+		if ( datasources.size() > 0 ){
+
+			List<DownloadStub>	dms = new ArrayList<DownloadStub>( datasources.size());
+			
+			for ( Object o: datasources ){
+				
+				dms.add((DownloadStub)o);
+			}
+			
+			String id = item.getID();
+			
+			if ( id.equals("remove")) {
+			
+				TorrentUtil.removeDataSources(datasources.toArray());
+				
+			}else if ( id.equals( "startstop" ) || id.equals( "start" )){
+				
+				ManagerUtils.restoreFromArchive( dms, true, null );
+			}
+			
+				
+			return true;
+		}
+		
+		return false;
+	}
+
+	public void 
+	refreshToolBarItems(
+		Map<String, Long> list) 
+	
+	{
+		if ( tv == null || !tv.isVisible()){
+			
+			return;
+		}
+
+		boolean canEnable = false;
+		
+		Object[] datasources = tv.getSelectedDataSources().toArray();
+		
+		if ( datasources.length > 0 ){
+			
+			canEnable = true;
+		}
+
+		list.put( "start", canEnable ? UIToolBarItem.STATE_ENABLED : 0);
+		list.put( "startstop", canEnable ? UIToolBarItem.STATE_ENABLED : 0);
+		
+		list.put( "remove", canEnable ? UIToolBarItem.STATE_ENABLED : 0);
+	}
+
+	public void 
+	updateUI() 
+	{
+		if (tv != null) {
+			
+			tv.refreshTable(false);
+		}
+	}
+
+	public String 
+	getUpdateUIName() 
+	{
+		return( TABLE_NAME );
+	}
+	
+	public void 
+	addThisColumnSubMenu(
+		String 		columnName, 
+		Menu 		menuThisColumn ) 
+	{
+	}
+	
+	public void 
+	fillMenu(
+		String 	sColumnName, 
+		Menu 	menu )
+	{
+		List<Object>	ds = tv.getSelectedDataSources();
+		
+		final List<DownloadStub>	dms = new ArrayList<DownloadStub>( ds.size());
+		
+		for ( Object o: ds ){
+			
+			dms.add((DownloadStub)o);
+		}
+		
+		boolean	hasSelection = dms.size() > 0;
+		
+			// Explore (or open containing folder)
+		
+		final boolean use_open_containing_folder = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled");
+		
+		final MenuItem itemExplore = new MenuItem(menu, SWT.PUSH);
+		
+		Messages.setLanguageText(itemExplore, "MyTorrentsView.menu."
+				+ (use_open_containing_folder ? "open_parent_folder" : "explore"));
+		
+		itemExplore.addListener(SWT.Selection, new Listener() {
+			public void 
+			handleEvent(
+				Event event) 
+			{
+				for ( DownloadStub download: dms ){
+				
+					ManagerUtils.open( new File( download.getSavePath()), use_open_containing_folder);
+				}
+			}
+		});
+		
+		itemExplore.setEnabled(hasSelection);
+		
+		new MenuItem( menu, SWT.SEPARATOR );
+		
+		final MenuItem itemRestore = new MenuItem(menu, SWT.PUSH);
+		
+		Messages.setLanguageText(itemRestore, "MyTorrentsView.menu.restore");
+		
+		itemRestore.addListener(
+			SWT.Selection, 
+			new Listener()
+			{
+				public void 
+				handleEvent(
+					Event event) 
+				{
+					ManagerUtils.restoreFromArchive( dms,false, null );				
+				}
+			});
+		
+		itemRestore.setEnabled( hasSelection );
+		
+		final MenuItem itemRestoreAnd = new MenuItem(menu, SWT.PUSH);
+		
+		Messages.setLanguageText(itemRestoreAnd, "MyTorrentsView.menu.restore.and");
+		
+		itemRestoreAnd.addListener(
+			SWT.Selection, 
+			new Listener()
+			{
+				public void 
+				handleEvent(
+					Event event) 
+				{
+					ManagerUtils.restoreFromArchive( 
+						dms, 
+						false, 
+						new ArchiveCallback()
+						{
+							private List<DownloadManager>	targets = new ArrayList<DownloadManager>();
+							
+							@Override
+							public void 
+							success(
+								final DownloadStub source,
+								final DownloadStub target) 
+							{
+								DownloadManager dm = PluginCoreUtils.unwrap((Download)target);
+								
+								if ( dm != null ){
+									
+									targets.add( dm );
+								}
+							}
+							
+							@Override
+							public void 
+							completed() 
+							{
+								Utils.execSWTThread(
+									new Runnable() 
+									{
+										public void 
+										run()
+										{
+											if ( targets.size() == 0 ){
+												
+												return;
+											}
+											
+											final Menu menu = new Menu( table_parent );
+											
+											DownloadManager[] dm_list = targets.toArray( new DownloadManager[ dms.size()]);
+											
+											TorrentUtil.fillTorrentMenu(
+												menu, dm_list, AzureusCoreFactory.getSingleton(), table_parent, true, 0, tv);
+											
+											menu.addMenuListener(
+												new MenuListener() {
+													
+													public void 
+													menuShown(
+														MenuEvent e) 
+													{
+													}
+													
+													public void 
+													menuHidden(
+														MenuEvent e) 
+													{
+														Utils.execSWTThreadLater(
+															1,
+															new Runnable() 
+															{
+																public void 
+																run() 
+																{
+																	menu.dispose();
+																}
+															});
+													}
+												});
+											
+											menu.setVisible( true );
+										}
+									});
+							}
+						});
+				}
+			});
+		
+		itemRestoreAnd.setEnabled( hasSelection );
+		
+		new MenuItem( menu, SWT.SEPARATOR );
+	}
+	
+	public void 
+	selected(
+		TableRowCore[] row )
+	{
+		UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+		
+		if ( uiFunctions != null ){
+			
+			uiFunctions.refreshIconBar();
+		}
+	}
+
+	public void 
+	deselected(
+		TableRowCore[] rows )
+	{
+	  	UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+	  	
+	  	if ( uiFunctions != null ){
+	  		
+	  		uiFunctions.refreshIconBar();
+	  	}
+	}
+	
+	public void 
+	focusChanged(
+		TableRowCore focus )
+	{
+	  	UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+	  	
+	  	if ( uiFunctions != null ){
+	  		
+	  		uiFunctions.refreshIconBar();
+	  	}
+	}
+
+	public void 
+	defaultSelected(
+		TableRowCore[] 	rows, 
+		int 			stateMask )
+	{
+		if ( rows.length == 1 ){
+			
+			Object obj = rows[0].getDataSource();
+
+		}
+	}
+
+	public void
+	downloadStubEventOccurred(
+		DownloadStubEvent		event )
+	
+		throws DownloadException
+	{
+		int type = event.getEventType();
+		
+		List<DownloadStub> dls = event.getDownloadStubs();
+				
+		if ( type == DownloadStubEvent.DSE_STUB_ADDED ){
+			
+			tv.addDataSources( dls.toArray( new DownloadStub[dls.size()] ));
+						
+		}else if ( type == DownloadStubEvent.DSE_STUB_REMOVED ){
+			
+			tv.removeDataSources( dls.toArray( new DownloadStub[dls.size()] ));
+		}
+	}
+	
+	public void 
+	mouseEnter(
+		TableRowCore row )
+	{
+	}
+
+	public void 
+	mouseExit(
+		TableRowCore row)
+	{	
+	}
+	
+	public void 
+	filterSet(
+		String filter) 
+	{
+	}
+	
+	public boolean 
+	filterCheck(
+		DownloadStub 	ds, 
+		String 			filter, 
+		boolean 		regex) 
+	{
+		if ( filter.toLowerCase( Locale.US ).startsWith( "f:" )){
+			
+			filter = filter.substring(2).trim();
+					
+			DownloadStubFile[] files = ds.getStubFiles();
+			
+			String s = regex ? filter : "\\Q" + filter.replaceAll("\\s*[|;]\\s*", "\\\\E|\\\\Q") + "\\E";
+			
+			boolean	match_result = true;
+			
+			if ( regex && s.startsWith( "!" )){
+				
+				s = s.substring(1);
+				
+				match_result = false;
+			}
+			
+			Pattern pattern = RegExUtil.getCachedPattern( "archiveview:search", s, Pattern.CASE_INSENSITIVE);
+
+			
+			boolean result = !match_result;
+			
+		
+			for ( DownloadStubFile file: files ){
+				
+				String name = file.getFile().getName();
+				
+				if ( pattern.matcher( name ).find()){
+				
+					result = match_result;
+						
+					break;
+				}
+			}
+			
+			return( result );
+			
+		}else{
+			
+			String name = ds.getName();
+			
+			String s = regex ? filter : "\\Q" + filter.replaceAll("\\s*[|;]\\s*", "\\\\E|\\\\Q") + "\\E";
+			
+			boolean	match_result = true;
+			
+			if ( regex && s.startsWith( "!" )){
+				
+				s = s.substring(1);
+				
+				match_result = false;
+			}
+			
+			Pattern pattern = RegExUtil.getCachedPattern( "archiveview:search", s, Pattern.CASE_INSENSITIVE);
+	
+			return( pattern.matcher(name).find() == match_result );
+		}
+	}
+
+	public Object 
+	dataSourceChanged(
+		SWTSkinObject 	skinObject, 
+		Object 			params) 
+	{
+		if ( params instanceof DownloadStub ){
+			
+			if (tv != null) {
+				
+				TableRowCore row = tv.getRow((DownloadStub) params);
+				
+				if ( row != null ){
+					
+					tv.setSelectedRows(new TableRowCore[] { row });
+				}
+			}
+		}
+		
+		datasource = params;
+		
+		return( null );
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_BurnFTUX.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_BurnFTUX.java
index 59caec6..ff3ec95 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_BurnFTUX.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_BurnFTUX.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_GenericBrowsePage.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_GenericBrowsePage.java
index f69fcce..23448d4 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_GenericBrowsePage.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_GenericBrowsePage.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 13, 2010
  *
- * Copyright 2010 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView.java
index 51a244d..7743b7b 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 3, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -18,6 +20,7 @@
 
 package com.aelitis.azureus.ui.swt.views.skin;
 
+import java.util.Locale;
 import java.util.Map;
 
 import org.eclipse.swt.SWT;
@@ -25,11 +28,11 @@ import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Text;
-
 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.torrent.TOTorrent;
+import org.gudy.azureus2.core3.torrent.TOTorrentFile;
 import org.gudy.azureus2.core3.util.AERunnable;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
@@ -55,7 +58,6 @@ import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.AzureusCoreRunningListener;
 import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
-import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.common.table.TableColumnCore;
@@ -63,6 +65,7 @@ import com.aelitis.azureus.ui.common.table.TableRowCore;
 import com.aelitis.azureus.ui.common.table.TableSelectionAdapter;
 import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdatable;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.ISelectedVuzeFileContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
@@ -222,7 +225,9 @@ public class SBC_LibraryTableView
 		}
 
 		try {
-			view = new UISWTViewImpl(UISWTInstance.VIEW_MAIN, ID + torrentFilterMode, swtViewListener, data);
+			view = new UISWTViewImpl(ID + torrentFilterMode, UISWTInstance.VIEW_MAIN, false);
+			view.setDatasource(data);
+			view.setEventListener(swtViewListener, true);
 		} catch (Exception e) {
 			Debug.out(e);
 		}
@@ -291,41 +296,82 @@ public class SBC_LibraryTableView
 		String mode = COConfigurationManager.getStringParameter("list.dm.dblclick");
 		if (mode.equals("1")) {
 			// OMG! Show Details! I <3 you!
-			DownloadManager dm = DataSourceUtils.getDM(ds);
-			if (dm != null) {
-				UIFunctionsManager.getUIFunctions().openView(UIFunctions.VIEW_DM_DETAILS, dm);
-				return;
-			}
-			DiskManagerFileInfo file = DataSourceUtils.getFileInfo(ds);
-			if (file != null) {
-				UIFunctionsManager.getUIFunctions().openView(UIFunctions.VIEW_DM_DETAILS, file.getDownloadManager());
+			if ( UIFunctionsManager.getUIFunctions().getMDI().showEntryByID( MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_DETAILS, ds)){
+			
 				return;
 			}
 		}else if (mode.equals("2")) {
 			// Show in explorer
-			DownloadManager dm = DataSourceUtils.getDM(ds);
-			if (dm != null) {
-				boolean openMode = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled");
-				ManagerUtils.open(dm, openMode);
-				return;
-			}
+			boolean openMode = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled");
 			DiskManagerFileInfo file = DataSourceUtils.getFileInfo(ds);
 			if (file != null) {
-				boolean openMode = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled");
 				ManagerUtils.open(file, openMode);
 				return;
 			}
-		}else if (mode.equals("3")) {
-			// Launch
 			DownloadManager dm = DataSourceUtils.getDM(ds);
 			if (dm != null) {
-				TorrentUtil.runDataSources(new Object[]{ dm });
+				ManagerUtils.open(dm, openMode);
 				return;
 			}
-			DiskManagerFileInfo file = DataSourceUtils.getFileInfo(ds);
-			if (file != null) {
-				TorrentUtil.runDataSources(new Object[]{ file });
-				return;
+		}else{
+			
+			boolean webInBrowser = COConfigurationManager.getBooleanParameter( "Library.LaunchWebsiteInBrowser" );
+			
+			if ( webInBrowser ){
+				
+				DiskManagerFileInfo fileInfo = DataSourceUtils.getFileInfo(ds);
+				
+				if ( fileInfo != null ){
+					
+					if ( ManagerUtils.browseWebsite( fileInfo )){
+						
+						return;
+					}
+				}else{
+				
+					DownloadManager dm = DataSourceUtils.getDM( ds);
+					
+					if ( dm != null ){
+						
+						if ( ManagerUtils.browseWebsite( dm )){
+							
+							return;
+						}
+					}
+				}
+			}
+			
+			if (mode.equals("3") || mode.equals("4")){
+		
+				// Launch
+				DiskManagerFileInfo file = DataSourceUtils.getFileInfo(ds);
+				if (file != null) {
+					if (	mode.equals("4") &&
+							file.getDownloaded() == file.getLength() &&
+							Utils.isQuickViewSupported( file )){
+						
+						Utils.setQuickViewActive( file, true );
+					}else{
+						TorrentUtil.runDataSources(new Object[]{ file });
+					}
+					return;
+				}
+				DownloadManager dm = DataSourceUtils.getDM(ds);
+				if (dm != null) {
+					TorrentUtil.runDataSources(new Object[]{ dm });
+					return;
+				}
+			}else if (mode.equals("5")) {
+				DiskManagerFileInfo fileInfo = DataSourceUtils.getFileInfo(ds);
+				if ( fileInfo != null ){
+					ManagerUtils.browse( fileInfo );
+					return;
+				}
+				DownloadManager dm = DataSourceUtils.getDM(ds);
+				if (dm != null) {
+					ManagerUtils.browse( dm );
+					return;
+				}
 			}
 		}
 		
@@ -335,13 +381,13 @@ public class SBC_LibraryTableView
 		
 			// fallback
 		
-		if (PlayUtils.canPlayDS(ds, -1) || (stateMask & SWT.CONTROL) != 0) {
+		if (PlayUtils.canPlayDS(ds, -1,true) || (stateMask & SWT.CONTROL) != 0) {
 			TorrentListViewsUtils.playOrStreamDataSource(ds,
 					DLReferals.DL_REFERAL_DBLCLICK, false, true );
 			return;
 		}
 
-		if (PlayUtils.canStreamDS(ds, -1)) {
+		if (PlayUtils.canStreamDS(ds, -1,true)) {
 			TorrentListViewsUtils.playOrStreamDataSource(ds,
 					DLReferals.DL_REFERAL_DBLCLICK, true, false );
 			return;
@@ -404,6 +450,9 @@ public class SBC_LibraryTableView
 		return super.skinObjectHidden(skinObject, params);
 	}
 
+	/* (non-Javadoc)
+	 * @see org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener#refreshToolBarItems(java.util.Map)
+	 */
 	public void refreshToolBarItems(Map<String, Long> list) {
 		if (!isVisible()) {
 			return;
@@ -421,14 +470,14 @@ public class SBC_LibraryTableView
 				has1Selection
 						&& (!(currentContent[0] instanceof ISelectedVuzeFileContent))
 						&& PlayUtils.canPlayDS(currentContent[0],
-								currentContent[0].getFileIndex())
+								currentContent[0].getFileIndex(),false)
 						? UIToolBarItem.STATE_ENABLED : 0);
 		list.put(
 				"stream",
 				has1Selection
 						&& (!(currentContent[0] instanceof ISelectedVuzeFileContent))
 						&& PlayUtils.canStreamDS(currentContent[0],
-								currentContent[0].getFileIndex())
+								currentContent[0].getFileIndex(),false)
 						? UIToolBarItem.STATE_ENABLED : 0);
 	}
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView_Big.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView_Big.java
index 4f58209..d4c8a6d 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView_Big.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryTableView_Big.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.views.skin;
 
 import com.aelitis.azureus.ui.common.table.TableColumnCore;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryView.java
index 5753a04..db29587 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_LibraryView.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jul 2, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -18,8 +20,8 @@
 
 package com.aelitis.azureus.ui.swt.views.skin;
 
+import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Locale;
 import java.util.Map;
 
 import org.eclipse.swt.events.PaintEvent;
@@ -30,9 +32,9 @@ import org.eclipse.swt.widgets.Control;
 import org.gudy.azureus2.core3.category.Category;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.config.ParameterListener;
-import org.gudy.azureus2.core3.disk.DiskManager;
 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.download.DownloadManagerStats;
 import org.gudy.azureus2.core3.internat.MessageText;
 import org.gudy.azureus2.core3.stats.transfer.OverallStats;
 import org.gudy.azureus2.core3.stats.transfer.StatsFactory;
@@ -40,14 +42,12 @@ 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.core3.util.SimpleTimer;
-import org.gudy.azureus2.core3.util.SystemTime;
 import org.gudy.azureus2.core3.util.TimeFormatter;
 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.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.ui.*;
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarEnablerBase;
 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
 import org.gudy.azureus2.ui.swt.Utils;
@@ -58,6 +58,7 @@ import com.aelitis.azureus.core.AzureusCore;
 import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.core.AzureusCoreRunningListener;
 import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagType;
 import com.aelitis.azureus.ui.InitializerListener;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.ToolBarItem;
@@ -107,12 +108,16 @@ public class SBC_LibraryView
 	};
 
 	private static boolean	header_show_uptime;
+	private static boolean	header_show_rates;
 	
 	private static volatile OverallStats 	totalStats;
-	private static volatile int				selection_count;
-	private static volatile long			selection_size;
-	private static volatile long			selection_done;
 	
+	private static volatile int					selection_count;
+	private static volatile long				selection_size;
+	private static volatile long				selection_done;
+	private static volatile DownloadManager[]	selection_dms = {};
+	
+
 	static{
 		SimpleTimer.addPeriodicEvent(
 			"SBLV:updater",
@@ -130,19 +135,52 @@ public class SBC_LibraryView
 				}
 			});
 		
-		header_show_uptime = COConfigurationManager.getBooleanParameter( "MyTorrentsView.showuptime" );
-		
-		COConfigurationManager.addParameterListener( 
-			"MyTorrentsView.showuptime",
+		COConfigurationManager.addAndFireParameterListeners(
+			new String[]{
+				"MyTorrentsView.showuptime", "MyTorrentsView.showrates"
+			},
 			new ParameterListener()
 			{
+				private TimerEventPeriodic rate_event;
+				
 				public void 
 				parameterChanged(
 					String name ) 
 				{
-					header_show_uptime = COConfigurationManager.getBooleanParameter( "MyTorrentsView.showuptime" );
+					header_show_uptime 	= COConfigurationManager.getBooleanParameter( "MyTorrentsView.showuptime" );
+					header_show_rates	= COConfigurationManager.getBooleanParameter( "MyTorrentsView.showrates" );
 
 					SB_Transfers.triggerCountRefreshListeners();
+					
+					synchronized( this ){
+						
+						if ( header_show_rates ){
+							
+							if ( rate_event == null ){
+							
+								rate_event = SimpleTimer.addPeriodicEvent(
+									"SBLV:rate-updater",
+									1*1000,
+									new TimerEventPerformer()
+									{
+										public void 
+										perform(
+											TimerEvent event ) 
+										{
+											SB_Transfers.triggerCountRefreshListeners();
+										}
+									});
+							}
+						}else{
+							
+							if ( rate_event != null ){
+								
+								rate_event.cancel();
+								
+								rate_event = null;
+							}
+						}
+					}
 				}
 			});
 		
@@ -170,12 +208,16 @@ public class SBC_LibraryView
 					long	total_size 	= 0;
 					long	total_done	= 0;
 					
+					ArrayList<DownloadManager>	dms = new ArrayList<DownloadManager>( currentContent.length );
+					
 					for ( ISelectedContent sc: currentContent ){
 						
 						DownloadManager dm = sc.getDownloadManager();
 						
 						if ( dm != null ){
 							
+							dms.add( dm );
+							
 							int	file_index = sc.getFileIndex();
 							
 							if ( file_index == -1 ){
@@ -206,6 +248,8 @@ public class SBC_LibraryView
 					selection_size	= total_size;
 					selection_done	= total_done;
 					
+					selection_dms	= dms.toArray( new DownloadManager[ dms.size()]);
+					
 					SB_Transfers.triggerCountRefreshListeners();
 				}
 			});
@@ -283,7 +327,7 @@ public class SBC_LibraryView
 		} else if (torrentFilterMode == TORRENTS_UNOPENED) {
 			entryID = SideBar.SIDEBAR_SECTION_LIBRARY_UNOPENED;
 		}
-
+		
 		if (entryID != null) {
 			MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
 			currentEntry = mdi.getEntry(entryID);
@@ -333,7 +377,6 @@ public class SBC_LibraryView
 										public void
 										update(
 											Composite	reporter,
-											boolean		seeding_view,
 											int			count,
 											int			active )
 										{
@@ -359,7 +402,6 @@ public class SBC_LibraryView
 										public void
 										setEnabled(
 											Composite	reporter,
-											boolean		seeding_view,
 											boolean		enabled )
 										{
 											ExtraInfoProvider	provider = getProvider( reporter );
@@ -429,18 +471,12 @@ public class SBC_LibraryView
 							
 							String s;
 							
-							if (torrentFilterMode == TORRENTS_INCOMPLETE) {
-								String id = "library.incomplete.header";
-								if (stats.numDownloading != 1) {
-									id += ".p";
-								}
-								s = MessageText.getString(id,
-										new String[] {
-										String.valueOf(stats.numDownloading),
-										String.valueOf(stats.numIncomplete - stats.numDownloading),
-								});
+								// seeding and downloading Tag views were changed to filter appropriately
+								// but that broke the header display - fixed by forcing through the 'TORRENTS_ALL'
+								// leg for Tag based views
+							
+							if ( torrentFilterMode == TORRENTS_ALL || (datasource instanceof Tag)){
 								
-							} else if (torrentFilterMode == TORRENTS_ALL) {
 								if (datasource instanceof Category) {
 									Category cat = (Category) datasource;
 
@@ -481,7 +517,20 @@ public class SBC_LibraryView
 												"label.num_queued", new String[]{ String.valueOf( stats.numQueued )});
 									}
 								}
-							} else if (torrentFilterMode == TORRENTS_UNOPENED) {
+								
+							}else if (torrentFilterMode == TORRENTS_INCOMPLETE) {
+								String id = "library.incomplete.header";
+								if (stats.numDownloading != 1) {
+									id += ".p";
+								}
+								s = MessageText.getString(id,
+										new String[] {
+										String.valueOf(stats.numDownloading),
+										String.valueOf(stats.numIncomplete - stats.numDownloading),
+								});
+								
+							} else if ( torrentFilterMode == TORRENTS_UNOPENED ||  torrentFilterMode == TORRENTS_COMPLETE ) {
+									// complete filtering currently uses same display text as unopened
 								String id = "library.unopened.header";
 								if (stats.numUnOpened != 1) {
 									id += ".p";
@@ -532,16 +581,65 @@ public class SBC_LibraryView
 										MessageText.getString(
 										"label.num_selected", new String[]{ String.valueOf( selection_count )});
 								
+								String	size_str = null;
+								String	rate_str = null;
+								
 								if ( selection_size > 0 ){
 									
 									if ( selection_size == selection_done ){
 										
-										s += " (" + DisplayFormatters.formatByteCountToKiBEtc( selection_size ) + ")";
+										size_str = DisplayFormatters.formatByteCountToKiBEtc( selection_size );
+										
 									}else{
-										s += " (" + DisplayFormatters.formatByteCountToKiBEtc( selection_done ) + "/" + DisplayFormatters.formatByteCountToKiBEtc( selection_size ) + ")";
+										
+										size_str = DisplayFormatters.formatByteCountToKiBEtc( selection_done ) + "/" + DisplayFormatters.formatByteCountToKiBEtc( selection_size );
 
 									}
 								}
+								
+								DownloadManager[] dms = selection_dms;
+								
+								if ( header_show_rates && dms.length > 1 ){
+										
+									long	total_data_up 		= 0;
+									long	total_prot_up 		= 0;
+									long	total_data_down		= 0;
+									long	total_prot_down		= 0;
+									
+									for ( DownloadManager dm: dms ){
+										
+										DownloadManagerStats dm_stats = dm.getStats();
+										
+										total_prot_up += dm_stats.getProtocolSendRate();
+										total_data_up += dm_stats.getDataSendRate();
+										total_prot_down += dm_stats.getProtocolReceiveRate();
+										total_data_down += dm_stats.getDataReceiveRate();
+									}
+								
+									rate_str = 
+											MessageText.getString( "ConfigView.download.abbreviated") + DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(total_data_down, total_prot_down) + " " +
+											MessageText.getString( "ConfigView.upload.abbreviated") + DisplayFormatters.formatDataProtByteCountToKiBEtcPerSec(total_data_up, total_prot_up);
+								}
+								
+								if ( size_str != null || rate_str != null ){
+									
+									String temp;
+									
+									if ( size_str == null ){
+									
+										temp = rate_str;
+										
+									}else if ( rate_str == null ){
+										
+										temp = size_str;
+										
+									}else{
+										
+										temp = size_str + "; " + rate_str;
+									}
+									
+									s += " (" + temp + ")";
+								}
 							}
 
 							if ( header_show_uptime && totalStats != null ){
@@ -562,7 +660,10 @@ public class SBC_LibraryView
 								}
 								
 								String up_str = TimeFormatter.format2( up_secs, false );
-																
+									
+								if ( s.equals( "" )){
+									Debug.out( "eh" );
+								}
 								s += "; " + 
 									MessageText.getString(
 										"label.uptime_coarse",
@@ -668,6 +769,19 @@ public class SBC_LibraryView
 		} else if (torrentFilter.equalsIgnoreCase(SideBar.SIDEBAR_SECTION_LIBRARY_UNOPENED)) {
 			torrentFilterMode = TORRENTS_UNOPENED;
 		}
+		
+		if (datasource instanceof Tag) {
+			Tag tag = (Tag) datasource;
+			TagType tagType = tag.getTagType();
+			if (tagType.getTagType() == TagType.TT_DOWNLOAD_STATE) {
+				int tagID = tag.getTagID(); // see GlobalManagerImp.tag_*
+				if (tagID == 1 || tagID == 3 || tagID == 11) {
+					torrentFilterMode = TORRENTS_INCOMPLETE;
+				} else if (tagID == 2 || tagID == 4 || tagID == 10) {
+					torrentFilterMode = TORRENTS_COMPLETE;
+				}
+			}
+		}
 
 		soListArea = getSkinObject(ID + "-area");
 
@@ -751,8 +865,12 @@ public class SBC_LibraryView
 	public Object dataSourceChanged(SWTSkinObject skinObject, Object params) {
 		datasource = params;
 		if (soListArea != null) {
-  		soListArea.getControl().setData("DataSource",
-  				params);
+			Control control = soListArea.getControl();
+  		
+			if ( !control.isDisposed()){
+			
+				control.setData("DataSource", params);
+			}
 		}
 		
 		return null;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_PlusFTUX.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_PlusFTUX.java
index 2853b86..9d865af 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_PlusFTUX.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_PlusFTUX.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TagDiscovery.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TagDiscovery.java
new file mode 100644
index 0000000..9c677cd
--- /dev/null
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TagDiscovery.java
@@ -0,0 +1,582 @@
+/**
+ * Created on Oct 3, 2014
+ *
+ * Copyright (C) Azureus Software, 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.views.skin;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.global.GlobalManager;
+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.util.*;
+import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
+import org.gudy.azureus2.plugins.ui.tables.TableColumn;
+import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener;
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
+import org.gudy.azureus2.ui.swt.Messages;
+import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.views.table.TableSelectedRowsListener;
+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.TableViewFactory;
+import org.gudy.azureus2.ui.swt.views.table.utils.TableColumnCreator;
+import org.gudy.azureus2.ui.swt.views.tableitems.ColumnDateSizer;
+
+import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreFactory;
+import com.aelitis.azureus.core.AzureusCoreRunningListener;
+import com.aelitis.azureus.core.content.ContentException;
+import com.aelitis.azureus.core.content.RelatedAttributeLookupListener;
+import com.aelitis.azureus.core.content.RelatedContentManager;
+import com.aelitis.azureus.core.tag.*;
+import com.aelitis.azureus.ui.common.ToolBarItem;
+import com.aelitis.azureus.ui.common.table.*;
+import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
+import com.aelitis.azureus.ui.common.updater.UIUpdatable;
+import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
+import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager;
+import com.aelitis.azureus.ui.mdi.MdiEntry;
+import com.aelitis.azureus.ui.mdi.MdiEntryVitalityImage;
+import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
+import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
+import com.aelitis.azureus.ui.swt.columns.tag.ColumnTagName;
+import com.aelitis.azureus.ui.swt.columns.tagdiscovery.*;
+import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter;
+import com.aelitis.azureus.ui.swt.skin.*;
+
+/**
+ * @author TuxPaper
+ */
+public class SBC_TagDiscovery
+	extends SkinView
+	implements UIUpdatable, UIPluginViewToolBarListener,
+	TableViewFilterCheck<TagDiscovery>, TableViewSWTMenuFillListener,
+	TableSelectionListener, ViewTitleInfo
+{
+
+	private static final String TABLE_TAGDISCOVERY = "TagDiscoveryView";
+
+	private static final boolean DEBUG = false;
+
+	private static final String CONFIG_FILE = "tag-discovery.config";
+
+	private static final String ID_VITALITY_ACTIVE = "image.sidebar.vitality.dots";
+
+	TableViewSWT<TagDiscovery> tv;
+
+	private Text txtFilter;
+
+	private Composite table_parent;
+
+	private boolean columnsAdded = false;
+
+	private int scansRemaining = 0;
+
+	private AEMonitor2 mon_scansRemaining = new AEMonitor2("scansRemaining");
+
+	private Map<String, TagDiscovery> mapTagDiscoveries = new HashMap<String, TagDiscovery>();
+
+	private MdiEntry entry;
+
+	private SWTSkinObjectText soTitle;
+
+	private MdiEntryVitalityImage vitalityImage;
+
+	private Map mapConfig;
+
+	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener#toolBarItemActivated(com.aelitis.azureus.ui.common.ToolBarItem, long, java.lang.Object)
+	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
+			Object datasource) {
+		if (tv == null || !tv.isVisible()) {
+			return (false);
+		}
+		if (item.getID().equals("remove")) {
+
+			Object[] datasources = tv.getSelectedDataSources().toArray();
+
+			if (datasources.length > 0) {
+
+				for (Object object : datasources) {
+					if (object instanceof TagDiscovery) {
+						TagDiscovery discovery = (TagDiscovery) object;
+
+					}
+				}
+
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	// @see com.aelitis.azureus.ui.common.table.TableViewFilterCheck#filterSet(java.lang.String)
+	public void filterSet(String filter) {
+	}
+
+	// @see org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener#refreshToolBarItems(java.util.Map)
+	public void refreshToolBarItems(Map<String, Long> list) {
+		if (tv == null || !tv.isVisible()) {
+			return;
+		}
+
+		list.put("remove", tv.getSelectedDataSources().size() > 0
+				? UIToolBarItem.STATE_ENABLED : 0);
+	}
+
+	// @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI()
+	public void updateUI() {
+		if (tv != null) {
+			tv.refreshTable(false);
+		}
+	}
+
+	// @see com.aelitis.azureus.ui.common.updater.UIUpdatable#getUpdateUIName()
+	public String getUpdateUIName() {
+		return TABLE_TAGDISCOVERY;
+	}
+
+	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectInitialShow(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
+	public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) {
+
+		mapConfig = FileUtil.readResilientConfigFile(CONFIG_FILE);
+
+		soTitle = (SWTSkinObjectText) getSkinObject("title");
+
+		SWTSkinObjectButton soScanButton = (SWTSkinObjectButton) getSkinObject("scan-button");
+		if (soScanButton != null) {
+			soScanButton.addSelectionListener(new ButtonListenerAdapter() {
+				// @see com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter#pressed(com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility, com.aelitis.azureus.ui.swt.skin.SWTSkinObject, int)
+				public void pressed(SWTSkinButtonUtility buttonUtility,
+						SWTSkinObject skinObject, int stateMask) {
+					startScan();
+				}
+			});
+		}
+		
+		final SWTSkinObject soFilterArea = getSkinObject("filterarea");
+		if (soFilterArea != null) {
+			
+			SWTSkinObjectToggle soFilterButton = (SWTSkinObjectToggle) getSkinObject("filter-button");
+			if (soFilterButton != null) {
+				soFilterButton.addSelectionListener(new SWTSkinToggleListener() {
+					public void toggleChanged(SWTSkinObjectToggle so, boolean toggled) {
+						soFilterArea.setVisible(toggled);
+						Utils.relayout(soFilterArea.getControl().getParent());
+					}
+				});
+			}
+			
+		}
+
+
+		MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
+
+		if (mdi != null) {
+			entry = mdi.getEntry(MultipleDocumentInterface.SIDEBAR_SECTION_TAG_DISCOVERY);
+			if (entry != null) {
+				entry.setViewTitleInfo(this);
+				vitalityImage = entry.addVitalityImage(ID_VITALITY_ACTIVE);
+				if ( vitalityImage != null ){
+					vitalityImage.setVisible(false);
+				}
+			}
+		}
+
+		initColumns();
+
+		return null;
+	}
+
+	public Object getTitleInfoProperty(int propertyID) {
+		if (propertyID == ViewTitleInfo.TITLE_INDICATOR_TEXT) {
+			int num = mapTagDiscoveries.size();
+			if (num > 0) {
+				return "" + num;
+			}
+		}
+		return null;
+	}
+
+	protected void initColumns() {
+		synchronized (SBC_TagDiscovery.class) {
+
+			if (columnsAdded) {
+
+				return;
+			}
+
+			columnsAdded = true;
+		}
+
+		TableColumnManager tableManager = TableColumnManager.getInstance();
+
+		tableManager.registerColumn(TagDiscovery.class,
+				ColumnTagDiscoveryName.COLUMN_ID, new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnTagDiscoveryName(column);
+					}
+				});
+		tableManager.registerColumn(TagDiscovery.class,
+				ColumnTagDiscoveryTorrent.COLUMN_ID, new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnTagDiscoveryTorrent(column);
+					}
+				});
+		tableManager.registerColumn(TagDiscovery.class,
+				ColumnTagDiscoveryAddedOn.COLUMN_ID,
+				new TableColumnCoreCreationListener() {
+					public TableColumnCore createTableColumnCore(
+							Class<?> forDataSourceType, String tableID, String columnID) {
+						return new ColumnDateSizer(TagDiscovery.class, columnID,
+								TableColumnCreator.DATE_COLUMN_WIDTH, tableID) {
+						};
+					}
+
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnTagDiscoveryAddedOn(column);
+					}
+				});
+		tableManager.registerColumn(TagDiscovery.class,
+				ColumnTagDiscoveryNetwork.COLUMN_ID, new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnTagDiscoveryNetwork(column);
+					}
+				});
+
+		tableManager.setDefaultColumnNames(TABLE_TAGDISCOVERY, new String[] {
+			ColumnTagDiscoveryName.COLUMN_ID,
+			ColumnTagDiscoveryTorrent.COLUMN_ID,
+			ColumnTagDiscoveryAddedOn.COLUMN_ID,
+		});
+
+		tableManager.setDefaultSortColumnName(TABLE_TAGDISCOVERY,
+				ColumnTagDiscoveryAddedOn.COLUMN_ID);
+	}
+
+	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectHidden(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
+	public Object skinObjectHidden(SWTSkinObject skinObject, Object params) {
+
+		if (mapConfig != null) {
+			FileUtil.writeResilientConfigFile(CONFIG_FILE, mapConfig);
+		}
+
+		if (tv != null) {
+
+			tv.delete();
+
+			tv = null;
+		}
+
+		Utils.disposeSWTObjects(new Object[] {
+			table_parent,
+		});
+
+		return super.skinObjectHidden(skinObject, params);
+	}
+
+	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectShown(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
+	public Object skinObjectShown(SWTSkinObject skinObject, Object params) {
+		super.skinObjectShown(skinObject, params);
+		SWTSkinObject so_list = getSkinObject("tag-discovery-list");
+
+		if (so_list != null) {
+			initTable((Composite) so_list.getControl());
+		} else {
+			System.out.println("NO tag-discovery-list");
+			return null;
+		}
+
+		if (tv == null) {
+			return null;
+		}
+
+		TagDiscovery[] tagDiscoveries = mapTagDiscoveries.values().toArray(
+				new TagDiscovery[0]);
+		tv.addDataSources(tagDiscoveries);
+
+		return null;
+	}
+
+	private void startScan() {
+		try {
+			mon_scansRemaining.enter();
+
+			if (scansRemaining > 0) {
+				return;
+			}
+		} finally {
+			mon_scansRemaining.exit();
+		}
+
+		AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
+			public void azureusCoreRunning(AzureusCore core) {
+				GlobalManager gm = core.getGlobalManager();
+				try {
+					try {
+						mon_scansRemaining.enter();
+
+						scansRemaining = 0;
+					} finally {
+						mon_scansRemaining.exit();
+					}
+
+					RelatedContentManager rcm = RelatedContentManager.getSingleton();
+					List<DownloadManager> dms = gm.getDownloadManagers();
+
+					for (final DownloadManager dm : dms) {
+						if ( tv == null ){
+							return;
+						}
+						TOTorrent torrent = dm.getTorrent();
+						if (torrent == null) {
+							continue;
+						}
+						try {
+							final byte[] hash = torrent.getHash();
+							try {
+								mon_scansRemaining.enter();
+
+								scansRemaining++;
+
+								if (vitalityImage != null && scansRemaining == 1) {
+									vitalityImage.setVisible(true);
+								}
+
+								if (soTitle != null) {
+									soTitle.setText(MessageText.getString("tag.discovery.view.heading")
+											+ " : Scanning " + scansRemaining);
+								}
+							} finally {
+								mon_scansRemaining.exit();
+							}
+
+							try {
+								rcm.lookupAttributes(hash, dm.getDownloadState().getNetworks(),
+										new RelatedAttributeLookupListener() {
+											public void tagFound(String tag, String network) {
+												if (DEBUG) {
+													System.out.println("Tag Search: Found Tag " + tag
+															+ " for " + dm.getDisplayName());
+												}
+												if ( tv == null ){
+													return;
+												}
+												String key = Base32.encode(hash) + tag;
+
+												TagManager tm = TagManagerFactory.getTagManager();
+												TagType tt_manual = tm.getTagType(TagType.TT_DOWNLOAD_MANUAL);
+												List<Tag> existingDMTags = tt_manual.getTagsForTaggable(dm);
+												for (Tag existingTag : existingDMTags) {
+													if (existingTag.getTagName(true).equalsIgnoreCase(tag)) {
+														return;
+													}
+												}
+												synchronized (mapTagDiscoveries) {
+													if (!mapTagDiscoveries.containsKey(key)) {
+														TagDiscovery tagDiscovery = new TagDiscovery(tag,
+																network, dm.getDisplayName(), hash);
+														mapTagDiscoveries.put(key, tagDiscovery);
+														ViewTitleInfoManager.refreshTitleInfo(SBC_TagDiscovery.this);
+														tv.addDataSource(tagDiscovery);
+
+													}
+												}
+											}
+
+											public void lookupStart() {
+												if (DEBUG) {
+													System.out.println("Tag Search: Start" + " for "
+															+ dm.getDisplayName());
+												}
+											}
+
+											public void lookupFailed(ContentException error) {
+												if (DEBUG) {
+													System.out.println("Tag Search: Failed "
+															+ error.getMessage() + " for "
+															+ dm.getDisplayName());
+												}
+											}
+
+											public void lookupComplete() {
+												decreaseScansRemaining();
+
+												if (DEBUG) {
+													System.out.println("Tag Search: Complete" + " for "
+															+ dm.getDisplayName());
+												}
+											}
+										});
+							} catch (Throwable e) {
+
+								// can get here if the scan never gets kicked off (dht unavailable for network etc)
+								decreaseScansRemaining();
+							}
+						} catch (TOTorrentException e) {
+							e.printStackTrace();
+						}
+					}
+				} catch (ContentException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+			}
+		});
+	}
+
+	protected void decreaseScansRemaining() {
+		try {
+			mon_scansRemaining.enter();
+
+			scansRemaining--;
+
+			if (soTitle != null) {
+				if (scansRemaining <= 0) {
+					soTitle.setTextID("tag.discovery.view.heading");
+				} else {
+					soTitle.setText(MessageText.getString("tag.discovery.view.heading")
+							+ " : Scanning " + scansRemaining);
+				}
+			}
+			if (vitalityImage != null && scansRemaining <= 0) {
+				vitalityImage.setVisible(false);
+			}
+		} finally {
+			mon_scansRemaining.exit();
+		}
+	}
+
+	@Override
+	public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) {
+		return super.skinObjectDestroyed(skinObject, params);
+	}
+
+	private void initTable(Composite control) {
+		if (tv == null) {
+
+			tv = TableViewFactory.createTableViewSWT(TagDiscovery.class,
+					TABLE_TAGDISCOVERY, TABLE_TAGDISCOVERY, new TableColumnCore[0],
+					ColumnTagName.COLUMN_ID, SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL);
+			if (txtFilter != null) {
+				tv.enableFilterCheck(txtFilter, this);
+			}
+			tv.setRowDefaultHeight(16);
+
+			table_parent = new Composite(control, SWT.BORDER);
+			table_parent.setLayoutData(Utils.getFilledFormData());
+			GridLayout layout = new GridLayout();
+			layout.marginHeight = layout.marginWidth = layout.verticalSpacing = layout.horizontalSpacing = 0;
+			table_parent.setLayout(layout);
+
+			tv.addMenuFillListener(this);
+			tv.addSelectionListener(this, false);
+
+			tv.initialize(table_parent);
+		}
+
+		control.layout(true);
+	}
+
+	// @see org.gudy.azureus2.ui.swt.views.table.TableViewSWTMenuFillListener#fillMenu(java.lang.String, org.eclipse.swt.widgets.Menu)
+	public void fillMenu(String sColumnName, Menu menu) {
+		List<Object> ds = tv.getSelectedDataSources();
+
+		final MenuItem menuTagIt = new MenuItem(menu, SWT.PUSH);
+
+		Messages.setLanguageText(menuTagIt, "TagDiscoveriesView.menu.tagit");
+		menuTagIt.addListener(SWT.Selection, new TableSelectedRowsListener(tv) {
+			public void run(TableRowCore row) {
+				TagDiscovery tagDiscovery = (TagDiscovery) row.getDataSource(true);
+				TagManager tm = TagManagerFactory.getTagManager();
+				TagType manual_tt = tm.getTagType(TagType.TT_DOWNLOAD_MANUAL);
+				Tag tag = manual_tt.getTag(tagDiscovery.getName(), true);
+				if (tag == null) {
+					try {
+						tag = manual_tt.createTag(tagDiscovery.getName(), true);
+						tag.setPublic(true);
+						tag.setGroup("Discovery");
+						tag.setVisible(true);
+					} catch (TagException e) {
+						return;
+					}
+				}
+				byte[] hash = tagDiscovery.getHash();
+				DownloadManager dm = AzureusCoreFactory.getSingleton().getGlobalManager().getDownloadManager(
+						new HashWrapper(hash));
+				tag.addTaggable(dm);
+
+				String key = Base32.encode(hash) + tag.getTagName(true);
+				mapTagDiscoveries.remove(key);
+				tv.removeDataSource(tagDiscovery);
+				ViewTitleInfoManager.refreshTitleInfo(SBC_TagDiscovery.this);
+			}
+		});
+	}
+
+	public void addThisColumnSubMenu(String sColumnName, Menu menuThisColumn) {
+
+	}
+
+	public void selected(TableRowCore[] row) {
+	}
+
+	public void deselected(TableRowCore[] rows) {
+	}
+
+	public void focusChanged(TableRowCore focus) {
+
+	}
+
+	public void defaultSelected(TableRowCore[] rows, int stateMask) {
+		if (rows.length == 1) {
+
+			Object obj = rows[0].getDataSource();
+
+			if (obj instanceof TagDiscovery) {
+
+				TagDiscovery tag = (TagDiscovery) obj;
+
+				// do something on double click
+			}
+		}
+	}
+
+	public void mouseEnter(TableRowCore row) {
+	}
+
+	public void mouseExit(TableRowCore row) {
+	}
+
+	// @see com.aelitis.azureus.ui.common.table.TableViewFilterCheck#filterCheck(java.lang.Object, java.lang.String, boolean)
+	public boolean filterCheck(TagDiscovery ds, String filter, boolean regex) {
+		return false;
+	}
+
+}
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TagsOverview.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TagsOverview.java
index 814a90b..947acc0 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TagsOverview.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TagsOverview.java
@@ -1,10 +1,12 @@
 /**
  * Created on May 10, 2013
  *
- * Copyright 2011 Vuze, LLC.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -32,7 +34,11 @@ import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
 import org.gudy.azureus2.plugins.ui.tables.TableColumn;
 import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener;
+import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
 import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
+import org.gudy.azureus2.ui.swt.views.MyTorrentsSubView;
+import org.gudy.azureus2.ui.swt.views.TagSettingsView;
 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.TableViewFactory;
@@ -42,14 +48,17 @@ import com.aelitis.azureus.core.tag.*;
 import com.aelitis.azureus.ui.UIFunctions;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.ToolBarItem;
-import com.aelitis.azureus.ui.common.table.TableColumnCore;
-import com.aelitis.azureus.ui.common.table.TableRowCore;
-import com.aelitis.azureus.ui.common.table.TableSelectionListener;
-import com.aelitis.azureus.ui.common.table.TableViewFilterCheck;
+import com.aelitis.azureus.ui.common.table.*;
 import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdatable;
+import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
+import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
 import com.aelitis.azureus.ui.swt.columns.tag.*;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
+import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectButton;
+import com.aelitis.azureus.ui.swt.utils.TagUIUtilsV3;
 
 /**
  * @author TuxPaper
@@ -73,10 +82,34 @@ public class SBC_TagsOverview
 	private boolean columnsAdded = false;
 
 	private boolean tm_listener_added;
+
+	private boolean registeredCoreSubViews;
+
+	private Object datasource;
 	
 	// @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener#toolBarItemActivated(com.aelitis.azureus.ui.common.ToolBarItem, long, java.lang.Object)
 	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
 			Object datasource) {
+		if ( tv == null || !tv.isVisible()){
+			return( false );
+		}
+		if (item.getID().equals("remove")) {
+			
+			Object[] datasources = tv.getSelectedDataSources().toArray();
+			
+			if ( datasources.length > 0 ){
+				
+				for (Object object : datasources) {
+					if (object instanceof Tag) {
+						Tag tag = (Tag) object;
+						tag.removeTag();
+					}
+				}
+				
+				return true;
+			}
+		}
+		
 		return false;
 	}
 
@@ -86,6 +119,27 @@ public class SBC_TagsOverview
 
 	// @see org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener#refreshToolBarItems(java.util.Map)
 	public void refreshToolBarItems(Map<String, Long> list) {
+		if ( tv == null || !tv.isVisible()){
+			return;
+		}
+
+		boolean canEnable = false;
+		Object[] datasources = tv.getSelectedDataSources().toArray();
+		
+		if ( datasources.length > 0 ){
+			
+			for (Object object : datasources) {
+				if (object instanceof Tag) {
+					Tag tag = (Tag) object;
+					if (tag.getTagType().getTagType() == TagType.TT_DOWNLOAD_MANUAL) {
+						canEnable = true;
+						break;
+					}
+				}
+			}
+		}
+
+		list.put("remove", canEnable ? UIToolBarItem.STATE_ENABLED : 0);
 	}
 
 	// @see com.aelitis.azureus.ui.common.updater.UIUpdatable#updateUI()
@@ -104,6 +158,24 @@ public class SBC_TagsOverview
 	public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) {
 		initColumns();
 
+		SWTSkinObjectButton soAddTagButton = (SWTSkinObjectButton) getSkinObject("add-tag");
+		if (soAddTagButton != null) {
+			soAddTagButton.addSelectionListener(new ButtonListenerAdapter() {
+				// @see com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter#pressed(com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility, com.aelitis.azureus.ui.swt.skin.SWTSkinObject, int)
+				public void pressed(SWTSkinButtonUtility buttonUtility,
+						SWTSkinObject skinObject, int stateMask) {
+					TagUIUtilsV3.showCreateTagDialog(null);
+				}
+			});
+		}
+
+		new InfoBarUtil(skinObject, "tagsview.infobar", false,
+				"tags.infobar", "tags.view.infobar") {
+			public boolean allowShow() {
+				return true;
+			}
+		};
+
 		return null;
 	}
 
@@ -229,6 +301,13 @@ public class SBC_TagsOverview
 					}
 				});
 
+		tableManager.registerColumn(Tag.class, ColumnTagCopyOnComp.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnTagCopyOnComp(column);
+					}
+				});
+		
 		tableManager.registerColumn(Tag.class, ColumnTagProperties.COLUMN_ID,
 				new TableColumnCreationListener() {
 					public void tableColumnCreated(TableColumn column) {
@@ -236,6 +315,20 @@ public class SBC_TagsOverview
 					}
 				});
 		
+		tableManager.registerColumn(Tag.class, ColumnTagVisible.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnTagVisible(column);
+					}
+				});
+		
+		tableManager.registerColumn(Tag.class, ColumnTagGroup.COLUMN_ID,
+				new TableColumnCreationListener() {
+					public void tableColumnCreated(TableColumn column) {
+						new ColumnTagGroup(column);
+					}
+				});
+
 		tableManager.setDefaultColumnNames(TABLE_TAGS,
 				new String[] {
 					ColumnTagColor.COLUMN_ID,
@@ -311,6 +404,7 @@ public class SBC_TagsOverview
 		return null;
 	}
 
+	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectDestroyed(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
 	@Override
 	public Object 
 	skinObjectDestroyed(
@@ -340,6 +434,14 @@ public class SBC_TagsOverview
 	 * @since 4.6.0.5
 	 */
 	private void initTable(Composite control) {
+		
+		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
+		if (uiFunctions != null) {
+			UISWTInstance pluginUI = uiFunctions.getUISWTInstance();
+			
+			registerPluginViews( pluginUI );
+		}
+
 		if ( tv == null ){
 			
 			tv = TableViewFactory.createTableViewSWT(Tag.class, TABLE_TAGS, TABLE_TAGS,
@@ -349,6 +451,7 @@ public class SBC_TagsOverview
 				tv.enableFilterCheck(txtFilter, this);
 			}
 			tv.setRowDefaultHeight(16);
+			tv.setEnableTabViews(true, true, null);
 	
 			table_parent = new Composite(control, SWT.BORDER);
 			table_parent.setLayoutData(Utils.getFilledFormData());
@@ -360,11 +463,36 @@ public class SBC_TagsOverview
 			tv.addSelectionListener(this, false);
 			
 			tv.initialize(table_parent);
+
+			tv.addCountChangeListener(new TableCountChangeListener() {
+				
+				public void rowRemoved(TableRowCore row) {
+				}
+				
+				public void rowAdded(TableRowCore row) {
+					if (datasource == row.getDataSource()) {
+						tv.setSelectedRows(new TableRowCore[] { row });
+					}
+				}
+			});
 		}
-		
+
 		control.layout(true);
 	}
 
+	private void registerPluginViews(UISWTInstance pluginUI) {
+		if (registeredCoreSubViews) {
+			return;
+		}
+		
+		pluginUI.addView(TABLE_TAGS, "TagSettingsView", TagSettingsView.class,
+				null);
+		pluginUI.addView(TABLE_TAGS, "MyTorrentsSubView", MyTorrentsSubView.class,
+				null);
+
+		registeredCoreSubViews = true;
+	}
+
 	public void 
 	fillMenu(
 		String 	sColumnName, 
@@ -384,6 +512,8 @@ public class SBC_TagsOverview
 		
 		if ( tags.size() == 1 ){
 			TagUIUtils.createSideBarMenuItems( menu, tags.get(0) );
+		}else{
+			TagUIUtils.createSideBarMenuItems( menu, tags );
 		}
 	}
 
@@ -399,19 +529,30 @@ public class SBC_TagsOverview
 	selected(
 		TableRowCore[] row )
 	{
+  	UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+  	if (uiFunctions != null) {
+  		uiFunctions.refreshIconBar();
+  	}
 	}
 
 	public void 
 	deselected(
 		TableRowCore[] rows )
 	{
+  	UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+  	if (uiFunctions != null) {
+  		uiFunctions.refreshIconBar();
+  	}
 	}
 	
 	public void 
 	focusChanged(
 		TableRowCore focus )
 	{
-		
+  	UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
+  	if (uiFunctions != null) {
+  		uiFunctions.refreshIconBar();
+  	}
 	}
 
 	public void 
@@ -441,7 +582,8 @@ public class SBC_TagsOverview
 						tag.setVisible( true );
 					}
 					
-					uiFunctions.openView( UIFunctions.VIEW_TAG, tag );
+					String id = "Tag." + tag.getTagType().getTagType() + "." + tag.getTagID();
+					uiFunctions.getMDI().showEntryByID(id, tag);
 				}
 			}
 		}
@@ -499,4 +641,18 @@ public class SBC_TagsOverview
 	public void tagRemoved(Tag tag) {
 		tv.removeDataSource(tag);
 	}
+	
+	// @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#dataSourceChanged(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
+	public Object dataSourceChanged(SWTSkinObject skinObject, Object params) {
+		if (params instanceof Tag) {
+			if (tv != null) {
+				TableRowCore row = tv.getRow((Tag) params);
+				if (row != null) {
+					tv.setSelectedRows(new TableRowCore[] { row });
+				}
+			}
+		}
+		datasource = params;
+		return null;
+	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TorrentDetailsView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TorrentDetailsView.java
index 7ff3ab1..a91f097 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TorrentDetailsView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SBC_TorrentDetailsView.java
@@ -1,6 +1,6 @@
 /*
  * Created on 2 juil. 2003
- * Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,24 +14,16 @@
  * 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.views.skin;
 
-import java.util.ArrayList;
 import java.util.Map;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.CTabFolder;
-import org.eclipse.swt.custom.CTabItem;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.layout.*;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Menu;
 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.core3.download.DownloadManager;
@@ -43,19 +35,14 @@ import org.gudy.azureus2.core3.peer.PEPeer;
 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.plugins.download.DownloadException;
 import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
-import org.gudy.azureus2.pluginsimpl.local.download.DownloadImpl;
-import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl;
-import org.gudy.azureus2.ui.swt.Messages;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.debug.ObfusticateTab;
 import org.gudy.azureus2.ui.swt.mainwindow.MenuFactory;
-import org.gudy.azureus2.ui.swt.plugins.*;
+import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
 import org.gudy.azureus2.ui.swt.plugins.UISWTInstance.UISWTViewEventListenerWrapper;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewEventListenerHolder;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl;
 import org.gudy.azureus2.ui.swt.views.MyTorrentsView;
 import org.gudy.azureus2.ui.swt.views.PeersView;
 import org.gudy.azureus2.ui.swt.views.piece.PieceInfoView;
@@ -67,23 +54,22 @@ 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.aelitis.azureus.ui.common.ToolBarEnabler;
 import com.aelitis.azureus.ui.common.ToolBarItem;
 import com.aelitis.azureus.ui.common.table.TableView;
 import com.aelitis.azureus.ui.common.table.TableViewFilterCheck;
 import com.aelitis.azureus.ui.common.updater.UIUpdatable;
 import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager;
+import com.aelitis.azureus.ui.mdi.MdiEntry;
+import com.aelitis.azureus.ui.mdi.MdiListener;
 import com.aelitis.azureus.ui.selectedcontent.ISelectedContent;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentListener;
 import com.aelitis.azureus.ui.selectedcontent.SelectedContentManager;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
-import com.aelitis.azureus.ui.swt.mdi.MdiEntrySWT;
-import com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT;
+import com.aelitis.azureus.ui.swt.mdi.*;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinObject;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectText;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinObjectTextbox;
-import com.aelitis.azureus.ui.swt.utils.ColorCache;
 import com.aelitis.azureus.util.DataSourceUtils;
 
 /**
@@ -100,9 +86,7 @@ public class SBC_TorrentDetailsView
 
 	private DownloadManager manager;
 
-	private CTabFolder folder;
-
-	private ArrayList<UISWTViewCore> tabViews = new ArrayList<UISWTViewCore>();
+	private TabbedMdiInterface tabbedMDI;
 
 	int lastCompleted = -1;
 
@@ -110,8 +94,6 @@ public class SBC_TorrentDetailsView
 
 	private Composite parent;
 
-	protected UISWTViewCore activeView;
-
 	private FilterCheckHandler filter_check_handler;
 
 	private volatile int selection_count = 0;
@@ -124,6 +106,8 @@ public class SBC_TorrentDetailsView
 
 	private MdiEntrySWT mdi_entry;
 
+	private Object dataSource;
+
 	/**
 	 * 
 	 */
@@ -149,54 +133,29 @@ public class SBC_TorrentDetailsView
 		});
 	}
 
-	public static DownloadManager dataSourceToDownloadManager(Object ds) {
-		DownloadManager dm = null;
-		if (ds instanceof DownloadImpl) {
-			DownloadImpl dataSourcePlugin = (DownloadImpl) ds;
-			dm = dataSourcePlugin.getDownload();
-		} else if (ds instanceof DownloadManager) {
-			dm = (DownloadManager) ds;
-		} else if (ds instanceof Object[]
-				&& ((Object[]) ds)[0] instanceof DownloadManager) {
-			Object[] o = (Object[]) ds;
-			dm = (DownloadManager) o[0];
-		} else if (ds instanceof String) {
-			final String s = (String) ds;
-			dm = DataSourceUtils.getDM(s);
-		} else {
-			dm = null;
-		}
-		return dm;
-	}
-	
 	private void dataSourceChanged(Object newDataSource) {
+		this.dataSource = newDataSource;
+		
 		if (manager != null) {
 			manager.removeListener(this);
 		}
 
-		manager = dataSourceToDownloadManager(newDataSource);
+		manager = DataSourceUtils.getDM(newDataSource);
 		
-		if (newDataSource instanceof Object[]
-				&& ((Object[]) newDataSource)[1] instanceof PEPeer) {
-			Object[] o = (Object[]) newDataSource;
-
-			PeersView pv = (PeersView) showView(PeersView.class);
-
-			if (pv != null) {
-
-				pv.selectPeer((PEPeer) o[1]);
-			}
+		if (tabbedMDI != null && newDataSource instanceof Object[]
+				&& ((Object[]) newDataSource)[0] instanceof PEPeer) {
+			tabbedMDI.showEntryByID(PeersView.MSGID_PREFIX);
 		}
 
 		if (manager != null) {
 			manager.addListener(this);
 		}
-
-		for (int i = 0; i < tabViews.size(); i++) {
-			UISWTViewCore view = tabViews.get(i);
-			if (view != null) {
-				view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, newDataSource);
-			}
+		
+		if (tabbedMDI != null) {
+  		MdiEntry[] entries = tabbedMDI.getEntries();
+  		for (MdiEntry entry : entries) {
+  			entry.setDatasource(newDataSource);
+  		}
 		}
 
 		refreshTitle();
@@ -220,32 +179,7 @@ public class SBC_TorrentDetailsView
 
 		SelectedContentManager.removeCurrentlySelectedContentListener(this);
 
-		if (folder != null && !folder.isDisposed()) {
-			folder.setSelection(0);
-		}
-
-		//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 (Utils.isCarbon) {
-			if (folder != null && !folder.isDisposed()) {
-				Utils.disposeSWTObjects(folder.getItems());
-			}
-		}
-
-		for (int i = 0; i < tabViews.size(); i++) {
-			UISWTViewCore view = tabViews.get(i);
-			try {
-				if (view != null) {
-					view.triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
-				}
-			} catch (Throwable t) {
-				Debug.out(t);
-			}
-		}
-		tabViews.clear();
-
 		Utils.disposeSWTObjects(new Object[] {
-			folder,
 			parent
 		});
 	}
@@ -258,30 +192,23 @@ public class SBC_TorrentDetailsView
 		//boolean az2 = Utils.isAZ2UI();
 		//Color bg_color = ColorCache.getColor(composite.getDisplay(), "#c0cbd4");
 
-		FormData formData;
+		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
 
 		this.parent = composite;
-		if (folder == null) {
-			folder = new CTabFolder(main_area, SWT.LEFT);
-			folder.setBorderVisible(true);
+		if (tabbedMDI == null) {
+			tabbedMDI = uiFunctions.createTabbedMDI(main_area, "detailsview");
 		} else {
 			System.out.println("ManagerView::initialize : folder isn't null !!!");
 		}
 
-		formData = Utils.getFilledFormData();
-
-		folder.setLayoutData(formData);
-
 		if (composite.getLayout() instanceof FormLayout) {
 			main_area.setLayoutData(Utils.getFilledFormData());
 		} else if (composite.getLayout() instanceof GridLayout) {
 			main_area.setLayoutData(new GridData(GridData.FILL_BOTH));
 		}
-
-		folder.setTabHeight(20);
+		composite.layout();
 
 		// Call plugin listeners
-		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
 		if (uiFunctions != null) {
 			UISWTInstance pluginUI = uiFunctions.getUISWTInstance();
 
@@ -310,10 +237,9 @@ public class SBC_TorrentDetailsView
 						if (l != null) {
 	
 							try {
-								UISWTViewImpl view = new UISWTViewImpl(
-										UISWTInstance.VIEW_TORRENT_DETAILS, l.getViewID(), l, null);
-	
-								addSection(view);
+								tabbedMDI.createEntryFromEventListener(null,
+										UISWTInstance.VIEW_TORRENT_DETAILS, l, l.getViewID(), false,
+										manager, null);
 	
 							} catch (Throwable e) {
 	
@@ -327,152 +253,87 @@ public class SBC_TorrentDetailsView
 
 		SelectedContentManager.addCurrentlySelectedContentListener(this);
 
-		Menu menu = new Menu(folder);
-
-		menu.setData("downloads", new DownloadManager[] {
-			manager
-		});
-		menu.setData("is_detailed_view", true);
-
-		MenuFactory.buildTorrentMenu(menu);
-
-		folder.setMenu(menu);
-
-		// Initialize view when user selects it
-		folder.addSelectionListener(new SelectionAdapter() {
-			public void widgetSelected(SelectionEvent e) {
-				CTabItem item = (CTabItem) e.item;
-				selectView(item);
+		tabbedMDI.addListener(new MdiSWTMenuHackListener() {
+			
+			public void menuWillBeShown(MdiEntry entry, Menu menuTree) {
+				menuTree.setData("downloads", new DownloadManager[] {
+					manager
+				});
+				menuTree.setData("is_detailed_view", true);
+				
+				MenuFactory.buildTorrentMenu(menuTree);
 			}
 		});
-
-		Utils.execSWTThreadLater(0, new AERunnable() {
-			public void runSupport() {
-				if (!folder.isDisposed() && folder.getItemCount() > 0) {
-					selectView(folder.getItem(0));
+		
+		tabbedMDI.addListener(new MdiListener() {
+			public void mdiEntrySelected(MdiEntry newEntry, MdiEntry oldEntry) {
+				// TODO Auto-generated method stub
+				if (oldEntry != null) {
+  				MdiEntrySWT oldEntrySWT = ((MdiEntrySWT) oldEntry);
+  				UISWTViewEventListener listener = oldEntrySWT.getEventListener();
+  				if (listener instanceof UISWTViewEventListenerHolder) {
+  					listener = ((UISWTViewEventListenerHolder) listener).getDelegatedEventListener(oldEntrySWT);
+  				}
+  
+  				// unhook filtering
+  
+  				if (listener instanceof TableViewTab<?>
+  						&& listener instanceof TableViewFilterCheck<?>) {
+  
+  					TableViewTab<?> tvt = (TableViewTab<?>) listener;
+  
+  					TableViewSWT tv = tvt.getTableView();
+  
+  					if (tv != null) {
+  						tv.disableFilterCheck();
+  					}
+  				}
 				}
-			}
-		});
-
-		Utils.relayout(folder);
-	}
-
-	private void selectView(CTabItem item) {
-		if (item == null) {
-			return;
-		}
-		if (folder.getSelection() != item) {
-			folder.setSelection(item);
-		}
-		folder.getShell().setCursor(
-				folder.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
-		try {
-			// Send one last refresh to previous tab, just in case it
-			// wants to do something when view goes invisible
-			refresh();
 
-			if (activeView != null) {
-				activeView.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
+				// hook in filtering
 
-				UISWTViewEventListener listener = activeView.getEventListener();
+				MdiEntrySWT newEntrySWT = ((MdiEntrySWT) newEntry);
+				UISWTViewEventListener listener = newEntrySWT.getEventListener();
+				if (listener instanceof TableViewTab
+						&& listener instanceof TableViewFilterCheck) {
 
-				if (listener instanceof UISWTViewEventListenerHolder) {
+					TableViewTab tvt = (TableViewTab) listener;
 
-					listener = ((UISWTViewEventListenerHolder) listener).getDelegatedEventListener(activeView);
-				}
+					TableViewFilterCheck delegate = (TableViewFilterCheck) tvt;
 
-				// unhook filtering
+					soFilterTextBox.setVisible(true);
 
-				if (listener instanceof TableViewTab<?>
-						&& listener instanceof TableViewFilterCheck<?>) {
+					filter_check_handler = new FilterCheckHandler(tvt, delegate);
 
-					TableViewTab<?> tvt = (TableViewTab<?>) listener;
+					tvt.enableFilterCheck(soFilterTextBox.getTextControl(),
+							filter_check_handler);
 
-					TableViewSWT tv = tvt.getTableView();
+				} else {
+					filter_check_handler = null;
 
-					tv.disableFilterCheck();
+					soFilterTextBox.setVisible(false);
 				}
-			}
-
-			UISWTViewCore view = (UISWTViewCore) item.getData("IView");
-			if (view == null) {
-				Class<?> cla = (Class<?>) item.getData("claEventListener");
-				UISWTViewEventListener l = (UISWTViewEventListener) cla.newInstance();
-				view = new UISWTViewImpl(UISWTInstance.VIEW_MAIN, cla.getSimpleName(),
-						l, manager);
-				item.setData("IView", view);
-			}
 
-			if (mdi_entry != null) {
-				String id = "";
-				if (activeView instanceof UISWTViewImpl) {
-					id = "" + ((UISWTViewImpl) activeView).getViewID();
-					id = id.substring(id.lastIndexOf(".") + 1);
-				} else if (activeView != null) {
-					String simpleName = activeView.getClass().getName();
-					id = simpleName.substring(simpleName.lastIndexOf(".") + 1);
-				} else {
-					id = "??";
+				refresh();
+				if ( mdi_entry != null ){
+					mdi_entry.redraw();
+					ViewTitleInfoManager.refreshTitleInfo(mdi_entry.getViewTitleInfo());
 				}
-				mdi_entry.setLogID("DMDetails-" + id);
-			}
-			activeView = view;
-
-			if (item.getControl() == null) {
-				view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, manager);
-				view.initialize(folder);
-				item.setControl(view.getComposite());
 			}
-
-			UISWTViewEventListener listener = view.getEventListener();
-
-			if (listener instanceof UISWTViewEventListenerHolder) {
-
-				listener = ((UISWTViewEventListenerHolder) listener).getDelegatedEventListener(view);
-			}
-
-			// hook in filtering
-
-			if (listener instanceof TableViewTab<?>
-					&& listener instanceof TableViewFilterCheck<?>) {
-
-				TableViewTab<Object> tvt = (TableViewTab<Object>) listener;
-
-				TableViewFilterCheck delegate = (TableViewFilterCheck) tvt;
-
-				soFilterTextBox.setVisible(true);
-
-				filter_check_handler = new FilterCheckHandler(tvt, delegate);
-
-				tvt.getTableView().enableFilterCheck(soFilterTextBox.getTextControl(),
-						filter_check_handler);
-
-			} else {
-				filter_check_handler = null;
-
-				soFilterTextBox.setVisible(false);
-			}
-
-			item.getControl().setFocus();
-			SelectedContentManager.clearCurrentlySelectedContent();
-
-			view.triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
-
-			UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
-			if (uiFunctions != null) {
-				uiFunctions.refreshIconBar(); // For edit columns view
-			}
-
-			refresh();
-			mdi_entry.redraw();
-			ViewTitleInfoManager.refreshTitleInfo(mdi_entry.getViewTitleInfo());
-		} catch (Exception e) {
-			Debug.out(e);
-		} finally {
-			folder.getShell().setCursor(null);
+		});
+		
+		if (dataSource instanceof Object[]
+				&& ((Object[]) dataSource)[0] instanceof PEPeer) {
+			tabbedMDI.showEntryByID(PeersView.MSGID_PREFIX);
+		} else {
+  		MdiEntry[] entries = tabbedMDI.getEntries();
+  		if (entries.length > 0) {
+  			tabbedMDI.showEntry(entries[0]);
+  		}
 		}
 	}
 
+
 	public void currentlySelectedContentChanged(
 			ISelectedContent[] currentContent, String viewId) {
 		selection_count = currentContent.length;
@@ -565,79 +426,11 @@ public class SBC_TorrentDetailsView
 		return( str );
 	}
 
-	protected Object showView(Class view_class) {
-		CTabItem[] items = folder.getItems();
-
-		for (int i = 0; i < items.length; i++) {
-
-			CTabItem item = items[i];
-
-			UISWTViewCore view = (UISWTViewCore) item.getData("IView");
-
-			UISWTViewEventListener listener = view.getEventListener();
-
-			if (listener instanceof UISWTViewEventListenerHolder) {
-
-				UISWTViewEventListenerHolder lh = (UISWTViewEventListenerHolder) listener;
-
-				UISWTViewEventListener delegated_listener = lh.getDelegatedEventListener(view);
-
-				if (view_class.isInstance(delegated_listener)) {
-
-					selectView(item);
-
-					return (delegated_listener);
-				}
-			}
-		}
-
-		return (null);
-	}
-
-	private UISWTViewCore getActiveView() {
-		return activeView;
-	}
-
 	/**
 	 * Called when view is visible
 	 */
 	private void refresh() {
-		if (folder == null || folder.isDisposed())
-			return;
-
-		try {
-			UISWTViewCore view = getActiveView();
-			if (view != null) {
-				view.triggerEvent(UISWTViewEvent.TYPE_REFRESH, null);
-			}
-
-			CTabItem[] items = folder.getItems();
-
-			for (int i = 0; i < items.length; i++) {
-				CTabItem item = items[i];
-				view = (UISWTViewCore) item.getData("IView");
-				try {
-					if (item.isDisposed() || view == null) {
-						continue;
-					}
-					String lastTitle = item.getText();
-					String newTitle = view.getFullTitle();
-					if (lastTitle == null || !lastTitle.equals(newTitle)) {
-						item.setText(escapeAccelerators(newTitle));
-					}
-					String lastToolTip = item.getToolTipText();
-					String newToolTip = view.getFullTitle();
-					if (lastToolTip == null || !lastToolTip.equals(newToolTip)) {
-						item.setToolTipText(newToolTip);
-					}
-				} catch (Exception e) {
-					Debug.printStackTrace(e);
-				}
-			}
-
-		} catch (Exception e) {
-			Debug.printStackTrace(e);
-		}
+		tabbedMDI.updateUI();
 	}
 
 	/**
@@ -646,7 +439,7 @@ public class SBC_TorrentDetailsView
 	 * @since 3.1.0.1
 	 */
 	private void refreshTitle() {
-		int completed = manager == null ? -1 : manager.getStats().getCompleted();
+		int completed = manager == null ? -1 : manager.getStats().getPercentDoneExcludingDND();
 		if (lastCompleted != completed) {
 			if (mdi_entry != null) {
 				ViewTitleInfoManager.refreshTitleInfo(mdi_entry.getViewTitleInfo());
@@ -668,39 +461,23 @@ public class SBC_TorrentDetailsView
 	 * @see org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener#refreshToolBarItems(java.util.Map)
 	 */
 	public void refreshToolBarItems(Map<String, Long> list) {
-		UISWTViewCore active_view = getActiveView();
-		if (active_view != null) {
-			UIPluginViewToolBarListener l = active_view.getToolBarListener();
-			if (l != null) {
-				l.refreshToolBarItems(list);
-				return;
-			}
+		BaseMdiEntry activeView = getActiveView();
+		if (activeView == null) {
+			return;
 		}
-
-	}
-
+		activeView.refreshToolBarItems(list);
+	};
+	
 	/* (non-Javadoc)
 	 * @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener#toolBarItemActivated(com.aelitis.azureus.ui.common.ToolBarItem, long, java.lang.Object)
 	 */
 	public boolean toolBarItemActivated(ToolBarItem item, long activationType,
 			Object datasource) {
-		UISWTViewCore active_view = getActiveView();
-		if (active_view != null) {
-			UIPluginViewToolBarListener l = active_view.getToolBarListener();
-			if (l != null && l.toolBarItemActivated(item, activationType, datasource)) {
-				return true;
-			}
+		BaseMdiEntry activeView = getActiveView();
+		if (activeView == null) {
+			return false;
 		}
-
-		String itemKey = item.getID();
-
-		if (itemKey.equals("editcolumns")) {
-			if (active_view instanceof ToolBarEnabler) {
-				return ((ToolBarEnabler) active_view).toolBarItemActivated(itemKey);
-			}
-		}
-
-		return false;
+		return activeView.toolBarItemActivated(item, activationType, datasource);
 	}
 
 	public void downloadComplete(DownloadManager manager) {
@@ -714,11 +491,9 @@ public class SBC_TorrentDetailsView
 	}
 
 	public void stateChanged(DownloadManager manager, int state) {
-		if (folder == null || folder.isDisposed())
-			return;
-		Display display = folder.getDisplay();
-		if (display == null || display.isDisposed())
+		if (tabbedMDI == null || tabbedMDI.isDisposed()) {
 			return;
+		}
 		Utils.execSWTThread(new AERunnable() {
 			public void runSupport() {
 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
@@ -733,28 +508,6 @@ public class SBC_TorrentDetailsView
 			int newPosition) {
 	}
 
-	public void addSection(UISWTViewImpl view) {
-		Object pluginDataSource = null;
-		try {
-			pluginDataSource = DownloadManagerImpl.getDownloadStatic(manager);
-		} catch (DownloadException e) {
-			/* Ignore */
-		}
-		addSection(view, pluginDataSource);
-	}
-
-	private void addSection(UISWTViewCore view, Object dataSource) {
-		if (view == null)
-			return;
-
-		view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, dataSource);
-
-		CTabItem item = new CTabItem(folder, SWT.NULL);
-		Messages.setLanguageText(item, view.getTitleID());
-		item.setData("IView", view);
-		tabViews.add(view);
-	}
-
 	public String getObfusticatedHeader() {
 		int completed = manager.getStats().getCompleted();
 		return DisplayFormatters.formatPercentFromThousands(completed) + " : "
@@ -802,6 +555,9 @@ public class SBC_TorrentDetailsView
 			updateHeader();
 		}
 
+		/* (non-Javadoc)
+		 * @see com.aelitis.azureus.ui.common.table.TableViewFilterCheck#filterCheck(java.lang.Object, java.lang.String, boolean)
+		 */
 		public boolean filterCheck(Object ds, String filter, boolean regex) {
 			return (delegate.filterCheck(ds, filter, regex));
 		};
@@ -868,6 +624,9 @@ public class SBC_TorrentDetailsView
 	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectInitialShow(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
 	public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) {
 		SWTSkinObject soListArea = getSkinObject("torrentdetails-list-area");
+		if (soListArea == null) {
+			return null;
+		}
 		soFilterTextBox = (SWTSkinObjectTextbox) getSkinObject("torrentdetails-filter");
 		soInfoArea = (SWTSkinObjectText) getSkinObject("torrentdetails-info");
 
@@ -887,47 +646,28 @@ public class SBC_TorrentDetailsView
 				mdi_entry = mdi.getCurrentEntrySWT();
 			}
 			
-			mdi_entry.addToolbarEnabler(this);
 		}
 
 		initialize((Composite) soListArea.getControl());
 		return null;
 	}
-
-	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectShown(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
-	public Object skinObjectShown(SWTSkinObject skinObject, Object params) {
-		UISWTViewCore view = getActiveView();
-		if (view != null) {
-			view.triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
-		}
-		refresh();
-		return super.skinObjectShown(skinObject, params);
-	}
-
-	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectHidden(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
-	public Object skinObjectHidden(SWTSkinObject skinObject, Object params) {
-		UISWTViewCore view = getActiveView();
-		if (view != null) {
-			view.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
-		}
-		return super.skinObjectHidden(skinObject, params);
-	}
-
+	
 	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectDestroyed(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
 	public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) {
 		delete();
 		return super.skinObjectDestroyed(skinObject, params);
 	}
 
-	// @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#updateLanguage(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
-	public Object updateLanguage(SWTSkinObject skinObject, Object params) {
-		Messages.updateLanguageForControl(folder);
-		return super.updateLanguage(skinObject, params);
-	}
-
 	// @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#dataSourceChanged(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
 	public Object dataSourceChanged(SWTSkinObject skinObject, Object params) {
 		dataSourceChanged(params);
-		return super.dataSourceChanged(skinObject, params);
-	};
+		return null;
+	}
+	
+	private BaseMdiEntry getActiveView() {
+		if (tabbedMDI == null || tabbedMDI.isDisposed()) {
+			return null;
+		}
+		return (BaseMdiEntry) tabbedMDI.getCurrentEntrySWT();
+	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Discovery.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Discovery.java
index 0e156d9..3a232d7 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Discovery.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Discovery.java
@@ -1,10 +1,12 @@
 /**
  * Created on May 10, 2013
  *
- * Copyright 2011 Vuze, LLC.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Transfers.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Transfers.java
index 7e03f8d..c8a02c2 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Transfers.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Transfers.java
@@ -1,10 +1,12 @@
 /**
  * Created on Oct 21, 2010
  *
- * Copyright 2010 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -18,10 +20,7 @@
 
 package com.aelitis.azureus.ui.swt.views.skin;
 
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
+import java.util.*;
 
 import org.eclipse.swt.widgets.Menu;
 import org.gudy.azureus2.core3.category.*;
@@ -39,7 +38,6 @@ import org.gudy.azureus2.plugins.ui.UIManager;
 import org.gudy.azureus2.plugins.ui.menus.*;
 import org.gudy.azureus2.plugins.ui.tables.TableManager;
 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl;
 import org.gudy.azureus2.ui.swt.CategoryAdderWindow;
 import org.gudy.azureus2.ui.swt.TorrentUtil;
 import org.gudy.azureus2.ui.swt.Utils;
@@ -836,7 +834,7 @@ public class SB_Transfers
 		
 		List<DownloadManager> downloadManagers = gm.getDownloadManagers();
 		for (Iterator<DownloadManager> iter = downloadManagers.iterator(); iter.hasNext();) {
-			DownloadManager dm = (DownloadManager) iter.next();
+			DownloadManager dm = iter.next();
 			boolean lowNoise = PlatformTorrentUtils.isAdvancedViewOnly(dm);
 			if ( dm.isPersistent() && dm.getTorrent() != null){	// ignore borked torrents as their create time is inaccurate
 				long createTime = dm.getCreationTime();
@@ -953,52 +951,53 @@ public class SB_Transfers
 				name, viewTitleInfo, category, false, null);
 		if (entry != null) {
 			entry.setImageLeftID("image.sidebar.library");
-		}
-
-		if (entry instanceof SideBarEntrySWT) {
-			final SideBarEntrySWT entrySWT = (SideBarEntrySWT) entry;
-			entrySWT.addListener(new MdiSWTMenuHackListener() {
-				public void menuWillBeShown(MdiEntry entry, Menu menuTree) {
-					CategoryUIUtils.createMenuItems(menuTree, category);
-				}
-			});
-		}
 
-		entry.addListener(new MdiEntryDropListener() {
-			public boolean mdiEntryDrop(MdiEntry entry, Object payload) {
-				if (!(payload instanceof String)) {
-					return false;
-				}
+			entry.addListener(new MdiEntryDropListener() {
+				public boolean mdiEntryDrop(MdiEntry entry, Object payload) {
+					if (!(payload instanceof String)) {
+						return false;
+					}
 
-				String dropped = (String) payload;
-				String[] split = Constants.PAT_SPLIT_SLASH_N.split(dropped);
-				if (split.length > 1) {
-					String type = split[0];
-					if (type.startsWith("DownloadManager")) {
-						GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
-						for (int i = 1; i < split.length; i++) {
-							String hash = split[i];
+					String dropped = (String) payload;
+					String[] split = Constants.PAT_SPLIT_SLASH_N.split(dropped);
+					if (split.length > 1) {
+						String type = split[0];
+						if (type.startsWith("DownloadManager")) {
+							GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
+							for (int i = 1; i < split.length; i++) {
+								String hash = split[i];
 
-							try {
-								DownloadManager dm = gm.getDownloadManager(new HashWrapper(
-										Base32.decode(hash)));
+								try {
+									DownloadManager dm = gm.getDownloadManager(new HashWrapper(
+											Base32.decode(hash)));
 
-								if (dm != null) {
-									TorrentUtil.assignToCategory(new Object[] {
-										dm
-									}, category);
-								}
+									if (dm != null) {
+										TorrentUtil.assignToCategory(new Object[] {
+											dm
+										}, category);
+									}
 
-							} catch (Throwable t) {
+								} catch (Throwable t) {
 
+								}
 							}
 						}
 					}
+
+					return true;
 				}
+			});
+		}
+
+		if (entry instanceof SideBarEntrySWT) {
+			final SideBarEntrySWT entrySWT = (SideBarEntrySWT) entry;
+			entrySWT.addListener(new MdiSWTMenuHackListener() {
+				public void menuWillBeShown(MdiEntry entry, Menu menuTree) {
+					CategoryUIUtils.createMenuItems(menuTree, category);
+				}
+			});
+		}
 
-				return true;
-			}
-		});
 	}
 
 	private static void removeCategory(Category category) {
@@ -1074,7 +1073,9 @@ public class SB_Transfers
 		}
 	}
 
-	private static void 
+	private static Object	tag_setup_lock = new Object();
+	
+	public static MdiEntry 
 	setupTag(
 		final Tag tag ) 
 	{
@@ -1082,226 +1083,254 @@ public class SB_Transfers
 		
 		if ( mdi == null ){
 			
-			return;
+			return null;
 		}
 
-		String id = "Tag." + tag.getTagType().getTagType() + "." + tag.getTagID();
-
-		if ( mdi.getEntry( id ) != null ){
-			
-			return;
-		}
+			/*
+			 * Can get hit here concurrently due to various threads interacting with tags...
+			 */
 		
-		String name = tag.getTagName( true );
-
-			// find where to locate this in the sidebar
-				
-		TreeMap<String,String>	name_map = 
-			new TreeMap<String,String>(new FormattersImpl().getAlphanumericComparator( true ));
-		
-		name_map.put( name, id );
-		
-		for ( Tag t: tag.getTagType().getTags()){
+		synchronized( tag_setup_lock ){
 			
-			if ( t.isVisible()){
-				
-				String tid = "Tag." + tag.getTagType().getTagType() + "." + t.getTagID();
-
-				if ( mdi.getEntry( tid ) != null ){
-					
-					name_map.put( t.getTagName( true ), tid );
-				}
-			}
-		}
-		
-		String	prev_id = null;
-		
-		for ( Map.Entry<String,String> entry: name_map.entrySet()){
-		
-			String	this_id = entry.getValue();
-			
-			if ( this_id == id ){
+			String id = "Tag." + tag.getTagType().getTagType() + "." + tag.getTagID();
+	
+			if ( mdi.getEntry( id ) != null ){
 				
-				break;
+				return null;
 			}
 			
-			prev_id = this_id;
-		}
-		
-		if ( prev_id == null && name_map.size() > 1 ){
-						
-			Iterator<String>	it = name_map.values().iterator();
+				// find where to locate this in the sidebar
+					
+			TreeMap<Tag,String>	name_map = new TreeMap<Tag,String>(TagUIUtils.getTagComparator());
 			
-			it.next();
+			name_map.put( tag, id );
 			
-			prev_id = "~" + it.next();
-		}
-		
-		boolean auto = tag.getTagType().isTagTypeAuto();
+			for ( Tag t: tag.getTagType().getTags()){
 				
-		ViewTitleInfo viewTitleInfo = 
-			new ViewTitleInfo() 
-			{
-				public Object 
-				getTitleInfoProperty(
-					int pid )
-				{
-					if ( pid == TITLE_INDICATOR_TEXT ){
-						
-						return( String.valueOf( tag.getTaggedCount()));
-						
-					}else if ( pid == TITLE_INDICATOR_COLOR ){
-						
-						TagType tag_type = tag.getTagType();
-						
-						int[] def_color = tag_type.getColorDefault();
-						
-						int[] tag_color = tag.getColor();
-						
-						if ( tag_color != def_color ){
-							
-							return( tag_color );
-						}
-						
-					}else if ( pid == TITLE_INDICATOR_TEXT_TOOLTIP ){
+				if ( t.isVisible()){
+					
+					String tid = "Tag." + tag.getTagType().getTagType() + "." + t.getTagID();
+	
+					if ( mdi.getEntry( tid ) != null ){
 						
-						return( TagUIUtils.getTagTooltip( tag ));	
+						name_map.put( t, tid );
 					}
-					
-					return null;
 				}
-			};
-
-		MdiEntry entry;
-		
-		boolean closable = auto;
-		
-		if ( tag.getTaggableTypes() == Taggable.TT_DOWNLOAD ){
-			
-			closable = true;
+			}
 			
-			entry = mdi.createEntryFromSkinRef(
-					MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS, id, "library",
-					name, viewTitleInfo, tag, closable, prev_id);
-		}else{
+			String	prev_id = null;
 			
-			entry = mdi.createEntryFromEventListener(
-						MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS, 
-						new PeersGeneralView( tag ), id, closable, null, prev_id);
+			for ( String this_id: name_map.values()){
+						
+				if ( this_id == id ){
+					
+					break;
+				}
+				
+				prev_id = this_id;
+			}
 			
-			entry.setViewTitleInfo( viewTitleInfo );
-		}
-		
-		if ( closable ){
+			if ( prev_id == null && name_map.size() > 1 ){
+							
+				Iterator<String>	it = name_map.values().iterator();
+				
+				it.next();
+				
+				prev_id = "~" + it.next();
+			}
 			
-			entry.addListener(
-				new MdiCloseListener()
+			boolean auto = tag.getTagType().isTagTypeAuto();
+					
+			ViewTitleInfo viewTitleInfo = 
+				new ViewTitleInfo() 
 				{
-					public void 
-					mdiEntryClosed(
-						MdiEntry 	entry, 
-						boolean 	userClosed )
+					public Object 
+					getTitleInfoProperty(
+						int pid )
 					{
-						if ( userClosed && entry.getUserData( AUTO_CLOSE_KEY ) == null ){
+						if ( pid == TITLE_INDICATOR_TEXT ){
+							
+							return( String.valueOf( tag.getTaggedCount()));
+							
+						}else if ( pid == TITLE_INDICATOR_COLOR ){
+							
+							TagType tag_type = tag.getTagType();
 							
-								// userClosed isn't all we want - it just means we're not closing the app... So to prevent
-								// a deselection of 'show tags in sidebar' 'user-closing' the entries we need this test
+							int[] def_color = tag_type.getColorDefault();
 							
-							if ( COConfigurationManager.getBooleanParameter("Library.TagInSideBar")){
+							int[] tag_color = tag.getColor();
 							
-								tag.setVisible( false );
+							if ( tag_color != def_color ){
+								
+								return( tag_color );
 							}
+							
+						}else if ( pid == TITLE_INDICATOR_TEXT_TOOLTIP ){
+							
+							return( TagUIUtils.getTagTooltip( tag ));	
 						}
+						
+						return null;
 					}
-				});
-		}
-		
-		if (entry != null) {
-			String image_id = tag.getImageID();
+				};
+	
+			MdiEntry entry;
+			
+			boolean closable = auto;
 			
-			if ( image_id != null ){
-				entry.setImageLeftID( image_id );
-			}else if ( tag.getTagType().getTagType() == TagType.TT_PEER_IPSET ){
-				entry.setImageLeftID("image.sidebar.tag-red");
-			}else if ( tag.getTagType().isTagTypePersistent()){
-				entry.setImageLeftID("image.sidebar.tag-green");
+			if ( tag.getTaggableTypes() == Taggable.TT_DOWNLOAD ){
+				
+				closable = true;
+				
+				String name = tag.getTagName( true );
+	
+				entry = mdi.createEntryFromSkinRef(
+						MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS, id, "library",
+						name, viewTitleInfo, tag, closable, prev_id);
 			}else{
-				entry.setImageLeftID("image.sidebar.tag-blue");
+				
+				entry = mdi.createEntryFromEventListener(
+							MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS, 
+							new PeersGeneralView( tag ), id, closable, null, prev_id);
+				
+				entry.setViewTitleInfo( viewTitleInfo );
 			}
-		}
-
-		if (entry instanceof SideBarEntrySWT) {
-			final SideBarEntrySWT entrySWT = (SideBarEntrySWT) entry;
-			entrySWT.addListener(new MdiSWTMenuHackListener() {
-				public void menuWillBeShown(MdiEntry entry, Menu menuTree) {
-					TagUIUtils.createSideBarMenuItems(menuTree, tag);
+			
+			if ( closable ){
+				
+				entry.addListener(
+					new MdiCloseListener()
+					{
+						public void 
+						mdiEntryClosed(
+							MdiEntry 	entry, 
+							boolean 	userClosed )
+						{
+							if ( userClosed && entry.getUserData( AUTO_CLOSE_KEY ) == null ){
+								
+									// userClosed isn't all we want - it just means we're not closing the app... So to prevent
+									// a deselection of 'show tags in sidebar' 'user-closing' the entries we need this test
+								
+								if ( COConfigurationManager.getBooleanParameter("Library.TagInSideBar")){
+								
+									tag.setVisible( false );
+								}
+							}
+						}
+					});
+			}
+			
+			if (entry != null) {
+				String image_id = tag.getImageID();
+				
+				if ( image_id != null ){
+					entry.setImageLeftID( image_id );
+				}else if ( tag.getTagType().getTagType() == TagType.TT_PEER_IPSET ){
+					entry.setImageLeftID("image.sidebar.tag-red");
+				}else if ( tag.getTagType().isTagTypePersistent()){
+					entry.setImageLeftID("image.sidebar.tag-green");
+				}else{
+					entry.setImageLeftID("image.sidebar.tag-blue");
 				}
-			});
-		}
-		
-		if ( !auto ){	
+			}
 	
-			MdiEntryDropListener dl = new MdiEntryDropListener() {
-				public boolean mdiEntryDrop(MdiEntry entry, Object payload) {
-					if (!(payload instanceof String)) {
-						return false;
+			if (entry instanceof SideBarEntrySWT) {
+				final SideBarEntrySWT entrySWT = (SideBarEntrySWT) entry;
+				entrySWT.addListener(new MdiSWTMenuHackListener() {
+					public void menuWillBeShown(MdiEntry entry, Menu menuTree) {
+						TagUIUtils.createSideBarMenuItems(menuTree, tag);
 					}
-					
-					if ( tag.isTagAuto()){
+				});
+			}
+			
+			if ( !auto && entry != null ){	
+		
+				MdiEntryDropListener dl = new MdiEntryDropListener() {
+					public boolean mdiEntryDrop(MdiEntry entry, Object payload) {
+						if (!(payload instanceof String)) {
+							return false;
+						}
+						
+						if ( tag.isTagAuto()){
+							
+							return( false );
+						}
 						
-						return( false );
+						final String dropped = (String) payload;
+	
+						new AEThread2("Tagger") {
+							@Override
+							public void run() {
+								dropTorrentOnTag(tag, dropped);
+							}
+						}.start();
+		
+						return true;
 					}
 	
-					String dropped = (String) payload;
-					String[] split = Constants.PAT_SPLIT_SLASH_N.split(dropped);
-					if (split.length > 1) {
-						String type = split[0];
-						if (type.startsWith("DownloadManager") || type.startsWith( "DiskManagerFileInfo" )) {
-							GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
-							for (int i = 1; i < split.length; i++) {
-								String hash = split[i];
+					private void dropTorrentOnTag(Tag tag, String dropped) {
+						String[] split = Constants.PAT_SPLIT_SLASH_N.split(dropped);
+						if (split.length <= 1) {
+							return;
+						}
 	
-								int sep = hash.indexOf( ";" );	// for files
+						String type = split[0];
+						if (!type.startsWith("DownloadManager") && !type.startsWith( "DiskManagerFileInfo" )) {
+							return;
+						}
+						GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
+						List<DownloadManager> listDMs = new ArrayList<DownloadManager>();
+						boolean doAdd = false;
+						for (int i = 1; i < split.length; i++) {
+							String hash = split[i];
+							
+							int sep = hash.indexOf( ";" );	// for files
+							
+							if ( sep != -1 ){
 								
-								if ( sep != -1 ){
+								hash = hash.substring( 0, sep );
+							}
+							
+							try {
+								DownloadManager dm = gm.getDownloadManager(new HashWrapper(
+										Base32.decode(hash)));
+								
+								if ( dm != null ){
+									
+									listDMs.add(dm);
 									
-									hash = hash.substring( 0, sep );
+									if (!doAdd && !tag.hasTaggable(dm)) {
+										doAdd = true;
+									}
 								}
+							}catch ( Throwable t ){
 								
-								try {
-									DownloadManager dm = gm.getDownloadManager(new HashWrapper(
-											Base32.decode(hash)));
-	
-									if ( dm != null ){
-										
-										if ( tag.hasTaggable( dm )){
-											
-											tag.removeTaggable( dm );
-											
-										}else{
-										
-											tag.addTaggable( dm );
-										}
-									}
-								}catch ( Throwable t ){
-	
+							}
+							
+							for (DownloadManager dm : listDMs) {
+								if ( doAdd ){
+									
+									tag.addTaggable( dm );
+									
+								}else{
+									
+									tag.removeTaggable( dm );
 								}
 							}
 						}
 					}
-	
-					return true;
-				}
-			};
-			
-			boolean tag_auto = tag.isTagAuto();
-			
-			entry.setUserData( TAG_DATA_KEY, new Object[]{ dl, tag_auto });
-			
-			if ( !tag_auto ){
+				};
+				
+				boolean tag_auto = tag.isTagAuto();
 				
-				entry.addListener( dl );
+				entry.setUserData( TAG_DATA_KEY, new Object[]{ dl, tag_auto });
+				
+				if ( !tag_auto ){
+					
+					entry.addListener( dl );
+				}
 			}
+			return entry;
 		}
 	}
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Vuze.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Vuze.java
index 5b5afa9..823ea51 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Vuze.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SB_Vuze.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.views.skin;
 
 import java.util.ArrayList;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SearchResultsTabArea.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SearchResultsTabArea.java
index 45df6ee..fc78406 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SearchResultsTabArea.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SearchResultsTabArea.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,22 +13,23 @@
  * 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 java.io.File;
 import java.net.InetSocketAddress;
-import java.net.Proxy;
 import java.net.URL;
 import java.util.*;
 import java.util.List;
 
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.browser.*;
+import org.eclipse.swt.browser.TitleListener;
+import org.eclipse.swt.browser.TitleEvent;
+import org.eclipse.swt.browser.ProgressListener;
+import org.eclipse.swt.browser.ProgressEvent;
+import org.eclipse.swt.browser.LocationListener;
+import org.eclipse.swt.browser.LocationEvent;
 import org.eclipse.swt.layout.FormAttachment;
 import org.eclipse.swt.layout.FormData;
 import org.eclipse.swt.widgets.*;
@@ -52,6 +53,7 @@ import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfoManager;
 import com.aelitis.azureus.ui.mdi.*;
 import com.aelitis.azureus.ui.skin.SkinConstants;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
+import org.gudy.azureus2.ui.swt.BrowserWrapper;
 import com.aelitis.azureus.ui.swt.browser.*;
 import com.aelitis.azureus.ui.swt.browser.BrowserContext.loadingListener;
 import com.aelitis.azureus.ui.swt.browser.listener.ExternalLoginCookieListener;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinView.java
index e4e569f..b0b2a99 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinView.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
@@ -50,6 +47,8 @@ public abstract class SkinView
 	protected SWTSkinObject soMain;
 
 	protected SWTSkin skin;
+	
+	private boolean disposed = false;
 
 	/**
 	 * 
@@ -102,6 +101,8 @@ public abstract class SkinView
 	
 	// @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#skinObjectDestroyed(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
 	public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) {
+		disposed = true;
+
 		SkinViewManager.remove(this);
 		if (this instanceof UIUpdatable) {
 			UIUpdatable updateable = (UIUpdatable) this;
@@ -114,6 +115,10 @@ public abstract class SkinView
 		}
 		return null;
 	}
+	
+	public boolean isDisposed() {
+		return disposed;
+	}
 
 	/**
 	 * @param skinObject
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinViewManager.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinViewManager.java
index 312d126..fcb7e47 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinViewManager.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinViewManager.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinnedDialog.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinnedDialog.java
index 7d06ced..598e2f5 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinnedDialog.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/SkinnedDialog.java
@@ -1,10 +1,12 @@
 /**
  * Created on Dec 23, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -64,12 +66,23 @@ public class SkinnedDialog
 				skinFile, shellSkinObjectID, style);
 	}
 
+	public SkinnedDialog(String skinFile, String shellSkinObjectID, Shell parent, int style) {
+		this(SkinnedDialog.class.getClassLoader(), "com/aelitis/azureus/ui/skin/",
+				skinFile, shellSkinObjectID, parent, style);
+	}
+	
 	public SkinnedDialog(ClassLoader cla, String skinPath, String skinFile,
 			String shellSkinObjectID, int style) {
+		this( cla, skinPath, skinFile, shellSkinObjectID, UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell(), style );
+	}
+	
+	public SkinnedDialog(ClassLoader cla, String skinPath, String skinFile,
+			String shellSkinObjectID, Shell parent, int style)
+	{
 		this.shellSkinObjectID = shellSkinObjectID;
 
 		mainShell = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell();
-		shell = ShellFactory.createShell(mainShell, style);
+		shell = ShellFactory.createShell(parent, style);
 
 		Utils.setShellIcon(shell);
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/StandardButtonsArea.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/StandardButtonsArea.java
index 610d626..d745a32 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/StandardButtonsArea.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/StandardButtonsArea.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.views.skin;
 
 import java.util.HashMap;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/ToolBarView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/ToolBarView.java
index 459319f..2ed02f7 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/ToolBarView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/ToolBarView.java
@@ -1,9 +1,11 @@
 /**
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -32,18 +34,18 @@ import org.gudy.azureus2.core3.global.GlobalManager;
 import org.gudy.azureus2.core3.util.AERunnable;
 import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.core3.util.FrequencyLimitedDispatcher;
-import org.gudy.azureus2.plugins.PluginInterface;
 import org.gudy.azureus2.plugins.ui.UIPluginViewToolBarListener;
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarActivationListener;
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarEnablerBase;
-import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
+import org.gudy.azureus2.plugins.ui.toolbar.*;
 import org.gudy.azureus2.ui.swt.TorrentUtil;
 import org.gudy.azureus2.ui.swt.Utils;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UIToolBarItemImpl;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UIToolBarManagerCore;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UIToolBarManagerImpl;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UIToolBarManagerImpl.ToolBarManagerListener;
 
 import com.aelitis.azureus.core.AzureusCoreFactory;
-import com.aelitis.azureus.ui.common.ToolBarEnabler;
 import com.aelitis.azureus.ui.common.ToolBarItem;
+import com.aelitis.azureus.ui.common.table.TableView;
 import com.aelitis.azureus.ui.selectedcontent.*;
 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.mdi.MdiEntrySWT;
@@ -53,7 +55,6 @@ import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapte
 import com.aelitis.azureus.ui.swt.toolbar.ToolBarItemSO;
 import com.aelitis.azureus.util.DLReferals;
 import com.aelitis.azureus.util.PlayUtils;
-import com.aelitis.azureus.util.StringCompareUtils;
 
 /**
  * @author TuxPaper
@@ -61,58 +62,114 @@ import com.aelitis.azureus.util.StringCompareUtils;
  */
 public class ToolBarView
 	extends SkinView
-	implements UIToolBarManagerCore, SelectedContentListener
+	implements SelectedContentListener, ToolBarManagerListener,
+	ToolBarItem.ToolBarItemListener
 {
 	private static boolean DEBUG = false;
 
 	private static toolbarButtonListener buttonListener;
 
-	private Map<String, List<String>> mapGroupToItemIDs = new HashMap<String, List<String>>();
-	
-	private Map<String, ToolBarItem> items = new LinkedHashMap<String, ToolBarItem>();
-
-	//private GlobalManager gm;
-
-	Control lastControl = null;
+	private Map<UIToolBarItem, ToolBarItemSO> mapToolBarItemToSO = new HashMap<UIToolBarItem, ToolBarItemSO>();
 
 	private boolean showText = true;
 
-	private SWTSkinObject so2nd;
-
 	private boolean initComplete = false;
-	
+
 	private boolean showCalled = false;
 
 	private ArrayList<ToolBarViewListener> listeners = new ArrayList<ToolBarViewListener>(
 			1);
 
+	private UIToolBarManagerCore tbm;
+
+	private boolean firstTimeEver = true;
+
+	public ToolBarView() {
+		tbm = (UIToolBarManagerCore) UIToolBarManagerImpl.getInstance();
+	}
+
+	private ToolBarItem createItem(ToolBarView tbv, String id, String imageid,
+			String textID) {
+		UIToolBarItemImpl base = new UIToolBarItemImpl(id);
+		base.setImageID(imageid);
+		base.setTextID(textID);
+		return base;
+	}
+
 	// @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) {
+	public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) {
 		boolean uiClassic = COConfigurationManager.getStringParameter("ui").equals(
 				"az2");
-		
+
 		if (uiClassic && !"global-toolbar".equals(skinObject.getViewID())) {
 			skinObject.setVisible(false);
 			return null;
 		}
 
-		buttonListener = new toolbarButtonListener();
-		//SWTSkin skin = skinObject.getSkin();
-		so2nd = skin.getSkinObject("toolbar-2nd", skinObject);
+			// walk up skins to see if toolbar explicitly disabled (for pop-out views for example)
 		
-		if (so2nd == null) {
-			skinObject.setVisible(false);
-			return null;
+		SWTSkinObject temp = skinObject;
+		
+		while( temp != null ){
+			
+			int visible = temp.getSkin().getSkinProperties().getIntValue( "mdientry.toolbar.visible", 1 );
+			
+			if ( visible == 0 ){
+				
+				skinObject.setVisible(false);
+				
+				return null;	
+			}
+			
+			temp = temp.getParent();
 		}
+		
+		buttonListener = new toolbarButtonListener();
+
 
-		ToolBarItemSO item;
+		if (firstTimeEver) {
+			firstTimeEver = false;
+			setupToolBarItems(uiClassic);
+		}
+		tbm.addListener(this);
 
 		if (uiClassic) {
-			lastControl = null;
+			bulkSetupItems("classic", "toolbar.area.sitem");
+		}
+		bulkSetupItems(UIToolBarManager.GROUP_MAIN, "toolbar.area.sitem");
+		bulkSetupItems("views", "toolbar.area.vitem");
+		
+		String[] groupIDs = tbm.getGroupIDs();
+		for (String groupID : groupIDs) {
+			if ("classic".equals(groupID)
+					|| UIToolBarManager.GROUP_MAIN.equals(groupID)
+					|| "views".equals(groupID)) {
+				continue;
+			}
+			bulkSetupItems(groupID, "toolbar.area.sitem");
+		}
+
+		initComplete = true;
 
+		synchronized (listeners) {
+			for (ToolBarViewListener l : listeners) {
+				try {
+					l.toolbarViewInitialized(this);
+				} catch (Exception e) {
+					Debug.out(e);
+				}
+			}
+		}
+
+		return null;
+	}
+
+	private void setupToolBarItems(boolean uiClassic) {
+		ToolBarItem item;
+
+		if (uiClassic) {
 			// ==OPEN
-			item = new ToolBarItemSO(this, "open", "image.toolbar.open", "Button.add");
+			item = createItem(this, "open", "image.toolbar.open", "Button.add");
 			item.setDefaultActivationListener(new UIToolBarActivationListener() {
 				public boolean toolBarItemActivated(ToolBarItem item,
 						long activationType, Object datasource) {
@@ -125,10 +182,10 @@ public class ToolBarView
 			});
 			item.setAlwaysAvailable(true);
 			item.setGroupID("classic");
-			addToolBarItemNoCreate(item);
+			tbm.addToolBarItem(item, false);
 
 			// ==SEARCH
-			item = new ToolBarItemSO(this, "search", "search", "Button.search");
+			item = createItem(this, "search", "search", "Button.search");
 			item.setDefaultActivationListener(new UIToolBarActivationListener() {
 				public boolean toolBarItemActivated(ToolBarItem item,
 						long activationType, Object datasource) {
@@ -141,13 +198,12 @@ public class ToolBarView
 			});
 			item.setAlwaysAvailable(true);
 			item.setGroupID("classic");
-			addToolBarItemNoCreate(item);
+			tbm.addToolBarItem(item, false);
 		}
 
 		if (!uiClassic) {
 			// ==play
-			item = new ToolBarItemSO(this, "play", "image.button.play",
-					"iconBar.play");
+			item = createItem(this, "play", "image.button.play", "iconBar.play");
 			item.setDefaultActivationListener(new UIToolBarActivationListener() {
 				public boolean toolBarItemActivated(ToolBarItem item,
 						long activationType, Object datasource) {
@@ -157,7 +213,7 @@ public class ToolBarView
 					ISelectedContent[] sc = SelectedContentManager.getCurrentlySelectedContent();
 					if (sc != null && sc.length > 0) {
 
-						if (PlayUtils.canStreamDS(sc[0], sc[0].getFileIndex())) {
+						if (PlayUtils.canStreamDS(sc[0], sc[0].getFileIndex(),true)) {
 							TorrentListViewsUtils.playOrStreamDataSource(sc[0],
 									DLReferals.DL_REFERAL_TOOLBAR, true, false);
 						} else {
@@ -168,31 +224,37 @@ public class ToolBarView
 					return false;
 				}
 			});
-			addToolBarItemNoCreate(item);
+			tbm.addToolBarItem(item, false);
 		}
 
 		// ==run
-		item = new ToolBarItemSO(this, "run", "image.toolbar.run", "iconBar.run");
+		item = createItem(this, "run", "image.toolbar.run", "iconBar.run");
 		item.setDefaultActivationListener(new UIToolBarActivationListener() {
 			public boolean toolBarItemActivated(ToolBarItem item,
 					long activationType, Object datasource) {
 				if (activationType != ACTIVATIONTYPE_NORMAL) {
 					return false;
 				}
-				DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent();
-				if (dms != null) {
-					TorrentUtil.runDataSources(dms);
+				TableView tv = SelectedContentManager.getCurrentlySelectedTableView();
+				Object[] ds;
+				if (tv != null) {
+					ds = tv.getSelectedDataSources().toArray();
+				} else {
+					ds = SelectedContentManager.getDMSFromSelectedContent();
+				}
+				if (ds != null) {
+					TorrentUtil.runDataSources(ds);
 					return true;
 				}
 				return false;
 			}
 		});
-		addToolBarItemNoCreate(item);
+		tbm.addToolBarItem(item, false);
 		//addToolBarItem(item, "toolbar.area.sitem", so2nd);
 
 		if (uiClassic) {
 			// ==TOP
-			item = new ToolBarItemSO(this, "top", "image.toolbar.top", "iconBar.top");
+			item = createItem(this, "top", "image.toolbar.top", "iconBar.top");
 			item.setDefaultActivationListener(new UIToolBarActivationListener() {
 				public boolean toolBarItemActivated(ToolBarItem item,
 						long activationType, Object datasource) {
@@ -203,11 +265,11 @@ public class ToolBarView
 					return false;
 				}
 			});
-			addToolBarItemNoCreate(item);
+			tbm.addToolBarItem(item, false);
 		}
 
 		// ==UP
-		item = new ToolBarItemSO(this, "up", "image.toolbar.up", "v3.iconBar.up");
+		item = createItem(this, "up", "image.toolbar.up", "v3.iconBar.up");
 		item.setDefaultActivationListener(new UIToolBarActivationListener() {
 			public boolean toolBarItemActivated(ToolBarItem item,
 					long activationType, Object datasource) {
@@ -236,11 +298,10 @@ public class ToolBarView
 				return false;
 			}
 		});
-		addToolBarItemNoCreate(item);
+		tbm.addToolBarItem(item, false);
 
 		// ==down
-		item = new ToolBarItemSO(this, "down", "image.toolbar.down",
-				"v3.iconBar.down");
+		item = createItem(this, "down", "image.toolbar.down", "v3.iconBar.down");
 		item.setDefaultActivationListener(new UIToolBarActivationListener() {
 			public boolean toolBarItemActivated(ToolBarItem item,
 					long activationType, Object datasource) {
@@ -271,11 +332,11 @@ public class ToolBarView
 				return false;
 			}
 		});
-		addToolBarItemNoCreate(item);
+		tbm.addToolBarItem(item, false);
 
 		if (uiClassic) {
 			// ==BOTTOM
-			item = new ToolBarItemSO(this, "bottom", "image.toolbar.bottom",
+			item = createItem(this, "bottom", "image.toolbar.bottom",
 					"iconBar.bottom");
 			item.setDefaultActivationListener(new UIToolBarActivationListener() {
 				public boolean toolBarItemActivated(ToolBarItem item,
@@ -286,11 +347,11 @@ public class ToolBarView
 					return moveBottom();
 				}
 			});
-			addToolBarItemNoCreate(item);
+			tbm.addToolBarItem(item, false);
 		}
 		/*
 				// ==start
-				item = new ToolBarItemSO(this, "start", "image.toolbar.start", "iconBar.start");
+				item = createItemSO(this, "start", "image.toolbar.start", "iconBar.start");
 				item.setDefaultActivation(new UIToolBarActivationListener() {
 					public boolean toolBarItemActivated(ToolBarItem item, long activationType) {
 						if (activationType != ACTIVATIONTYPE_NORMAL) {
@@ -310,7 +371,7 @@ public class ToolBarView
 				addSeperator(so2nd);
 
 				// ==stop
-				item = new ToolBarItemSO(this, "stop", "image.toolbar.stop", "iconBar.stop");
+				item = createItemSO(this, "stop", "image.toolbar.stop", "iconBar.stop");
 				item.setDefaultActivation(new UIToolBarActivationListener() {
 					public boolean toolBarItemActivated(ToolBarItem item, long activationType) {
 						if (activationType != ACTIVATIONTYPE_NORMAL) {
@@ -325,8 +386,8 @@ public class ToolBarView
 				addSeperator(so2nd);
 		*/
 		// ==startstop
-		item = new ToolBarItemSO(this, "startstop",
-				"image.toolbar.startstop.start", "iconBar.startstop");
+		item = createItem(this, "startstop", "image.toolbar.startstop.start",
+				"iconBar.startstop");
 		item.setDefaultActivationListener(new UIToolBarActivationListener() {
 			public boolean toolBarItemActivated(ToolBarItem item,
 					long activationType, Object datasource) {
@@ -338,138 +399,94 @@ public class ToolBarView
 				return true;
 			}
 		});
-		addToolBarItemNoCreate(item);
+		tbm.addToolBarItem(item, false);
 
 		// ==remove
-		item = new ToolBarItemSO(this, "remove", "image.toolbar.remove",
-				"iconBar.remove");
+		item = createItem(this, "remove", "image.toolbar.remove", "iconBar.remove");
 		item.setDefaultActivationListener(new UIToolBarActivationListener() {
 			public boolean toolBarItemActivated(ToolBarItem item,
 					long activationType, Object datasource) {
 				if (activationType != ACTIVATIONTYPE_NORMAL) {
 					return false;
 				}
-				DownloadManager[] dms = SelectedContentManager.getDMSFromSelectedContent();
-				if (dms != null) {
-					TorrentUtil.removeDownloads(dms, null);
-					return true;
-				}
-				return false;
+				TorrentUtil.removeDataSources(
+						SelectedContentManager.getCurrentlySelectedContent());
+				return true;
 			}
 		});
-		addToolBarItemNoCreate(item);
+		tbm.addToolBarItem(item, false);
 
 		///////////////////////
 
 		// == mode big
-		item = new ToolBarItemSO(this, "modeBig", "image.toolbar.table_large",
-				"v3.iconBar.view.big") {
-			public void setSkinButton(SWTSkinButtonUtility btn) {
-				super.setSkinButton(btn);
-				SWTSkinObject soTitle = skin.getSkinObject("toolbar-item-title",
-						btn.getSkinObject());
-				if (soTitle instanceof SWTSkinObjectText) {
-					((SWTSkinObjectText) soTitle).setStyle(SWT.RIGHT);
-				}
-			}
-		};
+		item = createItem(this, "modeBig", "image.toolbar.table_large",
+				"v3.iconBar.view.big");
 		item.setGroupID("views");
-		addToolBarItemNoCreate(item);
+		tbm.addToolBarItem(item, false);
 
 		// == mode small
-		item = new ToolBarItemSO(this, "modeSmall", "image.toolbar.table_normal",
-				"v3.iconBar.view.small") {
-			
-			public void setSkinButton(SWTSkinButtonUtility btn) {
-				super.setSkinButton(btn);
-				SWTSkinObject soTitle = skin.getSkinObject("toolbar-item-title",
-						btn.getSkinObject());
-				if (soTitle instanceof SWTSkinObjectText) {
-					((SWTSkinObjectText) soTitle).setStyle(SWT.LEFT);
-				}
-			}
-		};
+		item = createItem(this, "modeSmall", "image.toolbar.table_normal",
+				"v3.iconBar.view.small");
 		item.setGroupID("views");
-		addToolBarItemNoCreate(item);
-
-		
-		//addSeperator(so2nd);
-
-		if (uiClassic) {
-			bulkSetupItems("classic", "toolbar.area.sitem", so2nd);
-			addNonToolBar("toolbar.area.sitem.left2", so2nd);
-		}
-		bulkSetupItems(GROUP_MAIN, "toolbar.area.sitem", so2nd);
-		addNonToolBar("toolbar.area.sitem.left2", so2nd);
-		bulkSetupItems("views", "toolbar.area.vitem", so2nd);
-		addNonToolBar("toolbar.area.sitem.left2", so2nd);
-		
-		Utils.execSWTThreadLater(0, new Runnable() {
-			public void run() {
-				Utils.relayout(so2nd.getControl());
-			}
-		});
-
-		initComplete = true;
-
-		synchronized (listeners) {
-			for (ToolBarViewListener l : listeners) {
-				try {
-					l.toolbarViewInitialized(this);
-				} catch (Exception e) {
-					Debug.out(e);
-				}
-			}
-		}
-
-		return null;
+		tbm.addToolBarItem(item, false);
 	}
 
-	String lastViewID = null;
 	public void currentlySelectedContentChanged(
 			ISelectedContent[] currentContent, String viewID) {
 		//System.err.println("currentlySelectedContentChanged " + viewID + ";" + currentContent + ";" + getMainSkinObject() + this + " via " + Debug.getCompressedStackTrace());
-		if (!StringCompareUtils.equals(lastViewID, viewID)) {
-			lastViewID = viewID;
-			ToolBarItem[] allToolBarItems = getAllSWTToolBarItems();
-			for (int i = 0; i < allToolBarItems.length; i++) {
-				UIToolBarItem toolBarItem = allToolBarItems[i];
-				if (toolBarItem instanceof ToolBarItemSO) {
-					toolBarItem.setState(((ToolBarItemSO) toolBarItem).getDefaultState());
-				} else {
-					toolBarItem.setState(0);
-				}
-			}
-		}
 		refreshCoreToolBarItems();
-		//updateCoreItems(currentContent, viewID);
 		UIFunctionsManagerSWT.getUIFunctionsSWT().refreshTorrentMenu();
 	}
 
 	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectShown(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
 	public Object skinObjectShown(SWTSkinObject skinObject, Object params) {
-		
+
 		if (showCalled) {
 			return null;
 		}
 		showCalled = true;
-		SelectedContentManager.addCurrentlySelectedContentListener(this);
 
-		return super.skinObjectShown(skinObject, params);
+		Object object = super.skinObjectShown(skinObject, params);
+		
+  	ToolBarItem[] allToolBarItems = tbm.getAllSWTToolBarItems();
+  	for (int i = 0; i < allToolBarItems.length; i++) {
+  		ToolBarItem toolBarItem = allToolBarItems[i];
+  		toolBarItem.addToolBarItemListener(this);
+  		uiFieldChanged(toolBarItem);
+  	}
+
+		
+		SelectedContentManager.addCurrentlySelectedContentListener(this);
+		return object;
 	}
-	
+
 	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectHidden(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
 	public Object skinObjectHidden(SWTSkinObject skinObject, Object params) {
 		showCalled = false;
 		SelectedContentManager.removeCurrentlySelectedContentListener(this);
 
+  	ToolBarItem[] allToolBarItems = tbm.getAllSWTToolBarItems();
+  	for (int i = 0; i < allToolBarItems.length; i++) {
+  		ToolBarItem toolBarItem = allToolBarItems[i];
+  		toolBarItem.removeToolBarItemListener(this);
+  	}
+
 		return super.skinObjectHidden(skinObject, params);
 	}
 
+	// @see com.aelitis.azureus.ui.swt.views.skin.SkinView#skinObjectDestroyed(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object)
+	public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) {
+		tbm.removeListener(this);
+
+		return super.skinObjectDestroyed(skinObject, params);
+	}
+
 	public boolean triggerToolBarItem(ToolBarItem item, long activationType,
 			Object datasource) {
-		if (DEBUG && !isVisible()) {
-			Debug.out("Trying to triggerToolBarItem when toolbar is not visible");
+		if (!isVisible()) {
+			if (DEBUG) {
+				Debug.out("Trying to triggerToolBarItem when toolbar is not visible");
+			}
 			return false;
 		}
 		if (triggerViewToolBar(item, activationType, datasource)) {
@@ -504,7 +521,6 @@ public class ToolBarView
 		return true;
 	}
 
-
 	protected boolean moveTop() {
 		if (!AzureusCoreFactory.isCoreRunning()) {
 			return false;
@@ -517,22 +533,6 @@ public class ToolBarView
 		return true;
 	}
 
-	public UIToolBarItem getToolBarItem(String itemID) {
-		return items.get(itemID);
-	}
-
-	public ToolBarItemSO getToolBarItemSO(String itemID) {
-		return (ToolBarItemSO) items.get(itemID);
-	}
-
-	public UIToolBarItem[] getAllToolBarItems() {
-		return items.values().toArray(new ToolBarItem[0]);
-	}
-
-	public ToolBarItem[] getAllSWTToolBarItems() {
-		return items.values().toArray(new ToolBarItem[0]);
-	}
-
 	private FrequencyLimitedDispatcher refresh_limiter = new FrequencyLimitedDispatcher(
 			new AERunnable() {
 				private AERunnable lock = this;
@@ -570,52 +570,43 @@ public class ToolBarView
 
 	private IdentityHashMap<DownloadManager, DownloadManagerListener> dm_listener_map = new IdentityHashMap<DownloadManager, DownloadManagerListener>();
 
+	private SWTSkinObject soLastGroup;
+
 	public void refreshCoreToolBarItems() {
+		if (DEBUG) {
+			System.out.println("refreshCoreItems Start via "
+					+ Debug.getCompressedStackTrace());
+		}
 		refresh_limiter.dispatch();
 	}
 
 	public void _refreshCoreToolBarItems() {
 		if (DEBUG && !isVisible()) {
-			Debug.out("Trying to refresh core toolbar items when toolbar is not visible " + this + getMainSkinObject());
+			Debug.out("Trying to refresh core toolbar items when toolbar is not visible "
+					+ this + getMainSkinObject());
 		}
 
 		MultipleDocumentInterfaceSWT mdi = UIFunctionsManagerSWT.getUIFunctionsSWT().getMDISWT();
 
 		if (mdi != null) {
-			UIToolBarItem[] allToolBarItems = getAllToolBarItems();
+			UIToolBarItem[] allToolBarItems = tbm.getAllToolBarItems();
 			MdiEntrySWT entry = mdi.getCurrentEntrySWT();
 			Map<String, Long> mapStates = new HashMap<String, Long>();
 			if (entry != null) {
 				UIToolBarEnablerBase[] enablers = entry.getToolbarEnablers();
 				for (UIToolBarEnablerBase enabler : enablers) {
 					if (enabler instanceof UIPluginViewToolBarListener) {
-						try{
+						try {
 							((UIPluginViewToolBarListener) enabler).refreshToolBarItems(mapStates);
-						}catch( Throwable e ){
-							Debug.out( e );	// don't trust them plugins
-						}
-					} else if (enabler instanceof ToolBarEnabler) {
-						Map<String, Boolean> oldMapStates = new HashMap<String, Boolean>();
-						((ToolBarEnabler) enabler).refreshToolBar(oldMapStates);
-
-						for ( Map.Entry<String,Boolean> e: oldMapStates.entrySet()){
-							String key = e.getKey();
-							Boolean enable = e.getValue();
-							Long curState = mapStates.get(key);
-							if (curState == null) {
-								curState = 0L;
-							}
-							if (enable) {
-								mapStates.put(key, curState | UIToolBarItem.STATE_ENABLED);
-							} else {
-								mapStates.put(key, curState & (~UIToolBarItem.STATE_ENABLED));
-							}
+						} catch (Throwable e) {
+							Debug.out(e); // don't trust them plugins
 						}
 					}
 				}
 			}
 
 			ISelectedContent[] currentContent = SelectedContentManager.getCurrentlySelectedContent();
+			//System.out.println("_refreshCoreToolBarItems(" + currentContent.length + ", " + entry + " via " + Debug.getCompressedStackTrace());
 
 			synchronized (dm_listener_map) {
 
@@ -626,14 +617,14 @@ public class ToolBarView
 
 					DownloadManager dm = content.getDownloadManager();
 
-					if ( dm != null ){
+					if (dm != null) {
 
-						copy.remove( dm );
-						
-							// so in files view we can have multiple selections that map onto the SAME download manager
-							// - ensure that we only add the listener once!
-						
-						if ( !dm_listener_map.containsKey( dm )) {
+						copy.remove(dm);
+
+						// so in files view we can have multiple selections that map onto the SAME download manager
+						// - ensure that we only add the listener once!
+
+						if (!dm_listener_map.containsKey(dm)) {
 
 							DownloadManagerListener l = new DownloadManagerListener() {
 								public void stateChanged(DownloadManager manager, int state) {
@@ -681,15 +672,6 @@ public class ToolBarView
 				}
 			}
 
-			if (!mapStates.containsKey("download")) {
-				for (ISelectedContent content : currentContent) {
-					if (content.getDownloadManager() == null
-							&& content.getDownloadInfo() != null) {
-						mapStates.put("download", UIToolBarItem.STATE_ENABLED);
-						break;
-					}
-				}
-			}
 			boolean has1Selection = currentContent.length == 1;
 
 			boolean can_play = false;
@@ -702,9 +684,9 @@ public class ToolBarView
 				if (!(currentContent[0] instanceof ISelectedVuzeFileContent)) {
 
 					can_play = PlayUtils.canPlayDS(currentContent[0],
-							currentContent[0].getFileIndex());
+							currentContent[0].getFileIndex(),false);
 					can_stream = PlayUtils.canStreamDS(currentContent[0],
-							currentContent[0].getFileIndex());
+							currentContent[0].getFileIndex(),false);
 
 					if (can_stream) {
 
@@ -722,10 +704,10 @@ public class ToolBarView
 				can_stream |= (mapStates.get("stream") & UIToolBarItem.STATE_ENABLED) > 0;
 			}
 
-			mapStates.put("play", can_play | can_stream
-					? UIToolBarItem.STATE_ENABLED : 0);
+			mapStates.put("play", can_play | can_stream ? UIToolBarItem.STATE_ENABLED
+					: 0);
 
-			UIToolBarItem pitem = getToolBarItem("play");
+			UIToolBarItem pitem = tbm.getToolBarItem("play");
 
 			if (pitem != null) {
 
@@ -743,14 +725,59 @@ public class ToolBarView
 				}
 			}
 
-			UIToolBarItem ssItem = getToolBarItem("startstop");
-			if (ssItem != null) {
-				boolean shouldStopGroup = TorrentUtil.shouldStopGroup(currentContent);
+			UIToolBarItem ssItem = tbm.getToolBarItem("startstop");
+			if (ssItem != null){
+				
+				boolean shouldStopGroup;
+				
+					// if no selected content set then use the 'start' key to determine the start/stop
+					// toolbar state (required for archived downloads)
+					// alternative solution would be for the view to start updating the current selected
+					// content which is a little painful
+				
+				if ( 	currentContent.length == 0 &&
+						mapStates.containsKey( "start" ) && 
+						!mapStates.containsKey( "stop" ) && 
+						( mapStates.get("start") & UIToolBarItem.STATE_ENABLED) > 0 ){
+					
+					shouldStopGroup = false;
+					
+				}else{
+					shouldStopGroup = TorrentUtil.shouldStopGroup(currentContent);
+				}
+				
 				ssItem.setTextID(shouldStopGroup ? "iconBar.stop" : "iconBar.start");
 				ssItem.setImageID("image.toolbar.startstop."
 						+ (shouldStopGroup ? "stop" : "start"));
 			}
 
+			
+			Map<String, Long> fallBackStates = TorrentUtil.calculateToolbarStates(currentContent, null);
+			for (String key : fallBackStates.keySet()) {
+				if (!mapStates.containsKey(key)) {
+					mapStates.put(key, fallBackStates.get(key));
+				}
+			}
+
+
+			final String[] TBKEYS = new String[] {
+				"play",
+				"run",
+				"top",
+				"up",
+				"down",
+				"bottom",
+				"start",
+				"stop",
+				"startstop",
+				"remove"
+			};
+			for (String key : TBKEYS) {
+				if (!mapStates.containsKey(key)) {
+					mapStates.put(key, 0L);
+				}
+			}
+
 			for (int i = 0; i < allToolBarItems.length; i++) {
 				UIToolBarItem toolBarItem = allToolBarItems[i];
 				Long state = mapStates.get(toolBarItem.getID());
@@ -758,37 +785,38 @@ public class ToolBarView
 					toolBarItem.setState(state);
 				}
 			}
-			
-			if ( ssItem != null ){
-				
-					// fallback to handle start/stop settings when no explicit selected content (e.g. for devices transcode view)
-				
-				if ( currentContent.length == 0 && !mapStates.containsKey( "startstop" )){
-					
-					boolean	can_stop 	= mapStates.containsKey("stop") && (mapStates.get("stop") & UIToolBarItem.STATE_ENABLED) > 0;
-					boolean	can_start 	= mapStates.containsKey("start") && (mapStates.get("start") & UIToolBarItem.STATE_ENABLED) > 0;
-					
-					if ( can_start && can_stop ){
-						
+
+			if (ssItem != null) {
+
+				// fallback to handle start/stop settings when no explicit selected content (e.g. for devices transcode view)
+
+				if (currentContent.length == 0 && !mapStates.containsKey("startstop")) {
+
+					boolean can_stop = mapStates.containsKey("stop")
+							&& (mapStates.get("stop") & UIToolBarItem.STATE_ENABLED) > 0;
+					boolean can_start = mapStates.containsKey("start")
+							&& (mapStates.get("start") & UIToolBarItem.STATE_ENABLED) > 0;
+
+					if (can_start && can_stop) {
+
 						can_stop = false;
 					}
-					
-					if ( can_start | can_stop ){
+
+					if (can_start | can_stop) {
 						ssItem.setTextID(can_stop ? "iconBar.stop" : "iconBar.start");
 						ssItem.setImageID("image.toolbar.startstop."
 								+ (can_stop ? "stop" : "start"));
-						
-						ssItem.setState( 1 );
-						
-					}else{
-						
-						ssItem.setState( 0 );
+
+						ssItem.setState(1);
+
+					} else {
+
+						ssItem.setState(0);
 					}
 				}
 			}
-			
-			return;
 		}
+		
 	}
 
 	private boolean triggerViewToolBar(ToolBarItem item, long activationType,
@@ -807,11 +835,6 @@ public class ToolBarView
 							item, activationType, datasource)) {
 						return true;
 					}
-				} else if (enabler instanceof ToolBarEnabler) {
-					if (activationType == UIToolBarActivationListener.ACTIVATIONTYPE_NORMAL
-							&& ((ToolBarEnabler) enabler).toolBarItemActivated(item.getID())) {
-						return true;
-					}
 				}
 			}
 		}
@@ -819,103 +842,59 @@ public class ToolBarView
 		return false;
 	}
 
-	/* (non-Javadoc)
-	 * @see org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager#createToolBarItem(java.lang.String)
-	 */
-	public UIToolBarItem createToolBarItem(String id) {
-		return new ToolBarItemSO(this, id, true);
-	}
-
-	public void addToolBarItem(UIToolBarItem item) {
-		if (item instanceof ToolBarItemSO) {
-			ToolBarItemSO itemSO = (ToolBarItemSO) item;
-			itemSO.setGroupID("plugin");
-			//addNonToolBar("toolbar.area.sitem.left2", so2nd);
-			addToolBarItem(itemSO, "toolbar.area.sitem", so2nd);
+	private void bulkSetupItems(String groupID, String templatePrefix) {
+		String[] idsByGroup = tbm.getToolBarIDsByGroup(groupID);
+		SWTSkinObjectContainer groupSO = getGroupSO(groupID);
+		SWTSkinObject[] children = groupSO.getChildren();
+		for (SWTSkinObject so : children) {
+			so.dispose();
 		}
-	}
-
-	public void addToolBarItemNoCreate(final ToolBarItemSO item) {
-		addToolBarItem(item, null, null);
-	}
-
-	public void addToolBarItem(final ToolBarItemSO item, String templatePrefix,
-			SWTSkinObject soMain) {
-		item.setDefaultState(item.getState());
-		String groupID = item.getGroupID();
 		
-		int position = SWT.RIGHT;
-
-		synchronized (mapGroupToItemIDs) {
-			List<String> list = mapGroupToItemIDs.get(groupID);
-			if (list == null) {
-				list = new ArrayList<String>();
-				mapGroupToItemIDs.put(groupID, list);
-				position = SWT.LEFT;
-			} else if (soMain != null && !groupID.equals(GROUP_BIG)) {
-				// take the last item and change it to RIGHT
-				int size = list.size();
-				String lastID = list.get(size - 1);
-				ToolBarItemSO lastItem = getToolBarItemSO(lastID);
-				if (lastItem != null) {
-					SWTSkinObject so = skin.getSkinObjectByID("toolbar:" + lastItem.getID());
-					if (so != null) {
-						String configID = so.getConfigID();
-						if ((size == 1 && !configID.endsWith(".left")) || !configID.equals(templatePrefix)) {
-    					setupToolBarItem(lastItem, templatePrefix, soMain, size == 1 ? SWT.LEFT
-    							: SWT.CENTER);
-						}
-					}
+		for (int i = 0; i < idsByGroup.length; i++) {
+			String itemID = idsByGroup[i];
+			UIToolBarItem item = tbm.getToolBarItem(itemID);
+			if (item instanceof ToolBarItem) {
+
+
+				int position = 0;
+				int size = idsByGroup.length;
+				if (size == 1) {
+					position = SWT.SINGLE;
+				} else if (i == 0) {
+					position = SWT.LEFT;
+				} else if (i == size - 1) {
+					addSeperator(groupID);
+					position = SWT.RIGHT;
+				} else {
+					addSeperator(groupID);
 				}
-
-				addSeperator(soMain);
+				createItemSO((ToolBarItem) item, templatePrefix, position);
 			}
-			list.add(item.getID());
 		}
-		
-		if (soMain != null) {
-			setupToolBarItem(item, templatePrefix, soMain, groupID.equals(GROUP_BIG)
-					? 0 : position);
-		} else {
-			items.put(item.getID(), item);
+
+		addNonToolBar("toolbar.area.sitem.left2", groupID);
+	}
+
+	private Control getLastControl(String groupID) {
+		SWTSkinObjectContainer groupSO = getGroupSO(groupID);
+		SWTSkinObject[] children = groupSO.getChildren();
+		if (children == null || children.length == 0) {
+			return null;
 		}
+		return children[children.length - 1].getControl();
 	}
 	
-	private void bulkSetupItems(String groupID, String templatePrefix, SWTSkinObject soMain) {
-		synchronized (mapGroupToItemIDs) {
-			List<String> list = mapGroupToItemIDs.get(groupID);
-			if (list == null) {
-				return;
-			}
-			for (int i = 0; i < list.size(); i++) {
-				String itemID = list.get(i);
-				SWTSkinObject so = skin.getSkinObjectByID("toolbar:" + itemID, soMain);
-				if (so != null) {
-					so.dispose();
-				}
-				ToolBarItemSO item = getToolBarItemSO(itemID);
-				if (item != null) {
-					int position = 0;
-					int size = list.size();
-					if (size == 1) {
-						position = SWT.SINGLE;
-					} else if (i == 0) {
-						position = SWT.LEFT;
-					} else if (i == size - 1) {
-						addSeperator(soMain);
-						position = SWT.RIGHT;
-					} else {
-						addSeperator(soMain);
-					}
-					setupToolBarItem(item, templatePrefix, soMain, position);
-				}
-				
+	private void createItemSO(ToolBarItem item, String templatePrefix,
+			 int position) {
+
+		ToolBarItemSO existingItemSO = mapToolBarItemToSO.get(item);
+		if (existingItemSO != null) {
+			SWTSkinObject so = existingItemSO.getSO();
+			if (so != null) {
+				so.dispose();
 			}
 		}
-	}
 
-	private void setupToolBarItem(final ToolBarItemSO item, String templatePrefix,
-			SWTSkinObject soMain, int position) {
 		String templateID = templatePrefix;
 		if (position == SWT.RIGHT) {
 			templateID += ".right";
@@ -925,79 +904,111 @@ public class ToolBarView
 			templateID += ".lr";
 		}
 
-		Control attachToControl = this.lastControl;
+		Control attachToControl = getLastControl(item.getGroupID());
 		String id = "toolbar:" + item.getID();
-		SWTSkinObject oldSO = skin.getSkinObjectByID(id, soMain);
-		if (oldSO != null) {
-			Object layoutData = oldSO.getControl().getLayoutData();
-			if (layoutData instanceof FormData) {
-				FormData fd = (FormData) layoutData;
-				if (fd.left != null) {
-					attachToControl = fd.left.control;
-				}
-			}
-			oldSO.dispose();
-		}
-		SWTSkinObject so = skin.createSkinObject(id, templateID, soMain);
+		SWTSkinObject so = skin.createSkinObject(id, templateID, getGroupSO(item.getGroupID()));
 		if (so != null) {
-			so.setTooltipID(item.getTooltipID());
+			ToolBarItemSO itemSO;
+			itemSO = new ToolBarItemSO((UIToolBarItemImpl) item, so);
 
-			if (lastControl != null) {
+			if (attachToControl != null) {
 				FormData fd = (FormData) so.getControl().getLayoutData();
 				fd.left = new FormAttachment(attachToControl);
 			}
-
-			so.setData("toolbaritem", item);
-			SWTSkinButtonUtility btn = new SWTSkinButtonUtility(so,
-					"toolbar-item-image");
-			btn.setImage(item.getImageID());
-			btn.addSelectionListener(buttonListener);
-			item.setSkinButton(btn);
-
-			SWTSkinObject soTitle = skin.getSkinObject("toolbar-item-title", so);
-			if (soTitle instanceof SWTSkinObjectText) {
-				((SWTSkinObjectText) soTitle).setTextID(item.getTextID());
-				item.setSkinTitle((SWTSkinObjectText) soTitle);
-			}
+			
+			initSO(so, itemSO);
 
 			if (initComplete) {
 				Utils.relayout(so.getControl().getParent());
 			}
+		}
+	}
+	
+	private SWTSkinObjectContainer getGroupSO(String groupID) {
+		String soID = "toolbar-group-" + groupID;
+		SWTSkinObjectContainer soGroup = (SWTSkinObjectContainer) skin.getSkinObjectByID(
+				soID, soMain);
+
+		if (soGroup == null) {
+			soGroup = (SWTSkinObjectContainer) skin.createSkinObject(soID,
+					"toolbar.group", soMain);
+			FormData fd = (FormData) soGroup.getControl().getLayoutData();
+			if (soLastGroup != null) {
+				fd.left = new FormAttachment(soLastGroup.getControl(), 0, SWT.RIGHT);
+			} else {
+				fd.left = new FormAttachment(0, 2);
+			}
+		}
+
+		soLastGroup = soGroup;
+
+		return soGroup;
+	}
+
+	private void initSO(SWTSkinObject so, ToolBarItemSO itemSO) {
+		ToolBarItem item = itemSO.getBase();
+		itemSO.setSO(so);
+		String toolTip = item.getToolTip();
+		if (toolTip != null) {
+			so.setTooltipID("!" + toolTip + "!");
+		} else {
+			so.setTooltipID(item.getTooltipID());
+		}
+		so.setData("toolbaritem", item);
+		SWTSkinButtonUtility btn = (SWTSkinButtonUtility) so.getData("btn");
+		if (btn == null) {
+			btn = new SWTSkinButtonUtility(so, "toolbar-item-image");
+			so.setData("btn", btn);
+		}
+		btn.setImage(item.getImageID());
+		btn.addSelectionListener(buttonListener);
+		itemSO.setSkinButton(btn);
+
+		SWTSkinObject soTitle = skin.getSkinObject("toolbar-item-title", so);
+		if (soTitle instanceof SWTSkinObjectText) {
+			((SWTSkinObjectText) soTitle).setTextID(item.getTextID());
+			itemSO.setSkinTitle((SWTSkinObjectText) soTitle);
+		}
+		mapToolBarItemToSO.put(item, itemSO);
+	}
 
-			lastControl = item.getSkinButton().getSkinObject().getControl();
+	// @see com.aelitis.azureus.ui.common.ToolBarItem.ToolBarItemListener#uiFieldChanged(com.aelitis.azureus.ui.common.ToolBarItem)
+	public void uiFieldChanged(ToolBarItem item) {
+		ToolBarItemSO itemSO = mapToolBarItemToSO.get(item);
+		if (itemSO != null) {
+			itemSO.updateUI();
 		}
-		items.put(item.getID(), item);
 	}
 
-	private void addSeperator(SWTSkinObject soMain) {
-		addSeperator("toolbar.area.sitem.sep", soMain);
+	private void addSeperator(String groupID) {
+		addSeperator("toolbar.area.sitem.sep", groupID);
 	}
 
-	private void addSeperator(String id, SWTSkinObject soMain) {
+	private void addSeperator(String id, String groupID) {
+		SWTSkinObjectContainer soGroup = getGroupSO(groupID);
+		Control lastControl = getLastControl(groupID);
 		SWTSkinObject so = skin.createSkinObject("toolbar_sep" + Math.random(), id,
-				soMain);
+				soGroup);
 		if (so != null) {
 			if (lastControl != null) {
 				FormData fd = (FormData) so.getControl().getLayoutData();
 				fd.left = new FormAttachment(lastControl, fd.left == null ? 0
 						: fd.left.offset);
 			}
-
-			lastControl = so.getControl();
 		}
 	}
 
-	private void addNonToolBar(String skinid, SWTSkinObject soMain) {
+	private void addNonToolBar(String skinid, String groupID) {
+		SWTSkinObjectContainer soGroup = getGroupSO(groupID);
+		Control lastControl = getLastControl(groupID);
 		SWTSkinObject so = skin.createSkinObject("toolbar_d" + Math.random(),
-				skinid, soMain);
+				skinid, soGroup);
 		if (so != null) {
 			if (lastControl != null) {
 				FormData fd = (FormData) so.getControl().getLayoutData();
 				fd.left = new FormAttachment(lastControl, fd.left == null ? 0
 						: fd.left.offset);
 			}
-
-			lastControl = so.getControl();
 		}
 	}
 
@@ -1006,7 +1017,7 @@ public class ToolBarView
 	 */
 	public void setShowText(boolean showText) {
 		this.showText = showText;
-		UIToolBarItem[] allToolBarItems = getAllToolBarItems();
+		UIToolBarItem[] allToolBarItems = tbm.getAllToolBarItems();
 		for (int i = 0; i < allToolBarItems.length; i++) {
 			UIToolBarItem tbi = allToolBarItems[i];
 			SWTSkinObject so = ((ToolBarItemSO) tbi).getSkinButton().getSkinObject();
@@ -1032,10 +1043,10 @@ public class ToolBarView
 			ToolBarItem item = (ToolBarItem) buttonUtility.getSkinObject().getData(
 					"toolbaritem");
 			boolean rightClick = (stateMask & (SWT.BUTTON3 | SWT.MOD4)) > 0;
+			Object o = SelectedContentManager.convertSelectedContentToObject(null);
 			item.triggerToolBarItem(rightClick
 					? UIToolBarActivationListener.ACTIVATIONTYPE_RIGHTCLICK
-					: UIToolBarActivationListener.ACTIVATIONTYPE_NORMAL,
-					SelectedContentManager.convertSelectedContentToObject(null));
+					: UIToolBarActivationListener.ACTIVATIONTYPE_NORMAL, o);
 		}
 
 		public boolean held(SWTSkinButtonUtility buttonUtility) {
@@ -1043,9 +1054,9 @@ public class ToolBarView
 					"toolbaritem");
 			buttonUtility.getSkinObject().switchSuffix("", 0, false, true);
 
+			Object o = SelectedContentManager.convertSelectedContentToObject(null);
 			boolean triggerToolBarItemHold = item.triggerToolBarItem(
-					UIToolBarActivationListener.ACTIVATIONTYPE_HELD,
-					SelectedContentManager.convertSelectedContentToObject(null));
+					UIToolBarActivationListener.ACTIVATIONTYPE_HELD, o);
 			return triggerToolBarItemHold;
 		}
 	}
@@ -1075,15 +1086,115 @@ public class ToolBarView
 		public void toolbarViewInitialized(ToolBarView tbv);
 	}
 
-	public void removeToolBarItem(String id) {
-		UIToolBarItem toolBarItem = items.remove(id);
-		if (toolBarItem instanceof ToolBarItemSO) {
-			ToolBarItemSO item = (ToolBarItemSO) toolBarItem;
-			item.dispose();
-			SWTSkinObject so = skin.getSkinObjectByID("toolbar:" + item.getID(), soMain);
-			if (so != null) {
-				so.dispose();
-			}
+	// @see org.gudy.azureus2.ui.swt.pluginsimpl.UIToolBarManagerImpl.ToolBarManagerListener#toolbarItemRemoved(org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem)
+	public void toolbarItemRemoved(final UIToolBarItem toolBarItem) {
+		ToolBarItemSO itemSO = mapToolBarItemToSO.get(toolBarItem);
+		if (itemSO == null) {
+			return;
 		}
+
+		itemSO.dispose();
+		final SWTSkinObject so = itemSO.getSO();
+		if (so != null) {
+			Utils.execSWTThread(new AERunnable() {
+				public void runSupport() {
+
+					String groupID = toolBarItem.getGroupID();
+					
+					final String[] idsByGroup = tbm.getToolBarIDsByGroup(groupID);
+					
+					if (idsByGroup.length <= 1) {
+						boolean b = initComplete;
+						initComplete = false;
+						bulkSetupItems(groupID, "toolbar.area.sitem");
+						initComplete = b;
+						so.getParent().relayout();
+						return;
+					}
+					
+					int posToolBarItem = -1;
+					String id = toolBarItem.getID();
+
+
+					Control soControl = so.getControl();
+					
+					
+					SWTSkinObject middleSO = mapToolBarItemToSO.get(
+							tbm.getToolBarItem(idsByGroup[idsByGroup.length / 2])).getSO();
+					
+
+					SWTSkinObject[] children = ((SWTSkinObjectContainer) so.getParent()).getChildren();
+					int middle = -1;
+					for (int i = 0; i < children.length; i++) {
+						if (children[i] == middleSO) {
+							middle = i;
+							break;
+						}
+					}
+					
+					if (middle == -1) {
+						return;
+					}
+					
+					
+					children[middle].dispose();
+					children[middle + 1].dispose();
+					
+					Control controlLeft = children[middle - 1].getControl();
+					FormData fd = (FormData) children[middle + 2].getControl().getLayoutData();
+					fd.left.control = controlLeft;
+					Utils.relayout(children[middle + 2].getControl());
+					
+					int positionInGroup = 0;
+					UIToolBarItem curItem = tbm.getToolBarItem(idsByGroup[positionInGroup]);
+
+					children = ((SWTSkinObjectContainer) so.getParent()).getChildren();
+					for (int i = 0; i < children.length; i++) {
+						SWTSkinObject child = children[i];
+						
+						ToolBarItem item = (ToolBarItem) child.getData("toolbaritem");
+						if (item != null && item.getGroupID().equals(groupID)) {
+						
+							ToolBarItemSO toolBarItemSO = mapToolBarItemToSO.get(curItem);
+							initSO(child, toolBarItemSO);
+							positionInGroup++;
+							if (positionInGroup >= idsByGroup.length) {
+								break;
+							}
+							curItem = tbm.getToolBarItem(idsByGroup[positionInGroup]);
+						}
+					}
+
+					so.getParent().relayout();
+				}
+			});
+		}
+		mapToolBarItemToSO.remove(toolBarItem);
+	}
+
+	// @see org.gudy.azureus2.ui.swt.pluginsimpl.UIToolBarManagerImpl.ToolBarManagerListener#toolbarItemAdded(org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem)
+	public void toolbarItemAdded(final UIToolBarItem item) {
+		if (isVisible()) {
+  		if (item instanceof ToolBarItem) {
+  			ToolBarItem toolBarItem = (ToolBarItem) item;
+  			toolBarItem.addToolBarItemListener(this);
+  		}
+		}
+
+		Utils.execSWTThread(new AERunnable() {
+			public void runSupport() {
+				boolean b = initComplete;
+				initComplete = false;
+				bulkSetupItems(item.getGroupID(), "toolbar.area.sitem");
+				initComplete = b;
+				
+				Utils.execSWTThreadLater(0, new Runnable() {
+					public void run() {
+						Utils.relayout(soMain.getControl());
+					}
+				});
+			}
+		});
 	}
+
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java
index db671a7..65d77e9 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/TorrentListViewsUtils.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/VuzeMessageBox.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/VuzeMessageBox.java
index c023aa1..8e3ec0c 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/VuzeMessageBox.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/VuzeMessageBox.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.views.skin;
 
 import java.util.*;
@@ -53,6 +71,8 @@ public class VuzeMessageBox
 
 	private StandardButtonsArea buttonsArea;
 
+	private String dialogTempate = "skin3_dlg_generic";
+
 	public VuzeMessageBox(final String title, final String text,
 			final String[] buttons, final int defaultOption) {
 		this.title = title;
@@ -132,6 +152,10 @@ public class VuzeMessageBox
 			}
 		});
 	}
+	
+	public void setSkinnedDialagTemplate(String dialogTempate) {
+		this.dialogTempate = dialogTempate;
+	}
 
 	protected void _open(UserPrompterResultListener l) {
 		if (l != null) {
@@ -139,7 +163,7 @@ public class VuzeMessageBox
   			resultListeners.add(l);
   		}
 		}
-		dlg = new SkinnedDialog("skin3_dlg_generic", "shell", SWT.DIALOG_TRIM) {
+		dlg = new SkinnedDialog(dialogTempate, "shell", SWT.DIALOG_TRIM) {
 			protected void setSkin(SWTSkin skin) {
 				super.setSkin(skin);
 				
@@ -265,6 +289,10 @@ public class VuzeMessageBox
 	public void setRememberText(String rememberText) {
 	}
 
+	public void setRememberOnlyIfButton(int button) {
+		// TODO Auto-generated method stub
+		
+	}
 	/* (non-Javadoc)
 	 * @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setUrl(java.lang.String)
 	 */
@@ -312,12 +340,14 @@ public class VuzeMessageBox
 							}
 						}
 					}
+					skinDialogClosed(dlg);
 					return buttonsArea.getButtonVal(result);
 				}
 			}
 			sem.reserve();
 		}
 
+		skinDialogClosed(dlg);
 		return buttonsArea.getButtonVal(result);
 	}
 
@@ -334,6 +364,7 @@ public class VuzeMessageBox
 					Debug.out(e);
 				}
 			}
+			resultListeners.clear();
 		}
 	}
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/VuzeMessageBoxListener.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/VuzeMessageBoxListener.java
index eb9610f..d57e97f 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/VuzeMessageBoxListener.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/VuzeMessageBoxListener.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.views.skin;
 
 import org.eclipse.swt.widgets.Shell;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/WelcomeView.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/WelcomeView.java
index a991347..53d6b26 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/WelcomeView.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/WelcomeView.java
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -13,9 +13,6 @@
  * 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;
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBar.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBar.java
index e633450..47b9a9b 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBar.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBar.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jun 23, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -26,39 +28,39 @@ import org.eclipse.swt.SWT;
 import org.eclipse.swt.dnd.*;
 import org.eclipse.swt.events.*;
 import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.*;
 import org.eclipse.swt.widgets.*;
-
 import org.gudy.azureus2.core3.config.COConfigurationManager;
 import org.gudy.azureus2.core3.config.ParameterListener;
 import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.plugins.PluginInterface;
+import org.gudy.azureus2.plugins.PluginManager;
 import org.gudy.azureus2.plugins.ui.*;
 import org.gudy.azureus2.plugins.ui.menus.MenuItem;
+import org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener;
 import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
-import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
-import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionHolder;
-import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionRepository;
-import org.gudy.azureus2.ui.common.util.MenuItemManager;
-import org.gudy.azureus2.ui.swt.MenuBuildUtils;
+import org.gudy.azureus2.plugins.ui.menus.MenuManager;
 import org.gudy.azureus2.ui.swt.URLTransfer;
 import org.gudy.azureus2.ui.swt.Utils;
 import org.gudy.azureus2.ui.swt.debug.ObfusticateImage;
 import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
 import org.gudy.azureus2.ui.swt.plugins.*;
-import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
+import org.gudy.azureus2.ui.swt.pluginsimpl.*;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTInstanceImpl.SWTViewListener;
 import org.gudy.azureus2.ui.swt.views.IViewAlwaysInitialize;
 
-import com.aelitis.azureus.ui.UIFunctions;
+import com.aelitis.azureus.core.AzureusCoreFactory;
 import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdater;
 import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
 import com.aelitis.azureus.ui.mdi.MdiEntry;
 import com.aelitis.azureus.ui.mdi.MdiEntryVitalityImage;
+import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
 import com.aelitis.azureus.ui.swt.mdi.*;
 import com.aelitis.azureus.ui.swt.skin.*;
 import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter;
 import com.aelitis.azureus.ui.swt.utils.FontUtils;
+import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog;
 
 /**
  * @author TuxPaper
@@ -114,13 +116,15 @@ public class SideBar
 
 	private Color bg;
 
-	private List<MdiSWTMenuHackListener> listMenuHackListners;
-
 	private List<SideBarEntrySWT> 	attention_seekers = new ArrayList<SideBarEntrySWT>();
 	private TimerEventPeriodic		attention_event;
 
+	private Composite cPluginsArea;
+
 	public static SideBar instance = null;
 
+	private List<UISWTViewCore> pluginViews = new ArrayList<UISWTViewCore>();
+
 	
 	public SideBar() {
 		super();
@@ -140,7 +144,18 @@ public class SideBar
 		soSideBarList = skin.getSkinObject("sidebar-list");
 		soSideBarPopout = skin.getSkinObject("sidebar-pop");
 
-		// addTestMenus();
+		SWTSkinObjectContainer soSideBarPluginsArea = (SWTSkinObjectContainer) skin.getSkinObject("sidebar-plugins");
+		if (soSideBarPluginsArea != null) {
+			Composite composite = soSideBarPluginsArea.getComposite();
+			cPluginsArea = new Composite(composite, SWT.NONE);
+			GridLayout layout = new GridLayout();
+			layout.marginHeight = layout.marginWidth = 0;
+			layout.verticalSpacing = layout.horizontalSpacing = 0;
+			cPluginsArea.setLayout(layout);
+			cPluginsArea.setLayoutData(Utils.getFilledFormData());
+		}
+
+		addGeneralMenus();
 
 		createSideBar();
 
@@ -181,48 +196,57 @@ public class SideBar
 	 *
 	 * @since 3.1.0.1
 	 */
-	/*
-	private void addTestMenus() {
-		// Add some test menus
+
+	private void addGeneralMenus() {
+		
 		PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager();
 		PluginInterface pi = pm.getDefaultPluginInterface();
 		UIManager uim = pi.getUIManager();
 		MenuManager menuManager = uim.getMenuManager();
-		MenuItem menuItem = menuManager.addMenuItem("sidebar", "test menu");
+		MenuItem menuItem = menuManager.addMenuItem("sidebar._end_", "menu.pop.out");
+		
+		menuItem.addFillListener(
+			new MenuItemFillListener() {
+					
+				public void menuWillBeShown(MenuItem menu, Object data) {
+					SideBarEntrySWT sbe = (SideBarEntrySWT)currentEntry;
+					
+					menu.setVisible( sbe != null && sbe.canBuildStandAlone());
+				}
+			});
+		
 		menuItem.addListener(new MenuItemListener() {
 			public void selected(MenuItem menu, Object target) {
-				ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class);
-				if (tb != null) {
-					System.out.println("Found download Toolbar");
-					ToolBarItem dlItem = tb.getToolBarItem("download");
-					System.out.println("Download ToolBar Item is " + dlItem);
-					if (dlItem != null) {
-						System.out.println(dlItem.getSkinButton().getSkinObject());
+				SideBarEntrySWT sbe = (SideBarEntrySWT)currentEntry;
+				
+				if ( sbe != null ){
+					SkinnedDialog skinnedDialog = 
+							new SkinnedDialog( 
+									"skin3_dlg_sidebar_popout", 
+									"shell",
+									null,	// standalone
+									SWT.RESIZE | SWT.MAX | SWT.DIALOG_TRIM);
+	
+					SWTSkin skin = skinnedDialog.getSkin();
+					
+					SWTSkinObjectContainer cont = sbe.buildStandAlone((SWTSkinObjectContainer)skin.getSkinObject( "content-area" ));
+						
+					if ( cont != null ){
+							
+						skinnedDialog.setTitle( sbe.getTitle());
+						
+						skinnedDialog.open();
+						
+					}else{
+						
+						skinnedDialog.close();
 					}
-					dlItem.setEnabled(!dlItem.isEnabled());
-				}
-
-				if (target instanceof SideBarEntry) {
-					SideBarEntry info = (SideBarEntry) target;
-					System.err.println(info.getId() + " of " + info.getParentID()
-							+ ";ds=" + info.getDatasource());
 				}
 			}
 		});
 
-		menuItem = menuManager.addMenuItem("sidebar." + SIDEBAR_SECTION_ACTIVITIES,
-				"Activity Only Menu");
-		menuItem.addListener(new MenuItemListener() {
-			public void selected(MenuItem menu, Object target) {
-				if (target instanceof SideBarEntry) {
-					SideBarEntry info = (SideBarEntry) target;
-					System.err.println(info.getId() + " of " + info.getParentID()
-							+ ";ds=" + info.getDatasource());
-				}
-			}
-		});
 	}
-	*/
+	
 
 	/**
 	 * 
@@ -291,42 +315,7 @@ public class SideBar
 	// @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) {
 
-		UIManager ui_manager = PluginInitializer.getDefaultInterface().getUIManager();
-		ui_manager.addUIListener(new UIManagerListener() {
-			public void UIDetached(UIInstance instance) {
-			}
-			
-			public void UIAttached(UIInstance instance) {
-				if (instance instanceof UISWTInstance) {
-					final AESemaphore wait_sem = new AESemaphore( "SideBar:wait" );
-					
-					Utils.execSWTThread(new AERunnable() {
-						public void runSupport() {
-							try{
-								try {
-									loadCloseables();
-								} catch (Throwable t) {
-									Debug.out(t);
-								}
-	
-								setupPluginViews();
-							}finally{
-								
-								wait_sem.release();
-							}
-						}
-					});
-					
-						// we need to wait for the loadCloseables to complete as there is code in MainMDISetup that runs on the 'UIAttachedComplete'
-						// callback that needs the closables to be loaded (when setting 'start tab') otherwise the order gets broken
-					
-					if ( !wait_sem.reserve(10*1000)){
-						
-						Debug.out( "eh?");
-					}
-				}
-			}
-		});
+		super.skinObjectInitialShow(skinObject, params);
 
 		COConfigurationManager.addParameterListener(
 			"Show Side Bar",
@@ -349,6 +338,15 @@ public class SideBar
 		
 		return null;
 	}
+	
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.BaseMDI#setupPluginViews()
+	 */
+	@Override
+	protected void setupPluginViews() {
+		super.setupPluginViews();
+		createSideBarPluginViews();
+	}
 
 	public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) {
 		try {
@@ -384,6 +382,10 @@ public class SideBar
 
 		int fontHeight = (Constants.isOSX ? 11 : 12)
 				+ (tree.getItemHeight() > 18 ? tree.getItemHeight() - 18 : 0);
+		
+		if (Constants.isLinux && tree.getItemHeight() >= 38) {
+			fontHeight = 13;
+		}
 
 		fontData[0].setStyle(SWT.BOLD);
 		FontUtils.getFontHeightFromPX(tree.getDisplay(), fontData, null, fontHeight);
@@ -827,7 +829,7 @@ public class SideBar
 				}
 				SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry");
 
-				fillMenu(menuTree, entry);
+				fillMenu(menuTree, entry, "sidebar");
 
 				if (menuTree.getItemCount() == 0) {
 					Utils.execSWTThreadLater(0, new AERunnable() {
@@ -911,6 +913,114 @@ public class SideBar
 		}
 	}
 
+	private void createSideBarPluginViews() {
+		if (cPluginsArea == null) {
+			return;
+		}
+		UISWTInstanceImpl uiSWTinstance = (UISWTInstanceImpl) UIFunctionsManagerSWT.getUIFunctionsSWT().getUISWTInstance();
+
+		if (uiSWTinstance == null) {
+			return;
+		}
+
+		UISWTViewEventListenerHolder[] pluginViews = uiSWTinstance.getViewListeners(UISWTInstance.VIEW_SIDEBAR_AREA);
+		for (UISWTViewEventListenerHolder l : pluginViews) {
+			if (l != null) {
+				try {
+					UISWTViewImpl view = new UISWTViewImpl(l.getViewID(), UISWTInstance.VIEW_SIDEBAR_AREA, false);
+					view.setEventListener(l, true);
+					addSideBarView(view, cPluginsArea);
+					cPluginsArea.getParent().getParent().layout(true, true);
+				} catch (Exception e) {
+					e.printStackTrace();
+					// skip, plugin probably specifically asked to not be added
+				}
+			}
+		}
+		
+		uiSWTinstance.addSWTViewListener(new SWTViewListener() {
+
+			public void setViewAdded(final String parent, final String id,
+					final UISWTViewEventListener l) {
+				if (!parent.equals(UISWTInstance.VIEW_SIDEBAR_AREA)) {
+					return;
+				}
+				Utils.execSWTThread(new AERunnable() {
+
+					public void runSupport() {
+						try {
+							UISWTViewImpl view = new UISWTViewImpl(id, parent, false);
+							view.setEventListener(l, true);
+							addSideBarView(view, cPluginsArea);
+						} catch (Exception e) {
+							e.printStackTrace();
+							// skip, plugin probably specifically asked to not be added
+						}
+					}
+				});
+			}
+
+			public void setViewRemoved(final String parent, final String id,
+					final UISWTViewEventListener l) {
+				if (!parent.equals(UISWTInstance.VIEW_SIDEBAR_AREA)) {
+					return;
+				}
+				Utils.execSWTThread(new AERunnable() {
+
+					public void runSupport() {
+						try {
+							for (UISWTViewCore view : SideBar.this.pluginViews) {
+								if (l.equals(view.getEventListener())) {
+									view.closeView();
+								}
+							}
+						} catch (Exception e) {
+							e.printStackTrace();
+							// skip, plugin probably specifically asked to not be added
+						}
+					}
+				});
+			}
+		});
+		
+		cPluginsArea.getParent().getParent().layout(true, true);
+	}
+	
+	private void addSideBarView(UISWTViewImpl view, Composite cPluginsArea) {
+		Composite parent = new Composite(cPluginsArea, SWT.NONE);
+		GridData gridData = new GridData();
+		gridData.grabExcessHorizontalSpace = true;
+		gridData.horizontalAlignment = SWT.FILL;
+		parent.setLayoutData(gridData);
+		parent.setLayout(new FormLayout());
+		//parent.setBackground(ColorCache.getRandomColor());
+		//cPluginsArea.setBackground(ColorCache.getRandomColor());
+
+		view.initialize(parent);
+		parent.setVisible(true);
+
+		Control[] children = parent.getChildren();
+		for (int i = 0; i < children.length; i++) {
+			Control control = children[i];
+			Object ld = control.getLayoutData();
+			boolean useGridLayout = ld != null && (ld instanceof GridData);
+			if (useGridLayout) {
+				GridLayout gridLayout = new GridLayout();
+				gridLayout.horizontalSpacing = 0;
+				gridLayout.marginHeight = 0;
+				gridLayout.marginWidth = 0;
+				gridLayout.verticalSpacing = 0;
+				parent.setLayout(gridLayout);
+				break;
+			} else if (ld == null) {
+				control.setLayoutData(Utils.getFilledFormData());
+			}
+		}
+		
+		pluginViews.add(view);
+	}
+
+
 	/**
 	 * @param event
 	 */
@@ -971,132 +1081,6 @@ public class SideBar
 	}
 
 	/**
-	 * @param menuTree
-	 *
-	 * @since 3.1.0.1
-	 */
-	protected void fillMenu(Menu menuTree, final MdiEntry entry) {
-		org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items;
-
-		menu_items = MenuItemManager.getInstance().getAllAsArray("sidebar");
-
-		MenuBuildUtils.addPluginMenuItems((Composite) soMain.getControl(),
-				menu_items, menuTree, false, true,
-				new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Object[] {
-					entry
-				}));
-
-		if (entry != null) {
-
-			menu_items = MenuItemManager.getInstance().getAllAsArray(
-					"sidebar." + entry.getId());
-
-			if (menu_items.length == 0) {
-
-				UIPluginView view = entry.getView();
-
-				if (view instanceof UISWTView) {
-
-					PluginInterface pi = ((UISWTView) view).getPluginInterface();
-
-					if (pi != null) {
-
-						final List<String> relevant_sections = new ArrayList<String>();
-
-						List<ConfigSectionHolder> sections = ConfigSectionRepository.getInstance().getHolderList();
-
-						for (ConfigSectionHolder cs : sections) {
-
-							if (pi == cs.getPluginInterface()) {
-
-								relevant_sections.add(cs.configSectionGetName());
-							}
-						}
-
-						if (relevant_sections.size() > 0) {
-
-							MenuItem mi = pi.getUIManager().getMenuManager().addMenuItem(
-									"sidebar." + entry.getId(),
-									"MainWindow.menu.view.configuration");
-
-							mi.addListener(new MenuItemListener() {
-								public void selected(MenuItem menu, Object target) {
-									UIFunctions uif = UIFunctionsManager.getUIFunctions();
-
-									if (uif != null) {
-
-										for (String s : relevant_sections) {
-
-											uif.openView(UIFunctions.VIEW_CONFIG, s);
-										}
-									}
-								}
-							});
-
-							menu_items = MenuItemManager.getInstance().getAllAsArray(
-									"sidebar." + entry.getId());
-						}
-					}
-				}
-			}
-
-			MenuBuildUtils.addPluginMenuItems((Composite) soMain.getControl(),
-					menu_items, menuTree, false, true,
-					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Object[] {
-						entry
-					}));
-
-			MdiSWTMenuHackListener[] menuHackListeners = getMenuHackListeners();
-			for (MdiSWTMenuHackListener l : menuHackListeners) {
-				try {
-					l.menuWillBeShown(entry, menuTree);
-				} catch (Exception e) {
-					Debug.out(e);
-				}
-			}
-			if (currentEntry instanceof SideBarEntrySWT) {
-				menuHackListeners = ((SideBarEntrySWT) entry).getMenuHackListeners();
-				for (MdiSWTMenuHackListener l : menuHackListeners) {
-					try {
-						l.menuWillBeShown(entry, menuTree);
-					} catch (Exception e) {
-						Debug.out(e);
-					}
-				}
-			}
-		}
-	}
-
-	public void addListener(MdiSWTMenuHackListener l) {
-		synchronized (this) {
-			if (listMenuHackListners == null) {
-				listMenuHackListners = new ArrayList<MdiSWTMenuHackListener>(1);
-			}
-			if (!listMenuHackListners.contains(l)) {
-				listMenuHackListners.add(l);
-			}
-		}
-	}
-
-	public void removeListener(MdiSWTMenuHackListener l) {
-		synchronized (this) {
-			if (listMenuHackListners == null) {
-				listMenuHackListners = new ArrayList<MdiSWTMenuHackListener>(1);
-			}
-			listMenuHackListners.remove(l);
-		}
-	}
-
-	public MdiSWTMenuHackListener[] getMenuHackListeners() {
-		synchronized (this) {
-			if (listMenuHackListners == null) {
-				return new MdiSWTMenuHackListener[0];
-			}
-			return listMenuHackListners.toArray(new MdiSWTMenuHackListener[0]);
-		}
-	}
-
-	/**
 	 * 
 	 *
 	 * @since 3.1.1.1
@@ -1138,10 +1122,10 @@ public class SideBar
 		}
 	}
 
-	protected int indexOf(final MdiEntry entryLibrary) {
+	protected int indexOf(final MdiEntry entry) {
 		Object o = Utils.execSWTThreadWithObject("indexOf", new AERunnableObject() {
 			public Object runSupport() {
-				TreeItem treeItem = ((SideBarEntrySWT) entryLibrary).getTreeItem();
+				TreeItem treeItem = ((SideBarEntrySWT) entry).getTreeItem();
 				if (treeItem == null) {
 					return -1;
 				}
@@ -1164,7 +1148,7 @@ public class SideBar
 			return oldEntry;
 		}
 
-		SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id);
+		SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id, null);
 		entry.setSelectable(false);
 		entry.setPreferredAfterID(preferredAfterID);
 		entry.setTitleID(titleID);
@@ -1174,52 +1158,16 @@ public class SideBar
 		return entry;
 	}
 
-	public MdiEntry createEntryFromView(String parentID, UISWTViewCore iview, String id,
-			Object datasource, boolean closeable, boolean show, boolean expand) {
-		if (id == null) {
-			id = iview.getClass().getName();
-			int i = id.lastIndexOf('.');
-			if (i > 0) {
-				id = id.substring(i + 1);
-			}
-		}
-
-		MdiEntry oldEntry = getEntry(id);
-		if (oldEntry != null) {
-			if (show) {
-				showEntry(oldEntry);
-			}
-			return oldEntry;
-		}
-
-		SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id);
-
-		entry.setCoreView(iview);
-		entry.setDatasource(datasource);
-		entry.setParentID(parentID);
-
-		setupNewEntry(entry, id, expand, closeable);
-
-		if (iview instanceof IViewAlwaysInitialize) {
-			entry.build();
-		}
-
-		if (show) {
-			showEntry(entry);
-		}
-
-		return entry;
-	}
-
 	private void setupNewEntry(final SideBarEntrySWT entry, final String id,
 			final boolean expandParent, final boolean closeable) {
-		//System.out.println("createItem " + id + ";" + Debug.getCompressedStackTrace());
+		//System.out.println("createItem " + id + ";" + entry.getParentID() + ";" + Debug.getCompressedStackTrace());
 		synchronized (mapIdToEntry) {
 			mapIdToEntry.put(id, entry);
 		}
 
 		entry.setCloseable(closeable);
 		entry.setParentSkinObject(soSideBarContents);
+		entry.setDestroyOnDeactivate(false);
 
 		if (SIDEBAR_HEADER_PLUGINS.equals(entry.getParentID())
 				&& entry.getImageLeftID() == null) {
@@ -1390,7 +1338,7 @@ public class SideBar
 	/**
 	 *  @see com.aelitis.azureus.ui.swt.mdi.BaseMDI#createEntryFromEventListener(java.lang.String, org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener, java.lang.String, boolean, java.lang.Object)
 	 */
-	public MdiEntry createEntryFromEventListener(String parentID,
+	public MdiEntry createEntryFromEventListener(String parentEntryID, String parentViewID,
 			UISWTViewEventListener l, String id, boolean closeable, Object datasource, String preferredAfterID) {
 
 		MdiEntry oldEntry = getEntry(id);
@@ -1398,7 +1346,7 @@ public class SideBar
 			return oldEntry;
 		}
 
-		SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id);
+		SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id, parentViewID);
 		try {
 			// hack: setEventListner will create the UISWTView.
 			// We need to have the entry available for the view to use
@@ -1407,12 +1355,12 @@ public class SideBar
 				mapIdToEntry.put(id, entry);
 			}
 
-			entry.setParentID(parentID);
+			entry.setEventListener(l, true);
+			entry.setParentID(parentEntryID);
 			entry.setDatasource(datasource);
 			entry.setPreferredAfterID(preferredAfterID);
 			setupNewEntry(entry, id, false, closeable);
 
-			entry.setEventListener(l);
 
 			if (l instanceof IViewAlwaysInitialize) {
 				entry.build();
@@ -1420,6 +1368,7 @@ public class SideBar
 		} catch (Exception e) {
 			Debug.out(e);
 			entry.close(true);
+			entry = null;
 		}
 
 		return entry;
@@ -1435,7 +1384,7 @@ public class SideBar
 			return oldEntry;
 		}
 
-		SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id);
+		SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id, null);
 
 		entry.setTitle(title);
 		entry.setSkinRef(configID, params);
@@ -1450,8 +1399,27 @@ public class SideBar
 
 	// @see com.aelitis.azureus.ui.swt.utils.UIUpdatable#updateUI()
 	public void updateUI() {
-		if (currentEntry == null || currentEntry.getView() == null
-				|| tree.getSelectionCount() == 0) {
+		Object[] views = pluginViews.toArray();
+		for (int i = 0; i < views.length; i++) {
+			try {
+				UISWTViewCore view = (UISWTViewCore) views[i];
+				Composite composite = view.getComposite();
+				if ( composite == null ){
+					continue;
+				}
+				if (composite.isDisposed()) {
+					pluginViews.remove(view);
+					continue;
+				}
+				if (composite.isVisible()) {
+					view.triggerEvent(UISWTViewEvent.TYPE_REFRESH, null);
+				}
+			} catch (Exception e) {
+				Debug.out(e);
+			}
+		}
+
+		if (currentEntry == null || tree.getSelectionCount() == 0) {
 			return;
 		}
 		currentEntry.updateUI();
@@ -1588,9 +1556,7 @@ public class SideBar
 				continue;
 			}
 
-			UISWTViewCore view = entry.getCoreView();
-
-			if (!(view instanceof AEDiagnosticsEvidenceGenerator)) {
+			if (!(entry instanceof AEDiagnosticsEvidenceGenerator)) {
 				writer.println("Sidebar View (No Generator): " + entry.getId());
 				try {
 					writer.indent();
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarEntrySWT.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarEntrySWT.java
index 29f44ac..a2eb558 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarEntrySWT.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarEntrySWT.java
@@ -1,10 +1,12 @@
 /**
  * Created on Aug 13, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -27,7 +29,6 @@ import org.eclipse.swt.graphics.*;
 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.util.AERunnable;
 import org.gudy.azureus2.core3.util.Constants;
@@ -39,16 +40,21 @@ import org.gudy.azureus2.ui.swt.debug.UIDebugGenerator;
 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
 import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
 import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
+import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener;
 import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCore;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewCoreEventListenerEx;
+import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTViewImpl;
 import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
 
+import com.aelitis.azureus.ui.UIFunctionsManager;
+import com.aelitis.azureus.ui.common.updater.UIUpdatable;
+import com.aelitis.azureus.ui.common.updater.UIUpdater;
 import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
 import com.aelitis.azureus.ui.mdi.MdiEntry;
 import com.aelitis.azureus.ui.mdi.MdiEntryVitalityImage;
 import com.aelitis.azureus.ui.skin.SkinConstants;
 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
 import com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry;
-import com.aelitis.azureus.ui.swt.mdi.MdiSWTMenuHackListener;
 import com.aelitis.azureus.ui.swt.skin.*;
 import com.aelitis.azureus.ui.swt.utils.ColorCache;
 import com.aelitis.azureus.ui.swt.views.skin.InfoBarUtil;
@@ -121,16 +127,15 @@ public class SideBarEntrySWT
 	
 	private boolean selectable = true;
 
-	private List<MdiSWTMenuHackListener> listMenuHackListners;
-	
 	private boolean neverPainted = true;
 
 	private long 	attention_start = -1;
 	private boolean	attention_flash_on;
 
 	
-	public SideBarEntrySWT(SideBar sidebar, SWTSkin _skin, String id) {
-		super(sidebar, id);
+	public SideBarEntrySWT(SideBar sidebar, SWTSkin _skin, String id,
+			String parentViewID) {
+		super(sidebar, id, parentViewID);
 		this.skin = _skin;
 
 		if (id == null) {
@@ -280,6 +285,8 @@ public class SideBarEntrySWT
 	 * @see com.aelitis.azureus.ui.mdi.MdiEntry#redraw()
 	 */
 	boolean isRedrawQueued = false;
+
+	private InfoBarUtil toolBarInfoBar;
 	public void redraw() {
 		if (neverPainted) {
 			return;
@@ -390,7 +397,7 @@ public class SideBarEntrySWT
 		// dispose will trigger dispose listener, which removed it from BaseMDI
 		Utils.execSWTThread(new AERunnable() {
 			public void runSupport() {
-				if (swtItem != null) {
+				if (swtItem != null && !swtItem.isDisposed()) {
 					try {
   					swtItem.setFont(null);
   					swtItem.dispose();
@@ -403,18 +410,172 @@ public class SideBarEntrySWT
 					} finally {
   					swtItem = null;
 					}
-				} else if (view != null) {
-					try {
-	      		view.triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
-					} finally {
-						view = null;
-					}
 				}
 			}
 		});
 		return true;
 	}
 
+	public boolean
+	canBuildStandAlone()
+	{
+		String skinRef = getSkinRef();
+
+		if (skinRef != null){
+			
+			return( true );
+			
+		}else {
+			
+			UISWTViewEventListener event_listener = getEventListener();
+			
+			if ( event_listener instanceof UISWTViewCoreEventListenerEx && ((UISWTViewCoreEventListenerEx)event_listener).isCloneable()){
+
+				return( true );
+			}
+		}
+		
+		return( false );
+	}
+	
+	public SWTSkinObjectContainer 
+	buildStandAlone(
+		SWTSkinObjectContainer		soParent )
+	{
+		Control control = null;
+
+		//SWTSkin skin = soParent.getSkin();
+		
+		Composite parent = soParent.getComposite();
+
+		String skinRef = getSkinRef();
+		
+		if (skinRef != null){
+			
+			Shell shell = parent.getShell();
+			Cursor cursor = shell.getCursor();
+			try {
+				shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
+
+				// wrap skinRef with a container that we control visibility of
+				// (invisible by default)
+				SWTSkinObjectContainer soContents = (SWTSkinObjectContainer) skin.createSkinObject(
+						"MdiContents." + uniqueNumber++, SO_ID_ENTRY_WRAPPER,
+						soParent, null);
+				
+				SWTSkinObject skinObject = skin.createSkinObject(id, skinRef,
+						soContents, getDatasourceCore());
+
+				control = skinObject.getControl();
+				control.setLayoutData(Utils.getFilledFormData());
+				control.getParent().layout(true, true);
+			
+				soContents.setVisible( true );
+							
+				return( soContents );
+				
+			} finally {
+				shell.setCursor(cursor);
+			}
+		}else {
+			// XXX: This needs to be merged into BaseMDIEntry.initialize
+
+			UISWTViewEventListener event_listener = getEventListener();
+			
+			if ( event_listener instanceof UISWTViewCoreEventListenerEx && ((UISWTViewCoreEventListenerEx)event_listener).isCloneable()){
+				
+				final UISWTViewImpl view = new UISWTViewImpl( getParentID(), id, true );
+				
+				try{
+					view.setEventListener(((UISWTViewCoreEventListenerEx)event_listener).getClone(),false);
+					
+				}catch( Throwable e ){
+					// shouldn't happen as we aren't asking for 'create' to occur which means it can't fail
+					Debug.out( e );
+				}
+				
+				view.setDatasource( datasource );
+
+				try {
+					SWTSkinObjectContainer soContents = (SWTSkinObjectContainer) skin.createSkinObject(
+							"MdiIView." + uniqueNumber++, SO_ID_ENTRY_WRAPPER,
+							soParent );
+
+					parent.setBackgroundMode(SWT.INHERIT_NONE);
+
+					final Composite viewComposite = soContents.getComposite();
+					boolean doGridLayout = true;
+					if (getControlType() == UISWTViewCore.CONTROLTYPE_SKINOBJECT) {
+						doGridLayout = false;
+					}
+					//					viewComposite.setBackground(parent.getDisplay().getSystemColor(
+					//							SWT.COLOR_WIDGET_BACKGROUND));
+					//					viewComposite.setForeground(parent.getDisplay().getSystemColor(
+					//							SWT.COLOR_WIDGET_FOREGROUND));
+					if (doGridLayout) {
+						GridLayout gridLayout = new GridLayout();
+						gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginHeight = gridLayout.marginWidth = 0;
+						viewComposite.setLayout(gridLayout);
+						viewComposite.setLayoutData(Utils.getFilledFormData());
+					}
+
+					view.setPluginSkinObject(soContents);
+					view.initialize(viewComposite);
+					
+					//swtItem.setText(view.getFullTitle());
+
+					Composite iviewComposite = view.getComposite();
+					control = iviewComposite;
+					// force layout data of IView's composite to GridData, since we set
+					// the parent to GridLayout (most plugins use grid, so we stick with
+					// that instead of form)
+					if (doGridLayout) {
+						Object existingLayoutData = iviewComposite.getLayoutData();
+						Object existingParentLayoutData = iviewComposite.getParent().getLayoutData();
+						if (existingLayoutData == null
+								|| !(existingLayoutData instanceof GridData)
+								&& (existingParentLayoutData instanceof GridLayout)) {
+							GridData gridData = new GridData(GridData.FILL_BOTH);
+							iviewComposite.setLayoutData(gridData);
+						}
+					}
+
+					parent.layout(true, true);
+					
+					final UIUpdater updater = UIFunctionsManager.getUIFunctions().getUIUpdater();
+
+					updater.addUpdater(
+						new UIUpdatable() {
+							
+							public void updateUI() {
+								if (viewComposite.isDisposed()){
+									updater.removeUpdater( this );
+								}else{
+									triggerEvent(UISWTViewEvent.TYPE_REFRESH, null);
+								}
+							}
+							
+							public String getUpdateUIName() {
+								return( "popout" );
+							}
+						});
+					
+					soContents.setVisible( true );
+					
+					view.triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
+					
+					return( soContents );
+					
+				} catch (Throwable e) {
+					
+					Debug.out(e);
+				}
+			}
+		}
+		
+		return( null );
+	}
+	
 	public void build() {
 		Utils.execSWTThread(new AERunnable() {
 			public void runSupport() {
@@ -456,11 +617,14 @@ public class SideBarEntrySWT
 					control = skinObject.getControl();
 					control.setLayoutData(Utils.getFilledFormData());
 					control.getParent().layout(true, true);
-					setSkinObject(skinObject, soContents);
+					setPluginSkinObject(skinObject);
+					initialize((Composite) control);
+					setSkinObjectMaster(soContents);
 				} finally {
 					shell.setCursor(cursor);
 				}
-			} else if (view != null) {
+			} else {
+				// XXX: This needs to be merged into BaseMDIEntry.initialize
 				try {
 					SWTSkinObjectContainer soContents = (SWTSkinObjectContainer) skin.createSkinObject(
 							"MdiIView." + uniqueNumber++, SO_ID_ENTRY_WRAPPER,
@@ -470,7 +634,7 @@ public class SideBarEntrySWT
 
 					Composite viewComposite = soContents.getComposite();
 					boolean doGridLayout = true;
-					if (view.getControlType() == UISWTViewCore.CONTROLTYPE_SKINOBJECT) {
+					if (getControlType() == UISWTViewCore.CONTROLTYPE_SKINOBJECT) {
 						doGridLayout = false;
 					}
 					//					viewComposite.setBackground(parent.getDisplay().getSystemColor(
@@ -484,11 +648,14 @@ public class SideBarEntrySWT
 						viewComposite.setLayoutData(Utils.getFilledFormData());
 					}
 
-					view.setSkinObject(soContents, soContents.getComposite());
-					view.initialize(viewComposite);
-					swtItem.setText(view.getFullTitle());
+					setPluginSkinObject(soContents);
+					initialize(viewComposite);
+					String fullTitle = getFullTitle();
+					if (fullTitle != null) {
+						swtItem.setText(getFullTitle());
+					}
 
-					Composite iviewComposite = view.getComposite();
+					Composite iviewComposite = getComposite();
 					control = iviewComposite;
 					// force layout data of IView's composite to GridData, since we set
 					// the parent to GridLayout (most plugins use grid, so we stick with
@@ -506,28 +673,12 @@ public class SideBarEntrySWT
 
 					parent.layout(true, true);
 
-					setSkinObject(soContents, soContents);
+					setSkinObjectMaster(soContents);
 				} catch (Exception e) {
 					Debug.out("Error creating sidebar content area for " + id, e);
-					setCoreView(null);
 					close(true);
 				}
 
-			} else if (viewClass != null) {
-				try {
-					UISWTViewCore view = (UISWTViewCore) viewClass.newInstance();
-
-					if (view != null) {
-						setCoreView(view);
-						// now that we have an IView, go through show one more time
-						return swt_build();
-					}
-					close(true);
-					return false;
-				} catch (Throwable e) {
-					Debug.out(e);
-					close(true);
-				}
 			}
 
 			if (control != null && !control.isDisposed()) {
@@ -1036,6 +1187,8 @@ public class SideBarEntrySWT
 		imageLoader.releaseImage("image.sidebar.closeitem");
 		imageLoader.releaseImage("image.sidebar.closeitem-selected");
 
+		setDisposed(true);
+
 		final TreeItem treeItem = (TreeItem) e.widget;
 		if (treeItem != swtItem) {
 			Debug.out("Warning: TreeItem changed for sidebar " + id);
@@ -1045,7 +1198,7 @@ public class SideBarEntrySWT
 		if (swtItem == null) {
 			return;
 		}
-
+		
 		if (swtItem != null && !Constants.isOSX) {
 			// In theory, the disposal of swtItem will trigger the disposal of the
 			// children.  Let's force it just in case
@@ -1075,15 +1228,23 @@ public class SideBarEntrySWT
 
 		mdi.removeItem(SideBarEntrySWT.this);
 
-		triggerCloseListeners(!SWTThread.getInstance().isTerminated());
-
-		UISWTViewCore iview = getCoreView();
-		if (iview != null) {
-			setCoreView(null);
+		boolean user = !SWTThread.getInstance().isTerminated();
+		if (user) {
+			// It's not a user close if the parent is making the children (this entry)
+			// close.  parent will be marked disposed, so use that as a check.
+  		String parentID = getParentID();
+  		if (parentID != null) {
+  			MdiEntry entry = mdi.getEntry(parentID);
+  			if (entry != null && entry.isDisposed()) {
+  				user = false;
+  			}
+  		}
 		}
+		triggerCloseListeners(user);
+
 		SWTSkinObject so = getSkinObject();
 		if (so != null) {
-			setSkinObject(null, null);
+			setSkinObjectMaster(null);
 			so.getSkin().removeSkinObject(so);
 		}
 
@@ -1153,35 +1314,6 @@ public class SideBarEntrySWT
 		return true; // todo: bounds check
 	}
 
-	public void addListener(MdiSWTMenuHackListener l) {
-		synchronized (this) {
-			if (listMenuHackListners == null) {
-				listMenuHackListners = new ArrayList<MdiSWTMenuHackListener>(1);
-			}
-			if (!listMenuHackListners.contains(l)) {
-				listMenuHackListners.add(l);
-			}
-		}
-	}
-
-	public void removeListener(MdiSWTMenuHackListener l) {
-		synchronized (this) {
-			if (listMenuHackListners == null) {
-				listMenuHackListners = new ArrayList<MdiSWTMenuHackListener>(1);
-			}
-			listMenuHackListners.remove(l);
-		}
-	}
-	
-	public MdiSWTMenuHackListener[] getMenuHackListeners() {
-		synchronized (this) {
-			if (listMenuHackListners == null) {
-				return new MdiSWTMenuHackListener[0];
-			}
-			return listMenuHackListners.toArray(new MdiSWTMenuHackListener[0]);
-		}
-	}
-
 	// @see org.gudy.azureus2.ui.swt.debug.ObfusticateImage#obfusticatedImage(org.eclipse.swt.graphics.Image)
 	public Image obfusticatedImage(Image image) {
 		Rectangle bounds = swt_getBounds();
@@ -1195,9 +1327,7 @@ public class SideBarEntrySWT
 			Map<String, Object> map = new HashMap<String, Object>();
 			map.put("image", image);
 			map.put("obfuscateSideBar", false);
-			if (view != null) {
-				view.triggerEvent(UISWTViewEvent.TYPE_OBFUSCATE, map);
-			}
+			triggerEvent(UISWTViewEvent.TYPE_OBFUSCATE, map);
 	
 			if (MapUtils.getMapBoolean(map, "obfuscateSideBar", false)) {
 				int ofs = IMAGELEFT_GAP + IMAGELEFT_SIZE;
@@ -1217,6 +1347,14 @@ public class SideBarEntrySWT
 	
 	// @see com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry#setToolbarVisibility(boolean)
 	protected void setToolbarVisibility(boolean visible) {
+		if (toolBarInfoBar != null) {
+			if (visible) {
+				toolBarInfoBar.show();
+			} else {
+				toolBarInfoBar.hide(false);
+			}
+			return;
+		}
 		SWTSkinObject soMaster = getSkinObjectMaster();
 		if (soMaster == null) {
 			return;
@@ -1227,7 +1365,7 @@ public class SideBarEntrySWT
 		}
 		SWTSkinObject soToolbar = skin.getSkinObject(SkinConstants.VIEWID_VIEW_TOOLBAR, soMaster);
 		if (soToolbar == null && visible) {
-			new InfoBarUtil(so, SO_ID_TOOLBAR, true, "", "") {
+			toolBarInfoBar = new InfoBarUtil(so, SO_ID_TOOLBAR, true, "", "") {
 				public boolean allowShow() {
 					return true;
 				}
@@ -1236,4 +1374,24 @@ public class SideBarEntrySWT
 			soToolbar.setVisible(visible);
 		}
 	}
+	
+	/* (non-Javadoc)
+	 * @see com.aelitis.azureus.ui.swt.mdi.BaseMdiEntry#setTitle(java.lang.String)
+	 */
+	@Override
+	public void setTitle(String title) {
+		super.setTitle(title);
+
+		Utils.execSWTThread(new AERunnable() {
+			
+			@Override
+			public void runSupport() {
+				if (swtItem == null || swtItem.isDisposed()) {
+					return;
+				}
+				swtItem.setText(getTitle());
+				redraw();
+			}
+		});
+	}
 }
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarToolTips.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarToolTips.java
index 318ea3e..1a596be 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarToolTips.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarToolTips.java
@@ -1,10 +1,12 @@
 /**
  * Created on Aug 13, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -24,13 +26,9 @@ import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.widgets.*;
 
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.ui.UIFunctionsManager;
 import com.aelitis.azureus.ui.common.updater.UIUpdatable;
 import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo;
 import com.aelitis.azureus.ui.mdi.MdiEntry;
-import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
 import com.aelitis.azureus.ui.mdi.MdiEntryVitalityImage;
 import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT;
 
@@ -51,8 +49,6 @@ public class SideBarToolTips
 
 	private final Tree tree;
 
-	private final SideBar sidebar;
-
 	private MdiEntry mdiEntry;
 
 	private Point lastRelMouseHoverPos;
@@ -61,7 +57,6 @@ public class SideBarToolTips
 	 * Initialize
 	 */
 	public SideBarToolTips(SideBar sidebar, Tree tree) {
-		this.sidebar = sidebar;
 		this.tree = tree;
 		mainShell = tree.getShell();
 
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarVitalityImageSWT.java b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarVitalityImageSWT.java
index cc6c1de..bf7d1ec 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarVitalityImageSWT.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/views/skin/sidebar/SideBarVitalityImageSWT.java
@@ -1,10 +1,12 @@
 /**
  * Created on Sep 15, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/ui/swt/widgets/AnimatedImage.java b/azureus3/src/com/aelitis/azureus/ui/swt/widgets/AnimatedImage.java
index 384afc1..ccc5e8e 100644
--- a/azureus3/src/com/aelitis/azureus/ui/swt/widgets/AnimatedImage.java
+++ b/azureus3/src/com/aelitis/azureus/ui/swt/widgets/AnimatedImage.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.ui.swt.widgets;
 
 import org.eclipse.swt.SWT;
diff --git a/azureus3/src/com/aelitis/azureus/util/ConstantsVuze.java b/azureus3/src/com/aelitis/azureus/util/ConstantsVuze.java
index 36621ff..05805a8 100644
--- a/azureus3/src/com/aelitis/azureus/util/ConstantsVuze.java
+++ b/azureus3/src/com/aelitis/azureus/util/ConstantsVuze.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 10, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/util/ContentNetworkUtils.java b/azureus3/src/com/aelitis/azureus/util/ContentNetworkUtils.java
index c90133a..463fbcf 100644
--- a/azureus3/src/com/aelitis/azureus/util/ContentNetworkUtils.java
+++ b/azureus3/src/com/aelitis/azureus/util/ContentNetworkUtils.java
@@ -1,10 +1,12 @@
 /**
  * Created on Dec 10, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/util/DLReferals.java b/azureus3/src/com/aelitis/azureus/util/DLReferals.java
index bf0a446..33ecfac 100644
--- a/azureus3/src/com/aelitis/azureus/util/DLReferals.java
+++ b/azureus3/src/com/aelitis/azureus/util/DLReferals.java
@@ -1,10 +1,12 @@
 /**
  * Created on Feb 10, 2009
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/util/DataSourceUtils.java b/azureus3/src/com/aelitis/azureus/util/DataSourceUtils.java
index 161cfb0..bf03894 100644
--- a/azureus3/src/com/aelitis/azureus/util/DataSourceUtils.java
+++ b/azureus3/src/com/aelitis/azureus/util/DataSourceUtils.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jun 1, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -21,9 +23,7 @@ package com.aelitis.azureus.util;
 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.Base32;
-import org.gudy.azureus2.core3.util.Debug;
-import org.gudy.azureus2.core3.util.HashWrapper;
+import org.gudy.azureus2.core3.util.*;
 import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.plugins.download.Download;
 import org.gudy.azureus2.plugins.download.DownloadException;
@@ -127,6 +127,18 @@ public class DataSourceUtils
 				}
 			} else if (ds instanceof DeviceOfflineDownload ) {
 				return( PluginCoreUtils.unwrap(((DeviceOfflineDownload)ds).getDownload()));
+			} else if (ds instanceof Download) {
+				return PluginCoreUtils.unwrap((Download) ds);
+			} else if (ds instanceof byte[]) {
+				byte[] hash = (byte[]) ds;
+  			GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
+  			DownloadManager dm = gm.getDownloadManager(new HashWrapper(hash));
+  			if (dm != null) {
+  				return dm;
+  			}				
+			} else if (ds instanceof Object[]) {
+					Object[] o = (Object[]) ds;
+					return getDM(o[0]);
 			}	else if ((ds instanceof String)  && AzureusCoreFactory.isCoreRunning()) {
 				String hash = (String) ds;
 				try {
@@ -139,6 +151,11 @@ public class DataSourceUtils
 					// ignore
 				}
 			}
+			
+			org.gudy.azureus2.core3.disk.DiskManagerFileInfo fileInfo = getFileInfo(ds);
+			if (fileInfo != null) {
+				return fileInfo.getDownloadManager();
+			}
 
 
 		} catch (Exception e) {
@@ -228,6 +245,11 @@ public class DataSourceUtils
 				// ignore
 			}
 		}
+		
+		DownloadManager dm = getDM(ds);
+		if (dm != null) {
+			return dm.getTorrent();
+		}
 
 		return null;
 	}
@@ -251,20 +273,22 @@ public class DataSourceUtils
 
 	public static String getHash(Object ds) {
 		try {
-			if (ds instanceof DownloadManager) {
-				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) {
+			if (ds instanceof VuzeActivitiesEntry) {
 				VuzeActivitiesEntry entry = (VuzeActivitiesEntry) ds;
 				return entry.getAssetHash();
 			} else if (ds instanceof ISelectedContent) {
 				return ((ISelectedContent)ds).getHash();
+			} else if (ds instanceof byte[]) {
+				return Base32.encode((byte[]) ds);
 			} else if (ds instanceof String) {
+				// XXX Check validility
 				return (String) ds;
 			}
+			
+			TOTorrent torrent = getTorrent(ds);
+			if (torrent != null) {
+				return torrent.getHashWrapper().toBase32String();
+			}
 		} catch (Exception e) {
 			Debug.printStackTrace(e);
 		}
diff --git a/azureus3/src/com/aelitis/azureus/util/DownloadUtils.java b/azureus3/src/com/aelitis/azureus/util/DownloadUtils.java
index a6ca2a2..e60b1e7 100644
--- a/azureus3/src/com/aelitis/azureus/util/DownloadUtils.java
+++ b/azureus3/src/com/aelitis/azureus/util/DownloadUtils.java
@@ -1,7 +1,7 @@
 /*
  * Created on May 14, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/util/ExternalStimulusHandler.java b/azureus3/src/com/aelitis/azureus/util/ExternalStimulusHandler.java
index c666c23..a1bbf68 100644
--- a/azureus3/src/com/aelitis/azureus/util/ExternalStimulusHandler.java
+++ b/azureus3/src/com/aelitis/azureus/util/ExternalStimulusHandler.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 8, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/util/ExternalStimulusListener.java b/azureus3/src/com/aelitis/azureus/util/ExternalStimulusListener.java
index 0da4fde..2727c01 100644
--- a/azureus3/src/com/aelitis/azureus/util/ExternalStimulusListener.java
+++ b/azureus3/src/com/aelitis/azureus/util/ExternalStimulusListener.java
@@ -1,7 +1,7 @@
 /*
  * Created on Feb 8, 2007
  * Created by Paul Gardner
- * Copyright (C) 2007 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/util/FeatureUtils.java b/azureus3/src/com/aelitis/azureus/util/FeatureUtils.java
index 64ee5e1..b71b08d 100644
--- a/azureus3/src/com/aelitis/azureus/util/FeatureUtils.java
+++ b/azureus3/src/com/aelitis/azureus/util/FeatureUtils.java
@@ -3,19 +3,18 @@
  * Created by Paul Gardner
  * 
  * Copyright 2013 Azureus Software, 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 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
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 
diff --git a/azureus3/src/com/aelitis/azureus/util/ImportExportUtils.java b/azureus3/src/com/aelitis/azureus/util/ImportExportUtils.java
index 9344928..638885c 100644
--- a/azureus3/src/com/aelitis/azureus/util/ImportExportUtils.java
+++ b/azureus3/src/com/aelitis/azureus/util/ImportExportUtils.java
@@ -1,3 +1,21 @@
+/*
+ * Copyright (C) Azureus Software, 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 ( 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.util;
 
 import java.io.IOException;
diff --git a/azureus3/src/com/aelitis/azureus/util/InitialisationFunctions.java b/azureus3/src/com/aelitis/azureus/util/InitialisationFunctions.java
index 15f76f2..a5f160f 100644
--- a/azureus3/src/com/aelitis/azureus/util/InitialisationFunctions.java
+++ b/azureus3/src/com/aelitis/azureus/util/InitialisationFunctions.java
@@ -1,7 +1,7 @@
 /*
  * Created on 14-Sep-2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
@@ -37,13 +34,18 @@ import com.aelitis.azureus.core.devices.DeviceManager;
 import com.aelitis.azureus.core.devices.DeviceManagerFactory;
 import com.aelitis.azureus.core.devices.DeviceMediaRenderer;
 import com.aelitis.azureus.core.download.DownloadManagerEnhancer;
+import com.aelitis.azureus.core.metasearch.Engine;
 import com.aelitis.azureus.core.metasearch.MetaSearchManagerFactory;
 import com.aelitis.azureus.core.metasearch.MetaSearchManagerListener;
 import com.aelitis.azureus.core.peer.cache.CacheDiscovery;
 import com.aelitis.azureus.core.subs.Subscription;
+import com.aelitis.azureus.core.subs.SubscriptionManager;
 import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
 import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
 import com.aelitis.azureus.core.util.AZ3Functions;
+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;
 
@@ -132,6 +134,56 @@ public class InitialisationFunctions
 				}
 				
 				public void 
+				subscribeToSubscription(
+					String uri )
+					
+					throws Exception 
+				{
+					SubscriptionManager manager = SubscriptionManagerFactory.getSingleton();
+					
+					Subscription subs =	manager.createFromURI( uri );
+											
+					if ( !subs.isSubscribed()){
+							
+						subs.setSubscribed( true );
+						
+						if ( subs.isSearchTemplate()){
+							
+							try{
+								VuzeFile vf = subs.getSearchTemplateVuzeFile();
+								
+								if ( vf != null ){
+								
+									subs.setSubscribed( true );
+									
+									VuzeFileHandler.getSingleton().handleFiles( new VuzeFile[]{ vf }, VuzeFileComponent.COMP_TYPE_NONE );
+									
+									
+									for ( VuzeFileComponent comp: vf.getComponents()){
+										
+										Engine engine = (Engine)comp.getData( Engine.VUZE_FILE_COMPONENT_ENGINE_KEY );
+										
+										if ( engine != null && engine.getSelectionState() == Engine.SEL_STATE_DESELECTED ){
+											
+											engine.setSelectionState( Engine.SEL_STATE_MANUAL_SELECTED );
+										}
+									}
+								}
+							}catch( Throwable e ){
+								
+								Debug.out( e );
+							}
+						}else{
+						
+							subs.requestAttention();
+						}
+					}else{
+						
+						subs.requestAttention();
+					}
+				}
+				
+				public void 
 				openRemotePairingWindow() 
 				{
 					UIFunctions uif = UIFunctionsManager.getUIFunctions();
@@ -159,7 +211,7 @@ public class InitialisationFunctions
 					org.gudy.azureus2.core3.download.DownloadManager		dm,
 					int														file_index )
 				{
-					return( PlayUtils.canPlayDS(dm, file_index) || PlayUtils.canStreamDS(dm, file_index));
+					return( PlayUtils.canPlayDS(dm, file_index,true) || PlayUtils.canStreamDS(dm, file_index,true));
 				}
 				
 				public void
@@ -182,11 +234,11 @@ public class InitialisationFunctions
 						Debug.out( "UIFunctions not available, can't open play/stream content" );
 						
 					}else{
-						if ( PlayUtils.canPlayDS(dm, file_index)){
+						if ( PlayUtils.canPlayDS(dm, file_index,true)){
 							
 							uif.playOrStreamDataSource( ds, DLReferals.DL_REFERAL_PLAYDM, false, true );
 							
-						}else if ( PlayUtils.canStreamDS(dm, file_index)){
+						}else if ( PlayUtils.canStreamDS(dm, file_index,true)){
 							
 							uif.playOrStreamDataSource( ds, DLReferals.DL_REFERAL_PLAYDM, true, false );
 						}
diff --git a/azureus3/src/com/aelitis/azureus/util/LocalResourceHTTPServer.java b/azureus3/src/com/aelitis/azureus/util/LocalResourceHTTPServer.java
index 05784fa..ba2b253 100644
--- a/azureus3/src/com/aelitis/azureus/util/LocalResourceHTTPServer.java
+++ b/azureus3/src/com/aelitis/azureus/util/LocalResourceHTTPServer.java
@@ -1,7 +1,7 @@
 /*
  * Created on 8 Aug 2006
  * Created by Paul Gardner
- * Copyright (C) 2006 Aelitis, All Rights Reserved.
+ * Copyright (C) Azureus Software, 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
@@ -14,9 +14,6 @@
  * 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.
  *
  */
 
diff --git a/azureus3/src/com/aelitis/azureus/util/NavigationHelper.java b/azureus3/src/com/aelitis/azureus/util/NavigationHelper.java
index 7caa1cd..d12bec1 100644
--- a/azureus3/src/com/aelitis/azureus/util/NavigationHelper.java
+++ b/azureus3/src/com/aelitis/azureus/util/NavigationHelper.java
@@ -1,254 +1,253 @@
-/*
- * Created on May 19, 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.util;
-
-import java.io.File;
-import java.util.*;
-
-import org.gudy.azureus2.core3.util.Debug;
-
-import com.aelitis.azureus.core.util.CopyOnWriteList;
-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;
-
-public class 
-NavigationHelper 
-{
-	public static final int COMMAND_SWITCH_TO_TAB	= 1;
-	public static final int COMMAND_CONDITION_CHECK	= 2;
-	
-		
-	private static CopyOnWriteList	listeners = new CopyOnWriteList();
-	private static List				command_queue;
-	
-	protected static void
-	initialise()
-	{
-		VuzeFileHandler.getSingleton().addProcessor(
-			new VuzeFileProcessor()
-			{
-				public void
-				process(
-					VuzeFile[]		files,
-					int				expected_types )
-				{
-					for (int i=0;i<files.length;i++){
-						
-						VuzeFile	vf = files[i];
-						
-						VuzeFileComponent[] comps = vf.getComponents();
-						
-						for (int j=0;j<comps.length;j++){
-							
-							VuzeFileComponent comp = comps[j];
-								
-							if ( 	comp.getType() == VuzeFileComponent.COMP_TYPE_V3_NAVIGATION ||
-									comp.getType() == VuzeFileComponent.COMP_TYPE_V3_CONDITION_CHECK ){
-
-								try{
-
-									List commands = (List)comp.getContent().get("commands");
-									
-									for ( int k=0;k<commands.size();k++){
-										
-										Map	command = (Map)commands.get(k);
-										
-										int	command_type = ((Long)command.get("type")).intValue();
-										
-										List	l_args = (List)command.get( "args" );
-										
-										String[]	args;
-										
-										if ( l_args == null ){
-											
-											args = new String[0];
-											
-										}else{
-										
-											args = new String[l_args.size()];
-											
-											for (int l=0;l<args.length;l++){
-												
-												args[l] = new String((byte[])l_args.get(l), "UTF-8" );
-											}
-										}
-										
-										addCommand( command_type, args );
-									}
-									
-									comp.setProcessed();
-							
-								}catch( Throwable e ){
-									
-									Debug.printStackTrace(e);
-								}
-							}
-						}
-					}
-				}
-			});
-	}
-	
-	protected static void
-	addCommand(
-		int			type,
-		String[]	args )
-	{
-			// guarantee delivery to at least one listener by queueing if none
-		
-		synchronized( listeners ){
-			
-			if ( listeners.size() == 0 ){
-			
-				if ( command_queue == null ){
-					
-					command_queue = new ArrayList();
-				}
-				
-				command_queue.add( new Object[]{ new Integer( type ), args });
-			}
-		}
-		
-			// possible duplicate delivery - assumed not a problem
-		
-		Iterator	it = listeners.iterator();
-		
-		while( it.hasNext()){
-							
-			navigationListener l = (navigationListener)it.next();
-			
-			try{
-				l.processCommand( type, args );
-				
-			}catch( Throwable e ){
-				
-				Debug.printStackTrace(e);
-			}
-		}
-	}
-	
-	public static void
-	addListener(
-		navigationListener		l )
-	{
-		List	queue;
-		
-		synchronized( listeners ){
-			
-			listeners.add( l );
-			
-			queue = command_queue;
-			
-			command_queue = null;
-		}
-		
-		if ( queue != null ){
-			
-			for (int i=0;i<queue.size();i++){
-				
-				Object[]	entry = (Object[])queue.get(i);
-				
-				int			type = ((Integer)entry[0]).intValue();
-				String[]	args = (String[])entry[1];
-				
-				try{
-					l.processCommand( type, args );
-					
-				}catch( Throwable e ){
-					
-					Debug.printStackTrace( e );	
-				}
-			}
-		}
-	}
-	
-	public interface
-	navigationListener
-	{
-		public void
-		processCommand(
-			int			type,
-			String[]	args );
-	}
-	
-	public static void
-	main(
-		String[]	args )
-	{
-		try{
-			VuzeFile vf = VuzeFileHandler.getSingleton().create();
-			
-			Map	content = new HashMap();
-			
-			List	commands = new ArrayList();
-			
-			content.put( "commands", commands );
-			
-				// home tab
-			
-			Map	command1 = new HashMap();
-			
-			commands.add( command1 );
-			
-			List	l_args1 = new ArrayList();
-			
-			//l_args1.add( SkinConstants.VIEWID_HOME_TAB  );
-			
-			command1.put( "type", new Long( COMMAND_SWITCH_TO_TAB ));
-			command1.put( "args", l_args1 );
-
-				// activity tab
-			
-			Map	command2 = new HashMap();
-			
-			commands.add( command2 );
-			
-			List	l_args2 = new ArrayList();
-			
-			//l_args2.add( SkinConstants.VIEWID_ACTIVITY_TAB );
-			
-			command2.put( "type", new Long( COMMAND_SWITCH_TO_TAB ));
-			command2.put( "args", l_args2 );
-			
-				// check plugin available
-			
-			Map	command3 = new HashMap();
-			
-			commands.add( command3 );
-			
-			List	l_args3 = new ArrayList();
-			
-			command3.put( "type", new Long( COMMAND_CONDITION_CHECK ));
-			command3.put( "args", l_args3 );
-			
-			vf.addComponent( VuzeFileComponent.COMP_TYPE_V3_NAVIGATION, content );
-			
-			vf.write( new File( "C:\\temp\\v3ui.vuze" ));
-			
-		}catch( Throwable e ){
-			
-			e.printStackTrace();
-		}
-	}
-}
+/*
+ * Created on May 19, 2008
+ * Created by Paul Gardner
+ * 
+ * Copyright (C) Azureus Software, 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.util;
+
+import java.io.File;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.Debug;
+
+import com.aelitis.azureus.core.util.CopyOnWriteList;
+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;
+
+public class 
+NavigationHelper 
+{
+	public static final int COMMAND_SWITCH_TO_TAB	= 1;
+	public static final int COMMAND_CONDITION_CHECK	= 2;
+	
+		
+	private static CopyOnWriteList	listeners = new CopyOnWriteList();
+	private static List				command_queue;
+	
+	protected static void
+	initialise()
+	{
+		VuzeFileHandler.getSingleton().addProcessor(
+			new VuzeFileProcessor()
+			{
+				public void
+				process(
+					VuzeFile[]		files,
+					int				expected_types )
+				{
+					for (int i=0;i<files.length;i++){
+						
+						VuzeFile	vf = files[i];
+						
+						VuzeFileComponent[] comps = vf.getComponents();
+						
+						for (int j=0;j<comps.length;j++){
+							
+							VuzeFileComponent comp = comps[j];
+								
+							if ( 	comp.getType() == VuzeFileComponent.COMP_TYPE_V3_NAVIGATION ||
+									comp.getType() == VuzeFileComponent.COMP_TYPE_V3_CONDITION_CHECK ){
+
+								try{
+
+									List commands = (List)comp.getContent().get("commands");
+									
+									for ( int k=0;k<commands.size();k++){
+										
+										Map	command = (Map)commands.get(k);
+										
+										int	command_type = ((Long)command.get("type")).intValue();
+										
+										List	l_args = (List)command.get( "args" );
+										
+										String[]	args;
+										
+										if ( l_args == null ){
+											
+											args = new String[0];
+											
+										}else{
+										
+											args = new String[l_args.size()];
+											
+											for (int l=0;l<args.length;l++){
+												
+												args[l] = new String((byte[])l_args.get(l), "UTF-8" );
+											}
+										}
+										
+										addCommand( command_type, args );
+									}
+									
+									comp.setProcessed();
+							
+								}catch( Throwable e ){
+									
+									Debug.printStackTrace(e);
+								}
+							}
+						}
+					}
+				}
+			});
+	}
+	
+	protected static void
+	addCommand(
+		int			type,
+		String[]	args )
+	{
+			// guarantee delivery to at least one listener by queueing if none
+		
+		synchronized( listeners ){
+			
+			if ( listeners.size() == 0 ){
+			
+				if ( command_queue == null ){
+					
+					command_queue = new ArrayList();
+				}
+				
+				command_queue.add( new Object[]{ new Integer( type ), args });
+			}
+		}
+		
+			// possible duplicate delivery - assumed not a problem
+		
+		Iterator	it = listeners.iterator();
+		
+		while( it.hasNext()){
+							
+			navigationListener l = (navigationListener)it.next();
+			
+			try{
+				l.processCommand( type, args );
+				
+			}catch( Throwable e ){
+				
+				Debug.printStackTrace(e);
+			}
+		}
+	}
+	
+	public static void
+	addListener(
+		navigationListener		l )
+	{
+		List	queue;
+		
+		synchronized( listeners ){
+			
+			listeners.add( l );
+			
+			queue = command_queue;
+			
+			command_queue = null;
+		}
+		
+		if ( queue != null ){
+			
+			for (int i=0;i<queue.size();i++){
+				
+				Object[]	entry = (Object[])queue.get(i);
+				
+				int			type = ((Integer)entry[0]).intValue();
+				String[]	args = (String[])entry[1];
+				
+				try{
+					l.processCommand( type, args );
+					
+				}catch( Throwable e ){
+					
+					Debug.printStackTrace( e );	
+				}
+			}
+		}
+	}
+	
+	public interface
+	navigationListener
+	{
+		public void
+		processCommand(
+			int			type,
+			String[]	args );
+	}
+	
+	public static void
+	main(
+		String[]	args )
+	{
+		try{
+			VuzeFile vf = VuzeFileHandler.getSingleton().create();
+			
+			Map	content = new HashMap();
+			
+			List	commands = new ArrayList();
+			
+			content.put( "commands", commands );
+			
+				// home tab
+			
+			Map	command1 = new HashMap();
+			
+			commands.add( command1 );
+			
+			List	l_args1 = new ArrayList();
+			
+			//l_args1.add( SkinConstants.VIEWID_HOME_TAB  );
+			
+			command1.put( "type", new Long( COMMAND_SWITCH_TO_TAB ));
+			command1.put( "args", l_args1 );
+
+				// activity tab
+			
+			Map	command2 = new HashMap();
+			
+			commands.add( command2 );
+			
+			List	l_args2 = new ArrayList();
+			
+			//l_args2.add( SkinConstants.VIEWID_ACTIVITY_TAB );
+			
+			command2.put( "type", new Long( COMMAND_SWITCH_TO_TAB ));
+			command2.put( "args", l_args2 );
+			
+				// check plugin available
+			
+			Map	command3 = new HashMap();
+			
+			commands.add( command3 );
+			
+			List	l_args3 = new ArrayList();
+			
+			command3.put( "type", new Long( COMMAND_CONDITION_CHECK ));
+			command3.put( "args", l_args3 );
+			
+			vf.addComponent( VuzeFileComponent.COMP_TYPE_V3_NAVIGATION, content );
+			
+			vf.write( new File( "C:\\temp\\v3ui.vuze" ));
+			
+		}catch( Throwable e ){
+			
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/azureus3/src/com/aelitis/azureus/util/PlayUtils.java b/azureus3/src/com/aelitis/azureus/util/PlayUtils.java
index 7b5641a..828043a 100644
--- a/azureus3/src/com/aelitis/azureus/util/PlayUtils.java
+++ b/azureus3/src/com/aelitis/azureus/util/PlayUtils.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jun 1, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -171,7 +173,23 @@ public class PlayUtils
 		return canUseEMP(torrent, file_index);
 	}
 
-	public static boolean canPlayDS(Object ds, int file_index ) {
+	
+	private static ThreadLocal<int[]>		tls_non_block_indicator	= 
+		new ThreadLocal<int[]>()
+		{
+			public int[]
+			initialValue()
+			{
+				return( new int[1] );
+			}
+		};
+			
+	public static boolean 
+	canPlayDS(
+		Object 		ds, 
+		int 		file_index,
+		boolean		block_for_accuracy ) 
+	{
 		
 		if ( !( Constants.isWindows || Constants.isOSX )){
 			
@@ -182,29 +200,43 @@ public class PlayUtils
 			return false;
 		}
 		
-		if (ds instanceof org.gudy.azureus2.core3.disk.DiskManagerFileInfo) {
-			org.gudy.azureus2.core3.disk.DiskManagerFileInfo fi = (org.gudy.azureus2.core3.disk.DiskManagerFileInfo) ds;
-			return canPlayDS(fi.getDownloadManager(), fi.getIndex());
-		}
+		try{
+			if ( !block_for_accuracy ){
+			
+				tls_non_block_indicator.get()[0]++;
+			}
+			
+			if (ds instanceof org.gudy.azureus2.core3.disk.DiskManagerFileInfo) {
+				org.gudy.azureus2.core3.disk.DiskManagerFileInfo fi = (org.gudy.azureus2.core3.disk.DiskManagerFileInfo) ds;
+				return canPlayDS(fi.getDownloadManager(), fi.getIndex(), block_for_accuracy);
+			}
 	
-		DownloadManager dm = DataSourceUtils.getDM(ds);
-		if (dm != null) {
-			return canPlay(dm, file_index);
-		}
-		TOTorrent torrent = DataSourceUtils.getTorrent(ds);
-		if (torrent != null) {
-			return canPlay(torrent, file_index);
-		}
-		if (ds instanceof VuzeActivitiesEntry) {
-			return ((VuzeActivitiesEntry) ds).isPlayable();
-		}
-		
-		if (ds instanceof SelectedContentV3) {
-			SelectedContentV3 sel = (SelectedContentV3) ds;
-			return sel.canPlay();
+			DownloadManager dm = DataSourceUtils.getDM(ds);
+			if (dm != null) {
+				return canPlay(dm, file_index);
+			}
+			TOTorrent torrent = DataSourceUtils.getTorrent(ds);
+			if (torrent != null) {
+				return canPlay(torrent, file_index);
+			}
+			if (ds instanceof VuzeActivitiesEntry) {
+				return ((VuzeActivitiesEntry) ds).isPlayable( block_for_accuracy );
+			}
+			
+			if (ds instanceof SelectedContentV3) {
+				SelectedContentV3 sel = (SelectedContentV3) ds;
+				return sel.canPlay();
+			}
+			
+			return false;
+			
+		}finally{
+			
+			if ( !block_for_accuracy ){
+			
+				tls_non_block_indicator.get()[0]--;
+			}
 		}
-		
-		return false;
 	}
 	
 		// stream stuff
@@ -264,8 +296,9 @@ public class PlayUtils
 		
 	public static boolean 
 	canStreamDS(
-		Object ds, 
-		int file_index ) 
+		Object 		ds, 
+		int 		file_index,
+		boolean		block_for_accuracy ) 
 	{
 		if ( !( Constants.isWindows || Constants.isOSX )){
 			
@@ -277,19 +310,33 @@ public class PlayUtils
 			return( false );
 		}
 
-		if (ds instanceof org.gudy.azureus2.core3.disk.DiskManagerFileInfo) {
-			org.gudy.azureus2.core3.disk.DiskManagerFileInfo fi = (org.gudy.azureus2.core3.disk.DiskManagerFileInfo) ds;
-			return canStreamDS(fi.getDownloadManager(), fi.getIndex());
-		}
+		try{
+			if ( !block_for_accuracy ){
+				
+				tls_non_block_indicator.get()[0]++;
+			}
+			
+			if (ds instanceof org.gudy.azureus2.core3.disk.DiskManagerFileInfo) {
+				org.gudy.azureus2.core3.disk.DiskManagerFileInfo fi = (org.gudy.azureus2.core3.disk.DiskManagerFileInfo) ds;
+				return canStreamDS(fi.getDownloadManager(), fi.getIndex(), block_for_accuracy );
+			}
 
-		DownloadManager dm = DataSourceUtils.getDM(ds);
+			DownloadManager dm = DataSourceUtils.getDM(ds);
+			
+			if ( dm != null ){
+				
+				return( canStream( dm, file_index ));
+			}
+			
+			return( false );
+			
+		}finally{
 		
-		if ( dm != null ){
+			if ( !block_for_accuracy ){
 			
-			return( canStream( dm, file_index ));
+				tls_non_block_indicator.get()[0]--;
+			}
 		}
-		
-		return( false );
 	}
 
 	/**
@@ -412,7 +459,18 @@ public class PlayUtils
 				}
 			}
 	
-			Object url = pi.getIPC().invoke("getContentURL", new Object[] { file });
+			boolean	use_peek = tls_non_block_indicator.get()[0] > 0;
+			
+			Object url;
+			
+			if ( use_peek && pi.getIPC().canInvoke( "peekContentURL", new Object[] { file })){
+				
+				url = pi.getIPC().invoke("peekContentURL", new Object[] { file });
+
+			}else{
+				
+				url = pi.getIPC().invoke("getContentURL", new Object[] { file });
+			}
 			
 			if (url instanceof String) {
 				return new URL( (String) url);
diff --git a/azureus3/src/com/aelitis/azureus/util/StringCompareUtils.java b/azureus3/src/com/aelitis/azureus/util/StringCompareUtils.java
index cf2dcb3..0e7f820 100644
--- a/azureus3/src/com/aelitis/azureus/util/StringCompareUtils.java
+++ b/azureus3/src/com/aelitis/azureus/util/StringCompareUtils.java
@@ -1,10 +1,12 @@
 /**
  * Created on Jun 1, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
diff --git a/azureus3/src/com/aelitis/azureus/util/UrlFilter.java b/azureus3/src/com/aelitis/azureus/util/UrlFilter.java
index ffd076b..dd5cd5b 100644
--- a/azureus3/src/com/aelitis/azureus/util/UrlFilter.java
+++ b/azureus3/src/com/aelitis/azureus/util/UrlFilter.java
@@ -1,10 +1,12 @@
 /**
  * Created on Dec 9, 2008
  *
- * Copyright 2008 Vuze, Inc.  All rights reserved.
+ * Copyright (C) Azureus Software, 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.
+ * 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
@@ -60,11 +62,13 @@ public class UrlFilter
 	}
 
 	public UrlFilter() {
-		listUrlWhitelist.add(DEFAULT_RPC_WHITELIST);
-		listUrlWhitelist.add("https?://[^/]*\\.vuze\\.com:?[0-9]*/.*");
+		addUrlWhitelist(DEFAULT_RPC_WHITELIST);
+		addUrlWhitelist("https?://([^.]+.?)?vuze.com:?[0-9]*/.*");
+		addUrlWhitelist("https?://192\\.168\\.0\\.*:?[0-9]*/.*");
+		addUrlWhitelist("https?://localhost:?[0-9]*/.*");
 		// for +1 button
-		listUrlWhitelist.add("https?://plusone\\.google\\.com/.*");
-		listUrlWhitelist.add("https?://clients[0-9]\\.google\\.com/.*");
+		addUrlWhitelist("https?://plusone\\.google\\.com/.*");
+		addUrlWhitelist("https?://clients[0-9]\\.google\\.com/.*");
 
 		ContentNetworkManager cmn = ContentNetworkManagerFactory.getSingleton();
 		ContentNetwork[] contentNetworks = cmn.getContentNetworks();
@@ -111,7 +115,12 @@ public class UrlFilter
 
 			if ( network.isServiceSupported( service )){
 	
-				addUrlWhitelist( network.getServiceURL( service ) + ".*" );
+				String serviceUrl = network.getServiceURL( service );
+				
+				if (!isWhitelisted(serviceUrl)) {
+				
+					addUrlWhitelist( serviceUrl + ".*" );
+				}
 			}
 		}
 	}
diff --git a/build.xml b/build.xml
index c01d1e4..7018f22 100644
--- a/build.xml
+++ b/build.xml
@@ -87,7 +87,7 @@ extract messagebundles
 		</copy>
 		
 		<!-- Compile source code -->
-		<javac encoding="8859_1" includeAntRuntime="no" debug="true" debuglevel="source,lines,vars" destdir="${build.dir}" source="1.5" target="1.5" fork="yes" memoryMaximumSize="256m" >
+		<javac encoding="8859_1" includeAntRuntime="no" debug="true" debuglevel="source,lines,vars" destdir="${build.dir}" source="1.5" target="1.5" fork="yes" memoryMaximumSize="1024m" >
 			<src path="${azureus2.dir}/src"/>
 			<src path="${azureus3.dir}/src"/>
 			<src path="${uis.dir}/src"/>
@@ -131,7 +131,7 @@ extract messagebundles
 	
 	<target name="docs" depends="init" description="Make javadocs" >
 		<!-- Make core javadoc -->
-		<javadoc destdir="${dist.dir}/${build.name}_javadoc" useexternalfile="yes" maxmemory="256m" Encoding="8859_1" >
+		<javadoc destdir="${dist.dir}/${build.name}_javadoc" useexternalfile="yes" maxmemory="1000m" Encoding="8859_1" Verbose="false" >
 			 <fileset dir="${azureus2.dir}/src" />
 			 <fileset dir="${azureus3.dir}/src" />
 			 <fileset dir="${uis.dir}/src" />
@@ -140,7 +140,7 @@ extract messagebundles
 		</javadoc>
 		
 		<!-- Make plugin api javadoc -->
-		<javadoc destdir="${dist.dir}/${build.name}_plugindoc" useexternalfile="yes" maxmemory="256m" Encoding="8859_1">
+		<javadoc destdir="${dist.dir}/${build.name}_plugindoc" useexternalfile="yes" maxmemory="1000m" Encoding="8859_1" Verbose="false" >
 			 <fileset dir="${azureus2.dir}/src" >
 			 	 <patternset refid="pluginapi.inc"/>
 			 </fileset>
@@ -155,7 +155,7 @@ extract messagebundles
 			<!-- Pickup subversion revision -->
 			<exec executable="sh" dir="." outputproperty="svn.revision.new" >
 				<arg value="-c" />
-				<arg value="svn info . | grep Revision | sed "s/Revision: //"" />
+				<arg value="svn info http://svn.vuze.com/public/client/trunk | grep Revision | sed "s/Revision: //"" />
 			</exec>		
 			<echo message="svn.revision.new=${svn.revision.new}" />			
 			
@@ -176,7 +176,7 @@ extract messagebundles
 			      	<arg value="-a" />
 			      	<arg value="-r" />
 			      	<arg value="${svn.revision}:${svn.revision.new}" />
-			      	<arg value="${basedir}" />
+			      	<arg value="http://svn.vuze.com/public/client/trunk" />
 			  </exec>
 			  <echo message="changelog.text = ${changelog.text}" />
 		     <echo file="${dist.dir}/${build.name}_changelog.txt" message="${changelog.text}" />
diff --git a/uis/src/org/gudy/azureus2/ui/console/ConsoleInput.java b/uis/src/org/gudy/azureus2/ui/console/ConsoleInput.java
index 8eea210..677d4b5 100644
--- a/uis/src/org/gudy/azureus2/ui/console/ConsoleInput.java
+++ b/uis/src/org/gudy/azureus2/ui/console/ConsoleInput.java
@@ -11,6 +11,7 @@
 
 package org.gudy.azureus2.ui.console;
 
+import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -18,6 +19,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
 import java.io.PrintStream;
 import java.io.Reader;
 import java.util.ArrayList;
@@ -63,7 +65,11 @@ import org.gudy.azureus2.update.CorePatchChecker;
 import org.gudy.azureus2.update.UpdaterUpdateChecker;
 
 import com.aelitis.azureus.core.AzureusCore;
+import com.aelitis.azureus.core.AzureusCoreComponent;
 import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter;
+import com.aelitis.azureus.core.subs.SubscriptionManagerFactory;
+import com.aelitis.azureus.ui.swt.Initializer;
+import com.aelitis.azureus.util.InitialisationFunctions;
 
 /**
  * @author Tobias Minich
@@ -72,7 +78,7 @@ public class ConsoleInput extends Thread {
 
 	private static final String ALIASES_CONFIG_FILE = "console.aliases.properties";
 	public final AzureusCore azureus_core;
-	public final PrintStream out;
+	public volatile PrintStream out;
 	public final List torrents = new ArrayList();
 	public File[] adds = null;
 	
@@ -176,11 +182,24 @@ public class ConsoleInput extends Thread {
 				azureus_core.addLifecycleListener(
 					new AzureusCoreLifecycleAdapter()
 					{
+						public void 
+						componentCreated(
+							AzureusCore 			core,
+							AzureusCoreComponent 	component )
+						{							
+							if ( component instanceof GlobalManager ){
+								
+								InitialisationFunctions.earlyInitialisation( core );
+							}
+						}
+						
 						public void
 						started(
 							AzureusCore		core )
 						{
 							registerUpdateChecker();
+												
+							InitialisationFunctions.lateInitialisation(core);
 						}
 					});
 			}
@@ -331,6 +350,13 @@ public class ConsoleInput extends Thread {
 		registerCommand(new Plugin());
 		registerCommand(new Pairing());
 		registerCommand(new Archive());
+		
+		try{
+			registerCommand(new Subscriptions());
+		}catch( Throwable e ){
+			
+		}
+		registerCommand(new Tags());
 
 	}
 
@@ -572,7 +598,7 @@ public class ConsoleInput extends Thread {
 	}
 
 	public void run() {
-		List comargs;
+		List<String> comargs;
 		running = true;
 		while (running) {
 			try {
@@ -584,6 +610,34 @@ public class ConsoleInput extends Thread {
 				break;
 			}
 			if (!comargs.isEmpty()) {
+				
+				int	argNum = comargs.size();
+				
+				File 	outputFile 			= null;
+				boolean outputFileAppend	= false;
+				
+				if ( argNum >= 3 ){
+					
+					String temp = comargs.get( argNum-2 );
+					
+					if ( temp.equals( ">" ) || temp.equals( ">>" )){
+						
+						File file = new File( comargs.get( argNum-1 ));
+						
+						if ( !file.getParentFile().canWrite()){
+							
+							out.println("> Invalid output file '" + file + "'" );
+							
+							continue;
+						}
+						
+						outputFile 			= file;
+						outputFileAppend	= temp.equals( ">>" );
+						
+						comargs = comargs.subList( 0, argNum-2 );
+					}
+				}
+				
 				String command = ((String) comargs.get(0)).toLowerCase();
 				if( ".".equals(command) )
 				{
@@ -599,7 +653,17 @@ public class ConsoleInput extends Thread {
 				oldcommand.addAll(comargs);
 				comargs.remove(0);
 				
+				PrintStream	 base_os 	= null;
+				
 				try {
+					if ( outputFile != null ){
+						
+						PrintStream temp = new PrintStream( new BufferedOutputStream( new FileOutputStream( outputFile, outputFileAppend ), 128 ));
+						
+						base_os = out;
+						out		= temp;
+					}
+					
 					if (!invokeCommand(command, comargs)) {
 						out.println("> Command '" + command + "' unknown (or . used without prior command)");
 					}
@@ -607,6 +671,23 @@ public class ConsoleInput extends Thread {
 				{
 					out.println("Exception occurred when executing command: '" + command + "'");
 					e.printStackTrace(out);
+				}finally{
+					
+					if ( base_os != null ){
+						
+						try{
+							PrintStream temp = out;
+							
+							out = base_os;
+							
+							temp.close();
+							
+						}catch( Throwable e ){
+							
+							out.println("Exception occurred when closing output file" );
+							e.printStackTrace(out);
+						}
+					}
 				}
 			}
 		}
diff --git a/uis/src/org/gudy/azureus2/ui/console/UI.java b/uis/src/org/gudy/azureus2/ui/console/UI.java
index 3f9febf..70b478f 100644
--- a/uis/src/org/gudy/azureus2/ui/console/UI.java
+++ b/uis/src/org/gudy/azureus2/ui/console/UI.java
@@ -14,6 +14,7 @@ package org.gudy.azureus2.ui.console;
 import java.io.File;
 import java.io.PrintStream;
 import java.net.URL;
+import java.util.Locale;
 
 import org.apache.log4j.Logger;
 import org.gudy.azureus2.core3.config.COConfigurationManager;
@@ -122,17 +123,32 @@ UI
   }
   
   public void openTorrent(String fileName) {
-  	if( console != null )
-  	{
+	String uc_filename = fileName.toUpperCase( Locale.US );
+	
+	boolean	is_remote = 
+			uc_filename.startsWith( "HTTP://" ) 
+			|| uc_filename.startsWith( "HTTPS://" )
+			|| uc_filename.startsWith( "MAGNET:" );
+	
+  	if ( console != null ){
+  		
 //  		System.out.println("NOT NULL CONSOLE. CAN PASS STRAIGHT TO IT!");
-  		console.downloadTorrent(fileName);
+  		
+  		if ( is_remote ){
+  			
+  			console.out.println( "Downloading torrent from url: " + fileName );
+  			
+  			console.downloadRemoteTorrent( fileName );
+  		}else{
+  		
+  			console.downloadTorrent(fileName);
+  		}
   		return;
-  	}
-  	else
-  	{
+  	}else{
 //  		System.out.println("NULL CONSOLE");
   	}
-    if( fileName.toUpperCase().startsWith( "HTTP://" ) || fileName.toUpperCase().startsWith( "HTTPS://" )) {
+  	
+    if( is_remote ) {
       if ( console != null ){
     	  console.out.println( "Downloading torrent from url: " + fileName );
       }
diff --git a/uis/src/org/gudy/azureus2/ui/console/commands/Hack.java b/uis/src/org/gudy/azureus2/ui/console/commands/Hack.java
index f123b8c..dab17ef 100644
--- a/uis/src/org/gudy/azureus2/ui/console/commands/Hack.java
+++ b/uis/src/org/gudy/azureus2/ui/console/commands/Hack.java
@@ -15,12 +15,20 @@ import java.net.URL;
 import java.util.Iterator;
 import java.util.List;
 
+import org.gudy.azureus2.core3.category.Category;
+import org.gudy.azureus2.core3.category.CategoryManager;
 import org.gudy.azureus2.core3.disk.DiskManager;
 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
+import org.gudy.azureus2.core3.util.Debug;
 import org.gudy.azureus2.ui.console.ConsoleInput;
 
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManager;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
+
 /**
  * @author Tobias Minich
  */
@@ -37,6 +45,9 @@ public class Hack extends TorrentCommand
 		subCommands.add(new HackDownloadSpeed());
 		subCommands.add(new HackUploadSpeed());
 		subCommands.add(new HackUploads());
+		subCommands.add(new HackCategory());
+		subCommands.add(new HackTag());
+		
 	}
 	
 	public String getCommandDescriptions()
@@ -370,4 +381,122 @@ public class Hack extends TorrentCommand
 			return "url\t\tu\tChange the full URL (Note: you have to include the '/announce' part).";
 		}
 	}	
+	
+	private static class HackCategory extends TorrentSubCommand
+	{
+		public HackCategory()
+		{
+			super("category", "cat");
+		}
+		
+		public String getCommandDescriptions() {
+			return "category [set <category_name>|clear]\t\tcat\tSet or clear the torrent's. Category will be created if necessary.";
+		}
+		
+		/**
+		 * locate the appropriate subcommand and execute it 
+		 */
+		public boolean performCommand(ConsoleInput ci, DownloadManager dm, List<String> args) 
+		{
+			if (args.size() < 1) {
+				ci.out.println("> Command 'hack': Not enough parameters for subcommand '" + getCommandName() + "'");
+				return false;
+			}
+			
+			String op = args.get(0);
+			
+			if ( op.equals( "set" )){
+				
+				if (args.size() < 2) {
+					ci.out.println("> Command 'hack': Not enough parameters for subcommand '" + getCommandName() + "'");
+					return false;
+				}
+				
+				String cat_name = args.get(1);
+				
+				Category cat = CategoryManager.getCategory( cat_name );
+				
+				if ( cat == null ){
+					
+					cat = CategoryManager.createCategory( cat_name );
+				}
+				
+				dm.getDownloadState().setCategory( cat );
+				
+			}else if ( op.equals( "clear" )){
+			
+				dm.getDownloadState().setCategory( null );
+			}
+			
+			return true;
+		}
+	}
+	
+	private static class HackTag extends TorrentSubCommand
+	{
+		public HackTag()
+		{
+			super("tag", "tag");
+		}
+		
+		public String getCommandDescriptions() {
+			return "tag [add|remove] <tag_name>\t\tAdd or remove a tag. Tag will be created if necessary.";
+		}
+		
+		/**
+		 * locate the appropriate subcommand and execute it 
+		 */
+		public boolean performCommand(ConsoleInput ci, DownloadManager dm, List<String> args) 
+		{
+			if (args.size() < 2) {
+				ci.out.println("> Command 'hack': Not enough parameters for subcommand '" + getCommandName() + "'");
+				return false;
+			}
+			
+			try{
+				String op = args.get(0);
+				String tag_name	= args.get(1);
+				
+				TagManager tm = TagManagerFactory.getTagManager();
+				
+				TagType tt = tm.getTagType( TagType.TT_DOWNLOAD_MANUAL );
+				
+				Tag tag = tt.getTag( tag_name, true );
+				
+				if ( op.equals( "add" )){
+					
+					if ( tag == null ){
+						
+						tag = tt.createTag( tag_name, true );
+						
+						ci.out.println( "Tag '" + tag_name + "' created" );
+					}
+					
+					tag.addTaggable( dm );
+					
+				}else if ( op.equals( "remove" )){
+					
+					if ( tag == null ){
+						
+						ci.out.println("Tag '" + tag_name + "' not found" );
+						
+					}else{
+						
+						tag.removeTaggable( dm );
+					}
+				}else{
+					
+					ci.out.println("> Command 'hack': Invalid parameters for '" + getCommandName() + "'");
+					return false;
+				}
+			}catch( Throwable e ){
+				
+				ci.out.println( "Command failed: " + Debug.getNestedExceptionMessage(e));
+				
+				return false;
+			}
+			
+			return true;
+		}
+	}
 }
diff --git a/uis/src/org/gudy/azureus2/ui/console/commands/IConsoleCommand.java b/uis/src/org/gudy/azureus2/ui/console/commands/IConsoleCommand.java
index 7c577f0..3661471 100644
--- a/uis/src/org/gudy/azureus2/ui/console/commands/IConsoleCommand.java
+++ b/uis/src/org/gudy/azureus2/ui/console/commands/IConsoleCommand.java
@@ -8,13 +8,19 @@
 package org.gudy.azureus2.ui.console.commands;
 
 import java.io.PrintStream;
+import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
+import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
+import org.gudy.azureus2.core3.util.DisplayFormatters;
 import org.gudy.azureus2.ui.console.ConsoleInput;
 
 /**
@@ -22,6 +28,17 @@ import org.gudy.azureus2.ui.console.ConsoleInput;
  * @author Tobias Minich
  */
 public abstract class IConsoleCommand {
+	protected static final class TorrentComparator implements Comparator<DownloadManager> {
+			public final int compare(DownloadManager aDL, DownloadManager bDL) {
+				boolean aIsComplete = aDL.getStats().getDownloadCompleted(false) == 1000;
+				boolean bIsComplete = bDL.getStats().getDownloadCompleted(false) == 1000;
+				if (aIsComplete && !bIsComplete)
+					return 1;
+				if (!aIsComplete && bIsComplete)
+					return -1;
+				return aDL.getPosition() - bDL.getPosition();
+			}
+		}
 	private String main_name;
 	private String short_name;
 	private HashSet commands;
@@ -58,13 +75,13 @@ public abstract class IConsoleCommand {
 	 * @param out
 	 * @param args
 	 */
-	public final void printHelp(PrintStream out, List args)
+	public final void printHelp(PrintStream out, List<String> args)
 	{
 		out.println(getCommandDescriptions());
 		printHelpExtra(out, args);
 	}
 	
-	public void printHelpExtra(PrintStream out, List args) {
+	public void printHelpExtra(PrintStream out, List<String> args) {
 		// Do nothing by default.
 	}
 	
@@ -102,4 +119,193 @@ public abstract class IConsoleCommand {
 	public final String getCommandName() {return this.main_name;}
 	public final String getShortCommandName() {return this.short_name;}
 
+	
+	/**
+	 * returns the summary details for the specified torrent. - we do this by obtaining
+	 * the summary format and then performing variable substitution 
+	 * NOTE: we currently reprocess
+	 * the summary format string each time however we could pre-parse this once.. its 
+	 * probably not that important though.
+	 * @return
+	 */
+	protected String getTorrentSummary(DownloadManager dm) {
+		StringBuffer tstate = new StringBuffer();
+		String summaryFormat = getDefaultSummaryFormat();
+		char lastch = '0';
+		char []summaryChars = summaryFormat.toCharArray();
+		for (int i = 0; i < summaryChars.length; i++) {
+			char ch = summaryChars[i];
+			if( ch == '%' && lastch != '\\' )
+			{
+				i++;
+				if( i >= summaryChars.length )
+					tstate.append('%');
+				else
+					tstate.append(expandVariable(summaryChars[i], dm));
+			}
+			else
+				tstate.append(ch);
+			
+			lastch = ch;			
+		}
+		return tstate.toString();
+	}
+
+	/**
+	 * expands the specified variable character into a string. <br>currently available
+	 * variables that can be expanded are:<br>
+	 * <hr>
+	 * %a for state<br>
+	 * %c percentage complete<br>
+	 * %t torrent details - error message if error, otherwise torrent name<br>
+	 * %z size<br>
+	 * %e ETA<br>
+	 * %r progress, if we have disabled some files<br>
+	 * %d download speed<br>
+	 * %u upload speed<br>
+	 * %D amount downloaded<br>
+	 * %U amount uploaded<br>
+	 * %v upload slots
+	 * %s connected seeds<br>
+	 * %p connected peers<br>
+	 * %S tracker seeds<br>
+	 * %P tracker peers<br>
+	 * @param variable variable character, eg: 'e' for ETA
+	 * @param dm download manager object
+	 * @return string expansion of the variable
+	 */
+	protected String expandVariable( char variable, DownloadManager dm )
+	{
+		switch( variable )
+		{
+			case 'a':
+				return getShortStateString(dm.getState());
+			case 'c':
+				DecimalFormat df = new DecimalFormat("000.0%");
+				return df.format(dm.getStats().getCompleted() / 1000.0);
+			case 't':
+				if (dm.getState() == DownloadManager.STATE_ERROR)
+					return dm.getErrorDetails();
+				else {
+					if (dm.getDisplayName() == null)
+						return "?";
+					else
+						return dm.getDisplayName();
+				}
+			case 'z':
+				return DisplayFormatters.formatByteCountToKiBEtc(dm.getSize());
+			case 'e':
+				return DisplayFormatters.formatETA(dm.getStats().getSmoothedETA());
+			case 'r':
+				long to = 0;
+				long tot = 0;
+				if (dm.getDiskManager() != null) {
+					DiskManagerFileInfo files[] = dm.getDiskManager().getFiles();
+					if (files != null) {
+						if (files.length>1) { 
+							int c=0;
+							for (int i = 0; i < files.length; i++) {
+								if (files[i] != null) {
+									if (!files[i].isSkipped()) {
+										c += 1;
+										tot += files[i].getLength();
+										to += files[i].getDownloaded();
+									}
+								}
+							}
+							if (c == files.length)
+								tot = 0;
+						}
+					}
+				}
+				DecimalFormat df1 = new DecimalFormat("000.0%");
+				if (tot > 0) {
+					return "      ("+df1.format(to * 1.0 / tot)+")";
+				} else
+					return "\t";
+			case 'd':
+				return DisplayFormatters.formatByteCountToKiBEtcPerSec(dm.getStats().getDataReceiveRate());
+			case 'u':
+				return DisplayFormatters.formatByteCountToKiBEtcPerSec(dm.getStats().getDataSendRate());
+			case 'D':
+				return DisplayFormatters.formatDownloaded(dm.getStats());
+			case 'U':
+				return DisplayFormatters.formatByteCountToKiBEtc(dm.getStats().getTotalDataBytesSent());
+			case 's':
+				return Integer.toString(dm.getNbSeeds());
+			case 'p':
+				return Integer.toString(dm.getNbPeers());	
+			case 'v':
+				return Integer.toString(dm.getMaxUploads());
+			case 'I':
+				int downloadSpeed = dm.getStats().getDownloadRateLimitBytesPerSecond();
+				if( downloadSpeed <= 0 )
+					return "";
+				return "(max " + DisplayFormatters.formatByteCountToKiBEtcPerSec(downloadSpeed) + ")";
+			case 'O':
+				int uploadSpeed = dm.getStats().getUploadRateLimitBytesPerSecond();
+				if( uploadSpeed <= 0 )
+					return "";
+				return "(max " + DisplayFormatters.formatByteCountToKiBEtcPerSec(uploadSpeed) + ")";
+				
+			case 'S':
+			case 'P':
+				TRTrackerScraperResponse hd = dm.getTrackerScrapeResponse();
+				if (hd == null || !hd.isValid())
+					return "?";
+				else
+				{
+					if( variable == 'S' )
+						return Integer.toString(hd.getSeeds());
+					else
+						return Integer.toString(hd.getPeers());
+				}
+			default: 
+				return "??" + variable + "??";
+		}
+	}
+	
+	/**
+	 * returns the format string (in printf style format) to use for displaying the torrent summary
+	 * @return
+	 */
+	protected String getDefaultSummaryFormat()
+	{
+		return "[%a] %c\t%t (%z) ETA: %e\r\n%r\tSpeed: %d%I / %u%O\tAmount: %D / %U\tConnections: %s(%S) / %p(%P)";
+	}
+	
+	/**
+	 * returns a string representation of the specified state number
+	 * suitable for inclusion in a torrent summary
+	 * @param dmstate
+	 * @return
+	 */
+	private static String getShortStateString(int dmstate) {
+		switch( dmstate )
+		{
+		case DownloadManager.STATE_INITIALIZING:
+			return("I");
+		case DownloadManager.STATE_ALLOCATING:
+			return("A");
+		case DownloadManager.STATE_CHECKING:
+			return("C");
+		case DownloadManager.STATE_DOWNLOADING:
+			return(">");
+		case DownloadManager.STATE_ERROR:
+			return("E");
+		case DownloadManager.STATE_SEEDING:
+			return("*");
+		case DownloadManager.STATE_STOPPED:
+			return("!");
+		case DownloadManager.STATE_WAITING:
+			return(".");
+		case DownloadManager.STATE_READY:
+			return(":");
+		case DownloadManager.STATE_QUEUED:
+			return("-");
+		default:
+			return("?");
+		}
+	}
+
 }
diff --git a/uis/src/org/gudy/azureus2/ui/console/commands/Show.java b/uis/src/org/gudy/azureus2/ui/console/commands/Show.java
index dc75e34..e98ff53 100644
--- a/uis/src/org/gudy/azureus2/ui/console/commands/Show.java
+++ b/uis/src/org/gudy/azureus2/ui/console/commands/Show.java
@@ -17,13 +17,13 @@ import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
 
+import org.gudy.azureus2.core3.category.Category;
 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
 import org.gudy.azureus2.core3.download.DownloadManager;
 import org.gudy.azureus2.core3.download.DownloadManagerStats;
@@ -52,6 +52,9 @@ import com.aelitis.azureus.core.dht.transport.*;
 import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
 import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker;
 import com.aelitis.azureus.core.stats.AzureusCoreStats;
+import com.aelitis.azureus.core.tag.Tag;
+import com.aelitis.azureus.core.tag.TagManagerFactory;
+import com.aelitis.azureus.core.tag.TagType;
 import com.aelitis.azureus.plugins.dht.DHTPlugin;
 
 /**
@@ -59,20 +62,6 @@ import com.aelitis.azureus.plugins.dht.DHTPlugin;
  */
 public class Show extends IConsoleCommand {
 	
-	private static final class TorrentComparator implements Comparator {
-		public final int compare(Object a, Object b) {
-			DownloadManager aDL = (DownloadManager) a;
-			DownloadManager bDL = (DownloadManager) b;
-			boolean aIsComplete = aDL.getStats().getDownloadCompleted(false) == 1000;
-			boolean bIsComplete = bDL.getStats().getDownloadCompleted(false) == 1000;
-			if (aIsComplete && !bIsComplete)
-				return 1;
-			if (!aIsComplete && bIsComplete)
-				return -1;
-			return aDL.getPosition() - bDL.getPosition();
-		}
-	}
-
 	public Show()
 	{
 		super("show", "sh");
@@ -248,7 +237,8 @@ public class Show extends IConsoleCommand {
 					shown_torrents.add( dm );
 
 					try {
-						ps = dm.getPeerManager().getStats();
+						PEPeerManager pm = dm.getPeerManager();
+						ps = pm==null?null:pm.getStats();
 					} catch (Exception e) {
 						ps = null;
 					}
@@ -370,193 +360,6 @@ public class Show extends IConsoleCommand {
 		} 
 	}
 
-	/**
-	 * returns the summary details for the specified torrent. - we do this by obtaining
-	 * the summary format and then performing variable substitution 
-	 * NOTE: we currently reprocess
-	 * the summary format string each time however we could pre-parse this once.. its 
-	 * probably not that important though.
-	 * @return
-	 */
-	protected String getTorrentSummary(DownloadManager dm) {
-		StringBuffer tstate = new StringBuffer();
-		String summaryFormat = getDefaultSummaryFormat();
-		char lastch = '0';
-		char []summaryChars = summaryFormat.toCharArray();
-		for (int i = 0; i < summaryChars.length; i++) {
-			char ch = summaryChars[i];
-			if( ch == '%' && lastch != '\\' )
-			{
-				i++;
-				if( i >= summaryChars.length )
-					tstate.append('%');
-				else
-					tstate.append(expandVariable(summaryChars[i], dm));
-			}
-			else
-				tstate.append(ch);
-			
-			lastch = ch;			
-		}
-		return tstate.toString();
-	}
-
-	/**
-	 * expands the specified variable character into a string. <br>currently available
-	 * variables that can be expanded are:<br>
-	 * <hr>
-	 * %a for state<br>
-	 * %c percentage complete<br>
-	 * %t torrent details - error message if error, otherwise torrent name<br>
-	 * %z size<br>
-	 * %e ETA<br>
-	 * %r progress, if we have disabled some files<br>
-	 * %d download speed<br>
-	 * %u upload speed<br>
-	 * %D amount downloaded<br>
-	 * %U amount uploaded<br>
-	 * %v upload slots
-	 * %s connected seeds<br>
-	 * %p connected peers<br>
-	 * %S tracker seeds<br>
-	 * %P tracker peers<br>
-	 * @param variable variable character, eg: 'e' for ETA
-	 * @param dm download manager object
-	 * @return string expansion of the variable
-	 */
-	protected String expandVariable( char variable, DownloadManager dm )
-	{
-		switch( variable )
-		{
-			case 'a':
-				return getShortStateString(dm.getState());
-			case 'c':
-				DecimalFormat df = new DecimalFormat("000.0%");
-				return df.format(dm.getStats().getCompleted() / 1000.0);
-			case 't':
-				if (dm.getState() == DownloadManager.STATE_ERROR)
-					return dm.getErrorDetails();
-				else {
-					if (dm.getDisplayName() == null)
-						return "?";
-					else
-						return dm.getDisplayName();
-				}
-			case 'z':
-				return DisplayFormatters.formatByteCountToKiBEtc(dm.getSize());
-			case 'e':
-				return DisplayFormatters.formatETA(dm.getStats().getSmoothedETA());
-			case 'r':
-				long to = 0;
-				long tot = 0;
-				if (dm.getDiskManager() != null) {
-					DiskManagerFileInfo files[] = dm.getDiskManager().getFiles();
-					if (files != null) {
-						if (files.length>1) { 
-							int c=0;
-							for (int i = 0; i < files.length; i++) {
-								if (files[i] != null) {
-									if (!files[i].isSkipped()) {
-										c += 1;
-										tot += files[i].getLength();
-										to += files[i].getDownloaded();
-									}
-								}
-							}
-							if (c == files.length)
-								tot = 0;
-						}
-					}
-				}
-				DecimalFormat df1 = new DecimalFormat("000.0%");
-				if (tot > 0) {
-					return "      ("+df1.format(to * 1.0 / tot)+")";
-				} else
-					return "\t";
-			case 'd':
-				return DisplayFormatters.formatByteCountToKiBEtcPerSec(dm.getStats().getDataReceiveRate());
-			case 'u':
-				return DisplayFormatters.formatByteCountToKiBEtcPerSec(dm.getStats().getDataSendRate());
-			case 'D':
-				return DisplayFormatters.formatDownloaded(dm.getStats());
-			case 'U':
-				return DisplayFormatters.formatByteCountToKiBEtc(dm.getStats().getTotalDataBytesSent());
-			case 's':
-				return Integer.toString(dm.getNbSeeds());
-			case 'p':
-				return Integer.toString(dm.getNbPeers());	
-			case 'v':
-				return Integer.toString(dm.getMaxUploads());
-			case 'I':
-				int downloadSpeed = dm.getStats().getDownloadRateLimitBytesPerSecond();
-				if( downloadSpeed <= 0 )
-					return "";
-				return "(max " + DisplayFormatters.formatByteCountToKiBEtcPerSec(downloadSpeed) + ")";
-			case 'O':
-				int uploadSpeed = dm.getStats().getUploadRateLimitBytesPerSecond();
-				if( uploadSpeed <= 0 )
-					return "";
-				return "(max " + DisplayFormatters.formatByteCountToKiBEtcPerSec(uploadSpeed) + ")";
-				
-			case 'S':
-			case 'P':
-				TRTrackerScraperResponse hd = dm.getTrackerScrapeResponse();
-				if (hd == null || !hd.isValid())
-					return "?";
-				else
-				{
-					if( variable == 'S' )
-						return Integer.toString(hd.getSeeds());
-					else
-						return Integer.toString(hd.getPeers());
-				}
-			default: 
-				return "??" + variable + "??";
-		}
-	}
-	
-	/**
-	 * returns the format string (in printf style format) to use for displaying the torrent summary
-	 * @return
-	 */
-	protected String getDefaultSummaryFormat()
-	{
-		return "[%a] %c\t%t (%z) ETA: %e\r\n%r\tSpeed: %d%I / %u%O\tAmount: %D / %U\tConnections: %s(%S) / %p(%P)";
-	}
-	
-	/**
-	 * returns a string representation of the specified state number
-	 * suitable for inclusion in a torrent summary
-	 * @param dmstate
-	 * @return
-	 */
-	private static String getShortStateString(int dmstate) {
-		switch( dmstate )
-		{
-		case DownloadManager.STATE_INITIALIZING:
-			return("I");
-		case DownloadManager.STATE_ALLOCATING:
-			return("A");
-		case DownloadManager.STATE_CHECKING:
-			return("C");
-		case DownloadManager.STATE_DOWNLOADING:
-			return(">");
-		case DownloadManager.STATE_ERROR:
-			return("E");
-		case DownloadManager.STATE_SEEDING:
-			return("*");
-		case DownloadManager.STATE_STOPPED:
-			return("!");
-		case DownloadManager.STATE_WAITING:
-			return(".");
-		case DownloadManager.STATE_READY:
-			return(":");
-		case DownloadManager.STATE_QUEUED:
-			return("-");
-		default:
-			return("?");
-		}
-	}
 
 	/**
 	 * prints out the full details of a particular torrent
@@ -587,6 +390,21 @@ public class Show extends IConsoleCommand {
 		out.println("Saving to: " + dm.getSaveLocation());
 		out.println("Created By: " + dm.getTorrentCreatedBy());
 		out.println("Comment: " + dm.getTorrentComment());
+		Category cat = dm.getDownloadState().getCategory();
+	    if (cat != null){
+			out.println("Category: " + cat.getName());
+	    }
+		List<Tag> tags = TagManagerFactory.getTagManager().getTagsForTaggable( TagType.TT_DOWNLOAD_MANUAL, dm );
+		String tags_str;
+		if ( tags.size() == 0 ){
+			tags_str = "None";
+		}else{
+			tags_str = "";
+			for ( Tag t: tags ){
+				tags_str += (tags_str.length()==0?"":",") + t.getTagName(true);
+			}
+		}
+		out.println("Tags: " + tags_str);
 		out.println("- Tracker Info -");
 		TRTrackerAnnouncer trackerclient = dm.getTrackerClient();
 		if (trackerclient != null) {
diff --git a/uis/src/org/gudy/azureus2/ui/console/commands/Subscriptions.java b/uis/src/org/gudy/azureus2/ui/console/commands/Subscriptions.java
new file mode 100644
index 0000000..ce001aa
--- /dev/null
+++ b/uis/src/org/gudy/azureus2/ui/console/commands/Subscriptions.java
@@ -0,0 +1,382 @@
+package org.gudy.azureus2.ui.console.commands;
+
+import java.io.PrintStream;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.core3.util.TimeFormatter;
+import org.gudy.azureus2.ui.console.ConsoleInput;
+
+import com.aelitis.azureus.core.subs.*;
+
+
+public class Subscriptions extends IConsoleCommand {
+
+	private Subscription[] 				current_subs;
+	private Subscription				current_sub;
+	private List<SubscriptionResult>	current_results;
+	
+	public Subscriptions()
+	{
+		super("subscriptions", "subs");
+	}
+	
+	public String getCommandDescriptions()
+	{
+		return("subscriptions\t\tsubs\tAccess to subscriptions.");
+	}
+	
+	public void printHelpExtra(PrintStream out, List args) {
+		out.println("> -----");
+		out.println("Subcommands:");
+		out.println("\tlist\t: List subscriptions");
+		out.println("\tcreate <name> <rss_url>\t: Create a new subscription");
+		out.println("\tselect <number>\t: Select subscription <number> for further operations");
+		out.println("The following commands operate on a selected subscription" );
+		out.println("\tupdate \t: Update the subscription" );
+		out.println("\tset_autodownload [yes|no] \t: Set the auto-download setting" );
+		out.println("\tset_updatemins <number>\t: Set the refresh frequency to <number> minutes" );
+		out.println("\tresults [all]\t: List the subscription results, unread only unless 'all' supplied" );
+		out.println("\tset_read [<number>|all]\t: Mark specified result, or all, as read" );
+		out.println("\tset_unread [<number>|all]\t: Mark specified result, or all, as un-read" );
+		out.println("\tdownload [<number>|all]\t: Download the specified result, or all" );
+		out.println("\tdelete\t: Delete the subscription" );
+		out.println("> -----");
+	}
+	
+	public void 
+	execute(
+		String commandName, ConsoleInput ci, List<String> args) {
+				
+		if( args.isEmpty()){
+			
+			printHelp(ci.out, args);
+			
+			return;
+		}
+					
+		String cmd = args.get(0);
+			
+		SubscriptionManager sub_man = SubscriptionManagerFactory.getSingleton();
+		
+		if ( cmd.equals( "list" )){
+			
+			ci.out.println("> -----");
+
+			current_subs = sub_man.getSubscriptions( true );
+			
+			int index = 1;
+			
+			for ( Subscription sub: current_subs ){
+				
+				SubscriptionHistory history = sub.getHistory();
+				
+				String index_str = "" + index++;
+				
+				while( index_str.length() < 3 ){
+					index_str += " ";
+				}
+				
+				String str = index_str + sub.getName() + ", unread=" + history.getNumUnread() + ", auto_download=" + (history.isAutoDownload()?"yes":"no");
+				
+				str += ", check_period=" + history.getCheckFrequencyMins() + " mins";
+				
+				long	last_check = history.getLastScanTime();
+				
+				str += ", last_check=" + (last_check<=0?"never":new SimpleDateFormat("yy/MM/dd HH:mm" ).format( last_check ));
+				
+				String last_error = history.getLastError();
+				
+				if ( last_error != null && last_error.length() > 0 ){
+					
+					str += ", last_error=" + last_error;
+				}
+				
+				ci.out.println( str );
+			}
+					
+			if ( current_subs.length==0 ){
+				
+				ci.out.println( "No Subscriptions" );
+			}
+		}else if ( cmd.equals( "create" )){
+	
+			if ( args.size() < 3 ){
+				
+				ci.out.println( "Usage: subs create <name> <rss_feed_url>" );
+				
+			}else{
+				
+				try{
+					sub_man.createRSS( args.get(1), new URL(args.get(2)), SubscriptionHistory.DEFAULT_CHECK_INTERVAL_MINS, new HashMap());
+					
+					ci.out.println( "Subscription created" );
+					
+				}catch( Throwable e ){
+					
+					ci.out.println( "Failed to create subscription: " + Debug.getNestedExceptionMessage( e ));
+				}
+			}
+			
+		}else if ( cmd.equals( "select" )){
+			
+			if ( args.size() < 2 ){
+				
+				ci.out.println( "Usage: subs select <number>" );
+				
+			}else{
+				
+				try{
+					int	index = Integer.parseInt( args.get(1));
+					
+					if ( current_subs == null ){
+						
+						throw( new Exception( "subscriptions must be listed prior to being selected" ));
+						
+					}else if ( current_subs.length == 0 ){
+						
+						throw( new Exception( "no subscriptions exist" ));
+						
+					}else if ( index < 0 || index > current_subs.length ){
+						
+						throw( new Exception( "subscription index '" + index + "' is out of range" ));
+
+					}else{
+						current_sub = current_subs[index-1];
+						
+						current_results = null;
+						
+						ci.out.println( "Selected subscription '" + current_sub.getName() + "'" );
+					}
+				}catch( Throwable e ){
+				
+					ci.out.println( "Failed to select subscription: " + Debug.getNestedExceptionMessage( e ));
+
+				}
+			}
+			
+		}else if ( 	cmd.equals( "update" ) || 
+					cmd.equals( "results" ) || 
+					cmd.equals( "set_autodownload" ) ||
+					cmd.equals( "set_updatemins" ) ||
+					cmd.equals( "set_read" ) || 
+					cmd.equals( "set_unread" )|| 
+					cmd.equals( "download" )|| 
+					cmd.equals( "delete" )){
+			
+			if ( current_sub == null ){
+				
+				ci.out.println( "No current subscription - select one!" );
+				
+			}else{
+						
+				if ( cmd.equals( "update" )){
+					
+					try{
+						sub_man.getScheduler().downloadAsync( current_sub, true );
+						
+						ci.out.println( "Subscription scheduled for update" );
+						
+					}catch( Throwable e ){
+						
+						ci.out.println( "Subscription update failed: " + Debug.getNestedExceptionMessage(e));
+					}
+					
+				}else if ( cmd.equals( "results" )){
+					
+					boolean do_all = args.size() > 1 && args.get(1).equals( "all" );
+						
+					int	index = 1;
+					
+					int	total_read		= 0;
+					int total_unread	= 0;
+					
+					current_results = new ArrayList<SubscriptionResult>();
+
+					SubscriptionResult[] results = current_sub.getHistory().getResults( false );
+
+					for ( SubscriptionResult result: results ){
+						
+						boolean is_read = result.getRead();
+						
+						if ( is_read ){
+							
+							total_read++;
+							
+						}else{
+							
+							total_unread++;
+						}
+						
+						if ( is_read && !do_all ){
+							
+							continue;
+						}
+							
+						current_results.add( result );
+						
+						Map map = result.toJSONMap();
+						
+						String index_str = "" + index++;
+						
+						while( index_str.length() < 3 ){
+							index_str += " ";
+						}
+						
+						String str = index_str + map.get("n") + ", size=" + map.get("l") + ", seeds=" + map.get("s") + ", peers=" + map.get("p");
+						
+						if ( do_all ){
+							
+							str += ", read=" + (is_read?"yes":"no" );
+						}
+						
+						ci.out.println( str );
+					}
+					
+					ci.out.println("> -----");
+					ci.out.println("Total read=" + total_read + ", unread=" + total_unread );
+				
+				}else if ( 	cmd.equals( "set_autodownload" )){
+					
+					if ( args.size() < 2 ){
+						
+						ci.out.println( "Usage: " + cmd + " [yes|no]" );
+						
+					}else if ( !current_sub.isAutoDownloadSupported()){
+						
+						ci.out.println( "Auto-download not supported for this subscription" );
+						
+					}else{
+						
+						String temp = args.get(1);
+						
+						if ( temp.equals( "yes" )){
+							
+							current_sub.getHistory().setAutoDownload( true );
+							
+						}else if ( temp.equals( "no" )){
+							
+							current_sub.getHistory().setAutoDownload( false );
+							
+						}else{
+							
+							ci.out.println( "Usage: " + cmd + " [yes|no]" );
+						}
+					}
+					
+				}else if ( 	cmd.equals( "set_updatemins" )){
+					
+					if ( args.size() < 2 ){
+						
+						ci.out.println( "Usage: " + cmd + " <minutes>" );
+					
+						
+					}else{
+						
+						try{
+							int	mins = Integer.parseInt( args.get(1));
+						
+							current_sub.getHistory().setCheckFrequencyMins( mins );
+							
+						}catch( Throwable e ){
+							
+							ci.out.println( "Usage: " + cmd + " <minutes>" );
+						}
+					}
+				}else if ( 	cmd.equals( "set_read" ) || 
+							cmd.equals( "set_unread" )|| 
+							cmd.equals( "download" )){
+					
+					if ( args.size() < 2 ){
+						
+						ci.out.println( "Usage: " + cmd + " <result_number>|all" );
+						
+					}else if ( current_results == null ){
+						
+						ci.out.println( "results must be listed before operating on them" );
+						
+					}else{
+						try{
+							String temp = args.get(1);
+							
+							int		do_index = -1;
+							
+							if ( !temp.equals( "all" )){
+							
+								do_index = Integer.parseInt( temp );
+								
+								if ( do_index < 1 || do_index > current_results.size()){
+									
+									throw( new Exception( "Invalid result index" ));
+								}
+							}
+							
+							
+							List<SubscriptionResult> to_do = new ArrayList<SubscriptionResult>();
+							
+							if ( do_index == -1 ){
+								
+								to_do.addAll( current_results );
+								
+							}else{
+								
+								to_do.add( current_results.get( do_index-1 ));
+							}
+							
+							for ( SubscriptionResult result: to_do ){
+								
+								if ( cmd.equals( "set_read" )){
+									
+									result.setRead( true );
+									
+								}else if ( cmd.equals( "set_unread" )){
+									
+									result.setRead( false );
+									
+								}else if ( cmd.equals( "download" )){
+									
+									String download_link = result.getDownloadLink();
+									
+									try{
+										URL url = new URL( result.getDownloadLink());
+									
+										ci.downloadRemoteTorrent( url.toExternalForm());
+										
+										ci.out.println( "Queueing '" + download_link + "' for download" );
+										
+										result.setRead( true );
+										
+									}catch( Throwable e ){
+										
+										ci.out.println( "Failed to add download from URL '" + download_link + "': " + Debug.getNestedExceptionMessage(e));
+									}
+								}
+								
+							}
+						}catch( Throwable e ){
+							
+							ci.out.println( "Operation failed: " + Debug.getNestedExceptionMessage( e ));
+
+						}
+					}
+					
+				}else if ( cmd.equals( "delete" )){
+										
+					ci.out.println( "Subscription '" + current_sub.getName() + "' deleted" );
+					
+					current_sub.remove();
+
+					current_sub		= null;
+					current_results	= null;
+				}
+			}
+		}else{
+			
+			ci.out.println( "Unsupported sub-command: " + cmd );
+		}
+		
+		ci.out.println("> -----");
+	}
+}
diff --git a/uis/src/org/gudy/azureus2/ui/console/commands/Tags.java b/uis/src/org/gudy/azureus2/ui/console/commands/Tags.java
new file mode 100644
index 0000000..9565a6d
--- /dev/null
+++ b/uis/src/org/gudy/azureus2/ui/console/commands/Tags.java
@@ -0,0 +1,210 @@
+package org.gudy.azureus2.ui.console.commands;
+
+import java.io.PrintStream;
+import java.util.*;
+
+import org.gudy.azureus2.core3.download.DownloadManager;
+import org.gudy.azureus2.core3.util.Debug;
+import org.gudy.azureus2.ui.console.ConsoleInput;
+
+import com.aelitis.azureus.core.tag.*;
+
+
+public class Tags extends IConsoleCommand {
+
+	private List<Tag> 				current_tags;
+	private Tag						current_tag;
+	
+	public Tags()
+	{
+		super("tag", "tag");
+	}
+	
+	public String getCommandDescriptions()
+	{
+		return("tags\t\tAccess to tags.");
+	}
+	
+	public void printHelpExtra(PrintStream out, List<String> args) {
+		out.println("> -----");
+		out.println("Subcommands:");
+		out.println("\tlist\t: List tags");
+		out.println("\tcreate <name>\t: Create a new tag");
+		out.println("\tselect <number>\t: Select tag <number> for further operations");
+		out.println("The following commands operate on a selected tag" );
+		out.println("\ttorrents\t: List the tag's torrents" );
+		out.println("\tshow\t: Show tag properties" );
+		out.println("\tset_rssenable [yes|no]\t: Enable/disable RSS feed generation for the tag" );
+		out.println("\tdelete\t: Delete the tag" );
+		
+		out.println("> -----");
+	}
+	
+	public void 
+	execute(
+		String commandName, ConsoleInput ci, List<String> args) {
+				
+		if( args.isEmpty()){
+			
+			printHelp(ci.out, args);
+			
+			return;
+		}
+					
+		String cmd = args.get(0);
+			
+		TagManager tm = TagManagerFactory.getTagManager();
+		
+		TagType tt = tm.getTagType( TagType.TT_DOWNLOAD_MANUAL );
+		
+		if ( cmd.equals( "list" )){
+			
+			ci.out.println("> -----");
+			
+			current_tags = tt.getTags();
+			
+			int index = 1;
+			
+			for ( Tag tag: current_tags ){
+								
+				String index_str = "" + index++;
+				
+				while( index_str.length() < 3 ){
+					index_str += " ";
+				}
+				
+				String str = index_str + tag.getTagName( true ) + ", downloads=" + tag.getTaggedCount();
+				
+				ci.out.println( str );
+			}
+					
+			if ( current_tags.size()==0 ){
+				
+				ci.out.println( "No Tags" );
+			}
+		}else if ( cmd.equals( "create" )){
+			
+			if ( args.size() < 2 ){
+				
+				ci.out.println( "Usage: tag create <name>" );
+				
+			}else{
+				
+				String tag_name = args.get(1);
+				
+				if ( tt.getTag(tag_name, true) != null ){
+					
+					ci.out.println( "Tag already exists" );
+					
+				}else{
+					try{
+						tt.createTag( tag_name, true );
+						
+						ci.out.println( "Tag created" );
+						
+					}catch( Throwable e ){
+						
+						ci.out.println( "Failed to create tag: " + Debug.getNestedExceptionMessage( e ));
+					}
+				}
+			}
+		}else if ( cmd.equals( "select" )){
+			
+			if ( args.size() < 2 ){
+				
+				ci.out.println( "Usage: tag select <number>" );
+				
+			}else{
+				
+				try{
+					int	index = Integer.parseInt( args.get(1));
+					
+					if ( current_tags == null ){
+						
+						throw( new Exception( "tags must be listed prior to being selected" ));
+						
+					}else if ( current_tags.size() == 0 ){
+						
+						throw( new Exception( "no tags exist" ));
+						
+					}else if ( index < 0 || index > current_tags.size()){
+						
+						throw( new Exception( "tag index '" + index + "' is out of range" ));
+
+					}else{
+						current_tag = current_tags.get( index-1 );
+												
+						ci.out.println( "Selected tag '" + current_tag.getTagName( true ) + "'" );
+					}
+				}catch( Throwable e ){
+				
+					ci.out.println( "Failed to select tag: " + Debug.getNestedExceptionMessage( e ));
+
+				}
+			}
+			
+		}else if ( 	cmd.equals( "torrents" ) || 
+					cmd.equals( "show" ) ||
+					cmd.equals( "delete" ) ||
+					cmd.equals( "set_rssenable" )){
+			
+			if ( current_tag == null ){
+				
+				ci.out.println( "No current tag - select one!" );
+				
+			}else{
+						
+				if ( cmd.equals( "torrents" )){
+					
+					ci.out.println( "Torrents for tag '" + current_tag.getTagName( true ) + "'" );
+					
+					List<DownloadManager> downloads = new ArrayList<DownloadManager>((java.util.Set<DownloadManager>)(Object)current_tag.getTagged());
+					
+					Collections.sort( downloads, new TorrentComparator());
+					
+					for ( DownloadManager dm: downloads ){
+						
+						ci.out.println(getTorrentSummary(dm));
+					}
+			
+				}else if ( 	cmd.equals( "show" )){
+
+					ci.out.println( "Details for tag '" + current_tag.getTagName( true ) + "'" );
+					
+					ci.out.println( "\tRSS Enable: " + ((TagFeatureRSSFeed)current_tag).isTagRSSFeedEnabled());
+					
+				}else if ( 	cmd.equals( "set_rssenable" )){
+					
+					if ( args.size() < 2 ){
+						
+						ci.out.println( "Usage: " + cmd + " [yes|no]" );
+												
+					}else{
+						
+						String temp = args.get(1);
+						
+						if ( temp.equals( "yes" ) || temp.equals( "no" )){
+							
+							((TagFeatureRSSFeed)current_tag).setTagRSSFeedEnabled( temp.equals( "yes" ) );
+							
+						}else{
+							
+							ci.out.println( "Usage: " + cmd + " [yes|no]" );
+						}
+					}						
+				}else if ( cmd.equals( "delete" )){
+					
+					current_tag.removeTag();
+					
+					current_tag	 	= null;
+					current_tags	= null;
+				}
+			}
+		}else{
+			
+			ci.out.println( "Unsupported sub-command: " + cmd );
+		}
+		
+		ci.out.println("> -----");
+	}
+}
diff --git a/uis/src/org/gudy/azureus2/ui/console/commands/TorrentCommand.java b/uis/src/org/gudy/azureus2/ui/console/commands/TorrentCommand.java
index aabdaf2..f99c39e 100644
--- a/uis/src/org/gudy/azureus2/ui/console/commands/TorrentCommand.java
+++ b/uis/src/org/gudy/azureus2/ui/console/commands/TorrentCommand.java
@@ -47,7 +47,7 @@ public abstract class TorrentCommand extends IConsoleCommand {
 	{
 		return action;
 	}
-	protected abstract boolean performCommand(ConsoleInput ci, DownloadManager dm, List args);
+	protected abstract boolean performCommand(ConsoleInput ci, DownloadManager dm, List<String> args);
 	
 	/**
 	 * Stub for commands that operate on a hosted torrent rather than downloadmanager
@@ -55,7 +55,7 @@ public abstract class TorrentCommand extends IConsoleCommand {
 	 * @param args
 	 * @return
 	 */
-	protected boolean performCommand(ConsoleInput ci, TRHostTorrent torrent, List args)
+	protected boolean performCommand(ConsoleInput ci, TRHostTorrent torrent, List<String> args)
 	{
 		return( false );
 	}
diff --git a/uis/src/org/gudy/azureus2/ui/console/commands/TorrentSubCommand.java b/uis/src/org/gudy/azureus2/ui/console/commands/TorrentSubCommand.java
index 9bf032d..0e2f438 100644
--- a/uis/src/org/gudy/azureus2/ui/console/commands/TorrentSubCommand.java
+++ b/uis/src/org/gudy/azureus2/ui/console/commands/TorrentSubCommand.java
@@ -42,5 +42,5 @@ public abstract class TorrentSubCommand extends TorrentCommand
 		super(command_name, short_name, null);
 	}
 
-	public abstract boolean performCommand(ConsoleInput ci, DownloadManager dm, List args);
+	public abstract boolean performCommand(ConsoleInput ci, DownloadManager dm, List<String> args);
 }
diff --git a/uis/src/org/gudy/azureus2/ui/console/multiuser/UserManagerPersister.java b/uis/src/org/gudy/azureus2/ui/console/multiuser/UserManagerPersister.java
index 96722ad..517c2ee 100644
--- a/uis/src/org/gudy/azureus2/ui/console/multiuser/UserManagerPersister.java
+++ b/uis/src/org/gudy/azureus2/ui/console/multiuser/UserManagerPersister.java
@@ -6,16 +6,17 @@
  * 
  * 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.
- * 
+ * 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.
- * 
+ * 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.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 
diff --git a/uis/src/org/gudy/azureus2/ui/console/multiuser/persist/UserManagerXMLPersist.java b/uis/src/org/gudy/azureus2/ui/console/multiuser/persist/UserManagerXMLPersist.java
index 4b2e9e4..64acc50 100644
--- a/uis/src/org/gudy/azureus2/ui/console/multiuser/persist/UserManagerXMLPersist.java
+++ b/uis/src/org/gudy/azureus2/ui/console/multiuser/persist/UserManagerXMLPersist.java
@@ -6,16 +6,17 @@
  * 
  * 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.
- * 
+ * 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.
- * 
+ * 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.
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 
diff --git a/uis/src/org/pf/readme.txt b/uis/src/org/pf/readme.txt
index 375aa6e..3b54676 100644
--- a/uis/src/org/pf/readme.txt
+++ b/uis/src/org/pf/readme.txt
@@ -1,4 +1,33 @@
 This is a stripped down version of Manfred Duchrows Programmer's Freind class
 library. No code was changed, only classes irrelevant for Azureus were left out.
 The complete library can be found on its homepage:
-http://www.programmers-friend.org
\ No newline at end of file
+http://www.programmers-friend.org
+
+----------------------------------------------
+
+Update by PARG, 2014/07/07 after forum post:
+
+http://forum.vuze.com/thread.jspa?threadID=122409
+
+Hello!
+
+It's been brought to my attention that some libraries bundled with Vuze has an incompatible license. Starting out easy, the attached patch is my attempt (please bear with me, I'm no programmer) to re-implement the functionality of the ProgrammersFriend classes which are used in Vuze. 
+Comments and suggestions are very welcome (-:
+
+/David
+
+
+
+These classes were added in 2004 or earlier and around that time were actually LGPL:
+
+http://web.archive.org/web/20040331162102/http://www.programmers-friend.org/
+
+and the license was changed somewhere between
+
+http://web.archive.org/web/20050324020645/http://programmers-friend.org/
+
+and
+
+http://web.archive.org/web/20050829235527/http://programmers-friend.org/
+
+to be CPL.
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/azureus.git



More information about the pkg-java-commits mailing list